diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 4357cfb0068672aa90ba50ab0453ce0bf5e9557f..9ec000964a01b5d26fed325956b94fec2ce6f62b 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 bb3acc88db0f5ab82abccb33ba8ee2b15225ec1a..3130e491dd39cb940d0e1bc19dfa0f83cebb3224 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 e33877e3ba9f7b01df3b6dcc68b36b0289fc1bff..795b098b367731272ed209c30d2d2bf34290aed1 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 dc6140c07538ba2c4dfeef58be2e03c44b3ea4f3..ac70b4a2e01fb3a5a0a8846a8dc095836f73ee39 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 9044981bbb89d781da007f928c2e872a58390391..1a09118546f9caddca172f64a201a0ac81502acd 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 diff --git a/include/openssl/randerr.h b/include/openssl/randerr.h index b07ea233eb53be047e61548656197d500f2c76bc..b136ce87e1a6010ebe910f593c5f1fb02d58443b 100644 --- a/include/openssl/randerr.h +++ b/include/openssl/randerr.h @@ -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 diff --git a/test/drbgtest.c b/test/drbgtest.c index 68c169793c9987a5eed7d9fe4c6667eaf454ed5c..fcb4b2846010e1fccc9a7a35c55d1383694d4b8f 100644 --- a/test/drbgtest.c +++ b/test/drbgtest.c @@ -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;