Browse Source

Add non-constant-time variant to ECLookupTable

Ugochukwu Mmaduekwe 6 years ago
parent
commit
9fee46e4c8

+ 1 - 1
CryptoLib/src/Interfaces/ClpICurve25519Custom.pas

@@ -55,7 +55,7 @@ type
   end;
 
 type
-  ICurve25519LookupTable = Interface(IECLookupTable)
+  ICurve25519LookupTable = Interface(IAbstractECLookupTable)
     ['{79FE1276-3D22-4A20-A4F1-58F0C0532BAC}']
   end;
 

+ 15 - 2
CryptoLib/src/Interfaces/ClpIECC.pas

@@ -595,11 +595,24 @@ type
     ['{A1839961-4FBF-42EF-BF8B-6084064A05C1}']
     function GetSize: Int32;
     function Lookup(index: Int32): IECPoint;
+    function LookupVar(index: Int32): IECPoint;
     property Size: Int32 read GetSize;
   end;
 
 type
-  IDefaultLookupTable = interface(IECLookupTable)
+  IAbstractECLookupTable = interface(IECLookupTable)
+    ['{9695E807-6A2A-4879-8438-84CE029AD143}']
+
+  end;
+
+type
+  ISimpleLookupTable = interface(IAbstractECLookupTable)
+    ['{5C2C8292-CECE-4A01-89D2-AF75B55F6FA3}']
+
+  end;
+
+type
+  IDefaultLookupTable = interface(IAbstractECLookupTable)
     ['{094881EB-24A6-41A3-BAD6-D6DAB13DD17D}']
 
   end;
@@ -611,7 +624,7 @@ type
   end;
 
 type
-  IDefaultF2mLookupTable = interface(IECLookupTable)
+  IDefaultF2mLookupTable = interface(IAbstractECLookupTable)
     ['{0C019049-9839-4322-BAF5-8E5D39BC426D}']
 
   end;

+ 1 - 1
CryptoLib/src/Interfaces/ClpISecP256K1Custom.pas

@@ -50,7 +50,7 @@ type
   end;
 
 type
-  ISecP256K1LookupTable = Interface(IECLookupTable)
+  ISecP256K1LookupTable = Interface(IAbstractECLookupTable)
     ['{0E204483-F303-49FD-AF66-0F30CF855CA9}']
   end;
 

+ 1 - 1
CryptoLib/src/Interfaces/ClpISecP256R1Custom.pas

@@ -50,7 +50,7 @@ type
   end;
 
 type
-  ISecP256R1LookupTable = Interface(IECLookupTable)
+  ISecP256R1LookupTable = Interface(IAbstractECLookupTable)
     ['{87BF97BA-18D2-4248-ABEB-8E429998E9D9}']
   end;
 

+ 1 - 1
CryptoLib/src/Interfaces/ClpISecP384R1Custom.pas

@@ -50,7 +50,7 @@ type
   end;
 
 type
-  ISecP384R1LookupTable = Interface(IECLookupTable)
+  ISecP384R1LookupTable = Interface(IAbstractECLookupTable)
     ['{F1354F0B-577F-402C-A363-7761CF82DA43}']
   end;
 

+ 1 - 1
CryptoLib/src/Interfaces/ClpISecP521R1Custom.pas

@@ -50,7 +50,7 @@ type
   end;
 
 type
-  ISecP521R1LookupTable = Interface(IECLookupTable)
+  ISecP521R1LookupTable = Interface(IAbstractECLookupTable)
     ['{3A647191-94A9-483D-9AC5-57FEFDBA3060}']
   end;
 

+ 1 - 1
CryptoLib/src/Interfaces/ClpISecT283Custom.pas

@@ -74,7 +74,7 @@ type
   end;
 
 type
-  ISecT283K1LookupTable = Interface(IECLookupTable)
+  ISecT283K1LookupTable = Interface(IAbstractECLookupTable)
     ['{3AF41553-A108-46D6-9CCC-AB1814A0A247}']
   end;
 

+ 2 - 2
CryptoLib/src/Math/EC/ClpECAlgorithms.pas

@@ -273,8 +273,8 @@ begin
       System.Dec(j, d);
     end;
 
-    addP := lookupTableP.Lookup(Int32(secretIndexK));
-    addQ := lookupTableQ.Lookup(Int32(secretIndexL));
+    addP := lookupTableP.LookupVar(Int32(secretIndexK));
+    addQ := lookupTableQ.LookupVar(Int32(secretIndexL));
 
     t := addP.Add(addQ);
 

+ 171 - 35
CryptoLib/src/Math/EC/ClpECC.pas

