コード例 #1
0
ファイル: util.cpp プロジェクト: semyazza/bitcoin
void RandAddSeedPerfmon()
{
    RandAddSeed();

    // This can take up to 2 seconds, so only do it every 10 minutes
    static int64 nLastPerfmon;
    if (GetTime() < nLastPerfmon + 10 * 60)
        return;
    nLastPerfmon = GetTime();

#ifdef __WXMSW__
    // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
    // Seed with the entire set of perfmon data
    unsigned char pdata[250000];
    memset(pdata, 0, sizeof(pdata));
    unsigned long nSize = sizeof(pdata);
    long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize);
    RegCloseKey(HKEY_PERFORMANCE_DATA);
    if (ret == ERROR_SUCCESS)
    {
        RAND_add(pdata, nSize, nSize/100.0);
        memset(pdata, 0, nSize);
        printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M", GetTime()).c_str(), nSize);
    }
#endif
}
コード例 #2
0
ファイル: util.cpp プロジェクト: semyazza/bitcoin
void RandAddSeed()
{
    // Seed with CPU performance counter
    int64 nCounter = GetPerformanceCounter();
    RAND_add(&nCounter, sizeof(nCounter), 1.5);
    memset(&nCounter, 0, sizeof(nCounter));
}
int RAND_poll(void)
{
	unsigned long l;
#ifdef HAVE_GETPID	
	pid_t curr_pid = getpid();
#endif
#ifdef DEVRANDOM
	FILE *fh;
#endif

#ifdef DEVRANDOM
	/* Use a random entropy pool device. Linux, FreeBSD and OpenBSD
	 * have this. Use /dev/urandom if you can as /dev/random may block
	 * if it runs out of random entries.  */

	if ((fh = fopen(DEVRANDOM, "r")) != NULL)
		{
		unsigned char tmpbuf[ENTROPY_NEEDED];
		int n;
		
		setvbuf(fh, NULL, _IONBF, 0);
		n=fread((unsigned char *)tmpbuf,1,ENTROPY_NEEDED,fh);
		fclose(fh);
		RAND_add(tmpbuf,sizeof tmpbuf,n);
		memset(tmpbuf,0,n);
		}
#endif

	/* put in some default random data, we need more than just this */
#ifdef HAVE_GETPID
	l=curr_pid;
	RAND_add(&l,sizeof(l),0);
#endif
#ifdef HAVE_GETUID
	l=getuid();
	RAND_add(&l,sizeof(l),0);
#endif

	l=time(NULL);
	RAND_add(&l,sizeof(l),0);

#ifdef DEVRANDOM
	return 1;
#else
	return 0;
#endif
}
コード例 #4
0
ファイル: crypto-rand.c プロジェクト: Sp1l/heimdal
static int
seed_something(void)
{
#ifndef NO_RANDFILE
    char buf[1024], seedfile[256];

    /* If there is a seed file, load it. But such a file cannot be trusted,
       so use 0 for the entropy estimate */
    if (RAND_file_name(seedfile, sizeof(seedfile))) {
	int fd;
	fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC);
	if (fd >= 0) {
	    ssize_t ret;
	    rk_cloexec(fd);
	    ret = read(fd, buf, sizeof(buf));
	    if (ret > 0)
		RAND_add(buf, ret, 0.0);
	    close(fd);
	} else
	    seedfile[0] = '\0';
    } else
	seedfile[0] = '\0';
