[PATCH 1/2] Move stack burning from block ciphers to cipher modes

Jussi Kivilinna jussi.kivilinna at iki.fi
Tue Sep 3 19:18:24 CEST 2013


* src/gcrypt-module.h (gcry_cipher_encrypt_t)
(gcry_cipher_decrypt_t): Return 'unsigned int'.
* cipher/cipher.c (dummy_encrypt_block, dummy_decrypt_block): Return
zero.
(do_ecb_encrypt, do_ecb_decrypt): Get largest stack burn depth from
block cipher crypt function and burn stack at end.
* cipher/cipher-aeswrap.c (_gcry_cipher_aeswrap_encrypt)
(_gcry_cipher_aeswrap_decrypt): Ditto.
* cipher/cipher-cbc.c (_gcry_cipher_cbc_encrypt)
(_gcry_cipher_cbc_decrypt): Ditto.
* cipher/cipher-cfb.c (_gcry_cipher_cfb_encrypt)
(_gcry_cipher_cfb_decrypt): Ditto.
* cipher/cipher-ctr.c (_gcry_cipher_cbc_encrypt): Ditto.
* cipher/cipher-ofb.c (_gcry_cipher_ofb_encrypt)
(_gcry_cipher_ofb_decrypt): Ditto.
* cipher/blowfish.c (encrypt_block, decrypt_block): Return burn stack
depth.
* cipher/camellia-glue.c (camellia_encrypt, camellia_decrypt): Ditto.
* cipher/cast5.c (encrypt_block, decrypt_block): Ditto.
* cipher/des.c (do_tripledes_encrypt, do_tripledes_decrypt)
(do_des_encrypt, do_des_decrypt): Ditto.
* cipher/idea.c (idea_encrypt, idea_decrypt): Ditto.
* cipher/rijndael.c (rijndael_encrypt, rijndael_decrypt): Ditto.
* cipher/seed.c (seed_encrypt, seed_decrypt): Ditto.
* cipher/serpent.c (serpent_encrypt, serpent_decrypt): Ditto.
* cipher/twofish.c (twofish_encrypt, twofish_decrypt): Ditto.
* cipher/rfc2268.c (encrypt_block, decrypt_block): New.
(_gcry_cipher_spec_rfc2268_40): Use encrypt_block and decrypt_block.
--

Patch moves stack burning from block ciphers and cipher mode loop to end of
cipher mode functions. This greatly reduces the overall CPU usage of the
problematic _gcry_burn_stack. Internal cipher module API is changed so
that encrypt/decrypt functions now return the stack burn depth as unsigned
int to cipher mode function.

(Note, patch also adds missing burn_stack for RFC2268_40 cipher).

_gcry_burn_stack CPU time (looping tests/benchmark cipher blowfish):

arch	CPU		Old	New
i386	Intel-Haswell	4.1%	0.16%
x86_64	Intel-Haswell	3.4%	0.07%
armhf	Cortex-A8	8.7%	0.14%

New vs. old (armhf/Cortex-A8):
                ECB/Stream         CBC             CFB             OFB             CTR
             --------------- --------------- --------------- --------------- ---------------
IDEA          1.05x   1.05x   1.04x   1.04x   1.04x   1.04x   1.07x   1.05x   1.04x   1.04x
3DES          1.04x   1.03x   1.04x   1.03x   1.04x   1.04x   1.04x   1.04x   1.04x   1.04x
CAST5         1.19x   1.20x   1.15x   1.00x   1.17x   1.00x   1.15x   1.05x   1.00x   1.00x
BLOWFISH      1.21x   1.22x   1.16x   1.00x   1.18x   1.00x   1.16x   1.16x   1.00x   1.00x
AES           1.09x   1.09x   1.00x   1.00x   1.00x   1.00x   1.07x   1.07x   1.00x   1.00x
AES192        1.11x   1.11x   1.00x   1.00x   1.00x   1.00x   1.08x   1.09x   1.01x   1.00x
AES256        1.07x   1.08x   1.01x   .99x    1.00x   1.00x   1.07x   1.06x   1.00x   1.00x
TWOFISH       1.10x   1.09x   1.09x   1.00x   1.09x   1.00x   1.08x   1.09x   1.00x   1.00x
ARCFOUR       1.00x   1.00x
DES           1.07x   1.11x   1.06x   1.08x   1.07x   1.07x   1.06x   1.06x   1.06x   1.06x
TWOFISH128    1.10x   1.10x   1.09x   1.00x   1.09x   1.00x   1.08x   1.08x   1.00x   1.00x
SERPENT128    1.06x   1.07x   1.02x   1.00x   1.06x   1.00x   1.06x   1.05x   1.00x   1.00x
SERPENT192    1.07x   1.06x   1.03x   1.00x   1.06x   1.00x   1.06x   1.05x   1.00x   1.00x
SERPENT256    1.06x   1.07x   1.02x   1.00x   1.06x   1.00x   1.05x   1.06x   1.00x   1.00x
RFC2268_40    0.97x   1.01x   0.99x   0.98x   1.00x   0.97x   0.96x   0.96x   0.97x   0.97x
SEED          1.45x   1.54x   1.53x   1.56x   1.50x   1.51x   1.50x   1.50x   1.42x   1.42x
CAMELLIA128   1.08x   1.07x   1.06x   1.00x   1.07x   1.00x   1.06x   1.06x   1.00x   1.00x
CAMELLIA192   1.08x   1.08x   1.08x   1.00x   1.07x   1.00x   1.07x   1.07x   1.00x   1.00x
CAMELLIA256   1.08x   1.09x   1.07x   1.01x   1.08x   1.00x   1.07x   1.07x   1.00x   1.00x
SALSA20 .99x  1.00x

Raw data:

New (armhf/Cortex-A8):
Running each test 100 times.
                ECB/Stream         CBC             CFB             OFB             CTR
             --------------- --------------- --------------- --------------- ---------------
IDEA          8620ms  8680ms  9640ms 10010ms  9140ms  8960ms  9630ms  9660ms  9180ms  9180ms
3DES         13990ms 14000ms 14780ms 15300ms 14320ms 14370ms 14780ms 14780ms 14480ms 14480ms
CAST5         2980ms  2980ms  3780ms  2300ms  3290ms  2320ms  3770ms  4100ms  2320ms  2320ms
BLOWFISH      2740ms  2660ms  3530ms  2060ms  3050ms  2080ms  3530ms  3530ms  2070ms  2070ms
AES           2200ms  2330ms  2330ms  2450ms  2270ms  2270ms  2700ms  2690ms  2330ms  2320ms
AES192        2550ms  2670ms  2700ms  2910ms  2630ms  2640ms  3060ms  3060ms  2680ms  2690ms
AES256        2920ms  3010ms  3040ms  3190ms  3010ms  3000ms  3380ms  3420ms  3050ms  3050ms
TWOFISH       2790ms  2840ms  3300ms  2950ms  3010ms  2870ms  3310ms  3280ms  2940ms  2940ms
ARCFOUR       2050ms  2050ms
DES           5640ms  5630ms  6440ms  6970ms  5960ms  6000ms  6440ms  6440ms  6120ms  6120ms
TWOFISH128    2790ms  2840ms  3300ms  2950ms  3010ms  2890ms  3310ms  3290ms  2930ms  2930ms
SERPENT128    4530ms  4340ms  5210ms  4470ms  4740ms  4620ms  5020ms  5030ms  4680ms  4680ms
SERPENT192    4510ms  4340ms  5190ms  4460ms  4750ms  4620ms  5020ms  5030ms  4680ms  4680ms
SERPENT256    4540ms  4330ms  5220ms  4460ms  4730ms  4600ms  5030ms  5020ms  4680ms  4680ms
RFC2268_40   10530ms  7790ms 11140ms  9490ms 10650ms 10710ms 11710ms 11690ms 11000ms 11000ms
SEED          4530ms  4540ms  5050ms  5380ms  4760ms  4810ms  5060ms  5060ms  4850ms  4860ms
CAMELLIA128   2660ms  2630ms  3170ms  2750ms  2880ms  2740ms  3170ms  3170ms  2780ms  2780ms
CAMELLIA192   3430ms  3400ms  3930ms  3530ms  3650ms  3500ms  3940ms  3940ms  3570ms  3560ms
CAMELLIA256   3430ms  3390ms  3940ms  3500ms  3650ms  3510ms  3930ms  3940ms  3550ms  3550ms
SALSA20       1910ms  1900ms

Old (armhf/Cortex-A8):
Running each test 100 times.
                ECB/Stream         CBC             CFB             OFB             CTR
             --------------- --------------- --------------- --------------- ---------------
IDEA          9030ms  9100ms 10050ms 10410ms  9540ms  9360ms 10350ms 10190ms  9560ms  9570ms
3DES         14580ms 14460ms 15300ms 15720ms 14880ms 14900ms 15350ms 15330ms 15030ms 15020ms
CAST5         3560ms  3570ms  4350ms  2300ms  3860ms  2330ms  4340ms  4320ms  2330ms  2320ms
BLOWFISH      3320ms  3250ms  4110ms  2060ms  3610ms  2080ms  4100ms  4090ms  2070ms  2070ms
AES           2390ms  2530ms  2320ms  2460ms  2280ms  2270ms  2890ms  2880ms  2330ms  2330ms
AES192        2830ms  2970ms  2690ms  2900ms  2630ms  2650ms  3320ms  3330ms  2700ms  2690ms
AES256        3110ms  3250ms  3060ms  3170ms  3000ms  3000ms  3610ms  3610ms  3050ms  3060ms
TWOFISH       3080ms  3100ms  3600ms  2940ms  3290ms  2880ms  3560ms  3570ms  2940ms  2930ms
ARCFOUR       2060ms  2050ms
DES           6060ms  6230ms  6850ms  7540ms  6380ms  6400ms  6830ms  6840ms  6500ms  6510ms
TWOFISH128    3060ms  3110ms  3600ms  2940ms  3290ms  2890ms  3560ms  3560ms  2940ms  2930ms
SERPENT128    4820ms  4630ms  5330ms  4460ms  5030ms  4620ms  5300ms  5300ms  4680ms  4680ms
SERPENT192    4830ms  4620ms  5320ms  4460ms  5040ms  4620ms  5300ms  5300ms  4680ms  4680ms
SERPENT256    4820ms  4640ms  5330ms  4460ms  5030ms  4620ms  5300ms  5300ms  4680ms  4660ms
RFC2268_40   10260ms  7850ms 11080ms  9270ms 10620ms 10380ms 11250ms 11230ms 10690ms 10710ms
SEED          6580ms  6990ms  7710ms  8370ms  7140ms  7240ms  7600ms  7610ms  6870ms  6900ms
CAMELLIA128   2860ms  2820ms  3360ms  2750ms  3080ms  2740ms  3350ms  3360ms  2790ms  2790ms
CAMELLIA192   3710ms  3680ms  4240ms  3520ms  3910ms  3510ms  4200ms  4210ms  3560ms  3560ms
CAMELLIA256   3700ms  3680ms  4230ms  3520ms  3930ms  3510ms  4200ms  4210ms  3550ms  3560ms
SALSA20       1900ms  1900ms

Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
 cipher/blowfish.c       |   32 ++++++++++++++++++--------------
 cipher/camellia-glue.c  |   16 ++++++++--------
 cipher/cast5.c          |   32 ++++++++++++++++++--------------
 cipher/cipher-aeswrap.c |   19 +++++++++++++++++--
 cipher/cipher-cbc.c     |   27 ++++++++++++++++++++++-----
 cipher/cipher-cfb.c     |   32 ++++++++++++++++++++++++++------
 cipher/cipher-ctr.c     |   10 ++++++++--
 cipher/cipher-ofb.c     |   26 ++++++++++++++++++++++----
 cipher/cipher.c         |   24 ++++++++++++++++++++----
 cipher/des.c            |   16 ++++++++--------
 cipher/idea.c           |    8 ++++----
 cipher/rfc2268.c        |   16 +++++++++++++++-
 cipher/rijndael.c       |   20 ++++++++++++++------
 cipher/seed.c           |    8 ++++----
 cipher/serpent.c        |    8 ++++----
 cipher/twofish.c        |   16 ++++++++--------
 src/gcrypt-module.h     |   12 ++++++------
 17 files changed, 222 insertions(+), 100 deletions(-)

diff --git a/cipher/blowfish.c b/cipher/blowfish.c
index 2806433..80e1ec7 100644
--- a/cipher/blowfish.c
+++ b/cipher/blowfish.c
@@ -67,8 +67,8 @@ typedef struct {
 } BLOWFISH_context;
 
 static gcry_err_code_t bf_setkey (void *c, const byte *key, unsigned keylen);
-static void encrypt_block (void *bc, byte *outbuf, const byte *inbuf);
-static void decrypt_block (void *bc, byte *outbuf, const byte *inbuf);
+static unsigned int encrypt_block (void *bc, byte *outbuf, const byte *inbuf);
+static unsigned int decrypt_block (void *bc, byte *outbuf, const byte *inbuf);
 
 
 /* precomputed S boxes */
@@ -298,18 +298,20 @@ do_decrypt_block (BLOWFISH_context *context, byte *outbuf, const byte *inbuf)
   _gcry_blowfish_amd64_decrypt_block (context, outbuf, inbuf);
 }
 
-static void encrypt_block (void *context , byte *outbuf, const byte *inbuf)
+static unsigned int
+encrypt_block (void *context , byte *outbuf, const byte *inbuf)
 {
   BLOWFISH_context *c = (BLOWFISH_context *) context;
   do_encrypt_block (c, outbuf, inbuf);
-  _gcry_burn_stack (2*8);
+  return /*burn_stack*/ (2*8);
 }
 
-static void decrypt_block (void *context, byte *outbuf, const byte *inbuf)
+static unsigned int
+decrypt_block (void *context, byte *outbuf, const byte *inbuf)
 {
   BLOWFISH_context *c = (BLOWFISH_context *) context;
   do_decrypt_block (c, outbuf, inbuf);
-  _gcry_burn_stack (2*8);
+  return /*burn_stack*/ (2*8);
 }
 
 #elif defined(USE_ARMV6_ASM)
@@ -352,18 +354,20 @@ do_decrypt_block (BLOWFISH_context *context, byte *outbuf, const byte *inbuf)
   _gcry_blowfish_armv6_decrypt_block (context, outbuf, inbuf);
 }
 
-static void encrypt_block (void *context , byte *outbuf, const byte *inbuf)
+static unsigned int
+encrypt_block (void *context , byte *outbuf, const byte *inbuf)
 {
   BLOWFISH_context *c = (BLOWFISH_context *) context;
   do_encrypt_block (c, outbuf, inbuf);
-  _gcry_burn_stack (10*4);
+  return /*burn_stack*/ (10*4);
 }
 
-static void decrypt_block (void *context, byte *outbuf, const byte *inbuf)
+static unsigned int
+decrypt_block (void *context, byte *outbuf, const byte *inbuf)
 {
   BLOWFISH_context *c = (BLOWFISH_context *) context;
   do_decrypt_block (c, outbuf, inbuf);
-  _gcry_burn_stack (10*4);
+  return /*burn_stack*/ (10*4);
 }
 
 #else /*USE_ARMV6_ASM*/
@@ -553,12 +557,12 @@ do_encrypt_block ( BLOWFISH_context *bc, byte *outbuf, const byte *inbuf )
   outbuf[7] =  d2	   & 0xff;
 }
 
-static void
+static unsigned int
 encrypt_block (void *context, byte *outbuf, const byte *inbuf)
 {
   BLOWFISH_context *bc = (BLOWFISH_context *) context;
   do_encrypt_block (bc, outbuf, inbuf);
-  _gcry_burn_stack (64);
+  return /*burn_stack*/ (64);
 }
 
 
@@ -580,12 +584,12 @@ do_decrypt_block (BLOWFISH_context *bc, byte *outbuf, const byte *inbuf)
   outbuf[7] =  d2	   & 0xff;
 }
 
-static void
+static unsigned int
 decrypt_block (void *context, byte *outbuf, const byte *inbuf)
 {
   BLOWFISH_context *bc = (BLOWFISH_context *) context;
   do_decrypt_block (bc, outbuf, inbuf);
-  _gcry_burn_stack (64);
+  return /*burn_stack*/ (64);
 }
 
 #endif /*!USE_AMD64_ASM&&!USE_ARMV6_ASM*/
diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c
index 6e2319d..ad57cf5 100644
--- a/cipher/camellia-glue.c
+++ b/cipher/camellia-glue.c
@@ -222,27 +222,27 @@ static void Camellia_DecryptBlock(const int keyBitLength,
 				     keyBitLength);
 }
 
-static void
+static unsigned int
 camellia_encrypt(void *c, byte *outbuf, const byte *inbuf)
 {
   CAMELLIA_context *ctx = c;
   Camellia_EncryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf);
 #define CAMELLIA_encrypt_stack_burn_size (15*4)
-  _gcry_burn_stack(CAMELLIA_encrypt_stack_burn_size);
+  return /*burn_stack*/ (CAMELLIA_encrypt_stack_burn_size);
 }
 
-static void
+static unsigned int
 camellia_decrypt(void *c, byte *outbuf, const byte *inbuf)
 {
   CAMELLIA_context *ctx=c;
   Camellia_DecryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf);
 #define CAMELLIA_decrypt_stack_burn_size (15*4)
-  _gcry_burn_stack(CAMELLIA_decrypt_stack_burn_size);
+  return /*burn_stack*/ (CAMELLIA_decrypt_stack_burn_size);
 }
 
 #else /*USE_ARMV6_ASM*/
 
-static void
+static unsigned int
 camellia_encrypt(void *c, byte *outbuf, const byte *inbuf)
 {
   CAMELLIA_context *ctx=c;
@@ -256,10 +256,10 @@ camellia_encrypt(void *c, byte *outbuf, const byte *inbuf)
      +2*2*sizeof(void*) /* Function calls.  */ \
     )
 
-  _gcry_burn_stack(CAMELLIA_encrypt_stack_burn_size);
+  return /*burn_stack*/ (CAMELLIA_encrypt_stack_burn_size);
 }
 
-static void
+static unsigned int
 camellia_decrypt(void *c, byte *outbuf, const byte *inbuf)
 {
   CAMELLIA_context *ctx=c;
@@ -273,7 +273,7 @@ camellia_decrypt(void *c, byte *outbuf, const byte *inbuf)
      +2*2*sizeof(void*) /* Function calls.  */ \
     )
 
-  _gcry_burn_stack(CAMELLIA_decrypt_stack_burn_size);
+  return /*burn_stack*/ (CAMELLIA_decrypt_stack_burn_size);
 }
 
 #endif /*!USE_ARMV6_ASM*/
diff --git a/cipher/cast5.c b/cipher/cast5.c
index 4377c28..0cd5953 100644
--- a/cipher/cast5.c
+++ b/cipher/cast5.c
@@ -71,8 +71,8 @@ typedef struct {
 } CAST5_context;
 
 static gcry_err_code_t cast_setkey (void *c, const byte *key, unsigned keylen);
-static void encrypt_block (void *c, byte *outbuf, const byte *inbuf);
-static void decrypt_block (void *c, byte *outbuf, const byte *inbuf);
+static unsigned int encrypt_block (void *c, byte *outbuf, const byte *inbuf);
+static unsigned int decrypt_block (void *c, byte *outbuf, const byte *inbuf);
 
 
 
@@ -383,18 +383,20 @@ do_decrypt_block (CAST5_context *context, byte *outbuf, const byte *inbuf)
   _gcry_cast5_amd64_decrypt_block (context, outbuf, inbuf);
 }
 
-static void encrypt_block (void *context , byte *outbuf, const byte *inbuf)
+static unsigned int
+encrypt_block (void *context , byte *outbuf, const byte *inbuf)
 {
   CAST5_context *c = (CAST5_context *) context;
   do_encrypt_block (c, outbuf, inbuf);
-  _gcry_burn_stack (2*8);
+  return /*burn_stack*/ (2*8);
 }
 
