]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Revert "convert CRYPTO_THREAD_run_once to use InitOnceExecuteOnce api"
authorTomas Mraz <tomas@openssl.foundation>
Tue, 16 Jun 2026 10:45:19 +0000 (12:45 +0200)
committerTomas Mraz <tomas@openssl.foundation>
Wed, 17 Jun 2026 12:14:51 +0000 (14:14 +0200)
This reverts commit d053fe41a4add4e55dc5633e8aef6602a6a4b90b.

Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
MergeDate: Wed Jun 17 12:14:58 2026
(Merged from https://github.com/openssl/openssl/pull/31539)

crypto/threads_win.c
include/internal/e_os.h
include/openssl/crypto.h.in
include/openssl/e_os2.h
providers/implementations/rands/seeding/rand_win.c
ssl/rio/rio_notifier.c
util/platform_symbols/windows-symbols.txt

index d803b7221d9a69261e39059183b51d05690c4e3a..4fedf24e90c0b8598567710d7b6185dd68e6ae25 100644 (file)
@@ -512,28 +512,32 @@ void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock)
     return;
 }
 
-struct init_once_cb_info {
-    void (*init)(void);
-};
-
-static BOOL CALLBACK init_wrapper(PINIT_ONCE InitOnce, PVOID param, PVOID *context)
-{
-    struct init_once_cb_info *info = (struct init_once_cb_info *)param;
-
-    info->init();
-    return TRUE;
-}
+#define ONCE_UNINITED 0
+#define ONCE_ININIT 1
+#define ONCE_DONE 2
 
+/*
+ * We don't use InitOnceExecuteOnce because that isn't available in WinXP which
+ * we still have to support.
+ */
 int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void))
 {
-    INIT_ONCE *myonce = (INIT_ONCE *)once;
-    struct init_once_cb_info info = { init };
-    BOOL bstatus;
+    LONG volatile *lock = (LONG *)once;
+    LONG result;
 
-    bstatus = InitOnceExecuteOnce(myonce, init_wrapper, (void *)&info, NULL);
-    if (bstatus == TRUE)
+    if (*lock == ONCE_DONE)
         return 1;
-    return 0;
+
+    do {
+        result = InterlockedCompareExchange(lock, ONCE_ININIT, ONCE_UNINITED);
+        if (result == ONCE_UNINITED) {
+            init();
+            *lock = ONCE_DONE;
+            return 1;
+        }
+    } while (result == ONCE_ININIT);
+
+    return (*lock == ONCE_DONE);
 }
 
 int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *))
index f0de2f363ca0b83800453c4d279f8fdb5dff17ce..3ea75209cf5ff36fd72e9d43b8489adb8c6dc252 100644 (file)
  *     0x0603 // Windows 8.1
  *     0x0A00 // Windows 10
  */
-#define _WIN32_WINNT 0x0600
+#define _WIN32_WINNT 0x0501
 #endif
 #include <windows.h>
 #include <stdio.h>
index 071b11b3bc24efdf367ecef0071c1a5ee9dfbf43..a9ade25b155498b6c95cedb6c73adbb45892579b 100644 (file)
@@ -543,8 +543,8 @@ void OPENSSL_INIT_free(OPENSSL_INIT_SETTINGS *settings);
 typedef DWORD CRYPTO_THREAD_LOCAL;
 typedef DWORD CRYPTO_THREAD_ID;
 
-typedef INIT_ONCE CRYPTO_ONCE;
-#define CRYPTO_ONCE_STATIC_INIT INIT_ONCE_STATIC_INIT
+typedef LONG CRYPTO_ONCE;
+#define CRYPTO_ONCE_STATIC_INIT 0
 #endif
 #else
 #if defined(__TANDEM) && defined(_SPT_MODEL_)
