8134605: Partial rework of the fix for 8081297
Reviewed-by: xuelei, coffeys, valeriep
--- 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);