From 97ac06e5a8e3a8699279c06eeb64c8e958bad7bd Mon Sep 17 00:00:00 2001
From: Clemens Lang <cllang@redhat.com>
Date: Fri, 15 Jul 2022 17:45:40 +0200
Subject: [PATCH] FIPS: Use digest_sign & digest_verify in self test

In review for FIPS 140-3, the lack of a self-test for the digest_sign
and digest_verify provider functions was highlighted as a problem. NIST
no longer provides ACVP tests for the RSA SigVer primitive (see
https://github.com/usnistgov/ACVP/issues/1347). Because FIPS 140-3
recommends the use of functions that compute the digest and signature
within the module, we have been advised in our module review that the
self tests should also use the combined digest and signature APIs, i.e.
the digest_sign and digest_verify provider functions.

Modify the signature self-test to use these instead by switching to
EVP_DigestSign and EVP_DigestVerify. This requires adding more ifdefs to
crypto/evp/m_sigver.c to make these functions usable in the FIPS module.

Signed-off-by: Clemens Lang <cllang@redhat.com>
---
 crypto/evp/m_sigver.c           | 43 +++++++++++++++++++++++++++------
 providers/fips/self_test_kats.c | 37 +++++++++++++++-------------
 2 files changed, 56 insertions(+), 24 deletions(-)

diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c
index db1a1d7bc3..c94c3c53bd 100644
--- a/crypto/evp/m_sigver.c
+++ b/crypto/evp/m_sigver.c
@@ -88,6 +88,7 @@ static int update(EVP_MD_CTX *ctx, const void *data, size_t datalen)
     ERR_raise(ERR_LIB_EVP, EVP_R_ONLY_ONESHOT_SUPPORTED);
     return 0;
 }
+#endif /* !defined(FIPS_MODULE) */
 
 /*
  * If we get the "NULL" md then the name comes back as "UNDEF". We want to use
@@ -130,8 +131,10 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
         reinit = 0;
         if (e == NULL)
             ctx->pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, props);
+#ifndef FIPS_MODULE
         else
             ctx->pctx = EVP_PKEY_CTX_new(pkey, e);
+#endif /* !defined(FIPS_MODULE) */
     }
     if (ctx->pctx == NULL)
         return 0;
@@ -139,8 +142,10 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
     locpctx = ctx->pctx;
     ERR_set_mark();
 
+#ifndef FIPS_MODULE
     if (evp_pkey_ctx_is_legacy(locpctx))
         goto legacy;
+#endif /* !defined(FIPS_MODULE) */
 
     /* do not reinitialize if pkey is set or operation is different */
     if (reinit
@@ -225,8 +230,10 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
             signature =
                 evp_signature_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
                                               supported_sig, locpctx->propquery);
+#ifndef FIPS_MODULE
             if (signature == NULL)
                 goto legacy;
+#endif /* !defined(FIPS_MODULE) */
             break;
         }
         if (signature == NULL)
@@ -310,6 +317,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
             ctx->fetched_digest = EVP_MD_fetch(locpctx->libctx, mdname, props);
             if (ctx->fetched_digest != NULL) {
                 ctx->digest = ctx->reqdigest = ctx->fetched_digest;
+#ifndef FIPS_MODULE
             } else {
                 /* legacy engine support : remove the mark when this is deleted */
                 ctx->reqdigest = ctx->digest = EVP_get_digestbyname(mdname);
@@ -318,11 +326,13 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
                     ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
                     goto err;
                 }
+#endif /* !defined(FIPS_MODULE) */
             }
             (void)ERR_pop_to_mark();
         }
     }
 
+#ifndef FIPS_MODULE
     if (ctx->reqdigest != NULL
             && !EVP_PKEY_is_a(locpctx->pkey, SN_hmac)
             && !EVP_PKEY_is_a(locpctx->pkey, SN_tls1_prf)
@@ -334,6 +344,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
             goto err;
         }
     }
