summaryrefslogtreecommitdiff
path: root/serpent-set-key.c
diff options
context:
space:
mode:
Diffstat (limited to 'serpent-set-key.c')
-rw-r--r--serpent-set-key.c351
1 files changed, 351 insertions, 0 deletions
diff --git a/serpent-set-key.c b/serpent-set-key.c
new file mode 100644
index 00000000..d03f50eb
--- /dev/null
+++ b/serpent-set-key.c
@@ -0,0 +1,351 @@
+/* serpent-set-key.c
+ *
+ * The serpent block cipher.
+ *
+ * For more details on this algorithm, see the Serpent website at
+ * http://www.cl.cam.ac.uk/~rja14/serpent.html
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2011 Niels Möller
+ * Copyright (C) 2010, 2011 Simon Josefsson
+ * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+ *
+ * The nettle library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * The nettle library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the nettle library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/* This file is derived from cipher/serpent.c in Libgcrypt v1.4.6.
+ The adaption to Nettle was made by Simon Josefsson on 2010-12-07
+ with final touches on 2011-05-30. Changes include replacing
+ libgcrypt with nettle in the license template, renaming
+ serpent_context to serpent_ctx, renaming u32 to uint32_t, removing
+ libgcrypt stubs and selftests, modifying entry function prototypes,
+ using FOR_BLOCKS to iterate through data in encrypt/decrypt, using
+ LE_READ_UINT32 and LE_WRITE_UINT32 to access data in
+ encrypt/decrypt, and running indent on the code. */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <limits.h>
+
+#include "serpent.h"
+
+#include "macros.h"
+#include "serpent-internal.h"
+
+/* Magic number, used during generating of the subkeys. */
+#define PHI 0x9E3779B9
+
+/* These are the S-Boxes of Serpent. They are copied from Serpents
+ reference implementation (the optimized one, contained in
+ `floppy2') and are therefore:
+
+ Copyright (C) 1998 Ross Anderson, Eli Biham, Lars Knudsen.
+
+ To quote the Serpent homepage
+ (http://www.cl.cam.ac.uk/~rja14/serpent.html):
+
+ "Serpent is now completely in the public domain, and we impose no
+ restrictions on its use. This was announced on the 21st August at
+ the First AES Candidate Conference. The optimised implementations
+ in the submission package are now under the GNU PUBLIC LICENSE
+ (GPL), although some comments in the code still say otherwise. You
+ are welcome to use Serpent for any application." */
+
+/* FIXME: Except when used within the key schedule, the inputs are not
+ used after the substitution, and hence we could allow them to be
+ destroyed. Can this freedom be used to optimize the sboxes? */
+#define SBOX0(type, a, b, c, d, w, x, y, z) \
+ do { \
+ type t02, t03, t05, t06, t07, t08, t09; \
+ type t11, t12, t13, t14, t15, t17, t01; \
+ t01 = b ^ c ; \
+ t02 = a | d ; \
+ t03 = a ^ b ; \
+ z = t02 ^ t01; \
+ t05 = c | z ; \
+ t06 = a ^ d ; \
+ t07 = b | c ; \
+ t08 = d & t05; \
+ t09 = t03 & t07; \
+ y = t09 ^ t08; \
+ t11 = t09 & y ; \
+ t12 = c ^ d ; \
+ t13 = t07 ^ t11; \
+ t14 = b & t06; \
+ t15 = t06 ^ t13; \
+ w = ~ t15; \
+ t17 = w ^ t14; \
+ x = t12 ^ t17; \
+ } while (0)
+
+#define SBOX1(type, a, b, c, d, w, x, y, z) \
+ do { \
+ type t02, t03, t04, t05, t06, t07, t08; \
+ type t10, t11, t12, t13, t16, t17, t01; \
+ t01 = a | d ; \
+ t02 = c ^ d ; \
+ t03 = ~ b ; \
+ t04 = a ^ c ; \
+ t05 = a | t03; \
+ t06 = d & t04; \
+ t07 = t01 & t02; \
+ t08 = b | t06; \
+ y = t02 ^ t05; \
+ t10 = t07 ^ t08; \
+ t11 = t01 ^ t10; \
+ t12 = y ^ t11; \
+ t13 = b & d ; \
+ z = ~ t10; \
+ x = t13 ^ t12; \
+ t16 = t10 | x ; \
+ t17 = t05 & t16; \
+ w = c ^ t17; \
+ } while (0)
+
+#define SBOX2(type, a, b, c, d, w, x, y, z) \
+ do { \
+ type t02, t03, t05, t06, t07, t08; \
+ type t09, t10, t12, t13, t14, t01; \
+ t01 = a | c ; \
+ t02 = a ^ b ; \
+ t03 = d ^ t01; \
+ w = t02 ^ t03; \
+ t05 = c ^ w ; \
+ t06 = b ^ t05; \
+ t07 = b | t05; \
+ t08 = t01 & t06; \
+ t09 = t03 ^ t07; \
+ t10 = t02 | t09; \
+ x = t10 ^ t08; \
+ t12 = a | d ; \
+ t13 = t09 ^ x ; \
+ t14 = b ^ t13; \
+ z = ~ t09; \
+ y = t12 ^ t14; \
+ } while (0)
+
+#define SBOX3(type, a, b, c, d, w, x, y, z) \
+ do { \
+ type t02, t03, t04, t05, t06, t07, t08; \
+ type t09, t10, t11, t13, t14, t15, t01; \
+ t01 = a ^ c ; \
+ t02 = a | d ; \
+ t03 = a & d ; \
+ t04 = t01 & t02; \
+ t05 = b | t03; \
+ t06 = a & b ; \
+ t07 = d ^ t04; \
+ t08 = c | t06; \
+ t09 = b ^ t07; \
+ t10 = d & t05; \
+ t11 = t02 ^ t10; \
+ z = t08 ^ t09; \
+ t13 = d | z ; \
+ t14 = a | t07; \
+ t15 = b & t13; \
+ y = t08 ^ t11; \
+ w = t14 ^ t15; \
+ x = t05 ^ t04; \
+ } while (0)
+
+#define SBOX4(type, a, b, c, d, w, x, y, z) \
+ do { \
+ type t02, t03, t04, t05, t06, t08, t09; \
+ type t10, t11, t12, t13, t14, t15, t16, t01; \
+ t01 = a | b ; \
+ t02 = b | c ; \
+ t03 = a ^ t02; \
+ t04 = b ^ d ; \
+ t05 = d | t03; \
+ t06 = d & t01; \
+ z = t03 ^ t06; \
+ t08 = z & t04; \
+ t09 = t04 & t05; \
+ t10 = c ^ t06; \
+ t11 = b & c ; \
+ t12 = t04 ^ t08; \
+ t13 = t11 | t03; \
+ t14 = t10 ^ t09; \
+ t15 = a & t05; \
+ t16 = t11 | t12; \
+ y = t13 ^ t08; \
+ x = t15 ^ t16; \
+ w = ~ t14; \
+ } while (0)
+
+#define SBOX5(type, a, b, c, d, w, x, y, z) \
+ do { \
+ type t02, t03, t04, t05, t07, t08, t09; \
+ type t10, t11, t12, t13, t14, t01; \
+ t01 = b ^ d ; \
+ t02 = b | d ; \
+ t03 = a & t01; \
+ t04 = c ^ t02; \
+ t05 = t03 ^ t04; \
+ w = ~ t05; \
+ t07 = a ^ t01; \
+ t08 = d | w ; \
+ t09 = b | t05; \
+ t10 = d ^ t08; \
+ t11 = b | t07; \
+ t12 = t03 | w ; \
+ t13 = t07 | t10; \
+ t14 = t01 ^ t11; \
+ y = t09 ^ t13; \
+ x = t07 ^ t08; \
+ z = t12 ^ t14; \
+ } while (0)
+
+#define SBOX6(type, a, b, c, d, w, x, y, z) \
+ do { \
+ type t02, t03, t04, t05, t07, t08, t09, t10; \
+ type t11, t12, t13, t15, t17, t18, t01; \
+ t01 = a & d ; \
+ t02 = b ^ c ; \
+ t03 = a ^ d ; \
+ t04 = t01 ^ t02; \
+ t05 = b | c ; \
+ x = ~ t04; \
+ t07 = t03 & t05; \
+ t08 = b & x ; \
+ t09 = a | c ; \
+ t10 = t07 ^ t08; \
+ t11 = b | d ; \
+ t12 = c ^ t11; \
+ t13 = t09 ^ t10; \
+ y = ~ t13; \
+ t15 = x & t03; \
+ z = t12 ^ t07; \
+ t17 = a ^ b ; \
+ t18 = y ^ t15; \
+ w = t17 ^ t18; \
+ } while (0)
+
+#define SBOX7(type, a, b, c, d, w, x, y, z) \
+ do { \
+ type t02, t03, t04, t05, t06, t08, t09, t10; \
+ type t11, t13, t14, t15, t16, t17, t01; \
+ t01 = a & c ; \
+ t02 = ~ d ; \
+ t03 = a & t02; \
+ t04 = b | t01; \
+ t05 = a & b ; \
+ t06 = c ^ t04; \
+ z = t03 ^ t06; \
+ t08 = c | z ; \
+ t09 = d | t05; \
+ t10 = a ^ t08; \
+ t11 = t04 & z ; \
+ x = t09 ^ t10; \
+ t13 = b ^ x ; \
+ t14 = t01 ^ x ; \
+ t15 = c ^ t05; \
+ t16 = t11 | t13; \
+ t17 = t02 | t14; \
+ w = t15 ^ t17; \
+ y = a ^ t16; \
+ } while (0)
+
+/* Key schedule */
+/* Note: Increments k */
+#define KS_RECURRENCE(w, i, k) \
+ do { \
+ uint32_t _wn = (w)[(i)] ^ (w)[((i)+3)&7] ^ w[((i)+5)&7] \
+ ^ w[((i)+7)&7] ^ PHI ^ (k)++; \
+ ((w)[(i)] = ROL32(_wn, 11)); \
+ } while (0)
+
+/* Note: Increments k four times and keys once */
+#define KS(keys, s, w, i, k) \
+ do { \
+ KS_RECURRENCE(w, (i), (k)); \
+ KS_RECURRENCE(w, (i)+1, (k)); \
+ KS_RECURRENCE(w, (i)+2, (k)); \
+ KS_RECURRENCE(w, (i)+3, (k)); \
+ SBOX##s(uint32_t, w[(i)],w[(i)+1],w[(i)+2],w[(i)+3], \
+ (*keys)[0],(*keys)[1],(*keys)[2],(*keys)[3]); \
+ (keys)++; \
+ } while (0)
+
+/* Pad user key and convert to an array of 8 uint32_t. */
+static void
+serpent_key_pad (const uint8_t *key, unsigned int key_length,
+ uint32_t *w)
+{
+ unsigned int i;
+
+ assert (key_length <= SERPENT_MAX_KEY_SIZE);
+
+ for (i = 0; key_length >= 4; key_length -=4, key += 4)
+ w[i++] = LE_READ_UINT32(key);
+
+ if (i < 8)
+ {
+ /* Key must be padded according to the Serpent specification.
+ "aabbcc" -> "aabbcc0100...00" -> 0x01ccbbaa. */
+ uint32_t pad = 0x01;
+
+ while (key_length > 0)
+ pad = pad << 8 | key[--key_length];
+
+ w[i++] = pad;
+
+ while (i < 8)
+ w[i++] = 0;
+ }
+}
+
+/* Initialize CONTEXT with the key KEY of KEY_LENGTH bits. */
+void
+serpent_set_key (struct serpent_ctx *ctx,
+ unsigned length, const uint8_t * key)
+{
+ uint32_t w[8];
+ uint32_t (*keys)[4];
+ unsigned k;
+
+ serpent_key_pad (key, length, w);
+
+ /* Derive the 33 subkeys from KEY and store them in SUBKEYS. We do
+ the recurrence in the key schedule using W as a circular buffer
+ of just 8 uint32_t. */
+
+ /* FIXME: Would be better to invoke SBOX with scalar variables as
+ arguments, no arrays. To do that, unpack w into separate
+ variables, use temporary variables as the SBOX destination. */
+
+ keys = ctx->keys;
+ k = 0;
+ for (;;)
+ {
+ KS(keys, 3, w, 0, k);
+ if (k == 132)
+ break;
+ KS(keys, 2, w, 4, k);
+ KS(keys, 1, w, 0, k);
+ KS(keys, 0, w, 4, k);
+ KS(keys, 7, w, 0, k);
+ KS(keys, 6, w, 4, k);
+ KS(keys, 5, w, 0, k);
+ KS(keys, 4, w, 4, k);
+ }
+ assert (keys == ctx->keys + 33);
+}