diff --git a/src/share/classes/sun/security/jca/JCAUtil.java b/src/share/classes/sun/security/jca/JCAUtil.java index b7bae41ea569b1cfe2fd82a87e3e3b822bf804a6..59e7cbf5730557b8b87c6fb2c453b80641c1f4cf 100644 --- a/src/share/classes/sun/security/jca/JCAUtil.java +++ b/src/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 final static 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/src/share/classes/sun/security/pkcs11/P11Cipher.java b/src/share/classes/sun/security/pkcs11/P11Cipher.java index 6fe59f8da8d1c79d4d7e63b529ccc83a2d2fdf84..3d3f5a17c6571d30e7c8927353545eda1df9a471 100644 --- a/src/share/classes/sun/security/pkcs11/P11Cipher.java +++ b/src/share/classes/sun/security/pkcs11/P11Cipher.java @@ -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/src/share/classes/sun/security/pkcs11/P11RSACipher.java b/src/share/classes/sun/security/pkcs11/P11RSACipher.java index 253b8913a825416cab32ddf948f13dec0684c8b8..f3a16876a59dc0689eb7b4f7810ec894d107387f 100644 --- a/src/share/classes/sun/security/pkcs11/P11RSACipher.java +++ b/src/share/classes/sun/security/pkcs11/P11RSACipher.java @@ -468,49 +468,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; @@ -538,20 +538,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()); } @@ -570,29 +563,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/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java b/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java index aa7df0c9f15037383a51c9224374febe5a8828c1..038cf2a46765a5be12ac3aec5b41a188458522b7 100644 --- a/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java +++ b/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java @@ -111,18 +111,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); @@ -134,18 +139,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/src/share/classes/sun/security/util/KeyUtil.java b/src/share/classes/sun/security/util/KeyUtil.java index 0fb2ed7c85d6f8e66d866151813a6d1ede106875..67a9e459506681c7c76e45b330a0523d7e985d8c 100644 --- a/src/share/classes/sun/security/util/KeyUtil.java +++ b/src/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. */ @@ -200,7 +202,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);