md_rand.c 18.8 KB
Newer Older
1
/* crypto/rand/md_rand.c */
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
 * All rights reserved.
 *
 * This package is an SSL implementation written
 * by Eric Young (eay@cryptsoft.com).
 * The implementation was written so as to conform with Netscapes SSL.
 * 
 * This library is free for commercial and non-commercial use as long as
 * the following conditions are aheared to.  The following conditions
 * apply to all code found in this distribution, be it the RC4, RSA,
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 * included with this distribution is covered by the same copyright terms
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
 * 
 * Copyright remains Eric Young's, and as such any Copyright notices in
 * the code are not to be removed.
 * If this package is used in a product, Eric Young should be given attribution
 * as the author of the parts of the library used.
 * This can be in the form of a textual message at program startup or
 * in documentation (online or textual) provided with the package.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    "This product includes cryptographic software written by
 *     Eric Young (eay@cryptsoft.com)"
 *    The word 'cryptographic' can be left out if the rouines from the library
 *    being used are not cryptographic related :-).
 * 4. If you include any Windows specific code (or a derivative thereof) from 
 *    the apps directory (application code) you must include an acknowledgement:
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
 * 
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * 
 * The licence and distribution terms for any publically available version or
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 * copied and put under another distribution licence
 * [including the GNU Public Licence.]
 */
B
Bodo Möller 已提交
58
/* ====================================================================
B
Bodo Möller 已提交
59
 * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
B
Bodo Möller 已提交
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
 *
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    openssl-core@openssl.org.
 *
 * 5. Products derived from this software may not be called "OpenSSL"
 *    nor may "OpenSSL" appear in their names without prior written
 *    permission of the OpenSSL Project.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
 *
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 * This product includes cryptographic software written by Eric Young
 * (eay@cryptsoft.com).  This product includes software written by Tim
 * Hudson (tjh@cryptsoft.com).
 *
 */
111

112
#define OPENSSL_FIPSAPI
113

114
#ifdef MD_RAND_DEBUG
B
Bodo Möller 已提交
115 116 117 118 119 120
# ifndef NDEBUG
#   define NDEBUG
# endif
#endif

#include <assert.h>
121
#include <stdio.h>
B
Ben Laurie 已提交
122
#include <string.h>
123

124
#include "e_os.h"
125

126 127 128
#include <openssl/rand.h>
#include "rand_lcl.h"

129
#include <openssl/crypto.h>
130
#include <openssl/err.h>
131

132 133 134 135
#ifdef OPENSSL_FIPS
#include <openssl/fips.h>
#endif

136 137 138 139
#ifdef BN_DEBUG
# define PREDICT
#endif

140
/* #define PREDICT	1 */
141 142 143

#define STATE_SIZE	1023
static int state_num=0,state_index=0;
144
static unsigned char state[STATE_SIZE+MD_DIGEST_LENGTH];
145
static unsigned char md[MD_DIGEST_LENGTH];
146
static long md_count[2]={0,0};
147
static double entropy=0;
U
Ulf Möller 已提交
148
static int initialized=0;
149

B
Bodo Möller 已提交
150 151 152
static unsigned int crypto_lock_rand = 0; /* may be set only when a thread
                                           * holds CRYPTO_LOCK_RAND
                                           * (to prevent double locking) */
B
Bodo Möller 已提交
153
/* access to lockin_thread is synchronized by CRYPTO_LOCK_RAND2 */
154
static CRYPTO_THREADID locking_threadid; /* valid iff crypto_lock_rand is set */
B
Bodo Möller 已提交
155

156

157 158 159 160
#ifdef PREDICT
int rand_predictable=0;
#endif

161
const char RAND_version[]="RAND" OPENSSL_VERSION_PTEXT;
162

163
static void ssleay_rand_cleanup(void);
164 165
static int ssleay_rand_seed(const void *buf, int num);
static int ssleay_rand_add(const void *buf, int num, double add_entropy);
166 167
static int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo);
static int ssleay_rand_nopseudo_bytes(unsigned char *buf, int num);
168
static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num);
169
static int ssleay_rand_status(void);
170

171
RAND_METHOD rand_ssleay_meth={
172
	ssleay_rand_seed,
173
	ssleay_rand_nopseudo_bytes,
174
	ssleay_rand_cleanup,
175
	ssleay_rand_add,
176
	ssleay_rand_pseudo_bytes,
177
	ssleay_rand_status
178 179
	}; 

