mirror of https://github.com/openssl/openssl.git
				
				
				
			Start to overhaul RAND API
Remove unused rand_hw_xor, MD/EVP indirection
Make rand_pseudo same as rand.
Cleanup formatting and ifdef control
Rename some things:
    - rand_meth to openssl_rand_meth; make it global
    - source file
    - lock/init functions, start per-thread state
    - ossl_meth_init to ossl_rand_init
Put state into RAND_STATE structure
And put OSSL_RAND_STATE into ossl_typ.h
Use "randomness" instead of "entropy"
Reviewed-by: Ben Kaduk <kaduk@mit.edu>
(Merged from https://github.com/openssl/openssl/pull/3758)
			
			
This commit is contained in:
		
							parent
							
								
									71d57be52e
								
							
						
					
					
						commit
						da8fc25a98
					
				|  | @ -1,4 +1,4 @@ | ||||||
| LIBS=../../libcrypto | LIBS=../../libcrypto | ||||||
| SOURCE[../../libcrypto]=\ | SOURCE[../../libcrypto]=\ | ||||||
|         md_rand.c randfile.c rand_lib.c rand_err.c rand_egd.c \ |         ossl_rand.c randfile.c rand_lib.c rand_err.c rand_egd.c \ | ||||||
|         rand_win.c rand_unix.c rand_vms.c |         rand_win.c rand_unix.c rand_vms.c | ||||||
|  |  | ||||||
|  | @ -23,35 +23,40 @@ | ||||||
| #include <openssl/crypto.h> | #include <openssl/crypto.h> | ||||||
| #include <openssl/rand.h> | #include <openssl/rand.h> | ||||||
| #include <openssl/async.h> | #include <openssl/async.h> | ||||||
|  | #include <openssl/err.h> | ||||||
|  | #include <internal/thread_once.h> | ||||||
| #include "rand_lcl.h" | #include "rand_lcl.h" | ||||||
| 
 | 
 | ||||||
| #include <openssl/err.h> |  | ||||||
| 
 |  | ||||||
| #include <internal/thread_once.h> |  | ||||||
| 
 |  | ||||||
| #if defined(BN_DEBUG) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) | #if defined(BN_DEBUG) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) | ||||||
| # define PREDICT | # define PREDICT 1 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| /* #define PREDICT      1 */ |  | ||||||
| 
 |  | ||||||
| #define STATE_SIZE      1023 | #define STATE_SIZE      1023 | ||||||
| static size_t state_num = 0, state_index = 0; |  | ||||||
| static unsigned char state[STATE_SIZE + MD_DIGEST_LENGTH]; |  | ||||||
| static unsigned char md[MD_DIGEST_LENGTH]; |  | ||||||
| static long md_count[2] = { 0, 0 }; |  | ||||||
| 
 | 
 | ||||||
| static double entropy = 0; | typedef struct ossl_rand_state_st OSSL_RAND_STATE; | ||||||
|  | 
 | ||||||
|  | struct ossl_rand_state_st { | ||||||
|  |     size_t num; | ||||||
|  |     size_t index; | ||||||
|  |     unsigned char state[STATE_SIZE + RAND_DIGEST_LENGTH]; | ||||||
|  |     unsigned char md[RAND_DIGEST_LENGTH]; | ||||||
|  |     long md_count[2]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static OSSL_RAND_STATE global_state; | ||||||
|  | static double randomness = 0; | ||||||
| static int initialized = 0; | static int initialized = 0; | ||||||
| 
 |  | ||||||
| static CRYPTO_RWLOCK *rand_lock = NULL; | static CRYPTO_RWLOCK *rand_lock = NULL; | ||||||
| static CRYPTO_RWLOCK *rand_tmp_lock = NULL; | static CRYPTO_RWLOCK *rand_tmp_lock = NULL; | ||||||
| static CRYPTO_ONCE rand_lock_init = CRYPTO_ONCE_STATIC_INIT; | static CRYPTO_ONCE ossl_rand_init = CRYPTO_ONCE_STATIC_INIT; | ||||||
|  | static CRYPTO_THREAD_LOCAL key; | ||||||
| 
 | 
 | ||||||
| /* May be set only when a thread holds rand_lock (to prevent double locking) */ | /* May be set only when a thread holds rand_lock (to prevent double locking) */ | ||||||
| static unsigned int crypto_lock_rand = 0; | static unsigned int crypto_lock_rand = 0; | ||||||
| /* access to locking_threadid is synchronized by rand_tmp_lock */ | /*
 | ||||||
| /* valid iff crypto_lock_rand is set */ |  * access to locking_threadid is synchronized by rand_tmp_lock; | ||||||
|  |  * valid iff crypto_lock_rand is set | ||||||
|  |  */ | ||||||
| static CRYPTO_THREAD_ID locking_threadid; | static CRYPTO_THREAD_ID locking_threadid; | ||||||
| 
 | 
 | ||||||
| #ifdef PREDICT | #ifdef PREDICT | ||||||
|  | @ -60,51 +65,35 @@ int rand_predictable = 0; | ||||||
| 
 | 
 | ||||||
| static int rand_hw_seed(EVP_MD_CTX *ctx); | static int rand_hw_seed(EVP_MD_CTX *ctx); | ||||||
| 
 | 
 | ||||||
| static void rand_cleanup(void); | static void rand_thread_cleanup(void *arg) | ||||||
| static int rand_seed(const void *buf, int num); |  | ||||||
| static int rand_add(const void *buf, int num, double add_entropy); |  | ||||||
| static int rand_bytes(unsigned char *buf, int num, int pseudo); |  | ||||||
| static int rand_nopseudo_bytes(unsigned char *buf, int num); |  | ||||||
| #if OPENSSL_API_COMPAT < 0x10100000L |  | ||||||
| static int rand_pseudo_bytes(unsigned char *buf, int num); |  | ||||||
| #endif |  | ||||||
| static int rand_status(void); |  | ||||||
| 
 |  | ||||||
| static RAND_METHOD rand_meth = { |  | ||||||
|     rand_seed, |  | ||||||
|     rand_nopseudo_bytes, |  | ||||||
|     rand_cleanup, |  | ||||||
|     rand_add, |  | ||||||
| #if OPENSSL_API_COMPAT < 0x10100000L |  | ||||||
|     rand_pseudo_bytes, |  | ||||||
| #else |  | ||||||
|     NULL, |  | ||||||
| #endif |  | ||||||
|     rand_status |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| DEFINE_RUN_ONCE_STATIC(do_rand_lock_init) |  | ||||||
| { | { | ||||||
|  |     OSSL_RAND_STATE *sp = arg; | ||||||
|  | 
 | ||||||
|  |     OPENSSL_clear_free(sp, sizeof(*sp)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | DEFINE_RUN_ONCE_STATIC(do_ossl_rand_init) | ||||||
|  | { | ||||||
|  |     int ret = 1; | ||||||
|  | 
 | ||||||
|     OPENSSL_init_crypto(0, NULL); |     OPENSSL_init_crypto(0, NULL); | ||||||
|     rand_lock = CRYPTO_THREAD_lock_new(); |     rand_lock = CRYPTO_THREAD_lock_new(); | ||||||
|  |     ret &= rand_lock != NULL; | ||||||
|     rand_tmp_lock = CRYPTO_THREAD_lock_new(); |     rand_tmp_lock = CRYPTO_THREAD_lock_new(); | ||||||
|     return rand_lock != NULL && rand_tmp_lock != NULL; |     ret &= rand_tmp_lock != NULL; | ||||||
|  |     ret &= CRYPTO_THREAD_init_local(&key, rand_thread_cleanup) == 1; | ||||||
|  |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RAND_METHOD *RAND_OpenSSL(void) | RAND_METHOD *RAND_OpenSSL(void) | ||||||
| { | { | ||||||
|     return (&rand_meth); |     return &openssl_rand_meth; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void rand_cleanup(void) | static void rand_cleanup(void) | ||||||
| { | { | ||||||
|     OPENSSL_cleanse(state, sizeof(state)); |     OPENSSL_cleanse(&global_state, sizeof(global_state)); | ||||||
|     state_num = 0; |     randomness = 0; | ||||||
|     state_index = 0; |  | ||||||
|     OPENSSL_cleanse(md, MD_DIGEST_LENGTH); |  | ||||||
|     md_count[0] = 0; |  | ||||||
|     md_count[1] = 0; |  | ||||||
|     entropy = 0; |  | ||||||
|     initialized = 0; |     initialized = 0; | ||||||
|     CRYPTO_THREAD_lock_free(rand_lock); |     CRYPTO_THREAD_lock_free(rand_lock); | ||||||
|     CRYPTO_THREAD_lock_free(rand_tmp_lock); |     CRYPTO_THREAD_lock_free(rand_tmp_lock); | ||||||
|  | @ -114,10 +103,11 @@ static int rand_add(const void *buf, int num, double add) | ||||||
| { | { | ||||||
|     int i, j, k, st_idx; |     int i, j, k, st_idx; | ||||||
|     long md_c[2]; |     long md_c[2]; | ||||||
|     unsigned char local_md[MD_DIGEST_LENGTH]; |     unsigned char local_md[RAND_DIGEST_LENGTH]; | ||||||
|     EVP_MD_CTX *m; |     EVP_MD_CTX *m; | ||||||
|     int do_not_lock; |     int do_not_lock; | ||||||
|     int rv = 0; |     int rv = 0; | ||||||
|  |     OSSL_RAND_STATE *sp = &global_state; | ||||||
| 
 | 
 | ||||||
|     if (!num) |     if (!num) | ||||||
|         return 1; |         return 1; | ||||||
|  | @ -146,7 +136,7 @@ static int rand_add(const void *buf, int num, double add) | ||||||
|     if (m == NULL) |     if (m == NULL) | ||||||
|         goto err; |         goto err; | ||||||
| 
 | 
 | ||||||
|     if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init)) |     if (!RUN_ONCE(&ossl_rand_init, do_ossl_rand_init)) | ||||||
|         goto err; |         goto err; | ||||||
| 
 | 
 | ||||||
|     /* check if we already have the lock */ |     /* check if we already have the lock */ | ||||||
|  | @ -160,58 +150,58 @@ static int rand_add(const void *buf, int num, double add) | ||||||
| 
 | 
 | ||||||
|     if (!do_not_lock) |     if (!do_not_lock) | ||||||
|         CRYPTO_THREAD_write_lock(rand_lock); |         CRYPTO_THREAD_write_lock(rand_lock); | ||||||
|     st_idx = state_index; |     st_idx = sp->index; | ||||||
| 
 | 
 | ||||||
|     /*
 |     /*
 | ||||||
|      * use our own copies of the counters so that even if a concurrent thread |      * use our own copies of the counters so that even if a concurrent thread | ||||||
|      * seeds with exactly the same data and uses the same subarray there's |      * seeds with exactly the same data and uses the same subarray there's | ||||||
|      * _some_ difference |      * _some_ difference | ||||||
|      */ |      */ | ||||||
|     md_c[0] = md_count[0]; |     md_c[0] = sp->md_count[0]; | ||||||
|     md_c[1] = md_count[1]; |     md_c[1] = sp->md_count[1]; | ||||||
| 
 | 
 | ||||||
|     memcpy(local_md, md, sizeof md); |     memcpy(local_md, sp->md, sizeof(sp->md)); | ||||||
| 
 | 
 | ||||||
|     /* state_index <= state_num <= STATE_SIZE */ |     /* sp->index <= sp->num <= STATE_SIZE */ | ||||||
|     state_index += num; |     sp->index += num; | ||||||
|     if (state_index >= STATE_SIZE) { |     if (sp->index >= STATE_SIZE) { | ||||||
|         state_index %= STATE_SIZE; |         sp->index %= STATE_SIZE; | ||||||
|         state_num = STATE_SIZE; |         sp->num = STATE_SIZE; | ||||||
|     } else if (state_num < STATE_SIZE) { |     } else if (sp->num < STATE_SIZE) { | ||||||
|         if (state_index > state_num) |         if (sp->index > sp->num) | ||||||
|             state_num = state_index; |             sp->num = sp->index; | ||||||
|     } |     } | ||||||
|     /* state_index <= state_num <= STATE_SIZE */ |     /* sp->index <= sp->num <= STATE_SIZE */ | ||||||
| 
 | 
 | ||||||
|     /*
 |     /*
 | ||||||
|      * state[st_idx], ..., state[(st_idx + num - 1) % STATE_SIZE] are what we |      * state[st_idx], ..., state[(st_idx + num - 1) % STATE_SIZE] are what we | ||||||
|      * will use now, but other threads may use them as well |      * will use now, but other threads may use them as well | ||||||
|      */ |      */ | ||||||
| 
 | 
 | ||||||
|     md_count[1] += (num / MD_DIGEST_LENGTH) + (num % MD_DIGEST_LENGTH > 0); |     sp->md_count[1] += (num / RAND_DIGEST_LENGTH) + (num % RAND_DIGEST_LENGTH > 0); | ||||||
| 
 | 
 | ||||||
|     if (!do_not_lock) |     if (!do_not_lock) | ||||||
|         CRYPTO_THREAD_unlock(rand_lock); |         CRYPTO_THREAD_unlock(rand_lock); | ||||||
| 
 | 
 | ||||||
|     for (i = 0; i < num; i += MD_DIGEST_LENGTH) { |     for (i = 0; i < num; i += RAND_DIGEST_LENGTH) { | ||||||
|         j = (num - i); |         j = (num - i); | ||||||
|         j = (j > MD_DIGEST_LENGTH) ? MD_DIGEST_LENGTH : j; |         j = (j > RAND_DIGEST_LENGTH) ? RAND_DIGEST_LENGTH : j; | ||||||
| 
 | 
 | ||||||
|         if (!MD_Init(m)) |         if (!EVP_DigestInit_ex(m, RAND_DIGEST, NULL)) | ||||||
|             goto err; |             goto err; | ||||||
|         if (!MD_Update(m, local_md, MD_DIGEST_LENGTH)) |         if (!EVP_DigestUpdate(m, local_md, RAND_DIGEST_LENGTH)) | ||||||
|             goto err; |             goto err; | ||||||
|         k = (st_idx + j) - STATE_SIZE; |         k = (st_idx + j) - STATE_SIZE; | ||||||
|         if (k > 0) { |         if (k > 0) { | ||||||
|             if (!MD_Update(m, &(state[st_idx]), j - k)) |             if (!EVP_DigestUpdate(m, &sp->state[st_idx], j - k)) | ||||||
|                 goto err; |                 goto err; | ||||||
|             if (!MD_Update(m, &(state[0]), k)) |             if (!EVP_DigestUpdate(m, &sp->state[0], k)) | ||||||
|                 goto err; |                 goto err; | ||||||
|         } else if (!MD_Update(m, &(state[st_idx]), j)) |         } else if (!EVP_DigestUpdate(m, &sp->state[st_idx], j)) | ||||||
|             goto err; |             goto err; | ||||||
| 
 | 
 | ||||||
|         /* DO NOT REMOVE THE FOLLOWING CALL TO MD_Update()! */ |         /* DO NOT REMOVE THE FOLLOWING CALL TO EVP_DigestUpdate()! */ | ||||||
|         if (!MD_Update(m, buf, j)) |         if (!EVP_DigestUpdate(m, buf, j)) | ||||||
|             goto err; |             goto err; | ||||||
|         /*
 |         /*
 | ||||||
|          * We know that line may cause programs such as purify and valgrind |          * We know that line may cause programs such as purify and valgrind | ||||||
|  | @ -221,9 +211,9 @@ static int rand_add(const void *buf, int num, double add) | ||||||
|          * insecure keys. |          * insecure keys. | ||||||
|          */ |          */ | ||||||
| 
 | 
 | ||||||
|         if (!MD_Update(m, (unsigned char *)&(md_c[0]), sizeof(md_c))) |         if (!EVP_DigestUpdate(m, (unsigned char *)md_c, sizeof(md_c))) | ||||||
|             goto err; |             goto err; | ||||||
|         if (!MD_Final(m, local_md)) |         if (!EVP_DigestFinal_ex(m, local_md, NULL)) | ||||||
|             goto err; |             goto err; | ||||||
|         md_c[1]++; |         md_c[1]++; | ||||||
| 
 | 
 | ||||||
|  | @ -238,7 +228,7 @@ static int rand_add(const void *buf, int num, double add) | ||||||
|              * conflicts occur only when the total seeding is longer than the |              * conflicts occur only when the total seeding is longer than the | ||||||
|              * random state. |              * random state. | ||||||
|              */ |              */ | ||||||
|             state[st_idx++] ^= local_md[k]; |             sp->state[st_idx++] ^= local_md[k]; | ||||||
|             if (st_idx >= STATE_SIZE) |             if (st_idx >= STATE_SIZE) | ||||||
|                 st_idx = 0; |                 st_idx = 0; | ||||||
|         } |         } | ||||||
|  | @ -249,14 +239,14 @@ static int rand_add(const void *buf, int num, double add) | ||||||
|     /*
 |     /*
 | ||||||
|      * Don't just copy back local_md into md -- this could mean that other |      * Don't just copy back local_md into md -- this could mean that other | ||||||
|      * thread's seeding remains without effect (except for the incremented |      * thread's seeding remains without effect (except for the incremented | ||||||
|      * counter).  By XORing it we keep at least as much entropy as fits into |      * counter).  By XORing it we keep at least as much randomness as fits into | ||||||
|      * md. |      * md. | ||||||
|      */ |      */ | ||||||
|     for (k = 0; k < (int)sizeof(md); k++) { |     for (k = 0; k < (int)sizeof(sp->md); k++) { | ||||||
|         md[k] ^= local_md[k]; |         sp->md[k] ^= local_md[k]; | ||||||
|     } |     } | ||||||
|     if (entropy < ENTROPY_NEEDED) /* stop counting when we have enough */ |     if (randomness < RANDOMNESS_NEEDED) /* stop counting when we have enough */ | ||||||
|         entropy += add; |         randomness += add; | ||||||
|     if (!do_not_lock) |     if (!do_not_lock) | ||||||
|         CRYPTO_THREAD_unlock(rand_lock); |         CRYPTO_THREAD_unlock(rand_lock); | ||||||
| 
 | 
 | ||||||
|  | @ -271,15 +261,16 @@ static int rand_seed(const void *buf, int num) | ||||||
|     return rand_add(buf, num, (double)num); |     return rand_add(buf, num, (double)num); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int rand_bytes(unsigned char *buf, int num, int pseudo) | static int rand_bytes(unsigned char *buf, int num) | ||||||
| { | { | ||||||
|     static volatile int stirred_pool = 0; |     static volatile int stirred_pool = 0; | ||||||
|     int i, j, k; |     int i, j, k; | ||||||
|     size_t num_ceil, st_idx, st_num; |     size_t num_ceil, st_idx, st_num; | ||||||
|     int ok; |     int ok; | ||||||
|     long md_c[2]; |     long md_c[2]; | ||||||
|     unsigned char local_md[MD_DIGEST_LENGTH]; |     unsigned char local_md[RAND_DIGEST_LENGTH]; | ||||||
|     EVP_MD_CTX *m; |     EVP_MD_CTX *m; | ||||||
|  |     OSSL_RAND_STATE *sp = &global_state; | ||||||
| #ifndef GETPID_IS_MEANINGLESS | #ifndef GETPID_IS_MEANINGLESS | ||||||
|     pid_t curr_pid = getpid(); |     pid_t curr_pid = getpid(); | ||||||
| #endif | #endif | ||||||
|  | @ -323,9 +314,9 @@ static int rand_bytes(unsigned char *buf, int num, int pseudo) | ||||||
|     if (m == NULL) |     if (m == NULL) | ||||||
|         goto err_mem; |         goto err_mem; | ||||||
| 
 | 
 | ||||||
|     /* round upwards to multiple of MD_DIGEST_LENGTH/2 */ |     /* round upwards to multiple of RAND_DIGEST_LENGTH/2 */ | ||||||
|     num_ceil = |     num_ceil = | ||||||
|         (1 + (num - 1) / (MD_DIGEST_LENGTH / 2)) * (MD_DIGEST_LENGTH / 2); |         (1 + (num - 1) / (RAND_DIGEST_LENGTH / 2)) * (RAND_DIGEST_LENGTH / 2); | ||||||
| 
 | 
 | ||||||
|     /*
 |     /*
 | ||||||
|      * (Based on the rand(3) manpage:) |      * (Based on the rand(3) manpage:) | ||||||
|  | @ -345,7 +336,7 @@ static int rand_bytes(unsigned char *buf, int num, int pseudo) | ||||||
|      * global 'md'. |      * global 'md'. | ||||||
|      */ |      */ | ||||||
| 
 | 
 | ||||||
|     if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init)) |     if (!RUN_ONCE(&ossl_rand_init, do_ossl_rand_init)) | ||||||
|         goto err_mem; |         goto err_mem; | ||||||
| 
 | 
 | ||||||
|     CRYPTO_THREAD_write_lock(rand_lock); |     CRYPTO_THREAD_write_lock(rand_lock); | ||||||
|  | @ -369,28 +360,28 @@ static int rand_bytes(unsigned char *buf, int num, int pseudo) | ||||||
|     if (!stirred_pool) |     if (!stirred_pool) | ||||||
|         do_stir_pool = 1; |         do_stir_pool = 1; | ||||||
| 
 | 
 | ||||||
|     ok = (entropy >= ENTROPY_NEEDED); |     ok = (randomness >= RANDOMNESS_NEEDED); | ||||||
|     if (!ok) { |     if (!ok) { | ||||||
|         /*
 |         /*
 | ||||||
|          * If the PRNG state is not yet unpredictable, then seeing the PRNG |          * If the PRNG state is not yet unpredictable, then seeing the PRNG | ||||||
|          * output may help attackers to determine the new state; thus we have |          * output may help attackers to determine the new state; thus we have | ||||||
|          * to decrease the entropy estimate. Once we've had enough initial |          * to decrease the randomness estimate. Once we've had enough initial | ||||||
|          * seeding we don't bother to adjust the entropy count, though, |          * seeding we don't bother to adjust the randomness count, though, | ||||||
|          * because we're not ambitious to provide *information-theoretic* |          * because we're not ambitious to provide *information-theoretic* | ||||||
|          * randomness. NOTE: This approach fails if the program forks before |          * randomness. NOTE: This approach fails if the program forks before | ||||||
|          * we have enough entropy. Entropy should be collected in a separate |          * we have enough randomness. Randomness should be collected in a | ||||||
|          * input pool and be transferred to the output pool only when the |          * separate input pool and be transferred to the output pool only | ||||||
|          * entropy limit has been reached. |          * when the randomness limit has been reached. | ||||||
|          */ |          */ | ||||||
|         entropy -= num; |         randomness -= num; | ||||||
|         if (entropy < 0) |         if (randomness < 0) | ||||||
|             entropy = 0; |             randomness = 0; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (do_stir_pool) { |     if (do_stir_pool) { | ||||||
|         /*
 |         /*
 | ||||||
|          * In the output function only half of 'md' remains secret, so we |          * In the output function only half of 'md' remains secret, so we | ||||||
|          * better make sure that the required entropy gets 'evenly |          * better make sure that the required randomness gets 'evenly | ||||||
|          * distributed' through 'state', our randomness pool. The input |          * distributed' through 'state', our randomness pool. The input | ||||||
|          * function (rand_add) chains all of 'md', which makes it more |          * function (rand_add) chains all of 'md', which makes it more | ||||||
|          * suitable for this purpose. |          * suitable for this purpose. | ||||||
|  | @ -398,37 +389,37 @@ static int rand_bytes(unsigned char *buf, int num, int pseudo) | ||||||
| 
 | 
 | ||||||
|         int n = STATE_SIZE;     /* so that the complete pool gets accessed */ |         int n = STATE_SIZE;     /* so that the complete pool gets accessed */ | ||||||
|         while (n > 0) { |         while (n > 0) { | ||||||
| #if MD_DIGEST_LENGTH > 20 | #if RAND_DIGEST_LENGTH > 20 | ||||||
| # error "Please adjust DUMMY_SEED." | # error "Please adjust DUMMY_SEED." | ||||||
| #endif | #endif | ||||||
| #define DUMMY_SEED "...................." /* at least MD_DIGEST_LENGTH */ | #define DUMMY_SEED "...................." /* at least RAND_DIGEST_LENGTH */ | ||||||
|             /*
 |             /*
 | ||||||
|              * Note that the seed does not matter, it's just that |              * Note that the seed does not matter, it's just that | ||||||
|              * rand_add expects to have something to hash. |              * rand_add expects to have something to hash. | ||||||
|              */ |              */ | ||||||
|             rand_add(DUMMY_SEED, MD_DIGEST_LENGTH, 0.0); |             rand_add(DUMMY_SEED, RAND_DIGEST_LENGTH, 0.0); | ||||||
|             n -= MD_DIGEST_LENGTH; |             n -= RAND_DIGEST_LENGTH; | ||||||
|         } |         } | ||||||
|         if (ok) |         if (ok) | ||||||
|             stirred_pool = 1; |             stirred_pool = 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     st_idx = state_index; |     st_idx = sp->index; | ||||||
|     st_num = state_num; |     st_num = sp->num; | ||||||
|     md_c[0] = md_count[0]; |     md_c[0] = sp->md_count[0]; | ||||||
|     md_c[1] = md_count[1]; |     md_c[1] = sp->md_count[1]; | ||||||
|     memcpy(local_md, md, sizeof md); |     memcpy(local_md, sp->md, sizeof sp->md); | ||||||
| 
 | 
 | ||||||
|     state_index += num_ceil; |     sp->index += num_ceil; | ||||||
|     if (state_index > state_num) |     if (sp->index > sp->num) | ||||||
|         state_index %= state_num; |         sp->index %= sp->num; | ||||||
| 
 | 
 | ||||||
|     /*
 |     /*
 | ||||||
|      * state[st_idx], ..., state[(st_idx + num_ceil - 1) % st_num] are now |      * state[st_idx], ..., state[(st_idx + num_ceil - 1) % st_num] are now | ||||||
|      * ours (but other threads may use them too) |      * ours (but other threads may use them too) | ||||||
|      */ |      */ | ||||||
| 
 | 
 | ||||||
|     md_count[0] += 1; |     sp->md_count[0] += 1; | ||||||
| 
 | 
 | ||||||
|     /* before unlocking, we must clear 'crypto_lock_rand' */ |     /* before unlocking, we must clear 'crypto_lock_rand' */ | ||||||
|     crypto_lock_rand = 0; |     crypto_lock_rand = 0; | ||||||
|  | @ -436,63 +427,64 @@ static int rand_bytes(unsigned char *buf, int num, int pseudo) | ||||||
|     CRYPTO_THREAD_unlock(rand_lock); |     CRYPTO_THREAD_unlock(rand_lock); | ||||||
| 
 | 
 | ||||||
|     while (num > 0) { |     while (num > 0) { | ||||||
|         /* num_ceil -= MD_DIGEST_LENGTH/2 */ |         /* num_ceil -= RAND_DIGEST_LENGTH / 2 */ | ||||||
|         j = (num >= MD_DIGEST_LENGTH / 2) ? MD_DIGEST_LENGTH / 2 : num; |         j = (num >= RAND_DIGEST_LENGTH / 2) ? RAND_DIGEST_LENGTH / 2 : num; | ||||||
|         num -= j; |         num -= j; | ||||||
|         if (!MD_Init(m)) |         if (!EVP_DigestInit_ex(m, RAND_DIGEST, NULL)) | ||||||
|             goto err; |             goto err; | ||||||
| #ifndef GETPID_IS_MEANINGLESS | #ifndef GETPID_IS_MEANINGLESS | ||||||
|         if (curr_pid) {         /* just in the first iteration to save time */ |         if (curr_pid) {         /* just in the first iteration to save time */ | ||||||
|             if (!MD_Update(m, (unsigned char *)&curr_pid, sizeof curr_pid)) |             if (!EVP_DigestUpdate(m, (unsigned char *)&curr_pid, sizeof curr_pid)) | ||||||
|                 goto err; |                 goto err; | ||||||
|             curr_pid = 0; |             curr_pid = 0; | ||||||
|         } |         } | ||||||
| #endif | #endif | ||||||
|         if (curr_time) {        /* just in the first iteration to save time */ |         if (curr_time) {        /* just in the first iteration to save time */ | ||||||
|             if (!MD_Update(m, (unsigned char *)&curr_time, sizeof curr_time)) |             if (!EVP_DigestUpdate(m, (unsigned char *)&curr_time, sizeof curr_time)) | ||||||
|                 goto err; |                 goto err; | ||||||
|             if (!MD_Update(m, (unsigned char *)&tv, sizeof tv)) |             if (!EVP_DigestUpdate(m, (unsigned char *)&tv, sizeof tv)) | ||||||
|                 goto err; |                 goto err; | ||||||
|             curr_time = 0; |             curr_time = 0; | ||||||
|             if (!rand_hw_seed(m)) |             if (!rand_hw_seed(m)) | ||||||
|                 goto err; |                 goto err; | ||||||
|         } |         } | ||||||
|         if (!MD_Update(m, local_md, MD_DIGEST_LENGTH)) |         if (!EVP_DigestUpdate(m, local_md, RAND_DIGEST_LENGTH)) | ||||||
|             goto err; |             goto err; | ||||||
|         if (!MD_Update(m, (unsigned char *)&(md_c[0]), sizeof(md_c))) |         if (!EVP_DigestUpdate(m, (unsigned char *)md_c, sizeof(md_c))) | ||||||
|             goto err; |             goto err; | ||||||
| 
 | 
 | ||||||
|         k = (st_idx + MD_DIGEST_LENGTH / 2) - st_num; |         k = (st_idx + RAND_DIGEST_LENGTH / 2) - st_num; | ||||||
|         if (k > 0) { |         if (k > 0) { | ||||||
|             if (!MD_Update(m, &(state[st_idx]), MD_DIGEST_LENGTH / 2 - k)) |             if (!EVP_DigestUpdate(m, &sp->state[st_idx], RAND_DIGEST_LENGTH / 2 - k)) | ||||||
|                 goto err; |                 goto err; | ||||||
|             if (!MD_Update(m, &(state[0]), k)) |             if (!EVP_DigestUpdate(m, &sp->state[0], k)) | ||||||
|                 goto err; |                 goto err; | ||||||
|         } else if (!MD_Update(m, &(state[st_idx]), MD_DIGEST_LENGTH / 2)) |         } else if (!EVP_DigestUpdate(m, &sp->state[st_idx], RAND_DIGEST_LENGTH / 2)) | ||||||
|             goto err; |             goto err; | ||||||
|         if (!MD_Final(m, local_md)) |         if (!EVP_DigestFinal_ex(m, local_md, NULL)) | ||||||
|             goto err; |             goto err; | ||||||
| 
 | 
 | ||||||
|         for (i = 0; i < MD_DIGEST_LENGTH / 2; i++) { |         for (i = 0; i < RAND_DIGEST_LENGTH / 2; i++) { | ||||||
|             /* may compete with other threads */ |             /* may compete with other threads */ | ||||||
|             state[st_idx++] ^= local_md[i]; |             sp->state[st_idx++] ^= local_md[i]; | ||||||
|             if (st_idx >= st_num) |             if (st_idx >= st_num) | ||||||
|                 st_idx = 0; |                 st_idx = 0; | ||||||
|             if (i < j) |             if (i < j) | ||||||
|                 *(buf++) = local_md[i + MD_DIGEST_LENGTH / 2]; |                 *(buf++) = local_md[i + RAND_DIGEST_LENGTH / 2]; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!MD_Init(m) |     if (!EVP_DigestInit_ex(m, RAND_DIGEST, NULL) | ||||||
|         || !MD_Update(m, (unsigned char *)&(md_c[0]), sizeof(md_c)) |         || !EVP_DigestUpdate(m, (unsigned char *)md_c, sizeof(md_c)) | ||||||
|         || !MD_Update(m, local_md, MD_DIGEST_LENGTH)) |         || !EVP_DigestUpdate(m, local_md, RAND_DIGEST_LENGTH)) | ||||||
|         goto err; |         goto err; | ||||||
|     CRYPTO_THREAD_write_lock(rand_lock); |     CRYPTO_THREAD_write_lock(rand_lock); | ||||||
|     /*
 |     /*
 | ||||||
|      * Prevent deadlocks if we end up in an async engine |      * Prevent deadlocks if we end up in an async engine | ||||||
|      */ |      */ | ||||||
|     ASYNC_block_pause(); |     ASYNC_block_pause(); | ||||||
|     if (!MD_Update(m, md, MD_DIGEST_LENGTH) || !MD_Final(m, md)) { |     if (!EVP_DigestUpdate(m, sp->md, sizeof(sp->md)) | ||||||
|  |             || !EVP_DigestFinal_ex(m, sp->md, NULL)) { | ||||||
|         CRYPTO_THREAD_unlock(rand_lock); |         CRYPTO_THREAD_unlock(rand_lock); | ||||||
|         goto err; |         goto err; | ||||||
|     } |     } | ||||||
|  | @ -502,14 +494,10 @@ static int rand_bytes(unsigned char *buf, int num, int pseudo) | ||||||
|     EVP_MD_CTX_free(m); |     EVP_MD_CTX_free(m); | ||||||
|     if (ok) |     if (ok) | ||||||
|         return (1); |         return (1); | ||||||
|     else if (pseudo) |     RANDerr(RAND_F_RAND_BYTES, RAND_R_PRNG_NOT_SEEDED); | ||||||
|         return 0; |     ERR_add_error_data(1, "You need to read the OpenSSL FAQ, " | ||||||
|     else { |                        "https://www.openssl.org/docs/faq.html"); | ||||||
|         RANDerr(RAND_F_RAND_BYTES, RAND_R_PRNG_NOT_SEEDED); |     return (0); | ||||||
|         ERR_add_error_data(1, "You need to read the OpenSSL FAQ, " |  | ||||||
|                            "https://www.openssl.org/docs/faq.html"); |  | ||||||
|         return (0); |  | ||||||
|     } |  | ||||||
|  err: |  err: | ||||||
|     RANDerr(RAND_F_RAND_BYTES, ERR_R_EVP_LIB); |     RANDerr(RAND_F_RAND_BYTES, ERR_R_EVP_LIB); | ||||||
|     EVP_MD_CTX_free(m); |     EVP_MD_CTX_free(m); | ||||||
|  | @ -521,28 +509,13 @@ static int rand_bytes(unsigned char *buf, int num, int pseudo) | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int rand_nopseudo_bytes(unsigned char *buf, int num) |  | ||||||
| { |  | ||||||
|     return rand_bytes(buf, num, 0); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #if OPENSSL_API_COMPAT < 0x10100000L |  | ||||||
| /*
 |  | ||||||
|  * pseudo-random bytes that are guaranteed to be unique but not unpredictable |  | ||||||
|  */ |  | ||||||
| static int rand_pseudo_bytes(unsigned char *buf, int num) |  | ||||||
| { |  | ||||||
|     return rand_bytes(buf, num, 1); |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| static int rand_status(void) | static int rand_status(void) | ||||||
| { | { | ||||||
|     CRYPTO_THREAD_ID cur; |     CRYPTO_THREAD_ID cur; | ||||||
|     int ret; |     int ret; | ||||||
|     int do_not_lock; |     int do_not_lock; | ||||||
| 
 | 
 | ||||||
|     if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init)) |     if (!RUN_ONCE(&ossl_rand_init, do_ossl_rand_init)) | ||||||
|         return 0; |         return 0; | ||||||
| 
 | 
 | ||||||
|     cur = CRYPTO_THREAD_get_current_id(); |     cur = CRYPTO_THREAD_get_current_id(); | ||||||
|  | @ -578,7 +551,7 @@ static int rand_status(void) | ||||||
|         initialized = 1; |         initialized = 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ret = entropy >= ENTROPY_NEEDED; |     ret = randomness >= RANDOMNESS_NEEDED; | ||||||
| 
 | 
 | ||||||
|     if (!do_not_lock) { |     if (!do_not_lock) { | ||||||
|         /* before unlocking, we must clear 'crypto_lock_rand' */ |         /* before unlocking, we must clear 'crypto_lock_rand' */ | ||||||
|  | @ -595,9 +568,6 @@ static int rand_status(void) | ||||||
|  * rand_hw_seed: get seed data from any available hardware RNG. only |  * rand_hw_seed: get seed data from any available hardware RNG. only | ||||||
|  * currently supports rdrand. |  * currently supports rdrand. | ||||||
|  */ |  */ | ||||||
| 
 |  | ||||||
| /* Adapted from eng_rdrand.c */ |  | ||||||
| 
 |  | ||||||
| #if (defined(__i386)   || defined(__i386__)   || defined(_M_IX86) || \ | #if (defined(__i386)   || defined(__i386__)   || defined(_M_IX86) || \ | ||||||
|      defined(__x86_64) || defined(__x86_64__) || \ |      defined(__x86_64) || defined(__x86_64__) || \ | ||||||
|      defined(_M_AMD64) || defined (_M_X64)) && defined(OPENSSL_CPUID_OBJ) \ |      defined(_M_AMD64) || defined (_M_X64)) && defined(OPENSSL_CPUID_OBJ) \ | ||||||
|  | @ -618,40 +588,12 @@ static int rand_hw_seed(EVP_MD_CTX *ctx) | ||||||
|         rnd = OPENSSL_ia32_rdrand(); |         rnd = OPENSSL_ia32_rdrand(); | ||||||
|         if (rnd == 0) |         if (rnd == 0) | ||||||
|             return 1; |             return 1; | ||||||
|         if (!MD_Update(ctx, (unsigned char *)&rnd, sizeof(size_t))) |         if (!EVP_DigestUpdate(ctx, (unsigned char *)&rnd, sizeof(size_t))) | ||||||
|             return 0; |             return 0; | ||||||
|     } |     } | ||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* XOR an existing buffer with random data */ |  | ||||||
| 
 |  | ||||||
| void rand_hw_xor(unsigned char *buf, size_t num) |  | ||||||
| { |  | ||||||
|     size_t rnd; |  | ||||||
|     if (!(OPENSSL_ia32cap_P[1] & (1 << (62 - 32)))) |  | ||||||
|         return; |  | ||||||
|     while (num >= sizeof(size_t)) { |  | ||||||
|         rnd = OPENSSL_ia32_rdrand(); |  | ||||||
|         if (rnd == 0) |  | ||||||
|             return; |  | ||||||
|         *((size_t *)buf) ^= rnd; |  | ||||||
|         buf += sizeof(size_t); |  | ||||||
|         num -= sizeof(size_t); |  | ||||||
|     } |  | ||||||
|     if (num) { |  | ||||||
|         rnd = OPENSSL_ia32_rdrand(); |  | ||||||
|         if (rnd == 0) |  | ||||||
|             return; |  | ||||||
|         while (num) { |  | ||||||
|             *buf ^= rnd & 0xff; |  | ||||||
|             rnd >>= 8; |  | ||||||
|             buf++; |  | ||||||
|             num--; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #else | #else | ||||||
| 
 | 
 | ||||||
| static int rand_hw_seed(EVP_MD_CTX *ctx) | static int rand_hw_seed(EVP_MD_CTX *ctx) | ||||||
|  | @ -659,9 +601,14 @@ static int rand_hw_seed(EVP_MD_CTX *ctx) | ||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void rand_hw_xor(unsigned char *buf, size_t num) |  | ||||||
| { |  | ||||||
|     return; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #endif | #endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | RAND_METHOD openssl_rand_meth = { | ||||||
|  |     rand_seed, | ||||||
|  |     rand_bytes, | ||||||
|  |     rand_cleanup, | ||||||
|  |     rand_add, | ||||||
|  |     rand_bytes, | ||||||
|  |     rand_status | ||||||
|  | }; | ||||||
|  | @ -10,37 +10,15 @@ | ||||||
| #ifndef HEADER_RAND_LCL_H | #ifndef HEADER_RAND_LCL_H | ||||||
| # define HEADER_RAND_LCL_H | # define HEADER_RAND_LCL_H | ||||||
| 
 | 
 | ||||||
| # define ENTROPY_NEEDED 32      /* require 256 bits = 32 bytes of randomness */ | /* we require 256 bits of randomness */ | ||||||
| 
 | # define RANDOMNESS_NEEDED (256 / 8) | ||||||
| # if !defined(USE_MD5_RAND) && !defined(USE_SHA1_RAND) && !defined(USE_MDC2_RAND) && !defined(USE_MD2_RAND) |  | ||||||
| #  define USE_SHA1_RAND |  | ||||||
| # endif |  | ||||||
| 
 | 
 | ||||||
| # include <openssl/evp.h> | # include <openssl/evp.h> | ||||||
| # define MD_Update(a,b,c)        EVP_DigestUpdate(a,b,c) | # include <openssl/sha.h> | ||||||
| # define MD_Final(a,b)           EVP_DigestFinal_ex(a,b,NULL) |  | ||||||
| # if defined(USE_MD5_RAND) |  | ||||||
| #  include <openssl/md5.h> |  | ||||||
| #  define MD_DIGEST_LENGTH        MD5_DIGEST_LENGTH |  | ||||||
| #  define MD_Init(a)              EVP_DigestInit_ex(a,EVP_md5(), NULL) |  | ||||||
| #  define MD(a,b,c)               EVP_Digest(a,b,c,NULL,EVP_md5(), NULL) |  | ||||||
| # elif defined(USE_SHA1_RAND) |  | ||||||
| #  include <openssl/sha.h> |  | ||||||
| #  define MD_DIGEST_LENGTH        SHA_DIGEST_LENGTH |  | ||||||
| #  define MD_Init(a)              EVP_DigestInit_ex(a,EVP_sha1(), NULL) |  | ||||||
| #  define MD(a,b,c)               EVP_Digest(a,b,c,NULL,EVP_sha1(), NULL) |  | ||||||
| # elif defined(USE_MDC2_RAND) |  | ||||||
| #  include <openssl/mdc2.h> |  | ||||||
| #  define MD_DIGEST_LENGTH        MDC2_DIGEST_LENGTH |  | ||||||
| #  define MD_Init(a)              EVP_DigestInit_ex(a,EVP_mdc2(), NULL) |  | ||||||
| #  define MD(a,b,c)               EVP_Digest(a,b,c,NULL,EVP_mdc2(), NULL) |  | ||||||
| # elif defined(USE_MD2_RAND) |  | ||||||
| #  include <openssl/md2.h> |  | ||||||
| #  define MD_DIGEST_LENGTH        MD2_DIGEST_LENGTH |  | ||||||
| #  define MD_Init(a)              EVP_DigestInit_ex(a,EVP_md2(), NULL) |  | ||||||
| #  define MD(a,b,c)               EVP_Digest(a,b,c,NULL,EVP_md2(), NULL) |  | ||||||
| # endif |  | ||||||
| 
 | 
 | ||||||
| void rand_hw_xor(unsigned char *buf, size_t num); | # define RAND_DIGEST EVP_sha1() | ||||||
|  | # define RAND_DIGEST_LENGTH        SHA_DIGEST_LENGTH | ||||||
|  | 
 | ||||||
|  | extern RAND_METHOD openssl_rand_meth; | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -14,17 +14,19 @@ | ||||||
| #include "internal/rand.h" | #include "internal/rand.h" | ||||||
| #include <openssl/engine.h> | #include <openssl/engine.h> | ||||||
| #include "internal/thread_once.h" | #include "internal/thread_once.h" | ||||||
|  | #include "rand_lcl.h" | ||||||
| 
 | 
 | ||||||
| #ifndef OPENSSL_NO_ENGINE | #ifndef OPENSSL_NO_ENGINE | ||||||
| /* non-NULL if default_RAND_meth is ENGINE-provided */ | /* non-NULL if default_RAND_meth is ENGINE-provided */ | ||||||
| static ENGINE *funct_ref = NULL; | static ENGINE *funct_ref; | ||||||
| static CRYPTO_RWLOCK *rand_engine_lock = NULL; | static CRYPTO_RWLOCK *rand_engine_lock; | ||||||
| #endif | #endif | ||||||
| static const RAND_METHOD *default_RAND_meth = NULL; | static CRYPTO_RWLOCK *rand_meth_lock; | ||||||
| static CRYPTO_RWLOCK *rand_meth_lock = NULL; | static const RAND_METHOD *default_RAND_meth; | ||||||
| static CRYPTO_ONCE rand_lock_init = CRYPTO_ONCE_STATIC_INIT; | static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT; | ||||||
| 
 | 
 | ||||||
| DEFINE_RUN_ONCE_STATIC(do_rand_lock_init) | 
 | ||||||
|  | DEFINE_RUN_ONCE_STATIC(do_rand_init) | ||||||
| { | { | ||||||
|     int ret = 1; |     int ret = 1; | ||||||
| #ifndef OPENSSL_NO_ENGINE | #ifndef OPENSSL_NO_ENGINE | ||||||
|  | @ -36,9 +38,22 @@ DEFINE_RUN_ONCE_STATIC(do_rand_lock_init) | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void rand_cleanup_int(void) | ||||||
|  | { | ||||||
|  |     const RAND_METHOD *meth = default_RAND_meth; | ||||||
|  | 
 | ||||||
|  |     if (meth != NULL && meth->cleanup != NULL) | ||||||
|  |         meth->cleanup(); | ||||||
|  |     RAND_set_rand_method(NULL); | ||||||
|  | #ifndef OPENSSL_NO_ENGINE | ||||||
|  |     CRYPTO_THREAD_lock_free(rand_engine_lock); | ||||||
|  | #endif | ||||||
|  |     CRYPTO_THREAD_lock_free(rand_meth_lock); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| int RAND_set_rand_method(const RAND_METHOD *meth) | int RAND_set_rand_method(const RAND_METHOD *meth) | ||||||
| { | { | ||||||
|     if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init)) |     if (!RUN_ONCE(&rand_init, do_rand_init)) | ||||||
|         return 0; |         return 0; | ||||||
| 
 | 
 | ||||||
|     CRYPTO_THREAD_write_lock(rand_meth_lock); |     CRYPTO_THREAD_write_lock(rand_meth_lock); | ||||||
|  | @ -55,25 +70,26 @@ const RAND_METHOD *RAND_get_rand_method(void) | ||||||
| { | { | ||||||
|     const RAND_METHOD *tmp_meth = NULL; |     const RAND_METHOD *tmp_meth = NULL; | ||||||
| 
 | 
 | ||||||
|     if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init)) |     if (!RUN_ONCE(&rand_init, do_rand_init)) | ||||||
|         return NULL; |         return NULL; | ||||||
| 
 | 
 | ||||||
|     CRYPTO_THREAD_write_lock(rand_meth_lock); |     CRYPTO_THREAD_write_lock(rand_meth_lock); | ||||||
|     if (!default_RAND_meth) { |     if (default_RAND_meth == NULL) { | ||||||
| #ifndef OPENSSL_NO_ENGINE | #ifndef OPENSSL_NO_ENGINE | ||||||
|         ENGINE *e = ENGINE_get_default_RAND(); |         ENGINE *e; | ||||||
|         if (e) { | 
 | ||||||
|             default_RAND_meth = ENGINE_get_RAND(e); |         /* If we have an engine that can do RAND, use it. */ | ||||||
|             if (default_RAND_meth == NULL) { |         if ((e = ENGINE_get_default_RAND()) != NULL | ||||||
|                 ENGINE_finish(e); |                 && (tmp_meth = ENGINE_get_RAND(e)) != NULL) { | ||||||
|                 e = NULL; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         if (e) |  | ||||||
|             funct_ref = e; |             funct_ref = e; | ||||||
|         else |             default_RAND_meth = tmp_meth; | ||||||
|  |         } else { | ||||||
|  |             ENGINE_finish(e); | ||||||
|  |             default_RAND_meth = &openssl_rand_meth; | ||||||
|  |         } | ||||||
|  | #else | ||||||
|  |         default_RAND_meth = &openssl_rand_meth; | ||||||
| #endif | #endif | ||||||
|             default_RAND_meth = RAND_OpenSSL(); |  | ||||||
|     } |     } | ||||||
|     tmp_meth = default_RAND_meth; |     tmp_meth = default_RAND_meth; | ||||||
|     CRYPTO_THREAD_unlock(rand_meth_lock); |     CRYPTO_THREAD_unlock(rand_meth_lock); | ||||||
|  | @ -85,10 +101,10 @@ int RAND_set_rand_engine(ENGINE *engine) | ||||||
| { | { | ||||||
|     const RAND_METHOD *tmp_meth = NULL; |     const RAND_METHOD *tmp_meth = NULL; | ||||||
| 
 | 
 | ||||||
|     if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init)) |     if (!RUN_ONCE(&rand_init, do_rand_init)) | ||||||
|         return 0; |         return 0; | ||||||
| 
 | 
 | ||||||
|     if (engine) { |     if (engine != NULL) { | ||||||
|         if (!ENGINE_init(engine)) |         if (!ENGINE_init(engine)) | ||||||
|             return 0; |             return 0; | ||||||
|         tmp_meth = ENGINE_get_RAND(engine); |         tmp_meth = ENGINE_get_RAND(engine); | ||||||
|  | @ -106,55 +122,48 @@ int RAND_set_rand_engine(ENGINE *engine) | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| void rand_cleanup_int(void) |  | ||||||
| { |  | ||||||
|     const RAND_METHOD *meth = default_RAND_meth; |  | ||||||
|     if (meth && meth->cleanup) |  | ||||||
|         meth->cleanup(); |  | ||||||
|     RAND_set_rand_method(NULL); |  | ||||||
|     CRYPTO_THREAD_lock_free(rand_meth_lock); |  | ||||||
| #ifndef OPENSSL_NO_ENGINE |  | ||||||
|     CRYPTO_THREAD_lock_free(rand_engine_lock); |  | ||||||
| #endif |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void RAND_seed(const void *buf, int num) | void RAND_seed(const void *buf, int num) | ||||||
| { | { | ||||||
|     const RAND_METHOD *meth = RAND_get_rand_method(); |     const RAND_METHOD *meth = RAND_get_rand_method(); | ||||||
|     if (meth && meth->seed) | 
 | ||||||
|  |     if (meth->seed != NULL) | ||||||
|         meth->seed(buf, num); |         meth->seed(buf, num); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RAND_add(const void *buf, int num, double entropy) | void RAND_add(const void *buf, int num, double randomness) | ||||||
| { | { | ||||||
|     const RAND_METHOD *meth = RAND_get_rand_method(); |     const RAND_METHOD *meth = RAND_get_rand_method(); | ||||||
|     if (meth && meth->add) | 
 | ||||||
|         meth->add(buf, num, entropy); |     if (meth->add != NULL) | ||||||
|  |         meth->add(buf, num, randomness); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int RAND_bytes(unsigned char *buf, int num) | int RAND_bytes(unsigned char *buf, int num) | ||||||
| { | { | ||||||
|     const RAND_METHOD *meth = RAND_get_rand_method(); |     const RAND_METHOD *meth = RAND_get_rand_method(); | ||||||
|     if (meth && meth->bytes) | 
 | ||||||
|  |     if (meth->bytes != NULL) | ||||||
|         return meth->bytes(buf, num); |         return meth->bytes(buf, num); | ||||||
|     RANDerr(RAND_F_RAND_BYTES, RAND_R_FUNC_NOT_IMPLEMENTED); |     RANDerr(RAND_F_RAND_BYTES, RAND_R_FUNC_NOT_IMPLEMENTED); | ||||||
|     return (-1); |     return -1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #if OPENSSL_API_COMPAT < 0x10100000L | #if OPENSSL_API_COMPAT < 0x10100000L | ||||||
| int RAND_pseudo_bytes(unsigned char *buf, int num) | int RAND_pseudo_bytes(unsigned char *buf, int num) | ||||||
| { | { | ||||||
|     const RAND_METHOD *meth = RAND_get_rand_method(); |     const RAND_METHOD *meth = RAND_get_rand_method(); | ||||||
|     if (meth && meth->pseudorand) | 
 | ||||||
|  |     if (meth->pseudorand != NULL) | ||||||
|         return meth->pseudorand(buf, num); |         return meth->pseudorand(buf, num); | ||||||
|     return (-1); |     return -1; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| int RAND_status(void) | int RAND_status(void) | ||||||
| { | { | ||||||
|     const RAND_METHOD *meth = RAND_get_rand_method(); |     const RAND_METHOD *meth = RAND_get_rand_method(); | ||||||
|     if (meth && meth->status) | 
 | ||||||
|  |     if (meth->status != NULL) | ||||||
|         return meth->status(); |         return meth->status(); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -91,7 +91,7 @@ int RAND_poll(void) | ||||||
|     RAND_add(&curr_uid, sizeof curr_uid, 1); |     RAND_add(&curr_uid, sizeof curr_uid, 1); | ||||||
|     curr_uid = 0; |     curr_uid = 0; | ||||||
| 
 | 
 | ||||||
|     for (i = 0; i < (ENTROPY_NEEDED * 4); i++) { |     for (i = 0; i < (RANDOMNESS_NEEDED * 4); i++) { | ||||||
|         /*
 |         /*
 | ||||||
|          * burn some cpu; hope for interrupts, cache collisions, bus |          * burn some cpu; hope for interrupts, cache collisions, bus | ||||||
|          * interference, etc. |          * interference, etc. | ||||||
|  | @ -127,7 +127,7 @@ int RAND_poll(void) | ||||||
|     unsigned long l; |     unsigned long l; | ||||||
|     pid_t curr_pid = getpid(); |     pid_t curr_pid = getpid(); | ||||||
| #  if defined(DEVRANDOM) || (!defined(OPENSS_NO_EGD) && defined(DEVRANDOM_EGD)) | #  if defined(DEVRANDOM) || (!defined(OPENSS_NO_EGD) && defined(DEVRANDOM_EGD)) | ||||||
|     unsigned char tmpbuf[ENTROPY_NEEDED]; |     unsigned char tmpbuf[RANDOMNESS_NEEDED]; | ||||||
|     int n = 0; |     int n = 0; | ||||||
| #  endif | #  endif | ||||||
| #  ifdef DEVRANDOM | #  ifdef DEVRANDOM | ||||||
|  | @ -144,12 +144,12 @@ int RAND_poll(void) | ||||||
| #  ifdef DEVRANDOM | #  ifdef DEVRANDOM | ||||||
|     memset(randomstats, 0, sizeof(randomstats)); |     memset(randomstats, 0, sizeof(randomstats)); | ||||||
|     /*
 |     /*
 | ||||||
|      * Use a random entropy pool device. Linux, FreeBSD and OpenBSD have |      * Use a randomness device. Linux, FreeBSD and OpenBSD have | ||||||
|      * this. Use /dev/urandom if you can as /dev/random may block if it runs |      * this. Use /dev/urandom if you can as /dev/random may block if it runs | ||||||
|      * out of random entries. |      * out of random entries. | ||||||
|      */ |      */ | ||||||
| 
 | 
 | ||||||
|     for (i = 0; (i < OSSL_NELEM(randomfiles)) && (n < ENTROPY_NEEDED); i++) { |     for (i = 0; (i < OSSL_NELEM(randomfiles)) && (n < RANDOMNESS_NEEDED); i++) { | ||||||
|         if ((fd = open(randomfiles[i], O_RDONLY |         if ((fd = open(randomfiles[i], O_RDONLY | ||||||
| #   ifdef O_NONBLOCK | #   ifdef O_NONBLOCK | ||||||
|                        | O_NONBLOCK |                        | O_NONBLOCK | ||||||
|  | @ -229,7 +229,7 @@ int RAND_poll(void) | ||||||
| 
 | 
 | ||||||
|                 if (try_read) { |                 if (try_read) { | ||||||
|                     r = read(fd, (unsigned char *)tmpbuf + n, |                     r = read(fd, (unsigned char *)tmpbuf + n, | ||||||
|                              ENTROPY_NEEDED - n); |                              RANDOMNESS_NEEDED - n); | ||||||
|                     if (r > 0) |                     if (r > 0) | ||||||
|                         n += r; |                         n += r; | ||||||
|                 } else |                 } else | ||||||
|  | @ -246,7 +246,7 @@ int RAND_poll(void) | ||||||
|             } |             } | ||||||
|             while ((r > 0 || |             while ((r > 0 || | ||||||
|                     (errno == EINTR || errno == EAGAIN)) && usec != 0 |                     (errno == EINTR || errno == EAGAIN)) && usec != 0 | ||||||
|                    && n < ENTROPY_NEEDED); |                    && n < RANDOMNESS_NEEDED); | ||||||
| 
 | 
 | ||||||
|             close(fd); |             close(fd); | ||||||
|         } |         } | ||||||
|  | @ -255,16 +255,15 @@ int RAND_poll(void) | ||||||
| 
 | 
 | ||||||
| #  if !defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD) | #  if !defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD) | ||||||
|     /*
 |     /*
 | ||||||
|      * Use an EGD socket to read entropy from an EGD or PRNGD entropy |      * Use an EGD socket to read randomness from the daemon. | ||||||
|      * collecting daemon. |  | ||||||
|      */ |      */ | ||||||
| 
 | 
 | ||||||
|     for (egdsocket = egdsockets; *egdsocket && n < ENTROPY_NEEDED; |     for (egdsocket = egdsockets; *egdsocket && n < RANDOMNESS_NEEDED; | ||||||
|          egdsocket++) { |          egdsocket++) { | ||||||
|         int r; |         int r; | ||||||
| 
 | 
 | ||||||
|         r = RAND_query_egd_bytes(*egdsocket, (unsigned char *)tmpbuf + n, |         r = RAND_query_egd_bytes(*egdsocket, (unsigned char *)tmpbuf + n, | ||||||
|                                  ENTROPY_NEEDED - n); |                                  RANDOMNESS_NEEDED - n); | ||||||
|         if (r > 0) |         if (r > 0) | ||||||
|             n += r; |             n += r; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -7,16 +7,11 @@ | ||||||
|  * https://www.openssl.org/source/license.html
 |  * https://www.openssl.org/source/license.html
 | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /*
 | #include "e_os.h" | ||||||
|  * Modified by VMS Software, Inc (2016) |  | ||||||
|  *    Eliminate looping through all processes (performance) |  | ||||||
|  *    Add additional randomizations using rand() function |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #include <openssl/rand.h> |  | ||||||
| #include "rand_lcl.h" |  | ||||||
| 
 | 
 | ||||||
| #if defined(OPENSSL_SYS_VMS) | #if defined(OPENSSL_SYS_VMS) | ||||||
|  | # include <openssl/rand.h> | ||||||
|  | # include "rand_lcl.h" | ||||||
| # include <descrip.h> | # include <descrip.h> | ||||||
| # include <jpidef.h> | # include <jpidef.h> | ||||||
| # include <ssdef.h> | # include <ssdef.h> | ||||||
|  | @ -34,9 +29,9 @@ | ||||||
| #  define PTR_T __void_ptr64 | #  define PTR_T __void_ptr64 | ||||||
| #  pragma pointer_size save | #  pragma pointer_size save | ||||||
| #  pragma pointer_size 32 | #  pragma pointer_size 32 | ||||||
| # else                          /* __INITIAL_POINTER_SIZE == 64 */ | # else | ||||||
| #  define PTR_T void * | #  define PTR_T void * | ||||||
| # endif                         /* __INITIAL_POINTER_SIZE == 64 [else] */ | # endif | ||||||
| 
 | 
 | ||||||
| static struct items_data_st { | static struct items_data_st { | ||||||
|     short length, code;         /* length is number of bytes */ |     short length, code;         /* length is number of bytes */ | ||||||
|  | @ -52,27 +47,22 @@ static struct items_data_st { | ||||||
|     {4, JPI$_PPGCNT}, |     {4, JPI$_PPGCNT}, | ||||||
|     {4, JPI$_WSPEAK}, |     {4, JPI$_WSPEAK}, | ||||||
|     {4, JPI$_FINALEXC}, |     {4, JPI$_FINALEXC}, | ||||||
|     {0, 0}                      /* zero terminated */ |     {0, 0} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| int RAND_poll(void) | int RAND_poll(void) | ||||||
| { | { | ||||||
| 
 |  | ||||||
|     /* determine the number of items in the JPI array */ |     /* determine the number of items in the JPI array */ | ||||||
| 
 |  | ||||||
|     struct items_data_st item_entry; |     struct items_data_st item_entry; | ||||||
|     int item_entry_count = sizeof(items_data)/sizeof(item_entry); |     int item_entry_count = OSSL_NELEM(items_data); | ||||||
| 
 |  | ||||||
|     /* Create the JPI itemlist array to hold item_data content */ |     /* Create the JPI itemlist array to hold item_data content */ | ||||||
| 
 |  | ||||||
|     struct { |     struct { | ||||||
|         short length, code; |         short length, code; | ||||||
|         int *buffer; |         int *buffer; | ||||||
|         int *retlen; |         int *retlen; | ||||||
|     } item[item_entry_count], *pitem; /* number of entries in items_data */ |     } item[item_entry_count], *pitem; | ||||||
| 
 |  | ||||||
|     struct items_data_st *pitems_data; |     struct items_data_st *pitems_data; | ||||||
|     int data_buffer[(item_entry_count*2)+4]; /* 8 bytes per entry max */ |     int data_buffer[(item_entry_count * 2) + 4]; /* 8 bytes per entry max */ | ||||||
|     int iosb[2]; |     int iosb[2]; | ||||||
|     int sys_time[2]; |     int sys_time[2]; | ||||||
|     int *ptr; |     int *ptr; | ||||||
|  | @ -80,53 +70,46 @@ int RAND_poll(void) | ||||||
|     int tmp_length   = 0; |     int tmp_length   = 0; | ||||||
|     int total_length = 0; |     int total_length = 0; | ||||||
| 
 | 
 | ||||||
|     pitems_data = items_data; |  | ||||||
|     pitem = item; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     /* Setup itemlist for GETJPI */ |     /* Setup itemlist for GETJPI */ | ||||||
|     while (pitems_data->length) { |     pitems_data = items_data; | ||||||
|  |     for (pitem = item; pitems_data->length != 0; pitem++) { | ||||||
|         pitem->length = pitems_data->length; |         pitem->length = pitems_data->length; | ||||||
|         pitem->code   = pitems_data->code; |         pitem->code   = pitems_data->code; | ||||||
|         pitem->buffer = &data_buffer[total_length]; |         pitem->buffer = &data_buffer[total_length]; | ||||||
|         pitem->retlen = 0; |         pitem->retlen = 0; | ||||||
|         /* total_length is in longwords */ |         /* total_length is in longwords */ | ||||||
|         total_length += pitems_data->length/4; |         total_length += pitems_data->length / 4; | ||||||
|         pitems_data++; |         pitems_data++; | ||||||
|         pitem ++; |  | ||||||
|     } |     } | ||||||
|     pitem->length = pitem->code = 0; |     pitem->length = pitem->code = 0; | ||||||
| 
 | 
 | ||||||
|     /* Fill data_buffer with various info bits from this process */ |     /* Fill data_buffer with various info bits from this process */ | ||||||
|     /* and twist that data to seed the SSL random number init    */ |     if (sys$getjpiw(EFN$C_ENF, NULL, NULL, item, &iosb, 0, 0) != SS$_NORMAL) | ||||||
| 
 |  | ||||||
|     if (sys$getjpiw(EFN$C_ENF, NULL, NULL, item, &iosb, 0, 0) == SS$_NORMAL) { |  | ||||||
|         for (i = 0; i < total_length; i++) { |  | ||||||
|             sys$gettim((struct _generic_64 *)&sys_time[0]); |  | ||||||
|             srand(sys_time[0] * data_buffer[0] * data_buffer[1] + i); |  | ||||||
| 
 |  | ||||||
|             if (i == (total_length - 1)) { /* for JPI$_FINALEXC */ |  | ||||||
|                 ptr = &data_buffer[i]; |  | ||||||
|                 for (j = 0; j < 4; j++) { |  | ||||||
|                     data_buffer[i + j] = ptr[j]; |  | ||||||
|                     /* OK to use rand() just to scramble the seed */ |  | ||||||
|                     data_buffer[i + j] ^= (sys_time[0] ^ rand()); |  | ||||||
|                     tmp_length++; |  | ||||||
|                 } |  | ||||||
|             } else { |  | ||||||
|                 /* OK to use rand() just to scramble the seed */ |  | ||||||
|                 data_buffer[i] ^= (sys_time[0] ^ rand()); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         total_length += (tmp_length - 1); |  | ||||||
| 
 |  | ||||||
|         /* size of seed is total_length*4 bytes (64bytes) */ |  | ||||||
|         RAND_add((PTR_T) data_buffer, total_length*4, total_length * 2); |  | ||||||
|     } else { |  | ||||||
|         return 0; |         return 0; | ||||||
|  | 
 | ||||||
|  |     /* Now twist that data to seed the SSL random number init */ | ||||||
|  |     for (i = 0; i < total_length; i++) { | ||||||
|  |         sys$gettim((struct _generic_64 *)&sys_time[0]); | ||||||
|  |         srand(sys_time[0] * data_buffer[0] * data_buffer[1] + i); | ||||||
|  | 
 | ||||||
|  |         if (i == (total_length - 1)) { /* for JPI$_FINALEXC */ | ||||||
|  |             ptr = &data_buffer[i]; | ||||||
|  |             for (j = 0; j < 4; j++) { | ||||||
|  |                 data_buffer[i + j] = ptr[j]; | ||||||
|  |                 /* OK to use rand() just to scramble the seed */ | ||||||
|  |                 data_buffer[i + j] ^= (sys_time[0] ^ rand()); | ||||||
|  |                 tmp_length++; | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             /* OK to use rand() just to scramble the seed */ | ||||||
|  |             data_buffer[i] ^= (sys_time[0] ^ rand()); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     total_length += (tmp_length - 1); | ||||||
|  | 
 | ||||||
|  |     /* size of seed is total_length*4 bytes (64bytes) */ | ||||||
|  |     RAND_add((PTR_T)data_buffer, total_length * 4, total_length * 2); | ||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue