diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-05-20 00:18:15 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-05-20 00:18:15 +0000 |
commit | 9ff56c9570642711d5b7ab29920ecf5dbff14a27 (patch) | |
tree | c891bdec1e6f073f73fedeef23718bc3ac30d499 /libgo/go/crypto/tls | |
parent | 37cb25ed7acdb844b218231130e54b8b7a0ff6e6 (diff) | |
download | gcc-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.go | 89 | ||||
-rw-r--r-- | libgo/go/crypto/tls/common.go | 19 | ||||
-rw-r--r-- | libgo/go/crypto/tls/conn.go | 4 | ||||
-rw-r--r-- | libgo/go/crypto/tls/handshake_client.go | 49 | ||||
-rw-r--r-- | libgo/go/crypto/tls/handshake_messages.go | 10 | ||||
-rw-r--r-- | libgo/go/crypto/tls/handshake_messages_test.go | 22 | ||||
-rw-r--r-- | libgo/go/crypto/tls/handshake_server.go | 11 | ||||
-rw-r--r-- | libgo/go/crypto/tls/handshake_server_test.go | 6 | ||||
-rw-r--r-- | libgo/go/crypto/tls/tls.go | 3 |
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 ( |