xref: /freebsd/crypto/openssl/crypto/info.c (revision 046c625e9382e17da953767b881aaa782fa73af8)
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