OSDN Git Service

Update Go library to r60.
[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()
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 we don't have a root CA set configured then anything is accepted.
101         // TODO(rsc): Find certificates for OS X 10.6.
102         if c.config.RootCAs != nil {
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         transmitCert := false
168         certReq, ok := msg.(*certificateRequestMsg)
169         if ok {
170                 // We only accept certificates with RSA keys.
171                 rsaAvail := false
172                 for _, certType := range certReq.certificateTypes {
173                         if certType == certTypeRSASign {
174                                 rsaAvail = true
175                                 break
176                         }
177                 }
178
179                 // For now, only send a certificate back if the server gives us an
180                 // empty list of certificateAuthorities.
181                 //
182                 // RFC 4346 on the certificateAuthorities field:
183                 // A list of the distinguished names of acceptable certificate
184                 // authorities.  These distinguished names may specify a desired
185                 // distinguished name for a root CA or for a subordinate CA; thus,
186                 // this message can be used to describe both known roots and a
187                 // desired authorization space.  If the certificate_authorities
188                 // list is empty then the client MAY send any certificate of the
189                 // appropriate ClientCertificateType, unless there is some
190                 // external arrangement to the contrary.
191                 if rsaAvail && len(certReq.certificateAuthorities) == 0 {
192                         transmitCert = true
193                 }
194
195                 finishedHash.Write(certReq.marshal())
196
197                 msg, err = c.readHandshake()
198                 if err != nil {
199                         return err
200                 }
201         }
202
203         shd, ok := msg.(*serverHelloDoneMsg)
204         if !ok {
205                 return c.sendAlert(alertUnexpectedMessage)
206         }
207         finishedHash.Write(shd.marshal())
208
209         var cert *x509.Certificate
210         if transmitCert {
211                 certMsg = new(certificateMsg)
212                 if len(c.config.Certificates) > 0 {
213                         cert, err = x509.ParseCertificate(c.config.Certificates[0].Certificate[0])
214                         if err == nil && cert.PublicKeyAlgorithm == x509.RSA {
215                                 certMsg.certificates = c.config.Certificates[0].Certificate
216                         } else {
217                                 cert = nil
218                         }
219                 }
220                 finishedHash.Write(certMsg.marshal())
221                 c.writeRecord(recordTypeHandshake, certMsg.marshal())
222         }
223
224         preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hello, certs[0])
225         if err != nil {
226                 c.sendAlert(alertInternalError)
227                 return err
228         }
229         if ckx != nil {
230                 finishedHash.Write(ckx.marshal())
231                 c.writeRecord(recordTypeHandshake, ckx.marshal())
232         }
233
234         if cert != nil {
235                 certVerify := new(certificateVerifyMsg)
236                 var digest [36]byte
237                 copy(digest[0:16], finishedHash.serverMD5.Sum())
238                 copy(digest[16:36], finishedHash.serverSHA1.Sum())
239                 signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey, crypto.MD5SHA1, digest[0:])
240                 if err != nil {
241                         return c.sendAlert(alertInternalError)
242                 }
243                 certVerify.signature = signed
244
245                 finishedHash.Write(certVerify.marshal())
246                 c.writeRecord(recordTypeHandshake, certVerify.marshal())
247         }
248
249         masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
250                 keysFromPreMasterSecret10(preMasterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
251
252         clientCipher := suite.cipher(clientKey, clientIV, false /* not for reading */ )
253         clientHash := suite.mac(clientMAC)
254         c.out.prepareCipherSpec(clientCipher, clientHash)
255         c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
256
257         if serverHello.nextProtoNeg {
258                 nextProto := new(nextProtoMsg)
259                 proto, fallback := mutualProtocol(c.config.NextProtos, serverHello.nextProtos)
260                 nextProto.proto = proto
261                 c.clientProtocol = proto
262                 c.clientProtocolFallback = fallback
263
264                 finishedHash.Write(nextProto.marshal())
265                 c.writeRecord(recordTypeHandshake, nextProto.marshal())
266         }
267
268         finished := new(finishedMsg)
269         finished.verifyData = finishedHash.clientSum(masterSecret)
270         finishedHash.Write(finished.marshal())
271         c.writeRecord(recordTypeHandshake, finished.marshal())
272
273         serverCipher := suite.cipher(serverKey, serverIV, true /* for reading */ )
274         serverHash := suite.mac(serverMAC)
275         c.in.prepareCipherSpec(serverCipher, serverHash)
276         c.readRecord(recordTypeChangeCipherSpec)
277         if c.err != nil {
278                 return c.err
279         }
280
281         msg, err = c.readHandshake()
282         if err != nil {
283                 return err
284         }
285         serverFinished, ok := msg.(*finishedMsg)
286         if !ok {
287                 return c.sendAlert(alertUnexpectedMessage)
288         }
289
290         verify := finishedHash.serverSum(masterSecret)
291         if len(verify) != len(serverFinished.verifyData) ||
292                 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
293                 return c.sendAlert(alertHandshakeFailure)
294         }
295
296         c.handshakeComplete = true
297         c.cipherSuite = suiteId
298         return nil
299 }
300
301 // mutualProtocol finds the mutual Next Protocol Negotiation protocol given the
302 // set of client and server supported protocols. The set of client supported
303 // protocols must not be empty. It returns the resulting protocol and flag
304 // indicating if the fallback case was reached.
305 func mutualProtocol(clientProtos, serverProtos []string) (string, bool) {
306         for _, s := range serverProtos {
307                 for _, c := range clientProtos {
308                         if s == c {
309                                 return s, false
310                         }
311                 }
312         }
313
314         return clientProtos[0], true
315 }