Browse Source

Add sanity checks on scalar mult. outputs

Ugochukwu Mmaduekwe 6 years ago
parent
commit
e28c60f18e
1 changed files with 82 additions and 22 deletions
  1. 82 22
      CryptoLib/src/Math/EC/Rfc8032/ClpEd25519.pas

+ 82 - 22
CryptoLib/src/Math/EC/Rfc8032/ClpEd25519.pas

@@ -41,6 +41,7 @@ resourcestring
   SDigestError = 'Digest Produced Insufficient Data';
   SDigestError = 'Digest Produced Insufficient Data';
 
 
 type
 type
+  // -x^2 + y^2 == 1 + 0x52036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978A3 * x^2 * y^2
   TEd25519 = class(TInterfacedObject, IEd25519)
   TEd25519 = class(TInterfacedObject, IEd25519)
 
 
   strict private
   strict private
@@ -203,8 +204,8 @@ type
     class procedure Encode56(n: UInt64; const bs: TCryptoLibByteArray;
     class procedure Encode56(n: UInt64; const bs: TCryptoLibByteArray;
       off: Int32); static; inline;
       off: Int32); static; inline;
 
 
-    class procedure EncodePoint(var p: TPointAccum;
-      const r: TCryptoLibByteArray; rOff: Int32); static;
+    class function EncodePoint(var p: TPointAccum; const r: TCryptoLibByteArray;
+      rOff: Int32): Int32; static;
 
 
     class function GetWindow4(const X: TCryptoLibUInt32Array; n: Int32): Int32;
     class function GetWindow4(const X: TCryptoLibUInt32Array; n: Int32): Int32;
       static; inline;
       static; inline;
@@ -310,6 +311,11 @@ type
       (const AData: TCryptoLibByteArray; AIsNil: Boolean; ALength: Int32)
       (const AData: TCryptoLibByteArray; AIsNil: Boolean; ALength: Int32)
       : TCryptoLibCustomByteArrayBuffer; static; inline;
       : TCryptoLibCustomByteArrayBuffer; static; inline;
 
 
+    class function CheckPoint(const X, Y: TCryptoLibInt32Array): Int32;
+      overload; static;
+    class function CheckPoint(const X, Y, Z: TCryptoLibInt32Array): Int32;
+      overload; static;
+
     class procedure Boot(); static;
     class procedure Boot(); static;
     class constructor CreateEd25519();
     class constructor CreateEd25519();
     class destructor DestroyEd25519();
     class destructor DestroyEd25519();
@@ -685,6 +691,50 @@ begin
     ((not ctx.IsNil) and (ctx.Length < 256));
     ((not ctx.IsNil) and (ctx.Length < 256));
 end;
 end;
 
 
+class function TEd25519.CheckPoint(const X, Y: TCryptoLibInt32Array): Int32;
+var
+  T, U, V: TCryptoLibInt32Array;
+begin
+  T := TX25519Field.Create();
+  U := TX25519Field.Create();
+  V := TX25519Field.Create();
+
+  TX25519Field.Sqr(X, U);
+  TX25519Field.Sqr(Y, V);
+  TX25519Field.Mul(U, V, T);
+  TX25519Field.Sub(V, U, V);
+  TX25519Field.Mul(T, FC_d, T);
+  TX25519Field.AddOne(T);
+  TX25519Field.Sub(T, V, T);
+  TX25519Field.Normalize(T);
+
+  result := TX25519Field.IsZero(T);
+end;
+
+class function TEd25519.CheckPoint(const X, Y, Z: TCryptoLibInt32Array): Int32;
+var
+  T, U, V, W: TCryptoLibInt32Array;
+begin
+  T := TX25519Field.Create();
+  U := TX25519Field.Create();
+  V := TX25519Field.Create();
+  W := TX25519Field.Create();
+
+  TX25519Field.Sqr(X, U);
+  TX25519Field.Sqr(Y, V);
+  TX25519Field.Sqr(Z, W);
+  TX25519Field.Mul(U, V, T);
+  TX25519Field.Sub(V, U, V);
+  TX25519Field.Mul(V, W, V);
+  TX25519Field.Sqr(W, W);
+  TX25519Field.Mul(T, FC_d, T);
+  TX25519Field.Add(T, W, T);
+  TX25519Field.Sub(T, V, T);
+  TX25519Field.Normalize(T);
+
+  result := TX25519Field.IsZero(T);
+end;
+
 class function TEd25519.CheckPointVar(const p: TCryptoLibByteArray): Boolean;
 class function TEd25519.CheckPointVar(const p: TCryptoLibByteArray): Boolean;
 var
 var
   T: TCryptoLibUInt32Array;
   T: TCryptoLibUInt32Array;