U
Ulf Möller 已提交
180
RAND_METHOD *RAND_SSLeay(void)
181
	{
182
	return(&rand_ssleay_meth);
183 184
	}

U
Ulf Möller 已提交
185
static void ssleay_rand_cleanup(void)
186
	{
187
	OPENSSL_cleanse(state,sizeof(state));
188 189
	state_num=0;
	state_index=0;
190
	OPENSSL_cleanse(md,MD_DIGEST_LENGTH);
191 192
	md_count[0]=0;
	md_count[1]=0;
193
	entropy=0;
194
	initialized=0;
195 196
	}

197
static int ssleay_rand_add(const void *buf, int num, double add)
198
	{
199
	int i,j,k,st_idx;
B
Bodo Möller 已提交
200 201
	long md_c[2];
	unsigned char local_md[MD_DIGEST_LENGTH];
202
	EVP_MD_CTX m;
B
Bodo Möller 已提交
203
	int do_not_lock;
204
	int rv = 0;
205

B
Bodo Möller 已提交
206
	/*
U
Ulf Möller 已提交
207
	 * (Based on the rand(3) manpage)
B
Bodo Möller 已提交
208
	 *
209
	 * The input is chopped up into units of 20 bytes (or less for
U
Ulf Möller 已提交
210
	 * the last block).  Each of these blocks is run through the hash
211
	 * function as follows:  The data passed to the hash function
B
Bodo Möller 已提交
212 213 214 215 216
	 * is the current 'md', the same number of bytes from the 'state'
	 * (the location determined by in incremented looping index) as
	 * the current 'block', the new key data 'block', and 'count'
	 * (which is incremented after each use).
	 * The result of this is kept in 'md' and also xored into the
U
Ulf Möller 已提交
217 218
	 * 'state' at the same locations that were used as input into the
         * hash function.
B
Bodo Möller 已提交
219 220
	 */

221
	EVP_MD_CTX_init(&m);
B
Bodo Möller 已提交
222
	/* check if we already have the lock */
B
Bodo Möller 已提交
223 224
	if (crypto_lock_rand)
		{
225 226
		CRYPTO_THREADID cur;
		CRYPTO_THREADID_current(&cur);
B
Bodo Möller 已提交
227
		CRYPTO_r_lock(CRYPTO_LOCK_RAND2);
228
		do_not_lock = !CRYPTO_THREADID_cmp(&locking_threadid, &cur);
B
Bodo Möller 已提交
229 230 231 232
		CRYPTO_r_unlock(CRYPTO_LOCK_RAND2);
		}
	else
		do_not_lock = 0;
B
Bodo Möller 已提交
233 234

	if (!do_not_lock) CRYPTO_w_lock(CRYPTO_LOCK_RAND);
235 236
	st_idx=state_index;

B
Bodo Möller 已提交
237 238 239 240 241 242 243 244 245 246 247
	/* 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 _some_
	 * difference */
	md_c[0] = md_count[0];
	md_c[1] = md_count[1];

	memcpy(local_md, md, sizeof md);

	/* state_index <= state_num <= STATE_SIZE */
	state_index += num;
248
	if (state_index >= STATE_SIZE)
249 250 251 252 253 254 255 256 257
		{
		state_index%=STATE_SIZE;
		state_num=STATE_SIZE;
		}
	else if (state_num < STATE_SIZE)	
		{
		if (state_index > state_num)
			state_num=state_index;
		}
B
Bodo Möller 已提交
258 259 260 261 262 263 264 265
	/* state_index <= state_num <= STATE_SIZE */

	/* state[st_idx], ..., state[(st_idx + num - 1) % STATE_SIZE]
	 * are what we will use now, but other threads may use them
	 * as well */

	md_count[1] += (num / MD_DIGEST_LENGTH) + (num % MD_DIGEST_LENGTH > 0);

B
Bodo Möller 已提交
266
	if (!do_not_lock) CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
267 268 269 270 271 272

	for (i=0; i<num; i+=MD_DIGEST_LENGTH)
		{
		j=(num-i);
		j=(j > MD_DIGEST_LENGTH)?MD_DIGEST_LENGTH:j;

273 274 275 276
		if (!MD_Init(&m))
			goto err;
		if (!MD_Update(&m,local_md,MD_DIGEST_LENGTH))
			goto err;
277 278 279
		k=(st_idx+j)-STATE_SIZE;
		if (k > 0)
			{
280 281 282 283
			if (!MD_Update(&m,&(state[st_idx]),j-k))
				goto err;
			if (!MD_Update(&m,&(state[0]),k))
				goto err;
284 285
			}
		else
286 287
			if (!MD_Update(&m,&(state[st_idx]),j))
				goto err;
R
Richard Levitte 已提交
288 289

		/* DO NOT REMOVE THE FOLLOWING CALL TO MD_Update()! */
290 291
		if (!MD_Update(&m,buf,j))
			goto err;
R
Richard Levitte 已提交
292 293 294 295 296 297 298
		/* We know that line may cause programs such as
		   purify and valgrind to complain about use of
		   uninitialized data.  The problem is not, it's
		   with the caller.  Removing that line will make
		   sure you get really bad randomness and thereby
		   other problems such as very insecure keys. */

299 300 301 302
		if (!MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)))
			goto err;
		if (!MD_Final(&m,local_md))
			goto err;
