1*b077aed3SPierre Pronchery /*
2*b077aed3SPierre Pronchery * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
3*b077aed3SPierre Pronchery *
4*b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5*b077aed3SPierre Pronchery * this file except in compliance with the License. You can obtain a copy
6*b077aed3SPierre Pronchery * in the file LICENSE in the source distribution or at
7*b077aed3SPierre Pronchery * https://www.openssl.org/source/license.html
8*b077aed3SPierre Pronchery */
9*b077aed3SPierre Pronchery
10*b077aed3SPierre Pronchery #include "internal/cryptlib.h"
11*b077aed3SPierre Pronchery #include <openssl/rand.h>
12*b077aed3SPierre Pronchery #include "crypto/rand_pool.h"
13*b077aed3SPierre Pronchery #include "crypto/rand.h"
14*b077aed3SPierre Pronchery #include "prov/seeding.h"
15*b077aed3SPierre Pronchery
16*b077aed3SPierre Pronchery #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
17*b077aed3SPierre Pronchery
18*b077aed3SPierre Pronchery # ifndef OPENSSL_RAND_SEED_OS
19*b077aed3SPierre Pronchery # error "Unsupported seeding method configured; must be os"
20*b077aed3SPierre Pronchery # endif
21*b077aed3SPierre Pronchery
22*b077aed3SPierre Pronchery # include <windows.h>
23*b077aed3SPierre Pronchery /* On Windows Vista or higher use BCrypt instead of the legacy CryptoAPI */
24*b077aed3SPierre Pronchery # if defined(_MSC_VER) && _MSC_VER > 1500 /* 1500 = Visual Studio 2008 */ \
25*b077aed3SPierre Pronchery && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600
26*b077aed3SPierre Pronchery # define USE_BCRYPTGENRANDOM
27*b077aed3SPierre Pronchery # endif
28*b077aed3SPierre Pronchery
29*b077aed3SPierre Pronchery # ifdef USE_BCRYPTGENRANDOM
30*b077aed3SPierre Pronchery # include <bcrypt.h>
31*b077aed3SPierre Pronchery # ifdef _MSC_VER
32*b077aed3SPierre Pronchery # pragma comment(lib, "bcrypt.lib")
33*b077aed3SPierre Pronchery # endif
34*b077aed3SPierre Pronchery # ifndef STATUS_SUCCESS
35*b077aed3SPierre Pronchery # define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
36*b077aed3SPierre Pronchery # endif
37*b077aed3SPierre Pronchery # else
38*b077aed3SPierre Pronchery # include <wincrypt.h>
39*b077aed3SPierre Pronchery /*
40*b077aed3SPierre Pronchery * Intel hardware RNG CSP -- available from
41*b077aed3SPierre Pronchery * http://developer.intel.com/design/security/rng/redist_license.htm
42*b077aed3SPierre Pronchery */
43*b077aed3SPierre Pronchery # define PROV_INTEL_SEC 22
44*b077aed3SPierre Pronchery # define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider"
45*b077aed3SPierre Pronchery # endif
46*b077aed3SPierre Pronchery
ossl_pool_acquire_entropy(RAND_POOL * pool)47*b077aed3SPierre Pronchery size_t ossl_pool_acquire_entropy(RAND_POOL *pool)
48*b077aed3SPierre Pronchery {
49*b077aed3SPierre Pronchery # ifndef USE_BCRYPTGENRANDOM
50*b077aed3SPierre Pronchery HCRYPTPROV hProvider;
51*b077aed3SPierre Pronchery # endif
52*b077aed3SPierre Pronchery unsigned char *buffer;
53*b077aed3SPierre Pronchery size_t bytes_needed;
54*b077aed3SPierre Pronchery size_t entropy_available = 0;
55*b077aed3SPierre Pronchery
56*b077aed3SPierre Pronchery
57*b077aed3SPierre Pronchery # ifdef OPENSSL_RAND_SEED_RDTSC
58*b077aed3SPierre Pronchery entropy_available = ossl_prov_acquire_entropy_from_tsc(pool);
59*b077aed3SPierre Pronchery if (entropy_available > 0)
60*b077aed3SPierre Pronchery return entropy_available;
61*b077aed3SPierre Pronchery # endif
62*b077aed3SPierre Pronchery
63*b077aed3SPierre Pronchery # ifdef OPENSSL_RAND_SEED_RDCPU
64*b077aed3SPierre Pronchery entropy_available = ossl_prov_acquire_entropy_from_cpu(pool);
65*b077aed3SPierre Pronchery if (entropy_available > 0)
66*b077aed3SPierre Pronchery return entropy_available;
67*b077aed3SPierre Pronchery # endif
68*b077aed3SPierre Pronchery
69*b077aed3SPierre Pronchery # ifdef USE_BCRYPTGENRANDOM
70*b077aed3SPierre Pronchery bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
71*b077aed3SPierre Pronchery buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
72*b077aed3SPierre Pronchery if (buffer != NULL) {
73*b077aed3SPierre Pronchery size_t bytes = 0;
74*b077aed3SPierre Pronchery if (BCryptGenRandom(NULL, buffer, bytes_needed,
75*b077aed3SPierre Pronchery BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS)
76*b077aed3SPierre Pronchery bytes = bytes_needed;
77*b077aed3SPierre Pronchery
78*b077aed3SPierre Pronchery ossl_rand_pool_add_end(pool, bytes, 8 * bytes);
79*b077aed3SPierre Pronchery entropy_available = ossl_rand_pool_entropy_available(pool);
80*b077aed3SPierre Pronchery }
81*b077aed3SPierre Pronchery if (entropy_available > 0)
82*b077aed3SPierre Pronchery return entropy_available;
83*b077aed3SPierre Pronchery # else
84*b077aed3SPierre Pronchery bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
85*b077aed3SPierre Pronchery buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
86*b077aed3SPierre Pronchery if (buffer != NULL) {
87*b077aed3SPierre Pronchery size_t bytes = 0;
88*b077aed3SPierre Pronchery /* poll the CryptoAPI PRNG */
89*b077aed3SPierre Pronchery if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL,
90*b077aed3SPierre Pronchery CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) {
91*b077aed3SPierre Pronchery if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0)
92*b077aed3SPierre Pronchery bytes = bytes_needed;
93*b077aed3SPierre Pronchery
94*b077aed3SPierre Pronchery CryptReleaseContext(hProvider, 0);
95*b077aed3SPierre Pronchery }
96*b077aed3SPierre Pronchery
97*b077aed3SPierre Pronchery ossl_rand_pool_add_end(pool, bytes, 8 * bytes);
98*b077aed3SPierre Pronchery entropy_available = ossl_rand_pool_entropy_available(pool);
99*b077aed3SPierre Pronchery }
100*b077aed3SPierre Pronchery if (entropy_available > 0)
101*b077aed3SPierre Pronchery return entropy_available;
102*b077aed3SPierre Pronchery
103*b077aed3SPierre Pronchery bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
104*b077aed3SPierre Pronchery buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
105*b077aed3SPierre Pronchery if (buffer != NULL) {
106*b077aed3SPierre Pronchery size_t bytes = 0;
107*b077aed3SPierre Pronchery /* poll the Pentium PRG with CryptoAPI */
108*b077aed3SPierre Pronchery if (CryptAcquireContextW(&hProvider, NULL,
109*b077aed3SPierre Pronchery INTEL_DEF_PROV, PROV_INTEL_SEC,
110*b077aed3SPierre Pronchery CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) {
111*b077aed3SPierre Pronchery if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0)
112*b077aed3SPierre Pronchery bytes = bytes_needed;
113*b077aed3SPierre Pronchery
114*b077aed3SPierre Pronchery CryptReleaseContext(hProvider, 0);
115*b077aed3SPierre Pronchery }
116*b077aed3SPierre Pronchery ossl_rand_pool_add_end(pool, bytes, 8 * bytes);
117*b077aed3SPierre Pronchery entropy_available = ossl_rand_pool_entropy_available(pool);
118*b077aed3SPierre Pronchery }
119*b077aed3SPierre Pronchery if (entropy_available > 0)
120*b077aed3SPierre Pronchery return entropy_available;
121*b077aed3SPierre Pronchery # endif
122*b077aed3SPierre Pronchery
123*b077aed3SPierre Pronchery return ossl_rand_pool_entropy_available(pool);
124*b077aed3SPierre Pronchery }
125*b077aed3SPierre Pronchery
126*b077aed3SPierre Pronchery
ossl_pool_add_nonce_data(RAND_POOL * pool)127*b077aed3SPierre Pronchery int ossl_pool_add_nonce_data(RAND_POOL *pool)
128*b077aed3SPierre Pronchery {
129*b077aed3SPierre Pronchery struct {
130*b077aed3SPierre Pronchery DWORD pid;
131*b077aed3SPierre Pronchery DWORD tid;
132*b077aed3SPierre Pronchery FILETIME time;
133*b077aed3SPierre Pronchery } data;
134*b077aed3SPierre Pronchery
135*b077aed3SPierre Pronchery /* Erase the entire structure including any padding */
136*b077aed3SPierre Pronchery memset(&data, 0, sizeof(data));
137*b077aed3SPierre Pronchery
138*b077aed3SPierre Pronchery /*
139*b077aed3SPierre Pronchery * Add process id, thread id, and a high resolution timestamp to
140*b077aed3SPierre Pronchery * ensure that the nonce is unique with high probability for
141*b077aed3SPierre Pronchery * different process instances.
142*b077aed3SPierre Pronchery */
143*b077aed3SPierre Pronchery data.pid = GetCurrentProcessId();
144*b077aed3SPierre Pronchery data.tid = GetCurrentThreadId();
145*b077aed3SPierre Pronchery GetSystemTimeAsFileTime(&data.time);
146*b077aed3SPierre Pronchery
147*b077aed3SPierre Pronchery return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
148*b077aed3SPierre Pronchery }
149*b077aed3SPierre Pronchery
ossl_rand_pool_add_additional_data(RAND_POOL * pool)150*b077aed3SPierre Pronchery int ossl_rand_pool_add_additional_data(RAND_POOL *pool)
151*b077aed3SPierre Pronchery {
152*b077aed3SPierre Pronchery struct {
153*b077aed3SPierre Pronchery DWORD tid;
154*b077aed3SPierre Pronchery LARGE_INTEGER time;
155*b077aed3SPierre Pronchery } data;
156*b077aed3SPierre Pronchery
157*b077aed3SPierre Pronchery /* Erase the entire structure including any padding */
158*b077aed3SPierre Pronchery memset(&data, 0, sizeof(data));
159*b077aed3SPierre Pronchery
160*b077aed3SPierre Pronchery /*
161*b077aed3SPierre Pronchery * Add some noise from the thread id and a high resolution timer.
162*b077aed3SPierre Pronchery * The thread id adds a little randomness if the drbg is accessed
163*b077aed3SPierre Pronchery * concurrently (which is the case for the <master> drbg).
164*b077aed3SPierre Pronchery */
165*b077aed3SPierre Pronchery data.tid = GetCurrentThreadId();
166*b077aed3SPierre Pronchery QueryPerformanceCounter(&data.time);
167*b077aed3SPierre Pronchery return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
168*b077aed3SPierre Pronchery }
169*b077aed3SPierre Pronchery
ossl_rand_pool_init(void)170*b077aed3SPierre Pronchery int ossl_rand_pool_init(void)
171*b077aed3SPierre Pronchery {
172*b077aed3SPierre Pronchery return 1;
173*b077aed3SPierre Pronchery }
174*b077aed3SPierre Pronchery
ossl_rand_pool_cleanup(void)175*b077aed3SPierre Pronchery void ossl_rand_pool_cleanup(void)
176*b077aed3SPierre Pronchery {
177*b077aed3SPierre Pronchery }
178*b077aed3SPierre Pronchery
ossl_rand_pool_keep_random_devices_open(int keep)179*b077aed3SPierre Pronchery void ossl_rand_pool_keep_random_devices_open(int keep)
180*b077aed3SPierre Pronchery {
181*b077aed3SPierre Pronchery }
182*b077aed3SPierre Pronchery
183*b077aed3SPierre Pronchery #endif
184