Coverage Report

Created: 2026-07-16 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/info.c
Line
Count
Source
1
/*
2
 * Copyright 2019-2024 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 <stdarg.h>
11
#include <openssl/crypto.h>
12
#include "crypto/rand.h"
13
#include "crypto/dso_conf.h"
14
#include "internal/thread_once.h"
15
#include "internal/cryptlib.h"
16
#include "internal/e_os.h"
17
#include "buildinf.h"
18
19
#ifndef OPENSSL_NO_JITTER
20
#include <stdio.h>
21
#include <jitterentropy.h>
22
#endif
23
24
#if defined(__arm__) || defined(__arm) || defined(__aarch64__)
25
#include "arch/arm_arch.h"
26
#define CPU_INFO_STR_LEN 128
27
#elif defined(__powerpc__) || defined(__POWERPC__) || defined(_ARCH_PPC)
28
#include "arch/ppc_arch.h"
29
#define CPU_INFO_STR_LEN 128
30
#elif defined(__sparcv9) || defined(__sparcv9__)
31
#include "arch/sparc_arch.h"
32
#define CPU_INFO_STR_LEN 128
33
#elif defined(__s390__) || defined(__s390x__)
34
#include "arch/s390x_arch.h"
35
#define CPU_INFO_STR_LEN 2048
36
#elif defined(__riscv)
37
#include "arch/riscv_arch.h"
38
#define CPU_INFO_STR_LEN 2048
39
#else
40
#define CPU_INFO_STR_LEN 256
41
#endif
42
43
/* extern declaration to avoid warning */
44
extern char ossl_cpu_info_str[];
45
46
static char *seed_sources = NULL;
47
48
char ossl_cpu_info_str[CPU_INFO_STR_LEN] = "";
49
0
#define CPUINFO_PREFIX "CPUINFO: "
50
51
static CRYPTO_ONCE init_info = CRYPTO_ONCE_STATIC_INIT;
52
53
/*
54
 * Append a printf-formatted suffix to ossl_cpu_info_str, truncating to
55
 * fit.  The first call writes the base string (the buffer starts empty,
56
 * so off == 0); subsequent calls extend it.
57
 */
