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