From 23059ef0c3477c77941fdec2a7accb2c12d1556e Mon Sep 17 00:00:00 2001 From: bg Date: Sat, 15 Aug 2015 04:58:52 +0200 Subject: [PATCH] adding SHA3 --- src/algorithms/sha3/host_tools/iota.rb | 26 ++++ src/algorithms/sha3/host_tools/rho.rb | 9 ++ src/algorithms/sha3/keccak.adb | 150 ++++++++++++++++++++++ src/algorithms/sha3/keccak.ads | 35 +++++ src/algorithms/sha3/keccak_parameters.ads | 36 ++++++ src/algorithms/sha3/sha3.ads | 25 ++++ src/algorithms/sha3/sha3_generic.adb | 137 ++++++++++++++++++++ src/algorithms/sha3/sha3_generic.ads | 64 +++++++++ 8 files changed, 482 insertions(+) create mode 100644 src/algorithms/sha3/host_tools/iota.rb create mode 100644 src/algorithms/sha3/host_tools/rho.rb create mode 100644 src/algorithms/sha3/keccak.adb create mode 100644 src/algorithms/sha3/keccak.ads create mode 100644 src/algorithms/sha3/keccak_parameters.ads create mode 100644 src/algorithms/sha3/sha3.ads create mode 100644 src/algorithms/sha3/sha3_generic.adb create mode 100644 src/algorithms/sha3/sha3_generic.ads diff --git a/src/algorithms/sha3/host_tools/iota.rb b/src/algorithms/sha3/host_tools/iota.rb new file mode 100644 index 0000000..32d2c1d --- /dev/null +++ b/src/algorithms/sha3/host_tools/iota.rb @@ -0,0 +1,26 @@ + +def lfsr(i) + x = 0x80; + i.times { + v = x & 1; + x = x >> 1; + if v == 1 + x = x ^ 0x8e; + end + } + return x >> 7; +end + + +def rc(r) + a = 0; + 7.times { |j| + t = lfsr(j + 7 * r); + a |= t << ((1< +-- +-- 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; + +package body Keccak is + +-- procedure Print_State(A : State_T; S : String := "" ) is +-- c : Natural := 1; +-- l : u8_Array(1 .. 8); +-- begin +-- if S'Length > 0 then +-- Put_Line(S); +-- end if; +-- for i in y_T'Range loop +-- for j in x_T'Range loop +-- Store_le(A => l, +-- value => A(j, i)); +-- for z in l'Range loop +-- Put(To_Hex(l(z))); +-- Put(' '); +-- if c mod 16 = 0 then +-- New_Line; +-- end if; +-- c := c + 1; +-- end loop; +-- end loop; +-- end loop; +-- New_Line; +-- end; + + procedure theta( A : in out State_T ) is + C : Array (x_T) of Word_T; + D : Array (x_T) of Word_T; + begin + for i in x_T'Range loop + C(i) := A(i, 0) xor A(i, 1) xor A(i, 2) xor A(i, 3) xor A(i, 4); + end loop; + for i in x_T'Range loop + D(i) := C(i - 1) xor Rotate_Left(C(i + 1), 1); + end loop; + for i in x_T'Range loop + for j in y_T'Range loop + A(i, j) := A(i, j) xor D(i); + end loop; + end loop; + end theta; + + procedure rho( A : in out State_T ) is + Rotation_Table : constant Array (x_T, y_T) of z_T := + ( + ( 0, 36, 3, 41, 18 ), + ( 1, 44, 10, 45, 2 ), + ( 62, 6, 43, 15, 61 ), + ( 28, 55, 25, 21, 56 ), + ( 27, 20, 39, 8, 14 ) + ); + begin + for i in x_T'Range loop + for j in y_T'Range loop + A(i, j) := Rotate_Left(A(i, j), Integer(Rotation_Table(i, j))); + end loop; + end loop; + end rho; + + procedure pi( A : in out State_T ) is + Ax : constant State_T := A; + begin + for i in x_T'Range loop + for j in y_T'Range loop + A(i, j) := Ax(i + 3 * x_T(j), y_T(i)); + end loop; + end loop; + end pi; + + procedure chi( A : in out State_T ) is + Ax : constant State_T := A; + begin + for i in x_T'Range loop + for j in y_T'Range loop + A(i, j) := A(i, j) xor ((not Ax(i + 1, j)) and Ax(i + 2, j)); + end loop; + end loop; + end chi; + + procedure iota( A : in out State_T; round : Natural ) is + Round_Constants : constant Array(1 .. rounds) of Word_T := + ( + 16#0000000000000001#, -- round 1 + 16#0000000000008082#, -- round 2 + 16#800000000000808a#, -- round 3 + 16#8000000080008000#, -- round 4 + 16#000000000000808b#, -- round 5 + 16#0000000080000001#, -- round 6 + 16#8000000080008081#, -- round 7 + 16#8000000000008009#, -- round 8 + 16#000000000000008a#, -- round 9 + 16#0000000000000088#, -- round 10 + 16#0000000080008009#, -- round 11 + 16#000000008000000a#, -- round 12 + 16#000000008000808b#, -- round 13 + 16#800000000000008b#, -- round 14 + 16#8000000000008089#, -- round 15 + 16#8000000000008003#, -- round 16 + 16#8000000000008002#, -- round 17 + 16#8000000000000080#, -- round 18 + 16#000000000000800a#, -- round 19 + 16#800000008000000a#, -- round 20 + 16#8000000080008081#, -- round 21 + 16#8000000000008080#, -- round 22 + 16#0000000080000001#, -- round 23 + 16#8000000080008008# -- round 24 + ); + begin + A(0, 0) := A(0, 0) xor Round_Constants(round); + end iota; + + procedure Permute ( A : in out State_T ) is + begin +-- Print_State(A, "### Initial state:"); + for i in 1 .. rounds loop +-- Put_Line("## Round " & Integer'Image(i) & ":"); + theta(A); +-- Print_State(A, "After Theta:"); + rho(A); +-- Print_State(A, "After Rho:"); + pi(A); +-- Print_State(A, "After Pi:"); + chi(A); +-- Print_State(A, "After Chi:"); + iota(A, i); +-- Print_State(A, "After Iota:"); + end loop; + end Permute; + +end Keccak; + + diff --git a/src/algorithms/sha3/keccak.ads b/src/algorithms/sha3/keccak.ads new file mode 100644 index 0000000..7a250e1 --- /dev/null +++ b/src/algorithms/sha3/keccak.ads @@ -0,0 +1,35 @@ +-- 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 Keccak_Parameters; use Keccak_Parameters; + +use Crypto_Types.Crypto_Types_u8; +use Crypto_Types.Crypto_Types_u64; + +package Keccak is + + type State_T is Array (x_T, y_T) of Word_T; + + procedure Permute(A : in out State_T); + +private + + rounds : constant := 12 + 2 * l; + +end Keccak; + + diff --git a/src/algorithms/sha3/keccak_parameters.ads b/src/algorithms/sha3/keccak_parameters.ads new file mode 100644 index 0000000..463015b --- /dev/null +++ b/src/algorithms/sha3/keccak_parameters.ads @@ -0,0 +1,36 @@ +-- 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_u64; + +package Keccak_Parameters is + + subtype Word_T is u64; + w : constant := 64; + l : constant := 6; + b : constant := 25 * w; + subtype Capacity_T is Natural range 0 .. b; + subtype Capacity_Bytes_T is Natural range 0 .. b / 8; + type x_T is mod 5; + type y_T is mod 5; + type z_T is mod w; + +end Keccak_Parameters; + + diff --git a/src/algorithms/sha3/sha3.ads b/src/algorithms/sha3/sha3.ads new file mode 100644 index 0000000..1673dca --- /dev/null +++ b/src/algorithms/sha3/sha3.ads @@ -0,0 +1,25 @@ +-- 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 SHA3_Generic; + +package SHA3 is + + package SHA3_224 is new SHA3_Generic(Capacity_Bits => 448); + package SHA3_256 is new SHA3_Generic(Capacity_Bits => 512); + package SHA3_384 is new SHA3_Generic(Capacity_Bits => 768); + package SHA3_512 is new SHA3_Generic(Capacity_Bits => 1024); + +end SHA3; diff --git a/src/algorithms/sha3/sha3_generic.adb b/src/algorithms/sha3/sha3_generic.adb new file mode 100644 index 0000000..065985d --- /dev/null +++ b/src/algorithms/sha3/sha3_generic.adb @@ -0,0 +1,137 @@ +-- 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 Sha3_Generic is + + procedure Initialize(Context : out Context_T) is + begin + Context.A := (others => (others => 0)); + end Initialize; + + procedure Next_Block(Context : in out Context_T; Block : in Block_T) is + temp : u64; + begin + for i in 0 .. Rate_Bytes / 8 - 1 loop + temp := Load_le(Block(Block'First + i * 8 .. Block'First + i * 8 + 7)); + Context.A(x_T(i mod 5), y_T(i / 5)) := Context.A(x_T(i mod 5), y_T(i / 5)) xor temp; + end loop; + Permute(Context.A); + end Next_Block; + + procedure Append_Bit(Context : in out Context_T; Index : in out Capacity_T; Value : in Bit) is + begin + Context.A(x_t((Index / w) mod 5), y_t(Index / w / 5)) := Context.A(x_t((Index / w) mod 5), y_t(Index / w / 5)) xor Shift_Left(Word_T(Value), Index mod w); + Index := Index + 1; + if Index = Rate_Bits then + Permute(Context.A); + Index := 0; + end if; + end Append_Bit; + + procedure Append_Byte(Context : in out Context_T; Index : in out Capacity_T; Value : in u8) is + begin + if Index mod 8 /= 0 then + raise Constraint_Error; + end if; + Context.A(x_t((Index / w) mod 5), y_t(Index / w / 5)) := Context.A(x_t((Index / w) mod 5), y_t(Index / w / 5)) xor Shift_Left(Word_T(Value), Index mod w); + Index := Index + 8; + if Index = Rate_Bits then + Permute(Context.A); + Index := 0; + end if; + end Append_Byte; + + procedure Last_Block(Context : in out Context_T; Block : in u8_Array; Bits : in Integer := -1) is + Length : Natural; + Index : Integer := Block'First; + Dest_Index : Natural := 0; + begin + if Bits < 0 then + Length := Block'Length * 8; + else + Length := Bits; + end if; + while Length >= Rate_Bits loop + Next_Block(Context, Block(Index .. Index + Rate_Bytes - 1)); + Index := Index + Rate_Bytes; + Length := Length - Rate_bits; + end loop; + -- append trailing bytes + while Length >= 8 loop + Append_Byte(Context, Dest_Index, Block(Index)); + Index := Index + 1; + Length := Length - 8; + end loop; + -- append trailing bits + for j in 0 .. Length - 1 loop + Append_Bit(Context, Dest_Index, Bit(Shift_Right(Block(Index), j) mod 2)); + end loop; + -- append suffix + for j in 0 .. Suffix_Bit_Length - 1 loop + Append_Bit(Context, Dest_Index, Bit(Shift_Right(Suffix, Natural(j)) mod 2)); + end loop; + -- insert Padding + Append_Bit(Context, Dest_Index, 1); + Dest_Index := Rate_Bits - 1; + Append_Bit(Context, Dest_Index, 1); + end Last_Block; + + procedure Squeeze(Context : in out Context_T; Data : out u8_Array) is + Temp : u8_Array(1 .. 8); + Length_A : Integer := Data'First; + Length_B : Integer; + j : Natural; + begin + for i in 0 .. Data'Length / Rate_Bytes loop + Length_B := Length_A + Rate_Bytes - 1; + if Length_B > Data'Last then + Length_B := Data'Last; + end if; + j := 0; + while Length_A + 8 <= Length_B loop + Store_le(Data(Length_A .. Length_A + 7), Context.A(x_t(j mod 5), y_t(j / 5))); + Length_A := Length_A + 8; + j := j + 1; + end loop; + + if Length_A <= Length_B then + Store_le(Temp, Context.A(x_t(j mod 5), y_t(j / 5))); + Data(Length_A .. Length_B) := Temp(Temp'First .. Temp'First + Length_B - Length_A); + end if; + + Length_A := Length_B; + if Length_B < Data'Last then + Permute(Context.A); + end if; + end loop; + end Squeeze; + + procedure Get_Digest(Context : in out Context_T; Digest : out Digest_T) is + begin + Squeeze(Context, Digest); + end Get_Digest; + + procedure Hash(Data : in u8_array; Digest : out Digest_T; Bits : in Integer := -1) is + Ctx : Context_T; + begin + Initialize(Ctx); + Last_Block(Ctx, Data, Bits); + Get_Digest(Ctx, Digest); + end Hash; + +end Sha3_Generic; + + diff --git a/src/algorithms/sha3/sha3_generic.ads b/src/algorithms/sha3/sha3_generic.ads new file mode 100644 index 0000000..43ca7b6 --- /dev/null +++ b/src/algorithms/sha3/sha3_generic.ads @@ -0,0 +1,64 @@ +-- 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 Keccak_Parameters; use Keccak_Parameters; +with Keccak; use Keccak; + +use Crypto_Types.Crypto_Types_u8; +use Crypto_Types.Crypto_Types_u64; + +generic + Capacity_Bits : Capacity_T; + Suffix : u64 := 2#10#; + Suffix_Bit_Length : u8 := 2; + +package Sha3_Generic is + + type Context_T is private; + + BlockSize_Bits : constant Natural := b - Capacity_Bits; + DigestSize_Bits : constant Natural := Capacity_Bits / 2; + BlockSize_Bytes : constant Natural := BlockSize_Bits / 8; + DigestSize_Bytes : constant Natural := DigestSize_Bits / 8; + + subtype Block_T is u8_Array(1 .. BlockSize_Bytes); + subtype Digest_T is u8_Array(1 .. DigestSize_Bytes); + + procedure Initialize(Context : out Context_T); + procedure Next_Block(Context : in out Context_T; Block : in Block_T); + procedure Last_Block(Context : in out Context_T; Block : in u8_Array; Bits : in Integer := -1); + procedure Squeeze(Context : in out Context_T; Data : out u8_Array); + procedure Get_Digest(Context : in out Context_T; Digest : out Digest_T); + + procedure Hash(Data : in u8_array; Digest : out Digest_T; Bits : in Integer := -1); + +private + + Rate_Bits : constant Capacity_T := b - Capacity_Bits; + Capacity_Bytes : constant Capacity_Bytes_T := Capacity_Bits / 8; + Rate_Bytes : constant Capacity_Bytes_T := Rate_Bits / 8; + Digest_Bits : constant Natural := Capacity_Bits / 2; + Digest_Bytes : constant Natural := Digest_Bits / 8; + + type Context_T is record + A : State_T; + end record; + + +end Sha3_Generic; + +