diff --git a/jdk/src/java.base/share/classes/sun/security/jca/JCAUtil.java b/jdk/src/java.base/share/classes/sun/security/jca/JCAUtil.java index 7515a22b40e..59375cc220b 100644 --- a/jdk/src/java.base/share/classes/sun/security/jca/JCAUtil.java +++ b/jdk/src/java.base/share/classes/sun/security/jca/JCAUtil.java @@ -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 @@ public final class JCAUtil { // 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 @@ public final class JCAUtil { 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; } } diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/RSAClientKeyExchange.java b/jdk/src/java.base/share/classes/sun/security/ssl/RSAClientKeyExchange.java index 9d403db3dae..b374b8c42d7 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/RSAClientKeyExchange.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/RSAClientKeyExchange.java @@ -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 @@ final class RSAClientKeyExchange extends HandshakeMessage { } } - 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 @@ final class RSAClientKeyExchange extends HandshakeMessage { 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( diff --git a/jdk/src/java.base/share/classes/sun/security/util/KeyUtil.java b/jdk/src/java.base/share/classes/sun/security/util/KeyUtil.java index 1397f3b05e9..70f5952b077 100644 --- a/jdk/src/java.base/share/classes/sun/security/util/KeyUtil.java +++ b/jdk/src/java.base/share/classes/sun/security/util/KeyUtil.java @@ -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.DHParameterSpec; 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 @@ public final class KeyUtil { byte[] encoded, boolean isFailOver) { if (random == null) { - random = new SecureRandom(); + random = JCAUtil.getSecureRandom(); } byte[] replacer = new byte[48]; random.nextBytes(replacer); diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java index 690d865167e..022dc3be72a 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java @@ -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.*; 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 @@ final class P11Cipher extends CipherSpi { } // generate random IV if (random == null) { - random = new SecureRandom(); + random = JCAUtil.getSecureRandom(); } iv = new byte[blockSize]; random.nextBytes(iv); diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11RSACipher.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11RSACipher.java index bc65e2f2424..58a4e2f545d 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11RSACipher.java +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11RSACipher.java @@ -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 @@ final class P11RSACipher extends CipherSpi { 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"); - } - - byte[] encoded = null; - implUpdate(wrappedKey, 0, wrappedKey.length); try { - encoded = doFinal(); - } catch (BadPaddingException e) { - if (isTlsRsaPremasterSecret) { - failover = e; - } else { + 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 { + 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 @@ final class P11RSACipher extends CipherSpi { } 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 @@ final class P11RSACipher extends CipherSpi { 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; } } diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipher.java b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipher.java index 392ade324d3..af7767924a3 100644 --- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipher.java +++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipher.java @@ -38,6 +38,8 @@ import javax.crypto.*; 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 @@ class NativeCipher extends CipherSpi { 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"); diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeGCMCipher.java b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeGCMCipher.java index 2f9880cd792..10913cb3c06 100644 --- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeGCMCipher.java +++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeGCMCipher.java @@ -36,6 +36,8 @@ import javax.crypto.*; 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 @@ class NativeGCMCipher extends NativeCipher { // 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"); } diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSACipher.java b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSACipher.java index 183c4d0a17a..4b4e408e42d 100644 --- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSACipher.java +++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSACipher.java @@ -63,6 +63,7 @@ import javax.crypto.ShortBufferException; 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 @@ public class NativeRSACipher extends CipherSpi { "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);