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.AlgorithmConstraints;
  31 import java.security.GeneralSecurityException;
  32 import java.text.MessageFormat;
  33 import java.util.Arrays;
  34 import java.util.LinkedList;
  35 import java.util.List;
  36 import java.util.Locale;
  37 import java.util.Map;
  38 import javax.crypto.SecretKey;
  39 import javax.crypto.spec.IvParameterSpec;
  40 import javax.net.ssl.SSLException;
  41 import javax.net.ssl.SSLHandshakeException;
  42 import javax.net.ssl.SSLProtocolException;
  43 import sun.security.ssl.CipherSuite.KeyExchange;
  44 import sun.security.ssl.ClientHello.ClientHelloMessage;
  45 import sun.security.ssl.SSLCipher.SSLReadCipher;
  46 import sun.security.ssl.SSLCipher.SSLWriteCipher;
  47 import sun.security.ssl.SSLHandshake.HandshakeMessage;
  48 import sun.security.ssl.SupportedVersionsExtension.SHSupportedVersionsSpec;
  49 
  50 import static sun.security.ssl.SSLExtension.SH_SESSION_TICKET;
  51 
  52 /**
  53  * Pack of the ServerHello/HelloRetryRequest handshake message.
  54  */
  55 final class ServerHello {
  56     static final SSLConsumer handshakeConsumer =
  57         new ServerHelloConsumer();
  58     static final HandshakeProducer t12HandshakeProducer =
  59         new T12ServerHelloProducer();
  60     static final HandshakeProducer t13HandshakeProducer =
  61         new T13ServerHelloProducer();
  62     static final HandshakeProducer hrrHandshakeProducer =
  63         new T13HelloRetryRequestProducer();
  64 
  65     static final HandshakeProducer hrrReproducer =
  66         new T13HelloRetryRequestReproducer();
  67 
  68     private static final HandshakeConsumer t12HandshakeConsumer =
  69         new T12ServerHelloConsumer();
  70     private static final HandshakeConsumer t13HandshakeConsumer =
  71         new T13ServerHelloConsumer();
  72 
  73     private static final HandshakeConsumer d12HandshakeConsumer =
  74         new T12ServerHelloConsumer();
  75     private static final HandshakeConsumer d13HandshakeConsumer =
  76         new T13ServerHelloConsumer();
  77 
  78     private static final HandshakeConsumer t13HrrHandshakeConsumer =
  79         new T13HelloRetryRequestConsumer();
  80     private static final HandshakeConsumer d13HrrHandshakeConsumer =
  81         new T13HelloRetryRequestConsumer();
  82 
  83     /**
  84      * The ServerHello handshake message.
  85      */
  86     static final class ServerHelloMessage extends HandshakeMessage {
  87         final ProtocolVersion           serverVersion;      // TLS 1.3 legacy
  88         final RandomCookie              serverRandom;
  89         final SessionId                 sessionId;          // TLS 1.3 legacy
  90         final CipherSuite               cipherSuite;
  91         final byte                      compressionMethod;  // TLS 1.3 legacy
  92         final SSLExtensions             extensions;
  93 
  94         // The HelloRetryRequest producer needs to use the ClientHello message
  95         // for cookie generation.  Please don't use this field for other
  96         // purpose unless it is really necessary.
  97         final ClientHelloMessage        clientHello;
  98 
  99         // Reserved for HelloRetryRequest consumer.  Please don't use this
 100         // field for other purpose unless it is really necessary.
 101         final ByteBuffer                handshakeRecord;
 102 
 103         ServerHelloMessage(HandshakeContext context,
 104                 ProtocolVersion serverVersion, SessionId sessionId,
 105                 CipherSuite cipherSuite, RandomCookie serverRandom,
 106                 ClientHelloMessage clientHello) {
 107             super(context);
 108 
 109             this.serverVersion = serverVersion;
 110             this.serverRandom = serverRandom;
 111             this.sessionId = sessionId;
 112             this.cipherSuite = cipherSuite;
 113             this.compressionMethod = 0x00;      // Don't support compression.
 114             this.extensions = new SSLExtensions(this);
 115 
 116             // Reserve the ClientHello message for cookie generation.
 117             this.clientHello = clientHello;
 118 
 119             // The handshakeRecord field is used for HelloRetryRequest consumer
 120             // only.  It's fine to set it to null for generating side of the
 121             // ServerHello/HelloRetryRequest message.
 122             this.handshakeRecord = null;
 123         }
 124 
 125         ServerHelloMessage(HandshakeContext context,
 126                 ByteBuffer m) throws IOException {
 127             super(context);
 128 
 129             // Reserve for HelloRetryRequest consumer if needed.
 130             this.handshakeRecord = m.duplicate();
 131 
 132             byte major = m.get();
 133             byte minor = m.get();
 134             this.serverVersion = ProtocolVersion.valueOf(major, minor);
 135             if (this.serverVersion == null) {
 136                 // The client should only request for known protocol versions.
 137                 throw context.conContext.fatal(Alert.PROTOCOL_VERSION,
 138                     "Unsupported protocol version: " +
 139                     ProtocolVersion.nameOf(major, minor));
 140             }
 141 
 142             this.serverRandom = new RandomCookie(m);
 143             this.sessionId = new SessionId(Record.getBytes8(m));
 144             try {
 145                 sessionId.checkLength(serverVersion.id);
 146             } catch (SSLProtocolException ex) {
 147                 throw handshakeContext.conContext.fatal(
 148                         Alert.ILLEGAL_PARAMETER, ex);
 149             }
 150 
 151             int cipherSuiteId = Record.getInt16(m);
 152             this.cipherSuite = CipherSuite.valueOf(cipherSuiteId);
 153             if (cipherSuite == null || !context.isNegotiable(cipherSuite)) {
 154                 throw context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 155                     "Server selected improper ciphersuite " +
 156                     CipherSuite.nameOf(cipherSuiteId));
 157             }
 158 
 159             this.compressionMethod = m.get();
 160             if (compressionMethod != 0) {
 161                 throw context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 162                     "compression type not supported, " + compressionMethod);
 163             }
 164 
 165             SSLExtension[] supportedExtensions;
 166             if (serverRandom.isHelloRetryRequest()) {
 167                 supportedExtensions = context.sslConfig.getEnabledExtensions(
 168                             SSLHandshake.HELLO_RETRY_REQUEST);
 169             } else {
 170                 supportedExtensions = context.sslConfig.getEnabledExtensions(
 171                             SSLHandshake.SERVER_HELLO);
 172             }
 173 
 174             if (m.hasRemaining()) {
 175                 this.extensions =
 176                     new SSLExtensions(this, m, supportedExtensions);
 177             } else {
 178                 this.extensions = new SSLExtensions(this);
 179             }
 180 
 181             // The clientHello field is used for HelloRetryRequest producer
 182             // only.  It's fine to set it to null for receiving side of
 183             // ServerHello/HelloRetryRequest message.
 184             this.clientHello = null;        // not used, let it be null;
 185         }
 186 
 187         @Override
 188         public SSLHandshake handshakeType() {
 189             return serverRandom.isHelloRetryRequest() ?
 190                 SSLHandshake.HELLO_RETRY_REQUEST : SSLHandshake.SERVER_HELLO;
 191         }
 192 
 193         @Override
 194         public int messageLength() {
 195             // almost fixed header size, except session ID and extensions:
 196             //      major + minor = 2
 197             //      random = 32
 198             //      session ID len field = 1
 199             //      cipher suite = 2
 200             //      compression = 1
 201             //      extensions: if present, 2 + length of extensions
 202             // In TLS 1.3, use of certain extensions is mandatory.
 203             return 38 + sessionId.length() + extensions.length();
 204         }
 205 
 206         @Override
 207         public void send(HandshakeOutStream hos) throws IOException {
 208             hos.putInt8(serverVersion.major);
 209             hos.putInt8(serverVersion.minor);
 210             hos.write(serverRandom.randomBytes);
 211             hos.putBytes8(sessionId.getId());
 212             hos.putInt8((cipherSuite.id >> 8) & 0xFF);
 213             hos.putInt8(cipherSuite.id & 0xff);
 214             hos.putInt8(compressionMethod);
 215 
 216             extensions.send(hos);           // In TLS 1.3, use of certain
 217                                             // extensions is mandatory.
 218         }
 219 
 220         @Override
 221         public String toString() {
 222             MessageFormat messageFormat = new MessageFormat(
 223                 "\"{0}\": '{'\n" +
 224                 "  \"server version\"      : \"{1}\",\n" +
 225                 "  \"random\"              : \"{2}\",\n" +
 226                 "  \"session id\"          : \"{3}\",\n" +
 227                 "  \"cipher suite\"        : \"{4}\",\n" +
 228                 "  \"compression methods\" : \"{5}\",\n" +
 229                 "  \"extensions\"          : [\n" +
 230                 "{6}\n" +
 231                 "  ]\n" +
 232                 "'}'",
 233                 Locale.ENGLISH);
 234             Object[] messageFields = {
 235                 serverRandom.isHelloRetryRequest() ?
 236                     "HelloRetryRequest" : "ServerHello",
 237                 serverVersion.name,
 238                 Utilities.toHexString(serverRandom.randomBytes),
 239                 sessionId.toString(),
 240                 cipherSuite.name + "(" +
 241                         Utilities.byte16HexString(cipherSuite.id) + ")",
 242                 Utilities.toHexString(compressionMethod),
 243                 Utilities.indent(extensions.toString(), "    ")
 244             };
 245 
 246             return messageFormat.format(messageFields);
 247         }
 248     }
 249 
 250     /**
 251      * The "ServerHello" handshake message producer.
 252      */
 253     private static final class T12ServerHelloProducer
 254             implements HandshakeProducer {
 255 
 256         // Prevent instantiation of this class.
 257         private T12ServerHelloProducer() {
 258             // blank
 259         }
 260 
 261         @Override
 262         public byte[] produce(ConnectionContext context,
 263                 HandshakeMessage message) throws IOException {
 264             // The producing happens in server side only.
 265             ServerHandshakeContext shc = (ServerHandshakeContext)context;
 266             ClientHelloMessage clientHello = (ClientHelloMessage)message;
 267 
 268             // If client hasn't specified a session we can resume, start a
 269             // new one and choose its cipher suite and compression options,
 270             // unless new session creation is disabled for this connection!
 271             if (!shc.isResumption || shc.resumingSession == null) {
 272                 if (!shc.sslConfig.enableSessionCreation) {
 273                     throw new SSLException(
 274                         "Not resumption, and no new session is allowed");
 275                 }
 276 
 277                 if (shc.localSupportedSignAlgs == null) {
 278                     shc.localSupportedSignAlgs =
 279                         SignatureScheme.getSupportedAlgorithms(
 280                                 shc.algorithmConstraints, shc.activeProtocols);
 281                 }
 282 
 283                 SSLSessionImpl session =
 284                         new SSLSessionImpl(shc, CipherSuite.C_NULL);
 285                 session.setMaximumPacketSize(shc.sslConfig.maximumPacketSize);
 286                 shc.handshakeSession = session;
 287 
 288                 // consider the handshake extension impact
 289                 SSLExtension[] enabledExtensions =
 290                         shc.sslConfig.getEnabledExtensions(
 291                             SSLHandshake.CLIENT_HELLO, shc.negotiatedProtocol);
 292                 clientHello.extensions.consumeOnTrade(shc, enabledExtensions);
 293 
 294                 // negotiate the cipher suite.
 295                 KeyExchangeProperties credentials =
 296                         chooseCipherSuite(shc, clientHello);
 297                 if (credentials == null) {
 298                     throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 299                             "no cipher suites in common");
 300                 }
 301                 shc.negotiatedCipherSuite = credentials.cipherSuite;
 302                 shc.handshakeKeyExchange = credentials.keyExchange;
 303                 shc.handshakeSession.setSuite(credentials.cipherSuite);
 304                 shc.handshakePossessions.addAll(
 305                         Arrays.asList(credentials.possessions));
 306                 shc.handshakeHash.determine(
 307                         shc.negotiatedProtocol, shc.negotiatedCipherSuite);
 308 
 309                 // Check the incoming OCSP stapling extensions and attempt
 310                 // to get responses.  If the resulting stapleParams is non
 311                 // null, it implies that stapling is enabled on the server side.
 312                 shc.stapleParams = StatusResponseManager.processStapling(shc);
 313                 shc.staplingActive = (shc.stapleParams != null);
 314 
 315                 // update the responders
 316                 SSLKeyExchange ke = credentials.keyExchange;
 317                 if (ke != null) {
 318                     for (Map.Entry<Byte, HandshakeProducer> me :
 319                             ke.getHandshakeProducers(shc)) {
 320                         shc.handshakeProducers.put(
 321                                 me.getKey(), me.getValue());
 322                     }
 323                 }
 324 
 325                 if ((ke != null) &&
 326                         (shc.sslConfig.clientAuthType !=
 327                                 ClientAuthType.CLIENT_AUTH_NONE) &&
 328                         !shc.negotiatedCipherSuite.isAnonymous()) {
 329                     for (SSLHandshake hs :
 330                             ke.getRelatedHandshakers(shc)) {
 331                         if (hs == SSLHandshake.CERTIFICATE) {
 332                             shc.handshakeProducers.put(
 333                                     SSLHandshake.CERTIFICATE_REQUEST.id,
 334                                     SSLHandshake.CERTIFICATE_REQUEST);
 335                             break;
 336                         }
 337                     }
 338                 }
 339                 shc.handshakeProducers.put(SSLHandshake.SERVER_HELLO_DONE.id,
 340                         SSLHandshake.SERVER_HELLO_DONE);
 341             } else {
 342                 // stateless and use the client session id (RFC 5077 3.4)
 343                 if (shc.statelessResumption) {
 344                     shc.resumingSession = new SSLSessionImpl(shc.resumingSession,
 345                             (clientHello.sessionId.length() == 0) ?
 346                                     new SessionId(true,
 347                                             shc.sslContext.getSecureRandom()) :
 348                                     new SessionId(clientHello.sessionId.getId())
 349                     );
 350                 }
 351                 shc.handshakeSession = shc.resumingSession;
 352                 shc.negotiatedProtocol =
 353                         shc.resumingSession.getProtocolVersion();
 354                 shc.negotiatedCipherSuite = shc.resumingSession.getSuite();
 355                 shc.handshakeHash.determine(
 356                         shc.negotiatedProtocol, shc.negotiatedCipherSuite);
 357             }
 358 
 359             // Generate the ServerHello handshake message.
 360             ServerHelloMessage shm = new ServerHelloMessage(shc,
 361                     shc.negotiatedProtocol,
 362                     shc.handshakeSession.getSessionId(),
 363                     shc.negotiatedCipherSuite,
 364                     new RandomCookie(shc),
 365                     clientHello);
 366             shc.serverHelloRandom = shm.serverRandom;
 367 
 368             // Produce extensions for ServerHello handshake message.
 369             SSLExtension[] serverHelloExtensions =
 370                 shc.sslConfig.getEnabledExtensions(
 371                         SSLHandshake.SERVER_HELLO, shc.negotiatedProtocol);
 372             shm.extensions.produce(shc, serverHelloExtensions);
 373             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 374                 SSLLogger.fine("Produced ServerHello handshake message", shm);
 375             }
 376 
 377             // Output the handshake message.
 378             shm.write(shc.handshakeOutput);
 379             shc.handshakeOutput.flush();
 380 
 381             if (shc.isResumption && shc.resumingSession != null) {
 382                 SSLTrafficKeyDerivation kdg =
 383                     SSLTrafficKeyDerivation.valueOf(shc.negotiatedProtocol);
 384                 if (kdg == null) {
 385                     // unlikely
 386                     throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
 387                             "Not supported key derivation: " +
 388                             shc.negotiatedProtocol);
 389                 } else {
 390                     shc.handshakeKeyDerivation = kdg.createKeyDerivation(
 391                             shc, shc.resumingSession.getMasterSecret());
 392                 }
 393 
 394                 // update the responders
 395                 shc.handshakeProducers.put(SSLHandshake.FINISHED.id,
 396                         SSLHandshake.FINISHED);
 397             }
 398 
 399             // The handshake message has been delivered.
 400             return null;
 401         }
 402 
 403         private static KeyExchangeProperties chooseCipherSuite(
 404                 ServerHandshakeContext shc,
 405                 ClientHelloMessage clientHello) throws IOException {
 406             List<CipherSuite> preferred;
 407             List<CipherSuite> proposed;
 408             if (shc.sslConfig.preferLocalCipherSuites) {
 409                 preferred = shc.activeCipherSuites;
 410                 proposed = clientHello.cipherSuites;
 411             } else {
 412                 preferred = clientHello.cipherSuites;
 413                 proposed = shc.activeCipherSuites;
 414             }
 415 
 416             List<CipherSuite> legacySuites = new LinkedList<>();
 417             for (CipherSuite cs : preferred) {
 418                 if (!HandshakeContext.isNegotiable(
 419                         proposed, shc.negotiatedProtocol, cs)) {
 420                     continue;
 421                 }
 422 
 423                 if (shc.sslConfig.clientAuthType ==
 424                         ClientAuthType.CLIENT_AUTH_REQUIRED) {
 425                     if ((cs.keyExchange == KeyExchange.K_DH_ANON) ||
 426                         (cs.keyExchange == KeyExchange.K_ECDH_ANON)) {
 427                         continue;
 428                     }
 429                 }
 430 
 431                 SSLKeyExchange ke = SSLKeyExchange.valueOf(
 432                         cs.keyExchange, shc.negotiatedProtocol);
 433                 if (ke == null) {
 434                     continue;
 435                 }
 436                 if (!ServerHandshakeContext.legacyAlgorithmConstraints.permits(
 437                         null, cs.name, null)) {
 438                     legacySuites.add(cs);
 439                     continue;
 440                 }
 441 
 442                 SSLPossession[] hcds = ke.createPossessions(shc);
 443                 if ((hcds == null) || (hcds.length == 0)) {
 444                     continue;
 445                 }
 446 
 447                 // The cipher suite has been negotiated.
 448                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 449                     SSLLogger.fine("use cipher suite " + cs.name);
 450                 }
 451 
 452                 return new KeyExchangeProperties(cs, ke, hcds);
 453             }
 454 
 455             for (CipherSuite cs : legacySuites) {
 456                 SSLKeyExchange ke = SSLKeyExchange.valueOf(
 457                         cs.keyExchange,  shc.negotiatedProtocol);
 458                 if (ke != null) {
 459                     SSLPossession[] hcds = ke.createPossessions(shc);
 460                     if ((hcds != null) && (hcds.length != 0)) {
 461                         if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 462                             SSLLogger.warning(
 463                                 "use legacy cipher suite " + cs.name);
 464                         }
 465                         return new KeyExchangeProperties(cs, ke, hcds);
 466                     }
 467                 }
 468             }
 469 
 470             throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 471                     "no cipher suites in common");
 472         }
 473 
 474         private static final class KeyExchangeProperties {
 475             final CipherSuite cipherSuite;
 476             final SSLKeyExchange keyExchange;
 477             final SSLPossession[] possessions;
 478 
 479             private KeyExchangeProperties(CipherSuite cipherSuite,
 480                     SSLKeyExchange keyExchange, SSLPossession[] possessions) {
 481                 this.cipherSuite = cipherSuite;
 482                 this.keyExchange = keyExchange;
 483                 this.possessions = possessions;
 484             }
 485         }
 486     }
 487 
 488     /**
 489      * The "ServerHello" handshake message producer.
 490      */
 491     private static final
 492             class T13ServerHelloProducer implements HandshakeProducer {
 493         // Prevent instantiation of this class.
 494         private T13ServerHelloProducer() {
 495             // blank
 496         }
 497 
 498         @Override
 499         public byte[] produce(ConnectionContext context,
 500                 HandshakeMessage message) throws IOException {
 501             // The producing happens in server side only.
 502             ServerHandshakeContext shc = (ServerHandshakeContext)context;
 503             ClientHelloMessage clientHello = (ClientHelloMessage)message;
 504 
 505             SSLSessionContextImpl sessionCache = (SSLSessionContextImpl)
 506                     shc.sslContext.engineGetServerSessionContext();
 507 
 508             // If client hasn't specified a session we can resume, start a
 509             // new one and choose its cipher suite and compression options,
 510             // unless new session creation is disabled for this connection!
 511             if (!shc.isResumption || shc.resumingSession == null) {
 512                 if (!shc.sslConfig.enableSessionCreation) {
 513                     throw new SSLException(
 514                         "Not resumption, and no new session is allowed");
 515                 }
 516 
 517                 if (shc.localSupportedSignAlgs == null) {
 518                     shc.localSupportedSignAlgs =
 519                         SignatureScheme.getSupportedAlgorithms(
 520                                 shc.algorithmConstraints, shc.activeProtocols);
 521                 }
 522 
 523                 SSLSessionImpl session =
 524                         new SSLSessionImpl(shc, CipherSuite.C_NULL);
 525                 session.setMaximumPacketSize(shc.sslConfig.maximumPacketSize);
 526                 shc.handshakeSession = session;
 527 
 528                 // consider the handshake extension impact
 529                 SSLExtension[] enabledExtensions =
 530                         shc.sslConfig.getEnabledExtensions(
 531                             SSLHandshake.CLIENT_HELLO, shc.negotiatedProtocol);
 532                 clientHello.extensions.consumeOnTrade(shc, enabledExtensions);
 533 
 534                 // negotiate the cipher suite.
 535                 CipherSuite cipherSuite = chooseCipherSuite(shc, clientHello);
 536                 if (cipherSuite == null) {
 537                     throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 538                             "no cipher suites in common");
 539                 }
 540                 shc.negotiatedCipherSuite = cipherSuite;
 541                 shc.handshakeSession.setSuite(cipherSuite);
 542                 shc.handshakeHash.determine(
 543                         shc.negotiatedProtocol, shc.negotiatedCipherSuite);
 544             } else {
 545                 shc.handshakeSession = shc.resumingSession;
 546 
 547                 // consider the handshake extension impact
 548                 SSLExtension[] enabledExtensions =
 549                 shc.sslConfig.getEnabledExtensions(
 550                 SSLHandshake.CLIENT_HELLO, shc.negotiatedProtocol);
 551                 clientHello.extensions.consumeOnTrade(shc, enabledExtensions);
 552 
 553                 shc.negotiatedProtocol =
 554                         shc.resumingSession.getProtocolVersion();
 555                 shc.negotiatedCipherSuite = shc.resumingSession.getSuite();
 556                 shc.handshakeHash.determine(
 557                         shc.negotiatedProtocol, shc.negotiatedCipherSuite);
 558 
 559                 setUpPskKD(shc,
 560                         shc.resumingSession.consumePreSharedKey());
 561 
 562                 // The session can't be resumed again---remove it from cache
 563                 sessionCache.remove(shc.resumingSession.getSessionId());
 564             }
 565 
 566             // update the responders
 567             shc.handshakeProducers.put(SSLHandshake.ENCRYPTED_EXTENSIONS.id,
 568                     SSLHandshake.ENCRYPTED_EXTENSIONS);
 569             shc.handshakeProducers.put(SSLHandshake.FINISHED.id,
 570                     SSLHandshake.FINISHED);
 571 
 572             // Generate the ServerHello handshake message.
 573             ServerHelloMessage shm = new ServerHelloMessage(shc,
 574                     ProtocolVersion.TLS12,      // use legacy version
 575                     clientHello.sessionId,      // echo back
 576                     shc.negotiatedCipherSuite,
 577                     new RandomCookie(shc),
 578                     clientHello);
 579             shc.serverHelloRandom = shm.serverRandom;
 580 
 581             // Produce extensions for ServerHello handshake message.
 582             SSLExtension[] serverHelloExtensions =
 583                     shc.sslConfig.getEnabledExtensions(
 584                         SSLHandshake.SERVER_HELLO, shc.negotiatedProtocol);
 585             shm.extensions.produce(shc, serverHelloExtensions);
 586             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 587                 SSLLogger.fine("Produced ServerHello handshake message", shm);
 588             }
 589 
 590             // Output the handshake message.
 591             shm.write(shc.handshakeOutput);
 592             shc.handshakeOutput.flush();
 593 
 594             // Change client/server handshake traffic secrets.
 595             // Refresh handshake hash
 596             shc.handshakeHash.update();
 597 
 598             // Change client/server handshake traffic secrets.
 599             SSLKeyExchange ke = shc.handshakeKeyExchange;
 600             if (ke == null) {
 601                 // unlikely
 602                 throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
 603                         "Not negotiated key shares");
 604             }
 605 
 606             SSLKeyDerivation handshakeKD = ke.createKeyDerivation(shc);
 607             SecretKey handshakeSecret = handshakeKD.deriveKey(
 608                     "TlsHandshakeSecret", null);
 609 
 610             SSLTrafficKeyDerivation kdg =
 611                 SSLTrafficKeyDerivation.valueOf(shc.negotiatedProtocol);
 612             if (kdg == null) {
 613                 // unlikely
 614                 throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
 615                         "Not supported key derivation: " +
 616                         shc.negotiatedProtocol);
 617             }
 618 
 619             SSLKeyDerivation kd =
 620                     new SSLSecretDerivation(shc, handshakeSecret);
 621 
 622             // update the handshake traffic read keys.
 623             SecretKey readSecret = kd.deriveKey(
 624                     "TlsClientHandshakeTrafficSecret", null);
 625             SSLKeyDerivation readKD =
 626                     kdg.createKeyDerivation(shc, readSecret);
 627             SecretKey readKey = readKD.deriveKey(
 628                     "TlsKey", null);
 629             SecretKey readIvSecret = readKD.deriveKey(
 630                     "TlsIv", null);
 631             IvParameterSpec readIv =
 632                     new IvParameterSpec(readIvSecret.getEncoded());
 633             SSLReadCipher readCipher;
 634             try {
 635                 readCipher =
 636                     shc.negotiatedCipherSuite.bulkCipher.createReadCipher(
 637                         Authenticator.valueOf(shc.negotiatedProtocol),
 638                         shc.negotiatedProtocol, readKey, readIv,
 639                         shc.sslContext.getSecureRandom());
 640             } catch (GeneralSecurityException gse) {
 641                 // unlikely
 642                 throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 643                         "Missing cipher algorithm", gse);
 644             }
 645 
 646             if (readCipher == null) {
 647                 throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 648                     "Illegal cipher suite (" + shc.negotiatedCipherSuite +
 649                     ") and protocol version (" + shc.negotiatedProtocol +
 650                     ")");
 651             }
 652 
 653             shc.baseReadSecret = readSecret;
 654             shc.conContext.inputRecord.changeReadCiphers(readCipher);
 655 
 656             // update the handshake traffic write secret.
 657             SecretKey writeSecret = kd.deriveKey(
 658                     "TlsServerHandshakeTrafficSecret", null);
 659             SSLKeyDerivation writeKD =
 660                     kdg.createKeyDerivation(shc, writeSecret);
 661             SecretKey writeKey = writeKD.deriveKey(
 662                     "TlsKey", null);
 663             SecretKey writeIvSecret = writeKD.deriveKey(
 664                     "TlsIv", null);
 665             IvParameterSpec writeIv =
 666                     new IvParameterSpec(writeIvSecret.getEncoded());
 667             SSLWriteCipher writeCipher;
 668             try {
 669                 writeCipher =
 670                     shc.negotiatedCipherSuite.bulkCipher.createWriteCipher(
 671                         Authenticator.valueOf(shc.negotiatedProtocol),
 672                         shc.negotiatedProtocol, writeKey, writeIv,
 673                         shc.sslContext.getSecureRandom());
 674             } catch (GeneralSecurityException gse) {
 675                 // unlikely
 676                 throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 677                         "Missing cipher algorithm", gse);
 678             }
 679 
 680             if (writeCipher == null) {
 681                 throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 682                     "Illegal cipher suite (" + shc.negotiatedCipherSuite +
 683                     ") and protocol version (" + shc.negotiatedProtocol +
 684                     ")");
 685             }
 686 
 687             shc.baseWriteSecret = writeSecret;
 688             shc.conContext.outputRecord.changeWriteCiphers(
 689                     writeCipher, (clientHello.sessionId.length() != 0));
 690 
 691             // Update the context for master key derivation.
 692             shc.handshakeKeyDerivation = kd;
 693 
 694             // Check if the server supports stateless resumption
 695             if (sessionCache.statelessEnabled()) {
 696                 shc.statelessResumption = true;
 697             }
 698 
 699             // The handshake message has been delivered.
 700             return null;
 701         }
 702 
 703         private static CipherSuite chooseCipherSuite(
 704                 ServerHandshakeContext shc,
 705                 ClientHelloMessage clientHello) throws IOException {
 706             List<CipherSuite> preferred;
 707             List<CipherSuite> proposed;
 708             if (shc.sslConfig.preferLocalCipherSuites) {
 709                 preferred = shc.activeCipherSuites;
 710                 proposed = clientHello.cipherSuites;
 711             } else {
 712                 preferred = clientHello.cipherSuites;
 713                 proposed = shc.activeCipherSuites;
 714             }
 715 
 716             CipherSuite legacySuite = null;
 717             AlgorithmConstraints legacyConstraints =
 718                     ServerHandshakeContext.legacyAlgorithmConstraints;
 719             for (CipherSuite cs : preferred) {
 720                 if (!HandshakeContext.isNegotiable(
 721                         proposed, shc.negotiatedProtocol, cs)) {
 722                     continue;
 723                 }
 724 
 725                 if ((legacySuite == null) &&
 726                         !legacyConstraints.permits(null, cs.name, null)) {
 727                     legacySuite = cs;
 728                     continue;
 729                 }
 730 
 731                 // The cipher suite has been negotiated.
 732                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 733                     SSLLogger.fine("use cipher suite " + cs.name);
 734                 }
 735                 return cs;
 736             }
 737 
 738             if (legacySuite != null) {
 739                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 740                     SSLLogger.warning(
 741                             "use legacy cipher suite " + legacySuite.name);
 742                 }
 743                 return legacySuite;
 744             }
 745 
 746             // no cipher suites in common
 747             return null;
 748         }
 749     }
 750 
 751     /**
 752      * The "HelloRetryRequest" handshake message producer.
 753      */
 754     private static final
 755             class T13HelloRetryRequestProducer implements HandshakeProducer {
 756         // Prevent instantiation of this class.
 757         private T13HelloRetryRequestProducer() {
 758             // blank
 759         }
 760 
 761         @Override
 762         public byte[] produce(ConnectionContext context,
 763                 HandshakeMessage message) throws IOException {
 764             ServerHandshakeContext shc = (ServerHandshakeContext) context;
 765             ClientHelloMessage clientHello = (ClientHelloMessage) message;
 766 
 767             // negotiate the cipher suite.
 768             CipherSuite cipherSuite =
 769                     T13ServerHelloProducer.chooseCipherSuite(shc, clientHello);
 770             if (cipherSuite == null) {
 771                 throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 772                         "no cipher suites in common for hello retry request");
 773             }
 774 
 775             ServerHelloMessage hhrm = new ServerHelloMessage(shc,
 776                     ProtocolVersion.TLS12,      // use legacy version
 777                     clientHello.sessionId,      //  echo back
 778                     cipherSuite,
 779                     RandomCookie.hrrRandom,
 780                     clientHello
 781             );
 782 
 783             shc.negotiatedCipherSuite = cipherSuite;
 784             shc.handshakeHash.determine(
 785                     shc.negotiatedProtocol, shc.negotiatedCipherSuite);
 786 
 787             // Produce extensions for HelloRetryRequest handshake message.
 788             SSLExtension[] serverHelloExtensions =
 789                 shc.sslConfig.getEnabledExtensions(
 790                     SSLHandshake.HELLO_RETRY_REQUEST, shc.negotiatedProtocol);
 791             hhrm.extensions.produce(shc, serverHelloExtensions);
 792             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 793                 SSLLogger.fine(
 794                         "Produced HelloRetryRequest handshake message", hhrm);
 795             }
 796 
 797             // Output the handshake message.
 798             hhrm.write(shc.handshakeOutput);
 799             shc.handshakeOutput.flush();
 800 
 801             // Stateless, shall we clean up the handshake context as well?
 802             shc.handshakeHash.finish();     // forgot about the handshake hash
 803             shc.handshakeExtensions.clear();
 804 
 805             // What's the expected response?
 806             shc.handshakeConsumers.put(
 807                     SSLHandshake.CLIENT_HELLO.id, SSLHandshake.CLIENT_HELLO);
 808 
 809             // The handshake message has been delivered.
 810             return null;
 811         }
 812     }
 813 
 814     /**
 815      * The "HelloRetryRequest" handshake message reproducer.
 816      */
 817     private static final
 818             class T13HelloRetryRequestReproducer implements HandshakeProducer {
 819         // Prevent instantiation of this class.
 820         private T13HelloRetryRequestReproducer() {
 821             // blank
 822         }
 823 
 824         @Override
 825         public byte[] produce(ConnectionContext context,
 826                 HandshakeMessage message) throws IOException {
 827             ServerHandshakeContext shc = (ServerHandshakeContext) context;
 828             ClientHelloMessage clientHello = (ClientHelloMessage) message;
 829 
 830             // negotiate the cipher suite.
 831             CipherSuite cipherSuite = shc.negotiatedCipherSuite;
 832             ServerHelloMessage hhrm = new ServerHelloMessage(shc,
 833                     ProtocolVersion.TLS12,      // use legacy version
 834                     clientHello.sessionId,      //  echo back
 835                     cipherSuite,
 836                     RandomCookie.hrrRandom,
 837                     clientHello
 838             );
 839 
 840             // Produce extensions for HelloRetryRequest handshake message.
 841             SSLExtension[] serverHelloExtensions =
 842                 shc.sslConfig.getEnabledExtensions(
 843                     SSLHandshake.MESSAGE_HASH, shc.negotiatedProtocol);
 844             hhrm.extensions.produce(shc, serverHelloExtensions);
 845             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 846                 SSLLogger.fine(
 847                         "Reproduced HelloRetryRequest handshake message", hhrm);
 848             }
 849 
 850             HandshakeOutStream hos = new HandshakeOutStream(null);
 851             hhrm.write(hos);
 852 
 853             return hos.toByteArray();
 854         }
 855     }
 856 
 857     /**
 858      * The "ServerHello" handshake message consumer.
 859      */
 860     private static final
 861             class ServerHelloConsumer implements SSLConsumer {
 862         // Prevent instantiation of this class.
 863         private ServerHelloConsumer() {
 864             // blank
 865         }
 866 
 867         @Override
 868         public void consume(ConnectionContext context,
 869                 ByteBuffer message) throws IOException {
 870             // The consuming happens in client side only.
 871             ClientHandshakeContext chc = (ClientHandshakeContext)context;
 872 
 873             // clean up this consumer
 874             chc.handshakeConsumers.remove(SSLHandshake.SERVER_HELLO.id);
 875             if (!chc.handshakeConsumers.isEmpty()) {
 876                 // DTLS 1.0/1.2
 877                 chc.handshakeConsumers.remove(
 878                         SSLHandshake.HELLO_VERIFY_REQUEST.id);
 879             }
 880             if (!chc.handshakeConsumers.isEmpty()) {
 881                 throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
 882                     "No more message expected before ServerHello is processed");
 883             }
 884 
 885             ServerHelloMessage shm = new ServerHelloMessage(chc, message);
 886             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 887                 SSLLogger.fine("Consuming ServerHello handshake message", shm);
 888             }
 889 
 890             if (shm.serverRandom.isHelloRetryRequest()) {
 891                 onHelloRetryRequest(chc, shm);
 892             } else {
 893                 onServerHello(chc, shm);
 894             }
 895         }
 896 
 897         private void onHelloRetryRequest(ClientHandshakeContext chc,
 898                 ServerHelloMessage helloRetryRequest) throws IOException {
 899             // Negotiate protocol version.
 900             //
 901             // Check and launch SupportedVersions.
 902             SSLExtension[] extTypes = new SSLExtension[] {
 903                     SSLExtension.HRR_SUPPORTED_VERSIONS
 904                 };
 905             helloRetryRequest.extensions.consumeOnLoad(chc, extTypes);
 906 
 907             ProtocolVersion serverVersion;
 908             SHSupportedVersionsSpec svs =
 909                     (SHSupportedVersionsSpec)chc.handshakeExtensions.get(
 910                             SSLExtension.HRR_SUPPORTED_VERSIONS);
 911             if (svs != null) {
 912                 serverVersion =            // could be null
 913                         ProtocolVersion.valueOf(svs.selectedVersion);
 914             } else {
 915                 serverVersion = helloRetryRequest.serverVersion;
 916             }
 917 
 918             if (!chc.activeProtocols.contains(serverVersion)) {
 919                 throw chc.conContext.fatal(Alert.PROTOCOL_VERSION,
 920                     "The server selected protocol version " + serverVersion +
 921                     " is not accepted by client preferences " +
 922                     chc.activeProtocols);
 923             }
 924 
 925             if (!serverVersion.useTLS13PlusSpec()) {
 926                 throw chc.conContext.fatal(Alert.PROTOCOL_VERSION,
 927                     "Unexpected HelloRetryRequest for " + serverVersion.name);
 928             }
 929 
 930             chc.negotiatedProtocol = serverVersion;
 931             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 932                 SSLLogger.fine(
 933                     "Negotiated protocol version: " + serverVersion.name);
 934             }
 935 
 936             // TLS 1.3 key share extension may have produced client
 937             // possessions for TLS 1.3 key exchanges.
 938             //
 939             // Clean up before producing new client key share possessions.
 940             chc.handshakePossessions.clear();
 941 
 942             if (serverVersion.isDTLS) {
 943                 d13HrrHandshakeConsumer.consume(chc, helloRetryRequest);
 944             } else {
 945                 t13HrrHandshakeConsumer.consume(chc, helloRetryRequest);
 946             }
 947         }
 948 
 949         private void onServerHello(ClientHandshakeContext chc,
 950                 ServerHelloMessage serverHello) throws IOException {
 951             // Negotiate protocol version.
 952             //
 953             // Check and launch SupportedVersions.
 954             SSLExtension[] extTypes = new SSLExtension[] {
 955                     SSLExtension.SH_SUPPORTED_VERSIONS
 956                 };
 957             serverHello.extensions.consumeOnLoad(chc, extTypes);
 958 
 959             ProtocolVersion serverVersion;
 960             SHSupportedVersionsSpec svs =
 961                     (SHSupportedVersionsSpec)chc.handshakeExtensions.get(
 962                             SSLExtension.SH_SUPPORTED_VERSIONS);
 963             if (svs != null) {
 964                 serverVersion =            // could be null
 965                         ProtocolVersion.valueOf(svs.selectedVersion);
 966             } else {
 967                 serverVersion = serverHello.serverVersion;
 968             }
 969 
 970             if (!chc.activeProtocols.contains(serverVersion)) {
 971                 throw chc.conContext.fatal(Alert.PROTOCOL_VERSION,
 972                     "The server selected protocol version " + serverVersion +
 973                     " is not accepted by client preferences " +
 974                     chc.activeProtocols);
 975             }
 976 
 977             chc.negotiatedProtocol = serverVersion;
 978             if (!chc.conContext.isNegotiated) {
 979                 chc.conContext.protocolVersion = chc.negotiatedProtocol;
 980                 chc.conContext.outputRecord.setVersion(chc.negotiatedProtocol);
 981             }
 982             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 983                 SSLLogger.fine(
 984                     "Negotiated protocol version: " + serverVersion.name);
 985             }
 986 
 987             if (serverHello.serverRandom.isVersionDowngrade(chc)) {
 988                 throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 989                     "A potential protocol version downgrade attack");
 990             }
 991 
 992             // Consume the handshake message for the specific protocol version.
 993             if (serverVersion.isDTLS) {
 994                 if (serverVersion.useTLS13PlusSpec()) {
 995                     d13HandshakeConsumer.consume(chc, serverHello);
 996                 } else {
 997                     // TLS 1.3 key share extension may have produced client
 998                     // possessions for TLS 1.3 key exchanges.
 999                     chc.handshakePossessions.clear();
1000 
1001                     d12HandshakeConsumer.consume(chc, serverHello);
1002                 }
1003             } else {
1004                 if (serverVersion.useTLS13PlusSpec()) {
1005                     t13HandshakeConsumer.consume(chc, serverHello);
1006                 } else {
1007                     // TLS 1.3 key share extension may have produced client
1008                     // possessions for TLS 1.3 key exchanges.
1009                     chc.handshakePossessions.clear();
1010 
1011                     t12HandshakeConsumer.consume(chc, serverHello);
1012                 }
1013             }
1014         }
1015     }
1016 
1017     private static final
1018             class T12ServerHelloConsumer implements HandshakeConsumer {
1019         // Prevent instantiation of this class.
1020         private T12ServerHelloConsumer() {
1021             // blank
1022         }
1023 
1024         @Override
1025         public void consume(ConnectionContext context,
1026                 HandshakeMessage message) throws IOException {
1027             // The consuming happens in client side only.
1028             ClientHandshakeContext chc = (ClientHandshakeContext)context;
1029             ServerHelloMessage serverHello = (ServerHelloMessage)message;
1030             if (!chc.isNegotiable(serverHello.serverVersion)) {
1031                 throw chc.conContext.fatal(Alert.PROTOCOL_VERSION,
1032                     "Server chose " + serverHello.serverVersion +
1033                     ", but that protocol version is not enabled or " +
1034                     "not supported by the client.");
1035             }
1036 
1037             // chc.negotiatedProtocol = serverHello.serverVersion;
1038             chc.negotiatedCipherSuite = serverHello.cipherSuite;
1039             chc.handshakeHash.determine(
1040                     chc.negotiatedProtocol, chc.negotiatedCipherSuite);
1041             chc.serverHelloRandom = serverHello.serverRandom;
1042             if (chc.negotiatedCipherSuite.keyExchange == null) {
1043                 throw chc.conContext.fatal(Alert.PROTOCOL_VERSION,
1044                     "TLS 1.2 or prior version does not support the " +
1045                     "server cipher suite: " + chc.negotiatedCipherSuite.name);
1046             }
1047 
1048             //
1049             // validate
1050             //
1051 
1052             // Check and launch the "renegotiation_info" extension.
1053             SSLExtension[] extTypes = new SSLExtension[] {
1054                     SSLExtension.SH_RENEGOTIATION_INFO
1055                 };
1056             serverHello.extensions.consumeOnLoad(chc, extTypes);
1057 
1058             // Is it session resuming?
1059             if (chc.resumingSession != null) {
1060                 // we tried to resume, let's see what the server decided
1061                 if (serverHello.sessionId.equals(
1062                         chc.resumingSession.getSessionId())) {
1063                     // server resumed the session, let's make sure everything
1064                     // checks out
1065 
1066                     // Verify that the session ciphers are unchanged.
1067                     CipherSuite sessionSuite = chc.resumingSession.getSuite();
1068                     if (chc.negotiatedCipherSuite != sessionSuite) {
1069                         throw chc.conContext.fatal(Alert.PROTOCOL_VERSION,
1070                             "Server returned wrong cipher suite for session");
1071                     }
1072 
1073                     // verify protocol version match
1074                     ProtocolVersion sessionVersion =
1075                             chc.resumingSession.getProtocolVersion();
1076                     if (chc.negotiatedProtocol != sessionVersion) {
1077                         throw chc.conContext.fatal(Alert.PROTOCOL_VERSION,
1078                             "Server resumed with wrong protocol version");
1079                     }
1080 
1081                     // looks fine;  resume it.
1082                     chc.isResumption = true;
1083                     chc.resumingSession.setAsSessionResumption(true);
1084                     chc.handshakeSession = chc.resumingSession;
1085                 } else {
1086                     // we wanted to resume, but the server refused
1087                     //
1088                     // Invalidate the session for initial handshake in case
1089                     // of reusing next time.
1090                     if (chc.resumingSession != null) {
1091                         chc.resumingSession.invalidate();
1092                         chc.resumingSession = null;
1093                     }
1094                     chc.isResumption = false;
1095                     if (!chc.sslConfig.enableSessionCreation) {
1096                         throw chc.conContext.fatal(Alert.PROTOCOL_VERSION,
1097                             "New session creation is disabled");
1098                     }
1099                 }
1100             }
1101 
1102             // Check and launch ClientHello extensions.
1103             extTypes = chc.sslConfig.getEnabledExtensions(
1104                     SSLHandshake.SERVER_HELLO);
1105             serverHello.extensions.consumeOnLoad(chc, extTypes);
1106 
1107             if (!chc.isResumption) {
1108                 if (chc.resumingSession != null) {
1109                     // in case the resumption happens next time.
1110                     chc.resumingSession.invalidate();
1111                     chc.resumingSession = null;
1112                 }
1113 
1114                 if (!chc.sslConfig.enableSessionCreation) {
1115                     throw chc.conContext.fatal(Alert.PROTOCOL_VERSION,
1116                         "New session creation is disabled");
1117                 }
1118 
1119                 if (serverHello.sessionId.length() == 0 &&
1120                         chc.statelessResumption) {
1121                     SessionId newId = new SessionId(true,
1122                             chc.sslContext.getSecureRandom());
1123                     chc.handshakeSession = new SSLSessionImpl(chc,
1124                             chc.negotiatedCipherSuite, newId);
1125 
1126                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1127                         SSLLogger.fine("Locally assigned Session Id: " +
1128                                 newId.toString());
1129                     }
1130                 } else {
1131                     chc.handshakeSession = new SSLSessionImpl(chc,
1132                             chc.negotiatedCipherSuite,
1133                             serverHello.sessionId);
1134                 }
1135                 chc.handshakeSession.setMaximumPacketSize(
1136                         chc.sslConfig.maximumPacketSize);
1137             }
1138 
1139             //
1140             // update
1141             //
1142             serverHello.extensions.consumeOnTrade(chc, extTypes);
1143 
1144             // update the consumers and producers
1145             if (chc.isResumption) {
1146                 SSLTrafficKeyDerivation kdg =
1147                         SSLTrafficKeyDerivation.valueOf(chc.negotiatedProtocol);
1148                 if (kdg == null) {
1149                     // unlikely
1150                     throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
1151                             "Not supported key derivation: " +
1152                             chc.negotiatedProtocol);
1153                 } else {
1154                     chc.handshakeKeyDerivation = kdg.createKeyDerivation(
1155                             chc, chc.resumingSession.getMasterSecret());
1156                 }
1157 
1158                 chc.conContext.consumers.putIfAbsent(
1159                         ContentType.CHANGE_CIPHER_SPEC.id,
1160                         ChangeCipherSpec.t10Consumer);
1161                 if (chc.statelessResumption) {
1162                     chc.handshakeConsumers.putIfAbsent(
1163                             SSLHandshake.NEW_SESSION_TICKET.id,
1164                             SSLHandshake.NEW_SESSION_TICKET);
1165                 }
1166                 chc.handshakeConsumers.put(
1167                         SSLHandshake.FINISHED.id,
1168                         SSLHandshake.FINISHED);
1169             } else {
1170                 SSLKeyExchange ke = SSLKeyExchange.valueOf(
1171                         chc.negotiatedCipherSuite.keyExchange,
1172                         chc.negotiatedProtocol);
1173                 chc.handshakeKeyExchange = ke;
1174                 if (ke != null) {
1175                     for (SSLHandshake handshake :
1176                             ke.getRelatedHandshakers(chc)) {
1177                         chc.handshakeConsumers.put(handshake.id, handshake);
1178                     }
1179                 }
1180 
1181                 chc.handshakeConsumers.put(SSLHandshake.SERVER_HELLO_DONE.id,
1182                         SSLHandshake.SERVER_HELLO_DONE);
1183             }
1184 
1185             //
1186             // produce
1187             //
1188             // Need no new handshake message producers here.
1189         }
1190     }
1191 
1192     private static void setUpPskKD(HandshakeContext hc,
1193             SecretKey psk) throws SSLHandshakeException {
1194 
1195         if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1196             SSLLogger.fine("Using PSK to derive early secret");
1197         }
1198 
1199         try {
1200             CipherSuite.HashAlg hashAlg = hc.negotiatedCipherSuite.hashAlg;
1201             HKDF hkdf = new HKDF(hashAlg.name);
1202             byte[] zeros = new byte[hashAlg.hashLength];
1203             SecretKey earlySecret = hkdf.extract(zeros, psk, "TlsEarlySecret");
1204             hc.handshakeKeyDerivation =
1205                     new SSLSecretDerivation(hc, earlySecret);
1206         } catch  (GeneralSecurityException gse) {
1207             throw (SSLHandshakeException) new SSLHandshakeException(
1208                 "Could not generate secret").initCause(gse);
1209         }
1210     }
1211 
1212     private static final
1213             class T13ServerHelloConsumer implements HandshakeConsumer {
1214         // Prevent instantiation of this class.
1215         private T13ServerHelloConsumer() {
1216             // blank
1217         }
1218 
1219         @Override
1220         public void consume(ConnectionContext context,
1221                 HandshakeMessage message) throws IOException {
1222             // The consuming happens in client side only.
1223             ClientHandshakeContext chc = (ClientHandshakeContext)context;
1224             ServerHelloMessage serverHello = (ServerHelloMessage)message;
1225             if (serverHello.serverVersion != ProtocolVersion.TLS12) {
1226                 throw chc.conContext.fatal(Alert.PROTOCOL_VERSION,
1227                     "The ServerHello.legacy_version field is not TLS 1.2");
1228             }
1229 
1230             chc.negotiatedCipherSuite = serverHello.cipherSuite;
1231             chc.handshakeHash.determine(
1232                     chc.negotiatedProtocol, chc.negotiatedCipherSuite);
1233             chc.serverHelloRandom = serverHello.serverRandom;
1234 
1235             //
1236             // validate
1237             //
1238 
1239             // Check and launch ServerHello extensions.
1240             SSLExtension[] extTypes = chc.sslConfig.getEnabledExtensions(
1241                     SSLHandshake.SERVER_HELLO);
1242             serverHello.extensions.consumeOnLoad(chc, extTypes);
1243             if (!chc.isResumption) {
1244                 if (chc.resumingSession != null) {
1245                     // in case the resumption happens next time.
1246                     chc.resumingSession.invalidate();
1247                     chc.resumingSession = null;
1248                 }
1249 
1250                 if (!chc.sslConfig.enableSessionCreation) {
1251                     throw chc.conContext.fatal(Alert.PROTOCOL_VERSION,
1252                         "New session creation is disabled");
1253                 }
1254                 chc.handshakeSession = new SSLSessionImpl(chc,
1255                         chc.negotiatedCipherSuite,
1256                         serverHello.sessionId);
1257                 chc.handshakeSession.setMaximumPacketSize(
1258                         chc.sslConfig.maximumPacketSize);
1259             } else {
1260                 // The PSK is consumed to allow it to be deleted
1261                 SecretKey psk =
1262                         chc.resumingSession.consumePreSharedKey();
1263                 if(psk == null) {
1264                     throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
1265                     "No PSK available. Unable to resume.");
1266                 }
1267 
1268                 chc.handshakeSession = chc.resumingSession;
1269 
1270                 setUpPskKD(chc, psk);
1271             }
1272 
1273             //
1274             // update
1275             //
1276             serverHello.extensions.consumeOnTrade(chc, extTypes);
1277 
1278             // Change client/server handshake traffic secrets.
1279             // Refresh handshake hash
1280             chc.handshakeHash.update();
1281 
1282             SSLKeyExchange ke = chc.handshakeKeyExchange;
1283             if (ke == null) {
1284                 // unlikely
1285                 throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
1286                         "Not negotiated key shares");
1287             }
1288 
1289             SSLKeyDerivation handshakeKD = ke.createKeyDerivation(chc);
1290             SecretKey handshakeSecret = handshakeKD.deriveKey(
1291                     "TlsHandshakeSecret", null);
1292             SSLTrafficKeyDerivation kdg =
1293                 SSLTrafficKeyDerivation.valueOf(chc.negotiatedProtocol);
1294             if (kdg == null) {
1295                 // unlikely
1296                 throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
1297                         "Not supported key derivation: " +
1298                         chc.negotiatedProtocol);
1299             }
1300 
1301             SSLKeyDerivation secretKD =
1302                     new SSLSecretDerivation(chc, handshakeSecret);
1303 
1304             // update the handshake traffic read keys.
1305             SecretKey readSecret = secretKD.deriveKey(
1306                     "TlsServerHandshakeTrafficSecret", null);
1307 
1308             SSLKeyDerivation readKD =
1309                     kdg.createKeyDerivation(chc, readSecret);
1310             SecretKey readKey = readKD.deriveKey(
1311                     "TlsKey", null);
1312             SecretKey readIvSecret = readKD.deriveKey(
1313                     "TlsIv", null);
1314             IvParameterSpec readIv =
1315                     new IvParameterSpec(readIvSecret.getEncoded());
1316             SSLReadCipher readCipher;
1317             try {
1318                 readCipher =
1319                     chc.negotiatedCipherSuite.bulkCipher.createReadCipher(
1320                         Authenticator.valueOf(chc.negotiatedProtocol),
1321                         chc.negotiatedProtocol, readKey, readIv,
1322                         chc.sslContext.getSecureRandom());
1323             } catch (GeneralSecurityException gse) {
1324                 // unlikely
1325                 throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1326                         "Missing cipher algorithm", gse);
1327             }
1328 
1329             if (readCipher == null) {
1330                 throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
1331                     "Illegal cipher suite (" + chc.negotiatedCipherSuite +
1332                     ") and protocol version (" + chc.negotiatedProtocol +
1333                     ")");
1334             }
1335 
1336             chc.baseReadSecret = readSecret;
1337             chc.conContext.inputRecord.changeReadCiphers(readCipher);
1338 
1339             // update the handshake traffic write keys.
1340             SecretKey writeSecret = secretKD.deriveKey(
1341                     "TlsClientHandshakeTrafficSecret", null);
1342             SSLKeyDerivation writeKD =
1343                     kdg.createKeyDerivation(chc, writeSecret);
1344             SecretKey writeKey = writeKD.deriveKey(
1345                     "TlsKey", null);
1346             SecretKey writeIvSecret = writeKD.deriveKey(
1347                     "TlsIv", null);
1348             IvParameterSpec writeIv =
1349                     new IvParameterSpec(writeIvSecret.getEncoded());
1350             SSLWriteCipher writeCipher;
1351             try {
1352                 writeCipher =
1353                     chc.negotiatedCipherSuite.bulkCipher.createWriteCipher(
1354                         Authenticator.valueOf(chc.negotiatedProtocol),
1355                         chc.negotiatedProtocol, writeKey, writeIv,
1356                         chc.sslContext.getSecureRandom());
1357             } catch (GeneralSecurityException gse) {
1358                 // unlikely
1359                 throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1360                         "Missing cipher algorithm", gse);
1361             }
1362 
1363             if (writeCipher == null) {
1364                 throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
1365                     "Illegal cipher suite (" + chc.negotiatedCipherSuite +
1366                     ") and protocol version (" + chc.negotiatedProtocol +
1367                     ")");
1368             }
1369 
1370             chc.baseWriteSecret = writeSecret;
1371             chc.conContext.outputRecord.changeWriteCiphers(
1372                     writeCipher, (serverHello.sessionId.length() != 0));
1373 
1374             // Should use resumption_master_secret for TLS 1.3.
1375             // chc.handshakeSession.setMasterSecret(masterSecret);
1376 
1377             // Update the context for master key derivation.
1378             chc.handshakeKeyDerivation = secretKD;
1379 
1380             // update the consumers and producers
1381             //
1382             // The server sends a dummy change_cipher_spec record immediately
1383             // after its first handshake message.  This may either be after a
1384             // ServerHello or a HelloRetryRequest.
1385             chc.conContext.consumers.putIfAbsent(
1386                     ContentType.CHANGE_CIPHER_SPEC.id,
1387                     ChangeCipherSpec.t13Consumer);
1388 
1389             chc.handshakeConsumers.put(
1390                     SSLHandshake.ENCRYPTED_EXTENSIONS.id,
1391                     SSLHandshake.ENCRYPTED_EXTENSIONS);
1392 
1393             // Support cert authentication only, when not PSK.
1394             chc.handshakeConsumers.put(
1395                     SSLHandshake.CERTIFICATE_REQUEST.id,
1396                     SSLHandshake.CERTIFICATE_REQUEST);
1397             chc.handshakeConsumers.put(
1398                     SSLHandshake.CERTIFICATE.id,
1399                     SSLHandshake.CERTIFICATE);
1400             chc.handshakeConsumers.put(
1401                     SSLHandshake.CERTIFICATE_VERIFY.id,
1402                     SSLHandshake.CERTIFICATE_VERIFY);
1403 
1404             chc.handshakeConsumers.put(
1405                     SSLHandshake.FINISHED.id,
1406                     SSLHandshake.FINISHED);
1407 
1408             //
1409             // produce
1410             //
1411             // Need no new handshake message producers here.
1412         }
1413     }
1414 
1415     private static final
1416             class T13HelloRetryRequestConsumer implements HandshakeConsumer {
1417         // Prevent instantiation of this class.
1418         private T13HelloRetryRequestConsumer() {
1419             // blank
1420         }
1421 
1422         @Override
1423         public void consume(ConnectionContext context,
1424                 HandshakeMessage message) throws IOException {
1425             // The consuming happens in client side only.
1426             ClientHandshakeContext chc = (ClientHandshakeContext)context;
1427             ServerHelloMessage helloRetryRequest = (ServerHelloMessage)message;
1428             if (helloRetryRequest.serverVersion != ProtocolVersion.TLS12) {
1429                 throw chc.conContext.fatal(Alert.PROTOCOL_VERSION,
1430                     "The HelloRetryRequest.legacy_version is not TLS 1.2");
1431             }
1432 
1433             chc.negotiatedCipherSuite = helloRetryRequest.cipherSuite;
1434 
1435             //
1436             // validate
1437             //
1438 
1439             // Check and launch ClientHello extensions.
1440             SSLExtension[] extTypes = chc.sslConfig.getEnabledExtensions(
1441                     SSLHandshake.HELLO_RETRY_REQUEST);
1442             helloRetryRequest.extensions.consumeOnLoad(chc, extTypes);
1443 
1444             //
1445             // update
1446             //
1447             helloRetryRequest.extensions.consumeOnTrade(chc, extTypes);
1448 
1449             // Change client/server handshake traffic secrets.
1450             // Refresh handshake hash
1451             chc.handshakeHash.finish();     // reset the handshake hash
1452 
1453             // calculate the transcript hash of the 1st ClientHello message
1454             HandshakeOutStream hos = new HandshakeOutStream(null);
1455             try {
1456                 chc.initialClientHelloMsg.write(hos);
1457             } catch (IOException ioe) {
1458                 // unlikely
1459                 throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1460                     "Failed to construct message hash", ioe);
1461             }
1462             chc.handshakeHash.deliver(hos.toByteArray());
1463             chc.handshakeHash.determine(
1464                     chc.negotiatedProtocol, chc.negotiatedCipherSuite);
1465             byte[] clientHelloHash = chc.handshakeHash.digest();
1466 
1467             // calculate the message_hash
1468             //
1469             // Transcript-Hash(ClientHello1, HelloRetryRequest, ... Mn) =
1470             //   Hash(message_hash ||    /* Handshake type */
1471             //     00 00 Hash.length ||  /* Handshake message length (bytes) */
1472             //     Hash(ClientHello1) || /* Hash of ClientHello1 */
1473             //     HelloRetryRequest || ... || Mn)
1474             int hashLen = chc.negotiatedCipherSuite.hashAlg.hashLength;
1475             byte[] hashedClientHello = new byte[4 + hashLen];
1476             hashedClientHello[0] = SSLHandshake.MESSAGE_HASH.id;
1477             hashedClientHello[1] = (byte)0x00;
1478             hashedClientHello[2] = (byte)0x00;
1479             hashedClientHello[3] = (byte)(hashLen & 0xFF);
1480             System.arraycopy(clientHelloHash, 0,
1481                     hashedClientHello, 4, hashLen);
1482 
1483             chc.handshakeHash.finish();     // reset the handshake hash
1484             chc.handshakeHash.deliver(hashedClientHello);
1485 
1486             int hrrBodyLen = helloRetryRequest.handshakeRecord.remaining();
1487             byte[] hrrMessage = new byte[4 + hrrBodyLen];
1488             hrrMessage[0] = SSLHandshake.HELLO_RETRY_REQUEST.id;
1489             hrrMessage[1] = (byte)((hrrBodyLen >> 16) & 0xFF);
1490             hrrMessage[2] = (byte)((hrrBodyLen >> 8) & 0xFF);
1491             hrrMessage[3] = (byte)(hrrBodyLen & 0xFF);
1492 
1493             ByteBuffer hrrBody = helloRetryRequest.handshakeRecord.duplicate();
1494             hrrBody.get(hrrMessage, 4, hrrBodyLen);
1495 
1496             chc.handshakeHash.receive(hrrMessage);
1497 
1498             // Update the initial ClientHello handshake message.
1499             chc.initialClientHelloMsg.extensions.reproduce(chc,
1500                     new SSLExtension[] {
1501                         SSLExtension.CH_COOKIE,
1502                         SSLExtension.CH_KEY_SHARE,
1503                         SSLExtension.CH_PRE_SHARED_KEY
1504                     });
1505 
1506             //
1507             // produce response handshake message
1508             //
1509             SSLHandshake.CLIENT_HELLO.produce(context, helloRetryRequest);
1510         }
1511     }
1512 }