1 /* 2 * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.ssl; 27 28 import java.io.*; 29 import java.math.BigInteger; 30 import java.security.*; 31 import java.util.*; 32 33 import java.security.interfaces.ECPublicKey; 34 import java.security.interfaces.RSAPublicKey; 35 import java.security.spec.ECParameterSpec; 36 37 import java.security.cert.X509Certificate; 38 import java.security.cert.CertificateException; 39 import java.security.cert.CertificateParsingException; 40 import javax.security.auth.x500.X500Principal; 41 42 import javax.crypto.SecretKey; 43 import javax.crypto.spec.SecretKeySpec; 44 45 import javax.net.ssl.*; 46 47 import javax.security.auth.Subject; 48 49 import sun.security.ssl.HandshakeMessage.*; 50 import static sun.security.ssl.CipherSuite.KeyExchange.*; 51 52 /** 53 * ClientHandshaker does the protocol handshaking from the point 54 * of view of a client. It is driven asychronously by handshake messages 55 * as delivered by the parent Handshaker class, and also uses 56 * common functionality (e.g. key generation) that is provided there. 57 * 58 * @author David Brownell 59 */ 60 final class ClientHandshaker extends Handshaker { 61 62 // the server's public key from its certificate. 63 private PublicKey serverKey; 64 65 // the server's ephemeral public key from the server key exchange message 66 // for ECDHE/ECDH_anon and RSA_EXPORT. 67 private PublicKey ephemeralServerKey; 68 69 // server's ephemeral public value for DHE/DH_anon key exchanges 70 private BigInteger serverDH; 71 72 private DHCrypt dh; 73 74 private ECDHCrypt ecdh; 75 76 private CertificateRequest certRequest; 77 78 private boolean serverKeyExchangeReceived; 79 80 /* 81 * The RSA PreMasterSecret needs to know the version of 82 * ClientHello that was used on this handshake. This represents 83 * the "max version" this client is supporting. In the 84 * case of an initial handshake, it's the max version enabled, 85 * but in the case of a resumption attempt, it's the version 86 * of the session we're trying to resume. 87 */ 88 private ProtocolVersion maxProtocolVersion; 89 90 // To switch off the SNI extension. 91 private final static boolean enableSNIExtension = 92 Debug.getBooleanProperty("jsse.enableSNIExtension", true); 93 94 /* 95 * Allow unsafe server certificate change? 96 * 97 * Server certificate change during SSL/TLS renegotiation may be considered 98 * unsafe, as described in the Triple Handshake attacks: 99 * 100 * https://secure-resumption.com/tlsauth.pdf 101 * 102 * Endpoint identification (See 103 * SSLParameters.getEndpointIdentificationAlgorithm()) is a pretty nice 104 * guarantee that the server certificate change in renegotiation is legal. 105 * However, endpoing identification is only enabled for HTTPS and LDAP 106 * over SSL/TLS by default. It is not enough to protect SSL/TLS 107 * connections other than HTTPS and LDAP. 108 * 109 * The renegotiation indication extension (See RFC 5764) is a pretty 110 * strong guarantee that the endpoints on both client and server sides 111 * are identical on the same connection. However, the Triple Handshake 112 * attacks can bypass this guarantee if there is a session-resumption 113 * handshake between the initial full handshake and the renegotiation 114 * full handshake. 115 * 116 * Server certificate change may be unsafe and should be restricted if 117 * endpoint identification is not enabled and the previous handshake is 118 * a session-resumption abbreviated initial handshake, unless the 119 * identities represented by both certificates can be regraded as the 120 * same (See isIdentityEquivalent()). 121 * 122 * Considering the compatibility impact and the actual requirements to 123 * support server certificate change in practice, the system property, 124 * jdk.tls.allowUnsafeServerCertChange, is used to define whether unsafe 125 * server certificate change in renegotiation is allowed or not. The 126 * default value of the system property is "false". To mitigate the 127 * compactibility impact, applications may want to set the system 128 * property to "true" at their own risk. 129 * 130 * If the value of the system property is "false", server certificate 131 * change in renegotiation after a session-resumption abbreviated initial 132 * handshake is restricted (See isIdentityEquivalent()). 133 * 134 * If the system property is set to "true" explicitly, the restriction on 135 * server certificate change in renegotiation is disabled. 136 */ 137 private final static boolean allowUnsafeServerCertChange = 138 Debug.getBooleanProperty("jdk.tls.allowUnsafeServerCertChange", false); 139 140 private List<SNIServerName> requestedServerNames = 141 Collections.<SNIServerName>emptyList(); 142 143 private boolean serverNamesAccepted = false; 144 145 /* 146 * the reserved server certificate chain in previous handshaking 147 * 148 * The server certificate chain is only reserved if the previous 149 * handshake is a session-resumption abbreviated initial handshake. 150 */ 151 private X509Certificate[] reservedServerCerts = null; 152 153 /* 154 * Constructors 155 */ 156 ClientHandshaker(SSLSocketImpl socket, SSLContextImpl context, 157 ProtocolList enabledProtocols, 158 ProtocolVersion activeProtocolVersion, 159 boolean isInitialHandshake, boolean secureRenegotiation, 160 byte[] clientVerifyData, byte[] serverVerifyData) { 161 162 super(socket, context, enabledProtocols, true, true, 163 activeProtocolVersion, isInitialHandshake, secureRenegotiation, 164 clientVerifyData, serverVerifyData); 165 } 166 167 ClientHandshaker(SSLEngineImpl engine, SSLContextImpl context, 168 ProtocolList enabledProtocols, 169 ProtocolVersion activeProtocolVersion, 170 boolean isInitialHandshake, boolean secureRenegotiation, 171 byte[] clientVerifyData, byte[] serverVerifyData) { 172 173 super(engine, context, enabledProtocols, true, true, 174 activeProtocolVersion, isInitialHandshake, secureRenegotiation, 175 clientVerifyData, serverVerifyData); 176 } 177 178 /* 179 * This routine handles all the client side handshake messages, one at 180 * a time. Given the message type (and in some cases the pending cipher 181 * spec) it parses the type-specific message. Then it calls a function 182 * that handles that specific message. 183 * 184 * It updates the state machine (need to verify it) as each message 185 * is processed, and writes responses as needed using the connection 186 * in the constructor. 187 */ 188 @Override 189 void processMessage(byte type, int messageLen) throws IOException { 190 if (state >= type 191 && (type != HandshakeMessage.ht_hello_request)) { 192 throw new SSLProtocolException( 193 "Handshake message sequence violation, " + type); 194 } 195 196 switch (type) { 197 case HandshakeMessage.ht_hello_request: 198 this.serverHelloRequest(new HelloRequest(input)); 199 break; 200 201 case HandshakeMessage.ht_server_hello: 202 this.serverHello(new ServerHello(input, messageLen)); 203 break; 204 205 case HandshakeMessage.ht_certificate: 206 if (keyExchange == K_DH_ANON || keyExchange == K_ECDH_ANON 207 || keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) { 208 fatalSE(Alerts.alert_unexpected_message, 209 "unexpected server cert chain"); 210 // NOTREACHED 211 } 212 this.serverCertificate(new CertificateMsg(input)); 213 serverKey = 214 session.getPeerCertificates()[0].getPublicKey(); 215 break; 216 217 case HandshakeMessage.ht_server_key_exchange: 218 serverKeyExchangeReceived = true; 219 switch (keyExchange) { 220 case K_RSA_EXPORT: 221 /** 222 * The server key exchange message is sent by the server only 223 * when the server certificate message does not contain the 224 * proper amount of data to allow the client to exchange a 225 * premaster secret, such as when RSA_EXPORT is used and the 226 * public key in the server certificate is longer than 512 bits. 227 */ 228 if (serverKey == null) { 229 throw new SSLProtocolException 230 ("Server did not send certificate message"); 231 } 232 233 if (!(serverKey instanceof RSAPublicKey)) { 234 throw new SSLProtocolException("Protocol violation:" + 235 " the certificate type must be appropriate for the" + 236 " selected cipher suite's key exchange algorithm"); 237 } 238 239 if (JsseJce.getRSAKeyLength(serverKey) <= 512) { 240 throw new SSLProtocolException("Protocol violation:" + 241 " server sent a server key exchange message for" + 242 " key exchange " + keyExchange + 243 " when the public key in the server certificate" + 244 " is less than or equal to 512 bits in length"); 245 } 246 247 try { 248 this.serverKeyExchange(new RSA_ServerKeyExchange(input)); 249 } catch (GeneralSecurityException e) { 250 throwSSLException("Server key", e); 251 } 252 break; 253 case K_DH_ANON: 254 try { 255 this.serverKeyExchange(new DH_ServerKeyExchange( 256 input, protocolVersion)); 257 } catch (GeneralSecurityException e) { 258 throwSSLException("Server key", e); 259 } 260 break; 261 case K_DHE_DSS: 262 case K_DHE_RSA: 263 try { 264 this.serverKeyExchange(new DH_ServerKeyExchange( 265 input, serverKey, 266 clnt_random.random_bytes, svr_random.random_bytes, 267 messageLen, 268 localSupportedSignAlgs, protocolVersion)); 269 } catch (GeneralSecurityException e) { 270 throwSSLException("Server key", e); 271 } 272 break; 273 case K_ECDHE_ECDSA: 274 case K_ECDHE_RSA: 275 case K_ECDH_ANON: 276 try { 277 this.serverKeyExchange(new ECDH_ServerKeyExchange 278 (input, serverKey, clnt_random.random_bytes, 279 svr_random.random_bytes, 280 localSupportedSignAlgs, protocolVersion)); 281 } catch (GeneralSecurityException e) { 282 throwSSLException("Server key", e); 283 } 284 break; 285 case K_RSA: 286 case K_DH_RSA: 287 case K_DH_DSS: 288 case K_ECDH_ECDSA: 289 case K_ECDH_RSA: 290 throw new SSLProtocolException( 291 "Protocol violation: server sent a server key exchange" 292 + "message for key exchange " + keyExchange); 293 case K_KRB5: 294 case K_KRB5_EXPORT: 295 throw new SSLProtocolException( 296 "unexpected receipt of server key exchange algorithm"); 297 default: 298 throw new SSLProtocolException( 299 "unsupported key exchange algorithm = " 300 + keyExchange); 301 } 302 break; 303 304 case HandshakeMessage.ht_certificate_request: 305 // save for later, it's handled by serverHelloDone 306 if ((keyExchange == K_DH_ANON) || (keyExchange == K_ECDH_ANON)) { 307 throw new SSLHandshakeException( 308 "Client authentication requested for "+ 309 "anonymous cipher suite."); 310 } else if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) { 311 throw new SSLHandshakeException( 312 "Client certificate requested for "+ 313 "kerberos cipher suite."); 314 } 315 certRequest = new CertificateRequest(input, protocolVersion); 316 if (debug != null && Debug.isOn("handshake")) { 317 certRequest.print(System.out); 318 } 319 320 if (protocolVersion.v >= ProtocolVersion.TLS12.v) { 321 Collection<SignatureAndHashAlgorithm> peerSignAlgs = 322 certRequest.getSignAlgorithms(); 323 if (peerSignAlgs == null || peerSignAlgs.isEmpty()) { 324 throw new SSLHandshakeException( 325 "No peer supported signature algorithms"); 326 } 327 328 Collection<SignatureAndHashAlgorithm> supportedPeerSignAlgs = 329 SignatureAndHashAlgorithm.getSupportedAlgorithms( 330 peerSignAlgs); 331 if (supportedPeerSignAlgs.isEmpty()) { 332 throw new SSLHandshakeException( 333 "No supported signature and hash algorithm in common"); 334 } 335 336 setPeerSupportedSignAlgs(supportedPeerSignAlgs); 337 session.setPeerSupportedSignatureAlgorithms( 338 supportedPeerSignAlgs); 339 } 340 341 break; 342 343 case HandshakeMessage.ht_server_hello_done: 344 this.serverHelloDone(new ServerHelloDone(input)); 345 break; 346 347 case HandshakeMessage.ht_finished: 348 // A ChangeCipherSpec record must have been received prior to 349 // reception of the Finished message (RFC 5246, 7.4.9). 350 if (!receivedChangeCipherSpec()) { 351 fatalSE(Alerts.alert_handshake_failure, 352 "Received Finished message before ChangeCipherSpec"); 353 } 354 355 this.serverFinished( 356 new Finished(protocolVersion, input, cipherSuite)); 357 break; 358 359 default: 360 throw new SSLProtocolException( 361 "Illegal client handshake msg, " + type); 362 } 363 364 // 365 // Move state machine forward if the message handling 366 // code didn't already do so 367 // 368 if (state < type) { 369 state = type; 370 } 371 } 372 373 /* 374 * Used by the server to kickstart negotiations -- this requests a 375 * "client hello" to renegotiate current cipher specs (e.g. maybe lots 376 * of data has been encrypted with the same keys, or the server needs 377 * the client to present a certificate). 378 */ 379 private void serverHelloRequest(HelloRequest mesg) throws IOException { 380 if (debug != null && Debug.isOn("handshake")) { 381 mesg.print(System.out); 382 } 383 384 // 385 // Could be (e.g. at connection setup) that we already 386 // sent the "client hello" but the server's not seen it. 387 // 388 if (state < HandshakeMessage.ht_client_hello) { 389 if (!secureRenegotiation && !allowUnsafeRenegotiation) { 390 // renegotiation is not allowed. 391 if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) { 392 // response with a no_renegotiation warning, 393 warningSE(Alerts.alert_no_renegotiation); 394 395 // invalidate the handshake so that the caller can 396 // dispose this object. 397 invalidated = true; 398 399 // If there is still unread block in the handshake 400 // input stream, it would be truncated with the disposal 401 // and the next handshake message will become incomplete. 402 // 403 // However, according to SSL/TLS specifications, no more 404 // handshake message should immediately follow ClientHello 405 // or HelloRequest. So just let it be. 406 } else { 407 // For SSLv3, send the handshake_failure fatal error. 408 // Note that SSLv3 does not define a no_renegotiation 409 // alert like TLSv1. However we cannot ignore the message 410 // simply, otherwise the other side was waiting for a 411 // response that would never come. 412 fatalSE(Alerts.alert_handshake_failure, 413 "Renegotiation is not allowed"); 414 } 415 } else { 416 if (!secureRenegotiation) { 417 if (debug != null && Debug.isOn("handshake")) { 418 System.out.println( 419 "Warning: continue with insecure renegotiation"); 420 } 421 } 422 kickstart(); 423 } 424 } 425 } 426 427 428 /* 429 * Server chooses session parameters given options created by the 430 * client -- basically, cipher options, session id, and someday a 431 * set of compression options. 432 * 433 * There are two branches of the state machine, decided by the 434 * details of this message. One is the "fast" handshake, where we 435 * can resume the pre-existing session we asked resume. The other 436 * is a more expensive "full" handshake, with key exchange and 437 * probably authentication getting done. 438 */ 439 private void serverHello(ServerHello mesg) throws IOException { 440 serverKeyExchangeReceived = false; 441 if (debug != null && Debug.isOn("handshake")) { 442 mesg.print(System.out); 443 } 444 445 // check if the server selected protocol version is OK for us 446 ProtocolVersion mesgVersion = mesg.protocolVersion; 447 if (!isNegotiable(mesgVersion)) { 448 throw new SSLHandshakeException( 449 "Server chose " + mesgVersion + 450 ", but that protocol version is not enabled or not supported " + 451 "by the client."); 452 } 453 454 handshakeHash.protocolDetermined(mesgVersion); 455 456 // Set protocolVersion and propagate to SSLSocket and the 457 // Handshake streams 458 setVersion(mesgVersion); 459 460 // check the "renegotiation_info" extension 461 RenegotiationInfoExtension serverHelloRI = (RenegotiationInfoExtension) 462 mesg.extensions.get(ExtensionType.EXT_RENEGOTIATION_INFO); 463 if (serverHelloRI != null) { 464 if (isInitialHandshake) { 465 // verify the length of the "renegotiated_connection" field 466 if (!serverHelloRI.isEmpty()) { 467 // abort the handshake with a fatal handshake_failure alert 468 fatalSE(Alerts.alert_handshake_failure, 469 "The renegotiation_info field is not empty"); 470 } 471 472 secureRenegotiation = true; 473 } else { 474 // For a legacy renegotiation, the client MUST verify that 475 // it does not contain the "renegotiation_info" extension. 476 if (!secureRenegotiation) { 477 fatalSE(Alerts.alert_handshake_failure, 478 "Unexpected renegotiation indication extension"); 479 } 480 481 // verify the client_verify_data and server_verify_data values 482 byte[] verifyData = 483 new byte[clientVerifyData.length + serverVerifyData.length]; 484 System.arraycopy(clientVerifyData, 0, verifyData, 485 0, clientVerifyData.length); 486 System.arraycopy(serverVerifyData, 0, verifyData, 487 clientVerifyData.length, serverVerifyData.length); 488 if (!Arrays.equals(verifyData, 489 serverHelloRI.getRenegotiatedConnection())) { 490 fatalSE(Alerts.alert_handshake_failure, 491 "Incorrect verify data in ServerHello " + 492 "renegotiation_info message"); 493 } 494 } 495 } else { 496 // no renegotiation indication extension 497 if (isInitialHandshake) { 498 if (!allowLegacyHelloMessages) { 499 // abort the handshake with a fatal handshake_failure alert 500 fatalSE(Alerts.alert_handshake_failure, 501 "Failed to negotiate the use of secure renegotiation"); 502 } 503 504 secureRenegotiation = false; 505 if (debug != null && Debug.isOn("handshake")) { 506 System.out.println("Warning: No renegotiation " + 507 "indication extension in ServerHello"); 508 } 509 } else { 510 // For a secure renegotiation, the client must abort the 511 // handshake if no "renegotiation_info" extension is present. 512 if (secureRenegotiation) { 513 fatalSE(Alerts.alert_handshake_failure, 514 "No renegotiation indication extension"); 515 } 516 517 // we have already allowed unsafe renegotation before request 518 // the renegotiation. 519 } 520 } 521 522 // 523 // Save server nonce, we always use it to compute connection 524 // keys and it's also used to create the master secret if we're 525 // creating a new session (i.e. in the full handshake). 526 // 527 svr_random = mesg.svr_random; 528 529 if (isNegotiable(mesg.cipherSuite) == false) { 530 fatalSE(Alerts.alert_illegal_parameter, 531 "Server selected improper ciphersuite " + mesg.cipherSuite); 532 } 533 534 setCipherSuite(mesg.cipherSuite); 535 if (protocolVersion.v >= ProtocolVersion.TLS12.v) { 536 handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg()); 537 } 538 539 if (mesg.compression_method != 0) { 540 fatalSE(Alerts.alert_illegal_parameter, 541 "compression type not supported, " 542 + mesg.compression_method); 543 // NOTREACHED 544 } 545 546 // so far so good, let's look at the session 547 if (session != null) { 548 // we tried to resume, let's see what the server decided 549 if (session.getSessionId().equals(mesg.sessionId)) { 550 // server resumed the session, let's make sure everything 551 // checks out 552 553 // Verify that the session ciphers are unchanged. 554 CipherSuite sessionSuite = session.getSuite(); 555 if (cipherSuite != sessionSuite) { 556 throw new SSLProtocolException 557 ("Server returned wrong cipher suite for session"); 558 } 559 560 // verify protocol version match 561 ProtocolVersion sessionVersion = session.getProtocolVersion(); 562 if (protocolVersion != sessionVersion) { 563 throw new SSLProtocolException 564 ("Server resumed session with wrong protocol version"); 565 } 566 567 // validate subject identity 568 if (sessionSuite.keyExchange == K_KRB5 || 569 sessionSuite.keyExchange == K_KRB5_EXPORT) { 570 Principal localPrincipal = session.getLocalPrincipal(); 571 572 Subject subject = null; 573 try { 574 subject = AccessController.doPrivileged( 575 new PrivilegedExceptionAction<Subject>() { 576 @Override 577 public Subject run() throws Exception { 578 return Krb5Helper.getClientSubject(getAccSE()); 579 }}); 580 } catch (PrivilegedActionException e) { 581 subject = null; 582 if (debug != null && Debug.isOn("session")) { 583 System.out.println("Attempt to obtain" + 584 " subject failed!"); 585 } 586 } 587 588 if (subject != null) { 589 // Eliminate dependency on KerberosPrincipal 590 Set<Principal> principals = 591 subject.getPrincipals(Principal.class); 592 if (!principals.contains(localPrincipal)) { 593 throw new SSLProtocolException("Server resumed" + 594 " session with wrong subject identity"); 595 } else { 596 if (debug != null && Debug.isOn("session")) 597 System.out.println("Subject identity is same"); 598 } 599 } else { 600 if (debug != null && Debug.isOn("session")) 601 System.out.println("Kerberos credentials are not" + 602 " present in the current Subject; check if " + 603 " javax.security.auth.useSubjectAsCreds" + 604 " system property has been set to false"); 605 throw new SSLProtocolException 606 ("Server resumed session with no subject"); 607 } 608 } 609 610 // looks fine; resume it, and update the state machine. 611 resumingSession = true; 612 state = HandshakeMessage.ht_finished - 1; 613 calculateConnectionKeys(session.getMasterSecret()); 614 if (debug != null && Debug.isOn("session")) { 615 System.out.println("%% Server resumed " + session); 616 } 617 } else { 618 // we wanted to resume, but the server refused 619 session = null; 620 if (!enableNewSession) { 621 throw new SSLException("New session creation is disabled"); 622 } 623 } 624 } 625 626 if (resumingSession && session != null) { 627 setHandshakeSessionSE(session); 628 // Reserve the handshake state if this is a session-resumption 629 // abbreviated initial handshake. 630 if (isInitialHandshake) { 631 session.setAsSessionResumption(true); 632 } 633 634 return; 635 } 636 637 // check extensions 638 for (HelloExtension ext : mesg.extensions.list()) { 639 ExtensionType type = ext.type; 640 if (type == ExtensionType.EXT_SERVER_NAME) { 641 serverNamesAccepted = true; 642 } else if ((type != ExtensionType.EXT_ELLIPTIC_CURVES) 643 && (type != ExtensionType.EXT_EC_POINT_FORMATS) 644 && (type != ExtensionType.EXT_SERVER_NAME) 645 && (type != ExtensionType.EXT_RENEGOTIATION_INFO)) { 646 fatalSE(Alerts.alert_unsupported_extension, 647 "Server sent an unsupported extension: " + type); 648 } 649 } 650 651 // Create a new session, we need to do the full handshake 652 session = new SSLSessionImpl(protocolVersion, cipherSuite, 653 getLocalSupportedSignAlgs(), 654 mesg.sessionId, getHostSE(), getPortSE()); 655 session.setRequestedServerNames(requestedServerNames); 656 setHandshakeSessionSE(session); 657 if (debug != null && Debug.isOn("handshake")) { 658 System.out.println("** " + cipherSuite); 659 } 660 } 661 662 /* 663 * Server's own key was either a signing-only key, or was too 664 * large for export rules ... this message holds an ephemeral 665 * RSA key to use for key exchange. 666 */ 667 private void serverKeyExchange(RSA_ServerKeyExchange mesg) 668 throws IOException, GeneralSecurityException { 669 if (debug != null && Debug.isOn("handshake")) { 670 mesg.print(System.out); 671 } 672 if (!mesg.verify(serverKey, clnt_random, svr_random)) { 673 fatalSE(Alerts.alert_handshake_failure, 674 "server key exchange invalid"); 675 // NOTREACHED 676 } 677 ephemeralServerKey = mesg.getPublicKey(); 678 } 679 680 681 /* 682 * Diffie-Hellman key exchange. We save the server public key and 683 * our own D-H algorithm object so we can defer key calculations 684 * until after we've sent the client key exchange message (which 685 * gives client and server some useful parallelism). 686 */ 687 private void serverKeyExchange(DH_ServerKeyExchange mesg) 688 throws IOException { 689 if (debug != null && Debug.isOn("handshake")) { 690 mesg.print(System.out); 691 } 692 dh = new DHCrypt(mesg.getModulus(), mesg.getBase(), 693 sslContext.getSecureRandom()); 694 serverDH = mesg.getServerPublicKey(); 695 } 696 697 private void serverKeyExchange(ECDH_ServerKeyExchange mesg) 698 throws IOException { 699 if (debug != null && Debug.isOn("handshake")) { 700 mesg.print(System.out); 701 } 702 ECPublicKey key = mesg.getPublicKey(); 703 ecdh = new ECDHCrypt(key.getParams(), sslContext.getSecureRandom()); 704 ephemeralServerKey = key; 705 } 706 707 /* 708 * The server's "Hello Done" message is the client's sign that 709 * it's time to do all the hard work. 710 */ 711 private void serverHelloDone(ServerHelloDone mesg) throws IOException { 712 if (debug != null && Debug.isOn("handshake")) { 713 mesg.print(System.out); 714 } 715 /* 716 * Always make sure the input has been digested before we 717 * start emitting data, to ensure the hashes are correctly 718 * computed for the Finished and CertificateVerify messages 719 * which we send (here). 720 */ 721 input.digestNow(); 722 723 /* 724 * FIRST ... if requested, send an appropriate Certificate chain 725 * to authenticate the client, and remember the associated private 726 * key to sign the CertificateVerify message. 727 */ 728 PrivateKey signingKey = null; 729 730 if (certRequest != null) { 731 X509ExtendedKeyManager km = sslContext.getX509KeyManager(); 732 733 ArrayList<String> keytypesTmp = new ArrayList<>(4); 734 735 for (int i = 0; i < certRequest.types.length; i++) { 736 String typeName; 737 738 switch (certRequest.types[i]) { 739 case CertificateRequest.cct_rsa_sign: 740 typeName = "RSA"; 741 break; 742 743 case CertificateRequest.cct_dss_sign: 744 typeName = "DSA"; 745 break; 746 747 case CertificateRequest.cct_ecdsa_sign: 748 // ignore if we do not have EC crypto available 749 typeName = JsseJce.isEcAvailable() ? "EC" : null; 750 break; 751 752 // Fixed DH/ECDH client authentication not supported 753 case CertificateRequest.cct_rsa_fixed_dh: 754 case CertificateRequest.cct_dss_fixed_dh: 755 case CertificateRequest.cct_rsa_fixed_ecdh: 756 case CertificateRequest.cct_ecdsa_fixed_ecdh: 757 // Any other values (currently not used in TLS) 758 case CertificateRequest.cct_rsa_ephemeral_dh: 759 case CertificateRequest.cct_dss_ephemeral_dh: 760 default: 761 typeName = null; 762 break; 763 } 764 765 if ((typeName != null) && (!keytypesTmp.contains(typeName))) { 766 keytypesTmp.add(typeName); 767 } 768 } 769 770 String alias = null; 771 int keytypesTmpSize = keytypesTmp.size(); 772 if (keytypesTmpSize != 0) { 773 String keytypes[] = 774 keytypesTmp.toArray(new String[keytypesTmpSize]); 775 776 if (conn != null) { 777 alias = km.chooseClientAlias(keytypes, 778 certRequest.getAuthorities(), conn); 779 } else { 780 alias = km.chooseEngineClientAlias(keytypes, 781 certRequest.getAuthorities(), engine); 782 } 783 } 784 785 CertificateMsg m1 = null; 786 if (alias != null) { 787 X509Certificate[] certs = km.getCertificateChain(alias); 788 if ((certs != null) && (certs.length != 0)) { 789 PublicKey publicKey = certs[0].getPublicKey(); 790 // for EC, make sure we use a supported named curve 791 if (publicKey instanceof ECPublicKey) { 792 ECParameterSpec params = 793 ((ECPublicKey)publicKey).getParams(); 794 int index = 795 SupportedEllipticCurvesExtension.getCurveIndex( 796 params); 797 if (!SupportedEllipticCurvesExtension.isSupported( 798 index)) { 799 publicKey = null; 800 } 801 } 802 if (publicKey != null) { 803 m1 = new CertificateMsg(certs); 804 signingKey = km.getPrivateKey(alias); 805 session.setLocalPrivateKey(signingKey); 806 session.setLocalCertificates(certs); 807 } 808 } 809 } 810 if (m1 == null) { 811 // 812 // No appropriate cert was found ... report this to the 813 // server. For SSLv3, send the no_certificate alert; 814 // TLS uses an empty cert chain instead. 815 // 816 if (protocolVersion.v >= ProtocolVersion.TLS10.v) { 817 m1 = new CertificateMsg(new X509Certificate [0]); 818 } else { 819 warningSE(Alerts.alert_no_certificate); 820 } 821 } 822 823 // 824 // At last ... send any client certificate chain. 825 // 826 if (m1 != null) { 827 if (debug != null && Debug.isOn("handshake")) { 828 m1.print(System.out); 829 } 830 m1.write(output); 831 } 832 } 833 834 /* 835 * SECOND ... send the client key exchange message. The 836 * procedure used is a function of the cipher suite selected; 837 * one is always needed. 838 */ 839 HandshakeMessage m2; 840 841 switch (keyExchange) { 842 843 case K_RSA: 844 case K_RSA_EXPORT: 845 if (serverKey == null) { 846 throw new SSLProtocolException 847 ("Server did not send certificate message"); 848 } 849 850 if (!(serverKey instanceof RSAPublicKey)) { 851 throw new SSLProtocolException 852 ("Server certificate does not include an RSA key"); 853 } 854 855 /* 856 * For RSA key exchange, we randomly generate a new 857 * pre-master secret and encrypt it with the server's 858 * public key. Then we save that pre-master secret 859 * so that we can calculate the keying data later; 860 * it's a performance speedup not to do that until 861 * the client's waiting for the server response, but 862 * more of a speedup for the D-H case. 863 * 864 * If the RSA_EXPORT scheme is active, when the public 865 * key in the server certificate is less than or equal 866 * to 512 bits in length, use the cert's public key, 867 * otherwise, the ephemeral one. 868 */ 869 PublicKey key; 870 if (keyExchange == K_RSA) { 871 key = serverKey; 872 } else { // K_RSA_EXPORT 873 if (JsseJce.getRSAKeyLength(serverKey) <= 512) { 874 // extraneous ephemeralServerKey check done 875 // above in processMessage() 876 key = serverKey; 877 } else { 878 if (ephemeralServerKey == null) { 879 throw new SSLProtocolException("Server did not send" + 880 " a RSA_EXPORT Server Key Exchange message"); 881 } 882 key = ephemeralServerKey; 883 } 884 } 885 886 m2 = new RSAClientKeyExchange(protocolVersion, maxProtocolVersion, 887 sslContext.getSecureRandom(), key); 888 break; 889 case K_DH_RSA: 890 case K_DH_DSS: 891 /* 892 * For DH Key exchange, we only need to make sure the server 893 * knows our public key, so we calculate the same pre-master 894 * secret. 895 * 896 * For certs that had DH keys in them, we send an empty 897 * handshake message (no key) ... we flag this case by 898 * passing a null "dhPublic" value. 899 * 900 * Otherwise we send ephemeral DH keys, unsigned. 901 */ 902 // if (useDH_RSA || useDH_DSS) 903 m2 = new DHClientKeyExchange(); 904 break; 905 case K_DHE_RSA: 906 case K_DHE_DSS: 907 case K_DH_ANON: 908 if (dh == null) { 909 throw new SSLProtocolException 910 ("Server did not send a DH Server Key Exchange message"); 911 } 912 m2 = new DHClientKeyExchange(dh.getPublicKey()); 913 break; 914 case K_ECDHE_RSA: 915 case K_ECDHE_ECDSA: 916 case K_ECDH_ANON: 917 if (ecdh == null) { 918 throw new SSLProtocolException 919 ("Server did not send a ECDH Server Key Exchange message"); 920 } 921 m2 = new ECDHClientKeyExchange(ecdh.getPublicKey()); 922 break; 923 case K_ECDH_RSA: 924 case K_ECDH_ECDSA: 925 if (serverKey == null) { 926 throw new SSLProtocolException 927 ("Server did not send certificate message"); 928 } 929 if (serverKey instanceof ECPublicKey == false) { 930 throw new SSLProtocolException 931 ("Server certificate does not include an EC key"); 932 } 933 ECParameterSpec params = ((ECPublicKey)serverKey).getParams(); 934 ecdh = new ECDHCrypt(params, sslContext.getSecureRandom()); 935 m2 = new ECDHClientKeyExchange(ecdh.getPublicKey()); 936 break; 937 case K_KRB5: 938 case K_KRB5_EXPORT: 939 String sniHostname = null; 940 for (SNIServerName serverName : requestedServerNames) { 941 if (serverName instanceof SNIHostName) { 942 sniHostname = ((SNIHostName) serverName).getAsciiName(); 943 break; 944 } 945 } 946 947 KerberosClientKeyExchange kerberosMsg = null; 948 if (sniHostname != null) { 949 // use first requested SNI hostname 950 try { 951 kerberosMsg = new KerberosClientKeyExchange( 952 sniHostname, getAccSE(), protocolVersion, 953 sslContext.getSecureRandom()); 954 } catch(IOException e) { 955 if (serverNamesAccepted) { 956 // server accepted requested SNI hostname, 957 // so it must be used 958 throw e; 959 } 960 // fallback to using hostname 961 if (debug != null && Debug.isOn("handshake")) { 962 System.out.println( 963 "Warning, cannot use Server Name Indication: " 964 + e.getMessage()); 965 } 966 } 967 } 968 969 if (kerberosMsg == null) { 970 String hostname = getHostSE(); 971 if (hostname == null) { 972 throw new IOException("Hostname is required" + 973 " to use Kerberos cipher suites"); 974 } 975 kerberosMsg = new KerberosClientKeyExchange( 976 hostname, getAccSE(), protocolVersion, 977 sslContext.getSecureRandom()); 978 } 979 980 // Record the principals involved in exchange 981 session.setPeerPrincipal(kerberosMsg.getPeerPrincipal()); 982 session.setLocalPrincipal(kerberosMsg.getLocalPrincipal()); 983 m2 = kerberosMsg; 984 break; 985 default: 986 // somethings very wrong 987 throw new RuntimeException 988 ("Unsupported key exchange: " + keyExchange); 989 } 990 if (debug != null && Debug.isOn("handshake")) { 991 m2.print(System.out); 992 } 993 m2.write(output); 994 995 996 /* 997 * THIRD, send a "change_cipher_spec" record followed by the 998 * "Finished" message. We flush the messages we've queued up, to 999 * get concurrency between client and server. The concurrency is 1000 * useful as we calculate the master secret, which is needed both 1001 * to compute the "Finished" message, and to compute the keys used 1002 * to protect all records following the change_cipher_spec. 1003 */ 1004 1005 output.doHashes(); 1006 output.flush(); 1007 1008 /* 1009 * We deferred calculating the master secret and this connection's 1010 * keying data; we do it now. Deferring this calculation is good 1011 * from a performance point of view, since it lets us do it during 1012 * some time that network delays and the server's own calculations 1013 * would otherwise cause to be "dead" in the critical path. 1014 */ 1015 SecretKey preMasterSecret; 1016 switch (keyExchange) { 1017 case K_RSA: 1018 case K_RSA_EXPORT: 1019 preMasterSecret = ((RSAClientKeyExchange)m2).preMaster; 1020 break; 1021 case K_KRB5: 1022 case K_KRB5_EXPORT: 1023 byte[] secretBytes = 1024 ((KerberosClientKeyExchange)m2).getUnencryptedPreMasterSecret(); 1025 preMasterSecret = new SecretKeySpec(secretBytes, 1026 "TlsPremasterSecret"); 1027 break; 1028 case K_DHE_RSA: 1029 case K_DHE_DSS: 1030 case K_DH_ANON: 1031 preMasterSecret = dh.getAgreedSecret(serverDH, true); 1032 break; 1033 case K_ECDHE_RSA: 1034 case K_ECDHE_ECDSA: 1035 case K_ECDH_ANON: 1036 preMasterSecret = ecdh.getAgreedSecret(ephemeralServerKey); 1037 break; 1038 case K_ECDH_RSA: 1039 case K_ECDH_ECDSA: 1040 preMasterSecret = ecdh.getAgreedSecret(serverKey); 1041 break; 1042 default: 1043 throw new IOException("Internal error: unknown key exchange " 1044 + keyExchange); 1045 } 1046 1047 calculateKeys(preMasterSecret, null); 1048 1049 /* 1050 * FOURTH, if we sent a Certificate, we need to send a signed 1051 * CertificateVerify (unless the key in the client's certificate 1052 * was a Diffie-Hellman key).). 1053 * 1054 * This uses a hash of the previous handshake messages ... either 1055 * a nonfinal one (if the particular implementation supports it) 1056 * or else using the third element in the arrays of hashes being 1057 * computed. 1058 */ 1059 if (signingKey != null) { 1060 CertificateVerify m3; 1061 try { 1062 SignatureAndHashAlgorithm preferableSignatureAlgorithm = null; 1063 if (protocolVersion.v >= ProtocolVersion.TLS12.v) { 1064 preferableSignatureAlgorithm = 1065 SignatureAndHashAlgorithm.getPreferableAlgorithm( 1066 peerSupportedSignAlgs, signingKey.getAlgorithm(), 1067 signingKey); 1068 1069 if (preferableSignatureAlgorithm == null) { 1070 throw new SSLHandshakeException( 1071 "No supported signature algorithm"); 1072 } 1073 1074 String hashAlg = 1075 SignatureAndHashAlgorithm.getHashAlgorithmName( 1076 preferableSignatureAlgorithm); 1077 if (hashAlg == null || hashAlg.length() == 0) { 1078 throw new SSLHandshakeException( 1079 "No supported hash algorithm"); 1080 } 1081 } 1082 1083 m3 = new CertificateVerify(protocolVersion, handshakeHash, 1084 signingKey, session.getMasterSecret(), 1085 sslContext.getSecureRandom(), 1086 preferableSignatureAlgorithm); 1087 } catch (GeneralSecurityException e) { 1088 fatalSE(Alerts.alert_handshake_failure, 1089 "Error signing certificate verify", e); 1090 // NOTREACHED, make compiler happy 1091 m3 = null; 1092 } 1093 if (debug != null && Debug.isOn("handshake")) { 1094 m3.print(System.out); 1095 } 1096 m3.write(output); 1097 output.doHashes(); 1098 } 1099 1100 /* 1101 * OK, that's that! 1102 */ 1103 sendChangeCipherAndFinish(false); 1104 } 1105 1106 1107 /* 1108 * "Finished" is the last handshake message sent. If we got this 1109 * far, the MAC has been validated post-decryption. We validate 1110 * the two hashes here as an additional sanity check, protecting 1111 * the handshake against various active attacks. 1112 */ 1113 private void serverFinished(Finished mesg) throws IOException { 1114 if (debug != null && Debug.isOn("handshake")) { 1115 mesg.print(System.out); 1116 } 1117 1118 boolean verified = mesg.verify(handshakeHash, Finished.SERVER, 1119 session.getMasterSecret()); 1120 1121 if (!verified) { 1122 fatalSE(Alerts.alert_illegal_parameter, 1123 "server 'finished' message doesn't verify"); 1124 // NOTREACHED 1125 } 1126 1127 /* 1128 * save server verify data for secure renegotiation 1129 */ 1130 if (secureRenegotiation) { 1131 serverVerifyData = mesg.getVerifyData(); 1132 } 1133 1134 /* 1135 * Reset the handshake state if this is not an initial handshake. 1136 */ 1137 if (!isInitialHandshake) { 1138 session.setAsSessionResumption(false); 1139 } 1140 1141 /* 1142 * OK, it verified. If we're doing the fast handshake, add that 1143 * "Finished" message to the hash of handshake messages, then send 1144 * our own change_cipher_spec and Finished message for the server 1145 * to verify in turn. These are the last handshake messages. 1146 * 1147 * In any case, update the session cache. We're done handshaking, 1148 * so there are no threats any more associated with partially 1149 * completed handshakes. 1150 */ 1151 if (resumingSession) { 1152 input.digestNow(); 1153 sendChangeCipherAndFinish(true); 1154 } 1155 session.setLastAccessedTime(System.currentTimeMillis()); 1156 1157 if (!resumingSession) { 1158 if (session.isRejoinable()) { 1159 ((SSLSessionContextImpl) sslContext 1160 .engineGetClientSessionContext()) 1161 .put(session); 1162 if (debug != null && Debug.isOn("session")) { 1163 System.out.println("%% Cached client session: " + session); 1164 } 1165 } else if (debug != null && Debug.isOn("session")) { 1166 System.out.println( 1167 "%% Didn't cache non-resumable client session: " 1168 + session); 1169 } 1170 } 1171 } 1172 1173 1174 /* 1175 * Send my change-cipher-spec and Finished message ... done as the 1176 * last handshake act in either the short or long sequences. In 1177 * the short one, we've already seen the server's Finished; in the 1178 * long one, we wait for it now. 1179 */ 1180 private void sendChangeCipherAndFinish(boolean finishedTag) 1181 throws IOException { 1182 Finished mesg = new Finished(protocolVersion, handshakeHash, 1183 Finished.CLIENT, session.getMasterSecret(), cipherSuite); 1184 1185 /* 1186 * Send the change_cipher_spec message, then the Finished message 1187 * which we just calculated (and protected using the keys we just 1188 * calculated). Server responds with its Finished message, except 1189 * in the "fast handshake" (resume session) case. 1190 */ 1191 sendChangeCipherSpec(mesg, finishedTag); 1192 1193 /* 1194 * save client verify data for secure renegotiation 1195 */ 1196 if (secureRenegotiation) { 1197 clientVerifyData = mesg.getVerifyData(); 1198 } 1199 1200 /* 1201 * Update state machine so server MUST send 'finished' next. 1202 * (In "long" handshake case; in short case, we're responding 1203 * to its message.) 1204 */ 1205 state = HandshakeMessage.ht_finished - 1; 1206 } 1207 1208 1209 /* 1210 * Returns a ClientHello message to kickstart renegotiations 1211 */ 1212 @Override 1213 HandshakeMessage getKickstartMessage() throws SSLException { 1214 // session ID of the ClientHello message 1215 SessionId sessionId = SSLSessionImpl.nullSession.getSessionId(); 1216 1217 // a list of cipher suites sent by the client 1218 CipherSuiteList cipherSuites = getActiveCipherSuites(); 1219 1220 // set the max protocol version this client is supporting. 1221 maxProtocolVersion = protocolVersion; 1222 1223 // 1224 // Try to resume an existing session. This might be mandatory, 1225 // given certain API options. 1226 // 1227 session = ((SSLSessionContextImpl)sslContext 1228 .engineGetClientSessionContext()) 1229 .get(getHostSE(), getPortSE()); 1230 if (debug != null && Debug.isOn("session")) { 1231 if (session != null) { 1232 System.out.println("%% Client cached " 1233 + session 1234 + (session.isRejoinable() ? "" : " (not rejoinable)")); 1235 } else { 1236 System.out.println("%% No cached client session"); 1237 } 1238 } 1239 if (session != null) { 1240 // If unsafe server certificate change is not allowed, reserve 1241 // current server certificates if the previous handshake is a 1242 // session-resumption abbreviated initial handshake. 1243 if (!allowUnsafeServerCertChange && session.isSessionResumption()) { 1244 try { 1245 // If existing, peer certificate chain cannot be null. 1246 reservedServerCerts = 1247 (X509Certificate[])session.getPeerCertificates(); 1248 } catch (SSLPeerUnverifiedException puve) { 1249 // Maybe not certificate-based, ignore the exception. 1250 } 1251 } 1252 1253 if (!session.isRejoinable()) { 1254 session = null; 1255 } 1256 } 1257 1258 if (session != null) { 1259 CipherSuite sessionSuite = session.getSuite(); 1260 ProtocolVersion sessionVersion = session.getProtocolVersion(); 1261 if (isNegotiable(sessionSuite) == false) { 1262 if (debug != null && Debug.isOn("session")) { 1263 System.out.println("%% can't resume, unavailable cipher"); 1264 } 1265 session = null; 1266 } 1267 1268 if ((session != null) && !isNegotiable(sessionVersion)) { 1269 if (debug != null && Debug.isOn("session")) { 1270 System.out.println("%% can't resume, protocol disabled"); 1271 } 1272 session = null; 1273 } 1274 1275 if (session != null) { 1276 if (debug != null) { 1277 if (Debug.isOn("handshake") || Debug.isOn("session")) { 1278 System.out.println("%% Try resuming " + session 1279 + " from port " + getLocalPortSE()); 1280 } 1281 } 1282 1283 sessionId = session.getSessionId(); 1284 maxProtocolVersion = sessionVersion; 1285 1286 // Update SSL version number in underlying SSL socket and 1287 // handshake output stream, so that the output records (at the 1288 // record layer) have the correct version 1289 setVersion(sessionVersion); 1290 } 1291 1292 /* 1293 * Force use of the previous session ciphersuite, and 1294 * add the SCSV if enabled. 1295 */ 1296 if (!enableNewSession) { 1297 if (session == null) { 1298 throw new SSLHandshakeException( 1299 "Can't reuse existing SSL client session"); 1300 } 1301 1302 Collection<CipherSuite> cipherList = new ArrayList<>(2); 1303 cipherList.add(sessionSuite); 1304 if (!secureRenegotiation && 1305 cipherSuites.contains(CipherSuite.C_SCSV)) { 1306 cipherList.add(CipherSuite.C_SCSV); 1307 } // otherwise, renegotiation_info extension will be used 1308 1309 cipherSuites = new CipherSuiteList(cipherList); 1310 } 1311 } 1312 1313 if (session == null && !enableNewSession) { 1314 throw new SSLHandshakeException("No existing session to resume"); 1315 } 1316 1317 // exclude SCSV for secure renegotiation 1318 if (secureRenegotiation && cipherSuites.contains(CipherSuite.C_SCSV)) { 1319 Collection<CipherSuite> cipherList = 1320 new ArrayList<>(cipherSuites.size() - 1); 1321 for (CipherSuite suite : cipherSuites.collection()) { 1322 if (suite != CipherSuite.C_SCSV) { 1323 cipherList.add(suite); 1324 } 1325 } 1326 1327 cipherSuites = new CipherSuiteList(cipherList); 1328 } 1329 1330 // make sure there is a negotiable cipher suite. 1331 boolean negotiable = false; 1332 for (CipherSuite suite : cipherSuites.collection()) { 1333 if (isNegotiable(suite)) { 1334 negotiable = true; 1335 break; 1336 } 1337 } 1338 1339 if (!negotiable) { 1340 throw new SSLHandshakeException("No negotiable cipher suite"); 1341 } 1342 1343 // Not a TLS1.2+ handshake 1344 // For SSLv2Hello, HandshakeHash.reset() will be called, so we 1345 // cannot call HandshakeHash.protocolDetermined() here. As it does 1346 // not follow the spec that HandshakeHash.reset() can be only be 1347 // called before protocolDetermined. 1348 // if (maxProtocolVersion.v < ProtocolVersion.TLS12.v) { 1349 // handshakeHash.protocolDetermined(maxProtocolVersion); 1350 // } 1351 1352 // create the ClientHello message 1353 ClientHello clientHelloMessage = new ClientHello( 1354 sslContext.getSecureRandom(), maxProtocolVersion, 1355 sessionId, cipherSuites); 1356 1357 // add signature_algorithm extension 1358 if (maxProtocolVersion.v >= ProtocolVersion.TLS12.v) { 1359 // we will always send the signature_algorithm extension 1360 Collection<SignatureAndHashAlgorithm> localSignAlgs = 1361 getLocalSupportedSignAlgs(); 1362 if (localSignAlgs.isEmpty()) { 1363 throw new SSLHandshakeException( 1364 "No supported signature algorithm"); 1365 } 1366 1367 clientHelloMessage.addSignatureAlgorithmsExtension(localSignAlgs); 1368 } 1369 1370 // add server_name extension 1371 if (enableSNIExtension) { 1372 if (session != null) { 1373 requestedServerNames = session.getRequestedServerNames(); 1374 } else { 1375 requestedServerNames = serverNames; 1376 } 1377 1378 if (!requestedServerNames.isEmpty()) { 1379 clientHelloMessage.addSNIExtension(requestedServerNames); 1380 } 1381 } 1382 1383 // reset the client random cookie 1384 clnt_random = clientHelloMessage.clnt_random; 1385 1386 /* 1387 * need to set the renegotiation_info extension for: 1388 * 1: secure renegotiation 1389 * 2: initial handshake and no SCSV in the ClientHello 1390 * 3: insecure renegotiation and no SCSV in the ClientHello 1391 */ 1392 if (secureRenegotiation || 1393 !cipherSuites.contains(CipherSuite.C_SCSV)) { 1394 clientHelloMessage.addRenegotiationInfoExtension(clientVerifyData); 1395 } 1396 1397 return clientHelloMessage; 1398 } 1399 1400 /* 1401 * Fault detected during handshake. 1402 */ 1403 @Override 1404 void handshakeAlert(byte description) throws SSLProtocolException { 1405 String message = Alerts.alertDescription(description); 1406 1407 if (debug != null && Debug.isOn("handshake")) { 1408 System.out.println("SSL - handshake alert: " + message); 1409 } 1410 throw new SSLProtocolException("handshake alert: " + message); 1411 } 1412 1413 /* 1414 * Unless we are using an anonymous ciphersuite, the server always 1415 * sends a certificate message (for the CipherSuites we currently 1416 * support). The trust manager verifies the chain for us. 1417 */ 1418 private void serverCertificate(CertificateMsg mesg) throws IOException { 1419 if (debug != null && Debug.isOn("handshake")) { 1420 mesg.print(System.out); 1421 } 1422 X509Certificate[] peerCerts = mesg.getCertificateChain(); 1423 if (peerCerts.length == 0) { 1424 fatalSE(Alerts.alert_bad_certificate, "empty certificate chain"); 1425 } 1426 1427 // Allow server certificate change in client side during renegotiation 1428 // after a session-resumption abbreviated initial handshake? 1429 // 1430 // DO NOT need to check allowUnsafeServerCertChange here. We only 1431 // reserve server certificates when allowUnsafeServerCertChange is 1432 // flase. 1433 if (reservedServerCerts != null) { 1434 // It is not necessary to check the certificate update if endpoint 1435 // identification is enabled. 1436 String identityAlg = getEndpointIdentificationAlgorithmSE(); 1437 if ((identityAlg == null || identityAlg.length() == 0) && 1438 !isIdentityEquivalent(peerCerts[0], reservedServerCerts[0])) { 1439 1440 fatalSE(Alerts.alert_bad_certificate, 1441 "server certificate change is restricted " + 1442 "during renegotiation"); 1443 } 1444 } 1445 1446 // ask the trust manager to verify the chain 1447 X509TrustManager tm = sslContext.getX509TrustManager(); 1448 try { 1449 // find out the key exchange algorithm used 1450 // use "RSA" for non-ephemeral "RSA_EXPORT" 1451 String keyExchangeString; 1452 if (keyExchange == K_RSA_EXPORT && !serverKeyExchangeReceived) { 1453 keyExchangeString = K_RSA.name; 1454 } else { 1455 keyExchangeString = keyExchange.name; 1456 } 1457 1458 if (tm instanceof X509ExtendedTrustManager) { 1459 if (conn != null) { 1460 ((X509ExtendedTrustManager)tm).checkServerTrusted( 1461 peerCerts.clone(), 1462 keyExchangeString, 1463 conn); 1464 } else { 1465 ((X509ExtendedTrustManager)tm).checkServerTrusted( 1466 peerCerts.clone(), 1467 keyExchangeString, 1468 engine); 1469 } 1470 } else { 1471 // Unlikely to happen, because we have wrapped the old 1472 // X509TrustManager with the new X509ExtendedTrustManager. 1473 throw new CertificateException( 1474 "Improper X509TrustManager implementation"); 1475 } 1476 } catch (CertificateException e) { 1477 // This will throw an exception, so include the original error. 1478 fatalSE(Alerts.alert_certificate_unknown, e); 1479 } 1480 session.setPeerCertificates(peerCerts); 1481 } 1482 1483 /* 1484 * Whether the certificates can represent the same identity? 1485 * 1486 * The certificates can be used to represent the same identity: 1487 * 1. If the subject alternative names of IP address are present in 1488 * both certificates, they should be identical; otherwise, 1489 * 2. if the subject alternative names of DNS name are present in 1490 * both certificates, they should be identical; otherwise, 1491 * 3. if the subject fields are present in both certificates, the 1492 * certificate subjects and issuers should be identical. 1493 */ 1494 private static boolean isIdentityEquivalent(X509Certificate thisCert, 1495 X509Certificate prevCert) { 1496 if (thisCert.equals(prevCert)) { 1497 return true; 1498 } 1499 1500 // check the iPAddress field in subjectAltName extension 1501 Object thisIPAddress = getSubjectAltName(thisCert, 7); // 7: iPAddress 1502 Object prevIPAddress = getSubjectAltName(prevCert, 7); 1503 if (thisIPAddress != null && prevIPAddress!= null) { 1504 // only allow the exactly match 1505 return Objects.equals(thisIPAddress, prevIPAddress); 1506 } 1507 1508 // check the dNSName field in subjectAltName extension 1509 Object thisDNSName = getSubjectAltName(thisCert, 2); // 2: dNSName 1510 Object prevDNSName = getSubjectAltName(prevCert, 2); 1511 if (thisDNSName != null && prevDNSName!= null) { 1512 // only allow the exactly match 1513 return Objects.equals(thisDNSName, prevDNSName); 1514 } 1515 1516 // check the certificate subject and issuer 1517 X500Principal thisSubject = thisCert.getSubjectX500Principal(); 1518 X500Principal prevSubject = prevCert.getSubjectX500Principal(); 1519 X500Principal thisIssuer = thisCert.getIssuerX500Principal(); 1520 X500Principal prevIssuer = prevCert.getIssuerX500Principal(); 1521 if (!thisSubject.getName().isEmpty() && 1522 !prevSubject.getName().isEmpty() && 1523 thisSubject.equals(prevSubject) && 1524 thisIssuer.equals(prevIssuer)) { 1525 return true; 1526 } 1527 1528 return false; 1529 } 1530 1531 /* 1532 * Returns the subject alternative name of the specified type in the 1533 * subjectAltNames extension of a certificate. 1534 */ 1535 private static Object getSubjectAltName(X509Certificate cert, int type) { 1536 Collection<List<?>> subjectAltNames; 1537 1538 try { 1539 subjectAltNames = cert.getSubjectAlternativeNames(); 1540 } catch (CertificateParsingException cpe) { 1541 if (debug != null && Debug.isOn("handshake")) { 1542 System.out.println( 1543 "Attempt to obtain subjectAltNames extension failed!"); 1544 } 1545 return null; 1546 } 1547 1548 if (subjectAltNames != null) { 1549 for (List<?> subjectAltName : subjectAltNames) { 1550 int subjectAltNameType = (Integer)subjectAltName.get(0); 1551 if (subjectAltNameType == type) { 1552 return subjectAltName.get(1); 1553 } 1554 } 1555 } 1556 1557 return null; 1558 } 1559 }