Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/freebl/drbg.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
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 | |
5 #ifdef FREEBL_NO_DEPEND | |
6 #include "stubs.h" | |
7 #endif | |
8 | |
9 #include "prerror.h" | |
10 #include "secerr.h" | |
11 | |
12 #include "prtypes.h" | |
13 #include "prinit.h" | |
14 #include "blapi.h" | |
15 #include "blapii.h" | |
16 #include "nssilock.h" | |
17 #include "secitem.h" | |
18 #include "sha_fast.h" | |
19 #include "sha256.h" | |
20 #include "secrng.h" /* for RNG_SystemRNG() */ | |
21 #include "secmpi.h" | |
22 | |
23 /* PRNG_SEEDLEN defined in NIST SP 800-90 section 10.1 | |
24 * for SHA-1, SHA-224, and SHA-256 it's 440 bits. | |
25 * for SHA-384 and SHA-512 it's 888 bits */ | |
26 #define PRNG_SEEDLEN (440/PR_BITS_PER_BYTE) | |
27 static const PRInt64 PRNG_MAX_ADDITIONAL_BYTES = LL_INIT(0x1, 0x0); | |
28 /* 2^35 bits or 2^32 bytes */ | |
29 #define PRNG_MAX_REQUEST_SIZE 0x10000 /* 2^19 bits or 2^16 bytes */ | |
30 #define PRNG_ADDITONAL_DATA_CACHE_SIZE (8*1024) /* must be less than | |
31 * PRNG_MAX_ADDITIONAL_BYTES | |
32 */ | |
33 | |
34 /* RESEED_COUNT is how many calls to the prng before we need to reseed | |
35 * under normal NIST rules, you must return an error. In the NSS case, we | |
36 * self-reseed with RNG_SystemRNG(). Count can be a large number. For code | |
37 * simplicity, we specify count with 2 components: RESEED_BYTE (which is | |
38 * the same as LOG256(RESEED_COUNT)) and RESEED_VALUE (which is the same as | |
39 * RESEED_COUNT / (256 ^ RESEED_BYTE)). Another way to look at this is | |
40 * RESEED_COUNT = RESEED_VALUE * (256 ^ RESEED_BYTE). For Hash based DRBG | |
41 * we use the maximum count value, 2^48, or RESEED_BYTE=6 and RESEED_VALUE=1 | |
42 */ | |
43 #define RESEED_BYTE 6 | |
44 #define RESEED_VALUE 1 | |
45 | |
46 #define PRNG_RESET_RESEED_COUNT(rng) \ | |
47 PORT_Memset((rng)->reseed_counter, 0, sizeof (rng)->reseed_counter); \ | |
48 (rng)->reseed_counter[RESEED_BYTE] = 1; | |
49 | |
50 | |
51 /* | |
52 * The actual values of this enum are specified in SP 800-90, 10.1.1.* | |
53 * The spec does not name the types, it only uses bare values | |
54 */ | |
55 typedef enum { | |
56 prngCGenerateType = 0, /* used when creating a new 'C' */ | |
57 prngReseedType = 1, /* used in reseeding */ | |
58 prngAdditionalDataType = 2, /* used in mixing additional data */ | |
59 prngGenerateByteType = 3 /* used when mixing internal state while | |
60 * generating bytes */ | |
61 } prngVTypes; | |
62 | |
63 /* | |
64 * Global RNG context | |
65 */ | |
66 struct RNGContextStr { | |
67 PZLock *lock; /* Lock to serialize access to global rng */ | |
68 /* | |
69 * NOTE, a number of steps in the drbg algorithm need to hash | |
70 * V_type || V. The code, therefore, depends on the V array following | |
71 * immediately after V_type to avoid extra copies. To accomplish this | |
72 * in a way that compiliers can't perturb, we declare V_type and V | |
73 * as a V_Data array and reference them by macros */ | |
74 PRUint8 V_Data[PRNG_SEEDLEN+1]; /* internal state variables */ | |
75 #define V_type V_Data[0] | |
76 #define V(rng) (((rng)->V_Data)+1) | |
77 #define VSize(rng) ((sizeof (rng)->V_Data) -1) | |
78 PRUint8 C[PRNG_SEEDLEN]; /* internal state variables */ | |
79 PRUint8 oldV[PRNG_SEEDLEN]; /* for continuous rng checking */ | |
80 /* If we get calls for the PRNG to return less than the length of our | |
81 * hash, we extend the request for a full hash (since we'll be doing | |
82 * the full hash anyway). Future requests for random numbers are fulfilled | |
83 * from the remainder of the bytes we generated. Requests for bytes longer | |
84 * than the hash size are fulfilled directly from the HashGen function | |
85 * of the random number generator. */ | |
86 PRUint8 reseed_counter[RESEED_BYTE+1]; /* number of requests since the | |
87 * last reseed. Need only be | |
88 * big enough to hold the whole | |
89 * reseed count */ | |
90 PRUint8 data[SHA256_LENGTH]; /* when we request less than a block | |
91 * save the rest of the rng output for | |
92 * another partial block */ | |
93 PRUint8 dataAvail; /* # bytes of output available in our cache, | |
94 * [0...SHA256_LENGTH] */ | |
95 /* store additional data that has been shovelled off to us by | |
96 * RNG_RandomUpdate. */ | |
97 PRUint8 additionalDataCache[PRNG_ADDITONAL_DATA_CACHE_SIZE]; | |
98 PRUint32 additionalAvail; | |
99 PRBool isValid; /* false if RNG reaches an invalid state */ | |
100 }; | |
101 | |
102 typedef struct RNGContextStr RNGContext; | |
103 static RNGContext *globalrng = NULL; | |
104 static RNGContext theGlobalRng; | |
105 | |
106 | |
107 /* | |
108 * The next several functions are derived from the NIST SP 800-90 | |
109 * spec. In these functions, an attempt was made to use names consistent | |
110 * with the names in the spec, even if they differ from normal NSS usage. | |
111 */ | |
112 | |
113 /* | |
114 * Hash Derive function defined in NISP SP 800-90 Section 10.4.1. | |
115 * This function is used in the Instantiate and Reseed functions. | |
116 * | |
117 * NOTE: requested_bytes cannot overlap with input_string_1 or input_string_2. | |
118 * input_string_1 and input_string_2 are logically concatentated. | |
119 * input_string_1 must be supplied. | |
120 * if input_string_2 is not supplied, NULL should be passed for this parameter. | |
121 */ | |
122 static SECStatus | |
123 prng_Hash_df(PRUint8 *requested_bytes, unsigned int no_of_bytes_to_return, | |
124 const PRUint8 *input_string_1, unsigned int input_string_1_len, | |
125 const PRUint8 *input_string_2, unsigned int input_string_2_len) | |
126 { | |
127 SHA256Context ctx; | |
128 PRUint32 tmp; | |
129 PRUint8 counter; | |
130 | |
131 tmp=SHA_HTONL(no_of_bytes_to_return*8); | |
132 | |
133 for (counter = 1 ; no_of_bytes_to_return > 0; counter++) { | |
134 unsigned int hash_return_len; | |
135 SHA256_Begin(&ctx); | |
136 SHA256_Update(&ctx, &counter, 1); | |
137 SHA256_Update(&ctx, (unsigned char *)&tmp, sizeof tmp); | |
138 SHA256_Update(&ctx, input_string_1, input_string_1_len); | |
139 if (input_string_2) { | |
140 SHA256_Update(&ctx, input_string_2, input_string_2_len); | |
141 } | |
142 SHA256_End(&ctx, requested_bytes, &hash_return_len, | |
143 no_of_bytes_to_return); | |
144 requested_bytes += hash_return_len; | |
145 no_of_bytes_to_return -= hash_return_len; | |
146 } | |
147 return SECSuccess; | |
148 } | |
149 | |
150 | |
151 /* | |
152 * Hash_DRBG Instantiate NIST SP 800-80 10.1.1.2 | |
153 * | |
154 * NOTE: bytes & len are entropy || nonce || personalization_string. In | |
155 * normal operation, NSS calculates them all together in a single call. | |
156 */ | |
157 static SECStatus | |
158 prng_instantiate(RNGContext *rng, const PRUint8 *bytes, unsigned int len) | |
159 { | |
160 if (len < PRNG_SEEDLEN) { | |
161 /* if the seedlen is to small, it's probably because we failed to get | |
162 * enough random data */ | |
163 PORT_SetError(SEC_ERROR_NEED_RANDOM); | |
164 return SECFailure; | |
165 } | |
166 prng_Hash_df(V(rng), VSize(rng), bytes, len, NULL, 0); | |
167 rng->V_type = prngCGenerateType; | |
168 prng_Hash_df(rng->C,sizeof rng->C,rng->V_Data,sizeof rng->V_Data,NULL,0); | |
169 PRNG_RESET_RESEED_COUNT(rng) | |
170 return SECSuccess; | |
171 } | |
172 | |
173 | |
174 /* | |
175 * Update the global random number generator with more seeding | |
176 * material. Use the Hash_DRBG reseed algorithm from NIST SP-800-90 | |
177 * section 10.1.1.3 | |
178 * | |
179 * If entropy is NULL, it is fetched from the noise generator. | |
180 */ | |
181 static SECStatus | |
182 prng_reseed(RNGContext *rng, const PRUint8 *entropy, unsigned int entropy_len, | |
183 const PRUint8 *additional_input, unsigned int additional_input_len) | |
184 { | |
185 PRUint8 noiseData[(sizeof rng->V_Data)+PRNG_SEEDLEN]; | |
186 PRUint8 *noise = &noiseData[0]; | |
187 | |
188 /* if entropy wasn't supplied, fetch it. (normal operation case) */ | |
189 if (entropy == NULL) { | |
190 entropy_len = (unsigned int) RNG_SystemRNG( | |
191 &noiseData[sizeof rng->V_Data], PRNG_SEEDLEN); | |
192 } else { | |
193 /* NOTE: this code is only available for testing, not to applications */ | |
194 /* if entropy was too big for the stack variable, get it from malloc */ | |
195 if (entropy_len > PRNG_SEEDLEN) { | |
196 noise = PORT_Alloc(entropy_len + (sizeof rng->V_Data)); | |
197 if (noise == NULL) { | |
198 return SECFailure; | |
199 } | |
200 } | |
201 PORT_Memcpy(&noise[sizeof rng->V_Data],entropy, entropy_len); | |
202 } | |
203 | |
204 if (entropy_len < 256/PR_BITS_PER_BYTE) { | |
205 /* noise == &noiseData[0] at this point, so nothing to free */ | |
206 PORT_SetError(SEC_ERROR_NEED_RANDOM); | |
207 return SECFailure; | |
208 } | |
209 | |
210 rng->V_type = prngReseedType; | |
211 PORT_Memcpy(noise, rng->V_Data, sizeof rng->V_Data); | |
212 prng_Hash_df(V(rng), VSize(rng), noise, (sizeof rng->V_Data) + entropy_len, | |
213 additional_input, additional_input_len); | |
214 /* clear potential CSP */ | |
215 PORT_Memset(noise, 0, (sizeof rng->V_Data) + entropy_len); | |
216 rng->V_type = prngCGenerateType; | |
217 prng_Hash_df(rng->C,sizeof rng->C,rng->V_Data,sizeof rng->V_Data,NULL,0); | |
218 PRNG_RESET_RESEED_COUNT(rng) | |
219 | |
220 if (noise != &noiseData[0]) { | |
221 PORT_Free(noise); | |
222 } | |
223 return SECSuccess; | |
224 } | |
225 | |
226 /* | |
227 * SP 800-90 requires we rerun our health tests on reseed | |
228 */ | |
229 static SECStatus | |
230 prng_reseed_test(RNGContext *rng, const PRUint8 *entropy, | |
231 unsigned int entropy_len, const PRUint8 *additional_input, | |
232 unsigned int additional_input_len) | |
233 { | |
234 SECStatus rv; | |
235 | |
236 /* do health checks in FIPS mode */ | |
237 rv = PRNGTEST_RunHealthTests(); | |
238 if (rv != SECSuccess) { | |
239 /* error set by PRNGTEST_RunHealTests() */ | |
240 rng->isValid = PR_FALSE; | |
241 return SECFailure; | |
242 } | |
243 return prng_reseed(rng, entropy, entropy_len, | |
244 additional_input, additional_input_len); | |
245 } | |
246 | |
247 /* | |
248 * build some fast inline functions for adding. | |
249 */ | |
250 #define PRNG_ADD_CARRY_ONLY(dest, start, cy) \ | |
251 carry = cy; \ | |
252 for (k1=start; carry && k1 >=0 ; k1--) { \ | |
253 carry = !(++dest[k1]); \ | |
254 } | |
255 | |
256 /* | |
257 * NOTE: dest must be an array for the following to work. | |
258 */ | |
259 #define PRNG_ADD_BITS(dest, dest_len, add, len) \ | |
260 carry = 0; \ | |
261 for (k1=dest_len -1, k2=len-1; k2 >= 0; --k1, --k2) { \ | |
262 carry += dest[k1]+ add[k2]; \ | |
263 dest[k1] = (PRUint8) carry; \ | |
264 carry >>= 8; \ | |
265 } | |
266 | |
267 #define PRNG_ADD_BITS_AND_CARRY(dest, dest_len, add, len) \ | |
268 PRNG_ADD_BITS(dest, dest_len, add, len) \ | |
269 PRNG_ADD_CARRY_ONLY(dest, k1, carry) | |
270 | |
271 /* | |
272 * This function expands the internal state of the prng to fulfill any number | |
273 * of bytes we need for this request. We only use this call if we need more | |
274 * than can be supplied by a single call to SHA256_HashBuf. | |
275 * | |
276 * This function is specified in NIST SP 800-90 section 10.1.1.4, Hashgen | |
277 */ | |
278 static void | |
279 prng_Hashgen(RNGContext *rng, PRUint8 *returned_bytes, | |
280 unsigned int no_of_returned_bytes) | |
281 { | |
282 PRUint8 data[VSize(rng)]; | |
283 | |
284 PORT_Memcpy(data, V(rng), VSize(rng)); | |
285 while (no_of_returned_bytes) { | |
286 SHA256Context ctx; | |
287 unsigned int len; | |
288 unsigned int carry; | |
289 int k1; | |
290 | |
291 SHA256_Begin(&ctx); | |
292 SHA256_Update(&ctx, data, sizeof data); | |
293 SHA256_End(&ctx, returned_bytes, &len, no_of_returned_bytes); | |
294 returned_bytes += len; | |
295 no_of_returned_bytes -= len; | |
296 /* The carry parameter is a bool (increment or not). | |
297 * This increments data if no_of_returned_bytes is not zero */ | |
298 PRNG_ADD_CARRY_ONLY(data, (sizeof data)- 1, no_of_returned_bytes); | |
299 } | |
300 PORT_Memset(data, 0, sizeof data); | |
301 } | |
302 | |
303 /* | |
304 * Generates new random bytes and advances the internal prng state. | |
305 * additional bytes are only used in algorithm testing. | |
306 * | |
307 * This function is specified in NIST SP 800-90 section 10.1.1.4 | |
308 */ | |
309 static SECStatus | |
310 prng_generateNewBytes(RNGContext *rng, | |
311 PRUint8 *returned_bytes, unsigned int no_of_returned_bytes, | |
312 const PRUint8 *additional_input, | |
313 unsigned int additional_input_len) | |
314 { | |
315 PRUint8 H[SHA256_LENGTH]; /* both H and w since they | |
316 * aren't used concurrently */ | |
317 unsigned int carry; | |
318 int k1, k2; | |
319 | |
320 if (!rng->isValid) { | |
321 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
322 return SECFailure; | |
323 } | |
324 /* This code only triggers during tests, normal | |
325 * prng operation does not use additional_input */ | |
326 if (additional_input){ | |
327 SHA256Context ctx; | |
328 /* NIST SP 800-90 defines two temporaries in their calculations, | |
329 * w and H. These temporaries are the same lengths, and used | |
330 * at different times, so we use the following macro to collapse | |
331 * them to the same variable, but keeping their unique names for | |
332 * easy comparison to the spec */ | |
333 #define w H | |
334 rng->V_type = prngAdditionalDataType; | |
335 SHA256_Begin(&ctx); | |
336 SHA256_Update(&ctx, rng->V_Data, sizeof rng->V_Data); | |
337 SHA256_Update(&ctx, additional_input, additional_input_len); | |
338 SHA256_End(&ctx, w, NULL, sizeof w); | |
339 PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), w, sizeof w) | |
340 PORT_Memset(w, 0, sizeof w); | |
341 #undef w | |
342 } | |
343 | |
344 if (no_of_returned_bytes == SHA256_LENGTH) { | |
345 /* short_cut to hashbuf and save a copy and a clear */ | |
346 SHA256_HashBuf(returned_bytes, V(rng), VSize(rng) ); | |
347 } else { | |
348 prng_Hashgen(rng, returned_bytes, no_of_returned_bytes); | |
349 } | |
350 /* advance our internal state... */ | |
351 rng->V_type = prngGenerateByteType; | |
352 SHA256_HashBuf(H, rng->V_Data, sizeof rng->V_Data); | |
353 PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), H, sizeof H) | |
354 PRNG_ADD_BITS(V(rng), VSize(rng), rng->C, sizeof rng->C); | |
355 PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), rng->reseed_counter, | |
356 sizeof rng->reseed_counter) | |
357 PRNG_ADD_CARRY_ONLY(rng->reseed_counter,(sizeof rng->reseed_counter)-1, 1); | |
358 | |
359 /* continuous rng check */ | |
360 if (memcmp(V(rng), rng->oldV, sizeof rng->oldV) == 0) { | |
361 rng->isValid = PR_FALSE; | |
362 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
363 return SECFailure; | |
364 } | |
365 PORT_Memcpy(rng->oldV, V(rng), sizeof rng->oldV); | |
366 return SECSuccess; | |
367 } | |
368 | |
369 /* Use NSPR to prevent RNG_RNGInit from being called from separate | |
370 * threads, creating a race condition. | |
371 */ | |
372 static const PRCallOnceType pristineCallOnce; | |
373 static PRCallOnceType coRNGInit; | |
374 static PRStatus rng_init(void) | |
375 { | |
376 PRUint8 bytes[PRNG_SEEDLEN*2]; /* entropy + nonce */ | |
377 unsigned int numBytes; | |
378 SECStatus rv = SECSuccess; | |
379 | |
380 if (globalrng == NULL) { | |
381 /* bytes needs to have enough space to hold | |
382 * a SHA256 hash value. Blow up at compile time if this isn't true */ | |
383 PR_STATIC_ASSERT(sizeof(bytes) >= SHA256_LENGTH); | |
384 /* create a new global RNG context */ | |
385 globalrng = &theGlobalRng; | |
386 PORT_Assert(NULL == globalrng->lock); | |
387 /* create a lock for it */ | |
388 globalrng->lock = PZ_NewLock(nssILockOther); | |
389 if (globalrng->lock == NULL) { | |
390 globalrng = NULL; | |
391 PORT_SetError(PR_OUT_OF_MEMORY_ERROR); | |
392 return PR_FAILURE; | |
393 } | |
394 | |
395 /* Try to get some seed data for the RNG */ | |
396 numBytes = (unsigned int) RNG_SystemRNG(bytes, sizeof bytes); | |
397 PORT_Assert(numBytes == 0 || numBytes == sizeof bytes); | |
398 if (numBytes != 0) { | |
399 /* if this is our first call, instantiate, otherwise reseed | |
400 * prng_instantiate gets a new clean state, we want to mix | |
401 * any previous entropy we may have collected */ | |
402 if (V(globalrng)[0] == 0) { | |
403 rv = prng_instantiate(globalrng, bytes, numBytes); | |
404 } else { | |
405 rv = prng_reseed_test(globalrng, bytes, numBytes, NULL, 0); | |
406 } | |
407 memset(bytes, 0, numBytes); | |
408 } else { | |
409 PZ_DestroyLock(globalrng->lock); | |
410 globalrng->lock = NULL; | |
411 globalrng = NULL; | |
412 return PR_FAILURE; | |
413 } | |
414 | |
415 if (rv != SECSuccess) { | |
416 return PR_FAILURE; | |
417 } | |
418 /* the RNG is in a valid state */ | |
419 globalrng->isValid = PR_TRUE; | |
420 | |
421 /* fetch one random value so that we can populate rng->oldV for our | |
422 * continous random number test. */ | |
423 prng_generateNewBytes(globalrng, bytes, SHA256_LENGTH, NULL, 0); | |
424 | |
425 /* Fetch more entropy into the PRNG */ | |
426 RNG_SystemInfoForRNG(); | |
427 } | |
428 return PR_SUCCESS; | |
429 } | |
430 | |
431 /* | |
432 * Clean up the global RNG context | |
433 */ | |
434 static void | |
435 prng_freeRNGContext(RNGContext *rng) | |
436 { | |
437 PRUint8 inputhash[VSize(rng) + (sizeof rng->C)]; | |
438 | |
439 /* destroy context lock */ | |
440 SKIP_AFTER_FORK(PZ_DestroyLock(globalrng->lock)); | |
441 | |
442 /* zero global RNG context except for C & V to preserve entropy */ | |
443 prng_Hash_df(inputhash, sizeof rng->C, rng->C, sizeof rng->C, NULL, 0); | |
444 prng_Hash_df(&inputhash[sizeof rng->C], VSize(rng), V(rng), VSize(rng), | |
445 NULL, 0); | |
446 memset(rng, 0, sizeof *rng); | |
447 memcpy(rng->C, inputhash, sizeof rng->C); | |
448 memcpy(V(rng), &inputhash[sizeof rng->C], VSize(rng)); | |
449 | |
450 memset(inputhash, 0, sizeof inputhash); | |
451 } | |
452 | |
453 /* | |
454 * Public functions | |
455 */ | |
456 | |
457 /* | |
458 * Initialize the global RNG context and give it some seed input taken | |
459 * from the system. This function is thread-safe and will only allow | |
460 * the global context to be initialized once. The seed input is likely | |
461 * small, so it is imperative that RNG_RandomUpdate() be called with | |
462 * additional seed data before the generator is used. A good way to | |
463 * provide the generator with additional entropy is to call | |
464 * RNG_SystemInfoForRNG(). Note that C_Initialize() does exactly that. | |
465 */ | |
466 SECStatus | |
467 RNG_RNGInit(void) | |
468 { | |
469 /* Allow only one call to initialize the context */ | |
470 PR_CallOnce(&coRNGInit, rng_init); | |
471 /* Make sure there is a context */ | |
472 return (globalrng != NULL) ? SECSuccess : SECFailure; | |
473 } | |
474 | |
475 /* | |
476 ** Update the global random number generator with more seeding | |
477 ** material. | |
478 */ | |
479 SECStatus | |
480 RNG_RandomUpdate(const void *data, size_t bytes) | |
481 { | |
482 SECStatus rv; | |
483 | |
484 /* Make sure our assumption that size_t is unsigned is true */ | |
485 PR_STATIC_ASSERT(((size_t)-1) > (size_t)1); | |
486 | |
487 #if defined(NS_PTR_GT_32) || (defined(NSS_USE_64) && !defined(NS_PTR_LE_32)) | |
488 /* | |
489 * NIST 800-90 requires us to verify our inputs. This value can | |
490 * come from the application, so we need to make sure it's within the | |
491 * spec. The spec says it must be less than 2^32 bytes (2^35 bits). | |
492 * This can only happen if size_t is greater than 32 bits (i.e. on | |
493 * most 64 bit platforms). The 90% case (perhaps 100% case), size_t | |
494 * is less than or equal to 32 bits if the platform is not 64 bits, and | |
495 * greater than 32 bits if it is a 64 bit platform. The corner | |
496 * cases are handled with explicit defines NS_PTR_GT_32 and NS_PTR_LE_32. | |
497 * | |
498 * In general, neither NS_PTR_GT_32 nor NS_PTR_LE_32 will need to be | |
499 * defined. If you trip over the next two size ASSERTS at compile time, | |
500 * you will need to define them for your platform. | |
501 * | |
502 * if 'sizeof(size_t) > 4' is triggered it means that we were expecting | |
503 * sizeof(size_t) to be greater than 4, but it wasn't. Setting | |
504 * NS_PTR_LE_32 will correct that mistake. | |
505 * | |
506 * if 'sizeof(size_t) <= 4' is triggered, it means that we were expecting | |
507 * sizeof(size_t) to be less than or equal to 4, but it wasn't. Setting | |
508 * NS_PTR_GT_32 will correct that mistake. | |
509 */ | |
510 | |
511 PR_STATIC_ASSERT(sizeof(size_t) > 4); | |
512 | |
513 if (bytes > PRNG_MAX_ADDITIONAL_BYTES) { | |
514 bytes = PRNG_MAX_ADDITIONAL_BYTES; | |
515 } | |
516 #else | |
517 PR_STATIC_ASSERT(sizeof(size_t) <= 4); | |
518 #endif | |
519 | |
520 PZ_Lock(globalrng->lock); | |
521 /* if we're passed more than our additionalDataCache, simply | |
522 * call reseed with that data */ | |
523 if (bytes > sizeof (globalrng->additionalDataCache)) { | |
524 rv = prng_reseed_test(globalrng, NULL, 0, data, (unsigned int) bytes); | |
525 /* if we aren't going to fill or overflow the buffer, just cache it */ | |
526 } else if (bytes < ((sizeof globalrng->additionalDataCache) | |
527 - globalrng->additionalAvail)) { | |
528 PORT_Memcpy(globalrng->additionalDataCache+globalrng->additionalAvail, | |
529 data, bytes); | |
530 globalrng->additionalAvail += (PRUint32) bytes; | |
531 rv = SECSuccess; | |
532 } else { | |
533 /* we are going to fill or overflow the buffer. In this case we will | |
534 * fill the entropy buffer, reseed with it, start a new buffer with the | |
535 * remainder. We know the remainder will fit in the buffer because | |
536 * we already handled the case where bytes > the size of the buffer. | |
537 */ | |
538 size_t bufRemain = (sizeof globalrng->additionalDataCache) | |
539 - globalrng->additionalAvail; | |
540 /* fill the rest of the buffer */ | |
541 if (bufRemain) { | |
542 PORT_Memcpy(globalrng->additionalDataCache | |
543 +globalrng->additionalAvail, | |
544 data, bufRemain); | |
545 data = ((unsigned char *)data) + bufRemain; | |
546 bytes -= bufRemain; | |
547 } | |
548 /* reseed from buffer */ | |
549 rv = prng_reseed_test(globalrng, NULL, 0, | |
550 globalrng->additionalDataCache, | |
551 sizeof globalrng->additionalDataCache); | |
552 | |
553 /* copy the rest into the cache */ | |
554 PORT_Memcpy(globalrng->additionalDataCache, data, bytes); | |
555 globalrng->additionalAvail = (PRUint32) bytes; | |
556 } | |
557 | |
558 PZ_Unlock(globalrng->lock); | |
559 return rv; | |
560 } | |
561 | |
562 /* | |
563 ** Generate some random bytes, using the global random number generator | |
564 ** object. | |
565 */ | |
566 static SECStatus | |
567 prng_GenerateGlobalRandomBytes(RNGContext *rng, | |
568 void *dest, size_t len) | |
569 { | |
570 SECStatus rv = SECSuccess; | |
571 PRUint8 *output = dest; | |
572 /* check for a valid global RNG context */ | |
573 PORT_Assert(rng != NULL); | |
574 if (rng == NULL) { | |
575 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
576 return SECFailure; | |
577 } | |
578 /* FIPS limits the amount of entropy available in a single request */ | |
579 if (len > PRNG_MAX_REQUEST_SIZE) { | |
580 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
581 return SECFailure; | |
582 } | |
583 /* --- LOCKED --- */ | |
584 PZ_Lock(rng->lock); | |
585 /* Check the amount of seed data in the generator. If not enough, | |
586 * don't produce any data. | |
587 */ | |
588 if (rng->reseed_counter[0] >= RESEED_VALUE) { | |
589 rv = prng_reseed_test(rng, NULL, 0, NULL, 0); | |
590 PZ_Unlock(rng->lock); | |
591 if (rv != SECSuccess) { | |
592 return rv; | |
593 } | |
594 RNG_SystemInfoForRNG(); | |
595 PZ_Lock(rng->lock); | |
596 } | |
597 /* | |
598 * see if we have enough bytes to fulfill the request. | |
599 */ | |
600 if (len <= rng->dataAvail) { | |
601 memcpy(output, rng->data + ((sizeof rng->data) - rng->dataAvail), len); | |
602 memset(rng->data + ((sizeof rng->data) - rng->dataAvail), 0, len); | |
603 rng->dataAvail -= len; | |
604 rv = SECSuccess; | |
605 /* if we are asking for a small number of bytes, cache the rest of | |
606 * the bytes */ | |
607 } else if (len < sizeof rng->data) { | |
608 rv = prng_generateNewBytes(rng, rng->data, sizeof rng->data, | |
609 rng->additionalAvail ? rng->additionalDataCache : NULL, | |
610 rng->additionalAvail); | |
611 rng->additionalAvail = 0; | |
612 if (rv == SECSuccess) { | |
613 memcpy(output, rng->data, len); | |
614 memset(rng->data, 0, len); | |
615 rng->dataAvail = (sizeof rng->data) - len; | |
616 } | |
617 /* we are asking for lots of bytes, just ask the generator to pass them */ | |
618 } else { | |
619 rv = prng_generateNewBytes(rng, output, len, | |
620 rng->additionalAvail ? rng->additionalDataCache : NULL, | |
621 rng->additionalAvail); | |
622 rng->additionalAvail = 0; | |
623 } | |
624 PZ_Unlock(rng->lock); | |
625 /* --- UNLOCKED --- */ | |
626 return rv; | |
627 } | |
628 | |
629 /* | |
630 ** Generate some random bytes, using the global random number generator | |
631 ** object. | |
632 */ | |
633 SECStatus | |
634 RNG_GenerateGlobalRandomBytes(void *dest, size_t len) | |
635 { | |
636 return prng_GenerateGlobalRandomBytes(globalrng, dest, len); | |
637 } | |
638 | |
639 void | |
640 RNG_RNGShutdown(void) | |
641 { | |
642 /* check for a valid global RNG context */ | |
643 PORT_Assert(globalrng != NULL); | |
644 if (globalrng == NULL) { | |
645 /* Should set a "not initialized" error code. */ | |
646 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
647 return; | |
648 } | |
649 /* clear */ | |
650 prng_freeRNGContext(globalrng); | |
651 globalrng = NULL; | |
652 /* reset the callonce struct to allow a new call to RNG_RNGInit() */ | |
653 coRNGInit = pristineCallOnce; | |
654 } | |
655 | |
656 /* | |
657 * Test case interface. used by fips testing and power on self test | |
658 */ | |
659 /* make sure the test context is separate from the global context, This | |
660 * allows us to test the internal random number generator without losing | |
661 * entropy we may have previously collected. */ | |
662 RNGContext testContext; | |
663 | |
664 /* | |
665 * Test vector API. Use NIST SP 800-90 general interface so one of the | |
666 * other NIST SP 800-90 algorithms may be used in the future. | |
667 */ | |
668 SECStatus | |
669 PRNGTEST_Instantiate(const PRUint8 *entropy, unsigned int entropy_len, | |
670 const PRUint8 *nonce, unsigned int nonce_len, | |
671 const PRUint8 *personal_string, unsigned int ps_len) | |
672 { | |
673 int bytes_len = entropy_len + nonce_len + ps_len; | |
674 PRUint8 *bytes = NULL; | |
675 SECStatus rv; | |
676 | |
677 if (entropy_len < 256/PR_BITS_PER_BYTE) { | |
678 PORT_SetError(SEC_ERROR_NEED_RANDOM); | |
679 return SECFailure; | |
680 } | |
681 | |
682 bytes = PORT_Alloc(bytes_len); | |
683 if (bytes == NULL) { | |
684 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
685 return SECFailure; | |
686 } | |
687 /* concatenate the various inputs, internally NSS only instantiates with | |
688 * a single long string */ | |
689 PORT_Memcpy(bytes, entropy, entropy_len); | |
690 if (nonce) { | |
691 PORT_Memcpy(&bytes[entropy_len], nonce, nonce_len); | |
692 } else { | |
693 PORT_Assert(nonce_len == 0); | |
694 } | |
695 if (personal_string) { | |
696 PORT_Memcpy(&bytes[entropy_len+nonce_len], personal_string, ps_len); | |
697 } else { | |
698 PORT_Assert(ps_len == 0); | |
699 } | |
700 rv = prng_instantiate(&testContext, bytes, bytes_len); | |
701 PORT_ZFree(bytes, bytes_len); | |
702 if (rv == SECFailure) { | |
703 return SECFailure; | |
704 } | |
705 testContext.isValid = PR_TRUE; | |
706 return SECSuccess; | |
707 } | |
708 | |
709 SECStatus | |
710 PRNGTEST_Reseed(const PRUint8 *entropy, unsigned int entropy_len, | |
711 const PRUint8 *additional, unsigned int additional_len) | |
712 { | |
713 if (!testContext.isValid) { | |
714 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
715 return SECFailure; | |
716 } | |
717 /* This magic input tells us to set the reseed count to it's max count, | |
718 * so we can simulate PRNGTEST_Generate reaching max reseed count */ | |
719 if ((entropy == NULL) && (entropy_len == 0) && | |
720 (additional == NULL) && (additional_len == 0)) { | |
721 testContext.reseed_counter[0] = RESEED_VALUE; | |
722 return SECSuccess; | |
723 } | |
724 return prng_reseed(&testContext, entropy, entropy_len, additional, | |
725 additional_len); | |
726 | |
727 } | |
728 | |
729 SECStatus | |
730 PRNGTEST_Generate(PRUint8 *bytes, unsigned int bytes_len, | |
731 const PRUint8 *additional, unsigned int additional_len) | |
732 { | |
733 SECStatus rv; | |
734 if (!testContext.isValid) { | |
735 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
736 return SECFailure; | |
737 } | |
738 /* replicate reseed test from prng_GenerateGlobalRandomBytes */ | |
739 if (testContext.reseed_counter[0] >= RESEED_VALUE) { | |
740 rv = prng_reseed(&testContext, NULL, 0, NULL, 0); | |
741 if (rv != SECSuccess) { | |
742 return rv; | |
743 } | |
744 } | |
745 return prng_generateNewBytes(&testContext, bytes, bytes_len, | |
746 additional, additional_len); | |
747 | |
748 } | |
749 | |
750 SECStatus | |
751 PRNGTEST_Uninstantiate() | |
752 { | |
753 if (!testContext.isValid) { | |
754 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
755 return SECFailure; | |
756 } | |
757 PORT_Memset(&testContext, 0, sizeof testContext); | |
758 return SECSuccess; | |
759 } | |
760 | |
761 SECStatus | |
762 PRNGTEST_RunHealthTests() | |
763 { | |
764 static const PRUint8 entropy[] = { | |
765 0x8e,0x9c,0x0d,0x25,0x75,0x22,0x04,0xf9, | |
766 0xc5,0x79,0x10,0x8b,0x23,0x79,0x37,0x14, | |
767 0x9f,0x2c,0xc7,0x0b,0x39,0xf8,0xee,0xef, | |
768 0x95,0x0c,0x97,0x59,0xfc,0x0a,0x85,0x41, | |
769 0x76,0x9d,0x6d,0x67,0x00,0x4e,0x19,0x12, | |
770 0x02,0x16,0x53,0xea,0xf2,0x73,0xd7,0xd6, | |
771 0x7f,0x7e,0xc8,0xae,0x9c,0x09,0x99,0x7d, | |
772 0xbb,0x9e,0x48,0x7f,0xbb,0x96,0x46,0xb3, | |
773 0x03,0x75,0xf8,0xc8,0x69,0x45,0x3f,0x97, | |
774 0x5e,0x2e,0x48,0xe1,0x5d,0x58,0x97,0x4c }; | |
775 static const PRUint8 rng_known_result[] = { | |
776 0x16,0xe1,0x8c,0x57,0x21,0xd8,0xf1,0x7e, | |
777 0x5a,0xa0,0x16,0x0b,0x7e,0xa6,0x25,0xb4, | |
778 0x24,0x19,0xdb,0x54,0xfa,0x35,0x13,0x66, | |
779 0xbb,0xaa,0x2a,0x1b,0x22,0x33,0x2e,0x4a, | |
780 0x14,0x07,0x9d,0x52,0xfc,0x73,0x61,0x48, | |
781 0xac,0xc1,0x22,0xfc,0xa4,0xfc,0xac,0xa4, | |
782 0xdb,0xda,0x5b,0x27,0x33,0xc4,0xb3 }; | |
783 static const PRUint8 reseed_entropy[] = { | |
784 0xc6,0x0b,0x0a,0x30,0x67,0x07,0xf4,0xe2, | |
785 0x24,0xa7,0x51,0x6f,0x5f,0x85,0x3e,0x5d, | |
786 0x67,0x97,0xb8,0x3b,0x30,0x9c,0x7a,0xb1, | |
787 0x52,0xc6,0x1b,0xc9,0x46,0xa8,0x62,0x79 }; | |
788 static const PRUint8 additional_input[] = { | |
789 0x86,0x82,0x28,0x98,0xe7,0xcb,0x01,0x14, | |
790 0xae,0x87,0x4b,0x1d,0x99,0x1b,0xc7,0x41, | |
791 0x33,0xff,0x33,0x66,0x40,0x95,0x54,0xc6, | |
792 0x67,0x4d,0x40,0x2a,0x1f,0xf9,0xeb,0x65 }; | |
793 static const PRUint8 rng_reseed_result[] = { | |
794 0x02,0x0c,0xc6,0x17,0x86,0x49,0xba,0xc4, | |
795 0x7b,0x71,0x35,0x05,0xf0,0xdb,0x4a,0xc2, | |
796 0x2c,0x38,0xc1,0xa4,0x42,0xe5,0x46,0x4a, | |
797 0x7d,0xf0,0xbe,0x47,0x88,0xb8,0x0e,0xc6, | |
798 0x25,0x2b,0x1d,0x13,0xef,0xa6,0x87,0x96, | |
799 0xa3,0x7d,0x5b,0x80,0xc2,0x38,0x76,0x61, | |
800 0xc7,0x80,0x5d,0x0f,0x05,0x76,0x85 }; | |
801 static const PRUint8 rng_no_reseed_result[] = { | |
802 0xc4,0x40,0x41,0x8c,0xbf,0x2f,0x70,0x23, | |
803 0x88,0xf2,0x7b,0x30,0xc3,0xca,0x1e,0xf3, | |
804 0xef,0x53,0x81,0x5d,0x30,0xed,0x4c,0xf1, | |
805 0xff,0x89,0xa5,0xee,0x92,0xf8,0xc0,0x0f, | |
806 0x88,0x53,0xdf,0xb6,0x76,0xf0,0xaa,0xd3, | |
807 0x2e,0x1d,0x64,0x37,0x3e,0xe8,0x4a,0x02, | |
808 0xff,0x0a,0x7f,0xe5,0xe9,0x2b,0x6d }; | |
809 | |
810 SECStatus rng_status = SECSuccess; | |
811 PR_STATIC_ASSERT(sizeof(rng_known_result) >= sizeof(rng_reseed_result)); | |
812 PRUint8 result[sizeof(rng_known_result)]; | |
813 | |
814 /********************************************/ | |
815 /* First test instantiate error path. */ | |
816 /* In this case we supply enough entropy, */ | |
817 /* but not enough seed. This will trigger */ | |
818 /* the code that checks for a entropy */ | |
819 /* source failure. */ | |
820 /********************************************/ | |
821 rng_status = PRNGTEST_Instantiate(entropy, 256/PR_BITS_PER_BYTE, | |
822 NULL, 0, NULL, 0); | |
823 if (rng_status == SECSuccess) { | |
824 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
825 return SECFailure; | |
826 } | |
827 if (PORT_GetError() != SEC_ERROR_NEED_RANDOM) { | |
828 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
829 return SECFailure; | |
830 } | |
831 /* we failed with the proper error code, we can continue */ | |
832 | |
833 /********************************************/ | |
834 /* Generate random bytes with a known seed. */ | |
835 /********************************************/ | |
836 rng_status = PRNGTEST_Instantiate(entropy, sizeof entropy, | |
837 NULL, 0, NULL, 0); | |
838 if (rng_status != SECSuccess) { | |
839 /* Error set by PRNGTEST_Instantiate */ | |
840 return SECFailure; | |
841 } | |
842 rng_status = PRNGTEST_Generate(result, sizeof rng_known_result, NULL, 0); | |
843 if ( ( rng_status != SECSuccess) || | |
844 ( PORT_Memcmp( result, rng_known_result, | |
845 sizeof rng_known_result ) != 0 ) ) { | |
846 PRNGTEST_Uninstantiate(); | |
847 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
848 return SECFailure; | |
849 } | |
850 rng_status = PRNGTEST_Reseed(reseed_entropy, sizeof reseed_entropy, | |
851 additional_input, sizeof additional_input); | |
852 if (rng_status != SECSuccess) { | |
853 /* Error set by PRNG_Reseed */ | |
854 PRNGTEST_Uninstantiate(); | |
855 return SECFailure; | |
856 } | |
857 rng_status = PRNGTEST_Generate(result, sizeof rng_reseed_result, NULL, 0); | |
858 if ( ( rng_status != SECSuccess) || | |
859 ( PORT_Memcmp( result, rng_reseed_result, | |
860 sizeof rng_reseed_result ) != 0 ) ) { | |
861 PRNGTEST_Uninstantiate(); | |
862 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
863 return SECFailure; | |
864 } | |
865 /* This magic forces the reseed count to it's max count, so we can see if | |
866 * PRNGTEST_Generate will actually when it reaches it's count */ | |
867 rng_status = PRNGTEST_Reseed(NULL, 0, NULL, 0); | |
868 if (rng_status != SECSuccess) { | |
869 PRNGTEST_Uninstantiate(); | |
870 /* Error set by PRNG_Reseed */ | |
871 return SECFailure; | |
872 } | |
873 /* This generate should now reseed */ | |
874 rng_status = PRNGTEST_Generate(result, sizeof rng_reseed_result, NULL, 0); | |
875 if ( ( rng_status != SECSuccess) || | |
876 /* NOTE we fail if the result is equal to the no_reseed_result. | |
877 * no_reseed_result is the value we would have gotten if we didn't | |
878 * do an automatic reseed in PRNGTEST_Generate */ | |
879 ( PORT_Memcmp( result, rng_no_reseed_result, | |
880 sizeof rng_no_reseed_result ) == 0 ) ) { | |
881 PRNGTEST_Uninstantiate(); | |
882 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
883 return SECFailure; | |
884 } | |
885 /* make sure reseed fails when we don't supply enough entropy */ | |
886 rng_status = PRNGTEST_Reseed(reseed_entropy, 4, NULL, 0); | |
887 if (rng_status == SECSuccess) { | |
888 PRNGTEST_Uninstantiate(); | |
889 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
890 return SECFailure; | |
891 } | |
892 if (PORT_GetError() != SEC_ERROR_NEED_RANDOM) { | |
893 PRNGTEST_Uninstantiate(); | |
894 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
895 return SECFailure; | |
896 } | |
897 rng_status = PRNGTEST_Uninstantiate(); | |
898 if (rng_status != SECSuccess) { | |
899 /* Error set by PRNG_Uninstantiate */ | |
900 return rng_status; | |
901 } | |
902 /* make sure uninstantiate fails if the contest is not initiated (also tests | |
903 * if the context was cleared in the previous Uninstantiate) */ | |
904 rng_status = PRNGTEST_Uninstantiate(); | |
905 if (rng_status == SECSuccess) { | |
906 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
907 return SECFailure; | |
908 } | |
909 if (PORT_GetError() != SEC_ERROR_LIBRARY_FAILURE) { | |
910 return rng_status; | |
911 } | |
912 | |
913 return SECSuccess; | |
914 } |