Procházet zdrojové kódy

Add half our entropy from RAND_poll in OpenSSL. These know how to use egd (if present) openbsd weirdness (if present), vms/os2 weirdness (if we ever port there), and more in the future.

svn:r5215
Nick Mathewson před 20 roky
rodič
revize
a53ecc94f9
1 změnil soubory, kde provedl 34 přidání a 13 odebrání
  1. 34 13
      src/common/crypto.c

+ 34 - 13
src/common/crypto.c

@@ -1575,42 +1575,63 @@ crypto_dh_free(crypto_dh_env_t *dh)
 
 /* random numbers */
 
+/* This is how much entropy OpenSSL likes to add right now, so maybe it will
+ * work for us too. */
+#define ADD_ENTROPY 32
+
+/* Use RAND_poll if openssl is 0.9.6 release or later.  (The "f" means
+   "release".)  */
+#define USE_RAND_POLL (OPENSSL_VERSION_NUMBER >= 0x0090600fl)
+
 /** Seed OpenSSL's random number generator with bytes from the
  * operating system.  Return 0 on success, -1 on failure.
  */
 int
 crypto_seed_rng(void)
 {
-  char buf[64];
+  char buf[ADD_ENTROPY];
+  int rand_poll_status;
+
+  /* local variables */
 #ifdef MS_WINDOWS
   static int provider_set = 0;
   static HCRYPTPROV provider;
+#else
+  static const char *filenames[] = {
+    "/dev/srandom", "/dev/urandom", "/dev/random", NULL
+  };
+  int fd;
+  int i, n;
+#endif
 
+#if USE_RAND_POLL
+  /* OpenSSL 0.9.6 adds a RAND_poll function that knows about more kinds of
+   * entropy than we do.  We'll try calling that, *and* calling our own entropy
+   * functions.  If one succeeds, we'll accept the RNG as seeded. */
+  rand_poll_status = RAND_poll();
+  if (rand_poll_status == 0)
+    log_fn(LOG_WARN, "RAND_poll() failed.");
+#else
+  rand_poll_status = 0;
+#endif
+
+#ifdef MS_WINDOWS
   if (!provider_set) {
     if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
       if (GetLastError() != NTE_BAD_KEYSET) {
         log_fn(LOG_ERR,"Can't get CryptoAPI provider [1]");
-        return -1;
+        return rand_poll_status ? 0 : -1;
       }
     }
     provider_set = 1;
   }
   if (!CryptGenRandom(provider, sizeof(buf), buf)) {
     log_fn(LOG_ERR,"Can't get entropy from CryptoAPI.");
-    return -1;
+    return rand_poll_status ? 0 : -1;
   }
   RAND_seed(buf, sizeof(buf));
-  /* And add the current screen state to the entropy pool for
-   * good measure. */
-  RAND_screen();
   return 0;
 #else
-  static const char *filenames[] = {
-    "/dev/srandom", "/dev/urandom", "/dev/random", NULL
-  };
-  int fd;
-  int i, n;
-
   for (i = 0; filenames[i]; ++i) {
     fd = open(filenames[i], O_RDONLY, 0);
     if (fd<0) continue;
@@ -1626,7 +1647,7 @@ crypto_seed_rng(void)
   }
 
   log_fn(LOG_WARN, "Cannot seed RNG -- no entropy source found.");
-  return -1;
+  return rand_poll_status ? 0 : -1;
 #endif
 }