Browse Source

add support for SPECK Cipher Algorithm

Ugochukwu Mmaduekwe 6 years ago
parent
commit
a716cf691a

+ 4 - 2
CryptoLib.Samples/Delphi.Samples/UsageSamples.dpr

@@ -209,7 +209,7 @@ uses
   ClpDsaKeyPairGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpDsaKeyPairGenerator.pas',
   ClpDsaKeyPairGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpDsaKeyPairGenerator.pas',
   ClpIDsaKeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIDsaKeyPairGenerator.pas',
   ClpIDsaKeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIDsaKeyPairGenerator.pas',
   ClpDsaSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpDsaSigner.pas',
   ClpDsaSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpDsaSigner.pas',
-  ClpEncoders in '..\..\cryptolib\src\utils\encoders\ClpEncoders.pas',
+  ClpEncoders in '..\..\CryptoLib\src\Utils\Encoders\ClpEncoders.pas',
   ClpIDsaSigner in '..\..\CryptoLib\src\Interfaces\ClpIDsaSigner.pas',
   ClpIDsaSigner in '..\..\CryptoLib\src\Interfaces\ClpIDsaSigner.pas',
   ClpDigest in '..\..\CryptoLib\src\Crypto\Digests\ClpDigest.pas',
   ClpDigest in '..\..\CryptoLib\src\Crypto\Digests\ClpDigest.pas',
   ClpECDHCBasicAgreement in '..\..\CryptoLib\src\Crypto\Agreement\ClpECDHCBasicAgreement.pas',
   ClpECDHCBasicAgreement in '..\..\CryptoLib\src\Crypto\Agreement\ClpECDHCBasicAgreement.pas',
@@ -240,7 +240,7 @@ uses
   ClpNat512 in '..\..\CryptoLib\src\Math\Raw\ClpNat512.pas',
   ClpNat512 in '..\..\CryptoLib\src\Math\Raw\ClpNat512.pas',
   ClpInterleave in '..\..\CryptoLib\src\Math\Raw\ClpInterleave.pas',
   ClpInterleave in '..\..\CryptoLib\src\Math\Raw\ClpInterleave.pas',
   ClpIDsaExt in '..\..\CryptoLib\src\Interfaces\ClpIDsaExt.pas',
   ClpIDsaExt in '..\..\CryptoLib\src\Interfaces\ClpIDsaExt.pas',
-  ClpISignersEncodings in '..\..\cryptolib\src\interfaces\ClpISignersEncodings.pas',
+  ClpISignersEncodings in '..\..\CryptoLib\src\Interfaces\ClpISignersEncodings.pas',
   ClpBsiObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Bsi\ClpBsiObjectIdentifiers.pas',
   ClpBsiObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Bsi\ClpBsiObjectIdentifiers.pas',
   ClpEacObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Eac\ClpEacObjectIdentifiers.pas',
   ClpEacObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Eac\ClpEacObjectIdentifiers.pas',
   ClpSchnorrDigestSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpSchnorrDigestSigner.pas',
   ClpSchnorrDigestSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpSchnorrDigestSigner.pas',
@@ -251,6 +251,8 @@ uses
   ClpISchnorrExt in '..\..\CryptoLib\src\Interfaces\ClpISchnorrExt.pas',
   ClpISchnorrExt in '..\..\CryptoLib\src\Interfaces\ClpISchnorrExt.pas',
   ClpBlowfishEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpBlowfishEngine.pas',
   ClpBlowfishEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpBlowfishEngine.pas',
   ClpIBlowfishEngine in '..\..\CryptoLib\src\Interfaces\ClpIBlowfishEngine.pas',
   ClpIBlowfishEngine in '..\..\CryptoLib\src\Interfaces\ClpIBlowfishEngine.pas',
+  ClpSpeckEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpSpeckEngine.pas',
+  ClpISpeckEngine in '..\..\CryptoLib\src\Interfaces\ClpISpeckEngine.pas',
   ClpSecP256R1Custom in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256R1Custom.pas',
   ClpSecP256R1Custom in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256R1Custom.pas',
   ClpISecP256R1Custom in '..\..\CryptoLib\src\Interfaces\ClpISecP256R1Custom.pas',
   ClpISecP256R1Custom in '..\..\CryptoLib\src\Interfaces\ClpISecP256R1Custom.pas',
   ClpSecP256K1Custom in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1Custom.pas',
   ClpSecP256K1Custom in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1Custom.pas',

+ 4 - 0
CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.TestInsight.dpr

@@ -261,6 +261,8 @@ uses
   ClpISchnorrExt in '..\..\CryptoLib\src\Interfaces\ClpISchnorrExt.pas',
   ClpISchnorrExt in '..\..\CryptoLib\src\Interfaces\ClpISchnorrExt.pas',
   ClpBlowfishEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpBlowfishEngine.pas',
   ClpBlowfishEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpBlowfishEngine.pas',
   ClpIBlowfishEngine in '..\..\CryptoLib\src\Interfaces\ClpIBlowfishEngine.pas',
   ClpIBlowfishEngine in '..\..\CryptoLib\src\Interfaces\ClpIBlowfishEngine.pas',
+  ClpSpeckEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpSpeckEngine.pas',
+  ClpISpeckEngine in '..\..\CryptoLib\src\Interfaces\ClpISpeckEngine.pas',
   ClpSecP256R1Custom in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256R1Custom.pas',
   ClpSecP256R1Custom in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256R1Custom.pas',
   ClpISecP256R1Custom in '..\..\CryptoLib\src\Interfaces\ClpISecP256R1Custom.pas',
   ClpISecP256R1Custom in '..\..\CryptoLib\src\Interfaces\ClpISecP256R1Custom.pas',
   ClpSecP256K1Custom in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1Custom.pas',
   ClpSecP256K1Custom in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1Custom.pas',
@@ -286,6 +288,7 @@ uses
   BlowfishTestVectors in '..\src\Crypto\BlowfishTestVectors.pas',
   BlowfishTestVectors in '..\src\Crypto\BlowfishTestVectors.pas',
   BlockCipherVectorTests in '..\src\Crypto\BlockCipherVectorTests.pas',
   BlockCipherVectorTests in '..\src\Crypto\BlockCipherVectorTests.pas',
   AESTestVectors in '..\src\Crypto\AESTestVectors.pas',
   AESTestVectors in '..\src\Crypto\AESTestVectors.pas',
+  SpeckTestVectors in '..\src\Crypto\SpeckTestVectors.pas',
   OIDTests in '..\src\Asn1\OIDTests.pas',
   OIDTests in '..\src\Asn1\OIDTests.pas',
   SecureRandomTests in '..\src\Security\SecureRandomTests.pas',
   SecureRandomTests in '..\src\Security\SecureRandomTests.pas',
   EqualsAndHashCodeTests in '..\src\Asn1\EqualsAndHashCodeTests.pas',
   EqualsAndHashCodeTests in '..\src\Asn1\EqualsAndHashCodeTests.pas',
@@ -305,6 +308,7 @@ uses
   AESTests in '..\src\Crypto\AESTests.pas',
   AESTests in '..\src\Crypto\AESTests.pas',
   IESCipherTests in '..\src\Math\IESCipherTests.pas',
   IESCipherTests in '..\src\Math\IESCipherTests.pas',
   AESSICTests in '..\src\Crypto\AESSICTests.pas',
   AESSICTests in '..\src\Crypto\AESSICTests.pas',
+  SPECKTests in '..\src\Crypto\SPECKTests.pas',
   Pkcs5Tests in '..\src\Crypto\Pkcs5Tests.pas',
   Pkcs5Tests in '..\src\Crypto\Pkcs5Tests.pas',
   HkdfGeneratorTests in '..\src\Crypto\HkdfGeneratorTests.pas',
   HkdfGeneratorTests in '..\src\Crypto\HkdfGeneratorTests.pas',
   ECIESTests in '..\src\Math\ECIESTests.pas',
   ECIESTests in '..\src\Math\ECIESTests.pas',

+ 4 - 0
CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr

@@ -264,6 +264,8 @@ uses
   ClpISchnorrExt in '..\..\CryptoLib\src\Interfaces\ClpISchnorrExt.pas',
   ClpISchnorrExt in '..\..\CryptoLib\src\Interfaces\ClpISchnorrExt.pas',
   ClpBlowfishEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpBlowfishEngine.pas',
   ClpBlowfishEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpBlowfishEngine.pas',
   ClpIBlowfishEngine in '..\..\CryptoLib\src\Interfaces\ClpIBlowfishEngine.pas',
   ClpIBlowfishEngine in '..\..\CryptoLib\src\Interfaces\ClpIBlowfishEngine.pas',
+  ClpSpeckEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpSpeckEngine.pas',
+  ClpISpeckEngine in '..\..\CryptoLib\src\Interfaces\ClpISpeckEngine.pas',
   ClpSecP256R1Custom in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256R1Custom.pas',
   ClpSecP256R1Custom in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256R1Custom.pas',
   ClpISecP256R1Custom in '..\..\CryptoLib\src\Interfaces\ClpISecP256R1Custom.pas',
   ClpISecP256R1Custom in '..\..\CryptoLib\src\Interfaces\ClpISecP256R1Custom.pas',
   ClpSecP256K1Custom in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1Custom.pas',
   ClpSecP256K1Custom in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1Custom.pas',
@@ -289,6 +291,7 @@ uses
   BlowfishTestVectors in '..\src\Crypto\BlowfishTestVectors.pas',
   BlowfishTestVectors in '..\src\Crypto\BlowfishTestVectors.pas',
   BlockCipherVectorTests in '..\src\Crypto\BlockCipherVectorTests.pas',
   BlockCipherVectorTests in '..\src\Crypto\BlockCipherVectorTests.pas',
   AESTestVectors in '..\src\Crypto\AESTestVectors.pas',
   AESTestVectors in '..\src\Crypto\AESTestVectors.pas',
+  SpeckTestVectors in '..\src\Crypto\SpeckTestVectors.pas',
   OIDTests in '..\src\Asn1\OIDTests.pas',
   OIDTests in '..\src\Asn1\OIDTests.pas',
   SecureRandomTests in '..\src\Security\SecureRandomTests.pas',
   SecureRandomTests in '..\src\Security\SecureRandomTests.pas',
   EqualsAndHashCodeTests in '..\src\Asn1\EqualsAndHashCodeTests.pas',
   EqualsAndHashCodeTests in '..\src\Asn1\EqualsAndHashCodeTests.pas',
@@ -308,6 +311,7 @@ uses
   AESTests in '..\src\Crypto\AESTests.pas',
   AESTests in '..\src\Crypto\AESTests.pas',
   IESCipherTests in '..\src\Math\IESCipherTests.pas',
   IESCipherTests in '..\src\Math\IESCipherTests.pas',
   AESSICTests in '..\src\Crypto\AESSICTests.pas',
   AESSICTests in '..\src\Crypto\AESSICTests.pas',
+  SPECKTests in '..\src\Crypto\SPECKTests.pas',
   Pkcs5Tests in '..\src\Crypto\Pkcs5Tests.pas',
   Pkcs5Tests in '..\src\Crypto\Pkcs5Tests.pas',
   HkdfGeneratorTests in '..\src\Crypto\HkdfGeneratorTests.pas',
   HkdfGeneratorTests in '..\src\Crypto\HkdfGeneratorTests.pas',
   ECIESTests in '..\src\Math\ECIESTests.pas',
   ECIESTests in '..\src\Math\ECIESTests.pas',

+ 13 - 6
CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
 <CONFIG>
   <ProjectOptions>
   <ProjectOptions>
-    <Version Value="11"/>
+    <Version Value="10"/>
     <PathDelim Value="\"/>
     <PathDelim Value="\"/>
     <General>
     <General>
       <SessionStorage Value="InProjectDir"/>
       <SessionStorage Value="InProjectDir"/>
@@ -17,10 +17,9 @@
       <Version Value="2"/>
       <Version Value="2"/>
     </PublishOptions>
     </PublishOptions>
     <RunParams>
     <RunParams>
-      <FormatVersion Value="2"/>
-      <Modes Count="1">
-        <Mode0 Name="default"/>
-      </Modes>
+      <local>
+        <FormatVersion Value="1"/>
+      </local>
     </RunParams>
     </RunParams>
     <RequiredPackages Count="4">
     <RequiredPackages Count="4">
       <Item1>
       <Item1>
@@ -36,7 +35,7 @@
         <PackageName Value="FCL"/>
         <PackageName Value="FCL"/>
       </Item4>
       </Item4>
     </RequiredPackages>
     </RequiredPackages>
-    <Units Count="48">
+    <Units Count="50">
       <Unit0>
       <Unit0>
         <Filename Value="CryptoLib.lpr"/>
         <Filename Value="CryptoLib.lpr"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