@@ -769,22 +819,22 @@ end;
 class function TEd25519.GetWindow4(const X: TCryptoLibUInt32Array;
 class function TEd25519.GetWindow4(const X: TCryptoLibUInt32Array;
   n: Int32): Int32;
   n: Int32): Int32;
 var
 var
-  w, b: Int32;
+  W, b: Int32;
 begin
 begin
-  w := TBits.Asr32(n, 3);
+  W := TBits.Asr32(n, 3);
   b := (n and 7) shl 2;
   b := (n and 7) shl 2;
-  result := (X[w] shr b) and 15;
+  result := (X[W] shr b) and 15;
 end;
 end;
 
 
 class procedure TEd25519.PointLookup(const X: TCryptoLibUInt32Array; n: Int32;
 class procedure TEd25519.PointLookup(const X: TCryptoLibUInt32Array; n: Int32;
   const table: TCryptoLibInt32Array; var r: TPointExt);
   const table: TCryptoLibInt32Array; var r: TPointExt);
 var
 var
-  w, LSign, abs, i, off, cond: Int32;
+  W, LSign, abs, i, off, cond: Int32;
 begin
 begin
-  w := GetWindow4(X, n);
+  W := GetWindow4(X, n);
 
 
-  LSign := (TBits.Asr32(w, (PrecompTeeth - 1))) xor 1;
-  abs := (w xor -LSign) and PrecompMask;
+  LSign := (TBits.Asr32(W, (PrecompTeeth - 1))) xor 1;
+  abs := (W xor -LSign) and PrecompMask;
 
 
 {$IFDEF DEBUG}
 {$IFDEF DEBUG}
   System.Assert((LSign = 0) or (LSign = 1));
   System.Assert((LSign = 0) or (LSign = 1));
@@ -879,8 +929,8 @@ begin
   end;
   end;
 end;
 end;
 
 
-class procedure TEd25519.EncodePoint(var p: TPointAccum;
-  const r: TCryptoLibByteArray; rOff: Int32);
+class function TEd25519.EncodePoint(var p: TPointAccum;
+  const r: TCryptoLibByteArray; rOff: Int32): Int32;
 var
 var
   X, Y: TCryptoLibInt32Array;
   X, Y: TCryptoLibInt32Array;
 begin
 begin
@@ -893,6 +943,8 @@ begin
   TX25519Field.Normalize(X);
   TX25519Field.Normalize(X);
   TX25519Field.Normalize(Y);
   TX25519Field.Normalize(Y);
 
 
+  result := CheckPoint(X, Y);
+
   TX25519Field.Encode(Y, r, rOff);
   TX25519Field.Encode(Y, r, rOff);
   r[rOff + PointBytes - 1] := r[rOff + PointBytes - 1] or
   r[rOff + PointBytes - 1] := r[rOff + PointBytes - 1] or
     Byte((X[0] and 1) shl 7);
     Byte((X[0] and 1) shl 7);
@@ -921,7 +973,10 @@ var
 begin
 begin
   p := TPointAccum.CreatePointAccum();
   p := TPointAccum.CreatePointAccum();
   ScalarMultBase(k, p);
   ScalarMultBase(k, p);
