Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std: Update randomness implementation on Windows #45370

Merged
merged 1 commit into from
Oct 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 3 additions & 15 deletions src/libstd/sys/windows/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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")]
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -1175,6 +1160,9 @@ extern "system" {
writefds: *mut fd_set,
exceptfds: *mut fd_set,
timeout: *const timeval) -> c_int;

#[link_name = "SystemFunction036"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh of course, SystemFunction036 😨

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

um\NTSecAPI.h
#define RtlGenRandom SystemFunction036

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a comment about why its used.

pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
}

// Functions that aren't available on every version of Windows that we support,
Expand Down
38 changes: 7 additions & 31 deletions src/libstd/sys/windows/rand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand All @@ -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: {}",
Expand All @@ -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());
}
}
}