@@ -230,6 +229,14 @@
         <Filename Value="..\src\Crypto\BlowfishTestVectors.pas"/>
         <Filename Value="..\src\Crypto\BlowfishTestVectors.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit47>
       </Unit47>
+      <Unit48>
+        <Filename Value="..\src\Crypto\SpeckTestVectors.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit48>
+      <Unit49>
+        <Filename Value="..\src\Crypto\SPECKTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit49>
     </Units>
     </Units>
   </ProjectOptions>
   </ProjectOptions>
   <CompilerOptions>
   <CompilerOptions>

+ 2 - 0
CryptoLib.Tests/FreePascal.Tests/CryptoLib.lpr

@@ -33,7 +33,9 @@ uses
   BlockCipherMonteCarloTests,
   BlockCipherMonteCarloTests,
   AESTestVectors,
   AESTestVectors,
   BlowfishTestVectors,
   BlowfishTestVectors,
+  SpeckTestVectors,
   AESSICTests,
   AESSICTests,
+  SPECKTests,
   IESCipherTests,
   IESCipherTests,
   MD5HMacTests,
   MD5HMacTests,
   SHA1HMacTests,
   SHA1HMacTests,

+ 11 - 10
CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.Tests.lpi

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
 <CONFIG>
   <ProjectOptions>
   <ProjectOptions>
-    <Version Value="11"/>
+    <Version Value="10"/>
     <PathDelim Value="\"/>
     <PathDelim Value="\"/>
     <General>
     <General>
       <SessionStorage Value="InProjectDir"/>
       <SessionStorage Value="InProjectDir"/>
@@ -18,16 +18,9 @@
     </PublishOptions>
     </PublishOptions>
     <RunParams>
     <RunParams>
       <local>
       <local>
+        <FormatVersion Value="1"/>
         <CommandLineParams Value="--format=plain --all --progress"/>
         <CommandLineParams Value="--format=plain --all --progress"/>
       </local>
       </local>
-      <FormatVersion Value="2"/>
-      <Modes Count="1">
-        <Mode0 Name="default">
-          <local>
-            <CommandLineParams Value="--format=plain --all --progress"/>
-          </local>
-        </Mode0>
-      </Modes>
     </RunParams>
     </RunParams>
     <RequiredPackages Count="2">
     <RequiredPackages Count="2">
       <Item1>
       <Item1>
@@ -37,7 +30,7 @@
         <PackageName Value="FCL"/>
         <PackageName Value="FCL"/>
       </Item2>
       </Item2>
     </RequiredPackages>
     </RequiredPackages>
-    <Units Count="48">
+    <Units Count="50">
       <Unit0>
       <Unit0>
         <Filename Value="CryptoLibConsole.lpr"/>
         <Filename Value="CryptoLibConsole.lpr"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
@@ -230,6 +223,14 @@
         <Filename Value="..\src\Crypto\BlowfishTestVectors.pas"/>
         <Filename Value="..\src\Crypto\BlowfishTestVectors.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit47>
       </Unit47>
+      <Unit48>
+        <Filename Value="..\src\Crypto\SPECKTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit48>
+      <Unit49>
+        <Filename Value="..\src\Crypto\SpeckTestVectors.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit49>
     </Units>
     </Units>
   </ProjectOptions>
   </ProjectOptions>
   <CompilerOptions>
   <CompilerOptions>

+ 2 - 0
CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpr

@@ -31,7 +31,9 @@ uses
   BlockCipherMonteCarloTests,
   BlockCipherMonteCarloTests,
   AESTestVectors,
   AESTestVectors,
   BlowfishTestVectors,
   BlowfishTestVectors,
+  SpeckTestVectors,
   AESSICTests,
   AESSICTests,
+  SPECKTests,
   IESCipherTests,
   IESCipherTests,
   MD5HMacTests,
   MD5HMacTests,
   SHA1HMacTests,
   SHA1HMacTests,

+ 19 - 19
CryptoLib.Tests/src/Crypto/AESSICTests.pas

@@ -79,33 +79,33 @@ begin
   inherited;
   inherited;
 
 
   Fkeys := TCryptoLibMatrixByteArray.Create
   Fkeys := TCryptoLibMatrixByteArray.Create
-    (THex.Decode('2b7e151628aed2a6abf7158809cf4f3c'),
-    THex.Decode('8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'),
+    (THex.Decode('2B7E151628AED2A6ABF7158809CF4F3C'),
+    THex.Decode('8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B'),
     THex.Decode
     THex.Decode
-    ('603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'));
+    ('603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4'));
 
 
   Fplain := TCryptoLibMatrixByteArray.Create
   Fplain := TCryptoLibMatrixByteArray.Create
-    (THex.Decode('6bc1bee22e409f96e93d7e117393172a'),
-    THex.Decode('ae2d8a571e03ac9c9eb76fac45af8e51'),
-    THex.Decode('30c81c46a35ce411e5fbc1191a0a52ef'),
-    THex.Decode('f69f2445df4f9b17ad2b417be66c3710'));
+    (THex.Decode('6BC1BEE22E409F96E93D7E117393172A'),
+    THex.Decode('AE2D8A571E03AC9C9EB76FAC45AF8E51'),
+    THex.Decode('30C81C46A35CE411E5FBC1191A0A52EF'),
+    THex.Decode('F69F2445DF4F9B17AD2B417BE66C3710'));
 
 
   Fcipher := TCryptoLibGenericArray<TCryptoLibMatrixByteArray>.Create
   Fcipher := TCryptoLibGenericArray<TCryptoLibMatrixByteArray>.Create
     (TCryptoLibMatrixByteArray.Create
     (TCryptoLibMatrixByteArray.Create
-    (THex.Decode('874d6191b620e3261bef6864990db6ce'),
-    THex.Decode('9806f66b7970fdff8617187bb9fffdff'),
-    THex.Decode('5ae4df3edbd5d35e5b4f09020db03eab'),
-    THex.Decode('1e031dda2fbe03d1792170a0f3009cee')),
+    (THex.Decode('874D6191B620E3261BEF6864990DB6CE'),
+    THex.Decode('9806F66B7970FDFF8617187BB9FFFDFF'),
+    THex.Decode('5AE4DF3EDBD5D35E5B4F09020DB03EAB'),
+    THex.Decode('1E031DDA2FBE03D1792170A0F3009CEE')),
     TCryptoLibMatrixByteArray.Create
     TCryptoLibMatrixByteArray.Create
-    (THex.Decode('1abc932417521ca24f2b0459fe7e6e0b'),
-    THex.Decode('090339ec0aa6faefd5ccc2c6f4ce8e94'),
-    THex.Decode('1e36b26bd1ebc670d1bd1d665620abf7'),
-    THex.Decode('4f78a7f6d29809585a97daec58c6b050')),
+    (THex.Decode('1ABC932417521CA24F2B0459FE7E6E0B'),
+    THex.Decode('090339EC0AA6FAEFD5CCC2C6F4CE8E94'),
+    THex.Decode('1E36B26BD1EBC670D1BD1D665620ABF7'),
+    THex.Decode('4F78A7F6D29809585A97DAEC58C6B050')),
     TCryptoLibMatrixByteArray.Create
     TCryptoLibMatrixByteArray.Create
-    (THex.Decode('601ec313775789a5b7a7f504bbf3d228'),
-    THex.Decode('f443e3ca4d62b59aca84e990cacaf5c5'),
-    THex.Decode('2b0930daa23de94ce87017ba2d84988d'),
-    THex.Decode('dfc9c58db67aada613c2dd08457941a6')));
+    (THex.Decode('601EC313775789A5B7A7F504BBF3D228'),
+    THex.Decode('F443E3CA4D62B59ACA84E990CACAF5C5'),
+    THex.Decode('2B0930DAA23DE94CE87017BA2D84988D'),
+    THex.Decode('DFC9C58DB67AADA613C2DD08457941A6')));
 end;
 end;
 
 
 procedure TTestAESSIC.TearDown;
 procedure TTestAESSIC.TearDown;

+ 7 - 10
CryptoLib.Tests/src/Crypto/AESTests.pas

@@ -227,8 +227,7 @@ begin
 
 
   // // Set up
   // // Set up
   engine := TAesEngine.Create();
   engine := TAesEngine.Create();
-  blockCipher := TCbcBlockCipher.Create(engine); // CBC
-  // no padding
+  blockCipher := TCbcBlockCipher.Create(engine); // CBC no padding
   cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
   cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
 
 
   for i := System.Low(TAESTestVectors.FOfficialVectorKeys_AES_CBC)
   for i := System.Low(TAESTestVectors.FOfficialVectorKeys_AES_CBC)
@@ -296,8 +295,8 @@ begin
 
 
   // // Set up
   // // Set up
   engine := TAesEngine.Create();
   engine := TAesEngine.Create();
-  blockCipher := TCfbBlockCipher.Create(engine, engine.GetBlockSize * 8); // CFB
-  // no padding
+  // CFB no padding
+  blockCipher := TCfbBlockCipher.Create(engine, engine.GetBlockSize * 8);
   cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
   cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
 
 
   for i := System.Low(TAESTestVectors.FOfficialVectorKeys_AES_CFB)
   for i := System.Low(TAESTestVectors.FOfficialVectorKeys_AES_CFB)
@@ -329,8 +328,7 @@ begin
 
 
   // // Set up
   // // Set up
   engine := TAesEngine.Create();
   engine := TAesEngine.Create();
-  blockCipher := TSicBlockCipher.Create(engine); // CTR
-  // no padding
+  blockCipher := TSicBlockCipher.Create(engine); // CTR no padding
   cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
   cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
 
 
   for i := System.Low(TAESTestVectors.FOfficialVectorKeys_AES_CTR)
   for i := System.Low(TAESTestVectors.FOfficialVectorKeys_AES_CTR)
@@ -362,8 +360,7 @@ begin
 
 
   // // Set up
   // // Set up
   engine := TAesEngine.Create();
   engine := TAesEngine.Create();
-  blockCipher := engine as IBlockCipher; // ECB
-  // no padding
+  blockCipher := engine as IBlockCipher; // ECB no padding
   cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
   cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
 
 
   for i := System.Low(TAESTestVectors.FOfficialVectorKeys_AES_ECB)
   for i := System.Low(TAESTestVectors.FOfficialVectorKeys_AES_ECB)
@@ -393,8 +390,8 @@ begin
 
 
   // // Set up
   // // Set up
   engine := TAesEngine.Create();
   engine := TAesEngine.Create();
-  blockCipher := TOfbBlockCipher.Create(engine, engine.GetBlockSize * 8); // OFB
-  // no padding
+  // OFB no padding
+  blockCipher := TOfbBlockCipher.Create(engine, engine.GetBlockSize * 8);
   cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
   cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
 
 
   for i := System.Low(TAESTestVectors.FOfficialVectorKeys_AES_OFB)
   for i := System.Low(TAESTestVectors.FOfficialVectorKeys_AES_OFB)

+ 88 - 0
CryptoLib.Tests/src/Crypto/BlockCipherVectorTests.pas

@@ -33,6 +33,7 @@ uses
 {$ENDIF FPC}
 {$ENDIF FPC}
   AESTestVectors,
   AESTestVectors,
   BlowfishTestVectors,
   BlowfishTestVectors,
+  SpeckTestVectors,
   ClpIBlockCipher,
   ClpIBlockCipher,
   ClpICipherParameters,
   ClpICipherParameters,
   ClpAesEngine,
   ClpAesEngine,
@@ -41,6 +42,8 @@ uses
   ClpIAesLightEngine,
   ClpIAesLightEngine,
   ClpBlowfishEngine,
   ClpBlowfishEngine,
   ClpIBlowfishEngine,
   ClpIBlowfishEngine,
+  ClpSpeckEngine,
+  ClpISpeckEngine,
   ClpKeyParameter,
   ClpKeyParameter,
   ClpIKeyParameter,
   ClpIKeyParameter,
   ClpParametersWithIV,
   ClpParametersWithIV,
@@ -78,6 +81,11 @@ type
     procedure TestBlockCipherAESEngine;
     procedure TestBlockCipherAESEngine;
     procedure TestBlockCipherAESLightEngine;
     procedure TestBlockCipherAESLightEngine;
     procedure TestBlockCipherBlowfishEngine;
     procedure TestBlockCipherBlowfishEngine;
+    procedure TestBlockCipherSpeck32Engine;
+    procedure TestBlockCipherSpeck48Engine;
+    procedure TestBlockCipherSpeck64Engine;
+    procedure TestBlockCipherSpeck96Engine;
+    procedure TestBlockCipherSpeck128Engine;
     procedure TestBadParameters;
     procedure TestBadParameters;
 
 
   end;
   end;
