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

Subversion Repositories openrisc

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

Go to most recent revision | 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
        "crypto"
9
        "crypto/rsa"
10
        "crypto/subtle"
11
        "crypto/x509"
12
        "errors"
13
        "io"
14
)
15
 
16
func (c *Conn) serverHandshake() error {
17
        config := c.config
18
        msg, err := c.readHandshake()
19
        if err != nil {
20
                return err
21
        }
22
        clientHello, ok := msg.(*clientHelloMsg)
23
        if !ok {
24
                return c.sendAlert(alertUnexpectedMessage)
25
        }
26
        vers, ok := mutualVersion(clientHello.vers)
27
        if !ok {
28
                return c.sendAlert(alertProtocolVersion)
29
        }
30
        c.vers = vers
31
        c.haveVers = true
32
 
33
        finishedHash := newFinishedHash(vers)
34
        finishedHash.Write(clientHello.marshal())
35
 
36
        hello := new(serverHelloMsg)
37
 
38
        supportedCurve := false
39
Curves:
40
        for _, curve := range clientHello.supportedCurves {
41
                switch curve {
42
                case curveP256, curveP384, curveP521:
43
                        supportedCurve = true
44
                        break Curves
45
                }
46
        }
47
 
48
        supportedPointFormat := false
49
        for _, pointFormat := range clientHello.supportedPoints {
50
                if pointFormat == pointFormatUncompressed {
51
                        supportedPointFormat = true
52
                        break
53
                }
54
        }
55
 
56
        ellipticOk := supportedCurve && supportedPointFormat
57
 
58
        var suite *cipherSuite
59
FindCipherSuite:
60
        for _, id := range clientHello.cipherSuites {
61
                for _, supported := range config.cipherSuites() {
62
                        if id == supported {
63
                                suite = nil
64
                                for _, s := range cipherSuites {
65
                                        if s.id == id {
66
                                                suite = s
67
                                                break
68
                                        }
69
                                }
70
                                if suite == nil {
71
                                        continue
72
                                }
73
                                // Don't select a ciphersuite which we can't
74
                                // support for this client.
75
                                if suite.elliptic && !ellipticOk {
76
                                        continue
77
                                }
78
                                break FindCipherSuite
79
                        }
80
                }
81
        }
82
 
83
        foundCompression := false
84
        // We only support null compression, so check that the client offered it.
85
        for _, compression := range clientHello.compressionMethods {
86
                if compression == compressionNone {
87
                        foundCompression = true
88
                        break
89
                }
90
        }
91
 
92
        if suite == nil || !foundCompression {
93
                return c.sendAlert(alertHandshakeFailure)
94
        }
95
 
96
        hello.vers = vers
97
        hello.cipherSuite = suite.id
98
        t := uint32(config.time().Unix())
99
        hello.random = make([]byte, 32)
100
        hello.random[0] = byte(t >> 24)
101
        hello.random[1] = byte(t >> 16)
102
        hello.random[2] = byte(t >> 8)
103
        hello.random[3] = byte(t)
104
        _, err = io.ReadFull(config.rand(), hello.random[4:])
105
        if err != nil {
106
                return c.sendAlert(alertInternalError)
107
        }
108
        hello.compressionMethod = compressionNone
109
        if clientHello.nextProtoNeg {
110
                hello.nextProtoNeg = true
111
                hello.nextProtos = config.NextProtos
112
        }
113
        if clientHello.ocspStapling && len(config.Certificates[0].OCSPStaple) > 0 {
114
                hello.ocspStapling = true
115
        }
116
 
117
        finishedHash.Write(hello.marshal())
118
        c.writeRecord(recordTypeHandshake, hello.marshal())
119
 
120
        if len(config.Certificates) == 0 {
121
                return c.sendAlert(alertInternalError)
122
        }
123
 
124
        certMsg := new(certificateMsg)
125
        if len(clientHello.serverName) > 0 {
126
                c.serverName = clientHello.serverName
127
                certMsg.certificates = config.getCertificateForName(clientHello.serverName).Certificate
128
        } else {
129
                certMsg.certificates = config.Certificates[0].Certificate
130
        }
131
        finishedHash.Write(certMsg.marshal())
132
        c.writeRecord(recordTypeHandshake, certMsg.marshal())
133
 
134
        if hello.ocspStapling {
135
                certStatus := new(certificateStatusMsg)
136
                certStatus.statusType = statusTypeOCSP
137
                certStatus.response = config.Certificates[0].OCSPStaple
138
                finishedHash.Write(certStatus.marshal())
139
                c.writeRecord(recordTypeHandshake, certStatus.marshal())
140
        }
141
 
142
        keyAgreement := suite.ka()
143
        skx, err := keyAgreement.generateServerKeyExchange(config, clientHello, hello)
144
        if err != nil {
145
                c.sendAlert(alertHandshakeFailure)
146
                return err
147
        }
148
        if skx != nil {
149
                finishedHash.Write(skx.marshal())
150
                c.writeRecord(recordTypeHandshake, skx.marshal())
151
        }
152
 
153
        if config.ClientAuth >= RequestClientCert {
154
                // Request a client certificate
155
                certReq := new(certificateRequestMsg)
156
                certReq.certificateTypes = []byte{certTypeRSASign}
157
 
158
                // An empty list of certificateAuthorities signals to
159
                // the client that it may send any certificate in response
160
                // to our request. When we know the CAs we trust, then
161
                // we can send them down, so that the client can choose
162
                // an appropriate certificate to give to us.
163
                if config.ClientCAs != nil {
164
                        certReq.certificateAuthorities = config.ClientCAs.Subjects()
165
                }
166
                finishedHash.Write(certReq.marshal())
167
                c.writeRecord(recordTypeHandshake, certReq.marshal())
168
        }
169
 
170
        helloDone := new(serverHelloDoneMsg)
171
        finishedHash.Write(helloDone.marshal())
172
        c.writeRecord(recordTypeHandshake, helloDone.marshal())
173
 
174
        var pub *rsa.PublicKey // public key for client auth, if any
175
 
176
        msg, err = c.readHandshake()
177
        if err != nil {
178
                return err
179
        }
180
 
181
        // If we requested a client certificate, then the client must send a
182
        // certificate message, even if it's empty.
183
        if config.ClientAuth >= RequestClientCert {
184
                if certMsg, ok = msg.(*certificateMsg); !ok {
185
                        return c.sendAlert(alertHandshakeFailure)
186
                }
187
                finishedHash.Write(certMsg.marshal())
188
 
189
                if len(certMsg.certificates) == 0 {
190
                        // The client didn't actually send a certificate
191
                        switch config.ClientAuth {
192
                        case RequireAnyClientCert, RequireAndVerifyClientCert:
193
                                c.sendAlert(alertBadCertificate)
194
                                return errors.New("tls: client didn't provide a certificate")
195
                        }
196
                }
197
 
198
                certs := make([]*x509.Certificate, len(certMsg.certificates))
199
                for i, asn1Data := range certMsg.certificates {
200
                        if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
201
                                c.sendAlert(alertBadCertificate)
202
                                return errors.New("tls: failed to parse client certificate: " + err.Error())
203
                        }
204
                }
205
 
206
                if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
207
                        opts := x509.VerifyOptions{
208
                                Roots:         c.config.ClientCAs,
209
                                CurrentTime:   c.config.time(),
210
                                Intermediates: x509.NewCertPool(),
211
                        }
212
 
213
                        for i, cert := range certs {
214
                                if i == 0 {
215
                                        continue
216
                                }
217
                                opts.Intermediates.AddCert(cert)
218
                        }
219
 
220
                        chains, err := certs[0].Verify(opts)
221
                        if err != nil {
222
                                c.sendAlert(alertBadCertificate)
223
                                return errors.New("tls: failed to verify client's certificate: " + err.Error())
224
                        }
225
 
226
                        ok := false
227
                        for _, ku := range certs[0].ExtKeyUsage {
228
                                if ku == x509.ExtKeyUsageClientAuth {
229
                                        ok = true
230
                                        break
231
                                }
232
                        }
233
                        if !ok {
234
                                c.sendAlert(alertHandshakeFailure)
235
                                return errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
236
                        }
237
 
238
                        c.verifiedChains = chains
239
                }