index 698f2da26bf81fadef417ce61c10639724a0d758..bacc161bd6b1fdee8aaa49e1a0d9e0082ffd9d4c 100644 (file)
@@ -58,7 +58,6 @@ extern "C" {
 #define OPENSSL_SYS_WIN32_CYGWIN
 #else
 #if defined(_WIN32) || defined(OPENSSL_SYS_WIN32)
-#include "windows.h"
 #undef OPENSSL_SYS_UNIX
 #if !defined(OPENSSL_SYS_WIN32)
 #define OPENSSL_SYS_WIN32
index 5a0815042dc5c30803a336d95d7d3fadc9be86d8..63b523b729f37f0f6d17ba3f18a88ec2051b7e7e 100644 (file)
@@ -70,7 +70,7 @@ size_t ossl_pool_acquire_entropy(RAND_POOL *pool)
     buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
     if (buffer != NULL) {
         size_t bytes = 0;
-        if (BCryptGenRandom(NULL, buffer, (ULONG)bytes_needed,
+        if (BCryptGenRandom(NULL, buffer, bytes_needed,
                 BCRYPT_USE_SYSTEM_PREFERRED_RNG)
             == STATUS_SUCCESS)
             bytes = bytes_needed;
index 9d286144068c4c12cf4470d1600aa788a93d4924..ab635aa7a0bee3f8e23c70fe484643b991dd2337 100644 (file)
@@ -31,21 +31,63 @@ static int set_cloexec(int fd)
 #if defined(OPENSSL_SYS_WINDOWS)
 
 static CRYPTO_ONCE ensure_wsa_startup_once = CRYPTO_ONCE_STATIC_INIT;
+static CRYPTO_RWLOCK *wsa_lock;
+static int wsa_started;
+static int wsa_ref;
+
+static void ossl_wsa_cleanup(void)
+{
+    if (wsa_started) {
+        wsa_started = 0;
+        WSACleanup();
+    }
+
+    CRYPTO_THREAD_lock_free(wsa_lock);
+    wsa_lock = NULL;
+}
 
 DEFINE_RUN_ONCE_STATIC(do_wsa_startup)
 {
     WORD versionreq = 0x0202; /* Version 2.2 */
     WSADATA wsadata;
 
-    if (WSAStartup(versionreq, &wsadata) != 0)
+    wsa_lock = CRYPTO_THREAD_lock_new();
+    if (wsa_lock == NULL)
         return 0;
 
+    if (WSAStartup(versionreq, &wsadata) != 0) {
+        CRYPTO_THREAD_lock_free(wsa_lock);
+        wsa_lock = NULL;
+        return 0;
+    }
+    wsa_started = 1;
+
     return 1;
 }
 
 static ossl_inline int ensure_wsa_startup(void)
 {
-    return RUN_ONCE(&ensure_wsa_startup_once, do_wsa_startup);
+    int rv, unused;
+
+    rv = RUN_ONCE(&ensure_wsa_startup_once, do_wsa_startup);
+    if (rv != 0)
+        CRYPTO_atomic_add(&wsa_ref, 1, &unused, wsa_lock);
+
+    return rv;
+}
+
+static void wsa_done(void)
+{
+    int ref;
+
+    if (wsa_lock != NULL) {
+        CRYPTO_atomic_add(&wsa_ref, -1, &ref, wsa_lock);
+        if (ref == 0) {
+            ossl_wsa_cleanup();
+            ensure_wsa_startup_once = CRYPTO_ONCE_STATIC_INIT;
+            wsa_lock = NULL;
+        }
+    }
 }
 
 #endif
@@ -146,6 +188,8 @@ int ossl_rio_notifier_init(RIO_NOTIFIER *nfy)
     if (!ensure_wsa_startup()) {
         ERR_raise_data(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR,
             "Cannot start Windows sockets");
+
+        wsa_done();
         return 0;
     }
 #endif
@@ -332,6 +376,9 @@ void ossl_rio_notifier_cleanup(RIO_NOTIFIER *nfy)
     BIO_closesocket(nfy->wfd);
     BIO_closesocket(nfy->rfd);
     nfy->rfd = nfy->wfd = -1;
+#if defined(OPENSSL_SYS_WINDOWS)
+    wsa_done();
+#endif
 }
 
 int ossl_rio_notifier_signal(RIO_NOTIFIER *nfy)
index 7ae58a3f182a1e2bab7acc6c0a0d5a6a03dc3548..0f6cc11450cd03866dc3091a81eb18bfd242ec1a 100644 (file)
@@ -1,6 +1,5 @@
 AcquireSRWLockExclusive
 AcquireSRWLockShared
-BCryptGenRandom
 CertCloseStore
 CertFindCertificateInStore
 CertFreeCertificateContext