about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2017-10-18 11:43:17 -0700
committerAlex Crichton <alex@alexcrichton.com>2017-10-18 11:48:20 -0700
commit55c01736cbabc8e4541b814ae8149173b8028651 (patch)
tree9525eecc07ab0adde3de1e0dc87ae463cc2d41a5 /src/libstd/sys
parent7a4f39453cfbeab1c2220331f2eae8938165c964 (diff)
downloadrust-55c01736cbabc8e4541b814ae8149173b8028651.tar.gz
rust-55c01736cbabc8e4541b814ae8149173b8028651.zip
std: Update randomness implementation on Windows
This commit updates the OS random number generator on Windows to match the
upstream implementation in the `rand` crate. First proposed in
rust-lang-nursery/rand#111 this implementation uses a "private" API of
`RtlGenRandom`. Despite the [documentation][dox] indicating this is a private
function its widespread use in Chromium and Firefox as well as [comments] from
Microsoft internally indicates that it's highly unlikely to break.

Another motivation for switching this is to also attempt to make progress
on #44911. It may be the case that this function succeeds while the previous
implementation may fail in "weird" scenarios.

[dox]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa387694(v=vs.85).aspx
[comments]: https://github.com/rust-lang-nursery/rand/issues/111#issuecomment-316140155
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/windows/c.rs18
-rw-r--r--src/libstd/sys/windows/rand.rs38
2 files changed, 10 insertions, 46 deletions
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index 762e39809cc..39e00270233 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -37,7 +37,6 @@ pub type BOOL = c_int;
 pub type BYTE = u8;
 pub type BOOLEAN = BYTE;
 pub type GROUP = c_uint;
-pub type LONG_PTR = isize;
 pub type LARGE_INTEGER = c_longlong;
 pub type LONG = c_long;
 pub type UINT = c_uint;
@@ -46,7 +45,6 @@ pub type USHORT = c_ushort;
 pub type SIZE_T = usize;
 pub type WORD = u16;
 pub type CHAR = c_char;
-pub type HCRYPTPROV = LONG_PTR;
 pub type ULONG_PTR = usize;
 pub type ULONG = c_ulong;
 #[cfg(target_arch = "x86_64")]
@@ -288,10 +286,6 @@ pub const IMAGE_FILE_MACHINE_I386: DWORD = 0x014c;
 #[cfg(feature = "backtrace")]
 pub const IMAGE_FILE_MACHINE_AMD64: DWORD = 0x8664;
 
-pub const PROV_RSA_FULL: DWORD = 1;
-pub const CRYPT_SILENT: DWORD = 64;
-pub const CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
-
 pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
 pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
 pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15;
@@ -1136,15 +1130,6 @@ extern "system" {
     pub fn GetProcAddress(handle: HMODULE,
                           name: LPCSTR) -> *mut c_void;
     pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
-    pub fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
-                                pszContainer: LPCSTR,
-                                pszProvider: LPCSTR,
-                                dwProvType: DWORD,
-                                dwFlags: DWORD) -> BOOL;
-    pub fn CryptGenRandom(hProv: HCRYPTPROV,
-                          dwLen: DWORD,
-                          pbBuffer: *mut BYTE) -> BOOL;
-    pub fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
 
     pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME);
 
@@ -1175,6 +1160,9 @@ extern "system" {
                   writefds: *mut fd_set,
                   exceptfds: *mut fd_set,
                   timeout: *const timeval) -> c_int;
+
+    #[link_name = "SystemFunction036"]
+    pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
 }
 
 // Functions that aren't available on every version of Windows that we support,
diff --git a/src/libstd/sys/windows/rand.rs b/src/libstd/sys/windows/rand.rs
index 10e3d45f9d5..f66b0a3bdc3 100644
--- a/src/libstd/sys/windows/rand.rs
+++ b/src/libstd/sys/windows/rand.rs
@@ -14,25 +14,12 @@ use mem;
 use rand::Rng;
 use sys::c;
 
-pub struct OsRng {
-    hcryptprov: c::HCRYPTPROV
-}
+pub struct OsRng;
 
 impl OsRng {
     /// Create a new `OsRng`.
     pub fn new() -> io::Result<OsRng> {
-        let mut hcp = 0;
-        let ret = unsafe {
-            c::CryptAcquireContextA(&mut hcp, 0 as c::LPCSTR, 0 as c::LPCSTR,
-                                    c::PROV_RSA_FULL,
-                                    c::CRYPT_VERIFYCONTEXT | c::CRYPT_SILENT)
-        };
-
-        if ret == 0 {
-            Err(io::Error::last_os_error())
-        } else {
-            Ok(OsRng { hcryptprov: hcp })
-        }
+        Ok(OsRng)
     }
 }
 
@@ -42,18 +29,19 @@ impl Rng for OsRng {
         self.fill_bytes(&mut v);
         unsafe { mem::transmute(v) }
     }
+
     fn next_u64(&mut self) -> u64 {
         let mut v = [0; 8];
         self.fill_bytes(&mut v);
         unsafe { mem::transmute(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(<c::DWORD>::max_value() as usize) {
+        for slice in v.chunks_mut(<c::ULONG>::max_value() as usize) {
             let ret = unsafe {
-                c::CryptGenRandom(self.hcryptprov, slice.len() as c::DWORD,
-                                  slice.as_mut_ptr())
+                c::RtlGenRandom(slice.as_mut_ptr(), slice.len() as c::ULONG)
             };
             if ret == 0 {
                 panic!("couldn't generate random bytes: {}",
@@ -62,15 +50,3 @@ impl Rng for OsRng {
         }
     }
 }
-
-impl Drop for OsRng {
-    fn drop(&mut self) {
-        let ret = unsafe {
-            c::CryptReleaseContext(self.hcryptprov, 0)
-        };
-        if ret == 0 {
-            panic!("couldn't release context: {}",
-                   io::Error::last_os_error());
-        }
-    }
-}