@@ -93,6 +93,7 @@ resourcestring
   SNotProjectiveCoordSystem = 'Not a Projective Coordinate System';
   SCannotBeNegative = 'Cannot be Negative, "e"';
   SNilFieldElement = 'Exactly one of the Field Elements is Nil';
+  SUnsupportedOperation = 'Constant-time Lookup not Supported';
 
 type
   TECFieldElement = class abstract(TInterfacedObject, IECFieldElement)
@@ -690,20 +691,61 @@ type
   end;
 
 type
-  TDefaultLookupTable = class(TInterfacedObject, IDefaultLookupTable,
-    IECLookupTable)
+  TAbstractECLookupTable = class abstract(TInterfacedObject,
+    IAbstractECLookupTable, IECLookupTable)
+
+  strict protected
+    function GetSize: Int32; virtual; abstract;
+
+  public
+    function Lookup(index: Int32): IECPoint; virtual; abstract;
+    function LookupVar(index: Int32): IECPoint; virtual; abstract;
+    property Size: Int32 read GetSize;
+
+  end;
+
+type
+  TSimpleLookupTable = class abstract(TAbstractECLookupTable,
+    ISimpleLookupTable)
+
+  strict private
+  var
+    FPoints: TCryptoLibGenericArray<IECPoint>;
+
+    class function Copy(const points: TCryptoLibGenericArray<IECPoint>;
+      off, len: Int32): TCryptoLibGenericArray<IECPoint>; static;
+
+  strict protected
+    function GetSize: Int32; override;
+
+  public
+    constructor Create(const points: TCryptoLibGenericArray<IECPoint>;
+      off, len: Int32);
+
+    function Lookup(index: Int32): IECPoint; override;
+    function LookupVar(index: Int32): IECPoint; override;
+
+  end;
+
+type
+  TDefaultLookupTable = class(TAbstractECLookupTable, IDefaultLookupTable)
   strict private
   var
     Fm_outer: IECCurve;
     Fm_table: TCryptoLibByteArray;
     Fm_size: Int32;
 
+    function CreatePoint(const x, y: TCryptoLibByteArray): IECPoint;
+
+  strict protected
+    function GetSize: Int32; override;
+
   public
     constructor Create(const outer: IECCurve; const table: TCryptoLibByteArray;
-      size: Int32);
-    function GetSize: Int32; virtual;
-    function Lookup(index: Int32): IECPoint; virtual;
-    property size: Int32 read GetSize;
+      Size: Int32);
+
+    function Lookup(index: Int32): IECPoint; override;
+    function LookupVar(index: Int32): IECPoint; override;
 
   end;
 
@@ -723,20 +765,24 @@ type
   end;
 
 type
-  TDefaultF2mLookupTable = class(TInterfacedObject, IDefaultF2mLookupTable,
-    IECLookupTable)
+  TDefaultF2mLookupTable = class(TAbstractECLookupTable, IDefaultF2mLookupTable)
   strict private
   var
     Fm_outer: IF2mCurve;
     Fm_table: TCryptoLibInt64Array;
     Fm_size: Int32;
 
+    function CreatePoint(const x, y: TCryptoLibInt64Array): IECPoint;
+
+  strict protected
+    function GetSize: Int32; override;
+
   public
     constructor Create(const outer: IF2mCurve;
-      const table: TCryptoLibInt64Array; size: Int32);
-    function GetSize: Int32; virtual;
-    function Lookup(index: Int32): IECPoint; virtual;
-    property size: Int32 read GetSize;
+      const table: TCryptoLibInt64Array; Size: Int32);
+
+    function Lookup(index: Int32): IECPoint; override;
+    function LookupVar(index: Int32): IECPoint; override;
 
   end;
 
@@ -3654,12 +3700,22 @@ end;
 { TDefaultLookupTable }
 
 constructor TDefaultLookupTable.Create(const outer: IECCurve;
-  const table: TCryptoLibByteArray; size: Int32);
+  const table: TCryptoLibByteArray; Size: Int32);
 begin
   Inherited Create();
   Fm_outer := outer;
   Fm_table := table;
-  Fm_size := size;
+  Fm_size := Size;
+end;
+
+function TDefaultLookupTable.CreatePoint(const x, y: TCryptoLibByteArray)
+  : IECPoint;
+var
+  XFieldElement, YFieldElement: IECFieldElement;
+begin
+  XFieldElement := Fm_outer.FromBigInteger(TBigInteger.Create(1, x));
+  YFieldElement := Fm_outer.FromBigInteger(TBigInteger.Create(1, y));
+  result := Fm_outer.CreateRawPoint(XFieldElement, YFieldElement, false);
 end;
 
 function TDefaultLookupTable.GetSize: Int32;
@@ -3672,7 +3728,6 @@ var
   FE_BYTES, position, i, j: Int32;
   x, y: TCryptoLibByteArray;
   MASK: Byte;
-  XFieldElement, YFieldElement: IECFieldElement;
 begin
   FE_BYTES := (Fm_outer.FieldSize + 7) div 8;
   System.SetLength(x, FE_BYTES);
@@ -3687,41 +3742,52 @@ begin
 
     for j := 0 to System.Pred(FE_BYTES) do
     begin
-
       x[j] := x[j] xor Byte(Fm_table[position + j] and MASK);
       y[j] := y[j] xor Byte(Fm_table[position + FE_BYTES + j] and MASK);
     end;
     position := position + (FE_BYTES * 2);
   end;
 
-  XFieldElement := Fm_outer.FromBigInteger(TBigInteger.Create(1, x));
-  YFieldElement := Fm_outer.FromBigInteger(TBigInteger.Create(1, y));
-  result := Fm_outer.CreateRawPoint(XFieldElement, YFieldElement, false);
+  result := CreatePoint(x, y);
+end;
+
+function TDefaultLookupTable.LookupVar(index: Int32): IECPoint;
+var
+  FE_BYTES, position, j: Int32;
+  x, y: TCryptoLibByteArray;
+begin
+  FE_BYTES := (Fm_outer.FieldSize + 7) div 8;
+  System.SetLength(x, FE_BYTES);
+  System.SetLength(y, FE_BYTES);
+
+  position := index * FE_BYTES * 2;
+
+  for j := 0 to System.Pred(FE_BYTES) do
+  begin
+    x[j] := Fm_table[position + j];
+    y[j] := Fm_table[position + FE_BYTES + j];
+  end;
+
+  result := CreatePoint(x, y);
 end;
 
 { TDefaultF2mLookupTable }
 
 constructor TDefaultF2mLookupTable.Create(const outer: IF2mCurve;
-  const table: TCryptoLibInt64Array; size: Int32);
+  const table: TCryptoLibInt64Array; Size: Int32);
 begin
   Inherited Create();
   Fm_outer := outer;
   Fm_table := table;
-  Fm_size := size;
-end;
-
-function TDefaultF2mLookupTable.GetSize: Int32;
-begin
-  result := Fm_size;
+  Fm_size := Size;
 end;
 
-function TDefaultF2mLookupTable.Lookup(index: Int32): IECPoint;
+function TDefaultF2mLookupTable.CreatePoint(const x, y: TCryptoLibInt64Array)
+  : IECPoint;
 var
-  FE_LONGS, position, m, i, j: Int32;
-  ks: TCryptoLibInt32Array;
-  x, y: TCryptoLibInt64Array;
-  MASK: Int64;
   XFieldElement, YFieldElement: IECFieldElement;
+  m: Int32;
+  ks: TCryptoLibInt32Array;
 begin
   m := Fm_outer.m;
   if Fm_outer.IsTrinomial() then
@@ -3733,6 +3799,22 @@ begin
     ks := TCryptoLibInt32Array.Create(Fm_outer.k1, Fm_outer.k2, Fm_outer.k3);
   end;
 
+  XFieldElement := TF2mFieldElement.Create(m, ks, TLongArray.Create(x));
+  YFieldElement := TF2mFieldElement.Create(m, ks, TLongArray.Create(y));
+  result := Fm_outer.CreateRawPoint(XFieldElement, YFieldElement, false);
+end;
+
+function TDefaultF2mLookupTable.GetSize: Int32;
+begin
+  result := Fm_size;
+end;
+
+function TDefaultF2mLookupTable.Lookup(index: Int32): IECPoint;
+var
+  FE_LONGS, position, i, j: Int32;
+  x, y: TCryptoLibInt64Array;
+  MASK: Int64;
+begin
   FE_LONGS := (Fm_outer.m + 63) div 64;
   System.SetLength(x, FE_LONGS);
   System.SetLength(y, FE_LONGS);
@@ -3746,16 +3828,33 @@ begin
 
     for j := 0 to System.Pred(FE_LONGS) do
     begin
-
       x[j] := x[j] xor (Fm_table[position + j] and MASK);
       y[j] := y[j] xor (Fm_table[position + FE_LONGS + j] and MASK);
     end;
     position := position + (FE_LONGS * 2);
   end;
 
