/src/openssl/crypto/defaults.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. |
3 | | * |
4 | | * Licensed under the Apache License 2.0 (the "License"). You may not use |
5 | | * this file except in compliance with the License. You can obtain a copy |
6 | | * in the file LICENSE in the source distribution or at |
7 | | * https://www.openssl.org/source/license.html |
8 | | */ |
9 | | |
10 | | #include <stdio.h> |
11 | | #include <openssl/opensslv.h> |
12 | | #include "internal/thread_once.h" |
13 | | #include "internal/cryptlib.h" |
14 | | #include "internal/e_os.h" |
15 | | |
16 | | #if defined(_WIN32) && defined(OSSL_WINCTX) |
17 | | |
18 | | #define TOSTR(x) #x |
19 | | #define MAKESTR(x) TOSTR(x) |
20 | | #define NOQUOTE(x) x |
21 | | #if defined(OSSL_WINCTX) |
22 | | #define REGISTRY_KEY "SOFTWARE\\WOW6432Node\\OpenSSL" \ |
23 | | "-" MAKESTR(OPENSSL_VERSION_MAJOR) "." MAKESTR(OPENSSL_VERSION_MINOR) "-" MAKESTR(OSSL_WINCTX) |
24 | | #endif |
25 | | |
26 | | /** |
27 | | * @brief The directory where OpenSSL is installed. |
28 | | */ |
29 | | static char openssldir[MAX_PATH + 1]; |
30 | | |
31 | | /** |
32 | | * @brief The pointer to the openssldir buffer |
33 | | */ |
34 | | static char *openssldirptr = NULL; |
35 | | |
36 | | /** |
37 | | * @brief The directory where OpenSSL modules are located. |
38 | | */ |
39 | | static char modulesdir[MAX_PATH + 1]; |
40 | | |
41 | | /** |
42 | | * @brief The pointer to the modulesdir buffer |
43 | | */ |
44 | | static char *modulesdirptr = NULL; |
45 | | |
46 | | /** |
47 | | * @brief Get the list of Windows registry directories. |
48 | | * |
49 | | * This function retrieves a list of Windows registry directories. |
50 | | * |
51 | | * @return A pointer to a char array containing the registry directories. |
52 | | */ |
53 | | static char *get_windows_regdirs(char *dst, DWORD dstsizebytes, LPCWSTR valuename) |
54 | | { |
55 | | char *retval = NULL; |
56 | | #ifdef REGISTRY_KEY |
57 | | DWORD keysizebytes; |
58 | | DWORD ktype; |
59 | | HKEY hkey; |
60 | | LSTATUS ret; |
61 | | DWORD index = 0; |
62 | | LPCWSTR tempstr = NULL; |
63 | | |
64 | | /* |
65 | | * Narrow call: TEXT(REGISTRY_KEY) would widen only the first literal of the |
66 | | * concatenation, which MSVC 12.0 rejects. The subkey path is ASCII. |
67 | | */ |
68 | | ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, |
69 | | REGISTRY_KEY, KEY_WOW64_32KEY, |
70 | | KEY_QUERY_VALUE, &hkey); |
71 | | if (ret != ERROR_SUCCESS) |
72 | | goto out; |
73 | | |
74 | | /* Always use wide call so we can avoid extra encoding conversions on the output */ |
75 | | ret = RegQueryValueExW(hkey, valuename, NULL, &ktype, NULL, |
76 | | &keysizebytes); |
77 | | if (ret != ERROR_SUCCESS) |
78 | | goto out; |
79 | | if (ktype != REG_EXPAND_SZ && ktype != REG_SZ) |
80 | | goto out; |
81 | | if (keysizebytes > MAX_PATH * sizeof(WCHAR)) |
82 | | goto out; |
83 | | |
84 | | /* |
85 | | * RegQueryValueExW does not guarantee the buffer is null terminated, |
86 | | * so we make space for one in the allocation |
87 | | */ |
88 | | tempstr = OPENSSL_zalloc(keysizebytes + sizeof(WCHAR)); |
89 | | |
90 | | if (tempstr == NULL) |
91 | | goto out; |
92 | | |
93 | | if (RegQueryValueExW(hkey, valuename, |
94 | | NULL, &ktype, (LPBYTE)tempstr, &keysizebytes) |
95 | | != ERROR_SUCCESS) |
96 | | goto out; |
97 | | |
98 | | if (!WideCharToMultiByte(CP_UTF8, 0, tempstr, -1, dst, dstsizebytes, |
99 | | NULL, NULL)) |
100 | | goto out; |
101 | | |
102 | | retval = dst; |
103 | | out: |
104 | | OPENSSL_free(tempstr); |
105 | | RegCloseKey(hkey); |
106 | | #endif /* REGISTRY_KEY */ |
107 | | return retval; |
108 | | } |
109 | | |
110 | | static CRYPTO_ONCE defaults_setup_init = CRYPTO_ONCE_STATIC_INIT; |
111 | | |
112 | | /** |
113 | | * @brief Function to setup default values to run once. |
114 | | * Only used in Windows environments. Does run time initialization |
115 | | * of openssldir/modulesdir/enginesdir from the registry |
116 | | */ |
117 | | DEFINE_RUN_ONCE_STATIC(do_defaults_setup) |
118 | | { |
119 | | get_windows_regdirs(openssldir, sizeof(openssldir), L"OPENSSLDIR"); |
120 | | get_windows_regdirs(modulesdir, sizeof(modulesdir), L"MODULESDIR"); |
121 | | |
122 | | /* |
123 | | * Set our pointers only if the directories are fetched properly |
124 | | */ |
125 | | if (strlen(openssldir) > 0) |
126 | | openssldirptr = openssldir; |
127 | | |
128 | | if (strlen(modulesdir) > 0) |
129 | | modulesdirptr = modulesdir; |
130 | | |
131 | | return 1; |
132 | | } |
133 | | #endif /* defined(_WIN32) && defined(OSSL_WINCTX) */ |
134 | | |
135 | | /** |
136 | | * @brief Get the directory where OpenSSL is installed. |
137 | | * |
138 | | * @return A pointer to a string containing the OpenSSL directory path. |
139 | | */ |
140 | | const char *ossl_get_openssldir(void) |
141 | 0 | { |
142 | | #if defined(_WIN32) && defined(OSSL_WINCTX) |
143 | | if (!RUN_ONCE(&defaults_setup_init, do_defaults_setup)) |
144 | | return NULL; |
145 | | return (const char *)openssldirptr; |
146 | | #else |
147 | 0 | return OPENSSLDIR; |
148 | 0 | #endif |
149 | 0 | } |
150 | | |
151 | | /** |
152 | | * @brief Get the directory where OpenSSL modules are located. |
153 | | * |
154 | | * @return A pointer to a string containing the modules directory path. |
155 | | */ |
156 | | const char *ossl_get_modulesdir(void) |
157 | 0 | { |
158 | | #if defined(_WIN32) && defined(OSSL_WINCTX) |
159 | | if (!RUN_ONCE(&defaults_setup_init, do_defaults_setup)) |
160 | | return NULL; |
161 | | return (const char *)modulesdirptr; |
162 | | #else |
163 | 0 | return MODULESDIR; |
164 | 0 | #endif |
165 | 0 | } |
166 | | |
167 | | /** |
168 | | * @brief Get the build time defined windows installer context |
169 | | * |
170 | | * @return A char pointer to a string representing the windows install context |
171 | | */ |
172 | | const char *ossl_get_wininstallcontext(void) |
173 | 0 | { |
174 | | #if defined(_WIN32) && defined(OSSL_WINCTX) |
175 | | return MAKESTR(OSSL_WINCTX); |
176 | | #else |
177 | 0 | return "Undefined"; |
178 | 0 | #endif |
179 | 0 | } |