Coverage Report

Created: 2026-08-31 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}