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