diff options
Diffstat (limited to 'cipher')
-rw-r--r-- | cipher/ChangeLog | 15 | ||||
-rw-r--r-- | cipher/blowfish.c | 37 | ||||
-rw-r--r-- | cipher/cast5.c | 38 | ||||
-rw-r--r-- | cipher/des.c | 23 | ||||
-rw-r--r-- | cipher/md5.c | 16 | ||||
-rw-r--r-- | cipher/random.c | 11 | ||||
-rw-r--r-- | cipher/rijndael.c | 44 | ||||
-rw-r--r-- | cipher/rmd160.c | 15 | ||||
-rw-r--r-- | cipher/sha1.c | 14 | ||||
-rw-r--r-- | cipher/tiger.c | 16 | ||||
-rw-r--r-- | cipher/twofish.c | 44 |
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. */ |