+#endif /* !defined(FIPS_MODULE) */
 
     if (ver) {
         if (signature->digest_verify_init == NULL) {
@@ -366,6 +377,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
     EVP_KEYMGMT_free(tmp_keymgmt);
     return 0;
 
+#ifndef FIPS_MODULE
  legacy:
     /*
      * If we don't have the full support we need with provided methods,
@@ -437,6 +449,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
         ctx->pctx->flag_call_digest_custom = 1;
 
     ret = 1;
+#endif /* !defined(FIPS_MODULE) */
 
  end:
 #ifndef FIPS_MODULE
@@ -479,7 +492,6 @@ int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
     return do_sigver_init(ctx, pctx, type, NULL, NULL, NULL, e, pkey, 1,
                           NULL);
 }
-#endif /* FIPS_MDOE */
 
 int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
 {
@@ -541,23 +553,29 @@ int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
     return EVP_DigestUpdate(ctx, data, dsize);
 }
 
-#ifndef FIPS_MODULE
 int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
                         size_t *siglen)
 {
-    int sctx = 0, r = 0;
-    EVP_PKEY_CTX *dctx, *pctx = ctx->pctx;
+    int r = 0;
+#ifndef FIPS_MODULE
+    int sctx = 0;
+    EVP_PKEY_CTX *dctx;
+#endif /* !defined(FIPS_MODULE) */
+    EVP_PKEY_CTX *pctx = ctx->pctx;
 
+#ifndef FIPS_MODULE
     if (pctx == NULL
             || pctx->operation != EVP_PKEY_OP_SIGNCTX
             || pctx->op.sig.algctx == NULL
             || pctx->op.sig.signature == NULL)
         goto legacy;
+#endif /* !defined(FIPS_MODULE) */
 
     if (sigret == NULL || (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) != 0)
         return pctx->op.sig.signature->digest_sign_final(pctx->op.sig.algctx,
                                                          sigret, siglen,
                                                          sigret == NULL ? 0 : *siglen);
+#ifndef FIPS_MODULE
     dctx = EVP_PKEY_CTX_dup(pctx);
     if (dctx == NULL)
         return 0;
@@ -566,8 +584,10 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
                                                   sigret, siglen,
                                                   *siglen);
     EVP_PKEY_CTX_free(dctx);
+#endif /* defined(FIPS_MODULE) */
     return r;
 
+#ifndef FIPS_MODULE
  legacy:
     if (pctx == NULL || pctx->pmeth == NULL) {
         ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
@@ -639,6 +659,7 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
         }
     }
     return 1;
+#endif /* !defined(FIPS_MODULE) */
 }
 
 int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen,
@@ -669,21 +690,27 @@ int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen,
 int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
                           size_t siglen)
 {
-    unsigned char md[EVP_MAX_MD_SIZE];
     int r = 0;
+#ifndef FIPS_MODULE
+    unsigned char md[EVP_MAX_MD_SIZE];
     unsigned int mdlen = 0;
     int vctx = 0;
-    EVP_PKEY_CTX *dctx, *pctx = ctx->pctx;
+    EVP_PKEY_CTX *dctx;
+#endif /* !defined(FIPS_MODULE) */
+    EVP_PKEY_CTX *pctx = ctx->pctx;
 
+#ifndef FIPS_MODULE
     if (pctx == NULL
             || pctx->operation != EVP_PKEY_OP_VERIFYCTX
             || pctx->op.sig.algctx == NULL
             || pctx->op.sig.signature == NULL)
         goto legacy;
+#endif /* !defined(FIPS_MODULE) */
 
     if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISE) != 0)
         return pctx->op.sig.signature->digest_verify_final(pctx->op.sig.algctx,
                                                            sig, siglen);
+#ifndef FIPS_MODULE
     dctx = EVP_PKEY_CTX_dup(pctx);
     if (dctx == NULL)
         return 0;
@@ -691,8 +718,10 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
     r = dctx->op.sig.signature->digest_verify_final(dctx->op.sig.algctx,
                                                     sig, siglen);
     EVP_PKEY_CTX_free(dctx);
+#endif /* !defined(FIPS_MODULE) */
     return r;
 
+#ifndef FIPS_MODULE
  legacy:
     if (pctx == NULL || pctx->pmeth == NULL) {
         ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
@@ -732,6 +761,7 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
     if (vctx || !r)
         return r;
     return EVP_PKEY_verify(pctx, sig, siglen, md, mdlen);
+#endif /* !defined(FIPS_MODULE) */
 }
 
 int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
