File bouncycastle-CVE-2020-15522.patch of Package bouncycastle.19826
diff -PpuriN bc-java-r1rv65/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java bc-java-r1rv66/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java
--- bc-java-r1rv65/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java 2020-03-31 07:19:14.000000000 +0200
+++ bc-java-r1rv66/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java 2020-07-06 06:11:06.000000000 +0200
@@ -1,6 +1,7 @@
package org.bouncycastle.math.ec;
import java.math.BigInteger;
+import java.security.SecureRandom;
import java.util.Hashtable;
import java.util.Random;
@@ -107,6 +108,8 @@ public abstract class ECCurve
public abstract boolean isValidFieldElement(BigInteger x);
+ public abstract ECFieldElement randomFieldElementMult(SecureRandom r);
+
public synchronized Config configure()
{
return new Config(this.coord, this.endomorphism, this.multiplier);
@@ -585,6 +590,18 @@ public abstract class ECCurve
return x != null && x.signum() >= 0 && x.compareTo(this.getField().getCharacteristic()) < 0;
}
+ public ECFieldElement randomFieldElementMult(SecureRandom r)
+ {
+ /*
+ * NOTE: BigInteger comparisons in the rejection sampling are not constant-time, so we
+ * use the product of two independent elements to mitigate side-channels.
+ */
+ BigInteger p = getField().getCharacteristic();
+ ECFieldElement fe1 = fromBigInteger(implRandomFieldElementMult(r, p));
+ ECFieldElement fe2 = fromBigInteger(implRandomFieldElementMult(r, p));
+ return fe1.multiply(fe2);
+ }
+
protected ECPoint decompressPoint(int yTilde, BigInteger X1)
{
ECFieldElement x = this.fromBigInteger(X1);
@@ -607,6 +636,28 @@ public abstract class ECCurve
return this.createRawPoint(x, y);
}
+
+ private static BigInteger implRandomFieldElement(SecureRandom r, BigInteger p)
+ {
+ BigInteger x;
+ do
+ {
+ x = BigIntegers.createRandomBigInteger(p.bitLength(), r);
+ }
+ while (x.compareTo(p) >= 0);
+ return x;
+ }
+
+ private static BigInteger implRandomFieldElementMult(SecureRandom r, BigInteger p)
+ {
+ BigInteger x;
+ do
+ {
+ x = BigIntegers.createRandomBigInteger(p.bitLength(), r);
+ }
+ while (x.signum() <= 0 || x.compareTo(p) >= 0);
+ return x;
+ }
}
/**
@@ -835,6 +881,18 @@ public abstract class ECCurve
return this.createRawPoint(X, Y);
}
+ public ECFieldElement randomFieldElementMult(SecureRandom r)
+ {
+ /*
+ * NOTE: BigInteger comparisons in the rejection sampling are not constant-time, so we
+ * use the product of two independent elements to mitigate side-channels.
+ */
+ int m = getFieldSize();
+ ECFieldElement fe1 = fromBigInteger(implRandomFieldElementMult(r, m));
+ ECFieldElement fe2 = fromBigInteger(implRandomFieldElementMult(r, m));
+ return fe1.multiply(fe2);
+ }
+
/**
* Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
*
@@ -971,6 +1040,17 @@ public abstract class ECCurve
{
return this.order != null && this.cofactor != null && this.b.isOne() && (this.a.isZero() || this.a.isOne());
}
+
+ private static BigInteger implRandomFieldElementMult(SecureRandom r, int m)
+ {
+ BigInteger x;
+ do
+ {
+ x = BigIntegers.createRandomBigInteger(m, r);
+ }
+ while (x.signum() <= 0);
+ return x;
+ }
}
/**
diff -PpuriN bc-java-r1rv65/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java bc-java-r1rv66/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java
--- bc-java-r1rv65/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java 2020-03-31 07:19:14.000000000 +0200
+++ bc-java-r1rv66/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java 2020-07-06 06:11:06.000000000 +0200
@@ -1,8 +1,11 @@
package org.bouncycastle.math.ec;
import java.math.BigInteger;
+import java.security.SecureRandom;
import java.util.Hashtable;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
+
/**
* base class for points on elliptic curves.
*/
@@ -222,13 +225,31 @@ public abstract class ECPoint
}
default:
{
- ECFieldElement Z1 = getZCoord(0);
- if (Z1.isOne())
+ ECFieldElement z = getZCoord(0);
+ if (z.isOne())
{
return this;
}
- return normalize(Z1.invert());
+ if (null == curve)
+ {
+ throw new IllegalStateException("Detached points must be in affine coordinates");
+ }
+
+ /*
+ * Use blinding to avoid the side-channel leak identified and analyzed in the paper
+ * "Yet another GCD based inversion side-channel affecting ECC implementations" by Nir
+ * Drucker and Shay Gueron.
+ *
+ * To blind the calculation of z^-1, choose a multiplicative (i.e. non-zero) field
+ * element 'b' uniformly at random, then calculate the result instead as (z * b)^-1 * b.
+ * Any side-channel in the implementation of 'inverse' now only leaks information about
+ * the value (z * b), and no longer reveals information about 'z' itself.
+ */
+ SecureRandom r = CryptoServicesRegistrar.getSecureRandom();
+ ECFieldElement b = curve.randomFieldElementMult(r);
+ ECFieldElement zInv = z.multiply(b).invert().multiply(b);
+ return normalize(zInv);
}
}
}