-  XFieldElement := TF2mFieldElement.Create(m, ks, TLongArray.Create(x));
-  YFieldElement := TF2mFieldElement.Create(m, ks, TLongArray.Create(y));
-  result := Fm_outer.CreateRawPoint(XFieldElement, YFieldElement, false);
+  result := CreatePoint(x, y);
+end;
+
+function TDefaultF2mLookupTable.LookupVar(index: Int32): IECPoint;
+var
+  FE_LONGS, position, j: Int32;
+  x, y: TCryptoLibInt64Array;
+begin
+  FE_LONGS := (Fm_outer.m + 63) div 64;
+  System.SetLength(x, FE_LONGS);
+  System.SetLength(y, FE_LONGS);
+
+  position := index * FE_LONGS * 2;
+
+  for j := 0 to System.Pred(FE_LONGS) do
+  begin
+    x[j] := Fm_table[position + j];
+    y[j] := Fm_table[position + FE_LONGS + j];
+  end;
+
+  result := CreatePoint(x, y);
 end;
 
 { TECPoint }
@@ -6583,4 +6682,41 @@ begin
   result := info;
 end;
 
+{ TSimpleLookupTable }
+
+class function TSimpleLookupTable.Copy(const points
+  : TCryptoLibGenericArray<IECPoint>; off, len: Int32)
+  : TCryptoLibGenericArray<IECPoint>;
+var
+  i: Int32;
+begin
+  System.SetLength(result, len);
+  for i := 0 to System.Pred(len) do
+  begin
+    result[i] := points[off + i];
+  end;
+end;
+
+constructor TSimpleLookupTable.Create(const points
+  : TCryptoLibGenericArray<IECPoint>; off, len: Int32);
+begin
+  inherited Create();
+  FPoints := Copy(points, off, len);
+end;
+
+function TSimpleLookupTable.GetSize: Int32;
+begin
+  result := System.Length(FPoints);
+end;
+
+function TSimpleLookupTable.Lookup(index: Int32): IECPoint;
+begin
+  raise EInvalidOperationCryptoLibException.CreateRes(@SUnsupportedOperation);
+end;
+
+function TSimpleLookupTable.LookupVar(index: Int32): IECPoint;
+begin
+  result := FPoints[index];
+end;
+
 end.

+ 51 - 12
CryptoLib/src/Math/EC/Custom/Djb/ClpCurve25519Custom.pas

@@ -237,8 +237,8 @@ type
   strict private
 
   type
-    TCurve25519LookupTable = class sealed(TInterfacedObject,
-      ICurve25519LookupTable, IECLookupTable)
+    TCurve25519LookupTable = class sealed(TAbstractECLookupTable,
+      ICurve25519LookupTable)
 
     strict private
     var
@@ -246,16 +246,19 @@ type
       Fm_table: TCryptoLibUInt32Array;
       Fm_size: Int32;
 
-      function GetSize: Int32; virtual;
+      function CreatePoint(const x, y: TCryptoLibUInt32Array): IECPoint;
+
+    strict protected
+
+      function GetSize: Int32; override;
 
     public
 
       constructor Create(const outer: ICurve25519;
         const table: TCryptoLibUInt32Array; size: Int32);
 
-      function Lookup(index: Int32): IECPoint; virtual;
-
-      property size: Int32 read GetSize;
+      function Lookup(index: Int32): IECPoint; override;
+      function LookupVar(index: Int32): IECPoint; override;
 
     end;
 
@@ -1239,13 +1242,13 @@ begin
   Fm_infinity := TCurve25519Point.Create(Self as IECCurve, Nil, Nil);
 
   Fm_a := FromBigInteger(TBigInteger.Create(1,
-    THex.Decode
+    THex.decode
     ('2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA984914A144')));
   Fm_b := FromBigInteger(TBigInteger.Create(1,
-    THex.Decode
+    THex.decode
     ('7B425ED097B425ED097B425ED097B425ED097B425ED097B4260B5E9C7710C864')));
   Fm_order := TBigInteger.Create(1,
-    THex.Decode
+    THex.decode
     ('1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED'));
   Fm_cofactor := TBigInteger.ValueOf(8);
   Fm_coord := Curve25519_DEFAULT_COORDS;
@@ -1333,6 +1336,26 @@ begin
   Fm_size := size;
 end;
 