B
Bodo Möller 已提交
303
		md_c[1]++;
304

B
Ben Laurie 已提交
305
		buf=(const char *)buf + j;
306 307 308

		for (k=0; k<j; k++)
			{
B
Bodo Möller 已提交
309 310 311 312 313 314 315 316 317
			/* 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];
318 319 320 321
			if (st_idx >= STATE_SIZE)
				st_idx=0;
			}
		}
B
Bodo Möller 已提交
322

B
Bodo Möller 已提交
323
	if (!do_not_lock) CRYPTO_w_lock(CRYPTO_LOCK_RAND);
B
Bodo Möller 已提交
324 325 326 327
	/* 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. */
328
	for (k = 0; k < (int)sizeof(md); k++)
B
Bodo Möller 已提交
329 330 331
		{
		md[k] ^= local_md[k];
		}
B
Bodo Möller 已提交
332 333
	if (entropy < ENTROPY_NEEDED) /* stop counting when we have enough */
	    entropy += add;
B
Bodo Möller 已提交
334
	if (!do_not_lock) CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
B
Bodo Möller 已提交
335
	
336
#if !defined(OPENSSL_THREADS) && !defined(OPENSSL_SYS_WIN32)
B
Bodo Möller 已提交
337 338
	assert(md_c[1] == md_count[1]);
#endif
339 340 341 342
	rv = 1;
	err:
	EVP_MD_CTX_cleanup(&m);
	return rv;
343 344
	}

345
static int ssleay_rand_seed(const void *buf, int num)
346
	{
347
	return ssleay_rand_add(buf, num, (double)num);
348 349
	}

350
static int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo)
351
	{
B
Bodo Möller 已提交
352
	static volatile int stirred_pool = 0;
353
	int i,j,k,st_num,st_idx;
B
Bodo Möller 已提交
354
	int num_ceil;
355
	int ok;
B
Bodo Möller 已提交
356 357
	long md_c[2];
	unsigned char local_md[MD_DIGEST_LENGTH];
358
	EVP_MD_CTX m;
A
Andy Polyakov 已提交
359
#ifndef GETPID_IS_MEANINGLESS
360
	pid_t curr_pid = getpid();
B
Bodo Möller 已提交
361
#endif
B
Bodo Möller 已提交
362
	int do_stir_pool = 0;
363 364

#ifdef PREDICT
365 366 367
	if (rand_predictable)
		{
		static unsigned char val=0;
368

369 370 371 372
		for (i=0; i<num; i++)
			buf[i]=val++;
		return(1);
		}
373 374
#endif

B
Bodo Möller 已提交
375 376
	if (num <= 0)
		return 1;
377 378

	EVP_MD_CTX_init(&m);
B
Bodo Möller 已提交
379 380 381
	/* round upwards to multiple of MD_DIGEST_LENGTH/2 */
	num_ceil = (1 + (num-1)/(MD_DIGEST_LENGTH/2)) * (MD_DIGEST_LENGTH/2);

B
Bodo Möller 已提交
382
	/*
B
Bodo Möller 已提交
383
	 * (Based on the rand(3) manpage:)
B
Bodo Möller 已提交
384
	 *
385
	 * For each group of 10 bytes (or less), we do the following:
B
Bodo Möller 已提交
386
	 *
B
Bodo Möller 已提交
387 388 389 390 391 392 393
	 * Input into the hash function 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 10 bytes are xored into the 'state'.
	 * 
B
Bodo Möller 已提交
394
	 * Finally, after we have finished 'num' random bytes for the
B
Bodo Möller 已提交
395 396 397
	 * 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'.
B
Bodo Möller 已提交
398 399
	 */

400
	CRYPTO_w_lock(CRYPTO_LOCK_RAND);
401

B
Bodo Möller 已提交
402
	/* prevent ssleay_rand_bytes() from trying to obtain the lock again */
B
Bodo Möller 已提交
403
	CRYPTO_w_lock(CRYPTO_LOCK_RAND2);
404
	CRYPTO_THREADID_current(&locking_threadid);
B
Bodo Möller 已提交
405
	CRYPTO_w_unlock(CRYPTO_LOCK_RAND2);
B
Bodo Möller 已提交
406
	crypto_lock_rand = 1;
B
Bodo Möller 已提交
407 408 409 410 411 412 413

	if (!initialized)
		{
		RAND_poll();
		initialized = 1;
		}
	
B
Bodo Möller 已提交
414 415 416
	if (!stirred_pool)
		do_stir_pool = 1;
	
417
	ok = (entropy >= ENTROPY_NEEDED);
B
Bodo Möller 已提交
418 419 420 421 422 423 424 425
	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.
B
Bodo Möller 已提交
426 427 428 429 430
		 *
		 * 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.
B
Bodo Möller 已提交
431 432 433 434 435
		 */
		entropy -= num;
		if (entropy < 0)
			entropy = 0;
		}
