mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8262316: Reducing locks in RSA Blinding
Reviewed-by: jnimeh
This commit is contained in:
parent
d3fdd7399d
commit
7a99a9874b
1 changed files with 63 additions and 43 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -25,20 +25,25 @@
|
||||||
|
|
||||||
package sun.security.rsa;
|
package sun.security.rsa;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import sun.security.jca.JCAUtil;
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.security.interfaces.*;
|
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
import javax.crypto.BadPaddingException;
|
||||||
|
import java.math.BigInteger;
|
||||||
import sun.security.jca.JCAUtil;
|
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
|
* 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
|
* 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
|
* The code in this class only does the core RSA operation. Padding and
|
||||||
* unpadding must be done externally.
|
* unpadding must be done externally.
|
||||||
|
@ -53,11 +58,14 @@ public final class RSACore {
|
||||||
// globally enable/disable use of blinding
|
// globally enable/disable use of blinding
|
||||||
private static final boolean ENABLE_BLINDING = true;
|
private static final boolean ENABLE_BLINDING = true;
|
||||||
|
|
||||||
// cache for blinding parameters. Map<BigInteger, BlindingParameters>
|
// cache for blinding parameters. Map<BigInteger,
|
||||||
// use a weak hashmap so that cached values are automatically cleared
|
// ConcurrentLinkedQueue<BlindingParameters>> use a weak hashmap so that,
|
||||||
// when the modulus is GC'ed
|
// cached values are automatically cleared when the modulus is GC'ed.
|
||||||
private static final Map<BigInteger, BlindingParameters>
|
// Multiple BlindingParameters can be queued during times of heavy load,
|
||||||
|
// like performance testing.
|
||||||
|
private static final Map<BigInteger, ConcurrentLinkedQueue<BlindingParameters>>
|
||||||
blindingCache = new WeakHashMap<>();
|
blindingCache = new WeakHashMap<>();
|
||||||
|
private static final ReentrantLock lock = new ReentrantLock();
|
||||||
|
|
||||||
private RSACore() {
|
private RSACore() {
|
||||||
// empty
|
// empty
|
||||||
|
@ -402,56 +410,68 @@ public final class RSACore {
|
||||||
if ((this.e != null && this.e.equals(e)) ||
|
if ((this.e != null && this.e.equals(e)) ||
|
||||||
(this.d != null && this.d.equals(d))) {
|
(this.d != null && this.d.equals(d))) {
|
||||||
|
|
||||||
BlindingRandomPair brp = null;
|
BlindingRandomPair brp = new BlindingRandomPair(u, v);
|
||||||
synchronized (this) {
|
if (u.compareTo(BigInteger.ONE) <= 0 ||
|
||||||
if (!u.equals(BigInteger.ZERO) &&
|
v.compareTo(BigInteger.ONE) <= 0) {
|
||||||
!v.equals(BigInteger.ZERO)) {
|
// Reset so the parameters will be not queued later
|
||||||
|
u = BigInteger.ZERO;
|
||||||
brp = new BlindingRandomPair(u, v);
|
v = BigInteger.ZERO;
|
||||||
if (u.compareTo(BigInteger.ONE) <= 0 ||
|
} else {
|
||||||
v.compareTo(BigInteger.ONE) <= 0) {
|
u = u.modPow(BIG_TWO, n);
|
||||||
|
v = v.modPow(BIG_TWO, n);
|
||||||
// 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.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return brp;
|
return brp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
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(
|
private static BlindingRandomPair getBlindingRandomPair(
|
||||||
BigInteger e, BigInteger d, BigInteger n) {
|
BigInteger e, BigInteger d, BigInteger n) {
|
||||||
|
|
||||||
BlindingParameters bps = null;
|
ConcurrentLinkedQueue<BlindingParameters> queue;
|
||||||
synchronized (blindingCache) {
|
|
||||||
bps = blindingCache.get(n);
|
// 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) {
|
if (bps == null) {
|
||||||
bps = new BlindingParameters(e, d, n);
|
bps = new BlindingParameters(e, d, n);
|
||||||
synchronized (blindingCache) {
|
|
||||||
blindingCache.putIfAbsent(n, bps);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BlindingRandomPair brp = bps.getBlindingRandomPair(e, d, n);
|
BlindingRandomPair brp = null;
|
||||||
if (brp == null) {
|
|
||||||
// need to reset the blinding parameters
|
// Loops to get a valid pair, going through the queue or create a new
|
||||||
bps = new BlindingParameters(e, d, n);
|
// parameters if needed.
|
||||||
synchronized (blindingCache) {
|
while (brp == null) {
|
||||||
blindingCache.replace(n, bps);
|
|
||||||
}
|
|
||||||
brp = bps.getBlindingRandomPair(e, d, n);
|
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;
|
return brp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue