Bug#1134196: bouncycastle: proposed bullseye LTS fix for CVE-2026-5588

James Montgomery james_montgomery at disroot.org
Mon Apr 20 03:04:33 BST 2026


Hi,

I prepared a candidate bullseye-security update for CVE-2026-5588:
bouncycastle 1.68-2+deb11u1.

Summary:
- backports upstream commit 656bae0dbd9b1521f840521ff786e78749fe3057
- adds a regression test for an empty composite signature sequence
- clean bullseye pbuilder build passed
- targeted runtime check against the built libbcprov/libbcpkix jars passed
- lintian reports only pre-existing doc-package embedded JavaScript warnings
- no autopkgtest exists for this source package

I am new to LTS contribution and not a DD, so I have not claimed
bouncycastle in dla-needed.txt or attempted any upload. I am planning to
ask debian-lts at lists.debian.org whether this is useful for review or
sponsorship.

The debdiff is attached.

Regards,
James
-------------- next part --------------
diff -Nru bouncycastle-1.68/debian/changelog bouncycastle-1.68/debian/changelog
--- bouncycastle-1.68/debian/changelog	2021-05-14 02:14:07.000000000 +0000
+++ bouncycastle-1.68/debian/changelog	2026-04-20 01:18:25.000000000 +0000
@@ -1,3 +1,10 @@
+bouncycastle (1.68-2+deb11u1) bullseye-security; urgency=medium
+
+  * Non-maintainer upload.
+  * Fix CVE-2026-5588: reject empty composite signature sequences.
+
+ -- James Montgomery <james_montgomery at disroot.org>  Mon, 20 Apr 2026 01:18:25 +0000
+
 bouncycastle (1.68-2) unstable; urgency=medium
 
   * Team upload.
