@@ -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. */
6363static 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,17 @@ int Entropy_Init(void)
851866 #if !defined(SINGLE_THREADED ) && !defined(WOLFSSL_MUTEX_INITIALIZER )
852867 ret = wc_InitMutex (& entropy_mutex );
853868 #endif
869+ ret = wc_LockMutex (& entropy_mutex );
870+
871+ if (entropy_memuse_initialized ) {
872+ /* Short circuit return -- a competing thread initialized the state
873+ * while we were waiting. Note, this is only threadsafe when
874+ * WOLFSSL_MUTEX_INITIALIZER is defined.
875+ */
876+ wc_UnLockMutex (& entropy_mutex );
877+ return 0 ;
878+ }
879+
854880 if (ret == 0 ) {
855881 /* Initialize a SHA3-256 object for use in entropy operations. */
856882 ret = wc_InitSha3_256 (& entropyHash , NULL , INVALID_DEVID );
@@ -872,6 +898,10 @@ int Entropy_Init(void)
872898 Entropy_StopThread ();
873899 #endif
874900 }
901+
902+ if (ret != WC_NO_ERR_TRACE (BAD_MUTEX_E )) {
903+ wc_UnLockMutex (& entropy_mutex );
904+ }
875905 }
876906
877907 return ret ;
0 commit comments