8134605: Partial rework of the fix for 8081297
authorigerasim
Fri, 02 Oct 2015 11:50:20 +0300
changeset 35287 e59d934ce2ba
parent 35286 6dc8e176c81e
child 35288 d4d492397105
8134605: Partial rework of the fix for 8081297 Reviewed-by: xuelei, coffeys, valeriep
jdk/src/java.base/share/classes/sun/security/jca/JCAUtil.java
jdk/src/java.base/share/classes/sun/security/ssl/RSAClientKeyExchange.java
jdk/src/java.base/share/classes/sun/security/util/KeyUtil.java
jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java
jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11RSACipher.java
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipher.java
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeGCMCipher.java
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSACipher.java
--- a/jdk/src/java.base/share/classes/sun/security/jca/JCAUtil.java	Tue Oct 13 20:59:19 2015 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/jca/JCAUtil.java	Fri Oct 02 11:50:20 2015 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,12 +41,6 @@
         // no instantiation
     }
 
-    // lock to use for synchronization
-    private static final Object LOCK = JCAUtil.class;
-
-    // cached SecureRandom instance
-    private static volatile SecureRandom secureRandom;
-
     // size of the temporary arrays we use. Should fit into the CPU's 1st
     // level cache and could be adjusted based on the platform
     private static final int ARRAY_SIZE = 4096;
@@ -60,26 +54,19 @@
         return Math.min(ARRAY_SIZE, totalSize);
     }
 
+    // cached SecureRandom instance
+    private static class CachedSecureRandomHolder {
+        public static SecureRandom instance = new SecureRandom();
+    }
+
     /**
-     * Get a SecureRandom instance. This method should me used by JDK
+     * Get a SecureRandom instance. This method should be used by JDK
      * internal code in favor of calling "new SecureRandom()". That needs to
      * iterate through the provider table to find the default SecureRandom
      * implementation, which is fairly inefficient.
      */
     public static SecureRandom getSecureRandom() {
-        // we use double checked locking to minimize synchronization
-        // works because we use a volatile reference
-        SecureRandom r = secureRandom;
-        if (r == null) {
-            synchronized (LOCK) {
-                r = secureRandom;
-                if (r == null) {
-                    r = new SecureRandom();
-                    secureRandom = r;
-                }
-            }
-        }
-        return r;
+        return CachedSecureRandomHolder.instance;
     }
 
 }
--- a/jdk/src/java.base/share/classes/sun/security/ssl/RSAClientKeyExchange.java	Tue Oct 13 20:59:19 2015 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/RSAClientKeyExchange.java	Fri Oct 02 11:50:20 2015 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -113,18 +113,23 @@
             }
         }
 
-        boolean needFailover = false;
         byte[] encoded = null;
         try {
             Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
-            needFailover = !KeyUtil.isOracleJCEProvider(
-                                        cipher.getProvider().getName());
+            boolean needFailover = !KeyUtil.isOracleJCEProvider(
+                    cipher.getProvider().getName());
             if (needFailover) {
                 cipher.init(Cipher.DECRYPT_MODE, privateKey);
-                encoded = cipher.doFinal(encrypted);
+                boolean failed = false;
+                try {
+                    encoded = cipher.doFinal(encrypted);
+                } catch (BadPaddingException bpe) {
+                    // Note: encoded == null
+                    failed = true;
+                }
                 encoded = KeyUtil.checkTlsPreMasterSecretKey(
                                 maxVersion.v, currentVersion.v,
-                                generator, encoded, false);
+                                generator, encoded, failed);
                 preMaster = generatePreMasterSecret(
                                 maxVersion.v, currentVersion.v,
                                 encoded, generator);
@@ -136,18 +141,6 @@
                 preMaster = (SecretKey)cipher.unwrap(encrypted,
                         "TlsRsaPremasterSecret", Cipher.SECRET_KEY);
             }
