Do not fail if ctx dup does not succeed
authorSimo Sorce <simo@redhat.com>
Fri, 24 Feb 2023 00:51:27 +0000 (19:51 -0500)
committerPauli <pauli@openssl.org>
Tue, 14 Mar 2023 21:42:52 +0000 (08:42 +1100)
If the ctx was *really* needed we'll probably fail later with an error
anyway, so no point in failing immediately.

Document that this behavior is dependent on the provider used to
implement the signature/verification.

Signed-off-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/20375)

crypto/evp/m_sigver.c
crypto/evp/p_sign.c
crypto/evp/p_verify.c
doc/man3/EVP_DigestSignInit.pod
doc/man3/EVP_DigestVerifyInit.pod
doc/man3/EVP_SignInit.pod
doc/man3/EVP_VerifyInit.pod

index 630d339c35de40e9f862e995f7c9befc16be531d..68ae95705812c209a931c3b3e6957ec8480e0b7f 100644 (file)
@@ -462,7 +462,7 @@ 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;
+    EVP_PKEY_CTX *dctx = NULL, *pctx = ctx->pctx;
 
     if (pctx == NULL
             || pctx->operation != EVP_PKEY_OP_SIGNCTX
@@ -470,17 +470,15 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
             || pctx->op.sig.signature == NULL)
         goto legacy;
 
-    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);
-    dctx = EVP_PKEY_CTX_dup(pctx);
-    if (dctx == NULL)
-        return 0;
-
-    r = dctx->op.sig.signature->digest_sign_final(dctx->op.sig.algctx,
+    if (sigret != NULL && (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) == 0) {
+        /* try dup */
+        dctx = EVP_PKEY_CTX_dup(pctx);
+        if (dctx != NULL)
+            pctx = dctx;
+    }
+    r = pctx->op.sig.signature->digest_sign_final(pctx->op.sig.algctx,
                                                   sigret, siglen,
-                                                  *siglen);
+                                                  sigret == NULL ? 0 : *siglen);
     EVP_PKEY_CTX_free(dctx);
     return r;
 
@@ -589,7 +587,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 *dctx, *pctx = ctx->pctx;
+    EVP_PKEY_CTX *dctx = NULL, *pctx = ctx->pctx;
 
     if (pctx == NULL
             || pctx->operation != EVP_PKEY_OP_VERIFYCTX
@@ -597,14 +595,13 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
             || pctx->op.sig.signature == NULL)
         goto legacy;
 
-    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,
+    if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISE) == 0) {
+        /* try dup */
+        dctx = EVP_PKEY_CTX_dup(pctx);
+        if (dctx != NULL)
+            pctx = dctx;
+    }
+    r = pctx->op.sig.signature->digest_verify_final(pctx->op.sig.algctx,
                                                     sig, siglen);
     EVP_PKEY_CTX_free(dctx);
     return r;