@@ -495,4 +502,3 @@
   * Initial release (Closes: #234048)
 
  -- Charles Fry <debian at frogcircus.org>  Mon, 19 Sep 2005 08:02:36 -0400
-
diff -Nru bouncycastle-1.68/debian/patches/CVE-2026-5588.patch bouncycastle-1.68/debian/patches/CVE-2026-5588.patch
--- bouncycastle-1.68/debian/patches/CVE-2026-5588.patch	1970-01-01 00:00:00.000000000 +0000
+++ bouncycastle-1.68/debian/patches/CVE-2026-5588.patch	2026-04-20 01:13:49.000000000 +0000
@@ -0,0 +1,115 @@
+Description: reject empty composite signature sequences
+ CompositeVerifier accepted an empty ASN.1 sequence as a valid composite
+ signature because no component signature failed verification. Track whether
+ at least one component signature was checked and require that condition for
+ successful verification.
+Origin: upstream, https://github.com/bcgit/bc-java/commit/656bae0dbd9b1521f840521ff786e78749fe3057
+Bug-Debian: https://bugs.debian.org/1134196
+Applied-Upstream: 1.84, commit:656bae0dbd9b1521f840521ff786e78749fe3057
+
+--- bouncycastle-1.68.orig/pkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java
++++ bouncycastle-1.68/pkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java
+@@ -429,17 +429,19 @@ public class JcaContentVerifierProviderB
+             {
+                 ASN1Sequence sigSeq = ASN1Sequence.getInstance(expected);
+                 boolean failed = false;
++                boolean atLeastOneChecked = false;
+                 for (int i = 0; i != sigSeq.size(); i++)
+                 {
+                     if (sigs[i] != null)
+                     {
++                        atLeastOneChecked = true;
+                         if (!sigs[i].verify(DERBitString.getInstance(sigSeq.getObjectAt(i)).getBytes()))
+                         {
+                             failed = true;
+                         }
+                     }
+                 }
+-                return !failed;
++                return !failed & atLeastOneChecked;
+             }
+             catch (SignatureException e)
+             {
+@@ -447,4 +449,4 @@ public class JcaContentVerifierProviderB
+             }
+         }
+     }
+-}
+\ No newline at end of file
++}
+--- bouncycastle-1.68.orig/pkix/src/test/java/org/bouncycastle/cert/cmp/test/AllTests.java
++++ bouncycastle-1.68/pkix/src/test/java/org/bouncycastle/cert/cmp/test/AllTests.java
+@@ -17,6 +17,8 @@ import junit.framework.TestCase;
+ import junit.framework.TestSuite;
+ import org.bouncycastle.asn1.ASN1Integer;
+ import org.bouncycastle.asn1.ASN1Primitive;
++import org.bouncycastle.asn1.DERBitString;
++import org.bouncycastle.asn1.DERNull;
+ import org.bouncycastle.asn1.DERSequence;
+ import org.bouncycastle.asn1.cmp.CMPCertificate;
+ import org.bouncycastle.asn1.cmp.CertConfirmContent;
+@@ -25,6 +27,7 @@ import org.bouncycastle.asn1.cmp.CertRep
+ import org.bouncycastle.asn1.cmp.CertResponse;
+ import org.bouncycastle.asn1.cmp.CertifiedKeyPair;
+ import org.bouncycastle.asn1.cmp.PKIBody;
++import org.bouncycastle.asn1.cmp.PKIHeaderBuilder;
+ import org.bouncycastle.asn1.cmp.PKIMessage;
+ import org.bouncycastle.asn1.cmp.PKIStatus;
+ import org.bouncycastle.asn1.cmp.PKIStatusInfo;
+@@ -34,9 +37,12 @@ import org.bouncycastle.asn1.crmf.Encryp
+ import org.bouncycastle.asn1.crmf.EncryptedValue;
+ import org.bouncycastle.asn1.crmf.ProofOfPossession;
+ import org.bouncycastle.asn1.crmf.SubsequentMessage;
++import org.bouncycastle.asn1.misc.MiscObjectIdentifiers;
+ import org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo;
++import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+ import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
+ import org.bouncycastle.asn1.x500.X500Name;
++import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+ import org.bouncycastle.asn1.x509.GeneralName;
+ import org.bouncycastle.cert.CertException;
+ import org.bouncycastle.cert.X509CertificateHolder;
+@@ -330,6 +336,36 @@ public class AllTests
+         doNotBeforeNotAfterTest(kp, new Date(0L), null);
+     }
+ 
++    public void testForgedComposite()
++        throws Exception
++    {
++        KeyPairGenerator kGen = KeyPairGenerator.getInstance("RSA", BC);
++        kGen.initialize(2048);
++        KeyPair kp = kGen.generateKeyPair();
++
++        ContentVerifierProvider verifier =
++            new JcaContentVerifierProviderBuilder().build(kp.getPublic());
++
++        GeneralName sender = new GeneralName(new X500Name("CN=attacker"));
++        GeneralName recipient = new GeneralName(new X500Name("CN=victim"));
++        PKIBody body = new PKIBody(PKIBody.TYPE_CONFIRM, DERNull.INSTANCE);
++
++        AlgorithmIdentifier innerAlg = new AlgorithmIdentifier(
++            PKCSObjectIdentifiers.sha256WithRSAEncryption, DERNull.INSTANCE);
++        AlgorithmIdentifier compositeAlg = new AlgorithmIdentifier(
++            MiscObjectIdentifiers.id_alg_composite,
++            new DERSequence(innerAlg));
++
++        PKIHeaderBuilder headerBuilder = new PKIHeaderBuilder(2, sender, recipient);
++        headerBuilder.setProtectionAlg(compositeAlg);
++
++        DERBitString emptySigSeq = new DERBitString(new DERSequence().getEncoded());
++        PKIMessage forged = new PKIMessage(headerBuilder.build(), body, emptySigSeq);
++        ProtectedPKIMessage forgedPM = new ProtectedPKIMessage(new GeneralPKIMessage(forged));
++
++        assertFalse(forgedPM.verify(verifier));
++    }
++
+     private void doNotBeforeNotAfterTest(KeyPair kp, Date notBefore, Date notAfter)
+         throws Exception
+     {
+@@ -405,4 +441,4 @@ public class AllTests
+             throw new RuntimeException(e.toString());
+         }
+     }
+-}
+\ No newline at end of file
++}
diff -Nru bouncycastle-1.68/debian/patches/series bouncycastle-1.68/debian/patches/series
--- bouncycastle-1.68/debian/patches/series	2021-05-14 02:14:07.000000000 +0000
+++ bouncycastle-1.68/debian/patches/series	2026-04-20 01:13:25.000000000 +0000
@@ -1,3 +1,4 @@
 02_index.patch
 fix-encoding.patch
 backward-compatibility.patch
+CVE-2026-5588.patch


More information about the pkg-java-maintainers mailing list