jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java
changeset 23733 b9b80421cfa7
parent 22309 1990211a42e5
child 24194 45f278eb1b37
--- 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