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 * Note: Callers are encouraged to provide additional bytes of
29 * of entropy in the buf argument. This information is used in
30 * fallback mode to improve the quality of bytes returned.
32 int lutil_entropy( char *buf, int nbytes )
34 if( nbytes < 0 ) return -1;
35 if( nbytes == 0 ) return 0;
38 /* Linux and *BSD offer a urandom device */
42 fd = open( URANDOM_DEVICE, O_RDONLY );
44 if( fd < 0 ) return -1;
46 rc = read( fd, buf, nbytes );
49 /* should return nbytes */
50 if( rc < nbytes ) return -1;
56 /* Not used since _WIN32_WINNT not set... */
59 /* Get handle to user default provider */
60 if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) {
64 /* Generate random initialization vector */
65 if(!CryptGenRandom(hProv, (DWORD) nbytes, (BYTE *) buf)) {
69 /* Release provider handle */
70 if(hProv != 0) CryptReleaseContext(hProv, 0);
76 /* based upon Phil Karn's "practical randomness" idea
77 * but implementation 100% OpenLDAP. So don't blame Phil. */
78 /* worse case is this is a MD5 hash of a counter, if
79 * MD5 is a strong cryptographic hash, this should
80 * be fairly resistant to attack
84 * the caller may need to provide external synchronization OR
85 * provide entropy (in buf) to ensure quality results as
86 * access to this counter may not be atomic.
88 static int counter = 0;
95 struct rdata_s *stack;
99 #ifdef HAVE_GETTIMEOFDAY
105 unsigned long junk; /* purposely not initialized */
108 /* make sure rdata differs for each process */
109 rdata.pid = getpid();
111 /* make sure rdata differs for each program */
113 rdata.stack = &rdata;
115 for( n = 0; n < nbytes; n += 16 ) {
116 struct lutil_MD5Context ctx;
119 /* poor resolution */
120 #ifdef HAVE_GETTIMEOFDAY
121 (void) gettimeofday( &rdata.tv, NULL );
123 (void) time( &rdata.time );
126 /* make sure rdata differs */
127 rdata.counter = ++counter;
131 lutil_MD5Init( &ctx );
132 lutil_MD5Update( &ctx, (char *) &rdata, sizeof( rdata ) );
134 /* allow caller to provided additional entropy */
135 lutil_MD5Update( &ctx, (char *) &buf, nbytes );
137 lutil_MD5Final( digest, &ctx );
139 memcpy( &buf[n], digest,
140 nbytes - n >= 16 ? 16 : nbytes - n );