Browse Source

Sync CryptoLib and SimpleBaseLib with parent version

CryptoLib - add CTSBlockCipher Mode Support
SimpleBaseLib - Base58 decoding buffer size is now correctly calculated for all cases
Ugochukwu Mmaduekwe 6 years ago
parent
commit
7514b5f87c

+ 2 - 1
src/libraries/cryptolib4pascal/ClpAesEngine.pas

@@ -221,7 +221,6 @@ type
 
 
     function GetAlgorithmName: String; virtual;
     function GetAlgorithmName: String; virtual;
     function GetIsPartialBlockOkay: Boolean; virtual;
     function GetIsPartialBlockOkay: Boolean; virtual;
-    function GetBlockSize(): Int32; virtual;
 
 
     /// <summary>
     /// <summary>
     /// <para>
     /// <para>
@@ -284,6 +283,8 @@ type
 
 
     procedure Reset(); virtual;
     procedure Reset(); virtual;
 
 
+    function GetBlockSize(): Int32; virtual;
+
     property AlgorithmName: String read GetAlgorithmName;
     property AlgorithmName: String read GetAlgorithmName;
     property IsPartialBlockOkay: Boolean read GetIsPartialBlockOkay;
     property IsPartialBlockOkay: Boolean read GetIsPartialBlockOkay;
   end;
   end;

+ 3 - 2
src/libraries/cryptolib4pascal/ClpAesLightEngine.pas

@@ -17,7 +17,7 @@
 
 
 unit ClpAesLightEngine;
 unit ClpAesLightEngine;
 
 
-{$I ..\..\Include\CryptoLib.inc}
+{$I CryptoLib.inc}
 
 
 interface
 interface
 
 
@@ -129,7 +129,6 @@ type
 
 
     function GetAlgorithmName: String; virtual;
     function GetAlgorithmName: String; virtual;
     function GetIsPartialBlockOkay: Boolean; virtual;
     function GetIsPartialBlockOkay: Boolean; virtual;
-    function GetBlockSize(): Int32; virtual;
 
 
     /// <summary>
     /// <summary>
     /// <para>
     /// <para>
@@ -192,6 +191,8 @@ type
 
 
     procedure Reset(); virtual;
     procedure Reset(); virtual;
 
 
+    function GetBlockSize(): Int32; virtual;
+
     property AlgorithmName: String read GetAlgorithmName;
     property AlgorithmName: String read GetAlgorithmName;
     property IsPartialBlockOkay: Boolean read GetIsPartialBlockOkay;
     property IsPartialBlockOkay: Boolean read GetIsPartialBlockOkay;
 
 

+ 5 - 1
src/libraries/cryptolib4pascal/ClpBigInteger.pas

@@ -305,13 +305,14 @@ type
     class procedure ShiftRightOneInPlace(start: Int32;
     class procedure ShiftRightOneInPlace(start: Int32;
       const mag: TCryptoLibInt32Array); static;
       const mag: TCryptoLibInt32Array); static;
 
 
+{$IFNDEF _FIXINSIGHT_}
     /// <summary>
     /// <summary>
     /// returns x = x - y - we assume x is &gt;= y
     /// returns x = x - y - we assume x is &gt;= y
     /// </summary>
     /// </summary>
     class function Subtract(xStart: Int32; const x: TCryptoLibInt32Array;
     class function Subtract(xStart: Int32; const x: TCryptoLibInt32Array;
       yStart: Int32; const y: TCryptoLibInt32Array): TCryptoLibInt32Array;
       yStart: Int32; const y: TCryptoLibInt32Array): TCryptoLibInt32Array;
       overload; static;
       overload; static;
-
+{$ENDIF}
     class function doSubBigLil(const bigMag, lilMag: TCryptoLibInt32Array)
     class function doSubBigLil(const bigMag, lilMag: TCryptoLibInt32Array)
       : TCryptoLibInt32Array; static; inline;
       : TCryptoLibInt32Array; static; inline;
 
 
@@ -2739,6 +2740,8 @@ begin
   Result := TBigInteger.Create(1, yVal, True);
   Result := TBigInteger.Create(1, yVal, True);
 end;
 end;
 
 
+{$IFNDEF _FIXINSIGHT_}
+
 class function TBigInteger.Subtract(xStart: Int32;
 class function TBigInteger.Subtract(xStart: Int32;
   const x: TCryptoLibInt32Array; yStart: Int32; const y: TCryptoLibInt32Array)
   const x: TCryptoLibInt32Array; yStart: Int32; const y: TCryptoLibInt32Array)
   : TCryptoLibInt32Array;
   : TCryptoLibInt32Array;
@@ -2780,6 +2783,7 @@ begin
 
 
   Result := x;
   Result := x;
 end;
 end;
+{$ENDIF}
 
 
 class procedure TBigInteger.MontgomeryReduce(const x, m: TCryptoLibInt32Array;
 class procedure TBigInteger.MontgomeryReduce(const x, m: TCryptoLibInt32Array;
   mDash: UInt32);
   mDash: UInt32);

+ 353 - 39
src/libraries/cryptolib4pascal/ClpBlockCipherModes.pas

@@ -25,6 +25,7 @@ uses
   Math,
   Math,
   SysUtils,
   SysUtils,
   ClpIBlockCipher,
   ClpIBlockCipher,
+  ClpBufferedBlockCipher,
   ClpICipherParameters,
   ClpICipherParameters,
   ClpIParametersWithIV,
   ClpIParametersWithIV,
   ClpArrayUtils,
   ClpArrayUtils,
@@ -43,6 +44,9 @@ resourcestring
     'CTR/SIC mode requires IV no greater than: %u bytes';
     'CTR/SIC mode requires IV no greater than: %u bytes';
   SInvalidTooSmallIVLength = 'CTR/SIC mode requires IV of at least: %u bytes';
   SInvalidTooSmallIVLength = 'CTR/SIC mode requires IV of at least: %u bytes';
 {$ENDIF}
 {$ENDIF}
+  SUnsupportedCipher = 'CtsBlockCipher Can Only Accept ECB or CBC Ciphers';
+  SNegativeInputLength = 'Can''t Have a Negative Input Length!';
+  SCTSDoFinalError = 'Need at Least One Block of Input For CTS';
 
 
 type
 type
 
 
@@ -613,6 +617,98 @@ type
 
 
   end;
   end;
 
 
+type
+
+  /// <summary>
+  /// A Cipher Text Stealing (CTS) mode cipher. CTS allows block ciphers to
+  /// be used to produce cipher text which is the same outLength as the plain
+  /// text.
+  /// </summary>
+  TCtsBlockCipher = class sealed(TBufferedBlockCipher, ICtsBlockCipher)
+
+  strict private
+    FblockSize: Int32;
+
+  public
+
+    /// <summary>
+    /// Create a buffered block cipher that uses Cipher Text Stealing
+    /// </summary>
+    /// <param name="cipher">
+    /// the underlying block cipher this buffering object wraps.
+    /// </param>
+    constructor Create(const cipher: IBlockCipher);
+
+    /// <summary>
+    /// return the size of the output buffer required for an update plus a
+    /// doFinal with an input of len bytes.
+    /// </summary>
+    /// <param name="inputLen">
+    /// the outLength of the input.
+    /// </param>
+    /// <returns>
+    /// the space required to accommodate a call to update and doFinal with
+    /// length bytes of input.
+    /// </returns>
+    function GetOutputSize(inputLen: Int32): Int32; override;
+
+    /// <summary>
+    /// return the size of the output buffer required for an update an input
+    /// of len bytes.
+    /// </summary>
+    /// <param name="inputLen">
+    /// the outLength of the input.
+    /// </param>
+    /// <returns>
+    /// the space required to accommodate a call to update with length bytes
+    /// of input.
+    /// </returns>
+    function GetUpdateOutputSize(inputLen: Int32): Int32; override;
+
+    function ProcessByte(input: Byte; const output: TCryptoLibByteArray;
+      outOff: Int32): Int32; override;
+
+    /// <summary>
+    /// process an array of bytes, producing output if necessary.
+    /// </summary>
+    /// <param name="input">
+    /// the input byte array.
+    /// </param>
+    /// <param name="inOff">
+    /// the offset at which the input data starts.
+    /// </param>
+    /// <param name="Length">
+    /// the number of bytes to be copied out of the input array.
+    /// </param>
+    /// <param name="output">
+    /// the space for any output that might be produced.
+    /// </param>
+    /// <param name="outOff">
+    /// the offset from which the output will be copied.
+    /// </param>
+    /// <returns>
+    /// the number of output bytes copied to out.
+    /// </returns>
+    function ProcessBytes(const input: TCryptoLibByteArray; inOff, len: Int32;
+      const output: TCryptoLibByteArray; outOff: Int32): Int32; override;
+
+    /// <summary>
+    /// Process the last block in the buffer.
+    /// </summary>
+    /// <param name="output">
+    /// the array the block currently being held is copied into.
+    /// </param>
+    /// <param name="outOff">
+    /// the offset at which the copying starts.
+    /// </param>
+    /// <returns>
+    /// the number of output bytes copied to out.
+    /// </returns>
+    function DoFinal(const output: TCryptoLibByteArray; outOff: Int32)
+      : Int32; override;
+
+  end;
+
 implementation
 implementation
 
 
 { TCbcBlockCipher }
 { TCbcBlockCipher }
@@ -631,17 +727,17 @@ end;
 function TCbcBlockCipher.DecryptBlock(const input: TCryptoLibByteArray;
 function TCbcBlockCipher.DecryptBlock(const input: TCryptoLibByteArray;
   inOff: Int32; const outBytes: TCryptoLibByteArray; outOff: Int32): Int32;
   inOff: Int32; const outBytes: TCryptoLibByteArray; outOff: Int32): Int32;
 var
 var
-  length, I: Int32;
+  Length, I: Int32;
   tmp: TCryptoLibByteArray;
   tmp: TCryptoLibByteArray;
 begin
 begin
-  if ((inOff + FblockSize) > System.length(input)) then
+  if ((inOff + FblockSize) > System.Length(input)) then
   begin
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
   end;
   end;
 
 
   System.Move(input[inOff], FcbcNextV[0], FblockSize * System.SizeOf(Byte));
   System.Move(input[inOff], FcbcNextV[0], FblockSize * System.SizeOf(Byte));
 
 
-  length := Fcipher.ProcessBlock(input, inOff, outBytes, outOff);
+  Length := Fcipher.ProcessBlock(input, inOff, outBytes, outOff);
 
 
 
 
   // XOR the FcbcV and the output
   // XOR the FcbcV and the output
