From: Ingo Franzki Date: Tue, 22 Jul 2025 13:09:27 +0000 (+0200) Subject: Only report generic error if provider did not put an error on the error queue X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b9ff440dd613e0c65527ef7eaf565f618979ecce;p=thirdparty%2Fopenssl.git Only report generic error if provider did not put an error on the error queue 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 Reviewed-by: Dmitry Belyavskiy Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/28073) --- diff --git a/crypto/evp/asymcipher.c b/crypto/evp/asymcipher.c index 975170c0aa0..c97ce338fdf 100644 --- a/crypto/evp/asymcipher.c +++ b/crypto/evp/asymcipher.c @@ -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; diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c index f54684852b7..f57153b2c1a 100644 --- a/crypto/evp/keymgmt_meth.c +++ b/crypto/evp/keymgmt_meth.c @@ -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; } diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c index dfb844b5336..976401041a1 100644 --- a/crypto/evp/m_sigver.c +++ b/crypto/evp/m_sigver.c @@ -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 {