[PATCH 2/5] Separate common md block code

Dmitry Eremin-Solenikov dbaryshkov at gmail.com
Mon Sep 2 11:28:49 CEST 2013


* cipher/hash-common.c, cipher/hash-common.h: add _gcry_md_block_write()
  a new function to handle block md operations. Currently implementation
  is limited to 64 bytes buffer and u32 blocks counter.

* cipher/md4.c, cipher/md5.c, cipher/rmd.h, cipher/rmd160.c,
  cipher/sha1.c, cipher/sha256.c, cipher/tiger.c: convert to use
  _gcry_md_block_write().

whirpool and sha512 are left as before, as sha512 uses 128 bytes buffer
and u64 blocks counter and whirpool does not have trivial block handling
structure.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 cipher/hash-common.c |  42 ++++++++++++++++++
 cipher/hash-common.h |  19 ++++++--
 cipher/md4.c         | 109 +++++++++++++++-------------------------------
 cipher/md5.c         | 110 +++++++++++++++-------------------------------
 cipher/rmd.h         |   5 +--
 cipher/rmd160.c      | 104 +++++++++++++++----------------------------
 cipher/sha1.c        | 121 +++++++++++++++------------------------------------
 cipher/sha256.c      | 113 +++++++++++++++++------------------------------
 cipher/tiger.c       | 112 ++++++++++++++++-------------------------------
 9 files changed, 279 insertions(+), 456 deletions(-)

diff --git a/cipher/hash-common.c b/cipher/hash-common.c
index 8c413bc..e267da1 100644
--- a/cipher/hash-common.c
+++ b/cipher/hash-common.c
@@ -91,3 +91,45 @@ _gcry_hash_selftest_check_one (int algo,
 
   return result;
 }
+
+void
+_gcry_md_block_write( void *context, const void *inbuf_arg, size_t inlen)
+{
+  const unsigned char *inbuf = inbuf_arg;
+  gcry_md_block_ctx_t *hd = context;
+
+  if ( hd->buf == NULL || hd->bwrite == NULL)
+    return;
+
+  if( hd->count == hd->blocksize )  /* flush the buffer */
+    {
+      hd->bwrite( hd, hd->buf );
+      _gcry_burn_stack (hd->stack_burn);
+      hd->count = 0;
+      hd->nblocks++;
+    }
+  if( !inbuf )
+    return;
+
+  if( hd->count )
+    {
+      for( ; inlen && hd->count < hd->blocksize; inlen-- )
+        hd->buf[hd->count++] = *inbuf++;
+      _gcry_md_block_write( hd, NULL, 0 );
+      if( !inlen )
+        return;
+    }
+
+  while( inlen >= hd->blocksize)
+    {
+      hd->bwrite( hd, inbuf );
+      hd->count = 0;
+      hd->nblocks++;
+      inlen -= hd->blocksize;
+      inbuf += hd->blocksize;
+    }
+  _gcry_burn_stack (hd->stack_burn);
+  for( ; inlen && hd->count < hd->blocksize; inlen-- )
+    hd->buf[hd->count++] = *inbuf++;
+
+}
diff --git a/cipher/hash-common.h b/cipher/hash-common.h
index fdebef4..9553dcf 100644
--- a/cipher/hash-common.h
+++ b/cipher/hash-common.h
@@ -26,8 +26,21 @@ const char * _gcry_hash_selftest_check_one
               int datamode, const void *data, size_t datalen,
               const void *expect, size_t expectlen);
 
-
-
-
+/* Type for the md_write helper function for block MD.  */
+typedef void (*_gcry_md_block_write_t) (void *c, const unsigned char *buf);
+
+typedef struct gcry_md_block_ctx
+{
+    u32  nblocks;
+    int  count;
+    byte buf[64];
+    size_t blocksize;
+    _gcry_md_block_write_t bwrite;
+    size_t stack_burn;
+} gcry_md_block_ctx_t;
+
+
+void
+_gcry_md_block_write( void *context, const void *inbuf_arg, size_t inlen);
 
 #endif /*GCRY_HASH_COMMON_H*/
diff --git a/cipher/md4.c b/cipher/md4.c
index 22fbf8d..9e75fbc 100644
--- a/cipher/md4.c
+++ b/cipher/md4.c
@@ -56,15 +56,16 @@
 #include "cipher.h"
 
 #include "bithelp.h"
+#include "hash-common.h"
 
 
 typedef struct {
+    gcry_md_block_ctx_t bctx;
     u32 A,B,C,D;	  /* chaining variables */
-    u32  nblocks;
-    byte buf[64];
-    int  count;
 } MD4_CONTEXT;
 
+static void
+transform ( void *c, const unsigned char *data );
 
 static void
 md4_init( void *context )
@@ -76,8 +77,11 @@ md4_init( void *context )
   ctx->C = 0x98badcfe;
   ctx->D = 0x10325476;
 
-  ctx->nblocks = 0;
-  ctx->count = 0;
+  ctx->bctx.nblocks = 0;
+  ctx->bctx.count = 0;
+  ctx->bctx.blocksize = 64;
+  ctx->bctx.stack_burn = 80+6*sizeof(void*);
+  ctx->bctx.bwrite = transform;
 }
 
 #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
@@ -89,8 +93,9 @@ md4_init( void *context )
  * transform 64 bytes
  */
 static void
