Skip to content

Commit d3f7455

Browse files
committed
wolfcrypt/src/wolfentropy.c: add volatile attribute to entropy_memuse_initialized declaration; in wc_Entropy_Get(), if HAVE_FIPS, call Entropy_Init() if necessary, to accommodate FIPS KATs; in Entropy_Init(), add thread safety.
1 parent 6f95a9c commit d3f7455

File tree

1 file changed

+33
-1
lines changed

1 file changed

+33
-1
lines changed

wolfcrypt/src/wolfentropy.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ data, use this implementation to seed and re-seed the DRBG.
5858
#define MAX_NOISE_CNT (MAX_ENTROPY_BITS * 8 + ENTROPY_EXTRA)
5959

6060
/* MemUse entropy global state initialized. */
61-
static int entropy_memuse_initialized = 0;
61+
static volatile int entropy_memuse_initialized = 0;
6262
/* Global SHA-3 object used for conditioning entropy and creating noise. */
6363
static wc_Sha3 entropyHash;
6464
/* Reset the health tests. */
@@ -740,6 +740,21 @@ int wc_Entropy_Get(int bits, unsigned char* entropy, word32 len)
740740
int noise_len = (bits + ENTROPY_EXTRA) / ENTROPY_MIN;
741741
static byte noise[MAX_NOISE_CNT];
742742

743+
#ifdef HAVE_FIPS
744+
/* FIPS KATs, e.g. EccPrimitiveZ_KnownAnswerTest(), call wc_Entropy_Get()
745+
* incidental to wc_InitRng(), without first calling Entropy_Init(), neither
746+
* directly, nor indirectly via wolfCrypt_Init(). This matters, because
747+
* KATs must be usable before wolfCrypt_Init() (indeed, in the library
748+
* embodiment, the HMAC KAT always runs before wolfCrypt_Init(), incidental
749+
* to fipsEntry()). Without the InitSha3() under Entropy_Init(), the
750+
* SHA3_BLOCK function pointer is null when Sha3Update() is called by
751+
* Entropy_MemUse(), which ends badly.
752+
*/
753+
if (!entropy_memuse_initialized) {
754+
ret = Entropy_Init();
755+
}
756+
#endif
757+
743758
/* Lock the mutex as collection uses globals. */
744759
if ((ret == 0) && (wc_LockMutex(&entropy_mutex) != 0)) {
745760
ret = BAD_MUTEX_E;
@@ -851,6 +866,19 @@ int Entropy_Init(void)
851866
#if !defined(SINGLE_THREADED) && !defined(WOLFSSL_MUTEX_INITIALIZER)
852867
ret = wc_InitMutex(&entropy_mutex);
853868
#endif
869+
if (ret == 0)
870+
ret = wc_LockMutex(&entropy_mutex);
871+
872+
if (entropy_memuse_initialized) {
873+
/* Short circuit return -- a competing thread initialized the state
874+
* while we were waiting. Note, this is only threadsafe when
875+
* WOLFSSL_MUTEX_INITIALIZER is defined.
876+
*/
877+
if (ret == 0)
878+
wc_UnLockMutex(&entropy_mutex);
879+
return 0;
880+
}
881+
854882
if (ret == 0) {
855883
/* Initialize a SHA3-256 object for use in entropy operations. */
856884
ret = wc_InitSha3_256(&entropyHash, NULL, INVALID_DEVID);
@@ -872,6 +900,10 @@ int Entropy_Init(void)
872900
Entropy_StopThread();
873901
#endif
874902
}
903+
904+
if (ret != WC_NO_ERR_TRACE(BAD_MUTEX_E)) {
905+
wc_UnLockMutex(&entropy_mutex);
906+
}
875907
}
876908

877909
return ret;

0 commit comments

Comments
 (0)