| /* |
| * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. |
| * |
| * Licensed under the Apache License 2.0 (the "License"). You may not use |
| * this file except in compliance with the License. You can obtain a copy |
| * in the file LICENSE in the source distribution or at |
| * https://www.openssl.org/source/license.html |
| */ |
| |
| #include <stdio.h> |
| #include <openssl/opensslv.h> |
| #include "internal/thread_once.h" |
| #include "internal/cryptlib.h" |
| #include "internal/e_os.h" |
| |
| #if defined(_WIN32) && defined(OSSL_WINCTX) |
| |
| # define TOSTR(x) #x |
| # define MAKESTR(x) TOSTR(x) |
| # define NOQUOTE(x) x |
| # if defined(OSSL_WINCTX) |
| # define REGISTRY_KEY "SOFTWARE\\WOW6432Node\\OpenSSL" "-" MAKESTR(OPENSSL_VERSION_MAJOR) "." MAKESTR(OPENSSL_VERSION_MINOR) "-" MAKESTR(OSSL_WINCTX) |
| # endif |
| |
| /** |
| * @brief The directory where OpenSSL is installed. |
| */ |
| static char openssldir[MAX_PATH + 1]; |
| |
| /** |
| * @brief The pointer to the openssldir buffer |
| */ |
| static char *openssldirptr = NULL; |
| |
| /** |
| * @brief The directory where OpenSSL engines are located. |
| */ |
| |
| static char enginesdir[MAX_PATH + 1]; |
| |
| /** |
| * @brief The pointer to the enginesdir buffer |
| */ |
| static char *enginesdirptr = NULL; |
| |
| /** |
| * @brief The directory where OpenSSL modules are located. |
| */ |
| static char modulesdir[MAX_PATH + 1]; |
| |
| /** |
| * @brief The pointer to the modulesdir buffer |
| */ |
| static char *modulesdirptr = NULL; |
| |
| /** |
| * @brief Get the list of Windows registry directories. |
| * |
| * This function retrieves a list of Windows registry directories. |
| * |
| * @return A pointer to a char array containing the registry directories. |
| */ |
| static char *get_windows_regdirs(char *dst, DWORD dstsizebytes, LPCWSTR valuename) |
| { |
| char *retval = NULL; |
| # ifdef REGISTRY_KEY |
| DWORD keysizebytes; |
| DWORD ktype; |
| HKEY hkey; |
| LSTATUS ret; |
| DWORD index = 0; |
| LPCWSTR tempstr = NULL; |
| |
| ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, |
| TEXT(REGISTRY_KEY), KEY_WOW64_32KEY, |
| KEY_QUERY_VALUE, &hkey); |
| if (ret != ERROR_SUCCESS) |
| goto out; |
| |
| /* Always use wide call so we can avoid extra encoding conversions on the output */ |
| ret = RegQueryValueExW(hkey, valuename, NULL, &ktype, NULL, |
| &keysizebytes); |
| if (ret != ERROR_SUCCESS) |
| goto out; |
| if (ktype != REG_EXPAND_SZ && ktype != REG_SZ) |
| goto out; |
| if (keysizebytes > MAX_PATH * sizeof(WCHAR)) |
| goto out; |
| |
| /* |
| * RegQueryValueExW does not guarantee the buffer is null terminated, |
| * so we make space for one in the allocation |
| */ |
| tempstr = OPENSSL_zalloc(keysizebytes + sizeof(WCHAR)); |
| |
| if (tempstr == NULL) |
| goto out; |
| |
| if (RegQueryValueExW(hkey, valuename, |
| NULL, &ktype, (LPBYTE)tempstr, &keysizebytes) != ERROR_SUCCESS) |
| goto out; |
| |
| if (!WideCharToMultiByte(CP_UTF8, 0, tempstr, -1, dst, dstsizebytes, |
| NULL, NULL)) |
| goto out; |
| |
| retval = dst; |
| out: |
| OPENSSL_free(tempstr); |
| RegCloseKey(hkey); |
| # endif /* REGISTRY_KEY */ |
| return retval; |
| } |
| |
| static CRYPTO_ONCE defaults_setup_init = CRYPTO_ONCE_STATIC_INIT; |
| |
| /** |
| * @brief Function to setup default values to run once. |
| * Only used in Windows environments. Does run time initialization |
| * of openssldir/modulesdir/enginesdir from the registry |
| */ |
| DEFINE_RUN_ONCE_STATIC(do_defaults_setup) |
| { |
| get_windows_regdirs(openssldir, sizeof(openssldir), L"OPENSSLDIR"); |
| get_windows_regdirs(enginesdir, sizeof(enginesdir), L"ENGINESDIR"); |
| get_windows_regdirs(modulesdir, sizeof(modulesdir), L"MODULESDIR"); |
| |
| /* |
| * Set our pointers only if the directories are fetched properly |
| */ |
| if (strlen(openssldir) > 0) |
| openssldirptr = openssldir; |
| |
| if (strlen(enginesdir) > 0) |
| enginesdirptr = enginesdir; |
| |
| if (strlen(modulesdir) > 0) |
| modulesdirptr = modulesdir; |
| |
| return 1; |
| } |
| #endif /* defined(_WIN32) && defined(OSSL_WINCTX) */ |
| |
| /** |
| * @brief Get the directory where OpenSSL is installed. |
| * |
| * @return A pointer to a string containing the OpenSSL directory path. |
| */ |
| const char *ossl_get_openssldir(void) |
| { |
| #if defined(_WIN32) && defined (OSSL_WINCTX) |
| if (!RUN_ONCE(&defaults_setup_init, do_defaults_setup)) |
| return NULL; |
| return (const char *)openssldirptr; |
| # else |
| return OPENSSLDIR; |
| #endif |
| } |
| |
| /** |
| * @brief Get the directory where OpenSSL engines are located. |
| * |
| * @return A pointer to a string containing the engines directory path. |
| */ |
| const char *ossl_get_enginesdir(void) |
| { |
| #if defined(_WIN32) && defined (OSSL_WINCTX) |
| if (!RUN_ONCE(&defaults_setup_init, do_defaults_setup)) |
| return NULL; |
| return (const char *)enginesdirptr; |
| #else |
| return ENGINESDIR; |
| #endif |
| } |
| |
| /** |
| * @brief Get the directory where OpenSSL modules are located. |
| * |
| * @return A pointer to a string containing the modules directory path. |
| */ |
| const char *ossl_get_modulesdir(void) |
| { |
| #if defined(_WIN32) && defined(OSSL_WINCTX) |
| if (!RUN_ONCE(&defaults_setup_init, do_defaults_setup)) |
| return NULL; |
| return (const char *)modulesdirptr; |
| #else |
| return MODULESDIR; |
| #endif |
| } |
| |
| /** |
| * @brief Get the build time defined windows installer context |
| * |
| * @return A char pointer to a string representing the windows install context |
| */ |
| const char *ossl_get_wininstallcontext(void) |
| { |
| #if defined(_WIN32) && defined (OSSL_WINCTX) |
| return MAKESTR(OSSL_WINCTX); |
| #else |
| return "Undefined"; |
| #endif |
| } |