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