You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
313 lines
12 KiB
313 lines
12 KiB
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 |
|
|
|
|