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; | |||||
} |