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