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