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