Skip to content

Commit 21a5d96

Browse files
nhormanjogme
authored andcommitted
Fix unbounded cert cache growth in cmp
If a remote user sends cmp messages to a server with a list of extraCerts and the message is rejected, the extraCerts from the message remain in the server contexts untrusted certificate stack. This exposes servers with long lived ctx objects to denial of service attacks in which an attacker sends messages intending to be rejected with a large list of additional cerificated repeatedly, forcing the server to store them indefinately. Fix it by rolling back the added extra certs if the message is rejected, using the same method we do when the context is configured to not do caching at all. Fixes openssl/srt#224 Fixes CVE-2026-63074 Reviewed-by: Milan Broz <mbroz@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.foundation> Reviewed-by: Igor Ustinov <igus@openssl.foundation> Merge-date: Mon Aug 24 12:45:55 2026
1 parent 9f2b852 commit 21a5d96

1 file changed

Lines changed: 14 additions & 1 deletion

File tree

‎crypto/cmp/cmp_vfy.c‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,7 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
666666
{
667667
OSSL_CMP_PKIHEADER *hdr;
668668
const X509_NAME *expected_sender;
669+
int num_extra_before, num_extra_after, num_added;
669670

670671
if (!ossl_assert(ctx != NULL && msg != NULL && msg->header != NULL))
671672
return 0;
@@ -700,17 +701,27 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
700701
* extraCerts because they do not belong to the protected msg part anyway.
701702
* For efficiency, the extraCerts are prepended so they get used first.
702703
*/
704+
num_extra_before = sk_X509_num(ctx->untrusted);
703705
if (!X509_add_certs(ctx->untrusted, msg->extraCerts,
704706
/* this allows self-signed certs */
705707
X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
706708
| X509_ADD_FLAG_PREPEND))
707709
return 0;
708-
710+
num_extra_after = sk_X509_num(ctx->untrusted);
711+
num_added = num_extra_after - num_extra_before;
709712
/* validate message protection */
710713
if (hdr->protectionAlg != NULL) {
711714
/* detect explicitly permitted exceptions for invalid protection */
712715
if (!OSSL_CMP_validate_msg(ctx, msg)
713716
&& (cb == NULL || (*cb)(ctx, msg, 1, cb_arg) <= 0)) {
717+
/*
718+
* remove extraCerts again if not caching
719+
* or if we failed validation above, lest a remote user
720+
* starts sending us lots of certificate in invalid messages
721+
* leading to a DOS from unbounded certificate stack growth
722+
*/
723+
while (num_added-- > 0)
724+
X509_free(sk_X509_shift(ctx->untrusted));
714725
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
715726
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_PROTECTION);
716727
return 0;
@@ -719,6 +730,8 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
719730
} else {
720731
/* detect explicitly permitted exceptions for missing protection */
721732
if (cb == NULL || (*cb)(ctx, msg, 0, cb_arg) <= 0) {
733+
while (num_added-- > 0)
734+
X509_free(sk_X509_shift(ctx->untrusted));
722735
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
723736
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PROTECTION);
724737
return 0;

0 commit comments

Comments
 (0)