Browse Source

update cryptolib

Ugochukwu Mmaduekwe 6 years ago
parent
commit
476bcfd81b
78 changed files with 5984 additions and 3726 deletions
  1. 273 0
      src/libraries/cryptolib4pascal/ClpAESPRNGRandom.pas
  2. 0 101
      src/libraries/cryptolib4pascal/ClpAbstractECMultiplier.pas
  3. 19 2
      src/libraries/cryptolib4pascal/ClpArrayUtils.pas
  4. 24 42
      src/libraries/cryptolib4pascal/ClpAsn1Objects.pas
  5. 48 0
      src/libraries/cryptolib4pascal/ClpBits.pas
  6. 1 1
      src/libraries/cryptolib4pascal/ClpBsiObjectIdentifiers.pas
  7. 90 0
      src/libraries/cryptolib4pascal/ClpCryptLibObjectIdentifiers.pas
  8. 3 36
      src/libraries/cryptolib4pascal/ClpCryptoApiRandomGenerator.pas
  9. 55 25
      src/libraries/cryptolib4pascal/ClpCurve25519Custom.pas
  10. 48 42
      src/libraries/cryptolib4pascal/ClpCustomNamedCurves.pas
  11. 1 1
      src/libraries/cryptolib4pascal/ClpDHKeyGeneratorHelper.pas
  12. 1 1
      src/libraries/cryptolib4pascal/ClpDHParametersHelper.pas
  13. 5 25
      src/libraries/cryptolib4pascal/ClpDigestRandomGenerator.pas
  14. 1 1
      src/libraries/cryptolib4pascal/ClpDsaKeyPairGenerator.pas
  15. 242 973
      src/libraries/cryptolib4pascal/ClpECAlgorithms.pas
  16. 319 105
      src/libraries/cryptolib4pascal/ClpECC.pas
  17. 1534 0
      src/libraries/cryptolib4pascal/ClpECCompUtilities.pas
  18. 7 23
      src/libraries/cryptolib4pascal/ClpECDomainParameters.pas
  19. 1 1
      src/libraries/cryptolib4pascal/ClpECDsaSigner.pas
  20. 3 3
      src/libraries/cryptolib4pascal/ClpECKeyPairGenerator.pas
  21. 102 45
      src/libraries/cryptolib4pascal/ClpECNRSigner.pas
  22. 409 191
      src/libraries/cryptolib4pascal/ClpEd25519.pas
  23. 75 0
      src/libraries/cryptolib4pascal/ClpEndoPreCompInfo.pas
  24. 0 130
      src/libraries/cryptolib4pascal/ClpFixedPointCombMultiplier.pas
  25. 0 219
      src/libraries/cryptolib4pascal/ClpFixedPointUtilities.pas
  26. 0 106
      src/libraries/cryptolib4pascal/ClpGlvMultiplier.pas
  27. 92 0
      src/libraries/cryptolib4pascal/ClpGlvTypeAEndomorphism.pas
  28. 81 0
      src/libraries/cryptolib4pascal/ClpGlvTypeAParameters.pas
  29. 14 55
      src/libraries/cryptolib4pascal/ClpGlvTypeBEndomorphism.pas
  30. 20 59
      src/libraries/cryptolib4pascal/ClpGlvTypeBParameters.pas
  31. 1 1
      src/libraries/cryptolib4pascal/ClpICurve25519Custom.pas
  32. 19 2
      src/libraries/cryptolib4pascal/ClpIECC.pas
  33. 2 0
      src/libraries/cryptolib4pascal/ClpIECNRSigner.pas
  34. 47 0
      src/libraries/cryptolib4pascal/ClpIEndoPreCompInfo.pas
  35. 4 4
      src/libraries/cryptolib4pascal/ClpIGlvTypeAEndomorphism.pas
  36. 14 17
      src/libraries/cryptolib4pascal/ClpIGlvTypeAParameters.pas
  37. 0 2
      src/libraries/cryptolib4pascal/ClpIGlvTypeBEndomorphism.pas
  38. 5 12
      src/libraries/cryptolib4pascal/ClpIGlvTypeBParameters.pas
  39. 30 3
      src/libraries/cryptolib4pascal/ClpIMultipliers.pas
  40. 6 0
      src/libraries/cryptolib4pascal/ClpIRandomNumberGenerator.pas
  41. 52 0
      src/libraries/cryptolib4pascal/ClpIScalarSplitParameters.pas
  42. 5 4
      src/libraries/cryptolib4pascal/ClpIScaleXNegateYPointMap.pas
  43. 3 7
      src/libraries/cryptolib4pascal/ClpIScaleYNegateXPointMap.pas
  44. 1 1
      src/libraries/cryptolib4pascal/ClpISecP256K1Custom.pas
  45. 1 1
      src/libraries/cryptolib4pascal/ClpISecP256R1Custom.pas
  46. 1 1
      src/libraries/cryptolib4pascal/ClpISecP384R1Custom.pas
  47. 1 1
      src/libraries/cryptolib4pascal/ClpISecP521R1Custom.pas
  48. 1 1
      src/libraries/cryptolib4pascal/ClpISecT283Custom.pas
  49. 2 2
      src/libraries/cryptolib4pascal/ClpIValidityPrecompInfo.pas
  50. 18 0
      src/libraries/cryptolib4pascal/ClpIWNafPreCompInfo.pas
  51. 621 0
      src/libraries/cryptolib4pascal/ClpMultipliers.pas
  52. 259 78
      src/libraries/cryptolib4pascal/ClpNat.pas
  53. 6 6
      src/libraries/cryptolib4pascal/ClpNat192.pas
  54. 6 6
      src/libraries/cryptolib4pascal/ClpNat256.pas
  55. 329 113
      src/libraries/cryptolib4pascal/ClpOSRandom.pas
  56. 0 291
      src/libraries/cryptolib4pascal/ClpPcgRandomMinimal.pas
  57. 13 33
      src/libraries/cryptolib4pascal/ClpRandomNumberGenerator.pas
  58. 131 0
      src/libraries/cryptolib4pascal/ClpScalarSplitParameters.pas
  59. 56 0
      src/libraries/cryptolib4pascal/ClpScaleXNegateYPointMap.pas
  60. 56 0
      src/libraries/cryptolib4pascal/ClpScaleYNegateXPointMap.pas
  61. 184 203
      src/libraries/cryptolib4pascal/ClpSecNamedCurves.pas
  62. 48 22
      src/libraries/cryptolib4pascal/ClpSecP256K1Custom.pas
  63. 48 22
      src/libraries/cryptolib4pascal/ClpSecP256R1Custom.pas
  64. 49 23
      src/libraries/cryptolib4pascal/ClpSecP384R1Custom.pas
  65. 48 22
      src/libraries/cryptolib4pascal/ClpSecP521R1Custom.pas
  66. 105 24
      src/libraries/cryptolib4pascal/ClpSecT283Custom.pas
  67. 6 1
      src/libraries/cryptolib4pascal/ClpSecureRandom.pas
  68. 15 0
      src/libraries/cryptolib4pascal/ClpStringUtils.pas
  69. 78 67
      src/libraries/cryptolib4pascal/ClpTeleTrusTNamedCurves.pas
  70. 12 12
      src/libraries/cryptolib4pascal/ClpValidityPrecompInfo.pas
  71. 0 191
      src/libraries/cryptolib4pascal/ClpWNafL2RMultiplier.pas
  72. 101 22
      src/libraries/cryptolib4pascal/ClpWNafPreCompInfo.pas
  73. 0 276
      src/libraries/cryptolib4pascal/ClpWTauNafMultiplier.pas
  74. 32 8
      src/libraries/cryptolib4pascal/ClpX25519Field.pas
  75. 10 20
      src/libraries/cryptolib4pascal/ClpX9ECParametersHolder.pas
  76. 59 34
      src/libraries/cryptolib4pascal/CryptoLib.inc
  77. 4 0
      src/libraries/cryptolib4pascal/CryptoLibHelper.inc
  78. 27 6
      src/libraries/cryptolib4pascal/README.md

+ 273 - 0
src/libraries/cryptolib4pascal/ClpAESPRNGRandom.pas

@@ -0,0 +1,273 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAESPRNGRandom;
+
+{$I CryptoLib.inc}
+
+interface
+
+uses
+  SyncObjs,
+  ClpAesEngine,
+  ClpIAesEngine,
+  ClpIBlockCipher,
+  ClpIKeyParameter,
+  ClpKeyParameter,
+  ClpIBufferedCipher,
+  ClpIBufferedBlockCipher,
+  ClpBufferedBlockCipher,
+  ClpArrayUtils,
+  ClpOSRandom,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SInvalidAESRNGSeedLength =
+    'AES RNG Seed Length must be either one of these "128/192/256 bits".';
+
+type
+  IAESPRNGRandom = interface(IInterface)
+    ['{DE2F9387-CD63-475F-AD4B-EA0692790FB2}']
+
+    procedure FillBytes(const data: TCryptoLibByteArray);
+    procedure FillNonZeroBytes(const data: TCryptoLibByteArray);
+
+  end;
+
+type
+  TAESPRNGRandom = class sealed(TInterfacedObject, IAESPRNGRandom)
+
+  strict private
+  const
+    COUNTER_SIZE = Int32(16);
+    class var
+
+      FDefaultInstance: IAESPRNGRandom;
+
+  var
+    FLock: TCriticalSection;
+    FCounter: TCryptoLibByteArray;
+    FAESRNGSeedLength, FBytesSinceSeed, FReseedAfterBytes: Int32;
+    FCipher: IBufferedCipher;
+
+    class function GetDefaultInstance: IAESPRNGRandom; static; inline;
+
+    class procedure GetRawEntropy(const AEntropy: TCryptoLibByteArray); inline;
+
+    class procedure Boot(); static;
+    class constructor CreateAESPRNGRandom();
+    class destructor DestroyAESPRNGRandom();
+
+    class procedure ValidateAESRNGSeedLength(ASeedLength: Int32);
+
+    constructor Create(const AAESRNGSeed: TCryptoLibByteArray;
+      AReseedAfterBytes: Int32); overload;
+
+    procedure DoIncrementCounter();
+
+    procedure DoSeed(const AAESRNGSeed: TCryptoLibByteArray);
+
+  public
+    constructor Create(AAESRNGSeedLength: Int32 = 32;
+      AReseedAfterBytes: Int32 = 1024 * 1024); overload;
+
+    destructor Destroy; override;
+
+    procedure FillBytes(const data: TCryptoLibByteArray); overload;
+    procedure FillNonZeroBytes(const data: TCryptoLibByteArray); overload;
+
+    class procedure GetBytes(const data: TCryptoLibByteArray); overload; static;
+    class procedure GetNonZeroBytes(const data: TCryptoLibByteArray);
+      overload; static;
+
+    class property DefaultInstance: IAESPRNGRandom read GetDefaultInstance;
+
+  end;
+
+implementation
+
+{ TAESPRNGRandom }
+
+class function TAESPRNGRandom.GetDefaultInstance: IAESPRNGRandom;
+begin
+  result := FDefaultInstance;
+end;
+
+class procedure TAESPRNGRandom.ValidateAESRNGSeedLength(ASeedLength: Int32);
+begin
+  if ((ASeedLength < 16) or (ASeedLength > 32) or ((ASeedLength and 7) <> 0))
+  then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SInvalidAESRNGSeedLength);
+  end;
+end;
+
+class procedure TAESPRNGRandom.GetRawEntropy(const AEntropy
+  : TCryptoLibByteArray);
+begin
+  TOSRandom.GetBytes(AEntropy);
+end;
+
+class procedure TAESPRNGRandom.Boot;
+begin
+  if FDefaultInstance = Nil then
+  begin
+    FDefaultInstance := TAESPRNGRandom.Create();
+  end;
+end;
+
+procedure TAESPRNGRandom.DoIncrementCounter;
+var
+  i: Int32;
+begin
+  for i := System.Low(FCounter) to System.High(FCounter) do
+  begin
+    System.Inc(FCounter[i]);
+    // Check whether we need to loop again to carry the one.
+    if (FCounter[i] <> 0) then
+    begin
+      break;
+    end;
+  end;
+end;
+
+procedure TAESPRNGRandom.DoSeed(const AAESRNGSeed: TCryptoLibByteArray);
+var
+  LKeyParameter: IKeyParameter;
+begin
+  LKeyParameter := TKeyParameter.Create(AAESRNGSeed);
+  FLock.Acquire;
+  try
+    FCipher.Init(True, LKeyParameter);
+    FBytesSinceSeed := 0;
+  finally
+    FLock.Release;
+  end;
+end;
+
+constructor TAESPRNGRandom.Create(const AAESRNGSeed: TCryptoLibByteArray;
+  AReseedAfterBytes: Int32);
+var
+  LAesEngine: IAesEngine;
+  LBlockCipher: IBlockCipher;
+  LAESRNGSeed: TCryptoLibByteArray;
+begin
+  Inherited Create();
+  LAESRNGSeed := System.Copy(AAESRNGSeed);
+  FLock := TCriticalSection.Create;
+  // Set up engine
+  LAesEngine := TAesEngine.Create();
+  LBlockCipher := LAesEngine as IBlockCipher; // ECB no padding
+  FCipher := TBufferedBlockCipher.Create(LBlockCipher) as IBufferedBlockCipher;
+  System.SetLength(FCounter, COUNTER_SIZE);
+  FAESRNGSeedLength := System.Length(LAESRNGSeed);
+  FReseedAfterBytes := AReseedAfterBytes;
+  ValidateAESRNGSeedLength(FAESRNGSeedLength);
+  DoSeed(LAESRNGSeed);
+  TArrayUtils.ZeroFill(LAESRNGSeed); // clear key from memory
+end;
+
+constructor TAESPRNGRandom.Create(AAESRNGSeedLength, AReseedAfterBytes: Int32);
+var
+  LSeed: TCryptoLibByteArray;
+begin
+  System.SetLength(LSeed, AAESRNGSeedLength);
+  GetRawEntropy(LSeed); // pure entropy from OS
+  Create(LSeed, AReseedAfterBytes);
+  TArrayUtils.ZeroFill(LSeed); // clear seed from memory
+end;
+
+destructor TAESPRNGRandom.Destroy;
+begin
+  FLock.Free;
+  inherited Destroy;
+end;
+
+procedure TAESPRNGRandom.FillBytes(const data: TCryptoLibByteArray);
+var
+  LDataLength, LDatum, LResultLength: Int32;
+  LSeed, LResult: TCryptoLibByteArray;
+begin
+  LDataLength := System.Length(data);
+  if LDataLength <= 0 then
+  begin
+    Exit;
+  end;
+
+  if (FBytesSinceSeed > FReseedAfterBytes) then
+  begin
+    System.SetLength(LSeed, FAESRNGSeedLength);
+    GetRawEntropy(LSeed); // pure entropy from OS
+    DoSeed(LSeed);
+    TArrayUtils.ZeroFill(LSeed); // clear seed from memory
+  end;
+
+  LDatum := 0;
+
+  FLock.Acquire;
+  try
+    while (LDataLength shr 4) > 0 do
+    begin
+      DoIncrementCounter;
+      LResultLength := FCipher.DoFinal(FCounter, data, LDatum);
+
+      System.Inc(LDatum, LResultLength);
+      System.Inc(FBytesSinceSeed, LResultLength);
+      System.Dec(LDataLength, LResultLength);
+    end;
+
+    if LDataLength > 0 then
+    begin
+      DoIncrementCounter;
+      LResult := FCipher.DoFinal(FCounter);
+      System.Move(LResult[0], data[LDatum], LDataLength * System.SizeOf(Byte));
+      System.Inc(FBytesSinceSeed, LDataLength);
+    end;
+
+  finally
+    FLock.Release;
+  end;
+end;
+
+procedure TAESPRNGRandom.FillNonZeroBytes(const data: TCryptoLibByteArray);
+begin
+  repeat
+    FillBytes(data);
+  until (TArrayUtils.NoZeroes(data));
+end;
+
+class constructor TAESPRNGRandom.CreateAESPRNGRandom;
+begin
+  TAESPRNGRandom.Boot();
+end;
+
+class destructor TAESPRNGRandom.DestroyAESPRNGRandom;
+begin
+  FDefaultInstance := Nil;
+end;
+
+class procedure TAESPRNGRandom.GetBytes(const data: TCryptoLibByteArray);
+begin
+  DefaultInstance.FillBytes(data);
+end;
+
+class procedure TAESPRNGRandom.GetNonZeroBytes(const data: TCryptoLibByteArray);
+begin
+  DefaultInstance.FillNonZeroBytes(data);
+end;
+
+end.

+ 0 - 101
src/libraries/cryptolib4pascal/ClpAbstractECMultiplier.pas

@@ -1,101 +0,0 @@
-{ *********************************************************************************** }
-{ *                              CryptoLib Library                                  * }
-{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
-{ *                 Github Repository <https://github.com/Xor-el>                   * }
-
-{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
-{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
-
-{ *                              Acknowledgements:                                  * }
-{ *                                                                                 * }
-{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
-{ *                           development of this library                           * }
-
-{ * ******************************************************************************* * }
-
-(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
-
-unit ClpAbstractECMultiplier;
-
-{$I CryptoLib.inc}
-
-interface
-
-uses
-  ClpBigInteger,
-  ClpIECC,
-  ClpIAbstractECMultiplier,
-  ClpECAlgorithms;
-
-type
-  TAbstractECMultiplier = class abstract(TInterfacedObject,
-    IAbstractECMultiplier, IECMultiplier)
-
-  strict protected
-
-    function CheckResult(const p: IECPoint): IECPoint; virtual;
-    function MultiplyPositive(const p: IECPoint; const k: TBigInteger)
-      : IECPoint; virtual; abstract;
-
-  public
-
-    constructor Create();
-    destructor Destroy; override;
-    function Multiply(const p: IECPoint; const k: TBigInteger)
-      : IECPoint; virtual;
-
-  end;
-
-implementation
-
-{ TAbstractECMultiplier }
-
-function TAbstractECMultiplier.CheckResult(const p: IECPoint): IECPoint;
-begin
-  result := TECAlgorithms.ImplCheckResult(p);
-end;
-
-constructor TAbstractECMultiplier.Create;
-begin
-  Inherited Create();
-end;
-
-destructor TAbstractECMultiplier.Destroy;
-begin
-  inherited Destroy;
-end;
-
-function TAbstractECMultiplier.Multiply(const p: IECPoint; const k: TBigInteger)
-  : IECPoint;
-var
-  positive: IECPoint;
-  sign: Int32;
-begin
-
-  sign := k.SignValue;
-  if ((sign = 0) or (p.IsInfinity)) then
-  begin
-    result := p.Curve.Infinity;
-    Exit;
-  end;
-
-  positive := MultiplyPositive(p, k.Abs());
-
-  if sign > 0 then
-  begin
-    result := positive
-  end
-  else
-  begin
-    result := positive.Negate();
-  end;
-
-  // /*
-  // * Although the various multipliers ought not to produce invalid output under normal
-  // * circumstances, a final check here is advised to guard against fault attacks.
-  // */
-  result := CheckResult(result);
-
-end;
-
-end.

+ 19 - 2
src/libraries/cryptolib4pascal/ClpArrayUtils.pas

@@ -97,6 +97,8 @@ type
 
 
     class procedure ZeroFill(const buf: TCryptoLibByteArray); static;
     class procedure ZeroFill(const buf: TCryptoLibByteArray); static;
 
 
+    class function NoZeroes(const data: TCryptoLibByteArray): Boolean; static;
+
   end;
   end;
 
 
 implementation
 implementation
@@ -116,6 +118,21 @@ begin
   Result := newLength;
   Result := newLength;
 end;
 end;
 
 
+class function TArrayUtils.NoZeroes(const data: TCryptoLibByteArray): Boolean;
+var
+  i: Int32;
+begin
+  Result := True;
+  for i := System.Low(data) to System.High(data) do
+  begin
+    if data[i] = 0 then
+    begin
+      Result := False;
+      Exit;
+    end;
+  end;
+end;
+
 class function TArrayUtils.Concatenate(const A, B: TCryptoLibByteArray)
 class function TArrayUtils.Concatenate(const A, B: TCryptoLibByteArray)
   : TCryptoLibByteArray;
   : TCryptoLibByteArray;
 var
 var
@@ -173,7 +190,7 @@ class function TArrayUtils.AreEqual(const A, B: TCryptoLibByteArray): Boolean;
 begin
 begin
   if System.Length(A) <> System.Length(B) then
   if System.Length(A) <> System.Length(B) then
   begin
   begin
-    Result := false;
+    Result := False;
     Exit;
     Exit;
   end;
   end;
 
 
@@ -198,7 +215,7 @@ class function TArrayUtils.AreEqual(const A, B: TCryptoLibInt32Array): Boolean;
 begin
 begin
   if System.Length(A) <> System.Length(B) then
   if System.Length(A) <> System.Length(B) then
   begin
   begin
-    Result := false;
+    Result := False;
     Exit;
     Exit;
   end;
   end;
 
 

+ 24 - 42
src/libraries/cryptolib4pascal/ClpAsn1Objects.pas

@@ -4838,51 +4838,48 @@ end;
 class function TDerObjectIdentifier.IsValidBranchID(const branchID: String;
 class function TDerObjectIdentifier.IsValidBranchID(const branchID: String;
   start: Int32): Boolean;
   start: Int32): Boolean;
 var
 var
-  periodAllowed: Boolean;
-  Pos: Int32;
+  digitCount, Pos: Int32;
   ch: Char;
   ch: Char;
 begin
 begin
-  periodAllowed := False;
+  digitCount := 0;
 
 
   Pos := System.length(branchID) + 1;
   Pos := System.length(branchID) + 1;
   System.Dec(Pos);
   System.Dec(Pos);
+
   while (Pos >= start) do
   while (Pos >= start) do
   begin
   begin
     ch := branchID[Pos];
     ch := branchID[Pos];
 
 
-    // TODO Leading zeroes?
-    // if (('0' <= ch) and (ch <= '9')) then
-    // begin
-    // periodAllowed := true;
-    // continue;
-    // end;
-
-    // TODO Leading zeroes?
-    if (CharInSet(ch, ['0' .. '9'])) then
-    begin
-      periodAllowed := True;
-      System.Dec(Pos);
-      continue;
-    end;
-
     if (ch = '.') then
     if (ch = '.') then
     begin
     begin
-      if (not(periodAllowed)) then
+      if ((digitCount = 0) or ((digitCount > 1) and (branchID[Pos + 1] = '0')))
+      then
       begin
       begin
         result := False;
         result := False;
         Exit;
         Exit;
       end;
       end;
 
 
-      periodAllowed := False;
-      System.Dec(Pos);
-      continue;
+      digitCount := 0;
+    end
+    else if (CharInSet(ch, ['0' .. '9'])) then
+    begin
+      System.Inc(digitCount);
+    end
+    else
+    begin
+      result := False;
+      Exit;
     end;
     end;
+    System.Dec(Pos);
+  end;
 
 
+  if ((digitCount = 0) or ((digitCount > 1) and (branchID[Pos + 1] = '0'))) then
+  begin
     result := False;
     result := False;
     Exit;
     Exit;
   end;
   end;
 
 
-  result := periodAllowed;
+  result := True;
 end;
 end;
 
 
 class function TDerObjectIdentifier.IsValidIdentifier(const identifier
 class function TDerObjectIdentifier.IsValidIdentifier(const identifier
@@ -4897,11 +4894,7 @@ begin
   end;
   end;
 
 
   first := identifier[1];
   first := identifier[1];
-  // if ((first < '0') or (first > '2')) then
-  // begin
-  // result := false;
-  // Exit;
-  // end;
+
   if (not CharInSet(first, ['0' .. '2'])) then
   if (not CharInSet(first, ['0' .. '2'])) then
   begin
   begin
     result := False;
     result := False;
@@ -8134,22 +8127,11 @@ procedure TDerBmpString.Encode(const derOut: TStream);
 var
 var
   c: TCryptoLibCharArray;
   c: TCryptoLibCharArray;
   b: TCryptoLibByteArray;
   b: TCryptoLibByteArray;
-  I, LowPoint, HighPoint: Int32;
+  I: Int32;
 begin
 begin
-  System.SetLength(c, System.length(Str));
 
 
-  // had to use this loop because somehow, StrPLCopy causes memory leak in FPC v3.0.5
-{$IFDEF DELPHIXE3_UP}
-  LowPoint := System.Low(Str);
-  HighPoint := System.High(Str);
-{$ELSE}
-  LowPoint := 1;
-  HighPoint := System.length(Str);
-{$ENDIF DELPHIXE3_UP}
-  for I := LowPoint to HighPoint do
-  begin
-    c[I - 1] := Str[I];
-  end;
+  c := TStringUtils.StringToCharArray(Str);
+
   System.SetLength(b, System.length(c) * 2);
   System.SetLength(b, System.length(c) * 2);
 
 
   I := 0;
   I := 0;

+ 48 - 0
src/libraries/cryptolib4pascal/ClpBits.pas

@@ -149,6 +149,7 @@ type
     class function RotateRight64(a_value: UInt64; a_n: Int32): UInt64;
     class function RotateRight64(a_value: UInt64; a_n: Int32): UInt64;
       static; inline;
       static; inline;
 
 
+    class function NumberOfLeadingZeros(a_value: UInt32): Int32; static;
   end;
   end;
 
 
 implementation
 implementation
@@ -372,4 +373,51 @@ begin
 {$ENDIF FPC}
 {$ENDIF FPC}
 end;
 end;
 
 
+class function TBits.NumberOfLeadingZeros(a_value: UInt32): Int32;
+{$IFNDEF FPC}
+var
+  n: UInt32;
+{$ENDIF FPC}
+begin
+
+  if (a_value = 0) then
+  begin
+    Result := ((not a_value) shr (31 - 5)) and (1 shl 5);
+    Exit;
+  end;
+
+{$IFDEF FPC}
+  Result := BsrDWord(a_value) xor ((System.SizeOf(UInt32) * 8) - 1);
+  // this also works
+  // Result := ((System.SizeOf(UInt32) * 8) - 1) - BsrDWord(a_value);
+{$ELSE}
+  n := 1;
+  if ((a_value shr 16) = 0) then
+  begin
+    n := n + 16;
+    a_value := a_value shl 16;
+  end;
+
+  if ((a_value shr 24) = 0) then
+  begin
+    n := n + 8;
+    a_value := a_value shl 8;
+  end;
+
+  if ((a_value shr 28) = 0) then
+  begin
+    n := n + 4;
+    a_value := a_value shl 4;
+  end;
+
+  if ((a_value shr 30) = 0) then
+  begin
+    n := n + 2;
+    a_value := a_value shl 2;
+  end;
+
+  Result := Int32(n) - Int32(a_value shr 31);
+{$ENDIF FPC}
+end;
+
 end.
 end.

+ 1 - 1
src/libraries/cryptolib4pascal/ClpBsiObjectIdentifiers.pas

@@ -17,7 +17,7 @@
 
 
 unit ClpBsiObjectIdentifiers;
 unit ClpBsiObjectIdentifiers;
 
 
-{$I CryptoLib.inc}
+{$I ..\..\Include\CryptoLib.inc}
 
 
 interface
 interface
 
 

+ 90 - 0
src/libraries/cryptolib4pascal/ClpCryptLibObjectIdentifiers.pas

@@ -0,0 +1,90 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpCryptLibObjectIdentifiers;
+
+{$I CryptoLib.inc}
+
+interface
+
+uses
+  ClpAsn1Objects,
+  ClpIAsn1Objects;
+
+type
+  TCryptLibObjectIdentifiers = class abstract(TObject)
+
+  strict private
+
+  class var
+
+    FIsBooted: Boolean;
+    FCryptlib, FEcc, FCurvey25519: IDerObjectIdentifier;
+
+    class constructor CryptLibObjectIdentifiers();
+  private
+    class function GetCryptlib: IDerObjectIdentifier; static; inline;
+    class function GetEcc: IDerObjectIdentifier; static; inline;
+    class function GetCurvey25519: IDerObjectIdentifier; static; inline;
+
+  public
+
+    class property Cryptlib: IDerObjectIdentifier read GetCryptlib;
+    class property Ecc: IDerObjectIdentifier read GetEcc;
+    class property Curvey25519: IDerObjectIdentifier read GetCurvey25519;
+
+    class procedure Boot(); static;
+  end;
+
+implementation
+
+{ TCryptLibObjectIdentifiers }
+
+class procedure TCryptLibObjectIdentifiers.Boot;
+begin
+  if not FIsBooted then
+  begin
+    FCryptlib := TDerObjectIdentifier.Create('1.3.6.1.4.1.3029');
+
+    FEcc := Cryptlib.branch('1').branch('5');
+    FCurvey25519 := Ecc.branch('1');
+
+    FIsBooted := True;
+  end;
+end;
+
+class constructor TCryptLibObjectIdentifiers.CryptLibObjectIdentifiers;
+begin
+  TCryptLibObjectIdentifiers.Boot();
+end;
+
+class function TCryptLibObjectIdentifiers.GetCryptlib: IDerObjectIdentifier;
+begin
+  result := FCryptlib;
+end;
+
+class function TCryptLibObjectIdentifiers.GetEcc: IDerObjectIdentifier;
+begin
+  result := FEcc;
+end;
+
+class function TCryptLibObjectIdentifiers.GetCurvey25519: IDerObjectIdentifier;
+begin
+  result := FCurvey25519;
+end;
+
+end.

+ 3 - 36
src/libraries/cryptolib4pascal/ClpCryptoApiRandomGenerator.pas

@@ -22,12 +22,11 @@ unit ClpCryptoApiRandomGenerator;
 interface
 interface
 
 
 uses
 uses
-  SyncObjs,
-  ClpCryptoLibTypes,
   ClpIRandomNumberGenerator,
   ClpIRandomNumberGenerator,
   ClpRandomNumberGenerator,
   ClpRandomNumberGenerator,
   ClpICryptoApiRandomGenerator,
   ClpICryptoApiRandomGenerator,
-  ClpIRandomGenerator;
+  ClpIRandomGenerator,
+  ClpCryptoLibTypes;
 
 
 resourcestring
 resourcestring
   SNegativeOffset = 'Start Offset Cannot be Negative, "Start"';
   SNegativeOffset = 'Start Offset Cannot be Negative, "Start"';
@@ -44,14 +43,6 @@ type
   var
   var
     FrndProv: IRandomNumberGenerator;
     FrndProv: IRandomNumberGenerator;
 
 
-    class var
-
-      FLock: TCriticalSection;
-
-    class procedure Boot(); static;
-    class constructor CreateCryptoApiRandomGenerator();
-    class destructor DestroyCryptoApiRandomGenerator();
-
   public
   public
     /// <summary>
     /// <summary>
     /// Uses TRandomNumberGenerator.CreateRNG() to Get randomness generator
     /// Uses TRandomNumberGenerator.CreateRNG() to Get randomness generator
@@ -90,14 +81,6 @@ begin
   // We don't care about the seed
   // We don't care about the seed
 end;
 end;
 
 
-class procedure TCryptoApiRandomGenerator.Boot;
-begin
-  if FLock = Nil then
-  begin
-    FLock := TCriticalSection.Create;
-  end;
-end;
-
 procedure TCryptoApiRandomGenerator.AddSeedMaterial
 procedure TCryptoApiRandomGenerator.AddSeedMaterial
   (const seed: TCryptoLibByteArray);
   (const seed: TCryptoLibByteArray);
 begin
 begin
@@ -110,16 +93,6 @@ begin
   FrndProv := rng;
   FrndProv := rng;
 end;
 end;
 
 
-class constructor TCryptoApiRandomGenerator.CreateCryptoApiRandomGenerator;
-begin
-  TCryptoApiRandomGenerator.Boot;
-end;
-
-class destructor TCryptoApiRandomGenerator.DestroyCryptoApiRandomGenerator;
-begin
-  FLock.Free;
-end;
-
 constructor TCryptoApiRandomGenerator.Create;
 constructor TCryptoApiRandomGenerator.Create;
 begin
 begin
   Create(TRandomNumberGenerator.CreateRNG());
   Create(TRandomNumberGenerator.CreateRNG());
@@ -127,13 +100,7 @@ end;
 
 
 procedure TCryptoApiRandomGenerator.NextBytes(const bytes: TCryptoLibByteArray);
 procedure TCryptoApiRandomGenerator.NextBytes(const bytes: TCryptoLibByteArray);
 begin
 begin
-
-  FLock.Acquire;
-  try
-    FrndProv.GetBytes(bytes);
-  finally
-    FLock.Release;
-  end;
+  FrndProv.GetBytes(bytes);
 end;
 end;
 
 
 procedure TCryptoApiRandomGenerator.NextBytes(const bytes: TCryptoLibByteArray;
 procedure TCryptoApiRandomGenerator.NextBytes(const bytes: TCryptoLibByteArray;

+ 55 - 25
src/libraries/cryptolib4pascal/ClpCurve25519Custom.pas

@@ -237,8 +237,8 @@ type
   strict private
   strict private
 
 
   type
   type
-    TCurve25519LookupTable = class sealed(TInterfacedObject,
-      ICurve25519LookupTable, IECLookupTable)
+    TCurve25519LookupTable = class sealed(TAbstractECLookupTable,
+      ICurve25519LookupTable)
 
 
     strict private
     strict private
     var
     var
@@ -246,16 +246,19 @@ type
       Fm_table: TCryptoLibUInt32Array;
       Fm_table: TCryptoLibUInt32Array;
       Fm_size: Int32;
       Fm_size: Int32;
 
 
-      function GetSize: Int32; virtual;
+      function CreatePoint(const x, y: TCryptoLibUInt32Array): IECPoint;
+
+    strict protected
+
+      function GetSize: Int32; override;
 
 
     public
     public
 
 
       constructor Create(const outer: ICurve25519;
       constructor Create(const outer: ICurve25519;
         const table: TCryptoLibUInt32Array; size: Int32);
         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;
     end;
 
 
@@ -267,8 +270,6 @@ type
   var
   var
     Fq: TBigInteger;
     Fq: TBigInteger;
 
 
-    class function GetCurve25519_Q: TBigInteger; static; inline;
-
   strict protected
   strict protected
   var
   var
     Fm_infinity: ICurve25519Point;
     Fm_infinity: ICurve25519Point;
@@ -300,8 +301,6 @@ type
     property Infinity: IECPoint read GetInfinity;
     property Infinity: IECPoint read GetInfinity;
     property FieldSize: Int32 read GetFieldSize;
     property FieldSize: Int32 read GetFieldSize;
 
 
-    class property Curve25519_Q: TBigInteger read GetCurve25519_Q;
-
   end;
   end;
 
 
 implementation
 implementation
@@ -601,7 +600,7 @@ end;
 
 
 class function TCurve25519FieldElement.GetQ: TBigInteger;
 class function TCurve25519FieldElement.GetQ: TBigInteger;
 begin
 begin
-  result := TCurve25519.Curve25519_Q;
+  result := TNat256.ToBigInteger(TCurve25519Field.P);
 end;
 end;
 
 
 class procedure TCurve25519FieldElement.Boot;
 class procedure TCurve25519FieldElement.Boot;
@@ -708,10 +707,10 @@ begin
     * Q == 8m + 5, so we use Pocklington's method for this case.
     * Q == 8m + 5, so we use Pocklington's method for this case.
     *
     *
     * First, raise this element to the exponent 2^252 - 2^1 (i.e. m + 1)
     * First, raise this element to the exponent 2^252 - 2^1 (i.e. m + 1)
-    * 
+    *
     * Breaking up the exponent's binary representation into "repunits", we get:
     * Breaking up the exponent's binary representation into "repunits", we get:
     * { 251 1s } { 1 0s }
     * { 251 1s } { 1 0s }
-    * 
+    *
     * Therefore we need an addition chain containing 251 (the lengths of the repunits)
     * Therefore we need an addition chain containing 251 (the lengths of the repunits)
     * We use: 1, 2, 3, 4, 7, 11, 15, 30, 60, 120, 131, [251]
     * We use: 1, 2, 3, 4, 7, 11, 15, 30, 60, 120, 131, [251]
   *)
   *)
@@ -1236,25 +1235,20 @@ end;
 
 
 { TCurve25519 }
 { TCurve25519 }
 
 
-class function TCurve25519.GetCurve25519_Q: TBigInteger;
-begin
-  result := TNat256.ToBigInteger(TCurve25519Field.P);
-end;
-
 constructor TCurve25519.Create;
 constructor TCurve25519.Create;
 begin
 begin
-  Fq := Curve25519_Q;
+  Fq := TCurve25519FieldElement.Q;
   Inherited Create(Fq);
   Inherited Create(Fq);
   Fm_infinity := TCurve25519Point.Create(Self as IECCurve, Nil, Nil);
   Fm_infinity := TCurve25519Point.Create(Self as IECCurve, Nil, Nil);
 
 
   Fm_a := FromBigInteger(TBigInteger.Create(1,
   Fm_a := FromBigInteger(TBigInteger.Create(1,
-    THex.Decode
+    THex.decode
     ('2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA984914A144')));
     ('2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA984914A144')));
   Fm_b := FromBigInteger(TBigInteger.Create(1,
   Fm_b := FromBigInteger(TBigInteger.Create(1,
-    THex.Decode
+    THex.decode
     ('7B425ED097B425ED097B425ED097B425ED097B425ED097B4260B5E9C7710C864')));
     ('7B425ED097B425ED097B425ED097B425ED097B425ED097B4260B5E9C7710C864')));
   Fm_order := TBigInteger.Create(1,
   Fm_order := TBigInteger.Create(1,
-    THex.Decode
+    THex.decode
     ('1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED'));
     ('1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED'));
   Fm_cofactor := TBigInteger.ValueOf(8);
   Fm_cofactor := TBigInteger.ValueOf(8);
   Fm_coord := Curve25519_DEFAULT_COORDS;
   Fm_coord := Curve25519_DEFAULT_COORDS;
@@ -1342,6 +1336,26 @@ begin
   Fm_size := size;
   Fm_size := size;
 end;
 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;
 function TCurve25519.TCurve25519LookupTable.GetSize: Int32;
 begin
 begin
   result := Fm_size;
   result := Fm_size;
@@ -1370,9 +1384,25 @@ begin
     pos := pos + (CURVE25519_FE_INTS * 2);
     pos := pos + (CURVE25519_FE_INTS * 2);
   end;
   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;
 
 
 end.
 end.

+ 48 - 42
src/libraries/cryptolib4pascal/ClpCustomNamedCurves.pas

@@ -28,9 +28,11 @@ uses
   ClpGlvTypeBParameters,
   ClpGlvTypeBParameters,
   ClpIGlvTypeBEndomorphism,
   ClpIGlvTypeBEndomorphism,
   ClpSecObjectIdentifiers,
   ClpSecObjectIdentifiers,
+  ClpCryptLibObjectIdentifiers,
   ClpCryptoLibTypes,
   ClpCryptoLibTypes,
   ClpBigInteger,
   ClpBigInteger,
   ClpECC,
   ClpECC,
+  ClpECCompUtilities,
   ClpSecP256K1Custom,
   ClpSecP256K1Custom,
   ClpISecP256K1Custom,
   ClpISecP256K1Custom,
   ClpSecP256R1Custom,
   ClpSecP256R1Custom,
@@ -47,6 +49,8 @@ uses
   ClpX9ECC,
   ClpX9ECC,
   ClpIX9ECC,
   ClpIX9ECC,
   ClpIAsn1Objects,
   ClpIAsn1Objects,
+  ClpScalarSplitParameters,
+  ClpIScalarSplitParameters,
   ClpGlvTypeBEndomorphism,
   ClpGlvTypeBEndomorphism,
   ClpX9ECParameters,
   ClpX9ECParameters,
   ClpIX9ECParameters,
   ClpIX9ECParameters,
@@ -69,8 +73,8 @@ type
 
 
     class function GetNames: TCryptoLibStringArray; static; inline;
     class function GetNames: TCryptoLibStringArray; static; inline;
 
 
-    class procedure DefineCurve(const name: String;
-      const holder: IX9ECParametersHolder); static; inline;
+    // class procedure DefineCurve(const name: String;
+    // const holder: IX9ECParametersHolder); static; inline;
 
 
     class procedure DefineCurveWithOid(const name: String;
     class procedure DefineCurveWithOid(const name: String;
       const oid: IDerObjectIdentifier; const holder: IX9ECParametersHolder);
       const oid: IDerObjectIdentifier; const holder: IX9ECParametersHolder);
@@ -84,6 +88,9 @@ type
     class function ConfigureCurveGlv(const c: IECCurve;
     class function ConfigureCurveGlv(const c: IECCurve;
       const p: IGlvTypeBParameters): IECCurve; static; inline;
       const p: IGlvTypeBParameters): IECCurve; static; inline;
 
 
+    class function ConfigureBasepoint(const curve: IECCurve;
+      const encoding: String): IX9ECPoint; static;
+
     class procedure Boot(); static;
     class procedure Boot(); static;
     class constructor CreateCustomNamedCurves();
     class constructor CreateCustomNamedCurves();
     class destructor DestroyCustomNamedCurves();
     class destructor DestroyCustomNamedCurves();
@@ -220,17 +227,24 @@ implementation
 
 
 { TCustomNamedCurves }
 { TCustomNamedCurves }
 
 
-class procedure TCustomNamedCurves.DefineCurve(const name: String;
-  const holder: IX9ECParametersHolder);
-var
-  LName: string;
+class function TCustomNamedCurves.ConfigureBasepoint(const curve: IECCurve;
+  const encoding: String): IX9ECPoint;
 begin
 begin
-  LName := name;
-  Fnames.Add(LName);
-  LName := UpperCase(LName);
-  FnameToCurve.Add(LName, holder);
+  result := TX9ECPoint.Create(curve, THex.Decode(encoding));
+  TWnafUtilities.ConfigureBasepoint(result.Point);
 end;
 end;
 
 
+// class procedure TCustomNamedCurves.DefineCurve(const name: String;
+// const holder: IX9ECParametersHolder);
+// var
+// LName: string;
+// begin
+// LName := name;
+// Fnames.Add(LName);
+// LName := UpperCase(LName);
+// FnameToCurve.Add(LName, holder);
+// end;
+
 class procedure TCustomNamedCurves.DefineCurveWithOid(const name: String;
 class procedure TCustomNamedCurves.DefineCurveWithOid(const name: String;
   const oid: IDerObjectIdentifier; const holder: IX9ECParametersHolder);
   const oid: IDerObjectIdentifier; const holder: IX9ECParametersHolder);
 var
 var
@@ -353,7 +367,8 @@ begin
 
 
   Fnames := TList<String>.Create();
   Fnames := TList<String>.Create();
 
 
-  DefineCurve('curve25519', TCurve25519Holder.Instance);
+  DefineCurveWithOid('curve25519', TCryptlibObjectIdentifiers.Curvey25519,
+    TCurve25519Holder.Instance);
 
 
   DefineCurveWithOid('secp256k1', TSecObjectIdentifiers.SecP256k1,
   DefineCurveWithOid('secp256k1', TSecObjectIdentifiers.SecP256k1,
     TSecP256K1Holder.Instance);
     TSecP256K1Holder.Instance);
@@ -397,10 +412,8 @@ begin
     *
     *
     * (The other possible y value is 5F51E65E475F794B1FE122D388B72EB36DC2B28192839E4DD6163A5D81312C14)
     * (The other possible y value is 5F51E65E475F794B1FE122D388B72EB36DC2B28192839E4DD6163A5D81312C14)
     * }
     * }
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    '2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD245A' +
-    '20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9'));
+  G := ConfigureBasepoint(curve,
+    '042AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD245A20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9');
 
 
   result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
   result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
 end;
 end;
@@ -426,19 +439,19 @@ begin
     ('7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', 16),
     ('7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', 16),
     TBigInteger.Create
     TBigInteger.Create
     ('5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', 16),
     ('5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', 16),
-    TCryptoLibGenericArray<TBigInteger>.Create
+
+    TScalarSplitParameters.Create(TCryptoLibGenericArray<TBigInteger>.Create
     (TBigInteger.Create('3086d221a7d46bcde86c90e49284eb15', 16),
     (TBigInteger.Create('3086d221a7d46bcde86c90e49284eb15', 16),
     TBigInteger.Create('-e4437ed6010e88286f547fa90abfe4c3', 16)),
     TBigInteger.Create('-e4437ed6010e88286f547fa90abfe4c3', 16)),
-    TCryptoLibGenericArray<TBigInteger>.Create
-    (TBigInteger.Create('114ca50f7a8e2f3f657c1108d9d44cfd8', 16),
+    TCryptoLibGenericArray<TBigInteger>.Create(TBigInteger.Create
+    ('114ca50f7a8e2f3f657c1108d9d44cfd8', 16),
     TBigInteger.Create('3086d221a7d46bcde86c90e49284eb15', 16)),
     TBigInteger.Create('3086d221a7d46bcde86c90e49284eb15', 16)),
     TBigInteger.Create('3086d221a7d46bcde86c90e49284eb153dab', 16),
     TBigInteger.Create('3086d221a7d46bcde86c90e49284eb153dab', 16),
-    TBigInteger.Create('e4437ed6010e88286f547fa90abfe4c42212', 16), 272);
+    TBigInteger.Create('e4437ed6010e88286f547fa90abfe4c42212', 16), 272)
+    as IScalarSplitParameters);
   curve := ConfigureCurveGlv(TSecP256K1Curve.Create() as ISecP256K1Curve, glv);
   curve := ConfigureCurveGlv(TSecP256K1Curve.Create() as ISecP256K1Curve, glv);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    '79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798' +
-    '483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8'));
+  G := ConfigureBasepoint(curve,
+    '0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8');
   result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
   result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
 end;
 end;
 
 
@@ -458,11 +471,9 @@ var
 begin
 begin
   S := THex.Decode('A335926AA319A27A1D00896A6773A4827ACDAC73');
   S := THex.Decode('A335926AA319A27A1D00896A6773A4827ACDAC73');
   curve := ConfigureCurve(TSecP384R1Curve.Create() as ISecP384R1Curve);
   curve := ConfigureCurve(TSecP384R1Curve.Create() as ISecP384R1Curve);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    'AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7'
-    + '3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F')
-    );
+  G := ConfigureBasepoint(curve,
+    '04' + 'AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7'
+    + '3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F');
   result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
   result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
 end;
 end;
 
 
@@ -482,11 +493,9 @@ var
 begin
 begin
   S := THex.Decode('D09E8800291CB85396CC6717393284AAA0DA64BA');
   S := THex.Decode('D09E8800291CB85396CC6717393284AAA0DA64BA');
   curve := ConfigureCurve(TSecP521R1Curve.Create() as ISecP521R1Curve);
   curve := ConfigureCurve(TSecP521R1Curve.Create() as ISecP521R1Curve);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    '00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66'
-    + '011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650')
-    );
+  G := ConfigureBasepoint(curve,
+    '04' + '00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66'
+    + '011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650');
   result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
   result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
 end;
 end;
 
 
@@ -506,11 +515,9 @@ var
 begin
 begin
   S := Nil;
   S := Nil;
   curve := ConfigureCurve(TSecT283K1Curve.Create() as ISecT283K1Curve);
   curve := ConfigureCurve(TSecT283K1Curve.Create() as ISecT283K1Curve);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    '0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836' +
-    '01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259')
-    );
+  G := ConfigureBasepoint(curve,
+    '04' + '0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836'
+    + '01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259');
   result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
   result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
 end;
 end;
 
 
@@ -530,10 +537,9 @@ var
 begin
 begin
   S := THex.Decode('C49D360886E704936A6678E1139D26B7819F7E90');
   S := THex.Decode('C49D360886E704936A6678E1139D26B7819F7E90');
   curve := ConfigureCurve(TSecP256R1Curve.Create() as ISecP256R1Curve);
   curve := ConfigureCurve(TSecP256R1Curve.Create() as ISecP256R1Curve);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    '6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296' +
-    '4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5'));
+  G := ConfigureBasepoint(curve,
+    '046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5');
+
   result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
   result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
 end;
 end;
 
 

+ 1 - 1
src/libraries/cryptolib4pascal/ClpDHKeyGeneratorHelper.pas

@@ -27,7 +27,7 @@ uses
   ClpBits,
   ClpBits,
   ClpBigInteger,
   ClpBigInteger,
   ClpBigIntegers,
   ClpBigIntegers,
-  ClpECAlgorithms,
+  ClpECCompUtilities,
   ClpIDHParameters,
   ClpIDHParameters,
   ClpIDHKeyGeneratorHelper;
   ClpIDHKeyGeneratorHelper;
 
 

+ 1 - 1
src/libraries/cryptolib4pascal/ClpDHParametersHelper.pas

@@ -25,7 +25,7 @@ uses
   ClpISecureRandom,
   ClpISecureRandom,
   ClpBigInteger,
   ClpBigInteger,
   ClpBigIntegers,
   ClpBigIntegers,
-  ClpECAlgorithms,
+  ClpECCompUtilities,
   ClpBits,
   ClpBits,
   ClpCryptoLibTypes;
   ClpCryptoLibTypes;
 
 

+ 5 - 25
src/libraries/cryptolib4pascal/ClpDigestRandomGenerator.pas

@@ -45,6 +45,7 @@ type
     CYCLE_COUNT = Int64(10);
     CYCLE_COUNT = Int64(10);
 
 
   var
   var
+    FLock: TCriticalSection;
     FstateCounter, FseedCounter: Int64;
     FstateCounter, FseedCounter: Int64;
     Fdigest: IDigest;
     Fdigest: IDigest;
     Fstate, Fseed: TCryptoLibByteArray;
     Fstate, Fseed: TCryptoLibByteArray;
@@ -55,17 +56,10 @@ type
     procedure DigestUpdate(const inSeed: TCryptoLibByteArray); inline;
     procedure DigestUpdate(const inSeed: TCryptoLibByteArray); inline;
     procedure DigestDoFinal(const result: TCryptoLibByteArray); inline;
     procedure DigestDoFinal(const result: TCryptoLibByteArray); inline;
 
 
-    class var
-
-      FLock: TCriticalSection;
-
-    class procedure Boot(); static;
-    class constructor CreateDigestRandomGenerator();
-    class destructor DestroyDigestRandomGenerator();
-
   public
   public
 
 
     constructor Create(const digest: IDigest);
     constructor Create(const digest: IDigest);
+    destructor Destroy; override;
     procedure AddSeedMaterial(const inSeed: TCryptoLibByteArray);
     procedure AddSeedMaterial(const inSeed: TCryptoLibByteArray);
       overload; inline;
       overload; inline;
     procedure AddSeedMaterial(rSeed: Int64); overload; inline;
     procedure AddSeedMaterial(rSeed: Int64); overload; inline;
@@ -102,7 +96,6 @@ end;
 
 
 procedure TDigestRandomGenerator.AddSeedMaterial(rSeed: Int64);
 procedure TDigestRandomGenerator.AddSeedMaterial(rSeed: Int64);
 begin
 begin
-
   FLock.Acquire;
   FLock.Acquire;
   try
   try
     DigestAddCounter(rSeed);
     DigestAddCounter(rSeed);
@@ -113,18 +106,9 @@ begin
   end;
   end;
 end;
 end;
 
 
-class procedure TDigestRandomGenerator.Boot;
-begin
-  if FLock = Nil then
-  begin
-    FLock := TCriticalSection.Create;
-  end;
-end;
-
 procedure TDigestRandomGenerator.AddSeedMaterial(const inSeed
 procedure TDigestRandomGenerator.AddSeedMaterial(const inSeed
   : TCryptoLibByteArray);
   : TCryptoLibByteArray);
 begin
 begin
-
   FLock.Acquire;
   FLock.Acquire;
   try
   try
     DigestUpdate(inSeed);
     DigestUpdate(inSeed);
@@ -138,6 +122,7 @@ end;
 constructor TDigestRandomGenerator.Create(const digest: IDigest);
 constructor TDigestRandomGenerator.Create(const digest: IDigest);
 begin
 begin
   Inherited Create();
   Inherited Create();
+  FLock := TCriticalSection.Create;
   Fdigest := digest;
   Fdigest := digest;
   System.SetLength(Fseed, digest.GetDigestSize);
   System.SetLength(Fseed, digest.GetDigestSize);
   FseedCounter := 1;
   FseedCounter := 1;
@@ -145,11 +130,6 @@ begin
   FstateCounter := 1;
   FstateCounter := 1;
 end;
 end;
 
 
-class constructor TDigestRandomGenerator.CreateDigestRandomGenerator;
-begin
-  TDigestRandomGenerator.Boot;
-end;
-
 procedure TDigestRandomGenerator.CycleSeed;
 procedure TDigestRandomGenerator.CycleSeed;
 begin
 begin
   DigestUpdate(Fseed);
   DigestUpdate(Fseed);
@@ -158,9 +138,10 @@ begin
   DigestDoFinal(Fseed);
   DigestDoFinal(Fseed);
 end;
 end;
 
 
-class destructor TDigestRandomGenerator.DestroyDigestRandomGenerator;
+destructor TDigestRandomGenerator.Destroy;
 begin
 begin
   FLock.Free;
   FLock.Free;
+  inherited Destroy;
 end;
 end;
 
 
 procedure TDigestRandomGenerator.GenerateState;
 procedure TDigestRandomGenerator.GenerateState;
@@ -188,7 +169,6 @@ var
   stateOff, endPoint: Int32;
   stateOff, endPoint: Int32;
   I: Int32;
   I: Int32;
 begin
 begin
-
   FLock.Acquire;
   FLock.Acquire;
   try
   try
     stateOff := 0;
     stateOff := 0;

+ 1 - 1
src/libraries/cryptolib4pascal/ClpDsaKeyPairGenerator.pas

@@ -37,7 +37,7 @@ uses
   ClpBits,
   ClpBits,
   ClpBigInteger,
   ClpBigInteger,
   ClpBigIntegers,
   ClpBigIntegers,
-  ClpECAlgorithms,
+  ClpECCompUtilities,
   ClpCryptoLibTypes;
   ClpCryptoLibTypes;
 
 
 resourcestring
 resourcestring

+ 242 - 973
src/libraries/cryptolib4pascal/ClpECAlgorithms.pas

@@ -25,17 +25,18 @@ uses
   SysUtils,
   SysUtils,
   Math,
   Math,
   ClpCryptoLibTypes,
   ClpCryptoLibTypes,
-  ClpBits,
   ClpBigInteger,
   ClpBigInteger,
-  ClpWNafPreCompInfo,
-  ClpIPolynomialExtensionField,
-  ClpIGlvEndomorphism,
-  ClpIWNafPreCompInfo,
-  ClpIPreCompInfo,
-  ClpIPreCompCallBack,
+  ClpBits,
+  ClpNat,
   ClpIECC,
   ClpIECC,
-  ClpECCurveConstants,
-  ClpIFiniteField;
+  ClpECCompUtilities,
+  ClpIWNafPreCompInfo,
+  ClpIFiniteField,
+  ClpIFixedPointPreCompInfo,
+  ClpIGlvEndomorphism,
+  ClpIMultipliers,
+  ClpMultipliers,
+  ClpIPolynomialExtensionField;
 
 
 resourcestring
 resourcestring
   SInvalidArray =
   SInvalidArray =
@@ -43,160 +44,8 @@ resourcestring
   SInvalidPointLocation = 'Point Must be on the Same Curve';
   SInvalidPointLocation = 'Point Must be on the Same Curve';
   SInvalidPoint = 'Invalid Point, "P"';
   SInvalidPoint = 'Invalid Point, "P"';
   SInvalidResult = 'Invalid Result';
   SInvalidResult = 'Invalid Result';
-  SInvalidRange = 'Must be in the Range [2, 16], "width"';
-  SInvalidRange2 = 'Must be in the Range [2, 8], "width"';
-
-type
-  TWNafUtilities = class abstract(TObject)
-
-  strict private
-  const
-    FDEFAULT_WINDOW_SIZE_CUTOFFS: array [0 .. 5] of Int32 = (13, 41, 121, 337,
-      897, 2305);
-
-  class var
-    FEMPTY_BYTES: TCryptoLibByteArray;
-    FEMPTY_INTS: TCryptoLibInt32Array;
-
-  type
-    IMapPointCallback = interface(IPreCompCallback)
-      ['{730BF27F-D5C3-4DF4-AC77-B8653C457C10}']
-
-    end;
-
-  type
-    TMapPointCallback = class(TInterfacedObject, IPreCompCallback,
-      IMapPointCallback)
-
-    strict private
-    var
-      Fm_wnafPreCompP: IWNafPreCompInfo;
-      Fm_includeNegated: Boolean;
-      Fm_pointMap: IECPointMap;
-
-    public
-      constructor Create(const wnafPreCompP: IWNafPreCompInfo;
-        includeNegated: Boolean; const pointMap: IECPointMap);
-
-      function Precompute(const existing: IPreCompInfo): IPreCompInfo;
-
-    end;
-
-  type
-    IWNafCallback = interface(IPreCompCallback)
-      ['{A439A606-7899-4720-937E-C2F3D94D4811}']
-
-    end;
-
-  type
-    TWNafCallback = class(TInterfacedObject, IPreCompCallback, IWNafCallback)
-
-    strict private
-
-    var
-      Fm_p: IECPoint;
-      Fm_width: Int32;
-      Fm_includeNegated: Boolean;
-
-    public
-      constructor Create(const p: IECPoint; width: Int32;
-        includeNegated: Boolean);
-
-      function Precompute(const existing: IPreCompInfo): IPreCompInfo;
-
-    end;
-
-  class function CheckExisting(const existingWNaf: IWNafPreCompInfo;
-    reqPreCompLen: Int32; includeNegated: Boolean): Boolean; static; inline;
-
-  class function CheckTable(const table: TCryptoLibGenericArray<IECPoint>;
-    reqLen: Int32): Boolean; static; inline;
-
-  class function Trim(const a: TCryptoLibByteArray; length: Int32)
-    : TCryptoLibByteArray; overload; static; inline;
-
-  class function Trim(const a: TCryptoLibInt32Array; length: Int32)
-    : TCryptoLibInt32Array; overload; static; inline;
-
-  class function ResizeTable(const a: TCryptoLibGenericArray<IECPoint>;
-    length: Int32): TCryptoLibGenericArray<IECPoint>; static; inline;
-
-  class procedure Boot(); static;
-  class constructor CreateWNafUtilities();
-
-  public
-
-    const
-    PRECOMP_NAME: String = 'bc_wnaf';
-
-    class function GenerateCompactNaf(const k: TBigInteger)
-      : TCryptoLibInt32Array; static;
-    class function GenerateCompactWindowNaf(width: Int32; const k: TBigInteger)
-      : TCryptoLibInt32Array; static;
-
-    class function GenerateJsf(const g, h: TBigInteger)
-      : TCryptoLibByteArray; static;
-    class function GenerateNaf(const k: TBigInteger)
-      : TCryptoLibByteArray; static;
-    // /**
-    // * Computes the Window NAF (non-adjacent Form) of an integer.
-    // * @param width The width <code>w</code> of the Window NAF. The width is
-    // * defined as the minimal number <code>w</code>, such that for any
-    // * <code>w</code> consecutive digits in the resulting representation, at
-    // * most one is non-zero.
-    // * @param k The integer of which the Window NAF is computed.
-    // * @return The Window NAF of the given width, such that the following holds:
-    // * <code>k = &amp;sum;<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup>
-    // * </code>, where the <code>k<sub>i</sub></code> denote the elements of the
-    // * returned <code>byte[]</code>.
-    // */
-    class function GenerateWindowNaf(width: Int32; const k: TBigInteger)
-      : TCryptoLibByteArray; static;
-
-    class function GetNafWeight(const k: TBigInteger): Int32; static; inline;
-
-    class function GetWNafPreCompInfo(const p: IECPoint): IWNafPreCompInfo;
-      overload; static; inline;
-
-    class function GetWNafPreCompInfo(const preCompInfo: IPreCompInfo)
-      : IWNafPreCompInfo; overload; static; inline;
-
-    /// <summary>
-    /// Determine window width to use for a scalar multiplication of the
-    /// given size.
-    /// </summary>
-    /// <param name="bits">
-    /// the bit-length of the scalar to multiply by
-    /// </param>
-    /// <returns>
-    /// the window size to use
-    /// </returns>
-    class function GetWindowSize(bits: Int32): Int32; overload; static; inline;
-
-    /// <summary>
-    /// Determine window width to use for a scalar multiplication of the
-    /// given size.
-    /// </summary>
-    /// <param name="bits">
-    /// the bit-length of the scalar to multiply by
-    /// </param>
-    /// <param name="windowSizeCutoffs">
-    /// a monotonically increasing list of bit sizes at which to increment
-    /// the window width
-    /// </param>
-    /// <returns>
-    /// the window size to use
-    /// </returns>
-    class function GetWindowSize(bits: Int32;
-      const windowSizeCutoffs: array of Int32): Int32; overload; static;
-
-    class function MapPointWithPrecomp(const p: IECPoint; width: Int32;
-      includeNegated: Boolean; const pointMap: IECPointMap): IECPoint; static;
-
-    class function Precompute(const p: IECPoint; width: Int32;
-      includeNegated: Boolean): IWNafPreCompInfo; static;
-
-  end;
+  SInvalidComputation =
+    'Fixed-Point Comb Doesn''t Support Scalars Larger Than The Curve Order';
 
 
 type
 type
   TECAlgorithms = class sealed(TObject)
   TECAlgorithms = class sealed(TObject)
@@ -212,6 +61,10 @@ type
       const infos: TCryptoLibGenericArray<IWNafPreCompInfo>;
       const infos: TCryptoLibGenericArray<IWNafPreCompInfo>;
       const wnafs: TCryptoLibMatrixByteArray): IECPoint; overload; static;
       const wnafs: TCryptoLibMatrixByteArray): IECPoint; overload; static;
 
 
+    class function ImplShamirsTrickFixedPoint(const p: IECPoint;
+      const k: TBigInteger; const q: IECPoint; const l: TBigInteger)
+      : IECPoint; static;
+
   public
   public
     class function IsF2mCurve(const c: IECCurve): Boolean; static;
     class function IsF2mCurve(const c: IECCurve): Boolean; static;
     class function IsF2mField(const field: IFiniteField): Boolean; static;
     class function IsF2mField(const field: IFiniteField): Boolean; static;
@@ -222,7 +75,7 @@ type
       const ks: TCryptoLibGenericArray<TBigInteger>): IECPoint; static;
       const ks: TCryptoLibGenericArray<TBigInteger>): IECPoint; static;
 
 
     class function SumOfTwoMultiplies(const p: IECPoint; const a: TBigInteger;
     class function SumOfTwoMultiplies(const p: IECPoint; const a: TBigInteger;
-      const Q: IECPoint; const b: TBigInteger): IECPoint; static;
+      const q: IECPoint; const b: TBigInteger): IECPoint; static;
 
 
     // /*
     // /*
     // * "Shamir's Trick", originally due to E. G. Straus
     // * "Shamir's Trick", originally due to E. G. Straus
@@ -243,7 +96,7 @@ type
     // * 9: return R
     // * 9: return R
     // */
     // */
     class function ShamirsTrick(const p: IECPoint; const k: TBigInteger;
     class function ShamirsTrick(const p: IECPoint; const k: TBigInteger;
-      const Q: IECPoint; const l: TBigInteger): IECPoint; static;
+      const q: IECPoint; const l: TBigInteger): IECPoint; static;
 
 
     class function ImportPoint(const c: IECCurve; const p: IECPoint)
     class function ImportPoint(const c: IECCurve; const p: IECPoint)
       : IECPoint; static;
       : IECPoint; static;
@@ -277,14 +130,13 @@ type
       : IECPoint; static;
       : IECPoint; static;
 
 
     class function ImplShamirsTrickJsf(const p: IECPoint; const k: TBigInteger;
     class function ImplShamirsTrickJsf(const p: IECPoint; const k: TBigInteger;
-      const Q: IECPoint; const l: TBigInteger): IECPoint; static;
+      const q: IECPoint; const l: TBigInteger): IECPoint; static;
 
 
     class function ImplShamirsTrickWNaf(const p: IECPoint; const k: TBigInteger;
     class function ImplShamirsTrickWNaf(const p: IECPoint; const k: TBigInteger;
-      const Q: IECPoint; const l: TBigInteger): IECPoint; overload; static;
+      const q: IECPoint; const l: TBigInteger): IECPoint; overload; static;
 
 
-    class function ImplShamirsTrickWNaf(const p: IECPoint; const k: TBigInteger;
-      const pointMapQ: IECPointMap; const l: TBigInteger): IECPoint;
-      overload; static;
+    class function ImplShamirsTrickWNaf(const endomorphism: IECEndomorphism;
+      const p: IECPoint; const k, l: TBigInteger): IECPoint; overload; static;
 
 
     class function ImplSumOfMultiplies
     class function ImplSumOfMultiplies
       (const ps: TCryptoLibGenericArray<IECPoint>;
       (const ps: TCryptoLibGenericArray<IECPoint>;
@@ -296,8 +148,8 @@ type
       const ks: TCryptoLibGenericArray<TBigInteger>;
       const ks: TCryptoLibGenericArray<TBigInteger>;
       const glvEndomorphism: IGlvEndomorphism): IECPoint; static;
       const glvEndomorphism: IGlvEndomorphism): IECPoint; static;
 
 
-    class function ImplSumOfMultiplies
-      (const ps: TCryptoLibGenericArray<IECPoint>; const pointMap: IECPointMap;
+    class function ImplSumOfMultiplies(const endomorphism: IECEndomorphism;
+      const ps: TCryptoLibGenericArray<IECPoint>;
       const ks: TCryptoLibGenericArray<TBigInteger>): IECPoint;
       const ks: TCryptoLibGenericArray<TBigInteger>): IECPoint;
       overload; static;
       overload; static;
 
 
@@ -341,33 +193,124 @@ begin
   result := p;
   result := p;
 end;
 end;
 
 
+class function TECAlgorithms.ImplShamirsTrickFixedPoint(const p: IECPoint;
+  const k: TBigInteger; const q: IECPoint; const l: TBigInteger): IECPoint;
+var
+  c: IECCurve;
+  combSize, widthP, widthQ, width, d, fullComb, i, top, j: Int32;
+  infoP, infoQ: IFixedPointPreCompInfo;
+  lookupTableP, lookupTableQ: IECLookupTable;
+  m: IFixedPointCombMultiplier;
+  r1, r2, R, addP, addQ, t: IECPoint;
+  BigK, BigL: TCryptoLibUInt32Array;
+  secretBitK, secretBitL, secretIndexK, secretIndexL: UInt32;
+begin
+  c := p.Curve;
+  combSize := TFixedPointUtilities.GetCombSize(c);
+
+  if (((k.BitLength) > combSize) or (l.BitLength > combSize)) then
+  begin
+    (*
+      * TODO The comb works best when the scalars are less than the (possibly unknown) order.
+      * Still, if we want to handle larger scalars, we could allow customization of the comb
+      * size, or alternatively we could deal with the 'extra' bits either by running the comb
+      * multiple times as necessary, or by using an alternative multiplier as prelude.
+    *)
+    raise EInvalidOperationCryptoLibException.CreateRes(@SInvalidComputation);
+  end;
+
+  infoP := TFixedPointUtilities.Precompute(p);
+  infoQ := TFixedPointUtilities.Precompute(q);
+
+  lookupTableP := infoP.LookupTable;
+  lookupTableQ := infoQ.LookupTable;
+
+  widthP := infoP.width;
+  widthQ := infoQ.width;
+
+  // TODO This shouldn't normally happen, but a better "solution" is desirable anyway
+  if (widthP <> widthQ) then
+  begin
+    m := TFixedPointCombMultiplier.Create();
+    r1 := m.Multiply(p, k);
+    r2 := m.Multiply(q, l);
+    result := r1.Add(r2);
+    Exit;
+  end;
+
+  width := widthP;
+
+  d := ((combSize + width) - 1) div width;
+
+  R := c.Infinity;
+
+  fullComb := d * width;
+  BigK := TNat.FromBigInteger(fullComb, k);
+  BigL := TNat.FromBigInteger(fullComb, l);
+
+  top := fullComb - 1;
+
+  for i := 0 to System.Pred(d) do
+  begin
+    secretIndexK := 0;
+    secretIndexL := 0;
+
+    j := top - i;
+
+    while j >= 0 do
+    begin
+
+      secretBitK := BigK[TBits.Asr32(j, 5)] shr (j and $1F);
+      secretIndexK := secretIndexK xor (secretBitK shr 1);
+      secretIndexK := secretIndexK shl 1;
+      secretIndexK := secretIndexK xor secretBitK;
+
+      secretBitL := BigL[TBits.Asr32(j, 5)] shr (j and $1F);
+      secretIndexL := secretIndexL xor (secretBitL shr 1);
+      secretIndexL := secretIndexL shl 1;
+      secretIndexL := secretIndexL xor secretBitL;
+
+      System.Dec(j, d);
+    end;
+
+    addP := lookupTableP.LookupVar(Int32(secretIndexK));
+    addQ := lookupTableQ.LookupVar(Int32(secretIndexL));
+
+    t := addP.Add(addQ);
+
+    R := R.TwicePlus(t);
+  end;
+
+  result := R.Add(infoP.Offset).Add(infoQ.Offset);
+end;
+
 class function TECAlgorithms.ImplShamirsTrickJsf(const p: IECPoint;
 class function TECAlgorithms.ImplShamirsTrickJsf(const p: IECPoint;
-  const k: TBigInteger; const Q: IECPoint; const l: TBigInteger): IECPoint;
+  const k: TBigInteger; const q: IECPoint; const l: TBigInteger): IECPoint;
 var
 var
   Curve: IECCurve;
   Curve: IECCurve;
-  infinity, R: IECPoint;
+  Infinity, R: IECPoint;
   PaddQ, PsubQ: IECPoint;
   PaddQ, PsubQ: IECPoint;
   points, table: TCryptoLibGenericArray<IECPoint>;
   points, table: TCryptoLibGenericArray<IECPoint>;
   jsf: TCryptoLibByteArray;
   jsf: TCryptoLibByteArray;
   i, jsfi, kDigit, lDigit, index: Int32;
   i, jsfi, kDigit, lDigit, index: Int32;
 begin
 begin
   Curve := p.Curve;
   Curve := p.Curve;
-  infinity := Curve.infinity;
+  Infinity := Curve.Infinity;
 
 
   // TODO conjugate co-Z addition (ZADDC) can return both of these
   // TODO conjugate co-Z addition (ZADDC) can return both of these
-  PaddQ := p.Add(Q);
-  PsubQ := p.Subtract(Q);
+  PaddQ := p.Add(q);
+  PsubQ := p.Subtract(q);
 
 
-  points := TCryptoLibGenericArray<IECPoint>.Create(Q, PsubQ, p, PaddQ);
+  points := TCryptoLibGenericArray<IECPoint>.Create(q, PsubQ, p, PaddQ);
   Curve.NormalizeAll(points);
   Curve.NormalizeAll(points);
 
 
   table := TCryptoLibGenericArray<IECPoint>.Create(points[3].Negate(),
   table := TCryptoLibGenericArray<IECPoint>.Create(points[3].Negate(),
-    points[2].Negate(), points[1].Negate(), points[0].Negate(), infinity,
+    points[2].Negate(), points[1].Negate(), points[0].Negate(), Infinity,
     points[0], points[1], points[2], points[3]);
     points[0], points[1], points[2], points[3]);
 
 
   jsf := TWNafUtilities.GenerateJsf(k, l);
   jsf := TWNafUtilities.GenerateJsf(k, l);
 
 
-  R := infinity;
+  R := Infinity;
 
 
   i := System.length(jsf);
   i := System.length(jsf);
   System.Dec(i);
   System.Dec(i);
@@ -387,13 +330,12 @@ begin
   result := R;
   result := R;
 end;
 end;
 
 
-class function TECAlgorithms.ImplShamirsTrickWNaf(const p: IECPoint;
-  const k: TBigInteger; const pointMapQ: IECPointMap; const l: TBigInteger)
-  : IECPoint;
+class function TECAlgorithms.ImplShamirsTrickWNaf(const endomorphism
+  : IECEndomorphism; const p: IECPoint; const k, l: TBigInteger): IECPoint;
 var
 var
   negK, negL: Boolean;
   negK, negL: Boolean;
-  width: Int32;
-  Q: IECPoint;
+  minWidth, widthP, widthQ: Int32;
+  q: IECPoint;
   infoP, infoQ: IWNafPreCompInfo;
   infoP, infoQ: IWNafPreCompInfo;
   preCompP, preCompQ, preCompNegP, preCompNegQ
   preCompP, preCompQ, preCompNegP, preCompNegQ
     : TCryptoLibGenericArray<IECPoint>;
     : TCryptoLibGenericArray<IECPoint>;
@@ -408,12 +350,15 @@ begin
   LK := LK.Abs();
   LK := LK.Abs();
   LL := LL.Abs();
   LL := LL.Abs();
 
 
-  width := Max(2, Min(16, TWNafUtilities.GetWindowSize(Max(LK.BitLength,
-    LL.BitLength))));
+  minWidth := TWNafUtilities.GetWindowSize(Max(k.BitLength, l.BitLength), 8);
 
 
-  Q := TWNafUtilities.MapPointWithPrecomp(p, width, true, pointMapQ);
-  infoP := TWNafUtilities.GetWNafPreCompInfo(p);
-  infoQ := TWNafUtilities.GetWNafPreCompInfo(Q);
+  infoP := TWNafUtilities.Precompute(p, minWidth, true);
+  q := TEndoUtilities.MapPoint(endomorphism, p);
+  infoQ := TWNafUtilities.PrecomputeWithPointMap(q, endomorphism.pointMap,
+    infoP, true);
+
+  widthP := Min(8, infoP.width);
+  widthQ := Min(8, infoQ.width);
 
 
   case negK of
   case negK of
     true:
     true:
@@ -443,8 +388,8 @@ begin
       preCompNegQ := infoQ.PreCompNeg
       preCompNegQ := infoQ.PreCompNeg
   end;
   end;
 
 
-  wnafP := TWNafUtilities.GenerateWindowNaf(width, LK);
-  wnafQ := TWNafUtilities.GenerateWindowNaf(width, LL);
+  wnafP := TWNafUtilities.GenerateWindowNaf(widthP, LK);
+  wnafQ := TWNafUtilities.GenerateWindowNaf(widthQ, LL);
 
 
   result := ImplShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ,
   result := ImplShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ,
     preCompNegQ, wnafQ);
     preCompNegQ, wnafQ);
@@ -457,29 +402,48 @@ begin
 end;
 end;
 
 
 class function TECAlgorithms.ImplShamirsTrickWNaf(const p: IECPoint;
 class function TECAlgorithms.ImplShamirsTrickWNaf(const p: IECPoint;
-  const k: TBigInteger; const Q: IECPoint; const l: TBigInteger): IECPoint;
+  const k: TBigInteger; const q: IECPoint; const l: TBigInteger): IECPoint;
 var
 var
   negK, negL: Boolean;
   negK, negL: Boolean;
-  widthP, widthQ: Int32;
+  minWidthP, minWidthQ, widthP, widthQ, combSize: Int32;
   infoP, infoQ: IWNafPreCompInfo;
   infoP, infoQ: IWNafPreCompInfo;
   preCompP, preCompQ, preCompNegP, preCompNegQ
   preCompP, preCompQ, preCompNegP, preCompNegQ
     : TCryptoLibGenericArray<IECPoint>;
     : TCryptoLibGenericArray<IECPoint>;
   wnafP, wnafQ: TCryptoLibByteArray;
   wnafP, wnafQ: TCryptoLibByteArray;
-  LK, LL: TBigInteger;
+  kAbs, lAbs: TBigInteger;
+  c: IECCurve;
 begin
 begin
-  LK := k;
-  LL := l;
-  negK := LK.SignValue < 0;
-  negL := LL.SignValue < 0;
 
 
-  LK := LK.Abs();
-  LL := LL.Abs();
+  negK := k.SignValue < 0;
+  negL := l.SignValue < 0;
+
+  kAbs := k.Abs();
+  lAbs := l.Abs();
 
 
-  widthP := Max(2, Min(16, TWNafUtilities.GetWindowSize(LK.BitLength)));
-  widthQ := Max(2, Min(16, TWNafUtilities.GetWindowSize(LL.BitLength)));
+  minWidthP := TWNafUtilities.GetWindowSize(kAbs.BitLength, 8);
+  minWidthQ := TWNafUtilities.GetWindowSize(lAbs.BitLength, 8);
 
 
-  infoP := TWNafUtilities.Precompute(p, widthP, true);
-  infoQ := TWNafUtilities.Precompute(Q, widthQ, true);
+  infoP := TWNafUtilities.Precompute(p, minWidthP, true);
+  infoQ := TWNafUtilities.Precompute(q, minWidthQ, true);
+
+  // When P, Q are 'promoted' (i.e. reused several times), switch to fixed-point algorithm
+
+  c := p.Curve;
+  combSize := TFixedPointUtilities.GetCombSize(c);
+  if ((not negK) and (not negL) and (k.BitLength <= combSize) and
+    (l.BitLength <= combSize) and (infoP.IsPromoted) and (infoQ.IsPromoted))
+  then
+  begin
+    result := ImplShamirsTrickFixedPoint(p, k, q, l);
+    infoP.PreComp := Nil; // Review
+    infoP.PreCompNeg := Nil; // Review
+    infoQ.PreComp := Nil; // Review
+    infoQ.PreCompNeg := Nil; // Review
+    Exit;
+  end;
+
+  widthP := Min(8, infoP.width);
+  widthQ := Min(8, infoQ.width);
 
 
   if negK then
   if negK then
   begin
   begin
@@ -517,8 +481,8 @@ begin
     preCompNegQ := infoQ.PreCompNeg
     preCompNegQ := infoQ.PreCompNeg
   end;
   end;
 
 
-  wnafP := TWNafUtilities.GenerateWindowNaf(widthP, LK);
-  wnafQ := TWNafUtilities.GenerateWindowNaf(widthQ, LL);
+  wnafP := TWNafUtilities.GenerateWindowNaf(widthP, kAbs);
+  wnafQ := TWNafUtilities.GenerateWindowNaf(widthQ, lAbs);
 
 
   result := ImplShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ,
   result := ImplShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ,
     preCompNegQ, wnafQ);
     preCompNegQ, wnafQ);
@@ -536,15 +500,15 @@ class function TECAlgorithms.ImplShamirsTrickWNaf(const preCompP,
 var
 var
   len, zeroes, i, wiP, wiQ, nP, nQ: Int32;
   len, zeroes, i, wiP, wiQ, nP, nQ: Int32;
   Curve: IECCurve;
   Curve: IECCurve;
-  infinity, R, point: IECPoint;
+  Infinity, R, point: IECPoint;
   tableP, tableQ: TCryptoLibGenericArray<IECPoint>;
   tableP, tableQ: TCryptoLibGenericArray<IECPoint>;
 begin
 begin
-  len := Math.Max(System.length(wnafP), System.length(wnafQ));
+  len := Max(System.length(wnafP), System.length(wnafQ));
 
 
   Curve := preCompP[0].Curve;
   Curve := preCompP[0].Curve;
-  infinity := Curve.infinity;
+  Infinity := Curve.Infinity;
 
 
-  R := infinity;
+  R := Infinity;
   zeroes := 0;
   zeroes := 0;
 
 
   i := len - 1;
   i := len - 1;
@@ -576,7 +540,7 @@ begin
       continue;
       continue;
     end;
     end;
 
 
-    point := infinity;
+    point := Infinity;
     if (wiP <> 0) then
     if (wiP <> 0) then
     begin
     begin
       nP := System.Abs(wiP);
       nP := System.Abs(wiP);
@@ -626,17 +590,19 @@ begin
   result := R;
   result := R;
 end;
 end;
 
 
-class function TECAlgorithms.ImplSumOfMultiplies
-  (const ps: TCryptoLibGenericArray<IECPoint>; const pointMap: IECPointMap;
+class function TECAlgorithms.ImplSumOfMultiplies(const endomorphism
+  : IECEndomorphism; const ps: TCryptoLibGenericArray<IECPoint>;
   const ks: TCryptoLibGenericArray<TBigInteger>): IECPoint;
   const ks: TCryptoLibGenericArray<TBigInteger>): IECPoint;
 var
 var
   halfCount, fullCount: Int32;
   halfCount, fullCount: Int32;
   negs: TCryptoLibBooleanArray;
   negs: TCryptoLibBooleanArray;
   infos: TCryptoLibGenericArray<IWNafPreCompInfo>;
   infos: TCryptoLibGenericArray<IWNafPreCompInfo>;
+  infoP, infoQ: IWNafPreCompInfo;
   wnafs: TCryptoLibMatrixByteArray;
   wnafs: TCryptoLibMatrixByteArray;
-  i, j0, j1, width: Int32;
+  i, j0, j1, minWidth, widthP, widthQ: Int32;
   kj0, kj1: TBigInteger;
   kj0, kj1: TBigInteger;
-  p, Q: IECPoint;
+  p, q: IECPoint;
+  pointMap: IECPointMap;
 begin
 begin
   halfCount := System.length(ps);
   halfCount := System.length(ps);
   fullCount := halfCount shl 1;
   fullCount := halfCount shl 1;
@@ -644,6 +610,8 @@ begin
   System.SetLength(infos, fullCount);
   System.SetLength(infos, fullCount);
   System.SetLength(wnafs, fullCount);
   System.SetLength(wnafs, fullCount);
 
 
+  pointMap := endomorphism.pointMap;
+
   for i := 0 to System.Pred(halfCount) do
   for i := 0 to System.Pred(halfCount) do
   begin
   begin
     j0 := i shl 1;
     j0 := i shl 1;
@@ -656,15 +624,21 @@ begin
     negs[j1] := kj1.SignValue < 0;
     negs[j1] := kj1.SignValue < 0;
     kj1 := kj1.Abs();
     kj1 := kj1.Abs();
 
 
-    width := Max(2, Min(16, TWNafUtilities.GetWindowSize(Max(kj0.BitLength,
-      kj1.BitLength))));
+    minWidth := TWNafUtilities.GetWindowSize
+      (Max(kj0.BitLength, kj1.BitLength), 8);
 
 
     p := ps[i];
     p := ps[i];
-    Q := TWNafUtilities.MapPointWithPrecomp(p, width, true, pointMap);
-    infos[j0] := TWNafUtilities.GetWNafPreCompInfo(p);
-    infos[j1] := TWNafUtilities.GetWNafPreCompInfo(Q);
-    wnafs[j0] := TWNafUtilities.GenerateWindowNaf(width, kj0);
-    wnafs[j1] := TWNafUtilities.GenerateWindowNaf(width, kj1);
+    infoP := TWNafUtilities.Precompute(p, minWidth, true);
+    q := TEndoUtilities.MapPoint(endomorphism, p);
+    infoQ := TWNafUtilities.PrecomputeWithPointMap(q, pointMap, infoP, true);
+
+    widthP := Min(8, infoP.width);
+    widthQ := Min(8, infoQ.width);
+
+    infos[j0] := infoP;
+    infos[j1] := infoQ;
+    wnafs[j0] := TWNafUtilities.GenerateWindowNaf(widthP, kj0);
+    wnafs[j1] := TWNafUtilities.GenerateWindowNaf(widthQ, kj1);
   end;
   end;
 
 
   result := ImplSumOfMultiplies(negs, infos, wnafs);
   result := ImplSumOfMultiplies(negs, infos, wnafs);
@@ -681,8 +655,9 @@ class function TECAlgorithms.ImplSumOfMultiplies
   (const ps: TCryptoLibGenericArray<IECPoint>;
   (const ps: TCryptoLibGenericArray<IECPoint>;
   const ks: TCryptoLibGenericArray<TBigInteger>): IECPoint;
   const ks: TCryptoLibGenericArray<TBigInteger>): IECPoint;
 var
 var
-  count, i, width: Int32;
+  count, i, width, minWidth: Int32;
   negs: TCryptoLibBooleanArray;
   negs: TCryptoLibBooleanArray;
+  info: IWNafPreCompInfo;
   infos: TCryptoLibGenericArray<IWNafPreCompInfo>;
   infos: TCryptoLibGenericArray<IWNafPreCompInfo>;
   wnafs: TCryptoLibMatrixByteArray;
   wnafs: TCryptoLibMatrixByteArray;
   ki: TBigInteger;
   ki: TBigInteger;
@@ -700,8 +675,11 @@ begin
     negs[i] := ki.SignValue < 0;
     negs[i] := ki.SignValue < 0;
     ki := ki.Abs();
     ki := ki.Abs();
 
 
-    width := Max(2, Min(16, TWNafUtilities.GetWindowSize(ki.BitLength)));
-    infos[i] := TWNafUtilities.Precompute(ps[i], width, true);
+    minWidth := TWNafUtilities.GetWindowSize(ki.BitLength, 8);
+    info := TWNafUtilities.Precompute(ps[i], minWidth, true);
+    width := Min(8, info.width);
+
+    infos[i] := info;
     wnafs[i] := TWNafUtilities.GenerateWindowNaf(width, ki);
     wnafs[i] := TWNafUtilities.GenerateWindowNaf(width, ki);
   end;
   end;
 
 
@@ -721,9 +699,9 @@ class function TECAlgorithms.ImplSumOfMultiplies
   const wnafs: TCryptoLibMatrixByteArray): IECPoint;
   const wnafs: TCryptoLibMatrixByteArray): IECPoint;
 var
 var
   len, count, zeroes: Int32;
   len, count, zeroes: Int32;
-  i, J, wi, n: Int32;
+  i, j, wi, n: Int32;
   Curve: IECCurve;
   Curve: IECCurve;
-  infinity, R, point: IECPoint;
+  Infinity, R, point: IECPoint;
   wnaf: TCryptoLibByteArray;
   wnaf: TCryptoLibByteArray;
   info: IWNafPreCompInfo;
   info: IWNafPreCompInfo;
   table: TCryptoLibGenericArray<IECPoint>;
   table: TCryptoLibGenericArray<IECPoint>;
@@ -737,19 +715,19 @@ begin
   end;
   end;
 
 
   Curve := infos[0].PreComp[0].Curve;
   Curve := infos[0].PreComp[0].Curve;
-  infinity := Curve.infinity;
+  Infinity := Curve.Infinity;
 
 
-  R := infinity;
+  R := Infinity;
   zeroes := 0;
   zeroes := 0;
 
 
   i := len - 1;
   i := len - 1;
   while (i >= 0) do
   while (i >= 0) do
   begin
   begin
-    point := infinity;
+    point := Infinity;
 
 
-    for J := 0 to System.Pred(count) do
+    for j := 0 to System.Pred(count) do
     begin
     begin
-      wnaf := wnafs[J];
+      wnaf := wnafs[j];
       if i < System.length(wnaf) then
       if i < System.length(wnaf) then
       begin
       begin
         wi := Int32(ShortInt(wnaf[i]));
         wi := Int32(ShortInt(wnaf[i]));
@@ -762,8 +740,8 @@ begin
       if (wi <> 0) then
       if (wi <> 0) then
       begin
       begin
         n := System.Abs(wi);
         n := System.Abs(wi);
-        info := infos[J];
-        if (wi < 0 = negs[J]) then
+        info := infos[j];
+        if (wi < 0 = negs[j]) then
         begin
         begin
           table := info.PreComp;
           table := info.PreComp;
         end
         end
@@ -776,7 +754,7 @@ begin
       end;
       end;
     end;
     end;
 
 
-    if (point = infinity) then
+    if (point = Infinity) then
     begin
     begin
       System.Inc(zeroes);
       System.Inc(zeroes);
       System.Dec(i);
       System.Dec(i);
@@ -809,11 +787,10 @@ class function TECAlgorithms.ImplSumOfMultipliesGlv
   const glvEndomorphism: IGlvEndomorphism): IECPoint;
   const glvEndomorphism: IGlvEndomorphism): IECPoint;
 var
 var
   n: TBigInteger;
   n: TBigInteger;
-  len, i, J: Int32;
+  len, i, j: Int32;
   &abs, ab: TCryptoLibGenericArray<TBigInteger>;
   &abs, ab: TCryptoLibGenericArray<TBigInteger>;
-  pointMap: IECPointMap;
   pqs: TCryptoLibGenericArray<IECPoint>;
   pqs: TCryptoLibGenericArray<IECPoint>;
-  p, Q: IECPoint;
+  p, q: IECPoint;
 begin
 begin
   n := ps[0].Curve.Order;
   n := ps[0].Curve.Order;
 
 
@@ -822,40 +799,39 @@ begin
   System.SetLength(Abs, len shl 1);
   System.SetLength(Abs, len shl 1);
 
 
   i := 0;
   i := 0;
-  J := 0;
+  j := 0;
 
 
   while (i < len) do
   while (i < len) do
   begin
   begin
     ab := glvEndomorphism.DecomposeScalar(ks[i].&Mod(n));
     ab := glvEndomorphism.DecomposeScalar(ks[i].&Mod(n));
 
 
-    Abs[J] := ab[0];
-    System.Inc(J);
-    Abs[J] := ab[1];
-    System.Inc(J);
+    Abs[j] := ab[0];
+    System.Inc(j);
+    Abs[j] := ab[1];
+    System.Inc(j);
     System.Inc(i);
     System.Inc(i);
   end;
   end;
 
 
-  pointMap := glvEndomorphism.pointMap;
   if (glvEndomorphism.HasEfficientPointMap) then
   if (glvEndomorphism.HasEfficientPointMap) then
   begin
   begin
-    result := TECAlgorithms.ImplSumOfMultiplies(ps, pointMap, Abs);
+    result := TECAlgorithms.ImplSumOfMultiplies(glvEndomorphism, ps, Abs);
     Exit;
     Exit;
   end;
   end;
 
 
   System.SetLength(pqs, len shl 1);
   System.SetLength(pqs, len shl 1);
 
 
   i := 0;
   i := 0;
-  J := 0;
+  j := 0;
 
 
   while (i < len) do
   while (i < len) do
   begin
   begin
     p := ps[i];
     p := ps[i];
-    Q := pointMap.Map(p);
+    q := TEndoUtilities.MapPoint(glvEndomorphism, p);
 
 
-    pqs[J] := p;
-    System.Inc(J);
-    pqs[J] := Q;
-    System.Inc(J);
+    pqs[j] := p;
+    System.Inc(j);
+    pqs[j] := q;
+    System.Inc(j);
     System.Inc(i);
     System.Inc(i);
   end;
   end;
 
 
@@ -903,7 +879,7 @@ class procedure TECAlgorithms.MontgomeryTrick
   const scale: IECFieldElement);
   const scale: IECFieldElement);
 var
 var
   c: TCryptoLibGenericArray<IECFieldElement>;
   c: TCryptoLibGenericArray<IECFieldElement>;
-  i, J: Int32;
+  i, j: Int32;
   u, tmp: IECFieldElement;
   u, tmp: IECFieldElement;
 begin
 begin
   // /*
   // /*
@@ -935,10 +911,10 @@ begin
 
 
   while (i > 0) do
   while (i > 0) do
   begin
   begin
-    J := off + i;
+    j := off + i;
     System.Dec(i);
     System.Dec(i);
-    tmp := zs[J];
-    zs[J] := c[i].Multiply(u);
+    tmp := zs[j];
+    zs[j] := c[i].Multiply(u);
     u := u.Multiply(tmp);
     u := u.Multiply(tmp);
   end;
   end;
 
 
@@ -955,18 +931,18 @@ class function TECAlgorithms.ReferenceMultiply(const p: IECPoint;
   const k: TBigInteger): IECPoint;
   const k: TBigInteger): IECPoint;
 var
 var
   x: TBigInteger;
   x: TBigInteger;
-  Q, LP: IECPoint;
+  q, LP: IECPoint;
   t, i: Int32;
   t, i: Int32;
 begin
 begin
   LP := p;
   LP := p;
   x := k.Abs();
   x := k.Abs();
-  Q := LP.Curve.infinity;
+  q := LP.Curve.Infinity;
   t := x.BitLength;
   t := x.BitLength;
   if (t > 0) then
   if (t > 0) then
   begin
   begin
     if (x.TestBit(0)) then
     if (x.TestBit(0)) then
     begin
     begin
-      Q := LP;
+      q := LP;
     end;
     end;
     i := 1;
     i := 1;
     while (i < t) do
     while (i < t) do
@@ -974,7 +950,7 @@ begin
       LP := LP.Twice();
       LP := LP.Twice();
       if (x.TestBit(i)) then
       if (x.TestBit(i)) then
       begin
       begin
-        Q := Q.Add(LP);
+        q := q.Add(LP);
       end;
       end;
       System.Inc(i);
       System.Inc(i);
     end;
     end;
@@ -983,23 +959,23 @@ begin
 
 
   if k.SignValue < 0 then
   if k.SignValue < 0 then
   begin
   begin
-    result := Q.Negate();
+    result := q.Negate();
   end
   end
   else
   else
   begin
   begin
-    result := Q;
+    result := q;
   end;
   end;
 
 
 end;
 end;
 
 
 class function TECAlgorithms.ShamirsTrick(const p: IECPoint;
 class function TECAlgorithms.ShamirsTrick(const p: IECPoint;
-  const k: TBigInteger; const Q: IECPoint; const l: TBigInteger): IECPoint;
+  const k: TBigInteger; const q: IECPoint; const l: TBigInteger): IECPoint;
 var
 var
   cp: IECCurve;
   cp: IECCurve;
   LQ: IECPoint;
   LQ: IECPoint;
 begin
 begin
   cp := p.Curve;
   cp := p.Curve;
-  LQ := Q;
+  LQ := q;
   LQ := ImportPoint(cp, LQ);
   LQ := ImportPoint(cp, LQ);
 
 
   result := ImplCheckResult(ImplShamirsTrickJsf(p, k, LQ, l));
   result := ImplCheckResult(ImplShamirsTrickJsf(p, k, LQ, l));
@@ -1060,7 +1036,7 @@ begin
 end;
 end;
 
 
 class function TECAlgorithms.SumOfTwoMultiplies(const p: IECPoint;
 class function TECAlgorithms.SumOfTwoMultiplies(const p: IECPoint;
-  const a: TBigInteger; const Q: IECPoint; const b: TBigInteger): IECPoint;
+  const a: TBigInteger; const q: IECPoint; const b: TBigInteger): IECPoint;
 var
 var
   cp: IECCurve;
   cp: IECCurve;
   f2mCurve: IAbstractF2mCurve;
   f2mCurve: IAbstractF2mCurve;
@@ -1068,7 +1044,7 @@ var
   LQ: IECPoint;
   LQ: IECPoint;
 begin
 begin
   cp := p.Curve;
   cp := p.Curve;
-  LQ := Q;
+  LQ := q;
   LQ := ImportPoint(cp, LQ);
   LQ := ImportPoint(cp, LQ);
 
 
   // Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick
   // Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick
@@ -1090,711 +1066,4 @@ begin
   result := ImplCheckResult(ImplShamirsTrickWNaf(p, a, LQ, b));
   result := ImplCheckResult(ImplShamirsTrickWNaf(p, a, LQ, b));
 end;
 end;
 
 
-{ TWNafUtilities }
-
-class function TWNafUtilities.ResizeTable
-  (const a: TCryptoLibGenericArray<IECPoint>; length: Int32)
-  : TCryptoLibGenericArray<IECPoint>;
-begin
-  result := System.Copy(a);
-  System.SetLength(result, length);
-end;
-
-class function TWNafUtilities.Trim(const a: TCryptoLibInt32Array; length: Int32)
-  : TCryptoLibInt32Array;
-begin
-  result := System.Copy(a, 0, length);
-end;
-
-class function TWNafUtilities.Trim(const a: TCryptoLibByteArray; length: Int32)
-  : TCryptoLibByteArray;
-begin
-  result := System.Copy(a, 0, length);
-end;
-
-class function TWNafUtilities.CheckTable(const table
-  : TCryptoLibGenericArray<IECPoint>; reqLen: Int32): Boolean;
-begin
-  result := (table <> Nil) and (System.length(table) >= reqLen);
-end;
-
-class procedure TWNafUtilities.Boot;
-begin
-  FEMPTY_BYTES := Nil;
-  FEMPTY_INTS := Nil;
-end;
-
-class constructor TWNafUtilities.CreateWNafUtilities;
-begin
-  TWNafUtilities.Boot;
-end;
-
-class function TWNafUtilities.CheckExisting(const existingWNaf
-  : IWNafPreCompInfo; reqPreCompLen: Int32; includeNegated: Boolean): Boolean;
-begin
-  result := (existingWNaf <> Nil) and CheckTable(existingWNaf.PreComp,
-    reqPreCompLen) and ((not includeNegated) or
-    CheckTable(existingWNaf.PreCompNeg, reqPreCompLen));
-end;
-
-class function TWNafUtilities.GenerateCompactNaf(const k: TBigInteger)
-  : TCryptoLibInt32Array;
-var
-  _3k, diff: TBigInteger;
-  bits, highBit, &length, zeroes, i, digit: Int32;
-  naf: TCryptoLibInt32Array;
-begin
-  if ((TBits.Asr32(k.BitLength, 16)) <> 0) then
-  begin
-    raise EArgumentCryptoLibException.CreateRes(@SInvalidBitLength);
-  end;
-  if (k.SignValue = 0) then
-  begin
-    result := FEMPTY_INTS;
-    Exit;
-  end;
-
-  _3k := k.ShiftLeft(1).Add(k);
-
-  bits := _3k.BitLength;
-  System.SetLength(naf, TBits.Asr32(bits, 1));
-
-  diff := _3k.&Xor(k);
-
-  highBit := bits - 1;
-  &length := 0;
-  zeroes := 0;
-
-  i := 1;
-
-  while (i < highBit) do
-  begin
-    if (not diff.TestBit(i)) then
-    begin
-      System.Inc(zeroes);
-      System.Inc(i);
-      continue;
-    end;
-
-    if k.TestBit(i) then
-    begin
-      digit := -1;
-    end
-    else
-    begin
-      digit := 1;
-    end;
-
-    naf[length] := (digit shl 16) or zeroes;
-    System.Inc(length);
-    zeroes := 1;
-
-    System.Inc(i, 2);
-
-  end;
-
-  naf[length] := (1 shl 16) or zeroes;
-  System.Inc(length);
-
-  if (System.length(naf) > length) then
-  begin
-    naf := Trim(naf, length);
-  end;
-
-  result := naf;
-end;
-
-class function TWNafUtilities.GenerateCompactWindowNaf(width: Int32;
-  const k: TBigInteger): TCryptoLibInt32Array;
-var
-  wnaf: TCryptoLibInt32Array;
-  pow2, mask, sign, &length, &pos, digit, zeroes: Int32;
-  carry: Boolean;
-  LK: TBigInteger;
-begin
-  LK := k;
-  if (width = 2) then
-  begin
-    result := GenerateCompactNaf(LK);
-    Exit;
-  end;
-
-  if ((width < 2) or (width > 16)) then
-  begin
-    raise EArgumentCryptoLibException.CreateRes(@SInvalidRange);
-  end;
-  if ((TBits.Asr32(LK.BitLength, 16)) <> 0) then
-  begin
-    raise EArgumentCryptoLibException.CreateRes(@SInvalidBitLength);
-  end;
-  if (LK.SignValue = 0) then
-  begin
-    result := FEMPTY_INTS;
-    Exit;
-  end;
-
-  System.SetLength(wnaf, (LK.BitLength div width) + 1);
-
-  // 2^width and a mask and sign bit set accordingly
-  pow2 := 1 shl width;
-  mask := pow2 - 1;
-  sign := TBits.Asr32(pow2, 1);
-
-  carry := false;
-  length := 0;
-  pos := 0;
-
-  while (pos <= LK.BitLength) do
-  begin
-    if (LK.TestBit(pos) = carry) then
-    begin
-      System.Inc(pos);
-      continue;
-    end;
-
-    LK := LK.ShiftRight(pos);
-
-    digit := LK.Int32Value and mask;
-    if (carry) then
-    begin
-      System.Inc(digit);
-    end;
-
-    carry := (digit and sign) <> 0;
-    if (carry) then
-    begin
-      digit := digit - pow2;
-    end;
-
-    if length > 0 then
-    begin
-      zeroes := pos - 1;
-    end
-    else
-    begin
-      zeroes := pos;
-    end;
-
-    wnaf[length] := (digit shl 16) or zeroes;
-    System.Inc(length);
-    pos := width;
-  end;
-
-  // Reduce the WNAF array to its actual length
-  if (System.length(wnaf) > length) then
-  begin
-    wnaf := Trim(wnaf, length);
-  end;
-
-  result := wnaf;
-end;
-
-class function TWNafUtilities.GenerateJsf(const g, h: TBigInteger)
-  : TCryptoLibByteArray;
-var
-  digits, J, d0, d1, offset, n0, n1, u0, u1: Int32;
-  jsf: TCryptoLibByteArray;
-  k0, k1: TBigInteger;
-begin
-  digits := Max(g.BitLength, h.BitLength) + 1;
-
-  System.SetLength(jsf, digits);
-
-  k0 := g;
-  k1 := h;
-  J := 0;
-  d0 := 0;
-  d1 := 0;
-
-  offset := 0;
-
-  while (((d0 or d1) <> 0) or (k0.BitLength > offset) or
-    (k1.BitLength > offset)) do
-  begin
-    n0 := (Int32(UInt32(k0.Int32Value) shr offset) + d0) and 7;
-    n1 := (Int32(UInt32(k1.Int32Value) shr offset) + d1) and 7;
-
-    u0 := n0 and 1;
-    if (u0 <> 0) then
-    begin
-      u0 := u0 - (n0 and 2);
-      if (((n0 + u0) = 4) and ((n1 and 3) = 2)) then
-      begin
-        u0 := -u0;
-      end;
-    end;
-
-    u1 := n1 and 1;
-    if (u1 <> 0) then
-    begin
-      u1 := u1 - (n1 and 2);
-      if (((n1 + u1) = 4) and ((n0 and 3) = 2)) then
-      begin
-        u1 := -u1;
-      end;
-    end;
-
-    if ((d0 shl 1) = (1 + u0)) then
-    begin
-      d0 := d0 xor 1;
-    end;
-    if ((d1 shl 1) = (1 + u1)) then
-    begin
-      d1 := d1 xor 1;
-    end;
-
-    System.Inc(offset);
-    if (offset = 30) then
-    begin
-      offset := 0;
-      k0 := k0.ShiftRight(30);
-      k1 := k1.ShiftRight(30);
-    end;
-
-    jsf[J] := Byte((u0 shl 4) or (u1 and $F));
-    System.Inc(J);
-  end;
-
-  // Reduce the JSF array to its actual length
-  if (System.length(jsf) > J) then
-  begin
-    jsf := Trim(jsf, J);
-  end;
-
-  result := jsf;
-end;
-
-class function TWNafUtilities.GenerateNaf(const k: TBigInteger)
-  : TCryptoLibByteArray;
-var
-  _3k, diff: TBigInteger;
-  digits, i: Int32;
-  naf: TCryptoLibByteArray;
-begin
-  if (k.SignValue = 0) then
-  begin
-    result := FEMPTY_BYTES;
-    Exit;
-  end;
-
-  _3k := k.ShiftLeft(1).Add(k);
-
-  digits := _3k.BitLength - 1;
-  System.SetLength(naf, digits);
-
-  diff := _3k.&Xor(k);
-
-  i := 1;
-
-  while i < digits do
-  begin
-    if (diff.TestBit(i)) then
-    begin
-      if k.TestBit(i) then
-      begin
-        naf[i - 1] := Byte(-1);
-      end
-      else
-      begin
-        naf[i - 1] := Byte(1);
-      end;
-
-      System.Inc(i);
-    end;
-    System.Inc(i);
-  end;
-
-  naf[digits - 1] := 1;
-
-  result := naf;
-end;
-
-class function TWNafUtilities.GenerateWindowNaf(width: Int32;
-  const k: TBigInteger): TCryptoLibByteArray;
-var
-  wnaf: TCryptoLibByteArray;
-  pow2, mask, sign, &length, &pos, digit: Int32;
-  carry: Boolean;
-  LK: TBigInteger;
-begin
-  LK := k;
-  if (width = 2) then
-  begin
-    result := GenerateNaf(LK);
-    Exit;
-  end;
-
-  if ((width < 2) or (width > 8)) then
-  begin
-    raise EArgumentCryptoLibException.CreateRes(@SInvalidRange2);
-  end;
-  if (LK.SignValue = 0) then
-  begin
-    result := FEMPTY_BYTES;
-    Exit;
-  end;
-
-  System.SetLength(wnaf, LK.BitLength + 1);
-
-  // 2^width and a mask and sign bit set accordingly
-  pow2 := 1 shl width;
-  mask := pow2 - 1;
-  sign := TBits.Asr32(pow2, 1);
-
-  carry := false;
-  length := 0;
-  pos := 0;
-
-  while (pos <= LK.BitLength) do
-  begin
-    if (LK.TestBit(pos) = carry) then
-    begin
-      System.Inc(pos);
-      continue;
-    end;
-
-    LK := LK.ShiftRight(pos);
-
-    digit := LK.Int32Value and mask;
-    if (carry) then
-    begin
-      System.Inc(digit);
-    end;
-
-    carry := (digit and sign) <> 0;
-    if (carry) then
-    begin
-      digit := digit - pow2;
-    end;
-
-    if length > 0 then
-    begin
-      length := length + (pos - 1);
-    end
-    else
-    begin
-      length := length + (pos);
-    end;
-
-    wnaf[length] := Byte(digit);
-    System.Inc(length);
-    pos := width;
-  end;
-
-  // Reduce the WNAF array to its actual length
-  if (System.length(wnaf) > length) then
-  begin
-    wnaf := Trim(wnaf, length);
-  end;
-
-  result := wnaf;
-end;
-
-class function TWNafUtilities.GetNafWeight(const k: TBigInteger): Int32;
-var
-  _3k, diff: TBigInteger;
-begin
-  if (k.SignValue = 0) then
-  begin
-    result := 0;
-    Exit;
-  end;
-
-  _3k := k.ShiftLeft(1).Add(k);
-  diff := _3k.&Xor(k);
-
-  result := diff.BitCount;
-end;
-
-class function TWNafUtilities.GetWindowSize(bits: Int32;
-  const windowSizeCutoffs: array of Int32): Int32;
-var
-  w: Int32;
-begin
-  w := 0;
-  while (w < System.length(windowSizeCutoffs)) do
-  begin
-    if (bits < windowSizeCutoffs[w]) then
-    begin
-      break;
-    end;
-    System.Inc(w);
-  end;
-
-  result := w + 2;
-end;
-
-class function TWNafUtilities.GetWindowSize(bits: Int32): Int32;
-begin
-  result := GetWindowSize(bits, FDEFAULT_WINDOW_SIZE_CUTOFFS);
-end;
-
-class function TWNafUtilities.GetWNafPreCompInfo(const preCompInfo
-  : IPreCompInfo): IWNafPreCompInfo;
-begin
-  result := preCompInfo as IWNafPreCompInfo;
-end;
-
-class function TWNafUtilities.GetWNafPreCompInfo(const p: IECPoint)
-  : IWNafPreCompInfo;
-var
-  preCompInfo: IPreCompInfo;
-begin
-  preCompInfo := p.Curve.GetPreCompInfo(p, PRECOMP_NAME);
-  result := GetWNafPreCompInfo(preCompInfo);
-end;
-
-class function TWNafUtilities.MapPointWithPrecomp(const p: IECPoint;
-  width: Int32; includeNegated: Boolean; const pointMap: IECPointMap): IECPoint;
-var
-  c: IECCurve;
-  wnafPreCompP: IWNafPreCompInfo;
-  Q: IECPoint;
-begin
-  c := p.Curve;
-
-  wnafPreCompP := Precompute(p, width, includeNegated);
-
-  Q := pointMap.Map(p);
-
-  c.Precompute(Q, PRECOMP_NAME, TMapPointCallback.Create(wnafPreCompP,
-    includeNegated, pointMap) as IMapPointCallback);
-
-  result := Q;
-
-end;
-
-class function TWNafUtilities.Precompute(const p: IECPoint; width: Int32;
-  includeNegated: Boolean): IWNafPreCompInfo;
-begin
-  result := p.Curve.Precompute(p, PRECOMP_NAME, TWNafCallback.Create(p, width,
-    includeNegated) as IWNafCallback) as IWNafPreCompInfo;
-end;
-
-{ TWNafUtilities.TMapPointCallback }
-
-constructor TWNafUtilities.TMapPointCallback.Create(const wnafPreCompP
-  : IWNafPreCompInfo; includeNegated: Boolean; const pointMap: IECPointMap);
-begin
-  Inherited Create();
-  Fm_wnafPreCompP := wnafPreCompP;
-  Fm_includeNegated := includeNegated;
-  Fm_pointMap := pointMap;
-end;
-
-function TWNafUtilities.TMapPointCallback.Precompute(const existing
-  : IPreCompInfo): IPreCompInfo;
-var
-  tempResult: IWNafPreCompInfo;
-  twiceP, twiceQ: IECPoint;
-  preCompP, preCompQ, preCompNegQ: TCryptoLibGenericArray<IECPoint>;
-  i: Int32;
-begin
-  tempResult := TWNafPreCompInfo.Create();
-
-  twiceP := Fm_wnafPreCompP.Twice;
-  if (twiceP <> Nil) then
-  begin
-    twiceQ := Fm_pointMap.Map(twiceP);
-    tempResult.Twice := twiceQ;
-  end;
-
-  preCompP := Fm_wnafPreCompP.PreComp;
-
-  System.SetLength(preCompQ, System.length(preCompP));
-  for i := 0 to System.Pred(System.length(preCompP)) do
-  begin
-    preCompQ[i] := Fm_pointMap.Map(preCompP[i]);
-  end;
-
-  tempResult.PreComp := preCompQ;
-
-  if (Fm_includeNegated) then
-  begin
-
-    System.SetLength(preCompNegQ, System.length(preCompQ));
-
-    for i := 0 to System.Pred(System.length(preCompNegQ)) do
-    begin
-      preCompNegQ[i] := preCompQ[i].Negate();
-    end;
-
-    tempResult.PreCompNeg := preCompNegQ;
-  end;
-
-  result := tempResult;
-end;
-
-{ TWNafUtilities.TWNafCallback }
-
-constructor TWNafUtilities.TWNafCallback.Create(const p: IECPoint; width: Int32;
-  includeNegated: Boolean);
-begin
-  Inherited Create();
-  Fm_p := p;
-  Fm_width := width;
-  Fm_includeNegated := includeNegated;
-end;
-
-function TWNafUtilities.TWNafCallback.Precompute(const existing: IPreCompInfo)
-  : IPreCompInfo;
-var
-  twiceP, isoTwiceP, last: IECPoint;
-  c: IECCurve;
-  PreComp, PreCompNeg, EMPTY_POINTS: TCryptoLibGenericArray<IECPoint>;
-  tempRes, existingWNaf: IWNafPreCompInfo;
-  reqPreCompLen, iniPreCompLen, curPreCompLen, pos: Int32;
-  iso, iso2, iso3: IECFieldElement;
-begin
-  EMPTY_POINTS := Nil;
-  existingWNaf := existing as IWNafPreCompInfo;
-
-  reqPreCompLen := 1 shl Max(0, Fm_width - 2);
-
-  if (CheckExisting(existingWNaf, reqPreCompLen, Fm_includeNegated)) then
-  begin
-    result := existingWNaf;
-    Exit;
-  end;
-
-  c := Fm_p.Curve;
-
-  if (existingWNaf <> Nil) then
-  begin
-    PreComp := existingWNaf.PreComp;
-    PreCompNeg := existingWNaf.PreCompNeg;
-    twiceP := existingWNaf.Twice;
-  end;
-
-  iniPreCompLen := 0;
-  if (PreComp = Nil) then
-  begin
-    PreComp := EMPTY_POINTS;
-  end
-  else
-  begin
-    iniPreCompLen := System.length(PreComp);
-  end;
-
-  if (iniPreCompLen < reqPreCompLen) then
-  begin
-    PreComp := TWNafUtilities.ResizeTable(PreComp, reqPreCompLen);
-
-    if (reqPreCompLen = 1) then
-    begin
-      PreComp[0] := Fm_p.Normalize();
-    end
-    else
-    begin
-      curPreCompLen := iniPreCompLen;
-      if (curPreCompLen = 0) then
-      begin
-        PreComp[0] := Fm_p;
-        curPreCompLen := 1;
-      end;
-
-      if (reqPreCompLen = 2) then
-      begin
-        PreComp[1] := Fm_p.threeTimes();
-      end
-      else
-      begin
-        isoTwiceP := twiceP;
-        last := PreComp[curPreCompLen - 1];
-        if (isoTwiceP = Nil) then
-        begin
-          isoTwiceP := PreComp[0].Twice();
-          twiceP := isoTwiceP;
-          //
-          // /*
-          // * For Fp curves with Jacobian projective coordinates, use a (quasi-)isomorphism
-          // * where 'twiceP' is "affine", so that the subsequent additions are cheaper. This
-          // * also requires scaling the initial point's X, Y coordinates, and reversing the
-          // * isomorphism as part of the subsequent normalization.
-          // *
-          // *  NOTE: The correctness of this optimization depends on:
-          // *      1) additions do not use the curve's A, B coefficients.
-          // *      2) no special cases (i.e. Q +/- Q) when calculating 1P, 3P, 5P, ...
-          // */
-          if ((not(twiceP.IsInfinity)) and (TECAlgorithms.IsFpCurve(c)) and
-            (c.FieldSize >= 64)) then
-          begin
-            case (c.CoordinateSystem) of
-              TECCurveConstants.COORD_JACOBIAN,
-                TECCurveConstants.COORD_JACOBIAN_CHUDNOVSKY,
-                TECCurveConstants.COORD_JACOBIAN_MODIFIED:
-
-                begin
-                  iso := twiceP.GetZCoord(0);
-                  isoTwiceP := c.CreatePoint(twiceP.XCoord.ToBigInteger,
-                    twiceP.YCoord.ToBigInteger());
-
-                  iso2 := iso.square();
-                  iso3 := iso2.Multiply(iso);
-                  last := last.scaleX(iso2).scaleY(iso3);
-
-                  if (iniPreCompLen = 0) then
-                  begin
-                    PreComp[0] := last;
-                  end;
-                end;
-
-            end;
-
-          end;
-        end;
-
-        while (curPreCompLen < reqPreCompLen) do
-        begin
-          // /*
-          // * Compute the new ECPoints for the precomputation array. The values 1, 3,
-          // * 5, ..., 2^(width-1)-1 times p are computed
-          // */
-          last := last.Add(isoTwiceP);
-          PreComp[curPreCompLen] := last;
-          System.Inc(curPreCompLen);
-        end;
-      end;
-      //
-      // /*
-      // * Having oft-used operands in affine form makes operations faster.
-      // */
-      c.NormalizeAll(PreComp, iniPreCompLen,
-        reqPreCompLen - iniPreCompLen, iso);
-    end;
-  end;
-
-  if (Fm_includeNegated) then
-  begin
-
-    if (PreCompNeg = Nil) then
-    begin
-      pos := 0;
-      System.SetLength(PreCompNeg, reqPreCompLen);
-
-    end
-    else
-    begin
-      pos := System.length(PreCompNeg);
-      if (pos < reqPreCompLen) then
-      begin
-        PreCompNeg := TWNafUtilities.ResizeTable(PreCompNeg, reqPreCompLen);
-      end;
-    end;
-
-    while (pos < reqPreCompLen) do
-    begin
-      PreCompNeg[pos] := PreComp[pos].Negate();
-      System.Inc(pos);
-    end;
-  end;
-
-  tempRes := TWNafPreCompInfo.Create();
-  tempRes.PreComp := PreComp;
-  tempRes.PreCompNeg := PreCompNeg;
-  tempRes.Twice := twiceP;
-
-  result := tempRes;
-end;
-
 end.
 end.

+ 319 - 105
src/libraries/cryptolib4pascal/ClpECC.pas

@@ -37,9 +37,7 @@ uses
   ClpIGlvEndomorphism,
   ClpIGlvEndomorphism,
   ClpECAlgorithms,
   ClpECAlgorithms,
   ClpLongArray,
   ClpLongArray,
-  ClpGlvMultiplier,
-  ClpWNafL2RMultiplier,
-  ClpWTauNafMultiplier,
+  ClpMultipliers,
   ClpFiniteFields,
   ClpFiniteFields,
   ClpSetWeakRef,
   ClpSetWeakRef,
   ClpECCurveConstants,
   ClpECCurveConstants,
@@ -95,6 +93,7 @@ resourcestring
   SNotProjectiveCoordSystem = 'Not a Projective Coordinate System';
   SNotProjectiveCoordSystem = 'Not a Projective Coordinate System';
   SCannotBeNegative = 'Cannot be Negative, "e"';
   SCannotBeNegative = 'Cannot be Negative, "e"';
   SNilFieldElement = 'Exactly one of the Field Elements is Nil';
   SNilFieldElement = 'Exactly one of the Field Elements is Nil';
+  SUnsupportedOperation = 'Constant-time Lookup not Supported';
 
 
 type
 type
   TECFieldElement = class abstract(TInterfacedObject, IECFieldElement)
   TECFieldElement = class abstract(TInterfacedObject, IECFieldElement)
@@ -260,6 +259,7 @@ type
   public
   public
     function Trace(): Int32; virtual;
     function Trace(): Int32; virtual;
     function HalfTrace(): IECFieldElement; virtual;
     function HalfTrace(): IECFieldElement; virtual;
+    function HasFastTrace(): Boolean; virtual;
 
 
   end;
   end;
 
 
@@ -474,19 +474,10 @@ type
   /// </summary>
   /// </summary>
   TECCurve = class abstract(TInterfacedObject, IECCurve)
   TECCurve = class abstract(TInterfacedObject, IECCurve)
 
 
-  strict private
-
-    class procedure Boot(); static;
-    class constructor CreateECCurve();
-    class destructor DestroyECCurve();
-
   strict protected
   strict protected
 
 
-    class var
-
-      FLock: TCriticalSection;
-
   var
   var
+    FLock: TCriticalSection;
     Fm_field: IFiniteField;
     Fm_field: IFiniteField;
     Fm_order, Fm_cofactor: TBigInteger;
     Fm_order, Fm_cofactor: TBigInteger;
 
 
@@ -700,20 +691,61 @@ type
   end;
   end;
 
 
 type
 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
   strict private
   var
   var
     Fm_outer: IECCurve;
     Fm_outer: IECCurve;
     Fm_table: TCryptoLibByteArray;
     Fm_table: TCryptoLibByteArray;
     Fm_size: Int32;
     Fm_size: Int32;
 
 
+    function CreatePoint(const x, y: TCryptoLibByteArray): IECPoint;
+
+  strict protected
+    function GetSize: Int32; override;
+
   public
   public
     constructor Create(const outer: IECCurve; const table: TCryptoLibByteArray;
     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;
   end;
 
 
@@ -733,20 +765,24 @@ type
   end;
   end;
 
 
 type
 type
-  TDefaultF2mLookupTable = class(TInterfacedObject, IDefaultF2mLookupTable,
-    IECLookupTable)
+  TDefaultF2mLookupTable = class(TAbstractECLookupTable, IDefaultF2mLookupTable)
   strict private
   strict private
   var
   var
     Fm_outer: IF2mCurve;
     Fm_outer: IF2mCurve;
     Fm_table: TCryptoLibInt64Array;
     Fm_table: TCryptoLibInt64Array;
     Fm_size: Int32;
     Fm_size: Int32;
 
 
+    function CreatePoint(const x, y: TCryptoLibInt64Array): IECPoint;
+
+  strict protected
+    function GetSize: Int32; override;
+
   public
   public
     constructor Create(const outer: IF2mCurve;
     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;
   end;
 
 
@@ -1167,6 +1203,9 @@ type
     function ScaleX(const scale: IECFieldElement): IECPoint; virtual;
     function ScaleX(const scale: IECFieldElement): IECPoint; virtual;
     function ScaleY(const scale: IECFieldElement): IECPoint; virtual;
     function ScaleY(const scale: IECFieldElement): IECPoint; virtual;
 
 
+    function ScaleXNegateY(const scale: IECFieldElement): IECPoint; virtual;
+    function ScaleYNegateX(const scale: IECFieldElement): IECPoint; virtual;
+
     function GetEncoded(): TCryptoLibByteArray; overload; virtual;
     function GetEncoded(): TCryptoLibByteArray; overload; virtual;
     function GetEncoded(compressed: Boolean): TCryptoLibByteArray; overload;
     function GetEncoded(compressed: Boolean): TCryptoLibByteArray; overload;
       virtual; abstract;
       virtual; abstract;
@@ -1409,6 +1448,9 @@ type
     function ScaleX(const scale: IECFieldElement): IECPoint; override;
     function ScaleX(const scale: IECFieldElement): IECPoint; override;
     function ScaleY(const scale: IECFieldElement): IECPoint; override;
     function ScaleY(const scale: IECFieldElement): IECPoint; override;
 
 
+    function ScaleXNegateY(const scale: IECFieldElement): IECPoint; override;
+    function ScaleYNegateX(const scale: IECFieldElement): IECPoint; override;
+
     function Subtract(const b: IECPoint): IECPoint; override;
     function Subtract(const b: IECPoint): IECPoint; override;
 
 
     function Tau(): IAbstractF2mPoint; virtual;
     function Tau(): IAbstractF2mPoint; virtual;
@@ -2442,8 +2484,8 @@ end;
 
 
 function TAbstractF2mFieldElement.HalfTrace: IECFieldElement;
 function TAbstractF2mFieldElement.HalfTrace: IECFieldElement;
 var
 var
-  m, i: Int32;
-  fe, ht: IECFieldElement;
+  m, n, K, nk: Int32;
+  ht: IECFieldElement;
 begin
 begin
   m := FieldSize;
   m := FieldSize;
   if ((m and 1) = 0) then
   if ((m and 1) = 0) then
@@ -2451,34 +2493,53 @@ begin
     raise EArgumentCryptoLibException.CreateRes(@SHalfTraceUndefinedForM);
     raise EArgumentCryptoLibException.CreateRes(@SHalfTraceUndefinedForM);
   end;
   end;
 
 
-  fe := Self as IECFieldElement;
-  ht := fe;
-  i := 2;
-  while i < m do
+  n := TBits.Asr32((m + 1), 1);
+  K := 31 - TBits.NumberOfLeadingZeros(n);
+  nk := 1;
+
+  ht := Self as IECFieldElement;
+  while (K > 0) do
   begin
   begin
-    fe := fe.SquarePow(2);
-    ht := ht.Add(fe);
-    System.Inc(i, 2);
-  end;
+    ht := ht.SquarePow(nk shl 1).Add(ht);
+    System.Dec(K);
+    nk := TBits.Asr32(n, K);
 
 
+    if ((nk and 1) <> 0) then
+    begin
+      ht := ht.SquarePow(2).Add(Self as IECFieldElement);
+    end;
+  end;
   result := ht;
   result := ht;
 end;
 end;
 
 
+function TAbstractF2mFieldElement.HasFastTrace: Boolean;
+begin
+  result := false;
+
+end;
+
 function TAbstractF2mFieldElement.Trace: Int32;
 function TAbstractF2mFieldElement.Trace: Int32;
 var
 var
-  m, i: Int32;
-  fe, tr: IECFieldElement;
+  m, K, mk: Int32;
+  tr: IECFieldElement;
 begin
 begin
   m := FieldSize;
   m := FieldSize;
-  fe := Self as IECFieldElement;
-  tr := fe;
 
 
-  i := 1;
-  while i < m do
+  K := 31 - TBits.NumberOfLeadingZeros(m);
+  mk := 1;
+
+  tr := Self as IECFieldElement;
+  while (K > 0) do
   begin
   begin
-    fe := fe.Square();
-    tr := tr.Add(fe);
-    System.Inc(i);
+    tr := tr.SquarePow(mk).Add(tr);
+
+    System.Dec(K);
+    mk := TBits.Asr32(m, K);
+
+    if ((mk and 1) <> 0) then
+    begin
+      tr := tr.Square().Add(Self as IECFieldElement);
+    end;
   end;
   end;
 
 
   if (tr.IsZero) then
   if (tr.IsZero) then
@@ -2496,14 +2557,6 @@ end;
 
 
 { TECCurve }
 { TECCurve }
 
 
-class procedure TECCurve.Boot;
-begin
-  if FLock = Nil then
-  begin
-    FLock := TCriticalSection.Create;
-  end;
-end;
-
 procedure TECCurve.CheckPoint(const point: IECPoint);
 procedure TECCurve.CheckPoint(const point: IECPoint);
 begin
 begin
   if ((point = Nil) or ((Self as IECCurve) <> point.curve)) then
   if ((point = Nil) or ((Self as IECCurve) <> point.curve)) then
@@ -2552,9 +2605,16 @@ end;
 constructor TECCurve.Create(const field: IFiniteField);
 constructor TECCurve.Create(const field: IFiniteField);
 begin
 begin
   inherited Create();
   inherited Create();
+  FLock := TCriticalSection.Create;
   Fm_field := field;
   Fm_field := field;
 end;
 end;
 
 
+destructor TECCurve.Destroy;
+begin
+  FLock.Free;
+  inherited Destroy;
+end;
+
 function TECCurve.CreateCacheSafeLookupTable(const points
 function TECCurve.CreateCacheSafeLookupTable(const points
   : TCryptoLibGenericArray<IECPoint>; off, len: Int32): IECLookupTable;
   : TCryptoLibGenericArray<IECPoint>; off, len: Int32): IECLookupTable;
 var
 var
@@ -2618,11 +2678,6 @@ begin
   result := TWNafL2RMultiplier.Create();
   result := TWNafL2RMultiplier.Create();
 end;
 end;
 
 
-class constructor TECCurve.CreateECCurve;
-begin
-  TECCurve.Boot;
-end;
-
 function TECCurve.CreatePoint(const x, y: TBigInteger): IECPoint;
 function TECCurve.CreatePoint(const x, y: TBigInteger): IECPoint;
 begin
 begin
   result := CreatePoint(x, y, false);
   result := CreatePoint(x, y, false);
@@ -2728,16 +2783,6 @@ begin
   result := P;
   result := P;
 end;
 end;
 
 
-destructor TECCurve.Destroy;
-begin
-  inherited Destroy;
-end;
-
-class destructor TECCurve.DestroyECCurve;
-begin
-  FLock.Free;
-end;
-
 function TECCurve.Equals(const other: IECCurve): Boolean;
 function TECCurve.Equals(const other: IECCurve): Boolean;
 begin
 begin
   if ((Self as IECCurve) = other) then
   if ((Self as IECCurve) = other) then
@@ -3397,9 +3442,36 @@ end;
 function TAbstractF2mCurve.SolveQuadraticEquation(const beta: IECFieldElement)
 function TAbstractF2mCurve.SolveQuadraticEquation(const beta: IECFieldElement)
   : IECFieldElement;
   : IECFieldElement;
 var
 var
-  gamma, z, zeroElement, t, w, w2: IECFieldElement;
+  gamma, z, zeroElement, t, w, w2, r: IECFieldElement;
+  betaF2m: IAbstractF2mFieldElement;
   m, i: Int32;
   m, i: Int32;
+  fastTrace: Boolean;
 begin
 begin
+
+  betaF2m := beta as IAbstractF2mFieldElement;
+
+  fastTrace := betaF2m.HasFastTrace();
+  if ((fastTrace) and (betaF2m.Trace() <> 0)) then
+  begin
+    result := Nil;
+    Exit;
+  end;
+
+  m := FieldSize;
+
+  // For odd m, use the half-trace
+  if ((m and 1) <> 0) then
+  begin
+    r := betaF2m.HalfTrace();
+    if ((fastTrace) or (r.Square().Add(r).Add(beta).IsZero)) then
+    begin
+      result := r;
+      Exit;
+    end;
+    result := Nil;
+    Exit;
+  end;
+
   if (beta.IsZero) then
   if (beta.IsZero) then
   begin
   begin
     result := beta;
     result := beta;
@@ -3628,12 +3700,22 @@ end;
 { TDefaultLookupTable }
 { TDefaultLookupTable }
 
 
 constructor TDefaultLookupTable.Create(const outer: IECCurve;
 constructor TDefaultLookupTable.Create(const outer: IECCurve;
-  const table: TCryptoLibByteArray; size: Int32);
+  const table: TCryptoLibByteArray; Size: Int32);
 begin
 begin
   Inherited Create();
   Inherited Create();
   Fm_outer := outer;
   Fm_outer := outer;
   Fm_table := table;
   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;
 end;
 
 
 function TDefaultLookupTable.GetSize: Int32;
 function TDefaultLookupTable.GetSize: Int32;
@@ -3646,7 +3728,6 @@ var
   FE_BYTES, position, i, j: Int32;
   FE_BYTES, position, i, j: Int32;
   x, y: TCryptoLibByteArray;
   x, y: TCryptoLibByteArray;
   MASK: Byte;
   MASK: Byte;
-  XFieldElement, YFieldElement: IECFieldElement;
 begin
 begin
   FE_BYTES := (Fm_outer.FieldSize + 7) div 8;
   FE_BYTES := (Fm_outer.FieldSize + 7) div 8;
   System.SetLength(x, FE_BYTES);
   System.SetLength(x, FE_BYTES);
@@ -3661,41 +3742,52 @@ begin
 
 
     for j := 0 to System.Pred(FE_BYTES) do
     for j := 0 to System.Pred(FE_BYTES) do
     begin
     begin
-
       x[j] := x[j] xor Byte(Fm_table[position + j] and MASK);
       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);
       y[j] := y[j] xor Byte(Fm_table[position + FE_BYTES + j] and MASK);
     end;
     end;
     position := position + (FE_BYTES * 2);
     position := position + (FE_BYTES * 2);
   end;
   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;
 end;
 
 
 { TDefaultF2mLookupTable }
 { TDefaultF2mLookupTable }
 
 
 constructor TDefaultF2mLookupTable.Create(const outer: IF2mCurve;
 constructor TDefaultF2mLookupTable.Create(const outer: IF2mCurve;
-  const table: TCryptoLibInt64Array; size: Int32);
+  const table: TCryptoLibInt64Array; Size: Int32);
 begin
 begin
   Inherited Create();
   Inherited Create();
   Fm_outer := outer;
   Fm_outer := outer;
   Fm_table := table;
   Fm_table := table;
-  Fm_size := size;
-end;
-
-function TDefaultF2mLookupTable.GetSize: Int32;
-begin
-  result := Fm_size;
+  Fm_size := Size;
 end;
 end;
 
 
-function TDefaultF2mLookupTable.Lookup(index: Int32): IECPoint;
+function TDefaultF2mLookupTable.CreatePoint(const x, y: TCryptoLibInt64Array)
+  : IECPoint;
 var
 var
-  FE_LONGS, position, m, i, j: Int32;
-  ks: TCryptoLibInt32Array;
-  x, y: TCryptoLibInt64Array;
-  MASK: Int64;
   XFieldElement, YFieldElement: IECFieldElement;
   XFieldElement, YFieldElement: IECFieldElement;
+  m: Int32;
+  ks: TCryptoLibInt32Array;
 begin
 begin
   m := Fm_outer.m;
   m := Fm_outer.m;
   if Fm_outer.IsTrinomial() then
   if Fm_outer.IsTrinomial() then
@@ -3707,6 +3799,22 @@ begin
     ks := TCryptoLibInt32Array.Create(Fm_outer.k1, Fm_outer.k2, Fm_outer.k3);
     ks := TCryptoLibInt32Array.Create(Fm_outer.k1, Fm_outer.k2, Fm_outer.k3);
   end;
   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;
   FE_LONGS := (Fm_outer.m + 63) div 64;
   System.SetLength(x, FE_LONGS);
   System.SetLength(x, FE_LONGS);
   System.SetLength(y, FE_LONGS);
   System.SetLength(y, FE_LONGS);
@@ -3720,16 +3828,33 @@ begin
 
 
     for j := 0 to System.Pred(FE_LONGS) do
     for j := 0 to System.Pred(FE_LONGS) do
     begin
     begin
-
       x[j] := x[j] xor (Fm_table[position + j] and MASK);
       x[j] := x[j] xor (Fm_table[position + j] and MASK);
       y[j] := y[j] xor (Fm_table[position + FE_LONGS + j] and MASK);
       y[j] := y[j] xor (Fm_table[position + FE_LONGS + j] and MASK);
     end;
     end;
     position := position + (FE_LONGS * 2);
     position := position + (FE_LONGS * 2);
   end;
   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;
 end;
 
 
 { TECPoint }
 { TECPoint }
@@ -3823,6 +3948,19 @@ begin
   end;
   end;
 end;
 end;
 
 
+function TECPoint.ScaleXNegateY(const scale: IECFieldElement): IECPoint;
+begin
+  if IsInfinity then
+  begin
+    result := Self;
+  end
+  else
+  begin
+    result := curve.CreateRawPoint(RawXCoord.Multiply(scale), RawYCoord.Negate,
+      RawZCoords, IsCompressed);
+  end;
+end;
+
 function TECPoint.ScaleY(const scale: IECFieldElement): IECPoint;
 function TECPoint.ScaleY(const scale: IECFieldElement): IECPoint;
 begin
 begin
   if IsInfinity then
   if IsInfinity then
@@ -3836,6 +3974,19 @@ begin
   end;
   end;
 end;
 end;
 
 
+function TECPoint.ScaleYNegateX(const scale: IECFieldElement): IECPoint;
+begin
+  if IsInfinity then
+  begin
+    result := Self;
+  end
+  else
+  begin
+    result := curve.CreateRawPoint(RawXCoord.Negate, RawYCoord.Multiply(scale),
+      RawZCoords, IsCompressed);
+  end;
+end;
+
 procedure TECPoint.SetpreCompTable(const Value
 procedure TECPoint.SetpreCompTable(const Value
   : TDictionary<String, IPreCompInfo>);
   : TDictionary<String, IPreCompInfo>);
 begin
 begin
@@ -6226,21 +6377,23 @@ function TAbstractF2mPoint.SatisfiesOrder: Boolean;
 var
 var
   Cofactor: TBigInteger;
   Cofactor: TBigInteger;
   n: IECPoint;
   n: IECPoint;
-  x, rhs, lambda, w, t: IECFieldElement;
+  x, rhs, L, t, y: IECFieldElement;
   Lcurve: IECCurve;
   Lcurve: IECCurve;
 begin
 begin
   Lcurve := curve;
   Lcurve := curve;
   Cofactor := Lcurve.GetCofactor();
   Cofactor := Lcurve.GetCofactor();
   if (TBigInteger.Two.Equals(Cofactor)) then
   if (TBigInteger.Two.Equals(Cofactor)) then
   begin
   begin
-    // /*
-    // *  Check that the trace of (X + A) is 0, then there exists a solution to L^2 + L = X + A,
-    // *  and so a halving is possible, so this point is the double of another.
-    // */
+    (*
+      * Check that 0 == Tr(X + A); then there exists a solution to L^2 + L = X + A, and
+      * so a halving is possible, so this point is the double of another.
+      *
+      * Note: Tr(A) == 1 for cofactor 2 curves.
+    *)
     n := Normalize();
     n := Normalize();
     x := n.AffineXCoord;
     x := n.AffineXCoord;
     rhs := x.Add(Lcurve.a);
     rhs := x.Add(Lcurve.a);
-    result := (rhs as IAbstractF2mFieldElement).Trace() = 0;
+    result := (x as IAbstractF2mFieldElement).Trace() <> 0;
     Exit;
     Exit;
   end;
   end;
   if (TBigInteger.Four.Equals(Cofactor)) then
   if (TBigInteger.Four.Equals(Cofactor)) then
@@ -6251,21 +6404,33 @@ begin
     // * and check if Tr(w + A) == 0 for at least one; then a second halving is possible
     // * and check if Tr(w + A) == 0 for at least one; then a second halving is possible
     // * (see comments for cofactor 2 above), so this point is four times another.
     // * (see comments for cofactor 2 above), so this point is four times another.
     // *
     // *
-    // * Note: Tr(x^2) == Tr(x).
+    // * Note: Tr(A) == 0 for cofactor 4 curves.
     // */
     // */
     n := Normalize();
     n := Normalize();
     x := n.AffineXCoord;
     x := n.AffineXCoord;
-    lambda := (Lcurve as IAbstractF2mCurve).SolveQuadraticEquation
-      (x.Add(curve.a));
-    if (lambda = Nil) then
+    L := (Lcurve as IAbstractF2mCurve).SolveQuadraticEquation(x.Add(curve.a));
+    if (L = Nil) then
     begin
     begin
       result := false;
       result := false;
       Exit;
       Exit;
     end;
     end;
-    w := x.Multiply(lambda).Add(n.AffineYCoord);
-    t := w.Add(Lcurve.a);
-    result := ((t as IAbstractF2mFieldElement).Trace() = 0) or
-      ((t.Add(x) as IAbstractF2mFieldElement).Trace() = 0);
+
+    (*
+      * A solution exists, therefore 0 == Tr(X + A) == Tr(X).
+    *)
+    y := n.AffineYCoord;
+    t := x.Multiply(L).Add(y);
+
+    (*
+      * Either T or (T + X) is the square of a half-point's x coordinate (hx). In either
+      * case, the half-point can be halved again when 0 == Tr(hx + A).
+      *
+      * Note: Tr(hx + A) == Tr(hx) == Tr(hx^2) == Tr(T) == Tr(T + X)
+      *
+      * Check that 0 == Tr(T); then there exists a solution to L^2 + L = hx + A, and so a
+      * second halving is possible and this point is four times some other.
+    *)
+    result := (t as IAbstractF2mFieldElement).Trace() = 0;
     Exit;
     Exit;
   end;
   end;
 
 
@@ -6321,6 +6486,12 @@ begin
 
 
 end;
 end;
 
 
+function TAbstractF2mPoint.ScaleXNegateY(const scale: IECFieldElement)
+  : IECPoint;
+begin
+  result := ScaleX(scale);
+end;
+
 function TAbstractF2mPoint.ScaleY(const scale: IECFieldElement): IECPoint;
 function TAbstractF2mPoint.ScaleY(const scale: IECFieldElement): IECPoint;
 var
 var
   Lx, L, L2: IECFieldElement;
   Lx, L, L2: IECFieldElement;
@@ -6352,6 +6523,12 @@ begin
 
 
 end;
 end;
 
 
+function TAbstractF2mPoint.ScaleYNegateX(const scale: IECFieldElement)
+  : IECPoint;
+begin
+  result := ScaleY(scale);
+end;
+
 function TAbstractF2mPoint.Subtract(const b: IECPoint): IECPoint;
 function TAbstractF2mPoint.Subtract(const b: IECPoint): IECPoint;
 begin
 begin
   if (b.IsInfinity) then
   if (b.IsInfinity) then
@@ -6505,4 +6682,41 @@ begin
   result := info;
   result := info;
 end;
 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.
 end.

+ 1534 - 0
src/libraries/cryptolib4pascal/ClpECCompUtilities.pas

@@ -0,0 +1,1534 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpECCompUtilities;
+
+{$I CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  Math,
+  ClpBits,
+  ClpIECC,
+  ClpIPreCompInfo,
+  ClpIWNafPreCompInfo,
+  ClpWNafPreCompInfo,
+  ClpEndoPreCompInfo,
+  ClpIFixedPointPreCompInfo,
+  ClpIPreCompCallBack,
+  ClpBigInteger,
+  ClpIEndoPreCompInfo,
+  ClpIScalarSplitParameters,
+  ClpFixedPointPreCompInfo,
+  ClpCryptoLibTypes,
+  ClpECCurveConstants;
+
+resourcestring
+  SInvalidRange = 'Must be in the Range [2, 16], "width"';
+  SInvalidRange2 = 'Must be in the Range [2, 8], "width"';
+
+type
+  TWNafUtilities = class abstract(TObject)
+
+  strict private
+  const
+    DEFAULT_WINDOW_SIZE_CUTOFFS: array [0 .. 5] of Int32 = (13, 41, 121, 337,
+      897, 2305);
+
+    MAX_WIDTH = Int32(16);
+
+  class var
+    FEMPTY_BYTES: TCryptoLibByteArray;
+    FEMPTY_INTS: TCryptoLibInt32Array;
+
+  type
+    IMapPointCallback = interface(IPreCompCallback)
+      ['{730BF27F-D5C3-4DF4-AC77-B8653C457C10}']
+
+    end;
+
+  type
+    TMapPointCallback = class(TInterfacedObject, IPreCompCallback,
+      IMapPointCallback)
+
+    strict private
+    var
+      Fm_wnafPreCompP: IWNafPreCompInfo;
+      Fm_includeNegated: Boolean;
+      Fm_pointMap: IECPointMap;
+
+    public
+      constructor Create(const wnafPreCompP: IWNafPreCompInfo;
+        includeNegated: Boolean; const pointMap: IECPointMap);
+
+      function Precompute(const existing: IPreCompInfo): IPreCompInfo;
+
+    end;
+
+  type
+    IWNafCallback = interface(IPreCompCallback)
+      ['{A439A606-7899-4720-937E-C2F3D94D4811}']
+
+    end;
+
+  type
+    TWNafCallback = class(TInterfacedObject, IPreCompCallback, IWNafCallback)
+
+    strict private
+
+    var
+      Fm_p: IECPoint;
+      FminWidth: Int32;
+      Fm_includeNegated: Boolean;
+
+      class function CheckExisting(const existingWNaf: IWNafPreCompInfo;
+        width, reqPreCompLen: Int32; includeNegated: Boolean): Boolean;
+        static; inline;
+
+      class function CheckTable(const table: TCryptoLibGenericArray<IECPoint>;
+        reqLen: Int32): Boolean; static; inline;
+
+    public
+      constructor Create(const p: IECPoint; minWidth: Int32;
+        includeNegated: Boolean);
+
+      function Precompute(const existing: IPreCompInfo): IPreCompInfo;
+
+    end;
+
+  type
+    IPointMapCallback = interface(IPreCompCallback)
+      ['{00A66D4E-7D61-4A47-AE36-E8D89DEE8D9F}']
+
+    end;
+
+  type
+    TPointMapCallback = class(TInterfacedObject, IPreCompCallback,
+      IPointMapCallback)
+
+    strict private
+
+    var
+      Fm_p: IECPoint;
+      FpointMap: IECPointMap;
+      FfromWNaf: IWNafPreCompInfo;
+      FIncludeNegated: Boolean;
+
+      class function CheckExisting(const existingWNaf: IWNafPreCompInfo;
+        width, reqPreCompLen: Int32; includeNegated: Boolean): Boolean;
+        static; inline;
+
+      class function CheckTable(const table: TCryptoLibGenericArray<IECPoint>;
+        reqLen: Int32): Boolean; static; inline;
+
+    public
+      constructor Create(const p: IECPoint; const pointMap: IECPointMap;
+        const fromWNaf: IWNafPreCompInfo; includeNegated: Boolean);
+
+      function Precompute(const existing: IPreCompInfo): IPreCompInfo;
+
+    end;
+
+  type
+    IBasePointCallback = interface(IPreCompCallback)
+      ['{5A81CB00-3CB4-474D-A2A7-E949F7E71AEC}']
+
+    end;
+
+  type
+    TBasePointCallback = class(TInterfacedObject, IPreCompCallback,
+      IBasePointCallback)
+
+    strict private
+    var
+      FConfWidth: Int32;
+
+    public
+      constructor Create(ConfWidth: Int32);
+
+      function Precompute(const existing: IPreCompInfo): IPreCompInfo;
+
+    end;
+
+  class function Trim(const a: TCryptoLibByteArray; length: Int32)
+    : TCryptoLibByteArray; overload; static; inline;
+
+  class function Trim(const a: TCryptoLibInt32Array; length: Int32)
+    : TCryptoLibInt32Array; overload; static; inline;
+
+  class function ResizeTable(const a: TCryptoLibGenericArray<IECPoint>;
+    length: Int32): TCryptoLibGenericArray<IECPoint>; static; inline;
+
+  class procedure Boot(); static;
+  class constructor CreateWNafUtilities();
+
+  public
+
+    const
+    PRECOMP_NAME: String = 'bc_wnaf';
+
+    class function GenerateCompactNaf(const k: TBigInteger)
+      : TCryptoLibInt32Array; static;
+    class function GenerateCompactWindowNaf(width: Int32; const k: TBigInteger)
+      : TCryptoLibInt32Array; static;
+
+    class function GenerateJsf(const g, h: TBigInteger)
+      : TCryptoLibByteArray; static;
+    class function GenerateNaf(const k: TBigInteger)
+      : TCryptoLibByteArray; static;
+    // /**
+    // * Computes the Window NAF (non-adjacent Form) of an integer.
+    // * @param width The width <code>w</code> of the Window NAF. The width is
+    // * defined as the minimal number <code>w</code>, such that for any
+    // * <code>w</code> consecutive digits in the resulting representation, at
+    // * most one is non-zero.
+    // * @param k The integer of which the Window NAF is computed.
+    // * @return The Window NAF of the given width, such that the following holds:
+    // * <code>k = &amp;sum;<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup>
+    // * </code>, where the <code>k<sub>i</sub></code> denote the elements of the
+    // * returned <code>byte[]</code>.
+    // */
+    class function GenerateWindowNaf(width: Int32; const k: TBigInteger)
+      : TCryptoLibByteArray; static;
+
+    class function GetNafWeight(const k: TBigInteger): Int32; static; inline;
+
+    class function GetWNafPreCompInfo(const p: IECPoint): IWNafPreCompInfo;
+      overload; static; inline;
+
+    class function GetWNafPreCompInfo(const preCompInfo: IPreCompInfo)
+      : IWNafPreCompInfo; overload; static; inline;
+
+    /// <summary>
+    /// Determine window width to use for a scalar multiplication of the
+    /// given size.
+    /// </summary>
+    /// <param name="bits">
+    /// the bit-length of the scalar to multiply by
+    /// </param>
+    /// <returns>
+    /// the window size to use
+    /// </returns>
+    class function GetWindowSize(bits: Int32): Int32; overload; static; inline;
+
+    /// <summary>
+    /// Determine window width to use for a scalar multiplication of the
+    /// given size.
+    /// </summary>
+    /// <param name="bits">
+    /// the bit-length of the scalar to multiply by
+    /// </param>
+    /// <param name="maxWidth">
+    /// the maximum window width to return
+    /// </param>
+    /// <returns>
+    /// the window size to use
+    /// </returns>
+    class function GetWindowSize(bits, maxWidth: Int32): Int32; overload;
+      static; inline;
+
+    /// <summary>
+    /// Determine window width to use for a scalar multiplication of the
+    /// given size.
+    /// </summary>
+    /// <param name="bits">
+    /// the bit-length of the scalar to multiply by
+    /// </param>
+    /// <param name="windowSizeCutoffs">
+    /// a monotonically increasing list of bit sizes at which to increment
+    /// the window width
+    /// </param>
+    /// <returns>
+    /// the window size to use
+    /// </returns>
+    class function GetWindowSize(bits: Int32;
+      const windowSizeCutoffs: array of Int32): Int32; overload; static;
+
+    /// <summary>
+    /// Determine window width to use for a scalar multiplication of the
+    /// given size.
+    /// </summary>
+    /// <param name="bits">
+    /// the bit-length of the scalar to multiply by
+    /// </param>
+    /// <param name="windowSizeCutoffs">
+    /// a monotonically increasing list of bit sizes at which to increment
+    /// the window width
+    /// </param>
+    /// /// <param name="maxWidth">
+    /// the maximum window width to return
+    /// </param>
+    /// <returns>
+    /// the window size to use
+    /// </returns>
+    class function GetWindowSize(bits: Int32;
+      const windowSizeCutoffs: array of Int32; maxWidth: Int32): Int32;
+      overload; static;
+
+    class function Precompute(const p: IECPoint; minWidth: Int32;
+      includeNegated: Boolean): IWNafPreCompInfo; static;
+
+    class procedure ConfigureBasepoint(const p: IECPoint); static;
+
+    class function PrecomputeWithPointMap(const p: IECPoint;
+      const pointMap: IECPointMap; const fromWNaf: IWNafPreCompInfo;
+      includeNegated: Boolean): IWNafPreCompInfo;
+
+  end;
+
+type
+  TEndoUtilities = class abstract(TObject)
+
+  strict private
+  type
+    IEndoCallback = interface(IPreCompCallback)
+      ['{80C0B850-A97A-4603-A42F-A476ABAF2026}']
+
+    end;
+
+  type
+    TEndoCallback = class(TInterfacedObject, IPreCompCallback, IEndoCallback)
+
+    strict private
+    var
+      Fendomorphism: IECEndomorphism;
+      Fp: IECPoint;
+
+      class function CheckExisting(const existingEndo: IEndoPreCompInfo;
+        const endomorphism: IECEndomorphism): Boolean; static; inline;
+
+    public
+      constructor Create(const endomorphism: IECEndomorphism;
+        const p: IECPoint);
+
+      function Precompute(const existing: IPreCompInfo): IPreCompInfo;
+
+    end;
+
+  class function CalculateB(const k, g: TBigInteger; t: Int32)
+    : TBigInteger; static;
+
+  public
+
+    const
+    PRECOMP_NAME: String = 'bc_endo';
+
+  public
+    class function MapPoint(const endomorphism: IECEndomorphism;
+      const p: IECPoint): IECPoint; static;
+
+    class function DecomposeScalar(const p: IScalarSplitParameters;
+      const k: TBigInteger): TCryptoLibGenericArray<TBigInteger>; static;
+
+  end;
+
+type
+  TFixedPointUtilities = class sealed(TObject)
+  strict private
+
+  type
+    IFixedPointCallback = interface(IPreCompCallback)
+      ['{E6DFE8D3-A890-4568-AA4A-3D8BC6AF16E9}']
+
+    end;
+
+  type
+    TFixedPointCallback = class(TInterfacedObject, IPreCompCallback,
+      IFixedPointCallback)
+
+    strict private
+    var
+      Fm_p: IECPoint;
+
+      class function CheckExisting(const existingFP: IFixedPointPreCompInfo;
+        n: Int32): Boolean; static; inline;
+
+      class function CheckTable(const table: IECLookupTable; n: Int32): Boolean;
+        static; inline;
+
+    public
+      constructor Create(const p: IECPoint);
+
+      function Precompute(const existing: IPreCompInfo): IPreCompInfo;
+
+    end;
+
+  const
+    PRECOMP_NAME: String = 'bc_fixed_point';
+
+  public
+
+    class function GetFixedPointPreCompInfo(const preCompInfo: IPreCompInfo)
+      : IFixedPointPreCompInfo; static; inline;
+
+    class function GetCombSize(const c: IECCurve): Int32; static; inline;
+
+    class function Precompute(const p: IECPoint)
+      : IFixedPointPreCompInfo; static;
+  end;
+
+implementation
+
+{ TWNafUtilities }
+
+uses
+  ClpECAlgorithms; // included here to avoid circular dependency :)
+
+class function TWNafUtilities.ResizeTable
+  (const a: TCryptoLibGenericArray<IECPoint>; length: Int32)
+  : TCryptoLibGenericArray<IECPoint>;
+begin
+  result := System.Copy(a);
+  System.SetLength(result, length);
+end;
+
+class function TWNafUtilities.Trim(const a: TCryptoLibInt32Array; length: Int32)
+  : TCryptoLibInt32Array;
+begin
+  result := System.Copy(a, 0, length);
+end;
+
+class function TWNafUtilities.Trim(const a: TCryptoLibByteArray; length: Int32)
+  : TCryptoLibByteArray;
+begin
+  result := System.Copy(a, 0, length);
+end;
+
+class procedure TWNafUtilities.Boot;
+begin
+  FEMPTY_BYTES := Nil;
+  FEMPTY_INTS := Nil;
+end;
+
+class constructor TWNafUtilities.CreateWNafUtilities;
+begin
+  TWNafUtilities.Boot;
+end;
+
+class function TWNafUtilities.GetWindowSize(bits: Int32;
+  const windowSizeCutoffs: array of Int32; maxWidth: Int32): Int32;
+var
+  w: Int32;
+begin
+  w := 0;
+  while (w < System.length(windowSizeCutoffs)) do
+  begin
+    if (bits < windowSizeCutoffs[w]) then
+    begin
+      break;
+    end;
+    System.Inc(w);
+  end;
+
+  result := Max(2, Min(maxWidth, w + 2));
+end;
+
+class function TWNafUtilities.GetWindowSize(bits: Int32;
+  const windowSizeCutoffs: array of Int32): Int32;
+begin
+  result := GetWindowSize(bits, windowSizeCutoffs, MAX_WIDTH);
+end;
+
+class function TWNafUtilities.GetWindowSize(bits, maxWidth: Int32): Int32;
+begin
+  result := GetWindowSize(bits, DEFAULT_WINDOW_SIZE_CUTOFFS, maxWidth);
+end;
+
+class function TWNafUtilities.GetWindowSize(bits: Int32): Int32;
+begin
+  result := GetWindowSize(bits, DEFAULT_WINDOW_SIZE_CUTOFFS, MAX_WIDTH);
+end;
+
+class procedure TWNafUtilities.ConfigureBasepoint(const p: IECPoint);
+var
+  c: IECCurve;
+  n: TBigInteger;
+  bits, ConfWidth: Int32;
+begin
+  c := p.Curve;
+  if (c = Nil) then
+  begin
+    Exit;
+  end;
+
+  n := c.Order;
+  if (not n.IsInitialized) then
+  begin
+    bits := c.FieldSize + 1;
+  end
+  else
+  begin
+    bits := n.BitLength;
+  end;
+
+  ConfWidth := Min(MAX_WIDTH, GetWindowSize(bits) + 3);
+
+  c.Precompute(p, PRECOMP_NAME, TBasePointCallback.Create(ConfWidth)
+    as IBasePointCallback);
+end;
+
+class function TWNafUtilities.GenerateCompactNaf(const k: TBigInteger)
+  : TCryptoLibInt32Array;
+var
+  _3k, diff: TBigInteger;
+  bits, highBit, &length, zeroes, i, digit: Int32;
+  naf: TCryptoLibInt32Array;
+begin
+  if ((TBits.Asr32(k.BitLength, 16)) <> 0) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SInvalidBitLength);
+  end;
+  if (k.SignValue = 0) then
+  begin
+    result := FEMPTY_INTS;
+    Exit;
+  end;
+
+  _3k := k.ShiftLeft(1).Add(k);
+
+  bits := _3k.BitLength;
+  System.SetLength(naf, TBits.Asr32(bits, 1));
+
+  diff := _3k.&Xor(k);
+
+  highBit := bits - 1;
+  &length := 0;
+  zeroes := 0;
+
+  i := 1;
+
+  while (i < highBit) do
+  begin
+    if (not diff.TestBit(i)) then
+    begin
+      System.Inc(zeroes);
+      System.Inc(i);
+      continue;
+    end;
+
+    if k.TestBit(i) then
+    begin
+      digit := -1;
+    end
+    else
+    begin
+      digit := 1;
+    end;
+
+    naf[length] := (digit shl 16) or zeroes;
+    System.Inc(length);
+    zeroes := 1;
+
+    System.Inc(i, 2);
+
+  end;
+
+  naf[length] := (1 shl 16) or zeroes;
+  System.Inc(length);
+
+  if (System.length(naf) > length) then
+  begin
+    naf := Trim(naf, length);
+  end;
+
+  result := naf;
+end;
+
+class function TWNafUtilities.GenerateCompactWindowNaf(width: Int32;
+  const k: TBigInteger): TCryptoLibInt32Array;
+var
+  wnaf: TCryptoLibInt32Array;
+  pow2, mask, sign, &length, &pos, digit, zeroes: Int32;
+  carry: Boolean;
+  LK: TBigInteger;
+begin
+  LK := k;
+  if (width = 2) then
+  begin
+    result := GenerateCompactNaf(LK);
+    Exit;
+  end;
+
+  if ((width < 2) or (width > 16)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SInvalidRange);
+  end;
+  if ((TBits.Asr32(LK.BitLength, 16)) <> 0) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SInvalidBitLength);
+  end;
+  if (LK.SignValue = 0) then
+  begin
+    result := FEMPTY_INTS;
+    Exit;
+  end;
+
+  System.SetLength(wnaf, (LK.BitLength div width) + 1);
+
+  // 2^width and a mask and sign bit set accordingly
+  pow2 := 1 shl width;
+  mask := pow2 - 1;
+  sign := TBits.Asr32(pow2, 1);
+
+  carry := false;
+  length := 0;
+  pos := 0;
+
+  while (pos <= LK.BitLength) do
+  begin
+    if (LK.TestBit(pos) = carry) then
+    begin
+      System.Inc(pos);
+      continue;
+    end;
+
+    LK := LK.ShiftRight(pos);
+
+    digit := LK.Int32Value and mask;
+    if (carry) then
+    begin
+      System.Inc(digit);
+    end;
+
+    carry := (digit and sign) <> 0;
+    if (carry) then
+    begin
+      digit := digit - pow2;
+    end;
+
+    if length > 0 then
+    begin
+      zeroes := pos - 1;
+    end
+    else
+    begin
+      zeroes := pos;
+    end;
+
+    wnaf[length] := (digit shl 16) or zeroes;
+    System.Inc(length);
+    pos := width;
+  end;
+
+  // Reduce the WNAF array to its actual length
+  if (System.length(wnaf) > length) then
+  begin
+    wnaf := Trim(wnaf, length);
+  end;
+
+  result := wnaf;
+end;
+
+class function TWNafUtilities.GenerateJsf(const g, h: TBigInteger)
+  : TCryptoLibByteArray;
+var
+  digits, j, d0, d1, Offset, n0, n1, u0, u1: Int32;
+  jsf: TCryptoLibByteArray;
+  k0, k1: TBigInteger;
+begin
+  digits := Max(g.BitLength, h.BitLength) + 1;
+
+  System.SetLength(jsf, digits);
+
+  k0 := g;
+  k1 := h;
+  j := 0;
+  d0 := 0;
+  d1 := 0;
+
+  Offset := 0;
+
+  while (((d0 or d1) <> 0) or (k0.BitLength > Offset) or
+    (k1.BitLength > Offset)) do
+  begin
+    n0 := (Int32(UInt32(k0.Int32Value) shr Offset) + d0) and 7;
+    n1 := (Int32(UInt32(k1.Int32Value) shr Offset) + d1) and 7;
+
+    u0 := n0 and 1;
+    if (u0 <> 0) then
+    begin
+      u0 := u0 - (n0 and 2);
+      if (((n0 + u0) = 4) and ((n1 and 3) = 2)) then
+      begin
+        u0 := -u0;
+      end;
+    end;
+
+    u1 := n1 and 1;
+    if (u1 <> 0) then
+    begin
+      u1 := u1 - (n1 and 2);
+      if (((n1 + u1) = 4) and ((n0 and 3) = 2)) then
+      begin
+        u1 := -u1;
+      end;
+    end;
+
+    if ((d0 shl 1) = (1 + u0)) then
+    begin
+      d0 := d0 xor 1;
+    end;
+    if ((d1 shl 1) = (1 + u1)) then
+    begin
+      d1 := d1 xor 1;
+    end;
+
+    System.Inc(Offset);
+    if (Offset = 30) then
+    begin
+      Offset := 0;
+      k0 := k0.ShiftRight(30);
+      k1 := k1.ShiftRight(30);
+    end;
+
+    jsf[j] := Byte((u0 shl 4) or (u1 and $F));
+    System.Inc(j);
+  end;
+
+  // Reduce the JSF array to its actual length
+  if (System.length(jsf) > j) then
+  begin
+    jsf := Trim(jsf, j);
+  end;
+
+  result := jsf;
+end;
+
+class function TWNafUtilities.GenerateNaf(const k: TBigInteger)
+  : TCryptoLibByteArray;
+var
+  _3k, diff: TBigInteger;
+  digits, i: Int32;
+  naf: TCryptoLibByteArray;
+begin
+  if (k.SignValue = 0) then
+  begin
+    result := FEMPTY_BYTES;
+    Exit;
+  end;
+
+  _3k := k.ShiftLeft(1).Add(k);
+
+  digits := _3k.BitLength - 1;
+  System.SetLength(naf, digits);
+
+  diff := _3k.&Xor(k);
+
+  i := 1;
+
+  while i < digits do
+  begin
+    if (diff.TestBit(i)) then
+    begin
+      if k.TestBit(i) then
+      begin
+        naf[i - 1] := Byte(-1);
+      end
+      else
+      begin
+        naf[i - 1] := Byte(1);
+      end;
+
+      System.Inc(i);
+    end;
+    System.Inc(i);
+  end;
+
+  naf[digits - 1] := 1;
+
+  result := naf;
+end;
+
+class function TWNafUtilities.GenerateWindowNaf(width: Int32;
+  const k: TBigInteger): TCryptoLibByteArray;
+var
+  wnaf: TCryptoLibByteArray;
+  pow2, mask, sign, &length, &pos, digit: Int32;
+  carry: Boolean;
+  LK: TBigInteger;
+begin
+  LK := k;
+  if (width = 2) then
+  begin
+    result := GenerateNaf(LK);
+    Exit;
+  end;
+
+  if ((width < 2) or (width > 8)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SInvalidRange2);
+  end;
+  if (LK.SignValue = 0) then
+  begin
+    result := FEMPTY_BYTES;
+    Exit;
+  end;
+
+  System.SetLength(wnaf, LK.BitLength + 1);
+
+  // 2^width and a mask and sign bit set accordingly
+  pow2 := 1 shl width;
+  mask := pow2 - 1;
+  sign := TBits.Asr32(pow2, 1);
+
+  carry := false;
+  length := 0;
+  pos := 0;
+
+  while (pos <= LK.BitLength) do
+  begin
+    if (LK.TestBit(pos) = carry) then
+    begin
+      System.Inc(pos);
+      continue;
+    end;
+
+    LK := LK.ShiftRight(pos);
+
+    digit := LK.Int32Value and mask;
+    if (carry) then
+    begin
+      System.Inc(digit);
+    end;
+
+    carry := (digit and sign) <> 0;
+    if (carry) then
+    begin
+      digit := digit - pow2;
+    end;
+
+    if length > 0 then
+    begin
+      length := length + (pos - 1);
+    end
+    else
+    begin
+      length := length + (pos);
+    end;
+
+    wnaf[length] := Byte(digit);
+    System.Inc(length);
+    pos := width;
+  end;
+
+  // Reduce the WNAF array to its actual length
+  if (System.length(wnaf) > length) then
+  begin
+    wnaf := Trim(wnaf, length);
+  end;
+
+  result := wnaf;
+end;
+
+class function TWNafUtilities.GetNafWeight(const k: TBigInteger): Int32;
+var
+  _3k, diff: TBigInteger;
+begin
+  if (k.SignValue = 0) then
+  begin
+    result := 0;
+    Exit;
+  end;
+
+  _3k := k.ShiftLeft(1).Add(k);
+  diff := _3k.&Xor(k);
+
+  result := diff.BitCount;
+end;
+
+class function TWNafUtilities.GetWNafPreCompInfo(const preCompInfo
+  : IPreCompInfo): IWNafPreCompInfo;
+begin
+  result := preCompInfo as IWNafPreCompInfo;
+end;
+
+class function TWNafUtilities.GetWNafPreCompInfo(const p: IECPoint)
+  : IWNafPreCompInfo;
+var
+  preCompInfo: IPreCompInfo;
+begin
+  preCompInfo := p.Curve.GetPreCompInfo(p, PRECOMP_NAME);
+  result := GetWNafPreCompInfo(preCompInfo);
+end;
+
+class function TWNafUtilities.Precompute(const p: IECPoint; minWidth: Int32;
+  includeNegated: Boolean): IWNafPreCompInfo;
+begin
+  result := p.Curve.Precompute(p, PRECOMP_NAME,
+    TWNafCallback.Create(p, minWidth, includeNegated) as IWNafCallback)
+    as IWNafPreCompInfo;
+end;
+
+class function TWNafUtilities.PrecomputeWithPointMap(const p: IECPoint;
+  const pointMap: IECPointMap; const fromWNaf: IWNafPreCompInfo;
+  includeNegated: Boolean): IWNafPreCompInfo;
+var
+  c: IECCurve;
+begin
+  c := p.Curve;
+  result := c.Precompute(p, PRECOMP_NAME, TPointMapCallback.Create(p, pointMap,
+    fromWNaf, includeNegated) as IPointMapCallback) as IWNafPreCompInfo;
+end;
+
+{ TWNafUtilities.TMapPointCallback }
+
+constructor TWNafUtilities.TMapPointCallback.Create(const wnafPreCompP
+  : IWNafPreCompInfo; includeNegated: Boolean; const pointMap: IECPointMap);
+begin
+  Inherited Create();
+  Fm_wnafPreCompP := wnafPreCompP;
+  Fm_includeNegated := includeNegated;
+  Fm_pointMap := pointMap;
+end;
+
+function TWNafUtilities.TMapPointCallback.Precompute(const existing
+  : IPreCompInfo): IPreCompInfo;
+var
+  tempResult: IWNafPreCompInfo;
+  twiceP, twiceQ: IECPoint;
+  preCompP, preCompQ, preCompNegQ: TCryptoLibGenericArray<IECPoint>;
+  i: Int32;
+begin
+  tempResult := TWNafPreCompInfo.Create();
+
+  tempResult.ConfWidth := Fm_wnafPreCompP.ConfWidth;
+
+  twiceP := Fm_wnafPreCompP.Twice;
+  if (twiceP <> Nil) then
+  begin
+    twiceQ := Fm_pointMap.Map(twiceP);
+    tempResult.Twice := twiceQ;
+  end;
+
+  preCompP := Fm_wnafPreCompP.PreComp;
+
+  System.SetLength(preCompQ, System.length(preCompP));
+  for i := 0 to System.Pred(System.length(preCompP)) do
+  begin
+    preCompQ[i] := Fm_pointMap.Map(preCompP[i]);
+  end;
+
+  tempResult.PreComp := preCompQ;
+  tempResult.width := Fm_wnafPreCompP.width;
+
+  if (Fm_includeNegated) then
+  begin
+
+    System.SetLength(preCompNegQ, System.length(preCompQ));
+
+    for i := 0 to System.Pred(System.length(preCompNegQ)) do
+    begin
+      preCompNegQ[i] := preCompQ[i].Negate();
+    end;
+
+    tempResult.PreCompNeg := preCompNegQ;
+  end;
+
+  result := tempResult;
+end;
+
+{ TWNafUtilities.TWNafCallback }
+
+class function TWNafUtilities.TWNafCallback.CheckTable
+  (const table: TCryptoLibGenericArray<IECPoint>; reqLen: Int32): Boolean;
+begin
+  result := (table <> Nil) and (System.length(table) >= reqLen);
+end;
+
+class function TWNafUtilities.TWNafCallback.CheckExisting(const existingWNaf
+  : IWNafPreCompInfo; width, reqPreCompLen: Int32;
+  includeNegated: Boolean): Boolean;
+begin
+  result := (existingWNaf <> Nil) and
+    (existingWNaf.width >= Max(existingWNaf.ConfWidth, width))
+
+    and CheckTable(existingWNaf.PreComp, reqPreCompLen) and
+    ((not includeNegated) or CheckTable(existingWNaf.PreCompNeg,
+    reqPreCompLen));
+end;
+
+constructor TWNafUtilities.TWNafCallback.Create(const p: IECPoint;
+  minWidth: Int32; includeNegated: Boolean);
+begin
+  Inherited Create();
+  Fm_p := p;
+  FminWidth := minWidth;
+  Fm_includeNegated := includeNegated;
+end;
+
+function TWNafUtilities.TWNafCallback.Precompute(const existing: IPreCompInfo)
+  : IPreCompInfo;
+var
+  twiceP, isoTwiceP, last: IECPoint;
+  c: IECCurve;
+  PreComp, PreCompNeg, EMPTY_POINTS: TCryptoLibGenericArray<IECPoint>;
+  tempRes, existingWNaf: IWNafPreCompInfo;
+  reqPreCompLen, iniPreCompLen, curPreCompLen, pos, width, PromotionCountdown,
+    ConfWidth: Int32;
+  iso, iso2, iso3: IECFieldElement;
+begin
+  c := Fm_p.Curve;
+  EMPTY_POINTS := Nil;
+  existingWNaf := existing as IWNafPreCompInfo;
+
+  width := Max(2, Min(MAX_WIDTH, FminWidth));
+  reqPreCompLen := 1 shl (width - 2);
+
+  if (CheckExisting(existingWNaf, width, reqPreCompLen, Fm_includeNegated)) then
+  begin
+    existingWNaf.DecrementPromotionCountdown;
+    result := existingWNaf;
+    Exit;
+  end;
+
+  tempRes := TWNafPreCompInfo.Create();
+
+  if (existingWNaf <> Nil) then
+  begin
+
+    PromotionCountdown := existingWNaf.DecrementPromotionCountdown;
+    tempRes.PromotionCountdown := PromotionCountdown;
+
+    ConfWidth := existingWNaf.ConfWidth;
+    tempRes.ConfWidth := ConfWidth;
+
+    PreComp := existingWNaf.PreComp;
+    PreCompNeg := existingWNaf.PreCompNeg;
+    twiceP := existingWNaf.Twice;
+  end;
+
+  width := Min(MAX_WIDTH, Max(tempRes.ConfWidth, width));
+  reqPreCompLen := 1 shl (width - 2);
+
+  iniPreCompLen := 0;
+  if (PreComp = Nil) then
+  begin
+    PreComp := EMPTY_POINTS;
+  end
+  else
+  begin
+    iniPreCompLen := System.length(PreComp);
+  end;
+
+  if (iniPreCompLen < reqPreCompLen) then
+  begin
+    PreComp := TWNafUtilities.ResizeTable(PreComp, reqPreCompLen);
+
+    if (reqPreCompLen = 1) then
+    begin
+      PreComp[0] := Fm_p.Normalize();
+    end
+    else
+    begin
+      curPreCompLen := iniPreCompLen;
+      if (curPreCompLen = 0) then
+      begin
+        PreComp[0] := Fm_p;
+        curPreCompLen := 1;
+      end;
+
+      if (reqPreCompLen = 2) then
+      begin
+        PreComp[1] := Fm_p.threeTimes();
+      end
+      else
+      begin
+        isoTwiceP := twiceP;
+        last := PreComp[curPreCompLen - 1];
+        if (isoTwiceP = Nil) then
+        begin
+          isoTwiceP := PreComp[0].Twice();
+          twiceP := isoTwiceP;
+          //
+          // /*
+          // * For Fp curves with Jacobian projective coordinates, use a (quasi-)isomorphism
+          // * where 'twiceP' is "affine", so that the subsequent additions are cheaper. This
+          // * also requires scaling the initial point's X, Y coordinates, and reversing the
+          // * isomorphism as part of the subsequent normalization.
+          // *
+          // *  NOTE: The correctness of this optimization depends on:
+          // *      1) additions do not use the curve's A, B coefficients.
+          // *      2) no special cases (i.e. Q +/- Q) when calculating 1P, 3P, 5P, ...
+          // */
+          if ((not(twiceP.IsInfinity)) and (TECAlgorithms.IsFpCurve(c)) and
+            (c.FieldSize >= 64)) then
+          begin
+            case (c.CoordinateSystem) of
+              TECCurveConstants.COORD_JACOBIAN,
+                TECCurveConstants.COORD_JACOBIAN_CHUDNOVSKY,
+                TECCurveConstants.COORD_JACOBIAN_MODIFIED:
+
+                begin
+                  iso := twiceP.GetZCoord(0);
+                  isoTwiceP := c.CreatePoint(twiceP.XCoord.ToBigInteger,
+                    twiceP.YCoord.ToBigInteger());
+
+                  iso2 := iso.square();
+                  iso3 := iso2.Multiply(iso);
+                  last := last.scaleX(iso2).scaleY(iso3);
+
+                  if (iniPreCompLen = 0) then
+                  begin
+                    PreComp[0] := last;
+                  end;
+                end;
+
+            end;
+
+          end;
+        end;
+
+        while (curPreCompLen < reqPreCompLen) do
+        begin
+          // /*
+          // * Compute the new ECPoints for the precomputation array. The values 1, 3,
+          // * 5, ..., 2^(width-1)-1 times p are computed
+          // */
+          last := last.Add(isoTwiceP);
+          PreComp[curPreCompLen] := last;
+          System.Inc(curPreCompLen);
+        end;
+      end;
+      //
+      // /*
+      // * Having oft-used operands in affine form makes operations faster.
+      // */
+      c.NormalizeAll(PreComp, iniPreCompLen,
+        reqPreCompLen - iniPreCompLen, iso);
+    end;
+  end;
+
+  if (Fm_includeNegated) then
+  begin
+
+    if (PreCompNeg = Nil) then
+    begin
+      pos := 0;
+      System.SetLength(PreCompNeg, reqPreCompLen);
+
+    end
+    else
+    begin
+      pos := System.length(PreCompNeg);
+      if (pos < reqPreCompLen) then
+      begin
+        PreCompNeg := TWNafUtilities.ResizeTable(PreCompNeg, reqPreCompLen);
+      end;
+    end;
+
+    while (pos < reqPreCompLen) do
+    begin
+      PreCompNeg[pos] := PreComp[pos].Negate();
+      System.Inc(pos);
+    end;
+  end;
+
+  tempRes.PreComp := PreComp;
+  tempRes.PreCompNeg := PreCompNeg;
+  tempRes.Twice := twiceP;
+  tempRes.width := width;
+
+  result := tempRes;
+end;
+
+{ TWNafUtilities.TBasePointCallback }
+
+constructor TWNafUtilities.TBasePointCallback.Create(ConfWidth: Int32);
+begin
+  Inherited Create();
+  FConfWidth := ConfWidth;
+end;
+
+function TWNafUtilities.TBasePointCallback.Precompute(const existing
+  : IPreCompInfo): IPreCompInfo;
+var
+  existingWNaf, tempResult: IWNafPreCompInfo;
+begin
+
+  if Supports(existing, IWNafPreCompInfo) then
+  begin
+    existingWNaf := existing as IWNafPreCompInfo;
+  end
+  else
+  begin
+    existingWNaf := Nil;
+  end;
+
+  if ((existingWNaf <> Nil) and (existingWNaf.ConfWidth = FConfWidth)) then
+  begin
+    existingWNaf.PromotionCountdown := 0;
+    result := existingWNaf;
+    Exit;
+  end;
+
+  tempResult := TWNafPreCompInfo.Create();
+
+  tempResult.PromotionCountdown := 0;
+  tempResult.ConfWidth := FConfWidth;
+
+  if (existingWNaf <> Nil) then
+  begin
+    tempResult.PreComp := existingWNaf.PreComp;
+    tempResult.PreCompNeg := existingWNaf.PreCompNeg;
+    tempResult.Twice := existingWNaf.Twice;
+    tempResult.width := existingWNaf.width;
+  end;
+  result := tempResult;
+end;
+
+{ TWNafUtilities.TPointMapCallback }
+
+class function TWNafUtilities.TPointMapCallback.CheckTable
+  (const table: TCryptoLibGenericArray<IECPoint>; reqLen: Int32): Boolean;
+begin
+  result := ((table <> Nil) and (System.length(table) >= reqLen));
+end;
+
+class function TWNafUtilities.TPointMapCallback.CheckExisting(const existingWNaf
+  : IWNafPreCompInfo; width, reqPreCompLen: Int32;
+  includeNegated: Boolean): Boolean;
+begin
+  result := ((existingWNaf <> Nil) and (existingWNaf.width >= width) and
+    (CheckTable(existingWNaf.PreComp, reqPreCompLen)) and
+    ((not includeNegated) or (CheckTable(existingWNaf.PreCompNeg,
+    reqPreCompLen))));
+end;
+
+constructor TWNafUtilities.TPointMapCallback.Create(const p: IECPoint;
+  const pointMap: IECPointMap; const fromWNaf: IWNafPreCompInfo;
+  includeNegated: Boolean);
+begin
+  Inherited Create();
+  Fm_p := p;
+  FpointMap := pointMap;
+  FfromWNaf := fromWNaf;
+  FIncludeNegated := includeNegated;
+end;
+
+function TWNafUtilities.TPointMapCallback.Precompute(const existing
+  : IPreCompInfo): IPreCompInfo;
+var
+  existingWNaf: IWNafPreCompInfo;
+  width, reqPreCompLen, i: Int32;
+  tempResult: IWNafPreCompInfo;
+  twiceFrom, Ltwice: IECPoint;
+  LpreCompFrom, LpreComp, LpreCompNeg: TCryptoLibGenericArray<IECPoint>;
+begin
+  if Supports(existing, IWNafPreCompInfo) then
+  begin
+    existingWNaf := existing as IWNafPreCompInfo;
+  end
+  else
+  begin
+    existingWNaf := Nil;
+  end;
+  width := FfromWNaf.width;
+  reqPreCompLen := System.length(FfromWNaf.PreComp);
+
+  if (CheckExisting(existingWNaf, width, reqPreCompLen, FIncludeNegated)) then
+  begin
+    existingWNaf.DecrementPromotionCountdown;
+    result := existingWNaf;
+    Exit;
+  end;
+
+  (*
+    * TODO Ideally this method would support incremental calculation, but given the
+    * existing use-cases it would be of little-to-no benefit.
+  *)
+  tempResult := TWNafPreCompInfo.Create();
+
+  tempResult.PromotionCountdown := FfromWNaf.PromotionCountdown;
+
+  twiceFrom := FfromWNaf.Twice;
+  if (twiceFrom <> Nil) then
+  begin
+    Ltwice := FpointMap.Map(twiceFrom);
+    tempResult.Twice := Ltwice;
+  end;
+
+  LpreCompFrom := FfromWNaf.PreComp;
+  System.SetLength(LpreComp, System.length(LpreCompFrom));
+
+  for i := 0 to System.Pred(System.length(LpreCompFrom)) do
+  begin
+    LpreComp[i] := FpointMap.Map(LpreCompFrom[i]);
+  end;
+  tempResult.PreComp := LpreComp;
+  tempResult.width := width;
+
+  if (FIncludeNegated) then
+  begin
+    System.SetLength(LpreCompNeg, System.length(LpreComp));
+
+    for i := 0 to System.Pred(System.length(LpreCompNeg)) do
+    begin
+      LpreCompNeg[i] := LpreComp[i].Negate();
+    end;
+    tempResult.PreCompNeg := LpreCompNeg;
+  end;
+
+  result := tempResult;
+end;
+
+{ TEndoUtilities }
+
+class function TEndoUtilities.CalculateB(const k, g: TBigInteger; t: Int32)
+  : TBigInteger;
+var
+  negative, extra: Boolean;
+  b: TBigInteger;
+begin
+  negative := (g.SignValue < 0);
+  b := k.Multiply(g.Abs());
+  extra := b.TestBit(t - 1);
+  b := b.ShiftRight(t);
+  if (extra) then
+  begin
+    b := b.Add(TBigInteger.One);
+  end;
+
+  if negative then
+  begin
+    result := b.Negate();
+  end
+  else
+  begin
+    result := b;
+  end;
+end;
+
+class function TEndoUtilities.DecomposeScalar(const p: IScalarSplitParameters;
+  const k: TBigInteger): TCryptoLibGenericArray<TBigInteger>;
+var
+  bits: Int32;
+  b1, b2, a, b: TBigInteger;
+begin
+
+  bits := p.bits;
+  b1 := CalculateB(k, p.G1, bits);
+  b2 := CalculateB(k, p.G2, bits);
+
+  a := k.Subtract((b1.Multiply(p.V1A)).Add(b2.Multiply(p.V2A)));
+  b := (b1.Multiply(p.V1B)).Add(b2.Multiply(p.V2B)).Negate();
+
+  result := TCryptoLibGenericArray<TBigInteger>.Create(a, b);
+end;
+
+class function TEndoUtilities.MapPoint(const endomorphism: IECEndomorphism;
+  const p: IECPoint): IECPoint;
+var
+  c: IECCurve;
+  PreComp: IEndoPreCompInfo;
+begin
+  c := p.Curve;
+  PreComp := c.Precompute(p, PRECOMP_NAME, TEndoCallback.Create(endomorphism, p)
+    as IEndoCallback) as IEndoPreCompInfo;
+
+  result := PreComp.MappedPoint;
+end;
+
+{ TEndoUtilities.TEndoCallback }
+
+class function TEndoUtilities.TEndoCallback.CheckExisting(const existingEndo
+  : IEndoPreCompInfo; const endomorphism: IECEndomorphism): Boolean;
+begin
+  result := ((existingEndo <> Nil) and
+    (existingEndo.endomorphism = endomorphism) and
+    (existingEndo.MappedPoint <> Nil));
+end;
+
+constructor TEndoUtilities.TEndoCallback.Create(const endomorphism
+  : IECEndomorphism; const p: IECPoint);
+begin
+  Inherited Create();
+  Fendomorphism := endomorphism;
+  Fp := p;
+end;
+
+function TEndoUtilities.TEndoCallback.Precompute(const existing: IPreCompInfo)
+  : IPreCompInfo;
+var
+  existingEndo: IEndoPreCompInfo;
+  MappedPoint: IECPoint;
+  tempResult: IEndoPreCompInfo;
+begin
+
+  if Supports(existing, IEndoPreCompInfo) then
+  begin
+    existingEndo := existing as IEndoPreCompInfo;
+  end
+  else
+  begin
+    existingEndo := Nil;
+  end;
+
+  if (CheckExisting(existingEndo, Fendomorphism)) then
+  begin
+    result := existingEndo;
+    Exit;
+  end;
+
+  MappedPoint := Fendomorphism.pointMap.Map(Fp);
+
+  tempResult := TEndoPreCompInfo.Create() as IEndoPreCompInfo;
+  tempResult.endomorphism := Fendomorphism;
+  tempResult.MappedPoint := MappedPoint;
+  result := tempResult as IPreCompInfo;
+end;
+
+{ TFixedPointUtilities }
+
+class function TFixedPointUtilities.TFixedPointCallback.CheckTable
+  (const table: IECLookupTable; n: Int32): Boolean;
+begin
+  result := (table <> Nil) and (table.Size >= n);
+end;
+
+class function TFixedPointUtilities.TFixedPointCallback.CheckExisting
+  (const existingFP: IFixedPointPreCompInfo; n: Int32): Boolean;
+begin
+  result := (existingFP <> Nil) and CheckTable(existingFP.LookupTable, n);
+end;
+
+class function TFixedPointUtilities.GetCombSize(const c: IECCurve): Int32;
+var
+  Order: TBigInteger;
+begin
+  Order := c.Order;
+  if (not(Order.IsInitialized)) then
+  begin
+    result := c.FieldSize + 1;
+  end
+  else
+  begin
+    result := Order.BitLength;
+  end;
+end;
+
+class function TFixedPointUtilities.GetFixedPointPreCompInfo(const preCompInfo
+  : IPreCompInfo): IFixedPointPreCompInfo;
+begin
+  result := preCompInfo as IFixedPointPreCompInfo;
+end;
+
+class function TFixedPointUtilities.Precompute(const p: IECPoint)
+  : IFixedPointPreCompInfo;
+var
+  c: IECCurve;
+begin
+  c := p.Curve;
+
+  result := c.Precompute(p, PRECOMP_NAME, TFixedPointCallback.Create(p)
+    as IFixedPointCallback) as IFixedPointPreCompInfo;
+end;
+
+{ TFixedPointUtilities.TFixedPointCallback }
+
+constructor TFixedPointUtilities.TFixedPointCallback.Create(const p: IECPoint);
+begin
+  Inherited Create();
+  Fm_p := p;
+end;
+
+function TFixedPointUtilities.TFixedPointCallback.Precompute(const existing
+  : IPreCompInfo): IPreCompInfo;
+var
+  bit, bits, minWidth, n, d, i, step: Int32;
+  existingFP: IFixedPointPreCompInfo;
+  pow2Table, LookupTable: TCryptoLibGenericArray<IECPoint>;
+  pow2: IECPoint;
+  c: IECCurve;
+  tempResult: IFixedPointPreCompInfo;
+begin
+  if Supports(existing, IFixedPointPreCompInfo) then
+  begin
+    existingFP := existing as IFixedPointPreCompInfo;
+  end
+  else
+  begin
+    existingFP := Nil;
+  end;
+
+  c := Fm_p.Curve;
+  bits := TFixedPointUtilities.GetCombSize(c);
+  if bits > 250 then
+  begin
+    minWidth := 6
+  end
+  else
+  begin
+    minWidth := 5
+  end;
+  n := 1 shl minWidth;
+
+  if (CheckExisting(existingFP, n)) then
+  begin
+    result := existingFP;
+    Exit;
+  end;
+
+  d := (bits + minWidth - 1) div minWidth;
+
+  System.SetLength(pow2Table, minWidth + 1);
+
+  pow2Table[0] := Fm_p;
+  for i := 1 to System.Pred(minWidth) do
+  begin
+    pow2Table[i] := pow2Table[i - 1].TimesPow2(d);
+  end;
+
+  // This will be the 'offset' value
+  pow2Table[minWidth] := pow2Table[0].Subtract(pow2Table[1]);
+
+  c.NormalizeAll(pow2Table);
+
+  System.SetLength(LookupTable, n);
+  LookupTable[0] := pow2Table[0];
+
+  bit := minWidth - 1;
+  while bit >= 0 do
+  begin
+    pow2 := pow2Table[bit];
+
+    step := 1 shl bit;
+
+    i := step;
+
+    while i < n do
+    begin
+      LookupTable[i] := LookupTable[i - step].Add(pow2);
+
+      System.Inc(i, step shl 1);
+    end;
+
+    System.Dec(bit);
+  end;
+
+  c.NormalizeAll(LookupTable);
+
+  tempResult := TFixedPointPreCompInfo.Create();
+  tempResult.LookupTable := c.CreateCacheSafeLookupTable(LookupTable, 0,
+    System.length(LookupTable));
+  tempResult.Offset := pow2Table[minWidth];
+  tempResult.width := minWidth;
+  result := tempResult;
+end;
+
+end.

+ 7 - 23
src/libraries/cryptolib4pascal/ClpECDomainParameters.pas

@@ -43,11 +43,8 @@ type
 
 
   strict private
   strict private
 
 
-    class var
-
-      FLock: TCriticalSection;
-
   var
   var
+    FLock: TCriticalSection;
     Fcurve: IECCurve;
     Fcurve: IECCurve;
     Fseed: TCryptoLibByteArray;
     Fseed: TCryptoLibByteArray;
     Fg: IECPoint;
     Fg: IECPoint;
@@ -60,10 +57,6 @@ type
     function GetHInv: TBigInteger; inline;
     function GetHInv: TBigInteger; inline;
     function GetSeed: TCryptoLibByteArray; inline;
     function GetSeed: TCryptoLibByteArray; inline;
 
 
-    class procedure Boot(); static;
-    class constructor CreateECDomainParameters();
-    class destructor DestroyECDomainParameters();
-
   public
   public
 
 
     class function Validate(const c: IECCurve; const q: IECPoint)
     class function Validate(const c: IECCurve; const q: IECPoint)
@@ -76,6 +69,8 @@ type
     constructor Create(const curve: IECCurve; const g: IECPoint;
     constructor Create(const curve: IECCurve; const g: IECPoint;
       const n, h: TBigInteger; const seed: TCryptoLibByteArray); overload;
       const n, h: TBigInteger; const seed: TCryptoLibByteArray); overload;
 
 
+    destructor Destroy; override;
+
     property curve: IECCurve read GetCurve;
     property curve: IECCurve read GetCurve;
     property g: IECPoint read GetG;
     property g: IECPoint read GetG;
     property n: TBigInteger read GetN;
     property n: TBigInteger read GetN;
@@ -130,7 +125,6 @@ end;
 
 
 function TECDomainParameters.GetHInv: TBigInteger;
 function TECDomainParameters.GetHInv: TBigInteger;
 begin
 begin
-
   FLock.Acquire;
   FLock.Acquire;
   try
   try
     if (not(FhInv.IsInitialized)) then
     if (not(FhInv.IsInitialized)) then
@@ -160,14 +154,6 @@ begin
   Create(curve, g, n, h, Nil);
   Create(curve, g, n, h, Nil);
 end;
 end;
 
 
-class procedure TECDomainParameters.Boot;
-begin
-  if FLock = Nil then
-  begin
-    FLock := TCriticalSection.Create;
-  end;
-end;
-
 constructor TECDomainParameters.Create(const curve: IECCurve; const g: IECPoint;
 constructor TECDomainParameters.Create(const curve: IECCurve; const g: IECPoint;
   const n, h: TBigInteger; const seed: TCryptoLibByteArray);
   const n, h: TBigInteger; const seed: TCryptoLibByteArray);
 begin
 begin
@@ -180,6 +166,8 @@ begin
     raise EArgumentNilCryptoLibException.CreateResFmt
     raise EArgumentNilCryptoLibException.CreateResFmt
       (@SBigIntegerNotInitialized, ['n']);
       (@SBigIntegerNotInitialized, ['n']);
 
 
+  FLock := TCriticalSection.Create;
+
   // we can't check for (not (h.IsInitialized)) here as h is optional in X9.62 as it is not required for ECDSA
   // we can't check for (not (h.IsInitialized)) here as h is optional in X9.62 as it is not required for ECDSA
 
 
   Fcurve := curve;
   Fcurve := curve;
@@ -192,14 +180,10 @@ begin
 
 
 end;
 end;
 
 
-class constructor TECDomainParameters.CreateECDomainParameters;
-begin
-  TECDomainParameters.Boot;
-end;
-
-class destructor TECDomainParameters.DestroyECDomainParameters;
+destructor TECDomainParameters.Destroy;
 begin
 begin
   FLock.Free;
   FLock.Free;
+  inherited Destroy;
 end;
 end;
 
 
 function TECDomainParameters.Equals(const other: IECDomainParameters): Boolean;
 function TECDomainParameters.Equals(const other: IECDomainParameters): Boolean;

+ 1 - 1
src/libraries/cryptolib4pascal/ClpECDsaSigner.pas

@@ -31,7 +31,7 @@ uses
   ClpIParametersWithRandom,
   ClpIParametersWithRandom,
   ClpIECPublicKeyParameters,
   ClpIECPublicKeyParameters,
   ClpIECPrivateKeyParameters,
   ClpIECPrivateKeyParameters,
-  ClpFixedPointCombMultiplier,
+  ClpMultipliers,
   ClpCryptoLibTypes,
   ClpCryptoLibTypes,
   ClpICipherParameters,
   ClpICipherParameters,
   ClpIECDomainParameters,
   ClpIECDomainParameters,

+ 3 - 3
src/libraries/cryptolib4pascal/ClpECKeyPairGenerator.pas

@@ -27,7 +27,7 @@ uses
   ClpBits,
   ClpBits,
   ClpCryptoLibTypes,
   ClpCryptoLibTypes,
   ClpECKeyParameters,
   ClpECKeyParameters,
-  ClpECAlgorithms,
+  ClpECCompUtilities,
   ClpIECKeyPairGenerator,
   ClpIECKeyPairGenerator,
   ClpIAsn1Objects,
   ClpIAsn1Objects,
   ClpIKeyGenerationParameters,
   ClpIKeyGenerationParameters,
@@ -35,7 +35,8 @@ uses
   ClpECDomainParameters,
   ClpECDomainParameters,
   ClpIECDomainParameters,
   ClpIECDomainParameters,
   ClpIECC,
   ClpIECC,
-  ClpIFixedPointCombMultiplier,
+  ClpMultipliers,
+  ClpIMultipliers,
   ClpSecObjectIdentifiers,
   ClpSecObjectIdentifiers,
   ClpCustomNamedCurves,
   ClpCustomNamedCurves,
   ClpECNamedCurveTable,
   ClpECNamedCurveTable,
@@ -47,7 +48,6 @@ uses
   ClpIECPublicKeyParameters,
   ClpIECPublicKeyParameters,
   ClpECPrivateKeyParameters,
   ClpECPrivateKeyParameters,
   ClpIECPrivateKeyParameters,
   ClpIECPrivateKeyParameters,
-  ClpFixedPointCombMultiplier,
   ClpSecureRandom,
   ClpSecureRandom,
   ClpISecureRandom,
   ClpISecureRandom,
   ClpIAsymmetricCipherKeyPairGenerator;
   ClpIAsymmetricCipherKeyPairGenerator;

+ 102 - 45
src/libraries/cryptolib4pascal/ClpECNRSigner.pas

@@ -27,6 +27,7 @@ uses
   ClpIECC,
   ClpIECC,
   ClpIECNRSigner,
   ClpIECNRSigner,
   ClpBigInteger,
   ClpBigInteger,
+  ClpBigIntegers,
   ClpISecureRandom,
   ClpISecureRandom,
   ClpIECKeyParameters,
   ClpIECKeyParameters,
   ClpIParametersWithRandom,
   ClpIParametersWithRandom,
@@ -47,29 +48,45 @@ resourcestring
   SECPrivateKeyNotFound = 'EC Private Key Required for Signing';
   SECPrivateKeyNotFound = 'EC Private Key Required for Signing';
   SNotInitializedForSigning = 'Not Initialised For Signing';
   SNotInitializedForSigning = 'Not Initialised For Signing';
   SNotInitializedForVerifying = 'Not Initialised For Verifying';
   SNotInitializedForVerifying = 'Not Initialised For Verifying';
+  SNotInitializedForVerifyingRecovery =
+    'Not Initialised For Verifying/Recovery';
   SInputTooLargeForECNRKey = 'Input Too Large For ECNR Key.';
   SInputTooLargeForECNRKey = 'Input Too Large For ECNR Key.';
 
 
 type
 type
 
 
   /// <summary>
   /// <summary>
-  /// EC-NR as described in IEEE 1363-2000
+  /// EC-NR as described in IEEE 1363-2000 - a signature algorithm for Elliptic Curve which
+  /// also offers message recovery.
   /// </summary>
   /// </summary>
   TECNRSigner = class sealed(TInterfacedObject, IDsaExt, IECNRSigner)
   TECNRSigner = class sealed(TInterfacedObject, IDsaExt, IECNRSigner)
 
 
   strict private
   strict private
   var
   var
-    FforSigning: Boolean;
-    Fkey: IECKeyParameters;
-    Frandom: ISecureRandom;
+    FForSigning: Boolean;
+    FKey: IECKeyParameters;
+    FRandom: ISecureRandom;
 
 
-    function GetAlgorithmName: String; virtual;
-    function GetOrder: TBigInteger; virtual;
+    function GetAlgorithmName: String;
+    function GetOrder: TBigInteger;
+
+    function ExtractT(const pubKey: IECPublicKeyParameters;
+      const r, s: TBigInteger): TBigInteger;
 
 
   public
   public
 
 
     property Order: TBigInteger read GetOrder;
     property Order: TBigInteger read GetOrder;
     property AlgorithmName: String read GetAlgorithmName;
     property AlgorithmName: String read GetAlgorithmName;
 
 
+    /// <summary>
+    /// Initialise the signer.
+    /// </summary>
+    /// <param name="forSigning">
+    /// forSigning true if we are generating a signature, false for
+    /// verification or if we want to use the signer for message recovery.
+    /// </param>
+    /// <param name="parameters">
+    /// key parameters for signature generation.
+    /// </param>
     procedure Init(forSigning: Boolean;
     procedure Init(forSigning: Boolean;
       const parameters: ICipherParameters); virtual;
       const parameters: ICipherParameters); virtual;
 
 
@@ -121,23 +138,72 @@ type
     function VerifySignature(const &message: TCryptoLibByteArray;
     function VerifySignature(const &message: TCryptoLibByteArray;
       const r, s: TBigInteger): Boolean;
       const r, s: TBigInteger): Boolean;
 
 
+    /// <summary>
+    /// Returns the data used for the signature generation, assuming the
+    /// public key passed to Init() is correct.
+    /// </summary>
+    /// <returns>
+    /// null if r and s are not valid.
+    /// </returns>
+    function GetRecoveredMessage(const r, s: TBigInteger): TCryptoLibByteArray;
+
   end;
   end;
 
 
 implementation
 implementation
 
 
 { TECNRSigner }
 { TECNRSigner }
 
 
+function TECNRSigner.ExtractT(const pubKey: IECPublicKeyParameters;
+  const r, s: TBigInteger): TBigInteger;
+var
+  n, x: TBigInteger;
+  G, W, P: IECPoint;
+begin
+  n := pubKey.parameters.n;
+
+  // r in the range [1,n-1]
+  if ((r.CompareTo(TBigInteger.ONE) < 0) or (r.CompareTo(n) >= 0)) then
+  begin
+    result := Default (TBigInteger);
+    Exit;
+  end;
+
+  // s in the range [0,n-1]           NB: ECNR spec says 0
+  if ((s.CompareTo(TBigInteger.ZERO) < 0) or (s.CompareTo(n) >= 0)) then
+  begin
+    result := Default (TBigInteger);
+    Exit;
+  end;
+
+  // compute P = sG + rW
+
+  G := pubKey.parameters.G;
+  W := pubKey.Q;
+  // calculate P using Bouncy math
+  P := TECAlgorithms.SumOfTwoMultiplies(G, s, W, r).Normalize();
+
+  // components must be bogus.
+  if (P.IsInfinity) then
+  begin
+    result := Default (TBigInteger);
+    Exit;
+  end;
+
+  x := P.AffineXCoord.ToBigInteger();
+
+  result := r.Subtract(x).&Mod(n);
+end;
+
 function TECNRSigner.GenerateSignature(const &message: TCryptoLibByteArray)
 function TECNRSigner.GenerateSignature(const &message: TCryptoLibByteArray)
   : TCryptoLibGenericArray<TBigInteger>;
   : TCryptoLibGenericArray<TBigInteger>;
 var
 var
   n, e, r, s, Vx, x, u: TBigInteger;
   n, e, r, s, Vx, x, u: TBigInteger;
-  nBitLength, eBitLength: Int32;
   privKey: IECPrivateKeyParameters;
   privKey: IECPrivateKeyParameters;
   tempPair: IAsymmetricCipherKeyPair;
   tempPair: IAsymmetricCipherKeyPair;
   keyGen: IECKeyPairGenerator;
   keyGen: IECKeyPairGenerator;
   V: IECPublicKeyParameters;
   V: IECPublicKeyParameters;
 begin
 begin
-  if (not FforSigning) then
+  if (not FForSigning) then
   begin
   begin
     // not properly initialized... deal with it
     // not properly initialized... deal with it
     raise EInvalidOperationCryptoLibException.CreateRes
     raise EInvalidOperationCryptoLibException.CreateRes
@@ -145,14 +211,12 @@ begin
   end;
   end;
 
 
   n := Order;
   n := Order;
-  nBitLength := n.BitLength;
 
 
   e := TBigInteger.Create(1, &message);
   e := TBigInteger.Create(1, &message);
-  eBitLength := e.BitLength;
 
 
-  privKey := Fkey as IECPrivateKeyParameters;
+  privKey := FKey as IECPrivateKeyParameters;
 
 
-  if (eBitLength > nBitLength) then
+  if (e.CompareTo(n) >= 0) then
   begin
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SInputTooLargeForECNRKey);
     raise EDataLengthCryptoLibException.CreateRes(@SInputTooLargeForECNRKey);
   end;
   end;
@@ -162,7 +226,7 @@ begin
     // the same EC parameters
     // the same EC parameters
     keyGen := TECKeyPairGenerator.Create();
     keyGen := TECKeyPairGenerator.Create();
 
 
-    keyGen.Init(TECKeyGenerationParameters.Create(privKey.parameters, Frandom)
+    keyGen.Init(TECKeyGenerationParameters.Create(privKey.parameters, FRandom)
       as IECKeyGenerationParameters);
       as IECKeyGenerationParameters);
 
 
     tempPair := keyGen.GenerateKeyPair();
     tempPair := keyGen.GenerateKeyPair();
@@ -189,7 +253,7 @@ end;
 
 
 function TECNRSigner.GetOrder: TBigInteger;
 function TECNRSigner.GetOrder: TBigInteger;
 begin
 begin
-  result := Fkey.parameters.n;
+  result := FKey.parameters.n;
 end;
 end;
 
 
 procedure TECNRSigner.Init(forSigning: Boolean;
 procedure TECNRSigner.Init(forSigning: Boolean;
@@ -198,19 +262,19 @@ var
   rParam: IParametersWithRandom;
   rParam: IParametersWithRandom;
   Lparameters: ICipherParameters;
   Lparameters: ICipherParameters;
 begin
 begin
-  FforSigning := forSigning;
+  FForSigning := forSigning;
   Lparameters := parameters;
   Lparameters := parameters;
   if (forSigning) then
   if (forSigning) then
   begin
   begin
 
 
     if (Supports(Lparameters, IParametersWithRandom, rParam)) then
     if (Supports(Lparameters, IParametersWithRandom, rParam)) then
     begin
     begin
-      Frandom := rParam.random;
+      FRandom := rParam.random;
       Lparameters := rParam.parameters;
       Lparameters := rParam.parameters;
     end
     end
     else
     else
     begin
     begin
-      Frandom := TSecureRandom.Create();
+      FRandom := TSecureRandom.Create();
     end;
     end;
 
 
     if (not(Supports(Lparameters, IECPrivateKeyParameters))) then
     if (not(Supports(Lparameters, IECPrivateKeyParameters))) then
@@ -218,7 +282,7 @@ begin
       raise EInvalidKeyCryptoLibException.CreateRes(@SECPrivateKeyNotFound);
       raise EInvalidKeyCryptoLibException.CreateRes(@SECPrivateKeyNotFound);
     end;
     end;
 
 
-    Fkey := Lparameters as IECPrivateKeyParameters;
+    FKey := Lparameters as IECPrivateKeyParameters;
   end
   end
   else
   else
   begin
   begin
@@ -227,7 +291,7 @@ begin
       raise EInvalidKeyCryptoLibException.CreateRes(@SECPublicKeyNotFound);
       raise EInvalidKeyCryptoLibException.CreateRes(@SECPublicKeyNotFound);
     end;
     end;
 
 
-    Fkey := Lparameters as IECPublicKeyParameters;
+    FKey := Lparameters as IECPublicKeyParameters;
   end;
   end;
 end;
 end;
 
 
@@ -235,18 +299,17 @@ function TECNRSigner.VerifySignature(const &message: TCryptoLibByteArray;
   const r, s: TBigInteger): Boolean;
   const r, s: TBigInteger): Boolean;
 var
 var
   pubKey: IECPublicKeyParameters;
   pubKey: IECPublicKeyParameters;
-  n, e, x, t: TBigInteger;
+  n, e, t: TBigInteger;
   nBitLength, eBitLength: Int32;
   nBitLength, eBitLength: Int32;
-  G, W, P: IECPoint;
 begin
 begin
-  if (FforSigning) then
+  if (FForSigning) then
   begin
   begin
     // not properly initialized... deal with it
     // not properly initialized... deal with it
     raise EInvalidOperationCryptoLibException.CreateRes
     raise EInvalidOperationCryptoLibException.CreateRes
       (@SNotInitializedForVerifying);
       (@SNotInitializedForVerifying);
   end;
   end;
 
 
-  pubKey := Fkey as IECPublicKeyParameters;
+  pubKey := FKey as IECPublicKeyParameters;
   n := pubKey.parameters.n;
   n := pubKey.parameters.n;
   nBitLength := n.BitLength;
   nBitLength := n.BitLength;
 
 
@@ -258,37 +321,31 @@ begin
     raise EDataLengthCryptoLibException.CreateRes(@SInputTooLargeForECNRKey);
     raise EDataLengthCryptoLibException.CreateRes(@SInputTooLargeForECNRKey);
   end;
   end;
 
 
-  // r in the range [1,n-1]
-  if ((r.CompareTo(TBigInteger.One) < 0) or (r.CompareTo(n) >= 0)) then
-  begin
-    result := false;
-    Exit;
-  end;
+  t := ExtractT(pubKey, r, s);
 
 
-  // s in the range [0,n-1]           NB: ECNR spec says 0
-  if ((s.CompareTo(TBigInteger.Zero) < 0) or (s.CompareTo(n) >= 0)) then
+  result := (t.IsInitialized) and (t.Equals(e.&Mod(n)));
+end;
+
+function TECNRSigner.GetRecoveredMessage(const r, s: TBigInteger)
+  : TCryptoLibByteArray;
+var
+  t: TBigInteger;
+begin
+  if (FForSigning) then
   begin
   begin
-    result := false;
-    Exit;
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SNotInitializedForVerifyingRecovery);
   end;
   end;
 
 
-  // compute P = sG + rW
+  t := ExtractT(FKey as IECPublicKeyParameters, r, s);
 
 
-  G := pubKey.parameters.G;
-  W := pubKey.Q;
-  // calculate P using ECAlgorithms Math
-  P := TECAlgorithms.SumOfTwoMultiplies(G, s, W, r).Normalize();
-
-  if (P.IsInfinity) then
+  if (t.IsInitialized) then
   begin
   begin
-    result := false;
+    result := TBigIntegers.AsUnsignedByteArray(t);
     Exit;
     Exit;
   end;
   end;
 
 
-  x := P.AffineXCoord.ToBigInteger();
-  t := r.Subtract(x).&Mod(n);
-
-  result := t.Equals(e);
+  result := Nil;
 end;
 end;
 
 
 end.
 end.

File diff suppressed because it is too large
+ 409 - 191
src/libraries/cryptolib4pascal/ClpEd25519.pas


+ 75 - 0
src/libraries/cryptolib4pascal/ClpEndoPreCompInfo.pas

@@ -0,0 +1,75 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpEndoPreCompInfo;
+
+{$I CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECC,
+  ClpIPreCompInfo,
+  ClpIEndoPreCompInfo;
+
+type
+  TEndoPreCompInfo = class sealed(TInterfacedObject, IPreCompInfo,
+    IEndoPreCompInfo)
+
+  strict private
+  var
+    FEndomorphism: IECEndomorphism;
+    FMappedPoint: IECPoint;
+
+    function GetEndomorphism: IECEndomorphism; inline;
+    procedure SetEndomorphism(const value: IECEndomorphism); inline;
+
+    function GetMappedPoint: IECPoint; inline;
+    procedure SetMappedPoint(const value: IECPoint); inline;
+
+  public
+
+    property Endomorphism: IECEndomorphism read GetEndomorphism
+      write SetEndomorphism;
+    property MappedPoint: IECPoint read GetMappedPoint write SetMappedPoint;
+  end;
+
+implementation
+
+{ TEndoPreCompInfo }
+
+function TEndoPreCompInfo.GetEndomorphism: IECEndomorphism;
+begin
+  result := FEndomorphism;
+end;
+
+function TEndoPreCompInfo.GetMappedPoint: IECPoint;
+begin
+  result := FMappedPoint;
+end;
+
+procedure TEndoPreCompInfo.SetEndomorphism(const value: IECEndomorphism);
+begin
+  FEndomorphism := value;
+end;
+
+procedure TEndoPreCompInfo.SetMappedPoint(const value: IECPoint);
+begin
+  FMappedPoint := value;
+end;
+
+end.

+ 0 - 130
src/libraries/cryptolib4pascal/ClpFixedPointCombMultiplier.pas

@@ -1,130 +0,0 @@
-{ *********************************************************************************** }
-{ *                              CryptoLib Library                                  * }
-{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
-{ *                 Github Repository <https://github.com/Xor-el>                   * }
-
-{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
-{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
-
-{ *                              Acknowledgements:                                  * }
-{ *                                                                                 * }
-{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
-{ *                           development of this library                           * }
-
-{ * ******************************************************************************* * }
-
-(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
-
-unit ClpFixedPointCombMultiplier;
-
-{$I CryptoLib.inc}
-
-interface
-
-uses
-  ClpBits,
-  ClpBigInteger,
-  ClpNat,
-  ClpCryptoLibTypes,
-  ClpIECC,
-  ClpFixedPointUtilities,
-  ClpIFixedPointPreCompInfo,
-  ClpAbstractECMultiplier,
-  ClpIFixedPointCombMultiplier;
-
-resourcestring
-  SInvalidComputation =
-    'Fixed-Point Comb Doesn''t Support Scalars Larger Than The Curve Order';
-
-type
-  TFixedPointCombMultiplier = class sealed(TAbstractECMultiplier,
-    IFixedPointCombMultiplier)
-
-  strict protected
-    function MultiplyPositive(const p: IECPoint; const k: TBigInteger)
-      : IECPoint; override;
-
-  public
-    constructor Create();
-    destructor Destroy; override;
-
-  end;
-
-implementation
-
-{ TFixedPointCombMultiplier }
-
-constructor TFixedPointCombMultiplier.Create;
-begin
-  Inherited Create();
-end;
-
-destructor TFixedPointCombMultiplier.Destroy;
-begin
-  inherited Destroy;
-end;
-
-function TFixedPointCombMultiplier.MultiplyPositive(const p: IECPoint;
-  const k: TBigInteger): IECPoint;
-var
-  c: IECCurve;
-  R, add: IECPoint;
-  size, width, d, top, i, j, fullComb: Int32;
-  secretIndex, secretBit: UInt32;
-  info: IFixedPointPreCompInfo;
-  lookupTable: IECLookupTable;
-  LK: TCryptoLibUInt32Array;
-begin
-  c := p.Curve;
-  size := TFixedPointUtilities.GetCombSize(c);
-  if (k.BitLength > size) then
-  begin
-    // /*
-    // * TODO The comb works best when the scalars are less than the (possibly unknown) order.
-    // * Still, if we want to handle larger scalars, we could allow customization of the comb
-    // * size, or alternatively we could deal with the 'extra' bits either by running the comb
-    // * multiple times as necessary, or by using an alternative multiplier as prelude.
-    // */
-    raise EInvalidOperationCryptoLibException.CreateRes(@SInvalidComputation);
-  end;
-
-  info := TFixedPointUtilities.Precompute(p);
-  lookupTable := info.lookupTable;
-  width := info.width;
-
-  d := (size + width - 1) div width;
-
-  R := c.Infinity;
-  fullComb := d * width;
-  LK := TNat.FromBigInteger(fullComb, k);
-
-  top := fullComb - 1;
-
-  for i := 0 to System.Pred(d) do
-  begin
-
-    secretIndex := 0;
-
-    j := (top - i);
-
-    while j >= 0 do
-    begin
-
-      secretBit := LK[TBits.Asr32(j, 5)] shr (j and $1F);
-      secretIndex := secretIndex xor (secretBit shr 1);
-      secretIndex := secretIndex shl 1;
-      secretIndex := secretIndex xor secretBit;
-
-      System.Dec(j, d);
-    end;
-
-    add := lookupTable.Lookup(Int32(secretIndex));
-    R := R.TwicePlus(add);
-
-  end;
-
-  Result := R.add(info.Offset);
-
-end;
-
-end.

+ 0 - 219
src/libraries/cryptolib4pascal/ClpFixedPointUtilities.pas

@@ -1,219 +0,0 @@
-{ *********************************************************************************** }
-{ *                              CryptoLib Library                                  * }
-{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
-{ *                 Github Repository <https://github.com/Xor-el>                   * }
-
-{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
-{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
-
-{ *                              Acknowledgements:                                  * }
-{ *                                                                                 * }
-{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
-{ *                           development of this library                           * }
-
-{ * ******************************************************************************* * }
-
-(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
-
-unit ClpFixedPointUtilities;
-
-{$I CryptoLib.inc}
-
-interface
-
-uses
-  SysUtils,
-  ClpBigInteger,
-  ClpCryptoLibTypes,
-  ClpIPreCompInfo,
-  ClpIPreCompCallback,
-  ClpFixedPointPreCompInfo,
-  ClpIFixedPointPreCompInfo,
-  ClpIECC;
-
-type
-  TFixedPointUtilities = class sealed(TObject)
-  strict private
-
-  type
-    IFixedPointCallback = interface(IPreCompCallback)
-      ['{E6DFE8D3-A890-4568-AA4A-3D8BC6AF16E9}']
-
-    end;
-
-  type
-    TFixedPointCallback = class(TInterfacedObject, IPreCompCallback,
-      IFixedPointCallback)
-
-    strict private
-    var
-      Fm_p: IECPoint;
-
-    public
-      constructor Create(const p: IECPoint);
-
-      function Precompute(const existing: IPreCompInfo): IPreCompInfo;
-
-    end;
-
-  const
-    PRECOMP_NAME: String = 'bc_fixed_point';
-
-    class function CheckExisting(const existingFP: IFixedPointPreCompInfo;
-      n: Int32): Boolean; static; inline;
-
-    class function CheckTable(const table: IECLookupTable; n: Int32): Boolean;
-      static; inline;
-
-  public
-
-    class function GetFixedPointPreCompInfo(const preCompInfo: IPreCompInfo)
-      : IFixedPointPreCompInfo; static; inline;
-
-    class function GetCombSize(const c: IECCurve): Int32; static; inline;
-
-    class function Precompute(const p: IECPoint)
-      : IFixedPointPreCompInfo; static;
-  end;
-
-implementation
-
-{ TFixedPointUtilities }
-
-class function TFixedPointUtilities.CheckTable(const table: IECLookupTable;
-  n: Int32): Boolean;
-begin
-  result := (table <> Nil) and (table.Size >= n);
-end;
-
-class function TFixedPointUtilities.CheckExisting(const existingFP
-  : IFixedPointPreCompInfo; n: Int32): Boolean;
-begin
-  result := (existingFP <> Nil) and CheckTable(existingFP.LookUpTable, n);
-end;
-
-class function TFixedPointUtilities.GetCombSize(const c: IECCurve): Int32;
-var
-  order: TBigInteger;
-begin
-  order := c.order;
-  if (not(order.IsInitialized)) then
-  begin
-    result := c.FieldSize + 1;
-  end
-  else
-  begin
-    result := order.BitLength;
-  end;
-end;
-
-class function TFixedPointUtilities.GetFixedPointPreCompInfo(const preCompInfo
-  : IPreCompInfo): IFixedPointPreCompInfo;
-begin
-  result := preCompInfo as IFixedPointPreCompInfo;
-end;
-
-class function TFixedPointUtilities.Precompute(const p: IECPoint)
-  : IFixedPointPreCompInfo;
-var
-  c: IECCurve;
-begin
-  c := p.Curve;
-
-  result := c.Precompute(p, PRECOMP_NAME, TFixedPointCallback.Create(p)
-    as IFixedPointCallback) as IFixedPointPreCompInfo;
-end;
-
-{ TFixedPointUtilities.TFixedPointCallback }
-
-constructor TFixedPointUtilities.TFixedPointCallback.Create(const p: IECPoint);
-begin
-  Inherited Create();
-  Fm_p := p;
-end;
-
-function TFixedPointUtilities.TFixedPointCallback.Precompute(const existing
-  : IPreCompInfo): IPreCompInfo;
-var
-  bit, bits, minWidth, n, d, i, step: Int32;
-  existingFP: IFixedPointPreCompInfo;
-  pow2Table, LookUpTable: TCryptoLibGenericArray<IECPoint>;
-  pow2: IECPoint;
-  c: IECCurve;
-  tempResult: IFixedPointPreCompInfo;
-begin
-  if Supports(existing, IFixedPointPreCompInfo) then
-  begin
-    existingFP := existing as IFixedPointPreCompInfo;
-  end
-  else
-  begin
-    existingFP := Nil;
-  end;
-
-  c := Fm_p.Curve;
-  bits := TFixedPointUtilities.GetCombSize(c);
-  if bits > 250 then
-  begin
-    minWidth := 6
-  end
-  else
-  begin
-    minWidth := 5
-  end;
-  n := 1 shl minWidth;
-
-  if (CheckExisting(existingFP, n)) then
-  begin
-    result := existingFP;
-    Exit;
-  end;
-
-  d := (bits + minWidth - 1) div minWidth;
-
-  System.SetLength(pow2Table, minWidth + 1);
-
-  pow2Table[0] := Fm_p;
-  for i := 1 to System.Pred(minWidth) do
-  begin
-    pow2Table[i] := pow2Table[i - 1].TimesPow2(d);
-  end;
-
-  // This will be the 'offset' value
-  pow2Table[minWidth] := pow2Table[0].Subtract(pow2Table[1]);
-
-  c.NormalizeAll(pow2Table);
-
-  System.SetLength(LookUpTable, n);
-  LookUpTable[0] := pow2Table[0];
-
-  bit := minWidth - 1;
-  while bit >= 0 do
-  begin
-    pow2 := pow2Table[bit];
-
-    step := 1 shl bit;
-
-    i := step;
-
-    while i < n do
-    begin
-      LookUpTable[i] := LookUpTable[i - step].Add(pow2);
-
-      System.Inc(i, step shl 1);
-    end;
-
-    System.Dec(bit);
-  end;
-
-  c.NormalizeAll(LookUpTable);
-
-  tempResult := TFixedPointPreCompInfo.Create();
-  tempResult.LookUpTable := c.CreateCacheSafeLookupTable(LookUpTable, 0,
-    System.length(LookUpTable));
-  tempResult.Offset := pow2Table[minWidth];
-  tempResult.Width := minWidth;
-  result := tempResult;
-end;
-
-end.

+ 0 - 106
src/libraries/cryptolib4pascal/ClpGlvMultiplier.pas

@@ -1,106 +0,0 @@
-{ *********************************************************************************** }
-{ *                              CryptoLib Library                                  * }
-{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
-{ *                 Github Repository <https://github.com/Xor-el>                   * }
-
-{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
-{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
-
-{ *                              Acknowledgements:                                  * }
-{ *                                                                                 * }
-{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
-{ *                           development of this library                           * }
-
-{ * ******************************************************************************* * }
-
-(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
-
-unit ClpGlvMultiplier;
-
-{$I CryptoLib.inc}
-
-interface
-
-uses
-  ClpSetWeakRef,
-  ClpAbstractECMultiplier,
-  ClpIECC,
-  ClpIGlvEndomorphism,
-  ClpCryptoLibTypes,
-  ClpECAlgorithms,
-  ClpBigInteger,
-  ClpIGlvMultiplier;
-
-resourcestring
-  SCurveUnknownGroupOrder = 'Need Curve With Known Group Order, "curve"';
-
-type
-  TGlvMultiplier = class(TAbstractECMultiplier, IGlvMultiplier)
-
-  strict protected
-  var
-    Fcurve: IECCurve;
-    FglvEndomorphism: IGlvEndomorphism;
-
-    function MultiplyPositive(const p: IECPoint; const k: TBigInteger)
-      : IECPoint; override;
-
-  public
-    constructor Create(const curve: IECCurve;
-      const glvEndomorphism: IGlvEndomorphism);
-    destructor Destroy; override;
-
-  end;
-
-implementation
-
-{ TGlvMultiplier }
-
-constructor TGlvMultiplier.Create(const curve: IECCurve;
-  const glvEndomorphism: IGlvEndomorphism);
-begin
-  inherited Create();
-  if ((curve = Nil) or (not(curve.Order.IsInitialized))) then
-  begin
-    raise EArgumentCryptoLibException.CreateRes(@SCurveUnknownGroupOrder);
-  end;
-
-  // Fcurve := curve;
-  TSetWeakRef.SetWeakReference(@Fcurve, curve);
-  FglvEndomorphism := glvEndomorphism;
-end;
-
-destructor TGlvMultiplier.Destroy;
-begin
-  TSetWeakRef.SetWeakReference(@Fcurve, Nil);
-  inherited Destroy;
-end;
-
-function TGlvMultiplier.MultiplyPositive(const p: IECPoint;
-  const k: TBigInteger): IECPoint;
-var
-  n, a, b: TBigInteger;
-  ab: TCryptoLibGenericArray<TBigInteger>;
-  pointMap: IECPointMap;
-begin
-  if (not(Fcurve.Equals(p.curve))) then
-  begin
-    raise EInvalidOperationCryptoLibException.Create('');
-  end;
-
-  n := p.curve.Order;
-  ab := FglvEndomorphism.DecomposeScalar(k.&Mod(n));
-  a := ab[0];
-  b := ab[1];
-
-  pointMap := FglvEndomorphism.pointMap;
-  if (FglvEndomorphism.HasEfficientPointMap) then
-  begin
-    Result := TECAlgorithms.ImplShamirsTrickWNaf(p, a, pointMap, b);
-    Exit;
-  end;
-
-  Result := TECAlgorithms.ImplShamirsTrickWNaf(p, a, pointMap.Map(p), b);
-end;
-
-end.

+ 92 - 0
src/libraries/cryptolib4pascal/ClpGlvTypeAEndomorphism.pas

@@ -0,0 +1,92 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpGlvTypeAEndomorphism;
+
+{$I CryptoLib.inc}
+
+interface
+
+uses
+  ClpCryptoLibTypes,
+  ClpBigInteger,
+  ClpECCompUtilities,
+  ClpScaleYNegateXPointMap,
+  ClpIGlvTypeAEndomorphism,
+  ClpIECC,
+  ClpIGlvTypeAParameters,
+  ClpIGlvEndomorphism;
+
+type
+  TGlvTypeAEndomorphism = class(TInterfacedObject, IECEndomorphism,
+    IGlvEndomorphism, IGlvTypeAEndomorphism)
+
+  strict private
+    function GetHasEfficientPointMap: Boolean; virtual;
+    function GetPointMap: IECPointMap; virtual;
+
+  strict protected
+  var
+    FParameters: IGlvTypeAParameters;
+    FPointMap: IECPointMap;
+
+  public
+    constructor Create(const curve: IECCurve;
+      const parameters: IGlvTypeAParameters);
+
+    function DecomposeScalar(const k: TBigInteger)
+      : TCryptoLibGenericArray<TBigInteger>; virtual;
+
+    property PointMap: IECPointMap read GetPointMap;
+    property HasEfficientPointMap: Boolean read GetHasEfficientPointMap;
+  end;
+
+implementation
+
+{ TGlvTypeAEndomorphism }
+
+constructor TGlvTypeAEndomorphism.Create(const curve: IECCurve;
+  const parameters: IGlvTypeAParameters);
+begin
+  Inherited Create();
+  (*
+    * NOTE: 'curve' MUST only be used to create a suitable ECFieldElement. Due to the way
+    * ECCurve configuration works, 'curve' will not be the actual instance of ECCurve that the
+    * endomorphism is being used with.
+  *)
+  FParameters := parameters;
+  FPointMap := TScaleYNegateXPointMap.Create
+    (curve.FromBigInteger(parameters.I));
+end;
+
+function TGlvTypeAEndomorphism.DecomposeScalar(const k: TBigInteger)
+  : TCryptoLibGenericArray<TBigInteger>;
+begin
+  Result := TEndoUtilities.DecomposeScalar(FParameters.SplitParams, k);
+end;
+
+function TGlvTypeAEndomorphism.GetHasEfficientPointMap: Boolean;
+begin
+  Result := true;
+end;
+
+function TGlvTypeAEndomorphism.GetPointMap: IECPointMap;
+begin
+  Result := FPointMap;
+end;
+
+end.

+ 81 - 0
src/libraries/cryptolib4pascal/ClpGlvTypeAParameters.pas

@@ -0,0 +1,81 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpGlvTypeAParameters;
+
+{$I CryptoLib.inc}
+
+interface
+
+uses
+  ClpBigInteger,
+  ClpIGlvTypeAParameters,
+  ClpIScalarSplitParameters,
+  ClpCryptoLibTypes;
+
+type
+  TGlvTypeAParameters = class sealed(TInterfacedObject, IGlvTypeAParameters)
+
+  strict private
+  var
+    FI, Flambda: TBigInteger;
+    FsplitParams: IScalarSplitParameters;
+
+    function GetLambda: TBigInteger; inline;
+    function GetI: TBigInteger; inline;
+    function GetSplitParams: IScalarSplitParameters; inline;
+
+  public
+
+    constructor Create(const I, lambda: TBigInteger;
+      const splitParams: IScalarSplitParameters);
+
+    property lambda: TBigInteger read GetLambda;
+    property I: TBigInteger read GetI;
+    property splitParams: IScalarSplitParameters read GetSplitParams;
+
+  end;
+
+implementation
+
+{ TGlvTypeAParameters }
+
+constructor TGlvTypeAParameters.Create(const I, lambda: TBigInteger;
+  const splitParams: IScalarSplitParameters);
+begin
+  Inherited Create();
+  FI := I;
+  Flambda := lambda;
+  FsplitParams := splitParams;
+end;
+
+function TGlvTypeAParameters.GetI: TBigInteger;
+begin
+  Result := FI;
+end;
+
+function TGlvTypeAParameters.GetLambda: TBigInteger;
+begin
+  Result := Flambda;
+end;
+
+function TGlvTypeAParameters.GetSplitParams: IScalarSplitParameters;
+begin
+  Result := FsplitParams;
+end;
+
+end.

+ 14 - 55
src/libraries/cryptolib4pascal/ClpGlvTypeBEndomorphism.pas

@@ -28,7 +28,8 @@ uses
   ClpIGlvTypeBEndomorphism,
   ClpIGlvTypeBEndomorphism,
   ClpIECC,
   ClpIECC,
   ClpIGlvTypeBParameters,
   ClpIGlvTypeBParameters,
-  ClpIGlvEndomorphism;
+  ClpIGlvEndomorphism,
+  ClpECCompUtilities;
 
 
 type
 type
   TGlvTypeBEndomorphism = class(TInterfacedObject, IECEndomorphism,
   TGlvTypeBEndomorphism = class(TInterfacedObject, IECEndomorphism,
@@ -40,17 +41,13 @@ type
 
 
   strict protected
   strict protected
   var
   var
-    Fm_parameters: IGlvTypeBParameters;
-    Fm_pointMap: IECPointMap;
-    Fm_curve: IECCurve;
-
-    function CalculateB(const k, g: TBigInteger; t: Int32)
-      : TBigInteger; virtual;
+    FParameters: IGlvTypeBParameters;
+    FPointMap: IECPointMap;
 
 
   public
   public
     constructor Create(const curve: IECCurve;
     constructor Create(const curve: IECCurve;
       const parameters: IGlvTypeBParameters);
       const parameters: IGlvTypeBParameters);
-    destructor Destroy; override;
+
     function DecomposeScalar(const k: TBigInteger)
     function DecomposeScalar(const k: TBigInteger)
       : TCryptoLibGenericArray<TBigInteger>; virtual;
       : TCryptoLibGenericArray<TBigInteger>; virtual;
 
 
@@ -62,61 +59,23 @@ implementation
 
 
 { TGlvTypeBEndomorphism }
 { TGlvTypeBEndomorphism }
 
 
-function TGlvTypeBEndomorphism.CalculateB(const k, g: TBigInteger; t: Int32)
-  : TBigInteger;
-var
-  negative, extra: Boolean;
-  b: TBigInteger;
-begin
-  negative := (g.SignValue < 0);
-  b := k.Multiply(g.Abs());
-  extra := b.TestBit(t - 1);
-  b := b.ShiftRight(t);
-  if (extra) then
-  begin
-    b := b.Add(TBigInteger.One);
-  end;
-  if negative then
-  begin
-    Result := b.Negate();
-  end
-  else
-  begin
-    Result := b;
-  end;
-end;
-
 constructor TGlvTypeBEndomorphism.Create(const curve: IECCurve;
 constructor TGlvTypeBEndomorphism.Create(const curve: IECCurve;
   const parameters: IGlvTypeBParameters);
   const parameters: IGlvTypeBParameters);
 begin
 begin
   Inherited Create();
   Inherited Create();
-  Fm_curve := curve;
-  Fm_parameters := parameters;
-  Fm_pointMap := TScaleXPointMap.Create(curve.FromBigInteger(parameters.Beta));
+  (*
+    * NOTE: 'curve' MUST only be used to create a suitable ECFieldElement. Due to the way
+    * ECCurve configuration works, 'curve' will not be the actual instance of ECCurve that the
+    * endomorphism is being used with.
+  *)
+  FParameters := parameters;
+  FPointMap := TScaleXPointMap.Create(curve.FromBigInteger(parameters.Beta));
 end;
 end;
 
 
 function TGlvTypeBEndomorphism.DecomposeScalar(const k: TBigInteger)
 function TGlvTypeBEndomorphism.DecomposeScalar(const k: TBigInteger)
   : TCryptoLibGenericArray<TBigInteger>;
   : TCryptoLibGenericArray<TBigInteger>;
-var
-  bits: Int32;
-  b1, b2, a, b: TBigInteger;
-  v1, v2: TCryptoLibGenericArray<TBigInteger>;
-begin
-  bits := Fm_parameters.bits;
-  b1 := CalculateB(k, Fm_parameters.G1, bits);
-  b2 := CalculateB(k, Fm_parameters.G2, bits);
-
-  v1 := Fm_parameters.v1;
-  v2 := Fm_parameters.v2;
-  a := k.Subtract((b1.Multiply(v1[0])).Add(b2.Multiply(v2[0])));
-  b := (b1.Multiply(v1[1])).Add(b2.Multiply(v2[1])).Negate();
-
-  Result := TCryptoLibGenericArray<TBigInteger>.Create(a, b);
-end;
-
-destructor TGlvTypeBEndomorphism.Destroy;
 begin
 begin
-  inherited Destroy;
+  Result := TEndoUtilities.DecomposeScalar(FParameters.SplitParams, k);
 end;
 end;
 
 
 function TGlvTypeBEndomorphism.GetHasEfficientPointMap: Boolean;
 function TGlvTypeBEndomorphism.GetHasEfficientPointMap: Boolean;
@@ -126,7 +85,7 @@ end;
 
 
 function TGlvTypeBEndomorphism.GetPointMap: IECPointMap;
 function TGlvTypeBEndomorphism.GetPointMap: IECPointMap;
 begin
 begin
-  Result := Fm_pointMap;
+  Result := FPointMap;
 end;
 end;
 
 
 end.
 end.

+ 20 - 59
src/libraries/cryptolib4pascal/ClpGlvTypeBParameters.pas

@@ -24,39 +24,29 @@ interface
 uses
 uses
   ClpBigInteger,
   ClpBigInteger,
   ClpIGlvTypeBParameters,
   ClpIGlvTypeBParameters,
+  ClpIScalarSplitParameters,
   ClpCryptoLibTypes;
   ClpCryptoLibTypes;
 
 
 type
 type
   TGlvTypeBParameters = class sealed(TInterfacedObject, IGlvTypeBParameters)
   TGlvTypeBParameters = class sealed(TInterfacedObject, IGlvTypeBParameters)
 
 
   strict private
   strict private
-    function GetBeta: TBigInteger; inline;
-    function GetBits: Int32; inline;
-    function GetG1: TBigInteger; inline;
-    function GetG2: TBigInteger; inline;
+  var
+    Fbeta, Flambda: TBigInteger;
+    FsplitParams: IScalarSplitParameters;
+
     function GetLambda: TBigInteger; inline;
     function GetLambda: TBigInteger; inline;
-    function GetV1: TCryptoLibGenericArray<TBigInteger>; inline;
-    function GetV2: TCryptoLibGenericArray<TBigInteger>; inline;
-  strict protected
-    Fm_beta, Fm_lambda: TBigInteger;
-    Fm_v1, Fm_v2: TCryptoLibGenericArray<TBigInteger>;
-    Fm_g1, Fm_g2: TBigInteger;
-    Fm_bits: Int32;
+    function GetBeta: TBigInteger; inline;
+    function GetSplitParams: IScalarSplitParameters; inline;
 
 
   public
   public
-    constructor Create(const beta, lambda: TBigInteger;
-      const v1, v2: TCryptoLibGenericArray<TBigInteger>;
-      const g1, g2: TBigInteger; bits: Int32);
 
 
-    destructor Destroy; override;
+    constructor Create(const beta, lambda: TBigInteger;
+      const splitParams: IScalarSplitParameters);
 
 
-    property beta: TBigInteger read GetBeta;
     property lambda: TBigInteger read GetLambda;
     property lambda: TBigInteger read GetLambda;
-    property v1: TCryptoLibGenericArray<TBigInteger> read GetV1;
-    property v2: TCryptoLibGenericArray<TBigInteger> read GetV2;
-    property g1: TBigInteger read GetG1;
-    property g2: TBigInteger read GetG2;
-    property bits: Int32 read GetBits;
+    property beta: TBigInteger read GetBeta;
+    property splitParams: IScalarSplitParameters read GetSplitParams;
 
 
   end;
   end;
 
 
@@ -65,56 +55,27 @@ implementation
 { TGlvTypeBParameters }
 { TGlvTypeBParameters }
 
 
 constructor TGlvTypeBParameters.Create(const beta, lambda: TBigInteger;
 constructor TGlvTypeBParameters.Create(const beta, lambda: TBigInteger;
-  const v1, v2: TCryptoLibGenericArray<TBigInteger>; const g1, g2: TBigInteger;
-  bits: Int32);
+  const splitParams: IScalarSplitParameters);
 begin
 begin
-  Fm_beta := beta;
-  Fm_lambda := lambda;
-  Fm_v1 := v1;
-  Fm_v2 := v2;
-  Fm_g1 := g1;
-  Fm_g2 := g2;
-  Fm_bits := bits;
-end;
-
-destructor TGlvTypeBParameters.Destroy;
-begin
-  inherited Destroy;
+  Inherited Create();
+  Fbeta := beta;
+  Flambda := lambda;
+  FsplitParams := splitParams;
 end;
 end;
 
 
 function TGlvTypeBParameters.GetBeta: TBigInteger;
 function TGlvTypeBParameters.GetBeta: TBigInteger;
 begin
 begin
-  Result := Fm_beta;
-end;
-
-function TGlvTypeBParameters.GetBits: Int32;
-begin
-  Result := Fm_bits;
-end;
-
-function TGlvTypeBParameters.GetG1: TBigInteger;
-begin
-  Result := Fm_g1;
-end;
-
-function TGlvTypeBParameters.GetG2: TBigInteger;
-begin
-  Result := Fm_g2;
+  Result := Fbeta;
 end;
 end;
 
 
 function TGlvTypeBParameters.GetLambda: TBigInteger;
 function TGlvTypeBParameters.GetLambda: TBigInteger;
 begin
 begin
-  Result := Fm_lambda;
-end;
-
-function TGlvTypeBParameters.GetV1: TCryptoLibGenericArray<TBigInteger>;
-begin
-  Result := Fm_v1;
+  Result := Flambda;
 end;
 end;
 
 
-function TGlvTypeBParameters.GetV2: TCryptoLibGenericArray<TBigInteger>;
+function TGlvTypeBParameters.GetSplitParams: IScalarSplitParameters;
 begin
 begin
-  Result := Fm_v2;
+  Result := FsplitParams;
 end;
 end;
 
 
 end.
 end.

+ 1 - 1
src/libraries/cryptolib4pascal/ClpICurve25519Custom.pas

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

+ 19 - 2
src/libraries/cryptolib4pascal/ClpIECC.pas

@@ -118,6 +118,7 @@ type
 
 
     function Trace(): Int32;
     function Trace(): Int32;
     function HalfTrace(): IECFieldElement;
     function HalfTrace(): IECFieldElement;
+    function HasFastTrace(): Boolean;
   end;
   end;
 
 
 type
 type
@@ -252,6 +253,9 @@ type
     function ScaleX(const scale: IECFieldElement): IECPoint;
     function ScaleX(const scale: IECFieldElement): IECPoint;
     function ScaleY(const scale: IECFieldElement): IECPoint;
     function ScaleY(const scale: IECFieldElement): IECPoint;
 
 
+    function ScaleXNegateY(const scale: IECFieldElement): IECPoint;
+    function ScaleYNegateX(const scale: IECFieldElement): IECPoint;
+
     function GetEncoded(): TCryptoLibByteArray; overload;
     function GetEncoded(): TCryptoLibByteArray; overload;
     function GetEncoded(compressed: Boolean): TCryptoLibByteArray; overload;
     function GetEncoded(compressed: Boolean): TCryptoLibByteArray; overload;
 
 
@@ -591,11 +595,24 @@ type
     ['{A1839961-4FBF-42EF-BF8B-6084064A05C1}']
     ['{A1839961-4FBF-42EF-BF8B-6084064A05C1}']
     function GetSize: Int32;
     function GetSize: Int32;
     function Lookup(index: Int32): IECPoint;
     function Lookup(index: Int32): IECPoint;
+    function LookupVar(index: Int32): IECPoint;
     property Size: Int32 read GetSize;
     property Size: Int32 read GetSize;
   end;
   end;
 
 
 type
 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}']
     ['{094881EB-24A6-41A3-BAD6-D6DAB13DD17D}']
 
 
   end;
   end;
@@ -607,7 +624,7 @@ type
   end;
   end;
 
 
 type
 type
-  IDefaultF2mLookupTable = interface(IECLookupTable)
+  IDefaultF2mLookupTable = interface(IAbstractECLookupTable)
     ['{0C019049-9839-4322-BAF5-8E5D39BC426D}']
     ['{0C019049-9839-4322-BAF5-8E5D39BC426D}']
 
 
   end;
   end;

+ 2 - 0
src/libraries/cryptolib4pascal/ClpIECNRSigner.pas

@@ -30,6 +30,8 @@ type
   IECNRSigner = interface(IDsaExt)
   IECNRSigner = interface(IDsaExt)
     ['{C136F005-404E-4022-886E-DE5EFCECFF9C}']
     ['{C136F005-404E-4022-886E-DE5EFCECFF9C}']
 
 
+    function GetRecoveredMessage(const r, s: TBigInteger): TCryptoLibByteArray;
+
   end;
   end;
 
 
 implementation
 implementation

+ 47 - 0
src/libraries/cryptolib4pascal/ClpIEndoPreCompInfo.pas

@@ -0,0 +1,47 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpIEndoPreCompInfo;
+
+{$I CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECC,
+  ClpIPreCompInfo;
+
+type
+  IEndoPreCompInfo = interface(IPreCompInfo)
+    ['{84C79A80-8162-4079-8146-AA1D46A739ED}']
+
+    function GetEndomorphism: IECEndomorphism;
+    procedure SetEndomorphism(const value: IECEndomorphism);
+
+    property Endomorphism: IECEndomorphism read GetEndomorphism
+      write SetEndomorphism;
+
+    function GetMappedPoint: IECPoint;
+    procedure SetMappedPoint(const value: IECPoint);
+
+    property MappedPoint: IECPoint read GetMappedPoint write SetMappedPoint;
+
+  end;
+
+implementation
+
+end.

+ 4 - 4
src/libraries/cryptolib4pascal/ClpIGlvMultiplier.pas → src/libraries/cryptolib4pascal/ClpIGlvTypeAEndomorphism.pas

@@ -15,7 +15,7 @@
 
 
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 
 
-unit ClpIGlvMultiplier;
+unit ClpIGlvTypeAEndomorphism;
 
 
 {$I CryptoLib.inc}
 {$I CryptoLib.inc}
 
 
@@ -23,11 +23,11 @@ interface
 
 
 uses
 uses
   ClpBigInteger,
   ClpBigInteger,
-  ClpIAbstractECMultiplier;
+  ClpIGlvEndomorphism;
 
 
 type
 type
-  IGlvMultiplier = interface(IAbstractECMultiplier)
-    ['{F54D54F5-F544-421B-89FC-1D8058FB8F33}']
+  IGlvTypeAEndomorphism = interface(IGlvEndomorphism)
+    ['{961A1588-7D37-46C5-BC67-F71063641B42}']
 
 
   end;
   end;
 
 

+ 14 - 17
src/libraries/cryptolib4pascal/ClpIWNafL2RMultiplier.pas → src/libraries/cryptolib4pascal/ClpIGlvTypeAParameters.pas

@@ -15,7 +15,7 @@
 
 
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 
 
-unit ClpIWNafL2RMultiplier;
+unit ClpIGlvTypeAParameters;
 
 
 {$I CryptoLib.inc}
 {$I CryptoLib.inc}
 
 
@@ -23,24 +23,21 @@ interface
 
 
 uses
 uses
   ClpBigInteger,
   ClpBigInteger,
-  ClpIAbstractECMultiplier;
+  ClpIScalarSplitParameters,
+  ClpCryptoLibTypes;
 
 
 type
 type
-  IWNafL2RMultiplier = interface(IAbstractECMultiplier)
-
-    ['{E2A5E4EF-C092-4F83-ACCF-0FC8731FB274}']
-
-    /// <summary>
-    /// Determine window width to use for a scalar multiplication of the
-    /// given size.
-    /// </summary>
-    /// <param name="bits">
-    /// the bit-length of the scalar to multiply by
-    /// </param>
-    /// <returns>
-    /// the window size to use
-    /// </returns>
-    function GetWindowSize(bits: Int32): Int32;
+
+  IGlvTypeAParameters = interface(IInterface)
+    ['{B5DDABB5-B51C-41F4-B2FD-6C8733300502}']
+
+    function GetI: TBigInteger;
+    function GetLambda: TBigInteger;
+    function GetSplitParams: IScalarSplitParameters;
+
+    property I: TBigInteger read GetI;
+    property lambda: TBigInteger read GetLambda;
+    property splitParams: IScalarSplitParameters read GetSplitParams;
 
 
   end;
   end;
 
 

+ 0 - 2
src/libraries/cryptolib4pascal/ClpIGlvTypeBEndomorphism.pas

@@ -29,8 +29,6 @@ type
   IGlvTypeBEndomorphism = interface(IGlvEndomorphism)
   IGlvTypeBEndomorphism = interface(IGlvEndomorphism)
     ['{4F285F6A-F627-4873-9F4C-FBC7A7B83A9C}']
     ['{4F285F6A-F627-4873-9F4C-FBC7A7B83A9C}']
 
 
-    function CalculateB(const k, g: TBigInteger; t: Int32): TBigInteger;
-
   end;
   end;
 
 
 implementation
 implementation

+ 5 - 12
src/libraries/cryptolib4pascal/ClpIGlvTypeBParameters.pas

@@ -23,6 +23,7 @@ interface
 
 
 uses
 uses
   ClpBigInteger,
   ClpBigInteger,
+  ClpIScalarSplitParameters,
   ClpCryptoLibTypes;
   ClpCryptoLibTypes;
 
 
 type
 type
@@ -30,21 +31,13 @@ type
   IGlvTypeBParameters = interface(IInterface)
   IGlvTypeBParameters = interface(IInterface)
     ['{089AC2AB-15A1-47F5-BED0-C09EA77BECB9}']
     ['{089AC2AB-15A1-47F5-BED0-C09EA77BECB9}']
 
 
-    function GetBeta: TBigInteger;
-    function GetBits: Int32;
-    function GetG1: TBigInteger;
-    function GetG2: TBigInteger;
     function GetLambda: TBigInteger;
     function GetLambda: TBigInteger;
-    function GetV1: TCryptoLibGenericArray<TBigInteger>;
-    function GetV2: TCryptoLibGenericArray<TBigInteger>;
+    function GetBeta: TBigInteger;
+    function GetSplitParams: IScalarSplitParameters;
 
 
-    property beta: TBigInteger read GetBeta;
     property lambda: TBigInteger read GetLambda;
     property lambda: TBigInteger read GetLambda;
-    property v1: TCryptoLibGenericArray<TBigInteger> read GetV1;
-    property v2: TCryptoLibGenericArray<TBigInteger> read GetV2;
-    property g1: TBigInteger read GetG1;
-    property g2: TBigInteger read GetG2;
-    property bits: Int32 read GetBits;
+    property beta: TBigInteger read GetBeta;
+    property splitParams: IScalarSplitParameters read GetSplitParams;
 
 
   end;
   end;
 
 

+ 30 - 3
src/libraries/cryptolib4pascal/ClpIWTauNafMultiplier.pas → src/libraries/cryptolib4pascal/ClpIMultipliers.pas

@@ -15,7 +15,7 @@
 
 
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 
 
-unit ClpIWTauNafMultiplier;
+unit ClpIMultipliers;
 
 
 {$I CryptoLib.inc}
 {$I CryptoLib.inc}
 
 
@@ -23,9 +23,36 @@ interface
 
 
 uses
 uses
   ClpBigInteger,
   ClpBigInteger,
-  ClpIECC,
   ClpIZTauElement,
   ClpIZTauElement,
-  ClpIAbstractECMultiplier;
+  ClpIECC;
+
+type
+  IAbstractECMultiplier = interface(IECMultiplier)
+    ['{DD63984C-7D4D-46DE-9004-20FD909C2EFB}']
+
+    function MultiplyPositive(const p: IECPoint; const k: TBigInteger)
+      : IECPoint;
+
+  end;
+
+type
+  IFixedPointCombMultiplier = interface(IAbstractECMultiplier)
+    ['{A3345E31-4D5C-4442-9C3D-ACC7F6DA4A14}']
+
+  end;
+
+type
+  IGlvMultiplier = interface(IAbstractECMultiplier)
+    ['{F54D54F5-F544-421B-89FC-1D8058FB8F33}']
+
+  end;
+
+type
+  IWNafL2RMultiplier = interface(IAbstractECMultiplier)
+
+    ['{E2A5E4EF-C092-4F83-ACCF-0FC8731FB274}']
+
+  end;
 
 
 type
 type
   IWTauNafMultiplier = interface(IAbstractECMultiplier)
   IWTauNafMultiplier = interface(IAbstractECMultiplier)

+ 6 - 0
src/libraries/cryptolib4pascal/ClpIRandomNumberGenerator.pas

@@ -46,6 +46,12 @@ type
 
 
   end;
   end;
 
 
+type
+  IAESPRNGRandomNumberGenerator = interface(IRandomNumberGenerator)
+    ['{9E0D8D8F-D9D4-42D6-9D55-36271293B59E}']
+
+  end;
+
 implementation
 implementation
 
 
 end.
 end.

+ 52 - 0
src/libraries/cryptolib4pascal/ClpIScalarSplitParameters.pas

@@ -0,0 +1,52 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpIScalarSplitParameters;
+
+{$I CryptoLib.inc}
+
+interface
+
+uses
+  ClpBigInteger,
+  ClpIGlvEndomorphism;
+
+type
+  IScalarSplitParameters = interface(IInterface)
+    ['{C36FF223-C4F3-4483-B280-A50EF95497AF}']
+
+    function GetG1: TBigInteger;
+    function GetG2: TBigInteger;
+    function GetV1A: TBigInteger;
+    function GetV1B: TBigInteger;
+    function GetV2A: TBigInteger;
+    function GetV2B: TBigInteger;
+    function GetBits: Int32;
+
+    property g1: TBigInteger read GetG1;
+    property g2: TBigInteger read GetG2;
+    property V1A: TBigInteger read GetV1A;
+    property V1B: TBigInteger read GetV1B;
+    property V2A: TBigInteger read GetV2A;
+    property V2B: TBigInteger read GetV2B;
+    property bits: Int32 read GetBits;
+
+  end;
+
+implementation
+
+end.

+ 5 - 4
src/libraries/cryptolib4pascal/ClpIFixedPointCombMultiplier.pas → src/libraries/cryptolib4pascal/ClpIScaleXNegateYPointMap.pas

@@ -15,18 +15,19 @@
 
 
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 
 
-unit ClpIFixedPointCombMultiplier;
+unit ClpIScaleXNegateYPointMap;
 
 
 {$I CryptoLib.inc}
 {$I CryptoLib.inc}
 
 
 interface
 interface
 
 
 uses
 uses
-  ClpIAbstractECMultiplier;
+  ClpIECC;
 
 
 type
 type
-  IFixedPointCombMultiplier = interface(IAbstractECMultiplier)
-    ['{A3345E31-4D5C-4442-9C3D-ACC7F6DA4A14}']
+  IScaleXNegateYPointMap = interface(IECPointMap)
+
+    ['{D4FF6900-B627-45AB-8066-00E763213CE5}']
 
 
   end;
   end;
 
 

+ 3 - 7
src/libraries/cryptolib4pascal/ClpIAbstractECMultiplier.pas → src/libraries/cryptolib4pascal/ClpIScaleYNegateXPointMap.pas

@@ -15,23 +15,19 @@
 
 
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 
 
-unit ClpIAbstractECMultiplier;
+unit ClpIScaleYNegateXPointMap;
 
 
 {$I CryptoLib.inc}
 {$I CryptoLib.inc}
 
 
 interface
 interface
 
 
 uses
 uses
-  ClpBigInteger,
   ClpIECC;
   ClpIECC;
 
 
 type
 type
+  IScaleYNegateXPointMap = interface(IECPointMap)
 
 
-  IAbstractECMultiplier = interface(IECMultiplier)
-    ['{DD63984C-7D4D-46DE-9004-20FD909C2EFB}']
-
-    function MultiplyPositive(const p: IECPoint; const k: TBigInteger)
-      : IECPoint;
+    ['{6284EFA2-DE75-437F-86D3-DD93BCAF511B}']
 
 
   end;
   end;
 
 

+ 1 - 1
src/libraries/cryptolib4pascal/ClpISecP256K1Custom.pas

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

+ 1 - 1
src/libraries/cryptolib4pascal/ClpISecP256R1Custom.pas

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

+ 1 - 1
src/libraries/cryptolib4pascal/ClpISecP384R1Custom.pas

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

+ 1 - 1
src/libraries/cryptolib4pascal/ClpISecP521R1Custom.pas

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

+ 1 - 1
src/libraries/cryptolib4pascal/ClpISecT283Custom.pas

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

+ 2 - 2
src/libraries/cryptolib4pascal/ClpIValidityPrecompInfo.pas

@@ -15,7 +15,7 @@
 
 
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 
 
-unit ClpIValidityPrecompInfo;
+unit ClpIValidityPreCompInfo;
 
 
 {$I CryptoLib.inc}
 {$I CryptoLib.inc}
 
 
@@ -25,7 +25,7 @@ uses
   ClpIPreCompInfo;
   ClpIPreCompInfo;
 
 
 type
 type
-  IValidityPrecompInfo = interface(IPreCompInfo)
+  IValidityPreCompInfo = interface(IPreCompInfo)
 
 
     ['{2339F5CA-A4B3-4E95-B358-4D4F4CA97EB3}']
     ['{2339F5CA-A4B3-4E95-B358-4D4F4CA97EB3}']
 
 

+ 18 - 0
src/libraries/cryptolib4pascal/ClpIWNafPreCompInfo.pas

@@ -37,12 +37,30 @@ type
     function GetTwice: IECPoint;
     function GetTwice: IECPoint;
     procedure SetTwice(const Value: IECPoint);
     procedure SetTwice(const Value: IECPoint);
 
 
+    function GetConfWidth: Int32;
+    procedure SetConfWidth(Value: Int32);
+
+    function GetWidth: Int32;
+    procedure SetWidth(Value: Int32);
+
+    function GetPromotionCountdown: Int32;
+    procedure SetPromotionCountdown(Value: Int32);
+
+    function DecrementPromotionCountdown: Int32;
+
+    function IsPromoted: Boolean;
+
     property PreComp: TCryptoLibGenericArray<IECPoint> read GetPreComp
     property PreComp: TCryptoLibGenericArray<IECPoint> read GetPreComp
       write SetPreComp;
       write SetPreComp;
     property PreCompNeg: TCryptoLibGenericArray<IECPoint> read GetPreCompNeg
     property PreCompNeg: TCryptoLibGenericArray<IECPoint> read GetPreCompNeg
       write SetPreCompNeg;
       write SetPreCompNeg;
     property Twice: IECPoint read GetTwice write SetTwice;
     property Twice: IECPoint read GetTwice write SetTwice;
 
 
+    property ConfWidth: Int32 read GetConfWidth write SetConfWidth;
+    property Width: Int32 read GetWidth write SetWidth;
+    property PromotionCountdown: Int32 read GetPromotionCountdown
+      write SetPromotionCountdown;
+
   end;
   end;
 
 
 implementation
 implementation

+ 621 - 0
src/libraries/cryptolib4pascal/ClpMultipliers.pas

@@ -0,0 +1,621 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpMultipliers;
+
+{$I CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpBigInteger,
+  ClpBits,
+  ClpNat,
+  ClpTNaf,
+  ClpIECC,
+  ClpIGlvEndomorphism,
+  ClpIFixedPointPreCompInfo,
+  ClpIWTauNafPreCompInfo,
+  ClpWTauNafPreCompInfo,
+  ClpIZTauElement,
+  ClpIPreCompInfo,
+  ClpIPreCompCallBack,
+  ClpIMultipliers,
+  ClpIWNafPreCompInfo,
+  ClpECCompUtilities,
+  ClpSetWeakRef,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SInvalidComputation =
+    'Fixed-Point Comb Doesn''t Support Scalars Larger Than The Curve Order';
+  SCurveUnknownGroupOrder = 'Need Curve With Known Group Order, "curve"';
+  SInCompatiblePoint = 'Only AbstractF2mPoint can be used in WTauNafMultiplier';
+
+type
+  TAbstractECMultiplier = class abstract(TInterfacedObject,
+    IAbstractECMultiplier, IECMultiplier)
+
+  strict protected
+
+    function CheckResult(const p: IECPoint): IECPoint; virtual;
+    function MultiplyPositive(const p: IECPoint; const k: TBigInteger)
+      : IECPoint; virtual; abstract;
+
+  public
+
+    constructor Create();
+    function Multiply(const p: IECPoint; const k: TBigInteger)
+      : IECPoint; virtual;
+
+  end;
+
+type
+  TFixedPointCombMultiplier = class sealed(TAbstractECMultiplier,
+    IFixedPointCombMultiplier)
+
+  strict protected
+    function MultiplyPositive(const p: IECPoint; const k: TBigInteger)
+      : IECPoint; override;
+
+  public
+    constructor Create();
+
+  end;
+
+type
+  TGlvMultiplier = class(TAbstractECMultiplier, IGlvMultiplier)
+
+  strict protected
+  var
+    Fcurve: IECCurve;
+    FglvEndomorphism: IGlvEndomorphism;
+
+    function MultiplyPositive(const p: IECPoint; const k: TBigInteger)
+      : IECPoint; override;
+
+  public
+    constructor Create(const curve: IECCurve;
+      const glvEndomorphism: IGlvEndomorphism);
+    destructor Destroy; override;
+
+  end;
+
+type
+
+  /// <summary>
+  /// Class implementing the WNAF (Window Non-Adjacent Form) multiplication
+  /// algorithm.
+  /// </summary>
+  TWNafL2RMultiplier = class(TAbstractECMultiplier, IWNafL2RMultiplier)
+
+  strict protected
+    // /**
+    // * Multiplies <code>this</code> by an integer <code>k</code> using the
+    // * Window NAF method.
+    // * @param k The integer by which <code>this</code> is multiplied.
+    // * @return A new <code>ECPoint</code> which equals <code>this</code>
+    // * multiplied by <code>k</code>.
+    // */
+    function MultiplyPositive(const p: IECPoint; const k: TBigInteger)
+      : IECPoint; override;
+
+  public
+
+    constructor Create();
+
+  end;
+
+type
+  /// **
+  // * Class implementing the WTNAF (Window
+  // * <code>&#964;</code>-adic Non-Adjacent Form) algorithm.
+  // */
+  TWTauNafMultiplier = class(TAbstractECMultiplier, IWTauNafMultiplier)
+
+  strict private
+    // TODO Create WTauNafUtilities class and move various functionality into it
+
+  type
+    IWTauNafCallback = interface(IPreCompCallback)
+      ['{4D6F7B4A-B925-42C9-8D60-B7F24632EDC1}']
+
+    end;
+
+  type
+    TWTauNafCallback = class(TInterfacedObject, IPreCompCallback,
+      IWTauNafCallback)
+
+    strict private
+    var
+      Fm_p: IAbstractF2mPoint;
+      Fm_a: ShortInt;
+
+    public
+      constructor Create(const p: IAbstractF2mPoint; a: ShortInt);
+
+      function Precompute(const existing: IPreCompInfo): IPreCompInfo;
+
+    end;
+
+  const
+    PRECOMP_NAME: String = 'bc_wtnaf';
+
+    // /**
+    // * Multiplies an AbstractF2mPoint
+    // * by an element <code>&#955;</code> of <code><b>Z</b>[&#964;]</code> using
+    // * the <code>&#964;</code>-adic NAF (TNAF) method.
+    // * @param p The AbstractF2mPoint to multiply.
+    // * @param lambda The element <code>&#955;</code> of
+    // * <code><b>Z</b>[&#964;]</code> of which to compute the
+    // * <code>[&#964;]</code>-adic NAF.
+    // * @return <code>p</code> multiplied by <code>&#955;</code>.
+    // */
+    function MultiplyWTnaf(const p: IAbstractF2mPoint;
+      const lambda: IZTauElement; a, mu: ShortInt): IAbstractF2mPoint; inline;
+
+    // /**
+    // * Multiplies an AbstractF2mPoint
+    // * by an element <code>&#955;</code> of <code><b>Z</b>[&#964;]</code>
+    // * using the window <code>&#964;</code>-adic NAF (TNAF) method, given the
+    // * WTNAF of <code>&#955;</code>.
+    // * @param p The AbstractF2mPoint to multiply.
+    // * @param u The the WTNAF of <code>&#955;</code>..
+    // * @return <code>&#955; * p</code>
+    // */
+    class function MultiplyFromWTnaf(const p: IAbstractF2mPoint;
+      const u: TCryptoLibShortIntArray): IAbstractF2mPoint; static;
+
+  strict protected
+    // /**
+    // * Multiplies an AbstractF2mPoint
+    // * by <code>k</code> using the reduced <code>&#964;</code>-adic NAF (RTNAF)
+    // * method.
+    // * @param p The AbstractF2mPoint to multiply.
+    // * @param k The integer by which to multiply <code>k</code>.
+    // * @return <code>p</code> multiplied by <code>k</code>.
+    // */
+    function MultiplyPositive(const point: IECPoint; const k: TBigInteger)
+      : IECPoint; override;
+
+  public
+    constructor Create();
+
+  end;
+
+implementation
+
+uses
+  ClpECAlgorithms; // included here to avoid circular dependency :)
+
+{ TAbstractECMultiplier }
+
+function TAbstractECMultiplier.CheckResult(const p: IECPoint): IECPoint;
+begin
+  result := TECAlgorithms.ImplCheckResult(p);
+end;
+
+constructor TAbstractECMultiplier.Create;
+begin
+  Inherited Create();
+end;
+
+function TAbstractECMultiplier.Multiply(const p: IECPoint; const k: TBigInteger)
+  : IECPoint;
+var
+  positive: IECPoint;
+  sign: Int32;
+begin
+
+  sign := k.SignValue;
+  if ((sign = 0) or (p.IsInfinity)) then
+  begin
+    result := p.curve.Infinity;
+    Exit;
+  end;
+
+  positive := MultiplyPositive(p, k.Abs());
+
+  if sign > 0 then
+  begin
+    result := positive
+  end
+  else
+  begin
+    result := positive.Negate();
+  end;
+
+  // /*
+  // * Although the various multipliers ought not to produce invalid output under normal
+  // * circumstances, a final check here is advised to guard against fault attacks.
+  // */
+  result := CheckResult(result);
+
+end;
+
+{ TFixedPointCombMultiplier }
+
+constructor TFixedPointCombMultiplier.Create;
+begin
+  Inherited Create();
+end;
+
+function TFixedPointCombMultiplier.MultiplyPositive(const p: IECPoint;
+  const k: TBigInteger): IECPoint;
+var
+  c: IECCurve;
+  R, add: IECPoint;
+  size, width, d, top, i, j, fullComb: Int32;
+  secretIndex, secretBit: UInt32;
+  info: IFixedPointPreCompInfo;
+  lookupTable: IECLookupTable;
+  LK: TCryptoLibUInt32Array;
+begin
+  c := p.curve;
+  size := TFixedPointUtilities.GetCombSize(c);
+  if (k.BitLength > size) then
+  begin
+    // /*
+    // * TODO The comb works best when the scalars are less than the (possibly unknown) order.
+    // * Still, if we want to handle larger scalars, we could allow customization of the comb
+    // * size, or alternatively we could deal with the 'extra' bits either by running the comb
+    // * multiple times as necessary, or by using an alternative multiplier as prelude.
+    // */
+    raise EInvalidOperationCryptoLibException.CreateRes(@SInvalidComputation);
+  end;
+
+  info := TFixedPointUtilities.Precompute(p);
+  lookupTable := info.lookupTable;
+  width := info.width;
+
+  d := (size + width - 1) div width;
+
+  R := c.Infinity;
+  fullComb := d * width;
+  LK := TNat.FromBigInteger(fullComb, k);
+
+  top := fullComb - 1;
+
+  for i := 0 to System.Pred(d) do
+  begin
+
+    secretIndex := 0;
+
+    j := (top - i);
+
+    while j >= 0 do
+    begin
+
+      secretBit := LK[TBits.Asr32(j, 5)] shr (j and $1F);
+      secretIndex := secretIndex xor (secretBit shr 1);
+      secretIndex := secretIndex shl 1;
+      secretIndex := secretIndex xor secretBit;
+
+      System.Dec(j, d);
+    end;
+
+    add := lookupTable.Lookup(Int32(secretIndex));
+    R := R.TwicePlus(add);
+
+  end;
+
+  result := R.add(info.Offset);
+
+end;
+
+{ TGlvMultiplier }
+
+constructor TGlvMultiplier.Create(const curve: IECCurve;
+  const glvEndomorphism: IGlvEndomorphism);
+begin
+  inherited Create();
+  if ((curve = Nil) or (not(curve.Order.IsInitialized))) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SCurveUnknownGroupOrder);
+  end;
+
+  TSetWeakRef.SetWeakReference(@Fcurve, curve);
+  FglvEndomorphism := glvEndomorphism;
+end;
+
+destructor TGlvMultiplier.Destroy;
+begin
+  TSetWeakRef.SetWeakReference(@Fcurve, Nil);
+  inherited Destroy;
+end;
+
+function TGlvMultiplier.MultiplyPositive(const p: IECPoint;
+  const k: TBigInteger): IECPoint;
+var
+  n, a, b: TBigInteger;
+  ab: TCryptoLibGenericArray<TBigInteger>;
+  q: IECPoint;
+begin
+  if (not(Fcurve.Equals(p.curve))) then
+  begin
+    raise EInvalidOperationCryptoLibException.Create('');
+  end;
+
+  n := p.curve.Order;
+  ab := FglvEndomorphism.DecomposeScalar(k.&Mod(n));
+  a := ab[0];
+  b := ab[1];
+
+  if (FglvEndomorphism.HasEfficientPointMap) then
+  begin
+    result := TECAlgorithms.ImplShamirsTrickWNaf(FglvEndomorphism, p, a, b);
+    Exit;
+  end;
+
+  q := TEndoUtilities.MapPoint(FglvEndomorphism, p);
+
+  result := TECAlgorithms.ImplShamirsTrickWNaf(p, a, q, b);
+end;
+
+{ TWNafL2RMultiplier }
+
+constructor TWNafL2RMultiplier.Create;
+begin
+  Inherited Create();
+end;
+
+function TWNafL2RMultiplier.MultiplyPositive(const p: IECPoint;
+  const k: TBigInteger): IECPoint;
+var
+  width, minWidth, i, wi, digit, zeroes, n, highest, scale, lowBits, i1,
+    i2: Int32;
+  info: IWNafPreCompInfo;
+  preComp, preCompNeg, table: TCryptoLibGenericArray<IECPoint>;
+  wnaf: TCryptoLibInt32Array;
+  R, lr: IECPoint;
+begin
+  minWidth := TWNafUtilities.GetWindowSize(k.BitLength);
+
+  info := TWNafUtilities.Precompute(p, minWidth, true);
+  preComp := info.preComp;
+  preCompNeg := info.preCompNeg;
+  width := info.width;
+
+  wnaf := TWNafUtilities.GenerateCompactWindowNaf(width, k);
+
+  R := p.curve.Infinity;
+
+  i := System.Length(wnaf);
+
+  // /*
+  // * NOTE: We try to optimize the first window using the precomputed points to substitute an
+  // * addition for 2 or more doublings.
+  // */
+  if (i > 1) then
+  begin
+    System.Dec(i);
+    wi := wnaf[i];
+    digit := TBits.Asr32(wi, 16);
+    zeroes := wi and $FFFF;
+
+    n := System.Abs(digit);
+    if digit < 0 then
+    begin
+      table := preCompNeg;
+    end
+    else
+    begin
+      table := preComp;
+    end;
+
+    // Optimization can only be used for values in the lower half of the table
+    if ((n shl 2) < (1 shl width)) then
+    begin
+      highest := 32 - TBits.NumberOfLeadingZeros(n);
+
+      // TODO Get addition/doubling cost ratio from curve and compare to 'scale' to see if worth substituting?
+      scale := width - highest;
+      lowBits := n xor (1 shl (highest - 1));
+
+      i1 := ((1 shl (width - 1)) - 1);
+      i2 := (lowBits shl scale) + 1;
+      R := table[TBits.Asr32(i1, 1)].add(table[TBits.Asr32(i2, 1)]);
+
+      zeroes := zeroes - scale;
+    end
+    else
+    begin
+      R := table[TBits.Asr32(n, 1)];
+    end;
+
+    R := R.TimesPow2(zeroes);
+  end;
+
+  while (i > 0) do
+  begin
+    System.Dec(i);
+    wi := wnaf[i];
+    digit := TBits.Asr32(wi, 16);
+    zeroes := wi and $FFFF;
+
+    n := System.Abs(digit);
+    if digit < 0 then
+    begin
+      table := preCompNeg;
+    end
+    else
+    begin
+      table := preComp;
+    end;
+
+    lr := table[TBits.Asr32(n, 1)];
+
+    R := R.TwicePlus(lr);
+    R := R.TimesPow2(zeroes);
+  end;
+
+  result := R;
+
+  info.preComp := Nil; // Review
+  info.preCompNeg := Nil; // Review
+
+end;
+
+{ TWTauNafMultiplier }
+
+constructor TWTauNafMultiplier.Create;
+begin
+  Inherited Create();
+end;
+
+class function TWTauNafMultiplier.MultiplyFromWTnaf(const p: IAbstractF2mPoint;
+  const u: TCryptoLibShortIntArray): IAbstractF2mPoint;
+var
+  curve: IAbstractF2mCurve;
+  a: ShortInt;
+  i, tauCount, ui: Int32;
+  pu, puNeg: TCryptoLibGenericArray<IAbstractF2mPoint>;
+  pre: IWTauNafPreCompInfo;
+  q: IAbstractF2mPoint;
+  x: IECPoint;
+begin
+  curve := p.curve as IAbstractF2mCurve;
+  a := ShortInt(curve.a.ToBigInteger().Int32Value);
+
+  pre := curve.Precompute(p, PRECOMP_NAME, TWTauNafCallback.Create(p, a)
+    as IWTauNafCallback) as IWTauNafPreCompInfo;
+
+  pu := pre.preComp;
+  // TODO Include negations in precomp (optionally) and use from here
+  System.SetLength(puNeg, System.Length(pu));
+  for i := 0 to System.Pred(System.Length(pu)) do
+  begin
+    puNeg[i] := pu[i].Negate() as IAbstractF2mPoint;
+  end;
+
+  q := p.curve.Infinity as IAbstractF2mPoint;
+  tauCount := 0;
+  i := System.Length(u) - 1;
+  while i >= 0 do
+  begin
+    System.Inc(tauCount);
+    ui := u[i];
+    if (ui <> 0) then
+    begin
+      q := q.TauPow(tauCount);
+      tauCount := 0;
+
+      if ui > 0 then
+      begin
+        x := pu[TBits.Asr32(ui, 1)];
+      end
+      else
+      begin
+        x := puNeg[TBits.Asr32(-ui, 1)];
+      end;
+
+      q := q.add(x) as IAbstractF2mPoint;
+    end;
+    System.Dec(i);
+  end;
+  if (tauCount > 0) then
+  begin
+    q := q.TauPow(tauCount);
+  end;
+  result := q;
+
+  pre.preComp := Nil; // Review
+
+end;
+
+function TWTauNafMultiplier.MultiplyWTnaf(const p: IAbstractF2mPoint;
+  const lambda: IZTauElement; a, mu: ShortInt): IAbstractF2mPoint;
+var
+  alpha: TCryptoLibGenericArray<IZTauElement>;
+  tw: TBigInteger;
+  u: TCryptoLibShortIntArray;
+begin
+  if a = 0 then
+  begin
+    alpha := TTnaf.Alpha0;
+  end
+  else
+  begin
+    alpha := TTnaf.Alpha1;
+  end;
+
+  tw := TTnaf.GetTw(mu, TTnaf.width);
+
+  u := TTnaf.TauAdicWNaf(mu, lambda, TTnaf.width,
+    TBigInteger.ValueOf(TTnaf.Pow2Width), tw, alpha);
+
+  result := MultiplyFromWTnaf(p, u);
+end;
+
+function TWTauNafMultiplier.MultiplyPositive(const point: IECPoint;
+  const k: TBigInteger): IECPoint;
+var
+  p: IAbstractF2mPoint;
+  curve: IAbstractF2mCurve;
+  m: Int32;
+  a, mu: ShortInt;
+  s: TCryptoLibGenericArray<TBigInteger>;
+  rho: IZTauElement;
+begin
+  if (not(Supports(point, IAbstractF2mPoint))) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SInCompatiblePoint);
+  end;
+
+  p := point as IAbstractF2mPoint;
+  curve := p.curve as IAbstractF2mCurve;
+  m := curve.FieldSize;
+  a := ShortInt(curve.a.ToBigInteger().Int32Value);
+  mu := TTnaf.GetMu(a);
+  s := curve.GetSi();
+
+  rho := TTnaf.PartModReduction(k, m, a, s, mu, ShortInt(10));
+
+  result := MultiplyWTnaf(p, rho, a, mu);
+
+end;
+
+{ TWTauNafMultiplier.TWTauNafCallback }
+
+constructor TWTauNafMultiplier.TWTauNafCallback.Create
+  (const p: IAbstractF2mPoint; a: ShortInt);
+begin
+  Inherited Create();
+  Fm_p := p;
+  Fm_a := a;
+end;
+
+function TWTauNafMultiplier.TWTauNafCallback.Precompute(const existing
+  : IPreCompInfo): IPreCompInfo;
+var
+  tempResult: IWTauNafPreCompInfo;
+begin
+
+  // Review uncomment
+  // if (Supports(existing, IWTauNafPreCompInfo)) then
+  // begin
+  // result := existing;
+  // Exit;
+  // end;
+
+  tempResult := TWTauNafPreCompInfo.Create();
+  tempResult.preComp := TTnaf.GetPreComp(Fm_p, Fm_a);
+  result := tempResult;
+end;
+
+end.

+ 259 - 78
src/libraries/cryptolib4pascal/ClpNat.pas

@@ -80,6 +80,14 @@ type
       xOff: Int32; const z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
       xOff: Int32; const z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
       overload; static;
       overload; static;
 
 
+    class function AddTo(len: Int32; const x: TCryptoLibUInt32Array;
+      xOff: Int32; const z: TCryptoLibUInt32Array; zOff, cIn: Int32): UInt32;
+      overload; static;
+
+    class function AddToEachOther(len: Int32; const u: TCryptoLibUInt32Array;
+      uOff: Int32; const v: TCryptoLibUInt32Array; vOff: Int32): UInt32;
+      overload; static;
+
     class function AddWordAt(len: Int32; x: UInt32;
     class function AddWordAt(len: Int32; x: UInt32;
       const z: TCryptoLibUInt32Array; zPos: Int32): UInt32; overload; static;
       const z: TCryptoLibUInt32Array; zPos: Int32): UInt32; overload; static;
 
 
@@ -100,10 +108,6 @@ type
       xOff: Int32; const z: TCryptoLibUInt32Array; zOff: Int32);
       xOff: Int32; const z: TCryptoLibUInt32Array; zOff: Int32);
       overload; static;
       overload; static;
 
 
-    class procedure CMov(len, mask: Int32; const x: TCryptoLibInt32Array;
-      xOff: Int32; const z: TCryptoLibInt32Array; zOff: Int32);
-      overload; static;
-
     class procedure Copy(len: Int32; const x, z: TCryptoLibUInt32Array);
     class procedure Copy(len: Int32; const x, z: TCryptoLibUInt32Array);
       overload; static; inline;
       overload; static; inline;
 
 
@@ -114,10 +118,27 @@ type
       xOff: Int32; const z: TCryptoLibUInt32Array; zOff: Int32); overload;
       xOff: Int32; const z: TCryptoLibUInt32Array; zOff: Int32); overload;
       static; inline;
       static; inline;
 
 
+    class procedure Copy64(len: Int32; const x, z: TCryptoLibUInt64Array);
+      overload; static; inline;
+
+    class function Copy64(len: Int32; const x: TCryptoLibUInt64Array)
+      : TCryptoLibUInt64Array; overload; static; inline;
+
+    class procedure Copy64(len: Int32; const x: TCryptoLibUInt64Array;
+      xOff: Int32; const z: TCryptoLibUInt64Array; zOff: Int32); overload;
+      static; inline;
+
     class function Create(len: Int32): TCryptoLibUInt32Array; static; inline;
     class function Create(len: Int32): TCryptoLibUInt32Array; static; inline;
 
 
     class function Create64(len: Int32): TCryptoLibUInt64Array; static; inline;
     class function Create64(len: Int32): TCryptoLibUInt64Array; static; inline;
 
 
+    class function CSub(len, mask: Int32; const x, y, z: TCryptoLibUInt32Array)
+      : UInt32; overload; static;
+
+    class function CSub(len, mask: Int32; const x: TCryptoLibUInt32Array;
+      xOff: Int32; const y: TCryptoLibUInt32Array; yOff: Int32;
+      const z: TCryptoLibUInt32Array; zOff: Int32): UInt32; overload; static;
+
     class function Dec(len: Int32; const z: TCryptoLibUInt32Array): Int32;
     class function Dec(len: Int32; const z: TCryptoLibUInt32Array): Int32;
       overload; static;
       overload; static;
 
 
@@ -130,17 +151,27 @@ type
     class function DecAt(len: Int32; const z: TCryptoLibUInt32Array;
     class function DecAt(len: Int32; const z: TCryptoLibUInt32Array;
       zOff, zPos: Int32): Int32; overload; static;
       zOff, zPos: Int32): Int32; overload; static;
 
 
+    class function Diff(len: Int32; const x: TCryptoLibUInt32Array; xOff: Int32;
+      const y: TCryptoLibUInt32Array; yOff: Int32;
+      const z: TCryptoLibUInt32Array; zOff: Int32): Boolean; static;
+
     class function Eq(len: Int32; const x, y: TCryptoLibUInt32Array)
     class function Eq(len: Int32; const x, y: TCryptoLibUInt32Array)
       : Boolean; static;
       : Boolean; static;
 
 
     class function FromBigInteger(bits: Int32; const x: TBigInteger)
     class function FromBigInteger(bits: Int32; const x: TBigInteger)
       : TCryptoLibUInt32Array; static;
       : TCryptoLibUInt32Array; static;
 
 
+    class function FromBigInteger64(bits: Int32; const x: TBigInteger)
+      : TCryptoLibUInt64Array; static;
+
     class function GetBit(const x: TCryptoLibUInt32Array; bit: Int32)
     class function GetBit(const x: TCryptoLibUInt32Array; bit: Int32)
       : UInt32; static;
       : UInt32; static;
 
 
-    class function Gte(len: Int32; const x, y: TCryptoLibUInt32Array)
-      : Boolean; static;
+    class function Gte(len: Int32; const x, y: TCryptoLibUInt32Array): Boolean;
+      overload; static;
+
+    class function Gte(len: Int32; const x: TCryptoLibUInt32Array; xOff: Int32;
+      const y: TCryptoLibUInt32Array; yOff: Int32): Boolean; overload; static;
 
 
     class function Inc(len: Int32; const z: TCryptoLibUInt32Array): UInt32;
     class function Inc(len: Int32; const z: TCryptoLibUInt32Array): UInt32;
       overload; static;
       overload; static;
@@ -270,10 +301,10 @@ type
       xOff: Int32; const zz: TCryptoLibUInt32Array; zzOff: Int32);
       xOff: Int32; const zz: TCryptoLibUInt32Array; zzOff: Int32);
       overload; static;
       overload; static;
 
 
-    class function SquareWordAdd(const x: TCryptoLibUInt32Array; xPos: Int32;
+    class function SquareWordAddTo(const x: TCryptoLibUInt32Array; xPos: Int32;
       const z: TCryptoLibUInt32Array): UInt32; overload; static;
       const z: TCryptoLibUInt32Array): UInt32; overload; static;
 
 
-    class function SquareWordAdd(const x: TCryptoLibUInt32Array;
+    class function SquareWordAddTo(const x: TCryptoLibUInt32Array;
       xOff, xPos: Int32; const z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
       xOff, xPos: Int32; const z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
       overload; static;
       overload; static;
 
 
@@ -340,9 +371,12 @@ type
     class function ToBigInteger(len: Int32; const x: TCryptoLibUInt32Array)
     class function ToBigInteger(len: Int32; const x: TCryptoLibUInt32Array)
       : TBigInteger; static;
       : TBigInteger; static;
 
 
-    class procedure Zero(len: Int32; const z: TCryptoLibUInt32Array);
+    class procedure Zero(len: Int32; const z: TCryptoLibUInt32Array); overload;
       static; inline;
       static; inline;
 
 
+    class procedure Zero(len: Int32; const z: TCryptoLibUInt32Array;
+      zOff: Int32); overload; static; inline;
+
   end;
   end;
 
 
 implementation
 implementation
@@ -401,11 +435,9 @@ begin
   I := 0;
   I := 0;
 
 
   repeat
   repeat
-
     c := c + (xVal * y[yOff + I] + z[zOff + I]);
     c := c + (xVal * y[yOff + I] + z[zOff + I]);
     z[zOff + I] := UInt32(c);
     z[zOff + I] := UInt32(c);
     c := c shr 32;
     c := c shr 32;
-
     System.Inc(I);
     System.Inc(I);
   until (not(I < len));
   until (not(I < len));
 
 
@@ -452,11 +484,9 @@ begin
   I := 0;
   I := 0;
 
 
   repeat
   repeat
-
     c := c + (xVal * y[I]);
     c := c + (xVal * y[I]);
     z[I] := UInt32(c);
     z[I] := UInt32(c);
     c := c shr 32;
     c := c shr 32;
-
     System.Inc(I);
     System.Inc(I);
   until (not(I < len));
   until (not(I < len));
 
 
@@ -475,25 +505,23 @@ begin
   I := 0;
   I := 0;
 
 
   repeat
   repeat
-
     c := c + (xVal * y[yOff + I]);
     c := c + (xVal * y[yOff + I]);
     z[zOff + I] := UInt32(c);
     z[zOff + I] := UInt32(c);
     c := c shr 32;
     c := c shr 32;
-
     System.Inc(I);
     System.Inc(I);
   until (not(I < len));
   until (not(I < len));
 
 
   Result := UInt32(c);
   Result := UInt32(c);
 end;
 end;
 
 
-class function TNat.SquareWordAdd(const x: TCryptoLibUInt32Array;
+class function TNat.SquareWordAddTo(const x: TCryptoLibUInt32Array;
   xOff, xPos: Int32; const z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
   xOff, xPos: Int32; const z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
 var
 var
   c, xVal: UInt64;
   c, xVal: UInt64;
   I: Int32;
   I: Int32;
 begin
 begin
   c := 0;
   c := 0;
-  xVal := UInt64(x[xOff + xPos]);
+  xVal := x[xOff + xPos] and M;
   I := 0;
   I := 0;
 
 
   repeat
   repeat
@@ -507,18 +535,18 @@ begin
   Result := UInt32(c);
   Result := UInt32(c);
 end;
 end;
 
 
-class function TNat.SquareWordAdd(const x: TCryptoLibUInt32Array; xPos: Int32;
+class function TNat.SquareWordAddTo(const x: TCryptoLibUInt32Array; xPos: Int32;
   const z: TCryptoLibUInt32Array): UInt32;
   const z: TCryptoLibUInt32Array): UInt32;
 var
 var
   c, xVal: UInt64;
   c, xVal: UInt64;
   I: Int32;
   I: Int32;
 begin
 begin
   c := 0;
   c := 0;
-  xVal := UInt64(x[xPos]);
+  xVal := x[xPos] and M;
   I := 0;
   I := 0;
 
 
   repeat
   repeat
-    c := c + (xVal * x[I] + z[xPos + I]);
+    c := c + (xVal * (x[I] and M) + (z[xPos + I] and M));
     z[xPos + I] := UInt32(c);
     z[xPos + I] := UInt32(c);
     c := c shr 32;
     c := c shr 32;
     System.Inc(I);
     System.Inc(I);
@@ -805,6 +833,39 @@ begin
   Result := UInt32(c);
   Result := UInt32(c);
 end;
 end;
 
 
+class function TNat.AddTo(len: Int32; const x: TCryptoLibUInt32Array;
+  xOff: Int32; const z: TCryptoLibUInt32Array; zOff, cIn: Int32): UInt32;
+var
+  c: UInt64;
+  I: Int32;
+begin
+  c := cIn and M;
+  for I := 0 to System.Pred(len) do
+  begin
+    c := c + ((x[xOff + I] and M) + (z[zOff + I] and M));
+    z[zOff + I] := UInt32(c);
+    c := c shr 32;
+  end;
+  Result := UInt32(c);
+end;
+
+class function TNat.AddToEachOther(len: Int32; const u: TCryptoLibUInt32Array;
+  uOff: Int32; const v: TCryptoLibUInt32Array; vOff: Int32): UInt32;
+var
+  c: UInt64;
+  I: Int32;
+begin
+  c := 0;
+  for I := 0 to System.Pred(len) do
+  begin
+    c := c + ((u[uOff + I] and M) + (v[vOff + I] and M));
+    u[uOff + I] := UInt32(c);
+    v[vOff + I] := UInt32(c);
+    c := c shr 32;
+  end;
+  Result := UInt32(c);
+end;
+
 class function TNat.AddWordAt(len: Int32; x: UInt32;
 class function TNat.AddWordAt(len: Int32; x: UInt32;
   const z: TCryptoLibUInt32Array; zPos: Int32): UInt32;
   const z: TCryptoLibUInt32Array; zPos: Int32): UInt32;
 var
 var
@@ -913,7 +974,7 @@ end;
 class procedure TNat.CMov(len, mask: Int32; const x: TCryptoLibUInt32Array;
 class procedure TNat.CMov(len, mask: Int32; const x: TCryptoLibUInt32Array;
   xOff: Int32; const z: TCryptoLibUInt32Array; zOff: Int32);
   xOff: Int32; const z: TCryptoLibUInt32Array; zOff: Int32);
 var
 var
-  LMASK, z_i, diff: UInt32;
+  LMASK, z_i, LDiff: UInt32;
   I: Int32;
   I: Int32;
 begin
 begin
   LMASK := UInt32(-(mask and 1));
   LMASK := UInt32(-(mask and 1));
@@ -921,24 +982,8 @@ begin
   for I := 0 to System.Pred(len) do
   for I := 0 to System.Pred(len) do
   begin
   begin
     z_i := z[zOff + I];
     z_i := z[zOff + I];
-    diff := z_i xor x[xOff + I];
-    z_i := z_i xor ((diff and LMASK));
-    z[zOff + I] := z_i;
-  end;
-end;
-
-class procedure TNat.CMov(len, mask: Int32; const x: TCryptoLibInt32Array;
-  xOff: Int32; const z: TCryptoLibInt32Array; zOff: Int32);
-var
-  z_i, diff, I: Int32;
-begin
-  mask := -(mask and 1);
-
-  for I := 0 to System.Pred(len) do
-  begin
-    z_i := z[zOff + I];
-    diff := z_i xor x[xOff + I];
-    z_i := z_i xor ((diff and mask));
+    LDiff := z_i xor x[xOff + I];
+    z_i := z_i xor ((LDiff and LMASK));
     z[zOff + I] := z_i;
     z[zOff + I] := z_i;
   end;
   end;
 end;
 end;
@@ -955,6 +1000,24 @@ begin
   System.Move(x[0], z[0], len * System.SizeOf(UInt32));
   System.Move(x[0], z[0], len * System.SizeOf(UInt32));
 end;
 end;
 
 
+class procedure TNat.Copy64(len: Int32; const x: TCryptoLibUInt64Array;
+  xOff: Int32; const z: TCryptoLibUInt64Array; zOff: Int32);
+begin
+  System.Move(x[xOff], z[zOff], len * System.SizeOf(UInt64));
+end;
+
+class function TNat.Copy64(len: Int32; const x: TCryptoLibUInt64Array)
+  : TCryptoLibUInt64Array;
+begin
+  System.SetLength(Result, len);
+  System.Move(x[0], Result[0], len * System.SizeOf(UInt64));
+end;
+
+class procedure TNat.Copy64(len: Int32; const x, z: TCryptoLibUInt64Array);
+begin
+  System.Move(x[0], z[0], len * System.SizeOf(UInt64));
+end;
+
 class procedure TNat.Copy(len: Int32; const x: TCryptoLibUInt32Array;
 class procedure TNat.Copy(len: Int32; const x: TCryptoLibUInt32Array;
   xOff: Int32; const z: TCryptoLibUInt32Array; zOff: Int32);
   xOff: Int32; const z: TCryptoLibUInt32Array; zOff: Int32);
 begin
 begin
@@ -971,6 +1034,41 @@ begin
   System.SetLength(Result, len);
   System.SetLength(Result, len);
 end;
 end;
 
 
+class function TNat.CSub(len, mask: Int32;
+  const x, y, z: TCryptoLibUInt32Array): UInt32;
+var
+  LMASK, c: UInt64;
+  I: Int32;
+begin
+  LMASK := UInt64(-(mask and 1) and M);
+  c := 0;
+  for I := 0 to System.Pred(len) do
+  begin
+    c := c + ((x[I] and M) - (y[I] and LMASK));
+    z[I] := UInt32(c);
+    c := c shr 32;
+  end;
+  Result := UInt32(c);
+end;
+
+class function TNat.CSub(len, mask: Int32; const x: TCryptoLibUInt32Array;
+  xOff: Int32; const y: TCryptoLibUInt32Array; yOff: Int32;
+  const z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
+var
+  LMASK, c: UInt64;
+  I: Int32;
+begin
+  LMASK := UInt64(-(mask and 1) and M);
+  c := 0;
+  for I := 0 to System.Pred(len) do
+  begin
+    c := c + ((x[xOff + I] and M) - (y[yOff + I] and LMASK));
+    z[zOff + I] := UInt32(c);
+    c := c shr 32;
+  end;
+  Result := UInt32(c);
+end;
+
 class function TNat.Dec(len: Int32; const z: TCryptoLibUInt32Array): Int32;
 class function TNat.Dec(len: Int32; const z: TCryptoLibUInt32Array): Int32;
 var
 var
   I: Int32;
   I: Int32;
@@ -1053,6 +1151,25 @@ begin
   Result := -1;
   Result := -1;
 end;
 end;
 
 
+class function TNat.Diff(len: Int32; const x: TCryptoLibUInt32Array;
+  xOff: Int32; const y: TCryptoLibUInt32Array; yOff: Int32;
+  const z: TCryptoLibUInt32Array; zOff: Int32): Boolean;
+var
+  pos: Boolean;
+begin
+  pos := Gte(len, x, xOff, y, yOff);
+
+  if (pos) then
+  begin
+    Sub(len, x, xOff, y, yOff, z, zOff);
+  end
+  else
+  begin
+    Sub(len, y, yOff, x, xOff, z, zOff);
+  end;
+  Result := pos;
+end;
+
 class function TNat.Eq(len: Int32; const x, y: TCryptoLibUInt32Array): Boolean;
 class function TNat.Eq(len: Int32; const x, y: TCryptoLibUInt32Array): Boolean;
 var
 var
   I: Int32;
   I: Int32;
@@ -1083,7 +1200,6 @@ begin
     raise EArgumentCryptoLibException.Create('');
     raise EArgumentCryptoLibException.Create('');
   end;
   end;
 
 
-  // len := (bits + 31) shr 5;
   len := TBits.Asr32((bits + 31), 5);
   len := TBits.Asr32((bits + 31), 5);
   Result := Create(len);
   Result := Create(len);
   I := 0;
   I := 0;
@@ -1095,6 +1211,31 @@ begin
   end;
   end;
 end;
 end;
 
 
+class function TNat.FromBigInteger64(bits: Int32; const x: TBigInteger)
+  : TCryptoLibUInt64Array;
+var
+  len, I: Int32;
+  z: TCryptoLibUInt64Array;
+  Lx: TBigInteger;
+begin
+  Lx := x;
+  if ((Lx.SignValue < 0) or (Lx.BitLength > bits)) then
+  begin
+    raise EArgumentCryptoLibException.Create('');
+  end;
+
+  len := (bits + 63) shr 6;
+  z := Create64(len);
+  I := 0;
+  while (Lx.SignValue <> 0) do
+  begin
+    z[I] := Lx.Int64Value;
+    System.Inc(I);
+    Lx := Lx.ShiftRight(64);
+  end;
+  Result := z;
+end;
+
 class function TNat.GetBit(const x: TCryptoLibUInt32Array; bit: Int32): UInt32;
 class function TNat.GetBit(const x: TCryptoLibUInt32Array; bit: Int32): UInt32;
 var
 var
   w, b: Int32;
   w, b: Int32;
@@ -1104,7 +1245,7 @@ begin
     Result := x[0] and 1;
     Result := x[0] and 1;
     Exit;
     Exit;
   end;
   end;
-  // w := bit shr 5;
+
   w := TBits.Asr32(bit, 5);
   w := TBits.Asr32(bit, 5);
   if ((w < 0) or (w >= System.Length(x))) then
   if ((w < 0) or (w >= System.Length(x))) then
   begin
   begin
@@ -1140,6 +1281,32 @@ begin
   Result := true;
   Result := true;
 end;
 end;
 
 
+class function TNat.Gte(len: Int32; const x: TCryptoLibUInt32Array; xOff: Int32;
+  const y: TCryptoLibUInt32Array; yOff: Int32): Boolean;
+var
+  I: Int32;
+  x_i, y_i: UInt32;
+begin
+  I := len - 1;
+  while I >= 0 do
+  begin
+    x_i := x[xOff + I];
+    y_i := y[yOff + I];
+    if (x_i < y_i) then
+    begin
+      Result := false;
+      Exit;
+    end;
+    if (x_i > y_i) then
+    begin
+      Result := true;
+      Exit;
+    end;
+    System.Dec(I);
+  end;
+  Result := true;
+end;
+
 class function TNat.Inc(len: Int32; const z: TCryptoLibUInt32Array): UInt32;
 class function TNat.Inc(len: Int32; const z: TCryptoLibUInt32Array): UInt32;
 var
 var
   I: Int32;
   I: Int32;
@@ -1173,7 +1340,6 @@ begin
       begin
       begin
         z[I] := x[I];
         z[I] := x[I];
         System.Inc(I);
         System.Inc(I);
-
       end;
       end;
       Result := 0;
       Result := 0;
       Exit;
       Exit;
@@ -1229,7 +1395,6 @@ begin
   zz[len] := MulWord(len, x[0], y, zz);
   zz[len] := MulWord(len, x[0], y, zz);
 
 
   for I := 1 to System.Pred(len) do
   for I := 1 to System.Pred(len) do
-
   begin
   begin
     zz[I + len] := MulWordAddTo(len, x[I], y, 0, zz, I);
     zz[I + len] := MulWordAddTo(len, x[I], y, 0, zz, I);
   end;
   end;
@@ -1268,16 +1433,16 @@ end;
 class function TNat.MulAddTo(len: Int32;
 class function TNat.MulAddTo(len: Int32;
   const x, y, zz: TCryptoLibUInt32Array): UInt32;
   const x, y, zz: TCryptoLibUInt32Array): UInt32;
 var
 var
-  zc, c: UInt64;
+  zc: UInt64;
   I: Int32;
   I: Int32;
 begin
 begin
   zc := 0;
   zc := 0;
   for I := 0 to System.Pred(len) do
   for I := 0 to System.Pred(len) do
   begin
   begin
-    c := MulWordAddTo(len, x[I], y, 0, zz, I) and M;
-    c := c + (zc + (zz[I + len] and M));
-    zz[I + len] := UInt32(c);
-    zc := c shr 32;
+    zc := zc + (MulWordAddTo(len, x[I], y, 0, zz, I) and M);
+    zc := zc + (zz[I + len] and M);
+    zz[I + len] := UInt32(zc);
+    zc := zc shr 32;
   end;
   end;
   Result := UInt32(zc);
   Result := UInt32(zc);
 end;
 end;
@@ -1286,16 +1451,16 @@ class function TNat.MulAddTo(len: Int32; const x: TCryptoLibUInt32Array;
   xOff: Int32; const y: TCryptoLibUInt32Array; yOff: Int32;
   xOff: Int32; const y: TCryptoLibUInt32Array; yOff: Int32;
   const zz: TCryptoLibUInt32Array; zzOff: Int32): UInt32;
   const zz: TCryptoLibUInt32Array; zzOff: Int32): UInt32;
 var
 var
-  zc, c: UInt64;
+  zc: UInt64;
   I: Int32;
   I: Int32;
 begin
 begin
   zc := 0;
   zc := 0;
   for I := 0 to System.Pred(len) do
   for I := 0 to System.Pred(len) do
   begin
   begin
-    c := MulWordAddTo(len, x[xOff + I], y, yOff, zz, zzOff) and M;
-    c := c + (zc + (zz[zzOff + len] and M));
-    zz[zzOff + len] := UInt32(c);
-    zc := c shr 32;
+    zc := zc + (MulWordAddTo(len, x[xOff + I], y, yOff, zz, zzOff) and M);
+    zc := zc + (zz[zzOff + len] and M);
+    zz[zzOff + len] := UInt32(zc);
+    zc := zc shr 32;
     System.Inc(zzOff);
     System.Inc(zzOff);
   end;
   end;
   Result := UInt32(zc);
   Result := UInt32(zc);
@@ -1314,11 +1479,9 @@ begin
   I := 0;
   I := 0;
 
 
   repeat
   repeat
-
     c := c + (aVal * x[I] + bVal * y[I] + z[zOff + I]);
     c := c + (aVal * x[I] + bVal * y[I] + z[zOff + I]);
     z[zOff + I] := UInt32(c);
     z[zOff + I] := UInt32(c);
     c := c shr 32;
     c := c shr 32;
-
     System.Inc(I);
     System.Inc(I);
   until (not(I < len));
   until (not(I < len));
 
 
@@ -1506,7 +1669,6 @@ var
   next: UInt32;
   next: UInt32;
 begin
 begin
   for I := 0 to System.Pred(len) do
   for I := 0 to System.Pred(len) do
-
   begin
   begin
     next := x[I];
     next := x[I];
     z[I] := (next shl 1) or (c shr 31);
     z[I] := (next shl 1) or (c shr 31);
@@ -1522,7 +1684,6 @@ var
   next: UInt32;
   next: UInt32;
 begin
 begin
   for I := 0 to System.Pred(len) do
   for I := 0 to System.Pred(len) do
-
   begin
   begin
     next := x[xOff + I];
     next := x[xOff + I];
     z[zOff + I] := (next shl 1) or (c shr 31);
     z[zOff + I] := (next shl 1) or (c shr 31);
@@ -1538,7 +1699,6 @@ var
   next: UInt32;
   next: UInt32;
 begin
 begin
   for I := 0 to System.Pred(len) do
   for I := 0 to System.Pred(len) do
-
   begin
   begin
     next := z[I];
     next := z[I];
     z[I] := (next shl 1) or (c shr 31);
     z[I] := (next shl 1) or (c shr 31);
@@ -1554,7 +1714,6 @@ var
   next: UInt32;
   next: UInt32;
 begin
 begin
   for I := 0 to System.Pred(len) do
   for I := 0 to System.Pred(len) do
-
   begin
   begin
     next := z[zOff + I];
     next := z[zOff + I];
     z[zOff + I] := (next shl 1) or (c shr 31);
     z[zOff + I] := (next shl 1) or (c shr 31);
@@ -1570,7 +1729,6 @@ var
   next: UInt64;
   next: UInt64;
 begin
 begin
   for I := 0 to System.Pred(len) do
   for I := 0 to System.Pred(len) do
-
   begin
   begin
     next := x[xOff + I];
     next := x[xOff + I];
     z[zOff + I] := (next shl 1) or (c shr 63);
     z[zOff + I] := (next shl 1) or (c shr 63);
@@ -1691,9 +1849,9 @@ end;
 
 
 class procedure TNat.Square(len: Int32; const x, zz: TCryptoLibUInt32Array);
 class procedure TNat.Square(len: Int32; const x, zz: TCryptoLibUInt32Array);
 var
 var
-  extLen, j, k, I: Int32;
+  extLen, j, k, I, zzPos: Int32;
   c: UInt32;
   c: UInt32;
-  xVal, p: UInt64;
+  xVal, p, d: UInt64;
 begin
 begin
   extLen := len shl 1;
   extLen := len shl 1;
   c := 0;
   c := 0;
@@ -1711,21 +1869,33 @@ begin
     c := UInt32(p);
     c := UInt32(p);
   until (not(j > 0));
   until (not(j > 0));
 
 
+  d := 0;
+  zzPos := 2;
+
   for I := 1 to System.Pred(len) do
   for I := 1 to System.Pred(len) do
   begin
   begin
-    c := SquareWordAdd(x, I, zz);
-    AddWordAt(extLen, c, zz, I shl 1);
+    d := d + (SquareWordAddTo(x, I, zz) and M);
+    d := d + (zz[zzPos] and M);
+    zz[zzPos] := UInt32(d);
+    System.Inc(zzPos);
+    d := d shr 32;
+    d := d + (zz[zzPos] and M);
+    zz[zzPos] := UInt32(d);
+    System.Inc(zzPos);
+    d := d shr 32;
   end;
   end;
-
+{$IFDEF DEBUG}
+  System.Assert(d = 0);
+{$ENDIF DEBUG}
   ShiftUpBit(extLen, zz, x[0] shl 31);
   ShiftUpBit(extLen, zz, x[0] shl 31);
 end;
 end;
 
 
 class procedure TNat.Square(len: Int32; const x: TCryptoLibUInt32Array;
 class procedure TNat.Square(len: Int32; const x: TCryptoLibUInt32Array;
   xOff: Int32; const zz: TCryptoLibUInt32Array; zzOff: Int32);
   xOff: Int32; const zz: TCryptoLibUInt32Array; zzOff: Int32);
 var
 var
-  extLen, j, k, I: Int32;
+  extLen, j, k, I, zzPos: Int32;
   c: UInt32;
   c: UInt32;
-  xVal, p: UInt64;
+  xVal, p, d: UInt64;
 begin
 begin
   extLen := len shl 1;
   extLen := len shl 1;
   c := 0;
   c := 0;
@@ -1734,7 +1904,7 @@ begin
 
 
   repeat
   repeat
     System.Dec(j);
     System.Dec(j);
-    xVal := UInt64(x[xOff + j]);
+    xVal := x[xOff + j] and M;
     p := xVal * xVal;
     p := xVal * xVal;
     System.Dec(k);
     System.Dec(k);
     zz[zzOff + k] := (c shl 31) or UInt32((p shr 33));
     zz[zzOff + k] := (c shl 31) or UInt32((p shr 33));
@@ -1743,12 +1913,24 @@ begin
     c := UInt32(p);
     c := UInt32(p);
   until (not(j > 0));
   until (not(j > 0));
 
 
+  d := 0;
+  zzPos := zzOff + 2;
+
   for I := 1 to System.Pred(len) do
   for I := 1 to System.Pred(len) do
   begin
   begin
-    c := SquareWordAdd(x, xOff, I, zz, zzOff);
-    AddWordAt(extLen, c, zz, zzOff, I shl 1);
+    d := d + (SquareWordAddTo(x, I, zz) and M);
+    d := d + (zz[zzPos] and M);
+    zz[zzPos] := UInt32(d);
+    System.Inc(zzPos);
+    d := d shr 32;
+    d := d + (zz[zzPos] and M);
+    zz[zzPos] := UInt32(d);
+    System.Inc(zzPos);
+    d := d shr 32;
   end;
   end;
-
+{$IFDEF DEBUG}
+  System.Assert(d = 0);
+{$ENDIF DEBUG}
   ShiftUpBit(extLen, zz, zzOff, x[xOff] shl 31);
   ShiftUpBit(extLen, zz, zzOff, x[xOff] shl 31);
 end;
 end;
 
 
@@ -1761,7 +1943,6 @@ var
 begin
 begin
   c := 0;
   c := 0;
   for I := 0 to System.Pred(len) do
   for I := 0 to System.Pred(len) do
-
   begin
   begin
     c := c + (Int64(x[xOff + I]) - y[yOff + I]);
     c := c + (Int64(x[xOff + I]) - y[yOff + I]);
     z[zOff + I] := UInt32(c);
     z[zOff + I] := UInt32(c);
@@ -1778,7 +1959,6 @@ var
 begin
 begin
   c := 0;
   c := 0;
   for I := 0 to System.Pred(len) do
   for I := 0 to System.Pred(len) do
-
   begin
   begin
     c := c + (Int64(x[I]) - y[I]);
     c := c + (Int64(x[I]) - y[I]);
     z[I] := UInt32(c);
     z[I] := UInt32(c);
@@ -1885,7 +2065,6 @@ var
 begin
 begin
   c := 0;
   c := 0;
   for I := 0 to System.Pred(len) do
   for I := 0 to System.Pred(len) do
-
   begin
   begin
     c := c + (Int64(z[I]) - x[I] - y[I]);
     c := c + (Int64(z[I]) - x[I] - y[I]);
     z[I] := UInt32(c);
     z[I] := UInt32(c);
@@ -1903,7 +2082,6 @@ var
 begin
 begin
   c := 0;
   c := 0;
   for I := 0 to System.Pred(len) do
   for I := 0 to System.Pred(len) do
-
   begin
   begin
     c := c + (Int64(z[zOff + I]) - x[xOff + I] - y[yOff + I]);
     c := c + (Int64(z[zOff + I]) - x[xOff + I] - y[yOff + I]);
     z[zOff + I] := UInt32(c);
     z[zOff + I] := UInt32(c);
@@ -2011,7 +2189,6 @@ var
 begin
 begin
   c := 0;
   c := 0;
   for I := 0 to System.Pred(len) do
   for I := 0 to System.Pred(len) do
-
   begin
   begin
     c := c + (Int64(z[I]) - x[I]);
     c := c + (Int64(z[I]) - x[I]);
     z[I] := UInt32(c);
     z[I] := UInt32(c);
@@ -2028,7 +2205,6 @@ var
 begin
 begin
   c := 0;
   c := 0;
   for I := 0 to System.Pred(len) do
   for I := 0 to System.Pred(len) do
-
   begin
   begin
     c := c + (Int64(z[zOff + I]) - x[xOff + I]);
     c := c + (Int64(z[zOff + I]) - x[xOff + I]);
     z[zOff + I] := UInt32(c);
     z[zOff + I] := UInt32(c);
@@ -2130,7 +2306,6 @@ var
 begin
 begin
   System.SetLength(bs, len shl 2);
   System.SetLength(bs, len shl 2);
   for I := 0 to System.Pred(len) do
   for I := 0 to System.Pred(len) do
-
   begin
   begin
     x_i := x[I];
     x_i := x[I];
     if (x_i <> 0) then
     if (x_i <> 0) then
@@ -2148,4 +2323,10 @@ begin
   TArrayUtils.Fill(z, 0, len, UInt32(0));
   TArrayUtils.Fill(z, 0, len, UInt32(0));
 end;
 end;
 
 
+class procedure TNat.Zero(len: Int32; const z: TCryptoLibUInt32Array;
+  zOff: Int32);
+begin
+  TArrayUtils.Fill(z, zOff, zOff + len, UInt32(0));
+end;
+
 end.
 end.

+ 6 - 6
src/libraries/cryptolib4pascal/ClpNat192.pas

@@ -760,9 +760,9 @@ begin
     c := c + (x_i * y_5 + zz[i + 5]);
     c := c + (x_i * y_5 + zz[i + 5]);
     zz[i + 5] := UInt32(c);
     zz[i + 5] := UInt32(c);
     c := c shr 32;
     c := c shr 32;
-    c := c + (zc + zz[i + 6]);
-    zz[i + 6] := UInt32(c);
-    zc := c shr 32;
+    zc := zc + (c + (zz[i + 6] and M));
+    zz[i + 6] := UInt32(zc);
+    zc := zc shr 32;
   end;
   end;
   result := UInt32(zc);
   result := UInt32(zc);
 end;
 end;
@@ -804,9 +804,9 @@ begin
     c := c + (x_i * y_5 + zz[zzOff + 5]);
     c := c + (x_i * y_5 + zz[zzOff + 5]);
     zz[zzOff + 5] := UInt32(c);
     zz[zzOff + 5] := UInt32(c);
     c := c shr 32;
     c := c shr 32;
-    c := c + (zc + zz[zzOff + 6]);
-    zz[zzOff + 6] := UInt32(c);
-    zc := c shr 32;
+    zc := zc + (c + (zz[zzOff + 6] and M));
+    zz[zzOff + 6] := UInt32(zc);
+    zc := zc shr 32;
     System.Inc(zzOff);
     System.Inc(zzOff);
   end;
   end;
   result := UInt32(zc);
   result := UInt32(zc);

+ 6 - 6
src/libraries/cryptolib4pascal/ClpNat256.pas

@@ -908,9 +908,9 @@ begin
     c := c + (x_i * y_7 + zz[i + 7]);
     c := c + (x_i * y_7 + zz[i + 7]);
     zz[i + 7] := UInt32(c);
     zz[i + 7] := UInt32(c);
     c := c shr 32;
     c := c shr 32;
-    c := c + (zc + zz[i + 8]);
-    zz[i + 8] := UInt32(c);
-    zc := c shr 32;
+    zc := zc + (c + (zz[i + 8] and M));
+    zz[i + 8] := UInt32(zc);
+    zc := zc shr 32;
   end;
   end;
   result := UInt32(zc);
   result := UInt32(zc);
 end;
 end;
@@ -960,9 +960,9 @@ begin
     c := c + (x_i * y_7 + zz[zzOff + 7]);
     c := c + (x_i * y_7 + zz[zzOff + 7]);
     zz[zzOff + 7] := UInt32(c);
     zz[zzOff + 7] := UInt32(c);
     c := c shr 32;
     c := c shr 32;
-    c := c + (zc + zz[zzOff + 8]);
-    zz[zzOff + 8] := UInt32(c);
-    zc := c shr 32;
+    zc := zc + (c + (zz[zzOff + 8] and M));
+    zz[zzOff + 8] := UInt32(zc);
+    zc := zc shr 32;
     System.Inc(zzOff);
     System.Inc(zzOff);
   end;
   end;
   result := UInt32(zc);
   result := UInt32(zc);

+ 329 - 113
src/libraries/cryptolib4pascal/ClpOSRandom.pas

@@ -28,36 +28,42 @@ uses
 {$IFDEF CRYPTOLIB_APPLE}
 {$IFDEF CRYPTOLIB_APPLE}
 {$IFDEF FPC}
 {$IFDEF FPC}
 {$LINKFRAMEWORK Security}
 {$LINKFRAMEWORK Security}
+{$IFDEF CRYPTOLIB_MACOS}
+  CocoaAll,
+{$ENDIF} // ENDIF CRYPTOLIB_MACOS
 {$ELSE}
 {$ELSE}
   // Macapi.Dispatch, or
   // Macapi.Dispatch, or
   Macapi.ObjCRuntime,
   Macapi.ObjCRuntime,
-{$IF DEFINED(CRYPTOLIB_IOS)}
+{$IFDEF CRYPTOLIB_IOS}
   iOSapi.Foundation,
   iOSapi.Foundation,
-{$ELSEIF DEFINED(CRYPTOLIB_MACOS)}
+{$ENDIF} // ENDIF CRYPTOLIB_IOS
+{$IFDEF CRYPTOLIB_MACOS}
+  Macapi.AppKit,
   Macapi.Foundation,
   Macapi.Foundation,
-{$ELSE}
-{$MESSAGE ERROR 'UNSUPPORTED TARGET.'}
-{$IFEND} // ENDIF CRYPTOLIB_MACOS
+{$ENDIF} // ENDIF CRYPTOLIB_MACOS
 {$ENDIF}  // ENDIF FPC
 {$ENDIF}  // ENDIF FPC
 {$ENDIF}   // ENDIF CRYPTOLIB_APPLE
 {$ENDIF}   // ENDIF CRYPTOLIB_APPLE
-{$IFDEF CRYPTOLIB_LINUX}
+{$IFDEF CRYPTOLIB_UNIX}
+  Classes,
 {$IFDEF FPC}
 {$IFDEF FPC}
   BaseUnix,
   BaseUnix,
+{$IFDEF CRYPTOLIB_HAS_GETRANDOM}
   dl,
   dl,
+{$ENDIF}
 {$ELSE}
 {$ELSE}
   Posix.Errno,
   Posix.Errno,
+{$IFDEF CRYPTOLIB_HAS_GETRANDOM}
   Posix.Dlfcn,
   Posix.Dlfcn,
 {$ENDIF}
 {$ENDIF}
-{$ENDIF}  // ENDIF CRYPTOLIB_LINUX
+{$ENDIF}
+{$ENDIF}  // ENDIF CRYPTOLIB_UNIX
 {$IFDEF CRYPTOLIB_PUREBSD}
 {$IFDEF CRYPTOLIB_PUREBSD}
   // PureBSD (NetBSD, FreeBSD, OpenBSD)
   // PureBSD (NetBSD, FreeBSD, OpenBSD)
 {$ENDIF}  // ENDIF CRYPTOLIB_PUREBSD
 {$ENDIF}  // ENDIF CRYPTOLIB_PUREBSD
-{$IFDEF CRYPTOLIB_UNIX}
-  Classes,
-{$ENDIF}  // ENDIF CRYPTOLIB_UNIX
 {$IF DEFINED(CRYPTOLIB_MSWINDOWS) OR DEFINED(CRYPTOLIB_UNIX)}
 {$IF DEFINED(CRYPTOLIB_MSWINDOWS) OR DEFINED(CRYPTOLIB_UNIX)}
   SysUtils,
   SysUtils,
 {$IFEND}  // ENDIF CRYPTOLIB_MSWINDOWS OR CRYPTOLIB_UNIX
 {$IFEND}  // ENDIF CRYPTOLIB_MSWINDOWS OR CRYPTOLIB_UNIX
+  ClpArrayUtils,
   ClpCryptoLibTypes;
   ClpCryptoLibTypes;
 
 
 resourcestring
 resourcestring
@@ -73,14 +79,18 @@ resourcestring
   SLinuxGetRandomError =
   SLinuxGetRandomError =
     'An Error Occured while generating random data using getRandom API';
     'An Error Occured while generating random data using getRandom API';
 {$ENDIF}
 {$ENDIF}
+{$IFDEF CRYPTOLIB_SOLARIS}
+  SSolarisGetRandomError =
+    'An Error Occured while generating random data using getRandom API';
+{$ENDIF}
 {$IFDEF CRYPTOLIB_GENERIC_BSD}
 {$IFDEF CRYPTOLIB_GENERIC_BSD}
   SArc4RandomBufGenerationError =
   SArc4RandomBufGenerationError =
     'An Error Occured while generating random data using arc4random_buf API.';
     'An Error Occured while generating random data using arc4random_buf API.';
 {$ENDIF}
 {$ENDIF}
-{$IFDEF CRYPTOLIB_UNIX}
-  SRandomDeviceReadError =
-    'An Error Occured while reading random data from random device (file)';
-{$ENDIF}
+  // {$IFDEF CRYPTOLIB_UNIX}
+  // SRandomDeviceReadError =
+  // 'An Error Occured while reading random data from random device (file)';
+  // {$ENDIF}
 
 
 type
 type
 
 
@@ -107,13 +117,27 @@ type
   /// available)</description>
   /// available)</description>
   /// </item>
   /// </item>
   /// <item>
   /// <item>
+  /// <term>Solaris</term>
+  /// <description><see href="https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html">
+  /// getrandom</see> system call if available, otherwise ( <see href="https://docs.oracle.com/cd/E86824_01/html/E54777/random-7d.html">
+  /// /dev/urandom or /dev/random</see>) (which ever is
+  /// available)</description>
+  /// </item>
+  /// <item>
   /// <term>Windows</term>
   /// <term>Windows</term>
-  /// <description><see href="https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/nf-wincrypt-cryptgenrandom">
-  /// CryptGenRandom</see> for <b>XP</b>, <see href="https://docs.microsoft.com/en-us/windows/desktop/api/bcrypt/nf-bcrypt-bcryptgenrandom">
-  /// BCryptGenRandom</see> for <b>Vista</b> Upwards</description>
+  /// <description>Checks availability in this order, <see href="https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom">
+  /// RtlGenRandom</see> =&gt; <see href="https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/nf-wincrypt-cryptgenrandom">
+  /// CryptGenRandom</see> =&gt; <see href="https://docs.microsoft.com/en-us/windows/desktop/api/bcrypt/nf-bcrypt-bcryptgenrandom">
+  /// BCryptGenRandom</see></description>
   /// </item>
   /// </item>
   /// <item>
   /// <item>
-  /// <term>macOS, iOS</term>
+  /// <term>Mac OS X</term>
+  /// <description><see href="https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc">
+  /// SecRandomCopyBytes</see> for <b>10.7+,</b> ( /dev/urandom
+  /// or /dev/random) (which ever is available) for &lt; <b>10.7</b><br /></description>
+  /// </item>
+  /// <item>
+  /// <term>iOS</term>
   /// <description><see href="https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc">
   /// <description><see href="https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc">
   /// SecRandomCopyBytes</see><br /></description>
   /// SecRandomCopyBytes</see><br /></description>
   /// </item>
   /// </item>
@@ -145,7 +169,28 @@ type
 
 
     // ================================================================//
     // ================================================================//
 
 
+{$IFDEF CRYPTOLIB_UNIX}
+  const
+    EINTR = {$IFDEF FPC}ESysEINTR {$ELSE}Posix.Errno.EINTR{$ENDIF};
+
+    class function ErrorNo: Int32; static; inline;
+
+{$IFDEF CRYPTOLIB_HAS_GETRANDOM}
+
+  const
+    GRND_DEFAULT: Int32 = $0000;
+
 {$IFDEF CRYPTOLIB_LINUX}
 {$IFDEF CRYPTOLIB_LINUX}
+{$IFDEF CRYPTOLIB_ANDROID}
+    LIBC_SO = 'libc.so';
+{$ELSE}
+    LIBC_SO = 'libc.so.6';
+{$ENDIF}
+{$ENDIF}
+{$IFDEF CRYPTOLIB_SOLARIS}
+    LIBC_SO = 'libc.so.1';
+{$ENDIF}
+
   type
   type
     TGetRandom = function(pbBuffer: PByte; buflen: LongWord; flags: UInt32)
     TGetRandom = function(pbBuffer: PByte; buflen: LongWord; flags: UInt32)
       : Int32; cdecl;
       : Int32; cdecl;
@@ -155,8 +200,6 @@ type
     FIsGetRandomSupportedOnOS: Boolean;
     FIsGetRandomSupportedOnOS: Boolean;
     FGetRandom: TGetRandom;
     FGetRandom: TGetRandom;
 
 
-    class function ErrorNo: Int32; static; inline;
-
     class function GetIsGetRandomSupportedOnOS(): Boolean; static; inline;
     class function GetIsGetRandomSupportedOnOS(): Boolean; static; inline;
 
 
     class function IsGetRandomAvailable(): Boolean; static;
     class function IsGetRandomAvailable(): Boolean; static;
@@ -164,11 +207,16 @@ type
     class property IsGetRandomSupportedOnOS: Boolean
     class property IsGetRandomSupportedOnOS: Boolean
       read GetIsGetRandomSupportedOnOS;
       read GetIsGetRandomSupportedOnOS;
 
 
+{$ENDIF}
 {$ENDIF}
 {$ENDIF}
     // ================================================================//
     // ================================================================//
 
 
 {$IFDEF CRYPTOLIB_MSWINDOWS}
 {$IFDEF CRYPTOLIB_MSWINDOWS}
 
 
+  const
+    BCRYPT = 'bcrypt.dll';
+    ADVAPI32 = 'advapi32.dll';
+
   type
   type
     BCRYPT_ALG_HANDLE = THandle;
     BCRYPT_ALG_HANDLE = THandle;
     NTStatus = HRESULT;
     NTStatus = HRESULT;
@@ -193,10 +241,56 @@ type
       static; inline;
       static; inline;
 
 
     class function IsCngBCryptGenRandomAvailable(): Boolean; static;
     class function IsCngBCryptGenRandomAvailable(): Boolean; static;
-    class function GenRandomBytesWindows(len: Int32; data: PByte)
-      : Int32; static;
+
     class property IsCngBCryptGenRandomSupportedOnOS: Boolean
     class property IsCngBCryptGenRandomSupportedOnOS: Boolean
       read GetIsCngBCryptGenRandomSupportedOnOS;
       read GetIsCngBCryptGenRandomSupportedOnOS;
+
+  type
+
+    TCryptGenRandom = function(hProv: THandle; dwLen: DWORD; pbBuffer: PByte)
+      : BOOL; stdcall;
+
+    TCryptAcquireContextW = function(phProv: Pointer; pszContainer: LPCWSTR;
+      pszProvider: LPCWSTR; dwProvType: DWORD; dwFlags: DWORD): BOOL; stdcall;
+
+    TCryptReleaseContext = function(hProv: THandle; dwFlags: DWORD)
+      : BOOL; stdcall;
+
+  class var
+
+    FIsCryptGenRandomSupportedOnOS: Boolean;
+    FCryptGenRandom: TCryptGenRandom;
+    FCryptAcquireContextW: TCryptAcquireContextW;
+    FCryptReleaseContext: TCryptReleaseContext;
+
+    class function GetIsCryptGenRandomSupportedOnOS(): Boolean; static; inline;
+
+    class function IsCryptGenRandomAvailable(): Boolean; static;
+
+    class property IsCryptGenRandomSupportedOnOS: Boolean
+      read GetIsCryptGenRandomSupportedOnOS;
+
+  type
+    TRtlGenRandom = function(RandomBuffer: PVOID; RandomBufferLength: ULONG)
+      : Boolean; stdcall;
+
+  class var
+    FIsRtlGenRandomSupportedOnOS: Boolean;
+    FRtlGenRandom: TRtlGenRandom;
+
+    class function GetIsRtlGenRandomSupportedOnOS(): Boolean; static; inline;
+
+    class function IsRtlGenRandomAvailable(): Boolean; static;
+
+    class property IsRtlGenRandomSupportedOnOS: Boolean
+      read GetIsRtlGenRandomSupportedOnOS;
+
+    class function GetProcedureAddress(ModuleHandle: THandle;
+      const AProcedureName: String; var AFunctionFound: Boolean)
+      : Pointer; static;
+
+    class function GenRandomBytesWindows(len: Int32; data: PByte)
+      : Int32; static;
 {$ENDIF}
 {$ENDIF}
 
 
     // ================================================================//
     // ================================================================//
@@ -208,6 +302,11 @@ type
     class function GenRandomBytesLinux(len: Int32; data: PByte): Int32; static;
     class function GenRandomBytesLinux(len: Int32; data: PByte): Int32; static;
 {$ENDIF}
 {$ENDIF}
     // ================================================================//
     // ================================================================//
+{$IFDEF CRYPTOLIB_SOLARIS}
+    class function GenRandomBytesSolaris(len: Int32; data: PByte)
+      : Int32; static;
+{$ENDIF}
+    // ================================================================//
 {$IFDEF CRYPTOLIB_GENERIC_BSD}
 {$IFDEF CRYPTOLIB_GENERIC_BSD}
     class function GenRandomBytesGenericBSD(len: Int32; data: PByte)
     class function GenRandomBytesGenericBSD(len: Int32; data: PByte)
       : Int32; static;
       : Int32; static;
@@ -219,8 +318,6 @@ type
 {$ENDIF}
 {$ENDIF}
     // ================================================================//
     // ================================================================//
 
 
-    class function NoZeroes(const data: TCryptoLibByteArray): Boolean;
-      static; inline;
     class procedure Boot(); static;
     class procedure Boot(); static;
     class constructor OSRandom();
     class constructor OSRandom();
 
 
@@ -231,32 +328,19 @@ type
   end;
   end;
 
 
   // ************************************************************************//
   // ************************************************************************//
-
-{$IFDEF CRYPTOLIB_MSWINDOWS}
-
-const
-  ADVAPI32 = 'advapi32.dll';
-
-function CryptAcquireContextW(phProv: Pointer; pszContainer: LPCWSTR;
-  pszProvider: LPCWSTR; dwProvType: DWORD; dwFlags: DWORD): BOOL; stdcall;
-  external ADVAPI32 Name 'CryptAcquireContextW';
-
-function CryptGenRandom(hProv: THandle; dwLen: DWORD; pbBuffer: PByte): BOOL;
-  stdcall; external ADVAPI32 Name 'CryptGenRandom';
-
-function CryptReleaseContext(hProv: THandle; dwFlags: DWORD): BOOL; stdcall;
-  external ADVAPI32 Name 'CryptReleaseContext';
-{$ENDIF}
-// ************************************************************************//
 {$IFDEF CRYPTOLIB_APPLE}
 {$IFDEF CRYPTOLIB_APPLE}
 {$IFDEF FPC}
 {$IFDEF FPC}
 
 
 type
 type
   // similar to a TOpaqueData already defined in newer FPC but not available in 3.0.4
   // similar to a TOpaqueData already defined in newer FPC but not available in 3.0.4
+  // TODO when we upgrade to FPC 3.2.0, remove " __SecRandom = record end;" declaration
   __SecRandom = record
   __SecRandom = record
   end;
   end;
 
 
   // similar to POpaqueData (or an OpaquePointer) already defined in newer FPC but not available in 3.0.4
   // similar to POpaqueData (or an OpaquePointer) already defined in newer FPC but not available in 3.0.4
+  // TODO when we upgrade to FPC 3.2.0, use inbuilt OpaquePointer instead
+  // replace "SecRandomRef = ^__SecRandom;" with "SecRandomRef = OpaquePointer;"
+
   SecRandomRef = ^__SecRandom;
   SecRandomRef = ^__SecRandom;
 
 
 function SecRandomCopyBytes(rnd: SecRandomRef; count: LongWord; bytes: PByte)
 function SecRandomCopyBytes(rnd: SecRandomRef; count: LongWord; bytes: PByte)
@@ -277,33 +361,20 @@ function SecRandomCopyBytes(rnd: SecRandomRef; count: LongWord; bytes: PByte)
 {$ENDIF}
 {$ENDIF}
 // ************************************************************************//
 // ************************************************************************//
 {$IFDEF CRYPTOLIB_GENERIC_BSD}
 {$IFDEF CRYPTOLIB_GENERIC_BSD}
-procedure arc4random_buf(bytes: PByte; count: LongWord); cdecl; external;
-'c' name 'arc4random_buf';
+procedure arc4random_buf(bytes: PByte; count: LongWord); cdecl;
+  external 'c' name 'arc4random_buf';
 {$ENDIF}
 {$ENDIF}
 
 
 implementation
 implementation
 
 
-class function TOSRandom.NoZeroes(const data: TCryptoLibByteArray): Boolean;
-var
-  i: Int32;
-begin
-  result := True;
-  for i := System.Low(data) to System.High(data) do
-  begin
-    if data[i] = 0 then
-    begin
-      result := False;
-      Exit;
-    end;
-  end;
-end;
-
 class procedure TOSRandom.Boot;
 class procedure TOSRandom.Boot;
 begin
 begin
 {$IFDEF CRYPTOLIB_MSWINDOWS}
 {$IFDEF CRYPTOLIB_MSWINDOWS}
   FIsCngBCryptGenRandomSupportedOnOS := IsCngBCryptGenRandomAvailable();
   FIsCngBCryptGenRandomSupportedOnOS := IsCngBCryptGenRandomAvailable();
+  FIsCryptGenRandomSupportedOnOS := IsCryptGenRandomAvailable();
+  FIsRtlGenRandomSupportedOnOS := IsRtlGenRandomAvailable();
 {$ENDIF}
 {$ENDIF}
-{$IFDEF CRYPTOLIB_LINUX}
+{$IFDEF CRYPTOLIB_HAS_GETRANDOM}
   FIsGetRandomSupportedOnOS := IsGetRandomAvailable();
   FIsGetRandomSupportedOnOS := IsGetRandomAvailable();
 {$ENDIF}
 {$ENDIF}
 end;
 end;
@@ -315,38 +386,78 @@ end;
 
 
 {$IFDEF CRYPTOLIB_MSWINDOWS}
 {$IFDEF CRYPTOLIB_MSWINDOWS}
 
 
+class function TOSRandom.GetProcedureAddress(ModuleHandle: THandle;
+  const AProcedureName: String; var AFunctionFound: Boolean): Pointer;
+begin
+  result := GetProcAddress(ModuleHandle, PChar(AProcedureName));
+  if result = Nil then
+  begin
+    AFunctionFound := False;
+  end;
+end;
+
 class function TOSRandom.GetIsCngBCryptGenRandomSupportedOnOS(): Boolean;
 class function TOSRandom.GetIsCngBCryptGenRandomSupportedOnOS(): Boolean;
 begin
 begin
   result := FIsCngBCryptGenRandomSupportedOnOS;
   result := FIsCngBCryptGenRandomSupportedOnOS;
 end;
 end;
 
 
+class function TOSRandom.GetIsCryptGenRandomSupportedOnOS(): Boolean;
+begin
+  result := FIsCryptGenRandomSupportedOnOS;
+end;
+
+class function TOSRandom.GetIsRtlGenRandomSupportedOnOS(): Boolean;
+begin
+  result := FIsRtlGenRandomSupportedOnOS;
+end;
+
 class function TOSRandom.IsCngBCryptGenRandomAvailable(): Boolean;
 class function TOSRandom.IsCngBCryptGenRandomAvailable(): Boolean;
-const
-  BCRYPT = 'bcrypt.dll';
 var
 var
   ModuleHandle: THandle;
   ModuleHandle: THandle;
+begin
+  result := False;
+  ModuleHandle := SafeLoadLibrary(BCRYPT, SEM_FAILCRITICALERRORS);
+  if ModuleHandle <> 0 then
+  begin
+    result := True;
+    FBCryptOpenAlgorithmProvider := GetProcedureAddress(ModuleHandle,
+      'BCryptOpenAlgorithmProvider', result);
+    FBCryptCloseAlgorithmProvider := GetProcedureAddress(ModuleHandle,
+      'BCryptCloseAlgorithmProvider', result);
+    FBCryptGenRandom := GetProcedureAddress(ModuleHandle,
+      'BCryptGenRandom', result);
+  end;
+end;
 
 
-  function GetProcedureAddress(const AProcedureName: String;
-    var AFunctionFound: Boolean): Pointer;
+class function TOSRandom.IsCryptGenRandomAvailable(): Boolean;
+var
+  ModuleHandle: THandle;
+begin
+  result := False;
+  ModuleHandle := SafeLoadLibrary(ADVAPI32, SEM_FAILCRITICALERRORS);
+  if ModuleHandle <> 0 then
   begin
   begin
-    result := GetProcAddress(ModuleHandle, PChar(AProcedureName));
-    if result = Nil then
-    begin
-      AFunctionFound := False;
-    end;
+    result := True;
+    FCryptAcquireContextW := GetProcedureAddress(ModuleHandle,
+      'CryptAcquireContextW', result);
+    FCryptReleaseContext := GetProcedureAddress(ModuleHandle,
+      'CryptReleaseContext', result);
+    FCryptGenRandom := GetProcedureAddress(ModuleHandle,
+      'CryptGenRandom', result);
   end;
   end;
+end;
 
 
+class function TOSRandom.IsRtlGenRandomAvailable(): Boolean;
+var
+  ModuleHandle: THandle;
 begin
 begin
   result := False;
   result := False;
-  ModuleHandle := SafeLoadLibrary(PChar(BCRYPT), SEM_FAILCRITICALERRORS);
+  ModuleHandle := SafeLoadLibrary(ADVAPI32, SEM_FAILCRITICALERRORS);
   if ModuleHandle <> 0 then
   if ModuleHandle <> 0 then
   begin
   begin
     result := True;
     result := True;
-    FBCryptOpenAlgorithmProvider :=
-      GetProcedureAddress('BCryptOpenAlgorithmProvider', result);
-    FBCryptCloseAlgorithmProvider :=
-      GetProcedureAddress('BCryptCloseAlgorithmProvider', result);
-    FBCryptGenRandom := GetProcedureAddress('BCryptGenRandom', result);
+    FRtlGenRandom := GetProcedureAddress(ModuleHandle,
+      'SystemFunction036', result);
   end;
   end;
 end;
 end;
 
 
@@ -367,46 +478,63 @@ const
   BCRYPT_RNG_ALGORITHM: WideString = 'RNG';
   BCRYPT_RNG_ALGORITHM: WideString = 'RNG';
 
 
 begin
 begin
-  if IsCngBCryptGenRandomSupportedOnOS then
+  // first check if RtlGenRandom is available to avoid the memory overhead
+  // of pulling in 'CryptoAPI'
+  if IsRtlGenRandomSupportedOnOS then
   begin
   begin
-    // Windows Vista and Above
-    if (not BCRYPT_SUCCESS(FBCryptOpenAlgorithmProvider(@hProv,
-      PWideChar(BCRYPT_RNG_ALGORITHM), nil, 0))) then
+    // Availability: Windows XP / Server 2003 and Above
+    if not FRtlGenRandom(data, ULONG(len)) then
+    begin
+      result := HResultFromWin32(GetLastError);
+      Exit;
+    end;
+  end
+  else if IsCryptGenRandomSupportedOnOS then
+  begin
+    // Availability: Windows XP / Server 2003 and Above
+    if not FCryptAcquireContextW(@hProv, nil, nil, PROV_RSA_FULL,
+      CRYPT_VERIFYCONTEXT or CRYPT_SILENT) then
     begin
     begin
       result := HResultFromWin32(GetLastError);
       result := HResultFromWin32(GetLastError);
       Exit;
       Exit;
     end;
     end;
 
 
     try
     try
-      if (not BCRYPT_SUCCESS(FBCryptGenRandom(hProv, PUCHAR(data),
-        ULONG(len), 0))) then
+      if not FCryptGenRandom(hProv, DWORD(len), data) then
       begin
       begin
         result := HResultFromWin32(GetLastError);
         result := HResultFromWin32(GetLastError);
         Exit;
         Exit;
       end;
       end;
     finally
     finally
-      FBCryptCloseAlgorithmProvider(hProv, 0);
+      FCryptReleaseContext(hProv, 0);
     end;
     end;
   end
   end
-  else
+  else if IsCngBCryptGenRandomSupportedOnOS then
   begin
   begin
-    // Below Windows Vista
-    if not CryptAcquireContextW(@hProv, nil, nil, PROV_RSA_FULL,
-      CRYPT_VERIFYCONTEXT or CRYPT_SILENT) then
+    // Availability: Windows Vista / Server 2008 and Above
+    if (not BCRYPT_SUCCESS(FBCryptOpenAlgorithmProvider(@hProv,
+      PWideChar(BCRYPT_RNG_ALGORITHM), nil, 0))) then
     begin
     begin
       result := HResultFromWin32(GetLastError);
       result := HResultFromWin32(GetLastError);
       Exit;
       Exit;
     end;
     end;
 
 
     try
     try
-      if not CryptGenRandom(hProv, DWORD(len), data) then
+      if (not BCRYPT_SUCCESS(FBCryptGenRandom(hProv, PUCHAR(data),
+        ULONG(len), 0))) then
       begin
       begin
         result := HResultFromWin32(GetLastError);
         result := HResultFromWin32(GetLastError);
         Exit;
         Exit;
       end;
       end;
     finally
     finally
-      CryptReleaseContext(hProv, 0);
+      FBCryptCloseAlgorithmProvider(hProv, 0);
     end;
     end;
+  end
+  else
+  begin
+    // should never happen but who knows :)
+    result := S_FALSE;
+    Exit;
   end;
   end;
   result := S_OK;
   result := S_OK;
 end;
 end;
@@ -426,7 +554,20 @@ class function TOSRandom.GenRandomBytesApple(len: Int32; data: PByte): Int32;
   end;
   end;
 
 
 begin
 begin
+{$IF DEFINED(CRYPTOLIB_MACOS)}
+  // >= (Mac OS X 10.7+)
+  if NSAppKitVersionNumber >= 1138 then // NSAppKitVersionNumber10_7
+  begin
+    result := SecRandomCopyBytes(kSecRandomDefault, LongWord(len), data);
+  end
+  else
+  begin
+    // fallback for when SecRandomCopyBytes API is not available
+    result := dev_random_device_read(len, data);
+  end;
+{$ELSE}
   result := SecRandomCopyBytes(kSecRandomDefault, LongWord(len), data);
   result := SecRandomCopyBytes(kSecRandomDefault, LongWord(len), data);
+{$IFEND}
 end;
 end;
 
 
 {$ENDIF}
 {$ENDIF}
@@ -436,11 +577,20 @@ class function TOSRandom.dev_random_device_read(len: Int32; data: PByte): Int32;
 var
 var
   LStream: TFileStream;
   LStream: TFileStream;
   RandGen: String;
   RandGen: String;
+  got, MaxChunkSize: Int32;
 begin
 begin
+  MaxChunkSize := len;
   RandGen := '/dev/urandom';
   RandGen := '/dev/urandom';
+{$IFDEF CRYPTOLIB_SOLARIS}
+  MaxChunkSize := 128 * 1040; // 128 * 1040 bytes
+{$ENDIF}
   if not FileExists(RandGen) then
   if not FileExists(RandGen) then
   begin
   begin
+{$IFDEF CRYPTOLIB_SOLARIS}
+    MaxChunkSize := 1040; // 1040 bytes
+{$ENDIF}
     RandGen := '/dev/random';
     RandGen := '/dev/random';
+
     if not FileExists(RandGen) then
     if not FileExists(RandGen) then
     begin
     begin
       result := -1;
       result := -1;
@@ -451,23 +601,43 @@ begin
   LStream := TFileStream.Create(RandGen, fmOpenRead);
   LStream := TFileStream.Create(RandGen, fmOpenRead);
 
 
   try
   try
-    try
-      LStream.ReadBuffer(data[0], len);
-      result := 0;
-    except
-      result := -1;
+    while (len > 0) do
+    begin
+      if len <= MaxChunkSize then
+      begin
+        MaxChunkSize := len;
+      end;
+
+      got := LStream.Read(data^, MaxChunkSize);
+
+      if (got = 0) then
+      begin
+        if ErrorNo = EINTR then
+        begin
+          continue;
+        end;
+
+        result := -1;
+        Exit;
+      end;
+
+      System.Inc(data, got);
+      System.Dec(len, got);
     end;
     end;
+    result := 0;
   finally
   finally
     LStream.Free;
     LStream.Free;
   end;
   end;
 end;
 end;
 {$ENDIF}
 {$ENDIF}
-{$IFDEF CRYPTOLIB_LINUX}
+{$IFDEF CRYPTOLIB_UNIX}
 
 
 class function TOSRandom.ErrorNo: Int32;
 class function TOSRandom.ErrorNo: Int32;
 begin
 begin
   result := Errno;
   result := Errno;
 end;
 end;
+{$ENDIF}
+{$IFDEF CRYPTOLIB_HAS_GETRANDOM}
 
 
 class function TOSRandom.GetIsGetRandomSupportedOnOS(): Boolean;
 class function TOSRandom.GetIsGetRandomSupportedOnOS(): Boolean;
 begin
 begin
@@ -475,13 +645,11 @@ begin
 end;
 end;
 
 
 class function TOSRandom.IsGetRandomAvailable(): Boolean;
 class function TOSRandom.IsGetRandomAvailable(): Boolean;
-const
-  LIBC_SO_6 = 'libc.so.6';
 var
 var
   Lib: {$IFDEF FPC} PtrInt {$ELSE} NativeUInt {$ENDIF};
   Lib: {$IFDEF FPC} PtrInt {$ELSE} NativeUInt {$ENDIF};
 begin
 begin
   FGetRandom := Nil;
   FGetRandom := Nil;
-  Lib := {$IFDEF FPC}PtrInt{$ENDIF}(dlopen(LIBC_SO_6, RTLD_NOW));
+  Lib := {$IFDEF FPC}PtrInt{$ENDIF}(dlopen(LIBC_SO, RTLD_NOW));
   if Lib <> 0 then
   if Lib <> 0 then
   begin
   begin
     FGetRandom := dlsym(Lib, 'getrandom');
     FGetRandom := dlsym(Lib, 'getrandom');
@@ -490,29 +658,32 @@ begin
   result := System.Assigned(FGetRandom);
   result := System.Assigned(FGetRandom);
 end;
 end;
 
 
+{$ENDIF}
+{$IFDEF CRYPTOLIB_LINUX}
+
 class function TOSRandom.GenRandomBytesLinux(len: Int32; data: PByte): Int32;
 class function TOSRandom.GenRandomBytesLinux(len: Int32; data: PByte): Int32;
-const
-  GRND_DEFAULT: Int32 = $0000;
-  EINTR = {$IFDEF FPC}ESysEINTR {$ELSE}Posix.Errno.EINTR{$ENDIF};
 var
 var
-  n: Int64;
+  got: Int32;
 begin
 begin
+
   if IsGetRandomSupportedOnOS then
   if IsGetRandomSupportedOnOS then
   begin
   begin
     while (len > 0) do
     while (len > 0) do
     begin
     begin
 
 
-      repeat
-        n := FGetRandom(data, LongWord(len), GRND_DEFAULT);
-      until ((n > 0) and (ErrorNo <> EINTR));
+      got := FGetRandom(data, LongWord(len), GRND_DEFAULT);
 
 
-      if (n <= 0) then
+      if (got < 0) then
       begin
       begin
+        if ErrorNo = EINTR then
+        begin
+          continue;
+        end;
         result := -1;
         result := -1;
         Exit;
         Exit;
       end;
       end;
-      System.Inc(data, n);
-      System.Dec(len, n);
+      System.Inc(data, got);
+      System.Dec(len, got);
     end;
     end;
     result := 0;
     result := 0;
   end
   end
@@ -522,7 +693,46 @@ begin
     result := dev_random_device_read(len, data);
     result := dev_random_device_read(len, data);
   end;
   end;
 end;
 end;
+{$ENDIF}
+{$IFDEF CRYPTOLIB_SOLARIS}
+
+class function TOSRandom.GenRandomBytesSolaris(len: Int32; data: PByte): Int32;
+var
+  got, MaxChunkSize: Int32;
+begin
+  MaxChunkSize := 256; // 256 bytes
+
+  if IsGetRandomSupportedOnOS then
+  begin
+    while (len > 0) do
+    begin
+      if len <= MaxChunkSize then
+      begin
+        MaxChunkSize := len;
+      end;
+
+      got := FGetRandom(data, LongWord(MaxChunkSize), GRND_DEFAULT);
 
 
+      if (got = 0) then
+      begin
+        if ErrorNo = EINTR then
+        begin
+          continue;
+        end;
+        result := -1;
+        Exit;
+      end;
+      System.Inc(data, got);
+      System.Dec(len, got);
+    end;
+    result := 0;
+  end
+  else
+  begin
+    // fallback for when getrandom API is not available
+    result := dev_random_device_read(len, data);
+  end;
+end;
 {$ENDIF}
 {$ENDIF}
 {$IFDEF CRYPTOLIB_GENERIC_BSD}
 {$IFDEF CRYPTOLIB_GENERIC_BSD}
 
 
@@ -566,17 +776,23 @@ begin
     raise EOSRandomCryptoLibException.CreateRes(@SLinuxGetRandomError);
     raise EOSRandomCryptoLibException.CreateRes(@SLinuxGetRandomError);
   end;
   end;
 
 
+{$ELSEIF DEFINED(CRYPTOLIB_SOLARIS)}
+  if GenRandomBytesSolaris(count, PByte(data)) <> 0 then
+  begin
+    raise EOSRandomCryptoLibException.CreateRes(@SSolarisGetRandomError);
+  end;
+
 {$ELSEIF DEFINED(CRYPTOLIB_GENERIC_BSD)}
 {$ELSEIF DEFINED(CRYPTOLIB_GENERIC_BSD)}
   if GenRandomBytesGenericBSD(count, PByte(data)) <> 0 then
   if GenRandomBytesGenericBSD(count, PByte(data)) <> 0 then
   begin
   begin
     raise EOSRandomCryptoLibException.CreateRes(@SArc4RandomBufGenerationError);
     raise EOSRandomCryptoLibException.CreateRes(@SArc4RandomBufGenerationError);
   end;
   end;
-{$ELSEIF DEFINED(CRYPTOLIB_UNDEFINED_UNIX_VARIANTS)}
-  // fallback option for other Undefined Unix OSes
-  if dev_random_device_read(count, PByte(data)) <> 0 then
-  begin
-    raise EOSRandomCryptoLibException.CreateRes(@SRandomDeviceReadError);
-  end;
+  // {$ELSEIF DEFINED(CRYPTOLIB_UNDEFINED_UNIX_VARIANTS)}
+  // // fallback option for other Undefined Unix OSes
+  // if dev_random_device_read(count, PByte(data)) <> 0 then
+  // begin
+  // raise EOSRandomCryptoLibException.CreateRes(@SRandomDeviceReadError);
+  // end;
 {$ELSE}
 {$ELSE}
 {$MESSAGE ERROR 'UNSUPPORTED TARGET.'}
 {$MESSAGE ERROR 'UNSUPPORTED TARGET.'}
 {$IFEND}
 {$IFEND}
@@ -586,7 +802,7 @@ class procedure TOSRandom.GetNonZeroBytes(const data: TCryptoLibByteArray);
 begin
 begin
   repeat
   repeat
     TOSRandom.GetBytes(data);
     TOSRandom.GetBytes(data);
-  until (NoZeroes(data));
+  until (TArrayUtils.NoZeroes(data));
 end;
 end;
 
 
 end.
 end.

+ 0 - 291
src/libraries/cryptolib4pascal/ClpPcgRandomMinimal.pas

@@ -1,291 +0,0 @@
-{ *********************************************************************************** }
-{ *                              CryptoLib Library                                  * }
-{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
-{ *                 Github Repository <https://github.com/Xor-el>                   * }
-
-{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
-{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
-
-{ *                              Acknowledgements:                                  * }
-{ *                                                                                 * }
-{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
-{ *                           development of this library                           * }
-
-{ * ******************************************************************************* * }
-
-(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
-
-unit ClpPcgRandomMinimal;
-
-{$I CryptoLib.inc}
-(*
-  * PCG Random Number Generation for Pascal.
-  *
-  * Copyright 2015 Ugochukwu Mmaduekwe <[email protected]>
-  * Copyright 2015 Kevin Harris <[email protected]>
-  * Copyright 2014 Melissa O'Neill <[email protected]>
-  *
-  * For additional information about the PCG random number generation scheme,
-  * including its license and other licensing options, visit
-  *
-  *     http://www.pcg-random.org
-*)
-
-interface
-
-uses
-  SysUtils;
-
-type
-
-  /// <summary>
-  /// The Pcg Random Number Class.
-  /// </summary>
-
-  TPcg = class sealed(TObject)
-
-  strict private
-
-  class var
-    /// <summary>
-    /// The RNG state. All values are possible.
-    /// </summary>
-    Fm_state: UInt64;
-
-    /// <summary>
-    /// Controls which RNG sequence (stream) is selected.
-    /// Must <strong>always</strong> be odd.
-    /// </summary>
-    Fm_inc: UInt64;
-
-    /// <summary>
-    /// Record to help Cast a Comp to an Int64.
-    /// </summary>
-    /// <returns> Int64 </returns>
-
-  type
-
-    CompConverter = record
-    private
-      /// <summary>
-      /// Internal variable used for Casting.
-      /// </summary>
-      FI64: Int64;
-    end;
-
-    /// <summary>
-    /// static class constructor.
-    /// Initializes a new instance of the <see cref="TPcg"/> class
-    /// <strong>FOR USAGE</strong> with <strong>SYSTEM TIME</strong> as initState.
-    /// </summary>
-
-  class constructor Create;
-
-  /// <summary>
-  /// Seed Pcg in two parts, a state initializer
-  /// and a sequence selection constant (a.k.a.
-  /// stream id).
-  /// </summary>
-  /// <param name="initState">Initial state.</param>
-  /// <param name="initSeq">Initial sequence</param>
-
-  class procedure Seed(initState: UInt64; initSeq: UInt64); static;
-
-  /// <summary>
-  /// Generates a uniformly distributed number, r,
-  /// where 0 &lt;= r &lt; exclusiveBound.
-  /// </summary>
-  /// <param name="exclusiveBound">Exclusive bound.</param>
-
-  class function Range32(exclusiveBound: UInt32): UInt32; static;
-
-  /// <summary>
-  /// Generates an Init State from System Time.
-  /// </summary>
-  /// <param name="initSeq">Calculated initSeq.</param>
-  /// <returns> UInt64 </returns>
-
-  class function GetInitState(out initSeq: UInt64): UInt64; static; inline;
-
-  /// <summary>
-  /// Generates an Init Sequence from GetInitState value * 181783497276652981.
-  /// <param name="tempVal">Previous value from GetInitState.</param>
-  /// </summary>
-  /// <returns> UInt64 </returns>
-
-  class function GetInitSeq(tempVal: UInt64): UInt64; static; inline;
-
-  public
-
-    /// <summary>
-    /// Initializes a new instance of the <see cref="TPcg"/> class
-    /// <strong>FOR TESTING</strong> with a <strong>KNOWN</strong> seed.
-    /// </summary>
-
-    constructor Create(); overload;
-
-    /// <summary>
-    /// Initializes a new instance of the <see cref="TPcg"/> class.
-    /// </summary>
-    /// <param name="initState">Initial state.</param>
-    /// <param name="initSeq">Initial sequence</param>
-
-    constructor Create(initState: UInt64; initSeq: UInt64); overload;
-
-    /// <summary>
-    /// Generates a uniformly-distributed 32-bit random number.
-    /// </summary>
-
-    class function NextUInt32(): UInt32; overload; inline;
-
-    /// <summary>
-    /// Generates a uniformly distributed number, r,
-    /// where minimum &lt;= r &lt; exclusiveBound.
-    /// </summary>
-    /// <param name="minimum">The minimum inclusive value.</param>
-    /// <param name="exclusiveBound">The maximum exclusive bound.</param>
-
-    class function NextUInt32(minimum, exclusiveBound: UInt32): UInt32;
-      overload; inline;
-
-    /// <summary>
-    /// Generates a uniformly distributed number, r,
-    /// where minimum &lt;= r &lt; exclusiveBound.
-    /// </summary>
-    /// <param name="minimum">The minimum inclusive value.</param>
-    /// <param name="exclusiveBound">The maximum exclusive bound.</param>
-
-    class function NextInt(minimum, exclusiveBound: Int32): Int32; inline;
-
-  end;
-
-implementation
-
-class function TPcg.NextUInt32(): UInt32;
-var
-  oldState, LValue: UInt64;
-  xorShifted: UInt32;
-  rot: Int32;
-begin
-  oldState := Fm_state;
-  LValue := UInt64(6364136223846793005);
-  Fm_state := oldState * LValue + Fm_inc;
-  xorShifted := UInt32(((oldState shr 18) xor oldState) shr 27);
-  rot := Int32(oldState shr 59);
-  result := (xorShifted shr rot) or (xorShifted shl ((-rot) and 31));
-end;
-
-class function TPcg.NextUInt32(minimum: UInt32; exclusiveBound: UInt32): UInt32;
-var
-  boundRange, rangeResult: UInt32;
-begin
-  boundRange := exclusiveBound - minimum;
-  rangeResult := Range32(boundRange);
-  result := rangeResult + minimum;
-end;
-
-class function TPcg.Range32(exclusiveBound: UInt32): UInt32;
-var
-  r, threshold: UInt32;
-begin
-  // To avoid bias, we need to make the range of the RNG
-  // a multiple of bound, which we do by dropping output
-  // less than a threshold. A naive scheme to calculate the
-  // threshold would be to do
-  //
-  // threshold = UInt64($100000000) mod exclusiveBound;
-  //
-  // but 64-bit div/mod is slower than 32-bit div/mod
-  // (especially on 32-bit platforms). In essence, we do
-  //
-  // threshold := UInt32((UInt64($100000000) - exclusiveBound) mod exclusiveBound);
-  //
-  // because this version will calculate the same modulus,
-  // but the LHS value is less than 2^32.
-  threshold := UInt32((UInt64($100000000) - exclusiveBound) mod exclusiveBound);
-
-  // Uniformity guarantees that this loop will terminate.
-  // In practice, it should terminate quickly; on average
-  // (assuming all bounds are equally likely), 82.25% of
-  // the time, we can expect it to require just one
-  // iteration. In the worst case, someone passes a bound
-  // of 2^31 + 1 (i.e., 2147483649), which invalidates
-  // almost 50% of the range. In practice bounds are
-  // typically small and only a tiny amount of the range
-  // is eliminated.
-  while True do
-  begin
-    r := NextUInt32();
-    if (r >= threshold) then
-    begin
-      result := r mod exclusiveBound;
-      Exit;
-    end;
-
-  end;
-  result := 0; // to make FixInsight Happy :)
-end;
-
-class procedure TPcg.Seed(initState: UInt64; initSeq: UInt64);
-begin
-  Fm_state := UInt32(0);
-  Fm_inc := (initSeq shl 1) or UInt64(1);
-  NextUInt32();
-  Fm_state := Fm_state + initState;
-  NextUInt32();
-end;
-
-class function TPcg.GetInitSeq(tempVal: UInt64): UInt64;
-
-begin
-  result := tempVal * UInt64(181783497276652981);
-end;
-
-class function TPcg.GetInitState(out initSeq: UInt64): UInt64;
-
-begin
-  result := UInt64
-    (CompConverter(TimeStampToMsecs(DateTimeToTimeStamp(Now))).FI64);
-  initSeq := GetInitSeq(result) * UInt64(Int64(1000000));
-
-end;
-
-// static class constructor
-class constructor TPcg.Create();
-var
-  LinitState, LinitSeq: UInt64;
-begin
-
-  LinitState := GetInitState(LinitSeq);
-  // ==> initializes using system time as initState and calculated value as
-  // initSeq
-  Seed(LinitState, LinitSeq);
-
-end;
-
-constructor TPcg.Create();
-var
-  LinitState, LinitSeq: UInt64;
-begin
-  // ==> initializes using default seeds. you can change it to any reasonable
-  // value
-  LinitState := UInt64($853C49E6748FEA9B);
-  LinitSeq := UInt64($DA3E39CB94B95BDB);
-  Seed(LinitState, LinitSeq);
-end;
-
-constructor TPcg.Create(initState, initSeq: UInt64);
-begin
-  Seed(initState, initSeq);
-end;
-
-class function TPcg.NextInt(minimum, exclusiveBound: Int32): Int32;
-var
-  boundRange, rangeResult: UInt32;
-begin
-  boundRange := UInt32(exclusiveBound - minimum);
-  rangeResult := Range32(boundRange);
-  result := Int32(rangeResult) + Int32(minimum);
-end;
-
-end.

+ 13 - 33
src/libraries/cryptolib4pascal/ClpRandomNumberGenerator.pas

@@ -24,7 +24,7 @@ interface
 uses
 uses
   ClpCryptoLibTypes,
   ClpCryptoLibTypes,
   ClpOSRandom,
   ClpOSRandom,
-  ClpPcgRandomMinimal,
+  ClpAESPRNGRandom,
   ClpIRandomNumberGenerator;
   ClpIRandomNumberGenerator;
 
 
 resourcestring
 resourcestring
@@ -44,7 +44,7 @@ type
 
 
     type
     type
 {$SCOPEDENUMS ON}
 {$SCOPEDENUMS ON}
-    TRandomNumberGeneratorMode = (rngmOS = 0, rngmPCG = 1);
+    TRandomNumberGeneratorMode = (rngmOS = 0, rngmAES = 1);
 {$SCOPEDENUMS OFF}
 {$SCOPEDENUMS OFF}
   class function CreateRNG(): IRandomNumberGenerator; overload; static;
   class function CreateRNG(): IRandomNumberGenerator; overload; static;
 
 
@@ -71,8 +71,8 @@ type
   end;
   end;
 
 
 type
 type
-  TPCGRandomNumberGenerator = class sealed(TRandomNumberGenerator,
-    IPCGRandomNumberGenerator)
+  TAESPRNGRandomNumberGenerator = class sealed(TRandomNumberGenerator,
+    IAESPRNGRandomNumberGenerator)
 
 
   public
   public
     constructor Create();
     constructor Create();
@@ -113,9 +113,9 @@ begin
         Exit;
         Exit;
       end;
       end;
 
 
-    TRandomNumberGeneratorMode.rngmPCG:
+    TRandomNumberGeneratorMode.rngmAES:
       begin
       begin
-        result := TPCGRandomNumberGenerator.Create();
+        result := TAESPRNGRandomNumberGenerator.Create();
         Exit;
         Exit;
       end
       end
 
 
@@ -148,45 +148,25 @@ begin
   TOSRandom.GetNonZeroBytes(data);
   TOSRandom.GetNonZeroBytes(data);
 end;
 end;
 
 
-{ TPCGRandomNumberGenerator }
+{ TAESPRNGRandomNumberGenerator }
 
 
-constructor TPCGRandomNumberGenerator.Create;
+constructor TAESPRNGRandomNumberGenerator.Create;
 begin
 begin
   inherited Create();
   inherited Create();
 end;
 end;
 
 
-procedure TPCGRandomNumberGenerator.GetBytes(const data: TCryptoLibByteArray);
-var
-  i: Int64;
+procedure TAESPRNGRandomNumberGenerator.GetBytes
+  (const data: TCryptoLibByteArray);
 begin
 begin
   ValidateOutputBufferNotNull(data);
   ValidateOutputBufferNotNull(data);
-  i := System.Length(data);
-  while i > 0 do
-  begin
-    data[i - 1] := Byte(TPcg.NextInt(System.Low(Int32), System.High(Int32)));
-    System.Dec(i);
-  end;
-
+  TAESPRNGRandom.GetBytes(data);
 end;
 end;
 
 
-procedure TPCGRandomNumberGenerator.GetNonZeroBytes
+procedure TAESPRNGRandomNumberGenerator.GetNonZeroBytes
   (const data: TCryptoLibByteArray);
   (const data: TCryptoLibByteArray);
-var
-  i: Int64;
-  val: Byte;
 begin
 begin
   ValidateOutputBufferNotNull(data);
   ValidateOutputBufferNotNull(data);
-  i := System.Length(data);
-  while i > 0 do
-  begin
-    repeat
-      val := Byte(TPcg.NextUInt32(System.Low(UInt32), System.High(UInt32)));
-    until (not(val = 0));
-
-    data[i - 1] := val;
-    System.Dec(i);
-  end;
-
+  TAESPRNGRandom.GetNonZeroBytes(data);
 end;
 end;
 
 
 end.
 end.

+ 131 - 0
src/libraries/cryptolib4pascal/ClpScalarSplitParameters.pas

@@ -0,0 +1,131 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpScalarSplitParameters;
+
+{$I CryptoLib.inc}
+
+interface
+
+uses
+  ClpBigInteger,
+  ClpIScalarSplitParameters,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SInvalidParameters = '"%s" must consist of exactly 2 (initialized) values';
+
+type
+  TScalarSplitParameters = class sealed(TInterfacedObject,
+    IScalarSplitParameters)
+
+  strict private
+    function GetG1: TBigInteger; inline;
+    function GetG2: TBigInteger; inline;
+    function GetV1A: TBigInteger; inline;
+    function GetV1B: TBigInteger; inline;
+    function GetV2A: TBigInteger; inline;
+    function GetV2B: TBigInteger; inline;
+    function GetBits: Int32; inline;
+
+    class procedure CheckVector(const v: TCryptoLibGenericArray<TBigInteger>;
+      const name: String); static;
+
+  strict protected
+    Fg1, Fg2, Fv1A, Fv1B, Fv2A, Fv2B: TBigInteger;
+    Fbits: Int32;
+
+  public
+    constructor Create(const v1, v2: TCryptoLibGenericArray<TBigInteger>;
+      const g1, g2: TBigInteger; bits: Int32);
+
+    property g1: TBigInteger read GetG1;
+    property g2: TBigInteger read GetG2;
+    property V1A: TBigInteger read GetV1A;
+    property V1B: TBigInteger read GetV1B;
+    property V2A: TBigInteger read GetV2A;
+    property V2B: TBigInteger read GetV2B;
+    property bits: Int32 read GetBits;
+
+  end;
+
+implementation
+
+{ TScalarSplitParameters }
+
+class procedure TScalarSplitParameters.CheckVector
+  (const v: TCryptoLibGenericArray<TBigInteger>; const name: String);
+begin
+  if ((v = Nil) or (System.length(v) <> 2) or (not v[0].IsInitialized) or
+    (not v[1].IsInitialized)) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt(@SInvalidParameters, [name]);
+  end;
+end;
+
+constructor TScalarSplitParameters.Create(const v1,
+  v2: TCryptoLibGenericArray<TBigInteger>; const g1, g2: TBigInteger;
+  bits: Int32);
+begin
+  CheckVector(v1, 'v1');
+  CheckVector(v2, 'v2');
+
+  Fv1A := v1[0];
+  Fv1B := v1[1];
+  Fv2A := v2[0];
+  Fv2B := v2[1];
+  Fg1 := g1;
+  Fg2 := g2;
+  Fbits := bits;
+end;
+
+function TScalarSplitParameters.GetG1: TBigInteger;
+begin
+  Result := Fg1;
+end;
+
+function TScalarSplitParameters.GetG2: TBigInteger;
+begin
+  Result := Fg2;
+end;
+
+function TScalarSplitParameters.GetV1A: TBigInteger;
+begin
+  Result := Fv1A;
+end;
+
+function TScalarSplitParameters.GetV1B: TBigInteger;
+begin
+  Result := Fv1B;
+end;
+
+function TScalarSplitParameters.GetV2A: TBigInteger;
+begin
+  Result := Fv2A;
+end;
+
+function TScalarSplitParameters.GetV2B: TBigInteger;
+begin
+  Result := Fv2B;
+end;
+
+function TScalarSplitParameters.GetBits: Int32;
+begin
+  Result := Fbits;
+end;
+
+end.

+ 56 - 0
src/libraries/cryptolib4pascal/ClpScaleXNegateYPointMap.pas

@@ -0,0 +1,56 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpScaleXNegateYPointMap;
+
+{$I CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECC,
+  ClpIScaleXNegateYPointMap;
+
+type
+  TScaleXNegateYPointMap = class(TInterfacedObject, IECPointMap,
+    IScaleXNegateYPointMap)
+
+  strict protected
+  var
+    Fscale: IECFieldElement;
+
+  public
+    constructor Create(const scale: IECFieldElement);
+    function Map(const p: IECPoint): IECPoint; virtual;
+  end;
+
+implementation
+
+{ TScaleXNegateYPointMap }
+
+constructor TScaleXNegateYPointMap.Create(const scale: IECFieldElement);
+begin
+  Inherited Create();
+  Fscale := scale;
+end;
+
+function TScaleXNegateYPointMap.Map(const p: IECPoint): IECPoint;
+begin
+  Result := p.ScaleXNegateY(Fscale);
+end;
+
+end.

+ 56 - 0
src/libraries/cryptolib4pascal/ClpScaleYNegateXPointMap.pas

@@ -0,0 +1,56 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpScaleYNegateXPointMap;
+
+{$I CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECC,
+  ClpIScaleYNegateXPointMap;
+
+type
+  TScaleYNegateXPointMap = class(TInterfacedObject, IECPointMap,
+    IScaleYNegateXPointMap)
+
+  strict protected
+  var
+    Fscale: IECFieldElement;
+
+  public
+    constructor Create(const scale: IECFieldElement);
+    function Map(const p: IECPoint): IECPoint; virtual;
+  end;
+
+implementation
+
+{ TScaleYNegateXPointMap }
+
+constructor TScaleYNegateXPointMap.Create(const scale: IECFieldElement);
+begin
+  Inherited Create();
+  Fscale := scale;
+end;
+
+function TScaleYNegateXPointMap.Map(const p: IECPoint): IECPoint;
+begin
+  Result := p.ScaleYNegateX(Fscale);
+end;
+
+end.

+ 184 - 203
src/libraries/cryptolib4pascal/ClpSecNamedCurves.pas

@@ -29,6 +29,7 @@ uses
   ClpIGlvTypeBEndomorphism,
   ClpIGlvTypeBEndomorphism,
   ClpSecObjectIdentifiers,
   ClpSecObjectIdentifiers,
   ClpCryptoLibTypes,
   ClpCryptoLibTypes,
+  ClpECCompUtilities,
   ClpBigInteger,
   ClpBigInteger,
   ClpECC,
   ClpECC,
   ClpIECC,
   ClpIECC,
@@ -36,6 +37,8 @@ uses
   ClpIX9ECC,
   ClpIX9ECC,
   ClpIAsn1Objects,
   ClpIAsn1Objects,
   ClpGlvTypeBEndomorphism,
   ClpGlvTypeBEndomorphism,
+  ClpIScalarSplitParameters,
+  ClpScalarSplitParameters,
   ClpX9ECParameters,
   ClpX9ECParameters,
   ClpIX9ECParameters,
   ClpIX9ECParameters,
   ClpX9ECParametersHolder,
   ClpX9ECParametersHolder,
@@ -63,6 +66,9 @@ type
       const p: IGlvTypeBParameters): IECCurve; static; inline;
       const p: IGlvTypeBParameters): IECCurve; static; inline;
     class function FromHex(const Hex: String): TBigInteger; static; inline;
     class function FromHex(const Hex: String): TBigInteger; static; inline;
 
 
+    class function ConfigureBasepoint(const curve: IECCurve;
+      const encoding: String): IX9ECPoint; static;
+
     class procedure Boot(); static;
     class procedure Boot(); static;
     class constructor CreateSecNamedCurves();
     class constructor CreateSecNamedCurves();
     class destructor DestroySecNamedCurves();
     class destructor DestroySecNamedCurves();
@@ -347,7 +353,7 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(113);
+      M = Int32(113);
       Fk = Int32(9);
       Fk = Int32(9);
 
 
     strict protected
     strict protected
@@ -368,7 +374,7 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(113);
+      M = Int32(113);
       Fk = Int32(9);
       Fk = Int32(9);
 
 
     strict protected
     strict protected
@@ -389,10 +395,10 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(131);
-      Fk1 = Int32(2);
-      Fk2 = Int32(3);
-      Fk3 = Int32(8);
+      M = Int32(131);
+      K1 = Int32(2);
+      K2 = Int32(3);
+      K3 = Int32(8);
 
 
     strict protected
     strict protected
       function CreateParameters(): IX9ECParameters; override;
       function CreateParameters(): IX9ECParameters; override;
@@ -412,10 +418,10 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(131);
-      Fk1 = Int32(2);
-      Fk2 = Int32(3);
-      Fk3 = Int32(8);
+      M = Int32(131);
+      K1 = Int32(2);
+      K2 = Int32(3);
+      K3 = Int32(8);
 
 
     strict protected
     strict protected
       function CreateParameters(): IX9ECParameters; override;
       function CreateParameters(): IX9ECParameters; override;
@@ -435,10 +441,10 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(163);
-      Fk1 = Int32(3);
-      Fk2 = Int32(6);
-      Fk3 = Int32(7);
+      M = Int32(163);
+      K1 = Int32(3);
+      K2 = Int32(6);
+      K3 = Int32(7);
 
 
     strict protected
     strict protected
       function CreateParameters(): IX9ECParameters; override;
       function CreateParameters(): IX9ECParameters; override;
@@ -458,10 +464,10 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(163);
-      Fk1 = Int32(3);
-      Fk2 = Int32(6);
-      Fk3 = Int32(7);
+      M = Int32(163);
+      K1 = Int32(3);
+      K2 = Int32(6);
+      K3 = Int32(7);
 
 
     strict protected
     strict protected
       function CreateParameters(): IX9ECParameters; override;
       function CreateParameters(): IX9ECParameters; override;
@@ -481,10 +487,10 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(163);
-      Fk1 = Int32(3);
-      Fk2 = Int32(6);
-      Fk3 = Int32(7);
+      M = Int32(163);
+      K1 = Int32(3);
+      K2 = Int32(6);
+      K3 = Int32(7);
 
 
     strict protected
     strict protected
       function CreateParameters(): IX9ECParameters; override;
       function CreateParameters(): IX9ECParameters; override;
@@ -504,7 +510,7 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(193);
+      M = Int32(193);
       Fk = Int32(15);
       Fk = Int32(15);
 
 
     strict protected
     strict protected
@@ -525,7 +531,7 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(193);
+      M = Int32(193);
       Fk = Int32(15);
       Fk = Int32(15);
 
 
     strict protected
     strict protected
@@ -546,7 +552,7 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(233);
+      M = Int32(233);
       Fk = Int32(74);
       Fk = Int32(74);
 
 
     strict protected
     strict protected
@@ -567,7 +573,7 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(233);
+      M = Int32(233);
       Fk = Int32(74);
       Fk = Int32(74);
 
 
     strict protected
     strict protected
@@ -588,7 +594,7 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(239);
+      M = Int32(239);
       Fk = Int32(158);
       Fk = Int32(158);
 
 
     strict protected
     strict protected
@@ -609,10 +615,10 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(283);
-      Fk1 = Int32(5);
-      Fk2 = Int32(7);
-      Fk3 = Int32(12);
+      M = Int32(283);
+      K1 = Int32(5);
+      K2 = Int32(7);
+      K3 = Int32(12);
 
 
     strict protected
     strict protected
       function CreateParameters(): IX9ECParameters; override;
       function CreateParameters(): IX9ECParameters; override;
@@ -632,10 +638,10 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(283);
-      Fk1 = Int32(5);
-      Fk2 = Int32(7);
-      Fk3 = Int32(12);
+      M = Int32(283);
+      K1 = Int32(5);
+      K2 = Int32(7);
+      K3 = Int32(12);
 
 
     strict protected
     strict protected
       function CreateParameters(): IX9ECParameters; override;
       function CreateParameters(): IX9ECParameters; override;
@@ -655,7 +661,7 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(409);
+      M = Int32(409);
       Fk = Int32(87);
       Fk = Int32(87);
 
 
     strict protected
     strict protected
@@ -676,7 +682,7 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(409);
+      M = Int32(409);
       Fk = Int32(87);
       Fk = Int32(87);
 
 
     strict protected
     strict protected
@@ -697,10 +703,10 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(571);
-      Fk1 = Int32(2);
-      Fk2 = Int32(5);
-      Fk3 = Int32(10);
+      M = Int32(571);
+      K1 = Int32(2);
+      K2 = Int32(5);
+      K3 = Int32(10);
 
 
     strict protected
     strict protected
       function CreateParameters(): IX9ECParameters; override;
       function CreateParameters(): IX9ECParameters; override;
@@ -720,10 +726,10 @@ type
 
 
     strict private
     strict private
     const
     const
-      Fm = Int32(571);
-      Fk1 = Int32(2);
-      Fk2 = Int32(5);
-      Fk3 = Int32(10);
+      M = Int32(571);
+      K1 = Int32(2);
+      K2 = Int32(5);
+      K3 = Int32(10);
 
 
     strict protected
     strict protected
       function CreateParameters(): IX9ECParameters; override;
       function CreateParameters(): IX9ECParameters; override;
@@ -739,6 +745,13 @@ implementation
 
 
 { TSecNamedCurves }
 { TSecNamedCurves }
 
 
+class function TSecNamedCurves.ConfigureBasepoint(const curve: IECCurve;
+  const encoding: String): IX9ECPoint;
+begin
+  result := TX9ECPoint.Create(curve, THex.Decode(encoding));
+  TWnafUtilities.ConfigureBasepoint(result.Point);
+end;
+
 class procedure TSecNamedCurves.DefineCurve(const name: String;
 class procedure TSecNamedCurves.DefineCurve(const name: String;
   const oid: IDerObjectIdentifier; const holder: IX9ECParametersHolder);
   const oid: IDerObjectIdentifier; const holder: IX9ECParametersHolder);
 begin
 begin
@@ -922,9 +935,8 @@ begin
   h := TBigInteger.One;
   h := TBigInteger.One;
 
 
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + '09487239995A5EE76B55F9C2F098' +
-    'A89CE5AF8724C0A23E0E0FF77500'));
+  G := ConfigureBasepoint(curve,
+    '0409487239995A5EE76B55F9C2F098A89CE5AF8724C0A23E0E0FF77500');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -952,9 +964,8 @@ begin
   h := TBigInteger.ValueOf(4);
   h := TBigInteger.ValueOf(4);
 
 
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + '4BA30AB5E892B4E1649DD0928643' +
-    'ADCD46F5882E3747DEF36E956E97'));
+  G := ConfigureBasepoint(curve,
+    '044BA30AB5E892B4E1649DD0928643ADCD46F5882E3747DEF36E956E97');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -982,9 +993,8 @@ begin
   h := TBigInteger.One;
   h := TBigInteger.One;
 
 
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + '161FF7528B899B2D0C28607CA52C5B86' +
-    'CF5AC8395BAFEB13C02DA292DDED7A83'));
+  G := ConfigureBasepoint(curve,
+    '04161FF7528B899B2D0C28607CA52C5B86CF5AC8395BAFEB13C02DA292DDED7A83');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1012,9 +1022,8 @@ begin
   h := TBigInteger.ValueOf(4);
   h := TBigInteger.ValueOf(4);
 
 
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + '7B6AA5D85E572983E6FB32A7CDEBC140' +
-    '27B6916A894D3AEE7106FE805FC34B44'));
+  G := ConfigureBasepoint(curve,
+    '047B6AA5D85E572983E6FB32A7CDEBC14027B6916A894D3AEE7106FE805FC34B44');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1045,19 +1054,20 @@ begin
   glv := TGlvTypeBParameters.Create
   glv := TGlvTypeBParameters.Create
     (TBigInteger.Create('9ba48cba5ebcb9b6bd33b92830b2a2e0e192f10a', 16),
     (TBigInteger.Create('9ba48cba5ebcb9b6bd33b92830b2a2e0e192f10a', 16),
     TBigInteger.Create('c39c6c3b3a36d7701b9c71a1f5804ae5d0003f4', 16),
     TBigInteger.Create('c39c6c3b3a36d7701b9c71a1f5804ae5d0003f4', 16),
-    TCryptoLibGenericArray<TBigInteger>.Create
+
+    TScalarSplitParameters.Create(TCryptoLibGenericArray<TBigInteger>.Create
     (TBigInteger.Create('9162fbe73984472a0a9e', 16),
     (TBigInteger.Create('9162fbe73984472a0a9e', 16),
     TBigInteger.Create('-96341f1138933bc2f505', 16)),
     TBigInteger.Create('-96341f1138933bc2f505', 16)),
-    TCryptoLibGenericArray<TBigInteger>.Create
-    (TBigInteger.Create('127971af8721782ecffa3', 16),
-    TBigInteger.Create('9162fbe73984472a0a9e', 16)),
-    TBigInteger.Create('9162fbe73984472a0a9d0590', 16),
-    TBigInteger.Create('96341f1138933bc2f503fd44', 16), 176);
+
+    TCryptoLibGenericArray<TBigInteger>.Create(TBigInteger.Create
+    ('127971af8721782ecffa3', 16), TBigInteger.Create('9162fbe73984472a0a9e',
+    16)), TBigInteger.Create('9162fbe73984472a0a9d0590', 16),
+    TBigInteger.Create('96341f1138933bc2f503fd44', 16), 176)
+    as IScalarSplitParameters);
 
 
   curve := ConfigureCurveGlv(TFpCurve.Create(p, a, b, n, h) as IFpCurve, glv);
   curve := ConfigureCurveGlv(TFpCurve.Create(p, a, b, n, h) as IFpCurve, glv);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + '3B4C382CE37AA192A4019E763036F4F5DD4D7EBB' +
-    '938CF935318FDCED6BC28286531733C3F03C4FEE'));
+  G := ConfigureBasepoint(curve,
+    '043B4C382CE37AA192A4019E763036F4F5DD4D7EBB938CF935318FDCED6BC28286531733C3F03C4FEE');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1085,9 +1095,8 @@ begin
   h := TBigInteger.One;
   h := TBigInteger.One;
 
 
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + '4A96B5688EF573284664698968C38BB913CBFC82' +
-    '23A628553168947D59DCC912042351377AC5FB32'));
+  G := ConfigureBasepoint(curve,
+    '044A96B5688EF573284664698968C38BB913CBFC8223A628553168947D59DCC912042351377AC5FB32');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1115,9 +1124,8 @@ begin
   h := TBigInteger.One;
   h := TBigInteger.One;
 
 
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + '52DCB034293A117E1F4FF11B30F7199D3144CE6D' +
-    'FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E'));
+  G := ConfigureBasepoint(curve,
+    '0452DCB034293A117E1F4FF11B30F7199D3144CE6DFEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1148,19 +1156,20 @@ begin
   glv := TGlvTypeBParameters.Create
   glv := TGlvTypeBParameters.Create
     (TBigInteger.Create('bb85691939b869c1d087f601554b96b80cb4f55b35f433c2', 16),
     (TBigInteger.Create('bb85691939b869c1d087f601554b96b80cb4f55b35f433c2', 16),
     TBigInteger.Create('3d84f26c12238d7b4f3d516613c1759033b1a5800175d0b1', 16),
     TBigInteger.Create('3d84f26c12238d7b4f3d516613c1759033b1a5800175d0b1', 16),
-    TCryptoLibGenericArray<TBigInteger>.Create
+
+    TScalarSplitParameters.Create(TCryptoLibGenericArray<TBigInteger>.Create
     (TBigInteger.Create('71169be7330b3038edb025f1', 16),
     (TBigInteger.Create('71169be7330b3038edb025f1', 16),
     TBigInteger.Create('-b3fb3400dec5c4adceb8655c', 16)),
     TBigInteger.Create('-b3fb3400dec5c4adceb8655c', 16)),
-    TCryptoLibGenericArray<TBigInteger>.Create
-    (TBigInteger.Create('12511cfe811d0f4e6bc688b4d', 16),
+    TCryptoLibGenericArray<TBigInteger>.Create(TBigInteger.Create
+    ('12511cfe811d0f4e6bc688b4d', 16),
     TBigInteger.Create('71169be7330b3038edb025f1', 16)),
     TBigInteger.Create('71169be7330b3038edb025f1', 16)),
     TBigInteger.Create('71169be7330b3038edb025f1d0f9', 16),
     TBigInteger.Create('71169be7330b3038edb025f1d0f9', 16),
-    TBigInteger.Create('b3fb3400dec5c4adceb8655d4c94', 16), 208);
+    TBigInteger.Create('b3fb3400dec5c4adceb8655d4c94', 16), 208)
+    as IScalarSplitParameters);
 
 
   curve := ConfigureCurveGlv(TFpCurve.Create(p, a, b, n, h) as IFpCurve, glv);
   curve := ConfigureCurveGlv(TFpCurve.Create(p, a, b, n, h) as IFpCurve, glv);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + 'DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D' +
-    '9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D'));
+  G := ConfigureBasepoint(curve,
+    '04DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1188,9 +1197,8 @@ begin
   h := TBigInteger.One;
   h := TBigInteger.One;
 
 
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + '188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012' +
-    '07192B95FFC8DA78631011ED6B24CDD573F977A11E794811'));
+  G := ConfigureBasepoint(curve,
+    '04188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E794811');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1223,20 +1231,19 @@ begin
     ('fe0e87005b4e83761908c5131d552a850b3f58b749c37cf5b84d6768', 16),
     ('fe0e87005b4e83761908c5131d552a850b3f58b749c37cf5b84d6768', 16),
     TBigInteger.Create
     TBigInteger.Create
     ('60dcd2104c4cbc0be6eeefc2bdd610739ec34e317f9b33046c9e4788', 16),
     ('60dcd2104c4cbc0be6eeefc2bdd610739ec34e317f9b33046c9e4788', 16),
-    TCryptoLibGenericArray<TBigInteger>.Create
+    TScalarSplitParameters.Create(TCryptoLibGenericArray<TBigInteger>.Create
     (TBigInteger.Create('6b8cf07d4ca75c88957d9d670591', 16),
     (TBigInteger.Create('6b8cf07d4ca75c88957d9d670591', 16),
     TBigInteger.Create('-b8adf1378a6eb73409fa6c9c637d', 16)),
     TBigInteger.Create('-b8adf1378a6eb73409fa6c9c637d', 16)),
-    TCryptoLibGenericArray<TBigInteger>.Create
-    (TBigInteger.Create('1243ae1b4d71613bc9f780a03690e', 16),
+    TCryptoLibGenericArray<TBigInteger>.Create(TBigInteger.Create
+    ('1243ae1b4d71613bc9f780a03690e', 16),
     TBigInteger.Create('6b8cf07d4ca75c88957d9d670591', 16)),
     TBigInteger.Create('6b8cf07d4ca75c88957d9d670591', 16)),
     TBigInteger.Create('6b8cf07d4ca75c88957d9d67059037a4', 16),
     TBigInteger.Create('6b8cf07d4ca75c88957d9d67059037a4', 16),
-    TBigInteger.Create('b8adf1378a6eb73409fa6c9c637ba7f5', 16), 240);
+    TBigInteger.Create('b8adf1378a6eb73409fa6c9c637ba7f5', 16), 240)
+    as IScalarSplitParameters);
 
 
   curve := ConfigureCurveGlv(TFpCurve.Create(p, a, b, n, h) as IFpCurve, glv);
   curve := ConfigureCurveGlv(TFpCurve.Create(p, a, b, n, h) as IFpCurve, glv);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    'A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C' +
-    '7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5'));
+  G := ConfigureBasepoint(curve,
+    '04A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1264,10 +1271,8 @@ begin
   h := TBigInteger.One;
   h := TBigInteger.One;
 
 
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    'B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21' +
-    'BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34'));
+  G := ConfigureBasepoint(curve,
+    '04B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1302,20 +1307,20 @@ begin
     ('7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', 16),
     ('7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', 16),
     TBigInteger.Create
     TBigInteger.Create
     ('5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', 16),
     ('5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', 16),
-    TCryptoLibGenericArray<TBigInteger>.Create
+
+    TScalarSplitParameters.Create(TCryptoLibGenericArray<TBigInteger>.Create
     (TBigInteger.Create('3086d221a7d46bcde86c90e49284eb15', 16),
     (TBigInteger.Create('3086d221a7d46bcde86c90e49284eb15', 16),
     TBigInteger.Create('-e4437ed6010e88286f547fa90abfe4c3', 16)),
     TBigInteger.Create('-e4437ed6010e88286f547fa90abfe4c3', 16)),
-    TCryptoLibGenericArray<TBigInteger>.Create
-    (TBigInteger.Create('114ca50f7a8e2f3f657c1108d9d44cfd8', 16),
+    TCryptoLibGenericArray<TBigInteger>.Create(TBigInteger.Create
+    ('114ca50f7a8e2f3f657c1108d9d44cfd8', 16),
     TBigInteger.Create('3086d221a7d46bcde86c90e49284eb15', 16)),
     TBigInteger.Create('3086d221a7d46bcde86c90e49284eb15', 16)),
     TBigInteger.Create('3086d221a7d46bcde86c90e49284eb153dab', 16),
     TBigInteger.Create('3086d221a7d46bcde86c90e49284eb153dab', 16),
-    TBigInteger.Create('e4437ed6010e88286f547fa90abfe4c42212', 16), 272);
+    TBigInteger.Create('e4437ed6010e88286f547fa90abfe4c42212', 16), 272)
+    as IScalarSplitParameters);
 
 
   curve := ConfigureCurveGlv(TFpCurve.Create(p, a, b, n, h) as IFpCurve, glv);
   curve := ConfigureCurveGlv(TFpCurve.Create(p, a, b, n, h) as IFpCurve, glv);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    '79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798' +
-    '483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8'));
+  G := ConfigureBasepoint(curve,
+    '0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1347,10 +1352,8 @@ begin
   h := TBigInteger.One;
   h := TBigInteger.One;
 
 
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    '6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296' +
-    '4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5'));
+  G := ConfigureBasepoint(curve,
+    '046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1382,11 +1385,9 @@ begin
   h := TBigInteger.One;
   h := TBigInteger.One;
 
 
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    'AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7'
-    + '3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F')
-    );
+  G := ConfigureBasepoint(curve,
+    '04' + 'AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7'
+    + '3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1418,11 +1419,9 @@ begin
   h := TBigInteger.One;
   h := TBigInteger.One;
 
 
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
   curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h) as IFpCurve);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    '00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66'
-    + '011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650')
-    );
+  G := ConfigureBasepoint(curve,
+    '04' + '00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66'
+    + '011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1447,10 +1446,9 @@ begin
   n := FromHex('0100000000000000D9CCEC8A39E56F');
   n := FromHex('0100000000000000D9CCEC8A39E56F');
   h := TBigInteger.ValueOf(2);
   h := TBigInteger.ValueOf(2);
 
 
-  curve := TF2mCurve.Create(Fm, Fk, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + '009D73616F35F4AB1407D73562C10F' +
-    '00A52830277958EE84D1315ED31886'));
+  curve := ConfigureCurve(TF2mCurve.Create(M, Fk, a, b, n, h) as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '04009D73616F35F4AB1407D73562C10F00A52830277958EE84D1315ED31886');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1475,10 +1473,9 @@ begin
   n := FromHex('010000000000000108789B2496AF93');
   n := FromHex('010000000000000108789B2496AF93');
   h := TBigInteger.ValueOf(2);
   h := TBigInteger.ValueOf(2);
 
 
-  curve := TF2mCurve.Create(Fm, Fk, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + '01A57A6A7B26CA5EF52FCDB8164797' +
-    '00B3ADC94ED1FE674C06E695BABA1D'));
+  curve := ConfigureCurve(TF2mCurve.Create(M, Fk, a, b, n, h) as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '0401A57A6A7B26CA5EF52FCDB816479700B3ADC94ED1FE674C06E695BABA1D');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1503,10 +1500,10 @@ begin
   n := FromHex('0400000000000000023123953A9464B54D');
   n := FromHex('0400000000000000023123953A9464B54D');
   h := TBigInteger.ValueOf(2);
   h := TBigInteger.ValueOf(2);
 
 
-  curve := TF2mCurve.Create(Fm, Fk1, Fk2, Fk3, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + '0081BAF91FDF9833C40F9C181343638399' +
-    '078C6E7EA38C001F73C8134B1B4EF9E150'));
+  curve := ConfigureCurve(TF2mCurve.Create(M, K1, K2, K3, a, b, n, h)
+    as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '040081BAF91FDF9833C40F9C181343638399078C6E7EA38C001F73C8134B1B4EF9E150');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1531,10 +1528,10 @@ begin
   n := FromHex('0400000000000000016954A233049BA98F');
   n := FromHex('0400000000000000016954A233049BA98F');
   h := TBigInteger.ValueOf(2);
   h := TBigInteger.ValueOf(2);
 
 
-  curve := TF2mCurve.Create(Fm, Fk1, Fk2, Fk3, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + '0356DCD8F2F95031AD652D23951BB366A8' +
-    '0648F06D867940A5366D9E265DE9EB240F'));
+  curve := ConfigureCurve(TF2mCurve.Create(M, K1, K2, K3, a, b, n, h)
+    as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '040356DCD8F2F95031AD652D23951BB366A80648F06D867940A5366D9E265DE9EB240F');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1559,10 +1556,10 @@ begin
   n := FromHex('04000000000000000000020108A2E0CC0D99F8A5EF');
   n := FromHex('04000000000000000000020108A2E0CC0D99F8A5EF');
   h := TBigInteger.ValueOf(2);
   h := TBigInteger.ValueOf(2);
 
 
-  curve := TF2mCurve.Create(Fm, Fk1, Fk2, Fk3, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + '02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8' +
-    '0289070FB05D38FF58321F2E800536D538CCDAA3D9'));
+  curve := ConfigureCurve(TF2mCurve.Create(M, K1, K2, K3, a, b, n, h)
+    as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '0402FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE80289070FB05D38FF58321F2E800536D538CCDAA3D9');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1587,10 +1584,10 @@ begin
   n := FromHex('03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B');
   n := FromHex('03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B');
   h := TBigInteger.ValueOf(2);
   h := TBigInteger.ValueOf(2);
 
 
-  curve := TF2mCurve.Create(Fm, Fk1, Fk2, Fk3, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + '0369979697AB43897789566789567F787A7876A654' +
-    '00435EDB42EFAFB2989D51FEFCE3C80988F41FF883'));
+  curve := ConfigureCurve(TF2mCurve.Create(M, K1, K2, K3, a, b, n, h)
+    as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '040369979697AB43897789566789567F787A7876A65400435EDB42EFAFB2989D51FEFCE3C80988F41FF883');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1615,10 +1612,10 @@ begin
   n := FromHex('040000000000000000000292FE77E70C12A4234C33');
   n := FromHex('040000000000000000000292FE77E70C12A4234C33');
   h := TBigInteger.ValueOf(2);
   h := TBigInteger.ValueOf(2);
 
 
-  curve := TF2mCurve.Create(Fm, Fk1, Fk2, Fk3, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + '03F0EBA16286A2D57EA0991168D4994637E8343E36' +
-    '00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1'));
+  curve := ConfigureCurve(TF2mCurve.Create(M, K1, K2, K3, a, b, n, h)
+    as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '0403F0EBA16286A2D57EA0991168D4994637E8343E3600D51FBC6C71A0094FA2CDD545B11C5C0C797324F1');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1643,10 +1640,9 @@ begin
   n := FromHex('01000000000000000000000000C7F34A778F443ACC920EBA49');
   n := FromHex('01000000000000000000000000C7F34A778F443ACC920EBA49');
   h := TBigInteger.ValueOf(2);
   h := TBigInteger.ValueOf(2);
 
 
-  curve := TF2mCurve.Create(Fm, Fk, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + '01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1' +
-    '0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05'));
+  curve := ConfigureCurve(TF2mCurve.Create(M, Fk, a, b, n, h) as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '0401F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E10025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1671,10 +1667,9 @@ begin
   n := FromHex('010000000000000000000000015AAB561B005413CCD4EE99D5');
   n := FromHex('010000000000000000000000015AAB561B005413CCD4EE99D5');
   h := TBigInteger.ValueOf(2);
   h := TBigInteger.ValueOf(2);
 
 
-  curve := TF2mCurve.Create(Fm, Fk, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' + '00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F' +
-    '01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C'));
+  curve := ConfigureCurve(TF2mCurve.Create(M, Fk, a, b, n, h) as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '0400D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1699,11 +1694,9 @@ begin
   n := FromHex('8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF');
   n := FromHex('8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF');
   h := TBigInteger.ValueOf(4);
   h := TBigInteger.ValueOf(4);
 
 
-  curve := TF2mCurve.Create(Fm, Fk, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    '017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126' +
-    '01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3'));
+  curve := ConfigureCurve(TF2mCurve.Create(M, Fk, a, b, n, h) as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '04017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD612601DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1728,11 +1721,9 @@ begin
   n := FromHex('01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7');
   n := FromHex('01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7');
   h := TBigInteger.ValueOf(2);
   h := TBigInteger.ValueOf(2);
 
 
-  curve := TF2mCurve.Create(Fm, Fk, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    '00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B' +
-    '01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052'));
+  curve := ConfigureCurve(TF2mCurve.Create(M, Fk, a, b, n, h) as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '0400FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1757,11 +1748,9 @@ begin
   n := FromHex('2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5');
   n := FromHex('2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5');
   h := TBigInteger.ValueOf(4);
   h := TBigInteger.ValueOf(4);
 
 
-  curve := TF2mCurve.Create(Fm, Fk, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    '29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC' +
-    '76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA'));
+  curve := ConfigureCurve(TF2mCurve.Create(M, Fk, a, b, n, h) as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '0429A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1787,12 +1776,11 @@ begin
     ('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61');
     ('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61');
   h := TBigInteger.ValueOf(4);
   h := TBigInteger.ValueOf(4);
 
 
-  curve := TF2mCurve.Create(Fm, Fk1, Fk2, Fk3, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    '0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836' +
-    '01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259')
-    );
+  curve := ConfigureCurve(TF2mCurve.Create(M, K1, K2, K3, a, b, n, h)
+    as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '04' + '0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836'
+    + '01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1819,12 +1807,11 @@ begin
     ('03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307');
     ('03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307');
   h := TBigInteger.ValueOf(2);
   h := TBigInteger.ValueOf(2);
 
 
-  curve := TF2mCurve.Create(Fm, Fk1, Fk2, Fk3, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    '05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053' +
-    '03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4')
-    );
+  curve := ConfigureCurve(TF2mCurve.Create(M, K1, K2, K3, a, b, n, h)
+    as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '04' + '05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053'
+    + '03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1850,12 +1837,10 @@ begin
     ('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF');
     ('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF');
   h := TBigInteger.ValueOf(4);
   h := TBigInteger.ValueOf(4);
 
 
-  curve := TF2mCurve.Create(Fm, Fk, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    '0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746'
-    + '01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B')
-    );
+  curve := ConfigureCurve(TF2mCurve.Create(M, Fk, a, b, n, h) as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '04' + '0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746'
+    + '01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1882,12 +1867,10 @@ begin
     ('010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173');
     ('010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173');
   h := TBigInteger.ValueOf(2);
   h := TBigInteger.ValueOf(2);
 
 
-  curve := TF2mCurve.Create(Fm, Fk, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    '015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7'
-    + '0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706')
-    );
+  curve := ConfigureCurve(TF2mCurve.Create(M, Fk, a, b, n, h) as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '04' + '015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7'
+    + '0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1913,12 +1896,11 @@ begin
     ('020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001');
     ('020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001');
   h := TBigInteger.ValueOf(4);
   h := TBigInteger.ValueOf(4);
 
 
-  curve := TF2mCurve.Create(Fm, Fk1, Fk2, Fk3, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    '026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972'
-    + '0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3')
-    );
+  curve := ConfigureCurve(TF2mCurve.Create(M, K1, K2, K3, a, b, n, h)
+    as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '04' + '026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972'
+    + '0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;
@@ -1945,12 +1927,11 @@ begin
     ('03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47');
     ('03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47');
   h := TBigInteger.ValueOf(2);
   h := TBigInteger.ValueOf(2);
 
 
-  curve := TF2mCurve.Create(Fm, Fk1, Fk2, Fk3, a, b, n, h);
-  G := TX9ECPoint.Create(curve,
-    THex.Decode('04' +
-    '0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19'
-    + '037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B')
-    );
+  curve := ConfigureCurve(TF2mCurve.Create(M, K1, K2, K3, a, b, n, h)
+    as IF2mCurve);
+  G := ConfigureBasepoint(curve,
+    '04' + '0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19'
+    + '037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B');
 
 
   result := TX9ECParameters.Create(curve, G, n, h, S);
   result := TX9ECParameters.Create(curve, G, n, h, S);
 end;
 end;

+ 48 - 22
src/libraries/cryptolib4pascal/ClpSecP256K1Custom.pas

@@ -211,8 +211,8 @@ type
   strict private
   strict private
 
 
   type
   type
-    TSecP256K1LookupTable = class sealed(TInterfacedObject,
-      ISecP256K1LookupTable, IECLookupTable)
+    TSecP256K1LookupTable = class sealed(TAbstractECLookupTable,
+      ISecP256K1LookupTable)
 
 
     strict private
     strict private
     var
     var
@@ -220,16 +220,19 @@ type
       Fm_table: TCryptoLibUInt32Array;
       Fm_table: TCryptoLibUInt32Array;
       Fm_size: Int32;
       Fm_size: Int32;
 
 
-      function GetSize: Int32; virtual;
+      function CreatePoint(const x, y: TCryptoLibUInt32Array): IECPoint;
+
+    strict protected
+
+      function GetSize: Int32; override;
 
 
     public
     public
 
 
       constructor Create(const outer: ISecP256K1Curve;
       constructor Create(const outer: ISecP256K1Curve;
         const table: TCryptoLibUInt32Array; size: Int32);
         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;
     end;
 
 
@@ -240,8 +243,6 @@ type
   var
   var
     Fq: TBigInteger;
     Fq: TBigInteger;
 
 
-    class function GetSecP256K1Curve_Q: TBigInteger; static; inline;
-
   strict protected
   strict protected
   var
   var
     Fm_infinity: ISecP256K1Point;
     Fm_infinity: ISecP256K1Point;
@@ -273,8 +274,6 @@ type
     property Infinity: IECPoint read GetInfinity;
     property Infinity: IECPoint read GetInfinity;
     property FieldSize: Int32 read GetFieldSize;
     property FieldSize: Int32 read GetFieldSize;
 
 
-    class property SecP256K1Curve_Q: TBigInteger read GetSecP256K1Curve_Q;
-
   end;
   end;
 
 
 implementation
 implementation
@@ -500,7 +499,9 @@ end;
 
 
 class function TSecP256K1FieldElement.GetQ: TBigInteger;
 class function TSecP256K1FieldElement.GetQ: TBigInteger;
 begin
 begin
-  result := TSecP256K1Curve.SecP256K1Curve_Q;
+  result := TBigInteger.Create(1,
+    THex.Decode
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F'));
 end;
 end;
 
 
 function TSecP256K1FieldElement.GetX: TCryptoLibUInt32Array;
 function TSecP256K1FieldElement.GetX: TCryptoLibUInt32Array;
@@ -1032,16 +1033,9 @@ end;
 
 
 { TSecP256K1Curve }
 { TSecP256K1Curve }
 
 
-class function TSecP256K1Curve.GetSecP256K1Curve_Q: TBigInteger;
-begin
-  result := TBigInteger.Create(1,
-    THex.Decode
-    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F'));
-end;
-
 constructor TSecP256K1Curve.Create;
 constructor TSecP256K1Curve.Create;
 begin
 begin
-  Fq := SecP256K1Curve_Q;
+  Fq := TSecP256K1FieldElement.Q;
   Inherited Create(Fq);
   Inherited Create(Fq);
   Fm_infinity := TSecP256K1Point.Create(Self as IECCurve, Nil, Nil);
   Fm_infinity := TSecP256K1Point.Create(Self as IECCurve, Nil, Nil);
   Fm_a := FromBigInteger(TBigInteger.Zero);
   Fm_a := FromBigInteger(TBigInteger.Zero);
@@ -1135,6 +1129,21 @@ begin
   Fm_size := size;
   Fm_size := size;
 end;
 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;
 function TSecP256K1Curve.TSecP256K1LookupTable.GetSize: Int32;
 begin
 begin
   result := Fm_size;
   result := Fm_size;
@@ -1163,9 +1172,26 @@ begin
     pos := pos + (SECP256K1_FE_INTS * 2);
     pos := pos + (SECP256K1_FE_INTS * 2);
   end;
   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;
 
 
 end.
 end.

+ 48 - 22
src/libraries/cryptolib4pascal/ClpSecP256R1Custom.pas

@@ -212,8 +212,8 @@ type
   strict private
   strict private
 
 
   type
   type
-    TSecP256R1LookupTable = class sealed(TInterfacedObject,
-      ISecP256R1LookupTable, IECLookupTable)
+    TSecP256R1LookupTable = class sealed(TAbstractECLookupTable,
+      ISecP256R1LookupTable)
 
 
     strict private
     strict private
     var
     var
@@ -221,16 +221,19 @@ type
       Fm_table: TCryptoLibUInt32Array;
       Fm_table: TCryptoLibUInt32Array;
       Fm_size: Int32;
       Fm_size: Int32;
 
 
-      function GetSize: Int32; virtual;
+      function CreatePoint(const x, y: TCryptoLibUInt32Array): IECPoint;
+
+    strict protected
+
+      function GetSize: Int32; override;
 
 
     public
     public
 
 
       constructor Create(const outer: ISecP256R1Curve;
       constructor Create(const outer: ISecP256R1Curve;
         const table: TCryptoLibUInt32Array; size: Int32);
         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;
     end;
 
 
@@ -241,8 +244,6 @@ type
   var
   var
     Fq: TBigInteger;
     Fq: TBigInteger;
 
 
-    class function GetSecP256R1Curve_Q: TBigInteger; static; inline;
-
   strict protected
   strict protected
   var
   var
     Fm_infinity: ISecP256R1Point;
     Fm_infinity: ISecP256R1Point;
@@ -274,8 +275,6 @@ type
     property Infinity: IECPoint read GetInfinity;
     property Infinity: IECPoint read GetInfinity;
     property FieldSize: Int32 read GetFieldSize;
     property FieldSize: Int32 read GetFieldSize;
 
 
-    class property SecP256R1Curve_Q: TBigInteger read GetSecP256R1Curve_Q;
-
   end;
   end;
 
 
 implementation
 implementation
@@ -650,7 +649,9 @@ end;
 
 
 class function TSecP256R1FieldElement.GetQ: TBigInteger;
 class function TSecP256R1FieldElement.GetQ: TBigInteger;
 begin
 begin
-  result := TSecP256R1Curve.SecP256R1Curve_Q;
+  result := TBigInteger.Create(1,
+    THex.Decode
+    ('FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF'));
 end;
 end;
 
 
 function TSecP256R1FieldElement.GetX: TCryptoLibUInt32Array;
 function TSecP256R1FieldElement.GetX: TCryptoLibUInt32Array;
@@ -1171,16 +1172,9 @@ end;
 
 
 { TSecP256R1Curve }
 { TSecP256R1Curve }
 
 
-class function TSecP256R1Curve.GetSecP256R1Curve_Q: TBigInteger;
-begin
-  result := TBigInteger.Create(1,
-    THex.Decode
-    ('FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF'));
-end;
-
 constructor TSecP256R1Curve.Create;
 constructor TSecP256R1Curve.Create;
 begin
 begin
-  Fq := SecP256R1Curve_Q;
+  Fq := TSecP256R1FieldElement.Q;
   Inherited Create(Fq);
   Inherited Create(Fq);
   Fm_infinity := TSecP256R1Point.Create(Self as IECCurve, Nil, Nil);
   Fm_infinity := TSecP256R1Point.Create(Self as IECCurve, Nil, Nil);
   Fm_a := FromBigInteger(TBigInteger.Create(1,
   Fm_a := FromBigInteger(TBigInteger.Create(1,
@@ -1278,6 +1272,21 @@ begin
   Fm_size := size;
   Fm_size := size;
 end;
 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;
 function TSecP256R1Curve.TSecP256R1LookupTable.GetSize: Int32;
 begin
 begin
   result := Fm_size;
   result := Fm_size;
@@ -1306,9 +1315,26 @@ begin
     pos := pos + (SECP256R1_FE_INTS * 2);
     pos := pos + (SECP256R1_FE_INTS * 2);
   end;
   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;
 
 
 end.
 end.

+ 49 - 23
src/libraries/cryptolib4pascal/ClpSecP384R1Custom.pas

@@ -210,8 +210,8 @@ type
   strict private
   strict private
 
 
   type
   type
-    TSecP384R1LookupTable = class sealed(TInterfacedObject,
-      ISecP384R1LookupTable, IECLookupTable)
+    TSecP384R1LookupTable = class sealed(TAbstractECLookupTable,
+      ISecP384R1LookupTable)
 
 
     strict private
     strict private
     var
     var
@@ -219,16 +219,19 @@ type
       Fm_table: TCryptoLibUInt32Array;
       Fm_table: TCryptoLibUInt32Array;
       Fm_size: Int32;
       Fm_size: Int32;
 
 
-      function GetSize: Int32; virtual;
+      function CreatePoint(const x, y: TCryptoLibUInt32Array): IECPoint;
+
+    strict protected
+
+      function GetSize: Int32; override;
 
 
     public
     public
 
 
       constructor Create(const outer: ISecP384R1Curve;
       constructor Create(const outer: ISecP384R1Curve;
         const table: TCryptoLibUInt32Array; size: Int32);
         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;
     end;
 
 
@@ -239,8 +242,6 @@ type
   var
   var
     Fq: TBigInteger;
     Fq: TBigInteger;
 
 
-    class function GetSecP384R1Curve_Q: TBigInteger; static; inline;
-
   strict protected
   strict protected
   var
   var
     Fm_infinity: ISecP384R1Point;
     Fm_infinity: ISecP384R1Point;
@@ -272,8 +273,6 @@ type
     property Infinity: IECPoint read GetInfinity;
     property Infinity: IECPoint read GetInfinity;
     property FieldSize: Int32 read GetFieldSize;
     property FieldSize: Int32 read GetFieldSize;
 
 
-    class property SecP384R1Curve_Q: TBigInteger read GetSecP384R1Curve_Q;
-
   end;
   end;
 
 
 implementation
 implementation
@@ -631,7 +630,10 @@ end;
 
 
 class function TSecP384R1FieldElement.GetQ: TBigInteger;
 class function TSecP384R1FieldElement.GetQ: TBigInteger;
 begin
 begin
-  result := TSecP384R1Curve.SecP384R1Curve_Q;
+  result := TBigInteger.Create(1,
+    THex.Decode
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF')
+    );
 end;
 end;
 
 
 function TSecP384R1FieldElement.GetX: TCryptoLibUInt32Array;
 function TSecP384R1FieldElement.GetX: TCryptoLibUInt32Array;
@@ -1173,17 +1175,9 @@ end;
 
 
 { TSecP384R1Curve }
 { TSecP384R1Curve }
 
 
-class function TSecP384R1Curve.GetSecP384R1Curve_Q: TBigInteger;
-begin
-  result := TBigInteger.Create(1,
-    THex.Decode
-    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF')
-    );
-end;
-
 constructor TSecP384R1Curve.Create;
 constructor TSecP384R1Curve.Create;
 begin
 begin
-  Fq := SecP384R1Curve_Q;
+  Fq := TSecP384R1FieldElement.Q;
   Inherited Create(Fq);
   Inherited Create(Fq);
   Fm_infinity := TSecP384R1Point.Create(Self as IECCurve, Nil, Nil);
   Fm_infinity := TSecP384R1Point.Create(Self as IECCurve, Nil, Nil);
   Fm_a := FromBigInteger(TBigInteger.Create(1,
   Fm_a := FromBigInteger(TBigInteger.Create(1,
@@ -1286,6 +1280,21 @@ begin
   Fm_size := size;
   Fm_size := size;
 end;
 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;
 function TSecP384R1Curve.TSecP384R1LookupTable.GetSize: Int32;
 begin
 begin
   result := Fm_size;
   result := Fm_size;
@@ -1314,9 +1323,26 @@ begin
     pos := pos + (SECP384R1_FE_INTS * 2);
     pos := pos + (SECP384R1_FE_INTS * 2);
   end;
   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;
 
 
 end.
 end.

+ 48 - 22
src/libraries/cryptolib4pascal/ClpSecP521R1Custom.pas

@@ -207,7 +207,7 @@ type
   strict private
   strict private
 
 
   type
   type
-    TSecP521R1LookupTable = class sealed(TInterfacedObject,
+    TSecP521R1LookupTable = class sealed(TAbstractECLookupTable,
       ISecP521R1LookupTable, IECLookupTable)
       ISecP521R1LookupTable, IECLookupTable)
 
 
     strict private
     strict private
@@ -216,16 +216,19 @@ type
       Fm_table: TCryptoLibUInt32Array;
       Fm_table: TCryptoLibUInt32Array;
       Fm_size: Int32;
       Fm_size: Int32;
 
 
-      function GetSize: Int32; virtual;
+      function CreatePoint(const x, y: TCryptoLibUInt32Array): IECPoint;
+
+    strict protected
+
+      function GetSize: Int32; override;
 
 
     public
     public
 
 
       constructor Create(const outer: ISecP521R1Curve;
       constructor Create(const outer: ISecP521R1Curve;
         const table: TCryptoLibUInt32Array; size: Int32);
         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;
     end;
 
 
@@ -236,8 +239,6 @@ type
   var
   var
     Fq: TBigInteger;
     Fq: TBigInteger;
 
 
-    class function GetSecP521R1Curve_Q: TBigInteger; static; inline;
-
   strict protected
   strict protected
   var
   var
     Fm_infinity: ISecP521R1Point;
     Fm_infinity: ISecP521R1Point;
@@ -269,8 +270,6 @@ type
     property Infinity: IECPoint read GetInfinity;
     property Infinity: IECPoint read GetInfinity;
     property FieldSize: Int32 read GetFieldSize;
     property FieldSize: Int32 read GetFieldSize;
 
 
-    class property SecP521R1Curve_Q: TBigInteger read GetSecP521R1Curve_Q;
-
   end;
   end;
 
 
 implementation
 implementation
@@ -472,7 +471,10 @@ end;
 
 
 class function TSecP521R1FieldElement.GetQ: TBigInteger;
 class function TSecP521R1FieldElement.GetQ: TBigInteger;
 begin
 begin
-  result := TSecP521R1Curve.SecP521R1Curve_Q;
+  result := TBigInteger.Create(1,
+    THex.Decode
+    ('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF')
+    );
 end;
 end;
 
 
 function TSecP521R1FieldElement.GetX: TCryptoLibUInt32Array;
 function TSecP521R1FieldElement.GetX: TCryptoLibUInt32Array;
@@ -966,17 +968,9 @@ end;
 
 
 { TSecP521R1Curve }
 { TSecP521R1Curve }
 
 
-class function TSecP521R1Curve.GetSecP521R1Curve_Q: TBigInteger;
-begin
-  result := TBigInteger.Create(1,
-    THex.Decode
-    ('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF')
-    );
-end;
-
 constructor TSecP521R1Curve.Create;
 constructor TSecP521R1Curve.Create;
 begin
 begin
-  Fq := SecP521R1Curve_Q;
+  Fq := TSecP521R1FieldElement.Q;
   Inherited Create(Fq);
   Inherited Create(Fq);
   Fm_infinity := TSecP521R1Point.Create(Self as IECCurve, Nil, Nil);
   Fm_infinity := TSecP521R1Point.Create(Self as IECCurve, Nil, Nil);
   Fm_a := FromBigInteger(TBigInteger.Create(1,
   Fm_a := FromBigInteger(TBigInteger.Create(1,
@@ -1079,6 +1073,21 @@ begin
   Fm_size := size;
   Fm_size := size;
 end;
 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;
 function TSecP521R1Curve.TSecP521R1LookupTable.GetSize: Int32;
 begin
 begin
   result := Fm_size;
   result := Fm_size;
@@ -1107,9 +1116,26 @@ begin
     pos := pos + (SECP521R1_FE_INTS * 2);
     pos := pos + (SECP521R1_FE_INTS * 2);
   end;
   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;
 
 
 end.
 end.

+ 105 - 24
src/libraries/cryptolib4pascal/ClpSecT283Custom.pas

@@ -31,7 +31,7 @@ uses
   ClpBigInteger,
   ClpBigInteger,
   ClpArrayUtils,
   ClpArrayUtils,
   ClpIECC,
   ClpIECC,
-  ClpWTauNafMultiplier,
+  ClpMultipliers,
   ClpCryptoLibTypes,
   ClpCryptoLibTypes,
   ClpECCurveConstants,
   ClpECCurveConstants,
   ClpISecT283Custom;
   ClpISecT283Custom;
@@ -60,8 +60,9 @@ type
     class procedure ImplMulw(x, y: UInt64; const z: TCryptoLibUInt64Array;
     class procedure ImplMulw(x, y: UInt64; const z: TCryptoLibUInt64Array;
       zOff: Int32); static;
       zOff: Int32); static;
 
 
-    class procedure ImplSquare(const x, zz: TCryptoLibUInt64Array);
-      static; inline;
+    class procedure ImplSquare(const x, zz: TCryptoLibUInt64Array); static;
+
+    class procedure AddTo(const x, z: TCryptoLibUInt64Array); static; inline;
 
 
     class procedure Boot(); static;
     class procedure Boot(); static;
     class constructor SecT283Field();
     class constructor SecT283Field();
@@ -71,6 +72,10 @@ type
     class procedure AddExt(const xx, yy, zz: TCryptoLibUInt64Array);
     class procedure AddExt(const xx, yy, zz: TCryptoLibUInt64Array);
       static; inline;
       static; inline;
     class procedure AddOne(const x, z: TCryptoLibUInt64Array); static; inline;
     class procedure AddOne(const x, z: TCryptoLibUInt64Array); static; inline;
+
+    class procedure HalfTrace(const x, z: TCryptoLibUInt64Array);
+      static; inline;
+
     class function FromBigInteger(const x: TBigInteger): TCryptoLibUInt64Array;
     class function FromBigInteger(const x: TBigInteger): TCryptoLibUInt64Array;
       static; inline;
       static; inline;
 
 
@@ -152,6 +157,10 @@ type
 
 
     function Trace(): Int32; override;
     function Trace(): Int32; override;
 
 
+    function HalfTrace(): IECFieldElement; override;
+
+    function HasFastTrace(): Boolean; override;
+
     function Invert(): IECFieldElement; override;
     function Invert(): IECFieldElement; override;
 
 
     /// <summary>
     /// <summary>
@@ -249,8 +258,8 @@ type
   strict private
   strict private
 
 
   type
   type
-    TSecT283K1LookupTable = class sealed(TInterfacedObject,
-      ISecT283K1LookupTable, IECLookupTable)
+    TSecT283K1LookupTable = class sealed(TAbstractECLookupTable,
+      ISecT283K1LookupTable)
 
 
     strict private
     strict private
     var
     var
@@ -258,16 +267,19 @@ type
       Fm_table: TCryptoLibUInt64Array;
       Fm_table: TCryptoLibUInt64Array;
       Fm_size: Int32;
       Fm_size: Int32;
 
 
-      function GetSize: Int32; virtual;
+      function CreatePoint(const x, y: TCryptoLibUInt64Array): IECPoint;
+
+    strict protected
+
+      function GetSize: Int32; override;
 
 
     public
     public
 
 
       constructor Create(const outer: ISecT283K1Curve;
       constructor Create(const outer: ISecT283K1Curve;
         const table: TCryptoLibUInt64Array; size: Int32);
         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;
     end;
 
 
@@ -373,6 +385,15 @@ begin
   z[4] := x[4];
   z[4] := x[4];
 end;
 end;
 
 
+class procedure TSecT283Field.AddTo(const x, z: TCryptoLibUInt64Array);
+begin
+  z[0] := z[0] xor x[0];
+  z[1] := z[1] xor x[1];
+  z[2] := z[2] xor x[2];
+  z[3] := z[3] xor x[3];
+  z[4] := z[4] xor x[4];
+end;
+
 class procedure TSecT283Field.Boot;
 class procedure TSecT283Field.Boot;
 begin
 begin
   FROOT_Z := TCryptoLibUInt64Array.Create(UInt64($0C30C30C30C30808),
   FROOT_Z := TCryptoLibUInt64Array.Create(UInt64($0C30C30C30C30808),
@@ -380,14 +401,31 @@ begin
     UInt64($0820820820820820), UInt64($2082082));
     UInt64($0820820820820820), UInt64($2082082));
 end;
 end;
 
 
+class procedure TSecT283Field.HalfTrace(const x, z: TCryptoLibUInt64Array);
+var
+  tt: TCryptoLibUInt64Array;
+  i: Int32;
+begin
+  tt := TNat.Create64(9);
+
+  TNat320.Copy64(x, z);
+  i := 1;
+
+  while i < 283 do
+  begin
+    ImplSquare(z, tt);
+    Reduce(tt, z);
+    ImplSquare(z, tt);
+    Reduce(tt, z);
+    AddTo(x, z);
+    System.Inc(i, 2);
+  end;
+end;
+
 class function TSecT283Field.FromBigInteger(const x: TBigInteger)
 class function TSecT283Field.FromBigInteger(const x: TBigInteger)
   : TCryptoLibUInt64Array;
   : TCryptoLibUInt64Array;
-var
-  z: TCryptoLibUInt64Array;
 begin
 begin
-  z := TNat320.FromBigInteger64(x);
-  Reduce37(z, 0);
-  result := z;
+  result := TNat.FromBigInteger64(283, x);
 end;
 end;
 
 
 class procedure TSecT283Field.Multiply(const x, y, z: TCryptoLibUInt64Array);
 class procedure TSecT283Field.Multiply(const x, y, z: TCryptoLibUInt64Array);
@@ -400,14 +438,11 @@ begin
 end;
 end;
 
 
 class procedure TSecT283Field.ImplSquare(const x, zz: TCryptoLibUInt64Array);
 class procedure TSecT283Field.ImplSquare(const x, zz: TCryptoLibUInt64Array);
-var
-  i: Int32;
 begin
 begin
-  for i := 0 to System.Pred(4) do
-  begin
-    TInterleave.Expand64To128(x[i], zz, i shl 1);
-  end;
-
+  TInterleave.Expand64To128(x[0], zz, 0);
+  TInterleave.Expand64To128(x[1], zz, 2);
+  TInterleave.Expand64To128(x[2], zz, 4);
+  TInterleave.Expand64To128(x[3], zz, 6);
   zz[8] := TInterleave.Expand32to64(UInt32(x[4]));
   zz[8] := TInterleave.Expand32to64(UInt32(x[4]));
 end;
 end;
 
 
@@ -909,6 +944,20 @@ begin
   result := Fx;
   result := Fx;
 end;
 end;
 
 
+function TSecT283FieldElement.HalfTrace: IECFieldElement;
+var
+  z: TCryptoLibUInt64Array;
+begin
+  z := TNat320.Create64();
+  TSecT283Field.HalfTrace(x, z);
+  result := TSecT283FieldElement.Create(z) as ISecT283FieldElement;
+end;
+
+function TSecT283FieldElement.HasFastTrace: Boolean;
+begin
+  result := true;
+end;
+
 function TSecT283FieldElement.Invert: IECFieldElement;
 function TSecT283FieldElement.Invert: IECFieldElement;
 var
 var
   z: TCryptoLibUInt64Array;
   z: TCryptoLibUInt64Array;
@@ -1545,6 +1594,21 @@ begin
   Fm_size := size;
   Fm_size := size;
 end;
 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;
 function TSecT283K1Curve.TSecT283K1LookupTable.GetSize: Int32;
 begin
 begin
   result := Fm_size;
   result := Fm_size;
@@ -1573,9 +1637,26 @@ begin
     pos := pos + (SECT283K1_FE_LONGS * 2);
     pos := pos + (SECT283K1_FE_LONGS * 2);
   end;
   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;
 
 
 end.
 end.

+ 6 - 1
src/libraries/cryptolib4pascal/ClpSecureRandom.pas

@@ -230,7 +230,6 @@ end;
 
 
 class function TSecureRandom.NextCounterValue: Int64;
 class function TSecureRandom.NextCounterValue: Int64;
 begin
 begin
-
   FLock.Acquire;
   FLock.Acquire;
   try
   try
     System.Inc(FCounter);
     System.Inc(FCounter);
@@ -238,6 +237,12 @@ begin
   finally
   finally
     FLock.Release;
     FLock.Release;
   end;
   end;
+  // TODO when we upgrade to FPC 3.2.0 enable and remove locks above
+  // {$IFDEF FPC}
+  // Result := InterLockedIncrement64(FCounter);
+  // {$ELSE}
+  // Result := TInterlocked.Increment(FCounter);
+  // {$ENDIF}
 end;
 end;
 
 
 function TSecureRandom.NextDouble: Double;
 function TSecureRandom.NextDouble: Double;

+ 15 - 0
src/libraries/cryptolib4pascal/ClpStringUtils.pas

@@ -45,6 +45,9 @@ type
     class function LastIndexOf(const Input, SubString: string;
     class function LastIndexOf(const Input, SubString: string;
       StartIndex, Count: Int32; IgnoreCase: Boolean): Int32; overload; static;
       StartIndex, Count: Int32; IgnoreCase: Boolean): Int32; overload; static;
 
 
+    class function StringToCharArray(const S: String)
+      : TCryptoLibCharArray; static;
+
   end;
   end;
 
 
 implementation
 implementation
@@ -198,6 +201,18 @@ begin
   end;
   end;
 end;
 end;
 
 
+class function TStringUtils.StringToCharArray(const S: String)
+  : TCryptoLibCharArray;
+begin
+  Result := Nil;
+  if System.Length(S) > 0 then
+  begin
+    System.SetLength(Result, System.Length(S) + 1);
+    StrPLCopy(PChar(Result), S, System.Length(Result));
+    System.SetLength(Result, System.Length(S)); // to remove the null terminator
+  end;
+end;
+
 class function TStringUtils.BeginsWith(const Input, SubString: string;
 class function TStringUtils.BeginsWith(const Input, SubString: string;
   IgnoreCase: Boolean; Offset: Int32): Boolean;
   IgnoreCase: Boolean; Offset: Int32): Boolean;
 var
 var

+ 78 - 67
src/libraries/cryptolib4pascal/ClpTeleTrusTNamedCurves.pas

@@ -28,6 +28,7 @@ uses
   ClpTeleTrusTObjectIdentifiers,
   ClpTeleTrusTObjectIdentifiers,
   ClpCryptoLibTypes,
   ClpCryptoLibTypes,
   ClpBigInteger,
   ClpBigInteger,
+  ClpECCompUtilities,
   ClpECC,
   ClpECC,
   ClpIECC,
   ClpIECC,
   ClpX9ECC,
   ClpX9ECC,
@@ -61,6 +62,9 @@ type
     class function ConfigureCurve(const curve: IECCurve): IECCurve;
     class function ConfigureCurve(const curve: IECCurve): IECCurve;
       static; inline;
       static; inline;
 
 
+    class function ConfigureBasepoint(const curve: IECCurve;
+      const encoding: String): IX9ECPoint; static;
+
     class procedure Boot(); static;
     class procedure Boot(); static;
     class constructor CreateTeleTrusTNamedCurves();
     class constructor CreateTeleTrusTNamedCurves();
     class destructor DestroyTeleTrusTNamedCurves();
     class destructor DestroyTeleTrusTNamedCurves();
@@ -325,6 +329,13 @@ implementation
 
 
 { TeleTrusTNamedCurves }
 { TeleTrusTNamedCurves }
 
 
+class function TTeleTrusTNamedCurves.ConfigureBasepoint(const curve: IECCurve;
+  const encoding: String): IX9ECPoint;
+begin
+  result := TX9ECPoint.Create(curve, THex.Decode(encoding));
+  TWnafUtilities.ConfigureBasepoint(result.Point);
+end;
+
 class function TTeleTrusTNamedCurves.ConfigureCurve(const curve: IECCurve)
 class function TTeleTrusTNamedCurves.ConfigureCurve(const curve: IECCurve)
   : IECCurve;
   : IECCurve;
 begin
 begin
@@ -448,6 +459,7 @@ function TTeleTrusTNamedCurves.TBrainpoolP160r1Holder.CreateParameters
 var
 var
   n, h: TBigInteger;
   n, h: TBigInteger;
   curve: IECCurve;
   curve: IECCurve;
+  G: IX9ECPoint;
 begin
 begin
   n := TBigInteger.Create('E95E4A5F737059DC60DF5991D45029409E60FC09', 16);
   n := TBigInteger.Create('E95E4A5F737059DC60DF5991D45029409E60FC09', 16);
   h := TBigInteger.Create('01', 16);
   h := TBigInteger.Create('01', 16);
@@ -459,11 +471,10 @@ begin
     TBigInteger.Create('1E589A8595423412134FAA2DBDEC95C8D8675E58', 16), // b
     TBigInteger.Create('1E589A8595423412134FAA2DBDEC95C8D8675E58', 16), // b
     n, h) as IFpCurve);
     n, h) as IFpCurve);
 
 
-  result := TX9ECParameters.Create(curve, TX9ECPoint.Create(curve,
-    THex.Decode
-    ('04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321')
-    ) as IX9ECPoint, // G
-    n, h);
+  G := ConfigureBasepoint(curve,
+    '04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321');
+
+  result := TX9ECParameters.Create(curve, G, n, h);
 end;
 end;
 
 
 class function TTeleTrusTNamedCurves.TBrainpoolP160r1Holder.Instance
 class function TTeleTrusTNamedCurves.TBrainpoolP160r1Holder.Instance
@@ -479,6 +490,7 @@ function TTeleTrusTNamedCurves.TBrainpoolP160t1Holder.CreateParameters
 var
 var
   n, h: TBigInteger;
   n, h: TBigInteger;
   curve: IECCurve;
   curve: IECCurve;
+  G: IX9ECPoint;
 begin
 begin
   n := TBigInteger.Create('E95E4A5F737059DC60DF5991D45029409E60FC09', 16);
   n := TBigInteger.Create('E95E4A5F737059DC60DF5991D45029409E60FC09', 16);
   h := TBigInteger.Create('01', 16);
   h := TBigInteger.Create('01', 16);
@@ -490,11 +502,10 @@ begin
     TBigInteger.Create('7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380', 16), // b'
     TBigInteger.Create('7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380', 16), // b'
     n, h) as IFpCurve);
     n, h) as IFpCurve);
 
 
-  result := TX9ECParameters.Create(curve, TX9ECPoint.Create(curve,
-    THex.Decode
-    ('04B199B13B9B34EFC1397E64BAEB05ACC265FF2378ADD6718B7C7C1961F0991B842443772152C9E0AD')
-    ) as IX9ECPoint, // G'
-    n, h);
+  G := ConfigureBasepoint(curve,
+    '04B199B13B9B34EFC1397E64BAEB05ACC265FF2378ADD6718B7C7C1961F0991B842443772152C9E0AD');
+
+  result := TX9ECParameters.Create(curve, G, n, h);
 end;
 end;
 
 
 class function TTeleTrusTNamedCurves.TBrainpoolP160t1Holder.Instance
 class function TTeleTrusTNamedCurves.TBrainpoolP160t1Holder.Instance
@@ -510,6 +521,7 @@ function TTeleTrusTNamedCurves.TBrainpoolP192r1Holder.CreateParameters
 var
 var
   n, h: TBigInteger;
   n, h: TBigInteger;
   curve: IECCurve;
   curve: IECCurve;
+  G: IX9ECPoint;
 begin
 begin
   n := TBigInteger.Create
   n := TBigInteger.Create
     ('C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1', 16);
     ('C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1', 16);
@@ -524,11 +536,10 @@ begin
     // b
     // b
     n, h) as IFpCurve);
     n, h) as IFpCurve);
 
 
-  result := TX9ECParameters.Create(curve, TX9ECPoint.Create(curve,
-    THex.Decode
-    ('04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F')
-    ) as IX9ECPoint, // G
-    n, h);
+  G := ConfigureBasepoint(curve,
+    '04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F');
+
+  result := TX9ECParameters.Create(curve, G, n, h);
 end;
 end;
 
 
 class function TTeleTrusTNamedCurves.TBrainpoolP192r1Holder.Instance
 class function TTeleTrusTNamedCurves.TBrainpoolP192r1Holder.Instance
@@ -544,6 +555,7 @@ function TTeleTrusTNamedCurves.TBrainpoolP192t1Holder.CreateParameters
 var
 var
   n, h: TBigInteger;
   n, h: TBigInteger;
   curve: IECCurve;
   curve: IECCurve;
+  G: IX9ECPoint;
 begin
 begin
   n := TBigInteger.Create
   n := TBigInteger.Create
     ('C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1', 16);
     ('C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1', 16);
@@ -558,11 +570,10 @@ begin
     // b'
     // b'
     n, h) as IFpCurve);
     n, h) as IFpCurve);
 
 
-  result := TX9ECParameters.Create(curve, TX9ECPoint.Create(curve,
-    THex.Decode
-    ('043AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9')
-    ) as IX9ECPoint, // G'
-    n, h);
+  G := ConfigureBasepoint(curve,
+    '043AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9');
+
+  result := TX9ECParameters.Create(curve, G, n, h);
 end;
 end;
 
 
 class function TTeleTrusTNamedCurves.TBrainpoolP192t1Holder.Instance
 class function TTeleTrusTNamedCurves.TBrainpoolP192t1Holder.Instance
@@ -578,6 +589,7 @@ function TTeleTrusTNamedCurves.TBrainpoolP224r1Holder.CreateParameters
 var
 var
   n, h: TBigInteger;
   n, h: TBigInteger;
   curve: IECCurve;
   curve: IECCurve;
+  G: IX9ECPoint;
 begin
 begin
   n := TBigInteger.Create
   n := TBigInteger.Create
     ('D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F', 16);
     ('D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F', 16);
@@ -594,11 +606,10 @@ begin
     // b
     // b
     n, h) as IFpCurve);
     n, h) as IFpCurve);
 
 
-  result := TX9ECParameters.Create(curve, TX9ECPoint.Create(curve,
-    THex.Decode
-    ('040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD')
-    ) as IX9ECPoint, // G
-    n, h);
+  G := ConfigureBasepoint(curve,
+    '040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD');
+
+  result := TX9ECParameters.Create(curve, G, n, h);
 end;
 end;
 
 
 class function TTeleTrusTNamedCurves.TBrainpoolP224r1Holder.Instance
 class function TTeleTrusTNamedCurves.TBrainpoolP224r1Holder.Instance
@@ -614,6 +625,7 @@ function TTeleTrusTNamedCurves.TBrainpoolP224t1Holder.CreateParameters
 var
 var
   n, h: TBigInteger;
   n, h: TBigInteger;
   curve: IECCurve;
   curve: IECCurve;
+  G: IX9ECPoint;
 begin
 begin
   n := TBigInteger.Create
   n := TBigInteger.Create
     ('D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F', 16);
     ('D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F', 16);
@@ -630,11 +642,10 @@ begin
     // b'
     // b'
     n, h) as IFpCurve);
     n, h) as IFpCurve);
 
 
-  result := TX9ECParameters.Create(curve, TX9ECPoint.Create(curve,
-    THex.Decode
-    ('046AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D5800374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C')
-    ) as IX9ECPoint, // G'
-    n, h);
+  G := ConfigureBasepoint(curve,
+    '046AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D5800374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C');
+
+  result := TX9ECParameters.Create(curve, G, n, h);
 end;
 end;
 
 
 class function TTeleTrusTNamedCurves.TBrainpoolP224t1Holder.Instance
 class function TTeleTrusTNamedCurves.TBrainpoolP224t1Holder.Instance
@@ -650,6 +661,7 @@ function TTeleTrusTNamedCurves.TBrainpoolP256r1Holder.CreateParameters
 var
 var
   n, h: TBigInteger;
   n, h: TBigInteger;
   curve: IECCurve;
   curve: IECCurve;
+  G: IX9ECPoint;
 begin
 begin
   n := TBigInteger.Create
   n := TBigInteger.Create
     ('A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7', 16);
     ('A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7', 16);
@@ -667,11 +679,10 @@ begin
     // b
     // b
     n, h) as IFpCurve);
     n, h) as IFpCurve);
 
 
-  result := TX9ECParameters.Create(curve, TX9ECPoint.Create(curve,
-    THex.Decode
-    ('048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997')
-    ) as IX9ECPoint, // G
-    n, h);
+  G := ConfigureBasepoint(curve,
+    '048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997');
+
+  result := TX9ECParameters.Create(curve, G, n, h);
 end;
 end;
 
 
 class function TTeleTrusTNamedCurves.TBrainpoolP256r1Holder.Instance
 class function TTeleTrusTNamedCurves.TBrainpoolP256r1Holder.Instance
@@ -687,6 +698,7 @@ function TTeleTrusTNamedCurves.TBrainpoolP256t1Holder.CreateParameters
 var
 var
   n, h: TBigInteger;
   n, h: TBigInteger;
   curve: IECCurve;
   curve: IECCurve;
+  G: IX9ECPoint;
 begin
 begin
   n := TBigInteger.Create
   n := TBigInteger.Create
     ('A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7', 16);
     ('A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7', 16);
@@ -704,11 +716,10 @@ begin
     // b'
     // b'
     n, h) as IFpCurve);
     n, h) as IFpCurve);
 
 
-  result := TX9ECParameters.Create(curve, TX9ECPoint.Create(curve,
-    THex.Decode
-    ('04A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F42D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE')
-    ) as IX9ECPoint, // G'
-    n, h);
+  G := ConfigureBasepoint(curve,
+    '04A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F42D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE');
+
+  result := TX9ECParameters.Create(curve, G, n, h);
 end;
 end;
 
 
 class function TTeleTrusTNamedCurves.TBrainpoolP256t1Holder.Instance
 class function TTeleTrusTNamedCurves.TBrainpoolP256t1Holder.Instance
@@ -765,6 +776,7 @@ function TTeleTrusTNamedCurves.TBrainpoolP320t1Holder.CreateParameters
 var
 var
   n, h: TBigInteger;
   n, h: TBigInteger;
   curve: IECCurve;
   curve: IECCurve;
+  G: IX9ECPoint;
 begin
 begin
   n := TBigInteger.Create
   n := TBigInteger.Create
     ('D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311',
     ('D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311',
@@ -786,11 +798,10 @@ begin
     // b'
     // b'
     n, h) as IFpCurve);
     n, h) as IFpCurve);
 
 
-  result := TX9ECParameters.Create(curve, TX9ECPoint.Create(curve,
-    THex.Decode
-    ('04925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED5263BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3')
-    ) as IX9ECPoint, // G'
-    n, h);
+  G := ConfigureBasepoint(curve,
+    '04925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED5263BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3');
+
+  result := TX9ECParameters.Create(curve, G, n, h);
 end;
 end;
 
 
 class function TTeleTrusTNamedCurves.TBrainpoolP320t1Holder.Instance
 class function TTeleTrusTNamedCurves.TBrainpoolP320t1Holder.Instance
@@ -806,6 +817,7 @@ function TTeleTrusTNamedCurves.TBrainpoolP384r1Holder.CreateParameters
 var
 var
   n, h: TBigInteger;
   n, h: TBigInteger;
   curve: IECCurve;
   curve: IECCurve;
+  G: IX9ECPoint;
 begin
 begin
   n := TBigInteger.Create
   n := TBigInteger.Create
     ('8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565',
     ('8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565',
@@ -827,11 +839,10 @@ begin
     // b
     // b
     n, h) as IFpCurve);
     n, h) as IFpCurve);
 
 
-  result := TX9ECParameters.Create(curve, TX9ECPoint.Create(curve,
-    THex.Decode
-    ('041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315')
-    ) as IX9ECPoint, // G
-    n, h);
+  G := ConfigureBasepoint(curve,
+    '041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315');
+
+  result := TX9ECParameters.Create(curve, G, n, h);
 end;
 end;
 
 
 class function TTeleTrusTNamedCurves.TBrainpoolP384r1Holder.Instance
 class function TTeleTrusTNamedCurves.TBrainpoolP384r1Holder.Instance
@@ -847,6 +858,7 @@ function TTeleTrusTNamedCurves.TBrainpoolP384t1Holder.CreateParameters
 var
 var
   n, h: TBigInteger;
   n, h: TBigInteger;
   curve: IECCurve;
   curve: IECCurve;
+  G: IX9ECPoint;
 begin
 begin
   n := TBigInteger.Create
   n := TBigInteger.Create
     ('8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565',
     ('8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565',
@@ -868,11 +880,10 @@ begin
     // b'
     // b'
     n, h) as IFpCurve);
     n, h) as IFpCurve);
 
 
-  result := TX9ECParameters.Create(curve, TX9ECPoint.Create(curve,
-    THex.Decode
-    ('0418DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928')
-    ) as IX9ECPoint, // G'
-    n, h);
+  G := ConfigureBasepoint(curve,
+    '0418DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928');
+
+  result := TX9ECParameters.Create(curve, G, n, h);
 end;
 end;
 
 
 class function TTeleTrusTNamedCurves.TBrainpoolP384t1Holder.Instance
 class function TTeleTrusTNamedCurves.TBrainpoolP384t1Holder.Instance
@@ -888,6 +899,7 @@ function TTeleTrusTNamedCurves.TBrainpoolP512r1Holder.CreateParameters
 var
 var
   n, h: TBigInteger;
   n, h: TBigInteger;
   curve: IECCurve;
   curve: IECCurve;
+  G: IX9ECPoint;
 begin
 begin
   n := TBigInteger.Create
   n := TBigInteger.Create
     ('AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069',
     ('AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069',
@@ -909,12 +921,11 @@ begin
     // b
     // b
     n, h) as IFpCurve);
     n, h) as IFpCurve);
 
 
-  result := TX9ECParameters.Create(curve, TX9ECPoint.Create(curve,
-    THex.Decode
-    ('0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97'
-    + 'D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892')
-    ) as IX9ECPoint, // G
-    n, h);
+  G := ConfigureBasepoint(curve,
+    '0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF' +
+    '3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892');
+
+  result := TX9ECParameters.Create(curve, G, n, h);
 end;
 end;
 
 
 class function TTeleTrusTNamedCurves.TBrainpoolP512r1Holder.Instance
 class function TTeleTrusTNamedCurves.TBrainpoolP512r1Holder.Instance
@@ -930,6 +941,7 @@ function TTeleTrusTNamedCurves.TBrainpoolP512t1Holder.CreateParameters
 var
 var
   n, h: TBigInteger;
   n, h: TBigInteger;
   curve: IECCurve;
   curve: IECCurve;
+  G: IX9ECPoint;
 begin
 begin
   n := TBigInteger.Create
   n := TBigInteger.Create
     ('AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069',
     ('AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069',
@@ -951,12 +963,11 @@ begin
     // b'
     // b'
     n, h) as IFpCurve);
     n, h) as IFpCurve);
 
 
-  result := TX9ECParameters.Create(curve, TX9ECPoint.Create(curve,
-    THex.Decode
-    ('04640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D'
-    + '6943A64F7A3F25FE26F06B51BAA2696FA9035DA5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332')
-    ) as IX9ECPoint, // G'
-    n, h);
+  G := ConfigureBasepoint(curve,
+    '04640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA5'
+    + 'B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332');
+
+  result := TX9ECParameters.Create(curve, G, n, h);
 end;
 end;
 
 
 class function TTeleTrusTNamedCurves.TBrainpoolP512t1Holder.Instance
 class function TTeleTrusTNamedCurves.TBrainpoolP512t1Holder.Instance

+ 12 - 12
src/libraries/cryptolib4pascal/ClpValidityPrecompInfo.pas

@@ -15,7 +15,7 @@
 
 
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 
 
-unit ClpValidityPrecompInfo;
+unit ClpValidityPreCompInfo;
 
 
 {$I CryptoLib.inc}
 {$I CryptoLib.inc}
 
 
@@ -23,11 +23,11 @@ interface
 
 
 uses
 uses
   ClpIPreCompInfo,
   ClpIPreCompInfo,
-  ClpIValidityPrecompInfo;
+  ClpIValidityPreCompInfo;
 
 
 type
 type
-  TValidityPrecompInfo = class(TInterfacedObject, IPreCompInfo,
-    IValidityPrecompInfo)
+  TValidityPreCompInfo = class(TInterfacedObject, IPreCompInfo,
+    IValidityPreCompInfo)
 
 
   strict private
   strict private
 
 
@@ -52,9 +52,9 @@ type
 
 
 implementation
 implementation
 
 
-{ TValidityPrecompInfo }
+{ TValidityPreCompInfo }
 
 
-constructor TValidityPrecompInfo.Create;
+constructor TValidityPreCompInfo.Create;
 begin
 begin
   Inherited Create();
   Inherited Create();
   Ffailed := False;
   Ffailed := False;
@@ -62,32 +62,32 @@ begin
   ForderPassed := False;
   ForderPassed := False;
 end;
 end;
 
 
-function TValidityPrecompInfo.HasCurveEquationPassed: Boolean;
+function TValidityPreCompInfo.HasCurveEquationPassed: Boolean;
 begin
 begin
   result := FcurveEquationPassed;
   result := FcurveEquationPassed;
 end;
 end;
 
 
-function TValidityPrecompInfo.HasFailed: Boolean;
+function TValidityPreCompInfo.HasFailed: Boolean;
 begin
 begin
   result := Ffailed;
   result := Ffailed;
 end;
 end;
 
 
-function TValidityPrecompInfo.HasOrderPassed: Boolean;
+function TValidityPreCompInfo.HasOrderPassed: Boolean;
 begin
 begin
   result := ForderPassed;
   result := ForderPassed;
 end;
 end;
 
 
-procedure TValidityPrecompInfo.ReportCurveEquationPassed;
+procedure TValidityPreCompInfo.ReportCurveEquationPassed;
 begin
 begin
   FcurveEquationPassed := True;
   FcurveEquationPassed := True;
 end;
 end;
 
 
-procedure TValidityPrecompInfo.ReportFailed;
+procedure TValidityPreCompInfo.ReportFailed;
 begin
 begin
   Ffailed := True;
   Ffailed := True;
 end;
 end;
 
 
-procedure TValidityPrecompInfo.ReportOrderPassed;
+procedure TValidityPreCompInfo.ReportOrderPassed;
 begin
 begin
   ForderPassed := True;
   ForderPassed := True;
 end;
 end;

+ 0 - 191
src/libraries/cryptolib4pascal/ClpWNafL2RMultiplier.pas

@@ -1,191 +0,0 @@
-{ *********************************************************************************** }
-{ *                              CryptoLib Library                                  * }
-{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
-{ *                 Github Repository <https://github.com/Xor-el>                   * }
-
-{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
-{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
-
-{ *                              Acknowledgements:                                  * }
-{ *                                                                                 * }
-{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
-{ *                           development of this library                           * }
-
-{ * ******************************************************************************* * }
-
-(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
-
-unit ClpWNafL2RMultiplier;
-
-{$I CryptoLib.inc}
-
-interface
-
-uses
-  Math,
-  ClpBits,
-  ClpBigInteger,
-  ClpLongArray,
-  ClpCryptoLibTypes,
-  ClpIECC,
-  ClpIWNafPreCompInfo,
-  ClpECAlgorithms,
-  ClpAbstractECMultiplier,
-  ClpIWNafL2RMultiplier;
-
-type
-
-  /// <summary>
-  /// Class implementing the WNAF (Window Non-Adjacent Form) multiplication
-  /// algorithm.
-  /// </summary>
-  TWNafL2RMultiplier = class(TAbstractECMultiplier, IWNafL2RMultiplier)
-
-  strict protected
-    // /**
-    // * Multiplies <code>this</code> by an integer <code>k</code> using the
-    // * Window NAF method.
-    // * @param k The integer by which <code>this</code> is multiplied.
-    // * @return A new <code>ECPoint</code> which equals <code>this</code>
-    // * multiplied by <code>k</code>.
-    // */
-    function MultiplyPositive(const p: IECPoint; const k: TBigInteger)
-      : IECPoint; override;
-
-    /// <summary>
-    /// Determine window width to use for a scalar multiplication of the
-    /// given size.
-    /// </summary>
-    /// <param name="bits">
-    /// the bit-length of the scalar to multiply by
-    /// </param>
-    /// <returns>
-    /// the window size to use
-    /// </returns>
-    function GetWindowSize(bits: Int32): Int32; virtual;
-
-  public
-
-    constructor Create();
-    destructor Destroy; override;
-
-  end;
-
-implementation
-
-{ TWNafL2RMultiplier }
-
-constructor TWNafL2RMultiplier.Create;
-begin
-  Inherited Create();
-end;
-
-destructor TWNafL2RMultiplier.Destroy;
-begin
-  inherited Destroy;
-end;
-
-function TWNafL2RMultiplier.GetWindowSize(bits: Int32): Int32;
-begin
-  Result := TWNafUtilities.GetWindowSize(bits);
-end;
-
-function TWNafL2RMultiplier.MultiplyPositive(const p: IECPoint;
-  const k: TBigInteger): IECPoint;
-var
-  width, i, wi, digit, zeroes, n, highest, scale, lowBits, i1, i2: Int32;
-  wnafPreCompInfo: IWNafPreCompInfo;
-  preComp, preCompNeg, table: TCryptoLibGenericArray<IECPoint>;
-  wnaf: TCryptoLibInt32Array;
-  R, lr: IECPoint;
-begin
-  // Clamp the window width in the range [2, 16]
-  width := Math.Max(2, Math.Min(16, GetWindowSize(k.BitLength)));
-
-  wnafPreCompInfo := TWNafUtilities.Precompute(p, width, true);
-  preComp := wnafPreCompInfo.preComp;
-  preCompNeg := wnafPreCompInfo.preCompNeg;
-
-  wnaf := TWNafUtilities.GenerateCompactWindowNaf(width, k);
-
-  R := p.Curve.Infinity;
-
-  i := System.Length(wnaf);
-
-  // /*
-  // * NOTE: We try to optimize the first window using the precomputed points to substitute an
-  // * addition for 2 or more doublings.
-  // */
-  if (i > 1) then
-  begin
-    System.Dec(i);
-    wi := wnaf[i];
-    digit := TBits.Asr32(wi, 16);
-    zeroes := wi and $FFFF;
-
-    n := System.Abs(digit);
-    if digit < 0 then
-    begin
-      table := preCompNeg;
-    end
-    else
-    begin
-      table := preComp;
-    end;
-
-    // Optimization can only be used for values in the lower half of the table
-    if ((n shl 2) < (1 shl width)) then
-    begin
-      highest := TLongArray.BitLengths[n];
-
-      // TODO Get addition/doubling cost ratio from curve and compare to 'scale' to see if worth substituting?
-      scale := width - highest;
-      lowBits := n xor (1 shl (highest - 1));
-
-      i1 := ((1 shl (width - 1)) - 1);
-      i2 := (lowBits shl scale) + 1;
-      R := table[TBits.Asr32(i1, 1)].Add(table[TBits.Asr32(i2, 1)]);
-
-      zeroes := zeroes - scale;
-
-      // Console.WriteLine("Optimized: 2^" + scale + " * " + n + " = " + i1 + " + " + i2);
-    end
-    else
-    begin
-      R := table[TBits.Asr32(n, 1)];
-    end;
-
-    R := R.TimesPow2(zeroes);
-  end;
-
-  while (i > 0) do
-  begin
-    System.Dec(i);
-    wi := wnaf[i];
-    digit := TBits.Asr32(wi, 16);
-    zeroes := wi and $FFFF;
-
-    n := System.Abs(digit);
-    if digit < 0 then
-    begin
-      table := preCompNeg;
-    end
-    else
-    begin
-      table := preComp;
-    end;
-
-    lr := table[TBits.Asr32(n, 1)];
-
-    R := R.TwicePlus(lr);
-    R := R.TimesPow2(zeroes);
-  end;
-
-  Result := R;
-
-  wnafPreCompInfo.preComp := Nil; // Review
-  wnafPreCompInfo.preCompNeg := Nil; // Review
-
-end;
-
-end.

+ 101 - 22
src/libraries/cryptolib4pascal/ClpWNafPreCompInfo.pas

@@ -33,47 +33,72 @@ type
   /// Class holding precomputation data for the WNAF (Window Non-Adjacent
   /// Class holding precomputation data for the WNAF (Window Non-Adjacent
   /// Form) algorithm.
   /// Form) algorithm.
   /// </summary>
   /// </summary>
-  TWNafPreCompInfo = class(TInterfacedObject, IPreCompInfo, IWNafPreCompInfo)
+  TWNafPreCompInfo = class sealed(TInterfacedObject, IPreCompInfo,
+    IWNafPreCompInfo)
 
 
   strict private
   strict private
-    function GetPreComp: TCryptoLibGenericArray<IECPoint>; virtual;
-    procedure SetPreComp(const Value
-      : TCryptoLibGenericArray<IECPoint>); virtual;
-    function GetPreCompNeg: TCryptoLibGenericArray<IECPoint>; virtual;
-    procedure SetPreCompNeg(const Value
-      : TCryptoLibGenericArray<IECPoint>); virtual;
-    function GetTwice: IECPoint; virtual;
-    procedure SetTwice(const Value: IECPoint); virtual;
-  strict protected
   var
   var
     /// <summary>
     /// <summary>
     /// Array holding the precomputed <c>ECPoint</c>s used for a Window NAF
     /// Array holding the precomputed <c>ECPoint</c>s used for a Window NAF
     /// multiplication.
     /// multiplication.
     /// </summary>
     /// </summary>
-    Fm_preComp: TCryptoLibGenericArray<IECPoint>;
+    FPreComp: TCryptoLibGenericArray<IECPoint>;
 
 
     /// <summary>
     /// <summary>
     /// Array holding the negations of the precomputed <c>ECPoint</c>s used
     /// Array holding the negations of the precomputed <c>ECPoint</c>s used
     /// for a Window NAF multiplication.
     /// for a Window NAF multiplication.
     /// </summary>
     /// </summary>
-    Fm_preCompNeg: TCryptoLibGenericArray<IECPoint>;
+    FPreCompNeg: TCryptoLibGenericArray<IECPoint>;
 
 
     /// <summary>
     /// <summary>
     /// Holds an <c>ECPoint</c> representing Twice(this). Used for the Window
     /// Holds an <c>ECPoint</c> representing Twice(this). Used for the Window
     /// NAF multiplication to create or extend the precomputed values.
     /// NAF multiplication to create or extend the precomputed values.
     /// </summary>
     /// </summary>
-    Fm_twice: IECPoint;
+    FTwice: IECPoint;
+
+    FConfWidth, FWidth: Int32;
+
+{$IFNDEF FPC}
+{$IFDEF HAS_VOLATILE}[volatile]
+{$ENDIF}
+{$ENDIF}
+    FPromotionCountdown: Int32;
+
+    function GetPreComp: TCryptoLibGenericArray<IECPoint>; inline;
+    procedure SetPreComp(const Value: TCryptoLibGenericArray<IECPoint>); inline;
+    function GetPreCompNeg: TCryptoLibGenericArray<IECPoint>; inline;
+    procedure SetPreCompNeg(const Value
+      : TCryptoLibGenericArray<IECPoint>); inline;
+    function GetTwice: IECPoint; inline;
+    procedure SetTwice(const Value: IECPoint); inline;
+
+    function GetConfWidth: Int32; inline;
+    procedure SetConfWidth(Value: Int32); inline;
+
+    function GetWidth: Int32; inline;
+    procedure SetWidth(Value: Int32); inline;
+
+    function GetPromotionCountdown: Int32; inline;
+    procedure SetPromotionCountdown(Value: Int32); inline;
+
+    function DecrementPromotionCountdown: Int32; inline;
+    function IsPromoted: Boolean; inline;
 
 
   public
   public
 
 
     constructor Create();
     constructor Create();
-    destructor Destroy; override;
     property PreComp: TCryptoLibGenericArray<IECPoint> read GetPreComp
     property PreComp: TCryptoLibGenericArray<IECPoint> read GetPreComp
       write SetPreComp;
       write SetPreComp;
     property PreCompNeg: TCryptoLibGenericArray<IECPoint> read GetPreCompNeg
     property PreCompNeg: TCryptoLibGenericArray<IECPoint> read GetPreCompNeg
       write SetPreCompNeg;
       write SetPreCompNeg;
     property Twice: IECPoint read GetTwice write SetTwice;
     property Twice: IECPoint read GetTwice write SetTwice;
 
 
+    property ConfWidth: Int32 read GetConfWidth write SetConfWidth;
+    property Width: Int32 read GetWidth write SetWidth;
+
+    property PromotionCountdown: Int32 read GetPromotionCountdown
+      write SetPromotionCountdown;
+
   end;
   end;
 
 
 implementation
 implementation
@@ -83,43 +108,97 @@ implementation
 constructor TWNafPreCompInfo.Create;
 constructor TWNafPreCompInfo.Create;
 begin
 begin
   inherited Create();
   inherited Create();
+  FConfWidth := -1;
+  FWidth := -1;
+  FPromotionCountdown := 4;
+end;
+
+function TWNafPreCompInfo.DecrementPromotionCountdown: Int32;
+var
+  t: Int32;
+begin
+  t := PromotionCountdown;
+  if (t > 0) then
+  begin
+    System.Dec(t);
+    PromotionCountdown := t;
+  end;
+  result := t;
 end;
 end;
 
 
-destructor TWNafPreCompInfo.Destroy;
+function TWNafPreCompInfo.GetConfWidth: Int32;
 begin
 begin
-  inherited Destroy;
+  result := FConfWidth;
 end;
 end;
 
 
 function TWNafPreCompInfo.GetPreComp: TCryptoLibGenericArray<IECPoint>;
 function TWNafPreCompInfo.GetPreComp: TCryptoLibGenericArray<IECPoint>;
 begin
 begin
-  Result := Fm_preComp;
+  result := FPreComp;
 end;
 end;
 
 
 function TWNafPreCompInfo.GetPreCompNeg: TCryptoLibGenericArray<IECPoint>;
 function TWNafPreCompInfo.GetPreCompNeg: TCryptoLibGenericArray<IECPoint>;
 begin
 begin
-  Result := Fm_preCompNeg;
+  result := FPreCompNeg;
+end;
+
+function TWNafPreCompInfo.GetPromotionCountdown: Int32;
+begin
+{$IFDEF FPC}
+  result := {$IFDEF HAS_VOLATILE}volatile{$ENDIF}(FPromotionCountdown);
+{$ELSE}
+    result := FPromotionCountdown;
+{$ENDIF}
 end;
 end;
 
 
 function TWNafPreCompInfo.GetTwice: IECPoint;
 function TWNafPreCompInfo.GetTwice: IECPoint;
 begin
 begin
-  Result := Fm_twice;
+  result := FTwice;
+end;
+
+function TWNafPreCompInfo.GetWidth: Int32;
+begin
+  result := FWidth;
+end;
+
+function TWNafPreCompInfo.IsPromoted: Boolean;
+begin
+  result := PromotionCountdown <= 0;
+end;
+
+procedure TWNafPreCompInfo.SetConfWidth(Value: Int32);
+begin
+  FConfWidth := Value;
 end;
 end;
 
 
 procedure TWNafPreCompInfo.SetPreComp(const Value
 procedure TWNafPreCompInfo.SetPreComp(const Value
   : TCryptoLibGenericArray<IECPoint>);
   : TCryptoLibGenericArray<IECPoint>);
 begin
 begin
-  Fm_preComp := Value;
+  FPreComp := Value;
 end;
 end;
 
 
 procedure TWNafPreCompInfo.SetPreCompNeg(const Value
 procedure TWNafPreCompInfo.SetPreCompNeg(const Value
   : TCryptoLibGenericArray<IECPoint>);
   : TCryptoLibGenericArray<IECPoint>);
 begin
 begin
-  Fm_preCompNeg := Value;
+  FPreCompNeg := Value;
+end;
+
+procedure TWNafPreCompInfo.SetPromotionCountdown(Value: Int32);
+begin
+{$IFDEF FPC}
+  FPromotionCountdown := {$IFDEF HAS_VOLATILE}volatile{$ENDIF}(Value);
+{$ELSE}
+    FPromotionCountdown := Value;
+{$ENDIF}
 end;
 end;
 
 
 procedure TWNafPreCompInfo.SetTwice(const Value: IECPoint);
 procedure TWNafPreCompInfo.SetTwice(const Value: IECPoint);
 begin
 begin
-  Fm_twice := Value;
+  FTwice := Value;
+end;
+
+procedure TWNafPreCompInfo.SetWidth(Value: Int32);
+begin
+  FWidth := Value;
 end;
 end;
 
 
 end.
 end.

+ 0 - 276
src/libraries/cryptolib4pascal/ClpWTauNafMultiplier.pas

@@ -1,276 +0,0 @@
-{ *********************************************************************************** }
-{ *                              CryptoLib Library                                  * }
-{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
-{ *                 Github Repository <https://github.com/Xor-el>                   * }
-
-{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
-{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
-
-{ *                              Acknowledgements:                                  * }
-{ *                                                                                 * }
-{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
-{ *                           development of this library                           * }
-
-{ * ******************************************************************************* * }
-
-(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
-
-unit ClpWTauNafMultiplier;
-
-{$I CryptoLib.inc}
-
-interface
-
-uses
-  SysUtils,
-  ClpBits,
-  ClpBigInteger,
-  ClpCryptoLibTypes,
-  ClpTNaf,
-  ClpAbstractECMultiplier,
-  ClpIWTauNafPreCompInfo,
-  ClpWTauNafPreCompInfo,
-  ClpIECC,
-  ClpIPreCompCallBack,
-  ClpIZTauElement,
-  ClpIPreCompInfo,
-  ClpIWTauNafMultiplier;
-
-resourcestring
-  SInCompatiblePoint = 'Only AbstractF2mPoint can be used in WTauNafMultiplier';
-
-type
-  /// **
-  // * Class implementing the WTNAF (Window
-  // * <code>&#964;</code>-adic Non-Adjacent Form) algorithm.
-  // */
-  TWTauNafMultiplier = class(TAbstractECMultiplier, IWTauNafMultiplier)
-
-  strict private
-    // TODO Create WTauNafUtilities class and move various functionality into it
-
-  type
-    IWTauNafCallback = interface(IPreCompCallback)
-      ['{4D6F7B4A-B925-42C9-8D60-B7F24632EDC1}']
-
-    end;
-
-  type
-    TWTauNafCallback = class(TInterfacedObject, IPreCompCallback,
-      IWTauNafCallback)
-
-    strict private
-    var
-      Fm_p: IAbstractF2mPoint;
-      Fm_a: ShortInt;
-
-    public
-      constructor Create(const p: IAbstractF2mPoint; a: ShortInt);
-
-      function Precompute(const existing: IPreCompInfo): IPreCompInfo;
-
-    end;
-
-  const
-    PRECOMP_NAME: String = 'bc_wtnaf';
-
-    // /**
-    // * Multiplies an AbstractF2mPoint
-    // * by an element <code>&#955;</code> of <code><b>Z</b>[&#964;]</code> using
-    // * the <code>&#964;</code>-adic NAF (TNAF) method.
-    // * @param p The AbstractF2mPoint to multiply.
-    // * @param lambda The element <code>&#955;</code> of
-    // * <code><b>Z</b>[&#964;]</code> of which to compute the
-    // * <code>[&#964;]</code>-adic NAF.
-    // * @return <code>p</code> multiplied by <code>&#955;</code>.
-    // */
-    function MultiplyWTnaf(const p: IAbstractF2mPoint;
-      const lambda: IZTauElement; a, mu: ShortInt): IAbstractF2mPoint; inline;
-
-    // /**
-    // * Multiplies an AbstractF2mPoint
-    // * by an element <code>&#955;</code> of <code><b>Z</b>[&#964;]</code>
-    // * using the window <code>&#964;</code>-adic NAF (TNAF) method, given the
-    // * WTNAF of <code>&#955;</code>.
-    // * @param p The AbstractF2mPoint to multiply.
-    // * @param u The the WTNAF of <code>&#955;</code>..
-    // * @return <code>&#955; * p</code>
-    // */
-    class function MultiplyFromWTnaf(const p: IAbstractF2mPoint;
-      const u: TCryptoLibShortIntArray): IAbstractF2mPoint; static;
-
-  strict protected
-    // /**
-    // * Multiplies an AbstractF2mPoint
-    // * by <code>k</code> using the reduced <code>&#964;</code>-adic NAF (RTNAF)
-    // * method.
-    // * @param p The AbstractF2mPoint to multiply.
-    // * @param k The integer by which to multiply <code>k</code>.
-    // * @return <code>p</code> multiplied by <code>k</code>.
-    // */
-    function MultiplyPositive(const point: IECPoint; const k: TBigInteger)
-      : IECPoint; override;
-
-  public
-    constructor Create();
-    destructor Destroy; override;
-
-  end;
-
-implementation
-
-{ TWTauNafMultiplier }
-
-constructor TWTauNafMultiplier.Create;
-begin
-  Inherited Create();
-end;
-
-destructor TWTauNafMultiplier.Destroy;
-begin
-  inherited Destroy;
-end;
-
-class function TWTauNafMultiplier.MultiplyFromWTnaf(const p: IAbstractF2mPoint;
-  const u: TCryptoLibShortIntArray): IAbstractF2mPoint;
-var
-  curve: IAbstractF2mCurve;
-  a: ShortInt;
-  i, tauCount, ui: Int32;
-  pu, puNeg: TCryptoLibGenericArray<IAbstractF2mPoint>;
-  pre: IWTauNafPreCompInfo;
-  q: IAbstractF2mPoint;
-  x: IECPoint;
-  callback: IWTauNafCallback;
-begin
-  curve := p.curve as IAbstractF2mCurve;
-  a := ShortInt(curve.a.ToBigInteger().Int32Value);
-
-  callback := TWTauNafCallback.Create(p, a);
-  pre := curve.Precompute(p, PRECOMP_NAME, callback) as IWTauNafPreCompInfo;
-
-  pu := pre.PreComp;
-  // TODO Include negations in precomp (optionally) and use from here
-  System.SetLength(puNeg, System.Length(pu));
-  for i := 0 to System.Pred(System.Length(pu)) do
-  begin
-    puNeg[i] := pu[i].Negate() as IAbstractF2mPoint;
-  end;
-
-  // q = infinity
-  q := p.curve.Infinity as IAbstractF2mPoint;
-  tauCount := 0;
-  i := System.Length(u) - 1;
-  while i >= 0 do
-  begin
-    System.Inc(tauCount);
-    ui := u[i];
-    if (ui <> 0) then
-    begin
-      q := q.TauPow(tauCount);
-      tauCount := 0;
-
-      if ui > 0 then
-      begin
-        x := pu[TBits.Asr32(ui, 1)];
-      end
-      else
-      begin
-        x := puNeg[TBits.Asr32(-ui, 1)];
-      end;
-
-      q := q.Add(x) as IAbstractF2mPoint;
-    end;
-    System.Dec(i);
-  end;
-  if (tauCount > 0) then
-  begin
-    q := q.TauPow(tauCount);
-  end;
-  result := q;
-
-  pre.PreComp := Nil; // Review
-
-end;
-
-function TWTauNafMultiplier.MultiplyWTnaf(const p: IAbstractF2mPoint;
-  const lambda: IZTauElement; a, mu: ShortInt): IAbstractF2mPoint;
-var
-  alpha: TCryptoLibGenericArray<IZTauElement>;
-  tw: TBigInteger;
-  u: TCryptoLibShortIntArray;
-begin
-  if a = 0 then
-  begin
-    alpha := TTnaf.Alpha0;
-  end
-  else
-  begin
-    alpha := TTnaf.Alpha1;
-  end;
-
-  tw := TTnaf.GetTw(mu, TTnaf.Width);
-
-  u := TTnaf.TauAdicWNaf(mu, lambda, TTnaf.Width,
-    TBigInteger.ValueOf(TTnaf.Pow2Width), tw, alpha);
-
-  result := MultiplyFromWTnaf(p, u);
-end;
-
-function TWTauNafMultiplier.MultiplyPositive(const point: IECPoint;
-  const k: TBigInteger): IECPoint;
-var
-  p: IAbstractF2mPoint;
-  curve: IAbstractF2mCurve;
-  m: Int32;
-  a, mu: ShortInt;
-  s: TCryptoLibGenericArray<TBigInteger>;
-  rho: IZTauElement;
-begin
-  if (not(Supports(point, IAbstractF2mPoint))) then
-  begin
-    raise EArgumentCryptoLibException.CreateRes(@SInCompatiblePoint);
-  end;
-
-  p := point as IAbstractF2mPoint;
-  curve := p.curve as IAbstractF2mCurve;
-  m := curve.FieldSize;
-  a := ShortInt(curve.a.ToBigInteger().Int32Value);
-  mu := TTnaf.GetMu(a);
-  s := curve.GetSi();
-
-  rho := TTnaf.PartModReduction(k, m, a, s, mu, ShortInt(10));
-
-  result := MultiplyWTnaf(p, rho, a, mu);
-
-end;
-
-{ TWTauNafMultiplier.TWTauNafCallback }
-
-constructor TWTauNafMultiplier.TWTauNafCallback.Create
-  (const p: IAbstractF2mPoint; a: ShortInt);
-begin
-  Inherited Create();
-  Fm_p := p;
-  Fm_a := a;
-end;
-
-function TWTauNafMultiplier.TWTauNafCallback.Precompute(const existing
-  : IPreCompInfo): IPreCompInfo;
-var
-  tempResult: IWTauNafPreCompInfo;
-begin
-
-  // Review uncomment
-  // if (Supports(existing, IWTauNafPreCompInfo)) then
-  // begin
-  // result := existing;
-  // Exit;
-  // end;
-
-  tempResult := TWTauNafPreCompInfo.Create();
-  tempResult.PreComp := TTnaf.GetPreComp(Fm_p, Fm_a);
-  result := tempResult;
-end;
-
-end.

+ 32 - 8
src/libraries/cryptolib4pascal/ClpX25519Field.pas

@@ -24,6 +24,7 @@ interface
 uses
 uses
   ClpBits,
   ClpBits,
   ClpConverters,
   ClpConverters,
+  ClpArrayUtils,
   ClpCryptoLibTypes;
   ClpCryptoLibTypes;
 
 
 type
 type
@@ -77,6 +78,9 @@ type
 
 
     class procedure Carry(const z: TCryptoLibInt32Array); static;
     class procedure Carry(const z: TCryptoLibInt32Array); static;
 
 
+    class procedure CMov(cond: Int32; const x: TCryptoLibInt32Array;
+      xOff: Int32; const z: TCryptoLibInt32Array; zOff: Int32); static;
+
     class procedure CNegate(ANegate: Int32; const z: TCryptoLibInt32Array);
     class procedure CNegate(ANegate: Int32; const z: TCryptoLibInt32Array);
       static; inline;
       static; inline;
 
 
@@ -98,6 +102,8 @@ type
 
 
     class procedure Inv(const x, z: TCryptoLibInt32Array); static; inline;
     class procedure Inv(const x, z: TCryptoLibInt32Array); static; inline;
 
 
+    class function IsZero(const x: TCryptoLibInt32Array): Int32; static;
+
     class function IsZeroVar(const x: TCryptoLibInt32Array): Boolean;
     class function IsZeroVar(const x: TCryptoLibInt32Array): Boolean;
       static; inline;
       static; inline;
 
 
@@ -228,6 +234,23 @@ begin
   z[9] := z9;
   z[9] := z9;
 end;
 end;
 
 
+class procedure TX25519Field.CMov(cond: Int32; const x: TCryptoLibInt32Array;
+  xOff: Int32; const z: TCryptoLibInt32Array; zOff: Int32);
+var
+  i, z_i, diff: Int32;
+begin
+{$IFDEF DEBUG}
+  System.Assert((cond = 0) or (cond = -1));
+{$ENDIF DEBUG}
+  for i := 0 to System.Pred(Size) do
+  begin
+    z_i := z[zOff + i];
+    diff := z_i xor x[xOff + i];
+    z_i := z_i xor (diff and cond);
+    z[zOff + i] := z_i;
+  end;
+end;
+
 class procedure TX25519Field.CNegate(ANegate: Int32;
 class procedure TX25519Field.CNegate(ANegate: Int32;
   const z: TCryptoLibInt32Array);
   const z: TCryptoLibInt32Array);
 var
 var
@@ -379,7 +402,7 @@ begin
   Mul(t, x2, z);
   Mul(t, x2, z);
 end;
 end;
 
 
-class function TX25519Field.IsZeroVar(const x: TCryptoLibInt32Array): Boolean;
+class function TX25519Field.IsZero(const x: TCryptoLibInt32Array): Int32;
 var
 var
   d, i: Int32;
   d, i: Int32;
 begin
 begin
@@ -388,7 +411,13 @@ begin
   begin
   begin
     d := d or x[i];
     d := d or x[i];
   end;
   end;
-  Result := d = 0;
+  d := (TBits.Asr32(d, 1)) or (d and 1);
+  Result := (d - 1) shr 31;
+end;
+
+class function TX25519Field.IsZeroVar(const x: TCryptoLibInt32Array): Boolean;
+begin
+  Result := IsZero(x) <> 0;
 end;
 end;
 
 
 class procedure TX25519Field.Mul(const x: TCryptoLibInt32Array; y: Int32;
 class procedure TX25519Field.Mul(const x: TCryptoLibInt32Array; y: Int32;
@@ -912,13 +941,8 @@ begin
 end;
 end;
 
 
 class procedure TX25519Field.Zero(const z: TCryptoLibInt32Array);
 class procedure TX25519Field.Zero(const z: TCryptoLibInt32Array);
-var
-  i: Int32;
 begin
 begin
-  for i := 0 to System.Pred(Size) do
-  begin
-    z[i] := 0;
-  end;
+  TArrayUtils.Fill(z, 0, Size, Int32(0));
 end;
 end;
 
 
 end.
 end.

+ 10 - 20
src/libraries/cryptolib4pascal/ClpX9ECParametersHolder.pas

@@ -31,21 +31,18 @@ type
     IX9ECParametersHolder)
     IX9ECParametersHolder)
 
 
   strict private
   strict private
+  var
+    FLock: TCriticalSection;
     Fparameters: IX9ECParameters;
     Fparameters: IX9ECParameters;
 
 
-    class var
-
-      FLock: TCriticalSection;
-
-    class procedure Boot(); static;
-    class constructor CreateX9ECParametersHolder();
-    class destructor DestroyX9ECParametersHolder();
-
   strict protected
   strict protected
+
     function GetParameters: IX9ECParameters; inline;
     function GetParameters: IX9ECParameters; inline;
     function CreateParameters(): IX9ECParameters; virtual; abstract;
     function CreateParameters(): IX9ECParameters; virtual; abstract;
 
 
   public
   public
+    constructor Create();
+    destructor Destroy; override;
     property Parameters: IX9ECParameters read GetParameters;
     property Parameters: IX9ECParameters read GetParameters;
 
 
   end;
   end;
@@ -54,27 +51,20 @@ implementation
 
 
 { TX9ECParametersHolder }
 { TX9ECParametersHolder }
 
 
-class procedure TX9ECParametersHolder.Boot;
+constructor TX9ECParametersHolder.Create;
 begin
 begin
-  if FLock = Nil then
-  begin
-    FLock := TCriticalSection.Create;
-  end;
+  Inherited Create();
+  FLock := TCriticalSection.Create;
 end;
 end;
 
 
-class constructor TX9ECParametersHolder.CreateX9ECParametersHolder;
-begin
-  TX9ECParametersHolder.Boot;
-end;
-
-class destructor TX9ECParametersHolder.DestroyX9ECParametersHolder;
+destructor TX9ECParametersHolder.Destroy;
 begin
 begin
   FLock.Free;
   FLock.Free;
+  inherited Destroy;
 end;
 end;
 
 
 function TX9ECParametersHolder.GetParameters: IX9ECParameters;
 function TX9ECParametersHolder.GetParameters: IX9ECParameters;
 begin
 begin
-
   FLock.Acquire;
   FLock.Acquire;
   try
   try
     if (Fparameters = Nil) then
     if (Fparameters = Nil) then

+ 59 - 34
src/libraries/cryptolib4pascal/CryptoLib.inc

@@ -58,15 +58,27 @@
       {$ELSEIF DEFINED(FREEBSD) OR DEFINED(NETBSD) OR DEFINED(OPENBSD) OR DEFINED(DRAGONFLY)}
       {$ELSEIF DEFINED(FREEBSD) OR DEFINED(NETBSD) OR DEFINED(OPENBSD) OR DEFINED(DRAGONFLY)}
          {$DEFINE CRYPTOLIB_GENERIC_BSD}
          {$DEFINE CRYPTOLIB_GENERIC_BSD}
       {$IFEND}
       {$IFEND}
+  {$ELSEIF DEFINED(ANDROID)}
+     {$DEFINE CRYPTOLIB_ANDROID}
   {$ELSEIF DEFINED(LINUX)}
   {$ELSEIF DEFINED(LINUX)}
      {$DEFINE CRYPTOLIB_LINUX}
      {$DEFINE CRYPTOLIB_LINUX}
+  {$ELSEIF DEFINED(SOLARIS)}
+     {$DEFINE CRYPTOLIB_SOLARIS}
   {$ELSE}
   {$ELSE}
      {$DEFINE CRYPTOLIB_UNDEFINED_UNIX_VARIANTS}
      {$DEFINE CRYPTOLIB_UNDEFINED_UNIX_VARIANTS}
   {$IFEND}
   {$IFEND}
 {$ELSE}
 {$ELSE}
    {$MESSAGE ERROR 'UNSUPPORTED TARGET.'}
    {$MESSAGE ERROR 'UNSUPPORTED TARGET.'}
+{$IFEND}
+
+{$IFDEF CRYPTOLIB_ANDROID}
+   {$DEFINE CRYPTOLIB_LINUX}
 {$ENDIF}
 {$ENDIF}
 
 
+{$IF DEFINED(CRYPTOLIB_LINUX) OR DEFINED(CRYPTOLIB_SOLARIS)}
+   {$DEFINE CRYPTOLIB_HAS_GETRANDOM}
+{$IFEND}
+
 {$DEFINE USE_UNROLLED_VARIANT}
 {$DEFINE USE_UNROLLED_VARIANT}
 
 
 // Disable Overflow and RangeChecks.
 // Disable Overflow and RangeChecks.
@@ -104,6 +116,42 @@
 
 
 {$IFDEF DELPHI}
 {$IFDEF DELPHI}
 
 
+ // XE3 and Above
+{$IF CompilerVersion >= 24.0}
+   {$DEFINE DELPHIXE3_UP}
+   {$DEFINE SUPPORT_TSTREAM_READ_BYTEARRAY_OVERLOAD}
+   {$DEFINE SUPPORT_TSTREAM_WRITE_BYTEARRAY_OVERLOAD}
+   {$LEGACYIFEND ON}
+   {$ZEROBASEDSTRINGS OFF}
+{$IFEND}
+
+  // XE and Above
+{$IF CompilerVersion >= 22.0}
+   {$DEFINE DELPHIXE_UP}
+{$IFEND}
+
+ // XE4 and Above
+{$IF CompilerVersion >= 25.0}
+   {$DEFINE DELPHIXE4_UP}
+   {$DEFINE SHIFT_OVERFLOW_BUG_FIXED}
+{$IFEND}
+
+  // 10.1 Berlin and Above
+{$IF CompilerVersion >= 31.0}
+   {$DEFINE DELPHI10.1_BERLIN_UP}
+   {$DEFINE HAS_VOLATILE}
+{$IFEND}
+
+  // 10.2 Tokyo and Above
+{$IF CompilerVersion >= 32.0}
+   {$DEFINE DELPHI10.2_TOKYO_UP}
+{$IFEND}
+
+  // 10.2 Tokyo and Above
+{$IFNDEF DELPHI10.2_TOKYO_UP}
+   {$MESSAGE ERROR 'This Library requires Delphi Tokyo or higher.'}
+{$ENDIF}
+
 {$IFDEF CPU386}
 {$IFDEF CPU386}
    {$DEFINE CRYPTOLIB_X86}
    {$DEFINE CRYPTOLIB_X86}
 {$ENDIF}
 {$ENDIF}
@@ -128,7 +176,7 @@
 
 
 {$IFDEF IOS}
 {$IFDEF IOS}
    {$DEFINE CRYPTOLIB_IOS}
    {$DEFINE CRYPTOLIB_IOS}
-{$IFEND}
+{$ENDIF}
 
 
 {$IFDEF MSWINDOWS}
 {$IFDEF MSWINDOWS}
    {$DEFINE CRYPTOLIB_MSWINDOWS}
    {$DEFINE CRYPTOLIB_MSWINDOWS}
@@ -138,17 +186,25 @@
    {$DEFINE CRYPTOLIB_MACOS}
    {$DEFINE CRYPTOLIB_MACOS}
 {$ENDIF}
 {$ENDIF}
 
 
+{$IFDEF ANDROID}
+   {$DEFINE CRYPTOLIB_ANDROID}
+{$ENDIF}
+
 {$IF DEFINED(CRYPTOLIB_IOS) OR DEFINED(CRYPTOLIB_MACOS)}
 {$IF DEFINED(CRYPTOLIB_IOS) OR DEFINED(CRYPTOLIB_MACOS)}
    {$DEFINE CRYPTOLIB_APPLE}
    {$DEFINE CRYPTOLIB_APPLE}
 {$IFEND}
 {$IFEND}
 
 
-{$IF DEFINED(LINUX) OR DEFINED(ANDROID)}
+{$IF DEFINED(LINUX) OR DEFINED(CRYPTOLIB_ANDROID)}
    {$DEFINE CRYPTOLIB_LINUX}
    {$DEFINE CRYPTOLIB_LINUX}
+{$IFEND}
+
+{$IFDEF CRYPTOLIB_LINUX}
+   {$DEFINE CRYPTOLIB_HAS_GETRANDOM}
 {$ENDIF}
 {$ENDIF}
 
 
 {$IF DEFINED(CRYPTOLIB_APPLE) OR DEFINED(CRYPTOLIB_LINUX)}
 {$IF DEFINED(CRYPTOLIB_APPLE) OR DEFINED(CRYPTOLIB_LINUX)}
    {$DEFINE CRYPTOLIB_UNIX}
    {$DEFINE CRYPTOLIB_UNIX}
-{$ENDIF}
+{$IFEND}
 
 
 {$DEFINE USE_UNROLLED_VARIANT}
 {$DEFINE USE_UNROLLED_VARIANT}
 
 
@@ -172,37 +228,6 @@
 // Disable Deprecated Warnings
 // Disable Deprecated Warnings
 {$WARN SYMBOL_DEPRECATED OFF}
 {$WARN SYMBOL_DEPRECATED OFF}
 
 
- // XE3 and Above
-{$IF CompilerVersion >= 24.0}
-   {$DEFINE DELPHIXE3_UP}
-   {$DEFINE SUPPORT_TSTREAM_READ_BYTEARRAY_OVERLOAD}
-   {$DEFINE SUPPORT_TSTREAM_WRITE_BYTEARRAY_OVERLOAD}
-   {$LEGACYIFEND ON}
-   {$ZEROBASEDSTRINGS OFF}
-{$IFEND}
-
-  // XE and Above
-{$IF CompilerVersion >= 22.0}
-   {$DEFINE DELPHIXE_UP}
-{$IFEND}
-
- // XE4 and Above
-{$IF CompilerVersion >= 25.0}
-   {$DEFINE DELPHIXE4_UP}
-   {$DEFINE SHIFT_OVERFLOW_BUG_FIXED}
-{$IFEND}
-
-  // 10.2 Tokyo and Above
-{$IF CompilerVersion >= 32.0}
-   {$DEFINE DELPHI10.2_TOKYO_UP}
-{$IFEND}
-
-  // 10.2 Tokyo and Above
-{$IFNDEF DELPHI10.2_TOKYO_UP}
-   {$MESSAGE ERROR 'This Library requires Delphi Tokyo or higher.'}
-{$ENDIF}
-
-
 {$ENDIF DELPHI}
 {$ENDIF DELPHI}
 
 
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)

+ 4 - 0
src/libraries/cryptolib4pascal/CryptoLibHelper.inc

@@ -24,3 +24,7 @@
 {$IF FPC_FULLVERSION < 30004}
 {$IF FPC_FULLVERSION < 30004}
    {$MESSAGE ERROR 'This Library requires FreePascal 3.0.4 or higher.'}
    {$MESSAGE ERROR 'This Library requires FreePascal 3.0.4 or higher.'}
 {$IFEND}
 {$IFEND}
+
+{$IF FPC_FULLVERSION >= 30301}
+   {$DEFINE HAS_VOLATILE}
+{$IFEND}

+ 27 - 6
src/libraries/cryptolib4pascal/README.md

@@ -173,18 +173,39 @@ Available Algorithms
 
 
 * `Delphi Tokyo+`
 * `Delphi Tokyo+`
 
 
-### Supported OSes
+### Supported / Tested OSes
 ----------------------------------------
 ----------------------------------------
 
 
-* `Windows XP+`
+###### Tested OS boxes are checked
+----------------------------------------
+
+* - [x] `Windows XP+`
+
+
+* - [x] `Linux (Including Android and Raspberry PI)`
+
+
+* - [x] `Mac OS X`
+
+
+* - [x] `iOS 2.0+`
+
+
+* - [x] `(Oracle) Solaris`
+
+
+* - [x] `OpenBSD`
+
+
+* - [ ] `FreeBSD`
+
+
+* - [ ] `NetBSD`
 
 
-* `Linux (Including Android and Raspberry PI)`
 
 
-* `macOS 10.7+`
+* - [ ] `DragonBSD`
 
 
-* `iOS 2.0+`
 
 
-* `FreeBSD, NetBSD, OpenBSD and DragonBSD`
 
 
 ### Acknowledgements
 ### Acknowledgements
 ----------------------------------------
 ----------------------------------------

Some files were not shown because too many files changed in this diff