Ejemplo n.º 1
0
Archivo: drbg.c Proyecto: emaldona/nss
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;
}
Ejemplo n.º 2
0
Archivo: drbg.c Proyecto: emaldona/nss
SECStatus
PRNGTEST_Generate(PRUint8 *bytes, unsigned int bytes_len,
                  const PRUint8 *additional, unsigned int additional_len)
{
    SECStatus rv;
    if (!testContext.isValid) {
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
        return SECFailure;
    }
    /* replicate reseed test from prng_GenerateGlobalRandomBytes */
    if (testContext.reseed_counter[0] >= RESEED_VALUE) {
        rv = prng_reseed(&testContext, NULL, 0, NULL, 0);
        if (rv != SECSuccess) {
            return rv;
        }
    }
    return prng_generateNewBytes(&testContext, bytes, bytes_len,
                                 additional, additional_len);
}
Ejemplo n.º 3
0
/*
** Generate some random bytes, using the global random number generator
** object.
*/
static SECStatus 
prng_GenerateGlobalRandomBytes(RNGContext *rng,
                               void *dest, size_t len)
{
    SECStatus rv = SECSuccess;
    PRUint8 *output = dest;
    /* check for a valid global RNG context */
    PORT_Assert(rng != NULL);
    if (rng == NULL) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }
    /* FIPS limits the amount of entropy available in a single request */
    if (len > PRNG_MAX_REQUEST_SIZE) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }
    /* --- LOCKED --- */
    PZ_Lock(rng->lock);
    /* Check the amount of seed data in the generator.  If not enough,
     * don't produce any data.
     */
    if (rng->reseed_counter[0] >= RESEED_VALUE) {
	rv = prng_reseed_test(rng, NULL, 0, NULL, 0);
	PZ_Unlock(rng->lock);
	if (rv != SECSuccess) {
	    return rv;
	}
	RNG_SystemInfoForRNG();
	PZ_Lock(rng->lock);
    }
    /*
     * see if we have enough bytes to fulfill the request.
     */
    if (len <= rng->dataAvail) {
	memcpy(output, rng->data + ((sizeof rng->data) - rng->dataAvail), len);
	memset(rng->data + ((sizeof rng->data) - rng->dataAvail), 0, len);
	rng->dataAvail -= len;
	rv = SECSuccess;
    /* if we are asking for a small number of bytes, cache the rest of 
     * the bytes */
    } else if (len < sizeof rng->data) {
	rv = prng_generateNewBytes(rng, rng->data, sizeof rng->data, 
			rng->additionalAvail ? rng->additionalDataCache : NULL,
			rng->additionalAvail);
	rng->additionalAvail = 0;
	if (rv == SECSuccess) {
	    memcpy(output, rng->data, len);
	    memset(rng->data, 0, len); 
	    rng->dataAvail = (sizeof rng->data) - len;
	}
    /* we are asking for lots of bytes, just ask the generator to pass them */
    } else {
	rv = prng_generateNewBytes(rng, output, len,
			rng->additionalAvail ? rng->additionalDataCache : NULL,
			rng->additionalAvail);
	rng->additionalAvail = 0;
    }
    PZ_Unlock(rng->lock);
    /* --- UNLOCKED --- */
    return rv;
}