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 this.serverFinished( 349 new Finished(protocolVersion, input, cipherSuite)); 350 break; 351 352 default: 353 throw new SSLProtocolException( 354 "Illegal client handshake msg, " + type); 355 } 356 357 // 358 // Move state machine forward if the message handling 359 // code didn't already do so 360 // 361 if (state < type) { 362 state = type; 363 } 364 } 365 366 /* 367 * Used by the server to kickstart negotiations -- this requests a 368 * "client hello" to renegotiate current cipher specs (e.g. maybe lots 369 * of data has been encrypted with the same keys, or the server needs 370 * the client to present a certificate). 371 */ 372 private void serverHelloRequest(HelloRequest mesg) throws IOException { 373 if (debug != null && Debug.isOn("handshake")) { 374 mesg.print(System.out); 375 } 376 377 // 378 // Could be (e.g. at connection setup) that we already 379 // sent the "client hello" but the server's not seen it. 380 // 381 if (state < HandshakeMessage.ht_client_hello) { 382 if (!secureRenegotiation && !allowUnsafeRenegotiation) { 383 // renegotiation is not allowed. 384 if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) { 385 // response with a no_renegotiation warning, 386 warningSE(Alerts.alert_no_renegotiation); 387 388 // invalidate the handshake so that the caller can 389 // dispose this object. 390 invalidated = true; 391 392 // If there is still unread block in the handshake 393 // input stream, it would be truncated with the disposal 394 // and the next handshake message will become incomplete. 395 // 396 // However, according to SSL/TLS specifications, no more 397 // handshake message should immediately follow ClientHello 398 // or HelloRequest. So just let it be. 399 } else { 400 // For SSLv3, send the handshake_failure fatal error. 401 // Note that SSLv3 does not define a no_renegotiation 402 // alert like TLSv1. However we cannot ignore the message 403 // simply, otherwise the other side was waiting for a 404 // response that would never come. 405 fatalSE(Alerts.alert_handshake_failure, 406 "Renegotiation is not allowed"); 407 } 408 } else { 409 if (!secureRenegotiation) { 410 if (debug != null && Debug.isOn("handshake")) { 411 System.out.println( 412 "Warning: continue with insecure renegotiation"); 413 } 414 } 415 kickstart(); 416 } 417 } 418 } 419 420 421 /* 422 * Server chooses session parameters given options created by the 423 * client -- basically, cipher options, session id, and someday a 424 * set of compression options. 425 * 426 * There are two branches of the state machine, decided by the 427 * details of this message. One is the "fast" handshake, where we 428 * can resume the pre-existing session we asked resume. The other 429 * is a more expensive "full" handshake, with key exchange and 430 * probably authentication getting done. 431 */ 432 private void serverHello(ServerHello mesg) throws IOException { 433 serverKeyExchangeReceived = false; 434 if (debug != null && Debug.isOn("handshake")) { 435 mesg.print(System.out); 436 } 437 438 // check if the server selected protocol version is OK for us 439 ProtocolVersion mesgVersion = mesg.protocolVersion; 440 if (!isNegotiable(mesgVersion)) { 441 throw new SSLHandshakeException( 442 "Server chose " + mesgVersion + 443 ", but that protocol version is not enabled or not supported " + 444 "by the client."); 445 } 446 447 handshakeHash.protocolDetermined(mesgVersion); 448 449 // Set protocolVersion and propagate to SSLSocket and the 450 // Handshake streams 451 setVersion(mesgVersion); 452 453 // check the "renegotiation_info" extension 454 RenegotiationInfoExtension serverHelloRI = (RenegotiationInfoExtension) 455 mesg.extensions.get(ExtensionType.EXT_RENEGOTIATION_INFO); 456 if (serverHelloRI != null) { 457 if (isInitialHandshake) { 458 // verify the length of the "renegotiated_connection" field 459 if (!serverHelloRI.isEmpty()) { 460 // abort the handshake with a fatal handshake_failure alert 461 fatalSE(Alerts.alert_handshake_failure, 462 "The renegotiation_info field is not empty"); 463 } 464 465 secureRenegotiation = true; 466 } else { 467 // For a legacy renegotiation, the client MUST verify that 468 // it does not contain the "renegotiation_info" extension. 469 if (!secureRenegotiation) { 470 fatalSE(Alerts.alert_handshake_failure, 471 "Unexpected renegotiation indication extension"); 472 } 473 474 // verify the client_verify_data and server_verify_data values 475 byte[] verifyData = 476 new byte[clientVerifyData.length + serverVerifyData.length]; 477 System.arraycopy(clientVerifyData, 0, verifyData, 478 0, clientVerifyData.length); 479 System.arraycopy(serverVerifyData, 0, verifyData, 480 clientVerifyData.length, serverVerifyData.length); 481 if (!Arrays.equals(verifyData, 482 serverHelloRI.getRenegotiatedConnection())) { 483 fatalSE(Alerts.alert_handshake_failure, 484 "Incorrect verify data in ServerHello " + 485 "renegotiation_info message"); 486 } 487 } 488 } else { 489 // no renegotiation indication extension 490 if (isInitialHandshake) { 491 if (!allowLegacyHelloMessages) { 492 // abort the handshake with a fatal handshake_failure alert 493 fatalSE(Alerts.alert_handshake_failure, 494 "Failed to negotiate the use of secure renegotiation"); 495 } 496 497 secureRenegotiation = false; 498 if (debug != null && Debug.isOn("handshake")) { 499 System.out.println("Warning: No renegotiation " + 500 "indication extension in ServerHello"); 501 } 502 } else { 503 // For a secure renegotiation, the client must abort the 504 // handshake if no "renegotiation_info" extension is present. 505 if (secureRenegotiation) { 506 fatalSE(Alerts.alert_handshake_failure, 507 "No renegotiation indication extension"); 508 } 509 510 // we have already allowed unsafe renegotation before request 511 // the renegotiation. 512 } 513 } 514 515 // 516 // Save server nonce, we always use it to compute connection 517 // keys and it's also used to create the master secret if we're 518 // creating a new session (i.e. in the full handshake). 519 // 520 svr_random = mesg.svr_random; 521 522 if (isNegotiable(mesg.cipherSuite) == false) { 523 fatalSE(Alerts.alert_illegal_parameter, 524 "Server selected improper ciphersuite " + mesg.cipherSuite); 525 } 526 527 setCipherSuite(mesg.cipherSuite); 528 if (protocolVersion.v >= ProtocolVersion.TLS12.v) { 529 handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg()); 530 } 531 532 if (mesg.compression_method != 0) { 533 fatalSE(Alerts.alert_illegal_parameter, 534 "compression type not supported, " 535 + mesg.compression_method); 536 // NOTREACHED 537 } 538 539 // so far so good, let's look at the session 540 if (session != null) { 541 // we tried to resume, let's see what the server decided 542 if (session.getSessionId().equals(mesg.sessionId)) { 543 // server resumed the session, let's make sure everything 544 // checks out 545 546 // Verify that the session ciphers are unchanged. 547 CipherSuite sessionSuite = session.getSuite(); 548 if (cipherSuite != sessionSuite) { 549 throw new SSLProtocolException 550 ("Server returned wrong cipher suite for session"); 551 } 552 553 // verify protocol version match 554 ProtocolVersion sessionVersion = session.getProtocolVersion(); 555 if (protocolVersion != sessionVersion) { 556 throw new SSLProtocolException 557 ("Server resumed session with wrong protocol version"); 558 } 559 560 // validate subject identity 561 if (sessionSuite.keyExchange == K_KRB5 || 562 sessionSuite.keyExchange == K_KRB5_EXPORT) { 563 Principal localPrincipal = session.getLocalPrincipal(); 564 565 Subject subject = null; 566 try { 567 subject = AccessController.doPrivileged( 568 new PrivilegedExceptionAction<Subject>() { 569 @Override 570 public Subject run() throws Exception { 571 return Krb5Helper.getClientSubject(getAccSE()); 572 }}); 573 } catch (PrivilegedActionException e) { 574 subject = null; 575 if (debug != null && Debug.isOn("session")) { 576 System.out.println("Attempt to obtain" + 577 " subject failed!"); 578 } 579 } 580 581 if (subject != null) { 582 // Eliminate dependency on KerberosPrincipal 583 Set<Principal> principals = 584 subject.getPrincipals(Principal.class); 585 if (!principals.contains(localPrincipal)) { 586 throw new SSLProtocolException("Server resumed" + 587 " session with wrong subject identity"); 588 } else { 589 if (debug != null && Debug.isOn("session")) 590 System.out.println("Subject identity is same"); 591 } 592 } else { 593 if (debug != null && Debug.isOn("session")) 594 System.out.println("Kerberos credentials are not" + 595 " present in the current Subject; check if " + 596 " javax.security.auth.useSubjectAsCreds" + 597 " system property has been set to false"); 598 throw new SSLProtocolException 599 ("Server resumed session with no subject"); 600 } 601 } 602 603 // looks fine; resume it, and update the state machine. 604 resumingSession = true; 605 state = HandshakeMessage.ht_finished - 1; 606 calculateConnectionKeys(session.getMasterSecret()); 607 if (debug != null && Debug.isOn("session")) { 608 System.out.println("%% Server resumed " + session); 609 } 610 } else { 611 // we wanted to resume, but the server refused 612 session = null; 613 if (!enableNewSession) { 614 throw new SSLException("New session creation is disabled"); 615 } 616 } 617 } 618 619 if (resumingSession && session != null) { 620 setHandshakeSessionSE(session); 621 // Reserve the handshake state if this is a session-resumption 622 // abbreviated initial handshake. 623 if (isInitialHandshake) { 624 session.setAsSessionResumption(true); 625 } 626 627 return; 628 } 629 630 // check extensions 631 for (HelloExtension ext : mesg.extensions.list()) { 632 ExtensionType type = ext.type; 633 if (type == ExtensionType.EXT_SERVER_NAME) { 634 serverNamesAccepted = true; 635 } else if ((type != ExtensionType.EXT_ELLIPTIC_CURVES) 636 && (type != ExtensionType.EXT_EC_POINT_FORMATS) 637 && (type != ExtensionType.EXT_SERVER_NAME) 638 && (type != ExtensionType.EXT_RENEGOTIATION_INFO)) { 639 fatalSE(Alerts.alert_unsupported_extension, 640 "Server sent an unsupported extension: " + type); 641 } 642 } 643 644 // Create a new session, we need to do the full handshake 645 session = new SSLSessionImpl(protocolVersion, cipherSuite, 646 getLocalSupportedSignAlgs(), 647 mesg.sessionId, getHostSE(), getPortSE()); 648 session.setRequestedServerNames(requestedServerNames); 649 setHandshakeSessionSE(session); 650 if (debug != null && Debug.isOn("handshake")) { 651 System.out.println("** " + cipherSuite); 652 } 653 } 654 655 /* 656 * Server's own key was either a signing-only key, or was too 657 * large for export rules ... this message holds an ephemeral 658 * RSA key to use for key exchange. 659 */ 660 private void serverKeyExchange(RSA_ServerKeyExchange mesg) 661 throws IOException, GeneralSecurityException { 662 if (debug != null && Debug.isOn("handshake")) { 663 mesg.print(System.out); 664 } 665 if (!mesg.verify(serverKey, clnt_random, svr_random)) { 666 fatalSE(Alerts.alert_handshake_failure, 667 "server key exchange invalid"); 668 // NOTREACHED 669 } 670 ephemeralServerKey = mesg.getPublicKey(); 671 } 672 673 674 /* 675 * Diffie-Hellman key exchange. We save the server public key and 676 * our own D-H algorithm object so we can defer key calculations 677 * until after we've sent the client key exchange message (which 678 * gives client and server some useful parallelism). 679 */ 680 private void serverKeyExchange(DH_ServerKeyExchange mesg) 681 throws IOException { 682 if (debug != null && Debug.isOn("handshake")) { 683 mesg.print(System.out); 684 } 685 dh = new DHCrypt(mesg.getModulus(), mesg.getBase(), 686 sslContext.getSecureRandom()); 687 serverDH = mesg.getServerPublicKey(); 688 } 689 690 private void serverKeyExchange(ECDH_ServerKeyExchange mesg) 691 throws IOException { 692 if (debug != null && Debug.isOn("handshake")) { 693 mesg.print(System.out); 694 } 695 ECPublicKey key = mesg.getPublicKey(); 696 ecdh = new ECDHCrypt(key.getParams(), sslContext.getSecureRandom()); 697 ephemeralServerKey = key; 698 } 699 700 /* 701 * The server's "Hello Done" message is the client's sign that 702 * it's time to do all the hard work. 703 */ 704 private void serverHelloDone(ServerHelloDone mesg) throws IOException { 705 if (debug != null && Debug.isOn("handshake")) { 706 mesg.print(System.out); 707 } 708 /* 709 * Always make sure the input has been digested before we 710 * start emitting data, to ensure the hashes are correctly 711 * computed for the Finished and CertificateVerify messages 712 * which we send (here). 713 */ 714 input.digestNow(); 715 716 /* 717 * FIRST ... if requested, send an appropriate Certificate chain 718 * to authenticate the client, and remember the associated private 719 * key to sign the CertificateVerify message. 720 */ 721 PrivateKey signingKey = null; 722 723 if (certRequest != null) { 724 X509ExtendedKeyManager km = sslContext.getX509KeyManager(); 725 726 ArrayList<String> keytypesTmp = new ArrayList<>(4); 727 728 for (int i = 0; i < certRequest.types.length; i++) { 729 String typeName; 730 731 switch (certRequest.types[i]) { 732 case CertificateRequest.cct_rsa_sign: 733 typeName = "RSA"; 734 break; 735 736 case CertificateRequest.cct_dss_sign: 737 typeName = "DSA"; 738 break; 739 740 case CertificateRequest.cct_ecdsa_sign: 741 // ignore if we do not have EC crypto available 742 typeName = JsseJce.isEcAvailable() ? "EC" : null; 743 break; 744 745 // Fixed DH/ECDH client authentication not supported 746 case CertificateRequest.cct_rsa_fixed_dh: 747 case CertificateRequest.cct_dss_fixed_dh: 748 case CertificateRequest.cct_rsa_fixed_ecdh: 749 case CertificateRequest.cct_ecdsa_fixed_ecdh: 750 // Any other values (currently not used in TLS) 751 case CertificateRequest.cct_rsa_ephemeral_dh: 752 case CertificateRequest.cct_dss_ephemeral_dh: 753 default: 754 typeName = null; 755 break; 756 } 757 758 if ((typeName != null) && (!keytypesTmp.contains(typeName))) { 759 keytypesTmp.add(typeName); 760 } 761 } 762 763 String alias = null; 764 int keytypesTmpSize = keytypesTmp.size(); 765 if (keytypesTmpSize != 0) { 766 String keytypes[] = 767 keytypesTmp.toArray(new String[keytypesTmpSize]); 768 769 if (conn != null) { 770 alias = km.chooseClientAlias(keytypes, 771 certRequest.getAuthorities(), conn); 772 } else { 773 alias = km.chooseEngineClientAlias(keytypes, 774 certRequest.getAuthorities(), engine); 775 } 776 } 777 778 CertificateMsg m1 = null; 779 if (alias != null) { 780 X509Certificate[] certs = km.getCertificateChain(alias); 781 if ((certs != null) && (certs.length != 0)) { 782 PublicKey publicKey = certs[0].getPublicKey(); 783 // for EC, make sure we use a supported named curve 784 if (publicKey instanceof ECPublicKey) { 785 ECParameterSpec params = 786 ((ECPublicKey)publicKey).getParams(); 787 int index = 788 SupportedEllipticCurvesExtension.getCurveIndex( 789 params); 790 if (!SupportedEllipticCurvesExtension.isSupported( 791 index)) { 792 publicKey = null; 793 } 794 } 795 if (publicKey != null) { 796 m1 = new CertificateMsg(certs); 797 signingKey = km.getPrivateKey(alias); 798 session.setLocalPrivateKey(signingKey); 799 session.setLocalCertificates(certs); 800 } 801 } 802 } 803 if (m1 == null) { 804 // 805 // No appropriate cert was found ... report this to the 806 // server. For SSLv3, send the no_certificate alert; 807 // TLS uses an empty cert chain instead. 808 // 809 if (protocolVersion.v >= ProtocolVersion.TLS10.v) { 810 m1 = new CertificateMsg(new X509Certificate [0]); 811 } else { 812 warningSE(Alerts.alert_no_certificate); 813 } 814 } 815 816 // 817 // At last ... send any client certificate chain. 818 // 819 if (m1 != null) { 820 if (debug != null && Debug.isOn("handshake")) { 821 m1.print(System.out); 822 } 823 m1.write(output); 824 } 825 } 826 827 /* 828 * SECOND ... send the client key exchange message. The 829 * procedure used is a function of the cipher suite selected; 830 * one is always needed. 831 */ 832 HandshakeMessage m2; 833 834 switch (keyExchange) { 835 836 case K_RSA: 837 case K_RSA_EXPORT: 838 if (serverKey == null) { 839 throw new SSLProtocolException 840 ("Server did not send certificate message"); 841 } 842 843 if (!(serverKey instanceof RSAPublicKey)) { 844 throw new SSLProtocolException 845 ("Server certificate does not include an RSA key"); 846 } 847 848 /* 849 * For RSA key exchange, we randomly generate a new 850 * pre-master secret and encrypt it with the server's 851 * public key. Then we save that pre-master secret 852 * so that we can calculate the keying data later; 853 * it's a performance speedup not to do that until 854 * the client's waiting for the server response, but 855 * more of a speedup for the D-H case. 856 * 857 * If the RSA_EXPORT scheme is active, when the public 858 * key in the server certificate is less than or equal 859 * to 512 bits in length, use the cert's public key, 860 * otherwise, the ephemeral one. 861 */ 862 PublicKey key; 863 if (keyExchange == K_RSA) { 864 key = serverKey; 865 } else { // K_RSA_EXPORT 866 if (JsseJce.getRSAKeyLength(serverKey) <= 512) { 867 // extraneous ephemeralServerKey check done 868 // above in processMessage() 869 key = serverKey; 870 } else { 871 if (ephemeralServerKey == null) { 872 throw new SSLProtocolException("Server did not send" + 873 " a RSA_EXPORT Server Key Exchange message"); 874 } 875 key = ephemeralServerKey; 876 } 877 } 878 879 m2 = new RSAClientKeyExchange(protocolVersion, maxProtocolVersion, 880 sslContext.getSecureRandom(), key); 881 break; 882 case K_DH_RSA: 883 case K_DH_DSS: 884 /* 885 * For DH Key exchange, we only need to make sure the server 886 * knows our public key, so we calculate the same pre-master 887 * secret. 888 * 889 * For certs that had DH keys in them, we send an empty 890 * handshake message (no key) ... we flag this case by 891 * passing a null "dhPublic" value. 892 * 893 * Otherwise we send ephemeral DH keys, unsigned. 894 */ 895 // if (useDH_RSA || useDH_DSS) 896 m2 = new DHClientKeyExchange(); 897 break; 898 case K_DHE_RSA: 899 case K_DHE_DSS: 900 case K_DH_ANON: 901 if (dh == null) { 902 throw new SSLProtocolException 903 ("Server did not send a DH Server Key Exchange message"); 904 } 905 m2 = new DHClientKeyExchange(dh.getPublicKey()); 906 break; 907 case K_ECDHE_RSA: 908 case K_ECDHE_ECDSA: 909 case K_ECDH_ANON: 910 if (ecdh == null) { 911 throw new SSLProtocolException 912 ("Server did not send a ECDH Server Key Exchange message"); 913 } 914 m2 = new ECDHClientKeyExchange(ecdh.getPublicKey()); 915 break; 916 case K_ECDH_RSA: 917 case K_ECDH_ECDSA: 918 if (serverKey == null) { 919 throw new SSLProtocolException 920 ("Server did not send certificate message"); 921 } 922 if (serverKey instanceof ECPublicKey == false) { 923 throw new SSLProtocolException 924 ("Server certificate does not include an EC key"); 925 } 926 ECParameterSpec params = ((ECPublicKey)serverKey).getParams(); 927 ecdh = new ECDHCrypt(params, sslContext.getSecureRandom()); 928 m2 = new ECDHClientKeyExchange(ecdh.getPublicKey()); 929 break; 930 case K_KRB5: 931 case K_KRB5_EXPORT: 932 String sniHostname = null; 933 for (SNIServerName serverName : requestedServerNames) { 934 if (serverName instanceof SNIHostName) { 935 sniHostname = ((SNIHostName) serverName).getAsciiName(); 936 break; 937 } 938 } 939 940 KerberosClientKeyExchange kerberosMsg = null; 941 if (sniHostname != null) { 942 // use first requested SNI hostname 943 try { 944 kerberosMsg = new KerberosClientKeyExchange( 945 sniHostname, getAccSE(), protocolVersion, 946 sslContext.getSecureRandom()); 947 } catch(IOException e) { 948 if (serverNamesAccepted) { 949 // server accepted requested SNI hostname, 950 // so it must be used 951 throw e; 952 } 953 // fallback to using hostname 954 if (debug != null && Debug.isOn("handshake")) { 955 System.out.println( 956 "Warning, cannot use Server Name Indication: " 957 + e.getMessage()); 958 } 959 } 960 } 961 962 if (kerberosMsg == null) { 963 String hostname = getHostSE(); 964 if (hostname == null) { 965 throw new IOException("Hostname is required" + 966 " to use Kerberos cipher suites"); 967 } 968 kerberosMsg = new KerberosClientKeyExchange( 969 hostname, getAccSE(), protocolVersion, 970 sslContext.getSecureRandom()); 971 } 972 973 // Record the principals involved in exchange 974 session.setPeerPrincipal(kerberosMsg.getPeerPrincipal()); 975 session.setLocalPrincipal(kerberosMsg.getLocalPrincipal()); 976 m2 = kerberosMsg; 977 break; 978 default: 979 // somethings very wrong 980 throw new RuntimeException 981 ("Unsupported key exchange: " + keyExchange); 982 } 983 if (debug != null && Debug.isOn("handshake")) { 984 m2.print(System.out); 985 } 986 m2.write(output); 987 988 989 /* 990 * THIRD, send a "change_cipher_spec" record followed by the 991 * "Finished" message. We flush the messages we've queued up, to 992 * get concurrency between client and server. The concurrency is 993 * useful as we calculate the master secret, which is needed both 994 * to compute the "Finished" message, and to compute the keys used 995 * to protect all records following the change_cipher_spec. 996 */ 997 998 output.doHashes(); 999 output.flush(); 1000 1001 /* 1002 * We deferred calculating the master secret and this connection's 1003 * keying data; we do it now. Deferring this calculation is good 1004 * from a performance point of view, since it lets us do it during 1005 * some time that network delays and the server's own calculations 1006 * would otherwise cause to be "dead" in the critical path. 1007 */ 1008 SecretKey preMasterSecret; 1009 switch (keyExchange) { 1010 case K_RSA: 1011 case K_RSA_EXPORT: 1012 preMasterSecret = ((RSAClientKeyExchange)m2).preMaster; 1013 break; 1014 case K_KRB5: 1015 case K_KRB5_EXPORT: 1016 byte[] secretBytes = 1017 ((KerberosClientKeyExchange)m2).getUnencryptedPreMasterSecret(); 1018 preMasterSecret = new SecretKeySpec(secretBytes, 1019 "TlsPremasterSecret"); 1020 break; 1021 case K_DHE_RSA: 1022 case K_DHE_DSS: 1023 case K_DH_ANON: 1024 preMasterSecret = dh.getAgreedSecret(serverDH, true); 1025 break; 1026 case K_ECDHE_RSA: 1027 case K_ECDHE_ECDSA: 1028 case K_ECDH_ANON: 1029 preMasterSecret = ecdh.getAgreedSecret(ephemeralServerKey); 1030 break; 1031 case K_ECDH_RSA: 1032 case K_ECDH_ECDSA: 1033 preMasterSecret = ecdh.getAgreedSecret(serverKey); 1034 break; 1035 default: 1036 throw new IOException("Internal error: unknown key exchange " 1037 + keyExchange); 1038 } 1039 1040 calculateKeys(preMasterSecret, null); 1041 1042 /* 1043 * FOURTH, if we sent a Certificate, we need to send a signed 1044 * CertificateVerify (unless the key in the client's certificate 1045 * was a Diffie-Hellman key).). 1046 * 1047 * This uses a hash of the previous handshake messages ... either 1048 * a nonfinal one (if the particular implementation supports it) 1049 * or else using the third element in the arrays of hashes being 1050 * computed. 1051 */ 1052 if (signingKey != null) { 1053 CertificateVerify m3; 1054 try { 1055 SignatureAndHashAlgorithm preferableSignatureAlgorithm = null; 1056 if (protocolVersion.v >= ProtocolVersion.TLS12.v) { 1057 preferableSignatureAlgorithm = 1058 SignatureAndHashAlgorithm.getPreferableAlgorithm( 1059 peerSupportedSignAlgs, signingKey.getAlgorithm(), 1060 signingKey); 1061 1062 if (preferableSignatureAlgorithm == null) { 1063 throw new SSLHandshakeException( 1064 "No supported signature algorithm"); 1065 } 1066 1067 String hashAlg = 1068 SignatureAndHashAlgorithm.getHashAlgorithmName( 1069 preferableSignatureAlgorithm); 1070 if (hashAlg == null || hashAlg.length() == 0) { 1071 throw new SSLHandshakeException( 1072 "No supported hash algorithm"); 1073 } 1074 } 1075 1076 m3 = new CertificateVerify(protocolVersion, handshakeHash, 1077 signingKey, session.getMasterSecret(), 1078 sslContext.getSecureRandom(), 1079 preferableSignatureAlgorithm); 1080 } catch (GeneralSecurityException e) { 1081 fatalSE(Alerts.alert_handshake_failure, 1082 "Error signing certificate verify", e); 1083 // NOTREACHED, make compiler happy 1084 m3 = null; 1085 } 1086 if (debug != null && Debug.isOn("handshake")) { 1087 m3.print(System.out); 1088 } 1089 m3.write(output); 1090 output.doHashes(); 1091 } 1092 1093 /* 1094 * OK, that's that! 1095 */ 1096 sendChangeCipherAndFinish(false); 1097 } 1098 1099 1100 /* 1101 * "Finished" is the last handshake message sent. If we got this 1102 * far, the MAC has been validated post-decryption. We validate 1103 * the two hashes here as an additional sanity check, protecting 1104 * the handshake against various active attacks. 1105 */ 1106 private void serverFinished(Finished mesg) throws IOException { 1107 if (debug != null && Debug.isOn("handshake")) { 1108 mesg.print(System.out); 1109 } 1110 1111 boolean verified = mesg.verify(handshakeHash, Finished.SERVER, 1112 session.getMasterSecret()); 1113 1114 if (!verified) { 1115 fatalSE(Alerts.alert_illegal_parameter, 1116 "server 'finished' message doesn't verify"); 1117 // NOTREACHED 1118 } 1119 1120 /* 1121 * save server verify data for secure renegotiation 1122 */ 1123 if (secureRenegotiation) { 1124 serverVerifyData = mesg.getVerifyData(); 1125 } 1126 1127 /* 1128 * Reset the handshake state if this is not an initial handshake. 1129 */ 1130 if (!isInitialHandshake) { 1131 session.setAsSessionResumption(false); 1132 } 1133 1134 /* 1135 * OK, it verified. If we're doing the fast handshake, add that 1136 * "Finished" message to the hash of handshake messages, then send 1137 * our own change_cipher_spec and Finished message for the server 1138 * to verify in turn. These are the last handshake messages. 1139 * 1140 * In any case, update the session cache. We're done handshaking, 1141 * so there are no threats any more associated with partially 1142 * completed handshakes. 1143 */ 1144 if (resumingSession) { 1145 input.digestNow(); 1146 sendChangeCipherAndFinish(true); 1147 } 1148 session.setLastAccessedTime(System.currentTimeMillis()); 1149 1150 if (!resumingSession) { 1151 if (session.isRejoinable()) { 1152 ((SSLSessionContextImpl) sslContext 1153 .engineGetClientSessionContext()) 1154 .put(session); 1155 if (debug != null && Debug.isOn("session")) { 1156 System.out.println("%% Cached client session: " + session); 1157 } 1158 } else if (debug != null && Debug.isOn("session")) { 1159 System.out.println( 1160 "%% Didn't cache non-resumable client session: " 1161 + session); 1162 } 1163 } 1164 } 1165 1166 1167 /* 1168 * Send my change-cipher-spec and Finished message ... done as the 1169 * last handshake act in either the short or long sequences. In 1170 * the short one, we've already seen the server's Finished; in the 1171 * long one, we wait for it now. 1172 */ 1173 private void sendChangeCipherAndFinish(boolean finishedTag) 1174 throws IOException { 1175 Finished mesg = new Finished(protocolVersion, handshakeHash, 1176 Finished.CLIENT, session.getMasterSecret(), cipherSuite); 1177 1178 /* 1179 * Send the change_cipher_spec message, then the Finished message 1180 * which we just calculated (and protected using the keys we just 1181 * calculated). Server responds with its Finished message, except 1182 * in the "fast handshake" (resume session) case. 1183 */ 1184 sendChangeCipherSpec(mesg, finishedTag); 1185 1186 /* 1187 * save client verify data for secure renegotiation 1188 */ 1189 if (secureRenegotiation) { 1190 clientVerifyData = mesg.getVerifyData(); 1191 } 1192 1193 /* 1194 * Update state machine so server MUST send 'finished' next. 1195 * (In "long" handshake case; in short case, we're responding 1196 * to its message.) 1197 */ 1198 state = HandshakeMessage.ht_finished - 1; 1199 } 1200 1201 1202 /* 1203 * Returns a ClientHello message to kickstart renegotiations 1204 */ 1205 @Override 1206 HandshakeMessage getKickstartMessage() throws SSLException { 1207 // session ID of the ClientHello message 1208 SessionId sessionId = SSLSessionImpl.nullSession.getSessionId(); 1209 1210 // a list of cipher suites sent by the client 1211 CipherSuiteList cipherSuites = getActiveCipherSuites(); 1212 1213 // set the max protocol version this client is supporting. 1214 maxProtocolVersion = protocolVersion; 1215 1216 // 1217 // Try to resume an existing session. This might be mandatory, 1218 // given certain API options. 1219 // 1220 session = ((SSLSessionContextImpl)sslContext 1221 .engineGetClientSessionContext()) 1222 .get(getHostSE(), getPortSE()); 1223 if (debug != null && Debug.isOn("session")) { 1224 if (session != null) { 1225 System.out.println("%% Client cached " 1226 + session 1227 + (session.isRejoinable() ? "" : " (not rejoinable)")); 1228 } else { 1229 System.out.println("%% No cached client session"); 1230 } 1231 } 1232 if (session != null) { 1233 // If unsafe server certificate change is not allowed, reserve 1234 // current server certificates if the previous handshake is a 1235 // session-resumption abbreviated initial handshake. 1236 if (!allowUnsafeServerCertChange && session.isSessionResumption()) { 1237 try { 1238 // If existing, peer certificate chain cannot be null. 1239 reservedServerCerts = 1240 (X509Certificate[])session.getPeerCertificates(); 1241 } catch (SSLPeerUnverifiedException puve) { 1242 // Maybe not certificate-based, ignore the exception. 1243 } 1244 } 1245 1246 if (!session.isRejoinable()) { 1247 session = null; 1248 } 1249 } 1250 1251 if (session != null) { 1252 CipherSuite sessionSuite = session.getSuite(); 1253 ProtocolVersion sessionVersion = session.getProtocolVersion(); 1254 if (isNegotiable(sessionSuite) == false) { 1255 if (debug != null && Debug.isOn("session")) { 1256 System.out.println("%% can't resume, unavailable cipher"); 1257 } 1258 session = null; 1259 } 1260 1261 if ((session != null) && !isNegotiable(sessionVersion)) { 1262 if (debug != null && Debug.isOn("session")) { 1263 System.out.println("%% can't resume, protocol disabled"); 1264 } 1265 session = null; 1266 } 1267 1268 if (session != null) { 1269 if (debug != null) { 1270 if (Debug.isOn("handshake") || Debug.isOn("session")) { 1271 System.out.println("%% Try resuming " + session 1272 + " from port " + getLocalPortSE()); 1273 } 1274 } 1275 1276 sessionId = session.getSessionId(); 1277 maxProtocolVersion = sessionVersion; 1278 1279 // Update SSL version number in underlying SSL socket and 1280 // handshake output stream, so that the output records (at the 1281 // record layer) have the correct version 1282 setVersion(sessionVersion); 1283 } 1284 1285 /* 1286 * Force use of the previous session ciphersuite, and 1287 * add the SCSV if enabled. 1288 */ 1289 if (!enableNewSession) { 1290 if (session == null) { 1291 throw new SSLHandshakeException( 1292 "Can't reuse existing SSL client session"); 1293 } 1294 1295 Collection<CipherSuite> cipherList = new ArrayList<>(2); 1296 cipherList.add(sessionSuite); 1297 if (!secureRenegotiation && 1298 cipherSuites.contains(CipherSuite.C_SCSV)) { 1299 cipherList.add(CipherSuite.C_SCSV); 1300 } // otherwise, renegotiation_info extension will be used 1301 1302 cipherSuites = new CipherSuiteList(cipherList); 1303 } 1304 } 1305 1306 if (session == null && !enableNewSession) { 1307 throw new SSLHandshakeException("No existing session to resume"); 1308 } 1309 1310 // exclude SCSV for secure renegotiation 1311 if (secureRenegotiation && cipherSuites.contains(CipherSuite.C_SCSV)) { 1312 Collection<CipherSuite> cipherList = 1313 new ArrayList<>(cipherSuites.size() - 1); 1314 for (CipherSuite suite : cipherSuites.collection()) { 1315 if (suite != CipherSuite.C_SCSV) { 1316 cipherList.add(suite); 1317 } 1318 } 1319 1320 cipherSuites = new CipherSuiteList(cipherList); 1321 } 1322 1323 // make sure there is a negotiable cipher suite. 1324 boolean negotiable = false; 1325 for (CipherSuite suite : cipherSuites.collection()) { 1326 if (isNegotiable(suite)) { 1327 negotiable = true; 1328 break; 1329 } 1330 } 1331 1332 if (!negotiable) { 1333 throw new SSLHandshakeException("No negotiable cipher suite"); 1334 } 1335 1336 // Not a TLS1.2+ handshake 1337 // For SSLv2Hello, HandshakeHash.reset() will be called, so we 1338 // cannot call HandshakeHash.protocolDetermined() here. As it does 1339 // not follow the spec that HandshakeHash.reset() can be only be 1340 // called before protocolDetermined. 1341 // if (maxProtocolVersion.v < ProtocolVersion.TLS12.v) { 1342 // handshakeHash.protocolDetermined(maxProtocolVersion); 1343 // } 1344 1345 // create the ClientHello message 1346 ClientHello clientHelloMessage = new ClientHello( 1347 sslContext.getSecureRandom(), maxProtocolVersion, 1348 sessionId, cipherSuites); 1349 1350 // add signature_algorithm extension 1351 if (maxProtocolVersion.v >= ProtocolVersion.TLS12.v) { 1352 // we will always send the signature_algorithm extension 1353 Collection<SignatureAndHashAlgorithm> localSignAlgs = 1354 getLocalSupportedSignAlgs(); 1355 if (localSignAlgs.isEmpty()) { 1356 throw new SSLHandshakeException( 1357 "No supported signature algorithm"); 1358 } 1359 1360 clientHelloMessage.addSignatureAlgorithmsExtension(localSignAlgs); 1361 } 1362 1363 // add server_name extension 1364 if (enableSNIExtension) { 1365 if (session != null) { 1366 requestedServerNames = session.getRequestedServerNames(); 1367 } else { 1368 requestedServerNames = serverNames; 1369 } 1370 1371 if (!requestedServerNames.isEmpty()) { 1372 clientHelloMessage.addSNIExtension(requestedServerNames); 1373 } 1374 } 1375 1376 // reset the client random cookie 1377 clnt_random = clientHelloMessage.clnt_random; 1378 1379 /* 1380 * need to set the renegotiation_info extension for: 1381 * 1: secure renegotiation 1382 * 2: initial handshake and no SCSV in the ClientHello 1383 * 3: insecure renegotiation and no SCSV in the ClientHello 1384 */ 1385 if (secureRenegotiation || 1386 !cipherSuites.contains(CipherSuite.C_SCSV)) { 1387 clientHelloMessage.addRenegotiationInfoExtension(clientVerifyData); 1388 } 1389 1390 return clientHelloMessage; 1391 } 1392 1393 /* 1394 * Fault detected during handshake. 1395 */ 1396 @Override 1397 void handshakeAlert(byte description) throws SSLProtocolException { 1398 String message = Alerts.alertDescription(description); 1399 1400 if (debug != null && Debug.isOn("handshake")) { 1401 System.out.println("SSL - handshake alert: " + message); 1402 } 1403 throw new SSLProtocolException("handshake alert: " + message); 1404 } 1405 1406 /* 1407 * Unless we are using an anonymous ciphersuite, the server always 1408 * sends a certificate message (for the CipherSuites we currently 1409 * support). The trust manager verifies the chain for us. 1410 */ 1411 private void serverCertificate(CertificateMsg mesg) throws IOException { 1412 if (debug != null && Debug.isOn("handshake")) { 1413 mesg.print(System.out); 1414 } 1415 X509Certificate[] peerCerts = mesg.getCertificateChain(); 1416 if (peerCerts.length == 0) { 1417 fatalSE(Alerts.alert_bad_certificate, "empty certificate chain"); 1418 } 1419 1420 // Allow server certificate change in client side during renegotiation 1421 // after a session-resumption abbreviated initial handshake? 1422 // 1423 // DO NOT need to check allowUnsafeServerCertChange here. We only 1424 // reserve server certificates when allowUnsafeServerCertChange is 1425 // flase. 1426 if (reservedServerCerts != null) { 1427 // It is not necessary to check the certificate update if endpoint 1428 // identification is enabled. 1429 String identityAlg = getEndpointIdentificationAlgorithmSE(); 1430 if ((identityAlg == null || identityAlg.length() == 0) && 1431 !isIdentityEquivalent(peerCerts[0], reservedServerCerts[0])) { 1432 1433 fatalSE(Alerts.alert_bad_certificate, 1434 "server certificate change is restricted " + 1435 "during renegotiation"); 1436 } 1437 } 1438 1439 // ask the trust manager to verify the chain 1440 X509TrustManager tm = sslContext.getX509TrustManager(); 1441 try { 1442 // find out the key exchange algorithm used 1443 // use "RSA" for non-ephemeral "RSA_EXPORT" 1444 String keyExchangeString; 1445 if (keyExchange == K_RSA_EXPORT && !serverKeyExchangeReceived) { 1446 keyExchangeString = K_RSA.name; 1447 } else { 1448 keyExchangeString = keyExchange.name; 1449 } 1450 1451 if (tm instanceof X509ExtendedTrustManager) { 1452 if (conn != null) { 1453 ((X509ExtendedTrustManager)tm).checkServerTrusted( 1454 peerCerts.clone(), 1455 keyExchangeString, 1456 conn); 1457 } else { 1458 ((X509ExtendedTrustManager)tm).checkServerTrusted( 1459 peerCerts.clone(), 1460 keyExchangeString, 1461 engine); 1462 } 1463 } else { 1464 // Unlikely to happen, because we have wrapped the old 1465 // X509TrustManager with the new X509ExtendedTrustManager. 1466 throw new CertificateException( 1467 "Improper X509TrustManager implementation"); 1468 } 1469 } catch (CertificateException e) { 1470 // This will throw an exception, so include the original error. 1471 fatalSE(Alerts.alert_certificate_unknown, e); 1472 } 1473 session.setPeerCertificates(peerCerts); 1474 } 1475 1476 /* 1477 * Whether the certificates can represent the same identity? 1478 * 1479 * The certificates can be used to represent the same identity: 1480 * 1. If the subject alternative names of IP address are present in 1481 * both certificates, they should be identical; otherwise, 1482 * 2. if the subject alternative names of DNS name are present in 1483 * both certificates, they should be identical; otherwise, 1484 * 3. if the subject fields are present in both certificates, the 1485 * certificate subjects and issuers should be identical. 1486 */ 1487 private static boolean isIdentityEquivalent(X509Certificate thisCert, 1488 X509Certificate prevCert) { 1489 if (thisCert.equals(prevCert)) { 1490 return true; 1491 } 1492 1493 // check the iPAddress field in subjectAltName extension 1494 Object thisIPAddress = getSubjectAltName(thisCert, 7); // 7: iPAddress 1495 Object prevIPAddress = getSubjectAltName(prevCert, 7); 1496 if (thisIPAddress != null && prevIPAddress!= null) { 1497 // only allow the exactly match 1498 return Objects.equals(thisIPAddress, prevIPAddress); 1499 } 1500 1501 // check the dNSName field in subjectAltName extension 1502 Object thisDNSName = getSubjectAltName(thisCert, 2); // 2: dNSName 1503 Object prevDNSName = getSubjectAltName(prevCert, 2); 1504 if (thisDNSName != null && prevDNSName!= null) { 1505 // only allow the exactly match 1506 return Objects.equals(thisDNSName, prevDNSName); 1507 } 1508 1509 // check the certificate subject and issuer 1510 X500Principal thisSubject = thisCert.getSubjectX500Principal(); 1511 X500Principal prevSubject = prevCert.getSubjectX500Principal(); 1512 X500Principal thisIssuer = thisCert.getIssuerX500Principal(); 1513 X500Principal prevIssuer = prevCert.getIssuerX500Principal(); 1514 if (!thisSubject.getName().isEmpty() && 1515 !prevSubject.getName().isEmpty() && 1516 thisSubject.equals(prevSubject) && 1517 thisIssuer.equals(prevIssuer)) { 1518 return true; 1519 } 1520 1521 return false; 1522 } 1523 1524 /* 1525 * Returns the subject alternative name of the specified type in the 1526 * subjectAltNames extension of a certificate. 1527 */ 1528 private static Object getSubjectAltName(X509Certificate cert, int type) { 1529 Collection<List<?>> subjectAltNames; 1530 1531 try { 1532 subjectAltNames = cert.getSubjectAlternativeNames(); 1533 } catch (CertificateParsingException cpe) { 1534 if (debug != null && Debug.isOn("handshake")) { 1535 System.out.println( 1536 "Attempt to obtain subjectAltNames extension failed!"); 1537 } 1538 return null; 1539 } 1540 1541 if (subjectAltNames != null) { 1542 for (List<?> subjectAltName : subjectAltNames) { 1543 int subjectAltNameType = (Integer)subjectAltName.get(0); 1544 if (subjectAltNameType == type) { 1545 return subjectAltName.get(1); 1546 } 1547 } 1548 } 1549 1550 return null; 1551 } 1552 }