1 /* fips/rand/fips_drbg_selftest.c */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
5 /* ====================================================================
6 * Copyright (c) 2011 The OpenSSL Project. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
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
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/)"
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.
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.
34 * 6. Redistributions of any form whatsoever must retain the following
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
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 * ====================================================================
54 #define OPENSSL_FIPSAPI
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"
63 #include "fips_drbg_selftest.h"
70 /* KAT data for no PR */
71 const unsigned char *ent;
73 const unsigned char *nonce;
75 const unsigned char *pers;
77 const unsigned char *adin;
79 const unsigned char *entreseed;
81 const unsigned char *adinreseed;
83 const unsigned char *adin2;
85 const unsigned char *kat;
87 const unsigned char *kat2;
91 const unsigned char *ent_pr;
93 const unsigned char *nonce_pr;
95 const unsigned char *pers_pr;
97 const unsigned char *adin_pr;
99 const unsigned char *entpr_pr;
101 const unsigned char *ading_pr;
103 const unsigned char *entg_pr;
105 const unsigned char *kat_pr;
107 const unsigned char *kat2_pr;
110 } DRBG_SELFTEST_DATA;
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), \
133 #define make_drbg_test_data_df(nid, pr, p) \
134 make_drbg_test_data(nid, DRBG_FLAG_CTR_USE_DF, pr, p)
136 static DRBG_SELFTEST_DATA drbg_test[] = {
137 make_drbg_test_data_df(NID_aes_128_ctr, aes_128_use_df, 0),
138 make_drbg_test_data_df(NID_aes_192_ctr, aes_192_use_df, 0),
139 make_drbg_test_data_df(NID_aes_256_ctr, aes_256_use_df, 1),
140 make_drbg_test_data(NID_aes_128_ctr, 0, aes_128_no_df, 0),
141 make_drbg_test_data(NID_aes_192_ctr, 0, aes_192_no_df, 0),
142 make_drbg_test_data(NID_aes_256_ctr, 0, aes_256_no_df, 1),
143 make_drbg_test_data(NID_sha1, 0, sha1, 0),
144 make_drbg_test_data(NID_sha224, 0, sha224, 0),
145 make_drbg_test_data(NID_sha256, 0, sha256, 1),
146 make_drbg_test_data(NID_sha384, 0, sha384, 0),
147 make_drbg_test_data(NID_sha512, 0, sha512, 0),
148 make_drbg_test_data(NID_hmacWithSHA1, 0, hmac_sha1, 0),
149 make_drbg_test_data(NID_hmacWithSHA224, 0, hmac_sha224, 0),
150 make_drbg_test_data(NID_hmacWithSHA256, 0, hmac_sha256, 1),
151 make_drbg_test_data(NID_hmacWithSHA384, 0, hmac_sha384, 0),
152 make_drbg_test_data(NID_hmacWithSHA512, 0, hmac_sha512, 0),
158 const unsigned char *ent;
161 const unsigned char *nonce;
166 static size_t test_entropy(DRBG_CTX *dctx, unsigned char **pout,
167 int entropy, size_t min_len, size_t max_len)
169 TEST_ENT *t = FIPS_drbg_get_app_data(dctx);
170 *pout = (unsigned char *)t->ent;
175 static size_t test_nonce(DRBG_CTX *dctx, unsigned char **pout,
176 int entropy, size_t min_len, size_t max_len)
178 TEST_ENT *t = FIPS_drbg_get_app_data(dctx);
179 *pout = (unsigned char *)t->nonce;
184 static int fips_drbg_single_kat(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td,
190 unsigned char randout[1024];
192 /* Initial test without PR */
194 if (!FIPS_drbg_init(dctx, td->nid, td->flags))
196 if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0))
199 FIPS_drbg_set_app_data(dctx, &t);
202 t.entlen = td->entlen;
204 t.noncelen = td->noncelen;
208 if (!FIPS_drbg_instantiate(dctx, td->pers, td->perslen))
211 /* Note for CTR without DF some additional input values
212 * ignore bytes after the keylength: so reduce adinlen
213 * to half to ensure invalid data is fed in.
215 if (!fips_post_corrupt(FIPS_TEST_DRBG, dctx->type, &dctx->flags))
216 adinlen = td->adinlen / 2;
218 adinlen = td->adinlen;
219 if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0, 0,
223 if (memcmp(randout, td->kat, td->katlen))
225 FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_NOPR_TEST1_FAILURE);
229 t.ent = td->entreseed;
230 t.entlen = td->entreseedlen;
232 if (!FIPS_drbg_reseed(dctx, td->adinreseed, td->adinreseedlen))
235 if (!FIPS_drbg_generate(dctx, randout, td->kat2len, 0, 0,
236 td->adin2, td->adin2len))
239 if (memcmp(randout, td->kat2, td->kat2len))
241 FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_NOPR_TEST2_FAILURE);
245 FIPS_drbg_uninstantiate(dctx);
247 /* Now test with PR */
248 if (!FIPS_drbg_init(dctx, td->nid, td->flags))
250 if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0))
253 FIPS_drbg_set_app_data(dctx, &t);
256 t.entlen = td->entlen_pr;
257 t.nonce = td->nonce_pr;
258 t.noncelen = td->noncelen_pr;
262 if (!FIPS_drbg_instantiate(dctx, td->pers_pr, td->perslen_pr))
265 t.ent = td->entpr_pr;
266 t.entlen = td->entprlen_pr;
268 /* Note for CTR without DF some additional input values
269 * ignore bytes after the keylength: so reduce adinlen
270 * to half to ensure invalid data is fed in.
272 if (!fips_post_corrupt(FIPS_TEST_DRBG, dctx->type, &dctx->flags))
273 adinlen = td->adinlen_pr / 2;
275 adinlen = td->adinlen_pr;
276 if (!FIPS_drbg_generate(dctx, randout, td->katlen_pr, 0, 1,
277 td->adin_pr, adinlen))
280 if (memcmp(randout, td->kat_pr, td->katlen_pr))
282 FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_PR_TEST1_FAILURE);
293 t.entlen = td->entglen_pr;
295 if (!FIPS_drbg_generate(dctx, randout, td->kat2len_pr, 0, 1,
296 td->ading_pr, td->adinglen_pr))
299 if (memcmp(randout, td->kat2_pr, td->kat2len_pr))
301 FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_PR_TEST2_FAILURE);
309 FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_SELFTEST_FAILED);
311 FIPS_drbg_uninstantiate(dctx);
317 /* This is the "health check" function required by SP800-90. Induce several
318 * failure modes and check an error condition is set.
321 static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td)
323 unsigned char randout[1024];
326 unsigned int reseed_counter_tmp;
327 unsigned char *p = (unsigned char *)dctx;
329 /* Initialise DRBG */
331 if (!FIPS_drbg_init(dctx, td->nid, td->flags))
334 if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0))
337 FIPS_drbg_set_app_data(dctx, &t);
340 t.entlen = td->entlen;
342 t.noncelen = td->noncelen;
346 /* Don't report induced errors */
347 dctx->flags |= DRBG_FLAG_NOERR;
349 /* Try too large a personalisation length */
350 if (FIPS_drbg_instantiate(dctx, td->pers, dctx->max_pers + 1) > 0)
352 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_PERSONALISATION_ERROR_UNDETECTED);
356 /* Test entropy source failure detection */
359 if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0)
361 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
365 /* Try to generate output from uninstantiated DRBG */
366 if (FIPS_drbg_generate(dctx, randout, td->katlen, 0, 0,
367 td->adin, td->adinlen))
369 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_GENERATE_ERROR_UNDETECTED);
373 dctx->flags &= ~DRBG_FLAG_NOERR;
374 if (!FIPS_drbg_uninstantiate(dctx))
376 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
380 /* Instantiate with valid data. NB: errors now reported again */
381 if (!FIPS_drbg_init(dctx, td->nid, td->flags))
383 if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0))
385 FIPS_drbg_set_app_data(dctx, &t);
387 t.entlen = td->entlen;
388 if (!FIPS_drbg_instantiate(dctx, td->pers, td->perslen))
391 /* Check generation is now OK */
392 if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0, 0,
393 td->adin, td->adinlen))
396 /* Try to generate with too high a strength.
399 dctx->flags |= DRBG_FLAG_NOERR;
400 if (dctx->strength != 256)
402 if (FIPS_drbg_generate(dctx, randout, td->katlen, 256, 0,
403 td->adin, td->adinlen))
405 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_STRENGTH_ERROR_UNDETECTED);
411 /* Request too much data for one request */
412 if (FIPS_drbg_generate(dctx, randout, dctx->max_request + 1, 0, 0,
413 td->adin, td->adinlen))
415 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_REQUEST_LENGTH_ERROR_UNDETECTED);
419 /* Check prediction resistance request fails if entropy source
425 if (FIPS_drbg_generate(dctx, randout, td->katlen, 0, 1,
426 td->adin, td->adinlen))
428 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
432 dctx->flags &= ~DRBG_FLAG_NOERR;
434 if (!FIPS_drbg_uninstantiate(dctx))
436 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
441 /* Instantiate again with valid data */
443 if (!FIPS_drbg_init(dctx, td->nid, td->flags))
445 if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0))
447 FIPS_drbg_set_app_data(dctx, &t);
449 t.entlen = td->entlen;
450 /* Test reseed counter works */
451 if (!FIPS_drbg_instantiate(dctx, td->pers, td->perslen))
453 /* Save initial reseed counter */
454 reseed_counter_tmp = dctx->reseed_counter;
455 /* Set reseed counter to beyond interval */
456 dctx->reseed_counter = dctx->reseed_interval;
458 /* Generate output and check entropy has been requested for reseed */
460 if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0, 0,
461 td->adin, td->adinlen))
465 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED);
468 /* Check reseed counter has been reset */
469 if (dctx->reseed_counter != reseed_counter_tmp + 1)
471 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_RESEED_COUNTER_ERROR);
475 FIPS_drbg_uninstantiate(dctx);
476 p = (unsigned char *)&dctx->d;
477 /* Standard says we have to check uninstantiate really zeroes
480 for (i = 0; i < sizeof(dctx->d); i++)
484 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ZEROISE_ERROR);
493 /* A real error as opposed to an induced one: underlying function will
494 * indicate the error.
496 if (!(dctx->flags & DRBG_FLAG_NOERR))
497 FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_FUNCTION_ERROR);
498 FIPS_drbg_uninstantiate(dctx);
504 int fips_drbg_kat(DRBG_CTX *dctx, int nid, unsigned int flags)
507 DRBG_SELFTEST_DATA *td;
508 for (td = drbg_test; td->nid != 0; td++)
510 if (td->nid == nid && td->flags == flags)
512 rv = fips_drbg_single_kat(dctx, td, 0);
515 return fips_drbg_health_check(dctx, td);
521 int FIPS_selftest_drbg(void)
524 DRBG_SELFTEST_DATA *td;
526 dctx = FIPS_drbg_new(0, 0);
529 for (td = drbg_test; td->nid != 0; td++)
533 if (!fips_post_started(FIPS_TEST_DRBG, td->nid, &td->flags))
535 if (!fips_drbg_single_kat(dctx, td, 1))
537 fips_post_failed(FIPS_TEST_DRBG, td->nid, &td->flags);
541 if (!fips_post_success(FIPS_TEST_DRBG, td->nid, &td->flags))
544 FIPS_drbg_free(dctx);