summaryrefslogtreecommitdiffstats
path: root/crypto/evp
diff options
context:
space:
mode:
authorTomas Mraz <tomas@openssl.org>2021-08-25 13:50:40 +0200
committerTomas Mraz <tomas@openssl.org>2021-08-26 16:06:57 +0200
commit78539b250b05d0721da775bf4eddc096bde5ecaa (patch)
tree1a1bef066384c4829417dbb1d333324a664397f3 /crypto/evp
parent62bae84d4587ec9a56d0ce830e36e4a5b2fa8a33 (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.c35
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) {