Refactoring of entropy thread to allow faster propagation of interrupt (relates to github
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.prng.EntropySource;
*/
public class DRBG
{
+ private static final Logger LOG = Logger.getLogger(DRBG.class.getName());
+
private static final String PREFIX = DRBG.class.getName();
// {"Provider class name","SecureRandomSpi class name"}
@@ -306,7 +311,7 @@ void addTask(Runnable task)
@Override
public void run()
{
- for (; ; )
+ while (!Thread.currentThread().isInterrupted())
{
Runnable task = tasks.pollFirst();
@@ -364,15 +369,12 @@ private static long getPause()
}
private static void sleep(long ms)
+ throws InterruptedException
{
- try
+ if (ms != 0)
{
Thread.sleep(ms);
}
- catch (InterruptedException e)
- {
- Thread.currentThread().interrupt();
- }
}
private static class URLSeededEntropySourceProvider
@@ -428,11 +430,20 @@ public boolean isPredictionResistant()
}
public byte[] getEntropy()
+ {
+ try
{
return getEntropy(0);
}
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ throw new IllegalStateException("initial entropy fetch interrupted"); // should never happen
+ }
+ }
public byte[] getEntropy(long pause)
+ throws InterruptedException
{
byte[] data = new byte[numBytes];
@@ -469,7 +480,8 @@ public int entropySize()
* @param pause time in milliseconds to pause in build up seed.
* @return the resulting seed
*/
- byte[] getEntropy(long pause);
+ byte[] getEntropy(long pause)
+ throws InterruptedException;
}
private static class HybridEntropySource
@@ -562,11 +574,20 @@ public boolean isPredictionResistant()
}
public byte[] getEntropy()
+ {
+ try
{
return getEntropy(0);
}
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ throw new IllegalStateException("initial entropy fetch interrupted"); // should never happen
+ }
+ }
public byte[] getEntropy(long pause)
+ throws InterruptedException
{
byte[] seed = (byte[])entropy.getAndSet(null);
@@ -608,10 +629,21 @@ public int entropySize()
}
public void run()
+ {
+ try
{
entropy.set(baseRandom.getEntropy(pause));
seedAvailable.set(true);
}
+ catch (InterruptedException e)
+ {
+ if (LOG.isLoggable(Level.FINE))
+ {
+ LOG.fine("entropy thread interrupted - exiting");
+ }
+ Thread.currentThread().interrupt();
+ }
+ }
}
}
}
@@ -653,11 +685,20 @@ public boolean isPredictionResistant()
}
public byte[] getEntropy()
+ {
+ try
{
return getEntropy(0);
}
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ throw new IllegalStateException("initial entropy fetch interrupted"); // should never happen
+ }
+ }
public byte[] getEntropy(long pause)
+ throws InterruptedException
{
byte[] seed = new byte[numBytes];
for (int i = 0; i < numBytes / 8; i++)
