From a043b7a8d6b76a947577ddb6595bed82d5ff313e Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 9 Jan 2026 14:44:24 -0600 Subject: [PATCH] wolfcrypt/src/rng_bank.c, wolfssl/wolfcrypt/rng_bank.h, wolfcrypt/test/test.c: * add WC_RNG_BANK_STATIC to WC_RNG_BANK_SUPPORT, supporting WOLFSSL_NO_MALLOC; * in random_bank_test(), fix gate around _NO_VECTOR_OPS sha256.sha_method test (WOLFSSL_SMALL_STACK_CACHE, and USE_INTEL_SPEEDUP not WC_HAVE_VECTOR_SPEEDUPS); * in definition of struct wc_rng_bank_inst, accommodate WOLFSSL_NO_ATOMICS builds; wolfssl/wolfcrypt/random.h: in definition of struct WC_RNG, add gate to avoid empty union in !HAVE_HASHDRBG configs. --- wolfcrypt/src/rng_bank.c | 18 +- wolfcrypt/test/test.c | 316 ++++++++++++++++++++++++----------- wolfssl/wolfcrypt/random.h | 4 + wolfssl/wolfcrypt/rng_bank.h | 23 +++ 4 files changed, 258 insertions(+), 103 deletions(-) diff --git a/wolfcrypt/src/rng_bank.c b/wolfcrypt/src/rng_bank.c index f23c80584..56aa27d09 100644 --- a/wolfcrypt/src/rng_bank.c +++ b/wolfcrypt/src/rng_bank.c @@ -50,11 +50,16 @@ WOLFSSL_API int wc_rng_bank_init( ctx->flags = flags | WC_RNG_BANK_FLAG_INITED; ctx->heap = heap; +#ifdef WC_RNG_BANK_STATIC + if (n_rngs > WC_RNG_BANK_STATIC_SIZE) + return BAD_LENGTH_E; +#else 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; +#endif if (ret == 0) { XMEMSET(ctx->rngs, 0, sizeof(*ctx->rngs) * (size_t)n_rngs); @@ -116,6 +121,7 @@ WOLFSSL_API int wc_rng_bank_init( return ret; } +#ifndef WC_RNG_BANK_STATIC WOLFSSL_API int wc_rng_bank_new( struct wc_rng_bank **ctx, int n_rngs, @@ -142,6 +148,7 @@ WOLFSSL_API int wc_rng_bank_new( return ret; } +#endif /* !WC_RNG_BANK_STATIC */ WOLFSSL_API int wc_rng_bank_set_affinity_handlers( struct wc_rng_bank *ctx, @@ -181,7 +188,10 @@ WOLFSSL_API int wc_rng_bank_fini(struct wc_rng_bank *ctx) { if (wolfSSL_RefCur(ctx->refcount) > 1) return BUSY_E; - if (ctx->rngs) { +#ifndef WC_RNG_BANK_STATIC + if (ctx->rngs) +#endif + { for (i = 0; i < ctx->n_rngs; ++i) { if (ctx->rngs[i].lock != 0) { /* better to leak than to crash. */ @@ -198,8 +208,10 @@ WOLFSSL_API int wc_rng_bank_fini(struct wc_rng_bank *ctx) { wc_FreeRng(&ctx->rngs[i].rng); } +#ifndef WC_RNG_BANK_STATIC XFREE(ctx->rngs, ctx->heap, DYNAMIC_TYPE_RNG); ctx->rngs = NULL; +#endif ctx->n_rngs = 0; } @@ -211,6 +223,7 @@ WOLFSSL_API int wc_rng_bank_fini(struct wc_rng_bank *ctx) { return 0; } +#ifndef WC_RNG_BANK_STATIC WOLFSSL_API int wc_rng_bank_free(struct wc_rng_bank **ctx) { int ret; void *heap; @@ -232,6 +245,7 @@ WOLFSSL_API int wc_rng_bank_free(struct wc_rng_bank **ctx) { return ret; } +#endif /* !WC_RNG_BANK_STATIC */ /* wc_rng_bank_checkout() uses atomic operations to get exclusive ownership of a * DRBG without delay. It expects to be called in uninterruptible context, @@ -694,6 +708,7 @@ WOLFSSL_API int wc_BankRef_Release(WC_RNG *rng) return ret; } +#ifndef WC_RNG_BANK_STATIC WOLFSSL_API int wc_rng_new_bankref(struct wc_rng_bank *bank, WC_RNG **rng) { int ret; @@ -717,6 +732,7 @@ WOLFSSL_API int wc_rng_new_bankref(struct wc_rng_bank *bank, WC_RNG **rng) { return ret; } +#endif /* !WC_RNG_BANK_STATIC */ #endif /* WC_DRBG_BANKREF */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 9b2645dcb..dfe22a037 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -20170,15 +20170,19 @@ static int rng_bank_affinity_unlock(void *arg) { 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; +#ifdef WC_DRBG_BANKREF + WC_DECLARE_VAR(rng, WC_RNG, 1, HEAP_HINT); +#endif +#ifndef WC_RNG_BANK_STATIC struct wc_rng_bank *bank2 = NULL; struct wc_rng_bank_inst *rng_inst2 = NULL; #ifdef WC_DRBG_BANKREF - WC_RNG *rng = NULL, *rng2 = NULL; + WC_RNG *rng2 = NULL; #endif +#endif /* !WC_RNG_BANK_STATIC */ static const char bank_arg[] = "hi"; byte outbuf1[16], outbuf2[16]; int i; @@ -20188,11 +20192,22 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) 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); + WC_ALLOC_VAR_EX(rng, WC_RNG, 1, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER, + return WC_TEST_RET_ENC_EC(MEMORY_E)); + XMEMSET(rng, 0, sizeof(*rng)); + + ret = wc_rng_bank_init(NULL, WC_RNG_BANK_STATIC_SIZE, 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); +#ifdef WC_RNG_BANK_STATIC + ret = wc_rng_bank_init(bank, WC_RNG_BANK_STATIC_SIZE + 1, WC_RNG_BANK_FLAG_CAN_WAIT, 10, HEAP_HINT, INVALID_DEVID); + if (ret != WC_NO_ERR_TRACE(BAD_LENGTH_E)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); +#endif + + ret = wc_rng_bank_init(bank, WC_RNG_BANK_STATIC_SIZE, WC_RNG_BANK_FLAG_CAN_WAIT, 10, HEAP_HINT, INVALID_DEVID); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); @@ -20205,91 +20220,79 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) 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); + 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 != 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); + 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); - if (rng_inst2 != bank2->rngs + 2) + if (rng_inst != bank->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) && \ +#if defined(USE_INTEL_SPEEDUP) && \ defined(WOLFSSL_KERNEL_MODE) && \ + defined(WOLFSSL_SMALL_STACK_CACHE) && \ defined(WC_C_DYNAMIC_FALLBACK) && \ - defined(HAVE_HASHDRBG) && \ + 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); + if (((struct DRBG_internal *)rng_inst->rng.drbg)->sha256.sha_method != 7 /* SHA256_C */) + ERROR_OUT(WC_TEST_RET_ENC_I(((struct DRBG_internal *)rng_inst->rng.drbg)->sha256.sha_method), out); #endif - ret = wc_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(rng_inst2), outbuf1, sizeof(outbuf1)); + 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); - ret = wc_rng_bank_checkin(bank2, &rng_inst2); + ret = wc_rng_bank_checkin(bank, &rng_inst); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - if (rng_inst2 != NULL) + if (rng_inst != 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); + ret = wc_rng_bank_checkout(bank, &rng_inst, 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) + if (rng_inst != bank->rngs + 3) ERROR_OUT(WC_TEST_RET_ENC_NC, out); - ret = wc_rng_bank_checkin(bank2, &rng_inst2); + ret = wc_rng_bank_checkin(bank, &rng_inst); 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); + 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); - if (rng_inst2 != bank2->rngs + 3) + if (rng_inst != bank->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)); + 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); - ret = wc_rng_bank_checkin(bank2, &rng_inst2); + ret = wc_rng_bank_checkin(bank, &rng_inst); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); - if (rng_inst2 != NULL) + if (rng_inst != 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); + ret = wc_InitRng_BankRef(bank, rng); 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)); + ret = wc_RNG_GenerateBlock(rng, outbuf1, sizeof(outbuf1)); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); @@ -20297,12 +20300,12 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) ERROR_OUT(WC_TEST_RET_ENC_NC, out); #endif - ret = wc_rng_bank_reseed(bank2, 10, WC_RNG_BANK_FLAG_NONE); + ret = wc_rng_bank_reseed(bank, 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) + for (i = 0; i < bank->n_rngs; ++i) { + if (((struct DRBG_internal *)bank->rngs[i].rng.drbg) ->reseedCtr != WC_RESEED_INTERVAL) { ERROR_OUT(WC_TEST_RET_ENC_I(i), out); @@ -20313,53 +20316,35 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) /* 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); + ret = wc_rng_bank_checkout(bank, &rng_inst, -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)); + 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); - ret = wc_rng_bank_checkin(bank2, &rng_inst2); + ret = wc_rng_bank_checkin(bank, &rng_inst); 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); + ret = wc_rng_bank_checkout(bank, &rng_inst, -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)); + 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); - ret = wc_rng_bank_checkin(bank2, &rng_inst2); + ret = wc_rng_bank_checkin(bank, &rng_inst); 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); + 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); - 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); @@ -20368,8 +20353,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) 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. + if (XMEMCMP(outbuf1, outbuf2, sizeof(outbuf1)) == 0) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); + + /* can't wc_rng_bank_seed() while holding an inst (deadlock/timeout) -- + * check in then check back out. */ ret = wc_rng_bank_checkin(bank, &rng_inst); if (ret != 0) @@ -20387,25 +20375,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) 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. @@ -20428,24 +20397,160 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); +#ifdef WC_DRBG_BANKREF + if (wolfSSL_RefCur(bank->refcount) != 2) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); + + ret = wc_rng_bank_fini(bank); + if (ret != WC_NO_ERR_TRACE(BUSY_E)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); + + wc_FreeRng(rng); + + if (wolfSSL_RefCur(bank->refcount) != 1) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); +#endif + +#ifdef WC_RNG_BANK_STATIC + + ret = 0; + +#else /* !WC_RNG_BANK_STATIC */ + + ret = wc_rng_bank_new(&bank2, WC_RNG_BANK_STATIC_SIZE + 1, 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 = WC_RNG_BANK_STATIC_SIZE; + 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 + WC_RNG_BANK_STATIC_SIZE) + ERROR_OUT(WC_TEST_RET_ENC_NC, 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); + + /* can't wc_rng_bank_seed() while holding an inst (deadlock/timeout) -- + * check in then check back out. + */ + ret = wc_rng_bank_checkin(bank2, &rng_inst2); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + + ret = wc_rng_bank_seed(bank2, (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(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); + + 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); + + if (XMEMCMP(outbuf1, outbuf2, sizeof(outbuf1)) == 0) + 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); + + ret = wc_rng_bank_seed(bank2, (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(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); + + 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); + + /* 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(bank2, rng_inst2, 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_inst2), 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(bank2, &rng_inst2); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + +#ifdef WC_DRBG_BANKREF + ret = wc_rng_new_bankref(bank2, &rng2); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + if (rng2 == NULL) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); + + rng_bank_affinity_get_id_id = 1; + ret = wc_RNG_GenerateBlock(rng2, 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); + + 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_FreeRng(rng2); + + if (wolfSSL_RefCur(bank2->refcount) != 1) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); + +#endif /* WC_DRBG_BANKREF */ + + 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); + +#endif /* WC_RNG_BANK_STATIC */ + 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 - + cleanup_ret = wc_FreeRng(rng); + if ((cleanup_ret != 0) && (ret == 0)) +{ + ret = WC_TEST_RET_ENC_EC(cleanup_ret); +} + WC_FREE_VAR_EX(rng, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#endif /* WC_DRBG_BANKREF */ if (rng_inst) { cleanup_ret = wc_rng_bank_checkin(bank, &rng_inst); if ((cleanup_ret != 0) && (ret == 0)) @@ -20453,6 +20558,16 @@ out: if ((rng_inst != 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); + +#ifndef WC_RNG_BANK_STATIC +#ifdef WC_DRBG_BANKREF + if (rng2) + wc_rng_free(rng2); +#endif if (rng_inst2) { cleanup_ret = wc_rng_bank_checkin(bank2, &rng_inst2); if ((cleanup_ret != 0) && (ret == 0)) @@ -20460,15 +20575,12 @@ out: 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; +#endif /* !WC_RNG_BANK_STATIC */ } return ret; diff --git a/wolfssl/wolfcrypt/random.h b/wolfssl/wolfcrypt/random.h index 3a337ece4..6381c2f7a 100644 --- a/wolfssl/wolfcrypt/random.h +++ b/wolfssl/wolfcrypt/random.h @@ -284,6 +284,8 @@ struct WC_RNG { void* heap; byte status; +#if defined(WC_RNG_BANK_SUPPORT) || defined(HAVE_HASHDRBG) + #ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES union { #endif @@ -316,6 +318,8 @@ struct WC_RNG { }; #endif +#endif /* WC_RNG_BANK_SUPPORT || HAVE_HASHDRBG */ + #if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID) pid_t pid; #endif diff --git a/wolfssl/wolfcrypt/rng_bank.h b/wolfssl/wolfcrypt/rng_bank.h index 205c1e5e3..f8b502620 100644 --- a/wolfssl/wolfcrypt/rng_bank.h +++ b/wolfssl/wolfcrypt/rng_bank.h @@ -57,10 +57,23 @@ 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 { +#ifdef WOLFSSL_NO_ATOMICS + int lock; +#else wolfSSL_Atomic_Int lock; +#endif WC_RNG rng; }; +#if defined(WOLFSSL_NO_MALLOC) && defined(NO_WOLFSSL_MEMORY) && \ + !defined(WC_RNG_BANK_STATIC) + #define WC_RNG_BANK_STATIC +#endif + +#ifndef WC_RNG_BANK_STATIC_SIZE + #define WC_RNG_BANK_STATIC_SIZE 4 +#endif + struct wc_rng_bank { wolfSSL_Ref refcount; void *heap; @@ -70,9 +83,14 @@ struct wc_rng_bank { wc_affinity_unlock_fn_t affinity_unlock_cb; void *cb_arg; /* if mutable, caller is responsible for thread safety. */ int n_rngs; +#ifdef WC_RNG_BANK_STATIC + struct wc_rng_bank_inst rngs[WC_RNG_BANK_STATIC_SIZE]; +#else struct wc_rng_bank_inst *rngs; /* typically one per CPU ID, plus a few */ +#endif }; +#ifndef WC_RNG_BANK_STATIC WOLFSSL_API int wc_rng_bank_new( struct wc_rng_bank **ctx, int n_rngs, @@ -80,6 +98,7 @@ WOLFSSL_API int wc_rng_bank_new( int timeout_secs, void *heap, int devId); +#endif WOLFSSL_API int wc_rng_bank_init( struct wc_rng_bank *ctx, @@ -98,7 +117,9 @@ WOLFSSL_API int wc_rng_bank_set_affinity_handlers( WOLFSSL_API int wc_rng_bank_fini(struct wc_rng_bank *ctx); +#ifndef WC_RNG_BANK_STATIC WOLFSSL_API int wc_rng_bank_free(struct wc_rng_bank **ctx); +#endif WOLFSSL_API int wc_rng_bank_checkout( struct wc_rng_bank *bank, @@ -135,7 +156,9 @@ WOLFSSL_API int wc_InitRng_BankRef(struct wc_rng_bank *bank, WC_RNG *rng); WOLFSSL_API int wc_BankRef_Release(WC_RNG *rng); +#ifndef WC_RNG_BANK_STATIC WOLFSSL_API int wc_rng_new_bankref(struct wc_rng_bank *bank, WC_RNG **rng); +#endif #endif /* WC_DRBG_BANKREF */ #define WC_RNG_BANK_INST_TO_RNG(rng_inst) (&(rng_inst)->rng)