fips_drbg_selftest.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  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. #define OPENSSL_FIPSAPI
  54. #include <string.h>
  55. #include <openssl/crypto.h>
  56. #include <openssl/err.h>
  57. #include <openssl/fips_rand.h>
  58. #include "fips_rand_lcl.h"
  59. #include "fips_locl.h"
  60. #include "fips_drbg_selftest.h"
  61. typedef struct {
  62. int post;
  63. int nid;
  64. unsigned int flags;
  65. /* KAT data for no PR */
  66. const unsigned char *ent;
  67. size_t entlen;
  68. const unsigned char *nonce;
  69. size_t noncelen;
  70. const unsigned char *pers;
  71. size_t perslen;
  72. const unsigned char *adin;
  73. size_t adinlen;
  74. const unsigned char *entreseed;
  75. size_t entreseedlen;
  76. const unsigned char *adinreseed;
  77. size_t adinreseedlen;
  78. const unsigned char *adin2;
  79. size_t adin2len;
  80. const unsigned char *kat;
  81. size_t katlen;
  82. const unsigned char *kat2;
  83. size_t kat2len;
  84. /* KAT data for PR */
  85. const unsigned char *ent_pr;
  86. size_t entlen_pr;
  87. const unsigned char *nonce_pr;
  88. size_t noncelen_pr;
  89. const unsigned char *pers_pr;
  90. size_t perslen_pr;
  91. const unsigned char *adin_pr;
  92. size_t adinlen_pr;
  93. const unsigned char *entpr_pr;
  94. size_t entprlen_pr;
  95. const unsigned char *ading_pr;
  96. size_t adinglen_pr;
  97. const unsigned char *entg_pr;
  98. size_t entglen_pr;
  99. const unsigned char *kat_pr;
  100. size_t katlen_pr;
  101. const unsigned char *kat2_pr;
  102. size_t kat2len_pr;
  103. } DRBG_SELFTEST_DATA;
  104. #define make_drbg_test_data(nid, flag, pr, p) {p, nid, flag | DRBG_FLAG_TEST, \
  105. pr##_entropyinput, sizeof(pr##_entropyinput), \
  106. pr##_nonce, sizeof(pr##_nonce), \
  107. pr##_personalizationstring, sizeof(pr##_personalizationstring), \
  108. pr##_additionalinput, sizeof(pr##_additionalinput), \
  109. pr##_entropyinputreseed, sizeof(pr##_entropyinputreseed), \
  110. pr##_additionalinputreseed, sizeof(pr##_additionalinputreseed), \
  111. pr##_additionalinput2, sizeof(pr##_additionalinput2), \
  112. pr##_int_returnedbits, sizeof(pr##_int_returnedbits), \
  113. pr##_returnedbits, sizeof(pr##_returnedbits), \
  114. pr##_pr_entropyinput, sizeof(pr##_pr_entropyinput), \
  115. pr##_pr_nonce, sizeof(pr##_pr_nonce), \
  116. pr##_pr_personalizationstring, sizeof(pr##_pr_personalizationstring), \
  117. pr##_pr_additionalinput, sizeof(pr##_pr_additionalinput), \
  118. pr##_pr_entropyinputpr, sizeof(pr##_pr_entropyinputpr), \
  119. pr##_pr_additionalinput2, sizeof(pr##_pr_additionalinput2), \
  120. pr##_pr_entropyinputpr2, sizeof(pr##_pr_entropyinputpr2), \
  121. pr##_pr_int_returnedbits, sizeof(pr##_pr_int_returnedbits), \
  122. pr##_pr_returnedbits, sizeof(pr##_pr_returnedbits), \
  123. }
  124. #define make_drbg_test_data_df(nid, pr, p) \
  125. make_drbg_test_data(nid, DRBG_FLAG_CTR_USE_DF, pr, p)
  126. #define make_drbg_test_data_ec(curve, md, pr, p) \
  127. make_drbg_test_data((curve << 16) | md , 0, pr, p)
  128. static DRBG_SELFTEST_DATA drbg_test[] = {
  129. make_drbg_test_data_df(NID_aes_128_ctr, aes_128_use_df, 0),
  130. make_drbg_test_data_df(NID_aes_192_ctr, aes_192_use_df, 0),
  131. make_drbg_test_data_df(NID_aes_256_ctr, aes_256_use_df, 1),
  132. make_drbg_test_data(NID_aes_128_ctr, 0, aes_128_no_df, 0),
  133. make_drbg_test_data(NID_aes_192_ctr, 0, aes_192_no_df, 0),
  134. make_drbg_test_data(NID_aes_256_ctr, 0, aes_256_no_df, 1),
  135. make_drbg_test_data(NID_sha1, 0, sha1, 0),
  136. make_drbg_test_data(NID_sha224, 0, sha224, 0),
  137. make_drbg_test_data(NID_sha256, 0, sha256, 1),
  138. make_drbg_test_data(NID_sha384, 0, sha384, 0),
  139. make_drbg_test_data(NID_sha512, 0, sha512, 0),
  140. make_drbg_test_data(NID_hmacWithSHA1, 0, hmac_sha1, 0),
  141. make_drbg_test_data(NID_hmacWithSHA224, 0, hmac_sha224, 0),
  142. make_drbg_test_data(NID_hmacWithSHA256, 0, hmac_sha256, 1),
  143. make_drbg_test_data(NID_hmacWithSHA384, 0, hmac_sha384, 0),
  144. make_drbg_test_data(NID_hmacWithSHA512, 0, hmac_sha512, 0),
  145. make_drbg_test_data_ec(NID_X9_62_prime256v1, NID_sha1, p_256_sha1, 0),
  146. make_drbg_test_data_ec(NID_X9_62_prime256v1, NID_sha224, p_256_sha224, 0),
  147. make_drbg_test_data_ec(NID_X9_62_prime256v1, NID_sha256, p_256_sha256, 1),
  148. make_drbg_test_data_ec(NID_X9_62_prime256v1, NID_sha384, p_256_sha384, 0),
  149. make_drbg_test_data_ec(NID_X9_62_prime256v1, NID_sha512, p_256_sha512, 0),
  150. make_drbg_test_data_ec(NID_secp384r1, NID_sha224, p_384_sha224, 0),
  151. make_drbg_test_data_ec(NID_secp384r1, NID_sha256, p_384_sha256, 0),
  152. make_drbg_test_data_ec(NID_secp384r1, NID_sha384, p_384_sha384, 0),
  153. make_drbg_test_data_ec(NID_secp384r1, NID_sha512, p_384_sha512, 0),
  154. make_drbg_test_data_ec(NID_secp521r1, NID_sha256, p_521_sha256, 0),
  155. make_drbg_test_data_ec(NID_secp521r1, NID_sha384, p_521_sha384, 0),
  156. make_drbg_test_data_ec(NID_secp521r1, NID_sha512, p_521_sha512, 0),
  157. {0,0,0}
  158. };
  159. typedef struct
  160. {
  161. const unsigned char *ent;
  162. size_t entlen;
  163. int entcnt;
  164. const unsigned char *nonce;
  165. size_t noncelen;
  166. int noncecnt;
  167. } TEST_ENT;
  168. static size_t test_entropy(DRBG_CTX *dctx, unsigned char **pout,
  169. int entropy, size_t min_len, size_t max_len)
  170. {
  171. TEST_ENT *t = FIPS_drbg_get_app_data(dctx);
  172. *pout = (unsigned char *)t->ent;
  173. t->entcnt++;
  174. return t->entlen;
  175. }
  176. static size_t test_nonce(DRBG_CTX *dctx, unsigned char **pout,
  177. int entropy, size_t min_len, size_t max_len)
  178. {
  179. TEST_ENT *t = FIPS_drbg_get_app_data(dctx);
  180. *pout = (unsigned char *)t->nonce;
  181. t->noncecnt++;
  182. return t->noncelen;
  183. }
  184. static int fips_drbg_single_kat(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td,
  185. int quick)
  186. {
  187. TEST_ENT t;
  188. int rv = 0;
  189. size_t adinlen;
  190. unsigned char randout[1024];
  191. /* Initial test without PR */
  192. /* Instantiate DRBG with test entropy, nonce and personalisation
  193. * string.
  194. */
  195. if (!FIPS_drbg_init(dctx, td->nid, td->flags))
  196. return 0;
  197. if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0))
  198. return 0;
  199. FIPS_drbg_set_app_data(dctx, &t);
  200. t.ent = td->ent;
  201. t.entlen = td->entlen;
  202. t.nonce = td->nonce;
  203. t.noncelen = td->noncelen;
  204. t.entcnt = 0;
  205. t.noncecnt = 0;
  206. if (!FIPS_drbg_instantiate(dctx, td->pers, td->perslen))
  207. goto err;
  208. /* Note for CTR without DF some additional input values
  209. * ignore bytes after the keylength: so reduce adinlen
  210. * to half to ensure invalid data is fed in.
  211. */
  212. if (!fips_post_corrupt(FIPS_TEST_DRBG, dctx->type, &dctx->iflags))
  213. adinlen = td->adinlen / 2;
  214. else
  215. adinlen = td->adinlen;
  216. /* Generate with no PR and verify output matches expected data */
  217. if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0,
  218. td->adin, adinlen))
  219. goto err;
  220. if (memcmp(randout, td->kat, td->katlen))
  221. {
  222. FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_NOPR_TEST1_FAILURE);
  223. goto err2;
  224. }
  225. /* If abbreviated POST end of test */
  226. if (quick)
  227. {
  228. rv = 1;
  229. goto err;
  230. }
  231. /* Reseed DRBG with test entropy and additional input */
  232. t.ent = td->entreseed;
  233. t.entlen = td->entreseedlen;
  234. if (!FIPS_drbg_reseed(dctx, td->adinreseed, td->adinreseedlen))
  235. goto err;
  236. /* Generate with no PR and verify output matches expected data */
  237. if (!FIPS_drbg_generate(dctx, randout, td->kat2len, 0,
  238. td->adin2, td->adin2len))
  239. goto err;
  240. if (memcmp(randout, td->kat2, td->kat2len))
  241. {
  242. FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_NOPR_TEST2_FAILURE);
  243. goto err2;
  244. }
  245. FIPS_drbg_uninstantiate(dctx);
  246. /* Now test with PR */
  247. /* Instantiate DRBG with test entropy, nonce and personalisation
  248. * string.
  249. */
  250. if (!FIPS_drbg_init(dctx, td->nid, td->flags))
  251. return 0;
  252. if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0))
  253. return 0;
  254. FIPS_drbg_set_app_data(dctx, &t);
  255. t.ent = td->ent_pr;
  256. t.entlen = td->entlen_pr;
  257. t.nonce = td->nonce_pr;
  258. t.noncelen = td->noncelen_pr;
  259. t.entcnt = 0;
  260. t.noncecnt = 0;
  261. if (!FIPS_drbg_instantiate(dctx, td->pers_pr, td->perslen_pr))
  262. goto err;
  263. /* Now generate with PR: we need to supply entropy as this will
  264. * perform a reseed operation. Check output matches expected value.
  265. */
  266. t.ent = td->entpr_pr;
  267. 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.
  271. */
  272. if (!fips_post_corrupt(FIPS_TEST_DRBG, dctx->type, &dctx->iflags))
  273. adinlen = td->adinlen_pr / 2;
  274. else
  275. adinlen = td->adinlen_pr;
  276. if (!FIPS_drbg_generate(dctx, randout, td->katlen_pr, 1,
  277. td->adin_pr, adinlen))
  278. goto err;
  279. if (memcmp(randout, td->kat_pr, td->katlen_pr))
  280. {
  281. FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_PR_TEST1_FAILURE);
  282. goto err2;
  283. }
  284. /* Now generate again with PR: supply new entropy again.
  285. * Check output matches expected value.
  286. */
  287. t.ent = td->entg_pr;
  288. t.entlen = td->entglen_pr;
  289. if (!FIPS_drbg_generate(dctx, randout, td->kat2len_pr, 1,
  290. td->ading_pr, td->adinglen_pr))
  291. goto err;
  292. if (memcmp(randout, td->kat2_pr, td->kat2len_pr))
  293. {
  294. FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_PR_TEST2_FAILURE);
  295. goto err2;
  296. }
  297. /* All OK, test complete */
  298. rv = 1;
  299. err:
  300. if (rv == 0)
  301. FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_SELFTEST_FAILED);
  302. err2:
  303. FIPS_drbg_uninstantiate(dctx);
  304. return rv;
  305. }
  306. /* Initialise a DRBG based on selftest data */
  307. static int do_drbg_init(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td, TEST_ENT *t)
  308. {
  309. if (!FIPS_drbg_init(dctx, td->nid, td->flags))
  310. return 0;
  311. if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0))
  312. return 0;
  313. FIPS_drbg_set_app_data(dctx, t);
  314. t->ent = td->ent;
  315. t->entlen = td->entlen;
  316. t->nonce = td->nonce;
  317. t->noncelen = td->noncelen;
  318. t->entcnt = 0;
  319. t->noncecnt = 0;
  320. return 1;
  321. }
  322. /* Initialise and instantiate DRBG based on selftest data */
  323. static int do_drbg_instantiate(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td,
  324. TEST_ENT *t)
  325. {
  326. if (!do_drbg_init(dctx, td, t))
  327. return 0;
  328. if (!FIPS_drbg_instantiate(dctx, td->pers, td->perslen))
  329. return 0;
  330. return 1;
  331. }
  332. /* This function performs extensive error checking as required by SP800-90.
  333. * Induce several failure modes and check an error condition is set.
  334. * This function along with fips_drbg_single_kat peforms the health checking
  335. * operation.
  336. */
  337. static int fips_drbg_error_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td)
  338. {
  339. unsigned char randout[1024];
  340. TEST_ENT t;
  341. size_t i;
  342. unsigned int reseed_counter_tmp;
  343. unsigned char *p = (unsigned char *)dctx;
  344. /* Initialise DRBG */
  345. if (!do_drbg_init(dctx, td, &t))
  346. goto err;
  347. /* Don't report induced errors */
  348. dctx->iflags |= DRBG_FLAG_NOERR;
  349. /* Personalisation string tests */
  350. /* Test detection of too large personlisation string */
  351. if (FIPS_drbg_instantiate(dctx, td->pers, dctx->max_pers + 1) > 0)
  352. {
  353. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_PERSONALISATION_ERROR_UNDETECTED);
  354. goto err;
  355. }
  356. /* Entropy source tests */
  357. /* Test entropy source failure detecion: i.e. returns no data */
  358. t.entlen = 0;
  359. if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0)
  360. {
  361. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
  362. goto err;
  363. }
  364. /* Try to generate output from uninstantiated DRBG */
  365. if (FIPS_drbg_generate(dctx, randout, td->katlen, 0,
  366. td->adin, td->adinlen))
  367. {
  368. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_GENERATE_ERROR_UNDETECTED);
  369. goto err;
  370. }
  371. dctx->iflags &= ~DRBG_FLAG_NOERR;
  372. if (!FIPS_drbg_uninstantiate(dctx))
  373. {
  374. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
  375. goto err;
  376. }
  377. if (!do_drbg_init(dctx, td, &t))
  378. goto err;
  379. dctx->iflags |= DRBG_FLAG_NOERR;
  380. /* Test insufficient entropy */
  381. t.entlen = dctx->min_entropy - 1;
  382. if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0)
  383. {
  384. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
  385. goto err;
  386. }
  387. dctx->iflags &= ~DRBG_FLAG_NOERR;
  388. if (!FIPS_drbg_uninstantiate(dctx))
  389. {
  390. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
  391. goto err;
  392. }
  393. /* Test too much entropy */
  394. if (!do_drbg_init(dctx, td, &t))
  395. goto err;
  396. dctx->iflags |= DRBG_FLAG_NOERR;
  397. t.entlen = dctx->max_entropy + 1;
  398. if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0)
  399. {
  400. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
  401. goto err;
  402. }
  403. dctx->iflags &= ~DRBG_FLAG_NOERR;
  404. if (!FIPS_drbg_uninstantiate(dctx))
  405. {
  406. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
  407. goto err;
  408. }
  409. /* Nonce tests */
  410. /* Test too small nonce */
  411. if (dctx->min_nonce)
  412. {
  413. if (!do_drbg_init(dctx, td, &t))
  414. goto err;
  415. dctx->iflags |= DRBG_FLAG_NOERR;
  416. t.noncelen = dctx->min_nonce - 1;
  417. if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0)
  418. {
  419. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_NONCE_ERROR_UNDETECTED);
  420. goto err;
  421. }
  422. dctx->iflags &= ~DRBG_FLAG_NOERR;
  423. if (!FIPS_drbg_uninstantiate(dctx))
  424. {
  425. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
  426. goto err;
  427. }
  428. }
  429. /* Test too large nonce */
  430. if (dctx->max_nonce)
  431. {
  432. if (!do_drbg_init(dctx, td, &t))
  433. goto err;
  434. dctx->iflags |= DRBG_FLAG_NOERR;
  435. t.noncelen = dctx->max_nonce + 1;
  436. if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0)
  437. {
  438. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_NONCE_ERROR_UNDETECTED);
  439. goto err;
  440. }
  441. dctx->iflags &= ~DRBG_FLAG_NOERR;
  442. if (!FIPS_drbg_uninstantiate(dctx))
  443. {
  444. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
  445. goto err;
  446. }
  447. }
  448. /* Instantiate with valid data. */
  449. if (!do_drbg_instantiate(dctx, td, &t))
  450. goto err;
  451. /* Check generation is now OK */
  452. if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0,
  453. td->adin, td->adinlen))
  454. goto err;
  455. dctx->iflags |= DRBG_FLAG_NOERR;
  456. /* Request too much data for one request */
  457. if (FIPS_drbg_generate(dctx, randout, dctx->max_request + 1, 0,
  458. td->adin, td->adinlen))
  459. {
  460. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_REQUEST_LENGTH_ERROR_UNDETECTED);
  461. goto err;
  462. }
  463. /* Try too large additional input */
  464. if (FIPS_drbg_generate(dctx, randout, td->katlen, 0,
  465. td->adin, dctx->max_adin + 1))
  466. {
  467. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ADDITIONAL_INPUT_ERROR_UNDETECTED);
  468. goto err;
  469. }
  470. /* Check prediction resistance request fails if entropy source
  471. * failure.
  472. */
  473. t.entlen = 0;
  474. if (FIPS_drbg_generate(dctx, randout, td->katlen, 1,
  475. td->adin, td->adinlen))
  476. {
  477. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
  478. goto err;
  479. }
  480. dctx->iflags &= ~DRBG_FLAG_NOERR;
  481. if (!FIPS_drbg_uninstantiate(dctx))
  482. {
  483. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
  484. goto err;
  485. }
  486. /* Instantiate again with valid data */
  487. if (!do_drbg_instantiate(dctx, td, &t))
  488. goto err;
  489. /* Test reseed counter works */
  490. /* Save initial reseed counter */
  491. reseed_counter_tmp = dctx->reseed_counter;
  492. /* Set reseed counter to beyond interval */
  493. dctx->reseed_counter = dctx->reseed_interval;
  494. /* Generate output and check entropy has been requested for reseed */
  495. t.entcnt = 0;
  496. if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0,
  497. td->adin, td->adinlen))
  498. goto err;
  499. if (t.entcnt != 1)
  500. {
  501. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED);
  502. goto err;
  503. }
  504. /* Check reseed counter has been reset */
  505. if (dctx->reseed_counter != reseed_counter_tmp + 1)
  506. {
  507. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_RESEED_COUNTER_ERROR);
  508. goto err;
  509. }
  510. /* Explicit reseed tests */
  511. /* Test explicit reseed with too large additional input */
  512. if (!do_drbg_init(dctx, td, &t))
  513. goto err;
  514. dctx->iflags |= DRBG_FLAG_NOERR;
  515. if (FIPS_drbg_reseed(dctx, td->adin, dctx->max_adin + 1) > 0)
  516. {
  517. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ADDITIONAL_INPUT_ERROR_UNDETECTED);
  518. goto err;
  519. }
  520. /* Test explicit reseed with entropy source failure */
  521. /* Check prediction resistance request fails if entropy source
  522. * failure.
  523. */
  524. t.entlen = 0;
  525. if (FIPS_drbg_generate(dctx, randout, td->katlen, 1,
  526. td->adin, td->adinlen))
  527. {
  528. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
  529. goto err;
  530. }
  531. dctx->iflags &= ~DRBG_FLAG_NOERR;
  532. if (!FIPS_drbg_uninstantiate(dctx))
  533. {
  534. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
  535. goto err;
  536. }
  537. if (!do_drbg_instantiate(dctx, td, &t))
  538. goto err;
  539. /* Test reseed counter works */
  540. /* Save initial reseed counter */
  541. reseed_counter_tmp = dctx->reseed_counter;
  542. /* Set reseed counter to beyond interval */
  543. dctx->reseed_counter = dctx->reseed_interval;
  544. /* Generate output and check entropy has been requested for reseed */
  545. t.entcnt = 0;
  546. if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0,
  547. td->adin, td->adinlen))
  548. goto err;
  549. if (t.entcnt != 1)
  550. {
  551. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED);
  552. goto err;
  553. }
  554. /* Check reseed counter has been reset */
  555. if (dctx->reseed_counter != reseed_counter_tmp + 1)
  556. {
  557. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_RESEED_COUNTER_ERROR);
  558. goto err;
  559. }
  560. /* Explicit reseed tests */
  561. /* Test explicit reseed with too large additional input */
  562. if (!do_drbg_init(dctx, td, &t))
  563. goto err;
  564. dctx->iflags |= DRBG_FLAG_NOERR;
  565. if (FIPS_drbg_reseed(dctx, td->adin, dctx->max_adin + 1) > 0)
  566. {
  567. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ADDITIONAL_INPUT_ERROR_UNDETECTED);
  568. goto err;
  569. }
  570. /* Test explicit reseed with entropy source failure */
  571. if (!do_drbg_init(dctx, td, &t))
  572. goto err;
  573. dctx->iflags |= DRBG_FLAG_NOERR;
  574. t.entlen = 0;
  575. if (FIPS_drbg_reseed(dctx, td->adin, td->adinlen) > 0)
  576. {
  577. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
  578. goto err;
  579. }
  580. if (!FIPS_drbg_uninstantiate(dctx))
  581. {
  582. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
  583. goto err;
  584. }
  585. /* Test explicit reseed with too much entropy */
  586. if (!do_drbg_init(dctx, td, &t))
  587. goto err;
  588. dctx->iflags |= DRBG_FLAG_NOERR;
  589. t.entlen = dctx->max_entropy + 1;
  590. if (FIPS_drbg_reseed(dctx, td->adin, td->adinlen) > 0)
  591. {
  592. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
  593. goto err;
  594. }
  595. if (!FIPS_drbg_uninstantiate(dctx))
  596. {
  597. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
  598. goto err;
  599. }
  600. /* Test explicit reseed with too little entropy */
  601. if (!do_drbg_init(dctx, td, &t))
  602. goto err;
  603. dctx->iflags |= DRBG_FLAG_NOERR;
  604. t.entlen = dctx->min_entropy - 1;
  605. if (FIPS_drbg_reseed(dctx, td->adin, td->adinlen) > 0)
  606. {
  607. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
  608. goto err;
  609. }
  610. if (!FIPS_drbg_uninstantiate(dctx))
  611. {
  612. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR);
  613. goto err;
  614. }
  615. p = (unsigned char *)&dctx->d;
  616. /* Standard says we have to check uninstantiate really zeroes
  617. * the data...
  618. */
  619. for (i = 0; i < sizeof(dctx->d); i++)
  620. {
  621. if (*p != 0)
  622. {
  623. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ZEROISE_ERROR);
  624. goto err;
  625. }
  626. p++;
  627. }
  628. return 1;
  629. err:
  630. /* A real error as opposed to an induced one: underlying function will
  631. * indicate the error.
  632. */
  633. if (!(dctx->iflags & DRBG_FLAG_NOERR))
  634. FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_FUNCTION_ERROR);
  635. FIPS_drbg_uninstantiate(dctx);
  636. return 0;
  637. }
  638. int fips_drbg_kat(DRBG_CTX *dctx, int nid, unsigned int flags)
  639. {
  640. DRBG_SELFTEST_DATA *td;
  641. flags |= DRBG_FLAG_TEST;
  642. for (td = drbg_test; td->nid != 0; td++)
  643. {
  644. if (td->nid == nid && td->flags == flags)
  645. {
  646. if (!fips_drbg_single_kat(dctx, td, 0))
  647. return 0;
  648. return fips_drbg_error_check(dctx, td);
  649. }
  650. }
  651. return 0;
  652. }
  653. int FIPS_drbg_health_check(DRBG_CTX *dctx)
  654. {
  655. int rv;
  656. DRBG_CTX *tctx = NULL;
  657. tctx = FIPS_drbg_new(0, 0);
  658. fips_post_started(FIPS_TEST_DRBG, dctx->type, &dctx->xflags);
  659. if (!tctx)
  660. return 0;
  661. rv = fips_drbg_kat(tctx, dctx->type, dctx->xflags);
  662. if (tctx)
  663. FIPS_drbg_free(tctx);
  664. if (rv)
  665. fips_post_success(FIPS_TEST_DRBG, dctx->type, &dctx->xflags);
  666. else
  667. fips_post_failed(FIPS_TEST_DRBG, dctx->type, &dctx->xflags);
  668. if (!rv)
  669. dctx->status = DRBG_STATUS_ERROR;
  670. else
  671. dctx->health_check_cnt = 0;
  672. return rv;
  673. }
  674. int FIPS_selftest_drbg(void)
  675. {
  676. DRBG_CTX *dctx;
  677. DRBG_SELFTEST_DATA *td;
  678. int rv = 1;
  679. dctx = FIPS_drbg_new(0, 0);
  680. if (!dctx)
  681. return 0;
  682. for (td = drbg_test; td->nid != 0; td++)
  683. {
  684. if (td->post != 1)
  685. continue;
  686. if (!fips_post_started(FIPS_TEST_DRBG, td->nid, &td->flags))
  687. return 1;
  688. if (!fips_drbg_single_kat(dctx, td, 1))
  689. {
  690. fips_post_failed(FIPS_TEST_DRBG, td->nid, &td->flags);
  691. rv = 0;
  692. continue;
  693. }
  694. if (!fips_post_success(FIPS_TEST_DRBG, td->nid, &td->flags))
  695. return 0;
  696. }
  697. FIPS_drbg_free(dctx);
  698. return rv;
  699. }
  700. int FIPS_selftest_drbg_all(void)
  701. {
  702. DRBG_CTX *dctx;
  703. DRBG_SELFTEST_DATA *td;
  704. int rv = 1;
  705. dctx = FIPS_drbg_new(0, 0);
  706. if (!dctx)
  707. return 0;
  708. for (td = drbg_test; td->nid != 0; td++)
  709. {
  710. if (!fips_post_started(FIPS_TEST_DRBG, td->nid, &td->flags))
  711. return 1;
  712. if (!fips_drbg_single_kat(dctx, td, 0))
  713. {
  714. fips_post_failed(FIPS_TEST_DRBG, td->nid, &td->flags);
  715. rv = 0;
  716. continue;
  717. }
  718. if (!fips_drbg_error_check(dctx, td))
  719. {
  720. fips_post_failed(FIPS_TEST_DRBG, td->nid, &td->flags);
  721. rv = 0;
  722. continue;
  723. }
  724. if (!fips_post_success(FIPS_TEST_DRBG, td->nid, &td->flags))
  725. return 0;
  726. }
  727. FIPS_drbg_free(dctx);
  728. return rv;
  729. }