Use ProcessPrng instead of RtlGenRandom on Windows
The Windows system RNG[1] lives in bcryptprimitives.dll which exports the function ProcessPrng[2] to supply random bytes from its internal generators. These are seeded and reseeded from the operating system using a device connection to \\Device\CNG which is opened when bcryptprimitives.dll is first loaded. After this CL boringssl calls ProcessPrng() directly. Before this CL boringssl got its system randomness (on non-UWP desktop Windows) from calls to RtlGenRandom[3]. This function is undocumented and unsupported, but has always been available by linking to SystemFunction036 in advadpi32.dll. In Windows 10 and later, this export simply forwards to cryptbase.dll!SystemFunction036 which calls ProcessPrng() directly. cryptbase!SystemFunction036 decompiled: ``` BOOLEAN SystemFunction036(PVOID RandomBuffer,ULONG RandomBufferLength) { BOOL retval; retval = ProcessPrng(RandomBuffer,RandomBufferLength); return retval != 0; } ``` Loading cryptbase.dll has the side effect of opening a device handle to \\Device\KsecDD which is not used by boringssl's random number wrappers. Calling ProcessPrng() directly allows sandboxed programs such as Chromium to avoid having this handle if they do not need it. ProcessPrng() also takes a size_t length rather than a u32 length, allowing some simplification of the calling code. After this CL we require bcryptprimitives to be loaded before the first call to CRYPTO_srand(). Applications using the library should either load the module themselves or call CRYPTO_pre_sandbox_init(). Before this CL boringssl required that advapi32, cryptbase and bcryptprimitives were all loaded so this should not represent a breaking change. [1] https://learn.microsoft.com/en-us/windows/win32/seccng/processprng [2] https://download.microsoft.com/download/1/c/9/1c9813b8-089c-4fef-b2ad-ad80e79403ba/Whitepaper%20-%20The%20Windows%2010%20random%20number%20generation%20infrastructure.pdf [3] https://docs.google.com/document/d/13n1t5ak0yofzcadQCF7Ew5TewSUkNfQ3n-IYodjeRYc/edit Bug: chromium:74242 Change-Id: Ifb1d6ef1a4539ff6e9a2c36cc119b7700ca2be8f Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60825 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: David Benjamin <davidben@google.com>
This commit is contained in:
parent
bc97b7a8e1
commit
e79649ba4d
@ -70,11 +70,15 @@ void CRYPTO_sysrand(uint8_t *buf, size_t len);
|
||||
// depending on the vendor's configuration.
|
||||
void CRYPTO_sysrand_for_seed(uint8_t *buf, size_t len);
|
||||
|
||||
#if defined(OPENSSL_URANDOM)
|
||||
#if defined(OPENSSL_URANDOM) || defined(OPENSSL_WINDOWS)
|
||||
// CRYPTO_init_sysrand initializes long-lived resources needed to draw entropy
|
||||
// from the operating system.
|
||||
void CRYPTO_init_sysrand(void);
|
||||
#else
|
||||
OPENSSL_INLINE void CRYPTO_init_sysrand(void) {}
|
||||
#endif // defined(OPENSSL_URANDOM) || defined(OPENSSL_WINDOWS)
|
||||
|
||||
#if defined(OPENSSL_URANDOM)
|
||||
// CRYPTO_sysrand_if_available fills |len| bytes at |buf| with entropy from the
|
||||
// operating system, or early /dev/urandom data, and returns 1, _if_ the entropy
|
||||
// pool is initialized or if getrandom() is not available and not in FIPS mode.
|
||||
@ -82,13 +86,11 @@ void CRYPTO_init_sysrand(void);
|
||||
// return 0.
|
||||
int CRYPTO_sysrand_if_available(uint8_t *buf, size_t len);
|
||||
#else
|
||||
OPENSSL_INLINE void CRYPTO_init_sysrand(void) {}
|
||||
|
||||
OPENSSL_INLINE int CRYPTO_sysrand_if_available(uint8_t *buf, size_t len) {
|
||||
CRYPTO_sysrand(buf, len);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
#endif // defined(OPENSSL_URANDOM)
|
||||
|
||||
// rand_fork_unsafe_buffering_enabled returns whether fork-unsafe buffering has
|
||||
// been enabled via |RAND_enable_fork_unsafe_buffering|.
|
||||
|
@ -27,43 +27,63 @@ OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
#include <bcrypt.h>
|
||||
OPENSSL_MSVC_PRAGMA(comment(lib, "bcrypt.lib"))
|
||||
#else
|
||||
// #define needed to link in RtlGenRandom(), a.k.a. SystemFunction036. See the
|
||||
// "Community Additions" comment on MSDN here:
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx
|
||||
#define SystemFunction036 NTAPI SystemFunction036
|
||||
#include <ntsecapi.h>
|
||||
#undef SystemFunction036
|
||||
#endif // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
|
||||
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
|
||||
#include "../fipsmodule/rand/internal.h"
|
||||
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
|
||||
!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
void CRYPTO_init_sysrand(void) {}
|
||||
#else
|
||||
// See: https://learn.microsoft.com/en-us/windows/win32/seccng/processprng
|
||||
typedef BOOL (WINAPI *ProcessPrngFunction)(PBYTE pbData, SIZE_T cbData);
|
||||
static ProcessPrngFunction g_processprng_fn = NULL;
|
||||
|
||||
static void init_processprng(void) {
|
||||
HMODULE hmod = LoadLibraryW(L"bcryptprimitives");
|
||||
if (hmod == NULL) {
|
||||
abort();
|
||||
}
|
||||
g_processprng_fn = (ProcessPrngFunction)GetProcAddress(hmod, "ProcessPrng");
|
||||
if (g_processprng_fn == NULL) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void CRYPTO_init_sysrand(void) {
|
||||
static CRYPTO_once_t once = CRYPTO_ONCE_INIT;
|
||||
CRYPTO_once(&once, init_processprng);
|
||||
}
|
||||
#endif // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
|
||||
|
||||
void CRYPTO_sysrand(uint8_t *out, size_t requested) {
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
|
||||
!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
while (requested > 0) {
|
||||
ULONG output_bytes_this_pass = ULONG_MAX;
|
||||
if (requested < output_bytes_this_pass) {
|
||||
output_bytes_this_pass = (ULONG)requested;
|
||||
}
|
||||
// On non-UWP configurations, use RtlGenRandom instead of BCryptGenRandom
|
||||
// to avoid accessing resources that may be unavailable inside the
|
||||
// Chromium sandbox. See https://crbug.com/boringssl/307
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
|
||||
!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
if (!BCRYPT_SUCCESS(BCryptGenRandom(
|
||||
/*hAlgorithm=*/NULL, out, output_bytes_this_pass,
|
||||
BCRYPT_USE_SYSTEM_PREFERRED_RNG))) {
|
||||
#else
|
||||
if (RtlGenRandom(out, output_bytes_this_pass) == FALSE) {
|
||||
#endif // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
|
||||
abort();
|
||||
}
|
||||
requested -= output_bytes_this_pass;
|
||||
out += output_bytes_this_pass;
|
||||
}
|
||||
return;
|
||||
#else
|
||||
CRYPTO_init_sysrand();
|
||||
// On non-UWP configurations, use ProcessPrng instead of BCryptGenRandom
|
||||
// to avoid accessing resources that may be unavailable inside the
|
||||
// Chromium sandbox. See https://crbug.com/74242
|
||||
if (!g_processprng_fn(out, requested)) {
|
||||
abort();
|
||||
}
|
||||
#endif // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
|
||||
}
|
||||
|
||||
void CRYPTO_sysrand_for_seed(uint8_t *out, size_t requested) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user