mirror of
https://github.com/openssl/openssl.git
synced 2024-11-27 05:21:51 +08:00
crypto/rand: restore the generic DRBG implementation
The DRGB concept described in NIST SP 800-90A provides for having different algorithms to generate random output. In fact, the FIPS object module used to implement three of them, CTR DRBG, HASH DRBG and HMAC DRBG. When the FIPS code was ported to master in #4019, two of the three algorithms were dropped, and together with those the entire code that made RAND_DRBG generic was removed, since only one concrete implementation was left. This commit restores the original generic implementation of the DRBG, making it possible again to add additional implementations using different algorithms (like RAND_DRBG_CHACHA20) in the future. Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Tim Hudson <tjh@openssl.org> (Merged from https://github.com/openssl/openssl/pull/4998)
This commit is contained in:
parent
4e585e7201
commit
8212d50576
@ -893,6 +893,7 @@ RAND_F_RAND_DRBG_NEW:109:RAND_DRBG_new
|
||||
RAND_F_RAND_DRBG_RESEED:110:RAND_DRBG_reseed
|
||||
RAND_F_RAND_DRBG_RESTART:102:rand_drbg_restart
|
||||
RAND_F_RAND_DRBG_SET:104:RAND_DRBG_set
|
||||
RAND_F_RAND_DRBG_UNINSTANTIATE:118:RAND_DRBG_uninstantiate
|
||||
RAND_F_RAND_LOAD_FILE:111:RAND_load_file
|
||||
RAND_F_RAND_POOL_ADD:103:RAND_POOL_add
|
||||
RAND_F_RAND_POOL_ADD_BEGIN:113:RAND_POOL_add_begin
|
||||
@ -2258,6 +2259,7 @@ RAND_R_INTERNAL_ERROR:113:internal error
|
||||
RAND_R_IN_ERROR_STATE:114:in error state
|
||||
RAND_R_NOT_A_REGULAR_FILE:122:Not a regular file
|
||||
RAND_R_NOT_INSTANTIATED:115:not instantiated
|
||||
RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED:128:no drbg implementation selected
|
||||
RAND_R_PERSONALISATION_STRING_TOO_LONG:116:personalisation string too long
|
||||
RAND_R_PRNG_NOT_SEEDED:100:PRNG not seeded
|
||||
RAND_R_RANDOM_POOL_OVERFLOW:125:random pool overflow
|
||||
|
@ -201,7 +201,7 @@ static void ctr_update(RAND_DRBG *drbg,
|
||||
const unsigned char *in2, size_t in2len,
|
||||
const unsigned char *nonce, size_t noncelen)
|
||||
{
|
||||
RAND_DRBG_CTR *ctr = &drbg->ctr;
|
||||
RAND_DRBG_CTR *ctr = &drbg->data.ctr;
|
||||
|
||||
/* ks is already setup for correct key */
|
||||
inc_128(ctr);
|
||||
@ -236,12 +236,12 @@ static void ctr_update(RAND_DRBG *drbg,
|
||||
AES_set_encrypt_key(ctr->K, drbg->strength, &ctr->ks);
|
||||
}
|
||||
|
||||
int ctr_instantiate(RAND_DRBG *drbg,
|
||||
const unsigned char *entropy, size_t entropylen,
|
||||
const unsigned char *nonce, size_t noncelen,
|
||||
const unsigned char *pers, size_t perslen)
|
||||
static int drbg_ctr_instantiate(RAND_DRBG *drbg,
|
||||
const unsigned char *entropy, size_t entropylen,
|
||||
const unsigned char *nonce, size_t noncelen,
|
||||
const unsigned char *pers, size_t perslen)
|
||||
{
|
||||
RAND_DRBG_CTR *ctr = &drbg->ctr;
|
||||
RAND_DRBG_CTR *ctr = &drbg->data.ctr;
|
||||
|
||||
if (entropy == NULL)
|
||||
return 0;
|
||||
@ -253,9 +253,9 @@ int ctr_instantiate(RAND_DRBG *drbg,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ctr_reseed(RAND_DRBG *drbg,
|
||||
const unsigned char *entropy, size_t entropylen,
|
||||
const unsigned char *adin, size_t adinlen)
|
||||
static int drbg_ctr_reseed(RAND_DRBG *drbg,
|
||||
const unsigned char *entropy, size_t entropylen,
|
||||
const unsigned char *adin, size_t adinlen)
|
||||
{
|
||||
if (entropy == NULL)
|
||||
return 0;
|
||||
@ -263,11 +263,11 @@ int ctr_reseed(RAND_DRBG *drbg,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ctr_generate(RAND_DRBG *drbg,
|
||||
unsigned char *out, size_t outlen,
|
||||
const unsigned char *adin, size_t adinlen)
|
||||
static int drbg_ctr_generate(RAND_DRBG *drbg,
|
||||
unsigned char *out, size_t outlen,
|
||||
const unsigned char *adin, size_t adinlen)
|
||||
{
|
||||
RAND_DRBG_CTR *ctr = &drbg->ctr;
|
||||
RAND_DRBG_CTR *ctr = &drbg->data.ctr;
|
||||
|
||||
if (adin != NULL && adinlen != 0) {
|
||||
ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0);
|
||||
@ -299,15 +299,22 @@ int ctr_generate(RAND_DRBG *drbg,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ctr_uninstantiate(RAND_DRBG *drbg)
|
||||
static int drbg_ctr_uninstantiate(RAND_DRBG *drbg)
|
||||
{
|
||||
OPENSSL_cleanse(&drbg->ctr, sizeof(drbg->ctr));
|
||||
OPENSSL_cleanse(&drbg->data.ctr, sizeof(drbg->data.ctr));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ctr_init(RAND_DRBG *drbg)
|
||||
static RAND_DRBG_METHOD drbg_ctr_meth = {
|
||||
drbg_ctr_instantiate,
|
||||
drbg_ctr_reseed,
|
||||
drbg_ctr_generate,
|
||||
drbg_ctr_uninstantiate
|
||||
};
|
||||
|
||||
int drbg_ctr_init(RAND_DRBG *drbg)
|
||||
{
|
||||
RAND_DRBG_CTR *ctr = &drbg->ctr;
|
||||
RAND_DRBG_CTR *ctr = &drbg->data.ctr;
|
||||
size_t keylen;
|
||||
|
||||
switch (drbg->nid) {
|
||||
@ -325,6 +332,8 @@ int ctr_init(RAND_DRBG *drbg)
|
||||
break;
|
||||
}
|
||||
|
||||
drbg->meth = &drbg_ctr_meth;
|
||||
|
||||
ctr->keylen = keylen;
|
||||
drbg->strength = keylen * 8;
|
||||
drbg->seedlen = keylen + 16;
|
||||
|
@ -124,7 +124,7 @@ int RAND_DRBG_set(RAND_DRBG *drbg, int nid, unsigned int flags)
|
||||
case NID_aes_128_ctr:
|
||||
case NID_aes_192_ctr:
|
||||
case NID_aes_256_ctr:
|
||||
ret = ctr_init(drbg);
|
||||
ret = drbg_ctr_init(drbg);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -172,7 +172,8 @@ void RAND_DRBG_free(RAND_DRBG *drbg)
|
||||
if (drbg == NULL)
|
||||
return;
|
||||
|
||||
ctr_uninstantiate(drbg);
|
||||
if (drbg->meth != NULL)
|
||||
drbg->meth->uninstantiate(drbg);
|
||||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DRBG, drbg, &drbg->ex_data);
|
||||
OPENSSL_clear_free(drbg, sizeof(*drbg));
|
||||
}
|
||||
@ -196,6 +197,14 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg,
|
||||
RAND_R_PERSONALISATION_STRING_TOO_LONG);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (drbg->meth == NULL)
|
||||
{
|
||||
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
|
||||
RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (drbg->state != DRBG_UNINITIALISED) {
|
||||
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
|
||||
drbg->state == DRBG_ERROR ? RAND_R_IN_ERROR_STATE
|
||||
@ -223,7 +232,7 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg,
|
||||
}
|
||||
}
|
||||
|
||||
if (!ctr_instantiate(drbg, entropy, entropylen,
|
||||
if (!drbg->meth->instantiate(drbg, entropy, entropylen,
|
||||
nonce, noncelen, pers, perslen)) {
|
||||
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_INSTANTIATING_DRBG);
|
||||
goto end;
|
||||
@ -267,11 +276,18 @@ end:
|
||||
*/
|
||||
int RAND_DRBG_uninstantiate(RAND_DRBG *drbg)
|
||||
{
|
||||
if (drbg->meth == NULL)
|
||||
{
|
||||
RANDerr(RAND_F_RAND_DRBG_UNINSTANTIATE,
|
||||
RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Clear the entire drbg->ctr struct, then reset some important
|
||||
* members of the drbg->ctr struct (e.g. keysize, df_ks) to their
|
||||
* initial values.
|
||||
*/
|
||||
ctr_uninstantiate(drbg);
|
||||
drbg->meth->uninstantiate(drbg);
|
||||
return RAND_DRBG_set(drbg, drbg->nid, drbg->flags);
|
||||
}
|
||||
|
||||
@ -314,7 +330,7 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg,
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!ctr_reseed(drbg, entropy, entropylen, adin, adinlen))
|
||||
if (!drbg->meth->reseed(drbg, entropy, entropylen, adin, adinlen))
|
||||
goto end;
|
||||
|
||||
drbg->state = DRBG_READY;
|
||||
@ -420,7 +436,7 @@ int rand_drbg_restart(RAND_DRBG *drbg,
|
||||
* entropy from the trusted entropy source using get_entropy().
|
||||
* This is not a reseeding in the strict sense of NIST SP 800-90A.
|
||||
*/
|
||||
ctr_reseed(drbg, adin, adinlen, NULL, 0);
|
||||
drbg->meth->reseed(drbg, adin, adinlen, NULL, 0);
|
||||
} else if (reseeded == 0) {
|
||||
/* do a full reseeding if it has not been done yet above */
|
||||
RAND_DRBG_reseed(drbg, NULL, 0);
|
||||
@ -507,7 +523,7 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
|
||||
adinlen = 0;
|
||||
}
|
||||
|
||||
if (!ctr_generate(drbg, out, outlen, adin, adinlen)) {
|
||||
if (!drbg->meth->generate(drbg, out, outlen, adin, adinlen)) {
|
||||
drbg->state = DRBG_ERROR;
|
||||
RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_GENERATE_ERROR);
|
||||
return 0;
|
||||
|
@ -27,6 +27,8 @@ static const ERR_STRING_DATA RAND_str_functs[] = {
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_RESEED, 0), "RAND_DRBG_reseed"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_RESTART, 0), "rand_drbg_restart"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_SET, 0), "RAND_DRBG_set"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_UNINSTANTIATE, 0),
|
||||
"RAND_DRBG_uninstantiate"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_LOAD_FILE, 0), "RAND_load_file"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ADD, 0), "RAND_POOL_add"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ADD_BEGIN, 0),
|
||||
@ -76,6 +78,8 @@ static const ERR_STRING_DATA RAND_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NOT_A_REGULAR_FILE),
|
||||
"Not a regular file"},
|
||||
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NOT_INSTANTIATED), "not instantiated"},
|
||||
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED),
|
||||
"no drbg implementation selected"},
|
||||
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PERSONALISATION_STRING_TOO_LONG),
|
||||
"personalisation string too long"},
|
||||
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PRNG_NOT_SEEDED), "PRNG not seeded"},
|
||||
|
@ -54,6 +54,42 @@ typedef enum drbg_status_e {
|
||||
} DRBG_STATUS;
|
||||
|
||||
|
||||
/* intantiate */
|
||||
typedef int (*RAND_DRBG_instantiate_fn)(RAND_DRBG *ctx,
|
||||
const unsigned char *ent,
|
||||
size_t entlen,
|
||||
const unsigned char *nonce,
|
||||
size_t noncelen,
|
||||
const unsigned char *pers,
|
||||
size_t perslen);
|
||||
/* reseed */
|
||||
typedef int (*RAND_DRBG_reseed_fn)(RAND_DRBG *ctx,
|
||||
const unsigned char *ent,
|
||||
size_t entlen,
|
||||
const unsigned char *adin,
|
||||
size_t adinlen);
|
||||
/* generat output */
|
||||
typedef int (*RAND_DRBG_generate_fn)(RAND_DRBG *ctx,
|
||||
unsigned char *out,
|
||||
size_t outlen,
|
||||
const unsigned char *adin,
|
||||
size_t adinlen);
|
||||
/* uninstantiate */
|
||||
typedef int (*RAND_DRBG_uninstantiate_fn)(RAND_DRBG *ctx);
|
||||
|
||||
|
||||
/*
|
||||
* The DRBG methods
|
||||
*/
|
||||
|
||||
typedef struct rand_drbg_method_st {
|
||||
RAND_DRBG_instantiate_fn instantiate;
|
||||
RAND_DRBG_reseed_fn reseed;
|
||||
RAND_DRBG_generate_fn generate;
|
||||
RAND_DRBG_uninstantiate_fn uninstantiate;
|
||||
} RAND_DRBG_METHOD;
|
||||
|
||||
|
||||
/*
|
||||
* The state of a DRBG AES-CTR.
|
||||
*/
|
||||
@ -96,7 +132,7 @@ struct rand_drbg_st {
|
||||
/*
|
||||
* The following parameters are setup by the per-type "init" function.
|
||||
*
|
||||
* Currently the only type is CTR_DRBG, its init function is ctr_init().
|
||||
* Currently the only type is CTR_DRBG, its init function is drbg_ctr_init().
|
||||
*
|
||||
* The parameters are closely related to the ones described in
|
||||
* section '10.2.1 CTR_DRBG' of [NIST SP 800-90Ar1], with one
|
||||
@ -148,8 +184,13 @@ struct rand_drbg_st {
|
||||
/* Application data, mainly used in the KATs. */
|
||||
CRYPTO_EX_DATA ex_data;
|
||||
|
||||
/* Implementation specific structures; was a union, but inline for now */
|
||||
RAND_DRBG_CTR ctr;
|
||||
/* Implementation specific data (currently only one implementation) */
|
||||
union {
|
||||
RAND_DRBG_CTR ctr;
|
||||
} data;
|
||||
|
||||
/* Implementation specific methods */
|
||||
RAND_DRBG_METHOD *meth;
|
||||
|
||||
/* Callback functions. See comments in rand_lib.c */
|
||||
RAND_DRBG_get_entropy_fn get_entropy;
|
||||
@ -179,18 +220,7 @@ void rand_drbg_cleanup_entropy(RAND_DRBG *drbg,
|
||||
int rand_drbg_restart(RAND_DRBG *drbg,
|
||||
const unsigned char *buffer, size_t len, size_t entropy);
|
||||
|
||||
/* DRBG functions implementing AES-CTR */
|
||||
int ctr_init(RAND_DRBG *drbg);
|
||||
int ctr_uninstantiate(RAND_DRBG *drbg);
|
||||
int ctr_instantiate(RAND_DRBG *drbg,
|
||||
const unsigned char *entropy, size_t entropylen,
|
||||
const unsigned char *nonce, size_t noncelen,
|
||||
const unsigned char *pers, size_t perslen);
|
||||
int ctr_reseed(RAND_DRBG *drbg,
|
||||
const unsigned char *entropy, size_t entropylen,
|
||||
const unsigned char *adin, size_t adinlen);
|
||||
int ctr_generate(RAND_DRBG *drbg,
|
||||
unsigned char *out, size_t outlen,
|
||||
const unsigned char *adin, size_t adinlen);
|
||||
/* initializes the AES-CTR DRBG implementation */
|
||||
int drbg_ctr_init(RAND_DRBG *drbg);
|
||||
|
||||
#endif
|
||||
|
@ -33,6 +33,7 @@ int ERR_load_RAND_strings(void);
|
||||
# define RAND_F_RAND_DRBG_RESEED 110
|
||||
# define RAND_F_RAND_DRBG_RESTART 102
|
||||
# define RAND_F_RAND_DRBG_SET 104
|
||||
# define RAND_F_RAND_DRBG_UNINSTANTIATE 118
|
||||
# define RAND_F_RAND_LOAD_FILE 111
|
||||
# define RAND_F_RAND_POOL_ADD 103
|
||||
# define RAND_F_RAND_POOL_ADD_BEGIN 113
|
||||
@ -65,6 +66,7 @@ int ERR_load_RAND_strings(void);
|
||||
# define RAND_R_IN_ERROR_STATE 114
|
||||
# define RAND_R_NOT_A_REGULAR_FILE 122
|
||||
# define RAND_R_NOT_INSTANTIATED 115
|
||||
# define RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED 128
|
||||
# define RAND_R_PERSONALISATION_STRING_TOO_LONG 116
|
||||
# define RAND_R_PRNG_NOT_SEEDED 100
|
||||
# define RAND_R_RANDOM_POOL_OVERFLOW 125
|
||||
|
@ -438,7 +438,7 @@ static int error_check(DRBG_SELFTEST_DATA *td)
|
||||
goto err;
|
||||
|
||||
/* Standard says we have to check uninstantiate really zeroes */
|
||||
if (!TEST_mem_eq(zero, sizeof(drbg->ctr), &drbg->ctr, sizeof(drbg->ctr)))
|
||||
if (!TEST_mem_eq(zero, sizeof(drbg->data), &drbg->data, sizeof(drbg->data)))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
|
Loading…
Reference in New Issue
Block a user