-transform ( MD4_CONTEXT *ctx, const unsigned char *data )
+transform ( void *c, const unsigned char *data )
 {
+  MD4_CONTEXT *ctx = c;
   u32 in[16];
   register u32 A = ctx->A;
   register u32 B = ctx->B;
@@ -187,50 +192,6 @@ transform ( MD4_CONTEXT *ctx, const unsigned char *data )
 
 
 
-/* The routine updates the message-digest context to
- * account for the presence of each of the characters inBuf[0..inLen-1]
- * in the message whose digest is being computed.
- */
-static void
-md4_write ( void *context, const void *inbuf_arg, size_t inlen)
-{
-  const unsigned char *inbuf = inbuf_arg;
-  MD4_CONTEXT *hd = context;
-
-  if( hd->count == 64 ) /* flush the buffer */
-    {
-      transform( hd, hd->buf );
-      _gcry_burn_stack (80+6*sizeof(void*));
-      hd->count = 0;
-      hd->nblocks++;
-    }
-  if( !inbuf )
-    return;
-
-  if( hd->count )
-    {
-      for( ; inlen && hd->count < 64; inlen-- )
-        hd->buf[hd->count++] = *inbuf++;
-      md4_write( hd, NULL, 0 );
-      if( !inlen )
-        return;
-    }
-  _gcry_burn_stack (80+6*sizeof(void*));
-
-  while( inlen >= 64 )
-    {
-      transform( hd, inbuf );
-      hd->count = 0;
-      hd->nblocks++;
-      inlen -= 64;
-      inbuf += 64;
-    }
-  for( ; inlen && hd->count < 64; inlen-- )
-    hd->buf[hd->count++] = *inbuf++;
-}
-
-
-
 /* The routine final terminates the message-digest computation and
  * ends with the desired message digest in mdContext->digest[0...15].
  * The handle is prepared for a new MD4 cycle.
@@ -244,15 +205,15 @@ md4_final( void *context )
   u32 t, msb, lsb;
   byte *p;
 
-  md4_write(hd, NULL, 0); /* flush */;
+  _gcry_md_block_write(hd, NULL, 0); /* flush */;
 
-  t = hd->nblocks;
+  t = hd->bctx.nblocks;
   /* multiply by 64 to make a byte count */
   lsb = t << 6;
   msb = t >> 26;
   /* add the count */
   t = lsb;
-  if( (lsb += hd->count) < t )
+  if( (lsb += hd->bctx.count) < t )
     msb++;
   /* multiply by 8 to make a bit count */
   t = lsb;
@@ -260,33 +221,33 @@ md4_final( void *context )
   msb <<= 3;
   msb |= t >> 29;
 
-  if( hd->count < 56 )  /* enough room */
+  if( hd->bctx.count < 56 )  /* enough room */
     {
-      hd->buf[hd->count++] = 0x80; /* pad */
-      while( hd->count < 56 )
-        hd->buf[hd->count++] = 0;  /* pad */
+      hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */
+      while( hd->bctx.count < 56 )
+        hd->bctx.buf[hd->bctx.count++] = 0;  /* pad */
     }
   else /* need one extra block */
     {
-      hd->buf[hd->count++] = 0x80; /* pad character */
-      while( hd->count < 64 )
-        hd->buf[hd->count++] = 0;
-      md4_write(hd, NULL, 0);  /* flush */;
-      memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+      hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */
+      while( hd->bctx.count < 64 )
+        hd->bctx.buf[hd->bctx.count++] = 0;
+      _gcry_md_block_write(hd, NULL, 0);  /* flush */;
+      memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */
     }
   /* append the 64 bit count */
-  hd->buf[56] = lsb	   ;
-  hd->buf[57] = lsb >>  8;
-  hd->buf[58] = lsb >> 16;
-  hd->buf[59] = lsb >> 24;
-  hd->buf[60] = msb	   ;
-  hd->buf[61] = msb >>  8;
-  hd->buf[62] = msb >> 16;
-  hd->buf[63] = msb >> 24;
-  transform( hd, hd->buf );
+  hd->bctx.buf[56] = lsb	   ;
+  hd->bctx.buf[57] = lsb >>  8;
+  hd->bctx.buf[58] = lsb >> 16;
+  hd->bctx.buf[59] = lsb >> 24;
+  hd->bctx.buf[60] = msb	   ;
+  hd->bctx.buf[61] = msb >>  8;
+  hd->bctx.buf[62] = msb >> 16;
+  hd->bctx.buf[63] = msb >> 24;
+  transform( hd, hd->bctx.buf );
   _gcry_burn_stack (80+6*sizeof(void*));
 
-  p = hd->buf;
+  p = hd->bctx.buf;
 #ifdef WORDS_BIGENDIAN
 #define X(a) do { *p++ = hd->a      ; *p++ = hd->a >> 8;      \
 		  *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0)
@@ -305,7 +266,7 @@ static byte *
 md4_read (void *context)
 {
   MD4_CONTEXT *hd = context;
-  return hd->buf;
+  return hd->bctx.buf;
 }
 
 static byte asn[18] = /* Object ID is 1.2.840.113549.2.4 */
@@ -322,6 +283,6 @@ static gcry_md_oid_spec_t oid_spec_md4[] =
 gcry_md_spec_t _gcry_digest_spec_md4 =
   {
     "MD4", asn, DIM (asn), oid_spec_md4,16,
-    md4_init, md4_write, md4_final, md4_read,
+    md4_init, _gcry_md_block_write, md4_final, md4_read,
     sizeof (MD4_CONTEXT)
   };
diff --git a/cipher/md5.c b/cipher/md5.c
index a98678a..9857f2c 100644
--- a/cipher/md5.c
+++ b/cipher/md5.c
@@ -40,15 +40,16 @@
 #include "cipher.h"
 
 #include "bithelp.h"
+#include "hash-common.h"
 
 
 typedef struct {
+    gcry_md_block_ctx_t bctx;
     u32 A,B,C,D;	  /* chaining variables */
-    u32  nblocks;
-    byte buf[64];
-    int  count;
 } MD5_CONTEXT;
 
+static void
+transform ( void *ctx, const unsigned char *data );
 
 static void
 md5_init( void *context )
@@ -60,8 +61,11 @@ md5_init( void *context )
   ctx->C = 0x98badcfe;
   ctx->D = 0x10325476;
 
-  ctx->nblocks = 0;
-  ctx->count = 0;
+  ctx->bctx.nblocks = 0;
+  ctx->bctx.count = 0;
+  ctx->bctx.blocksize = 64;
+  ctx->bctx.stack_burn = 80+6*sizeof(void*);
+  ctx->bctx.bwrite = transform;
 }
 
 
@@ -79,8 +83,9 @@ md5_init( void *context )
  * transform n*64 bytes
  */
 static void
