Changeset View
Changeset View
Standalone View
Standalone View
b/random/drbg.c
| /* | |||||
| * 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 | |||||
| * | |||||
| * Copyright Stephan Mueller <smueller@chronox.de>, 2014 | |||||
| * | |||||
| * 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 | |||||
| * the GNU General Public License, in which case the provisions of the GPL are | |||||
| * required INSTEAD OF the above restrictions. (This clause is | |||||
| * necessary due to a potential bad interaction between the GPL 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: | |||||
| * * __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 drbg_string *pers: personalization string to be used for | |||||
| * initialization. | |||||
| * * struct drbg_test_data *test: TEST parameter only -- should be NULL in | |||||
| * normal use -- parameter sets predefined | |||||
| * "entropy" | |||||
| * 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 kernel crypto 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 | |||||
| * ------------------------------------------------------- | |||||
| * struct drbg_string 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, NULL); | |||||
| * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); | |||||
| * | |||||
| * | |||||
| * Usage with additional information string during random number request | |||||
| * --------------------------------------------------------------------- | |||||
| * struct drbg_string 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, NULL); | |||||
| * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); | |||||
| */ | |||||
| #include <sys/types.h> | |||||
| #include <asm/types.h> | |||||
| #include <string.h> | |||||
| #include <unistd.h> | |||||
| #include <stdint.h> | |||||
| #include <config.h> | |||||
| #include "g10lib.h" | |||||
| #include "random.h" | |||||
| #include "rand-internal.h" | |||||
| #include "../cipher/bithelp.h" | |||||
| /****************************************************************** | |||||
| * Common data structures | |||||
| ******************************************************************/ | |||||
| struct drbg_state; | |||||
| struct drbg_core | |||||
| { | |||||
| u_int32_t flags; /* flags for the cipher */ | |||||
| __u8 statelen; /* maximum state length */ | |||||
| __u8 blocklen_bytes; /* block size of output in bytes */ | |||||
| int backend_cipher; /* libgcrypt backend cipher */ | |||||
| }; | |||||
| struct drbg_state_ops | |||||
| { | |||||
| gpg_err_code_t (*update) (struct drbg_state * drbg, | |||||
| struct drbg_string * seed, int reseed); | |||||
| gpg_err_code_t (*generate) (struct drbg_state * drbg, | |||||
| unsigned char *buf, unsigned int buflen, | |||||
| struct drbg_string * addtl); | |||||
| }; | |||||
| struct drbg_state | |||||
| { | |||||
| 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 */ | |||||
| int seeded:1; /* DRBG fully seeded? */ | |||||
| int pr:1; /* Prediction resistance enabled? */ | |||||
| int fips_primed:1; /* Continuous test primed? */ | |||||
| unsigned char *prev; /* previous output value of drbg_blocklen for | |||||
| * FIPS 140-2 continuous test */ | |||||
| /* 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 *d_ops; | |||||
| const struct drbg_core *core; | |||||
| struct drbg_test_data *test_data; | |||||
| }; | |||||
| enum drbg_prefixes | |||||
| { | |||||
| DRBG_PREFIX0 = 0x00, | |||||
| DRBG_PREFIX1, | |||||
| DRBG_PREFIX2, | |||||
| DRBG_PREFIX3 | |||||
| }; | |||||
| #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) | |||||
| /*************************************************************** | |||||
| * Backend cipher definitions available to DRBG | |||||
| ***************************************************************/ | |||||
| static const struct drbg_core drbg_cores[] = { | |||||
| { | |||||
| /* Hash DRBGs */ | |||||
| .flags = DRBG_HASHSHA1, | |||||
| .statelen = 55, /* 440 bits */ | |||||
| .blocklen_bytes = 20, | |||||
| .backend_cipher = GCRY_MD_SHA1, | |||||
| }, | |||||
| { | |||||
| .flags = DRBG_HASHSHA256, | |||||
| .statelen = 55, /* 440 bits */ | |||||
| .blocklen_bytes = 32, | |||||
| .backend_cipher = GCRY_MD_SHA256, | |||||
| }, | |||||
| { | |||||
| .flags = DRBG_HASHSHA384, | |||||
| .statelen = 111, /* 888 bits */ | |||||
| .blocklen_bytes = 48, | |||||
| .backend_cipher = GCRY_MD_SHA384, | |||||
| }, | |||||
| { | |||||
| .flags = DRBG_HASHSHA512, | |||||
| .statelen = 111, /* 888 bits */ | |||||
| .blocklen_bytes = 64, | |||||
| .backend_cipher = GCRY_MD_SHA512, | |||||
| }, | |||||
| { | |||||
| /* HMAC DRBGs */ | |||||
| .flags = DRBG_HASHSHA1 | DRBG_HMAC, | |||||
| .statelen = 20, /* block length of cipher */ | |||||
| .blocklen_bytes = 20, | |||||
| .backend_cipher = GCRY_MD_SHA1, | |||||
| }, | |||||
| { | |||||
| .flags = DRBG_HASHSHA256 | DRBG_HMAC, | |||||
| .statelen = 32, /* block length of cipher */ | |||||
| .blocklen_bytes = 32, | |||||
| .backend_cipher = GCRY_MD_SHA256, | |||||
| }, | |||||
| { | |||||
| .flags = DRBG_HASHSHA384 | DRBG_HMAC, | |||||
| .statelen = 48, /* block length of cipher */ | |||||
| .blocklen_bytes = 48, | |||||
| .backend_cipher = GCRY_MD_SHA384, | |||||
| }, | |||||
| { | |||||
| .flags = DRBG_HASHSHA512 | DRBG_HMAC, | |||||
| .statelen = 64, /* block length of cipher */ | |||||
| .blocklen_bytes = 64, | |||||
| .backend_cipher = GCRY_MD_SHA512, | |||||
| }, | |||||
| { | |||||
| /* block ciphers */ | |||||
| .flags = DRBG_CTRAES | DRBG_SYM128, | |||||
| .statelen = 32, /* 256 bits as defined in 10.2.1 */ | |||||
| .blocklen_bytes = 16, | |||||
| .backend_cipher = GCRY_CIPHER_AES128, | |||||
| }, | |||||
| { | |||||
| /* block ciphers */ | |||||
| .flags = DRBG_CTRAES | DRBG_SYM192, | |||||
| .statelen = 40, /* 320 bits as defined in 10.2.1 */ | |||||
| .blocklen_bytes = 16, | |||||
| .backend_cipher = GCRY_CIPHER_AES192, | |||||
| }, | |||||
| { | |||||
| /* block ciphers */ | |||||
| .flags = DRBG_CTRAES | DRBG_SYM256, | |||||
| .statelen = 48, /* 384 bits as defined in 10.2.1 */ | |||||
| .blocklen_bytes = 16, | |||||
| .backend_cipher = GCRY_CIPHER_AES256, | |||||
| }, | |||||
| }; | |||||
| /****************************************************************** | |||||
| ****************************************************************** | |||||
| ****************************************************************** | |||||
| * Generic DRBG code | |||||
| ****************************************************************** | |||||
| ****************************************************************** | |||||
| ******************************************************************/ | |||||
| /****************************************************************** | |||||
| * Generic helper functions | |||||
| ******************************************************************/ | |||||
| #if 0 | |||||
| #define dbg(x) do { log_debug x; } while(0) | |||||
| #else | |||||
| #define dbg(x) | |||||
| #endif | |||||
| int drbg_healthcheck (void); | |||||
| static inline void * | |||||
| drbg_malloc (size_t len) | |||||
| { | |||||
| void *buf; | |||||
| buf = xmalloc_secure (len); | |||||
| if (buf) | |||||
| memset (buf, 0, len); | |||||
| return buf; | |||||
| } | |||||
| static inline __u8 | |||||
| drbg_statelen (struct drbg_state *drbg) | |||||
| { | |||||
| if (drbg && drbg->core) | |||||
| return drbg->core->statelen; | |||||
| return 0; | |||||
| } | |||||
| static inline __u8 | |||||
| drbg_blocklen (struct drbg_state *drbg) | |||||
| { | |||||
| if (drbg && drbg->core) | |||||
| return drbg->core->blocklen_bytes; | |||||
| return 0; | |||||
| } | |||||
| static inline __u8 | |||||
| drbg_keylen (struct drbg_state *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 (u_int32_t 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; | |||||
| } | |||||
| /* | |||||
| * FIPS 140-2 continuous self test | |||||
| * The test is performed on the result of one round of the output | |||||
| * function. Thus, the function implicitly knows the size of the | |||||
| * buffer. | |||||
| * | |||||
| * @drbg DRBG handle | |||||
| * @buf output buffer of random data to be checked | |||||
| * | |||||
| * return: | |||||
| * false on error | |||||
| * true on success | |||||
| */ | |||||
| static gpg_err_code_t | |||||
| drbg_fips_continuous_test (struct drbg_state *drbg, const unsigned char *buf) | |||||
| { | |||||
| gpg_err_code_t ret = 0; | |||||
| /* skip test if we test the overall system */ | |||||
| if (drbg->test_data) | |||||
| return 1; | |||||
| /* only perform test in FIPS mode */ | |||||
| if (0 == fips_mode ()) | |||||
| return 1; | |||||
| if (!drbg->fips_primed) | |||||
| { | |||||
| /* Priming of FIPS test */ | |||||
| memcpy (drbg->prev, buf, drbg_blocklen (drbg)); | |||||
| drbg->fips_primed = 1; | |||||
| /* return false due to priming, i.e. another round is needed */ | |||||
| return 0; | |||||
| } | |||||
| ret = memcmp (drbg->prev, buf, drbg_blocklen (drbg)); | |||||
| memcpy (drbg->prev, buf, drbg_blocklen (drbg)); | |||||
| /* the test shall pass when the two compared values are not equal */ | |||||
| return ret != 0; | |||||
| } | |||||
| static inline void drbg_cpu_to_be32(uint32_t val, unsigned char *buf) | |||||
| { | |||||
| struct s { | |||||
| uint32_t conv; | |||||
| }; | |||||
| struct s *conversion = (struct s *) buf; | |||||
| conversion->conv = be_bswap32(val); | |||||
| } | |||||
| 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 (struct drbg_state *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 (read_cb, 0, length, | |||||
| GCRY_VERY_STRONG_RANDOM); | |||||
| #elif USE_RNDW32 | |||||
| do | |||||
| { | |||||
| rc = _gcry_rndw32_gather_random (read_cb, 0, length, | |||||
| GCRY_VERY_STRONG_RANDOM); | |||||
| } | |||||
| while (rc >= 0 && read_cb_len < read_cb_size); | |||||
| #else | |||||
| rc = -1; | |||||
| #endif | |||||
| return rc; | |||||
| } | |||||
| /****************************************************************** | |||||
| * CTR DRBG callback functions | |||||
| ******************************************************************/ | |||||
| static gpg_err_code_t drbg_gcry_sym (struct drbg_state *drbg, | |||||
| const unsigned char *key, | |||||
| unsigned char *outval, | |||||
| const struct drbg_string *buf); | |||||
| /* BCC function for CTR DRBG as defined in 10.4.3 */ | |||||
| static gpg_err_code_t | |||||
| drbg_ctr_bcc (struct drbg_state *drbg, | |||||
| unsigned char *out, const unsigned char *key, | |||||
| struct drbg_string *in) | |||||
| { | |||||
| gpg_err_code_t ret = GPG_ERR_GENERAL; | |||||
| struct drbg_string *curr = in; | |||||
| size_t inpos = curr->len; | |||||
| const unsigned char *pos = curr->buf; | |||||
| struct drbg_string data; | |||||
| drbg_string_fill (&data, out, drbg_blocklen (drbg)); | |||||
| /* 10.4.3 step 1 */ | |||||
| memset (out, 0, drbg_blocklen (drbg)); | |||||
| /* 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_gcry_sym (drbg, key, 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 (struct drbg_state *drbg, unsigned char *df_data, | |||||
| size_t bytes_to_return, struct drbg_string *addtl) | |||||
| { | |||||
| gpg_err_code_t ret = GPG_ERR_GENERAL; | |||||
| unsigned char L_N[8]; | |||||
| /* S3 is input */ | |||||
| struct drbg_string S1, S2, S4, cipherin; | |||||
| struct drbg_string *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; | |||||
| drbg_cpu_to_be32 (inputlen, &L_N[0]); | |||||
| /* 10.4.2 step 3 */ | |||||
| drbg_cpu_to_be32 (bytes_to_return, &L_N[4]); | |||||
| /* 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 */ | |||||
| drbg_cpu_to_be32 (i, iv); | |||||
| /* 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 */ | |||||
| 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_gcry_sym (drbg, temp, 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 (struct drbg_state *drbg, | |||||
| struct drbg_string *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 *temp_p, *df_data_p; /* pointer to iterate over buffers */ | |||||
| unsigned int len = 0; | |||||
| struct drbg_string cipherin; | |||||
| unsigned char prefix = DRBG_PREFIX1; | |||||
| memset (temp, 0, drbg_statelen (drbg) + drbg_blocklen (drbg)); | |||||
| if (3 > reseed) | |||||
| memset (df_data, 0, drbg_statelen (drbg)); | |||||
| /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */ | |||||
| /* TODO use reseed variable to avoid re-doing DF operation */ | |||||
| (void) reseed; | |||||
| if (addtl && 0 < addtl->len) | |||||
| { | |||||
| ret = drbg_ctr_df (drbg, df_data, drbg_statelen (drbg), addtl); | |||||
| if (ret) | |||||
| goto out; | |||||
| } | |||||
| drbg_string_fill (&cipherin, drbg->V, drbg_blocklen (drbg)); | |||||
| /* 10.2.1.3.2 step 2 and 3 -- are already covered as we memset(0) | |||||
| * all memory during initialization */ | |||||
| while (len < (drbg_statelen (drbg))) | |||||
| { | |||||
| /* 10.2.1.2 step 2.1 */ | |||||
| drbg_add_buf (drbg->V, drbg_blocklen (drbg), &prefix, 1); | |||||
| /* 10.2.1.2 step 2.2 */ | |||||
| /* using target of temp + len: 10.2.1.2 step 2.3 and 3 */ | |||||
| ret = drbg_gcry_sym (drbg, drbg->C, temp + len, &cipherin); | |||||
| if (ret) | |||||
| goto out; | |||||
| /* 10.2.1.2 step 2.3 and 3 */ | |||||
| len += drbg_blocklen (drbg); | |||||
| } | |||||
| /* 10.2.1.2 step 4 */ | |||||
| temp_p = temp; | |||||
| df_data_p = df_data; | |||||
| for (len = 0; len < drbg_statelen (drbg); len++) | |||||
| { | |||||
| *temp_p ^= *df_data_p; | |||||
| df_data_p++; | |||||
| temp_p++; | |||||
| } | |||||
| /* 10.2.1.2 step 5 */ | |||||
| memcpy (drbg->C, temp, drbg_keylen (drbg)); | |||||
| /* 10.2.1.2 step 6 */ | |||||
| memcpy (drbg->V, temp + drbg_keylen (drbg), drbg_blocklen (drbg)); | |||||
| 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 (struct drbg_state *drbg, | |||||
| unsigned char *buf, unsigned int buflen, | |||||
| struct drbg_string *addtl) | |||||
| { | |||||
| gpg_err_code_t ret = 0; | |||||
| unsigned int len = 0; | |||||
| struct drbg_string data; | |||||
| unsigned char prefix = DRBG_PREFIX1; | |||||
| 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 */ | |||||
| drbg_add_buf (drbg->V, drbg_blocklen (drbg), &prefix, 1); | |||||
| drbg_string_fill (&data, drbg->V, drbg_blocklen (drbg)); | |||||
| while (len < buflen) | |||||
| { | |||||
| unsigned int outlen = 0; | |||||
| /* 10.2.1.5.2 step 4.2 */ | |||||
| ret = drbg_gcry_sym (drbg, drbg->C, drbg->scratchpad, &data); | |||||
| if (ret) | |||||
| goto out; | |||||
| outlen = (drbg_blocklen (drbg) < (buflen - len)) ? | |||||
| drbg_blocklen (drbg) : (buflen - len); | |||||
| if (!drbg_fips_continuous_test (drbg, drbg->scratchpad)) | |||||
| { | |||||
| /* 10.2.1.5.2 step 6 */ | |||||
| drbg_add_buf (drbg->V, drbg_blocklen (drbg), &prefix, 1); | |||||
| continue; | |||||
| } | |||||
| /* 10.2.1.5.2 step 4.3 */ | |||||
| memcpy (buf + len, drbg->scratchpad, outlen); | |||||
| len += outlen; | |||||
| /* 10.2.1.5.2 step 6 */ | |||||
| if (len < buflen) | |||||
| drbg_add_buf (drbg->V, drbg_blocklen (drbg), &prefix, 1); | |||||
| } | |||||
| /* 10.2.1.5.2 step 6 */ | |||||
| if (addtl) | |||||
| addtl->next = NULL; | |||||
| ret = drbg_ctr_update (drbg, addtl, 3); | |||||
| out: | |||||
| memset (drbg->scratchpad, 0, drbg_blocklen (drbg)); | |||||
| return ret; | |||||
| } | |||||
| static struct drbg_state_ops drbg_ctr_ops = { | |||||
| .update = drbg_ctr_update, | |||||
| .generate = drbg_ctr_generate, | |||||
| }; | |||||
| /****************************************************************** | |||||
| * HMAC DRBG callback functions | |||||
| ******************************************************************/ | |||||
| static gpg_err_code_t drbg_gcry_hmac (struct drbg_state *drbg, | |||||
| const unsigned char *key, | |||||
| unsigned char *outval, | |||||
| const struct drbg_string *buf); | |||||
| static gpg_err_code_t | |||||
| drbg_hmac_update (struct drbg_state *drbg, | |||||
| struct drbg_string *seed, int reseed) | |||||
| { | |||||
| gpg_err_code_t ret = GPG_ERR_GENERAL; | |||||
| int i = 0; | |||||
| struct drbg_string seed1, seed2, cipherin; | |||||
| if (!reseed) | |||||
| { | |||||
| /* 10.1.2.3 step 2 already implicitly covered with | |||||
| * the initial memset(0) of drbg->C */ | |||||
| memset (drbg->C, 0, drbg_statelen (drbg)); | |||||
| memset (drbg->V, 1, drbg_statelen (drbg)); | |||||
| } | |||||
| /* 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--) | |||||
| { | |||||
| /* first round uses 0x0, second 0x1 */ | |||||
| unsigned char prefix = DRBG_PREFIX0; | |||||
| if (1 == i) | |||||
| prefix = DRBG_PREFIX1; | |||||
| /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */ | |||||
| seed2.buf = &prefix; | |||||
| ret = drbg_gcry_hmac (drbg, drbg->C, drbg->C, &seed1); | |||||
| if (ret) | |||||
| return ret; | |||||
| /* 10.1.2.2 step 2 and 5 -- HMAC for V */ | |||||
| ret = drbg_gcry_hmac (drbg, drbg->C, drbg->V, &cipherin); | |||||
| if (ret) | |||||
| return ret; | |||||
| /* 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 (struct drbg_state *drbg, | |||||
| unsigned char *buf, | |||||
| unsigned int buflen, struct drbg_string *addtl) | |||||
| { | |||||
| gpg_err_code_t ret = 0; | |||||
| unsigned int len = 0; | |||||
| struct drbg_string 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 */ | |||||
| ret = drbg_gcry_hmac (drbg, drbg->C, drbg->V, &data); | |||||
| if (ret) | |||||
| return ret; | |||||
| outlen = (drbg_blocklen (drbg) < (buflen - len)) ? | |||||
| drbg_blocklen (drbg) : (buflen - len); | |||||
| if (!drbg_fips_continuous_test (drbg, drbg->V)) | |||||
| continue; | |||||
| /* 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 drbg_hmac_ops = { | |||||
| .update = drbg_hmac_update, | |||||
| .generate = drbg_hmac_generate, | |||||
| }; | |||||
| /****************************************************************** | |||||
| * 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 (struct drbg_state *drbg, | |||||
| unsigned char *outval, size_t outlen, | |||||
| struct drbg_string *entropy) | |||||
| { | |||||
| gpg_err_code_t ret = 0; | |||||
| size_t len = 0; | |||||
| unsigned char input[5]; | |||||
| unsigned char *tmp = drbg->scratchpad + drbg_statelen (drbg); | |||||
| struct drbg_string data1; | |||||
| memset (tmp, 0, drbg_blocklen (drbg)); | |||||
| /* 10.4.1 step 3 */ | |||||
| input[0] = 1; | |||||
| drbg_cpu_to_be32 ((outlen * 8), &input[1]); | |||||
| /* 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 */ | |||||
| ret = drbg_gcry_hmac (drbg, NULL, tmp, &data1); | |||||
| if (ret) | |||||
| goto out; | |||||
| /* 10.4.1 step 4.2 */ | |||||
| input[0]++; | |||||
| blocklen = (drbg_blocklen (drbg) < (outlen - len)) ? | |||||
| drbg_blocklen (drbg) : (outlen - len); | |||||
| memcpy (outval + len, tmp, blocklen); | |||||
| len += blocklen; | |||||
| } | |||||
| out: | |||||
| memset (tmp, 0, drbg_blocklen (drbg)); | |||||
| return ret; | |||||
| } | |||||
| /* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */ | |||||
| static gpg_err_code_t | |||||
| drbg_hash_update (struct drbg_state *drbg, struct drbg_string *seed, | |||||
| int reseed) | |||||
| { | |||||
| gpg_err_code_t ret = 0; | |||||
| struct drbg_string 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 (struct drbg_state *drbg, struct drbg_string *addtl) | |||||
| { | |||||
| gpg_err_code_t ret = 0; | |||||
| struct drbg_string data1, data2; | |||||
| struct drbg_string *data3; | |||||
| unsigned char prefix = DRBG_PREFIX2; | |||||
| /* this is value w as per documentation */ | |||||
| memset (drbg->scratchpad, 0, drbg_blocklen (drbg)); | |||||
| /* 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 */ | |||||
| ret = drbg_gcry_hmac (drbg, NULL, drbg->scratchpad, &data1); | |||||
| if (ret) | |||||
| goto out; | |||||
| /* 10.1.1.4 step 2b */ | |||||
| drbg_add_buf (drbg->V, drbg_statelen (drbg), | |||||
| drbg->scratchpad, drbg_blocklen (drbg)); | |||||
| out: | |||||
| memset (drbg->scratchpad, 0, drbg_blocklen (drbg)); | |||||
| return ret; | |||||
| } | |||||
| /* | |||||
| * Hashgen defined in 10.1.1.4 | |||||
| */ | |||||
| static gpg_err_code_t | |||||
| drbg_hash_hashgen (struct drbg_state *drbg, | |||||
| unsigned char *buf, unsigned int buflen) | |||||
| { | |||||
| gpg_err_code_t ret = 0; | |||||
| unsigned int len = 0; | |||||
| unsigned char *src = drbg->scratchpad; | |||||
| unsigned char *dst = drbg->scratchpad + drbg_statelen (drbg); | |||||
| struct drbg_string data; | |||||
| unsigned char prefix = DRBG_PREFIX1; | |||||
| /* use the scratchpad as a lookaside buffer */ | |||||
| memset (src, 0, drbg_statelen (drbg)); | |||||
| memset (dst, 0, drbg_blocklen (drbg)); | |||||
| /* 10.1.1.4 step hashgen 2 */ | |||||
| memcpy (src, drbg->V, drbg_statelen (drbg)); | |||||
| drbg_string_fill (&data, src, drbg_statelen (drbg)); | |||||
| while (len < buflen) | |||||
| { | |||||
| unsigned int outlen = 0; | |||||
| /* 10.1.1.4 step hashgen 4.1 */ | |||||
| ret = drbg_gcry_hmac (drbg, NULL, dst, &data); | |||||
| if (ret) | |||||
| goto out; | |||||
| outlen = (drbg_blocklen (drbg) < (buflen - len)) ? | |||||
| drbg_blocklen (drbg) : (buflen - len); | |||||
| if (!drbg_fips_continuous_test (drbg, dst)) | |||||
| { | |||||
| drbg_add_buf (src, drbg_statelen (drbg), &prefix, 1); | |||||
| continue; | |||||
| } | |||||
| /* 10.1.1.4 step hashgen 4.2 */ | |||||
| memcpy (buf + len, dst, outlen); | |||||
| len += outlen; | |||||
| /* 10.1.1.4 hashgen step 4.3 */ | |||||
| if (len < buflen) | |||||
| drbg_add_buf (src, drbg_statelen (drbg), &prefix, 1); | |||||
| } | |||||
| out: | |||||
| memset (drbg->scratchpad, 0, (drbg_statelen (drbg) + drbg_blocklen (drbg))); | |||||
| return ret; | |||||
| } | |||||
| /* generate function for Hash DRBG as defined in 10.1.1.4 */ | |||||
| static gpg_err_code_t | |||||
| drbg_hash_generate (struct drbg_state *drbg, | |||||
| unsigned char *buf, unsigned int buflen, | |||||
| struct drbg_string *addtl) | |||||
| { | |||||
| gpg_err_code_t ret = 0; | |||||
| unsigned char prefix = DRBG_PREFIX3; | |||||
| struct drbg_string data1, data2; | |||||
| union | |||||
| { | |||||
| unsigned char req[8]; | |||||
| uint64_t req_int; | |||||
| } u; | |||||
| /* | |||||
| * scratchpad usage: drbg_hash_process_addtl uses the scratchpad, but | |||||
| * fully completes before returning. Thus, we can reuse the scratchpad | |||||
| */ | |||||
| /* 10.1.1.4 step 2 */ | |||||
| ret = drbg_hash_process_addtl (drbg, addtl); | |||||
| if (ret) | |||||
| 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; | |||||
| /* this is the value H as documented in 10.1.1.4 */ | |||||
| memset (drbg->scratchpad, 0, drbg_blocklen (drbg)); | |||||
| /* 10.1.1.4 step 4 */ | |||||
| drbg_string_fill (&data1, &prefix, 1); | |||||
| drbg_string_fill (&data2, drbg->V, drbg_statelen (drbg)); | |||||
| data1.next = &data2; | |||||
| ret = drbg_gcry_hmac (drbg, NULL, drbg->scratchpad, &data1); | |||||
| if (ret) | |||||
| goto out; | |||||
| /* 10.1.1.4 step 5 */ | |||||
| drbg_add_buf (drbg->V, drbg_statelen (drbg), | |||||
| drbg->scratchpad, drbg_blocklen (drbg)); | |||||
| drbg_add_buf (drbg->V, drbg_statelen (drbg), drbg->C, drbg_statelen (drbg)); | |||||
| u.req_int = be_bswap64(drbg->reseed_ctr); | |||||
| drbg_add_buf (drbg->V, drbg_statelen (drbg), u.req, sizeof (u.req)); | |||||
| out: | |||||
| memset (drbg->scratchpad, 0, drbg_blocklen (drbg)); | |||||
| return ret; | |||||
| } | |||||
| /* | |||||
| * scratchpad usage: as update and generate are used isolated, both | |||||
| * can use the scratchpad | |||||
| */ | |||||
| static struct drbg_state_ops drbg_hash_ops = { | |||||
| .update = drbg_hash_update, | |||||
| .generate = drbg_hash_generate, | |||||
| }; | |||||
| /****************************************************************** | |||||
| * 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 (struct drbg_state *drbg, struct drbg_string *pers, int reseed) | |||||
| { | |||||
| gpg_err_code_t ret = 0; | |||||
| unsigned char *entropy = NULL; | |||||
| size_t entropylen = 0; | |||||
| struct drbg_string 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 = drbg_malloc (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: | |||||
| if (entropy) | |||||
| 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 (struct drbg_state *drbg, | |||||
| unsigned char *buf, unsigned int buflen, | |||||
| struct drbg_string *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 (struct drbg_state *drbg, | |||||
| unsigned char *buf, unsigned int buflen, | |||||
| struct drbg_string *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 (struct drbg_state *drbg) | |||||
| { | |||||
| if (!drbg) | |||||
| return GPG_ERR_INV_ARG; | |||||
| if (drbg->V) | |||||
| xfree (drbg->V); | |||||
| drbg->V = NULL; | |||||
| if (drbg->C) | |||||
| xfree (drbg->C); | |||||
| drbg->C = NULL; | |||||
| drbg->reseed_ctr = 0; | |||||
| if (drbg->scratchpad) | |||||
| xfree (drbg->scratchpad); | |||||
| drbg->scratchpad = NULL; | |||||
| drbg->seeded = 0; | |||||
| drbg->pr = 0; | |||||
| drbg->fips_primed = 0; | |||||
| if (drbg->prev) | |||||
| xfree (drbg->prev); | |||||
| drbg->prev = NULL; | |||||
| 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 (struct drbg_state *drbg, struct drbg_string *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 */ | |||||
| /* no allocation of drbg as this is done by the kernel crypto API */ | |||||
| drbg->V = drbg_malloc (drbg_statelen (drbg)); | |||||
| if (!drbg->V) | |||||
| goto err; | |||||
| drbg->C = drbg_malloc (drbg_statelen (drbg)); | |||||
| if (!drbg->C) | |||||
| goto err; | |||||
| drbg->prev = drbg_malloc (drbg_blocklen (drbg)); | |||||
| if (!drbg->prev) | |||||
| goto err; | |||||
| drbg->fips_primed = 0; | |||||
| /* 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) + drbg_blocklen (drbg); | |||||
| if (0 < sb_size) | |||||
| { | |||||
| drbg->scratchpad = drbg_malloc (sb_size); | |||||
| if (!drbg->scratchpad) | |||||
| goto err; | |||||
| } | |||||
| dbg (("DRBG: state allocated with scratchpad size %u bytes\n", sb_size)); | |||||
| /* 9.1 step 6 through 11 */ | |||||
| ret = drbg_seed (drbg, pers, 0); | |||||
| if (ret) | |||||
| goto err; | |||||
| dbg (("DRBG: core %d %s prediction resistance successfully initialized\n", | |||||
| coreref, pr ? "with" : "without")); | |||||
| return 0; | |||||
| 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 (struct drbg_state *drbg, struct drbg_string *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 | |||||
| ***************************************************************/ | |||||
| /* global state variable holding the current instance of the DRBG -- the | |||||
| * default DRBG type is defined in _gcry_drbg_init */ | |||||
| static struct drbg_state *gcry_drbg = NULL; | |||||
| GPGRT_LOCK_DEFINE (drbg_gcry_lock); | |||||
| static inline void | |||||
| drbg_lock (void) | |||||
| { | |||||
| gpg_err_code_t rc; | |||||
| rc = gpgrt_lock_lock (&drbg_gcry_lock); | |||||
| if (rc) | |||||
| log_fatal ("failed to acquire the RNG lock: %s\n", gpg_strerror (rc)); | |||||
| } | |||||
| static inline void | |||||
| drbg_unlock (void) | |||||
| { | |||||
| gpg_err_code_t rc; | |||||
| rc = gpgrt_lock_unlock (&drbg_gcry_lock); | |||||
| if (rc) | |||||
| log_fatal ("failed to release the RNG lock: %s\n", gpg_strerror (rc)); | |||||
| } | |||||
| /****** 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 (u_int32_t 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 | |||||
| _gcry_drbg_init_internal (int full, u_int32_t flags, struct drbg_string *pers) | |||||
| { | |||||
| gpg_err_code_t ret = 0; | |||||
| static u_int32_t oldflags = 0; | |||||
| int coreref = 0; | |||||
| int pr = 0; | |||||
| /* TODO what shall we do with the full variable? */ | |||||
| (void) full; | |||||
| /* 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 (0 == flags) | |||||
| flags = oldflags; | |||||
| else | |||||
| oldflags = flags; | |||||
| ret = drbg_algo_available (flags, &coreref); | |||||
| if (ret) | |||||
| return ret; | |||||
| if (NULL != gcry_drbg) | |||||
| { | |||||
| drbg_uninstantiate (gcry_drbg); | |||||
| } | |||||
| else | |||||
| { | |||||
| gcry_drbg = drbg_malloc (sizeof (struct drbg_state)); | |||||
| if (!gcry_drbg) | |||||
| return GPG_ERR_ENOMEM; | |||||
| } | |||||
| if (flags & DRBG_PREDICTION_RESIST) | |||||
| pr = 1; | |||||
| ret = drbg_instantiate (gcry_drbg, pers, coreref, pr); | |||||
| if (ret) | |||||
| fips_signal_error ("DRBG cannot be initialized"); | |||||
| else | |||||
| gcry_drbg->seed_init_pid = getpid (); | |||||
| return ret; | |||||
| } | |||||
| /************* calls available to common RNG code **************/ | |||||
| /* | |||||
| * Initialize one DRBG invoked by the libgcrypt API | |||||
| * | |||||
| * Function uses the kernel crypto API cra_name to look up | |||||
| * the flags to instantiate the DRBG | |||||
| */ | |||||
| void | |||||
| _gcry_drbg_init (int full) | |||||
| { | |||||
| /* default DRBG */ | |||||
| u_int32_t flags = DRBG_NOPR_HMACSHA256; | |||||
| drbg_lock (); | |||||
| _gcry_drbg_init_internal (full, flags, 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 == 0, do not change current DRBG | |||||
| * If parsonalization string is NULL or its length is 0, re-initialize without | |||||
| * personalization string | |||||
| * | |||||
| * If test_data is provided, the "entropy" is provided instead of using | |||||
| * the noise source. | |||||
| */ | |||||
| gpg_err_code_t | |||||
| _gcry_drbg_reinit (u_int32_t flags, struct drbg_string *pers, | |||||
| struct drbg_test_data *test_data) | |||||
| { | |||||
| gpg_err_code_t ret = GPG_ERR_GENERAL; | |||||
| dbg (("DRBG: reinitialize internal DRBG state with flags %u\n", flags)); | |||||
| drbg_lock (); | |||||
| gcry_drbg->test_data = test_data; | |||||
| ret = _gcry_drbg_init_internal (1, flags, pers); | |||||
| drbg_unlock (); | |||||
| return ret; | |||||
| } | |||||
| /* Try to close the FDs of the random gather module. This is | |||||
| * currently only implemented for rndlinux. */ | |||||
| void | |||||
| _gcry_drbg_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_drbg_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_drbg_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_drng_add_bytes (const void *buf, size_t buflen, int quality) | |||||
| { | |||||
| gpg_err_code_t ret = 0; | |||||
| struct drbg_string seed; | |||||
| (void) quality; | |||||
| if (NULL == gcry_drbg) | |||||
| return GPG_ERR_GENERAL; | |||||
| drbg_string_fill (&seed, (unsigned char *) buf, buflen); | |||||
| drbg_lock (); | |||||
| ret = drbg_reseed (gcry_drbg, &seed); | |||||
| drbg_unlock (); | |||||
| return ret; | |||||
| } | |||||
| /* This function is to be used for all types of random numbers, including | |||||
| * nonces | |||||
| */ | |||||
| void | |||||
| _gcry_drbg_randomize (void *buffer, size_t length, | |||||
| enum gcry_random_level level) | |||||
| { | |||||
| (void) level; | |||||
| drbg_lock (); | |||||
| if (NULL == gcry_drbg) | |||||
| { | |||||
| 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 (gcry_drbg->seed_init_pid != getpid ()) | |||||
| { | |||||
| /* We are in a child of us. Perform a reseeding. */ | |||||
| if (drbg_reseed (gcry_drbg, 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 (gcry_drbg, buffer, (unsigned int) length, NULL)) | |||||
| log_fatal ("No random numbers generated\n"); | |||||
| } | |||||
| else | |||||
| { | |||||
| struct drbg_gen *data = (struct drbg_gen *) buffer; | |||||
| /* catch NULL pointer */ | |||||
| if (!data || !data->outbuf) | |||||
| { | |||||
| fips_signal_error ("No output buffer provided"); | |||||
| goto bailout; | |||||
| } | |||||
| gcry_drbg->test_data = data->test_data; | |||||
| if (drbg_generate_long (gcry_drbg, 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 drbg_test_vector | |||||
| { | |||||
| u_int32_t flags; | |||||
| unsigned char *entropy; | |||||
| size_t entropylen; | |||||
| unsigned char *entpra; | |||||
| unsigned char *entprb; | |||||
| size_t entprlen; | |||||
| unsigned char *addtla; | |||||
| unsigned char *addtlb; | |||||
| size_t addtllen; | |||||
| unsigned char *pers; | |||||
| size_t perslen; | |||||
| unsigned char *expected; | |||||
| size_t expectedlen; | |||||
| }; | |||||
| struct drbg_test_vector drbg_test_pr[] = { | |||||
| { | |||||
| .flags = (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, | |||||
| .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, | |||||
| .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, | |||||
| }, | |||||
| { | |||||
| .flags = (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, | |||||
| .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, | |||||
| .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, | |||||
| }, | |||||
| { | |||||
| .flags = (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, | |||||
| .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, | |||||
| .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, | |||||
| }, | |||||
| }; | |||||
| struct drbg_test_vector drbg_test_nopr[] = { | |||||
| { | |||||
| .flags = 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, | |||||
| .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, | |||||
| .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, | |||||
| }, | |||||
| { | |||||
| .flags = 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, | |||||
| .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, | |||||
| .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, | |||||
| }, | |||||
| { | |||||
| .flags = 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, | |||||
| .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, | |||||
| .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, | |||||
| }, | |||||
| }; | |||||
| /* | |||||
| * Tests implement the CAVS test approach as documented in | |||||
| * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/DRBGVS.pdf | |||||
| */ | |||||
| /* | |||||
| * CAVS test | |||||
| */ | |||||
| static gpg_err_code_t | |||||
| drbg_healthcheck_one (struct drbg_test_vector *test) | |||||
| { | |||||
| gpg_err_code_t ret = GPG_ERR_ENOMEM; | |||||
| struct drbg_state *drbg = NULL; | |||||
| struct drbg_test_data test_data; | |||||
| struct drbg_string addtl, pers, testentropy; | |||||
| int coreref = 0; | |||||
| int pr = 0; | |||||
| unsigned char *buf = drbg_malloc (test->expectedlen); | |||||
| if (!buf) | |||||
| return GPG_ERR_ENOMEM; | |||||
| ret = drbg_algo_available (test->flags, &coreref); | |||||
| if (ret) | |||||
| goto outbuf; | |||||
| drbg = drbg_malloc (sizeof (struct drbg_state)); | |||||
| if (!drbg) | |||||
| goto outbuf; | |||||
| if (test->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; | |||||
| 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); | |||||
| ret = memcmp (test->expected, buf, test->expectedlen); | |||||
| drbg_uninstantiate (drbg); | |||||
| outbuf: | |||||
| xfree (buf); | |||||
| if (drbg) | |||||
| xfree (drbg); | |||||
| 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 drbg_test_vector *test) | |||||
| { | |||||
| unsigned int len = 0; | |||||
| struct drbg_state *drbg = NULL; | |||||
| gpg_err_code_t ret = GPG_ERR_GENERAL; | |||||
| gpg_err_code_t tmpret = GPG_ERR_GENERAL; | |||||
| struct drbg_test_data test_data; | |||||
| struct drbg_string addtl, testentropy; | |||||
| int coreref = 0; | |||||
| unsigned char *buf = NULL; | |||||
| size_t max_addtllen, max_request_bytes; | |||||
| /* only perform test in FIPS mode */ | |||||
| if (0 == fips_mode ()) | |||||
| return 0; | |||||
| buf = drbg_malloc (test->expectedlen); | |||||
| if (!buf) | |||||
| return GPG_ERR_ENOMEM; | |||||
| tmpret = drbg_algo_available (test->flags, &coreref); | |||||
| if (tmpret) | |||||
| goto outbuf; | |||||
| drbg = drbg_malloc (sizeof (struct drbg_state)); | |||||
| if (!drbg) | |||||
| 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 additonal 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; | |||||
| /* test uninstantated DRBG */ | |||||
| len = drbg_generate (drbg, buf, (max_request_bytes + 1), NULL); | |||||
| if (len) | |||||
| goto outbuf; | |||||
| dbg (("DRBG: Sanity tests for failure code paths successfully completed\n")); | |||||
| ret = 0; | |||||
| outdrbg: | |||||
| drbg_uninstantiate (drbg); | |||||
| outbuf: | |||||
| xfree (buf); | |||||
| if (drbg) | |||||
| 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) | |||||
| */ | |||||
| int | |||||
| drbg_healthcheck (void) | |||||
| { | |||||
| int ret = 0; | |||||
| ret += drbg_healthcheck_one (&drbg_test_nopr[0]); | |||||
| ret += drbg_healthcheck_one (&drbg_test_nopr[1]); | |||||
| ret += drbg_healthcheck_one (&drbg_test_nopr[2]); | |||||
| ret += drbg_healthcheck_one (&drbg_test_pr[0]); | |||||
| ret += drbg_healthcheck_one (&drbg_test_pr[1]); | |||||
| ret += drbg_healthcheck_one (&drbg_test_pr[2]); | |||||
| ret += drbg_healthcheck_sanity (&drbg_test_nopr[0]); | |||||
| return ret; | |||||
| } | |||||
| /* Run the self-tests. */ | |||||
| gcry_error_t | |||||
| _gcry_drbg_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_gcry_hmac (struct drbg_state *drbg, const unsigned char *key, | |||||
| unsigned char *outval, const struct drbg_string *buf) | |||||
| { | |||||
| gpg_error_t err; | |||||
| gcry_md_hd_t hd; | |||||
| if (key) | |||||
| { | |||||
| err = _gcry_md_open (&hd, drbg->core->backend_cipher, GCRY_MD_FLAG_HMAC); | |||||
| if (err) | |||||
| return err; | |||||
| err = _gcry_md_setkey (hd, key, drbg_statelen (drbg)); | |||||
| if (err) | |||||
| return err; | |||||
| } | |||||
| else | |||||
| { | |||||
| err = _gcry_md_open (&hd, drbg->core->backend_cipher, 0); | |||||
| if (err) | |||||
| return err; | |||||
| } | |||||
| for (; NULL != buf; buf = buf->next) | |||||
| _gcry_md_write (hd, buf->buf, buf->len); | |||||
| _gcry_md_final (hd); | |||||
| memcpy (outval, _gcry_md_read (hd, drbg->core->backend_cipher), | |||||
| drbg_blocklen (drbg)); | |||||
| _gcry_md_close (hd); | |||||
| return 0; | |||||
| } | |||||
| static gpg_err_code_t | |||||
| drbg_gcry_sym (struct drbg_state *drbg, const unsigned char *key, | |||||
| unsigned char *outval, const struct drbg_string *buf) | |||||
| { | |||||
| gpg_error_t err; | |||||
| gcry_cipher_hd_t hd; | |||||
| err = | |||||
| _gcry_cipher_open (&hd, drbg->core->backend_cipher, GCRY_CIPHER_MODE_ECB, | |||||
| 0); | |||||
| if (err) | |||||
| return err; | |||||
| if (drbg_blocklen (drbg) != | |||||
| _gcry_cipher_get_algo_blklen (drbg->core->backend_cipher)) | |||||
| return -GPG_ERR_NO_ERROR; | |||||
| if (drbg_blocklen (drbg) < buf->len) | |||||
| return -GPG_ERR_NO_ERROR; | |||||
| err = _gcry_cipher_setkey (hd, key, drbg_keylen (drbg)); | |||||
| if (err) | |||||
| return err; | |||||
| /* in is only component */ | |||||
| _gcry_cipher_encrypt (hd, outval, drbg_blocklen (drbg), buf->buf, buf->len); | |||||
| _gcry_cipher_close (hd); | |||||
| return 0; | |||||
| } | |||||