]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Only report generic error if provider did not put an error on the error queue
authorIngo Franzki <ifranzki@linux.ibm.com>
Tue, 22 Jul 2025 13:09:27 +0000 (15:09 +0200)
committerTomas Mraz <tomas@openssl.org>
Wed, 30 Jul 2025 16:27:54 +0000 (18:27 +0200)
Commit 72351b0d18078170af270418b2d5e9fc579cb1af added code to unconditionally
put a generic error onto the error stack, if key generation, encryption,
decryption, sign, or verify fails to ensure that there is an error entry
on the error queue, even if the provider did not itself put a specific error
onto the queue.

However, this can hide error details if an application just looks at the very
last error entry and checks for specific errors. Now, the generic error is
always the last entry, and the application won't find the expected error
entry, although it would be there as second last entry. This can lead to
different application behavior in error situations than before this change.

To fix this, only add the generic error entry if the provider did not itself
add an error entry onto the queue. That way, there always is an error on the
error queue in case of a failure, but no behavior change in case the provider
emitted the error entry itself.

Closes: https://github.com/openssl/openssl/issues/27992
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/28073)

(cherry picked from commit b9ff440dd613e0c65527ef7eaf565f618979ecce)

crypto/evp/asymcipher.c
crypto/evp/keymgmt_meth.c
crypto/evp/m_sigver.c

index 975170c0aa0941a5eb0d572d60d288dd5f1be8af..c97ce338fdf8515dcb3e4d52f6994f01f0a0eda1 100644 (file)
@@ -261,10 +261,12 @@ int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
 
     cipher = ctx->op.ciph.cipher;
     desc = cipher->description != NULL ? cipher->description : "";
+    ERR_set_mark();
     ret = cipher->encrypt(ctx->op.ciph.algctx, out, outlen, (out == NULL ? 0 : *outlen), in, inlen);
-    if (ret <= 0)
+    if (ret <= 0 && ERR_count_to_mark() == 0)
         ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_ASYM_CIPHER_FAILURE,
                        "%s encrypt:%s", cipher->type_name, desc);
+    ERR_clear_last_mark();
     return ret;
 
  legacy:
@@ -309,10 +311,12 @@ int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
 
     cipher = ctx->op.ciph.cipher;
     desc = cipher->description != NULL ? cipher->description : "";
+    ERR_set_mark();
     ret = cipher->decrypt(ctx->op.ciph.algctx, out, outlen, (out == NULL ? 0 : *outlen), in, inlen);
-    if (ret <= 0)
+    if (ret <= 0 && ERR_count_to_mark() == 0)
         ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_ASYM_CIPHER_FAILURE,
                        "%s decrypt:%s", cipher->type_name, desc);
+    ERR_clear_last_mark();
 
     return ret;
 
index f54684852b7c2445ca708b32e59838b31e013ab8..f57153b2c1a1de846d29046d1752b5cb1a572147 100644 (file)
@@ -460,10 +460,12 @@ void *evp_keymgmt_gen(const EVP_KEYMGMT *keymgmt, void *genctx,
         return NULL;
     }
 
+    ERR_set_mark();
     ret = keymgmt->gen(genctx, cb, cbarg);
-    if (ret == NULL)
+    if (ret == NULL && ERR_count_to_mark() == 0)
         ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_KEYMGMT_FAILURE,
                        "%s key generation:%s", keymgmt->type_name, desc);
+    ERR_clear_last_mark();
     return ret;
 }
 
index d5df497da77014ef9f676413e57709f07ac602ad..c27ed6dbe9b26f306ac0fd8cca60d37ee4985e1c 100644 (file)
@@ -426,10 +426,12 @@ int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
         return 0;
     }
 
+    ERR_set_mark();
     ret = signature->digest_sign_update(pctx->op.sig.algctx, data, dsize);
-    if (ret <= 0)
+    if (ret <= 0 && ERR_count_to_mark() == 0)
         ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
                        "%s digest_sign_update:%s", signature->type_name, desc);
+    ERR_clear_last_mark();
     return ret;
 
  legacy:
@@ -470,10 +472,12 @@ int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
         return 0;
     }
 
+    ERR_set_mark();
     ret = signature->digest_verify_update(pctx->op.sig.algctx, data, dsize);
-    if (ret <= 0)
+    if (ret <= 0 && ERR_count_to_mark() == 0)
         ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
                        "%s digest_verify_update:%s", signature->type_name, desc);
+    ERR_clear_last_mark();
     return ret;
 
  legacy:
@@ -523,11 +527,13 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
             pctx = dctx;
     }
 
+    ERR_set_mark();
     r = signature->digest_sign_final(pctx->op.sig.algctx, sigret, siglen,
                                      sigret == NULL ? 0 : *siglen);
-    if (!r)
+    if (!r && ERR_count_to_mark() == 0)
         ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
                        "%s digest_sign_final:%s", signature->type_name, desc);
+    ERR_clear_last_mark();
     if (dctx == NULL && sigret != NULL)
         ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
     else
@@ -634,11 +640,13 @@ int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen,
 
             if (sigret != NULL)
                 ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
+            ERR_set_mark();
             ret = signature->digest_sign(pctx->op.sig.algctx, sigret, siglen,
                                          sigret == NULL ? 0 : *siglen, tbs, tbslen);
-            if (ret <= 0)
+            if (ret <= 0 && ERR_count_to_mark() == 0)
                 ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
                                "%s digest_sign:%s", signature->type_name, desc);
+            ERR_clear_last_mark();
             return ret;
         }
     } else {
@@ -689,10 +697,12 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
             pctx = dctx;
     }
 
+    ERR_set_mark();
     r = signature->digest_verify_final(pctx->op.sig.algctx, sig, siglen);
-    if (!r)
+    if (!r && ERR_count_to_mark() == 0)
         ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
                        "%s digest_verify_final:%s", signature->type_name, desc);
+    ERR_clear_last_mark();
     if (dctx == NULL)
         ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
     else
@@ -765,10 +775,12 @@ int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
             int ret;
 
             ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
+            ERR_set_mark();
             ret = signature->digest_verify(pctx->op.sig.algctx, sigret, siglen, tbs, tbslen);
-            if (ret <= 0)
+            if (ret <= 0 && ERR_count_to_mark() == 0)
                 ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
                                "%s digest_verify:%s", signature->type_name, desc);
+            ERR_clear_last_mark();
             return ret;
         }
     } else {