+function TCurve25519.TCurve25519LookupTable.CreatePoint(const x,
+  y: TCryptoLibUInt32Array): IECPoint;
+var
+  XFieldElement, YFieldElement: ICurve25519FieldElement;
+  CURVE25519_AFFINE_ZS: TCryptoLibGenericArray<IECFieldElement>;
+  C_a: TBigInteger;
+begin
+  C_a := TBigInteger.Create(1,
+    THex.decode
+    ('2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA984914A144'));
+  CURVE25519_AFFINE_ZS := TCryptoLibGenericArray<IECFieldElement>.Create
+    (TCurve25519FieldElement.Create(TBigInteger.One) as ICurve25519FieldElement,
+    TCurve25519FieldElement.Create(C_a) as ICurve25519FieldElement);
+
+  XFieldElement := TCurve25519FieldElement.Create(x);
+  YFieldElement := TCurve25519FieldElement.Create(y);
+  result := Fm_outer.CreateRawPoint(XFieldElement, YFieldElement,
+    CURVE25519_AFFINE_ZS, false);
+end;
+
 function TCurve25519.TCurve25519LookupTable.GetSize: Int32;
 begin
   result := Fm_size;
@@ -1361,9 +1384,25 @@ begin
     pos := pos + (CURVE25519_FE_INTS * 2);
   end;
 
-  result := Fm_outer.CreateRawPoint(TCurve25519FieldElement.Create(x)
-    as ICurve25519FieldElement, TCurve25519FieldElement.Create(y)
-    as ICurve25519FieldElement, false);
+  result := CreatePoint(x, y)
+end;
+
+function TCurve25519.TCurve25519LookupTable.LookupVar(index: Int32): IECPoint;
+var
+  x, y: TCryptoLibUInt32Array;
+  pos, J: Int32;
+begin
+  x := TNat256.Create();
+  y := TNat256.Create();
+  pos := index * CURVE25519_FE_INTS * 2;
+
+  for J := 0 to System.Pred(CURVE25519_FE_INTS) do
+  begin
+    x[J] := Fm_table[pos + J];
+    y[J] := Fm_table[pos + CURVE25519_FE_INTS + J];
+  end;
+
+  result := CreatePoint(x, y)
 end;
 
 end.

+ 44 - 9
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP256K1Custom.pas

@@ -211,8 +211,8 @@ type
   strict private
 
   type
-    TSecP256K1LookupTable = class sealed(TInterfacedObject,
-      ISecP256K1LookupTable, IECLookupTable)
+    TSecP256K1LookupTable = class sealed(TAbstractECLookupTable,
+      ISecP256K1LookupTable)
 
     strict private
     var
@@ -220,16 +220,19 @@ type
       Fm_table: TCryptoLibUInt32Array;
       Fm_size: Int32;
 
-      function GetSize: Int32; virtual;
+      function CreatePoint(const x, y: TCryptoLibUInt32Array): IECPoint;
+
+    strict protected
+
+      function GetSize: Int32; override;
 
     public
 
       constructor Create(const outer: ISecP256K1Curve;
         const table: TCryptoLibUInt32Array; size: Int32);
 
-      function Lookup(index: Int32): IECPoint; virtual;
-
-      property size: Int32 read GetSize;
+      function Lookup(index: Int32): IECPoint; override;
+      function LookupVar(index: Int32): IECPoint; override;
 
     end;
 
@@ -1126,6 +1129,21 @@ begin
   Fm_size := size;
 end;
 
+function TSecP256K1Curve.TSecP256K1LookupTable.CreatePoint(const x,
+  y: TCryptoLibUInt32Array): IECPoint;
+var
+  XFieldElement, YFieldElement: ISecP256K1FieldElement;
+  SECP256K1_AFFINE_ZS: TCryptoLibGenericArray<IECFieldElement>;
+begin
+  SECP256K1_AFFINE_ZS := TCryptoLibGenericArray<IECFieldElement>.Create
+    (TSecP256K1FieldElement.Create(TBigInteger.One) as ISecP256K1FieldElement);
+
+  XFieldElement := TSecP256K1FieldElement.Create(x);
+  YFieldElement := TSecP256K1FieldElement.Create(y);
+  result := Fm_outer.CreateRawPoint(XFieldElement, YFieldElement,
+    SECP256K1_AFFINE_ZS, false);
+end;
+
 function TSecP256K1Curve.TSecP256K1LookupTable.GetSize: Int32;
 begin
   result := Fm_size;
@@ -1154,9 +1172,26 @@ begin
     pos := pos + (SECP256K1_FE_INTS * 2);
   end;
 
-  result := Fm_outer.CreateRawPoint(TSecP256K1FieldElement.Create(x)
-    as ISecP256K1FieldElement, TSecP256K1FieldElement.Create(y)
-    as ISecP256K1FieldElement, false);
+  result := CreatePoint(x, y);
+end;
+
+function TSecP256K1Curve.TSecP256K1LookupTable.LookupVar(index: Int32)
+  : IECPoint;
+var
+  x, y: TCryptoLibUInt32Array;
+  pos, J: Int32;
+begin
+  x := TNat256.Create();
+  y := TNat256.Create();
+  pos := index * SECP256K1_FE_INTS * 2;
+
+  for J := 0 to System.Pred(SECP256K1_FE_INTS) do
+  begin
+    x[J] := Fm_table[pos + J];
+    y[J] := Fm_table[pos + SECP256K1_FE_INTS + J];
+  end;
+
+  result := CreatePoint(x, y);
 end;
 
 end.

