Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: mozilla/security/nss/lib/freebl/drbg.c

Issue 10961060: Update NSS to NSS 3.14 Beta 1. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/nss/
Patch Set: Add the NSS snapshot timestamp to README.chromium and nss-checkout.sh Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « mozilla/security/nss/lib/freebl/dh.c ('k') | mozilla/security/nss/lib/freebl/dsa.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* This Source Code Form is subject to the terms of the Mozilla Public 1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 /* $Id: drbg.c,v 1.11 2012/06/28 17:55:05 rrelyea%redhat.com Exp $ */ 4 /* $Id: drbg.c,v 1.11 2012/06/28 17:55:05 rrelyea%redhat.com Exp $ */
5 5
6 #ifdef FREEBL_NO_DEPEND 6 #ifdef FREEBL_NO_DEPEND
7 #include "stubs.h" 7 #include "stubs.h"
8 #endif 8 #endif
9 9
10 #include "prerror.h" 10 #include "prerror.h"
(...skipping 14 matching lines...) Expand all
25 * for SHA-1, SHA-224, and SHA-256 it's 440 bits. 25 * for SHA-1, SHA-224, and SHA-256 it's 440 bits.
26 * for SHA-384 and SHA-512 it's 888 bits */ 26 * for SHA-384 and SHA-512 it's 888 bits */
27 #define PRNG_SEEDLEN (440/PR_BITS_PER_BYTE) 27 #define PRNG_SEEDLEN (440/PR_BITS_PER_BYTE)
28 static const PRInt64 PRNG_MAX_ADDITIONAL_BYTES = LL_INIT(0x1, 0x0); 28 static const PRInt64 PRNG_MAX_ADDITIONAL_BYTES = LL_INIT(0x1, 0x0);
29 /* 2^35 bits or 2^32 bytes */ 29 /* 2^35 bits or 2^32 bytes */
30 #define PRNG_MAX_REQUEST_SIZE 0x10000 /* 2^19 bits or 2^16 bytes */ 30 #define PRNG_MAX_REQUEST_SIZE 0x10000 /* 2^19 bits or 2^16 bytes */
31 #define PRNG_ADDITONAL_DATA_CACHE_SIZE (8*1024) /* must be less than 31 #define PRNG_ADDITONAL_DATA_CACHE_SIZE (8*1024) /* must be less than
32 * PRNG_MAX_ADDITIONAL_BYTES 32 * PRNG_MAX_ADDITIONAL_BYTES
33 */ 33 */
34 34
35
36 /* RESEED_COUNT is how many calls to the prng before we need to reseed 35 /* RESEED_COUNT is how many calls to the prng before we need to reseed
37 * under normal NIST rules, you must return an error. In the NSS case, we 36 * under normal NIST rules, you must return an error. In the NSS case, we
38 * self-reseed with RNG_SystemRNG(). Count can be a large number. For code 37 * self-reseed with RNG_SystemRNG(). Count can be a large number. For code
39 * simplicity, we specify count with 2 components: RESEED_BYTE (which is 38 * simplicity, we specify count with 2 components: RESEED_BYTE (which is
40 * the same as LOG256(RESEED_COUNT)) and RESEED_VALUE (which is the same as 39 * the same as LOG256(RESEED_COUNT)) and RESEED_VALUE (which is the same as
41 * RESEED_COUNT / (256 ^ RESEED_BYTE)). Another way to look at this is 40 * RESEED_COUNT / (256 ^ RESEED_BYTE)). Another way to look at this is
42 * RESEED_COUNT = RESEED_VALUE * (256 ^ RESEED_BYTE). For Hash based DRBG 41 * RESEED_COUNT = RESEED_VALUE * (256 ^ RESEED_BYTE). For Hash based DRBG
43 * we use the maximum count value, 2^48, or RESEED_BYTE=6 and RESEED_VALUE=1 42 * we use the maximum count value, 2^48, or RESEED_BYTE=6 and RESEED_VALUE=1
44 */ 43 */
45 #define RESEED_BYTE 6 44 #define RESEED_BYTE 6
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 } 149 }
151 150
152 151
153 /* 152 /*
154 * Hash_DRBG Instantiate NIST SP 800-80 10.1.1.2 153 * Hash_DRBG Instantiate NIST SP 800-80 10.1.1.2
155 * 154 *
156 * NOTE: bytes & len are entropy || nonce || personalization_string. In 155 * NOTE: bytes & len are entropy || nonce || personalization_string. In
157 * normal operation, NSS calculates them all together in a single call. 156 * normal operation, NSS calculates them all together in a single call.
158 */ 157 */
159 static SECStatus 158 static SECStatus
160 prng_instantiate(RNGContext *rng, PRUint8 *bytes, unsigned int len) 159 prng_instantiate(RNGContext *rng, const PRUint8 *bytes, unsigned int len)
161 { 160 {
161 if (len < PRNG_SEEDLEN) {
162 /* if the seedlen is to small, it's probably because we failed to get
163 * enough random data */
164 PORT_SetError(SEC_ERROR_NEED_RANDOM);
165 return SECFailure;
166 }
162 prng_Hash_df(V(rng), VSize(rng), bytes, len, NULL, 0); 167 prng_Hash_df(V(rng), VSize(rng), bytes, len, NULL, 0);
163 rng->V_type = prngCGenerateType; 168 rng->V_type = prngCGenerateType;
164 prng_Hash_df(rng->C,sizeof rng->C,rng->V_Data,sizeof rng->V_Data,NULL,0); 169 prng_Hash_df(rng->C,sizeof rng->C,rng->V_Data,sizeof rng->V_Data,NULL,0);
165 PRNG_RESET_RESEED_COUNT(rng) 170 PRNG_RESET_RESEED_COUNT(rng)
166 return SECSuccess; 171 return SECSuccess;
167 } 172 }
168 173
169 174
170 /* 175 /*
171 * Update the global random number generator with more seeding 176 * Update the global random number generator with more seeding
172 * material. Use the Hash_DRBG reseed algorithm from NIST SP-800-90 177 * material. Use the Hash_DRBG reseed algorithm from NIST SP-800-90
173 * section 10.1.1.3 178 * section 10.1.1.3
174 * 179 *
175 * If entropy is NULL, it is fetched from the noise generator. 180 * If entropy is NULL, it is fetched from the noise generator.
176 */ 181 */
177 static 182 static SECStatus
178 SECStatus
179 prng_reseed(RNGContext *rng, const PRUint8 *entropy, unsigned int entropy_len, 183 prng_reseed(RNGContext *rng, const PRUint8 *entropy, unsigned int entropy_len,
180 const PRUint8 *additional_input, unsigned int additional_input_len) 184 const PRUint8 *additional_input, unsigned int additional_input_len)
181 { 185 {
182 PRUint8 noiseData[(sizeof rng->V_Data)+PRNG_SEEDLEN]; 186 PRUint8 noiseData[(sizeof rng->V_Data)+PRNG_SEEDLEN];
183 PRUint8 *noise = &noiseData[0]; 187 PRUint8 *noise = &noiseData[0];
184 188
185 /* if entropy wasn't supplied, fetch it. (normal operation case) */ 189 /* if entropy wasn't supplied, fetch it. (normal operation case) */
186 if (entropy == NULL) { 190 if (entropy == NULL) {
187 entropy_len = (unsigned int) RNG_SystemRNG( 191 entropy_len = (unsigned int) RNG_SystemRNG(
188 &noiseData[sizeof rng->V_Data], PRNG_SEEDLEN); 192 &noiseData[sizeof rng->V_Data], PRNG_SEEDLEN);
189 } else { 193 } else {
190 /* NOTE: this code is only available for testing, not to applications */ 194 /* NOTE: this code is only available for testing, not to applications */
191 /* if entropy was too big for the stack variable, get it from malloc */ 195 /* if entropy was too big for the stack variable, get it from malloc */
192 if (entropy_len > PRNG_SEEDLEN) { 196 if (entropy_len > PRNG_SEEDLEN) {
193 noise = PORT_Alloc(entropy_len + (sizeof rng->V_Data)); 197 noise = PORT_Alloc(entropy_len + (sizeof rng->V_Data));
194 if (noise == NULL) { 198 if (noise == NULL) {
195 return SECFailure; 199 return SECFailure;
196 } 200 }
197 } 201 }
198 PORT_Memcpy(&noise[sizeof rng->V_Data],entropy, entropy_len); 202 PORT_Memcpy(&noise[sizeof rng->V_Data],entropy, entropy_len);
199 } 203 }
200 204
205 if (entropy_len < 256/PR_BITS_PER_BYTE) {
206 /* noise == &noiseData[0] at this point, so nothing to free */
207 PORT_SetError(SEC_ERROR_NEED_RANDOM);
208 return SECFailure;
209 }
210
201 rng->V_type = prngReseedType; 211 rng->V_type = prngReseedType;
202 PORT_Memcpy(noise, rng->V_Data, sizeof rng->V_Data); 212 PORT_Memcpy(noise, rng->V_Data, sizeof rng->V_Data);
203 prng_Hash_df(V(rng), VSize(rng), noise, (sizeof rng->V_Data) + entropy_len, 213 prng_Hash_df(V(rng), VSize(rng), noise, (sizeof rng->V_Data) + entropy_len,
204 additional_input, additional_input_len); 214 additional_input, additional_input_len);
205 /* clear potential CSP */ 215 /* clear potential CSP */
206 PORT_Memset(noise, 0, (sizeof rng->V_Data) + entropy_len); 216 PORT_Memset(noise, 0, (sizeof rng->V_Data) + entropy_len);
207 rng->V_type = prngCGenerateType; 217 rng->V_type = prngCGenerateType;
208 prng_Hash_df(rng->C,sizeof rng->C,rng->V_Data,sizeof rng->V_Data,NULL,0); 218 prng_Hash_df(rng->C,sizeof rng->C,rng->V_Data,sizeof rng->V_Data,NULL,0);
209 PRNG_RESET_RESEED_COUNT(rng) 219 PRNG_RESET_RESEED_COUNT(rng)
210 220
211 if (noise != &noiseData[0]) { 221 if (noise != &noiseData[0]) {
212 PORT_Free(noise); 222 PORT_Free(noise);
213 } 223 }
214 return SECSuccess; 224 return SECSuccess;
215 } 225 }
216 226
217 /* 227 /*
228 * SP 800-90 requires we rerun our health tests on reseed
229 */
230 static SECStatus
231 prng_reseed_test(RNGContext *rng, const PRUint8 *entropy,
232 unsigned int entropy_len, const PRUint8 *additional_input,
233 unsigned int additional_input_len)
234 {
235 SECStatus rv;
236
237 /* do health checks in FIPS mode */
238 rv = PRNGTEST_RunHealthTests();
239 if (rv != SECSuccess) {
240 /* error set by PRNGTEST_RunHealTests() */
241 rng->isValid = PR_FALSE;
242 return SECFailure;
243 }
244 return prng_reseed(rng, entropy, entropy_len,
245 additional_input, additional_input_len);
246 }
247
248 /*
218 * build some fast inline functions for adding. 249 * build some fast inline functions for adding.
219 */ 250 */
220 #define PRNG_ADD_CARRY_ONLY(dest, start, cy) \ 251 #define PRNG_ADD_CARRY_ONLY(dest, start, cy) \
221 carry = cy; \ 252 carry = cy; \
222 for (k1=start; carry && k1 >=0 ; k1--) { \ 253 for (k1=start; carry && k1 >=0 ; k1--) { \
223 carry = !(++dest[k1]); \ 254 carry = !(++dest[k1]); \
224 } 255 }
225 256
226 /* 257 /*
227 * NOTE: dest must be an array for the following to work. 258 * NOTE: dest must be an array for the following to work.
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 369
339 /* Use NSPR to prevent RNG_RNGInit from being called from separate 370 /* Use NSPR to prevent RNG_RNGInit from being called from separate
340 * threads, creating a race condition. 371 * threads, creating a race condition.
341 */ 372 */
342 static const PRCallOnceType pristineCallOnce; 373 static const PRCallOnceType pristineCallOnce;
343 static PRCallOnceType coRNGInit; 374 static PRCallOnceType coRNGInit;
344 static PRStatus rng_init(void) 375 static PRStatus rng_init(void)
345 { 376 {
346 PRUint8 bytes[PRNG_SEEDLEN*2]; /* entropy + nonce */ 377 PRUint8 bytes[PRNG_SEEDLEN*2]; /* entropy + nonce */
347 unsigned int numBytes; 378 unsigned int numBytes;
379 SECStatus rv = SECSuccess;
380
348 if (globalrng == NULL) { 381 if (globalrng == NULL) {
349 /* bytes needs to have enough space to hold 382 /* bytes needs to have enough space to hold
350 * a SHA256 hash value. Blow up at compile time if this isn't true */ 383 * a SHA256 hash value. Blow up at compile time if this isn't true */
351 PR_STATIC_ASSERT(sizeof(bytes) >= SHA256_LENGTH); 384 PR_STATIC_ASSERT(sizeof(bytes) >= SHA256_LENGTH);
352 /* create a new global RNG context */ 385 /* create a new global RNG context */
353 globalrng = &theGlobalRng; 386 globalrng = &theGlobalRng;
354 PORT_Assert(NULL == globalrng->lock); 387 PORT_Assert(NULL == globalrng->lock);
355 /* create a lock for it */ 388 /* create a lock for it */
356 globalrng->lock = PZ_NewLock(nssILockOther); 389 globalrng->lock = PZ_NewLock(nssILockOther);
357 if (globalrng->lock == NULL) { 390 if (globalrng->lock == NULL) {
358 globalrng = NULL; 391 globalrng = NULL;
359 PORT_SetError(PR_OUT_OF_MEMORY_ERROR); 392 PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
360 return PR_FAILURE; 393 return PR_FAILURE;
361 } 394 }
362 395
363 /* Try to get some seed data for the RNG */ 396 /* Try to get some seed data for the RNG */
364 numBytes = (unsigned int) RNG_SystemRNG(bytes, sizeof bytes); 397 numBytes = (unsigned int) RNG_SystemRNG(bytes, sizeof bytes);
365 PORT_Assert(numBytes == 0 || numBytes == sizeof bytes); 398 PORT_Assert(numBytes == 0 || numBytes == sizeof bytes);
366 if (numBytes != 0) { 399 if (numBytes != 0) {
367 /* if this is our first call, instantiate, otherwise reseed 400 /* if this is our first call, instantiate, otherwise reseed
368 * prng_instantiate gets a new clean state, we want to mix 401 * prng_instantiate gets a new clean state, we want to mix
369 * any previous entropy we may have collected */ 402 * any previous entropy we may have collected */
370 if (V(globalrng)[0] == 0) { 403 if (V(globalrng)[0] == 0) {
371 » » prng_instantiate(globalrng, bytes, numBytes); 404 » » rv = prng_instantiate(globalrng, bytes, numBytes);
372 } else { 405 } else {
373 » » prng_reseed(globalrng, bytes, numBytes, NULL, 0); 406 » » rv = prng_reseed_test(globalrng, bytes, numBytes, NULL, 0);
374 } 407 }
375 memset(bytes, 0, numBytes); 408 memset(bytes, 0, numBytes);
376 } else { 409 } else {
377 PZ_DestroyLock(globalrng->lock); 410 PZ_DestroyLock(globalrng->lock);
378 globalrng->lock = NULL; 411 globalrng->lock = NULL;
379 globalrng = NULL; 412 globalrng = NULL;
380 return PR_FAILURE; 413 return PR_FAILURE;
381 } 414 }
415
416 if (rv != SECSuccess) {
417 return PR_FAILURE;
418 }
382 /* the RNG is in a valid state */ 419 /* the RNG is in a valid state */
383 globalrng->isValid = PR_TRUE; 420 globalrng->isValid = PR_TRUE;
384 421
385 /* fetch one random value so that we can populate rng->oldV for our 422 /* fetch one random value so that we can populate rng->oldV for our
386 * continous random number test. */ 423 * continous random number test. */
387 prng_generateNewBytes(globalrng, bytes, SHA256_LENGTH, NULL, 0); 424 prng_generateNewBytes(globalrng, bytes, SHA256_LENGTH, NULL, 0);
388 425
389 /* Fetch more entropy into the PRNG */ 426 /* Fetch more entropy into the PRNG */
390 RNG_SystemInfoForRNG(); 427 RNG_SystemInfoForRNG();
391 } 428 }
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 bytes = PRNG_MAX_ADDITIONAL_BYTES; 515 bytes = PRNG_MAX_ADDITIONAL_BYTES;
479 } 516 }
480 #else 517 #else
481 PR_STATIC_ASSERT(sizeof(size_t) <= 4); 518 PR_STATIC_ASSERT(sizeof(size_t) <= 4);
482 #endif 519 #endif
483 520
484 PZ_Lock(globalrng->lock); 521 PZ_Lock(globalrng->lock);
485 /* if we're passed more than our additionalDataCache, simply 522 /* if we're passed more than our additionalDataCache, simply
486 * call reseed with that data */ 523 * call reseed with that data */
487 if (bytes > sizeof (globalrng->additionalDataCache)) { 524 if (bytes > sizeof (globalrng->additionalDataCache)) {
488 » rv = prng_reseed(globalrng, NULL, 0, data, (unsigned int) bytes); 525 » rv = prng_reseed_test(globalrng, NULL, 0, data, (unsigned int) bytes);
489 /* if we aren't going to fill or overflow the buffer, just cache it */ 526 /* if we aren't going to fill or overflow the buffer, just cache it */
490 } else if (bytes < ((sizeof globalrng->additionalDataCache) 527 } else if (bytes < ((sizeof globalrng->additionalDataCache)
491 - globalrng->additionalAvail)) { 528 - globalrng->additionalAvail)) {
492 PORT_Memcpy(globalrng->additionalDataCache+globalrng->additionalAvail, 529 PORT_Memcpy(globalrng->additionalDataCache+globalrng->additionalAvail,
493 data, bytes); 530 data, bytes);
494 globalrng->additionalAvail += (PRUint32) bytes; 531 globalrng->additionalAvail += (PRUint32) bytes;
495 rv = SECSuccess; 532 rv = SECSuccess;
496 } else { 533 } else {
497 /* we are going to fill or overflow the buffer. In this case we will 534 /* we are going to fill or overflow the buffer. In this case we will
498 * fill the entropy buffer, reseed with it, start a new buffer with the 535 * fill the entropy buffer, reseed with it, start a new buffer with the
499 * remainder. We know the remainder will fit in the buffer because 536 * remainder. We know the remainder will fit in the buffer because
500 * we already handled the case where bytes > the size of the buffer. 537 * we already handled the case where bytes > the size of the buffer.
501 */ 538 */
502 size_t bufRemain = (sizeof globalrng->additionalDataCache) 539 size_t bufRemain = (sizeof globalrng->additionalDataCache)
503 - globalrng->additionalAvail; 540 - globalrng->additionalAvail;
504 /* fill the rest of the buffer */ 541 /* fill the rest of the buffer */
505 if (bufRemain) { 542 if (bufRemain) {
506 PORT_Memcpy(globalrng->additionalDataCache 543 PORT_Memcpy(globalrng->additionalDataCache
507 +globalrng->additionalAvail, 544 +globalrng->additionalAvail,
508 data, bufRemain); 545 data, bufRemain);
509 data = ((unsigned char *)data) + bufRemain; 546 data = ((unsigned char *)data) + bufRemain;
510 bytes -= bufRemain; 547 bytes -= bufRemain;
511 } 548 }
512 /* reseed from buffer */ 549 /* reseed from buffer */
513 » rv = prng_reseed(globalrng, NULL, 0, globalrng->additionalDataCache, 550 » rv = prng_reseed_test(globalrng, NULL, 0,
551 » » » » globalrng->additionalDataCache,
514 sizeof globalrng->additionalDataCache); 552 sizeof globalrng->additionalDataCache);
515 553
516 /* copy the rest into the cache */ 554 /* copy the rest into the cache */
517 PORT_Memcpy(globalrng->additionalDataCache, data, bytes); 555 PORT_Memcpy(globalrng->additionalDataCache, data, bytes);
518 globalrng->additionalAvail = (PRUint32) bytes; 556 globalrng->additionalAvail = (PRUint32) bytes;
519 } 557 }
520 558
521 PZ_Unlock(globalrng->lock); 559 PZ_Unlock(globalrng->lock);
522 return rv; 560 return rv;
523 } 561 }
(...skipping 18 matching lines...) Expand all
542 if (len > PRNG_MAX_REQUEST_SIZE) { 580 if (len > PRNG_MAX_REQUEST_SIZE) {
543 PORT_SetError(SEC_ERROR_INVALID_ARGS); 581 PORT_SetError(SEC_ERROR_INVALID_ARGS);
544 return SECFailure; 582 return SECFailure;
545 } 583 }
546 /* --- LOCKED --- */ 584 /* --- LOCKED --- */
547 PZ_Lock(rng->lock); 585 PZ_Lock(rng->lock);
548 /* Check the amount of seed data in the generator. If not enough, 586 /* Check the amount of seed data in the generator. If not enough,
549 * don't produce any data. 587 * don't produce any data.
550 */ 588 */
551 if (rng->reseed_counter[0] >= RESEED_VALUE) { 589 if (rng->reseed_counter[0] >= RESEED_VALUE) {
552 » rv = prng_reseed(rng, NULL, 0, NULL, 0); 590 » rv = prng_reseed_test(rng, NULL, 0, NULL, 0);
553 PZ_Unlock(rng->lock); 591 PZ_Unlock(rng->lock);
554 if (rv != SECSuccess) { 592 if (rv != SECSuccess) {
555 return rv; 593 return rv;
556 } 594 }
557 RNG_SystemInfoForRNG(); 595 RNG_SystemInfoForRNG();
558 PZ_Lock(rng->lock); 596 PZ_Lock(rng->lock);
559 } 597 }
560 /* 598 /*
561 * see if we have enough bytes to fulfill the request. 599 * see if we have enough bytes to fulfill the request.
562 */ 600 */
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 return prng_GenerateGlobalRandomBytes(globalrng, dest, len); 637 return prng_GenerateGlobalRandomBytes(globalrng, dest, len);
600 } 638 }
601 639
602 void 640 void
603 RNG_RNGShutdown(void) 641 RNG_RNGShutdown(void)
604 { 642 {
605 /* check for a valid global RNG context */ 643 /* check for a valid global RNG context */
606 PORT_Assert(globalrng != NULL); 644 PORT_Assert(globalrng != NULL);
607 if (globalrng == NULL) { 645 if (globalrng == NULL) {
608 /* Should set a "not initialized" error code. */ 646 /* Should set a "not initialized" error code. */
609 » PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 647 » PORT_SetError(SEC_ERROR_NO_MEMORY);
610 return; 648 return;
611 } 649 }
612 /* clear */ 650 /* clear */
613 prng_freeRNGContext(globalrng); 651 prng_freeRNGContext(globalrng);
614 globalrng = NULL; 652 globalrng = NULL;
615 /* reset the callonce struct to allow a new call to RNG_RNGInit() */ 653 /* reset the callonce struct to allow a new call to RNG_RNGInit() */
616 coRNGInit = pristineCallOnce; 654 coRNGInit = pristineCallOnce;
617 } 655 }
618 656
619 /* 657 /*
620 * Test case interface. used by fips testing and power on self test 658 * Test case interface. used by fips testing and power on self test
621 */ 659 */
622 /* make sure the test context is separate from the global context, This 660 /* make sure the test context is separate from the global context, This
623 * allows us to test the internal random number generator without losing 661 * allows us to test the internal random number generator without losing
624 * entropy we may have previously collected. */ 662 * entropy we may have previously collected. */
625 RNGContext testContext; 663 RNGContext testContext;
626 664
627 /* 665 /*
628 * Test vector API. Use NIST SP 800-90 general interface so one of the 666 * Test vector API. Use NIST SP 800-90 general interface so one of the
629 * other NIST SP 800-90 algorithms may be used in the future. 667 * other NIST SP 800-90 algorithms may be used in the future.
630 */ 668 */
631 SECStatus 669 SECStatus
632 PRNGTEST_Instantiate(const PRUint8 *entropy, unsigned int entropy_len, 670 PRNGTEST_Instantiate(const PRUint8 *entropy, unsigned int entropy_len,
633 const PRUint8 *nonce, unsigned int nonce_len, 671 const PRUint8 *nonce, unsigned int nonce_len,
634 const PRUint8 *personal_string, unsigned int ps_len) 672 const PRUint8 *personal_string, unsigned int ps_len)
635 { 673 {
636 int bytes_len = entropy_len + nonce_len + ps_len; 674 int bytes_len = entropy_len + nonce_len + ps_len;
637 PRUint8 *bytes = PORT_Alloc(bytes_len); 675 PRUint8 *bytes = NULL;
676 SECStatus rv;
638 677
678 if (entropy_len < 256/PR_BITS_PER_BYTE) {
679 PORT_SetError(SEC_ERROR_NEED_RANDOM);
680 return SECFailure;
681 }
682
683 bytes = PORT_Alloc(bytes_len);
639 if (bytes == NULL) { 684 if (bytes == NULL) {
685 PORT_SetError(SEC_ERROR_NO_MEMORY);
640 return SECFailure; 686 return SECFailure;
641 } 687 }
642 /* concatenate the various inputs, internally NSS only instantiates with 688 /* concatenate the various inputs, internally NSS only instantiates with
643 * a single long string */ 689 * a single long string */
644 PORT_Memcpy(bytes, entropy, entropy_len); 690 PORT_Memcpy(bytes, entropy, entropy_len);
645 if (nonce) { 691 if (nonce) {
646 PORT_Memcpy(&bytes[entropy_len], nonce, nonce_len); 692 PORT_Memcpy(&bytes[entropy_len], nonce, nonce_len);
647 } else { 693 } else {
648 PORT_Assert(nonce_len == 0); 694 PORT_Assert(nonce_len == 0);
649 } 695 }
650 if (personal_string) { 696 if (personal_string) {
651 PORT_Memcpy(&bytes[entropy_len+nonce_len], personal_string, ps_len); 697 PORT_Memcpy(&bytes[entropy_len+nonce_len], personal_string, ps_len);
652 } else { 698 } else {
653 PORT_Assert(ps_len == 0); 699 PORT_Assert(ps_len == 0);
654 } 700 }
655 prng_instantiate(&testContext, bytes, bytes_len); 701 rv = prng_instantiate(&testContext, bytes, bytes_len);
702 PORT_ZFree(bytes, bytes_len);
703 if (rv == SECFailure) {
704 » return SECFailure;
705 }
656 testContext.isValid = PR_TRUE; 706 testContext.isValid = PR_TRUE;
657 PORT_ZFree(bytes, bytes_len);
658 return SECSuccess; 707 return SECSuccess;
659 } 708 }
660 709
661 SECStatus 710 SECStatus
662 PRNGTEST_Reseed(const PRUint8 *entropy, unsigned int entropy_len, 711 PRNGTEST_Reseed(const PRUint8 *entropy, unsigned int entropy_len,
663 const PRUint8 *additional, unsigned int additional_len) 712 const PRUint8 *additional, unsigned int additional_len)
664 { 713 {
665 if (!testContext.isValid) { 714 if (!testContext.isValid) {
666 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 715 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
667 return SECFailure; 716 return SECFailure;
668 } 717 }
718 /* This magic input tells us to set the reseed count to it's max count,
719 * so we can simulate PRNGTEST_Generate reaching max reseed count */
720 if ((entropy == NULL) && (entropy_len == 0) &&
721 (additional == NULL) && (additional_len == 0)) {
722 testContext.reseed_counter[0] = RESEED_VALUE;
723 return SECSuccess;
724 }
669 return prng_reseed(&testContext, entropy, entropy_len, additional, 725 return prng_reseed(&testContext, entropy, entropy_len, additional,
670 additional_len); 726 additional_len);
671 727
672 } 728 }
673 729
674 SECStatus 730 SECStatus
675 PRNGTEST_Generate(PRUint8 *bytes, unsigned int bytes_len, 731 PRNGTEST_Generate(PRUint8 *bytes, unsigned int bytes_len,
676 const PRUint8 *additional, unsigned int additional_len) 732 const PRUint8 *additional, unsigned int additional_len)
677 { 733 {
734 SECStatus rv;
678 if (!testContext.isValid) { 735 if (!testContext.isValid) {
679 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 736 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
680 return SECFailure; 737 return SECFailure;
681 } 738 }
739 /* replicate reseed test from prng_GenerateGlobalRandomBytes */
740 if (testContext.reseed_counter[0] >= RESEED_VALUE) {
741 rv = prng_reseed(&testContext, NULL, 0, NULL, 0);
742 if (rv != SECSuccess) {
743 return rv;
744 }
745 }
682 return prng_generateNewBytes(&testContext, bytes, bytes_len, 746 return prng_generateNewBytes(&testContext, bytes, bytes_len,
683 additional, additional_len); 747 additional, additional_len);
684 748
685 } 749 }
686 750
687 SECStatus 751 SECStatus
688 PRNGTEST_Uninstantiate() 752 PRNGTEST_Uninstantiate()
689 { 753 {
754 if (!testContext.isValid) {
755 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
756 return SECFailure;
757 }
690 PORT_Memset(&testContext, 0, sizeof testContext); 758 PORT_Memset(&testContext, 0, sizeof testContext);
691 return SECSuccess; 759 return SECSuccess;
692 } 760 }
693 761
762 SECStatus
763 PRNGTEST_RunHealthTests()
764 {
765 static const PRUint8 entropy[] = {
766 0x8e,0x9c,0x0d,0x25,0x75,0x22,0x04,0xf9,
767 0xc5,0x79,0x10,0x8b,0x23,0x79,0x37,0x14,
768 0x9f,0x2c,0xc7,0x0b,0x39,0xf8,0xee,0xef,
769 0x95,0x0c,0x97,0x59,0xfc,0x0a,0x85,0x41,
770 0x76,0x9d,0x6d,0x67,0x00,0x4e,0x19,0x12,
771 0x02,0x16,0x53,0xea,0xf2,0x73,0xd7,0xd6,
772 0x7f,0x7e,0xc8,0xae,0x9c,0x09,0x99,0x7d,
773 0xbb,0x9e,0x48,0x7f,0xbb,0x96,0x46,0xb3,
774 0x03,0x75,0xf8,0xc8,0x69,0x45,0x3f,0x97,
775 0x5e,0x2e,0x48,0xe1,0x5d,0x58,0x97,0x4c };
776 static const PRUint8 rng_known_result[] = {
777 0x16,0xe1,0x8c,0x57,0x21,0xd8,0xf1,0x7e,
778 0x5a,0xa0,0x16,0x0b,0x7e,0xa6,0x25,0xb4,
779 0x24,0x19,0xdb,0x54,0xfa,0x35,0x13,0x66,
780 0xbb,0xaa,0x2a,0x1b,0x22,0x33,0x2e,0x4a,
781 0x14,0x07,0x9d,0x52,0xfc,0x73,0x61,0x48,
782 0xac,0xc1,0x22,0xfc,0xa4,0xfc,0xac,0xa4,
783 0xdb,0xda,0x5b,0x27,0x33,0xc4,0xb3 };
784 static const PRUint8 reseed_entropy[] = {
785 0xc6,0x0b,0x0a,0x30,0x67,0x07,0xf4,0xe2,
786 0x24,0xa7,0x51,0x6f,0x5f,0x85,0x3e,0x5d,
787 0x67,0x97,0xb8,0x3b,0x30,0x9c,0x7a,0xb1,
788 0x52,0xc6,0x1b,0xc9,0x46,0xa8,0x62,0x79 };
789 static const PRUint8 additional_input[] = {
790 0x86,0x82,0x28,0x98,0xe7,0xcb,0x01,0x14,
791 0xae,0x87,0x4b,0x1d,0x99,0x1b,0xc7,0x41,
792 0x33,0xff,0x33,0x66,0x40,0x95,0x54,0xc6,
793 0x67,0x4d,0x40,0x2a,0x1f,0xf9,0xeb,0x65 };
794 static const PRUint8 rng_reseed_result[] = {
795 0x02,0x0c,0xc6,0x17,0x86,0x49,0xba,0xc4,
796 0x7b,0x71,0x35,0x05,0xf0,0xdb,0x4a,0xc2,
797 0x2c,0x38,0xc1,0xa4,0x42,0xe5,0x46,0x4a,
798 0x7d,0xf0,0xbe,0x47,0x88,0xb8,0x0e,0xc6,
799 0x25,0x2b,0x1d,0x13,0xef,0xa6,0x87,0x96,
800 0xa3,0x7d,0x5b,0x80,0xc2,0x38,0x76,0x61,
801 0xc7,0x80,0x5d,0x0f,0x05,0x76,0x85 };
802 static const PRUint8 rng_no_reseed_result[] = {
803 0xc4,0x40,0x41,0x8c,0xbf,0x2f,0x70,0x23,
804 0x88,0xf2,0x7b,0x30,0xc3,0xca,0x1e,0xf3,
805 0xef,0x53,0x81,0x5d,0x30,0xed,0x4c,0xf1,
806 0xff,0x89,0xa5,0xee,0x92,0xf8,0xc0,0x0f,
807 0x88,0x53,0xdf,0xb6,0x76,0xf0,0xaa,0xd3,
808 0x2e,0x1d,0x64,0x37,0x3e,0xe8,0x4a,0x02,
809 0xff,0x0a,0x7f,0xe5,0xe9,0x2b,0x6d };
694 810
811 SECStatus rng_status = SECSuccess;
812 PR_STATIC_ASSERT(sizeof(rng_known_result) >= sizeof(rng_reseed_result));
813 PRUint8 result[sizeof(rng_known_result)];
814
815 /********************************************/
816 /* First test instantiate error path. */
817 /* In this case we supply enough entropy, */
818 /* but not enough seed. This will trigger */
819 /* the code that checks for a entropy */
820 /* source failure. */
821 /********************************************/
822 rng_status = PRNGTEST_Instantiate(entropy, 256/PR_BITS_PER_BYTE,
823 NULL, 0, NULL, 0);
824 if (rng_status == SECSuccess) {
825 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
826 return SECFailure;
827 }
828 if (PORT_GetError() != SEC_ERROR_NEED_RANDOM) {
829 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
830 return SECFailure;
831 }
832 /* we failed with the proper error code, we can continue */
833
834 /********************************************/
835 /* Generate random bytes with a known seed. */
836 /********************************************/
837 rng_status = PRNGTEST_Instantiate(entropy, sizeof entropy,
838 NULL, 0, NULL, 0);
839 if (rng_status != SECSuccess) {
840 /* Error set by PRNGTEST_Instantiate */
841 return SECFailure;
842 }
843 rng_status = PRNGTEST_Generate(result, sizeof rng_known_result, NULL, 0);
844 if ( ( rng_status != SECSuccess) ||
845 ( PORT_Memcmp( result, rng_known_result,
846 sizeof rng_known_result ) != 0 ) ) {
847 PRNGTEST_Uninstantiate();
848 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
849 return SECFailure;
850 }
851 rng_status = PRNGTEST_Reseed(reseed_entropy, sizeof reseed_entropy,
852 additional_input, sizeof additional_input);
853 if (rng_status != SECSuccess) {
854 /* Error set by PRNG_Reseed */
855 PRNGTEST_Uninstantiate();
856 return SECFailure;
857 }
858 rng_status = PRNGTEST_Generate(result, sizeof rng_reseed_result, NULL, 0);
859 if ( ( rng_status != SECSuccess) ||
860 ( PORT_Memcmp( result, rng_reseed_result,
861 sizeof rng_reseed_result ) != 0 ) ) {
862 PRNGTEST_Uninstantiate();
863 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
864 return SECFailure;
865 }
866 /* This magic forces the reseed count to it's max count, so we can see if
867 * PRNGTEST_Generate will actually when it reaches it's count */
868 rng_status = PRNGTEST_Reseed(NULL, 0, NULL, 0);
869 if (rng_status != SECSuccess) {
870 PRNGTEST_Uninstantiate();
871 /* Error set by PRNG_Reseed */
872 return SECFailure;
873 }
874 /* This generate should now reseed */
875 rng_status = PRNGTEST_Generate(result, sizeof rng_reseed_result, NULL, 0);
876 if ( ( rng_status != SECSuccess) ||
877 /* NOTE we fail if the result is equal to the no_reseed_result.
878 * no_reseed_result is the value we would have gotten if we didn't
879 * do an automatic reseed in PRNGTEST_Generate */
880 ( PORT_Memcmp( result, rng_no_reseed_result,
881 sizeof rng_no_reseed_result ) == 0 ) ) {
882 PRNGTEST_Uninstantiate();
883 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
884 return SECFailure;
885 }
886 /* make sure reseed fails when we don't supply enough entropy */
887 rng_status = PRNGTEST_Reseed(reseed_entropy, 4, NULL, 0);
888 if (rng_status == SECSuccess) {
889 PRNGTEST_Uninstantiate();
890 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
891 return SECFailure;
892 }
893 if (PORT_GetError() != SEC_ERROR_NEED_RANDOM) {
894 PRNGTEST_Uninstantiate();
895 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
896 return SECFailure;
897 }
898 rng_status = PRNGTEST_Uninstantiate();
899 if (rng_status != SECSuccess) {
900 /* Error set by PRNG_Uninstantiate */
901 return rng_status;
902 }
903 /* make sure uninstantiate fails if the contest is not initiated (also tests
904 * if the context was cleared in the previous Uninstantiate) */
905 rng_status = PRNGTEST_Uninstantiate();
906 if (rng_status == SECSuccess) {
907 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
908 return SECFailure;
909 }
910 if (PORT_GetError() != SEC_ERROR_LIBRARY_FAILURE) {
911 return rng_status;
912 }
913
914 return SECSuccess;
915 }
OLDNEW
« no previous file with comments | « mozilla/security/nss/lib/freebl/dh.c ('k') | mozilla/security/nss/lib/freebl/dsa.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698