src/pkg/crypto/tls/handshake_client.go - The Go Programming Language

Golang

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