Commit e57e557f authored by Niels Möller's avatar Niels Möller
Browse files

* serpent.c (ROUNDS): Deleted macro.

(serpent_block_t): Deleted array typedef.
(KEYXOR): New macro, replacing BLOCK_XOR.
(BLOCK_COPY, SBOX, SBOX_INVERSE): Deleted macros.
(LINEAR_TRANSFORMATION): Use four separate arguments.
(LINEAR_TRANSFORMATION_INVERSE): Likewise.
(ROUND): Take separate arguments for all input and output words.
(ROUND_INVERSE): Likewise.
(ROUND_LAST, ROUND_FIRST_INVERSE): Deleted macros.
(serpent_set_key): Moved loop termination test.
(serpent_encrypt): Rewrote with unrolling of just eight rounds,
and without serpent_block_t.
(serpent_decrypt): Likewise.

Rev: nettle/ChangeLog:1.174
Rev: nettle/serpent.c:1.7
parent 763ed53e
2011-06-01 Niels Mller <nisse@lysator.liu.se> 2011-06-01 Niels Mller <nisse@lysator.liu.se>
* serpent.c (ROUNDS): Deleted macro.
(serpent_block_t): Deleted array typedef.
(KEYXOR): New macro, replacing BLOCK_XOR.
(BLOCK_COPY, SBOX, SBOX_INVERSE): Deleted macros.
(LINEAR_TRANSFORMATION): Use four separate arguments.
(LINEAR_TRANSFORMATION_INVERSE): Likewise.
(ROUND): Take separate arguments for all input and output words.
(ROUND_INVERSE): Likewise.
(ROUND_LAST, ROUND_FIRST_INVERSE): Deleted macros.
(serpent_set_key): Moved loop termination test.
(serpent_encrypt): Rewrote with unrolling of just eight rounds,
and without serpent_block_t.
(serpent_decrypt): Likewise.
* serpent.c: Added do { ... } while (0) around block macros. * serpent.c: Added do { ... } while (0) around block macros.
(serpent_key_t): Deleted array typedef. (serpent_key_t): Deleted array typedef.
(ROL32, ROR32): Renamed macros, were rol and ror. (ROL32, ROR32): Renamed macros, were rol and ror.
......
...@@ -48,15 +48,9 @@ ...@@ -48,15 +48,9 @@
#include "macros.h" #include "macros.h"
/* Number of rounds per Serpent encrypt/decrypt operation. */
#define ROUNDS 32
/* Magic number, used during generating of the subkeys. */ /* Magic number, used during generating of the subkeys. */
#define PHI 0x9E3779B9 #define PHI 0x9E3779B9
/* Serpent works on 128 bit blocks. */
typedef uint32_t serpent_block_t[4];
/* FIXME: Unify ROL macros used here, in camellia.c and cast128.c. */ /* FIXME: Unify ROL macros used here, in camellia.c and cast128.c. */
#define ROL32(x,n) ((((uint32_t)(x))<<(n))| \ #define ROL32(x,n) ((((uint32_t)(x))<<(n))| \
(((uint32_t)(x))>>(32-(n)))) (((uint32_t)(x))>>(32-(n))))
...@@ -79,6 +73,9 @@ typedef uint32_t serpent_block_t[4]; ...@@ -79,6 +73,9 @@ typedef uint32_t serpent_block_t[4];
(GPL), although some comments in the code still say otherwise. You (GPL), although some comments in the code still say otherwise. You
are welcome to use Serpent for any application." */ 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(a, b, c, d, w, x, y, z) \ #define SBOX0(a, b, c, d, w, x, y, z) \
do { \ do { \
uint32_t t02, t03, t05, t06, t07, t08, t09; \ uint32_t t02, t03, t05, t06, t07, t08, t09; \
...@@ -462,122 +459,63 @@ typedef uint32_t serpent_block_t[4]; ...@@ -462,122 +459,63 @@ typedef uint32_t serpent_block_t[4];
y = t14 ^ t16; \ y = t14 ^ t16; \
} while (0) } while (0)
/* XOR BLOCK1 into BLOCK0. */ /* In-place linear transformation. */
#define BLOCK_XOR(block0, block1) \ #define LINEAR_TRANSFORMATION(x0,x1,x2,x3) \
{ \
block0[0] ^= block1[0]; \
block0[1] ^= block1[1]; \
block0[2] ^= block1[2]; \
block0[3] ^= block1[3]; \
}
/* Copy BLOCK_SRC to BLOCK_DST. */
#define BLOCK_COPY(block_dst, block_src) \
{ \
block_dst[0] = block_src[0]; \
block_dst[1] = block_src[1]; \
block_dst[2] = block_src[2]; \
block_dst[3] = block_src[3]; \
}
/* Apply SBOX number WHICH to to the block found in ARRAY0 at index
INDEX, writing the output to the block found in ARRAY1 at index
INDEX. */
#define SBOX(which, array0, array1, index) \
SBOX##which (array0[index + 0], array0[index + 1], \
array0[index + 2], array0[index + 3], \
array1[index + 0], array1[index + 1], \
array1[index + 2], array1[index + 3]);
/* Apply inverse SBOX number WHICH to to the block found in ARRAY0 at
index INDEX, writing the output to the block found in ARRAY1 at
index INDEX. */
#define SBOX_INVERSE(which, array0, array1, index) \
SBOX##which##_INVERSE (array0[index + 0], array0[index + 1], \
array0[index + 2], array0[index + 3], \
array1[index + 0], array1[index + 1], \
array1[index + 2], array1[index + 3]);
/* Apply the linear transformation to BLOCK. */
#define LINEAR_TRANSFORMATION(block) \
do { \
block[0] = ROL32 (block[0], 13); \
block[2] = ROL32 (block[2], 3); \
block[1] = block[1] ^ block[0] ^ block[2]; \
block[3] = block[3] ^ block[2] ^ (block[0] << 3); \
block[1] = ROL32 (block[1], 1); \
block[3] = ROL32 (block[3], 7); \
block[0] = block[0] ^ block[1] ^ block[3]; \
block[2] = block[2] ^ block[3] ^ (block[1] << 7); \
block[0] = ROL32 (block[0], 5); \
block[2] = ROL32 (block[2], 22); \
} while (0)
/* Apply the inverse linear transformation to BLOCK. */
#define LINEAR_TRANSFORMATION_INVERSE(block) \
do { \ do { \
block[2] = ROR32 (block[2], 22); \ x0 = ROL32 (x0, 13); \
block[0] = ROR32 (block[0] , 5); \ x2 = ROL32 (x2, 3); \
block[2] = block[2] ^ block[3] ^ (block[1] << 7); \ x1 = x1 ^ x0 ^ x2; \
block[0] = block[0] ^ block[1] ^ block[3]; \ x3 = x3 ^ x2 ^ (x0 << 3); \
block[3] = ROR32 (block[3], 7); \ x1 = ROL32 (x1, 1); \
block[1] = ROR32 (block[1], 1); \ x3 = ROL32 (x3, 7); \
block[3] = block[3] ^ block[2] ^ (block[0] << 3); \ x0 = x0 ^ x1 ^ x3; \
block[1] = block[1] ^ block[0] ^ block[2]; \ x2 = x2 ^ x3 ^ (x1 << 7); \
block[2] = ROR32 (block[2], 3); \ x0 = ROL32 (x0, 5); \
block[0] = ROR32 (block[0], 13); \ x2 = ROL32 (x2, 22); \
} while (0) } while (0)
/* Apply a Serpent round to BLOCK, using the SBOX number WHICH and the /* In-place inverse linear transformation. */
subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage. #define LINEAR_TRANSFORMATION_INVERSE(x0,x1,x2,x3) \
This macro increments `round'. */
#define ROUND(which, subkeys, block, block_tmp) \
do { \ do { \
BLOCK_XOR (block, subkeys[round]); \ x2 = ROR32 (x2, 22); \
round++; \ x0 = ROR32 (x0 , 5); \
SBOX (which, block, block_tmp, 0); \ x2 = x2 ^ x3 ^ (x1 << 7); \
LINEAR_TRANSFORMATION (block_tmp); \ x0 = x0 ^ x1 ^ x3; \
BLOCK_COPY (block, block_tmp); \ x3 = ROR32 (x3, 7); \
x1 = ROR32 (x1, 1); \
x3 = x3 ^ x2 ^ (x0 << 3); \
x1 = x1 ^ x0 ^ x2; \
x2 = ROR32 (x2, 3); \
x0 = ROR32 (x0, 13); \
} while (0) } while (0)
/* Apply the last Serpent round to BLOCK, using the SBOX number WHICH #define KEYXOR(x0,x1,x2,x3, subkey) \
and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary
storage. The result will be stored in BLOCK_TMP. This macro
increments `round'. */
#define ROUND_LAST(which, subkeys, block, block_tmp) \
do { \ do { \
BLOCK_XOR (block, subkeys[round]); \ (x0) ^= (subkey)[0]; \
round++; \ (x1) ^= (subkey)[1]; \
SBOX (which, block, block_tmp, 0); \ (x2) ^= (subkey)[2]; \
BLOCK_XOR (block_tmp, subkeys[round]); \ (x3) ^= (subkey)[3]; \
round++; \
} while (0) } while (0)
/* Apply an inverse Serpent round to BLOCK, using the SBOX number /* Round inputs are x0,x1,x2,x3 (destroyed), and round outputs are
WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as y0,y1,y2,y3. */
temporary storage. This macro increments `round'. */ #define ROUND(which, subkey, x0,x1,x2,x3, y0,y1,y2,y3) \
#define ROUND_INVERSE(which, subkey, block, block_tmp) \
do { \ do { \
LINEAR_TRANSFORMATION_INVERSE (block); \ KEYXOR(x0,x1,x2,x3, subkey); \
SBOX_INVERSE (which, block, block_tmp, 0); \ SBOX##which(x0,x1,x2,x3, y0,y1,y2,y3); \
BLOCK_XOR (block_tmp, subkey[round]); \ LINEAR_TRANSFORMATION(y0,y1,y2,y3); \
round--; \
BLOCK_COPY (block, block_tmp); \
} while (0) } while (0)
/* Apply the first Serpent round to BLOCK, using the SBOX number WHICH /* Round inputs are x0,x1,x2,x3 (destroyed), and round outputs are
and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary y0,y1,y2,y3. */
storage. The result will be stored in BLOCK_TMP. This macro #define ROUND_INVERSE(which, subkey, x0,x1,x2,x3, y0,y1,y2,y3) \
increments `round'. */
#define ROUND_FIRST_INVERSE(which, subkeys, block, block_tmp) \
do { \ do { \
BLOCK_XOR (block, subkeys[round]); \ LINEAR_TRANSFORMATION_INVERSE (x0,x1,x2,x3); \
round--; \ SBOX##which##_INVERSE(x0,x1,x2,x3, y0,y1,y2,y3); \
SBOX_INVERSE (which, block, block_tmp, 0); \ KEYXOR(y0,y1,y2,y3, subkey); \
BLOCK_XOR (block_tmp, subkeys[round]); \
round--; \
} while (0) } while (0)
/* Key schedule */
/* Note: Increments k */ /* Note: Increments k */
#define KS_RECURRENCE(w, i, k) \ #define KS_RECURRENCE(w, i, k) \
do { \ do { \
...@@ -645,9 +583,13 @@ serpent_set_key (struct serpent_ctx *ctx, ...@@ -645,9 +583,13 @@ serpent_set_key (struct serpent_ctx *ctx,
arguments, no arrays. To do that, unpack w into separate arguments, no arrays. To do that, unpack w into separate
variables, use temporary variables as the SBOX destination. */ variables, use temporary variables as the SBOX destination. */
for (keys = ctx->keys, k = 0; k < 128;) keys = ctx->keys;
k = 0;
for (;;)
{ {
KS(keys, 3, w, 0, k); KS(keys, 3, w, 0, k);
if (k == 132)
break;
KS(keys, 2, w, 4, k); KS(keys, 2, w, 4, k);
KS(keys, 1, w, 0, k); KS(keys, 1, w, 0, k);
KS(keys, 0, w, 4, k); KS(keys, 0, w, 4, k);
...@@ -656,8 +598,6 @@ serpent_set_key (struct serpent_ctx *ctx, ...@@ -656,8 +598,6 @@ serpent_set_key (struct serpent_ctx *ctx,
KS(keys, 5, w, 0, k); KS(keys, 5, w, 0, k);
KS(keys, 4, w, 4, k); KS(keys, 4, w, 4, k);
} }
KS(keys, 3, w, 0, k);
assert (k == 132);
assert (keys == ctx->keys + 33); assert (keys == ctx->keys + 33);
} }
...@@ -667,52 +607,37 @@ serpent_encrypt (const struct serpent_ctx *ctx, ...@@ -667,52 +607,37 @@ serpent_encrypt (const struct serpent_ctx *ctx,
{ {
FOR_BLOCKS (length, dst, src, SERPENT_BLOCK_SIZE) FOR_BLOCKS (length, dst, src, SERPENT_BLOCK_SIZE)
{ {
serpent_block_t b, b_next; uint32_t x0,x1,x2,x3, y0,y1,y2,y3;
int round = 0; unsigned k;
b[0] = LE_READ_UINT32 (src); x0 = LE_READ_UINT32 (src);
b[1] = LE_READ_UINT32 (src + 4); x1 = LE_READ_UINT32 (src + 4);
b[2] = LE_READ_UINT32 (src + 8); x2 = LE_READ_UINT32 (src + 8);
b[3] = LE_READ_UINT32 (src + 12); x3 = LE_READ_UINT32 (src + 12);
ROUND (0, ctx->keys, b, b_next); for (k = 0; ; k += 8)
ROUND (1, ctx->keys, b, b_next); {
ROUND (2, ctx->keys, b, b_next); ROUND (0, ctx->keys[k+0], x0,x1,x2,x3, y0,y1,y2,y3);
ROUND (3, ctx->keys, b, b_next); ROUND (1, ctx->keys[k+1], y0,y1,y2,y3, x0,x1,x2,x3);
ROUND (4, ctx->keys, b, b_next); ROUND (2, ctx->keys[k+2], x0,x1,x2,x3, y0,y1,y2,y3);
ROUND (5, ctx->keys, b, b_next); ROUND (3, ctx->keys[k+3], y0,y1,y2,y3, x0,x1,x2,x3);
ROUND (6, ctx->keys, b, b_next); ROUND (4, ctx->keys[k+4], x0,x1,x2,x3, y0,y1,y2,y3);
ROUND (7, ctx->keys, b, b_next); ROUND (5, ctx->keys[k+5], y0,y1,y2,y3, x0,x1,x2,x3);
ROUND (0, ctx->keys, b, b_next); ROUND (6, ctx->keys[k+6], x0,x1,x2,x3, y0,y1,y2,y3);
ROUND (1, ctx->keys, b, b_next); if (k == 24)
ROUND (2, ctx->keys, b, b_next); break;
ROUND (3, ctx->keys, b, b_next); ROUND (7, ctx->keys[k+7], y0,y1,y2,y3, x0,x1,x2,x3);
ROUND (4, ctx->keys, b, b_next); }
ROUND (5, ctx->keys, b, b_next);
ROUND (6, ctx->keys, b, b_next); /* Special final round, using two subkeys. */
ROUND (7, ctx->keys, b, b_next); KEYXOR (y0,y1,y2,y3, ctx->keys[31]);
ROUND (0, ctx->keys, b, b_next); SBOX7 (y0,y1,y2,y3, x0,x1,x2,x3);
ROUND (1, ctx->keys, b, b_next); KEYXOR (x0,x1,x2,x3, ctx->keys[32]);
ROUND (2, ctx->keys, b, b_next);
ROUND (3, ctx->keys, b, b_next); LE_WRITE_UINT32 (dst, x0);
ROUND (4, ctx->keys, b, b_next); LE_WRITE_UINT32 (dst + 4, x1);
ROUND (5, ctx->keys, b, b_next); LE_WRITE_UINT32 (dst + 8, x2);
ROUND (6, ctx->keys, b, b_next); LE_WRITE_UINT32 (dst + 12, x3);
ROUND (7, ctx->keys, b, b_next);
ROUND (0, ctx->keys, b, b_next);
ROUND (1, ctx->keys, b, b_next);
ROUND (2, ctx->keys, b, b_next);
ROUND (3, ctx->keys, b, b_next);
ROUND (4, ctx->keys, b, b_next);
ROUND (5, ctx->keys, b, b_next);
ROUND (6, ctx->keys, b, b_next);
ROUND_LAST (7, ctx->keys, b, b_next);
LE_WRITE_UINT32 (dst, b_next[0]);
LE_WRITE_UINT32 (dst + 4, b_next[1]);
LE_WRITE_UINT32 (dst + 8, b_next[2]);
LE_WRITE_UINT32 (dst + 12, b_next[3]);
} }
} }
...@@ -722,51 +647,38 @@ serpent_decrypt (const struct serpent_ctx *ctx, ...@@ -722,51 +647,38 @@ serpent_decrypt (const struct serpent_ctx *ctx,
{ {
FOR_BLOCKS (length, dst, src, SERPENT_BLOCK_SIZE) FOR_BLOCKS (length, dst, src, SERPENT_BLOCK_SIZE)
{ {
serpent_block_t b, b_next; uint32_t x0,x1,x2,x3, y0,y1,y2,y3;
int round = ROUNDS; unsigned k;
b_next[0] = LE_READ_UINT32 (src); x0 = LE_READ_UINT32 (src);
b_next[1] = LE_READ_UINT32 (src + 4); x1 = LE_READ_UINT32 (src + 4);
b_next[2] = LE_READ_UINT32 (src + 8); x2 = LE_READ_UINT32 (src + 8);
b_next[3] = LE_READ_UINT32 (src + 12); x3 = LE_READ_UINT32 (src + 12);
ROUND_FIRST_INVERSE (7, ctx->keys, b_next, b); /* Inverse of special round */
KEYXOR (x0,x1,x2,x3, ctx->keys[32]);
ROUND_INVERSE (6, ctx->keys, b, b_next); SBOX7_INVERSE (x0,x1,x2,x3, y0,y1,y2,y3);
ROUND_INVERSE (5, ctx->keys, b, b_next); KEYXOR (y0,y1,y2,y3, ctx->keys[31]);
ROUND_INVERSE (4, ctx->keys, b, b_next);
ROUND_INVERSE (3, ctx->keys, b, b_next); k = 24;
ROUND_INVERSE (2, ctx->keys, b, b_next); goto start;
ROUND_INVERSE (1, ctx->keys, b, b_next); while (k > 0)
ROUND_INVERSE (0, ctx->keys, b, b_next); {
ROUND_INVERSE (7, ctx->keys, b, b_next); k -= 8;
ROUND_INVERSE (6, ctx->keys, b, b_next); ROUND_INVERSE (7, ctx->keys[k+7], x0,x1,x2,x3, y0,y1,y2,y3);
ROUND_INVERSE (5, ctx->keys, b, b_next); start:
ROUND_INVERSE (4, ctx->keys, b, b_next); ROUND_INVERSE (6, ctx->keys[k+6], y0,y1,y2,y3, x0,x1,x2,x3);
ROUND_INVERSE (3, ctx->keys, b, b_next); ROUND_INVERSE (5, ctx->keys[k+5], x0,x1,x2,x3, y0,y1,y2,y3);
ROUND_INVERSE (2, ctx->keys, b, b_next); ROUND_INVERSE (4, ctx->keys[k+4], y0,y1,y2,y3, x0,x1,x2,x3);
ROUND_INVERSE (1, ctx->keys, b, b_next); ROUND_INVERSE (3, ctx->keys[k+3], x0,x1,x2,x3, y0,y1,y2,y3);
ROUND_INVERSE (0, ctx->keys, b, b_next); ROUND_INVERSE (2, ctx->keys[k+2], y0,y1,y2,y3, x0,x1,x2,x3);
ROUND_INVERSE (7, ctx->keys, b, b_next); ROUND_INVERSE (1, ctx->keys[k+1], x0,x1,x2,x3, y0,y1,y2,y3);
ROUND_INVERSE (6, ctx->keys, b, b_next); ROUND_INVERSE (0, ctx->keys[k], y0,y1,y2,y3, x0,x1,x2,x3);
ROUND_INVERSE (5, ctx->keys, b, b_next); }
ROUND_INVERSE (4, ctx->keys, b, b_next);
ROUND_INVERSE (3, ctx->keys, b, b_next); LE_WRITE_UINT32 (dst, x0);
ROUND_INVERSE (2, ctx->keys, b, b_next); LE_WRITE_UINT32 (dst + 4, x1);
ROUND_INVERSE (1, ctx->keys, b, b_next); LE_WRITE_UINT32 (dst + 8, x2);
ROUND_INVERSE (0, ctx->keys, b, b_next); LE_WRITE_UINT32 (dst + 12, x3);
ROUND_INVERSE (7, ctx->keys, b, b_next);
ROUND_INVERSE (6, ctx->keys, b, b_next);
ROUND_INVERSE (5, ctx->keys, b, b_next);
ROUND_INVERSE (4, ctx->keys, b, b_next);
ROUND_INVERSE (3, ctx->keys, b, b_next);
ROUND_INVERSE (2, ctx->keys, b, b_next);
ROUND_INVERSE (1, ctx->keys, b, b_next);
ROUND_INVERSE (0, ctx->keys, b, b_next);
LE_WRITE_UINT32 (dst, b_next[0]);
LE_WRITE_UINT32 (dst + 4, b_next[1]);
LE_WRITE_UINT32 (dst + 8, b_next[2]);
LE_WRITE_UINT32 (dst + 12, b_next[3]);
} }
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment