]>
Commit | Line | Data |
---|---|---|
b1322259 | 1 | /* |
fbd2ece1 | 2 | * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. |
2ace287d | 3 | * |
0db63de9 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
b1322259 RS |
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 | |
2ace287d BM |
8 | */ |
9 | ||
b39fc560 | 10 | #include "internal/cryptlib.h" |
c0722725 | 11 | #include <openssl/rand.h> |
bcdea3ba | 12 | #include "prov/rand_pool.h" |
25f2138b | 13 | #include "crypto/rand.h" |
bcdea3ba P |
14 | #include "prov/seeding.h" |
15 | ||
7a8c7288 | 16 | #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) |
8389ec4b RS |
17 | |
18 | # ifndef OPENSSL_RAND_SEED_OS | |
19 | # error "Unsupported seeding method configured; must be os" | |
20 | # endif | |
21 | ||
0f113f3e | 22 | # include <windows.h> |
2621e640 | 23 | /* On Windows Vista or higher use BCrypt instead of the legacy CryptoAPI */ |
d3a1128b BE |
24 | # if defined(_MSC_VER) && _MSC_VER > 1500 /* 1500 = Visual Studio 2008 */ \ |
25 | && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 | |
8389ec4b | 26 | # define USE_BCRYPTGENRANDOM |
0814afcf M |
27 | # endif |
28 | ||
8389ec4b | 29 | # ifdef USE_BCRYPTGENRANDOM |
fa64e633 M |
30 | # include <bcrypt.h> |
31 | # pragma comment(lib, "bcrypt.lib") | |
6191fc86 M |
32 | # ifndef STATUS_SUCCESS |
33 | # define STATUS_SUCCESS ((NTSTATUS)0x00000000L) | |
34 | # endif | |
fa64e633 | 35 | # else |
fa64e633 | 36 | # include <wincrypt.h> |
0f113f3e MC |
37 | /* |
38 | * Intel hardware RNG CSP -- available from | |
c0722725 UM |
39 | * http://developer.intel.com/design/security/rng/redist_license.htm |
40 | */ | |
fa64e633 M |
41 | # define PROV_INTEL_SEC 22 |
42 | # define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider" | |
43 | # endif | |
c0722725 | 44 | |
1dc188ba | 45 | size_t ossl_pool_acquire_entropy(RAND_POOL *pool) |
c0722725 | 46 | { |
8389ec4b | 47 | # ifndef USE_BCRYPTGENRANDOM |
e56f956e | 48 | HCRYPTPROV hProvider; |
fa64e633 | 49 | # endif |
c16de9d8 DMSP |
50 | unsigned char *buffer; |
51 | size_t bytes_needed; | |
52 | size_t entropy_available = 0; | |
53 | ||
0f113f3e | 54 | |
8389ec4b | 55 | # ifdef OPENSSL_RAND_SEED_RDTSC |
7f791b25 | 56 | entropy_available = prov_acquire_entropy_from_tsc(pool); |
c16de9d8 DMSP |
57 | if (entropy_available > 0) |
58 | return entropy_available; | |
8389ec4b | 59 | # endif |
c16de9d8 | 60 | |
8389ec4b | 61 | # ifdef OPENSSL_RAND_SEED_RDCPU |
7f791b25 | 62 | entropy_available = prov_acquire_entropy_from_cpu(pool); |
c16de9d8 DMSP |
63 | if (entropy_available > 0) |
64 | return entropy_available; | |
8389ec4b RS |
65 | # endif |
66 | ||
67 | # ifdef USE_BCRYPTGENRANDOM | |
6ebb49f3 | 68 | bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); |
6decf943 | 69 | buffer = rand_pool_add_begin(pool, bytes_needed); |
c16de9d8 DMSP |
70 | if (buffer != NULL) { |
71 | size_t bytes = 0; | |
72 | if (BCryptGenRandom(NULL, buffer, bytes_needed, | |
c2e33a05 | 73 | BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS) |
c16de9d8 DMSP |
74 | bytes = bytes_needed; |
75 | ||
8e2bec9b RL |
76 | rand_pool_add_end(pool, bytes, 8 * bytes); |
77 | entropy_available = rand_pool_entropy_available(pool); | |
9ed79d8e | 78 | } |
c16de9d8 DMSP |
79 | if (entropy_available > 0) |
80 | return entropy_available; | |
fa64e633 | 81 | # else |
6ebb49f3 | 82 | bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); |
6decf943 | 83 | buffer = rand_pool_add_begin(pool, bytes_needed); |
c16de9d8 DMSP |
84 | if (buffer != NULL) { |
85 | size_t bytes = 0; | |
86 | /* poll the CryptoAPI PRNG */ | |
87 | if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, | |
c2e33a05 | 88 | CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { |
c16de9d8 DMSP |
89 | if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) |
90 | bytes = bytes_needed; | |
91 | ||
92 | CryptReleaseContext(hProvider, 0); | |
0f113f3e | 93 | } |
c16de9d8 | 94 | |
8e2bec9b RL |
95 | rand_pool_add_end(pool, bytes, 8 * bytes); |
96 | entropy_available = rand_pool_entropy_available(pool); | |
0f113f3e | 97 | } |
c16de9d8 DMSP |
98 | if (entropy_available > 0) |
99 | return entropy_available; | |
100 | ||
6ebb49f3 | 101 | bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); |
6decf943 | 102 | buffer = rand_pool_add_begin(pool, bytes_needed); |
c16de9d8 DMSP |
103 | if (buffer != NULL) { |
104 | size_t bytes = 0; | |
105 | /* poll the Pentium PRG with CryptoAPI */ | |
106 | if (CryptAcquireContextW(&hProvider, NULL, | |
107 | INTEL_DEF_PROV, PROV_INTEL_SEC, | |
108 | CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { | |
109 | if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) | |
110 | bytes = bytes_needed; | |
0f113f3e | 111 | |
c16de9d8 | 112 | CryptReleaseContext(hProvider, 0); |
0f113f3e | 113 | } |
8e2bec9b RL |
114 | rand_pool_add_end(pool, bytes, 8 * bytes); |
115 | entropy_available = rand_pool_entropy_available(pool); | |
0f113f3e | 116 | } |
c16de9d8 DMSP |
117 | if (entropy_available > 0) |
118 | return entropy_available; | |
fa64e633 | 119 | # endif |
0f113f3e | 120 | |
6decf943 | 121 | return rand_pool_entropy_available(pool); |
0f113f3e | 122 | } |
2ace287d | 123 | |
5bc6bcf8 | 124 | |
1dc188ba | 125 | int ossl_pool_add_nonce_data(RAND_POOL *pool) |
5bc6bcf8 DMSP |
126 | { |
127 | struct { | |
128 | DWORD pid; | |
129 | DWORD tid; | |
130 | FILETIME time; | |
678d2681 P |
131 | } data; |
132 | ||
133 | /* Erase the entire structure including any padding */ | |
134 | memset(&data, 0, sizeof(data)); | |
5bc6bcf8 DMSP |
135 | |
136 | /* | |
137 | * Add process id, thread id, and a high resolution timestamp to | |
79c44b4e | 138 | * ensure that the nonce is unique with high probability for |
5bc6bcf8 DMSP |
139 | * different process instances. |
140 | */ | |
141 | data.pid = GetCurrentProcessId(); | |
142 | data.tid = GetCurrentThreadId(); | |
143 | GetSystemTimeAsFileTime(&data.time); | |
144 | ||
145 | return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); | |
146 | } | |
147 | ||
148 | int rand_pool_add_additional_data(RAND_POOL *pool) | |
149 | { | |
150 | struct { | |
151 | DWORD tid; | |
152 | LARGE_INTEGER time; | |
678d2681 P |
153 | } data; |
154 | ||
155 | /* Erase the entire structure including any padding */ | |
156 | memset(&data, 0, sizeof(data)); | |
5bc6bcf8 DMSP |
157 | |
158 | /* | |
159 | * Add some noise from the thread id and a high resolution timer. | |
160 | * The thread id adds a little randomness if the drbg is accessed | |
161 | * concurrently (which is the case for the <master> drbg). | |
162 | */ | |
163 | data.tid = GetCurrentThreadId(); | |
164 | QueryPerformanceCounter(&data.time); | |
165 | return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); | |
166 | } | |
167 | ||
c7504aeb P |
168 | int rand_pool_init(void) |
169 | { | |
170 | return 1; | |
171 | } | |
172 | ||
173 | void rand_pool_cleanup(void) | |
174 | { | |
175 | } | |
176 | ||
177 | void rand_pool_keep_random_devices_open(int keep) | |
178 | { | |
179 | } | |
180 | ||
2ace287d | 181 | #endif |