github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/crypto/tls/handshake_client.go (about)

     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 := masterFromPreMasterSecret(c.vers, preMasterSecret, hello.random, serverHello.random)
   282  	clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
   283  		keysFromMasterSecret(c.vers, masterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
   284  
   285  	clientCipher := suite.cipher(clientKey, clientIV, false /* not for reading */)
   286  	clientHash := suite.mac(c.vers, clientMAC)
   287  	c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
   288  	c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
   289  
   290  	if serverHello.nextProtoNeg {
   291  		nextProto := new(nextProtoMsg)
   292  		proto, fallback := mutualProtocol(c.config.NextProtos, serverHello.nextProtos)
   293  		nextProto.proto = proto
   294  		c.clientProtocol = proto
   295  		c.clientProtocolFallback = fallback
   296  
   297  		finishedHash.Write(nextProto.marshal())
   298  		c.writeRecord(recordTypeHandshake, nextProto.marshal())
   299  	}
   300  
   301  	finished := new(finishedMsg)
   302  	finished.verifyData = finishedHash.clientSum(masterSecret)
   303  	finishedHash.Write(finished.marshal())
   304  	c.writeRecord(recordTypeHandshake, finished.marshal())
   305  
   306  	serverCipher := suite.cipher(serverKey, serverIV, true /* for reading */)
   307  	serverHash := suite.mac(c.vers, serverMAC)
   308  	c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
   309  	c.readRecord(recordTypeChangeCipherSpec)
   310  	if err := c.error(); err != nil {
   311  		return err
   312  	}
   313  
   314  	msg, err = c.readHandshake()
   315  	if err != nil {
   316  		return err
   317  	}
   318  	serverFinished, ok := msg.(*finishedMsg)
   319  	if !ok {
   320  		return c.sendAlert(alertUnexpectedMessage)
   321  	}
   322  
   323  	verify := finishedHash.serverSum(masterSecret)
   324  	if len(verify) != len(serverFinished.verifyData) ||
   325  		subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
   326  		return c.sendAlert(alertHandshakeFailure)
   327  	}
   328  
   329  	c.handshakeComplete = true
   330  	c.cipherSuite = suite.id
   331  	return nil
   332  }
   333  
   334  // mutualProtocol finds the mutual Next Protocol Negotiation protocol given the
   335  // set of client and server supported protocols. The set of client supported
   336  // protocols must not be empty. It returns the resulting protocol and flag
   337  // indicating if the fallback case was reached.
   338  func mutualProtocol(clientProtos, serverProtos []string) (string, bool) {
   339  	for _, s := range serverProtos {
   340  		for _, c := range clientProtos {
   341  			if s == c {
   342  				return s, false
   343  			}
   344  		}
   345  	}
   346  
   347  	return clientProtos[0], true
   348  }