github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/crypto/tls/handshake_client.go (about) 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 "bytes" 9 "crypto/ecdsa" 10 "crypto/rsa" 11 "crypto/subtle" 12 "crypto/x509" 13 "encoding/asn1" 14 "errors" 15 "io" 16 "strconv" 17 ) 18 19 func (c *Conn) clientHandshake() error { 20 if c.config == nil { 21 c.config = defaultConfig() 22 } 23 24 hello := &clientHelloMsg{ 25 vers: c.config.maxVersion(), 26 cipherSuites: c.config.cipherSuites(), 27 compressionMethods: []uint8{compressionNone}, 28 random: make([]byte, 32), 29 ocspStapling: true, 30 serverName: c.config.ServerName, 31 supportedCurves: []uint16{curveP256, curveP384, curveP521}, 32 supportedPoints: []uint8{pointFormatUncompressed}, 33 nextProtoNeg: len(c.config.NextProtos) > 0, 34 } 35 36 t := uint32(c.config.time().Unix()) 37 hello.random[0] = byte(t >> 24) 38 hello.random[1] = byte(t >> 16) 39 hello.random[2] = byte(t >> 8) 40 hello.random[3] = byte(t) 41 _, err := io.ReadFull(c.config.rand(), hello.random[4:]) 42 if err != nil { 43 c.sendAlert(alertInternalError) 44 return errors.New("short read from Rand") 45 } 46 47 if hello.vers >= VersionTLS12 { 48 hello.signatureAndHashes = supportedSignatureAlgorithms 49 } 50 51 c.writeRecord(recordTypeHandshake, hello.marshal()) 52 53 msg, err := c.readHandshake() 54 if err != nil { 55 return err 56 } 57 serverHello, ok := msg.(*serverHelloMsg) 58 if !ok { 59 return c.sendAlert(alertUnexpectedMessage) 60 } 61 62 vers, ok := c.config.mutualVersion(serverHello.vers) 63 if !ok || vers < VersionTLS10 { 64 // TLS 1.0 is the minimum version supported as a client. 65 return c.sendAlert(alertProtocolVersion) 66 } 67 c.vers = vers 68 c.haveVers = true 69 70 finishedHash := newFinishedHash(c.vers) 71 finishedHash.Write(hello.marshal()) 72 finishedHash.Write(serverHello.marshal()) 73 74 if serverHello.compressionMethod != compressionNone { 75 return c.sendAlert(alertUnexpectedMessage) 76 } 77 78 if !hello.nextProtoNeg && serverHello.nextProtoNeg { 79 c.sendAlert(alertHandshakeFailure) 80 return errors.New("server advertised unrequested NPN") 81 } 82 83 suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite) 84 if suite == nil { 85 return c.sendAlert(alertHandshakeFailure) 86 } 87 88 msg, err = c.readHandshake() 89 if err != nil { 90 return err 91 } 92 certMsg, ok := msg.(*certificateMsg) 93 if !ok || len(certMsg.certificates) == 0 { 94 return c.sendAlert(alertUnexpectedMessage) 95 } 96 finishedHash.Write(certMsg.marshal()) 97 98 certs := make([]*x509.Certificate, len(certMsg.certificates)) 99 for i, asn1Data := range certMsg.certificates { 100 cert, err := x509.ParseCertificate(asn1Data) 101 if err != nil { 102 c.sendAlert(alertBadCertificate) 103 return errors.New("failed to parse certificate from server: " + err.Error()) 104 } 105 certs[i] = cert 106 } 107 108 if !c.config.InsecureSkipVerify { 109 opts := x509.VerifyOptions{ 110 Roots: c.config.RootCAs, 111 CurrentTime: c.config.time(), 112 DNSName: c.config.ServerName, 113 Intermediates: x509.NewCertPool(), 114 } 115 116 for i, cert := range certs { 117 if i == 0 { 118 continue 119 } 120 opts.Intermediates.AddCert(cert) 121 } 122 c.verifiedChains, err = certs[0].Verify(opts) 123 if err != nil { 124 c.sendAlert(alertBadCertificate) 125 return err 126 } 127 } 128 129 switch certs[0].PublicKey.(type) { 130 case *rsa.PublicKey, *ecdsa.PublicKey: 131 break 132 default: 133 return c.sendAlert(alertUnsupportedCertificate) 134 } 135 136 c.peerCertificates = certs 137 138 if serverHello.ocspStapling { 139 msg, err = c.readHandshake() 140 if err != nil { 141 return err 142 } 143 cs, ok := msg.(*certificateStatusMsg) 144 if !ok { 145 return c.sendAlert(alertUnexpectedMessage) 146 } 147 finishedHash.Write(cs.marshal()) 148 149 if cs.statusType == statusTypeOCSP { 150 c.ocspResponse = cs.response 151 } 152 } 153 154 msg, err = c.readHandshake() 155 if err != nil { 156 return err 157 } 158 159 keyAgreement := suite.ka(c.vers) 160 161 skx, ok := msg.(*serverKeyExchangeMsg) 162 if ok { 163 finishedHash.Write(skx.marshal()) 164 err = keyAgreement.processServerKeyExchange(c.config, hello, serverHello, certs[0], skx) 165 if err != nil { 166 c.sendAlert(alertUnexpectedMessage) 167 return err 168 } 169 170 msg, err = c.readHandshake() 171 if err != nil { 172 return err 173 } 174 } 175 176 var chainToSend *Certificate 177 var certRequested bool 178 certReq, ok := msg.(*certificateRequestMsg) 179 if ok { 180 certRequested = true 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; 186 // thus, this message can be used to describe both known roots 187 // and a desired authorization space. If the 188 // certificate_authorities list is empty then the client MAY 189 // send any certificate of the appropriate 190 // ClientCertificateType, unless there is some external 191 // arrangement to the contrary. 192 193 finishedHash.Write(certReq.marshal()) 194 195 var rsaAvail, ecdsaAvail bool 196 for _, certType := range certReq.certificateTypes { 197 switch certType { 198 case certTypeRSASign: 199 rsaAvail = true 200 case certTypeECDSASign: 201 ecdsaAvail = true 202 } 203 } 204 205 // We need to search our list of client certs for one 206 // where SignatureAlgorithm is RSA and the Issuer is in 207 // certReq.certificateAuthorities 208 findCert: 209 for i, chain := range c.config.Certificates { 210 if !rsaAvail && !ecdsaAvail { 211 continue 212 } 213 214 for j, cert := range chain.Certificate { 215 x509Cert := chain.Leaf 216 // parse the certificate if this isn't the leaf 217 // node, or if chain.Leaf was nil 218 if j != 0 || x509Cert == nil { 219 if x509Cert, err = x509.ParseCertificate(cert); err != nil { 220 c.sendAlert(alertInternalError) 221 return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error()) 222 } 223 } 224 225 switch { 226 case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA: 227 case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA: 228 default: 229 continue findCert 230 } 231 232 if len(certReq.certificateAuthorities) == 0 { 233 // they gave us an empty list, so just take the 234 // first RSA cert from c.config.Certificates 235 chainToSend = &chain 236 break findCert 237 } 238 239 for _, ca := range certReq.certificateAuthorities { 240 if bytes.Equal(x509Cert.RawIssuer, ca) { 241 chainToSend = &chain 242 break findCert 243 } 244 } 245 } 246 } 247 248 msg, err = c.readHandshake() 249 if err != nil { 250 return err 251 } 252 } 253 254 shd, ok := msg.(*serverHelloDoneMsg) 255 if !ok { 256 return c.sendAlert(alertUnexpectedMessage) 257 } 258 finishedHash.Write(shd.marshal()) 259 260 // If the server requested a certificate then we have to send a 261 // Certificate message, even if it's empty because we don't have a 262 // certificate to send. 263 if certRequested { 264 certMsg = new(certificateMsg) 265 if chainToSend != nil { 266 certMsg.certificates = chainToSend.Certificate 267 } 268 finishedHash.Write(certMsg.marshal()) 269 c.writeRecord(recordTypeHandshake, certMsg.marshal()) 270 } 271 272 preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hello, certs[0]) 273 if err != nil { 274 c.sendAlert(alertInternalError) 275 return err 276 } 277 if ckx != nil { 278 finishedHash.Write(ckx.marshal()) 279 c.writeRecord(recordTypeHandshake, ckx.marshal()) 280 } 281 282 if chainToSend != nil { 283 var signed []byte 284 certVerify := new(certificateVerifyMsg) 285 switch key := c.config.Certificates[0].PrivateKey.(type) { 286 case *ecdsa.PrivateKey: 287 digest, _ := finishedHash.hashForClientCertificate(signatureECDSA) 288 r, s, err := ecdsa.Sign(c.config.rand(), key, digest) 289 if err == nil { 290 signed, err = asn1.Marshal(ecdsaSignature{r, s}) 291 } 292 case *rsa.PrivateKey: 293 digest, hashFunc := finishedHash.hashForClientCertificate(signatureRSA) 294 signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest) 295 default: 296 err = errors.New("unknown private key type") 297 } 298 if err != nil { 299 return c.sendAlert(alertInternalError) 300 } 301 certVerify.signature = signed 302 303 finishedHash.Write(certVerify.marshal()) 304 c.writeRecord(recordTypeHandshake, certVerify.marshal()) 305 } 306 307 masterSecret := masterFromPreMasterSecret(c.vers, preMasterSecret, hello.random, serverHello.random) 308 clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := 309 keysFromMasterSecret(c.vers, masterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen) 310 311 var clientCipher interface{} 312 var clientHash macFunction 313 if suite.cipher != nil { 314 clientCipher = suite.cipher(clientKey, clientIV, false /* not for reading */) 315 clientHash = suite.mac(c.vers, clientMAC) 316 } else { 317 clientCipher = suite.aead(clientKey, clientIV) 318 } 319 c.out.prepareCipherSpec(c.vers, clientCipher, clientHash) 320 c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) 321 322 if serverHello.nextProtoNeg { 323 nextProto := new(nextProtoMsg) 324 proto, fallback := mutualProtocol(c.config.NextProtos, serverHello.nextProtos) 325 nextProto.proto = proto 326 c.clientProtocol = proto 327 c.clientProtocolFallback = fallback 328 329 finishedHash.Write(nextProto.marshal()) 330 c.writeRecord(recordTypeHandshake, nextProto.marshal()) 331 } 332 333 finished := new(finishedMsg) 334 finished.verifyData = finishedHash.clientSum(masterSecret) 335 finishedHash.Write(finished.marshal()) 336 c.writeRecord(recordTypeHandshake, finished.marshal()) 337 338 var serverCipher interface{} 339 var serverHash macFunction 340 if suite.cipher != nil { 341 serverCipher = suite.cipher(serverKey, serverIV, true /* for reading */) 342 serverHash = suite.mac(c.vers, serverMAC) 343 } else { 344 serverCipher = suite.aead(serverKey, serverIV) 345 } 346 c.in.prepareCipherSpec(c.vers, serverCipher, serverHash) 347 c.readRecord(recordTypeChangeCipherSpec) 348 if err := c.error(); err != nil { 349 return err 350 } 351 352 msg, err = c.readHandshake() 353 if err != nil { 354 return err 355 } 356 serverFinished, ok := msg.(*finishedMsg) 357 if !ok { 358 return c.sendAlert(alertUnexpectedMessage) 359 } 360 361 verify := finishedHash.serverSum(masterSecret) 362 if len(verify) != len(serverFinished.verifyData) || 363 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 { 364 return c.sendAlert(alertHandshakeFailure) 365 } 366 367 c.handshakeComplete = true 368 c.cipherSuite = suite.id 369 return nil 370 } 371 372 // mutualProtocol finds the mutual Next Protocol Negotiation protocol given the 373 // set of client and server supported protocols. The set of client supported 374 // protocols must not be empty. It returns the resulting protocol and flag 375 // indicating if the fallback case was reached. 376 func mutualProtocol(clientProtos, serverProtos []string) (string, bool) { 377 for _, s := range serverProtos { 378 for _, c := range clientProtos { 379 if s == c { 380 return s, false 381 } 382 } 383 } 384 385 return clientProtos[0], true 386 }