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