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