+/* Generate a 32-byte random for the secure transport code. */
+void
+generate_random(uint8 * random)
+{
+ struct stat st;
+ struct tms tmsbuf;
+ MD5_CTX md5;
+ uint32 *r;
+ int fd, n;
+
+ /* If we have a kernel random device, try that first */
+ if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
+ || ((fd = open("/dev/random", O_RDONLY)) != -1))
+ {
+ n = read(fd, random, 32);
+ close(fd);
+ if (n == 32)
+ return;
+ }
+
+#ifdef EGD_SOCKET
+ /* As a second preference use an EGD */
+ if (generate_random_egd(random))
+ return;
+#endif
+
+ /* Otherwise use whatever entropy we can gather - ideas welcome. */
+ r = (uint32 *) random;
+ r[0] = (getpid()) | (getppid() << 16);
+ r[1] = (getuid()) | (getgid() << 16);
+ r[2] = times(&tmsbuf); /* system uptime (clocks) */
+ gettimeofday((struct timeval *) &r[3], NULL); /* sec and usec */
+ stat("/tmp", &st);
+ r[5] = st.st_atime;
+ r[6] = st.st_mtime;
+ r[7] = st.st_ctime;
+
+ /* Hash both halves with MD5 to obscure possible patterns */
+ MD5_Init(&md5);
+ MD5_Update(&md5, random, 16);
+ MD5_Final(random, &md5);
+ MD5_Update(&md5, random + 16, 16);
+ MD5_Final(random + 16, &md5);
+}
+