The Go Programming Language

Source file src/pkg/crypto/tls/handshake_client.go

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package tls
     6	
     7	import (
     8		"crypto"
     9		"crypto/rsa"
    10		"crypto/subtle"
    11		"crypto/x509"
    12		"io"
    13		"os"
    14	)
    15	
    16	func (c *Conn) clientHandshake() os.Error {
    17		finishedHash := newFinishedHash()
    18	
    19		if c.config == nil {
    20			c.config = defaultConfig()
    21		}
    22	
    23		hello := &clientHelloMsg{
    24			vers:               maxVersion,
    25			cipherSuites:       c.config.cipherSuites(),
    26			compressionMethods: []uint8{compressionNone},
    27			random:             make([]byte, 32),
    28			ocspStapling:       true,
    29			serverName:         c.config.ServerName,
    30			supportedCurves:    []uint16{curveP256, curveP384, curveP521},
    31			supportedPoints:    []uint8{pointFormatUncompressed},
    32			nextProtoNeg:       len(c.config.NextProtos) > 0,
    33		}
    34	
    35		t := uint32(c.config.time())
    36		hello.random[0] = byte(t >> 24)
    37		hello.random[1] = byte(t >> 16)
    38		hello.random[2] = byte(t >> 8)
    39		hello.random[3] = byte(t)
    40		_, err := io.ReadFull(c.config.rand(), hello.random[4:])
    41		if err != nil {
    42			c.sendAlert(alertInternalError)
    43			return os.NewError("short read from Rand")
    44		}
    45	
    46		finishedHash.Write(hello.marshal())
    47		c.writeRecord(recordTypeHandshake, hello.marshal())
    48	
    49		msg, err := c.readHandshake()
    50		if err != nil {
    51			return err
    52		}
    53		serverHello, ok := msg.(*serverHelloMsg)
    54		if !ok {
    55			return c.sendAlert(alertUnexpectedMessage)
    56		}
    57		finishedHash.Write(serverHello.marshal())
    58	
    59		vers, ok := mutualVersion(serverHello.vers)
    60		if !ok {
    61			return c.sendAlert(alertProtocolVersion)
    62		}
    63		c.vers = vers
    64		c.haveVers = true
    65	
    66		if serverHello.compressionMethod != compressionNone {
    67			return c.sendAlert(alertUnexpectedMessage)
    68		}
    69	
    70		if !hello.nextProtoNeg && serverHello.nextProtoNeg {
    71			c.sendAlert(alertHandshakeFailure)
    72			return os.NewError("server advertised unrequested NPN")
    73		}
    74	
    75		suite, suiteId := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
    76		if suite == nil {
    77			return c.sendAlert(alertHandshakeFailure)
    78		}
    79	
    80		msg, err = c.readHandshake()
    81		if err != nil {
    82			return err
    83		}
    84		certMsg, ok := msg.(*certificateMsg)
    85		if !ok || len(certMsg.certificates) == 0 {
    86			return c.sendAlert(alertUnexpectedMessage)
    87		}
    88		finishedHash.Write(certMsg.marshal())
    89	
    90		certs := make([]*x509.Certificate, len(certMsg.certificates))
    91		for i, asn1Data := range certMsg.certificates {
    92			cert, err := x509.ParseCertificate(asn1Data)
    93			if err != nil {
    94				c.sendAlert(alertBadCertificate)
    95				return os.NewError("failed to parse certificate from server: " + err.String())
    96			}
    97			certs[i] = cert
    98		}
    99	
   100		// If we don't have a root CA set configured then anything is accepted.
   101		// TODO(rsc): Find certificates for OS X 10.6.
   102		if c.config.RootCAs != nil {
   103			opts := x509.VerifyOptions{
   104				Roots:         c.config.RootCAs,
   105				CurrentTime:   c.config.time(),
   106				DNSName:       c.config.ServerName,
   107				Intermediates: x509.NewCertPool(),
   108			}
   109	
   110			for i, cert := range certs {
   111				if i == 0 {
   112					continue
   113				}
   114				opts.Intermediates.AddCert(cert)
   115			}
   116			c.verifiedChains, err = certs[0].Verify(opts)
   117			if err != nil {
   118				c.sendAlert(alertBadCertificate)
   119				return err
   120			}
   121		}
   122	
   123		if _, ok := certs[0].PublicKey.(*rsa.PublicKey); !ok {
   124			return c.sendAlert(alertUnsupportedCertificate)
   125		}
   126	
   127		c.peerCertificates = certs
   128	
   129		if serverHello.ocspStapling {
   130			msg, err = c.readHandshake()
   131			if err != nil {
   132				return err
   133			}
   134			cs, ok := msg.(*certificateStatusMsg)
   135			if !ok {
   136				return c.sendAlert(alertUnexpectedMessage)
   137			}
   138			finishedHash.Write(cs.marshal())
   139	
   140			if cs.statusType == statusTypeOCSP {
   141				c.ocspResponse = cs.response
   142			}
   143		}
   144	
   145		msg, err = c.readHandshake()
   146		if err != nil {
   147			return err
   148		}
   149	
   150		keyAgreement := suite.ka()
   151	
   152		skx, ok := msg.(*serverKeyExchangeMsg)
   153		if ok {
   154			finishedHash.Write(skx.marshal())
   155			err = keyAgreement.processServerKeyExchange(c.config, hello, serverHello, certs[0], skx)
   156			if err != nil {
   157				c.sendAlert(alertUnexpectedMessage)
   158				return err
   159			}
   160	
   161			msg, err = c.readHandshake()
   162			if err != nil {
   163				return err
   164			}
   165		}
   166	
   167		transmitCert := false
   168		certReq, ok := msg.(*certificateRequestMsg)
   169		if ok {
   170			// We only accept certificates with RSA keys.
   171			rsaAvail := false
   172			for _, certType := range certReq.certificateTypes {
   173				if certType == certTypeRSASign {
   174					rsaAvail = true
   175					break
   176				}
   177			}
   178	
   179			// For now, only send a certificate back if the server gives us an
   180			// empty list of certificateAuthorities.
   181			//
   182			// RFC 4346 on the certificateAuthorities field:
   183			// A list of the distinguished names of acceptable certificate
   184			// authorities.  These distinguished names may specify a desired
   185			// distinguished name for a root CA or for a subordinate CA; thus,
   186			// this message can be used to describe both known roots and a
   187			// desired authorization space.  If the certificate_authorities
   188			// list is empty then the client MAY send any certificate of the
   189			// appropriate ClientCertificateType, unless there is some
   190			// external arrangement to the contrary.
   191			if rsaAvail && len(certReq.certificateAuthorities) == 0 {
   192				transmitCert = true
   193			}
   194	
   195			finishedHash.Write(certReq.marshal())
   196	
   197			msg, err = c.readHandshake()
   198			if err != nil {
   199				return err
   200			}
   201		}
   202	
   203		shd, ok := msg.(*serverHelloDoneMsg)
   204		if !ok {
   205			return c.sendAlert(alertUnexpectedMessage)
   206		}
   207		finishedHash.Write(shd.marshal())
   208	
   209		var cert *x509.Certificate
   210		if transmitCert {
   211			certMsg = new(certificateMsg)
   212			if len(c.config.Certificates) > 0 {
   213				cert, err = x509.ParseCertificate(c.config.Certificates[0].Certificate[0])
   214				if err == nil && cert.PublicKeyAlgorithm == x509.RSA {
   215					certMsg.certificates = c.config.Certificates[0].Certificate
   216				} else {
   217					cert = nil
   218				}
   219			}
   220			finishedHash.Write(certMsg.marshal())
   221			c.writeRecord(recordTypeHandshake, certMsg.marshal())
   222		}
   223	
   224		preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hello, certs[0])
   225		if err != nil {
   226			c.sendAlert(alertInternalError)
   227			return err
   228		}
   229		if ckx != nil {
   230			finishedHash.Write(ckx.marshal())
   231			c.writeRecord(recordTypeHandshake, ckx.marshal())
   232		}
   233	
   234		if cert != nil {
   235			certVerify := new(certificateVerifyMsg)
   236			var digest [36]byte
   237			copy(digest[0:16], finishedHash.serverMD5.Sum())
   238			copy(digest[16:36], finishedHash.serverSHA1.Sum())
   239			signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey, crypto.MD5SHA1, digest[0:])
   240			if err != nil {
   241				return c.sendAlert(alertInternalError)
   242			}
   243			certVerify.signature = signed
   244	
   245			finishedHash.Write(certVerify.marshal())
   246			c.writeRecord(recordTypeHandshake, certVerify.marshal())
   247		}
   248	
   249		masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
   250			keysFromPreMasterSecret10(preMasterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
   251	
   252		clientCipher := suite.cipher(clientKey, clientIV, false /* not for reading */ )
   253		clientHash := suite.mac(clientMAC)
   254		c.out.prepareCipherSpec(clientCipher, clientHash)
   255		c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
   256	
   257		if serverHello.nextProtoNeg {
   258			nextProto := new(nextProtoMsg)
   259			proto, fallback := mutualProtocol(c.config.NextProtos, serverHello.nextProtos)
   260			nextProto.proto = proto
   261			c.clientProtocol = proto
   262			c.clientProtocolFallback = fallback
   263	
   264			finishedHash.Write(nextProto.marshal())
   265			c.writeRecord(recordTypeHandshake, nextProto.marshal())
   266		}
   267	
   268		finished := new(finishedMsg)
   269		finished.verifyData = finishedHash.clientSum(masterSecret)
   270		finishedHash.Write(finished.marshal())
   271		c.writeRecord(recordTypeHandshake, finished.marshal())
   272	
   273		serverCipher := suite.cipher(serverKey, serverIV, true /* for reading */ )
   274		serverHash := suite.mac(serverMAC)
   275		c.in.prepareCipherSpec(serverCipher, serverHash)
   276		c.readRecord(recordTypeChangeCipherSpec)
   277		if c.err != nil {
   278			return c.err
   279		}
   280	
   281		msg, err = c.readHandshake()
   282		if err != nil {
   283			return err
   284		}
   285		serverFinished, ok := msg.(*finishedMsg)
   286		if !ok {
   287			return c.sendAlert(alertUnexpectedMessage)
   288		}
   289	
   290		verify := finishedHash.serverSum(masterSecret)
   291		if len(verify) != len(serverFinished.verifyData) ||
   292			subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
   293			return c.sendAlert(alertHandshakeFailure)
   294		}
   295	
   296		c.handshakeComplete = true
   297		c.cipherSuite = suiteId
   298		return nil
   299	}
   300	
   301	// mutualProtocol finds the mutual Next Protocol Negotiation protocol given the
   302	// set of client and server supported protocols. The set of client supported
   303	// protocols must not be empty. It returns the resulting protocol and flag
   304	// indicating if the fallback case was reached.
   305	func mutualProtocol(clientProtos, serverProtos []string) (string, bool) {
   306		for _, s := range serverProtos {
   307			for _, c := range clientProtos {
   308				if s == c {
   309					return s, false
   310				}
   311			}
   312		}
   313	
   314		return clientProtos[0], true
   315	}

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.