166 lines
6.1 KiB
Diff
166 lines
6.1 KiB
Diff
Date: Mon, 5 Jun 2023 20:27:38 +0800
|
|
Subject: 8262316: Reducing locks in RSA Blinding
|
|
|
|
Bug url: https://bugs.openjdk.org/browse/JDK-8262316
|
|
---
|
|
.../classes/sun/security/rsa/RSACore.java | 101 +++++++++++-------
|
|
1 file changed, 60 insertions(+), 41 deletions(-)
|
|
|
|
diff --git a/jdk/src/share/classes/sun/security/rsa/RSACore.java b/jdk/src/share/classes/sun/security/rsa/RSACore.java
|
|
index 9809639a0..ae187b5a5 100644
|
|
--- a/jdk/src/share/classes/sun/security/rsa/RSACore.java
|
|
+++ b/jdk/src/share/classes/sun/security/rsa/RSACore.java
|
|
@@ -25,20 +25,26 @@
|
|
|
|
package sun.security.rsa;
|
|
|
|
-import java.math.BigInteger;
|
|
-import java.util.*;
|
|
-
|
|
-import java.security.SecureRandom;
|
|
-import java.security.interfaces.*;
|
|
+import sun.security.jca.JCAUtil;
|
|
|
|
import javax.crypto.BadPaddingException;
|
|
|
|
-import sun.security.jca.JCAUtil;
|
|
+import java.math.BigInteger;
|
|
+import java.security.SecureRandom;
|
|
+import java.security.interfaces.RSAKey;
|
|
+import java.security.interfaces.RSAPrivateCrtKey;
|
|
+import java.security.interfaces.RSAPrivateKey;
|
|
+import java.security.interfaces.RSAPublicKey;
|
|
+import java.util.Arrays;
|
|
+import java.util.Map;
|
|
+import java.util.WeakHashMap;
|
|
+import java.util.concurrent.ConcurrentLinkedQueue;
|
|
+import java.util.concurrent.locks.ReentrantLock;
|
|
|
|
/**
|
|
* Core of the RSA implementation. Has code to perform public and private key
|
|
* RSA operations (with and without CRT for private key ops). Private CRT ops
|
|
- * also support blinding to twart timing attacks.
|
|
+ * also support blinding to thwart timing attacks.
|
|
*
|
|
* The code in this class only does the core RSA operation. Padding and
|
|
* unpadding must be done externally.
|
|
@@ -53,11 +59,14 @@ public final class RSACore {
|
|
// globally enable/disable use of blinding
|
|
private final static boolean ENABLE_BLINDING = true;
|
|
|
|
- // cache for blinding parameters. Map<BigInteger, BlindingParameters>
|
|
- // use a weak hashmap so that cached values are automatically cleared
|
|
- // when the modulus is GC'ed
|
|
- private final static Map<BigInteger, BlindingParameters>
|
|
+ // cache for blinding parameters. Map<BigInteger,
|
|
+ // ConcurrentLinkedQueue<BlindingParameters>> use a weak hashmap so that,
|
|
+ // cached values are automatically cleared when the modulus is GC'ed.
|
|
+ // Multiple BlindingParameters can be queued during times of heavy load,
|
|
+ // like performance testing.
|
|
+ private static final Map<BigInteger, ConcurrentLinkedQueue<BlindingParameters>>
|
|
blindingCache = new WeakHashMap<>();
|
|
+ private static final ReentrantLock lock = new ReentrantLock();
|
|
|
|
private RSACore() {
|
|
// empty
|
|
@@ -402,56 +411,66 @@ public final class RSACore {
|
|
if ((this.e != null && this.e.equals(e)) ||
|
|
(this.d != null && this.d.equals(d))) {
|
|
|
|
- BlindingRandomPair brp = null;
|
|
- synchronized (this) {
|
|
- if (!u.equals(BigInteger.ZERO) &&
|
|
- !v.equals(BigInteger.ZERO)) {
|
|
-
|
|
- brp = new BlindingRandomPair(u, v);
|
|
- if (u.compareTo(BigInteger.ONE) <= 0 ||
|
|
- v.compareTo(BigInteger.ONE) <= 0) {
|
|
-
|
|
- // need to reset the random pair next time
|
|
- u = BigInteger.ZERO;
|
|
- v = BigInteger.ZERO;
|
|
- } else {
|
|
- u = u.modPow(BIG_TWO, n);
|
|
- v = v.modPow(BIG_TWO, n);
|
|
- }
|
|
- } // Otherwise, need to reset the random pair.
|
|
+ BlindingRandomPair brp = new BlindingRandomPair(u, v);
|
|
+ if (u.compareTo(BigInteger.ONE) <= 0 ||
|
|
+ v.compareTo(BigInteger.ONE) <= 0) {
|
|
+ // Reset so the parameters will be not queued later
|
|
+ u = BigInteger.ZERO;
|
|
+ v = BigInteger.ZERO;
|
|
+ } else {
|
|
+ u = u.modPow(BIG_TWO, n);
|
|
+ v = v.modPow(BIG_TWO, n);
|
|
}
|
|
return brp;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
+
|
|
+ // Check if reusable, return true if both u & v are not zero.
|
|
+ boolean isReusable() {
|
|
+ return !u.equals(BigInteger.ZERO) && !v.equals(BigInteger.ZERO);
|
|
+ }
|
|
}
|
|
|
|
private static BlindingRandomPair getBlindingRandomPair(
|
|
BigInteger e, BigInteger d, BigInteger n) {
|
|
|
|
- BlindingParameters bps = null;
|
|
- synchronized (blindingCache) {
|
|
- bps = blindingCache.get(n);
|
|
+ ConcurrentLinkedQueue<BlindingParameters> queue;
|
|
+
|
|
+ // Get queue from map, if there is none then create one
|
|
+ lock.lock();
|
|
+ try {
|
|
+ queue = blindingCache.computeIfAbsent(n,
|
|
+ ignored -> new ConcurrentLinkedQueue<>());
|
|
+ } finally {
|
|
+ lock.unlock();
|
|
}
|
|
|
|
+ BlindingParameters bps = queue.poll();
|
|
if (bps == null) {
|
|
bps = new BlindingParameters(e, d, n);
|
|
- synchronized (blindingCache) {
|
|
- blindingCache.putIfAbsent(n, bps);
|
|
- }
|
|
}
|
|
+ BlindingRandomPair brp = null;
|
|
|
|
- BlindingRandomPair brp = bps.getBlindingRandomPair(e, d, n);
|
|
- if (brp == null) {
|
|
- // need to reset the blinding parameters
|
|
- bps = new BlindingParameters(e, d, n);
|
|
- synchronized (blindingCache) {
|
|
- blindingCache.replace(n, bps);
|
|
- }
|
|
+ // Loops to get a valid pair, going through the queue or create a new
|
|
+ // parameters if needed.
|
|
+ while (brp == null) {
|
|
brp = bps.getBlindingRandomPair(e, d, n);
|
|
+ if (brp == null) {
|
|
+ // need to reset the blinding parameters, first check for
|
|
+ // another in the queue.
|
|
+ bps = queue.poll();
|
|
+ if (bps == null) {
|
|
+ bps = new BlindingParameters(e, d, n);
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
+ // If this parameters are still usable, put them back into the queue.
|
|
+ if (bps.isReusable()) {
|
|
+ queue.add(bps);
|
|
+ }
|
|
return brp;
|
|
}
|
|
|
|
--
|
|
2.22.0
|
|
|