src/java.base/share/classes/sun/security/ssl/SSLMasterKeyDerivation.java
changeset 50768 68fa3d4026ea
child 53734 cb1642ccc732
equal deleted inserted replaced
50767:356eaea05bf0 50768:68fa3d4026ea
       
     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 
       
    46     private SSLMasterKeyDerivation(String name) {
       
    47         this.name = name;
       
    48     }
       
    49 
       
    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
       
    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 
       
    79         LegacyMasterKeyDerivation(
       
    80                 HandshakeContext context, SecretKey preMasterSecret) {
       
    81             this.context = context;
       
    82             this.preMasterSecret = preMasterSecret;
       
    83         }
       
    84 
       
    85         @Override
       
    86         @SuppressWarnings("deprecation")
       
    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 }