Browse Source

generic update + PiCipherV2

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

+ 49
- 0
src/abstraction/block_cipher_generic.ads View File

@@ -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
- 0
src/abstraction/hash_generic.adb View File

@@ -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
- 0
src/abstraction/hash_generic.ads View File

@@ -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;

+ 26
- 47
src/algorithms/aes/aes.ads View File

@@ -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;

src/algorithms/aes/aes.adb → src/algorithms/aes/aes_spec.adb View File

@@ -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
- 0
src/algorithms/aes/aes_spec.ads View File

@@ -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;

+ 26
- 29
src/algorithms/aria/aria.ads View File

@@ -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;

src/algorithms/aria/aria.adb → src/algorithms/aria/aria_spec.adb View File

@@ -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
- 0
src/algorithms/aria/aria_spec.ads View File

@@ -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;

+ 10
- 19
src/algorithms/des/des.ads View File

@@ -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;

src/algorithms/des/des.adb → src/algorithms/des/des_spec.adb View File

@@ -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
- 0
src/algorithms/des/des_spec.ads View File

@@ -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;

+ 18
- 20
src/algorithms/des/tdes.ads View File

@@ -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;

src/algorithms/des/tdes.adb → src/algorithms/des/tdes_spec.adb View File

@@ -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
- 0
src/algorithms/des/tdes_spec.ads View File

@@ -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
- 0
src/algorithms/gcm/gcm128_spec.adb View File

@@ -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
- 0
src/algorithms/gcm/gcm128_spec.ads View File

@@ -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
- 0
src/algorithms/pi-cipher/pi16cipher_spec.adb View File

@@ -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
- 0
src/algorithms/pi-cipher/pi16cipher_spec.ads View File

@@ -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 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;

package Pi16Cipher_Spec is

type Context_T is private;

Cipher_Name : constant String := "pi16cipher";
Width_Bits : constant := 16;

N : constant := 4;
R : constant := 3;

IS_Bits : constant := (N * 4 * Width_Bits);
IS_Bytes : constant := IS_Bits / 8;
Rate_Bits : constant := IS_Bits / 2;
Rate_Bytes : constant := Rate_Bits / 8;
Capacity_Bits : constant := IS_Bits - Rate_Bits;
Capacity_Bytes : constant := Capacity_Bits / 8;
Block_Bits : constant := Rate_Bits;
Block_Bytes : constant := Block_Bits / 8;
Tag_Bits : constant := Rate_Bits;
Tag_Bytes : constant := Tag_Bits / 8;
Secret_Message_Number_Bits : constant := Block_Bits;
Secret_Message_Number_Bytes : constant := Secret_Message_Number_Bits / 8;

subtype Block_Number_T is Natural;

subtype Block_T is u8_Array (1 .. Rate_Bytes);

procedure Initialize(Context : out Context_T; Key : in u8_Array; Public_Nonce : in u8_Array);
-- procedure Encrypt_Secret_Message_Number(Context : in out Context; Secret_Message_Number : 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;

function Encrypt(Msg : u8_Array; AD : u8_Array; Public_Nonce : u8_Array; Secret_Nonce : Block_T; Key : u8_Array) return u8_Array;
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);


private

subtype Word_T is u16;
subtype Chunk_T is u16_Array(1 .. 4);
subtype Tag_Int_T is u16_Array(1 .. 4 * N / 2);
subtype Tag_T is u8_Array(1 .. Rate_Bytes);

type State_T is array (1 .. N) of Chunk_T;

type Context_T is record
State : State_T;
Tag : Tag_Int_T;
Counter : u64;
end record;

end Pi16Cipher_Spec;

+ 363
- 0
src/algorithms/pi-cipher/pi32cipher_spec.adb View File

@@ -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_u32;
use Crypto_Types.Crypto_Utils_u64;
with System; use System;

with Ada.Text_IO; use Ada.Text_IO;

package body Pi32Cipher_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#F0E8E4E2#, 16#E1D8D4D2#, 16#D1CCCAC9#, 16#C6C5C3B8# );
Mu_Rotation_Constants : constant Phi_Rotation_Constants := ( 5, 11, 17, 23 );
Nu_Constants : constant Phi_Constants := ( 16#B4B2B1AC#, 16#AAA9A6A5#, 16#A39C9A99#, 16#9695938E# );
Nu_Rotation_Constants : constant Phi_Rotation_Constants := ( 3, 10, 19, 29 );

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#8D8B8778#, 16#7472716C#, 16#6A696665#, 16#635C5A59# ),
( 16#5655534E#, 16#4D4B473C#, 16#3A393635#, 16#332E2D2B# ),
( 16#271E1D1B#, 16#170FF0E8#, 16#E4E2E1D8#, 16#D4D2D1CC# ),
( 16#CAC9C6C5#, 16#C3B8B4B2#, 16#B1ACAAA9#, 16#A6A5A39C# ),
( 16#9A999695#, 16#938E8D8B#, 16#87787472#, 16#716C6A69# ),
( 16#6665635C#, 16#5A595655#, 16#534E4D4B#, 16#473C3A39# )
);

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 Pi32Cipher_Spec;


+ 75
- 0
src/algorithms/pi-cipher/pi32cipher_spec.ads View File

@@ -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 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;

package Pi32Cipher_Spec is

type Context_T is private;

Cipher_Name : constant String := "pi32cipher";
Width_Bits : constant := 32;

N : constant := 4;
R : constant := 3;

IS_Bits : constant := (N * 4 * Width_Bits);
IS_Bytes : constant := IS_Bits / 8;
Rate_Bits : constant := IS_Bits / 2;
Rate_Bytes : constant := Rate_Bits / 8;
Capacity_Bits : constant := IS_Bits - Rate_Bits;
Capacity_Bytes : constant := Capacity_Bits / 8;
Block_Bits : constant := Rate_Bits;
Block_Bytes : constant := Block_Bits / 8;
Tag_Bits : constant := Rate_Bits;
Tag_Bytes : constant := Tag_Bits / 8;
Secret_Message_Number_Bits : constant := Block_Bits;
Secret_Message_Number_Bytes : constant := Secret_Message_Number_Bits / 8;

subtype Block_Number_T is Natural;

subtype Block_T is u8_Array (1 .. Rate_Bytes);

procedure Initialize(Context : out Context_T; Key : in u8_Array; Public_Nonce : in u8_Array);
-- procedure Encrypt_Secret_Message_Number(Context : in out Context; Secret_Message_Number : 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;

function Encrypt(Msg : u8_Array; AD : u8_Array; Public_Nonce : u8_Array; Secret_Nonce : Block_T; Key : u8_Array) return u8_Array;
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);


private

subtype Word_T is u32;
subtype Chunk_T is u32_Array(1 .. 4);
subtype Tag_Int_T is u32_Array(1 .. 4 * N / 2);
subtype Tag_T is u8_Array(1 .. Rate_Bytes);

type State_T is array (1 .. N) of Chunk_T;

type Context_T is record
State : State_T;
Tag : Tag_Int_T;
Counter : u64;
end record;

end Pi32Cipher_Spec;

+ 371
- 0
src/algorithms/pi-cipher/pi64cipher_spec.adb View File

@@ -0,0 +1,371 @@
-- 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 Pi64Cipher_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#F0E8E4E2E1D8D4D2#,
16#D1CCCAC9C6C5C3B8#,
16#B4B2B1ACAAA9A6A5#,
16#A39C9A999695938E# );

Mu_Rotation_Constants : constant Phi_Rotation_Constants := ( 7, 19, 31, 53 );
Nu_Constants : constant Phi_Constants := ( 16#8D8B87787472716C#,
16#6A696665635C5A59#,
16#5655534E4D4B473C#,
16#3A393635332E2D2B# );
Nu_Rotation_Constants : constant Phi_Rotation_Constants := ( 11, 23, 37, 59 );

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#271E1D1B170FF0E8#, 16#E4E2E1D8D4D2D1CC#, 16#CAC9C6C5C3B8B4B2#, 16#B1ACAAA9A6A5A39C# ),
( 16#9A999695938E8D8B#, 16#87787472716C6A69#, 16#6665635C5A595655#, 16#534E4D4B473C3A39# ),
( 16#3635332E2D2B271E#, 16#1D1B170FF0E8E4E2#, 16#E1D8D4D2D1CCCAC9#, 16#C6C5C3B8B4B2B1AC# ),
( 16#AAA9A6A5A39C9A99#, 16#9695938E8D8B8778#, 16#7472716C6A696665#, 16#635C5A595655534E# ),
( 16#4D4B473C3A393635#, 16#332E2D2B271E1D1B#, 16#170FF0E8E4E2E1D8#, 16#D4D2D1CCCAC9C6C5# ),
( 16#C3B8B4B2B1ACAAA9#, 16#A6A5A39C9A999695#, 16#938E8D8B87787472#, 16#716C6A696665635C# )
);

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