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 +}