diff --git a/CVE-2025-14813-701686cb.patch b/CVE-2025-14813-701686cb.patch new file mode 100644 index 0000000000000000000000000000000000000000..4d0a456ba7548e3ef8975f4482692913f04ea938 --- /dev/null +++ b/CVE-2025-14813-701686cb.patch @@ -0,0 +1,43 @@ +From 701686cb0184cd9ae103c801b3581fdf95c6d4f3 Mon Sep 17 00:00:00 2001 +From: David Hook +Date: Wed, 17 Dec 2025 11:58:12 +1100 +Subject: [PATCH] fixed one off error in G3413CTRBlockCipher + +--- + .../org/bouncycastle/crypto/modes/G3413CTRBlockCipher.java | 4 +--- + .../test/java/org/bouncycastle/crypto/test/GOST3412Test.java | 2 +- + 2 files changed, 2 insertions(+), 4 deletions(-) + +diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/G3413CTRBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/G3413CTRBlockCipher.java +index f524c01895..e3dad4ec75 100644 +--- a/core/src/main/java/org/bouncycastle/crypto/modes/G3413CTRBlockCipher.java ++++ b/core/src/main/java/org/bouncycastle/crypto/modes/G3413CTRBlockCipher.java +@@ -73,7 +73,6 @@ public void init( + CipherParameters params) + throws IllegalArgumentException + { +- + if (params instanceof ParametersWithIV) + { + ParametersWithIV ivParam = (ParametersWithIV)params; +@@ -198,7 +197,6 @@ private void generateCTR() + { + throw new IllegalStateException("attempt to process too many blocks"); + } +- CTR[start]++; + } + } + +diff --git a/core/src/test/java/org/bouncycastle/crypto/test/GOST3412Test.java b/core/src/test/java/org/bouncycastle/crypto/test/GOST3412Test.java +index fa0087a6de..d8e498c180 100644 +--- a/core/src/test/java/org/bouncycastle/crypto/test/GOST3412Test.java ++++ b/core/src/test/java/org/bouncycastle/crypto/test/GOST3412Test.java +@@ -87,7 +87,7 @@ public String getName() + public void performTest() + throws Exception + { +- //super.performTest(); ++ super.performTest(); + + ctrTest(); + // cfbTest(); diff --git a/CVE-2025-14813-b4257434.patch b/CVE-2025-14813-b4257434.patch new file mode 100644 index 0000000000000000000000000000000000000000..4cb2c816099a02c135c64cb426bc8cc75d07ee1d --- /dev/null +++ b/CVE-2025-14813-b4257434.patch @@ -0,0 +1,160 @@ +From b42574345414e4b7c8051b16fa1fafe01c29871f Mon Sep 17 00:00:00 2001 +From: David Hook +Date: Thu, 4 Dec 2025 16:10:11 +1100 +Subject: [PATCH] refactored counter code. + +--- + .../crypto/modes/G3413CTRBlockCipher.java | 20 ++++--- + .../crypto/test/GOST3412Test.java | 60 ++++++++++++++++++- + 2 files changed, 71 insertions(+), 9 deletions(-) + +diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/G3413CTRBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/G3413CTRBlockCipher.java +index 9e4a677d37..f524c01895 100644 +--- a/core/src/main/java/org/bouncycastle/crypto/modes/G3413CTRBlockCipher.java ++++ b/core/src/main/java/org/bouncycastle/crypto/modes/G3413CTRBlockCipher.java +@@ -13,8 +13,6 @@ + public class G3413CTRBlockCipher + extends StreamBlockCipher + { +- +- + private final int s; + private byte[] CTR; + private byte[] IV; +@@ -24,7 +22,6 @@ public class G3413CTRBlockCipher + private int byteCount = 0; + private boolean initialized; + +- + /** + * Basic constructor. + * +@@ -184,27 +181,34 @@ protected byte calculateByte(byte in) + if (byteCount == s) + { + byteCount = 0; +- generateCRT(); ++ generateCTR(); + } + + return rv; + + } + +- private void generateCRT() ++ private void generateCTR() + { +- CTR[CTR.length - 1]++; ++ int start = CTR.length - 1; ++ while (++CTR[start] == 0) ++ { ++ start--; ++ if (start == IV.length - 1) ++ { ++ throw new IllegalStateException("attempt to process too many blocks"); ++ } ++ CTR[start]++; ++ } + } + + + private byte[] generateBuf() + { +- + byte[] encryptedCTR = new byte[CTR.length]; + cipher.processBlock(CTR, 0, encryptedCTR, 0); + + return GOST3413CipherUtil.MSB(encryptedCTR, s); +- + } + + +diff --git a/core/src/test/java/org/bouncycastle/crypto/test/GOST3412Test.java b/core/src/test/java/org/bouncycastle/crypto/test/GOST3412Test.java +index 48a78e18db..f253f32f5a 100644 +--- a/core/src/test/java/org/bouncycastle/crypto/test/GOST3412Test.java ++++ b/core/src/test/java/org/bouncycastle/crypto/test/GOST3412Test.java +@@ -1,5 +1,6 @@ + package org.bouncycastle.crypto.test; + ++import org.bouncycastle.crypto.StreamBlockCipher; + import org.bouncycastle.crypto.engines.GOST3412_2015Engine; + import org.bouncycastle.crypto.modes.G3413CBCBlockCipher; + import org.bouncycastle.crypto.modes.G3413CFBBlockCipher; +@@ -7,6 +8,7 @@ + import org.bouncycastle.crypto.modes.G3413OFBBlockCipher; + import org.bouncycastle.crypto.params.KeyParameter; + import org.bouncycastle.crypto.params.ParametersWithIV; ++import org.bouncycastle.util.Arrays; + import org.bouncycastle.util.encoders.Hex; + import org.bouncycastle.util.test.SimpleTest; + +@@ -85,12 +87,68 @@ public String getName() + public void performTest() + throws Exception + { +- super.performTest(); ++ //super.performTest(); + ++ ctrTest(); + // cfbTest(); + // ofbTest(); + } + ++ private void ctrTest() ++ throws Exception ++ { ++ StreamBlockCipher sb = new G3413CTRBlockCipher(new GOST3412_2015Engine(), 128); ++ ++ sb.init(true, new ParametersWithIV(new KeyParameter(Hex.decode("8899aabbccddeeff0011223344556677fedcba98765432100123456789abcdef")), ++ Hex.decode("0001020304050607"))); ++ ++ byte[] block = Hex.decode("000102030405060708090a0b0c0d0e0f"); ++ byte[] output = new byte[16]; ++ byte[] last = new byte[16]; ++ ++ sb.processBytes(block, 0, block.length, last, 0); ++ ++ for (int i = 1; i < 255; i++) ++ { ++ sb.processBytes(block, 0, block.length, output, 0); ++ if (Arrays.areEqual(last, output)) ++ { ++ fail("cipher text repeats 1"); ++ } ++ } ++ ++ sb.processBytes(block, 0, block.length, output, 0); ++ if (Arrays.areEqual(last, output)) ++ { ++ fail("cipher text repeats 2"); ++ } ++ ++ sb = new G3413CTRBlockCipher(new GOST3412_2015Engine(), 128); ++ ++ sb.init(true, new ParametersWithIV(new KeyParameter(Hex.decode("8899aabbccddeeff0011223344556677fedcba98765432100123456789abcdef")), ++ Hex.decode("0001020304050607"))); ++ ++ sb.processBytes(block, 0, block.length, last, 0); ++ ++ for (int i = 1; i != ((1 << 15) - 1); i++) ++ { ++ sb.processBytes(block, 0, block.length, output, 0); ++ if (Arrays.areEqual(last, output)) ++ { ++ fail("cipher text repeats 3"); ++ } ++ byte[] tmp = last; ++ last = output; ++ output = tmp; ++ } ++ ++ sb.processBytes(block, 0, block.length, output, 0); ++ if (Arrays.areEqual(last, output)) ++ { ++ fail("cipher text repeats"); ++ } ++ } ++ + public static void main( + String[] args) + { diff --git a/bouncycastle.spec b/bouncycastle.spec index ba9b6b15f9decbe858d107130f663a611c5175a1..4e58c59bbfec300dfc7ece7d55452f0dd723dc83 100644 --- a/bouncycastle.spec +++ b/bouncycastle.spec @@ -4,10 +4,12 @@ Summary: Bouncy Castle Cryptography APIs for Java Name: bouncycastle Version: 1.80 -Release: 1%{?dist} +Release: 2%{?dist} License: MIT URL: http://www.bouncycastle.org Source0: https://github.com/bcgit/bc-java/archive/%{gittag}.tar.gz +Patch0: CVE-2025-14813-b4257434.patch +Patch1: CVE-2025-14813-701686cb.patch BuildRequires: javapackages-local BuildRequires: ant ant-junit BuildArch: noarch @@ -224,6 +226,10 @@ fi %changelog +* Fri Jul 10 2026 Zhao Zhen - 1.80-2 +- backport upstream fixes for CVE-2025-14813 +- fix G3413CTRBlockCipher counter handling and add regression tests + * Mon Jan 20 2025 Zhao Zhen - 1.80-1 - updated to upstream 1.80 - fixed CVE-2023-33201 CVE-2024-34447 CVE-2024-30171