#include "portable.h"
#include <ac/string.h>
#include <ac/time.h>
#include <ac/unistd.h>
#ifdef HAVE_PROCESS_H
#include <process.h>
#endif
#include <fcntl.h>
#include <lutil.h>
#include <lutil_md5.h>
int lutil_entropy( unsigned char *buf, ber_len_t nbytes )
{
if( nbytes == 0 ) return 0;
#ifdef URANDOM_DEVICE
#define URANDOM_NREADS 4
{
int rc, fd, n=0;
fd = open( URANDOM_DEVICE, O_RDONLY );
if( fd < 0 ) return -1;
do {
rc = read( fd, buf, nbytes );
if( rc <= 0 ) break;
buf+=rc;
nbytes-=rc;
if( ++n >= URANDOM_NREADS ) break;
} while( nbytes > 0 );
close(fd);
return nbytes > 0 ? -1 : 0;
}
#elif PROV_RSA_FULL
{
HCRYPTPROV hProv = 0;
if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) {
return -1;
}
if(!CryptGenRandom(hProv, (DWORD) nbytes, (BYTE *) buf)) {
return -1;
}
if(hProv != 0) CryptReleaseContext(hProv, 0);
return 0;
}
#else
{
static int counter = 0;
ber_len_t n;
struct rdata_s {
int counter;
unsigned char *buf;
struct rdata_s *stack;
pid_t pid;
#ifdef HAVE_GETTIMEOFDAY
struct timeval tv;
#else
time_t time;
#endif
unsigned long junk;
} rdata;
rdata.pid = getpid();
rdata.buf = buf;
rdata.stack = &rdata;
for( n = 0; n < nbytes; n += 16 ) {
struct lutil_MD5Context ctx;
char digest[16];
#ifdef HAVE_GETTIMEOFDAY
(void) gettimeofday( &rdata.tv, NULL );
#else
(void) time( &rdata.time );
#endif
rdata.counter = ++counter;
rdata.pid++;
rdata.junk++;
lutil_MD5Init( &ctx );
lutil_MD5Update( &ctx, (unsigned char *) &rdata, sizeof( rdata ) );
lutil_MD5Update( &ctx, buf, nbytes );
lutil_MD5Final( digest, &ctx );
AC_MEMCPY( &buf[n], digest,
nbytes - n >= 16 ? 16 : nbytes - n );
}
return 0;
}
#endif
return -1;
}