[Python-checkins] bpo-44611: Use BCryptGenRandom instead of CryptGenRandom on Windows (GH-27168)

corona10 webhook-mailer at python.org
Fri Jul 23 10:04:39 EDT 2021


https://github.com/python/cpython/commit/906fe47083bc9ab7ed2b70c99c1b0daad021f126
commit: 906fe47083bc9ab7ed2b70c99c1b0daad021f126
branch: main
author: Dong-hee Na <donghee.na at python.org>
committer: corona10 <donghee.na92 at gmail.com>
date: 2021-07-23T23:04:30+09:00
summary:

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

files:
A Misc/NEWS.d/next/Core and Builtins/2021-07-16-01-01-11.bpo-44611.LcfHN-.rst
M Doc/whatsnew/3.11.rst
M PCbuild/pythoncore.vcxproj
M Python/bootstrap_hash.c

diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst
index 7d2e4e81269e93..190c422d2a5caf 100644
--- a/Doc/whatsnew/3.11.rst
+++ b/Doc/whatsnew/3.11.rst
@@ -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
 -------
 
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-07-16-01-01-11.bpo-44611.LcfHN-.rst b/Misc/NEWS.d/next/Core and Builtins/2021-07-16-01-01-11.bpo-44611.LcfHN-.rst
new file mode 100644
index 00000000000000..1cc8b127382390
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2021-07-16-01-01-11.bpo-44611.LcfHN-.rst	
@@ -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.
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index 7cd3c21fbf691c..7b2a9b5913bc8d 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -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>
diff --git a/Python/bootstrap_hash.c b/Python/bootstrap_hash.c
index a212f69870ed10..144f7cb4a218a8 100644
--- a/Python/bootstrap_hash.c
+++ b/Python/bootstrap_hash.c
@@ -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
@@ -25,7 +23,7 @@
 #  include <sanitizer/msan_interface.h>
 #endif
 
-#if defined(__APPLE__) && defined(__has_builtin) 
+#if defined(__APPLE__) && defined(__has_builtin)
 #  if __has_builtin(__builtin_available)
 #    define HAVE_GETENTRYPY_GETRANDOM_RUNTIME __builtin_available(macOS 10.12, iOS 10.10, tvOS 10.0, watchOS 3.0, *)
 #  endif
@@ -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);
             }
@@ -221,7 +194,7 @@ py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise)
 
 #if defined(__APPLE__) && defined(__has_attribute) && __has_attribute(availability)
 static int
-py_getentropy(char *buffer, Py_ssize_t size, int raise) 
+py_getentropy(char *buffer, Py_ssize_t size, int raise)
         __attribute__((availability(macos,introduced=10.12)))
         __attribute__((availability(ios,introduced=10.0)))
         __attribute__((availability(tvos,introduced=10.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
 }



More information about the Python-checkins mailing list