1 | /* |
2 | * Copyright 1995-2018 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 "internal/cryptlib.h" |
11 | #include <openssl/rand.h> |
12 | #include "rand_local.h" |
13 | #include "crypto/rand.h" |
14 | #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) |
15 | |
16 | # ifndef OPENSSL_RAND_SEED_OS |
17 | # error "Unsupported seeding method configured; must be os" |
18 | # endif |
19 | |
20 | # include <windows.h> |
21 | /* On Windows Vista or higher use BCrypt instead of the legacy CryptoAPI */ |
22 | # if defined(_MSC_VER) && _MSC_VER > 1500 /* 1500 = Visual Studio 2008 */ \ |
23 | && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 |
24 | # define USE_BCRYPTGENRANDOM |
25 | # endif |
26 | |
27 | # ifdef USE_BCRYPTGENRANDOM |
28 | # include <bcrypt.h> |
29 | # pragma comment(lib, "bcrypt.lib") |
30 | # ifndef STATUS_SUCCESS |
31 | # define STATUS_SUCCESS ((NTSTATUS)0x00000000L) |
32 | # endif |
33 | # else |
34 | # include <wincrypt.h> |
35 | /* |
36 | * Intel hardware RNG CSP -- available from |
37 | * http://developer.intel.com/design/security/rng/redist_license.htm |
38 | */ |
39 | # define PROV_INTEL_SEC 22 |
40 | # define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider" |
41 | # endif |
42 | |
43 | size_t rand_pool_acquire_entropy(RAND_POOL *pool) |
44 | { |
45 | # ifndef USE_BCRYPTGENRANDOM |
46 | HCRYPTPROV hProvider; |
47 | # endif |
48 | unsigned char *buffer; |
49 | size_t bytes_needed; |
50 | size_t entropy_available = 0; |
51 | |
52 | |
53 | # ifdef OPENSSL_RAND_SEED_RDTSC |
54 | entropy_available = rand_acquire_entropy_from_tsc(pool); |
55 | if (entropy_available > 0) |
56 | return entropy_available; |
57 | # endif |
58 | |
59 | # ifdef OPENSSL_RAND_SEED_RDCPU |
60 | entropy_available = rand_acquire_entropy_from_cpu(pool); |
61 | if (entropy_available > 0) |
62 | return entropy_available; |
63 | # endif |
64 | |
65 | # ifdef USE_BCRYPTGENRANDOM |
66 | bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); |
67 | buffer = rand_pool_add_begin(pool, bytes_needed); |
68 | if (buffer != NULL) { |
69 | size_t bytes = 0; |
70 | if (BCryptGenRandom(NULL, buffer, bytes_needed, |
71 | BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS) |
72 | bytes = bytes_needed; |
73 | |
74 | rand_pool_add_end(pool, bytes, 8 * bytes); |
75 | entropy_available = rand_pool_entropy_available(pool); |
76 | } |
77 | if (entropy_available > 0) |
78 | return entropy_available; |
79 | # else |
80 | bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); |
81 | buffer = rand_pool_add_begin(pool, bytes_needed); |
82 | if (buffer != NULL) { |
83 | size_t bytes = 0; |
84 | /* poll the CryptoAPI PRNG */ |
85 | if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, |
86 | CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { |
87 | if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) |
88 | bytes = bytes_needed; |
89 | |
90 | CryptReleaseContext(hProvider, 0); |
91 | } |
92 | |
93 | rand_pool_add_end(pool, bytes, 8 * bytes); |
94 | entropy_available = rand_pool_entropy_available(pool); |
95 | } |
96 | if (entropy_available > 0) |
97 | return entropy_available; |
98 | |
99 | bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); |
100 | buffer = rand_pool_add_begin(pool, bytes_needed); |
101 | if (buffer != NULL) { |
102 | size_t bytes = 0; |
103 | /* poll the Pentium PRG with CryptoAPI */ |
104 | if (CryptAcquireContextW(&hProvider, NULL, |
105 | INTEL_DEF_PROV, PROV_INTEL_SEC, |
106 | CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { |
107 | if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) |
108 | bytes = bytes_needed; |
109 | |
110 | CryptReleaseContext(hProvider, 0); |
111 | } |
112 | rand_pool_add_end(pool, bytes, 8 * bytes); |
113 | entropy_available = rand_pool_entropy_available(pool); |
114 | } |
115 | if (entropy_available > 0) |
116 | return entropy_available; |
117 | # endif |
118 | |
119 | return rand_pool_entropy_available(pool); |
120 | } |
121 | |
122 | |
123 | int rand_pool_add_nonce_data(RAND_POOL *pool) |
124 | { |
125 | struct { |
126 | DWORD pid; |
127 | DWORD tid; |
128 | FILETIME time; |
129 | } data; |
130 | |
131 | /* Erase the entire structure including any padding */ |
132 | memset(&data, 0, sizeof(data)); |
133 | |
134 | /* |
135 | * Add process id, thread id, and a high resolution timestamp to |
136 | * ensure that the nonce is unique with high probability for |
137 | * different process instances. |
138 | */ |
139 | data.pid = GetCurrentProcessId(); |
140 | data.tid = GetCurrentThreadId(); |
141 | GetSystemTimeAsFileTime(&data.time); |
142 | |
143 | return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); |
144 | } |
145 | |
146 | int rand_pool_add_additional_data(RAND_POOL *pool) |
147 | { |
148 | struct { |
149 | DWORD tid; |
150 | LARGE_INTEGER time; |
151 | } data; |
152 | |
153 | /* Erase the entire structure including any padding */ |
154 | memset(&data, 0, sizeof(data)); |
155 | |
156 | /* |
157 | * Add some noise from the thread id and a high resolution timer. |
158 | * The thread id adds a little randomness if the drbg is accessed |
159 | * concurrently (which is the case for the <master> drbg). |
160 | */ |
161 | data.tid = GetCurrentThreadId(); |
162 | QueryPerformanceCounter(&data.time); |
163 | return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); |
164 | } |
165 | |
166 | # if !defined(OPENSSL_NO_DEPRECATED_1_1_0) && !defined(FIPS_MODE) |
167 | int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam) |
168 | { |
169 | RAND_poll(); |
170 | return RAND_status(); |
171 | } |
172 | |
173 | void RAND_screen(void) |
174 | { |
175 | RAND_poll(); |
176 | } |
177 | # endif |
178 | |
179 | int rand_pool_init(void) |
180 | { |
181 | return 1; |
182 | } |
183 | |
184 | void rand_pool_cleanup(void) |
185 | { |
186 | } |
187 | |
188 | void rand_pool_keep_random_devices_open(int keep) |
189 | { |
190 | } |
191 | |
192 | #endif |
193 | |