Пример #1
0
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;
}
Пример #2
0
/*
 * Update the global random number generator with more seeding
 * material. Use the Hash_DRBG reseed algorithm from NIST SP-800-90
 * section 10.1.1.3
 *
 * If entropy is NULL, it is fetched from the noise generator.
 */
static SECStatus
prng_reseed(RNGContext *rng, const PRUint8 *entropy, unsigned int entropy_len,
	const PRUint8 *additional_input, unsigned int additional_input_len)
{
    PRUint8 noiseData[(sizeof rng->V_Data)+PRNG_SEEDLEN];
    PRUint8 *noise = &noiseData[0];

    /* if entropy wasn't supplied, fetch it. (normal operation case) */
    if (entropy == NULL) {
    	entropy_len = (unsigned int) RNG_SystemRNG(
			&noiseData[sizeof rng->V_Data], PRNG_SEEDLEN);
    } else {
	/* NOTE: this code is only available for testing, not to applications */
	/* if entropy was too big for the stack variable, get it from malloc */
	if (entropy_len > PRNG_SEEDLEN) {
	    noise = PORT_Alloc(entropy_len + (sizeof rng->V_Data));
	    if (noise == NULL) {
		return SECFailure;
	    }
	}
	PORT_Memcpy(&noise[sizeof rng->V_Data],entropy, entropy_len);
    }

    if (entropy_len < 256/PR_BITS_PER_BYTE) {
	/* noise == &noiseData[0] at this point, so nothing to free */
	PORT_SetError(SEC_ERROR_NEED_RANDOM);
	return SECFailure;
    }

    rng->V_type = prngReseedType;
    PORT_Memcpy(noise, rng->V_Data, sizeof rng->V_Data);
    prng_Hash_df(V(rng), VSize(rng), noise, (sizeof rng->V_Data) + entropy_len,
		additional_input, additional_input_len);
    /* clear potential CSP */
    PORT_Memset(noise, 0, (sizeof rng->V_Data) + entropy_len); 
    rng->V_type = prngCGenerateType;
    prng_Hash_df(rng->C,sizeof rng->C,rng->V_Data,sizeof rng->V_Data,NULL,0);
    PRNG_RESET_RESEED_COUNT(rng)

    if (noise != &noiseData[0]) {
	PORT_Free(noise);
    }
    return SECSuccess;
}