@@ -249,6 +257,86 @@ begin
 
 
 end;
 end;
 
 
+procedure TTestBlockCipherVector.TestBlockCipherSpeck32Engine;
+var
+  I: Int32;
+begin
+  for I := System.Low(TSpeckTestVectors.FSpeck32BlockCipherVectorKeys)
+    to System.High(TSpeckTestVectors.FSpeck32BlockCipherVectorKeys) do
+  begin
+    DoBlockCipherVectorTest(TSpeck32Engine.Create() as ISpeckEngine,
+      TKeyParameter.Create
+      (THex.Decode(TSpeckTestVectors.FSpeck32BlockCipherVectorKeys[I]))
+      as IKeyParameter, TSpeckTestVectors.FSpeck32BlockCipherVectorInputs[I],
+      TSpeckTestVectors.FSpeck32BlockCipherVectorOutputs[I]);
+  end;
+
+end;
+
+procedure TTestBlockCipherVector.TestBlockCipherSpeck48Engine;
+var
+  I: Int32;
+begin
+  for I := System.Low(TSpeckTestVectors.FSpeck48BlockCipherVectorKeys)
+    to System.High(TSpeckTestVectors.FSpeck48BlockCipherVectorKeys) do
+  begin
+    DoBlockCipherVectorTest(TSpeck48Engine.Create() as ISpeckEngine,
+      TKeyParameter.Create
+      (THex.Decode(TSpeckTestVectors.FSpeck48BlockCipherVectorKeys[I]))
+      as IKeyParameter, TSpeckTestVectors.FSpeck48BlockCipherVectorInputs[I],
+      TSpeckTestVectors.FSpeck48BlockCipherVectorOutputs[I]);
+  end;
+
+end;
+
+procedure TTestBlockCipherVector.TestBlockCipherSpeck64Engine;
+var
+  I: Int32;
+begin
+  for I := System.Low(TSpeckTestVectors.FSpeck64BlockCipherVectorKeys)
+    to System.High(TSpeckTestVectors.FSpeck64BlockCipherVectorKeys) do
+  begin
+    DoBlockCipherVectorTest(TSpeck64Engine.Create() as ISpeckEngine,
+      TKeyParameter.Create
+      (THex.Decode(TSpeckTestVectors.FSpeck64BlockCipherVectorKeys[I]))
+      as IKeyParameter, TSpeckTestVectors.FSpeck64BlockCipherVectorInputs[I],
+      TSpeckTestVectors.FSpeck64BlockCipherVectorOutputs[I]);
+  end;
+
+end;
+
+procedure TTestBlockCipherVector.TestBlockCipherSpeck96Engine;
+var
+  I: Int32;
+begin
+  for I := System.Low(TSpeckTestVectors.FSpeck96BlockCipherVectorKeys)
+    to System.High(TSpeckTestVectors.FSpeck96BlockCipherVectorKeys) do
+  begin
+    DoBlockCipherVectorTest(TSpeck96Engine.Create() as ISpeckEngine,
+      TKeyParameter.Create
+      (THex.Decode(TSpeckTestVectors.FSpeck96BlockCipherVectorKeys[I]))
+      as IKeyParameter, TSpeckTestVectors.FSpeck96BlockCipherVectorInputs[I],
+      TSpeckTestVectors.FSpeck96BlockCipherVectorOutputs[I]);
+  end;
+
+end;
+
+procedure TTestBlockCipherVector.TestBlockCipherSpeck128Engine;
+var
+  I: Int32;
+begin
+  for I := System.Low(TSpeckTestVectors.FSpeck128BlockCipherVectorKeys)
+    to System.High(TSpeckTestVectors.FSpeck128BlockCipherVectorKeys) do
+  begin
+    DoBlockCipherVectorTest(TSpeck128Engine.Create() as ISpeckEngine,
+      TKeyParameter.Create
+      (THex.Decode(TSpeckTestVectors.FSpeck128BlockCipherVectorKeys[I]))
+      as IKeyParameter, TSpeckTestVectors.FSpeck128BlockCipherVectorInputs[I],
+      TSpeckTestVectors.FSpeck128BlockCipherVectorOutputs[I]);
+  end;
+
+end;
+
 initialization
 initialization
 
 
 // Register any test cases with the test runner
 // Register any test cases with the test runner

+ 369 - 0
CryptoLib.Tests/src/Crypto/SPECKTests.pas

@@ -0,0 +1,369 @@
+{ *********************************************************************************** }
+{ *                              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 SPECKTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  SpeckTestVectors,
+  ClpSpeckEngine,
+  ClpISpeckEngine,
+  ClpIKeyParameter,
+  ClpKeyParameter,
+  ClpParametersWithIV,
+  ClpIParametersWithIV,
+  ClpIBufferedCipher,
+  ClpICipherKeyGenerator,
+  ClpICipherParameters,
+  ClpBlockCipherModes,
+  ClpIBlockCipherModes,
+  ClpIBlockCipher,
+  ClpBufferedBlockCipher,
+  ClpIBufferedBlockCipher,
+  ClpEncoders,
+  ClpArrayUtils,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  TTestSPECK = class(TCryptoLibTestCase)
+  private
+
+    procedure doSPECKTest(const cipher: IBufferedCipher;
+      const param: ICipherParameters; const input, output: String;
+      withpadding: Boolean = False);
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    procedure TestSPECK64_CBC_NOPADDING_WITH_IV;
+    procedure TestSPECK128_CBC_NOPADDING_WITH_IV;
+    procedure TestSPECK64_CTR_NOPADDING_WITH_IV;
+    procedure TestSPECK128_CTR_NOPADDING_WITH_IV;
+    procedure TestSPECK64_ECB_NOPADDING_NO_IV;
+    procedure TestSPECK128_ECB_NOPADDING_NO_IV;
+
+  end;
+
+implementation
+
+{ TTestSPECK }
+
+procedure TTestSPECK.doSPECKTest(const cipher: IBufferedCipher;
+  const param: ICipherParameters; const input, output: String;
+  withpadding: Boolean);
+var
+  LInput, LOutput, EncryptionResult, DecryptionResult: TBytes;
+  // len1, len2: Int32;
+begin
+  LInput := THex.Decode(input);
+  LOutput := THex.Decode(output);
+
+  cipher.Init(True, param);
+
+  // Encryption
+  // Single Pass
+  EncryptionResult := cipher.DoFinal(LInput);
+
+  { *
+    // Multi Pass
+    System.SetLength(EncryptionResult,
+    cipher.GetOutputSize(System.Length(LInput)));
+
+    len1 := cipher.ProcessBytes(LInput, 0, System.Length(LInput),
+    EncryptionResult, 0);
+
+    len1 := len1 + cipher.DoFinal(EncryptionResult, len1);
+    * }
+
+  if not withpadding then
+  begin
+    if (not TArrayUtils.AreEqual(LOutput, EncryptionResult)) then
+    begin
+      Fail(Format('Encryption Failed - Expected %s but got %s',
+        [THex.Encode(LOutput), THex.Encode(EncryptionResult)]));
+    end;
+  end;
+
+  cipher.Init(False, param);
+
+  // Decryption
+  // Single Pass
+  DecryptionResult := cipher.DoFinal(EncryptionResult);
+  { *
+    // Multi Pass
+    System.SetLength(DecryptionResult,
+    cipher.GetOutputSize(System.Length(EncryptionResult)));
+
+    len2 := cipher.ProcessBytes(EncryptionResult, 0,
+    System.Length(EncryptionResult), DecryptionResult, 0);
+
+    len2 := len2 + cipher.DoFinal(DecryptionResult, len2);
+
+    // remove padding important!!!
+    System.SetLength(DecryptionResult, len2);
+    * }
+
+  if (not TArrayUtils.AreEqual(LInput, DecryptionResult)) then
+  begin
+    Fail(Format('Decryption Failed - Expected %s but got %s',
+      [THex.Encode(LInput), THex.Encode(DecryptionResult)]));
+  end;
+end;
+
+procedure TTestSPECK.SetUp;
+begin
+  inherited;
+end;
+
+procedure TTestSPECK.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestSPECK.TestSPECK64_CBC_NOPADDING_WITH_IV;
+var
+  KeyParametersWithIV: IParametersWithIV;
+  keyBytes, IVBytes: TBytes;
+  cipher: IBufferedCipher;
+  input, output: string;
+  i: Int32;
+  engine: ISpeckEngine;
+  blockCipher: ICbcBlockCipher;
+begin
+
+  // // Set up
+  engine := TSpeck64Engine.Create();
+  blockCipher := TCbcBlockCipher.Create(engine); // CBC no padding
+  cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
+
+  for i := System.Low(TSPECKTestVectors.FCryptoPPVectorKeys_SPECK64_CBC)
+    to System.High(TSPECKTestVectors.FCryptoPPVectorKeys_SPECK64_CBC) do
+  begin
+    keyBytes := THex.Decode
+      (TSPECKTestVectors.FCryptoPPVectorKeys_SPECK64_CBC[i]);
+    IVBytes := THex.Decode(TSPECKTestVectors.FCryptoPPVectorIVs_SPECK64_CBC[i]);
+    input := TSPECKTestVectors.FCryptoPPVectorInputs_SPECK64_CBC[i];
+    output := TSPECKTestVectors.FCryptoPPVectorOutputs_SPECK64_CBC[i];
+
+    KeyParametersWithIV := TParametersWithIV.Create
+      (TKeyParameter.Create(keyBytes) as IKeyParameter, IVBytes);
+
+    doSPECKTest(cipher, KeyParametersWithIV as ICipherParameters,
+      input, output);
+  end;
+
+end;
+
+procedure TTestSPECK.TestSPECK128_CBC_NOPADDING_WITH_IV;
+var
+  KeyParametersWithIV: IParametersWithIV;
+  keyBytes, IVBytes: TBytes;
+  cipher: IBufferedCipher;
+  input, output: string;
+  i: Int32;
+  engine: ISpeckEngine;
+  blockCipher: ICbcBlockCipher;
+begin
+
+  // // Set up
+  engine := TSpeck128Engine.Create();
+  blockCipher := TCbcBlockCipher.Create(engine); // CBC no padding
+  cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
+
+  for i := System.Low(TSPECKTestVectors.FCryptoPPVectorKeys_SPECK128_CBC)
+    to System.High(TSPECKTestVectors.FCryptoPPVectorKeys_SPECK128_CBC) do
+  begin
+    keyBytes := THex.Decode
+      (TSPECKTestVectors.FCryptoPPVectorKeys_SPECK128_CBC[i]);
+    IVBytes := THex.Decode
+      (TSPECKTestVectors.FCryptoPPVectorIVs_SPECK128_CBC[i]);
+    input := TSPECKTestVectors.FCryptoPPVectorInputs_SPECK128_CBC[i];
+    output := TSPECKTestVectors.FCryptoPPVectorOutputs_SPECK128_CBC[i];
+
+    KeyParametersWithIV := TParametersWithIV.Create
+      (TKeyParameter.Create(keyBytes) as IKeyParameter, IVBytes);
+
+    doSPECKTest(cipher, KeyParametersWithIV as ICipherParameters,
+      input, output);
+  end;
+
+end;
+
+procedure TTestSPECK.TestSPECK64_CTR_NOPADDING_WITH_IV;
+var
+  KeyParametersWithIV: IParametersWithIV;
+  keyBytes, IVBytes: TBytes;
+  cipher: IBufferedCipher;
+  input, output: string;
+  i: Int32;
+  engine: ISpeckEngine;
+  blockCipher: ISicBlockCipher;
+begin
+
+  // // Set up
+  engine := TSpeck64Engine.Create();
+  blockCipher := TSicBlockCipher.Create(engine); // CTR no padding
+  cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
+
+  for i := System.Low(TSPECKTestVectors.FCryptoPPVectorKeys_SPECK64_CTR)
+    to System.High(TSPECKTestVectors.FCryptoPPVectorKeys_SPECK64_CTR) do
+  begin
+    keyBytes := THex.Decode
+      (TSPECKTestVectors.FCryptoPPVectorKeys_SPECK64_CTR[i]);
+    IVBytes := THex.Decode(TSPECKTestVectors.FCryptoPPVectorIVs_SPECK64_CTR[i]);
+    input := TSPECKTestVectors.FCryptoPPVectorInputs_SPECK64_CTR[i];
+    output := TSPECKTestVectors.FCryptoPPVectorOutputs_SPECK64_CTR[i];
+
+    KeyParametersWithIV := TParametersWithIV.Create
+      (TKeyParameter.Create(keyBytes) as IKeyParameter, IVBytes);
+
+    doSPECKTest(cipher, KeyParametersWithIV as ICipherParameters,
+      input, output);
+  end;
+
+end;
+
+procedure TTestSPECK.TestSPECK128_CTR_NOPADDING_WITH_IV;
+var
+  KeyParametersWithIV: IParametersWithIV;
+  keyBytes, IVBytes: TBytes;
+  cipher: IBufferedCipher;
+  input, output: string;
+  i: Int32;
+  engine: ISpeckEngine;
+  blockCipher: ISicBlockCipher;
+begin
+
+  // // Set up
+  engine := TSpeck128Engine.Create();
+  blockCipher := TSicBlockCipher.Create(engine); // CTR no padding
+  cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
+
+  for i := System.Low(TSPECKTestVectors.FCryptoPPVectorKeys_SPECK128_CTR)
+    to System.High(TSPECKTestVectors.FCryptoPPVectorKeys_SPECK128_CTR) do
+  begin
+    keyBytes := THex.Decode
+      (TSPECKTestVectors.FCryptoPPVectorKeys_SPECK128_CTR[i]);
+    IVBytes := THex.Decode
+      (TSPECKTestVectors.FCryptoPPVectorIVs_SPECK128_CTR[i]);
+    input := TSPECKTestVectors.FCryptoPPVectorInputs_SPECK128_CTR[i];
+    output := TSPECKTestVectors.FCryptoPPVectorOutputs_SPECK128_CTR[i];
+
+    KeyParametersWithIV := TParametersWithIV.Create
+      (TKeyParameter.Create(keyBytes) as IKeyParameter, IVBytes);
+
+    doSPECKTest(cipher, KeyParametersWithIV as ICipherParameters,
+      input, output);
+  end;
+
+end;
+
+procedure TTestSPECK.TestSPECK64_ECB_NOPADDING_NO_IV;
+var
+  keyParameter: IKeyParameter;
+  keyBytes: TBytes;
+  cipher: IBufferedCipher;
+  input, output: string;
+  i: Int32;
+  engine: ISpeckEngine;
+  blockCipher: IBlockCipher;
+begin
+
+  // // Set up
+  engine := TSpeck64Engine.Create();
+  blockCipher := engine as IBlockCipher; // ECB no padding
+  cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
+
+  for i := System.Low(TSPECKTestVectors.FCryptoPPVectorKeys_SPECK64_ECB)
+    to System.High(TSPECKTestVectors.FCryptoPPVectorKeys_SPECK64_ECB) do
+  begin
+    keyBytes := THex.Decode
+      (TSPECKTestVectors.FCryptoPPVectorKeys_SPECK64_ECB[i]);
+    input := TSPECKTestVectors.FCryptoPPVectorInputs_SPECK64_ECB[i];
+    output := TSPECKTestVectors.FCryptoPPVectorOutputs_SPECK64_ECB[i];
+
+    keyParameter := TKeyParameter.Create(keyBytes);
+
+    doSPECKTest(cipher, keyParameter as ICipherParameters, input, output);
+  end;
+
+end;
+
+procedure TTestSPECK.TestSPECK128_ECB_NOPADDING_NO_IV;
+var
+  keyParameter: IKeyParameter;
+  keyBytes: TBytes;
+  cipher: IBufferedCipher;
+  input, output: string;
+  i: Int32;
+  engine: ISpeckEngine;
+  blockCipher: IBlockCipher;
+begin
+
+  // // Set up
+  engine := TSpeck128Engine.Create();
+  blockCipher := engine as IBlockCipher; // ECB no padding
+  cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
+
+  for i := System.Low(TSPECKTestVectors.FCryptoPPVectorKeys_SPECK128_ECB)
+    to System.High(TSPECKTestVectors.FCryptoPPVectorKeys_SPECK128_ECB) do
+  begin
+    keyBytes := THex.Decode
+      (TSPECKTestVectors.FCryptoPPVectorKeys_SPECK128_ECB[i]);
+    input := TSPECKTestVectors.FCryptoPPVectorInputs_SPECK128_ECB[i];
+    output := TSPECKTestVectors.FCryptoPPVectorOutputs_SPECK128_ECB[i];
+
+    keyParameter := TKeyParameter.Create(keyBytes);
+
+    doSPECKTest(cipher, keyParameter as ICipherParameters, input, output);
+  end;
+
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestSPECK);
+{$ELSE}
+  RegisterTest(TTestSPECK.Suite);
+{$ENDIF FPC}
+
+end.

