[git] GCRYPT - branch, master, updated. libgcrypt-1.7.3-32-g656395b

by Stephan Mueller cvs at cvs.gnupg.org
Thu Dec 8 09:11:42 CET 2016


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU crypto library".

The branch, master has been updated
       via  656395ba4cf34f42dda3a120bda3ed1220755a3d (commit)
       via  20886fdcb841b0bf89bb1d44303d42f1804e38cb (commit)
       via  227099f179df9dcf083d0ef6be9883c775df0874 (commit)
       via  df8634d8e2b595430dc1e6575a7452c242cffca1 (commit)
       via  677ddf5bbd9c172a72607c7d5d7006907071c2cf (commit)
      from  95bac312644ad45e486c94c2efd25d0748b9a20b (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 656395ba4cf34f42dda3a120bda3ed1220755a3d
Author: Stephan Mueller <smueller at chronox.de>
Date:   Sat Dec 3 19:18:01 2016 +0100

    random: Eliminate unneeded memcpy invocations in the DRBG.
    
    * random/random-drbg.c (drbg_hash): Remove arg 'outval' and return a
    pointer instead.
    (drbg_instantiate): Reduce size of scratchpad.
    (drbg_hmac_update): Avoid use of scratch buffers for the hash.
    (drbg_hmac_generate, drbg_hash_df): Ditto.
    (drbg_hash_process_addtl): Ditto.
    (drbg_hash_hashgen): Ditto.
    (drbg_hash_generate): Ditto.
    
    --
    The gcry_md_read returns a pointer to the hash which can be directly
    used instead of copying it into a scratch buffer. This eliminates a
    number of memcpy invocations for HMAC and Hash DRBG and reduces the
    memory footprint of the Hash DRBG by the block size of the used hash.
    
    The performance increase is between 1 and 3 MB/s depending on the output
    buffer size.
    
    Signed-off-by: Stephan Mueller <smueller at chronox.de>
    
    ChangeLog entries above written by -wk.

diff --git a/random/random-drbg.c b/random/random-drbg.c
index dc8e8f3..e2fe861 100644
--- a/random/random-drbg.c
+++ b/random/random-drbg.c
@@ -374,9 +374,7 @@ static gpg_err_code_t drbg_hmac_init (drbg_state_t drbg);
 static gpg_err_code_t drbg_hmac_setkey (drbg_state_t drbg,
 					const unsigned char *key);
 static void drbg_hash_fini (drbg_state_t drbg);
-static gpg_err_code_t drbg_hash (drbg_state_t drbg,
-                                 unsigned char *outval,
-                                 const drbg_string_t *buf);
+static byte *drbg_hash (drbg_state_t drbg, const drbg_string_t *buf);
 static gpg_err_code_t drbg_sym_init (drbg_state_t drbg);
 static void drbg_sym_fini (drbg_state_t drbg);
 static gpg_err_code_t drbg_sym_setkey (drbg_state_t drbg,
@@ -1042,24 +1040,21 @@ drbg_hmac_update (drbg_state_t drbg, drbg_string_t *seed, int reseed)
   /* we execute two rounds of V/K massaging */
   for (i = 2; 0 < i; i--)
     {
+      byte *retval;
       /* first round uses 0x0, second 0x1 */
       unsigned char prefix = DRBG_PREFIX0;
       if (1 == i)
 	prefix = DRBG_PREFIX1;
       /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
       seed2.buf = &prefix;
-      ret = drbg_hash (drbg, drbg->C, &seed1);
-      if (ret)
-	return ret;
-
-      ret = drbg_hmac_setkey (drbg, drbg->C);
+      retval = drbg_hash (drbg, &seed1);
+      ret = drbg_hmac_setkey (drbg, retval);
       if (ret)
 	return ret;
 
       /* 10.1.2.2 step 2 and 5 -- HMAC for V */
-      ret = drbg_hash (drbg, drbg->V, &cipherin);
-      if (ret)
-	return ret;
+      retval = drbg_hash (drbg, &cipherin);
+      memcpy(drbg->V, retval, drbg_blocklen (drbg));
 
       /* 10.1.2.2 step 3 */
       if (!seed || 0 == seed->len)
@@ -1091,9 +1086,8 @@ drbg_hmac_generate (drbg_state_t drbg, unsigned char *buf, unsigned int buflen,
     {
       unsigned int outlen = 0;
       /* 10.1.2.5 step 4.1 */
-      ret = drbg_hash (drbg, drbg->V, &data);
-      if (ret)
-	return ret;
+      byte *retval = drbg_hash (drbg, &data);
+      memcpy(drbg->V, retval, drbg_blocklen (drbg));
       outlen = (drbg_blocklen (drbg) < (buflen - len)) ?
 	drbg_blocklen (drbg) : (buflen - len);
 
@@ -1137,14 +1131,10 @@ drbg_hash_df (drbg_state_t drbg,
               unsigned char *outval, size_t outlen,
               drbg_string_t *entropy)
 {
-  gpg_err_code_t ret = 0;
   size_t len = 0;
   unsigned char input[5];
-  unsigned char *tmp = drbg->scratchpad + drbg_statelen (drbg);
   drbg_string_t data1;
 
-  memset (tmp, 0, drbg_blocklen (drbg));
-
   /* 10.4.1 step 3 */
   input[0] = 1;
   drbg_cpu_to_be32 ((outlen * 8), &input[1]);
@@ -1158,20 +1148,16 @@ drbg_hash_df (drbg_state_t drbg,
     {
       short blocklen = 0;
       /* 10.4.1 step 4.1 */
-      ret = drbg_hash (drbg, tmp, &data1);
-      if (ret)
-	goto out;
+      byte *retval = drbg_hash (drbg, &data1);
       /* 10.4.1 step 4.2 */
       input[0]++;
       blocklen = (drbg_blocklen (drbg) < (outlen - len)) ?
 	drbg_blocklen (drbg) : (outlen - len);
-      memcpy (outval + len, tmp, blocklen);
+      memcpy (outval + len, retval, blocklen);
       len += blocklen;
     }
 
- out:
-  memset (tmp, 0, drbg_blocklen (drbg));
-  return ret;
+  return 0;
 }
 
 /* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */
@@ -1227,13 +1213,10 @@ drbg_hash_update (drbg_state_t drbg, drbg_string_t *seed, int reseed)
 static gpg_err_code_t
 drbg_hash_process_addtl (drbg_state_t drbg, drbg_string_t *addtl)
 {
-  gpg_err_code_t ret = 0;
   drbg_string_t data1, data2;
   drbg_string_t *data3;
   unsigned char prefix = DRBG_PREFIX2;
-
-  /* this is value w as per documentation */
-  memset (drbg->scratchpad, 0, drbg_blocklen (drbg));
+  byte *retval;
 
   /* 10.1.1.4 step 2 */
   if (!addtl || 0 == addtl->len)
@@ -1247,37 +1230,25 @@ drbg_hash_process_addtl (drbg_state_t drbg, drbg_string_t *addtl)
   data2.next = data3;
   data3->next = NULL;
   /* 10.1.1.4 step 2a -- cipher invocation */
-  ret = drbg_hash (drbg, drbg->scratchpad, &data1);
-  if (ret)
-    goto out;
+  retval = drbg_hash (drbg, &data1);
 
   /* 10.1.1.4 step 2b */
-  drbg_add_buf (drbg->V, drbg_statelen (drbg),
-		drbg->scratchpad, drbg_blocklen (drbg));
+  drbg_add_buf (drbg->V, drbg_statelen (drbg), retval, drbg_blocklen (drbg));
 
- out:
-  memset (drbg->scratchpad, 0, drbg_blocklen (drbg));
-  return ret;
+  return 0;
 }
 
 /*
  * Hashgen defined in 10.1.1.4
  */
 static gpg_err_code_t
-drbg_hash_hashgen (drbg_state_t drbg,
-                   unsigned char *buf, unsigned int buflen)
+drbg_hash_hashgen (drbg_state_t drbg, unsigned char *buf, unsigned int buflen)
 {
-  gpg_err_code_t ret = 0;
   unsigned int len = 0;
   unsigned char *src = drbg->scratchpad;
-  unsigned char *dst = drbg->scratchpad + drbg_statelen (drbg);
   drbg_string_t data;
   unsigned char prefix = DRBG_PREFIX1;
 
-  /* use the scratchpad as a lookaside buffer */
-  memset (src, 0, drbg_statelen (drbg));
-  memset (dst, 0, drbg_blocklen (drbg));
-
   /* 10.1.1.4 step hashgen 2 */
   memcpy (src, drbg->V, drbg_statelen (drbg));
 
@@ -1286,44 +1257,36 @@ drbg_hash_hashgen (drbg_state_t drbg,
     {
       unsigned int outlen = 0;
       /* 10.1.1.4 step hashgen 4.1 */
-      ret = drbg_hash (drbg, dst, &data);
-      if (ret)
-	goto out;
+      byte *retval = drbg_hash (drbg, &data);
       outlen = (drbg_blocklen (drbg) < (buflen - len)) ?
 	drbg_blocklen (drbg) : (buflen - len);
       /* 10.1.1.4 step hashgen 4.2 */
-      memcpy (buf + len, dst, outlen);
+      memcpy (buf + len, retval, outlen);
       len += outlen;
       /* 10.1.1.4 hashgen step 4.3 */
       if (len < buflen)
 	drbg_add_buf (src, drbg_statelen (drbg), &prefix, 1);
     }
 
- out:
-  memset (drbg->scratchpad, 0,
-	  (drbg_statelen (drbg) + drbg_blocklen (drbg)));
-  return ret;
+  memset (drbg->scratchpad, 0, drbg_statelen (drbg));
+  return 0;
 }
 
 /* Generate function for Hash DRBG as defined in 10.1.1.4  */
 static gpg_err_code_t
-drbg_hash_generate (drbg_state_t drbg,
-			 unsigned char *buf, unsigned int buflen,
-			 drbg_string_t *addtl)
+drbg_hash_generate (drbg_state_t drbg, unsigned char *buf, unsigned int buflen,
+		    drbg_string_t *addtl)
 {
-  gpg_err_code_t ret = 0;
+  gpg_err_code_t ret;
   unsigned char prefix = DRBG_PREFIX3;
   drbg_string_t data1, data2;
+  byte *retval;
   union
   {
     unsigned char req[8];
     u64 req_int;
   } u;
 
-  /*
-   * scratchpad usage: drbg_hash_process_addtl uses the scratchpad, but
-   * fully completes before returning. Thus, we can reuse the scratchpad
-   */
   /* 10.1.1.4 step 2 */
   ret = drbg_hash_process_addtl (drbg, addtl);
   if (ret)
@@ -1334,27 +1297,20 @@ drbg_hash_generate (drbg_state_t drbg,
   if (ret)
     return ret;
 
-  /* this is the value H as documented in 10.1.1.4 */
-  memset (drbg->scratchpad, 0, drbg_blocklen (drbg));
   /* 10.1.1.4 step 4 */
   drbg_string_fill (&data1, &prefix, 1);
   drbg_string_fill (&data2, drbg->V, drbg_statelen (drbg));
   data1.next = &data2;
-  ret = drbg_hash (drbg, drbg->scratchpad, &data1);
-  if (ret)
-    goto out;
+
+  /* this is the value H as documented in 10.1.1.4 */
+  retval = drbg_hash (drbg, &data1);
 
   /* 10.1.1.4 step 5 */
-  drbg_add_buf (drbg->V, drbg_statelen (drbg),
-		     drbg->scratchpad, drbg_blocklen (drbg));
-  drbg_add_buf (drbg->V, drbg_statelen (drbg), drbg->C,
-		     drbg_statelen (drbg));
+  drbg_add_buf (drbg->V, drbg_statelen (drbg), retval, drbg_blocklen (drbg));
+  drbg_add_buf (drbg->V, drbg_statelen (drbg), drbg->C, drbg_statelen (drbg));
   u.req_int = be_bswap64 (drbg->reseed_ctr);
-  drbg_add_buf (drbg->V, drbg_statelen (drbg), u.req,
-		     sizeof (u.req));
+  drbg_add_buf (drbg->V, drbg_statelen (drbg), u.req, sizeof (u.req));
 
- out:
-  memset (drbg->scratchpad, 0, drbg_blocklen (drbg));
   return ret;
 }
 
@@ -1699,7 +1655,7 @@ drbg_instantiate (drbg_state_t drbg,
       drbg_blocklen (drbg) +	/* iv */
       drbg_statelen (drbg) + drbg_blocklen (drbg);	/* temp */
   else
-    sb_size = drbg_statelen (drbg) + drbg_blocklen (drbg);
+    sb_size = drbg_statelen (drbg);
 
   if (0 < sb_size)
     {
@@ -2626,8 +2582,8 @@ drbg_hash_fini (drbg_state_t drbg)
   _gcry_md_close (hd);
 }
 
-static gpg_err_code_t
-drbg_hash (drbg_state_t drbg, unsigned char *outval, const drbg_string_t *buf)
+static byte *
+drbg_hash (drbg_state_t drbg, const drbg_string_t *buf)
 {
   gcry_md_hd_t hd = (gcry_md_hd_t)drbg->priv_data;
 
@@ -2635,9 +2591,7 @@ drbg_hash (drbg_state_t drbg, unsigned char *outval, const drbg_string_t *buf)
   for (; NULL != buf; buf = buf->next)
     _gcry_md_write (hd, buf->buf, buf->len);
   _gcry_md_final (hd);
-  memcpy (outval, _gcry_md_read (hd, drbg->core->backend_cipher),
-	  drbg_blocklen (drbg));
-  return 0;
+  return _gcry_md_read (hd, drbg->core->backend_cipher);
 }
 
 static void

commit 20886fdcb841b0bf89bb1d44303d42f1804e38cb
Author: Stephan Mueller <smueller at chronox.de>
Date:   Thu Dec 1 17:15:10 2016 +0100

    random: Add performance improvements for the DRBG.
    
    * random/random-drbg.c (struct drbg_state_ops_s): New function
    pointers 'crypto_init' and 'crypto-fini'.
    (struct drbg_state_s): New fields 'priv_data', 'ctr_handle', and
    'ctr_null'.
    (drbg_hash_init, drbg_hash_fini): New.
    (drbg_hmac_init, drbg_hmac_setkey): New.
    (drbg_sym_fini, drbg_sym_init, drbg_sym_setkey): New.
    (drbg_sym_ctr): New.
    (drbg_ctr_bcc): Set the key.
    (drbg_ctr_df): Ditto.
    (drbg_hmac_update): Ditto.
    (drbg_hmac_generate): Replace drgb_hmac by drbg_hash.
    (drbg_hash_df): Ditto.
    (drbg_hash_process_addtl): Ditto.
    (drbg_hash_hashgen): Ditto.
    (drbg_ctr_update): Rework.
    (drbg_ctr_generate): Rework.
    (drbg_ctr_ops): Init new functions pointers.
    (drbg_uninstantiate): Call fini function.
    (drbg_instantiate): Call init function.
    
    --
    The performance improvements can be categorized as follows:
    
    * Initialize the cipher handle of the backend ciphers once and re-use
      them for subsequent cipher invocations.
    
    * Limit the invocation of setkey to the cases when the key is newly
      created.
    
    * Use the AES CTR mode and rip out the counter maintenance in the DRBG
      code. This allows the use of accelerated CTR AES implementations. To
      use the CTR AES mode, a NULL buffer is created that is used as the
      "plaintext" to the CTR mode, because the DRBG CTR AES operation is the
      result of the encryption of the CTR (i.e. the NULL buffer makes the
      final XOR of the CTR AES mode a noop).
    
    The following timing measurements are made. The measurement do not use a
    precise timing operation and should rather serve as a general hint to
    the performance improvements.
    
     On a Broadwell i7 CPU:
    
    	block size	4096		1024		128		32		16
     aes256 old		28MB/s	27MB/s	19MB/s	11MB/s	6MB/s
     aes128 old		29MB/s	32MB/s	23MB/s	15MB/s	9MB/s
     sha256 old		48MB/s	48MB/s	33MB/s	16MB/s	8MB/s
     hmac sha256 old	15MB/s	15MB/s	10MB/s	5MB/s	2MB/s
    
     aes256 new		180MB/s	169MB/s	93MB/s	37MB/s	20MB/s
     aes128 new		240MB/s	221MB/s	125MB/s	51MB/s	27MB/s
     sha256 new		75MB/s	69MB/s	48MB/s	23MB/s	11MB/s
     hmac sha256 new	37MB/s	34MB/s	21MB/s	8MB/s	4MB/s
    
    Signed-off-by: Stephan Mueller <smueller at chronox.de>
    
    ChnageLog entries above written by -wk

diff --git a/random/random-drbg.c b/random/random-drbg.c
index 9676f0e..dc8e8f3 100644
--- a/random/random-drbg.c
+++ b/random/random-drbg.c
@@ -289,6 +289,8 @@ struct drbg_state_ops_s
   gpg_err_code_t (*generate) (drbg_state_t drbg,
 			      unsigned char *buf, unsigned int buflen,
 			      drbg_string_t *addtl);
+  gpg_err_code_t (*crypto_init) (drbg_state_t drbg);
+  void		 (*crypto_fini) (drbg_state_t drbg);
 };
 
 struct drbg_test_data_s
@@ -309,6 +311,10 @@ struct drbg_state_s
 				 * 10.1.1.1 1c) */
   unsigned char *scratchpad;	/* some memory the DRBG can use for its
 				 * operation -- allocated during init */
+  void *priv_data;		/* Cipher handle */
+  gcry_cipher_hd_t ctr_handle;	/* CTR mode cipher handle */
+#define DRBG_CTR_NULL_LEN 128
+  unsigned char *ctr_null;	/* CTR mode zero buffer */
   int seeded:1;			/* DRBG fully seeded? */
   int pr:1;			/* Prediction resistance enabled? */
   /* Taken from libgcrypt ANSI X9.31 DRNG: We need to keep track of the
@@ -363,14 +369,23 @@ static const struct drbg_core_s drbg_cores[] = {
   {DRBG_CTRAES | DRBG_SYM256, 48, 16, GCRY_CIPHER_AES256}
 };
 
-static gpg_err_code_t drbg_sym (drbg_state_t drbg,
-                                const unsigned char *key,
-                                unsigned char *outval,
-                                const drbg_string_t *buf);
-static gpg_err_code_t drbg_hmac (drbg_state_t drbg,
-                                 const unsigned char *key,
+static gpg_err_code_t drbg_hash_init (drbg_state_t drbg);
+static gpg_err_code_t drbg_hmac_init (drbg_state_t drbg);
+static gpg_err_code_t drbg_hmac_setkey (drbg_state_t drbg,
+					const unsigned char *key);
+static void drbg_hash_fini (drbg_state_t drbg);
+static gpg_err_code_t drbg_hash (drbg_state_t drbg,
                                  unsigned char *outval,
                                  const drbg_string_t *buf);
+static gpg_err_code_t drbg_sym_init (drbg_state_t drbg);
+static void drbg_sym_fini (drbg_state_t drbg);
+static gpg_err_code_t drbg_sym_setkey (drbg_state_t drbg,
+				       const unsigned char *key);
+static gpg_err_code_t drbg_sym (drbg_state_t drbg, unsigned char *outval,
+				const drbg_string_t *buf);
+static gpg_err_code_t drbg_sym_ctr (drbg_state_t drbg,
+			const unsigned char *inbuf, unsigned int inbuflen,
+			unsigned char *outbuf, unsigned int outbuflen);
 
 /******************************************************************
  ******************************************************************
@@ -666,6 +681,10 @@ drbg_ctr_bcc (drbg_state_t drbg,
   /* 10.4.3 step 1 */
   memset (out, 0, drbg_blocklen (drbg));
 
+  ret = drbg_sym_setkey(drbg, key);
+  if (ret)
+    return ret;
+
   /* 10.4.3 step 2 / 4 */
   while (inpos)
     {
@@ -698,7 +717,7 @@ drbg_ctr_bcc (drbg_state_t drbg,
 	    }
 	}
       /* 10.4.3 step 4.2 */
-      ret = drbg_sym (drbg, key, out, &data);
+      ret = drbg_sym (drbg, out, &data);
       if (ret)
 	return ret;
       /* 10.4.3 step 2 */
@@ -839,6 +858,9 @@ drbg_ctr_df (drbg_state_t drbg, unsigned char *df_data,
   /* 10.4.2 step 12: overwriting of outval */
 
   /* 10.4.2 step 13 */
+  ret = drbg_sym_setkey(drbg, temp);
+  if (ret)
+    goto out;
   while (generated_len < bytes_to_return)
     {
       short blocklen = 0;
@@ -846,11 +868,10 @@ drbg_ctr_df (drbg_state_t drbg, unsigned char *df_data,
       /* the truncation of the key length is implicit as the key
        * is only drbg_blocklen in size -- check for the implementation
        * of the cipher function callback */
-      ret = drbg_sym (drbg, temp, X, &cipherin);
+      ret = drbg_sym (drbg, X, &cipherin);
       if (ret)
 	goto out;
-      blocklen = (drbg_blocklen (drbg) <
-		  (bytes_to_return - generated_len)) ?
+      blocklen = (drbg_blocklen (drbg) < (bytes_to_return - generated_len)) ?
 	drbg_blocklen (drbg) : (bytes_to_return - generated_len);
       /* 10.4.2 step 13.2 and 14 */
       memcpy (df_data + generated_len, X, blocklen);
@@ -889,54 +910,51 @@ drbg_ctr_update (drbg_state_t drbg, drbg_string_t *addtl, int reseed)
   unsigned char *temp = drbg->scratchpad;
   unsigned char *df_data = drbg->scratchpad +
     drbg_statelen (drbg) + drbg_blocklen (drbg);
-  unsigned char *temp_p, *df_data_p;	/* pointer to iterate over buffers */
-  unsigned int len = 0;
-  drbg_string_t cipherin;
   unsigned char prefix = DRBG_PREFIX1;
 
   memset (temp, 0, drbg_statelen (drbg) + drbg_blocklen (drbg));
   if (3 > reseed)
     memset (df_data, 0, drbg_statelen (drbg));
 
-  /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
-  if (addtl && 0 < addtl->len)
+  if (!reseed)
     {
-      ret =
-	drbg_ctr_df (drbg, df_data, drbg_statelen (drbg), addtl);
+      /*
+       * The DRBG uses the CTR mode of the underlying AES cipher. The
+       * CTR mode increments the counter value after the AES operation
+       * but SP800-90A requires that the counter is incremented before
+       * the AES operation. Hence, we increment it at the time we set
+       * it by one.
+       */
+      drbg_add_buf (drbg->V, drbg_blocklen (drbg), &prefix, 1);
+
+      ret = _gcry_cipher_setkey (drbg->ctr_handle, drbg->C, drbg_keylen (drbg));
       if (ret)
-	goto out;
+        goto out;
     }
 
-  drbg_string_fill (&cipherin, drbg->V, drbg_blocklen (drbg));
-  /* 10.2.1.3.2 step 2 and 3 -- are already covered as we memset(0)
-   * all memory during initialization */
-  while (len < (drbg_statelen (drbg)))
+  /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
+  if (addtl && 0 < addtl->len)
     {
-      /* 10.2.1.2 step 2.1 */
-      drbg_add_buf (drbg->V, drbg_blocklen (drbg), &prefix, 1);
-      /* 10.2.1.2 step 2.2 */
-      /* using target of temp + len: 10.2.1.2 step 2.3 and 3 */
-      ret = drbg_sym (drbg, drbg->C, temp + len, &cipherin);
+      ret =
+	drbg_ctr_df (drbg, df_data, drbg_statelen (drbg), addtl);
       if (ret)
 	goto out;
-      /* 10.2.1.2 step 2.3 and 3 */
-      len += drbg_blocklen (drbg);
     }
 
-  /* 10.2.1.2 step 4 */
-  temp_p = temp;
-  df_data_p = df_data;
-  for (len = 0; len < drbg_statelen (drbg); len++)
-    {
-      *temp_p ^= *df_data_p;
-      df_data_p++;
-      temp_p++;
-    }
+  ret = drbg_sym_ctr (drbg, df_data, drbg_statelen(drbg),
+		      temp, drbg_statelen(drbg));
+  if (ret)
+    goto out;
 
   /* 10.2.1.2 step 5 */
-  memcpy (drbg->C, temp, drbg_keylen (drbg));
+  ret = _gcry_cipher_setkey (drbg->ctr_handle, temp, drbg_keylen (drbg));
+  if (ret)
+    goto out;
+
   /* 10.2.1.2 step 6 */
   memcpy (drbg->V, temp + drbg_keylen (drbg), drbg_blocklen (drbg));
+  /* See above: increment counter by one to compensate timing of CTR op */
+  drbg_add_buf (drbg->V, drbg_blocklen (drbg), &prefix, 1);
   ret = 0;
 
  out:
@@ -957,9 +975,6 @@ drbg_ctr_generate (drbg_state_t drbg,
                    drbg_string_t *addtl)
 {
   gpg_err_code_t ret = 0;
-  unsigned int len = 0;
-  drbg_string_t data;
-  unsigned char prefix = DRBG_PREFIX1;
 
   memset (drbg->scratchpad, 0, drbg_blocklen (drbg));
 
@@ -973,24 +988,9 @@ drbg_ctr_generate (drbg_state_t drbg,
     }
 
   /* 10.2.1.5.2 step 4.1 */
-  drbg_add_buf (drbg->V, drbg_blocklen (drbg), &prefix, 1);
-  drbg_string_fill (&data, drbg->V, drbg_blocklen (drbg));
-  while (len < buflen)
-    {
-      unsigned int outlen = 0;
-      /* 10.2.1.5.2 step 4.2 */
-      ret = drbg_sym (drbg, drbg->C, drbg->scratchpad, &data);
-      if (ret)
-	goto out;
-      outlen = (drbg_blocklen (drbg) < (buflen - len)) ?
-	drbg_blocklen (drbg) : (buflen - len);
-      /* 10.2.1.5.2 step 4.3 */
-      memcpy (buf + len, drbg->scratchpad, outlen);
-      len += outlen;
-      /* 10.2.1.5.2 step 6 */
-      if (len < buflen)
-	drbg_add_buf (drbg->V, drbg_blocklen (drbg), &prefix, 1);
-    }
+  ret = drbg_sym_ctr (drbg, drbg->ctr_null, DRBG_CTR_NULL_LEN, buf, buflen);
+  if (ret)
+    goto out;
 
   /* 10.2.1.5.2 step 6 */
   if (addtl)
@@ -998,13 +998,14 @@ drbg_ctr_generate (drbg_state_t drbg,
   ret = drbg_ctr_update (drbg, addtl, 3);
 
  out:
-  memset (drbg->scratchpad, 0, drbg_blocklen (drbg));
   return ret;
 }
 
 static struct drbg_state_ops_s drbg_ctr_ops = {
   drbg_ctr_update,
-  drbg_ctr_generate
+  drbg_ctr_generate,
+  drbg_sym_init,
+  drbg_sym_fini,
 };
 
 /******************************************************************
@@ -1023,6 +1024,9 @@ drbg_hmac_update (drbg_state_t drbg, drbg_string_t *seed, int reseed)
       /* 10.1.2.3 step 2 already implicitly covered with
        * the initial memset(0) of drbg->C */
       memset (drbg->V, 1, drbg_statelen (drbg));
+      ret = drbg_hmac_setkey (drbg, drbg->C);
+      if (ret)
+	return ret;
     }
 
   /* build linked list which implements the concatenation and fill
@@ -1044,12 +1048,16 @@ drbg_hmac_update (drbg_state_t drbg, drbg_string_t *seed, int reseed)
 	prefix = DRBG_PREFIX1;
       /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
       seed2.buf = &prefix;
-      ret = drbg_hmac (drbg, drbg->C, drbg->C, &seed1);
+      ret = drbg_hash (drbg, drbg->C, &seed1);
+      if (ret)
+	return ret;
+
+      ret = drbg_hmac_setkey (drbg, drbg->C);
       if (ret)
 	return ret;
 
       /* 10.1.2.2 step 2 and 5 -- HMAC for V */
-      ret = drbg_hmac (drbg, drbg->C, drbg->V, &cipherin);
+      ret = drbg_hash (drbg, drbg->V, &cipherin);
       if (ret)
 	return ret;
 
@@ -1083,7 +1091,7 @@ drbg_hmac_generate (drbg_state_t drbg, unsigned char *buf, unsigned int buflen,
     {
       unsigned int outlen = 0;
       /* 10.1.2.5 step 4.1 */
-      ret = drbg_hmac (drbg, drbg->C, drbg->V, &data);
+      ret = drbg_hash (drbg, drbg->V, &data);
       if (ret)
 	return ret;
       outlen = (drbg_blocklen (drbg) < (buflen - len)) ?
@@ -1104,7 +1112,9 @@ drbg_hmac_generate (drbg_state_t drbg, unsigned char *buf, unsigned int buflen,
 
 static struct drbg_state_ops_s drbg_hmac_ops = {
   drbg_hmac_update,
-  drbg_hmac_generate
+  drbg_hmac_generate,
+  drbg_hmac_init,
+  drbg_hash_fini,
 };
 
 /******************************************************************
@@ -1148,7 +1158,7 @@ drbg_hash_df (drbg_state_t drbg,
     {
       short blocklen = 0;
       /* 10.4.1 step 4.1 */
-      ret = drbg_hmac (drbg, NULL, tmp, &data1);
+      ret = drbg_hash (drbg, tmp, &data1);
       if (ret)
 	goto out;
       /* 10.4.1 step 4.2 */
@@ -1237,13 +1247,13 @@ drbg_hash_process_addtl (drbg_state_t drbg, drbg_string_t *addtl)
   data2.next = data3;
   data3->next = NULL;
   /* 10.1.1.4 step 2a -- cipher invocation */
-  ret = drbg_hmac (drbg, NULL, drbg->scratchpad, &data1);
+  ret = drbg_hash (drbg, drbg->scratchpad, &data1);
   if (ret)
     goto out;
 
   /* 10.1.1.4 step 2b */
   drbg_add_buf (drbg->V, drbg_statelen (drbg),
-		     drbg->scratchpad, drbg_blocklen (drbg));
+		drbg->scratchpad, drbg_blocklen (drbg));
 
  out:
   memset (drbg->scratchpad, 0, drbg_blocklen (drbg));
@@ -1276,7 +1286,7 @@ drbg_hash_hashgen (drbg_state_t drbg,
     {
       unsigned int outlen = 0;
       /* 10.1.1.4 step hashgen 4.1 */
-      ret = drbg_hmac (drbg, NULL, dst, &data);
+      ret = drbg_hash (drbg, dst, &data);
       if (ret)
 	goto out;
       outlen = (drbg_blocklen (drbg) < (buflen - len)) ?
@@ -1330,7 +1340,7 @@ drbg_hash_generate (drbg_state_t drbg,
   drbg_string_fill (&data1, &prefix, 1);
   drbg_string_fill (&data2, drbg->V, drbg_statelen (drbg));
   data1.next = &data2;
-  ret = drbg_hmac (drbg, NULL, drbg->scratchpad, &data1);
+  ret = drbg_hash (drbg, drbg->scratchpad, &data1);
   if (ret)
     goto out;
 
@@ -1354,7 +1364,9 @@ drbg_hash_generate (drbg_state_t drbg,
  */
 static struct drbg_state_ops_s drbg_hash_ops = {
   drbg_hash_update,
-  drbg_hash_generate
+  drbg_hash_generate,
+  drbg_hash_init,
+  drbg_hash_fini,
 };
 
 /******************************************************************
@@ -1599,6 +1611,7 @@ drbg_uninstantiate (drbg_state_t drbg)
 {
   if (!drbg)
     return GPG_ERR_INV_ARG;
+  drbg->d_ops->crypto_fini(drbg);
   xfree (drbg->V);
   drbg->V = NULL;
   xfree (drbg->C);
@@ -1666,13 +1679,16 @@ drbg_instantiate (drbg_state_t drbg,
 
   /* 9.1 step 4 is implicit in  drbg_sec_strength */
 
-  /* no allocation of drbg as this is done by the kernel crypto API */
+  ret = drbg->d_ops->crypto_init(drbg);
+  if (ret)
+    goto err;
+
   drbg->V = xcalloc_secure (1, drbg_statelen (drbg));
   if (!drbg->V)
-    goto err;
+    goto fini;
   drbg->C = xcalloc_secure (1, drbg_statelen (drbg));
   if (!drbg->C)
-    goto err;
+    goto fini;
   /* scratchpad is only generated for CTR and Hash */
   if (drbg->core->flags & DRBG_HMAC)
     sb_size = 0;
@@ -1689,19 +1705,21 @@ drbg_instantiate (drbg_state_t drbg,
     {
       drbg->scratchpad = xcalloc_secure (1, sb_size);
       if (!drbg->scratchpad)
-	goto err;
+	goto fini;
     }
   dbg (("DRBG: state allocated with scratchpad size %u bytes\n", sb_size));
 
   /* 9.1 step 6 through 11 */
   ret = drbg_seed (drbg, pers, 0);
   if (ret)
-    goto err;
+    goto fini;
 
   dbg (("DRBG: core %d %s prediction resistance successfully initialized\n",
 	coreref, pr ? "with" : "without"));
   return 0;
 
+ fini:
+  drbg->d_ops->crypto_fini(drbg);
  err:
   drbg_uninstantiate (drbg);
   return ret;
@@ -2563,59 +2581,160 @@ _gcry_rngdrbg_selftest (selftest_report_func_t report)
  ***************************************************************/
 
 static gpg_err_code_t
-drbg_hmac (drbg_state_t drbg, const unsigned char *key,
-		unsigned char *outval, const drbg_string_t *buf)
+drbg_hash_init (drbg_state_t drbg)
 {
+  gcry_md_hd_t hd;
   gpg_error_t err;
+
+  err = _gcry_md_open (&hd, drbg->core->backend_cipher, 0);
+  if (err)
+    return err;
+
+  drbg->priv_data = hd;
+
+  return 0;
+}
+
+static gpg_err_code_t
+drbg_hmac_init (drbg_state_t drbg)
+{
   gcry_md_hd_t hd;
+  gpg_error_t err;
 
-  if (key)
-    {
-      err =
-	_gcry_md_open (&hd, drbg->core->backend_cipher, GCRY_MD_FLAG_HMAC);
-      if (err)
-	return err;
-      err = _gcry_md_setkey (hd, key, drbg_statelen (drbg));
-      if (err)
-	return err;
-    }
-  else
-    {
-      err = _gcry_md_open (&hd, drbg->core->backend_cipher, 0);
-      if (err)
-	return err;
-    }
+  err = _gcry_md_open (&hd, drbg->core->backend_cipher, GCRY_MD_FLAG_HMAC);
+  if (err)
+    return err;
+
+  drbg->priv_data = hd;
+
+  return 0;
+}
+
+static gpg_err_code_t
+drbg_hmac_setkey (drbg_state_t drbg, const unsigned char *key)
+{
+  gcry_md_hd_t hd = (gcry_md_hd_t)drbg->priv_data;
+
+  return _gcry_md_setkey (hd, key, drbg_statelen (drbg));
+}
+
+static void
+drbg_hash_fini (drbg_state_t drbg)
+{
+  gcry_md_hd_t hd = (gcry_md_hd_t)drbg->priv_data;
+
+  _gcry_md_close (hd);
+}
+
+static gpg_err_code_t
+drbg_hash (drbg_state_t drbg, unsigned char *outval, const drbg_string_t *buf)
+{
+  gcry_md_hd_t hd = (gcry_md_hd_t)drbg->priv_data;
+
+  _gcry_md_reset(hd);
   for (; NULL != buf; buf = buf->next)
     _gcry_md_write (hd, buf->buf, buf->len);
   _gcry_md_final (hd);
   memcpy (outval, _gcry_md_read (hd, drbg->core->backend_cipher),
 	  drbg_blocklen (drbg));
-  _gcry_md_close (hd);
   return 0;
 }
 
+static void
+drbg_sym_fini (drbg_state_t drbg)
+{
+  gcry_cipher_hd_t hd = (gcry_cipher_hd_t)drbg->priv_data;
+
+  if (hd)
+    _gcry_cipher_close (hd);
+  if (drbg->ctr_handle)
+    _gcry_cipher_close (drbg->ctr_handle);
+  if (drbg->ctr_null)
+    free(drbg->ctr_null);
+}
+
 static gpg_err_code_t
-drbg_sym (drbg_state_t drbg, const unsigned char *key,
-          unsigned char *outval, const drbg_string_t *buf)
+drbg_sym_init (drbg_state_t drbg)
 {
-  gpg_error_t err;
   gcry_cipher_hd_t hd;
+  gpg_error_t err;
+
+  drbg->ctr_null = calloc(1, DRBG_CTR_NULL_LEN);
+  if (!drbg->ctr_null)
+    return GPG_ERR_ENOMEM;
 
   err = _gcry_cipher_open (&hd, drbg->core->backend_cipher,
-                           GCRY_CIPHER_MODE_ECB, 0);
+			   GCRY_CIPHER_MODE_ECB, 0);
   if (err)
-    return err;
+    {
+      drbg_sym_fini (drbg);
+      return err;
+    }
+  drbg->priv_data = hd;
+
+  err = _gcry_cipher_open (&drbg->ctr_handle, drbg->core->backend_cipher,
+			   GCRY_CIPHER_MODE_CTR, 0);
+  if (err)
+    {
+      drbg_sym_fini (drbg);
+      return err;
+    }
+
+
   if (drbg_blocklen (drbg) !=
       _gcry_cipher_get_algo_blklen (drbg->core->backend_cipher))
-    return -GPG_ERR_NO_ERROR;
+    {
+      drbg_sym_fini (drbg);
+      return -GPG_ERR_NO_ERROR;
+    }
+
+  return 0;
+}
+
+static gpg_err_code_t
+drbg_sym_setkey (drbg_state_t drbg, const unsigned char *key)
+{
+  gcry_cipher_hd_t hd = (gcry_cipher_hd_t)drbg->priv_data;
+
+  return _gcry_cipher_setkey (hd, key, drbg_keylen (drbg));
+}
+
+static gpg_err_code_t
+drbg_sym (drbg_state_t drbg, unsigned char *outval, const drbg_string_t *buf)
+{
+  gcry_cipher_hd_t hd = (gcry_cipher_hd_t)drbg->priv_data;
+
+  _gcry_cipher_reset(hd);
   if (drbg_blocklen (drbg) < buf->len)
     return -GPG_ERR_NO_ERROR;
-  err = _gcry_cipher_setkey (hd, key, drbg_keylen (drbg));
+  /* in is only component */
+  return _gcry_cipher_encrypt (hd, outval, drbg_blocklen (drbg), buf->buf,
+			       buf->len);
+}
+
+static gpg_err_code_t
+drbg_sym_ctr (drbg_state_t drbg,
+	      const unsigned char *inbuf, unsigned int inbuflen,
+	      unsigned char *outbuf, unsigned int outbuflen)
+{
+  gpg_error_t err;
+
+  _gcry_cipher_reset(drbg->ctr_handle);
+  err = _gcry_cipher_setctr(drbg->ctr_handle, drbg->V, drbg_blocklen (drbg));
   if (err)
     return err;
-  /* in is only component */
-  _gcry_cipher_encrypt (hd, outval, drbg_blocklen (drbg), buf->buf,
-			buf->len);
-  _gcry_cipher_close (hd);
-  return 0;
+
+  while (outbuflen)
+    {
+       unsigned int cryptlen = (inbuflen > outbuflen) ? outbuflen : inbuflen;
+
+       err = _gcry_cipher_encrypt (drbg->ctr_handle, outbuf, cryptlen, inbuf,
+				   cryptlen);
+       if (err)
+         return err;
+
+       outbuflen -= cryptlen;
+       outbuf += cryptlen;
+    }
+  return _gcry_cipher_getctr(drbg->ctr_handle, drbg->V, drbg_blocklen (drbg));
 }

commit 227099f179df9dcf083d0ef6be9883c775df0874
Author: Stephan Mueller <smueller at chronox.de>
Date:   Thu Dec 1 17:11:42 2016 +0100

    cipher: New function for reading the counter in CTR mode
    
    * cipher/cipher.c (gcry_cipher_getctr): New.
    --
    The API call allows reading the current counter of the CTR mode. The API
    remains internal to libgcrypt and is not exported to external callers.
    
    Signed-off-by: Stephan Mueller <smueller at chronox.de>
    
    ChangeLog entry above added by -wk

diff --git a/cipher/cipher.c b/cipher/cipher.c
index ff3340f..55853da 100644
--- a/cipher/cipher.c
+++ b/cipher/cipher.c
@@ -1117,6 +1117,16 @@ _gcry_cipher_setctr (gcry_cipher_hd_t hd, const void *ctr, size_t ctrlen)
   return 0;
 }
 
+gpg_err_code_t
+_gcry_cipher_getctr (gcry_cipher_hd_t hd, void *ctr, size_t ctrlen)
+{
+  if (ctr && ctrlen == hd->spec->blocksize)
+    memcpy (ctr, hd->u_ctr.ctr, hd->spec->blocksize);
+  else
+    return GPG_ERR_INV_ARG;
+
+  return 0;
+}
 
 gcry_err_code_t
 _gcry_cipher_authenticate (gcry_cipher_hd_t hd, const void *abuf,
diff --git a/src/gcrypt-int.h b/src/gcrypt-int.h
index 729f54a..ef5337b 100644
--- a/src/gcrypt-int.h
+++ b/src/gcrypt-int.h
@@ -77,6 +77,8 @@ gpg_err_code_t _gcry_cipher_checktag (gcry_cipher_hd_t hd, const void *intag,
                                       size_t taglen);
 gpg_err_code_t _gcry_cipher_setctr (gcry_cipher_hd_t hd,
                                     const void *ctr, size_t ctrlen);
+gpg_err_code_t _gcry_cipher_getctr (gcry_cipher_hd_t hd,
+                                    void *ctr, size_t ctrlen);
 size_t _gcry_cipher_get_algo_keylen (int algo);
 size_t _gcry_cipher_get_algo_blklen (int algo);
 

commit df8634d8e2b595430dc1e6575a7452c242cffca1
Author: Stephan Mueller <smueller at chronox.de>
Date:   Sun Nov 27 10:14:21 2016 +0100

    doc: Remove comment that is not applicable any more.
    
    --
    Signed-off-by: Stephan Mueller <smueller at chronox.de>

diff --git a/random/random-drbg.c b/random/random-drbg.c
index f9d11a3..9676f0e 100644
--- a/random/random-drbg.c
+++ b/random/random-drbg.c
@@ -899,8 +899,6 @@ drbg_ctr_update (drbg_state_t drbg, drbg_string_t *addtl, int reseed)
     memset (df_data, 0, drbg_statelen (drbg));
 
   /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
-  /* TODO use reseed variable to avoid re-doing DF operation */
-  (void) reseed;
   if (addtl && 0 < addtl->len)
     {
       ret =

commit 677ddf5bbd9c172a72607c7d5d7006907071c2cf
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Dec 7 18:55:06 2016 +0100

    doc: Update NEWS.
    
    --

diff --git a/NEWS b/NEWS
index 0aaf863..722172a 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,14 @@ Noteworthy changes in version 1.8.0 (unreleased)  [C21/A1/R_]
      blocking read of /dev/random.  This allows other nPth threads to
      run while Libgcrypt is gathering entropy.
 
+   - When secure memory is requested by the MPI functions or by
+     gcry_xmalloc_secure, they do not anymore lead to a fatal error if
+     the secure memory pool is used up.  Instead new pools are
+     allocated as needed.  These new pools are not protected against
+     being swapped out (mlock can't be used).  However, these days
+     this is considered a minor issue and can easily be mitigated by
+     using encrypted swap space.
+
 
  * Interface changes relative to the 1.6.0 release:
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

-----------------------------------------------------------------------

Summary of changes:
 NEWS                 |   8 +
 cipher/cipher.c      |  10 ++
 random/random-drbg.c | 421 ++++++++++++++++++++++++++++++---------------------
 src/gcrypt-int.h     |   2 +
 4 files changed, 266 insertions(+), 175 deletions(-)


hooks/post-receive
-- 
The GNU crypto library
http://git.gnupg.org


_______________________________________________
Gnupg-commits mailing list
Gnupg-commits at gnupg.org
http://lists.gnupg.org/mailman/listinfo/gnupg-commits




More information about the Gcrypt-devel mailing list