summaryrefslogtreecommitdiffstats
path: root/vendor/getrandom/src/windows.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/getrandom/src/windows.rs')
-rw-r--r--vendor/getrandom/src/windows.rs23
1 files changed, 20 insertions, 3 deletions
diff --git a/vendor/getrandom/src/windows.rs b/vendor/getrandom/src/windows.rs
index 41dc37a5c..92d70429e 100644
--- a/vendor/getrandom/src/windows.rs
+++ b/vendor/getrandom/src/windows.rs
@@ -7,7 +7,7 @@
// except according to those terms.
use crate::Error;
-use core::{ffi::c_void, num::NonZeroU32, ptr};
+use core::{ffi::c_void, mem::MaybeUninit, num::NonZeroU32, ptr};
const BCRYPT_USE_SYSTEM_PREFERRED_RNG: u32 = 0x00000002;
@@ -21,20 +21,37 @@ extern "system" {
) -> u32;
}
-pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
+// Forbidden when targetting UWP
+#[cfg(not(target_vendor = "uwp"))]
+#[link(name = "advapi32")]
+extern "system" {
+ #[link_name = "SystemFunction036"]
+ fn RtlGenRandom(RandomBuffer: *mut c_void, RandomBufferLength: u32) -> u8;
+}
+
+pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
// Prevent overflow of u32
for chunk in dest.chunks_mut(u32::max_value() as usize) {
// BCryptGenRandom was introduced in Windows Vista
let ret = unsafe {
BCryptGenRandom(
ptr::null_mut(),
- chunk.as_mut_ptr(),
+ chunk.as_mut_ptr() as *mut u8,
chunk.len() as u32,
BCRYPT_USE_SYSTEM_PREFERRED_RNG,
)
};
// NTSTATUS codes use the two highest bits for severity status.
if ret >> 30 == 0b11 {
+ // Failed. Try RtlGenRandom as a fallback.
+ #[cfg(not(target_vendor = "uwp"))]
+ {
+ let ret =
+ unsafe { RtlGenRandom(chunk.as_mut_ptr() as *mut c_void, chunk.len() as u32) };
+ if ret != 0 {
+ continue;
+ }
+ }
// We zeroize the highest bit, so the error code will reside
// inside the range designated for OS codes.
let code = ret ^ (1 << 31);