md_rand.c
来自「一个用于点对点传输加密的工具包源码」· C语言 代码 · 共 512 行 · 第 1/2 页
C
512 行
else MD_Update(&m,&(state[st_idx]),j); MD_Update(&m,buf,j); MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)); MD_Final(local_md,&m); md_c[1]++; buf=(const char *)buf + j; for (k=0; k<j; k++) { /* Parallel threads may interfere with this, * but always each byte of the new state is * the XOR of some previous value of its * and local_md (itermediate values may be lost). * Alway using locking could hurt performance more * than necessary given that conflicts occur only * when the total seeding is longer than the random * state. */ state[st_idx++]^=local_md[k]; if (st_idx >= STATE_SIZE) st_idx=0; } } memset((char *)&m,0,sizeof(m)); if (!add_do_not_lock) CRYPTO_w_lock(CRYPTO_LOCK_RAND); /* Don't just copy back local_md into md -- this could mean that * other thread's seeding remains without effect (except for * the incremented counter). By XORing it we keep at least as * much entropy as fits into md. */ for (k = 0; k < sizeof md; k++) { md[k] ^= local_md[k]; } if (entropy < ENTROPY_NEEDED) /* stop counting when we have enough */ entropy += add; if (!add_do_not_lock) CRYPTO_w_unlock(CRYPTO_LOCK_RAND); #if !defined(THREADS) && !defined(WIN32) assert(md_c[1] == md_count[1]);#endif }static void ssleay_rand_seed(const void *buf, int num) { ssleay_rand_add(buf, num, num); }static int ssleay_rand_bytes(unsigned char *buf, int num) { static volatile int stirred_pool = 0; int i,j,k,st_num,st_idx; int ok; long md_c[2]; unsigned char local_md[MD_DIGEST_LENGTH]; MD_CTX m;#ifndef GETPID_IS_MEANINGLESS pid_t curr_pid = getpid();#endif int do_stir_pool = 0;#ifdef PREDICT if (rand_predictable) { static unsigned char val=0; for (i=0; i<num; i++) buf[i]=val++; return(1); }#endif /* * (Based on the rand(3) manpage:) * * For each group of 10 bytes (or less), we do the following: * * Input into the hash function the top 10 bytes from the * local 'md' (which is initialized from the global 'md' * before any bytes are generated), the bytes that are * to be overwritten by the random bytes, and bytes from the * 'state' (incrementing looping index). From this digest output * (which is kept in 'md'), the top (up to) 10 bytes are * returned to the caller and the bottom (up to) 10 bytes are xored * into the 'state'. * Finally, after we have finished 'num' random bytes for the * caller, 'count' (which is incremented) and the local and global 'md' * are fed into the hash function and the results are kept in the * global 'md'. */ if (!initialized) RAND_poll(); CRYPTO_w_lock(CRYPTO_LOCK_RAND); add_do_not_lock = 1; /* Since we call ssleay_rand_add while in this locked state. */ initialized = 1; if (!stirred_pool) do_stir_pool = 1; ok = (entropy >= ENTROPY_NEEDED); if (!ok) { /* If the PRNG state is not yet unpredictable, then seeing * the PRNG output may help attackers to determine the new * state; thus we have to decrease the entropy estimate. * Once we've had enough initial seeding we don't bother to * adjust the entropy count, though, because we're not ambitious * to provide *information-theoretic* randomness. * * NOTE: This approach fails if the program forks before * we have enough entropy. Entropy should be collected * in a separate input pool and be transferred to the * output pool only when the entropy limit has been reached. */ entropy -= num; if (entropy < 0) entropy = 0; } if (do_stir_pool) { /* Our output function chains only half of 'md', so we better * make sure that the required entropy gets 'evenly distributed' * through 'state', our randomness pool. The input function * (ssleay_rand_add) chains all of 'md', which makes it more * suitable for this purpose. */ int n = STATE_SIZE; /* so that the complete pool gets accessed */ while (n > 0) {#if MD_DIGEST_LENGTH > 20# error "Please adjust DUMMY_SEED."#endif#define DUMMY_SEED "...................." /* at least MD_DIGEST_LENGTH */ /* Note that the seed does not matter, it's just that * ssleay_rand_add expects to have something to hash. */ ssleay_rand_add(DUMMY_SEED, MD_DIGEST_LENGTH, 0.0); n -= MD_DIGEST_LENGTH; } if (ok) stirred_pool = 1; } st_idx=state_index; st_num=state_num; md_c[0] = md_count[0]; md_c[1] = md_count[1]; memcpy(local_md, md, sizeof md); state_index+=num; if (state_index > state_num) state_index %= state_num; /* state[st_idx], ..., state[(st_idx + num - 1) % st_num] * are now ours (but other threads may use them too) */ md_count[0] += 1; add_do_not_lock = 0; /* If this would ever be forgotten, we can expect any evil god to eat our souls. */ CRYPTO_w_unlock(CRYPTO_LOCK_RAND); while (num > 0) { j=(num >= MD_DIGEST_LENGTH/2)?MD_DIGEST_LENGTH/2:num; num-=j; MD_Init(&m);#ifndef GETPID_IS_MEANINGLESS if (curr_pid) /* just in the first iteration to save time */ { MD_Update(&m,(unsigned char*)&curr_pid,sizeof curr_pid); curr_pid = 0; }#endif MD_Update(&m,&(local_md[MD_DIGEST_LENGTH/2]),MD_DIGEST_LENGTH/2); 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; if (k > 0) { MD_Update(&m,&(state[st_idx]),j-k); MD_Update(&m,&(state[0]),k); } else MD_Update(&m,&(state[st_idx]),j); MD_Final(local_md,&m); for (i=0; i<j; i++) { state[st_idx++]^=local_md[i]; /* may compete with other threads */ *(buf++)=local_md[i+MD_DIGEST_LENGTH/2]; if (st_idx >= st_num) st_idx=0; } } MD_Init(&m); MD_Update(&m,(unsigned char *)&(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); CRYPTO_w_unlock(CRYPTO_LOCK_RAND); memset(&m,0,sizeof(m)); if (ok) return(1); else { RANDerr(RAND_F_SSLEAY_RAND_BYTES,RAND_R_PRNG_NOT_SEEDED); ERR_add_error_data(1, "You need to read the OpenSSL FAQ, " "http://www.openssl.org/support/faq.html"); return(0); } }/* pseudo-random bytes that are guaranteed to be unique but not unpredictable */static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num) { int ret, err; ret = RAND_bytes(buf, num); if (ret == 0) { 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(); } return (ret); }static int ssleay_rand_status(void) { int ret; if (!initialized) RAND_poll(); CRYPTO_w_lock(CRYPTO_LOCK_RAND); initialized = 1; ret = entropy >= ENTROPY_NEEDED; CRYPTO_w_unlock(CRYPTO_LOCK_RAND); return ret; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?