]>
Commit | Line | Data |
---|---|---|
12fb8c3d | 1 | /* |
72a7a702 | 2 | * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved. |
12fb8c3d RS |
3 | * |
4 | * Licensed under the OpenSSL license (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 <string.h> | |
176db6dc | 11 | #include "internal/nelem.h" |
12fb8c3d RS |
12 | #include <openssl/crypto.h> |
13 | #include <openssl/err.h> | |
14 | #include <openssl/rand.h> | |
15 | #include <openssl/obj_mac.h> | |
16 | #include <openssl/evp.h> | |
17 | #include <openssl/aes.h> | |
b5acbf91 | 18 | #include "../crypto/rand/rand_local.h" |
0c994d54 | 19 | #include "../include/crypto/rand.h" |
12fb8c3d | 20 | |
440bce8f KR |
21 | #if defined(_WIN32) |
22 | # include <windows.h> | |
23 | #endif | |
24 | ||
1b0fe00e DMSP |
25 | |
26 | #if defined(OPENSSL_SYS_UNIX) | |
27 | # include <sys/types.h> | |
28 | # include <sys/wait.h> | |
29 | # include <unistd.h> | |
30 | #endif | |
31 | ||
12fb8c3d RS |
32 | #include "testutil.h" |
33 | #include "drbgtest.h" | |
34 | ||
35 | typedef struct drbg_selftest_data_st { | |
36 | int post; | |
37 | int nid; | |
38 | unsigned int flags; | |
39 | ||
40 | /* KAT data for no PR */ | |
aa048aef DMSP |
41 | const unsigned char *entropy; |
42 | size_t entropylen; | |
12fb8c3d RS |
43 | const unsigned char *nonce; |
44 | size_t noncelen; | |
45 | const unsigned char *pers; | |
46 | size_t perslen; | |
47 | const unsigned char *adin; | |
48 | size_t adinlen; | |
aa048aef DMSP |
49 | const unsigned char *entropyreseed; |
50 | size_t entropyreseedlen; | |
12fb8c3d RS |
51 | const unsigned char *adinreseed; |
52 | size_t adinreseedlen; | |
53 | const unsigned char *adin2; | |
54 | size_t adin2len; | |
55 | const unsigned char *expected; | |
56 | size_t exlen; | |
57 | const unsigned char *kat2; | |
58 | size_t kat2len; | |
59 | ||
60 | /* KAT data for PR */ | |
aa048aef DMSP |
61 | const unsigned char *entropy_pr; |
62 | size_t entropylen_pr; | |
12fb8c3d RS |
63 | const unsigned char *nonce_pr; |
64 | size_t noncelen_pr; | |
65 | const unsigned char *pers_pr; | |
66 | size_t perslen_pr; | |
67 | const unsigned char *adin_pr; | |
68 | size_t adinlen_pr; | |
aa048aef DMSP |
69 | const unsigned char *entropypr_pr; |
70 | size_t entropyprlen_pr; | |
12fb8c3d RS |
71 | const unsigned char *ading_pr; |
72 | size_t adinglen_pr; | |
aa048aef DMSP |
73 | const unsigned char *entropyg_pr; |
74 | size_t entropyglen_pr; | |
12fb8c3d RS |
75 | const unsigned char *kat_pr; |
76 | size_t katlen_pr; | |
77 | const unsigned char *kat2_pr; | |
78 | size_t kat2len_pr; | |
79 | } DRBG_SELFTEST_DATA; | |
80 | ||
81 | #define make_drbg_test_data(nid, flag, pr, post) {\ | |
82 | post, nid, flag, \ | |
83 | pr##_entropyinput, sizeof(pr##_entropyinput), \ | |
84 | pr##_nonce, sizeof(pr##_nonce), \ | |
85 | pr##_personalizationstring, sizeof(pr##_personalizationstring), \ | |
86 | pr##_additionalinput, sizeof(pr##_additionalinput), \ | |
87 | pr##_entropyinputreseed, sizeof(pr##_entropyinputreseed), \ | |
88 | pr##_additionalinputreseed, sizeof(pr##_additionalinputreseed), \ | |
89 | pr##_additionalinput2, sizeof(pr##_additionalinput2), \ | |
90 | pr##_int_returnedbits, sizeof(pr##_int_returnedbits), \ | |
91 | pr##_returnedbits, sizeof(pr##_returnedbits), \ | |
92 | pr##_pr_entropyinput, sizeof(pr##_pr_entropyinput), \ | |
93 | pr##_pr_nonce, sizeof(pr##_pr_nonce), \ | |
94 | pr##_pr_personalizationstring, sizeof(pr##_pr_personalizationstring), \ | |
95 | pr##_pr_additionalinput, sizeof(pr##_pr_additionalinput), \ | |
96 | pr##_pr_entropyinputpr, sizeof(pr##_pr_entropyinputpr), \ | |
97 | pr##_pr_additionalinput2, sizeof(pr##_pr_additionalinput2), \ | |
98 | pr##_pr_entropyinputpr2, sizeof(pr##_pr_entropyinputpr2), \ | |
99 | pr##_pr_int_returnedbits, sizeof(pr##_pr_int_returnedbits), \ | |
100 | pr##_pr_returnedbits, sizeof(pr##_pr_returnedbits) \ | |
101 | } | |
102 | ||
8164d91d DMSP |
103 | #define make_drbg_test_data_use_df(nid, pr, p) \ |
104 | make_drbg_test_data(nid, 0, pr, p) | |
105 | ||
106 | #define make_drbg_test_data_no_df(nid, pr, p) \ | |
107 | make_drbg_test_data(nid, RAND_DRBG_FLAG_CTR_NO_DF, pr, p) | |
12fb8c3d RS |
108 | |
109 | static DRBG_SELFTEST_DATA drbg_test[] = { | |
8164d91d DMSP |
110 | make_drbg_test_data_no_df (NID_aes_128_ctr, aes_128_no_df, 0), |
111 | make_drbg_test_data_no_df (NID_aes_192_ctr, aes_192_no_df, 0), | |
112 | make_drbg_test_data_no_df (NID_aes_256_ctr, aes_256_no_df, 1), | |
113 | make_drbg_test_data_use_df(NID_aes_128_ctr, aes_128_use_df, 0), | |
114 | make_drbg_test_data_use_df(NID_aes_192_ctr, aes_192_use_df, 0), | |
115 | make_drbg_test_data_use_df(NID_aes_256_ctr, aes_256_use_df, 1), | |
12fb8c3d RS |
116 | }; |
117 | ||
118 | static int app_data_index; | |
119 | ||
120 | /* | |
75e2c877 | 121 | * Test context data, attached as EXDATA to the RAND_DRBG |
12fb8c3d RS |
122 | */ |
123 | typedef struct test_ctx_st { | |
aa048aef DMSP |
124 | const unsigned char *entropy; |
125 | size_t entropylen; | |
126 | int entropycnt; | |
12fb8c3d RS |
127 | const unsigned char *nonce; |
128 | size_t noncelen; | |
129 | int noncecnt; | |
130 | } TEST_CTX; | |
131 | ||
75e2c877 | 132 | static size_t kat_entropy(RAND_DRBG *drbg, unsigned char **pout, |
eb238134 KR |
133 | int entropy, size_t min_len, size_t max_len, |
134 | int prediction_resistance) | |
12fb8c3d | 135 | { |
75e2c877 | 136 | TEST_CTX *t = (TEST_CTX *)RAND_DRBG_get_ex_data(drbg, app_data_index); |
12fb8c3d | 137 | |
aa048aef DMSP |
138 | t->entropycnt++; |
139 | *pout = (unsigned char *)t->entropy; | |
140 | return t->entropylen; | |
12fb8c3d RS |
141 | } |
142 | ||
75e2c877 | 143 | static size_t kat_nonce(RAND_DRBG *drbg, unsigned char **pout, |
12fb8c3d RS |
144 | int entropy, size_t min_len, size_t max_len) |
145 | { | |
75e2c877 | 146 | TEST_CTX *t = (TEST_CTX *)RAND_DRBG_get_ex_data(drbg, app_data_index); |
12fb8c3d RS |
147 | |
148 | t->noncecnt++; | |
149 | *pout = (unsigned char *)t->nonce; | |
150 | return t->noncelen; | |
151 | } | |
152 | ||
75e2c877 | 153 | static int uninstantiate(RAND_DRBG *drbg) |
12fb8c3d | 154 | { |
75e2c877 | 155 | int ret = drbg == NULL ? 1 : RAND_DRBG_uninstantiate(drbg); |
12fb8c3d RS |
156 | |
157 | ERR_clear_error(); | |
158 | return ret; | |
159 | } | |
160 | ||
161 | /* | |
162 | * Do a single KAT test. Return 0 on failure. | |
163 | */ | |
164 | static int single_kat(DRBG_SELFTEST_DATA *td) | |
165 | { | |
75e2c877 | 166 | RAND_DRBG *drbg = NULL; |
12fb8c3d RS |
167 | TEST_CTX t; |
168 | int failures = 0; | |
169 | unsigned char buff[1024]; | |
170 | ||
171 | /* | |
172 | * Test without PR: Instantiate DRBG with test entropy, nonce and | |
173 | * personalisation string. | |
174 | */ | |
75e2c877 | 175 | if (!TEST_ptr(drbg = RAND_DRBG_new(td->nid, td->flags, NULL))) |
12fb8c3d | 176 | return 0; |
75e2c877 | 177 | if (!TEST_true(RAND_DRBG_set_callbacks(drbg, kat_entropy, NULL, |
12fb8c3d RS |
178 | kat_nonce, NULL))) { |
179 | failures++; | |
180 | goto err; | |
181 | } | |
182 | memset(&t, 0, sizeof(t)); | |
aa048aef DMSP |
183 | t.entropy = td->entropy; |
184 | t.entropylen = td->entropylen; | |
12fb8c3d RS |
185 | t.nonce = td->nonce; |
186 | t.noncelen = td->noncelen; | |
75e2c877 | 187 | RAND_DRBG_set_ex_data(drbg, app_data_index, &t); |
12fb8c3d | 188 | |
75e2c877 RS |
189 | if (!TEST_true(RAND_DRBG_instantiate(drbg, td->pers, td->perslen)) |
190 | || !TEST_true(RAND_DRBG_generate(drbg, buff, td->exlen, 0, | |
12fb8c3d RS |
191 | td->adin, td->adinlen)) |
192 | || !TEST_mem_eq(td->expected, td->exlen, buff, td->exlen)) | |
193 | failures++; | |
194 | ||
195 | /* Reseed DRBG with test entropy and additional input */ | |
aa048aef DMSP |
196 | t.entropy = td->entropyreseed; |
197 | t.entropylen = td->entropyreseedlen; | |
eb238134 | 198 | if (!TEST_true(RAND_DRBG_reseed(drbg, td->adinreseed, td->adinreseedlen, 0) |
75e2c877 | 199 | || !TEST_true(RAND_DRBG_generate(drbg, buff, td->kat2len, 0, |
12fb8c3d RS |
200 | td->adin2, td->adin2len)) |
201 | || !TEST_mem_eq(td->kat2, td->kat2len, buff, td->kat2len))) | |
202 | failures++; | |
75e2c877 | 203 | uninstantiate(drbg); |
12fb8c3d RS |
204 | |
205 | /* | |
206 | * Now test with PR: Instantiate DRBG with test entropy, nonce and | |
207 | * personalisation string. | |
208 | */ | |
75e2c877 RS |
209 | if (!TEST_true(RAND_DRBG_set(drbg, td->nid, td->flags)) |
210 | || !TEST_true(RAND_DRBG_set_callbacks(drbg, kat_entropy, NULL, | |
12fb8c3d RS |
211 | kat_nonce, NULL))) |
212 | failures++; | |
75e2c877 | 213 | RAND_DRBG_set_ex_data(drbg, app_data_index, &t); |
aa048aef DMSP |
214 | t.entropy = td->entropy_pr; |
215 | t.entropylen = td->entropylen_pr; | |
12fb8c3d RS |
216 | t.nonce = td->nonce_pr; |
217 | t.noncelen = td->noncelen_pr; | |
aa048aef | 218 | t.entropycnt = 0; |
12fb8c3d | 219 | t.noncecnt = 0; |
75e2c877 | 220 | if (!TEST_true(RAND_DRBG_instantiate(drbg, td->pers_pr, td->perslen_pr))) |
12fb8c3d RS |
221 | failures++; |
222 | ||
223 | /* | |
224 | * Now generate with PR: we need to supply entropy as this will | |
225 | * perform a reseed operation. | |
226 | */ | |
aa048aef DMSP |
227 | t.entropy = td->entropypr_pr; |
228 | t.entropylen = td->entropyprlen_pr; | |
75e2c877 | 229 | if (!TEST_true(RAND_DRBG_generate(drbg, buff, td->katlen_pr, 1, |
12fb8c3d RS |
230 | td->adin_pr, td->adinlen_pr)) |
231 | || !TEST_mem_eq(td->kat_pr, td->katlen_pr, buff, td->katlen_pr)) | |
232 | failures++; | |
233 | ||
234 | /* | |
235 | * Now generate again with PR: supply new entropy again. | |
236 | */ | |
aa048aef DMSP |
237 | t.entropy = td->entropyg_pr; |
238 | t.entropylen = td->entropyglen_pr; | |
12fb8c3d | 239 | |
75e2c877 | 240 | if (!TEST_true(RAND_DRBG_generate(drbg, buff, td->kat2len_pr, 1, |
12fb8c3d RS |
241 | td->ading_pr, td->adinglen_pr)) |
242 | || !TEST_mem_eq(td->kat2_pr, td->kat2len_pr, | |
243 | buff, td->kat2len_pr)) | |
244 | failures++; | |
245 | ||
246 | err: | |
75e2c877 RS |
247 | uninstantiate(drbg); |
248 | RAND_DRBG_free(drbg); | |
12fb8c3d RS |
249 | return failures == 0; |
250 | } | |
251 | ||
252 | /* | |
253 | * Initialise a DRBG based on selftest data | |
254 | */ | |
75e2c877 | 255 | static int init(RAND_DRBG *drbg, DRBG_SELFTEST_DATA *td, TEST_CTX *t) |
12fb8c3d | 256 | { |
75e2c877 RS |
257 | if (!TEST_true(RAND_DRBG_set(drbg, td->nid, td->flags)) |
258 | || !TEST_true(RAND_DRBG_set_callbacks(drbg, kat_entropy, NULL, | |
12fb8c3d RS |
259 | kat_nonce, NULL))) |
260 | return 0; | |
75e2c877 | 261 | RAND_DRBG_set_ex_data(drbg, app_data_index, t); |
aa048aef DMSP |
262 | t->entropy = td->entropy; |
263 | t->entropylen = td->entropylen; | |
12fb8c3d RS |
264 | t->nonce = td->nonce; |
265 | t->noncelen = td->noncelen; | |
aa048aef | 266 | t->entropycnt = 0; |
12fb8c3d RS |
267 | t->noncecnt = 0; |
268 | return 1; | |
269 | } | |
270 | ||
271 | /* | |
272 | * Initialise and instantiate DRBG based on selftest data | |
273 | */ | |
75e2c877 | 274 | static int instantiate(RAND_DRBG *drbg, DRBG_SELFTEST_DATA *td, |
12fb8c3d RS |
275 | TEST_CTX *t) |
276 | { | |
75e2c877 RS |
277 | if (!TEST_true(init(drbg, td, t)) |
278 | || !TEST_true(RAND_DRBG_instantiate(drbg, td->pers, td->perslen))) | |
12fb8c3d RS |
279 | return 0; |
280 | return 1; | |
281 | } | |
282 | ||
283 | /* | |
284 | * Perform extensive error checking as required by SP800-90. | |
285 | * Induce several failure modes and check an error condition is set. | |
286 | */ | |
287 | static int error_check(DRBG_SELFTEST_DATA *td) | |
288 | { | |
75e2c877 RS |
289 | static char zero[sizeof(RAND_DRBG)]; |
290 | RAND_DRBG *drbg = NULL; | |
12fb8c3d RS |
291 | TEST_CTX t; |
292 | unsigned char buff[1024]; | |
35a34508 | 293 | unsigned int reseed_counter_tmp; |
12fb8c3d RS |
294 | int ret = 0; |
295 | ||
75e2c877 | 296 | if (!TEST_ptr(drbg = RAND_DRBG_new(0, 0, NULL))) |
12fb8c3d RS |
297 | goto err; |
298 | ||
299 | /* | |
300 | * Personalisation string tests | |
301 | */ | |
302 | ||
a5c83db4 | 303 | /* Test detection of too large personalisation string */ |
75e2c877 | 304 | if (!init(drbg, td, &t) |
aa048aef | 305 | || RAND_DRBG_instantiate(drbg, td->pers, drbg->max_perslen + 1) > 0) |
12fb8c3d RS |
306 | goto err; |
307 | ||
308 | /* | |
309 | * Entropy source tests | |
310 | */ | |
311 | ||
35a34508 | 312 | /* Test entropy source failure detection: i.e. returns no data */ |
aa048aef | 313 | t.entropylen = 0; |
75e2c877 | 314 | if (TEST_int_le(RAND_DRBG_instantiate(drbg, td->pers, td->perslen), 0)) |
12fb8c3d RS |
315 | goto err; |
316 | ||
317 | /* Try to generate output from uninstantiated DRBG */ | |
75e2c877 | 318 | if (!TEST_false(RAND_DRBG_generate(drbg, buff, td->exlen, 0, |
12fb8c3d | 319 | td->adin, td->adinlen)) |
75e2c877 | 320 | || !uninstantiate(drbg)) |
12fb8c3d RS |
321 | goto err; |
322 | ||
323 | /* Test insufficient entropy */ | |
aa048aef | 324 | t.entropylen = drbg->min_entropylen - 1; |
75e2c877 RS |
325 | if (!init(drbg, td, &t) |
326 | || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0 | |
327 | || !uninstantiate(drbg)) | |
12fb8c3d RS |
328 | goto err; |
329 | ||
330 | /* Test too much entropy */ | |
aa048aef | 331 | t.entropylen = drbg->max_entropylen + 1; |
75e2c877 RS |
332 | if (!init(drbg, td, &t) |
333 | || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0 | |
334 | || !uninstantiate(drbg)) | |
12fb8c3d RS |
335 | goto err; |
336 | ||
337 | /* | |
338 | * Nonce tests | |
339 | */ | |
340 | ||
341 | /* Test too small nonce */ | |
aa048aef DMSP |
342 | if (drbg->min_noncelen) { |
343 | t.noncelen = drbg->min_noncelen - 1; | |
75e2c877 RS |
344 | if (!init(drbg, td, &t) |
345 | || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0 | |
346 | || !uninstantiate(drbg)) | |
12fb8c3d RS |
347 | goto err; |
348 | } | |
349 | ||
350 | /* Test too large nonce */ | |
aa048aef DMSP |
351 | if (drbg->max_noncelen) { |
352 | t.noncelen = drbg->max_noncelen + 1; | |
75e2c877 RS |
353 | if (!init(drbg, td, &t) |
354 | || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0 | |
355 | || !uninstantiate(drbg)) | |
12fb8c3d RS |
356 | goto err; |
357 | } | |
358 | ||
359 | /* Instantiate with valid data, Check generation is now OK */ | |
75e2c877 RS |
360 | if (!instantiate(drbg, td, &t) |
361 | || !TEST_true(RAND_DRBG_generate(drbg, buff, td->exlen, 0, | |
12fb8c3d RS |
362 | td->adin, td->adinlen))) |
363 | goto err; | |
364 | ||
365 | /* Request too much data for one request */ | |
75e2c877 | 366 | if (!TEST_false(RAND_DRBG_generate(drbg, buff, drbg->max_request + 1, 0, |
12fb8c3d RS |
367 | td->adin, td->adinlen))) |
368 | goto err; | |
369 | ||
370 | /* Try too large additional input */ | |
75e2c877 | 371 | if (!TEST_false(RAND_DRBG_generate(drbg, buff, td->exlen, 0, |
aa048aef | 372 | td->adin, drbg->max_adinlen + 1))) |
12fb8c3d RS |
373 | goto err; |
374 | ||
375 | /* | |
376 | * Check prediction resistance request fails if entropy source | |
377 | * failure. | |
378 | */ | |
aa048aef | 379 | t.entropylen = 0; |
75e2c877 | 380 | if (TEST_false(RAND_DRBG_generate(drbg, buff, td->exlen, 1, |
12fb8c3d | 381 | td->adin, td->adinlen)) |
75e2c877 | 382 | || !uninstantiate(drbg)) |
12fb8c3d RS |
383 | goto err; |
384 | ||
4468b6ed | 385 | /* Instantiate again with valid data */ |
75e2c877 | 386 | if (!instantiate(drbg, td, &t)) |
12fb8c3d | 387 | goto err; |
35a34508 DMSP |
388 | reseed_counter_tmp = drbg->reseed_gen_counter; |
389 | drbg->reseed_gen_counter = drbg->reseed_interval; | |
12fb8c3d RS |
390 | |
391 | /* Generate output and check entropy has been requested for reseed */ | |
aa048aef | 392 | t.entropycnt = 0; |
75e2c877 | 393 | if (!TEST_true(RAND_DRBG_generate(drbg, buff, td->exlen, 0, |
12fb8c3d | 394 | td->adin, td->adinlen)) |
aa048aef | 395 | || !TEST_int_eq(t.entropycnt, 1) |
35a34508 | 396 | || !TEST_int_eq(drbg->reseed_gen_counter, reseed_counter_tmp + 1) |
75e2c877 | 397 | || !uninstantiate(drbg)) |
12fb8c3d RS |
398 | goto err; |
399 | ||
400 | /* | |
401 | * Check prediction resistance request fails if entropy source | |
402 | * failure. | |
403 | */ | |
aa048aef | 404 | t.entropylen = 0; |
75e2c877 | 405 | if (!TEST_false(RAND_DRBG_generate(drbg, buff, td->exlen, 1, |
12fb8c3d | 406 | td->adin, td->adinlen)) |
75e2c877 | 407 | || !uninstantiate(drbg)) |
12fb8c3d RS |
408 | goto err; |
409 | ||
410 | /* Test reseed counter works */ | |
75e2c877 | 411 | if (!instantiate(drbg, td, &t)) |
12fb8c3d | 412 | goto err; |
35a34508 DMSP |
413 | reseed_counter_tmp = drbg->reseed_gen_counter; |
414 | drbg->reseed_gen_counter = drbg->reseed_interval; | |
12fb8c3d RS |
415 | |
416 | /* Generate output and check entropy has been requested for reseed */ | |
aa048aef | 417 | t.entropycnt = 0; |
75e2c877 | 418 | if (!TEST_true(RAND_DRBG_generate(drbg, buff, td->exlen, 0, |
12fb8c3d | 419 | td->adin, td->adinlen)) |
aa048aef | 420 | || !TEST_int_eq(t.entropycnt, 1) |
35a34508 | 421 | || !TEST_int_eq(drbg->reseed_gen_counter, reseed_counter_tmp + 1) |
75e2c877 | 422 | || !uninstantiate(drbg)) |
12fb8c3d RS |
423 | goto err; |
424 | ||
425 | /* | |
426 | * Explicit reseed tests | |
427 | */ | |
428 | ||
429 | /* Test explicit reseed with too large additional input */ | |
ee774d5d | 430 | if (!instantiate(drbg, td, &t) |
eb238134 | 431 | || RAND_DRBG_reseed(drbg, td->adin, drbg->max_adinlen + 1, 0) > 0) |
12fb8c3d RS |
432 | goto err; |
433 | ||
434 | /* Test explicit reseed with entropy source failure */ | |
aa048aef | 435 | t.entropylen = 0; |
eb238134 | 436 | if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen, 0), 0) |
75e2c877 | 437 | || !uninstantiate(drbg)) |
12fb8c3d RS |
438 | goto err; |
439 | ||
440 | /* Test explicit reseed with too much entropy */ | |
ee774d5d | 441 | if (!instantiate(drbg, td, &t)) |
12fb8c3d | 442 | goto err; |
aa048aef | 443 | t.entropylen = drbg->max_entropylen + 1; |
eb238134 | 444 | if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen, 0), 0) |
75e2c877 | 445 | || !uninstantiate(drbg)) |
12fb8c3d RS |
446 | goto err; |
447 | ||
448 | /* Test explicit reseed with too little entropy */ | |
ee774d5d | 449 | if (!instantiate(drbg, td, &t)) |
12fb8c3d | 450 | goto err; |
aa048aef | 451 | t.entropylen = drbg->min_entropylen - 1; |
eb238134 | 452 | if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen, 0), 0) |
75e2c877 | 453 | || !uninstantiate(drbg)) |
12fb8c3d RS |
454 | goto err; |
455 | ||
456 | /* Standard says we have to check uninstantiate really zeroes */ | |
8212d505 | 457 | if (!TEST_mem_eq(zero, sizeof(drbg->data), &drbg->data, sizeof(drbg->data))) |
12fb8c3d RS |
458 | goto err; |
459 | ||
460 | ret = 1; | |
461 | ||
462 | err: | |
75e2c877 RS |
463 | uninstantiate(drbg); |
464 | RAND_DRBG_free(drbg); | |
12fb8c3d RS |
465 | return ret; |
466 | } | |
467 | ||
468 | static int test_kats(int i) | |
469 | { | |
470 | DRBG_SELFTEST_DATA *td = &drbg_test[i]; | |
471 | int rv = 0; | |
472 | ||
473 | if (!single_kat(td)) | |
474 | goto err; | |
475 | rv = 1; | |
476 | ||
477 | err: | |
478 | return rv; | |
479 | } | |
480 | ||
481 | static int test_error_checks(int i) | |
482 | { | |
483 | DRBG_SELFTEST_DATA *td = &drbg_test[i]; | |
484 | int rv = 0; | |
485 | ||
486 | if (error_check(td)) | |
487 | goto err; | |
488 | rv = 1; | |
489 | ||
490 | err: | |
491 | return rv; | |
492 | } | |
493 | ||
a93ba405 DMSP |
494 | /* |
495 | * Hook context data, attached as EXDATA to the RAND_DRBG | |
496 | */ | |
497 | typedef struct hook_ctx_st { | |
498 | RAND_DRBG *drbg; | |
499 | /* | |
500 | * Currently, all DRBGs use the same get_entropy() callback. | |
501 | * The tests however, don't assume this and store | |
502 | * the original callback for every DRBG separately. | |
503 | */ | |
504 | RAND_DRBG_get_entropy_fn get_entropy; | |
505 | /* forces a failure of the get_entropy() call if nonzero */ | |
506 | int fail; | |
507 | /* counts successful reseeds */ | |
508 | int reseed_count; | |
509 | } HOOK_CTX; | |
510 | ||
511 | static HOOK_CTX master_ctx, public_ctx, private_ctx; | |
512 | ||
513 | static HOOK_CTX *get_hook_ctx(RAND_DRBG *drbg) | |
514 | { | |
515 | return (HOOK_CTX *)RAND_DRBG_get_ex_data(drbg, app_data_index); | |
516 | } | |
517 | ||
518 | /* Intercepts and counts calls to the get_entropy() callback */ | |
519 | static size_t get_entropy_hook(RAND_DRBG *drbg, unsigned char **pout, | |
eb238134 KR |
520 | int entropy, size_t min_len, size_t max_len, |
521 | int prediction_resistance) | |
a93ba405 DMSP |
522 | { |
523 | size_t ret; | |
524 | HOOK_CTX *ctx = get_hook_ctx(drbg); | |
525 | ||
526 | if (ctx->fail != 0) | |
527 | return 0; | |
528 | ||
eb238134 KR |
529 | ret = ctx->get_entropy(drbg, pout, entropy, min_len, max_len, |
530 | prediction_resistance); | |
a93ba405 DMSP |
531 | |
532 | if (ret != 0) | |
533 | ctx->reseed_count++; | |
534 | return ret; | |
535 | } | |
536 | ||
537 | /* Installs a hook for the get_entropy() callback of the given drbg */ | |
538 | static void hook_drbg(RAND_DRBG *drbg, HOOK_CTX *ctx) | |
539 | { | |
540 | memset(ctx, 0, sizeof(*ctx)); | |
541 | ctx->drbg = drbg; | |
542 | ctx->get_entropy = drbg->get_entropy; | |
543 | drbg->get_entropy = get_entropy_hook; | |
544 | RAND_DRBG_set_ex_data(drbg, app_data_index, ctx); | |
545 | } | |
546 | ||
547 | /* Installs the hook for the get_entropy() callback of the given drbg */ | |
548 | static void unhook_drbg(RAND_DRBG *drbg) | |
549 | { | |
550 | HOOK_CTX *ctx = get_hook_ctx(drbg); | |
551 | ||
552 | drbg->get_entropy = ctx->get_entropy; | |
553 | CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DRBG, drbg, &drbg->ex_data); | |
554 | } | |
75e2c877 | 555 | |
a93ba405 DMSP |
556 | /* Resets the given hook context */ |
557 | static void reset_hook_ctx(HOOK_CTX *ctx) | |
75e2c877 | 558 | { |
a93ba405 DMSP |
559 | ctx->fail = 0; |
560 | ctx->reseed_count = 0; | |
561 | } | |
562 | ||
563 | /* Resets all drbg hook contexts */ | |
3cb7c5cf | 564 | static void reset_drbg_hook_ctx(void) |
a93ba405 DMSP |
565 | { |
566 | reset_hook_ctx(&master_ctx); | |
567 | reset_hook_ctx(&public_ctx); | |
568 | reset_hook_ctx(&private_ctx); | |
569 | } | |
570 | ||
571 | /* | |
572 | * Generates random output using RAND_bytes() and RAND_priv_bytes() | |
573 | * and checks whether the three shared DRBGs were reseeded as | |
574 | * expected. | |
575 | * | |
576 | * |expect_success|: expected outcome (as reported by RAND_status()) | |
577 | * |master|, |public|, |private|: pointers to the three shared DRBGs | |
578 | * |expect_xxx_reseed| = | |
579 | * 1: it is expected that the specified DRBG is reseeded | |
580 | * 0: it is expected that the specified DRBG is not reseeded | |
581 | * -1: don't check whether the specified DRBG was reseeded or not | |
7b7fdf8a BE |
582 | * |reseed_time|: if nonzero, used instead of time(NULL) to set the |
583 | * |before_reseed| time. | |
a93ba405 DMSP |
584 | */ |
585 | static int test_drbg_reseed(int expect_success, | |
586 | RAND_DRBG *master, | |
587 | RAND_DRBG *public, | |
588 | RAND_DRBG *private, | |
589 | int expect_master_reseed, | |
590 | int expect_public_reseed, | |
7b7fdf8a BE |
591 | int expect_private_reseed, |
592 | time_t reseed_time | |
a93ba405 DMSP |
593 | ) |
594 | { | |
595 | unsigned char buf[32]; | |
08a65d96 | 596 | time_t before_reseed, after_reseed; |
a93ba405 DMSP |
597 | int expected_state = (expect_success ? DRBG_READY : DRBG_ERROR); |
598 | ||
599 | /* | |
600 | * step 1: check preconditions | |
601 | */ | |
602 | ||
603 | /* Test whether seed propagation is enabled */ | |
35a34508 DMSP |
604 | if (!TEST_int_ne(master->reseed_prop_counter, 0) |
605 | || !TEST_int_ne(public->reseed_prop_counter, 0) | |
606 | || !TEST_int_ne(private->reseed_prop_counter, 0)) | |
a93ba405 DMSP |
607 | return 0; |
608 | ||
609 | /* Check whether the master DRBG's reseed counter is the largest one */ | |
35a34508 DMSP |
610 | if (!TEST_int_le(public->reseed_prop_counter, master->reseed_prop_counter) |
611 | || !TEST_int_le(private->reseed_prop_counter, master->reseed_prop_counter)) | |
a93ba405 DMSP |
612 | return 0; |
613 | ||
614 | /* | |
615 | * step 2: generate random output | |
616 | */ | |
617 | ||
7b7fdf8a BE |
618 | if (reseed_time == 0) |
619 | reseed_time = time(NULL); | |
620 | ||
a93ba405 | 621 | /* Generate random output from the public and private DRBG */ |
7b7fdf8a | 622 | before_reseed = expect_master_reseed == 1 ? reseed_time : 0; |
a93ba405 DMSP |
623 | if (!TEST_int_eq(RAND_bytes(buf, sizeof(buf)), expect_success) |
624 | || !TEST_int_eq(RAND_priv_bytes(buf, sizeof(buf)), expect_success)) | |
625 | return 0; | |
08a65d96 | 626 | after_reseed = time(NULL); |
a93ba405 DMSP |
627 | |
628 | ||
629 | /* | |
630 | * step 3: check postconditions | |
631 | */ | |
75e2c877 | 632 | |
a93ba405 DMSP |
633 | /* Test whether reseeding succeeded as expected */ |
634 | if (!TEST_int_eq(master->state, expected_state) | |
635 | || !TEST_int_eq(public->state, expected_state) | |
636 | || !TEST_int_eq(private->state, expected_state)) | |
75e2c877 | 637 | return 0; |
a93ba405 DMSP |
638 | |
639 | if (expect_master_reseed >= 0) { | |
640 | /* Test whether master DRBG was reseeded as expected */ | |
641 | if (!TEST_int_eq(master_ctx.reseed_count, expect_master_reseed)) | |
642 | return 0; | |
643 | } | |
644 | ||
645 | if (expect_public_reseed >= 0) { | |
646 | /* Test whether public DRBG was reseeded as expected */ | |
647 | if (!TEST_int_eq(public_ctx.reseed_count, expect_public_reseed)) | |
648 | return 0; | |
649 | } | |
650 | ||
651 | if (expect_private_reseed >= 0) { | |
652 | /* Test whether public DRBG was reseeded as expected */ | |
653 | if (!TEST_int_eq(private_ctx.reseed_count, expect_private_reseed)) | |
654 | return 0; | |
655 | } | |
656 | ||
657 | if (expect_success == 1) { | |
658 | /* Test whether all three reseed counters are synchronized */ | |
35a34508 DMSP |
659 | if (!TEST_int_eq(public->reseed_prop_counter, master->reseed_prop_counter) |
660 | || !TEST_int_eq(private->reseed_prop_counter, master->reseed_prop_counter)) | |
a93ba405 | 661 | return 0; |
08a65d96 DMSP |
662 | |
663 | /* Test whether reseed time of master DRBG is set correctly */ | |
664 | if (!TEST_time_t_le(before_reseed, master->reseed_time) | |
665 | || !TEST_time_t_le(master->reseed_time, after_reseed)) | |
666 | return 0; | |
667 | ||
668 | /* Test whether reseed times of child DRBGs are synchronized with master */ | |
669 | if (!TEST_time_t_ge(public->reseed_time, master->reseed_time) | |
670 | || !TEST_time_t_ge(private->reseed_time, master->reseed_time)) | |
671 | return 0; | |
a93ba405 DMSP |
672 | } else { |
673 | ERR_clear_error(); | |
674 | } | |
675 | ||
75e2c877 RS |
676 | return 1; |
677 | } | |
678 | ||
1b0fe00e DMSP |
679 | |
680 | #if defined(OPENSSL_SYS_UNIX) | |
681 | /* | |
682 | * Test whether master, public and private DRBG are reseeded after | |
683 | * forking the process. | |
684 | */ | |
685 | static int test_drbg_reseed_after_fork(RAND_DRBG *master, | |
686 | RAND_DRBG *public, | |
687 | RAND_DRBG *private) | |
688 | { | |
689 | pid_t pid; | |
690 | int status=0; | |
691 | ||
692 | pid = fork(); | |
693 | if (!TEST_int_ge(pid, 0)) | |
694 | return 0; | |
695 | ||
696 | if (pid > 0) { | |
697 | /* I'm the parent; wait for the child and check its exit code */ | |
698 | return TEST_int_eq(waitpid(pid, &status, 0), pid) && TEST_int_eq(status, 0); | |
699 | } | |
700 | ||
701 | /* I'm the child; check whether all three DRBGs reseed. */ | |
702 | if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1, 0))) | |
703 | status = 1; | |
704 | ||
705 | /* Remove hooks */ | |
706 | unhook_drbg(master); | |
707 | unhook_drbg(public); | |
708 | unhook_drbg(private); | |
709 | exit(status); | |
710 | } | |
711 | #endif | |
712 | ||
a93ba405 DMSP |
713 | /* |
714 | * Test whether the default rand_method (RAND_OpenSSL()) is | |
715 | * setup correctly, in particular whether reseeding works | |
716 | * as designed. | |
717 | */ | |
d597a9a8 | 718 | static int test_rand_drbg_reseed(void) |
a93ba405 DMSP |
719 | { |
720 | RAND_DRBG *master, *public, *private; | |
721 | unsigned char rand_add_buf[256]; | |
722 | int rv=0; | |
7b7fdf8a | 723 | time_t before_reseed; |
a93ba405 DMSP |
724 | |
725 | /* Check whether RAND_OpenSSL() is the default method */ | |
726 | if (!TEST_ptr_eq(RAND_get_rand_method(), RAND_OpenSSL())) | |
727 | return 0; | |
728 | ||
729 | /* All three DRBGs should be non-null */ | |
730 | if (!TEST_ptr(master = RAND_DRBG_get0_master()) | |
731 | || !TEST_ptr(public = RAND_DRBG_get0_public()) | |
732 | || !TEST_ptr(private = RAND_DRBG_get0_private())) | |
733 | return 0; | |
734 | ||
735 | /* There should be three distinct DRBGs, two of them chained to master */ | |
736 | if (!TEST_ptr_ne(public, private) | |
737 | || !TEST_ptr_ne(public, master) | |
738 | || !TEST_ptr_ne(private, master) | |
739 | || !TEST_ptr_eq(public->parent, master) | |
740 | || !TEST_ptr_eq(private->parent, master)) | |
741 | return 0; | |
742 | ||
59f124f9 DMSP |
743 | /* uninstantiate the three global DRBGs */ |
744 | RAND_DRBG_uninstantiate(private); | |
745 | RAND_DRBG_uninstantiate(public); | |
746 | RAND_DRBG_uninstantiate(master); | |
747 | ||
748 | ||
a93ba405 DMSP |
749 | /* Install hooks for the following tests */ |
750 | hook_drbg(master, &master_ctx); | |
751 | hook_drbg(public, &public_ctx); | |
752 | hook_drbg(private, &private_ctx); | |
753 | ||
59f124f9 DMSP |
754 | |
755 | /* | |
756 | * Test initial seeding of shared DRBGs | |
757 | */ | |
7b7fdf8a | 758 | if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1, 0))) |
59f124f9 DMSP |
759 | goto error; |
760 | reset_drbg_hook_ctx(); | |
761 | ||
762 | ||
a93ba405 | 763 | /* |
59f124f9 | 764 | * Test initial state of shared DRBGs |
a93ba405 | 765 | */ |
7b7fdf8a | 766 | if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 0, 0, 0))) |
a93ba405 DMSP |
767 | goto error; |
768 | reset_drbg_hook_ctx(); | |
769 | ||
770 | /* | |
771 | * Test whether the public and private DRBG are both reseeded when their | |
772 | * reseed counters differ from the master's reseed counter. | |
773 | */ | |
35a34508 | 774 | master->reseed_prop_counter++; |
7b7fdf8a | 775 | if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 1, 1, 0))) |
a93ba405 DMSP |
776 | goto error; |
777 | reset_drbg_hook_ctx(); | |
778 | ||
779 | /* | |
780 | * Test whether the public DRBG is reseeded when its reseed counter differs | |
781 | * from the master's reseed counter. | |
782 | */ | |
35a34508 DMSP |
783 | master->reseed_prop_counter++; |
784 | private->reseed_prop_counter++; | |
7b7fdf8a | 785 | if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 1, 0, 0))) |
a93ba405 DMSP |
786 | goto error; |
787 | reset_drbg_hook_ctx(); | |
788 | ||
789 | /* | |
790 | * Test whether the private DRBG is reseeded when its reseed counter differs | |
791 | * from the master's reseed counter. | |
792 | */ | |
35a34508 DMSP |
793 | master->reseed_prop_counter++; |
794 | public->reseed_prop_counter++; | |
7b7fdf8a | 795 | if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 0, 1, 0))) |
a93ba405 DMSP |
796 | goto error; |
797 | reset_drbg_hook_ctx(); | |
798 | ||
1b0fe00e DMSP |
799 | #if defined(OPENSSL_SYS_UNIX) |
800 | if (!TEST_true(test_drbg_reseed_after_fork(master, public, private))) | |
801 | goto error; | |
802 | #endif | |
a93ba405 DMSP |
803 | |
804 | /* fill 'randomness' buffer with some arbitrary data */ | |
805 | memset(rand_add_buf, 'r', sizeof(rand_add_buf)); | |
806 | ||
807 | /* | |
7b7fdf8a BE |
808 | * Test whether all three DRBGs are reseeded by RAND_add(). |
809 | * The before_reseed time has to be measured here and passed into the | |
810 | * test_drbg_reseed() test, because the master DRBG gets already reseeded | |
811 | * in RAND_add(), whence the check for the condition | |
812 | * before_reseed <= master->reseed_time will fail if the time value happens | |
813 | * to increase between the RAND_add() and the test_drbg_reseed() call. | |
a93ba405 | 814 | */ |
7b7fdf8a | 815 | before_reseed = time(NULL); |
a93ba405 | 816 | RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf)); |
7b7fdf8a BE |
817 | if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1, |
818 | before_reseed))) | |
a93ba405 DMSP |
819 | goto error; |
820 | reset_drbg_hook_ctx(); | |
821 | ||
822 | ||
823 | /* | |
824 | * Test whether none of the DRBGs is reseed if the master fails to reseed | |
825 | */ | |
826 | master_ctx.fail = 1; | |
35a34508 | 827 | master->reseed_prop_counter++; |
a93ba405 | 828 | RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf)); |
7b7fdf8a | 829 | if (!TEST_true(test_drbg_reseed(0, master, public, private, 0, 0, 0, 0))) |
a93ba405 DMSP |
830 | goto error; |
831 | reset_drbg_hook_ctx(); | |
832 | ||
833 | rv = 1; | |
834 | ||
835 | error: | |
836 | /* Remove hooks */ | |
837 | unhook_drbg(master); | |
838 | unhook_drbg(public); | |
839 | unhook_drbg(private); | |
840 | ||
841 | return rv; | |
842 | } | |
843 | ||
440bce8f | 844 | #if defined(OPENSSL_THREADS) |
43687d68 DMSP |
845 | static int multi_thread_rand_bytes_succeeded = 1; |
846 | static int multi_thread_rand_priv_bytes_succeeded = 1; | |
440bce8f KR |
847 | |
848 | static void run_multi_thread_test(void) | |
849 | { | |
850 | unsigned char buf[256]; | |
851 | time_t start = time(NULL); | |
fd59e425 | 852 | RAND_DRBG *public = NULL, *private = NULL; |
440bce8f | 853 | |
fd59e425 BE |
854 | if (!TEST_ptr(public = RAND_DRBG_get0_public()) |
855 | || !TEST_ptr(private = RAND_DRBG_get0_private())) { | |
856 | multi_thread_rand_bytes_succeeded = 0; | |
857 | return; | |
858 | } | |
440bce8f | 859 | RAND_DRBG_set_reseed_time_interval(private, 1); |
fd59e425 | 860 | RAND_DRBG_set_reseed_time_interval(public, 1); |
440bce8f KR |
861 | |
862 | do { | |
43687d68 DMSP |
863 | if (RAND_bytes(buf, sizeof(buf)) <= 0) |
864 | multi_thread_rand_bytes_succeeded = 0; | |
865 | if (RAND_priv_bytes(buf, sizeof(buf)) <= 0) | |
866 | multi_thread_rand_priv_bytes_succeeded = 0; | |
440bce8f KR |
867 | } |
868 | while(time(NULL) - start < 5); | |
869 | } | |
870 | ||
871 | # if defined(OPENSSL_SYS_WINDOWS) | |
872 | ||
873 | typedef HANDLE thread_t; | |
874 | ||
875 | static DWORD WINAPI thread_run(LPVOID arg) | |
876 | { | |
877 | run_multi_thread_test(); | |
eaacc247 RL |
878 | /* |
879 | * Because we're linking with a static library, we must stop each | |
880 | * thread explicitly, or so says OPENSSL_thread_stop(3) | |
881 | */ | |
882 | OPENSSL_thread_stop(); | |
440bce8f KR |
883 | return 0; |
884 | } | |
885 | ||
886 | static int run_thread(thread_t *t) | |
887 | { | |
888 | *t = CreateThread(NULL, 0, thread_run, NULL, 0, NULL); | |
889 | return *t != NULL; | |
890 | } | |
891 | ||
892 | static int wait_for_thread(thread_t thread) | |
893 | { | |
894 | return WaitForSingleObject(thread, INFINITE) == 0; | |
895 | } | |
896 | ||
897 | # else | |
898 | ||
899 | typedef pthread_t thread_t; | |
900 | ||
901 | static void *thread_run(void *arg) | |
902 | { | |
903 | run_multi_thread_test(); | |
eaacc247 RL |
904 | /* |
905 | * Because we're linking with a static library, we must stop each | |
906 | * thread explicitly, or so says OPENSSL_thread_stop(3) | |
907 | */ | |
908 | OPENSSL_thread_stop(); | |
440bce8f KR |
909 | return NULL; |
910 | } | |
911 | ||
912 | static int run_thread(thread_t *t) | |
913 | { | |
914 | return pthread_create(t, NULL, thread_run, NULL) == 0; | |
915 | } | |
916 | ||
917 | static int wait_for_thread(thread_t thread) | |
918 | { | |
919 | return pthread_join(thread, NULL) == 0; | |
920 | } | |
921 | ||
922 | # endif | |
923 | ||
924 | /* | |
925 | * The main thread will also run the test, so we'll have THREADS+1 parallel | |
926 | * tests running | |
927 | */ | |
43687d68 | 928 | # define THREADS 3 |
440bce8f KR |
929 | |
930 | static int test_multi_thread(void) | |
931 | { | |
932 | thread_t t[THREADS]; | |
933 | int i; | |
934 | ||
935 | for (i = 0; i < THREADS; i++) | |
936 | run_thread(&t[i]); | |
937 | run_multi_thread_test(); | |
938 | for (i = 0; i < THREADS; i++) | |
939 | wait_for_thread(t[i]); | |
43687d68 DMSP |
940 | |
941 | if (!TEST_true(multi_thread_rand_bytes_succeeded)) | |
942 | return 0; | |
943 | if (!TEST_true(multi_thread_rand_priv_bytes_succeeded)) | |
944 | return 0; | |
945 | ||
440bce8f KR |
946 | return 1; |
947 | } | |
948 | #endif | |
12fb8c3d | 949 | |
2a70d65b | 950 | /* |
d597a9a8 DMSP |
951 | * Test that instantiation with RAND_seed() works as expected |
952 | * | |
953 | * If no os entropy source is available then RAND_seed(buffer, bufsize) | |
954 | * is expected to succeed if and only if the buffer length is at least | |
955 | * rand_drbg_seedlen(master) bytes. | |
956 | * | |
957 | * If an os entropy source is available then RAND_seed(buffer, bufsize) | |
958 | * is expected to succeed always. | |
2a70d65b | 959 | */ |
d597a9a8 | 960 | static int test_rand_seed(void) |
2a70d65b | 961 | { |
fd59e425 | 962 | RAND_DRBG *master = NULL; |
d597a9a8 DMSP |
963 | unsigned char rand_buf[256]; |
964 | size_t rand_buflen; | |
d597a9a8 | 965 | size_t required_seed_buflen = 0; |
fd59e425 BE |
966 | |
967 | if (!TEST_ptr(master = RAND_DRBG_get0_master())) | |
968 | return 0; | |
969 | ||
970 | #ifdef OPENSSL_RAND_SEED_NONE | |
971 | required_seed_buflen = rand_drbg_seedlen(master); | |
d597a9a8 DMSP |
972 | #endif |
973 | ||
974 | memset(rand_buf, 0xCD, sizeof(rand_buf)); | |
975 | ||
976 | for ( rand_buflen = 256 ; rand_buflen > 0 ; --rand_buflen ) { | |
977 | RAND_DRBG_uninstantiate(master); | |
978 | RAND_seed(rand_buf, rand_buflen); | |
979 | ||
980 | if (!TEST_int_eq(RAND_status(), | |
981 | (rand_buflen >= required_seed_buflen))) | |
982 | return 0; | |
983 | } | |
984 | ||
985 | return 1; | |
2a70d65b KR |
986 | } |
987 | ||
988 | /* | |
d597a9a8 DMSP |
989 | * Test that adding additional data with RAND_add() works as expected |
990 | * when the master DRBG is instantiated (and below its reseed limit). | |
991 | * | |
992 | * This should succeed regardless of whether an os entropy source is | |
993 | * available or not. | |
2a70d65b KR |
994 | */ |
995 | static int test_rand_add(void) | |
996 | { | |
d597a9a8 DMSP |
997 | unsigned char rand_buf[256]; |
998 | size_t rand_buflen; | |
2a70d65b | 999 | |
d597a9a8 | 1000 | memset(rand_buf, 0xCD, sizeof(rand_buf)); |
2a70d65b | 1001 | |
d597a9a8 DMSP |
1002 | /* make sure it's instantiated */ |
1003 | RAND_seed(rand_buf, sizeof(rand_buf)); | |
1004 | if (!TEST_true(RAND_status())) | |
1005 | return 0; | |
2a70d65b | 1006 | |
d597a9a8 DMSP |
1007 | for ( rand_buflen = 256 ; rand_buflen > 0 ; --rand_buflen ) { |
1008 | RAND_add(rand_buf, rand_buflen, 0.0); | |
1009 | if (!TEST_true(RAND_status())) | |
1010 | return 0; | |
1011 | } | |
1012 | ||
1013 | return 1; | |
2a70d65b KR |
1014 | } |
1015 | ||
ad887416 | 1016 | int setup_tests(void) |
12fb8c3d | 1017 | { |
12fb8c3d RS |
1018 | app_data_index = RAND_DRBG_get_ex_new_index(0L, NULL, NULL, NULL, NULL); |
1019 | ||
1020 | ADD_ALL_TESTS(test_kats, OSSL_NELEM(drbg_test)); | |
1021 | ADD_ALL_TESTS(test_error_checks, OSSL_NELEM(drbg_test)); | |
d597a9a8 DMSP |
1022 | ADD_TEST(test_rand_drbg_reseed); |
1023 | ADD_TEST(test_rand_seed); | |
2a70d65b | 1024 | ADD_TEST(test_rand_add); |
440bce8f KR |
1025 | #if defined(OPENSSL_THREADS) |
1026 | ADD_TEST(test_multi_thread); | |
1027 | #endif | |
ad887416 | 1028 | return 1; |
12fb8c3d | 1029 | } |