436

B
Bodo Möller 已提交
437 438
	if (do_stir_pool)
		{
B
Bodo Möller 已提交
439 440 441 442 443
		/* In the output function only half of 'md' remains secret,
		 * 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.
B
Bodo Möller 已提交
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
		 */

		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;
		}

462 463
	st_idx=state_index;
	st_num=state_num;
B
Bodo Möller 已提交
464 465 466 467
	md_c[0] = md_count[0];
	md_c[1] = md_count[1];
	memcpy(local_md, md, sizeof md);

B
Bodo Möller 已提交
468
	state_index+=num_ceil;
469
	if (state_index > state_num)
B
Bodo Möller 已提交
470 471
		state_index %= state_num;

B
Bodo Möller 已提交
472
	/* state[st_idx], ..., state[(st_idx + num_ceil - 1) % st_num]
B
Bodo Möller 已提交
473
	 * are now ours (but other threads may use them too) */
474

B
Bodo Möller 已提交
475
	md_count[0] += 1;
476

B
Bodo Möller 已提交
477 478
	/* before unlocking, we must clear 'crypto_lock_rand' */
	crypto_lock_rand = 0;
479 480 481 482
	CRYPTO_w_unlock(CRYPTO_LOCK_RAND);

	while (num > 0)
		{
B
Bodo Möller 已提交
483
		/* num_ceil -= MD_DIGEST_LENGTH/2 */
484 485
		j=(num >= MD_DIGEST_LENGTH/2)?MD_DIGEST_LENGTH/2:num;
		num-=j;
486 487
		if (!MD_Init(&m))
			goto err;
A
Andy Polyakov 已提交
488
#ifndef GETPID_IS_MEANINGLESS
489 490
		if (curr_pid) /* just in the first iteration to save time */
			{
491 492
			if (!MD_Update(&m,(unsigned char*)&curr_pid,sizeof curr_pid))
				goto err;
493 494 495
			curr_pid = 0;
			}
#endif
496 497 498 499
		if (!MD_Update(&m,local_md,MD_DIGEST_LENGTH))
			goto err;
		if (!MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)))
			goto err;
R
Richard Levitte 已提交
500 501

#ifndef PURIFY /* purify complains */
D
Dr. Stephen Henson 已提交
502 503 504 505 506 507 508
		/* The following line uses the supplied buffer as a small
		 * source of entropy: since this buffer is often uninitialised
		 * it may cause programs such as purify or valgrind to
		 * complain. So for those builds it is not used: the removal
		 * of such a small source of entropy has negligible impact on
		 * security.
		 */
509 510
		if (!MD_Update(&m,buf,j))
			goto err;
511
#endif
R
Richard Levitte 已提交
512

B
Bodo Möller 已提交
513
		k=(st_idx+MD_DIGEST_LENGTH/2)-st_num;
514 515
		if (k > 0)
			{
516 517 518 519
			if (!MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2-k))
				goto err;
			if (!MD_Update(&m,&(state[0]),k))
				goto err;
520 521
			}
		else
522 523 524 525
			if (!MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2))
				goto err;
		if (!MD_Final(&m,local_md))
			goto err;