@@ -666,7 +762,7 @@ function TCbcBlockCipher.EncryptBlock(const input: TCryptoLibByteArray;
 var
 var
   I, &length: Int32;
   I, &length: Int32;
 begin
 begin
-  if ((inOff + FblockSize) > System.length(input)) then
+  if ((inOff + FblockSize) > System.Length(input)) then
   begin
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
   end;
   end;
@@ -683,7 +779,7 @@ begin
 
 
   // copy ciphertext to FcbcV
   // copy ciphertext to FcbcV
 
 
-  System.Move(outBytes[outOff], FcbcV[0], System.length(FcbcV) *
+  System.Move(outBytes[outOff], FcbcV[0], System.Length(FcbcV) *
     System.SizeOf(Byte));
     System.SizeOf(Byte));
 
 
   result := &length;
   result := &length;
@@ -691,8 +787,8 @@ end;
 
 
 procedure TCbcBlockCipher.Reset;
 procedure TCbcBlockCipher.Reset;
 begin
 begin
-  System.Move(FIV[0], FcbcV[0], System.length(FIV));
-  TArrayUtils.Fill(FcbcNextV, 0, System.length(FcbcNextV), Byte(0));
+  System.Move(FIV[0], FcbcV[0], System.Length(FIV));
+  TArrayUtils.Fill(FcbcNextV, 0, System.Length(FcbcNextV), Byte(0));
 
 
   Fcipher.Reset();
   Fcipher.Reset();
 end;
 end;
@@ -733,12 +829,12 @@ begin
   begin
   begin
     iv := ivParam.GetIV();
     iv := ivParam.GetIV();
 
 
-    if (System.length(iv) <> FblockSize) then
+    if (System.Length(iv) <> FblockSize) then
     begin
     begin
       raise EArgumentCryptoLibException.CreateRes(@SInvalidIVLength);
       raise EArgumentCryptoLibException.CreateRes(@SInvalidIVLength);
     end;
     end;
 
 
-    System.Move(iv[0], FIV[0], System.length(iv) * System.SizeOf(Byte));
+    System.Move(iv[0], FIV[0], System.Length(iv) * System.SizeOf(Byte));
 
 
     Lparameters := ivParam.parameters;
     Lparameters := ivParam.parameters;
   end;
   end;
@@ -789,12 +885,12 @@ function TCfbBlockCipher.DecryptBlock(const input: TCryptoLibByteArray;
 var
 var
   I, count: Int32;
   I, count: Int32;
 begin
 begin
-  if ((inOff + FblockSize) > System.length(input)) then
+  if ((inOff + FblockSize) > System.Length(input)) then
   begin
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
   end;
   end;
 
 
-  if ((outOff + FblockSize) > System.length(outBytes)) then
+  if ((outOff + FblockSize) > System.Length(outBytes)) then
   begin
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SOutputBufferTooShort);
     raise EDataLengthCryptoLibException.CreateRes(@SOutputBufferTooShort);
   end;
   end;
@@ -804,13 +900,13 @@ begin
   //
   //
   // change over the input block.
   // change over the input block.
   //
   //
-  count := (System.length(FcfbV) - FblockSize) * System.SizeOf(Byte);
+  count := (System.Length(FcfbV) - FblockSize) * System.SizeOf(Byte);
   if count > 0 then
   if count > 0 then
   begin
   begin
     System.Move(FcfbV[FblockSize], FcfbV[0], count);
     System.Move(FcfbV[FblockSize], FcfbV[0], count);
   end;
   end;
 
 
-  System.Move(input[inOff], FcfbV[(System.length(FcfbV) - FblockSize)],
+  System.Move(input[inOff], FcfbV[(System.Length(FcfbV) - FblockSize)],
     FblockSize * System.SizeOf(Byte));
     FblockSize * System.SizeOf(Byte));
 
 
   // XOR the FcfbV with the ciphertext producing the plaintext
   // XOR the FcfbV with the ciphertext producing the plaintext
@@ -828,12 +924,12 @@ function TCfbBlockCipher.EncryptBlock(const input: TCryptoLibByteArray;
 var
 var
   I, count: Int32;
   I, count: Int32;
 begin
 begin
-  if ((inOff + FblockSize) > System.length(input)) then
+  if ((inOff + FblockSize) > System.Length(input)) then
   begin
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
   end;
   end;
 
 
-  if ((outOff + FblockSize) > System.length(outBytes)) then
+  if ((outOff + FblockSize) > System.Length(outBytes)) then
   begin
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SOutputBufferTooShort);
     raise EDataLengthCryptoLibException.CreateRes(@SOutputBufferTooShort);
   end;
   end;
@@ -850,14 +946,14 @@ begin
   //
   //
   // change over the input block.
   // change over the input block.
   //
   //
-  count := (System.length(FcfbV) - FblockSize) * System.SizeOf(Byte);
+  count := (System.Length(FcfbV) - FblockSize) * System.SizeOf(Byte);
 
 
   if count > 0 then
   if count > 0 then
   begin
   begin
     System.Move(FcfbV[FblockSize], FcfbV[0], count);
     System.Move(FcfbV[FblockSize], FcfbV[0], count);
   end;
   end;
 
 
-  System.Move(outBytes[outOff], FcfbV[(System.length(FcfbV) - FblockSize)],
+  System.Move(outBytes[outOff], FcfbV[(System.Length(FcfbV) - FblockSize)],
     FblockSize * System.SizeOf(Byte));
     FblockSize * System.SizeOf(Byte));
 
 
   result := FblockSize;
   result := FblockSize;
@@ -865,7 +961,7 @@ end;
 
 
 procedure TCfbBlockCipher.Reset;
 procedure TCfbBlockCipher.Reset;
 begin
 begin
-  System.Move(FIV[0], FcfbV[0], System.length(FIV));
+  System.Move(FIV[0], FcfbV[0], System.Length(FIV));
 
 
   Fcipher.Reset();
   Fcipher.Reset();
 end;
 end;
@@ -905,9 +1001,9 @@ begin
   begin
   begin
     iv := ivParam.GetIV();
     iv := ivParam.GetIV();
 
 
-    diff := System.length(FIV) - System.length(iv);
+    diff := System.Length(FIV) - System.Length(iv);
 
 
-    System.Move(iv[0], FIV[diff], System.length(iv) * System.SizeOf(Byte));
+    System.Move(iv[0], FIV[diff], System.Length(iv) * System.SizeOf(Byte));
     TArrayUtils.Fill(FIV, 0, diff, Byte(0));
     TArrayUtils.Fill(FIV, 0, diff, Byte(0));
 
 
     Lparameters := ivParam.parameters;
     Lparameters := ivParam.parameters;
@@ -952,7 +1048,7 @@ end;
 
 
 procedure TOfbBlockCipher.Reset;
 procedure TOfbBlockCipher.Reset;
 begin
 begin
-  System.Move(FIV[0], FofbV[0], System.length(FIV));
+  System.Move(FIV[0], FofbV[0], System.Length(FIV));
 
 
   Fcipher.Reset();
   Fcipher.Reset();
 
 
@@ -994,13 +1090,13 @@ begin
   begin
   begin
     iv := ivParam.GetIV();
     iv := ivParam.GetIV();
 
 
-    if (System.length(iv) < System.length(FIV)) then
+    if (System.Length(iv) < System.Length(FIV)) then
     begin
     begin
       // prepend the supplied IV with zeros (per FIPS PUB 81)
       // prepend the supplied IV with zeros (per FIPS PUB 81)
-      System.Move(iv[0], FIV[System.length(FIV) - System.length(iv)],
-        System.length(iv) * System.SizeOf(Byte));
+      System.Move(iv[0], FIV[System.Length(FIV) - System.Length(iv)],
+        System.Length(iv) * System.SizeOf(Byte));
 
 
-      for I := 0 to System.Pred(System.length(FIV) - System.length(iv)) do
+      for I := 0 to System.Pred(System.Length(FIV) - System.Length(iv)) do
       begin
       begin
         FIV[I] := 0;
         FIV[I] := 0;
       end;
       end;
@@ -1008,7 +1104,7 @@ begin
     end
     end
     else
     else
     begin
     begin
-      System.Move(iv[0], FIV[0], System.length(FIV) * System.SizeOf(Byte));
+      System.Move(iv[0], FIV[0], System.Length(FIV) * System.SizeOf(Byte));
     end;
     end;
 
 
     Lparameters := ivParam.parameters;
     Lparameters := ivParam.parameters;
@@ -1029,12 +1125,12 @@ function TOfbBlockCipher.ProcessBlock(const input: TCryptoLibByteArray;
 var
 var
   I, count: Int32;
   I, count: Int32;
 begin
 begin
-  if ((inOff + FblockSize) > System.length(input)) then
+  if ((inOff + FblockSize) > System.Length(input)) then
   begin
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
   end;
   end;
 
 
-  if ((outOff + FblockSize) > System.length(output)) then
+  if ((outOff + FblockSize) > System.Length(output)) then
   begin
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SOutputBufferTooShort);
     raise EDataLengthCryptoLibException.CreateRes(@SOutputBufferTooShort);
   end;
   end;
@@ -1054,14 +1150,14 @@ begin
   //
   //
   // change over the input block.
   // change over the input block.
   //
   //
-  count := (System.length(FofbV) - FblockSize) * System.SizeOf(Byte);
+  count := (System.Length(FofbV) - FblockSize) * System.SizeOf(Byte);
 
 
   if count > 0 then
   if count > 0 then
   begin
   begin
     System.Move(FofbV[FblockSize], FofbV[0], count);
     System.Move(FofbV[FblockSize], FofbV[0], count);
   end;
   end;
 
 
-  System.Move(FofbOutV[0], FofbV[(System.length(FofbV) - FblockSize)],
+  System.Move(FofbOutV[0], FofbV[(System.Length(FofbV) - FblockSize)],
     FblockSize * System.SizeOf(Byte));
     FblockSize * System.SizeOf(Byte));
 
 
   result := FblockSize;
   result := FblockSize;
@@ -1082,8 +1178,8 @@ end;
 
 
 procedure TSicBlockCipher.Reset;
 procedure TSicBlockCipher.Reset;
 begin
 begin
-  TArrayUtils.Fill(Fcounter, 0, System.length(Fcounter), Byte(0));
-  System.Move(FIV[0], Fcounter[0], System.length(FIV) * System.SizeOf(Byte));
+  TArrayUtils.Fill(Fcounter, 0, System.Length(Fcounter), Byte(0));
+  System.Move(FIV[0], Fcounter[0], System.Length(FIV) * System.SizeOf(Byte));
 
 
   Fcipher.Reset();
   Fcipher.Reset();
 
 
@@ -1125,7 +1221,7 @@ begin
   begin
   begin
     FIV := ivParam.GetIV();
     FIV := ivParam.GetIV();
 
 
-    if (FblockSize < System.length(FIV)) then
+    if (FblockSize < System.Length(FIV)) then
     begin
     begin
       raise EArgumentCryptoLibException.CreateResFmt(@SInvalidTooLargeIVLength,
       raise EArgumentCryptoLibException.CreateResFmt(@SInvalidTooLargeIVLength,
         [FblockSize]);
         [FblockSize]);
@@ -1133,7 +1229,7 @@ begin
 
 
     maxCounterSize := Min(8, FblockSize div 2);
     maxCounterSize := Min(8, FblockSize div 2);
 
 
-    if ((FblockSize - System.length(FIV)) > maxCounterSize) then
+    if ((FblockSize - System.Length(FIV)) > maxCounterSize) then
     begin
     begin
       raise EArgumentCryptoLibException.CreateResFmt(@SInvalidTooSmallIVLength,
       raise EArgumentCryptoLibException.CreateResFmt(@SInvalidTooSmallIVLength,
         [FblockSize - maxCounterSize]);
         [FblockSize - maxCounterSize]);
@@ -1163,12 +1259,12 @@ var
   I, J: Int32;
   I, J: Int32;
 begin
 begin
 
 
-  if ((inOff + FblockSize) > System.length(input)) then
+  if ((inOff + FblockSize) > System.Length(input)) then
   begin
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
     raise EDataLengthCryptoLibException.CreateRes(@SInputBufferTooShort);
   end;
   end;
 
 
-  if ((outOff + FblockSize) > System.length(output)) then
+  if ((outOff + FblockSize) > System.Length(output)) then
   begin
   begin
     raise EDataLengthCryptoLibException.CreateRes(@SOutputBufferTooShort);
     raise EDataLengthCryptoLibException.CreateRes(@SOutputBufferTooShort);
   end;
   end;
@@ -1178,14 +1274,14 @@ begin
   //
   //
   // XOR the counterOut with the plaintext producing the cipher text
   // XOR the counterOut with the plaintext producing the cipher text
   //
   //
-  for I := 0 to System.Pred(System.length(FcounterOut)) do
+  for I := 0 to System.Pred(System.Length(FcounterOut)) do
   begin
   begin
 
 
     output[outOff + I] := Byte(FcounterOut[I] xor input[inOff + I]);
     output[outOff + I] := Byte(FcounterOut[I] xor input[inOff + I]);
   end;
   end;
 
 
   // Increment the counter
   // Increment the counter
-  J := System.length(Fcounter);
+  J := System.Length(Fcounter);
   System.Dec(J);
   System.Dec(J);
   System.Inc(Fcounter[J]);
   System.Inc(Fcounter[J]);
   while ((J >= 0) and (Fcounter[J] = 0)) do
   while ((J >= 0) and (Fcounter[J] = 0)) do
@@ -1194,7 +1290,225 @@ begin
     System.Inc(Fcounter[J]);
     System.Inc(Fcounter[J]);
   end;
   end;
 
 
-  result := System.length(Fcounter);
+  result := System.Length(Fcounter);
+end;
+
+{ TCtsBlockCipher }
+
+constructor TCtsBlockCipher.Create(const cipher: IBlockCipher);
+begin
+  Inherited Create();
+  if Supports(cipher, ICfbBlockCipher) or Supports(cipher, IOfbBlockCipher) or
+    Supports(cipher, ISicBlockCipher) or Supports(cipher, ICtsBlockCipher) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SUnsupportedCipher);
+  end;
+
+  Fcipher := cipher;
+
+  FblockSize := Fcipher.GetBlockSize();
+  System.SetLength(Fbuf, FblockSize * 2);
+  FbufOff := 0;
+end;
+
+function TCtsBlockCipher.DoFinal(const output: TCryptoLibByteArray;
+  outOff: Int32): Int32;
+var
+  blockSize, len, I: Int32;
+  block, lastBlock: TCryptoLibByteArray;
+  c: IBlockCipher;
+begin
+  if ((FbufOff + outOff) > System.Length(output)) then
+  begin
+    raise EDataLengthCryptoLibException.CreateRes
+      (@SOutputBufferTooSmallForDoFinal);
+  end;
+
+  blockSize := Fcipher.GetBlockSize();
+  len := FbufOff - blockSize;
+  System.SetLength(block, blockSize);
+
+  if (FforEncryption) then
+  begin
+    if (FbufOff < blockSize) then
+    begin
+      raise EDataLengthCryptoLibException.CreateRes(@SCTSDoFinalError);
+    end;
+
+    Fcipher.ProcessBlock(Fbuf, 0, block, 0);
+
+    if (FbufOff > blockSize) then
+    begin
+
+      I := FbufOff;
+      while I <> System.Length(Fbuf) do
+      begin
+        Fbuf[I] := block[I - blockSize];
+        System.Inc(I);
+      end;
+
+      I := blockSize;
+      while I <> FbufOff do
+      begin
+        Fbuf[I] := Fbuf[I] xor (block[I - blockSize]);
+        System.Inc(I);
+      end;
+
+      if Supports(Fcipher, ICbcBlockCipher) then
+      begin
+        c := (Fcipher as ICbcBlockCipher).GetUnderlyingCipher();
+
+        c.ProcessBlock(Fbuf, blockSize, output, outOff);
+      end
+      else
+      begin
+        Fcipher.ProcessBlock(Fbuf, blockSize, output, outOff);
+      end;
+
+      System.Move(block[0], output[outOff + blockSize],
+        len * System.SizeOf(Byte));
+    end
+    else
+    begin
+      System.Move(block[0], output[outOff], blockSize * System.SizeOf(Byte));
+    end;
+  end
+  else
+  begin
+
+    if (FbufOff < blockSize) then
+    begin
+      raise EDataLengthCryptoLibException.CreateRes(@SCTSDoFinalError);
+    end;
+
+    System.SetLength(lastBlock, blockSize);
+
+    if (FbufOff > blockSize) then
+    begin
+
+      if Supports(Fcipher, ICbcBlockCipher) then
+      begin
+        c := (Fcipher as ICbcBlockCipher).GetUnderlyingCipher();
+
+        c.ProcessBlock(Fbuf, 0, block, 0);
+      end
+      else
+      begin
+        Fcipher.ProcessBlock(Fbuf, 0, block, 0);
+      end;
+
+      I := blockSize;
+      while I <> FbufOff do
+      begin
+        lastBlock[I - blockSize] := Byte(block[I - blockSize] xor Fbuf[I]);
+        System.Inc(I);
+      end;
+
+      System.Move(Fbuf[blockSize], block[0], len * System.SizeOf(Byte));
+      Fcipher.ProcessBlock(block, 0, output, outOff);
+      System.Move(lastBlock[0], output[outOff + blockSize],
+        len * System.SizeOf(Byte));
+    end
+    else
+    begin
+      Fcipher.ProcessBlock(Fbuf, 0, block, 0);
+      System.Move(block[0], output[outOff], blockSize * System.SizeOf(Byte));
+    end;
+
+  end;
+
+  result := FbufOff;
+
+  Reset();
+end;
+
+function TCtsBlockCipher.GetOutputSize(inputLen: Int32): Int32;
+begin
+  result := inputLen + FbufOff;
+end;
+
+function TCtsBlockCipher.GetUpdateOutputSize(inputLen: Int32): Int32;
+var
+  total, leftOver: Int32;
+begin
+  total := inputLen + FbufOff;
+  leftOver := total mod System.Length(Fbuf);
+
+  if (leftOver = 0) then
+  begin
+    result := total - System.Length(Fbuf);
+    Exit;
+  end;
+  result := total - leftOver;
+end;
+
+function TCtsBlockCipher.ProcessByte(input: Byte;
+  const output: TCryptoLibByteArray; outOff: Int32): Int32;
+begin
+  result := 0;
+
+  if (FbufOff = System.Length(Fbuf)) then
+  begin
+    result := Fcipher.ProcessBlock(Fbuf, 0, output, outOff);
+    System.Move(Fbuf[FblockSize], Fbuf[0], FblockSize * System.SizeOf(Byte));
+    FbufOff := FblockSize;
+  end;
+
+  Fbuf[FbufOff] := input;
+  System.Inc(FbufOff);
+end;
+
+function TCtsBlockCipher.ProcessBytes(const input: TCryptoLibByteArray;
+  inOff, len: Int32; const output: TCryptoLibByteArray; outOff: Int32): Int32;
+var
+  blockSize, Length, gapLen: Int32;
+begin
+  if (len < 0) then
+  begin
+    raise EInvalidArgument.CreateRes(@SNegativeInputLength);
+  end;
+
+  blockSize := GetBlockSize();
+  Length := GetUpdateOutputSize(len);
+
+  if (Length > 0) then
+  begin
+    if ((outOff + Length) > System.Length(output)) then
+    begin
+      raise EDataLengthCryptoLibException.CreateRes(@SOutputBufferTooShort);
+    end;
+  end;
+
+  result := 0;
+  gapLen := System.Length(Fbuf) - FbufOff;
+
+  if (len > gapLen) then
+  begin
+    System.Move(input[inOff], Fbuf[FbufOff], gapLen * System.SizeOf(Byte));
+
+    result := result + Fcipher.ProcessBlock(Fbuf, 0, output, outOff);
+    System.Move(Fbuf[blockSize], Fbuf[0], blockSize * System.SizeOf(Byte));
+
+    FbufOff := blockSize;
+
+    len := len - gapLen;
+    inOff := inOff + gapLen;
+
+    while (len > blockSize) do
+    begin
+      System.Move(input[inOff], Fbuf[FbufOff], blockSize * System.SizeOf(Byte));
+      result := result + Fcipher.ProcessBlock(Fbuf, 0, output, outOff + result);
+      System.Move(Fbuf[blockSize], Fbuf[0], blockSize * System.SizeOf(Byte));
+
+      len := len - blockSize;
+      inOff := inOff + blockSize;
+    end;
+  end;
+
+  System.Move(input[inOff], Fbuf[FbufOff], len * System.SizeOf(Byte));
+
+  FbufOff := FbufOff + len;
+
 end;
 end;
 
 
 end.
 end.

