CVE-2025-8916
Description
Allocation of Resources Without Limits or Throttling vulnerability in Legion of the Bouncy Castle Inc. BC Java bcpkix on All (API modules), Legion of the Bouncy Castle Inc. BC Java bcprov on All (API modules), Legion of the Bouncy Castle Inc. BCPKIX FIPS bcpkix-fips on All (API modules) allows Excessive Allocation. This vulnerability is associated with program files https://github.Com/bcgit/bc-java/blob/main/pkix/src/main/java/org/bouncycastle/pkix/jcajce/PKIXCertPathReviewer.Java, https://github.Com/bcgit/bc-java/blob/main/prov/src/main/java/org/bouncycastle/x509/PKIXCertPathReviewer.Java.
This issue affects BC Java: from 1.44 through 1.78; BC Java: from 1.44 through 1.78; BCPKIX FIPS: from 1.0.0 through 1.0.7, from 2.0.0 through 2.0.7.
Affected products
1Patches
2ff444a479942Limit alt names also in deprecated CertPath reviewer
3 files changed · +21 −84
pkix/src/main/java/org/bouncycastle/pkix/jcajce/PKIXCertPathReviewer.java+6 −1 modified@@ -500,7 +500,12 @@ private void checkNameConstraints() ErrorBundle msg = createErrorBundle("CertPathReviewer.subjAltNameExtError"); throw new CertPathReviewerException(msg,ae,certPath,index); } - + + /* + * TODO RFC3280CertPathUtilities (used in CertPath validation) has a block checking name + * constraints against subject's EmailAddress, which could be worth adding here too. + */ + if (altName != null) { if (altName.size() > NAME_CHECK_MAX)
prov/src/main/java/org/bouncycastle/jce/provider/RFC3280CertPathUtilities.java+5 −0 modified@@ -1160,6 +1160,11 @@ protected static void processCertBC( } if (altName != null) { + /* + * NOTE: PKIXCertPathReviewer limits the number of alternative names, to avoid a denial-of-service + * attack. That does not appear to be an issue for validation, so no limit is applied. + */ + GeneralName[] genNames = null; try {
prov/src/main/java/org/bouncycastle/x509/PKIXCertPathReviewer.java+10 −83 modified@@ -91,7 +91,9 @@ public class PKIXCertPathReviewer extends CertPathValidatorUtilities private static final String AUTH_INFO_ACCESS = Extension.authorityInfoAccess.getId(); private static final String RESOURCE_NAME = "org.bouncycastle.x509.CertPathReviewerMessages"; - + + private static final int NAME_CHECK_MAX = (1 << 10); + // input parameters protected CertPath certPath; @@ -501,9 +503,15 @@ private void checkNameConstraints() ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.subjAltNameExtError"); throw new CertPathReviewerException(msg,ae,certPath,index); } - + if (altName != null) { + if (altName.size() > NAME_CHECK_MAX) + { + ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.subjAltNameExtError"); + throw new CertPathReviewerException(msg,certPath,index); + } + for (int j = 0; j < altName.size(); j++) { GeneralName name = GeneralName.getInstance(altName.getObjectAt(j)); @@ -519,87 +527,6 @@ private void checkNameConstraints() new Object[] {new UntrustedInput(name)}); throw new CertPathReviewerException(msg,cpve,certPath,index); } -// switch(o.getTagNo()) TODO - move resources to PKIXNameConstraints -// { -// case 1: -// String email = ASN1IA5String.getInstance(o, true).getString(); -// -// try -// { -// checkPermittedEmail(permittedSubtreesEmail, email); -// } -// catch (CertPathValidatorException cpve) -// { -// ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.notPermittedEmail", -// new Object[] {new UntrustedInput(email)}); -// throw new CertPathReviewerException(msg,cpve,certPath,index); -// } -// -// try -// { -// checkExcludedEmail(excludedSubtreesEmail, email); -// } -// catch (CertPathValidatorException cpve) -// { -// ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.excludedEmail", -// new Object[] {new UntrustedInput(email)}); -// throw new CertPathReviewerException(msg,cpve,certPath,index); -// } -// -// break; -// case 4: -// ASN1Sequence altDN = ASN1Sequence.getInstance(o, true); -// -// try -// { -// checkPermittedDN(permittedSubtreesDN, altDN); -// } -// catch (CertPathValidatorException cpve) -// { -// X509Name altDNName = new X509Name(altDN); -// ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.notPermittedDN", -// new Object[] {new UntrustedInput(altDNName)}); -// throw new CertPathReviewerException(msg,cpve,certPath,index); -// } -// -// try -// { -// checkExcludedDN(excludedSubtreesDN, altDN); -// } -// catch (CertPathValidatorException cpve) -// { -// X509Name altDNName = new X509Name(altDN); -// ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.excludedDN", -// new Object[] {new UntrustedInput(altDNName)}); -// throw new CertPathReviewerException(msg,cpve,certPath,index); -// } -// -// break; -// case 7: -// byte[] ip = ASN1OctetString.getInstance(o, true).getOctets(); -// -// try -// { -// checkPermittedIP(permittedSubtreesIP, ip); -// } -// catch (CertPathValidatorException cpve) -// { -// ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.notPermittedIP", -// new Object[] {IPtoString(ip)}); -// throw new CertPathReviewerException(msg,cpve,certPath,index); -// } -// -// try -// { -// checkExcludedIP(excludedSubtreesIP, ip); -// } -// catch (CertPathValidatorException cpve) -// { -// ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.excludedIP", -// new Object[] {IPtoString(ip)}); -// throw new CertPathReviewerException(msg,cpve,certPath,index); -// } -// } } } }
310b30a4fbf3added cap on size of subject alt name extension reviewer will accept.
3 files changed · +131 −81
pkix/src/main/java/org/bouncycastle/pkix/jcajce/PKIXCertPathReviewer.java+8 −81 modified@@ -89,6 +89,8 @@ public class PKIXCertPathReviewer extends CertPathValidatorUtilities private static final String RESOURCE_NAME = "org.bouncycastle.pkix.CertPathReviewerMessages"; + private static final int NAME_CHECK_MAX = (1 << 10); + // input parameters protected CertPath certPath; @@ -501,6 +503,12 @@ private void checkNameConstraints() if (altName != null) { + if (altName.size() > NAME_CHECK_MAX) + { + ErrorBundle msg = createErrorBundle("CertPathReviewer.subjAltNameExtError"); + throw new CertPathReviewerException(msg,certPath,index); + } + for (int j = 0; j < altName.size(); j++) { GeneralName name = GeneralName.getInstance(altName.getObjectAt(j)); @@ -516,87 +524,6 @@ private void checkNameConstraints() new Object[] {new UntrustedInput(name)}); throw new CertPathReviewerException(msg,cpve,certPath,index); } -// switch(o.getTagNo()) TODO - move resources to PKIXNameConstraints -// { -// case 1: -// String email = ASN1IA5String.getInstance(o, true).getString(); -// -// try -// { -// checkPermittedEmail(permittedSubtreesEmail, email); -// } -// catch (CertPathValidatorException cpve) -// { -// ErrorBundle msg = createErrorBundle("CertPathReviewer.notPermittedEmail", -// new Object[] {new UntrustedInput(email)}); -// throw new CertPathReviewerException(msg,cpve,certPath,index); -// } -// -// try -// { -// checkExcludedEmail(excludedSubtreesEmail, email); -// } -// catch (CertPathValidatorException cpve) -// { -// ErrorBundle msg = createErrorBundle("CertPathReviewer.excludedEmail", -// new Object[] {new UntrustedInput(email)}); -// throw new CertPathReviewerException(msg,cpve,certPath,index); -// } -// -// break; -// case 4: -// ASN1Sequence altDN = ASN1Sequence.getInstance(o, true); -// -// try -// { -// checkPermittedDN(permittedSubtreesDN, altDN); -// } -// catch (CertPathValidatorException cpve) -// { -// X509Name altDNName = new X509Name(altDN); -// ErrorBundle msg = createErrorBundle("CertPathReviewer.notPermittedDN", -// new Object[] {new UntrustedInput(altDNName)}); -// throw new CertPathReviewerException(msg,cpve,certPath,index); -// } -// -// try -// { -// checkExcludedDN(excludedSubtreesDN, altDN); -// } -// catch (CertPathValidatorException cpve) -// { -// X509Name altDNName = new X509Name(altDN); -// ErrorBundle msg = createErrorBundle("CertPathReviewer.excludedDN", -// new Object[] {new UntrustedInput(altDNName)}); -// throw new CertPathReviewerException(msg,cpve,certPath,index); -// } -// -// break; -// case 7: -// byte[] ip = ASN1OctetString.getInstance(o, true).getOctets(); -// -// try -// { -// checkPermittedIP(permittedSubtreesIP, ip); -// } -// catch (CertPathValidatorException cpve) -// { -// ErrorBundle msg = createErrorBundle("CertPathReviewer.notPermittedIP", -// new Object[] {IPtoString(ip)}); -// throw new CertPathReviewerException(msg,cpve,certPath,index); -// } -// -// try -// { -// checkExcludedIP(excludedSubtreesIP, ip); -// } -// catch (CertPathValidatorException cpve) -// { -// ErrorBundle msg = createErrorBundle("CertPathReviewer.excludedIP", -// new Object[] {IPtoString(ip)}); -// throw new CertPathReviewerException(msg,cpve,certPath,index); -// } -// } } } }
pkix/src/test/java/org/bouncycastle/pkix/test/AllTests.java+1 −0 modified@@ -22,6 +22,7 @@ public static Test suite() suite.addTestSuite(CheckerTest.class); suite.addTestSuite(RevocationTest.class); + suite.addTestSuite(CheckNameConstraintsTest.class); return new BCTestSetup(suite); }
pkix/src/test/java/org/bouncycastle/pkix/test/CheckNameConstraintsTest.java+122 −0 added@@ -0,0 +1,122 @@ +package org.bouncycastle.pkix.test; + +import java.security.Security; +import java.security.cert.CertPath; +import java.security.cert.CertPathBuilder; +import java.security.cert.CertPathValidator; +import java.security.cert.CertStore; +import java.security.cert.CertificateFactory; +import java.security.cert.CollectionCertStoreParameters; +import java.security.cert.PKIXBuilderParameters; +import java.security.cert.PKIXCertPathBuilderResult; +import java.security.cert.PKIXParameters; +import java.security.cert.TrustAnchor; +import java.security.cert.X509CertSelector; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import junit.framework.TestCase; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.pkix.jcajce.PKIXCertPathReviewer; +import org.bouncycastle.test.TestResourceFinder; + +public class CheckNameConstraintsTest + extends TestCase +{ + public void testPKIXCertPathReviewer() + throws Exception + { + Security.addProvider(new BouncyCastleProvider()); + + CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC"); + + X509Certificate root = (X509Certificate) cf.generateCertificate(TestResourceFinder.findTestResource("pkix", "mal-root.crt")); + X509Certificate ca1 = (X509Certificate) cf.generateCertificate(TestResourceFinder.findTestResource("pkix", "mal-ca1.crt")); + X509Certificate ca2 = (X509Certificate) cf.generateCertificate(TestResourceFinder.findTestResource("pkix", "mal-ca2.crt")); + X509Certificate leaf = (X509Certificate) cf.generateCertificate(TestResourceFinder.findTestResource("pkix", "mal-leaf.crt")); + + List certchain = new ArrayList(); + certchain.add(root); + certchain.add(ca1); + certchain.add(ca2); + certchain.add(leaf); + + CertPath cp = cf.generateCertPath(certchain); + + Set trust = new HashSet(); + trust.add(new TrustAnchor(root, null)); + PKIXParameters param = new PKIXParameters(trust); + + PKIXCertPathReviewer certPathReviewer = new PKIXCertPathReviewer(); + certPathReviewer.init(cp, param); + + assertFalse(certPathReviewer.isValidCertPath()); // hit + } + + public void testPKIXCertPathBuilder() + throws Exception + { + Security.addProvider(new BouncyCastleProvider()); + + CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC"); + X509Certificate rootCert = (X509Certificate) cf.generateCertificate(TestResourceFinder.findTestResource("pkix", "mal-root.crt")); + X509Certificate endCert = (X509Certificate) cf.generateCertificate(TestResourceFinder.findTestResource("pkix", "mal-ca1.crt")); + + // create CertStore to support path building + List list = new ArrayList(); + list.add(endCert); + + CollectionCertStoreParameters params = new CollectionCertStoreParameters(list); + CertStore store = CertStore.getInstance("Collection", params, "BC"); + + // build the path + CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC"); + X509CertSelector pathConstraints = new X509CertSelector(); + + pathConstraints.setCertificate(endCert); + + PKIXBuilderParameters buildParams = new PKIXBuilderParameters(Collections.singleton(new TrustAnchor(rootCert, null)), pathConstraints); + + buildParams.addCertStore(store); + buildParams.setDate(new Date()); + buildParams.setRevocationEnabled(false); + + PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult)builder.build(buildParams); + CertPath path = result.getCertPath(); + + if (path.getCertificates().size() != 1) + { + fail("wrong number of certs in testPKIXCertPathBuilder path"); + } + } + + public void testPKIXCertPathValidator() + throws Exception + { + Security.addProvider(new BouncyCastleProvider()); + + CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC"); + + X509Certificate rootCert = (X509Certificate) cf.generateCertificate(TestResourceFinder.findTestResource("pkix", "mal-root.crt")); + X509Certificate endCert = (X509Certificate) cf.generateCertificate(TestResourceFinder.findTestResource("pkix", "mal-ca1.crt")); + + List list = new ArrayList(); + list.add(endCert); + + CertPath certPath = cf.generateCertPath(list); + + Set trust = new HashSet(); + trust.add(new TrustAnchor(rootCert, null)); + + CertPathValidator cpv = CertPathValidator.getInstance("PKIX", "BC"); + PKIXParameters param = new PKIXParameters(trust); + param.setRevocationEnabled(false); + + cpv.validate(certPath, param); + } +}
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-4cx2-fc23-5wg6ghsaADVISORY
- cert-portal.siemens.com/productcert/html/ssa-032379.htmlnvd
- github.com/bcgit/bc-java/commit/310b30a4fbf36d13f6cc201ffa7771715641e67eghsa
- github.com/bcgit/bc-java/commit/ff444a479942d88de64004dc82c3ee32a9e9075aghsa
- nvd.nist.gov/vuln/detail/CVE-2025-8916ghsa
News mentions
1- Siemens SIMATICCISA Alerts