526

B
Bodo Möller 已提交
527
		for (i=0; i<MD_DIGEST_LENGTH/2; i++)
528
			{
B
Bodo Möller 已提交
529
			state[st_idx++]^=local_md[i]; /* may compete with other threads */
530 531
			if (st_idx >= st_num)
				st_idx=0;
B
Bodo Möller 已提交
532 533
			if (i < j)
				*(buf++)=local_md[i+MD_DIGEST_LENGTH/2];
534 535 536
			}
		}

537 538 539 540
	if (!MD_Init(&m)
		|| !MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c))
		|| !MD_Update(&m,local_md,MD_DIGEST_LENGTH))
		goto err;
B
Bodo Möller 已提交
541
	CRYPTO_w_lock(CRYPTO_LOCK_RAND);
542 543 544 545 546
	if (!MD_Update(&m,md,MD_DIGEST_LENGTH) || !MD_Final(&m,md))
		{
		CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
		goto err;
		}
B
Bodo Möller 已提交
547 548
	CRYPTO_w_unlock(CRYPTO_LOCK_RAND);

549
	EVP_MD_CTX_cleanup(&m);
550 551
	if (ok)
		return(1);
552 553 554
	else if (pseudo)
		return 0;
	else 
555 556
		{
		RANDerr(RAND_F_SSLEAY_RAND_BYTES,RAND_R_PRNG_NOT_SEEDED);
557 558
		ERR_add_error_data(1, "You need to read the OpenSSL FAQ, "
			"http://www.openssl.org/support/faq.html");
559 560
		return(0);
		}
561 562 563 564 565
	err:
	EVP_MD_CTX_cleanup(&m);
	RANDerr(RAND_F_SSLEAY_RAND_BYTES,ERR_R_EVP_LIB);
	return 0;

566 567
	}

568 569 570 571 572
static int ssleay_rand_nopseudo_bytes(unsigned char *buf, int num)
	{
	return ssleay_rand_bytes(buf, num, 0);
	}

573 574
/* pseudo-random bytes that are guaranteed to be unique but not
   unpredictable */
575
static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num) 
576
	{
577
	return ssleay_rand_bytes(buf, num, 1);
578 579
	}

580
static int ssleay_rand_status(void)
U
Ulf Möller 已提交
581
	{
582
	CRYPTO_THREADID cur;
583
	int ret;
B
Bodo Möller 已提交
584
	int do_not_lock;
585

586
	CRYPTO_THREADID_current(&cur);
B
Bodo Möller 已提交
587 588
	/* check if we already have the lock
	 * (could happen if a RAND_poll() implementation calls RAND_status()) */
B
Bodo Möller 已提交
589 590 591
	if (crypto_lock_rand)
		{
		CRYPTO_r_lock(CRYPTO_LOCK_RAND2);
592
		do_not_lock = !CRYPTO_THREADID_cmp(&locking_threadid, &cur);
B
Bodo Möller 已提交
593 594 595 596
		CRYPTO_r_unlock(CRYPTO_LOCK_RAND2);
		}
	else
		do_not_lock = 0;
B
Bodo Möller 已提交
597 598 599 600 601 602
	
	if (!do_not_lock)
		{
		CRYPTO_w_lock(CRYPTO_LOCK_RAND);
		
		/* prevent ssleay_rand_bytes() from trying to obtain the lock again */
B
Bodo Möller 已提交
603
		CRYPTO_w_lock(CRYPTO_LOCK_RAND2);
604
		CRYPTO_THREADID_cpy(&locking_threadid, &cur);
B
Bodo Möller 已提交
605
		CRYPTO_w_unlock(CRYPTO_LOCK_RAND2);
B
Bodo Möller 已提交
606
		crypto_lock_rand = 1;
B
Bodo Möller 已提交
607 608
		}
	
U
Ulf Möller 已提交
609
	if (!initialized)
B
Bodo Möller 已提交
610
		{
611
		RAND_poll();
B
Bodo Möller 已提交
612 613
		initialized = 1;
		}
614

615
	ret = entropy >= ENTROPY_NEEDED;
616

B
Bodo Möller 已提交
617 618 619 620 621 622 623 624
	if (!do_not_lock)
		{
		/* before unlocking, we must clear 'crypto_lock_rand' */
		crypto_lock_rand = 0;
		
		CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
		}
	
625
	return ret;
U
Ulf Möller 已提交
626
	}