+ 2 - 1
src/libraries/cryptolib4pascal/ClpBlowfishEngine.pas

@@ -277,7 +277,6 @@ type
 
 
     function GetAlgorithmName: String; virtual;
     function GetAlgorithmName: String; virtual;
     function GetIsPartialBlockOkay: Boolean; virtual;
     function GetIsPartialBlockOkay: Boolean; virtual;
-    function GetBlockSize(): Int32; virtual;
 
 
   public
   public
 
 
@@ -301,6 +300,8 @@ type
 
 
     procedure Reset(); virtual;
     procedure Reset(); virtual;
 
 
+    function GetBlockSize(): Int32; virtual;
+
     property AlgorithmName: String read GetAlgorithmName;
     property AlgorithmName: String read GetAlgorithmName;
     property IsPartialBlockOkay: Boolean read GetIsPartialBlockOkay;
     property IsPartialBlockOkay: Boolean read GetIsPartialBlockOkay;
 
 

+ 2 - 1
src/libraries/cryptolib4pascal/ClpChaChaEngine.pas

@@ -23,6 +23,7 @@ interface
 
 
 uses
 uses
   SysUtils,
   SysUtils,
+  ClpIStreamCipher,
   ClpIChaChaEngine,
   ClpIChaChaEngine,
   ClpSalsa20Engine,
   ClpSalsa20Engine,
   ClpConverters,
   ClpConverters,
@@ -33,7 +34,7 @@ type
   /// <summary>
   /// <summary>
   /// Implementation of Daniel J. Bernstein's ChaCha stream cipher.
   /// Implementation of Daniel J. Bernstein's ChaCha stream cipher.
   /// </summary>
   /// </summary>
-  TChaChaEngine = class sealed(TSalsa20Engine, IChaChaEngine)
+  TChaChaEngine = class sealed(TSalsa20Engine, IChaChaEngine, IStreamCipher)
 
 
   strict private
   strict private
     /// <summary>
     /// <summary>

