Merge pull request #9616 from douzzer/20251230-persistent-drbg
20251230-persistent-drbg
This commit is contained in:
@@ -790,6 +790,7 @@ WOLFSSL_MONT_RED_CT
|
||||
WOLFSSL_MP_COND_COPY
|
||||
WOLFSSL_MP_INVMOD_CONSTANT_TIME
|
||||
WOLFSSL_MULTICIRCULATE_ALTNAMELIST
|
||||
WOLFSSL_NEW_PRIME_CHECK
|
||||
WOLFSSL_NONBLOCK_OCSP
|
||||
WOLFSSL_NOSHA3_384
|
||||
WOLFSSL_NOT_WINDOWS_API
|
||||
|
||||
24
configure.ac
24
configure.ac
@@ -1428,6 +1428,7 @@ then
|
||||
test "$enable_md5" = "" && enable_md5=yes
|
||||
test "$enable_anon" = "" && enable_anon=yes
|
||||
test "$enable_ssh" = "" && test "$enable_hmac" != "no" && enable_ssh=yes
|
||||
test "$enable_rng_bank" = "" && enable_rng_bank=yes
|
||||
|
||||
# the compiler optimizer generates a weird out-of-bounds bss reference for
|
||||
# find_hole() in the FP_ECC implementation.
|
||||
@@ -2208,6 +2209,19 @@ then
|
||||
AM_CFLAGS="$AM_CFLAGS -DWC_NO_RNG"
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([rng-bank],
|
||||
[AS_HELP_STRING([--enable-rng-bank],[Enable compiling and using RNG banks (default: disabled)])],
|
||||
[ ENABLED_RNG_BANK=$enableval ],
|
||||
[ ENABLED_RNG_BANK=$KERNEL_MODE_DEFAULTS ]
|
||||
)
|
||||
|
||||
if test "$ENABLED_RNG_BANK" = "yes"
|
||||
then
|
||||
AS_IF([test "$ENABLED_RNG" = "no"],
|
||||
AC_MSG_ERROR([--enable-rng-bank requires --enable-rng]))
|
||||
AM_CFLAGS="$AM_CFLAGS -DWC_RNG_BANK_SUPPORT"
|
||||
fi
|
||||
|
||||
|
||||
# DTLS-SCTP
|
||||
AC_ARG_ENABLE([sctp],
|
||||
@@ -3984,12 +3998,17 @@ then
|
||||
fi
|
||||
|
||||
# AMD RDSEED
|
||||
AC_ARG_ENABLE([amdrand],
|
||||
[AS_HELP_STRING([--enable-amdrand],[Enable AMD rdseed as preferred RNG seeding source (default: disabled)])],
|
||||
AC_ARG_ENABLE([amdrdseed],
|
||||
[AS_HELP_STRING([--enable-amdrdseed],[Enable AMD rdseed as preferred RNG seeding source (default: disabled)])],
|
||||
[ ENABLED_AMDRDSEED=$enableval ],
|
||||
[ ENABLED_AMDRDSEED=no ]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE([amdrand],
|
||||
[AS_HELP_STRING([--enable-amdrand],[Enable AMD rdseed as preferred RNG seeding source (default: disabled)])],
|
||||
[ ENABLED_AMDRDSEED=$enableval ]
|
||||
)
|
||||
|
||||
if test "$ENABLED_AMDRDSEED" = "yes"
|
||||
then
|
||||
AM_CFLAGS="$AM_CFLAGS -DHAVE_AMD_RDSEED"
|
||||
@@ -11079,6 +11098,7 @@ AM_CONDITIONAL([BUILD_ECCSI],[test "x$ENABLED_ECCSI" = "xyes" || test "x$ENABLED
|
||||
AM_CONDITIONAL([BUILD_SAKKE],[test "x$ENABLED_SAKKE" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_MEMORY],[test "x$ENABLED_MEMORY" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_MEMUSE],[test "x$ENABLED_ENTROPY_MEMUSE" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_RNG_BANK],[test "$ENABLED_RNG_BANK" = "yes" || test "$ENABLED_USERSETTINGS" = "yes"])
|
||||
AM_CONDITIONAL([BUILD_RSA],[test "x$ENABLED_RSA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_DH],[test "x$ENABLED_DH" != "xno" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_ASN],[test "x$ENABLED_ASN" != "xno" || test "x$ENABLED_RSA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
|
||||
@@ -937,7 +937,9 @@
|
||||
typeof(kfree) *kfree;
|
||||
typeof(ksize) *ksize;
|
||||
|
||||
#ifndef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
|
||||
typeof(get_random_bytes) *get_random_bytes;
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
|
||||
typeof(getnstimeofday) *getnstimeofday;
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
|
||||
@@ -1072,9 +1074,7 @@
|
||||
|
||||
#endif /* !WOLFCRYPT_ONLY && !NO_CERTS */
|
||||
|
||||
#ifdef WOLFSSL_DEBUG_BACKTRACE_ERROR_CODES
|
||||
typeof(dump_stack) *dump_stack;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
#ifndef CONFIG_ARCH_TEGRA
|
||||
@@ -1269,7 +1269,9 @@
|
||||
#endif
|
||||
#define ksize WC_PIE_INDIRECT_SYM(ksize)
|
||||
|
||||
#ifndef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
|
||||
#define get_random_bytes WC_PIE_INDIRECT_SYM(get_random_bytes)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
|
||||
#define getnstimeofday WC_PIE_INDIRECT_SYM(getnstimeofday)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
|
||||
@@ -1345,9 +1347,7 @@
|
||||
|
||||
#endif /* !WOLFCRYPT_ONLY && !NO_CERTS */
|
||||
|
||||
#ifdef WOLFSSL_DEBUG_BACKTRACE_ERROR_CODES
|
||||
#define dump_stack WC_PIE_INDIRECT_SYM(dump_stack)
|
||||
#endif
|
||||
|
||||
#undef preempt_count /* just in case -- not a macro on x86. */
|
||||
#define preempt_count WC_PIE_INDIRECT_SYM(preempt_count)
|
||||
@@ -1729,4 +1729,13 @@
|
||||
#error unexpected BITS_PER_LONG value.
|
||||
#endif
|
||||
|
||||
/* WC_DUMP_BACKTRACE_NONDEBUG is intended to dump a backtrace only if it hasn't
|
||||
* already been dumped by the called function.
|
||||
*/
|
||||
#if defined(WOLFSSL_DEBUG_TRACE_ERROR_CODES) && defined(WOLFSSL_DEBUG_BACKTRACE_ERROR_CODES)
|
||||
#define WC_DUMP_BACKTRACE_NONDEBUG WC_DO_NOTHING
|
||||
#else
|
||||
#define WC_DUMP_BACKTRACE_NONDEBUG dump_stack()
|
||||
#endif
|
||||
|
||||
#endif /* LINUXKM_WC_PORT_H */
|
||||
|
||||
@@ -749,10 +749,7 @@ static int km_ffdhe_init(struct crypto_kpp *tfm, int name, word32 nbits)
|
||||
ctx->name = name;
|
||||
ctx->nbits = nbits;
|
||||
|
||||
if (WOLFSSL_ATOMIC_LOAD(linuxkm_lkcapi_registering_now))
|
||||
err = LKCAPI_INITRNG_FOR_SELFTEST(&ctx->rng);
|
||||
else
|
||||
err = wc_InitRng(&ctx->rng);
|
||||
err = LKCAPI_INITRNG(&ctx->rng);
|
||||
if (err) {
|
||||
#ifdef WOLFKM_DEBUG_DH
|
||||
pr_err("%s: init rng returned: %d\n", WOLFKM_DH_DRIVER, err);
|
||||
|
||||
@@ -387,10 +387,7 @@ static int km_ecdh_init(struct crypto_kpp *tfm, int curve_id)
|
||||
ctx->curve_len = (word32) ret;
|
||||
}
|
||||
|
||||
if (WOLFSSL_ATOMIC_LOAD(linuxkm_lkcapi_registering_now))
|
||||
ret = LKCAPI_INITRNG_FOR_SELFTEST(&ctx->rng);
|
||||
else
|
||||
ret = wc_InitRng(&ctx->rng);
|
||||
ret = LKCAPI_INITRNG(&ctx->rng);
|
||||
if (ret) {
|
||||
#ifdef WOLFKM_DEBUG_ECDH
|
||||
pr_err("%s: init rng returned: %d\n", WOLFKM_ECDH_DRIVER, ret);
|
||||
|
||||
@@ -634,14 +634,13 @@ out:
|
||||
static inline int km_rsa_ctx_init_rng(struct km_rsa_ctx * ctx) {
|
||||
switch (ctx->rng.status) {
|
||||
case WC_DRBG_OK:
|
||||
#ifdef WC_RNG_BANK_SUPPORT
|
||||
case WC_DRBG_BANKREF:
|
||||
#endif
|
||||
return 0;
|
||||
case WC_DRBG_NOT_INIT:
|
||||
{
|
||||
int err;
|
||||
if (WOLFSSL_ATOMIC_LOAD(linuxkm_lkcapi_registering_now))
|
||||
err = LKCAPI_INITRNG_FOR_SELFTEST(&ctx->rng);
|
||||
else
|
||||
err = wc_InitRng(&ctx->rng);
|
||||
int err = LKCAPI_INITRNG(&ctx->rng);
|
||||
if (err) {
|
||||
pr_err("%s: init rng returned: %d\n", WOLFKM_RSA_DRIVER, err);
|
||||
if (err == WC_NO_ERR_TRACE(MEMORY_E))
|
||||
@@ -2105,7 +2104,7 @@ static int linuxkm_test_rsa_driver(const char * driver, int nbits)
|
||||
memset(&rng, 0, sizeof(rng));
|
||||
memset(key, 0, sizeof(RsaKey));
|
||||
|
||||
ret = LKCAPI_INITRNG_FOR_SELFTEST(&rng);
|
||||
ret = LKCAPI_INITRNG(&rng);
|
||||
|
||||
if (ret) {
|
||||
pr_err("error: init rng returned: %d\n", ret);
|
||||
@@ -2483,7 +2482,7 @@ static int linuxkm_test_pkcs1pad_driver(const char * driver, int nbits,
|
||||
memset(&rng, 0, sizeof(rng));
|
||||
memset(key, 0, sizeof(RsaKey));
|
||||
|
||||
ret = LKCAPI_INITRNG_FOR_SELFTEST(&rng);
|
||||
ret = LKCAPI_INITRNG(&rng);
|
||||
if (ret) {
|
||||
pr_err("error: init rng returned: %d\n", ret);
|
||||
goto test_pkcs1_end;
|
||||
@@ -3007,7 +3006,7 @@ static int linuxkm_test_pkcs1_driver(const char * driver, int nbits,
|
||||
memset(&rng, 0, sizeof(rng));
|
||||
memset(key, 0, sizeof(RsaKey));
|
||||
|
||||
ret = LKCAPI_INITRNG_FOR_SELFTEST(&rng);
|
||||
ret = LKCAPI_INITRNG(&rng);
|
||||
if (ret) {
|
||||
pr_err("error: init rng returned: %d\n", ret);
|
||||
goto test_pkcs1_end;
|
||||
|
||||
@@ -955,38 +955,7 @@ struct wc_swallow_the_semicolon
|
||||
#include <wolfssl/wolfcrypt/wolfentropy.h>
|
||||
#endif
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
|
||||
struct wc_linuxkm_drbg_ctx {
|
||||
size_t n_rngs;
|
||||
struct wc_rng_inst {
|
||||
wolfSSL_Atomic_Int lock;
|
||||
WC_RNG rng;
|
||||
} *rngs; /* one per CPU ID */
|
||||
};
|
||||
|
||||
static inline void wc_linuxkm_drbg_ctx_clear(struct wc_linuxkm_drbg_ctx * ctx)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (ctx->rngs) {
|
||||
for (i = 0; i < ctx->n_rngs; ++i) {
|
||||
if (ctx->rngs[i].lock != 0) {
|
||||
/* better to leak than to crash. */
|
||||
pr_err("BUG: wc_linuxkm_drbg_ctx_clear called with DRBG #%d still locked.", i);
|
||||
ctx->rngs = NULL;
|
||||
ctx->n_rngs = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
wc_FreeRng(&ctx->rngs[i].rng);
|
||||
}
|
||||
free(ctx->rngs);
|
||||
ctx->rngs = NULL;
|
||||
ctx->n_rngs = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#include <wolfssl/wolfcrypt/rng_bank.h>
|
||||
|
||||
static volatile int wc_linuxkm_drbg_init_tfm_disable_vector_registers = 0;
|
||||
|
||||
@@ -994,65 +963,71 @@ static volatile int wc_linuxkm_drbg_init_tfm_disable_vector_registers = 0;
|
||||
#define WC_LINUXKM_INITRNG_TIMEOUT_SEC 30
|
||||
#endif
|
||||
|
||||
static int linuxkm_affinity_lock(void *arg) {
|
||||
(void)arg;
|
||||
if (preempt_count() != 0)
|
||||
return ALREADY_E;
|
||||
#if defined(CONFIG_SMP) && (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
|
||||
migrate_disable(); /* this actually makes irq_count() nonzero, so that
|
||||
* DISABLE_VECTOR_REGISTERS() is superfluous, but
|
||||
* don't depend on that.
|
||||
*/
|
||||
#endif
|
||||
local_bh_disable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int linuxkm_affinity_get_id(void *arg, int *id) {
|
||||
(void)arg;
|
||||
*id = raw_smp_processor_id();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int linuxkm_affinity_unlock(void *arg) {
|
||||
(void)arg;
|
||||
local_bh_enable();
|
||||
#if defined(CONFIG_SMP) && (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
|
||||
migrate_enable();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wc_linuxkm_drbg_init_tfm(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct wc_linuxkm_drbg_ctx *ctx = (struct wc_linuxkm_drbg_ctx *)crypto_tfm_ctx(tfm);
|
||||
unsigned int i;
|
||||
struct wc_rng_bank *ctx = (struct wc_rng_bank *)crypto_tfm_ctx(tfm);
|
||||
int ret;
|
||||
int need_reenable_vec = 0;
|
||||
int can_sleep = (preempt_count() == 0);
|
||||
word32 flags = WC_RNG_BANK_FLAG_CAN_WAIT;
|
||||
|
||||
ctx->n_rngs = nr_cpu_ids + 4;
|
||||
ctx->rngs = (struct wc_rng_inst *)malloc(sizeof(*ctx->rngs) * ctx->n_rngs);
|
||||
if (! ctx->rngs) {
|
||||
ctx->n_rngs = 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
XMEMSET(ctx->rngs, 0, sizeof(*ctx->rngs) * ctx->n_rngs);
|
||||
if (wc_linuxkm_drbg_init_tfm_disable_vector_registers)
|
||||
flags |= WC_RNG_BANK_FLAG_NO_VECTOR_OPS;
|
||||
|
||||
for (i = 0; i < ctx->n_rngs; ++i) {
|
||||
int nretries = 0;
|
||||
u64 ts1 = ktime_get_ns();
|
||||
for (;;) {
|
||||
u64 ts2;
|
||||
if (wc_linuxkm_drbg_init_tfm_disable_vector_registers)
|
||||
need_reenable_vec = (DISABLE_VECTOR_REGISTERS() == 0);
|
||||
ret = wc_InitRng(&ctx->rngs[i].rng);
|
||||
if (need_reenable_vec)
|
||||
REENABLE_VECTOR_REGISTERS();
|
||||
if (can_sleep) {
|
||||
/* if we're allowed to sleep, relax the loop between each inner
|
||||
* iteration even on success, assuring relaxation of the outer
|
||||
* iterations.
|
||||
*/
|
||||
cond_resched();
|
||||
}
|
||||
if (ret == 0)
|
||||
break;
|
||||
if (can_sleep) {
|
||||
/* Allow interrupt only if we're stuck spinning retries -- i.e.,
|
||||
* don't allow an untimely user signal to derail an
|
||||
* initialization that is proceeding expeditiously.
|
||||
*/
|
||||
if (WC_CHECK_FOR_INTR_SIGNALS() == WC_NO_ERR_TRACE(INTERRUPTED_E)) {
|
||||
ret = -EINTR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ts2 = ktime_get_ns();
|
||||
if (ts2 - ts1 > 1000000000L * WC_LINUXKM_INITRNG_TIMEOUT_SEC)
|
||||
break;
|
||||
++nretries;
|
||||
}
|
||||
ret = wc_rng_bank_init(
|
||||
ctx, nr_cpu_ids + 4, flags, WC_LINUXKM_INITRNG_TIMEOUT_SEC,
|
||||
NULL /* heap */, INVALID_DEVID);
|
||||
|
||||
if (ret == 0) {
|
||||
ret = wc_rng_bank_set_affinity_handlers(
|
||||
ctx,
|
||||
linuxkm_affinity_lock,
|
||||
linuxkm_affinity_get_id,
|
||||
linuxkm_affinity_unlock,
|
||||
NULL);
|
||||
if (ret != 0) {
|
||||
pr_warn("WARNING: wc_InitRng returned %d after %d retries.\n", ret, nretries);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
(void)wc_rng_bank_fini(ctx);
|
||||
pr_err("ERROR: wc_rng_bank_set_affinity_handlers() in wc_linuxkm_drbg_init_tfm() returned err %d\n", ret);
|
||||
WC_DUMP_BACKTRACE_NONDEBUG;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
wc_linuxkm_drbg_ctx_clear(ctx);
|
||||
else {
|
||||
pr_err("ERROR: wc_rng_bank_init() in wc_linuxkm_drbg_init_tfm() returned err %d\n", ret);
|
||||
if (ret == WC_NO_ERR_TRACE(MEMORY_E))
|
||||
ret = -ENOMEM;
|
||||
else if (ret == WC_NO_ERR_TRACE(WC_TIMEOUT_E))
|
||||
ret = -ETIMEDOUT;
|
||||
else if (ret == WC_NO_ERR_TRACE(INTERRUPTED_E))
|
||||
ret = -EINTR;
|
||||
else
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -1060,101 +1035,54 @@ static int wc_linuxkm_drbg_init_tfm(struct crypto_tfm *tfm)
|
||||
|
||||
static void wc_linuxkm_drbg_exit_tfm(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct wc_linuxkm_drbg_ctx *ctx = (struct wc_linuxkm_drbg_ctx *)crypto_tfm_ctx(tfm);
|
||||
struct wc_rng_bank *ctx = (struct wc_rng_bank *)crypto_tfm_ctx(tfm);
|
||||
int ret = wc_rng_bank_fini(ctx);
|
||||
|
||||
wc_linuxkm_drbg_ctx_clear(ctx);
|
||||
if (ret != 0)
|
||||
pr_err("ERROR: wc_rng_bank_fini() in wc_linuxkm_drbg_exit_tfm() returned err %d\n", ret);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int wc_linuxkm_drbg_default_instance_registered = 0;
|
||||
|
||||
/* get_drbg() uses atomic operations to get exclusive ownership of a DRBG
|
||||
* without delay. It expects to be called in uninterruptible context, though
|
||||
* works fine in any context. It starts by trying the DRBG matching the current
|
||||
* CPU ID, and if that doesn't immediately succeed, it iterates upward until one
|
||||
* succeeds. The first attempt will always succeed, even under intense load,
|
||||
* unless there is or has recently been a reseed or mix-in operation competing
|
||||
* with generators.
|
||||
*
|
||||
* Note that wc_linuxkm_drbg_init_tfm() allocates at least 4 DRBGs, regardless
|
||||
* of nominal core count, to avoid stalling generators on unicore targets.
|
||||
*/
|
||||
static struct wc_rng_bank_inst *linuxkm_get_drbg(struct crypto_rng *tfm) {
|
||||
struct wc_rng_bank *ctx = (struct wc_rng_bank *)crypto_rng_ctx(tfm);
|
||||
int err;
|
||||
struct wc_rng_bank_inst *ret;
|
||||
word32 flags =
|
||||
WC_RNG_BANK_FLAG_CAN_FAIL_OVER_INST |
|
||||
WC_RNG_BANK_FLAG_CAN_WAIT |
|
||||
WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST;
|
||||
|
||||
static inline struct wc_rng_inst *get_drbg(struct crypto_rng *tfm) {
|
||||
struct wc_linuxkm_drbg_ctx *ctx = (struct wc_linuxkm_drbg_ctx *)crypto_rng_ctx(tfm);
|
||||
int n, new_lock_value;
|
||||
|
||||
/* check for mismatched handler or missing instance array. */
|
||||
if ((tfm->base.__crt_alg->cra_init != wc_linuxkm_drbg_init_tfm) ||
|
||||
(ctx->rngs == NULL))
|
||||
{
|
||||
/* check for mismatched handler. */
|
||||
if (tfm->base.__crt_alg->cra_init != wc_linuxkm_drbg_init_tfm) {
|
||||
pr_err("BUG: linuxkm_get_drbg() called on foreign tfm.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((tfm == crypto_default_rng) && (preempt_count() == 0)) {
|
||||
#if defined(CONFIG_SMP) && (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
|
||||
migrate_disable(); /* this actually makes irq_count() nonzero, so that
|
||||
* DISABLE_VECTOR_REGISTERS() is superfluous, but
|
||||
* don't depend on that.
|
||||
*/
|
||||
#endif
|
||||
local_bh_disable();
|
||||
new_lock_value = 2;
|
||||
}
|
||||
if (preempt_count() == 0)
|
||||
flags |= WC_RNG_BANK_FLAG_AFFINITY_LOCK;
|
||||
else
|
||||
{
|
||||
new_lock_value = 1;
|
||||
flags |= WC_RNG_BANK_FLAG_NO_VECTOR_OPS;
|
||||
|
||||
err = wc_rng_bank_checkout(ctx, &ret, 0, WC_LINUXKM_INITRNG_TIMEOUT_SEC, flags);
|
||||
|
||||
if (err != 0) {
|
||||
pr_err("ERROR: wc_rng_bank_checkout() in linuxkm_get_drbg() returned err %d.\n", err);
|
||||
WC_DUMP_BACKTRACE_NONDEBUG;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n = raw_smp_processor_id();
|
||||
|
||||
for (;;) {
|
||||
int expected = 0;
|
||||
if (likely(__atomic_compare_exchange_n(&ctx->rngs[n].lock, &expected, new_lock_value, 0, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE)))
|
||||
return &ctx->rngs[n];
|
||||
++n;
|
||||
if (n >= (int)ctx->n_rngs)
|
||||
n = 0;
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
__builtin_unreachable();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get_drbg_n() is used by bulk seed, mix-in, and reseed operations. It expects
|
||||
* the caller to be able to wait until the requested DRBG is available. If the
|
||||
* caller can't sleep and the requested DRBG is busy, it returns immediately --
|
||||
* this avoids priority inversions and deadlocks.
|
||||
*/
|
||||
static inline struct wc_rng_inst *get_drbg_n(struct wc_linuxkm_drbg_ctx *ctx, int n, int can_spin) {
|
||||
int can_sleep = (preempt_count() == 0);
|
||||
|
||||
for (;;) {
|
||||
int expected = 0;
|
||||
if (likely(__atomic_compare_exchange_n(&ctx->rngs[n].lock, &expected, 1, 0, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE)))
|
||||
return &ctx->rngs[n];
|
||||
if (can_sleep && can_spin) {
|
||||
if (signal_pending(current))
|
||||
return NULL;
|
||||
cond_resched();
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
static inline void put_drbg(struct wc_rng_inst *drbg) {
|
||||
int migration_disabled = (drbg->lock == 2);
|
||||
__atomic_store_n(&(drbg->lock),0,__ATOMIC_RELEASE);
|
||||
|
||||
if (migration_disabled) {
|
||||
local_bh_enable();
|
||||
#if defined(CONFIG_SMP) && (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
|
||||
migrate_enable();
|
||||
#endif
|
||||
static void linuxkm_put_drbg(struct crypto_rng *tfm, struct wc_rng_bank_inst **drbg) {
|
||||
struct wc_rng_bank *ctx = (struct wc_rng_bank *)crypto_rng_ctx(tfm);
|
||||
int ret = wc_rng_bank_checkin(ctx, drbg);
|
||||
if (ret != 0) {
|
||||
pr_err("ERROR: wc_rng_bank_checkin() in linuxkm_put_drbg() returned err %d.\n", ret);
|
||||
WC_DUMP_BACKTRACE_NONDEBUG;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1188,196 +1116,43 @@ static inline struct crypto_rng *get_crypto_default_rng(void) {
|
||||
return current_crypto_default_rng;
|
||||
}
|
||||
|
||||
static int drbg_init_from(WC_RNG *source_rng, struct DRBG_internal* dest_drbg) {
|
||||
int ret;
|
||||
int need_vec_reenable;
|
||||
|
||||
XMEMSET(dest_drbg, 0, sizeof(struct DRBG_internal));
|
||||
|
||||
need_vec_reenable = (DISABLE_VECTOR_REGISTERS() == 0);
|
||||
|
||||
/* Don't copy out the low level DRBG itself -- it contains sensitive secret
|
||||
* state. Instead, use it to generate fresh V and C values in a
|
||||
* non-intrusive way.
|
||||
*/
|
||||
ret = wc_RNG_GenerateBlock(source_rng, dest_drbg->V, sizeof dest_drbg->V);
|
||||
if (ret != 0) {
|
||||
pr_err("drbg_init_from: wc_RNG_GenerateBlock for V returned %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
ret = wc_RNG_GenerateBlock(source_rng, dest_drbg->C, sizeof dest_drbg->C);
|
||||
if (ret != 0) {
|
||||
pr_err("drbg_init_from: wc_RNG_GenerateBlock for C returned %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dest_drbg->heap = source_rng->heap;
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
|
||||
dest_drbg->devId = source_rng->devId;
|
||||
#ifndef WC_DRBG_BANKREF
|
||||
#error LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT requires WC_DRBG_BANKREF support.
|
||||
#endif
|
||||
|
||||
ret = wc_InitSha256_ex(&dest_drbg->sha256, dest_drbg->heap,
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
|
||||
source_rng->dev_id
|
||||
#else
|
||||
INVALID_DEVID
|
||||
#endif
|
||||
);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
|
||||
dest_drbg->reseedCtr = 1;
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
|
||||
if (need_vec_reenable)
|
||||
REENABLE_VECTOR_REGISTERS();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* fork_default_rng() is a non-FIPS-compliant helper function to initialize an
|
||||
* RNG for glue layer POSTs. Direct replacement for wc_InitRng(), and secure in
|
||||
* principle, but not permissible to use as such in FIPS runtimes.
|
||||
*/
|
||||
static WC_MAYBE_UNUSED int fork_default_rng(WC_RNG *forked_rng) {
|
||||
struct crypto_rng *current_crypto_default_rng;
|
||||
struct wc_rng_inst *rng = NULL;
|
||||
struct DRBG_internal *drbg = NULL;
|
||||
struct DRBG_internal *drbg_scratch = NULL;
|
||||
byte *health_check_scratch = NULL;
|
||||
byte *newSeed_buf = NULL;
|
||||
WC_MAYBE_UNUSED static int linuxkm_InitRng_DefaultRef(WC_RNG* rng) {
|
||||
int ret;
|
||||
|
||||
if (forked_rng == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
XMEMSET(forked_rng, 0, sizeof *forked_rng);
|
||||
|
||||
health_check_scratch =
|
||||
(byte *)XMALLOC(RNG_HEALTH_TEST_CHECK_SIZE, NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (health_check_scratch == NULL) {
|
||||
ret = MEMORY_E;
|
||||
goto out;
|
||||
}
|
||||
|
||||
newSeed_buf = (byte*)XMALLOC(WC_DRBG_SEED_SZ +
|
||||
WC_DRBG_SEED_BLOCK_SZ,
|
||||
NULL,
|
||||
DYNAMIC_TYPE_SEED);
|
||||
if (newSeed_buf == NULL) {
|
||||
ret = MEMORY_E;
|
||||
goto out;
|
||||
}
|
||||
|
||||
drbg = (struct DRBG_internal *)XMALLOC(sizeof *drbg, NULL,
|
||||
DYNAMIC_TYPE_RNG);
|
||||
if (drbg == NULL) {
|
||||
ret = MEMORY_E;
|
||||
goto out;
|
||||
}
|
||||
|
||||
drbg_scratch =
|
||||
(struct DRBG_internal *)XMALLOC(sizeof *drbg_scratch, NULL,
|
||||
DYNAMIC_TYPE_RNG);
|
||||
if (drbg_scratch == NULL) {
|
||||
ret = MEMORY_E;
|
||||
goto out;
|
||||
}
|
||||
|
||||
current_crypto_default_rng = get_crypto_default_rng();
|
||||
struct crypto_rng *current_crypto_default_rng = get_crypto_default_rng();
|
||||
if (current_crypto_default_rng == NULL) {
|
||||
ret = BAD_STATE_E;
|
||||
goto out;
|
||||
pr_warn_once("WARNING: get_crypto_default_rng() failed in linuxkm_InitRng_DefaultRef(); falling through to wc_InitRng().\n");
|
||||
return wc_InitRng(rng);
|
||||
}
|
||||
|
||||
rng = get_drbg(current_crypto_default_rng);
|
||||
if (rng == NULL) {
|
||||
ret = BAD_STATE_E;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rng->rng.status != WC_DRBG_OK) {
|
||||
pr_err("fork_default_rng: rng->rng.status = %d\n", rng->rng.status);
|
||||
ret = RNG_FAILURE_E;
|
||||
goto out;
|
||||
}
|
||||
|
||||
XMEMCPY(forked_rng, &rng->rng, sizeof *forked_rng);
|
||||
forked_rng->drbg = (struct DRBG *)drbg;
|
||||
forked_rng->drbg_scratch = drbg_scratch;
|
||||
forked_rng->health_check_scratch = health_check_scratch;
|
||||
forked_rng->newSeed_buf = newSeed_buf;
|
||||
|
||||
ret = drbg_init_from(&rng->rng, (struct DRBG_internal*)forked_rng->drbg);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
|
||||
ret = drbg_init_from(&rng->rng, (struct DRBG_internal*)forked_rng->drbg_scratch);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
|
||||
put_drbg(rng);
|
||||
rng = NULL;
|
||||
|
||||
{
|
||||
byte scratch[4];
|
||||
ret = wc_RNG_GenerateBlock(forked_rng, scratch, sizeof scratch);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
|
||||
if (ret == 0)
|
||||
return ret;
|
||||
else {
|
||||
if (rng)
|
||||
put_drbg(rng);
|
||||
XFREE(drbg, rng->rng.heap, DYNAMIC_TYPE_RNG);
|
||||
XFREE(drbg_scratch, rng->rng.heap, DYNAMIC_TYPE_RNG);
|
||||
XFREE(health_check_scratch, rng->rng.heap, DYNAMIC_TYPE_RNG);
|
||||
XFREE(newSeed_buf, rng->rng.heap, DYNAMIC_TYPE_RNG);
|
||||
pr_warn("WARNING: fork_default_rng: ret=%d; falling through to wc_InitRng()\n", ret);
|
||||
return wc_InitRng(forked_rng);
|
||||
struct wc_rng_bank *default_bank = (struct wc_rng_bank *)crypto_rng_ctx(current_crypto_default_rng);
|
||||
ret = wc_InitRng_BankRef(default_bank, rng);
|
||||
return ret;
|
||||
}
|
||||
|
||||
__builtin_unreachable();
|
||||
}
|
||||
#define LKCAPI_INITRNG(rng) linuxkm_InitRng_DefaultRef(rng)
|
||||
|
||||
#define LKCAPI_INITRNG_FOR_SELFTEST(rng) fork_default_rng(rng)
|
||||
|
||||
#else /* !LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT || !HAVE_HASHDRBG */
|
||||
|
||||
#define LKCAPI_INITRNG_FOR_SELFTEST(rng) wc_InitRng(rng)
|
||||
|
||||
#endif /* !LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT || !HAVE_HASHDRBG */
|
||||
#endif /* LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT && HAVE_HASHDRBG */
|
||||
|
||||
static int wc_linuxkm_drbg_generate(struct crypto_rng *tfm,
|
||||
const u8 *src, unsigned int slen,
|
||||
u8 *dst, unsigned int dlen)
|
||||
{
|
||||
int ret, retried = 0;
|
||||
int need_fpu_restore;
|
||||
struct wc_rng_inst *drbg = get_drbg(tfm);
|
||||
struct wc_rng_bank_inst *drbg = linuxkm_get_drbg(tfm);
|
||||
|
||||
if (! drbg) {
|
||||
pr_err_once("BUG: get_drbg() failed.");
|
||||
pr_err_once("BUG: linuxkm_get_drbg() failed.");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* for the default RNG, make sure we don't cache an underlying SHA256
|
||||
* method that uses vector insns (forbidden from irq handlers).
|
||||
*/
|
||||
need_fpu_restore = (tfm == crypto_default_rng) ? (DISABLE_VECTOR_REGISTERS() == 0) : 0;
|
||||
|
||||
retry:
|
||||
|
||||
if (slen > 0) {
|
||||
ret = wc_RNG_DRBG_Reseed(&drbg->rng, src, slen);
|
||||
ret = wc_RNG_DRBG_Reseed(WC_RNG_BANK_INST_TO_RNG(drbg), src, slen);
|
||||
if (ret != 0) {
|
||||
pr_warn_once("WARNING: wc_RNG_DRBG_Reseed returned %d\n",ret);
|
||||
ret = -EINVAL;
|
||||
@@ -1388,7 +1163,7 @@ retry:
|
||||
for (;;) {
|
||||
#define RNG_MAX_BLOCK_LEN_ROUNDED (RNG_MAX_BLOCK_LEN & ~0xfU)
|
||||
if (dlen > RNG_MAX_BLOCK_LEN_ROUNDED) {
|
||||
ret = wc_RNG_GenerateBlock(&drbg->rng, dst, RNG_MAX_BLOCK_LEN_ROUNDED);
|
||||
ret = wc_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(drbg), dst, RNG_MAX_BLOCK_LEN_ROUNDED);
|
||||
if (ret == 0) {
|
||||
dlen -= RNG_MAX_BLOCK_LEN_ROUNDED;
|
||||
dst += RNG_MAX_BLOCK_LEN_ROUNDED;
|
||||
@@ -1396,38 +1171,48 @@ retry:
|
||||
}
|
||||
#undef RNG_MAX_BLOCK_LEN_ROUNDED
|
||||
else {
|
||||
ret = wc_RNG_GenerateBlock(&drbg->rng, dst, dlen);
|
||||
dlen -= dlen;
|
||||
ret = wc_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(drbg), dst, dlen);
|
||||
if (ret == 0)
|
||||
dlen = 0;
|
||||
}
|
||||
|
||||
if (dlen == 0)
|
||||
break;
|
||||
|
||||
if (ret == 0)
|
||||
continue;
|
||||
|
||||
if (unlikely(ret == WC_NO_ERR_TRACE(RNG_FAILURE_E)) && (! retried)) {
|
||||
if (slen > 0)
|
||||
break;
|
||||
|
||||
retried = 1;
|
||||
wc_FreeRng(&drbg->rng);
|
||||
ret = wc_InitRng(&drbg->rng);
|
||||
|
||||
ret = wc_rng_bank_inst_reinit((struct wc_rng_bank *)crypto_rng_ctx(tfm),
|
||||
drbg,
|
||||
WC_LINUXKM_INITRNG_TIMEOUT_SEC,
|
||||
WC_RNG_BANK_FLAG_CAN_WAIT);
|
||||
|
||||
if (ret == 0) {
|
||||
pr_warn("WARNING: reinitialized DRBG #%d after RNG_FAILURE_E.", raw_smp_processor_id());
|
||||
goto retry;
|
||||
pr_warn("WARNING: reinitialized DRBG #%d after RNG_FAILURE_E from wc_RNG_GenerateBlock().", raw_smp_processor_id());
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
pr_warn_once("ERROR: reinitialization of DRBG #%d after RNG_FAILURE_E failed with ret %d.", raw_smp_processor_id(), ret);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ret != 0) {
|
||||
pr_warn_once("WARNING: wc_RNG_GenerateBlock returned %d\n",ret);
|
||||
else {
|
||||
pr_warn_once("ERROR: wc_linuxkm_drbg_generate() wc_RNG_GenerateBlock returned %d.\n",ret);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (! dlen)
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
if (need_fpu_restore)
|
||||
REENABLE_VECTOR_REGISTERS();
|
||||
put_drbg(drbg);
|
||||
linuxkm_put_drbg(tfm, &drbg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1435,13 +1220,10 @@ out:
|
||||
static int wc_linuxkm_drbg_seed(struct crypto_rng *tfm,
|
||||
const u8 *seed, unsigned int slen)
|
||||
{
|
||||
struct wc_linuxkm_drbg_ctx *ctx = (struct wc_linuxkm_drbg_ctx *)crypto_rng_ctx(tfm);
|
||||
u8 *seed_copy = NULL;
|
||||
int ret = 0;
|
||||
int n;
|
||||
struct wc_rng_bank *ctx = (struct wc_rng_bank *)crypto_rng_ctx(tfm);
|
||||
int ret;
|
||||
|
||||
if ((tfm->base.__crt_alg->cra_init != wc_linuxkm_drbg_init_tfm) ||
|
||||
(ctx->rngs == NULL))
|
||||
if (tfm->base.__crt_alg->cra_init != wc_linuxkm_drbg_init_tfm)
|
||||
{
|
||||
pr_err_once("BUG: mismatched tfm.");
|
||||
return -EFAULT;
|
||||
@@ -1450,51 +1232,12 @@ static int wc_linuxkm_drbg_seed(struct crypto_rng *tfm,
|
||||
if (slen == 0)
|
||||
return 0;
|
||||
|
||||
seed_copy = (u8 *)malloc(slen + 2);
|
||||
if (! seed_copy)
|
||||
return -ENOMEM;
|
||||
XMEMCPY(seed_copy + 2, seed, slen);
|
||||
|
||||
/* this iteration counts down, whereas the iteration in get_drbg() counts
|
||||
* up, to assure they can't possibly phase-lock to each other.
|
||||
*/
|
||||
for (n = ctx->n_rngs - 1; n >= 0; --n) {
|
||||
struct wc_rng_inst *drbg = get_drbg_n(ctx, n, 1);
|
||||
|
||||
if (! drbg) {
|
||||
ret = -EINTR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* perturb the seed with the CPU ID, so that no DRBG has the exact same
|
||||
* seed.
|
||||
*/
|
||||
seed_copy[0] = (u8)(n >> 8);
|
||||
seed_copy[1] = (u8)n;
|
||||
|
||||
{
|
||||
/* for the default RNG, make sure we don't cache an underlying SHA256
|
||||
* method that uses vector insns (forbidden from irq handlers).
|
||||
*/
|
||||
int need_fpu_restore = (tfm == crypto_default_rng) ? (DISABLE_VECTOR_REGISTERS() == 0) : 0;
|
||||
ret = wc_RNG_DRBG_Reseed(&drbg->rng, seed_copy, slen + 2);
|
||||
if (need_fpu_restore)
|
||||
REENABLE_VECTOR_REGISTERS();
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
pr_warn_once("WARNING: wc_RNG_DRBG_Reseed returned %d\n",ret);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
put_drbg(drbg);
|
||||
|
||||
if (ret != 0)
|
||||
break;
|
||||
ret = wc_rng_bank_seed(ctx, seed, slen, WC_LINUXKM_INITRNG_TIMEOUT_SEC, WC_RNG_BANK_FLAG_CAN_WAIT);
|
||||
if (ret != 0) {
|
||||
pr_err("wc_rng_bank_seed() in wc_linuxkm_drbg_seed() returned err %d.\n", ret);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
free(seed_copy);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1506,7 +1249,7 @@ static struct rng_alg wc_linuxkm_drbg = {
|
||||
.cra_name = WOLFKM_STDRNG_NAME,
|
||||
.cra_driver_name = WOLFKM_STDRNG_DRIVER,
|
||||
.cra_priority = WOLFSSL_LINUXKM_LKCAPI_PRIORITY,
|
||||
.cra_ctxsize = sizeof(struct wc_linuxkm_drbg_ctx),
|
||||
.cra_ctxsize = sizeof(struct wc_rng_bank),
|
||||
.cra_init = wc_linuxkm_drbg_init_tfm,
|
||||
.cra_exit = wc_linuxkm_drbg_exit_tfm,
|
||||
.cra_module = THIS_MODULE
|
||||
@@ -1549,9 +1292,9 @@ static int wc_linuxkm_drbg_loaded = 0;
|
||||
|
||||
#ifdef WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS
|
||||
|
||||
static inline struct wc_linuxkm_drbg_ctx *get_default_drbg_ctx(void) {
|
||||
static inline struct wc_rng_bank *get_default_drbg_ctx(void) {
|
||||
struct crypto_rng *current_crypto_default_rng = get_crypto_default_rng();
|
||||
struct wc_linuxkm_drbg_ctx *ctx = (current_crypto_default_rng ? (struct wc_linuxkm_drbg_ctx *)crypto_rng_ctx(current_crypto_default_rng) : NULL);
|
||||
struct wc_rng_bank *ctx = (current_crypto_default_rng ? (struct wc_rng_bank *)crypto_rng_ctx(current_crypto_default_rng) : NULL);
|
||||
if (ctx && (! ctx->rngs)) {
|
||||
pr_err_once("BUG: get_default_drbg_ctx() found null ctx->rngs.");
|
||||
return NULL;
|
||||
@@ -1681,7 +1424,7 @@ static ssize_t wc_extract_crng_user(void __user *buf, size_t nbytes) {
|
||||
}
|
||||
|
||||
static int wc_mix_pool_bytes(const void *buf, size_t len) {
|
||||
struct wc_linuxkm_drbg_ctx *ctx;
|
||||
struct wc_rng_bank *ctx;
|
||||
size_t i;
|
||||
int n;
|
||||
int can_sleep = (preempt_count() == 0);
|
||||
@@ -1693,19 +1436,20 @@ static int wc_mix_pool_bytes(const void *buf, size_t len) {
|
||||
return -EFAULT;
|
||||
|
||||
for (n = ctx->n_rngs - 1; n >= 0; --n) {
|
||||
struct wc_rng_inst *drbg = get_drbg_n(ctx, n, 0);
|
||||
struct wc_rng_bank_inst *drbg;
|
||||
|
||||
int V_offset;
|
||||
|
||||
if (! drbg)
|
||||
if (wc_rng_bank_checkout(ctx, &drbg, n, 0, WC_RNG_BANK_FLAG_NONE) != 0)
|
||||
continue;
|
||||
|
||||
for (i = 0, V_offset = 0; i < len; ++i) {
|
||||
((struct DRBG_internal *)drbg->rng.drbg)->V[V_offset++] += ((byte *)buf)[i];
|
||||
if (V_offset == (int)sizeof ((struct DRBG_internal *)drbg->rng.drbg)->V)
|
||||
((struct DRBG_internal *)WC_RNG_BANK_INST_TO_RNG(drbg)->drbg)->V[V_offset++] += ((byte *)buf)[i];
|
||||
if (V_offset == (int)sizeof ((struct DRBG_internal *)WC_RNG_BANK_INST_TO_RNG(drbg)->drbg)->V)
|
||||
V_offset = 0;
|
||||
}
|
||||
|
||||
put_drbg(drbg);
|
||||
wc_rng_bank_checkin(ctx, &drbg);
|
||||
if (can_sleep) {
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
@@ -1717,40 +1461,23 @@ static int wc_mix_pool_bytes(const void *buf, size_t len) {
|
||||
}
|
||||
|
||||
static int wc_crng_reseed(void) {
|
||||
struct wc_linuxkm_drbg_ctx *ctx = get_default_drbg_ctx();
|
||||
int n;
|
||||
struct wc_rng_bank *ctx = get_default_drbg_ctx();
|
||||
int can_sleep = (preempt_count() == 0);
|
||||
int ret;
|
||||
|
||||
if (! ctx)
|
||||
return -EFAULT;
|
||||
|
||||
for (n = ctx->n_rngs - 1; n >= 0; --n) {
|
||||
struct wc_rng_inst *drbg = get_drbg_n(ctx, n, 1);
|
||||
|
||||
if (! drbg)
|
||||
return -EINTR;
|
||||
|
||||
((struct DRBG_internal *)drbg->rng.drbg)->reseedCtr = WC_RESEED_INTERVAL;
|
||||
|
||||
if (can_sleep) {
|
||||
byte scratch[4];
|
||||
int need_reenable_vec = (DISABLE_VECTOR_REGISTERS() == 0);
|
||||
int ret = wc_RNG_GenerateBlock(&drbg->rng, scratch, (word32)sizeof(scratch));
|
||||
if (need_reenable_vec)
|
||||
REENABLE_VECTOR_REGISTERS();
|
||||
if (ret != 0)
|
||||
pr_err("ERROR: wc_crng_reseed() wc_RNG_GenerateBlock() for DRBG #%d returned %d.", n, ret);
|
||||
put_drbg(drbg);
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
cond_resched();
|
||||
}
|
||||
else {
|
||||
put_drbg(drbg);
|
||||
}
|
||||
ret = wc_rng_bank_reseed(ctx, WC_LINUXKM_INITRNG_TIMEOUT_SEC,
|
||||
can_sleep
|
||||
?
|
||||
WC_RNG_BANK_FLAG_CAN_WAIT
|
||||
:
|
||||
WC_RNG_BANK_FLAG_NONE);
|
||||
if (ret != 0) {
|
||||
pr_err("ERROR: wc_rng_bank_reseed() returned err %d.\n", ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct wolfssl_linuxkm_random_bytes_handlers random_bytes_handlers = {
|
||||
@@ -2266,4 +1993,8 @@ static int wc_linuxkm_drbg_cleanup(void) {
|
||||
|
||||
#endif /* LINUXKM_LKCAPI_REGISTER_HASH_DRBG */
|
||||
|
||||
#ifndef LKCAPI_INITRNG
|
||||
#define LKCAPI_INITRNG(rng) wc_InitRng(rng)
|
||||
#endif
|
||||
|
||||
#endif /* !WC_SKIP_INCLUDED_C_FILES */
|
||||
|
||||
@@ -66,6 +66,9 @@
|
||||
#include <wolfssl/wolfcrypt/wolfentropy.h>
|
||||
#endif
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
#ifdef WC_RNG_BANK_SUPPORT
|
||||
#include <wolfssl/wolfcrypt/rng_bank.h>
|
||||
#endif
|
||||
#endif
|
||||
#include <wolfssl/wolfcrypt/coding.h>
|
||||
#include <wolfssl/wolfcrypt/signature.h>
|
||||
|
||||
@@ -297,8 +297,10 @@ void wc_linuxkm_relax_long_loop(void) {
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
#if defined(WC_LINUXKM_WOLFENTROPY_IN_GLUE_LAYER)
|
||||
@@ -1286,7 +1288,9 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) {
|
||||
wolfssl_linuxkm_pie_redirect_table.kvfree = kvfree;
|
||||
#endif
|
||||
|
||||
#ifndef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
|
||||
wolfssl_linuxkm_pie_redirect_table.get_random_bytes = get_random_bytes;
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
|
||||
wolfssl_linuxkm_pie_redirect_table.getnstimeofday =
|
||||
getnstimeofday;
|
||||
@@ -1475,9 +1479,7 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) {
|
||||
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
|
||||
#endif /* !WOLFCRYPT_ONLY && !NO_CERTS */
|
||||
|
||||
#ifdef WOLFSSL_DEBUG_BACKTRACE_ERROR_CODES
|
||||
wolfssl_linuxkm_pie_redirect_table.dump_stack = dump_stack;
|
||||
#endif
|
||||
|
||||
wolfssl_linuxkm_pie_redirect_table.preempt_count = my_preempt_count;
|
||||
#ifndef _raw_spin_lock_irqsave
|
||||
|
||||
@@ -332,7 +332,8 @@ WARN_UNUSED_RESULT int wc_save_vector_registers_x86(enum wc_svr_flags flags)
|
||||
* a second look at preempt_count().
|
||||
*/
|
||||
if (((preempt_count() & (NMI_MASK | HARDIRQ_MASK)) != 0) || (task_pid_nr(current) == 0)) {
|
||||
VRG_PR_WARN_X("WARNING: wc_save_vector_registers_x86 called with preempt_count 0x%x and pid %d on CPU %d.\n", preempt_count(), task_pid_nr(current), raw_smp_processor_id());
|
||||
if (! (flags & WC_SVR_FLAG_INHIBIT))
|
||||
VRG_PR_WARN_X("WARNING: wc_save_vector_registers_x86(0x%x) called with preempt_count 0x%x and pid %d on CPU %d.\n", (unsigned)flags, preempt_count(), task_pid_nr(current), raw_smp_processor_id());
|
||||
return WC_ACCEL_INHIBIT_E;
|
||||
}
|
||||
|
||||
|
||||
@@ -185,6 +185,10 @@ if BUILD_MEMUSE
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wolfentropy.c
|
||||
endif
|
||||
|
||||
if BUILD_RNG_BANK
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/rng_bank.c
|
||||
endif
|
||||
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/kdf.c
|
||||
|
||||
if BUILD_RSA
|
||||
@@ -434,6 +438,10 @@ if BUILD_MEMUSE
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wolfentropy.c
|
||||
endif
|
||||
|
||||
if BUILD_RNG_BANK
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/rng_bank.c
|
||||
endif
|
||||
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/kdf.c
|
||||
|
||||
if BUILD_RSA
|
||||
@@ -789,6 +797,9 @@ src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/random.c
|
||||
if BUILD_MEMUSE
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wolfentropy.c
|
||||
endif
|
||||
if BUILD_RNG_BANK
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/rng_bank.c
|
||||
endif
|
||||
endif
|
||||
endif !BUILD_FIPS_V2_PLUS
|
||||
|
||||
|
||||
@@ -659,6 +659,12 @@ const char* wc_GetErrorString(int error)
|
||||
case MLKEM_PUB_HASH_E:
|
||||
return "ML-KEM priv key's stored hash doesn't match encoded pub key";
|
||||
|
||||
case BUSY_E:
|
||||
return "Object is busy";
|
||||
|
||||
case ALREADY_E:
|
||||
return "Operation was redundant or preempted";
|
||||
|
||||
case MAX_CODE_E:
|
||||
case WC_SPAN1_MIN_CODE_E:
|
||||
case MIN_CODE_E:
|
||||
|
||||
@@ -68,6 +68,9 @@ This library contains implementation for the random number generator.
|
||||
|
||||
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
#ifdef WC_RNG_BANK_SUPPORT
|
||||
#include <wolfssl/wolfcrypt/rng_bank.h>
|
||||
#endif
|
||||
#include <wolfssl/wolfcrypt/cpuid.h>
|
||||
|
||||
#ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */
|
||||
@@ -371,7 +374,8 @@ static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type,
|
||||
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if (ret != 0)
|
||||
WOLFSSL_DEBUG_PRINTF("%s failed with err = %d", __FUNCTION__, ret);
|
||||
WOLFSSL_DEBUG_PRINTF("ERROR: %s failed with err = %d", __FUNCTION__,
|
||||
ret);
|
||||
#endif
|
||||
|
||||
return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
|
||||
@@ -414,7 +418,8 @@ static int Hash_DRBG_Reseed(DRBG_internal* drbg, const byte* seed, word32 seedSz
|
||||
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if (ret != 0)
|
||||
WOLFSSL_DEBUG_PRINTF("Hash_DRBG_Reseed failed with err %d.", ret);
|
||||
WOLFSSL_DEBUG_PRINTF("ERROR: Hash_DRBG_Reseed failed with err %d.",
|
||||
ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
@@ -545,7 +550,7 @@ static int Hash_gen(DRBG_internal* drbg, byte* out, word32 outSz, const byte* V)
|
||||
* and (2) the caller will actually see the DRBG_FAILURE code, and is
|
||||
* free to (and probably will) log it itself.
|
||||
*/
|
||||
WOLFSSL_DEBUG_PRINTF("Hash_gen failed with err %d.", ret);
|
||||
WOLFSSL_DEBUG_PRINTF("ERROR: Hash_gen failed with err %d.", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -662,7 +667,8 @@ static int Hash_DRBG_Generate(DRBG_internal* drbg, byte* out, word32 outSz)
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if ((ret != DRBG_SUCCESS) && (ret != DRBG_FAILURE)) {
|
||||
/* see note above regarding log spam reduction */
|
||||
WOLFSSL_DEBUG_PRINTF("Hash_DRBG_Generate failed with err %d.", ret);
|
||||
WOLFSSL_DEBUG_PRINTF("ERROR: Hash_DRBG_Generate failed with err %d.",
|
||||
ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -962,7 +968,9 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
|
||||
ret = seedCb(&rng->seed, seed, seedSz);
|
||||
if (ret != 0) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF("seedCb in _InitRng() failed with err = %d", ret);
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: seedCb in _InitRng() failed with err = %d",
|
||||
ret);
|
||||
#endif
|
||||
ret = DRBG_FAILURE;
|
||||
}
|
||||
@@ -974,7 +982,9 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
|
||||
#if defined(DEBUG_WOLFSSL)
|
||||
WOLFSSL_MSG_EX("Seed generation failed... %d", ret);
|
||||
#elif defined(WC_VERBOSE_RNG)
|
||||
WOLFSSL_DEBUG_PRINTF("wc_GenerateSeed() in _InitRng() failed with err %d", ret);
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: wc_GenerateSeed() in _InitRng() failed with err %d",
|
||||
ret);
|
||||
#endif
|
||||
ret = DRBG_FAILURE;
|
||||
rng->status = DRBG_FAILED;
|
||||
@@ -988,7 +998,9 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
|
||||
}
|
||||
#elif defined(WC_VERBOSE_RNG)
|
||||
if (ret != DRBG_SUCCESS) {
|
||||
WOLFSSL_DEBUG_PRINTF("wc_RNG_TestSeed() in _InitRng() returned err %d.", ret);
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: wc_RNG_TestSeed() in _InitRng() returned err %d.",
|
||||
ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1166,7 +1178,8 @@ static int PollAndReSeed(WC_RNG* rng)
|
||||
ret = seedCb(&rng->seed, newSeed, SEED_SZ + SEED_BLOCK_SZ);
|
||||
if (ret != 0) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF("seedCb() in PollAndReSeed() failed with err %d", ret);
|
||||
WOLFSSL_DEBUG_PRINTF("ERROR: seedCb() in PollAndReSeed() "
|
||||
"failed with err %d", ret);
|
||||
#endif
|
||||
ret = DRBG_FAILURE;
|
||||
}
|
||||
@@ -1176,7 +1189,9 @@ static int PollAndReSeed(WC_RNG* rng)
|
||||
SEED_SZ + SEED_BLOCK_SZ);
|
||||
if (ret != 0) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF("wc_GenerateSeed() in PollAndReSeed() failed with err %d", ret);
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: wc_GenerateSeed() in PollAndReSeed() failed with "
|
||||
"err %d", ret);
|
||||
#endif
|
||||
ret = DRBG_FAILURE;
|
||||
}
|
||||
@@ -1186,7 +1201,9 @@ static int PollAndReSeed(WC_RNG* rng)
|
||||
ret = wc_RNG_TestSeed(newSeed, SEED_SZ + SEED_BLOCK_SZ);
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if (ret != DRBG_SUCCESS)
|
||||
WOLFSSL_DEBUG_PRINTF("wc_RNG_TestSeed() in PollAndReSeed() returned err %d.", ret);
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: wc_RNG_TestSeed() in PollAndReSeed() returned "
|
||||
"err %d.", ret);
|
||||
#endif
|
||||
}
|
||||
if (ret == DRBG_SUCCESS)
|
||||
@@ -1210,8 +1227,12 @@ static int PollAndReSeed(WC_RNG* rng)
|
||||
#endif
|
||||
|
||||
/* place a generated block in output */
|
||||
#ifdef WC_RNG_BANK_SUPPORT
|
||||
static int wc_local_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
|
||||
#else
|
||||
WOLFSSL_ABI
|
||||
int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
|
||||
#endif
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -1260,7 +1281,8 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
|
||||
ret = (int)CUSTOM_RAND_GENERATE_BLOCK(output, sz);
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if (ret != 0)
|
||||
WOLFSSL_DEBUG_PRINTF("CUSTOM_RAND_GENERATE_BLOCK failed with err %d.", ret);
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: CUSTOM_RAND_GENERATE_BLOCK failed with err %d.", ret);
|
||||
#endif
|
||||
#else
|
||||
|
||||
@@ -1311,6 +1333,42 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef WC_RNG_BANK_SUPPORT
|
||||
WOLFSSL_ABI
|
||||
int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
|
||||
{
|
||||
if (rng == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (rng->status == WC_DRBG_BANKREF) {
|
||||
int ret;
|
||||
struct wc_rng_bank_inst *bank_inst = NULL;
|
||||
|
||||
ret = wc_local_rng_bank_checkout_for_bankref(rng->bankref, &bank_inst);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
if (bank_inst == NULL)
|
||||
return BAD_STATE_E;
|
||||
ret = wc_local_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(bank_inst),
|
||||
output, sz);
|
||||
{
|
||||
int checkin_ret = wc_rng_bank_checkin(rng->bankref, &bank_inst);
|
||||
if (checkin_ret != 0) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: wc_RNG_GenerateBlock() wc_rng_bank_checkin() "
|
||||
"failed with err %d.", checkin_ret);
|
||||
#endif
|
||||
if (ret == 0)
|
||||
ret = checkin_ret;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
return wc_local_RNG_GenerateBlock(rng, output, sz);
|
||||
}
|
||||
#endif
|
||||
|
||||
int wc_RNG_GenerateByte(WC_RNG* rng, byte* b)
|
||||
{
|
||||
@@ -1325,6 +1383,11 @@ int wc_FreeRng(WC_RNG* rng)
|
||||
if (rng == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
#ifdef WC_RNG_BANK_SUPPORT
|
||||
if (rng->status == WC_DRBG_BANKREF)
|
||||
return wc_BankRef_Release(rng);
|
||||
#endif /* WC_RNG_BANK_SUPPORT */
|
||||
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT)
|
||||
wolfAsync_DevCtxFree(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG);
|
||||
#endif
|
||||
@@ -3071,32 +3134,10 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
|
||||
|
||||
#elif defined(WOLFSSL_LINUXKM)
|
||||
|
||||
/* When registering the kernel default DRBG with a native/intrinsic entropy
|
||||
* source, fallback to get_random_bytes() isn't allowed because we replace
|
||||
* it with our DRBG.
|
||||
*/
|
||||
#ifndef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
|
||||
#include <linux/random.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_ENTROPY_MEMUSE) && \
|
||||
defined(LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT)
|
||||
|
||||
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
|
||||
{
|
||||
(void)os;
|
||||
return wc_Entropy_Get(MAX_ENTROPY_BITS, output, sz);
|
||||
}
|
||||
|
||||
#elif (defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)) && \
|
||||
defined(LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT)
|
||||
|
||||
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
|
||||
{
|
||||
(void)os;
|
||||
return wc_GenerateSeed_IntelRD(NULL, output, sz);
|
||||
}
|
||||
|
||||
#else /* !((HAVE_ENTROPY_MEMUSE || HAVE_*_RDSEED) && LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT) */
|
||||
|
||||
#include <linux/random.h>
|
||||
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
|
||||
{
|
||||
(void)os;
|
||||
@@ -3104,11 +3145,9 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
|
||||
|
||||
#ifdef HAVE_ENTROPY_MEMUSE
|
||||
ret = wc_Entropy_Get(MAX_ENTROPY_BITS, output, sz);
|
||||
if (ret == 0) {
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
}
|
||||
#ifdef ENTROPY_MEMUSE_FORCE_FAILURE
|
||||
/* Don't fallback to /dev/urandom. */
|
||||
return ret;
|
||||
#endif
|
||||
#endif
|
||||
@@ -3116,23 +3155,30 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
|
||||
#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
|
||||
if (IS_INTEL_RDSEED(intel_flags)) {
|
||||
ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
|
||||
#ifndef FORCE_FAILURE_RDSEED
|
||||
if (ret == 0)
|
||||
#endif
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
#ifdef FORCE_FAILURE_RDSEED
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
#endif /* HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
|
||||
|
||||
#ifdef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
|
||||
#if !defined(HAVE_ENTROPY_MEMUSE) && \
|
||||
!defined(HAVE_INTEL_RDSEED) && \
|
||||
!defined(HAVE_AMD_RDSEED)
|
||||
#error LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT requires an intrinsic entropy source.
|
||||
#else
|
||||
return ret;
|
||||
#endif
|
||||
#else
|
||||
(void)ret;
|
||||
|
||||
get_random_bytes(output, sz);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* !(HAVE_*_RDSEED && LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT) */
|
||||
|
||||
#elif defined(WOLFSSL_BSDKM)
|
||||
#include <sys/random.h>
|
||||
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
|
||||
|
||||
723
wolfcrypt/src/rng_bank.c
Normal file
723
wolfcrypt/src/rng_bank.c
Normal file
@@ -0,0 +1,723 @@
|
||||
/* rng_bank.c
|
||||
*
|
||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
|
||||
|
||||
#ifdef WC_RNG_BANK_SUPPORT
|
||||
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
#include <wolfssl/wolfcrypt/rng_bank.h>
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_init(
|
||||
struct wc_rng_bank *ctx,
|
||||
int n_rngs,
|
||||
word32 flags,
|
||||
int timeout_secs,
|
||||
void *heap,
|
||||
int devId)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
int need_reenable_vec = 0;
|
||||
|
||||
if ((ctx == NULL) || (n_rngs <= 0))
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
XMEMSET(ctx, 0, sizeof(*ctx));
|
||||
|
||||
wolfSSL_RefInit(&ctx->refcount, &ret);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ctx->flags = flags | WC_RNG_BANK_FLAG_INITED;
|
||||
ctx->heap = heap;
|
||||
|
||||
ctx->rngs = (struct wc_rng_bank_inst *)
|
||||
XMALLOC(sizeof(*ctx->rngs) * (size_t)n_rngs,
|
||||
heap, DYNAMIC_TYPE_RNG);
|
||||
if (! ctx->rngs)
|
||||
ret = MEMORY_E;
|
||||
|
||||
if (ret == 0) {
|
||||
XMEMSET(ctx->rngs, 0, sizeof(*ctx->rngs) * (size_t)n_rngs);
|
||||
ctx->n_rngs = n_rngs;
|
||||
|
||||
for (i = 0; i < n_rngs; ++i) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
int nretries = 0;
|
||||
#endif
|
||||
time_t ts1 = XTIME(0);
|
||||
for (;;) {
|
||||
time_t ts2;
|
||||
|
||||
if (flags & WC_RNG_BANK_FLAG_NO_VECTOR_OPS)
|
||||
need_reenable_vec = (DISABLE_VECTOR_REGISTERS() == 0);
|
||||
ret = wc_InitRngNonce_ex(
|
||||
WC_RNG_BANK_INST_TO_RNG(ctx->rngs + i),
|
||||
(byte *)&ctx->rngs[i], sizeof(byte *), heap, devId);
|
||||
|
||||
if (need_reenable_vec)
|
||||
REENABLE_VECTOR_REGISTERS();
|
||||
/* if we're allowed to sleep, relax the loop between each inner
|
||||
* iteration even on success, assuring relaxation of the outer
|
||||
* iterations.
|
||||
*/
|
||||
WC_RELAX_LONG_LOOP();
|
||||
if (ret == 0)
|
||||
break;
|
||||
/* Allow interrupt only if we're stuck spinning retries -- i.e.,
|
||||
* don't allow an untimely user signal to derail an
|
||||
* initialization that is proceeding expeditiously.
|
||||
*/
|
||||
ret = WC_CHECK_FOR_INTR_SIGNALS();
|
||||
if (ret == WC_NO_ERR_TRACE(INTERRUPTED_E))
|
||||
break;
|
||||
ts2 = XTIME(0);
|
||||
if (ts2 - ts1 > timeout_secs) {
|
||||
ret = WC_TIMEOUT_E;
|
||||
break;
|
||||
}
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
++nretries;
|
||||
#endif
|
||||
}
|
||||
if (ret != 0) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: wc_InitRng returned %d after %d retries.\n", ret,
|
||||
nretries);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
(void)wc_rng_bank_fini(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_new(
|
||||
struct wc_rng_bank **ctx,
|
||||
int n_rngs,
|
||||
word32 flags,
|
||||
int timeout_secs,
|
||||
void *heap,
|
||||
int devId)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((ctx == NULL) || (n_rngs <= 0))
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
*ctx = (struct wc_rng_bank *)XMALLOC(sizeof(struct wc_rng_bank), heap, DYNAMIC_TYPE_RNG);
|
||||
if (*ctx == NULL)
|
||||
return MEMORY_E;
|
||||
|
||||
ret = wc_rng_bank_init(*ctx, n_rngs, flags, timeout_secs, heap, devId);
|
||||
|
||||
if (ret != 0) {
|
||||
XFREE(*ctx, heap, DYNAMIC_TYPE_RNG);
|
||||
*ctx = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_set_affinity_handlers(
|
||||
struct wc_rng_bank *ctx,
|
||||
wc_affinity_lock_fn_t affinity_lock_cb,
|
||||
wc_affinity_get_id_fn_t affinity_get_id_cb,
|
||||
wc_affinity_unlock_fn_t affinity_unlock_cb,
|
||||
void *cb_arg)
|
||||
{
|
||||
if ((ctx == NULL) ||
|
||||
(! (ctx->flags & WC_RNG_BANK_FLAG_INITED)))
|
||||
{
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if ((affinity_lock_cb == NULL) ^ (affinity_unlock_cb == NULL))
|
||||
return BAD_FUNC_ARG;
|
||||
if (wolfSSL_RefCur(ctx->refcount) != 1)
|
||||
return BUSY_E;
|
||||
ctx->affinity_lock_cb = affinity_lock_cb;
|
||||
ctx->affinity_get_id_cb = affinity_get_id_cb;
|
||||
ctx->affinity_unlock_cb = affinity_unlock_cb;
|
||||
ctx->cb_arg = cb_arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_fini(struct wc_rng_bank *ctx) {
|
||||
int i;
|
||||
|
||||
if (ctx == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (ctx->flags == WC_RNG_BANK_FLAG_NONE)
|
||||
return 0;
|
||||
|
||||
if (! (ctx->flags & WC_RNG_BANK_FLAG_INITED))
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (wolfSSL_RefCur(ctx->refcount) > 1)
|
||||
return BUSY_E;
|
||||
|
||||
if (ctx->rngs) {
|
||||
for (i = 0; i < ctx->n_rngs; ++i) {
|
||||
if (ctx->rngs[i].lock != 0) {
|
||||
/* better to leak than to crash. */
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"BUG: wc_rng_bank_fini() called with RNG #%d still "
|
||||
"locked.\n", i);
|
||||
#endif
|
||||
return BUSY_E;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ctx->n_rngs; ++i) {
|
||||
wc_FreeRng(&ctx->rngs[i].rng);
|
||||
}
|
||||
|
||||
XFREE(ctx->rngs, ctx->heap, DYNAMIC_TYPE_RNG);
|
||||
ctx->rngs = NULL;
|
||||
ctx->n_rngs = 0;
|
||||
}
|
||||
|
||||
wolfSSL_RefFree(&ctx->refcount);
|
||||
|
||||
ctx->flags = WC_RNG_BANK_FLAG_NONE;
|
||||
ctx->cb_arg = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_free(struct wc_rng_bank **ctx) {
|
||||
int ret;
|
||||
void *heap;
|
||||
|
||||
if (ctx == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (*ctx == NULL)
|
||||
return 0;
|
||||
|
||||
heap = (*ctx)->heap;
|
||||
|
||||
ret = wc_rng_bank_fini(*ctx);
|
||||
|
||||
if (ret == 0) {
|
||||
XFREE(*ctx, heap, DYNAMIC_TYPE_RNG);
|
||||
*ctx = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* wc_rng_bank_checkout() uses atomic operations to get exclusive ownership of a
|
||||
* DRBG without delay. It expects to be called in uninterruptible context,
|
||||
* though works fine in any context. When _PREFER_AFFINITY_INST, it starts by
|
||||
* trying the DRBG matching the local DRBG (usually the current CPU ID, returned
|
||||
* by bank->affinity_get_id_cb()), and if that doesn't immediately succeed, and
|
||||
* _CAN_FAIL_OVER_INST, it iterates upward until one succeeds. The first
|
||||
* attempt will always succeed, even under intense load, unless there is or has
|
||||
* recently been a reseed or mix-in operation competing with generators.
|
||||
*/
|
||||
WOLFSSL_API int wc_rng_bank_checkout(
|
||||
struct wc_rng_bank *bank,
|
||||
struct wc_rng_bank_inst **rng_inst,
|
||||
int preferred_inst_offset,
|
||||
int timeout_secs,
|
||||
word32 flags)
|
||||
{
|
||||
int new_lock_value = WC_RNG_BANK_INST_LOCK_HELD;
|
||||
int ret = 0;
|
||||
time_t ts1, ts2;
|
||||
int n_rngs_tried = 0;
|
||||
|
||||
if ((bank == NULL) ||
|
||||
(! (bank->flags & WC_RNG_BANK_FLAG_INITED)) ||
|
||||
(rng_inst == NULL))
|
||||
{
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if ((flags & WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST) &&
|
||||
(bank->affinity_get_id_cb == NULL))
|
||||
{
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"BUG: wc_rng_bank_checkout() called with _PREFER_AFFINITY_INST but "
|
||||
"no _get_id_cb.\n");
|
||||
#endif
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (flags & WC_RNG_BANK_FLAG_AFFINITY_LOCK) {
|
||||
if ((bank->affinity_lock_cb == NULL) ||
|
||||
(bank->affinity_unlock_cb == NULL))
|
||||
{
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"BUG: wc_rng_bank_checkout() called with _AFFINITY_LOCK but "
|
||||
"missing _lock_cb.\n");
|
||||
#endif
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
ret = bank->affinity_lock_cb(bank->cb_arg);
|
||||
if (ret == 0)
|
||||
new_lock_value |= WC_RNG_BANK_INST_LOCK_AFFINITY_LOCKED;
|
||||
else if (ret != WC_NO_ERR_TRACE(ALREADY_E))
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (flags & WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST) {
|
||||
preferred_inst_offset = -1;
|
||||
ret = bank->affinity_get_id_cb(bank->cb_arg, &preferred_inst_offset);
|
||||
if (ret != 0) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"BUG: bank->affinity_get_id_cb() returned err %d.\n", ret);
|
||||
#endif
|
||||
}
|
||||
else if (((preferred_inst_offset < 0) ||
|
||||
(preferred_inst_offset >= bank->n_rngs)))
|
||||
{
|
||||
ret = BAD_INDEX_E;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((preferred_inst_offset < 0) ||
|
||||
(preferred_inst_offset >= bank->n_rngs))
|
||||
{
|
||||
ret = BAD_INDEX_E;
|
||||
}
|
||||
}
|
||||
|
||||
if ((timeout_secs > 0) && (flags & WC_RNG_BANK_FLAG_CAN_WAIT))
|
||||
ts1 = XTIME(0);
|
||||
else
|
||||
ts1 = 0; /* mollify -Wmaybe-uninitialized... */
|
||||
|
||||
for (; ret == 0;) {
|
||||
int expected = 0;
|
||||
|
||||
if (wolfSSL_Atomic_Int_CompareExchange(
|
||||
&bank->rngs[preferred_inst_offset].lock,
|
||||
&expected,
|
||||
new_lock_value))
|
||||
{
|
||||
*rng_inst = &bank->rngs[preferred_inst_offset];
|
||||
|
||||
if ((! (flags & WC_RNG_BANK_FLAG_CAN_WAIT)) &&
|
||||
(((struct DRBG_internal *)(*rng_inst)->rng.drbg)->reseedCtr >=
|
||||
WC_RESEED_INTERVAL) &&
|
||||
(flags & WC_RNG_BANK_FLAG_CAN_FAIL_OVER_INST) &&
|
||||
(n_rngs_tried < bank->n_rngs))
|
||||
{
|
||||
WOLFSSL_ATOMIC_STORE((*rng_inst)->lock, WC_RNG_BANK_INST_LOCK_FREE);
|
||||
}
|
||||
else {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if ((! (flags & WC_RNG_BANK_FLAG_CAN_WAIT)) &&
|
||||
(((struct DRBG_internal *)(*rng_inst)->rng.drbg)->reseedCtr >=
|
||||
WC_RESEED_INTERVAL))
|
||||
{
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"WARNING: wc_rng_bank_checkout() returning RNG ID %d, "
|
||||
"currently marked for reseed, to !_CAN_WAIT caller.\n",
|
||||
preferred_inst_offset);
|
||||
}
|
||||
|
||||
/* Note that a caller can still encounter a PollAndReSeed() via
|
||||
* wc_RNG_GenerateBlock() if a call bumps reseedCtr up to
|
||||
* WC_RESEED_INTERVAL. In kernel mode, the default interval is
|
||||
* the SP 800-90A max of 2.81E+14, which is unlikely to be
|
||||
* reached in practice.
|
||||
*/
|
||||
#endif
|
||||
|
||||
if ((flags | bank->flags) & WC_RNG_BANK_FLAG_NO_VECTOR_OPS) {
|
||||
if (DISABLE_VECTOR_REGISTERS() == 0)
|
||||
WOLFSSL_ATOMIC_STORE((*rng_inst)->lock, new_lock_value |
|
||||
WC_RNG_BANK_INST_LOCK_VEC_OPS_INH);
|
||||
}
|
||||
|
||||
return 0; /* Short-circuit return, holding onto RNG and affinity
|
||||
* locks and vector register inhibition.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & WC_RNG_BANK_FLAG_CAN_FAIL_OVER_INST) {
|
||||
if ((! (flags & WC_RNG_BANK_FLAG_CAN_WAIT)) &&
|
||||
(n_rngs_tried >= bank->n_rngs))
|
||||
{
|
||||
ret = BUSY_E;
|
||||
break; /* jump to cleanup. */
|
||||
}
|
||||
++preferred_inst_offset;
|
||||
if (preferred_inst_offset >= bank->n_rngs)
|
||||
preferred_inst_offset = 0;
|
||||
++n_rngs_tried;
|
||||
}
|
||||
else {
|
||||
if (! (flags & WC_RNG_BANK_FLAG_CAN_WAIT)) {
|
||||
ret = BUSY_E;
|
||||
break; /* jump to cleanup. */
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & WC_RNG_BANK_FLAG_AFFINITY_LOCK)
|
||||
(void)bank->affinity_unlock_cb(bank->cb_arg);
|
||||
|
||||
ret = WC_CHECK_FOR_INTR_SIGNALS();
|
||||
if (ret == WC_NO_ERR_TRACE(INTERRUPTED_E))
|
||||
return ret; /* immediate return -- no locks held */
|
||||
|
||||
if (timeout_secs > 0) {
|
||||
ts2 = XTIME(0);
|
||||
if (ts2 - ts1 >= timeout_secs)
|
||||
return WC_TIMEOUT_E; /* immediate return -- no locks held */
|
||||
}
|
||||
WC_RELAX_LONG_LOOP();
|
||||
|
||||
if (flags & WC_RNG_BANK_FLAG_AFFINITY_LOCK) {
|
||||
ret = bank->affinity_lock_cb(bank->cb_arg);
|
||||
if (ret)
|
||||
return ret; /* immediate return -- no locks held */
|
||||
}
|
||||
|
||||
/* Note that we may have been migrated at this point, but it doesn't
|
||||
* matter -- we only reach this point if we have to retry/iterate.
|
||||
*/
|
||||
}
|
||||
|
||||
if (flags & WC_RNG_BANK_FLAG_AFFINITY_LOCK)
|
||||
(void)bank->affinity_unlock_cb(bank->cb_arg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef WC_DRBG_BANKREF
|
||||
WOLFSSL_LOCAL int wc_local_rng_bank_checkout_for_bankref(
|
||||
struct wc_rng_bank *bank,
|
||||
struct wc_rng_bank_inst **rng_inst)
|
||||
{
|
||||
return wc_rng_bank_checkout(
|
||||
bank, rng_inst, 0, 0,
|
||||
WC_RNG_BANK_FLAG_CAN_FAIL_OVER_INST |
|
||||
WC_RNG_BANK_FLAG_CAN_WAIT |
|
||||
((bank->affinity_get_id_cb != NULL) ? WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST : 0) |
|
||||
((bank->affinity_lock_cb != NULL) ? WC_RNG_BANK_FLAG_AFFINITY_LOCK : 0));
|
||||
}
|
||||
#endif /* WC_DRBG_BANKREF */
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_checkin(
|
||||
struct wc_rng_bank *bank,
|
||||
struct wc_rng_bank_inst **rng_inst)
|
||||
{
|
||||
int lockval;
|
||||
|
||||
if ((bank == NULL) || (rng_inst == NULL) || (*rng_inst == NULL))
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
lockval = (int)WOLFSSL_ATOMIC_LOAD((*rng_inst)->lock);
|
||||
|
||||
WOLFSSL_ATOMIC_STORE((*rng_inst)->lock, WC_RNG_BANK_INST_LOCK_FREE);
|
||||
|
||||
*rng_inst = NULL;
|
||||
|
||||
if (lockval & WC_RNG_BANK_INST_LOCK_VEC_OPS_INH)
|
||||
REENABLE_VECTOR_REGISTERS();
|
||||
|
||||
if (lockval & WC_RNG_BANK_INST_LOCK_AFFINITY_LOCKED)
|
||||
return bank->affinity_unlock_cb(bank->cb_arg);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* note the rng_inst passed to wc_rng_bank_inst_reinit() must have been obtained
|
||||
* via wc_rng_bank_checkout() to assure that the caller holds the proper locks.
|
||||
*/
|
||||
WOLFSSL_API int wc_rng_bank_inst_reinit(
|
||||
struct wc_rng_bank *bank,
|
||||
struct wc_rng_bank_inst *rng_inst,
|
||||
int timeout_secs,
|
||||
word32 flags)
|
||||
{
|
||||
int ret;
|
||||
time_t ts1 = 0;
|
||||
int devId;
|
||||
|
||||
if ((rng_inst == NULL) ||
|
||||
(rng_inst->rng.drbg == NULL))
|
||||
{
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if ((timeout_secs > 0) && (flags & WC_RNG_BANK_FLAG_CAN_WAIT))
|
||||
ts1 = XTIME(0);
|
||||
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
|
||||
devId = rng_inst->rng.devId;
|
||||
#else
|
||||
devId = INVALID_DEVID;
|
||||
#endif
|
||||
|
||||
wc_FreeRng(&rng_inst->rng);
|
||||
|
||||
for (;;) {
|
||||
ret = wc_InitRngNonce_ex(WC_RNG_BANK_INST_TO_RNG(rng_inst),
|
||||
(byte *)&rng_inst, sizeof(byte *),
|
||||
bank->heap, devId);
|
||||
if (ret == 0)
|
||||
break;
|
||||
if (! (flags & WC_RNG_BANK_FLAG_CAN_WAIT)) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"WARNING: wc_rng_bank_inst_reinit() returning err %d.\n", ret);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
if (timeout_secs > 0) {
|
||||
time_t ts2 = XTIME(0);
|
||||
if (ts2 - ts1 >= timeout_secs) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"WARNING: wc_rng_bank_inst_reinit() timed out, err %d.\n",
|
||||
ret);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_seed(struct wc_rng_bank *bank,
|
||||
const byte* seed, word32 seedSz,
|
||||
int timeout_secs,
|
||||
word32 flags)
|
||||
{
|
||||
int ret = 0;
|
||||
int n;
|
||||
|
||||
if ((bank == NULL) ||
|
||||
(! (bank->flags & WC_RNG_BANK_FLAG_INITED)))
|
||||
{
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (seedSz == 0)
|
||||
return 0;
|
||||
|
||||
/* this iteration counts down, whereas the iteration in get_drbg() counts
|
||||
* up, to assure they can't possibly phase-lock to each other.
|
||||
*/
|
||||
for (n = bank->n_rngs - 1; n >= 0; --n) {
|
||||
struct wc_rng_bank_inst *drbg;
|
||||
ret = wc_rng_bank_checkout(bank, &drbg, n, timeout_secs, flags);
|
||||
if (ret != 0) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"WARNING: wc_rng_bank_seed(): wc_rng_bank_checkout() for "
|
||||
"inst#%d returned err %d.\n", n, ret);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
else if (drbg->rng.drbg == NULL) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"WARNING: wc_rng_bank_seed(): inst#%d has null .drbg.\n", n);
|
||||
#endif
|
||||
ret = BAD_STATE_E;
|
||||
}
|
||||
else if ((ret = wc_RNG_DRBG_Reseed(WC_RNG_BANK_INST_TO_RNG(drbg), seed,
|
||||
seedSz)) != 0)
|
||||
{
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"WARNING: wc_rng_bank_seed(): Hash_DRBG_Reseed() for inst#%d "
|
||||
"returned %d\n", n, ret);
|
||||
#endif
|
||||
}
|
||||
|
||||
(void)wc_rng_bank_checkin(bank, &drbg);
|
||||
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_reseed(struct wc_rng_bank *bank,
|
||||
int timeout_secs,
|
||||
word32 flags)
|
||||
{
|
||||
int n;
|
||||
int ret;
|
||||
time_t ts1 = 0;
|
||||
|
||||
if (! bank)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (flags & (WC_RNG_BANK_FLAG_CAN_FAIL_OVER_INST |
|
||||
WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST))
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if ((timeout_secs > 0) && (flags & WC_RNG_BANK_FLAG_CAN_WAIT))
|
||||
ts1 = XTIME(0);
|
||||
|
||||
for (n = bank->n_rngs - 1; n >= 0; --n) {
|
||||
struct wc_rng_bank_inst *drbg;
|
||||
|
||||
ret = wc_rng_bank_checkout(bank, &drbg, n, timeout_secs, flags);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
((struct DRBG_internal *)drbg->rng.drbg)->reseedCtr =
|
||||
WC_RESEED_INTERVAL;
|
||||
|
||||
if (flags & WC_RNG_BANK_FLAG_CAN_WAIT) {
|
||||
byte scratch[4];
|
||||
for (;;) {
|
||||
time_t ts2;
|
||||
ret = wc_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(drbg), scratch,
|
||||
(word32)sizeof(scratch));
|
||||
if (ret == 0)
|
||||
break;
|
||||
if ((timeout_secs <= 0) ||
|
||||
(! (flags & WC_RNG_BANK_FLAG_CAN_WAIT)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
ts2 = XTIME(0);
|
||||
if (ts2 - ts1 > timeout_secs) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: timeout after attempted reseed by "
|
||||
"wc_RNG_GenerateBlock() for DRBG #%d, err %d.", n, ret);
|
||||
#endif
|
||||
ret = WC_TIMEOUT_E;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if ((ret != 0) && (ret != WC_NO_ERR_TRACE(WC_TIMEOUT_E)))
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: wc_crng_reseed() wc_RNG_GenerateBlock() "
|
||||
"for DRBG #%d returned %d.", n, ret);
|
||||
#endif
|
||||
wc_rng_bank_checkin(bank, &drbg);
|
||||
if (ret == WC_NO_ERR_TRACE(WC_TIMEOUT_E))
|
||||
return ret;
|
||||
ret = WC_CHECK_FOR_INTR_SIGNALS();
|
||||
if (ret == WC_NO_ERR_TRACE(INTERRUPTED_E))
|
||||
return ret;
|
||||
WC_RELAX_LONG_LOOP();
|
||||
}
|
||||
else {
|
||||
wc_rng_bank_checkin(bank, &drbg);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WC_DRBG_BANKREF
|
||||
|
||||
WOLFSSL_API int wc_InitRng_BankRef(struct wc_rng_bank *bank, WC_RNG *rng)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((bank == NULL) ||
|
||||
(! (bank->flags & WC_RNG_BANK_FLAG_INITED)) ||
|
||||
(rng == NULL))
|
||||
{
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
XMEMSET(rng, 0, sizeof(*rng));
|
||||
|
||||
wolfSSL_RefInc(&bank->refcount, &ret);
|
||||
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
rng->heap = bank->heap;
|
||||
rng->status = WC_DRBG_BANKREF;
|
||||
rng->bankref = bank;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
WOLFSSL_API int wc_BankRef_Release(WC_RNG *rng)
|
||||
{
|
||||
int isZero = 0;
|
||||
int ret = 0;
|
||||
if (rng->bankref == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
wolfSSL_RefDec(&rng->bankref->refcount, &isZero, &ret);
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if (isZero)
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"BUG: wc_BankRef_Release() popped refcount to zero.\n");
|
||||
#else
|
||||
(void)isZero;
|
||||
#endif
|
||||
rng->heap = NULL;
|
||||
rng->status = WC_DRBG_NOT_INIT;
|
||||
rng->bankref = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
WOLFSSL_API int wc_rng_new_bankref(struct wc_rng_bank *bank, WC_RNG **rng) {
|
||||
int ret;
|
||||
|
||||
if ((bank == NULL) ||
|
||||
(! (bank->flags & WC_RNG_BANK_FLAG_INITED)) ||
|
||||
(rng == NULL))
|
||||
{
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
*rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), bank->heap, DYNAMIC_TYPE_RNG);
|
||||
if (*rng == NULL) {
|
||||
return MEMORY_E;
|
||||
}
|
||||
|
||||
ret = wc_InitRng_BankRef(bank, *rng);
|
||||
if (ret != 0) {
|
||||
XFREE(*rng, bank->heap, DYNAMIC_TYPE_RNG);
|
||||
*rng = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* WC_DRBG_BANKREF */
|
||||
|
||||
#endif /* WC_RNG_BANK_SUPPORT */
|
||||
@@ -1698,6 +1698,7 @@ void wolfSSL_RefWithMutexFree(wolfSSL_RefWithMutex* ref)
|
||||
if (wc_FreeMutex(&ref->mutex) != 0) {
|
||||
WOLFSSL_MSG("Failed to free mutex of reference counting!");
|
||||
}
|
||||
ref->count = 0;
|
||||
}
|
||||
|
||||
void wolfSSL_RefWithMutexInc(wolfSSL_RefWithMutex* ref, int* err)
|
||||
|
||||
@@ -325,6 +325,9 @@ static const byte const_byte_array[] = "A+Gd\0\0\0";
|
||||
#include <wolfssl/wolfcrypt/arc4.h>
|
||||
#if !defined(WC_NO_RNG)
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
#ifdef WC_RNG_BANK_SUPPORT
|
||||
#include <wolfssl/wolfcrypt/rng_bank.h>
|
||||
#endif
|
||||
#endif
|
||||
#include <wolfssl/wolfcrypt/wolfmath.h>
|
||||
#include <wolfssl/wolfcrypt/coding.h>
|
||||
@@ -687,6 +690,9 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t dsa_test(void);
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t srp_test(void);
|
||||
#ifndef WC_NO_RNG
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_test(void);
|
||||
#ifdef WC_RNG_BANK_SUPPORT
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void);
|
||||
#endif
|
||||
#endif /* WC_NO_RNG */
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pwdbased_test(void);
|
||||
#if defined(USE_CERT_BUFFERS_2048) && \
|
||||
@@ -2133,6 +2139,12 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\
|
||||
TEST_FAIL("RANDOM test failed!\n", ret);
|
||||
else
|
||||
TEST_PASS("RANDOM test passed!\n");
|
||||
#ifdef WC_RNG_BANK_SUPPORT
|
||||
if ((ret = random_bank_test()) != 0)
|
||||
TEST_FAIL("RNGBANK test failed!\n", ret);
|
||||
else
|
||||
TEST_PASS("RNGBANK test passed!\n");
|
||||
#endif
|
||||
#endif /* WC_NO_RNG */
|
||||
|
||||
#ifdef WOLFSSL_SHAKE128
|
||||
@@ -20133,7 +20145,338 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_test(void)
|
||||
}
|
||||
|
||||
#endif /* !HAVE_HASHDRBG || CUSTOM_RAND_GENERATE_BLOCK || HAVE_INTEL_RDRAND */
|
||||
#endif /* WC_NO_RNG */
|
||||
|
||||
#ifdef WC_RNG_BANK_SUPPORT
|
||||
|
||||
static char *rng_bank_affinity_lock_lock;
|
||||
static int rng_bank_affinity_lock(void *arg) {
|
||||
rng_bank_affinity_lock_lock = (char *)arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rng_bank_affinity_get_id_id;
|
||||
static int rng_bank_affinity_get_id(void *arg, int *id) {
|
||||
if (rng_bank_affinity_lock_lock != (char *)arg)
|
||||
return BAD_STATE_E;
|
||||
rng_bank_affinity_lock_lock = (char *)arg + 1;
|
||||
*id = rng_bank_affinity_get_id_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rng_bank_affinity_unlock(void *arg) {
|
||||
rng_bank_affinity_lock_lock = (char *)arg + 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void)
|
||||
{
|
||||
|
||||
int ret;
|
||||
WC_DECLARE_VAR(bank, struct wc_rng_bank, 1, HEAP_HINT);
|
||||
struct wc_rng_bank_inst *rng_inst = NULL;
|
||||
struct wc_rng_bank *bank2 = NULL;
|
||||
struct wc_rng_bank_inst *rng_inst2 = NULL;
|
||||
#ifdef WC_DRBG_BANKREF
|
||||
WC_RNG *rng = NULL, *rng2 = NULL;
|
||||
#endif
|
||||
static const char bank_arg[] = "hi";
|
||||
byte outbuf1[16], outbuf2[16];
|
||||
int i;
|
||||
|
||||
WC_ALLOC_VAR_EX(bank, struct wc_rng_bank, 1, HEAP_HINT,
|
||||
DYNAMIC_TYPE_TMP_BUFFER,
|
||||
return WC_TEST_RET_ENC_EC(MEMORY_E));
|
||||
XMEMSET(bank, 0, sizeof(*bank));
|
||||
|
||||
ret = wc_rng_bank_init(NULL, 4, WC_RNG_BANK_FLAG_CAN_WAIT, 10, HEAP_HINT, INVALID_DEVID);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
ret = wc_rng_bank_init(bank, 4, WC_RNG_BANK_FLAG_CAN_WAIT, 10, HEAP_HINT, INVALID_DEVID);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
ret = wc_rng_bank_set_affinity_handlers(
|
||||
bank,
|
||||
rng_bank_affinity_lock,
|
||||
rng_bank_affinity_get_id,
|
||||
rng_bank_affinity_unlock,
|
||||
(char *)bank_arg);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
ret = wc_rng_bank_new(&bank2, 4, WC_RNG_BANK_FLAG_NO_VECTOR_OPS, 10, HEAP_HINT, INVALID_DEVID);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
ret = wc_rng_bank_set_affinity_handlers(
|
||||
bank2,
|
||||
rng_bank_affinity_lock,
|
||||
rng_bank_affinity_get_id,
|
||||
rng_bank_affinity_unlock,
|
||||
(char *)bank_arg);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
rng_bank_affinity_get_id_id = 4;
|
||||
ret = wc_rng_bank_checkout(bank2, &rng_inst2, -1, 10, WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST | WC_RNG_BANK_FLAG_AFFINITY_LOCK);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_INDEX_E))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
rng_bank_affinity_get_id_id = 2;
|
||||
ret = wc_rng_bank_checkout(bank2, &rng_inst2, -1, 10, WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST | WC_RNG_BANK_FLAG_AFFINITY_LOCK);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
if (rng_inst2 != bank2->rngs + 2)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (rng_bank_affinity_lock_lock != bank_arg + 1)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
|
||||
/* if we can, confirm that WC_RNG_BANK_FLAG_NO_VECTOR_OPS worked. */
|
||||
#if defined(WC_HAVE_VECTOR_SPEEDUPS) && \
|
||||
defined(WOLFSSL_KERNEL_MODE) && \
|
||||
defined(WC_C_DYNAMIC_FALLBACK) && \
|
||||
defined(HAVE_HASHDRBG) && \
|
||||
defined(WC_NO_INTERNAL_FUNCTION_POINTERS)
|
||||
if (((struct DRBG_internal *)rng_inst2->rng.drbg)->sha256.sha_method != 7 /* SHA256_C */)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_I(((struct DRBG_internal *)rng_inst2->rng.drbg)->sha256.sha_method), out);
|
||||
#endif
|
||||
|
||||
ret = wc_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(rng_inst2), outbuf1, sizeof(outbuf1));
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
ret = wc_rng_bank_checkin(bank2, &rng_inst2);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
if (rng_inst2 != NULL)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (rng_bank_affinity_lock_lock != bank_arg + 2)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
|
||||
ret = wc_rng_bank_checkout(bank2, &rng_inst2, 3, 10, WC_RNG_BANK_FLAG_NONE);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
if (rng_inst2 != bank2->rngs + 3)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
ret = wc_rng_bank_checkin(bank2, &rng_inst2);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
rng_bank_affinity_get_id_id = 3;
|
||||
ret = wc_rng_bank_checkout(bank2, &rng_inst2, -1, 10, WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST | WC_RNG_BANK_FLAG_AFFINITY_LOCK);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
if (rng_inst2 != bank2->rngs + 3)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
|
||||
ret = wc_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(rng_inst2), outbuf2, sizeof(outbuf2));
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
ret = wc_rng_bank_checkin(bank2, &rng_inst2);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
if (rng_inst2 != NULL)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
|
||||
if (XMEMCMP(outbuf1, outbuf2, sizeof(outbuf1)) == 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
|
||||
#ifdef WC_DRBG_BANKREF
|
||||
ret = wc_rng_new_bankref(bank2, &rng2);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
rng_bank_affinity_get_id_id = 1;
|
||||
ret = wc_RNG_GenerateBlock(rng2, outbuf1, sizeof(outbuf1));
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
if (XMEMCMP(outbuf1, outbuf2, sizeof(outbuf1)) == 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
#endif
|
||||
|
||||
ret = wc_rng_bank_reseed(bank2, 10, WC_RNG_BANK_FLAG_NONE);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
for (i = 0; i < bank2->n_rngs; ++i) {
|
||||
if (((struct DRBG_internal *)bank2->rngs[i].rng.drbg)
|
||||
->reseedCtr != WC_RESEED_INTERVAL)
|
||||
{
|
||||
ERROR_OUT(WC_TEST_RET_ENC_I(i), out);
|
||||
}
|
||||
}
|
||||
|
||||
rng_bank_affinity_get_id_id = 0;
|
||||
/* WC_RNG_BANK_FLAG_CAN_WAIT needed to avoiding warning message that the
|
||||
* instance needs reseed.
|
||||
*/
|
||||
ret = wc_rng_bank_checkout(bank2, &rng_inst2, -1, 10, WC_RNG_BANK_FLAG_CAN_WAIT | WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST | WC_RNG_BANK_FLAG_AFFINITY_LOCK);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
ret = wc_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(rng_inst2), outbuf1, sizeof(outbuf1));
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
ret = wc_rng_bank_checkin(bank2, &rng_inst2);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
rng_bank_affinity_get_id_id = 1;
|
||||
ret = wc_rng_bank_checkout(bank2, &rng_inst2, -1, 10, WC_RNG_BANK_FLAG_CAN_WAIT | WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST | WC_RNG_BANK_FLAG_AFFINITY_LOCK);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
ret = wc_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(rng_inst2), outbuf2, sizeof(outbuf2));
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
ret = wc_rng_bank_checkin(bank2, &rng_inst2);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
if (XMEMCMP(outbuf1, outbuf2, sizeof(outbuf1)) == 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
|
||||
#ifdef WC_DRBG_BANKREF
|
||||
if (wolfSSL_RefCur(bank2->refcount) != 2)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
|
||||
ret = wc_rng_bank_free(&bank2);
|
||||
if (ret != WC_NO_ERR_TRACE(BUSY_E))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
|
||||
wc_rng_free(rng2);
|
||||
rng2 = NULL;
|
||||
|
||||
if (wolfSSL_RefCur(bank2->refcount) != 1)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
#endif
|
||||
|
||||
ret = wc_rng_bank_free(&bank2);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
if (bank2 != NULL)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
|
||||
rng_bank_affinity_get_id_id = 0;
|
||||
|
||||
ret = wc_rng_bank_checkout(bank, &rng_inst, -1, 10, WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST | WC_RNG_BANK_FLAG_AFFINITY_LOCK);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
ret = wc_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(rng_inst), outbuf1, sizeof(outbuf1));
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
/* can't wc_rng_bank_seed() with _FLAG_CAN_WAIT while holding an inst --
|
||||
* deadlocks then times out.
|
||||
*/
|
||||
ret = wc_rng_bank_checkin(bank, &rng_inst);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
ret = wc_rng_bank_seed(bank, (byte *)bank_arg, (word32)sizeof(bank_arg), 10, WC_RNG_BANK_FLAG_CAN_WAIT);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
ret = wc_rng_bank_checkout(bank, &rng_inst, -1, 10, WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST | WC_RNG_BANK_FLAG_AFFINITY_LOCK);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
ret = wc_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(rng_inst), outbuf2, sizeof(outbuf2));
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
if (XMEMCMP(outbuf1, outbuf2, sizeof(outbuf1)) == 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
|
||||
ret = wc_rng_bank_checkin(bank, &rng_inst);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
ret = wc_rng_bank_seed(bank, (byte *)bank_arg, (word32)sizeof(bank_arg), 10, WC_RNG_BANK_FLAG_CAN_WAIT);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
ret = wc_rng_bank_checkout(bank, &rng_inst, -1, 10, WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST | WC_RNG_BANK_FLAG_AFFINITY_LOCK);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
ret = wc_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(rng_inst), outbuf1, sizeof(outbuf1));
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
/* even though we passed in the same seed, the state is different, because
|
||||
* Hash_DRBG_Reseed() chains in the previous state, and also churns in the
|
||||
* "type" only on reseed.
|
||||
*/
|
||||
if (XMEMCMP(outbuf1, outbuf2, sizeof(outbuf1)) == 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
|
||||
ret = wc_rng_bank_inst_reinit(bank, rng_inst, 10, WC_RNG_BANK_FLAG_CAN_WAIT);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
ret = wc_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(rng_inst), outbuf1, sizeof(outbuf1));
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
if (XMEMCMP(outbuf1, outbuf2, sizeof(outbuf1)) == 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
|
||||
ret = wc_rng_bank_checkin(bank, &rng_inst);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
out:
|
||||
|
||||
{
|
||||
int cleanup_ret;
|
||||
|
||||
#ifdef WC_DRBG_BANKREF
|
||||
if (rng) {
|
||||
cleanup_ret = wc_FreeRng(rng);
|
||||
if ((cleanup_ret != 0) && (ret == 0))
|
||||
ret = WC_TEST_RET_ENC_EC(cleanup_ret);
|
||||
}
|
||||
if (rng2) {
|
||||
cleanup_ret = wc_FreeRng(rng2);
|
||||
if ((cleanup_ret != 0) && (ret == 0))
|
||||
ret = WC_TEST_RET_ENC_EC(cleanup_ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rng_inst) {
|
||||
cleanup_ret = wc_rng_bank_checkin(bank, &rng_inst);
|
||||
if ((cleanup_ret != 0) && (ret == 0))
|
||||
ret = WC_TEST_RET_ENC_EC(cleanup_ret);
|
||||
if ((rng_inst != NULL) && (ret == 0))
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
}
|
||||
if (rng_inst2) {
|
||||
cleanup_ret = wc_rng_bank_checkin(bank2, &rng_inst2);
|
||||
if ((cleanup_ret != 0) && (ret == 0))
|
||||
ret = WC_TEST_RET_ENC_EC(cleanup_ret);
|
||||
if ((rng_inst2 != NULL) && (ret == 0))
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
}
|
||||
cleanup_ret = wc_rng_bank_fini(bank);
|
||||
if ((cleanup_ret != 0) && (ret == 0))
|
||||
ret = WC_TEST_RET_ENC_EC(cleanup_ret);
|
||||
WC_FREE_VAR_EX(bank, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
cleanup_ret = wc_rng_bank_free(&bank2);
|
||||
if ((cleanup_ret != 0) && (ret == 0))
|
||||
ret = WC_TEST_RET_ENC_EC(cleanup_ret);
|
||||
if ((bank2 != NULL) && (ret == 0))
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* WC_RNG_BANK_SUPPORT */
|
||||
|
||||
#endif /* !WC_NO_RNG */
|
||||
|
||||
#ifndef MEM_TEST_SZ
|
||||
#define MEM_TEST_SZ 1024
|
||||
@@ -31983,7 +32326,7 @@ static wc_test_ret_t ecc_test_deterministic_k(WC_RNG* rng)
|
||||
#endif
|
||||
|
||||
WC_ALLOC_VAR_EX(key, ecc_key, 1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER,
|
||||
return MEMORY_E);
|
||||
return WC_TEST_RET_ENC_EC(MEMORY_E));
|
||||
|
||||
ret = wc_ecc_init_ex(key, HEAP_HINT, devId);
|
||||
if (ret != 0)
|
||||
|
||||
@@ -186,7 +186,7 @@ struct WC_ASYNC_DEV;
|
||||
|
||||
typedef struct WC_ASYNC_SW {
|
||||
void* ctx;
|
||||
#if HAVE_ANONYMOUS_INLINE_AGGREGATES
|
||||
#ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES
|
||||
union {
|
||||
#endif
|
||||
#ifdef HAVE_ECC
|
||||
@@ -211,7 +211,7 @@ struct WC_ASYNC_DEV;
|
||||
#ifndef NO_DES3
|
||||
struct AsyncCryptSwDes des;
|
||||
#endif /* !NO_DES3 */
|
||||
#if HAVE_ANONYMOUS_INLINE_AGGREGATES
|
||||
#ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES
|
||||
}; /* union */
|
||||
#endif
|
||||
byte type; /* enum WC_ASYNC_SW_TYPE */
|
||||
|
||||
@@ -309,9 +309,11 @@ enum wolfCrypt_ErrorCodes {
|
||||
INTERRUPTED_E = -1004, /* Process interrupted */
|
||||
MLKEM_PUB_HASH_E = -1005, /* Encoded public key in decapsulation key does
|
||||
* not match stored hash*/
|
||||
BUSY_E = -1006, /* Object is busy */
|
||||
ALREADY_E = -1007, /* Operation was redundant or preempted */
|
||||
|
||||
WC_SPAN2_LAST_E = -1005, /* Update to indicate last used error code */
|
||||
WC_LAST_E = -1005, /* the last code used either here or in
|
||||
WC_SPAN2_LAST_E = -1007, /* Update to indicate last used error code */
|
||||
WC_LAST_E = -1007, /* the last code used either here or in
|
||||
* error-ssl.h */
|
||||
|
||||
WC_SPAN2_MIN_CODE_E = -1999, /* Last usable code in span 2 */
|
||||
|
||||
@@ -48,6 +48,7 @@ nobase_include_HEADERS+= \
|
||||
wolfssl/wolfcrypt/chacha20_poly1305.h \
|
||||
wolfssl/wolfcrypt/random.h \
|
||||
wolfssl/wolfcrypt/wolfentropy.h \
|
||||
wolfssl/wolfcrypt/rng_bank.h \
|
||||
wolfssl/wolfcrypt/ripemd.h \
|
||||
wolfssl/wolfcrypt/rsa.h \
|
||||
wolfssl/wolfcrypt/rc2.h \
|
||||
|
||||
@@ -247,12 +247,6 @@ struct OS_Seed {
|
||||
|
||||
#define RNG_HEALTH_TEST_CHECK_SIZE (WC_SHA256_DIGEST_SIZE * 4)
|
||||
|
||||
/* RNG health states */
|
||||
#define WC_DRBG_NOT_INIT 0
|
||||
#define WC_DRBG_OK 1
|
||||
#define WC_DRBG_FAILED 2
|
||||
#define WC_DRBG_CONT_FAILED 3
|
||||
|
||||
struct DRBG_internal {
|
||||
#ifdef WORD64_AVAILABLE
|
||||
word64 reseedCtr;
|
||||
@@ -271,26 +265,57 @@ struct DRBG_internal {
|
||||
byte digest_scratch[WC_SHA256_DIGEST_SIZE];
|
||||
#endif
|
||||
};
|
||||
#endif /* HAVE_HASHDRBG */
|
||||
|
||||
/* RNG health states */
|
||||
#define WC_DRBG_NOT_INIT 0
|
||||
#define WC_DRBG_OK 1
|
||||
#define WC_DRBG_FAILED 2
|
||||
#define WC_DRBG_CONT_FAILED 3
|
||||
#ifdef WC_RNG_BANK_SUPPORT
|
||||
#define WC_DRBG_BANKREF 4 /* Marks the WC_RNG as a ref to a wc_rng_bank,
|
||||
* with no usable DRBG of its own.
|
||||
*/
|
||||
#endif
|
||||
|
||||
/* RNG context */
|
||||
struct WC_RNG {
|
||||
struct OS_Seed seed;
|
||||
void* heap;
|
||||
#ifdef HAVE_HASHDRBG
|
||||
/* Hash-based Deterministic Random Bit Generator */
|
||||
struct DRBG* drbg;
|
||||
#if defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY)
|
||||
struct DRBG_internal drbg_data;
|
||||
#endif
|
||||
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
||||
/* Scratch buffer slots -- everything is preallocated by _InitRng(). */
|
||||
struct DRBG_internal *drbg_scratch;
|
||||
byte *health_check_scratch;
|
||||
byte *newSeed_buf;
|
||||
#endif
|
||||
byte status;
|
||||
#endif /* HAVE_HASHDRBG */
|
||||
|
||||
#ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES
|
||||
union {
|
||||
#endif
|
||||
|
||||
#ifdef WC_RNG_BANK_SUPPORT
|
||||
struct wc_rng_bank *bankref;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_HASHDRBG
|
||||
#ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES
|
||||
struct {
|
||||
#endif
|
||||
/* Hash-based Deterministic Random Bit Generator */
|
||||
struct DRBG* drbg;
|
||||
#if defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY)
|
||||
struct DRBG_internal drbg_data;
|
||||
#endif
|
||||
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
||||
/* Scratch buffers -- all preallocated by _InitRng(). */
|
||||
struct DRBG_internal *drbg_scratch;
|
||||
byte *health_check_scratch;
|
||||
byte *newSeed_buf;
|
||||
#endif
|
||||
#ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES
|
||||
};
|
||||
#endif
|
||||
#endif /* HAVE_HASHDRBG */
|
||||
|
||||
#ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID)
|
||||
pid_t pid;
|
||||
#endif
|
||||
|
||||
145
wolfssl/wolfcrypt/rng_bank.h
Normal file
145
wolfssl/wolfcrypt/rng_bank.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/* rng_bank.h
|
||||
*
|
||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
/*!
|
||||
\file wolfssl/wolfcrypt/rng_bank.h
|
||||
*/
|
||||
|
||||
/* This facility allocates and manages a bank of persistent RNGs with thread
|
||||
* safety and provisions for automatic affinity. It is typically used in kernel
|
||||
* applications.
|
||||
*/
|
||||
|
||||
#ifndef WOLF_CRYPT_RNG_BANK_H
|
||||
#define WOLF_CRYPT_RNG_BANK_H
|
||||
|
||||
#include <wolfssl/wolfcrypt/types.h>
|
||||
|
||||
#ifdef WC_RNG_BANK_SUPPORT
|
||||
|
||||
#ifdef WC_NO_RNG
|
||||
#error WC_RNG_BANK_SUPPORT requires RNG support.
|
||||
#endif
|
||||
|
||||
#define WC_RNG_BANK_FLAG_NONE 0
|
||||
#define WC_RNG_BANK_FLAG_INITED (1<<0)
|
||||
#define WC_RNG_BANK_FLAG_CAN_FAIL_OVER_INST (1<<1)
|
||||
#define WC_RNG_BANK_FLAG_CAN_WAIT (1<<2)
|
||||
#define WC_RNG_BANK_FLAG_NO_VECTOR_OPS (1<<3)
|
||||
#define WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST (1<<4)
|
||||
#define WC_RNG_BANK_FLAG_AFFINITY_LOCK (1<<5)
|
||||
|
||||
#define WC_RNG_BANK_INST_LOCK_FREE 0
|
||||
#define WC_RNG_BANK_INST_LOCK_HELD (1<<0)
|
||||
#define WC_RNG_BANK_INST_LOCK_AFFINITY_LOCKED (1<<1)
|
||||
#define WC_RNG_BANK_INST_LOCK_VEC_OPS_INH (1<<2)
|
||||
|
||||
typedef int (*wc_affinity_lock_fn_t)(void *arg);
|
||||
typedef int (*wc_affinity_get_id_fn_t)(void *arg, int *id);
|
||||
typedef int (*wc_affinity_unlock_fn_t)(void *arg);
|
||||
|
||||
struct wc_rng_bank_inst {
|
||||
wolfSSL_Atomic_Int lock;
|
||||
WC_RNG rng;
|
||||
};
|
||||
|
||||
struct wc_rng_bank {
|
||||
wolfSSL_Ref refcount;
|
||||
void *heap;
|
||||
word32 flags;
|
||||
wc_affinity_lock_fn_t affinity_lock_cb;
|
||||
wc_affinity_get_id_fn_t affinity_get_id_cb;
|
||||
wc_affinity_unlock_fn_t affinity_unlock_cb;
|
||||
void *cb_arg; /* if mutable, caller is responsible for thread safety. */
|
||||
int n_rngs;
|
||||
struct wc_rng_bank_inst *rngs; /* typically one per CPU ID, plus a few */
|
||||
};
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_new(
|
||||
struct wc_rng_bank **ctx,
|
||||
int n_rngs,
|
||||
word32 flags,
|
||||
int timeout_secs,
|
||||
void *heap,
|
||||
int devId);
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_init(
|
||||
struct wc_rng_bank *ctx,
|
||||
int n_rngs,
|
||||
word32 flags,
|
||||
int timeout_secs,
|
||||
void *heap,
|
||||
int devId);
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_set_affinity_handlers(
|
||||
struct wc_rng_bank *ctx,
|
||||
wc_affinity_lock_fn_t affinity_lock_cb,
|
||||
wc_affinity_get_id_fn_t affinity_get_id_cb,
|
||||
wc_affinity_unlock_fn_t affinity_unlock_cb,
|
||||
void *cb_arg);
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_fini(struct wc_rng_bank *ctx);
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_free(struct wc_rng_bank **ctx);
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_checkout(
|
||||
struct wc_rng_bank *bank,
|
||||
struct wc_rng_bank_inst **rng_inst,
|
||||
int preferred_inst_offset,
|
||||
int timeout_secs,
|
||||
word32 flags);
|
||||
|
||||
WOLFSSL_LOCAL int wc_local_rng_bank_checkout_for_bankref(
|
||||
struct wc_rng_bank *bank,
|
||||
struct wc_rng_bank_inst **rng_inst);
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_checkin(
|
||||
struct wc_rng_bank *bank,
|
||||
struct wc_rng_bank_inst **rng_inst);
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_inst_reinit(
|
||||
struct wc_rng_bank *bank,
|
||||
struct wc_rng_bank_inst *rng_inst,
|
||||
int timeout_secs,
|
||||
word32 flags);
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_seed(struct wc_rng_bank *bank,
|
||||
const byte* seed, word32 seedSz,
|
||||
int timeout_secs,
|
||||
word32 flags);
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_reseed(struct wc_rng_bank *bank,
|
||||
int timeout_secs,
|
||||
word32 flags);
|
||||
|
||||
#ifdef WC_DRBG_BANKREF
|
||||
WOLFSSL_API int wc_InitRng_BankRef(struct wc_rng_bank *bank, WC_RNG *rng);
|
||||
|
||||
WOLFSSL_API int wc_BankRef_Release(WC_RNG *rng);
|
||||
|
||||
WOLFSSL_API int wc_rng_new_bankref(struct wc_rng_bank *bank, WC_RNG **rng);
|
||||
#endif /* WC_DRBG_BANKREF */
|
||||
|
||||
#define WC_RNG_BANK_INST_TO_RNG(rng_inst) (&(rng_inst)->rng)
|
||||
|
||||
#endif /* WC_RNG_BANK_SUPPORT */
|
||||
|
||||
#endif /* WOLF_CRYPT_RNG_BANK_H */
|
||||
@@ -431,6 +431,8 @@
|
||||
(WOLFSSL_FIPS_VERSION2_CODE >= WOLFSSL_MAKE_FIPS_VERSION(major,minor))
|
||||
#define FIPS_VERSION_GT(major,minor) \
|
||||
(WOLFSSL_FIPS_VERSION2_CODE > WOLFSSL_MAKE_FIPS_VERSION(major,minor))
|
||||
#define FIPS_VERSION_NE(major,minor) \
|
||||
(WOLFSSL_FIPS_VERSION2_CODE != WOLFSSL_MAKE_FIPS_VERSION(major,minor))
|
||||
|
||||
#define FIPS_VERSION3_LT(major,minor,patch) \
|
||||
(WOLFSSL_FIPS_VERSION_CODE < WOLFSSL_MAKE_FIPS_VERSION3(major,minor,patch))
|
||||
@@ -3680,9 +3682,6 @@ extern void uITRON4_free(void *p) ;
|
||||
#ifndef WOLFSSL_KERNEL_MODE
|
||||
#define WOLFSSL_KERNEL_MODE
|
||||
#endif
|
||||
#ifndef WOLFSSL_API_PREFIX_MAP
|
||||
#define WOLFSSL_API_PREFIX_MAP
|
||||
#endif
|
||||
#if defined(WOLFSSL_LINUXKM_VERBOSE_DEBUG) && \
|
||||
!defined(WOLFSSL_KERNEL_VERBOSE_DEBUG)
|
||||
#define WOLFSSL_KERNEL_VERBOSE_DEBUG
|
||||
@@ -3715,21 +3714,11 @@ extern void uITRON4_free(void *p) ;
|
||||
#ifndef USE_WOLF_STRTOK
|
||||
#define USE_WOLF_STRTOK
|
||||
#endif
|
||||
#ifndef WOLFSSL_OLD_PRIME_CHECK
|
||||
#define WOLFSSL_OLD_PRIME_CHECK
|
||||
#endif
|
||||
#ifdef LINUXKM_LKCAPI_REGISTER
|
||||
#ifndef WC_TEST_EXPORT_SUBTESTS
|
||||
#define WC_TEST_EXPORT_SUBTESTS
|
||||
#endif
|
||||
#endif
|
||||
#ifndef WOLFSSL_TEST_SUBROUTINE
|
||||
#ifdef WC_TEST_EXPORT_SUBTESTS
|
||||
#define WOLFSSL_TEST_SUBROUTINE
|
||||
#else
|
||||
#define WOLFSSL_TEST_SUBROUTINE static
|
||||
#endif
|
||||
#endif
|
||||
#undef HAVE_PTHREAD
|
||||
/* linuxkm uses linux/string.h, included by linuxkm_wc_port.h. */
|
||||
#undef HAVE_STRINGS_H
|
||||
@@ -3790,21 +3779,6 @@ extern void uITRON4_free(void *p) ;
|
||||
#undef HAVE_PUBLIC_FFDHE
|
||||
#endif
|
||||
|
||||
#ifndef NO_OLD_WC_NAMES
|
||||
#define NO_OLD_WC_NAMES
|
||||
#endif
|
||||
#ifndef NO_OLD_SHA_NAMES
|
||||
#define NO_OLD_SHA_NAMES
|
||||
#endif
|
||||
#ifndef NO_OLD_MD5_NAME
|
||||
#define NO_OLD_MD5_NAME
|
||||
#endif
|
||||
#ifndef OPENSSL_COEXIST
|
||||
#define OPENSSL_COEXIST
|
||||
#endif
|
||||
#ifndef NO_OLD_SSL_NAMES
|
||||
#define NO_OLD_SSL_NAMES
|
||||
#endif
|
||||
#undef WOLFSSL_MIN_AUTH_TAG_SZ
|
||||
#define WOLFSSL_MIN_AUTH_TAG_SZ 4
|
||||
|
||||
@@ -3814,22 +3788,10 @@ extern void uITRON4_free(void *p) ;
|
||||
*/
|
||||
#define WOLFSSL_ASN_INT_LEAD_0_ANY
|
||||
#endif
|
||||
|
||||
#if !defined(WC_RESEED_INTERVAL) && defined(LINUXKM_LKCAPI_REGISTER)
|
||||
/* If installing handlers, use the maximum reseed interval allowed by
|
||||
* NIST SP 800-90A Rev. 1, to avoid unnecessary delays in DRBG
|
||||
* generation.
|
||||
*/
|
||||
#if defined(HAVE_FIPS) && FIPS_VERSION_LT(6,0)
|
||||
#define WC_RESEED_INTERVAL UINT_MAX
|
||||
#else
|
||||
#define WC_RESEED_INTERVAL (((word64)1UL)<<48UL)
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__aarch64__) && !defined(WOLFSSL_AARCH64_PRIVILEGE_MODE)
|
||||
#define WOLFSSL_AARCH64_PRIVILEGE_MODE
|
||||
#endif
|
||||
#endif
|
||||
#endif /* WOLFSSL_LINUXKM */
|
||||
|
||||
/* FreeBSD Kernel Module */
|
||||
#ifdef WOLFSSL_BSDKM
|
||||
@@ -3869,16 +3831,6 @@ extern void uITRON4_free(void *p) ;
|
||||
#ifndef USE_WOLF_STRTOK
|
||||
#define USE_WOLF_STRTOK
|
||||
#endif
|
||||
#ifndef WOLFSSL_OLD_PRIME_CHECK
|
||||
#define WOLFSSL_OLD_PRIME_CHECK
|
||||
#endif
|
||||
#ifndef WOLFSSL_TEST_SUBROUTINE
|
||||
#ifndef NO_CRYPT_TEST
|
||||
#define WOLFSSL_TEST_SUBROUTINE
|
||||
#else
|
||||
#define WOLFSSL_TEST_SUBROUTINE static
|
||||
#endif
|
||||
#endif
|
||||
/* bsdkm uses kernel headers, included in bsdkm_wc_port.h. */
|
||||
#undef HAVE_PTHREAD
|
||||
#undef HAVE_STRINGS_H
|
||||
@@ -3909,6 +3861,19 @@ extern void uITRON4_free(void *p) ;
|
||||
#define WOLFSSL_SP_DIV_WORD_HALF
|
||||
#endif
|
||||
|
||||
/* FreeBSD kernel defines its own min, max functions in sys/libkern.h */
|
||||
#undef WOLFSSL_HAVE_MIN
|
||||
#define WOLFSSL_HAVE_MIN
|
||||
|
||||
#undef WOLFSSL_HAVE_MAX
|
||||
#define WOLFSSL_HAVE_MAX
|
||||
#endif /* WOLFSSL_BSDKM */
|
||||
|
||||
/* Common setup for kernel mode builds */
|
||||
#ifdef WOLFSSL_KERNEL_MODE
|
||||
#ifndef WOLFSSL_API_PREFIX_MAP
|
||||
#define WOLFSSL_API_PREFIX_MAP
|
||||
#endif
|
||||
#ifndef NO_OLD_WC_NAMES
|
||||
#define NO_OLD_WC_NAMES
|
||||
#endif
|
||||
@@ -3925,18 +3890,36 @@ extern void uITRON4_free(void *p) ;
|
||||
#define NO_OLD_SSL_NAMES
|
||||
#endif
|
||||
|
||||
/* FreeBSD kernel defines its own min, max functions in sys/libkern.h */
|
||||
#undef WOLFSSL_HAVE_MIN
|
||||
#define WOLFSSL_HAVE_MIN
|
||||
#ifndef WOLFSSL_TEST_SUBROUTINE
|
||||
#ifdef WC_TEST_EXPORT_SUBTESTS
|
||||
#define WOLFSSL_TEST_SUBROUTINE
|
||||
#else
|
||||
#define WOLFSSL_TEST_SUBROUTINE static
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#undef WOLFSSL_HAVE_MAX
|
||||
#define WOLFSSL_HAVE_MAX
|
||||
#endif
|
||||
#if !defined(WOLFSSL_OLD_PRIME_CHECK) && \
|
||||
!defined(WOLFSSL_NEW_PRIME_CHECK) && !defined(HAVE_FIPS)
|
||||
#define WOLFSSL_OLD_PRIME_CHECK
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_KERNEL_MODE) && !defined(WC_NO_VERBOSE_RNG) && \
|
||||
!defined(WC_VERBOSE_RNG)
|
||||
#define WC_VERBOSE_RNG
|
||||
#endif
|
||||
#ifndef WC_RESEED_INTERVAL
|
||||
/* In kernel mode, use the maximum reseed interval allowed by
|
||||
* NIST SP 800-90A Rev. 1, to avoid unnecessary delays in DRBG
|
||||
* generation.
|
||||
*/
|
||||
#if defined(HAVE_FIPS) && \
|
||||
FIPS_VERSION_LT(6,0) && FIPS_VERSION3_NE(5,2,4)
|
||||
#define WC_RESEED_INTERVAL UINT_MAX
|
||||
#else
|
||||
#define WC_RESEED_INTERVAL (((word64)1UL)<<48UL)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(WC_NO_VERBOSE_RNG) && !defined(WC_VERBOSE_RNG)
|
||||
#define WC_VERBOSE_RNG
|
||||
#endif
|
||||
#endif /* WOLFSSL_KERNEL_MODE */
|
||||
|
||||
#if defined(WC_SYM_RELOC_TABLES) && defined(HAVE_FIPS) && \
|
||||
!defined(WC_PIE_RELOC_TABLES)
|
||||
|
||||
@@ -125,7 +125,7 @@ typedef const char wcchar[];
|
||||
/* if a version is available, pivot on the version, otherwise guess it's
|
||||
* disallowed, subject to override.
|
||||
*/
|
||||
#if !defined(WOLF_C89) && (!defined(__STDC__) \
|
||||
#if !defined(WOLF_C89) && !defined(_MSC_VER) && (!defined(__STDC__) \
|
||||
|| (!defined(__STDC_VERSION__) && !defined(__cplusplus)) \
|
||||
|| (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201101L)) \
|
||||
|| (defined(__cplusplus) && (__cplusplus >= 201103L)))
|
||||
|
||||
@@ -694,13 +694,15 @@ typedef struct wolfSSL_RefWithMutex {
|
||||
#endif
|
||||
int count;
|
||||
} wolfSSL_RefWithMutex;
|
||||
|
||||
#define wolfSSL_RefWithMutexCur(ref) ((ref).count)
|
||||
#if defined(WOLFSSL_ATOMIC_OPS) && !defined(SINGLE_THREADED)
|
||||
typedef struct wolfSSL_Ref {
|
||||
wolfSSL_Atomic_Int count;
|
||||
} wolfSSL_Ref;
|
||||
#define wolfSSL_RefCur(ref) WOLFSSL_ATOMIC_LOAD((ref).count)
|
||||
#else
|
||||
typedef struct wolfSSL_RefWithMutex wolfSSL_Ref;
|
||||
#define wolfSSL_RefCur(ref) wolfSSL_RefWithMutexCur(ref)
|
||||
#endif
|
||||
|
||||
#if defined(SINGLE_THREADED) || defined(WOLFSSL_ATOMIC_OPS)
|
||||
@@ -710,7 +712,10 @@ typedef struct wolfSSL_RefWithMutex wolfSSL_Ref;
|
||||
wolfSSL_Atomic_Int_Init(&(ref)->count, 1); \
|
||||
*(err) = 0; \
|
||||
} while(0)
|
||||
#define wolfSSL_RefFree(ref) WC_DO_NOTHING
|
||||
#define wolfSSL_RefFree(ref) \
|
||||
do { \
|
||||
wolfSSL_Atomic_Int_Init(&(ref)->count, 0); \
|
||||
} while(0)
|
||||
#define wolfSSL_RefInc(ref, err) \
|
||||
do { \
|
||||
(void)wolfSSL_Atomic_Int_FetchAdd(&(ref)->count, 1); \
|
||||
|
||||
Reference in New Issue
Block a user