Browse Source

add secp384r1 custom curve.

Ugochukwu Mmaduekwe 7 years ago
parent
commit
fe93c0bd53

+ 10 - 1
CryptoLib.Samples/Delphi.Samples/UsageSamples.dpr

@@ -423,7 +423,16 @@ uses
   ClpSecP256K1Point in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1Point.pas',
   ClpISecP256K1Point in '..\..\CryptoLib\src\Interfaces\ClpISecP256K1Point.pas',
   ClpSecP256K1Curve in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1Curve.pas',
-  ClpISecP256K1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecP256K1Curve.pas';
+  ClpISecP256K1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecP256K1Curve.pas',
+  ClpSecP384R1Field in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP384R1Field.pas',
+  ClpNat384 in '..\..\CryptoLib\src\Math\Raw\ClpNat384.pas',
+  ClpSecP384R1FieldElement in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP384R1FieldElement.pas',
+  ClpISecP384R1FieldElement in '..\..\CryptoLib\src\Interfaces\ClpISecP384R1FieldElement.pas',
+  ClpSecP384R1Point in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP384R1Point.pas',
+  ClpISecP384R1Point in '..\..\CryptoLib\src\Interfaces\ClpISecP384R1Point.pas',
+  ClpSecP384R1Curve in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP384R1Curve.pas',
+  ClpISecP384R1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecP384R1Curve.pas',
+  ClpNat192 in '..\..\CryptoLib\src\Math\Raw\ClpNat192.pas';
 
 begin
   try

+ 10 - 1
CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr

@@ -475,7 +475,16 @@ uses
   ClpSecP256K1Point in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1Point.pas',
   ClpISecP256K1Point in '..\..\CryptoLib\src\Interfaces\ClpISecP256K1Point.pas',
   ClpSecP256K1Curve in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1Curve.pas',
-  ClpISecP256K1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecP256K1Curve.pas';
+  ClpISecP256K1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecP256K1Curve.pas',
+  ClpSecP384R1Field in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP384R1Field.pas',
+  ClpNat384 in '..\..\CryptoLib\src\Math\Raw\ClpNat384.pas',
+  ClpSecP384R1FieldElement in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP384R1FieldElement.pas',
+  ClpISecP384R1FieldElement in '..\..\CryptoLib\src\Interfaces\ClpISecP384R1FieldElement.pas',
+  ClpSecP384R1Point in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP384R1Point.pas',
+  ClpISecP384R1Point in '..\..\CryptoLib\src\Interfaces\ClpISecP384R1Point.pas',
+  ClpSecP384R1Curve in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP384R1Curve.pas',
+  ClpISecP384R1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecP384R1Curve.pas',
+  ClpNat192 in '..\..\CryptoLib\src\Math\Raw\ClpNat192.pas';
 
 begin
 

+ 2 - 3
CryptoLib.Tests/src/Math/EC/Custom/Sec/SecP384R1FieldTests.pas

@@ -38,7 +38,7 @@ uses
   ClpIX9ECParameters,
   ClpSecObjectIdentifiers,
   ClpConverters,
-  ClpSecNamedCurves,
+  ClpCustomNamedCurves,
   ClpIECFieldElement,
   ClpBigInteger;
 
@@ -148,8 +148,7 @@ procedure TTestSecP384R1Field.SetUp;
 begin
   inherited;
   FRandom := TSecureRandom.Create();
-  // FDP := TCustomNamedCurves.GetByOid(TSecObjectIdentifiers.SecP384r1); // original
-  FDP := TSecNamedCurves.GetByOid(TSecObjectIdentifiers.SecP384r1);
+  FDP := TCustomNamedCurves.GetByOid(TSecObjectIdentifiers.SecP384r1);
 
   FQ := FDP.Curve.Field.Characteristic;
 end;

+ 0 - 1
CryptoLib.Tests/src/Math/ECPointTests.pas

@@ -268,7 +268,6 @@ begin
   CheckEquals(True, a.Equals(b));
 end;
 
-//
 procedure TTestECPoint.AssertIFiniteFieldsEqual(a, b: IFiniteField);
 begin
   CheckEquals(True, (a as TObject).Equals(b as TObject));

+ 58 - 13
CryptoLib/src/Crypto/EC/ClpCustomNamedCurves.pas

@@ -33,6 +33,8 @@ uses
   ClpECCurve,
   ClpSecP256K1Curve,
   ClpISecP256K1Curve,
+  ClpSecP384R1Curve,
+  ClpISecP384R1Curve,
   ClpIECInterface,
   ClpX9ECPoint,
   ClpIX9ECPoint,
@@ -70,8 +72,8 @@ type
     // class procedure DefineCurveAlias(const name: String;
     // const oid: IDerObjectIdentifier); static; inline;
 
-    // class function ConfigureCurve(const curve: IECCurve): IECCurve;
-    // static; inline;
+    class function ConfigureCurve(const curve: IECCurve): IECCurve;
+      static; inline;
     class function ConfigureCurveGlv(const c: IECCurve;
       const p: IGlvTypeBParameters): IECCurve; static; inline;
 
@@ -113,7 +115,23 @@ type
     /// <summary>
     /// secp256k1
     /// </summary>
-    TSecP256k1Holder = class sealed(TX9ECParametersHolder,
+    TSecP256K1Holder = class sealed(TX9ECParametersHolder,
+      IX9ECParametersHolder)
+
+    strict protected
+      function CreateParameters(): IX9ECParameters; override;
+
+    public
+      class function Instance(): IX9ECParametersHolder; static;
+
+    end;
+
+  type
+
+    /// <summary>
+    /// secp384r1
+    /// </summary>
+    TSecP384R1Holder = class sealed(TX9ECParametersHolder,
       IX9ECParametersHolder)
 
     strict protected
@@ -171,11 +189,11 @@ end;
 // FnameToCurve.Add(LName, curve);
 // end;
 //
-// class function TCustomNamedCurves.ConfigureCurve(const curve: IECCurve)
-// : IECCurve;
-// begin
-// result := curve;
-// end;
+class function TCustomNamedCurves.ConfigureCurve(const curve: IECCurve)
+  : IECCurve;
+begin
+  result := curve;
+end;
 
 class function TCustomNamedCurves.ConfigureCurveGlv(const c: IECCurve;
   const p: IGlvTypeBParameters): IECCurve;
@@ -250,7 +268,10 @@ begin
   Fnames := TList<String>.Create();
 
   DefineCurveWithOid('secp256k1', TSecObjectIdentifiers.SecP256k1,
-    TSecP256k1Holder.Instance);
+    TSecP256K1Holder.Instance);
+
+  DefineCurveWithOid('secp384r1', TSecObjectIdentifiers.SecP384r1,
+    TSecP384R1Holder.Instance);
 
 end;
 
@@ -263,9 +284,9 @@ begin
   Fnames.Free;
 end;
 
-{ TCustomNamedCurves.TSecP256k1Holder }
+{ TCustomNamedCurves.TSecP256K1Holder }
 
-function TCustomNamedCurves.TSecP256k1Holder.CreateParameters: IX9ECParameters;
+function TCustomNamedCurves.TSecP256K1Holder.CreateParameters: IX9ECParameters;
 var
   curve: IECCurve;
   G: IX9ECPoint;
@@ -294,10 +315,34 @@ begin
   result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
 end;
 
-class function TCustomNamedCurves.TSecP256k1Holder.Instance
+class function TCustomNamedCurves.TSecP256K1Holder.Instance
+  : IX9ECParametersHolder;
+begin
+  result := TSecP256K1Holder.Create();
+end;
+
+{ TCustomNamedCurves.TSecP384R1Holder }
+
+function TCustomNamedCurves.TSecP384R1Holder.CreateParameters: IX9ECParameters;
+var
+  S: TCryptoLibByteArray;
+  curve: IECCurve;
+  G: IX9ECPoint;
+begin
+  S := THex.Decode('A335926AA319A27A1D00896A6773A4827ACDAC73');
+  curve := ConfigureCurve(TSecP384R1Curve.Create() as ISecP384R1Curve);
+  G := TX9ECPoint.Create(curve,
+    THex.Decode('04' +
+    'AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7'
+    + '3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F')
+    );
+  result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
+end;
+
+class function TCustomNamedCurves.TSecP384R1Holder.Instance
   : IX9ECParametersHolder;
 begin
-  result := TSecP256k1Holder.Create();
+  result := TSecP384R1Holder.Create();
 end;
 
 end.

+ 45 - 0
CryptoLib/src/Interfaces/ClpISecP384R1Curve.pas

