static PRStatus rng_init(void) { PRUint8 bytes[PRNG_SEEDLEN * 2]; /* entropy + nonce */ unsigned int numBytes; SECStatus rv = SECSuccess; if (globalrng == NULL) { /* bytes needs to have enough space to hold * a SHA256 hash value. Blow up at compile time if this isn't true */ PR_STATIC_ASSERT(sizeof(bytes) >= SHA256_LENGTH); /* create a new global RNG context */ globalrng = &theGlobalRng; PORT_Assert(NULL == globalrng->lock); /* create a lock for it */ globalrng->lock = PZ_NewLock(nssILockOther); if (globalrng->lock == NULL) { globalrng = NULL; PORT_SetError(PR_OUT_OF_MEMORY_ERROR); return PR_FAILURE; } /* Try to get some seed data for the RNG */ numBytes = (unsigned int)RNG_SystemRNG(bytes, sizeof bytes); PORT_Assert(numBytes == 0 || numBytes == sizeof bytes); if (numBytes != 0) { /* if this is our first call, instantiate, otherwise reseed * prng_instantiate gets a new clean state, we want to mix * any previous entropy we may have collected */ if (V(globalrng)[0] == 0) { rv = prng_instantiate(globalrng, bytes, numBytes); } else { rv = prng_reseed_test(globalrng, bytes, numBytes, NULL, 0); } memset(bytes, 0, numBytes); } else { PZ_DestroyLock(globalrng->lock); globalrng->lock = NULL; globalrng = NULL; return PR_FAILURE; } if (rv != SECSuccess) { return PR_FAILURE; } /* the RNG is in a valid state */ globalrng->isValid = PR_TRUE; globalrng->isKatTest = PR_FALSE; /* fetch one random value so that we can populate rng->oldV for our * continous random number test. */ prng_generateNewBytes(globalrng, bytes, SHA256_LENGTH, NULL, 0); /* Fetch more entropy into the PRNG */ RNG_SystemInfoForRNG(); } return PR_SUCCESS; }
/* * Test vector API. Use NIST SP 800-90 general interface so one of the * other NIST SP 800-90 algorithms may be used in the future. */ 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) { int bytes_len = entropy_len + nonce_len + ps_len; PRUint8 *bytes = NULL; SECStatus rv; if (entropy_len < 256/PR_BITS_PER_BYTE) { PORT_SetError(SEC_ERROR_NEED_RANDOM); return SECFailure; } bytes = PORT_Alloc(bytes_len); if (bytes == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); return SECFailure; } /* concatenate the various inputs, internally NSS only instantiates with * a single long string */ PORT_Memcpy(bytes, entropy, entropy_len); if (nonce) { PORT_Memcpy(&bytes[entropy_len], nonce, nonce_len); } else { PORT_Assert(nonce_len == 0); } if (personal_string) { PORT_Memcpy(&bytes[entropy_len+nonce_len], personal_string, ps_len); } else { PORT_Assert(ps_len == 0); } rv = prng_instantiate(&testContext, bytes, bytes_len); PORT_ZFree(bytes, bytes_len); if (rv == SECFailure) { return SECFailure; } testContext.isValid = PR_TRUE; return SECSuccess; }