-static void decrypt_block (void *context, byte *outbuf, const byte *inbuf)
+static unsigned int
+decrypt_block (void *context, byte *outbuf, const byte *inbuf)
 {
   CAST5_context *c = (CAST5_context *) context;
   _gcry_cast5_amd64_decrypt_block (c, outbuf, inbuf);
-  _gcry_burn_stack (2*8);
+  return /*burn_stack*/ (2*8);
 }
 
 #elif defined(USE_ARMV6_ASM)
@@ -428,18 +430,20 @@ do_decrypt_block (CAST5_context *context, byte *outbuf, const byte *inbuf)
   _gcry_cast5_armv6_decrypt_block (context, outbuf, inbuf);
 }
 
-static void encrypt_block (void *context , byte *outbuf, const byte *inbuf)
+static unsigned int
+encrypt_block (void *context , byte *outbuf, const byte *inbuf)
 {
   CAST5_context *c = (CAST5_context *) context;
   do_encrypt_block (c, outbuf, inbuf);
-  _gcry_burn_stack (10*4);
+  return /*burn_stack*/ (10*4);
 }
 
-static void decrypt_block (void *context, byte *outbuf, const byte *inbuf)
+static unsigned int
+decrypt_block (void *context, byte *outbuf, const byte *inbuf)
 {
   CAST5_context *c = (CAST5_context *) context;
   do_decrypt_block (c, outbuf, inbuf);
-  _gcry_burn_stack (10*4);
+  return /*burn_stack*/ (10*4);
 }
 
 #else /*USE_ARMV6_ASM*/
@@ -519,12 +523,12 @@ do_encrypt_block( CAST5_context *c, byte *outbuf, const byte *inbuf )
     outbuf[7] =  l	  & 0xff;
 }
 
-static void
+static unsigned int
 encrypt_block (void *context , byte *outbuf, const byte *inbuf)
 {
   CAST5_context *c = (CAST5_context *) context;
   do_encrypt_block (c, outbuf, inbuf);
-  _gcry_burn_stack (20+4*sizeof(void*));
+  return /*burn_stack*/ (20+4*sizeof(void*));
 }
 
 
@@ -569,12 +573,12 @@ do_decrypt_block (CAST5_context *c, byte *outbuf, const byte *inbuf )
     outbuf[7] =  l	  & 0xff;
 }
 
-static void
+static unsigned int
 decrypt_block (void *context, byte *outbuf, const byte *inbuf)
 {
   CAST5_context *c = (CAST5_context *) context;
   do_decrypt_block (c, outbuf, inbuf);
-  _gcry_burn_stack (20+4*sizeof(void*));
+  return /*burn_stack*/ (20+4*sizeof(void*));
 }
 
 #endif /*!USE_ARMV6_ASM*/
diff --git a/cipher/cipher-aeswrap.c b/cipher/cipher-aeswrap.c
index 8e117eb..931dec1 100644
--- a/cipher/cipher-aeswrap.c
+++ b/cipher/cipher-aeswrap.c
@@ -42,6 +42,7 @@ _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c,
   unsigned int n, i;
   unsigned char *r, *a, *b;
   unsigned char t[8];
+  unsigned int burn, nburn;
 
 #if MAX_BLOCKSIZE < 8
 #error Invalid block size
@@ -64,6 +65,8 @@ _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c,
   if (n < 2)
     return GPG_ERR_INV_ARG;
 
+  burn = 0;
+
   r = outbuf;
   a = outbuf;  /* We store A directly in OUTBUF.  */
   b = c->u_ctr.ctr;  /* B is also used to concatenate stuff.  */
@@ -87,7 +90,8 @@ _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c,
           /* B := AES_k( A | R[i] ) */
           memcpy (b, a, 8);
           memcpy (b+8, r+i*8, 8);
-          c->cipher->encrypt (&c->context.c, b, b);
+          nburn = c->cipher->encrypt (&c->context.c, b, b);
+          burn = nburn > burn ? nburn : burn;
           /* t := t + 1  */
 	  for (x = 7; x >= 0; x--)
 	    {
@@ -102,6 +106,9 @@ _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c,
         }
    }
 
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4 * sizeof(void *));
+
   return 0;
 }
 
@@ -117,6 +124,7 @@ _gcry_cipher_aeswrap_decrypt (gcry_cipher_hd_t c,
   unsigned int n, i;
   unsigned char *r, *a, *b;
   unsigned char t[8];
+  unsigned int burn, nburn;
 
 #if MAX_BLOCKSIZE < 8
 #error Invalid block size
@@ -140,6 +148,8 @@ _gcry_cipher_aeswrap_decrypt (gcry_cipher_hd_t c,
   if (n < 3)
     return GPG_ERR_INV_ARG;
 
+  burn = 0;
+
   r = outbuf;
   a = c->lastiv;  /* We use c->LASTIV as buffer for A.  */
   b = c->u_ctr.ctr;     /* B is also used to concatenate stuff.  */
@@ -163,7 +173,8 @@ _gcry_cipher_aeswrap_decrypt (gcry_cipher_hd_t c,
           /* B := AES_k^1( (A ^ t)| R[i] ) */
 	  buf_xor(b, a, t, 8);
           memcpy (b+8, r+(i-1)*8, 8);
-          c->cipher->decrypt (&c->context.c, b, b);
+          nburn = c->cipher->decrypt (&c->context.c, b, b);
+          burn = nburn > burn ? nburn : burn;
           /* t := t - 1  */
 	  for (x = 7; x >= 0; x--)
 	    {
@@ -191,5 +202,9 @@ _gcry_cipher_aeswrap_decrypt (gcry_cipher_hd_t c,
             break;
           }
     }
+
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4 * sizeof(void *));
+
   return j? GPG_ERR_CHECKSUM : 0;
 }
diff --git a/cipher/cipher-cbc.c b/cipher/cipher-cbc.c
index 0d30f63..55a1c74 100644
--- a/cipher/cipher-cbc.c
+++ b/cipher/cipher-cbc.c
@@ -42,6 +42,7 @@ _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c,
   int i;
   size_t blocksize = c->cipher->blocksize;
   unsigned nblocks = inbuflen / blocksize;
+  unsigned int burn, nburn;
 
   if (outbuflen < ((c->flags & GCRY_CIPHER_CBC_MAC)? blocksize : inbuflen))
     return GPG_ERR_BUFFER_TOO_SHORT;
@@ -51,6 +52,8 @@ _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c,
            && (c->flags & GCRY_CIPHER_CBC_CTS)))
     return GPG_ERR_INV_LENGTH;
 
