github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/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 "fmt" 16 "io" 17 "net" 18 "strconv" 19 ) 20 21 type clientHandshakeState struct { 22 c *Conn 23 serverHello *serverHelloMsg 24 hello *clientHelloMsg 25 suite *cipherSuite 26 finishedHash finishedHash 27 masterSecret []byte 28 session *ClientSessionState 29 } 30 31 func (c *Conn) clientHandshake() error { 32 if c.config == nil { 33 c.config = defaultConfig() 34 } 35 36 if len(c.config.ServerName) == 0 && !c.config.InsecureSkipVerify { 37 return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config") 38 } 39 40 hello := &clientHelloMsg{ 41 vers: c.config.maxVersion(), 42 compressionMethods: []uint8{compressionNone}, 43 random: make([]byte, 32), 44 ocspStapling: true, 45 serverName: c.config.ServerName, 46 supportedCurves: c.config.curvePreferences(), 47 supportedPoints: []uint8{pointFormatUncompressed}, 48 nextProtoNeg: len(c.config.NextProtos) > 0, 49 secureRenegotiation: true, 50 } 51 52 possibleCipherSuites := c.config.cipherSuites() 53 hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites)) 54 55 NextCipherSuite: 56 for _, suiteId := range possibleCipherSuites { 57 for _, suite := range cipherSuites { 58 if suite.id != suiteId { 59 continue 60 } 61 // Don't advertise TLS 1.2-only cipher suites unless 62 // we're attempting TLS 1.2. 63 if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 { 64 continue 65 } 66 hello.cipherSuites = append(hello.cipherSuites, suiteId) 67 continue NextCipherSuite 68 } 69 } 70 71 _, err := io.ReadFull(c.config.rand(), hello.random) 72 if err != nil { 73 c.sendAlert(alertInternalError) 74 return errors.New("tls: short read from Rand: " + err.Error()) 75 } 76 77 if hello.vers >= VersionTLS12 { 78 hello.signatureAndHashes = supportedSKXSignatureAlgorithms 79 } 80 81 var session *ClientSessionState 82 var cacheKey string 83 sessionCache := c.config.ClientSessionCache 84 if c.config.SessionTicketsDisabled { 85 sessionCache = nil 86 } 87 88 if sessionCache != nil { 89 hello.ticketSupported = true 90 91 // Try to resume a previously negotiated TLS session, if 92 // available. 93 cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config) 94 candidateSession, ok := sessionCache.Get(cacheKey) 95 if ok { 96 // Check that the ciphersuite/version used for the 97 // previous session are still valid. 98 cipherSuiteOk := false 99 for _, id := range hello.cipherSuites { 100 if id == candidateSession.cipherSuite { 101 cipherSuiteOk = true 102 break 103 } 104 } 105 106 versOk := candidateSession.vers >= c.config.minVersion() && 107 candidateSession.vers <= c.config.maxVersion() 108 if versOk && cipherSuiteOk { 109 session = candidateSession 110 } 111 } 112 } 113 114 if session != nil { 115 hello.sessionTicket = session.sessionTicket 116 // A random session ID is used to detect when the 117 // server accepted the ticket and is resuming a session 118 // (see RFC 5077). 119 hello.sessionId = make([]byte, 16) 120 if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil { 121 c.sendAlert(alertInternalError) 122 return errors.New("tls: short read from Rand: " + err.Error()) 123 } 124 } 125 126 c.writeRecord(recordTypeHandshake, hello.marshal()) 127 128 msg, err := c.readHandshake() 129 if err != nil { 130 return err 131 } 132 serverHello, ok := msg.(*serverHelloMsg) 133 if !ok { 134 c.sendAlert(alertUnexpectedMessage) 135 return unexpectedMessageError(serverHello, msg) 136 } 137 138 vers, ok := c.config.mutualVersion(serverHello.vers) 139 if !ok || vers < VersionTLS10 { 140 // TLS 1.0 is the minimum version supported as a client. 141 c.sendAlert(alertProtocolVersion) 142 return fmt.Errorf("tls: server selected unsupported protocol version %x", serverHello.vers) 143 } 144 c.vers = vers 145 c.haveVers = true 146 147 suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite) 148 if suite == nil { 149 c.sendAlert(alertHandshakeFailure) 150 return fmt.Errorf("tls: server selected an unsupported cipher suite") 151 } 152 153 hs := &clientHandshakeState{ 154 c: c, 155 serverHello: serverHello, 156 hello: hello, 157 suite: suite, 158 finishedHash: newFinishedHash(c.vers), 159 session: session, 160 } 161 162 hs.finishedHash.Write(hs.hello.marshal()) 163 hs.finishedHash.Write(hs.serverHello.marshal()) 164 165 isResume, err := hs.processServerHello() 166 if err != nil { 167 return err 168 } 169 170 if isResume { 171 if err := hs.establishKeys(); err != nil { 172 return err 173 } 174 if err := hs.readSessionTicket(); err != nil { 175 return err 176 } 177 if err := hs.readFinished(); err != nil { 178 return err 179 } 180 if err := hs.sendFinished(); err != nil { 181 return err 182 } 183 } else { 184 if err := hs.doFullHandshake(); err != nil { 185 return err 186 } 187 if err := hs.establishKeys(); err != nil { 188 return err 189 } 190 if err := hs.sendFinished(); err != nil { 191 return err 192 } 193 if err := hs.readSessionTicket(); err != nil { 194 return err 195 } 196 if err := hs.readFinished(); err != nil { 197 return err 198 } 199 } 200 201 if sessionCache != nil && hs.session != nil && session != hs.session { 202 sessionCache.Put(cacheKey, hs.session) 203 } 204 205 c.didResume = isResume 206 c.handshakeComplete = true 207 c.cipherSuite = suite.id 208 return nil 209 } 210 211 func (hs *clientHandshakeState) doFullHandshake() error { 212 c := hs.c 213 214 msg, err := c.readHandshake() 215 if err != nil { 216 return err 217 } 218 certMsg, ok := msg.(*certificateMsg) 219 if !ok || len(certMsg.certificates) == 0 { 220 c.sendAlert(alertUnexpectedMessage) 221 return unexpectedMessageError(certMsg, msg) 222 } 223 hs.finishedHash.Write(certMsg.marshal()) 224 225 certs := make([]*x509.Certificate, len(certMsg.certificates)) 226 for i, asn1Data := range certMsg.certificates { 227 cert, err := x509.ParseCertificate(asn1Data) 228 if err != nil { 229 c.sendAlert(alertBadCertificate) 230 return errors.New("tls: failed to parse certificate from server: " + err.Error()) 231 } 232 certs[i] = cert 233 } 234 235 if !c.config.InsecureSkipVerify { 236 opts := x509.VerifyOptions{ 237 Roots: c.config.RootCAs, 238 CurrentTime: c.config.time(), 239 DNSName: c.config.ServerName, 240 Intermediates: x509.NewCertPool(), 241 } 242 243 for i, cert := range certs { 244 if i == 0 { 245 continue 246 } 247 opts.Intermediates.AddCert(cert) 248 } 249 c.verifiedChains, err = certs[0].Verify(opts) 250 if err != nil { 251 c.sendAlert(alertBadCertificate) 252 return err 253 } 254 } 255 256 switch certs[0].PublicKey.(type) { 257 case *rsa.PublicKey, *ecdsa.PublicKey: 258 break 259 default: 260 c.sendAlert(alertUnsupportedCertificate) 261 return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey) 262 } 263 264 c.peerCertificates = certs 265 266 if hs.serverHello.ocspStapling { 267 msg, err = c.readHandshake() 268 if err != nil { 269 return err 270 } 271 cs, ok := msg.(*certificateStatusMsg) 272 if !ok { 273 c.sendAlert(alertUnexpectedMessage) 274 return unexpectedMessageError(cs, msg) 275 } 276 hs.finishedHash.Write(cs.marshal()) 277 278 if cs.statusType == statusTypeOCSP { 279 c.ocspResponse = cs.response 280 } 281 } 282 283 msg, err = c.readHandshake() 284 if err != nil { 285 return err 286 } 287 288 keyAgreement := hs.suite.ka(c.vers) 289 290 skx, ok := msg.(*serverKeyExchangeMsg) 291 if ok { 292 hs.finishedHash.Write(skx.marshal()) 293 err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, certs[0], skx) 294 if err != nil { 295 c.sendAlert(alertUnexpectedMessage) 296 return err 297 } 298 299 msg, err = c.readHandshake() 300 if err != nil { 301 return err 302 } 303 } 304 305 var chainToSend *Certificate 306 var certRequested bool 307 certReq, ok := msg.(*certificateRequestMsg) 308 if ok { 309 certRequested = true 310 311 // RFC 4346 on the certificateAuthorities field: 312 // A list of the distinguished names of acceptable certificate 313 // authorities. These distinguished names may specify a desired 314 // distinguished name for a root CA or for a subordinate CA; 315 // thus, this message can be used to describe both known roots 316 // and a desired authorization space. If the 317 // certificate_authorities list is empty then the client MAY 318 // send any certificate of the appropriate 319 // ClientCertificateType, unless there is some external 320 // arrangement to the contrary. 321 322 hs.finishedHash.Write(certReq.marshal()) 323 324 var rsaAvail, ecdsaAvail bool 325 for _, certType := range certReq.certificateTypes { 326 switch certType { 327 case certTypeRSASign: 328 rsaAvail = true 329 case certTypeECDSASign: 330 ecdsaAvail = true 331 } 332 } 333 334 // We need to search our list of client certs for one 335 // where SignatureAlgorithm is RSA and the Issuer is in 336 // certReq.certificateAuthorities 337 findCert: 338 for i, chain := range c.config.Certificates { 339 if !rsaAvail && !ecdsaAvail { 340 continue 341 } 342 343 for j, cert := range chain.Certificate { 344 x509Cert := chain.Leaf 345 // parse the certificate if this isn't the leaf 346 // node, or if chain.Leaf was nil 347 if j != 0 || x509Cert == nil { 348 if x509Cert, err = x509.ParseCertificate(cert); err != nil { 349 c.sendAlert(alertInternalError) 350 return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error()) 351 } 352 } 353 354 switch { 355 case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA: 356 case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA: 357 default: 358 continue findCert 359 } 360 361 if len(certReq.certificateAuthorities) == 0 { 362 // they gave us an empty list, so just take the 363 // first RSA cert from c.config.Certificates 364 chainToSend = &chain 365 break findCert 366 } 367 368 for _, ca := range certReq.certificateAuthorities { 369 if bytes.Equal(x509Cert.RawIssuer, ca) { 370 chainToSend = &chain 371 break findCert 372 } 373 } 374 } 375 } 376 377 msg, err = c.readHandshake() 378 if err != nil { 379 return err 380 } 381 } 382 383 shd, ok := msg.(*serverHelloDoneMsg) 384 if !ok { 385 c.sendAlert(alertUnexpectedMessage) 386 return unexpectedMessageError(shd, msg) 387 } 388 hs.finishedHash.Write(shd.marshal()) 389 390 // If the server requested a certificate then we have to send a 391 // Certificate message, even if it's empty because we don't have a 392 // certificate to send. 393 if certRequested { 394 certMsg = new(certificateMsg) 395 if chainToSend != nil { 396 certMsg.certificates = chainToSend.Certificate 397 } 398 hs.finishedHash.Write(certMsg.marshal()) 399 c.writeRecord(recordTypeHandshake, certMsg.marshal()) 400 } 401 402 preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, certs[0]) 403 if err != nil { 404 c.sendAlert(alertInternalError) 405 return err 406 } 407 if ckx != nil { 408 hs.finishedHash.Write(ckx.marshal()) 409 c.writeRecord(recordTypeHandshake, ckx.marshal()) 410 } 411 412 if chainToSend != nil { 413 var signed []byte 414 certVerify := &certificateVerifyMsg{ 415 hasSignatureAndHash: c.vers >= VersionTLS12, 416 } 417 418 switch key := c.config.Certificates[0].PrivateKey.(type) { 419 case *ecdsa.PrivateKey: 420 digest, _, hashId := hs.finishedHash.hashForClientCertificate(signatureECDSA) 421 r, s, err := ecdsa.Sign(c.config.rand(), key, digest) 422 if err == nil { 423 signed, err = asn1.Marshal(ecdsaSignature{r, s}) 424 } 425 certVerify.signatureAndHash.signature = signatureECDSA 426 certVerify.signatureAndHash.hash = hashId 427 case *rsa.PrivateKey: 428 digest, hashFunc, hashId := hs.finishedHash.hashForClientCertificate(signatureRSA) 429 signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest) 430 certVerify.signatureAndHash.signature = signatureRSA 431 certVerify.signatureAndHash.hash = hashId 432 default: 433 err = errors.New("unknown private key type") 434 } 435 if err != nil { 436 c.sendAlert(alertInternalError) 437 return errors.New("tls: failed to sign handshake with client certificate: " + err.Error()) 438 } 439 certVerify.signature = signed 440 441 hs.finishedHash.Write(certVerify.marshal()) 442 c.writeRecord(recordTypeHandshake, certVerify.marshal()) 443 } 444 445 hs.masterSecret = masterFromPreMasterSecret(c.vers, preMasterSecret, hs.hello.random, hs.serverHello.random) 446 return nil 447 } 448 449 func (hs *clientHandshakeState) establishKeys() error { 450 c := hs.c 451 452 clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := 453 keysFromMasterSecret(c.vers, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) 454 var clientCipher, serverCipher interface{} 455 var clientHash, serverHash macFunction 456 if hs.suite.cipher != nil { 457 clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */) 458 clientHash = hs.suite.mac(c.vers, clientMAC) 459 serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */) 460 serverHash = hs.suite.mac(c.vers, serverMAC) 461 } else { 462 clientCipher = hs.suite.aead(clientKey, clientIV) 463 serverCipher = hs.suite.aead(serverKey, serverIV) 464 } 465 466 c.in.prepareCipherSpec(c.vers, serverCipher, serverHash) 467 c.out.prepareCipherSpec(c.vers, clientCipher, clientHash) 468 return nil 469 } 470 471 func (hs *clientHandshakeState) serverResumedSession() bool { 472 // If the server responded with the same sessionId then it means the 473 // sessionTicket is being used to resume a TLS session. 474 return hs.session != nil && hs.hello.sessionId != nil && 475 bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId) 476 } 477 478 func (hs *clientHandshakeState) processServerHello() (bool, error) { 479 c := hs.c 480 481 if hs.serverHello.compressionMethod != compressionNone { 482 c.sendAlert(alertUnexpectedMessage) 483 return false, errors.New("tls: server selected unsupported compression format") 484 } 485 486 if !hs.hello.nextProtoNeg && hs.serverHello.nextProtoNeg { 487 c.sendAlert(alertHandshakeFailure) 488 return false, errors.New("server advertised unrequested NPN extension") 489 } 490 491 if hs.serverResumedSession() { 492 // Restore masterSecret and peerCerts from previous state 493 hs.masterSecret = hs.session.masterSecret 494 c.peerCertificates = hs.session.serverCertificates 495 return true, nil 496 } 497 return false, nil 498 } 499 500 func (hs *clientHandshakeState) readFinished() error { 501 c := hs.c 502 503 c.readRecord(recordTypeChangeCipherSpec) 504 if err := c.in.error(); err != nil { 505 return err 506 } 507 508 msg, err := c.readHandshake() 509 if err != nil { 510 return err 511 } 512 serverFinished, ok := msg.(*finishedMsg) 513 if !ok { 514 c.sendAlert(alertUnexpectedMessage) 515 return unexpectedMessageError(serverFinished, msg) 516 } 517 518 verify := hs.finishedHash.serverSum(hs.masterSecret) 519 if len(verify) != len(serverFinished.verifyData) || 520 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 { 521 c.sendAlert(alertHandshakeFailure) 522 return errors.New("tls: server's Finished message was incorrect") 523 } 524 hs.finishedHash.Write(serverFinished.marshal()) 525 return nil 526 } 527 528 func (hs *clientHandshakeState) readSessionTicket() error { 529 if !hs.serverHello.ticketSupported { 530 return nil 531 } 532 533 c := hs.c 534 msg, err := c.readHandshake() 535 if err != nil { 536 return err 537 } 538 sessionTicketMsg, ok := msg.(*newSessionTicketMsg) 539 if !ok { 540 c.sendAlert(alertUnexpectedMessage) 541 return unexpectedMessageError(sessionTicketMsg, msg) 542 } 543 hs.finishedHash.Write(sessionTicketMsg.marshal()) 544 545 hs.session = &ClientSessionState{ 546 sessionTicket: sessionTicketMsg.ticket, 547 vers: c.vers, 548 cipherSuite: hs.suite.id, 549 masterSecret: hs.masterSecret, 550 serverCertificates: c.peerCertificates, 551 } 552 553 return nil 554 } 555 556 func (hs *clientHandshakeState) sendFinished() error { 557 c := hs.c 558 559 c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) 560 if hs.serverHello.nextProtoNeg { 561 nextProto := new(nextProtoMsg) 562 proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.nextProtos) 563 nextProto.proto = proto 564 c.clientProtocol = proto 565 c.clientProtocolFallback = fallback 566 567 hs.finishedHash.Write(nextProto.marshal()) 568 c.writeRecord(recordTypeHandshake, nextProto.marshal()) 569 } 570 571 finished := new(finishedMsg) 572 finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret) 573 hs.finishedHash.Write(finished.marshal()) 574 c.writeRecord(recordTypeHandshake, finished.marshal()) 575 return nil 576 } 577 578 // clientSessionCacheKey returns a key used to cache sessionTickets that could 579 // be used to resume previously negotiated TLS sessions with a server. 580 func clientSessionCacheKey(serverAddr net.Addr, config *Config) string { 581 if len(config.ServerName) > 0 { 582 return config.ServerName 583 } 584 return serverAddr.String() 585 } 586 587 // mutualProtocol finds the mutual Next Protocol Negotiation protocol given the 588 // set of client and server supported protocols. The set of client supported 589 // protocols must not be empty. It returns the resulting protocol and flag 590 // indicating if the fallback case was reached. 591 func mutualProtocol(clientProtos, serverProtos []string) (string, bool) { 592 for _, s := range serverProtos { 593 for _, c := range clientProtos { 594 if s == c { 595 return s, false 596 } 597 } 598 } 599 600 return clientProtos[0], true 601 }