Update some nits around the FIPS module
[openssl.git] / apps / fipsinstall.c
index 2aedcbaa6cef324a42962aeba4c014689733b071..157f08b11f182378a70fac7ffb20ed9fe4fdc59d 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -13,6 +13,8 @@
 #include <openssl/provider.h>
 #include <openssl/params.h>
 #include <openssl/fips_names.h>
 #include <openssl/provider.h>
 #include <openssl/params.h>
 #include <openssl/fips_names.h>
+#include <openssl/core_names.h>
+#include <openssl/self_test.h>
 #include "apps.h"
 #include "progs.h"
 
 #include "apps.h"
 #include "progs.h"
 
 #define VERSION_VAL  "1"
 #define INSTALL_STATUS_VAL "INSTALL_SELF_TEST_KATS_RUN"
 
 #define VERSION_VAL  "1"
 #define INSTALL_STATUS_VAL "INSTALL_SELF_TEST_KATS_RUN"
 
+static OSSL_CALLBACK self_test_events;
+static char *self_test_corrupt_desc = NULL;
+static char *self_test_corrupt_type = NULL;
+static int self_test_log = 1;
+static int quiet = 0;
+
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_IN, OPT_OUT, OPT_MODULE,
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_IN, OPT_OUT, OPT_MODULE,
-    OPT_PROV_NAME, OPT_SECTION_NAME, OPT_MAC_NAME, OPT_MACOPT, OPT_VERIFY
+    OPT_PROV_NAME, OPT_SECTION_NAME, OPT_MAC_NAME, OPT_MACOPT, OPT_VERIFY,
+    OPT_NO_LOG, OPT_CORRUPT_DESC, OPT_CORRUPT_TYPE, OPT_QUIET
 } OPTION_CHOICE;
 
 const OPTIONS fipsinstall_options[] = {
 } OPTION_CHOICE;
 
 const OPTIONS fipsinstall_options[] = {
+    OPT_SECTION("General"),
     {"help", OPT_HELP, '-', "Display this summary"},
     {"help", OPT_HELP, '-', "Display this summary"},
-    {OPT_MORE_STR, 0, 0, "e.g: openssl fipsinstall -provider_name fips"
-     "-section_name fipsinstall -out fips.conf -module ./fips.so"
-     "-mac_name HMAC -macopt digest:SHA256 -macopt hexkey:00"},
-    {"verify", OPT_VERIFY, '-', "Verification mode, i.e verify a config file "
-     "instead of generating one"},
-    {"in", OPT_IN, '<', "Input config file, used when verifying"},
-    {"out", OPT_OUT, '>', "Output config file, used when generating"},
+    {"verify", OPT_VERIFY, '-',
+        "Verify a config file instead of generating one"},
     {"module", OPT_MODULE, '<', "File name of the provider module"},
     {"provider_name", OPT_PROV_NAME, 's', "FIPS provider name"},
     {"section_name", OPT_SECTION_NAME, 's',
      "FIPS Provider config section name (optional)"},
     {"module", OPT_MODULE, '<', "File name of the provider module"},
     {"provider_name", OPT_PROV_NAME, 's', "FIPS provider name"},
     {"section_name", OPT_SECTION_NAME, 's',
      "FIPS Provider config section name (optional)"},
+
+    OPT_SECTION("Input"),
+    {"in", OPT_IN, '<', "Input config file, used when verifying"},
+
+    OPT_SECTION("Output"),
+    {"out", OPT_OUT, '>', "Output config file, used when generating"},
     {"mac_name", OPT_MAC_NAME, 's', "MAC name"},
     {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form. "
                                 "See 'PARAMETER NAMES' in the EVP_MAC_ docs"},
     {"mac_name", OPT_MAC_NAME, 's', "MAC name"},
     {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form. "
                                 "See 'PARAMETER NAMES' in the EVP_MAC_ docs"},
+    {"noout", OPT_NO_LOG, '-', "Disable logging of self test events"},
+    {"corrupt_desc", OPT_CORRUPT_DESC, 's', "Corrupt a self test by description"},
+    {"corrupt_type", OPT_CORRUPT_TYPE, 's', "Corrupt a self test by type"},
+    {"quiet", OPT_QUIET, '-', "No messages, just exit status"},
     {NULL}
 };
 
     {NULL}
 };
 
