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

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

Issue 14249009: Change the NSS and NSPR source tree to the new directory structure to be (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/nss/
Patch Set: Created 7 years, 8 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
(Empty)
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
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 /* $Id: drbg.c,v 1.12 2012/12/12 19:22:39 wtc%google.com Exp $ */
5
6 #ifdef FREEBL_NO_DEPEND
7 #include "stubs.h"
8 #endif
9
10 #include "prerror.h"
11 #include "secerr.h"
12
13 #include "prtypes.h"
14 #include "prinit.h"
15 #include "blapi.h"
16 #include "blapii.h"
17 #include "nssilock.h"
18 #include "secitem.h"
19 #include "sha_fast.h"
20 #include "sha256.h"
21 #include "secrng.h" /* for RNG_SystemRNG() */
22 #include "secmpi.h"
23
24 /* PRNG_SEEDLEN defined in NIST SP 800-90 section 10.1
25 * for SHA-1, SHA-224, and SHA-256 it's 440 bits.
26 * for SHA-384 and SHA-512 it's 888 bits */
27 #define PRNG_SEEDLEN (440/PR_BITS_PER_BYTE)
28 static const PRInt64 PRNG_MAX_ADDITIONAL_BYTES = LL_INIT(0x1, 0x0);
29 /* 2^35 bits or 2^32 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
32 * PRNG_MAX_ADDITIONAL_BYTES
33 */
34
35 /* RESEED_COUNT is how many calls to the prng before we need to reseed
36 * under normal NIST rules, you must return an error. In the NSS case, we
37 * self-reseed with RNG_SystemRNG(). Count can be a large number. For code
38 * simplicity, we specify count with 2 components: RESEED_BYTE (which is
39 * the same as LOG256(RESEED_COUNT)) and RESEED_VALUE (which is the same as
40 * RESEED_COUNT / (256 ^ RESEED_BYTE)). Another way to look at this is
41 * RESEED_COUNT = RESEED_VALUE * (256 ^ RESEED_BYTE). For Hash based DRBG
42 * we use the maximum count value, 2^48, or RESEED_BYTE=6 and RESEED_VALUE=1
43 */
44 #define RESEED_BYTE 6
45 #define RESEED_VALUE 1
46
47 #define PRNG_RESET_RESEED_COUNT(rng) \
48 PORT_Memset((rng)->reseed_counter, 0, sizeof (rng)->reseed_counter); \
49 (rng)->reseed_counter[RESEED_BYTE] = 1;
50
51
52 /*
53 * The actual values of this enum are specified in SP 800-90, 10.1.1.*
54 * The spec does not name the types, it only uses bare values
55 */
56 typedef enum {
57 prngCGenerateType = 0, /* used when creating a new 'C' */
58 prngReseedType = 1, /* used in reseeding */
59 prngAdditionalDataType = 2, /* used in mixing additional data */
60 prngGenerateByteType = 3 /* used when mixing internal state while
61 * generating bytes */
62 } prngVTypes;
63
64 /*
65 * Global RNG context
66 */
67 struct RNGContextStr {
68 PZLock *lock; /* Lock to serialize access to global rng */
69 /*
70 * NOTE, a number of steps in the drbg algorithm need to hash
71 * V_type || V. The code, therefore, depends on the V array following
72 * immediately after V_type to avoid extra copies. To accomplish this
73 * in a way that compiliers can't perturb, we declare V_type and V
74 * as a V_Data array and reference them by macros */
75 PRUint8 V_Data[PRNG_SEEDLEN+1]; /* internal state variables */
76 #define V_type V_Data[0]
77 #define V(rng) (((rng)->V_Data)+1)
78 #define VSize(rng) ((sizeof (rng)->V_Data) -1)
79 PRUint8 C[PRNG_SEEDLEN]; /* internal state variables */
80 PRUint8 oldV[PRNG_SEEDLEN]; /* for continuous rng checking */
81 /* If we get calls for the PRNG to return less than the length of our
82 * hash, we extend the request for a full hash (since we'll be doing
83 * the full hash anyway). Future requests for random numbers are fulfilled
84 * from the remainder of the bytes we generated. Requests for bytes longer
85 * than the hash size are fulfilled directly from the HashGen function
86 * of the random number generator. */
87 PRUint8 reseed_counter[RESEED_BYTE+1]; /* number of requests since the
88 * last reseed. Need only be
89 * big enough to hold the whole
90 * reseed count */
91 PRUint8 data[SHA256_LENGTH]; /* when we request less than a block
92 * save the rest of the rng output for
93 * another partial block */
94 PRUint8 dataAvail; /* # bytes of output available in our cache,
95 * [0...SHA256_LENGTH] */
96 /* store additional data that has been shovelled off to us by
97 * RNG_RandomUpdate. */
98 PRUint8 additionalDataCache[PRNG_ADDITONAL_DATA_CACHE_SIZE];
99 PRUint32 additionalAvail;
100 PRBool isValid; /* false if RNG reaches an invalid state */
101 };
102
103 typedef struct RNGContextStr RNGContext;
104 static RNGContext *globalrng = NULL;
105 static RNGContext theGlobalRng;
106
107
108 /*
109 * The next several functions are derived from the NIST SP 800-90
110 * spec. In these functions, an attempt was made to use names consistent
111 * with the names in the spec, even if they differ from normal NSS usage.
112 */
113
114 /*
115 * Hash Derive function defined in NISP SP 800-90 Section 10.4.1.
116 * This function is used in the Instantiate and Reseed functions.
117 *
118 * NOTE: requested_bytes cannot overlap with input_string_1 or input_string_2.
119 * input_string_1 and input_string_2 are logically concatentated.
120 * input_string_1 must be supplied.
121 * if input_string_2 is not supplied, NULL should be passed for this parameter.
122 */
123 static SECStatus
124 prng_Hash_df(PRUint8 *requested_bytes, unsigned int no_of_bytes_to_return,
125 const PRUint8 *input_string_1, unsigned int input_string_1_len,
126 const PRUint8 *input_string_2, unsigned int input_string_2_len)
127 {
128 SHA256Context ctx;
129 PRUint32 tmp;
130 PRUint8 counter;
131
132 tmp=SHA_HTONL(no_of_bytes_to_return*8);
133
134 for (counter = 1 ; no_of_bytes_to_return > 0; counter++) {
135 unsigned int hash_return_len;
136 SHA256_Begin(&ctx);
137 SHA256_Update(&ctx, &counter, 1);
138 SHA256_Update(&ctx, (unsigned char *)&tmp, sizeof tmp);
139 SHA256_Update(&ctx, input_string_1, input_string_1_len);
140 if (input_string_2) {
141 SHA256_Update(&ctx, input_string_2, input_string_2_len);
142 }
143 SHA256_End(&ctx, requested_bytes, &hash_return_len,
144 no_of_bytes_to_return);
145 requested_bytes += hash_return_len;
146 no_of_bytes_to_return -= hash_return_len;
147 }
148 return SECSuccess;
149 }
150
151
152 /*
153 * Hash_DRBG Instantiate NIST SP 800-80 10.1.1.2
154 *
155 * NOTE: bytes & len are entropy || nonce || personalization_string. In
156 * normal operation, NSS calculates them all together in a single call.
157 */
158 static SECStatus
159 prng_instantiate(RNGContext *rng, const PRUint8 *bytes, unsigned int len)
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 }
167 prng_Hash_df(V(rng), VSize(rng), bytes, len, NULL, 0);
168 rng->V_type = prngCGenerateType;
169 prng_Hash_df(rng->C,sizeof rng->C,rng->V_Data,sizeof rng->V_Data,NULL,0);
170 PRNG_RESET_RESEED_COUNT(rng)
171 return SECSuccess;
172 }
173
174
175 /*
176 * Update the global random number generator with more seeding
177 * material. Use the Hash_DRBG reseed algorithm from NIST SP-800-90
178 * section 10.1.1.3
179 *
180 * If entropy is NULL, it is fetched from the noise generator.
181 */
182 static SECStatus
183 prng_reseed(RNGContext *rng, const PRUint8 *entropy, unsigned int entropy_len,
184 const PRUint8 *additional_input, unsigned int additional_input_len)
185 {
186 PRUint8 noiseData[(sizeof rng->V_Data)+PRNG_SEEDLEN];
187 PRUint8 *noise = &noiseData[0];
188
189 /* if entropy wasn't supplied, fetch it. (normal operation case) */
190 if (entropy == NULL) {
191 entropy_len = (unsigned int) RNG_SystemRNG(
192 &noiseData[sizeof rng->V_Data], PRNG_SEEDLEN);
193 } else {
194 /* NOTE: this code is only available for testing, not to applications */
195 /* if entropy was too big for the stack variable, get it from malloc */
196 if (entropy_len > PRNG_SEEDLEN) {
197 noise = PORT_Alloc(entropy_len + (sizeof rng->V_Data));
198 if (noise == NULL) {
199 return SECFailure;
200 }
201 }
202 PORT_Memcpy(&noise[sizeof rng->V_Data],entropy, entropy_len);
203 }
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
211 rng->V_type = prngReseedType;
212 PORT_Memcpy(noise, rng->V_Data, sizeof rng->V_Data);
213 prng_Hash_df(V(rng), VSize(rng), noise, (sizeof rng->V_Data) + entropy_len,
214 additional_input, additional_input_len);
215 /* clear potential CSP */
216 PORT_Memset(noise, 0, (sizeof rng->V_Data) + entropy_len);
217 rng->V_type = prngCGenerateType;
218 prng_Hash_df(rng->C,sizeof rng->C,rng->V_Data,sizeof rng->V_Data,NULL,0);
219 PRNG_RESET_RESEED_COUNT(rng)
220
221 if (noise != &noiseData[0]) {
222 PORT_Free(noise);
223 }
224 return SECSuccess;
225 }
226
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 /*
249 * build some fast inline functions for adding.
250 */
251 #define PRNG_ADD_CARRY_ONLY(dest, start, cy) \
252 carry = cy; \
253 for (k1=start; carry && k1 >=0 ; k1--) { \
254 carry = !(++dest[k1]); \
255 }
256
257 /*
258 * NOTE: dest must be an array for the following to work.
259 */
260 #define PRNG_ADD_BITS(dest, dest_len, add, len) \
261 carry = 0; \
262 for (k1=dest_len -1, k2=len-1; k2 >= 0; --k1, --k2) { \
263 carry += dest[k1]+ add[k2]; \
264 dest[k1] = (PRUint8) carry; \
265 carry >>= 8; \
266 }
267
268 #define PRNG_ADD_BITS_AND_CARRY(dest, dest_len, add, len) \
269 PRNG_ADD_BITS(dest, dest_len, add, len) \
270 PRNG_ADD_CARRY_ONLY(dest, k1, carry)
271
272 /*
273 * This function expands the internal state of the prng to fulfill any number
274 * of bytes we need for this request. We only use this call if we need more
275 * than can be supplied by a single call to SHA256_HashBuf.
276 *
277 * This function is specified in NIST SP 800-90 section 10.1.1.4, Hashgen
278 */
279 static void
280 prng_Hashgen(RNGContext *rng, PRUint8 *returned_bytes,
281 unsigned int no_of_returned_bytes)
282 {
283 PRUint8 data[VSize(rng)];
284
285 PORT_Memcpy(data, V(rng), VSize(rng));
286 while (no_of_returned_bytes) {
287 SHA256Context ctx;
288 unsigned int len;
289 unsigned int carry;
290 int k1;
291
292 SHA256_Begin(&ctx);
293 SHA256_Update(&ctx, data, sizeof data);
294 SHA256_End(&ctx, returned_bytes, &len, no_of_returned_bytes);
295 returned_bytes += len;
296 no_of_returned_bytes -= len;
297 /* The carry parameter is a bool (increment or not).
298 * This increments data if no_of_returned_bytes is not zero */
299 PRNG_ADD_CARRY_ONLY(data, (sizeof data)- 1, no_of_returned_bytes);
300 }
301 PORT_Memset(data, 0, sizeof data);
302 }
303
304 /*
305 * Generates new random bytes and advances the internal prng state.
306 * additional bytes are only used in algorithm testing.
307 *
308 * This function is specified in NIST SP 800-90 section 10.1.1.4
309 */
310 static SECStatus
311 prng_generateNewBytes(RNGContext *rng,
312 PRUint8 *returned_bytes, unsigned int no_of_returned_bytes,
313 const PRUint8 *additional_input,
314 unsigned int additional_input_len)
315 {
316 PRUint8 H[SHA256_LENGTH]; /* both H and w since they
317 * aren't used concurrently */
318 unsigned int carry;
319 int k1, k2;
320
321 if (!rng->isValid) {
322 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
323 return SECFailure;
324 }
325 /* This code only triggers during tests, normal
326 * prng operation does not use additional_input */
327 if (additional_input){
328 SHA256Context ctx;
329 /* NIST SP 800-90 defines two temporaries in their calculations,
330 * w and H. These temporaries are the same lengths, and used
331 * at different times, so we use the following macro to collapse
332 * them to the same variable, but keeping their unique names for
333 * easy comparison to the spec */
334 #define w H
335 rng->V_type = prngAdditionalDataType;
336 SHA256_Begin(&ctx);
337 SHA256_Update(&ctx, rng->V_Data, sizeof rng->V_Data);
338 SHA256_Update(&ctx, additional_input, additional_input_len);
339 SHA256_End(&ctx, w, NULL, sizeof w);
340 PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), w, sizeof w)
341 PORT_Memset(w, 0, sizeof w);
342 #undef w
343 }
344
345 if (no_of_returned_bytes == SHA256_LENGTH) {
346 /* short_cut to hashbuf and save a copy and a clear */
347 SHA256_HashBuf(returned_bytes, V(rng), VSize(rng) );
348 } else {
349 prng_Hashgen(rng, returned_bytes, no_of_returned_bytes);
350 }
351 /* advance our internal state... */
352 rng->V_type = prngGenerateByteType;
353 SHA256_HashBuf(H, rng->V_Data, sizeof rng->V_Data);
354 PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), H, sizeof H)
355 PRNG_ADD_BITS(V(rng), VSize(rng), rng->C, sizeof rng->C);
356 PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), rng->reseed_counter,
357 sizeof rng->reseed_counter)
358 PRNG_ADD_CARRY_ONLY(rng->reseed_counter,(sizeof rng->reseed_counter)-1, 1);
359
360 /* continuous rng check */
361 if (memcmp(V(rng), rng->oldV, sizeof rng->oldV) == 0) {
362 rng->isValid = PR_FALSE;
363 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
364 return SECFailure;
365 }
366 PORT_Memcpy(rng->oldV, V(rng), sizeof rng->oldV);
367 return SECSuccess;
368 }
369
370 /* Use NSPR to prevent RNG_RNGInit from being called from separate
371 * threads, creating a race condition.
372 */
373 static const PRCallOnceType pristineCallOnce;
374 static PRCallOnceType coRNGInit;
375 static PRStatus rng_init(void)
376 {
377 PRUint8 bytes[PRNG_SEEDLEN*2]; /* entropy + nonce */
378 unsigned int numBytes;
379 SECStatus rv = SECSuccess;
380
381 if (globalrng == NULL) {
382 /* bytes needs to have enough space to hold
383 * a SHA256 hash value. Blow up at compile time if this isn't true */
384 PR_STATIC_ASSERT(sizeof(bytes) >= SHA256_LENGTH);
385 /* create a new global RNG context */
386 globalrng = &theGlobalRng;
387 PORT_Assert(NULL == globalrng->lock);
388 /* create a lock for it */
389 globalrng->lock = PZ_NewLock(nssILockOther);
390 if (globalrng->lock == NULL) {
391 globalrng = NULL;
392 PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
393 return PR_FAILURE;
394 }
395
396 /* Try to get some seed data for the RNG */
397 numBytes = (unsigned int) RNG_SystemRNG(bytes, sizeof bytes);
398 PORT_Assert(numBytes == 0 || numBytes == sizeof bytes);
399 if (numBytes != 0) {
400 /* if this is our first call, instantiate, otherwise reseed
401 * prng_instantiate gets a new clean state, we want to mix
402 * any previous entropy we may have collected */
403 if (V(globalrng)[0] == 0) {
404 rv = prng_instantiate(globalrng, bytes, numBytes);
405 } else {
406 rv = prng_reseed_test(globalrng, bytes, numBytes, NULL, 0);
407 }
408 memset(bytes, 0, numBytes);
409 } else {
410 PZ_DestroyLock(globalrng->lock);
411 globalrng->lock = NULL;
412 globalrng = NULL;
413 return PR_FAILURE;
414 }
415
416 if (rv != SECSuccess) {
417 return PR_FAILURE;
418 }
419 /* the RNG is in a valid state */
420 globalrng->isValid = PR_TRUE;
421
422 /* fetch one random value so that we can populate rng->oldV for our
423 * continous random number test. */
424 prng_generateNewBytes(globalrng, bytes, SHA256_LENGTH, NULL, 0);
425
426 /* Fetch more entropy into the PRNG */
427 RNG_SystemInfoForRNG();
428 }
429 return PR_SUCCESS;
430 }
431
432 /*
433 * Clean up the global RNG context
434 */
435 static void
436 prng_freeRNGContext(RNGContext *rng)
437 {
438 PRUint8 inputhash[VSize(rng) + (sizeof rng->C)];
439
440 /* destroy context lock */
441 SKIP_AFTER_FORK(PZ_DestroyLock(globalrng->lock));
442
443 /* zero global RNG context except for C & V to preserve entropy */
444 prng_Hash_df(inputhash, sizeof rng->C, rng->C, sizeof rng->C, NULL, 0);
445 prng_Hash_df(&inputhash[sizeof rng->C], VSize(rng), V(rng), VSize(rng),
446 NULL, 0);
447 memset(rng, 0, sizeof *rng);
448 memcpy(rng->C, inputhash, sizeof rng->C);
449 memcpy(V(rng), &inputhash[sizeof rng->C], VSize(rng));
450
451 memset(inputhash, 0, sizeof inputhash);
452 }
453
454 /*
455 * Public functions
456 */
457
458 /*
459 * Initialize the global RNG context and give it some seed input taken
460 * from the system. This function is thread-safe and will only allow
461 * the global context to be initialized once. The seed input is likely
462 * small, so it is imperative that RNG_RandomUpdate() be called with
463 * additional seed data before the generator is used. A good way to
464 * provide the generator with additional entropy is to call
465 * RNG_SystemInfoForRNG(). Note that C_Initialize() does exactly that.
466 */
467 SECStatus
468 RNG_RNGInit(void)
469 {
470 /* Allow only one call to initialize the context */
471 PR_CallOnce(&coRNGInit, rng_init);
472 /* Make sure there is a context */
473 return (globalrng != NULL) ? SECSuccess : SECFailure;
474 }
475
476 /*
477 ** Update the global random number generator with more seeding
478 ** material.
479 */
480 SECStatus
481 RNG_RandomUpdate(const void *data, size_t bytes)
482 {
483 SECStatus rv;
484
485 /* Make sure our assumption that size_t is unsigned is true */
486 PR_STATIC_ASSERT(((size_t)-1) > (size_t)1);
487
488 #if defined(NS_PTR_GT_32) || (defined(NSS_USE_64) && !defined(NS_PTR_LE_32))
489 /*
490 * NIST 800-90 requires us to verify our inputs. This value can
491 * come from the application, so we need to make sure it's within the
492 * spec. The spec says it must be less than 2^32 bytes (2^35 bits).
493 * This can only happen if size_t is greater than 32 bits (i.e. on
494 * most 64 bit platforms). The 90% case (perhaps 100% case), size_t
495 * is less than or equal to 32 bits if the platform is not 64 bits, and
496 * greater than 32 bits if it is a 64 bit platform. The corner
497 * cases are handled with explicit defines NS_PTR_GT_32 and NS_PTR_LE_32.
498 *
499 * In general, neither NS_PTR_GT_32 nor NS_PTR_LE_32 will need to be
500 * defined. If you trip over the next two size ASSERTS at compile time,
501 * you will need to define them for your platform.
502 *
503 * if 'sizeof(size_t) > 4' is triggered it means that we were expecting
504 * sizeof(size_t) to be greater than 4, but it wasn't. Setting
505 * NS_PTR_LE_32 will correct that mistake.
506 *
507 * if 'sizeof(size_t) <= 4' is triggered, it means that we were expecting
508 * sizeof(size_t) to be less than or equal to 4, but it wasn't. Setting
509 * NS_PTR_GT_32 will correct that mistake.
510 */
511
512 PR_STATIC_ASSERT(sizeof(size_t) > 4);
513
514 if (bytes > PRNG_MAX_ADDITIONAL_BYTES) {
515 bytes = PRNG_MAX_ADDITIONAL_BYTES;
516 }
517 #else
518 PR_STATIC_ASSERT(sizeof(size_t) <= 4);
519 #endif
520
521 PZ_Lock(globalrng->lock);
522 /* if we're passed more than our additionalDataCache, simply
523 * call reseed with that data */
524 if (bytes > sizeof (globalrng->additionalDataCache)) {
525 rv = prng_reseed_test(globalrng, NULL, 0, data, (unsigned int) bytes);
526 /* if we aren't going to fill or overflow the buffer, just cache it */
527 } else if (bytes < ((sizeof globalrng->additionalDataCache)
528 - globalrng->additionalAvail)) {
529 PORT_Memcpy(globalrng->additionalDataCache+globalrng->additionalAvail,
530 data, bytes);
531 globalrng->additionalAvail += (PRUint32) bytes;
532 rv = SECSuccess;
533 } else {
534 /* we are going to fill or overflow the buffer. In this case we will
535 * fill the entropy buffer, reseed with it, start a new buffer with the
536 * remainder. We know the remainder will fit in the buffer because
537 * we already handled the case where bytes > the size of the buffer.
538 */
539 size_t bufRemain = (sizeof globalrng->additionalDataCache)
540 - globalrng->additionalAvail;
541 /* fill the rest of the buffer */
542 if (bufRemain) {
543 PORT_Memcpy(globalrng->additionalDataCache
544 +globalrng->additionalAvail,
545 data, bufRemain);
546 data = ((unsigned char *)data) + bufRemain;
547 bytes -= bufRemain;
548 }
549 /* reseed from buffer */
550 rv = prng_reseed_test(globalrng, NULL, 0,
551 globalrng->additionalDataCache,
552 sizeof globalrng->additionalDataCache);
553
554 /* copy the rest into the cache */
555 PORT_Memcpy(globalrng->additionalDataCache, data, bytes);
556 globalrng->additionalAvail = (PRUint32) bytes;
557 }
558
559 PZ_Unlock(globalrng->lock);
560 return rv;
561 }
562
563 /*
564 ** Generate some random bytes, using the global random number generator
565 ** object.
566 */
567 static SECStatus
568 prng_GenerateGlobalRandomBytes(RNGContext *rng,
569 void *dest, size_t len)
570 {
571 SECStatus rv = SECSuccess;
572 PRUint8 *output = dest;
573 /* check for a valid global RNG context */
574 PORT_Assert(rng != NULL);
575 if (rng == NULL) {
576 PORT_SetError(SEC_ERROR_INVALID_ARGS);
577 return SECFailure;
578 }
579 /* FIPS limits the amount of entropy available in a single request */
580 if (len > PRNG_MAX_REQUEST_SIZE) {
581 PORT_SetError(SEC_ERROR_INVALID_ARGS);
582 return SECFailure;
583 }
584 /* --- LOCKED --- */
585 PZ_Lock(rng->lock);
586 /* Check the amount of seed data in the generator. If not enough,
587 * don't produce any data.
588 */
589 if (rng->reseed_counter[0] >= RESEED_VALUE) {
590 rv = prng_reseed_test(rng, NULL, 0, NULL, 0);
591 PZ_Unlock(rng->lock);
592 if (rv != SECSuccess) {
593 return rv;
594 }
595 RNG_SystemInfoForRNG();
596 PZ_Lock(rng->lock);
597 }
598 /*
599 * see if we have enough bytes to fulfill the request.
600 */
601 if (len <= rng->dataAvail) {
602 memcpy(output, rng->data + ((sizeof rng->data) - rng->dataAvail), len);
603 memset(rng->data + ((sizeof rng->data) - rng->dataAvail), 0, len);
604 rng->dataAvail -= len;
605 rv = SECSuccess;
606 /* if we are asking for a small number of bytes, cache the rest of
607 * the bytes */
608 } else if (len < sizeof rng->data) {
609 rv = prng_generateNewBytes(rng, rng->data, sizeof rng->data,
610 rng->additionalAvail ? rng->additionalDataCache : NULL,
611 rng->additionalAvail);
612 rng->additionalAvail = 0;
613 if (rv == SECSuccess) {
614 memcpy(output, rng->data, len);
615 memset(rng->data, 0, len);
616 rng->dataAvail = (sizeof rng->data) - len;
617 }
618 /* we are asking for lots of bytes, just ask the generator to pass them */
619 } else {
620 rv = prng_generateNewBytes(rng, output, len,
621 rng->additionalAvail ? rng->additionalDataCache : NULL,
622 rng->additionalAvail);
623 rng->additionalAvail = 0;
624 }
625 PZ_Unlock(rng->lock);
626 /* --- UNLOCKED --- */
627 return rv;
628 }
629
630 /*
631 ** Generate some random bytes, using the global random number generator
632 ** object.
633 */
634 SECStatus
635 RNG_GenerateGlobalRandomBytes(void *dest, size_t len)
636 {
637 return prng_GenerateGlobalRandomBytes(globalrng, dest, len);
638 }
639
640 void
641 RNG_RNGShutdown(void)
642 {
643 /* check for a valid global RNG context */
644 PORT_Assert(globalrng != NULL);
645 if (globalrng == NULL) {
646 /* Should set a "not initialized" error code. */
647 PORT_SetError(SEC_ERROR_NO_MEMORY);
648 return;
649 }
650 /* clear */
651 prng_freeRNGContext(globalrng);
652 globalrng = NULL;
653 /* reset the callonce struct to allow a new call to RNG_RNGInit() */
654 coRNGInit = pristineCallOnce;
655 }
656
657 /*
658 * Test case interface. used by fips testing and power on self test
659 */
660 /* make sure the test context is separate from the global context, This
661 * allows us to test the internal random number generator without losing
662 * entropy we may have previously collected. */
663 RNGContext testContext;
664
665 /*
666 * Test vector API. Use NIST SP 800-90 general interface so one of the
667 * other NIST SP 800-90 algorithms may be used in the future.
668 */
669 SECStatus
670 PRNGTEST_Instantiate(const PRUint8 *entropy, unsigned int entropy_len,
671 const PRUint8 *nonce, unsigned int nonce_len,
672 const PRUint8 *personal_string, unsigned int ps_len)
673 {
674 int bytes_len = entropy_len + nonce_len + ps_len;
675 PRUint8 *bytes = NULL;
676 SECStatus rv;
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);
684 if (bytes == NULL) {
685 PORT_SetError(SEC_ERROR_NO_MEMORY);
686 return SECFailure;
687 }
688 /* concatenate the various inputs, internally NSS only instantiates with
689 * a single long string */
690 PORT_Memcpy(bytes, entropy, entropy_len);
691 if (nonce) {
692 PORT_Memcpy(&bytes[entropy_len], nonce, nonce_len);
693 } else {
694 PORT_Assert(nonce_len == 0);
695 }
696 if (personal_string) {
697 PORT_Memcpy(&bytes[entropy_len+nonce_len], personal_string, ps_len);
698 } else {
699 PORT_Assert(ps_len == 0);
700 }
701 rv = prng_instantiate(&testContext, bytes, bytes_len);
702 PORT_ZFree(bytes, bytes_len);
703 if (rv == SECFailure) {
704 return SECFailure;
705 }
706 testContext.isValid = PR_TRUE;
707 return SECSuccess;
708 }
709
710 SECStatus
711 PRNGTEST_Reseed(const PRUint8 *entropy, unsigned int entropy_len,
712 const PRUint8 *additional, unsigned int additional_len)
713 {
714 if (!testContext.isValid) {
715 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
716 return SECFailure;
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 }
725 return prng_reseed(&testContext, entropy, entropy_len, additional,
726 additional_len);
727
728 }
729
730 SECStatus
731 PRNGTEST_Generate(PRUint8 *bytes, unsigned int bytes_len,
732 const PRUint8 *additional, unsigned int additional_len)
733 {
734 SECStatus rv;
735 if (!testContext.isValid) {
736 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
737 return SECFailure;
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 }
746 return prng_generateNewBytes(&testContext, bytes, bytes_len,
747 additional, additional_len);
748
749 }
750
751 SECStatus
752 PRNGTEST_Uninstantiate()
753 {
754 if (!testContext.isValid) {
755 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
756 return SECFailure;
757 }
758 PORT_Memset(&testContext, 0, sizeof testContext);
759 return SECSuccess;
760 }
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 };
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