+ 29 - 5
src/libraries/cryptolib4pascal/ClpCipherUtilities.pas

@@ -48,6 +48,8 @@ uses
   ClpIBlowfishEngine,
   ClpIBlowfishEngine,
   ClpSalsa20Engine,
   ClpSalsa20Engine,
   ClpISalsa20Engine,
   ClpISalsa20Engine,
+  ClpRijndaelEngine,
+  ClpIRijndaelEngine,
   ClpIBlockCipherPadding;
   ClpIBlockCipherPadding;
 
 
 resourcestring
 resourcestring
@@ -70,11 +72,11 @@ type
 
 
   type
   type
 {$SCOPEDENUMS ON}
 {$SCOPEDENUMS ON}
-    TCipherAlgorithm = (AES, BLOWFISH, SALSA20);
-    TCipherMode = (NONE, CBC, CFB, CTR, ECB, OFB, SIC);
+    TCipherAlgorithm = (AES, BLOWFISH, SALSA20, RIJNDAEL);
+    TCipherMode = (NONE, CBC, CFB, CTR, CTS, ECB, OFB, SIC);
     TCipherPadding = (NOPADDING, ISO10126PADDING, ISO10126D2PADDING,
     TCipherPadding = (NOPADDING, ISO10126PADDING, ISO10126D2PADDING,
       ISO10126_2PADDING, ISO7816_4PADDING, ISO9797_1PADDING, PKCS5,
       ISO10126_2PADDING, ISO7816_4PADDING, ISO9797_1PADDING, PKCS5,
-      PKCS5PADDING, PKCS7, PKCS7PADDING, TBCPADDING, X923PADDING,
+      PKCS5PADDING, PKCS7, PKCS7PADDING, TBCPADDING, WITHCTS, X923PADDING,
       ZEROBYTEPADDING);
       ZEROBYTEPADDING);
 {$SCOPEDENUMS OFF}
 {$SCOPEDENUMS OFF}
 
 
@@ -192,7 +194,7 @@ class function TCipherUtilities.GetCipher(algorithm: String): IBufferedCipher;
 var
 var
   aliased, algorithmName, temp, paddingName, mode, modeName: string;
   aliased, algorithmName, temp, paddingName, mode, modeName: string;
   di, LowPoint, bits, HighPoint: Int32;
   di, LowPoint, bits, HighPoint: Int32;
-  padded: Boolean;
+  padded, CTS: Boolean;
   parts: TCryptoLibStringArray;
   parts: TCryptoLibStringArray;
   cipherAlgorithm: TCipherAlgorithm;
   cipherAlgorithm: TCipherAlgorithm;
   cipherPadding: TCipherPadding;
   cipherPadding: TCipherPadding;
@@ -239,6 +241,10 @@ begin
       begin
       begin
         blockCipher := TBlowfishEngine.Create() as IBlowfishEngine;
         blockCipher := TBlowfishEngine.Create() as IBlowfishEngine;
       end;
       end;
+    TCipherAlgorithm.RIJNDAEL:
+      begin
+        blockCipher := TRijndaelEngine.Create() as IRijndaelEngine;
+      end;
     TCipherAlgorithm.SALSA20:
     TCipherAlgorithm.SALSA20:
       begin
       begin
         streamCipher := TSalsa20Engine.Create() as ISalsa20Engine;
         streamCipher := TSalsa20Engine.Create() as ISalsa20Engine;
@@ -263,6 +269,7 @@ begin
     Exit;
     Exit;
   end;
   end;
 
 
+  CTS := False;
   padded := true;
   padded := true;
   padding := Nil;
   padding := Nil;
 
 
@@ -280,7 +287,7 @@ begin
     case cipherPadding of
     case cipherPadding of
       TCipherPadding.NOPADDING:
       TCipherPadding.NOPADDING:
         begin
         begin
-          padded := false;
+          padded := False;
         end;
         end;
 
 
       TCipherPadding.ISO10126PADDING, TCipherPadding.ISO10126D2PADDING,
       TCipherPadding.ISO10126PADDING, TCipherPadding.ISO10126D2PADDING,
@@ -305,6 +312,11 @@ begin
           padding := TTBCPadding.Create() as ITBCPadding;
           padding := TTBCPadding.Create() as ITBCPadding;
         end;
         end;
 
 
+      TCipherPadding.WITHCTS:
+        begin
+          CTS := true;
+        end;
+
       TCipherPadding.X923PADDING:
       TCipherPadding.X923PADDING:
         begin
         begin
           padding := TX923Padding.Create() as IX923Padding;
           padding := TX923Padding.Create() as IX923Padding;
@@ -393,6 +405,12 @@ begin
           blockCipher := TSicBlockCipher.Create(blockCipher) as ISicBlockCipher;
           blockCipher := TSicBlockCipher.Create(blockCipher) as ISicBlockCipher;
         end;
         end;
 
 
+      TCipherMode.CTS:
+        begin
+          CTS := true;
+          blockCipher := TCbcBlockCipher.Create(blockCipher) as ICbcBlockCipher;
+        end;
+
       TCipherMode.OFB:
       TCipherMode.OFB:
         begin
         begin
           if (di < 0) then
           if (di < 0) then
@@ -433,6 +451,12 @@ begin
   if (blockCipher <> Nil) then
   if (blockCipher <> Nil) then
   begin
   begin
 
 
+    if (CTS) then
+    begin
+      Result := TCtsBlockCipher.Create(blockCipher) as ICtsBlockCipher;
+      Exit;
+    end;
+
     if (padding <> Nil) then
     if (padding <> Nil) then
     begin
     begin
       Result := TPaddedBufferedBlockCipher.Create(blockCipher, padding)
       Result := TPaddedBufferedBlockCipher.Create(blockCipher, padding)

+ 10 - 7
src/libraries/cryptolib4pascal/ClpECC.pas

@@ -243,7 +243,8 @@ type
 
 
     property Q: TBigInteger read GetQ;
     property Q: TBigInteger read GetQ;
 
 
-    function Equals(const other: IFpFieldElement): Boolean; reintroduce; overload;
+    function Equals(const other: IFpFieldElement): Boolean;
+      reintroduce; overload;
 
 
     function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
     function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
 {$ENDIF DELPHI}override;
 {$ENDIF DELPHI}override;
@@ -393,7 +394,8 @@ type
 
 
     function SquarePow(pow: Int32): IECFieldElement; override;
     function SquarePow(pow: Int32): IECFieldElement; override;
 
 
-    function Equals(const other: IF2mFieldElement): Boolean; reintroduce; overload;
+    function Equals(const other: IF2mFieldElement): Boolean;
+      reintroduce; overload;
 
 
     function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
     function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
 {$ENDIF DELPHI}override;
 {$ENDIF DELPHI}override;
@@ -1091,7 +1093,8 @@ type
     function GetIsInfinity: Boolean; inline;
     function GetIsInfinity: Boolean; inline;
     function GetIsCompressed: Boolean; inline;
     function GetIsCompressed: Boolean; inline;
     function GetpreCompTable: TDictionary<String, IPreCompInfo>; inline;
     function GetpreCompTable: TDictionary<String, IPreCompInfo>; inline;
-    procedure SetpreCompTable(const Value: TDictionary<String, IPreCompInfo>); inline;
+    procedure SetpreCompTable(const Value
+      : TDictionary<String, IPreCompInfo>); inline;
     function GetCurve: IECCurve; virtual;
     function GetCurve: IECCurve; virtual;
     function GetCurveCoordinateSystem: Int32; virtual;
     function GetCurveCoordinateSystem: Int32; virtual;
     function GetAffineXCoord: IECFieldElement; virtual;
     function GetAffineXCoord: IECFieldElement; virtual;
@@ -1718,8 +1721,8 @@ begin
   xx := (x as IF2mFieldElement).x;
   xx := (x as IF2mFieldElement).x;
   yx := (y as IF2mFieldElement).x;
   yx := (y as IF2mFieldElement).x;
 
 
-  ab := ax.Multiply(bx, Fm, FKs);
-  xy := xx.Multiply(yx, Fm, FKs);
+  ab := ax.Multiply(bx);
+  xy := xx.Multiply(yx);
 
 
   if ((ab.Equals(ax)) or (ab.Equals(bx))) then
   if ((ab.Equals(ax)) or (ab.Equals(bx))) then
   begin
   begin
@@ -1770,8 +1773,8 @@ begin
   xx := (x as IF2mFieldElement).x;
   xx := (x as IF2mFieldElement).x;
   yx := (y as IF2mFieldElement).x;
   yx := (y as IF2mFieldElement).x;
 
 
-  aa := ax.Square(Fm, FKs);
-  xy := xx.Multiply(yx, Fm, FKs);
+  aa := ax.Square();
+  xy := xx.Multiply(yx);
 
 
   if (aa.Equals(ax)) then
   if (aa.Equals(ax)) then
   begin
   begin

+ 23 - 1
src/libraries/cryptolib4pascal/ClpIBlockCipherModes.pas

@@ -22,7 +22,9 @@ unit ClpIBlockCipherModes;
 interface
 interface
 
 
 uses
 uses
-  ClpIBlockCipher;
+  ClpIBlockCipher,
+  ClpIBufferedBlockCipher,
+  ClpCryptoLibTypes;
 
 
 type
 type
   ICbcBlockCipher = interface(IBlockCipher)
   ICbcBlockCipher = interface(IBlockCipher)
@@ -84,6 +86,26 @@ type
 
 
   end;
   end;
 
 
+type
+  ICtsBlockCipher = interface(IBufferedBlockCipher)
+
+    ['{4D02FD0B-47D6-4914-B31F-5869FF364558}']
+
+    function GetOutputSize(inputLen: Int32): Int32;
+
+    function GetUpdateOutputSize(inputLen: Int32): Int32;
+
+    function ProcessByte(input: Byte; const output: TCryptoLibByteArray;
+      outOff: Int32): Int32;
+
+    function ProcessBytes(const input: TCryptoLibByteArray;
+      inOff, Length: Int32; const output: TCryptoLibByteArray;
+      outOff: Int32): Int32;
+
+    function DoFinal(const output: TCryptoLibByteArray; outOff: Int32): Int32;
+
+  end;
+
 implementation
 implementation
 
 
 end.
 end.

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

@@ -39,7 +39,7 @@ uses
   ClpIParametersWithIV,
   ClpIParametersWithIV,
   ClpIKeyParser,
   ClpIKeyParser,
   ClpIEphemeralKeyPair,
   ClpIEphemeralKeyPair,
-  ClpKDFParameters,
+  ClpKdfParameters,
   ClpIKdfParameters,
   ClpIKdfParameters,
   ClpIIESWithCipherParameters,
   ClpIIESWithCipherParameters,
   ClpConverters,
   ClpConverters,

+ 36 - 0
src/libraries/cryptolib4pascal/ClpIRijndaelEngine.pas

@@ -0,0 +1,36 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIRijndaelEngine;
+
+{$I CryptoLib.inc}
+
+interface
+
+uses
+  ClpIBlockCipher;
+
+type
+
+  IRijndaelEngine = interface(IBlockCipher)
+    ['{F4BB47F6-082F-4318-8434-95F06C26CE77}']
+
+  end;
+
+implementation
+
+end.

