diff options
author | Dr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com> | 2017-12-28 21:42:14 +0100 |
---|---|---|
committer | Pauli <paul.dale@oracle.com> | 2018-01-04 11:47:31 +1000 |
commit | 8212d50576147cd5db87b1e2f4607a6d5b5f435f (patch) | |
tree | 016885875e4a7ed596423afc9fdb8954cc66abaf /crypto | |
parent | 4e585e720195788c9546a9ce71d63dafdfd2aaf1 (diff) |
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)
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/err/openssl.txt | 2 | ||||
-rw-r--r-- | crypto/rand/drbg_ctr.c | 43 | ||||
-rw-r--r-- | crypto/rand/drbg_lib.c | 30 | ||||
-rw-r--r-- | crypto/rand/rand_err.c | 4 | ||||
-rw-r--r-- | crypto/rand/rand_lcl.h | 62 |
5 files changed, 101 insertions, 40 deletions
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 4357cfb006..9ec000964a 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -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 diff --git a/crypto/rand/drbg_ctr.c b/crypto/rand/drbg_ctr.c index bb3acc88db..3130e491dd 100644 --- a/crypto/rand/drbg_ctr.c +++ b/crypto/rand/drbg_ctr.c @@ -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; diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c index e33877e3ba..795b098b36 100644 --- a/crypto/rand/drbg_lib.c +++ b/crypto/rand/drbg_lib.c @@ -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; diff --git a/crypto/rand/rand_err.c b/crypto/rand/rand_err.c index dc6140c075..ac70b4a2e0 100644 --- a/crypto/rand/rand_err.c +++ b/crypto/rand/rand_err.c @@ -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"}, diff --git a/crypto/rand/rand_lcl.h b/crypto/rand/rand_lcl.h index 9044981bbb..1a09118546 100644 --- a/crypto/rand/rand_lcl.h +++ b/crypto/rand/rand_lcl.h @@ -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 |