summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta-oe/recipes-crypto/botan/botan/CVE-2026-32877.patch158
-rw-r--r--meta-oe/recipes-crypto/botan/botan_3.10.0.bb4
2 files changed, 161 insertions, 1 deletions
diff --git a/meta-oe/recipes-crypto/botan/botan/CVE-2026-32877.patch b/meta-oe/recipes-crypto/botan/botan/CVE-2026-32877.patch
new file mode 100644
index 0000000000..871f5c9a1b
--- /dev/null
+++ b/meta-oe/recipes-crypto/botan/botan/CVE-2026-32877.patch
@@ -0,0 +1,158 @@
1From a0048a6b97a349a3cb4a5f955d350ab2921719cc Mon Sep 17 00:00:00 2001
2From: Jack Lloyd <jack@randombit.net>
3Date: Sun, 15 Mar 2026 11:39:50 -0400
4Subject: [PATCH] In SM2 verify the C3 field is of the required length
5
6Previously the decryption step assumed that C3 was equal in length to the MAC
7output. If C3 is shorter than expected, up to 31 bytes of arbitrary heap data
8would be compared with the computed MAC. This heap over-read would potentially
9result in denial of service.
10
11CVE: CVE-2026-32877
12Upstream-Status: Backport [https://github.com/randombit/botan/commit/f3c31f96f58f1d1d482032d8f4286dc9ebbc6712]
13Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
14---
15 src/lib/pubkey/sm2/sm2_enc.cpp | 7 +++-
16 src/tests/data/pubkey/sm2_invalid.vec | 60 +++++++++++++++++++++++++++
17 src/tests/test_sm2.cpp | 31 ++++++++++++++
18 3 files changed, 97 insertions(+), 1 deletion(-)
19 create mode 100644 src/tests/data/pubkey/sm2_invalid.vec
20
21diff --git a/src/lib/pubkey/sm2/sm2_enc.cpp b/src/lib/pubkey/sm2/sm2_enc.cpp
22index 7a1b990..1141089 100644
23--- a/src/lib/pubkey/sm2/sm2_enc.cpp
24+++ b/src/lib/pubkey/sm2/sm2_enc.cpp
25@@ -133,6 +133,11 @@ class SM2_Decryption_Operation final : public PK_Ops::Decryption {
26 .end_cons()
27 .verify_end();
28
29+ // Wrong length so certainly invalid, reject immediately
30+ if(C3.size() != m_hash->output_length()) {
31+ return secure_vector<uint8_t>();
32+ }
33+
34 std::vector<uint8_t> recode_ctext;
35 DER_Encoder(recode_ctext)
36 .start_sequence()
37@@ -170,7 +175,7 @@ class SM2_Decryption_Operation final : public PK_Ops::Decryption {
38 m_hash->update(y2_bytes);
39 const auto u = m_hash->final();
40
41- if(!CT::is_equal(u.data(), C3.data(), m_hash->output_length()).as_bool()) {
42+ if(!CT::is_equal<uint8_t>(u, C3).as_bool()) {
43 return secure_vector<uint8_t>();
44 }
45
46diff --git a/src/tests/data/pubkey/sm2_invalid.vec b/src/tests/data/pubkey/sm2_invalid.vec
47new file mode 100644
48index 0000000..2517510
49--- /dev/null
50+++ b/src/tests/data/pubkey/sm2_invalid.vec
51@@ -0,0 +1,60 @@
52+
53+Key = 8C84F7F069CD09D59543ED980CFEB77E68C7D39B9B73D359EA67C0CDB2A86B6F
54+
55+
56+# Empty
57+Ctext =
58+
59+# Just the SEQUENCE marker
60+Ctext = 30
61+
62+# Truncated
63+Ctext = 3072022100A772DF5FFFDA85C05D9B82233B1E5F7DF7A87788504ABD4F74D265D49E5002C0022055C8A934A29DE58B31A063CDA81F12ABC712FB9ADC8988DA0FBD9FFF304E27CF04202E1B8A86EF14243EE2E9D74E0D0E7498DFAC2F0EFA8C5883D74F3682649386960409CA311F43DB0E5E51
64+
65+# C3 MAC too short
66+Ctext = 3071022100A772DF5FFFDA85C05D9B82233B1E5F7DF7A87788504ABD4F74D265D49E5002C0022055C8A934A29DE58B31A063CDA81F12ABC712FB9ADC8988DA0FBD9FFF304E27CF041F2E1B8A86EF14243EE2E9D74E0D0E7498DFAC2F0EFA8C5883D74F36826493860409CA311F43DB0E5E516F
67+
68+# C3 MAC too long
69+Ctext = 3073022100A772DF5FFFDA85C05D9B82233B1E5F7DF7A87788504ABD4F74D265D49E5002C0022055C8A934A29DE58B31A063CDA81F12ABC712FB9ADC8988DA0FBD9FFF304E27CF04212E1B8A86EF14243EE2E9D74E0D0E7498DFAC2F0EFA8C5883D74F368264938696000409CA311F43DB0E5E516F
70+
71+# C3 and C2 fields swapped
72+Ctext = 3072022100A772DF5FFFDA85C05D9B82233B1E5F7DF7A87788504ABD4F74D265D49E5002C0022055C8A934A29DE58B31A063CDA81F12ABC712FB9ADC8988DA0FBD9FFF304E27CF0409CA311F43DB0E5E516F04202E1B8A86EF14243EE2E9D74E0D0E7498DFAC2F0EFA8C5883D74F368264938696
73+
74+# C3 MAC last bit flipped
75+Ctext = 3072022100A772DF5FFFDA85C05D9B82233B1E5F7DF7A87788504ABD4F74D265D49E5002C0022055C8A934A29DE58B31A063CDA81F12ABC712FB9ADC8988DA0FBD9FFF304E27CF04202E1B8A86EF14243EE2E9D74E0D0E7498DFAC2F0EFA8C5883D74F3682649386970409CA311F43DB0E5E516F
76+
77+# C3 MAC first byte inverted
78+Ctext = 3072022100A772DF5FFFDA85C05D9B82233B1E5F7DF7A87788504ABD4F74D265D49E5002C0022055C8A934A29DE58B31A063CDA81F12ABC712FB9ADC8988DA0FBD9FFF304E27CF0420D11B8A86EF14243EE2E9D74E0D0E7498DFAC2F0EFA8C5883D74F3682649386960409CA311F43DB0E5E516F
79+
80+# C1 y off by one
81+Ctext = 3072022100A772DF5FFFDA85C05D9B82233B1E5F7DF7A87788504ABD4F74D265D49E5002C0022055C8A934A29DE58B31A063CDA81F12ABC712FB9ADC8988DA0FBD9FFF304E27D004202E1B8A86EF14243EE2E9D74E0D0E7498DFAC2F0EFA8C5883D74F3682649386960409CA311F43DB0E5E516F
82+
83+# C1 x/y serialization boundary shift
84+Ctext = 3073022100A772DF5FFFDA85C05D9B82233B1E5F7DF7A87788504ABD4F74D265D49E500200022100C055C8A934A29DE58B31A063CDA81F12ABC712FB9ADC8988DA0FBD9FFF304E2704202E1B8A86EF14243EE2E9D74E0D0E7498DFAC2F0EFA8C5883D74F3682649386960409CA311F43DB0E5E516F
85+
86+# C1 is generator point
87+Ctext = 3072022032C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7022100BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A004202E1B8A86EF14243EE2E9D74E0D0E7498DFAC2F0EFA8C5883D74F3682649386960409CA311F43DB0E5E516F
88+
89+# C1 is origin (0,0)
90+Ctext = 303302010002010004202E1B8A86EF14243EE2E9D74E0D0E7498DFAC2F0EFA8C5883D74F3682649386960409CA311F43DB0E5E516F
91+
92+# C1 x equals field prime
93+Ctext = 3072022100FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF022055C8A934A29DE58B31A063CDA81F12ABC712FB9ADC8988DA0FBD9FFF304E27CF04202E1B8A86EF14243EE2E9D74E0D0E7498DFAC2F0EFA8C5883D74F3682649386960409CA311F43DB0E5E516F
94+
95+# C2 last bit flipped
96+Ctext = 3072022100A772DF5FFFDA85C05D9B82233B1E5F7DF7A87788504ABD4F74D265D49E5002C0022055C8A934A29DE58B31A063CDA81F12ABC712FB9ADC8988DA0FBD9FFF304E27CF04202E1B8A86EF14243EE2E9D74E0D0E7498DFAC2F0EFA8C5883D74F3682649386960409CA311F43DB0E5E516E
97+
98+# C2 replaced with empty
99+Ctext = 3069022100A772DF5FFFDA85C05D9B82233B1E5F7DF7A87788504ABD4F74D265D49E5002C0022055C8A934A29DE58B31A063CDA81F12ABC712FB9ADC8988DA0FBD9FFF304E27CF04202E1B8A86EF14243EE2E9D74E0D0E7498DFAC2F0EFA8C5883D74F3682649386960400
100+
101+# Trailing byte after SEQUENCE
102+Ctext = 3072022100A772DF5FFFDA85C05D9B82233B1E5F7DF7A87788504ABD4F74D265D49E5002C0022055C8A934A29DE58B31A063CDA81F12ABC712FB9ADC8988DA0FBD9FFF304E27CF04202E1B8A86EF14243EE2E9D74E0D0E7498DFAC2F0EFA8C5883D74F3682649386960409CA311F43DB0E5E516F00
103+
104+# SEQUENCE with non-minimal long-form length
105+Ctext = 308172022100A772DF5FFFDA85C05D9B82233B1E5F7DF7A87788504ABD4F74D265D49E5002C0022055C8A934A29DE58B31A063CDA81F12ABC712FB9ADC8988DA0FBD9FFF304E27CF04202E1B8A86EF14243EE2E9D74E0D0E7498DFAC2F0EFA8C5883D74F3682649386960409CA311F43DB0E5E516F
106+
107+# INTEGER x1 with non-minimal leading zero
108+Ctext = 307302220000A772DF5FFFDA85C05D9B82233B1E5F7DF7A87788504ABD4F74D265D49E5002C0022055C8A934A29DE58B31A063CDA81F12ABC712FB9ADC8988DA0FBD9FFF304E27CF04202E1B8A86EF14243EE2E9D74E0D0E7498DFAC2F0EFA8C5883D74F3682649386960409CA311F43DB0E5E516F
109+
110+# OCTET STRING C3 with non-minimal long-form length
111+Ctext = 3073022100A772DF5FFFDA85C05D9B82233B1E5F7DF7A87788504ABD4F74D265D49E5002C0022055C8A934A29DE58B31A063CDA81F12ABC712FB9ADC8988DA0FBD9FFF304E27CF0481202E1B8A86EF14243EE2E9D74E0D0E7498DFAC2F0EFA8C5883D74F3682649386960409CA311F43DB0E5E516F
112diff --git a/src/tests/test_sm2.cpp b/src/tests/test_sm2.cpp
113index 2ffb14a..c5d2360 100644
114--- a/src/tests/test_sm2.cpp
115+++ b/src/tests/test_sm2.cpp
116@@ -9,6 +9,7 @@
117
118 #if defined(BOTAN_HAS_SM2)
119 #include "test_pubkey.h"
120+ #include <botan/pubkey.h>
121 #include <botan/sm2.h>
122 #endif
123
124@@ -108,4 +109,34 @@ BOTAN_REGISTER_TEST("pubkey", "sm2_keygen", SM2_Keygen_Tests);
125
126 #endif
127
128+namespace {
129+
130+class SM2_Invalid_Ciphertexts : public Text_Based_Test {
131+ public:
132+ SM2_Invalid_Ciphertexts() : Text_Based_Test("pubkey/sm2_invalid.vec", "Key,Ctext") {}
133+
134+ bool clear_between_callbacks() const override { return false; }
135+
136+ Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
137+ Test::Result result("SM2 invalid ciphertext");
138+
139+ const auto key = vars.get_req_bin("Key");
140+ const auto ctext = vars.get_req_bin("Ctext");
141+
142+ const auto group = Botan::EC_Group::from_name("sm2p256v1");
143+ const auto pkey = Botan::SM2_PrivateKey(group, Botan::EC_Scalar::deserialize(group, key).value());
144+
145+ Botan::PK_Decryptor_EME dec(pkey, rng(), "SM3");
146+
147+ result.test_throws<Botan::Exception>("Decryption should fail for invalid ciphertext",
148+ [&] { dec.decrypt(ctext); });
149+
150+ return result;
151+ }
152+};
153+
154+BOTAN_REGISTER_TEST("pubkey", "sm2_invalid_ctext", SM2_Invalid_Ciphertexts);
155+
156+} // namespace
157+
158 } // namespace Botan_Tests
diff --git a/meta-oe/recipes-crypto/botan/botan_3.10.0.bb b/meta-oe/recipes-crypto/botan/botan_3.10.0.bb
index e079dd73de..392c1aac94 100644
--- a/meta-oe/recipes-crypto/botan/botan_3.10.0.bb
+++ b/meta-oe/recipes-crypto/botan/botan_3.10.0.bb
@@ -4,7 +4,9 @@ LICENSE = "BSD-2-Clause"
4LIC_FILES_CHKSUM = "file://license.txt;md5=3f911cecfc74a2d9f1ead9a07bd92a6e" 4LIC_FILES_CHKSUM = "file://license.txt;md5=3f911cecfc74a2d9f1ead9a07bd92a6e"
5SECTION = "libs" 5SECTION = "libs"
6 6
7SRC_URI = "https://botan.randombit.net/releases/Botan-${PV}.tar.xz" 7SRC_URI = "https://botan.randombit.net/releases/Botan-${PV}.tar.xz \
8 file://CVE-2026-32877.patch \
9 "
8SRC_URI[sha256sum] = "fde194236f6d5434f136ea0a0627f6cc9d26af8b96e9f1e1c7d8c82cd90f4f24" 10SRC_URI[sha256sum] = "fde194236f6d5434f136ea0a0627f6cc9d26af8b96e9f1e1c7d8c82cd90f4f24"
9 11
10S = "${UNPACKDIR}/Botan-${PV}" 12S = "${UNPACKDIR}/Botan-${PV}"