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