240
 
241
                if len(certs) > 0 {
242
                        if pub, ok = certs[0].PublicKey.(*rsa.PublicKey); !ok {
243
                                return c.sendAlert(alertUnsupportedCertificate)
244
                        }
245
                        c.peerCertificates = certs
246
                }
247
 
248
                msg, err = c.readHandshake()
249
                if err != nil {
250
                        return err
251
                }
252
        }
253
 
254
        // Get client key exchange
255
        ckx, ok := msg.(*clientKeyExchangeMsg)
256
        if !ok {
257
                return c.sendAlert(alertUnexpectedMessage)
258
        }
259
        finishedHash.Write(ckx.marshal())
260
 
261
        // If we received a client cert in response to our certificate request message,
262
        // the client will send us a certificateVerifyMsg immediately after the
263
        // clientKeyExchangeMsg.  This message is a MD5SHA1 digest of all preceding
264
        // handshake-layer messages that is signed using the private key corresponding
265
        // to the client's certificate. This allows us to verify that the client is in
266
        // possession of the private key of the certificate.
267
        if len(c.peerCertificates) > 0 {
268
                msg, err = c.readHandshake()
269
                if err != nil {
270
                        return err
271
                }
272
                certVerify, ok := msg.(*certificateVerifyMsg)
273
                if !ok {
274
                        return c.sendAlert(alertUnexpectedMessage)
275
                }
276
 
277
                digest := make([]byte, 0, 36)
278
                digest = finishedHash.serverMD5.Sum(digest)
279
                digest = finishedHash.serverSHA1.Sum(digest)
280
                err = rsa.VerifyPKCS1v15(pub, crypto.MD5SHA1, digest, certVerify.signature)
281
                if err != nil {
282
                        c.sendAlert(alertBadCertificate)
283
                        return errors.New("could not validate signature of connection nonces: " + err.Error())
284
                }
285
 
286
                finishedHash.Write(certVerify.marshal())
287
        }
