tree checksum vpatch file split hunks
all signers: diana_coman
antecedents: smg_comms_raw_types
press order:
smg_comms_genesis | diana_coman |
smg_comms_raw_types | diana_coman |
smg_comms_packing_serpent | diana_coman |
patch:
(1 . 2)(1 . 3)
5 532398 smg_comms_genesis diana_coman The first seed of an implementation of S.MG's communication protocol for Eulora: definitions for basic types, methods to/from network format, basic client/server test running locally on the same machine.
6 546000 smg_comms_raw_types diana_coman Part of layer 0 - raw types for the updated version of the protocol containing only two types of packets: 1470 octets RSA packet and 1472 octets Serpent packet.
7 546152 smg_comms_packing_serpent diana_coman Packing/Unpacking Serpent messages <-> Serpent packets. Includes Serpent implementation.
-(0 . 0)(1 . 77)
12 -- Packing/unpacking for Eulora's communication protocol:
13 -- Serpent Message to/from Serpent Packet
14 -- RSA Message to/from RSA Packet
15 -- S.MG, 2018
16
17 package body Packing is
18
19 -- Packing a Serpent message into Serpent package, using the given key
20 function Pack( Msg : in Raw_Types.Serpent_Msg;
21 K : in Serpent.Key )
22 return Raw_Types.Serpent_Pkt is
23
24 -- single Serpent blocks containing plain / encrypted data
25 Plain : Serpent.Block;
26 Encr : Serpent.Block;
27
28 -- Serpent Key Schedule - needed for direct encr/decr calls
29 KS : Serpent.Key_Schedule;
30
31 -- final resulting Serpent package
32 Pkt : Raw_Types.Serpent_Pkt := (others => 0);
33 begin
34 -- prepare the Serpent key schedule based on given key
35 Serpent.Prepare_Key( K, KS );
36
37 -- encrypt message block by block and copy result in packet
38 for I in 1 .. S_Blocks loop
39 -- get current block to encrypt
40 Plain := Msg( Msg'First + (I-1) * Block_Len ..
41 Msg'First + I * Block_Len - 1 );
42 -- encrypt with Serpent
43 Serpent.Encrypt( KS, Plain, Encr );
44 -- copy result to output packet
45 Pkt( Pkt'First + (I-1) * Block_Len ..
46 Pkt'First + I * Block_Len - 1 )
47 := Encr;
48 end loop;
49
50 -- return result
51 return Pkt;
52 end Pack;
53
54 -- Unpacking a Serpent packet into contained message, using the given key
55 function Unpack( Pkt : in Raw_Types.Serpent_Pkt;
56 K : in Serpent.Key)
57 return Raw_Types.Serpent_Msg is
58 -- single Serpent blocks containing plain / encrypted data
59 Plain : Serpent.Block;
60 Encr : Serpent.Block;
61
62 -- Serpent Key Schedule - needed for direct encr/decr calls
63 KS : Serpent.Key_Schedule;
64
65 -- the message extracted from the given packet
66 Msg : Raw_Types.Serpent_Msg := (others => 0);
67 begin
68 -- prepare the Serpent key for use
69 Serpent.Prepare_Key( K, KS );
70
71 -- decrypt the Serpent packet block by block
72 for I in 1 .. S_Blocks loop
73 -- get current block from input and decrypt
74 Encr := Pkt( Pkt'First + (I-1) * Block_Len ..
75 Pkt'First + I * Block_Len - 1 );
76 Serpent.Decrypt( KS, Encr, Plain );
77
78 -- copy result to its correct position in final output
79 Msg( Msg'First + (I-1) * Block_Len ..
80 Msg'First + I * Block_Len - 1 )
81 := Plain;
82 end loop;
83
84 -- return the result - the message content of given package
85 return Msg;
86 end Unpack;
87
88 end Packing;
-(0 . 0)(1 . 31)
93 -- Packing/unpacking for Eulora's communication protocol:
94 -- Serpent Message to/from Serpent Packet
95 -- RSA Message to/from RSA Packet
96 -- S.MG, 2018
97
98 with Raw_Types;
99 with Serpent;
100
101 package Packing is
102 -- no side effects or internal state
103 Pragma Pure(Packing);
104
105 -- Packing a Serpent message into Serpent package, using the given key
106 function Pack( Msg : in Raw_Types.Serpent_Msg;
107 K : in Serpent.Key )
108 return Raw_Types.Serpent_Pkt;
109
110 -- Unpacking a Serpent packet into contained message, using the given key
111 function Unpack( Pkt : in Raw_Types.Serpent_Pkt;
112 K : in Serpent.Key)
113 return Raw_Types.Serpent_Msg;
114
115 -- internals of this package, NOT for outside use
116 private
117 -- length of 1 Serpent block
118 Block_Len: constant Natural := Serpent.Block'Length;
119
120 -- number of Serpent blocks in one single Serpent message/packet
121 S_Blocks : constant Natural := Raw_Types.SERPENT_OCTETS / Block_Len;
122
123 end Packing;
- BE61934D440DAD950D4F63EA9A1BB941A7994C832ADB4748A1E24083887853FDD52FDF024D940740A9D3B65759AAD66A05F42B0365624B0AFFA0E12418E2FE8D(9 . 13)(9 . 14)-
128 with Ada.Unchecked_Conversion;
129
130 package Raw_Types is
131 -- no side effects or internal state
132 Pragma Pure(Raw_Types);
133
134 -- constants from SMG.COMMS standard specification
135 -- size of a serpent-encrypted packet and message, in octets
136 -- note that this corresponds to 1472/16 = 92 Serpent blocks
137 -- NB: lengths are the same but the distinction makes the code clearer
138 SERPENT_PKT_OCTETS : constant Positive := 1472;
139 SERPENT_MSG_OCTETS : constant Positive := SERPENT_PKT_OCTETS;
140 -- NB: lengths are the same!
141 SERPENT_OCTETS : constant Positive := 1472;
142
143 -- size of a RSA-encrypted packet and message in octets and bits
144 RSA_PKT_OCTETS : constant Positive := 1470;
(38 . 8)(39 . 8)
146
147 -- Serpent packets and contained raw messages
148 -- NB: length is the same but the distinction makes the code clearer
149 subtype Serpent_Pkt is Octets( 1 .. SERPENT_PKT_OCTETS );
150 subtype Serpent_Msg is Octets( 1 .. SERPENT_MSG_OCTETS );
151 subtype Serpent_Pkt is Octets( 1 .. SERPENT_OCTETS );
152 subtype Serpent_Msg is Octets( 1 .. SERPENT_OCTETS );
153
154 -- blind, unchecked casts ( memcpy style )
155 function Cast is new Ada.Unchecked_Conversion( Integer_8 , Octets_1 );
(0 . 0)(1 . 624)
160 ------------------------------------------------------------------------------
161 --
162 -- Serpent Blockcipher
163 --
164 -- Copyright (c) 1998 Markus G. Kuhn <mkuhn@acm.org>. All rights reserved.
165 --
166 -- Modified by S.MG, 2018
167 --
168 ------------------------------------------------------------------------------
169 --
170 -- This implementation is optimized for best execution time by use of
171 -- function inlining and loop unrolling. It is not intended to be used in
172 -- applications (such as smartcards) where machine code size matters. Best
173 -- compiled with highest optimization level activated and all run-time
174 -- checks supressed.
175 --
176 ------------------------------------------------------------------------------
177
178 with System, Ada.Unchecked_Conversion;
179 use System;
180
181 package body Serpent is
182
183 pragma Optimize( Time );
184
185 -- Auxiliary functions for byte array to word array conversion with
186 -- Bigendian/Littleendian handling.
187 --
188 -- The convention followed here is that the input byte array
189 --
190 -- 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
191 --
192 -- is converted into the register values
193 --
194 -- X0 = 03020100, X1 = 07060504, X2 = 0b0a0908, X3 = 0f0e0d0c
195
196 subtype Bytes_4 is Bytes (0 .. 3);
197 function Cast is new Ada.Unchecked_Conversion (Bytes_4, Unsigned_32);
198 function Cast is new Ada.Unchecked_Conversion (Unsigned_32, Bytes_4);
199
200 function Bytes_To_Word (X : Bytes_4) return Unsigned_32 is
201 begin
202 if Default_Bit_Order = Low_Order_First then
203 -- we have a Littleendian processor
204 return Cast(X);
205 else
206 -- word sex change
207 return Cast((X(3), X(2), X(1), X(0)));
208 end if;
209 end Bytes_To_Word;
210
211 function Word_To_Bytes (X : Unsigned_32) return Bytes_4 is
212 begin
213 if Default_Bit_Order = Low_Order_First then
214 -- we have a Littleendian processor
215 return Cast(X);
216 else
217 -- word sex change
218 return (Cast(X)(3), Cast(X)(2), Cast(X)(1), Cast(X)(0));
219 end if;
220 end Word_To_Bytes;
221
222 pragma Inline(Bytes_To_Word, Word_To_Bytes);
223 -- inline functions for the Encryption and Decryption procedures
224
225 -- Sbox function
226 procedure S (R : Integer; X0, X1, X2, X3 : in out Unsigned_32) is
227 T01, T02, T03, T04, T05, T06, T07, T08, T09,
228 T10, T11, T12, T13, T14, T15, T16, T17, T18 : Unsigned_32;
229 W, X, Y, Z : Unsigned_32;
230 begin
231 if R = 0 then
232 -- S0: 3 8 15 1 10 6 5 11 14 13 4 2 7 0 9 12
233 -- depth = 5,7,4,2, Total gates=18
234 T01 := X1 xor X2;
235 T02 := X0 or X3;
236 T03 := X0 xor X1;
237 Z := T02 xor T01;
238 T05 := X2 or z;
239 T06 := X0 xor X3;
240 T07 := X1 or X2;
241 T08 := X3 and T05;
242 T09 := T03 and T07;
243 Y := T09 xor T08;
244 T11 := T09 and y;
245 T12 := X2 xor X3;
246 T13 := T07 xor T11;
247 T14 := X1 and T06;
248 T15 := T06 xor T13;
249 W := not T15;
250 T17 := W xor T14;
251 X := T12 xor T17;
252 elsif R = 1 then
253 -- S1: 15 12 2 7 9 0 5 10 1 11 14 8 6 13 3 4
254 -- depth = 10,7,3,5, Total gates=18
255 T01 := X0 or X3;
256 T02 := X2 xor X3;
257 T03 := not X1;
258 T04 := X0 xor X2;
259 T05 := X0 or T03;
260 T06 := X3 and T04;
261 T07 := T01 and T02;
262 T08 := X1 or T06;
263 Y := T02 xor T05;
264 T10 := T07 xor T08;
265 T11 := T01 xor T10;
266 T12 := Y xor T11;
267 T13 := X1 and X3;
268 Z := not T10;
269 X := T13 xor T12;
270 T16 := T10 or x;
271 T17 := T05 and T16;
272 W := X2 xor T17;
273 elsif R = 2 then
274 -- S2: 8 6 7 9 3 12 10 15 13 1 14 4 0 11 5 2
275 -- depth = 3,8,11,7, Total gates=16
276 T01 := X0 or X2;
277 T02 := X0 xor X1;
278 T03 := X3 xor T01;
279 W := T02 xor T03;
280 T05 := X2 xor w;
281 T06 := X1 xor T05;
282 T07 := X1 or T05;
283 T08 := T01 and T06;
284 T09 := T03 xor T07;
285 T10 := T02 or T09;
286 X := T10 xor T08;
287 T12 := X0 or X3;
288 T13 := T09 xor x;
289 T14 := X1 xor T13;
290 Z := not T09;
291 Y := T12 xor T14;
292 elsif R = 3 then
293 -- S3: 0 15 11 8 12 9 6 3 13 1 2 4 10 7 5 14
294 -- depth = 8,3,5,5, Total gates=18
295 T01 := X0 xor X2;
296 T02 := X0 or X3;
297 T03 := X0 and X3;
298 T04 := T01 and T02;
299 T05 := X1 or T03;
300 T06 := X0 and X1;
301 T07 := X3 xor T04;
302 T08 := X2 or T06;
303 T09 := X1 xor T07;
304 T10 := X3 and T05;
305 T11 := T02 xor T10;
306 Z := T08 xor T09;
307 T13 := X3 or z;
308 T14 := X0 or T07;
309 T15 := X1 and T13;
310 Y := T08 xor T11;
311 W := T14 xor T15;
312 X := T05 xor T04;
313 elsif R = 4 then
314 -- S4: 1 15 8 3 12 0 11 6 2 5 4 10 9 14 7 13
315 -- depth = 6,7,5,3, Total gates=19
316 T01 := X0 or X1;
317 T02 := X1 or X2;
318 T03 := X0 xor T02;
319 T04 := X1 xor X3;
320 T05 := X3 or T03;
321 T06 := X3 and T01;
322 Z := T03 xor T06;
323 T08 := Z and T04;
324 T09 := T04 and T05;
325 T10 := X2 xor T06;
326 T11 := X1 and X2;
327 T12 := T04 xor T08;
328 T13 := T11 or T03;
329 T14 := T10 xor T09;
330 T15 := X0 and T05;
331 T16 := T11 or T12;
332 Y := T13 xor T08;
333 X := T15 xor T16;
334 W := not T14;
335 elsif R = 5 then
336 -- S5: 15 5 2 11 4 10 9 12 0 3 14 8 13 6 7 1
337 -- depth = 4,6,8,6, Total gates=17
338 T01 := X1 xor X3;
339 T02 := X1 or X3;
340 T03 := X0 and T01;
341 T04 := X2 xor T02;
342 T05 := T03 xor T04;
343 W := not T05;
344 T07 := X0 xor T01;
345 T08 := X3 or w;
346 T09 := X1 or T05;
347 T10 := X3 xor T08;
348 T11 := X1 or T07;
349 T12 := T03 or w;
350 T13 := T07 or T10;
351 T14 := T01 xor T11;
352 Y := T09 xor T13;
353 X := T07 xor T08;
354 Z := T12 xor T14;
355 elsif R = 6 then
356 -- S6: 7 2 12 5 8 4 6 11 14 9 1 15 13 3 10 0
357 -- depth = 8,3,6,3, Total gates=19
358 T01 := X0 and X3;
359 T02 := X1 xor X2;
360 T03 := X0 xor X3;
361 T04 := T01 xor T02;
362 T05 := X1 or X2;
363 X := not T04;
364 T07 := T03 and T05;
365 T08 := X1 and x;
366 T09 := X0 or X2;
367 T10 := T07 xor T08;
368 T11 := X1 or X3;
369 T12 := X2 xor T11;
370 T13 := T09 xor T10;
371 Y := not T13;
372 T15 := X and T03;
373 Z := T12 xor T07;
374 T17 := X0 xor X1;
375 T18 := Y xor T15;
376 W := T17 xor T18;
377 elsif R = 7 then
378 -- S7: 1 13 15 0 14 8 2 11 7 4 12 10 9 3 5 6
379 -- depth = 10,7,10,4, Total gates=19
380 T01 := X0 and X2;
381 T02 := not X3;
382 T03 := X0 and T02;
383 T04 := X1 or T01;
384 T05 := X0 and X1;
385 T06 := X2 xor T04;
386 Z := T03 xor T06;
387 T08 := X2 or z;
388 T09 := X3 or T05;
389 T10 := X0 xor T08;
390 T11 := T04 and z;
391 X := T09 xor T10;
392 T13 := X1 xor x;
393 T14 := T01 xor x;
394 T15 := X2 xor T05;
395 T16 := T11 or T13;
396 T17 := T02 or T14;
397 W := T15 xor T17;
398 Y := X0 xor T16;
399 end if;
400 X0 := W;
401 X1 := X;
402 X2 := Y;
403 X3 := Z;
404 end S;
405
406
407 -- Inverse Sbox function
408
409 procedure SI (R : Integer; X0, X1, X2, X3 : in out Unsigned_32) is
410 T01, T02, T03, T04, T05, T06, T07, T08, T09,
411 T10, T11, T12, T13, T14, T15, T16, T17, T18 : Unsigned_32;
412 W, X, Y, Z : Unsigned_32;
413 begin
414 if R = 0 then
415 -- InvS0: 13 3 11 0 10 6 5 12 1 14 4 7 15 9 8 2
416 -- depth = 8,4,3,6, Total gates=19
417 T01 := X2 xor X3;
418 T02 := X0 or X1;
419 T03 := X1 or X2;
420 T04 := X2 and T01;
421 T05 := T02 xor T01;
422 T06 := X0 or T04;
423 Y := not T05;
424 T08 := X1 xor X3;
425 T09 := T03 and T08;
426 T10 := X3 or y;
427 X := T09 xor T06;
428 T12 := X0 or T05;
429 T13 := X xor T12;
430 T14 := T03 xor T10;
431 T15 := X0 xor X2;
432 Z := T14 xor T13;
433 T17 := T05 and T13;
434 T18 := T14 or T17;
435 W := T15 xor T18;
436 elsif R = 1 then
437 -- InvS1: 5 8 2 14 15 6 12 3 11 4 7 9 1 13 10 0
438 -- depth = 7,4,5,3, Total gates=18
439 T01 := X0 xor X1;
440 T02 := X1 or X3;
441 T03 := X0 and X2;
442 T04 := X2 xor T02;
443 T05 := X0 or T04;
444 T06 := T01 and T05;
445 T07 := X3 or T03;
446 T08 := X1 xor T06;
447 T09 := T07 xor T06;
448 T10 := T04 or T03;
449 T11 := X3 and T08;
450 Y := not T09;
451 X := T10 xor T11;
452 T14 := X0 or y;
453 T15 := T06 xor x;
454 Z := T01 xor T04;
455 T17 := X2 xor T15;
456 W := T14 xor T17;
457 elsif R = 2 then
458 -- InvS2: 12 9 15 4 11 14 1 2 0 3 6 13 5 8 10 7
459 -- depth = 3,6,8,3, Total gates=18
460 T01 := X0 xor X3;
461 T02 := X2 xor X3;
462 T03 := X0 and X2;
463 T04 := X1 or T02;
464 W := T01 xor T04;
465 T06 := X0 or X2;
466 T07 := X3 or w;
467 T08 := not X3;
468 T09 := X1 and T06;
469 T10 := T08 or T03;
470 T11 := X1 and T07;
471 T12 := T06 and T02;
472 Z := T09 xor T10;
473 X := T12 xor T11;
474 T15 := X2 and z;
475 T16 := W xor x;
476 T17 := T10 xor T15;
477 Y := T16 xor T17;
478 elsif R = 3 then
479 -- InvS3: 0 9 10 7 11 14 6 13 3 5 12 2 4 8 15 1
480 -- depth = 3,6,4,4, Total gates=17
481 T01 := X2 or X3;
482 T02 := X0 or X3;
483 T03 := X2 xor T02;
484 T04 := X1 xor T02;
485 T05 := X0 xor X3;
486 T06 := T04 and T03;
487 T07 := X1 and T01;
488 Y := T05 xor T06;
489 T09 := X0 xor T03;
490 W := T07 xor T03;
491 T11 := W or T05;
492 T12 := T09 and T11;
493 T13 := X0 and y;
494 T14 := T01 xor T05;
495 X := X1 xor T12;
496 T16 := X1 or T13;
497 Z := T14 xor T16;
498 elsif R = 4 then
499 -- InvS4: 5 0 8 3 10 9 7 14 2 12 11 6 4 15 13 1
500 -- depth = 6,4,7,3, Total gates=17
501 T01 := X1 or X3;
502 T02 := X2 or X3;
503 T03 := X0 and T01;
504 T04 := X1 xor T02;
505 T05 := X2 xor X3;
506 T06 := not T03;
507 T07 := X0 and T04;
508 X := T05 xor T07;
509 T09 := X or T06;
510 T10 := X0 xor T07;
511 T11 := T01 xor T09;
512 T12 := X3 xor T04;
513 T13 := X2 or T10;
514 Z := T03 xor T12;
515 T15 := X0 xor T04;
516 Y := T11 xor T13;
517 W := T15 xor T09;
518 elsif R = 5 then
519 -- InvS5: 8 15 2 9 4 1 13 14 11 6 5 3 7 12 10 0
520 -- depth = 4,6,9,7, Total gates=17
521 T01 := X0 and X3;
522 T02 := X2 xor T01;
523 T03 := X0 xor X3;
524 T04 := X1 and T02;
525 T05 := X0 and X2;
526 W := T03 xor T04;
527 T07 := X0 and w;
528 T08 := T01 xor w;
529 T09 := X1 or T05;
530 T10 := not X1;
531 X := T08 xor T09;
532 T12 := T10 or T07;
533 T13 := W or x;
534 Z := T02 xor T12;
535 T15 := T02 xor T13;
536 T16 := X1 xor X3;
537 Y := T16 xor T15;
538 elsif R = 6 then
539 -- InvS6: 15 10 1 13 5 3 6 0 4 9 14 7 2 12 8 11
540 -- depth = 5,3,8,6, Total gates=19
541 T01 := X0 xor X2;
542 T02 := not X2;
543 T03 := X1 and T01;
544 T04 := X1 or T02;
545 T05 := X3 or T03;
546 T06 := X1 xor X3;
547 T07 := X0 and T04;
548 T08 := X0 or T02;
549 T09 := T07 xor T05;
550 X := T06 xor T08;
551 W := not T09;
552 T12 := X1 and w;
553 T13 := T01 and T05;
554 T14 := T01 xor T12;
555 T15 := T07 xor T13;
556 T16 := X3 or T02;
557 T17 := X0 xor x;
558 Z := T17 xor T15;
559 Y := T16 xor T14;
560 elsif R = 7 then
561 -- InvS7: 3 0 6 13 9 14 15 8 5 12 11 7 10 1 4 2
562 -- depth := 9,7,3,3, Total gates:=18
563 T01 := X0 and X1;
564 T02 := X0 or X1;
565 T03 := X2 or T01;
566 T04 := X3 and T02;
567 Z := T03 xor T04;
568 T06 := X1 xor T04;
569 T07 := X3 xor z;
570 T08 := not T07;
571 T09 := T06 or T08;
572 T10 := X1 xor X3;
573 T11 := X0 or X3;
574 X := X0 xor T09;
575 T13 := X2 xor T06;
576 T14 := X2 and T11;
577 T15 := X3 or x;
578 T16 := T01 or T10;
579 W := T13 xor T15;
580 Y := T14 xor T16;
581 end if;
582 X0 := W;
583 X1 := X;
584 X2 := Y;
585 X3 := Z;
586 end SI;
587
588
589 -- Linear Transform
590
591 procedure Tr (X0, X1, X2, X3 : in out Unsigned_32) is
592 begin
593 X0 := Rotate_Left(X0, 13);
594 X2 := Rotate_Left(X2, 3);
595 X1 := X1 xor X0 xor X2;
596 X3 := X3 xor X2 xor Shift_Left(X0, 3);
597 X1 := Rotate_Left(X1, 1);
598 X3 := Rotate_Left(X3, 7);
599 X0 := X0 xor X1 xor X3;
600 X2 := X2 xor X3 xor Shift_Left(X1, 7);
601 X0 := Rotate_Left(X0, 5);
602 X2 := Rotate_Left(X2, 22);
603 end Tr;
604
605
606 -- Inverse Linear Transform
607
608 procedure TrI (X0, X1, X2, X3 : in out Unsigned_32) is
609 begin
610 X2 := Rotate_Right(X2, 22);
611 X0 := Rotate_Right(X0, 5);
612 X2 := X2 xor X3 xor Shift_Left(X1, 7);
613 X0 := X0 xor X1 xor X3;
614 X3 := Rotate_Right(X3, 7);
615 X1 := Rotate_Right(X1, 1);
616 X3 := X3 xor X2 xor Shift_Left(X0, 3);
617 X1 := X1 xor X0 xor X2;
618 X2 := Rotate_Right(X2, 3);
619 X0 := Rotate_Right(X0, 13);
620 end TrI;
621
622
623 procedure Keying (W : Key_Schedule;
624 R : Integer;
625 X0, X1, X2, X3 : in out Unsigned_32) is
626 begin
627 X0 := X0 xor W(4*R);
628 X1 := X1 xor W(4*R+1);
629 X2 := X2 xor W(4*R+2);
630 X3 := X3 xor W(4*R+3);
631 end Keying;
632
633
634 pragma Inline(S, SI, Tr, TrI, Keying);
635
636
637 procedure Prepare_Key (K : in Key; W : out Key_Schedule) is
638 begin
639 for I in 0..7 loop
640 W(-8+I) := Bytes_To_Word(K(4*I .. 4*I+3));
641 end loop;
642 for I in 0..131 loop
643 W(I) := Rotate_Left(W(I-8) xor W(I-5) xor W(I-3) xor W(I-1) xor
644 16#9e3779b9# xor Unsigned_32(I), 11);
645 end loop;
646 S(3, W( 0), W( 1), W( 2), W( 3));
647 S(2, W( 4), W( 5), W( 6), W( 7));
648 S(1, W( 8), W( 9), W( 10), W( 11));
649 S(0, W( 12), W( 13), W( 14), W( 15));
650 S(7, W( 16), W( 17), W( 18), W( 19));
651 S(6, W( 20), W( 21), W( 22), W( 23));
652 S(5, W( 24), W( 25), W( 26), W( 27));
653 S(4, W( 28), W( 29), W( 30), W( 31));
654 S(3, W( 32), W( 33), W( 34), W( 35));
655 S(2, W( 36), W( 37), W( 38), W( 39));
656 S(1, W( 40), W( 41), W( 42), W( 43));
657 S(0, W( 44), W( 45), W( 46), W( 47));
658 S(7, W( 48), W( 49), W( 50), W( 51));
659 S(6, W( 52), W( 53), W( 54), W( 55));
660 S(5, W( 56), W( 57), W( 58), W( 59));
661 S(4, W( 60), W( 61), W( 62), W( 63));
662 S(3, W( 64), W( 65), W( 66), W( 67));
663 S(2, W( 68), W( 69), W( 70), W( 71));
664 S(1, W( 72), W( 73), W( 74), W( 75));
665 S(0, W( 76), W( 77), W( 78), W( 79));
666 S(7, W( 80), W( 81), W( 82), W( 83));
667 S(6, W( 84), W( 85), W( 86), W( 87));
668 S(5, W( 88), W( 89), W( 90), W( 91));
669 S(4, W( 92), W( 93), W( 94), W( 95));
670 S(3, W( 96), W( 97), W( 98), W( 99));
671 S(2, W(100), W(101), W(102), W(103));
672 S(1, W(104), W(105), W(106), W(107));
673 S(0, W(108), W(109), W(110), W(111));
674 S(7, W(112), W(113), W(114), W(115));
675 S(6, W(116), W(117), W(118), W(119));
676 S(5, W(120), W(121), W(122), W(123));
677 S(4, W(124), W(125), W(126), W(127));
678 S(3, W(128), W(129), W(130), W(131));
679 end Prepare_Key;
680
681
682 procedure Encrypt (W : in Key_Schedule; Plaintext : in Block;
683 Ciphertext : out Block) is
684 X0, X1, X2, X3 : Unsigned_32;
685 begin
686 X0 := Bytes_To_Word(Plaintext( 0 .. 3));
687 X1 := Bytes_To_Word(Plaintext( 4 .. 7));
688 X2 := Bytes_To_Word(Plaintext( 8 .. 11));
689 X3 := Bytes_To_Word(Plaintext(12 .. 15));
690
691 Keying(W, 0, X0, X1, X2, X3); S(0, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
692 Keying(W, 1, X0, X1, X2, X3); S(1, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
693 Keying(W, 2, X0, X1, X2, X3); S(2, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
694 Keying(W, 3, X0, X1, X2, X3); S(3, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
695 Keying(W, 4, X0, X1, X2, X3); S(4, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
696 Keying(W, 5, X0, X1, X2, X3); S(5, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
697 Keying(W, 6, X0, X1, X2, X3); S(6, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
698 Keying(W, 7, X0, X1, X2, X3); S(7, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
699 Keying(W, 8, X0, X1, X2, X3); S(0, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
700 Keying(W, 9, X0, X1, X2, X3); S(1, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
701 Keying(W, 10, X0, X1, X2, X3); S(2, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
702 Keying(W, 11, X0, X1, X2, X3); S(3, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
703 Keying(W, 12, X0, X1, X2, X3); S(4, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
704 Keying(W, 13, X0, X1, X2, X3); S(5, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
705 Keying(W, 14, X0, X1, X2, X3); S(6, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
706 Keying(W, 15, X0, X1, X2, X3); S(7, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
707 Keying(W, 16, X0, X1, X2, X3); S(0, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
708 Keying(W, 17, X0, X1, X2, X3); S(1, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
709 Keying(W, 18, X0, X1, X2, X3); S(2, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
710 Keying(W, 19, X0, X1, X2, X3); S(3, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
711 Keying(W, 20, X0, X1, X2, X3); S(4, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
712 Keying(W, 21, X0, X1, X2, X3); S(5, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
713 Keying(W, 22, X0, X1, X2, X3); S(6, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
714 Keying(W, 23, X0, X1, X2, X3); S(7, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
715 Keying(W, 24, X0, X1, X2, X3); S(0, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
716 Keying(W, 25, X0, X1, X2, X3); S(1, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
717 Keying(W, 26, X0, X1, X2, X3); S(2, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
718 Keying(W, 27, X0, X1, X2, X3); S(3, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
719 Keying(W, 28, X0, X1, X2, X3); S(4, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
720 Keying(W, 29, X0, X1, X2, X3); S(5, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
721 Keying(W, 30, X0, X1, X2, X3); S(6, X0, X1, X2, X3); Tr(X0, X1, X2, X3);
722 Keying(W, 31, X0, X1, X2, X3);
723 S(7, X0, X1, X2, X3);
724 Keying(W, 32, X0, X1, X2, X3);
725
726 Ciphertext( 0 .. 3) := Word_To_Bytes(X0);
727 Ciphertext( 4 .. 7) := Word_To_Bytes(X1);
728 Ciphertext( 8 .. 11) := Word_To_Bytes(X2);
729 Ciphertext(12 .. 15) := Word_To_Bytes(X3);
730 end Encrypt;
731
732
733 procedure Decrypt (W : in Key_Schedule; Ciphertext : in Block;
734 Plaintext : out Block) is
735 X0, X1, X2, X3 : Unsigned_32;
736 begin
737 X0 := Bytes_To_Word(Ciphertext( 0 .. 3));
738 X1 := Bytes_To_Word(Ciphertext( 4 .. 7));
739 X2 := Bytes_To_Word(Ciphertext( 8 .. 11));
740 X3 := Bytes_To_Word(Ciphertext(12 .. 15));
741
742 Keying(W, 32, X0, X1, X2, X3);
743 SI(7, X0, X1, X2, X3);
744 Keying(W, 31, X0, X1, X2, X3);
745 TrI(X0, X1, X2, X3); SI(6, X0, X1, X2, X3); Keying(W,30, X0, X1, X2, X3);
746 TrI(X0, X1, X2, X3); SI(5, X0, X1, X2, X3); Keying(W,29, X0, X1, X2, X3);
747 TrI(X0, X1, X2, X3); SI(4, X0, X1, X2, X3); Keying(W,28, X0, X1, X2, X3);
748 TrI(X0, X1, X2, X3); SI(3, X0, X1, X2, X3); Keying(W,27, X0, X1, X2, X3);
749 TrI(X0, X1, X2, X3); SI(2, X0, X1, X2, X3); Keying(W,26, X0, X1, X2, X3);
750 TrI(X0, X1, X2, X3); SI(1, X0, X1, X2, X3); Keying(W,25, X0, X1, X2, X3);
751 TrI(X0, X1, X2, X3); SI(0, X0, X1, X2, X3); Keying(W,24, X0, X1, X2, X3);
752 TrI(X0, X1, X2, X3); SI(7, X0, X1, X2, X3); Keying(W,23, X0, X1, X2, X3);
753 TrI(X0, X1, X2, X3); SI(6, X0, X1, X2, X3); Keying(W,22, X0, X1, X2, X3);
754 TrI(X0, X1, X2, X3); SI(5, X0, X1, X2, X3); Keying(W,21, X0, X1, X2, X3);
755 TrI(X0, X1, X2, X3); SI(4, X0, X1, X2, X3); Keying(W,20, X0, X1, X2, X3);
756 TrI(X0, X1, X2, X3); SI(3, X0, X1, X2, X3); Keying(W,19, X0, X1, X2, X3);
757 TrI(X0, X1, X2, X3); SI(2, X0, X1, X2, X3); Keying(W,18, X0, X1, X2, X3);
758 TrI(X0, X1, X2, X3); SI(1, X0, X1, X2, X3); Keying(W,17, X0, X1, X2, X3);
759 TrI(X0, X1, X2, X3); SI(0, X0, X1, X2, X3); Keying(W,16, X0, X1, X2, X3);
760 TrI(X0, X1, X2, X3); SI(7, X0, X1, X2, X3); Keying(W,15, X0, X1, X2, X3);
761 TrI(X0, X1, X2, X3); SI(6, X0, X1, X2, X3); Keying(W,14, X0, X1, X2, X3);
762 TrI(X0, X1, X2, X3); SI(5, X0, X1, X2, X3); Keying(W,13, X0, X1, X2, X3);
763 TrI(X0, X1, X2, X3); SI(4, X0, X1, X2, X3); Keying(W,12, X0, X1, X2, X3);
764 TrI(X0, X1, X2, X3); SI(3, X0, X1, X2, X3); Keying(W,11, X0, X1, X2, X3);
765 TrI(X0, X1, X2, X3); SI(2, X0, X1, X2, X3); Keying(W,10, X0, X1, X2, X3);
766 TrI(X0, X1, X2, X3); SI(1, X0, X1, X2, X3); Keying(W, 9, X0, X1, X2, X3);
767 TrI(X0, X1, X2, X3); SI(0, X0, X1, X2, X3); Keying(W, 8, X0, X1, X2, X3);
768 TrI(X0, X1, X2, X3); SI(7, X0, X1, X2, X3); Keying(W, 7, X0, X1, X2, X3);
769 TrI(X0, X1, X2, X3); SI(6, X0, X1, X2, X3); Keying(W, 6, X0, X1, X2, X3);
770 TrI(X0, X1, X2, X3); SI(5, X0, X1, X2, X3); Keying(W, 5, X0, X1, X2, X3);
771 TrI(X0, X1, X2, X3); SI(4, X0, X1, X2, X3); Keying(W, 4, X0, X1, X2, X3);
772 TrI(X0, X1, X2, X3); SI(3, X0, X1, X2, X3); Keying(W, 3, X0, X1, X2, X3);
773 TrI(X0, X1, X2, X3); SI(2, X0, X1, X2, X3); Keying(W, 2, X0, X1, X2, X3);
774 TrI(X0, X1, X2, X3); SI(1, X0, X1, X2, X3); Keying(W, 1, X0, X1, X2, X3);
775 TrI(X0, X1, X2, X3); SI(0, X0, X1, X2, X3); Keying(W, 0, X0, X1, X2, X3);
776
777 Plaintext( 0 .. 3) := Word_To_Bytes(X0);
778 Plaintext( 4 .. 7) := Word_To_Bytes(X1);
779 Plaintext( 8 .. 11) := Word_To_Bytes(X2);
780 Plaintext(12 .. 15) := Word_To_Bytes(X3);
781 end Decrypt;
782
783 end Serpent;
-(0 . 0)(1 . 44)
788 -------------------------------------------------------------------------------
789 -- S.MG, 2018;
790 --
791 -- Serpent Blockcipher
792 --
793 -- Copyright (c) 1998 Markus G. Kuhn <mkuhn@acm.org>. All rights reserved.
794 --
795 --
796 -------------------------------------------------------------------------------
797 --
798 -- This is the Ada95 reference implementation of the Serpent cipher
799 -- submitted by Ross Anderson, Eli Biham and Lars Knudson in June 1998 to
800 -- the NIST Advanced Encryption Standard (AES) contest. Please note that
801 -- this is a revised algorithm that is not identical to the old version
802 -- presented at the 1998 Fast Software Encryption Workshop.
803 -- <http://www.cs.technion.ac.il/~biham/Reports/Serpent/>
804 --
805 -- Compiled with GNAT 3.10p under Linux, this implementation encrypts and
806 -- decrypts with 20.8 Mbit/s on a 300 MHz Pentium II.
807 --
808 -------------------------------------------------------------------------------
809
810 with Interfaces; use Interfaces;
811 with Raw_Types;
812
813 package Serpent is
814
815 pragma Pure(Serpent);
816
817 subtype Bytes is Raw_Types.Octets;
818 type Words is array (Integer range <>) of Unsigned_32;
819 subtype Block is Bytes (0 .. 15);
820 subtype Key is Bytes (0 .. 31);
821 subtype Key_Schedule is Words (-8 .. 131);
822
823 procedure Prepare_Key (K : in Key; W : out Key_Schedule);
824
825 procedure Encrypt (W : in Key_Schedule; Plaintext : in Block;
826 Ciphertext : out Block);
827
828 procedure Decrypt (W : in Key_Schedule; Ciphertext : in Block;
829 Plaintext : out Block);
830
831 end Serpent;
-(0 . 0)(1 . 1)
836 obj
-(0 . 0)(1 . 52)
841 -- S.MG, 2018
842 -- basic tests for the prototype implementation of S.MG communication protocol
843 -- http://trilema.com/2018/euloras-communication-protocol-restated/
844
845 with "../smg_comms.gpr";
846
847 project Test_comms is
848
849 type Mode_Type is ("debug", "release");
850 Mode : Mode_Type := external ("mode", "release");
851
852 for Languages use ("Ada");
853
854 for Source_Dirs use (".");
855 for Ignore_Source_Sub_Dirs use (".svn", ".git", "@*");
856
857 for Object_Dir use "obj";
858 for Exec_Dir use ".";
859
860 for Main use ("testall.adb");
861
862 package Compiler is
863
864 case Mode is
865 when "debug" =>
866 for Switches ("Ada")
867 use ("-g");
868 when "release" =>
869 for Switches ("Ada")
870 use ("-O2", "-fdump-scos", "-gnata", "-fstack-check",
871 "-gnatyd", "-gnatym",
872 "-fdata-sections", "-ffunction-sections", "-gnatwr", "-gnatw.d",
873 "-gnatec=" & SMG_Comms'Project_Dir & "restrict.adc");
874 end case;
875 end Compiler;
876
877 package Builder is
878 for Executable ("test_comms.adb") use "test_comms";
879 end Builder;
880
881 package Binder is
882 case Mode is
883 when "debug" =>
884 for Switches ("Ada")
885 use ();
886 when "release" =>
887 for Switches ("Ada")
888 use ("-static");
889 end case;
890 end Binder;
891
892 end Test_comms;
-(0 . 0)(1 . 63)
897 -- Tests for SMG_Comms.Packing
898 -- S.MG, 2018
899
900 with Packing; use Packing;
901 with Raw_Types; use Raw_Types;
902 with Serpent; use Serpent;
903
904 with Interfaces; use Interfaces;
905 with Ada.Text_IO; use Ada.Text_IO;
906
907 package body Test_Packing is
908
909 procedure Print(Data: in Raw_Types.Octets; Msg: in String) is
910 begin
911 Put_Line(Msg);
912 for I of Data loop
913 Put(Unsigned_8'Image(I));
914 end loop;
915 New_Line;
916 end Print;
917
918 procedure Test_Pack_Unpack is
919 InMsg : Serpent_Msg := (others => 0);
920 OutMsg : Serpent_Msg := (others => 0);
921
922 InPkt : Serpent_Pkt := (others => 0);
923 OutPkt : Serpent_Pkt := (others => 0);
924
925 K : Key := (others => 0);
926 KS : Key_Schedule;
927 Plain : Block := (others => 0);
928 Encr : Block := (others => 0);
929 Len : constant Natural :=
930 Raw_Types.SERPENT_OCTETS / Serpent.Block'Length;
931 begin
932 for I in 1 .. 128 loop
933 OutPkt := Pack(InMsg, K);
934 if OutPkt = InMsg then
935 raise Test_Error;
936 end if;
937
938 OutMsg := Unpack(OutPkt, K);
939 if OutMsg /= InMsg then
940 raise Test_Error;
941 end if;
942
943 -- check result of pack
944 Prepare_Key(K, KS);
945 for J in 1 .. Len loop
946 Plain := InMsg((J-1)*Block'Length + 1 .. J*Block'Length);
947 Serpent.Encrypt(KS, Plain, Encr);
948 if Encr /= OutPkt((J-1)*Block'Length + 1 .. J*Block'Length) then
949 raise Test_Error;
950 end if;
951 end loop;
952
953 -- iterate, re-packing as "message" the previous package
954 InMsg := OutPkt;
955 end loop;
956
957 end Test_Pack_Unpack;
958
959 end Test_Packing;
-(0 . 0)(1 . 13)
964 -- Tests for SMG_Comms.Packing
965 -- S.MG, 2018
966
967 with Raw_Types;
968
969 package Test_Packing is
970 Test_Error : exception; -- raised if a test failed
971
972 -- utility method for printing an array of octets
973 procedure Print(Data: in Raw_Types.Octets; Msg: in String);
974
975 procedure Test_Pack_Unpack;
976 end Test_Packing;
-(0 . 0)(1 . 31)
981 -- S.MG, 2018
982
983 with Raw_Types; use Raw_Types;
984 with Serpent; use Serpent;
985
986 package body Test_Serpent is
987
988 procedure Selftest is
989 K : Key := (others => 0);
990 P : Block := (others => 0);
991 P2, C : Block;
992 W : Key_Schedule;
993 begin
994 for I in 1 .. 128 loop
995 Prepare_Key(K, W);
996 Encrypt(W, P, C);
997 Decrypt(W, C, P2);
998 if (P2 /= P) then
999 raise Implementation_Error;
1000 end if;
1001 P := K( 0 .. 15);
1002 K( 0 .. 15) := K(16 .. 31);
1003 K(16 .. 31) := C;
1004 end loop;
1005 if C /= (16#A2#, 16#46#, 16#AB#, 16#69#, 16#0A#, 16#E6#, 16#8D#, 16#FB#,
1006 16#02#, 16#04#, 16#CB#, 16#E2#, 16#8E#, 16#D8#, 16#EB#, 16#7A#)
1007 then
1008 raise Implementation_Error;
1009 end if;
1010 end Selftest;
1011 end Test_Serpent;
-(0 . 0)(1 . 8)
1016 --S.MG, 2018
1017
1018 package Test_Serpent is
1019 Implementation_Error : exception; -- raised if Selftest failed
1020
1021 procedure Selftest;
1022
1023 end Test_Serpent;
-(0 . 0)(1 . 10)
1028 -- S.MG, 2018
1029
1030 with Test_Serpent;
1031 with Test_Packing;
1032
1033 procedure testall is
1034 begin
1035 Test_Serpent.Selftest;
1036 Test_Packing.Test_Pack_Unpack;
1037 end testall;