-transform ( MD5_CONTEXT *ctx, const unsigned char *data )
+transform ( void *c, const unsigned char *data )
 {
+  MD5_CONTEXT *ctx = c;
   u32 correct_words[16];
   register u32 A = ctx->A;
   register u32 B = ctx->B;
@@ -212,51 +217,6 @@ transform ( MD5_CONTEXT *ctx, const unsigned char *data )
 
 
 
-/* The routine updates the message-digest context to
- * account for the presence of each of the characters inBuf[0..inLen-1]
- * in the message whose digest is being computed.
- */
-static void
-md5_write( void *context, const void *inbuf_arg , size_t inlen)
-{
-  const unsigned char *inbuf = inbuf_arg;
-  MD5_CONTEXT *hd = context;
-
-  if( hd->count == 64 )  /* flush the buffer */
-    {
-      transform( hd, hd->buf );
-      _gcry_burn_stack (80+6*sizeof(void*));
-      hd->count = 0;
-      hd->nblocks++;
-    }
-  if( !inbuf )
-    return;
-
-  if( hd->count )
-    {
-      for( ; inlen && hd->count < 64; inlen-- )
-        hd->buf[hd->count++] = *inbuf++;
-      md5_write( hd, NULL, 0 );
-      if( !inlen )
-        return;
-    }
-  _gcry_burn_stack (80+6*sizeof(void*));
-
-  while( inlen >= 64 )
-    {
-      transform( hd, inbuf );
-      hd->count = 0;
-      hd->nblocks++;
-      inlen -= 64;
-      inbuf += 64;
-    }
-  for( ; inlen && hd->count < 64; inlen-- )
-    hd->buf[hd->count++] = *inbuf++;
-
-}
-
-
-
 /* The routine final terminates the message-digest computation and
  * ends with the desired message digest in mdContext->digest[0...15].
  * The handle is prepared for a new MD5 cycle.
@@ -270,15 +230,15 @@ md5_final( void *context)
   u32 t, msb, lsb;
   byte *p;
 
-  md5_write(hd, NULL, 0); /* flush */;
+  _gcry_md_block_write(hd, NULL, 0); /* flush */;
 
-  t = hd->nblocks;
+  t = hd->bctx.nblocks;
   /* multiply by 64 to make a byte count */
   lsb = t << 6;
   msb = t >> 26;
   /* add the count */
   t = lsb;
-  if( (lsb += hd->count) < t )
+  if( (lsb += hd->bctx.count) < t )
     msb++;
   /* multiply by 8 to make a bit count */
   t = lsb;
@@ -286,33 +246,33 @@ md5_final( void *context)
   msb <<= 3;
   msb |= t >> 29;
 
-  if( hd->count < 56 )  /* enough room */
+  if( hd->bctx.count < 56 )  /* enough room */
     {
-      hd->buf[hd->count++] = 0x80; /* pad */
-      while( hd->count < 56 )
-        hd->buf[hd->count++] = 0;  /* pad */
+      hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */
+      while( hd->bctx.count < 56 )
+        hd->bctx.buf[hd->bctx.count++] = 0;  /* pad */
     }
   else  /* need one extra block */
     {
-      hd->buf[hd->count++] = 0x80; /* pad character */
-      while( hd->count < 64 )
-        hd->buf[hd->count++] = 0;
-      md5_write(hd, NULL, 0);  /* flush */;
-      memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+      hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */
+      while( hd->bctx.count < 64 )
+        hd->bctx.buf[hd->bctx.count++] = 0;
+      _gcry_md_block_write(hd, NULL, 0);  /* flush */;
+      memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */
     }
   /* append the 64 bit count */
-  hd->buf[56] = lsb	   ;
-  hd->buf[57] = lsb >>  8;
-  hd->buf[58] = lsb >> 16;
-  hd->buf[59] = lsb >> 24;
-  hd->buf[60] = msb	   ;
-  hd->buf[61] = msb >>  8;
-  hd->buf[62] = msb >> 16;
-  hd->buf[63] = msb >> 24;
-  transform( hd, hd->buf );
+  hd->bctx.buf[56] = lsb	   ;
+  hd->bctx.buf[57] = lsb >>  8;
+  hd->bctx.buf[58] = lsb >> 16;
+  hd->bctx.buf[59] = lsb >> 24;
+  hd->bctx.buf[60] = msb	   ;
+  hd->bctx.buf[61] = msb >>  8;
+  hd->bctx.buf[62] = msb >> 16;
+  hd->bctx.buf[63] = msb >> 24;
+  transform( hd, hd->bctx.buf );
   _gcry_burn_stack (80+6*sizeof(void*));
 
-  p = hd->buf;
+  p = hd->bctx.buf;
 #ifdef WORDS_BIGENDIAN
 #define X(a) do { *p++ = hd->a      ; *p++ = hd->a >> 8;      \
 	          *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0)
@@ -331,7 +291,7 @@ static byte *
 md5_read( void *context )
 {
   MD5_CONTEXT *hd = (MD5_CONTEXT *) context;
-  return hd->buf;
+  return hd->bctx.buf;
 }
 
 static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 */
@@ -350,6 +310,6 @@ static gcry_md_oid_spec_t oid_spec_md5[] =
 gcry_md_spec_t _gcry_digest_spec_md5 =
   {
     "MD5", asn, DIM (asn), oid_spec_md5, 16,
-    md5_init, md5_write, md5_final, md5_read,
+    md5_init, _gcry_md_block_write, md5_final, md5_read,
     sizeof (MD5_CONTEXT)
   };
diff --git a/cipher/rmd.h b/cipher/rmd.h
index 6a9fe31..a56ee49 100644
--- a/cipher/rmd.h
+++ b/cipher/rmd.h
@@ -20,14 +20,13 @@
 #ifndef G10_RMD_H
 #define G10_RMD_H
 
+#include "hash-common.h"
 
 /* We need this here because random.c must have direct access. */
 typedef struct
 {
+  gcry_md_block_ctx_t bctx;
   u32  h0,h1,h2,h3,h4;
-  u32  nblocks;
-  byte buf[64];
-  int  count;
 } RMD160_CONTEXT;
 
 void _gcry_rmd160_init ( void *context );