+  burn = 0;
+
   if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
     {
       if ((inbuflen % blocksize) == 0)
@@ -70,7 +73,8 @@ _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c,
       for (n=0; n < nblocks; n++ )
         {
           buf_xor(outbuf, inbuf, c->u_iv.iv, blocksize);
-          c->cipher->encrypt ( &c->context.c, outbuf, outbuf );
+          nburn = c->cipher->encrypt ( &c->context.c, outbuf, outbuf );
+          burn = nburn > burn ? nburn : burn;
           memcpy (c->u_iv.iv, outbuf, blocksize );
           inbuf  += blocksize;
           if (!(c->flags & GCRY_CIPHER_CBC_MAC))
@@ -100,10 +104,14 @@ _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c,
       for (; i < blocksize; i++)
         outbuf[i] = 0 ^ *ivp++;
 
-      c->cipher->encrypt (&c->context.c, outbuf, outbuf);
+      nburn = c->cipher->encrypt (&c->context.c, outbuf, outbuf);
+      burn = nburn > burn ? nburn : burn;
       memcpy (c->u_iv.iv, outbuf, blocksize);
     }
 
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4 * sizeof(void *));
+
   return 0;
 }
 
@@ -117,6 +125,7 @@ _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c,
   int i;
   size_t blocksize = c->cipher->blocksize;
   unsigned int nblocks = inbuflen / blocksize;
+  unsigned int burn, nburn;
 
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
@@ -126,6 +135,8 @@ _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c,
            && (c->flags & GCRY_CIPHER_CBC_CTS)))
     return GPG_ERR_INV_LENGTH;
 
+  burn = 0;
+
   if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
     {
       nblocks--;
@@ -148,7 +159,8 @@ _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c,
            * save the original ciphertext block.  We use LASTIV for
            * this here because it is not used otherwise. */
           memcpy (c->lastiv, inbuf, blocksize);
-          c->cipher->decrypt ( &c->context.c, outbuf, inbuf );
+          nburn = c->cipher->decrypt ( &c->context.c, outbuf, inbuf );
+          burn = nburn > burn ? nburn : burn;
           buf_xor(outbuf, outbuf, c->u_iv.iv, blocksize);
           memcpy(c->u_iv.iv, c->lastiv, blocksize );
           inbuf  += c->cipher->blocksize;
@@ -168,16 +180,21 @@ _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c,
       memcpy (c->lastiv, c->u_iv.iv, blocksize );         /* Save Cn-2. */
       memcpy (c->u_iv.iv, inbuf + blocksize, restbytes ); /* Save Cn. */
 
-      c->cipher->decrypt ( &c->context.c, outbuf, inbuf );
+      nburn = c->cipher->decrypt ( &c->context.c, outbuf, inbuf );
+      burn = nburn > burn ? nburn : burn;
       buf_xor(outbuf, outbuf, c->u_iv.iv, restbytes);
 
       memcpy(outbuf + blocksize, outbuf, restbytes);
       for(i=restbytes; i < blocksize; i++)
         c->u_iv.iv[i] = outbuf[i];
-      c->cipher->decrypt (&c->context.c, outbuf, c->u_iv.iv);
+      nburn = c->cipher->decrypt (&c->context.c, outbuf, c->u_iv.iv);
+      burn = nburn > burn ? nburn : burn;
       buf_xor(outbuf, outbuf, c->lastiv, blocksize);
       /* c->lastiv is now really lastlastiv, does this matter? */
     }
 
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4 * sizeof(void *));
+
   return 0;
 }
diff --git a/cipher/cipher-cfb.c b/cipher/cipher-cfb.c
index ed84b75..f772280 100644
--- a/cipher/cipher-cfb.c
+++ b/cipher/cipher-cfb.c
@@ -39,6 +39,7 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c,
   unsigned char *ivp;
   size_t blocksize = c->cipher->blocksize;
   size_t blocksize_x_2 = blocksize + blocksize;
+  unsigned int burn, nburn;
 
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
@@ -53,6 +54,8 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c,
       return 0;
     }
 
+  burn = 0;
+
   if ( c->unused )
     {
       /* XOR the input with the IV and store input into IV */
@@ -80,7 +83,8 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c,
       while ( inbuflen >= blocksize_x_2 )
         {
           /* Encrypt the IV. */
-          c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+          nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+          burn = nburn > burn ? nburn : burn;
           /* XOR the input with the IV and store input into IV.  */
           buf_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize);
           outbuf += blocksize;
@@ -93,7 +97,8 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c,
     {
       /* Save the current IV and then encrypt the IV. */
       memcpy( c->lastiv, c->u_iv.iv, blocksize );
-      c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      burn = nburn > burn ? nburn : burn;
       /* XOR the input with the IV and store input into IV */
       buf_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize);
       outbuf += blocksize;
@@ -104,7 +109,8 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c,
     {
       /* Save the current IV and then encrypt the IV. */
       memcpy( c->lastiv, c->u_iv.iv, blocksize );
-      c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      burn = nburn > burn ? nburn : burn;
       c->unused = blocksize;
       /* Apply the XOR. */
       c->unused -= inbuflen;
@@ -113,6 +119,10 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c,
       inbuf += inbuflen;
       inbuflen = 0;
     }
+
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4 * sizeof(void *));
+
   return 0;
 }
 
@@ -125,6 +135,7 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,
   unsigned char *ivp;
   size_t blocksize = c->cipher->blocksize;
   size_t blocksize_x_2 = blocksize + blocksize;
+  unsigned int burn, nburn;
 
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
@@ -139,6 +150,8 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,
       return 0;
     }
 
+  burn = 0;
+
   if (c->unused)
     {
       /* XOR the input with the IV and store input into IV. */
@@ -166,7 +179,8 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,
       while (inbuflen >= blocksize_x_2 )
         {
           /* Encrypt the IV. */
-          c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+          nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+          burn = nburn > burn ? nburn : burn;
           /* XOR the input with the IV and store input into IV. */
           buf_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize);
           outbuf += blocksize;
@@ -179,7 +193,8 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,
     {
       /* Save the current IV and then encrypt the IV. */
       memcpy ( c->lastiv, c->u_iv.iv, blocksize);
-      c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      burn = nburn > burn ? nburn : burn;
       /* XOR the input with the IV and store input into IV */
       buf_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize);
       outbuf += blocksize;
@@ -191,7 +206,8 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,
     {
       /* Save the current IV and then encrypt the IV. */
       memcpy ( c->lastiv, c->u_iv.iv, blocksize );
-      c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      burn = nburn > burn ? nburn : burn;
       c->unused = blocksize;
       /* Apply the XOR. */
       c->unused -= inbuflen;
@@ -200,5 +216,9 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,
       inbuf += inbuflen;
       inbuflen = 0;
     }
+
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4 * sizeof(void *));
+
   return 0;
 }
diff --git a/cipher/cipher-ctr.c b/cipher/cipher-ctr.c
index 6bc6ffc..ff1742c 100644
--- a/cipher/cipher-ctr.c
+++ b/cipher/cipher-ctr.c
@@ -40,10 +40,13 @@ _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c,
   int i;
   unsigned int blocksize = c->cipher->blocksize;
   unsigned int nblocks;
