Browse Source

generic update + PiCipherV2

master
bg nerilex 6 years ago
parent
commit
8e4081389a
  1. 49
      src/abstraction/block_cipher_generic.ads
  2. 36
      src/abstraction/hash_generic.adb
  3. 53
      src/abstraction/hash_generic.ads
  4. 73
      src/algorithms/aes/aes.ads
  5. 4
      src/algorithms/aes/aes_spec.adb
  6. 70
      src/algorithms/aes/aes_spec.ads
  7. 55
      src/algorithms/aria/aria.ads
  8. 23
      src/algorithms/aria/aria_spec.adb
  9. 50
      src/algorithms/aria/aria_spec.ads
  10. 29
      src/algorithms/des/des.ads
  11. 4
      src/algorithms/des/des_spec.adb
  12. 39
      src/algorithms/des/des_spec.ads
  13. 38
      src/algorithms/des/tdes.ads
  14. 28
      src/algorithms/des/tdes_spec.adb
  15. 43
      src/algorithms/des/tdes_spec.ads
  16. 202
      src/algorithms/gcm/gcm128_spec.adb
  17. 50
      src/algorithms/gcm/gcm128_spec.ads
  18. 363
      src/algorithms/pi-cipher/pi16cipher_spec.adb
  19. 75
      src/algorithms/pi-cipher/pi16cipher_spec.ads
  20. 363
      src/algorithms/pi-cipher/pi32cipher_spec.adb
  21. 75
      src/algorithms/pi-cipher/pi32cipher_spec.ads
  22. 371
      src/algorithms/pi-cipher/pi64cipher_spec.adb
  23. 75
      src/algorithms/pi-cipher/pi64cipher_spec.ads
  24. 39
      src/algorithms/sha2/sha2_224.ads
  25. 15
      src/algorithms/sha2/sha2_224_spec.adb
  26. 44
      src/algorithms/sha2/sha2_224_spec.ads
  27. 42
      src/algorithms/sha2/sha2_256.ads
  28. 19
      src/algorithms/sha2/sha2_256_spec.adb
  29. 44
      src/algorithms/sha2/sha2_256_spec.ads
  30. 39
      src/algorithms/sha2/sha2_384.ads
  31. 15
      src/algorithms/sha2/sha2_384_spec.adb
  32. 44
      src/algorithms/sha2/sha2_384_spec.ads
  33. 39
      src/algorithms/sha2/sha2_512.ads
  34. 15
      src/algorithms/sha2/sha2_512_spec.adb
  35. 44
      src/algorithms/sha2/sha2_512_spec.ads
  36. 4
      src/algorithms/sha2/sha2_large.ads
  37. 4
      src/algorithms/sha2/sha2_small.adb
  38. 5
      src/algorithms/sha2/sha2_small.ads
  39. 2
      src/algorithms/sha3/keccak.adb
  40. 4
      src/algorithms/sha3/keccak.ads
  41. 4
      src/algorithms/sha3/keccak_parameters.ads
  42. 45
      src/algorithms/sha3/sha3.ads
  43. 2
      src/algorithms/sha3/sha3_generic.adb
  44. 6
      src/algorithms/sha3/sha3_generic.ads
  45. 2
      src/algorithms/spritz/spritz.ads
  46. 2
      src/algorithms/spritz/spritz_aead.ads
  47. 3
      src/algorithms/spritz/spritz_hash.ads
  48. 2
      src/algorithms/spritz/spritz_stream.ads
  49. 222
      src/main.adb
  50. 11
      src/test_modules/nessie_bc_test_generator.adb
  51. 17
      src/test_modules/nessie_bc_test_generator.ads
  52. 99
      src/test_modules/nessie_hash_test_generator.adb
  53. 14
      src/test_modules/nessie_hash_test_generator.ads
  54. 62
      src/test_modules/nist_test_io.adb
  55. 54
      src/test_modules/nist_test_io.ads
  56. 0
      src/test_modules/sha_test_io.adb
  57. 0
      src/test_modules/sha_test_io.ads
  58. 301
      src/tests/main.adb
  59. 61
      src/tests/test_aes.adb
  60. 37
      src/tests/test_aes_nessie.adb
  61. 15
      src/tests/test_des_nessie.adb
  62. 4
      src/tests/test_keccak.adb
  63. 204
      src/tests/test_pi16cipher.adb
  64. 146
      src/tests/test_pi32cipher.adb
  65. 204
      src/tests/test_pi64cipher.adb
  66. 120
      src/tests/test_sha2.adb
  67. 2
      src/tests/test_sha224.adb
  68. 2
      src/tests/test_sha256.adb
  69. 45
      src/tests/test_sha2_nessie.adb
  70. 72
      src/tests/test_sha2_nist.adb
  71. 2
      src/tests/test_sha384.adb
  72. 42
      src/tests/test_sha3_nessie.adb
  73. 6
      src/tests/test_sha3_nist.adb
  74. 2
      src/tests/test_sha512.adb
  75. 52
      src/tests/test_tdes.adb
  76. 38
      src/tests/test_tdes_nessie.adb
  77. 31
      src/types/crypto_core_types.adb
  78. 6
      src/types/crypto_core_types.ads
  79. 10
      src/types/crypto_generic_utils.adb
  80. 42
      src/types/crypto_generic_utils.ads
  81. 13
      src/types/crypto_types.ads
  82. 95
      steelcrypt.gpr

49
src/abstraction/block_cipher_generic.ads

@ -0,0 +1,49 @@
-- Copyright (C) 2015 Daniel Otte <bg@nerilex.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with Crypto_Core_Types; use Crypto_Core_Types;
generic
Name_Intern : String;
type Context_T_Intern is private;
Block_Size_Bits_Intern : Natural;
Key_Size_Bits_Intern : Natural;
with procedure Initialize_Intern(Context : out Context_T_Intern; Key : in u8_Array);
with procedure Encrypt_Intern(Context : in Context_T_Intern; Block : in out u8_Array);
with procedure Decrypt_Intern(Context : in Context_T_Intern; Block : in out u8_Array);
package Block_Cipher_Generic is
Name : String renames Name_Intern;
subtype Context_T is Context_T_Intern;
Block_Size_Bits : Natural renames Block_Size_Bits_Intern;
Key_Size_Bits : Natural renames Key_Size_Bits_Intern;
Block_Size_Bytes : Natural := (Block_Size_Bits) / 8;
Key_Size_Bytes : Natural := (Key_Size_Bits) / 8;
procedure Initialize(Context : out Context_T_Intern; Key : in u8_Array) renames Initialize_Intern;
procedure Encrypt(Context : in Context_T_Intern; Block : in out u8_Array) renames Encrypt_Intern;
procedure Decrypt(Context : in Context_T_Intern; Block : in out u8_Array) renames Decrypt_Intern;
private
end Block_Cipher_Generic;

36
src/abstraction/hash_generic.adb

