diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 61f67b7121..a1d0651647 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -646,6 +646,7 @@ WC_NO_VERBOSE_RNG WC_PKCS11_FIND_WITH_ID_ONLY WC_PKCS12_PBKDF_USING_MP_API WC_PROTECT_ENCRYPTED_MEM +WC_RNG_BANK_NO_DEFAULT_SUPPORT WC_RNG_BLOCKING WC_RSA_NONBLOCK WC_RSA_NONBLOCK_TIME diff --git a/linuxkm/lkcapi_sha_glue.c b/linuxkm/lkcapi_sha_glue.c index 1a3c55574c..4edf50a06f 100644 --- a/linuxkm/lkcapi_sha_glue.c +++ b/linuxkm/lkcapi_sha_glue.c @@ -997,7 +997,11 @@ struct wc_swallow_the_semicolon #include #include -static volatile int wc_linuxkm_drbg_init_tfm_disable_vector_registers = 0; +#ifndef WC_RNG_BANK_DEFAULT_SUPPORT + #error LINUXKM_LKCAPI_REGISTER_HASH_DRBG requires WC_RNG_BANK_DEFAULT_SUPPORT. +#endif + +static volatile int wc_linuxkm_rng_initing_default_bank_flag = 0; #ifndef WC_LINUXKM_INITRNG_TIMEOUT_SEC #define WC_LINUXKM_INITRNG_TIMEOUT_SEC 30 @@ -1032,13 +1036,12 @@ static int linuxkm_affinity_unlock(void *arg) { return 0; } -static int wc_linuxkm_drbg_init_tfm(struct crypto_tfm *tfm) +static int wc_linuxkm_rng_bank_init(struct wc_rng_bank *ctx) { - struct wc_rng_bank *ctx = (struct wc_rng_bank *)crypto_tfm_ctx(tfm); int ret; word32 flags = WC_RNG_BANK_FLAG_CAN_WAIT; - if (wc_linuxkm_drbg_init_tfm_disable_vector_registers) + if (wc_linuxkm_rng_initing_default_bank_flag) flags |= WC_RNG_BANK_FLAG_NO_VECTOR_OPS; ret = wc_rng_bank_init( @@ -1052,14 +1055,24 @@ static int wc_linuxkm_drbg_init_tfm(struct crypto_tfm *tfm) linuxkm_affinity_get_id, linuxkm_affinity_unlock, NULL); - if (ret != 0) { + if (ret == 0) { + if (wc_linuxkm_rng_initing_default_bank_flag) { + ret = wc_rng_bank_default_set(ctx); + if (ret != 0) { + (void)wc_rng_bank_fini(ctx); + pr_err("ERROR: wc_rng_bank_default_set() in wc_linuxkm_rng_bank_init() returned err %d\n", ret); + WC_DUMP_BACKTRACE_NONDEBUG; + } + } + } + else { (void)wc_rng_bank_fini(ctx); - pr_err("ERROR: wc_rng_bank_set_affinity_handlers() in wc_linuxkm_drbg_init_tfm() returned err %d\n", ret); + pr_err("ERROR: wc_rng_bank_set_affinity_handlers() in wc_linuxkm_rng_bank_init() returned err %d\n", ret); WC_DUMP_BACKTRACE_NONDEBUG; } } else { - pr_err("ERROR: wc_rng_bank_init() in wc_linuxkm_drbg_init_tfm() returned err %d\n", ret); + pr_err("ERROR: wc_rng_bank_init() in wc_linuxkm_rng_bank_init() returned err %d\n", ret); if (ret == WC_NO_ERR_TRACE(MEMORY_E)) ret = -ENOMEM; else if (ret == WC_NO_ERR_TRACE(WC_TIMEOUT_E)) @@ -1073,10 +1086,21 @@ static int wc_linuxkm_drbg_init_tfm(struct crypto_tfm *tfm) return ret; } +static int wc_linuxkm_drbg_init_tfm(struct crypto_tfm *tfm) +{ + return wc_linuxkm_rng_bank_init((struct wc_rng_bank *)crypto_tfm_ctx(tfm)); +} + static void wc_linuxkm_drbg_exit_tfm(struct crypto_tfm *tfm) { struct wc_rng_bank *ctx = (struct wc_rng_bank *)crypto_tfm_ctx(tfm); - int ret = wc_rng_bank_fini(ctx); + int ret; + + ret = wc_rng_bank_default_clear(ctx); + if (ret && (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))) + pr_err("ERROR: wc_rng_bank_default_clear() in wc_linuxkm_drbg_exit_tfm() returned unexpected code %d\n", ret); + + ret = wc_rng_bank_fini(ctx); if (ret != 0) pr_err("ERROR: wc_rng_bank_fini() in wc_linuxkm_drbg_exit_tfm() returned err %d\n", ret); @@ -1086,8 +1110,7 @@ static void wc_linuxkm_drbg_exit_tfm(struct crypto_tfm *tfm) static int wc_linuxkm_drbg_default_instance_registered = 0; -static struct wc_rng_bank_inst *linuxkm_get_drbg(struct crypto_rng *tfm) { - struct wc_rng_bank *ctx = (struct wc_rng_bank *)crypto_rng_ctx(tfm); +static struct wc_rng_bank_inst *linuxkm_get_drbg(struct wc_rng_bank *ctx) { int err; struct wc_rng_bank_inst *ret; word32 flags = @@ -1095,12 +1118,6 @@ static struct wc_rng_bank_inst *linuxkm_get_drbg(struct crypto_rng *tfm) { WC_RNG_BANK_FLAG_CAN_WAIT | WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST; - /* check for mismatched handler. */ - if (tfm->base.__crt_alg->cra_init != wc_linuxkm_drbg_init_tfm) { - pr_err("BUG: linuxkm_get_drbg() called on foreign tfm.\n"); - return NULL; - } - if (preempt_count() == 0) flags |= WC_RNG_BANK_FLAG_AFFINITY_LOCK; else @@ -1117,8 +1134,7 @@ static struct wc_rng_bank_inst *linuxkm_get_drbg(struct crypto_rng *tfm) { return ret; } -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); +static void linuxkm_put_drbg(struct wc_rng_bank *ctx, struct wc_rng_bank_inst **drbg) { int ret = wc_rng_bank_checkin(ctx, drbg); if (ret != 0) { pr_err("ERROR: wc_rng_bank_checkin() in linuxkm_put_drbg() returned err %d.\n", ret); @@ -1140,48 +1156,22 @@ int wc_linux_kernel_rng_is_wolfcrypt(struct crypto_rng *rng) { } } -static inline struct crypto_rng *get_crypto_default_rng(void) { - struct crypto_rng *current_crypto_default_rng = crypto_default_rng; - - if (unlikely(! current_crypto_default_rng)) { - pr_warn("BUG: get_default_drbg_ctx() called with NULL crypto_default_rng."); - return NULL; - } - - if (unlikely(! wc_linuxkm_drbg_default_instance_registered)) { - pr_warn("BUG: get_default_drbg_ctx() called without wc_linuxkm_drbg_default_instance_registered."); - return NULL; - } - - /* note we can't call crypto_get_default_rng(), because it uses a mutex - * (not allowed in interrupt handlers). we do however sanity-check the - * cra_init function pointer, and these handlers are protected by - * random_bytes_cb_refcnt in the patched drivers/char/random.c. - */ - - if (current_crypto_default_rng->base.__crt_alg->cra_init != wc_linuxkm_drbg_init_tfm) { - pr_err("BUG: get_default_drbg_ctx() found wrong crypto_default_rng \"%s\"\n", crypto_tfm_alg_driver_name(¤t_crypto_default_rng->base)); - return NULL; - } - - 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) { - int ret; - struct crypto_rng *current_crypto_default_rng = get_crypto_default_rng(); - if (current_crypto_default_rng == NULL) { - pr_warn_once("WARNING: get_crypto_default_rng() failed in linuxkm_InitRng_DefaultRef(); falling through to wc_InitRng().\n"); - return wc_InitRng(rng); + struct wc_rng_bank *ctx; + int ret = wc_rng_bank_default_checkout(&ctx); + + if (ret == 0) { + ret = wc_InitRng_BankRef(ctx, rng); + (void)wc_rng_bank_default_checkin(&ctx); + return ret; } else { - struct wc_rng_bank *default_bank = (struct wc_rng_bank *)crypto_rng_ctx(current_crypto_default_rng); - ret = wc_InitRng_BankRef(default_bank, rng); - return ret; + pr_warn_once("WARNING: linuxkm_InitRng_DefaultRef() called with null default_wc_rng_bank; falling through to wc_InitRng().\n"); + return wc_InitRng(rng); } __builtin_unreachable(); @@ -1190,12 +1180,12 @@ WC_MAYBE_UNUSED static int linuxkm_InitRng_DefaultRef(WC_RNG* rng) { #endif /* LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT && HAVE_HASHDRBG */ -static int wc_linuxkm_drbg_generate(struct crypto_rng *tfm, - const u8 *src, unsigned int slen, - u8 *dst, unsigned int dlen) +static int wc_linuxkm_drbg_generate(struct wc_rng_bank *ctx, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int dlen) { int ret, retried = 0; - struct wc_rng_bank_inst *drbg = linuxkm_get_drbg(tfm); + struct wc_rng_bank_inst *drbg = linuxkm_get_drbg(ctx); if (! drbg) { pr_err_once("BUG: linuxkm_get_drbg() failed."); @@ -1239,7 +1229,7 @@ static int wc_linuxkm_drbg_generate(struct crypto_rng *tfm, retried = 1; - ret = wc_rng_bank_inst_reinit((struct wc_rng_bank *)crypto_rng_ctx(tfm), + ret = wc_rng_bank_inst_reinit(ctx, drbg, WC_LINUXKM_INITRNG_TIMEOUT_SEC, WC_RNG_BANK_FLAG_CAN_WAIT); @@ -1263,23 +1253,30 @@ static int wc_linuxkm_drbg_generate(struct crypto_rng *tfm, out: - linuxkm_put_drbg(tfm, &drbg); + linuxkm_put_drbg(ctx, &drbg); return ret; } -static int wc_linuxkm_drbg_seed(struct crypto_rng *tfm, - const u8 *seed, unsigned int slen) +static int wc_linuxkm_drbg_generate_tfm(struct crypto_rng *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int dlen) { - struct wc_rng_bank *ctx = (struct wc_rng_bank *)crypto_rng_ctx(tfm); - int ret; - if (tfm->base.__crt_alg->cra_init != wc_linuxkm_drbg_init_tfm) { pr_err_once("BUG: mismatched tfm."); return -EFAULT; } + return wc_linuxkm_drbg_generate((struct wc_rng_bank *)crypto_rng_ctx(tfm), + src, slen, dst, dlen); +} + +static int wc_linuxkm_drbg_seed(struct wc_rng_bank *ctx, + const u8 *seed, unsigned int slen) +{ + int ret; + if (slen == 0) return 0; @@ -1292,9 +1289,22 @@ static int wc_linuxkm_drbg_seed(struct crypto_rng *tfm, return ret; } +static int wc_linuxkm_drbg_seed_tfm(struct crypto_rng *tfm, + const u8 *seed, unsigned int slen) +{ + if (tfm->base.__crt_alg->cra_init != wc_linuxkm_drbg_init_tfm) + { + pr_err_once("BUG: mismatched tfm."); + return -EFAULT; + } + + return wc_linuxkm_drbg_seed((struct wc_rng_bank *)crypto_rng_ctx(tfm), + seed, slen); +} + static struct rng_alg wc_linuxkm_drbg = { - .generate = wc_linuxkm_drbg_generate, - .seed = wc_linuxkm_drbg_seed, + .generate = wc_linuxkm_drbg_generate_tfm, + .seed = wc_linuxkm_drbg_seed_tfm, .seedsize = 0, .base = { .cra_name = WOLFKM_STDRNG_NAME, @@ -1329,26 +1339,22 @@ static int wc_linuxkm_drbg_loaded = 0; #ifdef WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS -static inline struct wc_rng_bank *get_default_drbg_ctx(void) { - struct crypto_rng *current_crypto_default_rng = get_crypto_default_rng(); - struct wc_rng_bank *ctx = (current_crypto_default_rng ? (struct wc_rng_bank *)crypto_rng_ctx(current_crypto_default_rng) : NULL); - if (ctx && (! ctx->rngs)) { - pr_err_once("BUG: get_default_drbg_ctx() found null ctx->rngs."); - return NULL; - } - else - return ctx; -} - static int wc__get_random_bytes(void *buf, size_t len) { - struct crypto_rng *current_crypto_default_rng = get_crypto_default_rng(); - if (! current_crypto_default_rng) + struct wc_rng_bank *current_default_wc_rng_bank; + int ret = wc_rng_bank_default_checkout(¤t_default_wc_rng_bank); + if (ret) { +#ifdef WC_VERBOSE_RNG + pr_err_ratelimited("ERROR: wc_rng_bank_default_checkout() in wc__get_random_bytes() returned %d.\n", ret); +#endif return -EFAULT; + } else { - int ret = crypto_rng_get_bytes(current_crypto_default_rng, buf, len); + ret = wc_linuxkm_drbg_generate(current_default_wc_rng_bank, + NULL, 0, buf, len); + (void)wc_rng_bank_default_checkin(¤t_default_wc_rng_bank); if (ret) { - pr_warn("BUG: wc_get_random_bytes falling through to native get_random_bytes with wc_linuxkm_drbg_default_instance_registered, ret=%d.", ret); + pr_warn("BUG: wc__get_random_bytes falling through to native get_random_bytes with wc_linuxkm_drbg_default_instance_registered, ret=%d.", ret); } return ret; } @@ -1357,21 +1363,27 @@ static int wc__get_random_bytes(void *buf, size_t len) /* used by kernel >=5.14.0 */ static ssize_t wc_get_random_bytes_user(struct iov_iter *iter) { - struct crypto_rng *current_crypto_default_rng; + struct wc_rng_bank *current_default_wc_rng_bank; + int ret; if (unlikely(!iov_iter_count(iter))) return 0; - current_crypto_default_rng = get_crypto_default_rng(); - if (! current_crypto_default_rng) + + ret = wc_rng_bank_default_checkout(¤t_default_wc_rng_bank); + if (ret) { +#ifdef WC_VERBOSE_RNG + pr_err_ratelimited("ERROR: wc_rng_bank_default_checkout() in wc_get_random_bytes_user() returned %d.\n", ret); +#endif return -ECANCELED; + } else { - ssize_t ret; size_t this_copied, total_copied = 0; byte block[WC_SHA256_BLOCK_SIZE]; for (;;) { - ret = (ssize_t)crypto_rng_get_bytes(current_crypto_default_rng, block, sizeof block); + ret = wc_linuxkm_drbg_generate(current_default_wc_rng_bank, + NULL, 0, block, sizeof block); if (unlikely(ret != 0)) { - pr_err("ERROR: wc_get_random_bytes_user() crypto_rng_get_bytes() returned %ld.", ret); + pr_err("ERROR: wc_get_random_bytes_user() wc_linuxkm_drbg_generate() returned %d.", ret); break; } @@ -1392,6 +1404,8 @@ static ssize_t wc_get_random_bytes_user(struct iov_iter *iter) { } } + (void)wc_rng_bank_default_checkin(¤t_default_wc_rng_bank); + ForceZero(block, sizeof(block)); if (total_copied == 0) { @@ -1411,21 +1425,27 @@ static ssize_t wc_get_random_bytes_user(struct iov_iter *iter) { /* used by kernel 4.9.0-5.13.x */ static ssize_t wc_extract_crng_user(void __user *buf, size_t nbytes) { - struct crypto_rng *current_crypto_default_rng; + int ret; + struct wc_rng_bank *current_default_wc_rng_bank; if (unlikely(!nbytes)) return 0; - current_crypto_default_rng = get_crypto_default_rng(); - if (! current_crypto_default_rng) + + ret = wc_rng_bank_default_checkout(¤t_default_wc_rng_bank); + if (ret) { +#ifdef WC_VERBOSE_RNG + pr_err_ratelimited("ERROR: wc_rng_bank_default_checkout() in wc_extract_crng_user() returned %d.\n", ret); +#endif return -ECANCELED; + } else { - ssize_t ret; size_t this_copied, total_copied = 0; byte block[WC_SHA256_BLOCK_SIZE]; for (;;) { - ret = (ssize_t)crypto_rng_get_bytes(current_crypto_default_rng, block, sizeof block); + ret = wc_linuxkm_drbg_generate(current_default_wc_rng_bank, + NULL, 0, block, sizeof block); if (unlikely(ret != 0)) { - pr_err("ERROR: wc_extract_crng_user() crypto_rng_get_bytes() returned %ld.", ret); + pr_err("ERROR: wc_extract_crng_user() wc_linuxkm_drbg_generate() returned %d.", ret); break; } @@ -1446,6 +1466,8 @@ static ssize_t wc_extract_crng_user(void __user *buf, size_t nbytes) { } } + (void)wc_rng_bank_default_checkin(¤t_default_wc_rng_bank); + ForceZero(block, sizeof(block)); if ((total_copied == 0) && (ret == 0)) { @@ -1461,6 +1483,7 @@ static ssize_t wc_extract_crng_user(void __user *buf, size_t nbytes) { } static int wc_mix_pool_bytes(const void *buf, size_t len) { + int ret; struct wc_rng_bank *ctx; size_t i; int n; @@ -1469,8 +1492,15 @@ static int wc_mix_pool_bytes(const void *buf, size_t len) { if (len == 0) return 0; - if (! (ctx = get_default_drbg_ctx())) + ret = wc_rng_bank_default_checkout(&ctx); + if (ret) { +#ifdef WC_VERBOSE_RNG + pr_err_ratelimited("ERROR: wc_rng_bank_default_checkout() in wc_mix_pool_bytes() returned %d.\n", ret); +#endif return -EFAULT; + } + + ret = 0; for (n = ctx->n_rngs - 1; n >= 0; --n) { struct wc_rng_bank_inst *drbg; @@ -1488,19 +1518,30 @@ static int wc_mix_pool_bytes(const void *buf, size_t len) { wc_rng_bank_checkin(ctx, &drbg); if (can_sleep) { - if (signal_pending(current)) - return -EINTR; + if (signal_pending(current)) { + ret = -EINTR; + break; + } cond_resched(); } } - return 0; + (void)wc_rng_bank_default_checkin(&ctx); + + return ret; } static int wc_crng_reseed(void) { - struct wc_rng_bank *ctx = get_default_drbg_ctx(); + struct wc_rng_bank *ctx; int can_sleep = (preempt_count() == 0); - int ret; + int ret = wc_rng_bank_default_checkout(&ctx); + + if (ret) { +#ifdef WC_VERBOSE_RNG + pr_err_ratelimited("ERROR: wc_rng_bank_default_checkout() in wc_crng_reseed() returned %d.\n", ret); +#endif + return -EFAULT; + } ret = wc_rng_bank_reseed(ctx, WC_LINUXKM_INITRNG_TIMEOUT_SEC, can_sleep @@ -1508,6 +1549,9 @@ static int wc_crng_reseed(void) { WC_RNG_BANK_FLAG_CAN_WAIT : WC_RNG_BANK_FLAG_NONE); + + (void)wc_rng_bank_default_checkin(&ctx); + if (ret != 0) { pr_err("ERROR: wc_rng_bank_reseed() returned err %d.\n", ret); return -EINVAL; @@ -1710,12 +1754,15 @@ static int wc_get_random_bytes_user_kretprobe_installed = 0; #endif /* LINUXKM_DRBG_GET_RANDOM_BYTES */ +#if defined(LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)) +static struct wc_rng_bank default_bank; +static int default_bank_inited; +#endif + static int wc_linuxkm_drbg_startup(void) { int ret; -#ifdef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT - int cur_refcnt; -#endif if (wc_linuxkm_drbg_loaded) { pr_err("ERROR: wc_linuxkm_drbg_set_default called with wc_linuxkm_drbg_loaded."); @@ -1824,27 +1871,33 @@ static int wc_linuxkm_drbg_startup(void) /* for the default RNG, make sure we don't cache an underlying SHA256 * method that uses vector insns (forbidden from irq handlers). */ - wc_linuxkm_drbg_init_tfm_disable_vector_registers = 1; + wc_linuxkm_rng_initing_default_bank_flag = 1; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(7, 1, 0) + ret = crypto_del_default_rng(); if (ret) { - wc_linuxkm_drbg_init_tfm_disable_vector_registers = 0; + wc_linuxkm_rng_initing_default_bank_flag = 0; pr_err("ERROR: crypto_del_default_rng returned %d", ret); return ret; } + ret = crypto_get_default_rng(); - wc_linuxkm_drbg_init_tfm_disable_vector_registers = 0; + wc_linuxkm_rng_initing_default_bank_flag = 0; if (ret) { pr_err("ERROR: crypto_get_default_rng returned %d", ret); return ret; } - cur_refcnt = WC_LKM_REFCOUNT_TO_INT(wc_linuxkm_drbg.base.cra_refcnt); - if (cur_refcnt < 2) { - pr_err("ERROR: wc_linuxkm_drbg refcnt = %d after crypto_get_default_rng()", cur_refcnt); - crypto_put_default_rng(); - return -EINVAL; + { + int cur_refcnt = WC_LKM_REFCOUNT_TO_INT(wc_linuxkm_drbg.base.cra_refcnt); + if (cur_refcnt < 2) { + pr_err("ERROR: wc_linuxkm_drbg refcnt = %d after crypto_get_default_rng()", cur_refcnt); + crypto_put_default_rng(); + return -EINVAL; + } } if (! crypto_default_rng) { @@ -1860,6 +1913,66 @@ static int wc_linuxkm_drbg_startup(void) } crypto_put_default_rng(); + +#else /* >= 7.1.0 */ + +#ifdef CONFIG_CRYPTO_FIPS + if (fips_enabled) { + char buf[16]; + + ret = crypto_del_default_rng(); + if (ret) { + wc_linuxkm_rng_initing_default_bank_flag = 0; + pr_err("ERROR: crypto_del_default_rng returned %d", ret); + return ret; + } + + ret = __crypto_stdrng_get_bytes(buf, (unsigned int)sizeof buf); + + wc_linuxkm_rng_initing_default_bank_flag = 0; + + if (ret) { + pr_err("ERROR: __crypto_stdrng_get_bytes returned %d", ret); + return ret; + } + } + else +#endif /* CONFIG_CRYPTO_FIPS */ + { + ret = wc_linuxkm_rng_bank_init(&default_bank); + wc_linuxkm_rng_initing_default_bank_flag = 0; + if (ret) { + pr_err("ERROR: wc_linuxkm_rng_bank_init returned %d", ret); + return ret; + } + default_bank_inited = 1; + } + +#endif /* >= 7.1.0 */ + + { + struct wc_rng_bank *current_default_wc_rng_bank; + ret = wc_rng_bank_default_checkout(¤t_default_wc_rng_bank); + if (ret) + pr_err("ERROR: wc_rng_bank_default_checkout() after default stdrng registration returned %d", ret); + else { + ret = wc_rng_bank_default_checkin(¤t_default_wc_rng_bank); + if (ret) + pr_err("ERROR: wc_rng_bank_default_checkin() after wc_rng_bank_default_checkout() returned %d", ret); + } + if (ret != 0) { +#if defined(LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)) + if (default_bank_inited) { + (void)wc_rng_bank_default_clear(&default_bank); + (void)wc_rng_bank_fini(&default_bank); + default_bank_inited = 0; + } +#endif + return -ECANCELED; + } + } + wc_linuxkm_drbg_default_instance_registered = 1; pr_info("%s registered as systemwide default stdrng.", wc_linuxkm_drbg.base.cra_driver_name); pr_info("libwolfssl: to unload module, first echo 1 > /sys/module/libwolfssl/deinstall_algs"); @@ -1999,11 +2112,36 @@ static int wc_linuxkm_drbg_cleanup(void) { #endif /* LINUXKM_DRBG_GET_RANDOM_BYTES */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(7, 1, 0) ret = crypto_del_default_rng(); if (ret) { pr_err("ERROR: crypto_del_default_rng failed: %d", ret); return ret; } +#else /* >= 7.1.0 */ + +#ifdef CONFIG_CRYPTO_FIPS + if (fips_enabled) { + ret = crypto_del_default_rng(); + if (ret) { + pr_err("ERROR: crypto_del_default_rng failed: %d", ret); + return ret; + } + } + else +#endif /* CONFIG_CRYPTO_FIPS */ + if (default_bank_inited) { + ret = wc_rng_bank_default_clear(&default_bank); + if (ret) + pr_err("ERROR: wc_rng_bank_default_clear in wc_linuxkm_drbg_cleanup failed: %d", ret); + else { + ret = wc_rng_bank_fini(&default_bank); + if (ret) + pr_err("ERROR: wc_rng_bank_fini in wc_linuxkm_drbg_cleanup failed: %d", ret); + } + default_bank_inited = 0; + } +#endif /* >= 7.1.0 */ wc_linuxkm_drbg_default_instance_registered = 0; } diff --git a/tests/api.c b/tests/api.c index 8f561b0648..879c941b97 100644 --- a/tests/api.c +++ b/tests/api.c @@ -27475,7 +27475,7 @@ static int error_test(void) { EXPECT_DECLS; const char* errStr; - const char* unknownStr = wc_GetErrorString(0); + const char* unknownStr = wc_GetErrorString(WC_LAST_E - 1); #ifdef NO_ERROR_STRINGS /* Ensure a valid error code's string matches an invalid code's. diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index 431a3c996c..4e02795e89 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -37,6 +37,9 @@ const char* wc_GetErrorString(int error) { switch ((enum wolfCrypt_ErrorCodes)error) { + case WC_SUCCESS: + return "wolfCrypt generic success"; + case WC_FAILURE: return "wolfCrypt generic failure"; diff --git a/wolfcrypt/src/rng_bank.c b/wolfcrypt/src/rng_bank.c index fe87d86539..3cea1c7520 100644 --- a/wolfcrypt/src/rng_bank.c +++ b/wolfcrypt/src/rng_bank.c @@ -187,6 +187,8 @@ WOLFSSL_API int wc_rng_bank_fini(struct wc_rng_bank *ctx) { if (wolfSSL_RefCur(ctx->refcount) > 1) return BUSY_E; + else if (wolfSSL_RefCur(ctx->refcount) < 1) + return BAD_STATE_E; #ifndef WC_RNG_BANK_STATIC if (ctx->rngs) @@ -247,6 +249,123 @@ WOLFSSL_API int wc_rng_bank_free(struct wc_rng_bank **ctx) { } #endif /* !WC_RNG_BANK_STATIC */ +#ifdef WC_RNG_BANK_DEFAULT_SUPPORT + +/* The default_rng_bank facility is used by the Linux kernel module as a global + * resource for wc_rng_bank_checkout(), + * wc_local_rng_bank_checkout_for_bankref(), and wc_InitRng_BankRef(), and can + * be similarly used by any application, to cache DRBG seeding at application + * startup. + */ + +static struct wc_rng_bank * volatile default_rng_bank; + +WOLFSSL_API int wc_rng_bank_default_set(struct wc_rng_bank *bank) { + int ret; + struct wc_rng_bank *cur_default_rng_bank = NULL; + int new_refcount; + + if (bank == NULL) + return BAD_FUNC_ARG; + + if ((! (bank->flags & WC_RNG_BANK_FLAG_INITED)) || + (wolfSSL_RefCur(bank->refcount) < 1)) + { + return BAD_STATE_E; + } + + wolfSSL_RefInc2(&bank->refcount, &new_refcount, &ret); + if (ret != 0) + return ret; +#ifdef WC_VERBOSE_RNG + if (new_refcount < 2) + WOLFSSL_DEBUG_PRINTF( + "BUG: wc_rng_bank_default_set() new_refcount %d.\n", new_refcount); +#else + (void)new_refcount; +#endif + if (wolfSSL_Atomic_Ptr_CompareExchange((void * volatile *)&default_rng_bank, (void **)&cur_default_rng_bank, bank)) + return 0; + else { + wolfSSL_RefDec2(&bank->refcount, &new_refcount, &ret); +#ifdef WC_VERBOSE_RNG + if (new_refcount <= 0) + WOLFSSL_DEBUG_PRINTF( + "BUG: wc_rng_bank_default_set() cleanup popped refcount to %d.\n", new_refcount); +#else + (void)new_refcount; +#endif + return BUSY_E; + } +} + +/* Note wc_rng_bank_default_checkout() must not be called before + * wc_rng_bank_default_set() returns, or after wc_rng_bank_default_clear() is + * called -- it is the caller's responsibility to assure this. + */ +WOLFSSL_API int wc_rng_bank_default_checkout(struct wc_rng_bank **bank) { + int ret; + struct wc_rng_bank *cur_default_rng_bank = default_rng_bank; + if (bank == NULL) + return BAD_FUNC_ARG; + if (cur_default_rng_bank == NULL) + return BAD_STATE_E; + wolfSSL_RefInc(&cur_default_rng_bank->refcount, &ret); + if (ret == 0) + *bank = cur_default_rng_bank; + return ret; +} + +WOLFSSL_API int wc_rng_bank_default_checkin(struct wc_rng_bank **bank) { + int ret; + int new_refcount; + if ((bank == NULL) || (*bank == NULL)) + return BAD_FUNC_ARG; + wolfSSL_RefDec2(&(*bank)->refcount, &new_refcount, &ret); +#ifdef WC_VERBOSE_RNG + if (new_refcount <= 0) + WOLFSSL_DEBUG_PRINTF( + "BUG: wc_rng_bank_default_checkin() popped refcount to %d.\n", new_refcount); +#else + (void)new_refcount; +#endif + *bank = NULL; + return ret; +} + +/* Note, wc_rng_bank_default_clear() should only be called at module or + * application shutdown to avoid races with wc_rng_bank_default_checkout(), and + * must be called before wc_rng_bank_fini() on a bank previously passed to + * wc_rng_bank_default_set(). + */ +WOLFSSL_API int wc_rng_bank_default_clear(struct wc_rng_bank *bank) { + if ((bank != default_rng_bank) || (bank == NULL)) + return BAD_FUNC_ARG; + if (wolfSSL_Atomic_Ptr_CompareExchange((void * volatile *)&default_rng_bank, (void **)&bank, NULL)) { + int ret; + int new_refcount; + wolfSSL_RefDec2(&bank->refcount, &new_refcount, &ret); +#ifdef WC_VERBOSE_RNG + /* wc_rng_bank_fini() is the sole responsibility of the context that + * called wc_rng_bank_default_set() for this wc_rng_bank. + */ + if (new_refcount < 1) + WOLFSSL_DEBUG_PRINTF( + "BUG: wc_rng_bank_default_clear() popped refcount to %d.\n", new_refcount); + if (! (bank->flags & WC_RNG_BANK_FLAG_INITED)) + WOLFSSL_DEBUG_PRINTF( + "BUG: wc_rng_bank_default_clear() bank is already uninited.\n"); +#else + (void)new_refcount; +#endif + return ret; + } + else + return BUSY_E; +} + +#endif /* WC_RNG_BANK_DEFAULT_SUPPORT */ + /* 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 @@ -268,13 +387,23 @@ WOLFSSL_API int wc_rng_bank_checkout( time_t ts1, ts2; int n_rngs_tried = 0; +#ifdef WC_RNG_BANK_DEFAULT_SUPPORT + if (bank == NULL) + bank = default_rng_bank; +#endif + if ((bank == NULL) || - (! (bank->flags & WC_RNG_BANK_FLAG_INITED)) || (rng_inst == NULL)) { return BAD_FUNC_ARG; } + if ((! (bank->flags & WC_RNG_BANK_FLAG_INITED)) || + (wolfSSL_RefCur(bank->refcount) < 1)) + { + return BAD_STATE_E; + } + if ((flags & WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST) && (bank->affinity_get_id_cb == NULL)) { @@ -446,15 +575,46 @@ WOLFSSL_LOCAL int wc_local_rng_bank_checkout_for_bankref( } #endif /* WC_DRBG_BANKREF */ +static WC_INLINE int rng_inst_matches_bank( + struct wc_rng_bank *bank, + struct wc_rng_bank_inst *rng_inst) +{ + if ((bank == NULL) || (rng_inst == NULL)) + return BAD_FUNC_ARG; +#ifdef WC_RNG_BANK_STATIC + if ((rng_inst >= &bank->rngs[0]) && + (rng_inst <= &bank->rngs[WC_RNG_BANK_STATIC_SIZE - 1])) + return 1; + else + return BAD_FUNC_ARG; +#else + if ((rng_inst >= bank->rngs) && + (rng_inst <= bank->rngs + bank->n_rngs - 1)) + return 1; + else + return BAD_FUNC_ARG; +#endif +} + WOLFSSL_API int wc_rng_bank_checkin( struct wc_rng_bank *bank, struct wc_rng_bank_inst **rng_inst) { int lockval; + int ret; - if ((bank == NULL) || (rng_inst == NULL) || (*rng_inst == NULL)) + if (rng_inst == NULL) return BAD_FUNC_ARG; +#ifdef WC_RNG_BANK_DEFAULT_SUPPORT + if (bank == NULL) + bank = default_rng_bank; +#endif + + ret = rng_inst_matches_bank(bank, *rng_inst); + if (ret < 0) + return ret; + lockval = (int)WOLFSSL_ATOMIC_LOAD((*rng_inst)->lock); WOLFSSL_ATOMIC_STORE((*rng_inst)->lock, WC_RNG_BANK_INST_LOCK_FREE); @@ -483,8 +643,16 @@ WOLFSSL_API int wc_rng_bank_inst_reinit( time_t ts1 = 0; int devId; - if ((rng_inst == NULL) || - (rng_inst->rng.drbg == NULL)) +#ifdef WC_RNG_BANK_DEFAULT_SUPPORT + if (bank == NULL) + bank = default_rng_bank; +#endif + + ret = rng_inst_matches_bank(bank, rng_inst); + if (ret < 0) + return BAD_FUNC_ARG; + + if (rng_inst->rng.drbg == NULL) { return BAD_FUNC_ARG; } @@ -538,6 +706,11 @@ WOLFSSL_API int wc_rng_bank_seed(struct wc_rng_bank *bank, int ret = 0; int n; +#ifdef WC_RNG_BANK_DEFAULT_SUPPORT + if (bank == NULL) + bank = default_rng_bank; +#endif + if ((bank == NULL) || (! (bank->flags & WC_RNG_BANK_FLAG_INITED))) { @@ -595,8 +768,16 @@ WOLFSSL_API int wc_rng_bank_reseed(struct wc_rng_bank *bank, int ret; time_t ts1 = 0; - if (! bank) +#ifdef WC_RNG_BANK_DEFAULT_SUPPORT + if (bank == NULL) + bank = default_rng_bank; +#endif + + if ((bank == NULL) || + (! (bank->flags & WC_RNG_BANK_FLAG_INITED))) + { return BAD_FUNC_ARG; + } if (flags & (WC_RNG_BANK_FLAG_CAN_FAIL_OVER_INST | WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST)) @@ -667,13 +848,23 @@ WOLFSSL_API int wc_InitRng_BankRef(struct wc_rng_bank *bank, WC_RNG *rng) { int ret; +#ifdef WC_RNG_BANK_DEFAULT_SUPPORT + if (bank == NULL) + bank = default_rng_bank; +#endif + if ((bank == NULL) || - (! (bank->flags & WC_RNG_BANK_FLAG_INITED)) || (rng == NULL)) { return BAD_FUNC_ARG; } + if ((! (bank->flags & WC_RNG_BANK_FLAG_INITED)) || + (wolfSSL_RefCur(bank->refcount) < 1)) + { + return BAD_STATE_E; + } + XMEMSET(rng, 0, sizeof(*rng)); wolfSSL_RefInc(&bank->refcount, &ret); @@ -712,13 +903,23 @@ WOLFSSL_API int wc_BankRef_Release(WC_RNG *rng) WOLFSSL_API int wc_rng_new_bankref(struct wc_rng_bank *bank, WC_RNG **rng) { int ret; +#ifdef WC_RNG_BANK_DEFAULT_SUPPORT + if (bank == NULL) + bank = default_rng_bank; +#endif + if ((bank == NULL) || - (! (bank->flags & WC_RNG_BANK_FLAG_INITED)) || (rng == NULL)) { return BAD_FUNC_ARG; } + if ((! (bank->flags & WC_RNG_BANK_FLAG_INITED)) || + (wolfSSL_RefCur(bank->refcount) < 1)) + { + return BAD_STATE_E; + } + *rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), bank->heap, DYNAMIC_TYPE_RNG); if (*rng == NULL) { return MEMORY_E; diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index db4e5a5399..92283abdfe 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -1835,6 +1835,21 @@ void wolfSSL_RefWithMutexInc(wolfSSL_RefWithMutex* ref, int* err) *err = ret; } +void wolfSSL_RefWithMutexInc2(wolfSSL_RefWithMutex* ref, int *new_count, + int* err) +{ + int ret = wc_LockMutex(&ref->mutex); + if (ret != 0) { + WOLFSSL_MSG("Failed to lock mutex for reference increment!"); + *new_count = -1; + } + else { + *new_count = ++ref->count; + wc_UnLockMutex(&ref->mutex); + } + *err = ret; +} + int wolfSSL_RefWithMutexLock(wolfSSL_RefWithMutex* ref) { return wc_LockMutex(&ref->mutex); @@ -1862,6 +1877,24 @@ void wolfSSL_RefWithMutexDec(wolfSSL_RefWithMutex* ref, int* isZero, int* err) } *err = ret; } + +void wolfSSL_RefWithMutexDec2(wolfSSL_RefWithMutex* ref, int* new_count, + int* err) +{ + int ret = wc_LockMutex(&ref->mutex); + if (ret != 0) { + WOLFSSL_MSG("Failed to lock mutex for reference decrement!"); + *new_count = -1; + } + else { + if (ref->count > 0) { + ref->count--; + } + *new_count = ref->count; + wc_UnLockMutex(&ref->mutex); + } + *err = ret; +} #endif /* ! SINGLE_THREADED */ #if WOLFSSL_CRYPT_HW_MUTEX diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 755aa94358..ab6f3b4816 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -3682,7 +3682,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t error_test(void) { const char* errStr; char out[WOLFSSL_MAX_ERROR_SZ]; /* test fails if too small, < 64 */ - const char* unknownStr = wc_GetErrorString(0); + const char* unknownStr = wc_GetErrorString((int)WC_LAST_E - 1); #ifdef NO_ERROR_STRINGS /* Ensure a valid error code's string matches an invalid code's. @@ -21066,6 +21066,13 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + { + struct wc_rng_bank_inst *bogus_inst = (struct wc_rng_bank_inst *)(wc_ptr_t)bank; + ret = wc_rng_bank_checkin(bank, &bogus_inst); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + } + ret = wc_rng_bank_checkin(bank, &rng_inst); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); @@ -21104,6 +21111,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) ERROR_OUT(WC_TEST_RET_ENC_NC, out); #ifdef WC_DRBG_BANKREF + ret = wc_InitRng_BankRef(NULL, rng); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + + ret = wc_InitRng_BankRef(bank, NULL); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_InitRng_BankRef(bank, rng); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); @@ -21117,6 +21132,10 @@ 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(NULL, 10, WC_RNG_BANK_FLAG_NONE); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_rng_bank_reseed(bank, 10, WC_RNG_BANK_FLAG_NONE); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); @@ -21180,6 +21199,10 @@ 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_seed(NULL, (byte *)bank_arg, (word32)sizeof(bank_arg), 10, WC_RNG_BANK_FLAG_CAN_WAIT); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + 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); @@ -21199,6 +21222,15 @@ 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(NULL, rng_inst, 10, WC_RNG_BANK_FLAG_CAN_WAIT); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + + /* bogus pointer test */ + ret = wc_rng_bank_inst_reinit(bank, (struct wc_rng_bank_inst *)(wc_ptr_t)bank, 10, WC_RNG_BANK_FLAG_CAN_WAIT); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), 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); @@ -21210,10 +21242,18 @@ 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_checkin(NULL, &rng_inst); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), 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_checkout(NULL, &rng_inst, -1, 10, WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST | WC_RNG_BANK_FLAG_AFFINITY_LOCK); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + 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); @@ -21228,6 +21268,70 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) ERROR_OUT(WC_TEST_RET_ENC_NC, out); #endif +#ifdef WC_RNG_BANK_DEFAULT_SUPPORT + + ret = wc_rng_bank_default_clear(NULL); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + + ret = wc_rng_bank_default_clear(bank); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + + ret = wc_rng_bank_default_set(bank); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + + /* When gated in, passing a NULL bank arg to wc_rng_bank_checkout(), + * wc_rng_bank_checkin(), wc_rng_bank_inst_reinit(), wc_rng_bank_seed(), + * wc_rng_bank_reseed(), wc_InitRng_BankRef(), or wc_rng_new_bankref() + * implicitly designates the default bank. + */ + ret = wc_rng_bank_checkout(NULL, &rng_inst, 3, 10, WC_RNG_BANK_FLAG_NONE); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + if (rng_inst != bank->rngs + 3) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); + + ret = wc_rng_bank_inst_reinit(NULL, rng_inst, 10, WC_RNG_BANK_FLAG_CAN_WAIT); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + +#ifdef WC_DRBG_BANKREF + ret = wc_InitRng_BankRef(NULL, rng); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + wc_FreeRng(rng); + +#ifndef WC_RNG_BANK_STATIC + ret = wc_rng_new_bankref(NULL, &rng2); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + + wc_rng_free(rng2); + rng2 = NULL; +#endif + +#endif + + ret = wc_rng_bank_checkin(NULL, &rng_inst); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + + ret = wc_rng_bank_seed(NULL, (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_reseed(NULL, 10, WC_RNG_BANK_FLAG_NONE); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + + ret = wc_rng_bank_default_clear(bank); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + +#endif /* WC_RNG_BANK_DEFAULT_SUPPORT */ + #ifdef WC_RNG_BANK_STATIC ret = 0; @@ -21319,6 +21423,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); #ifdef WC_DRBG_BANKREF + ret = wc_rng_new_bankref(NULL, &rng2); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + + ret = wc_rng_new_bankref(bank2, NULL); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_rng_new_bankref(bank2, &rng2); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index db5530045a..40962ee084 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -46,6 +46,7 @@ enum wolfCrypt_ErrorCodes { /* note that WOLFSSL_FATAL_ERROR is defined as -1 in error-ssl.h, for * reasons of backward compatibility. */ + WC_SUCCESS = 0, WC_FAILURE = -1, /* Generic but traceable back compat errcode. * Note, not reflected in MAX_CODE_E or * WC_FIRST_E. diff --git a/wolfssl/wolfcrypt/rng_bank.h b/wolfssl/wolfcrypt/rng_bank.h index bd74fcf63e..d26b41a5e5 100644 --- a/wolfssl/wolfcrypt/rng_bank.h +++ b/wolfssl/wolfcrypt/rng_bank.h @@ -121,6 +121,18 @@ WOLFSSL_API int wc_rng_bank_fini(struct wc_rng_bank *ctx); WOLFSSL_API int wc_rng_bank_free(struct wc_rng_bank **ctx); #endif +#ifdef WC_RNG_BANK_NO_DEFAULT_SUPPORT +#undef WC_RNG_BANK_DEFAULT_SUPPORT +#else /* !WC_RNG_BANK_NO_DEFAULT_SUPPORT */ +#ifndef WC_RNG_BANK_DEFAULT_SUPPORT +#define WC_RNG_BANK_DEFAULT_SUPPORT +#endif +WOLFSSL_API int wc_rng_bank_default_set(struct wc_rng_bank *bank); +WOLFSSL_API int wc_rng_bank_default_checkout(struct wc_rng_bank **bank); +WOLFSSL_API int wc_rng_bank_default_checkin(struct wc_rng_bank **bank); +WOLFSSL_API int wc_rng_bank_default_clear(struct wc_rng_bank *bank); +#endif /* !WC_RNG_BANK_NO_DEFAULT_SUPPORT */ + WOLFSSL_API int wc_rng_bank_checkout( struct wc_rng_bank *bank, struct wc_rng_bank_inst **rng_inst, diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index 011a852bee..ade6b6c1da 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -675,7 +675,7 @@ } } static WC_INLINE int wolfSSL_Atomic_Ptr_CompareExchange( - void * volatile *c, void *expected_ptr, void *new_ptr) + void * volatile *c, void **expected_ptr, void *new_ptr) { if (*(char * volatile *)c == *(char **)expected_ptr) { *(char * volatile *)c = (char *)new_ptr; @@ -758,6 +758,11 @@ typedef struct wolfSSL_RefWithMutex wolfSSL_Ref; (void)wolfSSL_Atomic_Int_FetchAdd(&(ref)->count, 1); \ *(err) = 0; \ } while(0) +#define wolfSSL_RefInc2(ref, new_count, err) \ + do { \ + *(new_count) = wolfSSL_Atomic_Int_AddFetch(&(ref)->count, 1); \ + *(err) = 0; \ + } while(0) #define wolfSSL_RefDec(ref, isZero, err) \ do { \ int __prev = wolfSSL_Atomic_Int_FetchSub(&(ref)->count, 1); \ @@ -765,6 +770,11 @@ typedef struct wolfSSL_RefWithMutex wolfSSL_Ref; *(isZero) = (__prev == 1); \ *(err) = 0; \ } while(0) +#define wolfSSL_RefDec2(ref, new_count, err) \ + do { \ + *(new_count) = wolfSSL_Atomic_Int_SubFetch(&(ref)->count, 1); \ + *(err) = 0; \ + } while(0) #else @@ -773,7 +783,9 @@ typedef struct wolfSSL_RefWithMutex wolfSSL_Ref; #define wolfSSL_RefInit wolfSSL_RefWithMutexInit #define wolfSSL_RefFree wolfSSL_RefWithMutexFree #define wolfSSL_RefInc wolfSSL_RefWithMutexInc +#define wolfSSL_RefInc2 wolfSSL_RefWithMutexInc2 #define wolfSSL_RefDec wolfSSL_RefWithMutexDec +#define wolfSSL_RefDec2 wolfSSL_RefWithMutexDec2 #endif @@ -782,9 +794,11 @@ typedef struct wolfSSL_RefWithMutex wolfSSL_Ref; #define wolfSSL_RefWithMutexInit wolfSSL_RefInit #define wolfSSL_RefWithMutexFree wolfSSL_RefFree #define wolfSSL_RefWithMutexInc wolfSSL_RefInc +#define wolfSSL_RefWithMutexInc2 wolfSSL_RefInc2 #define wolfSSL_RefWithMutexLock(ref) 0 #define wolfSSL_RefWithMutexUnlock(ref) 0 #define wolfSSL_RefWithMutexDec wolfSSL_RefDec +#define wolfSSL_RefWithMutexDec2 wolfSSL_RefDec2 #else @@ -793,10 +807,15 @@ WOLFSSL_LOCAL void wolfSSL_RefWithMutexInit(wolfSSL_RefWithMutex* ref, WOLFSSL_LOCAL void wolfSSL_RefWithMutexFree(wolfSSL_RefWithMutex* ref); WOLFSSL_LOCAL void wolfSSL_RefWithMutexInc(wolfSSL_RefWithMutex* ref, int* err); +WOLFSSL_LOCAL void wolfSSL_RefWithMutexInc2(wolfSSL_RefWithMutex* ref, + int *new_count, + int* err); WOLFSSL_LOCAL int wolfSSL_RefWithMutexLock(wolfSSL_RefWithMutex* ref); WOLFSSL_LOCAL int wolfSSL_RefWithMutexUnlock(wolfSSL_RefWithMutex* ref); WOLFSSL_LOCAL void wolfSSL_RefWithMutexDec(wolfSSL_RefWithMutex* ref, int* isZero, int* err); +WOLFSSL_LOCAL void wolfSSL_RefWithMutexDec2(wolfSSL_RefWithMutex* ref, + int* new_count, int* err); #endif