From: Shane Lontis Date: Tue, 1 Sep 2020 23:08:09 +0000 (+1000) Subject: Add selftest callback to CRNG output test X-Git-Tag: openssl-3.0.0-alpha7~212 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7f9e74403677a995ded00f070d84297401f6e3fd;p=thirdparty%2Fopenssl.git Add selftest callback to CRNG output test Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/12795) --- diff --git a/crypto/self_test_core.c b/crypto/self_test_core.c index 1a6f828c1d0..ca8925abe50 100644 --- a/crypto/self_test_core.c +++ b/crypto/self_test_core.c @@ -157,12 +157,15 @@ void OSSL_SELF_TEST_onend(OSSL_SELF_TEST *st, int ret) * is modified (corrupted). This is used to modify output signatures or * ciphertext before they are verified or decrypted. */ -void OSSL_SELF_TEST_oncorrupt_byte(OSSL_SELF_TEST *st, unsigned char *bytes) +int OSSL_SELF_TEST_oncorrupt_byte(OSSL_SELF_TEST *st, unsigned char *bytes) { if (st != NULL && st->cb != NULL) { st->phase = OSSL_SELF_TEST_PHASE_CORRUPT; self_test_setparams(st); - if (!st->cb(st->params, st->cb_arg)) + if (!st->cb(st->params, st->cb_arg)) { bytes[0] ^= 1; + return 1; + } } + return 0; } diff --git a/doc/man3/OSSL_SELF_TEST_new.pod b/doc/man3/OSSL_SELF_TEST_new.pod index b2c4f5ccce7..744c82e204f 100644 --- a/doc/man3/OSSL_SELF_TEST_new.pod +++ b/doc/man3/OSSL_SELF_TEST_new.pod @@ -17,7 +17,7 @@ OSSL_SELF_TEST_onend - functionality to trigger a callback during a self test void OSSL_SELF_TEST_onbegin(OSSL_SELF_TEST *st, const char *type, const char *desc); - void OSSL_SELF_TEST_oncorrupt_byte(OSSL_SELF_TEST *st, unsigned char *bytes); + int OSSL_SELF_TEST_oncorrupt_byte(OSSL_SELF_TEST *st, unsigned char *bytes); void OSSL_SELF_TEST_onend(OSSL_SELF_TEST *st, int ret); =head1 DESCRIPTION @@ -104,6 +104,9 @@ This allows the callback to identify the sub category of the test being run. OSSL_SELF_TEST_new() returns the allocated B object, or NULL if it fails. +OSSL_SELF_TEST_oncorrupt_byte() returns 1 if corruption occurs, otherwise it +returns 0. + =head1 EXAMPLES A single self test could be set up in the following way: diff --git a/doc/man7/OSSL_PROVIDER-FIPS.pod b/doc/man7/OSSL_PROVIDER-FIPS.pod index 2ae999e0235..98c6079d72f 100644 --- a/doc/man7/OSSL_PROVIDER-FIPS.pod +++ b/doc/man7/OSSL_PROVIDER-FIPS.pod @@ -212,6 +212,10 @@ Known answer test for a Deterministic Random Bit Generator. Conditional test that is run during the generation of key pairs. +=item "Continuous_RNG_Test" (B) + +Continuous random number generator test. + =back The "Module_Integrity" self test is always run at startup. @@ -289,6 +293,10 @@ Key Derivation Function tests used with the "KAT_KDF" type. DRBG tests used with the "DRBG" type. += item "RNG" (B) + +"Continuous_RNG_Test" uses this. + =back =head1 EXAMPLES diff --git a/include/openssl/self_test.h b/include/openssl/self_test.h index 4d99aaa4e3a..be375c9469a 100644 --- a/include/openssl/self_test.h +++ b/include/openssl/self_test.h @@ -60,6 +60,7 @@ extern "C" { # define OSSL_SELF_TEST_DESC_KA_ECDH "ECDH" # define OSSL_SELF_TEST_DESC_KDF_HKDF "HKDF" # define OSSL_SELF_TEST_DESC_KDF_SSKDF "SSKDF" +# define OSSL_SELF_TEST_DESC_RNG "RNG" # ifdef __cplusplus } @@ -75,7 +76,7 @@ void OSSL_SELF_TEST_free(OSSL_SELF_TEST *st); void OSSL_SELF_TEST_onbegin(OSSL_SELF_TEST *st, const char *type, const char *desc); -void OSSL_SELF_TEST_oncorrupt_byte(OSSL_SELF_TEST *st, unsigned char *bytes); +int OSSL_SELF_TEST_oncorrupt_byte(OSSL_SELF_TEST *st, unsigned char *bytes); void OSSL_SELF_TEST_onend(OSSL_SELF_TEST *st, int ret); #endif /* OPENSSL_SELF_TEST_H */ diff --git a/providers/implementations/rands/crngt.c b/providers/implementations/rands/crngt.c index e23485291b4..c6874f8916d 100644 --- a/providers/implementations/rands/crngt.c +++ b/providers/implementations/rands/crngt.c @@ -94,8 +94,8 @@ static const OPENSSL_CTX_METHOD rand_crng_ossl_ctx_method = { }; static int prov_crngt_compare_previous(const unsigned char *prev, - const unsigned char *cur, - size_t sz) + const unsigned char *cur, + size_t sz) { const int res = memcmp(prev, cur, sz) != 0; @@ -113,11 +113,14 @@ size_t prov_crngt_get_entropy(PROV_DRBG *drbg, unsigned int sz; RAND_POOL *pool; size_t q, r = 0, s, t = 0; - int attempts = 3; + int attempts = 3, crng_test_pass = 1; OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(drbg->provctx); CRNG_TEST_GLOBAL *crngt_glob = openssl_ctx_get_data(libctx, OPENSSL_CTX_RAND_CRNGT_INDEX, &rand_crng_ossl_ctx_method); + OSSL_CALLBACK *stcb = NULL; + void *stcbarg = NULL; + OSSL_SELF_TEST *st = NULL; if (crngt_glob == NULL) return 0; @@ -125,12 +128,27 @@ size_t prov_crngt_get_entropy(PROV_DRBG *drbg, if ((pool = rand_pool_new(entropy, 1, min_len, max_len)) == NULL) return 0; + OSSL_SELF_TEST_get_callback(libctx, &stcb, &stcbarg); + if (stcb != NULL) { + st = OSSL_SELF_TEST_new(stcb, stcbarg); + if (st == NULL) + goto err; + OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_CRNG, + OSSL_SELF_TEST_DESC_RNG); + } + while ((q = rand_pool_bytes_needed(pool, 1)) > 0 && attempts-- > 0) { s = q > sizeof(buf) ? sizeof(buf) : q; - if (!crngt_get_entropy(libctx, crngt_glob->crngt_pool, buf, md, - &sz) - || !prov_crngt_compare_previous(crngt_glob->crngt_prev, md, sz) - || !rand_pool_add(pool, buf, s, s * 8)) + if (!crngt_get_entropy(libctx, crngt_glob->crngt_pool, buf, md, &sz)) + goto err; + /* Force a failure here if the callback returns 1 */ + if (OSSL_SELF_TEST_oncorrupt_byte(st, md)) + memcpy(md, crngt_glob->crngt_prev, sz); + if (!prov_crngt_compare_previous(crngt_glob->crngt_prev, md, sz)) { + crng_test_pass = 0; + goto err; + } + if (!rand_pool_add(pool, buf, s, s * 8)) goto err; memcpy(crngt_glob->crngt_prev, md, sz); t += s; @@ -139,6 +157,8 @@ size_t prov_crngt_get_entropy(PROV_DRBG *drbg, r = t; *pout = rand_pool_detach(pool); err: + OSSL_SELF_TEST_onend(st, crng_test_pass); + OSSL_SELF_TEST_free(st); OPENSSL_cleanse(buf, sizeof(buf)); rand_pool_free(pool); return r;