PR: 2563
authorDr. Stephen Henson <steve@openssl.org>
Mon, 19 Dec 2011 17:01:37 +0000 (17:01 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 19 Dec 2011 17:01:37 +0000 (17:01 +0000)
Submitted by: Paul Green <Paul.Green@stratus.com>
Reviewed by: steve

Improved PRNG seeding for VOS.

CHANGES
Configure
crypto/rand/rand_unix.c
e_os2.h

diff --git a/CHANGES b/CHANGES
index 5d544d83480423a79553d027ce4012450681acbd..66f3928b88913fe743e9fc11c739cca4a272b7d7 100644 (file)
--- a/CHANGES
+++ b/CHANGES
   
  Changes between 1.0.0f and 1.0.1  [xx XXX xxxx]
 
+  *) Improved PRNG seeding for VOS.
+     [Paul Green <Paul.Green@stratus.com>]
+
   *) Extensive assembler packs updates, most notably:
 
        - x86[_64]:     AES-NI, PCLMULQDQ, RDRAND support;
index 915c06857fa1e49838031abd7e4bd1e4e78b31e9..75bd162f33b9d7755f486638f1ac27e3a202ecf8 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -200,8 +200,8 @@ my %table=(
 "cc",          "cc:-O::(unknown)::::::",
 
 ####VOS Configurations
-"vos-gcc","gcc:-O3 -Wall -D_POSIX_C_SOURCE=200112L -D_BSD -D_VOS_EXTENDED_NAMES -DB_ENDIAN::(unknown):VOS:-Wl,-map:BN_LLONG:${no_asm}:::::.so:",
-"debug-vos-gcc","gcc:-O0 -g -Wall -D_POSIX_C_SOURCE=200112L -D_BSD -D_VOS_EXTENDED_NAMES -DB_ENDIAN -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG::(unknown):VOS:-Wl,-map:BN_LLONG:${no_asm}:::::.so:",
+"vos-gcc","gcc:-O3 -Wall -DOPENSSL_SYSNAME_VOS -D_POSIX_C_SOURCE=200112L -D_BSD -D_VOS_EXTENDED_NAMES -DB_ENDIAN::(unknown):VOS:-Wl,-map:BN_LLONG:${no_asm}:::::.so:",
+"debug-vos-gcc","gcc:-O0 -g -Wall -DOPENSSL_SYSNAME_VOS -D_POSIX_C_SOURCE=200112L -D_BSD -D_VOS_EXTENDED_NAMES -DB_ENDIAN -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG::(unknown):VOS:-Wl,-map:BN_LLONG:${no_asm}:::::.so:",
 
 #### Solaris x86 with GNU C setups
 # -DOPENSSL_NO_INLINE_ASM switches off inline assembler. We have to do it
index e9ead3a529688fd2c49a95b6871240d24ac6d70d..e3a65571c8dfcd0b5e6fdd19e82ee48ed80fbbae 100644 (file)
 # define FD_SETSIZE (8*sizeof(fd_set))
 #endif
 
-#ifdef __VOS__
+#if defined(OPENSSL_SYS_VOS)
+
+/* The following algorithm repeatedly samples the real-time clock
+   (RTC) to generate a sequence of unpredictable data.  The algorithm
+   relies upon the uneven execution speed of the code (due to factors
+   such as cache misses, interrupts, bus activity, and scheduling) and
+   upon the rather large relative difference between the speed of the
+   clock and the rate at which it can be read.
+
+   If this code is ported to an environment where execution speed is
+   more constant or where the RTC ticks at a much slower rate, or the
+   clock can be read with fewer instructions, it is likely that the
+   results would be far more predictable.
+
+   As a precaution, we generate 4 times the minimum required amount of
+   seed data.  */
+
 int RAND_poll(void)
 {
-       unsigned char buf[ENTROPY_NEEDED];
+       short int code;
+       gid_t curr_gid;
        pid_t curr_pid;
        uid_t curr_uid;
-       static int first=1;
-       int i;
-       long rnd = 0;
+       int i, k;
        struct timespec ts;
-       unsigned seed;
-
-/* The VOS random() function starts from a static seed so its
-   initial value is predictable.  If random() returns the
-   initial value, reseed it with dynamic data.  The VOS
-   real-time clock has a granularity of 1 nsec so it should be
-   reasonably difficult to predict its exact value.  Do not
-   gratuitously reseed the PRNG because other code in this
-   process or thread may be using it.  */
-
-       if (first) {
-               first = 0;
-               rnd = random ();
-               if (rnd == 1804289383) {
-                       clock_gettime (CLOCK_REALTIME, &ts);
-                       curr_pid = getpid();
-                       curr_uid = getuid();
-                       seed = ts.tv_sec ^ ts.tv_nsec ^ curr_pid ^ curr_uid;
-                       srandom (seed);
-               }
-       }
+       unsigned char v;
 
-       for (i = 0; i < sizeof(buf); i++) {
-               if (i % 4 == 0)
-                       rnd = random();
-               buf[i] = rnd;
-               rnd >>= 8;
-       }
-       RAND_add(buf, sizeof(buf), ENTROPY_NEEDED);
-       memset(buf, 0, sizeof(buf));
+#ifdef OPENSSL_SYS_VOS_HPPA
+       long duration;
+       extern void s$sleep (long *_duration, short int *_code);
+#else
+#ifdef OPENSSL_SYS_VOS_IA32
+       long long duration;
+       extern void s$sleep2 (long long *_duration, short int *_code);
+#else
+#error "Unsupported Platform."
+#endif /* OPENSSL_SYS_VOS_IA32 */
+#endif /* OPENSSL_SYS_VOS_HPPA */
+
+       /* Seed with the gid, pid, and uid, to ensure *some*
+          variation between different processes.  */
+
+       curr_gid = getgid();
+       RAND_add (&curr_gid, sizeof curr_gid, 1);
+       curr_gid = 0;
+
+       curr_pid = getpid();
+       RAND_add (&curr_pid, sizeof curr_pid, 1);
+       curr_pid = 0;
+
+       curr_uid = getuid();
+       RAND_add (&curr_uid, sizeof curr_uid, 1);
+       curr_uid = 0;
 
+       for (i=0; i<(ENTROPY_NEEDED*4); i++)
+       {
+               /* burn some cpu; hope for interrupts, cache
+                  collisions, bus interference, etc.  */
+               for (k=0; k<99; k++)
+                       ts.tv_nsec = random ();
+
+#ifdef OPENSSL_SYS_VOS_HPPA
+               /* sleep for 1/1024 of a second (976 us).  */
+               duration = 1;
+               s$sleep (&duration, &code);
+#else
+#ifdef OPENSSL_SYS_VOS_IA32
+               /* sleep for 1/65536 of a second (15 us).  */
+               duration = 1;
+               s$sleep2 (&duration, &code);
+#endif /* OPENSSL_SYS_VOS_IA32 */
+#endif /* OPENSSL_SYS_VOS_HPPA */
+
+               /* get wall clock time.  */
+               clock_gettime (CLOCK_REALTIME, &ts);
+
+               /* take 8 bits */
+               v = (unsigned char) (ts.tv_nsec % 256);
+               RAND_add (&v, sizeof v, 1);
+               v = 0;
+       }
        return 1;
 }
 #elif defined __OpenBSD__
diff --git a/e_os2.h b/e_os2.h
index 405b51fceca403afc80254c7d8b4ef62356ab270..f4597a2c6703fc2037e0b06e0d55f74e415c0a4f 100644 (file)
--- a/e_os2.h
+++ b/e_os2.h
@@ -193,8 +193,14 @@ extern "C" {
 #endif
 
 /* --------------------------------- VOS ----------------------------------- */
-#ifdef OPENSSL_SYSNAME_VOS
+#if defined(__VOS__) || defined(OPENSSL_SYSNAME_VOS)
 # define OPENSSL_SYS_VOS
+#ifdef __HPPA__
+# define OPENSSL_SYS_VOS_HPPA
+#endif
+#ifdef __IA32__
+# define OPENSSL_SYS_VOS_IA32
+#endif
 #endif
 
 /* ------------------------------- VxWorks --------------------------------- */