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