@@ -0,0 +1,45 @@
+{ *********************************************************************************** }
+{ *                              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 ClpISecP384R1Curve;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECInterface,
+  ClpBigInteger,
+  ClpCryptoLibTypes;
+
+type
+  ISecP384R1LookupTable = Interface(IECLookupTable)
+    ['{F1354F0B-577F-402C-A363-7761CF82DA43}']
+  end;
+
+type
+  ISecP384R1Curve = Interface(IAbstractFpCurve)
+    ['{50639F3D-E15C-4C3C-A7AA-7A8ACA243341}']
+
+    function GetQ: TBigInteger;
+    property Q: TBigInteger read GetQ;
+
+  end;
+
+implementation
+
+end.

+ 38 - 0
CryptoLib/src/Interfaces/ClpISecP384R1FieldElement.pas

@@ -0,0 +1,38 @@
+{ *********************************************************************************** }
+{ *                              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 ClpISecP384R1FieldElement;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECFieldElement,
+  ClpCryptoLibTypes;
+
+type
+  ISecP384R1FieldElement = Interface(IAbstractFpFieldElement)
+    ['{EE28D1BA-2409-4915-99E9-EACD18C420DA}']
+
+    function GetX: TCryptoLibUInt32Array;
+    property X: TCryptoLibUInt32Array read GetX;
+  end;
+
+implementation
+
+end.

+ 35 - 0
CryptoLib/src/Interfaces/ClpISecP384R1Point.pas

@@ -0,0 +1,35 @@
+{ *********************************************************************************** }
+{ *                              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 ClpISecP384R1Point;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECInterface;
+
+type
+  ISecP384R1Point = Interface(IAbstractFpPoint)
+    ['{2F1900E8-0B35-414A-B2EE-EDCA9763E2E8}']
+
+  end;
+
+implementation
+
+end.

+ 269 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP384R1Curve.pas

@@ -0,0 +1,269 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecP384R1Curve;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpHex,
+  ClpBits,
+  ClpNat,
+  ClpECCurve,
+  ClpIECInterface,
+  ClpISecP384R1FieldElement,
+  ClpSecP384R1Point,
+  ClpISecP384R1Curve,
+  ClpISecP384R1Point,
+  ClpIECFieldElement,
+  ClpBigInteger,
+  ClpCryptoLibTypes;
+
+type
+  TSecP384R1Curve = class sealed(TAbstractFpCurve, ISecP384R1Curve)
+
+  strict private
+
+  type
+    TSecP384R1LookupTable = class sealed(TInterfacedObject,
+      ISecP384R1LookupTable, IECLookupTable)
+
+    strict private
+    var
+      Fm_outer: ISecP384R1Curve;
+      Fm_table: TCryptoLibUInt32Array;
+      Fm_size: Int32;
+
+      function GetSize: Int32; virtual;
+
+    public
+
+      constructor Create(const outer: ISecP384R1Curve;
+        table: TCryptoLibUInt32Array; size: Int32);
+
+      function Lookup(index: Int32): IECPoint; virtual;
+
+      property size: Int32 read GetSize;
+
+    end;
+
+  const
+    SECP384R1_DEFAULT_COORDS = Int32(TECCurve.COORD_JACOBIAN);
+    SECP384R1_FE_INTS = Int32(12);
+
+    class var
+
+      Fq: TBigInteger;
+
+    class function GetSecP384R1Curve_Q: TBigInteger; static; inline;
+    class constructor SecP384R1Curve();
+
+  strict protected
+  var
+    Fm_infinity: ISecP384R1Point;
+
+    function GetQ: TBigInteger; virtual;
+    function GetFieldSize: Int32; override;
+    function GetInfinity: IECPoint; override;
+
+    function CloneCurve(): IECCurve; override;
+
+    function CreateRawPoint(const x, y: IECFieldElement;
+      withCompression: Boolean): IECPoint; overload; override;
+
+    function CreateRawPoint(const x, y: IECFieldElement;
+      zs: TCryptoLibGenericArray<IECFieldElement>; withCompression: Boolean)
+      : IECPoint; overload; override;
+
+  public
+    constructor Create();
+    function FromBigInteger(const x: TBigInteger): IECFieldElement; override;
+
+    function SupportsCoordinateSystem(coord: Int32): Boolean; override;
+
+    function CreateCacheSafeLookupTable
+      (points: TCryptoLibGenericArray<IECPoint>; off, len: Int32)
+      : IECLookupTable; override;
+
+    property Q: TBigInteger read GetQ;
+    property Infinity: IECPoint read GetInfinity;
+    property FieldSize: Int32 read GetFieldSize;
+
+    class property SecP384R1Curve_Q: TBigInteger read GetSecP384R1Curve_Q;
+
+  end;
+
+implementation
+
+uses
+  // included here to avoid circular dependency :)
+  ClpSecP384R1FieldElement;
+
+{ TSecP384R1Curve }
+
+class function TSecP384R1Curve.GetSecP384R1Curve_Q: TBigInteger;
+begin
+  result := Fq;
+end;
+
+class constructor TSecP384R1Curve.SecP384R1Curve;
+begin
+  Fq := TBigInteger.Create(1,
+    THex.Decode
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF')
+    );
+end;
+
+constructor TSecP384R1Curve.Create;
+begin
+  Inherited Create(Fq);
+  Fm_infinity := TSecP384R1Point.Create(Self as IECCurve, Nil, Nil);
+  Fm_a := FromBigInteger(TBigInteger.Create(1,
+    THex.Decode
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC'))
+    );
+  Fm_b := FromBigInteger(TBigInteger.Create(1,
+    THex.Decode
+    ('B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF'))
+    );
+  Fm_order := TBigInteger.Create(1,
+    THex.Decode
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973')
+    );
+  Fm_cofactor := TBigInteger.One;
+  Fm_coord := SECP384R1_DEFAULT_COORDS;
+end;
+
+function TSecP384R1Curve.CloneCurve: IECCurve;
+begin
+  result := TSecP384R1Curve.Create();
+end;
+
+function TSecP384R1Curve.CreateCacheSafeLookupTable
+  (points: TCryptoLibGenericArray<IECPoint>; off, len: Int32): IECLookupTable;
+var
+  table: TCryptoLibUInt32Array;
+  pos, i: Int32;
+  p: IECPoint;
+begin
+  System.SetLength(table, len * SECP384R1_FE_INTS * 2);
+
+  pos := 0;
+  for i := 0 to System.Pred(len) do
+  begin
+    p := points[off + i];
+    TNat.Copy(SECP384R1_FE_INTS, (p.RawXCoord as ISecP384R1FieldElement).x, 0,
+      table, pos);
+    pos := pos + SECP384R1_FE_INTS;
+    TNat.Copy(SECP384R1_FE_INTS, (p.RawYCoord as ISecP384R1FieldElement).x, 0,
+      table, pos);
+    pos := pos + SECP384R1_FE_INTS;
+  end;
+
+  result := TSecP384R1LookupTable.Create(Self as ISecP384R1Curve, table, len);
+end;
+
+function TSecP384R1Curve.CreateRawPoint(const x, y: IECFieldElement;
+  withCompression: Boolean): IECPoint;
+begin
+  result := TSecP384R1Point.Create(Self as IECCurve, x, y, withCompression);
+end;
+
+function TSecP384R1Curve.CreateRawPoint(const x, y: IECFieldElement;
+  zs: TCryptoLibGenericArray<IECFieldElement>; withCompression: Boolean)
+  : IECPoint;
+begin
+  result := TSecP384R1Point.Create(Self as IECCurve, x, y, zs, withCompression);
+end;
+
+function TSecP384R1Curve.FromBigInteger(const x: TBigInteger): IECFieldElement;
+begin
+  result := TSecP384R1FieldElement.Create(x);
+end;
+
+function TSecP384R1Curve.GetFieldSize: Int32;
+begin
+  result := Fq.BitLength;
+end;
+
+function TSecP384R1Curve.GetInfinity: IECPoint;
+begin
+  result := Fm_infinity;
+end;
+
+function TSecP384R1Curve.GetQ: TBigInteger;
+begin
+  result := Fq;
+end;
+
+function TSecP384R1Curve.SupportsCoordinateSystem(coord: Int32): Boolean;
+begin
+  case coord of
+    COORD_JACOBIAN:
+      result := True
+  else
+    result := False;
+  end;
+end;
+
+{ TSecP384R1Curve.TSecP384R1LookupTable }
+
+constructor TSecP384R1Curve.TSecP384R1LookupTable.Create
+  (const outer: ISecP384R1Curve; table: TCryptoLibUInt32Array; size: Int32);
+begin
+  Inherited Create();
+  Fm_outer := outer;
+  Fm_table := table;
+  Fm_size := size;
+end;
+
+function TSecP384R1Curve.TSecP384R1LookupTable.GetSize: Int32;
+begin
+  result := Fm_size;
+end;
+
+function TSecP384R1Curve.TSecP384R1LookupTable.Lookup(index: Int32): IECPoint;
+var
+  x, y: TCryptoLibUInt32Array;
+  pos, i, J: Int32;
+  MASK: UInt32;
+begin
+  x := TNat.Create(SECP384R1_FE_INTS);
+  y := TNat.Create(SECP384R1_FE_INTS);
+  pos := 0;
+
+  for i := 0 to System.Pred(Fm_size) do
+  begin
+    MASK := UInt32(TBits.Asr32((i xor index) - 1, 31));
+
+    for J := 0 to System.Pred(SECP384R1_FE_INTS) do
+    begin
+      x[J] := x[J] xor (Fm_table[pos + J] and MASK);
+      y[J] := y[J] xor (Fm_table[pos + SECP384R1_FE_INTS + J] and MASK);
+    end;
+
+    pos := pos + (SECP384R1_FE_INTS * 2);
+  end;
+
+  result := Fm_outer.CreateRawPoint(TSecP384R1FieldElement.Create(x)
+    as ISecP384R1FieldElement, TSecP384R1FieldElement.Create(y)
+    as ISecP384R1FieldElement, False);
+end;
+
+end.

+ 418 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP384R1Field.pas

@@ -0,0 +1,418 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecP384R1Field;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat,
+  ClpNat384,
+  ClpBits,
+  ClpBigInteger,
+  ClpCryptoLibTypes;
+
+type
+  // 2^384 - 2^128 - 2^96 + 2^32 - 1
+  TSecP384R1Field = class sealed(TObject)
+
+  strict private
+  const
+    P11 = UInt32($FFFFFFFF);
+    PExt23 = UInt32($FFFFFFFF);
+
+    class var
+
+      FP, FPExt, FPExtInv: TCryptoLibUInt32Array;
+
+    class function GetP: TCryptoLibUInt32Array; static; inline;
+
+    class procedure AddPInvTo(z: TCryptoLibUInt32Array); static; inline;
+    class procedure SubPInvFrom(z: TCryptoLibUInt32Array); static; inline;
+
+    class constructor CreateSecP384R1Field();
+
+  public
+    class procedure Add(x, y, z: TCryptoLibUInt32Array); static; inline;
+    class procedure AddExt(xx, yy, zz: TCryptoLibUInt32Array); static; inline;
+    class procedure AddOne(x, z: TCryptoLibUInt32Array); static; inline;
+    class function FromBigInteger(const x: TBigInteger): TCryptoLibUInt32Array;
+      static; inline;
+    class procedure Half(x, z: TCryptoLibUInt32Array); static; inline;
+    class procedure Multiply(x, y, z: TCryptoLibUInt32Array); static; inline;
+    class procedure Negate(x, z: TCryptoLibUInt32Array); static; inline;
+    class procedure Reduce(xx, z: TCryptoLibUInt32Array); static; inline;
+    class procedure Reduce32(x: UInt32; z: TCryptoLibUInt32Array);
+      static; inline;
+    class procedure Square(x, z: TCryptoLibUInt32Array); static; inline;
+    class procedure SquareN(x: TCryptoLibUInt32Array; n: Int32;
+      z: TCryptoLibUInt32Array); static; inline;
+    class procedure Subtract(x, y, z: TCryptoLibUInt32Array); static; inline;
+    class procedure SubtractExt(xx, yy, zz: TCryptoLibUInt32Array);
+      static; inline;
+    class procedure Twice(x, z: TCryptoLibUInt32Array); static; inline;
+
+    class property P: TCryptoLibUInt32Array read GetP;
+  end;
+
+implementation
+
+{ TSecP384R1Field }
+
+class constructor TSecP384R1Field.CreateSecP384R1Field;
+begin
+  FP := TCryptoLibUInt32Array.Create($FFFFFFFF, $00000000, $00000000, $FFFFFFFF,
+    $FFFFFFFE, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
+    $FFFFFFFF);
+  FPExt := TCryptoLibUInt32Array.Create($00000001, $FFFFFFFE, $00000000,
+    $00000002, $00000000, $FFFFFFFE, $00000000, $00000002, $00000001, $00000000,
+    $00000000, $00000000, $FFFFFFFE, $00000001, $00000000, $FFFFFFFE, $FFFFFFFD,
+    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
+    $FFFFFFFF);
+  FPExtInv := TCryptoLibUInt32Array.Create($FFFFFFFF, $00000001, $FFFFFFFF,
+    $FFFFFFFD, $FFFFFFFF, $00000001, $FFFFFFFF, $FFFFFFFD, $FFFFFFFE, $FFFFFFFF,
+    $FFFFFFFF, $FFFFFFFF, $00000001, $FFFFFFFE, $FFFFFFFF, $00000001,
+    $00000002);
+end;
+
+class function TSecP384R1Field.GetP: TCryptoLibUInt32Array;
+begin
+  result := FP;
+end;
+
+class procedure TSecP384R1Field.AddPInvTo(z: TCryptoLibUInt32Array);
+var
+  c: Int64;
+begin
+  c := Int64(z[0]) + 1;
+  z[0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[1]) - 1);
+  z[1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  if (c <> 0) then
+  begin
+    c := c + Int64(z[2]);
+    z[2] := UInt32(c);
+    c := TBits.Asr64(c, 32);
+  end;
+  c := c + (Int64(z[3]) + 1);
+  z[3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[4]) + 1);
+  z[4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  if (c <> 0) then
+  begin
+    TNat.IncAt(12, z, 5);
+  end;
+end;
+
+class procedure TSecP384R1Field.SubPInvFrom(z: TCryptoLibUInt32Array);
+var
+  c: Int64;
+begin
+  c := Int64(z[0]) - 1;
+  z[0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[1]) + 1);
+  z[1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  if (c <> 0) then
+  begin
+    c := c + Int64(z[2]);
+    z[2] := UInt32(c);
+    c := TBits.Asr64(c, 32);
+  end;
+  c := c + (Int64(z[3]) - 1);
+  z[3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[4]) - 1);
+  z[4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  if (c <> 0) then
+  begin
+    TNat.DecAt(12, z, 5);
+  end;
+end;
+
+class procedure TSecP384R1Field.Add(x, y, z: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  c := TNat.Add(12, x, y, z);
+  if ((c <> 0) or ((z[11] = P11) and (TNat.Gte(12, z, P)))) then
+  begin
+    AddPInvTo(z);
+  end;
+end;
+
+class procedure TSecP384R1Field.AddExt(xx, yy, zz: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  c := TNat.Add(24, xx, yy, zz);
+  if ((c <> 0) or ((zz[23] = PExt23) and (TNat.Gte(24, zz, FPExt)))) then
+  begin
+    if (TNat.AddTo(System.Length(FPExtInv), FPExtInv, zz) <> 0) then
+    begin
+      TNat.IncAt(24, zz, System.Length(FPExtInv));
+    end;
+  end;
+end;
+
+class procedure TSecP384R1Field.AddOne(x, z: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  c := TNat.Inc(12, x, z);
+  if ((c <> 0) or ((z[11] = P11) and (TNat.Gte(12, z, FP)))) then
+  begin
+    AddPInvTo(z);
+  end;
+end;
+
+class function TSecP384R1Field.FromBigInteger(const x: TBigInteger)
+  : TCryptoLibUInt32Array;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.FromBigInteger(384, x);
+  if ((z[11] = P11) and (TNat.Gte(12, z, FP))) then
+  begin
+    TNat.SubFrom(12, FP, z);
+  end;
+  result := z;
+end;
+
+class procedure TSecP384R1Field.Half(x, z: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  if ((x[0] and 1) = 0) then
+  begin
+    TNat.ShiftDownBit(12, x, 0, z);
+  end
+  else
+  begin
+    c := TNat.Add(12, x, FP, z);
+    TNat.ShiftDownBit(12, z, c);
+  end;
+end;
+
+class procedure TSecP384R1Field.Reduce32(x: UInt32; z: TCryptoLibUInt32Array);
+var
+  cc, xx12: Int64;
+begin
+  cc := 0;
+
+  if (x <> 0) then
+  begin
+    xx12 := x;
+
+    cc := cc + (Int64(z[0]) + xx12);
+    z[0] := UInt32(cc);
+    cc := TBits.Asr64(cc, 32);
+    cc := cc + (Int64(z[1]) - xx12);
+    z[1] := UInt32(cc);
+    cc := TBits.Asr64(cc, 32);
+    if (cc <> 0) then
+    begin
+      cc := cc + Int64(z[2]);
+      z[2] := UInt32(cc);
+      cc := TBits.Asr64(cc, 32);
+    end;
+    cc := cc + (Int64(z[3]) + xx12);
+    z[3] := UInt32(cc);
+    cc := TBits.Asr64(cc, 32);
+    cc := cc + (Int64(z[4]) + xx12);
+    z[4] := UInt32(cc);
+    cc := TBits.Asr64(cc, 32);
+
+{$IFDEF DEBUG}
+    System.Assert((cc = 0) or (cc = 1));
+{$ENDIF DEBUG}
+  end;
+
+  if (((cc <> 0) and (TNat.IncAt(12, z, 5) <> 0)) or
+    ((z[11] = P11) and (TNat.Gte(12, z, P)))) then
+  begin
+    AddPInvTo(z);
+  end;
+end;
+
+class procedure TSecP384R1Field.Reduce(xx, z: TCryptoLibUInt32Array);
+const
+  n: Int64 = 1;
+var
+  cc, xx16, xx17, xx18, xx19, xx20, xx21, xx22, xx23, t0, t1, t2, t3, t4, t5,
+    t6, t7: Int64;
+
+begin
+  xx16 := xx[16];
+  xx17 := xx[17];
+  xx18 := xx[18];
+  xx19 := xx[19];
+  xx20 := xx[20];
+  xx21 := xx[21];
+  xx22 := xx[22];
+  xx23 := xx[23];
+
+  t0 := Int64(xx[12]) + xx20 - n;
+  t1 := Int64(xx[13]) + xx22;
+  t2 := Int64(xx[14]) + xx22 + xx23;
+  t3 := Int64(xx[15]) + xx23;
+  t4 := xx17 + xx21;
+  t5 := xx21 - xx23;
+  t6 := xx22 - xx23;
+  t7 := t0 + t5;
+
+  cc := 0;
+  cc := cc + (Int64(xx[0]) + t7);
+  z[0] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[1]) + xx23 - t0 + t1);
+  z[1] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[2]) - xx21 - t1 + t2);
+  z[2] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[3]) - t2 + t3 + t7);
+  z[3] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[4]) + xx16 + xx21 + t1 - t3 + t7);
+  z[4] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[5]) - xx16 + t1 + t2 + t4);
+  z[5] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[6]) + xx18 - xx17 + t2 + t3);
+  z[6] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[7]) + xx16 + xx19 - xx18 + t3);
+  z[7] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[8]) + xx16 + xx17 + xx20 - xx19);
+  z[8] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[9]) + xx18 - xx20 + t4);
+  z[9] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[10]) + xx18 + xx19 - t5 + t6);
+  z[10] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[11]) + xx19 + xx20 - t6);
+  z[11] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (n);
+
+{$IFDEF DEBUG}
+  System.Assert(cc >= 0);
+{$ENDIF DEBUG}
+  Reduce32(UInt32(cc), z);
+end;
+
+class procedure TSecP384R1Field.Multiply(x, y, z: TCryptoLibUInt32Array);
+var
+  tt: TCryptoLibUInt32Array;
+begin
+  tt := TNat.Create(24);
+  TNat384.Mul(x, y, tt);
+  Reduce(tt, z);
+end;
+
+class procedure TSecP384R1Field.Negate(x, z: TCryptoLibUInt32Array);
+begin
+  if (TNat.IsZero(12, x)) then
+  begin
+    TNat.Zero(12, z);
+  end
+  else
+  begin
+    TNat.Sub(12, FP, x, z);
+  end;
+end;
+
+class procedure TSecP384R1Field.Square(x, z: TCryptoLibUInt32Array);
+var
+  tt: TCryptoLibUInt32Array;
+begin
+  tt := TNat.Create(24);
+  TNat384.Square(x, tt);
+  Reduce(tt, z);
+end;
+
+class procedure TSecP384R1Field.SquareN(x: TCryptoLibUInt32Array; n: Int32;
+  z: TCryptoLibUInt32Array);
+var
+  tt: TCryptoLibUInt32Array;
+begin
+{$IFDEF DEBUG}
+  System.Assert(n > 0);
+{$ENDIF DEBUG}
+  tt := TNat.Create(24);
+  TNat384.Square(x, tt);
+  Reduce(tt, z);
+
+  System.Dec(n);
+  while (n > 0) do
+  begin
+    TNat384.Square(z, tt);
+    Reduce(tt, z);
+    System.Dec(n);
+  end;
+end;
+
+class procedure TSecP384R1Field.Subtract(x, y, z: TCryptoLibUInt32Array);
+var
+  c: Int32;
+begin
+  c := TNat.Sub(12, x, y, z);
+  if (c <> 0) then
+  begin
+    SubPInvFrom(z);
+  end;
+end;
+
+class procedure TSecP384R1Field.SubtractExt(xx, yy, zz: TCryptoLibUInt32Array);
+var
+  c: Int32;
+begin
+  c := TNat.Sub(24, xx, yy, zz);
+  if (c <> 0) then
+  begin
+    if (TNat.SubFrom(System.Length(FPExtInv), FPExtInv, zz) <> 0) then
+    begin
+      TNat.DecAt(24, zz, System.Length(FPExtInv));
+    end;
+  end;
+end;
+
+class procedure TSecP384R1Field.Twice(x, z: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  c := TNat.ShiftUpBit(12, x, 0, z);
+  if ((c <> 0) or ((z[11] = P11) and (TNat.Gte(12, z, FP)))) then
+  begin
+    AddPInvTo(z);
+  end;
+end;
+
+end.

+ 342 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP384R1FieldElement.pas

@@ -0,0 +1,342 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecP384R1FieldElement;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat,
+  ClpMod,
+  ClpSecP384R1Curve,
+  ClpECFieldElement,
+  ClpIECFieldElement,
+  ClpSecP384R1Field,
+  ClpISecP384R1FieldElement,
+  ClpBigInteger,
+  ClpArrayUtils,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SInvalidValueForSecP384R1FieldElement =
+    'Value Invalid for SecP384R1FieldElement "%s"';
+
+type
+  TSecP384R1FieldElement = class(TAbstractFpFieldElement,
+    ISecP384R1FieldElement)
+
+  strict private
+
+    class function GetQ: TBigInteger; static; inline;
+
+  strict protected
+  var
+    Fx: TCryptoLibUInt32Array;
+
+    function GetFieldName: string; override;
+    function GetFieldSize: Int32; override;
+    function GetIsOne: Boolean; override;
+    function GetIsZero: Boolean; override;
+
+    function GetX: TCryptoLibUInt32Array; inline;
+    property X: TCryptoLibUInt32Array read GetX;
+
+  public
+    constructor Create(); overload;
+    constructor Create(const X: TBigInteger); overload;
+    constructor Create(X: TCryptoLibUInt32Array); overload;
+
+    function TestBitZero: Boolean; override;
+    function ToBigInteger(): TBigInteger; override;
+
+    function Add(const b: IECFieldElement): IECFieldElement; override;
+    function AddOne(): IECFieldElement; override;
+    function Subtract(const b: IECFieldElement): IECFieldElement; override;
+
+    function Multiply(const b: IECFieldElement): IECFieldElement; override;
+    function Divide(const b: IECFieldElement): IECFieldElement; override;
+    function Negate(): IECFieldElement; override;
+    function Square(): IECFieldElement; override;
+
+    function Invert(): IECFieldElement; override;
+
+    /// <summary>
+    /// return a sqrt root - the routine verifies that the calculation
+    /// returns the right value - if <br />none exists it returns null.
+    /// </summary>
+    function Sqrt(): IECFieldElement; override;
+
+    function Equals(const other: IECFieldElement): Boolean; overload; override;
+
+    function Equals(const other: ISecP384R1FieldElement): Boolean;
+      reintroduce; overload;
+
+    function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}override;
+
+    property IsZero: Boolean read GetIsZero;
+    property IsOne: Boolean read GetIsOne;
+    property FieldName: string read GetFieldName;
+    property FieldSize: Int32 read GetFieldSize;
+
+    class property Q: TBigInteger read GetQ;
+  end;
+
+implementation
+
+{ TSecP384R1FieldElement }
+
+class function TSecP384R1FieldElement.GetQ: TBigInteger;
+begin
+  result := TSecP384R1Curve.SecP384R1Curve_Q;
+end;
+
+function TSecP384R1FieldElement.GetX: TCryptoLibUInt32Array;
+begin
+  result := Fx;
+end;
+
+constructor TSecP384R1FieldElement.Create;
+begin
+  Inherited Create();
+  Fx := TNat.Create(12);
+end;
+
+constructor TSecP384R1FieldElement.Create(const X: TBigInteger);
+begin
+  if ((not(X.IsInitialized)) or (X.SignValue < 0) or (X.CompareTo(Q) >= 0)) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt
+      (@SInvalidValueForSecP384R1FieldElement, ['x']);
+  end;
+  Inherited Create();
+  Fx := TSecP384R1Field.FromBigInteger(X);
+end;
+
+constructor TSecP384R1FieldElement.Create(X: TCryptoLibUInt32Array);
+begin
+  Inherited Create();
+  Fx := X;
+end;
+
+function TSecP384R1FieldElement.GetFieldName: string;
+begin
+  result := 'SecP384R1Field';
+end;
+
+function TSecP384R1FieldElement.GetFieldSize: Int32;
+begin
+  result := Q.BitLength;
+end;
+
+function TSecP384R1FieldElement.GetHashCode: {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}
+begin
+  result := Q.GetHashCode() xor TArrayUtils.GetArrayHashCode(Fx, 0, 12);
+end;
+
+function TSecP384R1FieldElement.GetIsOne: Boolean;
+begin
+  result := TNat.IsOne(12, Fx);
+end;
+
+function TSecP384R1FieldElement.GetIsZero: Boolean;
+begin
+  result := TNat.IsZero(12, Fx);
+end;
+
+function TSecP384R1FieldElement.Sqrt: IECFieldElement;
+var
+  x1, t1, t2, t3, t4, r: TCryptoLibUInt32Array;
+begin
+  // Raise this element to the exponent 2^382 - 2^126 - 2^94 + 2^30
+  x1 := Fx;
+  if ((TNat.IsZero(12, x1)) or (TNat.IsOne(12, x1))) then
+  begin
+    result := Self as IECFieldElement;
+    Exit;
+  end;
+
+  t1 := TNat.Create(12);
+  t2 := TNat.Create(12);
+  t3 := TNat.Create(12);
+  t4 := TNat.Create(12);
+
+  TSecP384R1Field.Square(x1, t1);
+  TSecP384R1Field.Multiply(t1, x1, t1);
+
+  TSecP384R1Field.SquareN(t1, 2, t2);
+  TSecP384R1Field.Multiply(t2, t1, t2);
+
+  TSecP384R1Field.Square(t2, t2);
+  TSecP384R1Field.Multiply(t2, x1, t2);
+
+  TSecP384R1Field.SquareN(t2, 5, t3);
+  TSecP384R1Field.Multiply(t3, t2, t3);
+
+  TSecP384R1Field.SquareN(t3, 5, t4);
+  TSecP384R1Field.Multiply(t4, t2, t4);
+
+  TSecP384R1Field.SquareN(t4, 15, t2);
+  TSecP384R1Field.Multiply(t2, t4, t2);
+
+  TSecP384R1Field.SquareN(t2, 2, t3);
+  TSecP384R1Field.Multiply(t1, t3, t1);
+
+  TSecP384R1Field.SquareN(t3, 28, t3);
+  TSecP384R1Field.Multiply(t2, t3, t2);
+
+  TSecP384R1Field.SquareN(t2, 60, t3);
+  TSecP384R1Field.Multiply(t3, t2, t3);
+
+  r := t2;
+
+  TSecP384R1Field.SquareN(t3, 120, r);
+  TSecP384R1Field.Multiply(r, t3, r);
+
+  TSecP384R1Field.SquareN(r, 15, r);
+  TSecP384R1Field.Multiply(r, t4, r);
+
+  TSecP384R1Field.SquareN(r, 33, r);
+  TSecP384R1Field.Multiply(r, t1, r);
+
+  TSecP384R1Field.SquareN(r, 64, r);
+  TSecP384R1Field.Multiply(r, x1, r);
+
+  TSecP384R1Field.SquareN(r, 30, t1);
+  TSecP384R1Field.Square(t1, t2);
+
+  if TNat.Eq(12, x1, t2) then
+  begin
+    result := TSecP384R1FieldElement.Create(t1);
+  end
+  else
+  begin
+    result := Nil;
+  end;
+end;
+
+function TSecP384R1FieldElement.TestBitZero: Boolean;
+begin
+  result := TNat.GetBit(Fx, 0) = 1;
+end;
+
+function TSecP384R1FieldElement.ToBigInteger: TBigInteger;
+begin
+  result := TNat.ToBigInteger(12, Fx);
+end;
+
+function TSecP384R1FieldElement.Add(const b: IECFieldElement): IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(12);
+  TSecP384R1Field.Add(Fx, (b as ISecP384R1FieldElement).X, z);
+  result := TSecP384R1FieldElement.Create(z);
+end;
+
+function TSecP384R1FieldElement.AddOne: IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(12);
+  TSecP384R1Field.AddOne(Fx, z);
+  result := TSecP384R1FieldElement.Create(z);
+end;
+
+function TSecP384R1FieldElement.Subtract(const b: IECFieldElement)
+  : IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(12);
+  TSecP384R1Field.Subtract(Fx, (b as ISecP384R1FieldElement).X, z);
+  result := TSecP384R1FieldElement.Create(z);
+end;
+
+function TSecP384R1FieldElement.Multiply(const b: IECFieldElement)
+  : IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(12);
+  TSecP384R1Field.Multiply(Fx, (b as ISecP384R1FieldElement).X, z);
+  result := TSecP384R1FieldElement.Create(z);
+end;
+
+function TSecP384R1FieldElement.Divide(const b: IECFieldElement)
+  : IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(12);
+  TMod.Invert(TSecP384R1Field.P, (b as ISecP384R1FieldElement).X, z);
+  TSecP384R1Field.Multiply(z, Fx, z);
+  result := TSecP384R1FieldElement.Create(z);
+end;
+
+function TSecP384R1FieldElement.Negate: IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(12);
+  TSecP384R1Field.Negate(Fx, z);
+  result := TSecP384R1FieldElement.Create(z);
+end;
+
+function TSecP384R1FieldElement.Square: IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(12);
+  TSecP384R1Field.Square(Fx, z);
+  result := TSecP384R1FieldElement.Create(z);
+end;
+
+function TSecP384R1FieldElement.Invert: IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(12);
+  TMod.Invert(TSecP384R1Field.P, Fx, z);
+  result := TSecP384R1FieldElement.Create(z);
+end;
+
+function TSecP384R1FieldElement.Equals(const other
+  : ISecP384R1FieldElement): Boolean;
+begin
+  if ((Self as ISecP384R1FieldElement) = other) then
+  begin
+    result := true;
+    Exit;
+  end;
+  if (other = Nil) then
+  begin
+    result := false;
+    Exit;
+  end;
+  result := TNat.Eq(12, Fx, other.X);
+end;
+
+function TSecP384R1FieldElement.Equals(const other: IECFieldElement): Boolean;
+begin
+  result := Equals(other as ISecP384R1FieldElement);
+end;
+
+end.

