1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <openssl/crypto.h>
11e1051a39Sopenharmony_ci#include "crypto/rand.h"
12e1051a39Sopenharmony_ci#include "crypto/dso_conf.h"
13e1051a39Sopenharmony_ci#include "internal/thread_once.h"
14e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
15e1051a39Sopenharmony_ci#include "e_os.h"
16e1051a39Sopenharmony_ci#include "buildinf.h"
17e1051a39Sopenharmony_ci
18e1051a39Sopenharmony_ci#if defined(__arm__) || defined(__arm) || defined(__aarch64__)
19e1051a39Sopenharmony_ci# include "arm_arch.h"
20e1051a39Sopenharmony_ci# define CPU_INFO_STR_LEN 128
21e1051a39Sopenharmony_ci#elif defined(__s390__) || defined(__s390x__)
22e1051a39Sopenharmony_ci# include "s390x_arch.h"
23e1051a39Sopenharmony_ci# define CPU_INFO_STR_LEN 2048
24e1051a39Sopenharmony_ci#else
25e1051a39Sopenharmony_ci# define CPU_INFO_STR_LEN 128
26e1051a39Sopenharmony_ci#endif
27e1051a39Sopenharmony_ci
28e1051a39Sopenharmony_ci/* extern declaration to avoid warning */
29e1051a39Sopenharmony_ciextern char ossl_cpu_info_str[];
30e1051a39Sopenharmony_ci
31e1051a39Sopenharmony_cistatic char *seed_sources = NULL;
32e1051a39Sopenharmony_ci
33e1051a39Sopenharmony_cichar ossl_cpu_info_str[CPU_INFO_STR_LEN] = "";
34e1051a39Sopenharmony_ci#define CPUINFO_PREFIX "CPUINFO: "
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_cistatic CRYPTO_ONCE init_info = CRYPTO_ONCE_STATIC_INIT;
37e1051a39Sopenharmony_ci
38e1051a39Sopenharmony_ciDEFINE_RUN_ONCE_STATIC(init_info_strings)
39e1051a39Sopenharmony_ci{
40e1051a39Sopenharmony_ci#if defined(OPENSSL_CPUID_OBJ)
41e1051a39Sopenharmony_ci# if defined(__i386)   || defined(__i386__)   || defined(_M_IX86) || \
42e1051a39Sopenharmony_ci     defined(__x86_64) || defined(__x86_64__) || \
43e1051a39Sopenharmony_ci     defined(_M_AMD64) || defined(_M_X64)
44e1051a39Sopenharmony_ci    const char *env;
45e1051a39Sopenharmony_ci
46e1051a39Sopenharmony_ci    BIO_snprintf(ossl_cpu_info_str, sizeof(ossl_cpu_info_str),
47e1051a39Sopenharmony_ci                 CPUINFO_PREFIX "OPENSSL_ia32cap=0x%llx:0x%llx",
48e1051a39Sopenharmony_ci                 (unsigned long long)OPENSSL_ia32cap_P[0] |
49e1051a39Sopenharmony_ci                 (unsigned long long)OPENSSL_ia32cap_P[1] << 32,
50e1051a39Sopenharmony_ci                 (unsigned long long)OPENSSL_ia32cap_P[2] |
51e1051a39Sopenharmony_ci                 (unsigned long long)OPENSSL_ia32cap_P[3] << 32);
52e1051a39Sopenharmony_ci    if ((env = getenv("OPENSSL_ia32cap")) != NULL)
53e1051a39Sopenharmony_ci        BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str),
54e1051a39Sopenharmony_ci                     sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str),
55e1051a39Sopenharmony_ci                     " env:%s", env);
56e1051a39Sopenharmony_ci# elif defined(__arm__) || defined(__arm) || defined(__aarch64__)
57e1051a39Sopenharmony_ci    const char *env;
58e1051a39Sopenharmony_ci
59e1051a39Sopenharmony_ci    BIO_snprintf(ossl_cpu_info_str, sizeof(ossl_cpu_info_str),
60e1051a39Sopenharmony_ci                 CPUINFO_PREFIX "OPENSSL_armcap=0x%x", OPENSSL_armcap_P);
61e1051a39Sopenharmony_ci    if ((env = getenv("OPENSSL_armcap")) != NULL)
62e1051a39Sopenharmony_ci        BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str),
63e1051a39Sopenharmony_ci                     sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str),
64e1051a39Sopenharmony_ci                     " env:%s", env);
65e1051a39Sopenharmony_ci# elif defined(__s390__) || defined(__s390x__)
66e1051a39Sopenharmony_ci    const char *env;
67e1051a39Sopenharmony_ci
68e1051a39Sopenharmony_ci    BIO_snprintf(ossl_cpu_info_str, sizeof(ossl_cpu_info_str),
69e1051a39Sopenharmony_ci                 CPUINFO_PREFIX "OPENSSL_s390xcap="
70e1051a39Sopenharmony_ci                 "stfle:0x%llx:0x%llx:0x%llx:0x%llx:"
71e1051a39Sopenharmony_ci                 "kimd:0x%llx:0x%llx:"
72e1051a39Sopenharmony_ci                 "klmd:0x%llx:0x%llx:"
73e1051a39Sopenharmony_ci                 "km:0x%llx:0x%llx:"
74e1051a39Sopenharmony_ci                 "kmc:0x%llx:0x%llx:"
75e1051a39Sopenharmony_ci                 "kmac:0x%llx:0x%llx:"
76e1051a39Sopenharmony_ci                 "kmctr:0x%llx:0x%llx:"
77e1051a39Sopenharmony_ci                 "kmo:0x%llx:0x%llx:"
78e1051a39Sopenharmony_ci                 "kmf:0x%llx:0x%llx:"
79e1051a39Sopenharmony_ci                 "prno:0x%llx:0x%llx:"
80e1051a39Sopenharmony_ci                 "kma:0x%llx:0x%llx:"
81e1051a39Sopenharmony_ci                 "pcc:0x%llx:0x%llx:"
82e1051a39Sopenharmony_ci                 "kdsa:0x%llx:0x%llx",
83e1051a39Sopenharmony_ci                 OPENSSL_s390xcap_P.stfle[0], OPENSSL_s390xcap_P.stfle[1],
84e1051a39Sopenharmony_ci                 OPENSSL_s390xcap_P.stfle[2], OPENSSL_s390xcap_P.stfle[3],
85e1051a39Sopenharmony_ci                 OPENSSL_s390xcap_P.kimd[0], OPENSSL_s390xcap_P.kimd[1],
86e1051a39Sopenharmony_ci                 OPENSSL_s390xcap_P.klmd[0], OPENSSL_s390xcap_P.klmd[1],
87e1051a39Sopenharmony_ci                 OPENSSL_s390xcap_P.km[0], OPENSSL_s390xcap_P.km[1],
88e1051a39Sopenharmony_ci                 OPENSSL_s390xcap_P.kmc[0], OPENSSL_s390xcap_P.kmc[1],
89e1051a39Sopenharmony_ci                 OPENSSL_s390xcap_P.kmac[0], OPENSSL_s390xcap_P.kmac[1],
90e1051a39Sopenharmony_ci                 OPENSSL_s390xcap_P.kmctr[0], OPENSSL_s390xcap_P.kmctr[1],
91e1051a39Sopenharmony_ci                 OPENSSL_s390xcap_P.kmo[0], OPENSSL_s390xcap_P.kmo[1],
92e1051a39Sopenharmony_ci                 OPENSSL_s390xcap_P.kmf[0], OPENSSL_s390xcap_P.kmf[1],
93e1051a39Sopenharmony_ci                 OPENSSL_s390xcap_P.prno[0], OPENSSL_s390xcap_P.prno[1],
94e1051a39Sopenharmony_ci                 OPENSSL_s390xcap_P.kma[0], OPENSSL_s390xcap_P.kma[1],
95e1051a39Sopenharmony_ci                 OPENSSL_s390xcap_P.pcc[0], OPENSSL_s390xcap_P.pcc[1],
96e1051a39Sopenharmony_ci                 OPENSSL_s390xcap_P.kdsa[0], OPENSSL_s390xcap_P.kdsa[1]);
97e1051a39Sopenharmony_ci    if ((env = getenv("OPENSSL_s390xcap")) != NULL)
98e1051a39Sopenharmony_ci        BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str),
99e1051a39Sopenharmony_ci                     sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str),
100e1051a39Sopenharmony_ci                     " env:%s", env);
101e1051a39Sopenharmony_ci# endif
102e1051a39Sopenharmony_ci#endif
103e1051a39Sopenharmony_ci
104e1051a39Sopenharmony_ci    {
105e1051a39Sopenharmony_ci        static char seeds[512] = "";
106e1051a39Sopenharmony_ci
107e1051a39Sopenharmony_ci#define add_seeds_string(str)                                           \
108e1051a39Sopenharmony_ci        do {                                                            \
109e1051a39Sopenharmony_ci            if (seeds[0] != '\0')                                       \
110e1051a39Sopenharmony_ci                OPENSSL_strlcat(seeds, " ", sizeof(seeds));             \
111e1051a39Sopenharmony_ci            OPENSSL_strlcat(seeds, str, sizeof(seeds));                 \
112e1051a39Sopenharmony_ci        } while (0)
113e1051a39Sopenharmony_ci#define add_seeds_stringlist(label, strlist)                            \
114e1051a39Sopenharmony_ci        do {                                                            \
115e1051a39Sopenharmony_ci            add_seeds_string(label "(");                                \
116e1051a39Sopenharmony_ci            {                                                           \
117e1051a39Sopenharmony_ci                const char *dev[] =  { strlist, NULL };                 \
118e1051a39Sopenharmony_ci                const char **p;                                         \
119e1051a39Sopenharmony_ci                int first = 1;                                          \
120e1051a39Sopenharmony_ci                                                                        \
121e1051a39Sopenharmony_ci                for (p = dev; *p != NULL; p++) {                        \
122e1051a39Sopenharmony_ci                    if (!first)                                         \
123e1051a39Sopenharmony_ci                        OPENSSL_strlcat(seeds, " ", sizeof(seeds));     \
124e1051a39Sopenharmony_ci                    first = 0;                                          \
125e1051a39Sopenharmony_ci                    OPENSSL_strlcat(seeds, *p, sizeof(seeds));          \
126e1051a39Sopenharmony_ci                }                                                       \
127e1051a39Sopenharmony_ci            }                                                           \
128e1051a39Sopenharmony_ci            OPENSSL_strlcat(seeds, ")", sizeof(seeds));                 \
129e1051a39Sopenharmony_ci        } while (0)
130e1051a39Sopenharmony_ci
131e1051a39Sopenharmony_ci#ifdef OPENSSL_RAND_SEED_NONE
132e1051a39Sopenharmony_ci        add_seeds_string("none");
133e1051a39Sopenharmony_ci#endif
134e1051a39Sopenharmony_ci#ifdef OPENSSL_RAND_SEED_RDTSC
135e1051a39Sopenharmony_ci        add_seeds_string("rdtsc");
136e1051a39Sopenharmony_ci#endif
137e1051a39Sopenharmony_ci#ifdef OPENSSL_RAND_SEED_RDCPU
138e1051a39Sopenharmony_ci        add_seeds_string("rdrand ( rdseed rdrand )");
139e1051a39Sopenharmony_ci#endif
140e1051a39Sopenharmony_ci#ifdef OPENSSL_RAND_SEED_LIBRANDOM
141e1051a39Sopenharmony_ci        add_seeds_string("C-library-random");
142e1051a39Sopenharmony_ci#endif
143e1051a39Sopenharmony_ci#ifdef OPENSSL_RAND_SEED_GETRANDOM
144e1051a39Sopenharmony_ci        add_seeds_string("getrandom-syscall");
145e1051a39Sopenharmony_ci#endif
146e1051a39Sopenharmony_ci#ifdef OPENSSL_RAND_SEED_DEVRANDOM
147e1051a39Sopenharmony_ci        add_seeds_stringlist("random-device", DEVRANDOM);
148e1051a39Sopenharmony_ci#endif
149e1051a39Sopenharmony_ci#ifdef OPENSSL_RAND_SEED_EGD
150e1051a39Sopenharmony_ci        add_seeds_stringlist("EGD", DEVRANDOM_EGD);
151e1051a39Sopenharmony_ci#endif
152e1051a39Sopenharmony_ci#ifdef OPENSSL_RAND_SEED_OS
153e1051a39Sopenharmony_ci        add_seeds_string("os-specific");
154e1051a39Sopenharmony_ci#endif
155e1051a39Sopenharmony_ci        seed_sources = seeds;
156e1051a39Sopenharmony_ci    }
157e1051a39Sopenharmony_ci    return 1;
158e1051a39Sopenharmony_ci}
159e1051a39Sopenharmony_ci
160e1051a39Sopenharmony_ciconst char *OPENSSL_info(int t)
161e1051a39Sopenharmony_ci{
162e1051a39Sopenharmony_ci    /*
163e1051a39Sopenharmony_ci     * We don't care about the result.  Worst case scenario, the strings
164e1051a39Sopenharmony_ci     * won't be initialised, i.e. remain NULL, which means that the info
165e1051a39Sopenharmony_ci     * isn't available anyway...
166e1051a39Sopenharmony_ci     */
167e1051a39Sopenharmony_ci    (void)RUN_ONCE(&init_info, init_info_strings);
168e1051a39Sopenharmony_ci
169e1051a39Sopenharmony_ci    switch (t) {
170e1051a39Sopenharmony_ci    case OPENSSL_INFO_CONFIG_DIR:
171e1051a39Sopenharmony_ci        return OPENSSLDIR;
172e1051a39Sopenharmony_ci    case OPENSSL_INFO_ENGINES_DIR:
173e1051a39Sopenharmony_ci        return ENGINESDIR;
174e1051a39Sopenharmony_ci    case OPENSSL_INFO_MODULES_DIR:
175e1051a39Sopenharmony_ci        return MODULESDIR;
176e1051a39Sopenharmony_ci    case OPENSSL_INFO_DSO_EXTENSION:
177e1051a39Sopenharmony_ci        return DSO_EXTENSION;
178e1051a39Sopenharmony_ci    case OPENSSL_INFO_DIR_FILENAME_SEPARATOR:
179e1051a39Sopenharmony_ci#if defined(_WIN32)
180e1051a39Sopenharmony_ci        return "\\";
181e1051a39Sopenharmony_ci#elif defined(__VMS)
182e1051a39Sopenharmony_ci        return "";
183e1051a39Sopenharmony_ci#else  /* Assume POSIX */
184e1051a39Sopenharmony_ci        return "/";
185e1051a39Sopenharmony_ci#endif
186e1051a39Sopenharmony_ci    case OPENSSL_INFO_LIST_SEPARATOR:
187e1051a39Sopenharmony_ci        {
188e1051a39Sopenharmony_ci            static const char list_sep[] = { LIST_SEPARATOR_CHAR, '\0' };
189e1051a39Sopenharmony_ci            return list_sep;
190e1051a39Sopenharmony_ci        }
191e1051a39Sopenharmony_ci    case OPENSSL_INFO_SEED_SOURCE:
192e1051a39Sopenharmony_ci        return seed_sources;
193e1051a39Sopenharmony_ci    case OPENSSL_INFO_CPU_SETTINGS:
194e1051a39Sopenharmony_ci        /*
195e1051a39Sopenharmony_ci         * If successfully initialized, ossl_cpu_info_str will start
196e1051a39Sopenharmony_ci         * with CPUINFO_PREFIX, if failed it will be an empty string.
197e1051a39Sopenharmony_ci         * Strip away the CPUINFO_PREFIX which we don't need here.
198e1051a39Sopenharmony_ci         */
199e1051a39Sopenharmony_ci        if (ossl_cpu_info_str[0] != '\0')
200e1051a39Sopenharmony_ci            return ossl_cpu_info_str + strlen(CPUINFO_PREFIX);
201e1051a39Sopenharmony_ci        break;
202e1051a39Sopenharmony_ci    default:
203e1051a39Sopenharmony_ci        break;
204e1051a39Sopenharmony_ci    }
205e1051a39Sopenharmony_ci    /* Not an error */
206e1051a39Sopenharmony_ci    return NULL;
207e1051a39Sopenharmony_ci}
208