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 String peerCertID = ""; 1091 try { 1092 peerCertID = session 1093 .getCertificateChain()[0] 1094 .getSerialNumber() 1095 .toString(16); 1096 } catch (SSLPeerUnverifiedException e) { 1097 peerCertID = e.getMessage(); // not verified msg 1098 } 1099 if(event.shouldCommit()) { 1100 event.peerHost = session.getPeerHost(); 1101 event.peerPort = session.getPeerPort(); 1102 event.cipherSuite = session.getCipherSuite(); 1103 event.protocolVersion = session.getProtocol(); 1104 event.peerCertId = peerCertID; 1105 event.commit(); 1106 } 1107 if (EventHelper.isLoggingSecurity()) { 1108 EventHelper.logTLSHandshakeEvent(null, 1109 session.getPeerHost(), 1110 session.getPeerPort(), 1111 session.getCipherSuite(), 1112 session.getProtocol(), 1113 peerCertID); 1114 } 1115 } 1116 } 1117 }