+  unsigned int burn, nburn;
 
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
 
+  burn = 0;
+
   /* First process a left over encrypted counter.  */
   if (c->unused)
     {
@@ -57,7 +60,6 @@ _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c,
       inbuflen -= n;
     }
 
-
   /* Use a bulk method if available.  */
   nblocks = inbuflen / blocksize;
   if (nblocks && c->bulk.ctr_enc)
@@ -75,7 +77,8 @@ _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c,
       unsigned char tmp[MAX_BLOCKSIZE];
 
       do {
-        c->cipher->encrypt (&c->context.c, tmp, c->u_ctr.ctr);
+        nburn = c->cipher->encrypt (&c->context.c, tmp, c->u_ctr.ctr);
+        burn = nburn > burn ? nburn : burn;
 
         for (i = blocksize; i > 0; i--)
           {
@@ -100,5 +103,8 @@ _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c,
       wipememory (tmp, sizeof tmp);
     }
 
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4 * sizeof(void *));
+
   return 0;
 }
diff --git a/cipher/cipher-ofb.c b/cipher/cipher-ofb.c
index e194976..3fb9b0d 100644
--- a/cipher/cipher-ofb.c
+++ b/cipher/cipher-ofb.c
@@ -38,6 +38,7 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c,
 {
   unsigned char *ivp;
   size_t blocksize = c->cipher->blocksize;
+  unsigned int burn, nburn;
 
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
@@ -52,6 +53,8 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c,
       return 0;
     }
 
+  burn = 0;
+
   if( c->unused )
     {
       inbuflen -= c->unused;
@@ -67,7 +70,8 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c,
     {
       /* Encrypt the IV (and save the current one). */
       memcpy( c->lastiv, c->u_iv.iv, blocksize );
-      c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      burn = nburn > burn ? nburn : burn;
       buf_xor(outbuf, c->u_iv.iv, inbuf, blocksize);
       outbuf += blocksize;
       inbuf += blocksize;
@@ -76,7 +80,8 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c,
   if ( inbuflen )
     { /* process the remaining bytes */
       memcpy( c->lastiv, c->u_iv.iv, blocksize );
-      c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      burn = nburn > burn ? nburn : burn;
       c->unused = blocksize;
       c->unused -= inbuflen;
       buf_xor(outbuf, c->u_iv.iv, inbuf, inbuflen);
@@ -84,6 +89,10 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c,
       inbuf += inbuflen;
       inbuflen = 0;
     }
+
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4 * sizeof(void *));
+
   return 0;
 }
 
@@ -95,6 +104,7 @@ _gcry_cipher_ofb_decrypt (gcry_cipher_hd_t c,
 {
   unsigned char *ivp;
   size_t blocksize = c->cipher->blocksize;
+  unsigned int burn, nburn;
 
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
@@ -108,6 +118,8 @@ _gcry_cipher_ofb_decrypt (gcry_cipher_hd_t c,
       return 0;
     }
 
+  burn = 0;
+
   if ( c->unused )
     {
       inbuflen -= c->unused;
@@ -123,7 +135,8 @@ _gcry_cipher_ofb_decrypt (gcry_cipher_hd_t c,
     {
       /* Encrypt the IV (and save the current one). */
       memcpy( c->lastiv, c->u_iv.iv, blocksize );
-      c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      burn = nburn > burn ? nburn : burn;
       buf_xor(outbuf, c->u_iv.iv, inbuf, blocksize);
       outbuf += blocksize;
       inbuf += blocksize;
@@ -133,7 +146,8 @@ _gcry_cipher_ofb_decrypt (gcry_cipher_hd_t c,
     { /* Process the remaining bytes. */
       /* Encrypt the IV (and save the current one). */
       memcpy( c->lastiv, c->u_iv.iv, blocksize );
-      c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      burn = nburn > burn ? nburn : burn;
       c->unused = blocksize;
       c->unused -= inbuflen;
       buf_xor(outbuf, c->u_iv.iv, inbuf, inbuflen);
@@ -141,5 +155,9 @@ _gcry_cipher_ofb_decrypt (gcry_cipher_hd_t c,
       inbuf += inbuflen;
       inbuflen = 0;
     }
+
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4 * sizeof(void *));
+
   return 0;
 }
diff --git a/cipher/cipher.c b/cipher/cipher.c
index 08d6165..2337c09 100644
--- a/cipher/cipher.c
+++ b/cipher/cipher.c
@@ -150,7 +150,7 @@ dummy_setkey (void *c, const unsigned char *key, unsigned int keylen)
   return GPG_ERR_NO_ERROR;
 }
 
-static void
+static unsigned int
 dummy_encrypt_block (void *c,
 		     unsigned char *outbuf, const unsigned char *inbuf)
 {
@@ -158,9 +158,10 @@ dummy_encrypt_block (void *c,
   (void)outbuf;
   (void)inbuf;
   BUG();
+  return 0;
 }
 
-static void
+static unsigned int
 dummy_decrypt_block (void *c,
 		     unsigned char *outbuf, const unsigned char *inbuf)
 {
@@ -168,6 +169,7 @@ dummy_decrypt_block (void *c,
   (void)outbuf;
   (void)inbuf;
   BUG();
+  return 0;
 }
 
 static void
@@ -902,6 +904,7 @@ do_ecb_encrypt (gcry_cipher_hd_t c,
 {
   unsigned int blocksize = c->cipher->blocksize;
   unsigned int n, nblocks;
+  unsigned int burn, nburn;
 
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
@@ -909,13 +912,19 @@ do_ecb_encrypt (gcry_cipher_hd_t c,
     return GPG_ERR_INV_LENGTH;
 
   nblocks = inbuflen / c->cipher->blocksize;
+  burn = 0;
 
   for (n=0; n < nblocks; n++ )
     {
-      c->cipher->encrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf);
+      nburn = c->cipher->encrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf);
+      burn = nburn > burn ? nburn : burn;
       inbuf  += blocksize;
       outbuf += blocksize;
     }
+
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4 * sizeof(void *));
+
   return 0;
 }
 
@@ -926,20 +935,27 @@ do_ecb_decrypt (gcry_cipher_hd_t c,
 {
   unsigned int blocksize = c->cipher->blocksize;
   unsigned int n, nblocks;
+  unsigned int burn, nburn;
 
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
   if ((inbuflen % blocksize))
     return GPG_ERR_INV_LENGTH;
+
   nblocks = inbuflen / c->cipher->blocksize;
+  burn = 0;
 
   for (n=0; n < nblocks; n++ )
     {
-      c->cipher->decrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf );
+      nburn = c->cipher->decrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf);
+      burn = nburn > burn ? nburn : burn;
       inbuf  += blocksize;
       outbuf += blocksize;
     }
 
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4 * sizeof(void *));
+
   return 0;
 }
 
diff --git a/cipher/des.c b/cipher/des.c
index 96b06ae..7db9e5d 100644
--- a/cipher/des.c
+++ b/cipher/des.c
@@ -1054,21 +1054,21 @@ do_tripledes_set_extra_info (void *context, int what,
 }
 
 
-static void
+static unsigned int
 do_tripledes_encrypt( void *context, byte *outbuf, const byte *inbuf )
 {
   struct _tripledes_ctx *ctx = (struct _tripledes_ctx *) context;
 
   tripledes_ecb_encrypt ( ctx, inbuf, outbuf );
-  _gcry_burn_stack (32);
+  return /*burn_stack*/ (32);
 }
 
-static void
+static unsigned int
 do_tripledes_decrypt( void *context, byte *outbuf, const byte *inbuf )
 {
   struct _tripledes_ctx *ctx = (struct _tripledes_ctx *) context;
   tripledes_ecb_decrypt ( ctx, inbuf, outbuf );
-  _gcry_burn_stack (32);
+  return /*burn_stack*/ (32);
 }
 
 static gcry_err_code_t
@@ -1091,22 +1091,22 @@ do_des_setkey (void *context, const byte *key, unsigned keylen)
 }
 
 
-static void
+static unsigned int
 do_des_encrypt( void *context, byte *outbuf, const byte *inbuf )
 {
   struct _des_ctx *ctx = (struct _des_ctx *) context;
 
   des_ecb_encrypt ( ctx, inbuf, outbuf );
-  _gcry_burn_stack (32);
+  return /*burn_stack*/ (32);
 }
 
-static void
+static unsigned int
 do_des_decrypt( void *context, byte *outbuf, const byte *inbuf )
 {
   struct _des_ctx *ctx = (struct _des_ctx *) context;
 
   des_ecb_decrypt ( ctx, inbuf, outbuf );
-  _gcry_burn_stack (32);
+  return /*burn_stack*/ (32);
 }
 
 
diff --git a/cipher/idea.c b/cipher/idea.c
index c025c95..6e81e84 100644
--- a/cipher/idea.c
+++ b/cipher/idea.c
@@ -272,12 +272,12 @@ encrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf )
     cipher( outbuf, inbuf, c->ek );
 }
 
