random: Remove the new API introduced by the new DRBG.
authorWerner Koch <wk@gnupg.org>
Thu, 18 Feb 2016 16:51:34 +0000 (17:51 +0100)
committerWerner Koch <wk@gnupg.org>
Fri, 19 Feb 2016 13:35:29 +0000 (14:35 +0100)
* src/gcrypt.h.in (struct gcry_drbg_gen): Move to random/drbg.c.
(struct gcry_drbg_string): Ditto.
(gcry_drbg_string_fill): Ditto.
(gcry_randomize_drbg): Remove.
* random/drbg.c (parse_flag_string): New.
(_gcry_drbg_reinit): Change the way the arguments are passed.
* src/global.c (_gcry_vcontrol) <GCRYCTL_DRBG_REINIT>: Change calling
convention.
--

It does not make sense to extend the API for a somewhat questionable
feature.  For GCRYCTL_DRBG_REINIT we change to use a string with flags
and libgcrypt's native buffer data structure.

NB: GCRYCTL_DRBG_REINIT has not been tested!
Signed-off-by: Werner Koch <wk@gnupg.org>
random/drbg.c
random/random.h
src/gcrypt.h.in
src/global.c

index 871e4e5..8c9a42e 100644 (file)
  * state of the DRBG is zeroized (with two exceptions listed in
  * GCRYCTL_DRBG_SET_ENTROPY).
  *
- * The control request takes the following values which influences how the DRBG
- * is re-initialized:
- *   * u32 flags: This variable specifies the DRBG type to be used for the
- *                 next initialization. If set to 0, the previous DRBG type is
- *                 used for the initialization. The DRBG type is an OR of the
- *                 mandatory flags of the requested DRBG strength and DRBG
- *                 cipher type. Optionally, the prediction resistance flag
- *                 can be ORed into the flags variable. For example:
- *                 - CTR-DRBG with AES-128 without prediction resistance:
- *                     DRBG_CTRAES128
- *                 - HMAC-DRBG with SHA-512 with prediction resistance:
- *                     DRBG_HMACSHA512 | DRBG_PREDICTION_RESIST
- *   * struct gcry_drbg_string *pers: personalization string to be used for
- *                              initialization.
+ * The control request takes the following values which influences how
+ * the DRBG is re-initialized:
+ *
+ *  - const char *flagstr
+
+ *      This variable specifies the DRBG type to be used for the next
+ *     initialization.  If set to NULL, the previous DRBG type is
+ *     used for the initialization.  If not NULL a space separated
+ *     list of tokens with associated flag values is expected which
+ *     are ORed to form the mandatory flags of the requested DRBG
+ *     strength and cipher type.  Optionally, the prediction
+ *     resistance flag can be ORed into the flags variable.
+ *
+ *      | String token | Flag value             |
+ *      |--------------+------------------------|
+ *      | aes          | DRBG_CTRAES            |
+ *      | serpent      | DRBG_CTRSERPENT        |
+ *      | twofish      | DRBG_CTRTWOFISH        |
+ *      | sha1         | DRBG_HASHSHA1          |
+ *      | sha256       | DRBG_HASHSHA256        |
+ *      | sha512       | DRBG_HASHSHA512        |
+ *      | hmac         | DRBG_HMAC              |
+ *      | sym128       | DRBG_SYM128            |
+ *      | sym192       | DRBG_SYM192            |
+ *      | sym256       | DRBG_SYM256            |
+ *      | pr           | DRBG_PREDICTION_RESIST |
+ *
+ *    For example:
+ *
+ *     - CTR-DRBG with AES-128 without prediction resistance:
+ *         "aes sym128"
+ *     - HMAC-DRBG with SHA-512 with prediction resistance:
+ *         "hmac sha512 pr"
+ *
+ *  - gcry_buffer_t *pers
+ *
+ *      NULL terminated array with personalization strings to be used
+ *     for initialization.
+ *
+ *  - int npers
+ *
+ *     Size of PERS.
+ *
+ *  - void *guard
+ *
+ *      A value of NULL must be passed for this.
+ *
  * The variable of flags is independent from the pers/perslen variables. If
  * flags is set to 0 and perslen is set to 0, the current DRBG type is
  * completely reset without using a personalization string.
  * ==========
  * The SP 800-90A DRBG allows the user to specify a personalization string
  * for initialization as well as an additional information string for each
- * random number request. The following code fragments show how a caller
- * uses the kernel crypto API to use the full functionality of the DRBG.
+ * random number request.  The following code fragments show how a caller
+ * uses the API to use the full functionality of the DRBG.
  *
  * Usage without any additional data
  * ---------------------------------
  * Common data structures
  ******************************************************************/
 
