Skip to content

Commit cc03782

Browse files
committedOct 21, 2017
Auto merge of #45370 - alexcrichton:update-windows-rand, r=sfackler
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-random/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]: rust-random/rand#111 (comment)
2 parents 6a136f6 + 55c0173 commit cc03782

File tree

2 files changed

+10
-46
lines changed

2 files changed

+10
-46
lines changed
 

‎src/libstd/sys/windows/c.rs

+3-15
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ pub type BOOL = c_int;
3737
pub type BYTE = u8;
3838
pub type BOOLEAN = BYTE;
3939
pub type GROUP = c_uint;
40-
pub type LONG_PTR = isize;
4140
pub type LARGE_INTEGER = c_longlong;
4241
pub type LONG = c_long;
4342
pub type UINT = c_uint;
@@ -46,7 +45,6 @@ pub type USHORT = c_ushort;
4645
pub type SIZE_T = usize;
4746
pub type WORD = u16;
4847
pub type CHAR = c_char;
49-
pub type HCRYPTPROV = LONG_PTR;
5048
pub type ULONG_PTR = usize;
5149
pub type ULONG = c_ulong;
5250
#[cfg(target_arch = "x86_64")]
@@ -288,10 +286,6 @@ pub const IMAGE_FILE_MACHINE_I386: DWORD = 0x014c;
288286
#[cfg(feature = "backtrace")]
289287
pub const IMAGE_FILE_MACHINE_AMD64: DWORD = 0x8664;
290288

291-
pub const PROV_RSA_FULL: DWORD = 1;
292-
pub const CRYPT_SILENT: DWORD = 64;
293-
pub const CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
294-
295289
pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
296290
pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
297291
pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15;
@@ -1136,15 +1130,6 @@ extern "system" {
11361130
pub fn GetProcAddress(handle: HMODULE,
11371131
name: LPCSTR) -> *mut c_void;
11381132
pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
1139-
pub fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
1140-
pszContainer: LPCSTR,
1141-
pszProvider: LPCSTR,
1142-
dwProvType: DWORD,
1143-
dwFlags: DWORD) -> BOOL;
1144-
pub fn CryptGenRandom(hProv: HCRYPTPROV,
1145-
dwLen: DWORD,
1146-
pbBuffer: *mut BYTE) -> BOOL;
1147-
pub fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
11481133

11491134
pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME);
11501135

@@ -1175,6 +1160,9 @@ extern "system" {
11751160
writefds: *mut fd_set,
11761161
exceptfds: *mut fd_set,
11771162
timeout: *const timeval) -> c_int;
1163+
1164+
#[link_name = "SystemFunction036"]
1165+
pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
11781166
}
11791167

11801168
// Functions that aren't available on every version of Windows that we support,

‎src/libstd/sys/windows/rand.rs

+7-31
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,12 @@ use mem;
1414
use rand::Rng;
1515
use sys::c;
1616

17-
pub struct OsRng {
18-
hcryptprov: c::HCRYPTPROV
19-
}
17+
pub struct OsRng;
2018

2119
impl OsRng {
2220
/// Create a new `OsRng`.
2321
pub fn new() -> io::Result<OsRng> {
24-
let mut hcp = 0;
25-
let ret = unsafe {
26-
c::CryptAcquireContextA(&mut hcp, 0 as c::LPCSTR, 0 as c::LPCSTR,
27-
c::PROV_RSA_FULL,
28-
c::CRYPT_VERIFYCONTEXT | c::CRYPT_SILENT)
29-
};
30-
31-
if ret == 0 {
32-
Err(io::Error::last_os_error())
33-
} else {
34-
Ok(OsRng { hcryptprov: hcp })
35-
}
22+
Ok(OsRng)
3623
}
3724
}
3825

@@ -42,18 +29,19 @@ impl Rng for OsRng {
4229
self.fill_bytes(&mut v);
4330
unsafe { mem::transmute(v) }
4431
}
32+
4533
fn next_u64(&mut self) -> u64 {
4634
let mut v = [0; 8];
4735
self.fill_bytes(&mut v);
4836
unsafe { mem::transmute(v) }
4937
}
38+
5039
fn fill_bytes(&mut self, v: &mut [u8]) {
51-
// CryptGenRandom takes a DWORD (u32) for the length so we need to
40+
// RtlGenRandom takes an ULONG (u32) for the length so we need to
5241
// split up the buffer.
53-
for slice in v.chunks_mut(<c::DWORD>::max_value() as usize) {
42+
for slice in v.chunks_mut(<c::ULONG>::max_value() as usize) {
5443
let ret = unsafe {
55-
c::CryptGenRandom(self.hcryptprov, slice.len() as c::DWORD,
56-
slice.as_mut_ptr())
44+
c::RtlGenRandom(slice.as_mut_ptr(), slice.len() as c::ULONG)
5745
};
5846
if ret == 0 {
5947
panic!("couldn't generate random bytes: {}",
@@ -62,15 +50,3 @@ impl Rng for OsRng {
6250
}
6351
}
6452
}
65-
66-
impl Drop for OsRng {
67-
fn drop(&mut self) {
68-
let ret = unsafe {
69-
c::CryptReleaseContext(self.hcryptprov, 0)
70-
};
71-
if ret == 0 {
72-
panic!("couldn't release context: {}",
73-
io::Error::last_os_error());
74-
}
75-
}
76-
}

0 commit comments

Comments
 (0)
Please sign in to comment.