src/java.base/share/classes/sun/security/ssl/SSLMasterKeyDerivation.java
branchJDK-8145252-TLS13-branch
changeset 56542 56aaa6cb3693
child 56714 2d7e08d730b6
equal deleted inserted replaced
56541:92cbbfc996f3 56542:56aaa6cb3693
       
     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 }