OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [crypto/] [tls/] [handshake_client.go] - Blame information for rev 747

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// 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 || vers < versionTLS10 {
63
                // TLS 1.0 is the minimum version supported as a client.
64
                return c.sendAlert(alertProtocolVersion)
65
        }
66
        c.vers = vers
67
        c.haveVers = true
68
 
69
        if serverHello.compressionMethod != compressionNone {
70
                return c.sendAlert(alertUnexpectedMessage)
71
        }
72
 
73
        if !hello.nextProtoNeg && serverHello.nextProtoNeg {
74
                c.sendAlert(alertHandshakeFailure)
75
                return errors.New("server advertised unrequested NPN")
76
        }
77
 
78
        suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
79
        if suite == nil {
80
                return c.sendAlert(alertHandshakeFailure)
81
        }
82
 
83
        msg, err = c.readHandshake()
84
        if err != nil {
85
                return err
86
        }
87
        certMsg, ok := msg.(*certificateMsg)
88
        if !ok || len(certMsg.certificates) == 0 {
89
                return c.sendAlert(alertUnexpectedMessage)
90
        }
91
        finishedHash.Write(certMsg.marshal())
92
 
93
        certs := make([]*x509.Certificate, len(certMsg.certificates))
94
        for i, asn1Data := range certMsg.certificates {
95
                cert, err := x509.ParseCertificate(asn1Data)
96
                if err != nil {
97
                        c.sendAlert(alertBadCertificate)
98
                        return errors.New("failed to parse certificate from server: " + err.Error())
99
                }
100
                certs[i] = cert
101
        }
102
 
103
        if !c.config.InsecureSkipVerify {
104
                opts := x509.VerifyOptions{
105
                        Roots:         c.config.rootCAs(),
106
                        CurrentTime:   c.config.time(),
107
                        DNSName:       c.config.ServerName,
108
                        Intermediates: x509.NewCertPool(),
109
                }
110
 
111
                for i, cert := range certs {
112
                        if i == 0 {
113
                                continue
114
                        }
115
                        opts.Intermediates.AddCert(cert)
116
                }
117
                c.verifiedChains, err = certs[0].Verify(opts)
118
                if err != nil {
119
                        c.sendAlert(alertBadCertificate)
120
                        return err
121
                }
122
        }
123
 
124
        if _, ok := certs[0].PublicKey.(*rsa.PublicKey); !ok {
125
                return c.sendAlert(alertUnsupportedCertificate)
126
        }
127
 
128
        c.peerCertificates = certs
129
 
130
        if serverHello.ocspStapling {
131
                msg, err = c.readHandshake()
132
                if err != nil {
133
                        return err
134
                }
135
                cs, ok := msg.(*certificateStatusMsg)
136
                if !ok {
137
                        return c.sendAlert(alertUnexpectedMessage)
138
                }
139
                finishedHash.Write(cs.marshal())
140
 
141
                if cs.statusType == statusTypeOCSP {
142
                        c.ocspResponse = cs.response
143
                }
144
        }
145
 
146
        msg, err = c.readHandshake()
147
        if err != nil {
148
                return err
149
        }
150
 
151
        keyAgreement := suite.ka()
152
 
153
        skx, ok := msg.(*serverKeyExchangeMsg)
154
        if ok {
155
                finishedHash.Write(skx.marshal())
156
                err = keyAgreement.processServerKeyExchange(c.config, hello, serverHello, certs[0], skx)
157
                if err != nil {
158
                        c.sendAlert(alertUnexpectedMessage)
159
                        return err
160
                }
161
 
162
                msg, err = c.readHandshake()
163
                if err != nil {
164
                        return err
165
                }
166
        }
167
 
168
        var certToSend *Certificate
169
        certReq, ok := msg.(*certificateRequestMsg)
170
        if ok {
171
                // RFC 4346 on the certificateAuthorities field:
172
                // A list of the distinguished names of acceptable certificate
173
                // authorities. These distinguished names may specify a desired
174
                // distinguished name for a root CA or for a subordinate CA;
175
                // thus, this message can be used to describe both known roots
176
                // and a desired authorization space. If the
177
                // certificate_authorities list is empty then the client MAY
178
                // send any certificate of the appropriate
179
                // ClientCertificateType, unless there is some external
180
                // arrangement to the contrary.
181
 
182
                finishedHash.Write(certReq.marshal())
183
 
184
                // For now, we only know how to sign challenges with RSA
185
                rsaAvail := false
186
                for _, certType := range certReq.certificateTypes {
187
                        if certType == certTypeRSASign {
188
                                rsaAvail = true
189
                                break
190
                        }
191
                }
192
 
193
                // We need to search our list of client certs for one
194
                // where SignatureAlgorithm is RSA and the Issuer is in
195
                // certReq.certificateAuthorities
196
        findCert:
197
                for i, cert := range c.config.Certificates {
198
                        if !rsaAvail {
199
                                continue
200
                        }
201
 
202
                        leaf := cert.Leaf
203
                        if leaf == nil {
204
                                if leaf, err = x509.ParseCertificate(cert.Certificate[0]); err != nil {
205
                                        c.sendAlert(alertInternalError)
206
                                        return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
207
                                }
208
                        }
209
 
210
                        if leaf.PublicKeyAlgorithm != x509.RSA {
211
                                continue
212
                        }
213
 
214
                        if len(certReq.certificateAuthorities) == 0 {
215
                                // they gave us an empty list, so just take the
216
                                // first RSA cert from c.config.Certificates
217
                                certToSend = &cert
218
                                break
219
                        }
220
 
221
                        for _, ca := range certReq.certificateAuthorities {
222
                                if bytes.Equal(leaf.RawIssuer, ca) {
223
                                        certToSend = &cert
224
                                        break findCert
225
                                }
226
                        }
227
                }
228
 
229
                msg, err = c.readHandshake()
230
                if err != nil {
231
                        return err
232
                }
233
        }
