Add selftest callback to CRNG output test

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/12795)
This commit is contained in:
Shane Lontis 2020-09-02 09:08:09 +10:00
parent 4b51903d86
commit 7f9e744036
5 changed files with 46 additions and 11 deletions

View File

@ -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;
}

View File

@ -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:

View File

@ -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

View File

@ -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 */

View File

@ -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;