diff options
author | Shane Lontis <shane.lontis@oracle.com> | 2020-09-02 09:08:09 +1000 |
---|---|---|
committer | Shane Lontis <shane.lontis@oracle.com> | 2020-09-18 06:20:33 +1000 |
commit | 7f9e74403677a995ded00f070d84297401f6e3fd (patch) | |
tree | a8eb5cc00e8ca3ae7e4c5e82263430ba12675d3a | |
parent | 4b51903d8681c7fd429c566548529d5753e24f47 (diff) |
Add selftest callback to CRNG output test
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/12795)
-rw-r--r-- | crypto/self_test_core.c | 7 | ||||
-rw-r--r-- | doc/man3/OSSL_SELF_TEST_new.pod | 5 | ||||
-rw-r--r-- | doc/man7/OSSL_PROVIDER-FIPS.pod | 8 | ||||
-rw-r--r-- | include/openssl/self_test.h | 3 | ||||
-rw-r--r-- | providers/implementations/rands/crngt.c | 34 |
5 files changed, 46 insertions, 11 deletions
diff --git a/crypto/self_test_core.c b/crypto/self_test_core.c index 1a6f828c1d..ca8925abe5 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 b2c4f5ccce..744c82e204 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<OSSL_SELF_TEST> 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 2ae999e023..98c6079d72 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<OSSL_SELF_TEST_TYPE_CRNG>) + +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<OSSL_SELF_TEST_DESC_RNG>) + +"Continuous_RNG_Test" uses this. + =back =head1 EXAMPLES diff --git a/include/openssl/self_test.h b/include/openssl/self_test.h index 4d99aaa4e3..be375c9469 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 e23485291b..c6874f8916 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; |