[PATCH 1/3] Reduce overhead on generic hash write function

Jussi Kivilinna jussi.kivilinna at iki.fi
Thu Mar 21 20:36:20 CET 2019


* cipher/hash-common.c (_gcry_md_block_write): Remove recursive
function call; Use buf_cpy for copying buffers; Burn stack only once.
--

Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
 0 files changed

diff --git a/cipher/hash-common.c b/cipher/hash-common.c
index a750d6443..74675d49f 100644
--- a/cipher/hash-common.c
+++ b/cipher/hash-common.c
@@ -26,6 +26,7 @@
 #endif
 
 #include "g10lib.h"
+#include "bufhelp.h"
 #include "hash-common.h"
 
 
@@ -121,8 +122,10 @@ _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;
   unsigned int stack_burn = 0;
+  unsigned int nburn;
   const unsigned int blocksize = hd->blocksize;
   size_t inblocks;
+  size_t copylen;
 
   if (sizeof(hd->buf) < blocksize)
     BUG();
@@ -130,38 +133,53 @@ _gcry_md_block_write (void *context, const void *inbuf_arg, size_t inlen)
   if (!hd->bwrite)
     return;
 
-  if (hd->count == blocksize)  /* Flush the buffer. */
+  while (hd->count)
     {
-      stack_burn = hd->bwrite (hd, hd->buf, 1);
-      _gcry_burn_stack (stack_burn);
-      stack_burn = 0;
-      hd->count = 0;
-      if (!++hd->nblocks)
-        hd->nblocks_high++;
-    }
-  if (!inbuf)
-    return;
+      if (hd->count == blocksize)  /* Flush the buffer. */
+	{
+	  nburn = hd->bwrite (hd, hd->buf, 1);
+	  stack_burn = nburn > stack_burn ? nburn : stack_burn;
+	  hd->count = 0;
+	  if (!++hd->nblocks)
+	    hd->nblocks_high++;
+	}
+      else
+	{
+	  copylen = inlen;
+	  if (copylen > blocksize - hd->count)
+	    copylen = blocksize - hd->count;
 
-  if (hd->count)
-    {
-      for (; inlen && hd->count < blocksize; inlen--)
-        hd->buf[hd->count++] = *inbuf++;
-      _gcry_md_block_write (hd, NULL, 0);
-      if (!inlen)
-        return;
+	  if (copylen == 0)
+	    break;
+
+	  buf_cpy (&hd->buf[hd->count], inbuf, copylen);
+	  hd->count += copylen;
+	  inbuf += copylen;
+	  inlen -= copylen;
+	}
     }
 
+  if (inlen == 0)
+    return;
+
   if (inlen >= blocksize)
     {
       inblocks = inlen / blocksize;
-      stack_burn = hd->bwrite (hd, inbuf, inblocks);
+      nburn = hd->bwrite (hd, inbuf, inblocks);
+      stack_burn = nburn > stack_burn ? nburn : stack_burn;
       hd->count = 0;
       hd->nblocks_high += (hd->nblocks + inblocks < inblocks);
       hd->nblocks += inblocks;
       inlen -= inblocks * blocksize;
       inbuf += inblocks * blocksize;
     }
-  _gcry_burn_stack (stack_burn);
-  for (; inlen && hd->count < blocksize; inlen--)
-    hd->buf[hd->count++] = *inbuf++;
+
+  if (inlen)
+    {
+      buf_cpy (hd->buf, inbuf, inlen);
+      hd->count = inlen;
+    }
+
+  if (stack_burn > 0)
+    _gcry_burn_stack (stack_burn);
 }




More information about the Gcrypt-devel mailing list