fipsinstall.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. /*
  2. * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include <string.h>
  10. #include <openssl/evp.h>
  11. #include <openssl/err.h>
  12. #include <openssl/provider.h>
  13. #include <openssl/params.h>
  14. #include <openssl/fips_names.h>
  15. #include <openssl/core_names.h>
  16. #include <openssl/self_test.h>
  17. #include "apps.h"
  18. #include "progs.h"
  19. DEFINE_STACK_OF_STRING()
  20. #define BUFSIZE 4096
  21. #define DEFAULT_MAC_NAME "HMAC"
  22. #define DEFAULT_FIPS_SECTION "fips_check_section"
  23. /* Configuration file values */
  24. #define VERSION_KEY "version"
  25. #define VERSION_VAL "1"
  26. #define INSTALL_STATUS_VAL "INSTALL_SELF_TEST_KATS_RUN"
  27. static OSSL_CALLBACK self_test_events;
  28. static char *self_test_corrupt_desc = NULL;
  29. static char *self_test_corrupt_type = NULL;
  30. static int self_test_log = 1;
  31. static int quiet = 0;
  32. typedef enum OPTION_choice {
  33. OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
  34. OPT_IN, OPT_OUT, OPT_MODULE,
  35. OPT_PROV_NAME, OPT_SECTION_NAME, OPT_MAC_NAME, OPT_MACOPT, OPT_VERIFY,
  36. OPT_NO_LOG, OPT_CORRUPT_DESC, OPT_CORRUPT_TYPE, OPT_QUIET
  37. } OPTION_CHOICE;
  38. const OPTIONS fipsinstall_options[] = {
  39. OPT_SECTION("General"),
  40. {"help", OPT_HELP, '-', "Display this summary"},
  41. {"verify", OPT_VERIFY, '-',
  42. "Verify a config file instead of generating one"},
  43. {"module", OPT_MODULE, '<', "File name of the provider module"},
  44. {"provider_name", OPT_PROV_NAME, 's', "FIPS provider name"},
  45. {"section_name", OPT_SECTION_NAME, 's',
  46. "FIPS Provider config section name (optional)"},
  47. OPT_SECTION("Input"),
  48. {"in", OPT_IN, '<', "Input config file, used when verifying"},
  49. OPT_SECTION("Output"),
  50. {"out", OPT_OUT, '>', "Output config file, used when generating"},
  51. {"mac_name", OPT_MAC_NAME, 's', "MAC name"},
  52. {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form. "
  53. "See 'PARAMETER NAMES' in the EVP_MAC_ docs"},
  54. {"noout", OPT_NO_LOG, '-', "Disable logging of self test events"},
  55. {"corrupt_desc", OPT_CORRUPT_DESC, 's', "Corrupt a self test by description"},
  56. {"corrupt_type", OPT_CORRUPT_TYPE, 's', "Corrupt a self test by type"},
  57. {"quiet", OPT_QUIET, '-', "No messages, just exit status"},
  58. {NULL}
  59. };
  60. static int do_mac(EVP_MAC_CTX *ctx, unsigned char *tmp, BIO *in,
  61. unsigned char *out, size_t *out_len)
  62. {
  63. int ret = 0;
  64. int i;
  65. size_t outsz = *out_len;
  66. if (!EVP_MAC_init(ctx))
  67. goto err;
  68. if (EVP_MAC_size(ctx) > outsz)
  69. goto end;
  70. while ((i = BIO_read(in, (char *)tmp, BUFSIZE)) != 0) {
  71. if (i < 0 || !EVP_MAC_update(ctx, tmp, i))
  72. goto err;
  73. }
  74. end:
  75. if (!EVP_MAC_final(ctx, out, out_len, outsz))
  76. goto err;
  77. ret = 1;
  78. err:
  79. return ret;
  80. }
  81. static int load_fips_prov_and_run_self_test(const char *prov_name)
  82. {
  83. int ret = 0;
  84. OSSL_PROVIDER *prov = NULL;
  85. prov = OSSL_PROVIDER_load(NULL, prov_name);
  86. if (prov == NULL) {
  87. BIO_printf(bio_err, "Failed to load FIPS module\n");
  88. goto end;
  89. }
  90. ret = 1;
  91. end:
  92. OSSL_PROVIDER_unload(prov);
  93. return ret;
  94. }
  95. static int print_mac(BIO *bio, const char *label, const unsigned char *mac,
  96. size_t len)
  97. {
  98. int ret;
  99. char *hexstr = NULL;
  100. hexstr = OPENSSL_buf2hexstr(mac, (long)len);
  101. if (hexstr == NULL)
  102. return 0;
  103. ret = BIO_printf(bio, "%s = %s\n", label, hexstr);
  104. OPENSSL_free(hexstr);
  105. return ret;
  106. }
  107. static int write_config_header(BIO *out, const char *prov_name,
  108. const char *section)
  109. {
  110. return BIO_printf(out, "openssl_conf = openssl_init\n\n")
  111. && BIO_printf(out, "[openssl_init]\n")
  112. && BIO_printf(out, "providers = provider_section\n\n")
  113. && BIO_printf(out, "[provider_section]\n")
  114. && BIO_printf(out, "%s = %s\n\n", prov_name, section);
  115. }
  116. /*
  117. * Outputs a fips related config file that contains entries for the fips
  118. * module checksum and the installation indicator checksum.
  119. *
  120. * Returns 1 if the config file is written otherwise it returns 0 on error.
  121. */
  122. static int write_config_fips_section(BIO *out, const char *section,
  123. unsigned char *module_mac,
  124. size_t module_mac_len,
  125. unsigned char *install_mac,
  126. size_t install_mac_len)
  127. {
  128. int ret = 0;
  129. if (!(BIO_printf(out, "[%s]\n", section) > 0
  130. && BIO_printf(out, "activate = 1\n") > 0
  131. && BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_VERSION,
  132. VERSION_VAL) > 0
  133. && print_mac(out, OSSL_PROV_FIPS_PARAM_MODULE_MAC, module_mac,
  134. module_mac_len)))
  135. goto end;
  136. if (install_mac != NULL) {
  137. if (!(print_mac(out, OSSL_PROV_FIPS_PARAM_INSTALL_MAC, install_mac,
  138. install_mac_len)
  139. && BIO_printf(out, "%s = %s\n",
  140. OSSL_PROV_FIPS_PARAM_INSTALL_STATUS,
  141. INSTALL_STATUS_VAL) > 0))
  142. goto end;
  143. }
  144. ret = 1;
  145. end:
  146. return ret;
  147. }
  148. static CONF *generate_config_and_load(const char *prov_name,
  149. const char *section,
  150. unsigned char *module_mac,
  151. size_t module_mac_len)
  152. {
  153. BIO *mem_bio = NULL;
  154. CONF *conf = NULL;
  155. mem_bio = BIO_new(BIO_s_mem());
  156. if (mem_bio == NULL)
  157. return 0;
  158. if (!write_config_header(mem_bio, prov_name, section)
  159. || !write_config_fips_section(mem_bio, section, module_mac,
  160. module_mac_len, NULL, 0))
  161. goto end;
  162. conf = app_load_config_bio(mem_bio, NULL);
  163. if (conf == NULL)
  164. goto end;
  165. if (CONF_modules_load(conf, NULL, 0) <= 0)
  166. goto end;
  167. BIO_free(mem_bio);
  168. return conf;
  169. end:
  170. NCONF_free(conf);
  171. BIO_free(mem_bio);
  172. return NULL;
  173. }
  174. static void free_config_and_unload(CONF *conf)
  175. {
  176. if (conf != NULL) {
  177. NCONF_free(conf);
  178. CONF_modules_unload(1);
  179. }
  180. }
  181. /*
  182. * Returns 1 if the config file entries match the passed in module_mac and
  183. * install_mac values, otherwise it returns 0.
  184. */
  185. static int verify_config(const char *infile, const char *section,
  186. unsigned char *module_mac, size_t module_mac_len,
  187. unsigned char *install_mac, size_t install_mac_len)
  188. {
  189. int ret = 0;
  190. char *s = NULL;
  191. unsigned char *buf1 = NULL, *buf2 = NULL;
  192. long len;
  193. CONF *conf = NULL;
  194. /* read in the existing values and check they match the saved values */
  195. conf = app_load_config(infile);
  196. if (conf == NULL)
  197. goto end;
  198. s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_VERSION);
  199. if (s == NULL || strcmp(s, VERSION_VAL) != 0) {
  200. BIO_printf(bio_err, "version not found\n");
  201. goto end;
  202. }
  203. s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_STATUS);
  204. if (s == NULL || strcmp(s, INSTALL_STATUS_VAL) != 0) {
  205. BIO_printf(bio_err, "install status not found\n");
  206. goto end;
  207. }
  208. s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_MODULE_MAC);
  209. if (s == NULL) {
  210. BIO_printf(bio_err, "Module integrity MAC not found\n");
  211. goto end;
  212. }
  213. buf1 = OPENSSL_hexstr2buf(s, &len);
  214. if (buf1 == NULL
  215. || (size_t)len != module_mac_len
  216. || memcmp(module_mac, buf1, module_mac_len) != 0) {
  217. BIO_printf(bio_err, "Module integrity mismatch\n");
  218. goto end;
  219. }
  220. s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_MAC);
  221. if (s == NULL) {
  222. BIO_printf(bio_err, "Install indicator MAC not found\n");
  223. goto end;
  224. }
  225. buf2 = OPENSSL_hexstr2buf(s, &len);
  226. if (buf2 == NULL
  227. || (size_t)len != install_mac_len
  228. || memcmp(install_mac, buf2, install_mac_len) != 0) {
  229. BIO_printf(bio_err, "Install indicator status mismatch\n");
  230. goto end;
  231. }
  232. ret = 1;
  233. end:
  234. OPENSSL_free(buf1);
  235. OPENSSL_free(buf2);
  236. NCONF_free(conf);
  237. return ret;
  238. }
  239. int fipsinstall_main(int argc, char **argv)
  240. {
  241. int ret = 1, verify = 0;
  242. BIO *module_bio = NULL, *mem_bio = NULL, *fout = NULL;
  243. char *in_fname = NULL, *out_fname = NULL, *prog, *section_name = NULL;
  244. char *prov_name = NULL, *module_fname = NULL;
  245. static const char *mac_name = DEFAULT_MAC_NAME;
  246. EVP_MAC_CTX *ctx = NULL, *ctx2 = NULL;
  247. STACK_OF(OPENSSL_STRING) *opts = NULL;
  248. OPTION_CHOICE o;
  249. unsigned char *read_buffer = NULL;
  250. unsigned char module_mac[EVP_MAX_MD_SIZE];
  251. size_t module_mac_len = EVP_MAX_MD_SIZE;
  252. unsigned char install_mac[EVP_MAX_MD_SIZE];
  253. size_t install_mac_len = EVP_MAX_MD_SIZE;
  254. EVP_MAC *mac = NULL;
  255. CONF *conf = NULL;
  256. section_name = DEFAULT_FIPS_SECTION;
  257. prog = opt_init(argc, argv, fipsinstall_options);
  258. while ((o = opt_next()) != OPT_EOF) {
  259. switch (o) {
  260. case OPT_EOF:
  261. case OPT_ERR:
  262. opthelp:
  263. BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
  264. goto cleanup;
  265. case OPT_HELP:
  266. opt_help(fipsinstall_options);
  267. ret = 0;
  268. goto end;
  269. case OPT_IN:
  270. in_fname = opt_arg();
  271. break;
  272. case OPT_OUT:
  273. out_fname = opt_arg();
  274. break;
  275. case OPT_QUIET:
  276. quiet = 1;
  277. /* FALLTHROUGH */
  278. case OPT_NO_LOG:
  279. self_test_log = 0;
  280. break;
  281. case OPT_CORRUPT_DESC:
  282. self_test_corrupt_desc = opt_arg();
  283. break;
  284. case OPT_CORRUPT_TYPE:
  285. self_test_corrupt_type = opt_arg();
  286. break;
  287. case OPT_PROV_NAME:
  288. prov_name = opt_arg();
  289. break;
  290. case OPT_MODULE:
  291. module_fname = opt_arg();
  292. break;
  293. case OPT_SECTION_NAME:
  294. section_name = opt_arg();
  295. break;
  296. case OPT_MAC_NAME:
  297. mac_name = opt_arg();
  298. break;
  299. case OPT_MACOPT:
  300. if (opts == NULL)
  301. opts = sk_OPENSSL_STRING_new_null();
  302. if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg()))
  303. goto opthelp;
  304. break;
  305. case OPT_VERIFY:
  306. verify = 1;
  307. break;
  308. }
  309. }
  310. argc = opt_num_rest();
  311. if (module_fname == NULL
  312. || (verify && in_fname == NULL)
  313. || (!verify && (out_fname == NULL || prov_name == NULL))
  314. || opts == NULL
  315. || argc != 0)
  316. goto opthelp;
  317. if (self_test_log
  318. || self_test_corrupt_desc != NULL
  319. || self_test_corrupt_type != NULL)
  320. OSSL_SELF_TEST_set_callback(NULL, self_test_events, NULL);
  321. module_bio = bio_open_default(module_fname, 'r', FORMAT_BINARY);
  322. if (module_bio == NULL) {
  323. BIO_printf(bio_err, "Failed to open module file\n");
  324. goto end;
  325. }
  326. read_buffer = app_malloc(BUFSIZE, "I/O buffer");
  327. if (read_buffer == NULL)
  328. goto end;
  329. mac = EVP_MAC_fetch(NULL, mac_name, NULL);
  330. if (mac == NULL) {
  331. BIO_printf(bio_err, "Unable to get MAC of type %s\n", mac_name);
  332. goto end;
  333. }
  334. ctx = EVP_MAC_CTX_new(mac);
  335. if (ctx == NULL) {
  336. BIO_printf(bio_err, "Unable to create MAC CTX for module check\n");
  337. goto end;
  338. }
  339. if (opts != NULL) {
  340. int ok = 1;
  341. OSSL_PARAM *params =
  342. app_params_new_from_opts(opts, EVP_MAC_settable_ctx_params(mac));
  343. if (params == NULL)
  344. goto end;
  345. if (!EVP_MAC_CTX_set_params(ctx, params)) {
  346. BIO_printf(bio_err, "MAC parameter error\n");
  347. ERR_print_errors(bio_err);
  348. ok = 0;
  349. }
  350. app_params_free(params);
  351. if (!ok)
  352. goto end;
  353. }
  354. ctx2 = EVP_MAC_CTX_dup(ctx);
  355. if (ctx2 == NULL) {
  356. BIO_printf(bio_err, "Unable to create MAC CTX for install indicator\n");
  357. goto end;
  358. }
  359. if (!do_mac(ctx, read_buffer, module_bio, module_mac, &module_mac_len))
  360. goto end;
  361. mem_bio = BIO_new_mem_buf((const void *)INSTALL_STATUS_VAL,
  362. strlen(INSTALL_STATUS_VAL));
  363. if (mem_bio == NULL) {
  364. BIO_printf(bio_err, "Unable to create memory BIO\n");
  365. goto end;
  366. }
  367. if (!do_mac(ctx2, read_buffer, mem_bio, install_mac, &install_mac_len))
  368. goto end;
  369. if (verify) {
  370. if (!verify_config(in_fname, section_name, module_mac, module_mac_len,
  371. install_mac, install_mac_len))
  372. goto end;
  373. if (!quiet)
  374. BIO_printf(bio_out, "VERIFY PASSED\n");
  375. } else {
  376. conf = generate_config_and_load(prov_name, section_name, module_mac,
  377. module_mac_len);
  378. if (conf == NULL)
  379. goto end;
  380. if (!load_fips_prov_and_run_self_test(prov_name))
  381. goto end;
  382. fout = bio_open_default(out_fname, 'w', FORMAT_TEXT);
  383. if (fout == NULL) {
  384. BIO_printf(bio_err, "Failed to open file\n");
  385. goto end;
  386. }
  387. if (!write_config_fips_section(fout, section_name, module_mac,
  388. module_mac_len, install_mac,
  389. install_mac_len))
  390. goto end;
  391. if (!quiet)
  392. BIO_printf(bio_out, "INSTALL PASSED\n");
  393. }
  394. ret = 0;
  395. end:
  396. if (ret == 1) {
  397. if (!quiet)
  398. BIO_printf(bio_err, "%s FAILED\n", verify ? "VERIFY" : "INSTALL");
  399. ERR_print_errors(bio_err);
  400. }
  401. cleanup:
  402. BIO_free(fout);
  403. BIO_free(mem_bio);
  404. BIO_free(module_bio);
  405. sk_OPENSSL_STRING_free(opts);
  406. EVP_MAC_free(mac);
  407. EVP_MAC_CTX_free(ctx2);
  408. EVP_MAC_CTX_free(ctx);
  409. OPENSSL_free(read_buffer);
  410. free_config_and_unload(conf);
  411. return ret;
  412. }
  413. static int self_test_events(const OSSL_PARAM params[], void *arg)
  414. {
  415. const OSSL_PARAM *p = NULL;
  416. const char *phase = NULL, *type = NULL, *desc = NULL;
  417. int ret = 0;
  418. p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_PHASE);
  419. if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
  420. goto err;
  421. phase = (const char *)p->data;
  422. p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_DESC);
  423. if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
  424. goto err;
  425. desc = (const char *)p->data;
  426. p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_TYPE);
  427. if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
  428. goto err;
  429. type = (const char *)p->data;
  430. if (self_test_log) {
  431. if (strcmp(phase, OSSL_SELF_TEST_PHASE_START) == 0)
  432. BIO_printf(bio_out, "%s : (%s) : ", desc, type);
  433. else if (strcmp(phase, OSSL_SELF_TEST_PHASE_PASS) == 0
  434. || strcmp(phase, OSSL_SELF_TEST_PHASE_FAIL) == 0)
  435. BIO_printf(bio_out, "%s\n", phase);
  436. }
  437. /*
  438. * The self test code will internally corrupt the KAT test result if an
  439. * error is returned during the corrupt phase.
  440. */
  441. if (strcmp(phase, OSSL_SELF_TEST_PHASE_CORRUPT) == 0
  442. && (self_test_corrupt_desc != NULL
  443. || self_test_corrupt_type != NULL)) {
  444. if (self_test_corrupt_desc != NULL
  445. && strcmp(self_test_corrupt_desc, desc) != 0)
  446. goto end;
  447. if (self_test_corrupt_type != NULL
  448. && strcmp(self_test_corrupt_type, type) != 0)
  449. goto end;
  450. BIO_printf(bio_out, "%s ", phase);
  451. goto err;
  452. }
  453. end:
  454. ret = 1;
  455. err:
  456. return ret;
  457. }