From: Simon Josefsson Date: Tue, 31 May 2011 20:56:10 +0000 (+0200) Subject: Serpent rewrite. X-Git-Tag: nettle_2.2_release_20110711~90 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6578740ed53c510a48ab831760b0d5d1fd724b0d;p=thirdparty%2Fnettle.git Serpent rewrite. Rev: nettle/ChangeLog:1.170 Rev: nettle/Makefile.in:1.33 Rev: nettle/serpent.c:1.4 Rev: nettle/serpent_sboxes.h:1.2(DEAD) --- diff --git a/ChangeLog b/ChangeLog index a8338e4c..96a910f2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-05-30 Simon Josefsson + + * serpent.c: Rewrite, based on libgcrypt code. License changed + from GPL to LGPL. + * serpent_sboxes.h: Removed. + * Makefile.in: Drop serpent_sboxes.h. + 2011-05-31 Niels Möller * testsuite/serpent-test.c (test_main): Added some tests for diff --git a/Makefile.in b/Makefile.in index d71a7127..6b4948b5 100644 --- a/Makefile.in +++ b/Makefile.in @@ -128,7 +128,7 @@ DISTFILES = $(SOURCES) $(HEADERS) .bootstrap aclocal.m4 configure.ac \ README AUTHORS COPYING COPYING.LIB INSTALL NEWS TODO ChangeLog \ memxor.c $(des_headers) descore.README \ aes-internal.h camellia-internal.h cast128_sboxes.h desinfo.h desCode.h \ - serpent_sboxes.h nettle-internal.h nettle-write.h prime-list.h \ + nettle-internal.h nettle-write.h prime-list.h \ asm.m4 \ nettle.texinfo nettle.info nettle.html nettle.pdf sha-example.c diff --git a/serpent.c b/serpent.c index c88192d2..1667d65f 100644 --- a/serpent.c +++ b/serpent.c @@ -1,4 +1,4 @@ -/* serpent.h +/* serpent.c * * The serpent block cipher. * @@ -8,358 +8,787 @@ /* nettle, low-level cryptographics library * - * Copyright (C) 1998, 2000, 2001, 2011, - * Ross Anderson, Eli Biham, Lars Knudsen, Rafael R. Sevilla, Niels Möller - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* I've modified this code a bit so that it interoperates with lsh - * properly. 2000-9-5, Rafael R. Sevilla + * 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. */ -/* NOTE: The copyright notice for the original version of this code - * said "All rights reserved. This code is freely distributed for AES - * selection process. No other use is allowed." However, the authors - * later decided to GPL the code. /nisse */ +/* 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" +#include "config.h" #endif #include #include "serpent.h" -#include "serpent_sboxes.h" #include "macros.h" -void -serpent_set_key(struct serpent_ctx *ctx, - unsigned key_size, const uint8_t *key) -{ - unsigned i, j; - uint32_t w[132], k[132]; +/* Number of rounds per Serpent encrypt/decrypt operation. */ +#define ROUNDS 32 + +/* Magic number, used during generating of the subkeys. */ +#define PHI 0x9E3779B9 + +/* Serpent works on 128 bit blocks. */ +typedef uint32_t serpent_block_t[4]; + +/* Serpent key, provided by the user. If the original key is shorter + than 256 bits, it is padded. */ +typedef uint32_t serpent_key_t[8]; + +#define byte_swap_32(x) \ + (0 \ + | (((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \ + | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#define rol(x,n) ((((uint32_t)(x))<<(n))| \ + (((uint32_t)(x))>>(32-(n)))) +#define ror(x,n) ((((uint32_t)(x))<<(32-(n)))| \ + (((uint32_t)(x))>>(n))) + +/* 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." */ + +#define SBOX0(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t05, t06, t07, t08, t09; \ + uint32_t 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; \ + } + +#define SBOX0_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t08, t09, t10; \ + uint32_t t12, t13, t14, t15, t17, t18, t01; \ + t01 = c ^ d ; \ + t02 = a | b ; \ + t03 = b | c ; \ + t04 = c & t01; \ + t05 = t02 ^ t01; \ + t06 = a | t04; \ + y = ~ t05; \ + t08 = b ^ d ; \ + t09 = t03 & t08; \ + t10 = d | y ; \ + x = t09 ^ t06; \ + t12 = a | t05; \ + t13 = x ^ t12; \ + t14 = t03 ^ t10; \ + t15 = a ^ c ; \ + z = t14 ^ t13; \ + t17 = t05 & t13; \ + t18 = t14 | t17; \ + w = t15 ^ t18; \ + } + +#define SBOX1(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t07, t08; \ + uint32_t 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; \ + } + +#define SBOX1_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t07, t08; \ + uint32_t t09, t10, t11, t14, t15, t17, t01; \ + t01 = a ^ b ; \ + t02 = b | d ; \ + t03 = a & c ; \ + t04 = c ^ t02; \ + t05 = a | t04; \ + t06 = t01 & t05; \ + t07 = d | t03; \ + t08 = b ^ t06; \ + t09 = t07 ^ t06; \ + t10 = t04 | t03; \ + t11 = d & t08; \ + y = ~ t09; \ + x = t10 ^ t11; \ + t14 = a | y ; \ + t15 = t06 ^ x ; \ + z = t01 ^ t04; \ + t17 = c ^ t15; \ + w = t14 ^ t17; \ + } + +#define SBOX2(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t05, t06, t07, t08; \ + uint32_t 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; \ + } + +#define SBOX2_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t06, t07, t08, t09; \ + uint32_t t10, t11, t12, t15, t16, t17, t01; \ + t01 = a ^ d ; \ + t02 = c ^ d ; \ + t03 = a & c ; \ + t04 = b | t02; \ + w = t01 ^ t04; \ + t06 = a | c ; \ + t07 = d | w ; \ + t08 = ~ d ; \ + t09 = b & t06; \ + t10 = t08 | t03; \ + t11 = b & t07; \ + t12 = t06 & t02; \ + z = t09 ^ t10; \ + x = t12 ^ t11; \ + t15 = c & z ; \ + t16 = w ^ x ; \ + t17 = t10 ^ t15; \ + y = t16 ^ t17; \ + } + +#define SBOX3(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t07, t08; \ + uint32_t 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; \ + } + +#define SBOX3_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t07, t09; \ + uint32_t t11, t12, t13, t14, t16, t01; \ + t01 = c | d ; \ + t02 = a | d ; \ + t03 = c ^ t02; \ + t04 = b ^ t02; \ + t05 = a ^ d ; \ + t06 = t04 & t03; \ + t07 = b & t01; \ + y = t05 ^ t06; \ + t09 = a ^ t03; \ + w = t07 ^ t03; \ + t11 = w | t05; \ + t12 = t09 & t11; \ + t13 = a & y ; \ + t14 = t01 ^ t05; \ + x = b ^ t12; \ + t16 = b | t13; \ + z = t14 ^ t16; \ + } + +#define SBOX4(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t08, t09; \ + uint32_t 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; \ + } + +#define SBOX4_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t07, t09; \ + uint32_t t10, t11, t12, t13, t15, t01; \ + t01 = b | d ; \ + t02 = c | d ; \ + t03 = a & t01; \ + t04 = b ^ t02; \ + t05 = c ^ d ; \ + t06 = ~ t03; \ + t07 = a & t04; \ + x = t05 ^ t07; \ + t09 = x | t06; \ + t10 = a ^ t07; \ + t11 = t01 ^ t09; \ + t12 = d ^ t04; \ + t13 = c | t10; \ + z = t03 ^ t12; \ + t15 = a ^ t04; \ + y = t11 ^ t13; \ + w = t15 ^ t09; \ + } + +#define SBOX5(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t07, t08, t09; \ + uint32_t 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; \ + } + +#define SBOX5_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t07, t08, t09; \ + uint32_t t10, t12, t13, t15, t16, t01; \ + t01 = a & d ; \ + t02 = c ^ t01; \ + t03 = a ^ d ; \ + t04 = b & t02; \ + t05 = a & c ; \ + w = t03 ^ t04; \ + t07 = a & w ; \ + t08 = t01 ^ w ; \ + t09 = b | t05; \ + t10 = ~ b ; \ + x = t08 ^ t09; \ + t12 = t10 | t07; \ + t13 = w | x ; \ + z = t02 ^ t12; \ + t15 = t02 ^ t13; \ + t16 = b ^ d ; \ + y = t16 ^ t15; \ + } + +#define SBOX6(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t07, t08, t09, t10; \ + uint32_t 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; \ + } + +#define SBOX6_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t07, t08, t09; \ + uint32_t t12, t13, t14, t15, t16, t17, t01; \ + t01 = a ^ c ; \ + t02 = ~ c ; \ + t03 = b & t01; \ + t04 = b | t02; \ + t05 = d | t03; \ + t06 = b ^ d ; \ + t07 = a & t04; \ + t08 = a | t02; \ + t09 = t07 ^ t05; \ + x = t06 ^ t08; \ + w = ~ t09; \ + t12 = b & w ; \ + t13 = t01 & t05; \ + t14 = t01 ^ t12; \ + t15 = t07 ^ t13; \ + t16 = d | t02; \ + t17 = a ^ x ; \ + z = t17 ^ t15; \ + y = t16 ^ t14; \ + } + +#define SBOX7(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t08, t09, t10; \ + uint32_t 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; \ + } + +#define SBOX7_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t06, t07, t08, t09; \ + uint32_t t10, t11, t13, t14, t15, t16, t01; \ + t01 = a & b ; \ + t02 = a | b ; \ + t03 = c | t01; \ + t04 = d & t02; \ + z = t03 ^ t04; \ + t06 = b ^ t04; \ + t07 = d ^ z ; \ + t08 = ~ t07; \ + t09 = t06 | t08; \ + t10 = b ^ d ; \ + t11 = a | d ; \ + x = a ^ t09; \ + t13 = c ^ t06; \ + t14 = c & t11; \ + t15 = d | x ; \ + t16 = t01 | t10; \ + w = t13 ^ t15; \ + y = t14 ^ t16; \ + } + +/* XOR BLOCK1 into BLOCK0. */ +#define BLOCK_XOR(block0, block1) \ + { \ + block0[0] ^= block1[0]; \ + block0[1] ^= block1[1]; \ + block0[2] ^= block1[2]; \ + block0[3] ^= block1[3]; \ + } - assert(key_size >= SERPENT_MIN_KEY_SIZE); - assert(key_size <= SERPENT_MAX_KEY_SIZE); +/* 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]; \ + } - for (i = 0; key_size >= 4; key_size -= 4, key += 4, i++) +/* 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) \ + { \ + block[0] = rol (block[0], 13); \ + block[2] = rol (block[2], 3); \ + block[1] = block[1] ^ block[0] ^ block[2]; \ + block[3] = block[3] ^ block[2] ^ (block[0] << 3); \ + block[1] = rol (block[1], 1); \ + block[3] = rol (block[3], 7); \ + block[0] = block[0] ^ block[1] ^ block[3]; \ + block[2] = block[2] ^ block[3] ^ (block[1] << 7); \ + block[0] = rol (block[0], 5); \ + block[2] = rol (block[2], 22); \ + } + +/* Apply the inverse linear transformation to BLOCK. */ +#define LINEAR_TRANSFORMATION_INVERSE(block) \ + { \ + block[2] = ror (block[2], 22); \ + block[0] = ror (block[0] , 5); \ + block[2] = block[2] ^ block[3] ^ (block[1] << 7); \ + block[0] = block[0] ^ block[1] ^ block[3]; \ + block[3] = ror (block[3], 7); \ + block[1] = ror (block[1], 1); \ + block[3] = block[3] ^ block[2] ^ (block[0] << 3); \ + block[1] = block[1] ^ block[0] ^ block[2]; \ + block[2] = ror (block[2], 3); \ + block[0] = ror (block[0], 13); \ + } + +/* Apply a Serpent round to BLOCK, using the SBOX number WHICH and the + subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage. + This macro increments `round'. */ +#define ROUND(which, subkeys, block, block_tmp) \ + { \ + BLOCK_XOR (block, subkeys[round]); \ + round++; \ + SBOX (which, block, block_tmp, 0); \ + LINEAR_TRANSFORMATION (block_tmp); \ + BLOCK_COPY (block, block_tmp); \ + } + +/* Apply the last Serpent round to BLOCK, using the SBOX number WHICH + 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) \ + { \ + BLOCK_XOR (block, subkeys[round]); \ + round++; \ + SBOX (which, block, block_tmp, 0); \ + BLOCK_XOR (block_tmp, subkeys[round]); \ + round++; \ + } + +/* Apply an inverse Serpent round to BLOCK, using the SBOX number + WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as + temporary storage. This macro increments `round'. */ +#define ROUND_INVERSE(which, subkey, block, block_tmp) \ + { \ + LINEAR_TRANSFORMATION_INVERSE (block); \ + SBOX_INVERSE (which, block, block_tmp, 0); \ + BLOCK_XOR (block_tmp, subkey[round]); \ + round--; \ + BLOCK_COPY (block, block_tmp); \ + } + +/* Apply the first Serpent round to BLOCK, using the SBOX number WHICH + 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_FIRST_INVERSE(which, subkeys, block, block_tmp) \ + { \ + BLOCK_XOR (block, subkeys[round]); \ + round--; \ + SBOX_INVERSE (which, block, block_tmp, 0); \ + BLOCK_XOR (block_tmp, subkeys[round]); \ + round--; \ + } + +/* Convert the user provided key KEY of KEY_LENGTH bytes into the + internally used format. */ +static void +serpent_key_prepare (const uint8_t * key, unsigned int key_length, + serpent_key_t key_prepared) +{ + unsigned int i; + + /* Copy key. */ + for (i = 0; i < key_length / 4; i++) { - assert(i < 8); - w[i] = LE_READ_UINT32 (key); +#ifdef WORDS_BIGENDIAN + key_prepared[i] = byte_swap_32 (((uint32_t *) key)[i]); +#else + key_prepared[i] = ((uint32_t *) key)[i]; +#endif } if (i < 8) { - /* Pad key, "aabbcc" -> "aabbcc0100...00" -> 0x01ccbbaa*/ - uint32_t partial = 0x01; - while (key_size > 0) - partial = (partial << 8 ) | key[--key_size]; - - w[i++] = partial; - while (i < 8) - w[i++] = 0; + /* Key must be padded according to the Serpent + specification. */ + key_prepared[i] = 0x00000001; + + for (i++; i < 8; i++) + key_prepared[i] = 0; } +} + +/* Derive the 33 subkeys from KEY and store them in SUBKEYS. */ +static void +serpent_subkeys_generate (serpent_key_t key, struct serpent_ctx *ctx) +{ + uint32_t w_real[140]; /* The `prekey'. */ + uint32_t k[132]; + uint32_t *w = &w_real[8]; + int i, j; + + /* Initialize with key values. */ + for (i = 0; i < 8; i++) + w[i - 8] = key[i]; + + /* Expand to intermediate key using the affine recurrence. */ + for (i = 0; i < 132; i++) + w[i] = rol (w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i, 11); - for(i=8; i<16; i++) - w[i]=ROL(w[i-8]^w[i-5]^w[i-3]^w[i-1]^PHI^(i-8),11); - for(i=0; i<8; i++) - w[i]=w[i+8]; - for(i=8; i<132; i++) - w[i]=ROL(w[i-8]^w[i-5]^w[i-3]^w[i-1]^PHI^i,11); - - RND03(w[ 0], w[ 1], w[ 2], w[ 3], k[ 0], k[ 1], k[ 2], k[ 3]); - RND02(w[ 4], w[ 5], w[ 6], w[ 7], k[ 4], k[ 5], k[ 6], k[ 7]); - RND01(w[ 8], w[ 9], w[ 10], w[ 11], k[ 8], k[ 9], k[ 10], k[ 11]); - RND00(w[ 12], w[ 13], w[ 14], w[ 15], k[ 12], k[ 13], k[ 14], k[ 15]); - RND31(w[ 16], w[ 17], w[ 18], w[ 19], k[ 16], k[ 17], k[ 18], k[ 19]); - RND30(w[ 20], w[ 21], w[ 22], w[ 23], k[ 20], k[ 21], k[ 22], k[ 23]); - RND29(w[ 24], w[ 25], w[ 26], w[ 27], k[ 24], k[ 25], k[ 26], k[ 27]); - RND28(w[ 28], w[ 29], w[ 30], w[ 31], k[ 28], k[ 29], k[ 30], k[ 31]); - RND27(w[ 32], w[ 33], w[ 34], w[ 35], k[ 32], k[ 33], k[ 34], k[ 35]); - RND26(w[ 36], w[ 37], w[ 38], w[ 39], k[ 36], k[ 37], k[ 38], k[ 39]); - RND25(w[ 40], w[ 41], w[ 42], w[ 43], k[ 40], k[ 41], k[ 42], k[ 43]); - RND24(w[ 44], w[ 45], w[ 46], w[ 47], k[ 44], k[ 45], k[ 46], k[ 47]); - RND23(w[ 48], w[ 49], w[ 50], w[ 51], k[ 48], k[ 49], k[ 50], k[ 51]); - RND22(w[ 52], w[ 53], w[ 54], w[ 55], k[ 52], k[ 53], k[ 54], k[ 55]); - RND21(w[ 56], w[ 57], w[ 58], w[ 59], k[ 56], k[ 57], k[ 58], k[ 59]); - RND20(w[ 60], w[ 61], w[ 62], w[ 63], k[ 60], k[ 61], k[ 62], k[ 63]); - RND19(w[ 64], w[ 65], w[ 66], w[ 67], k[ 64], k[ 65], k[ 66], k[ 67]); - RND18(w[ 68], w[ 69], w[ 70], w[ 71], k[ 68], k[ 69], k[ 70], k[ 71]); - RND17(w[ 72], w[ 73], w[ 74], w[ 75], k[ 72], k[ 73], k[ 74], k[ 75]); - RND16(w[ 76], w[ 77], w[ 78], w[ 79], k[ 76], k[ 77], k[ 78], k[ 79]); - RND15(w[ 80], w[ 81], w[ 82], w[ 83], k[ 80], k[ 81], k[ 82], k[ 83]); - RND14(w[ 84], w[ 85], w[ 86], w[ 87], k[ 84], k[ 85], k[ 86], k[ 87]); - RND13(w[ 88], w[ 89], w[ 90], w[ 91], k[ 88], k[ 89], k[ 90], k[ 91]); - RND12(w[ 92], w[ 93], w[ 94], w[ 95], k[ 92], k[ 93], k[ 94], k[ 95]); - RND11(w[ 96], w[ 97], w[ 98], w[ 99], k[ 96], k[ 97], k[ 98], k[ 99]); - RND10(w[100], w[101], w[102], w[103], k[100], k[101], k[102], k[103]); - RND09(w[104], w[105], w[106], w[107], k[104], k[105], k[106], k[107]); - RND08(w[108], w[109], w[110], w[111], k[108], k[109], k[110], k[111]); - RND07(w[112], w[113], w[114], w[115], k[112], k[113], k[114], k[115]); - RND06(w[116], w[117], w[118], w[119], k[116], k[117], k[118], k[119]); - RND05(w[120], w[121], w[122], w[123], k[120], k[121], k[122], k[123]); - RND04(w[124], w[125], w[126], w[127], k[124], k[125], k[126], k[127]); - RND03(w[128], w[129], w[130], w[131], k[128], k[129], k[130], k[131]); - - for(i=0; i<=32; i++) - for(j=0; j<4; j++) - ctx->keys[i][j] = k[4*i+j]; + /* Calculate subkeys via S-Boxes, in bitslice mode. */ + SBOX (3, w, k, 0); + SBOX (2, w, k, 4); + SBOX (1, w, k, 8); + SBOX (0, w, k, 12); + SBOX (7, w, k, 16); + SBOX (6, w, k, 20); + SBOX (5, w, k, 24); + SBOX (4, w, k, 28); + SBOX (3, w, k, 32); + SBOX (2, w, k, 36); + SBOX (1, w, k, 40); + SBOX (0, w, k, 44); + SBOX (7, w, k, 48); + SBOX (6, w, k, 52); + SBOX (5, w, k, 56); + SBOX (4, w, k, 60); + SBOX (3, w, k, 64); + SBOX (2, w, k, 68); + SBOX (1, w, k, 72); + SBOX (0, w, k, 76); + SBOX (7, w, k, 80); + SBOX (6, w, k, 84); + SBOX (5, w, k, 88); + SBOX (4, w, k, 92); + SBOX (3, w, k, 96); + SBOX (2, w, k, 100); + SBOX (1, w, k, 104); + SBOX (0, w, k, 108); + SBOX (7, w, k, 112); + SBOX (6, w, k, 116); + SBOX (5, w, k, 120); + SBOX (4, w, k, 124); + SBOX (3, w, k, 128); + + /* Renumber subkeys. */ + for (i = 0; i < ROUNDS + 1; i++) + for (j = 0; j < 4; j++) + ctx->keys[i][j] = k[4 * i + j]; } +/* Initialize CONTEXT with the key KEY of KEY_LENGTH bits. */ void -serpent_encrypt(const struct serpent_ctx *ctx, - unsigned length, uint8_t *dst, - const uint8_t *plain) +serpent_set_key (struct serpent_ctx *ctx, + unsigned length, const uint8_t * key) { - register uint32_t x0, x1, x2, x3; - register uint32_t y0, y1, y2, y3; + serpent_key_t key_prepared; - FOR_BLOCKS(length, dst, plain, SERPENT_BLOCK_SIZE) - { - x0 = LE_READ_UINT32(plain); - x1 = LE_READ_UINT32(plain + 4); - x2 = LE_READ_UINT32(plain + 8); - x3 = LE_READ_UINT32(plain + 12); - - /* Start to encrypt the plaintext x */ - keying(x0, x1, x2, x3, ctx->keys[ 0]); - RND00(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[ 1]); - RND01(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[ 2]); - RND02(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[ 3]); - RND03(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[ 4]); - RND04(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[ 5]); - RND05(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[ 6]); - RND06(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[ 7]); - RND07(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[ 8]); - RND08(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[ 9]); - RND09(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[10]); - RND10(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[11]); - RND11(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[12]); - RND12(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[13]); - RND13(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[14]); - RND14(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[15]); - RND15(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[16]); - RND16(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[17]); - RND17(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[18]); - RND18(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[19]); - RND19(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[20]); - RND20(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[21]); - RND21(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[22]); - RND22(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[23]); - RND23(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[24]); - RND24(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[25]); - RND25(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[26]); - RND26(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[27]); - RND27(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[28]); - RND28(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[29]); - RND29(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[30]); - RND30(x0, x1, x2, x3, y0, y1, y2, y3); - transform(y0, y1, y2, y3, x0, x1, x2, x3); - keying(x0, x1, x2, x3, ctx->keys[31]); - RND31(x0, x1, x2, x3, y0, y1, y2, y3); - x0 = y0; x1 = y1; x2 = y2; x3 = y3; - keying(x0, x1, x2, x3, ctx->keys[32]); - - /* The ciphertext is now in x */ - LE_WRITE_UINT32(dst, x0); - LE_WRITE_UINT32(dst+4, x1); - LE_WRITE_UINT32(dst+8, x2); - LE_WRITE_UINT32(dst+12, x3); - } + serpent_key_prepare (key, length, key_prepared); + serpent_subkeys_generate (key_prepared, ctx); } void -serpent_decrypt(const struct serpent_ctx *ctx, - unsigned length, uint8_t *dst, - const uint8_t *cipher) +serpent_encrypt (const struct serpent_ctx *ctx, + unsigned length, uint8_t * dst, const uint8_t * src) { - register uint32_t x0, x1, x2, x3; - register uint32_t y0, y1, y2, y3; + FOR_BLOCKS (length, dst, src, SERPENT_BLOCK_SIZE) + { + serpent_block_t b, b_next; + int round = 0; - FOR_BLOCKS(length, dst, cipher, SERPENT_BLOCK_SIZE) - { - x0 = LE_READ_UINT32(cipher); - x1 = LE_READ_UINT32(cipher + 4); - x2 = LE_READ_UINT32(cipher + 8); - x3 = LE_READ_UINT32(cipher + 12); - - /* Start to decrypt the ciphertext x */ - keying(x0, x1, x2, x3, ctx->keys[32]); - InvRND31(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[31]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND30(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[30]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND29(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[29]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND28(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[28]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND27(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[27]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND26(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[26]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND25(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[25]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND24(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[24]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND23(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[23]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND22(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[22]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND21(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[21]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND20(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[20]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND19(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[19]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND18(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[18]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND17(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[17]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND16(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[16]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND15(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[15]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND14(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[14]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND13(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[13]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND12(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[12]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND11(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[11]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND10(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[10]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND09(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[ 9]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND08(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[ 8]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND07(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[ 7]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND06(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[ 6]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND05(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[ 5]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND04(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[ 4]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND03(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[ 3]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND02(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[ 2]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND01(x0, x1, x2, x3, y0, y1, y2, y3); - keying(y0, y1, y2, y3, ctx->keys[ 1]); - inv_transform(y0, y1, y2, y3, x0, x1, x2, x3); - InvRND00(x0, x1, x2, x3, y0, y1, y2, y3); - x0 = y0; x1 = y1; x2 = y2; x3 = y3; - keying(x0, x1, x2, x3, ctx->keys[ 0]); - - /* The plaintext is now in x */ - LE_WRITE_UINT32(dst, x0); - LE_WRITE_UINT32(dst+4, x1); - LE_WRITE_UINT32(dst+8, x2); - LE_WRITE_UINT32(dst+12, x3); - } + b[0] = LE_READ_UINT32 (src); + b[1] = LE_READ_UINT32 (src + 4); + b[2] = LE_READ_UINT32 (src + 8); + b[3] = LE_READ_UINT32 (src + 12); + + 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 (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 (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 (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]); + } +} + +void +serpent_decrypt (const struct serpent_ctx *ctx, + unsigned length, uint8_t * dst, const uint8_t * src) +{ + FOR_BLOCKS (length, dst, src, SERPENT_BLOCK_SIZE) + { + serpent_block_t b, b_next; + int round = ROUNDS; + + b_next[0] = LE_READ_UINT32 (src); + b_next[1] = LE_READ_UINT32 (src + 4); + b_next[2] = LE_READ_UINT32 (src + 8); + b_next[3] = LE_READ_UINT32 (src + 12); + + ROUND_FIRST_INVERSE (7, ctx->keys, b_next, b); + + 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); + 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); + 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); + 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]); + } } diff --git a/serpent_sboxes.h b/serpent_sboxes.h deleted file mode 100644 index 0dc0787c..00000000 --- a/serpent_sboxes.h +++ /dev/null @@ -1,511 +0,0 @@ -/* serpentsboxes.h - * - * $Id$ - * - * For more details on this algorithm, see the Serpent website at - * http://www.cl.cam.ac.uk/~rja14/serpent.html - */ - -/* Copyright (C) 1998 Ross Anderson, Eli Biham, Lars Knudsen - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* I've modified this code a bit so that it interoperates with lsh - * properly. 2000-9-5, Rafael R. Sevilla - */ - -/* NOTE: The copyright notice for the original version of this code - * said "All rights reserved. This code is freely distributed for AES - * selection process. No other use is allowed." However, the authors - * later decided to GPL the code. /nisse */ - -#ifndef SERPENT_SBOXES_H_INCLUDED -#define SERPENT_SBOXES_H_INCLUDED - -#include "serpent.h" - -/* S0: 3 8 15 1 10 6 5 11 14 13 4 2 7 0 9 12 */ - -/* depth = 5,7,4,2, Total gates=18 */ -#define RND00(a,b,c,d,w,x,y,z) \ - { register uint32_t t02, t03, t05, t06, t07, t08, t09, 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; } - -/* InvS0: 13 3 11 0 10 6 5 12 1 14 4 7 15 9 8 2 */ - -/* depth = 8,4,3,6, Total gates=19 */ -#define InvRND00(a,b,c,d,w,x,y,z) \ - { register uint32_t t02, t03, t04, t05, t06, t08, t09, t10, t12, t13, t14, t15, t17, t18, t01;\ - t01 = c ^ d ; \ - t02 = a | b ; \ - t03 = b | c ; \ - t04 = c & t01; \ - t05 = t02 ^ t01; \ - t06 = a | t04; \ - y = ~ t05; \ - t08 = b ^ d ; \ - t09 = t03 & t08; \ - t10 = d | y ; \ - x = t09 ^ t06; \ - t12 = a | t05; \ - t13 = x ^ t12; \ - t14 = t03 ^ t10; \ - t15 = a ^ c ; \ - z = t14 ^ t13; \ - t17 = t05 & t13; \ - t18 = t14 | t17; \ - w = t15 ^ t18; } - -/* S1: 15 12 2 7 9 0 5 10 1 11 14 8 6 13 3 4 */ - -/* depth = 10,7,3,5, Total gates=18 */ -#define RND01(a,b,c,d,w,x,y,z) \ - { register uint32_t t02, t03, t04, t05, t06, t07, t08, 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; } - -/* InvS1: 5 8 2 14 15 6 12 3 11 4 7 9 1 13 10 0 */ - -/* depth = 7,4,5,3, Total gates=18 */ -#define InvRND01(a,b,c,d,w,x,y,z) \ - { register uint32_t t02, t03, t04, t05, t06, t07, t08, t09, t10, t11, t14, t15, t17, t01;\ - t01 = a ^ b ; \ - t02 = b | d ; \ - t03 = a & c ; \ - t04 = c ^ t02; \ - t05 = a | t04; \ - t06 = t01 & t05; \ - t07 = d | t03; \ - t08 = b ^ t06; \ - t09 = t07 ^ t06; \ - t10 = t04 | t03; \ - t11 = d & t08; \ - y = ~ t09; \ - x = t10 ^ t11; \ - t14 = a | y ; \ - t15 = t06 ^ x ; \ - z = t01 ^ t04; \ - t17 = c ^ t15; \ - w = t14 ^ t17; } - -/* S2: 8 6 7 9 3 12 10 15 13 1 14 4 0 11 5 2 */ - -/* depth = 3,8,11,7, Total gates=16 */ -#define RND02(a,b,c,d,w,x,y,z) \ - { register uint32_t t02, t03, t05, t06, t07, t08, 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; } - -/* InvS2: 12 9 15 4 11 14 1 2 0 3 6 13 5 8 10 7 */ - -/* depth = 3,6,8,3, Total gates=18 */ -#define InvRND02(a,b,c,d,w,x,y,z) \ - { register uint32_t t02, t03, t04, t06, t07, t08, t09, t10, t11, t12, t15, t16, t17, t01;\ - t01 = a ^ d ; \ - t02 = c ^ d ; \ - t03 = a & c ; \ - t04 = b | t02; \ - w = t01 ^ t04; \ - t06 = a | c ; \ - t07 = d | w ; \ - t08 = ~ d ; \ - t09 = b & t06; \ - t10 = t08 | t03; \ - t11 = b & t07; \ - t12 = t06 & t02; \ - z = t09 ^ t10; \ - x = t12 ^ t11; \ - t15 = c & z ; \ - t16 = w ^ x ; \ - t17 = t10 ^ t15; \ - y = t16 ^ t17; } - -/* S3: 0 15 11 8 12 9 6 3 13 1 2 4 10 7 5 14 */ - -/* depth = 8,3,5,5, Total gates=18 */ -#define RND03(a,b,c,d,w,x,y,z) \ - { register uint32_t t02, t03, t04, t05, t06, t07, t08, 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; } - -/* InvS3: 0 9 10 7 11 14 6 13 3 5 12 2 4 8 15 1 */ - -/* depth = 3,6,4,4, Total gates=17 */ -#define InvRND03(a,b,c,d,w,x,y,z) \ - { register uint32_t t02, t03, t04, t05, t06, t07, t09, t11, t12, t13, t14, t16, t01;\ - t01 = c | d ; \ - t02 = a | d ; \ - t03 = c ^ t02; \ - t04 = b ^ t02; \ - t05 = a ^ d ; \ - t06 = t04 & t03; \ - t07 = b & t01; \ - y = t05 ^ t06; \ - t09 = a ^ t03; \ - w = t07 ^ t03; \ - t11 = w | t05; \ - t12 = t09 & t11; \ - t13 = a & y ; \ - t14 = t01 ^ t05; \ - x = b ^ t12; \ - t16 = b | t13; \ - z = t14 ^ t16; } - -/* S4: 1 15 8 3 12 0 11 6 2 5 4 10 9 14 7 13 */ - -/* depth = 6,7,5,3, Total gates=19 */ -#define RND04(a,b,c,d,w,x,y,z) \ - { register uint32_t t02, t03, t04, t05, t06, t08, t09, 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; } - -/* InvS4: 5 0 8 3 10 9 7 14 2 12 11 6 4 15 13 1 */ - -/* depth = 6,4,7,3, Total gates=17 */ -#define InvRND04(a,b,c,d,w,x,y,z) \ - { register uint32_t t02, t03, t04, t05, t06, t07, t09, t10, t11, t12, t13, t15, t01;\ - t01 = b | d ; \ - t02 = c | d ; \ - t03 = a & t01; \ - t04 = b ^ t02; \ - t05 = c ^ d ; \ - t06 = ~ t03; \ - t07 = a & t04; \ - x = t05 ^ t07; \ - t09 = x | t06; \ - t10 = a ^ t07; \ - t11 = t01 ^ t09; \ - t12 = d ^ t04; \ - t13 = c | t10; \ - z = t03 ^ t12; \ - t15 = a ^ t04; \ - y = t11 ^ t13; \ - w = t15 ^ t09; } - -/* S5: 15 5 2 11 4 10 9 12 0 3 14 8 13 6 7 1 */ - -/* depth = 4,6,8,6, Total gates=17 */ -#define RND05(a,b,c,d,w,x,y,z) \ - { register uint32_t t02, t03, t04, t05, t07, t08, t09, 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; } - -/* InvS5: 8 15 2 9 4 1 13 14 11 6 5 3 7 12 10 0 */ - -/* depth = 4,6,9,7, Total gates=17 */ -#define InvRND05(a,b,c,d,w,x,y,z) \ - { register uint32_t t02, t03, t04, t05, t07, t08, t09, t10, t12, t13, t15, t16, t01;\ - t01 = a & d ; \ - t02 = c ^ t01; \ - t03 = a ^ d ; \ - t04 = b & t02; \ - t05 = a & c ; \ - w = t03 ^ t04; \ - t07 = a & w ; \ - t08 = t01 ^ w ; \ - t09 = b | t05; \ - t10 = ~ b ; \ - x = t08 ^ t09; \ - t12 = t10 | t07; \ - t13 = w | x ; \ - z = t02 ^ t12; \ - t15 = t02 ^ t13; \ - t16 = b ^ d ; \ - y = t16 ^ t15; } - -/* S6: 7 2 12 5 8 4 6 11 14 9 1 15 13 3 10 0 */ - -/* depth = 8,3,6,3, Total gates=19 */ -#define RND06(a,b,c,d,w,x,y,z) \ - { register uint32_t t02, t03, t04, t05, t07, t08, t09, t10, 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; } - -/* InvS6: 15 10 1 13 5 3 6 0 4 9 14 7 2 12 8 11 */ - -/* depth = 5,3,8,6, Total gates=19 */ -#define InvRND06(a,b,c,d,w,x,y,z) \ - { register uint32_t t02, t03, t04, t05, t06, t07, t08, t09, t12, t13, t14, t15, t16, t17, t01;\ - t01 = a ^ c ; \ - t02 = ~ c ; \ - t03 = b & t01; \ - t04 = b | t02; \ - t05 = d | t03; \ - t06 = b ^ d ; \ - t07 = a & t04; \ - t08 = a | t02; \ - t09 = t07 ^ t05; \ - x = t06 ^ t08; \ - w = ~ t09; \ - t12 = b & w ; \ - t13 = t01 & t05; \ - t14 = t01 ^ t12; \ - t15 = t07 ^ t13; \ - t16 = d | t02; \ - t17 = a ^ x ; \ - z = t17 ^ t15; \ - y = t16 ^ t14; } - -/* S7: 1 13 15 0 14 8 2 11 7 4 12 10 9 3 5 6 */ - -/* depth = 10,7,10,4, Total gates=19 */ -#define RND07(a,b,c,d,w,x,y,z) \ - { register uint32_t t02, t03, t04, t05, t06, t08, t09, t10, 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; } - -/* InvS7: 3 0 6 13 9 14 15 8 5 12 11 7 10 1 4 2 */ - -/* depth = 9,7,3,3, Total gates=18 */ -#define InvRND07(a,b,c,d,w,x,y,z) \ - { register uint32_t t02, t03, t04, t06, t07, t08, t09, t10, t11, t13, t14, t15, t16, t01;\ - t01 = a & b ; \ - t02 = a | b ; \ - t03 = c | t01; \ - t04 = d & t02; \ - z = t03 ^ t04; \ - t06 = b ^ t04; \ - t07 = d ^ z ; \ - t08 = ~ t07; \ - t09 = t06 | t08; \ - t10 = b ^ d ; \ - t11 = a | d ; \ - x = a ^ t09; \ - t13 = c ^ t06; \ - t14 = c & t11; \ - t15 = d | x ; \ - t16 = t01 | t10; \ - w = t13 ^ t15; \ - y = t14 ^ t16; } - -#define RND08(a,b,c,d,e,f,g,h) RND00(a,b,c,d,e,f,g,h) -#define RND09(a,b,c,d,e,f,g,h) RND01(a,b,c,d,e,f,g,h) -#define RND10(a,b,c,d,e,f,g,h) RND02(a,b,c,d,e,f,g,h) -#define RND11(a,b,c,d,e,f,g,h) RND03(a,b,c,d,e,f,g,h) -#define RND12(a,b,c,d,e,f,g,h) RND04(a,b,c,d,e,f,g,h) -#define RND13(a,b,c,d,e,f,g,h) RND05(a,b,c,d,e,f,g,h) -#define RND14(a,b,c,d,e,f,g,h) RND06(a,b,c,d,e,f,g,h) -#define RND15(a,b,c,d,e,f,g,h) RND07(a,b,c,d,e,f,g,h) -#define RND16(a,b,c,d,e,f,g,h) RND00(a,b,c,d,e,f,g,h) -#define RND17(a,b,c,d,e,f,g,h) RND01(a,b,c,d,e,f,g,h) -#define RND18(a,b,c,d,e,f,g,h) RND02(a,b,c,d,e,f,g,h) -#define RND19(a,b,c,d,e,f,g,h) RND03(a,b,c,d,e,f,g,h) -#define RND20(a,b,c,d,e,f,g,h) RND04(a,b,c,d,e,f,g,h) -#define RND21(a,b,c,d,e,f,g,h) RND05(a,b,c,d,e,f,g,h) -#define RND22(a,b,c,d,e,f,g,h) RND06(a,b,c,d,e,f,g,h) -#define RND23(a,b,c,d,e,f,g,h) RND07(a,b,c,d,e,f,g,h) -#define RND24(a,b,c,d,e,f,g,h) RND00(a,b,c,d,e,f,g,h) -#define RND25(a,b,c,d,e,f,g,h) RND01(a,b,c,d,e,f,g,h) -#define RND26(a,b,c,d,e,f,g,h) RND02(a,b,c,d,e,f,g,h) -#define RND27(a,b,c,d,e,f,g,h) RND03(a,b,c,d,e,f,g,h) -#define RND28(a,b,c,d,e,f,g,h) RND04(a,b,c,d,e,f,g,h) -#define RND29(a,b,c,d,e,f,g,h) RND05(a,b,c,d,e,f,g,h) -#define RND30(a,b,c,d,e,f,g,h) RND06(a,b,c,d,e,f,g,h) -#define RND31(a,b,c,d,e,f,g,h) RND07(a,b,c,d,e,f,g,h) - -#define InvRND08(a,b,c,d,e,f,g,h) InvRND00(a,b,c,d,e,f,g,h) -#define InvRND09(a,b,c,d,e,f,g,h) InvRND01(a,b,c,d,e,f,g,h) -#define InvRND10(a,b,c,d,e,f,g,h) InvRND02(a,b,c,d,e,f,g,h) -#define InvRND11(a,b,c,d,e,f,g,h) InvRND03(a,b,c,d,e,f,g,h) -#define InvRND12(a,b,c,d,e,f,g,h) InvRND04(a,b,c,d,e,f,g,h) -#define InvRND13(a,b,c,d,e,f,g,h) InvRND05(a,b,c,d,e,f,g,h) -#define InvRND14(a,b,c,d,e,f,g,h) InvRND06(a,b,c,d,e,f,g,h) -#define InvRND15(a,b,c,d,e,f,g,h) InvRND07(a,b,c,d,e,f,g,h) -#define InvRND16(a,b,c,d,e,f,g,h) InvRND00(a,b,c,d,e,f,g,h) -#define InvRND17(a,b,c,d,e,f,g,h) InvRND01(a,b,c,d,e,f,g,h) -#define InvRND18(a,b,c,d,e,f,g,h) InvRND02(a,b,c,d,e,f,g,h) -#define InvRND19(a,b,c,d,e,f,g,h) InvRND03(a,b,c,d,e,f,g,h) -#define InvRND20(a,b,c,d,e,f,g,h) InvRND04(a,b,c,d,e,f,g,h) -#define InvRND21(a,b,c,d,e,f,g,h) InvRND05(a,b,c,d,e,f,g,h) -#define InvRND22(a,b,c,d,e,f,g,h) InvRND06(a,b,c,d,e,f,g,h) -#define InvRND23(a,b,c,d,e,f,g,h) InvRND07(a,b,c,d,e,f,g,h) -#define InvRND24(a,b,c,d,e,f,g,h) InvRND00(a,b,c,d,e,f,g,h) -#define InvRND25(a,b,c,d,e,f,g,h) InvRND01(a,b,c,d,e,f,g,h) -#define InvRND26(a,b,c,d,e,f,g,h) InvRND02(a,b,c,d,e,f,g,h) -#define InvRND27(a,b,c,d,e,f,g,h) InvRND03(a,b,c,d,e,f,g,h) -#define InvRND28(a,b,c,d,e,f,g,h) InvRND04(a,b,c,d,e,f,g,h) -#define InvRND29(a,b,c,d,e,f,g,h) InvRND05(a,b,c,d,e,f,g,h) -#define InvRND30(a,b,c,d,e,f,g,h) InvRND06(a,b,c,d,e,f,g,h) -#define InvRND31(a,b,c,d,e,f,g,h) InvRND07(a,b,c,d,e,f,g,h) - -/* Linear transformations and key mixing: */ - -#define ROL(x,n) ((((uint32_t)(x))<<(n))| \ - (((uint32_t)(x))>>(32-(n)))) -#define ROR(x,n) ((((uint32_t)(x))<<(32-(n)))| \ - (((uint32_t)(x))>>(n))) - -#define transform(x0, x1, x2, x3, y0, y1, y2, y3) \ - y0 = ROL(x0, 13); \ - y2 = ROL(x2, 3); \ - y1 = x1 ^ y0 ^ y2; \ - y3 = x3 ^ y2 ^ ((uint32_t)y0)<<3; \ - y1 = ROL(y1, 1); \ - y3 = ROL(y3, 7); \ - y0 = y0 ^ y1 ^ y3; \ - y2 = y2 ^ y3 ^ ((uint32_t)y1<<7); \ - y0 = ROL(y0, 5); \ - y2 = ROL(y2, 22) - -#define inv_transform(x0, x1, x2, x3, y0, y1, y2, y3) \ - y2 = ROR(x2, 22);\ - y0 = ROR(x0, 5); \ - y2 = y2 ^ x3 ^ ((uint32_t)x1<<7); \ - y0 = y0 ^ x1 ^ x3; \ - y3 = ROR(x3, 7); \ - y1 = ROR(x1, 1); \ - y3 = y3 ^ y2 ^ ((uint32_t)y0)<<3; \ - y1 = y1 ^ y0 ^ y2; \ - y2 = ROR(y2, 3); \ - y0 = ROR(y0, 13) - -#define keying(x0, x1, x2, x3, subkey) \ - x0^=subkey[0];x1^=subkey[1]; \ - x2^=subkey[2];x3^=subkey[3] - -/* PHI: Constant used in the key schedule */ -#define PHI 0x9e3779b9L - -#endif /* SERPENT_SBOXES_H_INCLUDED */