--- a/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java Wed Apr 09 17:19:19 2014 +0800
+++ b/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java Wed Apr 09 12:49:51 2014 +0000
@@ -48,23 +48,6 @@
*/
final class RSAClientKeyExchange extends HandshakeMessage {
- /**
- * The TLS spec says that the version in the RSA premaster secret must
- * be the maximum version supported by the client (i.e. the version it
- * requested in its client hello version). However, we (and other
- * implementations) used to send the active negotiated version. The
- * system property below allows to toggle the behavior.
- */
- private final static String PROP_NAME =
- "com.sun.net.ssl.rsaPreMasterSecretFix";
-
- /*
- * Default is "false" (old behavior) for compatibility reasons in
- * SSLv3/TLSv1. Later protocols (TLSv1.1+) do not use this property.
- */
- private final static boolean rsaPreMasterSecretFix =
- Debug.getBooleanProperty(PROP_NAME, false);
-
/*
* The following field values were encrypted with the server's public
* key (or temp key from server key exchange msg) and are presented
@@ -88,22 +71,12 @@
}
this.protocolVersion = protocolVersion;
- int major, minor;
-
- if (rsaPreMasterSecretFix || maxVersion.v >= ProtocolVersion.TLS11.v) {
- major = maxVersion.major;
- minor = maxVersion.minor;
- } else {
- major = protocolVersion.major;
- minor = protocolVersion.minor;
- }
-
try {
String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ?
"SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
KeyGenerator kg = JsseJce.getKeyGenerator(s);
- kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor),
- generator);
+ kg.init(new TlsRsaPremasterSecretParameterSpec(
+ maxVersion.v, protocolVersion.v), generator);
preMaster = kg.generateKey();
Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
@@ -138,18 +111,17 @@
}
}
- Exception failover = null;
- byte[] encoded = null;
try {
Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
// Cannot generate key here, please don't use Cipher.UNWRAP_MODE!
- cipher.init(Cipher.DECRYPT_MODE, privateKey);
- encoded = cipher.doFinal(encrypted);
- } catch (BadPaddingException bpe) {
- failover = bpe;
- encoded = null;
- } catch (IllegalBlockSizeException ibse) {
- // the message it too big to process with RSA
+ cipher.init(Cipher.UNWRAP_MODE, privateKey,
+ new TlsRsaPremasterSecretParameterSpec(
+ maxVersion.v, currentVersion.v),
+ generator);
+ preMaster = (SecretKey)cipher.unwrap(encrypted,
+ "TlsRsaPremasterSecret", Cipher.SECRET_KEY);
+ } catch (InvalidKeyException ibk) {
+ // the message is too big to process with RSA
throw new SSLProtocolException(
"Unable to process PreMasterSecret, may be too big");
} catch (Exception e) {
@@ -160,124 +132,6 @@
}
throw new RuntimeException("Could not generate dummy secret", e);
}
-
- // polish the premaster secret
- preMaster = polishPreMasterSecretKey(
- currentVersion, maxVersion, generator, encoded, failover);
- }
-
- /**
- * To avoid vulnerabilities described by section 7.4.7.1, RFC 5246,
- * treating incorrectly formatted message blocks and/or mismatched
- * version numbers in a manner indistinguishable from correctly
- * formatted RSA blocks.
- *
- * RFC 5246 describes the approach as :
- *
- * 1. Generate a string R of 48 random bytes
- *
- * 2. Decrypt the message to recover the plaintext M
- *
- * 3. If the PKCS#1 padding is not correct, or the length of message
- * M is not exactly 48 bytes:
- * pre_master_secret = R
- * else If ClientHello.client_version <= TLS 1.0, and version
- * number check is explicitly disabled:
- * premaster secret = M
- * else If M[0..1] != ClientHello.client_version:
- * premaster secret = R
- * else:
- * premaster secret = M
- *
- * Note that #2 has completed before the call of this method.
- */
- private SecretKey polishPreMasterSecretKey(ProtocolVersion currentVersion,
- ProtocolVersion clientHelloVersion, SecureRandom generator,
- byte[] encoded, Exception failoverException) {
-
- this.protocolVersion = clientHelloVersion;
- if (generator == null) {
- generator = new SecureRandom();
- }
- byte[] random = new byte[48];
- generator.nextBytes(random);
-
- if (failoverException == null && encoded != null) {
- // check the length
- if (encoded.length != 48) {
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println(
- "incorrect length of premaster secret: " +
- encoded.length);
- }
-
- return generatePreMasterSecret(
- clientHelloVersion, random, generator);
- }
-
- if (clientHelloVersion.major != encoded[0] ||
- clientHelloVersion.minor != encoded[1]) {
-
- if (clientHelloVersion.v <= ProtocolVersion.TLS10.v &&
- currentVersion.major == encoded[0] &&
- currentVersion.minor == encoded[1]) {
- /*
- * For compatibility, we maintain the behavior that the
- * version in pre_master_secret can be the negotiated
- * version for TLS v1.0 and SSL v3.0.
- */
- this.protocolVersion = currentVersion;
- } else {
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println("Mismatching Protocol Versions, " +
- "ClientHello.client_version is " +
- clientHelloVersion +
- ", while PreMasterSecret.client_version is " +
- ProtocolVersion.valueOf(encoded[0], encoded[1]));
- }
-
- encoded = random;
- }
- }
-
- return generatePreMasterSecret(
- clientHelloVersion, encoded, generator);
- }
-
- if (debug != null && Debug.isOn("handshake") &&
- failoverException != null) {
- System.out.println("Error decrypting premaster secret:");
- failoverException.printStackTrace(System.out);
- }
-
- return generatePreMasterSecret(clientHelloVersion, random, generator);
- }
-
- // generate a premaster secret with the specified version number
- private static SecretKey generatePreMasterSecret(
- ProtocolVersion version, byte[] encodedSecret,
- SecureRandom generator) {
-
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println("Generating a random fake premaster secret");
- }
-
- try {
- String s = ((version.v >= ProtocolVersion.TLS12.v) ?
- "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
- KeyGenerator kg = JsseJce.getKeyGenerator(s);
- kg.init(new TlsRsaPremasterSecretParameterSpec(
- version.major, version.minor, encodedSecret), generator);
- return kg.generateKey();
- } catch (InvalidAlgorithmParameterException |
- NoSuchAlgorithmException iae) {
- // unlikely to happen, otherwise, must be a provider exception
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println("RSA premaster secret generation error:");
- iae.printStackTrace(System.out);
- }
- throw new RuntimeException("Could not generate dummy secret", iae);
- }
}
@Override