Call RtlGenRandom directly in RAND_bytes. It works within the Chromium sandbox, unlike CryptAcquireContext and CryptGenRandom which requires the HCRYPTPROV be pre-warmed and held within the sandbox. Also account for the mismatch between size_t and ULONG/DWORD. See https://chromium.googlesource.com/chromium/src/+/master/base/rand_util_win.cc BUG=crbug.com/429919 Change-Id: Ia684124736c0c039ca9410509973192a597856ab Reviewed-on: https://boringssl-review.googlesource.com/2190 Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/rand/windows.c b/crypto/rand/windows.c index 967dd9b..ed6e5e9 100644 --- a/crypto/rand/windows.c +++ b/crypto/rand/windows.c
@@ -14,57 +14,36 @@ #include <openssl/rand.h> -#include <openssl/thread.h> - - #if defined(OPENSSL_WINDOWS) +#include <limits.h> #include <stdlib.h> #include <Windows.h> -#include <Wincrypt.h> -static char global_provider_init; -static HCRYPTPROV global_provider; +/* #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 + void RAND_cleanup(void) { - CRYPTO_w_lock(CRYPTO_LOCK_RAND); - CryptReleaseContext(global_provider, 0); - global_provider_init = 0; - CRYPTO_w_unlock(CRYPTO_LOCK_RAND); } int RAND_bytes(uint8_t *out, size_t requested) { - HCRYPTPROV provider = 0; - int ok; - - CRYPTO_r_lock(CRYPTO_LOCK_RAND); - if (!global_provider_init) { - CRYPTO_r_unlock(CRYPTO_LOCK_RAND); - CRYPTO_w_lock(CRYPTO_LOCK_RAND); - if (!global_provider_init) { - if (CryptAcquireContext(&global_provider, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { - global_provider_init = 1; - } + while (requested > 0) { + ULONG output_bytes_this_pass = ULONG_MAX; + if (requested < output_bytes_this_pass) { + output_bytes_this_pass = requested; } - CRYPTO_w_unlock(CRYPTO_LOCK_RAND); - CRYPTO_r_lock(CRYPTO_LOCK_RAND); + if (RtlGenRandom(out, output_bytes_this_pass) == FALSE) { + abort(); + return 0; + } + requested -= output_bytes_this_pass; + out += output_bytes_this_pass; } - - ok = global_provider_init; - provider = global_provider; - CRYPTO_r_unlock(CRYPTO_LOCK_RAND); - - if (!ok) { - abort(); - return ok; - } - - if (TRUE != CryptGenRandom(provider, requested, out)) { - abort(); - return 0; - } - return 1; }