OSDN Git Service

632ceea9c1a2adbdfb7261cd373666770d519c6c
[pf3gnuchains/gcc-fork.git] / libgo / go / crypto / tls / handshake_client.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         "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 {
63                 return c.sendAlert(alertProtocolVersion)
64         }
65         c.vers = vers
66         c.haveVers = true
67
68         if serverHello.compressionMethod != compressionNone {
69                 return c.sendAlert(alertUnexpectedMessage)
70         }
71
72         if !hello.nextProtoNeg && serverHello.nextProtoNeg {
73                 c.sendAlert(alertHandshakeFailure)
74                 return errors.New("server advertised unrequested NPN")
75         }
76
77         suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
78         if suite == nil {
79                 return c.sendAlert(alertHandshakeFailure)
80         }
81
82         msg, err = c.readHandshake()
83         if err != nil {
84                 return err
85         }
86         certMsg, ok := msg.(*certificateMsg)
87         if !ok || len(certMsg.certificates) == 0 {
88                 return c.sendAlert(alertUnexpectedMessage)
89         }
90         finishedHash.Write(certMsg.marshal())
91
92         certs := make([]*x509.Certificate, len(certMsg.certificates))
93         for i, asn1Data := range certMsg.certificates {
94                 cert, err := x509.ParseCertificate(asn1Data)
95                 if err != nil {
96                         c.sendAlert(alertBadCertificate)
97                         return errors.New("failed to parse certificate from server: " + err.Error())
98                 }
99                 certs[i] = cert
100         }
101
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(),
108                 }
109
110                 for i, cert := range certs {
111                         if i == 0 {
112                                 continue
113                         }
114                         opts.Intermediates.AddCert(cert)
115                 }
116                 c.verifiedChains, err = certs[0].Verify(opts)
117                 if err != nil {
118                         c.sendAlert(alertBadCertificate)
119                         return err
120                 }
121         }
122
123         if _, ok := certs[0].PublicKey.(*rsa.PublicKey); !ok {
124                 return c.sendAlert(alertUnsupportedCertificate)
125         }
126
127         c.peerCertificates = certs
128
129         if serverHello.ocspStapling {
130                 msg, err = c.readHandshake()
131                 if err != nil {
132                         return err
133                 }
134                 cs, ok := msg.(*certificateStatusMsg)
135                 if !ok {
136                         return c.sendAlert(alertUnexpectedMessage)
137                 }
138                 finishedHash.Write(cs.marshal())
139
140                 if cs.statusType == statusTypeOCSP {
141                         c.ocspResponse = cs.response
142                 }
143         }
144
145         msg, err = c.readHandshake()
146         if err != nil {
147                 return err
148         }
149
150         keyAgreement := suite.ka()
151
152         skx, ok := msg.(*serverKeyExchangeMsg)
153         if ok {
154                 finishedHash.Write(skx.marshal())
155                 err = keyAgreement.processServerKeyExchange(c.config, hello, serverHello, certs[0], skx)
156                 if err != nil {
157                         c.sendAlert(alertUnexpectedMessage)
158                         return err
159                 }
160
161                 msg, err = c.readHandshake()
162                 if err != nil {
163                         return err
164                 }
165         }
166
167         var certToSend *Certificate
168         certReq, ok := msg.(*certificateRequestMsg)
169         if ok {
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.
180
181                 finishedHash.Write(certReq.marshal())
182
183                 // For now, we only know how to sign challenges with RSA
184                 rsaAvail := false
185                 for _, certType := range certReq.certificateTypes {
186                         if certType == certTypeRSASign {
187                                 rsaAvail = true
188                                 break
189                         }
190                 }
191
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
195         findCert:
196                 for i, cert := range c.config.Certificates {
197                         if !rsaAvail {
198                                 continue
199                         }
200
201                         leaf := cert.Leaf
202                         if leaf == nil {
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())
206                                 }
207                         }
208
209                         if leaf.PublicKeyAlgorithm != x509.RSA {
210                                 continue
211                         }
212
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
216                                 certToSend = &cert
217                                 break
218                         }
219
220                         for _, ca := range certReq.certificateAuthorities {
221                                 if bytes.Equal(leaf.RawIssuer, ca) {
222                                         certToSend = &cert
223                                         break findCert
224                                 }
225                         }
226                 }
227
228                 msg, err = c.readHandshake()
229                 if err != nil {
230                         return err
231                 }
232         }
233
234         shd, ok := msg.(*serverHelloDoneMsg)
235         if !ok {
236                 return c.sendAlert(alertUnexpectedMessage)
237         }
238         finishedHash.Write(shd.marshal())
239
240         if certToSend != nil {
241                 certMsg = new(certificateMsg)
242                 certMsg.certificates = certToSend.Certificate
243                 finishedHash.Write(certMsg.marshal())
244                 c.writeRecord(recordTypeHandshake, certMsg.marshal())
245         }
246
247         preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hello, certs[0])
248         if err != nil {
249                 c.sendAlert(alertInternalError)
250                 return err
251         }
252         if ckx != nil {
253                 finishedHash.Write(ckx.marshal())
254                 c.writeRecord(recordTypeHandshake, ckx.marshal())
255         }
256
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)
263                 if err != nil {
264                         return c.sendAlert(alertInternalError)
265                 }
266                 certVerify.signature = signed
267
268                 finishedHash.Write(certVerify.marshal())
269                 c.writeRecord(recordTypeHandshake, certVerify.marshal())
270         }
271
272         masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
273                 keysFromPreMasterSecret(c.vers, preMasterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
274
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})
279
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
286
287                 finishedHash.Write(nextProto.marshal())
288                 c.writeRecord(recordTypeHandshake, nextProto.marshal())
289         }
290
291         finished := new(finishedMsg)
292         finished.verifyData = finishedHash.clientSum(masterSecret)
293         finishedHash.Write(finished.marshal())
294         c.writeRecord(recordTypeHandshake, finished.marshal())
295
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)
300         if c.err != nil {
301                 return c.err
302         }
303
304         msg, err = c.readHandshake()
305         if err != nil {
306                 return err
307         }
308         serverFinished, ok := msg.(*finishedMsg)
309         if !ok {
310                 return c.sendAlert(alertUnexpectedMessage)
311         }
312
313         verify := finishedHash.serverSum(masterSecret)
314         if len(verify) != len(serverFinished.verifyData) ||
315                 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
316                 return c.sendAlert(alertHandshakeFailure)
317         }
318
319         c.handshakeComplete = true
320         c.cipherSuite = suite.id
321         return nil
322 }
323
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 {
331                         if s == c {
332                                 return s, false
333                         }
334                 }
335         }
336
337         return clientProtos[0], true
338 }