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);
         }
         }
     }
openSUSE Build Service is sponsored by