diff --git a/cipher/rmd160.c b/cipher/rmd160.c
index 179a4d9..5bb32a6 100644
--- a/cipher/rmd160.c
+++ b/cipher/rmd160.c
@@ -139,6 +139,8 @@
  * 1 million times "a"   52783243c1697bdbe16d37f97f68f08325dc1528
  */
 
+static void
+transform ( void *ctx, const unsigned char *data );
 
 void
 _gcry_rmd160_init (void *context)
@@ -150,8 +152,11 @@ _gcry_rmd160_init (void *context)
   hd->h2 = 0x98BADCFE;
   hd->h3 = 0x10325476;
   hd->h4 = 0xC3D2E1F0;
-  hd->nblocks = 0;
-  hd->count = 0;
+  hd->bctx.nblocks = 0;
+  hd->bctx.count = 0;
+  hd->bctx.blocksize = 64;
+  hd->bctx.stack_burn = 108+5*sizeof(void*);
+  hd->bctx.bwrite = transform;
 }
 
 
@@ -160,8 +165,9 @@ _gcry_rmd160_init (void *context)
  * Transform the message X which consists of 16 32-bit-words
  */
 static void
-transform ( RMD160_CONTEXT *hd, const unsigned char *data )
+transform ( void *ctx, const unsigned char *data )
 {
+  RMD160_CONTEXT *hd = ctx;
   register u32 a,b,c,d,e;
   u32 aa,bb,cc,dd,ee,t;
 #ifdef WORDS_BIGENDIAN
@@ -397,46 +403,6 @@ transform ( RMD160_CONTEXT *hd, const unsigned char *data )
 }
 
 
-/* Update the message digest with the contents
- * of INBUF with length INLEN.
- */
-static void
-rmd160_write ( void *context, const void *inbuf_arg, size_t inlen)
-{
-  const unsigned char *inbuf = inbuf_arg;
-  RMD160_CONTEXT *hd = context;
-
-  if( hd->count == 64 )  /* flush the buffer */
-    {
-      transform( hd, hd->buf );
-      _gcry_burn_stack (108+5*sizeof(void*));
-      hd->count = 0;
-      hd->nblocks++;
-    }
-  if( !inbuf )
-    return;
-  if( hd->count )
-    {
-      for( ; inlen && hd->count < 64; inlen-- )
-        hd->buf[hd->count++] = *inbuf++;
-      rmd160_write( hd, NULL, 0 );
-      if( !inlen )
-        return;
-    }
-
-  while( inlen >= 64 )
-    {
-      transform( hd, inbuf );
-      hd->count = 0;
-      hd->nblocks++;
-      inlen -= 64;
-      inbuf += 64;
-    }
-  _gcry_burn_stack (108+5*sizeof(void*));
-  for( ; inlen && hd->count < 64; inlen-- )
-    hd->buf[hd->count++] = *inbuf++;
-}
-
 /****************
  * Apply the rmd160 transform function on the buffer which must have
  * a length 64 bytes. Do not use this function together with the
@@ -469,15 +435,15 @@ rmd160_final( void *context )
   u32 t, msb, lsb;
   byte *p;
 
-  rmd160_write(hd, NULL, 0); /* flush */;
+  _gcry_md_block_write(hd, NULL, 0); /* flush */;
 
-  t = hd->nblocks;
+  t = hd->bctx.nblocks;
   /* multiply by 64 to make a byte count */
   lsb = t << 6;
   msb = t >> 26;
   /* add the count */
   t = lsb;
-  if( (lsb += hd->count) < t )
+  if( (lsb += hd->bctx.count) < t )
     msb++;
   /* multiply by 8 to make a bit count */
   t = lsb;
@@ -485,33 +451,33 @@ rmd160_final( void *context )
   msb <<= 3;
   msb |= t >> 29;
 
-  if( hd->count < 56 )  /* enough room */
+  if( hd->bctx.count < 56 )  /* enough room */
     {
-      hd->buf[hd->count++] = 0x80; /* pad */
-      while( hd->count < 56 )
-        hd->buf[hd->count++] = 0;  /* pad */
+      hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */
+      while( hd->bctx.count < 56 )
+        hd->bctx.buf[hd->bctx.count++] = 0;  /* pad */
     }
   else  /* need one extra block */
     {
-      hd->buf[hd->count++] = 0x80; /* pad character */
-      while( hd->count < 64 )
-        hd->buf[hd->count++] = 0;
-      rmd160_write(hd, NULL, 0);  /* flush */;
-      memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+      hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */
+      while( hd->bctx.count < 64 )
+        hd->bctx.buf[hd->bctx.count++] = 0;
+      _gcry_md_block_write(hd, NULL, 0);  /* flush */;
+      memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */
     }
   /* append the 64 bit count */
-  hd->buf[56] = lsb	   ;
-  hd->buf[57] = lsb >>  8;
-  hd->buf[58] = lsb >> 16;
-  hd->buf[59] = lsb >> 24;
-  hd->buf[60] = msb	   ;
-  hd->buf[61] = msb >>  8;
-  hd->buf[62] = msb >> 16;
-  hd->buf[63] = msb >> 24;
-  transform( hd, hd->buf );
+  hd->bctx.buf[56] = lsb	   ;
+  hd->bctx.buf[57] = lsb >>  8;
+  hd->bctx.buf[58] = lsb >> 16;
+  hd->bctx.buf[59] = lsb >> 24;
+  hd->bctx.buf[60] = msb	   ;
+  hd->bctx.buf[61] = msb >>  8;
+  hd->bctx.buf[62] = msb >> 16;
+  hd->bctx.buf[63] = msb >> 24;
+  transform( hd, hd->bctx.buf );
   _gcry_burn_stack (108+5*sizeof(void*));
 
-  p = hd->buf;
+  p = hd->bctx.buf;
 #ifdef WORDS_BIGENDIAN
 #define X(a) do { *p++ = hd->h##a	   ; *p++ = hd->h##a >> 8;	\
 	          *p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0)
@@ -531,7 +497,7 @@ rmd160_read( void *context )
 {
   RMD160_CONTEXT *hd = context;
 
-  return hd->buf;
+  return hd->bctx.buf;
 }
 
 
