From 87ab5d8470829879219e50213912bab6b1ab8fe8 Mon Sep 17 00:00:00 2001
From: Peter Dettman <peter.dettman@bouncycastle.org>
Date: Sat, 4 Jul 2020 00:09:03 +0700
Subject: [PATCH] Blind the inversion when normalizing

- see the paper "Yet another GCD based inversion side-channel affecting
ECC implementations" by Nir Drucker and Shay Gueron.
---
 .../org/bouncycastle/math/ec/ECPoint.java     | 27 ++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java b/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java
index 20882dacc9..575ddb851e 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java
@@ -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 ECPoint normalize()
         }
         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);
         }
         }
     }
