[newlib-cygwin] Rearrange RNG code slightly

Corinna Vinschen corinna@sourceware.org
Wed Dec 14 11:21:00 GMT 2016


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=74f7872f89dc8ecad500c5d5c4e03b4757f6418d

commit 74f7872f89dc8ecad500c5d5c4e03b4757f6418d
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Tue Dec 13 22:59:31 2016 +0100

    Rearrange RNG code slightly
    
    In preparation of exporting getentropy/getrandom to userspace, rearrange
    code a bit:
    
    - Define RtlGenRandom in ntdll.h.
    
    - Drop calls to getentropy in favor of RtlGenRandom (fhandler_socket,
      fhandler_dev_random).
    
    - Add try/except blocks in fhandler_dev_random to return EFAULT rather
      than crashing if buffer pointer is invalid.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/fhandler_random.cc | 72 +++++++++++++++++++++++++---------------
 winsup/cygwin/fhandler_socket.cc |  2 +-
 winsup/cygwin/miscfuncs.cc       |  6 ----
 winsup/cygwin/ntdll.h            |  6 ++++
 4 files changed, 52 insertions(+), 34 deletions(-)

diff --git a/winsup/cygwin/fhandler_random.cc b/winsup/cygwin/fhandler_random.cc
index af76a66..c56ce73 100644
--- a/winsup/cygwin/fhandler_random.cc
+++ b/winsup/cygwin/fhandler_random.cc
@@ -47,16 +47,26 @@ fhandler_dev_random::write (const void *ptr, size_t len)
     }
 
   /* Limit len to a value <= 4096 since we don't want to overact.
-     Copy to local buffer because CryptGenRandom violates const. */
+     Copy to local buffer because RtlGenRandom violates const. */
   size_t limited_len = MIN (len, 4096);
   unsigned char buf[limited_len];
-  memcpy (buf, ptr, limited_len);
 
   /* Mess up system entropy source. Return error if device is /dev/random. */
-  if (getentropy (buf, limited_len) && dev () == FH_RANDOM)
-    return -1;
-  /* Mess up the pseudo random number generator. */
-  pseudo_write (buf, limited_len);
+  __try
+    {
+      memcpy (buf, ptr, limited_len);
+      if (!RtlGenRandom (buf, limited_len) && dev () == FH_RANDOM)
+	return -1;
+      /* Mess up the pseudo random number generator. */
+      pseudo_write (buf, limited_len);
+    }
+  __except (EFAULT)
+    {
+      len = -1;
+    }
+  __endtry
+  /* Note that we return len, not limited_len.  No reason to confuse the
+     caller... */
   return len;
 }
 
@@ -88,32 +98,40 @@ fhandler_dev_random::read (void *ptr, size_t& len)
       return;
     }
 
-  /* /dev/random has to provide high quality random numbers.  Therefore we
-     re-seed the system PRNG for each block of 512 bytes.  This results in
-     sufficiently random sequences, comparable to the Linux /dev/random. */
-  if (dev () == FH_RANDOM)
+  __try
     {
-      void *dummy = malloc (RESEED_INTERVAL);
-      if (!dummy)
+      /* /dev/random has to provide high quality random numbers.  Therefore we
+	 re-seed the system PRNG for each block of 512 bytes.  This results in
+	 sufficiently random sequences, comparable to the Linux /dev/random. */
+      if (dev () == FH_RANDOM)
 	{
-	  __seterrno ();
-	  len = (size_t) -1;
-	  return;
-	}
-      for (size_t offset = 0; offset < len; offset += 512)
-	{
-	  if (getentropy (dummy, RESEED_INTERVAL) ||
-	      getentropy ((PBYTE) ptr + offset, len - offset))
+	  void *dummy = malloc (RESEED_INTERVAL);
+	  if (!dummy)
 	    {
+	      __seterrno ();
 	      len = (size_t) -1;
-	      break;
+	      return;
 	    }
+	  for (size_t offset = 0; offset < len; offset += 512)
+	    {
+	      if (!RtlGenRandom (dummy, RESEED_INTERVAL) ||
+		  !RtlGenRandom ((PBYTE) ptr + offset, len - offset))
+		{
+		  len = (size_t) -1;
+		  break;
+		}
+	    }
+	  free (dummy);
 	}
-      free (dummy);
-    }
 
-  /* If device is /dev/urandom, just use system RNG as is, with our own
-     PRNG as fallback. */
-  else if (getentropy (ptr, len))
-    len = pseudo_read (ptr, len);
+      /* If device is /dev/urandom, just use system RNG as is, with our own
+	 PRNG as fallback. */
+      else if (!RtlGenRandom (ptr, len))
+	len = pseudo_read (ptr, len);
+    }
+  __except (EFAULT)
+    {
+      len = (size_t) -1;
+    }
+  __endtry
 }
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 9ada469..801a731 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -485,7 +485,7 @@ fhandler_socket::af_local_copy (fhandler_socket *sock)
 void
 fhandler_socket::af_local_set_secret (char *buf)
 {
-  if (getentropy (connect_secret, sizeof (connect_secret)))
+  if (!RtlGenRandom (connect_secret, sizeof (connect_secret)))
     bzero ((char*) connect_secret, sizeof (connect_secret));
   __small_sprintf (buf, "%08x-%08x-%08x-%08x",
 		   connect_secret [0], connect_secret [1],
diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc
index f90d6ef..0b19b28 100644
--- a/winsup/cygwin/miscfuncs.cc
+++ b/winsup/cygwin/miscfuncs.cc
@@ -233,12 +233,6 @@ check_iovec (const struct iovec *iov, int iovcnt, bool forwrite)
   return -1;
 }
 
-/* There's a bug in ntsecapi.h (Mingw as well as MSFT).  SystemFunction036
-   is, in fact, a WINAPI function, but it's not defined as such.  Therefore
-   we have to do it correctly here. */
-#define RtlGenRandom SystemFunction036
-extern "C" BOOLEAN WINAPI RtlGenRandom (PVOID, ULONG);
-
 /* Used by arc2random, fhandler_socket and fhandler_random. */
 extern "C" int
 getentropy (void *ptr, size_t len)
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index 448eadf..bf5a7cf 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -1608,4 +1608,10 @@ extern "C"
 
   }
 }
+
+/* There's a bug in ntsecapi.h (Mingw as well as MSFT).  SystemFunction036
+   is, in fact, a WINAPI function, but it's not defined as such.  Therefore
+   we have to do it correctly here.  *Strictly*, this is not ntdll... */
+#define RtlGenRandom SystemFunction036
+extern "C" BOOLEAN WINAPI RtlGenRandom (PVOID, ULONG);
 #endif



More information about the Cygwin-cvs mailing list