1 /*
   2  * Copyright (c) 2015, 2019, 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.IOException;
  29 import java.nio.ByteBuffer;
  30 import java.security.SecureRandom;
  31 import java.security.cert.X509Certificate;
  32 import java.text.MessageFormat;
  33 import java.util.Arrays;
  34 import java.util.Collections;
  35 import java.util.LinkedList;
  36 import java.util.List;
  37 import java.util.Locale;
  38 import java.util.Objects;
  39 import javax.net.ssl.SSLException;
  40 import javax.net.ssl.SSLHandshakeException;
  41 import javax.net.ssl.SSLPeerUnverifiedException;
  42 import javax.net.ssl.SSLProtocolException;
  43 import static sun.security.ssl.ClientAuthType.CLIENT_AUTH_REQUIRED;
  44 import sun.security.ssl.SSLHandshake.HandshakeMessage;
  45 import sun.security.ssl.SupportedVersionsExtension.CHSupportedVersionsSpec;
  46 
  47 /**
  48  * Pack of the ClientHello handshake message.
  49  */
  50 final class ClientHello {
  51     static final SSLProducer kickstartProducer =
  52         new ClientHelloKickstartProducer();
  53     static final SSLConsumer handshakeConsumer =
  54         new ClientHelloConsumer();
  55     static final HandshakeProducer handshakeProducer =
  56         new ClientHelloProducer();
  57 
  58     private static final HandshakeConsumer t12HandshakeConsumer =
  59             new T12ClientHelloConsumer();
  60     private static final HandshakeConsumer t13HandshakeConsumer =
  61             new T13ClientHelloConsumer();
  62     private static final HandshakeConsumer d12HandshakeConsumer =
  63             new D12ClientHelloConsumer();
  64     private static final HandshakeConsumer d13HandshakeConsumer =
  65             new D13ClientHelloConsumer();
  66 
  67     /**
  68      * The ClientHello handshake message.
  69      *
  70      * See RFC 5264/4346/2246/6347 for the specifications.
  71      */
  72     static final class ClientHelloMessage extends HandshakeMessage {
  73         private final boolean       isDTLS;
  74 
  75         final int                   clientVersion;
  76         final RandomCookie          clientRandom;
  77         final SessionId             sessionId;
  78         private byte[]              cookie;         // DTLS only
  79         final int[]                 cipherSuiteIds;
  80         final List<CipherSuite>     cipherSuites;   // known cipher suites only
  81         final byte[]                compressionMethod;
  82         final SSLExtensions         extensions;
  83 
  84         private static final byte[]  NULL_COMPRESSION = new byte[] {0};
  85 
  86         ClientHelloMessage(HandshakeContext handshakeContext,
  87                 int clientVersion, SessionId sessionId,
  88                 List<CipherSuite> cipherSuites, SecureRandom generator) {
  89             super(handshakeContext);
  90             this.isDTLS = handshakeContext.sslContext.isDTLS();
  91 
  92             this.clientVersion = clientVersion;
  93             this.clientRandom = new RandomCookie(generator);
  94             this.sessionId = sessionId;
  95             if (isDTLS) {
  96                 this.cookie = new byte[0];
  97             } else {
  98                 this.cookie = null;
  99             }
 100 
 101             this.cipherSuites = cipherSuites;
 102             this.cipherSuiteIds = getCipherSuiteIds(cipherSuites);
 103             this.extensions = new SSLExtensions(this);
 104 
 105             // Don't support compression.
 106             this.compressionMethod = NULL_COMPRESSION;
 107         }
 108 
 109         /* Read up to the binders in the PSK extension. After this method
 110          * returns, the ByteBuffer position will be at end of the message
 111          * fragment that should be hashed to produce the PSK binder values.
 112          * The client of this method can use this position to determine the
 113          * message fragment and produce the binder values.
 114          */
 115         static void readPartial(TransportContext tc,
 116                 ByteBuffer m) throws IOException {
 117             boolean isDTLS = tc.sslContext.isDTLS();
 118 
 119             // version
 120             Record.getInt16(m);
 121 
 122             new RandomCookie(m);
 123 
 124             // session ID
 125             Record.getBytes8(m);
 126 
 127             // DTLS cookie
 128             if (isDTLS) {
 129                 Record.getBytes8(m);
 130             }
 131 
 132             // cipher suite IDs
 133             Record.getBytes16(m);
 134             // compression method
 135             Record.getBytes8(m);
 136             // read extensions, if present
 137             if (m.remaining() >= 2) {
 138                 int remaining = Record.getInt16(m);
 139                 while (remaining > 0) {
 140                     int id = Record.getInt16(m);
 141                     int extLen = Record.getInt16(m);
 142                     remaining -= extLen + 4;
 143 
 144                     if (id == SSLExtension.CH_PRE_SHARED_KEY.id) {
 145                         // ensure pre_shared_key is the last extension
 146                         if (remaining > 0) {
 147                             throw tc.fatal(Alert.ILLEGAL_PARAMETER,
 148                                     "pre_shared_key extension is not last");
 149                         }
 150                         // read only up to the IDs
 151                         Record.getBytes16(m);
 152                         return;
 153                     } else {
 154                         m.position(m.position() + extLen);
 155 
 156                     }
 157                 }
 158             }   // Otherwise, ignore the remaining bytes.
 159         }
 160 
 161         ClientHelloMessage(HandshakeContext handshakeContext, ByteBuffer m,
 162                 SSLExtension[] supportedExtensions) throws IOException {
 163             super(handshakeContext);
 164             this.isDTLS = handshakeContext.sslContext.isDTLS();
 165 
 166             this.clientVersion = ((m.get() & 0xFF) << 8) | (m.get() & 0xFF);
 167             this.clientRandom = new RandomCookie(m);
 168             this.sessionId = new SessionId(Record.getBytes8(m));
 169             try {
 170                 sessionId.checkLength(clientVersion);
 171             } catch (SSLProtocolException ex) {
 172                 throw handshakeContext.conContext.fatal(
 173                         Alert.ILLEGAL_PARAMETER, ex);
 174             }
 175             if (isDTLS) {
 176                 this.cookie = Record.getBytes8(m);
 177             } else {
 178                 this.cookie = null;
 179             }
 180 
 181             byte[] encodedIds = Record.getBytes16(m);
 182             if (encodedIds.length == 0 || (encodedIds.length & 0x01) != 0) {
 183                 throw handshakeContext.conContext.fatal(
 184                         Alert.ILLEGAL_PARAMETER,
 185                         "Invalid ClientHello message");
 186             }
 187 
 188             this.cipherSuiteIds = new int[encodedIds.length >> 1];
 189             for (int i = 0, j = 0; i < encodedIds.length; i++, j++) {
 190                 cipherSuiteIds[j] =
 191                     ((encodedIds[i++] & 0xFF) << 8) | (encodedIds[i] & 0xFF);
 192             }
 193             this.cipherSuites = getCipherSuites(cipherSuiteIds);
 194 
 195             this.compressionMethod = Record.getBytes8(m);
 196             // In TLS 1.3, use of certain extensions is mandatory.
 197             if (m.hasRemaining()) {
 198                 this.extensions =
 199                         new SSLExtensions(this, m, supportedExtensions);
 200             } else {
 201                 this.extensions = new SSLExtensions(this);
 202             }
 203         }
 204 
 205         void setHelloCookie(byte[] cookie) {
 206             this.cookie = cookie;
 207         }
 208 
 209         // DTLS 1.0/1.2, for cookie generation.
 210         byte[] getHelloCookieBytes() {
 211             HandshakeOutStream hos = new HandshakeOutStream(null);
 212             try {
 213                 // copied from send() method
 214                 hos.putInt8((byte)((clientVersion >>> 8) & 0xFF));
 215                 hos.putInt8((byte)(clientVersion & 0xFF));
 216                 hos.write(clientRandom.randomBytes, 0, 32);
 217                 hos.putBytes8(sessionId.getId());
 218                 // ignore cookie
 219                 hos.putBytes16(getEncodedCipherSuites());
 220                 hos.putBytes8(compressionMethod);
 221                 extensions.send(hos);       // In TLS 1.3, use of certain
 222                                             // extensions is mandatory.
 223             } catch (IOException ioe) {
 224                 // unlikely
 225             }
 226 
 227             return hos.toByteArray();
 228         }
 229 
 230         // (D)TLS 1.3, for cookie generation.
 231         byte[] getHeaderBytes() {
 232             HandshakeOutStream hos = new HandshakeOutStream(null);
 233             try {
 234                 // copied from send() method
 235                 hos.putInt8((byte)((clientVersion >>> 8) & 0xFF));
 236                 hos.putInt8((byte)(clientVersion & 0xFF));
 237                 hos.write(clientRandom.randomBytes, 0, 32);
 238                 hos.putBytes8(sessionId.getId());
 239                 hos.putBytes16(getEncodedCipherSuites());
 240                 hos.putBytes8(compressionMethod);
 241             } catch (IOException ioe) {
 242                 // unlikely
 243             }
 244 
 245             return hos.toByteArray();
 246         }
 247 
 248         private static int[] getCipherSuiteIds(
 249                 List<CipherSuite> cipherSuites) {
 250             if (cipherSuites != null) {
 251                 int[] ids = new int[cipherSuites.size()];
 252                 int i = 0;
 253                 for (CipherSuite cipherSuite : cipherSuites) {
 254                     ids[i++] = cipherSuite.id;
 255                 }
 256 
 257                 return ids;
 258             }
 259 
 260             return new int[0];
 261         }
 262 
 263         private static List<CipherSuite> getCipherSuites(int[] ids) {
 264             List<CipherSuite> cipherSuites = new LinkedList<>();
 265             for (int id : ids) {
 266                 CipherSuite cipherSuite = CipherSuite.valueOf(id);
 267                 if (cipherSuite != null) {
 268                     cipherSuites.add(cipherSuite);
 269                 }
 270             }
 271 
 272             return Collections.unmodifiableList(cipherSuites);
 273         }
 274 
 275         private List<String> getCipherSuiteNames() {
 276             List<String> names = new LinkedList<>();
 277             for (int id : cipherSuiteIds) {
 278                 names.add(CipherSuite.nameOf(id) +
 279                         "(" + Utilities.byte16HexString(id) + ")");            }
 280 
 281             return names;
 282         }
 283 
 284         private byte[] getEncodedCipherSuites() {
 285             byte[] encoded = new byte[cipherSuiteIds.length << 1];
 286             int i = 0;
 287             for (int id : cipherSuiteIds) {
 288                 encoded[i++] = (byte)(id >> 8);
 289                 encoded[i++] = (byte)id;
 290             }
 291             return encoded;
 292         }
 293 
 294         @Override
 295         public SSLHandshake handshakeType() {
 296             return SSLHandshake.CLIENT_HELLO;
 297         }
 298 
 299         @Override
 300         public int messageLength() {
 301             /*
 302              * Add fixed size parts of each field...
 303              * version + random + session + cipher + compress
 304              */
 305             return (2 + 32 + 1 + 2 + 1
 306                 + sessionId.length()        /* ... + variable parts */
 307                 + (isDTLS ? (1 + cookie.length) : 0)
 308                 + (cipherSuiteIds.length * 2)
 309                 + compressionMethod.length)
 310                 + extensions.length();      // In TLS 1.3, use of certain
 311                                             // extensions is mandatory.
 312         }
 313 
 314         @Override
 315         public void send(HandshakeOutStream hos) throws IOException {
 316             sendCore(hos);
 317             extensions.send(hos);       // In TLS 1.3, use of certain
 318                                         // extensions is mandatory.
 319         }
 320 
 321         void sendCore(HandshakeOutStream hos) throws IOException {
 322             hos.putInt8((byte) (clientVersion >>> 8));
 323             hos.putInt8((byte) clientVersion);
 324             hos.write(clientRandom.randomBytes, 0, 32);
 325             hos.putBytes8(sessionId.getId());
 326             if (isDTLS) {
 327                 hos.putBytes8(cookie);
 328             }
 329             hos.putBytes16(getEncodedCipherSuites());
 330             hos.putBytes8(compressionMethod);
 331         }
 332 
 333         @Override
 334         public String toString() {
 335             if (isDTLS) {
 336                 MessageFormat messageFormat = new MessageFormat(
 337                     "\"ClientHello\": '{'\n" +
 338                     "  \"client version\"      : \"{0}\",\n" +
 339                     "  \"random\"              : \"{1}\",\n" +
 340                     "  \"session id\"          : \"{2}\",\n" +
 341                     "  \"cookie\"              : \"{3}\",\n" +
 342                     "  \"cipher suites\"       : \"{4}\",\n" +
 343                     "  \"compression methods\" : \"{5}\",\n" +
 344                     "  \"extensions\"          : [\n" +
 345                     "{6}\n" +
 346                     "  ]\n" +
 347                     "'}'",
 348                     Locale.ENGLISH);
 349                 Object[] messageFields = {
 350                     ProtocolVersion.nameOf(clientVersion),
 351                     Utilities.toHexString(clientRandom.randomBytes),
 352                     sessionId.toString(),
 353                     Utilities.toHexString(cookie),
 354                     getCipherSuiteNames().toString(),
 355                     Utilities.toHexString(compressionMethod),
 356                     Utilities.indent(Utilities.indent(extensions.toString()))
 357                 };
 358 
 359                 return messageFormat.format(messageFields);
 360             } else {
 361                 MessageFormat messageFormat = new MessageFormat(
 362                     "\"ClientHello\": '{'\n" +
 363                     "  \"client version\"      : \"{0}\",\n" +
 364                     "  \"random\"              : \"{1}\",\n" +
 365                     "  \"session id\"          : \"{2}\",\n" +
 366                     "  \"cipher suites\"       : \"{3}\",\n" +
 367                     "  \"compression methods\" : \"{4}\",\n" +
 368                     "  \"extensions\"          : [\n" +
 369                     "{5}\n" +
 370                     "  ]\n" +
 371                     "'}'",
 372                     Locale.ENGLISH);
 373                 Object[] messageFields = {
 374                     ProtocolVersion.nameOf(clientVersion),
 375                     Utilities.toHexString(clientRandom.randomBytes),
 376                     sessionId.toString(),
 377                     getCipherSuiteNames().toString(),
 378                     Utilities.toHexString(compressionMethod),
 379                     Utilities.indent(Utilities.indent(extensions.toString()))
 380                 };
 381 
 382                 return messageFormat.format(messageFields);
 383             }
 384         }
 385     }
 386 
 387     /**
 388      * The "ClientHello" handshake message kick start producer.
 389      */
 390     private static final
 391             class ClientHelloKickstartProducer implements SSLProducer {
 392         // Prevent instantiation of this class.
 393         private ClientHelloKickstartProducer() {
 394             // blank
 395         }
 396 
 397         // Produce kickstart handshake message.
 398         @Override
 399         public byte[] produce(ConnectionContext context) throws IOException {
 400             // The producing happens in client side only.
 401             ClientHandshakeContext chc = (ClientHandshakeContext)context;
 402 
 403             // clean up this producer
 404             chc.handshakeProducers.remove(SSLHandshake.CLIENT_HELLO.id);
 405 
 406             // the max protocol version this client is supporting.
 407             ProtocolVersion maxProtocolVersion = chc.maximumActiveProtocol;
 408 
 409             // session ID of the ClientHello message
 410             SessionId sessionId = SSLSessionImpl.nullSession.getSessionId();
 411 
 412             // a list of cipher suites sent by the client
 413             List<CipherSuite> cipherSuites = chc.activeCipherSuites;
 414 
 415             //
 416             // Try to resume an existing session.
 417             //
 418             SSLSessionContextImpl ssci = (SSLSessionContextImpl)
 419                     chc.sslContext.engineGetClientSessionContext();
 420             SSLSessionImpl session = ssci.get(
 421                     chc.conContext.transport.getPeerHost(),
 422                     chc.conContext.transport.getPeerPort());
 423             if (session != null) {
 424                 // If unsafe server certificate change is not allowed, reserve
 425                 // current server certificates if the previous handshake is a
 426                 // session-resumption abbreviated initial handshake.
 427                 if (!ClientHandshakeContext.allowUnsafeServerCertChange &&
 428                         session.isSessionResumption()) {
 429                     try {
 430                         // If existing, peer certificate chain cannot be null.
 431                         chc.reservedServerCerts =
 432                             (X509Certificate[])session.getPeerCertificates();
 433                     } catch (SSLPeerUnverifiedException puve) {
 434                         // Maybe not certificate-based, ignore the exception.
 435                     }
 436                 }
 437 
 438                 if (!session.isRejoinable()) {
 439                     session = null;
 440                     if (SSLLogger.isOn &&
 441                             SSLLogger.isOn("ssl,handshake,verbose")) {
 442                         SSLLogger.finest(
 443                             "Can't resume, the session is not rejoinable");
 444                     }
 445                 }
 446             }
 447 
 448             CipherSuite sessionSuite = null;
 449             if (session != null) {
 450                 sessionSuite = session.getSuite();
 451                 if (!chc.isNegotiable(sessionSuite)) {
 452                     session = null;
 453                     if (SSLLogger.isOn &&
 454                             SSLLogger.isOn("ssl,handshake,verbose")) {
 455                         SSLLogger.finest(
 456                             "Can't resume, unavailable session cipher suite");
 457                     }
 458                 }
 459             }
 460 
 461             ProtocolVersion sessionVersion = null;
 462             if (session != null) {
 463                 sessionVersion = session.getProtocolVersion();
 464                 if (!chc.isNegotiable(sessionVersion)) {
 465                     session = null;
 466                     if (SSLLogger.isOn &&
 467                             SSLLogger.isOn("ssl,handshake,verbose")) {
 468                         SSLLogger.finest(
 469                             "Can't resume, unavailable protocol version");
 470                     }
 471                 }
 472             }
 473 
 474             if (session != null &&
 475                 !sessionVersion.useTLS13PlusSpec() &&
 476                 SSLConfiguration.useExtendedMasterSecret) {
 477 
 478                 boolean isEmsAvailable = chc.sslConfig.isAvailable(
 479                     SSLExtension.CH_EXTENDED_MASTER_SECRET, sessionVersion);
 480                 if (isEmsAvailable && !session.useExtendedMasterSecret &&
 481                         !SSLConfiguration.allowLegacyResumption) {
 482                     // perform full handshake instead
 483                     //
 484                     // The client SHOULD NOT offer an abbreviated handshake
 485                     // to resume a session that does not use an extended
 486                     // master secret.  Instead, it SHOULD offer a full
 487                     // handshake.
 488                      session = null;
 489                 }
 490 
 491                 if ((session != null) &&
 492                         !ClientHandshakeContext.allowUnsafeServerCertChange) {
 493                     // It is fine to move on with abbreviate handshake if
 494                     // endpoint identification is enabled.
 495                     String identityAlg = chc.sslConfig.identificationProtocol;
 496                     if (identityAlg == null || identityAlg.isEmpty()) {
 497                         if (isEmsAvailable) {
 498                             if (!session.useExtendedMasterSecret) {
 499                                 // perform full handshake instead
 500                                 session = null;
 501                             }   // Otherwise, use extended master secret.
 502                         } else {
 503                             // The extended master secret extension does not
 504                             // apply to SSL 3.0.  Perform a full handshake
 505                             // instead.
 506                             //
 507                             // Note that the useExtendedMasterSecret is
 508                             // extended to protect SSL 3.0 connections,
 509                             // by discarding abbreviate handshake.
 510                             session = null;
 511                         }
 512                     }
 513                 }
 514             }
 515 
 516             // ensure that the endpoint identification algorithm matches the
 517             // one in the session
 518             String identityAlg = chc.sslConfig.identificationProtocol;
 519             if (session != null && identityAlg != null) {
 520                 String sessionIdentityAlg =
 521                     session.getIdentificationProtocol();
 522                 if (!identityAlg.equalsIgnoreCase(sessionIdentityAlg)) {
 523                     if (SSLLogger.isOn &&
 524                     SSLLogger.isOn("ssl,handshake,verbose")) {
 525                         SSLLogger.finest("Can't resume, endpoint id" +
 526                             " algorithm does not match, requested: " +
 527                             identityAlg + ", cached: " + sessionIdentityAlg);
 528                     }
 529                     session = null;
 530                 }
 531             }
 532 
 533             if (session != null) {
 534                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake,verbose")) {
 535                     SSLLogger.finest("Try resuming session", session);
 536                 }
 537 
 538                 // only set session id if session is 1.2 or earlier
 539                 if (!session.getProtocolVersion().useTLS13PlusSpec()) {
 540                     sessionId = session.getSessionId();
 541                 }
 542                 if (!maxProtocolVersion.equals(sessionVersion)) {
 543                     maxProtocolVersion = sessionVersion;
 544 
 545                     // Update protocol version number in underlying socket and
 546                     // handshake output stream, so that the output records
 547                     // (at the record layer) have the correct version
 548                     chc.setVersion(sessionVersion);
 549                 }
 550 
 551                 // If no new session is allowed, force use of the previous
 552                 // session ciphersuite, and add the renegotiation SCSV if
 553                 // necessary.
 554                 if (!chc.sslConfig.enableSessionCreation) {
 555                     if (!chc.conContext.isNegotiated &&
 556                         !sessionVersion.useTLS13PlusSpec() &&
 557                         cipherSuites.contains(
 558                             CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) {
 559                         cipherSuites = Arrays.asList(sessionSuite,
 560                             CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
 561                     } else {    // otherwise, use renegotiation_info extension
 562                         cipherSuites = Arrays.asList(sessionSuite);
 563                     }
 564 
 565                     if (SSLLogger.isOn &&
 566                             SSLLogger.isOn("ssl,handshake,verbose")) {
 567                         SSLLogger.finest(
 568                             "No new session is allowed, so try to resume " +
 569                             "the session cipher suite only", sessionSuite);
 570                     }
 571                 }
 572 
 573                 chc.isResumption = true;
 574                 chc.resumingSession = session;
 575             }
 576 
 577             if (session == null) {
 578                 if (!chc.sslConfig.enableSessionCreation) {
 579                     throw new SSLHandshakeException(
 580                             "No new session is allowed and " +
 581                             "no existing session can be resumed");
 582                 }
 583 
 584                 if (maxProtocolVersion.useTLS13PlusSpec() &&
 585                         SSLConfiguration.useCompatibilityMode) {
 586                     // In compatibility mode, the TLS 1.3 legacy_session_id
 587                     // field MUST be non-empty, so a client not offering a
 588                     // pre-TLS 1.3 session MUST generate a new 32-byte value.
 589                     sessionId =
 590                         new SessionId(true, chc.sslContext.getSecureRandom());
 591                 }
 592             }
 593 
 594             ProtocolVersion minimumVersion = ProtocolVersion.NONE;
 595             for (ProtocolVersion pv : chc.activeProtocols) {
 596                 if (minimumVersion == ProtocolVersion.NONE ||
 597                         pv.compare(minimumVersion) < 0) {
 598                     minimumVersion = pv;
 599                 }
 600             }
 601 
 602             // exclude SCSV for secure renegotiation
 603             if (!minimumVersion.useTLS13PlusSpec()) {
 604                 if (chc.conContext.secureRenegotiation &&
 605                         cipherSuites.contains(
 606                             CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) {
 607                     // The cipherSuites may be unmodifiable
 608                     cipherSuites = new LinkedList<>(cipherSuites);
 609                     cipherSuites.remove(
 610                             CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
 611                 }
 612             }
 613 
 614             // make sure there is a negotiable cipher suite.
 615             boolean negotiable = false;
 616             for (CipherSuite suite : cipherSuites) {
 617                 if (chc.isNegotiable(suite)) {
 618                     negotiable = true;
 619                     break;
 620                 }
 621             }
 622             if (!negotiable) {
 623                 throw new SSLHandshakeException("No negotiable cipher suite");
 624             }
 625 
 626             // Create the handshake message.
 627             ProtocolVersion clientHelloVersion = maxProtocolVersion;
 628             if (clientHelloVersion.useTLS13PlusSpec()) {
 629                 // In (D)TLS 1.3, the client indicates its version preferences
 630                 // in the "supported_versions" extension and the client_version
 631                 // (legacy_version) field MUST be set to (D)TLS 1.2.
 632                 if (clientHelloVersion.isDTLS) {
 633                     clientHelloVersion = ProtocolVersion.DTLS12;
 634                 } else {
 635                     clientHelloVersion = ProtocolVersion.TLS12;
 636                 }
 637             }
 638 
 639             ClientHelloMessage chm = new ClientHelloMessage(chc,
 640                     clientHelloVersion.id, sessionId, cipherSuites,
 641                     chc.sslContext.getSecureRandom());
 642 
 643             // cache the client random number for further using
 644             chc.clientHelloRandom = chm.clientRandom;
 645             chc.clientHelloVersion = clientHelloVersion.id;
 646 
 647             // Produce extensions for ClientHello handshake message.
 648             SSLExtension[] extTypes = chc.sslConfig.getEnabledExtensions(
 649                     SSLHandshake.CLIENT_HELLO, chc.activeProtocols);
 650             chm.extensions.produce(chc, extTypes);
 651 
 652             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 653                 SSLLogger.fine("Produced ClientHello handshake message", chm);
 654             }
 655 
 656             // Output the handshake message.
 657             chm.write(chc.handshakeOutput);
 658             chc.handshakeOutput.flush();
 659 
 660             // Reserve the initial ClientHello message for the follow on
 661             // cookie exchange if needed.
 662             chc.initialClientHelloMsg = chm;
 663 
 664             // What's the expected response?
 665             chc.handshakeConsumers.put(
 666                     SSLHandshake.SERVER_HELLO.id, SSLHandshake.SERVER_HELLO);
 667             if (chc.sslContext.isDTLS() &&
 668                     !minimumVersion.useTLS13PlusSpec()) {
 669                 chc.handshakeConsumers.put(
 670                         SSLHandshake.HELLO_VERIFY_REQUEST.id,
 671                         SSLHandshake.HELLO_VERIFY_REQUEST);
 672             }
 673 
 674             // The handshake message has been delivered.
 675             return null;
 676         }
 677     }
 678 
 679     private static final
 680             class ClientHelloProducer implements HandshakeProducer {
 681         // Prevent instantiation of this class.
 682         private ClientHelloProducer() {
 683             // blank
 684         }
 685 
 686         // Response to one of the following handshake message:
 687         //     HelloRequest                     (SSL 3.0/TLS 1.0/1.1/1.2)
 688         //     ServerHello(HelloRetryRequest)   (TLS 1.3)
 689         //     HelloVerifyRequest               (DTLS 1.0/1.2)
 690         @Override
 691         public byte[] produce(ConnectionContext context,
 692                 HandshakeMessage message) throws IOException {
 693             // The producing happens in client side only.
 694             ClientHandshakeContext chc = (ClientHandshakeContext)context;
 695 
 696             SSLHandshake ht = message.handshakeType();
 697             if (ht == null) {
 698                 throw new UnsupportedOperationException("Not supported yet.");
 699             }
 700 
 701             switch (ht) {
 702                 case HELLO_REQUEST:
 703                     // SSL 3.0/TLS 1.0/1.1/1.2
 704                     try {
 705                         chc.kickstart();
 706                     } catch (IOException ioe) {
 707                         throw chc.conContext.fatal(
 708                                 Alert.HANDSHAKE_FAILURE, ioe);
 709                     }
 710 
 711                     // The handshake message has been delivered.
 712                     return null;
 713                 case HELLO_VERIFY_REQUEST:
 714                     // DTLS 1.0/1.2
 715                     //
 716                     // The HelloVerifyRequest consumer should have updated the
 717                     // ClientHello handshake message with cookie.
 718                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 719                         SSLLogger.fine(
 720                             "Produced ClientHello(cookie) handshake message",
 721                             chc.initialClientHelloMsg);
 722                     }
 723 
 724                     // Output the handshake message.
 725                     chc.initialClientHelloMsg.write(chc.handshakeOutput);
 726                     chc.handshakeOutput.flush();
 727 
 728                     // What's the expected response?
 729                     chc.handshakeConsumers.put(SSLHandshake.SERVER_HELLO.id,
 730                             SSLHandshake.SERVER_HELLO);
 731 
 732                     ProtocolVersion minimumVersion = ProtocolVersion.NONE;
 733                     for (ProtocolVersion pv : chc.activeProtocols) {
 734                         if (minimumVersion == ProtocolVersion.NONE ||
 735                                 pv.compare(minimumVersion) < 0) {
 736                             minimumVersion = pv;
 737                         }
 738                     }
 739                     if (chc.sslContext.isDTLS() &&
 740                             !minimumVersion.useTLS13PlusSpec()) {
 741                         chc.handshakeConsumers.put(
 742                                 SSLHandshake.HELLO_VERIFY_REQUEST.id,
 743                                 SSLHandshake.HELLO_VERIFY_REQUEST);
 744                     }
 745 
 746                     // The handshake message has been delivered.
 747                     return null;
 748                 case HELLO_RETRY_REQUEST:
 749                     // TLS 1.3
 750                     // The HelloRetryRequest consumer should have updated the
 751                     // ClientHello handshake message with cookie.
 752                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 753                         SSLLogger.fine(
 754                             "Produced ClientHello(HRR) handshake message",
 755                             chc.initialClientHelloMsg);
 756                     }
 757 
 758                     // Output the handshake message.
 759                     chc.initialClientHelloMsg.write(chc.handshakeOutput);
 760                     chc.handshakeOutput.flush();
 761 
 762                     // What's the expected response?
 763                     chc.conContext.consumers.putIfAbsent(
 764                             ContentType.CHANGE_CIPHER_SPEC.id,
 765                             ChangeCipherSpec.t13Consumer);
 766                     chc.handshakeConsumers.put(SSLHandshake.SERVER_HELLO.id,
 767                             SSLHandshake.SERVER_HELLO);
 768 
 769                     // The handshake message has been delivered.
 770                     return null;
 771                 default:
 772                     throw new UnsupportedOperationException(
 773                             "Not supported yet.");
 774             }
 775         }
 776     }
 777 
 778     /**
 779      * The "ClientHello" handshake message consumer.
 780      */
 781     private static final class ClientHelloConsumer implements SSLConsumer {
 782         // Prevent instantiation of this class.
 783         private ClientHelloConsumer() {
 784             // blank
 785         }
 786 
 787         @Override
 788         public void consume(ConnectionContext context,
 789                 ByteBuffer message) throws IOException {
 790             // The consuming happens in server side only.
 791             ServerHandshakeContext shc = (ServerHandshakeContext)context;
 792 
 793             // clean up this consumer
 794             shc.handshakeConsumers.remove(SSLHandshake.CLIENT_HELLO.id);
 795             if (!shc.handshakeConsumers.isEmpty()) {
 796                 throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
 797                         "No more handshake message allowed " +
 798                         "in a ClientHello flight");
 799             }
 800 
 801             // Get enabled extension types in ClientHello handshake message.
 802             SSLExtension[] enabledExtensions =
 803                     shc.sslConfig.getEnabledExtensions(
 804                             SSLHandshake.CLIENT_HELLO);
 805 
 806             ClientHelloMessage chm =
 807                     new ClientHelloMessage(shc, message, enabledExtensions);
 808             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 809                 SSLLogger.fine("Consuming ClientHello handshake message", chm);
 810             }
 811 
 812             shc.clientHelloVersion = chm.clientVersion;
 813             onClientHello(shc, chm);
 814         }
 815 
 816         private void onClientHello(ServerHandshakeContext context,
 817                 ClientHelloMessage clientHello) throws IOException {
 818             // Negotiate protocol version.
 819             //
 820             // Check and launch SupportedVersions.
 821             SSLExtension[] extTypes = new SSLExtension[] {
 822                     SSLExtension.CH_SUPPORTED_VERSIONS
 823                 };
 824             clientHello.extensions.consumeOnLoad(context, extTypes);
 825 
 826             ProtocolVersion negotiatedProtocol;
 827             CHSupportedVersionsSpec svs =
 828                     (CHSupportedVersionsSpec)context.handshakeExtensions.get(
 829                             SSLExtension.CH_SUPPORTED_VERSIONS);
 830             if (svs != null) {
 831                 negotiatedProtocol =
 832                         negotiateProtocol(context, svs.requestedProtocols);
 833             } else {
 834                 negotiatedProtocol =
 835                         negotiateProtocol(context, clientHello.clientVersion);
 836             }
 837             context.negotiatedProtocol = negotiatedProtocol;
 838             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 839                 SSLLogger.fine(
 840                     "Negotiated protocol version: " + negotiatedProtocol.name);
 841             }
 842 
 843             // Consume the handshake message for the specific protocol version.
 844             if (negotiatedProtocol.isDTLS) {
 845                 if (negotiatedProtocol.useTLS13PlusSpec()) {
 846                     d13HandshakeConsumer.consume(context, clientHello);
 847                 } else {
 848                     d12HandshakeConsumer.consume(context, clientHello);
 849                 }
 850             } else {
 851                 if (negotiatedProtocol.useTLS13PlusSpec()) {
 852                     t13HandshakeConsumer.consume(context, clientHello);
 853                 } else {
 854                     t12HandshakeConsumer.consume(context, clientHello);
 855                 }
 856             }
 857         }
 858 
 859         // Select a protocol version according to the
 860         // ClientHello.client_version.
 861         private ProtocolVersion negotiateProtocol(
 862                 ServerHandshakeContext context,
 863                 int clientHelloVersion) throws SSLException {
 864 
 865             // Per TLS 1.3 specification, server MUST negotiate TLS 1.2 or prior
 866             // even if ClientHello.client_version is 0x0304 or later.
 867             int chv = clientHelloVersion;
 868             if (context.sslContext.isDTLS()) {
 869                 if (chv < ProtocolVersion.DTLS12.id) {
 870                     chv = ProtocolVersion.DTLS12.id;
 871                 }
 872             } else {
 873                 if (chv > ProtocolVersion.TLS12.id) {
 874                     chv = ProtocolVersion.TLS12.id;
 875                 }
 876             }
 877 
 878             // Select a protocol version from the activated protocols.
 879             ProtocolVersion pv = ProtocolVersion.selectedFrom(
 880                     context.activeProtocols, chv);
 881             if (pv == null || pv == ProtocolVersion.NONE ||
 882                     pv == ProtocolVersion.SSL20Hello) {
 883                 throw context.conContext.fatal(Alert.PROTOCOL_VERSION,
 884                     "Client requested protocol " +
 885                     ProtocolVersion.nameOf(clientHelloVersion) +
 886                     " is not enabled or supported in server context");
 887             }
 888 
 889             return pv;
 890         }
 891 
 892         // Select a protocol version according to the
 893         // supported_versions extension.
 894         private ProtocolVersion negotiateProtocol(
 895                 ServerHandshakeContext context,
 896                 int[] clientSupportedVersions) throws SSLException {
 897 
 898             // The client supported protocol versions are present in client
 899             // preference order.  This implementation chooses to use the server
 900             // preference of protocol versions instead.
 901             for (ProtocolVersion spv : context.activeProtocols) {
 902                 if (spv == ProtocolVersion.SSL20Hello) {
 903                     continue;
 904                 }
 905                 for (int cpv : clientSupportedVersions) {
 906                     if (cpv == ProtocolVersion.SSL20Hello.id) {
 907                         continue;
 908                     }
 909                     if (spv.id == cpv) {
 910                         return spv;
 911                     }
 912                 }
 913             }
 914 
 915             // No protocol version can be negotiated.
 916             throw context.conContext.fatal(Alert.PROTOCOL_VERSION,
 917                 "The client supported protocol versions " + Arrays.toString(
 918                     ProtocolVersion.toStringArray(clientSupportedVersions)) +
 919                 " are not accepted by server preferences " +
 920                 context.activeProtocols);
 921         }
 922     }
 923 
 924     /**
 925      * The "ClientHello" handshake message consumer for TLS 1.2 and
 926      * prior SSL/TLS protocol versions.
 927      */
 928     private static final
 929             class T12ClientHelloConsumer implements HandshakeConsumer {
 930         // Prevent instantiation of this class.
 931         private T12ClientHelloConsumer() {
 932             // blank
 933         }
 934 
 935         @Override
 936         public void consume(ConnectionContext context,
 937                 HandshakeMessage message) throws IOException {
 938             // The consuming happens in server side only.
 939             ServerHandshakeContext shc = (ServerHandshakeContext)context;
 940             ClientHelloMessage clientHello = (ClientHelloMessage)message;
 941 
 942             //
 943             // validate
 944             //
 945 
 946             // Reject client initiated renegotiation?
 947             //
 948             // If server side should reject client-initiated renegotiation,
 949             // send an Alert.HANDSHAKE_FAILURE fatal alert, not a
 950             // no_renegotiation warning alert (no_renegotiation must be a
 951             // warning: RFC 2246).  no_renegotiation might seem more
 952             // natural at first, but warnings are not appropriate because
 953             // the sending party does not know how the receiving party
 954             // will behave.  This state must be treated as a fatal server
 955             // condition.
 956             //
 957             // This will not have any impact on server initiated renegotiation.
 958             if (shc.conContext.isNegotiated) {
 959                 if (!shc.conContext.secureRenegotiation &&
 960                         !HandshakeContext.allowUnsafeRenegotiation) {
 961                     throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 962                             "Unsafe renegotiation is not allowed");
 963                 }
 964 
 965                 if (ServerHandshakeContext.rejectClientInitiatedRenego &&
 966                         !shc.kickstartMessageDelivered) {
 967                     throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 968                             "Client initiated renegotiation is not allowed");
 969                 }
 970             }
 971 
 972             // Is it an abbreviated handshake?
 973             if (clientHello.sessionId.length() != 0) {
 974                 SSLSessionImpl previous = ((SSLSessionContextImpl)shc.sslContext
 975                             .engineGetServerSessionContext())
 976                             .get(clientHello.sessionId.getId());
 977 
 978                 boolean resumingSession =
 979                         (previous != null) && previous.isRejoinable();
 980                 if (!resumingSession) {
 981                     if (SSLLogger.isOn &&
 982                             SSLLogger.isOn("ssl,handshake,verbose")) {
 983                         SSLLogger.finest(
 984                                 "Can't resume, " +
 985                                 "the existing session is not rejoinable");
 986                     }
 987                 }
 988                 // Validate the negotiated protocol version.
 989                 if (resumingSession) {
 990                     ProtocolVersion sessionProtocol =
 991                             previous.getProtocolVersion();
 992                     if (sessionProtocol != shc.negotiatedProtocol) {
 993                         resumingSession = false;
 994                         if (SSLLogger.isOn &&
 995                                 SSLLogger.isOn("ssl,handshake,verbose")) {
 996                             SSLLogger.finest(
 997                                 "Can't resume, not the same protocol version");
 998                         }
 999                     }
1000                 }
1001 
1002                 // Validate the required client authentication.
1003                 if (resumingSession &&
1004                     (shc.sslConfig.clientAuthType == CLIENT_AUTH_REQUIRED)) {
1005                     try {
1006                         previous.getPeerPrincipal();
1007                     } catch (SSLPeerUnverifiedException e) {
1008                         resumingSession = false;
1009                         if (SSLLogger.isOn &&
1010                                 SSLLogger.isOn("ssl,handshake,verbose")) {
1011                             SSLLogger.finest(
1012                                 "Can't resume, " +
1013                                 "client authentication is required");
1014                         }
1015                     }
1016                 }
1017 
1018                 // Validate that the cached cipher suite.
1019                 if (resumingSession) {
1020                     CipherSuite suite = previous.getSuite();
1021                     if ((!shc.isNegotiable(suite)) ||
1022                             (!clientHello.cipherSuites.contains(suite))) {
1023                         resumingSession = false;
1024                         if (SSLLogger.isOn &&
1025                                 SSLLogger.isOn("ssl,handshake,verbose")) {
1026                             SSLLogger.finest(
1027                                 "Can't resume, " +
1028                                 "the session cipher suite is absent");
1029                         }
1030                     }
1031                 }
1032 
1033                 // ensure that the endpoint identification algorithm matches the
1034                 // one in the session
1035                 String identityAlg = shc.sslConfig.identificationProtocol;
1036                 if (resumingSession && identityAlg != null) {
1037                     String sessionIdentityAlg =
1038                         previous.getIdentificationProtocol();
1039                     if (!identityAlg.equalsIgnoreCase(sessionIdentityAlg)) {
1040                         if (SSLLogger.isOn &&
1041                         SSLLogger.isOn("ssl,handshake,verbose")) {
1042                             SSLLogger.finest("Can't resume, endpoint id" +
1043                             " algorithm does not match, requested: " +
1044                             identityAlg + ", cached: " + sessionIdentityAlg);
1045                         }
1046                         resumingSession = false;
1047                     }
1048                 }
1049 
1050                 // So far so good.  Note that the handshake extensions may reset
1051                 // the resuming options later.
1052                 shc.isResumption = resumingSession;
1053                 shc.resumingSession = resumingSession ? previous : null;
1054             }
1055 
1056             // cache the client random number for further using
1057             shc.clientHelloRandom = clientHello.clientRandom;
1058 
1059             // Check and launch ClientHello extensions.
1060             SSLExtension[] extTypes = shc.sslConfig.getEnabledExtensions(
1061                     SSLHandshake.CLIENT_HELLO);
1062             clientHello.extensions.consumeOnLoad(shc, extTypes);
1063 
1064             //
1065             // update
1066             //
1067             if (!shc.conContext.isNegotiated) {
1068                 shc.conContext.protocolVersion = shc.negotiatedProtocol;
1069                 shc.conContext.outputRecord.setVersion(shc.negotiatedProtocol);
1070             }
1071 
1072             // update the responders
1073             //
1074             // Only need to ServerHello, which may add more responders later.
1075             // Note that ServerHello and HelloRetryRequest share the same
1076             // handshake type/id.  The ServerHello producer may be replaced
1077             // by HelloRetryRequest producer if needed.
1078             shc.handshakeProducers.put(SSLHandshake.SERVER_HELLO.id,
1079                     SSLHandshake.SERVER_HELLO);
1080 
1081             //
1082             // produce
1083             //
1084             SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
1085                 SSLHandshake.SERVER_HELLO,
1086 
1087                 // full handshake messages
1088                 SSLHandshake.CERTIFICATE,
1089                 SSLHandshake.CERTIFICATE_STATUS,
1090                 SSLHandshake.SERVER_KEY_EXCHANGE,
1091                 SSLHandshake.CERTIFICATE_REQUEST,
1092                 SSLHandshake.SERVER_HELLO_DONE,
1093 
1094                 // abbreviated handshake messages
1095                 SSLHandshake.FINISHED
1096             };
1097 
1098             for (SSLHandshake hs : probableHandshakeMessages) {
1099                 HandshakeProducer handshakeProducer =
1100                         shc.handshakeProducers.remove(hs.id);
1101                 if (handshakeProducer != null) {
1102                     handshakeProducer.produce(context, clientHello);
1103                 }
1104             }
1105         }
1106     }
1107 
1108     /**
1109      * The "ClientHello" handshake message consumer for TLS 1.3.
1110      */
1111     private static final
1112             class T13ClientHelloConsumer implements HandshakeConsumer {
1113         // Prevent instantiation of this class.
1114         private T13ClientHelloConsumer() {
1115             // blank
1116         }
1117 
1118         @Override
1119         public void consume(ConnectionContext context,
1120                 HandshakeMessage message) throws IOException {
1121             // The consuming happens in server side only.
1122             ServerHandshakeContext shc = (ServerHandshakeContext)context;
1123             ClientHelloMessage clientHello = (ClientHelloMessage)message;
1124 
1125             // The client may send a dummy change_cipher_spec record
1126             // immediately after the first ClientHello.
1127             shc.conContext.consumers.putIfAbsent(
1128                     ContentType.CHANGE_CIPHER_SPEC.id,
1129                     ChangeCipherSpec.t13Consumer);
1130 
1131             // Is it a resumption?
1132             //
1133             // Check and launch the "psk_key_exchange_modes" and
1134             // "pre_shared_key" extensions first, which will reset the
1135             // resuming session, no matter the extensions present or not.
1136             shc.isResumption = true;
1137             SSLExtension[] extTypes = new SSLExtension[] {
1138                     SSLExtension.PSK_KEY_EXCHANGE_MODES,
1139                     SSLExtension.CH_PRE_SHARED_KEY
1140                 };
1141             clientHello.extensions.consumeOnLoad(shc, extTypes);
1142 
1143             // Check and launch ClientHello extensions other than
1144             // "psk_key_exchange_modes", "pre_shared_key", "protocol_version"
1145             // and "key_share" extensions.
1146             //
1147             // These extensions may discard session resumption, or ask for
1148             // hello retry.
1149             extTypes = shc.sslConfig.getExclusiveExtensions(
1150                     SSLHandshake.CLIENT_HELLO,
1151                     Arrays.asList(
1152                             SSLExtension.PSK_KEY_EXCHANGE_MODES,
1153                             SSLExtension.CH_PRE_SHARED_KEY,
1154                             SSLExtension.CH_SUPPORTED_VERSIONS));
1155             clientHello.extensions.consumeOnLoad(shc, extTypes);
1156 
1157             if (!shc.handshakeProducers.isEmpty()) {
1158                 // Should be HelloRetryRequest producer.
1159                 goHelloRetryRequest(shc, clientHello);
1160             } else {
1161                 goServerHello(shc, clientHello);
1162             }
1163         }
1164 
1165         private void goHelloRetryRequest(ServerHandshakeContext shc,
1166                 ClientHelloMessage clientHello) throws IOException {
1167             HandshakeProducer handshakeProducer =
1168                     shc.handshakeProducers.remove(
1169                             SSLHandshake.HELLO_RETRY_REQUEST.id);
1170             if (handshakeProducer != null) {
1171                     handshakeProducer.produce(shc, clientHello);
1172             } else {
1173                 // unlikely
1174                 throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1175                     "No HelloRetryRequest producer: " + shc.handshakeProducers);
1176             }
1177 
1178             if (!shc.handshakeProducers.isEmpty()) {
1179                 // unlikely, but please double check.
1180                 throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1181                     "unknown handshake producers: " + shc.handshakeProducers);
1182             }
1183         }
1184 
1185         private void goServerHello(ServerHandshakeContext shc,
1186                 ClientHelloMessage clientHello) throws IOException {
1187             //
1188             // validate
1189             //
1190             shc.clientHelloRandom = clientHello.clientRandom;
1191 
1192             //
1193             // update
1194             //
1195             if (!shc.conContext.isNegotiated) {
1196                 shc.conContext.protocolVersion = shc.negotiatedProtocol;
1197                 shc.conContext.outputRecord.setVersion(shc.negotiatedProtocol);
1198             }
1199 
1200             // update the responders
1201             //
1202             // Only ServerHello/HelloRetryRequest producer, which adds
1203             // more responders later.
1204             shc.handshakeProducers.put(SSLHandshake.SERVER_HELLO.id,
1205                 SSLHandshake.SERVER_HELLO);
1206 
1207             SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
1208                 SSLHandshake.SERVER_HELLO,
1209 
1210                 // full handshake messages
1211                 SSLHandshake.ENCRYPTED_EXTENSIONS,
1212                 SSLHandshake.CERTIFICATE_REQUEST,
1213                 SSLHandshake.CERTIFICATE,
1214                 SSLHandshake.CERTIFICATE_VERIFY,
1215                 SSLHandshake.FINISHED
1216             };
1217 
1218             //
1219             // produce
1220             //
1221             for (SSLHandshake hs : probableHandshakeMessages) {
1222                 HandshakeProducer handshakeProducer =
1223                         shc.handshakeProducers.remove(hs.id);
1224                 if (handshakeProducer != null) {
1225                     handshakeProducer.produce(shc, clientHello);
1226                 }
1227             }
1228         }
1229     }
1230 
1231     /**
1232      * The "ClientHello" handshake message consumer for DTLS 1.2 and
1233      * previous DTLS protocol versions.
1234      */
1235     private static final
1236             class D12ClientHelloConsumer implements HandshakeConsumer {
1237         // Prevent instantiation of this class.
1238         private D12ClientHelloConsumer() {
1239             // blank
1240         }
1241 
1242         @Override
1243         public void consume(ConnectionContext context,
1244                 HandshakeMessage message) throws IOException {
1245             // The consuming happens in server side only.
1246             ServerHandshakeContext shc = (ServerHandshakeContext)context;
1247             ClientHelloMessage clientHello = (ClientHelloMessage)message;
1248 
1249             //
1250             // validate
1251             //
1252 
1253             // Reject client initiated renegotiation?
1254             //
1255             // If server side should reject client-initiated renegotiation,
1256             // send an Alert.HANDSHAKE_FAILURE fatal alert, not a
1257             // no_renegotiation warning alert (no_renegotiation must be a
1258             // warning: RFC 2246).  no_renegotiation might seem more
1259             // natural at first, but warnings are not appropriate because
1260             // the sending party does not know how the receiving party
1261             // will behave.  This state must be treated as a fatal server
1262             // condition.
1263             //
1264             // This will not have any impact on server initiated renegotiation.
1265             if (shc.conContext.isNegotiated) {
1266                 if (!shc.conContext.secureRenegotiation &&
1267                         !HandshakeContext.allowUnsafeRenegotiation) {
1268                     throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1269                             "Unsafe renegotiation is not allowed");
1270                 }
1271 
1272                 if (ServerHandshakeContext.rejectClientInitiatedRenego &&
1273                         !shc.kickstartMessageDelivered) {
1274                     throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1275                             "Client initiated renegotiation is not allowed");
1276                 }
1277             }
1278 
1279             // Is it an abbreviated handshake?
1280             if (clientHello.sessionId.length() != 0) {
1281                 SSLSessionImpl previous = ((SSLSessionContextImpl)shc.sslContext
1282                             .engineGetServerSessionContext())
1283                             .get(clientHello.sessionId.getId());
1284 
1285                 boolean resumingSession =
1286                         (previous != null) && previous.isRejoinable();
1287                 if (!resumingSession) {
1288                     if (SSLLogger.isOn &&
1289                             SSLLogger.isOn("ssl,handshake,verbose")) {
1290                         SSLLogger.finest(
1291                             "Can't resume, " +
1292                             "the existing session is not rejoinable");
1293                     }
1294                 }
1295                 // Validate the negotiated protocol version.
1296                 if (resumingSession) {
1297                     ProtocolVersion sessionProtocol =
1298                             previous.getProtocolVersion();
1299                     if (sessionProtocol != shc.negotiatedProtocol) {
1300                         resumingSession = false;
1301                         if (SSLLogger.isOn &&
1302                                 SSLLogger.isOn("ssl,handshake,verbose")) {
1303                             SSLLogger.finest(
1304                                 "Can't resume, not the same protocol version");
1305                         }
1306                     }
1307                 }
1308 
1309                 // Validate the required client authentication.
1310                 if (resumingSession &&
1311                     (shc.sslConfig.clientAuthType == CLIENT_AUTH_REQUIRED)) {
1312 
1313                     try {
1314                         previous.getPeerPrincipal();
1315                     } catch (SSLPeerUnverifiedException e) {
1316                         resumingSession = false;
1317                         if (SSLLogger.isOn &&
1318                                 SSLLogger.isOn("ssl,handshake,verbose")) {
1319                             SSLLogger.finest(
1320                                 "Can't resume, " +
1321                                 "client authentication is required");
1322                         }
1323                     }
1324                 }
1325 
1326                 // Validate that the cached cipher suite.
1327                 if (resumingSession) {
1328                     CipherSuite suite = previous.getSuite();
1329                     if ((!shc.isNegotiable(suite)) ||
1330                             (!clientHello.cipherSuites.contains(suite))) {
1331                         resumingSession = false;
1332                         if (SSLLogger.isOn &&
1333                                 SSLLogger.isOn("ssl,handshake,verbose")) {
1334                             SSLLogger.finest(
1335                                 "Can't resume, " +
1336                                 "the session cipher suite is absent");
1337                         }
1338                     }
1339                 }
1340 
1341                 // So far so good.  Note that the handshake extensions may reset
1342                 // the resuming options later.
1343                 shc.isResumption = resumingSession;
1344                 shc.resumingSession = resumingSession ? previous : null;
1345             }
1346 
1347             HelloCookieManager hcm =
1348                 shc.sslContext.getHelloCookieManager(ProtocolVersion.DTLS10);
1349             if (!shc.isResumption &&
1350                 !hcm.isCookieValid(shc, clientHello, clientHello.cookie)) {
1351                 //
1352                 // Perform cookie exchange for DTLS handshaking if no cookie
1353                 // or the cookie is invalid in the ClientHello message.
1354                 //
1355                 // update the responders
1356                 shc.handshakeProducers.put(
1357                         SSLHandshake.HELLO_VERIFY_REQUEST.id,
1358                         SSLHandshake.HELLO_VERIFY_REQUEST);
1359 
1360                 //
1361                 // produce response handshake message
1362                 //
1363                 SSLHandshake.HELLO_VERIFY_REQUEST.produce(context, clientHello);
1364 
1365                 return;
1366             }
1367 
1368             // cache the client random number for further using
1369             shc.clientHelloRandom = clientHello.clientRandom;
1370 
1371             // Check and launch ClientHello extensions.
1372             SSLExtension[] extTypes = shc.sslConfig.getEnabledExtensions(
1373                     SSLHandshake.CLIENT_HELLO);
1374             clientHello.extensions.consumeOnLoad(shc, extTypes);
1375 
1376             //
1377             // update
1378             //
1379             if (!shc.conContext.isNegotiated) {
1380                 shc.conContext.protocolVersion = shc.negotiatedProtocol;
1381                 shc.conContext.outputRecord.setVersion(shc.negotiatedProtocol);
1382             }
1383 
1384             // update the responders
1385             //
1386             // Only need to ServerHello, which may add more responders later.
1387             shc.handshakeProducers.put(SSLHandshake.SERVER_HELLO.id,
1388                     SSLHandshake.SERVER_HELLO);
1389 
1390             //
1391             // produce
1392             //
1393             SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
1394                 SSLHandshake.SERVER_HELLO,
1395 
1396                 // full handshake messages
1397                 SSLHandshake.CERTIFICATE,
1398                 SSLHandshake.CERTIFICATE_STATUS,
1399                 SSLHandshake.SERVER_KEY_EXCHANGE,
1400                 SSLHandshake.CERTIFICATE_REQUEST,
1401                 SSLHandshake.SERVER_HELLO_DONE,
1402 
1403                 // abbreviated handshake messages
1404                 SSLHandshake.FINISHED
1405             };
1406 
1407             for (SSLHandshake hs : probableHandshakeMessages) {
1408                 HandshakeProducer handshakeProducer =
1409                         shc.handshakeProducers.remove(hs.id);
1410                 if (handshakeProducer != null) {
1411                     handshakeProducer.produce(context, clientHello);
1412                 }
1413             }
1414         }
1415     }
1416 
1417     /**
1418      * The "ClientHello" handshake message consumer for DTLS 1.3.
1419      */
1420     private static final
1421             class D13ClientHelloConsumer implements HandshakeConsumer {
1422         // Prevent instantiation of this class.
1423         private D13ClientHelloConsumer() {
1424             // blank
1425         }
1426 
1427         @Override
1428         public void consume(ConnectionContext context,
1429                 HandshakeMessage message) throws IOException {
1430             throw new UnsupportedOperationException("Not supported yet.");
1431         }
1432     }
1433 }