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