-static void
+static unsigned int
 idea_encrypt (void *context, byte *out, const byte *in)
 {
     IDEA_context *ctx = context;
     encrypt_block (ctx, out, in);
-    _gcry_burn_stack (24+3*sizeof (void*));
+    return /*burn_stack*/ (24+3*sizeof (void*));
 }
 
 static void
@@ -290,12 +290,12 @@ decrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf )
     cipher( outbuf, inbuf, c->dk );
 }
 
-static void
+static unsigned int
 idea_decrypt (void *context, byte *out, const byte *in)
 {
     IDEA_context *ctx = context;
     decrypt_block (ctx, out, in);
-    _gcry_burn_stack (24+3*sizeof (void*));
+    return /*burn_stack*/ (24+3*sizeof (void*));
 }
 
 
diff --git a/cipher/rfc2268.c b/cipher/rfc2268.c
index 1c9c8d4..130be9b 100644
--- a/cipher/rfc2268.c
+++ b/cipher/rfc2268.c
@@ -136,6 +136,13 @@ do_encrypt (void *context, unsigned char *outbuf, const unsigned char *inbuf)
   outbuf[7] = word3 >> 8;
 }
 
+static unsigned int
+encrypt_block (void *context, unsigned char *outbuf, const unsigned char *inbuf)
+{
+  do_encrypt (context, outbuf, inbuf);
+  return /*burn_stack*/ (4 * sizeof(void *) + sizeof(void *) + sizeof(u32) * 4);
+}
+
 static void
 do_decrypt (void *context, unsigned char *outbuf, const unsigned char *inbuf)
 {
@@ -188,6 +195,13 @@ do_decrypt (void *context, unsigned char *outbuf, const unsigned char *inbuf)
   outbuf[7] = word3 >> 8;
 }
 
+static unsigned int
+decrypt_block (void *context, unsigned char *outbuf, const unsigned char *inbuf)
+{
+  do_decrypt (context, outbuf, inbuf);
+  return /*burn_stack*/ (4 * sizeof(void *) + sizeof(void *) + sizeof(u32) * 4);
+}
+
 
 static gpg_err_code_t
 setkey_core (void *context, const unsigned char *key, unsigned int keylen, int with_phase2)
@@ -340,5 +354,5 @@ static gcry_cipher_oid_spec_t oids_rfc2268_40[] =
 gcry_cipher_spec_t _gcry_cipher_spec_rfc2268_40 = {
   "RFC2268_40", NULL, oids_rfc2268_40,
   RFC2268_BLOCKSIZE, 40, sizeof(RFC2268_context),
-  do_setkey, do_encrypt, do_decrypt
+  do_setkey, encrypt_block, decrypt_block
 };
diff --git a/cipher/rijndael.c b/cipher/rijndael.c
index 314f106..190d0f9 100644
--- a/cipher/rijndael.c
+++ b/cipher/rijndael.c
@@ -1450,10 +1450,11 @@ do_aesni (RIJNDAEL_context *ctx, int decrypt_flag,
 #endif /*USE_AESNI*/
 
 
-static void
+static unsigned int
 rijndael_encrypt (void *context, byte *b, const byte *a)
 {
   RIJNDAEL_context *ctx = context;
+  unsigned int burn_stack;
 
   if (0)
     ;
@@ -1461,7 +1462,7 @@ rijndael_encrypt (void *context, byte *b, const byte *a)
   else if (ctx->use_padlock)
     {
       do_padlock (ctx, 0, b, a);
-      _gcry_burn_stack (48 + 15 /* possible padding for alignment */);
+      burn_stack = (48 + 15 /* possible padding for alignment */);
     }
 #endif /*USE_PADLOCK*/
 #ifdef USE_AESNI
@@ -1470,13 +1471,16 @@ rijndael_encrypt (void *context, byte *b, const byte *a)
       aesni_prepare ();
       do_aesni (ctx, 0, b, a);
       aesni_cleanup ();
+      burn_stack = 0;
     }
 #endif /*USE_AESNI*/
   else
     {
       do_encrypt (ctx, b, a);
-      _gcry_burn_stack (56 + 2*sizeof(int));
+      burn_stack = (56 + 2*sizeof(int));
     }
+
+  return burn_stack;
 }
 
 
@@ -1820,10 +1824,11 @@ do_decrypt (RIJNDAEL_context *ctx, byte *bx, const byte *ax)
 
 
 