+ 406 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP384R1Point.pas

@@ -0,0 +1,406 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecP384R1Point;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat,
+  ClpNat384,
+  ClpECPoint,
+  ClpSecP384R1Field,
+  ClpISecP384R1Point,
+  ClpISecP384R1FieldElement,
+  ClpIECFieldElement,
+  ClpIECInterface,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SOneOfECFieldElementIsNil = 'Exactly One of the Field Elements is Nil';
+
+type
+  TSecP384R1Point = class sealed(TAbstractFpPoint, ISecP384R1Point)
+
+  strict protected
+    function Detach(): IECPoint; override;
+
+  public
+
+    /// <summary>
+    /// Create a point which encodes without point compression.
+    /// </summary>
+    /// <param name="curve">
+    /// the curve to use
+    /// </param>
+    /// <param name="x">
+    /// affine x co-ordinate
+    /// </param>
+    /// <param name="y">
+    /// affine y co-ordinate
+    /// </param>
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement);
+      overload; deprecated 'Use ECCurve.createPoint to construct points';
+
+    /// <summary>
+    /// Create a point that encodes with or without point compresion.
+    /// </summary>
+    /// <param name="curve">
+    /// the curve to use
+    /// </param>
+    /// <param name="x">
+    /// affine x co-ordinate
+    /// </param>
+    /// <param name="y">
+    /// affine y co-ordinate
+    /// </param>
+    /// <param name="withCompression">
+    /// if true encode with point compression
+    /// </param>
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement;
+      withCompression: Boolean); overload;
+      deprecated
+      'Per-point compression property will be removed, see GetEncoded(boolean)';
+
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement;
+      zs: TCryptoLibGenericArray<IECFieldElement>;
+      withCompression: Boolean); overload;
+
+    function Add(const b: IECPoint): IECPoint; override;
+    function Negate(): IECPoint; override;
+
+    function Twice(): IECPoint; override;
+    function TwicePlus(const b: IECPoint): IECPoint; override;
+
+    function ThreeTimes(): IECPoint; override;
+
+  end;
+
+implementation
+
+uses
+  // included here to avoid circular dependency :)
+  ClpSecP384R1FieldElement;
+
+{ TSecP384R1Point }
+
+constructor TSecP384R1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement);
+begin
+  Create(curve, x, y, false);
+end;
+
+constructor TSecP384R1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement; withCompression: Boolean);
+begin
+  Inherited Create(curve, x, y, withCompression);
+  if ((x = Nil) <> (y = Nil)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SOneOfECFieldElementIsNil);
+  end;
+end;
+
+constructor TSecP384R1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement; zs: TCryptoLibGenericArray<IECFieldElement>;
+  withCompression: Boolean);
+begin
+  Inherited Create(curve, x, y, zs, withCompression);
+end;
+
+function TSecP384R1Point.Add(const b: IECPoint): IECPoint;
+var
+  Lcurve: IECCurve;
+  X1, Y1, X2, Y2, Z1, Z2, X3, Y3, Z3: ISecP384R1FieldElement;
+  c: UInt32;
+  tt1, tt2, t3, t4, U2, S2, U1, S1, H, R, HSquared, G, V: TCryptoLibUInt32Array;
+  Z1IsOne, Z2IsOne: Boolean;
+  zs: TCryptoLibGenericArray<IECFieldElement>;
+begin
+  if (IsInfinity) then
+  begin
+    result := b;
+    Exit;
+  end;
+  if (b.IsInfinity) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+  if ((Self as IECPoint) = b) then
+  begin
+    result := Twice();
+    Exit;
+  end;
+
+  Lcurve := curve;
+
+  X1 := RawXCoord as ISecP384R1FieldElement;
+  Y1 := RawYCoord as ISecP384R1FieldElement;
+  X2 := b.RawXCoord as ISecP384R1FieldElement;
+  Y2 := b.RawYCoord as ISecP384R1FieldElement;
+
+  Z1 := RawZCoords[0] as ISecP384R1FieldElement;
+  Z2 := b.RawZCoords[0] as ISecP384R1FieldElement;
+
+  tt1 := TNat.Create(24);
+  tt2 := TNat.Create(24);
+  t3 := TNat.Create(12);
+  t4 := TNat.Create(12);
+
+  Z1IsOne := Z1.IsOne;
+
+  if (Z1IsOne) then
+  begin
+    U2 := X2.x;
+    S2 := Y2.x;
+  end
+  else
+  begin
+    S2 := t3;
+    TSecP384R1Field.Square(Z1.x, S2);
+
+    U2 := tt2;
+    TSecP384R1Field.Multiply(S2, X2.x, U2);
+
+    TSecP384R1Field.Multiply(S2, Z1.x, S2);
+    TSecP384R1Field.Multiply(S2, Y2.x, S2);
+  end;
+
+  Z2IsOne := Z2.IsOne;
+  if (Z2IsOne) then
+  begin
+    U1 := X1.x;
+    S1 := Y1.x;
+  end
+  else
+  begin
+    S1 := t4;
+    TSecP384R1Field.Square(Z2.x, S1);
+
+    U1 := tt1;
+    TSecP384R1Field.Multiply(S1, X1.x, U1);
+
+    TSecP384R1Field.Multiply(S1, Z2.x, S1);
+    TSecP384R1Field.Multiply(S1, Y1.x, S1);
+  end;
+
+  H := TNat.Create(12);
+  TSecP384R1Field.Subtract(U1, U2, H);
+
+  R := TNat.Create(12);
+  TSecP384R1Field.Subtract(S1, S2, R);
+
+  // Check if b = Self or b = -Self
+  if (TNat.IsZero(12, H)) then
+  begin
+    if (TNat.IsZero(12, R)) then
+    begin
+      // Self = b, i.e. Self must be doubled
+      result := Twice();
+      Exit;
+    end;
+
+    // Self = -b, i.e. the result is the point at infinity
+    result := Lcurve.Infinity;
+    Exit;
+  end;
+
+  HSquared := t3;
+  TSecP384R1Field.Square(H, HSquared);
+
+  G := TNat.Create(12);
+  TSecP384R1Field.Multiply(HSquared, H, G);
+
+  V := t3;
+  TSecP384R1Field.Multiply(HSquared, U1, V);
+
+  TSecP384R1Field.Negate(G, G);
+  TNat384.Mul(S1, G, tt1);
+
+  c := TNat.AddBothTo(12, V, V, G);
+  TSecP384R1Field.Reduce32(c, G);
+
+  X3 := TSecP384R1FieldElement.Create(t4);
+  TSecP384R1Field.Square(R, X3.x);
+  TSecP384R1Field.Subtract(X3.x, G, X3.x);
+
+  Y3 := TSecP384R1FieldElement.Create(G);
+  TSecP384R1Field.Subtract(V, X3.x, Y3.x);
+  TNat384.Mul(Y3.x, R, tt2);
+  TSecP384R1Field.AddExt(tt1, tt2, tt1);
+  TSecP384R1Field.Reduce(tt1, Y3.x);
+
+  Z3 := TSecP384R1FieldElement.Create(H);
+  if (not(Z1IsOne)) then
+  begin
+    TSecP384R1Field.Multiply(Z3.x, Z1.x, Z3.x);
+  end;
+  if (not(Z2IsOne)) then
+  begin
+    TSecP384R1Field.Multiply(Z3.x, Z2.x, Z3.x);
+  end;
+
+  zs := TCryptoLibGenericArray<IECFieldElement>.Create(Z3);
+
+  result := TSecP384R1Point.Create(Lcurve, X3, Y3, zs, IsCompressed)
+    as IECPoint;
+end;
+
+function TSecP384R1Point.Detach: IECPoint;
+begin
+  result := TSecP384R1Point.Create(Nil, AffineXCoord, AffineYCoord) as IECPoint;
+end;
+
+function TSecP384R1Point.Negate: IECPoint;
+begin
+  if (IsInfinity) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  result := TSecP384R1Point.Create(curve, RawXCoord, RawYCoord.Negate(),
+    RawZCoords, IsCompressed) as IECPoint;
+end;
+
+function TSecP384R1Point.ThreeTimes: IECPoint;
+begin
+  if ((IsInfinity) or (RawYCoord.IsZero)) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  // NOTE: Be careful about recursions between TwicePlus and ThreeTimes
+  result := Twice().Add(Self as IECPoint);
+end;
+
+function TSecP384R1Point.Twice: IECPoint;
+var
+  Lcurve: IECCurve;
+  Y1, X1, Z1, X3, Y3, Z3: ISecP384R1FieldElement;
+  c: UInt32;
+  Y1Squared, Z1Squared, T, M, S, t1, t2: TCryptoLibUInt32Array;
+  Z1IsOne: Boolean;
+begin
+
+  if (IsInfinity) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  Lcurve := curve;
+
+  Y1 := RawYCoord as ISecP384R1FieldElement;
+  if (Y1.IsZero) then
+  begin
+    result := Lcurve.Infinity;
+    Exit;
+  end;
+
+  X1 := RawXCoord as ISecP384R1FieldElement;
+  Z1 := RawZCoords[0] as ISecP384R1FieldElement;
+
+  t1 := TNat.Create(12);
+  t2 := TNat.Create(12);
+  Y1Squared := TNat.Create(12);
+  TSecP384R1Field.Square(Y1.x, Y1Squared);
+
+  T := TNat.Create(12);
+  TSecP384R1Field.Square(Y1Squared, T);
+
+  Z1IsOne := Z1.IsOne;
+
+  Z1Squared := Z1.x;
+  if (not(Z1IsOne)) then
+  begin
+    Z1Squared := t2;
+    TSecP384R1Field.Square(Z1.x, Z1Squared);
+  end;
+
+  TSecP384R1Field.Subtract(X1.x, Z1Squared, t1);
+
+  M := t2;
+  TSecP384R1Field.Add(X1.x, Z1Squared, M);
+  TSecP384R1Field.Multiply(M, t1, M);
+  c := TNat.AddBothTo(12, M, M, M);
+  TSecP384R1Field.Reduce32(c, M);
+
+  S := Y1Squared;
+  TSecP384R1Field.Multiply(Y1Squared, X1.x, S);
+  c := TNat.ShiftUpBits(12, S, 2, 0);
+  TSecP384R1Field.Reduce32(c, S);
+
+  c := TNat.ShiftUpBits(12, T, 3, 0, t1);
+  TSecP384R1Field.Reduce32(c, t1);
+
+  X3 := TSecP384R1FieldElement.Create(T);
+  TSecP384R1Field.Square(M, X3.x);
+  TSecP384R1Field.Subtract(X3.x, S, X3.x);
+  TSecP384R1Field.Subtract(X3.x, S, X3.x);
+
+  Y3 := TSecP384R1FieldElement.Create(S);
+  TSecP384R1Field.Subtract(S, X3.x, Y3.x);
+  TSecP384R1Field.Multiply(Y3.x, M, Y3.x);
+  TSecP384R1Field.Subtract(Y3.x, t1, Y3.x);
+
+  Z3 := TSecP384R1FieldElement.Create(M);
+  TSecP384R1Field.Twice(Y1.x, Z3.x);
+  if (not(Z1IsOne)) then
+  begin
+    TSecP384R1Field.Multiply(Z3.x, Z1.x, Z3.x);
+  end;
+
+  result := TSecP384R1Point.Create(Lcurve, X3, Y3,
+    TCryptoLibGenericArray<IECFieldElement>.Create(Z3), IsCompressed)
+    as IECPoint;
+end;
+
+function TSecP384R1Point.TwicePlus(const b: IECPoint): IECPoint;
+var
+  Y1: IECFieldElement;
+begin
+  if ((Self as IECPoint) = b) then
+  begin
+    result := ThreeTimes();
+    Exit;
+  end;
+  if (IsInfinity) then
+  begin
+    result := b;
+    Exit;
+  end;
+  if (b.IsInfinity) then
+  begin
+    result := Twice();
+    Exit;
+  end;
+
+  Y1 := RawYCoord;
+  if (Y1.IsZero) then
+  begin
+    result := b;
+    Exit;
+  end;
+
+  result := Twice().Add(b);
+end;
+
+end.

