1 /* Modified for SILC. -Pekka */x
\r
3 /* This is an independent implementation of the encryption algorithm: */
\r
5 /* Serpent by Ross Anderson, Eli Biham and Lars Knudsen */
\r
7 /* which is a candidate algorithm in the Advanced Encryption Standard */
\r
8 /* programme of the US National Institute of Standards and Technology. */
\r
10 /* Copyright in this implementation is held by Dr B R Gladman but I */
\r
11 /* hereby give permission for its free direct or derivative use subject */
\r
12 /* to acknowledgment of its origin and compliance with any conditions */
\r
13 /* that the originators of the algorithm place on its exploitation. */
\r
15 /* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */
\r
17 /* Timing data for Serpent (serpent.c)
\r
19 Core timing without I/O endian conversion:
\r
22 Key Setup: 2402 cycles
\r
23 Encrypt: 952 cycles = 26.9 mbits/sec
\r
24 Decrypt: 914 cycles = 28.0 mbits/sec
\r
25 Mean: 933 cycles = 27.4 mbits/sec
\r
28 Key Setup: 2449 cycles
\r
29 Encrypt: 952 cycles = 26.9 mbits/sec
\r
30 Decrypt: 914 cycles = 28.0 mbits/sec
\r
31 Mean: 933 cycles = 27.4 mbits/sec
\r
34 Key Setup: 2349 cycles
\r
35 Encrypt: 952 cycles = 26.9 mbits/sec
\r
36 Decrypt: 914 cycles = 28.0 mbits/sec
\r
37 Mean: 933 cycles = 27.4 mbits/sec
\r
39 Full timing with I/O endian conversion:
\r
42 Key Setup: 2415 cycles
\r
43 Encrypt: 985 cycles = 26.0 mbits/sec
\r
44 Decrypt: 954 cycles = 26.8 mbits/sec
\r
45 Mean: 970 cycles = 26.4 mbits/sec
\r
48 Key Setup: 2438 cycles
\r
49 Encrypt: 985 cycles = 26.0 mbits/sec
\r
50 Decrypt: 954 cycles = 26.8 mbits/sec
\r
51 Mean: 970 cycles = 26.4 mbits/sec
\r
54 Key Setup: 2463 cycles
\r
55 Encrypt: 985 cycles = 26.0 mbits/sec
\r
56 Decrypt: 954 cycles = 26.8 mbits/sec
\r
57 Mean: 970 cycles = 26.4 mbits/sec
\r
62 #include <sys/types.h>
\r
63 #include "serpent_internal.h"
\r
65 /* Partially optimised Serpent S Box boolean functions derived */
\r
66 /* using a recursive descent analyser but without a full search */
\r
67 /* of all subtrees. This set of S boxes is the result of work */
\r
68 /* by Sam Simpson and Brian Gladman using the spare time on a */
\r
69 /* cluster of high capacity servers to search for S boxes with */
\r
70 /* this customised search engine. */
\r
72 /* Copyright: Dr B. R Gladman (gladman@seven77.demon.co.uk) */
\r
73 /* and Sam Simpson (s.simpson@mia.co.uk) */
\r
74 /* 17th December 1998 */
\r
76 /* We hereby give permission for information in this file to be */
\r
77 /* used freely subject only to acknowledgement of its origin */
\r
81 #define sb0(a,b,c,d,e,f,g,h) \
\r
100 #define ib0(a,b,c,d,e,f,g,h) \
\r
119 #define sb1(a,b,c,d,e,f,g,h) \
\r
137 #define ib1(a,b,c,d,e,f,g,h) \
\r
158 #define sb2(a,b,c,d,e,f,g,h) \
\r
178 #define ib2(a,b,c,d,e,f,g,h) \
\r
198 #define sb3(a,b,c,d,e,f,g,h) \
\r
217 /* 16 term solution that performs less well than 17 term one
\r
218 in my environment (PPro/PII)
\r
220 #define sb3(a,b,c,d,e,f,g,h) \
\r
241 #define ib3(a,b,c,d,e,f,g,h) \
\r
262 #define sb4(a,b,c,d,e,f,g,h) \
\r
281 #define ib4(a,b,c,d,e,f,g,h) \
\r
302 #define sb5(a,b,c,d,e,f,g,h) \
\r
322 #define ib5(a,b,c,d,e,f,g,h) \
\r
342 #define sb6(a,b,c,d,e,f,g,h) \
\r
361 #define ib6(a,b,c,d,e,f,g,h) \
\r
380 #define sb7(a,b,c,d,e,f,g,h) \
\r
401 #define ib7(a,b,c,d,e,f,g,h) \
\r
420 #define k_xor(r,a,b,c,d) \
\r
421 a ^= l_key[4 * r + 8]; \
\r
422 b ^= l_key[4 * r + 9]; \
\r
423 c ^= l_key[4 * r + 10]; \
\r
424 d ^= l_key[4 * r + 11]
\r
426 #define k_set(r,a,b,c,d) \
\r
427 a = l_key[4 * r + 8]; \
\r
428 b = l_key[4 * r + 9]; \
\r
429 c = l_key[4 * r + 10]; \
\r
430 d = l_key[4 * r + 11]
\r
432 #define k_get(r,a,b,c,d) \
\r
433 l_key[4 * r + 8] = a; \
\r
434 l_key[4 * r + 9] = b; \
\r
435 l_key[4 * r + 10] = c; \
\r
436 l_key[4 * r + 11] = d
\r
438 /* the linear transformation and its inverse */
\r
440 #define rot(a,b,c,d) \
\r
443 d ^= c ^ (a << 3); \
\r
448 c ^= d ^ (b << 7); \
\r
452 #define irot(a,b,c,d) \
\r
455 c ^= d ^ (b << 7); \
\r
459 d ^= c ^ (a << 3); \
\r
464 /* initialise the key schedule from the user supplied key */
\r
466 u4byte *serpent_set_key(SerpentContext *ctx,
\r
467 const u4byte in_key[], const u4byte key_len)
\r
469 u4byte i,lk,a,b,c,d,e,f,g,h;
\r
470 u4byte t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16;
\r
471 u4byte *l_key = ctx->l_key;
\r
473 if(key_len < 0 || key_len > 256)
\r
477 i = 0; lk = (key_len + 31) / 32;
\r
482 l_key[i] = io_swap(in_key[lk - i - 1]);
\r
484 l_key[i] = in_key[i];
\r
495 i = key_len / 32; lk = 1 << key_len % 32;
\r
497 l_key[i] = l_key[i] & (lk - 1) | lk;
\r
500 for(i = 0; i < 132; ++i)
\r
502 lk = l_key[i] ^ l_key[i + 3] ^ l_key[i + 5]
\r
503 ^ l_key[i + 7] ^ 0x9e3779b9 ^ i;
\r
505 l_key[i + 8] = (lk << 11) | (lk >> 21);
\r
508 k_set( 0,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get( 0,e,f,g,h);
\r
509 k_set( 1,a,b,c,d);sb2(a,b,c,d,e,f,g,h);k_get( 1,e,f,g,h);
\r
510 k_set( 2,a,b,c,d);sb1(a,b,c,d,e,f,g,h);k_get( 2,e,f,g,h);
\r
511 k_set( 3,a,b,c,d);sb0(a,b,c,d,e,f,g,h);k_get( 3,e,f,g,h);
\r
512 k_set( 4,a,b,c,d);sb7(a,b,c,d,e,f,g,h);k_get( 4,e,f,g,h);
\r
513 k_set( 5,a,b,c,d);sb6(a,b,c,d,e,f,g,h);k_get( 5,e,f,g,h);
\r
514 k_set( 6,a,b,c,d);sb5(a,b,c,d,e,f,g,h);k_get( 6,e,f,g,h);
\r
515 k_set( 7,a,b,c,d);sb4(a,b,c,d,e,f,g,h);k_get( 7,e,f,g,h);
\r
516 k_set( 8,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get( 8,e,f,g,h);
\r
517 k_set( 9,a,b,c,d);sb2(a,b,c,d,e,f,g,h);k_get( 9,e,f,g,h);
\r
518 k_set(10,a,b,c,d);sb1(a,b,c,d,e,f,g,h);k_get(10,e,f,g,h);
\r
519 k_set(11,a,b,c,d);sb0(a,b,c,d,e,f,g,h);k_get(11,e,f,g,h);
\r
520 k_set(12,a,b,c,d);sb7(a,b,c,d,e,f,g,h);k_get(12,e,f,g,h);
\r
521 k_set(13,a,b,c,d);sb6(a,b,c,d,e,f,g,h);k_get(13,e,f,g,h);
\r
522 k_set(14,a,b,c,d);sb5(a,b,c,d,e,f,g,h);k_get(14,e,f,g,h);
\r
523 k_set(15,a,b,c,d);sb4(a,b,c,d,e,f,g,h);k_get(15,e,f,g,h);
\r
524 k_set(16,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get(16,e,f,g,h);
\r
525 k_set(17,a,b,c,d);sb2(a,b,c,d,e,f,g,h);k_get(17,e,f,g,h);
\r
526 k_set(18,a,b,c,d);sb1(a,b,c,d,e,f,g,h);k_get(18,e,f,g,h);
\r
527 k_set(19,a,b,c,d);sb0(a,b,c,d,e,f,g,h);k_get(19,e,f,g,h);
\r
528 k_set(20,a,b,c,d);sb7(a,b,c,d,e,f,g,h);k_get(20,e,f,g,h);
\r
529 k_set(21,a,b,c,d);sb6(a,b,c,d,e,f,g,h);k_get(21,e,f,g,h);
\r
530 k_set(22,a,b,c,d);sb5(a,b,c,d,e,f,g,h);k_get(22,e,f,g,h);
\r
531 k_set(23,a,b,c,d);sb4(a,b,c,d,e,f,g,h);k_get(23,e,f,g,h);
\r
532 k_set(24,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get(24,e,f,g,h);
\r
533 k_set(25,a,b,c,d);sb2(a,b,c,d,e,f,g,h);k_get(25,e,f,g,h);
\r
534 k_set(26,a,b,c,d);sb1(a,b,c,d,e,f,g,h);k_get(26,e,f,g,h);
\r
535 k_set(27,a,b,c,d);sb0(a,b,c,d,e,f,g,h);k_get(27,e,f,g,h);
\r
536 k_set(28,a,b,c,d);sb7(a,b,c,d,e,f,g,h);k_get(28,e,f,g,h);
\r
537 k_set(29,a,b,c,d);sb6(a,b,c,d,e,f,g,h);k_get(29,e,f,g,h);
\r
538 k_set(30,a,b,c,d);sb5(a,b,c,d,e,f,g,h);k_get(30,e,f,g,h);
\r
539 k_set(31,a,b,c,d);sb4(a,b,c,d,e,f,g,h);k_get(31,e,f,g,h);
\r
540 k_set(32,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get(32,e,f,g,h);
\r
545 /* encrypt a block of text */
\r
547 void serpent_encrypt(SerpentContext *ctx,
\r
548 const u4byte in_blk[4], u4byte out_blk[])
\r
550 u4byte a,b,c,d,e,f,g,h;
\r
551 u4byte t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16;
\r
552 u4byte *l_key = ctx->l_key;
\r
555 a = io_swap(in_blk[3]); b = io_swap(in_blk[2]);
\r
556 c = io_swap(in_blk[1]); d = io_swap(in_blk[0]);
\r
558 a = in_blk[0]; b = in_blk[1]; c = in_blk[2]; d = in_blk[3];
\r
561 k_xor( 0,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);
\r
562 k_xor( 1,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);
\r
563 k_xor( 2,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);
\r
564 k_xor( 3,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);
\r
565 k_xor( 4,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);
\r
566 k_xor( 5,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);
\r
567 k_xor( 6,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);
\r
568 k_xor( 7,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d);
\r
569 k_xor( 8,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);
\r
570 k_xor( 9,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);
\r
571 k_xor(10,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);
\r
572 k_xor(11,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);
\r
573 k_xor(12,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);
\r
574 k_xor(13,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);
\r
575 k_xor(14,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);
\r
576 k_xor(15,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d);
\r
577 k_xor(16,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);
\r
578 k_xor(17,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);
\r
579 k_xor(18,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);
\r
580 k_xor(19,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);
\r
581 k_xor(20,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);
\r
582 k_xor(21,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);
\r
583 k_xor(22,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);
\r
584 k_xor(23,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d);
\r
585 k_xor(24,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);
\r
586 k_xor(25,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);
\r
587 k_xor(26,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);
\r
588 k_xor(27,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);
\r
589 k_xor(28,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);
\r
590 k_xor(29,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);
\r
591 k_xor(30,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);
\r
592 k_xor(31,e,f,g,h); sb7(e,f,g,h,a,b,c,d); k_xor(32,a,b,c,d);
\r
595 out_blk[3] = io_swap(a); out_blk[2] = io_swap(b);
\r
596 out_blk[1] = io_swap(c); out_blk[0] = io_swap(d);
\r
598 out_blk[0] = a; out_blk[1] = b; out_blk[2] = c; out_blk[3] = d;
\r
602 /* decrypt a block of text */
\r
604 void serpent_decrypt(SerpentContext *ctx,
\r
605 const u4byte in_blk[4], u4byte out_blk[4])
\r
607 u4byte a,b,c,d,e,f,g,h;
\r
608 u4byte t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16;
\r
609 u4byte *l_key = ctx->l_key;
\r
612 a = io_swap(in_blk[3]); b = io_swap(in_blk[2]);
\r
613 c = io_swap(in_blk[1]); d = io_swap(in_blk[0]);
\r
615 a = in_blk[0]; b = in_blk[1]; c = in_blk[2]; d = in_blk[3];
\r
618 k_xor(32,a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(31,e,f,g,h);
\r
619 irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(30,a,b,c,d);
\r
620 irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(29,e,f,g,h);
\r
621 irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(28,a,b,c,d);
\r
622 irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(27,e,f,g,h);
\r
623 irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(26,a,b,c,d);
\r
624 irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor(25,e,f,g,h);
\r
625 irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor(24,a,b,c,d);
\r
626 irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(23,e,f,g,h);
\r
627 irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(22,a,b,c,d);
\r
628 irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(21,e,f,g,h);
\r
629 irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(20,a,b,c,d);
\r
630 irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(19,e,f,g,h);
\r
631 irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(18,a,b,c,d);
\r
632 irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor(17,e,f,g,h);
\r
633 irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor(16,a,b,c,d);
\r
634 irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(15,e,f,g,h);
\r
635 irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(14,a,b,c,d);
\r
636 irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(13,e,f,g,h);
\r
637 irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(12,a,b,c,d);
\r
638 irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(11,e,f,g,h);
\r
639 irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(10,a,b,c,d);
\r
640 irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor( 9,e,f,g,h);
\r
641 irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor( 8,a,b,c,d);
\r
642 irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor( 7,e,f,g,h);
\r
643 irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor( 6,a,b,c,d);
\r
644 irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor( 5,e,f,g,h);
\r
645 irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor( 4,a,b,c,d);
\r
646 irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor( 3,e,f,g,h);
\r
647 irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor( 2,a,b,c,d);
\r
648 irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor( 1,e,f,g,h);
\r
649 irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor( 0,a,b,c,d);
\r
652 out_blk[3] = io_swap(a); out_blk[2] = io_swap(b);
\r
653 out_blk[1] = io_swap(c); out_blk[0] = io_swap(d);
\r
655 out_blk[0] = a; out_blk[1] = b; out_blk[2] = c; out_blk[3] = d;
\r