-static void
+static unsigned int
 rijndael_decrypt (void *context, byte *b, const byte *a)
 {
   RIJNDAEL_context *ctx = context;
+  unsigned int burn_stack;
 
   if (0)
     ;
@@ -1831,7 +1836,7 @@ rijndael_decrypt (void *context, byte *b, const byte *a)
   else if (ctx->use_padlock)
     {
       do_padlock (ctx, 1, b, a);
-      _gcry_burn_stack (48 + 2*sizeof(int) /* FIXME */);
+      burn_stack = (48 + 2*sizeof(int) /* FIXME */);
     }
 #endif /*USE_PADLOCK*/
 #ifdef USE_AESNI
@@ -1840,13 +1845,16 @@ rijndael_decrypt (void *context, byte *b, const byte *a)
       aesni_prepare ();
       do_aesni (ctx, 1, b, a);
       aesni_cleanup ();
+      burn_stack = 0;
     }
 #endif /*USE_AESNI*/
   else
     {
       do_decrypt (ctx, b, a);
-      _gcry_burn_stack (56+2*sizeof(int));
+      burn_stack = (56+2*sizeof(int));
     }
+
+  return burn_stack;
 }
 
 
diff --git a/cipher/seed.c b/cipher/seed.c
index ae26e67..1600c55 100644
--- a/cipher/seed.c
+++ b/cipher/seed.c
@@ -371,13 +371,13 @@ do_encrypt (const SEED_context *ctx, byte *outbuf, const byte *inbuf)
   PUTU32 (outbuf+12, x2);
 }
 
-static void
+static unsigned int
 seed_encrypt (void *context, byte *outbuf, const byte *inbuf)
 {
   SEED_context *ctx = context;
 
   do_encrypt (ctx, outbuf, inbuf);
-  _gcry_burn_stack (4*6);
+  return /*burn_stack*/ (4*6);
 }
 
 
@@ -417,13 +417,13 @@ do_decrypt (SEED_context *ctx, byte *outbuf, const byte *inbuf)
   PUTU32 (outbuf+12, x2);
 }
 
-static void
+static unsigned int
 seed_decrypt (void *context, byte *outbuf, const byte *inbuf)
 {
   SEED_context *ctx = context;
 
   do_decrypt (ctx, outbuf, inbuf);
-  _gcry_burn_stack (4*6);
+  return /*burn_stack*/ (4*6);
 }
 
 

diff --git a/cipher/serpent.c b/cipher/serpent.c
index bf03fe7..30ba4dd 100644
--- a/cipher/serpent.c
+++ b/cipher/serpent.c
@@ -792,22 +792,22 @@ serpent_decrypt_internal (serpent_context_t *context,
   memcpy (output, b_next, sizeof (b_next));
 }
 
-static void
+static unsigned int
 serpent_encrypt (void *ctx, byte *buffer_out, const byte *buffer_in)
 {
   serpent_context_t *context = ctx;
 
   serpent_encrypt_internal (context, buffer_in, buffer_out);
-  _gcry_burn_stack (2 * sizeof (serpent_block_t));
+  return /*burn_stack*/ (2 * sizeof (serpent_block_t));
 }
 
-static void
+static unsigned int
 serpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in)
 {
   serpent_context_t *context = ctx;
 
   serpent_decrypt_internal (context, buffer_in, buffer_out);
-  _gcry_burn_stack (2 * sizeof (serpent_block_t));
+  return /*burn_stack*/ (2 * sizeof (serpent_block_t));
 }
 
 

diff --git a/cipher/twofish.c b/cipher/twofish.c
index 07a4ebe..70cdb47 100644
--- a/cipher/twofish.c
+++ b/cipher/twofish.c
@@ -819,12 +819,12 @@ do_twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
   _gcry_twofish_amd64_encrypt_block(ctx, out, in);
 }
 
-static void
+static unsigned int
 twofish_encrypt (void *context, byte *out, const byte *in)
 {
   TWOFISH_context *ctx = context;
   _gcry_twofish_amd64_encrypt_block(ctx, out, in);
-  _gcry_burn_stack (4*sizeof (void*));
+  return /*burn_stack*/ (4*sizeof (void*));
 }
 
 #else /*!USE_AMD64_ASM*/
@@ -861,12 +861,12 @@ do_twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
   OUTUNPACK (3, b, 7);
 }
 
-static void
+static unsigned int
 twofish_encrypt (void *context, byte *out, const byte *in)
 {
   TWOFISH_context *ctx = context;
   do_twofish_encrypt (ctx, out, in);
-  _gcry_burn_stack (24+3*sizeof (void*));
+  return /*burn_stack*/ (24+3*sizeof (void*));
 }
 
 #endif /*!USE_AMD64_ASM*/
@@ -882,12 +882,12 @@ do_twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
   _gcry_twofish_amd64_decrypt_block(ctx, out, in);
 }
 
-static void
+static unsigned int
 twofish_decrypt (void *context, byte *out, const byte *in)
 {
   TWOFISH_context *ctx = context;
   _gcry_twofish_amd64_decrypt_block(ctx, out, in);
-  _gcry_burn_stack (4*sizeof (void*));
+  return /*burn_stack*/ (4*sizeof (void*));
 }
 
 #else /*!USE_AMD64_ASM*/
@@ -924,13 +924,13 @@ do_twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
   OUTUNPACK (3, d, 3);
 }
 
-static void
+static unsigned int
 twofish_decrypt (void *context, byte *out, const byte *in)
 {
   TWOFISH_context *ctx = context;
 
   do_twofish_decrypt (ctx, out, in);
-  _gcry_burn_stack (24+3*sizeof (void*));
+  return /*burn_stack*/ (24+3*sizeof (void*));
 }
 
 #endif /*!USE_AMD64_ASM*/
diff --git a/src/gcrypt-module.h b/src/gcrypt-module.h
index cd55207..10c9f02 100644
--- a/src/gcrypt-module.h
+++ b/src/gcrypt-module.h
@@ -52,14 +52,14 @@ typedef gcry_err_code_t (*gcry_cipher_setkey_t) (void *c,
 						 unsigned keylen);
 
 /* Type for the cipher_encrypt function.  */
-typedef void (*gcry_cipher_encrypt_t) (void *c,
-				       unsigned char *outbuf,
-				       const unsigned char *inbuf);
+typedef unsigned int __attribute__ ((warn_unused_result)) (*gcry_cipher_encrypt_t) (void *c,
+					       unsigned char *outbuf,
+					       const unsigned char *inbuf);
 
 /* Type for the cipher_decrypt function.  */
-typedef void (*gcry_cipher_decrypt_t) (void *c,
-				       unsigned char *outbuf,
-				       const unsigned char *inbuf);
+typedef unsigned int __attribute__ ((warn_unused_result)) (*gcry_cipher_decrypt_t) (void *c,
+					       unsigned char *outbuf,
+					       const unsigned char *inbuf);
 
 /* Type for the cipher_stencrypt function.  */
 typedef void (*gcry_cipher_stencrypt_t) (void *c,




More information about the Gcrypt-devel mailing list