diff --git a/include/serpent.h b/include/serpent.h index 0cf482a1543d2a5f781d65fd2307e41e7e8c13d2..94d98ed5b66a4594803d8f6a5af0202fd810d0f3 100644 --- a/include/serpent.h +++ b/include/serpent.h @@ -21,13 +21,18 @@ to using key lengths less than 256 bits. */ #define SERPENT_KEYSIZE 32 +/* Allow keys of size 128 <= bits <= 256 */ + +#define SERPENT_MIN_KEYSIZE 16 +#define SERPENT_MAX_KEYSIZE 32 + typedef struct { UINT32 keys[33][4]; /* key schedule */ } SERPENT_context; /* This performs Serpent's key scheduling algorithm. */ void -serpent_setup(SERPENT_context *ctx, const UINT8 *key); +serpent_setup(SERPENT_context *ctx, UINT32 key_size, const UINT8 *key); /* * serpent_encrypt() diff --git a/serpent.c b/serpent.c index 20112a928bcf760e9d731a7be24af535ff036273..32161aad73b7a69588efa7b492afac4693bc81bd 100644 --- a/serpent.c +++ b/serpent.c @@ -36,16 +36,37 @@ #include "serpent.h" #include "serpentsboxes.h" +#include <assert.h> + /* The functions */ void -serpent_setup(SERPENT_context *ctx, const UINT8 *key) +serpent_setup(SERPENT_context *ctx, UINT32 key_size, const UINT8 *key) { UINT32 i, j; UINT32 w[132], k[132]; UINT32 kd[8]; const UINT8 *kptr; - kptr = key; + assert(key_size >= SERPENT_MIN_KEYSIZE); + assert(key_size <= SERPENT_MAX_KEYSIZE); + + if (key_size == SERPENT_KEYSIZE) + kptr = key; + else + { + /* Expand key by appending bits 1000...0. */ + 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++) @@ -55,8 +76,11 @@ serpent_setup(SERPENT_context *ctx, const UINT8 *key) for(i=0; i<8; i++) w[i]=kd[i]; +#if 0 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); for(i=0; i<8; i++)