58
static ossl_unused void cpu_info_append(const char *fmt, ...)
59
0
{
60
0
    size_t off = strlen(ossl_cpu_info_str);
61
0
    va_list args;
62
0
63
0
    if (off >= sizeof(ossl_cpu_info_str))
64
0
        return;
65
0
    va_start(args, fmt);
66
0
    (void)vsnprintf(ossl_cpu_info_str + off,
67
0
        sizeof(ossl_cpu_info_str) - off, fmt, args);
68
0
    va_end(args);
69
0
}
70
71
DEFINE_RUN_ONCE_STATIC(init_info_strings)
72
0
{
73
#if defined(OPENSSL_CPUID_OBJ)
74
#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
75
    const char *env;
76
77
    cpu_info_append(CPUINFO_PREFIX
78
        "OPENSSL_ia32cap=0x%.16llx:0x%.16llx:0x%.16llx:0x%.16llx:0x%.16llx",
79
        (unsigned long long)OPENSSL_ia32cap_P[0] | (unsigned long long)OPENSSL_ia32cap_P[1] << 32,
80
        (unsigned long long)OPENSSL_ia32cap_P[2] | (unsigned long long)OPENSSL_ia32cap_P[3] << 32,
81
        (unsigned long long)OPENSSL_ia32cap_P[4] | (unsigned long long)OPENSSL_ia32cap_P[5] << 32,
82
        (unsigned long long)OPENSSL_ia32cap_P[6] | (unsigned long long)OPENSSL_ia32cap_P[7] << 32,
83
        (unsigned long long)OPENSSL_ia32cap_P[8] | (unsigned long long)OPENSSL_ia32cap_P[9] << 32);
84
    if ((env = getenv("OPENSSL_ia32cap")) != NULL)
85
        cpu_info_append(" env:%s", env);
86
#elif defined(__arm__) || defined(__arm) || defined(__aarch64__)
87
    const char *env;
88
89
    cpu_info_append(CPUINFO_PREFIX "OPENSSL_armcap=0x%x", OPENSSL_armcap_P);
90
    if ((env = getenv("OPENSSL_armcap")) != NULL)
91
        cpu_info_append(" env:%s", env);
92
#elif defined(__powerpc__) || defined(__POWERPC__) || defined(_ARCH_PPC)
93
    const char *env;
94
95
    cpu_info_append(CPUINFO_PREFIX "OPENSSL_ppccap=0x%x", OPENSSL_ppccap_P);
96
    if ((env = getenv("OPENSSL_ppccap")) != NULL)
97
        cpu_info_append(" env:%s", env);
98
#elif defined(__sparcv9) || defined(__sparcv9__)
99
    const char *env;
100
101
    cpu_info_append(CPUINFO_PREFIX "OPENSSL_sparcv9cap=0x%x:0x%x",
102
        OPENSSL_sparcv9cap_P[0], OPENSSL_sparcv9cap_P[1]);
103
    if ((env = getenv("OPENSSL_sparcv9cap")) != NULL)
104
        cpu_info_append(" env:%s", env);
105
#elif defined(__s390__) || defined(__s390x__)
106
    const char *env;
107
108
    cpu_info_append(CPUINFO_PREFIX "OPENSSL_s390xcap="
109
                                   "stfle:0x%llx:0x%llx:0x%llx:0x%llx:"
110
                                   "kimd:0x%llx:0x%llx:"
111
                                   "klmd:0x%llx:0x%llx:"
112
                                   "km:0x%llx:0x%llx:"
113
                                   "kmc:0x%llx:0x%llx:"
114
                                   "kmac:0x%llx:0x%llx:"
115
                                   "kmctr:0x%llx:0x%llx:"
116
                                   "kmo:0x%llx:0x%llx:"
117
                                   "kmf:0x%llx:0x%llx:"
118
                                   "prno:0x%llx:0x%llx:"
119
                                   "kma:0x%llx:0x%llx:"
120
                                   "pcc:0x%llx:0x%llx:"
121
                                   "kdsa:0x%llx:0x%llx",
122
        OPENSSL_s390xcap_P.stfle[0], OPENSSL_s390xcap_P.stfle[1],
123
        OPENSSL_s390xcap_P.stfle[2], OPENSSL_s390xcap_P.stfle[3],
124
        OPENSSL_s390xcap_P.kimd[0], OPENSSL_s390xcap_P.kimd[1],
125
        OPENSSL_s390xcap_P.klmd[0], OPENSSL_s390xcap_P.klmd[1],
126
        OPENSSL_s390xcap_P.km[0], OPENSSL_s390xcap_P.km[1],
127
        OPENSSL_s390xcap_P.kmc[0], OPENSSL_s390xcap_P.kmc[1],
128
        OPENSSL_s390xcap_P.kmac[0], OPENSSL_s390xcap_P.kmac[1],
129
        OPENSSL_s390xcap_P.kmctr[0], OPENSSL_s390xcap_P.kmctr[1],
130
        OPENSSL_s390xcap_P.kmo[0], OPENSSL_s390xcap_P.kmo[1],
131
        OPENSSL_s390xcap_P.kmf[0], OPENSSL_s390xcap_P.kmf[1],
132
        OPENSSL_s390xcap_P.prno[0], OPENSSL_s390xcap_P.prno[1],
133
        OPENSSL_s390xcap_P.kma[0], OPENSSL_s390xcap_P.kma[1],
134
        OPENSSL_s390xcap_P.pcc[0], OPENSSL_s390xcap_P.pcc[1],
135
        OPENSSL_s390xcap_P.kdsa[0], OPENSSL_s390xcap_P.kdsa[1]);
136
    if ((env = getenv("OPENSSL_s390xcap")) != NULL)
137
        cpu_info_append(" env:%s", env);
138
#elif defined(__riscv)
139
    const char *env;
140
    size_t i;
141
142
    cpu_info_append(CPUINFO_PREFIX "OPENSSL_riscvcap=RV"
143
#if __riscv_xlen == 32
144
                                   "32"
145
#elif __riscv_xlen == 64
146
                                   "64"
147
#elif __riscv_xlen == 128
148
                                   "128"
149
#endif
150
#if defined(__riscv_i) && defined(__riscv_m) && defined(__riscv_a) \
151
    && defined(__riscv_f) && defined(__riscv_d)                    \
152
    && defined(__riscv_zicsr) && defined(__riscv_zifencei)
153
                                   "G" /* shorthand for IMAFD_Zicsr_Zifencei */
154
#else
155
#ifdef __riscv_i
156
                                   "I"
157
#endif
158
#ifdef __riscv_m
159
                                   "M"
160
#endif
161
#ifdef __riscv_a
162
                                   "A"
163
#endif
164
#ifdef __riscv_f
165
                                   "F"
166
#endif
167
#ifdef __riscv_d
168
                                   "D"
169
#endif
170
#endif
171
#ifdef __riscv_c
172
                                   "C"
173
#endif
174
    );
175
    for (i = 0; i < kRISCVNumCaps; i++) {
176
        if (OPENSSL_riscvcap_P[RISCV_capabilities[i].index]
177
            & (1 << RISCV_capabilities[i].bit_offset))
178
            /* Match, display the name */
179
            cpu_info_append("_%s", RISCV_capabilities[i].name);
180
    }
181
    if (RISCV_HAS_V())
182
        cpu_info_append(" vlen:%lu", riscv_vlen());
183
    if ((env = getenv("OPENSSL_riscvcap")) != NULL)
184
        cpu_info_append(" env:%s", env);
185
#endif
186
#endif
187
188
0
    {
189
0
        static char seeds[512] = "";
190
191
0
#define add_seeds_string(str)                           \
192
0
    do {                                                \
193
0
        if (seeds[0] != '\0')                           \
194
0
            OPENSSL_strlcat(seeds, " ", sizeof(seeds)); \
195
0
        OPENSSL_strlcat(seeds, str, sizeof(seeds));     \
196
0
    } while (0)
197
0
#define add_seeds_stringlist(label, strlist)                    \
198
0
    do {                                                        \
199
0
        add_seeds_string(label "(");                            \
200
0
        {                                                       \
201
0
            const char *dev[] = { strlist, NULL };              \
202
0
            const char **p;                                     \
203
0
            int first = 1;                                      \
204
0
                                                                \
205
0
            for (p = dev; *p != NULL; p++) {                    \
206
0
                if (!first)                                     \
207
0
                    OPENSSL_strlcat(seeds, " ", sizeof(seeds)); \
208
0
                first = 0;                                      \
209
0
                OPENSSL_strlcat(seeds, *p, sizeof(seeds));      \
210
0
            }                                                   \
211
0
        }                                                       \
212
0
        OPENSSL_strlcat(seeds, ")", sizeof(seeds));             \
213
0
    } while (0)
214
215
#ifdef OPENSSL_RAND_SEED_NONE
216
        add_seeds_string("none");
217
#endif
218
#ifdef OPENSSL_RAND_SEED_RDTSC
219
        add_seeds_string("rdtsc");
220
#endif
221
#ifdef OPENSSL_RAND_SEED_RDCPU
222
#ifdef __aarch64__
223
        add_seeds_string("rndr ( rndrrs rndr )");
224
#else
225
        add_seeds_string("rdrand ( rdseed rdrand )");
226
#endif
227
#endif
228
#ifdef OPENSSL_RAND_SEED_GETRANDOM
229
        add_seeds_string("getrandom-syscall");
230
#endif
231
#ifdef OPENSSL_RAND_SEED_DEVRANDOM
232
        add_seeds_stringlist("random-device", DEVRANDOM);
233
#endif
234
#ifdef OPENSSL_RAND_SEED_EGD
235
        add_seeds_stringlist("EGD", DEVRANDOM_EGD);
236
#endif
237
0
#ifdef OPENSSL_RAND_SEED_OS
238
0
        add_seeds_string("os-specific");
239
0
#endif
240
#ifndef OPENSSL_NO_JITTER
241
        {
242
            char buf[32];
243
244
            BIO_snprintf(buf, sizeof(buf), "JITTER (%d)", jent_version());
245
            add_seeds_string(buf);
246
        }
247
#endif
248
0
        seed_sources = seeds;
249
0
    }
250
0
    return 1;
251
0
}
252
253
const char *OPENSSL_info(int t)
254
0
{
255
    /*
256
     * We don't care about the result.  Worst case scenario, the strings
257
     * won't be initialised, i.e. remain NULL, which means that the info
258
     * isn't available anyway...
259
     */
260
0
    (void)RUN_ONCE(&init_info, init_info_strings);
261
262
0
    switch (t) {
263
0
    case OPENSSL_INFO_CONFIG_DIR:
264
0
        return ossl_get_openssldir();
265
0
    case OPENSSL_INFO_ENGINES_DIR:
266
0
        return NULL;
267
0
    case OPENSSL_INFO_MODULES_DIR:
268
0
        return ossl_get_modulesdir();
269
0
    case OPENSSL_INFO_DSO_EXTENSION:
270
0
        return DSO_EXTENSION;
271
0
    case OPENSSL_INFO_DIR_FILENAME_SEPARATOR:
272
#if defined(_WIN32)
273
        return "\\";
274
#elif defined(__VMS)
275
        return "";
276
#else /* Assume POSIX */
277
0
        return "/";
278
0
#endif
279
0
    case OPENSSL_INFO_LIST_SEPARATOR: {
280
0
        static const char list_sep[] = { LIST_SEPARATOR_CHAR, '\0' };
281
0
        return list_sep;
282
0
    }
283
0
    case OPENSSL_INFO_SEED_SOURCE:
284
0
        return seed_sources;
285
0
    case OPENSSL_INFO_CPU_SETTINGS:
286
        /*
287
         * If successfully initialized, ossl_cpu_info_str will start
288
         * with CPUINFO_PREFIX, if failed it will be an empty string.
289
         * Strip away the CPUINFO_PREFIX which we don't need here.
290
         */
291
0
        if (ossl_cpu_info_str[0] != '\0')
292
0
            return ossl_cpu_info_str + strlen(CPUINFO_PREFIX);
293
0
        break;
294
0
    case OPENSSL_INFO_WINDOWS_CONTEXT:
295
0
        return ossl_get_wininstallcontext();
296
0
    default:
297
0
        break;
298
0
    }
299
    /* Not an error */
300
0
    return NULL;
301
0
}