@@ -546,9 +512,9 @@ _gcry_rmd160_hash_buffer (void *outbuf, const void *buffer, size_t length )
   RMD160_CONTEXT hd;
 
   _gcry_rmd160_init ( &hd );
-  rmd160_write ( &hd, buffer, length );
+  _gcry_md_block_write ( &hd, buffer, length );
   rmd160_final ( &hd );
-  memcpy ( outbuf, hd.buf, 20 );
+  memcpy ( outbuf, hd.bctx.buf, 20 );
 }
 
 static byte asn[15] = /* Object ID is 1.3.36.3.2.1 */
@@ -567,6 +533,6 @@ static gcry_md_oid_spec_t oid_spec_rmd160[] =
 gcry_md_spec_t _gcry_digest_spec_rmd160 =
   {
     "RIPEMD160", asn, DIM (asn), oid_spec_rmd160, 20,
-    _gcry_rmd160_init, rmd160_write, rmd160_final, rmd160_read,
+    _gcry_rmd160_init, _gcry_md_block_write, rmd160_final, rmd160_read,
     sizeof (RMD160_CONTEXT)
   };
diff --git a/cipher/sha1.c b/cipher/sha1.c
index 4b784ac..6777348 100644
--- a/cipher/sha1.c
+++ b/cipher/sha1.c
@@ -51,18 +51,15 @@
 /* # define U32_ALIGNED_P(p) (!(((uintptr_t)p) % sizeof (u32))) */
 /* #endif */
 
-#define TRANSFORM(x,d,n) transform ((x), (d), (n))
-
-
 typedef struct
 {
+  gcry_md_block_ctx_t bctx;
   u32           h0,h1,h2,h3,h4;
-  u32           nblocks;
-  unsigned char buf[64];
-  int           count;
 } SHA1_CONTEXT;
 
 
+static void
+transform (void *c, const unsigned char *data);
 
 static void
 sha1_init (void *context)
@@ -74,8 +71,11 @@ sha1_init (void *context)
   hd->h2 = 0x98badcfe;
   hd->h3 = 0x10325476;
   hd->h4 = 0xc3d2e1f0;
-  hd->nblocks = 0;
-  hd->count = 0;
+  hd->bctx.nblocks = 0;
+  hd->bctx.count = 0;
+  hd->bctx.blocksize = 64;
+  hd->bctx.stack_burn = 88+4*sizeof(void*);
+  hd->bctx.bwrite = transform;
 }
 
 
@@ -105,15 +105,13 @@ sha1_init (void *context)
  * Transform NBLOCKS of each 64 bytes (16 32-bit words) at DATA.
  */
 static void
-transform (SHA1_CONTEXT *hd, const unsigned char *data, size_t nblocks)
+transform (void *ctx, const unsigned char *data)
 {
+  SHA1_CONTEXT *hd = ctx;
   register u32 a, b, c, d, e; /* Local copies of the chaining variables.  */
   register u32 tm;            /* Helper.  */
   u32 x[16];                  /* The array we work on. */
 
-  /* Loop over all blocks.  */
-  for ( ;nblocks; nblocks--)
-    {
 #ifdef WORDS_BIGENDIAN
       memcpy (x, data, 64);
       data += 64;
@@ -226,53 +224,6 @@ transform (SHA1_CONTEXT *hd, const unsigned char *data, size_t nblocks)
       hd->h2 += c;
       hd->h3 += d;
       hd->h4 += e;
-    }
-}
-
-
-/* Update the message digest with the contents
- * of INBUF with length INLEN.
- */
-static void
-sha1_write( void *context, const void *inbuf_arg, size_t inlen)
-{
-  const unsigned char *inbuf = inbuf_arg;
-  SHA1_CONTEXT *hd = context;
-  size_t nblocks;
-
-  if (hd->count == 64)  /* Flush the buffer. */
-    {
-      TRANSFORM( hd, hd->buf, 1 );
-      _gcry_burn_stack (88+4*sizeof(void*));
-      hd->count = 0;
-      hd->nblocks++;
-    }
-  if (!inbuf)
-    return;
-
-  if (hd->count)
-    {
-      for (; inlen && hd->count < 64; inlen--)
-        hd->buf[hd->count++] = *inbuf++;
-      sha1_write (hd, NULL, 0);
-      if (!inlen)
-        return;
-    }
-
-  nblocks = inlen / 64;
-  if (nblocks)
-    {
-      TRANSFORM (hd, inbuf, nblocks);
-      hd->count = 0;
-      hd->nblocks += nblocks;
-      inlen -= nblocks * 64;
-      inbuf += nblocks * 64;
-    }
-  _gcry_burn_stack (88+4*sizeof(void*));
-
-  /* Save remaining bytes.  */
-  for (; inlen && hd->count < 64; inlen--)
-    hd->buf[hd->count++] = *inbuf++;
 }
 
 
@@ -291,15 +242,15 @@ sha1_final(void *context)
   u32 t, msb, lsb;
   unsigned char *p;
 
-  sha1_write(hd, NULL, 0); /* flush */;
+  _gcry_md_block_write (hd, NULL, 0); /* flush */;
 
-  t = hd->nblocks;
+  t = hd->bctx.nblocks;
   /* multiply by 64 to make a byte count */
   lsb = t << 6;
   msb = t >> 26;
   /* add the count */
   t = lsb;
-  if( (lsb += hd->count) < t )
+  if( (lsb += hd->bctx.count) < t )
     msb++;
   /* multiply by 8 to make a bit count */
   t = lsb;
@@ -307,33 +258,33 @@ sha1_final(void *context)
   msb <<= 3;
   msb |= t >> 29;
 
-  if( hd->count < 56 )  /* enough room */
+  if( hd->bctx.count < 56 )  /* enough room */
     {
-      hd->buf[hd->count++] = 0x80; /* pad */
-      while( hd->count < 56 )
-        hd->buf[hd->count++] = 0;  /* pad */
+      hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */
+      while( hd->bctx.count < 56 )
+        hd->bctx.buf[hd->bctx.count++] = 0;  /* pad */
     }
   else  /* need one extra block */
     {
-      hd->buf[hd->count++] = 0x80; /* pad character */
-      while( hd->count < 64 )
-        hd->buf[hd->count++] = 0;
-      sha1_write(hd, NULL, 0);  /* flush */;
-      memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+      hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */
+      while( hd->bctx.count < 64 )
+        hd->bctx.buf[hd->bctx.count++] = 0;
+      _gcry_md_block_write(hd, NULL, 0);  /* flush */;
+      memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */
     }
   /* append the 64 bit count */
