evp_test: allow FIPS provider version based escapes in evp_test
authorPauli <pauli@openssl.org>
Mon, 12 Sep 2022 22:49:05 +0000 (08:49 +1000)
committerPauli <pauli@openssl.org>
Thu, 15 Sep 2022 22:37:31 +0000 (08:37 +1000)
Also fix a number of regressions when run against the 3.0.0 FIPS provider
that result from bug fixes.

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/19201)

(cherry picked from commit 54a7bbedf43a1ade98c8f47eb8896d75f3db0165)

test/evp_test.c

index ce4c66ddccb3cd91e57ac1a1dd6d0dbbb9002498..2be97e916eaf77d92b94dc92aa03b9ecc980f8fa 100644 (file)
@@ -1575,7 +1575,8 @@ static int mac_test_run_mac(EVP_TEST *t)
             goto err;
         }
     }
-    if (reinit--) {
+    /* 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;
 
@@ -2882,21 +2883,26 @@ static int pkey_kdf_test_run(EVP_TEST *t)
     unsigned char *got = NULL;
     size_t got_len = 0;
 
-    /* Find out the KDF output size */
-    if (EVP_PKEY_derive(expected->ctx, NULL, &got_len) <= 0) {
-        t->err = "INTERNAL_ERROR";
-        goto err;
-    }
-
-    /*
-     * We may get an absurd output size, which signals that anything goes.
-     * If not, we specify a too big buffer for the output, to test that
-     * EVP_PKEY_derive() can cope with it.
-     */
-    if (got_len == SIZE_MAX || got_len == 0)
+    if (fips_provider_version_eq(libctx, 3, 0, 0)) {
+        /* FIPS 3.0.0 can't deal with oversized output buffers #18533 */
         got_len = expected->output_len;
-    else
-        got_len = expected->output_len * 2;
+    } else {
+        /* Find out the KDF output size */
+        if (EVP_PKEY_derive(expected->ctx, NULL, &got_len) <= 0) {
+            t->err = "INTERNAL_ERROR";
+            goto err;
+        }
+
+        /*
+         * We may get an absurd output size, which signals that anything goes.
+         * If not, we specify a too big buffer for the output, to test that
+         * EVP_PKEY_derive() can cope with it.
+         */
+        if (got_len == SIZE_MAX || got_len == 0)
+            got_len = expected->output_len;
+        else
+            got_len = expected->output_len * 2;
+    }
 
     if (!TEST_ptr(got = OPENSSL_malloc(got_len == 0 ? 1 : got_len))) {
         t->err = "INTERNAL_ERROR";
@@ -3693,13 +3699,79 @@ 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)
 {
     KEY_LIST *key, **klist;
     EVP_PKEY *pkey;
     PAIR *pp;
-    int i, skip_availablein = 0;
+    int i, j, skipped = 0;
 
 top:
     do {
@@ -3786,7 +3858,23 @@ start:
                 t->skip = 1;
                 return 0;
         }
-        skip_availablein++;
+        skipped++;
+        pp++;
+        goto start;
+    } else if (strcmp(pp->key, "FIPSversion") == 0) {
+        if (prov_available("fips")) {
+            j = check_fips_versions(pp->value, t);
+            if (j < 0) {
+                TEST_info("Line %d: error matching FIPS versions\n", t->s.curr);
+                return 0;
+            } else if (j == 0) {
+                TEST_info("skipping, FIPS provider incompatible version: %s:%d",
+                          t->s.test_file, t->s.start);
+                    t->skip = 1;
+                    return 0;
+            }
+        }
+        skipped++;
         pp++;
         goto start;
     }
@@ -3805,7 +3893,7 @@ start:
         *klist = key;
 
         /* Go back and start a new stanza. */
-        if ((t->s.numpairs - skip_availablein) != 1)
+        if ((t->s.numpairs - skipped) != 1)
             TEST_info("Line %d: missing blank line\n", t->s.curr);
         goto top;
     }
@@ -3822,7 +3910,7 @@ start:
         return 0;
     }
 
-    for (pp++, i = 1; i < (t->s.numpairs - skip_availablein); pp++, i++) {
+    for (pp++, i = 1; i < (t->s.numpairs - skipped); pp++, i++) {
         if (strcmp(pp->key, "Securitycheck") == 0) {
 #if defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
 #else