rand: move rand_{unix,vms,vxworks,win}.c without change to preserve history
[openssl.git] / providers / implementations / rands / seeding / rand_win.c
1 /*
2  * Copyright 1995-2020 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_MODULE)
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