raw
eucrypt_ch8_bit_k...    1  -- S.MG, 2018
eucrypt_ch8_bit_k... 2
eucrypt_ch8_bit_k... 3 package body SMG_Bit_Keccak is
eucrypt_ch8_bit_k... 4
eucrypt_ch8_bit_k... 5 -- public function, sponge
eucrypt_ch8_bit_k... 6 procedure Sponge( Input : in Bitstream;
eucrypt_ch8_bit_k... 7 Block_Len : in Keccak_Rate;
eucrypt_ch8_bit_k... 8 Output : out Bitstream) is
eucrypt_ch8_bit_k... 9 Internal : State := (others => (others => (others => 0)));
eucrypt_ch8_bit_k... 10 begin
eucrypt_ch8_bit_k... 11 --absorb input into sponge in a loop on available blocks, including padding
eucrypt_ch8_bit_k... 12 declare
eucrypt_ch8_bit_k... 13 -- number of input blocks after padding (between 2 and block_len bits pad)
eucrypt_ch8_bit_k... 14 Padded_Blocks : constant Positive := 1 + (Input'Length + 1) / Block_Len;
eucrypt_ch8_bit_k... 15 Padded : Bitstream ( 1 .. Padded_Blocks * Block_Len );
eucrypt_ch8_bit_k... 16 Block : Bitstream ( 1 .. Block_Len );
eucrypt_ch8_bit_k... 17 begin
eucrypt_ch8_bit_k... 18 -- initialise Padded with 0 everywhere
eucrypt_ch8_bit_k... 19 Padded := ( others => 0 );
eucrypt_ch8_bit_k... 20 -- copy and pad input with rule 10*1
eucrypt_ch8_bit_k... 21 Padded( Padded'First .. Padded'First + Input'Length - 1 ) := Input;
eucrypt_ch8_bit_k... 22 Padded( Padded'First + Input'Length ) := 1;
eucrypt_ch8_bit_k... 23 Padded( Padded'Last ) := 1;
eucrypt_ch8_bit_k... 24
eucrypt_ch8_bit_k... 25 -- loop through padded input and absorb block by block into sponge
eucrypt_ch8_bit_k... 26 -- padded input IS a multiple of blocks, so no stray bits left
eucrypt_ch8_bit_k... 27 for B in 0 .. Padded_Blocks - 1 loop
eucrypt_ch8_bit_k... 28 -- first get the current block to absorb
eucrypt_ch8_bit_k... 29 Block := Padded( Padded'First + B * Block_Len ..
eucrypt_ch8_bit_k... 30 Padded'First + (B+1) * Block_Len - 1 );
eucrypt_ch8_bit_k... 31 AbsorbBlock( Block, Internal );
eucrypt_ch8_bit_k... 32 -- scramble state with Keccak function
eucrypt_ch8_bit_k... 33 Internal := Keccak_Function( Internal );
eucrypt_ch8_bit_k... 34
eucrypt_ch8_bit_k... 35 end loop; -- end absorb loop for blocks
eucrypt_ch8_bit_k... 36 end; -- end absorb stage
eucrypt_ch8_bit_k... 37
eucrypt_ch8_bit_k... 38 --squeeze required bits from sponge in a loop as needed
eucrypt_ch8_bit_k... 39 declare
eucrypt_ch8_bit_k... 40 -- full blocks per output
eucrypt_ch8_bit_k... 41 BPO : constant Natural := Output'Length / Block_Len;
eucrypt_ch8_bit_k... 42 -- stray bits per output
eucrypt_ch8_bit_k... 43 SPO : constant Natural := Output'Length mod Block_Len;
eucrypt_ch8_bit_k... 44 Block : Bitstream( 1 .. Block_Len );
eucrypt_ch8_bit_k... 45 begin
eucrypt_ch8_bit_k... 46 -- squeeze block by block (if at least one full block is needed)
eucrypt_ch8_bit_k... 47 for I in 0 .. BPO - 1 loop
eucrypt_ch8_bit_k... 48 SqueezeBlock( Block, Internal );
eucrypt_ch8_bit_k... 49 Output( Output'First + I * Block_Len ..
eucrypt_ch8_bit_k... 50 Output'First + (I + 1) * Block_Len -1) := Block;
eucrypt_ch8_bit_k... 51
eucrypt_ch8_bit_k... 52 -- scramble state
eucrypt_ch8_bit_k... 53 Internal := Keccak_Function( Internal );
eucrypt_ch8_bit_k... 54 end loop; -- end squeezing full blocks
eucrypt_ch8_bit_k... 55
eucrypt_ch8_bit_k... 56 -- squeeze any partial block needed (stray bits)
eucrypt_ch8_bit_k... 57 if SPO > 0 then
eucrypt_ch8_bit_k... 58 SqueezeBlock( Block, Internal );
eucrypt_ch8_bit_k... 59 Output( Output'Last - SPO + 1 .. Output'Last ) :=
eucrypt_ch8_bit_k... 60 Block( Block'First .. Block'First + SPO - 1 );
eucrypt_ch8_bit_k... 61 end if; -- end squeezing partial last block (stray bits)
eucrypt_ch8_bit_k... 62
eucrypt_ch8_bit_k... 63 end; -- end squeeze stage
eucrypt_ch8_bit_k... 64
eucrypt_ch8_bit_k... 65 end Sponge;
eucrypt_ch8_bit_k... 66
eucrypt_ch8_bit_k... 67 -- helper procedures for sponge absorb/squeeze
eucrypt_ch8_bit_k... 68
eucrypt_ch8_bit_k... 69 -- NO scramble here, this will absorb ALL given block, make sure it fits!
eucrypt_ch8_bit_k... 70 procedure AbsorbBlock( Block: in Bitstream; S: in out State ) is
eucrypt_ch8_bit_k... 71 X, Y : XYCoord;
eucrypt_ch8_bit_k... 72 Z : ZCoord;
eucrypt_ch8_bit_k... 73 begin
eucrypt_ch8_bit_k... 74 -- xor current block, bit by bit, into first Block'Length bits of state
eucrypt_ch8_bit_k... 75 First_Pos( X, Y, Z);
eucrypt_ch8_bit_k... 76 for B of Block loop
eucrypt_ch8_bit_k... 77 -- xor this bit into the state
eucrypt_ch8_bit_k... 78 S( X, Y )( Z ) := S( X, Y )( Z ) + B;
eucrypt_ch8_bit_k... 79 -- move to next bit of the state
eucrypt_ch8_bit_k... 80 Next_Pos( X, Y, Z );
eucrypt_ch8_bit_k... 81 end loop;
eucrypt_ch8_bit_k... 82 end AbsorbBlock;
eucrypt_ch8_bit_k... 83
eucrypt_ch8_bit_k... 84 -- NO scramble here, this will squeeze Block'Length bits out of *same* state S
eucrypt_ch8_bit_k... 85 procedure SqueezeBlock( Block: out Bitstream; S: in State) is
eucrypt_ch8_bit_k... 86 X, Y : XYCoord;
eucrypt_ch8_bit_k... 87 Z : ZCoord;
eucrypt_ch8_bit_k... 88 begin
eucrypt_ch8_bit_k... 89 -- start with first position of the state
eucrypt_ch8_bit_k... 90 First_Pos( X, Y, Z );
eucrypt_ch8_bit_k... 91 -- squeeze bit by bit, as many bits as needed to fill Block
eucrypt_ch8_bit_k... 92 for I in Block'Range loop
eucrypt_ch8_bit_k... 93 -- squeeze current bit from state
eucrypt_ch8_bit_k... 94 Block( I ) := S( X, Y )( Z );
eucrypt_ch8_bit_k... 95 -- advance to next bit of state
eucrypt_ch8_bit_k... 96 Next_Pos( X, Y, Z);
eucrypt_ch8_bit_k... 97 end loop;
eucrypt_ch8_bit_k... 98 end SqueezeBlock;
eucrypt_ch8_bit_k... 99
eucrypt_ch8_bit_k... 100 -- moving one bit forwards in Keccak state
eucrypt_ch8_bit_k... 101 procedure Next_Pos( X : in out XYCoord;
eucrypt_ch8_bit_k... 102 Y : in out XYCoord;
eucrypt_ch8_bit_k... 103 Z : in out ZCoord
eucrypt_ch8_bit_k... 104 ) is
eucrypt_ch8_bit_k... 105 begin
eucrypt_ch8_bit_k... 106 Z := Z - 1;
eucrypt_ch8_bit_k... 107 if Z = ZCoord'Last then
eucrypt_ch8_bit_k... 108 X := X + 1;
eucrypt_ch8_bit_k... 109 if X = XYCoord'First then
eucrypt_ch8_bit_k... 110 Y := Y + 1;
eucrypt_ch8_bit_k... 111 end if;
eucrypt_ch8_bit_k... 112 end if;
eucrypt_ch8_bit_k... 113 end Next_Pos;
eucrypt_ch8_bit_k... 114
eucrypt_ch8_bit_k... 115 -- position of first bit in Keccak state
eucrypt_ch8_bit_k... 116 procedure First_Pos( X : out XYCoord;
eucrypt_ch8_bit_k... 117 Y : out XYCoord;
eucrypt_ch8_bit_k... 118 Z : out ZCoord
eucrypt_ch8_bit_k... 119 ) is
eucrypt_ch8_bit_k... 120 begin
eucrypt_ch8_bit_k... 121 X := XYCoord'First;
eucrypt_ch8_bit_k... 122 Y := XYCoord'First;
eucrypt_ch8_bit_k... 123 Z := ZCoord'Last;
eucrypt_ch8_bit_k... 124 end First_Pos;
eucrypt_ch8_bit_k... 125
eucrypt_ch8_bit_k... 126 -- operations with Bitwords
eucrypt_ch8_bit_k... 127 function BWRotate_Left( Input: in Bitword;
eucrypt_ch8_bit_k... 128 Count: in Natural)
eucrypt_ch8_bit_k... 129 return Bitword is
eucrypt_ch8_bit_k... 130 Output : Bitword;
eucrypt_ch8_bit_k... 131 Advance : constant ZCoord := ZCoord( Count mod Z_Length );
eucrypt_ch8_bit_k... 132 begin
eucrypt_ch8_bit_k... 133 for I in ZCoord loop
eucrypt_ch8_bit_k... 134 Output( I ) := Input( I + Advance );
eucrypt_ch8_bit_k... 135 end loop;
eucrypt_ch8_bit_k... 136 return Output;
eucrypt_ch8_bit_k... 137 end BWRotate_Left;
eucrypt_ch8_bit_k... 138
eucrypt_ch8_bit_k... 139 -- Keccak transformations of the internal state
eucrypt_ch8_bit_k... 140 function Theta ( Input : in State) return State is
eucrypt_ch8_bit_k... 141 Output : State;
eucrypt_ch8_bit_k... 142 S1, S2 : Bit;
eucrypt_ch8_bit_k... 143 begin
eucrypt_ch8_bit_k... 144 for X in XYCoord loop
eucrypt_ch8_bit_k... 145 for Y in XYCoord loop
eucrypt_ch8_bit_k... 146 for Z in ZCoord loop
eucrypt_ch8_bit_k... 147 S1 := 0;
eucrypt_ch8_bit_k... 148 S2 := 0;
eucrypt_ch8_bit_k... 149 for Y1 in XYCoord loop
eucrypt_ch8_bit_k... 150 S1 := S1 + Input( X - 1, Y1 )( Z );
eucrypt_ch8_bit_k... 151 -- Z direction is opposite to the one assumed in the ref so Z + 1
eucrypt_ch8_bit_k... 152 S2 := S2 + Input( X + 1, Y1 )( Z + 1 );
eucrypt_ch8_bit_k... 153 end loop;
eucrypt_ch8_bit_k... 154 Output( X, Y )(Z) := Input( X, Y )( Z ) + S1 + S2;
eucrypt_ch8_bit_k... 155 end loop;
eucrypt_ch8_bit_k... 156 end loop;
eucrypt_ch8_bit_k... 157 end loop;
eucrypt_ch8_bit_k... 158
eucrypt_ch8_bit_k... 159 return Output;
eucrypt_ch8_bit_k... 160 end Theta;
eucrypt_ch8_bit_k... 161
eucrypt_ch8_bit_k... 162 function Rho ( Input : in State) return State is
eucrypt_ch8_bit_k... 163 Output : State;
eucrypt_ch8_bit_k... 164 X, Y, Old_Y : XYCoord;
eucrypt_ch8_bit_k... 165 begin
eucrypt_ch8_bit_k... 166 Output( 0, 0) := Input( 0, 0);
eucrypt_ch8_bit_k... 167 X := 1;
eucrypt_ch8_bit_k... 168 Y := 0;
eucrypt_ch8_bit_k... 169
eucrypt_ch8_bit_k... 170 for T in 0 .. 23 loop
eucrypt_ch8_bit_k... 171 Output(X, Y) := BWRotate_Left(Input(X,Y), (T+1)*(T+2)/2);
eucrypt_ch8_bit_k... 172 Old_Y := Y;
eucrypt_ch8_bit_k... 173 Y := 2 * X + 3 * Y;
eucrypt_ch8_bit_k... 174 X := Old_Y;
eucrypt_ch8_bit_k... 175 end loop;
eucrypt_ch8_bit_k... 176 return Output;
eucrypt_ch8_bit_k... 177 end Rho;
eucrypt_ch8_bit_k... 178
eucrypt_ch8_bit_k... 179 function Pi ( Input : in State) return State is
eucrypt_ch8_bit_k... 180 Output : State;
eucrypt_ch8_bit_k... 181 begin
eucrypt_ch8_bit_k... 182 for X in XYCoord loop
eucrypt_ch8_bit_k... 183 for Y in XYCoord loop
eucrypt_ch8_bit_k... 184 Output( Y, 2 * X + 3 * Y ) := Input( X, Y );
eucrypt_ch8_bit_k... 185 end loop;
eucrypt_ch8_bit_k... 186 end loop;
eucrypt_ch8_bit_k... 187
eucrypt_ch8_bit_k... 188 return Output;
eucrypt_ch8_bit_k... 189 end Pi;
eucrypt_ch8_bit_k... 190
eucrypt_ch8_bit_k... 191 function Chi ( Input : in State) return State is
eucrypt_ch8_bit_k... 192 Output : State;
eucrypt_ch8_bit_k... 193 begin
eucrypt_ch8_bit_k... 194 for Y in XYCoord loop
eucrypt_ch8_bit_k... 195 for X in XYCoord loop
eucrypt_ch8_bit_k... 196 for Z in ZCoord loop
eucrypt_ch8_bit_k... 197 Output(X, Y)(Z) := Input( X, Y )( Z ) +
eucrypt_ch8_bit_k... 198 ( Input( X + 1, Y )( Z ) + 1 ) *
eucrypt_ch8_bit_k... 199 ( Input( X + 2, Y )( Z ) );
eucrypt_ch8_bit_k... 200 end loop;
eucrypt_ch8_bit_k... 201 end loop;
eucrypt_ch8_bit_k... 202 end loop;
eucrypt_ch8_bit_k... 203
eucrypt_ch8_bit_k... 204 return Output;
eucrypt_ch8_bit_k... 205 end Chi;
eucrypt_ch8_bit_k... 206
eucrypt_ch8_bit_k... 207 function Iota ( Round_Const : in Bitword; Input : in State) return State is
eucrypt_ch8_bit_k... 208 Output : State;
eucrypt_ch8_bit_k... 209 begin
eucrypt_ch8_bit_k... 210 Output := Input;
eucrypt_ch8_bit_k... 211 for Z in ZCoord loop
eucrypt_ch8_bit_k... 212 Output( 0, 0 )(Z) := Input( 0, 0 )( Z ) + Round_Const( Z );
eucrypt_ch8_bit_k... 213 end loop;
eucrypt_ch8_bit_k... 214 return Output;
eucrypt_ch8_bit_k... 215 end Iota;
eucrypt_ch8_bit_k... 216
eucrypt_ch8_bit_k... 217 function Keccak_Function(Input: in State) return State is
eucrypt_ch8_bit_k... 218 Output: State;
eucrypt_ch8_bit_k... 219 begin
eucrypt_ch8_bit_k... 220 Output := Input;
eucrypt_ch8_bit_k... 221 for I in Round_Index loop
eucrypt_ch8_bit_k... 222 Output := Iota(RC(I), Chi(Pi(Rho(Theta(Output)))));
eucrypt_ch8_bit_k... 223 end loop;
eucrypt_ch8_bit_k... 224
eucrypt_ch8_bit_k... 225 return Output;
eucrypt_ch8_bit_k... 226 end Keccak_Function;
eucrypt_ch8_bit_k... 227
eucrypt_ch8_bit_k... 228 end SMG_Bit_Keccak;
eucrypt_ch8_bit_k... 229