@@ -128,6 +143,7 @@ static int write_config_fips_section(BIO *out, const char *section,
     int ret = 0;
 
     if (!(BIO_printf(out, "[%s]\n", section) > 0
     int ret = 0;
 
     if (!(BIO_printf(out, "[%s]\n", section) > 0
+          && BIO_printf(out, "activate = 1\n") > 0
           && BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_VERSION,
                         VERSION_VAL) > 0
           && print_mac(out, OSSL_PROV_FIPS_PARAM_MODULE_MAC, module_mac,
           && BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_VERSION,
                         VERSION_VAL) > 0
           && print_mac(out, OSSL_PROV_FIPS_PARAM_MODULE_MAC, module_mac,
@@ -167,7 +183,7 @@ static CONF *generate_config_and_load(const char *prov_name,
     if (conf == NULL)
         goto end;
 
     if (conf == NULL)
         goto end;
 
-    if (!CONF_modules_load(conf, NULL, 0))
+    if (CONF_modules_load(conf, NULL, 0) <= 0)
         goto end;
     BIO_free(mem_bio);
     return conf;
         goto end;
     BIO_free(mem_bio);
     return conf;
@@ -273,7 +289,7 @@ int fipsinstall_main(int argc, char **argv)
         case OPT_ERR:
 opthelp:
             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
         case OPT_ERR:
 opthelp:
             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
-            goto end;
+            goto cleanup;
         case OPT_HELP:
             opt_help(fipsinstall_options);
             ret = 0;
         case OPT_HELP:
             opt_help(fipsinstall_options);
             ret = 0;
@@ -284,6 +300,18 @@ opthelp:
         case OPT_OUT:
             out_fname = opt_arg();
             break;
         case OPT_OUT:
             out_fname = opt_arg();
             break;
+        case OPT_QUIET:
+            quiet = 1;
+            /* FALLTHROUGH */
+        case OPT_NO_LOG:
+            self_test_log = 0;
+            break;
+        case OPT_CORRUPT_DESC:
+            self_test_corrupt_desc = opt_arg();
+            break;
+        case OPT_CORRUPT_TYPE:
+            self_test_corrupt_type = opt_arg();
+            break;
         case OPT_PROV_NAME:
             prov_name = opt_arg();
             break;
         case OPT_PROV_NAME:
             prov_name = opt_arg();
             break;
@@ -315,6 +343,11 @@ opthelp:
         || argc != 0)
         goto opthelp;
 
         || argc != 0)
         goto opthelp;
 
+    if (self_test_log
+            || self_test_corrupt_desc != NULL
+            || self_test_corrupt_type != NULL)
+        OSSL_SELF_TEST_set_callback(NULL, self_test_events, NULL);
+
     module_bio = bio_open_default(module_fname, 'r', FORMAT_BINARY);
     if (module_bio == NULL) {
         BIO_printf(bio_err, "Failed to open module file\n");
     module_bio = bio_open_default(module_fname, 'r', FORMAT_BINARY);
     if (module_bio == NULL) {
         BIO_printf(bio_err, "Failed to open module file\n");
@@ -340,7 +373,7 @@ opthelp:
     if (opts != NULL) {
         int ok = 1;
         OSSL_PARAM *params =
     if (opts != NULL) {
         int ok = 1;
         OSSL_PARAM *params =
-            app_params_new_from_opts(opts, EVP_MAC_CTX_settable_params(mac));
+            app_params_new_from_opts(opts, EVP_MAC_settable_ctx_params(mac));
 
         if (params == NULL)
             goto end;
 
         if (params == NULL)
             goto end;
@@ -377,7 +410,8 @@ opthelp:
         if (!verify_config(in_fname, section_name, module_mac, module_mac_len,
                            install_mac, install_mac_len))
             goto end;
         if (!verify_config(in_fname, section_name, module_mac, module_mac_len,
                            install_mac, install_mac_len))
             goto end;
-        BIO_printf(bio_out, "VERIFY PASSED\n");
+        if (!quiet)
+            BIO_printf(bio_out, "VERIFY PASSED\n");
     } else {
 
         conf = generate_config_and_load(prov_name, section_name, module_mac,
     } else {
 
         conf = generate_config_and_load(prov_name, section_name, module_mac,
@@ -396,16 +430,19 @@ opthelp:
                                        module_mac_len, install_mac,
                                        install_mac_len))
             goto end;
                                        module_mac_len, install_mac,
                                        install_mac_len))
             goto end;
-        BIO_printf(bio_out, "INSTALL PASSED\n");
+        if (!quiet)
+            BIO_printf(bio_out, "INSTALL PASSED\n");
     }
 
     ret = 0;
 end:
     if (ret == 1) {
     }
 
     ret = 0;
 end:
     if (ret == 1) {
-        BIO_printf(bio_err, "%s FAILED\n", verify ? "VERIFY" : "INSTALL");
+        if (!quiet)
+            BIO_printf(bio_err, "%s FAILED\n", verify ? "VERIFY" : "INSTALL");
         ERR_print_errors(bio_err);
     }
 
         ERR_print_errors(bio_err);
     }
 
+cleanup:
     BIO_free(fout);
     BIO_free(mem_bio);
     BIO_free(module_bio);
     BIO_free(fout);
     BIO_free(mem_bio);
     BIO_free(module_bio);
@@ -417,3 +454,53 @@ end:
     free_config_and_unload(conf);
     return ret;
 }
     free_config_and_unload(conf);
     return ret;
 }
+
+static int self_test_events(const OSSL_PARAM params[], void *arg)
+{
+    const OSSL_PARAM *p = NULL;
+    const char *phase = NULL, *type = NULL, *desc = NULL;
+    int ret = 0;
+
+    p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_PHASE);
+    if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
+        goto err;
+    phase = (const char *)p->data;
+
+    p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_DESC);
+    if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
+        goto err;
+    desc = (const char *)p->data;
+
+    p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_TYPE);
+    if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
+        goto err;
+    type = (const char *)p->data;
+
+    if (self_test_log) {
+        if (strcmp(phase, OSSL_SELF_TEST_PHASE_START) == 0)
+            BIO_printf(bio_out, "%s : (%s) : ", desc, type);
+        else if (strcmp(phase, OSSL_SELF_TEST_PHASE_PASS) == 0
+                 || strcmp(phase, OSSL_SELF_TEST_PHASE_FAIL) == 0)
+            BIO_printf(bio_out, "%s\n", phase);
+    }
+    /*
+     * The self test code will internally corrupt the KAT test result if an
+     * error is returned during the corrupt phase.
+     */
+    if (strcmp(phase, OSSL_SELF_TEST_PHASE_CORRUPT) == 0
+            && (self_test_corrupt_desc != NULL
+                || self_test_corrupt_type != NULL)) {
+        if (self_test_corrupt_desc != NULL
+                && strcmp(self_test_corrupt_desc, desc) != 0)
+            goto end;
+        if (self_test_corrupt_type != NULL
+                && strcmp(self_test_corrupt_type, type) != 0)
+            goto end;
+        BIO_printf(bio_out, "%s ", phase);
+        goto err;
+    }
+end:
+    ret = 1;
+err:
+    return ret;
+}