@@ -757,4 +787,3 @@ int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
         return -1;
     return EVP_DigestVerifyFinal(ctx, sigret, siglen);
 }
-#endif /* FIPS_MODULE */
diff --git a/providers/fips/self_test_kats.c b/providers/fips/self_test_kats.c
index b6d5e8e134..77eec075e6 100644
--- a/providers/fips/self_test_kats.c
+++ b/providers/fips/self_test_kats.c
@@ -444,11 +444,14 @@ static int self_test_sign(const ST_KAT_SIGN *t,
     int ret = 0;
     OSSL_PARAM *params = NULL, *params_sig = NULL;
     OSSL_PARAM_BLD *bld = NULL;
+    EVP_MD *md = NULL;
+    EVP_MD_CTX *ctx = NULL;
     EVP_PKEY_CTX *sctx = NULL, *kctx = NULL;
     EVP_PKEY *pkey = NULL;
-    unsigned char sig[256];
     BN_CTX *bnctx = NULL;
     BIGNUM *K = NULL;
+    const char *msg = "Hello World!";
+    unsigned char sig[256];
     size_t siglen = sizeof(sig);
     static const unsigned char dgst[] = {
         0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81,
@@ -488,23 +491,26 @@ static int self_test_sign(const ST_KAT_SIGN *t,
         || EVP_PKEY_fromdata(kctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0)
         goto err;
 
-    /* Create a EVP_PKEY_CTX to use for the signing operation */
-    sctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, NULL);
-    if (sctx == NULL
-        || EVP_PKEY_sign_init(sctx) <= 0)
-        goto err;
-
-    /* set signature parameters */
-    if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_SIGNATURE_PARAM_DIGEST,
-                                         t->mdalgorithm,
-                                         strlen(t->mdalgorithm) + 1))
-        goto err;
+    /* Create a EVP_MD_CTX to use for the signature operation, assign signature
+     * parameters and sign */
     params_sig = OSSL_PARAM_BLD_to_param(bld);
-    if (EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0)
+    md = EVP_MD_fetch(libctx, "SHA256", NULL);
+    ctx = EVP_MD_CTX_new();
+    if (md == NULL || ctx == NULL)
+        goto err;
+    EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_FINALISE | EVP_MD_CTX_FLAG_ONESHOT);
+    if (EVP_DigestSignInit(ctx, &sctx, md, NULL, pkey) <= 0
+        || EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0
+        || EVP_DigestSign(ctx, sig, &siglen, (const unsigned char *)msg, strlen(msg)) <= 0
+        || EVP_MD_CTX_reset(ctx) <= 0)
         goto err;
 
-    if (EVP_PKEY_sign(sctx, sig, &siglen, dgst, sizeof(dgst)) <= 0
-        || EVP_PKEY_verify_init(sctx) <= 0
+    /* sctx is not freed automatically inside the FIPS module */
+    EVP_PKEY_CTX_free(sctx);
+    sctx = NULL;
+
+    EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_FINALISE | EVP_MD_CTX_FLAG_ONESHOT);
+    if (EVP_DigestVerifyInit(ctx, &sctx, md, NULL, pkey) <= 0
         || EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0)
         goto err;
 
@@ -509,14 +510,17 @@ static int self_test_sign(const ST_KAT_SIGN *t,
         goto err;
 
     OSSL_SELF_TEST_oncorrupt_byte(st, sig);
-    if (EVP_PKEY_verify(sctx, sig, siglen, dgst, sizeof(dgst)) <= 0)
+    if (EVP_DigestVerify(ctx, sig, siglen, (const unsigned char *)msg, strlen(msg)) <= 0)
         goto err;
     ret = 1;
 err:
     BN_CTX_free(bnctx);
     EVP_PKEY_free(pkey);
-    EVP_PKEY_CTX_free(kctx);
+    EVP_MD_free(md);
+    EVP_MD_CTX_free(ctx);
+    /* sctx is not freed automatically inside the FIPS module */
     EVP_PKEY_CTX_free(sctx);
+    EVP_PKEY_CTX_free(kctx);
     OSSL_PARAM_free(params);
     OSSL_PARAM_free(params_sig);
     OSSL_PARAM_BLD_free(bld);
-- 
2.37.1