-  hd->buf[56] = msb >> 24;
-  hd->buf[57] = msb >> 16;
-  hd->buf[58] = msb >>  8;
-  hd->buf[59] = msb	   ;
-  hd->buf[60] = lsb >> 24;
-  hd->buf[61] = lsb >> 16;
-  hd->buf[62] = lsb >>  8;
-  hd->buf[63] = lsb	   ;
-  TRANSFORM( hd, hd->buf, 1 );
+  hd->bctx.buf[56] = msb >> 24;
+  hd->bctx.buf[57] = msb >> 16;
+  hd->bctx.buf[58] = msb >>  8;
+  hd->bctx.buf[59] = msb	   ;
+  hd->bctx.buf[60] = lsb >> 24;
+  hd->bctx.buf[61] = lsb >> 16;
+  hd->bctx.buf[62] = lsb >>  8;
+  hd->bctx.buf[63] = lsb	   ;
+  transform( hd, hd->bctx.buf );
   _gcry_burn_stack (88+4*sizeof(void*));
 
-  p = hd->buf;
+  p = hd->bctx.buf;
 #ifdef WORDS_BIGENDIAN
 #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0)
 #else /* little endian */
@@ -354,7 +305,7 @@ sha1_read( void *context )
 {
   SHA1_CONTEXT *hd = context;
 
-  return hd->buf;
+  return hd->bctx.buf;
 }
 
 /****************
@@ -367,9 +318,9 @@ _gcry_sha1_hash_buffer (void *outbuf, const void *buffer, size_t length)
   SHA1_CONTEXT hd;
 
   sha1_init (&hd);
-  sha1_write (&hd, buffer, length);
+  _gcry_md_block_write (&hd, buffer, length);
   sha1_final (&hd);
-  memcpy (outbuf, hd.buf, 20);
+  memcpy (outbuf, hd.bctx.buf, 20);
 }
 
 
@@ -468,7 +419,7 @@ static gcry_md_oid_spec_t oid_spec_sha1[] =
 gcry_md_spec_t _gcry_digest_spec_sha1 =
   {
     "SHA1", asn, DIM (asn), oid_spec_sha1, 20,
-    sha1_init, sha1_write, sha1_final, sha1_read,
+    sha1_init, _gcry_md_block_write, sha1_final, sha1_read,
     sizeof (SHA1_CONTEXT)
   };
 md_extra_spec_t _gcry_digest_extraspec_sha1 =
diff --git a/cipher/sha256.c b/cipher/sha256.c
index 309fa3b..1785699 100644
--- a/cipher/sha256.c
+++ b/cipher/sha256.c
@@ -46,12 +46,12 @@
 #include "hash-common.h"
 
 typedef struct {
+  gcry_md_block_ctx_t bctx;
   u32  h0,h1,h2,h3,h4,h5,h6,h7;
-  u32  nblocks;
-  byte buf[64];
-  int  count;
 } SHA256_CONTEXT;
 
+static void
+transform (void *c, const unsigned char *data);
 
 static void
 sha256_init (void *context)
@@ -67,8 +67,11 @@ sha256_init (void *context)
   hd->h6 = 0x1f83d9ab;
   hd->h7 = 0x5be0cd19;
 
-  hd->nblocks = 0;
-  hd->count = 0;
+  hd->bctx.nblocks = 0;
+  hd->bctx.count = 0;
+  hd->bctx.blocksize = 64;
+  hd->bctx.stack_burn = 74*4+32;
+  hd->bctx.bwrite = transform;
 }
 
 
@@ -86,8 +89,11 @@ sha224_init (void *context)
   hd->h6 = 0x64f98fa7;
   hd->h7 = 0xbefa4fa4;
 
-  hd->nblocks = 0;
-  hd->count = 0;
+  hd->bctx.nblocks = 0;
+  hd->bctx.count = 0;
+  hd->bctx.blocksize = 64;
+  hd->bctx.stack_burn = 74*4+32;
+  hd->bctx.bwrite = transform;
 }
 
 
@@ -140,8 +146,9 @@ Sum1 (u32 x)
 
 
 static void
-transform (SHA256_CONTEXT *hd, const unsigned char *data)
+transform (void *ctx, const unsigned char *data)
 {
+  SHA256_CONTEXT *hd = ctx;
   static const u32 K[64] = {
     0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
     0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
@@ -260,46 +267,6 @@ transform (SHA256_CONTEXT *hd, const unsigned char *data)
 #undef R
 
 
-/* Update the message digest with the contents of INBUF with length
-  INLEN.  */
-static void
-sha256_write (void *context, const void *inbuf_arg, size_t inlen)
-{
-  const unsigned char *inbuf = inbuf_arg;
-  SHA256_CONTEXT *hd = context;
-
-  if (hd->count == 64)
-    { /* flush the buffer */
-      transform (hd, hd->buf);
-      _gcry_burn_stack (74*4+32);
-      hd->count = 0;
-      hd->nblocks++;
-    }
-  if (!inbuf)
-    return;
-  if (hd->count)
-    {
-      for (; inlen && hd->count < 64; inlen--)
-        hd->buf[hd->count++] = *inbuf++;
-      sha256_write (hd, NULL, 0);
-      if (!inlen)
-        return;
-    }
-
-  while (inlen >= 64)
-    {
-      transform (hd, inbuf);
-      hd->count = 0;
-      hd->nblocks++;
-      inlen -= 64;
-      inbuf += 64;
-    }
-  _gcry_burn_stack (74*4+32);
-  for (; inlen && hd->count < 64; inlen--)
-    hd->buf[hd->count++] = *inbuf++;
-}
-
-
 /*
    The routine finally terminates the computation and returns the
    digest.  The handle is prepared for a new cycle, but adding bytes
@@ -312,15 +279,15 @@ sha256_final(void *context)
   u32 t, msb, lsb;
   byte *p;
 
-  sha256_write (hd, NULL, 0); /* flush */;
+  _gcry_md_block_write (hd, NULL, 0); /* flush */;
 
