]> 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:08 +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)

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 dfb844b53368fab781f3b890f2ac7b9c662aadfe..976401041a100abc5eb236fd84baf7ba18f35488 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:
@@ -474,10 +476,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:
@@ -527,11 +531,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
@@ -638,11 +644,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 {
@@ -693,10 +701,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
@@ -769,10 +779,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 {