tree checksum vpatch file split hunks
all signers: diana_coman
antecedents: eucrypt_ch12_wrapper_rsa_oaep_c_ada eucrypt_fix_256 eucrypt_ch10_oaep_tmsr eucrypt_keccak_bitrate_fix eucrypt_ch15_arbitrary_e
press order:
patch:
(20 . 3)(20 . 4)
5 543780 eucrypt_fix_256 diana_coman Fix the error in smg_oaep.adb that used 255 instead of 256 when calculating/retrieving length stored on 2 octets.
6 545170 eucrypt_ch14_crc32 diana_coman A simple implementation of CRC32 checksum using a lookup table. The CRC32 lib can be compiled on its own or together with the whole EuCrypt.
7 552693 eucrypt_ch15_arbitrary_e diana_coman Changes to allow the user to pick their desired length for the public exponent when generating a new pair of RSA keys.
8 567195 eucrypt_ch16_bytestream_keccak diana_coman Changes the workhorse keccak implementation to get rid of the wasteful bitstream input/output and work instead with bytestream input/output.
- C1A09DF1A356CC9042207A12DE9290C85B22A734499661486D419E44B3B22551F87EAA0F6EB2173F771E31CBB078471D3B6650B76434EA9FFBDE1A8D4AFB2814(1 . 30)(1 . 32)- 7503D06B8F87F1CD8A4246A7BAF27BA9431646E65F07FEA64173F24852BE71DC493C3E866D5C16F6723F80C6E6ED1479A46FAC9DEA5FDF02B0387724BDB99E08
13 -- S.MG, 2018
14 with System; use System; -- for Bit_Order
15 with Interfaces; use Interfaces;
16
17 package body SMG_Keccak is
18
19 -- public function, sponge
20 procedure Sponge( Input : in Bitstream;
21 Output : out Bitstream;
22 Block_Len : in Keccak_Rate := Default_Bitrate ) is
23 procedure Sponge( Input : in Bytestream;
24 Output : out Bytestream;
25 Block_Len : in Keccak_Rate := Default_Byterate ) is
26 Internal : State := (others => (others => 0));
27 begin
28 --absorb input into sponge in a loop on available blocks, including padding
29 declare
30 -- number of input blocks after padding (between 2 and block_len bits pad)
31 Padded_Blocks : constant Positive := 1 + (Input'Length + 1) / Block_Len;
32 Padded : Bitstream ( 1 .. Padded_Blocks * Block_Len );
33 Block : Bitstream ( 1 .. Block_Len );
34 -- number of input blocks after padding (pad between 1 and block_len)
35 Padded_Blocks : constant Positive := 1 + Input'Length / Block_Len;
36 Padded : Bytestream ( 1 .. Padded_Blocks * Block_Len );
37 Block : Bytestream ( 1 .. Block_Len );
38 begin
39 -- initialise Padded with 0 everywhere
40 Padded := ( others => 0 );
41 -- copy and pad input with rule 10*1
42 Padded( Padded'First .. Padded'First + Input'Length - 1 ) := Input;
43 -- padding is 10*1 so start and end with an 1 but LSB order hence 16#80#
44 Padded( Padded'First + Input'Length ) := 1;
45 Padded( Padded'Last ) := 1;
46 Padded( Padded'Last ) := Padded( Padded'Last ) + 16#80#;
47
48 -- loop through padded input and absorb block by block into sponge
49 -- padded input IS a multiple of blocks, so no stray bits left
50 -- padded input IS a multiple of blocks, so no stray octets left
51 for B in 0 .. Padded_Blocks - 1 loop
52 -- first get the current block to absorb
53 Block := Padded( Padded'First + B * Block_Len ..
(36 . 13)(38 . 13)
55 end loop; -- end absorb loop for blocks
56 end; -- end absorb stage
57
58 --squeeze required bits from sponge in a loop as needed
59 --squeeze required octets from sponge in a loop as needed
60 declare
61 -- full blocks per output
62 BPO : constant Natural := Output'Length / Block_Len;
63 -- stray bits per output
64 -- stray octets per output
65 SPO : constant Natural := Output'Length mod Block_Len;
66 Block : Bitstream( 1 .. Block_Len );
67 Block : Bytestream( 1 .. Block_Len );
68 begin
69 -- squeeze block by block (if at least one full block is needed)
70 for I in 0 .. BPO - 1 loop
(54 . 88)(56 . 90)
72 Internal := Keccak_Function( Internal );
73 end loop; -- end squeezing full blocks
74
75 -- squeeze any partial block needed (stray bits)
76 -- squeeze any partial block needed (stray octets)
77 if SPO > 0 then
78 SqueezeBlock( Block, Internal );
79 Output( Output'Last - SPO + 1 .. Output'Last ) :=
80 Block( Block'First .. Block'First + SPO - 1 );
81 end if; -- end squeezing partial last block (stray bits)
82 end if; -- end squeezing partial last block (stray octets)
83
84 end; -- end squeeze stage
85 end Sponge;
86
87 -- convert from a bitstream of ZWord size to an actual ZWord number
88 function BitsToWord( BWord: in Bitword ) return ZWord is
89 -- convert from a bytestream of ZWord/8 size to an actual ZWord number
90 -- NB: this will FLIP bits on big endian because keccak expects input LSB
91 -- NOT exact opposite of WordToBytes
92 function BytesToWordLE( BWord: in Byteword ) return ZWord is
93 W : ZWord;
94 Bits: Bitword;
95 B : Byteword;
96 begin
97 -- just copy octets if machine is little endian
98 -- flip octets if machine is big endian
99 -- flip octets AND bits if machine is big endian
100 if Default_Bit_Order = Low_Order_First then
101 Bits := BWord;
102 B := BWord;
103 else
104 Bits := FlipOctets( BWord );
105 B := FlipOctets( BWord );
106 for I in B'First..B'Last loop
107 B(I) := Reverse_Table(Natural(B(I)));
108 end loop;
109 end if;
110 -- actual bits to word conversion
111 W := 0;
112 -- LSB bit order (inside octet) as per Keccak spec
113 for I in reverse Bitword'Range loop
114 W := Shift_Left( W, 1 ) + ZWord( Bits( I ) );
115 end loop;
116 -- actual bytes to word conversion
117 W := Cast(B);
118 return W;
119 end BitsToWord;
120 end BytesToWordLE;
121
122 -- convert from a ZWord (lane of state) to a bitstream of ZWord size
123 function WordToBits( Word: in ZWord ) return Bitword is
124 Bits: Bitword := (others => 0);
125 W: ZWord;
126 begin
127 W := Word;
128 for I in Bitword'Range loop
129 Bits( I ) := Bit( W mod 2 );
130 W := Shift_Right( W, 1 );
131 end loop;
132 -- convert from a ZWord (lane of state) to a bytestream of ZWord size
133 -- NOT exact oppositve of BytesToWordLE
134 -- Keccak sponge spits out MSB so bits are flipped on LITTLE Endian iron.
135 function WordToBytesBE( Word: in ZWord ) return Byteword is
136 B: Byteword;
137 begin
138 B := Cast( Word );
139
140 -- flip octets if machine is big endian
141 if Default_Bit_Order = High_Order_First then
142 Bits := FlipOctets( Bits );
143 B := FlipOctets( B );
144 else
145 -- onth flip bits if machine is little endian....
146 for I in B'First..B'Last loop
147 B(I) := Reverse_Table(Natural(B(I)));
148 end loop;
149 end if;
150
151 return Bits;
152 end WordToBits;
153 return B;
154 end WordToBytesBE;
155
156 -- flip given octets (i.e. groups of 8 bits)
157 function FlipOctets( BWord : in Bitword ) return Bitword is
158 Bits : Bitword;
159 function FlipOctets( BWord : in Byteword ) return Byteword is
160 B : Byteword;
161 begin
162 -- copy groups of 8 octets changing their order in the array
163 -- i.e. 1st octet in BWord becomes last octet in Bits and so on
164 for I in 0 .. ( Bitword'Length / 8 - 1 ) loop
165 Bits ( Bits'First + I * 8 .. Bits'First + I * 8 + 7 ) :=
166 BWord( BWord'Last - I * 8 - 7 .. BWord'Last - I * 8);
167 -- copy octets changing their order in the array
168 -- i.e. 1st octet in BWord becomes last octet in B and so on
169 for I in 0 .. BWord'Length-1 loop
170 B(B'First + I) := BWord(BWord'Last-I);
171 end loop;
172 return Bits;
173 return B;
174 end FlipOctets;
175
176 -- helper procedures for sponge absorb/squeeze
177
178 -- NO scramble here, this will absorb ALL given block, make sure it fits!
179 procedure AbsorbBlock( Block: in Bitstream; S: in out State ) is
180 WPB: constant Natural := Block'Length / Z_Length; -- words per block
181 SBB: constant Natural := Block'Length mod Z_Length; -- stray bits
182 procedure AbsorbBlock( Block: in Bytestream; S: in out State ) is
183 WPB: constant Natural := Block'Length / Byteword'Length; -- words per block
184 SBB: constant Natural := Block'Length mod Byteword'Length; -- stray octets
185 FromPos, ToPos : Natural;
186 X, Y : XYCoord;
187 Word : ZWord;
188 BWord : Bitword;
189 BWord : Byteword;
190 begin
191 -- xor current block into first Block'Length bits of state
192 -- xor current block into first Block'Length octets of state
193 -- a block can consist in more than one word
194 X := 0;
195 Y := 0;
196 for I in 0..WPB-1 loop
197 FromPos := Block'First + I * Z_Length;
198 ToPos := FromPos + Z_Length - 1;
199 Word := BitsToWord( Block( FromPos .. ToPos ) );
200 FromPos := Block'First + I * Byteword'Length;
201 ToPos := FromPos + Byteword'Length - 1;
202 Word := BytesToWordLE( Block( FromPos .. ToPos ) );
203 S( X, Y ) := S( X, Y ) xor Word;
204 -- move on to next word in state
205 X := X + 1;
(143 . 21)(147 . 21)
207 Y := Y + 1;
208 end if;
209 end loop;
210 -- absorb also any remaining bits from block
211 -- absorb also any remaining bytes from block
212 if SBB > 0 then
213 ToPos := Block'Last;
214 FromPos := ToPos - SBB + 1;
215 BWord := (others => 0);
216 BWord(Bitword'First .. Bitword'First + SBB - 1) := Block(FromPos..ToPos);
217 Word := BitsToWord( BWord );
218 BWord(Byteword'First .. Byteword'First + SBB - 1) := Block(FromPos..ToPos);
219 Word := BytesToWordLE( BWord );
220 S( X, Y ) := S( X, Y ) xor Word;
221 end if;
222 end AbsorbBlock;
223
224 -- NO scramble here, this will squeeze Block'Length bits out of *same* state S
225 procedure SqueezeBlock( Block: out Bitstream; S: in State) is
226 procedure SqueezeBlock( Block: out Bytestream; S: in State) is
227 X, Y : XYCoord;
228 BWord : Bitword;
229 BWord : Byteword;
230 FromPos : Natural;
231 Len : Natural;
232 begin
(166 . 7)(170 . 7)
234 FromPos := Block'First;
235
236 while FromPos <= Block'Last loop
237 BWord := WordToBits( S(X, Y) );
238 BWord := WordToBytesBE( S(X, Y) );
239
240 X := X + 1;
241 if X = 0 then
(174 . 10)(178 . 10)
243 end if;
244
245 -- copy full word if it fits or
246 -- only as many bits as are still needed to fill the block
247 -- only as many bytes as are still needed to fill the block
248 Len := Block'Last - FromPos + 1;
249 if Len > Z_Length then
250 Len := Z_Length;
251 if Len > BWord'Length then
252 Len := BWord'Length;
253 end if;
254
255 Block(FromPos..FromPos+Len-1) := BWord(BWord'First..BWord'First+Len-1);
(3 . 7)(3 . 13)- AB9FD79FE71C8BA5C6015B658E2FB609449DDF8C717A0C97C3BA88E7B7C7E8172C00D93637F7697F7D040615854F6FA5865BA04AB3AEA90B33CDF129F4F5589E
260 -- (Based on The Keccak Reference, Version 3.0, January 14, 2011, by
261 -- Guido Bertoni, Joan Daemen, Michael Peeters and Gilles Van Assche)
262
263 -- NB: this is a byte-level (octet) implementation!
264 -- Input/output are always multiple of octets, NOT bits.
265
266 -- S.MG, 2018
267 with Ada.Unchecked_Conversion; --for byteword to zword
268 with Interfaces.C;
269 with Interfaces;
270
271 package SMG_Keccak is
272 pragma Pure(SMG_Keccak); --stateless, no side effects -> can cache calls
(13 . 7)(19 . 7)
274 --therefore keccak function 1600 with current
275 --constants (5*5*2^6)
276
277 Default_Bitrate: constant := 1344; --max bits the sponge can eat/spit without
278 Default_Byterate: constant := 168;--max octets the sponge can eat/spit without
279 --needing to scramble the state
280
281 --constants: dimensions of keccak state and number of rounds
(33 . 47)(39 . 85)
283
284 type Round_Constants is array(Round_Index) of ZWord; --magic keccak constants
285
286 -- rate can be chosen by caller at each call, between 1 and width of state
287 -- higher rate means sponge "eats" more bits at a time but has fewer bits in
288 -- the "secret" part of the state (i.e. lower capacity)
289 subtype Keccak_Rate is Positive range 1..Width; -- capacity = width - rate
290
291 type Bit is mod 2;
292 type Bitstream is array( Natural range <> ) of Bit; -- any length; message
293 subtype Bitword is Bitstream( 0..Z_Length - 1 ); -- bits of one state "word"
294 -- rate can be chosen by caller at each call, between 1 and width of state /8
295 -- higher rate means sponge "eats" more octets at a time but has fewer octets
296 -- in the "secret" part of the state (i.e. lower capacity)
297 subtype Keccak_Rate is Positive range 1..Width/8; -- capacity = width - rate
298
299 type Bytestream is array( Natural range <> ) of Interfaces.Unsigned_8;
300 subtype Byteword is Bytestream( 0..Z_Length/8-1); --octets of one state "word"
301 function Cast is new Ada.Unchecked_Conversion (Byteword, ZWord);
302 function Cast is new Ada.Unchecked_Conversion (ZWord, Byteword);
303
304 -- type conversions
305 function BitsToWord( BWord : in Bitword ) return ZWord;
306 function WordToBits( Word : in ZWord ) return Bitword;
307 -- NB: those are NOT perfect opposites!
308 -- BytesToWord assumes input is raw and in LSB order, will flip on MSB iron
309 -- WordToBytes assumes input is MSB and will flip on LSB
310 -- This is because the Sponge squeezes MSB but absorbs LSB...
311 function BytesToWordLE( BWord : in Byteword ) return ZWord;
312 function WordToBytesBE( Word : in ZWord ) return Byteword;
313
314 -- flip input octets (i.e. groups of 8 bits)
315 function FlipOctets( BWord : in Bitword ) return Bitword;
316 function FlipOctets( BWord : in Byteword ) return Byteword;
317
318 -- public function, the sponge itself
319 -- Keccak sponge structure using Keccak_Function, Pad and a given bitrate;
320 -- Keccak sponge structure using Keccak_Function, Pad and a given octetrate;
321 -- Input - the stream of bits to hash (the message)
322 -- Output - a bitstream of desired size for holding output
323 -- Block_Len - the bitrate to use; this is effectively the block length
324 -- Output - a bytestream of desired size for holding output
325 -- Block_Len - the octetrate to use; this is effectively the block length
326 -- for splitting Input AND squeezing output between scrambles
327 procedure Sponge(Input : in Bitstream;
328 Output : out Bitstream;
329 Block_Len : in Keccak_Rate := Default_Bitrate );
330
331 procedure Sponge(Input : in Bytestream;
332 Output : out Bytestream;
333 Block_Len : in Keccak_Rate := Default_Byterate );
334
335 Reverse_Table : constant array(0..255) of Interfaces.Unsigned_8 := (
336 16#00#, 16#80#, 16#40#, 16#C0#, 16#20#, 16#A0#, 16#60#, 16#E0#,
337 16#10#, 16#90#, 16#50#, 16#D0#, 16#30#, 16#B0#, 16#70#, 16#F0#,
338 16#08#, 16#88#, 16#48#, 16#C8#, 16#28#, 16#A8#, 16#68#, 16#E8#,
339 16#18#, 16#98#, 16#58#, 16#D8#, 16#38#, 16#B8#, 16#78#, 16#F8#,
340 16#04#, 16#84#, 16#44#, 16#C4#, 16#24#, 16#A4#, 16#64#, 16#E4#,
341 16#14#, 16#94#, 16#54#, 16#D4#, 16#34#, 16#B4#, 16#74#, 16#F4#,
342 16#0C#, 16#8C#, 16#4C#, 16#CC#, 16#2C#, 16#AC#, 16#6C#, 16#EC#,
343 16#1C#, 16#9C#, 16#5C#, 16#DC#, 16#3C#, 16#BC#, 16#7C#, 16#FC#,
344 16#02#, 16#82#, 16#42#, 16#C2#, 16#22#, 16#A2#, 16#62#, 16#E2#,
345 16#12#, 16#92#, 16#52#, 16#D2#, 16#32#, 16#B2#, 16#72#, 16#F2#,
346 16#0A#, 16#8A#, 16#4A#, 16#CA#, 16#2A#, 16#AA#, 16#6A#, 16#EA#,
347 16#1A#, 16#9A#, 16#5A#, 16#DA#, 16#3A#, 16#BA#, 16#7A#, 16#FA#,
348 16#06#, 16#86#, 16#46#, 16#C6#, 16#26#, 16#A6#, 16#66#, 16#E6#,
349 16#16#, 16#96#, 16#56#, 16#D6#, 16#36#, 16#B6#, 16#76#, 16#F6#,
350 16#0E#, 16#8E#, 16#4E#, 16#CE#, 16#2E#, 16#AE#, 16#6E#, 16#EE#,
351 16#1E#, 16#9E#, 16#5E#, 16#DE#, 16#3E#, 16#BE#, 16#7E#, 16#FE#,
352 16#01#, 16#81#, 16#41#, 16#C1#, 16#21#, 16#A1#, 16#61#, 16#E1#,
353 16#11#, 16#91#, 16#51#, 16#D1#, 16#31#, 16#B1#, 16#71#, 16#F1#,
354 16#09#, 16#89#, 16#49#, 16#C9#, 16#29#, 16#A9#, 16#69#, 16#E9#,
355 16#19#, 16#99#, 16#59#, 16#D9#, 16#39#, 16#B9#, 16#79#, 16#F9#,
356 16#05#, 16#85#, 16#45#, 16#C5#, 16#25#, 16#A5#, 16#65#, 16#E5#,
357 16#15#, 16#95#, 16#55#, 16#D5#, 16#35#, 16#B5#, 16#75#, 16#F5#,
358 16#0D#, 16#8D#, 16#4D#, 16#CD#, 16#2D#, 16#AD#, 16#6D#, 16#ED#,
359 16#1D#, 16#9D#, 16#5D#, 16#DD#, 16#3D#, 16#BD#, 16#7D#, 16#FD#,
360 16#03#, 16#83#, 16#43#, 16#C3#, 16#23#, 16#A3#, 16#63#, 16#E3#,
361 16#13#, 16#93#, 16#53#, 16#D3#, 16#33#, 16#B3#, 16#73#, 16#F3#,
362 16#0B#, 16#8B#, 16#4B#, 16#CB#, 16#2B#, 16#AB#, 16#6B#, 16#EB#,
363 16#1B#, 16#9B#, 16#5B#, 16#DB#, 16#3B#, 16#BB#, 16#7B#, 16#FB#,
364 16#07#, 16#87#, 16#47#, 16#C7#, 16#27#, 16#A7#, 16#67#, 16#E7#,
365 16#17#, 16#97#, 16#57#, 16#D7#, 16#37#, 16#B7#, 16#77#, 16#F7#,
366 16#0F#, 16#8F#, 16#4F#, 16#CF#, 16#2F#, 16#AF#, 16#6F#, 16#EF#,
367 16#1F#, 16#9F#, 16#5F#, 16#DF#, 16#3F#, 16#BF#, 16#7F#, 16#FF#);
368 private
369 -- these are internals of the keccak implementation, not meant to be directly
370 -- accessed/used
371
372 -- this will squeeze Block'Length bits out of state S
373 -- this will squeeze Block'Length octets out of state S
374 -- NO scramble of state in here!
375 -- NB: make SURE that Block'Length is the correct bitrate for this sponge
376 -- in particular, Block'Length should be a correct bitrate aka LESS than Width
377 procedure SqueezeBlock( Block: out Bitstream; S: in State);
378 -- NB: make SURE that Block'Length is the correct octetrate for this sponge
379 -- esp: Block'Length should be a correct octetrate aka LESS than Width/8
380 procedure SqueezeBlock( Block: out Bytestream; S: in State);
381
382 -- This absorbs into sponge the given block, modifying the state accordingly
383 -- NO scramble of state in here so make sure the whole Block fits in state!
384 -- NB: make SURE that Block'Length is *the correct bitrate* for this sponge
385 -- in particular, Block'Length should be a correct bitrate aka LESS than Width
386 procedure AbsorbBlock( Block: in Bitstream; S: in out State );
387 -- NB: make SURE that Block'Length is *the correct byterate* for this sponge
388 -- esp: Block'Length should be a correct byterate aka LESS than Width
389 procedure AbsorbBlock( Block: in Bytestream; S: in out State );
390
391 --Keccak magic numbers
392 RC : constant Round_Constants :=
(35 . 11)(35 . 11)- EC569AE6EE3890AD5ACEF443CEAC290FE43C084515FF09F60A65AD07DFC147BD858B2E2AEA5F0C687673F6EDE25AC6EA8EEF145CEDAC6359F227D2225D808965
397
398 procedure HashKeccak( Input : in String;
399 Output : out String;
400 Block_Len : in Keccak_Rate := Default_Bitrate) is
401 BIn : Bitstream( 0 .. Input'Length * 8 - 1 );
402 BOut : Bitstream( 0 .. Output'Length * 8 - 1 );
403 Block_Len : in Keccak_Rate := Default_Byterate) is
404 BIn : Bytestream( 0 .. Input'Length - 1 );
405 BOut : Bytestream( 0 .. Output'Length - 1 );
406 begin
407 ToBitstream( Input, BIn);
408 ToBytestream( Input, BIn);
409 Sponge( BIn, BOut, Block_Len);
410 ToString( BOut, Output );
411 end HashKeccak;
(52 . 7)(52 . 7)
413 AdaLenOut : Natural := Natural( LenOut );
414 InStr : String( 1 .. AdaLenIn ) := (others => '0');
415 OutStr : String( 1 .. AdaLenOut ) := (others => '0');
416 Block_Len : Keccak_Rate := Default_Bitrate;
417 Block_Len : Keccak_Rate := Default_Byterate;
418 begin
419 -- Interfaces.C.To_Ada( Input, InStr, AdaLenIn );
420 Char_Array_To_String( Input, AdaLenIn, InStr );
(62 . 44)(62 . 21)
422 end Hash;
423
424 -- conversion between types
425 procedure ToString(B: in Bitstream; S: out String ) is
426 N : Natural;
427 Pos : Natural;
428 procedure ToString(B: in Bytestream; S: out String ) is
429 begin
430 Pos := B'First;
431 for I in S'Range loop
432 N := Natural( B( Pos ) ) +
433 Natural( B( Pos + 1 ) ) * 2 +
434 Natural( B( Pos + 2 ) ) * 4 +
435 Natural( B( Pos + 3 ) ) * 8 +
436 Natural( B( Pos + 4 ) ) * 16 +
437 Natural( B( Pos + 5 ) ) * 32 +
438 Natural( B( Pos + 6 ) ) * 64 +
439 Natural( B( Pos + 7 ) ) * 128;
440 Pos := Pos + 8;
441 S( I ) := Character'Val( N );
442 for I in 0..B'Length-1 loop
443 S(S'First + I) := Character'Val(B(B'First+I));
444 end loop;
445 end ToString;
446
447 procedure ToBitstream(S: in String; B: out Bitstream ) is
448 procedure ToBytestream(S: in String; B: out Bytestream ) is
449 V : Unsigned_8;
450 Pos : Natural;
451 begin
452 Pos := B'First;
453 for C of S loop
454 V := Character'Pos( C );
455 B( Pos ) := Bit( V and 1 );
456 B( Pos + 1 ) := Bit( Shift_Right( V, 1 ) and 1 );
457 B( Pos + 2 ) := Bit( Shift_Right( V, 2 ) and 1 );
458 B( Pos + 3 ) := Bit( Shift_Right( V, 3 ) and 1 );
459 B( Pos + 4 ) := Bit( Shift_Right( V, 4 ) and 1 );
460 B( Pos + 5 ) := Bit( Shift_Right( V, 5 ) and 1 );
461 B( Pos + 6 ) := Bit( Shift_Right( V, 6 ) and 1 );
462 B( Pos + 7 ) := Bit( Shift_Right( V, 7 ) and 1 );
463
464 Pos := Pos + 8;
465 for I in 0..S'Length -1 loop
466 B(B'First+I) := Character'Pos( S(S'First + I) );
467 end loop;
468 end ToBitstream;
469 end ToBytestream;
470
471 -- padding & formatting of maximum 1960 bits of the given String
472 -- uses TMSR's OAEP schema:
(108 . 17)(108 . 17)
477 return Unsigned_8;
478 pragma Import(Intrinsic, Shift_Left);
479
480 -- conversions between bitstream and string
481 -- conversions between bytestream and string
482 -- NB: caller has to ensure correct size of output parameter! no checks here.
483 procedure ToString( B: in Bitstream; S: out String );
484 procedure ToBitstream( S: in String; B: out Bitstream );
485 procedure ToString( B: in Bytestream; S: out String );
486 procedure ToBytestream( S: in String; B: out Bytestream );
487
488 -- public wrapper for Sponge to use String for input/output
489 procedure HashKeccak( Input : in String;
490 Output : out String;
491 Block_Len : in Keccak_Rate := Default_Bitrate);
492 Block_Len : in Keccak_Rate := Default_Byterate);
493
494 -- wrapper for calling Keccak hashing from C, with DEFAULT bitrate
495 -- wrapper for calling Keccak hashing from C, with DEFAULT byterate
496 -- @param Input the input string, as array of characters (C style)
497 -- @param LenIn the length of the input string (as number of OCTETS)
498 -- @param LenOut the desired number of OCTETS to be returned as output
- 3735CBB1DEE9B07A59BBB461BA507613D83D6A67B9CDF5298613EF27074E6962C926C96A491501A315907C01C3E16CC6FD56AACF58106306D56D67D9835753C5(1 . 11)(1 . 14)
503 with Interfaces; use Interfaces;
504 with SMG_OAEP; use SMG_OAEP;
505 with SMG_Keccak; use SMG_Keccak;
506 with Ada.Exceptions; use Ada.Exceptions;
507 with Ada.Text_IO; use Ada.Text_IO;
508 with Ada.Strings.Fixed; use Ada.Strings.Fixed;
509 with Interfaces; use Interfaces;
510 with System;
511
512 procedure SMG_Keccak.Test is
513 package Octet_IO is new Ada.Text_IO.Modular_IO(Interfaces.Unsigned_8);
514
515 --types
516 type Keccak_Perms is (None, Theta, Rho, Pi, Chi, Iota);
517 type Test_Vector is array(Keccak_Perms) of State;
(32 . 23)(35 . 14)
519 end loop;
520 end;
521
522 procedure print_bitstream(B: in Bitstream; Title: in String) is
523 Hex : array(0..15) of Character := ("0123456789ABCDEF");
524 HexString : String(1..B'Length/4);
525 C : Natural;
526 Pos : Natural;
527 begin
528 for I in 1..B'Length/4 loop
529 Pos := (I-1)*4 + B'First;
530 C := Natural( B(Pos) ) * 8 +
531 Natural( B(Pos + 1) ) * 4 +
532 Natural( B(Pos + 2) ) * 2 +
533 Natural( B(Pos + 3) );
534 HexString(I) := Hex(C);
535 end loop;
536 procedure print_bytestream(B: in Bytestream; Title: in String) is
537 begin
538 Put_Line("---" & Title & "---");
539 Put_Line(HexString);
540 end print_bitstream;
541 for Pos in B'First..B'Last loop
542 Octet_IO.Put(Item => B(Pos), Width => 2, Base => 16);
543 end loop;
544 New_Line;
545 end print_bytestream;
546
547 function read_state(File: in FILE_TYPE; Oct: Positive :=8) return State is
548 S: State;
(159 . 74)(153 . 61)
550 end loop;
551 end test_one_round;
552
553 procedure test_bits_to_word_conversion is
554 bits: Bitword := (others => 0);
555 obtained_bits: Bitword := (others => 0);
556 procedure test_bytes_to_word_conversion is
557 bytes: Byteword := (others => 0);
558 obtained_bytes: Byteword := (others => 0);
559 expected: ZWord;
560 msbexpected: ZWord;
561 obtained: ZWord;
562 begin
563 expected := 16#8FA4F19E0287BBE7#;
564 bits := (1,1,1,0, 0,1,1,1, 1,1,0,1, 1,1,0,1, 1,1,1,0, 0,0,0,1, 0,1,0,0,
565 0,0,0,0, 0,1,1,1, 1,0,0,1, 1,0,0,0, 1,1,1,1, 0,0,1,0, 0,1,0,1,
566 1,1,1,1, 0,0,0,1);
567 obtained := BitsToWord(bits);
568 obtained_bits := WordToBits(expected);
569 msbexpected := 16#F1258F7940E1DDE7#;
570 bytes := (231, 187, 135, 2, 158, 241, 164, 143); --LSByte order!
571
572 obtained := BytesToWordLE(bytes);
573 obtained_bytes := WordToBytesBE(msbexpected);
574
575 if obtained /= expected then
576 Put_Line("FAIL: bits to word");
577 Put_Line("FAIL: bytes to word");
578 Put_Line("Expected: " & ZWord'Image(expected));
579 Put_Line("Obtained: " & ZWord'Image(obtained));
580 else
581 Put_Line("PASSED: bits to word");
582 Put_Line("PASSED: bytes to word");
583 end if;
584
585 if obtained_bits /= bits then
586 Put_Line("FAIL: word to bits");
587 if obtained_bytes /= bytes then
588 Put_Line("FAIL: word to bytes");
589 Put("Expected: ");
590 for I in Bitword'Range loop
591 Put(Bit'Image(bits(I)));
592 for I in Byteword'Range loop
593 Put(Interfaces.Unsigned_8'Image(bytes(I)));
594 end loop;
595 Put_Line("");
596 Put_Line("Obtained: ");
597 for I in Bitword'Range loop
598 Put(Bit'Image(obtained_bits(I)));
599 for I in Byteword'Range loop
600 Put(Interfaces.Unsigned_8'Image(obtained_bytes(I)));
601 end loop;
602 Put_Line("");
603 else
604 Put_Line("PASSED: word to bits");
605 Put_Line("PASSED: word to bytes");
606 end if;
607 end test_bits_to_word_conversion;
608 end test_bytes_to_word_conversion;
609
610 procedure test_flip is
611 B: constant Bitword := (1, 0, 1, 1, 1, 1, 0, 0,
612 1, 1, 1, 0, 0, 0, 0, 1,
613 0, 1, 1, 0, 0, 0, 1, 0,
614 1, 1, 1, 1, 1, 1, 1, 1,
615 1, 1, 0, 1, 1, 0, 0, 1,
616 0, 0, 0, 0, 0, 0, 0, 0,
617 0, 0, 1, 1, 0, 0, 0, 1,
618 0, 0, 0, 1, 1, 0, 0, 0);
619 Expected: Bitword := (0, 0, 0, 1, 1, 0, 0, 0,
620 0, 0, 1, 1, 0, 0, 0, 1,
621 0, 0, 0, 0, 0, 0, 0, 0,
622 1, 1, 0, 1, 1, 0, 0, 1,
623 1, 1, 1, 1, 1, 1, 1, 1,
624 0, 1, 1, 0, 0, 0, 1, 0,
625 1, 1, 1, 0, 0, 0, 0, 1,
626 1, 0, 1, 1, 1, 1, 0, 0);
627 Output : Bitword;
628 B : Byteword := (231, 187, 135, 2, 158, 241, 164, 143);
629 Expected: Byteword := (143, 164, 241, 158, 2, 135, 187, 231);
630 Output : Byteword;
631 begin
632 Output := FlipOctets( B );
633 if Output /= Expected then
634 Put_Line( "FAILED: flip octets" );
635 Put_Line( "Expected: " );
636 for I of Expected loop
637 Put(Bit'Image(I));
638 Put(Interfaces.Unsigned_8'Image(I));
639 end loop;
640 new_line(1);
641 Put_Line( "Output: " );
642 for I of Output loop
643 Put(Bit'Image(I));
644 Put(Interfaces.Unsigned_8'Image(I));
645 end loop;
646 new_line(1);
647 else
(235 . 72)(216 . 97)
649 end test_flip;
650
651 procedure test_sponge is
652 Bitrate : constant Keccak_Rate := 1344;
653 Input : Bitstream(1..5) := (1, 1, 0, 0, 1);
654 Bitrate : constant Keccak_Rate := 1344 / 8;
655 Input : Bytestream(1..1);
656 Hex : array(0..15) of Character := ("0123456789ABCDEF");
657 C : Natural;
658 HexPos : Natural;
659 Error : Natural;
660 Pos : Natural;
661 ExpHex : constant String :=
662 "CB7FFB7CE7572A06C537858A0090FC2888C3C6BA9A3ADAB4"&
663 "FE7C9AB4EFE7A1E619B834C843A5A79E23F3F7E314AA597D"&
664 "9DAD376E8413A005984D00CF954F62F59EF30B050C99EA64"&
665 "E958335DAE684195D439B6E6DFD0E402518B5E7A227C48CF"&
666 "239CEA1C391241D7605733A9F4B8F3FFBE74EE45A40730ED"&
667 "1E2FDEFCCA941F518708CBB5B6D5A69C30263267B97D7B29"&
668 "AC87043880AE43033B1017EFB75C33248E2962892CE69DA8"&
669 "BAF1DF4C0902B16C64A1ADD42FF458C94C4D3B0B32711BBA"&
670 "22104989982543D1EF1661AFAF2573687D588C81113ED7FA"&
671 "F7DDF912021FC03D0E98ACC0200A9F7A0E9629DBA33BA0A3"&
672 "C03CCA5A7D3560A6DB589422AC64882EF14A62AD9807B353"&
673 "8DEE1548194DBD456F92B568CE76827F41E0FB3C7F25F3A4"&
674 "C707AD825B289730FEBDFD22A3E742C6FB7125DE0E38B130"&
675 "F3059450CA6185156A7EEE2AB7C8E4709956DC6D5E9F99D5"&
676 "0A19473EA7D737AC934815D68C0710235483DB8551FD8756"&
677 "45692B4E5E16BB9B1142AE300F5F69F43F0091D534F372E1"&
678 "FFC2E522E71003E4D27EF6ACCD36B2756FB5FF02DBF0C96B"&
679 "CAE68E7D6427810582F87051590F6FB65D7B948A9C9D6C93"&
680 "AF4562367A0AD79109D6F3087C775FE6D60D66B74F8D29FB"&
681 "4BA80D0168693A748812EA0CD3CA23854CC84D4E716F4C1A"&
682 "A3B340B1DED2F304DFDBACC1D792C8AC9A1426913E3F67DB"&
683 "790FD5CFB77DAA29";
684 Output : Bitstream( 1 .. ExpHex'Length * 4 );
685 HexString : String( 1 .. ExpHex'Length );
686 begin
687 ExpHex : constant String :=
688 --for 129 aka 1000 0001
689 -- "4BAB86C1E1C067A913F62EFD0D65AF58A9268A80A1D8A606F8"&
690 -- "72F535CDE3F1D66704093C78E6F1A8AFA7D9C6D1C016BA88ED"&
691 -- "3577450B2B339745ACF467E6DE357A14EC1B1E005E75156FF2"&
692 -- "B131F224CB2851F9D70D88ACEE2A7C05B9EF0724C1C8653E01"&
693 -- "A55B0A51145C73F23D6C31E0087D2C414B08939F1E67480867"&
694 -- "923B3FC7706675678A50260A62DBBFC38A144D75179DFBCA7B"&
695 -- "DA3CD87C7B8FFD0F8F12149EE6EAF0322BD48A079B3039A62C"&
696 -- "E1A8A5E9BCB03CE38C61ACF3AA9B9FBB159D7EB212054F7DBA"&
697 -- "D7ACE8EF0F70B0863E9E6E018F6AE23D74B01707ED59452B73"&
698 -- "862579B07C3B20DB9E5AA2479E98C0DBE6FD290FCE7F55BDA7"&
699 -- "8C1ED4A6C6A61E373F0A9D154AFF2DC86673658AF2494AAD09"&
700 -- "B8409C9B48D217FF354797BFED51807272B3C3AFE52F80FE4A"&
701 -- "4180ABE14296FF09A5024AED31F310F870288E91CB58569EE1"&
702 -- "FAA2D558E404D2ADFDD96480AE51CBF7FE6D19E8F0FEBC21DA"&
703 -- "88D597CA0C2998B95DDA72EF4C749F965688A1E133698E9E71"&
704 -- "15F3AEC61ADB7CCB279504FA716E7A059564A8DC5E20535A33"&
705 -- "E781C116B5B72B803E204BB25D91192756A575C1D9513282E1"&
706 -- "D8204AABE5DAA0A7774A296F2E4B9A87A87F72CD16A00639E7"&
707 -- "9EF280227975E05CED112346D3AE1DCE1E12EBA9A5673B29C7"&
708 -- "12AE3546D9CD3E09BCA2F2AAD46FFFCC2418E08604BFE30650"&
709 -- "549CF10FE6339D769D628828";
710
711 --for 19 aka 00010011
712 "18F5F5E68207EA4A2F5A992AA4415DDC5DA7EBE12D74CF9E"&
713 "0F33205D4E998E09883471A929959B146733C0D1FAD57919"&
714 "C6F5B5AA64130266AB5D36666AA896FC69D14E821873138E"&
715 "1C53B92FF6106428E5E407AC9E7084DEC1E8819CFB09DD54"&
716 "0DE980C631F67BF0CE55F1D6274E5E4274C1D966551B4A6F"&
717 "DFD780710872F4A8D4DF380F530EFF443355AAC86CA3AC50"&
718 "F65C0339B107B479411B8EFB8860066A2016513E8B3B9E23"&
719 "9A5EEF664EA5B50143F9152E45890078D174A75C837633A8"&
720 "76E9842316CBDACAFACB87D48E57C6A6948CE71F4A934AB0"&
721 "E73E8107F28B3E4CE2CA9A5828F3097126D7141FCF8E6DA4"&
722 "FDA017805782BD761663B43AB607914E6FC853443A240E93"&
723 "F13C228394C036D0E51CD926D033825951279D4A658F6F81"&
724 "5406A8695685C255237CDC6CDD16EC743A42D32BBDDF50A3"&
725 "6033E3121B19049AA127138C58411C7B9E7DF4A130C5A3A1"&
726 "D7253EC804379A75BF443F54575E96DF71757FEFB8EF4634"&
727 "861B2816BAC62B54A88D520D373E7AAAB6F564DEDECC7140"&
728 "0B7113BFF9B88AA62EFEC914401FD54B394C54E4B14E7423"&
729 "99847A7D1E3EEAC173202B275F7A79E4E6721AA29A9EB974"&
730 "D30F72D666A9F7BD7C3FD0EA39239289EB8BA56E3EB4DF94"&
731 "D516ADBEE177CE1462379F8A22C82A315D7A4C7BDAE1D0A5"&
732 "4A4878C81F56011CDD53D49D2366CCF2D9BBCA0494BD72B4"&
733 "17E0C6987118B8F6";
734 Output : Bytestream( 1 .. ExpHex'Length / 2 );
735 begin
736 -- Input(Input'First) := 129; --1000 0001--
737 Input(Input'First) := 19; --00010011 MSB--
738 -- Input(Input'First) := 200; --11001000 MSB--
739 Put_Line("---sponge test---");
740 Sponge(Input, Output, Bitrate);
741 Put_Line("Input is:");
742 for I of Input loop
743 Put(Bit'Image(I));
744 Put(Interfaces.Unsigned_8'Image(I));
745 end loop;
746 new_line(1);
747
748 Put_Line("Output is:");
749 for I of Output loop
750 Put(Bit'Image(I));
751 Put(Interfaces.Unsigned_8'Image(I));
752 end loop;
753 new_line(1);
754
755 Error := 0;
756 for I in 1..Output'Length/4 loop
757 Pos := Output'First + (I-1)*4;
758 C := Natural( Output( Pos ) ) +
759 Natural( Output( Pos + 1 ) ) * 2 +
760 Natural( Output( Pos + 2 ) ) * 4 +
761 Natural( Output( Pos + 3 ) ) * 8;
762 HexPos := I + 2 * ( I mod 2 ) - 1;
763 Hexstring(HexPos) := Hex( C );
764 if Hexstring(HexPos) /= ExpHex(HexPos) then
765 Error := Error + 1;
766 -- check output
767 declare
768 PO, PE: Natural;
769 Pass: Boolean := True;
770 begin
771
772 for I in 0..Output'Length-1 loop
773 PO := Output'First + I;
774 PE := ExpHex'First + I*2;
775 if Hex(Natural(Output(PO) mod 16)) /= ExpHex(PE+1) or
776 Hex(Natural(Output(PO) / 16)) /= ExpHex(PE) then
777 Put_Line("FAIL: test_sponge");
778 Octet_IO.Put(Output(Output'First+I), Width=>2, Base=>16);
779 Put_Line(" vs exp: " & ExpHex(ExpHex'First+I*2..ExpHex'First+I*2+1));
780 Pass := False;
781 exit;
782 end if;
783 end loop;
784 if Pass then
785 Put_Line("PASS: test_sponge");
786 end if;
787 end loop;
788 Put_Line("Expected: ");
789 Put_Line(ExpHex);
790 Put_Line("Obtained: ");
791 Put_Line(Hexstring);
792 Put_Line("Errors found: " & Natural'Image(Error));
793
794 end;
795 end test_sponge;
796
797 procedure test_keccak_function(T: in Test_Round) is
(315 . 56)(321 . 56)
799 end if;
800 end test_keccak_function;
801
802 procedure test_bitstream_conversion is
803 procedure test_bytestream_conversion is
804 S: String := "Aa*/";
805 E: Bitstream( 0 .. 31 ) := (1, 0, 0, 0, 0, 0, 1, 0,
806 1, 0, 0, 0, 0, 1, 1, 0,
807 0, 1, 0, 1, 0, 1, 0, 0,
808 1, 1, 1, 1, 0, 1, 0, 0);
809 B: Bitstream( 0 .. 31 );
810 E: Bytestream( 0..3 ) := (65, 97, 42, 47);
811 B: Bytestream( 0..3 );
812 SS: String := " t ";
813 begin
814 Put_Line("---Testing string to bitstream conversion---");
815 ToBitstream( S, B );
816 Put_Line("---Testing string to bytestream conversion---");
817 ToBytestream( S, B );
818 if E /= B then
819 Put_Line("FAILED: string to bitstream conversion.");
820 Put_Line("FAILED: string to bytestream conversion.");
821 for I in 0..3 loop
822 Put_Line("Got " & Interfaces.Unsigned_8'Image(B(I)) & " vs " &
823 Interfaces.Unsigned_8'Image(E(I)));
824 end loop;
825 else
826 Put_Line("PASSED: string to bitstream conversion.");
827 Put_Line("PASSED: string to bytestream conversion.");
828 end if;
829
830 Put_Line("---Testing bitstream to string conversion---");
831 Put_Line("---Testing bytestream to string conversion---");
832 ToString( B, SS );
833 if SS /= S then
834 Put_Line("FAILED: bitstream to string conversion");
835 Put_Line("FAILED: bytestream to string conversion");
836 Put_Line("EXPECTED: " & S);
837 Put_Line("OUTPUT: " & SS);
838 else
839 Put_Line("PASSED: bitstream to string conversion");
840 Put_Line("PASSED: bytestream to string conversion");
841 end if;
842 end test_bitstream_conversion;
843 end test_bytestream_conversion;
844
845 procedure test_hash_keccak is
846 S: String := "X";
847 O: String := "abc";
848 B: Bitstream( 0 .. 23 );
849 BB: Bitstream( 1.. 8):= (0, 0, 0, 1, 1, 0, 1, 0);
850 Exp: Bitstream( 0 .. 23 ) := (1, 1, 1, 0, 0, 0, 0, 1,
851 0, 1, 1, 0, 0, 0, 1, 0,
852 1, 1, 1, 0, 0, 0, 1, 1);
853 B: Bytestream( 0 .. 2 );
854 BB: Bytestream( 1.. 3);
855 Exp: Bytestream( 1 .. 3 ) := (225, 98, 227);
856 begin
857 BB(BB'First) := 26;
858 Put_Line("----Testing hash keccak on string " & S & "----");
859 HashKeccak(S, O);
860 ToBitstream( O, B );
861 ToBytestream( O, B );
862 if B /= Exp then
863 Put_Line("FAILED: testing hash keccak on string");
864 Put_Line("Output:");
865 for I of B loop
866 Put( Bit'Image( I ) );
867 Put( Interfaces.Unsigned_8'Image( I ) );
868 end loop;
869 new_line(1);
870 Put_Line("Expected:");
871 for I of Exp loop
872 Put( Bit'Image( I ) );
873 Put( Interfaces.Unsigned_8'Image( I ) );
874 end loop;
875 else
876 Put_Line("PASSED: testing hash keccak on string");
(466 . 18)(472 . 46)
878
879 end test_oaep;
880
881 procedure test_all_bitrates is
882 procedure test_all_byterates is
883 Input : constant String := "hello, world";
884 Bin : Bitstream( 0 .. Input'Length * 8 - 1 ) := ( others => 0 );
885 Bout : Bitstream( 0 .. 100 ) := ( others => 0 );
886 Bin : Bytestream( 0 .. Input'Length - 1 ) := ( others => 0 );
887 Bout : Bytestream( 0 .. 100 ) := ( others => 0 );
888 begin
889 ToBitstream( Input, Bin );
890 ToBytestream( Input, Bin );
891 Put_Line("Testing all bitrates:");
892 for Bitrate in Keccak_Rate'Range loop
893 Sponge(Bin, Bout, Bitrate);
894 Put_Line("PASSED: keccak with bitrate " & Integer'Image(Bitrate));
895 for Byterate in Keccak_Rate'Range loop
896 Sponge(Bin, Bout, Byterate);
897 Put_Line("PASSED: keccak with byterate " & Integer'Image(Byterate));
898 end loop;
899 end test_all_byterates;
900
901 procedure test_bitreverse is
902 A: Interfaces.Unsigned_8;
903 B: Interfaces.Unsigned_8;
904 Pass: Boolean := True;
905 begin
906 for I in 0..255 loop
907 -- reverse the bits
908 A := Interfaces.Unsigned_8(I);
909 B := 0;
910 for J in 0..7 loop
911 B := B*2 + A mod 2;
912 A := A / 2;
913 end loop;
914 end test_all_bitrates;
915 -- compare with tabled value
916 if B /= Reverse_Table(I) then
917 Pass := False;
918 Put_Line("FAIL: reverse table value is wrong Table(" &
919 Integer'Image(I) & ")= " &
920 Interfaces.Unsigned_8'Image(Reverse_Table(I)) &
921 " but should be " &
922 Interfaces.Unsigned_8'Image(B));
923 end if;
924 end loop;
925 if Pass then
926 Put_Line("PASS: bitreverse table is correct.");
927 end if;
928 end test_bitreverse;
929
930 -- end of helper methods
931
(510 . 8)(544 . 8)
933 -- test also Keccak_Function as a whole --
934 test_keccak_function(T);
935
936 -- test BitsToWord and WordToBits
937 test_bits_to_word_conversion;
938 -- test BytesToWord and WordToBytes
939 test_bytes_to_word_conversion;
940
941 -- test Sponge construction
942 test_sponge;
(520 . 9)(554 . 11)
944 test_flip;
945
946 -- test bitstream conversion
947 test_bitstream_conversion;
948 test_bytestream_conversion;
949
950 -- test hash keccak (strings version)
951 Put_Line("Sytem's BIT order is " &
952 System.Bit_Order'Image(System.Default_Bit_Order));
953 test_hash_keccak;
954
955 -- test oaep encrypt + decrypt
(531 . 7)(567 . 10)
957 -- test xor on strings
958 test_xor_strings;
959
960 -- test ALL bitrates of the Keccak sponge
961 test_all_bitrates;
962 -- test ALL byterates of the Keccak sponge
963 test_all_byterates;
964
965 -- test the values in the lookup table for bit reversing
966 test_bitreverse;
967
968 end SMG_Keccak.Test;