bpo-44611: Use BCryptGenRandom instead of CryptGenRandom on Windows (GH-27168)

This commit is contained in:
Dong-hee Na 2021-07-23 14:04:30 +00:00 committed by GitHub
parent a4760cc32d
commit 906fe47083
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 19 additions and 41 deletions

View File

@ -198,6 +198,14 @@ math
Dickinson in :issue:`44339`.)
os
--
* On Windows, :func:`os.urandom`: uses BCryptGenRandom API instead of CryptGenRandom API
which is deprecated from Microsoft Windows API.
(Contributed by Dong-hee Na in :issue:`44611`.)
sqlite3
-------

View File

@ -0,0 +1,2 @@
On Windows, :func:`os.urandom`: uses BCryptGenRandom API instead of CryptGenRandom API
which is deprecated from Microsoft Windows API. Patch by Dong-hee Na.

View File

@ -106,7 +106,7 @@
<PreprocessorDefinitions Condition="$(IncludeExternals)">_Py_HAVE_ZLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>version.lib;shlwapi.lib;ws2_32.lib;pathcch.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>version.lib;shlwapi.lib;ws2_32.lib;pathcch.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>

View File

@ -2,9 +2,7 @@
#include "pycore_initconfig.h"
#ifdef MS_WINDOWS
# include <windows.h>
/* All sample MSDN wincrypt programs include the header below. It is at least
* required with Min GW. */
# include <wincrypt.h>
# include <bcrypt.h>
#else
# include <fcntl.h>
# ifdef HAVE_SYS_STAT_H
@ -42,43 +40,18 @@ static int _Py_HashSecret_Initialized = 0;
#endif
#ifdef MS_WINDOWS
static HCRYPTPROV hCryptProv = 0;
static int
win32_urandom_init(int raise)
{
/* Acquire context */
if (!CryptAcquireContextW(&hCryptProv, NULL, NULL,
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
goto error;
return 0;
error:
if (raise) {
PyErr_SetFromWindowsErr(0);
}
return -1;
}
/* Fill buffer with size pseudo-random bytes generated by the Windows CryptoGen
API. Return 0 on success, or raise an exception and return -1 on error. */
static int
win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
{
if (hCryptProv == 0)
{
if (win32_urandom_init(raise) == -1) {
return -1;
}
}
while (size > 0)
{
DWORD chunk = (DWORD)Py_MIN(size, PY_DWORD_MAX);
if (!CryptGenRandom(hCryptProv, chunk, buffer))
{
/* CryptGenRandom() failed */
NTSTATUS status = BCryptGenRandom(NULL, buffer, chunk, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
if (!BCRYPT_SUCCESS(status)) {
/* BCryptGenRandom() failed */
if (raise) {
PyErr_SetFromWindowsErr(0);
}
@ -458,7 +431,7 @@ lcg_urandom(unsigned int x0, unsigned char *buffer, size_t size)
Used sources of entropy ordered by preference, preferred source first:
- CryptGenRandom() on Windows
- BCryptGenRandom() on Windows
- getrandom() function (ex: Linux and Solaris): call py_getrandom()
- getentropy() function (ex: OpenBSD): call py_getentropy()
- /dev/urandom device
@ -612,12 +585,7 @@ _Py_HashRandomization_Init(const PyConfig *config)
void
_Py_HashRandomization_Fini(void)
{
#ifdef MS_WINDOWS
if (hCryptProv) {
CryptReleaseContext(hCryptProv, 0);
hCryptProv = 0;
}
#else
#ifndef MS_WINDOWS
dev_urandom_close();
#endif
}