aboutsummaryrefslogtreecommitdiffstats
path: root/cipher
diff options
context:
space:
mode:
Diffstat (limited to 'cipher')
-rw-r--r--cipher/ChangeLog15
-rw-r--r--cipher/blowfish.c37
-rw-r--r--cipher/cast5.c38
-rw-r--r--cipher/des.c23
-rw-r--r--cipher/md5.c16
-rw-r--r--cipher/random.c11
-rw-r--r--cipher/rijndael.c44
-rw-r--r--cipher/rmd160.c15
-rw-r--r--cipher/sha1.c14
-rw-r--r--cipher/tiger.c16
-rw-r--r--cipher/twofish.c44
11 files changed, 255 insertions, 18 deletions
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index ede3b892b..7692ef62d 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,3 +1,18 @@
+2001-04-06 Werner Koch <[email protected]>
+
+ * rijndael.c, des.c, blowfish.c, twofish.c, cast5.c (burn_stack):
+ New. Add wrappers for most functions to be able to call
+ burn_stack after the function invocation. This methods seems to be
+ the most portable way to zeroise the stack used. It does only work
+ on stack frame based machines but it is highly portable and has no
+ side effects. Just setting the automatic variables at the end of
+ a function to zero does not work well because the compiler will
+ optimize them away - marking them as volatile woule be bad for
+ performance.
+ * md5.c, sha1.c, rmd160.c, tiger.c (burn_stack): Likewise.
+ * random.c (burn_stack): New.
+ (mix_pool): Use it here to burn the stack of te mixblock function.
+
2001-04-02 Werner Koch <[email protected]>
* primegen.c (generate_elg_prime): I was not initialized for mode
diff --git a/cipher/blowfish.c b/cipher/blowfish.c
index f58c70f44..0bf497e33 100644
--- a/cipher/blowfish.c
+++ b/cipher/blowfish.c
@@ -278,6 +278,17 @@ function_F( BLOWFISH_context *bc, u32 x )
#endif
#define R(l,r,i) do { l ^= p[i]; r ^= F(l); } while(0)
+static void
+burn_stack (int bytes)
+{
+ char buf[64];
+
+ memset (buf, 0, sizeof buf);
+ bytes -= sizeof buf;
+ if (bytes > 0)
+ burn_stack (bytes);
+}
+
static void
do_encrypt( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
@@ -413,7 +424,7 @@ decrypt( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
#undef R
static void
-encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
+do_encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
{
u32 d1, d2;
@@ -430,9 +441,15 @@ encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
outbuf[7] = d2 & 0xff;
}
+static void
+encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
+{
+ do_encrypt_block (bc, outbuf, inbuf);
+ burn_stack (64);
+}
static void
-decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
+do_decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
{
u32 d1, d2;
@@ -449,6 +466,13 @@ decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
outbuf[7] = d2 & 0xff;
}
+static void
+decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
+{
+ do_decrypt_block (bc, outbuf, inbuf);
+ burn_stack (64);
+}
+
static const char*
selftest(void)
@@ -481,7 +505,7 @@ selftest(void)
static int
-bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
+do_bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
{
int i, j;
u32 data, datal, datar;
@@ -563,6 +587,13 @@ bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
return 0;
}
+static int
+bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
+{
+ int rc = do_bf_setkey (c, key, keylen);
+ burn_stack (64);
+ return rc;
+}
/****************
* Return some information about the algorithm. We need algo here to
diff --git a/cipher/cast5.c b/cipher/cast5.c
index 329f00ff7..8f9658362 100644
--- a/cipher/cast5.c
+++ b/cipher/cast5.c
@@ -355,7 +355,19 @@ rol(int n, u32 x)
(((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) )
static void
-encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
+burn_stack (int bytes)
+{
+ char buf[64];
+
+ memset (buf, 0, sizeof buf);
+ bytes -= sizeof buf;
+ if (bytes > 0)
+ burn_stack (bytes);
+}
+
+
+static void
+do_encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
{
u32 l, r, t;
u32 I; /* used by the Fx macros */
@@ -409,7 +421,14 @@ encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
}
static void
-decrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
+encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
+{
+ do_encrypt_block (c, outbuf, inbuf);
+ burn_stack (20+4*sizeof(void*));
+}
+
+static void
+do_decrypt_block (CAST5_context *c, byte *outbuf, byte *inbuf )
{
u32 l, r, t;
u32 I;
@@ -449,6 +468,12 @@ decrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
outbuf[7] = l & 0xff;
}
+static void
+decrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
+{
+ do_decrypt_block (c, outbuf, inbuf);
+ burn_stack (20+4*sizeof(void*));
+}
static const char*
@@ -547,7 +572,7 @@ key_schedule( u32 *x, u32 *z, u32 *k )
static int
-cast_setkey( CAST5_context *c, byte *key, unsigned keylen )
+do_cast_setkey( CAST5_context *c, byte *key, unsigned keylen )
{
static int initialized;
static const char* selftest_failed;
@@ -589,6 +614,13 @@ cast_setkey( CAST5_context *c, byte *key, unsigned keylen )
return 0;
}
+static int
+cast_setkey( CAST5_context *c, byte *key, unsigned keylen )
+{
+ int rc = do_cast_setkey (c, key, keylen);
+ burn_stack (96+7*sizeof(void*));
+ return rc;
+}
/****************
* Return some information about the algorithm. We need algo here to
diff --git a/cipher/des.c b/cipher/des.c
index 847a3473e..ce436d847 100644
--- a/cipher/des.c
+++ b/cipher/des.c
@@ -449,9 +449,16 @@ static byte weak_keys[64][8] =
#define tripledes_ecb_decrypt(ctx, from, to) tripledes_ecb_crypt(ctx, from, to, 1)
-
-
-
+static void
+burn_stack (int bytes)
+{
+ char buf[64];
+
+ memset (buf, 0, sizeof buf);
+ bytes -= sizeof buf;
+ if (bytes > 0)
+ burn_stack (bytes);
+}
/*
* des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for
@@ -558,6 +565,7 @@ des_setkey (struct _des_ctx *ctx, const byte * key)
return G10ERR_SELFTEST_FAILED;
des_key_schedule (key, ctx->encrypt_subkeys);
+ burn_stack (32);
for(i=0; i<32; i+=2)
{
@@ -616,6 +624,7 @@ tripledes_set2keys (struct _tripledes_ctx *ctx,
des_key_schedule (key1, ctx->encrypt_subkeys);
des_key_schedule (key2, &(ctx->decrypt_subkeys[32]));
+ burn_stack (32);
for(i=0; i<32; i+=2)
{
@@ -653,6 +662,7 @@ tripledes_set3keys (struct _tripledes_ctx *ctx,
des_key_schedule (key1, ctx->encrypt_subkeys);
des_key_schedule (key2, &(ctx->decrypt_subkeys[32]));
des_key_schedule (key3, &(ctx->encrypt_subkeys[64]));
+ burn_stack (32);
for(i=0; i<32; i+=2)
{
@@ -947,8 +957,11 @@ do_tripledes_setkey ( struct _tripledes_ctx *ctx, byte *key, unsigned keylen )
tripledes_set3keys ( ctx, key, key+8, key+16);
- if( is_weak_key( key ) || is_weak_key( key+8 ) || is_weak_key( key+16 ) )
+ if( is_weak_key( key ) || is_weak_key( key+8 ) || is_weak_key( key+16 ) ) {
+ burn_stack (64);
return G10ERR_WEAK_KEY;
+ }
+ burn_stack (64);
return 0;
}
@@ -958,12 +971,14 @@ static void
do_tripledes_encrypt( struct _tripledes_ctx *ctx, byte *outbuf, byte *inbuf )
{
tripledes_ecb_encrypt ( ctx, inbuf, outbuf );
+ burn_stack (32);
}
static void
do_tripledes_decrypt( struct _tripledes_ctx *ctx, byte *outbuf, byte *inbuf )
{
tripledes_ecb_decrypt ( ctx, inbuf, outbuf );
+ burn_stack (32);
}
diff --git a/cipher/md5.c b/cipher/md5.c
index 9bba57641..cf8861d10 100644
--- a/cipher/md5.c
+++ b/cipher/md5.c
@@ -72,6 +72,18 @@ md5_init( MD5_CONTEXT *ctx )
#define FH(b, c, d) (b ^ c ^ d)
#define FI(b, c, d) (c ^ (b | ~d))
+static void
+burn_stack (int bytes)
+{
+ char buf[128];
+
+ memset (buf, 0, sizeof buf);
+ bytes -= sizeof buf;
+ if (bytes > 0)
+ burn_stack (bytes);
+}
+
+
/****************
* transform n*64 bytes
@@ -217,6 +229,7 @@ md5_write( MD5_CONTEXT *hd, byte *inbuf, size_t inlen)
{
if( hd->count == 64 ) { /* flush the buffer */
transform( hd, hd->buf );
+ burn_stack (80+6*sizeof(void*));
hd->count = 0;
hd->nblocks++;
}
@@ -237,9 +250,9 @@ md5_write( MD5_CONTEXT *hd, byte *inbuf, size_t inlen)
inlen -= 64;
inbuf += 64;
}
+ burn_stack (80+6*sizeof(void*));
for( ; inlen && hd->count < 64; inlen-- )
hd->buf[hd->count++] = *inbuf++;
-
}
@@ -294,6 +307,7 @@ md5_final( MD5_CONTEXT *hd )
hd->buf[62] = msb >> 16;
hd->buf[63] = msb >> 24;
transform( hd, hd->buf );
+ burn_stack (80+6*sizeof(void*));
p = hd->buf;
#ifdef BIG_ENDIAN_HOST
diff --git a/cipher/random.c b/cipher/random.c
index de4bcf6c1..03a54e580 100644
--- a/cipher/random.c
+++ b/cipher/random.c
@@ -139,6 +139,16 @@ initialize(void)
cipher_modules_constructor();
}
+static void
+burn_stack (int bytes)
+{
+ char buf[128];
+
+ memset (buf, 0, sizeof buf);
+ bytes -= sizeof buf;
+ if (bytes > 0)
+ burn_stack (bytes);
+}
void
random_dump_stats()
@@ -269,6 +279,7 @@ mix_pool(byte *pool)
rmd160_mixblock( &md, hashbuf);
memcpy(p, hashbuf, 20 );
}
+ burn_stack (200); /* for the rmd160_mixblock() */
}
diff --git a/cipher/rijndael.c b/cipher/rijndael.c
index 0284989c3..3eac290c1 100644
--- a/cipher/rijndael.c
+++ b/cipher/rijndael.c
@@ -1707,10 +1707,23 @@ static const u32 rcon[30] = {
};
+
+static void
+burn_stack (int bytes)
+{
+ char buf[64];
+
+ memset (buf, 0, sizeof buf);
+ bytes -= sizeof buf;
+ if (bytes > 0)
+ burn_stack (bytes);
+}
+
+
/* Perform the key setup.
*/
static int
-rijndael_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
+do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
{
static int initialized = 0;
static const char *selftest_failed=0;
@@ -1719,6 +1732,7 @@ rijndael_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
int i,j, r, t, rconpointer = 0;
byte tk[MAXKC][4];
int KC;
+ /* space for automatic variables is about 64 + 11*int */
if (!initialized) {
initialized = 1;
@@ -1809,6 +1823,14 @@ rijndael_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
return 0;
}
+static int
+rijndael_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
+{
+ int rc = do_setkey (ctx, key, keylen);
+ burn_stack ( 100 + 16*sizeof(int));
+ return rc;
+}
+
/* make a decryption key from an encryption key */
static void
prepare_decryption( RIJNDAEL_context *ctx )
@@ -1847,7 +1869,7 @@ prepare_decryption( RIJNDAEL_context *ctx )
/* Encrypt one block. A and B may be the same. */
static void
-rijndael_encrypt (const RIJNDAEL_context *ctx, byte *b, const byte *a)
+do_encrypt (const RIJNDAEL_context *ctx, byte *b, const byte *a)
{
int r;
byte temp[4][4];
@@ -1924,10 +1946,18 @@ rijndael_encrypt (const RIJNDAEL_context *ctx, byte *b, const byte *a)
*((u32*)(b+12)) ^= *((u32*)rk[ROUNDS][3]);
#undef rk
}
+
+static void
+rijndael_encrypt (const RIJNDAEL_context *ctx, byte *b, const byte *a)
+{
+ do_encrypt (ctx, b, a);
+ burn_stack (16 + 2*sizeof(int));
+}
+
/* Decrypt one block. a and b may be the same. */
static void
-rijndael_decrypt (RIJNDAEL_context *ctx, byte *b, const byte *a)
+do_decrypt (RIJNDAEL_context *ctx, byte *b, const byte *a)
{
#define rk (ctx->keySched2)
int ROUNDS = ctx->ROUNDS;
@@ -1936,6 +1966,7 @@ rijndael_decrypt (RIJNDAEL_context *ctx, byte *b, const byte *a)
if ( !ctx->decryption_prepared ) {
prepare_decryption ( ctx );
+ burn_stack (64);
ctx->decryption_prepared = 1;
}
@@ -2009,6 +2040,13 @@ rijndael_decrypt (RIJNDAEL_context *ctx, byte *b, const byte *a)
*((u32*)(b+12)) ^= *((u32*)rk[0][3]);
#undef rk
}
+
+static void
+rijndael_decrypt (RIJNDAEL_context *ctx, byte *b, const byte *a)
+{
+ do_decrypt (ctx, b, a);
+ burn_stack (16+2*sizeof(int));
+}
/* Test a single encryption and decryption with each key size. */
diff --git a/cipher/rmd160.c b/cipher/rmd160.c
index 94e3ece0b..9f5ab852c 100644
--- a/cipher/rmd160.c
+++ b/cipher/rmd160.c
@@ -141,6 +141,18 @@
* 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528
*/
+static void
+burn_stack (int bytes)
+{
+ char buf[150];
+
+ memset (buf, 0, sizeof buf);
+ bytes -= sizeof buf;
+ if (bytes > 0)
+ burn_stack (bytes);
+}
+
+
void
rmd160_init( RMD160_CONTEXT *hd )
@@ -405,6 +417,7 @@ rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen)
{
if( hd->count == 64 ) { /* flush the buffer */
transform( hd, hd->buf );
+ burn_stack (108+5*sizeof(void*));
hd->count = 0;
hd->nblocks++;
}
@@ -425,6 +438,7 @@ rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen)
inlen -= 64;
inbuf += 64;
}
+ burn_stack (108+5*sizeof(void*));
for( ; inlen && hd->count < 64; inlen-- )
hd->buf[hd->count++] = *inbuf++;
}
@@ -497,6 +511,7 @@ rmd160_final( RMD160_CONTEXT *hd )
hd->buf[62] = msb >> 16;
hd->buf[63] = msb >> 24;
transform( hd, hd->buf );
+ burn_stack (108+5*sizeof(void*));
p = hd->buf;
#ifdef BIG_ENDIAN_HOST
diff --git a/cipher/sha1.c b/cipher/sha1.c
index 9160bc260..0f8f17ce2 100644
--- a/cipher/sha1.c
+++ b/cipher/sha1.c
@@ -49,7 +49,16 @@ typedef struct {
int count;
} SHA1_CONTEXT;
-
+static void
+burn_stack (int bytes)
+{
+ char buf[128];
+
+ memset (buf, 0, sizeof buf);
+ bytes -= sizeof buf;
+ if (bytes > 0)
+ burn_stack (bytes);
+}
void
@@ -214,6 +223,7 @@ sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen)
{
if( hd->count == 64 ) { /* flush the buffer */
transform( hd, hd->buf );
+ burn_stack (88+4*sizeof(void*));
hd->count = 0;
hd->nblocks++;
}
@@ -234,6 +244,7 @@ sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen)
inlen -= 64;
inbuf += 64;
}
+ burn_stack (88+4*sizeof(void*));
for( ; inlen && hd->count < 64; inlen-- )
hd->buf[hd->count++] = *inbuf++;
}
@@ -290,6 +301,7 @@ sha1_final(SHA1_CONTEXT *hd)
hd->buf[62] = lsb >> 8;
hd->buf[63] = lsb ;
transform( hd, hd->buf );
+ burn_stack (88+4*sizeof(void*));
p = hd->buf;
#ifdef BIG_ENDIAN_HOST
diff --git a/cipher/tiger.c b/cipher/tiger.c
index adc23c85c..76fcbbdac 100644
--- a/cipher/tiger.c
+++ b/cipher/tiger.c
@@ -631,6 +631,19 @@ print_data( const char *text, u64 a, u64 b, u64 c,
static void
+burn_stack (int bytes)
+{
+ char buf[256];
+
+ memset (buf, 0, sizeof buf);
+ bytes -= sizeof buf;
+ if (bytes > 0)
+ burn_stack (bytes);
+}
+
+
+
+static void
tiger_init( TIGER_CONTEXT *hd )
{
hd->a = 0x0123456789abcdefLL;
@@ -768,6 +781,7 @@ tiger_write( TIGER_CONTEXT *hd, byte *inbuf, size_t inlen)
{
if( hd->count == 64 ) { /* flush the buffer */
transform( hd, hd->buf );
+ burn_stack (21*8+11*sizeof(void*));
hd->count = 0;
hd->nblocks++;
}
@@ -788,6 +802,7 @@ tiger_write( TIGER_CONTEXT *hd, byte *inbuf, size_t inlen)
inlen -= 64;
inbuf += 64;
}
+ burn_stack (21*8+11*sizeof(void*));
for( ; inlen && hd->count < 64; inlen-- )
hd->buf[hd->count++] = *inbuf++;
}
@@ -841,6 +856,7 @@ tiger_final( TIGER_CONTEXT *hd )
hd->buf[62] = msb >> 16;
hd->buf[63] = msb >> 24;
transform( hd, hd->buf );
+ burn_stack (21*8+11*sizeof(void*));
p = hd->buf;
#ifdef BIG_ENDIAN_HOST
diff --git a/cipher/twofish.c b/cipher/twofish.c
index e5a66520c..3cd59da61 100644
--- a/cipher/twofish.c
+++ b/cipher/twofish.c
@@ -545,11 +545,25 @@ static byte calc_sb_tbl[512] = {
x += y; y += x; ctx->a[j] = x; \
ctx->a[(j) + 1] = (y << 9) + (y >> 23)
+
+static void
+burn_stack (int bytes)
+{
+ char buf[64];
+
+ memset (buf, 0, sizeof buf);
+ bytes -= sizeof buf;
+ if (bytes > 0)
+ burn_stack (bytes);
+}
+
+
+
/* Perform the key setup. Note that this works only with 128- and 256-bit
* keys, despite the API that looks like it might support other sizes. */
static int
-twofish_setkey (TWOFISH_context *ctx, const byte *key, const unsigned keylen)
+do_twofish_setkey (TWOFISH_context *ctx, const byte *key, unsigned int keylen)
{
int i, j, k;
@@ -682,6 +696,16 @@ twofish_setkey (TWOFISH_context *ctx, const byte *key, const unsigned keylen)
return 0;
}
+
+static int
+twofish_setkey (TWOFISH_context *ctx, const byte *key, unsigned int keylen)
+{
+ int rc = do_twofish_setkey (ctx, key, keylen);
+ burn_stack (23+6*sizeof(void*));
+ return rc;
+}
+
+
/* Macros to compute the g() function in the encryption and decryption
* rounds. G1 is the straight g() function; G2 includes the 8-bit
@@ -744,7 +768,7 @@ twofish_setkey (TWOFISH_context *ctx, const byte *key, const unsigned keylen)
/* Encrypt one block. in and out may be the same. */
static void
-twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
+do_twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
{
/* The four 32-bit chunks of the text. */
u32 a, b, c, d;
@@ -774,11 +798,18 @@ twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
OUTUNPACK (2, a, 6);
OUTUNPACK (3, b, 7);
}
+
+static void
+twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
+{
+ do_twofish_encrypt (ctx, out, in);
+ burn_stack (24+3*sizeof (void*));
+}
/* Decrypt one block. in and out may be the same. */
static void
-twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
+do_twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
{
/* The four 32-bit chunks of the text. */
u32 a, b, c, d;
@@ -808,6 +839,13 @@ twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
OUTUNPACK (2, c, 2);
OUTUNPACK (3, d, 3);
}
+
+static void
+twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
+{
+ do_twofish_decrypt (ctx, out, in);
+ burn_stack (24+3*sizeof (void*));
+}
/* Test a single encryption and decryption with each key size. */