-- S.MG bit-level implementation of Keccak-f permutations -- (Based on The Keccak Reference, Version 3.0, January 14, 2011, by -- Guido Bertoni, Joan Daemen, Michael Peeters and Gilles Van Assche) -- S.MG, 2018 package SMG_Bit_Keccak is pragma Pure(SMG_Bit_Keccak); --stateless, no side effects -> can cache calls --knobs (can change as per keccak design but fixed here for S.MG purposes)-- Keccak_L: constant := 6; --gives keccak z dimension of 2^6=64 bits and --therefore keccak function 1600 with current --constants (5*5*2^6) --constants: dimensions of keccak state and number of rounds XY_Length: constant := 5; Z_Length: constant := 2 ** Keccak_L; Width: constant := XY_Length * XY_Length * Z_Length; N_Rounds: constant := 12 + 2 * Keccak_L; --types type XYCoord is mod XY_Length; type ZCoord is mod Z_Length; type Round_Index is mod N_Rounds; type Bit is mod 2; type Bitstream is array( Natural range <> ) of Bit; -- any length; message type Bitword is array( ZCoord ) of Bit; -- a keccak "word" of bits type State is array( XYCoord, XYCoord ) of Bitword; -- the full keccak state type Round_Constants is array(Round_Index) of Bitword; --magic keccak values -- rate can be chosen by caller at each call, between 1 and width of state -- higher rate means sponge "eats" more bits at a time but has fewer bits in -- the "secret" part of the state (i.e. lower capacity) subtype Keccak_Rate is Positive range 1..Width; -- capacity = width - rate -- public function, the sponge itself -- Keccak sponge structure using Keccak_Function, Pad and a given bitrate; -- Input - the stream of bits to hash (the message) -- Block_Len - the bitrate to use; this is effectively the block length -- for splitting Input AND squeezing output between scrambles -- Output - a bitstream of desired size for holding output procedure Sponge(Input : in Bitstream; Block_Len : in Keccak_Rate; Output : out Bitstream); private -- these are internals of the keccak implementation, not meant to be directly -- accessed/used -- moving one bit forwards in Keccak state procedure Next_Pos( X : in out XYCoord; Y : in out XYCoord; Z : in out ZCoord ); -- set coordinates to first bit of Keccak state procedure First_Pos( X : out XYCoord; Y : out XYCoord; Z : out ZCoord ); -- operations with Bitwords function BWRotate_Left( Input: in Bitword; Count: in Natural) return Bitword; -- this will squeeze Block'Length bits out of state S -- NO scramble of state in here! -- NB: make SURE that Block'Length is the correct bitrate for this sponge -- in particular, Block'Length should be a correct bitrate aka LESS than Width procedure SqueezeBlock( Block: out Bitstream; S: in State); -- This absorbs into sponge the given block, modifying the state accordingly -- NO scramble of state in here so make sure the whole Block fits in state! -- NB: make SURE that Block'Length is *the correct bitrate* for this sponge -- in particular, Block'Length should be a correct bitrate aka LESS than Width procedure AbsorbBlock( Block: in Bitstream; S: in out State ); -- Keccak magic bitwords RC : constant Round_Constants := ( -- 16#0000_0000_0000_0001#, round 0 (0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1), -- 16#0000_0000_0000_8082#, round 1 (0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,1,0), -- 16#8000_0000_0000_808A#, round 2 (1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 1,0,1,0), -- 16#8000_0000_8000_8000#, round 3 (1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0), -- 16#0000_0000_0000_808B#, round 4 (0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 1,0,1,1), -- 16#0000_0000_8000_0001#, round 5 (0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1), -- 16#8000_0000_8000_8081#, round 6 (1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,1), -- 16#8000_0000_0000_8009#, round 7 (1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,1), -- 16#0000_0000_0000_008A#, round 8 (0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 1,0,1,0), -- 16#0000_0000_0000_0088#, round 9 (0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 1,0,0,0), -- 16#0000_0000_8000_8009#, round 10 (0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,1), -- 16#0000_0000_8000_000A#, round 11 (0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,1,0), -- 16#0000_0000_8000_808B#, round 12 (0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 1,0,1,1), -- 16#8000_0000_0000_008B#, round 13 (1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 1,0,1,1), -- 16#8000_0000_0000_8089#, round 14 (1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 1,0,0,1), -- 16#8000_0000_0000_8003#, round 15 (1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,1,1), -- 16#8000_0000_0000_8002#, round 16 (1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,1,0), -- 16#8000_0000_0000_0080#, round 17 (1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0), -- 16#0000_0000_0000_800A#, round 18 (0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,1,0), -- 16#8000_0000_8000_000A#, round 19 (1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,1,0), -- 16#8000_0000_8000_8081#, round 20 (1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,1), -- 16#8000_0000_0000_8080#, round 21 (1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0), -- 16#0000_0000_8000_0001#, round 22 (0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1), -- 16#8000_0000_8000_8008#, round 23 (1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0) ); -- Keccak transformations of the internal state function Theta ( Input : in State ) return State; function Rho ( Input : in State ) return State; function Pi ( Input : in State ) return State; function Chi ( Input : in State ) return State; function Iota ( Round_Const : in Bitword; Input : in State ) return State; -- Keccak function with block width currently 1600 (Width constant above) -- It simply applies *all* keccak transformations in the correct order, using -- the keccak magic numbers (round constants) as per keccak reference function Keccak_Function(Input: in State) return State; end SMG_Bit_Keccak;