-
+ E35CBB412CFE6885F74E67714C94C05F4C6DBF15B96573308030233D6493876863837D29FB7A0384FA1D51965AE14B32567623E8FCF20AEEEB371E27B7D78CE9
eucrypt/smg_bit_keccak/smg_bit_keccak.adb
(0 . 0)(1 . 229)
57 -- S.MG, 2018
58
59 package body SMG_Bit_Keccak is
60
61 -- public function, sponge
62 procedure Sponge( Input : in Bitstream;
63 Block_Len : in Keccak_Rate;
64 Output : out Bitstream) is
65 Internal : State := (others => (others => (others => 0)));
66 begin
67 --absorb input into sponge in a loop on available blocks, including padding
68 declare
69 -- number of input blocks after padding (between 2 and block_len bits pad)
70 Padded_Blocks : constant Positive := 1 + (Input'Length + 1) / Block_Len;
71 Padded : Bitstream ( 1 .. Padded_Blocks * Block_Len );
72 Block : Bitstream ( 1 .. Block_Len );
73 begin
74 -- initialise Padded with 0 everywhere
75 Padded := ( others => 0 );
76 -- copy and pad input with rule 10*1
77 Padded( Padded'First .. Padded'First + Input'Length - 1 ) := Input;
78 Padded( Padded'First + Input'Length ) := 1;
79 Padded( Padded'Last ) := 1;
80
81 -- loop through padded input and absorb block by block into sponge
82 -- padded input IS a multiple of blocks, so no stray bits left
83 for B in 0 .. Padded_Blocks - 1 loop
84 -- first get the current block to absorb
85 Block := Padded( Padded'First + B * Block_Len ..
86 Padded'First + (B+1) * Block_Len - 1 );
87 AbsorbBlock( Block, Internal );
88 -- scramble state with Keccak function
89 Internal := Keccak_Function( Internal );
90
91 end loop; -- end absorb loop for blocks
92 end; -- end absorb stage
93
94 --squeeze required bits from sponge in a loop as needed
95 declare
96 -- full blocks per output
97 BPO : constant Natural := Output'Length / Block_Len;
98 -- stray bits per output
99 SPO : constant Natural := Output'Length mod Block_Len;
100 Block : Bitstream( 1 .. Block_Len );
101 begin
102 -- squeeze block by block (if at least one full block is needed)
103 for I in 0 .. BPO - 1 loop
104 SqueezeBlock( Block, Internal );
105 Output( Output'First + I * Block_Len ..
106 Output'First + (I + 1) * Block_Len -1) := Block;
107
108 -- scramble state
109 Internal := Keccak_Function( Internal );
110 end loop; -- end squeezing full blocks
111
112 -- squeeze any partial block needed (stray bits)
113 if SPO > 0 then
114 SqueezeBlock( Block, Internal );
115 Output( Output'Last - SPO + 1 .. Output'Last ) :=
116 Block( Block'First .. Block'First + SPO - 1 );
117 end if; -- end squeezing partial last block (stray bits)
118
119 end; -- end squeeze stage
120
121 end Sponge;
122
123 -- helper procedures for sponge absorb/squeeze
124
125 -- NO scramble here, this will absorb ALL given block, make sure it fits!
126 procedure AbsorbBlock( Block: in Bitstream; S: in out State ) is
127 X, Y : XYCoord;
128 Z : ZCoord;
129 begin
130 -- xor current block, bit by bit, into first Block'Length bits of state
131 First_Pos( X, Y, Z);
132 for B of Block loop
133 -- xor this bit into the state
134 S( X, Y )( Z ) := S( X, Y )( Z ) + B;
135 -- move to next bit of the state
136 Next_Pos( X, Y, Z );
137 end loop;
138 end AbsorbBlock;
139
140 -- NO scramble here, this will squeeze Block'Length bits out of *same* state S
141 procedure SqueezeBlock( Block: out Bitstream; S: in State) is
142 X, Y : XYCoord;
143 Z : ZCoord;
144 begin
145 -- start with first position of the state
146 First_Pos( X, Y, Z );
147 -- squeeze bit by bit, as many bits as needed to fill Block
148 for I in Block'Range loop
149 -- squeeze current bit from state
150 Block( I ) := S( X, Y )( Z );
151 -- advance to next bit of state
152 Next_Pos( X, Y, Z);
153 end loop;
154 end SqueezeBlock;
155
156 -- moving one bit forwards in Keccak state
157 procedure Next_Pos( X : in out XYCoord;
158 Y : in out XYCoord;
159 Z : in out ZCoord
160 ) is
161 begin
162 Z := Z - 1;
163 if Z = ZCoord'Last then
164 X := X + 1;
165 if X = XYCoord'First then
166 Y := Y + 1;
167 end if;
168 end if;
169 end Next_Pos;
170
171 -- position of first bit in Keccak state
172 procedure First_Pos( X : out XYCoord;
173 Y : out XYCoord;
174 Z : out ZCoord
175 ) is
176 begin
177 X := XYCoord'First;
178 Y := XYCoord'First;
179 Z := ZCoord'Last;
180 end First_Pos;
181
182 -- operations with Bitwords
183 function BWRotate_Left( Input: in Bitword;
184 Count: in Natural)
185 return Bitword is
186 Output : Bitword;
187 Advance : constant ZCoord := ZCoord( Count mod Z_Length );
188 begin
189 for I in ZCoord loop
190 Output( I ) := Input( I + Advance );
191 end loop;
192 return Output;
193 end BWRotate_Left;
194
195 -- Keccak transformations of the internal state
196 function Theta ( Input : in State) return State is
197 Output : State;
198 S1, S2 : Bit;
199 begin
200 for X in XYCoord loop
201 for Y in XYCoord loop
202 for Z in ZCoord loop
203 S1 := 0;
204 S2 := 0;
205 for Y1 in XYCoord loop
206 S1 := S1 + Input( X - 1, Y1 )( Z );
207 -- Z direction is opposite to the one assumed in the ref so Z + 1
208 S2 := S2 + Input( X + 1, Y1 )( Z + 1 );
209 end loop;
210 Output( X, Y )(Z) := Input( X, Y )( Z ) + S1 + S2;
211 end loop;
212 end loop;
213 end loop;
214
215 return Output;
216 end Theta;
217
218 function Rho ( Input : in State) return State is
219 Output : State;
220 X, Y, Old_Y : XYCoord;
221 begin
222 Output( 0, 0) := Input( 0, 0);
223 X := 1;
224 Y := 0;
225
226 for T in 0 .. 23 loop
227 Output(X, Y) := BWRotate_Left(Input(X,Y), (T+1)*(T+2)/2);
228 Old_Y := Y;
229 Y := 2 * X + 3 * Y;
230 X := Old_Y;
231 end loop;
232 return Output;
233 end Rho;
234
235 function Pi ( Input : in State) return State is
236 Output : State;
237 begin
238 for X in XYCoord loop
239 for Y in XYCoord loop
240 Output( Y, 2 * X + 3 * Y ) := Input( X, Y );
241 end loop;
242 end loop;
243
244 return Output;
245 end Pi;
246
247 function Chi ( Input : in State) return State is
248 Output : State;
249 begin
250 for Y in XYCoord loop
251 for X in XYCoord loop
252 for Z in ZCoord loop
253 Output(X, Y)(Z) := Input( X, Y )( Z ) +
254 ( Input( X + 1, Y )( Z ) + 1 ) *
255 ( Input( X + 2, Y )( Z ) );
256 end loop;
257 end loop;
258 end loop;
259
260 return Output;
261 end Chi;
262
263 function Iota ( Round_Const : in Bitword; Input : in State) return State is
264 Output : State;
265 begin
266 Output := Input;
267 for Z in ZCoord loop
268 Output( 0, 0 )(Z) := Input( 0, 0 )( Z ) + Round_Const( Z );
269 end loop;
270 return Output;
271 end Iota;
272
273 function Keccak_Function(Input: in State) return State is
274 Output: State;
275 begin
276 Output := Input;
277 for I in Round_Index loop
278 Output := Iota(RC(I), Chi(Pi(Rho(Theta(Output)))));
279 end loop;
280
281 return Output;
282 end Keccak_Function;
283
284 end SMG_Bit_Keccak;
285