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