1 /* 2 * Copyright 2019-2021 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 10 #include <string.h> 11 #include <openssl/evp.h> 12 #include <openssl/err.h> 13 #include <openssl/provider.h> 14 #include <openssl/params.h> 15 #include <openssl/fips_names.h> 16 #include <openssl/core_names.h> 17 #include <openssl/self_test.h> 18 #include <openssl/fipskey.h> 19 #include "apps.h" 20 #include "progs.h" 21 22 #define BUFSIZE 4096 23 24 /* Configuration file values */ 25 #define VERSION_KEY "version" 26 #define VERSION_VAL "1" 27 #define INSTALL_STATUS_VAL "INSTALL_SELF_TEST_KATS_RUN" 28 29 static OSSL_CALLBACK self_test_events; 30 static char *self_test_corrupt_desc = NULL; 31 static char *self_test_corrupt_type = NULL; 32 static int self_test_log = 1; 33 static int quiet = 0; 34 35 typedef enum OPTION_choice { 36 OPT_COMMON, 37 OPT_IN, OPT_OUT, OPT_MODULE, 38 OPT_PROV_NAME, OPT_SECTION_NAME, OPT_MAC_NAME, OPT_MACOPT, OPT_VERIFY, 39 OPT_NO_LOG, OPT_CORRUPT_DESC, OPT_CORRUPT_TYPE, OPT_QUIET, OPT_CONFIG, 40 OPT_NO_CONDITIONAL_ERRORS, 41 OPT_NO_SECURITY_CHECKS, 42 OPT_SELF_TEST_ONLOAD 43 } OPTION_CHOICE; 44 45 const OPTIONS fipsinstall_options[] = { 46 OPT_SECTION("General"), 47 {"help", OPT_HELP, '-', "Display this summary"}, 48 {"verify", OPT_VERIFY, '-', 49 "Verify a config file instead of generating one"}, 50 {"module", OPT_MODULE, '<', "File name of the provider module"}, 51 {"provider_name", OPT_PROV_NAME, 's', "FIPS provider name"}, 52 {"section_name", OPT_SECTION_NAME, 's', 53 "FIPS Provider config section name (optional)"}, 54 {"no_conditional_errors", OPT_NO_CONDITIONAL_ERRORS, '-', 55 "Disable the ability of the fips module to enter an error state if" 56 " any conditional self tests fail"}, 57 {"no_security_checks", OPT_NO_SECURITY_CHECKS, '-', 58 "Disable the run-time FIPS security checks in the module"}, 59 {"self_test_onload", OPT_SELF_TEST_ONLOAD, '-', 60 "Forces self tests to always run on module load"}, 61 OPT_SECTION("Input"), 62 {"in", OPT_IN, '<', "Input config file, used when verifying"}, 63 64 OPT_SECTION("Output"), 65 {"out", OPT_OUT, '>', "Output config file, used when generating"}, 66 {"mac_name", OPT_MAC_NAME, 's', "MAC name"}, 67 {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form. " 68 "See 'PARAMETER NAMES' in the EVP_MAC_ docs"}, 69 {"noout", OPT_NO_LOG, '-', "Disable logging of self test events"}, 70 {"corrupt_desc", OPT_CORRUPT_DESC, 's', "Corrupt a self test by description"}, 71 {"corrupt_type", OPT_CORRUPT_TYPE, 's', "Corrupt a self test by type"}, 72 {"config", OPT_CONFIG, '<', "The parent config to verify"}, 73 {"quiet", OPT_QUIET, '-', "No messages, just exit status"}, 74 {NULL} 75 }; 76 77 static int do_mac(EVP_MAC_CTX *ctx, unsigned char *tmp, BIO *in, 78 unsigned char *out, size_t *out_len) 79 { 80 int ret = 0; 81 int i; 82 size_t outsz = *out_len; 83 84 if (!EVP_MAC_init(ctx, NULL, 0, NULL)) 85 goto err; 86 if (EVP_MAC_CTX_get_mac_size(ctx) > outsz) 87 goto end; 88 while ((i = BIO_read(in, (char *)tmp, BUFSIZE)) != 0) { 89 if (i < 0 || !EVP_MAC_update(ctx, tmp, i)) 90 goto err; 91 } 92 end: 93 if (!EVP_MAC_final(ctx, out, out_len, outsz)) 94 goto err; 95 ret = 1; 96 err: 97 return ret; 98 } 99 100 static int load_fips_prov_and_run_self_test(const char *prov_name) 101 { 102 int ret = 0; 103 OSSL_PROVIDER *prov = NULL; 104 105 prov = OSSL_PROVIDER_load(NULL, prov_name); 106 if (prov == NULL) { 107 BIO_printf(bio_err, "Failed to load FIPS module\n"); 108 goto end; 109 } 110 ret = 1; 111 end: 112 OSSL_PROVIDER_unload(prov); 113 return ret; 114 } 115 116 static int print_mac(BIO *bio, const char *label, const unsigned char *mac, 117 size_t len) 118 { 119 int ret; 120 char *hexstr = NULL; 121 122 hexstr = OPENSSL_buf2hexstr(mac, (long)len); 123 if (hexstr == NULL) 124 return 0; 125 ret = BIO_printf(bio, "%s = %s\n", label, hexstr); 126 OPENSSL_free(hexstr); 127 return ret; 128 } 129 130 static int write_config_header(BIO *out, const char *prov_name, 131 const char *section) 132 { 133 return BIO_printf(out, "openssl_conf = openssl_init\n\n") 134 && BIO_printf(out, "[openssl_init]\n") 135 && BIO_printf(out, "providers = provider_section\n\n") 136 && BIO_printf(out, "[provider_section]\n") 137 && BIO_printf(out, "%s = %s\n\n", prov_name, section); 138 } 139 140 /* 141 * Outputs a fips related config file that contains entries for the fips 142 * module checksum, installation indicator checksum and the options 143 * conditional_errors and security_checks. 144 * 145 * Returns 1 if the config file is written otherwise it returns 0 on error. 146 */ 147 static int write_config_fips_section(BIO *out, const char *section, 148 unsigned char *module_mac, 149 size_t module_mac_len, 150 int conditional_errors, 151 int security_checks, 152 unsigned char *install_mac, 153 size_t install_mac_len) 154 { 155 int ret = 0; 156 157 if (BIO_printf(out, "[%s]\n", section) <= 0 158 || BIO_printf(out, "activate = 1\n") <= 0 159 || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_VERSION, 160 VERSION_VAL) <= 0 161 || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS, 162 conditional_errors ? "1" : "0") <= 0 163 || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS, 164 security_checks ? "1" : "0") <= 0 165 || !print_mac(out, OSSL_PROV_FIPS_PARAM_MODULE_MAC, module_mac, 166 module_mac_len)) 167 goto end; 168 169 if (install_mac != NULL && install_mac_len > 0) { 170 if (!print_mac(out, OSSL_PROV_FIPS_PARAM_INSTALL_MAC, install_mac, 171 install_mac_len) 172 || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_STATUS, 173 INSTALL_STATUS_VAL) <= 0) 174 goto end; 175 } 176 ret = 1; 177 end: 178 return ret; 179 } 180 181 static CONF *generate_config_and_load(const char *prov_name, 182 const char *section, 183 unsigned char *module_mac, 184 size_t module_mac_len, 185 int conditional_errors, 186 int security_checks) 187 { 188 BIO *mem_bio = NULL; 189 CONF *conf = NULL; 190 191 mem_bio = BIO_new(BIO_s_mem()); 192 if (mem_bio == NULL) 193 return 0; 194 if (!write_config_header(mem_bio, prov_name, section) 195 || !write_config_fips_section(mem_bio, section, 196 module_mac, module_mac_len, 197 conditional_errors, 198 security_checks, 199 NULL, 0)) 200 goto end; 201 202 conf = app_load_config_bio(mem_bio, NULL); 203 if (conf == NULL) 204 goto end; 205 206 if (CONF_modules_load(conf, NULL, 0) <= 0) 207 goto end; 208 BIO_free(mem_bio); 209 return conf; 210 end: 211 NCONF_free(conf); 212 BIO_free(mem_bio); 213 return NULL; 214 } 215 216 static void free_config_and_unload(CONF *conf) 217 { 218 if (conf != NULL) { 219 NCONF_free(conf); 220 CONF_modules_unload(1); 221 } 222 } 223 224 static int verify_module_load(const char *parent_config_file) 225 { 226 return OSSL_LIB_CTX_load_config(NULL, parent_config_file); 227 } 228 229 /* 230 * Returns 1 if the config file entries match the passed in module_mac and 231 * install_mac values, otherwise it returns 0. 232 */ 233 static int verify_config(const char *infile, const char *section, 234 unsigned char *module_mac, size_t module_mac_len, 235 unsigned char *install_mac, size_t install_mac_len) 236 { 237 int ret = 0; 238 char *s = NULL; 239 unsigned char *buf1 = NULL, *buf2 = NULL; 240 long len; 241 CONF *conf = NULL; 242 243 /* read in the existing values and check they match the saved values */ 244 conf = app_load_config(infile); 245 if (conf == NULL) 246 goto end; 247 248 s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_VERSION); 249 if (s == NULL || strcmp(s, VERSION_VAL) != 0) { 250 BIO_printf(bio_err, "version not found\n"); 251 goto end; 252 } 253 s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_MODULE_MAC); 254 if (s == NULL) { 255 BIO_printf(bio_err, "Module integrity MAC not found\n"); 256 goto end; 257 } 258 buf1 = OPENSSL_hexstr2buf(s, &len); 259 if (buf1 == NULL 260 || (size_t)len != module_mac_len 261 || memcmp(module_mac, buf1, module_mac_len) != 0) { 262 BIO_printf(bio_err, "Module integrity mismatch\n"); 263 goto end; 264 } 265 if (install_mac != NULL && install_mac_len > 0) { 266 s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_STATUS); 267 if (s == NULL || strcmp(s, INSTALL_STATUS_VAL) != 0) { 268 BIO_printf(bio_err, "install status not found\n"); 269 goto end; 270 } 271 s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_MAC); 272 if (s == NULL) { 273 BIO_printf(bio_err, "Install indicator MAC not found\n"); 274 goto end; 275 } 276 buf2 = OPENSSL_hexstr2buf(s, &len); 277 if (buf2 == NULL 278 || (size_t)len != install_mac_len 279 || memcmp(install_mac, buf2, install_mac_len) != 0) { 280 BIO_printf(bio_err, "Install indicator status mismatch\n"); 281 goto end; 282 } 283 } 284 ret = 1; 285 end: 286 OPENSSL_free(buf1); 287 OPENSSL_free(buf2); 288 NCONF_free(conf); 289 return ret; 290 } 291 292 int fipsinstall_main(int argc, char **argv) 293 { 294 int ret = 1, verify = 0, gotkey = 0, gotdigest = 0, self_test_onload = 0; 295 int enable_conditional_errors = 1, enable_security_checks = 1; 296 const char *section_name = "fips_sect"; 297 const char *mac_name = "HMAC"; 298 const char *prov_name = "fips"; 299 BIO *module_bio = NULL, *mem_bio = NULL, *fout = NULL; 300 char *in_fname = NULL, *out_fname = NULL, *prog; 301 char *module_fname = NULL, *parent_config = NULL, *module_path = NULL; 302 const char *tail; 303 EVP_MAC_CTX *ctx = NULL, *ctx2 = NULL; 304 STACK_OF(OPENSSL_STRING) *opts = NULL; 305 OPTION_CHOICE o; 306 unsigned char *read_buffer = NULL; 307 unsigned char module_mac[EVP_MAX_MD_SIZE]; 308 size_t module_mac_len = EVP_MAX_MD_SIZE; 309 unsigned char install_mac[EVP_MAX_MD_SIZE]; 310 size_t install_mac_len = EVP_MAX_MD_SIZE; 311 EVP_MAC *mac = NULL; 312 CONF *conf = NULL; 313 314 if ((opts = sk_OPENSSL_STRING_new_null()) == NULL) 315 goto end; 316 317 prog = opt_init(argc, argv, fipsinstall_options); 318 while ((o = opt_next()) != OPT_EOF) { 319 switch (o) { 320 case OPT_EOF: 321 case OPT_ERR: 322 opthelp: 323 BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 324 goto cleanup; 325 case OPT_HELP: 326 opt_help(fipsinstall_options); 327 ret = 0; 328 goto end; 329 case OPT_IN: 330 in_fname = opt_arg(); 331 break; 332 case OPT_OUT: 333 out_fname = opt_arg(); 334 break; 335 case OPT_NO_CONDITIONAL_ERRORS: 336 enable_conditional_errors = 0; 337 break; 338 case OPT_NO_SECURITY_CHECKS: 339 enable_security_checks = 0; 340 break; 341 case OPT_QUIET: 342 quiet = 1; 343 /* FALLTHROUGH */ 344 case OPT_NO_LOG: 345 self_test_log = 0; 346 break; 347 case OPT_CORRUPT_DESC: 348 self_test_corrupt_desc = opt_arg(); 349 break; 350 case OPT_CORRUPT_TYPE: 351 self_test_corrupt_type = opt_arg(); 352 break; 353 case OPT_PROV_NAME: 354 prov_name = opt_arg(); 355 break; 356 case OPT_MODULE: 357 module_fname = opt_arg(); 358 break; 359 case OPT_SECTION_NAME: 360 section_name = opt_arg(); 361 break; 362 case OPT_MAC_NAME: 363 mac_name = opt_arg(); 364 break; 365 case OPT_CONFIG: 366 parent_config = opt_arg(); 367 break; 368 case OPT_MACOPT: 369 if (!sk_OPENSSL_STRING_push(opts, opt_arg())) 370 goto opthelp; 371 if (strncmp(opt_arg(), "hexkey:", 7) == 0) 372 gotkey = 1; 373 else if (strncmp(opt_arg(), "digest:", 7) == 0) 374 gotdigest = 1; 375 break; 376 case OPT_VERIFY: 377 verify = 1; 378 break; 379 case OPT_SELF_TEST_ONLOAD: 380 self_test_onload = 1; 381 break; 382 } 383 } 384 385 /* No extra arguments. */ 386 argc = opt_num_rest(); 387 if (argc != 0 || (verify && in_fname == NULL)) 388 goto opthelp; 389 390 if (parent_config != NULL) { 391 /* Test that a parent config can load the module */ 392 if (verify_module_load(parent_config)) { 393 ret = OSSL_PROVIDER_available(NULL, prov_name) ? 0 : 1; 394 if (!quiet) 395 BIO_printf(bio_err, "FIPS provider is %s\n", 396 ret == 0 ? "available" : " not available"); 397 } 398 goto end; 399 } 400 if (module_fname == NULL) 401 goto opthelp; 402 403 tail = opt_path_end(module_fname); 404 if (tail != NULL) { 405 module_path = OPENSSL_strdup(module_fname); 406 if (module_path == NULL) 407 goto end; 408 module_path[tail - module_fname] = '\0'; 409 if (!OSSL_PROVIDER_set_default_search_path(NULL, module_path)) 410 goto end; 411 } 412 413 if (self_test_log 414 || self_test_corrupt_desc != NULL 415 || self_test_corrupt_type != NULL) 416 OSSL_SELF_TEST_set_callback(NULL, self_test_events, NULL); 417 418 /* Use the default FIPS HMAC digest and key if not specified. */ 419 if (!gotdigest && !sk_OPENSSL_STRING_push(opts, "digest:SHA256")) 420 goto end; 421 if (!gotkey && !sk_OPENSSL_STRING_push(opts, "hexkey:" FIPS_KEY_STRING)) 422 goto end; 423 424 module_bio = bio_open_default(module_fname, 'r', FORMAT_BINARY); 425 if (module_bio == NULL) { 426 BIO_printf(bio_err, "Failed to open module file\n"); 427 goto end; 428 } 429 430 read_buffer = app_malloc(BUFSIZE, "I/O buffer"); 431 if (read_buffer == NULL) 432 goto end; 433 434 mac = EVP_MAC_fetch(app_get0_libctx(), mac_name, app_get0_propq()); 435 if (mac == NULL) { 436 BIO_printf(bio_err, "Unable to get MAC of type %s\n", mac_name); 437 goto end; 438 } 439 440 ctx = EVP_MAC_CTX_new(mac); 441 if (ctx == NULL) { 442 BIO_printf(bio_err, "Unable to create MAC CTX for module check\n"); 443 goto end; 444 } 445 446 if (opts != NULL) { 447 int ok = 1; 448 OSSL_PARAM *params = 449 app_params_new_from_opts(opts, EVP_MAC_settable_ctx_params(mac)); 450 451 if (params == NULL) 452 goto end; 453 454 if (!EVP_MAC_CTX_set_params(ctx, params)) { 455 BIO_printf(bio_err, "MAC parameter error\n"); 456 ERR_print_errors(bio_err); 457 ok = 0; 458 } 459 app_params_free(params); 460 if (!ok) 461 goto end; 462 } 463 464 ctx2 = EVP_MAC_CTX_dup(ctx); 465 if (ctx2 == NULL) { 466 BIO_printf(bio_err, "Unable to create MAC CTX for install indicator\n"); 467 goto end; 468 } 469 470 if (!do_mac(ctx, read_buffer, module_bio, module_mac, &module_mac_len)) 471 goto end; 472 473 if (self_test_onload == 0) { 474 mem_bio = BIO_new_mem_buf((const void *)INSTALL_STATUS_VAL, 475 strlen(INSTALL_STATUS_VAL)); 476 if (mem_bio == NULL) { 477 BIO_printf(bio_err, "Unable to create memory BIO\n"); 478 goto end; 479 } 480 if (!do_mac(ctx2, read_buffer, mem_bio, install_mac, &install_mac_len)) 481 goto end; 482 } else { 483 install_mac_len = 0; 484 } 485 486 if (verify) { 487 if (!verify_config(in_fname, section_name, module_mac, module_mac_len, 488 install_mac, install_mac_len)) 489 goto end; 490 if (!quiet) 491 BIO_printf(bio_err, "VERIFY PASSED\n"); 492 } else { 493 494 conf = generate_config_and_load(prov_name, section_name, module_mac, 495 module_mac_len, 496 enable_conditional_errors, 497 enable_security_checks); 498 if (conf == NULL) 499 goto end; 500 if (!load_fips_prov_and_run_self_test(prov_name)) 501 goto end; 502 503 fout = 504 out_fname == NULL ? dup_bio_out(FORMAT_TEXT) 505 : bio_open_default(out_fname, 'w', FORMAT_TEXT); 506 if (fout == NULL) { 507 BIO_printf(bio_err, "Failed to open file\n"); 508 goto end; 509 } 510 if (!write_config_fips_section(fout, section_name, 511 module_mac, module_mac_len, 512 enable_conditional_errors, 513 enable_security_checks, 514 install_mac, install_mac_len)) 515 goto end; 516 if (!quiet) 517 BIO_printf(bio_err, "INSTALL PASSED\n"); 518 } 519 520 ret = 0; 521 end: 522 if (ret == 1) { 523 if (!quiet) 524 BIO_printf(bio_err, "%s FAILED\n", verify ? "VERIFY" : "INSTALL"); 525 ERR_print_errors(bio_err); 526 } 527 528 cleanup: 529 OPENSSL_free(module_path); 530 BIO_free(fout); 531 BIO_free(mem_bio); 532 BIO_free(module_bio); 533 sk_OPENSSL_STRING_free(opts); 534 EVP_MAC_free(mac); 535 EVP_MAC_CTX_free(ctx2); 536 EVP_MAC_CTX_free(ctx); 537 OPENSSL_free(read_buffer); 538 free_config_and_unload(conf); 539 return ret; 540 } 541 542 static int self_test_events(const OSSL_PARAM params[], void *arg) 543 { 544 const OSSL_PARAM *p = NULL; 545 const char *phase = NULL, *type = NULL, *desc = NULL; 546 int ret = 0; 547 548 p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_PHASE); 549 if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING) 550 goto err; 551 phase = (const char *)p->data; 552 553 p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_DESC); 554 if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING) 555 goto err; 556 desc = (const char *)p->data; 557 558 p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_TYPE); 559 if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING) 560 goto err; 561 type = (const char *)p->data; 562 563 if (self_test_log) { 564 if (strcmp(phase, OSSL_SELF_TEST_PHASE_START) == 0) 565 BIO_printf(bio_err, "%s : (%s) : ", desc, type); 566 else if (strcmp(phase, OSSL_SELF_TEST_PHASE_PASS) == 0 567 || strcmp(phase, OSSL_SELF_TEST_PHASE_FAIL) == 0) 568 BIO_printf(bio_err, "%s\n", phase); 569 } 570 /* 571 * The self test code will internally corrupt the KAT test result if an 572 * error is returned during the corrupt phase. 573 */ 574 if (strcmp(phase, OSSL_SELF_TEST_PHASE_CORRUPT) == 0 575 && (self_test_corrupt_desc != NULL 576 || self_test_corrupt_type != NULL)) { 577 if (self_test_corrupt_desc != NULL 578 && strcmp(self_test_corrupt_desc, desc) != 0) 579 goto end; 580 if (self_test_corrupt_type != NULL 581 && strcmp(self_test_corrupt_type, type) != 0) 582 goto end; 583 BIO_printf(bio_err, "%s ", phase); 584 goto err; 585 } 586 end: 587 ret = 1; 588 err: 589 return ret; 590 } 591