+ 0 - 5
src/libraries/cryptolib4pascal/ClpISignersEncodings.pas

@@ -103,11 +103,6 @@ type
     procedure EncodeValue(const n, x: TBigInteger;
     procedure EncodeValue(const n, x: TBigInteger;
       const buf: TCryptoLibByteArray; off, len: Int32);
       const buf: TCryptoLibByteArray; off, len: Int32);
 
 
-    function Decode(const n: TBigInteger; const encoding: TCryptoLibByteArray)
-      : TCryptoLibGenericArray<TBigInteger>;
-
-    function Encode(const n, r, s: TBigInteger): TCryptoLibByteArray;
-
   end;
   end;
 
 
 implementation
 implementation

+ 8 - 12
src/libraries/cryptolib4pascal/ClpLongArray.pas

@@ -515,8 +515,8 @@ type
     class procedure FlipVector(const x: TCryptoLibInt64Array; xOff: Int32;
     class procedure FlipVector(const x: TCryptoLibInt64Array; xOff: Int32;
       const y: TCryptoLibInt64Array; yOff, yLen, bits: Int32); static;
       const y: TCryptoLibInt64Array; yOff, yLen, bits: Int32); static;
 
 
-    class procedure SquareInPlace(const x: TCryptoLibInt64Array; xLen, m: Int32;
-      const ks: TCryptoLibInt32Array); static; inline;
+    class procedure SquareInPlace(const x: TCryptoLibInt64Array; xLen: Int32);
+      static; inline;
 
 
     class procedure Interleave(const x: TCryptoLibInt64Array; xOff: Int32;
     class procedure Interleave(const x: TCryptoLibInt64Array; xOff: Int32;
       const z: TCryptoLibInt64Array; zOff, count, width: Int32); static; inline;
       const z: TCryptoLibInt64Array; zOff, count, width: Int32); static; inline;
@@ -603,8 +603,7 @@ type
     function ModReduce(m: Int32; const ks: TCryptoLibInt32Array)
     function ModReduce(m: Int32; const ks: TCryptoLibInt32Array)
       : TLongArray; inline;
       : TLongArray; inline;
 
 
-    function Multiply(const other: TLongArray; m: Int32;
-      const ks: TCryptoLibInt32Array): TLongArray;
+    function Multiply(const other: TLongArray): TLongArray;
 
 
     procedure Reduce(m: Int32; const ks: TCryptoLibInt32Array); inline;
     procedure Reduce(m: Int32; const ks: TCryptoLibInt32Array); inline;
 
 
@@ -614,8 +613,7 @@ type
     function ModSquareN(n, m: Int32; const ks: TCryptoLibInt32Array)
     function ModSquareN(n, m: Int32; const ks: TCryptoLibInt32Array)
       : TLongArray; inline;
       : TLongArray; inline;
 
 
-    function Square(m: Int32; const ks: TCryptoLibInt32Array)
-      : TLongArray; inline;
+    function Square(): TLongArray; inline;
 
 
     function ModInverse(m: Int32; const ks: TCryptoLibInt32Array): TLongArray;
     function ModInverse(m: Int32; const ks: TCryptoLibInt32Array): TLongArray;
 
 
@@ -787,7 +785,7 @@ begin
 end;
 end;
 
 
 class procedure TLongArray.SquareInPlace(const x: TCryptoLibInt64Array;
 class procedure TLongArray.SquareInPlace(const x: TCryptoLibInt64Array;
-  xLen, m: Int32; const ks: TCryptoLibInt32Array);
+  xLen: Int32);
 var
 var
   pos: Int32;
   pos: Int32;
   xVal: Int64;
   xVal: Int64;
@@ -2241,7 +2239,7 @@ begin
   System.Dec(n);
   System.Dec(n);
   while (n >= 0) do
   while (n >= 0) do
   begin
   begin
-    SquareInPlace(r, len, m, ks);
+    SquareInPlace(r, len);
     len := ReduceInPlace(r, 0, System.Length(r), m, ks);
     len := ReduceInPlace(r, 0, System.Length(r), m, ks);
     System.Dec(n);
     System.Dec(n);
   end;
   end;
@@ -2249,8 +2247,7 @@ begin
   Result := TLongArray.Create(r, 0, len);
   Result := TLongArray.Create(r, 0, len);
 end;
 end;
 
 
-function TLongArray.Multiply(const other: TLongArray; m: Int32;
-  const ks: TCryptoLibInt32Array): TLongArray;
+function TLongArray.Multiply(const other: TLongArray): TLongArray;
 var
 var
   aDeg, bDeg, tmp, aLen, bLen, cLen, bMax, tOff, I, MASK, aPos, cOff,
   aDeg, bDeg, tmp, aLen, bLen, cLen, bMax, tOff, I, MASK, aPos, cOff,
     u, v: Int32;
     u, v: Int32;
@@ -2501,8 +2498,7 @@ begin
   Result := prev;
   Result := prev;
 end;
 end;
 
 
-function TLongArray.Square(m: Int32; const ks: TCryptoLibInt32Array)
-  : TLongArray;
+function TLongArray.Square(): TLongArray;
 var
 var
   len, _2len, pos: Int32;
   len, _2len, pos: Int32;
   r: TCryptoLibInt64Array;
   r: TCryptoLibInt64Array;

+ 911 - 0
src/libraries/cryptolib4pascal/ClpRijndaelEngine.pas

