|
| 1 | +//! # Random key generation |
| 2 | +//! |
| 3 | +//! This module wraps the RNG provided by the OS. There are a few different |
| 4 | +//! ways to interface with the OS RNG so it's worth exploring each of the options. |
| 5 | +//! Note that at the time of writing these all go through the (undocumented) |
| 6 | +//! `bcryptPrimitives.dll` but they use different route to get there. |
| 7 | +//! |
| 8 | +//! Originally we were using [`RtlGenRandom`], however that function is |
| 9 | +//! deprecated and warns it "may be altered or unavailable in subsequent versions". |
| 10 | +//! |
| 11 | +//! So we switched to [`BCryptGenRandom`] with the `BCRYPT_USE_SYSTEM_PREFERRED_RNG` |
| 12 | +//! flag to query and find the system configured RNG. However, this change caused a small |
| 13 | +//! but significant number of users to experience panics caused by a failure of |
| 14 | +//! this function. See [#94098]. |
| 15 | +//! |
| 16 | +//! The current version changes this to use the `BCRYPT_RNG_ALG_HANDLE` |
| 17 | +//! [Pseudo-handle], which gets the default RNG algorithm without querying the |
| 18 | +//! system preference thus hopefully avoiding the previous issue. |
| 19 | +//! This is only supported on Windows 10+ so a fallback is used for older versions. |
| 20 | +//! |
| 21 | +//! [#94098]: https://github.com/rust-lang/rust/issues/94098 |
| 22 | +//! [`RtlGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom |
| 23 | +//! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom |
| 24 | +//! [Pseudo-handle]: https://docs.microsoft.com/en-us/windows/win32/seccng/cng-algorithm-pseudo-handles |
1 | 25 | use crate::io;
|
2 | 26 | use crate::mem;
|
3 | 27 | use crate::ptr;
|
4 | 28 | use crate::sys::c;
|
5 | 29 |
|
| 30 | +/// Generates high quality secure random keys for use by [`HashMap`]. |
| 31 | +/// |
| 32 | +/// This is used to seed the default [`RandomState`]. |
| 33 | +/// |
| 34 | +/// [`HashMap`]: crate::collections::HashMap |
| 35 | +/// [`RandomState`]: crate::collections::hash_map::RandomState |
6 | 36 | pub fn hashmap_random_keys() -> (u64, u64) {
|
7 | 37 | let mut v = (0, 0);
|
8 | 38 | let ret = unsafe {
|
| 39 | + let size = mem::size_of_val(&v).try_into().unwrap(); |
9 | 40 | c::BCryptGenRandom(
|
10 |
| - ptr::null_mut(), |
11 |
| - &mut v as *mut _ as *mut u8, |
12 |
| - mem::size_of_val(&v) as c::ULONG, |
13 |
| - c::BCRYPT_USE_SYSTEM_PREFERRED_RNG, |
| 41 | + // BCRYPT_RNG_ALG_HANDLE is only supported in Windows 10+. |
| 42 | + // So for Windows 8.1 and Windows 7 we'll need a fallback when this fails. |
| 43 | + ptr::invalid_mut(c::BCRYPT_RNG_ALG_HANDLE), |
| 44 | + ptr::addr_of_mut!(v).cast(), |
| 45 | + size, |
| 46 | + 0, |
14 | 47 | )
|
15 | 48 | };
|
16 | 49 | if ret != 0 { fallback_rng() } else { v }
|
|
0 commit comments