+ 1415 - 0
CryptoLib/src/Math/Raw/ClpNat192.pas

@@ -0,0 +1,1415 @@
+{ *********************************************************************************** }
+{ *                              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 ClpNat192;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpBits,
+  ClpNat,
+  ClpBigInteger,
+  ClpConverters,
+  ClpCryptoLibTypes;
+
+type
+  TNat192 = class sealed(TObject)
+
+  strict private
+  const
+    M = UInt64($FFFFFFFF);
+
+  public
+    class function Add(x, y, z: TCryptoLibUInt32Array): UInt32;
+      overload; static;
+
+    class function AddBothTo(x, y, z: TCryptoLibUInt32Array): UInt32;
+      overload; static;
+
+    class function AddTo(x, z: TCryptoLibUInt32Array): UInt32; overload; static;
+    class function AddTo(x: TCryptoLibUInt32Array; xOff: Int32;
+      z: TCryptoLibUInt32Array; zOff: Int32; cIn: UInt32): UInt32;
+      overload; static;
+
+    class function AddToEachOther(u: TCryptoLibUInt32Array; uOff: Int32;
+      v: TCryptoLibUInt32Array; vOff: Int32): UInt32; static;
+
+    class procedure Copy(x, z: TCryptoLibUInt32Array); overload; static; inline;
+    class procedure Copy(x: TCryptoLibUInt32Array; xOff: Int32;
+      z: TCryptoLibUInt32Array; zOff: Int32); overload; static; inline;
+
+    class procedure Copy64(x, z: TCryptoLibUInt64Array); overload;
+      static; inline;
+
+    class procedure Copy64(x: TCryptoLibUInt64Array; xOff: Int32;
+      z: TCryptoLibUInt64Array; zOff: Int32); overload; static; inline;
+
+    class function Create(): TCryptoLibUInt32Array; static; inline;
+
+    class function Create64(): TCryptoLibUInt64Array; static; inline;
+
+    class function CreateExt(): TCryptoLibUInt32Array; static; inline;
+
+    class function CreateExt64(): TCryptoLibUInt64Array; static; inline;
+
+    class function Diff(x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+      zOff: Int32): Boolean; static; inline;
+
+    class function Eq(x, y: TCryptoLibUInt32Array): Boolean; static;
+
+    class function Eq64(x, y: TCryptoLibUInt64Array): Boolean; static;
+
+    class function FromBigInteger(const x: TBigInteger)
+      : TCryptoLibUInt32Array; static;
+
+    class function FromBigInteger64(const x: TBigInteger)
+      : TCryptoLibUInt64Array; static;
+
+    class function GetBit(x: TCryptoLibUInt32Array; bit: Int32): UInt32;
+      static; inline;
+
+    class function Gte(x, y: TCryptoLibUInt32Array): Boolean; overload; static;
+
+    class function Gte(x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32): Boolean; overload; static;
+
+    class function IsOne(x: TCryptoLibUInt32Array): Boolean; static;
+
+    class function IsOne64(x: TCryptoLibUInt64Array): Boolean; static;
+
+    class function IsZero(x: TCryptoLibUInt32Array): Boolean; static;
+
+    class function IsZero64(x: TCryptoLibUInt64Array): Boolean; static;
+
+    class procedure Mul(x, y, zz: TCryptoLibUInt32Array); overload; static;
+
+    class procedure Mul(x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32; zz: TCryptoLibUInt32Array;
+      zzOff: Int32); overload; static;
+
+    class function MulAddTo(x, y, zz: TCryptoLibUInt32Array): UInt32;
+      overload; static;
+
+    class function MulAddTo(x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32; zz: TCryptoLibUInt32Array;
+      zzOff: Int32): UInt32; overload; static;
+
+    class function Mul33Add(w: UInt32; x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+      zOff: Int32): UInt64; static;
+
+    class function MulWordAddExt(x: UInt32; yy: TCryptoLibUInt32Array;
+      yyOff: Int32; zz: TCryptoLibUInt32Array; zzOff: Int32): UInt32; static;
+
+    class function Mul33DWordAdd(x: UInt32; y: UInt64; z: TCryptoLibUInt32Array;
+      zOff: Int32): UInt32; static;
+
+    class function Mul33WordAdd(x, y: UInt32; z: TCryptoLibUInt32Array;
+      zOff: Int32): UInt32; static;
+
+    class function MulWordDwordAdd(x: UInt32; y: UInt64;
+      z: TCryptoLibUInt32Array; zOff: Int32): UInt32; static;
+
+    class function MulWord(x: UInt32; y, z: TCryptoLibUInt32Array; zOff: Int32)
+      : UInt32; static;
+
+    class procedure Square(x, zz: TCryptoLibUInt32Array); overload; static;
+
+    class procedure Square(x: TCryptoLibUInt32Array; xOff: Int32;
+      zz: TCryptoLibUInt32Array; zzOff: Int32); overload; static;
+
+    class function Sub(x, y, z: TCryptoLibUInt32Array): Int32; overload; static;
+
+    class function Sub(x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+      zOff: Int32): Int32; overload; static;
+
+    class function SubBothFrom(x, y, z: TCryptoLibUInt32Array): Int32; static;
+
+    class function SubFrom(x, z: TCryptoLibUInt32Array): Int32;
+      overload; static;
+
+    class function SubFrom(x: TCryptoLibUInt32Array; xOff: Int32;
+      z: TCryptoLibUInt32Array; zOff: Int32): Int32; overload; static;
+
+    class function ToBigInteger(x: TCryptoLibUInt32Array): TBigInteger; static;
+
+    class function ToBigInteger64(x: TCryptoLibUInt64Array)
+      : TBigInteger; static;
+
+    class procedure Zero(z: TCryptoLibUInt32Array); static; inline;
+
+  end;
+
+implementation
+
+{ TNat192 }
+
+class function TNat192.Add(x, y, z: TCryptoLibUInt32Array): UInt32;
+var
+  c: UInt64;
+begin
+  c := 0;
+  c := c + (UInt64(x[0]) + y[0]);
+  z[0] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[1]) + y[1]);
+  z[1] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[2]) + y[2]);
+  z[2] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[3]) + y[3]);
+  z[3] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[4]) + y[4]);
+  z[4] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[5]) + y[5]);
+  z[5] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat192.AddBothTo(x, y, z: TCryptoLibUInt32Array): UInt32;
+var
+  c: UInt64;
+begin
+  c := 0;
+  c := c + (UInt64(x[0]) + y[0] + z[0]);
+  z[0] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[1]) + y[1] + z[1]);
+  z[1] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[2]) + y[2] + z[2]);
+  z[2] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[3]) + y[3] + z[3]);
+  z[3] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[4]) + y[4] + z[4]);
+  z[4] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[5]) + y[5] + z[5]);
+  z[5] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat192.AddTo(x, z: TCryptoLibUInt32Array): UInt32;
+var
+  c: UInt64;
+begin
+  c := 0;
+  c := c + (UInt64(x[0]) + z[0]);
+  z[0] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[1]) + z[1]);
+  z[1] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[2]) + z[2]);
+  z[2] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[3]) + z[3]);
+  z[3] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[4]) + z[4]);
+  z[4] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[5]) + z[5]);
+  z[5] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat192.AddTo(x: TCryptoLibUInt32Array; xOff: Int32;
+  z: TCryptoLibUInt32Array; zOff: Int32; cIn: UInt32): UInt32;
+var
+  c: UInt64;
+begin
+  c := cIn;
+  c := c + (UInt64(x[xOff + 0]) + z[zOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 1]) + z[zOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 2]) + z[zOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 3]) + z[zOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 4]) + z[zOff + 4]);
+  z[zOff + 4] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 5]) + z[zOff + 5]);
+  z[zOff + 5] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat192.AddToEachOther(u: TCryptoLibUInt32Array; uOff: Int32;
+  v: TCryptoLibUInt32Array; vOff: Int32): UInt32;
+var
+  c: UInt64;
+begin
+  c := 0;
+  c := c + (UInt64(u[uOff + 0]) + v[vOff + 0]);
+  u[uOff + 0] := UInt32(c);
+  v[vOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(u[uOff + 1]) + v[vOff + 1]);
+  u[uOff + 1] := UInt32(c);
+  v[vOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(u[uOff + 2]) + v[vOff + 2]);
+  u[uOff + 2] := UInt32(c);
+  v[vOff + 2] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(u[uOff + 3]) + v[vOff + 3]);
+  u[uOff + 3] := UInt32(c);
+  v[vOff + 3] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(u[uOff + 4]) + v[vOff + 4]);
+  u[uOff + 4] := UInt32(c);
+  v[vOff + 4] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(u[uOff + 5]) + v[vOff + 5]);
+  u[uOff + 5] := UInt32(c);
+  v[vOff + 5] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class procedure TNat192.Copy(x, z: TCryptoLibUInt32Array);
+begin
+  System.Move(x[0], z[0], 6 * System.SizeOf(UInt32));
+end;
+
+class procedure TNat192.Copy(x: TCryptoLibUInt32Array; xOff: Int32;
+  z: TCryptoLibUInt32Array; zOff: Int32);
+begin
+  System.Move(x[xOff], z[zOff], 6 * System.SizeOf(UInt32));
+end;
+
+class procedure TNat192.Copy64(x, z: TCryptoLibUInt64Array);
+begin
+  System.Move(x[0], z[0], 3 * System.SizeOf(UInt64));
+end;
+
+class procedure TNat192.Copy64(x: TCryptoLibUInt64Array; xOff: Int32;
+  z: TCryptoLibUInt64Array; zOff: Int32);
+begin
+  System.Move(x[xOff], z[zOff], 3 * System.SizeOf(UInt64));
+end;
+
+class function TNat192.Create: TCryptoLibUInt32Array;
+begin
+  System.SetLength(result, 6);
+end;
+
+class function TNat192.Create64: TCryptoLibUInt64Array;
+begin
+  System.SetLength(result, 3);
+end;
+
+class function TNat192.CreateExt: TCryptoLibUInt32Array;
+begin
+  System.SetLength(result, 12);
+end;
+
+class function TNat192.CreateExt64: TCryptoLibUInt64Array;
+begin
+  System.SetLength(result, 6);
+end;
+
+class function TNat192.Diff(x: TCryptoLibUInt32Array; xOff: Int32;
+  y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+  zOff: Int32): Boolean;
+var
+  pos: Boolean;
+begin
+  pos := Gte(x, xOff, y, yOff);
+  if (pos) then
+  begin
+    Sub(x, xOff, y, yOff, z, zOff);
+  end
+  else
+  begin
+    Sub(y, yOff, x, xOff, z, zOff);
+  end;
+  result := pos;
+end;
+
+class function TNat192.Eq(x, y: TCryptoLibUInt32Array): Boolean;
+var
+  i: Int32;
+begin
+  i := 5;
+  while i >= 0 do
+  begin
+    if (x[i] <> y[i]) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Dec(i);
+  end;
+  result := true;
+end;
+
+class function TNat192.Eq64(x, y: TCryptoLibUInt64Array): Boolean;
+var
+  i: Int32;
+begin
+  i := 2;
+  while i >= 0 do
+  begin
+    if (x[i] <> y[i]) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Dec(i);
+  end;
+  result := true;
+end;
+
+class function TNat192.FromBigInteger(const x: TBigInteger)
+  : TCryptoLibUInt32Array;
+var
+  i: Int32;
+  Lx: TBigInteger;
+begin
+  Lx := x;
+  if ((Lx.SignValue < 0) or (Lx.BitLength > 192)) then
+  begin
+    raise EArgumentCryptoLibException.Create('');
+  end;
+
+  result := Create();
+  i := 0;
+  while (Lx.SignValue <> 0) do
+  begin
+    result[i] := UInt32(Lx.Int32Value);
+    System.Inc(i);
+    Lx := Lx.ShiftRight(32);
+  end;
+end;
+
+class function TNat192.FromBigInteger64(const x: TBigInteger)
+  : TCryptoLibUInt64Array;
+var
+  i: Int32;
+  Lx: TBigInteger;
+begin
+  Lx := x;
+  if ((Lx.SignValue < 0) or (Lx.BitLength > 192)) then
+  begin
+    raise EArgumentCryptoLibException.Create('');
+  end;
+
+  result := Create64();
+  i := 0;
+  while (Lx.SignValue <> 0) do
+  begin
+    result[i] := UInt64(Lx.Int64Value);
+    System.Inc(i);
+    Lx := Lx.ShiftRight(64);
+  end;
+end;
+
+class function TNat192.GetBit(x: TCryptoLibUInt32Array; bit: Int32): UInt32;
+var
+  w, b: Int32;
+begin
+  if (bit = 0) then
+  begin
+    result := x[0] and 1;
+    Exit;
+  end;
+  w := TBits.Asr32(bit, 5);
+  if ((w < 0) or (w >= 6)) then
+  begin
+    result := 0;
+    Exit;
+  end;
+  b := bit and 31;
+  result := (x[w] shr b) and 1;
+end;
+
+class function TNat192.Gte(x, y: TCryptoLibUInt32Array): Boolean;
+var
+  i: Int32;
+  x_i, y_i: UInt32;
+begin
+  i := 5;
+  while i >= 0 do
+  begin
+    x_i := x[i];
+    y_i := y[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 TNat192.Gte(x: TCryptoLibUInt32Array; xOff: Int32;
+  y: TCryptoLibUInt32Array; yOff: Int32): Boolean;
+var
+  i: Int32;
+  x_i, y_i: UInt32;
+begin
+  i := 5;
+  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 TNat192.IsOne(x: TCryptoLibUInt32Array): Boolean;
+var
+  i: Int32;
+begin
+  if (x[0] <> 1) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  i := 1;
+  while i < 6 do
+  begin
+    if (x[i] <> 0) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Inc(i);
+  end;
+  result := true;
+end;
+
+class function TNat192.IsOne64(x: TCryptoLibUInt64Array): Boolean;
+var
+  i: Int32;
+begin
+  if (x[0] <> UInt64(1)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  i := 1;
+  while i < 3 do
+  begin
+    if (x[i] <> UInt64(0)) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Inc(i);
+  end;
+  result := true;
+end;
+
+class function TNat192.IsZero(x: TCryptoLibUInt32Array): Boolean;
+var
+  i: Int32;
+begin
+  i := 0;
+  while i < 6 do
+  begin
+    if (x[i] <> 0) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Inc(i);
+  end;
+  result := true;
+end;
+
+class function TNat192.IsZero64(x: TCryptoLibUInt64Array): Boolean;
+var
+  i: Int32;
+begin
+  i := 0;
+  while i < 3 do
+  begin
+    if (x[i] <> UInt64(0)) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Inc(i);
+  end;
+  result := true;
+end;
+
+class procedure TNat192.Mul(x, y, zz: TCryptoLibUInt32Array);
+var
+  c, x_0, x_i, y_0, y_1, y_2, y_3, y_4, y_5: UInt64;
+  i: Int32;
+begin
+  y_0 := y[0];
+  y_1 := y[1];
+  y_2 := y[2];
+  y_3 := y[3];
+  y_4 := y[4];
+  y_5 := y[5];
+
+  c := 0;
+  x_0 := x[0];
+  c := c + (x_0 * y_0);
+  zz[0] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_1);
+  zz[1] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_2);
+  zz[2] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_3);
+  zz[3] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_4);
+  zz[4] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_5);
+  zz[5] := UInt32(c);
+  c := c shr 32;
+  zz[6] := UInt32(c);
+
+  for i := 1 to System.Pred(6) do
+  begin
+    c := 0;
+    x_i := x[i];
+    c := c + (x_i * y_0 + zz[i + 0]);
+    zz[i + 0] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_1 + zz[i + 1]);
+    zz[i + 1] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_2 + zz[i + 2]);
+    zz[i + 2] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_3 + zz[i + 3]);
+    zz[i + 3] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_4 + zz[i + 4]);
+    zz[i + 4] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_5 + zz[i + 5]);
+    zz[i + 5] := UInt32(c);
+    c := c shr 32;
+    zz[i + 6] := UInt32(c);
+  end;
+end;
+
+class procedure TNat192.Mul(x: TCryptoLibUInt32Array; xOff: Int32;
+  y: TCryptoLibUInt32Array; yOff: Int32; zz: TCryptoLibUInt32Array;
+  zzOff: Int32);
+var
+  c, x_0, x_i, y_0, y_1, y_2, y_3, y_4, y_5: UInt64;
+  i: Int32;
+begin
+  y_0 := y[yOff + 0];
+  y_1 := y[yOff + 1];
+  y_2 := y[yOff + 2];
+  y_3 := y[yOff + 3];
+  y_4 := y[yOff + 4];
+  y_5 := y[yOff + 5];
+
+  c := 0;
+  x_0 := x[xOff + 0];
+  c := c + (x_0 * y_0);
+  zz[zzOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_1);
+  zz[zzOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_2);
+  zz[zzOff + 2] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_3);
+  zz[zzOff + 3] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_4);
+  zz[zzOff + 4] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_5);
+  zz[zzOff + 5] := UInt32(c);
+  c := c shr 32;
+  zz[zzOff + 6] := UInt32(c);
+
+  for i := 1 to System.Pred(6) do
+  begin
+    System.Inc(zzOff);
+    c := 0;
+    x_i := x[xOff + i];
+    c := c + (x_i * y_0 + zz[zzOff + 0]);
+    zz[zzOff + 0] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_1 + zz[zzOff + 1]);
+    zz[zzOff + 1] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_2 + zz[zzOff + 2]);
+    zz[zzOff + 2] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_3 + zz[zzOff + 3]);
+    zz[zzOff + 3] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_4 + zz[zzOff + 4]);
+    zz[zzOff + 4] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_5 + zz[zzOff + 5]);
+    zz[zzOff + 5] := UInt32(c);
+    c := c shr 32;
+    zz[zzOff + 6] := UInt32(c);
+  end;
+end;
+
+class function TNat192.MulAddTo(x, y, zz: TCryptoLibUInt32Array): UInt32;
+var
+  c, x_i, y_0, y_1, y_2, y_3, y_4, y_5, zc: UInt64;
+  i: Int32;
+begin
+  y_0 := y[0];
+  y_1 := y[1];
+  y_2 := y[2];
+  y_3 := y[3];
+  y_4 := y[4];
+  y_5 := y[5];
+
+  zc := 0;
+  for i := 0 to System.Pred(6) do
+  begin
+    c := 0;
+    x_i := x[i];
+    c := c + (x_i * y_0 + zz[i + 0]);
+    zz[i + 0] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_1 + zz[i + 1]);
+    zz[i + 1] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_2 + zz[i + 2]);
+    zz[i + 2] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_3 + zz[i + 3]);
+    zz[i + 3] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_4 + zz[i + 4]);
+    zz[i + 4] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_5 + zz[i + 5]);
+    zz[i + 5] := UInt32(c);
+    c := c shr 32;
+    c := c + (zc + zz[i + 6]);
+    zz[i + 6] := UInt32(c);
+    zc := c shr 32;
+  end;
+  result := UInt32(zc);
+end;
+
+class function TNat192.MulAddTo(x: TCryptoLibUInt32Array; xOff: Int32;
+  y: TCryptoLibUInt32Array; yOff: Int32; zz: TCryptoLibUInt32Array;
+  zzOff: Int32): UInt32;
+var
+  c, x_i, y_0, y_1, y_2, y_3, y_4, y_5, zc: UInt64;
+  i: Int32;
+begin
+  y_0 := y[yOff + 0];
+  y_1 := y[yOff + 1];
+  y_2 := y[yOff + 2];
+  y_3 := y[yOff + 3];
+  y_4 := y[yOff + 4];
+  y_5 := y[yOff + 5];
+
+  zc := 0;
+  for i := 0 to System.Pred(6) do
+  begin
+    c := 0;
+    x_i := x[xOff + i];
+    c := c + (x_i * y_0 + zz[zzOff + 0]);
+    zz[zzOff + 0] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_1 + zz[zzOff + 1]);
+    zz[zzOff + 1] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_2 + zz[zzOff + 2]);
+    zz[zzOff + 2] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_3 + zz[zzOff + 3]);
+    zz[zzOff + 3] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_4 + zz[zzOff + 4]);
+    zz[zzOff + 4] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_5 + zz[zzOff + 5]);
+    zz[zzOff + 5] := UInt32(c);
+    c := c shr 32;
+    c := c + (zc + zz[zzOff + 6]);
+    zz[zzOff + 6] := UInt32(c);
+    zc := c shr 32;
+    System.Inc(zzOff);
+  end;
+  result := UInt32(zc);
+end;
+
+class function TNat192.Mul33Add(w: UInt32; x: TCryptoLibUInt32Array;
+  xOff: Int32; y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+  zOff: Int32): UInt64;
+var
+  c, wVal, x0, x1, x2, x3, x4, x5: UInt64;
+begin
+{$IFDEF DEBUG}
+  System.Assert(w shr 31 = 0);
+{$ENDIF DEBUG}
+  c := 0;
+  wVal := w;
+  x0 := x[xOff + 0];
+  c := c + (wVal * x0 + y[yOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  x1 := x[xOff + 1];
+  c := c + (wVal * x1 + x0 + y[yOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  x2 := x[xOff + 2];
+  c := c + (wVal * x2 + x1 + y[yOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  x3 := x[xOff + 3];
+  c := c + (wVal * x3 + x2 + y[yOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := c shr 32;
+  x4 := x[xOff + 4];
+  c := c + (wVal * x4 + x3 + y[yOff + 4]);
+  z[zOff + 4] := UInt32(c);
+  c := c shr 32;
+  x5 := x[xOff + 5];
+  c := c + (wVal * x5 + x4 + y[yOff + 5]);
+  z[zOff + 5] := UInt32(c);
+  c := c shr 32;
+  c := c + x5;
+  result := c;
+end;
+
+class function TNat192.MulWordAddExt(x: UInt32; yy: TCryptoLibUInt32Array;
+  yyOff: Int32; zz: TCryptoLibUInt32Array; zzOff: Int32): UInt32;
+var
+  c, xVal: UInt64;
+begin
+{$IFDEF DEBUG}
+  System.Assert(yyOff <= 6);
+  System.Assert(zzOff <= 6);
+{$ENDIF DEBUG}
+  c := 0;
+  xVal := x;
+  c := c + (xVal * yy[yyOff + 0] + zz[zzOff + 0]);
+  zz[zzOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * yy[yyOff + 1] + zz[zzOff + 1]);
+  zz[zzOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * yy[yyOff + 2] + zz[zzOff + 2]);
+  zz[zzOff + 2] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * yy[yyOff + 3] + zz[zzOff + 3]);
+  zz[zzOff + 3] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * yy[yyOff + 4] + zz[zzOff + 4]);
+  zz[zzOff + 4] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * yy[yyOff + 5] + zz[zzOff + 5]);
+  zz[zzOff + 5] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat192.Mul33DWordAdd(x: UInt32; y: UInt64;
+  z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
+var
+  c, xVal, y00, y01: UInt64;
+begin
+{$IFDEF DEBUG}
+  System.Assert(x shr 31 = 0);
+  System.Assert(zOff <= 2);
+{$ENDIF DEBUG}
+  c := 0;
+  xVal := x;
+  y00 := y and M;
+  c := c + (xVal * y00 + z[zOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  y01 := y shr 32;
+  c := c + (xVal * y01 + y00 + z[zOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (y01 + z[zOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  c := c + (z[zOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := c shr 32;
+  if c = 0 then
+  begin
+    result := 0;
+  end
+  else
+  begin
+    result := TNat.IncAt(6, z, zOff, 4);
+  end;
+end;
+
+class function TNat192.Mul33WordAdd(x, y: UInt32; z: TCryptoLibUInt32Array;
+  zOff: Int32): UInt32;
+var
+  c, yVal: UInt64;
+begin
+{$IFDEF DEBUG}
+  System.Assert(x shr 31 = 0);
+  System.Assert(zOff <= 3);
+{$ENDIF DEBUG}
+  c := 0;
+  yVal := y;
+  c := c + (yVal * x + z[zOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (yVal + z[zOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (z[zOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  if c = 0 then
+  begin
+    result := 0;
+  end
+  else
+  begin
+    result := TNat.IncAt(6, z, zOff, 3);
+  end;
+end;
+
+class function TNat192.MulWordDwordAdd(x: UInt32; y: UInt64;
+  z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
+var
+  c, xVal: UInt64;
+begin
+{$IFDEF DEBUG}
+  System.Assert(zOff <= 3);
+{$ENDIF DEBUG}
+  c := 0;
+  xVal := x;
+  c := c + (xVal * y + z[zOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * (y shr 32) + z[zOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (z[zOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  if c = 0 then
+  begin
+    result := 0;
+  end
+  else
+  begin
+    result := TNat.IncAt(6, z, zOff, 3);
+  end;
+end;
+
+class function TNat192.MulWord(x: UInt32; y, z: TCryptoLibUInt32Array;
+  zOff: Int32): UInt32;
+var
+  c, xVal: UInt64;
+  i: Int32;
+begin
+  c := 0;
+  xVal := x;
+  i := 0;
+  repeat
+    c := c + (xVal * y[i]);
+    z[zOff + i] := UInt32(c);
+    c := c shr 32;
+    System.Inc(i);
+  until not(i < 6);
+  result := UInt32(c);
+end;
+
+class procedure TNat192.Square(x, zz: TCryptoLibUInt32Array);
+var
+  x_0, zz_1, xVal, p, x_1, zz_2, x_2, zz_3, zz_4, x_3, zz_5, zz_6, x_4, zz_7,
+    zz_8, x_5, zz_9, zz_10: UInt64;
+  c, w: UInt32;
+  i, j: Int32;
+begin
+  x_0 := x[0];
+  c := 0;
+  i := 5;
+  j := 12;
+
+  repeat
+    xVal := x[i];
+    System.Dec(i);
+    p := xVal * xVal;
+    System.Dec(j);
+    zz[j] := (c shl 31) or UInt32(p shr 33);
+    System.Dec(j);
+    zz[j] := UInt32(p shr 1);
+    c := UInt32(p);
+  until not(i > 0);
+
+  p := x_0 * x_0;
+  zz_1 := UInt64(c shl 31) or (p shr 33);
+  zz[0] := UInt32(p);
+  c := UInt32(p shr 32) and 1;
+
+  x_1 := x[1];
+  zz_2 := zz[2];
+
+  zz_1 := zz_1 + (x_1 * x_0);
+  w := UInt32(zz_1);
+  zz[1] := (w shl 1) or c;
+  c := w shr 31;
+  zz_2 := zz_2 + (zz_1 shr 32);
+
+  x_2 := x[2];
+  zz_3 := zz[3];
+  zz_4 := zz[4];
+
+  zz_2 := zz_2 + (x_2 * x_0);
+  w := UInt32(zz_2);
+  zz[2] := (w shl 1) or c;
+  c := w shr 31;
+  zz_3 := zz_3 + ((zz_2 shr 32) + x_2 * x_1);
+  zz_4 := zz_4 + (zz_3 shr 32);
+  zz_3 := zz_3 and M;
+
+  x_3 := x[3];
+  zz_5 := zz[5] + (zz_4 shr 32);
+  zz_4 := zz_4 and M;
+  zz_6 := zz[6] + (zz_5 shr 32);
+  zz_5 := zz_5 and M;
+
+  zz_3 := zz_3 + (x_3 * x_0);
+  w := UInt32(zz_3);
+  zz[3] := (w shl 1) or c;
+  c := w shr 31;
+  zz_4 := zz_4 + ((zz_3 shr 32) + x_3 * x_1);
+  zz_5 := zz_5 + ((zz_4 shr 32) + x_3 * x_2);
+  zz_4 := zz_4 and M;
+  zz_6 := zz_6 + (zz_5 shr 32);
+  zz_5 := zz_5 and M;
+
+  x_4 := x[4];
+  zz_7 := zz[7] + (zz_6 shr 32);
+  zz_6 := zz_6 and M;
+  zz_8 := zz[8] + (zz_7 shr 32);
+  zz_7 := zz_7 and M;
+
+  zz_4 := zz_4 + (x_4 * x_0);
+  w := UInt32(zz_4);
+  zz[4] := (w shl 1) or c;
+  c := w shr 31;
+  zz_5 := zz_5 + ((zz_4 shr 32) + x_4 * x_1);
+  zz_6 := zz_6 + ((zz_5 shr 32) + x_4 * x_2);
+  zz_5 := zz_5 and M;
+  zz_7 := zz_7 + ((zz_6 shr 32) + x_4 * x_3);
+  zz_6 := zz_6 and M;
+  zz_8 := zz_8 + (zz_7 shr 32);
+  zz_7 := zz_7 and M;
+
+  x_5 := x[5];
+  zz_9 := zz[9] + (zz_8 shr 32);
+  zz_8 := zz_8 and M;
+  zz_10 := zz[10] + (zz_9 shr 32);
+  zz_9 := zz_9 and M;
+
+  zz_5 := zz_5 + (x_5 * x_0);
+  w := UInt32(zz_5);
+  zz[5] := (w shl 1) or c;
+  c := w shr 31;
+  zz_6 := zz_6 + ((zz_5 shr 32) + x_5 * x_1);
+  zz_7 := zz_7 + ((zz_6 shr 32) + x_5 * x_2);
+  zz_8 := zz_8 + ((zz_7 shr 32) + x_5 * x_3);
+  zz_9 := zz_9 + ((zz_8 shr 32) + x_5 * x_4);
+  zz_10 := zz_10 + (zz_9 shr 32);
+
+  w := UInt32(zz_6);
+  zz[6] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := UInt32(zz_7);
+  zz[7] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := UInt32(zz_8);
+  zz[8] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := UInt32(zz_9);
+  zz[9] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := UInt32(zz_10);
+  zz[10] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := zz[11] + UInt32(zz_10 shr 32);
+  zz[11] := (w shl 1) or c;
+end;
+
+class procedure TNat192.Square(x: TCryptoLibUInt32Array; xOff: Int32;
+  zz: TCryptoLibUInt32Array; zzOff: Int32);
+var
+  x_0, zz_1, xVal, p, x_1, zz_2, x_2, zz_3, zz_4, x_3, zz_5, zz_6, x_4, zz_7,
+    zz_8, x_5, zz_9, zz_10: UInt64;
+  c, w: UInt32;
+  i, j: Int32;
+begin
+  x_0 := x[xOff + 0];
+  c := 0;
+  i := 5;
+  j := 12;
+
+  repeat
+    xVal := x[xOff + i];
+    System.Dec(i);
+    p := xVal * xVal;
+    System.Dec(j);
+    zz[zzOff + j] := (c shl 31) or UInt32(p shr 33);
+    System.Dec(j);
+    zz[zzOff + j] := UInt32(p shr 1);
+    c := UInt32(p);
+  until not(i > 0);
+
+  p := x_0 * x_0;
+  zz_1 := UInt64(c shl 31) or (p shr 33);
+  zz[zzOff + 0] := UInt32(p);
+  c := UInt32(p shr 32) and 1;
+
+  x_1 := x[xOff + 1];
+  zz_2 := zz[zzOff + 2];
+
+  zz_1 := zz_1 + (x_1 * x_0);
+  w := UInt32(zz_1);
+  zz[zzOff + 1] := (w shl 1) or c;
+  c := w shr 31;
+  zz_2 := zz_2 + (zz_1 shr 32);
+
+  x_2 := x[xOff + 2];
+  zz_3 := zz[zzOff + 3];
+  zz_4 := zz[zzOff + 4];
+
+  zz_2 := zz_2 + (x_2 * x_0);
+  w := UInt32(zz_2);
+  zz[zzOff + 2] := (w shl 1) or c;
+  c := w shr 31;
+  zz_3 := zz_3 + ((zz_2 shr 32) + x_2 * x_1);
+  zz_4 := zz_4 + (zz_3 shr 32);
+  zz_3 := zz_3 and M;
+
+  x_3 := x[xOff + 3];
+  zz_5 := zz[zzOff + 5] + (zz_4 shr 32);
+  zz_4 := zz_4 and M;
+  zz_6 := zz[zzOff + 6] + (zz_5 shr 32);
+  zz_5 := zz_5 and M;
+
+  zz_3 := zz_3 + (x_3 * x_0);
+  w := UInt32(zz_3);
+  zz[zzOff + 3] := (w shl 1) or c;
+  c := w shr 31;
+  zz_4 := zz_4 + ((zz_3 shr 32) + x_3 * x_1);
+  zz_5 := zz_5 + ((zz_4 shr 32) + x_3 * x_2);
+  zz_4 := zz_4 and M;
+  zz_6 := zz_6 + (zz_5 shr 32);
+  zz_5 := zz_5 and M;
+
+  x_4 := x[xOff + 4];
+  zz_7 := zz[zzOff + 7] + (zz_6 shr 32);
+  zz_6 := zz_6 and M;
+  zz_8 := zz[zzOff + 8] + (zz_7 shr 32);
+  zz_7 := zz_7 and M;
+
+  zz_4 := zz_4 + (x_4 * x_0);
+  w := UInt32(zz_4);
+  zz[zzOff + 4] := (w shl 1) or c;
+  c := w shr 31;
+  zz_5 := zz_5 + ((zz_4 shr 32) + x_4 * x_1);
+  zz_6 := zz_6 + ((zz_5 shr 32) + x_4 * x_2);
+  zz_5 := zz_5 and M;
+  zz_7 := zz_7 + ((zz_6 shr 32) + x_4 * x_3);
+  zz_6 := zz_6 and M;
+  zz_8 := zz_8 + (zz_7 shr 32);
+  zz_7 := zz_7 and M;
+
+  x_5 := x[xOff + 5];
+  zz_9 := zz[zzOff + 9] + (zz_8 shr 32);
+  zz_8 := zz_8 and M;
+  zz_10 := zz[zzOff + 10] + (zz_9 shr 32);
+  zz_9 := zz_9 and M;
+
+  zz_5 := zz_5 + (x_5 * x_0);
+  w := UInt32(zz_5);
+  zz[zzOff + 5] := (w shl 1) or c;
+  c := w shr 31;
+  zz_6 := zz_6 + ((zz_5 shr 32) + x_5 * x_1);
+  zz_7 := zz_7 + ((zz_6 shr 32) + x_5 * x_2);
+  zz_8 := zz_8 + ((zz_7 shr 32) + x_5 * x_3);
+  zz_9 := zz_9 + ((zz_8 shr 32) + x_5 * x_4);
+  zz_10 := zz_10 + (zz_9 shr 32);
+
+  w := UInt32(zz_6);
+  zz[zzOff + 6] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := UInt32(zz_7);
+  zz[zzOff + 7] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := UInt32(zz_8);
+  zz[zzOff + 8] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := UInt32(zz_9);
+  zz[zzOff + 9] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := UInt32(zz_10);
+  zz[zzOff + 10] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := zz[zzOff + 11] + UInt32(zz_10 shr 32);
+  zz[zzOff + 11] := (w shl 1) or c;
+end;
+
+class function TNat192.Sub(x, y, z: TCryptoLibUInt32Array): Int32;
+var
+  c: Int64;
+begin
+  c := 0;
+  c := c + (Int64(x[0]) - y[0]);
+  z[0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[1]) - y[1]);
+  z[1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[2]) - y[2]);
+  z[2] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[3]) - y[3]);
+  z[3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[4]) - y[4]);
+  z[4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[5]) - y[5]);
+  z[5] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  result := Int32(c);
+end;
+
+class function TNat192.Sub(x: TCryptoLibUInt32Array; xOff: Int32;
+  y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+  zOff: Int32): Int32;
+var
+  c: Int64;
+begin
+  c := 0;
+  c := c + (Int64(x[xOff + 0]) - y[yOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[xOff + 1]) - y[yOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[xOff + 2]) - y[yOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[xOff + 3]) - y[yOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[xOff + 4]) - y[yOff + 4]);
+  z[zOff + 4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[xOff + 5]) - y[yOff + 5]);
+  z[zOff + 5] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  result := Int32(c);
+end;
+
+class function TNat192.SubBothFrom(x, y, z: TCryptoLibUInt32Array): Int32;
+var
+  c: Int64;
+begin
+  c := 0;
+  c := c + (Int64(z[0]) - x[0] - y[0]);
+  z[0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[1]) - x[1] - y[1]);
+  z[1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[2]) - x[2] - y[2]);
+  z[2] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[3]) - x[3] - y[3]);
+  z[3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[4]) - x[4] - y[4]);
+  z[4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[5]) - x[5] - y[5]);
+  z[5] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  result := Int32(c);
+end;
+
+class function TNat192.SubFrom(x, z: TCryptoLibUInt32Array): Int32;
+var
+  c: Int64;
+begin
+  c := 0;
+  c := c + (Int64(z[0]) - x[0]);
+  z[0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[1]) - x[1]);
+  z[1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[2]) - x[2]);
+  z[2] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[3]) - x[3]);
+  z[3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[4]) - x[4]);
+  z[4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[5]) - x[5]);
+  z[5] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  result := Int32(c);
+end;
+
+class function TNat192.SubFrom(x: TCryptoLibUInt32Array; xOff: Int32;
+  z: TCryptoLibUInt32Array; zOff: Int32): Int32;
+var
+  c: Int64;
+begin
+  c := 0;
+  c := c + (Int64(z[zOff + 0]) - x[xOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[zOff + 1]) - x[xOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[zOff + 2]) - x[xOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[zOff + 3]) - x[xOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[zOff + 4]) - x[xOff + 4]);
+  z[zOff + 4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[zOff + 5]) - x[xOff + 5]);
+  z[zOff + 5] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  result := Int32(c);
+end;
+
+class function TNat192.ToBigInteger(x: TCryptoLibUInt32Array): TBigInteger;
+var
+  bs, temp: TCryptoLibByteArray;
+  i: Int32;
+  x_i: UInt32;
+begin
+  System.SetLength(bs, 24);
+  for i := 0 to System.Pred(6) do
+
+  begin
+    x_i := x[i];
+    if (x_i <> 0) then
+    begin
+      temp := TConverters.ReadUInt32AsBytesBE(x_i);
+      System.Move(temp[0], bs[(5 - i) shl 2], System.Length(temp) *
+        System.SizeOf(Byte))
+    end;
+  end;
+  result := TBigInteger.Create(1, bs);
+end;
+
+class function TNat192.ToBigInteger64(x: TCryptoLibUInt64Array): TBigInteger;
+var
+  bs, temp: TCryptoLibByteArray;
+  i: Int32;
+  x_i: UInt64;
+begin
+  System.SetLength(bs, 24);
+  for i := 0 to System.Pred(3) do
+
+  begin
+    x_i := x[i];
+    if (x_i <> Int64(0)) then
+    begin
+      temp := TConverters.ReadUInt64AsBytesBE(x_i);
+      System.Move(temp[0], bs[(2 - i) shl 3], System.Length(temp) *
+        System.SizeOf(Byte))
+    end;
+  end;
+  result := TBigInteger.Create(1, bs);
+end;
+
+class procedure TNat192.Zero(z: TCryptoLibUInt32Array);
+begin
+  System.FillChar(z[0], 6 * System.SizeOf(UInt32), UInt32(0));
+end;
+
+end.

+ 95 - 0
CryptoLib/src/Math/Raw/ClpNat384.pas

@@ -0,0 +1,95 @@
+{ *********************************************************************************** }
+{ *                              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 ClpNat384;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat,
+  ClpNat192,
+  ClpCryptoLibTypes;
+
+type
+  TNat384 = class sealed(TObject)
+
+  public
+    class procedure Mul(x, y, zz: TCryptoLibUInt32Array); static; inline;
+    class procedure Square(x, zz: TCryptoLibUInt32Array); static; inline;
+
+  end;
+
+implementation
+
+{ TNat384 }
+
+class procedure TNat384.Mul(x, y, zz: TCryptoLibUInt32Array);
+var
+  c18, c12: UInt32;
+  dx, dy, tt: TCryptoLibUInt32Array;
+  neg: Boolean;
+begin
+  TNat192.Mul(x, y, zz);
+  TNat192.Mul(x, 6, y, 6, zz, 12);
+
+  c18 := TNat192.AddToEachOther(zz, 6, zz, 12);
+  c12 := c18 + TNat192.AddTo(zz, 0, zz, 6, 0);
+  c18 := c18 + (TNat192.AddTo(zz, 18, zz, 12, c12));
+
+  dx := TNat192.Create();
+  dy := TNat192.Create();
+  neg := TNat192.Diff(x, 6, x, 0, dx, 0) <> TNat192.Diff(y, 6, y, 0, dy, 0);
+
+  tt := TNat192.CreateExt();
+  TNat192.Mul(dx, dy, tt);
+
+  if neg then
+  begin
+    c18 := c18 + TNat.AddTo(12, tt, 0, zz, 6);
+  end
+  else
+  begin
+    c18 := c18 + UInt32(TNat.SubFrom(12, tt, 0, zz, 6));
+  end;
+  TNat.AddWordAt(24, c18, zz, 18);
+end;
+
+class procedure TNat384.Square(x, zz: TCryptoLibUInt32Array);
+var
+  c18, c12: UInt32;
+  dx, m: TCryptoLibUInt32Array;
+begin
+  TNat192.Square(x, zz);
+  TNat192.Square(x, 6, zz, 12);
+
+  c18 := TNat192.AddToEachOther(zz, 6, zz, 12);
+  c12 := c18 + TNat192.AddTo(zz, 0, zz, 6, 0);
+  c18 := c18 + TNat192.AddTo(zz, 18, zz, 12, c12);
+
+  dx := TNat192.Create();
+  TNat192.Diff(x, 6, x, 0, dx, 0);
+
+  m := TNat192.CreateExt();
+  TNat192.Square(dx, m);
+
+  c18 := c18 + UInt32(TNat.SubFrom(12, m, 0, zz, 6));
+  TNat.AddWordAt(24, c18, zz, 18);
+end;
+
+end.

+ 37 - 1
CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.lpk

@@ -25,7 +25,7 @@
  Acknowledgements: 
 Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the development of this library "/>
     <Version Major="2" Minor="3"/>
-    <Files Count="421">
+    <Files Count="430">
       <Item1>
         <Filename Value="..\..\Asn1\ClpAsn1Encodable.pas"/>
         <UnitName Value="ClpAsn1Encodable"/>
@@ -1712,6 +1712,42 @@ Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the devel
         <Filename Value="..\..\Interfaces\ClpISecP256K1Curve.pas"/>
         <UnitName Value="ClpISecP256K1Curve"/>
       </Item421>
+      <Item422>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecP384R1Field.pas"/>
+        <UnitName Value="ClpSecP384R1Field"/>
+      </Item422>
+      <Item423>
+        <Filename Value="..\..\Math\Raw\ClpNat384.pas"/>
+        <UnitName Value="ClpNat384"/>
+      </Item423>
+      <Item424>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecP384R1FieldElement.pas"/>
+        <UnitName Value="ClpSecP384R1FieldElement"/>
+      </Item424>
+      <Item425>
+        <Filename Value="..\..\Interfaces\ClpISecP384R1FieldElement.pas"/>
+        <UnitName Value="ClpISecP384R1FieldElement"/>
+      </Item425>
+      <Item426>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecP384R1Point.pas"/>
+        <UnitName Value="ClpSecP384R1Point"/>
+      </Item426>
+      <Item427>
+        <Filename Value="..\..\Interfaces\ClpISecP384R1Point.pas"/>
+        <UnitName Value="ClpISecP384R1Point"/>
+      </Item427>
+      <Item428>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecP384R1Curve.pas"/>
+        <UnitName Value="ClpSecP384R1Curve"/>
+      </Item428>
+      <Item429>
+        <Filename Value="..\..\Math\Raw\ClpNat192.pas"/>
+        <UnitName Value="ClpNat192"/>
+      </Item429>
+      <Item430>
+        <Filename Value="..\..\Interfaces\ClpISecP384R1Curve.pas"/>
+        <UnitName Value="ClpISecP384R1Curve"/>
+      </Item430>
     </Files>
     <RequiredPkgs Count="3">
       <Item1>

+ 4 - 1
CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.pas

@@ -138,7 +138,10 @@ uses
   ClpIPreCompCallBack, ClpNistNamedCurves, ClpNat256, ClpNat320, 
   ClpAesLightEngine, ClpIAesLightEngine, ClpCustomNamedCurves, 
   ClpSecP256K1Field, ClpSecP256K1FieldElement, ClpISecP256K1FieldElement, 
-  ClpSecP256K1Point, ClpISecP256K1Point, ClpSecP256K1Curve, ClpISecP256K1Curve;
+  ClpSecP256K1Point, ClpISecP256K1Point, ClpSecP256K1Curve, 
+  ClpISecP256K1Curve, ClpSecP384R1Field, ClpNat384, ClpSecP384R1FieldElement, 
+  ClpISecP384R1FieldElement, ClpSecP384R1Point, ClpISecP384R1Point, 
+  ClpSecP384R1Curve, ClpNat192, ClpISecP384R1Curve;
 
 implementation
 

+ 39 - 8
CryptoLib/src/Utils/ClpBits.pas

@@ -41,7 +41,7 @@ type
     /// <param name="Size">Size of the Array to Reverse.</param>
 
     class procedure ReverseByteArray(Source, Dest: Pointer;
-      Size: int64); static;
+      Size: Int64); static;
 
     /// <summary>
     /// Calculates Arithmetic shift right.
@@ -60,7 +60,7 @@ type
     /// <returns>Shifted value.</returns>
     /// Implementation was found here <see cref="https://github.com/Spelt/ZXing.Delphi/blob/master/Lib/Classes/Common/MathUtils.pas" />
 
-    class function Asr64(Value: int64; ShiftBits: Int32): int64; static; inline;
+    class function Asr64(Value: Int64; ShiftBits: Int32): Int64; static; inline;
 
     /// <summary>
     /// Calculates Negative Left Shift. This was implemented to circumvent a
@@ -108,13 +108,16 @@ type
     class function NegativeRightShift32(Value: UInt32; ShiftBits: Int32)
       : UInt32; static; inline;
 
-    class function RotateLeft32(a_value: UInt32; a_n: Int32): UInt32; overload;
+    class function RotateLeft8(a_value: Byte; a_n: Int32): Byte; static; inline;
+    class function RotateLeft32(a_value: UInt32; a_n: Int32): UInt32;
       static; inline;
-    class function RotateLeft64(a_value: UInt64; a_n: Int32): UInt64; overload;
+    class function RotateLeft64(a_value: UInt64; a_n: Int32): UInt64;
       static; inline;
-    class function RotateRight32(a_value: UInt32; a_n: Int32): UInt32; overload;
+    class function RotateRight8(a_value: Byte; a_n: Int32): Byte;
       static; inline;
-    class function RotateRight64(a_value: UInt64; a_n: Int32): UInt64; overload;
+    class function RotateRight32(a_value: UInt32; a_n: Int32): UInt32;
+      static; inline;
+    class function RotateRight64(a_value: UInt64; a_n: Int32): UInt64;
       static; inline;
 
   end;
@@ -123,7 +126,7 @@ implementation
 
 { TBits }
 
-class procedure TBits.ReverseByteArray(Source, Dest: Pointer; Size: int64);
+class procedure TBits.ReverseByteArray(Source, Dest: Pointer; Size: Int64);
 var
   ptr_src, ptr_dest: PByte;
 begin
@@ -221,7 +224,7 @@ begin
 {$ENDIF FPC}
 end;
 
-class function TBits.Asr64(Value: int64; ShiftBits: Int32): int64;
+class function TBits.Asr64(Value: Int64; ShiftBits: Int32): Int64;
 begin
 {$IFDEF FPC}
   Result := SarInt64(Value, ShiftBits);
@@ -237,6 +240,20 @@ begin
 {$ENDIF FPC}
 end;
 
+class function TBits.RotateLeft8(a_value: Byte; a_n: Int32): Byte;
+begin
+{$IFDEF DEBUG}
+  System.Assert(a_n >= 0);
+{$ENDIF DEBUG}
+{$IFDEF FPC}
+  Result := RolByte(a_value, a_n);
+{$ELSE}
+  a_n := a_n and 7;
+
+  Result := (a_value shl a_n) or (a_value shr (8 - a_n));
+{$ENDIF FPC}
+end;
+
 class function TBits.NegativeLeftShift32(Value: UInt32;
   ShiftBits: Int32): UInt32;
 begin
@@ -283,6 +300,20 @@ begin
 {$ENDIF FPC}
 end;
 
+class function TBits.RotateRight8(a_value: Byte; a_n: Int32): Byte;
+begin
+{$IFDEF DEBUG}
+  System.Assert(a_n >= 0);
+{$ENDIF DEBUG}
+{$IFDEF FPC}
+  Result := RorByte(a_value, a_n);
+{$ELSE}
+  a_n := a_n and 7;
+
+  Result := (a_value shr a_n) or (a_value shl (8 - a_n));
+{$ENDIF FPC}
+end;
+
 class function TBits.RotateRight32(a_value: UInt32; a_n: Int32): UInt32;
 begin
 {$IFDEF DEBUG}