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