1
/* This file was automatically imported with
2
import_gcry.py. Please don't modify it */
3
/* serpent.c - Implementation of the Serpent encryption algorithm.
4
* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
6
* This file is part of Libgcrypt.
8
* Libgcrypt is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU Lesser general Public License as
10
* published by the Free Software Foundation; either version 2.1 of
11
* the License, or (at your option) any later version.
13
* Libgcrypt is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU Lesser General Public License for more details.
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
31
/* Number of rounds per Serpent encrypt/decrypt operation. */
34
/* Magic number, used during generating of the subkeys. */
35
#define PHI 0x9E3779B9
37
/* Serpent works on 128 bit blocks. */
38
typedef u32 serpent_block_t[4];
40
/* Serpent key, provided by the user. If the original key is shorter
41
than 256 bits, it is padded. */
42
typedef u32 serpent_key_t[8];
44
/* The key schedule consists of 33 128 bit subkeys. */
45
typedef u32 serpent_subkeys_t[ROUNDS + 1][4];
47
/* A Serpent context. */
48
typedef struct serpent_context
50
serpent_subkeys_t keys; /* Generated subkeys. */
55
static const char *serpent_test (void);
58
#define byte_swap_32(x) \
60
| (((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \
61
| (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
63
/* These are the S-Boxes of Serpent. They are copied from Serpents
64
reference implementation (the optimized one, contained in
65
`floppy2') and are therefore:
67
Copyright (C) 1998 Ross Anderson, Eli Biham, Lars Knudsen.
69
To quote the Serpent homepage
70
(http://www.cl.cam.ac.uk/~rja14/serpent.html):
72
"Serpent is now completely in the public domain, and we impose no
73
restrictions on its use. This was announced on the 21st August at
74
the First AES Candidate Conference. The optimised implementations
75
in the submission package are now under the GNU PUBLIC LICENSE
76
(GPL), although some comments in the code still say otherwise. You
77
are welcome to use Serpent for any application." */
79
#define SBOX0(a, b, c, d, w, x, y, z) \
81
u32 t02, t03, t05, t06, t07, t08, t09; \
82
u32 t11, t12, t13, t14, t15, t17, t01; \
103
#define SBOX0_INVERSE(a, b, c, d, w, x, y, z) \
105
u32 t02, t03, t04, t05, t06, t08, t09, t10; \
106
u32 t12, t13, t14, t15, t17, t18, t01; \
128
#define SBOX1(a, b, c, d, w, x, y, z) \
130
u32 t02, t03, t04, t05, t06, t07, t08; \
131
u32 t10, t11, t12, t13, t16, t17, t01; \
152
#define SBOX1_INVERSE(a, b, c, d, w, x, y, z) \
154
u32 t02, t03, t04, t05, t06, t07, t08; \
155
u32 t09, t10, t11, t14, t15, t17, t01; \
176
#define SBOX2(a, b, c, d, w, x, y, z) \
178
u32 t02, t03, t05, t06, t07, t08; \
179
u32 t09, t10, t12, t13, t14, t01; \
198
#define SBOX2_INVERSE(a, b, c, d, w, x, y, z) \
200
u32 t02, t03, t04, t06, t07, t08, t09; \
201
u32 t10, t11, t12, t15, t16, t17, t01; \
222
#define SBOX3(a, b, c, d, w, x, y, z) \
224
u32 t02, t03, t04, t05, t06, t07, t08; \
225
u32 t09, t10, t11, t13, t14, t15, t01; \
246
#define SBOX3_INVERSE(a, b, c, d, w, x, y, z) \
248
u32 t02, t03, t04, t05, t06, t07, t09; \
249
u32 t11, t12, t13, t14, t16, t01; \
269
#define SBOX4(a, b, c, d, w, x, y, z) \
271
u32 t02, t03, t04, t05, t06, t08, t09; \
272
u32 t10, t11, t12, t13, t14, t15, t16, t01; \
294
#define SBOX4_INVERSE(a, b, c, d, w, x, y, z) \
296
u32 t02, t03, t04, t05, t06, t07, t09; \
297
u32 t10, t11, t12, t13, t15, t01; \
317
#define SBOX5(a, b, c, d, w, x, y, z) \
319
u32 t02, t03, t04, t05, t07, t08, t09; \
320
u32 t10, t11, t12, t13, t14, t01; \
340
#define SBOX5_INVERSE(a, b, c, d, w, x, y, z) \
342
u32 t02, t03, t04, t05, t07, t08, t09; \
343
u32 t10, t12, t13, t15, t16, t01; \
363
#define SBOX6(a, b, c, d, w, x, y, z) \
365
u32 t02, t03, t04, t05, t07, t08, t09, t10; \
366
u32 t11, t12, t13, t15, t17, t18, t01; \
388
#define SBOX6_INVERSE(a, b, c, d, w, x, y, z) \
390
u32 t02, t03, t04, t05, t06, t07, t08, t09; \
391
u32 t12, t13, t14, t15, t16, t17, t01; \
413
#define SBOX7(a, b, c, d, w, x, y, z) \
415
u32 t02, t03, t04, t05, t06, t08, t09, t10; \
416
u32 t11, t13, t14, t15, t16, t17, t01; \
438
#define SBOX7_INVERSE(a, b, c, d, w, x, y, z) \
440
u32 t02, t03, t04, t06, t07, t08, t09; \
441
u32 t10, t11, t13, t14, t15, t16, t01; \
462
/* XOR BLOCK1 into BLOCK0. */
463
#define BLOCK_XOR(block0, block1) \
465
block0[0] ^= block1[0]; \
466
block0[1] ^= block1[1]; \
467
block0[2] ^= block1[2]; \
468
block0[3] ^= block1[3]; \
471
/* Copy BLOCK_SRC to BLOCK_DST. */
472
#define BLOCK_COPY(block_dst, block_src) \
474
block_dst[0] = block_src[0]; \
475
block_dst[1] = block_src[1]; \
476
block_dst[2] = block_src[2]; \
477
block_dst[3] = block_src[3]; \
480
/* Apply SBOX number WHICH to to the block found in ARRAY0 at index
481
INDEX, writing the output to the block found in ARRAY1 at index
483
#define SBOX(which, array0, array1, index) \
484
SBOX##which (array0[index + 0], array0[index + 1], \
485
array0[index + 2], array0[index + 3], \
486
array1[index + 0], array1[index + 1], \
487
array1[index + 2], array1[index + 3]);
489
/* Apply inverse SBOX number WHICH to to the block found in ARRAY0 at
490
index INDEX, writing the output to the block found in ARRAY1 at
492
#define SBOX_INVERSE(which, array0, array1, index) \
493
SBOX##which##_INVERSE (array0[index + 0], array0[index + 1], \
494
array0[index + 2], array0[index + 3], \
495
array1[index + 0], array1[index + 1], \
496
array1[index + 2], array1[index + 3]);
498
/* Apply the linear transformation to BLOCK. */
499
#define LINEAR_TRANSFORMATION(block) \
501
block[0] = rol (block[0], 13); \
502
block[2] = rol (block[2], 3); \
503
block[1] = block[1] ^ block[0] ^ block[2]; \
504
block[3] = block[3] ^ block[2] ^ (block[0] << 3); \
505
block[1] = rol (block[1], 1); \
506
block[3] = rol (block[3], 7); \
507
block[0] = block[0] ^ block[1] ^ block[3]; \
508
block[2] = block[2] ^ block[3] ^ (block[1] << 7); \
509
block[0] = rol (block[0], 5); \
510
block[2] = rol (block[2], 22); \
513
/* Apply the inverse linear transformation to BLOCK. */
514
#define LINEAR_TRANSFORMATION_INVERSE(block) \
516
block[2] = ror (block[2], 22); \
517
block[0] = ror (block[0] , 5); \
518
block[2] = block[2] ^ block[3] ^ (block[1] << 7); \
519
block[0] = block[0] ^ block[1] ^ block[3]; \
520
block[3] = ror (block[3], 7); \
521
block[1] = ror (block[1], 1); \
522
block[3] = block[3] ^ block[2] ^ (block[0] << 3); \
523
block[1] = block[1] ^ block[0] ^ block[2]; \
524
block[2] = ror (block[2], 3); \
525
block[0] = ror (block[0], 13); \
528
/* Apply a Serpent round to BLOCK, using the SBOX number WHICH and the
529
subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage.
530
This macro increments `round'. */
531
#define ROUND(which, subkeys, block, block_tmp) \
533
BLOCK_XOR (block, subkeys[round]); \
535
SBOX (which, block, block_tmp, 0); \
536
LINEAR_TRANSFORMATION (block_tmp); \
537
BLOCK_COPY (block, block_tmp); \
540
/* Apply the last Serpent round to BLOCK, using the SBOX number WHICH
541
and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary
542
storage. The result will be stored in BLOCK_TMP. This macro
543
increments `round'. */
544
#define ROUND_LAST(which, subkeys, block, block_tmp) \
546
BLOCK_XOR (block, subkeys[round]); \
548
SBOX (which, block, block_tmp, 0); \
549
BLOCK_XOR (block_tmp, subkeys[round]); \
553
/* Apply an inverse Serpent round to BLOCK, using the SBOX number
554
WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as
555
temporary storage. This macro increments `round'. */
556
#define ROUND_INVERSE(which, subkey, block, block_tmp) \
558
LINEAR_TRANSFORMATION_INVERSE (block); \
559
SBOX_INVERSE (which, block, block_tmp, 0); \
560
BLOCK_XOR (block_tmp, subkey[round]); \
562
BLOCK_COPY (block, block_tmp); \
565
/* Apply the first Serpent round to BLOCK, using the SBOX number WHICH
566
and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary
567
storage. The result will be stored in BLOCK_TMP. This macro
568
increments `round'. */
569
#define ROUND_FIRST_INVERSE(which, subkeys, block, block_tmp) \
571
BLOCK_XOR (block, subkeys[round]); \
573
SBOX_INVERSE (which, block, block_tmp, 0); \
574
BLOCK_XOR (block_tmp, subkeys[round]); \
578
/* Convert the user provided key KEY of KEY_LENGTH bytes into the
579
internally used format. */
581
serpent_key_prepare (const byte *key, unsigned int key_length,
582
serpent_key_t key_prepared)
587
for (i = 0; i < key_length / 4; i++)
589
#ifdef WORDS_BIGENDIAN
590
key_prepared[i] = byte_swap_32 (((u32 *) key)[i]);
592
key_prepared[i] = ((u32 *) key)[i];
598
/* Key must be padded according to the Serpent
600
key_prepared[i] = 0x00000001;
602
for (i++; i < 8; i++)
607
/* Derive the 33 subkeys from KEY and store them in SUBKEYS. */
609
serpent_subkeys_generate (serpent_key_t key, serpent_subkeys_t subkeys)
611
u32 w_real[140]; /* The `prekey'. */
616
/* Initialize with key values. */
617
for (i = 0; i < 8; i++)
620
/* Expand to intermediate key using the affine recurrence. */
621
for (i = 0; i < 132; i++)
622
w[i] = rol (w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i, 11);
624
/* Calculate subkeys via S-Boxes, in bitslice mode. */
659
/* Renumber subkeys. */
660
for (i = 0; i < ROUNDS + 1; i++)
661
for (j = 0; j < 4; j++)
662
subkeys[i][j] = k[4 * i + j];
665
/* Initialize CONTEXT with the key KEY of KEY_LENGTH bits. */
667
serpent_setkey_internal (serpent_context_t *context,
668
const byte *key, unsigned int key_length)
670
serpent_key_t key_prepared;
672
serpent_key_prepare (key, key_length, key_prepared);
673
serpent_subkeys_generate (key_prepared, context->keys);
674
_gcry_burn_stack (272 * sizeof (u32));
677
/* Initialize CTX with the key KEY of KEY_LENGTH bytes. */
678
static gcry_err_code_t
679
serpent_setkey (void *ctx,
680
const byte *key, unsigned int key_length)
682
serpent_context_t *context = ctx;
683
static const char *serpent_test_ret;
684
static int serpent_init_done;
685
gcry_err_code_t ret = GPG_ERR_NO_ERROR;
687
if (! serpent_init_done)
689
/* Execute a self-test the first time, Serpent is used. */
690
serpent_test_ret = serpent_test ();
691
if (serpent_test_ret)
692
log_error ("Serpent test failure: %s\n", serpent_test_ret);
693
serpent_init_done = 1;
696
if (serpent_test_ret)
697
ret = GPG_ERR_SELFTEST_FAILED;
700
serpent_setkey_internal (context, key, key_length);
701
_gcry_burn_stack (sizeof (serpent_key_t));
708
serpent_encrypt_internal (serpent_context_t *context,
709
const serpent_block_t input, serpent_block_t output)
711
serpent_block_t b, b_next;
714
#ifdef WORDS_BIGENDIAN
715
b[0] = byte_swap_32 (input[0]);
716
b[1] = byte_swap_32 (input[1]);
717
b[2] = byte_swap_32 (input[2]);
718
b[3] = byte_swap_32 (input[3]);
726
ROUND (0, context->keys, b, b_next);
727
ROUND (1, context->keys, b, b_next);
728
ROUND (2, context->keys, b, b_next);
729
ROUND (3, context->keys, b, b_next);
730
ROUND (4, context->keys, b, b_next);
731
ROUND (5, context->keys, b, b_next);
732
ROUND (6, context->keys, b, b_next);
733
ROUND (7, context->keys, b, b_next);
734
ROUND (0, context->keys, b, b_next);
735
ROUND (1, context->keys, b, b_next);
736
ROUND (2, context->keys, b, b_next);
737
ROUND (3, context->keys, b, b_next);
738
ROUND (4, context->keys, b, b_next);
739
ROUND (5, context->keys, b, b_next);
740
ROUND (6, context->keys, b, b_next);
741
ROUND (7, context->keys, b, b_next);
742
ROUND (0, context->keys, b, b_next);
743
ROUND (1, context->keys, b, b_next);
744
ROUND (2, context->keys, b, b_next);
745
ROUND (3, context->keys, b, b_next);
746
ROUND (4, context->keys, b, b_next);
747
ROUND (5, context->keys, b, b_next);
748
ROUND (6, context->keys, b, b_next);
749
ROUND (7, context->keys, b, b_next);
750
ROUND (0, context->keys, b, b_next);
751
ROUND (1, context->keys, b, b_next);
752
ROUND (2, context->keys, b, b_next);
753
ROUND (3, context->keys, b, b_next);
754
ROUND (4, context->keys, b, b_next);
755
ROUND (5, context->keys, b, b_next);
756
ROUND (6, context->keys, b, b_next);
758
ROUND_LAST (7, context->keys, b, b_next);
760
#ifdef WORDS_BIGENDIAN
761
output[0] = byte_swap_32 (b_next[0]);
762
output[1] = byte_swap_32 (b_next[1]);
763
output[2] = byte_swap_32 (b_next[2]);
764
output[3] = byte_swap_32 (b_next[3]);
766
output[0] = b_next[0];
767
output[1] = b_next[1];
768
output[2] = b_next[2];
769
output[3] = b_next[3];
774
serpent_decrypt_internal (serpent_context_t *context,
775
const serpent_block_t input, serpent_block_t output)
777
serpent_block_t b, b_next;
780
#ifdef WORDS_BIGENDIAN
781
b_next[0] = byte_swap_32 (input[0]);
782
b_next[1] = byte_swap_32 (input[1]);
783
b_next[2] = byte_swap_32 (input[2]);
784
b_next[3] = byte_swap_32 (input[3]);
786
b_next[0] = input[0];
787
b_next[1] = input[1];
788
b_next[2] = input[2];
789
b_next[3] = input[3];
792
ROUND_FIRST_INVERSE (7, context->keys, b_next, b);
794
ROUND_INVERSE (6, context->keys, b, b_next);
795
ROUND_INVERSE (5, context->keys, b, b_next);
796
ROUND_INVERSE (4, context->keys, b, b_next);
797
ROUND_INVERSE (3, context->keys, b, b_next);
798
ROUND_INVERSE (2, context->keys, b, b_next);
799
ROUND_INVERSE (1, context->keys, b, b_next);
800
ROUND_INVERSE (0, context->keys, b, b_next);
801
ROUND_INVERSE (7, context->keys, b, b_next);
802
ROUND_INVERSE (6, context->keys, b, b_next);
803
ROUND_INVERSE (5, context->keys, b, b_next);
804
ROUND_INVERSE (4, context->keys, b, b_next);
805
ROUND_INVERSE (3, context->keys, b, b_next);
806
ROUND_INVERSE (2, context->keys, b, b_next);
807
ROUND_INVERSE (1, context->keys, b, b_next);
808
ROUND_INVERSE (0, context->keys, b, b_next);
809
ROUND_INVERSE (7, context->keys, b, b_next);
810
ROUND_INVERSE (6, context->keys, b, b_next);
811
ROUND_INVERSE (5, context->keys, b, b_next);
812
ROUND_INVERSE (4, context->keys, b, b_next);
813
ROUND_INVERSE (3, context->keys, b, b_next);
814
ROUND_INVERSE (2, context->keys, b, b_next);
815
ROUND_INVERSE (1, context->keys, b, b_next);
816
ROUND_INVERSE (0, context->keys, b, b_next);
817
ROUND_INVERSE (7, context->keys, b, b_next);
818
ROUND_INVERSE (6, context->keys, b, b_next);
819
ROUND_INVERSE (5, context->keys, b, b_next);
820
ROUND_INVERSE (4, context->keys, b, b_next);
821
ROUND_INVERSE (3, context->keys, b, b_next);
822
ROUND_INVERSE (2, context->keys, b, b_next);
823
ROUND_INVERSE (1, context->keys, b, b_next);
824
ROUND_INVERSE (0, context->keys, b, b_next);
827
#ifdef WORDS_BIGENDIAN
828
output[0] = byte_swap_32 (b_next[0]);
829
output[1] = byte_swap_32 (b_next[1]);
830
output[2] = byte_swap_32 (b_next[2]);
831
output[3] = byte_swap_32 (b_next[3]);
833
output[0] = b_next[0];
834
output[1] = b_next[1];
835
output[2] = b_next[2];
836
output[3] = b_next[3];
841
serpent_encrypt (void *ctx, byte *buffer_out, const byte *buffer_in)
843
serpent_context_t *context = ctx;
845
serpent_encrypt_internal (context,
846
(const u32 *) buffer_in, (u32 *) buffer_out);
847
_gcry_burn_stack (2 * sizeof (serpent_block_t));
851
serpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in)
853
serpent_context_t *context = ctx;
855
serpent_decrypt_internal (context,
856
(const u32 *) buffer_in,
858
_gcry_burn_stack (2 * sizeof (serpent_block_t));
868
serpent_context_t context;
869
unsigned char scratch[16];
875
unsigned char key[32];
876
unsigned char text_plain[16];
877
unsigned char text_cipher[16];
882
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
883
"\xD2\x9D\x57\x6F\xCE\xA3\xA3\xA7\xED\x90\x99\xF2\x92\x73\xD7\x8E",
884
"\xB2\x28\x8B\x96\x8A\xE8\xB0\x86\x48\xD1\xCE\x96\x06\xFD\x99\x2D"
888
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
889
"\x00\x00\x00\x00\x00\x00\x00\x00",
890
"\xD2\x9D\x57\x6F\xCE\xAB\xA3\xA7\xED\x98\x99\xF2\x92\x7B\xD7\x8E",
891
"\x13\x0E\x35\x3E\x10\x37\xC2\x24\x05\xE8\xFA\xEF\xB2\xC3\xC3\xE9"
895
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
896
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
897
"\xD0\x95\x57\x6F\xCE\xA3\xE3\xA7\xED\x98\xD9\xF2\x90\x73\xD7\x8E",
898
"\xB9\x0E\xE5\x86\x2D\xE6\x91\x68\xF2\xBD\xD5\x12\x5B\x45\x47\x2B"
902
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
903
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
904
"\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00",
905
"\x20\x61\xA4\x27\x82\xBD\x52\xEC\x69\x1E\xC3\x83\xB0\x3B\xA7\x7C"
912
for (i = 0; test_data[i].key_length; i++)
914
serpent_setkey_internal (&context, test_data[i].key,
915
test_data[i].key_length);
916
serpent_encrypt_internal (&context,
917
(const u32 *) test_data[i].text_plain,
920
if (memcmp (scratch, test_data[i].text_cipher, sizeof (serpent_block_t)))
921
switch (test_data[i].key_length)
924
return "Serpent-128 test encryption failed.";
926
return "Serpent-192 test encryption failed.";
928
return "Serpent-256 test encryption failed.";
931
serpent_decrypt_internal (&context,
932
(const u32 *) test_data[i].text_cipher,
934
if (memcmp (scratch, test_data[i].text_plain, sizeof (serpent_block_t)))
935
switch (test_data[i].key_length)
938
return "Serpent-128 test decryption failed.";
940
return "Serpent-192 test decryption failed.";
942
return "Serpent-256 test decryption failed.";
951
/* "SERPENT" is an alias for "SERPENT128". */
952
static const char *cipher_spec_serpent128_aliases[] =
958
gcry_cipher_spec_t _gcry_cipher_spec_serpent128 =
960
"SERPENT128", cipher_spec_serpent128_aliases, NULL, 16, 128,
961
sizeof (serpent_context_t),
962
serpent_setkey, serpent_encrypt, serpent_decrypt
965
gcry_cipher_spec_t _gcry_cipher_spec_serpent192 =
967
"SERPENT192", NULL, NULL, 16, 192,
968
sizeof (serpent_context_t),
969
serpent_setkey, serpent_encrypt, serpent_decrypt
972
gcry_cipher_spec_t _gcry_cipher_spec_serpent256 =
974
"SERPENT256", NULL, NULL, 16, 256,
975
sizeof (serpent_context_t),
976
serpent_setkey, serpent_encrypt, serpent_decrypt
980
GRUB_MOD_INIT(gcry_serpent)
982
grub_cipher_register (&_gcry_cipher_spec_serpent128);
983
grub_cipher_register (&_gcry_cipher_spec_serpent192);
984
grub_cipher_register (&_gcry_cipher_spec_serpent256);
987
GRUB_MOD_FINI(gcry_serpent)
989
grub_cipher_unregister (&_gcry_cipher_spec_serpent128);
990
grub_cipher_unregister (&_gcry_cipher_spec_serpent192);
991
grub_cipher_unregister (&_gcry_cipher_spec_serpent256);