tree checksum vpatch file split hunks

all signers: diana_coman

antecedents: eucrypt_ch9_keccak_endianness

press order:

eucrypt_genesisdiana_coman
eucrypt_ch6_keccak_permutationsdiana_coman
eucrypt_ch7_keccak_spongediana_coman
eucrypt_ch9_keccak_endiannessdiana_coman
eucrypt_ch10_oaep_tmsrdiana_coman

patch:

- 589991A191E8D120F9338FD279017CAD6C04AAACE3045C9FCF337AC156C7DF9AAE8D8D353FA32C08439D005A8CB30D309E957EB26D5A1CB8BEA2D4FADD44C8C6
+ 88E40423C88BA2AC7D44225B388794D61719746B02412E2DAE4684BCFA72399978D599F9301B4A2BE101B41769D3C5B20DE6FF94E76A01FF767EDC00746B8B96
eucrypt/smg_keccak/smg_keccak.adb
(5 . 8)(5 . 8)
5
6 -- public function, sponge
7 procedure Sponge( Input : in Bitstream;
8 Block_Len : in Keccak_Rate;
9 Output : out Bitstream) is
10 Output : out Bitstream;
11 Block_Len : in Keccak_Rate := Default_Bitrate ) is
12 Internal : State := (others => (others => 0));
13 begin
14 --absorb input into sponge in a loop on available blocks, including padding
- 63A6A9F8168017265C7CCF9B3D7DFFD7C3CD21F529AE88993C3B05E0DCAFF9530C68B3420B58F643FF2425F575C66E9E0DF19ED25C8A38F56A0D1E713E27B15C
+ 7503D06B8F87F1CD8A4246A7BAF27BA9431646E65F07FEA64173F24852BE71DC493C3E866D5C16F6723F80C6E6ED1479A46FAC9DEA5FDF02B0387724BDB99E08
eucrypt/smg_keccak/smg_keccak.ads
(13 . 6)(13 . 9)
19 --therefore keccak function 1600 with current
20 --constants (5*5*2^6)
21
22 Default_Bitrate: constant := 1344; --max bits the sponge can eat/spit without
23 --needing to scramble the state
24
25 --constants: dimensions of keccak state and number of rounds
26 XY_Length: constant := 5;
27 Z_Length: constant := 2**Keccak_L;
(49 . 12)(52 . 12)
29 -- public function, the sponge itself
30 -- Keccak sponge structure using Keccak_Function, Pad and a given bitrate;
31 -- Input - the stream of bits to hash (the message)
32 -- Output - a bitstream of desired size for holding output
33 -- Block_Len - the bitrate to use; this is effectively the block length
34 -- for splitting Input AND squeezing output between scrambles
35 -- Output - a bitstream of desired size for holding output
36 procedure Sponge(Input : in Bitstream;
37 Block_Len : in Keccak_Rate;
38 Output : out Bitstream);
39 Output : out Bitstream;
40 Block_Len : in Keccak_Rate := Default_Bitrate );
41
42 private
43 -- these are internals of the keccak implementation, not meant to be directly
-
+ 399C9451D688077B5F5701C05032A4F39B0CF3FAE9CB841123F23680C0C2D2DCE5BA5E1F7322B9158642380D1F9EF948A44F7A425DE699965D8706323883CFF7
eucrypt/smg_keccak/smg_oaep.adb
(0 . 0)(1 . 202)
48 -- S.MG, 2018
49
50 package body SMG_OAEP is
51
52 procedure HashKeccak( Input : in String;
53 Output : out String;
54 Block_Len : in Keccak_Rate := Default_Bitrate) is
55 BIn : Bitstream( 0 .. Input'Length * 8 - 1 );
56 BOut : Bitstream( 0 .. Output'Length * 8 - 1 );
57 begin
58 ToBitstream( Input, BIn);
59 Sponge( BIn, BOut, Block_Len);
60 ToString( BOut, Output );
61 end HashKeccak;
62
63 function Hash( Input : Interfaces.C.Char_Array;
64 LenIn : Interfaces.C.size_t;
65 LenOut : Interfaces.C.size_t;
66 Block_Len : Interfaces.C.int := Default_Bitrate)
67 return Interfaces.C.Char_Array is
68 AdaLenIn : Natural := Natural(LenIn);
69 AdaLenOut : Natural := Natural(LenOut);
70 InStr : String( 0 .. AdaLenIn-1 ) := (others => '0');
71 OutStr : String( 0 .. AdaLenOut-1 ) := (others => '0');
72 COut : Interfaces.C.Char_Array( 0 .. LenOut-1 );
73 Count : Natural := AdaLenOut;
74 CCount : Interfaces.C.size_t := LenOut;
75 begin
76 Interfaces.C.To_Ada( Input, InStr, AdaLenIn );
77 HashKeccak( InStr, OutStr, Keccak_Rate(Block_Len) );
78 Interfaces.C.To_C( OutStr, COut, CCount );
79 return COut;
80 end Hash;
81
82 -- conversion between types
83 procedure ToString(B: in Bitstream; S: out String ) is
84 N : Natural;
85 Pos : Natural;
86 begin
87 Pos := B'First;
88 for I in S'Range loop
89 N := Natural( B( Pos ) ) +
90 Natural( B( Pos + 1 ) ) * 2 +
91 Natural( B( Pos + 2 ) ) * 4 +
92 Natural( B( Pos + 3 ) ) * 8 +
93 Natural( B( Pos + 4 ) ) * 16 +
94 Natural( B( Pos + 5 ) ) * 32 +
95 Natural( B( Pos + 6 ) ) * 64 +
96 Natural( B( Pos + 7 ) ) * 128;
97 Pos := Pos + 8;
98 S( I ) := Character'Val( N );
99 end loop;
100 end ToString;
101
102 procedure ToBitstream(S: in String; B: out Bitstream ) is
103 V : Unsigned_8;
104 Pos : Natural;
105 begin
106 Pos := B'First;
107 for C of S loop
108 V := Character'Pos( C );
109 B( Pos ) := Bit( V and 1 );
110 B( Pos + 1 ) := Bit( Shift_Right( V, 1 ) and 1 );
111 B( Pos + 2 ) := Bit( Shift_Right( V, 2 ) and 1 );
112 B( Pos + 3 ) := Bit( Shift_Right( V, 3 ) and 1 );
113 B( Pos + 4 ) := Bit( Shift_Right( V, 4 ) and 1 );
114 B( Pos + 5 ) := Bit( Shift_Right( V, 5 ) and 1 );
115 B( Pos + 6 ) := Bit( Shift_Right( V, 6 ) and 1 );
116 B( Pos + 7 ) := Bit( Shift_Right( V, 7 ) and 1 );
117
118 Pos := Pos + 8;
119 end loop;
120 end ToBitstream;
121
122 -- padding & formatting of maximum 1960 bits of the given String
123 -- uses TMSR's OAEP schema:
124 -- 1.format M00 as: [random octet][sz1][sz2]"TMSR-RSA"[random]*Message
125 -- where sz1 and sz2 store the length of the message in bits
126 -- the random octets before message are padding to make OAEP_LENGTH_OCTETS
127 -- 2. R = OAEP_HALF_OCTETS random bits
128 -- 3. X = M00 xor hash(R)
129 -- 4. Y = R xor hash(X)
130 -- 5. Result is X || Y
131 -- NB: the Entropy parameter should be random octets from which this method
132 -- will use as many as required for the OAEP encryption of given Msg
133 -- NB: at MOST OAEP_LENGTH_OCTETS - 11 octets of Msg! (Msg at most 1960 bits)
134 procedure OAEP_Encrypt( Msg : in String;
135 Entropy : in OAEP_Block;
136 Output : out OAEP_Block) is
137 M00 : OAEP_HALF;
138 R : OAEP_HALF;
139 HashR : OAEP_HALF;
140 X : OAEP_HALF;
141 HashX : OAEP_HALF;
142 Y : OAEP_HALF;
143 MsgLen : Natural;
144 MaxLen : Natural;
145 PadLen : Natural;
146 TMSR : constant String := "TMSR-RSA";
147 begin
148 -- calculate maximum length of msg and needed amount of padding
149 -- make sure also that only MaxLen octets at most are used from Msg
150 MaxLen := OAEP_HALF_OCTETS - TMSR'Length - 3; -- maximum msg that fits
151 MsgLen := Msg'Length; -- real msg length
152 if MsgLen > MaxLen then
153 MsgLen := MaxLen; --only first MaxLen octets will be considered
154 PadLen := 0; --no padding needed
155 else
156 PadLen := MaxLen - MsgLen; -- msg is potentially too short, add padding
157 end if;
158
159 -- step 1: header and format to obtain M00
160 -- first octet is random bits
161 M00( M00'First ) := Entropy( Entropy'First );
162
163 -- next 2 octets hold the used length of Msg (number of octets)
164 M00( M00'First + 2) := Character'Val( ( MsgLen * 8 ) mod 255 );
165 M00( M00'First + 1) := Character'Val( ( (MsgLen * 8 ) / 255 ) mod 255 );
166
167 -- next 8 octets are reserved for later use, currently "TMSR-RSA"
168 M00( M00'First + 3 .. M00'First + 10 ) := TMSR;
169
170 -- random bits for padding, if Msg is less than 245 octets
171 for I in 1 .. PadLen loop
172 M00( M00'First + 10 + I ) := Entropy( Entropy'First + I );
173 end loop;
174
175 -- the message itself
176 M00( M00'Last - MsgLen + 1 .. M00'Last ) :=
177 Msg( Msg'First .. Msg'First + MsgLen - 1 );
178
179 -- step 2: R = OAEP_HALF_OCTETS random octets
180 -- can take LAST octets from given entropy as they are NOT used before
181 -- (even if original message was empty, padding uses at most half - 10
182 -- while entropy has full block length)
183 R := Entropy( Entropy'Last - OAEP_HALF_OCTETS + 1 .. Entropy'Last );
184
185 -- step 3: X = M00 xor hash(R)
186 HashKeccak( R, HashR );
187 XOR_Strings( M00, HashR, X );
188
189 -- step 4: Y = R xor hash(X)
190 HashKeccak( X, HashX );
191 XOR_Strings( R, HashX, Y );
192
193 -- step 5: Output is X || Y
194 Output( Output'First .. Output'First + X'Length - 1 ) := X;
195 Output( Output'Last - Y'Length + 1 .. Output'Last ) := Y;
196
197 end OAEP_Encrypt;
198
199 procedure OAEP_Decrypt( Encr : in OAEP_Block;
200 Len : out Natural;
201 Output : out OAEP_HALF;
202 Success : out Boolean ) is
203 X, Y, M, R : OAEP_HALF;
204 HashX, HashR : OAEP_HALF;
205 MaxLen : constant Natural := OAEP_LENGTH_OCTETS - 11;
206 LenOctets : Natural;
207 begin
208 -- step 1: separate X and Y
209 X := Encr( Encr'First .. Encr'First + X'Length - 1 );
210 Y := Encr( Encr'Last - Y'Length + 1 .. Encr'Last );
211
212 -- step 2: R = Y xor hash(X)
213 HashKeccak( X, HashX );
214 XOR_Strings( Y, HashX, R );
215
216 -- step 3: M = X xor hash(R)
217 HashKeccak( R, HashR );
218 XOR_Strings( X, HashR, M );
219
220 -- step 4: extract length and message
221 Len := Character'Pos( M( M'First + 1 ) ) * 255 +
222 Character'Pos( M( M'First + 2 ) );
223 LenOctets := Len / 8;
224
225 if LenOctets > MaxLen or LenOctets < 0 then
226 Success := False; -- error, failed to retrieve message
227 else
228 Success := True;
229 Output( Output'First .. Output'First + LenOctets - 1 ) :=
230 M( M'Last - LenOctets + 1 .. M'Last );
231 end if;
232
233 end OAEP_Decrypt;
234
235 -- helper method, xor on strings
236 -- NB: only Output'Length bits will be considered from S1 and S2
237 -- NB: caller is responsible for S1 and S2 being long enough!
238 procedure XOR_Strings( S1: in String; S2: in String; Output: out String ) is
239 V1, V2: Unsigned_8;
240 begin
241 for I in Output'Range loop
242 V1 := Character'Pos( S1( I ) );
243 V2 := Character'Pos( S2( I ) );
244 Output( I ) := Character'Val( V1 xor V2 );
245 end loop;
246 end XOR_Strings;
247
248
249 end SMG_OAEP;
-
+ ED6FC57F63DEF71E7C286F1E9115264412611AD19E925CB0EDE29C3BDA6CD40F6F63CCE6CDC9ECC2C7F55E555292D7EBA058FBCF4C9A49AF24CAB43B8345F253
eucrypt/smg_keccak/smg_oaep.ads
(0 . 0)(1 . 90)
254 -- Implementation of TMSR's OAEP with Keccak as hash function
255 --
256 -- S.MG, 2018
257
258 with SMG_Keccak; use SMG_Keccak; -- Keccak is used as hash function
259 with Interfaces; use Interfaces; -- for Unsigned_8 type and bit-level ops
260 with Interfaces.C; use Interfaces.C; -- for interop with C
261
262 package SMG_OAEP is
263 pragma Pure( SMG_OAEP ); -- stateless, no side effects -> can cache calls
264
265 -- fixed length of OAEP block in bits and in octets
266 OAEP_LENGTH_BITS : constant := 4096;
267 OAEP_LENGTH_OCTETS : constant := 512;
268 OAEP_HALF_OCTETS : constant := OAEP_LENGTH_OCTETS / 2;
269
270 -- subtypes used by the OAEP encrypt/decrypt
271 subtype OAEP_Block is String( 1 .. OAEP_LENGTH_OCTETS );
272 subtype OAEP_HALF is String( 1 .. OAEP_HALF_OCTETS );
273
274 -- padding & formatting of maximum 1960 bits of the given String
275 -- uses TMSR's OAEP schema:
276 -- 1.format M00 as: [random octet][sz1][sz2]"TMSR-RSA"[random]*Message
277 -- where sz1 and sz2 store the length of the message in bits
278 -- the random octets before message are padding to make OAEP_LENGTH_OCTETS
279 -- 2. R = OAEP_HALF_OCTETS random bits
280 -- 3. X = M00 xor hash(R)
281 -- 4. Y = R xor hash(X)
282 -- 5. Result is X || Y
283 -- NB: the Entropy parameter should be random octets from which this method
284 -- will use as many as required for the OAEP encryption of given Msg
285 -- NB: at MOST OAEP_LENGTH_OCTETS - 11 octets of Msg! (Msg at most 1960 bits)
286 procedure OAEP_Encrypt( Msg : in String;
287 Entropy : in OAEP_Block;
288 Output : out OAEP_Block);
289
290 -- This is the opposite of OAEP_Encrypt above.
291 -- @param Encr - an OAEP block previously obtained from OAEP_Encrypt
292 -- @param Len - this will hold the length of the obtained message (in bits!)
293 -- @param Output - the first Len octets of this are the recovered message
294 -- @param Success - set to TRUE if message was recovered, false otherwise
295 -- NB: when Success is FALSE, both Len and Output have undefined values
296 procedure OAEP_Decrypt( Encr : in OAEP_Block;
297 Len : out Natural;
298 Output : out OAEP_HALF;
299 Success : out Boolean);
300
301 -- helper method, xor on strings
302 -- NB: only Output'Length bits will be considered from S1 and S2
303 -- NB: caller is responsible for S1 and S2 being long enough!
304 procedure XOR_Strings( S1: in String; S2: in String; Output: out String );
305
306 -- gnat-specific methods for bit-level operations
307 function Shift_Right( Value : Unsigned_8;
308 Amount : Natural )
309 return Unsigned_8;
310 pragma Import(Intrinsic, Shift_Right);
311
312 function Shift_Left( Value : Unsigned_8;
313 Amount : Natural )
314 return Unsigned_8;
315 pragma Import(Intrinsic, Shift_Left);
316
317 -- conversions between bitstream and string
318 -- NB: caller has to ensure correct size of output parameter! no checks here.
319 procedure ToString( B: in Bitstream; S: out String );
320 procedure ToBitstream( S: in String; B: out Bitstream );
321
322 -- public wrapper for Sponge to use String for input/output
323 procedure HashKeccak( Input : in String;
324 Output : out String;
325 Block_Len : in Keccak_Rate := Default_Bitrate);
326
327 -- wrapper for calling from C
328 -- @param Input the input string, as array of characters (C style)
329 -- @param LenIn the length of the input string (as number of BITS)
330 -- @param LenOut the desired number of bits to be returned as output
331 -- @param Block_Len the bitrate used by the Keccak sponge (number of BITS)
332 -- @return an array of characters with first LenOut bits set to Keccak output
333
334 -- NB: caller HAS TO provide the length of the Input (parameter LenIn)
335 -- NB: caller HAS TO provide the length of the Output (parameter LenOut)
336 function Hash( Input : Interfaces.C.Char_Array;
337 LenIn : Interfaces.C.size_t;
338 LenOut : Interfaces.C.size_t;
339 Block_Len : Interfaces.C.int := Default_Bitrate)
340 return Interfaces.C.Char_Array;
341 pragma Export( C, Hash, "hash" );
342
343 end SMG_OAEP;
- F90807132CF1AD922F6B901A4CD35190646BAAD554E0CBAE71C570909AF0025260DED9BD163657917AF4B08F5B29AEB704076D4F5949D8F6B1D14F60C837800B
+ B9DD611C05352BC2DCD237EE59409CBBABF02068D8639CBDE73B6F273EA1480BB9C40CAB85F83FD7D56CE6CD59BBBE42F171CE90BD1AAAD265109B745FABB808
eucrypt/smg_keccak/tests/smg_keccak-test.adb
(1 . 3)(1 . 4)
348 with SMG_OAEP; use SMG_OAEP;
349 with SMG_Keccak; use SMG_Keccak;
350 with Ada.Exceptions; use Ada.Exceptions;
351 with Ada.Text_IO; use Ada.Text_IO;
(268 . 7)(269 . 7)
353 HexString : String( 1 .. ExpHex'Length );
354 begin
355 Put_Line("---sponge test---");
356 Sponge(Input, Bitrate, Output);
357 Sponge(Input, Output, Bitrate);
358 Put_Line("Input is:");
359 for I of Input loop
360 Put(Bit'Image(I));
(314 . 6)(315 . 123)
362 end if;
363 end test_keccak_function;
364
365 procedure test_bitstream_conversion is
366 S: String := "Aa*/";
367 E: Bitstream( 0 .. 31 ) := (1, 0, 0, 0, 0, 0, 1, 0,
368 1, 0, 0, 0, 0, 1, 1, 0,
369 0, 1, 0, 1, 0, 1, 0, 0,
370 1, 1, 1, 1, 0, 1, 0, 0);
371 B: Bitstream( 0 .. 31 );
372 SS: String := " t ";
373 begin
374 Put_Line("---Testing string to bitstream conversion---");
375 ToBitstream( S, B );
376 if E /= B then
377 Put_Line("FAILED: string to bitstream conversion.");
378 else
379 Put_Line("PASSED: string to bitstream conversion.");
380 end if;
381
382 Put_Line("---Testing bitstream to string conversion---");
383 ToString( B, SS );
384 if SS /= S then
385 Put_Line("FAILED: bitstream to string conversion");
386 Put_Line("EXPECTED: " & S);
387 Put_Line("OUTPUT: " & SS);
388 else
389 Put_Line("PASSED: bitstream to string conversion");
390 end if;
391 end test_bitstream_conversion;
392
393 procedure test_hash_keccak is
394 S: String := "X";
395 O: String := "abc";
396 B: Bitstream( 0 .. 23 );
397 BB: Bitstream( 1.. 8):= (0, 0, 0, 1, 1, 0, 1, 0);
398 Exp: Bitstream( 0 .. 23 ) := (1, 1, 1, 0, 0, 0, 0, 1,
399 0, 1, 1, 0, 0, 0, 1, 0,
400 1, 1, 1, 0, 0, 0, 1, 1);
401 begin
402 Put_Line("----Testing hash keccak on string " & S & "----");
403 HashKeccak(S, O);
404 Put_Line("OUTPUT: " & O);
405 ToBitstream( O, B );
406 if B /= Exp then
407 Put_Line("FAILED: testing hash keccak on string");
408 Put_Line("Output:");
409 for I of B loop
410 Put( Bit'Image( I ) );
411 end loop;
412 new_line(1);
413 Put_Line("Expected:");
414 for I of Exp loop
415 Put( Bit'Image( I ) );
416 end loop;
417 else
418 Put_Line("PASSED: testing hash keccak on string");
419 end if;
420 new_line(1);
421 end test_hash_keccak;
422
423 procedure test_xor_strings is
424 S1 : String := "ABC";
425 S2 : String := "CBA";
426 Exp : String := "...";
427 Result : String := "...";
428 begin
429 Exp( Exp'First ) := Character'Val( 2 );
430 Exp( Exp'First + 1 ) := Character'Val( 0 );
431 Exp( Exp'First + 2 ) := Character'Val( 2 );
432
433 Put_Line("----Testing xor on strings---");
434 XOR_Strings( S1, S2, Result);
435 Put_Line("S1 is " & S1);
436 Put_Line("S2 is " & S2);
437 Put_Line("S1 xor S2 is " & Result);
438 Put_Line("Result is: ");
439 for C of Result loop
440 Put( Natural'Image( Character'Pos( C ) ) );
441 end loop;
442 new_line(1);
443
444 if Result /= Exp then
445 Put_Line("FAILED: xor on strings");
446 else
447 Put_Line("PASSED: xor on strings");
448 end if;
449 end test_xor_strings;
450
451 procedure test_oaep is
452 Msg : String := "abcdefghij jihgfedcba123456789";
453 Encr : OAEP_Block := ( others => ' ' );
454 Decr : OAEP_HALF := ( others => ' ' );
455 Entropy : OAEP_Block := ( others => 'e' );
456 Len : Natural;
457 Flag : Boolean;
458 begin
459 Put_Line("----Testing OAEP Encrypt----");
460 OAEP_Encrypt( Msg, Entropy, Encr );
461
462 Put_Line("----Testing OAEP Decrypt----");
463 OAEP_Decrypt( Encr, Len, Decr, Flag );
464
465 Put_Line("Msg is: " & Msg);
466 Put_Line("Encr is: " & Encr);
467 Put_Line("Decr is: " & Decr);
468 Put_Line("Flag is: " & Boolean'Image( Flag ) );
469 Put_Line("Len is: " & Natural'Image( Len ) );
470
471 if Flag = False or
472 Len /= Msg'Length * 8 or
473 Decr( Decr'First .. Decr'First + Msg'Length - 1 ) /= Msg
474 then
475 Put_Line("FAILED: oaep test");
476 else
477 Put_Line("PASSED: oaep test");
478 end if;
479
480 end test_oaep;
481
482 -- end of helper methods
483
484 --variables
(354 . 4)(472 . 16)
486 -- test flipping octets
487 test_flip;
488
489 -- test bitstream conversion
490 test_bitstream_conversion;
491
492 -- test hash keccak (strings version)
493 test_hash_keccak;
494
495 -- test oaep encrypt + decrypt
496 test_oaep;
497
498 -- test xor on strings
499 test_xor_strings;
500
501 end SMG_Keccak.Test;