security/nss/lib/freebl/drbg.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/freebl/drbg.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,914 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#ifdef FREEBL_NO_DEPEND
     1.9 +#include "stubs.h"
    1.10 +#endif
    1.11 +
    1.12 +#include "prerror.h"
    1.13 +#include "secerr.h"
    1.14 +
    1.15 +#include "prtypes.h"
    1.16 +#include "prinit.h"
    1.17 +#include "blapi.h"
    1.18 +#include "blapii.h"
    1.19 +#include "nssilock.h"
    1.20 +#include "secitem.h"
    1.21 +#include "sha_fast.h"
    1.22 +#include "sha256.h"
    1.23 +#include "secrng.h"	/* for RNG_SystemRNG() */
    1.24 +#include "secmpi.h"
    1.25 +
    1.26 +/* PRNG_SEEDLEN defined in NIST SP 800-90 section 10.1 
    1.27 + * for SHA-1, SHA-224, and SHA-256 it's 440 bits.
    1.28 + * for SHA-384 and SHA-512 it's 888 bits */
    1.29 +#define PRNG_SEEDLEN      (440/PR_BITS_PER_BYTE)
    1.30 +static const PRInt64 PRNG_MAX_ADDITIONAL_BYTES = LL_INIT(0x1, 0x0);
    1.31 +						/* 2^35 bits or 2^32 bytes */
    1.32 +#define PRNG_MAX_REQUEST_SIZE 0x10000		/* 2^19 bits or 2^16 bytes */
    1.33 +#define PRNG_ADDITONAL_DATA_CACHE_SIZE (8*1024) /* must be less than
    1.34 +						 *  PRNG_MAX_ADDITIONAL_BYTES
    1.35 +						 */
    1.36 +
    1.37 +/* RESEED_COUNT is how many calls to the prng before we need to reseed 
    1.38 + * under normal NIST rules, you must return an error. In the NSS case, we
    1.39 + * self-reseed with RNG_SystemRNG(). Count can be a large number. For code
    1.40 + * simplicity, we specify count with 2 components: RESEED_BYTE (which is 
    1.41 + * the same as LOG256(RESEED_COUNT)) and RESEED_VALUE (which is the same as
    1.42 + * RESEED_COUNT / (256 ^ RESEED_BYTE)). Another way to look at this is
    1.43 + * RESEED_COUNT = RESEED_VALUE * (256 ^ RESEED_BYTE). For Hash based DRBG
    1.44 + * we use the maximum count value, 2^48, or RESEED_BYTE=6 and RESEED_VALUE=1
    1.45 + */
    1.46 +#define RESEED_BYTE 6
    1.47 +#define RESEED_VALUE 1
    1.48 +
    1.49 +#define PRNG_RESET_RESEED_COUNT(rng) \
    1.50 +	PORT_Memset((rng)->reseed_counter, 0, sizeof (rng)->reseed_counter); \
    1.51 +	(rng)->reseed_counter[RESEED_BYTE] = 1;
    1.52 +
    1.53 +
    1.54 +/*
    1.55 + * The actual values of this enum are specified in SP 800-90, 10.1.1.*
    1.56 + * The spec does not name the types, it only uses bare values 
    1.57 + */
    1.58 +typedef enum {
    1.59 +   prngCGenerateType = 0,   	/* used when creating a new 'C' */
    1.60 +   prngReseedType = 1,	    	/* used in reseeding */
    1.61 +   prngAdditionalDataType = 2,  /* used in mixing additional data */
    1.62 +   prngGenerateByteType = 3	/* used when mixing internal state while
    1.63 +				 * generating bytes */
    1.64 +} prngVTypes;
    1.65 +
    1.66 +/*
    1.67 + * Global RNG context
    1.68 + */ 
    1.69 +struct RNGContextStr {
    1.70 +    PZLock   *lock;        /* Lock to serialize access to global rng */
    1.71 +    /*
    1.72 +     * NOTE, a number of steps in the drbg algorithm need to hash 
    1.73 +     * V_type || V. The code, therefore, depends on the V array following 
    1.74 +     * immediately after V_type to avoid extra copies. To accomplish this
    1.75 +     * in a way that compiliers can't perturb, we declare V_type and V
    1.76 +     * as a V_Data array and reference them by macros */
    1.77 +    PRUint8  V_Data[PRNG_SEEDLEN+1]; /* internal state variables */
    1.78 +#define  V_type  V_Data[0]
    1.79 +#define  V(rng)       (((rng)->V_Data)+1)
    1.80 +#define  VSize(rng)   ((sizeof (rng)->V_Data) -1)
    1.81 +    PRUint8  C[PRNG_SEEDLEN];        /* internal state variables */
    1.82 +    PRUint8  oldV[PRNG_SEEDLEN];     /* for continuous rng checking */
    1.83 +    /* If we get calls for the PRNG to return less than the length of our
    1.84 +     * hash, we extend the request for a full hash (since we'll be doing
    1.85 +     * the full hash anyway). Future requests for random numbers are fulfilled
    1.86 +     * from the remainder of the bytes we generated. Requests for bytes longer
    1.87 +     * than the hash size are fulfilled directly from the HashGen function
    1.88 +     * of the random number generator. */
    1.89 +    PRUint8  reseed_counter[RESEED_BYTE+1]; /* number of requests since the 
    1.90 +					     * last reseed. Need only be
    1.91 +					     * big enough to hold the whole
    1.92 +					     * reseed count */
    1.93 +    PRUint8  data[SHA256_LENGTH];	/* when we request less than a block
    1.94 +					 * save the rest of the rng output for 
    1.95 +					 * another partial block */
    1.96 +    PRUint8  dataAvail;            /* # bytes of output available in our cache,
    1.97 +	                            * [0...SHA256_LENGTH] */
    1.98 +    /* store additional data that has been shovelled off to us by
    1.99 +     * RNG_RandomUpdate. */
   1.100 +    PRUint8  additionalDataCache[PRNG_ADDITONAL_DATA_CACHE_SIZE];
   1.101 +    PRUint32 additionalAvail;
   1.102 +    PRBool   isValid;          /* false if RNG reaches an invalid state */
   1.103 +};
   1.104 +
   1.105 +typedef struct RNGContextStr RNGContext;
   1.106 +static RNGContext *globalrng = NULL;
   1.107 +static RNGContext theGlobalRng;
   1.108 +
   1.109 +
   1.110 +/*
   1.111 + * The next several functions are derived from the NIST SP 800-90
   1.112 + * spec. In these functions, an attempt was made to use names consistent
   1.113 + * with the names in the spec, even if they differ from normal NSS usage.
   1.114 + */
   1.115 +
   1.116 +/*
   1.117 + * Hash Derive function defined in NISP SP 800-90 Section 10.4.1.
   1.118 + * This function is used in the Instantiate and Reseed functions.
   1.119 + * 
   1.120 + * NOTE: requested_bytes cannot overlap with input_string_1 or input_string_2.
   1.121 + * input_string_1 and input_string_2 are logically concatentated. 
   1.122 + * input_string_1 must be supplied.
   1.123 + * if input_string_2 is not supplied, NULL should be passed for this parameter.
   1.124 + */
   1.125 +static SECStatus
   1.126 +prng_Hash_df(PRUint8 *requested_bytes, unsigned int no_of_bytes_to_return, 
   1.127 +	const PRUint8 *input_string_1, unsigned int input_string_1_len, 
   1.128 +	const PRUint8 *input_string_2, unsigned int input_string_2_len)
   1.129 +{
   1.130 +    SHA256Context ctx;
   1.131 +    PRUint32 tmp;
   1.132 +    PRUint8 counter;
   1.133 +
   1.134 +    tmp=SHA_HTONL(no_of_bytes_to_return*8);
   1.135 +
   1.136 +    for (counter = 1 ; no_of_bytes_to_return > 0; counter++) {
   1.137 +	unsigned int hash_return_len;
   1.138 + 	SHA256_Begin(&ctx);
   1.139 + 	SHA256_Update(&ctx, &counter, 1);
   1.140 + 	SHA256_Update(&ctx, (unsigned char *)&tmp, sizeof tmp);
   1.141 + 	SHA256_Update(&ctx, input_string_1, input_string_1_len);
   1.142 +	if (input_string_2) {
   1.143 + 	    SHA256_Update(&ctx, input_string_2, input_string_2_len);
   1.144 +	}
   1.145 +	SHA256_End(&ctx, requested_bytes, &hash_return_len,
   1.146 +		no_of_bytes_to_return);
   1.147 +	requested_bytes += hash_return_len;
   1.148 +	no_of_bytes_to_return -= hash_return_len;
   1.149 +    }
   1.150 +    return SECSuccess;
   1.151 +}
   1.152 +
   1.153 +
   1.154 +/*
   1.155 + * Hash_DRBG Instantiate NIST SP 800-80 10.1.1.2
   1.156 + *
   1.157 + * NOTE: bytes & len are entropy || nonce || personalization_string. In
   1.158 + * normal operation, NSS calculates them all together in a single call.
   1.159 + */
   1.160 +static SECStatus
   1.161 +prng_instantiate(RNGContext *rng, const PRUint8 *bytes, unsigned int len)
   1.162 +{
   1.163 +    if (len < PRNG_SEEDLEN) {
   1.164 +	/* if the seedlen is to small, it's probably because we failed to get
   1.165 +	 * enough random data */
   1.166 +	PORT_SetError(SEC_ERROR_NEED_RANDOM);
   1.167 +	return SECFailure;
   1.168 +    }
   1.169 +    prng_Hash_df(V(rng), VSize(rng), bytes, len, NULL, 0);
   1.170 +    rng->V_type = prngCGenerateType;
   1.171 +    prng_Hash_df(rng->C,sizeof rng->C,rng->V_Data,sizeof rng->V_Data,NULL,0);
   1.172 +    PRNG_RESET_RESEED_COUNT(rng)
   1.173 +    return SECSuccess;
   1.174 +}
   1.175 +    
   1.176 +
   1.177 +/*
   1.178 + * Update the global random number generator with more seeding
   1.179 + * material. Use the Hash_DRBG reseed algorithm from NIST SP-800-90
   1.180 + * section 10.1.1.3
   1.181 + *
   1.182 + * If entropy is NULL, it is fetched from the noise generator.
   1.183 + */
   1.184 +static SECStatus
   1.185 +prng_reseed(RNGContext *rng, const PRUint8 *entropy, unsigned int entropy_len,
   1.186 +	const PRUint8 *additional_input, unsigned int additional_input_len)
   1.187 +{
   1.188 +    PRUint8 noiseData[(sizeof rng->V_Data)+PRNG_SEEDLEN];
   1.189 +    PRUint8 *noise = &noiseData[0];
   1.190 +
   1.191 +    /* if entropy wasn't supplied, fetch it. (normal operation case) */
   1.192 +    if (entropy == NULL) {
   1.193 +    	entropy_len = (unsigned int) RNG_SystemRNG(
   1.194 +			&noiseData[sizeof rng->V_Data], PRNG_SEEDLEN);
   1.195 +    } else {
   1.196 +	/* NOTE: this code is only available for testing, not to applications */
   1.197 +	/* if entropy was too big for the stack variable, get it from malloc */
   1.198 +	if (entropy_len > PRNG_SEEDLEN) {
   1.199 +	    noise = PORT_Alloc(entropy_len + (sizeof rng->V_Data));
   1.200 +	    if (noise == NULL) {
   1.201 +		return SECFailure;
   1.202 +	    }
   1.203 +	}
   1.204 +	PORT_Memcpy(&noise[sizeof rng->V_Data],entropy, entropy_len);
   1.205 +    }
   1.206 +
   1.207 +    if (entropy_len < 256/PR_BITS_PER_BYTE) {
   1.208 +	/* noise == &noiseData[0] at this point, so nothing to free */
   1.209 +	PORT_SetError(SEC_ERROR_NEED_RANDOM);
   1.210 +	return SECFailure;
   1.211 +    }
   1.212 +
   1.213 +    rng->V_type = prngReseedType;
   1.214 +    PORT_Memcpy(noise, rng->V_Data, sizeof rng->V_Data);
   1.215 +    prng_Hash_df(V(rng), VSize(rng), noise, (sizeof rng->V_Data) + entropy_len,
   1.216 +		additional_input, additional_input_len);
   1.217 +    /* clear potential CSP */
   1.218 +    PORT_Memset(noise, 0, (sizeof rng->V_Data) + entropy_len); 
   1.219 +    rng->V_type = prngCGenerateType;
   1.220 +    prng_Hash_df(rng->C,sizeof rng->C,rng->V_Data,sizeof rng->V_Data,NULL,0);
   1.221 +    PRNG_RESET_RESEED_COUNT(rng)
   1.222 +
   1.223 +    if (noise != &noiseData[0]) {
   1.224 +	PORT_Free(noise);
   1.225 +    }
   1.226 +    return SECSuccess;
   1.227 +}
   1.228 +
   1.229 +/*
   1.230 + * SP 800-90 requires we rerun our health tests on reseed
   1.231 + */
   1.232 +static SECStatus
   1.233 +prng_reseed_test(RNGContext *rng, const PRUint8 *entropy, 
   1.234 +	unsigned int entropy_len, const PRUint8 *additional_input, 
   1.235 +	unsigned int additional_input_len)
   1.236 +{
   1.237 +    SECStatus rv;
   1.238 +
   1.239 +    /* do health checks in FIPS mode */
   1.240 +    rv = PRNGTEST_RunHealthTests();
   1.241 +    if (rv != SECSuccess) {
   1.242 +	/* error set by PRNGTEST_RunHealTests() */
   1.243 +	rng->isValid = PR_FALSE;
   1.244 +	return SECFailure;
   1.245 +    }
   1.246 +    return prng_reseed(rng, entropy, entropy_len, 
   1.247 +				additional_input, additional_input_len);
   1.248 +}
   1.249 +
   1.250 +/*
   1.251 + * build some fast inline functions for adding.
   1.252 + */
   1.253 +#define PRNG_ADD_CARRY_ONLY(dest, start, cy) \
   1.254 +   carry = cy; \
   1.255 +   for (k1=start; carry && k1 >=0 ; k1--) { \
   1.256 +	carry = !(++dest[k1]); \
   1.257 +   } 
   1.258 +
   1.259 +/*
   1.260 + * NOTE: dest must be an array for the following to work.
   1.261 + */
   1.262 +#define PRNG_ADD_BITS(dest, dest_len, add, len) \
   1.263 +    carry = 0; \
   1.264 +    for (k1=dest_len -1, k2=len-1; k2 >= 0; --k1, --k2) { \
   1.265 +	carry += dest[k1]+ add[k2]; \
   1.266 +	dest[k1] = (PRUint8) carry; \
   1.267 +	carry >>= 8; \
   1.268 +    }
   1.269 +
   1.270 +#define PRNG_ADD_BITS_AND_CARRY(dest, dest_len, add, len) \
   1.271 +    PRNG_ADD_BITS(dest, dest_len, add, len) \
   1.272 +    PRNG_ADD_CARRY_ONLY(dest, k1, carry)
   1.273 +
   1.274 +/*
   1.275 + * This function expands the internal state of the prng to fulfill any number
   1.276 + * of bytes we need for this request. We only use this call if we need more
   1.277 + * than can be supplied by a single call to SHA256_HashBuf. 
   1.278 + *
   1.279 + * This function is specified in NIST SP 800-90 section 10.1.1.4, Hashgen
   1.280 + */
   1.281 +static void
   1.282 +prng_Hashgen(RNGContext *rng, PRUint8 *returned_bytes, 
   1.283 +	     unsigned int no_of_returned_bytes)
   1.284 +{
   1.285 +    PRUint8 data[VSize(rng)];
   1.286 +
   1.287 +    PORT_Memcpy(data, V(rng), VSize(rng));
   1.288 +    while (no_of_returned_bytes) {
   1.289 +	SHA256Context ctx;
   1.290 +	unsigned int len;
   1.291 +	unsigned int carry;
   1.292 +	int k1;
   1.293 +
   1.294 + 	SHA256_Begin(&ctx);
   1.295 + 	SHA256_Update(&ctx, data, sizeof data);
   1.296 +	SHA256_End(&ctx, returned_bytes, &len, no_of_returned_bytes);
   1.297 +	returned_bytes += len;
   1.298 +	no_of_returned_bytes -= len;
   1.299 +	/* The carry parameter is a bool (increment or not). 
   1.300 +	 * This increments data if no_of_returned_bytes is not zero */
   1.301 +	PRNG_ADD_CARRY_ONLY(data, (sizeof data)- 1, no_of_returned_bytes);
   1.302 +    }
   1.303 +    PORT_Memset(data, 0, sizeof data); 
   1.304 +}
   1.305 +
   1.306 +/* 
   1.307 + * Generates new random bytes and advances the internal prng state.	
   1.308 + * additional bytes are only used in algorithm testing.
   1.309 + * 
   1.310 + * This function is specified in NIST SP 800-90 section 10.1.1.4
   1.311 + */
   1.312 +static SECStatus
   1.313 +prng_generateNewBytes(RNGContext *rng, 
   1.314 +		PRUint8 *returned_bytes, unsigned int no_of_returned_bytes,
   1.315 +		const PRUint8 *additional_input,
   1.316 +		unsigned int additional_input_len)
   1.317 +{
   1.318 +    PRUint8 H[SHA256_LENGTH]; /* both H and w since they 
   1.319 +			       * aren't used concurrently */
   1.320 +    unsigned int carry;
   1.321 +    int k1, k2;
   1.322 +
   1.323 +    if (!rng->isValid) {
   1.324 +	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1.325 +	return SECFailure;
   1.326 +    }
   1.327 +    /* This code only triggers during tests, normal
   1.328 +     * prng operation does not use additional_input */
   1.329 +    if (additional_input){
   1.330 +	SHA256Context ctx;
   1.331 +	/* NIST SP 800-90 defines two temporaries in their calculations,
   1.332 +	 * w and H. These temporaries are the same lengths, and used
   1.333 +	 * at different times, so we use the following macro to collapse
   1.334 +	 * them to the same variable, but keeping their unique names for
   1.335 +	 * easy comparison to the spec */
   1.336 +#define w H
   1.337 +	rng->V_type = prngAdditionalDataType;
   1.338 + 	SHA256_Begin(&ctx);
   1.339 + 	SHA256_Update(&ctx, rng->V_Data, sizeof rng->V_Data);
   1.340 + 	SHA256_Update(&ctx, additional_input, additional_input_len);
   1.341 +	SHA256_End(&ctx, w, NULL, sizeof w);
   1.342 +	PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), w, sizeof w)
   1.343 +	PORT_Memset(w, 0, sizeof w);
   1.344 +#undef w 
   1.345 +    }
   1.346 +
   1.347 +    if (no_of_returned_bytes == SHA256_LENGTH) {
   1.348 +	/* short_cut to hashbuf and save a copy and a clear */
   1.349 +	SHA256_HashBuf(returned_bytes, V(rng), VSize(rng) );
   1.350 +    } else {
   1.351 +    	prng_Hashgen(rng, returned_bytes, no_of_returned_bytes);
   1.352 +    }
   1.353 +    /* advance our internal state... */
   1.354 +    rng->V_type = prngGenerateByteType;
   1.355 +    SHA256_HashBuf(H, rng->V_Data, sizeof rng->V_Data);
   1.356 +    PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), H, sizeof H)
   1.357 +    PRNG_ADD_BITS(V(rng), VSize(rng), rng->C, sizeof rng->C);
   1.358 +    PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), rng->reseed_counter, 
   1.359 +					sizeof rng->reseed_counter)
   1.360 +    PRNG_ADD_CARRY_ONLY(rng->reseed_counter,(sizeof rng->reseed_counter)-1, 1);
   1.361 +
   1.362 +    /* continuous rng check */
   1.363 +    if (memcmp(V(rng), rng->oldV, sizeof rng->oldV) == 0) {
   1.364 +	rng->isValid = PR_FALSE;
   1.365 +	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1.366 +	return SECFailure;
   1.367 +    }
   1.368 +    PORT_Memcpy(rng->oldV, V(rng), sizeof rng->oldV);
   1.369 +    return SECSuccess;
   1.370 +}
   1.371 +
   1.372 +/* Use NSPR to prevent RNG_RNGInit from being called from separate
   1.373 + * threads, creating a race condition.
   1.374 + */
   1.375 +static const PRCallOnceType pristineCallOnce;
   1.376 +static PRCallOnceType coRNGInit;
   1.377 +static PRStatus rng_init(void)
   1.378 +{
   1.379 +    PRUint8 bytes[PRNG_SEEDLEN*2]; /* entropy + nonce */
   1.380 +    unsigned int numBytes;
   1.381 +    SECStatus rv = SECSuccess;
   1.382 +
   1.383 +    if (globalrng == NULL) {
   1.384 +	/* bytes needs to have enough space to hold
   1.385 +	 * a SHA256 hash value. Blow up at compile time if this isn't true */
   1.386 +	PR_STATIC_ASSERT(sizeof(bytes) >= SHA256_LENGTH);
   1.387 +	/* create a new global RNG context */
   1.388 +	globalrng = &theGlobalRng;
   1.389 +        PORT_Assert(NULL == globalrng->lock);
   1.390 +	/* create a lock for it */
   1.391 +	globalrng->lock = PZ_NewLock(nssILockOther);
   1.392 +	if (globalrng->lock == NULL) {
   1.393 +	    globalrng = NULL;
   1.394 +	    PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
   1.395 +	    return PR_FAILURE;
   1.396 +	}
   1.397 +
   1.398 +	/* Try to get some seed data for the RNG */
   1.399 +	numBytes = (unsigned int) RNG_SystemRNG(bytes, sizeof bytes);
   1.400 +	PORT_Assert(numBytes == 0 || numBytes == sizeof bytes);
   1.401 +	if (numBytes != 0) {
   1.402 +	    /* if this is our first call,  instantiate, otherwise reseed 
   1.403 +	     * prng_instantiate gets a new clean state, we want to mix
   1.404 +	     * any previous entropy we may have collected */
   1.405 +	    if (V(globalrng)[0] == 0) {
   1.406 +		rv = prng_instantiate(globalrng, bytes, numBytes);
   1.407 +	    } else {
   1.408 +		rv = prng_reseed_test(globalrng, bytes, numBytes, NULL, 0);
   1.409 +	    }
   1.410 +	    memset(bytes, 0, numBytes);
   1.411 +	} else {
   1.412 +	    PZ_DestroyLock(globalrng->lock);
   1.413 +	    globalrng->lock = NULL;
   1.414 +	    globalrng = NULL;
   1.415 +	    return PR_FAILURE;
   1.416 +	}
   1.417 + 
   1.418 +	if (rv != SECSuccess) {
   1.419 +	    return PR_FAILURE;
   1.420 +	}
   1.421 +	/* the RNG is in a valid state */
   1.422 +	globalrng->isValid = PR_TRUE;
   1.423 +
   1.424 +	/* fetch one random value so that we can populate rng->oldV for our
   1.425 +	 * continous random number test. */
   1.426 +	prng_generateNewBytes(globalrng, bytes, SHA256_LENGTH, NULL, 0);
   1.427 +
   1.428 +	/* Fetch more entropy into the PRNG */
   1.429 +	RNG_SystemInfoForRNG();
   1.430 +    }
   1.431 +    return PR_SUCCESS;
   1.432 +}
   1.433 +
   1.434 +/*
   1.435 + * Clean up the global RNG context
   1.436 + */
   1.437 +static void
   1.438 +prng_freeRNGContext(RNGContext *rng)
   1.439 +{
   1.440 +    PRUint8 inputhash[VSize(rng) + (sizeof rng->C)];
   1.441 +
   1.442 +    /* destroy context lock */
   1.443 +    SKIP_AFTER_FORK(PZ_DestroyLock(globalrng->lock));
   1.444 +
   1.445 +    /* zero global RNG context except for C & V to preserve entropy */
   1.446 +    prng_Hash_df(inputhash, sizeof rng->C, rng->C, sizeof rng->C, NULL, 0); 
   1.447 +    prng_Hash_df(&inputhash[sizeof rng->C], VSize(rng), V(rng), VSize(rng), 
   1.448 +								  NULL, 0); 
   1.449 +    memset(rng, 0, sizeof *rng);
   1.450 +    memcpy(rng->C, inputhash, sizeof rng->C); 
   1.451 +    memcpy(V(rng), &inputhash[sizeof rng->C], VSize(rng)); 
   1.452 +
   1.453 +    memset(inputhash, 0, sizeof inputhash);
   1.454 +}
   1.455 +
   1.456 +/*
   1.457 + * Public functions
   1.458 + */
   1.459 +
   1.460 +/*
   1.461 + * Initialize the global RNG context and give it some seed input taken
   1.462 + * from the system.  This function is thread-safe and will only allow
   1.463 + * the global context to be initialized once.  The seed input is likely
   1.464 + * small, so it is imperative that RNG_RandomUpdate() be called with
   1.465 + * additional seed data before the generator is used.  A good way to
   1.466 + * provide the generator with additional entropy is to call
   1.467 + * RNG_SystemInfoForRNG().  Note that C_Initialize() does exactly that.
   1.468 + */
   1.469 +SECStatus 
   1.470 +RNG_RNGInit(void)
   1.471 +{
   1.472 +    /* Allow only one call to initialize the context */
   1.473 +    PR_CallOnce(&coRNGInit, rng_init);
   1.474 +    /* Make sure there is a context */
   1.475 +    return (globalrng != NULL) ? SECSuccess : SECFailure;
   1.476 +}
   1.477 +
   1.478 +/*
   1.479 +** Update the global random number generator with more seeding
   1.480 +** material.
   1.481 +*/
   1.482 +SECStatus 
   1.483 +RNG_RandomUpdate(const void *data, size_t bytes)
   1.484 +{
   1.485 +    SECStatus rv;
   1.486 +
   1.487 +    /* Make sure our assumption that size_t is unsigned is true */
   1.488 +    PR_STATIC_ASSERT(((size_t)-1) > (size_t)1);
   1.489 +
   1.490 +#if defined(NS_PTR_GT_32) || (defined(NSS_USE_64) && !defined(NS_PTR_LE_32))
   1.491 +    /*
   1.492 +     * NIST 800-90 requires us to verify our inputs. This value can
   1.493 +     * come from the application, so we need to make sure it's within the
   1.494 +     * spec. The spec says it must be less than 2^32 bytes (2^35 bits).
   1.495 +     * This can only happen if size_t is greater than 32 bits (i.e. on
   1.496 +     * most 64 bit platforms). The 90% case (perhaps 100% case), size_t
   1.497 +     * is less than or equal to 32 bits if the platform is not 64 bits, and
   1.498 +     * greater than 32 bits if it is a 64 bit platform. The corner
   1.499 +     * cases are handled with explicit defines NS_PTR_GT_32 and NS_PTR_LE_32.
   1.500 +     *
   1.501 +     * In general, neither NS_PTR_GT_32 nor NS_PTR_LE_32 will need to be 
   1.502 +     * defined. If you trip over the next two size ASSERTS at compile time,
   1.503 +     * you will need to define them for your platform.
   1.504 +     *
   1.505 +     * if 'sizeof(size_t) > 4' is triggered it means that we were expecting
   1.506 +     *   sizeof(size_t) to be greater than 4, but it wasn't. Setting 
   1.507 +     *   NS_PTR_LE_32 will correct that mistake.
   1.508 +     *
   1.509 +     * if 'sizeof(size_t) <= 4' is triggered, it means that we were expecting
   1.510 +     *   sizeof(size_t) to be less than or equal to 4, but it wasn't. Setting 
   1.511 +     *   NS_PTR_GT_32 will correct that mistake.
   1.512 +     */
   1.513 +
   1.514 +    PR_STATIC_ASSERT(sizeof(size_t) > 4);
   1.515 +
   1.516 +    if (bytes > PRNG_MAX_ADDITIONAL_BYTES) {
   1.517 +	bytes = PRNG_MAX_ADDITIONAL_BYTES;
   1.518 +    }
   1.519 +#else
   1.520 +    PR_STATIC_ASSERT(sizeof(size_t) <= 4);
   1.521 +#endif
   1.522 +
   1.523 +    PZ_Lock(globalrng->lock);
   1.524 +    /* if we're passed more than our additionalDataCache, simply
   1.525 +     * call reseed with that data */
   1.526 +    if (bytes > sizeof (globalrng->additionalDataCache)) {
   1.527 +	rv = prng_reseed_test(globalrng, NULL, 0, data, (unsigned int) bytes);
   1.528 +    /* if we aren't going to fill or overflow the buffer, just cache it */
   1.529 +    } else if (bytes < ((sizeof globalrng->additionalDataCache)
   1.530 +				- globalrng->additionalAvail)) {
   1.531 +	PORT_Memcpy(globalrng->additionalDataCache+globalrng->additionalAvail,
   1.532 +		    data, bytes);
   1.533 +	globalrng->additionalAvail += (PRUint32) bytes;
   1.534 +	rv = SECSuccess;
   1.535 +    } else {
   1.536 +	/* we are going to fill or overflow the buffer. In this case we will
   1.537 +	 * fill the entropy buffer, reseed with it, start a new buffer with the
   1.538 +	 * remainder. We know the remainder will fit in the buffer because
   1.539 +	 * we already handled the case where bytes > the size of the buffer.
   1.540 +	 */
   1.541 +	size_t bufRemain = (sizeof globalrng->additionalDataCache) 
   1.542 +					- globalrng->additionalAvail;
   1.543 +	/* fill the rest of the buffer */
   1.544 +	if (bufRemain) {
   1.545 +	    PORT_Memcpy(globalrng->additionalDataCache
   1.546 +			+globalrng->additionalAvail, 
   1.547 +			data, bufRemain);
   1.548 +	    data = ((unsigned char *)data) + bufRemain;
   1.549 +	    bytes -= bufRemain;
   1.550 +	}
   1.551 +	/* reseed from buffer */
   1.552 +	rv = prng_reseed_test(globalrng, NULL, 0, 
   1.553 +				        globalrng->additionalDataCache, 
   1.554 +					sizeof globalrng->additionalDataCache);
   1.555 +
   1.556 +	/* copy the rest into the cache */
   1.557 +	PORT_Memcpy(globalrng->additionalDataCache, data, bytes);
   1.558 +	globalrng->additionalAvail = (PRUint32) bytes;
   1.559 +    }
   1.560 +		
   1.561 +    PZ_Unlock(globalrng->lock);
   1.562 +    return rv;
   1.563 +}
   1.564 +
   1.565 +/*
   1.566 +** Generate some random bytes, using the global random number generator
   1.567 +** object.
   1.568 +*/
   1.569 +static SECStatus 
   1.570 +prng_GenerateGlobalRandomBytes(RNGContext *rng,
   1.571 +                               void *dest, size_t len)
   1.572 +{
   1.573 +    SECStatus rv = SECSuccess;
   1.574 +    PRUint8 *output = dest;
   1.575 +    /* check for a valid global RNG context */
   1.576 +    PORT_Assert(rng != NULL);
   1.577 +    if (rng == NULL) {
   1.578 +	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1.579 +	return SECFailure;
   1.580 +    }
   1.581 +    /* FIPS limits the amount of entropy available in a single request */
   1.582 +    if (len > PRNG_MAX_REQUEST_SIZE) {
   1.583 +	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1.584 +	return SECFailure;
   1.585 +    }
   1.586 +    /* --- LOCKED --- */
   1.587 +    PZ_Lock(rng->lock);
   1.588 +    /* Check the amount of seed data in the generator.  If not enough,
   1.589 +     * don't produce any data.
   1.590 +     */
   1.591 +    if (rng->reseed_counter[0] >= RESEED_VALUE) {
   1.592 +	rv = prng_reseed_test(rng, NULL, 0, NULL, 0);
   1.593 +	PZ_Unlock(rng->lock);
   1.594 +	if (rv != SECSuccess) {
   1.595 +	    return rv;
   1.596 +	}
   1.597 +	RNG_SystemInfoForRNG();
   1.598 +	PZ_Lock(rng->lock);
   1.599 +    }
   1.600 +    /*
   1.601 +     * see if we have enough bytes to fulfill the request.
   1.602 +     */
   1.603 +    if (len <= rng->dataAvail) {
   1.604 +	memcpy(output, rng->data + ((sizeof rng->data) - rng->dataAvail), len);
   1.605 +	memset(rng->data + ((sizeof rng->data) - rng->dataAvail), 0, len);
   1.606 +	rng->dataAvail -= len;
   1.607 +	rv = SECSuccess;
   1.608 +    /* if we are asking for a small number of bytes, cache the rest of 
   1.609 +     * the bytes */
   1.610 +    } else if (len < sizeof rng->data) {
   1.611 +	rv = prng_generateNewBytes(rng, rng->data, sizeof rng->data, 
   1.612 +			rng->additionalAvail ? rng->additionalDataCache : NULL,
   1.613 +			rng->additionalAvail);
   1.614 +	rng->additionalAvail = 0;
   1.615 +	if (rv == SECSuccess) {
   1.616 +	    memcpy(output, rng->data, len);
   1.617 +	    memset(rng->data, 0, len); 
   1.618 +	    rng->dataAvail = (sizeof rng->data) - len;
   1.619 +	}
   1.620 +    /* we are asking for lots of bytes, just ask the generator to pass them */
   1.621 +    } else {
   1.622 +	rv = prng_generateNewBytes(rng, output, len,
   1.623 +			rng->additionalAvail ? rng->additionalDataCache : NULL,
   1.624 +			rng->additionalAvail);
   1.625 +	rng->additionalAvail = 0;
   1.626 +    }
   1.627 +    PZ_Unlock(rng->lock);
   1.628 +    /* --- UNLOCKED --- */
   1.629 +    return rv;
   1.630 +}
   1.631 +
   1.632 +/*
   1.633 +** Generate some random bytes, using the global random number generator
   1.634 +** object.
   1.635 +*/
   1.636 +SECStatus 
   1.637 +RNG_GenerateGlobalRandomBytes(void *dest, size_t len)
   1.638 +{
   1.639 +    return prng_GenerateGlobalRandomBytes(globalrng, dest, len);
   1.640 +}
   1.641 +
   1.642 +void
   1.643 +RNG_RNGShutdown(void)
   1.644 +{
   1.645 +    /* check for a valid global RNG context */
   1.646 +    PORT_Assert(globalrng != NULL);
   1.647 +    if (globalrng == NULL) {
   1.648 +	/* Should set a "not initialized" error code. */
   1.649 +	PORT_SetError(SEC_ERROR_NO_MEMORY);
   1.650 +	return;
   1.651 +    }
   1.652 +    /* clear */
   1.653 +    prng_freeRNGContext(globalrng);
   1.654 +    globalrng = NULL;
   1.655 +    /* reset the callonce struct to allow a new call to RNG_RNGInit() */
   1.656 +    coRNGInit = pristineCallOnce;
   1.657 +}
   1.658 +
   1.659 +/*
   1.660 + * Test case interface. used by fips testing and power on self test
   1.661 + */
   1.662 + /* make sure the test context is separate from the global context, This
   1.663 +  * allows us to test the internal random number generator without losing
   1.664 +  * entropy we may have previously collected. */
   1.665 +RNGContext testContext;
   1.666 +
   1.667 +/*
   1.668 + * Test vector API. Use NIST SP 800-90 general interface so one of the
   1.669 + * other NIST SP 800-90 algorithms may be used in the future.
   1.670 + */
   1.671 +SECStatus
   1.672 +PRNGTEST_Instantiate(const PRUint8 *entropy, unsigned int entropy_len, 
   1.673 +		const PRUint8 *nonce, unsigned int nonce_len,
   1.674 +		const PRUint8 *personal_string, unsigned int ps_len)
   1.675 +{
   1.676 +   int bytes_len = entropy_len + nonce_len + ps_len;
   1.677 +   PRUint8 *bytes = NULL;
   1.678 +   SECStatus rv;
   1.679 +
   1.680 +   if (entropy_len < 256/PR_BITS_PER_BYTE) {
   1.681 +	PORT_SetError(SEC_ERROR_NEED_RANDOM);
   1.682 +	return SECFailure;
   1.683 +   }
   1.684 +
   1.685 +   bytes = PORT_Alloc(bytes_len);
   1.686 +   if (bytes == NULL) {
   1.687 +	PORT_SetError(SEC_ERROR_NO_MEMORY);
   1.688 +	return SECFailure;
   1.689 +   }
   1.690 +   /* concatenate the various inputs, internally NSS only instantiates with
   1.691 +    * a single long string */
   1.692 +   PORT_Memcpy(bytes, entropy, entropy_len);
   1.693 +   if (nonce) {
   1.694 +	PORT_Memcpy(&bytes[entropy_len], nonce, nonce_len);
   1.695 +   } else {
   1.696 +	PORT_Assert(nonce_len == 0);
   1.697 +   }
   1.698 +   if (personal_string) {
   1.699 +       PORT_Memcpy(&bytes[entropy_len+nonce_len], personal_string, ps_len);
   1.700 +   } else {
   1.701 +	PORT_Assert(ps_len == 0);
   1.702 +   }
   1.703 +   rv = prng_instantiate(&testContext, bytes, bytes_len);
   1.704 +   PORT_ZFree(bytes, bytes_len);
   1.705 +   if (rv == SECFailure) {
   1.706 +	return SECFailure;
   1.707 +   }
   1.708 +   testContext.isValid = PR_TRUE;
   1.709 +   return SECSuccess;
   1.710 +}
   1.711 +
   1.712 +SECStatus
   1.713 +PRNGTEST_Reseed(const PRUint8 *entropy, unsigned int entropy_len, 
   1.714 +		  const PRUint8 *additional, unsigned int additional_len)
   1.715 +{
   1.716 +    if (!testContext.isValid) {
   1.717 +	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1.718 +	return SECFailure;
   1.719 +    }
   1.720 +   /* This magic input tells us to set the reseed count to it's max count, 
   1.721 +    * so we can simulate PRNGTEST_Generate reaching max reseed count */
   1.722 +    if ((entropy == NULL) && (entropy_len == 0) && 
   1.723 +		(additional == NULL) && (additional_len == 0)) {
   1.724 +	testContext.reseed_counter[0] = RESEED_VALUE;
   1.725 +	return SECSuccess;
   1.726 +    }
   1.727 +    return prng_reseed(&testContext, entropy, entropy_len, additional,
   1.728 +			additional_len);
   1.729 +
   1.730 +}
   1.731 +
   1.732 +SECStatus
   1.733 +PRNGTEST_Generate(PRUint8 *bytes, unsigned int bytes_len, 
   1.734 +		  const PRUint8 *additional, unsigned int additional_len)
   1.735 +{
   1.736 +    SECStatus rv;
   1.737 +    if (!testContext.isValid) {
   1.738 +	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1.739 +	return SECFailure;
   1.740 +    }
   1.741 +    /* replicate reseed test from prng_GenerateGlobalRandomBytes */
   1.742 +    if (testContext.reseed_counter[0] >= RESEED_VALUE) {
   1.743 +	rv = prng_reseed(&testContext, NULL, 0, NULL, 0);
   1.744 +	if (rv != SECSuccess) {
   1.745 +	    return rv;
   1.746 +	}
   1.747 +    }
   1.748 +    return prng_generateNewBytes(&testContext, bytes, bytes_len,
   1.749 +			additional, additional_len);
   1.750 +
   1.751 +}
   1.752 +
   1.753 +SECStatus
   1.754 +PRNGTEST_Uninstantiate()
   1.755 +{
   1.756 +    if (!testContext.isValid) {
   1.757 +	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1.758 +	return SECFailure;
   1.759 +    }
   1.760 +   PORT_Memset(&testContext, 0, sizeof testContext);
   1.761 +   return SECSuccess;
   1.762 +}
   1.763 +
   1.764 +SECStatus
   1.765 +PRNGTEST_RunHealthTests()
   1.766 +{
   1.767 +   static const PRUint8 entropy[] = {
   1.768 +			0x8e,0x9c,0x0d,0x25,0x75,0x22,0x04,0xf9,
   1.769 +			0xc5,0x79,0x10,0x8b,0x23,0x79,0x37,0x14,
   1.770 +			0x9f,0x2c,0xc7,0x0b,0x39,0xf8,0xee,0xef,
   1.771 +			0x95,0x0c,0x97,0x59,0xfc,0x0a,0x85,0x41,
   1.772 +			0x76,0x9d,0x6d,0x67,0x00,0x4e,0x19,0x12,
   1.773 +			0x02,0x16,0x53,0xea,0xf2,0x73,0xd7,0xd6,
   1.774 +			0x7f,0x7e,0xc8,0xae,0x9c,0x09,0x99,0x7d,
   1.775 +			0xbb,0x9e,0x48,0x7f,0xbb,0x96,0x46,0xb3,
   1.776 +			0x03,0x75,0xf8,0xc8,0x69,0x45,0x3f,0x97,
   1.777 +			0x5e,0x2e,0x48,0xe1,0x5d,0x58,0x97,0x4c };
   1.778 +   static const PRUint8 rng_known_result[] = {
   1.779 +			0x16,0xe1,0x8c,0x57,0x21,0xd8,0xf1,0x7e,
   1.780 +			0x5a,0xa0,0x16,0x0b,0x7e,0xa6,0x25,0xb4,
   1.781 +			0x24,0x19,0xdb,0x54,0xfa,0x35,0x13,0x66,
   1.782 +			0xbb,0xaa,0x2a,0x1b,0x22,0x33,0x2e,0x4a,
   1.783 +			0x14,0x07,0x9d,0x52,0xfc,0x73,0x61,0x48,
   1.784 +			0xac,0xc1,0x22,0xfc,0xa4,0xfc,0xac,0xa4,
   1.785 +			0xdb,0xda,0x5b,0x27,0x33,0xc4,0xb3 };
   1.786 +   static const PRUint8 reseed_entropy[] = {
   1.787 +			0xc6,0x0b,0x0a,0x30,0x67,0x07,0xf4,0xe2,
   1.788 +			0x24,0xa7,0x51,0x6f,0x5f,0x85,0x3e,0x5d,
   1.789 +			0x67,0x97,0xb8,0x3b,0x30,0x9c,0x7a,0xb1,
   1.790 +			0x52,0xc6,0x1b,0xc9,0x46,0xa8,0x62,0x79 };
   1.791 +   static const PRUint8 additional_input[] = {
   1.792 +			0x86,0x82,0x28,0x98,0xe7,0xcb,0x01,0x14,
   1.793 +			0xae,0x87,0x4b,0x1d,0x99,0x1b,0xc7,0x41,
   1.794 +			0x33,0xff,0x33,0x66,0x40,0x95,0x54,0xc6,
   1.795 +			0x67,0x4d,0x40,0x2a,0x1f,0xf9,0xeb,0x65 };
   1.796 +   static const PRUint8 rng_reseed_result[] = {
   1.797 +			0x02,0x0c,0xc6,0x17,0x86,0x49,0xba,0xc4,
   1.798 +			0x7b,0x71,0x35,0x05,0xf0,0xdb,0x4a,0xc2,
   1.799 +			0x2c,0x38,0xc1,0xa4,0x42,0xe5,0x46,0x4a,
   1.800 +			0x7d,0xf0,0xbe,0x47,0x88,0xb8,0x0e,0xc6,
   1.801 +			0x25,0x2b,0x1d,0x13,0xef,0xa6,0x87,0x96,
   1.802 +			0xa3,0x7d,0x5b,0x80,0xc2,0x38,0x76,0x61,
   1.803 +			0xc7,0x80,0x5d,0x0f,0x05,0x76,0x85 };
   1.804 +   static const PRUint8 rng_no_reseed_result[] = {
   1.805 +			0xc4,0x40,0x41,0x8c,0xbf,0x2f,0x70,0x23,
   1.806 +			0x88,0xf2,0x7b,0x30,0xc3,0xca,0x1e,0xf3,
   1.807 +			0xef,0x53,0x81,0x5d,0x30,0xed,0x4c,0xf1,
   1.808 +			0xff,0x89,0xa5,0xee,0x92,0xf8,0xc0,0x0f,
   1.809 +			0x88,0x53,0xdf,0xb6,0x76,0xf0,0xaa,0xd3,
   1.810 +			0x2e,0x1d,0x64,0x37,0x3e,0xe8,0x4a,0x02,
   1.811 +			0xff,0x0a,0x7f,0xe5,0xe9,0x2b,0x6d };
   1.812 +
   1.813 +   SECStatus rng_status = SECSuccess;
   1.814 +   PR_STATIC_ASSERT(sizeof(rng_known_result) >= sizeof(rng_reseed_result));
   1.815 +   PRUint8 result[sizeof(rng_known_result)];
   1.816 +
   1.817 +   /********************************************/
   1.818 +   /*   First test instantiate error path.     */
   1.819 +   /*   In this case we supply enough entropy, */
   1.820 +   /*   but not enough seed. This will trigger */
   1.821 +   /*   the code that checks for a entropy     */
   1.822 +   /*   source failure.                        */
   1.823 +   /********************************************/
   1.824 +   rng_status = PRNGTEST_Instantiate(entropy, 256/PR_BITS_PER_BYTE, 
   1.825 +				     NULL, 0, NULL, 0);
   1.826 +   if (rng_status == SECSuccess) {
   1.827 +	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1.828 +	return SECFailure;
   1.829 +   }
   1.830 +   if (PORT_GetError() != SEC_ERROR_NEED_RANDOM) {
   1.831 +	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1.832 +	return SECFailure;
   1.833 +   }
   1.834 +   /* we failed with the proper error code, we can continue */
   1.835 +
   1.836 +   /********************************************/
   1.837 +   /* Generate random bytes with a known seed. */
   1.838 +   /********************************************/
   1.839 +   rng_status = PRNGTEST_Instantiate(entropy, sizeof entropy, 
   1.840 +				     NULL, 0, NULL, 0);
   1.841 +   if (rng_status != SECSuccess) {
   1.842 +	/* Error set by PRNGTEST_Instantiate */
   1.843 +	return SECFailure;
   1.844 +   }
   1.845 +   rng_status = PRNGTEST_Generate(result, sizeof rng_known_result, NULL, 0);
   1.846 +   if ( ( rng_status != SECSuccess)  ||
   1.847 +        ( PORT_Memcmp( result, rng_known_result,
   1.848 +                       sizeof rng_known_result ) != 0 ) ) {
   1.849 +	PRNGTEST_Uninstantiate();
   1.850 +	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1.851 +	return SECFailure;
   1.852 +   }
   1.853 +   rng_status = PRNGTEST_Reseed(reseed_entropy, sizeof reseed_entropy,
   1.854 +				additional_input, sizeof additional_input);
   1.855 +   if (rng_status != SECSuccess) {
   1.856 +	/* Error set by PRNG_Reseed */
   1.857 +	PRNGTEST_Uninstantiate();
   1.858 +	return SECFailure;
   1.859 +   }
   1.860 +   rng_status = PRNGTEST_Generate(result, sizeof rng_reseed_result, NULL, 0);
   1.861 +   if ( ( rng_status != SECSuccess)  ||
   1.862 +        ( PORT_Memcmp( result, rng_reseed_result,
   1.863 +                       sizeof rng_reseed_result ) != 0 ) ) {
   1.864 +	PRNGTEST_Uninstantiate();
   1.865 +	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1.866 +	return SECFailure;
   1.867 +   }
   1.868 +   /* This magic forces the reseed count to it's max count, so we can see if
   1.869 +    * PRNGTEST_Generate will actually when it reaches it's count */
   1.870 +   rng_status = PRNGTEST_Reseed(NULL, 0, NULL, 0);
   1.871 +   if (rng_status != SECSuccess) {
   1.872 +	PRNGTEST_Uninstantiate();
   1.873 +	/* Error set by PRNG_Reseed */
   1.874 +	return SECFailure;
   1.875 +   }
   1.876 +   /* This generate should now reseed */
   1.877 +   rng_status = PRNGTEST_Generate(result, sizeof rng_reseed_result, NULL, 0);
   1.878 +   if ( ( rng_status != SECSuccess)  ||
   1.879 +	/* NOTE we fail if the result is equal to the no_reseed_result. 
   1.880 +         * no_reseed_result is the value we would have gotten if we didn't
   1.881 +	 * do an automatic reseed in PRNGTEST_Generate */
   1.882 +        ( PORT_Memcmp( result, rng_no_reseed_result,
   1.883 +                       sizeof rng_no_reseed_result ) == 0 ) ) {
   1.884 +	PRNGTEST_Uninstantiate();
   1.885 +	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1.886 +	return SECFailure;
   1.887 +   }
   1.888 +   /* make sure reseed fails when we don't supply enough entropy */
   1.889 +   rng_status = PRNGTEST_Reseed(reseed_entropy, 4, NULL, 0);
   1.890 +   if (rng_status == SECSuccess) {
   1.891 +	PRNGTEST_Uninstantiate();
   1.892 +	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1.893 +	return SECFailure;
   1.894 +   }
   1.895 +   if (PORT_GetError() != SEC_ERROR_NEED_RANDOM) {
   1.896 +	PRNGTEST_Uninstantiate();
   1.897 +	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1.898 +	return SECFailure;
   1.899 +   }
   1.900 +   rng_status = PRNGTEST_Uninstantiate();
   1.901 +   if (rng_status != SECSuccess) {
   1.902 +	/* Error set by PRNG_Uninstantiate */
   1.903 +	return rng_status;
   1.904 +   }
   1.905 +   /* make sure uninstantiate fails if the contest is not initiated (also tests
   1.906 +    * if the context was cleared in the previous Uninstantiate) */
   1.907 +   rng_status = PRNGTEST_Uninstantiate();
   1.908 +   if (rng_status == SECSuccess) {
   1.909 +	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1.910 +	return SECFailure;
   1.911 +   }
   1.912 +   if (PORT_GetError() != SEC_ERROR_LIBRARY_FAILURE) {
   1.913 +	return rng_status;
   1.914 +   }
   1.915 +  
   1.916 +   return SECSuccess;
   1.917 +}

mercurial