#endif

    /* Calling RAND_status() will try to use /dev/urandom if it exists so
       we do not have to deal with it. */
    if (RAND_status() != 1) {
#if defined(HAVE_RAND_EGD)
	krb5_context context;
	const char *p;

#ifndef OPENSSL_NO_EGD
	/* Try using egd */
	if (!krb5_init_context(&context)) {
	    p = krb5_config_get_string(context, NULL, "libdefaults",
				       "egd_socket", NULL);
	    if (p != NULL)
		RAND_egd_bytes(p, ENTROPY_NEEDED);
	    krb5_free_context(context);
	}
#endif

#else
	/* TODO: Once a Windows CryptoAPI RAND method is defined, we
	   can use that and failover to another method. */
#endif
    }

    if (RAND_status() == 1)	{
#ifndef NO_RANDFILE
	/* Update the seed file */
	if (seedfile[0])
	    RAND_write_file(seedfile);
#endif

	return 0;
    } else
	return -1;
}
コード例 #5
0
ファイル: ossl_rand.c プロジェクト: AdamDotCom/my-rvm
/*
 *  call-seq:
 *     add(str, entropy) -> self
 *
 */
static VALUE
ossl_rand_add(VALUE self, VALUE str, VALUE entropy)
{
    StringValue(str);
    RAND_add(RSTRING_PTR(str), RSTRING_LEN(str), NUM2DBL(entropy));

    return self;
}
コード例 #6
0
ファイル: lcrypto.c プロジェクト: dtiedy/luaplus51-all
static int rand_add(lua_State *L)
{
  size_t num;
  const void *buf = luaL_checklstring(L, 1, &num);
  double entropy = luaL_optnumber(L, 2, num);
  RAND_add(buf, (int)num, entropy);
  return 0;
}
コード例 #7
0
int RAND_poll(void)
	{
	unsigned long Time=(unsigned long)TINYCLR_SSL_TIME(NULL);

	RAND_add(&Time,sizeof(Time),ENTROPY_NEEDED);

	return 1;
	}
