--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/SSLMasterKeyDerivation.java Fri May 11 15:53:12 2018 -0700
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ssl;
+
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.ProviderException;
+import java.security.spec.AlgorithmParameterSpec;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import sun.security.internal.spec.TlsMasterSecretParameterSpec;
+import sun.security.ssl.CipherSuite.HashAlg;
+import static sun.security.ssl.CipherSuite.HashAlg.H_NONE;
+
+enum SSLMasterKeyDerivation implements SSLKeyDerivationGenerator {
+ SSL30 ("kdf_ssl30", S30MasterSecretKeyDerivationGenerator.instance),
+ TLS10 ("kdf_tls10", T10MasterSecretKeyDerivationGenerator.instance),
+ TLS12 ("kdf_tls12", T12MasterSecretKeyDerivationGenerator.instance),
+ TLS13 ("kdf_tls13", null);
+
+ final String name;
+ final SSLKeyDerivationGenerator keyDerivationGenerator;
+
+ SSLMasterKeyDerivation(String name,
+ SSLKeyDerivationGenerator keyDerivationGenerator) {
+ this.name = name;
+ this.keyDerivationGenerator = keyDerivationGenerator;
+ }
+
+ static SSLMasterKeyDerivation valueOf(ProtocolVersion protocolVersion) {
+ switch (protocolVersion) {
+ case SSL30:
+ return SSLMasterKeyDerivation.SSL30;
+ case TLS10:
+ case TLS11:
+ case DTLS10:
+ return SSLMasterKeyDerivation.TLS10;
+ case TLS12:
+ case DTLS12:
+ return SSLMasterKeyDerivation.TLS12;
+ case TLS13:
+ case DTLS13:
+ return SSLMasterKeyDerivation.TLS13;
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ public SSLKeyDerivation createKeyDerivation(HandshakeContext context,
+ SecretKey secretKey) throws IOException {
+ return keyDerivationGenerator.createKeyDerivation(context, secretKey);
+ }
+
+ private static final class S30MasterSecretKeyDerivationGenerator
+ implements SSLKeyDerivationGenerator {
+ private static final S30MasterSecretKeyDerivationGenerator instance =
+ new S30MasterSecretKeyDerivationGenerator();
+
+ // Prevent instantiation of this class.
+ private S30MasterSecretKeyDerivationGenerator() {
+ // blank
+ }
+
+ @Override
+ public SSLKeyDerivation createKeyDerivation(
+ HandshakeContext context, SecretKey secretKey) throws IOException {
+ return new LegacyMasterKeyDerivation(context, secretKey);
+ }
+ }
+
+
+ private static final class T10MasterSecretKeyDerivationGenerator
+ implements SSLKeyDerivationGenerator {
+ private static final T10MasterSecretKeyDerivationGenerator instance =
+ new T10MasterSecretKeyDerivationGenerator();
+
+ // Prevent instantiation of this class.
+ private T10MasterSecretKeyDerivationGenerator() {
+ // blank
+ }
+
+ @Override
+ public SSLKeyDerivation createKeyDerivation(
+ HandshakeContext context, SecretKey secretKey) throws IOException {
+ return new LegacyMasterKeyDerivation(context, secretKey);
+ }
+ }
+
+ private static final class T12MasterSecretKeyDerivationGenerator
+ implements SSLKeyDerivationGenerator {
+ private static final T12MasterSecretKeyDerivationGenerator instance =
+ new T12MasterSecretKeyDerivationGenerator();
+
+ // Prevent instantiation of this class.
+ private T12MasterSecretKeyDerivationGenerator() {
+ // blank
+ }
+
+ @Override
+ public SSLKeyDerivation createKeyDerivation(
+ HandshakeContext context, SecretKey secretKey) throws IOException {
+ return new LegacyMasterKeyDerivation(context, secretKey);
+ }
+
+ }
+
+ private static final
+ class LegacyMasterKeyDerivation implements SSLKeyDerivation {
+
+ final HandshakeContext context;
+ final SecretKey preMasterSecret;
+
+ LegacyMasterKeyDerivation(
+ HandshakeContext context, SecretKey preMasterSecret) {
+ this.context = context;
+ this.preMasterSecret = preMasterSecret;
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public SecretKey deriveKey(String algorithm,
+ AlgorithmParameterSpec params) throws IOException {
+
+ CipherSuite cipherSuite = context.negotiatedCipherSuite;
+ ProtocolVersion protocolVersion = context.negotiatedProtocol;
+
+ // What algs/params do we need to use?
+ String masterAlg;
+ HashAlg hashAlg;
+
+ byte majorVersion = protocolVersion.major;
+ byte minorVersion = protocolVersion.minor;
+ if (protocolVersion.isDTLS) {
+ // Use TLS version number for DTLS key calculation
+ if (protocolVersion.id == ProtocolVersion.DTLS10.id) {
+ majorVersion = ProtocolVersion.TLS11.major;
+ minorVersion = ProtocolVersion.TLS11.minor;
+
+ masterAlg = "SunTlsMasterSecret";
+ hashAlg = H_NONE;
+ } else { // DTLS 1.2
+ majorVersion = ProtocolVersion.TLS12.major;
+ minorVersion = ProtocolVersion.TLS12.minor;
+
+ masterAlg = "SunTls12MasterSecret";
+ hashAlg = cipherSuite.hashAlg;
+ }
+ } else {
+ if (protocolVersion.id >= ProtocolVersion.TLS12.id) {
+ masterAlg = "SunTls12MasterSecret";
+ hashAlg = cipherSuite.hashAlg;
+ } else {
+ masterAlg = "SunTlsMasterSecret";
+ hashAlg = H_NONE;
+ }
+ }
+
+ TlsMasterSecretParameterSpec spec;
+ if (context.handshakeSession.useExtendedMasterSecret) {
+ // reset to use the extended master secret algorithm
+ masterAlg = "SunTlsExtendedMasterSecret";
+
+ // For the session hash, use the handshake messages up to and
+ // including the ClientKeyExchange message.
+ context.handshakeHash.utilize();
+ byte[] sessionHash = context.handshakeHash.digest();
+ spec = new TlsMasterSecretParameterSpec(
+ preMasterSecret,
+ (majorVersion & 0xFF), (minorVersion & 0xFF),
+ sessionHash,
+ hashAlg.name, hashAlg.hashLength, hashAlg.blockSize);
+ } else {
+ spec = new TlsMasterSecretParameterSpec(
+ preMasterSecret,
+ (majorVersion & 0xFF), (minorVersion & 0xFF),
+ context.clientHelloRandom.randomBytes,
+ context.serverHelloRandom.randomBytes,
+ hashAlg.name, hashAlg.hashLength, hashAlg.blockSize);
+ }
+
+ try {
+ KeyGenerator kg = JsseJce.getKeyGenerator(masterAlg);
+ kg.init(spec);
+ return kg.generateKey();
+ } catch (InvalidAlgorithmParameterException |
+ NoSuchAlgorithmException iae) {
+ // unlikely to happen, otherwise, must be a provider exception
+ //
+ // For RSA premaster secrets, do not signal a protocol error
+ // due to the Bleichenbacher attack. See comments further down.
+ if (SSLLogger.isOn && SSLLogger.isOn("handshake")) {
+ SSLLogger.fine("RSA master secret generation error.", iae);
+ }
+ throw new ProviderException(iae);
+ }
+ }
+ }
+}