@@ -0,0 +1,911 @@
+{ *********************************************************************************** }
+{ *                              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 ClpRijndaelEngine;
+
+{$I CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpCheck,
+  ClpIBlockCipher,
+  ClpIRijndaelEngine,
+  ClpIKeyParameter,
+  ClpICipherParameters,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SInputBuffertooShort = 'Input Buffer too Short';
+  SOutputBuffertooShort = 'Output Buffer too Short';
+  SUnsupportedBlock = 'Unknown Blocksize to Rijndael';
+  SInvalidKeyLength = 'Key Length not 128/160/192/224/256 bits.';
+  SRijndaelEngineNotInitialised = 'Rijndael Engine not Initialised';
+  SInvalidParameterRijndaelInit =
+    'Invalid Parameter Passed to Rijndael Init - "%s"';
+
+type
+
+  /// <summary>
+  /// <para>
+  /// an implementation of Rijndael, based on the documentation and
+  /// reference implementation by Paulo Barreto, Vincent Rijmen, for v2.0
+  /// August '99.
+  /// </para>
+  /// <para>
+  /// Note: this implementation is based on information prior to readonly
+  /// NIST publication.
+  /// </para>
+  /// </summary>
+  TRijndaelEngine = class(TInterfacedObject, IRijndaelEngine, IBlockCipher)
+
+  strict private
+  const
+    MAXROUNDS = Int32(14);
+    MAXKC = Int32(256 div 4);
+
+    Logtable: array [0 .. 255] of Byte = (0, 0, 25, 1, 50, 2, 26, 198, 75, 199,
+      27, 104, 51, 238, 223, 3, 100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8,
+      200, 248, 105, 28, 193, 125, 194, 29, 181, 249, 185, 39, 106, 77, 228,
+      166, 114, 154, 201, 9, 120, 101, 47, 138, 5, 33, 15, 225, 36, 18, 240,
+      130, 69, 53, 147, 218, 142, 150, 143, 219, 189, 54, 208, 206, 148, 19, 92,
+      210, 241, 64, 70, 131, 56, 102, 221, 253, 48, 191, 6, 139, 98, 179, 37,
+      226, 152, 34, 136, 145, 16, 126, 110, 72, 195, 163, 182, 30, 66, 58, 107,
+      40, 84, 250, 133, 61, 186, 43, 121, 10, 21, 155, 159, 94, 202, 78, 212,
+      172, 229, 243, 115, 167, 87, 175, 88, 168, 80, 244, 234, 214, 116, 79,
+      174, 233, 213, 231, 230, 173, 232, 44, 215, 117, 122, 235, 22, 11, 245,
+      89, 203, 95, 176, 156, 169, 81, 160, 127, 12, 246, 111, 23, 196, 73, 236,
+      216, 67, 31, 45, 164, 118, 123, 183, 204, 187, 62, 90, 251, 96, 177, 134,
+      59, 82, 161, 108, 170, 85, 41, 157, 151, 178, 135, 144, 97, 190, 220, 252,
+      188, 149, 207, 205, 55, 63, 91, 209, 83, 57, 132, 60, 65, 162, 109, 71,
+      20, 42, 158, 93, 86, 242, 211, 171, 68, 17, 146, 217, 35, 32, 46, 137,
+      180, 124, 184, 38, 119, 153, 227, 165, 103, 74, 237, 222, 197, 49, 254,
+      24, 13, 99, 140, 128, 192, 247, 112, 7);
+
+    Alogtable: array [0 .. 510] of Byte = (0, 3, 5, 15, 17, 51, 85, 255, 26, 46,
+      114, 150, 161, 248, 19, 53, 95, 225, 56, 72, 216, 115, 149, 164, 247, 2,
+      6, 10, 30, 34, 102, 170, 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217,
+      112, 144, 171, 230, 49, 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104,
+      184, 211, 110, 178, 205, 76, 212, 103, 169, 224, 59, 77, 215, 98, 166,
+      241, 8, 24, 40, 120, 136, 131, 158, 185, 208, 107, 189, 220, 127, 129,
+      152, 179, 206, 73, 219, 118, 154, 181, 196, 87, 249, 16, 48, 80, 240, 11,
+      29, 39, 105, 187, 214, 97, 163, 254, 25, 43, 125, 135, 146, 173, 236, 47,
+      113, 147, 174, 233, 32, 96, 160, 251, 22, 58, 78, 210, 109, 183, 194, 93,
+      231, 50, 86, 250, 21, 63, 65, 195, 94, 226, 61, 71, 201, 64, 192, 91, 237,
+      44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, 239, 42, 126, 130,
+      157, 188, 223, 122, 142, 137, 128, 155, 182, 193, 88, 232, 35, 101, 175,
+      234, 37, 111, 177, 200, 67, 197, 84, 252, 31, 33, 99, 165, 244, 7, 9, 27,
+      45, 119, 153, 176, 203, 70, 202, 69, 207, 74, 222, 121, 139, 134, 145,
+      168, 227, 62, 66, 198, 81, 243, 14, 18, 54, 90, 238, 41, 123, 141, 140,
+      143, 138, 133, 148, 167, 242, 13, 23, 57, 75, 221, 124, 132, 151, 162,
+      253, 28, 36, 108, 180, 199, 82, 246, 1, 3, 5, 15, 17, 51, 85, 255, 26, 46,
+      114, 150, 161, 248, 19, 53, 95, 225, 56, 72, 216, 115, 149, 164, 247, 2,
+      6, 10, 30, 34, 102, 170, 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217,
+      112, 144, 171, 230, 49, 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104,
+      184, 211, 110, 178, 205, 76, 212, 103, 169, 224, 59, 77, 215, 98, 166,
+      241, 8, 24, 40, 120, 136, 131, 158, 185, 208, 107, 189, 220, 127, 129,
+      152, 179, 206, 73, 219, 118, 154, 181, 196, 87, 249, 16, 48, 80, 240, 11,
+      29, 39, 105, 187, 214, 97, 163, 254, 25, 43, 125, 135, 146, 173, 236, 47,
+      113, 147, 174, 233, 32, 96, 160, 251, 22, 58, 78, 210, 109, 183, 194, 93,
+      231, 50, 86, 250, 21, 63, 65, 195, 94, 226, 61, 71, 201, 64, 192, 91, 237,
+      44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, 239, 42, 126, 130,
+      157, 188, 223, 122, 142, 137, 128, 155, 182, 193, 88, 232, 35, 101, 175,
+      234, 37, 111, 177, 200, 67, 197, 84, 252, 31, 33, 99, 165, 244, 7, 9, 27,
+      45, 119, 153, 176, 203, 70, 202, 69, 207, 74, 222, 121, 139, 134, 145,
+      168, 227, 62, 66, 198, 81, 243, 14, 18, 54, 90, 238, 41, 123, 141, 140,
+      143, 138, 133, 148, 167, 242, 13, 23, 57, 75, 221, 124, 132, 151, 162,
+      253, 28, 36, 108, 180, 199, 82, 246, 1);
+
+    S: array [0 .. 255] of Byte = (99, 124, 119, 123, 242, 107, 111, 197, 48, 1,
+      103, 43, 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173,
+      212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204,
+      52, 165, 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7,
+      18, 128, 226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59,
+      214, 179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203,
+      190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2,
+      127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218,
+      33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126,
+      61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184,
+      20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98,
+      145, 149, 228, 121, 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244,
+      234, 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116,
+      31, 75, 189, 139, 138, 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185,
+      134, 193, 29, 158, 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135,
+      233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45,
+      15, 176, 84, 187, 22);
+
+    Si: array [0 .. 255] of Byte = (82, 9, 106, 213, 48, 54, 165, 56, 191, 64,
+      163, 158, 129, 243, 215, 251, 124, 227, 57, 130, 155, 47, 255, 135, 52,
+      142, 67, 68, 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238,
+      76, 149, 11, 66, 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91,
+      162, 73, 109, 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212,
+      164, 92, 204, 93, 101, 182, 146, 108, 112, 72, 80, 253, 237, 185, 218, 94,
+      21, 70, 87, 167, 141, 157, 132, 144, 216, 171, 0, 140, 188, 211, 10, 247,
+      228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2, 193, 175,
+      189, 3, 1, 19, 138, 107, 58, 145, 17, 65, 79, 103, 220, 234, 151, 242,
+      207, 206, 240, 180, 230, 115, 150, 172, 116, 34, 231, 173, 53, 133, 226,
+      249, 55, 232, 28, 117, 223, 110, 71, 241, 26, 113, 29, 41, 197, 137, 111,
+      183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75, 198, 210, 121, 32, 154,
+      219, 192, 254, 120, 205, 90, 244, 31, 221, 168, 51, 136, 7, 199, 49, 177,
+      18, 16, 89, 39, 128, 236, 95, 96, 81, 127, 169, 25, 181, 74, 13, 45, 229,
+      122, 159, 147, 201, 156, 239, 160, 224, 59, 77, 174, 42, 245, 176, 200,
+      235, 187, 60, 131, 83, 153, 97, 23, 43, 4, 126, 186, 119, 214, 38, 225,
+      105, 20, 99, 85, 33, 12, 125);
+
+    rcon: array [0 .. 29] of Byte = ($01, $02, $04, $08, $10, $20, $40, $80,
+      $1B, $36, $6C, $D8, $AB, $4D, $9A, $2F, $5E, $BC, $63, $C6, $97, $35, $6A,
+      $D4, $B3, $7D, $FA, $EF, $C5, $91);
+
+    shifts0: array [0 .. 4, 0 .. 3] of Byte = ((0, 8, 16, 24), (0, 8, 16, 24),
+      (0, 8, 16, 24), (0, 8, 16, 32), (0, 8, 24, 32));
+
+    shifts1: array [0 .. 4, 0 .. 3] of Byte = ((0, 24, 16, 8), (0, 32, 24, 16),
+      (0, 40, 32, 24), (0, 48, 40, 24), (0, 56, 40, 32));
+
+  var
+    FForEncryption: Boolean;
+    FBC, FROUNDS, FBlockBits: Int32;
+    FBC_MASK, FA0, FA1, FA2, FA3: UInt64;
+    FShifts0SC, FShifts1SC: TCryptoLibByteArray;
+    FWorkingKey: TCryptoLibMatrixUInt64Array;
+
+    function GetAlgorithmName: String; virtual;
+    function GetIsPartialBlockOkay: Boolean; virtual;
+
+    /// <summary>
+    /// multiply two elements of GF(2^m) needed for MixColumn and
+    /// InvMixColumn
+    /// </summary>
+    function Mul0x2(b: Int32): Byte; inline;
+
+    function Mul0x3(b: Int32): Byte; inline;
+
+    function Mul0x9(b: Int32): Byte; inline;
+
+    function Mul0xb(b: Int32): Byte; inline;
+
+    function Mul0xd(b: Int32): Byte; inline;
+
+    function Mul0xe(b: Int32): Byte; inline;
+
+    /// <summary>
+    /// xor corresponding text input and round key input bytes
+    /// </summary>
+    procedure KeyAddition(const rk: TCryptoLibUInt64Array); inline;
+
+    /// <summary>
+    /// rotate right custom
+    /// </summary>
+    function Shift(r: UInt64; Shift: Int32): UInt64; inline;
+
+    /// <summary>
+    /// Row 0 remains unchanged <br />The other three rows are shifted a
+    /// variable amount
+    /// </summary>
+    procedure ShiftRow(const shiftsSC: TCryptoLibByteArray); inline;
+
+    function ApplyS(r: UInt64; box: PByte): UInt64; inline;
+
+    /// <summary>
+    /// Replace every byte of the input by the byte at that place <br />in
+    /// the nonlinear S-box
+    /// </summary>
+    procedure Substitution(box: PByte); inline;
+
+    /// <summary>
+    /// Mix the bytes of every column in a linear way
+    /// </summary>
+    procedure MixColumn();
+
+    /// <summary>
+    /// Mix the bytes of every column in a linear way <br />This is the
+    /// opposite operation of Mixcolumn
+    /// </summary>
+    procedure InvMixColumn();
+
+    /// <summary>
+    /// Calculate the necessary round keys <br />The number of calculations
+    /// depends on keyBits and blockBits
+    /// </summary>
+    function GenerateWorkingKey(const key: TCryptoLibByteArray)
+      : TCryptoLibMatrixUInt64Array;
+
+    procedure UnPackBlock(const bytes: TCryptoLibByteArray; off: Int32); inline;
+    procedure PackBlock(const bytes: TCryptoLibByteArray; off: Int32); inline;
+
+    procedure EncryptBlock(const rk: TCryptoLibMatrixUInt64Array);
+
+    procedure DecryptBlock(const rk: TCryptoLibMatrixUInt64Array);
+
+  public
+
+    /// <summary>
+    /// default constructor - 128 bit block size.
+    /// </summary>
+    constructor Create(); overload;
+
+    /// <summary>
+    /// basic constructor - set the cipher up for a given blocksize
+    /// </summary>
+    /// <param name="blockBits">
+    /// the blocksize in bits, must be 128, 192, or 256.
+    /// </param>
+    constructor Create(blockBits: Int32); overload;
+
+    /// <summary>
+    /// initialise a Rijndael cipher.
+    /// </summary>
+    /// <param name="forEncryption">
+    /// whether or not we are for encryption.
+    /// </param>
+    /// <param name="parameters">
+    /// the parameters required to set up the cipher.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the parameters argument is inappropriate.
+    /// </exception>
+    procedure Init(forEncryption: Boolean;
+      const parameters: ICipherParameters); virtual;
+
+    function ProcessBlock(const input: TCryptoLibByteArray; inOff: Int32;
+      const output: TCryptoLibByteArray; outOff: Int32): Int32; virtual;
+
+    procedure Reset(); virtual;
+
+    function GetBlockSize(): Int32; virtual;
+
+    property AlgorithmName: String read GetAlgorithmName;
+    property IsPartialBlockOkay: Boolean read GetIsPartialBlockOkay;
+
+  end;
+
+implementation
+
+{ TRijndaelEngine }
+
+function TRijndaelEngine.Mul0x2(b: Int32): Byte;
+begin
+  if (b <> 0) then
+  begin
+    result := Alogtable[25 + (Logtable[b] and $FF)];
+  end
+  else
+  begin
+    result := 0;
+  end;
+end;
+
+function TRijndaelEngine.Mul0x3(b: Int32): Byte;
+begin
+  if (b <> 0) then
+  begin
+    result := Alogtable[1 + (Logtable[b] and $FF)];
+  end
+  else
+  begin
+    result := 0;
+  end;
+end;
+
+function TRijndaelEngine.Mul0x9(b: Int32): Byte;
+begin
+  if (b >= 0) then
+  begin
+    result := Alogtable[199 + b];
+  end
+  else
+  begin
+    result := 0;
+  end;
+end;
+
+function TRijndaelEngine.Mul0xb(b: Int32): Byte;
+begin
+  if (b >= 0) then
+  begin
+    result := Alogtable[104 + b];
+  end
+  else
+  begin
+    result := 0;
+  end;
+end;
+
+function TRijndaelEngine.Mul0xd(b: Int32): Byte;
+begin
+  if (b >= 0) then
+  begin
+    result := Alogtable[238 + b];
+  end
+  else
+  begin
+    result := 0;
+  end;
+end;
+
+function TRijndaelEngine.Mul0xe(b: Int32): Byte;
+begin
+  if (b >= 0) then
+  begin
+    result := Alogtable[223 + b];
+  end
+  else
+  begin
+    result := 0;
+  end;
+end;
+
+procedure TRijndaelEngine.KeyAddition(const rk: TCryptoLibUInt64Array);
+begin
+  FA0 := FA0 xor rk[0];
+  FA1 := FA1 xor rk[1];
+  FA2 := FA2 xor rk[2];
+  FA3 := FA3 xor rk[3];
+end;
+
+function TRijndaelEngine.Shift(r: UInt64; Shift: Int32): UInt64;
+begin
+  result := (((r shr Shift) or (r shl (FBC - Shift)))) and FBC_MASK;
+end;
+
+procedure TRijndaelEngine.ShiftRow(const shiftsSC: TCryptoLibByteArray);
+begin
+  FA1 := Shift(FA1, shiftsSC[1]);
+  FA2 := Shift(FA2, shiftsSC[2]);
+  FA3 := Shift(FA3, shiftsSC[3]);
+end;
+
+function TRijndaelEngine.ApplyS(r: UInt64; box: PByte): UInt64;
+var
+  j: Int32;
+begin
+  result := 0;
+  j := 0;
+  while j < FBC do
+  begin
+    result := result or (UInt64(box[((r shr j) and $FF)] and $FF) shl j);
+    System.Inc(j, 8);
+  end;
+end;
+
+procedure TRijndaelEngine.Substitution(box: PByte);
+begin
+  FA0 := ApplyS(FA0, box);
+  FA1 := ApplyS(FA1, box);
+  FA2 := ApplyS(FA2, box);
+  FA3 := ApplyS(FA3, box);
+end;
+
+procedure TRijndaelEngine.MixColumn;
+var
+  r0, r1, r2, r3: UInt64;
+  a0, a1, a2, a3, j: Int32;
+begin
+  r0 := 0;
+  r1 := 0;
+  r2 := 0;
+  r3 := 0;
+  j := 0;
+  while j < FBC do
+  begin
+
+    a0 := Int32((FA0 shr j) and $FF);
+    a1 := Int32((FA1 shr j) and $FF);
+    a2 := Int32((FA2 shr j) and $FF);
+    a3 := Int32((FA3 shr j) and $FF);
+
+    r0 := r0 or (UInt64(((Mul0x2(a0) xor Mul0x3(a1) xor a2 xor a3) and
+      $FF)) shl j);
+
+    r1 := r1 or (UInt64(((Mul0x2(a1) xor Mul0x3(a2) xor a3 xor a0) and
+      $FF)) shl j);
+
+    r2 := r2 or (UInt64(((Mul0x2(a2) xor Mul0x3(a3) xor a0 xor a1) and
+      $FF)) shl j);
+
+    r3 := r3 or (UInt64(((Mul0x2(a3) xor Mul0x3(a0) xor a1 xor a2) and
+      $FF)) shl j);
+
+    System.Inc(j, 8);
+  end;
+
+  FA0 := r0;
+  FA1 := r1;
+  FA2 := r2;
+  FA3 := r3;
+end;
+
+procedure TRijndaelEngine.InvMixColumn;
+var
+  r0, r1, r2, r3: UInt64;
+  a0, a1, a2, a3, j: Int32;
+begin
+  r0 := 0;
+  r1 := 0;
+  r2 := 0;
+  r3 := 0;
+  j := 0;
+  while j < FBC do
+  begin
+
+    a0 := Int32((FA0 shr j) and $FF);
+    a1 := Int32((FA1 shr j) and $FF);
+    a2 := Int32((FA2 shr j) and $FF);
+    a3 := Int32((FA3 shr j) and $FF);
+
+    //
+    // pre-lookup the log table
+    //
+    if (a0 <> 0) then
+    begin
+      a0 := (Logtable[a0 and $FF] and $FF);
+    end
+    else
+    begin
+      a0 := -1;
+    end;
+
+    if (a1 <> 0) then
+    begin
+      a1 := (Logtable[a1 and $FF] and $FF);
+    end
+    else
+    begin
+      a1 := -1;
+    end;
+
+    if (a2 <> 0) then
+    begin
+      a2 := (Logtable[a2 and $FF] and $FF);
+    end
+    else
+    begin
+      a2 := -1;
+    end;
+
+    if (a3 <> 0) then
+    begin
+      a3 := (Logtable[a3 and $FF] and $FF);
+    end
+    else
+    begin
+      a3 := -1;
+    end;
+
+    r0 := r0 or
+      (UInt64(((Mul0xe(a0) xor Mul0xb(a1) xor Mul0xd(a2) xor Mul0x9(a3)) and
+      $FF)) shl j);
+
+    r1 := r1 or
+      (UInt64(((Mul0xe(a1) xor Mul0xb(a2) xor Mul0xd(a3) xor Mul0x9(a0)) and
+      $FF)) shl j);
+
+    r2 := r2 or
+      (UInt64(((Mul0xe(a2) xor Mul0xb(a3) xor Mul0xd(a0) xor Mul0x9(a1)) and
+      $FF)) shl j);
+
+    r3 := r3 or
+      (UInt64(((Mul0xe(a3) xor Mul0xb(a0) xor Mul0xd(a1) xor Mul0x9(a2)) and
+      $FF)) shl j);
+
+    System.Inc(j, 8);
+  end;
+
+  FA0 := r0;
+  FA1 := r1;
+  FA2 := r2;
+  FA3 := r3;
+end;
+
+function TRijndaelEngine.GenerateWorkingKey(const key: TCryptoLibByteArray)
+  : TCryptoLibMatrixUInt64Array;
+var
+  KC, t, rconpointer, keyBits, i, index, j: Int32;
+  tk: TCryptoLibMatrixByteArray;
+  W: TCryptoLibMatrixUInt64Array;
+begin
+  rconpointer := 0;
+  keyBits := System.Length(key) * 8;
+  System.SetLength(tk, 4);
+  for i := System.Low(tk) to System.High(tk) do
+  begin
+    System.SetLength(tk[i], MAXKC);
+  end;
+
+  System.SetLength(W, MAXROUNDS + 1);
+  for i := System.Low(W) to System.High(W) do
+  begin
+    System.SetLength(W[i], 4);
+  end;
+
+  case keyBits of
+    128:
+      KC := 4;
+    160:
+      KC := 5;
+    192:
+      KC := 6;
+    224:
+      KC := 7;
+    256:
+      KC := 8
+  else
+    begin
+      raise EArgumentCryptoLibException.CreateRes(@SInvalidKeyLength);
+    end;
+  end;
+
+  if (keyBits >= FBlockBits) then
+  begin
+    FROUNDS := KC + 6;
+  end
+  else
+  begin
+    FROUNDS := (FBC div 8) + 6;
+  end;
+
+  //
+  // copy the key into the processing area
+  //
+  index := 0;
+
+  for i := 0 to System.Pred(System.Length(key)) do
+  begin
+    tk[i mod 4][i div 4] := key[index];
+    System.Inc(index);
+  end;
+
+  t := 0;
+  //
+  // copy values into round key array
+  //
+  j := 0;
+
+  while ((j < KC) and (t < ((FROUNDS + 1) * (FBC div 8)))) do
+  begin
+    for i := 0 to System.Pred(4) do
+    begin
+      W[t div (FBC div 8)][i] := W[t div (FBC div 8)][i] or
+        (UInt64(tk[i][j] and $FF) shl ((t * 8) mod FBC));
+    end;
+    System.Inc(j);
+    System.Inc(t);
+  end;
+
+  //
+  // while not enough round key material calculated
+  // calculate new values
+  //
+  while (t < ((FROUNDS + 1) * (FBC div 8))) do
+  begin
+
+    for i := 0 to System.Pred(4) do
+    begin
+      tk[i][0] := tk[i][0] xor (S[tk[(i + 1) mod 4][KC - 1] and $FF]);
+    end;
+
+    tk[0][0] := tk[0][0] xor Byte(rcon[rconpointer]);
+    System.Inc(rconpointer);
+
+    if (KC <= 6) then
+    begin
+      for j := 1 to System.Pred(KC) do
+      begin
+        for i := 0 to System.Pred(4) do
+        begin
+          tk[i][j] := tk[i][j] xor tk[i][j - 1];
+        end;
+      end;
+    end
+    else
+    begin
+
+      for j := 1 to System.Pred(4) do
+      begin
+        for i := 0 to System.Pred(4) do
+        begin
+          tk[i][j] := tk[i][j] xor tk[i][j - 1];
+        end;
+      end;
+
+      for i := 0 to System.Pred(4) do
+      begin
+        tk[i][4] := tk[i][4] xor (S[tk[i][3] and $FF]);
+      end;
+
+      for j := 5 to System.Pred(KC) do
+      begin
+        for i := 0 to System.Pred(4) do
+        begin
+          tk[i][j] := tk[i][j] xor tk[i][j - 1];
+        end;
+      end;
+    end;
+
+    //
+    // copy values into round key array
+    //
+    j := 0;
+
+    while ((j < KC) and (t < ((FROUNDS + 1) * (FBC div 8)))) do
+    begin
+      for i := 0 to System.Pred(4) do
+      begin
+        W[t div (FBC div 8)][i] := W[t div (FBC div 8)][i] or
+          (UInt64(tk[i][j] and $FF) shl ((t * 8) mod FBC));
+      end;
+      System.Inc(j);
+      System.Inc(t);
+    end;
+  end;
+  result := W;
+end;
+
+procedure TRijndaelEngine.PackBlock(const bytes: TCryptoLibByteArray;
+  off: Int32);
+var
+  index, j: Int32;
+begin
+  index := off;
+  j := 0;
+
+  while j <> FBC do
+  begin
+    bytes[index] := Byte(FA0 shr j);
+    System.Inc(index);
+    bytes[index] := Byte(FA1 shr j);
+    System.Inc(index);
+    bytes[index] := Byte(FA2 shr j);
+    System.Inc(index);
+    bytes[index] := Byte(FA3 shr j);
+    System.Inc(index);
+    System.Inc(j, 8);
+  end;
+end;
+
+procedure TRijndaelEngine.UnPackBlock(const bytes: TCryptoLibByteArray;
+  off: Int32);
+var
+  index, j: Int32;
+begin
+  index := off;
+
+  FA0 := UInt64(bytes[index] and $FF);
+  System.Inc(index);
+  FA1 := UInt64(bytes[index] and $FF);
+  System.Inc(index);
+  FA2 := UInt64(bytes[index] and $FF);
+  System.Inc(index);
+  FA3 := UInt64(bytes[index] and $FF);
+  System.Inc(index);
+
+  j := 8;
+
+  while j <> FBC do
+  begin
+    FA0 := FA0 or (UInt64(bytes[index] and $FF) shl j);
+    System.Inc(index);
+    FA1 := FA1 or (UInt64(bytes[index] and $FF) shl j);
+    System.Inc(index);
+    FA2 := FA2 or (UInt64(bytes[index] and $FF) shl j);
+    System.Inc(index);
+    FA3 := FA3 or (UInt64(bytes[index] and $FF) shl j);
+    System.Inc(index);
+    System.Inc(j, 8);
+  end;
+end;
+
+procedure TRijndaelEngine.EncryptBlock(const rk: TCryptoLibMatrixUInt64Array);
+var
+  r: Int32;
+begin
+  //
+  // begin with a key addition
+  //
+  KeyAddition(rk[0]);
+
+  //
+  // ROUNDS-1 ordinary rounds
+  //
+  for r := 1 to System.Pred(FROUNDS) do
+  begin
+    Substitution(@(S[0]));
+    ShiftRow(FShifts0SC);
+    MixColumn();
+    KeyAddition(rk[r]);
+  end;
+
+  //
+  // Last round is special: there is no MixColumn
+  //
+  Substitution(@(S[0]));
+  ShiftRow(FShifts0SC);
+  KeyAddition(rk[FROUNDS]);
+end;
+
+procedure TRijndaelEngine.DecryptBlock(const rk: TCryptoLibMatrixUInt64Array);
+var
+  r: Int32;
+begin
+  // To decrypt: apply the inverse operations of the encrypt routine,
+  // in opposite order
+  //
+  // (KeyAddition is an involution: it 's equal to its inverse)
+  // (the inverse of Substitution with table S is Substitution with the inverse table of S)
+  // (the inverse of Shiftrow is Shiftrow over a suitable distance)
+  //
+
+  // First the special round:
+  // without InvMixColumn
+  // with extra KeyAddition
+  //
+  KeyAddition(rk[FROUNDS]);
+  Substitution(@(Si[0]));
+  ShiftRow(FShifts1SC);
+
+  //
+  // ROUNDS-1 ordinary rounds
+  //
+  for r := System.Pred(FROUNDS) downto 1 do
+  begin
+    KeyAddition(rk[r]);
+    InvMixColumn();
+    Substitution(@(Si[0]));
+    ShiftRow(FShifts1SC);
+  end;
+
+  //
+  // End with the extra key addition
+  //
+  KeyAddition(rk[0]);
+end;
+
+constructor TRijndaelEngine.Create();
+begin
+  Create(128);
+end;
+
+constructor TRijndaelEngine.Create(blockBits: Int32);
+begin
+  Inherited Create();
+  case blockBits of
+
+    128:
+      begin
+        FBC := 32;
+        FBC_MASK := $FFFFFFFF;
+        System.SetLength(FShifts0SC, System.SizeOf(shifts0[0]));
+        System.Move(shifts0[0], FShifts0SC[0], System.SizeOf(shifts0[0]));
+        System.SetLength(FShifts1SC, System.SizeOf(shifts1[0]));
+        System.Move(shifts1[0], FShifts1SC[0], System.SizeOf(shifts1[0]));
+      end;
+
+    160:
+      begin
+        FBC := 40;
+        FBC_MASK := $FFFFFFFFFF;
+        System.SetLength(FShifts0SC, System.SizeOf(shifts0[1]));
+        System.Move(shifts0[1], FShifts0SC[0], System.SizeOf(shifts0[1]));
+        System.SetLength(FShifts1SC, System.SizeOf(shifts1[1]));
+        System.Move(shifts1[1], FShifts1SC[0], System.SizeOf(shifts1[1]));
+      end;
+
+    192:
+      begin
+        FBC := 48;
+        FBC_MASK := $FFFFFFFFFFFF;
+        System.SetLength(FShifts0SC, System.SizeOf(shifts0[2]));
+        System.Move(shifts0[2], FShifts0SC[0], System.SizeOf(shifts0[2]));
+        System.SetLength(FShifts1SC, System.SizeOf(shifts1[2]));
+        System.Move(shifts1[2], FShifts1SC[0], System.SizeOf(shifts1[2]));
+      end;
+
+    224:
+      begin
+        FBC := 56;
+        FBC_MASK := $FFFFFFFFFFFFFF;
+        System.SetLength(FShifts0SC, System.SizeOf(shifts0[3]));
+        System.Move(shifts0[3], FShifts0SC[0], System.SizeOf(shifts0[3]));
+        System.SetLength(FShifts1SC, System.SizeOf(shifts1[3]));
+        System.Move(shifts1[3], FShifts1SC[0], System.SizeOf(shifts1[3]));
+      end;
+
+    256:
+      begin
+        FBC := 64;
+        FBC_MASK := UInt64($FFFFFFFFFFFFFFFF);
+        System.SetLength(FShifts0SC, System.SizeOf(shifts0[4]));
+        System.Move(shifts0[4], FShifts0SC[0], System.SizeOf(shifts0[4]));
+        System.SetLength(FShifts1SC, System.SizeOf(shifts1[4]));
+        System.Move(shifts1[4], FShifts1SC[0], System.SizeOf(shifts1[4]));
+      end
+  else
+    begin
+      raise EArgumentOutOfRangeCryptoLibException.CreateRes(@SUnsupportedBlock);
+    end;
+
+  end;
+
+  FBlockBits := blockBits;
+end;
+
+function TRijndaelEngine.GetAlgorithmName: String;
+begin
+  result := 'Rijndael';
+end;
+
+function TRijndaelEngine.GetBlockSize: Int32;
+begin
+  result := FBC div 2;
+end;
+
+function TRijndaelEngine.GetIsPartialBlockOkay: Boolean;
+begin
+  result := False;
+end;
+
+procedure TRijndaelEngine.Init(forEncryption: Boolean;
+  const parameters: ICipherParameters);
+var
+  keyParameter: IKeyParameter;
+begin
+  if not Supports(parameters, IKeyParameter, keyParameter) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt
+      (@SInvalidParameterRijndaelInit, [(parameters as TObject).ToString]);
+  end;
+
+  FWorkingKey := GenerateWorkingKey(keyParameter.GetKey());
+
+  FForEncryption := forEncryption;
+end;
+
+function TRijndaelEngine.ProcessBlock(const input: TCryptoLibByteArray;
+  inOff: Int32; const output: TCryptoLibByteArray; outOff: Int32): Int32;
+begin
+  if (FWorkingKey = Nil) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SRijndaelEngineNotInitialised);
+  end;
+
+  TCheck.DataLength(input, inOff, (FBC div 2), SInputBuffertooShort);
+  TCheck.OutputLength(output, outOff, (FBC div 2), SOutputBuffertooShort);
+
+  UnPackBlock(input, inOff);
+
+  if (FForEncryption) then
+  begin
+    EncryptBlock(FWorkingKey);
+  end
+  else
+  begin
+    DecryptBlock(FWorkingKey);
+  end;
+
+  PackBlock(output, outOff);
+
+  result := FBC div 2;
+end;
+
+procedure TRijndaelEngine.Reset;
+begin
+
+end;
+
+end.

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

@@ -25,10 +25,10 @@ uses
   SysUtils,
   SysUtils,
   ClpBits,
   ClpBits,
   ClpCheck,
   ClpCheck,
+  ClpIStreamCipher,
   ClpISalsa20Engine,
   ClpISalsa20Engine,
   ClpIKeyParameter,
   ClpIKeyParameter,
   ClpICipherParameters,
   ClpICipherParameters,
-  ClpParametersWithIV,
   ClpIParametersWithIV,
   ClpIParametersWithIV,
   ClpConverters,
   ClpConverters,
   ClpCryptoLibTypes;
   ClpCryptoLibTypes;
@@ -56,7 +56,7 @@ type
   /// <summary>
   /// <summary>
   /// Implementation of Daniel J. Bernstein's Salsa20 stream cipher, Snuffle 2005
   /// Implementation of Daniel J. Bernstein's Salsa20 stream cipher, Snuffle 2005
   /// </summary>
   /// </summary>
-  TSalsa20Engine = class(TInterfacedObject, ISalsa20Engine)
+  TSalsa20Engine = class(TInterfacedObject, ISalsa20Engine, IStreamCipher)
 
 
   strict private
   strict private
   const
   const

+ 0 - 1
src/libraries/cryptolib4pascal/ClpSchnorrDigestSigner.pas

@@ -32,7 +32,6 @@ uses
   ClpBigInteger,
   ClpBigInteger,
   ClpCryptoLibTypes,
   ClpCryptoLibTypes,
   ClpIParametersWithRandom,
   ClpIParametersWithRandom,
-  ClpSignersEncodings,
   ClpIAsymmetricKeyParameter,
   ClpIAsymmetricKeyParameter,
   ClpICipherParameters,
   ClpICipherParameters,
   ClpISigner;
   ClpISigner;

+ 2 - 1
src/libraries/cryptolib4pascal/ClpXSalsa20Engine.pas

@@ -22,6 +22,7 @@ unit ClpXSalsa20Engine;
 interface
 interface
 
 
 uses
 uses
+  ClpIStreamCipher,
   ClpSalsa20Engine,
   ClpSalsa20Engine,
   ClpIXSalsa20Engine,
   ClpIXSalsa20Engine,
   ClpConverters,
   ClpConverters,
@@ -38,7 +39,7 @@ type
   /// <remarks>
   /// <remarks>
   /// XSalsa20 requires a 256 bit key, and a 192 bit nonce.
   /// XSalsa20 requires a 256 bit key, and a 192 bit nonce.
   /// </remarks>
   /// </remarks>
-  TXSalsa20Engine = class sealed(TSalsa20Engine, IXSalsa20Engine)
+  TXSalsa20Engine = class sealed(TSalsa20Engine, IXSalsa20Engine, IStreamCipher)
 
 
   strict protected
   strict protected
     function GetAlgorithmName: String; override;
     function GetAlgorithmName: String; override;

+ 1 - 1
src/libraries/cryptolib4pascal/README.md

@@ -1,5 +1,5 @@
 # CryptoLib4Pascal [![License](http://img.shields.io/badge/license-MIT-green.svg)](https://github.com/Xor-el/CryptoLib4Pascal/blob/master/LICENSE)
 # CryptoLib4Pascal [![License](http://img.shields.io/badge/license-MIT-green.svg)](https://github.com/Xor-el/CryptoLib4Pascal/blob/master/LICENSE)
-CryptoLib4Pascal is a Cryptographic Package for Delphi/FreePascal Compilers that provides at the moment support for creating, signing and verifying DSA, ECDSA, ECNR and ECSchnorr signatures using various curves and hashes, AES, Blowfish Encryption and Decryption (With various modes and paddings) and ECIES.
+CryptoLib4Pascal is a Cryptographic Package for Delphi/FreePascal Compilers that provides at the moment support for creating, signing and verifying DSA, ECDSA, ECNR and ECSchnorr signatures using various curves and hashes, AES, Rijndael, Blowfish and Speck Block Encryption and Decryption (With various modes and paddings), Salsa20, XSalsa20, ChaCha Stream Ciphers and ECIES.
 
 
 **Supported Elliptic Curves:**
 **Supported Elliptic Curves:**
 
 

+ 4 - 1
src/libraries/simplebaselib4pascal/SbpBase58.pas

@@ -5,6 +5,7 @@ unit SbpBase58;
 interface
 interface
 
 
 uses
 uses
+  Math,
   SbpSimpleBaseLibTypes,
   SbpSimpleBaseLibTypes,
   SbpUtilities,
   SbpUtilities,
   SbpBase58Alphabet,
   SbpBase58Alphabet,
@@ -94,6 +95,7 @@ const
   reductionFactor = Int32(733);
   reductionFactor = Int32(733);
 var
 var
   textLen, numZeroes, outputLen, carry, resultLen, LowPoint: Int32;
   textLen, numZeroes, outputLen, carry, resultLen, LowPoint: Int32;
+  tempDouble: Double;
   inputPtr, pEnd, pInput: PChar;
   inputPtr, pEnd, pInput: PChar;
   outputPtr, pOutputEnd, pDigit, pOutput: PByte;
   outputPtr, pOutputEnd, pDigit, pOutput: PByte;
   FirstChar, c: Char;
   FirstChar, c: Char;
@@ -130,7 +132,8 @@ begin
     Exit;
     Exit;
   end;
   end;
 
 
-  outputLen := ((textLen * reductionFactor) div 1000) + 1;
+  tempDouble := ((textLen * reductionFactor) / 1000.0) + 1;
+  outputLen := Int32(Round(tempDouble));
   table := Falphabet.ReverseLookupTable;
   table := Falphabet.ReverseLookupTable;
   System.SetLength(output, outputLen);
   System.SetLength(output, outputLen);
   outputPtr := PByte(output);
   outputPtr := PByte(output);