@ -0,0 +1,36 @@
-- Copyright (C) 2015 Daniel Otte <bg@nerilex.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
package body Hash_Generic is
procedure Hash(Data : in u8_Array; Digest : out u8_Array; Bits : in Integer := -1) is
Context : Context_T_Intern;
Counter : Natural := Data'Length * 8;
Index : Integer := Data'First;
begin
if Bits >= 0 then
Counter := Bits;
end if;
Initialize(Context);
while Counter > Block_Size_Bits loop
Next_Block(Context, Data(Index .. Index + Block_Size_Bytes - 1));
Index := Index + Block_Size_Bytes;
Counter := Counter - Block_Size_Bits;
end loop;
Last_Block(Context, Data(Index .. Data'Last), Counter);
Get_Digest(Context, Digest);
end;
end Hash_Generic;

53
src/abstraction/hash_generic.ads

@ -0,0 +1,53 @@
-- Copyright (C) 2015 Daniel Otte <bg@nerilex.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with Crypto_Core_Types; use Crypto_Core_Types;
generic
Name_Intern : String;
type Context_T_Intern is private;
Block_Size_Bits_Intern : Natural;
Digest_Size_Bits_Intern : Natural;
with procedure Initialize_Intern(Context : out Context_T_Intern);
with procedure Next_Block_Intern(Context : in out Context_T_Intern; Block : in u8_Array);
with procedure Last_Block_Intern(Context : in out Context_T_Intern; Block : in u8_Array; Bits : in Integer := -1);
with procedure Get_Digest_Intern(Context : in out Context_T_Intern; Digest : out u8_Array);
package Hash_Generic is
Name : String renames Name_Intern;
subtype Context_T is Context_T_Intern;
Block_Size_Bits : Natural renames Block_Size_Bits_Intern;
Digest_Size_Bits : Natural renames Digest_Size_Bits_Intern;
Block_Size_Bytes : Natural := (Block_Size_Bits) / 8;
Digest_Size_Bytes : Natural := (Digest_Size_Bits) / 8;
procedure Initialize(Context : out Context_T_Intern) renames Initialize_Intern;
procedure Next_Block(Context : in out Context_T_Intern; Block : in u8_Array) renames Next_Block_Intern;
procedure Last_Block(Context : in out Context_T_Intern; Block : in u8_Array; Bits : in Integer := -1) renames Last_Block_Intern;
procedure Get_Digest(Context : in out Context_T_Intern; Digest : out u8_Array) renames Get_Digest_Intern;
procedure Hash(Data : in u8_Array; Digest : out u8_Array; Bits : in Integer := -1);
private
end Hash_Generic;

73
src/algorithms/aes/aes.ads

@ -13,58 +13,37 @@
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with Block_Cipher_Generic;
with Crypto_Core_Types; use Crypto_Core_Types;
with Crypto_Types; use Crypto_Types;
with AES_Spec;
use Crypto_Types.Crypto_Types_u8;
use Crypto_Types.Crypto_Utils_u8;
package AES is
subtype Key_128_T is Block_128_Bit;
subtype Key_192_T is Block_192_Bit;
subtype Key_256_T is Block_256_Bit;
type Context_128_T is private;
type Context_192_T is private;
type Context_256_T is private;
subtype Block_T is Block_128_Bit;
procedure Initialize(Context : out Context_128_T; Key : in Key_128_T);
procedure Encrypt(Context : in Context_128_T; Block: in out Block_T);
procedure Decrypt(Context : in Context_128_T; Block: in out Block_T);
procedure Initialize(Context : out Context_192_T; Key : in Key_192_T);
procedure Encrypt(Context : in Context_192_T; Block: in out Block_T);
procedure Decrypt(Context : in Context_192_T; Block: in out Block_T);
procedure Initialize(Context : out Context_256_T; Key : in Key_256_T);
procedure Encrypt(Context : in Context_256_T; Block: in out Block_T);
procedure Decrypt(Context : in Context_256_T; Block: in out Block_T);
private
subtype RoundKey_T is Block_128_Bit;
type RoundKeys_T is Array (Integer range <>) of RoundKey_T;
subtype Num_RoundKeys_T is Integer range 11 .. 15;
type Context_T(Num_RoundKeys : Num_RoundKeys_T := 15) is record
RoundKeys : RoundKeys_T(1 .. Num_RoundKeys);
end record;
type Context_128_T is new Context_T(11);
type Context_192_T is new Context_T(13);
type Context_256_T is new Context_T(15);
Nb : constant Integer := 4;
polynom : constant u8 := 16#1B#;
function gf256mul(a, b : u8) return u8;
generic
type T_In(<>) is new u8_Array;
type T_Out(<>) is new Context_T;
procedure Initialize_Generic(Key : T_In; Context : out T_Out);
package AES_128 is new Block_Cipher_Generic( Name_Intern => "AES-128",
Context_T_Intern => AES_Spec.Context_128_T,
Block_Size_Bits_Intern => 128,
Key_Size_Bits_Intern => 128,
Initialize_Intern => AES_Spec.Initialize,
Encrypt_Intern => AES_Spec.Encrypt,
Decrypt_Intern => AES_Spec.Decrypt );
package AES_192 is new Block_Cipher_Generic( Name_Intern => "AES-192",
Context_T_Intern => AES_Spec.Context_192_T,
Block_Size_Bits_Intern => 128,
Key_Size_Bits_Intern => 192,
Initialize_Intern => AES_Spec.Initialize,
Encrypt_Intern => AES_Spec.Encrypt,
Decrypt_Intern => AES_Spec.Decrypt );
package AES_256 is new Block_Cipher_Generic( Name_Intern => "AES-256",
Context_T_Intern => AES_Spec.Context_256_T,
Block_Size_Bits_Intern => 128,
Key_Size_Bits_Intern => 256,
Initialize_Intern => AES_Spec.Initialize,
Encrypt_Intern => AES_Spec.Encrypt,
Decrypt_Intern => AES_Spec.Decrypt );
end AES;

4
src/algorithms/aes/aes.adb → src/algorithms/aes/aes_spec.adb

@ -13,7 +13,7 @@
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
package body AES is
package body AES_Spec is
Sbox : constant array (u8 range 0 .. 255) of u8 := (
16#63#, 16#7c#, 16#77#, 16#7b#, 16#f2#, 16#6b#, 16#6f#, 16#c5#, 16#30#, 16#01#, 16#67#, 16#2b#, 16#fe#, 16#d7#, 16#ab#, 16#76#,
@ -275,4 +275,4 @@ package body AES is
Decrypt_Generic(Context_T(Context), Block);
end Decrypt;
end AES;
end AES_Spec;

70
src/algorithms/aes/aes_spec.ads

@ -0,0 +1,70 @@
-- Copyright (C) 2015 Daniel Otte <bg@nerilex.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with Crypto_Core_Types; use Crypto_Core_Types;
with Crypto_Types; use Crypto_Types;
use Crypto_Types.Crypto_Utils_u8;
package AES_Spec is
subtype Key_128_T is Block_128_Bit;
subtype Key_192_T is Block_192_Bit;
subtype Key_256_T is Block_256_Bit;
type Context_128_T is private;
type Context_192_T is private;
type Context_256_T is private;
subtype Block_T is Block_128_Bit;
procedure Initialize(Context : out Context_128_T; Key : in Key_128_T);
procedure Encrypt(Context : in Context_128_T; Block: in out Block_T);
procedure Decrypt(Context : in Context_128_T; Block: in out Block_T);
procedure Initialize(Context : out Context_192_T; Key : in Key_192_T);
procedure Encrypt(Context : in Context_192_T; Block: in out Block_T);
procedure Decrypt(Context : in Context_192_T; Block: in out Block_T);
procedure Initialize(Context : out Context_256_T; Key : in Key_256_T);
procedure Encrypt(Context : in Context_256_T; Block: in out Block_T);
procedure Decrypt(Context : in Context_256_T; Block: in out Block_T);
private
subtype RoundKey_T is Block_128_Bit;
type RoundKeys_T is Array (Integer range <>) of RoundKey_T;
subtype Num_RoundKeys_T is Integer range 11 .. 15;
type Context_T(Num_RoundKeys : Num_RoundKeys_T := 15) is record
RoundKeys : RoundKeys_T(1 .. Num_RoundKeys);
end record;
type Context_128_T is new Context_T(11);
type Context_192_T is new Context_T(13);
type Context_256_T is new Context_T(15);
Nb : constant Integer := 4;
polynom : constant u8 := 16#1B#;
function gf256mul(a, b : u8) return u8;
generic
type T_In(<>) is new u8_Array;
type T_Out(<>) is new Context_T;
procedure Initialize_Generic(Key : T_In; Context : out T_Out);
end AES_Spec;

55
src/algorithms/aria/aria.ads

@ -13,40 +13,37 @@
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with Block_Cipher_Generic;
with Crypto_Core_Types; use Crypto_Core_Types;
with Crypto_Types; use Crypto_Types;
with ARIA_Spec;
use Crypto_Types.Crypto_Types_u8;
use Crypto_Types.Crypto_Utils_u8;
package ARIA is
type Key_128 is new Block_128_Bit;
type Key_192 is new Block_192_Bit;
type Key_256 is new Block_256_Bit;
type Context_T is private;
type Plaintext is new Block_128_Bit;
type Ciphertext is new Block_128_Bit;
procedure Initialize(Context : out Context_T; Key : in Key_128);
procedure Initialize(Context : out Context_T; Key : in Key_192);
procedure Initialize(Context : out Context_T; Key : in Key_256);
procedure Encrypt(Context : in Context_T; Block: in out Block_128_Bit);
procedure Decrypt(Context : in Context_T; Block: in out Block_128_Bit);
private
type PreKey_T is new Block_128_Bit;
type PreKeys_T is Array (1 .. 4) of PreKey_T;
type Num_Rounds is range 1 .. 16;
type Context_T is record
W : PreKeys_T;
Rounds : Num_Rounds;
end record;
package ARIA_128 is new Block_Cipher_Generic( Name_Intern => "ARIA-128",
Context_T_Intern => ARIA_Spec.Context_T,
Block_Size_Bits_Intern => 128,
Key_Size_Bits_Intern => 128,
Initialize_Intern => ARIA_Spec.Initialize,
Encrypt_Intern => ARIA_Spec.Encrypt,
Decrypt_Intern => ARIA_Spec.Decrypt );
package ARIA_192 is new Block_Cipher_Generic( Name_Intern => "ARIA-192",
Context_T_Intern => ARIA_Spec.Context_T,
Block_Size_Bits_Intern => 128,
Key_Size_Bits_Intern => 192,
Initialize_Intern => ARIA_Spec.Initialize,
Encrypt_Intern => ARIA_Spec.Encrypt,
Decrypt_Intern => ARIA_Spec.Decrypt );
package ARIA_256 is new Block_Cipher_Generic( Name_Intern => "ARIA-256",
Context_T_Intern => ARIA_Spec.Context_T,
Block_Size_Bits_Intern => 128,
Key_Size_Bits_Intern => 256,
Initialize_Intern => ARIA_Spec.Initialize,
Encrypt_Intern => ARIA_Spec.Encrypt,
Decrypt_Intern => ARIA_Spec.Decrypt );
end ARIA;

23
src/algorithms/aria/aria.adb → src/algorithms/aria/aria_spec.adb

@ -13,7 +13,7 @@
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
package body ARIA is
package body ARIA_Spec is
SBox : constant array (Integer range 1 .. 4, u8 range 0 .. 255) of u8 := ( (
16#63#, 16#7c#, 16#77#, 16#7b#, 16#f2#, 16#6b#, 16#6f#, 16#c5#, 16#30#, 16#01#, 16#67#, 16#2b#, 16#fe#, 16#d7#, 16#ab#, 16#76#,
@ -157,7 +157,7 @@ package body ARIA is
A(Block);
end F_Even;
procedure Initialize(Key : in u8_Array; Context : out Context_T) is
procedure Initialize(Context : out Context_T; Key : in u8_Array) is
C_Select : Array (1 .. 3) of Natural range 1 .. 3;
begin
case Key'Length is
@ -170,7 +170,7 @@ package body ARIA is
when 32 =>
C_Select := (3, 1, 2);
Context.Rounds := 16;
when others => raise Constraint_Error;
when others => raise Invalid_Key_Size;
end case;
Context.W(1) := PreKey_T(Key(1 .. 16));
Context.W(2) := Context.W(1);
@ -189,21 +189,6 @@ package body ARIA is
Context.W(4) := PreKey_T(u8_Array(Context.W(4)) xor u8_Array(Context.W(2)));
end Initialize;
procedure Initialize(Context : out Context_T; Key : in Key_128) is
begin
Initialize(u8_Array(Key), Context);
end Initialize;
procedure Initialize(Context : out Context_T; Key : in Key_192) is
begin
Initialize(u8_Array(Key), Context);
end Initialize;
procedure Initialize(Context : out Context_T; Key : in Key_256) is
begin
Initialize(u8_Array(Key), Context);
end Initialize;
procedure Encrypt(Context : in Context_T; Block: in out Block_128_Bit) is
temp_key : Block_128_Bit;
n : Integer;
@ -254,4 +239,4 @@ package body ARIA is
end Decrypt;
end ARIA;
end ARIA_Spec;

50
src/algorithms/aria/aria_spec.ads

@ -0,0 +1,50 @@
-- Copyright (C) 2015 Daniel Otte <bg@nerilex.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with Crypto_Core_Types; use Crypto_Core_Types;
with Crypto_Types; use Crypto_Types;
use Crypto_Types.Crypto_Utils_u8;
package ARIA_Spec is
subtype Key_128 is Block_128_Bit;
subtype Key_192 is Block_192_Bit;
subtype Key_256 is Block_256_Bit;
type Context_T is private;
type Plaintext is new Block_128_Bit;
type Ciphertext is new Block_128_Bit;
procedure Initialize(Context : out Context_T; Key : in u8_Array);
procedure Encrypt(Context : in Context_T; Block: in out Block_128_Bit);
procedure Decrypt(Context : in Context_T; Block: in out Block_128_Bit);
private
type PreKey_T is new Block_128_Bit;
type PreKeys_T is Array (1 .. 4) of PreKey_T;
type Num_Rounds is range 1 .. 16;
type Context_T is record
W : PreKeys_T;
Rounds : Num_Rounds;
end record;
end ARIA_Spec;

29
src/algorithms/des/des.ads

@ -13,27 +13,18 @@
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with Block_Cipher_Generic;
with Crypto_Core_Types; use Crypto_Core_Types;
with Crypto_Types; use Crypto_Types;
with DES_Spec;
use Crypto_Types.Crypto_Types_u8;
use Crypto_Types.Crypto_Types_u32;
use Crypto_Types.Crypto_Utils_u8;
package DES is
package DES is new Block_Cipher_Generic( Name_Intern => "DES",
Context_T_Intern => DES_Spec.Context_T,
Block_Size_Bits_Intern => 64,
Key_Size_Bits_Intern => 64,
Initialize_Intern => DES_Spec.Initialize,
Encrypt_Intern => DES_Spec.Encrypt,
Decrypt_Intern => DES_Spec.Decrypt );
type Context_T is private;
subtype Key_T is Block_64_Bit;
subtype Block_T is Block_64_Bit;
procedure Initialize(Context : out Context_T; Key : in Key_T);
procedure Encrypt(Context : in Context_T; Block: in out Block_64_Bit);
procedure Decrypt(Context : in Context_T; Block: in out Block_64_Bit);
private
type Context_T is record
Key : Block_56_Bit;
end record;
end DES;

4
src/algorithms/des/des.adb → src/algorithms/des/des_spec.adb

@ -15,7 +15,7 @@
with System;
package body DES is
package body DES_Spec is
function SBox(X : Block_48_Bit) return Block_32_Bit is
function Map_To_Index(X : u8) return u8 is
@ -321,4 +321,4 @@ package body DES is
end;
end DES;
end DES_Spec;

39
src/algorithms/des/des_spec.ads

@ -0,0 +1,39 @@
-- Copyright (C) 2015 Daniel Otte <bg@nerilex.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with Crypto_Core_Types; use Crypto_Core_Types;
with Crypto_Types; use Crypto_Types;
use Crypto_Types.Crypto_Utils_u8;
use Crypto_Types.Crypto_Utils_u32;
package DES_Spec is
type Context_T is private;
subtype Key_T is Block_64_Bit;
subtype Block_T is Block_64_Bit;
procedure Initialize(Context : out Context_T; Key : in Key_T);
procedure Encrypt(Context : in Context_T; Block: in out Block_64_Bit);
procedure Decrypt(Context : in Context_T; Block: in out Block_64_Bit);
private
type Context_T is record
Key : Block_56_Bit;
end record;
end DES_Spec;

38
src/algorithms/des/tdes.ads

@ -13,31 +13,29 @@
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with Block_Cipher_Generic;
with Crypto_Core_Types; use Crypto_Core_Types;
with Crypto_Types; use Crypto_Types;
with TDES_Spec;
with DES;
use Crypto_Types.Crypto_Types_u8;
use Crypto_Types.Crypto_Types_u32;
use Crypto_Types.Crypto_Utils_u8;
package TDES is
type Context_T is private;
subtype Key_128_T is Block_128_Bit;
subtype Key_192_T is Block_192_Bit;
subtype Block_T is Block_64_Bit;
procedure Initialize(Context : out Context_T; Key : in u8_Array);
procedure Encrypt(Context : in Context_T; Block: in out Block_64_Bit);
procedure Decrypt(Context : in Context_T; Block: in out Block_64_Bit);
private
type Context_T is record
Ctx1 : DES.Context_T;
Ctx2 : DES.Context_T;
Ctx3 : DES.Context_T;
end record;
package TDES_Two_Key is new Block_Cipher_Generic( Name_Intern => "Triple-DES (two keys)",
Context_T_Intern => TDES_Spec.Context_T,
Block_Size_Bits_Intern => 64,
Key_Size_Bits_Intern => 128,
Initialize_Intern => TDES_Spec.Initialize,
Encrypt_Intern => TDES_Spec.Encrypt,
Decrypt_Intern => TDES_Spec.Decrypt );
package TDES_Three_Key is new Block_Cipher_Generic( Name_Intern => "Triple-DES (three keys)",
Context_T_Intern => TDES_Spec.Context_T,
Block_Size_Bits_Intern => 64,
Key_Size_Bits_Intern => 192,
Initialize_Intern => TDES_Spec.Initialize,
Encrypt_Intern => TDES_Spec.Encrypt,
Decrypt_Intern => TDES_Spec.Decrypt );
end TDES;

28
src/algorithms/des/tdes.adb → src/algorithms/des/tdes_spec.adb

@ -13,18 +13,18 @@
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
package body TDES is
package body TDES_Spec is
procedure Initialize(Context : out Context_T; Key : in u8_Array) is
begin
if Key'Length = 16 then
DES.Initialize(Context.Ctx1, Key(Key'First + 0 .. Key'First + 7));
DES.Initialize(Context.Ctx2, Key(Key'First + 8 .. Key'First + 15));
DES.Initialize(Context.Ctx3, Key(Key'First + 0 .. Key'First + 7));
DES_Spec.Initialize(Context.Ctx1, Key(Key'First + 0 .. Key'First + 7));
DES_Spec.Initialize(Context.Ctx2, Key(Key'First + 8 .. Key'First + 15));
DES_Spec.Initialize(Context.Ctx3, Key(Key'First + 0 .. Key'First + 7));
elsif Key'Length = 24 then
DES.Initialize(Context.Ctx1, Key(Key'First + 0 .. Key'First + 7));
DES.Initialize(Context.Ctx2, Key(Key'First + 8 .. Key'First + 15));
DES.Initialize(Context.Ctx3, Key(Key'First + 16 .. Key'First + 23));
DES_Spec.Initialize(Context.Ctx1, Key(Key'First + 0 .. Key'First + 7));
DES_Spec.Initialize(Context.Ctx2, Key(Key'First + 8 .. Key'First + 15));
DES_Spec.Initialize(Context.Ctx3, Key(Key'First + 16 .. Key'First + 23));
else
raise Invalid_Key_Size;
end if;
@ -32,16 +32,16 @@ package body TDES is
procedure Encrypt(Context : in Context_T; Block: in out Block_64_Bit) is
begin
DES.Encrypt(Context.Ctx1, Block);
DES.Decrypt(Context.Ctx2, Block);
DES.Encrypt(Context.Ctx3, Block);
DES_Spec.Encrypt(Context.Ctx1, Block);
DES_Spec.Decrypt(Context.Ctx2, Block);
DES_Spec.Encrypt(Context.Ctx3, Block);
end Encrypt;
procedure Decrypt(Context : in Context_T; Block: in out Block_64_Bit) is
begin
DES.Decrypt(Context.Ctx3, Block);
DES.Encrypt(Context.Ctx2, Block);
DES.Decrypt(Context.Ctx1, Block);
DES_Spec.Decrypt(Context.Ctx3, Block);
DES_Spec.Encrypt(Context.Ctx2, Block);
DES_Spec.Decrypt(Context.Ctx1, Block);
end Decrypt;
end TDES;
end TDES_Spec;

43
src/algorithms/des/tdes_spec.ads

@ -0,0 +1,43 @@
-- Copyright (C) 2015 Daniel Otte <bg@nerilex.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with Crypto_Core_Types; use Crypto_Core_Types;
with Crypto_Types; use Crypto_Types;
with DES_Spec;
use Crypto_Types.Crypto_Utils_u8;
use Crypto_Types.Crypto_Utils_u32;
package TDES_Spec is
type Context_T is private;
subtype Key_128_T is Block_128_Bit;
subtype Key_192_T is Block_192_Bit;
subtype Block_T is Block_64_Bit;
procedure Initialize(Context : out Context_T; Key : in u8_Array);
procedure Encrypt(Context : in Context_T; Block: in out Block_64_Bit);
procedure Decrypt(Context : in Context_T; Block: in out Block_64_Bit);
private
type Context_T is record
Ctx1 : DES_Spec.Context_T;
Ctx2 : DES_Spec.Context_T;
Ctx3 : DES_Spec.Context_T;
end record;
end TDES_Spec;

202
src/algorithms/gcm/gcm128_spec.adb

@ -0,0 +1,202 @@
-- Copyright (C) 2015 Daniel Otte <bg@nerilex.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with Crypto_Types; use Crypto_Types;
use Crypto_Types.Crypto_Utils_u8;
use Crypto_Types.Crypto_Utils_u32;
use Crypto_Types.Crypto_Utils_u64;
with System; use System;
with Ada.Text_IO; use Ada.Text_IO;
package body GCM128_Spec is
function GFmul(X,Y : Block_128_Bit) return Block_128_Bit is
Mask : constant array(Bit) of u8 := (0, 2#1110_0001#);
V : array (Bit) of Block_128_Bit := ( (others => 0), Y);
Z : Block_128_Bit := (others => 0);
Temp : Bit;
begin
for i in 0 .. 127 loop
Z := Z xor V(Bit_Get(X, i, High_Order_First));
Temp := Bit_Get(V(1), 127, High_Order_First);
V(1) := Shift_be(V(1), -1);
V(1)(1) := V(1)(1) xor Mask(Temp);
end loop;
return Z;
end GFmul;
function GHash(Key : in Block_128_Bit; Data : in u8_Array; Seed : Block_128_Bit := (others => 0)) return Block_128_Bit is
A : Block_128_Bit := Seed;
Index : Integer := Data'First;
Length : Integer := Data'Length * 8;
begin
-- for each complete block
for i in 1 .. Length / Block_Size_Bits loop
A := A xor Data(Index .. Index + Block_Size_Bytes - 1);
Index := Index + Block_Size_Bytes;
Length := Length - Block_Size_Bits;
A := GFmul(A, Key);
end loop;
if Length > 0 then
A(1 .. Length / 8) := A(1 .. Length / 8) xor Data(Index .. Index + Length / 8 - 1);
if Length mod 8 /= 0 then
A(Length / 8 + 1) := A(Length / 8 + 1) xor (Data(Index + Length / 8) and not Shift_Right(u8'(16#FF#), Length mod 8));
end if;
A := GFmul(A, Key);
end if;
return A;
end;
procedure Inc_32(A : in out Block_128_Bit) is
c : u32;
begin
c := Load_be(A(13 .. 16));
c := c + 1;
Store_be(A(13 .. 16), c);
end Inc_32;
procedure Initialize(Context : out Context_T; Key : in u8_Array; IV : in u8_Array) is
begin
Cipher.Initialize(Context.Cipher_Ctx, Key);
Context.Header_Length := 0;
Context.Plaintext_Length := 0;
Context.Y := (others => 0);
Context.H := (others => 0);
Cipher.Encrypt(Context.Cipher_Ctx, Context.H);
if IV'Length = 96 / 8 then
Context.J0( 1 .. 12) := IV;
Context.J0(13 .. 16) := (0, 0, 0, 1);
else
declare
IV_Length_Block : Block_64_Bit;
begin
Context.J0 := GHash(Context.H, IV);
Store_be(IV_Length_Block, u64(IV'Length * 8));
Context.J0(9 .. 16) := Context.J0(9 .. 16) xor IV_Length_Block;
Context.J0 := GHash(Context.H, Context.J0);
end;
end if;
Context.ICB := Context.J0;
-- encrypt J0 for final XOR on tag
Cipher.Encrypt(Context.Cipher_Ctx, Context.J0);
end Initialize;
procedure Header_Next_Block(Context : in out Context_T; Header : in u8_Array) is
begin
if Header'Length mod Block_Size_Bytes /= 0 then
raise Format_Violation;
end if;
Context.Y := GHash(Context.H, Header, Seed => Context.Y);
Context.Header_Length := Context.Header_Length + Header'Length * 8;
end;
procedure Header_Last_Block(Context : in out Context_T; Header : in u8_Array) is
begin
Context.Y := GHash(Context.H, Header, Seed => Context.Y);
Context.Header_Length := Context.Header_Length + Header'Length * 8;
end;
procedure Encrypt_Next_Block(Context : in out Context_T; Block : in out u8_Array) is
Temp : Block_128_Bit;
begin
if Block'Length /= Block_Size_Bytes then
raise Format_Violation;
end if;
Inc_32(Context.ICB);
Temp := Context.ICB;
Cipher.Encrypt(Context.Cipher_Ctx, Temp);
Block := Block xor Temp;
Context.Y := GHash(Context.H, Block, Seed => Context.Y);
Context.Plaintext_Length := Context.Plaintext_Length + u64(Block_Size_Bits);
end;
procedure Encrypt_Last_Block(Context : in out Context_T; Block : in out u8_Array) is
Length : Integer := Block'Length * 8;
Index : Integer := Block'First;
Temp : Block_128_Bit := (others => 0);
Fin_Block : Block_128_Bit;
begin
while Length >= Block_Size_Bits loop
Encrypt_Next_Block(Context, Block(Index .. Index + Block_Size_Bytes - 1));
Length := Length - Block_Size_Bits;
Index := Index + Block_Size_Bytes;
end loop;
if Length > 0 then
Inc_32(Context.ICB);
Temp := Context.ICB;
Cipher.Encrypt(Context.Cipher_Ctx, Temp);
Block(Index .. Index + (Length + 7) / 8 - 1) := Block(Index .. Index + (Length + 7) / 8 - 1) xor Temp(1 .. 1 + (Length + 7) / 8 - 1);
Context.Y := GHash(Context.H, Block(Index .. Index + (Length + 7) / 8 - 1), Seed => Context.Y);
Context.Plaintext_Length := Context.Plaintext_Length + u64(Length);
Put_Line("DBG: Trailing Length: " & Integer'Image(Length));
end if;
Store_be(Fin_Block(1 .. 8), Context.Header_Length);
Store_be(Fin_Block(9 .. 16), Context.Plaintext_Length);
Context.Y := GHash(Context.H, Fin_Block, Seed => Context.Y);
end;
procedure Decrypt_Next_Block(Context : in out Context_T; Block : in out u8_Array) is
Temp : Block_128_Bit;
begin
if Block'Length /= Block_Size_Bytes then
raise Format_Violation;
end if;
Context.Y := GHash(Context.H, Block, Seed => Context.Y);
Context.Plaintext_Length := Context.Plaintext_Length + u64(Block_Size_Bits);
Inc_32(Context.ICB);
Temp := Context.ICB;
Cipher.Encrypt(Context.Cipher_Ctx, Temp);
Block := Block xor Temp;
end;
procedure Decrypt_Last_Block(Context : in out Context_T; Block : in out u8_Array) is
Length : Integer := Block'Length * 8;
Index : Integer := Block'First;
Temp : Block_128_Bit := (others => 0);
Fin_Block : Block_128_Bit;
begin
while Length >= Block_Size_Bits loop
Decrypt_Next_Block(Context, Block(Index .. Index + Block_Size_Bytes - 1));
Length := Length - Block_Size_Bits;
Index := Index + Block_Size_Bytes;
end loop;
if Length > 0 then
Context.Y := GHash(Context.H, Block(Index .. Index + (Length + 7) / 8 - 1), Seed => Context.Y);
Context.Plaintext_Length := Context.Plaintext_Length + u64(Length);
Inc_32(Context.ICB);
Temp := Context.ICB;
Cipher.Encrypt(Context.Cipher_Ctx, Temp);
Block(Index .. Index + (Length + 7) / 8 - 1) := Block(Index .. Index + (Length + 7) / 8 - 1) xor Temp(1 .. 1 + (Length + 7) / 8 - 1);
end if;
Store_be(Fin_Block(1 .. 8), Context.Header_Length);
Store_be(Fin_Block(9 .. 16), Context.Plaintext_Length);
Context.Y := GHash(Context.H, Fin_Block, Seed => Context.Y);
end;
procedure Get_Tag(Context : in Context_T; Tag : out u8_Array) is
begin
Tag := Context.J0(1 .. Tag'Length) xor Context.Y(1 .. Tag'Length);
end Get_Tag;
function Is_Valid(Context : in Context_T; Tag : in u8_Array) return Boolean is
Is_Tag : u8_Array(Tag'Range);
begin
Get_Tag(Context, Is_Tag);
return Is_Tag = Tag;
end;
end GCM128_Spec;

50
src/algorithms/gcm/gcm128_spec.ads

@ -0,0 +1,50 @@
-- Copyright (C) 2015 Daniel Otte <bg@nerilex.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with Block_Cipher_Generic;
with Crypto_Core_Types; use Crypto_Core_Types;
generic
with package Cipher is new Block_Cipher_Generic(<>);
package GCM128_Spec is
type Context_T is private;
Key_Size_Bits : Natural := Cipher.Key_Size_Bits;
Block_Size_Bits : Natural := Cipher.Block_Size_Bits;
Key_Size_Bytes : Natural := Cipher.Key_Size_Bytes;
Block_Size_Bytes : Natural := Cipher.Block_Size_Bytes;
procedure Initialize(Context : out Context_T; Key : in u8_Array; IV : in u8_Array);
procedure Header_Next_Block(Context : in out Context_T; Header : in u8_Array);
procedure Header_Last_Block(Context : in out Context_T; Header : in u8_Array);
procedure Encrypt_Next_Block(Context : in out Context_T; Block : in out u8_Array);
procedure Encrypt_Last_Block(Context : in out Context_T; Block : in out u8_Array);
procedure Decrypt_Next_Block(Context : in out Context_T; Block : in out u8_Array);
procedure Decrypt_Last_Block(Context : in out Context_T; Block : in out u8_Array);
procedure Get_Tag(Context : in Context_T; Tag : out u8_Array);
function Is_Valid(Context : in Context_T; Tag : in u8_Array) return Boolean;
private
type Context_T is record
ICB, J0, H, Y : Block_128_Bit;
Header_Length : u64;
Plaintext_Length : u64;
Cipher_Ctx : Cipher.Context_T;
end record;
end GCM128_Spec;

363
src/algorithms/pi-cipher/pi16cipher_spec.adb

@ -0,0 +1,363 @@
-- Copyright (C) 2015 Daniel Otte <bg@nerilex.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with Crypto_Types; use Crypto_Types;
use Crypto_Types.Crypto_Utils_u16;
use Crypto_Types.Crypto_Utils_u64;
with System; use System;
with Ada.Text_IO; use Ada.Text_IO;
package body Pi16Cipher_Spec is
subtype Rotation_Ammount_T is Integer range 0 .. Word_T'Size - 1;
subtype Chunk_Index_T is Integer range Chunk_T'Range;
subtype Rate_Block is u8_Array(1 .. Rate_Bytes);
type Phi_Constants is array (1 .. 4) of Word_T;
type Phi_Rotation_Constants is array (1 .. 4) of Rotation_Ammount_T;
type Phi_V_Constants is array (1 .. 4) of Chunk_Index_T;
Mu_Constants : constant Phi_Constants := ( 16#F0E8#, 16#E4E2#, 16#E1D8#, 16#D4D2# );
Mu_Rotation_Constants : constant Phi_Rotation_Constants := ( 1, 4, 9, 11 );
Nu_Constants : constant Phi_Constants := ( 16#D1CC#, 16#CAC9#, 16#C6C5#, 16#C3B8# );
Nu_Rotation_Constants : constant Phi_Rotation_Constants := ( 2, 5, 7, 13 );
Mu_V_Constants : constant Phi_V_Constants := ( 4, 3, 2, 1 );
Nu_V_Constants : constant Phi_V_Constants := ( 2, 1, 4, 3 );
Pi_Constants : constant array (1 .. 2 * R) of Chunk_T :=
(
( 16#B4B2#, 16#B1AC#, 16#AAA9#, 16#A6A5# ),
( 16#A39C#, 16#9A99#, 16#9695#, 16#938E# ),
( 16#8D8B#, 16#8778#, 16#7472#, 16#716C# ),
( 16#6A69#, 16#6665#, 16#635C#, 16#5A59# ),
( 16#5655#, 16#534E#, 16#4D4B#, 16#473C# ),
( 16#3A39#, 16#3635#, 16#332E#, 16#2D2B# )
);
generic
Constants : Phi_Constants;
Rotation_Constants : Phi_Rotation_Constants;
V_Constants : Phi_V_Constants;
function Phi(Chunk : in Chunk_T) return Chunk_T;
function Phi(Chunk : in Chunk_T) return Chunk_T is
Ret : Chunk_T;
Sum : Word_T;
begin
Sum := 0 + Chunk;
for i in Chunk'Range loop
Ret(i) := Rotate_Left(Constants(i) + Sum - Chunk(V_Constants(i)), Rotation_Constants(i));
end loop;
Sum := 0 xor Ret;
Ret := Ret xor Sum;
return Ret;
end Phi;
function Nu is new Phi (Constants => Nu_Constants, Rotation_Constants => Nu_Rotation_Constants, V_Constants => Nu_V_Constants);
function Mu(Chunk : Chunk_T) return Chunk_T is
function foo is new Phi (Constants => Mu_Constants, Rotation_Constants => Mu_Rotation_Constants, V_Constants => Mu_V_Constants);
Ret : Chunk_T;
begin
Ret := foo(Chunk);
Ret := Rotate_Array_Left(Ret, 2);
return Ret;
end Mu;
function "*" (X : Chunk_T; Y : Chunk_T) return Chunk_T is
Ret : Chunk_T;
begin
Ret := Mu(X) + Nu(Y);
Ret := Rotate_Array_Left(Ret, 1);
return Ret;
end "*";
function E1 (C : Chunk_T; I : State_T) return State_T is
J : State_T;
begin
J(1) := C * I(1);
for index in 2 .. N loop
J(index) := J(index - 1) * I(index);
end loop;
return J;
end E1;
function E2 (C : Chunk_T; I : State_T) return State_T is
J : State_T;
begin
J(N) := I(N) * C;
for index in reverse 1 .. N - 1 loop
J(index) := I(index) * J(index + 1);
end loop;
return J;
end E2;
function Pi (State : State_T) return State_T is
Ret : State_T := State;
begin
for round in 0 .. R - 1 loop
Ret := E1(Pi_Constants(2 * round + 1), Ret);
Ret := E2(Pi_Constants(2 * round + 2), Ret);
end loop;
return Ret;
end Pi;
procedure Dump(State : in State_T) is
begin
Put_Line("State:");
for i in State'Range loop
Put(" [ ");
for j in State(i)'Range loop
Put(To_Hex(State(i)(j)));
Put(' ');
end loop;
Put_Line("]");
end loop;
end;
procedure Initialize(Context : out Context_T; Key : in u8_Array; Public_Nonce : in u8_Array) is
Scratch : u8_Array(1 .. IS_Bytes) := (others => 0);
Index : Integer := Scratch'First;
begin
if Key'Length + Public_Nonce'Length >= Scratch'Length then
raise Invalid_Key_Size;
end if;
Context.Tag := (others => 0);
Scratch(1 .. Key'Length) := Key;
Scratch(Key'Length + 1 .. Key'Length + Public_Nonce'Length) := Public_Nonce;
Scratch(Key'Length + Public_Nonce'Length + 1) := 1;
for i in Context.State'Range loop
Context.State(i) := Load_LE(Scratch(Index .. Index + Chunk_T'Length * Word_T'Size / 8 - 1));
Index := Index + Chunk_T'Length * Word_T'Size / 8;
end loop;
Context.State := pi(Context.State);
Context.Counter := 0;
for i in 1 .. 64 / Word_T'Size loop
Context.Counter := Context.Counter or Shift_Left(u64(Context.State(2)(i)), (i - 1) * Word_T'Size);
end loop;
end Initialize;
function "+" (Context : Context_T; Block_Number : Block_Number_T) return State_T is
Counter : u64 := Context.Counter + u64(Block_Number);
Ret : State_T := Context.State;
begin
for i in 1 .. 64 / Word_T'Size loop
Ret(1)(i) := Ret(1)(i) xor Word_T( Counter and (Shift_Left(u64'(1), Word_T'Size) - 1));
Counter := Shift_Right(Counter, Word_T'Size);
end loop;
return Ret;
end "+";
function Extract(State : State_T) return Rate_Block is
Data : Rate_Block;
Index : Positive := Data'First;
begin
for i in 0 .. N / 2 - 1 loop
Store_LE(Data(Index .. Index + 4 * Word_T'Size / 8 - 1), State(2 * i + 1));
Index := Index + 4 * Word_T'Size / 8;
end loop;
return Data;
end Extract;
function Extract(State : State_T) return Tag_Int_T is
Tag : Tag_Int_T;
begin
for i in 0 .. N / 2 - 1 loop
Tag(Tag'First + i * 4 .. Tag'First + i * 4 + 3) := State(2 * i + 1);
end loop;
return Tag;
end Extract;
function "xor" (State : State_T; Data : Rate_Block) return State_T is
Ret : State_T := State;
Index : Positive := Data'First;
begin
for i in 0 .. N / 2 - 1 loop
Ret(2 * i + 1) := Ret(2 * i + 1) xor Chunk_T'(Load_LE(Data(Index .. Index + 4 * Word_T'Size / 8 - 1)));
Index := Index + 4 * Word_T'Size / 8;
end loop;
return Ret;
end "xor";
function "xor" (State : State_T; Tag : Tag_Int_T) return State_T is
Ret : State_T := State;
Index : Positive := Tag'First;
begin
for i in 0 .. N / 2 - 1 loop
Ret(2 * i + 1) := Ret(2 * i + 1) xor Tag(Index .. Index + 3);
Index := Index + 4;
end loop;
return Ret;
end "xor";
function set (State : State_T; Data : Rate_Block) return State_T is
Ret : State_T := State;
Index : Positive := Data'First;
begin
for i in 0 .. N / 2 - 1 loop
Ret(2 * i + 1) := Chunk_T'(Load_LE(Data(Index .. Index + 4 * Word_T'Size / 8 - 1)));
Index := Index + 4 * Word_T'Size / 8;
end loop;
return Ret;
end set;
function "+" (Tag : Tag_Int_T) return Tag_T is
Ret : Tag_T;
begin
Store_LE(Ret, Tag);
return Ret;
end "+";
function Pad (Data : u8_Array) return Block_T is
Ret : Block_T := (others => 0);
begin
if Data'Length >= Block_T'Length then
raise Constraint_Error;
end if;
Ret(Ret'First .. Ret'First + Data'Length -1 ) := Data;
Ret(Ret'First + Data'Length) := 1;
return Ret;
end Pad;
procedure Process_Header_Block (Context : in out Context_T; Block : Block_T; Block_Number : Block_Number_T) is
begin
Context.Tag := Context.Tag + Extract(Pi(Pi(Context + Block_Number) xor Block));
end Process_Header_Block;
procedure Process_Header_Last_Block (Context : in out Context_T; Block : u8_Array; Block_Number : Block_Number_T) is
Num : Block_Number_T := Block_Number;
Index : Integer := Block'First;
begin
for i in 1 .. Block'Length / Block_Bytes loop
Process_Header_Block(Context, Block(Index .. Index + Block_Bytes - 1), Num);
Num := Num + 1;
Index := Index + Block_Bytes;
end loop;
Process_Header_Block(Context, Pad(Block(Index .. Block'Last)), Num);
Context.State := Pi(Context.State xor Context.Tag);
Context.Counter := Context.Counter + u64(Num);
end Process_Header_Last_Block;
procedure Encrypt_Secret_Message_Number(Context : in out Context_T; Block : in out Block_T) is
State : constant State_T := Pi(Context + Block_Number_T'(1)) xor Block;
begin
Block := Extract(State);
Context.State := Pi(State);
Context.Tag := Context.Tag + Extract(Context.State);
Context.Counter := Context.Counter + 1;
end Encrypt_Secret_Message_Number;
procedure Decrypt_Secret_Message_Number(Context : in out Context_T; Block : in out Block_T) is
State : constant State_T := Pi(Context + Block_Number_T'(1)) xor Block;
Block_In : constant Block_T := Block;
begin
Block := Extract(State);
Context.State := Pi(set(State, Block_In));
Context.Tag := Context.Tag + Extract(Context.State);
Context.Counter := Context.Counter + 1;
end Decrypt_Secret_Message_Number;
procedure Encrypt_Block(Context : in out Context_T; Block : in out Block_T; Block_Number : Block_Number_T) is
State : State_T := Pi(Context + Block_Number) xor Block;
begin
Block := Extract(State);
State := Pi(State);
Context.Tag := Context.Tag + Extract(State);
end Encrypt_Block;
procedure Decrypt_Block(Context : in out Context_T; Block : in out Block_T; Block_Number : Block_Number_T) is
State : State_T := Pi(Context + Block_Number) xor Block;
In_Block : constant Block_T := Block;
begin
Block := Extract(State);
State := Pi(set(State, In_Block));
Context.Tag := Context.Tag + Extract(State);
end Decrypt_Block;
procedure Encrypt_Last_Block(Context : in out Context_T; Block : in out u8_Array; Block_Number : Block_Number_T) is
State : State_T;
Index : Integer := Block'First;
Num : Block_Number_T := Block_Number;
Temp_Block : Block_T;
begin
for i in 1 .. Block'Length / Block_Bytes loop
Encrypt_Block(Context, Block(Index .. Index + Block_Bytes - 1), Num);
Index := Index + Block_Bytes;
Num := Num + 1;
end loop;
Temp_Block := Pad(Block(Index .. Block'Last));
State := Pi(Context + Num) xor Temp_Block;
Temp_Block := Extract(State);
Block(Index .. Block'Last) := Temp_Block(Temp_Block'First .. Temp_Block'First + Block'Last - Index);
State := Pi(State);
Context.Tag := Context.Tag + Extract(State);
end Encrypt_Last_Block;
procedure Decrypt_Last_Block(Context : in out Context_T; Block : in out u8_Array; Block_Number : Block_Number_T) is
State : State_T;
Index : Integer := Block'First;
Num : Block_Number_T := Block_Number;
Temp_Block : Block_T;
begin
for i in 1 .. Block'Length / Block_Bytes loop
Decrypt_Block(Context, Block(Index .. Index + Block_Bytes - 1), Num);
Index := Index + Block_Bytes;
Num := Num + 1;
end loop;
Temp_Block := Pad(Block(Index .. Block'Last));
State := Pi(Context + Num) xor Temp_Block;
Block(Index .. Block'Last) := Extract(State)(Temp_Block'First .. Temp_Block'First + Block'Last - Index);
Temp_Block(Temp_Block'First + Block'Last - Index + 1 .. Temp_Block'Last) := Extract(State)(Temp_Block'First + Block'Last - Index + 1 .. Temp_Block'Last);
State := Pi(set(State, Temp_Block));
Context.Tag := Context.Tag + Extract(State);
end Decrypt_Last_Block;
function Get_Tag(Context : Context_T) return Tag_T is
begin
return +Context.Tag;
end Get_Tag;
function Encrypt(Msg : u8_Array; AD : u8_Array; Public_Nonce : u8_Array; Secret_Nonce : Block_T; Key : u8_Array) return u8_Array is
Crypt : u8_Array(1 .. Secret_Nonce'Length + Msg'Length + Tag_Bytes);
Ctx : Context_T;
begin
Initialize(Context => Ctx, Key => Key, Public_Nonce => Public_Nonce);
Process_Header_Last_Block(Context => Ctx, Block => AD, Block_Number => 1);
Crypt(Crypt'First .. Crypt'First + Secret_Message_Number_Bytes - 1) := Secret_Nonce;
Crypt(Crypt'First + Secret_Message_Number_Bytes .. Crypt'Last - Tag_Bytes) := Msg;
Encrypt_Secret_Message_Number(Context => Ctx, Block => Crypt(Crypt'First .. Crypt'First + Secret_Message_Number_Bytes - 1));
Encrypt_Last_Block(Context => Ctx, Block => Crypt(Crypt'First + Secret_Message_Number_Bytes .. Crypt'Last - Tag_Bytes), Block_Number => 1);
Crypt(Crypt'Last - Tag_Bytes + 1 .. Crypt'Last) := Get_Tag(Ctx);
return Crypt;
end Encrypt;
procedure Decrypt(Is_Valid : out Boolean; Msg : out u8_Array; Secret_Nonce : out Block_T; Cipher : in u8_Array; AD : in u8_Array; Public_Nonce : in u8_Array; Key : in u8_Array) is
Tag : Tag_T;
Ctx : Context_T;
begin
Initialize(Context => Ctx, Key => Key, Public_Nonce => Public_Nonce);
Process_Header_Last_Block(Context => Ctx, Block => AD, Block_Number => 1);
Secret_Nonce := Cipher(Cipher'First .. Cipher'First + Secret_Message_Number_Bytes - 1);
Msg := Cipher(Cipher'First + Secret_Message_Number_Bytes .. Cipher'Last - Tag_Bytes);
Decrypt_Secret_Message_Number(Context => Ctx, Block => Secret_Nonce);
Decrypt_Last_Block(Context => Ctx, Block => Msg, Block_Number => 1);
Tag := Get_Tag(Ctx);
Is_Valid := Tag = Cipher(Cipher'Last - Tag_Bytes + 1 .. Cipher'Last);
end Decrypt;
end Pi16Cipher_Spec;

75
src/algorithms/pi-cipher/pi16cipher_spec.ads

@ -0,0 +1,75 @@
-- Copyright (C) 2015 Daniel Otte <bg@nerilex.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of