With fips provider 3.0.0 skip tests related to explicit curves handling
authorTomas Mraz <tomas@openssl.org>
Tue, 13 Sep 2022 20:38:30 +0000 (22:38 +0200)
committerPauli <pauli@openssl.org>
Thu, 15 Sep 2022 22:34:53 +0000 (08:34 +1000)
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19201)

test/build.info
test/endecode_test.c
test/evp_test.c
test/fips_version_test.c [new file with mode: 0644]
test/recipes/25-test_verify.t
test/testutil.h
test/testutil/provider.c

index 0fac691cab3954d5e3a5963389a537248884b4e7..bab28035a8d9ae2106eea37f8b65cf0b2edf23ef 100644 (file)
@@ -63,7 +63,7 @@ IF[{- !$disabled{tests} -}]
           keymgmt_internal_test hexstr_test provider_status_test defltfips_test \
           bio_readbuffer_test user_property_test pkcs7_test upcallstest \
           provfetchtest prov_config_test rand_test ca_internals_test \
-          bio_tfo_test membio_test list_test
+          bio_tfo_test membio_test list_test fips_version_test
 
   IF[{- !$disabled{'deprecated-3.0'} -}]
     PROGRAMS{noinst}=enginetest
@@ -427,6 +427,10 @@ IF[{- !$disabled{tests} -}]
   INCLUDE[defltfips_test]=../include  ../apps/include
   DEPEND[defltfips_test]=../libcrypto libtestutil.a
 
+  SOURCE[fips_version_test]=fips_version_test.c
+  INCLUDE[fips_version_test]=../include  ../apps/include
+  DEPEND[fips_version_test]=../libcrypto libtestutil.a
+
   SOURCE[ocspapitest]=ocspapitest.c
   INCLUDE[ocspapitest]=../include ../apps/include
   DEPEND[ocspapitest]=../libcrypto libtestutil.a
index c139fe63bef0bc05db01aa96262bb0013d32a9f3..14648287eb2d85d2a32b4a794af7607facc77d8b 100644 (file)
@@ -47,6 +47,7 @@ OSSL_provider_init_fn ossl_legacy_provider_init;
 
 static int default_libctx = 1;
 static int is_fips = 0;
+static int is_fips_3_0_0 = 0;
 
 static OSSL_LIB_CTX *testctx = NULL;
 static OSSL_LIB_CTX *keyctx = NULL;
@@ -174,7 +175,7 @@ static int test_encode_decode(const char *file, const int line,
                              output_type, output_structure, pass, pcipher)))
         goto end;
 
