1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/ssl/libcrypto/src/crypto/rand/md_rand.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,630 @@
1.4 +/* crypto/rand/md_rand.c */
1.5 +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
1.6 + * All rights reserved.
1.7 + *
1.8 + * This package is an SSL implementation written
1.9 + * by Eric Young (eay@cryptsoft.com).
1.10 + * The implementation was written so as to conform with Netscapes SSL.
1.11 + *
1.12 + * This library is free for commercial and non-commercial use as long as
1.13 + * the following conditions are aheared to. The following conditions
1.14 + * apply to all code found in this distribution, be it the RC4, RSA,
1.15 + * lhash, DES, etc., code; not just the SSL code. The SSL documentation
1.16 + * included with this distribution is covered by the same copyright terms
1.17 + * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1.18 + *
1.19 + * Copyright remains Eric Young's, and as such any Copyright notices in
1.20 + * the code are not to be removed.
1.21 + * If this package is used in a product, Eric Young should be given attribution
1.22 + * as the author of the parts of the library used.
1.23 + * This can be in the form of a textual message at program startup or
1.24 + * in documentation (online or textual) provided with the package.
1.25 + *
1.26 + * Redistribution and use in source and binary forms, with or without
1.27 + * modification, are permitted provided that the following conditions
1.28 + * are met:
1.29 + * 1. Redistributions of source code must retain the copyright
1.30 + * notice, this list of conditions and the following disclaimer.
1.31 + * 2. Redistributions in binary form must reproduce the above copyright
1.32 + * notice, this list of conditions and the following disclaimer in the
1.33 + * documentation and/or other materials provided with the distribution.
1.34 + * 3. All advertising materials mentioning features or use of this software
1.35 + * must display the following acknowledgement:
1.36 + * "This product includes cryptographic software written by
1.37 + * Eric Young (eay@cryptsoft.com)"
1.38 + * The word 'cryptographic' can be left out if the rouines from the library
1.39 + * being used are not cryptographic related :-).
1.40 + * 4. If you include any Windows specific code (or a derivative thereof) from
1.41 + * the apps directory (application code) you must include an acknowledgement:
1.42 + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
1.43 + *
1.44 + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
1.45 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1.46 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1.47 + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1.48 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1.49 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1.50 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1.51 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1.52 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1.53 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1.54 + * SUCH DAMAGE.
1.55 + *
1.56 + * The licence and distribution terms for any publically available version or
1.57 + * derivative of this code cannot be changed. i.e. this code cannot simply be
1.58 + * copied and put under another distribution licence
1.59 + * [including the GNU Public Licence.]
1.60 + */
1.61 +/* ====================================================================
1.62 + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
1.63 + *
1.64 + * Redistribution and use in source and binary forms, with or without
1.65 + * modification, are permitted provided that the following conditions
1.66 + * are met:
1.67 + *
1.68 + * 1. Redistributions of source code must retain the above copyright
1.69 + * notice, this list of conditions and the following disclaimer.
1.70 + *
1.71 + * 2. Redistributions in binary form must reproduce the above copyright
1.72 + * notice, this list of conditions and the following disclaimer in
1.73 + * the documentation and/or other materials provided with the
1.74 + * distribution.
1.75 + *
1.76 + * 3. All advertising materials mentioning features or use of this
1.77 + * software must display the following acknowledgment:
1.78 + * "This product includes software developed by the OpenSSL Project
1.79 + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
1.80 + *
1.81 + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
1.82 + * endorse or promote products derived from this software without
1.83 + * prior written permission. For written permission, please contact
1.84 + * openssl-core@openssl.org.
1.85 + *
1.86 + * 5. Products derived from this software may not be called "OpenSSL"
1.87 + * nor may "OpenSSL" appear in their names without prior written
1.88 + * permission of the OpenSSL Project.
1.89 + *
1.90 + * 6. Redistributions of any form whatsoever must retain the following
1.91 + * acknowledgment:
1.92 + * "This product includes software developed by the OpenSSL Project
1.93 + * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
1.94 + *
1.95 + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
1.96 + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1.97 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1.98 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
1.99 + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1.100 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1.101 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1.102 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1.103 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
1.104 + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1.105 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
1.106 + * OF THE POSSIBILITY OF SUCH DAMAGE.
1.107 + * ====================================================================
1.108 + *
1.109 + * This product includes cryptographic software written by Eric Young
1.110 + * (eay@cryptsoft.com). This product includes software written by Tim
1.111 + * Hudson (tjh@cryptsoft.com).
1.112 + *
1.113 + */
1.114 + /*
1.115 + © Portions copyright (c) 2006 Nokia Corporation. All rights reserved.
1.116 + */
1.117 +
1.118 +
1.119 +#ifdef MD_RAND_DEBUG
1.120 +# ifndef NDEBUG
1.121 +# define NDEBUG
1.122 +# endif
1.123 +#endif
1.124 +
1.125 +#include <assert.h>
1.126 +#include <stdio.h>
1.127 +#include <string.h>
1.128 +
1.129 +#include "e_os.h"
1.130 +
1.131 +#include <openssl/rand.h>
1.132 +#include "rand_lcl.h"
1.133 +
1.134 +#include <openssl/crypto.h>
1.135 +#include <openssl/err.h>
1.136 +#if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
1.137 +#include "libcrypto_wsd_macros.h"
1.138 +#include "libcrypto_wsd.h"
1.139 +#endif
1.140 +
1.141 +
1.142 +#ifdef BN_DEBUG
1.143 +# define PREDICT
1.144 +#endif
1.145 +
1.146 +/* #define PREDICT 1 */
1.147 +
1.148 +#define STATE_SIZE 1023
1.149 +
1.150 +#ifndef EMULATOR
1.151 +static int state_num=0,state_index=0;
1.152 +static unsigned char state[STATE_SIZE+MD_DIGEST_LENGTH];
1.153 +static unsigned char md[MD_DIGEST_LENGTH];
1.154 +static long md_count[2]={0,0};
1.155 +static double entropy=0;
1.156 +static int initialized=0;
1.157 +
1.158 +static unsigned int crypto_lock_rand = 0; /* may be set only when a thread
1.159 + * holds CRYPTO_LOCK_RAND
1.160 + * (to prevent double locking) */
1.161 +/* access to lockin_thread is synchronized by CRYPTO_LOCK_RAND2 */
1.162 +static unsigned long locking_thread = 0; /* valid iff crypto_lock_rand is set */
1.163 +#else
1.164 +GET_STATIC_VAR_FROM_TLS(state_num,md_rand,int)
1.165 +#define state_num (*GET_WSD_VAR_NAME(state_num,md_rand, s)())
1.166 +
1.167 +GET_STATIC_VAR_FROM_TLS(state_index,md_rand,int)
1.168 +#define state_index (*GET_WSD_VAR_NAME(state_index,md_rand, s)())
1.169 +
1.170 +GET_STATIC_ARRAY_FROM_TLS(state,md_rand,unsigned char)
1.171 +#define state (GET_WSD_VAR_NAME(state,md_rand, s)())
1.172 +
1.173 +GET_STATIC_ARRAY_FROM_TLS(md,md_rand,unsigned char)
1.174 +#define md (GET_WSD_VAR_NAME(md,md_rand, s)())
1.175 +
1.176 +GET_STATIC_ARRAY_FROM_TLS(md_count,md_rand,unsigned char)
1.177 +#define md_count (GET_WSD_VAR_NAME(md_count,md_rand, s)())
1.178 +
1.179 +GET_STATIC_VAR_FROM_TLS(entropy,md_rand,double)
1.180 +#define entropy (*GET_WSD_VAR_NAME(entropy,md_rand, s)())
1.181 +
1.182 +GET_STATIC_VAR_FROM_TLS(initialized,md_rand,int)
1.183 +#define initialized (*GET_WSD_VAR_NAME(initialized,md_rand, s)())
1.184 +
1.185 +GET_STATIC_VAR_FROM_TLS(crypto_lock_rand,md_rand,unsigned int)
1.186 +#define crypto_lock_rand (*GET_WSD_VAR_NAME(crypto_lock_rand,md_rand, s)())
1.187 +
1.188 +GET_STATIC_VAR_FROM_TLS(locking_thread,md_rand,unsigned long)
1.189 +#define locking_thread (*GET_WSD_VAR_NAME(locking_thread,md_rand, s)())
1.190 +
1.191 +#endif
1.192 +
1.193 +#ifdef PREDICT
1.194 +int rand_predictable=0;
1.195 +#endif
1.196 +
1.197 +const char RAND_version[]="RAND" OPENSSL_VERSION_PTEXT;
1.198 +
1.199 +static void ssleay_rand_cleanup(void);
1.200 +static void ssleay_rand_seed(const void *buf, int num);
1.201 +static void ssleay_rand_add(const void *buf, int num, double add_entropy);
1.202 +static int ssleay_rand_bytes(unsigned char *buf, int num);
1.203 +static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num);
1.204 +static int ssleay_rand_status(void);
1.205 +
1.206 +#ifndef EMULATOR
1.207 +RAND_METHOD rand_ssleay_meth={
1.208 + ssleay_rand_seed,
1.209 + ssleay_rand_bytes,
1.210 + ssleay_rand_cleanup,
1.211 + ssleay_rand_add,
1.212 + ssleay_rand_pseudo_bytes,
1.213 + ssleay_rand_status
1.214 + };
1.215 +#else
1.216 +
1.217 +GET_GLOBAL_VAR_FROM_TLS(rand_ssleay_meth,md_rand, RAND_METHOD)
1.218 +#define rand_ssleay_meth (*GET_WSD_VAR_NAME(rand_ssleay_meth,md_rand, g)())
1.219 +const RAND_METHOD temp_g_rand_ssleay_meth={
1.220 + ssleay_rand_seed,
1.221 + ssleay_rand_bytes,
1.222 + ssleay_rand_cleanup,
1.223 + ssleay_rand_add,
1.224 + ssleay_rand_pseudo_bytes,
1.225 + ssleay_rand_status
1.226 + };
1.227 +
1.228 +#endif
1.229 +EXPORT_C RAND_METHOD *RAND_SSLeay(void)
1.230 + {
1.231 + return(&rand_ssleay_meth);
1.232 + }
1.233 +
1.234 +static void ssleay_rand_cleanup(void)
1.235 + {
1.236 + OPENSSL_cleanse(state,sizeof(state));
1.237 + state_num=0;
1.238 + state_index=0;
1.239 + OPENSSL_cleanse(md,MD_DIGEST_LENGTH);
1.240 + md_count[0]=0;
1.241 + md_count[1]=0;
1.242 + entropy=0;
1.243 + initialized=0;
1.244 + }
1.245 +
1.246 +static void ssleay_rand_add(const void *buf, int num, double add)
1.247 + {
1.248 + int i,j,k,st_idx;
1.249 + long md_c[2];
1.250 + unsigned char local_md[MD_DIGEST_LENGTH];
1.251 + EVP_MD_CTX m;
1.252 + int do_not_lock;
1.253 +
1.254 + /*
1.255 + * (Based on the rand(3) manpage)
1.256 + *
1.257 + * The input is chopped up into units of 20 bytes (or less for
1.258 + * the last block). Each of these blocks is run through the hash
1.259 + * function as follows: The data passed to the hash function
1.260 + * is the current 'md', the same number of bytes from the 'state'
1.261 + * (the location determined by in incremented looping index) as
1.262 + * the current 'block', the new key data 'block', and 'count'
1.263 + * (which is incremented after each use).
1.264 + * The result of this is kept in 'md' and also xored into the
1.265 + * 'state' at the same locations that were used as input into the
1.266 + * hash function.
1.267 + */
1.268 +
1.269 + /* check if we already have the lock */
1.270 + if (crypto_lock_rand)
1.271 + {
1.272 + CRYPTO_r_lock(CRYPTO_LOCK_RAND2);
1.273 + do_not_lock = (locking_thread == CRYPTO_thread_id());
1.274 + CRYPTO_r_unlock(CRYPTO_LOCK_RAND2);
1.275 + }
1.276 + else
1.277 + do_not_lock = 0;
1.278 +
1.279 + if (!do_not_lock) CRYPTO_w_lock(CRYPTO_LOCK_RAND);
1.280 + st_idx=state_index;
1.281 +
1.282 + /* use our own copies of the counters so that even
1.283 + * if a concurrent thread seeds with exactly the
1.284 + * same data and uses the same subarray there's _some_
1.285 + * difference */
1.286 + md_c[0] = md_count[0];
1.287 + md_c[1] = md_count[1];
1.288 +
1.289 + memcpy(local_md, md, sizeof md);
1.290 +
1.291 + /* state_index <= state_num <= STATE_SIZE */
1.292 + state_index += num;
1.293 + if (state_index >= STATE_SIZE)
1.294 + {
1.295 + state_index%=STATE_SIZE;
1.296 + state_num=STATE_SIZE;
1.297 + }
1.298 + else if (state_num < STATE_SIZE)
1.299 + {
1.300 + if (state_index > state_num)
1.301 + state_num=state_index;
1.302 + }
1.303 + /* state_index <= state_num <= STATE_SIZE */
1.304 +
1.305 + /* state[st_idx], ..., state[(st_idx + num - 1) % STATE_SIZE]
1.306 + * are what we will use now, but other threads may use them
1.307 + * as well */
1.308 +
1.309 + md_count[1] += (num / MD_DIGEST_LENGTH) + (num % MD_DIGEST_LENGTH > 0);
1.310 +
1.311 + if (!do_not_lock) CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
1.312 +
1.313 + EVP_MD_CTX_init(&m);
1.314 + for (i=0; i<num; i+=MD_DIGEST_LENGTH)
1.315 + {
1.316 + j=(num-i);
1.317 + j=(j > MD_DIGEST_LENGTH)?MD_DIGEST_LENGTH:j;
1.318 +
1.319 + MD_Init(&m);
1.320 + MD_Update(&m,local_md,MD_DIGEST_LENGTH);
1.321 + k=(st_idx+j)-STATE_SIZE;
1.322 + if (k > 0)
1.323 + {
1.324 + MD_Update(&m,&(state[st_idx]),j-k);
1.325 + MD_Update(&m,&(state[0]),k);
1.326 + }
1.327 + else
1.328 + MD_Update(&m,&(state[st_idx]),j);
1.329 +
1.330 + MD_Update(&m,buf,j);
1.331 + MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c));
1.332 + MD_Final(&m,local_md);
1.333 + md_c[1]++;
1.334 +
1.335 + buf=(const char *)buf + j;
1.336 +
1.337 + for (k=0; k<j; k++)
1.338 + {
1.339 + /* Parallel threads may interfere with this,
1.340 + * but always each byte of the new state is
1.341 + * the XOR of some previous value of its
1.342 + * and local_md (itermediate values may be lost).
1.343 + * Alway using locking could hurt performance more
1.344 + * than necessary given that conflicts occur only
1.345 + * when the total seeding is longer than the random
1.346 + * state. */
1.347 + state[st_idx++]^=local_md[k];
1.348 + if (st_idx >= STATE_SIZE)
1.349 + st_idx=0;
1.350 + }
1.351 + }
1.352 + EVP_MD_CTX_cleanup(&m);
1.353 +
1.354 + if (!do_not_lock) CRYPTO_w_lock(CRYPTO_LOCK_RAND);
1.355 + /* Don't just copy back local_md into md -- this could mean that
1.356 + * other thread's seeding remains without effect (except for
1.357 + * the incremented counter). By XORing it we keep at least as
1.358 + * much entropy as fits into md. */
1.359 + for (k = 0; k < (int)sizeof(md); k++)
1.360 + {
1.361 + md[k] ^= local_md[k];
1.362 + }
1.363 + if (entropy < ENTROPY_NEEDED) /* stop counting when we have enough */
1.364 + entropy += add;
1.365 + if (!do_not_lock) CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
1.366 +
1.367 +#if !defined(OPENSSL_THREADS) && !defined(OPENSSL_SYS_WIN32)
1.368 + assert(md_c[1] == md_count[1]);
1.369 +#endif
1.370 + }
1.371 +
1.372 +static void ssleay_rand_seed(const void *buf, int num)
1.373 + {
1.374 + ssleay_rand_add(buf, num, (double)num);
1.375 + }
1.376 +#ifdef EMULATOR
1.377 +GET_STATIC_VAR_FROM_TLS(stirred_pool,md_rand,volatile int)
1.378 +#define stirred_pool (*GET_WSD_VAR_NAME(stirred_pool,md_rand, s)())
1.379 +#endif
1.380 +static int ssleay_rand_bytes(unsigned char *buf, int num)
1.381 + {
1.382 +#ifndef EMULATOR
1.383 + static volatile int stirred_pool = 0;
1.384 +#endif
1.385 + int i,j,k,st_num,st_idx;
1.386 + int num_ceil;
1.387 + int ok;
1.388 + long md_c[2];
1.389 + unsigned char local_md[MD_DIGEST_LENGTH];
1.390 + EVP_MD_CTX m;
1.391 +#ifndef GETPID_IS_MEANINGLESS
1.392 + pid_t curr_pid = getpid();
1.393 +#endif
1.394 + int do_stir_pool = 0;
1.395 +
1.396 +#ifdef PREDICT
1.397 + if (rand_predictable)
1.398 + {
1.399 + static unsigned char val=0;
1.400 +
1.401 + for (i=0; i<num; i++)
1.402 + buf[i]=val++;
1.403 + return(1);
1.404 + }
1.405 +#endif
1.406 +
1.407 + if (num <= 0)
1.408 + return 1;
1.409 +
1.410 + EVP_MD_CTX_init(&m);
1.411 + /* round upwards to multiple of MD_DIGEST_LENGTH/2 */
1.412 + num_ceil = (1 + (num-1)/(MD_DIGEST_LENGTH/2)) * (MD_DIGEST_LENGTH/2);
1.413 +
1.414 + /*
1.415 + * (Based on the rand(3) manpage:)
1.416 + *
1.417 + * For each group of 10 bytes (or less), we do the following:
1.418 + *
1.419 + * Input into the hash function the local 'md' (which is initialized from
1.420 + * the global 'md' before any bytes are generated), the bytes that are to
1.421 + * be overwritten by the random bytes, and bytes from the 'state'
1.422 + * (incrementing looping index). From this digest output (which is kept
1.423 + * in 'md'), the top (up to) 10 bytes are returned to the caller and the
1.424 + * bottom 10 bytes are xored into the 'state'.
1.425 + *
1.426 + * Finally, after we have finished 'num' random bytes for the
1.427 + * caller, 'count' (which is incremented) and the local and global 'md'
1.428 + * are fed into the hash function and the results are kept in the
1.429 + * global 'md'.
1.430 + */
1.431 +
1.432 + CRYPTO_w_lock(CRYPTO_LOCK_RAND);
1.433 +
1.434 + /* prevent ssleay_rand_bytes() from trying to obtain the lock again */
1.435 + CRYPTO_w_lock(CRYPTO_LOCK_RAND2);
1.436 + locking_thread = CRYPTO_thread_id();
1.437 + CRYPTO_w_unlock(CRYPTO_LOCK_RAND2);
1.438 + crypto_lock_rand = 1;
1.439 +
1.440 + if (!initialized)
1.441 + {
1.442 + RAND_poll();
1.443 + initialized = 1;
1.444 + }
1.445 +
1.446 + if (!stirred_pool)
1.447 + do_stir_pool = 1;
1.448 +
1.449 + ok = (entropy >= ENTROPY_NEEDED);
1.450 + if (!ok)
1.451 + {
1.452 + /* If the PRNG state is not yet unpredictable, then seeing
1.453 + * the PRNG output may help attackers to determine the new
1.454 + * state; thus we have to decrease the entropy estimate.
1.455 + * Once we've had enough initial seeding we don't bother to
1.456 + * adjust the entropy count, though, because we're not ambitious
1.457 + * to provide *information-theoretic* randomness.
1.458 + *
1.459 + * NOTE: This approach fails if the program forks before
1.460 + * we have enough entropy. Entropy should be collected
1.461 + * in a separate input pool and be transferred to the
1.462 + * output pool only when the entropy limit has been reached.
1.463 + */
1.464 + entropy -= num;
1.465 + if (entropy < 0)
1.466 + entropy = 0;
1.467 + }
1.468 +
1.469 + if (do_stir_pool)
1.470 + {
1.471 + /* In the output function only half of 'md' remains secret,
1.472 + * so we better make sure that the required entropy gets
1.473 + * 'evenly distributed' through 'state', our randomness pool.
1.474 + * The input function (ssleay_rand_add) chains all of 'md',
1.475 + * which makes it more suitable for this purpose.
1.476 + */
1.477 +
1.478 + int n = STATE_SIZE; /* so that the complete pool gets accessed */
1.479 + while (n > 0)
1.480 + {
1.481 +#if MD_DIGEST_LENGTH > 20
1.482 +# error "Please adjust DUMMY_SEED."
1.483 +#endif
1.484 +#define DUMMY_SEED "...................." /* at least MD_DIGEST_LENGTH */
1.485 + /* Note that the seed does not matter, it's just that
1.486 + * ssleay_rand_add expects to have something to hash. */
1.487 + ssleay_rand_add(DUMMY_SEED, MD_DIGEST_LENGTH, 0.0);
1.488 + n -= MD_DIGEST_LENGTH;
1.489 + }
1.490 + if (ok)
1.491 + stirred_pool = 1;
1.492 + }
1.493 +
1.494 + st_idx=state_index;
1.495 + st_num=state_num;
1.496 + md_c[0] = md_count[0];
1.497 + md_c[1] = md_count[1];
1.498 + memcpy(local_md, md, sizeof md);
1.499 +
1.500 + state_index+=num_ceil;
1.501 + if (state_index > state_num)
1.502 + state_index %= state_num;
1.503 +
1.504 + /* state[st_idx], ..., state[(st_idx + num_ceil - 1) % st_num]
1.505 + * are now ours (but other threads may use them too) */
1.506 +
1.507 + md_count[0] += 1;
1.508 +
1.509 + /* before unlocking, we must clear 'crypto_lock_rand' */
1.510 + crypto_lock_rand = 0;
1.511 + CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
1.512 +
1.513 + while (num > 0)
1.514 + {
1.515 + /* num_ceil -= MD_DIGEST_LENGTH/2 */
1.516 + j=(num >= MD_DIGEST_LENGTH/2)?MD_DIGEST_LENGTH/2:num;
1.517 + num-=j;
1.518 + MD_Init(&m);
1.519 +#ifndef GETPID_IS_MEANINGLESS
1.520 + if (curr_pid) /* just in the first iteration to save time */
1.521 + {
1.522 + MD_Update(&m,(unsigned char*)&curr_pid,sizeof curr_pid);
1.523 + curr_pid = 0;
1.524 + }
1.525 +#endif
1.526 + MD_Update(&m,local_md,MD_DIGEST_LENGTH);
1.527 + MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c));
1.528 +#ifndef PURIFY
1.529 + MD_Update(&m,buf,j); /* purify complains */
1.530 +#endif
1.531 + k=(st_idx+MD_DIGEST_LENGTH/2)-st_num;
1.532 + if (k > 0)
1.533 + {
1.534 + MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2-k);
1.535 + MD_Update(&m,&(state[0]),k);
1.536 + }
1.537 + else
1.538 + MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2);
1.539 + MD_Final(&m,local_md);
1.540 +
1.541 + for (i=0; i<MD_DIGEST_LENGTH/2; i++)
1.542 + {
1.543 + state[st_idx++]^=local_md[i]; /* may compete with other threads */
1.544 + if (st_idx >= st_num)
1.545 + st_idx=0;
1.546 + if (i < j)
1.547 + *(buf++)=local_md[i+MD_DIGEST_LENGTH/2];
1.548 + }
1.549 + }
1.550 +
1.551 + MD_Init(&m);
1.552 + MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c));
1.553 + MD_Update(&m,local_md,MD_DIGEST_LENGTH);
1.554 + CRYPTO_w_lock(CRYPTO_LOCK_RAND);
1.555 + MD_Update(&m,md,MD_DIGEST_LENGTH);
1.556 + MD_Final(&m,md);
1.557 + CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
1.558 +
1.559 + EVP_MD_CTX_cleanup(&m);
1.560 + if (ok)
1.561 + return(1);
1.562 + else
1.563 + {
1.564 + RANDerr(RAND_F_SSLEAY_RAND_BYTES,RAND_R_PRNG_NOT_SEEDED);
1.565 + ERR_add_error_data(1, "You need to read the OpenSSL FAQ, "
1.566 + "http://www.openssl.org/support/faq.html");
1.567 + return(0);
1.568 + }
1.569 + }
1.570 +
1.571 +/* pseudo-random bytes that are guaranteed to be unique but not
1.572 + unpredictable */
1.573 +static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num)
1.574 + {
1.575 + int ret;
1.576 + unsigned long err;
1.577 +
1.578 + ret = RAND_bytes(buf, num);
1.579 + if (ret == 0)
1.580 + {
1.581 + err = ERR_peek_error();
1.582 + if (ERR_GET_LIB(err) == ERR_LIB_RAND &&
1.583 + ERR_GET_REASON(err) == RAND_R_PRNG_NOT_SEEDED)
1.584 + ERR_clear_error();
1.585 + }
1.586 + return (ret);
1.587 + }
1.588 +
1.589 +static int ssleay_rand_status(void)
1.590 + {
1.591 + int ret;
1.592 + int do_not_lock;
1.593 +
1.594 + /* check if we already have the lock
1.595 + * (could happen if a RAND_poll() implementation calls RAND_status()) */
1.596 + if (crypto_lock_rand)
1.597 + {
1.598 + CRYPTO_r_lock(CRYPTO_LOCK_RAND2);
1.599 + do_not_lock = (locking_thread == CRYPTO_thread_id());
1.600 + CRYPTO_r_unlock(CRYPTO_LOCK_RAND2);
1.601 + }
1.602 + else
1.603 + do_not_lock = 0;
1.604 +
1.605 + if (!do_not_lock)
1.606 + {
1.607 + CRYPTO_w_lock(CRYPTO_LOCK_RAND);
1.608 +
1.609 + /* prevent ssleay_rand_bytes() from trying to obtain the lock again */
1.610 + CRYPTO_w_lock(CRYPTO_LOCK_RAND2);
1.611 + locking_thread = CRYPTO_thread_id();
1.612 + CRYPTO_w_unlock(CRYPTO_LOCK_RAND2);
1.613 + crypto_lock_rand = 1;
1.614 + }
1.615 +
1.616 + if (!initialized)
1.617 + {
1.618 + RAND_poll();
1.619 + initialized = 1;
1.620 + }
1.621 +
1.622 + ret = entropy >= ENTROPY_NEEDED;
1.623 +
1.624 + if (!do_not_lock)
1.625 + {
1.626 + /* before unlocking, we must clear 'crypto_lock_rand' */
1.627 + crypto_lock_rand = 0;
1.628 +
1.629 + CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
1.630 + }
1.631 +
1.632 + return ret;
1.633 + }