Merge pull request #159 from GuildMasterInfinite/fix-crypt-windows

Use `RtlGenRandom` on Windows
diff --git a/src/os.rs b/src/os.rs
index 970cfd7..7f24119 100644
--- a/src/os.rs
+++ b/src/os.rs
@@ -21,8 +21,8 @@
 ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
 /// - OpenBSD: calls `getentropy(2)`
 /// - FreeBSD: uses the `kern.arandom` `sysctl(2)` mib
-/// - Windows: calls `CryptGenRandom`, using the default cryptographic
-///   service provider with the `PROV_RSA_FULL` type.
+/// - Windows: calls `RtlGenRandom`, exported from `advapi32.dll` as
+///   `SystemFunction036`.
 /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
 /// - PNaCl: calls into the `nacl-irt-random-0.1` IRT interface.
 ///
@@ -383,53 +383,25 @@
 #[cfg(windows)]
 mod imp {
     use std::io;
-    use std::ptr;
     use Rng;
 
     use super::{next_u32, next_u64};
 
-    type BOOL = i32;
-    type LPCSTR = *const i8;
-    type DWORD = u32;
-    type HCRYPTPROV = usize;
-    type BYTE = u8;
-
-    const PROV_RSA_FULL: DWORD = 1;
-    const CRYPT_SILENT: DWORD = 0x00000040;
-    const CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
+    type BOOLEAN = u8;
+    type ULONG = u32;
 
     #[link(name = "advapi32")]
     extern "system" {
-        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
-                                szContainer: LPCSTR,
-                                szProvider: LPCSTR,
-                                dwProvType: DWORD,
-                                dwFlags: DWORD) -> BOOL;
-        fn CryptGenRandom(hProv: HCRYPTPROV,
-                          dwLen: DWORD,
-                          pbBuffer: *mut BYTE) -> BOOL;
-        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
+        // This function's real name is `RtlGenRandom`.
+        fn SystemFunction036(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
     }
 
     #[derive(Debug)]
-    pub struct OsRng {
-        hcryptprov: HCRYPTPROV
-    }
+    pub struct OsRng;
 
     impl OsRng {
         pub fn new() -> io::Result<OsRng> {
-            let mut hcp = 0;
-            let ret = unsafe {
-                CryptAcquireContextA(&mut hcp, ptr::null(), ptr::null(),
-                                     PROV_RSA_FULL,
-                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
-            };
-
-            if ret == 0 {
-                Err(io::Error::last_os_error())
-            } else {
-                Ok(OsRng { hcryptprov: hcp })
-            }
+            Ok(OsRng)
         }
     }
 
@@ -441,12 +413,11 @@
             next_u64(&mut |v| self.fill_bytes(v))
         }
         fn fill_bytes(&mut self, v: &mut [u8]) {
-            // CryptGenRandom takes a DWORD (u32) for the length so we need to
+            // RtlGenRandom takes an ULONG (u32) for the length so we need to
             // split up the buffer.
-            for slice in v.chunks_mut(<DWORD>::max_value() as usize) {
+            for slice in v.chunks_mut(<ULONG>::max_value() as usize) {
                 let ret = unsafe {
-                    CryptGenRandom(self.hcryptprov, slice.len() as DWORD,
-                                   slice.as_mut_ptr())
+                    SystemFunction036(slice.as_mut_ptr(), slice.len() as ULONG)
                 };
                 if ret == 0 {
                     panic!("couldn't generate random bytes: {}",
@@ -455,18 +426,6 @@
             }
         }
     }
-
-    impl Drop for OsRng {
-        fn drop(&mut self) {
-            let ret = unsafe {
-                CryptReleaseContext(self.hcryptprov, 0)
-            };
-            if ret == 0 {
-                panic!("couldn't release context: {}",
-                       io::Error::last_os_error());
-            }
-        }
-    }
 }
 
 #[cfg(target_os = "nacl")]