From d541e54fbb78129cb42ea444c64d75449741509f Mon Sep 17 00:00:00 2001 From: MaxPatri Date: Fri, 26 Sep 2025 13:34:23 +0300 Subject: [PATCH 1/2] CmsSigner: dispose X509Chain --- .../Security/Cryptography/Pkcs/CmsSigner.cs | 80 +++++++++++-------- 1 file changed, 46 insertions(+), 34 deletions(-) diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs index 312e25dc1affc5..474318f811277e 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs @@ -449,54 +449,66 @@ internal SignerInfoAsn Sign( else if (IncludeOption != X509IncludeOption.None) { X509Chain chain = new X509Chain(); - chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags; - chain.ChainPolicy.VerificationTime = Certificate!.NotBefore; - - if (!chain.Build(Certificate!)) + try { - foreach (X509ChainStatus status in chain.ChainStatus) + chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; + chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags; + chain.ChainPolicy.VerificationTime = Certificate!.NotBefore; + + if (!chain.Build(Certificate!)) { - if (status.Status == X509ChainStatusFlags.PartialChain) + foreach (X509ChainStatus status in chain.ChainStatus) { - if (chain.ChainElements.Count == 0) + if (status.Status == X509ChainStatusFlags.PartialChain) { - // On Android, we will fail with PartialChain to build a cert chain - // even if the failure is an untrusted root cert since the underlying platform - // does not provide a way to distinguish the failure. - // In that case, just use the provided cert. - certs.Add(Certificate!); - } - else - { - throw new CryptographicException(SR.Cryptography_Cms_IncompleteCertChain); + if (chain.ChainElements.Count == 0) + { + // On Android, we will fail with PartialChain to build a cert chain + // even if the failure is an untrusted root cert since the underlying platform + // does not provide a way to distinguish the failure. + // In that case, just use the provided cert. + certs.Add(Certificate!); + } + else + { + throw new CryptographicException(SR.Cryptography_Cms_IncompleteCertChain); + } } } } - } - X509ChainElementCollection elements = chain.ChainElements; - int count = elements.Count; - int last = count - 1; + X509ChainElementCollection elements = chain.ChainElements; + int count = elements.Count; + int last = count - 1; - if (last == 0) - { - // If there's always one cert treat it as EE, not root. - last = -1; - } + if (last == 0) + { + // If there's always one cert treat it as EE, not root. + last = -1; + } - for (int i = 0; i < count; i++) - { - X509Certificate2 cert = elements[i].Certificate; + for (int i = 0; i < count; i++) + { + X509Certificate2 cert = elements[i].Certificate; + + if (i == last && + IncludeOption == X509IncludeOption.ExcludeRoot && + cert.SubjectName.RawData.AsSpan().SequenceEqual(cert.IssuerName.RawData)) + { + break; + } - if (i == last && - IncludeOption == X509IncludeOption.ExcludeRoot && - cert.SubjectName.RawData.AsSpan().SequenceEqual(cert.IssuerName.RawData)) + certs.Add(cert); + } + } + finally + { + for (int i = 0; i < chain.ChainElements.Count; i++) { - break; + chain.ChainElements[i].Certificate.Dispose(); } - certs.Add(cert); + chain.Dispose(); } } } From 7367d68b4a523ff7cd4791bcc38f7c0c9042dd39 Mon Sep 17 00:00:00 2001 From: MaxPatri Date: Tue, 30 Sep 2025 10:27:47 +0300 Subject: [PATCH 2/2] Dispose only chain --- .../src/System/Security/Cryptography/Pkcs/CmsSigner.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs index 474318f811277e..947e3698f4d739 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs @@ -503,11 +503,6 @@ internal SignerInfoAsn Sign( } finally { - for (int i = 0; i < chain.ChainElements.Count; i++) - { - chain.ChainElements[i].Certificate.Dispose(); - } - chain.Dispose(); } }