+ 44 - 9
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP256R1Custom.pas

@@ -212,8 +212,8 @@ type
   strict private
 
   type
-    TSecP256R1LookupTable = class sealed(TInterfacedObject,
-      ISecP256R1LookupTable, IECLookupTable)
+    TSecP256R1LookupTable = class sealed(TAbstractECLookupTable,
+      ISecP256R1LookupTable)
 
     strict private
     var
@@ -221,16 +221,19 @@ type
       Fm_table: TCryptoLibUInt32Array;
       Fm_size: Int32;
 
-      function GetSize: Int32; virtual;
+      function CreatePoint(const x, y: TCryptoLibUInt32Array): IECPoint;
+
+    strict protected
+
+      function GetSize: Int32; override;
 
     public
 
       constructor Create(const outer: ISecP256R1Curve;
         const table: TCryptoLibUInt32Array; size: Int32);
 
-      function Lookup(index: Int32): IECPoint; virtual;
-
-      property size: Int32 read GetSize;
+      function Lookup(index: Int32): IECPoint; override;
+      function LookupVar(index: Int32): IECPoint; override;
 
     end;
 
@@ -1269,6 +1272,21 @@ begin
   Fm_size := size;
 end;
 
+function TSecP256R1Curve.TSecP256R1LookupTable.CreatePoint(const x,
+  y: TCryptoLibUInt32Array): IECPoint;
+var
+  XFieldElement, YFieldElement: ISecP256R1FieldElement;
+  SECP256R1_AFFINE_ZS: TCryptoLibGenericArray<IECFieldElement>;
+begin
+  SECP256R1_AFFINE_ZS := TCryptoLibGenericArray<IECFieldElement>.Create
+    (TSecP256R1FieldElement.Create(TBigInteger.One) as ISecP256R1FieldElement);
+
+  XFieldElement := TSecP256R1FieldElement.Create(x);
+  YFieldElement := TSecP256R1FieldElement.Create(y);
+  result := Fm_outer.CreateRawPoint(XFieldElement, YFieldElement,
+    SECP256R1_AFFINE_ZS, false);
+end;
+
 function TSecP256R1Curve.TSecP256R1LookupTable.GetSize: Int32;
 begin
   result := Fm_size;
@@ -1297,9 +1315,26 @@ begin
     pos := pos + (SECP256R1_FE_INTS * 2);
   end;
 
-  result := Fm_outer.CreateRawPoint(TSecP256R1FieldElement.Create(x)
-    as ISecP256R1FieldElement, TSecP256R1FieldElement.Create(y)
-    as ISecP256R1FieldElement, false);
+  result := CreatePoint(x, y);
+end;
+
+function TSecP256R1Curve.TSecP256R1LookupTable.LookupVar(index: Int32)
+  : IECPoint;
+var
+  x, y: TCryptoLibUInt32Array;
+  pos, J: Int32;
+begin
+  x := TNat256.Create();
+  y := TNat256.Create();
+  pos := index * SECP256R1_FE_INTS * 2;
+
+  for J := 0 to System.Pred(SECP256R1_FE_INTS) do
+  begin
+    x[J] := Fm_table[pos + J];
+    y[J] := Fm_table[pos + SECP256R1_FE_INTS + J];
+  end;
+
+  result := CreatePoint(x, y);
 end;
 
 end.

+ 44 - 9
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP384R1Custom.pas

@@ -210,8 +210,8 @@ type
   strict private
 
   type
-    TSecP384R1LookupTable = class sealed(TInterfacedObject,
-      ISecP384R1LookupTable, IECLookupTable)
+    TSecP384R1LookupTable = class sealed(TAbstractECLookupTable,
+      ISecP384R1LookupTable)
 
     strict private
     var
@@ -219,16 +219,19 @@ type
       Fm_table: TCryptoLibUInt32Array;
       Fm_size: Int32;
 
-      function GetSize: Int32; virtual;
+      function CreatePoint(const x, y: TCryptoLibUInt32Array): IECPoint;
+
+    strict protected
+
+      function GetSize: Int32; override;
 
     public
 
       constructor Create(const outer: ISecP384R1Curve;
         const table: TCryptoLibUInt32Array; size: Int32);
 
