3 * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
12 #ifdef HAVE_WINCRYPT_H
22 #include <lutil_md5.h>
25 * lutil_entropy() provides nbytes of entropy in buf.
26 * Quality offerred is suitable for one-time uses, such as "once" keys.
28 int lutil_entropy( char *buf, int nbytes )
30 if( nbytes < 0 ) return -1;
31 if( nbytes == 0 ) return 0;
34 /* Linux and *BSD offer a urandom device */
38 fd = open( URANDOM_DEVICE, O_RDONLY );
40 if( fd < 0 ) return -1;
42 rc = read( fd, buf, nbytes );
45 /* should return nbytes */
46 if( rc < nbytes ) return -1;
52 /* Not used since _WIN32_WINNT not set... */
55 /* Get handle to user default provider */
56 if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) {
60 /* Generate random initialization vector */
61 if(!CryptGenRandom(hProv, (DWORD) nbytes, (BYTE *) buf)) {
65 /* Release provider handle */
66 if(hProv != 0) CryptReleaseContext(hProv, 0);
72 /* based upon Phil Karn's "practical randomness" idea
73 * but implementation 100% OpenLDAP. So don't blame Phil. */
74 /* worse case is this is a MD5 hash of a counter, if
75 * MD5 is a strong cryptographic hash, this should
76 * be fairly resistant to attack
78 static int counter = 0;
85 struct rdata_s *stack;
89 #ifdef HAVE_GETTIMEOFDAY
97 /* make sure rdata differs for each process */
100 /* make sure rdata differs for each program */
102 rdata.stack = &rdata;
104 for( n = 0; n < nbytes; n += 16 ) {
105 struct lutil_MD5Context ctx;
108 /* hopefully has good resolution */
109 #ifdef HAVE_GETTIMEOFDAY
110 (void) gettimeofday( &rdata.tv, sizeof( rdata.tv ) );
112 (void) time( &rdata.time );
115 /* make sure rdata differs */
116 rdata.counter = ++counter;
120 lutil_MD5Init( &ctx );
121 lutil_MD5Update( &ctx, (char *) &rdata, sizeof( rdata ) );
122 lutil_MD5Final( digest, &ctx );
124 memcpy( &buf[n], digest,
125 nbytes - n > 16 ? 16 : nbytes - n );