X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Frand%2Fmd_rand.c;h=48cc2e84a84bde86740600f1cc3504b591dcd92b;hp=d4d2f36ad4f2acf998d93b6bcc7c44b26c8fcc67;hb=d40a1b865fddc3d67f8c06ff1f1466fad331c8f7;hpb=47b0f48dd9f849f0149f5a5809292e322e129080 diff --git a/crypto/rand/md_rand.c b/crypto/rand/md_rand.c index d4d2f36ad4..48cc2e84a8 100644 --- a/crypto/rand/md_rand.c +++ b/crypto/rand/md_rand.c @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ /* ==================================================================== - * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -144,20 +144,21 @@ static int initialized=0; static unsigned int crypto_lock_rand = 0; /* may be set only when a thread * holds CRYPTO_LOCK_RAND * (to prevent double locking) */ -static unsigned long locking_thread = 0; /* valid iff crypto_lock_rand is set */ +/* access to lockin_thread is synchronized by CRYPTO_LOCK_RAND2 */ +static CRYPTO_THREADID locking_threadid; /* valid iff crypto_lock_rand is set */ #ifdef PREDICT int rand_predictable=0; #endif -const char *RAND_version="RAND" OPENSSL_VERSION_PTEXT; +const char RAND_version[]="RAND" OPENSSL_VERSION_PTEXT; static void ssleay_rand_cleanup(void); -static void ssleay_rand_seed(const void *buf, int num); -static void ssleay_rand_add(const void *buf, int num, double add_entropy); -static int ssleay_rand_bytes(unsigned char *buf, int num); -static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num); +static void ssleay_rand_seed(const void *buf, size_t num); +static void ssleay_rand_add(const void *buf, size_t num, double add_entropy); +static int ssleay_rand_bytes(unsigned char *buf, size_t num); +static int ssleay_rand_pseudo_bytes(unsigned char *buf, size_t num); static int ssleay_rand_status(void); RAND_METHOD rand_ssleay_meth={ @@ -176,22 +177,24 @@ RAND_METHOD *RAND_SSLeay(void) static void ssleay_rand_cleanup(void) { - memset(state,0,sizeof(state)); + OPENSSL_cleanse(state,sizeof(state)); state_num=0; state_index=0; - memset(md,0,MD_DIGEST_LENGTH); + OPENSSL_cleanse(md,MD_DIGEST_LENGTH); md_count[0]=0; md_count[1]=0; entropy=0; initialized=0; } -static void ssleay_rand_add(const void *buf, int num, double add) +static void ssleay_rand_add(const void *buf, size_t num, double add) { - int i,j,k,st_idx; + int i,st_idx; + size_t j; + ssize_t k; long md_c[2]; unsigned char local_md[MD_DIGEST_LENGTH]; - MD_CTX m; + EVP_MD_CTX m; int do_not_lock; /* @@ -210,7 +213,16 @@ static void ssleay_rand_add(const void *buf, int num, double add) */ /* check if we already have the lock */ - do_not_lock = crypto_lock_rand && (locking_thread == CRYPTO_thread_id()); + if (crypto_lock_rand) + { + CRYPTO_THREADID cur; + CRYPTO_THREADID_current(&cur); + CRYPTO_r_lock(CRYPTO_LOCK_RAND2); + do_not_lock = !CRYPTO_THREADID_cmp(&locking_threadid, &cur); + CRYPTO_r_unlock(CRYPTO_LOCK_RAND2); + } + else + do_not_lock = 0; if (!do_not_lock) CRYPTO_w_lock(CRYPTO_LOCK_RAND); st_idx=state_index; @@ -246,6 +258,7 @@ static void ssleay_rand_add(const void *buf, int num, double add) if (!do_not_lock) CRYPTO_w_unlock(CRYPTO_LOCK_RAND); + EVP_MD_CTX_init(&m); for (i=0; i state_num) state_index %= state_num; - /* state[st_idx], ..., state[(st_idx + num - 1) % st_num] + /* state[st_idx], ..., state[(st_idx + num_ceil - 1) % st_num] * are now ours (but other threads may use them too) */ md_count[0] += 1; /* before unlocking, we must clear 'crypto_lock_rand' */ crypto_lock_rand = 0; - locking_thread = 0; CRYPTO_w_unlock(CRYPTO_LOCK_RAND); while (num > 0) { + /* num_ceil -= MD_DIGEST_LENGTH/2 */ j=(num >= MD_DIGEST_LENGTH/2)?MD_DIGEST_LENGTH/2:num; num-=j; MD_Init(&m); @@ -444,39 +468,40 @@ static int ssleay_rand_bytes(unsigned char *buf, int num) curr_pid = 0; } #endif - MD_Update(&m,&(local_md[MD_DIGEST_LENGTH/2]),MD_DIGEST_LENGTH/2); + MD_Update(&m,local_md,MD_DIGEST_LENGTH); MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)); #ifndef PURIFY MD_Update(&m,buf,j); /* purify complains */ #endif - k=(st_idx+j)-st_num; + k=(st_idx+MD_DIGEST_LENGTH/2)-st_num; if (k > 0) { - MD_Update(&m,&(state[st_idx]),j-k); + MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2-k); MD_Update(&m,&(state[0]),k); } else - MD_Update(&m,&(state[st_idx]),j); - MD_Final(local_md,&m); + MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2); + MD_Final(&m,local_md); - for (i=0; i= st_num) st_idx=0; + if (i < j) + *(buf++)=local_md[i+MD_DIGEST_LENGTH/2]; } } MD_Init(&m); - MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)); + MD_Update(&m,&(md_c[0]),sizeof(md_c)); MD_Update(&m,local_md,MD_DIGEST_LENGTH); CRYPTO_w_lock(CRYPTO_LOCK_RAND); MD_Update(&m,md,MD_DIGEST_LENGTH); - MD_Final(md,&m); + MD_Final(&m,md); CRYPTO_w_unlock(CRYPTO_LOCK_RAND); - memset(&m,0,sizeof(m)); + EVP_MD_CTX_cleanup(&m); if (ok) return(1); else @@ -490,7 +515,7 @@ static int ssleay_rand_bytes(unsigned char *buf, int num) /* pseudo-random bytes that are guaranteed to be unique but not unpredictable */ -static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num) +static int ssleay_rand_pseudo_bytes(unsigned char *buf, size_t num) { int ret; unsigned long err; @@ -501,27 +526,38 @@ static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num) err = ERR_peek_error(); if (ERR_GET_LIB(err) == ERR_LIB_RAND && ERR_GET_REASON(err) == RAND_R_PRNG_NOT_SEEDED) - (void)ERR_get_error(); + ERR_clear_error(); } return (ret); } static int ssleay_rand_status(void) { + CRYPTO_THREADID cur; int ret; int do_not_lock; + CRYPTO_THREADID_current(&cur); /* check if we already have the lock * (could happen if a RAND_poll() implementation calls RAND_status()) */ - do_not_lock = crypto_lock_rand && (locking_thread == CRYPTO_thread_id()); + if (crypto_lock_rand) + { + CRYPTO_r_lock(CRYPTO_LOCK_RAND2); + do_not_lock = !CRYPTO_THREADID_cmp(&locking_threadid, &cur); + CRYPTO_r_unlock(CRYPTO_LOCK_RAND2); + } + else + do_not_lock = 0; if (!do_not_lock) { CRYPTO_w_lock(CRYPTO_LOCK_RAND); /* prevent ssleay_rand_bytes() from trying to obtain the lock again */ + CRYPTO_w_lock(CRYPTO_LOCK_RAND2); + CRYPTO_THREADID_cpy(&locking_threadid, &cur); + CRYPTO_w_unlock(CRYPTO_LOCK_RAND2); crypto_lock_rand = 1; - locking_thread = CRYPTO_thread_id(); } if (!initialized) @@ -536,7 +572,6 @@ static int ssleay_rand_status(void) { /* before unlocking, we must clear 'crypto_lock_rand' */ crypto_lock_rand = 0; - locking_thread = 0; CRYPTO_w_unlock(CRYPTO_LOCK_RAND); }