1 /*
2  * Copyright (c) 2005, 2017, 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 com.sun.crypto.provider;
27 
28 import java.security.*;
29 import java.security.spec.AlgorithmParameterSpec;
30 
31 import javax.crypto.*;
32 
33 import sun.security.internal.interfaces.TlsMasterSecret;
34 import sun.security.internal.spec.TlsMasterSecretParameterSpec;
35 
36 import static com.sun.crypto.provider.TlsPrfGenerator.*;
37 
38 /**
39  * KeyGenerator implementation for the SSL/TLS master secret derivation.
40  *
41  * @author  Andreas Sterbenz
42  * @since   1.6
43  */
44 public final class TlsMasterSecretGenerator extends KeyGeneratorSpi {
45 
46     private static final String MSG = "TlsMasterSecretGenerator must be "
47         + "initialized using a TlsMasterSecretParameterSpec";
48 
49     @SuppressWarnings("deprecation")
50     private TlsMasterSecretParameterSpec spec;
51 
52     private int protocolVersion;
53 
TlsMasterSecretGenerator()54     public TlsMasterSecretGenerator() {
55     }
56 
engineInit(SecureRandom random)57     protected void engineInit(SecureRandom random) {
58         throw new InvalidParameterException(MSG);
59     }
60 
61     @SuppressWarnings("deprecation")
engineInit(AlgorithmParameterSpec params, SecureRandom random)62     protected void engineInit(AlgorithmParameterSpec params,
63             SecureRandom random) throws InvalidAlgorithmParameterException {
64         if (params instanceof TlsMasterSecretParameterSpec == false) {
65             throw new InvalidAlgorithmParameterException(MSG);
66         }
67         this.spec = (TlsMasterSecretParameterSpec)params;
68         if ("RAW".equals(spec.getPremasterSecret().getFormat()) == false) {
69             throw new InvalidAlgorithmParameterException(
70                 "Key format must be RAW");
71         }
72         protocolVersion = (spec.getMajorVersion() << 8)
73             | spec.getMinorVersion();
74         if ((protocolVersion < 0x0300) || (protocolVersion > 0x0303)) {
75             throw new InvalidAlgorithmParameterException(
76                 "Only SSL 3.0, TLS 1.0/1.1/1.2 supported");
77         }
78     }
79 
engineInit(int keysize, SecureRandom random)80     protected void engineInit(int keysize, SecureRandom random) {
81         throw new InvalidParameterException(MSG);
82     }
83 
engineGenerateKey()84     protected SecretKey engineGenerateKey() {
85         if (spec == null) {
86             throw new IllegalStateException(
87                 "TlsMasterSecretGenerator must be initialized");
88         }
89         SecretKey premasterKey = spec.getPremasterSecret();
90         byte[] premaster = premasterKey.getEncoded();
91 
92         int premasterMajor, premasterMinor;
93         if (premasterKey.getAlgorithm().equals("TlsRsaPremasterSecret")) {
94             // RSA
95             premasterMajor = premaster[0] & 0xff;
96             premasterMinor = premaster[1] & 0xff;
97         } else {
98             // DH, others
99             premasterMajor = -1;
100             premasterMinor = -1;
101         }
102 
103         try {
104             byte[] master;
105             if (protocolVersion >= 0x0301) {
106                 byte[] label;
107                 byte[] seed;
108                 byte[] extendedMasterSecretSessionHash =
109                         spec.getExtendedMasterSecretSessionHash();
110                 if (extendedMasterSecretSessionHash.length != 0) {
111                     label = LABEL_EXTENDED_MASTER_SECRET;
112                     seed = extendedMasterSecretSessionHash;
113                 } else {
114                     byte[] clientRandom = spec.getClientRandom();
115                     byte[] serverRandom = spec.getServerRandom();
116                     label = LABEL_MASTER_SECRET;
117                     seed = concat(clientRandom, serverRandom);
118                 }
119                 master = ((protocolVersion >= 0x0303) ?
120                         doTLS12PRF(premaster, label, seed, 48,
121                                 spec.getPRFHashAlg(), spec.getPRFHashLength(),
122                                 spec.getPRFBlockSize()) :
123                         doTLS10PRF(premaster, label, seed, 48));
124             } else {
125                 master = new byte[48];
126                 MessageDigest md5 = MessageDigest.getInstance("MD5");
127                 MessageDigest sha = MessageDigest.getInstance("SHA");
128 
129                 byte[] clientRandom = spec.getClientRandom();
130                 byte[] serverRandom = spec.getServerRandom();
131                 byte[] tmp = new byte[20];
132                 for (int i = 0; i < 3; i++) {
133                     sha.update(SSL3_CONST[i]);
134                     sha.update(premaster);
135                     sha.update(clientRandom);
136                     sha.update(serverRandom);
137                     sha.digest(tmp, 0, 20);
138 
139                     md5.update(premaster);
140                     md5.update(tmp);
141                     md5.digest(master, i << 4, 16);
142                 }
143 
144             }
145 
146             return new TlsMasterSecretKey(master, premasterMajor,
147                 premasterMinor);
148         } catch (NoSuchAlgorithmException e) {
149             throw new ProviderException(e);
150         } catch (DigestException e) {
151             throw new ProviderException(e);
152         }
153     }
154 
155    @SuppressWarnings("deprecation")
156    private static final class TlsMasterSecretKey implements TlsMasterSecret {
157         private static final long serialVersionUID = 1019571680375368880L;
158 
159         private byte[] key;
160         private final int majorVersion, minorVersion;
161 
TlsMasterSecretKey(byte[] key, int majorVersion, int minorVersion)162         TlsMasterSecretKey(byte[] key, int majorVersion, int minorVersion) {
163             this.key = key;
164             this.majorVersion = majorVersion;
165             this.minorVersion = minorVersion;
166         }
167 
getMajorVersion()168         public int getMajorVersion() {
169             return majorVersion;
170         }
171 
getMinorVersion()172         public int getMinorVersion() {
173             return minorVersion;
174         }
175 
getAlgorithm()176         public String getAlgorithm() {
177             return "TlsMasterSecret";
178         }
179 
getFormat()180         public String getFormat() {
181             return "RAW";
182         }
183 
getEncoded()184         public byte[] getEncoded() {
185             return key.clone();
186         }
187 
188     }
189 }
190 
191