]> git.ipfire.org Git - thirdparty/openssl.git/blob - fips/rand/fips_drbg_selftest.c
Revise DRBG to split between internal and external flags.
[thirdparty/openssl.git] / fips / rand / fips_drbg_selftest.c
1 /* fips/rand/fips_drbg_selftest.c */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project.
4 */
5 /* ====================================================================
6 * Copyright (c) 2011 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 */
53
54 #define OPENSSL_FIPSAPI
55
56 #include <string.h>
57 #include <openssl/crypto.h>
58 #include <openssl/err.h>
59 #include <openssl/fips_rand.h>
60 #include "fips_rand_lcl.h"
61 #include "fips_locl.h"
62
63 #include "fips_drbg_selftest.h"
64
65 typedef struct {
66 int post;
67 int nid;
68 unsigned int flags;
69
70 /* KAT data for no PR */
71 const unsigned char *ent;
72 size_t entlen;
73 const unsigned char *nonce;
74 size_t noncelen;
75 const unsigned char *pers;
76 size_t perslen;
77 const unsigned char *adin;
78 size_t adinlen;
79 const unsigned char *entreseed;
80 size_t entreseedlen;
81 const unsigned char *adinreseed;
82 size_t adinreseedlen;
83 const unsigned char *adin2;
84 size_t adin2len;
85 const unsigned char *kat;
86 size_t katlen;
87 const unsigned char *kat2;
88 size_t kat2len;
89
90 /* KAT data for PR */
91 const unsigned char *ent_pr;
92 size_t entlen_pr;
93 const unsigned char *nonce_pr;
94 size_t noncelen_pr;
95 const unsigned char *pers_pr;
96 size_t perslen_pr;
97 const unsigned char *adin_pr;
98 size_t adinlen_pr;
99 const unsigned char *entpr_pr;
100 size_t entprlen_pr;
101 const unsigned char *ading_pr;
102 size_t adinglen_pr;
103 const unsigned char *entg_pr;
104 size_t entglen_pr;
105 const unsigned char *kat_pr;
106 size_t katlen_pr;
107 const unsigned char *kat2_pr;
108 size_t kat2len_pr;
109
110 } DRBG_SELFTEST_DATA;
111
112 #define make_drbg_test_data(nid, flag, pr, p) {p, nid, flag | DRBG_FLAG_TEST, \
113 pr##_entropyinput, sizeof(pr##_entropyinput), \
114 pr##_nonce, sizeof(pr##_nonce), \
115 pr##_personalizationstring, sizeof(pr##_personalizationstring), \
116 pr##_additionalinput, sizeof(pr##_additionalinput), \
117 pr##_entropyinputreseed, sizeof(pr##_entropyinputreseed), \
118 pr##_additionalinputreseed, sizeof(pr##_additionalinputreseed), \
119 pr##_additionalinput2, sizeof(pr##_additionalinput2), \
120 pr##_int_returnedbits, sizeof(pr##_int_returnedbits), \
121 pr##_returnedbits, sizeof(pr##_returnedbits), \
122 pr##_pr_entropyinput, sizeof(pr##_pr_entropyinput), \
123 pr##_pr_nonce, sizeof(pr##_pr_nonce), \
124 pr##_pr_personalizationstring, sizeof(pr##_pr_personalizationstring), \
125 pr##_pr_additionalinput, sizeof(pr##_pr_additionalinput), \
126 pr##_pr_entropyinputpr, sizeof(pr##_pr_entropyinputpr), \
127 pr##_pr_additionalinput2, sizeof(pr##_pr_additionalinput2), \
128 pr##_pr_entropyinputpr2, sizeof(pr##_pr_entropyinputpr2), \
129 pr##_pr_int_returnedbits, sizeof(pr##_pr_int_returnedbits), \
130 pr##_pr_returnedbits, sizeof(pr##_pr_returnedbits), \
131 }
132
133 #define make_drbg_test_data_df(nid, pr, p) \
134 make_drbg_test_data(nid, DRBG_FLAG_CTR_USE_DF, pr, p)
135
136 #define make_drbg_test_data_ec(curve, md, pr, p) \
137 make_drbg_test_data((curve << 16) | md , 0, pr, p)
138
139 static DRBG_SELFTEST_DATA drbg_test[] = {
140 make_drbg_test_data_df(NID_aes_128_ctr, aes_128_use_df, 0),
141 make_drbg_test_data_df(NID_aes_192_ctr, aes_192_use_df, 0),
142 make_drbg_test_data_df(NID_aes_256_ctr, aes_256_use_df, 1),
143 make_drbg_test_data(NID_aes_128_ctr, 0, aes_128_no_df, 0),
144 make_drbg_test_data(NID_aes_192_ctr, 0, aes_192_no_df, 0),
145 make_drbg_test_data(NID_aes_256_ctr, 0, aes_256_no_df, 1),
146 make_drbg_test_data(NID_sha1, 0, sha1, 0),
147 make_drbg_test_data(NID_sha224, 0, sha224, 0),
148 make_drbg_test_data(NID_sha256, 0, sha256, 1),
149 make_drbg_test_data(NID_sha384, 0, sha384, 0),
150 make_drbg_test_data(NID_sha512, 0, sha512, 0),
151 make_drbg_test_data(NID_hmacWithSHA1, 0, hmac_sha1, 0),
152 make_drbg_test_data(NID_hmacWithSHA224, 0, hmac_sha224, 0),
153 make_drbg_test_data(NID_hmacWithSHA256, 0, hmac_sha256, 1),
154 make_drbg_test_data(NID_hmacWithSHA384, 0, hmac_sha384, 0),
155 make_drbg_test_data(NID_hmacWithSHA512, 0, hmac_sha512, 0),
156 make_drbg_test_data_ec(NID_X9_62_prime256v1, NID_sha1, p_256_sha1, 0),
157 make_drbg_test_data_ec(NID_X9_62_prime256v1, NID_sha224, p_256_sha224, 0),
158 make_drbg_test_data_ec(NID_X9_62_prime256v1, NID_sha256, p_256_sha256, 1),
159 make_drbg_test_data_ec(NID_X9_62_prime256v1, NID_sha384, p_256_sha384, 0),
160 make_drbg_test_data_ec(NID_X9_62_prime256v1, NID_sha512, p_256_sha512, 0),
161 make_drbg_test_data_ec(NID_secp384r1, NID_sha224, p_384_sha224, 0),
162 make_drbg_test_data_ec(NID_secp384r1, NID_sha256, p_384_sha256, 0),
163 make_drbg_test_data_ec(NID_secp384r1, NID_sha384, p_384_sha384, 0),
164 make_drbg_test_data_ec(NID_secp384r1, NID_sha512, p_384_sha512, 0),
165 make_drbg_test_data_ec(NID_secp521r1, NID_sha256, p_521_sha256, 0),
166 make_drbg_test_data_ec(NID_secp521r1, NID_sha384, p_521_sha384, 0),
167 make_drbg_test_data_ec(NID_secp521r1, NID_sha512, p_521_sha512, 0),
168 {0,0,0}
169 };
170
171 typedef struct
172 {
173 const unsigned char *ent;
174 size_t entlen;
175 int entcnt;
176 const unsigned char *nonce;
177 size_t noncelen;
178 int noncecnt;
179 } TEST_ENT;
180
181 static size_t test_entropy(DRBG_CTX *dctx, unsigned char **pout,
182 int entropy, size_t min_len, size_t max_len)
183 {
184 TEST_ENT *t = FIPS_drbg_get_app_data(dctx);
185 *pout = (unsigned char *)t->ent;
186 t->entcnt++;
187 return t->entlen;
188 }
189
190 static size_t test_nonce(DRBG_CTX *dctx, unsigned char **pout,
191 int entropy, size_t min_len, size_t max_len)
192 {
193 TEST_ENT *t = FIPS_drbg_get_app_data(dctx);
194 *pout = (unsigned char *)t->nonce;
195 t->noncecnt++;
196 return t->noncelen;
197 }
198
199 static int fips_drbg_single_kat(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td,
200 int quick)
201 {
202 TEST_ENT t;
203 int rv = 0;
204 size_t adinlen;
205 unsigned char randout[1024];
206
207 /* Initial test without PR */
208
209 if (!FIPS_drbg_init(dctx, td->nid, td->flags))
210 return 0;
211 if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0))
212 return 0;
213
214 FIPS_drbg_set_app_data(dctx, &t);
215
216 t.ent = td->ent;
217 t.entlen = td->entlen;
218 t.nonce = td->nonce;
219 t.noncelen = td->noncelen;
220 t.entcnt = 0;
221 t.noncecnt = 0;
222
223 if (!FIPS_drbg_instantiate(dctx, td->pers, td->perslen))
224 goto err;
225
226 /* Note for CTR without DF some additional input values
227 * ignore bytes after the keylength: so reduce adinlen
228 * to half to ensure invalid data is fed in.
229 */
230 if (!fips_post_corrupt(FIPS_TEST_DRBG, dctx->type, &dctx->iflags))
231 adinlen = td->adinlen / 2;
232 else
233 adinlen = td->adinlen;
234 if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0,
235 td->adin, adinlen))
236 goto err;
237
238 if (memcmp(randout, td->kat, td->katlen))
239 {
240 FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_NOPR_TEST1_FAILURE);
241 goto err2;
242 }
243
244 if (quick)
245 {
246 rv = 1;
247 goto err;
248 }
249
250 t.ent = td->entreseed;
251 t.entlen = td->entreseedlen;
252
253 if (!FIPS_drbg_reseed(dctx, td->adinreseed, td->adinreseedlen))
254 goto err;
255
256 if (!FIPS_drbg_generate(dctx, randout, td->kat2len, 0,
257 td->adin2, td->adin2len))
258 goto err;
259
260 if (memcmp(randout, td->kat2, td->kat2len))
261 {
262 FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_NOPR_TEST2_FAILURE);
263 goto err2;
264 }
265
266 FIPS_drbg_uninstantiate(dctx);
267
268 /* Now test with PR */
269 if (!FIPS_drbg_init(dctx, td->nid, td->flags))
270 return 0;
271 if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0))
272 return 0;
273
274 FIPS_drbg_set_app_data(dctx, &t);
275
276 t.ent = td->ent_pr;
277 t.entlen = td->entlen_pr;
278 t.nonce = td->nonce_pr;
279 t.noncelen = td->noncelen_pr;
280 t.entcnt = 0;
281 t.noncecnt = 0;
282
283 if (!FIPS_drbg_instantiate(dctx, td->pers_pr, td->perslen_pr))
284 goto err;
285
286 t.ent = td->entpr_pr;
287 t.entlen = td->entprlen_pr;
288
289 /* Note for CTR without DF some additional input values
290 * ignore bytes after the keylength: so reduce adinlen
291 * to half to ensure invalid data is fed in.
292 */
293 if (!fips_post_corrupt(FIPS_TEST_DRBG, dctx->type, &dctx->iflags))
294 adinlen = td->adinlen_pr / 2;
295 else
296 adinlen = td->adinlen_pr;
297 if (!FIPS_drbg_generate(dctx, randout, td->katlen_pr, 1,
298 td->adin_pr, adinlen))
299 goto err;
300
301 if (memcmp(randout, td->kat_pr, td->katlen_pr))
302 {
303 FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_PR_TEST1_FAILURE);
304 goto err2;
305 }
306
307 t.ent = td->entg_pr;
308 t.entlen = td->entglen_pr;
309
310 if (!FIPS_drbg_generate(dctx, randout, td->kat2len_pr, 1,
311 td->ading_pr, td->adinglen_pr))
312 goto err;
313
314 if (memcmp(randout, td->kat2_pr, td->kat2len_pr))
315 {
316 FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_PR_TEST2_FAILURE);
317 goto err2;
318 }
319
320 rv = 1;
321
322 err:
323 if (rv == 0)
324 FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_SELFTEST_FAILED);
325 err2:
326 FIPS_drbg_uninstantiate(dctx);
327
328 return rv;
329
330 }
331
332 /* Initialise a DRBG based on selftest data */
333
334 static int do_drbg_init(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td, TEST_ENT *t)
335 {
336
337 if (!FIPS_drbg_init(dctx, td->nid, td->flags))
338 return 0;
339
340 if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0))
341 return 0;
342
343 FIPS_drbg_set_app_data(dctx, t);
344
345 t->ent = td->ent;
346 t->entlen = td->entlen;
347 t->nonce = td->nonce;
348 t->noncelen = td->noncelen;
349 t->entcnt = 0;
350 t->noncecnt = 0;
351 return 1;
352 }
353
354 /* Initialise and instantiate DRBG based on selftest data */
355 static int do_drbg_instantiate(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td,
356 TEST_ENT *t)
357 {
358 if (!do_drbg_init(dctx, td, t))
359 return 0;
360 if (!FIPS_drbg_instantiate(dctx, td->pers, td->perslen))
361 return 0;
362
363 return 1;
364 }
365
366 /* This is the "health check" function required by SP800-90. Induce several
367 * failure modes and check an error condition is set.
368 */
369
370 static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td)
371 {
372 unsigned char randout[1024];
373 TEST_ENT t;
374 size_t i;
375 unsigned int reseed_counter_tmp;
376 unsigned char *p = (unsigned char *)dctx;
377
378 /* Initialise DRBG */
379
380 if (!do_drbg_init(dctx, td, &t))
381 goto err;
382
383 /* Don't report induced errors */
384 dctx->iflags |= DRBG_FLAG_NOERR;
385
386 /* Personalisation string tests */
387
388 /* Test detection of too large personlisation string */
389
390 if (FIPS_drbg_instantiate(dctx, td->pers, dctx->max_pers + 1) > 0)
391 {
392 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_PERSONALISATION_ERROR_UNDETECTED);
393 goto err;
394 }
395
396 /* Entropy source tests */
397
398 /* Test entropy source failure detecion: i.e. returns no data */
399
400 t.entlen = 0;
401
402 if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0)
403 {
404 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
405 goto err;
406 }
407
408 /* Try to generate output from uninstantiated DRBG */
409 if (FIPS_drbg_generate(dctx, randout, td->katlen, 0,
410 td->adin, td->adinlen))
411 {
412 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_GENERATE_ERROR_UNDETECTED);
413 goto err;
414 }
415
416 dctx->iflags &= ~DRBG_FLAG_NOERR;
417 if (!FIPS_drbg_uninstantiate(dctx))
418 {
419 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
420 goto err;
421 }
422
423 if (!do_drbg_init(dctx, td, &t))
424 goto err;
425
426 dctx->iflags |= DRBG_FLAG_NOERR;
427
428 /* Test insufficient entropy */
429
430 t.entlen = dctx->min_entropy - 1;
431
432 if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0)
433 {
434 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
435 goto err;
436 }
437
438 dctx->iflags &= ~DRBG_FLAG_NOERR;
439 if (!FIPS_drbg_uninstantiate(dctx))
440 {
441 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
442 goto err;
443 }
444
445 /* Test too much entropy */
446
447 if (!do_drbg_init(dctx, td, &t))
448 goto err;
449
450 dctx->iflags |= DRBG_FLAG_NOERR;
451
452 t.entlen = dctx->max_entropy + 1;
453
454 if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0)
455 {
456 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
457 goto err;
458 }
459
460 dctx->iflags &= ~DRBG_FLAG_NOERR;
461 if (!FIPS_drbg_uninstantiate(dctx))
462 {
463 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
464 goto err;
465 }
466
467 /* Nonce tests */
468
469 /* Test too small nonce */
470
471 if (dctx->min_nonce)
472 {
473
474 if (!do_drbg_init(dctx, td, &t))
475 goto err;
476
477 dctx->iflags |= DRBG_FLAG_NOERR;
478
479 t.noncelen = dctx->min_nonce - 1;
480
481 if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0)
482 {
483 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_NONCE_ERROR_UNDETECTED);
484 goto err;
485 }
486
487 dctx->iflags &= ~DRBG_FLAG_NOERR;
488 if (!FIPS_drbg_uninstantiate(dctx))
489 {
490 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
491 goto err;
492 }
493
494 }
495
496 /* Test too large nonce */
497
498 if (dctx->max_nonce)
499 {
500
501 if (!do_drbg_init(dctx, td, &t))
502 goto err;
503
504 dctx->iflags |= DRBG_FLAG_NOERR;
505
506 t.noncelen = dctx->max_nonce + 1;
507
508 if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0)
509 {
510 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_NONCE_ERROR_UNDETECTED);
511 goto err;
512 }
513
514 dctx->iflags &= ~DRBG_FLAG_NOERR;
515 if (!FIPS_drbg_uninstantiate(dctx))
516 {
517 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
518 goto err;
519 }
520
521 }
522
523 /* Instantiate with valid data. */
524 if (!do_drbg_instantiate(dctx, td, &t))
525 goto err;
526
527 /* Check generation is now OK */
528 if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0,
529 td->adin, td->adinlen))
530 goto err;
531
532 dctx->iflags |= DRBG_FLAG_NOERR;
533
534 /* Request too much data for one request */
535 if (FIPS_drbg_generate(dctx, randout, dctx->max_request + 1, 0,
536 td->adin, td->adinlen))
537 {
538 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_REQUEST_LENGTH_ERROR_UNDETECTED);
539 goto err;
540 }
541
542 /* Try too large additional input */
543 if (FIPS_drbg_generate(dctx, randout, td->katlen, 0,
544 td->adin, dctx->max_adin + 1))
545 {
546 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ADDITIONAL_INPUT_ERROR_UNDETECTED);
547 goto err;
548 }
549
550 /* Check prediction resistance request fails if entropy source
551 * failure.
552 */
553
554 t.entlen = 0;
555
556 if (FIPS_drbg_generate(dctx, randout, td->katlen, 1,
557 td->adin, td->adinlen))
558 {
559 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
560 goto err;
561 }
562
563 dctx->iflags &= ~DRBG_FLAG_NOERR;
564
565 if (!FIPS_drbg_uninstantiate(dctx))
566 {
567 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
568 goto err;
569 }
570
571
572 /* Instantiate again with valid data */
573
574 if (!do_drbg_instantiate(dctx, td, &t))
575 goto err;
576 /* Test reseed counter works */
577 /* Save initial reseed counter */
578 reseed_counter_tmp = dctx->reseed_counter;
579 /* Set reseed counter to beyond interval */
580 dctx->reseed_counter = dctx->reseed_interval;
581
582 /* Generate output and check entropy has been requested for reseed */
583 t.entcnt = 0;
584 if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0,
585 td->adin, td->adinlen))
586 goto err;
587 if (t.entcnt != 1)
588 {
589 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED);
590 goto err;
591 }
592 /* Check reseed counter has been reset */
593 if (dctx->reseed_counter != reseed_counter_tmp + 1)
594 {
595 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_RESEED_COUNTER_ERROR);
596 goto err;
597 }
598
599 /* Explicit reseed tests */
600
601 /* Test explicit reseed with too large additional input */
602 if (!do_drbg_init(dctx, td, &t))
603 goto err;
604
605 dctx->iflags |= DRBG_FLAG_NOERR;
606
607 if (FIPS_drbg_reseed(dctx, td->adin, dctx->max_adin + 1) > 0)
608 {
609 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ADDITIONAL_INPUT_ERROR_UNDETECTED);
610 goto err;
611 }
612
613 /* Test explicit reseed with entropy source failure */
614
615 /* Check prediction resistance request fails if entropy source
616 * failure.
617 */
618
619 t.entlen = 0;
620
621 if (FIPS_drbg_generate(dctx, randout, td->katlen, 1,
622 td->adin, td->adinlen))
623 {
624 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
625 goto err;
626 }
627
628 dctx->iflags &= ~DRBG_FLAG_NOERR;
629
630 if (!FIPS_drbg_uninstantiate(dctx))
631 {
632 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
633 goto err;
634 }
635
636
637 if (!do_drbg_instantiate(dctx, td, &t))
638 goto err;
639 /* Test reseed counter works */
640 /* Save initial reseed counter */
641 reseed_counter_tmp = dctx->reseed_counter;
642 /* Set reseed counter to beyond interval */
643 dctx->reseed_counter = dctx->reseed_interval;
644
645 /* Generate output and check entropy has been requested for reseed */
646 t.entcnt = 0;
647 if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0,
648 td->adin, td->adinlen))
649 goto err;
650 if (t.entcnt != 1)
651 {
652 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED);
653 goto err;
654 }
655 /* Check reseed counter has been reset */
656 if (dctx->reseed_counter != reseed_counter_tmp + 1)
657 {
658 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_RESEED_COUNTER_ERROR);
659 goto err;
660 }
661
662 /* Explicit reseed tests */
663
664 /* Test explicit reseed with too large additional input */
665 if (!do_drbg_init(dctx, td, &t))
666 goto err;
667
668 dctx->iflags |= DRBG_FLAG_NOERR;
669
670 if (FIPS_drbg_reseed(dctx, td->adin, dctx->max_adin + 1) > 0)
671 {
672 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ADDITIONAL_INPUT_ERROR_UNDETECTED);
673 goto err;
674 }
675
676 /* Test explicit reseed with entropy source failure */
677
678 if (!do_drbg_init(dctx, td, &t))
679 goto err;
680
681 dctx->iflags |= DRBG_FLAG_NOERR;
682
683 t.entlen = 0;
684
685 if (FIPS_drbg_reseed(dctx, td->adin, td->adinlen) > 0)
686 {
687 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
688 goto err;
689 }
690
691 if (!FIPS_drbg_uninstantiate(dctx))
692 {
693 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
694 goto err;
695 }
696
697 /* Test explicit reseed with too much entropy */
698
699 if (!do_drbg_init(dctx, td, &t))
700 goto err;
701
702 dctx->iflags |= DRBG_FLAG_NOERR;
703
704 t.entlen = dctx->max_entropy + 1;
705
706 if (FIPS_drbg_reseed(dctx, td->adin, td->adinlen) > 0)
707 {
708 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
709 goto err;
710 }
711
712 if (!FIPS_drbg_uninstantiate(dctx))
713 {
714 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
715 goto err;
716 }
717
718 /* Test explicit reseed with too little entropy */
719
720 if (!do_drbg_init(dctx, td, &t))
721 goto err;
722
723 dctx->iflags |= DRBG_FLAG_NOERR;
724
725 t.entlen = dctx->min_entropy - 1;
726
727 if (FIPS_drbg_reseed(dctx, td->adin, td->adinlen) > 0)
728 {
729 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
730 goto err;
731 }
732
733 if (!FIPS_drbg_uninstantiate(dctx))
734 {
735 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
736 goto err;
737 }
738
739 p = (unsigned char *)&dctx->d;
740 /* Standard says we have to check uninstantiate really zeroes
741 * the data...
742 */
743 for (i = 0; i < sizeof(dctx->d); i++)
744 {
745 if (*p != 0)
746 {
747 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ZEROISE_ERROR);
748 goto err;
749 }
750 p++;
751 }
752
753 return 1;
754
755 err:
756 /* A real error as opposed to an induced one: underlying function will
757 * indicate the error.
758 */
759 if (!(dctx->iflags & DRBG_FLAG_NOERR))
760 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_FUNCTION_ERROR);
761 FIPS_drbg_uninstantiate(dctx);
762 return 0;
763
764 }
765
766 int fips_drbg_kat(DRBG_CTX *dctx, int nid, unsigned int flags)
767 {
768 int rv;
769 DRBG_SELFTEST_DATA *td;
770 flags |= DRBG_FLAG_TEST;
771 for (td = drbg_test; td->nid != 0; td++)
772 {
773 if (td->nid == nid && td->flags == flags)
774 {
775 rv = fips_drbg_single_kat(dctx, td, 0);
776 if (rv <= 0)
777 return rv;
778 return fips_drbg_health_check(dctx, td);
779 }
780 }
781 return 0;
782 }
783
784 int FIPS_drbg_test(DRBG_CTX *dctx)
785 {
786 int rv;
787 DRBG_CTX *tctx = NULL;
788 tctx = FIPS_drbg_new(0, 0);
789 fips_post_started(FIPS_TEST_DRBG, dctx->type, &dctx->xflags);
790 if (!tctx)
791 return 0;
792 rv = fips_drbg_kat(tctx, dctx->type, dctx->xflags);
793 if (tctx)
794 FIPS_drbg_free(tctx);
795 if (rv)
796 fips_post_success(FIPS_TEST_DRBG, dctx->type, &dctx->xflags);
797 else
798 fips_post_failed(FIPS_TEST_DRBG, dctx->type, &dctx->xflags);
799 return rv;
800 }
801
802 int FIPS_selftest_drbg(void)
803 {
804 DRBG_CTX *dctx;
805 DRBG_SELFTEST_DATA *td;
806 int rv = 1;
807 dctx = FIPS_drbg_new(0, 0);
808 if (!dctx)
809 return 0;
810 for (td = drbg_test; td->nid != 0; td++)
811 {
812 if (td->post != 1)
813 continue;
814 if (!fips_post_started(FIPS_TEST_DRBG, td->nid, &td->flags))
815 return 1;
816 if (!fips_drbg_single_kat(dctx, td, 1))
817 {
818 fips_post_failed(FIPS_TEST_DRBG, td->nid, &td->flags);
819 rv = 0;
820 continue;
821 }
822 if (!fips_post_success(FIPS_TEST_DRBG, td->nid, &td->flags))
823 return 0;
824 }
825 FIPS_drbg_free(dctx);
826 return rv;
827 }
828
829
830 int FIPS_selftest_drbg_all(void)
831 {
832 DRBG_CTX *dctx;
833 DRBG_SELFTEST_DATA *td;
834 int rv = 1;
835 dctx = FIPS_drbg_new(0, 0);
836 if (!dctx)
837 return 0;
838 for (td = drbg_test; td->nid != 0; td++)
839 {
840 if (!fips_post_started(FIPS_TEST_DRBG, td->nid, &td->flags))
841 return 1;
842 if (!fips_drbg_single_kat(dctx, td, 0))
843 {
844 fips_post_failed(FIPS_TEST_DRBG, td->nid, &td->flags);
845 rv = 0;
846 continue;
847 }
848 if (!fips_drbg_health_check(dctx, td))
849 {
850 fips_post_failed(FIPS_TEST_DRBG, td->nid, &td->flags);
851 rv = 0;
852 continue;
853 }
854 if (!fips_post_success(FIPS_TEST_DRBG, td->nid, &td->flags))
855 return 0;
856 }
857 FIPS_drbg_free(dctx);
858 return rv;
859 }
860