index 4eb34db267e5deff8c88ace86dd80da009f8497e..ae0de57202a109b7f92f7575335ac36a1415b02a 100644 (file)
@@ -39,6 +39,8 @@ int EVP_SignFinal_ex(EVP_MD_CTX *ctx, unsigned char *sigret,
         rv = EVP_MD_CTX_copy_ex(tmp_ctx, ctx);
         if (rv)
             rv = EVP_DigestFinal_ex(tmp_ctx, m, &m_len);
+        else
+            rv = EVP_DigestFinal_ex(ctx, m, &m_len);
         EVP_MD_CTX_free(tmp_ctx);
         if (!rv)
             return 0;
index eb5084f83917f7049a528479f35e9c9a8d15d683..8478e643dd858e40743160f76e4dee5eefc9a0ae 100644 (file)
@@ -37,6 +37,8 @@ int EVP_VerifyFinal_ex(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
         rv = EVP_MD_CTX_copy_ex(tmp_ctx, ctx);
         if (rv)
             rv = EVP_DigestFinal_ex(tmp_ctx, m, &m_len);
+        else
+            rv = EVP_DigestFinal_ex(ctx, m, &m_len);
         EVP_MD_CTX_free(tmp_ctx);
         if (!rv)
             return 0;
index fe4a68618405b9578a5edcde9c0f62ed3e43c62c..f38eefcbbf78652f73a75137fdef0e684c8db0ec 100644 (file)
@@ -166,6 +166,13 @@ external circumstances (see L<RAND(7)>), the operation will fail.
 The call to EVP_DigestSignFinal() internally finalizes a copy of the digest
 context. This means that calls to EVP_DigestSignUpdate() and
 EVP_DigestSignFinal() can be called later to digest and sign additional data.
+Applications may disable this behavior by setting the EVP_MD_CTX_FLAG_FINALISE
+context flag via L<EVP_MD_CTX_set_flags(3)>.
+
+Note that not all providers support continuation, in case the selected
+provider does not allow to duplicate contexts EVP_DigestSignFinal() will
+finalize the digest context and attempting to process additional data via
+EVP_DigestSignUpdate() will result in an error.
 
 EVP_DigestSignInit() and EVP_DigestSignInit_ex() functions can be called
 multiple times on a context and the parameters set by previous calls should be
index d4bb8163d1f8def45872ff7c507bcff808ffe08c..0dc8151a90a1395b08956d87097564b8ad5327eb 100644 (file)
@@ -154,7 +154,14 @@ external circumstances (see L<RAND(7)>), the operation will fail.
 
 The call to EVP_DigestVerifyFinal() internally finalizes a copy of the digest
 context. This means that EVP_VerifyUpdate() and EVP_VerifyFinal() can
-be called later to digest and verify additional data.
+be called later to digest and verify additional data. Applications may disable
+this behavior by setting the EVP_MD_CTX_FLAG_FINALISE context flag via
+L<EVP_MD_CTX_set_flags(3)>.
+
+Note that not all providers support continuation, in case the selected
+provider does not allow to duplicate contexts EVP_DigestVerifyFinal() will
+finalize the digest context and attempting to process additional data via
+EVP_DigestVerifyUpdate() will result in an error.
 
 EVP_DigestVerifyInit() and EVP_DigestVerifyInit_ex() functions can be called
 multiple times on a context and the parameters set by previous calls should be
index 11832ff7618028ebef792e1aae8f24cac4f07cf6..c274ad9917fbdd5de78fd60e85a607c726df5134 100644 (file)
@@ -66,12 +66,19 @@ due to external circumstances (see L<RAND(7)>), the operation will fail.
 
 The call to EVP_SignFinal() internally finalizes a copy of the digest context.
 This means that calls to EVP_SignUpdate() and EVP_SignFinal() can be called
-later to digest and sign additional data.
+later to digest and sign additional data.cApplications may disable this
+behavior by setting the EVP_MD_CTX_FLAG_FINALISE context flag via
+L<EVP_MD_CTX_set_flags(3)>.
 
 Since only a copy of the digest context is ever finalized the context must
 be cleaned up after use by calling EVP_MD_CTX_free() or a memory leak
 will occur.
 
+Note that not all providers support continuation, in case the selected
+provider does not allow to duplicate contexts EVP_SignFinal() will
+finalize the digest context and attempting to process additional data via
+EVP_SignUpdate() will result in an error.
+
 =head1 BUGS
 
 Older versions of this documentation wrongly stated that calls to
index a6d5772c3b83cf3058f7f411bf3ce7c5331d7816..f05b9135bfc1f47b02cc0d30c4aed543438d30c5 100644 (file)
@@ -62,12 +62,19 @@ transparent to the algorithm used and much more flexible.
 
 The call to EVP_VerifyFinal() internally finalizes a copy of the digest context.
 This means that calls to EVP_VerifyUpdate() and EVP_VerifyFinal() can be called
-later to digest and verify additional data.
+later to digest and verify additional data. Applications may disable this
+behavior by setting the EVP_MD_CTX_FLAG_FINALISE context flag via
+L<EVP_MD_CTX_set_flags(3)>.
 
 Since only a copy of the digest context is ever finalized the context must
 be cleaned up after use by calling EVP_MD_CTX_free() or a memory leak
 will occur.
 
+Note that not all providers support continuation, in case the selected
+provider does not allow to duplicate contexts EVP_VerifyFinal() will
+finalize the digest context and attempting to process additional data via
+EVP_VerifyUpdate() will result in an error.
+
 =head1 BUGS
 
 Older versions of this documentation wrongly stated that calls to