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", S30MasterSecretKeyDerivationGenerator.instance),
  41     TLS10       ("kdf_tls10", T10MasterSecretKeyDerivationGenerator.instance),
  42     TLS12       ("kdf_tls12", T12MasterSecretKeyDerivationGenerator.instance),
  43     TLS13       ("kdf_tls13", null);
  44 
  45     final String name;
  46     final SSLKeyDerivationGenerator keyDerivationGenerator;
  47 
  48     SSLMasterKeyDerivation(String name,
  49             SSLKeyDerivationGenerator keyDerivationGenerator) {
  50         this.name = name;
  51         this.keyDerivationGenerator = keyDerivationGenerator;
  52     }
  53 
  54     static SSLMasterKeyDerivation valueOf(ProtocolVersion protocolVersion) {
  55         switch (protocolVersion) {
  56             case SSL30:
  57                 return SSLMasterKeyDerivation.SSL30;
  58             case TLS10:
  59             case TLS11:
  60             case DTLS10:
  61                 return SSLMasterKeyDerivation.TLS10;
  62             case TLS12:
  63             case DTLS12:
  64                 return SSLMasterKeyDerivation.TLS12;
  65             case TLS13:
  66             case DTLS13:
  67                 return SSLMasterKeyDerivation.TLS13;
  68             default:
  69                 return null;
  70         }
  71     }
  72 
  73     @Override
  74     public SSLKeyDerivation createKeyDerivation(HandshakeContext context,
  75             SecretKey secretKey) throws IOException {
  76         return keyDerivationGenerator.createKeyDerivation(context, secretKey);
  77     }
  78 
  79     private static final class S30MasterSecretKeyDerivationGenerator
  80             implements SSLKeyDerivationGenerator {
  81         private static final S30MasterSecretKeyDerivationGenerator instance =
  82                 new S30MasterSecretKeyDerivationGenerator();
  83 
  84         // Prevent instantiation of this class.
  85         private S30MasterSecretKeyDerivationGenerator() {
  86             // blank
  87         }
  88 
  89         @Override
  90         public SSLKeyDerivation createKeyDerivation(
  91             HandshakeContext context, SecretKey secretKey) throws IOException {
  92             return new LegacyMasterKeyDerivation(context, secretKey);
  93         }
  94     }
  95 
  96 
  97     private static final class T10MasterSecretKeyDerivationGenerator
  98             implements SSLKeyDerivationGenerator {
  99         private static final T10MasterSecretKeyDerivationGenerator instance =
 100                 new T10MasterSecretKeyDerivationGenerator();
 101 
 102         // Prevent instantiation of this class.
 103         private T10MasterSecretKeyDerivationGenerator() {
 104             // blank
 105         }
 106 
 107         @Override
 108         public SSLKeyDerivation createKeyDerivation(
 109             HandshakeContext context, SecretKey secretKey) throws IOException {
 110             return new LegacyMasterKeyDerivation(context, secretKey);
 111         }
 112     }
 113 
 114     private static final class T12MasterSecretKeyDerivationGenerator
 115             implements SSLKeyDerivationGenerator {
 116         private static final T12MasterSecretKeyDerivationGenerator instance =
 117                 new T12MasterSecretKeyDerivationGenerator();
 118 
 119         // Prevent instantiation of this class.
 120         private T12MasterSecretKeyDerivationGenerator() {
 121             // blank
 122         }
 123 
 124         @Override
 125         public SSLKeyDerivation createKeyDerivation(
 126             HandshakeContext context, SecretKey secretKey) throws IOException {
 127             return new LegacyMasterKeyDerivation(context, secretKey);
 128         }
 129 
 130     }
 131 
 132     private static final
 133             class LegacyMasterKeyDerivation implements SSLKeyDerivation {
 134 
 135         final HandshakeContext context;
 136         final SecretKey preMasterSecret;
 137 
 138         LegacyMasterKeyDerivation(
 139                 HandshakeContext context, SecretKey preMasterSecret) {
 140             this.context = context;
 141             this.preMasterSecret = preMasterSecret;
 142         }
 143 
 144         @Override
 145         @SuppressWarnings("deprecation")
 146         public SecretKey deriveKey(String algorithm,
 147                 AlgorithmParameterSpec params) throws IOException {
 148 
 149             CipherSuite cipherSuite = context.negotiatedCipherSuite;
 150             ProtocolVersion protocolVersion = context.negotiatedProtocol;
 151 
 152             // What algs/params do we need to use?
 153             String masterAlg;
 154             HashAlg hashAlg;
 155 
 156             byte majorVersion = protocolVersion.major;
 157             byte minorVersion = protocolVersion.minor;
 158             if (protocolVersion.isDTLS) {
 159                 // Use TLS version number for DTLS key calculation
 160                 if (protocolVersion.id == ProtocolVersion.DTLS10.id) {
 161                     majorVersion = ProtocolVersion.TLS11.major;
 162                     minorVersion = ProtocolVersion.TLS11.minor;
 163 
 164                     masterAlg = "SunTlsMasterSecret";
 165                     hashAlg = H_NONE;
 166                 } else {    // DTLS 1.2
 167                     majorVersion = ProtocolVersion.TLS12.major;
 168                     minorVersion = ProtocolVersion.TLS12.minor;
 169 
 170                     masterAlg = "SunTls12MasterSecret";
 171                     hashAlg = cipherSuite.hashAlg;
 172                 }
 173             } else {
 174                 if (protocolVersion.id >= ProtocolVersion.TLS12.id) {
 175                     masterAlg = "SunTls12MasterSecret";
 176                     hashAlg = cipherSuite.hashAlg;
 177                 } else {
 178                     masterAlg = "SunTlsMasterSecret";
 179                     hashAlg = H_NONE;
 180                 }
 181             }
 182 
 183             TlsMasterSecretParameterSpec spec;
 184             if (context.handshakeSession.useExtendedMasterSecret) {
 185                 // reset to use the extended master secret algorithm
 186                 masterAlg = "SunTlsExtendedMasterSecret";
 187 
 188                 // For the session hash, use the handshake messages up to and
 189                 // including the ClientKeyExchange message.
 190                 context.handshakeHash.utilize();
 191                 byte[] sessionHash = context.handshakeHash.digest();
 192                 spec = new TlsMasterSecretParameterSpec(
 193                         preMasterSecret,
 194                         (majorVersion & 0xFF), (minorVersion & 0xFF),
 195                         sessionHash,
 196                         hashAlg.name, hashAlg.hashLength, hashAlg.blockSize);
 197             } else {
 198                 spec = new TlsMasterSecretParameterSpec(
 199                         preMasterSecret,
 200                         (majorVersion & 0xFF), (minorVersion & 0xFF),
 201                         context.clientHelloRandom.randomBytes,
 202                         context.serverHelloRandom.randomBytes,
 203                         hashAlg.name, hashAlg.hashLength, hashAlg.blockSize);
 204             }
 205 
 206             try {
 207                 KeyGenerator kg = JsseJce.getKeyGenerator(masterAlg);
 208                 kg.init(spec);
 209                 return kg.generateKey();
 210             } catch (InvalidAlgorithmParameterException |
 211                     NoSuchAlgorithmException iae) {
 212                 // unlikely to happen, otherwise, must be a provider exception
 213                 //
 214                 // For RSA premaster secrets, do not signal a protocol error
 215                 // due to the Bleichenbacher attack. See comments further down.
 216                 if (SSLLogger.isOn && SSLLogger.isOn("handshake")) {
 217                     SSLLogger.fine("RSA master secret generation error.", iae);
 218                 }
 219                 throw new ProviderException(iae);
 220             }
 221         }
 222     }
 223 }