-    if ((flags & FLAG_FAIL_IF_FIPS) != 0 && is_fips) {
+    if ((flags & FLAG_FAIL_IF_FIPS) != 0 && is_fips && !is_fips_3_0_0) {
         if (TEST_false(decode_cb(file, line, (void **)&pkey2, encoded,
                                   encoded_len, output_type, output_structure,
                                   (flags & FLAG_DECODE_WITH_TYPE ? type : NULL),
@@ -1323,6 +1324,11 @@ int setup_tests(void)
             return 0;
     }
 
+    /* FIPS(3.0.0): provider imports explicit params but they won't work #17998 */
+    is_fips_3_0_0 = fips_provider_version_eq(testctx, 3, 0, 0);
+    if (is_fips_3_0_0 < 0)
+        return 0;
+
 #ifdef STATIC_LEGACY
     /*
      * This test is always statically linked against libcrypto. We must not
index e4350c39b4d37778fdd50caea99112047b7d2168..a5f7b93cfb41f9180a82ab50e0e822018bb40964 100644 (file)
@@ -1596,7 +1596,7 @@ static int mac_test_run_mac(EVP_TEST *t)
             goto err;
         }
     }
-    /* FIPS 3.0.0 can't reinitialise MAC contexts #18100 */
+    /* FIPS(3.0.0): can't reinitialise MAC contexts #18100 */
     if (reinit-- && fips_provider_version_gt(libctx, 3, 0, 0)) {
         OSSL_PARAM ivparams[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
         int ret;
@@ -2823,7 +2823,7 @@ static int kdf_test_run(EVP_TEST *t)
         t->err = "INTERNAL_ERROR";
         goto err;
     }
-    /* FIPS 3.0.0 can't dup KDF contexts #17572 */
+    /* FIPS(3.0.0): can't dup KDF contexts #17572 */
     if (fips_provider_version_gt(libctx, 3, 0, 0)
             && (ctx = EVP_KDF_CTX_dup(expected->ctx)) != NULL) {
         EVP_KDF_CTX_free(expected->ctx);
@@ -2922,7 +2922,7 @@ static int pkey_kdf_test_run(EVP_TEST *t)
     size_t got_len = 0;
 
     if (fips_provider_version_eq(libctx, 3, 0, 0)) {
-        /* FIPS 3.0.0 can't deal with oversized output buffers #18533 */
+        /* FIPS(3.0.0): can't deal with oversized output buffers #18533 */
         got_len = expected->output_len;
     } else {
         /* Find out the KDF output size */
@@ -3737,72 +3737,6 @@ static int prov_available(char *providers)
     return 0;
 }
 
-static int check_fips_versions(char *versions, const EVP_TEST *t)
-{
-    char *p;
-    int major, minor, patch, r;
-    enum {
-        MODE_EQ, MODE_NE, MODE_LE, MODE_GT
-    } mode;
-
-    while (*versions != '\0') {
-        for (; isspace(*versions); versions++)
-            continue;
-        if (*versions == '\0')
-            break;
-        for (p = versions; *versions != '\0' && !isspace(*versions); versions++)
-            continue;
-        if (*versions != '\0')
-            *versions++ = '\0';
-        if (*p == '!') {
-            mode = MODE_NE;
-            p++;
-        } else if (*p == '=') {
-            mode = MODE_EQ;
-            p++;
-        } else if (*p == '<' && p[1] == '=') {
-            mode = MODE_LE;
-            p += 2;
-        } else if (*p == '>') {
-            mode = MODE_GT;
-            p++;
-        } else if (isdigit(*p)) {
-            mode = MODE_EQ;
-        } else {
-            TEST_info("Line %d: error matching FIPS version: mode %s\n",
-                      t->s.curr, p);
-            return -1;
-        }
-        if (sscanf(p, "%d.%d.%d", &major, &minor, &patch) != 3) {
-            TEST_info("Line %d: error matching FIPS version: version %s\n",
-                      t->s.curr, p);
-            return -1;
-        }
-        switch (mode) {
-        case MODE_EQ:
-            r = fips_provider_version_eq(libctx, major, minor, patch);
-            break;
-        case MODE_NE:
-            r = fips_provider_version_ne(libctx, major, minor, patch);
-            break;
-        case MODE_LE:
-            r = fips_provider_version_le(libctx, major, minor, patch);
-            break;
-        case MODE_GT:
-            r = fips_provider_version_gt(libctx, major, minor, patch);
-            break;
-        }
-        if (r < 0) {
-            TEST_info("Line %d: error matching FIPS version: internal error\n",
-                      t->s.curr);
-            return -1;
-        }
-        if (r == 0)
-            return 0;
-    }
-    return 1;
-}
-
 /* Read and parse one test.  Return 0 if failure, 1 if okay. */
 static int parse(EVP_TEST *t)
 {
@@ -3901,7 +3835,7 @@ start:
         goto start;
     } else if (strcmp(pp->key, "FIPSversion") == 0) {
         if (prov_available("fips")) {
-            j = check_fips_versions(pp->value, t);
+            j = fips_provider_version_match(libctx, pp->value);
             if (j < 0) {
                 TEST_info("Line %d: error matching FIPS versions\n", t->s.curr);
                 return 0;
diff --git a/test/fips_version_test.c b/test/fips_version_test.c
new file mode 100644 (file)
index 0000000..dd23bb5
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2022 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/evp.h>
+#include <openssl/provider.h>
+#include "testutil.h"
+
+static OSSL_LIB_CTX *libctx = NULL;
+static OSSL_PROVIDER *libprov = NULL;
+
+typedef enum OPTION_choice {
+    OPT_ERR = -1,
+    OPT_EOF = 0,
+    OPT_CONFIG_FILE,
+    OPT_TEST_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS *test_get_options(void)
+{
+    static const OPTIONS test_options[] = {
+        OPT_TEST_OPTIONS_DEFAULT_USAGE,
+        { "config", OPT_CONFIG_FILE, '<',
+          "The configuration file to use for the libctx" },
+        { NULL }
+    };
+    return test_options;
+}
+
+static int test_fips_version(int n)
+{
+    const char *version = test_get_argument(n);
+
+    if (!TEST_ptr(version))
+        return 0;
+    return TEST_int_eq(fips_provider_version_match(libctx, version), 1);
+}
+
+int setup_tests(void)
+{
+    char *config_file = NULL;
+    OPTION_CHOICE o;
+    int n;
+
+    while ((o = opt_next()) != OPT_EOF) {
+        switch (o) {
+        case OPT_CONFIG_FILE:
+            config_file = opt_arg();
+            break;
+        case OPT_TEST_CASES:
+           break;
+        default:
+        case OPT_ERR:
+            return 0;
+        }
+    }
+
+    if (!test_get_libctx(&libctx, NULL, config_file, &libprov, NULL))
+        return 0;
+
+    n = test_get_argument_count();
+    if (n == 0)
+        return 0;
+
+    ADD_ALL_TESTS(test_fips_version, n);
+    return 1;
+}
+
+void cleanup_tests(void)
+{
+    OSSL_PROVIDER_unload(libprov);
+    OSSL_LIB_CTX_free(libctx);
+}
index d6d25759b5f8cbea532a0da2659addc10688775d..2bb77f2189d9b6ca809f1ddd99fedf396b2b5165 100644 (file)
@@ -354,12 +354,18 @@ SKIP: {
 # Same as above but with base provider used for decoding
 SKIP: {
     my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0);
-    skip "EC is not supported or FIPS is disabled", 3
-        if disabled("ec") || $no_fips;
-
     my $provconf = srctop_file("test", "fips-and-base.cnf");
     my $provpath = bldtop_dir("providers");
     my @prov = ("-provider-path", $provpath);
+
+    skip "EC is not supported or FIPS is disabled", 3
+        if disabled("ec") || $no_fips;
+
+    run(test(["fips_version_test", "-config", $provconf, ">3.0.0"]),
+             capture => 1, statusvar => \my $exit);
+    skip "FIPS provider version is too old", 3
+        if !$exit;
+
     $ENV{OPENSSL_CONF} = $provconf;
 
     ok(!verify("ee-cert-ec-explicit", "", ["root-cert"],
index 3a3e0f279e37b7e52dfbacfa7089b82da9ec15af..0a050bb060edb566b729ca08c5f0d986389b2eab 100644 (file)
@@ -240,7 +240,7 @@ void cleanup_tests(void);
 /*
  * Helper functions to detect specific versions of the FIPS provider being in use.
  * Because of FIPS rules, code changes after a module has been validated are
- * difficult and because we provide an hard guarantee of ABI and behavioural
+ * difficult and because we provide a hard guarantee of ABI and behavioural
  * stability going forwards, it is a requirement to have tests be conditional
  * on specific FIPS provider versions.  Without this, bug fixes cannot be tested
  * in later releases.
@@ -259,6 +259,17 @@ int fips_provider_version_ne(OSSL_LIB_CTX *libctx, int major, int minor, int pat
 int fips_provider_version_le(OSSL_LIB_CTX *libctx, int major, int minor, int patch);
 int fips_provider_version_gt(OSSL_LIB_CTX *libctx, int major, int minor, int patch);
 
+/*
+ * This function matches fips provider version with (potentially multiple)
+ * <operator>maj.min.patch version strings in versions.
+ * The operator can be one of = ! <= or > comparison symbols.
+ * If the fips provider matches all the version comparisons (or if there is no
+ * fips provider available) the function returns 1.
+ * If the fips provider does not match the version comparisons, it returns 0.
+ * On error the function returns -1.
+ */
+int fips_provider_version_match(OSSL_LIB_CTX *libctx, const char *versions);
+
 /*
  * Used to supply test specific command line options,
  * If non optional parameters are used, then the first entry in the OPTIONS[]
index f9b37cca8f775aa6768a3a5a520b5e026fe7493c..c8b5dfc0617b47f3273b83d3f0dc29199c7efe7b 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include "../testutil.h"
+#include <ctype.h>
 #include <openssl/provider.h>
 #include <openssl/core_names.h>
 #include <string.h>
@@ -88,7 +89,7 @@ static int fips_provider_version(OSSL_LIB_CTX *libctx, FIPS_VERSION *vers)
             || sscanf(vs, "%d.%d.%d", &vers->major, &vers->minor, &vers->patch) != 3)
         goto err;
     if (!OSSL_PROVIDER_unload(fips_prov))
-        return -1;  /* WTF do we do here??? */
+        return -1;
     return 1;
  err:
     OSSL_PROVIDER_unload(fips_prov);
@@ -140,3 +141,64 @@ int fips_provider_version_gt(OSSL_LIB_CTX *libctx, int major, int minor, int pat
                && (prov.minor > minor
                    || (prov.minor == minor && prov.patch > patch)));
 }
+
+int fips_provider_version_match(OSSL_LIB_CTX *libctx, const char *versions)
+{
+    const char *p;
+    int major, minor, patch, r;
+    enum {
+        MODE_EQ, MODE_NE, MODE_LE, MODE_GT
+    } mode;
+
+    while (*versions != '\0') {
+        for (; isspace(*versions); versions++)
+            continue;
+        if (*versions == '\0')
+            break;
+        for (p = versions; *versions != '\0' && !isspace(*versions); versions++)
+            continue;
+        if (*p == '!') {
+            mode = MODE_NE;
+            p++;
+        } else if (*p == '=') {
+            mode = MODE_EQ;
+            p++;
+        } else if (*p == '<' && p[1] == '=') {
+            mode = MODE_LE;
+            p += 2;
+        } else if (*p == '>') {
+            mode = MODE_GT;
+            p++;
+        } else if (isdigit(*p)) {
+            mode = MODE_EQ;
+        } else {
+            TEST_info("Error matching FIPS version: mode %s\n", p);
+            return -1;
+        }
+        if (sscanf(p, "%d.%d.%d", &major, &minor, &patch) != 3) {
+            TEST_info("Error matching FIPS version: version %s\n", p);
+            return -1;
+        }
+        switch (mode) {
+        case MODE_EQ:
+            r = fips_provider_version_eq(libctx, major, minor, patch);
+            break;
+        case MODE_NE:
+            r = fips_provider_version_ne(libctx, major, minor, patch);
+            break;
+        case MODE_LE:
+            r = fips_provider_version_le(libctx, major, minor, patch);
+            break;
+        case MODE_GT:
+            r = fips_provider_version_gt(libctx, major, minor, patch);
+            break;
+        }
+        if (r < 0) {
+            TEST_info("Error matching FIPS version: internal error\n");
+            return -1;
+        }
+        if (r == 0)
+            return 0;
+    }
+    return 1;
+}