summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShane Lontis <shane.lontis@oracle.com>2020-09-02 09:08:09 +1000
committerShane Lontis <shane.lontis@oracle.com>2020-09-18 06:20:33 +1000
commit7f9e74403677a995ded00f070d84297401f6e3fd (patch)
treea8eb5cc00e8ca3ae7e4c5e82263430ba12675d3a
parent4b51903d8681c7fd429c566548529d5753e24f47 (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.c7
-rw-r--r--doc/man3/OSSL_SELF_TEST_new.pod5
-rw-r--r--doc/man7/OSSL_PROVIDER-FIPS.pod8
-rw-r--r--include/openssl/self_test.h3
-rw-r--r--providers/implementations/rands/crngt.c34
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;