Index: ossp-pkg/uuid/ChangeLog RCS File: /v/ossp/cvs/ossp-pkg/uuid/Attic/ChangeLog,v rcsdiff -q -kk '-r1.75' '-r1.76' -u '/v/ossp/cvs/ossp-pkg/uuid/Attic/ChangeLog,v' 2>/dev/null --- ChangeLog 2005/08/29 20:25:44 1.75 +++ ChangeLog 2005/08/30 15:26:07 1.76 @@ -13,6 +13,11 @@ Changes between 1.2.0 and 1.2.1 (23-Jan-2005 to xx-Mar-2005) + o Improve the PRNG in case no stronger system PRNG device is + available by passing time and rand(3) based entropy into the MD5 + one-way hash function to achieve at least some sort of weaker PRN data. + [Ralf S. Engelschall] + o Fix MAC address determination under Solaris by using the result of ioctl(...,SIOCGARP,...) only if arp_flags had ATF_COM set. [Ralf S. Engelschall] Index: ossp-pkg/uuid/uuid_prng.c RCS File: /v/ossp/cvs/ossp-pkg/uuid/Attic/uuid_prng.c,v rcsdiff -q -kk '-r1.5' '-r1.6' -u '/v/ossp/cvs/ossp-pkg/uuid/Attic/uuid_prng.c,v' 2>/dev/null --- uuid_prng.c 2005/03/29 19:01:41 1.5 +++ uuid_prng.c 2005/08/30 15:26:07 1.6 @@ -35,9 +35,12 @@ #include #include "uuid_prng.h" +#include "uuid_md5.h" struct prng_st { - int devfd; + int dev; /* system PRNG device */ + md5_t *md5; /* local MD5 PRNG engine */ + long cnt; /* time resolution compensation counter */ }; prng_rc_t prng_create(prng_t **prng) @@ -56,14 +59,21 @@ return PRNG_RC_MEM; /* try to open the system PRNG device */ - (*prng)->devfd = -1; + (*prng)->dev = -1; if ((fd = open("/dev/urandom", O_RDONLY)) == -1) fd = open("/dev/random", O_RDONLY|O_NONBLOCK); if (fd != -1) { fcntl(fd, F_SETFD, FD_CLOEXEC); - (*prng)->devfd = fd; + (*prng)->dev = fd; } + /* initialize MD5 engine */ + if (md5_create(&((*prng)->md5)) != MD5_RC_OK) + return PRNG_RC_INT; + + /* initialize time resolution compensation counter */ + (*prng)->cnt = 0; + /* seed the C library PRNG once */ gettimeofday(&tv, NULL); pid = getpid(); @@ -72,10 +82,7 @@ ^ (unsigned int)pid ^ (unsigned int)tv.tv_sec ^ (unsigned int)tv.tv_usec)); - - /* crank the PRNG a few times */ - gettimeofday(&tv, NULL); - for (i = (unsigned int)(tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) + for (i = (unsigned int)((tv.tv_sec ^ tv.tv_usec) & 0x1F); i > 0; i--) (void)rand(); return PRNG_RC_OK; @@ -85,35 +92,59 @@ { size_t n; unsigned char *p; - int cnt; + struct { + struct timeval tv; + long cnt; + int rnd; + } entropy; + unsigned char md5_buf[MD5_LEN_BIN]; + unsigned char *md5_ptr; + size_t md5_len; + int retries; int i; /* sanity check argument(s) */ if (prng == NULL || data_len == 0) return PRNG_RC_ARG; - /* try to gather data from the system PRNG device */ - if (prng->devfd != -1) { - p = (unsigned char *)data_ptr; - n = data_len; - cnt = 0; + /* prepare for generation */ + p = (unsigned char *)data_ptr; + n = data_len; + + /* approach 1: try to gather data via stronger system PRNG device */ + if (prng->dev != -1) { + retries = 0; while (n > 0) { - i = read(prng->devfd, (void *)p, n); + i = read(prng->dev, (void *)p, n); if (i <= 0) { - if (cnt++ > 16) + if (retries++ > 16) break; continue; } + retries = 0; n -= (unsigned int)i; p += (unsigned int)i; - cnt = 0; } } - /* always also apply the weaker PRNG. In case the stronger PRNG device - based source failed, this is the only remaining randomness, of course */ - for (p = (unsigned char *)data_ptr, n = 0; n < data_len; n++) - *p++ ^= (unsigned char)(((unsigned int)rand() >> 7) & 0xFF); + /* approach 2: try to gather data via weaker libc PRNG API. */ + while (n > 0) { + /* gather new entropy */ + gettimeofday(&(entropy.tv), NULL); + entropy.cnt = prng->cnt++; + entropy.rnd = rand(); + + /* pass entropy into MD5 engine */ + md5_update(prng->md5, (void *)&entropy, sizeof(entropy)); + + /* store MD5 engine state as PRN output */ + md5_ptr = md5_buf; + md5_len = sizeof(md5_buf); + md5_store(prng->md5, (void *)&md5_ptr, &md5_len); + for (i = 0; i < MD5_LEN_BIN && n > 0; i++, n--) + *p++ ^= md5_buf[i]; /* intentionally no assignment because arbitrary + caller buffer content is leveraged, too */ + } return PRNG_RC_OK; } @@ -125,8 +156,8 @@ return PRNG_RC_ARG; /* close PRNG device */ - if (prng->devfd != -1) - close(prng->devfd); + if (prng->dev != -1) + close(prng->dev); /* free object */ free(prng); Index: ossp-pkg/uuid/uuid_prng.h RCS File: /v/ossp/cvs/ossp-pkg/uuid/Attic/uuid_prng.h,v rcsdiff -q -kk '-r1.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/uuid/Attic/uuid_prng.h,v' 2>/dev/null --- uuid_prng.h 2004/12/31 19:20:34 1.2 +++ uuid_prng.h 2005/08/30 15:26:07 1.3 @@ -56,7 +56,8 @@ typedef enum { PRNG_RC_OK = 0, PRNG_RC_ARG = 1, - PRNG_RC_MEM = 2 + PRNG_RC_MEM = 2, + PRNG_RC_INT = 3 } prng_rc_t; extern prng_rc_t prng_create (prng_t **prng);