From 97ac06e5a8e3a8699279c06eeb64c8e958bad7bd Mon Sep 17 00:00:00 2001 From: Clemens Lang 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 --- crypto/evp/m_sigver.c | 43 +++++++++++++++++++++++++++------ providers/fips/self_test_kats.c | 37 +++++++++++++++------------- 2 files changed, 56 insertions(+), 24 deletions(-) Index: openssl-3.1.4/crypto/evp/m_sigver.c =================================================================== --- openssl-3.1.4.orig/crypto/evp/m_sigver.c +++ openssl-3.1.4/crypto/evp/m_sigver.c @@ -90,6 +90,7 @@ static int update(EVP_MD_CTX *ctx, const 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 @@ -125,8 +126,10 @@ static int do_sigver_init(EVP_MD_CTX *ct 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; @@ -134,8 +137,10 @@ static int do_sigver_init(EVP_MD_CTX *ct 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 @@ -220,8 +225,10 @@ static int do_sigver_init(EVP_MD_CTX *ct 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) @@ -305,6 +312,7 @@ static int do_sigver_init(EVP_MD_CTX *ct 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); @@ -313,11 +321,13 @@ static int do_sigver_init(EVP_MD_CTX *ct 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) @@ -329,6 +339,7 @@ static int do_sigver_init(EVP_MD_CTX *ct goto err; } } +#endif /* !defined(FIPS_MODULE) */ if (ver) { if (signature->digest_verify_init == NULL) { @@ -361,6 +372,7 @@ static int do_sigver_init(EVP_MD_CTX *ct EVP_KEYMGMT_free(tmp_keymgmt); return 0; +#ifndef FIPS_MODULE legacy: /* * If we don't have the full support we need with provided methods, @@ -432,6 +444,7 @@ static int do_sigver_init(EVP_MD_CTX *ct ctx->pctx->flag_call_digest_custom = 1; ret = 1; +#endif /* !defined(FIPS_MODULE) */ end: #ifndef FIPS_MODULE @@ -474,7 +487,6 @@ int EVP_DigestVerifyInit(EVP_MD_CTX *ctx 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) { @@ -536,23 +548,29 @@ int EVP_DigestVerifyUpdate(EVP_MD_CTX *c 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; @@ -561,8 +579,10 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, 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); @@ -634,6 +654,7 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, } } return 1; +#endif /* !defined(FIPS_MODULE) */ } int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen, @@ -664,21 +685,27 @@ int EVP_DigestSign(EVP_MD_CTX *ctx, unsi 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; @@ -686,8 +713,10 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ct 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); @@ -727,6 +756,7 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ct 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, @@ -752,4 +782,3 @@ int EVP_DigestVerify(EVP_MD_CTX *ctx, co return -1; return EVP_DigestVerifyFinal(ctx, sigret, siglen); } -#endif /* FIPS_MODULE */ Index: openssl-3.1.4/providers/fips/self_test_kats.c =================================================================== --- openssl-3.1.4.orig/providers/fips/self_test_kats.c +++ openssl-3.1.4/providers/fips/self_test_kats.c @@ -450,10 +450,13 @@ static int self_test_sign(const ST_KAT_S 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; + 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, @@ -487,23 +490,26 @@ static int self_test_sign(const ST_KAT_S || 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; @@ -513,14 +519,17 @@ static int self_test_sign(const ST_KAT_S 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);