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