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