-        } catch (BadPaddingException bpe) {
-            if (needFailover) {
-                encoded = KeyUtil.checkTlsPreMasterSecretKey(
-                                maxVersion.v, currentVersion.v,
-                                generator, null, false);
-                preMaster = generatePreMasterSecret(
-                                maxVersion.v, currentVersion.v,
-                                encoded, generator);
-            } else {
-                //  Otherwise, unlikely to happen
-                throw new RuntimeException("Unexpected exception", bpe);
-            }
         } catch (InvalidKeyException ibk) {
             // the message is too big to process with RSA
             throw new SSLProtocolException(
--- a/jdk/src/java.base/share/classes/sun/security/util/KeyUtil.java	Tue Oct 13 20:59:19 2015 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/util/KeyUtil.java	Fri Oct 02 11:50:20 2015 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,6 +41,8 @@
 import javax.crypto.spec.DHPublicKeySpec;
 import java.math.BigInteger;
 
+import sun.security.jca.JCAUtil;
+
 /**
  * A utility class to get key length, valiate keys, etc.
  */
@@ -201,7 +203,7 @@
             byte[] encoded, boolean isFailOver) {
 
         if (random == null) {
-            random = new SecureRandom();
+            random = JCAUtil.getSecureRandom();
         }
         byte[] replacer = new byte[48];
         random.nextBytes(replacer);
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java	Tue Oct 13 20:59:19 2015 +0300
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java	Fri Oct 02 11:50:20 2015 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@
 import javax.crypto.spec.*;
 
 import sun.nio.ch.DirectBuffer;
+import sun.security.jca.JCAUtil;
 import sun.security.pkcs11.wrapper.*;
 import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
 
@@ -379,7 +380,7 @@
                 }
                 // generate random IV
                 if (random == null) {
-                    random = new SecureRandom();
+                    random = JCAUtil.getSecureRandom();
                 }
                 iv = new byte[blockSize];
                 random.nextBytes(iv);
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11RSACipher.java	Tue Oct 13 20:59:19 2015 +0300
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11RSACipher.java	Fri Oct 02 11:50:20 2015 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -470,49 +470,49 @@
                 algorithm.equals("TlsRsaPremasterSecret");
         Exception failover = null;
 
-        SecureRandom secureRandom = random;
-        if (secureRandom == null && isTlsRsaPremasterSecret) {
-            secureRandom = new SecureRandom();
-        }
-
         // Should C_Unwrap be preferred for non-TLS RSA premaster secret?
         if (token.supportsRawSecretKeyImport()) {
             // XXX implement unwrap using C_Unwrap() for all keys
             implInit(Cipher.DECRYPT_MODE, p11Key);
-            if (wrappedKey.length > maxInputSize) {
-                throw new InvalidKeyException("Key is too long for unwrapping");
-            }
+            try {
+                if (wrappedKey.length > maxInputSize) {
+                    throw new InvalidKeyException("Key is too long for unwrapping");
+                }
 
-            byte[] encoded = null;
-            implUpdate(wrappedKey, 0, wrappedKey.length);
-            try {
-                encoded = doFinal();
-            } catch (BadPaddingException e) {
-                if (isTlsRsaPremasterSecret) {
-                    failover = e;
-                } else {
+                byte[] encoded = null;
+                implUpdate(wrappedKey, 0, wrappedKey.length);
+                try {
+                    encoded = doFinal();
+                } catch (BadPaddingException e) {
+                    if (isTlsRsaPremasterSecret) {
+                        failover = e;
+                    } else {
+                        throw new InvalidKeyException("Unwrapping failed", e);
+                    }
+                } catch (IllegalBlockSizeException e) {
+                    // should not occur, handled with length check above
                     throw new InvalidKeyException("Unwrapping failed", e);
                 }
-            } catch (IllegalBlockSizeException e) {
-                // should not occur, handled with length check above
-                throw new InvalidKeyException("Unwrapping failed", e);
-            }
+
+                if (isTlsRsaPremasterSecret) {
+                    if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
+                        throw new IllegalStateException(
+                                "No TlsRsaPremasterSecretParameterSpec specified");
+                    }
 
-            if (isTlsRsaPremasterSecret) {
-                if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
-                    throw new IllegalStateException(
-                            "No TlsRsaPremasterSecretParameterSpec specified");
+                    // polish the TLS premaster secret
+                    TlsRsaPremasterSecretParameterSpec psps =
+                            (TlsRsaPremasterSecretParameterSpec)spec;
+                    encoded = KeyUtil.checkTlsPreMasterSecretKey(
+                            psps.getClientVersion(), psps.getServerVersion(),
+                            random, encoded, (failover != null));
                 }
 
-                // polish the TLS premaster secret
-                TlsRsaPremasterSecretParameterSpec psps =
-                        (TlsRsaPremasterSecretParameterSpec)spec;
-                encoded = KeyUtil.checkTlsPreMasterSecretKey(
-                        psps.getClientVersion(), psps.getServerVersion(),
-                        secureRandom, encoded, (failover != null));
+                return ConstructKeys.constructKey(encoded, algorithm, type);
+            } finally {
+                // Restore original mode
+                implInit(Cipher.UNWRAP_MODE, p11Key);
             }
-
-            return ConstructKeys.constructKey(encoded, algorithm, type);
         } else {
             Session s = null;
             SecretKey secretKey = null;
@@ -540,20 +540,13 @@
                 }
 
                 if (isTlsRsaPremasterSecret) {
-                    byte[] replacer = new byte[48];
-                    if (failover == null) {
-                        // Does smart compiler dispose this operation?
-                        secureRandom.nextBytes(replacer);
-                    }
-
                     TlsRsaPremasterSecretParameterSpec psps =
                             (TlsRsaPremasterSecretParameterSpec)spec;
 
-                    // Please use the tricky failover and replacer byte array
-                    // as the parameters so that smart compiler won't dispose
-                    // the unused variable .
+                    // Please use the tricky failover as the parameter so that
+                    // smart compiler won't dispose the unused variable.
                     secretKey = polishPreMasterSecretKey(token, s,
-                            failover, replacer, secretKey,
+                            failover, secretKey,
                             psps.getClientVersion(), psps.getServerVersion());
                 }
 
@@ -572,29 +565,27 @@
 
     private static SecretKey polishPreMasterSecretKey(
             Token token, Session session,
-            Exception failover, byte[] replacer, SecretKey secretKey,
+            Exception failover, SecretKey unwrappedKey,
             int clientVersion, int serverVersion) {
 
-        if (failover != null) {
-            CK_VERSION version = new CK_VERSION(
-                    (clientVersion >>> 8) & 0xFF, clientVersion & 0xFF);
-            try {
-                CK_ATTRIBUTE[] attributes = token.getAttributes(
-                        O_GENERATE, CKO_SECRET_KEY,
-                        CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]);
-                long keyID = token.p11.C_GenerateKey(session.id(),
-                    // new CK_MECHANISM(CKM_TLS_PRE_MASTER_KEY_GEN, version),
-                        new CK_MECHANISM(CKM_SSL3_PRE_MASTER_KEY_GEN, version),
-                        attributes);
-                return P11Key.secretKey(session,
-                        keyID, "TlsRsaPremasterSecret", 48 << 3, attributes);
-            } catch (PKCS11Exception e) {
-                throw new ProviderException(
-                        "Could not generate premaster secret", e);
-            }
+        SecretKey newKey;
+        CK_VERSION version = new CK_VERSION(
+                (clientVersion >>> 8) & 0xFF, clientVersion & 0xFF);
+        try {
+            CK_ATTRIBUTE[] attributes = token.getAttributes(
+                    O_GENERATE, CKO_SECRET_KEY,
+                    CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]);
+            long keyID = token.p11.C_GenerateKey(session.id(),
+                    new CK_MECHANISM(CKM_SSL3_PRE_MASTER_KEY_GEN, version),
+                    attributes);
+            newKey = P11Key.secretKey(session,
+                    keyID, "TlsRsaPremasterSecret", 48 << 3, attributes);
+        } catch (PKCS11Exception e) {
+            throw new ProviderException(
+                    "Could not generate premaster secret", e);
         }
 
-        return secretKey;
+        return (failover == null) ? unwrappedKey : newKey;
     }
 
 }
--- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipher.java	Tue Oct 13 20:59:19 2015 +0300
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipher.java	Fri Oct 02 11:50:20 2015 +0300
@@ -38,6 +38,8 @@
 import javax.crypto.spec.SecretKeySpec;
 import javax.crypto.spec.IvParameterSpec;
 
+import sun.security.jca.JCAUtil;
+
 /**
  * Cipher wrapper class utilizing ucrypto APIs. This class currently supports
  * - AES/ECB/NOPADDING
@@ -288,7 +290,10 @@
                 if (encrypt) {
                     // generate IV if none supplied for encryption
                     ivBytes = new byte[blockSize];
-                    new SecureRandom().nextBytes(ivBytes);
+                    if (random == null) {
+                        random = JCAUtil.getSecureRandom();
+                    }
+                    random.nextBytes(ivBytes);
                 } else {
                     throw new InvalidAlgorithmParameterException
                             ("Parameters required for decryption");
--- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeGCMCipher.java	Tue Oct 13 20:59:19 2015 +0300
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeGCMCipher.java	Fri Oct 02 11:50:20 2015 +0300
@@ -36,6 +36,8 @@
 import javax.crypto.spec.SecretKeySpec;
 import javax.crypto.spec.GCMParameterSpec;
 
+import sun.security.jca.JCAUtil;
+
 /**
  * Cipher wrapper class utilizing ucrypto APIs. This class currently supports
  * - AES/GCM/NoPADDING
@@ -200,7 +202,10 @@
 
                 // generate IV if none supplied for encryption
                 ivBytes = new byte[blockSize];
-                new SecureRandom().nextBytes(ivBytes);
+                if (random == null) {
+                    random = JCAUtil.getSecureRandom();
+                }
+                random.nextBytes(ivBytes);
             } else {
                 throw new InvalidAlgorithmParameterException("Parameters required for decryption");
             }
--- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSACipher.java	Tue Oct 13 20:59:19 2015 +0300
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSACipher.java	Fri Oct 02 11:50:20 2015 +0300
@@ -63,6 +63,7 @@
 import javax.crypto.spec.SecretKeySpec;
 
 import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
+import sun.security.jca.JCAUtil;
 import sun.security.util.KeyUtil;
 
 /**
@@ -201,6 +202,9 @@
                         "No Parameters can be specified");
             }
             spec = params;
+            if (random == null) {
+                random = JCAUtil.getSecureRandom();
+            }
             this.random = random;   // for TLS RSA premaster secret
         }
         boolean doEncrypt = (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE);