blob: 809c8c15e5df19a2db9e3d4387c11c9bc1b39859 [file] [log] [blame]
Adam Langley5e598c52009-11-05 15:44:32 -08001// 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
5package tls
6
Adam Langley5e598c52009-11-05 15:44:32 -08007import (
Adam Langleye308d552011-02-01 11:02:48 -05008 "crypto"
Robert Griesemer5a1d3322009-12-15 15:33:31 -08009 "crypto/rsa"
Robert Griesemer5a1d3322009-12-15 15:33:31 -080010 "crypto/subtle"
Mikkel Krautzc47123d2010-08-16 11:22:22 -040011 "crypto/x509"
Robert Griesemer5a1d3322009-12-15 15:33:31 -080012 "io"
Russ Cox72d93222010-04-26 22:19:04 -070013 "os"
Adam Langley5e598c52009-11-05 15:44:32 -080014)
15
Russ Cox72d93222010-04-26 22:19:04 -070016func (c *Conn) serverHandshake() os.Error {
17 config := c.config
18 msg, err := c.readHandshake()
19 if err != nil {
20 return err
Adam Langley5e598c52009-11-05 15:44:32 -080021 }
Russ Cox72d93222010-04-26 22:19:04 -070022 clientHello, ok := msg.(*clientHelloMsg)
Adam Langley5e598c52009-11-05 15:44:32 -080023 if !ok {
Russ Cox72d93222010-04-26 22:19:04 -070024 return c.sendAlert(alertUnexpectedMessage)
Adam Langley5e598c52009-11-05 15:44:32 -080025 }
Russ Cox72d93222010-04-26 22:19:04 -070026 vers, ok := mutualVersion(clientHello.vers)
27 if !ok {
28 return c.sendAlert(alertProtocolVersion)
29 }
30 c.vers = vers
31 c.haveVers = true
Adam Langley5e598c52009-11-05 15:44:32 -080032
Robert Griesemer5a1d3322009-12-15 15:33:31 -080033 finishedHash := newFinishedHash()
34 finishedHash.Write(clientHello.marshal())
Adam Langley5e598c52009-11-05 15:44:32 -080035
Robert Griesemer5a1d3322009-12-15 15:33:31 -080036 hello := new(serverHelloMsg)
Adam Langley5e598c52009-11-05 15:44:32 -080037
Adam Langley4883b732010-12-16 17:10:50 -050038 supportedCurve := false
39Curves:
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
Robert Griesemer5a1d3322009-12-15 15:33:31 -080058 var suite *cipherSuite
Adam Langleyeedf5c42010-12-15 11:49:55 -050059 var suiteId uint16
Adam Langleyab2aca52011-02-05 13:56:36 -050060FindCipherSuite:
Adam Langley5e598c52009-11-05 15:44:32 -080061 for _, id := range clientHello.cipherSuites {
Adam Langleyeedf5c42010-12-15 11:49:55 -050062 for _, supported := range config.cipherSuites() {
63 if id == supported {
64 suite = cipherSuites[id]
Adam Langley4883b732010-12-16 17:10:50 -050065 // Don't select a ciphersuite which we can't
66 // support for this client.
67 if suite.elliptic && !ellipticOk {
68 continue
69 }
Adam Langleyeedf5c42010-12-15 11:49:55 -050070 suiteId = id
Adam Langleyab2aca52011-02-05 13:56:36 -050071 break FindCipherSuite
Adam Langley5e598c52009-11-05 15:44:32 -080072 }
73 }
74 }
75
Robert Griesemer5a1d3322009-12-15 15:33:31 -080076 foundCompression := false
Adam Langley5e598c52009-11-05 15:44:32 -080077 // We only support null compression, so check that the client offered it.
78 for _, compression := range clientHello.compressionMethods {
79 if compression == compressionNone {
Robert Griesemer5a1d3322009-12-15 15:33:31 -080080 foundCompression = true
81 break
Adam Langley5e598c52009-11-05 15:44:32 -080082 }
83 }
84
85 if suite == nil || !foundCompression {
Russ Cox72d93222010-04-26 22:19:04 -070086 return c.sendAlert(alertHandshakeFailure)
Adam Langley5e598c52009-11-05 15:44:32 -080087 }
88
Russ Cox72d93222010-04-26 22:19:04 -070089 hello.vers = vers
Adam Langleyeedf5c42010-12-15 11:49:55 -050090 hello.cipherSuite = suiteId
Russ Coxb15c4242010-12-07 16:15:15 -050091 t := uint32(config.time())
Robert Griesemer5a1d3322009-12-15 15:33:31 -080092 hello.random = make([]byte, 32)
Russ Cox72d93222010-04-26 22:19:04 -070093 hello.random[0] = byte(t >> 24)
94 hello.random[1] = byte(t >> 16)
95 hello.random[2] = byte(t >> 8)
96 hello.random[3] = byte(t)
Russ Coxb15c4242010-12-07 16:15:15 -050097 _, err = io.ReadFull(config.rand(), hello.random[4:])
Adam Langley5e598c52009-11-05 15:44:32 -080098 if err != nil {
Russ Cox72d93222010-04-26 22:19:04 -070099 return c.sendAlert(alertInternalError)
Adam Langley5e598c52009-11-05 15:44:32 -0800100 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800101 hello.compressionMethod = compressionNone
Adam Langley9ebb5962009-12-23 11:13:09 -0800102 if clientHello.nextProtoNeg {
103 hello.nextProtoNeg = true
104 hello.nextProtos = config.NextProtos
105 }
Adam Langley5e598c52009-11-05 15:44:32 -0800106
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800107 finishedHash.Write(hello.marshal())
Russ Cox72d93222010-04-26 22:19:04 -0700108 c.writeRecord(recordTypeHandshake, hello.marshal())
Adam Langley5e598c52009-11-05 15:44:32 -0800109
110 if len(config.Certificates) == 0 {
Russ Cox72d93222010-04-26 22:19:04 -0700111 return c.sendAlert(alertInternalError)
Adam Langley5e598c52009-11-05 15:44:32 -0800112 }
113
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800114 certMsg := new(certificateMsg)
115 certMsg.certificates = config.Certificates[0].Certificate
116 finishedHash.Write(certMsg.marshal())
Russ Cox72d93222010-04-26 22:19:04 -0700117 c.writeRecord(recordTypeHandshake, certMsg.marshal())
Adam Langley5e598c52009-11-05 15:44:32 -0800118
Adam Langley4883b732010-12-16 17:10:50 -0500119 keyAgreement := suite.ka()
120
121 skx, err := keyAgreement.generateServerKeyExchange(config, clientHello, hello)
122 if err != nil {
123 c.sendAlert(alertHandshakeFailure)
124 return err
125 }
126 if skx != nil {
127 finishedHash.Write(skx.marshal())
128 c.writeRecord(recordTypeHandshake, skx.marshal())
129 }
130
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400131 if config.AuthenticateClient {
132 // Request a client certificate
133 certReq := new(certificateRequestMsg)
134 certReq.certificateTypes = []byte{certTypeRSASign}
135 // An empty list of certificateAuthorities signals to
136 // the client that it may send any certificate in response
137 // to our request.
138
139 finishedHash.Write(certReq.marshal())
140 c.writeRecord(recordTypeHandshake, certReq.marshal())
141 }
142
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800143 helloDone := new(serverHelloDoneMsg)
144 finishedHash.Write(helloDone.marshal())
Russ Cox72d93222010-04-26 22:19:04 -0700145 c.writeRecord(recordTypeHandshake, helloDone.marshal())
Adam Langley5e598c52009-11-05 15:44:32 -0800146
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400147 var pub *rsa.PublicKey
148 if config.AuthenticateClient {
149 // Get client certificate
150 msg, err = c.readHandshake()
151 if err != nil {
152 return err
153 }
154 certMsg, ok = msg.(*certificateMsg)
155 if !ok {
156 return c.sendAlert(alertUnexpectedMessage)
157 }
158 finishedHash.Write(certMsg.marshal())
159
160 certs := make([]*x509.Certificate, len(certMsg.certificates))
161 for i, asn1Data := range certMsg.certificates {
162 cert, err := x509.ParseCertificate(asn1Data)
163 if err != nil {
Adam Langleyf6e2eab2010-10-11 10:39:56 -0400164 c.sendAlert(alertBadCertificate)
165 return os.ErrorString("could not parse client's certificate: " + err.String())
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400166 }
167 certs[i] = cert
168 }
169
170 // TODO(agl): do better validation of certs: max path length, name restrictions etc.
171 for i := 1; i < len(certs); i++ {
172 if err := certs[i-1].CheckSignatureFrom(certs[i]); err != nil {
Adam Langleyf6e2eab2010-10-11 10:39:56 -0400173 c.sendAlert(alertBadCertificate)
174 return os.ErrorString("could not validate certificate signature: " + err.String())
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400175 }
176 }
177
178 if len(certs) > 0 {
179 key, ok := certs[0].PublicKey.(*rsa.PublicKey)
180 if !ok {
181 return c.sendAlert(alertUnsupportedCertificate)
182 }
183 pub = key
184 c.peerCertificates = certs
185 }
186 }
187
188 // Get client key exchange
Russ Cox72d93222010-04-26 22:19:04 -0700189 msg, err = c.readHandshake()
190 if err != nil {
191 return err
192 }
193 ckx, ok := msg.(*clientKeyExchangeMsg)
Adam Langley5e598c52009-11-05 15:44:32 -0800194 if !ok {
Russ Cox72d93222010-04-26 22:19:04 -0700195 return c.sendAlert(alertUnexpectedMessage)
Adam Langley5e598c52009-11-05 15:44:32 -0800196 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800197 finishedHash.Write(ckx.marshal())
Adam Langley5e598c52009-11-05 15:44:32 -0800198
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400199 // If we received a client cert in response to our certificate request message,
200 // the client will send us a certificateVerifyMsg immediately after the
201 // clientKeyExchangeMsg. This message is a MD5SHA1 digest of all preceeding
202 // handshake-layer messages that is signed using the private key corresponding
203 // to the client's certificate. This allows us to verify that the client is in
204 // posession of the private key of the certificate.
205 if len(c.peerCertificates) > 0 {
206 msg, err = c.readHandshake()
207 if err != nil {
208 return err
209 }
210 certVerify, ok := msg.(*certificateVerifyMsg)
211 if !ok {
212 return c.sendAlert(alertUnexpectedMessage)
213 }
214
215 digest := make([]byte, 36)
216 copy(digest[0:16], finishedHash.serverMD5.Sum())
217 copy(digest[16:36], finishedHash.serverSHA1.Sum())
Adam Langleye308d552011-02-01 11:02:48 -0500218 err = rsa.VerifyPKCS1v15(pub, crypto.MD5SHA1, digest, certVerify.signature)
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400219 if err != nil {
Adam Langleyf6e2eab2010-10-11 10:39:56 -0400220 c.sendAlert(alertBadCertificate)
221 return os.ErrorString("could not validate signature of connection nonces: " + err.String())
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400222 }
223
224 finishedHash.Write(certVerify.marshal())
225 }
226
Adam Langley4883b732010-12-16 17:10:50 -0500227 preMasterSecret, err := keyAgreement.processClientKeyExchange(config, ckx)
Adam Langley5e598c52009-11-05 15:44:32 -0800228 if err != nil {
Adam Langley4883b732010-12-16 17:10:50 -0500229 c.sendAlert(alertHandshakeFailure)
230 return err
Adam Langley5e598c52009-11-05 15:44:32 -0800231 }
232
Adam Langleyeedf5c42010-12-15 11:49:55 -0500233 masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
234 keysFromPreMasterSecret10(preMasterSecret, clientHello.random, hello.random, suite.macLen, suite.keyLen, suite.ivLen)
Adam Langley5e598c52009-11-05 15:44:32 -0800235
Adam Langleyeedf5c42010-12-15 11:49:55 -0500236 clientCipher := suite.cipher(clientKey, clientIV, true /* for reading */ )
237 clientHash := suite.mac(clientMAC)
238 c.in.prepareCipherSpec(clientCipher, clientHash)
Russ Cox72d93222010-04-26 22:19:04 -0700239 c.readRecord(recordTypeChangeCipherSpec)
240 if err := c.error(); err != nil {
241 return err
Adam Langley5e598c52009-11-05 15:44:32 -0800242 }
243
Adam Langley9ebb5962009-12-23 11:13:09 -0800244 if hello.nextProtoNeg {
Russ Cox72d93222010-04-26 22:19:04 -0700245 msg, err = c.readHandshake()
246 if err != nil {
247 return err
248 }
249 nextProto, ok := msg.(*nextProtoMsg)
Adam Langley9ebb5962009-12-23 11:13:09 -0800250 if !ok {
Russ Cox72d93222010-04-26 22:19:04 -0700251 return c.sendAlert(alertUnexpectedMessage)
Adam Langley9ebb5962009-12-23 11:13:09 -0800252 }
253 finishedHash.Write(nextProto.marshal())
Russ Cox72d93222010-04-26 22:19:04 -0700254 c.clientProtocol = nextProto.proto
Adam Langley9ebb5962009-12-23 11:13:09 -0800255 }
256
Russ Cox72d93222010-04-26 22:19:04 -0700257 msg, err = c.readHandshake()
258 if err != nil {
259 return err
260 }
261 clientFinished, ok := msg.(*finishedMsg)
Adam Langley5e598c52009-11-05 15:44:32 -0800262 if !ok {
Russ Cox72d93222010-04-26 22:19:04 -0700263 return c.sendAlert(alertUnexpectedMessage)
Adam Langley5e598c52009-11-05 15:44:32 -0800264 }
265
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800266 verify := finishedHash.clientSum(masterSecret)
Adam Langley5e598c52009-11-05 15:44:32 -0800267 if len(verify) != len(clientFinished.verifyData) ||
268 subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
Russ Cox72d93222010-04-26 22:19:04 -0700269 return c.sendAlert(alertHandshakeFailure)
Adam Langley5e598c52009-11-05 15:44:32 -0800270 }
271
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800272 finishedHash.Write(clientFinished.marshal())
Adam Langley5e598c52009-11-05 15:44:32 -0800273
Adam Langleyeedf5c42010-12-15 11:49:55 -0500274 serverCipher := suite.cipher(serverKey, serverIV, false /* not for reading */ )
275 serverHash := suite.mac(serverMAC)
276 c.out.prepareCipherSpec(serverCipher, serverHash)
Russ Cox72d93222010-04-26 22:19:04 -0700277 c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
Adam Langley5e598c52009-11-05 15:44:32 -0800278
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800279 finished := new(finishedMsg)
280 finished.verifyData = finishedHash.serverSum(masterSecret)
Russ Cox72d93222010-04-26 22:19:04 -0700281 c.writeRecord(recordTypeHandshake, finished.marshal())
Adam Langley5e598c52009-11-05 15:44:32 -0800282
Russ Cox72d93222010-04-26 22:19:04 -0700283 c.handshakeComplete = true
Adam Langleyeedf5c42010-12-15 11:49:55 -0500284 c.cipherSuite = suiteId
Adam Langley5e598c52009-11-05 15:44:32 -0800285
Russ Cox72d93222010-04-26 22:19:04 -0700286 return nil
Adam Langley5e598c52009-11-05 15:44:32 -0800287}