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