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.
16 func (c *Conn) clientHandshake() os.Error {
17 finishedHash := newFinishedHash(versionTLS10)
20 c.config = defaultConfig()
23 hello := &clientHelloMsg{
25 cipherSuites: c.config.cipherSuites(),
26 compressionMethods: []uint8{compressionNone},
27 random: make([]byte, 32),
29 serverName: c.config.ServerName,
30 supportedCurves: []uint16{curveP256, curveP384, curveP521},
31 supportedPoints: []uint8{pointFormatUncompressed},
32 nextProtoNeg: len(c.config.NextProtos) > 0,
35 t := uint32(c.config.time())
36 hello.random[0] = byte(t >> 24)
37 hello.random[1] = byte(t >> 16)
38 hello.random[2] = byte(t >> 8)
39 hello.random[3] = byte(t)
40 _, err := io.ReadFull(c.config.rand(), hello.random[4:])
42 c.sendAlert(alertInternalError)
43 return os.NewError("short read from Rand")
46 finishedHash.Write(hello.marshal())
47 c.writeRecord(recordTypeHandshake, hello.marshal())
49 msg, err := c.readHandshake()
53 serverHello, ok := msg.(*serverHelloMsg)
55 return c.sendAlert(alertUnexpectedMessage)
57 finishedHash.Write(serverHello.marshal())
59 vers, ok := mutualVersion(serverHello.vers)
61 return c.sendAlert(alertProtocolVersion)
66 if serverHello.compressionMethod != compressionNone {
67 return c.sendAlert(alertUnexpectedMessage)
70 if !hello.nextProtoNeg && serverHello.nextProtoNeg {
71 c.sendAlert(alertHandshakeFailure)
72 return os.NewError("server advertised unrequested NPN")
75 suite, suiteId := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
77 return c.sendAlert(alertHandshakeFailure)
80 msg, err = c.readHandshake()
84 certMsg, ok := msg.(*certificateMsg)
85 if !ok || len(certMsg.certificates) == 0 {
86 return c.sendAlert(alertUnexpectedMessage)
88 finishedHash.Write(certMsg.marshal())
90 certs := make([]*x509.Certificate, len(certMsg.certificates))
91 for i, asn1Data := range certMsg.certificates {
92 cert, err := x509.ParseCertificate(asn1Data)
94 c.sendAlert(alertBadCertificate)
95 return os.NewError("failed to parse certificate from server: " + err.String())
100 if !c.config.InsecureSkipVerify {
101 opts := x509.VerifyOptions{
102 Roots: c.config.rootCAs(),
103 CurrentTime: c.config.time(),
104 DNSName: c.config.ServerName,
105 Intermediates: x509.NewCertPool(),
108 for i, cert := range certs {
112 opts.Intermediates.AddCert(cert)
114 c.verifiedChains, err = certs[0].Verify(opts)
116 c.sendAlert(alertBadCertificate)
121 if _, ok := certs[0].PublicKey.(*rsa.PublicKey); !ok {
122 return c.sendAlert(alertUnsupportedCertificate)
125 c.peerCertificates = certs
127 if serverHello.ocspStapling {
128 msg, err = c.readHandshake()
132 cs, ok := msg.(*certificateStatusMsg)
134 return c.sendAlert(alertUnexpectedMessage)
136 finishedHash.Write(cs.marshal())
138 if cs.statusType == statusTypeOCSP {
139 c.ocspResponse = cs.response
143 msg, err = c.readHandshake()
148 keyAgreement := suite.ka()
150 skx, ok := msg.(*serverKeyExchangeMsg)
152 finishedHash.Write(skx.marshal())
153 err = keyAgreement.processServerKeyExchange(c.config, hello, serverHello, certs[0], skx)
155 c.sendAlert(alertUnexpectedMessage)
159 msg, err = c.readHandshake()
165 transmitCert := false
166 certReq, ok := msg.(*certificateRequestMsg)
168 // We only accept certificates with RSA keys.
170 for _, certType := range certReq.certificateTypes {
171 if certType == certTypeRSASign {
177 // For now, only send a certificate back if the server gives us an
178 // empty list of certificateAuthorities.
180 // RFC 4346 on the certificateAuthorities field:
181 // A list of the distinguished names of acceptable certificate
182 // authorities. These distinguished names may specify a desired
183 // distinguished name for a root CA or for a subordinate CA; thus,
184 // this message can be used to describe both known roots and a
185 // desired authorization space. If the certificate_authorities
186 // list is empty then the client MAY send any certificate of the
187 // appropriate ClientCertificateType, unless there is some
188 // external arrangement to the contrary.
189 if rsaAvail && len(certReq.certificateAuthorities) == 0 {
193 finishedHash.Write(certReq.marshal())
195 msg, err = c.readHandshake()
201 shd, ok := msg.(*serverHelloDoneMsg)
203 return c.sendAlert(alertUnexpectedMessage)
205 finishedHash.Write(shd.marshal())
207 var cert *x509.Certificate
209 certMsg = new(certificateMsg)
210 if len(c.config.Certificates) > 0 {
211 cert, err = x509.ParseCertificate(c.config.Certificates[0].Certificate[0])
212 if err == nil && cert.PublicKeyAlgorithm == x509.RSA {
213 certMsg.certificates = c.config.Certificates[0].Certificate
218 finishedHash.Write(certMsg.marshal())
219 c.writeRecord(recordTypeHandshake, certMsg.marshal())
222 preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hello, certs[0])
224 c.sendAlert(alertInternalError)
228 finishedHash.Write(ckx.marshal())
229 c.writeRecord(recordTypeHandshake, ckx.marshal())
233 certVerify := new(certificateVerifyMsg)
235 copy(digest[0:16], finishedHash.serverMD5.Sum())
236 copy(digest[16:36], finishedHash.serverSHA1.Sum())
237 signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey, crypto.MD5SHA1, digest[0:])
239 return c.sendAlert(alertInternalError)
241 certVerify.signature = signed
243 finishedHash.Write(certVerify.marshal())
244 c.writeRecord(recordTypeHandshake, certVerify.marshal())
247 masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
248 keysFromPreMasterSecret(c.vers, preMasterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
250 clientCipher := suite.cipher(clientKey, clientIV, false /* not for reading */ )
251 clientHash := suite.mac(c.vers, clientMAC)
252 c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
253 c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
255 if serverHello.nextProtoNeg {
256 nextProto := new(nextProtoMsg)
257 proto, fallback := mutualProtocol(c.config.NextProtos, serverHello.nextProtos)
258 nextProto.proto = proto
259 c.clientProtocol = proto
260 c.clientProtocolFallback = fallback
262 finishedHash.Write(nextProto.marshal())
263 c.writeRecord(recordTypeHandshake, nextProto.marshal())
266 finished := new(finishedMsg)
267 finished.verifyData = finishedHash.clientSum(masterSecret)
268 finishedHash.Write(finished.marshal())
269 c.writeRecord(recordTypeHandshake, finished.marshal())
271 serverCipher := suite.cipher(serverKey, serverIV, true /* for reading */ )
272 serverHash := suite.mac(c.vers, serverMAC)
273 c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
274 c.readRecord(recordTypeChangeCipherSpec)
279 msg, err = c.readHandshake()
283 serverFinished, ok := msg.(*finishedMsg)
285 return c.sendAlert(alertUnexpectedMessage)
288 verify := finishedHash.serverSum(masterSecret)
289 if len(verify) != len(serverFinished.verifyData) ||
290 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
291 return c.sendAlert(alertHandshakeFailure)
294 c.handshakeComplete = true
295 c.cipherSuite = suiteId
299 // mutualProtocol finds the mutual Next Protocol Negotiation protocol given the
300 // set of client and server supported protocols. The set of client supported
301 // protocols must not be empty. It returns the resulting protocol and flag
302 // indicating if the fallback case was reached.
303 func mutualProtocol(clientProtos, serverProtos []string) (string, bool) {
304 for _, s := range serverProtos {
305 for _, c := range clientProtos {
312 return clientProtos[0], true