-      function Lookup(index: Int32): IECPoint; virtual;
-
-      property size: Int32 read GetSize;
+      function Lookup(index: Int32): IECPoint; override;
+      function LookupVar(index: Int32): IECPoint; override;
 
     end;
 
@@ -1277,6 +1280,21 @@ begin
   Fm_size := size;
 end;
 
+function TSecP384R1Curve.TSecP384R1LookupTable.CreatePoint(const x,
+  y: TCryptoLibUInt32Array): IECPoint;
+var
+  XFieldElement, YFieldElement: ISecP384R1FieldElement;
+  SECP384R1_AFFINE_ZS: TCryptoLibGenericArray<IECFieldElement>;
+begin
+  SECP384R1_AFFINE_ZS := TCryptoLibGenericArray<IECFieldElement>.Create
+    (TSecP384R1FieldElement.Create(TBigInteger.One) as ISecP384R1FieldElement);
+
+  XFieldElement := TSecP384R1FieldElement.Create(x);
+  YFieldElement := TSecP384R1FieldElement.Create(y);
+  result := Fm_outer.CreateRawPoint(XFieldElement, YFieldElement,
+    SECP384R1_AFFINE_ZS, false);
+end;
+
 function TSecP384R1Curve.TSecP384R1LookupTable.GetSize: Int32;
 begin
   result := Fm_size;
@@ -1305,9 +1323,26 @@ begin
     pos := pos + (SECP384R1_FE_INTS * 2);
   end;
 
-  result := Fm_outer.CreateRawPoint(TSecP384R1FieldElement.Create(x)
-    as ISecP384R1FieldElement, TSecP384R1FieldElement.Create(y)
-    as ISecP384R1FieldElement, false);
+  result := CreatePoint(x, y)
+end;
+
+function TSecP384R1Curve.TSecP384R1LookupTable.LookupVar(index: Int32)
+  : IECPoint;
+var
+  x, y: TCryptoLibUInt32Array;
+  pos, J: Int32;
+begin
+  x := TNat.Create(SECP384R1_FE_INTS);
+  y := TNat.Create(SECP384R1_FE_INTS);
+  pos := index * SECP384R1_FE_INTS * 2;
+
+  for J := 0 to System.Pred(SECP384R1_FE_INTS) do
+  begin
+    x[J] := Fm_table[pos + J];
+    y[J] := Fm_table[pos + SECP384R1_FE_INTS + J];
+  end;
+
+  result := CreatePoint(x, y)
 end;
 
 end.

+ 43 - 8
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP521R1Custom.pas

@@ -207,7 +207,7 @@ type
   strict private
 
   type
