RSA key generations have failed on rare occasions in various testing scenarios.
I was able to recreate the failure using the following test:
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Security;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class RSAKeyGenStressTest {
private static final int NUM_THREADS = 16;
private static final int ITERATIONS_PER_THREAD = 100000;
private static final AtomicInteger successCount = new AtomicInteger(0);
public static void main(String[] args) {
System.out.println("================================");
System.out.println("RSA Key Generation Stress Test");
System.out.println("================================");
System.out.println("Threads: " + NUM_THREADS);
System.out.println("Iterations per thread: " + ITERATIONS_PER_THREAD);
System.out.println("================================");
System.out.println();
try {
Class<?> providerClass = Class.forName("com.ibm.crypto.plus.provider.OpenJCEPlusFIPS");
java.security.Provider provider = (java.security.Provider) providerClass.getDeclaredConstructor().newInstance();
Security.addProvider(provider);
System.out.println("Loaded provider: " + provider.getName());
} catch (Exception e) {
System.err.println("ERROR: Could not load OpenJCEPlusFIPS provider: " + e.getMessage());
System.exit(-1);
}
System.out.println("\nStarting stress test...\n");
ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
CountDownLatch latch = new CountDownLatch(NUM_THREADS);
for (int t = 0; t < NUM_THREADS; t++) {
final int threadId = t;
executor.submit(() -> {
try {
runTest(threadId);
} finally {
latch.countDown();
}
});
}
try {
latch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.err.println("Test interrupted");
}
executor.shutdown();
System.out.println("\n================================");
System.out.println("Test Results:");
System.out.println("================================");
System.out.println("Successes: " + successCount.get());
System.out.println("\nAll key generations succeeded");
System.out.println("================================");
System.exit(-1);
}
private static void runTest(int threadId) {
KeyPairGenerator kpg = null;
try {
kpg = KeyPairGenerator.getInstance("RSA", "OpenJCEPlusFIPS");
} catch (Exception e) {
System.err.println("Failed to get RSA instance.");
System.exit(-1);
}
for (int i = 0; i < ITERATIONS_PER_THREAD; i++) {
try {
KeyPair keyPair = kpg.generateKeyPair();
if (keyPair == null || keyPair.getPrivate() == null || keyPair.getPublic() == null) {
System.err.println("Error empty key.");
System.exit(-1);
} else {
successCount.incrementAndGet();
if (successCount.get() % 100 == 0) {
System.out.println("Progress: " + successCount.get() + " keys generated...");
}
}
} catch (Exception e) {
System.err.println("FAILURE generating key.");
System.err.println("Exception: " + e.getClass().getName() + ": " + e.getMessage());
e.printStackTrace(System.err);
System.exit(-1);
}
}
}
}
With enough time the failure can be observed on MacOS:
...
...
...
Progress: 1226100 keys generated...
Progress: 1226200 keys generated...
Progress: 1226300 keys generated...
FAILURE generating key.
Exception: java.security.ProviderException: Failure in generateKeyPair
java.security.ProviderException: Failure in generateKeyPair
at openjceplus/com.ibm.crypto.plus.provider.OpenJCEPlusFIPS.providerException(OpenJCEPlusFIPS.java:935)
at openjceplus/com.ibm.crypto.plus.provider.RSAKeyPairGenerator.generateKeyPair(RSAKeyPairGenerator.java:125)
at openjceplus/com.ibm.crypto.plus.provider.RSAKeyPairGenerator$Legacy.generateKeyPair(RSAKeyPairGenerator.java:129)
at java.base/java.security.KeyPairGenerator$Delegate.generateKeyPair(KeyPairGenerator.java:723)
at RSAKeyGenStressTest.runTest(RSAKeyGenStressTest.java:81)
at RSAKeyGenStressTest.lambda$main$0(RSAKeyGenStressTest.java:47)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614)
at java.base/java.lang.Thread.run(Thread.java:1485)
Caused by: com.ibm.crypto.plus.provider.ock.OCKException: ICC_RSA_generate_key() failed
at openjceplus/com.ibm.crypto.plus.provider.ock.NativeInterface.RSAKEY_generate(Native Method)
at openjceplus/com.ibm.crypto.plus.provider.ock.RSAKey.generateKeyPair(RSAKey.java:41)
at openjceplus/com.ibm.crypto.plus.provider.RSAKeyPairGenerator.generateKeyPair(RSAKeyPairGenerator.java:119)
... 9 more
RSA key generations have failed on rare occasions in various testing scenarios.
I was able to recreate the failure using the following test:
With enough time the failure can be observed on MacOS: