diff --git a/src/block_cipher/aes/aes.adb b/src/block_cipher/aes/aes.adb index a5cbdca..2083f46 100644 --- a/src/block_cipher/aes/aes.adb +++ b/src/block_cipher/aes/aes.adb @@ -1,5 +1,67 @@ +-- Copyright (C) 2015 Daniel Otte +-- +-- 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 . + + +with Ada.Text_IO; use Ada.Text_IO; +-- with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; + package body AES is + sbox : constant u8_Array(0 .. 255) := ( + 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#, + 16#ca#, 16#82#, 16#c9#, 16#7d#, 16#fa#, 16#59#, 16#47#, 16#f0#, 16#ad#, 16#d4#, 16#a2#, 16#af#, 16#9c#, 16#a4#, 16#72#, 16#c0#, + 16#b7#, 16#fd#, 16#93#, 16#26#, 16#36#, 16#3f#, 16#f7#, 16#cc#, 16#34#, 16#a5#, 16#e5#, 16#f1#, 16#71#, 16#d8#, 16#31#, 16#15#, + 16#04#, 16#c7#, 16#23#, 16#c3#, 16#18#, 16#96#, 16#05#, 16#9a#, 16#07#, 16#12#, 16#80#, 16#e2#, 16#eb#, 16#27#, 16#b2#, 16#75#, + 16#09#, 16#83#, 16#2c#, 16#1a#, 16#1b#, 16#6e#, 16#5a#, 16#a0#, 16#52#, 16#3b#, 16#d6#, 16#b3#, 16#29#, 16#e3#, 16#2f#, 16#84#, + 16#53#, 16#d1#, 16#00#, 16#ed#, 16#20#, 16#fc#, 16#b1#, 16#5b#, 16#6a#, 16#cb#, 16#be#, 16#39#, 16#4a#, 16#4c#, 16#58#, 16#cf#, + 16#d0#, 16#ef#, 16#aa#, 16#fb#, 16#43#, 16#4d#, 16#33#, 16#85#, 16#45#, 16#f9#, 16#02#, 16#7f#, 16#50#, 16#3c#, 16#9f#, 16#a8#, + 16#51#, 16#a3#, 16#40#, 16#8f#, 16#92#, 16#9d#, 16#38#, 16#f5#, 16#bc#, 16#b6#, 16#da#, 16#21#, 16#10#, 16#ff#, 16#f3#, 16#d2#, + 16#cd#, 16#0c#, 16#13#, 16#ec#, 16#5f#, 16#97#, 16#44#, 16#17#, 16#c4#, 16#a7#, 16#7e#, 16#3d#, 16#64#, 16#5d#, 16#19#, 16#73#, + 16#60#, 16#81#, 16#4f#, 16#dc#, 16#22#, 16#2a#, 16#90#, 16#88#, 16#46#, 16#ee#, 16#b8#, 16#14#, 16#de#, 16#5e#, 16#0b#, 16#db#, + 16#e0#, 16#32#, 16#3a#, 16#0a#, 16#49#, 16#06#, 16#24#, 16#5c#, 16#c2#, 16#d3#, 16#ac#, 16#62#, 16#91#, 16#95#, 16#e4#, 16#79#, + 16#e7#, 16#c8#, 16#37#, 16#6d#, 16#8d#, 16#d5#, 16#4e#, 16#a9#, 16#6c#, 16#56#, 16#f4#, 16#ea#, 16#65#, 16#7a#, 16#ae#, 16#08#, + 16#ba#, 16#78#, 16#25#, 16#2e#, 16#1c#, 16#a6#, 16#b4#, 16#c6#, 16#e8#, 16#dd#, 16#74#, 16#1f#, 16#4b#, 16#bd#, 16#8b#, 16#8a#, + 16#70#, 16#3e#, 16#b5#, 16#66#, 16#48#, 16#03#, 16#f6#, 16#0e#, 16#61#, 16#35#, 16#57#, 16#b9#, 16#86#, 16#c1#, 16#1d#, 16#9e#, + 16#e1#, 16#f8#, 16#98#, 16#11#, 16#69#, 16#d9#, 16#8e#, 16#94#, 16#9b#, 16#1e#, 16#87#, 16#e9#, 16#ce#, 16#55#, 16#28#, 16#df#, + 16#8c#, 16#a1#, 16#89#, 16#0d#, 16#bf#, 16#e6#, 16#42#, 16#68#, 16#41#, 16#99#, 16#2d#, 16#0f#, 16#b0#, 16#54#, 16#bb#, 16#16# + ); + + + rcon : constant u8_Array(1 .. 10) := ( + 16#01#, 16#02#, 16#04#, 16#08#, 16#10#, 16#20#, 16#40#, 16#80#, 16#1b#, 16#36# + ); + + procedure print_hex(value : in u8) is + hex_table : constant array (0 .. 15) of Character := + ( '0', '1', '2', '3', + '4', '5', '6', '7', + '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f'); + begin + Put(hex_table(Integer(Shift_Right(value, 4)))); + Put(hex_table(Integer(value and 16#F#))); + end; + + procedure print_hex(value : in u8_Array) is + begin + for i in value'Range loop + print_hex(value(i)); + Put(" "); + end loop; + end; + function gf256mul(a, b : u8) return u8 is r : u8 := 0; t1 : u8 := a; @@ -18,4 +80,146 @@ package body AES is return r; end gf256mul; + function RotWord(A : u8_Array) return u8_Array is + begin + return Rotate_be(A, 8); + end; + + function SubArray(A : u8_Array) return u8_Array is + r : u8_Array(A'Range); + begin + for i in A'Range loop + r(i) := sbox(Natural(A(i))); + end loop; + return r; + end; + + function Initialize(Key : Key_128) return Context_128 is + Ret : Context_128; + w : u8_Array(1 .. Ret.Roundkeys'Length * RoundKey_T'Length); + temp : u8_Array(1 .. 4); + Nk : Constant := Key'Length / 4; + k : Integer range rcon'First .. rcon'Last + 1 := 1; + j : Integer range w'First .. w'Last + 1 := 1; + begin + New_Line; + Put("== Debug =="); + New_Line; + + w(1 .. Key'Length) := u8_Array(Key); + for i in 1 + Key'Length / 4 .. Ret.RoundKeys'Length * RoundKey_T'Length / 4 loop + temp := w((i - 1) * 4 - 3 .. (i - 1) * 4); + print_hex(temp); + if (i - 1) mod Nk = 0 then + temp := SubArray(RotWord(temp)); + Put(" - "); + print_hex(temp); + temp(1) := temp(1) xor rcon(k); + k := k + 1; + Put(" - "); + print_hex(temp); + end if; + temp := temp xor w((i - Nk) * 4 - 3 .. (i - Nk) * 4); + Put(" - "); + print_hex(temp); + w(i * 4 - 3 .. i * 4) := temp; + New_Line; + end loop; + for i in Ret.RoundKeys'Range loop + Ret.RoundKeys(i) := RoundKey_T(w(j .. j + RoundKey_T'Length - 1)); + j := j + RoundKey_T'Length; + end loop; + return Ret; + end Initialize; + + function Initialize(Key : Key_192) return Context_192 is + Ret : Context_192; + w : u8_Array(1 .. Ret.Roundkeys'Length * RoundKey_T'Length); + temp : u8_Array(1 .. 4); + Nk : Constant := Key'Length / 4; + k : Integer range rcon'First .. rcon'Last + 1 := 1; + j : Integer range w'First .. w'Last + 1 := 1; + begin + New_Line; + Put("== Debug =="); + New_Line; + + w(1 .. Key'Length) := u8_Array(Key); + for i in 1 + Key'Length / 4 .. Ret.RoundKeys'Length * RoundKey_T'Length / 4 loop + temp := w((i - 1) * 4 - 3 .. (i - 1) * 4); + print_hex(temp); + if (i - 1) mod Nk = 0 then + temp := SubArray(RotWord(temp)); + Put(" - "); + print_hex(temp); + temp(1) := temp(1) xor rcon(k); + k := k + 1; + Put(" - "); + print_hex(temp); + end if; + temp := temp xor w((i - Nk) * 4 - 3 .. (i - Nk) * 4); + Put(" - "); + print_hex(temp); + w(i * 4 - 3 .. i * 4) := temp; + New_Line; + end loop; + for i in Ret.RoundKeys'Range loop + Ret.RoundKeys(i) := RoundKey_T(w(j .. j + RoundKey_T'Length - 1)); + j := j + RoundKey_T'Length; + end loop; + return Ret; + end Initialize; + + function Initialize(Key : Key_256) return Context_256 is + Ret : Context_256; + w : u8_Array(1 .. Ret.Roundkeys'Length * RoundKey_T'Length); + temp : u8_Array(1 .. 4); + Nk : Constant := Key'Length / 4; + k : Integer range rcon'First .. rcon'Last + 1 := 1; + j : Integer range w'First .. w'Last + 1 := 1; + begin + New_Line; + Put("== Debug =="); + New_Line; + + w(1 .. Key'Length) := u8_Array(Key); + for i in 1 + Key'Length / 4 .. Ret.RoundKeys'Length * RoundKey_T'Length / 4 loop + temp := w((i - 1) * 4 - 3 .. (i - 1) * 4); + print_hex(temp); + if (i - 1) mod Nk = 0 then + temp := SubArray(RotWord(temp)); + Put(" - "); + print_hex(temp); + temp(1) := temp(1) xor rcon(k); + k := k + 1; + Put(" - "); + print_hex(temp); + else if Nk > 6 and then (i - 1) mod Nk = 4 then + temp := SubArray(temp); + end if; + end if; + temp := temp xor w((i - Nk) * 4 - 3 .. (i - Nk) * 4); + Put(" - "); + print_hex(temp); + w(i * 4 - 3 .. i * 4) := temp; + New_Line; + end loop; + for i in Ret.RoundKeys'Range loop + Ret.RoundKeys(i) := RoundKey_T(w(j .. j + RoundKey_T'Length - 1)); + j := j + RoundKey_T'Length; + end loop; + return Ret; + end Initialize; + +-- function Encrypt(Ctx : Context_128; Source : Plaintext) return Ciphertext; +-- function Decrypt(Ctx : Context_128; Source : Ciphertext) return Plaintext; +-- +-- function Initialize(Key : Key_192) return Context_192; +-- function Encrypt(Ctx : Context_192; Source : Plaintext) return Ciphertext; +-- function Decrypt(Ctx : Context_192; Source : Ciphertext) return Plaintext; +-- +-- function Initialize(Key : Key_256) return Context_256; +-- function Encrypt(Ctx : Context_256; Source : Plaintext) return Ciphertext; +-- function Decrypt(Ctx : Context_256; Source : Ciphertext) return Plaintext; + end AES; diff --git a/src/block_cipher/aes/aes.ads b/src/block_cipher/aes/aes.ads index c23d3f6..7b5c13a 100644 --- a/src/block_cipher/aes/aes.ads +++ b/src/block_cipher/aes/aes.ads @@ -1,8 +1,67 @@ +-- Copyright (C) 2015 Daniel Otte +-- +-- 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 . + +with Crypto_Core_Types; use Crypto_Core_Types; with Crypto_Types; use Crypto_Types; +use Crypto_Types.Crypto_Types_u8; + package AES 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_128 is private; + -- type Context_192 is private; + -- type Context_256 is private; + + type Plaintext is new Block_128_Bit; + type Ciphertext is new Block_128_Bit; + + + type RoundKey_T is new Block_128_Bit; + type RoundKeys_T is Array (Integer range <>) of RoundKey_T; + + type Context_128 is record + RoundKeys : RoundKeys_T(1 .. 11); + end record; + + type Context_192 is record + RoundKeys : RoundKeys_T(1 .. 13); + end record; + + type Context_256 is record + RoundKeys : RoundKeys_T(1 .. 15); + end record; + + function Initialize(Key : Key_128) return Context_128; +-- function Encrypt(Ctx : Context_128; Source : Plaintext) return Ciphertext; +-- function Decrypt(Ctx : Context_128; Source : Ciphertext) return Plaintext; +-- + function Initialize(Key : Key_192) return Context_192; +-- function Encrypt(Ctx : Context_192; Source : Plaintext) return Ciphertext; +-- function Decrypt(Ctx : Context_192; Source : Ciphertext) return Plaintext; +-- + function Initialize(Key : Key_256) return Context_256; +-- function Encrypt(Ctx : Context_256; Source : Plaintext) return Ciphertext; +-- function Decrypt(Ctx : Context_256; Source : Ciphertext) return Plaintext; + private + + Nb : constant Integer := 4; polynom : constant u8 := 16#1B#; function gf256mul(a, b : u8) return u8; end AES; diff --git a/src/crypto_core_types.ads b/src/crypto_core_types.ads index e935fb7..4535020 100644 --- a/src/crypto_core_types.ads +++ b/src/crypto_core_types.ads @@ -39,4 +39,18 @@ package Crypto_Core_Types is type u32_Array_Access is access all u32_Array; type u64_Array_Access is access all u64_Array; + subtype Block_64_Bit is u8_Array(1 .. 64 / 8); + subtype Block_96_Bit is u8_Array(1 .. 96 / 8); + subtype Block_128_Bit is u8_Array(1 .. 128 / 8); + subtype Block_192_Bit is u8_Array(1 .. 192 / 8); + subtype Block_256_Bit is u8_Array(1 .. 256 / 8); + subtype Block_384_Bit is u8_Array(1 .. 384 / 8); + subtype Block_512_Bit is u8_Array(1 .. 512 / 8); + subtype Block_768_Bit is u8_Array(1 .. 768 / 8); + subtype Block_1024_Bit is u8_Array(1 .. 1024 / 8); + subtype Block_1536_Bit is u8_Array(1 .. 1536 / 8); + subtype Block_2084_Bit is u8_Array(1 .. 2048 / 8); + + Wrong_Opertaion_Order : exception; + end Crypto_Core_Types; diff --git a/src/crypto_generic_types.adb b/src/crypto_generic_types.adb index 0131ad1..94292c8 100644 --- a/src/crypto_generic_types.adb +++ b/src/crypto_generic_types.adb @@ -204,17 +204,17 @@ package body Crypto_Generic_Types is return r; end "-"; - procedure Rotate_Array_Left(A : T_Array_Access; Amount : Natural) is - b : T; - begin - for i in 1 .. Amount loop - b := A(A'First); - for j in A'First .. A'Last - 1 loop - A(j) := A(j + 1); - end loop; - A(A'Last) := b; - end loop; - end; +-- procedure Rotate_Array_Left(A : T_Array_Access; Amount : Natural) is +-- b : T; +-- begin +-- for i in 1 .. Amount loop +-- b := A(A'First); +-- for j in A'First .. A'Last - 1 loop +-- A(j) := A(j + 1); +-- end loop; +-- A(A'Last) := b; +-- end loop; +-- end; function Rotate_Array_Left(A : T_Array; Amount : Natural) return T_Array is r : T_Array(A'Range); diff --git a/src/crypto_generic_types.ads b/src/crypto_generic_types.ads index c1e79ef..0918b73 100644 --- a/src/crypto_generic_types.ads +++ b/src/crypto_generic_types.ads @@ -20,9 +20,9 @@ with Crypto_Core_Types; use Crypto_Core_Types; -- -------------------------- generic - type T is mod <>; + type T is mod <>; - with function Shift_Left + with function Shift_Left (Value : T; Amount : Natural) return T is <>; @@ -47,7 +47,6 @@ generic -- -------------------------- package Crypto_Generic_Types is - -- compare two array with timing independent of content -- function "="(Left, Right : T_Array ) return Boolean; -- xor each element on the left with the corresponding element on the right diff --git a/src/crypto_types.ads b/src/crypto_types.ads index 90cbafe..815473a 100644 --- a/src/crypto_types.ads +++ b/src/crypto_types.ads @@ -16,11 +16,24 @@ with Crypto_Generic_Types; with Crypto_Core_Types; use Crypto_Core_Types; +with Ada.Direct_IO; +with Ada.Sequential_IO; + package Crypto_Types is - package Crypto_Types_u8 is new Crypto_Generic_Types(T => u8, T_Array => u8_Array, T_Array_Access => u8_Array_Access); + package Crypto_Types_u8 is new Crypto_Generic_Types(T => u8, T_Array => u8_Array, T_Array_Access => u8_Array_Access); package Crypto_Types_u16 is new Crypto_Generic_Types(T => u16, T_Array => u16_Array, T_Array_Access => u16_Array_Access); package Crypto_Types_u32 is new Crypto_Generic_Types(T => u32, T_Array => u32_Array, T_Array_Access => u32_Array_Access); package Crypto_Types_u64 is new Crypto_Generic_Types(T => u64, T_Array => u64_Array, T_Array_Access => u64_Array_Access); + package u8_Direct_IO is new Ada.Direct_IO(u8); + package u16_Direct_IO is new Ada.Direct_IO(u16); + package u32_Direct_IO is new Ada.Direct_IO(u32); + package u64_Direct_IO is new Ada.Direct_IO(u64); + + package u8_Sequential_IO is new Ada.Sequential_IO(u8); + package u16_Sequential_IO is new Ada.Sequential_IO(u16); + package u32_Sequential_IO is new Ada.Sequential_IO(u32); + package u64_Sequential_IO is new Ada.Sequential_IO(u64); + end Crypto_Types; diff --git a/src/main.adb b/src/main.adb index 7aa8012..1aa828b 100644 --- a/src/main.adb +++ b/src/main.adb @@ -14,72 +14,147 @@ -- along with this program. If not, see . with Ada.Text_IO; use Ada.Text_IO; +with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; with Crypto_Core_Types; use Crypto_Core_Types; with Crypto_Types; use Crypto_Types; -with Spritz; + +with Spritz_Stream; +with Spritz_Hash; + +with AES; + use Crypto_Types.Crypto_Types_u8; procedure main is +-- package u8_IO is new Crypto_Types.u8_Sequential_IO; procedure print_hex(value : in u8) is hex_table : constant array (0 .. 15) of Character := ( '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', - 'C', 'D', 'E', 'F'); + '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f'); begin Put(hex_table(Integer(Shift_Right(value, 4)))); Put(hex_table(Integer(value and 16#F#))); end; - procedure test_spritz(s : in String) is - ctx : Spritz.Context; - z : u8; + procedure print_hex(value : in u8_Array) is begin - Spritz.InitializeContext(ctx); - Spritz.Absorb(ctx, s); + for i in value'Range loop + print_hex(value(i)); + Put(" "); + end loop; + end; + + procedure test_spritz_stream(s : in String) is + ctx : Spritz_Stream.Context; + z : u8_Array(1 .. 8) := (others => 0); + begin + Spritz_Stream.Initialize(ctx, key => s); Put(s); for i in 0 .. 6 - s'Length loop Put(" "); end loop; Put(": "); - for j in 0 .. 7 loop - Spritz.Drip(ctx, z); - print_hex(z); - Put(" "); - end loop; + Spritz_Stream.Encrypt(ctx, z); + print_hex(z); New_Line; - end test_spritz; + end test_spritz_stream; procedure test_spritz_hash(s : in String) is - ctx : Spritz.Context; - z : u8; + ctx : Spritz_Hash.Context; + hash : u8_Array(1 .. 32); begin - Spritz.InitializeContext(ctx); - Spritz.Absorb(ctx, s); - Spritz.AbsorbStop(ctx); - Spritz.Absorb(ctx, u8(32)); + Spritz_Hash.Initialize(ctx); + Spritz_Hash.Add_Data(ctx, s); + Spritz_Hash.Extract_Hash(ctx => ctx, Hash => hash); Put(s); for i in 0 .. 6 - s'Length loop Put(" "); end loop; Put(": "); - for j in 0 .. 7 loop - Spritz.Drip(ctx, z); - print_hex(z); - Put(" "); - end loop; + print_hex(hash(1 .. 8)); New_Line; end test_spritz_hash; + procedure test_aes_schedule(key : u8_Array) is + Ctx : AES.Context_128; + begin + Ctx := AES.Initialize(AES.Key_128(key)); + for i in Ctx.RoundKeys'Range loop + Put("RoundKey "); + Put(i); + Put(": "); + print_hex(u8_Array(Ctx.RoundKeys(i))); + New_Line; + end loop; + New_Line; + end test_aes_schedule; + + procedure test_aes_schedule192(key : u8_Array) is + Ctx : AES.Context_192; + begin + Ctx := AES.Initialize(AES.Key_192(key)); + for i in Ctx.RoundKeys'Range loop + Put("RoundKey "); + Put(i); + Put(": "); + print_hex(u8_Array(Ctx.RoundKeys(i))); + New_Line; + end loop; + New_Line; + end test_aes_schedule192; + + procedure test_aes_schedule256(key : u8_Array) is + Ctx : AES.Context_256; + begin + Ctx := AES.Initialize(AES.Key_256(key)); + for i in Ctx.RoundKeys'Range loop + Put("RoundKey "); + Put(i); + Put(": "); + print_hex(u8_Array(Ctx.RoundKeys(i))); + New_Line; + end loop; + New_Line; + end test_aes_schedule256; + + +-- Random_File : File_Type; begin - test_spritz("ABC"); - test_spritz("spam"); - test_spritz("arcfour"); + test_spritz_stream("ABC"); + test_spritz_stream("spam"); + test_spritz_stream("arcfour"); New_Line; test_spritz_hash("ABC"); test_spritz_hash("spam"); test_spritz_hash("arcfour"); New_Line; + + test_aes_schedule(u8_Array'( + 16#2b#, 16#7e#, 16#15#, 16#16#, + 16#28#, 16#ae#, 16#d2#, 16#a6#, + 16#ab#, 16#f7#, 16#15#, 16#88#, + 16#09#, 16#cf#, 16#4f#, 16#3c# )); + + test_aes_schedule192(u8_Array'( + 16#8e#, 16#73#, 16#b0#, 16#f7#, + 16#da#, 16#0e#, 16#64#, 16#52#, + 16#c8#, 16#10#, 16#f3#, 16#2b#, + 16#80#, 16#90#, 16#79#, 16#e5#, + 16#62#, 16#f8#, 16#ea#, 16#d2#, + 16#52#, 16#2c#, 16#6b#, 16#7b# )); + + test_aes_schedule256(u8_Array'( + 16#60#, 16#3d#, 16#eb#, 16#10#, + 16#15#, 16#ca#, 16#71#, 16#be#, + 16#2b#, 16#73#, 16#ae#, 16#f0#, + 16#85#, 16#7d#, 16#77#, 16#81#, + 16#1f#, 16#35#, 16#2c#, 16#07#, + 16#3b#, 16#61#, 16#08#, 16#d7#, + 16#2d#, 16#98#, 16#10#, 16#a3#, + 16#09#, 16#14#, 16#df#, 16#f4# )); + end main;