diff --git a/Makefile.am b/Makefile.am index 6d074c868ae931aaf87792ced42e414fc0982284..b8700a5af4cdfd828738eb472cae6fdc5a92f2d4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,7 +8,8 @@ lib_LIBRARIES = libnettle.a libnettleinclude_HEADERS = aes.h arcfour.h des.h md5.h sha1.h libnettle_a_SOURCES = aes.c aes.h arcfour.c arcfour.h des.c des.h \ - md5.c md5.h sha1.c sha1.h + md5.c md5.h sha1.c sha1.h \ + serpent.c serpent.h serpent_sboxes.h libnettle_a_LIBADD = @LIBOBJS@ diff --git a/serpent.c b/serpent.c index 88b7025beeda3e759e9b3d7d819a4f358c6601b5..b198955afd1af5cfeac9e838b36acdeb75b99ef0 100644 --- a/serpent.c +++ b/serpent.c @@ -1,12 +1,15 @@ -/* serpent.c +/* serpent.h * - * $Id$ + * The serpent block cipher. * * 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 +/* nettle, low-level cryptographics library + * + * Copyright (C) 1998, 2000, 2001, 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 @@ -32,23 +35,23 @@ * selection process. No other use is allowed." However, the authors * later decided to GPL the code. /nisse */ +/* FIXME: Use the READ_UINT32 and WRITE_UINT32 macros, where + * applicable. */ #include "serpent.h" #include "serpentsboxes.h" #include <assert.h> -/* The functions */ void -serpent_setup(SERPENT_context *ctx, UINT32 key_size, const UINT8 *key) +serpent_set_key(struct serpent_ctx *ctx, + unsigned length, const uint8_t *key) { unsigned i, j; - UINT32 w[132], k[132]; - /* UINT32 kd[8]; */ - /* const UINT8 *kptr; */ + uint32_t w[132], k[132]; - assert(key_size >= SERPENT_MIN_KEYSIZE); - assert(key_size <= SERPENT_MAX_KEYSIZE); + assert(key_size >= SERPENT_MIN_KEY_SIZE); + assert(key_size <= SERPENT_MAX_KEY_SIZE); for (i = key_size, j = 0; (i >= 4); @@ -69,36 +72,6 @@ serpent_setup(SERPENT_context *ctx, UINT32 key_size, const UINT8 *key) while (j < 8) w[j++] = 0; } -#if 0 - if (key_size == SERPENT_KEYSIZE) - kptr = key; - else - { - /* Expand key by appending bits 1000...00. */ - UINT8 *ekey = alloca(SERPENT_KEYSIZE); - unsigned i = key_size; - - memcpy(ekey, key, i); - ekey[i++] = 0x01; - - while (i < SERPENT_KEYSIZE) - ekey[i++] = 0; - - kptr = ekey; - } - - for (i=0; i<8; i++) { - kd[i] = 0; - for (j=0; j<4; j++) - kd[i] |= (*kptr++) << j*8; - } - - for(i=0; i<8; i++) - w[i]=kd[i]; - - for(i++; i<8; i++) - w[i]=0; -#endif 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); @@ -147,255 +120,265 @@ serpent_setup(SERPENT_context *ctx, UINT32 key_size, const UINT8 *key) } void -serpent_encrypt(SERPENT_context *ctx, - const UINT8 *plaintext, - UINT8 *ciphertext) +serpent_encrypt(struct aes_ctx *ctx, + unsigned length, uint8_t *dst, + const uint8_t *plain) { - register UINT32 x0, x1, x2, x3; - register UINT32 y0, y1, y2, y3; + register uint32_t x0, x1, x2, x3; + register uint32_t y0, y1, y2, y3; int i; - UINT8 *cptr; - x0=plaintext[0]|(plaintext[1]<<8)|(plaintext[2]<<16)|(plaintext[3]<<24); - x1=plaintext[4]|(plaintext[5]<<8)|(plaintext[6]<<16)|(plaintext[7]<<24); - x2=plaintext[8]|(plaintext[9]<<8)|(plaintext[10]<<16)|(plaintext[11]<<24); - x3=plaintext[12]|(plaintext[13]<<8)|(plaintext[14]<<16)|(plaintext[15]<<24); + assert (!(length % SERPENT_BLOCKSIZE)); + + for (; length; + length -= SERPENT_BLOCKSIZE, + plain += SERPENT_BLOCKSIZE, + dst += SERPENT_BLOCKSIZE) + { + x0=plain[0]|(plain[1]<<8)|(plain[2]<<16)|(plain[3]<<24); + x1=plain[4]|(plain[5]<<8)|(plain[6]<<16)|(plain[7]<<24); + x2=plain[8]|(plain[9]<<8)|(plain[10]<<16)|(plain[11]<<24); + x3=plain[12]|(plain[13]<<8)|(plain[14]<<16)|(plain[15]<<24); - /* 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 */ + /* 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]); - cptr = ciphertext; + /* The ciphertext is now in x */ - for (i=0; i<4; i++) - *cptr++ = (x0 >> i*8) & 0xff; - for (i=0; i<4; i++) - *cptr++ = (x1 >> i*8) & 0xff; - for (i=0; i<4; i++) - *cptr++ = (x2 >> i*8) & 0xff; - for (i=0; i<4; i++) - *cptr++ = (x3 >> i*8) & 0xff; + for (i=0; i<4; i++) + *dst++ = (x0 >> i*8) & 0xff; + for (i=0; i<4; i++) + *dst++ = (x1 >> i*8) & 0xff; + for (i=0; i<4; i++) + *dst++ = (x2 >> i*8) & 0xff; + for (i=0; i<4; i++) + *dst++ = (x3 >> i*8) & 0xff; + } } void -serpent_decrypt(SERPENT_context *ctx, - const UINT8 *ciphertext, - UINT8 *plaintext) +serpent_decrypt(struct aes_ctx *ctx, + unsigned length, uint8_t *dst, + const uint8_t *cipher); { - register UINT32 x0, x1, x2, x3; - register UINT32 y0, y1, y2, y3; + register uint32_t x0, x1, x2, x3; + register uint32_t y0, y1, y2, y3; int i; - UINT8 *pptr; - x0=ciphertext[0]|(ciphertext[1]<<8)|(ciphertext[2]<<16)|(ciphertext[3]<<24); - x1=ciphertext[4]|(ciphertext[5]<<8)|(ciphertext[6]<<16)|(ciphertext[7]<<24); - x2=ciphertext[8]|(ciphertext[9]<<8)|(ciphertext[10]<<16)|(ciphertext[11]<<24); - x3=ciphertext[12]|(ciphertext[13]<<8)|(ciphertext[14]<<16)|(ciphertext[15]<<24); + for (; length; + length -= SERPENT_BLOCKSIZE, + plain += SERPENT_BLOCKSIZE, + dst += SERPENT_BLOCKSIZE) + { + x0=cipher[0]|(cipher[1]<<8)|(cipher[2]<<16)|(cipher[3]<<24); + x1=cipher[4]|(cipher[5]<<8)|(cipher[6]<<16)|(cipher[7]<<24); + x2=cipher[8]|(cipher[9]<<8)|(cipher[10]<<16)|(cipher[11]<<24); + x3=cipher[12]|(cipher[13]<<8)|(cipher[14]<<16)|(cipher[15]<<24); - /* 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 */ + /* 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]); - pptr = plaintext; + /* The plaintext is now in x */ - for (i=0; i<4; i++) - *pptr++ = (x0 >> i*8) & 0xff; - for (i=0; i<4; i++) - *pptr++ = (x1 >> i*8) & 0xff; - for (i=0; i<4; i++) - *pptr++ = (x2 >> i*8) & 0xff; - for (i=0; i<4; i++) - *pptr++ = (x3 >> i*8) & 0xff; + for (i=0; i<4; i++) + *dst++ = (x0 >> i*8) & 0xff; + for (i=0; i<4; i++) + *dst++ = (x1 >> i*8) & 0xff; + for (i=0; i<4; i++) + *dst++ = (x2 >> i*8) & 0xff; + for (i=0; i<4; i++) + *dst++ = (x3 >> i*8) & 0xff; + } } diff --git a/serpent.h b/serpent.h new file mode 100644 index 0000000000000000000000000000000000000000..981f7f3ad847d7dba867c6f865f58d525f676ba9 --- /dev/null +++ b/serpent.h @@ -0,0 +1,68 @@ +/* serpent.h + * + * The serpent block cipher. + */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2001 Niels M�ller + * + * 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 GNU MP 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 GNU MP 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. + */ + +/* Serpent is a 128-bit block cipher that accepts a key size of 256 + * bits, designed by Ross Anderson, Eli Biham, and Lars Knudsen. See + * http://www.cl.cam.ac.uk/~rja14/serpent.html for details. + */ + +#ifndef NETTLE_SERPENT_H_INCLUDED +#define NETTLE_SERPENT_H_INCLUDED + +#include <stdint.h> + +#define SERPENT_BLOCKSIZE 16 + +/* Other key lengths are possible, but we only use 256 bits. Besides, the + design of Serpent makes other key lengths useless; they cheated with the + AES requirements, using a 256-bit key length exclusively and just padding + it out if the desired key length was less, so there really is no advantage + to using key lengths less than 256 bits. */ +#define SERPENT_KEYSIZE 32 + +/* Allow keys of size 128 <= bits <= 256 */ + +#define SERPENT_MIN_KEY_SIZE 16 +#define SERPENT_MAX_KEY_SIZE 32 + +struct serpent_ctx +{ + uint32_t keys[33][4]; /* key schedule */ +}; + +void +serpent_set_key(struct serpent_ctx *ctx, + unsigned length, const uint8_t *key); + +void +serpent_encrypt(struct aes_ctx *ctx, + unsigned length, uint8_t *dst, + const uint8_t *src); +void +serpent_decrypt(struct aes_ctx *ctx, + unsigned length, uint8_t *dst, + const uint8_t *src); + +#endif /* NETTLE_SERPENT_H_INCLUDED */ diff --git a/serpent_sboxes.h b/serpent_sboxes.h new file mode 100644 index 0000000000000000000000000000000000000000..0dc0787ce5d8298c9cc95859e4d50b83ba920c84 --- /dev/null +++ b/serpent_sboxes.h @@ -0,0 +1,511 @@ +/* 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 <dido@pacific.net.ph> + */ + +/* 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 */