/* random-drbg.c - Deterministic Random Bits Generator * Copyright 2014 Stephan Mueller * * DRBG: Deterministic Random Bits Generator * Based on NIST Recommended DRBG from NIST SP800-90A with the following * properties: * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores * * with and without prediction resistance * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, and the entire permission notice in its entirety, * including the disclaimer of warranties. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * ALTERNATIVELY, this product may be distributed under the terms of * LGPLv2+, in which case the provisions of the LGPL are * required INSTEAD OF the above restrictions. (This clause is * necessary due to a potential bad interaction between the LGPL and * the restrictions contained in a BSD-style copyright.) * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * * gcry_control GCRYCTL_DRBG_REINIT * ================================ * This control request re-initializes the DRBG completely, i.e. the entire * 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: * * - 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. * * DRBG Usage * ========== * 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 API to use the full functionality of the DRBG. * * Usage without any additional data * --------------------------------- * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); * * * Usage with personalization string during initialization * ------------------------------------------------------- * drbg_string_t pers; * char personalization[11] = "some-string"; * * drbg_string_fill(&pers, personalization, strlen(personalization)); * // The reset completely re-initializes the DRBG with the provided * // personalization string without changing the DRBG type * ret = gcry_control(GCRYCTL_DRBG_REINIT, 0, &pers); * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); * * * Usage with additional information string during random number request * --------------------------------------------------------------------- * drbg_string_t addtl; * char addtl_string[11] = "some-string"; * * drbg_string_fill(&addtl, addtl_string, strlen(addtl_string)); * // The following call is a wrapper to gcry_randomize() and returns * // the same error codes. * gcry_randomize_drbg(outbuf, OUTLEN, GCRY_STRONG_RANDOM, &addtl); * * * Usage with personalization and additional information strings * ------------------------------------------------------------- * Just mix both scenarios above. * * * Switch the DRBG type to some other type * --------------------------------------- * // Switch to CTR DRBG AES-128 without prediction resistance * ret = gcry_control(GCRYCTL_DRBG_REINIT, DRBG_NOPR_CTRAES128, NULL); * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); */ #include #include #include #include #include "g10lib.h" #include "random.h" #include "rand-internal.h" #include "../cipher/bufhelp.h" /****************************************************************** * Constants ******************************************************************/ /* * DRBG flags bitmasks * * 31 (B) 28 19 (A) 0 * +-+-+-+--------+---+-----------+-----+ * |~|~|u|~~~~~~~~| 3 | 2 | 1 | * +-+-+-+--------+- -+-----------+-----+ * ctl flg| |drbg use selection flags * */ /* Internal state control flags (B) */ #define DRBG_PREDICTION_RESIST ((u32)1<<28) /* CTR type modifiers (A.1)*/ #define DRBG_CTRAES ((u32)1<<0) #define DRBG_CTRSERPENT ((u32)1<<1) #define DRBG_CTRTWOFISH ((u32)1<<2) #define DRBG_CTR_MASK (DRBG_CTRAES | DRBG_CTRSERPENT \ | DRBG_CTRTWOFISH) /* HASH type modifiers (A.2)*/ #define DRBG_HASHSHA1 ((u32)1<<4) #define DRBG_HASHSHA224 ((u32)1<<5) #define DRBG_HASHSHA256 ((u32)1<<6) #define DRBG_HASHSHA384 ((u32)1<<7) #define DRBG_HASHSHA512 ((u32)1<<8) #define DRBG_HASH_MASK (DRBG_HASHSHA1 | DRBG_HASHSHA224 \ | DRBG_HASHSHA256 | DRBG_HASHSHA384 \ | DRBG_HASHSHA512) /* type modifiers (A.3)*/ #define DRBG_HMAC ((u32)1<<12) #define DRBG_SYM128 ((u32)1<<13) #define DRBG_SYM192 ((u32)1<<14) #define DRBG_SYM256 ((u32)1<<15) #define DRBG_TYPE_MASK (DRBG_HMAC | DRBG_SYM128 | DRBG_SYM192 \ | DRBG_SYM256) #define DRBG_CIPHER_MASK (DRBG_CTR_MASK | DRBG_HASH_MASK \ | DRBG_TYPE_MASK) #define DRBG_PR_CTRAES128 (DRBG_PREDICTION_RESIST | DRBG_CTRAES | DRBG_SYM128) #define DRBG_PR_CTRAES192 (DRBG_PREDICTION_RESIST | DRBG_CTRAES | DRBG_SYM192) #define DRBG_PR_CTRAES256 (DRBG_PREDICTION_RESIST | DRBG_CTRAES | DRBG_SYM256) #define DRBG_NOPR_CTRAES128 (DRBG_CTRAES | DRBG_SYM128) #define DRBG_NOPR_CTRAES192 (DRBG_CTRAES | DRBG_SYM192) #define DRBG_NOPR_CTRAES256 (DRBG_CTRAES | DRBG_SYM256) #define DRBG_PR_HASHSHA1 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA1) #define DRBG_PR_HASHSHA256 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA256) #define DRBG_PR_HASHSHA384 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA384) #define DRBG_PR_HASHSHA512 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA512) #define DRBG_NOPR_HASHSHA1 (DRBG_HASHSHA1) #define DRBG_NOPR_HASHSHA256 (DRBG_HASHSHA256) #define DRBG_NOPR_HASHSHA384 (DRBG_HASHSHA384) #define DRBG_NOPR_HASHSHA512 (DRBG_HASHSHA512) #define DRBG_PR_HMACSHA1 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA1 \ | DRBG_HMAC) #define DRBG_PR_HMACSHA256 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA256 \ | DRBG_HMAC) #define DRBG_PR_HMACSHA384 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA384 \ | DRBG_HMAC) #define DRBG_PR_HMACSHA512 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA512 \ | DRBG_HMAC) #define DRBG_NOPR_HMACSHA1 (DRBG_HASHSHA1 | DRBG_HMAC) #define DRBG_NOPR_HMACSHA256 (DRBG_HASHSHA256 | DRBG_HMAC) #define DRBG_NOPR_HMACSHA384 (DRBG_HASHSHA384 | DRBG_HMAC) #define DRBG_NOPR_HMACSHA512 (DRBG_HASHSHA512 | DRBG_HMAC) /* The default DRGB type. */ #define DRBG_DEFAULT_TYPE DRBG_NOPR_HMACSHA256 /****************************************************************** * Common data structures ******************************************************************/ /* * 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 drbg_string_s { const unsigned char *buf; size_t len; struct drbg_string_s *next; }; typedef struct drbg_string_s drbg_string_t; /* DRBG input data structure for DRBG generate with additional * information string. */ struct drbg_gen_s { unsigned char *outbuf; /* output buffer for random numbers */ unsigned int outlen; /* size of output buffer */ drbg_string_t *addtl; /* input buffer for * additional information string */ }; typedef struct drbg_gen_s drbg_gen_t; /* Forward declaration of the state object pointer. */ struct drbg_state_s; typedef struct drbg_state_s *drbg_state_t; struct drbg_core_s { u32 flags; /* flags for the cipher */ ushort statelen; /* maximum state length */ ushort blocklen_bytes; /* block size of output in bytes */ int backend_cipher; /* libgcrypt backend cipher */ }; struct drbg_state_ops_s { gpg_err_code_t (*update) (drbg_state_t drbg, drbg_string_t *seed, int reseed); 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 { drbg_string_t *testentropy; /* TEST PARAMETER: test entropy */ int fail_seed_source:1; /* If set, the seed function will * return an error. */ }; /* This state object keeps the state of an DRBG instance. */ struct drbg_state_s { unsigned char *V; /* internal state 10.1.1.1 1a) */ unsigned char *C; /* hash: static value 10.1.1.1 1b) * hmac / ctr: key */ size_t reseed_ctr; /* Number of RNG requests since last reseed -- * 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 * process which did the initialization so that we can detect a fork. * The volatile modifier is required so that the compiler does not * optimize it away in case the getpid function is badly attributed. */ pid_t seed_init_pid; const struct drbg_state_ops_s *d_ops; const struct drbg_core_s *core; struct drbg_test_data_s *test_data; }; enum drbg_prefixes { DRBG_PREFIX0 = 0x00, DRBG_PREFIX1, DRBG_PREFIX2, DRBG_PREFIX3 }; #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) /*************************************************************** * Global variables ***************************************************************/ /* Global state variable holding the current instance of the DRBG. */ static drbg_state_t drbg_state; /* This is the lock variable we use to serialize access to this RNG. */ GPGRT_LOCK_DEFINE(drbg_lock_var); /*************************************************************** * Backend cipher definitions available to DRBG ***************************************************************/ static const struct drbg_core_s drbg_cores[] = { /* Hash DRBGs */ {DRBG_HASHSHA1, 55, 20, GCRY_MD_SHA1}, {DRBG_HASHSHA256, 55, 32, GCRY_MD_SHA256}, {DRBG_HASHSHA384, 111, 48, GCRY_MD_SHA384}, {DRBG_HASHSHA512, 111, 64, GCRY_MD_SHA512}, /* HMAC DRBGs */ {DRBG_HASHSHA1 | DRBG_HMAC, 20, 20, GCRY_MD_SHA1}, {DRBG_HASHSHA256 | DRBG_HMAC, 32, 32, GCRY_MD_SHA256}, {DRBG_HASHSHA384 | DRBG_HMAC, 48, 48, GCRY_MD_SHA384}, {DRBG_HASHSHA512 | DRBG_HMAC, 64, 64, GCRY_MD_SHA512}, /* block ciphers */ {DRBG_CTRAES | DRBG_SYM128, 32, 16, GCRY_CIPHER_AES128}, {DRBG_CTRAES | DRBG_SYM192, 40, 16, GCRY_CIPHER_AES192}, {DRBG_CTRAES | DRBG_SYM256, 48, 16, GCRY_CIPHER_AES256} }; 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 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, 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); /****************************************************************** ****************************************************************** ****************************************************************** * Generic DRBG code ****************************************************************** ****************************************************************** ******************************************************************/ /****************************************************************** * Generic helper functions ******************************************************************/ #if 0 #define dbg(x) do { log_debug x; } while(0) #else #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", 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 } }; *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 drbg_string_fill (drbg_string_t *string, const unsigned char *buf, size_t len) { string->buf = buf; string->len = len; string->next = NULL; } static inline ushort drbg_statelen (drbg_state_t drbg) { if (drbg && drbg->core) return drbg->core->statelen; return 0; } static inline ushort drbg_blocklen (drbg_state_t drbg) { if (drbg && drbg->core) return drbg->core->blocklen_bytes; return 0; } static inline ushort drbg_keylen (drbg_state_t drbg) { if (drbg && drbg->core) return (drbg->core->statelen - drbg->core->blocklen_bytes); return 0; } static inline size_t drbg_max_request_bytes (void) { /* SP800-90A requires the limit 2**19 bits, but we return bytes */ return (1 << 16); } static inline size_t drbg_max_addtl (void) { /* SP800-90A requires 2**35 bytes additional info str / pers str */ #ifdef __LP64__ return (1UL << 35); #else /* * SP800-90A allows smaller maximum numbers to be returned -- we * return SIZE_MAX - 1 to allow the verification of the enforcement * of this value in drbg_healthcheck_sanity. */ return (SIZE_MAX - 1); #endif } static inline size_t drbg_max_requests (void) { /* SP800-90A requires 2**48 maximum requests before reseeding */ #ifdef __LP64__ return (1UL << 48); #else return SIZE_MAX; #endif } /* * Return strength of DRBG according to SP800-90A section 8.4 * * flags: DRBG flags reference * * Return: normalized strength value or 32 as a default to counter * programming errors */ static inline unsigned short drbg_sec_strength (u32 flags) { if ((flags & DRBG_HASHSHA1) || (flags & DRBG_SYM128)) return 16; else if (flags & DRBG_SYM192) return 24; else if ((flags & DRBG_SYM256) || (flags & DRBG_HASHSHA256) || (flags & DRBG_HASHSHA384) || (flags & DRBG_HASHSHA512)) return 32; else return 32; } static void drbg_add_buf (unsigned char *dst, size_t dstlen, unsigned char *add, size_t addlen) { /* implied: dstlen > addlen */ unsigned char *dstptr, *addptr; unsigned int remainder = 0; size_t len = addlen; dstptr = dst + (dstlen - 1); addptr = add + (addlen - 1); while (len) { remainder += *dstptr + *addptr; *dstptr = remainder & 0xff; remainder >>= 8; len--; dstptr--; addptr--; } len = dstlen - addlen; while (len && remainder > 0) { remainder = *dstptr + 1; *dstptr = remainder & 0xff; remainder >>= 8; len--; dstptr--; } } /* Helper variables for read_cb(). * * The _gcry_rnd*_gather_random interface does not allow to provide a * data pointer. Thus we need to use a global variable for * communication. However, the then required locking is anyway a good * idea because it does not make sense to have several readers of (say * /dev/random). It is easier to serve them one after the other. */ static unsigned char *read_cb_buffer; /* The buffer. */ static size_t read_cb_size; /* Size of the buffer. */ static size_t read_cb_len; /* Used length. */ /* Callback for generating seed from kernel device. */ static void drbg_read_cb (const void *buffer, size_t length, enum random_origins origin) { const unsigned char *p = buffer; (void) origin; gcry_assert (read_cb_buffer); /* Note that we need to protect against gatherers returning more * than the requested bytes (e.g. rndw32). */ while (length-- && read_cb_len < read_cb_size) read_cb_buffer[read_cb_len++] = *p++; } static inline int drbg_get_entropy (drbg_state_t drbg, unsigned char *buffer, size_t len) { int rc = 0; /* Perform testing as defined in 11.3.2 */ if (drbg->test_data && drbg->test_data->fail_seed_source) return -1; read_cb_buffer = buffer; read_cb_size = len; read_cb_len = 0; #if USE_RNDLINUX rc = _gcry_rndlinux_gather_random (drbg_read_cb, 0, len, GCRY_VERY_STRONG_RANDOM); #elif USE_RNDUNIX rc = _gcry_rndunix_gather_random (drbg_read_cb, 0, len, GCRY_VERY_STRONG_RANDOM); #elif USE_RNDW32 do { rc = _gcry_rndw32_gather_random (drbg_read_cb, 0, len, GCRY_VERY_STRONG_RANDOM); } while (rc >= 0 && read_cb_len < read_cb_size); #else rc = -1; #endif return rc; } /****************************************************************** * CTR DRBG callback functions ******************************************************************/ /* BCC function for CTR DRBG as defined in 10.4.3 */ static gpg_err_code_t drbg_ctr_bcc (drbg_state_t drbg, unsigned char *out, const unsigned char *key, drbg_string_t *in) { gpg_err_code_t ret = GPG_ERR_GENERAL; drbg_string_t *curr = in; size_t inpos = curr->len; const unsigned char *pos = curr->buf; drbg_string_t data; drbg_string_fill (&data, out, drbg_blocklen (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) { short cnt = 0; /* 10.4.3 step 4.1 */ for (cnt = 0; cnt < drbg_blocklen (drbg); cnt++) { out[cnt] ^= *pos; pos++; inpos--; /* the following branch implements the linked list * iteration. If we are at the end of the current data * set, we have to start using the next data set if * available -- the inpos value always points to the * current byte and will be zero if we have processed * the last byte of the last linked list member */ if (0 == inpos) { curr = curr->next; if (NULL != curr) { pos = curr->buf; inpos = curr->len; } else { inpos = 0; break; } } } /* 10.4.3 step 4.2 */ ret = drbg_sym (drbg, out, &data); if (ret) return ret; /* 10.4.3 step 2 */ } return 0; } /* * scratchpad usage: drbg_ctr_update is interlinked with drbg_ctr_df * (and drbg_ctr_bcc, but this function does not need any temporary buffers), * the scratchpad is used as follows: * drbg_ctr_update: * temp * start: drbg->scratchpad * length: drbg_statelen(drbg) + drbg_blocklen(drbg) * note: the cipher writing into this variable works * blocklen-wise. Now, when the statelen is not a multiple * of blocklen, the generateion loop below "spills over" * by at most blocklen. Thus, we need to give sufficient * memory. * df_data * start: drbg->scratchpad + * drbg_statelen(drbg) + * drbg_blocklen(drbg) * length: drbg_statelen(drbg) * * drbg_ctr_df: * pad * start: df_data + drbg_statelen(drbg) * length: drbg_blocklen(drbg) * iv * start: pad + drbg_blocklen(drbg) * length: drbg_blocklen(drbg) * temp * start: iv + drbg_blocklen(drbg) * length: drbg_satelen(drbg) + drbg_blocklen(drbg) * note: temp is the buffer that the BCC function operates * on. BCC operates blockwise. drbg_statelen(drbg) * is sufficient when the DRBG state length is a multiple * of the block size. For AES192 (and maybe other ciphers) * this is not correct and the length for temp is * insufficient (yes, that also means for such ciphers, * the final output of all BCC rounds are truncated). * Therefore, add drbg_blocklen(drbg) to cover all * possibilities. */ /* Derivation Function for CTR DRBG as defined in 10.4.2 */ static gpg_err_code_t drbg_ctr_df (drbg_state_t drbg, unsigned char *df_data, size_t bytes_to_return, drbg_string_t *addtl) { gpg_err_code_t ret = GPG_ERR_GENERAL; unsigned char L_N[8]; /* S3 is input */ drbg_string_t S1, S2, S4, cipherin; drbg_string_t *tempstr = addtl; unsigned char *pad = df_data + drbg_statelen (drbg); unsigned char *iv = pad + drbg_blocklen (drbg); unsigned char *temp = iv + drbg_blocklen (drbg); size_t padlen = 0; unsigned int templen = 0; /* 10.4.2 step 7 */ unsigned int i = 0; /* 10.4.2 step 8 */ const unsigned char *K = (unsigned char *) "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"; unsigned char *X; size_t generated_len = 0; size_t inputlen = 0; memset (pad, 0, drbg_blocklen (drbg)); memset (iv, 0, drbg_blocklen (drbg)); memset (temp, 0, drbg_statelen (drbg)); /* 10.4.2 step 1 is implicit as we work byte-wise */ /* 10.4.2 step 2 */ if ((512 / 8) < bytes_to_return) return GPG_ERR_INV_ARG; /* 10.4.2 step 2 -- calculate the entire length of all input data */ for (; NULL != tempstr; tempstr = tempstr->next) inputlen += tempstr->len; buf_put_be32 (&L_N[0], inputlen); /* 10.4.2 step 3 */ buf_put_be32 (&L_N[4], bytes_to_return); /* 10.4.2 step 5: length is size of L_N, input_string, one byte, padding */ padlen = (inputlen + sizeof (L_N) + 1) % (drbg_blocklen (drbg)); /* wrap the padlen appropriately */ if (padlen) padlen = drbg_blocklen (drbg) - padlen; /* pad / padlen contains the 0x80 byte and the following zero bytes, so * add one for byte for 0x80 */ padlen++; pad[0] = 0x80; /* 10.4.2 step 4 -- first fill the linked list and then order it */ drbg_string_fill (&S1, iv, drbg_blocklen (drbg)); drbg_string_fill (&S2, L_N, sizeof (L_N)); drbg_string_fill (&S4, pad, padlen); S1.next = &S2; S2.next = addtl; /* Splice in addtl between S2 and S4 -- we place S4 at the end of the * input data chain. As this code is only triggered when addtl is not * NULL, no NULL checks are necessary.*/ tempstr = addtl; while (tempstr->next) tempstr = tempstr->next; tempstr->next = &S4; /* 10.4.2 step 9 */ while (templen < (drbg_keylen (drbg) + (drbg_blocklen (drbg)))) { /* 10.4.2 step 9.1 - the padding is implicit as the buffer * holds zeros after allocation -- even the increment of i * is irrelevant as the increment remains within length of i */ buf_put_be32 (iv, i); /* 10.4.2 step 9.2 -- BCC and concatenation with temp */ ret = drbg_ctr_bcc (drbg, temp + templen, K, &S1); if (ret) goto out; /* 10.4.2 step 9.3 */ i++; templen += drbg_blocklen (drbg); } /* 10.4.2 step 11 */ /* implicit key len with seedlen - blocklen according to table 3 */ X = temp + (drbg_keylen (drbg)); drbg_string_fill (&cipherin, X, drbg_blocklen (drbg)); /* 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; /* 10.4.2 step 13.1 */ /* 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, X, &cipherin); if (ret) goto out; 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); generated_len += blocklen; } ret = 0; out: memset (iv, 0, drbg_blocklen (drbg)); memset (temp, 0, drbg_statelen (drbg)); memset (pad, 0, drbg_blocklen (drbg)); return ret; } /* * Update function of CTR DRBG as defined in 10.2.1.2 * * The reseed variable has an enhanced meaning compared to the update * functions of the other DRBGs as follows: * 0 => initial seed from initialization * 1 => reseed via drbg_seed * 2 => first invocation from drbg_ctr_update when addtl is present. In * this case, the df_data scratchpad is not deleted so that it is * available for another calls to prevent calling the DF function * again. * 3 => second invocation from drbg_ctr_update. When the update function * was called with addtl, the df_data memory already contains the * DFed addtl information and we do not need to call DF again. */ static gpg_err_code_t drbg_ctr_update (drbg_state_t drbg, drbg_string_t *addtl, int reseed) { gpg_err_code_t ret = GPG_ERR_GENERAL; /* 10.2.1.2 step 1 */ unsigned char *temp = drbg->scratchpad; unsigned char *df_data = drbg->scratchpad + drbg_statelen (drbg) + drbg_blocklen (drbg); unsigned char prefix = DRBG_PREFIX1; memset (temp, 0, drbg_statelen (drbg) + drbg_blocklen (drbg)); if (3 > reseed) memset (df_data, 0, drbg_statelen (drbg)); if (!reseed) { /* * 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; } /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */ if (addtl && 0 < addtl->len) { ret = drbg_ctr_df (drbg, df_data, drbg_statelen (drbg), addtl); if (ret) goto out; } ret = drbg_sym_ctr (drbg, df_data, drbg_statelen(drbg), temp, drbg_statelen(drbg)); if (ret) goto out; /* 10.2.1.2 step 5 */ 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: memset (temp, 0, drbg_statelen (drbg) + drbg_blocklen (drbg)); if (2 != reseed) memset (df_data, 0, drbg_statelen (drbg)); return ret; } /* * scratchpad use: drbg_ctr_update is called independently from * drbg_ctr_extract_bytes. Therefore, the scratchpad is reused */ /* Generate function of CTR DRBG as defined in 10.2.1.5.2 */ static gpg_err_code_t drbg_ctr_generate (drbg_state_t drbg, unsigned char *buf, unsigned int buflen, drbg_string_t *addtl) { gpg_err_code_t ret = 0; memset (drbg->scratchpad, 0, drbg_blocklen (drbg)); /* 10.2.1.5.2 step 2 */ if (addtl && 0 < addtl->len) { addtl->next = NULL; ret = drbg_ctr_update (drbg, addtl, 2); if (ret) return ret; } /* 10.2.1.5.2 step 4.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) addtl->next = NULL; ret = drbg_ctr_update (drbg, addtl, 3); out: return ret; } static struct drbg_state_ops_s drbg_ctr_ops = { drbg_ctr_update, drbg_ctr_generate, drbg_sym_init, drbg_sym_fini, }; /****************************************************************** * HMAC DRBG callback functions ******************************************************************/ static gpg_err_code_t drbg_hmac_update (drbg_state_t drbg, drbg_string_t *seed, int reseed) { gpg_err_code_t ret = GPG_ERR_GENERAL; int i = 0; drbg_string_t seed1, seed2, cipherin; if (!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 * first part*/ drbg_string_fill (&seed1, drbg->V, drbg_statelen (drbg)); /* buffer will be filled in for loop below with one byte */ drbg_string_fill (&seed2, NULL, 1); seed1.next = &seed2; /* seed may be NULL */ seed2.next = seed; drbg_string_fill (&cipherin, drbg->V, drbg_statelen (drbg)); /* 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; 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 */ retval = drbg_hash (drbg, &cipherin); memcpy(drbg->V, retval, drbg_blocklen (drbg)); /* 10.1.2.2 step 3 */ if (!seed || 0 == seed->len) return ret; } return 0; } /* generate function of HMAC DRBG as defined in 10.1.2.5 */ static gpg_err_code_t drbg_hmac_generate (drbg_state_t drbg, unsigned char *buf, unsigned int buflen, drbg_string_t *addtl) { gpg_err_code_t ret = 0; unsigned int len = 0; drbg_string_t data; /* 10.1.2.5 step 2 */ if (addtl && 0 < addtl->len) { addtl->next = NULL; ret = drbg_hmac_update (drbg, addtl, 1); if (ret) return ret; } drbg_string_fill (&data, drbg->V, drbg_statelen (drbg)); while (len < buflen) { unsigned int outlen = 0; /* 10.1.2.5 step 4.1 */ byte *retval = drbg_hash (drbg, &data); memcpy(drbg->V, retval, drbg_blocklen (drbg)); outlen = (drbg_blocklen (drbg) < (buflen - len)) ? drbg_blocklen (drbg) : (buflen - len); /* 10.1.2.5 step 4.2 */ memcpy (buf + len, drbg->V, outlen); len += outlen; } /* 10.1.2.5 step 6 */ if (addtl) addtl->next = NULL; ret = drbg_hmac_update (drbg, addtl, 1); return ret; } static struct drbg_state_ops_s drbg_hmac_ops = { drbg_hmac_update, drbg_hmac_generate, drbg_hmac_init, drbg_hash_fini, }; /****************************************************************** * Hash DRBG callback functions ******************************************************************/ /* * scratchpad usage: as drbg_hash_update and drbg_hash_df are used * interlinked, the scratchpad is used as follows: * drbg_hash_update * start: drbg->scratchpad * length: drbg_statelen(drbg) * drbg_hash_df: * start: drbg->scratchpad + drbg_statelen(drbg) * length: drbg_blocklen(drbg) */ /* Derivation Function for Hash DRBG as defined in 10.4.1 */ static gpg_err_code_t drbg_hash_df (drbg_state_t drbg, unsigned char *outval, size_t outlen, drbg_string_t *entropy) { size_t len = 0; unsigned char input[5]; drbg_string_t data1; /* 10.4.1 step 3 */ input[0] = 1; buf_put_be32 (&input[1], (outlen * 8)); /* 10.4.1 step 4.1 -- concatenation of data for input into hash */ drbg_string_fill (&data1, input, 5); data1.next = entropy; /* 10.4.1 step 4 */ while (len < outlen) { short blocklen = 0; /* 10.4.1 step 4.1 */ 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, retval, blocklen); len += blocklen; } return 0; } /* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */ static gpg_err_code_t drbg_hash_update (drbg_state_t drbg, drbg_string_t *seed, int reseed) { gpg_err_code_t ret = 0; drbg_string_t data1, data2; unsigned char *V = drbg->scratchpad; unsigned char prefix = DRBG_PREFIX1; memset (drbg->scratchpad, 0, drbg_statelen (drbg)); if (!seed) return GPG_ERR_INV_ARG; if (reseed) { /* 10.1.1.3 step 1: string length is concatenation of * 1 byte, V and seed (which is concatenated entropy/addtl * input) */ memcpy (V, drbg->V, drbg_statelen (drbg)); drbg_string_fill (&data1, &prefix, 1); drbg_string_fill (&data2, V, drbg_statelen (drbg)); data1.next = &data2; data2.next = seed; } else { drbg_string_fill (&data1, seed->buf, seed->len); data1.next = seed->next; } /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */ ret = drbg_hash_df (drbg, drbg->V, drbg_statelen (drbg), &data1); if (ret) goto out; /* 10.1.1.2 / 10.1.1.3 step 4 -- concatenation */ prefix = DRBG_PREFIX0; drbg_string_fill (&data1, &prefix, 1); drbg_string_fill (&data2, drbg->V, drbg_statelen (drbg)); data1.next = &data2; /* 10.1.1.2 / 10.1.1.3 step 4 -- df operation */ ret = drbg_hash_df (drbg, drbg->C, drbg_statelen (drbg), &data1); out: memset (drbg->scratchpad, 0, drbg_statelen (drbg)); return ret; } /* Processing of additional information string for Hash DRBG. */ static gpg_err_code_t drbg_hash_process_addtl (drbg_state_t drbg, drbg_string_t *addtl) { drbg_string_t data1, data2; drbg_string_t *data3; unsigned char prefix = DRBG_PREFIX2; byte *retval; /* 10.1.1.4 step 2 */ if (!addtl || 0 == addtl->len) return 0; /* 10.1.1.4 step 2a -- concatenation */ drbg_string_fill (&data1, &prefix, 1); drbg_string_fill (&data2, drbg->V, drbg_statelen (drbg)); data3 = addtl; data1.next = &data2; data2.next = data3; data3->next = NULL; /* 10.1.1.4 step 2a -- cipher invocation */ retval = drbg_hash (drbg, &data1); /* 10.1.1.4 step 2b */ drbg_add_buf (drbg->V, drbg_statelen (drbg), retval, drbg_blocklen (drbg)); 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) { unsigned int len = 0; unsigned char *src = drbg->scratchpad; drbg_string_t data; unsigned char prefix = DRBG_PREFIX1; /* 10.1.1.4 step hashgen 2 */ memcpy (src, drbg->V, drbg_statelen (drbg)); drbg_string_fill (&data, src, drbg_statelen (drbg)); while (len < buflen) { unsigned int outlen = 0; /* 10.1.1.4 step hashgen 4.1 */ 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, retval, outlen); len += outlen; /* 10.1.1.4 hashgen step 4.3 */ if (len < buflen) drbg_add_buf (src, drbg_statelen (drbg), &prefix, 1); } 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) { 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; /* 10.1.1.4 step 2 */ ret = drbg_hash_process_addtl (drbg, addtl); if (ret) return ret; /* 10.1.1.4 step 3 -- invocation of the Hashgen function defined in * 10.1.1.4 */ ret = drbg_hash_hashgen (drbg, buf, buflen); if (ret) return ret; /* 10.1.1.4 step 4 */ drbg_string_fill (&data1, &prefix, 1); drbg_string_fill (&data2, drbg->V, drbg_statelen (drbg)); data1.next = &data2; /* 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), 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)); return ret; } /* * scratchpad usage: as update and generate are used isolated, both * can use the scratchpad */ static struct drbg_state_ops_s drbg_hash_ops = { drbg_hash_update, drbg_hash_generate, drbg_hash_init, drbg_hash_fini, }; /****************************************************************** * Functions common for DRBG implementations ******************************************************************/ /* * Seeding or reseeding of the DRBG * * @drbg: DRBG state struct * @pers: personalization / additional information buffer * @reseed: 0 for initial seed process, 1 for reseeding * * return: * 0 on success * error value otherwise */ static gpg_err_code_t drbg_seed (drbg_state_t drbg, drbg_string_t *pers, int reseed) { gpg_err_code_t ret = 0; unsigned char *entropy = NULL; size_t entropylen = 0; drbg_string_t data1; /* 9.1 / 9.2 / 9.3.1 step 3 */ if (pers && pers->len > (drbg_max_addtl ())) { dbg (("DRBG: personalization string too long %lu\n", pers->len)); return GPG_ERR_INV_ARG; } if (drbg->test_data && drbg->test_data->testentropy) { drbg_string_fill (&data1, drbg->test_data->testentropy->buf, drbg->test_data->testentropy->len); dbg (("DRBG: using test entropy\n")); } else { /* Gather entropy equal to the security strength of the DRBG. * With a derivation function, a nonce is required in addition * to the entropy. A nonce must be at least 1/2 of the security * strength of the DRBG in size. Thus, entropy * nonce is 3/2 * of the strength. The consideration of a nonce is only * applicable during initial seeding. */ entropylen = drbg_sec_strength (drbg->core->flags); if (!entropylen) return GPG_ERR_GENERAL; if (0 == reseed) /* make sure we round up strength/2 in * case it is not divisible by 2 */ entropylen = ((entropylen + 1) / 2) * 3; dbg (("DRBG: (re)seeding with %lu bytes of entropy\n", entropylen)); entropy = xcalloc_secure (1, entropylen); if (!entropy) return GPG_ERR_ENOMEM; ret = drbg_get_entropy (drbg, entropy, entropylen); if (ret) goto out; drbg_string_fill (&data1, entropy, entropylen); } /* concatenation of entropy with personalization str / addtl input) * the variable pers is directly handed by the caller, check its * contents whether it is appropriate */ if (pers && pers->buf && 0 < pers->len && NULL == pers->next) { data1.next = pers; dbg (("DRBG: using personalization string\n")); } ret = drbg->d_ops->update (drbg, &data1, reseed); dbg (("DRBG: state updated with seed\n")); if (ret) goto out; drbg->seeded = 1; /* 10.1.1.2 / 10.1.1.3 step 5 */ drbg->reseed_ctr = 1; out: xfree (entropy); return ret; } /************************************************************************* * Exported interfaces. *************************************************************************/ /* * DRBG generate function as required by SP800-90A - this function * generates random numbers * * @drbg DRBG state handle * @buf Buffer where to store the random numbers -- the buffer must already * be pre-allocated by caller * @buflen Length of output buffer - this value defines the number of random * bytes pulled from DRBG * @addtl Additional input that is mixed into state, may be NULL -- note * the entropy is pulled by the DRBG internally unconditionally * as defined in SP800-90A. The additional input is mixed into * the state in addition to the pulled entropy. * * return: Generated number of bytes. */ static gpg_err_code_t drbg_generate (drbg_state_t drbg, unsigned char *buf, unsigned int buflen, drbg_string_t *addtl) { gpg_err_code_t ret = GPG_ERR_INV_ARG; if (0 == buflen || !buf) { dbg (("DRBG: no buffer provided\n")); return ret; } if (addtl && NULL == addtl->buf && 0 < addtl->len) { dbg (("DRBG: wrong format of additional information\n")); return ret; } /* 9.3.1 step 2 */ if (buflen > (drbg_max_request_bytes ())) { dbg (("DRBG: requested random numbers too large %u\n", buflen)); return ret; } /* 9.3.1 step 3 is implicit with the chosen DRBG */ /* 9.3.1 step 4 */ if (addtl && addtl->len > (drbg_max_addtl ())) { dbg (("DRBG: additional information string too long %lu\n", addtl->len)); return ret; } /* 9.3.1 step 5 is implicit with the chosen DRBG */ /* 9.3.1 step 6 and 9 supplemented by 9.3.2 step c -- the spec is a * bit convoluted here, we make it simpler */ if ((drbg_max_requests ()) < drbg->reseed_ctr) drbg->seeded = 0; if (drbg->pr || !drbg->seeded) { dbg (("DRBG: reseeding before generation (prediction resistance: %s, state %s)\n", drbg->pr ? "true" : "false", drbg->seeded ? "seeded" : "unseeded")); /* 9.3.1 steps 7.1 through 7.3 */ ret = drbg_seed (drbg, addtl, 1); if (ret) return ret; /* 9.3.1 step 7.4 */ addtl = NULL; } if (addtl && addtl->buf) { dbg (("DRBG: using additional information string\n")); } /* 9.3.1 step 8 and 10 */ ret = drbg->d_ops->generate (drbg, buf, buflen, addtl); /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */ drbg->reseed_ctr++; if (ret) return ret; /* 11.3.3 -- re-perform self tests after some generated random * numbers, the chosen value after which self test is performed * is arbitrary, but it should be reasonable */ /* Here we do not perform the self tests because of the following * reasons: it is mathematically impossible that the initial self tests * were successfully and the following are not. If the initial would * pass and the following would not, the system integrity is violated. * In this case, the entire system operation is questionable and it * is unlikely that the integrity violation only affects to the * correct operation of the DRBG. */ #if 0 if (drbg->reseed_ctr && !(drbg->reseed_ctr % 4096)) { dbg (("DRBG: start to perform self test\n")); ret = drbg_healthcheck (); if (ret) { log_fatal (("DRBG: self test failed\n")); return ret; } else { dbg (("DRBG: self test successful\n")); } } #endif return ret; } /* * Wrapper around drbg_generate which can pull arbitrary long strings * from the DRBG without hitting the maximum request limitation. * * Parameters: see drbg_generate * Return codes: see drbg_generate -- if one drbg_generate request fails, * the entire drbg_generate_long request fails */ static gpg_err_code_t drbg_generate_long (drbg_state_t drbg, unsigned char *buf, unsigned int buflen, drbg_string_t *addtl) { gpg_err_code_t ret = 0; unsigned int slice = 0; unsigned char *buf_p = buf; unsigned len = 0; do { unsigned int chunk = 0; slice = ((buflen - len) / drbg_max_request_bytes ()); chunk = slice ? drbg_max_request_bytes () : (buflen - len); ret = drbg_generate (drbg, buf_p, chunk, addtl); if (ret) return ret; buf_p += chunk; len += chunk; } while (slice > 0 && (len < buflen)); return ret; } /* * DRBG uninstantiate function as required by SP800-90A - this function * frees all buffers and the DRBG handle * * @drbg DRBG state handle * * return * 0 on success */ static gpg_err_code_t 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); drbg->C = NULL; drbg->reseed_ctr = 0; xfree (drbg->scratchpad); drbg->scratchpad = NULL; drbg->seeded = 0; drbg->pr = 0; drbg->seed_init_pid = 0; return 0; } /* * DRBG instantiation function as required by SP800-90A - this function * sets up the DRBG handle, performs the initial seeding and all sanity * checks required by SP800-90A * * @drbg memory of state -- if NULL, new memory is allocated * @pers Personalization string that is mixed into state, may be NULL -- note * the entropy is pulled by the DRBG internally unconditionally * as defined in SP800-90A. The additional input is mixed into * the state in addition to the pulled entropy. * @coreref reference to core * @flags Flags defining the requested DRBG type and cipher type. The flags * are defined in drbg.h and may be XORed. Beware, if you XOR multiple * cipher types together, the code picks the core on a first come first * serve basis as it iterates through the available cipher cores and * uses the one with the first match. The minimum required flags are: * cipher type flag * * return * 0 on success * error value otherwise */ static gpg_err_code_t drbg_instantiate (drbg_state_t drbg, drbg_string_t *pers, int coreref, int pr) { gpg_err_code_t ret = GPG_ERR_ENOMEM; unsigned int sb_size = 0; if (!drbg) return GPG_ERR_INV_ARG; dbg (("DRBG: Initializing DRBG core %d with prediction resistance %s\n", coreref, pr ? "enabled" : "disabled")); drbg->core = &drbg_cores[coreref]; drbg->pr = pr; drbg->seeded = 0; if (drbg->core->flags & DRBG_HMAC) drbg->d_ops = &drbg_hmac_ops; else if (drbg->core->flags & DRBG_HASH_MASK) drbg->d_ops = &drbg_hash_ops; else if (drbg->core->flags & DRBG_CTR_MASK) drbg->d_ops = &drbg_ctr_ops; else return GPG_ERR_GENERAL; /* 9.1 step 1 is implicit with the selected DRBG type -- see * drbg_sec_strength() */ /* 9.1 step 2 is implicit as caller can select prediction resistance * and the flag is copied into drbg->flags -- * all DRBG types support prediction resistance */ /* 9.1 step 4 is implicit in drbg_sec_strength */ ret = drbg->d_ops->crypto_init(drbg); if (ret) goto err; drbg->V = xcalloc_secure (1, drbg_statelen (drbg)); if (!drbg->V) goto fini; drbg->C = xcalloc_secure (1, drbg_statelen (drbg)); if (!drbg->C) goto fini; /* scratchpad is only generated for CTR and Hash */ if (drbg->core->flags & DRBG_HMAC) sb_size = 0; else if (drbg->core->flags & DRBG_CTR_MASK) sb_size = drbg_statelen (drbg) + drbg_blocklen (drbg) + /* temp */ drbg_statelen (drbg) + /* df_data */ drbg_blocklen (drbg) + /* pad */ drbg_blocklen (drbg) + /* iv */ drbg_statelen (drbg) + drbg_blocklen (drbg); /* temp */ else sb_size = drbg_statelen (drbg); if (0 < sb_size) { drbg->scratchpad = xcalloc_secure (1, sb_size); if (!drbg->scratchpad) 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 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; } /* * DRBG reseed function as required by SP800-90A * * @drbg DRBG state handle * @addtl Additional input that is mixed into state, may be NULL -- note * the entropy is pulled by the DRBG internally unconditionally * as defined in SP800-90A. The additional input is mixed into * the state in addition to the pulled entropy. * * return * 0 on success * error value otherwise */ static gpg_err_code_t drbg_reseed (drbg_state_t drbg,drbg_string_t *addtl) { gpg_err_code_t ret = 0; ret = drbg_seed (drbg, addtl, 1); return ret; } /****************************************************************** * Libgcrypt integration code. ******************************************************************/ /*************************************************** * Libgcrypt backend functions to the RNG API code. ***************************************************/ static inline void drbg_lock (void) { gpg_err_code_t ec; ec = gpgrt_lock_lock (&drbg_lock_var); if (ec) log_fatal ("failed to acquire the RNG lock: %s\n", gpg_strerror (ec)); } static inline void drbg_unlock (void) { gpg_err_code_t ec; ec = gpgrt_lock_unlock (&drbg_lock_var); if (ec) log_fatal ("failed to release the RNG lock: %s\n", gpg_strerror (ec)); } /* Basic initialization is required to initialize mutexes and do a few checks on the implementation. */ static void basic_initialization (void) { static int initialized; if (initialized) return; initialized = 1; /* Make sure that we are still using the values we have traditionally used for the random levels. */ gcry_assert (GCRY_WEAK_RANDOM == 0 && GCRY_STRONG_RANDOM == 1 && GCRY_VERY_STRONG_RANDOM == 2); } /****** helper functions where lock must be held by caller *****/ /* Check whether given flags are known to point to an applicable DRBG */ static gpg_err_code_t drbg_algo_available (u32 flags, int *coreref) { int i = 0; for (i = 0; ARRAY_SIZE (drbg_cores) > i; i++) { if ((drbg_cores[i].flags & DRBG_CIPHER_MASK) == (flags & DRBG_CIPHER_MASK)) { *coreref = i; return 0; } } return GPG_ERR_GENERAL; } static gpg_err_code_t _drbg_init_internal (u32 flags, drbg_string_t *pers) { static u32 oldflags; gpg_err_code_t ret = 0; int coreref = 0; int pr = 0; /* If a caller provides 0 as flags, use the flags of the previous * initialization, otherwise use the current flags and remember them * for the next invocation. If no flag is given and no global state * is set this is the first initialization and we set the default * type. */ if (!flags && !drbg_state) flags = oldflags = DRBG_DEFAULT_TYPE; else if (!flags) flags = oldflags; else oldflags = flags; ret = drbg_algo_available (flags, &coreref); if (ret) return ret; if (drbg_state) { drbg_uninstantiate (drbg_state); } else { drbg_state = xtrycalloc_secure (1, sizeof *drbg_state); if (!drbg_state) return gpg_err_code_from_syserror (); } if (flags & DRBG_PREDICTION_RESIST) pr = 1; ret = drbg_instantiate (drbg_state, pers, coreref, pr); if (ret) fips_signal_error ("DRBG cannot be initialized"); else drbg_state->seed_init_pid = getpid (); return ret; } /************* calls available to common RNG code **************/ /* * Initialize one DRBG invoked by the libgcrypt API */ void _gcry_rngdrbg_inititialize (int full) { basic_initialization (); if (!full) return; drbg_lock (); if (!drbg_state) _drbg_init_internal (0, NULL); drbg_unlock (); } /* * Backend handler function for GCRYCTL_DRBG_REINIT * * Select a different DRBG type and initialize it. * Function checks whether requested DRBG type exists and returns an error in * case it does not. In case of an error, the previous instantiated DRBG is * left untouched and alive. Thus, in case of an error, a DRBG is always * available, even if it is not the chosen one. * * Re-initialization will be performed in any case regardless whether flags * or personalization string are set. * * 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_rngdrbg_reinit (const char *flagstr, gcry_buffer_t *pers, int npers) { 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)); drbg_lock (); if (pers) { drbg_string_t persbuf; drbg_string_fill (&persbuf, (const unsigned char *)pers[0].data + pers[0].off, pers[0].len); ret = _drbg_init_internal (flags, &persbuf); } else ret = _drbg_init_internal (flags, NULL); drbg_unlock (); } return ret; } /* Try to close the FDs of the random gather module. This is * currently only implemented for rndlinux. */ void _gcry_rngdrbg_close_fds (void) { #if USE_RNDLINUX drbg_lock (); _gcry_rndlinux_gather_random (NULL, 0, 0, 0); drbg_unlock (); #endif } /* Print some statistics about the RNG. */ void _gcry_rngdrbg_dump_stats (void) { /* Not yet implemented. */ /* Maybe dumping of reseed counter? */ } /* This function returns true if no real RNG is available or the * quality of the RNG has been degraded for test purposes. */ int _gcry_rngdrbg_is_faked (void) { return 0; /* Faked random is not allowed. */ } /* Add BUFLEN bytes from BUF to the internal random pool. QUALITY * should be in the range of 0..100 to indicate the goodness of the * entropy added, or -1 for goodness not known. */ gcry_error_t _gcry_rngdrbg_add_bytes (const void *buf, size_t buflen, int quality) { gpg_err_code_t ret = 0; drbg_string_t seed; (void) quality; _gcry_rngdrbg_inititialize (1); /* Auto-initialize if needed */ if (!drbg_state) return GPG_ERR_GENERAL; drbg_string_fill (&seed, (unsigned char *) buf, buflen); drbg_lock (); ret = drbg_reseed (drbg_state, &seed); drbg_unlock (); return ret; } /* This function is to be used for all types of random numbers, including * nonces */ void _gcry_rngdrbg_randomize (void *buffer, size_t length, enum gcry_random_level level) { (void) level; _gcry_rngdrbg_inititialize (1); /* Auto-initialize if needed */ drbg_lock (); if (!drbg_state) { fips_signal_error ("DRBG is not initialized"); goto bailout; } /* As reseeding changes the entire state of the DRBG, including any * key, either a re-init or a reseed is sufficient for a fork */ if (drbg_state->seed_init_pid != getpid ()) { /* We are in a child of us. Perform a reseeding. */ if (drbg_reseed (drbg_state, NULL)) { fips_signal_error ("reseeding upon fork failed"); log_fatal ("severe error getting random\n"); goto bailout; } } /* potential integer overflow is covered by drbg_generate which * ensures that length cannot overflow an unsigned int */ if (0 < length) { if (!buffer) goto bailout; if (drbg_generate_long (drbg_state, buffer, (unsigned int) length, NULL)) log_fatal ("No random numbers generated\n"); } else { drbg_gen_t *data = (drbg_gen_t *)buffer; /* catch NULL pointer */ if (!data || !data->outbuf) { fips_signal_error ("No output buffer provided"); goto bailout; } if (drbg_generate_long (drbg_state, data->outbuf, data->outlen, data->addtl)) log_fatal ("No random numbers generated\n"); } bailout: drbg_unlock (); return; } /*************************************************************** * Self-test code ***************************************************************/ /* * Test vectors from * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip */ struct gcry_drbg_test_vector drbg_test_pr[] = { { /* .flags = */ "sha256 pr" /* DRBG_PR_HASHSHA256 */, /* .entropy = */ (unsigned char *) "\x5d\xf2\x14\xbc\xf6\xb5\x4e\x0b\xf0\x0d\x6f\x2d" "\xe2\x01\x66\x7b\xd0\xa4\x73\xa4\x21\xdd\xb0\xc0" "\x51\x79\x09\xf4\xea\xa9\x08\xfa\xa6\x67\xe0\xe1" "\xd1\x88\xa8\xad\xee\x69\x74\xb3\x55\x06\x9b\xf6", /* .entropylen = */ 48, /* .entpra = */ (unsigned char *) "\xef\x48\x06\xa2\xc2\x45\xf1\x44\xfa\x34\x2c\xeb" "\x8d\x78\x3c\x09\x8f\x34\x72\x20\xf2\xe7\xfd\x13" "\x76\x0a\xf6\xdc\x3c\xf5\xc0\x15", /* .entprb = */ (unsigned char *) "\x4b\xbe\xe5\x24\xed\x6a\x2d\x0c\xdb\x73\x5e\x09" "\xf9\xad\x67\x7c\x51\x47\x8b\x6b\x30\x2a\xc6\xde" "\x76\xaa\x55\x04\x8b\x0a\x72\x95", /* .entprlen = */ 32, /* .addtla = */ (unsigned char *) "\xbe\x13\xdb\x2a\xe9\xa8\xfe\x09\x97\xe1\xce\x5d" "\xe8\xbb\xc0\x7c\x4f\xcb\x62\x19\x3f\x0f\xd2\xad" "\xa9\xd0\x1d\x59\x02\xc4\xff\x70", /* .addtlb = */ (unsigned char *) "\x6f\x96\x13\xe2\xa7\xf5\x6c\xfe\xdf\x66\xe3\x31" "\x63\x76\xbf\x20\x27\x06\x49\xf1\xf3\x01\x77\x41" "\x9f\xeb\xe4\x38\xfe\x67\x00\xcd", /* .addtllen = */ 32, /* .pers = */ NULL, /* .perslen = */ 0, /* .expected = */ (unsigned char *) "\x3b\x14\x71\x99\xa1\xda\xa0\x42\xe6\xc8\x85\x32" "\x70\x20\x32\x53\x9a\xbe\xd1\x1e\x15\xef\xfb\x4c" "\x25\x6e\x19\x3a\xf0\xb9\xcb\xde\xf0\x3b\xc6\x18" "\x4d\x85\x5a\x9b\xf1\xe3\xc2\x23\x03\x93\x08\xdb" "\xa7\x07\x4b\x33\x78\x40\x4d\xeb\x24\xf5\x6e\x81" "\x4a\x1b\x6e\xa3\x94\x52\x43\xb0\xaf\x2e\x21\xf4" "\x42\x46\x8e\x90\xed\x34\x21\x75\xea\xda\x67\xb6" "\xe4\xf6\xff\xc6\x31\x6c\x9a\x5a\xdb\xb3\x97\x13" "\x09\xd3\x20\x98\x33\x2d\x6d\xd7\xb5\x6a\xa8\xa9" "\x9a\x5b\xd6\x87\x52\xa1\x89\x2b\x4b\x9c\x64\x60" "\x50\x47\xa3\x63\x81\x16\xaf\x19", /* .expectedlen = */ 128, /* .entropyreseed = */ NULL, /* .entropyreseed_len = */ 0, /* .addtl_reseed = */ NULL, /* .addtl_reseed_len = */ 0 }, { /* flags = */ "hmac sha256 pr" /* DRBG_PR_HMACSHA256 */, /* .entropy = */ (unsigned char *) "\x13\x54\x96\xfc\x1b\x7d\x28\xf3\x18\xc9\xa7\x89" "\xb6\xb3\xc8\x72\xac\x00\xd4\x59\x36\x25\x05\xaf" "\xa5\xdb\x96\xcb\x3c\x58\x46\x87\xa5\xaa\xbf\x20" "\x3b\xfe\x23\x0e\xd1\xc7\x41\x0f\x3f\xc9\xb3\x67", /* .entropylen = */ 48, /* .entpra = */ (unsigned char *) "\xe2\xbd\xb7\x48\x08\x06\xf3\xe1\x93\x3c\xac\x79" "\xa7\x2b\x11\xda\xe3\x2e\xe1\x91\xa5\x02\x19\x57" "\x20\x28\xad\xf2\x60\xd7\xcd\x45", /* .entprb = */ (unsigned char *) "\x8b\xd4\x69\xfc\xff\x59\x95\x95\xc6\x51\xde\x71" "\x68\x5f\xfc\xf9\x4a\xab\xec\x5a\xcb\xbe\xd3\x66" "\x1f\xfa\x74\xd3\xac\xa6\x74\x60", /* .entprlen = */ 32, /* .addtla = */ NULL, /* .addtlb = */ NULL, /* .addtllen = */ 0, /* .pers = */ (unsigned char *) "\x64\xb6\xfc\x60\xbc\x61\x76\x23\x6d\x3f\x4a\x0f" "\xe1\xb4\xd5\x20\x9e\x70\xdd\x03\x53\x6d\xbf\xce" "\xcd\x56\x80\xbc\xb8\x15\xc8\xaa", /* .perslen = */ 32, /* .expected = */ (unsigned char *) "\x1f\x9e\xaf\xe4\xd2\x46\xb7\x47\x41\x4c\x65\x99" "\x01\xe9\x3b\xbb\x83\x0c\x0a\xb0\xc1\x3a\xe2\xb3" "\x31\x4e\xeb\x93\x73\xee\x0b\x26\xc2\x63\xa5\x75" "\x45\x99\xd4\x5c\x9f\xa1\xd4\x45\x87\x6b\x20\x61" "\x40\xea\x78\xa5\x32\xdf\x9e\x66\x17\xaf\xb1\x88" "\x9e\x2e\x23\xdd\xc1\xda\x13\x97\x88\xa5\xb6\x5e" "\x90\x14\x4e\xef\x13\xab\x5c\xd9\x2c\x97\x9e\x7c" "\xd7\xf8\xce\xea\x81\xf5\xcd\x71\x15\x49\x44\xce" "\x83\xb6\x05\xfb\x7d\x30\xb5\x57\x2c\x31\x4f\xfc" "\xfe\x80\xb6\xc0\x13\x0c\x5b\x9b\x2e\x8f\x3d\xfc" "\xc2\xa3\x0c\x11\x1b\x80\x5f\xf3", /* .expectedlen = */ 128, /* .entropyreseed = */ NULL, /* .entropyreseed_len = */ 0, /* .addtl_reseed = */ NULL, /* .addtl_reseed_len = */ 0 }, { /* .flags = */ "aes sym128 pr", /* DRBG_PR_CTRAES128 */ /* .entropy = */ (unsigned char *) "\x92\x89\x8f\x31\xfa\x1c\xff\x6d\x18\x2f\x26\x06" "\x43\xdf\xf8\x18\xc2\xa4\xd9\x72\xc3\xb9\xb6\x97", /* .entropylen = */ 24, /* .entpra = */ (unsigned char *) "\x20\x72\x8a\x06\xf8\x6f\x8d\xd4\x41\xe2\x72\xb7" "\xc4\x2c\xe8\x10", /* .entprb = */ (unsigned char *) "\x3d\xb0\xf0\x94\xf3\x05\x50\x33\x17\x86\x3e\x22" "\x08\xf7\xa5\x01", /* .entprlen = */ 16, /* .addtla = */ (unsigned char *) "\x1a\x40\xfa\xe3\xcc\x6c\x7c\xa0\xf8\xda\xba\x59" "\x23\x6d\xad\x1d", /* .addtlb = */ (unsigned char *) "\x9f\x72\x76\x6c\xc7\x46\xe5\xed\x2e\x53\x20\x12" "\xbc\x59\x31\x8c", /* .addtllen = */ 16, /* .pers = */ (unsigned char *) "\xea\x65\xee\x60\x26\x4e\x7e\xb6\x0e\x82\x68\xc4" "\x37\x3c\x5c\x0b", /* .perslen = */ 16, /* .expected = */ (unsigned char *) "\x5a\x35\x39\x87\x0f\x4d\x22\xa4\x09\x24\xee\x71" "\xc9\x6f\xac\x72\x0a\xd6\xf0\x88\x82\xd0\x83\x28" "\x73\xec\x3f\x93\xd8\xab\x45\x23\xf0\x7e\xac\x45" "\x14\x5e\x93\x9f\xb1\xd6\x76\x43\x3d\xb6\xe8\x08" "\x88\xf6\xda\x89\x08\x77\x42\xfe\x1a\xf4\x3f\xc4" "\x23\xc5\x1f\x68", /* .expectedlen = */ 64, /* .entropyreseed = */ NULL, /* .entropyreseed_len = */ 0, /* .addtl_reseed = */ NULL, /* .addtl_reseed_len = */ 0 } }; struct gcry_drbg_test_vector drbg_test_nopr[] = { { /* .flags = */ "sha256" /* DRBG_NOPR_HASHSHA256 */, /* .entropy = */ (unsigned char *) "\x73\xd3\xfb\xa3\x94\x5f\x2b\x5f\xb9\x8f\xf6\x9c" "\x8a\x93\x17\xae\x19\xc3\x4c\xc3\xd6\xca\xa3\x2d" "\x16\xfc\x42\xd2\x2d\xd5\x6f\x56\xcc\x1d\x30\xff" "\x9e\x06\x3e\x09\xce\x58\xe6\x9a\x35\xb3\xa6\x56", /* .entropylen = */ 48, /* .entpra = */ NULL, /* .entprb = */ NULL, /* .entprlen = */ 0, /* .addtla = */ (unsigned char *) "\xf4\xd5\x98\x3d\xa8\xfc\xfa\x37\xb7\x54\x67\x73" "\xc7\xc3\xdd\x47\x34\x71\x02\x5d\xc1\xa0\xd3\x10" "\xc1\x8b\xbd\xf5\x66\x34\x6f\xdd", /* .addtlb = */ (unsigned char *) "\xf7\x9e\x6a\x56\x0e\x73\xe9\xd9\x7a\xd1\x69\xe0" "\x6f\x8c\x55\x1c\x44\xd1\xce\x6f\x28\xcc\xa4\x4d" "\xa8\xc0\x85\xd1\x5a\x0c\x59\x40", /* .addtllen = */ 32, /* .pers = */ NULL, /* .perslen = */ 0, /* .expected = */ (unsigned char *) "\x71\x7b\x93\x46\x1a\x40\xaa\x35\xa4\xaa\xc5\xe7" "\x6d\x5b\x5b\x8a\xa0\xdf\x39\x7d\xae\x71\x58\x5b" "\x3c\x7c\xb4\xf0\x89\xfa\x4a\x8c\xa9\x5c\x54\xc0" "\x40\xdf\xbc\xce\x26\x81\x34\xf8\xba\x7d\x1c\xe8" "\xad\x21\xe0\x74\xcf\x48\x84\x30\x1f\xa1\xd5\x4f" "\x81\x42\x2f\xf4\xdb\x0b\x23\xf8\x73\x27\xb8\x1d" "\x42\xf8\x44\x58\xd8\x5b\x29\x27\x0a\xf8\x69\x59" "\xb5\x78\x44\xeb\x9e\xe0\x68\x6f\x42\x9a\xb0\x5b" "\xe0\x4e\xcb\x6a\xaa\xe2\xd2\xd5\x33\x25\x3e\xe0" "\x6c\xc7\x6a\x07\xa5\x03\x83\x9f\xe2\x8b\xd1\x1c" "\x70\xa8\x07\x59\x97\xeb\xf6\xbe", /* .expectedlen = */ 128, /* .entropyreseed = */ NULL, /* .entropyreseed_len = */ 0, /* .addtl_reseed = */ NULL, /* .addtl_reseed_len = */ 0 }, { /* .flags = */ "hmac sha256" /* DRBG_NOPR_HMACSHA256 */, /* .entropy = */ (unsigned char *) "\x8d\xf0\x13\xb4\xd1\x03\x52\x30\x73\x91\x7d\xdf" "\x6a\x86\x97\x93\x05\x9e\x99\x43\xfc\x86\x54\x54" "\x9e\x7a\xb2\x2f\x7c\x29\xf1\x22\xda\x26\x25\xaf" "\x2d\xdd\x4a\xbc\xce\x3c\xf4\xfa\x46\x59\xd8\x4e", /* .entropylen = */ 48, /* .entpra = */ NULL, /* .entprb = */ NULL, /* .entprlen = */ 0, /* .addtla = */ NULL, /* .addtlb = */ NULL, /* .addtllen = */ 0, /* .pers = */ (unsigned char *) "\xb5\x71\xe6\x6d\x7c\x33\x8b\xc0\x7b\x76\xad\x37" "\x57\xbb\x2f\x94\x52\xbf\x7e\x07\x43\x7a\xe8\x58" "\x1c\xe7\xbc\x7c\x3a\xc6\x51\xa9", /* .perslen = */ 32, /* .expected = */ (unsigned char *) "\xb9\x1c\xba\x4c\xc8\x4f\xa2\x5d\xf8\x61\x0b\x81" "\xb6\x41\x40\x27\x68\xa2\x09\x72\x34\x93\x2e\x37" "\xd5\x90\xb1\x15\x4c\xbd\x23\xf9\x74\x52\xe3\x10" "\xe2\x91\xc4\x51\x46\x14\x7f\x0d\xa2\xd8\x17\x61" "\xfe\x90\xfb\xa6\x4f\x94\x41\x9c\x0f\x66\x2b\x28" "\xc1\xed\x94\xda\x48\x7b\xb7\xe7\x3e\xec\x79\x8f" "\xbc\xf9\x81\xb7\x91\xd1\xbe\x4f\x17\x7a\x89\x07" "\xaa\x3c\x40\x16\x43\xa5\xb6\x2b\x87\xb8\x9d\x66" "\xb3\xa6\x0e\x40\xd4\xa8\xe4\xe9\xd8\x2a\xf6\xd2" "\x70\x0e\x6f\x53\x5c\xdb\x51\xf7\x5c\x32\x17\x29" "\x10\x37\x41\x03\x0c\xcc\x3a\x56", /* .expectedlen = */ 128, /* .entropyreseed = */ NULL, /* .entropyreseed_len = */ 0, /* .addtl_reseed = */ NULL, /* .addtl_reseed_len = */ 0 }, { /* .flags = */ "aes sym128" /* DRBG_NOPR_CTRAES128 */, /* .entropy = */ (unsigned char *) "\xc0\x70\x1f\x92\x50\x75\x8f\xcd\xf2\xbe\x73\x98" "\x80\xdb\x66\xeb\x14\x68\xb4\xa5\x87\x9c\x2d\xa6", /* .entropylen = */ 24, /* .entpra = */ NULL, /* .entprb = */ NULL, /* .entprlen = */ 0, /* .addtla = */ (unsigned char *) "\xf9\x01\xf8\x16\x7a\x1d\xff\xde\x8e\x3c\x83\xe2" "\x44\x85\xe7\xfe", /* .addtlb = */ (unsigned char *) "\x17\x1c\x09\x38\xc2\x38\x9f\x97\x87\x60\x55\xb4" "\x82\x16\x62\x7f", /* .addtllen = */ 16, /* .pers = */ (unsigned char *) "\x80\x08\xae\xe8\xe9\x69\x40\xc5\x08\x73\xc7\x9f" "\x8e\xcf\xe0\x02", /* .perslen = */ 16, /* .expected = */ (unsigned char *) "\x97\xc0\xc0\xe5\xa0\xcc\xf2\x4f\x33\x63\x48\x8a" "\xdb\x13\x0a\x35\x89\xbf\x80\x65\x62\xee\x13\x95" "\x7c\x33\xd3\x7d\xf4\x07\x77\x7a\x2b\x65\x0b\x5f" "\x45\x5c\x13\xf1\x90\x77\x7f\xc5\x04\x3f\xcc\x1a" "\x38\xf8\xcd\x1b\xbb\xd5\x57\xd1\x4a\x4c\x2e\x8a" "\x2b\x49\x1e\x5c", /* .expectedlen = */ 64, /* .entropyreseed = */ NULL, /* .entropyreseed_len = */ 0, /* .addtl_reseed = */ NULL, /* .addtl_reseed_len = */ 0 }, { /* .flags = */ "sha1" /* DRBG_NOPR_HASHSHA1 */, /* .entropy = */ (unsigned char *) "\x16\x10\xb8\x28\xcc\xd2\x7d\xe0\x8c\xee\xa0\x32" "\xa2\x0e\x92\x08\x49\x2c\xf1\x70\x92\x42\xf6\xb5", /* .entropylen = */ 24, /* .entpra = */ NULL, /* .entprb = */ NULL, /* .entprlen = */ 0, /* .addtla = */ NULL, /* .addtlb = */ NULL, /* .addtllen = */ 0, /* .pers = */ NULL, /* .perslen = */ 0, /* .expected = */ (unsigned char *) "\x56\xf3\x3d\x4f\xdb\xb9\xa5\xb6\x4d\x26\x23\x44" "\x97\xe9\xdc\xb8\x77\x98\xc6\x8d\x08\xf7\xc4\x11" "\x99\xd4\xbd\xdf\x97\xeb\xbf\x6c\xb5\x55\x0e\x5d" "\x14\x9f\xf4\xd5\xbd\x0f\x05\xf2\x5a\x69\x88\xc1" "\x74\x36\x39\x62\x27\x18\x4a\xf8\x4a\x56\x43\x35" "\x65\x8e\x2f\x85\x72\xbe\xa3\x33\xee\xe2\xab\xff" "\x22\xff\xa6\xde\x3e\x22\xac\xa2", /* .expectedlen = */ 80, /* .entropyreseed = */ (unsigned char *) "\x72\xd2\x8c\x90\x8e\xda\xf9\xa4\xd1\xe5\x26\xd8" "\xf2\xde\xd5\x44", /* .entropyreseed_len = */ 16, /* .addtl_reseed = */ NULL, /* .addtl_reseed_len = */ 0 }, { /* .flags = */ "sha1" /* DRBG_NOPR_HASHSHA1 */, /* .entropy = */ (unsigned char *) "\xd9\xba\xb5\xce\xdc\xa9\x6f\x61\x78\xd6\x45\x09" "\xa0\xdf\xdc\x5e\xda\xd8\x98\x94\x14\x45\x0e\x01", /* .entropylen = */ 24, /* .entpra = */ NULL, /* .entprb = */ NULL, /* .entprlen = */ 0, /* .addtla = */ (unsigned char *) "\x04\xfa\x28\x95\xaa\x5a\x6f\x8c\x57\x43\x34\x3b" "\x80\x5e\x5e\xa4", /* .addtlb = */ (unsigned char *) "\xdf\x5d\xc4\x59\xdf\xf0\x2a\xa2\xf0\x52\xd7\x21" "\xec\x60\x72\x30", /* .addtllen = */ 16, /* .pers = */ NULL, /* .perslen = */ 0, /* .expected = */ (unsigned char *) "\xc4\x8b\x89\xf9\xda\x3f\x74\x82\x45\x55\x5d\x5d" "\x03\x3b\x69\x3d\xd7\x1a\x4d\xf5\x69\x02\x05\xce" "\xfc\xd7\x20\x11\x3c\xc2\x4e\x09\x89\x36\xff\x5e" "\x77\xb5\x41\x53\x58\x70\xb3\x39\x46\x8c\xdd\x8d" "\x6f\xaf\x8c\x56\x16\x3a\x70\x0a\x75\xb2\x3e\x59" "\x9b\x5a\xec\xf1\x6f\x3b\xaf\x6d\x5f\x24\x19\x97" "\x1f\x24\xf4\x46\x72\x0f\xea\xbe", /* .expectedlen = */ 80, /* .entropyreseed = */ (unsigned char *) "\xc6\xba\xd0\x74\xc5\x90\x67\x86\xf5\xe1\xf3\x20" "\x99\xf5\xb4\x91", /* .entropyreseed_len = */ 16, /* .addtl_reseed = */ (unsigned char *) "\x3e\x6b\xf4\x6f\x4d\xaa\x38\x25\xd7\x19\x4e\x69" "\x4e\x77\x52\xf7", /* .addtl_reseed_len = */ 16 } }; /* * Tests implement the CAVS test approach as documented in * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/DRBGVS.pdf */ /* * CAVS test * * This function is not static as it is needed for as a private API * call for the CAVS test tool. */ gpg_err_code_t _gcry_rngdrbg_cavs_test (struct gcry_drbg_test_vector *test, unsigned char *buf) { gpg_err_code_t ret = 0; drbg_state_t drbg = NULL; struct drbg_test_data_s test_data; drbg_string_t addtl, pers, testentropy; int coreref = 0; int pr = 0; u32 flags; ret = parse_flag_string (test->flagstr, &flags); if (ret) goto outbuf; ret = drbg_algo_available (flags, &coreref); if (ret) goto outbuf; drbg = xtrycalloc_secure (1, sizeof *drbg); if (!drbg) { ret = gpg_err_code_from_syserror (); goto outbuf; } if ((flags & DRBG_PREDICTION_RESIST)) pr = 1; test_data.testentropy = &testentropy; drbg_string_fill (&testentropy, test->entropy, test->entropylen); drbg->test_data = &test_data; drbg_string_fill (&pers, test->pers, test->perslen); ret = drbg_instantiate (drbg, &pers, coreref, pr); if (ret) goto outbuf; if (test->entropyreseed) { drbg_string_fill (&testentropy, test->entropyreseed, test->entropyreseed_len); drbg_string_fill (&addtl, test->addtl_reseed, test->addtl_reseed_len); if (drbg_reseed (drbg, &addtl)) goto outbuf; } drbg_string_fill (&addtl, test->addtla, test->addtllen); if (test->entpra) { drbg_string_fill (&testentropy, test->entpra, test->entprlen); drbg->test_data = &test_data; } drbg_generate_long (drbg, buf, test->expectedlen, &addtl); drbg_string_fill (&addtl, test->addtlb, test->addtllen); if (test->entprb) { drbg_string_fill (&testentropy, test->entprb, test->entprlen); drbg->test_data = &test_data; } drbg_generate_long (drbg, buf, test->expectedlen, &addtl); drbg_uninstantiate (drbg); outbuf: xfree (drbg); return ret; } /* * Invoke the CAVS test and perform the final check whether the * calculated random value matches the expected one. * * This function is not static as it is needed for as a private API * call for the CAVS test tool. */ gpg_err_code_t _gcry_rngdrbg_healthcheck_one (struct gcry_drbg_test_vector * test) { gpg_err_code_t ret = GPG_ERR_ENOMEM; unsigned char *buf = xcalloc_secure (1, test->expectedlen); if (!buf) return GPG_ERR_ENOMEM; ret = _gcry_rngdrbg_cavs_test (test, buf); /* FIXME: The next line is wrong. */ ret = memcmp (test->expected, buf, test->expectedlen); xfree (buf); return ret; } /* * Tests as defined in 11.3.2 in addition to the cipher tests: testing * of the error handling. * * Note, testing the reseed counter is not done as an automatic reseeding * is performed in drbg_generate when the reseed counter is too large. */ static gpg_err_code_t drbg_healthcheck_sanity (struct gcry_drbg_test_vector *test) { unsigned int len = 0; drbg_state_t drbg = NULL; gpg_err_code_t ret = GPG_ERR_GENERAL; gpg_err_code_t tmpret = GPG_ERR_GENERAL; struct drbg_test_data_s test_data; drbg_string_t addtl, testentropy; int coreref = 0; unsigned char *buf = NULL; size_t max_addtllen, max_request_bytes; u32 flags; /* only perform test in FIPS mode */ if (0 == fips_mode ()) return 0; ret = parse_flag_string (test->flagstr, &flags); if (ret) return ret; ret = GPG_ERR_GENERAL; /* Fixme: Improve handling of RET. */ buf = xtrycalloc_secure (1, test->expectedlen); if (!buf) return gpg_err_code_from_syserror (); tmpret = drbg_algo_available (flags, &coreref); if (tmpret) goto outbuf; drbg = xtrycalloc_secure (1, sizeof *drbg); if (!drbg) { ret = gpg_err_code_from_syserror (); goto outbuf; } /* if the following tests fail, it is likely that there is a buffer * overflow and we get a SIGSEV */ ret = drbg_instantiate (drbg, NULL, coreref, 1); if (ret) goto outbuf; max_addtllen = drbg_max_addtl (); max_request_bytes = drbg_max_request_bytes (); /* overflow addtllen with additional info string */ drbg_string_fill (&addtl, test->addtla, (max_addtllen + 1)); len = drbg_generate (drbg, buf, test->expectedlen, &addtl); if (len) goto outdrbg; /* overflow max_bits */ len = drbg_generate (drbg, buf, (max_request_bytes + 1), NULL); if (len) goto outdrbg; drbg_uninstantiate (drbg); /* test failing entropy source as defined in 11.3.2 */ test_data.testentropy = NULL; test_data.fail_seed_source = 1; drbg->test_data = &test_data; tmpret = drbg_instantiate (drbg, NULL, coreref, 0); if (!tmpret) goto outdrbg; test_data.fail_seed_source = 0; test_data.testentropy = &testentropy; drbg_string_fill (&testentropy, test->entropy, test->entropylen); /* overflow max addtllen with personalization string */ tmpret = drbg_instantiate (drbg, &addtl, coreref, 0); if (!tmpret) goto outdrbg; dbg (("DRBG: Sanity tests for failure code paths successfully completed\n")); ret = 0; outdrbg: drbg_uninstantiate (drbg); outbuf: xfree (buf); xfree (drbg); return ret; } /* * DRBG Healthcheck function as required in SP800-90A * * return: * 0 on success (all tests pass) * >0 on error (return code indicate the number of failures) */ static int drbg_healthcheck (void) { int ret = 0; ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[0]); ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[1]); ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[2]); ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[3]); ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[4]); ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_pr[0]); ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_pr[1]); ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_pr[2]); ret += drbg_healthcheck_sanity (&drbg_test_nopr[0]); return ret; } /* Run the self-tests. */ gcry_error_t _gcry_rngdrbg_selftest (selftest_report_func_t report) { gcry_err_code_t ec; const char *errtxt = NULL; drbg_lock (); if (0 != drbg_healthcheck ()) errtxt = "RNG output does not match known value"; drbg_unlock (); if (report && errtxt) report ("random", 0, "KAT", errtxt); ec = errtxt ? GPG_ERR_SELFTEST_FAILED : 0; return gpg_error (ec); } /*************************************************************** * Cipher invocations requested by DRBG ***************************************************************/ static gpg_err_code_t 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; 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 byte * drbg_hash (drbg_state_t drbg, 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); return _gcry_md_read (hd, drbg->core->backend_cipher); } 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_init (drbg_state_t drbg) { 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); if (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)) { 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; /* 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; 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)); }