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             if (chc.statelessResumption) {
 414                 chc.handshakeConsumers.put(
 415                         SSLHandshake.NEW_SESSION_TICKET.id, SSLHandshake.NEW_SESSION_TICKET);
 416             }
 417             // update the consumers and producers
 418             if (!chc.isResumption) {
 419                 chc.conContext.consumers.put(ContentType.CHANGE_CIPHER_SPEC.id,
 420                         ChangeCipherSpec.t10Consumer);
 421                 chc.handshakeConsumers.put(
 422                         SSLHandshake.FINISHED.id, SSLHandshake.FINISHED);
 423                 chc.conContext.inputRecord.expectingFinishFlight();
 424             } else {
 425                 if (chc.handshakeSession.isRejoinable()) {
 426                     ((SSLSessionContextImpl)chc.sslContext.
 427                         engineGetClientSessionContext()).put(
 428                             chc.handshakeSession);
 429                 }
 430                 chc.conContext.conSession = chc.handshakeSession.finish();
 431                 chc.conContext.protocolVersion = chc.negotiatedProtocol;
 432 
 433                 // handshake context cleanup.
 434                 chc.handshakeFinished = true;
 435 
 436                 // May need to retransmit the last flight for DTLS.
 437                 if (!chc.sslContext.isDTLS()) {
 438                     chc.conContext.finishHandshake();
 439                 }
 440             }
 441 
 442             // The handshake message has been delivered.
 443             return null;
 444         }
 445 
 446         private byte[] onProduceFinished(ServerHandshakeContext shc,
 447                 HandshakeMessage message) throws IOException {
 448             if (shc.statelessResumption) {
 449                 NewSessionTicket.handshake12Producer.produce(shc, message);
 450             }
 451 
 452             // Refresh handshake hash
 453             shc.handshakeHash.update();
 454 
 455             FinishedMessage fm = new FinishedMessage(shc);
 456 
 457             // Change write cipher and delivery ChangeCipherSpec message.
 458             ChangeCipherSpec.t10Producer.produce(shc, message);
 459 
 460             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 461                 SSLLogger.fine(
 462                         "Produced server Finished handshake message", fm);
 463             }
 464 
 465             // Output the handshake message.
 466             fm.write(shc.handshakeOutput);
 467             shc.handshakeOutput.flush();
 468 
 469             /*
 470              * save client verify data for secure renegotiation
 471              */
 472             if (shc.conContext.secureRenegotiation) {
 473                 shc.conContext.serverVerifyData = fm.verifyData;
 474             }
 475 
 476             // update the consumers and producers
 477             if (shc.isResumption) {
 478                 shc.conContext.consumers.put(ContentType.CHANGE_CIPHER_SPEC.id,
 479                         ChangeCipherSpec.t10Consumer);
 480                 shc.handshakeConsumers.put(
 481                         SSLHandshake.FINISHED.id, SSLHandshake.FINISHED);
 482                 shc.conContext.inputRecord.expectingFinishFlight();
 483             } else {
 484                 if (shc.handshakeSession.isRejoinable() &&
 485                         !shc.statelessResumption) {
 486                     ((SSLSessionContextImpl)shc.sslContext.
 487                         engineGetServerSessionContext()).put(
 488                             shc.handshakeSession);
 489                 }
 490                 shc.conContext.conSession = shc.handshakeSession.finish();
 491                 shc.conContext.protocolVersion = shc.negotiatedProtocol;
 492 
 493                 // handshake context cleanup.
 494                 shc.handshakeFinished = true;
 495 
 496                 // May need to retransmit the last flight for DTLS.
 497                 if (!shc.sslContext.isDTLS()) {
 498                     shc.conContext.finishHandshake();
 499                 }
 500             }
 501 
 502             // The handshake message has been delivered.
 503             return null;
 504         }
 505     }
 506 
 507     /**
 508      * The "Finished" handshake message consumer.
 509      */
 510     private static final class T12FinishedConsumer implements SSLConsumer {
 511         // Prevent instantiation of this class.
 512         private T12FinishedConsumer() {
 513             // blank
 514         }
 515 
 516         @Override
 517         public void consume(ConnectionContext context,
 518                 ByteBuffer message) throws IOException {
 519             // The consuming happens in handshake context only.
 520             HandshakeContext hc = (HandshakeContext)context;
 521 
 522             // This consumer can be used only once.
 523             hc.handshakeConsumers.remove(SSLHandshake.FINISHED.id);
 524 
 525             // We should not be processing finished messages unless
 526             // we have received ChangeCipherSpec
 527             if (hc.conContext.consumers.containsKey(
 528                     ContentType.CHANGE_CIPHER_SPEC.id)) {
 529                 throw hc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
 530                         "Missing ChangeCipherSpec message");
 531             }
 532 
 533             if (hc.sslConfig.isClientMode) {
 534                 onConsumeFinished((ClientHandshakeContext)context, message);
 535             } else {
 536                 onConsumeFinished((ServerHandshakeContext)context, message);
 537             }
 538         }
 539 
 540         private void onConsumeFinished(ClientHandshakeContext chc,
 541                 ByteBuffer message) throws IOException {
 542             FinishedMessage fm = new FinishedMessage(chc, message);
 543             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 544                 SSLLogger.fine(
 545                         "Consuming server Finished handshake message", fm);
 546             }
 547 
 548             if (chc.conContext.secureRenegotiation) {
 549                 chc.conContext.serverVerifyData = fm.verifyData;
 550             }
 551 
 552             if (!chc.isResumption) {
 553                 if (chc.handshakeSession.isRejoinable()) {
 554                     ((SSLSessionContextImpl)chc.sslContext.
 555                         engineGetClientSessionContext()).put(
 556                             chc.handshakeSession);
 557                 }
 558                 chc.conContext.conSession = chc.handshakeSession.finish();
 559                 chc.conContext.protocolVersion = chc.negotiatedProtocol;
 560 
 561                 // handshake context cleanup.
 562                 chc.handshakeFinished = true;
 563                 recordEvent(chc.conContext.conSession);
 564 
 565                 // May need to retransmit the last flight for DTLS.
 566                 if (!chc.sslContext.isDTLS()) {
 567                     chc.conContext.finishHandshake();
 568                 }
 569             } else {
 570                 chc.handshakeProducers.put(SSLHandshake.FINISHED.id,
 571                         SSLHandshake.FINISHED);
 572             }
 573 
 574             //
 575             // produce
 576             //
 577             SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
 578                 SSLHandshake.FINISHED
 579             };
 580 
 581             for (SSLHandshake hs : probableHandshakeMessages) {
 582                 HandshakeProducer handshakeProducer =
 583                         chc.handshakeProducers.remove(hs.id);
 584                 if (handshakeProducer != null) {
 585                     handshakeProducer.produce(chc, fm);
 586                 }
 587             }
 588         }
 589 
 590         private void onConsumeFinished(ServerHandshakeContext shc,
 591                 ByteBuffer message) throws IOException {
 592             FinishedMessage fm = new FinishedMessage(shc, message);
 593             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 594                 SSLLogger.fine(
 595                         "Consuming client Finished handshake message", fm);
 596             }
 597 
 598             if (shc.conContext.secureRenegotiation) {
 599                 shc.conContext.clientVerifyData = fm.verifyData;
 600             }
 601 
 602             if (shc.isResumption) {
 603                 if (shc.handshakeSession.isRejoinable() &&
 604                         !shc.statelessResumption) {
 605                     ((SSLSessionContextImpl)shc.sslContext.
 606                         engineGetServerSessionContext()).put(
 607                             shc.handshakeSession);
 608                 }
 609                 shc.conContext.conSession = shc.handshakeSession.finish();
 610                 shc.conContext.protocolVersion = shc.negotiatedProtocol;
 611 
 612                 // handshake context cleanup.
 613                 shc.handshakeFinished = true;
 614                 recordEvent(shc.conContext.conSession);
 615 
 616                 // May need to retransmit the last flight for DTLS.
 617                 if (!shc.sslContext.isDTLS()) {
 618                     shc.conContext.finishHandshake();
 619                 }
 620             } else {
 621                 shc.handshakeProducers.put(SSLHandshake.FINISHED.id,
 622                         SSLHandshake.FINISHED);
 623             }
 624 
 625             //
 626             // produce
 627             //
 628             SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
 629                 SSLHandshake.FINISHED
 630             };
 631 
 632             for (SSLHandshake hs : probableHandshakeMessages) {
 633                 HandshakeProducer handshakeProducer =
 634                         shc.handshakeProducers.remove(hs.id);
 635                 if (handshakeProducer != null) {
 636                     handshakeProducer.produce(shc, fm);
 637                 }
 638             }
 639         }
 640     }
 641 
 642     /**
 643      * The "Finished" handshake message producer.
 644      */
 645     private static final
 646             class T13FinishedProducer implements HandshakeProducer {
 647         // Prevent instantiation of this class.
 648         private T13FinishedProducer() {
 649             // blank
 650         }
 651 
 652         @Override
 653         public byte[] produce(ConnectionContext context,
 654                 HandshakeMessage message) throws IOException {
 655             // The consuming happens in handshake context only.
 656             HandshakeContext hc = (HandshakeContext)context;
 657             if (hc.sslConfig.isClientMode) {
 658                 return onProduceFinished(
 659                         (ClientHandshakeContext)context, message);
 660             } else {
 661                 return onProduceFinished(
 662                         (ServerHandshakeContext)context, message);
 663             }
 664         }
 665 
 666         private byte[] onProduceFinished(ClientHandshakeContext chc,
 667                 HandshakeMessage message) throws IOException {
 668             // Refresh handshake hash
 669             chc.handshakeHash.update();
 670 
 671             FinishedMessage fm = new FinishedMessage(chc);
 672             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 673                 SSLLogger.fine(
 674                         "Produced client Finished handshake message", fm);
 675             }
 676 
 677             // Output the handshake message.
 678             fm.write(chc.handshakeOutput);
 679             chc.handshakeOutput.flush();
 680 
 681             // save server verify data for secure renegotiation
 682             if (chc.conContext.secureRenegotiation) {
 683                 chc.conContext.clientVerifyData = fm.verifyData;
 684             }
 685 
 686             // update the context
 687             // Change client/server application traffic secrets.
 688             SSLKeyDerivation kd = chc.handshakeKeyDerivation;
 689             if (kd == null) {
 690                 // unlikely
 691                 throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
 692                     "no key derivation");
 693             }
 694 
 695             SSLTrafficKeyDerivation kdg =
 696                     SSLTrafficKeyDerivation.valueOf(chc.negotiatedProtocol);
 697             if (kdg == null) {
 698                 // unlikely
 699                 throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
 700                         "Not supported key derivation: " +
 701                         chc.negotiatedProtocol);
 702             }
 703 
 704             try {
 705                 // update the application traffic read keys.
 706                 SecretKey writeSecret = kd.deriveKey(
 707                         "TlsClientAppTrafficSecret", null);
 708 
 709                 SSLKeyDerivation writeKD =
 710                         kdg.createKeyDerivation(chc, writeSecret);
 711                 SecretKey writeKey = writeKD.deriveKey(
 712                         "TlsKey", null);
 713                 SecretKey writeIvSecret = writeKD.deriveKey(
 714                         "TlsIv", null);
 715                 IvParameterSpec writeIv =
 716                         new IvParameterSpec(writeIvSecret.getEncoded());
 717                 SSLWriteCipher writeCipher =
 718                         chc.negotiatedCipherSuite.bulkCipher.createWriteCipher(
 719                                 Authenticator.valueOf(chc.negotiatedProtocol),
 720                                 chc.negotiatedProtocol, writeKey, writeIv,
 721                                 chc.sslContext.getSecureRandom());
 722 
 723                 if (writeCipher == null) {
 724                     throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 725                         "Illegal cipher suite (" + chc.negotiatedCipherSuite +
 726                         ") and protocol version (" + chc.negotiatedProtocol +
 727                         ")");
 728                 }
 729 
 730                 chc.baseWriteSecret = writeSecret;
 731                 chc.conContext.outputRecord.changeWriteCiphers(
 732                         writeCipher, false);
 733 
 734             } catch (GeneralSecurityException gse) {
 735                 throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
 736                         "Failure to derive application secrets", gse);
 737             }
 738 
 739             // The resumption master secret is stored in the session so
 740             // it can be used after the handshake is completed.
 741             SSLSecretDerivation sd = ((SSLSecretDerivation) kd).forContext(chc);
 742             SecretKey resumptionMasterSecret = sd.deriveKey(
 743                     "TlsResumptionMasterSecret", null);
 744             chc.handshakeSession.setResumptionMasterSecret(
 745                     resumptionMasterSecret);
 746 
 747             chc.conContext.conSession = chc.handshakeSession.finish();
 748             chc.conContext.protocolVersion = chc.negotiatedProtocol;
 749 
 750             // handshake context cleanup.
 751             chc.handshakeFinished = true;
 752             chc.conContext.finishHandshake();
 753             recordEvent(chc.conContext.conSession);
 754 
 755 
 756             // The handshake message has been delivered.
 757             return null;
 758         }
 759 
 760         private byte[] onProduceFinished(ServerHandshakeContext shc,
 761                 HandshakeMessage message) throws IOException {
 762             // Refresh handshake hash
 763             shc.handshakeHash.update();
 764 
 765             FinishedMessage fm = new FinishedMessage(shc);
 766             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 767                 SSLLogger.fine(
 768                         "Produced server Finished handshake message", fm);
 769             }
 770 
 771             // Output the handshake message.
 772             fm.write(shc.handshakeOutput);
 773             shc.handshakeOutput.flush();
 774 
 775             // Change client/server application traffic secrets.
 776             SSLKeyDerivation kd = shc.handshakeKeyDerivation;
 777             if (kd == null) {
 778                 // unlikely
 779                 throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
 780                     "no key derivation");
 781             }
 782 
 783             SSLTrafficKeyDerivation kdg =
 784                     SSLTrafficKeyDerivation.valueOf(shc.negotiatedProtocol);
 785             if (kdg == null) {
 786                 // unlikely
 787                 throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
 788                         "Not supported key derivation: " +
 789                         shc.negotiatedProtocol);
 790             }
 791 
 792             // derive salt secret
 793             try {
 794                 SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
 795 
 796                 // derive application secrets
 797                 HashAlg hashAlg = shc.negotiatedCipherSuite.hashAlg;
 798                 HKDF hkdf = new HKDF(hashAlg.name);
 799                 byte[] zeros = new byte[hashAlg.hashLength];
 800                 SecretKeySpec sharedSecret =
 801                         new SecretKeySpec(zeros, "TlsZeroSecret");
 802                 SecretKey masterSecret =
 803                     hkdf.extract(saltSecret, sharedSecret, "TlsMasterSecret");
 804 
 805                 SSLKeyDerivation secretKD =
 806                         new SSLSecretDerivation(shc, masterSecret);
 807 
 808                 // update the handshake traffic write keys.
 809                 SecretKey writeSecret = secretKD.deriveKey(
 810                         "TlsServerAppTrafficSecret", null);
 811                 SSLKeyDerivation writeKD =
 812                         kdg.createKeyDerivation(shc, writeSecret);
 813                 SecretKey writeKey = writeKD.deriveKey(
 814                         "TlsKey", null);
 815                 SecretKey writeIvSecret = writeKD.deriveKey(
 816                         "TlsIv", null);
 817                 IvParameterSpec writeIv =
 818                         new IvParameterSpec(writeIvSecret.getEncoded());
 819                 SSLWriteCipher writeCipher =
 820                         shc.negotiatedCipherSuite.bulkCipher.createWriteCipher(
 821                                 Authenticator.valueOf(shc.negotiatedProtocol),
 822                                 shc.negotiatedProtocol, writeKey, writeIv,
 823                                 shc.sslContext.getSecureRandom());
 824 
 825                 if (writeCipher == null) {
 826                     throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 827                         "Illegal cipher suite (" + shc.negotiatedCipherSuite +
 828                         ") and protocol version (" + shc.negotiatedProtocol +
 829                         ")");
 830                 }
 831 
 832                 shc.baseWriteSecret = writeSecret;
 833                 shc.conContext.outputRecord.changeWriteCiphers(
 834                         writeCipher, false);
 835 
 836                 // update the context for the following key derivation
 837                 shc.handshakeKeyDerivation = secretKD;
 838             } catch (GeneralSecurityException gse) {
 839                 throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
 840                         "Failure to derive application secrets", gse);
 841             }
 842 
 843             /*
 844              * save client verify data for secure renegotiation
 845              */
 846             if (shc.conContext.secureRenegotiation) {
 847                 shc.conContext.serverVerifyData = fm.verifyData;
 848             }
 849 
 850             // update the context
 851             shc.handshakeConsumers.put(
 852                     SSLHandshake.FINISHED.id, SSLHandshake.FINISHED);
 853 
 854             // The handshake message has been delivered.
 855             return null;
 856         }
 857     }
 858 
 859     /**
 860      * The "Finished" handshake message consumer.
 861      */
 862     private static final class T13FinishedConsumer implements SSLConsumer {
 863         // Prevent instantiation of this class.
 864         private T13FinishedConsumer() {
 865             // blank
 866         }
 867 
 868         @Override
 869         public void consume(ConnectionContext context,
 870                 ByteBuffer message) throws IOException {
 871             // The consuming happens in handshake context only.
 872             HandshakeContext hc = (HandshakeContext)context;
 873             if (hc.sslConfig.isClientMode) {
 874                 onConsumeFinished(
 875                         (ClientHandshakeContext)context, message);
 876             } else {
 877                 onConsumeFinished(
 878                         (ServerHandshakeContext)context, message);
 879             }
 880         }
 881 
 882         private void onConsumeFinished(ClientHandshakeContext chc,
 883                 ByteBuffer message) throws IOException {
 884             FinishedMessage fm = new FinishedMessage(chc, message);
 885             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 886                 SSLLogger.fine(
 887                         "Consuming server Finished handshake message", fm);
 888             }
 889 
 890             // Save client verify data for secure renegotiation.
 891             if (chc.conContext.secureRenegotiation) {
 892                 chc.conContext.serverVerifyData = fm.verifyData;
 893             }
 894 
 895             //
 896             // validate
 897             //
 898             // blank
 899 
 900             //
 901             // update
 902             //
 903             // A change_cipher_spec record received after the peer's Finished
 904             // message MUST be treated as an unexpected record type.
 905             chc.conContext.consumers.remove(ContentType.CHANGE_CIPHER_SPEC.id);
 906 
 907             // Change client/server application traffic secrets.
 908             // Refresh handshake hash
 909             chc.handshakeHash.update();
 910             SSLKeyDerivation kd = chc.handshakeKeyDerivation;
 911             if (kd == null) {
 912                 // unlikely
 913                 throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
 914                     "no key derivation");
 915             }
 916 
 917             SSLTrafficKeyDerivation kdg =
 918                     SSLTrafficKeyDerivation.valueOf(chc.negotiatedProtocol);
 919             if (kdg == null) {
 920                 // unlikely
 921                 throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
 922                         "Not supported key derivation: " +
 923                         chc.negotiatedProtocol);
 924             }
 925 
 926             // save the session
 927             if (!chc.isResumption && chc.handshakeSession.isRejoinable()) {
 928                 ((SSLSessionContextImpl)chc.sslContext.
 929                         engineGetClientSessionContext()).
 930                         put(chc.handshakeSession);
 931             }
 932 
 933             // derive salt secret
 934             try {
 935                 SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
 936 
 937                 // derive application secrets
 938                 HashAlg hashAlg = chc.negotiatedCipherSuite.hashAlg;
 939                 HKDF hkdf = new HKDF(hashAlg.name);
 940                 byte[] zeros = new byte[hashAlg.hashLength];
 941                 SecretKeySpec sharedSecret =
 942                         new SecretKeySpec(zeros, "TlsZeroSecret");
 943                 SecretKey masterSecret =
 944                     hkdf.extract(saltSecret, sharedSecret, "TlsMasterSecret");
 945 
 946                 SSLKeyDerivation secretKD =
 947                         new SSLSecretDerivation(chc, masterSecret);
 948 
 949                 // update the handshake traffic read keys.
 950                 SecretKey readSecret = secretKD.deriveKey(
 951                         "TlsServerAppTrafficSecret", null);
 952                 SSLKeyDerivation writeKD =
 953                         kdg.createKeyDerivation(chc, readSecret);
 954                 SecretKey readKey = writeKD.deriveKey(
 955                         "TlsKey", null);
 956                 SecretKey readIvSecret = writeKD.deriveKey(
 957                         "TlsIv", null);
 958                 IvParameterSpec readIv =
 959                         new IvParameterSpec(readIvSecret.getEncoded());
 960                 SSLReadCipher readCipher =
 961                         chc.negotiatedCipherSuite.bulkCipher.createReadCipher(
 962                                 Authenticator.valueOf(chc.negotiatedProtocol),
 963                                 chc.negotiatedProtocol, readKey, readIv,
 964                                 chc.sslContext.getSecureRandom());
 965 
 966                 if (readCipher == null) {
 967                     throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 968                         "Illegal cipher suite (" + chc.negotiatedCipherSuite +
 969                         ") and protocol version (" + chc.negotiatedProtocol +
 970                         ")");
 971                 }
 972 
 973                 chc.baseReadSecret = readSecret;
 974                 chc.conContext.inputRecord.changeReadCiphers(readCipher);
 975 
 976                 // update the context for the following key derivation
 977                 chc.handshakeKeyDerivation = secretKD;
 978             } catch (GeneralSecurityException gse) {
 979                 throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
 980                         "Failure to derive application secrets", gse);
 981             }
 982 
 983             //
 984             // produce
 985             //
 986             chc.handshakeProducers.put(SSLHandshake.FINISHED.id,
 987                         SSLHandshake.FINISHED);
 988             SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
 989                 // full handshake messages
 990                 SSLHandshake.CERTIFICATE,
 991                 SSLHandshake.CERTIFICATE_VERIFY,
 992                 SSLHandshake.FINISHED
 993             };
 994 
 995             for (SSLHandshake hs : probableHandshakeMessages) {
 996                 HandshakeProducer handshakeProducer =
 997                         chc.handshakeProducers.remove(hs.id);
 998                 if (handshakeProducer != null) {
 999                     handshakeProducer.produce(chc, null);
1000                 }
1001             }
1002         }
1003 
1004         private void onConsumeFinished(ServerHandshakeContext shc,
1005                 ByteBuffer message) throws IOException {
1006             FinishedMessage fm = new FinishedMessage(shc, message);
1007             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1008                 SSLLogger.fine(
1009                         "Consuming client Finished handshake message", fm);
1010             }
1011 
1012             if (shc.conContext.secureRenegotiation) {
1013                 shc.conContext.clientVerifyData = fm.verifyData;
1014             }
1015 
1016             //
1017             // validate
1018             //
1019             // blank
1020 
1021             //
1022             // update
1023             //
1024             // Change client/server application traffic secrets.
1025             SSLKeyDerivation kd = shc.handshakeKeyDerivation;
1026             if (kd == null) {
1027                 // unlikely
1028                 throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
1029                     "no key derivation");
1030             }
1031 
1032             SSLTrafficKeyDerivation kdg =
1033                     SSLTrafficKeyDerivation.valueOf(shc.negotiatedProtocol);
1034             if (kdg == null) {
1035                 // unlikely
1036                 throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
1037                         "Not supported key derivation: " +
1038                         shc.negotiatedProtocol);
1039             }
1040 
1041             // Save the session if possible and not stateless
1042             if (!shc.statelessResumption && !shc.isResumption &&
1043                     shc.handshakeSession.isRejoinable()) {
1044                 SSLSessionContextImpl sessionContext = (SSLSessionContextImpl)
1045                         shc.sslContext.engineGetServerSessionContext();
1046                 sessionContext.put(shc.handshakeSession);
1047             }
1048 
1049             try {
1050                 // update the application traffic read keys.
1051                 SecretKey readSecret = kd.deriveKey(
1052                         "TlsClientAppTrafficSecret", null);
1053 
1054                 SSLKeyDerivation readKD =
1055                         kdg.createKeyDerivation(shc, readSecret);
1056                 SecretKey readKey = readKD.deriveKey(
1057                         "TlsKey", null);
1058                 SecretKey readIvSecret = readKD.deriveKey(
1059                         "TlsIv", null);
1060                 IvParameterSpec readIv =
1061                         new IvParameterSpec(readIvSecret.getEncoded());
1062                 SSLReadCipher readCipher =
1063                         shc.negotiatedCipherSuite.bulkCipher.createReadCipher(
1064                                 Authenticator.valueOf(shc.negotiatedProtocol),
1065                                 shc.negotiatedProtocol, readKey, readIv,
1066                                 shc.sslContext.getSecureRandom());
1067 
1068                 if (readCipher == null) {
1069                     throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
1070                         "Illegal cipher suite (" + shc.negotiatedCipherSuite +
1071                         ") and protocol version (" + shc.negotiatedProtocol +
1072                         ")");
1073                 }
1074 
1075                 shc.baseReadSecret = readSecret;
1076                 shc.conContext.inputRecord.changeReadCiphers(readCipher);
1077 
1078                 // The resumption master secret is stored in the session so
1079                 // it can be used after the handshake is completed.
1080                 shc.handshakeHash.update();
1081                 SSLSecretDerivation sd =
1082                         ((SSLSecretDerivation)kd).forContext(shc);
1083                 SecretKey resumptionMasterSecret = sd.deriveKey(
1084                 "TlsResumptionMasterSecret", null);
1085                 shc.handshakeSession.setResumptionMasterSecret(
1086                         resumptionMasterSecret);
1087             } catch (GeneralSecurityException gse) {
1088                 throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
1089                         "Failure to derive application secrets", gse);
1090             }
1091 
1092             //  update connection context
1093             shc.conContext.conSession = shc.handshakeSession.finish();
1094             shc.conContext.protocolVersion = shc.negotiatedProtocol;
1095 
1096             // handshake context cleanup.
1097             shc.handshakeFinished = true;
1098 
1099             // May need to retransmit the last flight for DTLS.
1100             if (!shc.sslContext.isDTLS()) {
1101                 shc.conContext.finishHandshake();
1102             }
1103             recordEvent(shc.conContext.conSession);
1104 
1105             //
1106             // produce
1107             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1108                 SSLLogger.fine(
1109                 "Sending new session ticket");
1110             }
1111             NewSessionTicket.kickstartProducer.produce(shc);
1112 
1113         }
1114     }
1115 
1116     private static void recordEvent(SSLSessionImpl session) {
1117         TLSHandshakeEvent event = new TLSHandshakeEvent();
1118         if (event.shouldCommit() || EventHelper.isLoggingSecurity()) {
1119             int peerCertificateId = 0;
1120             try {
1121                 // use hash code for Id
1122                 peerCertificateId = session
1123                         .getCertificateChain()[0]
1124                         .hashCode();
1125             } catch (SSLPeerUnverifiedException e) {
1126                  // not verified msg
1127             }
1128             if (event.shouldCommit()) {
1129                 event.peerHost = session.getPeerHost();
1130                 event.peerPort = session.getPeerPort();
1131                 event.cipherSuite = session.getCipherSuite();
1132                 event.protocolVersion = session.getProtocol();
1133                 event.certificateId = peerCertificateId;
1134                 event.commit();
1135             }
1136             if (EventHelper.isLoggingSecurity()) {
1137                 EventHelper.logTLSHandshakeEvent(null,
1138                                 session.getPeerHost(),
1139                                 session.getPeerPort(),
1140                                 session.getCipherSuite(),
1141                                 session.getProtocol(),
1142                                 peerCertificateId);
1143             }
1144         }
1145     }
1146 }