File nss-CC-drbg_fork_reseeds.patch of Package mozilla-nss.972

# HG changeset patch
# Parent  858d4927422479cf13bdd90a2557190d09d2c2d6
Reseed PRNG before giving out any random data after a fork()
Also see bsc#918112

diff --git a/lib/freebl/drbg.c b/lib/freebl/drbg.c
--- a/lib/freebl/drbg.c
+++ b/lib/freebl/drbg.c
@@ -15,16 +15,21 @@
 #include "blapii.h"
 #include "nssilock.h"
 #include "secitem.h"
 #include "sha_fast.h"
 #include "sha256.h"
 #include "secrng.h"	/* for RNG_SystemRNG() */
 #include "secmpi.h"
 
+#ifdef XP_UNIX
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
 /* PRNG_SEEDLEN defined in NIST SP 800-90 section 10.1 
  * for SHA-1, SHA-224, and SHA-256 it's 440 bits.
  * for SHA-384 and SHA-512 it's 888 bits */
 #define PRNG_SEEDLEN      (440/PR_BITS_PER_BYTE)
 static const PRInt64 PRNG_MAX_ADDITIONAL_BYTES = LL_INIT(0x1, 0x0);
 						/* 2^35 bits or 2^32 bytes */
 #define PRNG_MAX_REQUEST_SIZE 0x10000		/* 2^19 bits or 2^16 bytes */
 #define PRNG_ADDITONAL_DATA_CACHE_SIZE (8*1024) /* must be less than
@@ -101,16 +106,38 @@ struct RNGContextStr {
                                 * first generated random block, which is used
                                 * solely for continuous testing */
 };
 
 typedef struct RNGContextStr RNGContext;
 static RNGContext *globalrng = NULL;
 static RNGContext theGlobalRng;
 
+#ifdef XP_UNIX
+/* require PRNG reseed if the process has been recently forked */
+static pid_t myPid = 0;
+
+static PRBool
+prng_fork_reseed_needed(void)
+{
+    pid_t curPid;
+    PRBool retval = PR_FALSE;
+
+    if (myPid) {
+	curPid = getpid();
+	if (myPid != curPid) {
+	    myPid = curPid;
+	    retval = PR_TRUE;
+	}
+    } else {
+	myPid = getpid();
+    }
+    return retval;
+}
+#endif
 
 /*
  * The next several functions are derived from the NIST SP 800-90
  * spec. In these functions, an attempt was made to use names consistent
  * with the names in the spec, even if they differ from normal NSS usage.
  */
 
 /*
@@ -689,16 +716,23 @@ prng_GenerateGlobalRandomBytes(RNGContex
 
 /*
 ** Generate some random bytes, using the global random number generator
 ** object.
 */
 SECStatus 
 RNG_GenerateGlobalRandomBytes(void *dest, size_t len)
 {
+#ifdef XP_UNIX
+    SECStatus rv;
+    if (prng_fork_reseed_needed()) {
+	if (rv = prng_reseed(globalrng, NULL, 0, NULL, 0))
+	    return rv;
+    }
+#endif
     return prng_GenerateGlobalRandomBytes(globalrng, dest, len);
 }
 
 void
 RNG_RNGShutdown(void)
 {
     /* check for a valid global RNG context */
     PORT_Assert(globalrng != NULL);