OLD | NEW |
1 /* crypto/rand/md_rand.c */ | 1 /* crypto/rand/md_rand.c */ |
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 * All rights reserved. | 3 * All rights reserved. |
4 * | 4 * |
5 * This package is an SSL implementation written | 5 * This package is an SSL implementation written |
6 * by Eric Young (eay@cryptsoft.com). | 6 * by Eric Young (eay@cryptsoft.com). |
7 * The implementation was written so as to conform with Netscapes SSL. | 7 * The implementation was written so as to conform with Netscapes SSL. |
8 * | 8 * |
9 * This library is free for commercial and non-commercial use as long as | 9 * This library is free for commercial and non-commercial use as long as |
10 * the following conditions are aheared to. The following conditions | 10 * the following conditions are aheared to. The following conditions |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 #include <stdio.h> | 119 #include <stdio.h> |
120 #include <string.h> | 120 #include <string.h> |
121 | 121 |
122 #include "e_os.h" | 122 #include "e_os.h" |
123 | 123 |
124 #include <openssl/rand.h> | 124 #include <openssl/rand.h> |
125 #include "rand_lcl.h" | 125 #include "rand_lcl.h" |
126 | 126 |
127 #include <openssl/crypto.h> | 127 #include <openssl/crypto.h> |
128 #include <openssl/err.h> | 128 #include <openssl/err.h> |
129 #ifdef OPENSSL_FIPS | |
130 #include <openssl/fips.h> | |
131 #endif | |
132 | |
133 | 129 |
134 #ifdef BN_DEBUG | 130 #ifdef BN_DEBUG |
135 # define PREDICT | 131 # define PREDICT |
136 #endif | 132 #endif |
137 | 133 |
138 /* #define PREDICT 1 */ | 134 /* #define PREDICT 1 */ |
139 | 135 |
140 #define STATE_SIZE 1023 | 136 #define STATE_SIZE 1023 |
141 static int state_num=0,state_index=0; | 137 static int state_num=0,state_index=0; |
142 static unsigned char state[STATE_SIZE+MD_DIGEST_LENGTH]; | 138 static unsigned char state[STATE_SIZE+MD_DIGEST_LENGTH]; |
143 static unsigned char md[MD_DIGEST_LENGTH]; | 139 static unsigned char md[MD_DIGEST_LENGTH]; |
144 static long md_count[2]={0,0}; | 140 static long md_count[2]={0,0}; |
145 static double entropy=0; | 141 static double entropy=0; |
146 static int initialized=0; | 142 static int initialized=0; |
147 | 143 |
148 static unsigned int crypto_lock_rand = 0; /* may be set only when a thread | 144 static unsigned int crypto_lock_rand = 0; /* may be set only when a thread |
149 * holds CRYPTO_LOCK_RAND | 145 * holds CRYPTO_LOCK_RAND |
150 * (to prevent double locking) */ | 146 * (to prevent double locking) */ |
151 /* access to lockin_thread is synchronized by CRYPTO_LOCK_RAND2 */ | 147 /* access to lockin_thread is synchronized by CRYPTO_LOCK_RAND2 */ |
152 static unsigned long locking_thread = 0; /* valid iff crypto_lock_rand is set */ | 148 static CRYPTO_THREADID locking_threadid; /* valid iff crypto_lock_rand is set */ |
153 | 149 |
154 | 150 |
155 #ifdef PREDICT | 151 #ifdef PREDICT |
156 int rand_predictable=0; | 152 int rand_predictable=0; |
157 #endif | 153 #endif |
158 | 154 |
159 const char RAND_version[]="RAND" OPENSSL_VERSION_PTEXT; | 155 const char RAND_version[]="RAND" OPENSSL_VERSION_PTEXT; |
160 | 156 |
161 static void ssleay_rand_cleanup(void); | 157 static void ssleay_rand_cleanup(void); |
162 static void ssleay_rand_seed(const void *buf, int num); | 158 static void ssleay_rand_seed(const void *buf, int num); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 * the current 'block', the new key data 'block', and 'count' | 206 * the current 'block', the new key data 'block', and 'count' |
211 * (which is incremented after each use). | 207 * (which is incremented after each use). |
212 * The result of this is kept in 'md' and also xored into the | 208 * The result of this is kept in 'md' and also xored into the |
213 * 'state' at the same locations that were used as input into the | 209 * 'state' at the same locations that were used as input into the |
214 * hash function. | 210 * hash function. |
215 */ | 211 */ |
216 | 212 |
217 /* check if we already have the lock */ | 213 /* check if we already have the lock */ |
218 if (crypto_lock_rand) | 214 if (crypto_lock_rand) |
219 { | 215 { |
| 216 CRYPTO_THREADID cur; |
| 217 CRYPTO_THREADID_current(&cur); |
220 CRYPTO_r_lock(CRYPTO_LOCK_RAND2); | 218 CRYPTO_r_lock(CRYPTO_LOCK_RAND2); |
221 » » do_not_lock = (locking_thread == CRYPTO_thread_id()); | 219 » » do_not_lock = !CRYPTO_THREADID_cmp(&locking_threadid, &cur); |
222 CRYPTO_r_unlock(CRYPTO_LOCK_RAND2); | 220 CRYPTO_r_unlock(CRYPTO_LOCK_RAND2); |
223 } | 221 } |
224 else | 222 else |
225 do_not_lock = 0; | 223 do_not_lock = 0; |
226 | 224 |
227 if (!do_not_lock) CRYPTO_w_lock(CRYPTO_LOCK_RAND); | 225 if (!do_not_lock) CRYPTO_w_lock(CRYPTO_LOCK_RAND); |
228 st_idx=state_index; | 226 st_idx=state_index; |
229 | 227 |
230 /* use our own copies of the counters so that even | 228 /* use our own copies of the counters so that even |
231 * if a concurrent thread seeds with exactly the | 229 * if a concurrent thread seeds with exactly the |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 MD_Init(&m); | 265 MD_Init(&m); |
268 MD_Update(&m,local_md,MD_DIGEST_LENGTH); | 266 MD_Update(&m,local_md,MD_DIGEST_LENGTH); |
269 k=(st_idx+j)-STATE_SIZE; | 267 k=(st_idx+j)-STATE_SIZE; |
270 if (k > 0) | 268 if (k > 0) |
271 { | 269 { |
272 MD_Update(&m,&(state[st_idx]),j-k); | 270 MD_Update(&m,&(state[st_idx]),j-k); |
273 MD_Update(&m,&(state[0]),k); | 271 MD_Update(&m,&(state[0]),k); |
274 } | 272 } |
275 else | 273 else |
276 MD_Update(&m,&(state[st_idx]),j); | 274 MD_Update(&m,&(state[st_idx]),j); |
277 » » » | 275 |
| 276 » » /* DO NOT REMOVE THE FOLLOWING CALL TO MD_Update()! */ |
278 MD_Update(&m,buf,j); | 277 MD_Update(&m,buf,j); |
| 278 /* We know that line may cause programs such as |
| 279 purify and valgrind to complain about use of |
| 280 uninitialized data. The problem is not, it's |
| 281 with the caller. Removing that line will make |
| 282 sure you get really bad randomness and thereby |
| 283 other problems such as very insecure keys. */ |
| 284 |
279 MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)); | 285 MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)); |
280 MD_Final(&m,local_md); | 286 MD_Final(&m,local_md); |
281 md_c[1]++; | 287 md_c[1]++; |
282 | 288 |
283 buf=(const char *)buf + j; | 289 buf=(const char *)buf + j; |
284 | 290 |
285 for (k=0; k<j; k++) | 291 for (k=0; k<j; k++) |
286 { | 292 { |
287 /* Parallel threads may interfere with this, | 293 /* Parallel threads may interfere with this, |
288 * but always each byte of the new state is | 294 * but always each byte of the new state is |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 int num_ceil; | 335 int num_ceil; |
330 int ok; | 336 int ok; |
331 long md_c[2]; | 337 long md_c[2]; |
332 unsigned char local_md[MD_DIGEST_LENGTH]; | 338 unsigned char local_md[MD_DIGEST_LENGTH]; |
333 EVP_MD_CTX m; | 339 EVP_MD_CTX m; |
334 #ifndef GETPID_IS_MEANINGLESS | 340 #ifndef GETPID_IS_MEANINGLESS |
335 pid_t curr_pid = getpid(); | 341 pid_t curr_pid = getpid(); |
336 #endif | 342 #endif |
337 int do_stir_pool = 0; | 343 int do_stir_pool = 0; |
338 | 344 |
339 #ifdef OPENSSL_FIPS | |
340 if(FIPS_mode()) | |
341 { | |
342 FIPSerr(FIPS_F_SSLEAY_RAND_BYTES,FIPS_R_NON_FIPS_METHOD); | |
343 return 0; | |
344 } | |
345 #endif | |
346 | |
347 #ifdef PREDICT | 345 #ifdef PREDICT |
348 if (rand_predictable) | 346 if (rand_predictable) |
349 { | 347 { |
350 static unsigned char val=0; | 348 static unsigned char val=0; |
351 | 349 |
352 for (i=0; i<num; i++) | 350 for (i=0; i<num; i++) |
353 buf[i]=val++; | 351 buf[i]=val++; |
354 return(1); | 352 return(1); |
355 } | 353 } |
356 #endif | 354 #endif |
(...skipping 20 matching lines...) Expand all Loading... |
377 * Finally, after we have finished 'num' random bytes for the | 375 * Finally, after we have finished 'num' random bytes for the |
378 * caller, 'count' (which is incremented) and the local and global 'md' | 376 * caller, 'count' (which is incremented) and the local and global 'md' |
379 * are fed into the hash function and the results are kept in the | 377 * are fed into the hash function and the results are kept in the |
380 * global 'md'. | 378 * global 'md'. |
381 */ | 379 */ |
382 | 380 |
383 CRYPTO_w_lock(CRYPTO_LOCK_RAND); | 381 CRYPTO_w_lock(CRYPTO_LOCK_RAND); |
384 | 382 |
385 /* prevent ssleay_rand_bytes() from trying to obtain the lock again */ | 383 /* prevent ssleay_rand_bytes() from trying to obtain the lock again */ |
386 CRYPTO_w_lock(CRYPTO_LOCK_RAND2); | 384 CRYPTO_w_lock(CRYPTO_LOCK_RAND2); |
387 » locking_thread = CRYPTO_thread_id(); | 385 » CRYPTO_THREADID_current(&locking_threadid); |
388 CRYPTO_w_unlock(CRYPTO_LOCK_RAND2); | 386 CRYPTO_w_unlock(CRYPTO_LOCK_RAND2); |
389 crypto_lock_rand = 1; | 387 crypto_lock_rand = 1; |
390 | 388 |
391 if (!initialized) | 389 if (!initialized) |
392 { | 390 { |
393 RAND_poll(); | 391 RAND_poll(); |
394 initialized = 1; | 392 initialized = 1; |
395 } | 393 } |
396 | 394 |
397 if (!stirred_pool) | 395 if (!stirred_pool) |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 MD_Init(&m); | 467 MD_Init(&m); |
470 #ifndef GETPID_IS_MEANINGLESS | 468 #ifndef GETPID_IS_MEANINGLESS |
471 if (curr_pid) /* just in the first iteration to save time */ | 469 if (curr_pid) /* just in the first iteration to save time */ |
472 { | 470 { |
473 MD_Update(&m,(unsigned char*)&curr_pid,sizeof curr_pid); | 471 MD_Update(&m,(unsigned char*)&curr_pid,sizeof curr_pid); |
474 curr_pid = 0; | 472 curr_pid = 0; |
475 } | 473 } |
476 #endif | 474 #endif |
477 MD_Update(&m,local_md,MD_DIGEST_LENGTH); | 475 MD_Update(&m,local_md,MD_DIGEST_LENGTH); |
478 MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)); | 476 MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)); |
479 #ifndef PURIFY | 477 |
480 » » MD_Update(&m,buf,j); /* purify complains */ | 478 #ifndef PURIFY /* purify complains */ |
| 479 » » /* The following line uses the supplied buffer as a small |
| 480 » » * source of entropy: since this buffer is often uninitialised |
| 481 » » * it may cause programs such as purify or valgrind to |
| 482 » » * complain. So for those builds it is not used: the removal |
| 483 » » * of such a small source of entropy has negligible impact on |
| 484 » » * security. |
| 485 » » */ |
| 486 » » MD_Update(&m,buf,j); |
481 #endif | 487 #endif |
| 488 |
482 k=(st_idx+MD_DIGEST_LENGTH/2)-st_num; | 489 k=(st_idx+MD_DIGEST_LENGTH/2)-st_num; |
483 if (k > 0) | 490 if (k > 0) |
484 { | 491 { |
485 MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2-k); | 492 MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2-k); |
486 MD_Update(&m,&(state[0]),k); | 493 MD_Update(&m,&(state[0]),k); |
487 } | 494 } |
488 else | 495 else |
489 MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2); | 496 MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2); |
490 MD_Final(&m,local_md); | 497 MD_Final(&m,local_md); |
491 | 498 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
532 err = ERR_peek_error(); | 539 err = ERR_peek_error(); |
533 if (ERR_GET_LIB(err) == ERR_LIB_RAND && | 540 if (ERR_GET_LIB(err) == ERR_LIB_RAND && |
534 ERR_GET_REASON(err) == RAND_R_PRNG_NOT_SEEDED) | 541 ERR_GET_REASON(err) == RAND_R_PRNG_NOT_SEEDED) |
535 ERR_clear_error(); | 542 ERR_clear_error(); |
536 } | 543 } |
537 return (ret); | 544 return (ret); |
538 } | 545 } |
539 | 546 |
540 static int ssleay_rand_status(void) | 547 static int ssleay_rand_status(void) |
541 { | 548 { |
| 549 CRYPTO_THREADID cur; |
542 int ret; | 550 int ret; |
543 int do_not_lock; | 551 int do_not_lock; |
544 | 552 |
| 553 CRYPTO_THREADID_current(&cur); |
545 /* check if we already have the lock | 554 /* check if we already have the lock |
546 * (could happen if a RAND_poll() implementation calls RAND_status()) */ | 555 * (could happen if a RAND_poll() implementation calls RAND_status()) */ |
547 if (crypto_lock_rand) | 556 if (crypto_lock_rand) |
548 { | 557 { |
549 CRYPTO_r_lock(CRYPTO_LOCK_RAND2); | 558 CRYPTO_r_lock(CRYPTO_LOCK_RAND2); |
550 » » do_not_lock = (locking_thread == CRYPTO_thread_id()); | 559 » » do_not_lock = !CRYPTO_THREADID_cmp(&locking_threadid, &cur); |
551 CRYPTO_r_unlock(CRYPTO_LOCK_RAND2); | 560 CRYPTO_r_unlock(CRYPTO_LOCK_RAND2); |
552 } | 561 } |
553 else | 562 else |
554 do_not_lock = 0; | 563 do_not_lock = 0; |
555 | 564 |
556 if (!do_not_lock) | 565 if (!do_not_lock) |
557 { | 566 { |
558 CRYPTO_w_lock(CRYPTO_LOCK_RAND); | 567 CRYPTO_w_lock(CRYPTO_LOCK_RAND); |
559 | 568 |
560 /* prevent ssleay_rand_bytes() from trying to obtain the lock ag
ain */ | 569 /* prevent ssleay_rand_bytes() from trying to obtain the lock ag
ain */ |
561 CRYPTO_w_lock(CRYPTO_LOCK_RAND2); | 570 CRYPTO_w_lock(CRYPTO_LOCK_RAND2); |
562 » » locking_thread = CRYPTO_thread_id(); | 571 » » CRYPTO_THREADID_cpy(&locking_threadid, &cur); |
563 CRYPTO_w_unlock(CRYPTO_LOCK_RAND2); | 572 CRYPTO_w_unlock(CRYPTO_LOCK_RAND2); |
564 crypto_lock_rand = 1; | 573 crypto_lock_rand = 1; |
565 } | 574 } |
566 | 575 |
567 if (!initialized) | 576 if (!initialized) |
568 { | 577 { |
569 RAND_poll(); | 578 RAND_poll(); |
570 initialized = 1; | 579 initialized = 1; |
571 } | 580 } |
572 | 581 |
573 ret = entropy >= ENTROPY_NEEDED; | 582 ret = entropy >= ENTROPY_NEEDED; |
574 | 583 |
575 if (!do_not_lock) | 584 if (!do_not_lock) |
576 { | 585 { |
577 /* before unlocking, we must clear 'crypto_lock_rand' */ | 586 /* before unlocking, we must clear 'crypto_lock_rand' */ |
578 crypto_lock_rand = 0; | 587 crypto_lock_rand = 0; |
579 | 588 |
580 CRYPTO_w_unlock(CRYPTO_LOCK_RAND); | 589 CRYPTO_w_unlock(CRYPTO_LOCK_RAND); |
581 } | 590 } |
582 | 591 |
583 return ret; | 592 return ret; |
584 } | 593 } |
OLD | NEW |