-  EncodePoint(p, r, rOff);
+  if (EncodePoint(p, r, rOff) = 0) then
+  begin
+    raise EInvalidOperationCryptoLibException.Create('');
+  end;
 end;
 end;
 
 
 procedure TEd25519.GeneratePublicKey(const sk: TCryptoLibByteArray;
 procedure TEd25519.GeneratePublicKey(const sk: TCryptoLibByteArray;
@@ -1162,7 +1217,8 @@ begin
 
 
   EncodePoint(pR, check, 0);
   EncodePoint(pR, check, 0);
 
 
-  result := TArrayUtils.ConstantTimeAreEqual(check, r);
+  result := (EncodePoint(pR, check, 0) <> 0) and
+    (TArrayUtils.ConstantTimeAreEqual(check, r));
 end;
 end;
 
 
 class procedure TEd25519.PointAddPrecomp(var p: TPointPrecomp;
 class procedure TEd25519.PointAddPrecomp(var p: TPointPrecomp;
@@ -1804,7 +1860,7 @@ var
   n: TCryptoLibUInt32Array;
   n: TCryptoLibUInt32Array;
   table: TCryptoLibInt32Array;
   table: TCryptoLibInt32Array;
   q: TPointExt;
   q: TPointExt;
-  w, c1, c2: Int32;
+  W, c1, c2: Int32;
 begin
 begin
   Precompute();
   Precompute();
   System.SetLength(n, ScalarUints);
   System.SetLength(n, ScalarUints);
@@ -1838,18 +1894,18 @@ begin
   PointLookup(table, 7, q);
   PointLookup(table, 7, q);
   PointAdd(q, r);
   PointAdd(q, r);
 
 
-  w := 62;
+  W := 62;
   while (true) do
   while (true) do
   begin
   begin
-    PointLookup(n, w, table, q);
+    PointLookup(n, W, table, q);
     PointAdd(q, r);
     PointAdd(q, r);
 
 
     PointDouble(r);
     PointDouble(r);
     PointDouble(r);
     PointDouble(r);
     PointDouble(r);
     PointDouble(r);
 
 
-    System.Dec(w);
-    if (w < 0) then
+    System.Dec(W);
+    if (W < 0) then
     begin
     begin
       break;
       break;
     end;
     end;
@@ -1862,7 +1918,7 @@ class procedure TEd25519.ScalarMultBase(const k: TCryptoLibByteArray;
   var r: TPointAccum);
   var r: TPointAccum);
 var
 var
   n: TCryptoLibUInt32Array;
   n: TCryptoLibUInt32Array;
-  w, c1, c2: UInt32;
+  W, c1, c2: UInt32;
   i, cOff, b, LSign, abs: Int32;
   i, cOff, b, LSign, abs: Int32;
   p: TPointPrecomp;
   p: TPointPrecomp;
 begin
 begin
@@ -1895,9 +1951,9 @@ begin
   begin
   begin
     for b := 0 to System.Pred(PrecompBlocks) do
     for b := 0 to System.Pred(PrecompBlocks) do
     begin
     begin
-      w := n[b] shr cOff;
-      LSign := Int32(w shr (PrecompTeeth - 1)) and 1;
-      abs := (Int32(w) xor -LSign) and PrecompMask;
+      W := n[b] shr cOff;
+      LSign := Int32(W shr (PrecompTeeth - 1)) and 1;
+      abs := (Int32(W) xor -LSign) and PrecompMask;
 
 
 {$IFDEF DEBUG}
 {$IFDEF DEBUG}
       System.Assert((LSign = 0) or (LSign = 1));
       System.Assert((LSign = 0) or (LSign = 1));
@@ -1931,6 +1987,10 @@ begin
 
 
   p := TPointAccum.CreatePointAccum();
   p := TPointAccum.CreatePointAccum();
   ScalarMultBase(n, p);
   ScalarMultBase(n, p);
+  if (CheckPoint(p.X, p.Y, p.Z) = 0) then
+  begin
+    raise EInvalidOperationCryptoLibException.Create('');
+  end;
   TX25519Field.Copy(p.Y, 0, Y, 0);
   TX25519Field.Copy(p.Y, 0, Y, 0);
   TX25519Field.Copy(p.Z, 0, Z, 0);
   TX25519Field.Copy(p.Z, 0, Z, 0);
 end;
 end;