]>
Commit | Line | Data |
---|---|---|
12fb8c3d | 1 | /* |
33388b44 | 2 | * Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved. |
12fb8c3d | 3 | * |
909f1a2e | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
12fb8c3d 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 | |
8 | */ | |
9 | ||
3f078163 P |
10 | /* |
11 | * RAND_DRBG_set is deprecated for public use, but still ok for | |
12 | * internal use. | |
13 | */ | |
14 | #include "internal/deprecated.h" | |
15 | ||
12fb8c3d | 16 | #include <string.h> |
176db6dc | 17 | #include "internal/nelem.h" |
12fb8c3d RS |
18 | #include <openssl/crypto.h> |
19 | #include <openssl/err.h> | |
20 | #include <openssl/rand.h> | |
21 | #include <openssl/obj_mac.h> | |
22 | #include <openssl/evp.h> | |
23 | #include <openssl/aes.h> | |
706457b7 | 24 | #include "../crypto/rand/rand_local.h" |
25f2138b | 25 | #include "../include/crypto/rand.h" |
3f078163 P |
26 | #include "../providers/implementations/rands/drbg_local.h" |
27 | #include "../crypto/evp/evp_local.h" | |
12fb8c3d | 28 | |
440bce8f KR |
29 | #if defined(_WIN32) |
30 | # include <windows.h> | |
31 | #endif | |
32 | ||
84952925 DMSP |
33 | |
34 | #if defined(OPENSSL_SYS_UNIX) | |
35 | # include <sys/types.h> | |
36 | # include <sys/wait.h> | |
37 | # include <unistd.h> | |
38 | #endif | |
39 | ||
12fb8c3d RS |
40 | #include "testutil.h" |
41 | #include "drbgtest.h" | |
42 | ||
7d615e21 P |
43 | /* |
44 | * DRBG generate wrappers | |
45 | */ | |
46 | static int gen_bytes(EVP_RAND_CTX *drbg, unsigned char *buf, int num) | |
47 | { | |
48 | const RAND_METHOD *meth = RAND_get_rand_method(); | |
12fb8c3d | 49 | |
7d615e21 P |
50 | if (meth != NULL && meth != RAND_OpenSSL()) { |
51 | if (meth->bytes != NULL) | |
52 | return meth->bytes(buf, num); | |
53 | return -1; | |
54 | } | |
8164d91d | 55 | |
7d615e21 P |
56 | if (drbg != NULL) |
57 | return EVP_RAND_generate(drbg, buf, num, 0, 0, NULL, 0); | |
58 | return 0; | |
59 | } | |
12fb8c3d | 60 | |
7d615e21 P |
61 | static int rand_bytes(unsigned char *buf, int num) |
62 | { | |
63 | return gen_bytes(RAND_get0_public(NULL), buf, num); | |
64 | } | |
8bf36651 | 65 | |
7d615e21 P |
66 | static int rand_priv_bytes(unsigned char *buf, int num) |
67 | { | |
68 | return gen_bytes(RAND_get0_private(NULL), buf, num); | |
69 | } | |
12fb8c3d | 70 | |
3f078163 P |
71 | /* |
72 | * DRBG query functions | |
73 | */ | |
7d615e21 | 74 | static int state(EVP_RAND_CTX *drbg) |
3f078163 | 75 | { |
7d615e21 | 76 | return EVP_RAND_state(drbg); |
3f078163 P |
77 | } |
78 | ||
7d615e21 | 79 | static unsigned int query_rand_uint(EVP_RAND_CTX *drbg, const char *name) |
3f078163 P |
80 | { |
81 | OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; | |
82 | unsigned int n; | |
83 | ||
84 | *params = OSSL_PARAM_construct_uint(name, &n); | |
7d615e21 | 85 | if (EVP_RAND_get_ctx_params(drbg, params)) |
3f078163 P |
86 | return n; |
87 | return 0; | |
88 | } | |
89 | ||
3f078163 | 90 | #define DRBG_UINT(name) \ |
7d615e21 | 91 | static unsigned int name(EVP_RAND_CTX *drbg) \ |
3f078163 P |
92 | { \ |
93 | return query_rand_uint(drbg, #name); \ | |
94 | } | |
3f078163 P |
95 | DRBG_UINT(reseed_counter) |
96 | ||
7d615e21 | 97 | static PROV_DRBG *prov_rand(EVP_RAND_CTX *drbg) |
d1768e82 | 98 | { |
7d615e21 | 99 | return (PROV_DRBG *)drbg->data; |
d1768e82 DMSP |
100 | } |
101 | ||
7d615e21 | 102 | static void set_reseed_counter(EVP_RAND_CTX *drbg, unsigned int n) |
3f078163 P |
103 | { |
104 | PROV_DRBG *p = prov_rand(drbg); | |
105 | ||
106 | p->reseed_counter = n; | |
107 | } | |
108 | ||
7d615e21 | 109 | static void inc_reseed_counter(EVP_RAND_CTX *drbg) |
3f078163 P |
110 | { |
111 | set_reseed_counter(drbg, reseed_counter(drbg) + 1); | |
112 | } | |
113 | ||
7d615e21 | 114 | static time_t reseed_time(EVP_RAND_CTX *drbg) |
3f078163 P |
115 | { |
116 | OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; | |
117 | time_t t; | |
118 | ||
119 | *params = OSSL_PARAM_construct_time_t(OSSL_DRBG_PARAM_RESEED_TIME, &t); | |
7d615e21 | 120 | if (EVP_RAND_get_ctx_params(drbg, params)) |
3f078163 P |
121 | return t; |
122 | return 0; | |
123 | } | |
124 | ||
3f078163 P |
125 | /* |
126 | * When building the FIPS module, it isn't possible to disable the continuous | |
127 | * RNG tests. Tests that require this are skipped. | |
128 | */ | |
129 | static int crngt_skip(void) | |
130 | { | |
131 | #ifdef FIPS_MODULE | |
132 | return 1; | |
133 | #else | |
134 | return 0; | |
135 | #endif | |
136 | } | |
137 | ||
d69226a3 P |
138 | /* |
139 | * Disable CRNG testing if it is enabled. | |
3f078163 P |
140 | * This stub remains to indicate the calling locations where it is necessary. |
141 | * Once the RNG infrastructure is able to disable these tests, it should be | |
142 | * reconstituted. | |
d69226a3 | 143 | */ |
7d615e21 | 144 | static int disable_crngt(EVP_RAND_CTX *drbg) |
12fb8c3d | 145 | { |
12fb8c3d RS |
146 | return 1; |
147 | } | |
148 | ||
149 | /* | |
7d615e21 | 150 | * Generates random output using rand_bytes() and rand_priv_bytes() |
a93ba405 DMSP |
151 | * and checks whether the three shared DRBGs were reseeded as |
152 | * expected. | |
153 | * | |
154 | * |expect_success|: expected outcome (as reported by RAND_status()) | |
ce3080e9 | 155 | * |primary|, |public|, |private|: pointers to the three shared DRBGs |
a93ba405 DMSP |
156 | * |expect_xxx_reseed| = |
157 | * 1: it is expected that the specified DRBG is reseeded | |
158 | * 0: it is expected that the specified DRBG is not reseeded | |
159 | * -1: don't check whether the specified DRBG was reseeded or not | |
2bb1b5dd BE |
160 | * |reseed_time|: if nonzero, used instead of time(NULL) to set the |
161 | * |before_reseed| time. | |
a93ba405 DMSP |
162 | */ |
163 | static int test_drbg_reseed(int expect_success, | |
7d615e21 P |
164 | EVP_RAND_CTX *primary, |
165 | EVP_RAND_CTX *public, | |
166 | EVP_RAND_CTX *private, | |
ce3080e9 | 167 | int expect_primary_reseed, |
a93ba405 | 168 | int expect_public_reseed, |
2bb1b5dd | 169 | int expect_private_reseed, |
3f078163 | 170 | time_t reseed_when |
a93ba405 DMSP |
171 | ) |
172 | { | |
173 | unsigned char buf[32]; | |
08a65d96 | 174 | time_t before_reseed, after_reseed; |
a93ba405 | 175 | int expected_state = (expect_success ? DRBG_READY : DRBG_ERROR); |
ce3080e9 | 176 | unsigned int primary_reseed, public_reseed, private_reseed; |
a93ba405 DMSP |
177 | |
178 | /* | |
179 | * step 1: check preconditions | |
180 | */ | |
181 | ||
182 | /* Test whether seed propagation is enabled */ | |
ce3080e9 | 183 | if (!TEST_int_ne(primary_reseed = reseed_counter(primary), 0) |
3f078163 P |
184 | || !TEST_int_ne(public_reseed = reseed_counter(public), 0) |
185 | || !TEST_int_ne(private_reseed = reseed_counter(private), 0)) | |
a93ba405 DMSP |
186 | return 0; |
187 | ||
188 | /* | |
189 | * step 2: generate random output | |
190 | */ | |
191 | ||
3f078163 P |
192 | if (reseed_when == 0) |
193 | reseed_when = time(NULL); | |
2bb1b5dd | 194 | |
a93ba405 | 195 | /* Generate random output from the public and private DRBG */ |
ce3080e9 | 196 | before_reseed = expect_primary_reseed == 1 ? reseed_when : 0; |
7d615e21 P |
197 | if (!TEST_int_eq(rand_bytes(buf, sizeof(buf)), expect_success) |
198 | || !TEST_int_eq(rand_priv_bytes(buf, sizeof(buf)), expect_success)) | |
a93ba405 | 199 | return 0; |
08a65d96 | 200 | after_reseed = time(NULL); |
a93ba405 DMSP |
201 | |
202 | ||
203 | /* | |
204 | * step 3: check postconditions | |
205 | */ | |
75e2c877 | 206 | |
a93ba405 | 207 | /* Test whether reseeding succeeded as expected */ |
7d615e21 P |
208 | if (!TEST_int_eq(state(primary), expected_state) |
209 | || !TEST_int_eq(state(public), expected_state) | |
3f078163 | 210 | || !TEST_int_eq(state(private), expected_state)) |
75e2c877 | 211 | return 0; |
a93ba405 | 212 | |
ce3080e9 P |
213 | if (expect_primary_reseed >= 0) { |
214 | /* Test whether primary DRBG was reseeded as expected */ | |
215 | if (!TEST_int_ge(reseed_counter(primary), primary_reseed)) | |
a93ba405 DMSP |
216 | return 0; |
217 | } | |
218 | ||
219 | if (expect_public_reseed >= 0) { | |
220 | /* Test whether public DRBG was reseeded as expected */ | |
3f078163 P |
221 | if (!TEST_int_ge(reseed_counter(public), public_reseed) |
222 | || !TEST_uint_ge(reseed_counter(public), | |
ce3080e9 | 223 | reseed_counter(primary))) |
a93ba405 DMSP |
224 | return 0; |
225 | } | |
226 | ||
227 | if (expect_private_reseed >= 0) { | |
228 | /* Test whether public DRBG was reseeded as expected */ | |
3f078163 P |
229 | if (!TEST_int_ge(reseed_counter(private), private_reseed) |
230 | || !TEST_uint_ge(reseed_counter(private), | |
ce3080e9 | 231 | reseed_counter(primary))) |
a93ba405 DMSP |
232 | return 0; |
233 | } | |
234 | ||
235 | if (expect_success == 1) { | |
ce3080e9 P |
236 | /* Test whether reseed time of primary DRBG is set correctly */ |
237 | if (!TEST_time_t_le(before_reseed, reseed_time(primary)) | |
238 | || !TEST_time_t_le(reseed_time(primary), after_reseed)) | |
08a65d96 DMSP |
239 | return 0; |
240 | ||
ce3080e9 P |
241 | /* Test whether reseed times of child DRBGs are synchronized with primary */ |
242 | if (!TEST_time_t_ge(reseed_time(public), reseed_time(primary)) | |
243 | || !TEST_time_t_ge(reseed_time(private), reseed_time(primary))) | |
08a65d96 | 244 | return 0; |
a93ba405 DMSP |
245 | } else { |
246 | ERR_clear_error(); | |
247 | } | |
248 | ||
75e2c877 RS |
249 | return 1; |
250 | } | |
251 | ||
84952925 DMSP |
252 | |
253 | #if defined(OPENSSL_SYS_UNIX) | |
254 | /* | |
ce3080e9 | 255 | * Test whether primary, public and private DRBG are reseeded after |
84952925 DMSP |
256 | * forking the process. |
257 | */ | |
7d615e21 P |
258 | static int test_drbg_reseed_after_fork(EVP_RAND_CTX *primary, |
259 | EVP_RAND_CTX *public, | |
260 | EVP_RAND_CTX *private) | |
84952925 DMSP |
261 | { |
262 | pid_t pid; | |
263 | int status=0; | |
264 | ||
265 | pid = fork(); | |
266 | if (!TEST_int_ge(pid, 0)) | |
267 | return 0; | |
268 | ||
269 | if (pid > 0) { | |
270 | /* I'm the parent; wait for the child and check its exit code */ | |
271 | return TEST_int_eq(waitpid(pid, &status, 0), pid) && TEST_int_eq(status, 0); | |
272 | } | |
273 | ||
274 | /* I'm the child; check whether all three DRBGs reseed. */ | |
ce3080e9 | 275 | if (!TEST_true(test_drbg_reseed(1, primary, public, private, 1, 1, 1, 0))) |
84952925 | 276 | status = 1; |
84952925 DMSP |
277 | exit(status); |
278 | } | |
279 | #endif | |
280 | ||
a93ba405 DMSP |
281 | /* |
282 | * Test whether the default rand_method (RAND_OpenSSL()) is | |
283 | * setup correctly, in particular whether reseeding works | |
284 | * as designed. | |
285 | */ | |
8817215d | 286 | static int test_rand_drbg_reseed(void) |
a93ba405 | 287 | { |
7d615e21 | 288 | EVP_RAND_CTX *primary, *public, *private; |
a93ba405 | 289 | unsigned char rand_add_buf[256]; |
3f078163 | 290 | int rv = 0; |
2bb1b5dd | 291 | time_t before_reseed; |
a93ba405 | 292 | |
3f078163 P |
293 | if (crngt_skip()) |
294 | return TEST_skip("CRNGT cannot be disabled"); | |
295 | ||
a93ba405 DMSP |
296 | /* Check whether RAND_OpenSSL() is the default method */ |
297 | if (!TEST_ptr_eq(RAND_get_rand_method(), RAND_OpenSSL())) | |
298 | return 0; | |
299 | ||
300 | /* All three DRBGs should be non-null */ | |
7d615e21 P |
301 | if (!TEST_ptr(primary = RAND_get0_primary(NULL)) |
302 | || !TEST_ptr(public = RAND_get0_public(NULL)) | |
303 | || !TEST_ptr(private = RAND_get0_private(NULL))) | |
a93ba405 DMSP |
304 | return 0; |
305 | ||
ce3080e9 | 306 | /* There should be three distinct DRBGs, two of them chained to primary */ |
a93ba405 | 307 | if (!TEST_ptr_ne(public, private) |
ce3080e9 P |
308 | || !TEST_ptr_ne(public, primary) |
309 | || !TEST_ptr_ne(private, primary) | |
7d615e21 P |
310 | || !TEST_ptr_eq(prov_rand(public)->parent, prov_rand(primary)) |
311 | || !TEST_ptr_eq(prov_rand(private)->parent, prov_rand(primary))) | |
a93ba405 DMSP |
312 | return 0; |
313 | ||
ce3080e9 P |
314 | /* Disable CRNG testing for the primary DRBG */ |
315 | if (!TEST_true(disable_crngt(primary))) | |
d69226a3 P |
316 | return 0; |
317 | ||
59f124f9 | 318 | /* uninstantiate the three global DRBGs */ |
7d615e21 P |
319 | EVP_RAND_uninstantiate(primary); |
320 | EVP_RAND_uninstantiate(private); | |
321 | EVP_RAND_uninstantiate(public); | |
a93ba405 | 322 | |
59f124f9 DMSP |
323 | |
324 | /* | |
325 | * Test initial seeding of shared DRBGs | |
326 | */ | |
ce3080e9 | 327 | if (!TEST_true(test_drbg_reseed(1, primary, public, private, 1, 1, 1, 0))) |
59f124f9 | 328 | goto error; |
59f124f9 DMSP |
329 | |
330 | ||
a93ba405 | 331 | /* |
59f124f9 | 332 | * Test initial state of shared DRBGs |
a93ba405 | 333 | */ |
ce3080e9 | 334 | if (!TEST_true(test_drbg_reseed(1, primary, public, private, 0, 0, 0, 0))) |
a93ba405 | 335 | goto error; |
a93ba405 DMSP |
336 | |
337 | /* | |
338 | * Test whether the public and private DRBG are both reseeded when their | |
ce3080e9 | 339 | * reseed counters differ from the primary's reseed counter. |
a93ba405 | 340 | */ |
ce3080e9 P |
341 | inc_reseed_counter(primary); |
342 | if (!TEST_true(test_drbg_reseed(1, primary, public, private, 0, 1, 1, 0))) | |
a93ba405 | 343 | goto error; |
a93ba405 DMSP |
344 | |
345 | /* | |
346 | * Test whether the public DRBG is reseeded when its reseed counter differs | |
ce3080e9 | 347 | * from the primary's reseed counter. |
a93ba405 | 348 | */ |
ce3080e9 | 349 | inc_reseed_counter(primary); |
3f078163 | 350 | inc_reseed_counter(private); |
ce3080e9 | 351 | if (!TEST_true(test_drbg_reseed(1, primary, public, private, 0, 1, 0, 0))) |
a93ba405 | 352 | goto error; |
a93ba405 DMSP |
353 | |
354 | /* | |
355 | * Test whether the private DRBG is reseeded when its reseed counter differs | |
ce3080e9 | 356 | * from the primary's reseed counter. |
a93ba405 | 357 | */ |
ce3080e9 | 358 | inc_reseed_counter(primary); |
3f078163 | 359 | inc_reseed_counter(public); |
ce3080e9 | 360 | if (!TEST_true(test_drbg_reseed(1, primary, public, private, 0, 0, 1, 0))) |
a93ba405 | 361 | goto error; |
a93ba405 | 362 | |
84952925 | 363 | #if defined(OPENSSL_SYS_UNIX) |
ce3080e9 | 364 | if (!TEST_true(test_drbg_reseed_after_fork(primary, public, private))) |
84952925 DMSP |
365 | goto error; |
366 | #endif | |
a93ba405 DMSP |
367 | |
368 | /* fill 'randomness' buffer with some arbitrary data */ | |
369 | memset(rand_add_buf, 'r', sizeof(rand_add_buf)); | |
370 | ||
f844f9eb | 371 | #ifndef FIPS_MODULE |
a93ba405 | 372 | /* |
2bb1b5dd BE |
373 | * Test whether all three DRBGs are reseeded by RAND_add(). |
374 | * The before_reseed time has to be measured here and passed into the | |
ce3080e9 | 375 | * test_drbg_reseed() test, because the primary DRBG gets already reseeded |
2bb1b5dd | 376 | * in RAND_add(), whence the check for the condition |
ce3080e9 | 377 | * before_reseed <= reseed_time(primary) will fail if the time value happens |
2bb1b5dd | 378 | * to increase between the RAND_add() and the test_drbg_reseed() call. |
a93ba405 | 379 | */ |
2bb1b5dd | 380 | before_reseed = time(NULL); |
a93ba405 | 381 | RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf)); |
ce3080e9 | 382 | if (!TEST_true(test_drbg_reseed(1, primary, public, private, 1, 1, 1, |
2bb1b5dd | 383 | before_reseed))) |
a93ba405 | 384 | goto error; |
f844f9eb | 385 | #else /* FIPS_MODULE */ |
3a50a8a9 DMSP |
386 | /* |
387 | * In FIPS mode, random data provided by the application via RAND_add() | |
388 | * is not considered a trusted entropy source. It is only treated as | |
389 | * additional_data and no reseeding is forced. This test assures that | |
390 | * no reseeding occurs. | |
391 | */ | |
392 | before_reseed = time(NULL); | |
393 | RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf)); | |
ce3080e9 | 394 | if (!TEST_true(test_drbg_reseed(1, primary, public, private, 0, 0, 0, |
3a50a8a9 DMSP |
395 | before_reseed))) |
396 | goto error; | |
3a50a8a9 | 397 | #endif |
a93ba405 DMSP |
398 | |
399 | rv = 1; | |
400 | ||
401 | error: | |
3f078163 | 402 | return rv; |
a93ba405 DMSP |
403 | } |
404 | ||
440bce8f | 405 | #if defined(OPENSSL_THREADS) |
43687d68 DMSP |
406 | static int multi_thread_rand_bytes_succeeded = 1; |
407 | static int multi_thread_rand_priv_bytes_succeeded = 1; | |
440bce8f | 408 | |
7d615e21 P |
409 | static int set_reseed_time_interval(EVP_RAND_CTX *drbg, int t) |
410 | { | |
411 | OSSL_PARAM params[2]; | |
412 | ||
413 | params[0] = OSSL_PARAM_construct_int(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL, | |
414 | &t); | |
415 | params[1] = OSSL_PARAM_construct_end(); | |
416 | return EVP_RAND_set_ctx_params(drbg, params); | |
417 | } | |
418 | ||
440bce8f KR |
419 | static void run_multi_thread_test(void) |
420 | { | |
421 | unsigned char buf[256]; | |
422 | time_t start = time(NULL); | |
7d615e21 | 423 | EVP_RAND_CTX *public = NULL, *private = NULL; |
440bce8f | 424 | |
7d615e21 P |
425 | if (!TEST_ptr(public = RAND_get0_public(NULL)) |
426 | || !TEST_ptr(private = RAND_get0_private(NULL)) | |
427 | || !TEST_true(set_reseed_time_interval(private, 1)) | |
428 | || !TEST_true(set_reseed_time_interval(public, 1))) { | |
7ecd6c51 BE |
429 | multi_thread_rand_bytes_succeeded = 0; |
430 | return; | |
431 | } | |
440bce8f KR |
432 | |
433 | do { | |
7d615e21 | 434 | if (rand_bytes(buf, sizeof(buf)) <= 0) |
43687d68 | 435 | multi_thread_rand_bytes_succeeded = 0; |
7d615e21 | 436 | if (rand_priv_bytes(buf, sizeof(buf)) <= 0) |
43687d68 | 437 | multi_thread_rand_priv_bytes_succeeded = 0; |
440bce8f | 438 | } |
7d615e21 | 439 | while (time(NULL) - start < 5); |
440bce8f KR |
440 | } |
441 | ||
442 | # if defined(OPENSSL_SYS_WINDOWS) | |
443 | ||
444 | typedef HANDLE thread_t; | |
445 | ||
446 | static DWORD WINAPI thread_run(LPVOID arg) | |
447 | { | |
448 | run_multi_thread_test(); | |
03cdfe1e RL |
449 | /* |
450 | * Because we're linking with a static library, we must stop each | |
451 | * thread explicitly, or so says OPENSSL_thread_stop(3) | |
452 | */ | |
453 | OPENSSL_thread_stop(); | |
440bce8f KR |
454 | return 0; |
455 | } | |
456 | ||
457 | static int run_thread(thread_t *t) | |
458 | { | |
459 | *t = CreateThread(NULL, 0, thread_run, NULL, 0, NULL); | |
460 | return *t != NULL; | |
461 | } | |
462 | ||
463 | static int wait_for_thread(thread_t thread) | |
464 | { | |
465 | return WaitForSingleObject(thread, INFINITE) == 0; | |
466 | } | |
467 | ||
468 | # else | |
469 | ||
470 | typedef pthread_t thread_t; | |
471 | ||
472 | static void *thread_run(void *arg) | |
473 | { | |
474 | run_multi_thread_test(); | |
03cdfe1e RL |
475 | /* |
476 | * Because we're linking with a static library, we must stop each | |
477 | * thread explicitly, or so says OPENSSL_thread_stop(3) | |
478 | */ | |
479 | OPENSSL_thread_stop(); | |
440bce8f KR |
480 | return NULL; |
481 | } | |
482 | ||
483 | static int run_thread(thread_t *t) | |
484 | { | |
485 | return pthread_create(t, NULL, thread_run, NULL) == 0; | |
486 | } | |
487 | ||
488 | static int wait_for_thread(thread_t thread) | |
489 | { | |
490 | return pthread_join(thread, NULL) == 0; | |
491 | } | |
492 | ||
493 | # endif | |
494 | ||
495 | /* | |
496 | * The main thread will also run the test, so we'll have THREADS+1 parallel | |
497 | * tests running | |
498 | */ | |
43687d68 | 499 | # define THREADS 3 |
440bce8f KR |
500 | |
501 | static int test_multi_thread(void) | |
502 | { | |
503 | thread_t t[THREADS]; | |
504 | int i; | |
505 | ||
506 | for (i = 0; i < THREADS; i++) | |
507 | run_thread(&t[i]); | |
508 | run_multi_thread_test(); | |
509 | for (i = 0; i < THREADS; i++) | |
510 | wait_for_thread(t[i]); | |
43687d68 DMSP |
511 | |
512 | if (!TEST_true(multi_thread_rand_bytes_succeeded)) | |
513 | return 0; | |
514 | if (!TEST_true(multi_thread_rand_priv_bytes_succeeded)) | |
515 | return 0; | |
516 | ||
440bce8f KR |
517 | return 1; |
518 | } | |
519 | #endif | |
12fb8c3d | 520 | |
7d615e21 P |
521 | static EVP_RAND_CTX *new_drbg(EVP_RAND_CTX *parent) |
522 | { | |
523 | OSSL_PARAM params[2]; | |
524 | EVP_RAND *rand = NULL; | |
525 | EVP_RAND_CTX *drbg = NULL; | |
526 | ||
527 | params[0] = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER, | |
528 | "AES-256-CTR", 0); | |
529 | params[1] = OSSL_PARAM_construct_end(); | |
530 | ||
531 | if (!TEST_ptr(rand = EVP_RAND_fetch(NULL, "CTR-DRBG", NULL)) | |
532 | || !TEST_ptr(drbg = EVP_RAND_CTX_new(rand, parent)) | |
533 | || !TEST_true(EVP_RAND_set_ctx_params(drbg, params))) { | |
534 | EVP_RAND_CTX_rand(drbg); | |
535 | EVP_RAND_free(rand); | |
536 | drbg = NULL; | |
537 | } | |
538 | return drbg; | |
539 | } | |
540 | ||
65175163 P |
541 | static int test_rand_drbg_prediction_resistance(void) |
542 | { | |
7d615e21 | 543 | EVP_RAND_CTX *x = NULL, *y = NULL, *z = NULL; |
65175163 | 544 | unsigned char buf1[51], buf2[sizeof(buf1)]; |
ce3080e9 | 545 | int ret = 0, xreseed, yreseed, zreseed; |
65175163 | 546 | |
3f078163 P |
547 | if (crngt_skip()) |
548 | return TEST_skip("CRNGT cannot be disabled"); | |
549 | ||
65175163 | 550 | /* Initialise a three long DRBG chain */ |
7d615e21 | 551 | if (!TEST_ptr(x = new_drbg(NULL)) |
ce3080e9 | 552 | || !TEST_true(disable_crngt(x)) |
7d615e21 P |
553 | || !TEST_true(EVP_RAND_instantiate(x, 0, 0, NULL, 0)) |
554 | || !TEST_ptr(y = new_drbg(x)) | |
555 | || !TEST_true(EVP_RAND_instantiate(y, 0, 0, NULL, 0)) | |
556 | || !TEST_ptr(z = new_drbg(y)) | |
557 | || !TEST_true(EVP_RAND_instantiate(z, 0, 0, NULL, 0))) | |
65175163 P |
558 | goto err; |
559 | ||
ce3080e9 P |
560 | /* |
561 | * During a normal reseed, only the last DRBG in the chain should | |
562 | * be reseeded. | |
563 | */ | |
564 | inc_reseed_counter(y); | |
565 | xreseed = reseed_counter(x); | |
566 | yreseed = reseed_counter(y); | |
567 | zreseed = reseed_counter(z); | |
7d615e21 | 568 | if (!TEST_true(EVP_RAND_reseed(z, 0, NULL, 0, NULL, 0)) |
ce3080e9 P |
569 | || !TEST_int_eq(reseed_counter(x), xreseed) |
570 | || !TEST_int_eq(reseed_counter(y), yreseed) | |
571 | || !TEST_int_gt(reseed_counter(z), zreseed)) | |
65175163 P |
572 | goto err; |
573 | ||
574 | /* | |
575 | * When prediction resistance is requested, the request should be | |
ce3080e9 | 576 | * propagated to the primary, so that the entire DRBG chain reseeds. |
65175163 | 577 | */ |
ce3080e9 | 578 | zreseed = reseed_counter(z); |
7d615e21 | 579 | if (!TEST_true(EVP_RAND_reseed(z, 1, NULL, 0, NULL, 0)) |
ce3080e9 P |
580 | || !TEST_int_gt(reseed_counter(x), xreseed) |
581 | || !TEST_int_gt(reseed_counter(y), yreseed) | |
582 | || !TEST_int_gt(reseed_counter(z), zreseed)) | |
65175163 P |
583 | goto err; |
584 | ||
ce3080e9 P |
585 | /* |
586 | * During a normal generate, only the last DRBG should be reseed */ | |
587 | inc_reseed_counter(y); | |
588 | xreseed = reseed_counter(x); | |
589 | yreseed = reseed_counter(y); | |
590 | zreseed = reseed_counter(z); | |
7d615e21 | 591 | if (!TEST_true(EVP_RAND_generate(z, buf1, sizeof(buf1), 0, 0, NULL, 0)) |
ce3080e9 P |
592 | || !TEST_int_eq(reseed_counter(x), xreseed) |
593 | || !TEST_int_eq(reseed_counter(y), yreseed) | |
594 | || !TEST_int_gt(reseed_counter(z), zreseed)) | |
65175163 P |
595 | goto err; |
596 | ||
597 | /* | |
598 | * When a prediction resistant generate is requested, the request | |
ce3080e9 | 599 | * should be propagated to the primary, reseeding the entire DRBG chain. |
65175163 | 600 | */ |
ce3080e9 | 601 | zreseed = reseed_counter(z); |
7d615e21 | 602 | if (!TEST_true(EVP_RAND_generate(z, buf2, sizeof(buf2), 0, 1, NULL, 0)) |
ce3080e9 P |
603 | || !TEST_int_gt(reseed_counter(x), xreseed) |
604 | || !TEST_int_gt(reseed_counter(y), yreseed) | |
605 | || !TEST_int_gt(reseed_counter(z), zreseed) | |
65175163 P |
606 | || !TEST_mem_ne(buf1, sizeof(buf1), buf2, sizeof(buf2))) |
607 | goto err; | |
608 | ||
ce3080e9 P |
609 | /* Verify that a normal reseed still only reseeds the last DRBG */ |
610 | inc_reseed_counter(y); | |
611 | xreseed = reseed_counter(x); | |
612 | yreseed = reseed_counter(y); | |
613 | zreseed = reseed_counter(z); | |
7d615e21 | 614 | if (!TEST_true(EVP_RAND_reseed(z, 0, NULL, 0, NULL, 0)) |
ce3080e9 P |
615 | || !TEST_int_eq(reseed_counter(x), xreseed) |
616 | || !TEST_int_eq(reseed_counter(y), yreseed) | |
617 | || !TEST_int_gt(reseed_counter(z), zreseed)) | |
65175163 P |
618 | goto err; |
619 | ||
620 | ret = 1; | |
621 | err: | |
7d615e21 P |
622 | EVP_RAND_CTX_free(z); |
623 | EVP_RAND_CTX_free(y); | |
624 | EVP_RAND_CTX_free(x); | |
65175163 P |
625 | return ret; |
626 | } | |
627 | ||
ad887416 | 628 | int setup_tests(void) |
12fb8c3d | 629 | { |
64827f40 P |
630 | /* |
631 | * TODO(3.0): figure out why and fix. | |
632 | * Create the primary DRBG here to avoid a memory leak if it is done in | |
633 | * the test cases. | |
634 | */ | |
635 | if (RAND_get0_primary(NULL) == NULL) | |
636 | return 0; | |
8817215d | 637 | ADD_TEST(test_rand_drbg_reseed); |
65175163 | 638 | ADD_TEST(test_rand_drbg_prediction_resistance); |
440bce8f KR |
639 | #if defined(OPENSSL_THREADS) |
640 | ADD_TEST(test_multi_thread); | |
641 | #endif | |
ad887416 | 642 | return 1; |
12fb8c3d | 643 | } |