#include <openssl/core_names.h>
#include <openssl/param_build.h>
#include <openssl/rand.h>
+#include "crypto/rand.h"
#include "internal/cryptlib.h"
#include "internal/nelem.h"
#include "self_test.h"
const unsigned char *entropy, size_t entropy_len,
const unsigned char *nonce, size_t nonce_len,
const unsigned char *persstr, size_t persstr_len);
-static int reset_original_drbg(OSSL_LIB_CTX *ctx);
+static int reset_main_drbg(OSSL_LIB_CTX *ctx);
static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_SELF_TEST *st,
OSSL_LIB_CTX *libctx)
return 0;
if (!self_test_sign(t, st, libctx))
ret = 0;
- if (!reset_original_drbg(libctx))
+ if (!reset_main_drbg(libctx))
ret = 0;
}
return ret;
}
-/*
- * Run the algorithm KAT's.
- * Return 1 is successful, otherwise return 0.
- * This runs all the tests regardless of if any fail.
- */
-int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
-{
- int ret = 1;
-
- if (!self_test_digests(st, libctx))
- ret = 0;
- if (!self_test_ciphers(st, libctx))
- ret = 0;
- if (!self_test_signatures(st, libctx))
- ret = 0;
- if (!self_test_kdfs(st, libctx))
- ret = 0;
- if (!self_test_drbgs(st, libctx))
- ret = 0;
- if (!self_test_kas(st, libctx))
- ret = 0;
- if (!self_test_asym_ciphers(st, libctx))
- ret = 0;
-
- return ret;
-}
-
/*
* Swap the library context DRBG for KAT testing
*
*/
/*
- * The default private DRBG of the library context, saved for the duration
- * of KAT testing.
+ * Replacement "random" sources
+ * main_rand is used for most tests and it's set to generate mode.
+ * kat_rand is used for KATs where specific input is mandated.
*/
-static EVP_RAND_CTX *saved_rand = NULL;
-
-/* Replacement "random" source */
static EVP_RAND_CTX *kat_rand = NULL;
+static EVP_RAND_CTX *main_rand = NULL;
static int set_kat_drbg(OSSL_LIB_CTX *ctx,
const unsigned char *entropy, size_t entropy_len,
};
/* If not NULL, we didn't cleanup from last call: BAD */
- if (kat_rand != NULL || saved_rand != NULL)
+ if (kat_rand != NULL)
return 0;
rand = EVP_RAND_fetch(ctx, "TEST-RAND", NULL);
if (parent_rand == NULL)
goto err;
- drbg_params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, &strength);
+ drbg_params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH,
+ &strength);
if (!EVP_RAND_CTX_set_params(parent_rand, drbg_params))
goto err;
if (!EVP_RAND_instantiate(kat_rand, strength, 0, persstr, persstr_len, NULL))
goto err;
+ /* When we set the new private generator this one is freed, so upref it */
+ if (!EVP_RAND_CTX_up_ref(main_rand))
+ goto err;
+
/* Update the library context DRBG */
- if ((saved_rand = RAND_get0_private(ctx)) != NULL)
- /* Avoid freeing this since we replace it */
- if (!EVP_RAND_CTX_up_ref(saved_rand)) {
- saved_rand = NULL;
- goto err;
- }
if (RAND_set0_private(ctx, kat_rand) > 0) {
/* Keeping a copy to verify zeroization */
if (EVP_RAND_CTX_up_ref(kat_rand))
return 1;
- if (saved_rand != NULL)
- RAND_set0_private(ctx, saved_rand);
+ RAND_set0_private(ctx, main_rand);
}
err:
EVP_RAND_CTX_free(parent_rand);
- EVP_RAND_CTX_free(saved_rand);
EVP_RAND_CTX_free(kat_rand);
- kat_rand = saved_rand = NULL;
+ kat_rand = NULL;
return 0;
}
-static int reset_original_drbg(OSSL_LIB_CTX *ctx) {
+static int reset_main_drbg(OSSL_LIB_CTX *ctx) {
int ret = 1;
- if (saved_rand != NULL) {
- if (!RAND_set0_private(ctx, saved_rand))
- ret = 0;
- saved_rand = NULL;
- }
+ if (!RAND_set0_private(ctx, main_rand))
+ ret = 0;
if (kat_rand != NULL) {
if (!EVP_RAND_uninstantiate(kat_rand)
|| !EVP_RAND_verify_zeroization(kat_rand))
return ret;
}
+static int setup_main_random(OSSL_LIB_CTX *libctx)
+{
+ OSSL_PARAM drbg_params[3] = {
+ OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END
+ };
+ unsigned int strength = 256, generate = 1;
+ EVP_RAND *rand;
+
+ rand = EVP_RAND_fetch(libctx, "TEST-RAND", NULL);
+ if (rand == NULL)
+ return 0;
+
+ main_rand = EVP_RAND_CTX_new(rand, NULL);
+ EVP_RAND_free(rand);
+ if (main_rand == NULL)
+ goto err;
+
+ drbg_params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_GENERATE,
+ &generate);
+ drbg_params[1] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH,
+ &strength);
+
+ if (!EVP_RAND_instantiate(main_rand, strength, 0, NULL, 0, drbg_params))
+ goto err;
+ return 1;
+ err:
+ EVP_RAND_CTX_free(main_rand);
+ return 0;
+}
+
+/*
+ * Run the algorithm KAT's.
+ * Return 1 is successful, otherwise return 0.
+ * This runs all the tests regardless of if any fail.
+ */
+int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
+{
+ EVP_RAND_CTX *saved_rand = ossl_rand_get0_private_noncreating(libctx);
+ int ret = 1;
+
+ if (!setup_main_random(libctx)
+ || !RAND_set0_private(libctx, main_rand)) {
+ EVP_RAND_CTX_free(main_rand);
+ return 0;
+ }
+
+ if (!self_test_digests(st, libctx))
+ ret = 0;
+ if (!self_test_ciphers(st, libctx))
+ ret = 0;
+ if (!self_test_signatures(st, libctx))
+ ret = 0;
+ if (!self_test_kdfs(st, libctx))
+ ret = 0;
+ if (!self_test_drbgs(st, libctx))
+ ret = 0;
+ if (!self_test_kas(st, libctx))
+ ret = 0;
+ if (!self_test_asym_ciphers(st, libctx))
+ ret = 0;
+
+ RAND_set0_private(libctx, saved_rand);
+ return ret;
+}
+
*/
#include <string.h>
+#include <stdlib.h>
#include <openssl/core_dispatch.h>
#include <openssl/e_os2.h>
#include <openssl/params.h>
typedef struct {
void *provctx;
+ unsigned int generate;
int state;
unsigned int strength;
size_t max_request;
return 1;
}
+static unsigned char gen_byte(PROV_TEST_RNG *t)
+{
+ return rand() & 0xff;
+}
+
static int test_rng_generate(void *vtest, unsigned char *out, size_t outlen,
unsigned int strength, int prediction_resistance,
const unsigned char *adin, size_t adin_len)
{
PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest;
+ size_t i;
- if (strength > t->strength || t->entropy_len - t->entropy_pos < outlen)
+ if (strength > t->strength)
return 0;
- memcpy(out, t->entropy + t->entropy_pos, outlen);
- t->entropy_pos += outlen;
+ if (t->generate) {
+ for (i = 0; i < outlen; i++)
+ out[i] = gen_byte(t);
+ } else {
+ if (t->entropy_len - t->entropy_pos < outlen)
+ return 0;
+
+ memcpy(out, t->entropy + t->entropy_pos, outlen);
+ t->entropy_pos += outlen;
+ }
return 1;
}
}
static size_t test_rng_nonce(void *vtest, unsigned char *out,
- unsigned int strength,
- ossl_unused size_t min_noncelen,
+ unsigned int strength, size_t min_noncelen,
ossl_unused size_t max_noncelen)
{
PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest;
+ size_t i;
- if (t->nonce == NULL || strength > t->strength)
+ if (strength > t->strength)
return 0;
+ if (t->generate) {
+ for (i = 0; i < min_noncelen; i++)
+ out[i] = gen_byte(t);
+ return min_noncelen;
+ }
+
+ if (t->nonce == NULL)
+ return 0;
if (out != NULL)
memcpy(out, t->nonce, t->nonce_len);
return t->nonce_len;
p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
if (p != NULL && !OSSL_PARAM_set_size_t(p, t->max_request))
return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_GENERATE);
+ if (p != NULL && OSSL_PARAM_set_uint(p, t->generate))
+ return 0;
return 1;
}
OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL),
OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL),
OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL),
+ OSSL_PARAM_uint(OSSL_RAND_PARAM_GENERATE, NULL),
OSSL_PARAM_END
};
return known_gettable_ctx_params;
}
p = OSSL_PARAM_locate_const(params, OSSL_RAND_PARAM_MAX_REQUEST);
- if (p != NULL && !OSSL_PARAM_get_size_t(p, &t->max_request))
+ if (p != NULL && !OSSL_PARAM_get_size_t(p, &t->max_request))
return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_RAND_PARAM_GENERATE);
+ if (p != NULL && !OSSL_PARAM_get_uint(p, &t->generate))
+ return 0;
return 1;
}
OSSL_PARAM_octet_string(OSSL_RAND_PARAM_TEST_NONCE, NULL, 0),
OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL),
OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL),
+ OSSL_PARAM_uint(OSSL_RAND_PARAM_GENERATE, NULL),
OSSL_PARAM_END
};
return known_settable_ctx_params;