+/* DRBG input data structure for DRBG generate with additional information
+ * string */
+struct gcry_drbg_gen
+{
+  unsigned char *outbuf;       /* output buffer for random numbers */
+  unsigned int outlen; /* size of output buffer */
+  struct gcry_drbg_string *addtl;      /* input buffer for
+                                        * additional information string */
+};
+
+
+/*
+ * SP800-90A requires the concatenation of different data. To avoid copying
+ * buffers around or allocate additional memory, the following data structure
+ * is used to point to the original memory with its size. In addition, it
+ * is used to build a linked list. The linked list defines the concatenation
+ * of individual buffers. The order of memory block referenced in that
+ * linked list determines the order of concatenation.
+ */
+struct gcry_drbg_string
+{
+  const unsigned char *buf;
+  size_t len;
+  struct gcry_drbg_string *next;
+};
+
+
+/* (Declared below) */
 struct gcry_drbg_state;
 
 struct gcry_drbg_core
@@ -305,6 +366,69 @@ static gpg_err_code_t gcry_drbg_hmac (struct gcry_drbg_state *drbg,
 #define dbg(x)
 #endif
 
+/*
+ * Parse a string of flags and store the flag values at R_FLAGS.
+ * Return 0 on success.
+ */
+static gpg_err_code_t
+parse_flag_string (const char *string, u32 *r_flags)
+{
+  struct {
+    const char *name;
+    u32 flag;
+  } table[] = {
+    { "aes",     GCRY_DRBG_CTRAES            },
+    { "serpent", GCRY_DRBG_CTRSERPENT        },
+    { "twofish", GCRY_DRBG_CTRTWOFISH        },
+    { "sha1",    GCRY_DRBG_HASHSHA1          },
+    { "sha256",  GCRY_DRBG_HASHSHA256        },
+    { "sha512",  GCRY_DRBG_HASHSHA512        },
+    { "hmac",    GCRY_DRBG_HMAC              },
+    { "sym128",  GCRY_DRBG_SYM128            },
+    { "sym192",  GCRY_DRBG_SYM192            },
+    { "sym256",  GCRY_DRBG_SYM256            },
+    { "pr",      GCRY_DRBG_PREDICTION_RESIST }
+  };
+
+  *r_flags = 0;
+  if (string)
+    {
+      char **tl;
+      const char *s;
+      int i, j;
+
+      tl = _gcry_strtokenize (string, NULL);
+      if (!tl)
+        return gpg_err_code_from_syserror ();
+      for (i=0; (s=tl[i]); i++)
+        {
+          for (j=0; j < DIM (table); j++)
+            if (!strcmp (s, table[j].name))
+              {
+                *r_flags |= table[j].flag;
+                break;
+              }
+          if (!(j < DIM (table)))
+            {
+              xfree (tl);
+              return GPG_ERR_INV_FLAG;
+            }
+        }
+      xfree (tl);
+    }
+
+  return 0;
+}
+
+static inline void
+gcry_drbg_string_fill (struct gcry_drbg_string *string,
+                       const unsigned char *buf, size_t len)
+{
+  string->buf = buf;
+  string->len = len;
+  string->next = NULL;
+}
+
 static inline ushort
 gcry_drbg_statelen (struct gcry_drbg_state *drbg)
 {
@@ -1732,18 +1856,40 @@ _gcry_drbg_init (int full)
  * Re-initialization will be performed in any case regardless whether flags
  * or personalization string are set.
  *
- * If flags == 0, do not change current DRBG
- * If personalization string is NULL or its length is 0, re-initialize without
- * personalization string
+ * If flags is NULL, do not change current DRBG.  If PERS is NULL and
+ * NPERS is 0, re-initialize without personalization string.  If PERS
+ * is not NULL NPERS must be one and PERS and the first ietm from the
+ * bufer is take as personalization string.
  */
 gpg_err_code_t
-_gcry_drbg_reinit (u32 flags, struct gcry_drbg_string *pers)
+_gcry_drbg_reinit (const char *flagstr, gcry_buffer_t *pers, int npers)
 {
-  gpg_err_code_t ret = GPG_ERR_GENERAL;
-  dbg (("DRBG: reinitialize internal DRBG state with flags %u\n", flags));
-  gcry_drbg_lock ();
-  ret = _gcry_drbg_init_internal (flags, pers);
-  gcry_drbg_unlock ();
+  gpg_err_code_t ret;
+  unsigned int flags;
+
+  /* If PERS is not given we expect NPERS to be zero; if given we
+     expect a one-item array.  */
+  if ((!pers && npers) || (pers && npers != 1))
+    return GPG_ERR_INV_ARG;
+
+  ret = parse_flag_string (flagstr, &flags);
+  if (!ret)
+    {
+      dbg (("DRBG: reinitialize internal DRBG state with flags %u\n", flags));
+      gcry_drbg_lock ();
+      if (pers)
+        {
+          struct gcry_drbg_string persbuf;
+
+          gcry_drbg_string_fill
+            (&persbuf, (const unsigned char *)pers[0].data + pers[0].off,
+             pers[0].len);
+          ret = _gcry_drbg_init_internal (flags, &persbuf);
+        }
+      else
+        ret = _gcry_drbg_init_internal (flags, NULL);
+      gcry_drbg_unlock ();
+    }
   return ret;
 }
 
index 9623971..2c4f1df 100644 (file)
@@ -55,7 +55,8 @@ gcry_err_code_t _gcry_random_run_external_test (void *context,
 void            _gcry_random_deinit_external_test (void *context);
 
 /*-- drbg.c --*/
-gpg_err_code_t _gcry_drbg_reinit (u32 flags, struct gcry_drbg_string *pers);
+gpg_err_code_t _gcry_drbg_reinit (const char *flagstr,
+                                  gcry_buffer_t *pers, int npers);
 /* private interfaces for testing of DRBG */
 struct gcry_drbg_test_vector
 {
index 23b0969..f48f04f 100644 (file)
@@ -1722,54 +1722,6 @@ int gcry_is_secure (const void *a) _GCRY_GCC_ATTR_PURE;
 /* Return true if Libgcrypt is in FIPS mode.  */
 #define gcry_fips_mode_active()  !!gcry_control (GCRYCTL_FIPS_MODE_P, 0)
 
-/* DRBG input data structure for DRBG generate with additional information
- * string */
-struct gcry_drbg_gen
-{
-  unsigned char *outbuf;       /* output buffer for random numbers */
-  unsigned int outlen; /* size of output buffer */
-  struct gcry_drbg_string *addtl;      /* input buffer for
-                                        * additional information string */
-};
-
-/*
- * Concatenation Helper and string operation helper
- *
- * SP800-90A requires the concatenation of different data. To avoid copying
- * buffers around or allocate additional memory, the following data structure
- * is used to point to the original memory with its size. In addition, it
- * is used to build a linked list. The linked list defines the concatenation
- * of individual buffers. The order of memory block referenced in that
- * linked list determines the order of concatenation.
- */
-/* DRBG string definition */
-struct gcry_drbg_string
-{
-  const unsigned char *buf;
-  size_t len;
-  struct gcry_drbg_string *next;
-};
-
-static inline void gcry_drbg_string_fill(struct gcry_drbg_string *string,
-                                   const unsigned char *buf, size_t len)
-{
-  string->buf = buf;
-  string->len = len;
-  string->next = NULL;
-}
-
-/* this is a wrapper function for users of libgcrypt */
-static inline void gcry_randomize_drbg(void *outbuf, size_t outlen,
-                                      enum gcry_random_level level,
-                                      struct gcry_drbg_string *addtl)
-{
-  struct gcry_drbg_gen genbuf;
-  genbuf.outbuf = (unsigned char *)outbuf;
-  genbuf.outlen = outlen;
-  genbuf.addtl = addtl;
-  gcry_randomize(&genbuf, 0, level);
-}
-
 
 #if 0 /* (Keep Emacsens' auto-indent happy.) */
 {
index e14d8c4..ffba325 100644 (file)
@@ -657,10 +657,13 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
 
     case GCRYCTL_DRBG_REINIT:
       {
-        u32 flags = va_arg (arg_ptr, u32);
-        struct gcry_drbg_string *pers = va_arg (arg_ptr,
-                                               struct gcry_drbg_string *);
-        rc = _gcry_drbg_reinit(flags, pers);
+        const char *flagstr = va_arg (arg_ptr, const char *);
+        gcry_buffer_t *pers = va_arg (arg_ptr, gcry_buffer_t *);
+        int npers = va_arg (arg_ptr, int);
+        if (va_arg (arg_ptr, void *) || npers < 0)
+          rc = GPG_ERR_INV_ARG;
+        else
+          rc = _gcry_drbg_reinit (flagstr, pers, npers);
       }
       break;