/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 | | ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, |
65 | | TEXT(REGISTRY_KEY), KEY_WOW64_32KEY, |
66 | | KEY_QUERY_VALUE, &hkey); |
67 | | if (ret != ERROR_SUCCESS) |
68 | | goto out; |
69 | | |
70 | | /* Always use wide call so we can avoid extra encoding conversions on the output */ |
71 | | ret = RegQueryValueExW(hkey, valuename, NULL, &ktype, NULL, |
72 | | &keysizebytes); |
73 | | if (ret != ERROR_SUCCESS) |
74 | | goto out; |
75 | | if (ktype != REG_EXPAND_SZ && ktype != REG_SZ) |
76 | | goto out; |
77 | | if (keysizebytes > MAX_PATH * sizeof(WCHAR)) |
78 | | goto out; |
79 | | |
80 | | /* |
81 | | * RegQueryValueExW does not guarantee the buffer is null terminated, |
82 | | * so we make space for one in the allocation |
83 | | */ |
84 | | tempstr = OPENSSL_zalloc(keysizebytes + sizeof(WCHAR)); |
85 | | |
86 | | if (tempstr == NULL) |
87 | | goto out; |
88 | | |
89 | | if (RegQueryValueExW(hkey, valuename, |
90 | | NULL, &ktype, (LPBYTE)tempstr, &keysizebytes) |
91 | | != ERROR_SUCCESS) |
92 | | goto out; |
93 | | |
94 | | if (!WideCharToMultiByte(CP_UTF8, 0, tempstr, -1, dst, dstsizebytes, |
95 | | NULL, NULL)) |
96 | | goto out; |
97 | | |
98 | | retval = dst; |
99 | | out: |
100 | | OPENSSL_free(tempstr); |
101 | | RegCloseKey(hkey); |
102 | | #endif /* REGISTRY_KEY */ |
103 | | return retval; |
104 | | } |
105 | | |
106 | | static CRYPTO_ONCE defaults_setup_init = CRYPTO_ONCE_STATIC_INIT; |
107 | | |
108 | | /** |
109 | | * @brief Function to setup default values to run once. |
110 | | * Only used in Windows environments. Does run time initialization |
111 | | * of openssldir/modulesdir/enginesdir from the registry |
112 | | */ |
113 | | DEFINE_RUN_ONCE_STATIC(do_defaults_setup) |
114 | | { |
115 | | get_windows_regdirs(openssldir, sizeof(openssldir), L"OPENSSLDIR"); |
116 | | get_windows_regdirs(modulesdir, sizeof(modulesdir), L"MODULESDIR"); |
117 | | |
118 | | /* |
119 | | * Set our pointers only if the directories are fetched properly |
120 | | */ |
121 | | if (strlen(openssldir) > 0) |
122 | | openssldirptr = openssldir; |
123 | | |
124 | | if (strlen(modulesdir) > 0) |
125 | | modulesdirptr = modulesdir; |
126 | | |
127 | | return 1; |
128 | | } |
129 | | #endif /* defined(_WIN32) && defined(OSSL_WINCTX) */ |
130 | | |
131 | | /** |
132 | | * @brief Get the directory where OpenSSL is installed. |
133 | | * |
134 | | * @return A pointer to a string containing the OpenSSL directory path. |
135 | | */ |
136 | | const char *ossl_get_openssldir(void) |
137 | 0 | { |
138 | | #if defined(_WIN32) && defined(OSSL_WINCTX) |
139 | | if (!RUN_ONCE(&defaults_setup_init, do_defaults_setup)) |
140 | | return NULL; |
141 | | return (const char *)openssldirptr; |
142 | | #else |
143 | 0 | return OPENSSLDIR; |
144 | 0 | #endif |
145 | 0 | } |
146 | | |
147 | | /** |
148 | | * @brief Get the directory where OpenSSL modules are located. |
149 | | * |
150 | | * @return A pointer to a string containing the modules directory path. |
151 | | */ |
152 | | const char *ossl_get_modulesdir(void) |
153 | 0 | { |
154 | | #if defined(_WIN32) && defined(OSSL_WINCTX) |
155 | | if (!RUN_ONCE(&defaults_setup_init, do_defaults_setup)) |
156 | | return NULL; |
157 | | return (const char *)modulesdirptr; |
158 | | #else |
159 | 0 | return MODULESDIR; |
160 | 0 | #endif |
161 | 0 | } |
162 | | |
163 | | /** |
164 | | * @brief Get the build time defined windows installer context |
165 | | * |
166 | | * @return A char pointer to a string representing the windows install context |
167 | | */ |
168 | | const char *ossl_get_wininstallcontext(void) |
169 | 0 | { |
170 | | #if defined(_WIN32) && defined(OSSL_WINCTX) |
171 | | return MAKESTR(OSSL_WINCTX); |
172 | | #else |
173 | 0 | return "Undefined"; |
174 | 0 | #endif |
175 | 0 | } |