+ 252 - 0
CryptoLib.Tests/src/Crypto/SpeckTestVectors.pas

@@ -0,0 +1,252 @@
+{ *********************************************************************************** }
+{ *                              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 SpeckTestVectors;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  ClpCryptoLibTypes;
+
+type
+  /// <summary>
+  /// Speck tester
+  /// </summary>
+  /// <remarks>
+  /// test vectors were gotten from <see href="https://eprint.iacr.org/2013/404.pdf" />
+  /// , <br /><see href="https://nsacyber.github.io/simon-speck/implementations/ImplementationGuide1.1.pdf" />
+  /// and
+  /// https://github.com/weidai11/cryptopp/blob/master/TestVectors/speck.txt <br />
+  /// (do note that the tests vector in the first link are given in big
+  /// endian order) <br />and were swapped to little endian here
+  /// </remarks>
+  TSpeckTestVectors = class sealed(TObject)
+
+  public
+    class var
+
+      FSpeck32BlockCipherVectorKeys, FSpeck32BlockCipherVectorInputs,
+      FSpeck32BlockCipherVectorOutputs,
+
+      FSpeck48BlockCipherVectorKeys, FSpeck48BlockCipherVectorInputs,
+      FSpeck48BlockCipherVectorOutputs,
+
+      FSpeck64BlockCipherVectorKeys, FSpeck64BlockCipherVectorInputs,
+      FSpeck64BlockCipherVectorOutputs,
+
+      FSpeck96BlockCipherVectorKeys, FSpeck96BlockCipherVectorInputs,
+      FSpeck96BlockCipherVectorOutputs,
+
+      FSpeck128BlockCipherVectorKeys, FSpeck128BlockCipherVectorInputs,
+      FSpeck128BlockCipherVectorOutputs,
+
+      FCryptoPPVectorKeys_SPECK64_ECB, FCryptoPPVectorInputs_SPECK64_ECB,
+      FCryptoPPVectorOutputs_SPECK64_ECB,
+
+      FCryptoPPVectorKeys_SPECK128_ECB, FCryptoPPVectorInputs_SPECK128_ECB,
+      FCryptoPPVectorOutputs_SPECK128_ECB,
+
+      FCryptoPPVectorKeys_SPECK64_CBC, FCryptoPPVectorIVs_SPECK64_CBC,
+      FCryptoPPVectorInputs_SPECK64_CBC, FCryptoPPVectorOutputs_SPECK64_CBC,
+
+      FCryptoPPVectorKeys_SPECK128_CBC, FCryptoPPVectorIVs_SPECK128_CBC,
+      FCryptoPPVectorInputs_SPECK128_CBC, FCryptoPPVectorOutputs_SPECK128_CBC,
+
+      FCryptoPPVectorKeys_SPECK64_CTR, FCryptoPPVectorIVs_SPECK64_CTR,
+      FCryptoPPVectorInputs_SPECK64_CTR, FCryptoPPVectorOutputs_SPECK64_CTR,
+
+      FCryptoPPVectorKeys_SPECK128_CTR, FCryptoPPVectorIVs_SPECK128_CTR,
+      FCryptoPPVectorInputs_SPECK128_CTR, FCryptoPPVectorOutputs_SPECK128_CTR
+
+      : TCryptoLibStringArray;
+
+    class constructor SpeckTestVectors();
+
+  end;
+
+implementation
+
+{ TSpeckTestVectors }
+
+class constructor TSpeckTestVectors.SpeckTestVectors;
+begin
+
+  FSpeck32BlockCipherVectorKeys := TCryptoLibStringArray.Create
+    ('0001080910111819');
+
+  FSpeck32BlockCipherVectorInputs := TCryptoLibStringArray.Create('4C697465');
+
+  FSpeck32BlockCipherVectorOutputs := TCryptoLibStringArray.Create('F24268A8');
+
+  FSpeck48BlockCipherVectorKeys := TCryptoLibStringArray.Create
+    ('00010208090A101112', '00010208090A101112', '00010208090A10111218191A');
+
+  FSpeck48BlockCipherVectorInputs := TCryptoLibStringArray.Create
+    ('72616C6C7920', '72616C6C7920', '74686973206D');
+
+  FSpeck48BlockCipherVectorOutputs := TCryptoLibStringArray.Create
+    ('DC5A38A549C0', 'DC5A38A549C0', '5D44B6105E73');
+
+  FSpeck64BlockCipherVectorKeys := TCryptoLibStringArray.Create
+    ('0001020308090A0B10111213', '0001020308090A0B1011121318191A1B');
+
+  FSpeck64BlockCipherVectorInputs := TCryptoLibStringArray.Create
+    ('65616E7320466174', '2D4375747465723B');
+
+  FSpeck64BlockCipherVectorOutputs := TCryptoLibStringArray.Create
+    ('6C947541EC52799F', '8B024E4548A56F8C');
+
+  FSpeck96BlockCipherVectorKeys := TCryptoLibStringArray.Create
+    ('00010203040508090A0B0C0D', '00010203040508090A0B0C0D101112131415');
+
+  FSpeck96BlockCipherVectorInputs := TCryptoLibStringArray.Create
+    ('2075736167652C20686F7765', '7665722C20696E2074696D65');
+
+  FSpeck96BlockCipherVectorOutputs := TCryptoLibStringArray.Create
+    ('AA798FDEBD627871AB094D9E', 'E62E2540E47A8A227210F32B');
+
+  FSpeck128BlockCipherVectorKeys := TCryptoLibStringArray.Create
+    ('000102030405060708090A0B0C0D0E0F',
+    '000102030405060708090A0B0C0D0E0F1011121314151617',
+    '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F');
+
+  FSpeck128BlockCipherVectorInputs := TCryptoLibStringArray.Create
+    ('206D616465206974206571756976616C', '656E7420746F20436869656620486172',
+    '706F6F6E65722E20496E2074686F7365');
+
+  FSpeck128BlockCipherVectorOutputs := TCryptoLibStringArray.Create
+    ('180D575CDFFE60786532787951985DA6', '86183CE05D18BCF9665513133ACFE41B',
+    '438F189C8DB4EE4E3EF5C00504010941');
+
+  // https://github.com/weidai11/cryptopp/blob/master/TestVectors/speck.txt
+
+  // ====================================================================================== //
+
+  FCryptoPPVectorKeys_SPECK64_ECB := TCryptoLibStringArray.Create
+    ('F64F824BDA9DA2D0D446ABE3', '64B76FA61CE980AB2F71098D75D66E5F');
+  FCryptoPPVectorInputs_SPECK64_ECB := TCryptoLibStringArray.Create
+    ('48731C8BFE3260D4', '1589A8BBFF4C7A85');
+  FCryptoPPVectorOutputs_SPECK64_ECB := TCryptoLibStringArray.Create
+    ('55CABA8DE9F967C8', '2F1D122370946BDA');
+
+  // ====================================================================================== //
+
+  FCryptoPPVectorKeys_SPECK128_ECB := TCryptoLibStringArray.Create
+    ('75289E33D18BDFC9C689B29A43CBF3F2',
+    'C289F537364FF63CB37FD75FEFB7C64D9D0997CD230B0BA2',
+    '3FAD1C9A616C155D42A077C2458E6BBA12C340F1475EA1F1624F8636FFB14ECC');
+  FCryptoPPVectorInputs_SPECK128_ECB := TCryptoLibStringArray.Create
+    ('51C16CD9AFAB4F1D326658F89C06C940', '0FF691D4E981FEFFC226BB85C2793B45',
+    '83A3C8AC4655B7B09FD2E6372F67D80B');
+  FCryptoPPVectorOutputs_SPECK128_ECB := TCryptoLibStringArray.Create
+    ('C003C0497684789B3A6CCBE8E7F98D9E', 'A757BDA6BAFD5356AE0693B89E4124F9',
+    'C1666B5CEFC7A834AA8E17151325D89C');
+
+  // ====================================================================================== //
+
+  FCryptoPPVectorKeys_SPECK64_CBC := TCryptoLibStringArray.Create
+    ('87A6829C1FDAAB90AC8AFC52', 'CA4345F53BE6D8F371D91C334FC0838B');
+
+  FCryptoPPVectorIVs_SPECK64_CBC := TCryptoLibStringArray.Create
+    ('869AF558D633F02D', '51A3A8DE472EF740');
+
+  FCryptoPPVectorInputs_SPECK64_CBC := TCryptoLibStringArray.Create
+    ('2DE1856588CAC5A3225A1048A6C9C98E7B6E1E80DF1DD431AC075133555F1091B075AAE0D05C057249D0032D78DE2CD74F1BB05AE8C38347088C1207D3EF53890F35F0FA99BBDB10F17DB0F8E7AFD03E40DD31E2B4330CAFE1C329930096CEEA',
+    '8A46B92E16B50EA93080F6801A0F77D7B1C7A11E8F212D036EDC6AB5E30ADE3B6A980C36FD40A62EB868F42B8CFB5907EBDA51F1C9D394DB691A326FA0DB093B632FEE98C106207AEFC6E26DC14724AD7684E2D54F7C3417A1BF438224B23FF1');
+
+  FCryptoPPVectorOutputs_SPECK64_CBC := TCryptoLibStringArray.Create
+    ('570D66C5A24534BF916C25B7F1093A0555C54857A11FDBCE549E3CFA0E65307F46B3796025925E55DD53D4419E5651A6B4D615DCB34EF4AADF7CA9AE4B0B266BCB2DBB78F933028E655F9F00820A8B32C27CB7481C071C012B54DCFB1FBFDB62',
+    'F2475EFA5C2F3BB9D4D16DFF5E3A3D16679C265660F6ABD2C4FC73B84806127ADDFAACC45E968770C747E2D6D66CF1AA37C96637DED14E439DA5F99778F4BA226592DFEDFE7EAB84D9B3665F71A6F9CC6E3AD6C8CCA1DB91D0F4F8BC572ED873');
+
+  // ====================================================================================== //
+
+  FCryptoPPVectorKeys_SPECK128_CBC := TCryptoLibStringArray.Create
+    ('84B6C2745A7515168E794BC312949733',
+    '52EB87E80BC7BE50A0F2C823BFC1D1478540010A1E61BA1E',
+    '4FFE6ED614F3662199AB5B77C01FFEFFF6F2A2928486F2CBD0AA0555E28837E9');
+
+  FCryptoPPVectorIVs_SPECK128_CBC := TCryptoLibStringArray.Create
+    ('89B996EC3A2030EEAB18E777A4A826F4', '817111309CF0E5FDD3D29A87F24A3D42',
+    '2A6421928921E1A364798D330D22E4C3');
+
+  FCryptoPPVectorInputs_SPECK128_CBC := TCryptoLibStringArray.Create
+    ('E99CEF37FA72BB342275090D36460E599982535234C52780FA11AE65F36208B82D9C439183DBF93CB1EC5E7'
+    + 'B14EA3707C6C5A4C12F9942C43C24D0FE1BB17BC473137E3E55B7687113A71DDFF47623B29B5431656976E8BE845FA2676F4B5073D980BE0BC45216299B8D8A2026E21B6C4737F3601196307D82F986D0D44808951172A160B4EE2D'
+    + 'CA04C4EAE7D5BB53BA0929C990AA706495BDEF15DD989C1460CB821FEDB14EFBEB6CEF223B4BA00F6FCB775B79EBD4F2FCDC570057045B9956',
+    'B3DACAA4EE7C1AE96BF563F9EEAE8C32A47A2CC10F9D1F06CFDC1BC5AC57BF425F4D2816A4517035DBEB9A43E6EE7BBF592B861BB04077AD784B19'
+    + '049B6E25D8E85182053B0C89695B3F49CA874CA37F263E004862FFC178B82E7844B13AE98E3E7E4DE517BF00F89316C54CECA154A9A618C4CECA7D0F5423A459335B6758AE2D0134526791EEC3A1730B055C3D6A8A96422A37'
+    + 'DF32F910365B319FED76591EA32865920A4357BFF6B3DED6DEB9A453F8A4FFE66AE621159F40DE5170F94EAC',
+    '05DE17F97F9DC2DF3BA5858D161B21255C539BC715A55D8CD09BAE727920CB5744CDA1B7C962B13B4263F0D67B65ACFA84D6CBEB95B187032F5887D4DB0A'
+    + '509E14FF4373546BE2B4071B78387EB6922591E2F276E8FABE4E3BCC444D036EC400C9980F45D09F79D5DA9FF01A9B1950874013BC855BAB6F922030DA96FB4822A3887401C50DCB6AA56B44C06CD43EBA843ED339B'
+    + '91991E791B956752EF773D5B359E988C7CA4AF92DAA14E046DFB3DE5220EC3884C786B8443574211A4970FA78');
+  FCryptoPPVectorOutputs_SPECK128_CBC := TCryptoLibStringArray.Create
+    ('88E166E1D46064E47187F9854A19570223E96BE0EE13D890E0209B66F0E45808F9B60513D90EAC2F0C1BF8A'
+    + '55EF2B637B72597D9B9B3107FD42FD86AC9EE58D983C334F938FDC7E50DE292AC030FF3C68B6C5F5DA298DAB7438F322B8E4F003CE5310BC88074E98D9C38045D40C956909F766774CE00C30BBE2D7DDDDC94C96D9FA252EB5EB514'
+    + 'D066D8DB995526F402389057C2310F64B26BF936C902D7B4F4E4E9D9DFB4294DFFB81BC3A524EFD7A80317E8F812E940137172F6DA27B4C01D',
+    '73024FB7D9931CFC64738C1B46417089226FA3E1ACAC0FBDE253B8C46673AB61142C76CC8F965762113384C462793FC01F7B8FE04EB42D9276E25F7C'
+    + 'CB4DEAED845CCA1F14EE034628E917EC7B95D658E00B1DED8F2E0D44BEBEF62B5BBAD9E3872BB5600842991918F6DC8D8E2D96CEA85743270BC7DF4A0363E65959794910A3EB9689A8DF'
+    + '5AB314A26B31B60AA63EFD57AD5FFBBAA793996B71841F468F99B485CB0CEEE6D10130BEB091A4D55206577A354768E5B8A044C6BE7C992EB0EF',
+    '21BA4DF8F5BC068B530800358033A3B976098B304E8CCAA264F9BB3FB5E0BDB5C888E6BB9AC6508B8F56798DBACDCBFE963AB5172E4A4FC2FD160CFD378A597E6F1E8FE0'
+    + 'DCEA6BA0B06142BA49FFDCF05F1E9D02D06E71B1FAD3E8A6E8B14C65AD24973B5739D076EBAD7E4ED9ECF9E360CA32E41066A5E669DF888F49803F55FD7097'
+    + 'ED4D182552F71720E77A416046A81C71A53E3F6DD8FBEAB1D9F5F4146E4E2E4F0A344A740F8091135B1CF6C04B3B00B6E557F0F8078894483242DC165B');
+
+  // ====================================================================================== //
+
+  FCryptoPPVectorKeys_SPECK64_CTR := TCryptoLibStringArray.Create
+    ('C72CBD543750780FBCD5CB64', 'D0F15E55870DD39236C0251C438F57B4');
+  FCryptoPPVectorIVs_SPECK64_CTR := TCryptoLibStringArray.Create
+    ('E4FE17997B0F8028', '6942E2B8C46D5374');
+  FCryptoPPVectorInputs_SPECK64_CTR := TCryptoLibStringArray.Create
+    ('2F75D63915E9E524D98DF7F6F5B32FFBE4B7F911F3CEC758FF265FB1B202C78A7F5353E508F23D84D6FFF2CA54AC649BF583A4098876A52EF54341F581AF8C2C2E5AF8734B7535B854295C0BB3A20B7382650F6262D33DC40403B79482A71437',
+    'A71E62DCF454EEC5A1ED766C45B7B67AB82E5019AD8DB7F4AA0A53730AA301C11441908D4290643E71FF39E3666934A317912C68DF01E137E28A6047F7E12F5766D01E2016408AE554B63EA66DBF87AEBD1BCE95ADA845634E6D33D90E10E60E');
+  FCryptoPPVectorOutputs_SPECK64_CTR := TCryptoLibStringArray.Create
+    ('AB692394FB3A7B7D4A356673075C947E04EE4CA1DC025EAEF950FF24527DE9E72DC4B3BE5E0C82A7964A64AE9820451910F448026C43FA0886A095E2277D484E90CFB960AA43023C958863D8741333AB3CB25B2BC4778DCFEAFA89C9DC6285E6',
+    '309D96C038FD03AA85815D6EF445344037980EACD6B61BCDD7F74FF8207F0F0533AF40AB822F480DB08C9729CF59BF2D3EF4192EBA1087BCBC112B46EA4D512AF2FA8FFCE2824C316D401771A25BF98E842BDA8120039AE2049733B329A189DA');
+
+  // ====================================================================================== //
+
+  FCryptoPPVectorKeys_SPECK128_CTR := TCryptoLibStringArray.Create
+    ('B043F5B45E8256956AFC4E26B4861240',
+    '691EC1C805EFBD7A9D509F226D2331D20771EE79BDDFCAFC',
+    'EB78929D56C5D0F49F75C1C8694AFDA496F808E5524CC592FD980EEC363E5382');
+  FCryptoPPVectorIVs_SPECK128_CTR := TCryptoLibStringArray.Create
+    ('E0BEDD6ECE0D72FC19D59E7BF853AEEC', '348ECA9766C09F04826520DE47A212FA',
+    'AF322427139F48ECD9C779FB768B28C0');
+  FCryptoPPVectorInputs_SPECK128_CTR := TCryptoLibStringArray.Create
+    ('4CB83714C34CA56DE8FB06069F794A5189F468191552CF8F5C46A07960BAC354C2D73359B01BF1508213ABF986ACA73E413566129134A6DAAAF54A45F7CFFE63E476B6EF237FA1FB0878F30338A18D29B91E204F37FC504A'
+    + '4908103AE843CDB05FACE5CC5EBD85D603F187CC4245D18D78036B81F8980A86A333418D7F81C75214D30555368B5D11A56AE732B291003128181F8364EA2C3D1C333C7615EFF41078E9CC8C69BB87BCE5EB8630E9B2E261758DF6693730E3C5F5C8F4F9F992D886',
+    '8BF93C7DFA63CF6D78842FD7458A6CB17184F75ECBE1DC0BE9F32DAC0E8F28D5152FE7351A46A402AE019C38BA55B2EF6C00DEAF4BF721A8C6C15434E466CBAEFA643BCCFEB4F2FAA5CE9178DB83DDE37A2F388ED9FFFB91DF4E2F16D84D9B03A122ACD1745FF2E3568C4F535689FEB99A30985EAD5BEF39A0'
+    + '730B569326FB23435CCE3696A8CD42C6D8C57A04134ADE9A68D927A16890CBD245A2FDF4E194550692A75A196780140AEBA98E800BE9851EDE654D4AB8EE31FADB1815CB66BCA8',
+    '5DCC0F8301F377741D8517CD6DA27D1E8170109C361FC68D8E5022CE3DA1C8FBDD37F50A7DCB5BB1A059D7CF100A94EAB59ECE9260072B64B746FD9ED93F49F0C654CD5DFD321E4D8959CBD1095FE2B5D4ACC78474AC2232EC34ECA0737F8886E156866C279C679CBAF544E7F69E3E8C710DE732C1F8FEEDF20773C6A'
+    + '674D706BF7EF2B5AD9C3D7B00A734E0919F181B59FBC8CFCEA4BEE9525894814CE42122E3AD0F07C0AD56E899D780C5D1759312351057C15F550C965379BADFC728E8F3');
+  FCryptoPPVectorOutputs_SPECK128_CTR := TCryptoLibStringArray.Create
+    ('A17264CC79FB96348E22E42F8FA8DCB43E9415AEF3552A673D5BF27B81E810F15923578D0B5CA148B183FB51AEE2E23CE2CFE4820B91DF21A6C915B2268608A62960EE8802991546048BDB4C2B9461B55869335954EABBAF09F255FA'
+    + 'E862140E87AABBF497AE3578AD030FBC4CB87A5EE4DEEB114FA4DE64DA74CE1AEA41D9FC72962B26C1339E2593166E8D79E06EAE809A080D4197934298FBE3586A3235CA76A176E41DE1A0BEF47CD37F5DE36E79C78E20A2E6BD0DCFE27A5A71431A5983',
+    '8F1C06AD392094314A7C514FEE0BA31A4129325900789A5F0F5638F5114509F07C22C527B41831ECF67B25EDEB4A069481950B7BE611772129F7995011A1429CF26CB6E91E970D745958223DCB55D606A7D78C20F5866D532C7CE27A97D1DCBA43494948C969820117DA62B83F421270BC90997F0ABC27099AAA9610FF44C48'
+    + 'BD701EB20DEA3008164097783E6006010AE26486D46726E0507E4C8F3F9448EC29642AD71A05B60A1386E39B81E747B64C8B39F73E27208B1EA3BC075223804AA',
+    '46DDAF62B84BDB9B97E2C114417AA5BD126132D922FA7B2C8B25A0D3147C9C1B203F06C546A7DAE20E98BC95AC6CB124C0E7C51566B5D1061EE61E25405E51CD6EB848C673E21BC10F9B9DCC36DDC16281F1369D9DFAABDB43C50C7CE10BF9805596D8C3CA530810C1BE9EBDCC0950BDA5A0CEB196B8E81CD1678094'
+    + '81E61E46B7748C8B88D7169352C41761C0536286A61619BBB841E19EA7867DE51DAAD87080C317A4B269AE8D5BD6087E61BF9EE765DC69619E87FBC1AB1E26EA9CF9EA42');
+
+  // ====================================================================================== //
+
+end;
+
+end.

+ 1090 - 0
CryptoLib/src/Crypto/Engines/ClpSpeckEngine.pas

@@ -0,0 +1,1090 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSpeckEngine;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpCheck,
+  ClpISpeckEngine,
+  ClpIBlockCipher,
+  ClpICipherParameters,
+  ClpIKeyParameter,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SSpeckEngineNotInitialised = '%s Engine not Initialised';
+  SInputBuffertooShort = 'Input Buffer too Short';
+  SOutputBuffertooShort = 'Output Buffer too Short';
+  SInvalidArgumentEncountered = 'Invalid Argument Encountered.';
+  SInvalidParameterSpeckInit = 'Invalid Parameter Passed to Speck Init - "%s"';
+  SSpeck32InvalidKeySize =
+    'Speck32 requires a key of 64 bits but input was "%d" bits.';
+  SSpeck48InvalidKeySize =
+    'Speck48 requires a key of 72 or 96 bits but input was "%d" bits.';
+  SSpeck64InvalidKeySize =
+    'Speck64 requires a key of 96 or 128 bits but input was "%d" bits.';
+  SSpeck96InvalidKeySize =
+    'Speck96 requires a key of 96 or 144 bits but input was "%d" bits.';
+  SSpeck128InvalidKeySize =
+    'Speck128 requires a key of 128, 192 or 256 bits but input was "%d" bits.';
+
+type
+
+  /// <summary>
+  /// <para>
+  /// The Speck family of block ciphers, described in <i>The Simon and
+  /// Speck Families of Lightweight Block Ciphers</i> by <i>Ray Beaulieu,
+  /// Douglas Shors, Jason Smith, Stefan Treatman-Clark, Bryan Weeks,
+  /// Louis Wingers</i> All block size and key size variants are
+  /// supported, with the key size determined from the key during <see cref="ClpSpeckEngine|TSpeckEngine.Init(Boolean,ICipherParameters)" />
+  /// .
+  /// </para>
+  /// </summary>
+  TSpeckEngine = class abstract(TInterfacedObject, ISpeckEngine, IBlockCipher)
+
+  strict private
+  var
+
+    Finitialised, FforEncryption: Boolean;
+
+    function GetIsPartialBlockOkay: Boolean; virtual;
+
+    /// <summary>
+    /// Internal method to Initialise this cipher instance.
+    /// <code>true</code> for encryption, <code>false</code> for decryption.
+    /// the bytes of the key to use.
+    /// </summary>
+    procedure EngineInit(forEncryption: Boolean;
+      const keyBytes: TCryptoLibByteArray); virtual;
+
+  strict protected
+
+  var
+    FblockSize, FwordSize, FwordSizeBits, Falpha, Fbeta, FbaseRounds,
+      Frounds: Int32;
+
+    /// <summary>
+    /// Gets the algorithm name of this Speck engine.
+    /// </summary>
+    /// <value>
+    /// the name of the Speck variant, specified to the level of the block size (e.g.
+    /// <em>Speck96</em>).
+    /// </value>
+    function GetAlgorithmName: String; virtual;
+    function GetBlockSize(): Int32; virtual;
+
+    /// <summary>
+    /// Checks whether a key size provided to the <see cref="ClpSpeckEngine|TSpeckEngine.EngineInit(Boolean,TCryptoLibByteArray)" />
+    /// method is valid.
+    /// </summary>
+    procedure CheckKeySize(keySizeBytes: Int32); virtual; abstract;
+
+    /// <summary>
+    /// Sets a key for this cipher instance, calculating the key schedule.
+    /// </summary>
+    procedure SetKey(const keyBytes: TCryptoLibByteArray); virtual; abstract;
+
+    /// <summary>
+    /// Unpack a block of data into working state prior to an
+    /// encrypt/decrypt operation.
+    /// </summary>
+    /// <param name="bytes">
+    /// the input data.
+    /// </param>
+    /// <param name="off">
+    /// the offset to begin reading the input data at.
+    /// </param>
+    procedure UnPackBlock(const bytes: TCryptoLibByteArray; off: Int32);
+      virtual; abstract;
+
+    /// <summary>
+    /// Packs the 2 word working state following an encrypt/decrypt into a
+    /// byte sequence.
+    /// </summary>
+    /// <param name="bytes">
+    /// the output buffer.
+    /// </param>
+    /// <param name="off">
+    /// the offset to begin writing the output data at.
+    /// </param>
+    procedure PackBlock(const bytes: TCryptoLibByteArray; off: Int32);
+      virtual; abstract;
+
+    /// <summary>
+    /// Encrypts the plaintext words loaded with a previous call to <see cref="ClpSpeckEngine|TSpeckEngine.UnPackBlock(TCryptoLibByteArray,Int32)" />
+    /// leaving the resulting ciphertext words in the working state.
+    /// </summary>
+    procedure EncryptBlock(); virtual; abstract;
+
+    /// <summary>
+    /// Decrypts the ciphertext words loaded with a previous call to <see cref="ClpSpeckEngine|TSpeckEngine.UnPackBlock(TCryptoLibByteArray,Int32)" />
+    /// leaving the resulting ciphertext words in the working state.
+    /// </summary>
+
+    procedure DecryptBlock(); virtual; abstract;
+
+    /// <summary>
+    /// Constructs a Speck engine.
+    /// </summary>
+    /// <param name="wordSize">
+    /// the size of the word to use, in bytes.
+    /// </param>
+    /// <param name="baseRounds">
+    /// the base number of rounds (for a 2 word key variant) for the
+    /// specified word/block size.
+    /// </param>
+    /// <param name="alpha">
+    /// the alpha rotation constant to use.
+    /// </param>
+    /// <param name="beta">
+    /// the beta rotation constant to use.
+    /// </param>
+    constructor Create(wordSize, baseRounds, alpha, beta: Int32);
+
+    /// <summary>
+    /// initialise a Speck 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="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;
+
+    property AlgorithmName: String read GetAlgorithmName;
+    property IsPartialBlockOkay: Boolean read GetIsPartialBlockOkay;
+
+  end;
+
+type
+
+  /// <summary>
+  /// Base class of Speck variants that fit in 32 bit Pascal Integers:
+  /// Speck32, Speck48, Speck64.
+  /// Speck32 and Speck48 (16 and 24 bit word sizes) are implemented using masking.
+  /// </summary>
+  TSpeckUInt32Engine = class abstract(TSpeckEngine)
+
+  strict private
+  var
+
+    /// <summary>
+    /// The expanded key schedule for all <see cref="ClpSpeckEngine|TSpeckEngine.Frounds" />
+    /// </summary>
+    Fk: TCryptoLibUInt32Array;
+
+    /// <summary>
+    /// The 2 words of the working state;
+    /// </summary>
+    Fx, Fy: UInt32;
+
+    /// <summary>
+    /// Rotates a word left by the specified distance. <br />The rotation is
+    /// on the word size of the cipher instance, not on the full 32 bits of
+    /// the UInt32.
+    /// </summary>
+    /// <param name="i">
+    /// the word to rotate.
+    /// </param>
+    /// <param name="distance">
+    /// the distance in bits to rotate.
+    /// </param>
+    /// <returns>
+    /// the rotated word, which may have unmasked high (&gt; word size) bits.
+    /// </returns>
+    function Rotl(i: UInt32; distance: Int32): UInt32; inline;
+
+    /// <summary>
+    /// Rotates a word right by the specified distance. <br />The rotation is
+    /// on the word size of the cipher instance, not on the full 32 bits of
+    /// the UInt32.
+    /// </summary>
+    /// <param name="i">
+    /// the word to rotate.
+    /// </param>
+    /// <param name="distance">
+    /// the distance in bits to rotate.
+    /// </param>
+    /// <returns>
+    /// the rotated word, which may have unmasked high (&gt; word size) bits.
+    /// </returns>
+    function Rotr(i: UInt32; distance: Int32): UInt32; inline;
+
+    /// <summary>
+    /// Read <see cref="ClpSpeckEngine|TSpeckEngine.FwordSize" /> bytes from
+    /// the input data in <b>little-endian</b> order.
+    /// </summary>
+    /// <param name="bytes">
+    /// the data to read a word from.
+    /// </param>
+    /// <param name="off">
+    /// the offset to read the word from.
+    /// </param>
+    /// <returns>
+    /// the read word, with zeroes in any bits higher than the word size.
+    /// </returns>
+    function BytesToWord(const bytes: TCryptoLibByteArray; off: Int32)
+      : UInt32; inline;
+
+    /// <summary>
+    /// Writes <see cref="ClpSpeckEngine|TSpeckEngine.FwordSize" /> bytes
+    /// into a buffer in <b>little-endian</b> order.
+    /// </summary>
+    /// <param name="word">
+    /// the word to write.
+    /// </param>
+    /// <param name="bytes">
+    /// the buffer to write the word bytes to.
+    /// </param>
+    /// <param name="off">
+    /// the offset to write the data at.
+    /// </param>
+    procedure WordToBytes(word: UInt32; const bytes: TCryptoLibByteArray;
+      off: Int32); inline;
+
+  strict protected
+
+    /// <summary>
+    /// Masks all bits higher than the word size of this cipher in the
+    /// supplied value.
+    /// </summary>
+    /// <param name="val">
+    /// the value to mask.
+    /// </param>
+    /// <returns>
+    /// the masked value.
+    /// </returns>
+    function Mask(val: UInt32): UInt32; virtual; abstract;
+
+    procedure SetKey(const keyBytes: TCryptoLibByteArray); override;
+
+    procedure UnPackBlock(const bytes: TCryptoLibByteArray;
+      off: Int32); override;
+
+    procedure PackBlock(const bytes: TCryptoLibByteArray; off: Int32); override;
+
+    procedure EncryptBlock(); override;
+
+    procedure DecryptBlock(); override;
+
+    /// <summary>
+    /// Constructs a Speck cipher with &lt;= 32 bit word size, using the
+    /// standard 8,3 rotation constants.
+    /// </summary>
+    /// <param name="wordSize">
+    /// the word size in bytes.
+    /// </param>
+    /// <param name="baseRounds">
+    /// the base (for 2 word key) round count.
+    /// </param>
+    constructor Create(wordSize, baseRounds: Int32); overload;
+
+    /// <summary>
+    /// Constructs a Speck cipher with &lt;= 32 bit word size, using custom
+    /// rotation constants.
+    /// </summary>
+    /// <param name="wordSize">
+    /// the word size in bytes.
+    /// </param>
+    /// <param name="baseRounds">
+    /// the base (for 2 word key) round count.
+    /// </param>
+    /// <param name="alpha">
+    /// the <em>alpha</em> rotation constant.
+    /// </param>
+    /// <param name="beta">
+    /// the <em>beta</em> rotation constant.
+    /// </param>
+    constructor Create(wordSize, baseRounds, alpha, beta: Int32); overload;
+
+  end;
+
+type
+
+  /// <summary>
+  /// Base class of Speck variants that fit in 64 bit Pascal Integers:
+  /// Speck96, Speck128.
+  /// Speck96 (48 bit word size) is implemented using masking.
+  /// </summary>
+  TSpeckUInt64Engine = class abstract(TSpeckEngine)
+
+  strict private
+  var
+
+    /// <summary>
+    /// The expanded key schedule for all <see cref="ClpSpeckEngine|TSpeckEngine.Frounds" />
+    /// </summary>
+    Fk: TCryptoLibUInt64Array;
+
+    /// <summary>
+    /// The 2 words of the working state;
+    /// </summary>
+    Fx, Fy: UInt64;
+
+    /// <summary>
+    /// Rotates a word left by the specified distance. <br />The rotation is
+    /// on the word size of the cipher instance, not on the full 64 bits of
+    /// the UInt64.
+    /// </summary>
+    /// <param name="i">
+    /// the word to rotate.
+    /// </param>
+    /// <param name="distance">
+    /// the distance in bits to rotate.
+    /// </param>
+    /// <returns>
+    /// the rotated word, which may have unmasked high (&gt; word size) bits.
+    /// </returns>
+    function Rotl(i: UInt64; distance: Int32): UInt64; inline;
+
+    /// <summary>
+    /// Rotates a word right by the specified distance. <br />The rotation is
+    /// on the word size of the cipher instance, not on the full 64 bits of
+    /// the UInt64.
+    /// </summary>
+    /// <param name="i">
+    /// the word to rotate.
+    /// </param>
+    /// <param name="distance">
+    /// the distance in bits to rotate.
+    /// </param>
+    /// <returns>
+    /// the rotated word, which may have unmasked high (&gt; word size) bits.
+    /// </returns>
+    function Rotr(i: UInt64; distance: Int32): UInt64; inline;
+
+    /// <summary>
+    /// Read <see cref="ClpSpeckEngine|TSpeckEngine.FwordSize" /> bytes from
+    /// the input data in little-endian order.
+    /// </summary>
+    /// <param name="bytes">
+    /// the data to read a word from.
+    /// </param>
+    /// <param name="off">
+    /// the offset to read the word from.
+    /// </param>
+    /// <returns>
+    /// the read word, with zeroes in any bits higher than the word size.
+    /// </returns>
+    function BytesToWord(const bytes: TCryptoLibByteArray; off: Int32)
+      : UInt64; inline;
+
+    /// <summary>
+    /// Writes <see cref="ClpSpeckEngine|TSpeckEngine.FwordSize" /> bytes
+    /// into a buffer in little-endian order.
+    /// </summary>
+    /// <param name="word">
+    /// the word to write.
+    /// </param>
+    /// <param name="bytes">
+    /// the buffer to write the word bytes to.
+    /// </param>
+    /// <param name="off">
+    /// the offset to write the data at.
+    /// </param>
+    procedure WordToBytes(word: UInt64; const bytes: TCryptoLibByteArray;
+      off: Int32); inline;
+
+  strict protected
+
+    /// <summary>
+    /// Masks all bits higher than the word size of this cipher in the
+    /// supplied value.
+    /// </summary>
+    /// <param name="val">
+    /// the value to mask.
+    /// </param>
+    /// <returns>
+    /// the masked value.
+    /// </returns>
+    function Mask(val: UInt64): UInt64; virtual; abstract;
+
+    procedure SetKey(const keyBytes: TCryptoLibByteArray); override;
+
+    procedure UnPackBlock(const bytes: TCryptoLibByteArray;
+      off: Int32); override;
+
+    procedure PackBlock(const bytes: TCryptoLibByteArray; off: Int32); override;
+
+    procedure EncryptBlock(); override;
+
+    procedure DecryptBlock(); override;
+
+    /// <summary>
+    /// Constructs a Speck cipher with &lt;= 64 bit word size, using the
+    /// standard 8,3 rotation constants.
+    /// </summary>
+    /// <param name="wordSize">
+    /// the word size in bytes.
+    /// </param>
+    /// <param name="baseRounds">
+    /// the base (for 2 word key) round count.
+    /// </param>
+    constructor Create(wordSize, baseRounds: Int32); overload;
+
+    /// <summary>
+    /// Constructs a Speck cipher with &lt;= 64 bit word size, using custom
+    /// rotation constants.
+    /// </summary>
+    /// <param name="wordSize">
+    /// the word size in bytes.
+    /// </param>
+    /// <param name="baseRounds">
+    /// the base (for 2 word key) round count.
+    /// </param>
+    /// <param name="alpha">
+    /// the <em>alpha</em> rotation constant.
+    /// </param>
+    /// <param name="beta">
+    /// the <em>beta</em> rotation constant.
+    /// </param>
+    constructor Create(wordSize, baseRounds, alpha, beta: Int32); overload;
+
+  end;
+
+type
+
+  /// <summary>
+  /// Speck32: 2 byte words, 7/2 rotation constants.
+  /// <p>
+  /// 20 base rounds (hypothetical)
+  /// </p>
+  /// 64 bit key/22 rounds.
+  /// </summary>
+  TSpeck32Engine = class sealed(TSpeckUInt32Engine)
+
+  strict protected
+    function Mask(val: UInt32): UInt32; override;
+    procedure CheckKeySize(keySizeBytes: Int32); override;
+
+  public
+    constructor Create();
+
+  end;
+
+type
+
+  /// <summary>
+  /// Speck48: 3 byte words, 8/3 rotation constants.
+  /// <p>
+  /// 21 base rounds (hypothetical)
+  /// </p>
+  /// 72 bit key/22 rounds.
+  /// 96 bit key/23 rounds.
+  /// </summary>
+  TSpeck48Engine = class sealed(TSpeckUInt32Engine)
+
+  strict protected
+    function Mask(val: UInt32): UInt32; override;
+    procedure CheckKeySize(keySizeBytes: Int32); override;
+
+  public
+    constructor Create();
+
+  end;
+
+type
+
+  /// <summary>
+  /// Speck64: 4 byte words, 8/3 rotation constants.
+  /// <p>
+  /// 25 base rounds (hypothetical)
+  /// </p>
+  /// 96 bit key/26 rounds.
+  /// 128 bit key/27 rounds.
+  /// </summary>
+  TSpeck64Engine = class sealed(TSpeckUInt32Engine)
+
+  strict protected
+    function Mask(val: UInt32): UInt32; override;
+    procedure CheckKeySize(keySizeBytes: Int32); override;
+
+  public
+    constructor Create();
+
+  end;
+
+type
+
+  /// <summary>
+  /// Speck96: 6 byte words, 8/3 rotation constants.
+  /// <p>
+  /// 28 base rounds
+  /// </p>
+  /// 96 bit key/28 rounds.
+  /// 144 bit key/29 rounds.
+  /// </summary>
+  TSpeck96Engine = class sealed(TSpeckUInt64Engine)
+
+  strict protected
+    function Mask(val: UInt64): UInt64; override;
+    procedure CheckKeySize(keySizeBytes: Int32); override;
+
+  public
+    constructor Create();
+
+  end;
+
+type
+
+  /// <summary>
+  /// Speck128: 8 byte words, 8/3 rotation constants.
+  /// <p>
+  /// 32 base rounds
+  /// </p>
+  /// 128 bit key/32 rounds.
+  /// 192 bit key/33 rounds.
+  /// 256 bit key/34 rounds.
+  /// </summary>
+  TSpeck128Engine = class sealed(TSpeckUInt64Engine)
+
+  strict protected
+    function Mask(val: UInt64): UInt64; override;
+    procedure CheckKeySize(keySizeBytes: Int32); override;
+
+  public
+    constructor Create();
+
+  end;
+
+implementation
+
+{ TSpeckEngine }
+
+constructor TSpeckEngine.Create(wordSize, baseRounds, alpha, beta: Int32);
+begin
+  Inherited Create();
+  FwordSize := wordSize;
+  FbaseRounds := baseRounds;
+  Frounds := baseRounds;
+  FblockSize := wordSize * 2;
+  FwordSizeBits := wordSize * 8;
+  Falpha := alpha;
+  Fbeta := beta;
+end;
+
+function TSpeckEngine.GetBlockSize: Int32;
+begin
+  result := FblockSize;
+end;
+
+procedure TSpeckEngine.EngineInit(forEncryption: Boolean;
+  const keyBytes: TCryptoLibByteArray);
+begin
+  FforEncryption := forEncryption;
+  CheckKeySize(System.Length(keyBytes));
+  SetKey(keyBytes);
+  Finitialised := true;
+end;
+
+function TSpeckEngine.GetAlgorithmName: String;
+begin
+  result := Format('Speck%d', [FblockSize * 8]);
+end;
+
+function TSpeckEngine.GetIsPartialBlockOkay: Boolean;
+begin
+  result := false;
+end;
+
+procedure TSpeckEngine.Init(forEncryption: Boolean;
+  const parameters: ICipherParameters);
+var
+  keyParameter: IKeyParameter;
+  keyBytes: TCryptoLibByteArray;
+begin
+
+  if not Supports(parameters, IKeyParameter, keyParameter) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt(@SInvalidParameterSpeckInit,
+      [(parameters as TObject).ToString]);
+  end;
+  keyBytes := keyParameter.GetKey;
+  EngineInit(forEncryption, keyBytes);
+end;
+
+function TSpeckEngine.ProcessBlock(const input: TCryptoLibByteArray;
+  inOff: Int32; const output: TCryptoLibByteArray; outOff: Int32): Int32;
+begin
+  if (not Finitialised) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateResFmt
+      (@SSpeckEngineNotInitialised, [AlgorithmName]);
+  end;
+
+  TCheck.DataLength((inOff + FblockSize) > System.Length(input),
+    SInputBuffertooShort);
+  TCheck.DataLength((outOff + FblockSize) > System.Length(output),
+    SOutputBuffertooShort);
+
+  UnPackBlock(input, inOff);
+  if (FforEncryption) then
+  begin
+    EncryptBlock();
+  end
+  else
+  begin
+    DecryptBlock();
+  end;
+  PackBlock(output, outOff);
+
+  result := FblockSize;
+end;
+
+procedure TSpeckEngine.Reset;
+begin
+  // nothing to do.
+end;
+
+{ TSpeckUInt32Engine }
+
+function TSpeckUInt32Engine.Rotl(i: UInt32; distance: Int32): UInt32;
+begin
+  result := ((i shl distance) or (i shr (FwordSizeBits - distance)));
+end;
+
+function TSpeckUInt32Engine.Rotr(i: UInt32; distance: Int32): UInt32;
+begin
+  result := ((i shr distance) or (i shl (FwordSizeBits - distance)));
+end;
+
+function TSpeckUInt32Engine.BytesToWord(const bytes: TCryptoLibByteArray;
+  off: Int32): UInt32;
+var
+  index: Int32;
+begin
+  TCheck.DataLength((off + FwordSize) > System.Length(bytes),
+    SInvalidArgumentEncountered);
+
+  index := off + FwordSize - 1;
+  result := (bytes[index]);
+  System.Dec(index);
+  result := (result shl 8) or (bytes[index]);
+  System.Dec(index);
+  if (FwordSize > 2) then
+  begin
+    result := (result shl 8) or (bytes[index]);
+    System.Dec(index);
+    if (FwordSize > 3) then
+    begin
+      result := (result shl 8) or (bytes[index]);
+    end;
+  end;
+
+end;
+
+procedure TSpeckUInt32Engine.WordToBytes(word: UInt32;
+  const bytes: TCryptoLibByteArray; off: Int32);
+begin
+  TCheck.DataLength((off + FwordSize) > System.Length(bytes),
+    SInvalidArgumentEncountered);
+
+  bytes[off] := Byte(word);
+  System.Inc(off);
+  bytes[off] := Byte(word shr 8);
+  System.Inc(off);
+  if (FwordSize > 2) then
+  begin
+    bytes[off] := Byte(word shr 16);
+    System.Inc(off);
+    if (FwordSize > 3) then
+    begin
+      bytes[off] := Byte(word shr 24);
+    end;
+  end;
+
+end;
+
+constructor TSpeckUInt32Engine.Create(wordSize, baseRounds: Int32);
+begin
+  Create(wordSize, baseRounds, 8, 3);
+end;
+
+constructor TSpeckUInt32Engine.Create(wordSize, baseRounds, alpha, beta: Int32);
+begin
+  Inherited Create(wordSize, baseRounds, alpha, beta);
+end;
+
+procedure TSpeckUInt32Engine.EncryptBlock;
+var
+  x, y: UInt32;
+  r: Int32;
+begin
+  x := Fx;
+  y := Fy;
+
+  for r := 0 to System.Pred(Frounds) do
+  begin
+    x := Mask((Rotr(x, Falpha) + y) xor Fk[r]);
+    y := Mask(Rotl(y, Fbeta) xor x);
+  end;
+
+  Fx := x;
+  Fy := y;
+end;
+
+procedure TSpeckUInt32Engine.DecryptBlock;
+var
+  x, y: UInt32;
+  r: Int32;
+begin
+  x := Fx;
+  y := Fy;
+
+  for r := System.Pred(Frounds) downto 0 do
+  begin
+    y := Mask(Rotr(x xor y, Fbeta));
+    x := Mask(Rotl(Mask((x xor Fk[r]) - y), Falpha));
+  end;
+
+  Fx := x;
+  Fy := y;
+
+end;
+
+procedure TSpeckUInt32Engine.PackBlock(const bytes: TCryptoLibByteArray;
+  off: Int32);
+begin
+  WordToBytes(Fx, bytes, off + FwordSize);
+  WordToBytes(Fy, bytes, off);
+end;
+
+procedure TSpeckUInt32Engine.UnPackBlock(const bytes: TCryptoLibByteArray;
+  off: Int32);
+begin
+  Fx := BytesToWord(bytes, off + FwordSize);
+  Fy := BytesToWord(bytes, off);
+end;
+
+procedure TSpeckUInt32Engine.SetKey(const keyBytes: TCryptoLibByteArray);
+var
+  keyWords, i, lw: Int32;
+  L: TCryptoLibUInt32Array;
+begin
+  // Determine number of key words m
+  keyWords := System.Length(keyBytes) div FwordSize;
+
+  // Number of rounds is increased by 1 for each key word > 2
+  Frounds := FbaseRounds + (keyWords - 2);
+  System.SetLength(Fk, Frounds);
+
+  // Load k[0]
+  Fk[0] := BytesToWord(keyBytes, 0);
+
+  // Load l[m-2]...l[0], leave space for l[m-1] in key expansion
+  System.SetLength(L, keyWords);
+
+  for i := 0 to System.Pred(keyWords - 1) do
+  begin
+    L[(keyWords - 2) - i] := BytesToWord(keyBytes, ((keyWords - 1) - i) *
+      FwordSize);
+  end;
+  // Key expansion using round function over l[m-2]...l[0],k[0] with round number as key
+  for i := 0 to System.Pred(Frounds - 1) do
+  begin
+    lw := (i + keyWords - 1) mod keyWords;
+    L[lw] := Mask((Rotr(L[i mod keyWords], Falpha) + Fk[i]) xor UInt32(i));
+    Fk[i + 1] := Mask(Rotl(Fk[i], Fbeta) xor L[lw]);
+
+  end;
+
+end;
+
+{ TSpeckUInt64Engine }
+
+function TSpeckUInt64Engine.Rotl(i: UInt64; distance: Int32): UInt64;
+begin
+  result := ((i shl distance) or (i shr (FwordSizeBits - distance)));
+end;
+
+function TSpeckUInt64Engine.Rotr(i: UInt64; distance: Int32): UInt64;
+begin
+  result := ((i shr distance) or (i shl (FwordSizeBits - distance)));
+end;
+
+function TSpeckUInt64Engine.BytesToWord(const bytes: TCryptoLibByteArray;
+  off: Int32): UInt64;
+var
+  index: Int32;
+begin
+  TCheck.DataLength((off + FwordSize) > System.Length(bytes),
+    SInvalidArgumentEncountered);
+
+  index := off + FwordSize - 1;
+  result := (bytes[index]);
+  System.Dec(index);
+  result := (result shl 8) or (bytes[index]);
+  System.Dec(index);
+  result := (result shl 8) or (bytes[index]);
+  System.Dec(index);
+  result := (result shl 8) or (bytes[index]);
+  System.Dec(index);
+  result := (result shl 8) or (bytes[index]);
+  System.Dec(index);
+  result := (result shl 8) or (bytes[index]);
+  System.Dec(index);
+  if (FwordSize = 8) then
+  begin
+    result := (result shl 8) or (bytes[index]);
+    System.Dec(index);
+    result := (result shl 8) or (bytes[index]);
+  end;
+end;
+
+procedure TSpeckUInt64Engine.WordToBytes(word: UInt64;
+  const bytes: TCryptoLibByteArray; off: Int32);
+begin
+  TCheck.DataLength((off + FwordSize) > System.Length(bytes),
+    SInvalidArgumentEncountered);
+
+  bytes[off] := Byte(word);
+  System.Inc(off);
+  bytes[off] := Byte(word shr 8);
+  System.Inc(off);
+  bytes[off] := Byte(word shr 16);
+  System.Inc(off);
+  bytes[off] := Byte(word shr 24);
+  System.Inc(off);
+  bytes[off] := Byte(word shr 32);
+  System.Inc(off);
+  bytes[off] := Byte(word shr 40);
+  System.Inc(off);
+  if (FwordSize = 8) then
+  begin
+    bytes[off] := Byte(word shr 48);
+    System.Inc(off);
+    bytes[off] := Byte(word shr 56);
+  end;
+
+end;
+
+constructor TSpeckUInt64Engine.Create(wordSize, baseRounds: Int32);
+begin
+  Create(wordSize, baseRounds, 8, 3);
+end;
+
+constructor TSpeckUInt64Engine.Create(wordSize, baseRounds, alpha, beta: Int32);
+begin
+  Inherited Create(wordSize, baseRounds, alpha, beta);
+end;
+
+procedure TSpeckUInt64Engine.EncryptBlock;
+var
+  x, y: UInt64;
+  r: Int32;
+begin
+  x := Fx;
+  y := Fy;
+
+  for r := 0 to System.Pred(Frounds) do
+  begin
+    x := Mask((Rotr(x, Falpha) + y) xor Fk[r]);
+    y := Mask(Rotl(y, Fbeta) xor x);
+  end;
+
+  Fx := x;
+  Fy := y;
+end;
+
+procedure TSpeckUInt64Engine.DecryptBlock;
+var
+  x, y: UInt64;
+  r: Int32;
+begin
+  x := Fx;
+  y := Fy;
+
+  for r := System.Pred(Frounds) downto 0 do
+  begin
+    y := Mask(Rotr(x xor y, Fbeta));
+    x := Mask(Rotl(Mask((x xor Fk[r]) - y), Falpha));
+  end;
+
+  Fx := x;
+  Fy := y;
+
+end;
+
+procedure TSpeckUInt64Engine.PackBlock(const bytes: TCryptoLibByteArray;
+  off: Int32);
+begin
+  WordToBytes(Fx, bytes, off + FwordSize);
+  WordToBytes(Fy, bytes, off);
+end;
+
+procedure TSpeckUInt64Engine.UnPackBlock(const bytes: TCryptoLibByteArray;
+  off: Int32);
+begin
+  Fx := BytesToWord(bytes, off + FwordSize);
+  Fy := BytesToWord(bytes, off);
+end;
+
+procedure TSpeckUInt64Engine.SetKey(const keyBytes: TCryptoLibByteArray);
+var
+  keyWords, i, lw: Int32;
+  L: TCryptoLibUInt64Array;
+begin
+  // Determine number of key words m
+  keyWords := System.Length(keyBytes) div FwordSize;
+
+  // Number of rounds is increased by 1 for each key word > 2
+  Frounds := FbaseRounds + (keyWords - 2);
+  System.SetLength(Fk, Frounds);
+
+  // Load k[0]
+  Fk[0] := BytesToWord(keyBytes, 0);
+
+  // Load l[m-2]...l[0], leave space for l[m-1] in key expansion
+  System.SetLength(L, keyWords);
+
+  for i := 0 to System.Pred(keyWords - 1) do
+  begin
+    L[(keyWords - 2) - i] := BytesToWord(keyBytes, ((keyWords - 1) - i) *
+      FwordSize);
+  end;
+  // Key expansion using round function over l[m-2]...l[0],k[0] with round number as key
+  for i := 0 to System.Pred(Frounds - 1) do
+  begin
+    lw := (i + keyWords - 1) mod keyWords;
+    L[lw] := Mask((Rotr(L[i mod keyWords], Falpha) + Fk[i]) xor UInt64(i));
+    Fk[i + 1] := Mask(Rotl(Fk[i], Fbeta) xor L[lw]);
+
+  end;
+
+end;
+
+{ TSpeck32Engine }
+
+constructor TSpeck32Engine.Create;
+begin
+  Inherited Create(2, 20, 7, 2);
+end;
+
+function TSpeck32Engine.Mask(val: UInt32): UInt32;
+begin
+  result := (val and $FFFF);
+end;
+
+procedure TSpeck32Engine.CheckKeySize(keySizeBytes: Int32);
+begin
+  if (keySizeBytes <> 8) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt(@SSpeck32InvalidKeySize,
+      [keySizeBytes * 8]);
+  end;
+end;
+
+{ TSpeck48Engine }
+
+constructor TSpeck48Engine.Create;
+begin
+  Inherited Create(3, 21);
+end;
+
+function TSpeck48Engine.Mask(val: UInt32): UInt32;
+begin
+  result := (val and $FFFFFF);
+end;
+
+procedure TSpeck48Engine.CheckKeySize(keySizeBytes: Int32);
+begin
+  if not(keySizeBytes in [9, 12]) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt(@SSpeck48InvalidKeySize,
+      [keySizeBytes * 8]);
+  end;
+end;
+
+{ TSpeck64Engine }
+
+constructor TSpeck64Engine.Create;
+begin
+  Inherited Create(4, 25);
+end;
+
+function TSpeck64Engine.Mask(val: UInt32): UInt32;
+begin
+  result := val;
+end;
+
+procedure TSpeck64Engine.CheckKeySize(keySizeBytes: Int32);
+begin
+  if not(keySizeBytes in [12, 16]) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt(@SSpeck64InvalidKeySize,
+      [keySizeBytes * 8]);
+  end;
+end;
+
+{ TSpeck96Engine }
+
+constructor TSpeck96Engine.Create;
+begin
+  Inherited Create(6, 28);
+end;
+
+function TSpeck96Engine.Mask(val: UInt64): UInt64;
+begin
+  result := (val and $0000FFFFFFFFFFFF);
+end;
+
+procedure TSpeck96Engine.CheckKeySize(keySizeBytes: Int32);
+begin
+  if not(keySizeBytes in [12, 18]) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt(@SSpeck96InvalidKeySize,
+      [keySizeBytes * 8]);
+  end;
+end;
+
+{ TSpeck128Engine }
+
+constructor TSpeck128Engine.Create;
+begin
+  Inherited Create(8, 32);
+end;
+
+function TSpeck128Engine.Mask(val: UInt64): UInt64;
+begin
+  result := val;
+end;
+
+procedure TSpeck128Engine.CheckKeySize(keySizeBytes: Int32);
+begin
+  if not(keySizeBytes in [16, 24, 32]) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt(@SSpeck128InvalidKeySize,
+      [keySizeBytes * 8]);
+  end;
+end;
+
+end.

+ 36 - 0
CryptoLib/src/Interfaces/ClpISpeckEngine.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 ClpISpeckEngine;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIBlockCipher;
+
+type
+
+  ISpeckEngine = interface(IBlockCipher)
+    ['{60AEDFFF-5FAB-4018-90E7-ED9BD1B3D406}']
+
+  end;
+
+implementation
+
+end.

+ 11 - 3
CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.lpk

@@ -19,13 +19,13 @@
         </Optimizations>
         </Optimizations>
       </CodeGeneration>
       </CodeGeneration>
     </CompilerOptions>
     </CompilerOptions>
-    <Description Value="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 Encryption and Decryption (With various modes and paddings) and ECIES ."/>
+    <Description Value="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, Speck Encryption and Decryption (With various modes and paddings) and ECIES."/>
     <License Value="MIT License                          
     <License Value="MIT License                          
 
 
  Acknowledgements: 
  Acknowledgements: 
 Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the development of this library "/>
 Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the development of this library "/>
-    <Version Major="2" Minor="9"/>
-    <Files Count="269">
+    <Version Major="3"/>
+    <Files Count="271">
       <Item1>
       <Item1>
         <Filename Value="..\..\Asn1\ClpOidTokenizer.pas"/>
         <Filename Value="..\..\Asn1\ClpOidTokenizer.pas"/>
         <UnitName Value="ClpOidTokenizer"/>
         <UnitName Value="ClpOidTokenizer"/>
@@ -1104,6 +1104,14 @@ Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the devel
         <Filename Value="..\..\Interfaces\ClpIECC.pas"/>
         <Filename Value="..\..\Interfaces\ClpIECC.pas"/>
         <UnitName Value="ClpIECC"/>
         <UnitName Value="ClpIECC"/>
       </Item269>
       </Item269>
+      <Item270>
+        <Filename Value="..\..\Interfaces\ClpISpeckEngine.pas"/>
+        <UnitName Value="ClpISpeckEngine"/>
+      </Item270>
+      <Item271>
+        <Filename Value="..\..\Crypto\Engines\ClpSpeckEngine.pas"/>
+        <UnitName Value="ClpSpeckEngine"/>
+      </Item271>
     </Files>
     </Files>
     <RequiredPkgs Count="3">
     <RequiredPkgs Count="3">
       <Item1>
       <Item1>

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

@@ -94,7 +94,7 @@ uses
   ClpIAsn1Objects, ClpBlockCipherModes, ClpECCurveConstants, 
   ClpIAsn1Objects, ClpBlockCipherModes, ClpECCurveConstants, 
   ClpIBlockCipherModes, ClpIPaddingModes, ClpISecP256K1Custom, 
   ClpIBlockCipherModes, ClpIPaddingModes, ClpISecP256K1Custom, 
   ClpISecP256R1Custom, ClpISecP384R1Custom, ClpISecP521R1Custom, 
   ClpISecP256R1Custom, ClpISecP384R1Custom, ClpISecP521R1Custom, 
-  ClpISecT283Custom, ClpPaddingModes, ClpIECC;
+  ClpISecT283Custom, ClpPaddingModes, ClpIECC, ClpISpeckEngine, ClpSpeckEngine;
 
 
 implementation
 implementation