diff --git a/src/algorithms/des/des.adb b/src/algorithms/des/des.adb new file mode 100644 index 0000000..db04d91 --- /dev/null +++ b/src/algorithms/des/des.adb @@ -0,0 +1,324 @@ +-- 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 System; + +package body DES is + + function SBox(X : Block_48_Bit) return Block_32_Bit is + function Map_To_Index(X : u8) return u8 is + i, j : u8; + begin + i := X and 2#10_0001#; + i := (i or Shift_Right(i, 4)) and 3; + j := Shift_Right(X and 2#01_1110#, 1); + return i * 16 + j; + end; + + + box : constant array (1 .. 8, 0 .. 31) of u8 := + ( + ( -- S-box 1 + 16#E4#, 16#D1#, 16#2F#, 16#B8#, 16#3A#, 16#6C#, 16#59#, 16#07#, + 16#0F#, 16#74#, 16#E2#, 16#D1#, 16#A6#, 16#CB#, 16#95#, 16#38#, + 16#41#, 16#E8#, 16#D6#, 16#2B#, 16#FC#, 16#97#, 16#3A#, 16#50#, + 16#FC#, 16#82#, 16#49#, 16#17#, 16#5B#, 16#3E#, 16#A0#, 16#6D# + ), + ( -- S-box 2 + 16#F1#, 16#8E#, 16#6B#, 16#34#, 16#97#, 16#2D#, 16#C0#, 16#5A#, + 16#3D#, 16#47#, 16#F2#, 16#8E#, 16#C0#, 16#1A#, 16#69#, 16#B5#, + 16#0E#, 16#7B#, 16#A4#, 16#D1#, 16#58#, 16#C6#, 16#93#, 16#2F#, + 16#D8#, 16#A1#, 16#3F#, 16#42#, 16#B6#, 16#7C#, 16#05#, 16#E9# + ), + (-- S-box 3 + 16#A0#, 16#9E#, 16#63#, 16#F5#, 16#1D#, 16#C7#, 16#B4#, 16#28#, + 16#D7#, 16#09#, 16#34#, 16#6A#, 16#28#, 16#5E#, 16#CB#, 16#F1#, + 16#D6#, 16#49#, 16#8F#, 16#30#, 16#B1#, 16#2C#, 16#5A#, 16#E7#, + 16#1A#, 16#D0#, 16#69#, 16#87#, 16#4F#, 16#E3#, 16#B5#, 16#2C# + ), + (-- S-box 4 + 16#7D#, 16#E3#, 16#06#, 16#9A#, 16#12#, 16#85#, 16#BC#, 16#4F#, + 16#D8#, 16#B5#, 16#6F#, 16#03#, 16#47#, 16#2C#, 16#1A#, 16#E9#, + 16#A6#, 16#90#, 16#CB#, 16#7D#, 16#F1#, 16#3E#, 16#52#, 16#84#, + 16#3F#, 16#06#, 16#A1#, 16#D8#, 16#94#, 16#5B#, 16#C7#, 16#2E# + ), + (-- S-box 5 + 16#2C#, 16#41#, 16#7A#, 16#B6#, 16#85#, 16#3F#, 16#D0#, 16#E9#, + 16#EB#, 16#2C#, 16#47#, 16#D1#, 16#50#, 16#FA#, 16#39#, 16#86#, + 16#42#, 16#1B#, 16#AD#, 16#78#, 16#F9#, 16#C5#, 16#63#, 16#0E#, + 16#B8#, 16#C7#, 16#1E#, 16#2D#, 16#6F#, 16#09#, 16#A4#, 16#53# + ), + (-- S-box 6 + 16#C1#, 16#AF#, 16#92#, 16#68#, 16#0D#, 16#34#, 16#E7#, 16#5B#, + 16#AF#, 16#42#, 16#7C#, 16#95#, 16#61#, 16#DE#, 16#0B#, 16#38#, + 16#9E#, 16#F5#, 16#28#, 16#C3#, 16#70#, 16#4A#, 16#1D#, 16#B6#, + 16#43#, 16#2C#, 16#95#, 16#FA#, 16#BE#, 16#17#, 16#60#, 16#8D# + ), + (-- S-box 7 + 16#4B#, 16#2E#, 16#F0#, 16#8D#, 16#3C#, 16#97#, 16#5A#, 16#61#, + 16#D0#, 16#B7#, 16#49#, 16#1A#, 16#E3#, 16#5C#, 16#2F#, 16#86#, + 16#14#, 16#BD#, 16#C3#, 16#7E#, 16#AF#, 16#68#, 16#05#, 16#92#, + 16#6B#, 16#D8#, 16#14#, 16#A7#, 16#95#, 16#0F#, 16#E2#, 16#3C# + ), + (-- S-box 8 + 16#D2#, 16#84#, 16#6F#, 16#B1#, 16#A9#, 16#3E#, 16#50#, 16#C7#, + 16#1F#, 16#D8#, 16#A3#, 16#74#, 16#C5#, 16#6B#, 16#0E#, 16#92#, + 16#7B#, 16#41#, 16#9C#, 16#E2#, 16#06#, 16#AD#, 16#F3#, 16#58#, + 16#21#, 16#E7#, 16#4A#, 16#8D#, 16#FC#, 16#90#, 16#35#, 16#6B# + ) + ); + temp : u8_Array(1 .. 8); + idx : u8; + ret : Block_32_Bit; + begin + temp(1) := Shift_Right(X(1), 2); + temp(2) := (Shift_Left(X(1), 4) or Shift_Right(X(2), 4)) and 16#3F#; + temp(3) := (Shift_Left(X(2), 2) or Shift_Right(X(3), 6)) and 16#3F#; + temp(4) := X(3) and 16#3F#; + temp(5) := Shift_Right(X(4), 2); + temp(6) := (Shift_Left(X(4), 4) or Shift_Right(X(5), 4)) and 16#3F#; + temp(7) := (Shift_Left(X(5), 2) or Shift_Right(X(6), 6)) and 16#3F#; + temp(8) := X(6) and 16#3F#; + for i in temp'Range loop + idx := Map_To_Index(temp(i)); + temp(i) := box(i, Integer(idx / 2)); + if idx mod 2 = 0 then + temp(i) := Shift_Right(temp(i), 4); + else + temp(i) := temp(i) and 16#0F#; + end if; + end loop; + for i in 0..3 loop + ret(i + 1) := Shift_Left(temp(2 * i + 1), 4) or temp(2 * i + 2); + end loop; + return ret; + end SBox; + + + subtype Bit_Index_T is Integer range 1 .. 64; + type Bit_Index_Table_T is array (Bit_Index_T range <>) of Bit_Index_T; + + type Permutation_Table_T(Out_Bits : Bit_Index_T) is record + In_Bits : Bit_Index_T; + Table : Bit_Index_Table_T(1 .. Out_Bits); + end record; + + E_Table : constant Permutation_Table_T := + ( In_Bits => 32, + Out_Bits => 48, + Table => + ( + 32, 1, 2, 3, 4, 5, + 4, 5, 6, 7, 8, 9, + 8, 9, 10, 11, 12, 13, + 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, + 20, 21, 22, 23, 24, 25, + 24, 25, 26, 27, 28, 29, + 28, 29, 30, 31, 32, 1 + ) + ); + + P_Table : constant Permutation_Table_T := + ( In_Bits => 32, + Out_Bits => 32, + Table => + ( + 16, 7, 20, 21, + 29, 12, 28, 17, + 1, 15, 23, 26, + 5, 18, 31, 10, + 2, 8, 24, 14, + 32, 27, 3, 9, + 19, 13, 30, 6, + 22, 11, 4, 25 + ) + ); + + IP_Table : constant Permutation_Table_T := + ( In_Bits => 64, + Out_Bits => 64, + Table => + ( + 58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, + 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7 + ) + ); + + FP_Table : constant Permutation_Table_T := + ( In_Bits => 64, + Out_Bits => 64, + Table => + ( + 40, 8, 48, 16, 56, 24, 64, 32, + 39, 7, 47, 15, 55, 23, 63, 31, + 38, 6, 46, 14, 54, 22, 62, 30, + 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, + 35, 3, 43, 11, 51, 19, 59, 27, + 34, 2, 42, 10, 50, 18, 58, 26, + 33, 1, 41, 9, 49, 17, 57, 25 + ) + ); + + PC1_Table : constant Permutation_Table_T := + ( In_Bits => 64, + Out_Bits => 56, + Table => + ( + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 + ) + ); + + PC2_Table : constant Permutation_Table_T := + ( In_Bits => 56, + Out_Bits => 48, + Table => + ( + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 + ) + ); + + Round_Shifts : constant array(1 .. 16) of u8 := + ( 1, 1, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 1 ); + + procedure Permute(Out_Buffer : out u8_Array; In_Buffer : in u8_Array; Table : in Permutation_Table_T) is + use system; + begin + if Out_Buffer'Length /= Table.Out_Bits / 8 then + raise Constraint_Error; + end if; + if In_Buffer'Length /= Table.In_Bits / 8 then + raise Constraint_Error; + end if; + for i in Table.Table'Range loop + Bit_Set(Out_Buffer, i - 1, Bit_Get(In_Buffer, Table.Table(i) - 1, High_Order_First), High_Order_First); + end loop; + end Permute; + + function F(X : Block_32_Bit; Round_Key : Block_48_Bit) return Block_32_Bit is + temp_48 : Block_48_Bit; + temp_32, ret : Block_32_Bit; + begin + Permute(temp_48, X, E_Table); + temp_48 := temp_48 xor Round_Key; + temp_32 := SBox(temp_48); + Permute(ret, temp_32, P_Table); + return ret; + end F; + + procedure Initialize(Context : out Context_T; Key : in Key_T) is + begin + Permute(Context.Key, u8_Array(Key), PC1_Table); + end; + + procedure RoundKey_Step(Key : in out Block_56_Bit; Steps : in Positive; Backwards : Boolean := False) is + C, D : u32; + begin + C := Shift_Left( + Shift_Left( + Shift_Left( + u32(Key(1)), 8) + or u32(Key(2)), 8) + or u32(Key(3)), 4) + or u32(Shift_Right(Key(4), 4)); + D := Shift_Left( + Shift_Left( + Shift_Left( + u32(Key(4) and 16#0F#), 8) + or u32(Key(5)), 8) + or u32(Key(6)), 8) + or u32(Key(7)); + if Backwards = False then + C := Shift_Left(C, Steps); + D := Shift_Left(D, Steps); + C := ( C or Shift_Right(C, 28)) and 16#0FFF_FFFF#; + D := ( D or Shift_Right(D, 28)) and 16#0FFF_FFFF#; + else + C := Rotate_Right(C, Steps); + D := Rotate_Right(D, Steps); + C := C or (Shift_Right((C and 16#C0000000#), 4) and not 16#F000_0000#); + D := D or (Shift_Right((D and 16#C0000000#), 4) and not 16#F000_0000#); + end if; + Key(1) := u8(Shift_Right(C, 20) and 16#FF#); + Key(2) := u8(Shift_Right(C, 12) and 16#FF#); + Key(3) := u8(Shift_Right(C, 4) and 16#FF#); + Key(4) := u8(Shift_Left(C, 4) and 16#F0#) or u8(Shift_Right(D, 24) and 16#0F#); + Key(5) := u8(Shift_Right(D, 16) and 16#FF#); + Key(6) := u8(Shift_Right(D, 8) and 16#FF#); + Key(7) := u8(D and 16#FF#); + end; + + + procedure Encrypt(Context : in Context_T; Block: in out Block_64_Bit) is + Key : Block_56_Bit := Context.Key; + Round_Key : Block_48_Bit; + Data : Block_64_Bit; + begin + Permute(Data, Block, IP_Table); + for Round in 0 .. 7 loop + RoundKey_Step(Key, Integer(Round_Shifts(1 + 2 * Round))); + Permute(Round_Key, Key, PC2_Table); + Data(1 .. 4) := Data(1 .. 4) xor F(Data(5 .. 8), Round_Key); + RoundKey_Step(Key, Integer(Round_Shifts(2 + 2 * Round))); + Permute(Round_Key, Key, PC2_Table); + Data(5 .. 8) := Data(5 .. 8) xor F(Data(1 .. 4), Round_Key); + end loop; + Swap(Data(1 .. 4), Data(5 .. 8)); + Permute(Block, Data, FP_Table); + end; + + + procedure Decrypt(Context : in Context_T; Block: in out Block_64_Bit) is + Key : Block_56_Bit := Context.Key; + Round_Key : Block_48_Bit; + Data : Block_64_Bit; + begin + Permute(Data, Block, IP_Table); + for Round in reverse 0 .. 7 loop + Permute(Round_Key, Key, PC2_Table); + Data(1 .. 4) := Data(1 .. 4) xor F(Data(5 .. 8), Round_Key); + RoundKey_Step(Key, Integer(Round_Shifts(2 + 2 * Round)), Backwards => True); + Permute(Round_Key, Key, PC2_Table); + Data(5 .. 8) := Data(5 .. 8) xor F(Data(1 .. 4), Round_Key); + RoundKey_Step(Key, Integer(Round_Shifts(1 + 2 * Round)), Backwards => True); + end loop; + Swap(Data(1 .. 4), Data(5 .. 8)); + Permute(Block, Data, FP_Table); + end; + + +end DES; diff --git a/src/algorithms/des/des.ads b/src/algorithms/des/des.ads new file mode 100644 index 0000000..aec8eff --- /dev/null +++ b/src/algorithms/des/des.ads @@ -0,0 +1,39 @@ +-- 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; +use Crypto_Types.Crypto_Types_u32; + +package DES 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; diff --git a/src/algorithms/des/tdes.adb b/src/algorithms/des/tdes.adb new file mode 100644 index 0000000..f938134 --- /dev/null +++ b/src/algorithms/des/tdes.adb @@ -0,0 +1,47 @@ +-- 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 . + +package body TDES 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)); + 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)); + else + raise Invalid_Key_Size; + end if; + end; + + 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); + 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); + end Decrypt; + +end TDES; diff --git a/src/algorithms/des/tdes.ads b/src/algorithms/des/tdes.ads new file mode 100644 index 0000000..2ee38d5 --- /dev/null +++ b/src/algorithms/des/tdes.ads @@ -0,0 +1,43 @@ +-- 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; + +with DES; + +use Crypto_Types.Crypto_Types_u8; +use Crypto_Types.Crypto_Types_u32; + +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; + +end TDES;