288
 
289
        preMasterSecret, err := keyAgreement.processClientKeyExchange(config, ckx, c.vers)
290
        if err != nil {
291
                c.sendAlert(alertHandshakeFailure)
292
                return err
293
        }
294
 
295
        masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
296
                keysFromPreMasterSecret(c.vers, preMasterSecret, clientHello.random, hello.random, suite.macLen, suite.keyLen, suite.ivLen)
297
 
298
        clientCipher := suite.cipher(clientKey, clientIV, true /* for reading */ )
299
        clientHash := suite.mac(c.vers, clientMAC)
300
        c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
301
        c.readRecord(recordTypeChangeCipherSpec)
302
        if err := c.error(); err != nil {
303
                return err
304
        }
305
 
306
        if hello.nextProtoNeg {
307
                msg, err = c.readHandshake()
308
                if err != nil {
309
                        return err
310
                }
311
                nextProto, ok := msg.(*nextProtoMsg)
312
                if !ok {
313
                        return c.sendAlert(alertUnexpectedMessage)
314
                }
315
                finishedHash.Write(nextProto.marshal())
316
                c.clientProtocol = nextProto.proto
317
        }
318
 
319
        msg, err = c.readHandshake()
320
        if err != nil {
321
                return err
322
        }
323
        clientFinished, ok := msg.(*finishedMsg)
324
        if !ok {
325
                return c.sendAlert(alertUnexpectedMessage)
326
        }
327
 
328
        verify := finishedHash.clientSum(masterSecret)
329
        if len(verify) != len(clientFinished.verifyData) ||
330
                subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
331
                return c.sendAlert(alertHandshakeFailure)
332
        }
333
 
334
        finishedHash.Write(clientFinished.marshal())
335
 
336
        serverCipher := suite.cipher(serverKey, serverIV, false /* not for reading */ )
337
        serverHash := suite.mac(c.vers, serverMAC)
338
        c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
339
        c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
340
 
341
        finished := new(finishedMsg)
342
        finished.verifyData = finishedHash.serverSum(masterSecret)
343
        c.writeRecord(recordTypeHandshake, finished.marshal())
344
 
345
        c.handshakeComplete = true
346
        c.cipherSuite = suite.id
347
 
348
        return nil
349
}

powered by: WebSVN 2.1.0

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