]> git.ipfire.org Git - thirdparty/openssl.git/blame - fips/rand/fips_drbg_selftest.c
Use function name FIPS_drbg_health_check() for health check function.
[thirdparty/openssl.git] / fips / rand / fips_drbg_selftest.c
CommitLineData
fbbabb64
DSH
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>
fbbabb64
DSH
58#include <openssl/err.h>
59#include <openssl/fips_rand.h>
60#include "fips_rand_lcl.h"
76089788 61#include "fips_locl.h"
fbbabb64 62
eb9e63df
DSH
63#include "fips_drbg_selftest.h"
64
fbbabb64 65typedef struct {
74c40744 66 int post;
fbbabb64
DSH
67 int nid;
68 unsigned int flags;
eb9e63df
DSH
69
70 /* KAT data for no PR */
fbbabb64
DSH
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;
eb9e63df
DSH
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;
fbbabb64
DSH
85 const unsigned char *kat;
86 size_t katlen;
eb9e63df
DSH
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
fbbabb64
DSH
110 } DRBG_SELFTEST_DATA;
111
74c40744 112#define make_drbg_test_data(nid, flag, pr, p) {p, nid, flag | DRBG_FLAG_TEST, \
fbbabb64
DSH
113 pr##_entropyinput, sizeof(pr##_entropyinput), \
114 pr##_nonce, sizeof(pr##_nonce), \
115 pr##_personalizationstring, sizeof(pr##_personalizationstring), \
116 pr##_additionalinput, sizeof(pr##_additionalinput), \
eb9e63df
DSH
117 pr##_entropyinputreseed, sizeof(pr##_entropyinputreseed), \
118 pr##_additionalinputreseed, sizeof(pr##_additionalinputreseed), \
fbbabb64 119 pr##_additionalinput2, sizeof(pr##_additionalinput2), \
eb9e63df 120 pr##_int_returnedbits, sizeof(pr##_int_returnedbits), \
fbbabb64 121 pr##_returnedbits, sizeof(pr##_returnedbits), \
eb9e63df
DSH
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), \
fbbabb64
DSH
131 }
132
74c40744
DSH
133#define make_drbg_test_data_df(nid, pr, p) \
134 make_drbg_test_data(nid, DRBG_FLAG_CTR_USE_DF, pr, p)
fbbabb64 135
7fdcb457
DSH
136#define make_drbg_test_data_ec(curve, md, pr, p) \
137 make_drbg_test_data((curve << 16) | md , 0, pr, p)
138
fbbabb64 139static DRBG_SELFTEST_DATA drbg_test[] = {
74c40744
DSH
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),
7fdcb457
DSH
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),
fbbabb64
DSH
168 {0,0,0}
169 };
170
171typedef struct
172 {
173 const unsigned char *ent;
174 size_t entlen;
96ec46f7 175 int entcnt;
fbbabb64
DSH
176 const unsigned char *nonce;
177 size_t noncelen;
96ec46f7 178 int noncecnt;
fbbabb64
DSH
179 } TEST_ENT;
180
52b6ee82 181static size_t test_entropy(DRBG_CTX *dctx, unsigned char **pout,
fbbabb64
DSH
182 int entropy, size_t min_len, size_t max_len)
183 {
184 TEST_ENT *t = FIPS_drbg_get_app_data(dctx);
52b6ee82 185 *pout = (unsigned char *)t->ent;
96ec46f7 186 t->entcnt++;
fbbabb64
DSH
187 return t->entlen;
188 }
189
52b6ee82 190static size_t test_nonce(DRBG_CTX *dctx, unsigned char **pout,
fbbabb64
DSH
191 int entropy, size_t min_len, size_t max_len)
192 {
193 TEST_ENT *t = FIPS_drbg_get_app_data(dctx);
52b6ee82 194 *pout = (unsigned char *)t->nonce;
96ec46f7 195 t->noncecnt++;
fbbabb64
DSH
196 return t->noncelen;
197 }
198
bbb19418
DSH
199static int fips_drbg_single_kat(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td,
200 int quick)
fbbabb64
DSH
201 {
202 TEST_ENT t;
203 int rv = 0;
76089788 204 size_t adinlen;
fbbabb64 205 unsigned char randout[1024];
eb9e63df
DSH
206
207 /* Initial test without PR */
208
cb71870d
DSH
209 /* Instantiate DRBG with test entropy, nonce and personalisation
210 * string.
211 */
212
fbbabb64
DSH
213 if (!FIPS_drbg_init(dctx, td->nid, td->flags))
214 return 0;
b8b6a13a 215 if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0))
fbbabb64
DSH
216 return 0;
217
218 FIPS_drbg_set_app_data(dctx, &t);
219
220 t.ent = td->ent;
221 t.entlen = td->entlen;
222 t.nonce = td->nonce;
223 t.noncelen = td->noncelen;
96ec46f7
DSH
224 t.entcnt = 0;
225 t.noncecnt = 0;
fbbabb64 226
96ec46f7 227 if (!FIPS_drbg_instantiate(dctx, td->pers, td->perslen))
fbbabb64
DSH
228 goto err;
229
76089788
DSH
230 /* Note for CTR without DF some additional input values
231 * ignore bytes after the keylength: so reduce adinlen
232 * to half to ensure invalid data is fed in.
233 */
4420b3b1 234 if (!fips_post_corrupt(FIPS_TEST_DRBG, dctx->type, &dctx->iflags))
76089788
DSH
235 adinlen = td->adinlen / 2;
236 else
237 adinlen = td->adinlen;
cb71870d
DSH
238
239 /* Generate with no PR and verify output matches expected data */
de2132de 240 if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0,
76089788 241 td->adin, adinlen))
fbbabb64
DSH
242 goto err;
243
eb9e63df 244 if (memcmp(randout, td->kat, td->katlen))
bbb19418
DSH
245 {
246 FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_NOPR_TEST1_FAILURE);
247 goto err2;
248 }
cb71870d 249 /* If abbreviated POST end of test */
d9836039
DSH
250 if (quick)
251 {
252 rv = 1;
253 goto err;
254 }
cb71870d 255 /* Reseed DRBG with test entropy and additional input */
eb9e63df
DSH
256 t.ent = td->entreseed;
257 t.entlen = td->entreseedlen;
fbbabb64 258
eb9e63df 259 if (!FIPS_drbg_reseed(dctx, td->adinreseed, td->adinreseedlen))
fbbabb64
DSH
260 goto err;
261
cb71870d 262 /* Generate with no PR and verify output matches expected data */
de2132de 263 if (!FIPS_drbg_generate(dctx, randout, td->kat2len, 0,
eb9e63df
DSH
264 td->adin2, td->adin2len))
265 goto err;
266
267 if (memcmp(randout, td->kat2, td->kat2len))
bbb19418
DSH
268 {
269 FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_NOPR_TEST2_FAILURE);
270 goto err2;
271 }
eb9e63df
DSH
272
273 FIPS_drbg_uninstantiate(dctx);
274
275 /* Now test with PR */
cb71870d
DSH
276
277 /* Instantiate DRBG with test entropy, nonce and personalisation
278 * string.
279 */
eb9e63df
DSH
280 if (!FIPS_drbg_init(dctx, td->nid, td->flags))
281 return 0;
282 if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0))
283 return 0;
284
285 FIPS_drbg_set_app_data(dctx, &t);
286
287 t.ent = td->ent_pr;
288 t.entlen = td->entlen_pr;
289 t.nonce = td->nonce_pr;
290 t.noncelen = td->noncelen_pr;
291 t.entcnt = 0;
292 t.noncecnt = 0;
293
294 if (!FIPS_drbg_instantiate(dctx, td->pers_pr, td->perslen_pr))
295 goto err;
296
cb71870d
DSH
297 /* Now generate with PR: we need to supply entropy as this will
298 * perform a reseed operation. Check output matches expected value.
299 */
300
eb9e63df
DSH
301 t.ent = td->entpr_pr;
302 t.entlen = td->entprlen_pr;
303
304 /* Note for CTR without DF some additional input values
305 * ignore bytes after the keylength: so reduce adinlen
306 * to half to ensure invalid data is fed in.
307 */
4420b3b1 308 if (!fips_post_corrupt(FIPS_TEST_DRBG, dctx->type, &dctx->iflags))
eb9e63df
DSH
309 adinlen = td->adinlen_pr / 2;
310 else
311 adinlen = td->adinlen_pr;
de2132de 312 if (!FIPS_drbg_generate(dctx, randout, td->katlen_pr, 1,
eb9e63df
DSH
313 td->adin_pr, adinlen))
314 goto err;
315
316 if (memcmp(randout, td->kat_pr, td->katlen_pr))
bbb19418
DSH
317 {
318 FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_PR_TEST1_FAILURE);
319 goto err2;
320 }
321
cb71870d
DSH
322 /* Now generate again with PR: supply new entropy again.
323 * Check output matches expected value.
324 */
325
eb9e63df
DSH
326 t.ent = td->entg_pr;
327 t.entlen = td->entglen_pr;
328
de2132de 329 if (!FIPS_drbg_generate(dctx, randout, td->kat2len_pr, 1,
eb9e63df
DSH
330 td->ading_pr, td->adinglen_pr))
331 goto err;
332
333 if (memcmp(randout, td->kat2_pr, td->kat2len_pr))
bbb19418
DSH
334 {
335 FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_PR_TEST2_FAILURE);
336 goto err2;
337 }
cb71870d 338 /* All OK, test complete */
fbbabb64
DSH
339 rv = 1;
340
341 err:
e06de4dd
DSH
342 if (rv == 0)
343 FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_SELFTEST_FAILED);
bbb19418 344 err2:
fbbabb64
DSH
345 FIPS_drbg_uninstantiate(dctx);
346
347 return rv;
eb9e63df 348
fbbabb64
DSH
349 }
350
a11f06b2
DSH
351/* Initialise a DRBG based on selftest data */
352
353static int do_drbg_init(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td, TEST_ENT *t)
354 {
355
356 if (!FIPS_drbg_init(dctx, td->nid, td->flags))
357 return 0;
358
359 if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0))
360 return 0;
361
362 FIPS_drbg_set_app_data(dctx, t);
363
364 t->ent = td->ent;
365 t->entlen = td->entlen;
366 t->nonce = td->nonce;
367 t->noncelen = td->noncelen;
368 t->entcnt = 0;
369 t->noncecnt = 0;
370 return 1;
371 }
372
373/* Initialise and instantiate DRBG based on selftest data */
374static int do_drbg_instantiate(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td,
375 TEST_ENT *t)
376 {
377 if (!do_drbg_init(dctx, td, t))
378 return 0;
379 if (!FIPS_drbg_instantiate(dctx, td->pers, td->perslen))
380 return 0;
381
382 return 1;
383 }
384
cb71870d
DSH
385/* This function performd extensive error checking as required by SP800-90.
386 * Induce several failure modes and check an error condition is set.
387 * This function along with fips_drbg_single_kat peforms the health checking
388 * operation.
96ec46f7
DSH
389 */
390
cb71870d 391static int fips_drbg_error_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td)
96ec46f7
DSH
392 {
393 unsigned char randout[1024];
394 TEST_ENT t;
395 size_t i;
74c40744 396 unsigned int reseed_counter_tmp;
96ec46f7
DSH
397 unsigned char *p = (unsigned char *)dctx;
398
399 /* Initialise DRBG */
400
a11f06b2 401 if (!do_drbg_init(dctx, td, &t))
96ec46f7
DSH
402 goto err;
403
96ec46f7 404 /* Don't report induced errors */
4420b3b1 405 dctx->iflags |= DRBG_FLAG_NOERR;
96ec46f7 406
a11f06b2
DSH
407 /* Personalisation string tests */
408
409 /* Test detection of too large personlisation string */
410
96ec46f7
DSH
411 if (FIPS_drbg_instantiate(dctx, td->pers, dctx->max_pers + 1) > 0)
412 {
413 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_PERSONALISATION_ERROR_UNDETECTED);
414 goto err;
415 }
416
a11f06b2
DSH
417 /* Entropy source tests */
418
419 /* Test entropy source failure detecion: i.e. returns no data */
96ec46f7
DSH
420
421 t.entlen = 0;
a11f06b2 422
96ec46f7
DSH
423 if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0)
424 {
425 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
426 goto err;
427 }
428
429 /* Try to generate output from uninstantiated DRBG */
de2132de 430 if (FIPS_drbg_generate(dctx, randout, td->katlen, 0,
96ec46f7
DSH
431 td->adin, td->adinlen))
432 {
433 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_GENERATE_ERROR_UNDETECTED);
434 goto err;
435 }
436
4420b3b1 437 dctx->iflags &= ~DRBG_FLAG_NOERR;
49cb5e0b
DSH
438 if (!FIPS_drbg_uninstantiate(dctx))
439 {
440 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
441 goto err;
442 }
443
a11f06b2 444 if (!do_drbg_init(dctx, td, &t))
96ec46f7 445 goto err;
a11f06b2 446
4420b3b1 447 dctx->iflags |= DRBG_FLAG_NOERR;
a11f06b2
DSH
448
449 /* Test insufficient entropy */
450
451 t.entlen = dctx->min_entropy - 1;
452
453 if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0)
454 {
455 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
96ec46f7 456 goto err;
a11f06b2 457 }
96ec46f7 458
4420b3b1 459 dctx->iflags &= ~DRBG_FLAG_NOERR;
a11f06b2
DSH
460 if (!FIPS_drbg_uninstantiate(dctx))
461 {
462 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
463 goto err;
464 }
465
466 /* Test too much entropy */
467
468 if (!do_drbg_init(dctx, td, &t))
469 goto err;
470
4420b3b1 471 dctx->iflags |= DRBG_FLAG_NOERR;
a11f06b2
DSH
472
473 t.entlen = dctx->max_entropy + 1;
474
475 if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0)
476 {
477 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
96ec46f7 478 goto err;
a11f06b2
DSH
479 }
480
4420b3b1 481 dctx->iflags &= ~DRBG_FLAG_NOERR;
a11f06b2
DSH
482 if (!FIPS_drbg_uninstantiate(dctx))
483 {
484 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
485 goto err;
486 }
487
488 /* Nonce tests */
489
490 /* Test too small nonce */
491
492 if (dctx->min_nonce)
493 {
494
495 if (!do_drbg_init(dctx, td, &t))
496 goto err;
497
4420b3b1 498 dctx->iflags |= DRBG_FLAG_NOERR;
a11f06b2
DSH
499
500 t.noncelen = dctx->min_nonce - 1;
501
502 if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0)
503 {
504 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_NONCE_ERROR_UNDETECTED);
505 goto err;
506 }
507
4420b3b1 508 dctx->iflags &= ~DRBG_FLAG_NOERR;
a11f06b2
DSH
509 if (!FIPS_drbg_uninstantiate(dctx))
510 {
511 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
512 goto err;
513 }
514
515 }
516
517 /* Test too large nonce */
518
519 if (dctx->max_nonce)
520 {
521
522 if (!do_drbg_init(dctx, td, &t))
523 goto err;
524
4420b3b1 525 dctx->iflags |= DRBG_FLAG_NOERR;
a11f06b2
DSH
526
527 t.noncelen = dctx->max_nonce + 1;
528
529 if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0)
530 {
531 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_NONCE_ERROR_UNDETECTED);
532 goto err;
533 }
534
4420b3b1 535 dctx->iflags &= ~DRBG_FLAG_NOERR;
a11f06b2
DSH
536 if (!FIPS_drbg_uninstantiate(dctx))
537 {
538 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
539 goto err;
540 }
541
542 }
543
544 /* Instantiate with valid data. */
545 if (!do_drbg_instantiate(dctx, td, &t))
546 goto err;
96ec46f7
DSH
547
548 /* Check generation is now OK */
de2132de 549 if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0,
96ec46f7
DSH
550 td->adin, td->adinlen))
551 goto err;
552
4420b3b1 553 dctx->iflags |= DRBG_FLAG_NOERR;
96ec46f7
DSH
554
555 /* Request too much data for one request */
de2132de 556 if (FIPS_drbg_generate(dctx, randout, dctx->max_request + 1, 0,
96ec46f7
DSH
557 td->adin, td->adinlen))
558 {
559 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_REQUEST_LENGTH_ERROR_UNDETECTED);
560 goto err;
561 }
562
a11f06b2
DSH
563 /* Try too large additional input */
564 if (FIPS_drbg_generate(dctx, randout, td->katlen, 0,
565 td->adin, dctx->max_adin + 1))
566 {
567 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ADDITIONAL_INPUT_ERROR_UNDETECTED);
568 goto err;
569 }
570
96ec46f7
DSH
571 /* Check prediction resistance request fails if entropy source
572 * failure.
573 */
574
575 t.entlen = 0;
576
de2132de 577 if (FIPS_drbg_generate(dctx, randout, td->katlen, 1,
96ec46f7
DSH
578 td->adin, td->adinlen))
579 {
580 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
581 goto err;
582 }
583
4420b3b1 584 dctx->iflags &= ~DRBG_FLAG_NOERR;
49cb5e0b
DSH
585
586 if (!FIPS_drbg_uninstantiate(dctx))
587 {
588 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
589 goto err;
590 }
591
96ec46f7
DSH
592
593 /* Instantiate again with valid data */
594
a11f06b2
DSH
595 if (!do_drbg_instantiate(dctx, td, &t))
596 goto err;
597 /* Test reseed counter works */
598 /* Save initial reseed counter */
599 reseed_counter_tmp = dctx->reseed_counter;
600 /* Set reseed counter to beyond interval */
601 dctx->reseed_counter = dctx->reseed_interval;
602
603 /* Generate output and check entropy has been requested for reseed */
604 t.entcnt = 0;
605 if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0,
606 td->adin, td->adinlen))
96ec46f7 607 goto err;
a11f06b2
DSH
608 if (t.entcnt != 1)
609 {
610 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED);
96ec46f7 611 goto err;
a11f06b2
DSH
612 }
613 /* Check reseed counter has been reset */
614 if (dctx->reseed_counter != reseed_counter_tmp + 1)
615 {
616 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_RESEED_COUNTER_ERROR);
617 goto err;
618 }
96ec46f7 619
a11f06b2
DSH
620 /* Explicit reseed tests */
621
622 /* Test explicit reseed with too large additional input */
623 if (!do_drbg_init(dctx, td, &t))
624 goto err;
625
4420b3b1 626 dctx->iflags |= DRBG_FLAG_NOERR;
a11f06b2
DSH
627
628 if (FIPS_drbg_reseed(dctx, td->adin, dctx->max_adin + 1) > 0)
629 {
630 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ADDITIONAL_INPUT_ERROR_UNDETECTED);
631 goto err;
632 }
633
634 /* Test explicit reseed with entropy source failure */
635
636 /* Check prediction resistance request fails if entropy source
637 * failure.
638 */
639
640 t.entlen = 0;
641
642 if (FIPS_drbg_generate(dctx, randout, td->katlen, 1,
643 td->adin, td->adinlen))
644 {
645 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
646 goto err;
647 }
648
4420b3b1 649 dctx->iflags &= ~DRBG_FLAG_NOERR;
a11f06b2
DSH
650
651 if (!FIPS_drbg_uninstantiate(dctx))
652 {
653 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
96ec46f7 654 goto err;
a11f06b2
DSH
655 }
656
657
658 if (!do_drbg_instantiate(dctx, td, &t))
659 goto err;
660 /* Test reseed counter works */
74c40744
DSH
661 /* Save initial reseed counter */
662 reseed_counter_tmp = dctx->reseed_counter;
663 /* Set reseed counter to beyond interval */
664 dctx->reseed_counter = dctx->reseed_interval;
96ec46f7 665
74c40744 666 /* Generate output and check entropy has been requested for reseed */
96ec46f7 667 t.entcnt = 0;
de2132de 668 if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0,
96ec46f7
DSH
669 td->adin, td->adinlen))
670 goto err;
671 if (t.entcnt != 1)
672 {
673 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED);
674 goto err;
675 }
74c40744
DSH
676 /* Check reseed counter has been reset */
677 if (dctx->reseed_counter != reseed_counter_tmp + 1)
678 {
679 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_RESEED_COUNTER_ERROR);
680 goto err;
681 }
96ec46f7 682
a11f06b2
DSH
683 /* Explicit reseed tests */
684
685 /* Test explicit reseed with too large additional input */
686 if (!do_drbg_init(dctx, td, &t))
687 goto err;
688
4420b3b1 689 dctx->iflags |= DRBG_FLAG_NOERR;
a11f06b2
DSH
690
691 if (FIPS_drbg_reseed(dctx, td->adin, dctx->max_adin + 1) > 0)
692 {
693 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ADDITIONAL_INPUT_ERROR_UNDETECTED);
694 goto err;
695 }
696
697 /* Test explicit reseed with entropy source failure */
698
699 if (!do_drbg_init(dctx, td, &t))
700 goto err;
701
4420b3b1 702 dctx->iflags |= DRBG_FLAG_NOERR;
a11f06b2
DSH
703
704 t.entlen = 0;
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 much entropy */
719
720 if (!do_drbg_init(dctx, td, &t))
721 goto err;
722
4420b3b1 723 dctx->iflags |= DRBG_FLAG_NOERR;
a11f06b2
DSH
724
725 t.entlen = dctx->max_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 /* Test explicit reseed with too little entropy */
740
741 if (!do_drbg_init(dctx, td, &t))
742 goto err;
743
4420b3b1 744 dctx->iflags |= DRBG_FLAG_NOERR;
a11f06b2
DSH
745
746 t.entlen = dctx->min_entropy - 1;
747
748 if (FIPS_drbg_reseed(dctx, td->adin, td->adinlen) > 0)
749 {
750 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
751 goto err;
752 }
753
754 if (!FIPS_drbg_uninstantiate(dctx))
755 {
756 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
757 goto err;
758 }
759
e5cadaf8 760 p = (unsigned char *)&dctx->d;
96ec46f7
DSH
761 /* Standard says we have to check uninstantiate really zeroes
762 * the data...
763 */
e5cadaf8 764 for (i = 0; i < sizeof(dctx->d); i++)
96ec46f7
DSH
765 {
766 if (*p != 0)
767 {
768 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ZEROISE_ERROR);
769 goto err;
770 }
771 p++;
772 }
773
774 return 1;
775
776 err:
777 /* A real error as opposed to an induced one: underlying function will
778 * indicate the error.
779 */
4420b3b1 780 if (!(dctx->iflags & DRBG_FLAG_NOERR))
96ec46f7
DSH
781 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_FUNCTION_ERROR);
782 FIPS_drbg_uninstantiate(dctx);
783 return 0;
784
785 }
e5cadaf8 786
fbbabb64
DSH
787int fips_drbg_kat(DRBG_CTX *dctx, int nid, unsigned int flags)
788 {
789 DRBG_SELFTEST_DATA *td;
4420b3b1 790 flags |= DRBG_FLAG_TEST;
fbbabb64
DSH
791 for (td = drbg_test; td->nid != 0; td++)
792 {
793 if (td->nid == nid && td->flags == flags)
96ec46f7 794 {
05272d4c
DSH
795 if (!fips_drbg_single_kat(dctx, td, 0))
796 return 0;
cb71870d 797 return fips_drbg_error_check(dctx, td);
96ec46f7 798 }
fbbabb64
DSH
799 }
800 return 0;
801 }
802
cb71870d 803int FIPS_drbg_health_check(DRBG_CTX *dctx)
4420b3b1
DSH
804 {
805 int rv;
806 DRBG_CTX *tctx = NULL;
807 tctx = FIPS_drbg_new(0, 0);
808 fips_post_started(FIPS_TEST_DRBG, dctx->type, &dctx->xflags);
809 if (!tctx)
810 return 0;
811 rv = fips_drbg_kat(tctx, dctx->type, dctx->xflags);
812 if (tctx)
813 FIPS_drbg_free(tctx);
814 if (rv)
815 fips_post_success(FIPS_TEST_DRBG, dctx->type, &dctx->xflags);
816 else
817 fips_post_failed(FIPS_TEST_DRBG, dctx->type, &dctx->xflags);
cb71870d
DSH
818 if (!rv)
819 dctx->status = DRBG_STATUS_ERROR;
820 else
821 dctx->health_check_cnt = 0;
4420b3b1
DSH
822 return rv;
823 }
824
fbbabb64
DSH
825int FIPS_selftest_drbg(void)
826 {
827 DRBG_CTX *dctx;
828 DRBG_SELFTEST_DATA *td;
76089788 829 int rv = 1;
fbbabb64
DSH
830 dctx = FIPS_drbg_new(0, 0);
831 if (!dctx)
832 return 0;
833 for (td = drbg_test; td->nid != 0; td++)
96ec46f7 834 {
74c40744
DSH
835 if (td->post != 1)
836 continue;
76089788
DSH
837 if (!fips_post_started(FIPS_TEST_DRBG, td->nid, &td->flags))
838 return 1;
bbb19418 839 if (!fips_drbg_single_kat(dctx, td, 1))
76089788
DSH
840 {
841 fips_post_failed(FIPS_TEST_DRBG, td->nid, &td->flags);
842 rv = 0;
843 continue;
844 }
76089788
DSH
845 if (!fips_post_success(FIPS_TEST_DRBG, td->nid, &td->flags))
846 return 0;
96ec46f7 847 }
beb89508 848 FIPS_drbg_free(dctx);
76089788 849 return rv;
fbbabb64
DSH
850 }
851
852
a11f06b2
DSH
853int FIPS_selftest_drbg_all(void)
854 {
855 DRBG_CTX *dctx;
856 DRBG_SELFTEST_DATA *td;
857 int rv = 1;
858 dctx = FIPS_drbg_new(0, 0);
859 if (!dctx)
860 return 0;
861 for (td = drbg_test; td->nid != 0; td++)
862 {
863 if (!fips_post_started(FIPS_TEST_DRBG, td->nid, &td->flags))
864 return 1;
865 if (!fips_drbg_single_kat(dctx, td, 0))
866 {
867 fips_post_failed(FIPS_TEST_DRBG, td->nid, &td->flags);
868 rv = 0;
869 continue;
870 }
cb71870d 871 if (!fips_drbg_error_check(dctx, td))
a11f06b2
DSH
872 {
873 fips_post_failed(FIPS_TEST_DRBG, td->nid, &td->flags);
874 rv = 0;
875 continue;
876 }
877 if (!fips_post_success(FIPS_TEST_DRBG, td->nid, &td->flags))
878 return 0;
879 }
880 FIPS_drbg_free(dctx);
881 return rv;
882 }
fbbabb64 883