aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/crypto/tls
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-05-20 00:18:15 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-05-20 00:18:15 +0000
commit9ff56c9570642711d5b7ab29920ecf5dbff14a27 (patch)
treec891bdec1e6f073f73fedeef23718bc3ac30d499 /libgo/go/crypto/tls
parent37cb25ed7acdb844b218231130e54b8b7a0ff6e6 (diff)
downloadgcc-9ff56c9570642711d5b7ab29920ecf5dbff14a27.zip
gcc-9ff56c9570642711d5b7ab29920ecf5dbff14a27.tar.gz
gcc-9ff56c9570642711d5b7ab29920ecf5dbff14a27.tar.bz2
Update to current version of Go library.
From-SVN: r173931
Diffstat (limited to 'libgo/go/crypto/tls')
-rw-r--r--libgo/go/crypto/tls/ca_set.go89
-rw-r--r--libgo/go/crypto/tls/common.go19
-rw-r--r--libgo/go/crypto/tls/conn.go4
-rw-r--r--libgo/go/crypto/tls/handshake_client.go49
-rw-r--r--libgo/go/crypto/tls/handshake_messages.go10
-rw-r--r--libgo/go/crypto/tls/handshake_messages_test.go22
-rw-r--r--libgo/go/crypto/tls/handshake_server.go11
-rw-r--r--libgo/go/crypto/tls/handshake_server_test.go6
-rw-r--r--libgo/go/crypto/tls/tls.go3
9 files changed, 64 insertions, 149 deletions
diff --git a/libgo/go/crypto/tls/ca_set.go b/libgo/go/crypto/tls/ca_set.go
deleted file mode 100644
index ae00ac5..0000000
--- a/libgo/go/crypto/tls/ca_set.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package tls
-
-import (
- "crypto/x509"
- "encoding/pem"
- "strings"
-)
-
-// A CASet is a set of certificates.
-type CASet struct {
- bySubjectKeyId map[string][]*x509.Certificate
- byName map[string][]*x509.Certificate
-}
-
-// NewCASet returns a new, empty CASet.
-func NewCASet() *CASet {
- return &CASet{
- make(map[string][]*x509.Certificate),
- make(map[string][]*x509.Certificate),
- }
-}
-
-func nameToKey(name *x509.Name) string {
- return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
-}
-
-// FindVerifiedParent attempts to find the certificate in s which has signed
-// the given certificate. If no such certificate can be found or the signature
-// doesn't match, it returns nil.
-func (s *CASet) FindVerifiedParent(cert *x509.Certificate) (parent *x509.Certificate) {
- var candidates []*x509.Certificate
-
- if len(cert.AuthorityKeyId) > 0 {
- candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
- }
- if len(candidates) == 0 {
- candidates = s.byName[nameToKey(&cert.Issuer)]
- }
-
- for _, c := range candidates {
- if cert.CheckSignatureFrom(c) == nil {
- return c
- }
- }
-
- return nil
-}
-
-// AddCert adds a certificate to the set
-func (s *CASet) AddCert(cert *x509.Certificate) {
- if len(cert.SubjectKeyId) > 0 {
- keyId := string(cert.SubjectKeyId)
- s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], cert)
- }
- name := nameToKey(&cert.Subject)
- s.byName[name] = append(s.byName[name], cert)
-}
-
-// SetFromPEM attempts to parse a series of PEM encoded root certificates. It
-// appends any certificates found to s and returns true if any certificates
-// were successfully parsed. On many Linux systems, /etc/ssl/cert.pem will
-// contains the system wide set of root CAs in a format suitable for this
-// function.
-func (s *CASet) SetFromPEM(pemCerts []byte) (ok bool) {
- for len(pemCerts) > 0 {
- var block *pem.Block
- block, pemCerts = pem.Decode(pemCerts)
- if block == nil {
- break
- }
- if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
- continue
- }
-
- cert, err := x509.ParseCertificate(block.Bytes)
- if err != nil {
- continue
- }
-
- s.AddCert(cert)
- ok = true
- }
-
- return
-}
diff --git a/libgo/go/crypto/tls/common.go b/libgo/go/crypto/tls/common.go
index c779234..0b26aae 100644
--- a/libgo/go/crypto/tls/common.go
+++ b/libgo/go/crypto/tls/common.go
@@ -100,6 +100,8 @@ type ConnectionState struct {
// the certificate chain that was presented by the other side
PeerCertificates []*x509.Certificate
+ // the verified certificate chains built from PeerCertificates.
+ VerifiedChains [][]*x509.Certificate
}
// A Config structure is used to configure a TLS client or server. After one
@@ -122,7 +124,7 @@ type Config struct {
// RootCAs defines the set of root certificate authorities
// that clients use when verifying server certificates.
// If RootCAs is nil, TLS uses the host's root CA set.
- RootCAs *CASet
+ RootCAs *x509.CertPool
// NextProtos is a list of supported, application level protocols.
NextProtos []string
@@ -158,7 +160,7 @@ func (c *Config) time() int64 {
return t()
}
-func (c *Config) rootCAs() *CASet {
+func (c *Config) rootCAs() *x509.CertPool {
s := c.RootCAs
if s == nil {
s = defaultRoots()
@@ -178,6 +180,9 @@ func (c *Config) cipherSuites() []uint16 {
type Certificate struct {
Certificate [][]byte
PrivateKey *rsa.PrivateKey
+ // OCSPStaple contains an optional OCSP response which will be served
+ // to clients that request it.
+ OCSPStaple []byte
}
// A TLS record.
@@ -221,7 +226,7 @@ var certFiles = []string{
var once sync.Once
-func defaultRoots() *CASet {
+func defaultRoots() *x509.CertPool {
once.Do(initDefaults)
return varDefaultRoots
}
@@ -236,14 +241,14 @@ func initDefaults() {
initDefaultCipherSuites()
}
-var varDefaultRoots *CASet
+var varDefaultRoots *x509.CertPool
func initDefaultRoots() {
- roots := NewCASet()
+ roots := x509.NewCertPool()
for _, file := range certFiles {
data, err := ioutil.ReadFile(file)
if err == nil {
- roots.SetFromPEM(data)
+ roots.AppendCertsFromPEM(data)
break
}
}
@@ -255,7 +260,7 @@ var varDefaultCipherSuites []uint16
func initDefaultCipherSuites() {
varDefaultCipherSuites = make([]uint16, len(cipherSuites))
i := 0
- for id, _ := range cipherSuites {
+ for id := range cipherSuites {
varDefaultCipherSuites[i] = id
i++
}
diff --git a/libgo/go/crypto/tls/conn.go b/libgo/go/crypto/tls/conn.go
index b94e235..48d3f72 100644
--- a/libgo/go/crypto/tls/conn.go
+++ b/libgo/go/crypto/tls/conn.go
@@ -34,6 +34,9 @@ type Conn struct {
cipherSuite uint16
ocspResponse []byte // stapled OCSP response
peerCertificates []*x509.Certificate
+ // verifedChains contains the certificate chains that we built, as
+ // opposed to the ones presented by the server.
+ verifiedChains [][]*x509.Certificate
clientProtocol string
clientProtocolFallback bool
@@ -765,6 +768,7 @@ func (c *Conn) ConnectionState() ConnectionState {
state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback
state.CipherSuite = c.cipherSuite
state.PeerCertificates = c.peerCertificates
+ state.VerifiedChains = c.verifiedChains
}
return state
diff --git a/libgo/go/crypto/tls/handshake_client.go b/libgo/go/crypto/tls/handshake_client.go
index 540b25c..c758c96 100644
--- a/libgo/go/crypto/tls/handshake_client.go
+++ b/libgo/go/crypto/tls/handshake_client.go
@@ -88,7 +88,6 @@ func (c *Conn) clientHandshake() os.Error {
finishedHash.Write(certMsg.marshal())
certs := make([]*x509.Certificate, len(certMsg.certificates))
- chain := NewCASet()
for i, asn1Data := range certMsg.certificates {
cert, err := x509.ParseCertificate(asn1Data)
if err != nil {
@@ -96,47 +95,29 @@ func (c *Conn) clientHandshake() os.Error {
return os.ErrorString("failed to parse certificate from server: " + err.String())
}
certs[i] = cert
- chain.AddCert(cert)
}
// If we don't have a root CA set configured then anything is accepted.
// TODO(rsc): Find certificates for OS X 10.6.
- for cur := certs[0]; c.config.RootCAs != nil; {
- parent := c.config.RootCAs.FindVerifiedParent(cur)
- if parent != nil {
- break
+ if c.config.RootCAs != nil {
+ opts := x509.VerifyOptions{
+ Roots: c.config.RootCAs,
+ CurrentTime: c.config.time(),
+ DNSName: c.config.ServerName,
+ Intermediates: x509.NewCertPool(),
}
- parent = chain.FindVerifiedParent(cur)
- if parent == nil {
- c.sendAlert(alertBadCertificate)
- return os.ErrorString("could not find root certificate for chain")
+ for i, cert := range certs {
+ if i == 0 {
+ continue
+ }
+ opts.Intermediates.AddCert(cert)
}
-
- if !parent.BasicConstraintsValid || !parent.IsCA {
+ c.verifiedChains, err = certs[0].Verify(opts)
+ if err != nil {
c.sendAlert(alertBadCertificate)
- return os.ErrorString("intermediate certificate does not have CA bit set")
+ return err
}
- // KeyUsage status flags are ignored. From Engineering
- // Security, Peter Gutmann: A European government CA marked its
- // signing certificates as being valid for encryption only, but
- // no-one noticed. Another European CA marked its signature
- // keys as not being valid for signatures. A different CA
- // marked its own trusted root certificate as being invalid for
- // certificate signing. Another national CA distributed a
- // certificate to be used to encrypt data for the country’s tax
- // authority that was marked as only being usable for digital
- // signatures but not for encryption. Yet another CA reversed
- // the order of the bit flags in the keyUsage due to confusion
- // over encoding endianness, essentially setting a random
- // keyUsage in certificates that it issued. Another CA created
- // a self-invalidating certificate by adding a certificate
- // policy statement stipulating that the certificate had to be
- // used strictly as specified in the keyUsage, and a keyUsage
- // containing a flag indicating that the RSA encryption key
- // could only be used for Diffie-Hellman key agreement.
-
- cur = parent
}
if _, ok := certs[0].PublicKey.(*rsa.PublicKey); !ok {
@@ -145,7 +126,7 @@ func (c *Conn) clientHandshake() os.Error {
c.peerCertificates = certs
- if serverHello.certStatus {
+ if serverHello.ocspStapling {
msg, err = c.readHandshake()
if err != nil {
return err
diff --git a/libgo/go/crypto/tls/handshake_messages.go b/libgo/go/crypto/tls/handshake_messages.go
index e5e8562..6645adc 100644
--- a/libgo/go/crypto/tls/handshake_messages.go
+++ b/libgo/go/crypto/tls/handshake_messages.go
@@ -306,7 +306,7 @@ type serverHelloMsg struct {
compressionMethod uint8
nextProtoNeg bool
nextProtos []string
- certStatus bool
+ ocspStapling bool
}
func (m *serverHelloMsg) marshal() []byte {
@@ -327,7 +327,7 @@ func (m *serverHelloMsg) marshal() []byte {
nextProtoLen += len(m.nextProtos)
extensionsLength += nextProtoLen
}
- if m.certStatus {
+ if m.ocspStapling {
numExtensions++
}
if numExtensions > 0 {
@@ -373,7 +373,7 @@ func (m *serverHelloMsg) marshal() []byte {
z = z[1+l:]
}
}
- if m.certStatus {
+ if m.ocspStapling {
z[0] = byte(extensionStatusRequest >> 8)
z[1] = byte(extensionStatusRequest)
z = z[4:]
@@ -406,7 +406,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
m.nextProtoNeg = false
m.nextProtos = nil
- m.certStatus = false
+ m.ocspStapling = false
if len(data) == 0 {
// ServerHello is optionally followed by extension data
@@ -450,7 +450,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
if length > 0 {
return false
}
- m.certStatus = true
+ m.ocspStapling = true
}
data = data[length:]
}
diff --git a/libgo/go/crypto/tls/handshake_messages_test.go b/libgo/go/crypto/tls/handshake_messages_test.go
index 0b93b89..23f729d 100644
--- a/libgo/go/crypto/tls/handshake_messages_test.go
+++ b/libgo/go/crypto/tls/handshake_messages_test.go
@@ -32,7 +32,7 @@ type testMessage interface {
func TestMarshalUnmarshal(t *testing.T) {
rand := rand.New(rand.NewSource(0))
for i, iface := range tests {
- ty := reflect.NewValue(iface).Type()
+ ty := reflect.ValueOf(iface).Type()
n := 100
if testing.Short() {
@@ -121,11 +121,11 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m.ocspStapling = rand.Intn(10) > 5
m.supportedPoints = randomBytes(rand.Intn(5)+1, rand)
m.supportedCurves = make([]uint16, rand.Intn(5)+1)
- for i, _ := range m.supportedCurves {
+ for i := range m.supportedCurves {
m.supportedCurves[i] = uint16(rand.Intn(30000))
}
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
@@ -146,7 +146,7 @@ func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
}
}
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
func (*certificateMsg) Generate(rand *rand.Rand, size int) reflect.Value {
@@ -156,7 +156,7 @@ func (*certificateMsg) Generate(rand *rand.Rand, size int) reflect.Value {
for i := 0; i < numCerts; i++ {
m.certificates[i] = randomBytes(rand.Intn(10)+1, rand)
}
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
func (*certificateRequestMsg) Generate(rand *rand.Rand, size int) reflect.Value {
@@ -167,13 +167,13 @@ func (*certificateRequestMsg) Generate(rand *rand.Rand, size int) reflect.Value
for i := 0; i < numCAs; i++ {
m.certificateAuthorities[i] = randomBytes(rand.Intn(15)+1, rand)
}
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
func (*certificateVerifyMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m := &certificateVerifyMsg{}
m.signature = randomBytes(rand.Intn(15)+1, rand)
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
func (*certificateStatusMsg) Generate(rand *rand.Rand, size int) reflect.Value {
@@ -184,23 +184,23 @@ func (*certificateStatusMsg) Generate(rand *rand.Rand, size int) reflect.Value {
} else {
m.statusType = 42
}
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
func (*clientKeyExchangeMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m := &clientKeyExchangeMsg{}
m.ciphertext = randomBytes(rand.Intn(1000)+1, rand)
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
func (*finishedMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m := &finishedMsg{}
m.verifyData = randomBytes(12, rand)
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
func (*nextProtoMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m := &nextProtoMsg{}
m.proto = randomString(rand.Intn(255), rand)
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
diff --git a/libgo/go/crypto/tls/handshake_server.go b/libgo/go/crypto/tls/handshake_server.go
index 809c8c1..37c8d15 100644
--- a/libgo/go/crypto/tls/handshake_server.go
+++ b/libgo/go/crypto/tls/handshake_server.go
@@ -103,6 +103,9 @@ FindCipherSuite:
hello.nextProtoNeg = true
hello.nextProtos = config.NextProtos
}
+ if clientHello.ocspStapling && len(config.Certificates[0].OCSPStaple) > 0 {
+ hello.ocspStapling = true
+ }
finishedHash.Write(hello.marshal())
c.writeRecord(recordTypeHandshake, hello.marshal())
@@ -116,6 +119,14 @@ FindCipherSuite:
finishedHash.Write(certMsg.marshal())
c.writeRecord(recordTypeHandshake, certMsg.marshal())
+ if hello.ocspStapling {
+ certStatus := new(certificateStatusMsg)
+ certStatus.statusType = statusTypeOCSP
+ certStatus.response = config.Certificates[0].OCSPStaple
+ finishedHash.Write(certStatus.marshal())
+ c.writeRecord(recordTypeHandshake, certStatus.marshal())
+ }
+
keyAgreement := suite.ka()
skx, err := keyAgreement.generateServerKeyExchange(config, clientHello, hello)
diff --git a/libgo/go/crypto/tls/handshake_server_test.go b/libgo/go/crypto/tls/handshake_server_test.go
index 6beb6a9..5a1e754 100644
--- a/libgo/go/crypto/tls/handshake_server_test.go
+++ b/libgo/go/crypto/tls/handshake_server_test.go
@@ -188,8 +188,10 @@ var testPrivateKey = &rsa.PrivateKey{
E: 65537,
},
D: bigFromString("29354450337804273969007277378287027274721892607543397931919078829901848876371746653677097639302788129485893852488285045793268732234230875671682624082413996177431586734171663258657462237320300610850244186316880055243099640544518318093544057213190320837094958164973959123058337475052510833916491060913053867729"),
- P: bigFromString("11969277782311800166562047708379380720136961987713178380670422671426759650127150688426177829077494755200794297055316163155755835813760102405344560929062149"),
- Q: bigFromString("10998999429884441391899182616418192492905073053684657075974935218461686523870125521822756579792315215543092255516093840728890783887287417039645833477273829"),
+ Primes: []*big.Int{
+ bigFromString("11969277782311800166562047708379380720136961987713178380670422671426759650127150688426177829077494755200794297055316163155755835813760102405344560929062149"),
+ bigFromString("10998999429884441391899182616418192492905073053684657075974935218461686523870125521822756579792315215543092255516093840728890783887287417039645833477273829"),
+ },
}
// Script of interaction with gnutls implementation.
diff --git a/libgo/go/crypto/tls/tls.go b/libgo/go/crypto/tls/tls.go
index 7de44bb..7d0bb9f 100644
--- a/libgo/go/crypto/tls/tls.go
+++ b/libgo/go/crypto/tls/tls.go
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This package partially implements the TLS 1.1 protocol, as specified in RFC 4346.
+// Package tls partially implements the TLS 1.1 protocol, as specified in RFC
+// 4346.
package tls
import (