コード例 #8
0
ファイル: rand_win.c プロジェクト: 2007750219/openssl
int RAND_poll(void)
{
    MEMORYSTATUS mst;
# ifndef RAND_WINDOWS_USE_BCRYPT
    HCRYPTPROV hProvider;
# endif
    DWORD w;
    BYTE buf[64];

# ifdef RAND_WINDOWS_USE_BCRYPT
    if (BCryptGenRandom(NULL, buf, (ULONG)sizeof(buf), BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS) {
        RAND_add(buf, sizeof(buf), sizeof(buf));
    }
# else
    /* poll the CryptoAPI PRNG */
    /* The CryptoAPI returns sizeof(buf) bytes of randomness */
    if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
        if (CryptGenRandom(hProvider, (DWORD)sizeof(buf), buf) != 0) {
            RAND_add(buf, sizeof(buf), sizeof(buf));
        }
        CryptReleaseContext(hProvider, 0);
    }

    /* poll the Pentium PRG with CryptoAPI */
    if (CryptAcquireContextW(&hProvider, NULL, INTEL_DEF_PROV, PROV_INTEL_SEC, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
        if (CryptGenRandom(hProvider, (DWORD)sizeof(buf), buf) != 0) {
            RAND_add(buf, sizeof(buf), sizeof(buf));
        }
        CryptReleaseContext(hProvider, 0);
    }
# endif

    /* timer data */
    readtimer();

    /* memory usage statistics */
    GlobalMemoryStatus(&mst);
    RAND_add(&mst, sizeof(mst), 1);

    /* process ID */
    w = GetCurrentProcessId();
    RAND_add(&w, sizeof(w), 1);

    return (1);
}
コード例 #9
0
ファイル: openssl.c プロジェクト: Epictetus/postgres
int
px_add_entropy(const uint8 *data, unsigned count)
{
	/*
	 * estimate 0 bits
	 */
	RAND_add(data, count, 0);
	return 0;
}
コード例 #10
0
ファイル: openssl.c プロジェクト: zhaozg/lua-openssl
/***
mixes the num bytes at buf into the PRNG state.
@function rand_add
@tparam string seed data to seed random generator
@tparam number entropy the lower bound of an estimate of how much randomness is contained in buf, measured in bytes.
*/
static int openssl_random_add(lua_State*L)
{
  size_t num = 0;
  const void *buf = luaL_checklstring(L, 1, &num);
  double entropy = luaL_optinteger(L, 2, num);

  RAND_add(buf, num, entropy);
  return 0;
}
コード例 #11
0
ファイル: rand_nw.c プロジェクト: DarovskikhAndrei/openssl
   /*
    * the FAQ indicates we need to provide at least 20 bytes (160 bits) of
    * seed
    */
int RAND_poll(void)
{
    unsigned long l;
    unsigned long tsc;
    int i;

    /*
     * There are several options to gather miscellaneous data but for now we
     * will loop checking the time stamp counter (rdtsc) and the
     * SuperHighResolutionTimer.  Each iteration will collect 8 bytes of data
     * but it is treated as only 1 byte of entropy.  The call to
     * ThreadSwitchWithDelay() will introduce additional variability into the
     * data returned by rdtsc. Applications can argument the seed material
     * by adding additional stuff with RAND_add() and should probably do so.
     */
    l = GetProcessSwitchCount();
    RAND_add(&l, sizeof(l), 1);

    /* need to cast the void* to unsigned long here */
    l = (unsigned long)RunningProcess;
    RAND_add(&l, sizeof(l), 1);

    for (i = 2; i < ENTROPY_NEEDED; i++) {
# ifdef __MWERKS__
        asm {
        rdtsc mov tsc, eax}
# elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
        asm volatile ("rdtsc":"=a" (tsc)::"edx");
# endif

        RAND_add(&tsc, sizeof(tsc), 1);

        l = GetSuperHighResolutionTimer();
        RAND_add(&l, sizeof(l), 0);

# if defined(NETWARE_LIBC)
        NXThreadYield();
# else                          /* NETWARE_CLIB */
        ThreadSwitchWithDelay();
# endif
    }

    return 1;
}
コード例 #12
0
ファイル: rand_vms.c プロジェクト: 1564143452/kbengine
int RAND_poll(void)
{
    long pid, iosb[2];
    int status = 0;
    struct {
        short length, code;
        long *buffer;
        int *retlen;
    } item[32], *pitem;
    unsigned char data_buffer[256];
    short total_length = 0;
    struct items_data_st *pitems_data;

    pitems_data = items_data;
    pitem = item;

    /* Setup */
    while (pitems_data->length && (total_length + pitems_data->length <= 256)) {
        pitem->length = pitems_data->length;
        pitem->code = pitems_data->code;
        pitem->buffer = (long *)&data_buffer[total_length];
        pitem->retlen = 0;
        total_length += pitems_data->length;
        pitems_data++;
        pitem ++;
    }
    pitem->length = pitem->code = 0;

    /*
     * Scan through all the processes in the system and add entropy with
     * results from the processes that were possible to look at.
     * However, view the information as only half trustable.
     */
    pid = -1;                   /* search context */
    while ((status = sys$getjpiw(0, &pid, 0, item, iosb, 0, 0))
           != SS$_NOMOREPROC) {
        if (status == SS$_NORMAL) {
            RAND_add((PTR_T) data_buffer, total_length, total_length / 2);
        }
    }
    sys$gettim(iosb);
    RAND_add((PTR_T) iosb, sizeof(iosb), sizeof(iosb) / 2);
    return 1;
}
コード例 #13
0
ファイル: drbgtest.c プロジェクト: lookfun/openssl
static int test_rand_add(void)
{
    char *p;

    if (!TEST_ptr(p = malloc(RAND_ADD_SIZE)))
        return 0;
    RAND_add(p, RAND_ADD_SIZE, RAND_ADD_SIZE);
    free(p);
    return 1;
}
コード例 #14
0
ファイル: crypto_openssl.c プロジェクト: akrav/sqlcipher
static int sqlcipher_openssl_add_random(void *ctx, void *buffer, int length) {
#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
  sqlite3_mutex_enter(openssl_rand_mutex);
#endif
  RAND_add(buffer, length, 0);
#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
  sqlite3_mutex_leave(openssl_rand_mutex);
#endif
  return SQLITE_OK;
}
コード例 #15
0
ファイル: randfile.c プロジェクト: ahenroid/ptptl-0.2
int RAND_load_file(const char *file, long bytes)
	{
	/* If bytes >= 0, read up to 'bytes' bytes.
	 * if bytes == -1, read complete file. */

	MS_STATIC unsigned char buf[BUFSIZE];
	struct stat sb;
	int i,ret=0,n;
	FILE *in;

	if (file == NULL) return(0);

	i=stat(file,&sb);
	/* If the state fails, put some crap in anyway */
	RAND_add(&sb,sizeof(sb),0);
	if (i < 0) return(0);
	if (bytes == 0) return(ret);

	in=fopen(file,"rb");
	if (in == NULL) goto err;
	for (;;)
		{
		if (bytes > 0)
			n = (bytes < BUFSIZE)?(int)bytes:BUFSIZE;
		else
			n = BUFSIZE;
		i=fread(buf,1,n,in);
		if (i <= 0) break;
		/* even if n != i, use the full array */
		RAND_add(buf,n,i);
		ret+=i;
		if (bytes > 0)
			{
			bytes-=n;
			if (bytes == 0) break;
			}
		}
	fclose(in);
	memset(buf,0,BUFSIZE);
err:
	return(ret);
	}
コード例 #16
0
ファイル: csprng.cpp プロジェクト: Empresaria/rippled
void
csprng_engine::mix (
    void* data, std::size_t size, double bitsPerByte)
{
    assert (data != nullptr);
    assert (size != 0);
    assert (bitsPerByte != 0);

    std::lock_guard<std::mutex> lock (mutex_);
    RAND_add (data, size, (size * bitsPerByte) / 8.0);
}
コード例 #17
0
ファイル: entropy.cpp プロジェクト: lodyagin/shiesh
void
rexec_recv_rng_seed(Buffer *m)
{
	u_char *buf;
	u_int len;

	buf = buffer_get_string_ret(m, &len);
	if (buf != NULL) {
		debug3("rexec_recv_rng_seed: seeding rng with %u bytes", len);
		RAND_add(buf, len, len);
	}
}
コード例 #18
0
unsigned char * get_random_bytes(size_t len) {
	char timeseed[32];
    time_t now = time(NULL);
    size_t b = snprintf(timeseed,32,"%ld",now);
    RAND_add(&timeseed[0],b,2);

	unsigned char *randbytes = malloc(sizeof(unsigned char)*len);
    RAND_bytes(randbytes,len);

    RAND_cleanup();
    return randbytes;
}
コード例 #19
0
ファイル: ndn_signing.c プロジェクト: cawka/ndnd-tlv
/**
 * Feed some entropy to the random number generator.
 * 
 * @param buf is the source buffer
 * @param size is in bytes
 * @param bits_of_entropy is an estimate; use 0 to make me guess
 */
void
ndn_add_entropy(const void *buf, size_t size, int bits_of_entropy)
{
    int num = size;
    
    if (num < 0 || num != size)
        abort();
    /* Supply a hopefully conservative estimate of entropy. */
    if (bits_of_entropy <= 0)
        bits_of_entropy = (num < 32) ? 1 : num / 32;
    RAND_add((unsigned char *)buf, num, bits_of_entropy * 0.125);
}
コード例 #20
0
ファイル: lcrypto.c プロジェクト: hahnakane/junkcode
static int rand_add(lua_State *L)
{
  size_t num;
  const void *buf = luaL_checklstring(L, 1, &num);
#if CRYPTO_OPENSSL
  double entropy = (double)luaL_optnumber(L, 2, num);
  RAND_add(buf, num, entropy);
#elif CRYPTO_GCRYPT
  gcry_random_add_bytes(buf, num, -1); // unknown quality
#endif
  return 0;
}
コード例 #21
0
double
stir_gettimeofday(double entropy_estimate)
{
	struct timeval tv;

	if (gettimeofday(&tv, NULL) == -1)
		fatal("Couldn't gettimeofday: %s", strerror(errno));

	RAND_add(&tv, sizeof(tv), entropy_estimate);

	return entropy_estimate;
}
コード例 #22
0
static void ini_ssl(void) {
    static int inited = 0;
    if (inited) return;
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    SSL_library_init();
    while (!RAND_status()) {
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);
        RAND_add(&ts.tv_nsec, sizeof(ts.tv_nsec), 0.1);
    }
    inited = 1;
}
コード例 #23
0
/* helper routines for seeding the SSL PRNG */
static PyObject *
PySSL_RAND_add(PyObject *self, PyObject *args)
{
    char *buf;
    int len;
    double entropy;

    if (!PyArg_ParseTuple(args, "s#d:RAND_add", &buf, &len, &entropy))
	return NULL;
    RAND_add(buf, len, entropy);
    Py_INCREF(Py_None);
    return Py_None;
}
コード例 #24
0
ファイル: rand_win.c プロジェクト: LucidOne/Rovio
int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam)
        {
        double add_entropy=0;

        switch (iMsg)
                {
        case WM_KEYDOWN:
                        {
                        static WPARAM key;
                        if (key != wParam)
                                add_entropy = 0.05;
                        key = wParam;
                        }
                        break;
	case WM_MOUSEMOVE:
                        {
                        static int lastx,lasty,lastdx,lastdy;
                        int x,y,dx,dy;

                        x=LOWORD(lParam);
                        y=HIWORD(lParam);
                        dx=lastx-x;
                        dy=lasty-y;
                        if (dx != 0 && dy != 0 && dx-lastdx != 0 && dy-lastdy != 0)
                                add_entropy=.2;
                        lastx=x, lasty=y;
                        lastdx=dx, lastdy=dy;
                        }
		break;
		}

	readtimer();
        RAND_add(&iMsg, sizeof(iMsg), add_entropy);
	RAND_add(&wParam, sizeof(wParam), 0);
	RAND_add(&lParam, sizeof(lParam), 0);
 
	return (RAND_status());
	}
PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken)
{
	PKCS8_PRIV_KEY_INFO *p8;

	if (!(p8 = PKCS8_PRIV_KEY_INFO_new())) {	
		EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
		return NULL;
	}
	p8->broken = broken;
	ASN1_INTEGER_set (p8->version, 0);
	if (!(p8->pkeyalg->parameter = ASN1_TYPE_new ())) {
		EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
		PKCS8_PRIV_KEY_INFO_free (p8);
		return NULL;
	}
	p8->pkey->type = V_ASN1_OCTET_STRING;
	switch (EVP_PKEY_type(pkey->type)) {
#ifndef NO_RSA
		case EVP_PKEY_RSA:

		if(p8->broken == PKCS8_NO_OCTET) p8->pkey->type = V_ASN1_SEQUENCE;

		p8->pkeyalg->algorithm = OBJ_nid2obj(NID_rsaEncryption);
		p8->pkeyalg->parameter->type = V_ASN1_NULL;
		if (!ASN1_pack_string ((char *)pkey, (i2d_func_t)i2d_PrivateKey,
					 &p8->pkey->value.octet_string)) {
			EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
			PKCS8_PRIV_KEY_INFO_free (p8);
			return NULL;
		}
		break;
#endif
#ifndef NO_DSA
		case EVP_PKEY_DSA:
		if(!dsa_pkey2pkcs8(p8, pkey)) {
			PKCS8_PRIV_KEY_INFO_free (p8);
			return NULL;
		}

		break;
#endif
		default:
		EVPerr(EVP_F_EVP_PKEY2PKCS8, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
		PKCS8_PRIV_KEY_INFO_free (p8);
		return NULL;
	}
	RAND_add(p8->pkey->value.octet_string->data,
		 p8->pkey->value.octet_string->length, 0);
	return p8;
}
コード例 #26
0
double
stir_clock(double entropy_estimate)
{
#ifdef HAVE_CLOCK
	clock_t c;

	c = clock();
	RAND_add(&c, sizeof(c), entropy_estimate);

	return entropy_estimate;
#else /* _HAVE_CLOCK */
	return 0;
#endif /* _HAVE_CLOCK */
}
コード例 #27
0
ファイル: crypto_openssl.c プロジェクト: SCALE-GmbH/sqlcipher
static int sqlcipher_openssl_add_random(void *ctx, void *buffer, int length) {
#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
  CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: entering openssl_rand_mutex %p\n", openssl_rand_mutex);
  sqlite3_mutex_enter(openssl_rand_mutex);
  CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: entered openssl_rand_mutex %p\n", openssl_rand_mutex);
#endif
  RAND_add(buffer, length, 0);
#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
  CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: leaving openssl_rand_mutex %p\n", openssl_rand_mutex);
  sqlite3_mutex_leave(openssl_rand_mutex);
  CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: left openssl_rand_mutex %p\n", openssl_rand_mutex);
#endif
  return SQLITE_OK;
}
コード例 #28
0
ファイル: rand_win.c プロジェクト: KISSMonX/openssl
int RAND_poll(void)
{
    MEMORYSTATUS mst;
    HCRYPTPROV hProvider = 0;
    DWORD w;
    BYTE buf[64];

    /* poll the CryptoAPI PRNG */
    /* The CryptoAPI returns sizeof(buf) bytes of randomness */
    if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
        if (CryptGenRandom(hProvider, sizeof(buf), buf) != 0) {
            RAND_add(buf, sizeof(buf), sizeof(buf));
        }
        CryptReleaseContext(hProvider, 0);
    }

    /* poll the Pentium PRG with CryptoAPI */
    if (CryptAcquireContextW(&hProvider, NULL, INTEL_DEF_PROV, PROV_INTEL_SEC, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
        if (CryptGenRandom(hProvider, sizeof(buf), buf) != 0) {
            RAND_add(buf, sizeof(buf), sizeof(buf));
        }
        CryptReleaseContext(hProvider, 0);
    }

    /* timer data */
    readtimer();

    /* memory usage statistics */
    GlobalMemoryStatus(&mst);
    RAND_add(&mst, sizeof(mst), 1);

    /* process ID */
    w = GetCurrentProcessId();
    RAND_add(&w, sizeof(w), 1);

    return (1);
}
コード例 #29
0
ファイル: rand_win.c プロジェクト: LucidOne/Rovio
/* feed timing information to the PRNG */
static void readtimer(void)
{
	DWORD w;
	LARGE_INTEGER l;
	static int have_perfc = 1;
#if defined(_MSC_VER) && defined(_M_X86)
	static int have_tsc = 1;
	DWORD cyclecount;

	if (have_tsc) {
	  __try {
	    __asm {
	      _emit 0x0f
	      _emit 0x31
	      mov cyclecount, eax
	      }
	    RAND_add(&cyclecount, sizeof(cyclecount), 1);
	  } __except(EXCEPTION_EXECUTE_HANDLER) {
	    have_tsc = 0;
	  }
	}
#else
# define have_tsc 0
#endif

	if (have_perfc) {
	  if (QueryPerformanceCounter(&l) == 0)
	    have_perfc = 0;
	  else
	    RAND_add(&l, sizeof(l), 0);
	}

	if (!have_tsc && !have_perfc) {
	  w = GetTickCount();
	  RAND_add(&w, sizeof(w), 0);
	}
}
コード例 #30
0
double
stir_rusage(int who, double entropy_estimate)
{
#ifdef HAVE_GETRUSAGE
	struct rusage ru;

	if (getrusage(who, &ru) == -1)
		return 0;

	RAND_add(&ru, sizeof(ru), entropy_estimate);

	return entropy_estimate;
#else /* _HAVE_GETRUSAGE */
	return 0;
#endif /* _HAVE_GETRUSAGE */
}