OSSP CVS Repository

ossp - Difference in ossp-pkg/uuid/uuid_prng.c versions 1.5 and 1.6
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [History

ossp-pkg/uuid/uuid_prng.c 1.5 -> 1.6

--- 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 <fcntl.h>
 
 #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);

CVSTrac 2.0.1