diff options
author | Tomas Mraz <tomas@openssl.org> | 2021-08-25 13:50:40 +0200 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2021-08-26 16:06:57 +0200 |
commit | 78539b250b05d0721da775bf4eddc096bde5ecaa (patch) | |
tree | 1a1bef066384c4829417dbb1d333324a664397f3 /crypto/evp | |
parent | 62bae84d4587ec9a56d0ce830e36e4a5b2fa8a33 (diff) |
EVP_DigestSign/VerifyFinal: Duplicate the pctx to allow multiple calls
The legacy implementation duplicates the pctx before creating/verifying
the signature unless EVP_MD_CTX_FLAG_FINALISE is set. We have to do the
same with provided implementations.
Fixes #16321
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/16422)
Diffstat (limited to 'crypto/evp')
-rw-r--r-- | crypto/evp/m_sigver.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c index f21865a8c3..806ef3224c 100644 --- a/crypto/evp/m_sigver.c +++ b/crypto/evp/m_sigver.c @@ -400,7 +400,7 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen) { int sctx = 0, r = 0; - EVP_PKEY_CTX *pctx = ctx->pctx; + EVP_PKEY_CTX *dctx, *pctx = ctx->pctx; if (pctx == NULL || pctx->operation != EVP_PKEY_OP_SIGNCTX @@ -408,8 +408,19 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, || pctx->op.sig.signature == NULL) goto legacy; - return pctx->op.sig.signature->digest_sign_final(pctx->op.sig.algctx, - sigret, siglen, SIZE_MAX); + 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, + SIZE_MAX); + dctx = EVP_PKEY_CTX_dup(pctx); + if (dctx == NULL) + return 0; + + r = dctx->op.sig.signature->digest_sign_final(dctx->op.sig.algctx, + sigret, siglen, + SIZE_MAX); + EVP_PKEY_CTX_free(dctx); + return r; legacy: if (pctx == NULL || pctx->pmeth == NULL) { @@ -429,8 +440,7 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) r = pctx->pmeth->signctx(pctx, sigret, siglen, ctx); else { - EVP_PKEY_CTX *dctx = EVP_PKEY_CTX_dup(pctx); - + dctx = EVP_PKEY_CTX_dup(pctx); if (dctx == NULL) return 0; r = dctx->pmeth->signctx(dctx, sigret, siglen, ctx); @@ -516,7 +526,7 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, int r = 0; unsigned int mdlen = 0; int vctx = 0; - EVP_PKEY_CTX *pctx = ctx->pctx; + EVP_PKEY_CTX *dctx, *pctx = ctx->pctx; if (pctx == NULL || pctx->operation != EVP_PKEY_OP_VERIFYCTX @@ -524,8 +534,17 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, || pctx->op.sig.signature == NULL) goto legacy; - return pctx->op.sig.signature->digest_verify_final(pctx->op.sig.algctx, - sig, siglen); + if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISE) != 0) + return pctx->op.sig.signature->digest_verify_final(pctx->op.sig.algctx, + sig, siglen); + dctx = EVP_PKEY_CTX_dup(pctx); + if (dctx == NULL) + return 0; + + r = dctx->op.sig.signature->digest_verify_final(dctx->op.sig.algctx, + sig, siglen); + EVP_PKEY_CTX_free(dctx); + return r; legacy: if (pctx == NULL || pctx->pmeth == NULL) { |