diff options
author | Werner Koch <wk@gnupg.org> | 2016-02-18 17:51:34 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2016-02-19 14:35:29 +0100 |
commit | dfac2b13d0068b2b1b420d77e9771a49964b81c1 (patch) | |
tree | 8e21474b236fc9219450aefb643d6d9116787b1a | |
parent | 4e134b6e77f558730ec1eceb6b816b0bcfd845e9 (diff) | |
download | libgcrypt-dfac2b13d0068b2b1b420d77e9771a49964b81c1.tar.gz |
random: Remove the new API introduced by the new DRBG.
* 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>
-rw-r--r-- | random/drbg.c | 196 | ||||
-rw-r--r-- | random/random.h | 3 | ||||
-rw-r--r-- | src/gcrypt.h.in | 48 | ||||
-rw-r--r-- | src/global.c | 11 |
4 files changed, 180 insertions, 78 deletions
diff --git a/random/drbg.c b/random/drbg.c index 871e4e52..8c9a42e7 100644 --- a/random/drbg.c +++ b/random/drbg.c @@ -48,20 +48,53 @@ * 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. @@ -70,8 +103,8 @@ * ========== * 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 * --------------------------------- @@ -199,6 +232,34 @@ * 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; } diff --git a/random/random.h b/random/random.h index 96239718..2c4f1df6 100644 --- a/random/random.h +++ b/random/random.h @@ -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 { diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 23b09690..f48f04fb 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -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.) */ { diff --git a/src/global.c b/src/global.c index e14d8c44..ffba3254 100644 --- a/src/global.c +++ b/src/global.c @@ -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; |