Make the fuzzer PRNG thread-safe.

We run some unit tests with multiple threads now. While that makes it no
longer deterministic, we should at least be thread-safe.

Change-Id: I5d75f2ff1ce76d0b7914cd6ea61bcf640aa085ab
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41184
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
diff --git a/crypto/rand_extra/deterministic.c b/crypto/rand_extra/deterministic.c
index 17fa71e..38cfd11 100644
--- a/crypto/rand_extra/deterministic.c
+++ b/crypto/rand_extra/deterministic.c
@@ -30,19 +30,23 @@
 // multi-threaded program, replace this with a thread-local. (A mutex would not
 // be deterministic.)
 static uint64_t g_num_calls = 0;
+static struct CRYPTO_STATIC_MUTEX g_num_calls_lock = CRYPTO_STATIC_MUTEX_INIT;
 
 void RAND_reset_for_fuzzing(void) { g_num_calls = 0; }
 
 void CRYPTO_sysrand(uint8_t *out, size_t requested) {
   static const uint8_t kZeroKey[32];
 
+  CRYPTO_STATIC_MUTEX_lock_write(&g_num_calls_lock);
+  uint64_t num_calls = g_num_calls++;
+  CRYPTO_STATIC_MUTEX_unlock_write(&g_num_calls_lock);
+
   uint8_t nonce[12];
   OPENSSL_memset(nonce, 0, sizeof(nonce));
-  OPENSSL_memcpy(nonce, &g_num_calls, sizeof(g_num_calls));
+  OPENSSL_memcpy(nonce, &num_calls, sizeof(num_calls));
 
   OPENSSL_memset(out, 0, requested);
   CRYPTO_chacha_20(out, out, requested, kZeroKey, nonce, 0);
-  g_num_calls++;
 }
 
 #endif  // BORINGSSL_UNSAFE_DETERMINISTIC_MODE