src/java.base/share/classes/sun/security/ssl/Finished.java
changeset 50768 68fa3d4026ea
child 52621 f7309a1491d9
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.GeneralSecurityException;
       
    31 import java.security.InvalidKeyException;
       
    32 import java.security.MessageDigest;
       
    33 import java.security.NoSuchAlgorithmException;
       
    34 import java.security.ProviderException;
       
    35 import java.security.spec.AlgorithmParameterSpec;
       
    36 import java.text.MessageFormat;
       
    37 import java.util.Locale;
       
    38 import javax.crypto.KeyGenerator;
       
    39 import javax.crypto.Mac;
       
    40 import javax.crypto.SecretKey;
       
    41 import javax.crypto.spec.IvParameterSpec;
       
    42 import javax.crypto.spec.SecretKeySpec;
       
    43 import sun.security.internal.spec.TlsPrfParameterSpec;
       
    44 import sun.security.ssl.CipherSuite.HashAlg;
       
    45 import static sun.security.ssl.CipherSuite.HashAlg.H_NONE;
       
    46 import sun.security.ssl.SSLBasicKeyDerivation.SecretSizeSpec;
       
    47 import sun.security.ssl.SSLCipher.SSLReadCipher;
       
    48 import sun.security.ssl.SSLCipher.SSLWriteCipher;
       
    49 import sun.security.ssl.SSLHandshake.HandshakeMessage;
       
    50 import sun.security.util.HexDumpEncoder;
       
    51 
       
    52 /**
       
    53  * Pack of the Finished handshake message.
       
    54  */
       
    55 final class Finished {
       
    56     static final SSLConsumer t12HandshakeConsumer =
       
    57         new T12FinishedConsumer();
       
    58     static final HandshakeProducer t12HandshakeProducer =
       
    59         new T12FinishedProducer();
       
    60 
       
    61     static final SSLConsumer t13HandshakeConsumer =
       
    62         new T13FinishedConsumer();
       
    63     static final HandshakeProducer t13HandshakeProducer =
       
    64         new T13FinishedProducer();
       
    65 
       
    66     /**
       
    67      * The Finished handshake message.
       
    68      */
       
    69     private static final class FinishedMessage extends HandshakeMessage {
       
    70         private final byte[] verifyData;
       
    71 
       
    72         FinishedMessage(HandshakeContext context) throws IOException {
       
    73             super(context);
       
    74 
       
    75             VerifyDataScheme vds =
       
    76                     VerifyDataScheme.valueOf(context.negotiatedProtocol);
       
    77 
       
    78             byte[] vd = null;
       
    79             try {
       
    80                 vd = vds.createVerifyData(context, false);
       
    81             } catch (IOException ioe) {
       
    82                 context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
    83                         "Failed to generate verify_data", ioe);
       
    84             }
       
    85 
       
    86             this.verifyData = vd;
       
    87         }
       
    88 
       
    89         FinishedMessage(HandshakeContext context,
       
    90                 ByteBuffer m) throws IOException {
       
    91             super(context);
       
    92             int verifyDataLen = 12;
       
    93             if (context.negotiatedProtocol == ProtocolVersion.SSL30) {
       
    94                 verifyDataLen = 36;
       
    95             } else if (context.negotiatedProtocol.useTLS13PlusSpec()) {
       
    96                 verifyDataLen =
       
    97                         context.negotiatedCipherSuite.hashAlg.hashLength;
       
    98             }
       
    99 
       
   100             if (m.remaining() != verifyDataLen) {
       
   101                 context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   102                     "Inappropriate finished message: need " + verifyDataLen +
       
   103                     " but remaining " + m.remaining() + " bytes verify_data");
       
   104             }
       
   105 
       
   106             this.verifyData = new byte[verifyDataLen];
       
   107             m.get(verifyData);
       
   108 
       
   109             VerifyDataScheme vd =
       
   110                     VerifyDataScheme.valueOf(context.negotiatedProtocol);
       
   111             byte[] myVerifyData;
       
   112             try {
       
   113                 myVerifyData = vd.createVerifyData(context, true);
       
   114             } catch (IOException ioe) {
       
   115                 context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   116                         "Failed to generate verify_data", ioe);
       
   117                 return;     // make the compiler happy
       
   118             }
       
   119             if (!MessageDigest.isEqual(myVerifyData, verifyData)) {
       
   120                 context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   121                         "The Finished message cannot be verified.");
       
   122             }
       
   123         }
       
   124 
       
   125         @Override
       
   126         public SSLHandshake handshakeType() {
       
   127             return SSLHandshake.FINISHED;
       
   128         }
       
   129 
       
   130         @Override
       
   131         public int messageLength() {
       
   132             return verifyData.length;
       
   133         }
       
   134 
       
   135         @Override
       
   136         public void send(HandshakeOutStream hos) throws IOException {
       
   137             hos.write(verifyData);
       
   138         }
       
   139 
       
   140         @Override
       
   141         public String toString() {
       
   142             MessageFormat messageFormat = new MessageFormat(
       
   143                     "\"Finished\": '{'\n" +
       
   144                     "  \"verify data\": '{'\n" +
       
   145                     "{0}\n" +
       
   146                     "  '}'" +
       
   147                     "'}'",
       
   148                     Locale.ENGLISH);
       
   149 
       
   150             HexDumpEncoder hexEncoder = new HexDumpEncoder();
       
   151             Object[] messageFields = {
       
   152                     Utilities.indent(hexEncoder.encode(verifyData), "    "),
       
   153                 };
       
   154             return messageFormat.format(messageFields);
       
   155         }
       
   156     }
       
   157 
       
   158     interface VerifyDataGenerator {
       
   159         byte[] createVerifyData(HandshakeContext context,
       
   160                 boolean isValidation) throws IOException;
       
   161     }
       
   162 
       
   163     enum VerifyDataScheme {
       
   164         SSL30       ("kdf_ssl30", new S30VerifyDataGenerator()),
       
   165         TLS10       ("kdf_tls10", new T10VerifyDataGenerator()),
       
   166         TLS12       ("kdf_tls12", new T12VerifyDataGenerator()),
       
   167         TLS13       ("kdf_tls13", new T13VerifyDataGenerator());
       
   168 
       
   169         final String name;
       
   170         final VerifyDataGenerator generator;
       
   171 
       
   172         VerifyDataScheme(String name, VerifyDataGenerator verifyDataGenerator) {
       
   173             this.name = name;
       
   174             this.generator = verifyDataGenerator;
       
   175         }
       
   176 
       
   177         static VerifyDataScheme valueOf(ProtocolVersion protocolVersion) {
       
   178             switch (protocolVersion) {
       
   179                 case SSL30:
       
   180                     return VerifyDataScheme.SSL30;
       
   181                 case TLS10:
       
   182                 case TLS11:
       
   183                 case DTLS10:
       
   184                     return VerifyDataScheme.TLS10;
       
   185                 case TLS12:
       
   186                 case DTLS12:
       
   187                     return VerifyDataScheme.TLS12;
       
   188                 case TLS13:
       
   189                     return VerifyDataScheme.TLS13;
       
   190                 default:
       
   191                     return null;
       
   192             }
       
   193         }
       
   194 
       
   195         public byte[] createVerifyData(HandshakeContext context,
       
   196                 boolean isValidation) throws IOException {
       
   197             if (generator != null) {
       
   198                 return generator.createVerifyData(context, isValidation);
       
   199             }
       
   200 
       
   201             throw new UnsupportedOperationException("Not supported yet.");
       
   202         }
       
   203     }
       
   204 
       
   205     // SSL 3.0
       
   206     private static final
       
   207             class S30VerifyDataGenerator implements VerifyDataGenerator {
       
   208         @Override
       
   209         public byte[] createVerifyData(HandshakeContext context,
       
   210                 boolean isValidation) throws IOException {
       
   211             HandshakeHash handshakeHash = context.handshakeHash;
       
   212             SecretKey masterSecretKey =
       
   213                     context.handshakeSession.getMasterSecret();
       
   214 
       
   215             boolean useClientLabel =
       
   216                     (context.sslConfig.isClientMode && !isValidation) ||
       
   217                     (!context.sslConfig.isClientMode && isValidation);
       
   218             return handshakeHash.digest(useClientLabel, masterSecretKey);
       
   219         }
       
   220     }
       
   221 
       
   222     // TLS 1.0, TLS 1.1, DTLS 1.0
       
   223     private static final
       
   224             class T10VerifyDataGenerator implements VerifyDataGenerator {
       
   225         @Override
       
   226         public byte[] createVerifyData(HandshakeContext context,
       
   227                 boolean isValidation) throws IOException {
       
   228             HandshakeHash handshakeHash = context.handshakeHash;
       
   229             SecretKey masterSecretKey =
       
   230                     context.handshakeSession.getMasterSecret();
       
   231 
       
   232             boolean useClientLabel =
       
   233                     (context.sslConfig.isClientMode && !isValidation) ||
       
   234                     (!context.sslConfig.isClientMode && isValidation);
       
   235             String tlsLabel;
       
   236             if (useClientLabel) {
       
   237                 tlsLabel = "client finished";
       
   238             } else {
       
   239                 tlsLabel = "server finished";
       
   240             }
       
   241 
       
   242             try {
       
   243                 byte[] seed = handshakeHash.digest();
       
   244                 String prfAlg = "SunTlsPrf";
       
   245                 HashAlg hashAlg = H_NONE;
       
   246 
       
   247                 /*
       
   248                  * RFC 5246/7.4.9 says that finished messages can
       
   249                  * be ciphersuite-specific in both length/PRF hash
       
   250                  * algorithm.  If we ever run across a different
       
   251                  * length, this call will need to be updated.
       
   252                  */
       
   253                 @SuppressWarnings("deprecation")
       
   254                 TlsPrfParameterSpec spec = new TlsPrfParameterSpec(
       
   255                     masterSecretKey, tlsLabel, seed, 12,
       
   256                     hashAlg.name, hashAlg.hashLength, hashAlg.blockSize);
       
   257                 KeyGenerator kg = JsseJce.getKeyGenerator(prfAlg);
       
   258                 kg.init(spec);
       
   259                 SecretKey prfKey = kg.generateKey();
       
   260                 if (!"RAW".equals(prfKey.getFormat())) {
       
   261                     throw new ProviderException(
       
   262                         "Invalid PRF output, format must be RAW. " +
       
   263                         "Format received: " + prfKey.getFormat());
       
   264                 }
       
   265                 byte[] finished = prfKey.getEncoded();
       
   266                 return finished;
       
   267             } catch (GeneralSecurityException e) {
       
   268                 throw new RuntimeException("PRF failed", e);
       
   269             }
       
   270         }
       
   271     }
       
   272 
       
   273     // TLS 1.2
       
   274     private static final
       
   275             class T12VerifyDataGenerator implements VerifyDataGenerator {
       
   276         @Override
       
   277         public byte[] createVerifyData(HandshakeContext context,
       
   278                 boolean isValidation) throws IOException {
       
   279             CipherSuite cipherSuite = context.negotiatedCipherSuite;
       
   280             HandshakeHash handshakeHash = context.handshakeHash;
       
   281             SecretKey masterSecretKey =
       
   282                     context.handshakeSession.getMasterSecret();
       
   283 
       
   284             boolean useClientLabel =
       
   285                     (context.sslConfig.isClientMode && !isValidation) ||
       
   286                     (!context.sslConfig.isClientMode && isValidation);
       
   287             String tlsLabel;
       
   288             if (useClientLabel) {
       
   289                 tlsLabel = "client finished";
       
   290             } else {
       
   291                 tlsLabel = "server finished";
       
   292             }
       
   293 
       
   294             try {
       
   295                 byte[] seed = handshakeHash.digest();
       
   296                 String prfAlg = "SunTls12Prf";
       
   297                 HashAlg hashAlg = cipherSuite.hashAlg;
       
   298 
       
   299                 /*
       
   300                  * RFC 5246/7.4.9 says that finished messages can
       
   301                  * be ciphersuite-specific in both length/PRF hash
       
   302                  * algorithm.  If we ever run across a different
       
   303                  * length, this call will need to be updated.
       
   304                  */
       
   305                 @SuppressWarnings("deprecation")
       
   306                 TlsPrfParameterSpec spec = new TlsPrfParameterSpec(
       
   307                     masterSecretKey, tlsLabel, seed, 12,
       
   308                     hashAlg.name, hashAlg.hashLength, hashAlg.blockSize);
       
   309                 KeyGenerator kg = JsseJce.getKeyGenerator(prfAlg);
       
   310                 kg.init(spec);
       
   311                 SecretKey prfKey = kg.generateKey();
       
   312                 if (!"RAW".equals(prfKey.getFormat())) {
       
   313                     throw new ProviderException(
       
   314                         "Invalid PRF output, format must be RAW. " +
       
   315                         "Format received: " + prfKey.getFormat());
       
   316                 }
       
   317                 byte[] finished = prfKey.getEncoded();
       
   318                 return finished;
       
   319             } catch (GeneralSecurityException e) {
       
   320                 throw new RuntimeException("PRF failed", e);
       
   321             }
       
   322         }
       
   323     }
       
   324 
       
   325     // TLS 1.2
       
   326     private static final
       
   327             class T13VerifyDataGenerator implements VerifyDataGenerator {
       
   328         private static final byte[] hkdfLabel = "tls13 finished".getBytes();
       
   329         private static final byte[] hkdfContext = new byte[0];
       
   330 
       
   331         @Override
       
   332         public byte[] createVerifyData(HandshakeContext context,
       
   333                 boolean isValidation) throws IOException {
       
   334             // create finished secret key
       
   335             HashAlg hashAlg =
       
   336                     context.negotiatedCipherSuite.hashAlg;
       
   337             SecretKey secret = isValidation ?
       
   338                     context.baseReadSecret : context.baseWriteSecret;
       
   339             SSLBasicKeyDerivation kdf = new SSLBasicKeyDerivation(
       
   340                     secret, hashAlg.name,
       
   341                     hkdfLabel, hkdfContext, hashAlg.hashLength);
       
   342             AlgorithmParameterSpec keySpec =
       
   343                     new SecretSizeSpec(hashAlg.hashLength);
       
   344             SecretKey finishedSecret =
       
   345                     kdf.deriveKey("TlsFinishedSecret", keySpec);
       
   346 
       
   347             String hmacAlg =
       
   348                 "Hmac" + hashAlg.name.replace("-", "");
       
   349             try {
       
   350                 Mac hmac = JsseJce.getMac(hmacAlg);
       
   351                 hmac.init(finishedSecret);
       
   352                 return hmac.doFinal(context.handshakeHash.digest());
       
   353             } catch (NoSuchAlgorithmException |InvalidKeyException ex) {
       
   354                 throw new ProviderException(
       
   355                         "Failed to generate verify_data", ex);
       
   356             }
       
   357         }
       
   358     }
       
   359 
       
   360     /**
       
   361      * The "Finished" handshake message producer.
       
   362      */
       
   363     private static final
       
   364             class T12FinishedProducer implements HandshakeProducer {
       
   365         // Prevent instantiation of this class.
       
   366         private T12FinishedProducer() {
       
   367             // blank
       
   368         }
       
   369 
       
   370         @Override
       
   371         public byte[] produce(ConnectionContext context,
       
   372                 HandshakeMessage message) throws IOException {
       
   373             // The consuming happens in handshake context only.
       
   374             HandshakeContext hc = (HandshakeContext)context;
       
   375             if (hc.sslConfig.isClientMode) {
       
   376                 return onProduceFinished(
       
   377                         (ClientHandshakeContext)context, message);
       
   378             } else {
       
   379                 return onProduceFinished(
       
   380                         (ServerHandshakeContext)context, message);
       
   381             }
       
   382         }
       
   383 
       
   384         private byte[] onProduceFinished(ClientHandshakeContext chc,
       
   385                 HandshakeMessage message) throws IOException {
       
   386             // Refresh handshake hash
       
   387             chc.handshakeHash.update();
       
   388 
       
   389             FinishedMessage fm = new FinishedMessage(chc);
       
   390 
       
   391             // Change write cipher and delivery ChangeCipherSpec message.
       
   392             ChangeCipherSpec.t10Producer.produce(chc, message);
       
   393 
       
   394             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   395                 SSLLogger.fine(
       
   396                         "Produced client Finished handshake message", fm);
       
   397             }
       
   398 
       
   399             // Output the handshake message.
       
   400             fm.write(chc.handshakeOutput);
       
   401             chc.handshakeOutput.flush();
       
   402 
       
   403             /*
       
   404              * save server verify data for secure renegotiation
       
   405              */
       
   406             if (chc.conContext.secureRenegotiation) {
       
   407                 chc.conContext.clientVerifyData = fm.verifyData;
       
   408             }
       
   409 
       
   410             // update the consumers and producers
       
   411             if (!chc.isResumption) {
       
   412                 chc.conContext.consumers.put(ContentType.CHANGE_CIPHER_SPEC.id,
       
   413                         ChangeCipherSpec.t10Consumer);
       
   414                 chc.handshakeConsumers.put(
       
   415                         SSLHandshake.FINISHED.id, SSLHandshake.FINISHED);
       
   416                 chc.conContext.inputRecord.expectingFinishFlight();
       
   417             } else {
       
   418                 if (chc.handshakeSession.isRejoinable()) {
       
   419                     ((SSLSessionContextImpl)chc.sslContext.
       
   420                         engineGetClientSessionContext()).put(
       
   421                             chc.handshakeSession);
       
   422                 }
       
   423                 chc.conContext.conSession = chc.handshakeSession.finish();
       
   424                 chc.conContext.protocolVersion = chc.negotiatedProtocol;
       
   425 
       
   426                 // handshake context cleanup.
       
   427                 chc.handshakeFinished = true;
       
   428 
       
   429                 // May need to retransmit the last flight for DTLS.
       
   430                 if (!chc.sslContext.isDTLS()) {
       
   431                     chc.conContext.finishHandshake();
       
   432                 }
       
   433             }
       
   434 
       
   435             // The handshake message has been delivered.
       
   436             return null;
       
   437         }
       
   438 
       
   439         private byte[] onProduceFinished(ServerHandshakeContext shc,
       
   440                 HandshakeMessage message) throws IOException {
       
   441             // Refresh handshake hash
       
   442             shc.handshakeHash.update();
       
   443 
       
   444             FinishedMessage fm = new FinishedMessage(shc);
       
   445 
       
   446             // Change write cipher and delivery ChangeCipherSpec message.
       
   447             ChangeCipherSpec.t10Producer.produce(shc, message);
       
   448 
       
   449             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   450                 SSLLogger.fine(
       
   451                         "Produced server Finished handshake message", fm);
       
   452             }
       
   453 
       
   454             // Output the handshake message.
       
   455             fm.write(shc.handshakeOutput);
       
   456             shc.handshakeOutput.flush();
       
   457 
       
   458             /*
       
   459              * save client verify data for secure renegotiation
       
   460              */
       
   461             if (shc.conContext.secureRenegotiation) {
       
   462                 shc.conContext.serverVerifyData = fm.verifyData;
       
   463             }
       
   464 
       
   465             // update the consumers and producers
       
   466             if (shc.isResumption) {
       
   467                 shc.conContext.consumers.put(ContentType.CHANGE_CIPHER_SPEC.id,
       
   468                         ChangeCipherSpec.t10Consumer);
       
   469                 shc.handshakeConsumers.put(
       
   470                         SSLHandshake.FINISHED.id, SSLHandshake.FINISHED);
       
   471                 shc.conContext.inputRecord.expectingFinishFlight();
       
   472             } else {
       
   473                 if (shc.handshakeSession.isRejoinable()) {
       
   474                     ((SSLSessionContextImpl)shc.sslContext.
       
   475                         engineGetServerSessionContext()).put(
       
   476                             shc.handshakeSession);
       
   477                 }
       
   478                 shc.conContext.conSession = shc.handshakeSession.finish();
       
   479                 shc.conContext.protocolVersion = shc.negotiatedProtocol;
       
   480 
       
   481                 // handshake context cleanup.
       
   482                 shc.handshakeFinished = true;
       
   483 
       
   484                 // May need to retransmit the last flight for DTLS.
       
   485                 if (!shc.sslContext.isDTLS()) {
       
   486                     shc.conContext.finishHandshake();
       
   487                 }
       
   488             }
       
   489 
       
   490             // The handshake message has been delivered.
       
   491             return null;
       
   492         }
       
   493     }
       
   494 
       
   495     /**
       
   496      * The "Finished" handshake message consumer.
       
   497      */
       
   498     private static final class T12FinishedConsumer implements SSLConsumer {
       
   499         // Prevent instantiation of this class.
       
   500         private T12FinishedConsumer() {
       
   501             // blank
       
   502         }
       
   503 
       
   504         @Override
       
   505         public void consume(ConnectionContext context,
       
   506                 ByteBuffer message) throws IOException {
       
   507             // The consuming happens in handshake context only.
       
   508             HandshakeContext hc = (HandshakeContext)context;
       
   509 
       
   510             // This consumer can be used only once.
       
   511             hc.handshakeConsumers.remove(SSLHandshake.FINISHED.id);
       
   512 
       
   513             // We should not be processing finished messages unless
       
   514             // we have received ChangeCipherSpec
       
   515             if (hc.conContext.consumers.containsKey(
       
   516                     ContentType.CHANGE_CIPHER_SPEC.id)) {
       
   517                 hc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
       
   518                         "Missing ChangeCipherSpec message");
       
   519             }
       
   520 
       
   521             if (hc.sslConfig.isClientMode) {
       
   522                 onConsumeFinished((ClientHandshakeContext)context, message);
       
   523             } else {
       
   524                 onConsumeFinished((ServerHandshakeContext)context, message);
       
   525             }
       
   526         }
       
   527 
       
   528         private void onConsumeFinished(ClientHandshakeContext chc,
       
   529                 ByteBuffer message) throws IOException {
       
   530             FinishedMessage fm = new FinishedMessage(chc, message);
       
   531             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   532                 SSLLogger.fine(
       
   533                         "Consuming server Finished handshake message", fm);
       
   534             }
       
   535 
       
   536             if (chc.conContext.secureRenegotiation) {
       
   537                 chc.conContext.serverVerifyData = fm.verifyData;
       
   538             }
       
   539 
       
   540             if (!chc.isResumption) {
       
   541                 if (chc.handshakeSession.isRejoinable()) {
       
   542                     ((SSLSessionContextImpl)chc.sslContext.
       
   543                         engineGetClientSessionContext()).put(
       
   544                             chc.handshakeSession);
       
   545                 }
       
   546                 chc.conContext.conSession = chc.handshakeSession.finish();
       
   547                 chc.conContext.protocolVersion = chc.negotiatedProtocol;
       
   548 
       
   549                 // handshake context cleanup.
       
   550                 chc.handshakeFinished = true;
       
   551 
       
   552                 // May need to retransmit the last flight for DTLS.
       
   553                 if (!chc.sslContext.isDTLS()) {
       
   554                     chc.conContext.finishHandshake();
       
   555                 }
       
   556             } else {
       
   557                 chc.handshakeProducers.put(SSLHandshake.FINISHED.id,
       
   558                         SSLHandshake.FINISHED);
       
   559             }
       
   560 
       
   561             //
       
   562             // produce
       
   563             //
       
   564             SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
       
   565                 SSLHandshake.FINISHED
       
   566             };
       
   567 
       
   568             for (SSLHandshake hs : probableHandshakeMessages) {
       
   569                 HandshakeProducer handshakeProducer =
       
   570                         chc.handshakeProducers.remove(hs.id);
       
   571                 if (handshakeProducer != null) {
       
   572                     handshakeProducer.produce(chc, fm);
       
   573                 }
       
   574             }
       
   575         }
       
   576 
       
   577         private void onConsumeFinished(ServerHandshakeContext shc,
       
   578                 ByteBuffer message) throws IOException {
       
   579             FinishedMessage fm = new FinishedMessage(shc, message);
       
   580             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   581                 SSLLogger.fine(
       
   582                         "Consuming client Finished handshake message", fm);
       
   583             }
       
   584 
       
   585             if (shc.conContext.secureRenegotiation) {
       
   586                 shc.conContext.clientVerifyData = fm.verifyData;
       
   587             }
       
   588 
       
   589             if (shc.isResumption) {
       
   590                 if (shc.handshakeSession.isRejoinable()) {
       
   591                     ((SSLSessionContextImpl)shc.sslContext.
       
   592                         engineGetServerSessionContext()).put(
       
   593                             shc.handshakeSession);
       
   594                 }
       
   595                 shc.conContext.conSession = shc.handshakeSession.finish();
       
   596                 shc.conContext.protocolVersion = shc.negotiatedProtocol;
       
   597 
       
   598                 // handshake context cleanup.
       
   599                 shc.handshakeFinished = true;
       
   600 
       
   601                 // May need to retransmit the last flight for DTLS.
       
   602                 if (!shc.sslContext.isDTLS()) {
       
   603                     shc.conContext.finishHandshake();
       
   604                 }
       
   605             } else {
       
   606                 shc.handshakeProducers.put(SSLHandshake.FINISHED.id,
       
   607                         SSLHandshake.FINISHED);
       
   608             }
       
   609 
       
   610             //
       
   611             // produce
       
   612             //
       
   613             SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
       
   614                 SSLHandshake.FINISHED
       
   615             };
       
   616 
       
   617             for (SSLHandshake hs : probableHandshakeMessages) {
       
   618                 HandshakeProducer handshakeProducer =
       
   619                         shc.handshakeProducers.remove(hs.id);
       
   620                 if (handshakeProducer != null) {
       
   621                     handshakeProducer.produce(shc, fm);
       
   622                 }
       
   623             }
       
   624         }
       
   625     }
       
   626 
       
   627     /**
       
   628      * The "Finished" handshake message producer.
       
   629      */
       
   630     private static final
       
   631             class T13FinishedProducer implements HandshakeProducer {
       
   632         // Prevent instantiation of this class.
       
   633         private T13FinishedProducer() {
       
   634             // blank
       
   635         }
       
   636 
       
   637         @Override
       
   638         public byte[] produce(ConnectionContext context,
       
   639                 HandshakeMessage message) throws IOException {
       
   640             // The consuming happens in handshake context only.
       
   641             HandshakeContext hc = (HandshakeContext)context;
       
   642             if (hc.sslConfig.isClientMode) {
       
   643                 return onProduceFinished(
       
   644                         (ClientHandshakeContext)context, message);
       
   645             } else {
       
   646                 return onProduceFinished(
       
   647                         (ServerHandshakeContext)context, message);
       
   648             }
       
   649         }
       
   650 
       
   651         private byte[] onProduceFinished(ClientHandshakeContext chc,
       
   652                 HandshakeMessage message) throws IOException {
       
   653             // Refresh handshake hash
       
   654             chc.handshakeHash.update();
       
   655 
       
   656             FinishedMessage fm = new FinishedMessage(chc);
       
   657             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   658                 SSLLogger.fine(
       
   659                         "Produced client Finished handshake message", fm);
       
   660             }
       
   661 
       
   662             // Output the handshake message.
       
   663             fm.write(chc.handshakeOutput);
       
   664             chc.handshakeOutput.flush();
       
   665 
       
   666             // save server verify data for secure renegotiation
       
   667             if (chc.conContext.secureRenegotiation) {
       
   668                 chc.conContext.clientVerifyData = fm.verifyData;
       
   669             }
       
   670 
       
   671             // update the context
       
   672             // Change client/server application traffic secrets.
       
   673             SSLKeyDerivation kd = chc.handshakeKeyDerivation;
       
   674             if (kd == null) {
       
   675                 // unlikely
       
   676                 chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   677                     "no key derivation");
       
   678                 return null;    // make the compiler happy
       
   679             }
       
   680 
       
   681             SSLTrafficKeyDerivation kdg =
       
   682                     SSLTrafficKeyDerivation.valueOf(chc.negotiatedProtocol);
       
   683             if (kdg == null) {
       
   684                 // unlikely
       
   685                 chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   686                         "Not supported key derivation: " +
       
   687                         chc.negotiatedProtocol);
       
   688                 return null;    // make the compiler happy
       
   689             }
       
   690 
       
   691             try {
       
   692                 // update the application traffic read keys.
       
   693                 SecretKey writeSecret = kd.deriveKey(
       
   694                         "TlsClientAppTrafficSecret", null);
       
   695 
       
   696                 SSLKeyDerivation writeKD =
       
   697                         kdg.createKeyDerivation(chc, writeSecret);
       
   698                 SecretKey writeKey = writeKD.deriveKey(
       
   699                         "TlsKey", null);
       
   700                 SecretKey writeIvSecret = writeKD.deriveKey(
       
   701                         "TlsIv", null);
       
   702                 IvParameterSpec writeIv =
       
   703                         new IvParameterSpec(writeIvSecret.getEncoded());
       
   704                 SSLWriteCipher writeCipher =
       
   705                         chc.negotiatedCipherSuite.bulkCipher.createWriteCipher(
       
   706                                 Authenticator.valueOf(chc.negotiatedProtocol),
       
   707                                 chc.negotiatedProtocol, writeKey, writeIv,
       
   708                                 chc.sslContext.getSecureRandom());
       
   709 
       
   710                 chc.baseWriteSecret = writeSecret;
       
   711                 chc.conContext.outputRecord.changeWriteCiphers(
       
   712                         writeCipher, false);
       
   713 
       
   714             } catch (GeneralSecurityException gse) {
       
   715                 chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   716                         "Failure to derive application secrets", gse);
       
   717                 return null;    // make the compiler happy
       
   718             }
       
   719 
       
   720             // The resumption master secret is stored in the session so
       
   721             // it can be used after the handshake is completed.
       
   722             SSLSecretDerivation sd = ((SSLSecretDerivation) kd).forContext(chc);
       
   723             SecretKey resumptionMasterSecret = sd.deriveKey(
       
   724             "TlsResumptionMasterSecret", null);
       
   725             chc.handshakeSession.setResumptionMasterSecret(resumptionMasterSecret);
       
   726 
       
   727             chc.conContext.conSession = chc.handshakeSession.finish();
       
   728             chc.conContext.protocolVersion = chc.negotiatedProtocol;
       
   729 
       
   730             // handshake context cleanup.
       
   731             chc.handshakeFinished = true;
       
   732             chc.conContext.finishHandshake();
       
   733 
       
   734             // The handshake message has been delivered.
       
   735             return null;
       
   736         }
       
   737 
       
   738         private byte[] onProduceFinished(ServerHandshakeContext shc,
       
   739                 HandshakeMessage message) throws IOException {
       
   740             // Refresh handshake hash
       
   741             shc.handshakeHash.update();
       
   742 
       
   743             FinishedMessage fm = new FinishedMessage(shc);
       
   744             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   745                 SSLLogger.fine(
       
   746                         "Produced server Finished handshake message", fm);
       
   747             }
       
   748 
       
   749             // Output the handshake message.
       
   750             fm.write(shc.handshakeOutput);
       
   751             shc.handshakeOutput.flush();
       
   752 
       
   753             // Change client/server application traffic secrets.
       
   754             SSLKeyDerivation kd = shc.handshakeKeyDerivation;
       
   755             if (kd == null) {
       
   756                 // unlikely
       
   757                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   758                     "no key derivation");
       
   759                 return null;    // make the compiler happy
       
   760             }
       
   761 
       
   762             SSLTrafficKeyDerivation kdg =
       
   763                     SSLTrafficKeyDerivation.valueOf(shc.negotiatedProtocol);
       
   764             if (kdg == null) {
       
   765                 // unlikely
       
   766                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   767                         "Not supported key derivation: " +
       
   768                         shc.negotiatedProtocol);
       
   769                 return null;    // make the compiler happy
       
   770             }
       
   771 
       
   772             // derive salt secret
       
   773             try {
       
   774                 SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
       
   775 
       
   776                 // derive application secrets
       
   777                 HashAlg hashAlg = shc.negotiatedCipherSuite.hashAlg;
       
   778                 HKDF hkdf = new HKDF(hashAlg.name);
       
   779                 byte[] zeros = new byte[hashAlg.hashLength];
       
   780                 SecretKeySpec sharedSecret =
       
   781                         new SecretKeySpec(zeros, "TlsZeroSecret");
       
   782                 SecretKey masterSecret =
       
   783                     hkdf.extract(saltSecret, sharedSecret, "TlsMasterSecret");
       
   784 
       
   785                 SSLKeyDerivation secretKD =
       
   786                         new SSLSecretDerivation(shc, masterSecret);
       
   787 
       
   788                 // update the handshake traffic write keys.
       
   789                 SecretKey writeSecret = secretKD.deriveKey(
       
   790                         "TlsServerAppTrafficSecret", null);
       
   791                 SSLKeyDerivation writeKD =
       
   792                         kdg.createKeyDerivation(shc, writeSecret);
       
   793                 SecretKey writeKey = writeKD.deriveKey(
       
   794                         "TlsKey", null);
       
   795                 SecretKey writeIvSecret = writeKD.deriveKey(
       
   796                         "TlsIv", null);
       
   797                 IvParameterSpec writeIv =
       
   798                         new IvParameterSpec(writeIvSecret.getEncoded());
       
   799                 SSLWriteCipher writeCipher =
       
   800                         shc.negotiatedCipherSuite.bulkCipher.createWriteCipher(
       
   801                                 Authenticator.valueOf(shc.negotiatedProtocol),
       
   802                                 shc.negotiatedProtocol, writeKey, writeIv,
       
   803                                 shc.sslContext.getSecureRandom());
       
   804 
       
   805                 shc.baseWriteSecret = writeSecret;
       
   806                 shc.conContext.outputRecord.changeWriteCiphers(
       
   807                         writeCipher, false);
       
   808 
       
   809                 // update the context for the following key derivation
       
   810                 shc.handshakeKeyDerivation = secretKD;
       
   811             } catch (GeneralSecurityException gse) {
       
   812                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   813                         "Failure to derive application secrets", gse);
       
   814                 return null;    // make the compiler happy
       
   815             }
       
   816 
       
   817             /*
       
   818              * save client verify data for secure renegotiation
       
   819              */
       
   820             if (shc.conContext.secureRenegotiation) {
       
   821                 shc.conContext.serverVerifyData = fm.verifyData;
       
   822             }
       
   823 
       
   824             // update the context
       
   825             shc.handshakeConsumers.put(
       
   826                     SSLHandshake.FINISHED.id, SSLHandshake.FINISHED);
       
   827 
       
   828             // The handshake message has been delivered.
       
   829             return null;
       
   830         }
       
   831     }
       
   832 
       
   833     /**
       
   834      * The "Finished" handshake message consumer.
       
   835      */
       
   836     private static final class T13FinishedConsumer implements SSLConsumer {
       
   837         // Prevent instantiation of this class.
       
   838         private T13FinishedConsumer() {
       
   839             // blank
       
   840         }
       
   841 
       
   842         @Override
       
   843         public void consume(ConnectionContext context,
       
   844                 ByteBuffer message) throws IOException {
       
   845             // The consuming happens in handshake context only.
       
   846             HandshakeContext hc = (HandshakeContext)context;
       
   847             if (hc.sslConfig.isClientMode) {
       
   848                 onConsumeFinished(
       
   849                         (ClientHandshakeContext)context, message);
       
   850             } else {
       
   851                 onConsumeFinished(
       
   852                         (ServerHandshakeContext)context, message);
       
   853             }
       
   854         }
       
   855 
       
   856         private void onConsumeFinished(ClientHandshakeContext chc,
       
   857                 ByteBuffer message) throws IOException {
       
   858             FinishedMessage fm = new FinishedMessage(chc, message);
       
   859             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   860                 SSLLogger.fine(
       
   861                         "Consuming server Finished handshake message", fm);
       
   862             }
       
   863 
       
   864             // Save client verify data for secure renegotiation.
       
   865             if (chc.conContext.secureRenegotiation) {
       
   866                 chc.conContext.serverVerifyData = fm.verifyData;
       
   867             }
       
   868 
       
   869             //
       
   870             // validate
       
   871             //
       
   872             // blank
       
   873 
       
   874             //
       
   875             // update
       
   876             //
       
   877             // A change_cipher_spec record received after the peer's Finished
       
   878             // message MUST be treated as an unexpected record type.
       
   879             chc.conContext.consumers.remove(ContentType.CHANGE_CIPHER_SPEC.id);
       
   880 
       
   881             // Change client/server application traffic secrets.
       
   882             // Refresh handshake hash
       
   883             chc.handshakeHash.update();
       
   884             SSLKeyDerivation kd = chc.handshakeKeyDerivation;
       
   885             if (kd == null) {
       
   886                 // unlikely
       
   887                 chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   888                     "no key derivation");
       
   889                 return;    // make the compiler happy
       
   890             }
       
   891 
       
   892             SSLTrafficKeyDerivation kdg =
       
   893                     SSLTrafficKeyDerivation.valueOf(chc.negotiatedProtocol);
       
   894             if (kdg == null) {
       
   895                 // unlikely
       
   896                 chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   897                         "Not supported key derivation: " +
       
   898                         chc.negotiatedProtocol);
       
   899                 return;    // make the compiler happy
       
   900             }
       
   901 
       
   902             // save the session
       
   903             if (!chc.isResumption && chc.handshakeSession.isRejoinable()) {
       
   904                 SSLSessionContextImpl sessionContext = (SSLSessionContextImpl)
       
   905                 chc.sslContext.engineGetClientSessionContext();
       
   906                 sessionContext.put(chc.handshakeSession);
       
   907             }
       
   908 
       
   909             // derive salt secret
       
   910             try {
       
   911                 SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
       
   912 
       
   913                 // derive application secrets
       
   914                 HashAlg hashAlg = chc.negotiatedCipherSuite.hashAlg;
       
   915                 HKDF hkdf = new HKDF(hashAlg.name);
       
   916                 byte[] zeros = new byte[hashAlg.hashLength];
       
   917                 SecretKeySpec sharedSecret =
       
   918                         new SecretKeySpec(zeros, "TlsZeroSecret");
       
   919                 SecretKey masterSecret =
       
   920                     hkdf.extract(saltSecret, sharedSecret, "TlsMasterSecret");
       
   921 
       
   922                 SSLKeyDerivation secretKD =
       
   923                         new SSLSecretDerivation(chc, masterSecret);
       
   924 
       
   925                 // update the handshake traffic read keys.
       
   926                 SecretKey readSecret = secretKD.deriveKey(
       
   927                         "TlsServerAppTrafficSecret", null);
       
   928                 SSLKeyDerivation writeKD =
       
   929                         kdg.createKeyDerivation(chc, readSecret);
       
   930                 SecretKey readKey = writeKD.deriveKey(
       
   931                         "TlsKey", null);
       
   932                 SecretKey readIvSecret = writeKD.deriveKey(
       
   933                         "TlsIv", null);
       
   934                 IvParameterSpec readIv =
       
   935                         new IvParameterSpec(readIvSecret.getEncoded());
       
   936                 SSLReadCipher readCipher =
       
   937                         chc.negotiatedCipherSuite.bulkCipher.createReadCipher(
       
   938                                 Authenticator.valueOf(chc.negotiatedProtocol),
       
   939                                 chc.negotiatedProtocol, readKey, readIv,
       
   940                                 chc.sslContext.getSecureRandom());
       
   941 
       
   942                 chc.baseReadSecret = readSecret;
       
   943                 chc.conContext.inputRecord.changeReadCiphers(readCipher);
       
   944 
       
   945                 // update the context for the following key derivation
       
   946                 chc.handshakeKeyDerivation = secretKD;
       
   947             } catch (GeneralSecurityException gse) {
       
   948                 chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   949                         "Failure to derive application secrets", gse);
       
   950                 return;    // make the compiler happy
       
   951             }
       
   952 
       
   953             //
       
   954             // produce
       
   955             //
       
   956             chc.handshakeProducers.put(SSLHandshake.FINISHED.id,
       
   957                         SSLHandshake.FINISHED);
       
   958             SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
       
   959                 // full handshake messages
       
   960                 SSLHandshake.CERTIFICATE,
       
   961                 SSLHandshake.CERTIFICATE_VERIFY,
       
   962                 SSLHandshake.FINISHED
       
   963             };
       
   964 
       
   965             for (SSLHandshake hs : probableHandshakeMessages) {
       
   966                 HandshakeProducer handshakeProducer =
       
   967                         chc.handshakeProducers.remove(hs.id);
       
   968                 if (handshakeProducer != null) {
       
   969                     handshakeProducer.produce(chc, null);
       
   970                 }
       
   971             }
       
   972         }
       
   973 
       
   974         private void onConsumeFinished(ServerHandshakeContext shc,
       
   975                 ByteBuffer message) throws IOException {
       
   976             FinishedMessage fm = new FinishedMessage(shc, message);
       
   977             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   978                 SSLLogger.fine(
       
   979                         "Consuming client Finished handshake message", fm);
       
   980             }
       
   981 
       
   982             if (shc.conContext.secureRenegotiation) {
       
   983                 shc.conContext.clientVerifyData = fm.verifyData;
       
   984             }
       
   985 
       
   986             //
       
   987             // validate
       
   988             //
       
   989             // blank
       
   990 
       
   991             //
       
   992             // update
       
   993             //
       
   994             // Change client/server application traffic secrets.
       
   995             SSLKeyDerivation kd = shc.handshakeKeyDerivation;
       
   996             if (kd == null) {
       
   997                 // unlikely
       
   998                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   999                     "no key derivation");
       
  1000                 return;    // make the compiler happy
       
  1001             }
       
  1002 
       
  1003             SSLTrafficKeyDerivation kdg =
       
  1004                     SSLTrafficKeyDerivation.valueOf(shc.negotiatedProtocol);
       
  1005             if (kdg == null) {
       
  1006                 // unlikely
       
  1007                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
  1008                         "Not supported key derivation: " +
       
  1009                         shc.negotiatedProtocol);
       
  1010                 return;    // make the compiler happy
       
  1011             }
       
  1012 
       
  1013             // save the session
       
  1014             if (!shc.isResumption && shc.handshakeSession.isRejoinable()) {
       
  1015                 SSLSessionContextImpl sessionContext = (SSLSessionContextImpl)
       
  1016                 shc.sslContext.engineGetServerSessionContext();
       
  1017                 sessionContext.put(shc.handshakeSession);
       
  1018             }
       
  1019 
       
  1020             try {
       
  1021                 // update the application traffic read keys.
       
  1022                 SecretKey readSecret = kd.deriveKey(
       
  1023                         "TlsClientAppTrafficSecret", null);
       
  1024 
       
  1025                 SSLKeyDerivation readKD =
       
  1026                         kdg.createKeyDerivation(shc, readSecret);
       
  1027                 SecretKey readKey = readKD.deriveKey(
       
  1028                         "TlsKey", null);
       
  1029                 SecretKey readIvSecret = readKD.deriveKey(
       
  1030                         "TlsIv", null);
       
  1031                 IvParameterSpec readIv =
       
  1032                         new IvParameterSpec(readIvSecret.getEncoded());
       
  1033                 SSLReadCipher readCipher =
       
  1034                         shc.negotiatedCipherSuite.bulkCipher.createReadCipher(
       
  1035                                 Authenticator.valueOf(shc.negotiatedProtocol),
       
  1036                                 shc.negotiatedProtocol, readKey, readIv,
       
  1037                                 shc.sslContext.getSecureRandom());
       
  1038 
       
  1039                 shc.baseReadSecret = readSecret;
       
  1040                 shc.conContext.inputRecord.changeReadCiphers(readCipher);
       
  1041 
       
  1042                 // The resumption master secret is stored in the session so
       
  1043                 // it can be used after the handshake is completed.
       
  1044                 shc.handshakeHash.update();
       
  1045                 SSLSecretDerivation sd = ((SSLSecretDerivation)kd).forContext(shc);
       
  1046                 SecretKey resumptionMasterSecret = sd.deriveKey(
       
  1047                 "TlsResumptionMasterSecret", null);
       
  1048                 shc.handshakeSession.setResumptionMasterSecret(resumptionMasterSecret);
       
  1049             } catch (GeneralSecurityException gse) {
       
  1050                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
  1051                         "Failure to derive application secrets", gse);
       
  1052                 return;    // make the compiler happy
       
  1053             }
       
  1054 
       
  1055             //  update connection context
       
  1056             shc.conContext.conSession = shc.handshakeSession.finish();
       
  1057             shc.conContext.protocolVersion = shc.negotiatedProtocol;
       
  1058 
       
  1059             // handshake context cleanup.
       
  1060             shc.handshakeFinished = true;
       
  1061 
       
  1062             // May need to retransmit the last flight for DTLS.
       
  1063             if (!shc.sslContext.isDTLS()) {
       
  1064                 shc.conContext.finishHandshake();
       
  1065             }
       
  1066 
       
  1067             //
       
  1068             // produce
       
  1069             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
  1070                 SSLLogger.fine(
       
  1071                 "Sending new session ticket");
       
  1072             }
       
  1073             NewSessionTicket.kickstartProducer.produce(shc);
       
  1074 
       
  1075         }
       
  1076     }
       
  1077 }