234
 
235
        shd, ok := msg.(*serverHelloDoneMsg)
236
        if !ok {
237
                return c.sendAlert(alertUnexpectedMessage)
238
        }
239
        finishedHash.Write(shd.marshal())
240
 
241
        if certToSend != nil {
242
                certMsg = new(certificateMsg)
243
                certMsg.certificates = certToSend.Certificate
244
                finishedHash.Write(certMsg.marshal())
245
                c.writeRecord(recordTypeHandshake, certMsg.marshal())
246
        }
247
 
248
        preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hello, certs[0])
249
        if err != nil {
250
                c.sendAlert(alertInternalError)
251
                return err
252
        }
253
        if ckx != nil {
254
                finishedHash.Write(ckx.marshal())
255
                c.writeRecord(recordTypeHandshake, ckx.marshal())
256
        }
257
 
258
        if certToSend != nil {
259
                certVerify := new(certificateVerifyMsg)
260
                digest := make([]byte, 0, 36)
261
                digest = finishedHash.serverMD5.Sum(digest)
262
                digest = finishedHash.serverSHA1.Sum(digest)
263
                signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey.(*rsa.PrivateKey), crypto.MD5SHA1, digest)
264
                if err != nil {
265
                        return c.sendAlert(alertInternalError)
266
                }
267
                certVerify.signature = signed
268
 
269
                finishedHash.Write(certVerify.marshal())
270
                c.writeRecord(recordTypeHandshake, certVerify.marshal())
271
        }
272
 
273
        masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
274
                keysFromPreMasterSecret(c.vers, preMasterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
275
 
276
        clientCipher := suite.cipher(clientKey, clientIV, false /* not for reading */ )
277
        clientHash := suite.mac(c.vers, clientMAC)
278
        c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
279
        c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
280
 
281
        if serverHello.nextProtoNeg {
282
                nextProto := new(nextProtoMsg)
283
                proto, fallback := mutualProtocol(c.config.NextProtos, serverHello.nextProtos)
284
                nextProto.proto = proto
285
                c.clientProtocol = proto
286
                c.clientProtocolFallback = fallback
287
 
288
                finishedHash.Write(nextProto.marshal())
289
                c.writeRecord(recordTypeHandshake, nextProto.marshal())
290
        }
291
 
292
        finished := new(finishedMsg)
293
        finished.verifyData = finishedHash.clientSum(masterSecret)
294
        finishedHash.Write(finished.marshal())
295
        c.writeRecord(recordTypeHandshake, finished.marshal())
296
 
297
        serverCipher := suite.cipher(serverKey, serverIV, true /* for reading */ )
298
        serverHash := suite.mac(c.vers, serverMAC)
299
        c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
300
        c.readRecord(recordTypeChangeCipherSpec)
301
        if c.err != nil {
302
                return c.err
303
        }
304
 
305
        msg, err = c.readHandshake()
306
        if err != nil {
307
                return err
308
        }
309
        serverFinished, ok := msg.(*finishedMsg)
310
        if !ok {
311
                return c.sendAlert(alertUnexpectedMessage)
312
        }
313
 
314
        verify := finishedHash.serverSum(masterSecret)
315
        if len(verify) != len(serverFinished.verifyData) ||
316
                subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
317
                return c.sendAlert(alertHandshakeFailure)
318
        }
319
 
320
        c.handshakeComplete = true
321
        c.cipherSuite = suite.id
322
        return nil
323
}
324
 
325
// mutualProtocol finds the mutual Next Protocol Negotiation protocol given the
326
// set of client and server supported protocols. The set of client supported
327
// protocols must not be empty. It returns the resulting protocol and flag
328
// indicating if the fallback case was reached.
329
func mutualProtocol(clientProtos, serverProtos []string) (string, bool) {
330
        for _, s := range serverProtos {
331
                for _, c := range clientProtos {
332
                        if s == c {
333
                                return s, false
334
                        }
335
                }
336
        }
337
 
338
        return clientProtos[0], true
339
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.