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.
18 func (c *Conn) clientHandshake() error {
19 finishedHash := newFinishedHash(versionTLS10)
22 c.config = defaultConfig()
25 hello := &clientHelloMsg{
27 cipherSuites: c.config.cipherSuites(),
28 compressionMethods: []uint8{compressionNone},
29 random: make([]byte, 32),
31 serverName: c.config.ServerName,
32 supportedCurves: []uint16{curveP256, curveP384, curveP521},
33 supportedPoints: []uint8{pointFormatUncompressed},
34 nextProtoNeg: len(c.config.NextProtos) > 0,
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:])
44 c.sendAlert(alertInternalError)
45 return errors.New("short read from Rand")
48 finishedHash.Write(hello.marshal())
49 c.writeRecord(recordTypeHandshake, hello.marshal())
51 msg, err := c.readHandshake()
55 serverHello, ok := msg.(*serverHelloMsg)
57 return c.sendAlert(alertUnexpectedMessage)
59 finishedHash.Write(serverHello.marshal())
61 vers, ok := mutualVersion(serverHello.vers)
63 return c.sendAlert(alertProtocolVersion)
68 if serverHello.compressionMethod != compressionNone {
69 return c.sendAlert(alertUnexpectedMessage)
72 if !hello.nextProtoNeg && serverHello.nextProtoNeg {
73 c.sendAlert(alertHandshakeFailure)
74 return errors.New("server advertised unrequested NPN")
77 suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
79 return c.sendAlert(alertHandshakeFailure)
82 msg, err = c.readHandshake()
86 certMsg, ok := msg.(*certificateMsg)
87 if !ok || len(certMsg.certificates) == 0 {
88 return c.sendAlert(alertUnexpectedMessage)
90 finishedHash.Write(certMsg.marshal())
92 certs := make([]*x509.Certificate, len(certMsg.certificates))
93 for i, asn1Data := range certMsg.certificates {
94 cert, err := x509.ParseCertificate(asn1Data)
96 c.sendAlert(alertBadCertificate)
97 return errors.New("failed to parse certificate from server: " + err.Error())
102 if !c.config.InsecureSkipVerify {
103 opts := x509.VerifyOptions{
104 Roots: c.config.rootCAs(),
105 CurrentTime: c.config.time(),
106 DNSName: c.config.ServerName,
107 Intermediates: x509.NewCertPool(),
110 for i, cert := range certs {
114 opts.Intermediates.AddCert(cert)
116 c.verifiedChains, err = certs[0].Verify(opts)
118 c.sendAlert(alertBadCertificate)
123 if _, ok := certs[0].PublicKey.(*rsa.PublicKey); !ok {
124 return c.sendAlert(alertUnsupportedCertificate)
127 c.peerCertificates = certs
129 if serverHello.ocspStapling {
130 msg, err = c.readHandshake()
134 cs, ok := msg.(*certificateStatusMsg)
136 return c.sendAlert(alertUnexpectedMessage)
138 finishedHash.Write(cs.marshal())
140 if cs.statusType == statusTypeOCSP {
141 c.ocspResponse = cs.response
145 msg, err = c.readHandshake()
150 keyAgreement := suite.ka()
152 skx, ok := msg.(*serverKeyExchangeMsg)
154 finishedHash.Write(skx.marshal())
155 err = keyAgreement.processServerKeyExchange(c.config, hello, serverHello, certs[0], skx)
157 c.sendAlert(alertUnexpectedMessage)
161 msg, err = c.readHandshake()
167 var certToSend *Certificate
168 certReq, ok := msg.(*certificateRequestMsg)
170 // RFC 4346 on the certificateAuthorities field:
171 // A list of the distinguished names of acceptable certificate
172 // authorities. These distinguished names may specify a desired
173 // distinguished name for a root CA or for a subordinate CA;
174 // thus, this message can be used to describe both known roots
175 // and a desired authorization space. If the
176 // certificate_authorities list is empty then the client MAY
177 // send any certificate of the appropriate
178 // ClientCertificateType, unless there is some external
179 // arrangement to the contrary.
181 finishedHash.Write(certReq.marshal())
183 // For now, we only know how to sign challenges with RSA
185 for _, certType := range certReq.certificateTypes {
186 if certType == certTypeRSASign {
192 // We need to search our list of client certs for one
193 // where SignatureAlgorithm is RSA and the Issuer is in
194 // certReq.certificateAuthorities
196 for i, cert := range c.config.Certificates {
203 if leaf, err = x509.ParseCertificate(cert.Certificate[0]); err != nil {
204 c.sendAlert(alertInternalError)
205 return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
209 if leaf.PublicKeyAlgorithm != x509.RSA {
213 if len(certReq.certificateAuthorities) == 0 {
214 // they gave us an empty list, so just take the
215 // first RSA cert from c.config.Certificates
220 for _, ca := range certReq.certificateAuthorities {
221 if bytes.Equal(leaf.RawIssuer, ca) {
228 msg, err = c.readHandshake()
234 shd, ok := msg.(*serverHelloDoneMsg)
236 return c.sendAlert(alertUnexpectedMessage)
238 finishedHash.Write(shd.marshal())
240 if certToSend != nil {
241 certMsg = new(certificateMsg)
242 certMsg.certificates = certToSend.Certificate
243 finishedHash.Write(certMsg.marshal())
244 c.writeRecord(recordTypeHandshake, certMsg.marshal())
247 preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hello, certs[0])
249 c.sendAlert(alertInternalError)
253 finishedHash.Write(ckx.marshal())
254 c.writeRecord(recordTypeHandshake, ckx.marshal())
257 if certToSend != nil {
258 certVerify := new(certificateVerifyMsg)
259 digest := make([]byte, 0, 36)
260 digest = finishedHash.serverMD5.Sum(digest)
261 digest = finishedHash.serverSHA1.Sum(digest)
262 signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey.(*rsa.PrivateKey), crypto.MD5SHA1, digest)
264 return c.sendAlert(alertInternalError)
266 certVerify.signature = signed
268 finishedHash.Write(certVerify.marshal())
269 c.writeRecord(recordTypeHandshake, certVerify.marshal())
272 masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
273 keysFromPreMasterSecret(c.vers, preMasterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
275 clientCipher := suite.cipher(clientKey, clientIV, false /* not for reading */ )
276 clientHash := suite.mac(c.vers, clientMAC)
277 c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
278 c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
280 if serverHello.nextProtoNeg {
281 nextProto := new(nextProtoMsg)
282 proto, fallback := mutualProtocol(c.config.NextProtos, serverHello.nextProtos)
283 nextProto.proto = proto
284 c.clientProtocol = proto
285 c.clientProtocolFallback = fallback
287 finishedHash.Write(nextProto.marshal())
288 c.writeRecord(recordTypeHandshake, nextProto.marshal())
291 finished := new(finishedMsg)
292 finished.verifyData = finishedHash.clientSum(masterSecret)
293 finishedHash.Write(finished.marshal())
294 c.writeRecord(recordTypeHandshake, finished.marshal())
296 serverCipher := suite.cipher(serverKey, serverIV, true /* for reading */ )
297 serverHash := suite.mac(c.vers, serverMAC)
298 c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
299 c.readRecord(recordTypeChangeCipherSpec)
304 msg, err = c.readHandshake()
308 serverFinished, ok := msg.(*finishedMsg)
310 return c.sendAlert(alertUnexpectedMessage)
313 verify := finishedHash.serverSum(masterSecret)
314 if len(verify) != len(serverFinished.verifyData) ||
315 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
316 return c.sendAlert(alertHandshakeFailure)
319 c.handshakeComplete = true
320 c.cipherSuite = suite.id
324 // mutualProtocol finds the mutual Next Protocol Negotiation protocol given the
325 // set of client and server supported protocols. The set of client supported
326 // protocols must not be empty. It returns the resulting protocol and flag
327 // indicating if the fallback case was reached.
328 func mutualProtocol(clientProtos, serverProtos []string) (string, bool) {
329 for _, s := range serverProtos {
330 for _, c := range clientProtos {
337 return clientProtos[0], true