OSDN Git Service

Update Go library to last weekly.
[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         "crypto"
9         "crypto/rsa"
10         "crypto/subtle"
11         "crypto/x509"
12         "io"
13         "os"
14 )
15
16 func (c *Conn) clientHandshake() os.Error {
17         finishedHash := newFinishedHash(versionTLS10)
18
19         if c.config == nil {
20                 c.config = defaultConfig()
21         }
22
23         hello := &clientHelloMsg{
24                 vers:               maxVersion,
25                 cipherSuites:       c.config.cipherSuites(),
26                 compressionMethods: []uint8{compressionNone},
27                 random:             make([]byte, 32),
28                 ocspStapling:       true,
29                 serverName:         c.config.ServerName,
30                 supportedCurves:    []uint16{curveP256, curveP384, curveP521},
31                 supportedPoints:    []uint8{pointFormatUncompressed},
32                 nextProtoNeg:       len(c.config.NextProtos) > 0,
33         }
34
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:])
41         if err != nil {
42                 c.sendAlert(alertInternalError)
43                 return os.NewError("short read from Rand")
44         }
45
46         finishedHash.Write(hello.marshal())
47         c.writeRecord(recordTypeHandshake, hello.marshal())
48
49         msg, err := c.readHandshake()
50         if err != nil {
51                 return err
52         }
53         serverHello, ok := msg.(*serverHelloMsg)
54         if !ok {
55                 return c.sendAlert(alertUnexpectedMessage)
56         }
57         finishedHash.Write(serverHello.marshal())
58
59         vers, ok := mutualVersion(serverHello.vers)
60         if !ok {
61                 return c.sendAlert(alertProtocolVersion)
62         }
63         c.vers = vers
64         c.haveVers = true
65
66         if serverHello.compressionMethod != compressionNone {
67                 return c.sendAlert(alertUnexpectedMessage)
68         }
69
70         if !hello.nextProtoNeg && serverHello.nextProtoNeg {
71                 c.sendAlert(alertHandshakeFailure)
72                 return os.NewError("server advertised unrequested NPN")
73         }
74
75         suite, suiteId := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
76         if suite == nil {
77                 return c.sendAlert(alertHandshakeFailure)
78         }
79
80         msg, err = c.readHandshake()
81         if err != nil {
82                 return err
83         }
84         certMsg, ok := msg.(*certificateMsg)
85         if !ok || len(certMsg.certificates) == 0 {
86                 return c.sendAlert(alertUnexpectedMessage)
87         }
88         finishedHash.Write(certMsg.marshal())
89
90         certs := make([]*x509.Certificate, len(certMsg.certificates))
91         for i, asn1Data := range certMsg.certificates {
92                 cert, err := x509.ParseCertificate(asn1Data)
93                 if err != nil {
94                         c.sendAlert(alertBadCertificate)
95                         return os.NewError("failed to parse certificate from server: " + err.String())
96                 }
97                 certs[i] = cert
98         }
99
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(),
106                 }
107
108                 for i, cert := range certs {
109                         if i == 0 {
110                                 continue
111                         }
112                         opts.Intermediates.AddCert(cert)
113                 }
114                 c.verifiedChains, err = certs[0].Verify(opts)
115                 if err != nil {
116                         c.sendAlert(alertBadCertificate)
117                         return err
118                 }
119         }
120
121         if _, ok := certs[0].PublicKey.(*rsa.PublicKey); !ok {
122                 return c.sendAlert(alertUnsupportedCertificate)
123         }
124
125         c.peerCertificates = certs
126
127         if serverHello.ocspStapling {
128                 msg, err = c.readHandshake()
129                 if err != nil {
130                         return err
131                 }
132                 cs, ok := msg.(*certificateStatusMsg)
133                 if !ok {
134                         return c.sendAlert(alertUnexpectedMessage)
135                 }
136                 finishedHash.Write(cs.marshal())
137
138                 if cs.statusType == statusTypeOCSP {
139                         c.ocspResponse = cs.response
140                 }
141         }
142
143         msg, err = c.readHandshake()
144         if err != nil {
145                 return err
146         }
147
148         keyAgreement := suite.ka()
149
150         skx, ok := msg.(*serverKeyExchangeMsg)
151         if ok {
152                 finishedHash.Write(skx.marshal())
153                 err = keyAgreement.processServerKeyExchange(c.config, hello, serverHello, certs[0], skx)
154                 if err != nil {
155                         c.sendAlert(alertUnexpectedMessage)
156                         return err
157                 }
158
159                 msg, err = c.readHandshake()
160                 if err != nil {
161                         return err
162                 }
163         }
164
165         transmitCert := false
166         certReq, ok := msg.(*certificateRequestMsg)
167         if ok {
168                 // We only accept certificates with RSA keys.
169                 rsaAvail := false
170                 for _, certType := range certReq.certificateTypes {
171                         if certType == certTypeRSASign {
172                                 rsaAvail = true
173                                 break
174                         }
175                 }
176
177                 // For now, only send a certificate back if the server gives us an
178                 // empty list of certificateAuthorities.
179                 //
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 {
190                         transmitCert = true
191                 }
192
193                 finishedHash.Write(certReq.marshal())
194
195                 msg, err = c.readHandshake()
196                 if err != nil {
197                         return err
198                 }
199         }
200
201         shd, ok := msg.(*serverHelloDoneMsg)
202         if !ok {
203                 return c.sendAlert(alertUnexpectedMessage)
204         }
205         finishedHash.Write(shd.marshal())
206
207         var cert *x509.Certificate
208         if transmitCert {
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
214                         } else {
215                                 cert = nil
216                         }
217                 }
218                 finishedHash.Write(certMsg.marshal())
219                 c.writeRecord(recordTypeHandshake, certMsg.marshal())
220         }
221
222         preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hello, certs[0])
223         if err != nil {
224                 c.sendAlert(alertInternalError)
225                 return err
226         }
227         if ckx != nil {
228                 finishedHash.Write(ckx.marshal())
229                 c.writeRecord(recordTypeHandshake, ckx.marshal())
230         }
231
232         if cert != nil {
233                 certVerify := new(certificateVerifyMsg)
234                 var digest [36]byte
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:])
238                 if err != nil {
239                         return c.sendAlert(alertInternalError)
240                 }
241                 certVerify.signature = signed
242
243                 finishedHash.Write(certVerify.marshal())
244                 c.writeRecord(recordTypeHandshake, certVerify.marshal())
245         }
246
247         masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
248                 keysFromPreMasterSecret(c.vers, preMasterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
249
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})
254
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
261
262                 finishedHash.Write(nextProto.marshal())
263                 c.writeRecord(recordTypeHandshake, nextProto.marshal())
264         }
265
266         finished := new(finishedMsg)
267         finished.verifyData = finishedHash.clientSum(masterSecret)
268         finishedHash.Write(finished.marshal())
269         c.writeRecord(recordTypeHandshake, finished.marshal())
270
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)
275         if c.err != nil {
276                 return c.err
277         }
278
279         msg, err = c.readHandshake()
280         if err != nil {
281                 return err
282         }
283         serverFinished, ok := msg.(*finishedMsg)
284         if !ok {
285                 return c.sendAlert(alertUnexpectedMessage)
286         }
287
288         verify := finishedHash.serverSum(masterSecret)
289         if len(verify) != len(serverFinished.verifyData) ||
290                 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
291                 return c.sendAlert(alertHandshakeFailure)
292         }
293
294         c.handshakeComplete = true
295         c.cipherSuite = suiteId
296         return nil
297 }
298
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 {
306                         if s == c {
307                                 return s, false
308                         }
309                 }
310         }
311
312         return clientProtos[0], true
313 }