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