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