diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 5d605a4d55..56eb6a0dfd 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -1074,6 +1074,7 @@ __WATCOMC__ __WATCOM_INT64__ __XC32 __XTENSA__ +__ZEPHYR__ __aarch64__ __alpha__ __arch64__ @@ -1105,7 +1106,6 @@ __thumb__ __ti__ __x86_64__ __xtensa__ -__ZEPHYR__ byte configTICK_RATE_HZ fallthrough diff --git a/wolfcrypt/src/rng_bank.c b/wolfcrypt/src/rng_bank.c index f23c805846..5bb5d9d35a 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, @@ -631,7 +645,7 @@ WOLFSSL_API int wc_rng_bank_reseed(struct wc_rng_bank *bank, "ERROR: wc_crng_reseed() wc_RNG_GenerateBlock() " "for DRBG #%d returned %d.", n, ret); #endif - wc_rng_bank_checkin(bank, &drbg); + (void)wc_rng_bank_checkin(bank, &drbg); if (ret == WC_NO_ERR_TRACE(WC_TIMEOUT_E)) return ret; ret = WC_CHECK_FOR_INTR_SIGNALS(); @@ -640,7 +654,7 @@ WOLFSSL_API int wc_rng_bank_reseed(struct wc_rng_bank *bank, WC_RELAX_LONG_LOOP(); } else { - wc_rng_bank_checkin(bank, &drbg); + (void)wc_rng_bank_checkin(bank, &drbg); } } @@ -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 9b2645dcb8..1aab2d1e76 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,29 +20192,27 @@ 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); - 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) +#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_new(&bank2, 4, WC_RNG_BANK_FLAG_NO_VECTOR_OPS, 10, HEAP_HINT, INVALID_DEVID); + 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); ret = wc_rng_bank_set_affinity_handlers( - bank2, + bank, rng_bank_affinity_lock, rng_bank_affinity_get_id, rng_bank_affinity_unlock, @@ -20219,77 +20221,78 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) 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,96 +20316,166 @@ 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); + + 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); + + 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); + + 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) + 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); + + /* 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); + #ifdef WC_DRBG_BANKREF - if (wolfSSL_RefCur(bank2->refcount) != 2) + if (wolfSSL_RefCur(bank->refcount) != 2) ERROR_OUT(WC_TEST_RET_ENC_NC, out); - ret = wc_rng_bank_free(&bank2); + ret = wc_rng_bank_fini(bank); if (ret != WC_NO_ERR_TRACE(BUSY_E)) ERROR_OUT(WC_TEST_RET_ENC_NC, out); - wc_rng_free(rng2); - rng2 = NULL; + wc_FreeRng(rng); - if (wolfSSL_RefCur(bank2->refcount) != 1) + if (wolfSSL_RefCur(bank->refcount) != 1) ERROR_OUT(WC_TEST_RET_ENC_NC, out); #endif - ret = wc_rng_bank_free(&bank2); +#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); - if (bank2 != NULL) - ERROR_OUT(WC_TEST_RET_ENC_NC, out); - rng_bank_affinity_get_id_id = 0; + 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); - ret = wc_rng_bank_checkout(bank, &rng_inst, -1, 10, WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST | WC_RNG_BANK_FLAG_AFFINITY_LOCK); + 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_inst), outbuf1, sizeof(outbuf1)); + 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() with _FLAG_CAN_WAIT while holding an inst -- - * deadlocks then times 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); + 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(bank, (byte *)bank_arg, (word32)sizeof(bank_arg), 10, WC_RNG_BANK_FLAG_CAN_WAIT); + 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(bank, &rng_inst, -1, 10, WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST | WC_RNG_BANK_FLAG_AFFINITY_LOCK); + 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_inst), outbuf2, sizeof(outbuf2)); + 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(bank, &rng_inst); + 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(bank, (byte *)bank_arg, (word32)sizeof(bank_arg), 10, WC_RNG_BANK_FLAG_CAN_WAIT); + 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(bank, &rng_inst, -1, 10, WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST | WC_RNG_BANK_FLAG_AFFINITY_LOCK); + 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_inst), outbuf1, sizeof(outbuf1)); + 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); @@ -20413,20 +20486,58 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) 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); + 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_inst), outbuf1, sizeof(outbuf1)); + 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(bank, &rng_inst); + 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_rng_free(rng2); + rng2 = NULL; + + 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: @@ -20434,18 +20545,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) 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 +20557,16 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) 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 +20574,12 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) 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 3a337ece49..6381c2f7a7 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 205c1e5e32..f8b5026209 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)