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