steelcrypt/src/algorithms/sha3/keccak.adb

151 lines
4.7 KiB
Ada

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