-    TSecP521R1LookupTable = class sealed(TInterfacedObject,
+    TSecP521R1LookupTable = class sealed(TAbstractECLookupTable,
       ISecP521R1LookupTable, IECLookupTable)
 
     strict private
@@ -216,16 +216,19 @@ type
       Fm_table: TCryptoLibUInt32Array;
       Fm_size: Int32;
 
-      function GetSize: Int32; virtual;
+      function CreatePoint(const x, y: TCryptoLibUInt32Array): IECPoint;
+
+    strict protected
+
+      function GetSize: Int32; override;
 
     public
 
       constructor Create(const outer: ISecP521R1Curve;
         const table: TCryptoLibUInt32Array; size: Int32);
 
-      function Lookup(index: Int32): IECPoint; virtual;
-
-      property size: Int32 read GetSize;
+      function Lookup(index: Int32): IECPoint; override;
+      function LookupVar(index: Int32): IECPoint; override;
 
     end;
 
@@ -1070,6 +1073,21 @@ begin
   Fm_size := size;
 end;
 
+function TSecP521R1Curve.TSecP521R1LookupTable.CreatePoint(const x,
+  y: TCryptoLibUInt32Array): IECPoint;
+var
+  XFieldElement, YFieldElement: ISecP521R1FieldElement;
+  SECP521R1_AFFINE_ZS: TCryptoLibGenericArray<IECFieldElement>;
+begin
+  SECP521R1_AFFINE_ZS := TCryptoLibGenericArray<IECFieldElement>.Create
+    (TSecP521R1FieldElement.Create(TBigInteger.One) as ISecP521R1FieldElement);
+
+  XFieldElement := TSecP521R1FieldElement.Create(x);
+  YFieldElement := TSecP521R1FieldElement.Create(y);
+  result := Fm_outer.CreateRawPoint(XFieldElement, YFieldElement,
+    SECP521R1_AFFINE_ZS, false);
+end;
+
 function TSecP521R1Curve.TSecP521R1LookupTable.GetSize: Int32;
 begin
   result := Fm_size;
@@ -1098,9 +1116,26 @@ begin
     pos := pos + (SECP521R1_FE_INTS * 2);
   end;
 
-  result := Fm_outer.CreateRawPoint(TSecP521R1FieldElement.Create(x)
-    as ISecP521R1FieldElement, TSecP521R1FieldElement.Create(y)
-    as ISecP521R1FieldElement, false);
+  result := CreatePoint(x, y);
+end;
+
+function TSecP521R1Curve.TSecP521R1LookupTable.LookupVar(index: Int32)
+  : IECPoint;
+var
+  x, y: TCryptoLibUInt32Array;
+  pos, J: Int32;
+begin
+  x := TNat.Create(SECP521R1_FE_INTS);
+  y := TNat.Create(SECP521R1_FE_INTS);
+  pos := index * SECP521R1_FE_INTS * 2;
+
+  for J := 0 to System.Pred(SECP521R1_FE_INTS) do
+  begin
+    x[J] := x[J] xor Fm_table[pos + J];
+    y[J] := y[J] xor Fm_table[pos + SECP521R1_FE_INTS + J];
+  end;
+
+  result := CreatePoint(x, y);
 end;
 
 end.

+ 44 - 9
CryptoLib/src/Math/EC/Custom/Sec/ClpSecT283Custom.pas

@@ -258,8 +258,8 @@ type
   strict private
 
   type
-    TSecT283K1LookupTable = class sealed(TInterfacedObject,
-      ISecT283K1LookupTable, IECLookupTable)
+    TSecT283K1LookupTable = class sealed(TAbstractECLookupTable,
+      ISecT283K1LookupTable)
 
     strict private
     var
@@ -267,16 +267,19 @@ type
       Fm_table: TCryptoLibUInt64Array;
       Fm_size: Int32;
 
-      function GetSize: Int32; virtual;
+      function CreatePoint(const x, y: TCryptoLibUInt64Array): IECPoint;
+
+    strict protected
+
+      function GetSize: Int32; override;
 
     public
 
       constructor Create(const outer: ISecT283K1Curve;
         const table: TCryptoLibUInt64Array; size: Int32);
 
-      function Lookup(index: Int32): IECPoint; virtual;
-
-      property size: Int32 read GetSize;
+      function Lookup(index: Int32): IECPoint; override;
+      function LookupVar(index: Int32): IECPoint; override;
 
     end;
 
@@ -1591,6 +1594,21 @@ begin
   Fm_size := size;
 end;
 
+function TSecT283K1Curve.TSecT283K1LookupTable.CreatePoint(const x,
+  y: TCryptoLibUInt64Array): IECPoint;
+var
+  XFieldElement, YFieldElement: ISecT283FieldElement;
+  SECT283K1_AFFINE_ZS: TCryptoLibGenericArray<IECFieldElement>;
+begin
+  SECT283K1_AFFINE_ZS := TCryptoLibGenericArray<IECFieldElement>.Create
+    (TSecT283FieldElement.Create(TBigInteger.One) as ISecT283FieldElement);
+
+  XFieldElement := TSecT283FieldElement.Create(x);
+  YFieldElement := TSecT283FieldElement.Create(y);
+  result := Fm_outer.CreateRawPoint(XFieldElement, YFieldElement,
+    SECT283K1_AFFINE_ZS, false);
+end;
+
 function TSecT283K1Curve.TSecT283K1LookupTable.GetSize: Int32;
 begin
   result := Fm_size;
@@ -1619,9 +1637,26 @@ begin
     pos := pos + (SECT283K1_FE_LONGS * 2);
   end;
 
-  result := Fm_outer.CreateRawPoint(TSecT283FieldElement.Create(x)
-    as ISecT283FieldElement, TSecT283FieldElement.Create(y)
-    as ISecT283FieldElement, false);
+  result := CreatePoint(x, y);
+end;
+
+function TSecT283K1Curve.TSecT283K1LookupTable.LookupVar(index: Int32)
+  : IECPoint;
+var
+  x, y: TCryptoLibUInt64Array;
+  pos, j: Int32;
+begin
+  x := TNat320.Create64();
+  y := TNat320.Create64();
+  pos := index * SECT283K1_FE_LONGS * 2;
+
+  for j := 0 to System.Pred(SECT283K1_FE_LONGS) do
+  begin
+    x[j] := Fm_table[pos + j];
+    y[j] := Fm_table[pos + SECT283K1_FE_LONGS + j];
+  end;
+
+  result := CreatePoint(x, y);
 end;
 
 end.