1 /* 2 * Copyright (c) 1996, 2012, 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 27 package sun.security.ssl; 28 29 import java.io.*; 30 import java.security.*; 31 import java.security.interfaces.*; 32 33 import javax.crypto.*; 34 import javax.crypto.spec.*; 35 36 import javax.net.ssl.*; 37 38 import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; 39 import sun.security.util.KeyUtil; 40 41 /** 42 * This is the client key exchange message (CLIENT --> SERVER) used with 43 * all RSA key exchanges; it holds the RSA-encrypted pre-master secret. 44 * 45 * The message is encrypted using PKCS #1 block type 02 encryption with the 46 * server's public key. The padding and resulting message size is a function 47 * of this server's public key modulus size, but the pre-master secret is 48 * always exactly 48 bytes. 49 * 50 */ 51 final class RSAClientKeyExchange extends HandshakeMessage { 52 53 /** 54 * The TLS spec says that the version in the RSA premaster secret must 55 * be the maximum version supported by the client (i.e. the version it 56 * requested in its client hello version). However, we (and other 57 * implementations) used to send the active negotiated version. The 58 * system property below allows to toggle the behavior. 59 */ 60 private final static String PROP_NAME = 61 "com.sun.net.ssl.rsaPreMasterSecretFix"; 62 63 /* 64 * Default is "false" (old behavior) for compatibility reasons in 65 * SSLv3/TLSv1. Later protocols (TLSv1.1+) do not use this property. 66 */ 67 private final static boolean rsaPreMasterSecretFix = 68 Debug.getBooleanProperty(PROP_NAME, false); 69 70 /* 71 * The following field values were encrypted with the server's public 72 * key (or temp key from server key exchange msg) and are presented 73 * here in DECRYPTED form. 74 */ 75 private ProtocolVersion protocolVersion; // preMaster [0,1] 76 SecretKey preMaster; 77 private byte[] encrypted; // same size as public modulus 78 79 /* 80 * Client randomly creates a pre-master secret and encrypts it 81 * using the server's RSA public key; only the server can decrypt 82 * it, using its RSA private key. Result is the same size as the 83 * server's public key, and uses PKCS #1 block format 02. 84 */ RSAClientKeyExchange(ProtocolVersion protocolVersion, ProtocolVersion maxVersion, SecureRandom generator, PublicKey publicKey)85 RSAClientKeyExchange(ProtocolVersion protocolVersion, 86 ProtocolVersion maxVersion, 87 SecureRandom generator, PublicKey publicKey) throws IOException { 88 if (publicKey.getAlgorithm().equals("RSA") == false) { 89 throw new SSLKeyException("Public key not of type RSA"); 90 } 91 this.protocolVersion = protocolVersion; 92 93 int major, minor; 94 95 if (rsaPreMasterSecretFix || maxVersion.v >= ProtocolVersion.TLS11.v) { 96 major = maxVersion.major; 97 minor = maxVersion.minor; 98 } else { 99 major = protocolVersion.major; 100 minor = protocolVersion.minor; 101 } 102 103 try { 104 String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ? 105 "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret"); 106 KeyGenerator kg = JsseJce.getKeyGenerator(s); 107 kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor), 108 generator); 109 preMaster = kg.generateKey(); 110 111 Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); 112 cipher.init(Cipher.WRAP_MODE, publicKey, generator); 113 encrypted = cipher.wrap(preMaster); 114 } catch (GeneralSecurityException e) { 115 throw (SSLKeyException)new SSLKeyException 116 ("RSA premaster secret error").initCause(e); 117 } 118 } 119 120 /* 121 * Server gets the PKCS #1 (block format 02) data, decrypts 122 * it with its private key. 123 */ RSAClientKeyExchange(ProtocolVersion currentVersion, ProtocolVersion maxVersion, SecureRandom generator, HandshakeInStream input, int messageSize, PrivateKey privateKey)124 RSAClientKeyExchange(ProtocolVersion currentVersion, 125 ProtocolVersion maxVersion, 126 SecureRandom generator, HandshakeInStream input, 127 int messageSize, PrivateKey privateKey) throws IOException { 128 129 if (privateKey.getAlgorithm().equals("RSA") == false) { 130 throw new SSLKeyException("Private key not of type RSA"); 131 } 132 133 if (currentVersion.v >= ProtocolVersion.TLS10.v) { 134 encrypted = input.getBytes16(); 135 } else { 136 encrypted = new byte [messageSize]; 137 if (input.read(encrypted) != messageSize) { 138 throw new SSLProtocolException 139 ("SSL: read PreMasterSecret: short read"); 140 } 141 } 142 143 try { 144 Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); 145 cipher.init(Cipher.UNWRAP_MODE, privateKey); 146 preMaster = (SecretKey)cipher.unwrap(encrypted, 147 "TlsRsaPremasterSecret", Cipher.SECRET_KEY); 148 149 // polish the premaster secret 150 preMaster = polishPreMasterSecretKey(currentVersion, maxVersion, 151 generator, preMaster, null); 152 } catch (Exception e) { 153 // polish the premaster secret 154 preMaster = 155 polishPreMasterSecretKey(currentVersion, maxVersion, 156 generator, null, e); 157 } 158 } 159 160 /** 161 * To avoid vulnerabilities described by section 7.4.7.1, RFC 5246, 162 * treating incorrectly formatted message blocks and/or mismatched 163 * version numbers in a manner indistinguishable from correctly 164 * formatted RSA blocks. 165 * 166 * RFC 5246 describes the approach as : 167 * 168 * 1. Generate a string R of 46 random bytes 169 * 170 * 2. Decrypt the message to recover the plaintext M 171 * 172 * 3. If the PKCS#1 padding is not correct, or the length of message 173 * M is not exactly 48 bytes: 174 * pre_master_secret = ClientHello.client_version || R 175 * else If ClientHello.client_version <= TLS 1.0, and version 176 * number check is explicitly disabled: 177 * pre_master_secret = M 178 * else: 179 * pre_master_secret = ClientHello.client_version || M[2..47] 180 */ polishPreMasterSecretKey(ProtocolVersion currentVersion, ProtocolVersion clientHelloVersion, SecureRandom generator, SecretKey secretKey, Exception failoverException)181 private SecretKey polishPreMasterSecretKey(ProtocolVersion currentVersion, 182 ProtocolVersion clientHelloVersion, SecureRandom generator, 183 SecretKey secretKey, Exception failoverException) { 184 185 this.protocolVersion = clientHelloVersion; 186 187 if (failoverException == null && secretKey != null) { 188 // check the length 189 byte[] encoded = secretKey.getEncoded(); 190 if (encoded == null) { // unable to get the encoded key 191 if (debug != null && Debug.isOn("handshake")) { 192 System.out.println( 193 "unable to get the plaintext of the premaster secret"); 194 } 195 196 int keySize = KeyUtil.getKeySize(secretKey); 197 if (keySize > 0 && keySize != 384) { // 384 = 48 * 8 198 if (debug != null && Debug.isOn("handshake")) { 199 System.out.println( 200 "incorrect length of premaster secret: " + 201 (keySize/8)); 202 } 203 204 return generateDummySecret(clientHelloVersion); 205 } 206 207 // The key size is exactly 48 bytes or not accessible. 208 // 209 // Conservatively, pass the checking to master secret 210 // calculation. 211 return secretKey; 212 } else if (encoded.length == 48) { 213 // check the version 214 if (clientHelloVersion.major == encoded[0] && 215 clientHelloVersion.minor == encoded[1]) { 216 217 return secretKey; 218 } else if (clientHelloVersion.v <= ProtocolVersion.TLS10.v && 219 currentVersion.major == encoded[0] && 220 currentVersion.minor == encoded[1]) { 221 /* 222 * For compatibility, we maintain the behavior that the 223 * version in pre_master_secret can be the negotiated 224 * version for TLS v1.0 and SSL v3.0. 225 */ 226 this.protocolVersion = currentVersion; 227 return secretKey; 228 } 229 230 if (debug != null && Debug.isOn("handshake")) { 231 System.out.println("Mismatching Protocol Versions, " + 232 "ClientHello.client_version is " + clientHelloVersion + 233 ", while PreMasterSecret.client_version is " + 234 ProtocolVersion.valueOf(encoded[0], encoded[1])); 235 } 236 237 return generateDummySecret(clientHelloVersion); 238 } else { 239 if (debug != null && Debug.isOn("handshake")) { 240 System.out.println( 241 "incorrect length of premaster secret: " + 242 encoded.length); 243 } 244 245 return generateDummySecret(clientHelloVersion); 246 } 247 } 248 249 if (debug != null && Debug.isOn("handshake") && 250 failoverException != null) { 251 System.out.println("Error decrypting premaster secret:"); 252 failoverException.printStackTrace(System.out); 253 } 254 255 return generateDummySecret(clientHelloVersion); 256 } 257 258 // generate a premaster secret with the specified version number generateDummySecret(ProtocolVersion version)259 static SecretKey generateDummySecret(ProtocolVersion version) { 260 if (debug != null && Debug.isOn("handshake")) { 261 System.out.println("Generating a random fake premaster secret"); 262 } 263 264 try { 265 String s = ((version.v >= ProtocolVersion.TLS12.v) ? 266 "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret"); 267 KeyGenerator kg = JsseJce.getKeyGenerator(s); 268 kg.init(new TlsRsaPremasterSecretParameterSpec 269 (version.major, version.minor)); 270 return kg.generateKey(); 271 } catch (GeneralSecurityException e) { 272 throw new RuntimeException("Could not generate dummy secret", e); 273 } 274 } 275 276 @Override messageType()277 int messageType() { 278 return ht_client_key_exchange; 279 } 280 281 @Override messageLength()282 int messageLength() { 283 if (protocolVersion.v >= ProtocolVersion.TLS10.v) { 284 return encrypted.length + 2; 285 } else { 286 return encrypted.length; 287 } 288 } 289 290 @Override send(HandshakeOutStream s)291 void send(HandshakeOutStream s) throws IOException { 292 if (protocolVersion.v >= ProtocolVersion.TLS10.v) { 293 s.putBytes16(encrypted); 294 } else { 295 s.write(encrypted); 296 } 297 } 298 299 @Override print(PrintStream s)300 void print(PrintStream s) throws IOException { 301 s.println("*** ClientKeyExchange, RSA PreMasterSecret, " + 302 protocolVersion); 303 } 304 } 305