Update some nits around the FIPS module
[openssl.git] / apps / fipsinstall.c
index 3b19ef15a8808c4209e1286819e7eeedd1968324..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
@@ -13,6 +13,8 @@
 #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"
 
 #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,
-    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[] = {
@@ -49,6 +58,10 @@ const OPTIONS fipsinstall_options[] = {
     {"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}
 };
 
@@ -170,7 +183,7 @@ static CONF *generate_config_and_load(const char *prov_name,
     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;
@@ -276,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);
-            goto end;
+            goto cleanup;
         case OPT_HELP:
             opt_help(fipsinstall_options);
             ret = 0;
@@ -287,6 +300,18 @@ opthelp:
         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;
@@ -318,6 +343,11 @@ 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");
@@ -380,7 +410,8 @@ opthelp:
         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,
@@ -399,16 +430,19 @@ opthelp:
                                        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) {
-        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);
     }
 
+cleanup:
     BIO_free(fout);
     BIO_free(mem_bio);
     BIO_free(module_bio);
@@ -420,3 +454,53 @@ end:
     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;
+}