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