From 266a9eab5f9451fa0b9f69616feaa0bb7d506a76 Mon Sep 17 00:00:00 2001 From: Yosuke Shimizu Date: Tue, 4 Aug 2026 14:47:39 +0900 Subject: [PATCH] Lock globalRNGMutex in BN_rand, ECDH, EC25519 and AddSession --- src/pk.c | 22 ++++++++++++++++++++-- src/pk_ec.c | 47 ++++++++++++++++++++++++++++++++--------------- src/ssl_bn.c | 15 ++++++++++++--- src/ssl_sess.c | 18 ++++++++++++++++-- 4 files changed, 80 insertions(+), 22 deletions(-) diff --git a/src/pk.c b/src/pk.c index e18dfdc5079..b6a7d32625a 100644 --- a/src/pk.c +++ b/src/pk.c @@ -5187,6 +5187,11 @@ int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz, int res = 1; curve25519_key privkey; curve25519_key pubkey; +#ifdef WOLFSSL_CURVE25519_BLINDING + WC_RNG* rng = NULL; + WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0); + int initTmpRng = 0; +#endif WOLFSSL_ENTER("wolfSSL_EC25519_shared_key"); @@ -5206,8 +5211,13 @@ int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz, } if (res) { #ifdef WOLFSSL_CURVE25519_BLINDING - /* An RNG is needed. */ - if (wc_curve25519_set_rng(&privkey, wolfssl_make_global_rng()) != 0) { + /* An RNG is needed for blinding - create local or get global. */ + rng = wolfssl_make_rng(tmpRng, &initTmpRng); + if (rng == NULL) { + WOLFSSL_MSG("wolfSSL_EC25519_shared_key failed to make RNG"); + res = 0; + } + else if (wc_curve25519_set_rng(&privkey, rng) != 0) { res = 0; } else @@ -5250,6 +5260,14 @@ int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz, wc_curve25519_free(&privkey); } +#ifdef WOLFSSL_CURVE25519_BLINDING + /* Disposed of after privkey, which references it for blinding. */ + if (initTmpRng) { + wc_FreeRng(rng); + WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG); + } +#endif + return res; #else WOLFSSL_MSG("No Key Gen built in"); diff --git a/src/pk_ec.c b/src/pk_ec.c index 778478344ff..12d11c874a4 100644 --- a/src/pk_ec.c +++ b/src/pk_ec.c @@ -5489,7 +5489,10 @@ int wolfSSL_ECDH_compute_key(void *out, size_t outLen, ecc_key* key = NULL; #if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \ (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0)) - int setGlobalRNG = 0; + WC_RNG* rng = NULL; + WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0); + int initTmpRng = 0; + int setKeyRng = 0; #endif /* TODO: support using the KDF. */ @@ -5524,31 +5527,45 @@ int wolfSSL_ECDH_compute_key(void *out, size_t outLen, #if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \ (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0)) - /* An RNG is needed. */ + /* An RNG is needed - create local or get global. */ if (key->rng == NULL) { - key->rng = wolfssl_make_global_rng(); - /* RNG set and needs to be unset. */ - setGlobalRNG = 1; + rng = wolfssl_make_rng(tmpRng, &initTmpRng); + if (rng == NULL) { + WOLFSSL_MSG("wolfSSL_ECDH_compute_key failed to make RNG"); + err = 1; + } + else { + key->rng = rng; + /* RNG set and needs to be unset. */ + setKeyRng = 1; + } } #endif - PRIVATE_KEY_UNLOCK(); - /* Create secret using wolfSSL. */ - ret = wc_ecc_shared_secret_ex(key, (ecc_point*)pubKey->internal, - (byte *)out, &len); - PRIVATE_KEY_LOCK(); - if (ret != MP_OKAY) { - WOLFSSL_MSG("wc_ecc_shared_secret failed"); - err = 1; + if (!err) { + PRIVATE_KEY_UNLOCK(); + /* Create secret using wolfSSL. */ + ret = wc_ecc_shared_secret_ex(key, (ecc_point*)pubKey->internal, + (byte *)out, &len); + PRIVATE_KEY_LOCK(); + if (ret != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_shared_secret failed"); + err = 1; + } } } #if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \ (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0)) - /* Remove global from key. */ - if (setGlobalRNG) { + /* Clear before the RNG is disposed of - key must not keep a dangling + * reference to a local RNG. */ + if (setKeyRng) { key->rng = NULL; } + if (initTmpRng) { + wc_FreeRng(rng); + WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG); + } #endif if (err) { diff --git a/src/ssl_bn.c b/src/ssl_bn.c index 74d828da934..cb2c9b0f405 100644 --- a/src/ssl_bn.c +++ b/src/ssl_bn.c @@ -2146,11 +2146,20 @@ int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) WOLFSSL_MSG("Failed to allocate buffer."); ret = 0; } - /* Generate bytes to cover bits. */ - if ((ret == 1) && wc_RNG_GenerateBlock(rng, buff, len) != 0) { - WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); + /* Global RNG is shared, lock it while generating. */ + if ((ret == 1) && (wc_LockMutex(&globalRNGMutex) != 0)) { + WOLFSSL_MSG("Bad Lock Mutex rng"); ret = 0; } + + /* Generate bytes to cover bits. */ + if (ret == 1) { + if (wc_RNG_GenerateBlock(rng, buff, len) != 0) { + WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); + ret = 0; + } + wc_UnLockMutex(&globalRNGMutex); + } /* Read bytes in to big number. */ if ((ret == 1) && mp_read_unsigned_bin((mp_int*)bn->internal, buff, len) != MP_OKAY) { diff --git a/src/ssl_sess.c b/src/ssl_sess.c index cfc5eb48133..a12b56ae60f 100644 --- a/src/ssl_sess.c +++ b/src/ssl_sess.c @@ -2162,15 +2162,29 @@ void AddSession(WOLFSSL* ssl) * this point, it won't on resumption. */ if (idSz == 0 && ssl->options.side == WOLFSSL_CLIENT_END) { WC_RNG* rng = NULL; + int genRet; +#if defined(HAVE_GLOBAL_RNG) && defined(OPENSSL_EXTRA) + int rngLocked = 0; +#endif if (ssl->rng != NULL) rng = ssl->rng; #if defined(HAVE_GLOBAL_RNG) && defined(OPENSSL_EXTRA) else if (initGlobalRNG == 1 || wolfSSL_RAND_Init() == WOLFSSL_SUCCESS) { + /* Global RNG is shared, lock it while generating. */ + if (wc_LockMutex(&globalRNGMutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex rng"); + return; + } rng = &globalRNG; + rngLocked = 1; } #endif - if (wc_RNG_GenerateBlock(rng, ssl->session->altSessionID, - ID_LEN) != 0) + genRet = wc_RNG_GenerateBlock(rng, ssl->session->altSessionID, ID_LEN); +#if defined(HAVE_GLOBAL_RNG) && defined(OPENSSL_EXTRA) + if (rngLocked) + wc_UnLockMutex(&globalRNGMutex); +#endif + if (genRet != 0) return; ssl->session->haveAltSessionID = 1; id = ssl->session->altSessionID;