diff --git a/src/share/classes/java/security/SecureRandom.java b/src/share/classes/java/security/SecureRandom.java index 3481e21789319bbfa51817ba49e569b8453c9b80..6848be5a2d215b1bbaae1659029b10a85db31d48 100644 --- a/src/share/classes/java/security/SecureRandom.java +++ b/src/share/classes/java/security/SecureRandom.java @@ -464,7 +464,7 @@ public class SecureRandom extends java.util.Random { * @param bytes the array to be filled in with random bytes. */ @Override - synchronized public void nextBytes(byte[] bytes) { + public void nextBytes(byte[] bytes) { secureRandomSpi.engineNextBytes(bytes); } diff --git a/src/share/lib/security/sunpkcs11-solaris.cfg b/src/share/lib/security/sunpkcs11-solaris.cfg index 4cade8e48ea54d6a5ace6cf48c8d88cc75b3268d..29aae460e5ad87a0fe94d5223675ef32ad8b03f3 100644 --- a/src/share/lib/security/sunpkcs11-solaris.cfg +++ b/src/share/lib/security/sunpkcs11-solaris.cfg @@ -18,6 +18,7 @@ attributes = compatibility disabledMechanisms = { CKM_DSA_KEY_PAIR_GEN + SecureRandom # the following mechanisms are disabled due to performance issues # (Solaris bug 6337157) CKM_DSA_SHA1 diff --git a/src/solaris/classes/sun/security/provider/NativePRNG.java b/src/solaris/classes/sun/security/provider/NativePRNG.java index 1d275f086cbc653b7e25301a3abe8bad6072f9e7..bbb48c4593ebee6ed0b169e357900ec071f3add9 100644 --- a/src/solaris/classes/sun/security/provider/NativePRNG.java +++ b/src/solaris/classes/sun/security/provider/NativePRNG.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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 @@ -28,6 +28,8 @@ package sun.security.provider; import java.io.*; import java.net.*; import java.security.*; +import java.util.Arrays; + import sun.security.util.Debug; /** @@ -334,7 +336,9 @@ public final class NativePRNG extends SecureRandomSpi { private final static long MAX_BUFFER_TIME = 100; // size of the "next" buffer - private final static int BUFFER_SIZE = 32; + private static final int MAX_BUFFER_SIZE = 65536; + private static final int MIN_BUFFER_SIZE = 32; + private int bufferSize = 256; // Holder for the seedFile. Used if we ever add seed material. File seedFile; @@ -351,7 +355,7 @@ public final class NativePRNG extends SecureRandomSpi { private volatile sun.security.provider.SecureRandom mixRandom; // buffer for next bits - private final byte[] nextBuffer; + private byte[] nextBuffer; // number of bytes left in nextBuffer private int buffered; @@ -359,6 +363,16 @@ public final class NativePRNG extends SecureRandomSpi { // time we read the data into the nextBuffer private long lastRead; + // Count for the number of buffer size changes requests + // Positive value in increase size, negative to lower it. + private int change_buffer = 0; + + // Request limit to trigger an increase in nextBuffer size + private static final int REQ_LIMIT_INC = 1000; + + // Request limit to trigger a decrease in nextBuffer size + private static final int REQ_LIMIT_DEC = -100; + // mutex lock for nextBytes() private final Object LOCK_GET_BYTES = new Object(); @@ -373,7 +387,7 @@ public final class NativePRNG extends SecureRandomSpi { this.seedFile = seedFile; seedIn = new FileInputStream(seedFile); nextIn = new FileInputStream(nextFile); - nextBuffer = new byte[BUFFER_SIZE]; + nextBuffer = new byte[bufferSize]; } // get the SHA1PRNG for mixing @@ -466,9 +480,47 @@ public final class NativePRNG extends SecureRandomSpi { // if not, read new bytes private void ensureBufferValid() throws IOException { long time = System.currentTimeMillis(); - if ((buffered > 0) && (time - lastRead < MAX_BUFFER_TIME)) { - return; + int new_buffer_size = 0; + + // Check if buffer has bytes available that are not too old + if (buffered > 0) { + if (time - lastRead < MAX_BUFFER_TIME) { + return; + } else { + // byte is old, so subtract from counter to shrink buffer + change_buffer--; + } + } else { + // No bytes available, so add to count to increase buffer + change_buffer++; } + + // If counter has it a limit, increase or decrease size + if (change_buffer > REQ_LIMIT_INC) { + new_buffer_size = nextBuffer.length * 2; + } else if (change_buffer < REQ_LIMIT_DEC) { + new_buffer_size = nextBuffer.length / 2; + } + + // If buffer size is to be changed, replace nextBuffer. + if (new_buffer_size > 0) { + if (new_buffer_size <= MAX_BUFFER_SIZE && + new_buffer_size >= MIN_BUFFER_SIZE) { + nextBuffer = new byte[new_buffer_size]; + if (debug != null) { + debug.println("Buffer size changed to " + + new_buffer_size); + } + } else { + if (debug != null) { + debug.println("Buffer reached limit: " + + nextBuffer.length); + } + } + change_buffer = 0; + } + + // Load fresh random bytes into nextBuffer lastRead = time; readFully(nextIn, nextBuffer); buffered = nextBuffer.length; @@ -478,24 +530,40 @@ public final class NativePRNG extends SecureRandomSpi { // read from "next" and XOR with bytes generated by the // mixing SHA1PRNG private void implNextBytes(byte[] data) { - synchronized (LOCK_GET_BYTES) { try { getMixRandom().engineNextBytes(data); - int len = data.length; + int data_len = data.length; int ofs = 0; - while (len > 0) { - ensureBufferValid(); - int bufferOfs = nextBuffer.length - buffered; - while ((len > 0) && (buffered > 0)) { - data[ofs++] ^= nextBuffer[bufferOfs++]; - len--; - buffered--; + int len; + int buf_pos; + int localofs; + byte[] localBuffer; + + while (data_len > 0) { + synchronized (LOCK_GET_BYTES) { + ensureBufferValid(); + buf_pos = nextBuffer.length - buffered; + if (data_len > buffered) { + len = buffered; + buffered = 0; + } else { + len = data_len; + buffered -= len; + } + localBuffer = Arrays.copyOfRange(nextBuffer, buf_pos, + buf_pos + len); } + localofs = 0; + while (len > localofs) { + data[ofs] ^= localBuffer[localofs]; + ofs++; + localofs++; + } + data_len -= len; } - } catch (IOException e) { + } catch (IOException e){ throw new ProviderException("nextBytes() failed", e); } - } } - } + } } diff --git a/test/java/security/SecureRandom/DefaultProvider.java b/test/java/security/SecureRandom/DefaultProvider.java index 50b4719acc620a22d549e5983fd89ce8c9bf74ec..597f2352a4ba1c6068dc150dd3daa3e9b5f8864b 100644 --- a/test/java/security/SecureRandom/DefaultProvider.java +++ b/test/java/security/SecureRandom/DefaultProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -43,12 +43,7 @@ public class DefaultProvider { out.println("TEST: Default provider with constructor"); SecureRandom secureRandom = new SecureRandom(); String provider = secureRandom.getProvider().getName(); - if (OS_NAME.startsWith(SUNOS)) { - if (!provider.startsWith("SunPKCS11-")) { - throw new RuntimeException("Unexpected provider name: " - + provider); - } - } else if (!provider.equals("SUN")) { + if (!provider.equals("SUN")) { throw new RuntimeException("Unexpected provider name: " + provider); } @@ -77,16 +72,6 @@ public class DefaultProvider { instance = SecureRandom.getInstance(algorithm); assertInstance(instance, algorithm, provider); out.println("Passed."); - - if (OS_NAME.startsWith(SUNOS)) { - out.println( - "TEST: PKCS11 is supported on Solaris by SunPKCS11 provider"); - algorithm = "PKCS11"; - provider = "SunPKCS11-Solaris"; - instance = SecureRandom.getInstance(algorithm); - assertInstance(instance, algorithm, provider); - out.println("Passed."); - } } private static void assertInstance(SecureRandom instance,