mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-01-28 07:02:21 +01:00
move WC_RNG_BANK_SUPPORT implementation from wolfcrypt/src/random.c and wolfssl/wolfcrypt/random.h to new files wolfcrypt/src/rng_bank.c and wolfssl/wolfcrypt/rng_bank.h;
wolfcrypt/src/rng_bank.c: * add wc_local_rng_bank_checkout_for_bankref, wc_BankRef_Release(), wc_rng_bank_new(), and wc_rng_bank_free(); * in wc_rng_bank_checkin(), take a struct wc_rng_bank_inst **rng_inst and NULL it before return; * in wc_rng_bank_init(), add a devId arg, and handle devId in wc_rng_bank_inst_reinit(); * add WC_RNG_BANK_INST_LOCK_* and use them in wc_rng_bank_checkout() and wc_rng_bank_checkin(); * fix order of operations in wc_rng_bank_checkout() re DISABLE_VECTOR_REGISTERS(); wolfcrypt/src/random.c: * refactor per-instance salting for wc_rng_bank_inst: remove changes in Hash_df(), Hash_DRBG_Instantiate(), and _InitRng(), and in wc_rng_bank_init() and wc_rng_bank_inst_reinit(), use wc_InitRngNonce_ex() and pass the wc_rng_bank_inst pointer as the nonce; * simplify the WC_RNG_BANK_SUPPORT variant of wc_RNG_GenerateBlock() -- delegate to wc_local_rng_bank_checkout_for_bankref() and remove supplementary error checking; * in wc_FreeRng(), call wc_BankRef_Release() when WC_DRBG_BANKREF, and in wc_BankRef_Release(), fix refcount flub (not wolfSSL_RefFree, rather wolfSSL_RefDec); * streamline the WOLFSSL_LINUXKM wc_GenerateSeed(); wolfcrypt/test/test.c: add random_bank_test(); linuxkm/lkcapi_sha_glue.c: use WC_RNG_BANK_INST_TO_RNG() opportunistically; configure.ac: add --enable-amdrdseed as a synonym for --enable-amdrand; linuxkm/linuxkm_wc_port.h: when LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT, don't include get_random_bytes() in struct wolfssl_linuxkm_pie_redirect_table; add various comments for clarity.
This commit is contained in:
10
configure.ac
10
configure.ac
@@ -3998,12 +3998,17 @@ then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# AMD RDSEED
|
# AMD RDSEED
|
||||||
AC_ARG_ENABLE([amdrand],
|
AC_ARG_ENABLE([amdrdseed],
|
||||||
[AS_HELP_STRING([--enable-amdrand],[Enable AMD rdseed as preferred RNG seeding source (default: disabled)])],
|
[AS_HELP_STRING([--enable-amdrdseed],[Enable AMD rdseed as preferred RNG seeding source (default: disabled)])],
|
||||||
[ ENABLED_AMDRDSEED=$enableval ],
|
[ ENABLED_AMDRDSEED=$enableval ],
|
||||||
[ ENABLED_AMDRDSEED=no ]
|
[ 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"
|
if test "$ENABLED_AMDRDSEED" = "yes"
|
||||||
then
|
then
|
||||||
AM_CFLAGS="$AM_CFLAGS -DHAVE_AMD_RDSEED"
|
AM_CFLAGS="$AM_CFLAGS -DHAVE_AMD_RDSEED"
|
||||||
@@ -11093,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_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_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_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_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_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"])
|
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(kfree) *kfree;
|
||||||
typeof(ksize) *ksize;
|
typeof(ksize) *ksize;
|
||||||
|
|
||||||
|
#ifndef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
|
||||||
typeof(get_random_bytes) *get_random_bytes;
|
typeof(get_random_bytes) *get_random_bytes;
|
||||||
|
#endif
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
|
||||||
typeof(getnstimeofday) *getnstimeofday;
|
typeof(getnstimeofday) *getnstimeofday;
|
||||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
|
#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
|
||||||
@@ -1267,7 +1269,9 @@
|
|||||||
#endif
|
#endif
|
||||||
#define ksize WC_PIE_INDIRECT_SYM(ksize)
|
#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)
|
#define get_random_bytes WC_PIE_INDIRECT_SYM(get_random_bytes)
|
||||||
|
#endif
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
|
||||||
#define getnstimeofday WC_PIE_INDIRECT_SYM(getnstimeofday)
|
#define getnstimeofday WC_PIE_INDIRECT_SYM(getnstimeofday)
|
||||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
|
#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
|
||||||
|
|||||||
@@ -955,6 +955,7 @@ struct wc_swallow_the_semicolon
|
|||||||
#include <wolfssl/wolfcrypt/wolfentropy.h>
|
#include <wolfssl/wolfcrypt/wolfentropy.h>
|
||||||
#endif
|
#endif
|
||||||
#include <wolfssl/wolfcrypt/random.h>
|
#include <wolfssl/wolfcrypt/random.h>
|
||||||
|
#include <wolfssl/wolfcrypt/rng_bank.h>
|
||||||
|
|
||||||
static volatile int wc_linuxkm_drbg_init_tfm_disable_vector_registers = 0;
|
static volatile int wc_linuxkm_drbg_init_tfm_disable_vector_registers = 0;
|
||||||
|
|
||||||
@@ -1000,8 +1001,9 @@ static int wc_linuxkm_drbg_init_tfm(struct crypto_tfm *tfm)
|
|||||||
if (wc_linuxkm_drbg_init_tfm_disable_vector_registers)
|
if (wc_linuxkm_drbg_init_tfm_disable_vector_registers)
|
||||||
flags |= WC_RNG_BANK_FLAG_NO_VECTOR_OPS;
|
flags |= WC_RNG_BANK_FLAG_NO_VECTOR_OPS;
|
||||||
|
|
||||||
ret = wc_rng_bank_init(ctx, nr_cpu_ids + 4, flags,
|
ret = wc_rng_bank_init(
|
||||||
WC_LINUXKM_INITRNG_TIMEOUT_SEC, NULL /* heap */);
|
ctx, nr_cpu_ids + 4, flags, WC_LINUXKM_INITRNG_TIMEOUT_SEC,
|
||||||
|
NULL /* heap */, INVALID_DEVID);
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
ret = wc_rng_bank_set_affinity_handlers(
|
ret = wc_rng_bank_set_affinity_handlers(
|
||||||
@@ -1075,7 +1077,7 @@ static struct wc_rng_bank_inst *linuxkm_get_drbg(struct crypto_rng *tfm) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void linuxkm_put_drbg(struct crypto_rng *tfm, struct wc_rng_bank_inst *drbg) {
|
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);
|
struct wc_rng_bank *ctx = (struct wc_rng_bank *)crypto_rng_ctx(tfm);
|
||||||
int ret = wc_rng_bank_checkin(ctx, drbg);
|
int ret = wc_rng_bank_checkin(ctx, drbg);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
@@ -1114,6 +1116,10 @@ static inline struct crypto_rng *get_crypto_default_rng(void) {
|
|||||||
return current_crypto_default_rng;
|
return current_crypto_default_rng;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef WC_DRBG_BANKREF
|
||||||
|
#error LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT requires WC_DRBG_BANKREF support.
|
||||||
|
#endif
|
||||||
|
|
||||||
WC_MAYBE_UNUSED static int linuxkm_InitRng_DefaultRef(WC_RNG* rng) {
|
WC_MAYBE_UNUSED static int linuxkm_InitRng_DefaultRef(WC_RNG* rng) {
|
||||||
int ret;
|
int ret;
|
||||||
struct crypto_rng *current_crypto_default_rng = get_crypto_default_rng();
|
struct crypto_rng *current_crypto_default_rng = get_crypto_default_rng();
|
||||||
@@ -1146,7 +1152,7 @@ static int wc_linuxkm_drbg_generate(struct crypto_rng *tfm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (slen > 0) {
|
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) {
|
if (ret != 0) {
|
||||||
pr_warn_once("WARNING: wc_RNG_DRBG_Reseed returned %d\n",ret);
|
pr_warn_once("WARNING: wc_RNG_DRBG_Reseed returned %d\n",ret);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
@@ -1157,7 +1163,7 @@ static int wc_linuxkm_drbg_generate(struct crypto_rng *tfm,
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
#define RNG_MAX_BLOCK_LEN_ROUNDED (RNG_MAX_BLOCK_LEN & ~0xfU)
|
#define RNG_MAX_BLOCK_LEN_ROUNDED (RNG_MAX_BLOCK_LEN & ~0xfU)
|
||||||
if (dlen > RNG_MAX_BLOCK_LEN_ROUNDED) {
|
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) {
|
if (ret == 0) {
|
||||||
dlen -= RNG_MAX_BLOCK_LEN_ROUNDED;
|
dlen -= RNG_MAX_BLOCK_LEN_ROUNDED;
|
||||||
dst += RNG_MAX_BLOCK_LEN_ROUNDED;
|
dst += RNG_MAX_BLOCK_LEN_ROUNDED;
|
||||||
@@ -1165,7 +1171,7 @@ static int wc_linuxkm_drbg_generate(struct crypto_rng *tfm,
|
|||||||
}
|
}
|
||||||
#undef RNG_MAX_BLOCK_LEN_ROUNDED
|
#undef RNG_MAX_BLOCK_LEN_ROUNDED
|
||||||
else {
|
else {
|
||||||
ret = wc_RNG_GenerateBlock(&drbg->rng, dst, dlen);
|
ret = wc_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(drbg), dst, dlen);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
dlen = 0;
|
dlen = 0;
|
||||||
}
|
}
|
||||||
@@ -1206,7 +1212,7 @@ static int wc_linuxkm_drbg_generate(struct crypto_rng *tfm,
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
||||||
linuxkm_put_drbg(tfm, drbg);
|
linuxkm_put_drbg(tfm, &drbg);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1438,12 +1444,12 @@ static int wc_mix_pool_bytes(const void *buf, size_t len) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (i = 0, V_offset = 0; i < len; ++i) {
|
for (i = 0, V_offset = 0; i < len; ++i) {
|
||||||
((struct DRBG_internal *)drbg->rng.drbg)->V[V_offset++] += ((byte *)buf)[i];
|
((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 *)drbg->rng.drbg)->V)
|
if (V_offset == (int)sizeof ((struct DRBG_internal *)WC_RNG_BANK_INST_TO_RNG(drbg)->drbg)->V)
|
||||||
V_offset = 0;
|
V_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
wc_rng_bank_checkin(ctx, drbg);
|
wc_rng_bank_checkin(ctx, &drbg);
|
||||||
if (can_sleep) {
|
if (can_sleep) {
|
||||||
if (signal_pending(current))
|
if (signal_pending(current))
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
|
|||||||
@@ -66,6 +66,9 @@
|
|||||||
#include <wolfssl/wolfcrypt/wolfentropy.h>
|
#include <wolfssl/wolfcrypt/wolfentropy.h>
|
||||||
#endif
|
#endif
|
||||||
#include <wolfssl/wolfcrypt/random.h>
|
#include <wolfssl/wolfcrypt/random.h>
|
||||||
|
#ifdef WC_RNG_BANK_SUPPORT
|
||||||
|
#include <wolfssl/wolfcrypt/rng_bank.h>
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#include <wolfssl/wolfcrypt/coding.h>
|
#include <wolfssl/wolfcrypt/coding.h>
|
||||||
#include <wolfssl/wolfcrypt/signature.h>
|
#include <wolfssl/wolfcrypt/signature.h>
|
||||||
|
|||||||
@@ -1288,7 +1288,9 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) {
|
|||||||
wolfssl_linuxkm_pie_redirect_table.kvfree = kvfree;
|
wolfssl_linuxkm_pie_redirect_table.kvfree = kvfree;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
|
||||||
wolfssl_linuxkm_pie_redirect_table.get_random_bytes = get_random_bytes;
|
wolfssl_linuxkm_pie_redirect_table.get_random_bytes = get_random_bytes;
|
||||||
|
#endif
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
|
||||||
wolfssl_linuxkm_pie_redirect_table.getnstimeofday =
|
wolfssl_linuxkm_pie_redirect_table.getnstimeofday =
|
||||||
getnstimeofday;
|
getnstimeofday;
|
||||||
|
|||||||
@@ -185,6 +185,10 @@ if BUILD_MEMUSE
|
|||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wolfentropy.c
|
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wolfentropy.c
|
||||||
endif
|
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
|
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/kdf.c
|
||||||
|
|
||||||
if BUILD_RSA
|
if BUILD_RSA
|
||||||
@@ -434,6 +438,10 @@ if BUILD_MEMUSE
|
|||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wolfentropy.c
|
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wolfentropy.c
|
||||||
endif
|
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
|
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/kdf.c
|
||||||
|
|
||||||
if BUILD_RSA
|
if BUILD_RSA
|
||||||
@@ -789,6 +797,9 @@ src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/random.c
|
|||||||
if BUILD_MEMUSE
|
if BUILD_MEMUSE
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wolfentropy.c
|
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wolfentropy.c
|
||||||
endif
|
endif
|
||||||
|
if BUILD_RNG_BANK
|
||||||
|
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/rng_bank.c
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
endif !BUILD_FIPS_V2_PLUS
|
endif !BUILD_FIPS_V2_PLUS
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ This library contains implementation for the random number generator.
|
|||||||
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/random.h>
|
#include <wolfssl/wolfcrypt/random.h>
|
||||||
|
#ifdef WC_RNG_BANK_SUPPORT
|
||||||
|
#include <wolfssl/wolfcrypt/rng_bank.h>
|
||||||
|
#endif
|
||||||
#include <wolfssl/wolfcrypt/cpuid.h>
|
#include <wolfssl/wolfcrypt/cpuid.h>
|
||||||
|
|
||||||
#ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */
|
#ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */
|
||||||
@@ -345,12 +348,6 @@ static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type,
|
|||||||
if (inB != NULL && inBSz > 0)
|
if (inB != NULL && inBSz > 0)
|
||||||
ret = wc_Sha256Update(sha, inB, inBSz);
|
ret = wc_Sha256Update(sha, inB, inBSz);
|
||||||
}
|
}
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
|
||||||
if (ret == 0) {
|
|
||||||
if (drbg->saltSz > 0)
|
|
||||||
ret = wc_Sha256Update(sha, drbg->salt, drbg->saltSz);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
ret = wc_Sha256Final(sha, digest);
|
ret = wc_Sha256Final(sha, digest);
|
||||||
|
|
||||||
@@ -701,9 +698,6 @@ static int Hash_DRBG_Init(DRBG_internal* drbg, const byte* seed, word32 seedSz,
|
|||||||
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
|
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
|
||||||
static int Hash_DRBG_Instantiate(DRBG_internal* drbg, const byte* seed, word32 seedSz,
|
static int Hash_DRBG_Instantiate(DRBG_internal* drbg, const byte* seed, word32 seedSz,
|
||||||
const byte* nonce, word32 nonceSz,
|
const byte* nonce, word32 nonceSz,
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
|
||||||
const byte *salt, word32 saltSz,
|
|
||||||
#endif
|
|
||||||
void* heap, int devId)
|
void* heap, int devId)
|
||||||
{
|
{
|
||||||
int ret = DRBG_FAILURE;
|
int ret = DRBG_FAILURE;
|
||||||
@@ -716,16 +710,6 @@ static int Hash_DRBG_Instantiate(DRBG_internal* drbg, const byte* seed, word32 s
|
|||||||
(void)devId;
|
(void)devId;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
|
||||||
if ((salt == NULL) && (saltSz > 0))
|
|
||||||
return BAD_FUNC_ARG;
|
|
||||||
else if (saltSz > sizeof(drbg->salt))
|
|
||||||
return BAD_LENGTH_E;
|
|
||||||
XMEMSET(drbg->salt, 0, sizeof(drbg->salt));
|
|
||||||
if (saltSz > 0)
|
|
||||||
XMEMCPY(drbg->salt, salt, saltSz);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
||||||
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
|
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
|
||||||
ret = wc_InitSha256_ex(&drbg->sha256, drbg->heap, drbg->devId);
|
ret = wc_InitSha256_ex(&drbg->sha256, drbg->heap, drbg->devId);
|
||||||
@@ -787,9 +771,6 @@ int wc_RNG_TestSeed(const byte* seed, word32 seedSz)
|
|||||||
|
|
||||||
|
|
||||||
static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
|
static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
|
||||||
const byte* salt, word32 saltSz,
|
|
||||||
#endif
|
|
||||||
void* heap, int devId)
|
void* heap, int devId)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -928,11 +909,7 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
|
|||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
ret = Hash_DRBG_Instantiate((DRBG_internal *)rng->drbg_scratch,
|
ret = Hash_DRBG_Instantiate((DRBG_internal *)rng->drbg_scratch,
|
||||||
NULL /* seed */, 0, NULL /* nonce */, 0,
|
NULL /* seed */, 0, NULL /* nonce */, 0, rng->heap, devId);
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
|
||||||
salt, saltSz,
|
|
||||||
#endif
|
|
||||||
rng->heap, devId);
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
drbg_scratch_instantiated = 1;
|
drbg_scratch_instantiated = 1;
|
||||||
}
|
}
|
||||||
@@ -1034,11 +1011,7 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
|
|||||||
#else
|
#else
|
||||||
seed, seedSz,
|
seed, seedSz,
|
||||||
#endif
|
#endif
|
||||||
nonce, nonceSz,
|
nonce, nonceSz, rng->heap, devId);
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
|
||||||
salt, saltSz,
|
|
||||||
#endif
|
|
||||||
rng->heap, devId);
|
|
||||||
} /* ret == 0 */
|
} /* ret == 0 */
|
||||||
|
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
@@ -1128,11 +1101,7 @@ int wc_rng_new_ex(WC_RNG **rng, byte* nonce, word32 nonceSz,
|
|||||||
return MEMORY_E;
|
return MEMORY_E;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = _InitRng(*rng, nonce, nonceSz,
|
ret = _InitRng(*rng, nonce, nonceSz, heap, devId);
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
|
||||||
NULL /* salt */, 0,
|
|
||||||
#endif
|
|
||||||
heap, devId);
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
XFREE(*rng, heap, DYNAMIC_TYPE_RNG);
|
XFREE(*rng, heap, DYNAMIC_TYPE_RNG);
|
||||||
*rng = NULL;
|
*rng = NULL;
|
||||||
@@ -1158,42 +1127,26 @@ void wc_rng_free(WC_RNG* rng)
|
|||||||
WOLFSSL_ABI
|
WOLFSSL_ABI
|
||||||
int wc_InitRng(WC_RNG* rng)
|
int wc_InitRng(WC_RNG* rng)
|
||||||
{
|
{
|
||||||
return _InitRng(rng, NULL, 0,
|
return _InitRng(rng, NULL, 0, NULL, INVALID_DEVID);
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
|
||||||
NULL, 0,
|
|
||||||
#endif
|
|
||||||
NULL, INVALID_DEVID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId)
|
int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId)
|
||||||
{
|
{
|
||||||
return _InitRng(rng, NULL, 0,
|
return _InitRng(rng, NULL, 0, heap, devId);
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
|
||||||
NULL, 0,
|
|
||||||
#endif
|
|
||||||
heap, devId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wc_InitRngNonce(WC_RNG* rng, byte* nonce, word32 nonceSz)
|
int wc_InitRngNonce(WC_RNG* rng, byte* nonce, word32 nonceSz)
|
||||||
{
|
{
|
||||||
return _InitRng(rng, nonce, nonceSz,
|
return _InitRng(rng, nonce, nonceSz, NULL, INVALID_DEVID);
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
|
||||||
NULL, 0,
|
|
||||||
#endif
|
|
||||||
NULL, INVALID_DEVID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz,
|
int wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz,
|
||||||
void* heap, int devId)
|
void* heap, int devId)
|
||||||
{
|
{
|
||||||
return _InitRng(rng, nonce, nonceSz,
|
return _InitRng(rng, nonce, nonceSz, heap, devId);
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
|
||||||
NULL, 0,
|
|
||||||
#endif
|
|
||||||
heap, devId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_HASHDRBG
|
#ifdef HAVE_HASHDRBG
|
||||||
@@ -1384,35 +1337,22 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
|
|||||||
WOLFSSL_ABI
|
WOLFSSL_ABI
|
||||||
int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
|
int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
|
||||||
{
|
{
|
||||||
if ((rng == NULL) || (output == NULL))
|
if (rng == NULL)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
if (rng->status == WC_DRBG_BANKREF) {
|
if (rng->status == WC_DRBG_BANKREF) {
|
||||||
int ret;
|
int ret;
|
||||||
struct wc_rng_bank_inst *bank_inst = NULL;
|
struct wc_rng_bank_inst *bank_inst = NULL;
|
||||||
|
|
||||||
if ((rng->bankref == NULL) ||
|
ret = wc_local_rng_bank_checkout_for_bankref(rng->bankref, &bank_inst);
|
||||||
(! (rng->bankref->flags & WC_RNG_BANK_FLAG_INITED)))
|
|
||||||
{
|
|
||||||
return BAD_FUNC_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = wc_rng_bank_checkout(rng->bankref, &bank_inst, 0, 0,
|
|
||||||
WC_RNG_BANK_FLAG_CAN_FAIL_OVER_INST |
|
|
||||||
WC_RNG_BANK_FLAG_CAN_WAIT |
|
|
||||||
WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST |
|
|
||||||
WC_RNG_BANK_FLAG_AFFINITY_LOCK);
|
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
if (bank_inst == NULL)
|
if (bank_inst == NULL)
|
||||||
return BAD_STATE_E;
|
return BAD_STATE_E;
|
||||||
if (bank_inst->rng.status != WC_DRBG_OK) {
|
ret = wc_local_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(bank_inst),
|
||||||
(void)wc_rng_bank_checkin(rng->bankref, bank_inst);
|
output, sz);
|
||||||
return BAD_STATE_E;
|
|
||||||
}
|
|
||||||
ret = wc_local_RNG_GenerateBlock(&bank_inst->rng, output, sz);
|
|
||||||
{
|
{
|
||||||
int checkin_ret = wc_rng_bank_checkin(rng->bankref, bank_inst);
|
int checkin_ret = wc_rng_bank_checkin(rng->bankref, &bank_inst);
|
||||||
if (checkin_ret != 0) {
|
if (checkin_ret != 0) {
|
||||||
#ifdef WC_VERBOSE_RNG
|
#ifdef WC_VERBOSE_RNG
|
||||||
WOLFSSL_DEBUG_PRINTF(
|
WOLFSSL_DEBUG_PRINTF(
|
||||||
@@ -1444,14 +1384,8 @@ int wc_FreeRng(WC_RNG* rng)
|
|||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
#ifdef WC_RNG_BANK_SUPPORT
|
||||||
if (rng->status == WC_DRBG_BANKREF) {
|
if (rng->status == WC_DRBG_BANKREF)
|
||||||
if (rng->bankref == NULL)
|
return wc_BankRef_Release(rng);
|
||||||
return BAD_FUNC_ARG;
|
|
||||||
wolfSSL_RefFree(&rng->bankref->refcount);
|
|
||||||
rng->bankref = NULL;
|
|
||||||
rng->status = DRBG_NOT_INIT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* WC_RNG_BANK_SUPPORT */
|
#endif /* WC_RNG_BANK_SUPPORT */
|
||||||
|
|
||||||
#if defined(WOLFSSL_ASYNC_CRYPT)
|
#if defined(WOLFSSL_ASYNC_CRYPT)
|
||||||
@@ -1547,9 +1481,6 @@ static int wc_RNG_HealthTest_ex_internal(DRBG_internal* drbg,
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (Hash_DRBG_Instantiate(drbg, seedA, seedASz, nonce, nonceSz,
|
if (Hash_DRBG_Instantiate(drbg, seedA, seedASz, nonce, nonceSz,
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
|
||||||
NULL /* salt */, 0,
|
|
||||||
#endif
|
|
||||||
heap, devId) != 0) {
|
heap, devId) != 0) {
|
||||||
goto exit_rng_ht;
|
goto exit_rng_ht;
|
||||||
}
|
}
|
||||||
@@ -1613,11 +1544,7 @@ int wc_RNG_HealthTest_ex(int reseed, const byte* nonce, word32 nonceSz,
|
|||||||
|
|
||||||
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
||||||
ret = Hash_DRBG_Instantiate(drbg,
|
ret = Hash_DRBG_Instantiate(drbg,
|
||||||
NULL /* seed */, 0, NULL /* nonce */, 0,
|
NULL /* seed */, 0, NULL /* nonce */, 0, heap, devId);
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
|
||||||
NULL /* salt */, 0,
|
|
||||||
#endif
|
|
||||||
heap, devId);
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@@ -3207,32 +3134,10 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
|
|||||||
|
|
||||||
#elif defined(WOLFSSL_LINUXKM)
|
#elif defined(WOLFSSL_LINUXKM)
|
||||||
|
|
||||||
/* When registering the kernel default DRBG with a native/intrinsic entropy
|
#ifndef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
|
||||||
* source, fallback to get_random_bytes() isn't allowed because we replace
|
#include <linux/random.h>
|
||||||
* it with our DRBG.
|
#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)
|
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
|
||||||
{
|
{
|
||||||
(void)os;
|
(void)os;
|
||||||
@@ -3240,11 +3145,9 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
|
|||||||
|
|
||||||
#ifdef HAVE_ENTROPY_MEMUSE
|
#ifdef HAVE_ENTROPY_MEMUSE
|
||||||
ret = wc_Entropy_Get(MAX_ENTROPY_BITS, output, sz);
|
ret = wc_Entropy_Get(MAX_ENTROPY_BITS, output, sz);
|
||||||
if (ret == 0) {
|
if (ret == 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
#ifdef ENTROPY_MEMUSE_FORCE_FAILURE
|
#ifdef ENTROPY_MEMUSE_FORCE_FAILURE
|
||||||
/* Don't fallback to /dev/urandom. */
|
|
||||||
return ret;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@@ -3252,23 +3155,30 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
|
|||||||
#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
|
#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
|
||||||
if (IS_INTEL_RDSEED(intel_flags)) {
|
if (IS_INTEL_RDSEED(intel_flags)) {
|
||||||
ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
|
ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
|
||||||
#ifndef FORCE_FAILURE_RDSEED
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
#endif
|
return 0;
|
||||||
{
|
#ifdef FORCE_FAILURE_RDSEED
|
||||||
return ret;
|
return ret;
|
||||||
}
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
|
#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;
|
(void)ret;
|
||||||
|
|
||||||
get_random_bytes(output, sz);
|
get_random_bytes(output, sz);
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !(HAVE_*_RDSEED && LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT) */
|
|
||||||
|
|
||||||
#elif defined(WOLFSSL_BSDKM)
|
#elif defined(WOLFSSL_BSDKM)
|
||||||
#include <sys/random.h>
|
#include <sys/random.h>
|
||||||
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
|
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
|
||||||
@@ -3841,593 +3751,4 @@ int wc_hwrng_generate_block(byte *output, word32 sz)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
|
||||||
|
|
||||||
WOLFSSL_API int wc_rng_bank_init(
|
|
||||||
struct wc_rng_bank *ctx,
|
|
||||||
int n_rngs,
|
|
||||||
word32 flags,
|
|
||||||
int timeout_secs,
|
|
||||||
void *heap)
|
|
||||||
{
|
|
||||||
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 = _InitRng(&ctx->rngs[i].rng, NULL, 0, (const byte *)&i,
|
|
||||||
sizeof(i), heap, INVALID_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_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) ||
|
|
||||||
(! (ctx->flags & WC_RNG_BANK_FLAG_INITED)))
|
|
||||||
{
|
|
||||||
return BAD_FUNC_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wolfSSL_RefCur(ctx->refcount) > 1) {
|
|
||||||
#ifdef WC_VERBOSE_RNG
|
|
||||||
WOLFSSL_DEBUG_PRINTF(
|
|
||||||
"BUG: wc_rng_bank_fini() called with refcount %d.\n",
|
|
||||||
wolfSSL_RefCur(ctx->refcount));
|
|
||||||
#endif
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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,
|
|
||||||
int preferred_inst_offset,
|
|
||||||
int timeout_secs,
|
|
||||||
word32 flags)
|
|
||||||
{
|
|
||||||
int new_lock_value, ret = 0;
|
|
||||||
time_t ts1, ts2;
|
|
||||||
int n_rngs_tried = 0;
|
|
||||||
|
|
||||||
if ((bank == NULL) ||
|
|
||||||
(! (bank->flags & WC_RNG_BANK_FLAG_INITED)) ||
|
|
||||||
(rng == 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 = 2;
|
|
||||||
else if (ret == WC_NO_ERR_TRACE(ALREADY_E))
|
|
||||||
new_lock_value = 1;
|
|
||||||
else
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
new_lock_value = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) && ((preferred_inst_offset < 0) ||
|
|
||||||
(preferred_inst_offset >= bank->n_rngs)))
|
|
||||||
{
|
|
||||||
#ifdef WC_VERBOSE_RNG
|
|
||||||
WOLFSSL_DEBUG_PRINTF(
|
|
||||||
"BUG: bank->affinity_get_id_cb() returned out-of-range inst ID "
|
|
||||||
"%d, with bank->n_rngs %d.\n", preferred_inst_offset,
|
|
||||||
bank->n_rngs);
|
|
||||||
#endif
|
|
||||||
ret = BAD_INDEX_E;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ((preferred_inst_offset < 0) ||
|
|
||||||
(preferred_inst_offset >= bank->n_rngs))
|
|
||||||
{
|
|
||||||
#ifdef WC_VERBOSE_RNG
|
|
||||||
WOLFSSL_DEBUG_PRINTF(
|
|
||||||
"BUG: wc_rng_bank_checkout() passed out-of-range inst ID %d, "
|
|
||||||
"with bank->n_rngs %d.\n", preferred_inst_offset, bank->n_rngs);
|
|
||||||
#endif
|
|
||||||
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 = &bank->rngs[preferred_inst_offset];
|
|
||||||
if ((flags | bank->flags) & WC_RNG_BANK_FLAG_NO_VECTOR_OPS) {
|
|
||||||
if (DISABLE_VECTOR_REGISTERS() == 0)
|
|
||||||
WOLFSSL_ATOMIC_STORE((*rng)->lock, new_lock_value | 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((! (flags & WC_RNG_BANK_FLAG_CAN_WAIT)) &&
|
|
||||||
(((DRBG_internal *)(*rng)->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)->lock, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
#ifdef WC_VERBOSE_RNG
|
|
||||||
if ((! (flags & WC_RNG_BANK_FLAG_CAN_WAIT)) &&
|
|
||||||
(((DRBG_internal *)(*rng)->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);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
++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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (timeout_secs > 0) {
|
|
||||||
ts2 = XTIME(0);
|
|
||||||
if (ts2 - ts1 >= timeout_secs)
|
|
||||||
return WC_TIMEOUT_E;
|
|
||||||
}
|
|
||||||
WC_RELAX_LONG_LOOP();
|
|
||||||
|
|
||||||
if (flags & WC_RNG_BANK_FLAG_AFFINITY_LOCK) {
|
|
||||||
ret = bank->affinity_lock_cb(bank->cb_arg);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new_lock_value & 2)
|
|
||||||
(void)bank->affinity_unlock_cb(bank->cb_arg);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
WOLFSSL_API int wc_rng_bank_checkin(
|
|
||||||
struct wc_rng_bank *bank,
|
|
||||||
struct wc_rng_bank_inst *rng_inst)
|
|
||||||
{
|
|
||||||
int migration_disabled = (WOLFSSL_ATOMIC_LOAD(rng_inst->lock) & 2);
|
|
||||||
int vec_ops_disabled = (WOLFSSL_ATOMIC_LOAD(rng_inst->lock) & 4);
|
|
||||||
|
|
||||||
WOLFSSL_ATOMIC_STORE(rng_inst->lock, 0);
|
|
||||||
|
|
||||||
if (vec_ops_disabled)
|
|
||||||
REENABLE_VECTOR_REGISTERS();
|
|
||||||
|
|
||||||
if (migration_disabled)
|
|
||||||
return bank->affinity_unlock_cb(bank->cb_arg);
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
word32 saltSz;
|
|
||||||
DRBG_internal *drbg_internal;
|
|
||||||
byte salt[sizeof((DRBG_internal *)rng_inst->rng.drbg)->salt];
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
drbg_internal = (DRBG_internal *)rng_inst->rng.drbg;
|
|
||||||
saltSz = drbg_internal->saltSz;
|
|
||||||
XMEMCPY(salt, drbg_internal->salt, saltSz);
|
|
||||||
|
|
||||||
wc_FreeRng(&rng_inst->rng);
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
ret = _InitRng(&rng_inst->rng, NULL, 0, salt,
|
|
||||||
saltSz, bank->heap, INVALID_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 = Hash_DRBG_Reseed((DRBG_internal *)drbg->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 ((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(&drbg->rng, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_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_RNG_BANK_SUPPORT */
|
|
||||||
|
|
||||||
#endif /* WC_NO_RNG */
|
#endif /* WC_NO_RNG */
|
||||||
|
|||||||
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 */
|
||||||
@@ -325,6 +325,9 @@ static const byte const_byte_array[] = "A+Gd\0\0\0";
|
|||||||
#include <wolfssl/wolfcrypt/arc4.h>
|
#include <wolfssl/wolfcrypt/arc4.h>
|
||||||
#if !defined(WC_NO_RNG)
|
#if !defined(WC_NO_RNG)
|
||||||
#include <wolfssl/wolfcrypt/random.h>
|
#include <wolfssl/wolfcrypt/random.h>
|
||||||
|
#ifdef WC_RNG_BANK_SUPPORT
|
||||||
|
#include <wolfssl/wolfcrypt/rng_bank.h>
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#include <wolfssl/wolfcrypt/wolfmath.h>
|
#include <wolfssl/wolfcrypt/wolfmath.h>
|
||||||
#include <wolfssl/wolfcrypt/coding.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);
|
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t srp_test(void);
|
||||||
#ifndef WC_NO_RNG
|
#ifndef WC_NO_RNG
|
||||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_test(void);
|
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 */
|
#endif /* WC_NO_RNG */
|
||||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pwdbased_test(void);
|
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pwdbased_test(void);
|
||||||
#if defined(USE_CERT_BUFFERS_2048) && \
|
#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);
|
TEST_FAIL("RANDOM test failed!\n", ret);
|
||||||
else
|
else
|
||||||
TEST_PASS("RANDOM test passed!\n");
|
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 */
|
#endif /* WC_NO_RNG */
|
||||||
|
|
||||||
#ifdef WOLFSSL_SHAKE128
|
#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 /* !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
|
#ifndef MEM_TEST_SZ
|
||||||
#define MEM_TEST_SZ 1024
|
#define MEM_TEST_SZ 1024
|
||||||
@@ -31983,7 +32326,7 @@ static wc_test_ret_t ecc_test_deterministic_k(WC_RNG* rng)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
WC_ALLOC_VAR_EX(key, ecc_key, 1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER,
|
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);
|
ret = wc_ecc_init_ex(key, HEAP_HINT, devId);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ nobase_include_HEADERS+= \
|
|||||||
wolfssl/wolfcrypt/chacha20_poly1305.h \
|
wolfssl/wolfcrypt/chacha20_poly1305.h \
|
||||||
wolfssl/wolfcrypt/random.h \
|
wolfssl/wolfcrypt/random.h \
|
||||||
wolfssl/wolfcrypt/wolfentropy.h \
|
wolfssl/wolfcrypt/wolfentropy.h \
|
||||||
|
wolfssl/wolfcrypt/rng_bank.h \
|
||||||
wolfssl/wolfcrypt/ripemd.h \
|
wolfssl/wolfcrypt/ripemd.h \
|
||||||
wolfssl/wolfcrypt/rsa.h \
|
wolfssl/wolfcrypt/rsa.h \
|
||||||
wolfssl/wolfcrypt/rc2.h \
|
wolfssl/wolfcrypt/rc2.h \
|
||||||
|
|||||||
@@ -247,15 +247,6 @@ struct OS_Seed {
|
|||||||
|
|
||||||
#define RNG_HEALTH_TEST_CHECK_SIZE (WC_SHA256_DIGEST_SIZE * 4)
|
#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
|
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
|
||||||
#define WC_DRBG_BANKREF 4
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct DRBG_internal {
|
struct DRBG_internal {
|
||||||
#ifdef WORD64_AVAILABLE
|
#ifdef WORD64_AVAILABLE
|
||||||
word64 reseedCtr;
|
word64 reseedCtr;
|
||||||
@@ -273,14 +264,18 @@ struct DRBG_internal {
|
|||||||
byte seed_scratch[DRBG_SEED_LEN];
|
byte seed_scratch[DRBG_SEED_LEN];
|
||||||
byte digest_scratch[WC_SHA256_DIGEST_SIZE];
|
byte digest_scratch[WC_SHA256_DIGEST_SIZE];
|
||||||
#endif
|
#endif
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
|
||||||
#ifndef WC_DRBG_MAX_SALT_SZ
|
|
||||||
#define WC_DRBG_MAX_SALT_SZ 4
|
|
||||||
#endif
|
|
||||||
word32 saltSz;
|
|
||||||
byte salt[WC_DRBG_MAX_SALT_SZ];
|
|
||||||
#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
|
#endif
|
||||||
|
|
||||||
/* RNG context */
|
/* RNG context */
|
||||||
@@ -407,92 +402,6 @@ WOLFSSL_API int wc_FreeRng(WC_RNG* rng);
|
|||||||
void* heap, int devId);
|
void* heap, int devId);
|
||||||
#endif /* HAVE_HASHDRBG */
|
#endif /* HAVE_HASHDRBG */
|
||||||
|
|
||||||
#ifdef WC_RNG_BANK_SUPPORT
|
|
||||||
|
|
||||||
/* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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)
|
|
||||||
|
|
||||||
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_init(
|
|
||||||
struct wc_rng_bank *ctx,
|
|
||||||
int n_rngs,
|
|
||||||
word32 flags,
|
|
||||||
int timeout_secs,
|
|
||||||
void *heap);
|
|
||||||
|
|
||||||
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_checkout(
|
|
||||||
struct wc_rng_bank *bank,
|
|
||||||
struct wc_rng_bank_inst **rng,
|
|
||||||
int preferred_inst_offset,
|
|
||||||
int timeout_secs,
|
|
||||||
word32 flags);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
WOLFSSL_API int wc_InitRng_BankRef(struct wc_rng_bank *bank, WC_RNG *rng);
|
|
||||||
|
|
||||||
WOLFSSL_API int wc_rng_new_bankref(struct wc_rng_bank *bank, WC_RNG **rng);
|
|
||||||
|
|
||||||
#define WC_RNG_BANK_INST_TO_RNG(rng_inst) (&(rng_inst)->rng)
|
|
||||||
|
|
||||||
#endif /* WC_DRBG_BANK_SUPPORT */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#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 */
|
||||||
Reference in New Issue
Block a user