21 #include <winpr/config.h>
23 #include <winpr/crt.h>
24 #include <winpr/synch.h>
25 #include <winpr/ssl.h>
26 #include <winpr/thread.h>
27 #include <winpr/crypto.h>
31 #include <openssl/ssl.h>
32 #include <openssl/err.h>
34 #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
35 #include <openssl/provider.h>
39 #define TAG WINPR_TAG("utils.ssl")
41 static BOOL g_winpr_openssl_initialized_by_winpr = FALSE;
43 #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
44 static OSSL_PROVIDER* s_winpr_openssl_provider_fips = NULL;
45 static OSSL_PROVIDER* s_winpr_openssl_provider_legacy = NULL;
46 static OSSL_PROVIDER* s_winpr_openssl_provider_default = NULL;
55 #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
57 #define WINPR_OPENSSL_LOCKING_REQUIRED 1
59 static int g_winpr_openssl_num_locks = 0;
60 static HANDLE* g_winpr_openssl_locks = NULL;
62 struct CRYPTO_dynlock_value
67 #if (OPENSSL_VERSION_NUMBER < 0x10000000L) || defined(LIBRESSL_VERSION_NUMBER)
68 static unsigned long _winpr_openssl_id(
void)
70 return (
unsigned long)GetCurrentThreadId();
74 static void _winpr_openssl_locking(
int mode,
int type,
const char* file,
int line)
76 if (mode & CRYPTO_LOCK)
78 (void)WaitForSingleObject(g_winpr_openssl_locks[type], INFINITE);
82 (void)ReleaseMutex(g_winpr_openssl_locks[type]);
86 static struct CRYPTO_dynlock_value* _winpr_openssl_dynlock_create(
const char* file,
int line)
88 struct CRYPTO_dynlock_value* dynlock;
90 if (!(dynlock = (
struct CRYPTO_dynlock_value*)malloc(
sizeof(
struct CRYPTO_dynlock_value))))
93 if (!(dynlock->mutex = CreateMutex(NULL, FALSE, NULL)))
102 static void _winpr_openssl_dynlock_lock(
int mode,
struct CRYPTO_dynlock_value* dynlock,
103 const char* file,
int line)
105 if (mode & CRYPTO_LOCK)
107 (void)WaitForSingleObject(dynlock->mutex, INFINITE);
111 (void)ReleaseMutex(dynlock->mutex);
115 static void _winpr_openssl_dynlock_destroy(
struct CRYPTO_dynlock_value* dynlock,
const char* file,
118 (void)CloseHandle(dynlock->mutex);
122 static BOOL _winpr_openssl_initialize_locking(
void)
128 if (CRYPTO_get_locking_callback())
130 WLog_WARN(TAG,
"OpenSSL static locking callback is already set");
134 if ((count = CRYPTO_num_locks()) > 0)
138 if (!(locks = calloc(count,
sizeof(HANDLE))))
140 WLog_ERR(TAG,
"error allocating lock table");
144 for (
int i = 0; i < count; i++)
146 if (!(locks[i] = CreateMutex(NULL, FALSE, NULL)))
148 WLog_ERR(TAG,
"error creating lock #%d", i);
153 (void)CloseHandle(locks[i]);
161 g_winpr_openssl_locks = locks;
162 g_winpr_openssl_num_locks = count;
163 CRYPTO_set_locking_callback(_winpr_openssl_locking);
169 if (CRYPTO_get_dynlock_create_callback() || CRYPTO_get_dynlock_lock_callback() ||
170 CRYPTO_get_dynlock_destroy_callback())
172 WLog_WARN(TAG,
"dynamic locking callbacks are already set");
176 CRYPTO_set_dynlock_create_callback(_winpr_openssl_dynlock_create);
177 CRYPTO_set_dynlock_lock_callback(_winpr_openssl_dynlock_lock);
178 CRYPTO_set_dynlock_destroy_callback(_winpr_openssl_dynlock_destroy);
182 #if (OPENSSL_VERSION_NUMBER < 0x10000000L) || defined(LIBRESSL_VERSION_NUMBER)
184 if (CRYPTO_get_id_callback())
186 WLog_WARN(TAG,
"OpenSSL id_callback is already set");
190 CRYPTO_set_id_callback(_winpr_openssl_id);
197 static BOOL _winpr_openssl_cleanup_locking(
void)
200 if (CRYPTO_get_locking_callback() == _winpr_openssl_locking)
202 CRYPTO_set_locking_callback(NULL);
204 for (
int i = 0; i < g_winpr_openssl_num_locks; i++)
206 (void)CloseHandle(g_winpr_openssl_locks[i]);
209 g_winpr_openssl_num_locks = 0;
210 free(g_winpr_openssl_locks);
211 g_winpr_openssl_locks = NULL;
216 if (CRYPTO_get_dynlock_create_callback() == _winpr_openssl_dynlock_create)
218 CRYPTO_set_dynlock_create_callback(NULL);
221 if (CRYPTO_get_dynlock_lock_callback() == _winpr_openssl_dynlock_lock)
223 CRYPTO_set_dynlock_lock_callback(NULL);
226 if (CRYPTO_get_dynlock_destroy_callback() == _winpr_openssl_dynlock_destroy)
228 CRYPTO_set_dynlock_destroy_callback(NULL);
231 #if (OPENSSL_VERSION_NUMBER < 0x10000000L) || defined(LIBRESSL_VERSION_NUMBER)
233 if (CRYPTO_get_id_callback() == _winpr_openssl_id)
235 CRYPTO_set_id_callback(NULL);
244 static BOOL winpr_enable_fips(DWORD flags)
246 if (flags & WINPR_SSL_INIT_ENABLE_FIPS)
248 #if (OPENSSL_VERSION_NUMBER < 0x10001000L) || defined(LIBRESSL_VERSION_NUMBER)
249 WLog_ERR(TAG,
"Openssl fips mode not available on openssl versions less than 1.0.1!");
252 WLog_DBG(TAG,
"Ensuring openssl fips mode is enabled");
254 #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
255 s_winpr_openssl_provider_fips = OSSL_PROVIDER_load(NULL,
"fips");
256 if (s_winpr_openssl_provider_fips == NULL)
258 WLog_WARN(TAG,
"OpenSSL FIPS provider failled to load");
260 if (!EVP_default_properties_is_fips_enabled(NULL))
262 if (FIPS_mode() != 1)
265 #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
266 if (EVP_set_default_properties(NULL,
"fips=yes"))
268 if (FIPS_mode_set(1))
270 WLog_INFO(TAG,
"Openssl fips mode enabled!");
273 WLog_ERR(TAG,
"Openssl fips mode enable failed!");
284 static void winpr_openssl_cleanup(
void)
286 winpr_CleanupSSL(WINPR_SSL_INIT_DEFAULT);
289 static BOOL CALLBACK winpr_openssl_initialize(
PINIT_ONCE once, PVOID param, PVOID* context)
291 DWORD flags = param ? *(PDWORD)param : WINPR_SSL_INIT_DEFAULT;
293 if (flags & WINPR_SSL_INIT_ALREADY_INITIALIZED)
298 #ifdef WINPR_OPENSSL_LOCKING_REQUIRED
300 if (flags & WINPR_SSL_INIT_ENABLE_LOCKING)
302 if (!_winpr_openssl_initialize_locking())
310 #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
311 SSL_load_error_strings();
314 OpenSSL_add_all_digests();
315 OpenSSL_add_all_ciphers();
318 if (OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
319 OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS |
320 OPENSSL_INIT_ENGINE_ALL_BUILTIN,
326 #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
328 s_winpr_openssl_provider_legacy = OSSL_PROVIDER_load(NULL,
"legacy");
329 if (s_winpr_openssl_provider_legacy == NULL)
331 WLog_WARN(TAG,
"OpenSSL LEGACY provider failed to load, no md4 support available!");
333 s_winpr_openssl_provider_default = OSSL_PROVIDER_load(NULL,
"default");
334 if (s_winpr_openssl_provider_default == NULL)
336 WLog_WARN(TAG,
"OpenSSL DEFAULT provider failed to load");
340 (void)atexit(winpr_openssl_cleanup);
341 g_winpr_openssl_initialized_by_winpr = TRUE;
347 BOOL winpr_InitializeSSL(DWORD flags)
349 static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
351 if (!InitOnceExecuteOnce(&once, winpr_openssl_initialize, &flags, NULL))
354 return winpr_enable_fips(flags);
357 #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
358 static int unload(OSSL_PROVIDER* provider,
void* data)
362 const char* name = OSSL_PROVIDER_get0_name(provider);
366 OSSL_LIB_CTX* ctx = OSSL_LIB_CTX_get0_global_default();
367 const int rc = OSSL_PROVIDER_available(ctx, name);
370 OSSL_PROVIDER_unload(provider);
375 BOOL winpr_CleanupSSL(DWORD flags)
377 if (flags & WINPR_SSL_CLEANUP_GLOBAL)
379 if (!g_winpr_openssl_initialized_by_winpr)
381 WLog_WARN(TAG,
"ssl was not initialized by winpr");
385 g_winpr_openssl_initialized_by_winpr = FALSE;
386 #ifdef WINPR_OPENSSL_LOCKING_REQUIRED
387 _winpr_openssl_cleanup_locking();
389 #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
390 CRYPTO_cleanup_all_ex_data();
394 #ifdef WINPR_OPENSSL_LOCKING_REQUIRED
395 flags |= WINPR_SSL_CLEANUP_THREAD;
399 #ifdef WINPR_OPENSSL_LOCKING_REQUIRED
401 if (flags & WINPR_SSL_CLEANUP_THREAD)
403 #if (OPENSSL_VERSION_NUMBER < 0x10000000L) || defined(LIBRESSL_VERSION_NUMBER)
406 ERR_remove_thread_state(NULL);
411 #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
412 OSSL_LIB_CTX* ctx = OSSL_LIB_CTX_get0_global_default();
413 OSSL_PROVIDER_do_all(ctx, unload, NULL);
419 BOOL winpr_FIPSMode(
void)
421 #if (OPENSSL_VERSION_NUMBER < 0x10001000L) || defined(LIBRESSL_VERSION_NUMBER)
423 #elif defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
424 return (EVP_default_properties_is_fips_enabled(NULL) == 1);
426 return (FIPS_mode() == 1);
432 BOOL winpr_InitializeSSL(DWORD flags)
437 BOOL winpr_CleanupSSL(DWORD flags)
442 BOOL winpr_FIPSMode(
void)