src/java.base/share/classes/sun/security/ssl/ServerHello.java
changeset 50768 68fa3d4026ea
child 51574 ed52ea83f830
equal deleted inserted replaced
50767:356eaea05bf0 50768:68fa3d4026ea
       
     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 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                 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             ServerHelloMessage shm = new ServerHelloMessage(shc,
       
   348                     shc.negotiatedProtocol,
       
   349                     shc.handshakeSession.getSessionId(),
       
   350                     shc.negotiatedCipherSuite,
       
   351                     new RandomCookie(shc),
       
   352                     clientHello);
       
   353             shc.serverHelloRandom = shm.serverRandom;
       
   354 
       
   355             // Produce extensions for ServerHello handshake message.
       
   356             SSLExtension[] serverHelloExtensions =
       
   357                 shc.sslConfig.getEnabledExtensions(
       
   358                         SSLHandshake.SERVER_HELLO, shc.negotiatedProtocol);
       
   359             shm.extensions.produce(shc, serverHelloExtensions);
       
   360             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   361                 SSLLogger.fine("Produced ServerHello handshake message", shm);
       
   362             }
       
   363 
       
   364             // Output the handshake message.
       
   365             shm.write(shc.handshakeOutput);
       
   366             shc.handshakeOutput.flush();
       
   367 
       
   368             if (shc.isResumption && shc.resumingSession != null) {
       
   369                 SSLTrafficKeyDerivation kdg =
       
   370                     SSLTrafficKeyDerivation.valueOf(shc.negotiatedProtocol);
       
   371                 if (kdg == null) {
       
   372                     // unlikely
       
   373                     shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   374                             "Not supported key derivation: " +
       
   375                             shc.negotiatedProtocol);
       
   376                 } else {
       
   377                     shc.handshakeKeyDerivation = kdg.createKeyDerivation(
       
   378                             shc, shc.resumingSession.getMasterSecret());
       
   379                 }
       
   380 
       
   381                 // update the responders
       
   382                 shc.handshakeProducers.put(SSLHandshake.FINISHED.id,
       
   383                         SSLHandshake.FINISHED);
       
   384             }
       
   385 
       
   386             // The handshake message has been delivered.
       
   387             return null;
       
   388         }
       
   389 
       
   390         private static KeyExchangeProperties chooseCipherSuite(
       
   391                 ServerHandshakeContext shc,
       
   392                 ClientHelloMessage clientHello) throws IOException {
       
   393             List<CipherSuite> preferred;
       
   394             List<CipherSuite> proposed;
       
   395             if (shc.sslConfig.preferLocalCipherSuites) {
       
   396                 preferred = shc.activeCipherSuites;
       
   397                 proposed = clientHello.cipherSuites;
       
   398             } else {
       
   399                 preferred = clientHello.cipherSuites;
       
   400                 proposed = shc.activeCipherSuites;
       
   401             }
       
   402 
       
   403             List<CipherSuite> legacySuites = new LinkedList<>();
       
   404             for (CipherSuite cs : preferred) {
       
   405                 if (!HandshakeContext.isNegotiable(
       
   406                         proposed, shc.negotiatedProtocol, cs)) {
       
   407                     continue;
       
   408                 }
       
   409 
       
   410                 if (shc.sslConfig.clientAuthType ==
       
   411                         ClientAuthType.CLIENT_AUTH_REQUIRED) {
       
   412                     if ((cs.keyExchange == KeyExchange.K_DH_ANON) ||
       
   413                         (cs.keyExchange == KeyExchange.K_ECDH_ANON)) {
       
   414                         continue;
       
   415                     }
       
   416                 }
       
   417 
       
   418                 SSLKeyExchange ke = SSLKeyExchange.valueOf(
       
   419                         cs.keyExchange, shc.negotiatedProtocol);
       
   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(
       
   444                         cs.keyExchange,  shc.negotiatedProtocol);
       
   445                 if (ke != null) {
       
   446                     SSLPossession[] hcds = ke.createPossessions(shc);
       
   447                     if ((hcds != null) && (hcds.length != 0)) {
       
   448                         if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   449                             SSLLogger.warning(
       
   450                                 "use legacy cipher suite " + cs.name);
       
   451                         }
       
   452                         return new KeyExchangeProperties(cs, ke, hcds);
       
   453                     }
       
   454                 }
       
   455             }
       
   456 
       
   457             shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   458                     "no cipher suites in common");
       
   459 
       
   460             return null;    // make the compiler happy.
       
   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                     shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   524                             "no cipher suites in common");
       
   525                     return null;    // make the compiler happy
       
   526                 }
       
   527                 shc.negotiatedCipherSuite = cipherSuite;
       
   528                 shc.handshakeSession.setSuite(cipherSuite);
       
   529                 shc.handshakeHash.determine(
       
   530                         shc.negotiatedProtocol, shc.negotiatedCipherSuite);
       
   531             } else {
       
   532                 shc.handshakeSession = shc.resumingSession;
       
   533 
       
   534                 // consider the handshake extension impact
       
   535                 SSLExtension[] enabledExtensions =
       
   536                 shc.sslConfig.getEnabledExtensions(
       
   537                 SSLHandshake.CLIENT_HELLO, shc.negotiatedProtocol);
       
   538                 clientHello.extensions.consumeOnTrade(shc, enabledExtensions);
       
   539 
       
   540                 shc.negotiatedProtocol =
       
   541                         shc.resumingSession.getProtocolVersion();
       
   542                 shc.negotiatedCipherSuite = shc.resumingSession.getSuite();
       
   543                 shc.handshakeHash.determine(
       
   544                         shc.negotiatedProtocol, shc.negotiatedCipherSuite);
       
   545 
       
   546                 setUpPskKD(shc,
       
   547                         shc.resumingSession.consumePreSharedKey().get());
       
   548 
       
   549                 // The session can't be resumed again---remove it from cache
       
   550                 SSLSessionContextImpl sessionCache = (SSLSessionContextImpl)
       
   551                     shc.sslContext.engineGetServerSessionContext();
       
   552                 sessionCache.remove(shc.resumingSession.getSessionId());
       
   553             }
       
   554 
       
   555             // update the responders
       
   556             shc.handshakeProducers.put(SSLHandshake.ENCRYPTED_EXTENSIONS.id,
       
   557                     SSLHandshake.ENCRYPTED_EXTENSIONS);
       
   558             shc.handshakeProducers.put(SSLHandshake.FINISHED.id,
       
   559                     SSLHandshake.FINISHED);
       
   560 
       
   561             // Generate the ServerHello handshake message.
       
   562             ServerHelloMessage shm = new ServerHelloMessage(shc,
       
   563                     ProtocolVersion.TLS12,      // use legacy version
       
   564                     clientHello.sessionId,      // echo back
       
   565                     shc.negotiatedCipherSuite,
       
   566                     new RandomCookie(shc),
       
   567                     clientHello);
       
   568             shc.serverHelloRandom = shm.serverRandom;
       
   569 
       
   570             // Produce extensions for ServerHello handshake message.
       
   571             SSLExtension[] serverHelloExtensions =
       
   572                     shc.sslConfig.getEnabledExtensions(
       
   573                         SSLHandshake.SERVER_HELLO, shc.negotiatedProtocol);
       
   574             shm.extensions.produce(shc, serverHelloExtensions);
       
   575             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   576                 SSLLogger.fine("Produced ServerHello handshake message", shm);
       
   577             }
       
   578 
       
   579             // Output the handshake message.
       
   580             shm.write(shc.handshakeOutput);
       
   581             shc.handshakeOutput.flush();
       
   582 
       
   583             // Change client/server handshake traffic secrets.
       
   584             // Refresh handshake hash
       
   585             shc.handshakeHash.update();
       
   586 
       
   587             // Change client/server handshake traffic secrets.
       
   588             SSLKeyExchange ke = shc.handshakeKeyExchange;
       
   589             if (ke == null) {
       
   590                 // unlikely
       
   591                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   592                         "Not negotiated key shares");
       
   593                 return null;    // make the compiler happy
       
   594             }
       
   595 
       
   596             SSLKeyDerivation handshakeKD = ke.createKeyDerivation(shc);
       
   597             SecretKey handshakeSecret = handshakeKD.deriveKey(
       
   598                     "TlsHandshakeSecret", null);
       
   599 
       
   600             SSLTrafficKeyDerivation kdg =
       
   601                 SSLTrafficKeyDerivation.valueOf(shc.negotiatedProtocol);
       
   602             if (kdg == null) {
       
   603                 // unlikely
       
   604                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   605                         "Not supported key derivation: " +
       
   606                         shc.negotiatedProtocol);
       
   607                 return null;    // make the compiler happy
       
   608             }
       
   609 
       
   610             SSLKeyDerivation kd =
       
   611                     new SSLSecretDerivation(shc, handshakeSecret);
       
   612 
       
   613             // update the handshake traffic read keys.
       
   614             SecretKey readSecret = kd.deriveKey(
       
   615                     "TlsClientHandshakeTrafficSecret", null);
       
   616             SSLKeyDerivation readKD =
       
   617                     kdg.createKeyDerivation(shc, readSecret);
       
   618             SecretKey readKey = readKD.deriveKey(
       
   619                     "TlsKey", null);
       
   620             SecretKey readIvSecret = readKD.deriveKey(
       
   621                     "TlsIv", null);
       
   622             IvParameterSpec readIv =
       
   623                     new IvParameterSpec(readIvSecret.getEncoded());
       
   624             SSLReadCipher readCipher;
       
   625             try {
       
   626                 readCipher =
       
   627                     shc.negotiatedCipherSuite.bulkCipher.createReadCipher(
       
   628                         Authenticator.valueOf(shc.negotiatedProtocol),
       
   629                         shc.negotiatedProtocol, readKey, readIv,
       
   630                         shc.sslContext.getSecureRandom());
       
   631             } catch (GeneralSecurityException gse) {
       
   632                 // unlikely
       
   633                 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   634                         "Missing cipher algorithm", gse);
       
   635                 return null;    // make the compiler happy
       
   636             }
       
   637 
       
   638             shc.baseReadSecret = readSecret;
       
   639             shc.conContext.inputRecord.changeReadCiphers(readCipher);
       
   640 
       
   641             // update the handshake traffic write secret.
       
   642             SecretKey writeSecret = kd.deriveKey(
       
   643                     "TlsServerHandshakeTrafficSecret", null);
       
   644             SSLKeyDerivation writeKD =
       
   645                     kdg.createKeyDerivation(shc, writeSecret);
       
   646             SecretKey writeKey = writeKD.deriveKey(
       
   647                     "TlsKey", null);
       
   648             SecretKey writeIvSecret = writeKD.deriveKey(
       
   649                     "TlsIv", null);
       
   650             IvParameterSpec writeIv =
       
   651                     new IvParameterSpec(writeIvSecret.getEncoded());
       
   652             SSLWriteCipher writeCipher;
       
   653             try {
       
   654                 writeCipher =
       
   655                     shc.negotiatedCipherSuite.bulkCipher.createWriteCipher(
       
   656                         Authenticator.valueOf(shc.negotiatedProtocol),
       
   657                         shc.negotiatedProtocol, writeKey, writeIv,
       
   658                         shc.sslContext.getSecureRandom());
       
   659             } catch (GeneralSecurityException gse) {
       
   660                 // unlikely
       
   661                 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   662                         "Missing cipher algorithm", gse);
       
   663                 return null;    //  make the compiler happy
       
   664             }
       
   665 
       
   666             shc.baseWriteSecret = writeSecret;
       
   667             shc.conContext.outputRecord.changeWriteCiphers(
       
   668                     writeCipher, (clientHello.sessionId.length() != 0));
       
   669 
       
   670             // Update the context for master key derivation.
       
   671             shc.handshakeKeyDerivation = kd;
       
   672 
       
   673             // The handshake message has been delivered.
       
   674             return null;
       
   675         }
       
   676 
       
   677         private static CipherSuite chooseCipherSuite(
       
   678                 ServerHandshakeContext shc,
       
   679                 ClientHelloMessage clientHello) throws IOException {
       
   680             List<CipherSuite> preferred;
       
   681             List<CipherSuite> proposed;
       
   682             if (shc.sslConfig.preferLocalCipherSuites) {
       
   683                 preferred = shc.activeCipherSuites;
       
   684                 proposed = clientHello.cipherSuites;
       
   685             } else {
       
   686                 preferred = clientHello.cipherSuites;
       
   687                 proposed = shc.activeCipherSuites;
       
   688             }
       
   689 
       
   690             CipherSuite legacySuite = null;
       
   691             AlgorithmConstraints legacyConstraints =
       
   692                     ServerHandshakeContext.legacyAlgorithmConstraints;
       
   693             for (CipherSuite cs : preferred) {
       
   694                 if (!HandshakeContext.isNegotiable(
       
   695                         proposed, shc.negotiatedProtocol, cs)) {
       
   696                     continue;
       
   697                 }
       
   698 
       
   699                 if ((legacySuite == null) &&
       
   700                         !legacyConstraints.permits(null, cs.name, null)) {
       
   701                     legacySuite = cs;
       
   702                     continue;
       
   703                 }
       
   704 
       
   705                 // The cipher suite has been negotiated.
       
   706                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   707                     SSLLogger.fine("use cipher suite " + cs.name);
       
   708                 }
       
   709                 return cs;
       
   710             }
       
   711 
       
   712             if (legacySuite != null) {
       
   713                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   714                     SSLLogger.warning(
       
   715                             "use legacy cipher suite " + legacySuite.name);
       
   716                 }
       
   717                 return legacySuite;
       
   718             }
       
   719 
       
   720             // no cipher suites in common
       
   721             return null;
       
   722         }
       
   723     }
       
   724 
       
   725     /**
       
   726      * The "HelloRetryRequest" handshake message producer.
       
   727      */
       
   728     private static final
       
   729             class T13HelloRetryRequestProducer implements HandshakeProducer {
       
   730         // Prevent instantiation of this class.
       
   731         private T13HelloRetryRequestProducer() {
       
   732             // blank
       
   733         }
       
   734 
       
   735         @Override
       
   736         public byte[] produce(ConnectionContext context,
       
   737                 HandshakeMessage message) throws IOException {
       
   738             ServerHandshakeContext shc = (ServerHandshakeContext) context;
       
   739             ClientHelloMessage clientHello = (ClientHelloMessage) message;
       
   740 
       
   741             // negotiate the cipher suite.
       
   742             CipherSuite cipherSuite =
       
   743                     T13ServerHelloProducer.chooseCipherSuite(shc, clientHello);
       
   744             if (cipherSuite == null) {
       
   745                 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   746                         "no cipher suites in common for hello retry request");
       
   747                 return null;    // make the compiler happy
       
   748             }
       
   749 
       
   750             ServerHelloMessage hhrm = new ServerHelloMessage(shc,
       
   751                     ProtocolVersion.TLS12,      // use legacy version
       
   752                     clientHello.sessionId,      //  echo back
       
   753                     cipherSuite,
       
   754                     RandomCookie.hrrRandom,
       
   755                     clientHello
       
   756             );
       
   757 
       
   758             shc.negotiatedCipherSuite = cipherSuite;
       
   759             shc.handshakeHash.determine(
       
   760                     shc.negotiatedProtocol, shc.negotiatedCipherSuite);
       
   761 
       
   762             // Produce extensions for HelloRetryRequest handshake message.
       
   763             SSLExtension[] serverHelloExtensions =
       
   764                 shc.sslConfig.getEnabledExtensions(
       
   765                     SSLHandshake.HELLO_RETRY_REQUEST, shc.negotiatedProtocol);
       
   766             hhrm.extensions.produce(shc, serverHelloExtensions);
       
   767             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   768                 SSLLogger.fine(
       
   769                         "Produced HelloRetryRequest handshake message", hhrm);
       
   770             }
       
   771 
       
   772             // Output the handshake message.
       
   773             hhrm.write(shc.handshakeOutput);
       
   774             shc.handshakeOutput.flush();
       
   775 
       
   776             // Stateless, shall we clean up the handshake context as well?
       
   777             shc.handshakeHash.finish();     // forgot about the handshake hash
       
   778             shc.handshakeExtensions.clear();
       
   779 
       
   780             // What's the expected response?
       
   781             shc.handshakeConsumers.put(
       
   782                     SSLHandshake.CLIENT_HELLO.id, SSLHandshake.CLIENT_HELLO);
       
   783 
       
   784             // The handshake message has been delivered.
       
   785             return null;
       
   786         }
       
   787     }
       
   788 
       
   789     /**
       
   790      * The "HelloRetryRequest" handshake message reproducer.
       
   791      */
       
   792     private static final
       
   793             class T13HelloRetryRequestReproducer implements HandshakeProducer {
       
   794         // Prevent instantiation of this class.
       
   795         private T13HelloRetryRequestReproducer() {
       
   796             // blank
       
   797         }
       
   798 
       
   799         @Override
       
   800         public byte[] produce(ConnectionContext context,
       
   801                 HandshakeMessage message) throws IOException {
       
   802             ServerHandshakeContext shc = (ServerHandshakeContext) context;
       
   803             ClientHelloMessage clientHello = (ClientHelloMessage) message;
       
   804 
       
   805             // negotiate the cipher suite.
       
   806             CipherSuite cipherSuite = shc.negotiatedCipherSuite;
       
   807             ServerHelloMessage hhrm = new ServerHelloMessage(shc,
       
   808                     ProtocolVersion.TLS12,      // use legacy version
       
   809                     clientHello.sessionId,      //  echo back
       
   810                     cipherSuite,
       
   811                     RandomCookie.hrrRandom,
       
   812                     clientHello
       
   813             );
       
   814 
       
   815             // Produce extensions for HelloRetryRequest handshake message.
       
   816             SSLExtension[] serverHelloExtensions =
       
   817                 shc.sslConfig.getEnabledExtensions(
       
   818                     SSLHandshake.MESSAGE_HASH, shc.negotiatedProtocol);
       
   819             hhrm.extensions.produce(shc, serverHelloExtensions);
       
   820             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   821                 SSLLogger.fine(
       
   822                         "Reproduced HelloRetryRequest handshake message", hhrm);
       
   823             }
       
   824 
       
   825             HandshakeOutStream hos = new HandshakeOutStream(null);
       
   826             hhrm.write(hos);
       
   827 
       
   828             return hos.toByteArray();
       
   829         }
       
   830     }
       
   831 
       
   832     /**
       
   833      * The "ServerHello" handshake message consumer.
       
   834      */
       
   835     private static final
       
   836             class ServerHelloConsumer implements SSLConsumer {
       
   837         // Prevent instantiation of this class.
       
   838         private ServerHelloConsumer() {
       
   839             // blank
       
   840         }
       
   841 
       
   842         @Override
       
   843         public void consume(ConnectionContext context,
       
   844                 ByteBuffer message) throws IOException {
       
   845             // The consuming happens in client side only.
       
   846             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
   847 
       
   848             // clean up this consumer
       
   849             chc.handshakeConsumers.remove(SSLHandshake.SERVER_HELLO.id);
       
   850             if (!chc.handshakeConsumers.isEmpty()) {
       
   851                 // DTLS 1.0/1.2
       
   852                 chc.handshakeConsumers.remove(
       
   853                         SSLHandshake.HELLO_VERIFY_REQUEST.id);
       
   854             }
       
   855             if (!chc.handshakeConsumers.isEmpty()) {
       
   856                 chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
       
   857                     "No more message expected before ServerHello is processed");
       
   858             }
       
   859 
       
   860             ServerHelloMessage shm = new ServerHelloMessage(chc, message);
       
   861             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   862                 SSLLogger.fine("Consuming ServerHello handshake message", shm);
       
   863             }
       
   864 
       
   865             if (shm.serverRandom.isHelloRetryRequest()) {
       
   866                 onHelloRetryRequest(chc, shm);
       
   867             } else {
       
   868                 onServerHello(chc, shm);
       
   869             }
       
   870         }
       
   871 
       
   872         private void onHelloRetryRequest(ClientHandshakeContext chc,
       
   873                 ServerHelloMessage helloRetryRequest) throws IOException {
       
   874             // Negotiate protocol version.
       
   875             //
       
   876             // Check and launch SupportedVersions.
       
   877             SSLExtension[] extTypes = new SSLExtension[] {
       
   878                     SSLExtension.HRR_SUPPORTED_VERSIONS
       
   879                 };
       
   880             helloRetryRequest.extensions.consumeOnLoad(chc, extTypes);
       
   881 
       
   882             ProtocolVersion serverVersion;
       
   883             SHSupportedVersionsSpec svs =
       
   884                     (SHSupportedVersionsSpec)chc.handshakeExtensions.get(
       
   885                             SSLExtension.HRR_SUPPORTED_VERSIONS);
       
   886             if (svs != null) {
       
   887                 serverVersion =            // could be null
       
   888                         ProtocolVersion.valueOf(svs.selectedVersion);
       
   889             } else {
       
   890                 serverVersion = helloRetryRequest.serverVersion;
       
   891             }
       
   892 
       
   893             if (!chc.activeProtocols.contains(serverVersion)) {
       
   894                 chc.conContext.fatal(Alert.PROTOCOL_VERSION,
       
   895                     "The server selected protocol version " + serverVersion +
       
   896                     " is not accepted by client preferences " +
       
   897                     chc.activeProtocols);
       
   898             }
       
   899 
       
   900             if (!serverVersion.useTLS13PlusSpec()) {
       
   901                 chc.conContext.fatal(Alert.PROTOCOL_VERSION,
       
   902                     "Unexpected HelloRetryRequest for " + serverVersion.name);
       
   903             }
       
   904 
       
   905             chc.negotiatedProtocol = serverVersion;
       
   906             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   907                 SSLLogger.fine(
       
   908                     "Negotiated protocol version: " + serverVersion.name);
       
   909             }
       
   910 
       
   911             // TLS 1.3 key share extension may have produced client
       
   912             // possessions for TLS 1.3 key exchanges.
       
   913             //
       
   914             // Clean up before producing new client key share possessions.
       
   915             chc.handshakePossessions.clear();
       
   916 
       
   917             if (serverVersion.isDTLS) {
       
   918                 d13HrrHandshakeConsumer.consume(chc, helloRetryRequest);
       
   919             } else {
       
   920                 t13HrrHandshakeConsumer.consume(chc, helloRetryRequest);
       
   921             }
       
   922         }
       
   923 
       
   924         private void onServerHello(ClientHandshakeContext chc,
       
   925                 ServerHelloMessage serverHello) throws IOException {
       
   926             // Negotiate protocol version.
       
   927             //
       
   928             // Check and launch SupportedVersions.
       
   929             SSLExtension[] extTypes = new SSLExtension[] {
       
   930                     SSLExtension.SH_SUPPORTED_VERSIONS
       
   931                 };
       
   932             serverHello.extensions.consumeOnLoad(chc, extTypes);
       
   933 
       
   934             ProtocolVersion serverVersion;
       
   935             SHSupportedVersionsSpec svs =
       
   936                     (SHSupportedVersionsSpec)chc.handshakeExtensions.get(
       
   937                             SSLExtension.SH_SUPPORTED_VERSIONS);
       
   938             if (svs != null) {
       
   939                 serverVersion =            // could be null
       
   940                         ProtocolVersion.valueOf(svs.selectedVersion);
       
   941             } else {
       
   942                 serverVersion = serverHello.serverVersion;
       
   943             }
       
   944 
       
   945             if (!chc.activeProtocols.contains(serverVersion)) {
       
   946                 chc.conContext.fatal(Alert.PROTOCOL_VERSION,
       
   947                     "The server selected protocol version " + serverVersion +
       
   948                     " is not accepted by client preferences " +
       
   949                     chc.activeProtocols);
       
   950             }
       
   951 
       
   952             chc.negotiatedProtocol = serverVersion;
       
   953             if (!chc.conContext.isNegotiated) {
       
   954                 chc.conContext.protocolVersion = chc.negotiatedProtocol;
       
   955                 chc.conContext.outputRecord.setVersion(chc.negotiatedProtocol);
       
   956             }
       
   957             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   958                 SSLLogger.fine(
       
   959                     "Negotiated protocol version: " + serverVersion.name);
       
   960             }
       
   961 
       
   962             if (serverHello.serverRandom.isVersionDowngrade(chc)) {
       
   963                 chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   964                     "A potential protocol version downgrade attack");
       
   965             }
       
   966 
       
   967             // Consume the handshake message for the specific protocol version.
       
   968             if (serverVersion.isDTLS) {
       
   969                 if (serverVersion.useTLS13PlusSpec()) {
       
   970                     d13HandshakeConsumer.consume(chc, serverHello);
       
   971                 } else {
       
   972                     // TLS 1.3 key share extension may have produced client
       
   973                     // possessions for TLS 1.3 key exchanges.
       
   974                     chc.handshakePossessions.clear();
       
   975 
       
   976                     d12HandshakeConsumer.consume(chc, serverHello);
       
   977                 }
       
   978             } else {
       
   979                 if (serverVersion.useTLS13PlusSpec()) {
       
   980                     t13HandshakeConsumer.consume(chc, serverHello);
       
   981                 } else {
       
   982                     // TLS 1.3 key share extension may have produced client
       
   983                     // possessions for TLS 1.3 key exchanges.
       
   984                     chc.handshakePossessions.clear();
       
   985 
       
   986                     t12HandshakeConsumer.consume(chc, serverHello);
       
   987                 }
       
   988             }
       
   989         }
       
   990     }
       
   991 
       
   992     private static final
       
   993             class T12ServerHelloConsumer implements HandshakeConsumer {
       
   994         // Prevent instantiation of this class.
       
   995         private T12ServerHelloConsumer() {
       
   996             // blank
       
   997         }
       
   998 
       
   999         @Override
       
  1000         public void consume(ConnectionContext context,
       
  1001                 HandshakeMessage message) throws IOException {
       
  1002             // The consuming happens in client side only.
       
  1003             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
  1004             ServerHelloMessage serverHello = (ServerHelloMessage)message;
       
  1005             if (!chc.isNegotiable(serverHello.serverVersion)) {
       
  1006                 chc.conContext.fatal(Alert.PROTOCOL_VERSION,
       
  1007                     "Server chose " + serverHello.serverVersion +
       
  1008                     ", but that protocol version is not enabled or " +
       
  1009                     "not supported by the client.");
       
  1010             }
       
  1011 
       
  1012             // chc.negotiatedProtocol = serverHello.serverVersion;
       
  1013             chc.negotiatedCipherSuite = serverHello.cipherSuite;
       
  1014             chc.handshakeHash.determine(
       
  1015                     chc.negotiatedProtocol, chc.negotiatedCipherSuite);
       
  1016             chc.serverHelloRandom = serverHello.serverRandom;
       
  1017             if (chc.negotiatedCipherSuite.keyExchange == null) {
       
  1018                 chc.conContext.fatal(Alert.PROTOCOL_VERSION,
       
  1019                     "TLS 1.2 or prior version does not support the " +
       
  1020                     "server cipher suite: " + chc.negotiatedCipherSuite.name);
       
  1021             }
       
  1022 
       
  1023             //
       
  1024             // validate
       
  1025             //
       
  1026 
       
  1027             // Check and launch the "renegotiation_info" extension.
       
  1028             SSLExtension[] extTypes = new SSLExtension[] {
       
  1029                     SSLExtension.SH_RENEGOTIATION_INFO
       
  1030                 };
       
  1031             serverHello.extensions.consumeOnLoad(chc, extTypes);
       
  1032 
       
  1033             // Is it session resuming?
       
  1034             if (chc.resumingSession != null) {
       
  1035                 // we tried to resume, let's see what the server decided
       
  1036                 if (serverHello.sessionId.equals(
       
  1037                         chc.resumingSession.getSessionId())) {
       
  1038                     // server resumed the session, let's make sure everything
       
  1039                     // checks out
       
  1040 
       
  1041                     // Verify that the session ciphers are unchanged.
       
  1042                     CipherSuite sessionSuite = chc.resumingSession.getSuite();
       
  1043                     if (chc.negotiatedCipherSuite != sessionSuite) {
       
  1044                         chc.conContext.fatal(Alert.PROTOCOL_VERSION,
       
  1045                             "Server returned wrong cipher suite for session");
       
  1046                     }
       
  1047 
       
  1048                     // verify protocol version match
       
  1049                     ProtocolVersion sessionVersion =
       
  1050                             chc.resumingSession.getProtocolVersion();
       
  1051                     if (chc.negotiatedProtocol != sessionVersion) {
       
  1052                         chc.conContext.fatal(Alert.PROTOCOL_VERSION,
       
  1053                             "Server resumed with wrong protocol version");
       
  1054                     }
       
  1055 
       
  1056                     // looks fine;  resume it.
       
  1057                     chc.isResumption = true;
       
  1058                     chc.resumingSession.setAsSessionResumption(true);
       
  1059                     chc.handshakeSession = chc.resumingSession;
       
  1060                 } else {
       
  1061                     // we wanted to resume, but the server refused
       
  1062                     //
       
  1063                     // Invalidate the session for initial handshake in case
       
  1064                     // of reusing next time.
       
  1065                     if (chc.resumingSession != null) {
       
  1066                         chc.resumingSession.invalidate();
       
  1067                         chc.resumingSession = null;
       
  1068                     }
       
  1069                     chc.isResumption = false;
       
  1070                     if (!chc.sslConfig.enableSessionCreation) {
       
  1071                         chc.conContext.fatal(Alert.PROTOCOL_VERSION,
       
  1072                             "New session creation is disabled");
       
  1073                     }
       
  1074                 }
       
  1075             }
       
  1076 
       
  1077             // Check and launch ClientHello extensions.
       
  1078             extTypes = chc.sslConfig.getEnabledExtensions(
       
  1079                     SSLHandshake.SERVER_HELLO);
       
  1080             serverHello.extensions.consumeOnLoad(chc, extTypes);
       
  1081 
       
  1082             if (!chc.isResumption) {
       
  1083                 if (chc.resumingSession != null) {
       
  1084                     // in case the resumption happens next time.
       
  1085                     chc.resumingSession.invalidate();
       
  1086                     chc.resumingSession = null;
       
  1087                 }
       
  1088 
       
  1089                 if (!chc.sslConfig.enableSessionCreation) {
       
  1090                     chc.conContext.fatal(Alert.PROTOCOL_VERSION,
       
  1091                         "New session creation is disabled");
       
  1092                 }
       
  1093                 chc.handshakeSession = new SSLSessionImpl(chc,
       
  1094                         chc.negotiatedCipherSuite,
       
  1095                         serverHello.sessionId);
       
  1096                 chc.handshakeSession.setMaximumPacketSize(
       
  1097                         chc.sslConfig.maximumPacketSize);
       
  1098             }
       
  1099 
       
  1100             //
       
  1101             // update
       
  1102             //
       
  1103             serverHello.extensions.consumeOnTrade(chc, extTypes);
       
  1104 
       
  1105             // update the consumers and producers
       
  1106             if (chc.isResumption) {
       
  1107                 SSLTrafficKeyDerivation kdg =
       
  1108                         SSLTrafficKeyDerivation.valueOf(chc.negotiatedProtocol);
       
  1109                 if (kdg == null) {
       
  1110                     // unlikely
       
  1111                     chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
  1112                             "Not supported key derivation: " +
       
  1113                             chc.negotiatedProtocol);
       
  1114                 } else {
       
  1115                     chc.handshakeKeyDerivation = kdg.createKeyDerivation(
       
  1116                             chc, chc.resumingSession.getMasterSecret());
       
  1117                 }
       
  1118 
       
  1119                 chc.conContext.consumers.putIfAbsent(
       
  1120                         ContentType.CHANGE_CIPHER_SPEC.id,
       
  1121                         ChangeCipherSpec.t10Consumer);
       
  1122                 chc.handshakeConsumers.put(
       
  1123                         SSLHandshake.FINISHED.id,
       
  1124                         SSLHandshake.FINISHED);
       
  1125             } else {
       
  1126                 SSLKeyExchange ke = SSLKeyExchange.valueOf(
       
  1127                         chc.negotiatedCipherSuite.keyExchange,
       
  1128                         chc.negotiatedProtocol);
       
  1129                 chc.handshakeKeyExchange = ke;
       
  1130                 if (ke != null) {
       
  1131                     for (SSLHandshake handshake :
       
  1132                             ke.getRelatedHandshakers(chc)) {
       
  1133                         chc.handshakeConsumers.put(handshake.id, handshake);
       
  1134                     }
       
  1135                 }
       
  1136 
       
  1137                 chc.handshakeConsumers.put(SSLHandshake.SERVER_HELLO_DONE.id,
       
  1138                         SSLHandshake.SERVER_HELLO_DONE);
       
  1139             }
       
  1140 
       
  1141             //
       
  1142             // produce
       
  1143             //
       
  1144             // Need no new handshake message producers here.
       
  1145         }
       
  1146     }
       
  1147 
       
  1148     private static void setUpPskKD(HandshakeContext hc,
       
  1149             SecretKey psk) throws SSLHandshakeException {
       
  1150 
       
  1151         if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
  1152             SSLLogger.fine("Using PSK to derive early secret");
       
  1153         }
       
  1154 
       
  1155         try {
       
  1156             CipherSuite.HashAlg hashAlg = hc.negotiatedCipherSuite.hashAlg;
       
  1157             HKDF hkdf = new HKDF(hashAlg.name);
       
  1158             byte[] zeros = new byte[hashAlg.hashLength];
       
  1159             SecretKey earlySecret = hkdf.extract(zeros, psk, "TlsEarlySecret");
       
  1160             hc.handshakeKeyDerivation =
       
  1161                     new SSLSecretDerivation(hc, earlySecret);
       
  1162         } catch  (GeneralSecurityException gse) {
       
  1163             throw (SSLHandshakeException) new SSLHandshakeException(
       
  1164                 "Could not generate secret").initCause(gse);
       
  1165         }
       
  1166     }
       
  1167 
       
  1168     private static final
       
  1169             class T13ServerHelloConsumer implements HandshakeConsumer {
       
  1170         // Prevent instantiation of this class.
       
  1171         private T13ServerHelloConsumer() {
       
  1172             // blank
       
  1173         }
       
  1174 
       
  1175         @Override
       
  1176         public void consume(ConnectionContext context,
       
  1177                 HandshakeMessage message) throws IOException {
       
  1178             // The consuming happens in client side only.
       
  1179             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
  1180             ServerHelloMessage serverHello = (ServerHelloMessage)message;
       
  1181             if (serverHello.serverVersion != ProtocolVersion.TLS12) {
       
  1182                 chc.conContext.fatal(Alert.PROTOCOL_VERSION,
       
  1183                     "The ServerHello.legacy_version field is not TLS 1.2");
       
  1184             }
       
  1185 
       
  1186             chc.negotiatedCipherSuite = serverHello.cipherSuite;
       
  1187             chc.handshakeHash.determine(
       
  1188                     chc.negotiatedProtocol, chc.negotiatedCipherSuite);
       
  1189             chc.serverHelloRandom = serverHello.serverRandom;
       
  1190 
       
  1191             //
       
  1192             // validate
       
  1193             //
       
  1194 
       
  1195             // Check and launch ServerHello extensions.
       
  1196             SSLExtension[] extTypes = chc.sslConfig.getEnabledExtensions(
       
  1197                     SSLHandshake.SERVER_HELLO);
       
  1198             serverHello.extensions.consumeOnLoad(chc, extTypes);
       
  1199             if (!chc.isResumption) {
       
  1200                 if (chc.resumingSession != null) {
       
  1201                     // in case the resumption happens next time.
       
  1202                     chc.resumingSession.invalidate();
       
  1203                     chc.resumingSession = null;
       
  1204                 }
       
  1205 
       
  1206                 if (!chc.sslConfig.enableSessionCreation) {
       
  1207                     chc.conContext.fatal(Alert.PROTOCOL_VERSION,
       
  1208                         "New session creation is disabled");
       
  1209                 }
       
  1210                 chc.handshakeSession = new SSLSessionImpl(chc,
       
  1211                         chc.negotiatedCipherSuite,
       
  1212                         serverHello.sessionId);
       
  1213                 chc.handshakeSession.setMaximumPacketSize(
       
  1214                         chc.sslConfig.maximumPacketSize);
       
  1215             } else {
       
  1216                 // The PSK is consumed to allow it to be deleted
       
  1217                 Optional<SecretKey> psk =
       
  1218                         chc.resumingSession.consumePreSharedKey();
       
  1219                 if(!psk.isPresent()) {
       
  1220                     chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
  1221                     "No PSK available. Unable to resume.");
       
  1222                 }
       
  1223 
       
  1224                 chc.handshakeSession = chc.resumingSession;
       
  1225 
       
  1226                 setUpPskKD(chc, psk.get());
       
  1227             }
       
  1228 
       
  1229             //
       
  1230             // update
       
  1231             //
       
  1232             serverHello.extensions.consumeOnTrade(chc, extTypes);
       
  1233 
       
  1234             // Change client/server handshake traffic secrets.
       
  1235             // Refresh handshake hash
       
  1236             chc.handshakeHash.update();
       
  1237 
       
  1238             SSLKeyExchange ke = chc.handshakeKeyExchange;
       
  1239             if (ke == null) {
       
  1240                 // unlikely
       
  1241                 chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
  1242                         "Not negotiated key shares");
       
  1243                 return;     // make the compiler happy
       
  1244             }
       
  1245 
       
  1246             SSLKeyDerivation handshakeKD = ke.createKeyDerivation(chc);
       
  1247             SecretKey handshakeSecret = handshakeKD.deriveKey(
       
  1248                     "TlsHandshakeSecret", null);
       
  1249             SSLTrafficKeyDerivation kdg =
       
  1250                 SSLTrafficKeyDerivation.valueOf(chc.negotiatedProtocol);
       
  1251             if (kdg == null) {
       
  1252                 // unlikely
       
  1253                 chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
  1254                         "Not supported key derivation: " +
       
  1255                         chc.negotiatedProtocol);
       
  1256                 return;     // make the compiler happy
       
  1257             }
       
  1258 
       
  1259             SSLKeyDerivation secretKD =
       
  1260                     new SSLSecretDerivation(chc, handshakeSecret);
       
  1261 
       
  1262             // update the handshake traffic read keys.
       
  1263             SecretKey readSecret = secretKD.deriveKey(
       
  1264                     "TlsServerHandshakeTrafficSecret", null);
       
  1265 
       
  1266             SSLKeyDerivation readKD =
       
  1267                     kdg.createKeyDerivation(chc, readSecret);
       
  1268             SecretKey readKey = readKD.deriveKey(
       
  1269                     "TlsKey", null);
       
  1270             SecretKey readIvSecret = readKD.deriveKey(
       
  1271                     "TlsIv", null);
       
  1272             IvParameterSpec readIv =
       
  1273                     new IvParameterSpec(readIvSecret.getEncoded());
       
  1274             SSLReadCipher readCipher;
       
  1275             try {
       
  1276                 readCipher =
       
  1277                     chc.negotiatedCipherSuite.bulkCipher.createReadCipher(
       
  1278                         Authenticator.valueOf(chc.negotiatedProtocol),
       
  1279                         chc.negotiatedProtocol, readKey, readIv,
       
  1280                         chc.sslContext.getSecureRandom());
       
  1281             } catch (GeneralSecurityException gse) {
       
  1282                 // unlikely
       
  1283                 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
  1284                         "Missing cipher algorithm", gse);
       
  1285                 return;     // make the compiler happy
       
  1286             }
       
  1287 
       
  1288             chc.baseReadSecret = readSecret;
       
  1289             chc.conContext.inputRecord.changeReadCiphers(readCipher);
       
  1290 
       
  1291             // update the handshake traffic write keys.
       
  1292             SecretKey writeSecret = secretKD.deriveKey(
       
  1293                     "TlsClientHandshakeTrafficSecret", null);
       
  1294             SSLKeyDerivation writeKD =
       
  1295                     kdg.createKeyDerivation(chc, writeSecret);
       
  1296             SecretKey writeKey = writeKD.deriveKey(
       
  1297                     "TlsKey", null);
       
  1298             SecretKey writeIvSecret = writeKD.deriveKey(
       
  1299                     "TlsIv", null);
       
  1300             IvParameterSpec writeIv =
       
  1301                     new IvParameterSpec(writeIvSecret.getEncoded());
       
  1302             SSLWriteCipher writeCipher;
       
  1303             try {
       
  1304                 writeCipher =
       
  1305                     chc.negotiatedCipherSuite.bulkCipher.createWriteCipher(
       
  1306                         Authenticator.valueOf(chc.negotiatedProtocol),
       
  1307                         chc.negotiatedProtocol, writeKey, writeIv,
       
  1308                         chc.sslContext.getSecureRandom());
       
  1309             } catch (GeneralSecurityException gse) {
       
  1310                 // unlikely
       
  1311                 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
  1312                         "Missing cipher algorithm", gse);
       
  1313                 return;     //  make the compiler happy
       
  1314             }
       
  1315 
       
  1316             chc.baseWriteSecret = writeSecret;
       
  1317             chc.conContext.outputRecord.changeWriteCiphers(
       
  1318                     writeCipher, (serverHello.sessionId.length() != 0));
       
  1319 
       
  1320             // Should use resumption_master_secret for TLS 1.3.
       
  1321             // chc.handshakeSession.setMasterSecret(masterSecret);
       
  1322 
       
  1323             // Update the context for master key derivation.
       
  1324             chc.handshakeKeyDerivation = secretKD;
       
  1325 
       
  1326             // update the consumers and producers
       
  1327             //
       
  1328             // The server sends a dummy change_cipher_spec record immediately
       
  1329             // after its first handshake message.  This may either be after a
       
  1330             // ServerHello or a HelloRetryRequest.
       
  1331             chc.conContext.consumers.putIfAbsent(
       
  1332                     ContentType.CHANGE_CIPHER_SPEC.id,
       
  1333                     ChangeCipherSpec.t13Consumer);
       
  1334 
       
  1335             chc.handshakeConsumers.put(
       
  1336                     SSLHandshake.ENCRYPTED_EXTENSIONS.id,
       
  1337                     SSLHandshake.ENCRYPTED_EXTENSIONS);
       
  1338 
       
  1339             // Support cert authentication only, when not PSK.
       
  1340             chc.handshakeConsumers.put(
       
  1341                     SSLHandshake.CERTIFICATE_REQUEST.id,
       
  1342                     SSLHandshake.CERTIFICATE_REQUEST);
       
  1343             chc.handshakeConsumers.put(
       
  1344                     SSLHandshake.CERTIFICATE.id,
       
  1345                     SSLHandshake.CERTIFICATE);
       
  1346             chc.handshakeConsumers.put(
       
  1347                     SSLHandshake.CERTIFICATE_VERIFY.id,
       
  1348                     SSLHandshake.CERTIFICATE_VERIFY);
       
  1349 
       
  1350             chc.handshakeConsumers.put(
       
  1351                     SSLHandshake.FINISHED.id,
       
  1352                     SSLHandshake.FINISHED);
       
  1353 
       
  1354             //
       
  1355             // produce
       
  1356             //
       
  1357             // Need no new handshake message producers here.
       
  1358         }
       
  1359     }
       
  1360 
       
  1361     private static final
       
  1362             class T13HelloRetryRequestConsumer implements HandshakeConsumer {
       
  1363         // Prevent instantiation of this class.
       
  1364         private T13HelloRetryRequestConsumer() {
       
  1365             // blank
       
  1366         }
       
  1367 
       
  1368         @Override
       
  1369         public void consume(ConnectionContext context,
       
  1370                 HandshakeMessage message) throws IOException {
       
  1371             // The consuming happens in client side only.
       
  1372             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
  1373             ServerHelloMessage helloRetryRequest = (ServerHelloMessage)message;
       
  1374             if (helloRetryRequest.serverVersion != ProtocolVersion.TLS12) {
       
  1375                 chc.conContext.fatal(Alert.PROTOCOL_VERSION,
       
  1376                     "The HelloRetryRequest.legacy_version is not TLS 1.2");
       
  1377             }
       
  1378 
       
  1379             chc.negotiatedCipherSuite = helloRetryRequest.cipherSuite;
       
  1380 
       
  1381             //
       
  1382             // validate
       
  1383             //
       
  1384 
       
  1385             // Check and launch ClientHello extensions.
       
  1386             SSLExtension[] extTypes = chc.sslConfig.getEnabledExtensions(
       
  1387                     SSLHandshake.HELLO_RETRY_REQUEST);
       
  1388             helloRetryRequest.extensions.consumeOnLoad(chc, extTypes);
       
  1389 
       
  1390             //
       
  1391             // update
       
  1392             //
       
  1393             helloRetryRequest.extensions.consumeOnTrade(chc, extTypes);
       
  1394 
       
  1395             // Change client/server handshake traffic secrets.
       
  1396             // Refresh handshake hash
       
  1397             chc.handshakeHash.finish();     // reset the handshake hash
       
  1398 
       
  1399             // calculate the transcript hash of the 1st ClientHello message
       
  1400             HandshakeOutStream hos = new HandshakeOutStream(null);
       
  1401             try {
       
  1402                 chc.initialClientHelloMsg.write(hos);
       
  1403             } catch (IOException ioe) {
       
  1404                 // unlikely
       
  1405                 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
  1406                     "Failed to construct message hash", ioe);
       
  1407             }
       
  1408             chc.handshakeHash.deliver(hos.toByteArray());
       
  1409             chc.handshakeHash.determine(
       
  1410                     chc.negotiatedProtocol, chc.negotiatedCipherSuite);
       
  1411             byte[] clientHelloHash = chc.handshakeHash.digest();
       
  1412 
       
  1413             // calculate the message_hash
       
  1414             //
       
  1415             // Transcript-Hash(ClientHello1, HelloRetryRequest, ... Mn) =
       
  1416             //   Hash(message_hash ||    /* Handshake type */
       
  1417             //     00 00 Hash.length ||  /* Handshake message length (bytes) */
       
  1418             //     Hash(ClientHello1) || /* Hash of ClientHello1 */
       
  1419             //     HelloRetryRequest || ... || Mn)
       
  1420             int hashLen = chc.negotiatedCipherSuite.hashAlg.hashLength;
       
  1421             byte[] hashedClientHello = new byte[4 + hashLen];
       
  1422             hashedClientHello[0] = SSLHandshake.MESSAGE_HASH.id;
       
  1423             hashedClientHello[1] = (byte)0x00;
       
  1424             hashedClientHello[2] = (byte)0x00;
       
  1425             hashedClientHello[3] = (byte)(hashLen & 0xFF);
       
  1426             System.arraycopy(clientHelloHash, 0,
       
  1427                     hashedClientHello, 4, hashLen);
       
  1428 
       
  1429             chc.handshakeHash.finish();     // reset the handshake hash
       
  1430             chc.handshakeHash.deliver(hashedClientHello);
       
  1431 
       
  1432             int hrrBodyLen = helloRetryRequest.handshakeRecord.remaining();
       
  1433             byte[] hrrMessage = new byte[4 + hrrBodyLen];
       
  1434             hrrMessage[0] = SSLHandshake.HELLO_RETRY_REQUEST.id;
       
  1435             hrrMessage[1] = (byte)((hrrBodyLen >> 16) & 0xFF);
       
  1436             hrrMessage[2] = (byte)((hrrBodyLen >> 8) & 0xFF);
       
  1437             hrrMessage[3] = (byte)(hrrBodyLen & 0xFF);
       
  1438 
       
  1439             ByteBuffer hrrBody = helloRetryRequest.handshakeRecord.duplicate();
       
  1440             hrrBody.get(hrrMessage, 4, hrrBodyLen);
       
  1441 
       
  1442             chc.handshakeHash.receive(hrrMessage);
       
  1443 
       
  1444             // Update the initial ClientHello handshake message.
       
  1445             chc.initialClientHelloMsg.extensions.reproduce(chc,
       
  1446                     new SSLExtension[] {
       
  1447                         SSLExtension.CH_COOKIE,
       
  1448                         SSLExtension.CH_KEY_SHARE,
       
  1449                         SSLExtension.CH_PRE_SHARED_KEY
       
  1450                     });
       
  1451 
       
  1452             //
       
  1453             // produce response handshake message
       
  1454             //
       
  1455             SSLHandshake.CLIENT_HELLO.produce(context, helloRetryRequest);
       
  1456         }
       
  1457     }
       
  1458 }