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

Golang

Source file src/pkg/crypto/tls/handshake_server.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		"errors"
    13		"io"
    14	)
    15	
    16	func (c *Conn) serverHandshake() error {
    17		config := c.config
    18		msg, err := c.readHandshake()
    19		if err != nil {
    20			return err
    21		}
    22		clientHello, ok := msg.(*clientHelloMsg)
    23		if !ok {
    24			return c.sendAlert(alertUnexpectedMessage)
    25		}
    26		vers, ok := mutualVersion(clientHello.vers)
    27		if !ok {
    28			return c.sendAlert(alertProtocolVersion)
    29		}
    30		c.vers = vers
    31		c.haveVers = true
    32	
    33		finishedHash := newFinishedHash(vers)
    34		finishedHash.Write(clientHello.marshal())
    35	
    36		hello := new(serverHelloMsg)
    37	
    38		supportedCurve := false
    39	Curves:
    40		for _, curve := range clientHello.supportedCurves {
    41			switch curve {
    42			case curveP256, curveP384, curveP521:
    43				supportedCurve = true
    44				break Curves
    45			}
    46		}
    47	
    48		supportedPointFormat := false
    49		for _, pointFormat := range clientHello.supportedPoints {
    50			if pointFormat == pointFormatUncompressed {
    51				supportedPointFormat = true
    52				break
    53			}
    54		}
    55	
    56		ellipticOk := supportedCurve && supportedPointFormat
    57	
    58		var suite *cipherSuite
    59	FindCipherSuite:
    60		for _, id := range clientHello.cipherSuites {
    61			for _, supported := range config.cipherSuites() {
    62				if id == supported {
    63					var candidate *cipherSuite
    64	
    65					for _, s := range cipherSuites {
    66						if s.id == id {
    67							candidate = s
    68							break
    69						}
    70					}
    71					if candidate == nil {
    72						continue
    73					}
    74					// Don't select a ciphersuite which we can't
    75					// support for this client.
    76					if candidate.elliptic && !ellipticOk {
    77						continue
    78					}
    79					suite = candidate
    80					break FindCipherSuite
    81				}
    82			}
    83		}
    84	
    85		foundCompression := false
    86		// We only support null compression, so check that the client offered it.
    87		for _, compression := range clientHello.compressionMethods {
    88			if compression == compressionNone {
    89				foundCompression = true
    90				break
    91			}
    92		}
    93	
    94		if suite == nil || !foundCompression {
    95			return c.sendAlert(alertHandshakeFailure)
    96		}
    97	
    98		hello.vers = vers
    99		hello.cipherSuite = suite.id
   100		t := uint32(config.time().Unix())
   101		hello.random = make([]byte, 32)
   102		hello.random[0] = byte(t >> 24)
   103		hello.random[1] = byte(t >> 16)
   104		hello.random[2] = byte(t >> 8)
   105		hello.random[3] = byte(t)
   106		_, err = io.ReadFull(config.rand(), hello.random[4:])
   107		if err != nil {
   108			return c.sendAlert(alertInternalError)
   109		}
   110		hello.compressionMethod = compressionNone
   111		if clientHello.nextProtoNeg {
   112			hello.nextProtoNeg = true
   113			hello.nextProtos = config.NextProtos
   114		}
   115	
   116		if len(config.Certificates) == 0 {
   117			return c.sendAlert(alertInternalError)
   118		}
   119		cert := &config.Certificates[0]
   120		if len(clientHello.serverName) > 0 {
   121			c.serverName = clientHello.serverName
   122			cert = config.getCertificateForName(clientHello.serverName)
   123		}
   124	
   125		if clientHello.ocspStapling && len(cert.OCSPStaple) > 0 {
   126			hello.ocspStapling = true
   127		}
   128	
   129		finishedHash.Write(hello.marshal())
   130		c.writeRecord(recordTypeHandshake, hello.marshal())
   131	
   132		certMsg := new(certificateMsg)
   133		certMsg.certificates = cert.Certificate
   134		finishedHash.Write(certMsg.marshal())
   135		c.writeRecord(recordTypeHandshake, certMsg.marshal())
   136	
   137		if hello.ocspStapling {
   138			certStatus := new(certificateStatusMsg)
   139			certStatus.statusType = statusTypeOCSP
   140			certStatus.response = cert.OCSPStaple
   141			finishedHash.Write(certStatus.marshal())
   142			c.writeRecord(recordTypeHandshake, certStatus.marshal())
   143		}
   144	
   145		keyAgreement := suite.ka()
   146		skx, err := keyAgreement.generateServerKeyExchange(config, cert, clientHello, hello)
   147		if err != nil {
   148			c.sendAlert(alertHandshakeFailure)
   149			return err
   150		}
   151		if skx != nil {
   152			finishedHash.Write(skx.marshal())
   153			c.writeRecord(recordTypeHandshake, skx.marshal())
   154		}
   155	
   156		if config.ClientAuth >= RequestClientCert {
   157			// Request a client certificate
   158			certReq := new(certificateRequestMsg)
   159			certReq.certificateTypes = []byte{certTypeRSASign}
   160	
   161			// An empty list of certificateAuthorities signals to
   162			// the client that it may send any certificate in response
   163			// to our request. When we know the CAs we trust, then
   164			// we can send them down, so that the client can choose
   165			// an appropriate certificate to give to us.
   166			if config.ClientCAs != nil {
   167				certReq.certificateAuthorities = config.ClientCAs.Subjects()
   168			}
   169			finishedHash.Write(certReq.marshal())
   170			c.writeRecord(recordTypeHandshake, certReq.marshal())
   171		}
   172	
   173		helloDone := new(serverHelloDoneMsg)
   174		finishedHash.Write(helloDone.marshal())
   175		c.writeRecord(recordTypeHandshake, helloDone.marshal())
   176	
   177		var pub *rsa.PublicKey // public key for client auth, if any
   178	
   179		msg, err = c.readHandshake()
   180		if err != nil {
   181			return err
   182		}
   183	
   184		// If we requested a client certificate, then the client must send a
   185		// certificate message, even if it's empty.
   186		if config.ClientAuth >= RequestClientCert {
   187			if certMsg, ok = msg.(*certificateMsg); !ok {
   188				return c.sendAlert(alertHandshakeFailure)
   189			}
   190			finishedHash.Write(certMsg.marshal())
   191	
   192			if len(certMsg.certificates) == 0 {
   193				// The client didn't actually send a certificate
   194				switch config.ClientAuth {
   195				case RequireAnyClientCert, RequireAndVerifyClientCert:
   196					c.sendAlert(alertBadCertificate)
   197					return errors.New("tls: client didn't provide a certificate")
   198				}
   199			}
   200	
   201			certs := make([]*x509.Certificate, len(certMsg.certificates))
   202			for i, asn1Data := range certMsg.certificates {
   203				if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
   204					c.sendAlert(alertBadCertificate)
   205					return errors.New("tls: failed to parse client certificate: " + err.Error())
   206				}
   207			}
   208	
   209			if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
   210				opts := x509.VerifyOptions{
   211					Roots:         c.config.ClientCAs,
   212					CurrentTime:   c.config.time(),
   213					Intermediates: x509.NewCertPool(),
   214				}
   215	
   216				for i, cert := range certs {
   217					if i == 0 {
   218						continue
   219					}
   220					opts.Intermediates.AddCert(cert)
   221				}
   222	
   223				chains, err := certs[0].Verify(opts)
   224				if err != nil {
   225					c.sendAlert(alertBadCertificate)
   226					return errors.New("tls: failed to verify client's certificate: " + err.Error())
   227				}
   228	
   229				ok := false
   230				for _, ku := range certs[0].ExtKeyUsage {
   231					if ku == x509.ExtKeyUsageClientAuth {
   232						ok = true
   233						break
   234					}
   235				}
   236				if !ok {
   237					c.sendAlert(alertHandshakeFailure)
   238					return errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
   239				}
   240	
   241				c.verifiedChains = chains
   242			}
   243	
   244			if len(certs) > 0 {
   245				if pub, ok = certs[0].PublicKey.(*rsa.PublicKey); !ok {
   246					return c.sendAlert(alertUnsupportedCertificate)
   247				}
   248				c.peerCertificates = certs
   249			}
   250	
   251			msg, err = c.readHandshake()
   252			if err != nil {
   253				return err
   254			}
   255		}
   256	
   257		// Get client key exchange
   258		ckx, ok := msg.(*clientKeyExchangeMsg)
   259		if !ok {
   260			return c.sendAlert(alertUnexpectedMessage)
   261		}
   262		finishedHash.Write(ckx.marshal())
   263	
   264		// If we received a client cert in response to our certificate request message,
   265		// the client will send us a certificateVerifyMsg immediately after the
   266		// clientKeyExchangeMsg.  This message is a MD5SHA1 digest of all preceding
   267		// handshake-layer messages that is signed using the private key corresponding
   268		// to the client's certificate. This allows us to verify that the client is in
   269		// possession of the private key of the certificate.
   270		if len(c.peerCertificates) > 0 {
   271			msg, err = c.readHandshake()
   272			if err != nil {
   273				return err
   274			}
   275			certVerify, ok := msg.(*certificateVerifyMsg)
   276			if !ok {
   277				return c.sendAlert(alertUnexpectedMessage)
   278			}
   279	
   280			digest := make([]byte, 0, 36)
   281			digest = finishedHash.serverMD5.Sum(digest)
   282			digest = finishedHash.serverSHA1.Sum(digest)
   283			err = rsa.VerifyPKCS1v15(pub, crypto.MD5SHA1, digest, certVerify.signature)
   284			if err != nil {
   285				c.sendAlert(alertBadCertificate)
   286				return errors.New("could not validate signature of connection nonces: " + err.Error())
   287			}
   288	
   289			finishedHash.Write(certVerify.marshal())
   290		}
   291	
   292		preMasterSecret, err := keyAgreement.processClientKeyExchange(config, cert, ckx, c.vers)
   293		if err != nil {
   294			c.sendAlert(alertHandshakeFailure)
   295			return err
   296		}
   297	
   298		masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
   299			keysFromPreMasterSecret(c.vers, preMasterSecret, clientHello.random, hello.random, suite.macLen, suite.keyLen, suite.ivLen)
   300	
   301		clientCipher := suite.cipher(clientKey, clientIV, true /* for reading */)
   302		clientHash := suite.mac(c.vers, clientMAC)
   303		c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
   304		c.readRecord(recordTypeChangeCipherSpec)
   305		if err := c.error(); err != nil {
   306			return err
   307		}
   308	
   309		if hello.nextProtoNeg {
   310			msg, err = c.readHandshake()
   311			if err != nil {
   312				return err
   313			}
   314			nextProto, ok := msg.(*nextProtoMsg)
   315			if !ok {
   316				return c.sendAlert(alertUnexpectedMessage)
   317			}
   318			finishedHash.Write(nextProto.marshal())
   319			c.clientProtocol = nextProto.proto
   320		}
   321	
   322		msg, err = c.readHandshake()
   323		if err != nil {
   324			return err
   325		}
   326		clientFinished, ok := msg.(*finishedMsg)
   327		if !ok {
   328			return c.sendAlert(alertUnexpectedMessage)
   329		}
   330	
   331		verify := finishedHash.clientSum(masterSecret)
   332		if len(verify) != len(clientFinished.verifyData) ||
   333			subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
   334			return c.sendAlert(alertHandshakeFailure)
   335		}
   336	
   337		finishedHash.Write(clientFinished.marshal())
   338	
   339		serverCipher := suite.cipher(serverKey, serverIV, false /* not for reading */)
   340		serverHash := suite.mac(c.vers, serverMAC)
   341		c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
   342		c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
   343	
   344		finished := new(finishedMsg)
   345		finished.verifyData = finishedHash.serverSum(masterSecret)
   346		c.writeRecord(recordTypeHandshake, finished.marshal())
   347	
   348		c.handshakeComplete = true
   349		c.cipherSuite = suite.id
   350	
   351		return nil
   352	}