314 lines
12 KiB
Diff
314 lines
12 KiB
Diff
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,
|
|
(siglen == 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 == NULL) ? 0 : *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
|
|
|