Bug 1376494 - don't initialise the deterministic rng twice, r=ttaubert
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Mon, 21 Aug 2017 11:56:13 +0200
changeset 13539 30c6078f307516729317acc64a0f969823db2cde
parent 13538 711b3866b2ce311baa27316c53aeeab6f7980e86
child 13540 0ca145683a7035d8c488ec59a2f11b1b9286b88e
push id2331
push userfranziskuskiefer@gmail.com
push dateMon, 21 Aug 2017 10:42:57 +0000
reviewersttaubert
bugs1376494
Bug 1376494 - don't initialise the deterministic rng twice, r=ttaubert Differential Revision: https://nss-review.dev.mozaws.net/D348
lib/freebl/det_rng.c
--- a/lib/freebl/det_rng.c
+++ b/lib/freebl/det_rng.c
@@ -3,36 +3,50 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "blapi.h"
 #include "blapit.h"
 #include "chacha20.h"
 #include "nssilock.h"
 #include "seccomon.h"
 #include "secerr.h"
+#include "prinit.h"
 
 #define GLOBAL_BYTES_SIZE 100
 static PRUint8 globalBytes[GLOBAL_BYTES_SIZE];
 static unsigned long globalNumCalls = 0;
 static PZLock *rng_lock = NULL;
+static PRCallOnceType coRNGInit;
+static const PRCallOnceType pristineCallOnce;
 
-SECStatus
-RNG_RNGInit(void)
+static PRStatus
+rng_init(void)
 {
     rng_lock = PZ_NewLock(nssILockOther);
     if (!rng_lock) {
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        return SECFailure;
+        return PR_FAILURE;
     }
     /* --- LOCKED --- */
     PZ_Lock(rng_lock);
     memset(globalBytes, 0, GLOBAL_BYTES_SIZE);
     PZ_Unlock(rng_lock);
     /* --- UNLOCKED --- */
 
+    return PR_SUCCESS;
+}
+
+SECStatus
+RNG_RNGInit(void)
+{
+    /* Allow only one call to initialize the context */
+    if (PR_CallOnce(&coRNGInit, rng_init) != PR_SUCCESS) {
+        return SECFailure;
+    }
+
     return SECSuccess;
 }
 
 /* Take min(size, GLOBAL_BYTES_SIZE) bytes from data and use as seed and reset
  * the rng state. */
 SECStatus
 RNG_RandomUpdate(const void *data, size_t bytes)
 {
@@ -92,18 +106,21 @@ RNG_GenerateGlobalRandomBytes(void *dest
     /* --- UNLOCKED --- */
 
     return SECSuccess;
 }
 
 void
 RNG_RNGShutdown(void)
 {
-    PZ_DestroyLock(rng_lock);
-    rng_lock = NULL;
+    if (rng_lock) {
+        PZ_DestroyLock(rng_lock);
+        rng_lock = NULL;
+    }
+    coRNGInit = pristineCallOnce;
 }
 
 /* Test functions are not implemented! */
 SECStatus
 PRNGTEST_Instantiate(const PRUint8 *entropy, unsigned int entropy_len,
                      const PRUint8 *nonce, unsigned int nonce_len,
                      const PRUint8 *personal_string, unsigned int ps_len)
 {