-  t = hd->nblocks;
+  t = hd->bctx.nblocks;
   /* multiply by 64 to make a byte count */
   lsb = t << 6;
   msb = t >> 26;
   /* add the count */
   t = lsb;
-  if ((lsb += hd->count) < t)
+  if ((lsb += hd->bctx.count) < t)
     msb++;
   /* multiply by 8 to make a bit count */
   t = lsb;
@@ -328,33 +295,33 @@ sha256_final(void *context)
   msb <<= 3;
   msb |= t >> 29;
 
-  if (hd->count < 56)
+  if (hd->bctx.count < 56)
     { /* enough room */
-      hd->buf[hd->count++] = 0x80; /* pad */
-      while (hd->count < 56)
-        hd->buf[hd->count++] = 0;  /* pad */
+      hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */
+      while (hd->bctx.count < 56)
+        hd->bctx.buf[hd->bctx.count++] = 0;  /* pad */
     }
   else
     { /* need one extra block */
-      hd->buf[hd->count++] = 0x80; /* pad character */
-      while (hd->count < 64)
-        hd->buf[hd->count++] = 0;
-      sha256_write (hd, NULL, 0);  /* flush */;
-      memset (hd->buf, 0, 56 ); /* fill next block with zeroes */
+      hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */
+      while (hd->bctx.count < 64)
+        hd->bctx.buf[hd->bctx.count++] = 0;
+      _gcry_md_block_write (hd, NULL, 0);  /* flush */;
+      memset (hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */
     }
   /* append the 64 bit count */
-  hd->buf[56] = msb >> 24;
-  hd->buf[57] = msb >> 16;
-  hd->buf[58] = msb >>  8;
-  hd->buf[59] = msb;
-  hd->buf[60] = lsb >> 24;
-  hd->buf[61] = lsb >> 16;
-  hd->buf[62] = lsb >>  8;
-  hd->buf[63] = lsb;
-  transform (hd, hd->buf);
+  hd->bctx.buf[56] = msb >> 24;
+  hd->bctx.buf[57] = msb >> 16;
+  hd->bctx.buf[58] = msb >>  8;
+  hd->bctx.buf[59] = msb;
+  hd->bctx.buf[60] = lsb >> 24;
+  hd->bctx.buf[61] = lsb >> 16;
+  hd->bctx.buf[62] = lsb >>  8;
+  hd->bctx.buf[63] = lsb;
+  transform (hd, hd->bctx.buf);
   _gcry_burn_stack (74*4+32);
 
-  p = hd->buf;
+  p = hd->bctx.buf;
 #ifdef WORDS_BIGENDIAN
 #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0)
 #else /* little endian */
@@ -377,7 +344,7 @@ sha256_read (void *context)
 {
   SHA256_CONTEXT *hd = context;
 
-  return hd->buf;
+  return hd->bctx.buf;
 }
 
 
@@ -534,7 +501,7 @@ static gcry_md_oid_spec_t oid_spec_sha256[] =
 gcry_md_spec_t _gcry_digest_spec_sha224 =
   {
     "SHA224", asn224, DIM (asn224), oid_spec_sha224, 28,
-    sha224_init, sha256_write, sha256_final, sha256_read,
+    sha224_init, _gcry_md_block_write, sha256_final, sha256_read,
     sizeof (SHA256_CONTEXT)
   };
 md_extra_spec_t _gcry_digest_extraspec_sha224 =
@@ -545,7 +512,7 @@ md_extra_spec_t _gcry_digest_extraspec_sha224 =
 gcry_md_spec_t _gcry_digest_spec_sha256 =
   {
     "SHA256", asn256, DIM (asn256), oid_spec_sha256, 32,
-    sha256_init, sha256_write, sha256_final, sha256_read,
+    sha256_init, _gcry_md_block_write, sha256_final, sha256_read,
     sizeof (SHA256_CONTEXT)
   };
 md_extra_spec_t _gcry_digest_extraspec_sha256 =
diff --git a/cipher/tiger.c b/cipher/tiger.c
index d4ad514..49d3919 100644
--- a/cipher/tiger.c
+++ b/cipher/tiger.c
@@ -27,16 +27,15 @@
 
 #include "g10lib.h"
 #include "cipher.h"
+#include "hash-common.h"
 
 /* We really need a 64 bit type for this code.  */
 #ifdef HAVE_U64_TYPEDEF
 
 typedef struct
 {
+  gcry_md_block_ctx_t bctx;
   u64  a, b, c;
-  byte buf[64];
-  int  count;
-  u32  nblocks;
   int  variant;  /* 0 = old code, 1 = fixed code, 2 - TIGER2.  */
 } TIGER_CONTEXT;
 
@@ -589,6 +588,9 @@ static u64 sbox4[256] = {
 };
 
 static void
+transform ( void *ctx, const unsigned char *data );
+
+static void
 do_init (void *context, int variant)
 {
   TIGER_CONTEXT *hd = context;
@@ -596,8 +598,11 @@ do_init (void *context, int variant)
   hd->a = 0x0123456789abcdefLL;
   hd->b = 0xfedcba9876543210LL;
   hd->c = 0xf096a5b4c3b2e187LL;
-  hd->nblocks = 0;
-  hd->count = 0;
+  hd->bctx.nblocks = 0;
+  hd->bctx.count = 0;
+  hd->bctx.blocksize = 64;
+  hd->bctx.stack_burn = 21*8+11*sizeof(void*);
+  hd->bctx.bwrite = transform;
   hd->variant = variant;
 }
 
@@ -687,8 +692,9 @@ key_schedule( u64 *x )
  * Transform the message DATA which consists of 512 bytes (8 words)
  */
 static void
-transform ( TIGER_CONTEXT *hd, const unsigned char *data )
+transform ( void *ctx, const unsigned char *data )
 {
+  TIGER_CONTEXT *hd = ctx;
   u64 a,b,c,aa,bb,cc;
   u64 x[8];
 #ifdef WORDS_BIGENDIAN
@@ -733,48 +739,6 @@ transform ( TIGER_CONTEXT *hd, const unsigned char *data )
 
 
 
-/* Update the message digest with the contents
- * of INBUF with length INLEN.
- */
-static void
-tiger_write ( void *context, const void *inbuf_arg, size_t inlen)
-{
-  const unsigned char *inbuf = inbuf_arg;
-  TIGER_CONTEXT *hd = context;
-
-  if( hd->count == 64 ) /* flush the buffer */
-    {
-      transform( hd, hd->buf );
-      _gcry_burn_stack (21*8+11*sizeof(void*));
-      hd->count = 0;
-      hd->nblocks++;
-    }
-  if( !inbuf )
-    return;
-  if( hd->count )
-    {
-      for( ; inlen && hd->count < 64; inlen-- )
-        hd->buf[hd->count++] = *inbuf++;
-      tiger_write( hd, NULL, 0 );
-      if( !inlen )
-        return;
-    }
-
-  while( inlen >= 64 )
-    {
-      transform( hd, inbuf );
-      hd->count = 0;
-      hd->nblocks++;
-      inlen -= 64;
-      inbuf += 64;
-    }
-  _gcry_burn_stack (21*8+11*sizeof(void*));
-  for( ; inlen && hd->count < 64; inlen-- )
-    hd->buf[hd->count++] = *inbuf++;
-}
-
-
-
 /* The routine terminates the computation
  */
 static void
@@ -785,15 +749,15 @@ tiger_final( void *context )
   byte *p;
   byte pad = hd->variant == 2? 0x80 : 0x01;
 
-  tiger_write(hd, NULL, 0); /* flush */;
+  _gcry_md_block_write(hd, NULL, 0); /* flush */;
 
-  t = hd->nblocks;
+  t = hd->bctx.nblocks;
   /* multiply by 64 to make a byte count */
   lsb = t << 6;
   msb = t >> 26;
   /* add the count */
   t = lsb;
-  if( (lsb += hd->count) < t )
+  if( (lsb += hd->bctx.count) < t )
     msb++;
   /* multiply by 8 to make a bit count */
   t = lsb;
@@ -801,33 +765,33 @@ tiger_final( void *context )
   msb <<= 3;
   msb |= t >> 29;
 
-  if( hd->count < 56 )  /* enough room */
+  if( hd->bctx.count < 56 )  /* enough room */
     {
-      hd->buf[hd->count++] = pad;
-      while( hd->count < 56 )
-        hd->buf[hd->count++] = 0;  /* pad */
+      hd->bctx.buf[hd->bctx.count++] = pad;
+      while( hd->bctx.count < 56 )
+        hd->bctx.buf[hd->bctx.count++] = 0;  /* pad */
     }
   else  /* need one extra block */
     {
-      hd->buf[hd->count++] = pad; /* pad character */
-      while( hd->count < 64 )
-        hd->buf[hd->count++] = 0;
-      tiger_write(hd, NULL, 0);  /* flush */;
-      memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+      hd->bctx.buf[hd->bctx.count++] = pad; /* pad character */
+      while( hd->bctx.count < 64 )
+        hd->bctx.buf[hd->bctx.count++] = 0;
+      _gcry_md_block_write(hd, NULL, 0);  /* flush */;
+      memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */
     }
   /* append the 64 bit count */
-  hd->buf[56] = lsb	   ;
-  hd->buf[57] = lsb >>  8;
-  hd->buf[58] = lsb >> 16;
-  hd->buf[59] = lsb >> 24;
-  hd->buf[60] = msb	   ;
-  hd->buf[61] = msb >>  8;
-  hd->buf[62] = msb >> 16;
-  hd->buf[63] = msb >> 24;
-  transform( hd, hd->buf );
+  hd->bctx.buf[56] = lsb	   ;
+  hd->bctx.buf[57] = lsb >>  8;
+  hd->bctx.buf[58] = lsb >> 16;
+  hd->bctx.buf[59] = lsb >> 24;
+  hd->bctx.buf[60] = msb	   ;
+  hd->bctx.buf[61] = msb >>  8;
+  hd->bctx.buf[62] = msb >> 16;
+  hd->bctx.buf[63] = msb >> 24;
+  transform( hd, hd->bctx.buf );
   _gcry_burn_stack (21*8+11*sizeof(void*));
 
-  p = hd->buf;
+  p = hd->bctx.buf;
 #ifdef WORDS_BIGENDIAN
 #define X(a) do { *(u64*)p = hd->a ; p += 8; } while(0)
 #else /* little endian */
@@ -861,7 +825,7 @@ tiger_read( void *context )
 {
   TIGER_CONTEXT *hd = context;
 
-  return hd->buf;
+  return hd->bctx.buf;
 }
 
 
@@ -872,7 +836,7 @@ tiger_read( void *context )
 gcry_md_spec_t _gcry_digest_spec_tiger =
   {
     "TIGER192", NULL, 0, NULL, 24,
-    tiger_init, tiger_write, tiger_final, tiger_read,
+    tiger_init, _gcry_md_block_write, tiger_final, tiger_read,
     sizeof (TIGER_CONTEXT)
   };
 
@@ -894,7 +858,7 @@ static gcry_md_oid_spec_t oid_spec_tiger1[] =
 gcry_md_spec_t _gcry_digest_spec_tiger1 =
   {
     "TIGER", asn1, DIM (asn1), oid_spec_tiger1, 24,
-    tiger1_init, tiger_write, tiger_final, tiger_read,
+    tiger1_init, _gcry_md_block_write, tiger_final, tiger_read,
     sizeof (TIGER_CONTEXT)
   };
 
@@ -904,7 +868,7 @@ gcry_md_spec_t _gcry_digest_spec_tiger1 =
 gcry_md_spec_t _gcry_digest_spec_tiger2 =
   {
     "TIGER2", NULL, 0, NULL, 24,
-    tiger2_init, tiger_write, tiger_final, tiger_read,
+    tiger2_init, _gcry_md_block_write, tiger_final, tiger_read,
     sizeof (TIGER_CONTEXT)
   };
 
-- 
1.8.4.rc3




More information about the Gcrypt-devel mailing list