diff options
author | beck <> | 2000-03-19 11:13:58 +0000 |
---|---|---|
committer | beck <> | 2000-03-19 11:13:58 +0000 |
commit | 796d609550df3a33fc11468741c5d2f6d3df4c11 (patch) | |
tree | 6c6d539061caa20372dad0ac4ddb1dfae2fbe7fe /src/lib/libcrypto/rand/md_rand.c | |
parent | 5be3114c1fd7e0dfea1e38d3abb4cbba75244419 (diff) | |
download | openbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.tar.gz openbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.tar.bz2 openbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.zip |
OpenSSL 0.9.5 merge
*warning* this bumps shared lib minors for libssl and libcrypto from 2.1 to 2.2
if you are using the ssl26 packages for ssh and other things to work you will
need to get new ones (see ~beck/libsslsnap/<arch>) on cvs or ~beck/src-patent.tar.gz on cvs
Diffstat (limited to 'src/lib/libcrypto/rand/md_rand.c')
-rw-r--r-- | src/lib/libcrypto/rand/md_rand.c | 312 |
1 files changed, 237 insertions, 75 deletions
diff --git a/src/lib/libcrypto/rand/md_rand.c b/src/lib/libcrypto/rand/md_rand.c index c9a071bd22..6b158f0349 100644 --- a/src/lib/libcrypto/rand/md_rand.c +++ b/src/lib/libcrypto/rand/md_rand.c | |||
@@ -56,15 +56,23 @@ | |||
56 | * [including the GNU Public Licence.] | 56 | * [including the GNU Public Licence.] |
57 | */ | 57 | */ |
58 | 58 | ||
59 | #define ENTROPY_NEEDED 16 /* require 128 bits = 16 bytes of randomness */ | ||
60 | |||
61 | #ifndef MD_RAND_DEBUG | ||
62 | # ifndef NDEBUG | ||
63 | # define NDEBUG | ||
64 | # endif | ||
65 | #endif | ||
66 | |||
67 | #include <assert.h> | ||
59 | #include <stdio.h> | 68 | #include <stdio.h> |
60 | #include <sys/types.h> | ||
61 | #include <fcntl.h> | ||
62 | #include <time.h> | 69 | #include <time.h> |
63 | #include <string.h> | 70 | #include <string.h> |
64 | 71 | ||
65 | #include "openssl/e_os.h" | 72 | #include "openssl/e_os.h" |
66 | 73 | ||
67 | #include <openssl/crypto.h> | 74 | #include <openssl/crypto.h> |
75 | #include <openssl/err.h> | ||
68 | 76 | ||
69 | #if !defined(USE_MD5_RAND) && !defined(USE_SHA1_RAND) && !defined(USE_MDC2_RAND) && !defined(USE_MD2_RAND) | 77 | #if !defined(USE_MD5_RAND) && !defined(USE_SHA1_RAND) && !defined(USE_MDC2_RAND) && !defined(USE_MD2_RAND) |
70 | #if !defined(NO_SHA) && !defined(NO_SHA1) | 78 | #if !defined(NO_SHA) && !defined(NO_SHA1) |
@@ -130,17 +138,23 @@ static int state_num=0,state_index=0; | |||
130 | static unsigned char state[STATE_SIZE+MD_DIGEST_LENGTH]; | 138 | static unsigned char state[STATE_SIZE+MD_DIGEST_LENGTH]; |
131 | static unsigned char md[MD_DIGEST_LENGTH]; | 139 | static unsigned char md[MD_DIGEST_LENGTH]; |
132 | static long md_count[2]={0,0}; | 140 | static long md_count[2]={0,0}; |
141 | static double entropy=0; | ||
142 | static int initialized=0; | ||
133 | 143 | ||
134 | const char *RAND_version="RAND" OPENSSL_VERSION_PTEXT; | 144 | const char *RAND_version="RAND" OPENSSL_VERSION_PTEXT; |
135 | 145 | ||
136 | static void ssleay_rand_cleanup(void); | 146 | static void ssleay_rand_cleanup(void); |
137 | static void ssleay_rand_seed(const void *buf, int num); | 147 | static void ssleay_rand_seed(const void *buf, int num); |
138 | static void ssleay_rand_bytes(unsigned char *buf, int num); | 148 | static void ssleay_rand_add(const void *buf, int num, double add_entropy); |
149 | static int ssleay_rand_bytes(unsigned char *buf, int num); | ||
150 | static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num); | ||
139 | 151 | ||
140 | RAND_METHOD rand_ssleay_meth={ | 152 | RAND_METHOD rand_ssleay_meth={ |
141 | ssleay_rand_seed, | 153 | ssleay_rand_seed, |
142 | ssleay_rand_bytes, | 154 | ssleay_rand_bytes, |
143 | ssleay_rand_cleanup, | 155 | ssleay_rand_cleanup, |
156 | ssleay_rand_add, | ||
157 | ssleay_rand_pseudo_bytes, | ||
144 | }; | 158 | }; |
145 | 159 | ||
146 | RAND_METHOD *RAND_SSLeay(void) | 160 | RAND_METHOD *RAND_SSLeay(void) |
@@ -156,22 +170,49 @@ static void ssleay_rand_cleanup(void) | |||
156 | memset(md,0,MD_DIGEST_LENGTH); | 170 | memset(md,0,MD_DIGEST_LENGTH); |
157 | md_count[0]=0; | 171 | md_count[0]=0; |
158 | md_count[1]=0; | 172 | md_count[1]=0; |
173 | entropy=0; | ||
159 | } | 174 | } |
160 | 175 | ||
161 | static void ssleay_rand_seed(const void *buf, int num) | 176 | static void ssleay_rand_add(const void *buf, int num, double add) |
162 | { | 177 | { |
163 | int i,j,k,st_idx,st_num; | 178 | int i,j,k,st_idx; |
179 | long md_c[2]; | ||
180 | unsigned char local_md[MD_DIGEST_LENGTH]; | ||
164 | MD_CTX m; | 181 | MD_CTX m; |
165 | 182 | ||
166 | #ifdef NORAND | 183 | #ifdef NORAND |
167 | return; | 184 | return; |
168 | #endif | 185 | #endif |
169 | 186 | ||
187 | /* | ||
188 | * (Based on the rand(3) manpage) | ||
189 | * | ||
190 | * The input is chopped up into units of 20 bytes (or less for | ||
191 | * the last block). Each of these blocks is run through the hash | ||
192 | * function as follows: The data passed to the hash function | ||
193 | * is the current 'md', the same number of bytes from the 'state' | ||
194 | * (the location determined by in incremented looping index) as | ||
195 | * the current 'block', the new key data 'block', and 'count' | ||
196 | * (which is incremented after each use). | ||
197 | * The result of this is kept in 'md' and also xored into the | ||
198 | * 'state' at the same locations that were used as input into the | ||
199 | * hash function. | ||
200 | */ | ||
201 | |||
170 | CRYPTO_w_lock(CRYPTO_LOCK_RAND); | 202 | CRYPTO_w_lock(CRYPTO_LOCK_RAND); |
171 | st_idx=state_index; | 203 | st_idx=state_index; |
172 | st_num=state_num; | ||
173 | 204 | ||
174 | state_index=(state_index+num); | 205 | /* use our own copies of the counters so that even |
206 | * if a concurrent thread seeds with exactly the | ||
207 | * same data and uses the same subarray there's _some_ | ||
208 | * difference */ | ||
209 | md_c[0] = md_count[0]; | ||
210 | md_c[1] = md_count[1]; | ||
211 | |||
212 | memcpy(local_md, md, sizeof md); | ||
213 | |||
214 | /* state_index <= state_num <= STATE_SIZE */ | ||
215 | state_index += num; | ||
175 | if (state_index >= STATE_SIZE) | 216 | if (state_index >= STATE_SIZE) |
176 | { | 217 | { |
177 | state_index%=STATE_SIZE; | 218 | state_index%=STATE_SIZE; |
@@ -182,6 +223,14 @@ static void ssleay_rand_seed(const void *buf, int num) | |||
182 | if (state_index > state_num) | 223 | if (state_index > state_num) |
183 | state_num=state_index; | 224 | state_num=state_index; |
184 | } | 225 | } |
226 | /* state_index <= state_num <= STATE_SIZE */ | ||
227 | |||
228 | /* state[st_idx], ..., state[(st_idx + num - 1) % STATE_SIZE] | ||
229 | * are what we will use now, but other threads may use them | ||
230 | * as well */ | ||
231 | |||
232 | md_count[1] += (num / MD_DIGEST_LENGTH) + (num % MD_DIGEST_LENGTH > 0); | ||
233 | |||
185 | CRYPTO_w_unlock(CRYPTO_LOCK_RAND); | 234 | CRYPTO_w_unlock(CRYPTO_LOCK_RAND); |
186 | 235 | ||
187 | for (i=0; i<num; i+=MD_DIGEST_LENGTH) | 236 | for (i=0; i<num; i+=MD_DIGEST_LENGTH) |
@@ -190,7 +239,7 @@ static void ssleay_rand_seed(const void *buf, int num) | |||
190 | j=(j > MD_DIGEST_LENGTH)?MD_DIGEST_LENGTH:j; | 239 | j=(j > MD_DIGEST_LENGTH)?MD_DIGEST_LENGTH:j; |
191 | 240 | ||
192 | MD_Init(&m); | 241 | MD_Init(&m); |
193 | MD_Update(&m,md,MD_DIGEST_LENGTH); | 242 | MD_Update(&m,local_md,MD_DIGEST_LENGTH); |
194 | k=(st_idx+j)-STATE_SIZE; | 243 | k=(st_idx+j)-STATE_SIZE; |
195 | if (k > 0) | 244 | if (k > 0) |
196 | { | 245 | { |
@@ -201,33 +250,107 @@ static void ssleay_rand_seed(const void *buf, int num) | |||
201 | MD_Update(&m,&(state[st_idx]),j); | 250 | MD_Update(&m,&(state[st_idx]),j); |
202 | 251 | ||
203 | MD_Update(&m,buf,j); | 252 | MD_Update(&m,buf,j); |
204 | MD_Update(&m,(unsigned char *)&(md_count[0]),sizeof(md_count)); | 253 | MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)); |
205 | MD_Final(md,&m); | 254 | MD_Final(local_md,&m); |
206 | md_count[1]++; | 255 | md_c[1]++; |
207 | 256 | ||
208 | buf=(const char *)buf + j; | 257 | buf=(const char *)buf + j; |
209 | 258 | ||
210 | for (k=0; k<j; k++) | 259 | for (k=0; k<j; k++) |
211 | { | 260 | { |
212 | state[st_idx++]^=md[k]; | 261 | /* Parallel threads may interfere with this, |
262 | * but always each byte of the new state is | ||
263 | * the XOR of some previous value of its | ||
264 | * and local_md (itermediate values may be lost). | ||
265 | * Alway using locking could hurt performance more | ||
266 | * than necessary given that conflicts occur only | ||
267 | * when the total seeding is longer than the random | ||
268 | * state. */ | ||
269 | state[st_idx++]^=local_md[k]; | ||
213 | if (st_idx >= STATE_SIZE) | 270 | if (st_idx >= STATE_SIZE) |
214 | { | ||
215 | st_idx=0; | 271 | st_idx=0; |
216 | st_num=STATE_SIZE; | ||
217 | } | ||
218 | } | 272 | } |
219 | } | 273 | } |
220 | memset((char *)&m,0,sizeof(m)); | 274 | memset((char *)&m,0,sizeof(m)); |
275 | |||
276 | CRYPTO_w_lock(CRYPTO_LOCK_RAND); | ||
277 | /* Don't just copy back local_md into md -- this could mean that | ||
278 | * other thread's seeding remains without effect (except for | ||
279 | * the incremented counter). By XORing it we keep at least as | ||
280 | * much entropy as fits into md. */ | ||
281 | for (k = 0; k < sizeof md; k++) | ||
282 | { | ||
283 | md[k] ^= local_md[k]; | ||
284 | } | ||
285 | if (entropy < ENTROPY_NEEDED) /* stop counting when we have enough */ | ||
286 | entropy += add; | ||
287 | CRYPTO_w_unlock(CRYPTO_LOCK_RAND); | ||
288 | |||
289 | #ifndef THREADS | ||
290 | assert(md_c[1] == md_count[1]); | ||
291 | #endif | ||
221 | } | 292 | } |
222 | 293 | ||
223 | static void ssleay_rand_bytes(unsigned char *buf, int num) | 294 | static void ssleay_rand_seed(const void *buf, int num) |
295 | { | ||
296 | ssleay_rand_add(buf, num, num); | ||
297 | } | ||
298 | |||
299 | static void ssleay_rand_initialize(void) | ||
224 | { | 300 | { |
225 | int i,j,k,st_num,st_idx; | ||
226 | MD_CTX m; | ||
227 | static int init=1; | ||
228 | unsigned long l; | 301 | unsigned long l; |
302 | #ifndef GETPID_IS_MEANINGLESS | ||
303 | pid_t curr_pid = getpid(); | ||
304 | #endif | ||
229 | #ifdef DEVRANDOM | 305 | #ifdef DEVRANDOM |
230 | int fd; | 306 | FILE *fh; |
307 | #endif | ||
308 | |||
309 | CRYPTO_w_unlock(CRYPTO_LOCK_RAND); | ||
310 | /* put in some default random data, we need more than just this */ | ||
311 | #ifndef GETPID_IS_MEANINGLESS | ||
312 | l=curr_pid; | ||
313 | RAND_add(&l,sizeof(l),0); | ||
314 | l=getuid(); | ||
315 | RAND_add(&l,sizeof(l),0); | ||
316 | #endif | ||
317 | l=time(NULL); | ||
318 | RAND_add(&l,sizeof(l),0); | ||
319 | |||
320 | #ifdef DEVRANDOM | ||
321 | /* Use a random entropy pool device. Linux, FreeBSD and OpenBSD | ||
322 | * have this. Use /dev/urandom if you can as /dev/random may block | ||
323 | * if it runs out of random entries. */ | ||
324 | |||
325 | if ((fh = fopen(DEVRANDOM, "r")) != NULL) | ||
326 | { | ||
327 | unsigned char tmpbuf[ENTROPY_NEEDED]; | ||
328 | int n; | ||
329 | |||
330 | setvbuf(fh, NULL, _IONBF, 0); | ||
331 | n=fread((unsigned char *)tmpbuf,1,ENTROPY_NEEDED,fh); | ||
332 | fclose(fh); | ||
333 | RAND_add(tmpbuf,sizeof tmpbuf,n); | ||
334 | memset(tmpbuf,0,n); | ||
335 | } | ||
336 | #endif | ||
337 | #ifdef PURIFY | ||
338 | memset(state,0,STATE_SIZE); | ||
339 | memset(md,0,MD_DIGEST_LENGTH); | ||
340 | #endif | ||
341 | CRYPTO_w_lock(CRYPTO_LOCK_RAND); | ||
342 | initialized=1; | ||
343 | } | ||
344 | |||
345 | static int ssleay_rand_bytes(unsigned char *buf, int num) | ||
346 | { | ||
347 | int i,j,k,st_num,st_idx; | ||
348 | int ok; | ||
349 | long md_c[2]; | ||
350 | unsigned char local_md[MD_DIGEST_LENGTH]; | ||
351 | MD_CTX m; | ||
352 | #ifndef GETPID_IS_MEANINGLESS | ||
353 | pid_t curr_pid = getpid(); | ||
231 | #endif | 354 | #endif |
232 | 355 | ||
233 | #ifdef PREDICT | 356 | #ifdef PREDICT |
@@ -236,65 +359,63 @@ static void ssleay_rand_bytes(unsigned char *buf, int num) | |||
236 | 359 | ||
237 | for (i=0; i<num; i++) | 360 | for (i=0; i<num; i++) |
238 | buf[i]=val++; | 361 | buf[i]=val++; |
239 | return; | 362 | return(1); |
240 | } | 363 | } |
241 | #endif | 364 | #endif |
242 | 365 | ||
366 | /* | ||
367 | * (Based on the rand(3) manpage:) | ||
368 | * | ||
369 | * For each group of 10 bytes (or less), we do the following: | ||
370 | * | ||
371 | * Input into the hash function the top 10 bytes from the | ||
372 | * local 'md' (which is initialized from the global 'md' | ||
373 | * before any bytes are generated), the bytes that are | ||
374 | * to be overwritten by the random bytes, and bytes from the | ||
375 | * 'state' (incrementing looping index). From this digest output | ||
376 | * (which is kept in 'md'), the top (up to) 10 bytes are | ||
377 | * returned to the caller and the bottom (up to) 10 bytes are xored | ||
378 | * into the 'state'. | ||
379 | * Finally, after we have finished 'num' random bytes for the | ||
380 | * caller, 'count' (which is incremented) and the local and global 'md' | ||
381 | * are fed into the hash function and the results are kept in the | ||
382 | * global 'md'. | ||
383 | */ | ||
384 | |||
243 | CRYPTO_w_lock(CRYPTO_LOCK_RAND); | 385 | CRYPTO_w_lock(CRYPTO_LOCK_RAND); |
244 | 386 | ||
245 | if (init) | 387 | if (!initialized) |
388 | ssleay_rand_initialize(); | ||
389 | |||
390 | ok = (entropy >= ENTROPY_NEEDED); | ||
391 | if (!ok) | ||
246 | { | 392 | { |
247 | CRYPTO_w_unlock(CRYPTO_LOCK_RAND); | 393 | /* If the PRNG state is not yet unpredictable, then seeing |
248 | /* put in some default random data, we need more than | 394 | * the PRNG output may help attackers to determine the new |
249 | * just this */ | 395 | * state; thus we have to decrease the entropy estimate. |
250 | RAND_seed(&m,sizeof(m)); | 396 | * Once we've had enough initial seeding we don't bother to |
251 | #ifndef MSDOS | 397 | * adjust the entropy count, though, because we're not ambitious |
252 | l=getpid(); | 398 | * to provide *information-theoretic* randomness. |
253 | RAND_seed(&l,sizeof(l)); | ||
254 | l=getuid(); | ||
255 | RAND_seed(&l,sizeof(l)); | ||
256 | #endif | ||
257 | l=time(NULL); | ||
258 | RAND_seed(&l,sizeof(l)); | ||
259 | |||
260 | /* #ifdef DEVRANDOM */ | ||
261 | /* | ||
262 | * Use a random entropy pool device. | ||
263 | * Linux 1.3.x, OpenBSD, and FreeBSD have | ||
264 | * this. Use /dev/urandom if you can | ||
265 | * as /dev/random will block if it runs out | ||
266 | * of random entries. | ||
267 | */ | 399 | */ |
268 | if ((fd = open(DEVRANDOM, O_RDONLY)) != NULL) | 400 | entropy -= num; |
269 | { | 401 | if (entropy < 0) |
270 | unsigned char tmpbuf[32]; | 402 | entropy = 0; |
271 | |||
272 | read(fd, tmpbuf, sizeof(tmpbuf)); | ||
273 | /* we don't care how many bytes we read, | ||
274 | * we will just copy the 'stack' if there is | ||
275 | * nothing else :-) */ | ||
276 | /* the above comment is EVIL. Security software | ||
277 | * RELIES ON THESE PRIMITIVES HAVING MORE SECURE | ||
278 | * BEHAVIOUR! Secure entropy is required in | ||
279 | * many cases! */ | ||
280 | RAND_seed(tmpbuf,32); | ||
281 | memset(tmpbuf,0,32); | ||
282 | } | ||
283 | /* #endif */ | ||
284 | #ifdef PURIFY | ||
285 | memset(state,0,STATE_SIZE); | ||
286 | memset(md,0,MD_DIGEST_LENGTH); | ||
287 | #endif | ||
288 | CRYPTO_w_lock(CRYPTO_LOCK_RAND); | ||
289 | init=0; | ||
290 | } | 403 | } |
291 | 404 | ||
292 | st_idx=state_index; | 405 | st_idx=state_index; |
293 | st_num=state_num; | 406 | st_num=state_num; |
407 | md_c[0] = md_count[0]; | ||
408 | md_c[1] = md_count[1]; | ||
409 | memcpy(local_md, md, sizeof md); | ||
410 | |||
294 | state_index+=num; | 411 | state_index+=num; |
295 | if (state_index > state_num) | 412 | if (state_index > state_num) |
296 | state_index=(state_index%state_num); | 413 | state_index %= state_num; |
414 | |||
415 | /* state[st_idx], ..., state[(st_idx + num - 1) % st_num] | ||
416 | * are now ours (but other threads may use them too) */ | ||
297 | 417 | ||
418 | md_count[0] += 1; | ||
298 | CRYPTO_w_unlock(CRYPTO_LOCK_RAND); | 419 | CRYPTO_w_unlock(CRYPTO_LOCK_RAND); |
299 | 420 | ||
300 | while (num > 0) | 421 | while (num > 0) |
@@ -302,8 +423,15 @@ static void ssleay_rand_bytes(unsigned char *buf, int num) | |||
302 | j=(num >= MD_DIGEST_LENGTH/2)?MD_DIGEST_LENGTH/2:num; | 423 | j=(num >= MD_DIGEST_LENGTH/2)?MD_DIGEST_LENGTH/2:num; |
303 | num-=j; | 424 | num-=j; |
304 | MD_Init(&m); | 425 | MD_Init(&m); |
305 | MD_Update(&m,&(md[MD_DIGEST_LENGTH/2]),MD_DIGEST_LENGTH/2); | 426 | #ifndef GETPID_IS_MEANINGLESS |
306 | MD_Update(&m,(unsigned char *)&(md_count[0]),sizeof(md_count)); | 427 | if (curr_pid) /* just in the first iteration to save time */ |
428 | { | ||
429 | MD_Update(&m,(unsigned char*)&curr_pid,sizeof curr_pid); | ||
430 | curr_pid = 0; | ||
431 | } | ||
432 | #endif | ||
433 | MD_Update(&m,&(local_md[MD_DIGEST_LENGTH/2]),MD_DIGEST_LENGTH/2); | ||
434 | MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)); | ||
307 | #ifndef PURIFY | 435 | #ifndef PURIFY |
308 | MD_Update(&m,buf,j); /* purify complains */ | 436 | MD_Update(&m,buf,j); /* purify complains */ |
309 | #endif | 437 | #endif |
@@ -315,23 +443,57 @@ static void ssleay_rand_bytes(unsigned char *buf, int num) | |||
315 | } | 443 | } |
316 | else | 444 | else |
317 | MD_Update(&m,&(state[st_idx]),j); | 445 | MD_Update(&m,&(state[st_idx]),j); |
318 | MD_Final(md,&m); | 446 | MD_Final(local_md,&m); |
319 | 447 | ||
320 | for (i=0; i<j; i++) | 448 | for (i=0; i<j; i++) |
321 | { | 449 | { |
450 | state[st_idx++]^=local_md[i]; /* may compete with other threads */ | ||
451 | *(buf++)=local_md[i+MD_DIGEST_LENGTH/2]; | ||
322 | if (st_idx >= st_num) | 452 | if (st_idx >= st_num) |
323 | st_idx=0; | 453 | st_idx=0; |
324 | state[st_idx++]^=md[i]; | ||
325 | *(buf++)=md[i+MD_DIGEST_LENGTH/2]; | ||
326 | } | 454 | } |
327 | } | 455 | } |
328 | 456 | ||
329 | MD_Init(&m); | 457 | MD_Init(&m); |
330 | MD_Update(&m,(unsigned char *)&(md_count[0]),sizeof(md_count)); | 458 | MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)); |
331 | md_count[0]++; | 459 | MD_Update(&m,local_md,MD_DIGEST_LENGTH); |
460 | CRYPTO_w_lock(CRYPTO_LOCK_RAND); | ||
332 | MD_Update(&m,md,MD_DIGEST_LENGTH); | 461 | MD_Update(&m,md,MD_DIGEST_LENGTH); |
333 | MD_Final(md,&m); | 462 | MD_Final(md,&m); |
463 | CRYPTO_w_unlock(CRYPTO_LOCK_RAND); | ||
464 | |||
334 | memset(&m,0,sizeof(m)); | 465 | memset(&m,0,sizeof(m)); |
466 | if (ok) | ||
467 | return(1); | ||
468 | else | ||
469 | { | ||
470 | RANDerr(RAND_F_SSLEAY_RAND_BYTES,RAND_R_PRNG_NOT_SEEDED); | ||
471 | return(0); | ||
472 | } | ||
473 | } | ||
474 | |||
475 | /* pseudo-random bytes that are guaranteed to be unique but not | ||
476 | unpredictable */ | ||
477 | static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num) | ||
478 | { | ||
479 | int ret, err; | ||
480 | |||
481 | ret = RAND_bytes(buf, num); | ||
482 | if (ret == 0) | ||
483 | { | ||
484 | err = ERR_peek_error(); | ||
485 | if (ERR_GET_LIB(err) == ERR_LIB_RAND && | ||
486 | ERR_GET_REASON(err) == RAND_R_PRNG_NOT_SEEDED) | ||
487 | (void)ERR_get_error(); | ||
488 | } | ||
489 | return (ret); | ||
490 | } | ||
491 | |||
492 | int RAND_status(void) | ||
493 | { | ||
494 | if (!initialized) | ||
495 | ssleay_rand_initialize(); | ||
496 | return (entropy >= ENTROPY_NEEDED); | ||
335 | } | 497 | } |
336 | 498 | ||
337 | #ifdef WINDOWS | 499 | #ifdef WINDOWS |
@@ -358,12 +520,12 @@ static void ssleay_rand_bytes(unsigned char *buf, int num) | |||
358 | */ | 520 | */ |
359 | /* | 521 | /* |
360 | * I have modified the loading of bytes via RAND_seed() mechanism since | 522 | * I have modified the loading of bytes via RAND_seed() mechanism since |
361 | * the origional would have been very very CPU intensive since RAND_seed() | 523 | * the original would have been very very CPU intensive since RAND_seed() |
362 | * does an MD5 per 16 bytes of input. The cost to digest 16 bytes is the same | 524 | * does an MD5 per 16 bytes of input. The cost to digest 16 bytes is the same |
363 | * as that to digest 56 bytes. So under the old system, a screen of | 525 | * as that to digest 56 bytes. So under the old system, a screen of |
364 | * 1024*768*256 would have been CPU cost of approximatly 49,000 56 byte MD5 | 526 | * 1024*768*256 would have been CPU cost of approximately 49,000 56 byte MD5 |
365 | * digests or digesting 2.7 mbytes. What I have put in place would | 527 | * digests or digesting 2.7 mbytes. What I have put in place would |
366 | * be 48 16k MD5 digests, or efectivly 48*16+48 MD5 bytes or 816 kbytes | 528 | * be 48 16k MD5 digests, or effectively 48*16+48 MD5 bytes or 816 kbytes |
367 | * or about 3.5 times as much. | 529 | * or about 3.5 times as much. |
368 | * - eric | 530 | * - eric |
369 | */ | 531 | */ |