1 /* 2 * Copyright (c) 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.security.InvalidAlgorithmParameterException; 30 import java.security.NoSuchAlgorithmException; 31 import java.security.ProviderException; 32 import java.security.spec.AlgorithmParameterSpec; 33 import javax.crypto.KeyGenerator; 34 import javax.crypto.SecretKey; 35 import sun.security.internal.spec.TlsMasterSecretParameterSpec; 36 import sun.security.ssl.CipherSuite.HashAlg; 37 import static sun.security.ssl.CipherSuite.HashAlg.H_NONE; 38 39 enum SSLMasterKeyDerivation implements SSLKeyDerivationGenerator { 40 SSL30 ("kdf_ssl30"), 41 TLS10 ("kdf_tls10"), 42 TLS12 ("kdf_tls12"); 43 44 final String name; 45 SSLMasterKeyDerivation(String name)46 private SSLMasterKeyDerivation(String name) { 47 this.name = name; 48 } 49 valueOf(ProtocolVersion protocolVersion)50 static SSLMasterKeyDerivation valueOf(ProtocolVersion protocolVersion) { 51 switch (protocolVersion) { 52 case SSL30: 53 return SSLMasterKeyDerivation.SSL30; 54 case TLS10: 55 case TLS11: 56 case DTLS10: 57 return SSLMasterKeyDerivation.TLS10; 58 case TLS12: 59 case DTLS12: 60 return SSLMasterKeyDerivation.TLS12; 61 default: 62 return null; 63 } 64 } 65 66 @Override createKeyDerivation(HandshakeContext context, SecretKey secretKey)67 public SSLKeyDerivation createKeyDerivation(HandshakeContext context, 68 SecretKey secretKey) throws IOException { 69 return new LegacyMasterKeyDerivation(context, secretKey); 70 } 71 72 // Note, we may use different key derivation implementation in the future. 73 private static final 74 class LegacyMasterKeyDerivation implements SSLKeyDerivation { 75 76 final HandshakeContext context; 77 final SecretKey preMasterSecret; 78 LegacyMasterKeyDerivation( HandshakeContext context, SecretKey preMasterSecret)79 LegacyMasterKeyDerivation( 80 HandshakeContext context, SecretKey preMasterSecret) { 81 this.context = context; 82 this.preMasterSecret = preMasterSecret; 83 } 84 85 @Override 86 @SuppressWarnings("deprecation") deriveKey(String algorithm, AlgorithmParameterSpec params)87 public SecretKey deriveKey(String algorithm, 88 AlgorithmParameterSpec params) throws IOException { 89 90 CipherSuite cipherSuite = context.negotiatedCipherSuite; 91 ProtocolVersion protocolVersion = context.negotiatedProtocol; 92 93 // What algs/params do we need to use? 94 String masterAlg; 95 HashAlg hashAlg; 96 97 byte majorVersion = protocolVersion.major; 98 byte minorVersion = protocolVersion.minor; 99 if (protocolVersion.isDTLS) { 100 // Use TLS version number for DTLS key calculation 101 if (protocolVersion.id == ProtocolVersion.DTLS10.id) { 102 majorVersion = ProtocolVersion.TLS11.major; 103 minorVersion = ProtocolVersion.TLS11.minor; 104 105 masterAlg = "SunTlsMasterSecret"; 106 hashAlg = H_NONE; 107 } else { // DTLS 1.2 108 majorVersion = ProtocolVersion.TLS12.major; 109 minorVersion = ProtocolVersion.TLS12.minor; 110 111 masterAlg = "SunTls12MasterSecret"; 112 hashAlg = cipherSuite.hashAlg; 113 } 114 } else { 115 if (protocolVersion.id >= ProtocolVersion.TLS12.id) { 116 masterAlg = "SunTls12MasterSecret"; 117 hashAlg = cipherSuite.hashAlg; 118 } else { 119 masterAlg = "SunTlsMasterSecret"; 120 hashAlg = H_NONE; 121 } 122 } 123 124 TlsMasterSecretParameterSpec spec; 125 if (context.handshakeSession.useExtendedMasterSecret) { 126 // reset to use the extended master secret algorithm 127 masterAlg = "SunTlsExtendedMasterSecret"; 128 129 // For the session hash, use the handshake messages up to and 130 // including the ClientKeyExchange message. 131 context.handshakeHash.utilize(); 132 byte[] sessionHash = context.handshakeHash.digest(); 133 spec = new TlsMasterSecretParameterSpec( 134 preMasterSecret, 135 (majorVersion & 0xFF), (minorVersion & 0xFF), 136 sessionHash, 137 hashAlg.name, hashAlg.hashLength, hashAlg.blockSize); 138 } else { 139 spec = new TlsMasterSecretParameterSpec( 140 preMasterSecret, 141 (majorVersion & 0xFF), (minorVersion & 0xFF), 142 context.clientHelloRandom.randomBytes, 143 context.serverHelloRandom.randomBytes, 144 hashAlg.name, hashAlg.hashLength, hashAlg.blockSize); 145 } 146 147 try { 148 KeyGenerator kg = JsseJce.getKeyGenerator(masterAlg); 149 kg.init(spec); 150 return kg.generateKey(); 151 } catch (InvalidAlgorithmParameterException | 152 NoSuchAlgorithmException iae) { 153 // unlikely to happen, otherwise, must be a provider exception 154 // 155 // For RSA premaster secrets, do not signal a protocol error 156 // due to the Bleichenbacher attack. See comments further down. 157 if (SSLLogger.isOn && SSLLogger.isOn("handshake")) { 158 SSLLogger.fine("RSA master secret generation error.", iae); 159 } 160 throw new ProviderException(iae); 161 } 162 } 163 } 164 } 165