summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHitendra Prajapati <hprajapati@mvista.com>2026-05-14 18:45:41 +0530
committerAnuj Mittal <anuj.mittal@oss.qualcomm.com>2026-05-21 08:57:48 +0530
commita587f53a0eff978246f7aec466fb42588c339056 (patch)
tree051ee6a8f39f6b50084944f06ed2bc4954bd6911
parent9f70f8d461abae94342da0e41ed978022e0eefe2 (diff)
downloadmeta-openembedded-a587f53a0eff978246f7aec466fb42588c339056.tar.gz
strongswan: fix for CVE-2026-35334
Pick patch according to [1] [1] https://download.strongswan.org/security/CVE-2026-35334 [2] https://www.strongswan.org/blog/2026/04/22/strongswan-vulnerability-(cve-2026-35334).html [3] https://security-tracker.debian.org/tracker/CVE-2026-35334 Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com>
-rw-r--r--meta-networking/recipes-support/strongswan/strongswan/CVE-2026-35334.patch255
-rw-r--r--meta-networking/recipes-support/strongswan/strongswan_5.9.14.bb1
2 files changed, 256 insertions, 0 deletions
diff --git a/meta-networking/recipes-support/strongswan/strongswan/CVE-2026-35334.patch b/meta-networking/recipes-support/strongswan/strongswan/CVE-2026-35334.patch
new file mode 100644
index 0000000000..5ed9f1bf61
--- /dev/null
+++ b/meta-networking/recipes-support/strongswan/strongswan/CVE-2026-35334.patch
@@ -0,0 +1,255 @@
1From c23cf29373bb25a24b952ea4c5bf7ea326b78714 Mon Sep 17 00:00:00 2001
2From: Tobias Brunner <tobias@strongswan.org>
3Date: Tue, 24 Mar 2026 18:00:23 +0100
4Subject: [PATCH] gmp: Avoid crash and timing leaks in PKCS#1 v1.5 decryption
5 padding validation
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10This fixes a potential crash due to a null-pointer dereference if rsadp()
11returns NULL (e.g. with an all-zero ciphertext).
12
13And it also implements the PKCS#1 v1.5 decryption padding check in
14constant time.
15
16The timing leak caused by the previous implementation was measured at
17~17.5 μs at 3 GHz, which could allow a Bleichenbacher-like attack in
18LAN environments. However, because of how RSA encryption is used in
19strongSwan, this is not that much of an issue in practice. The mechanism
20is only used for two use cases. One is SCEP/EST via PKCS#7 enveloped
21data. Fortunately, this can not be triggered in significant numbers by
22an attacker. The other use case is TLS as used by EAP methods (EAP-TLS,
23EAP-PEAP/TTLS) during the authentication. While the cipher suites that
24use RSA encryption are still enabled by default, the TLS messages are
25wrapped in EAP and encrypted by IKE, making any kind of attack difficult.
26
27Note that the gmp plugin isn't enabled anymore by default. And even
28before that, most setups had the openssl plugin enabled, which has
29priority over the gmp plugin. So it's unlikely the plugin was used in
30practice.
31
32Also note that this patch doesn't modify libstrongswan's Makefile.am
33to avoid potentially requiring autotools when patching a tarball.
34
35Fixes: d615ffdcf3cd ("implement gmp_rsa_private_key.decrypt()")
36Fixes: CVE-2026-35334
37
38
39CVE: CVE-2026-35334
40Upstream-Status: Backport [https://download.strongswan.org/security/CVE-2026-35334/strongswan-5.3.1-6.0.5_gmp_rsa_decrypt_pad.patch]
41Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
42---
43 .../plugins/gmp/gmp_rsa_private_key.c | 54 ++++++---
44 src/libstrongswan/utils/utils.h | 1 +
45 src/libstrongswan/utils/utils/constant_time.h | 103 ++++++++++++++++++
46 3 files changed, 140 insertions(+), 18 deletions(-)
47 create mode 100644 src/libstrongswan/utils/utils/constant_time.h
48
49diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
50index 47784b6..7312fa9 100644
51--- a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
52+++ b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
53@@ -495,8 +495,8 @@ METHOD(private_key_t, decrypt, bool,
54 private_gmp_rsa_private_key_t *this, encryption_scheme_t scheme,
55 void *params, chunk_t crypto, chunk_t *plain)
56 {
57- chunk_t em, stripped;
58- bool success = FALSE;
59+ chunk_t em;
60+ u_int valid, i, j, found_sep = 0, sep_index = 0, m_index;
61
62 if (scheme != ENCRYPT_RSA_PKCS1)
63 {
64@@ -505,33 +505,51 @@ METHOD(private_key_t, decrypt, bool,
65 return FALSE;
66 }
67 /* rsa decryption using PKCS#1 RSADP */
68- stripped = em = rsadp(this, crypto);
69+ em = rsadp(this, crypto);
70+ if (em.len != this->k)
71+ {
72+ return FALSE;
73+ }
74
75- /* PKCS#1 v1.5 8.1 encryption-block formatting (EB = 00 || 02 || PS || 00 || D) */
76+ /* PKCS#1 v1.5, RFC 8017, section 7.2.2 message structure:
77+ * EM = 00 || 02 || PS || 00 || M */
78
79 /* check for hex pattern 00 02 in decrypted message */
80- if ((*stripped.ptr++ != 0x00) || (*(stripped.ptr++) != 0x02))
81+ valid = constant_time_eq(em.ptr[0], 0x00);
82+ valid &= constant_time_eq(em.ptr[1], 0x02);
83+
84+ /* the plaintext data starts after first 0x00 byte */
85+ for (i = 2; i < em.len; i++)
86 {
87- DBG1(DBG_LIB, "incorrect padding - probably wrong rsa key");
88- goto end;
89+ u_int zero = constant_time_eq(em.ptr[i], 0x00);
90+
91+ sep_index = constant_time_select(i, sep_index, ~found_sep & zero);
92+ found_sep |= zero;
93 }
94- stripped.len -= 2;
95
96- /* the plaintext data starts after first 0x00 byte */
97- while (stripped.len-- > 0 && *stripped.ptr++ != 0x00)
98+ /* make sure PS is at least eight bytes long (plus the initial bytes) */
99+ valid &= constant_time_ge(sep_index, 10);
100+
101+ /* instead of copying the message directly, we try not to reveal the message
102+ * length i.e. where the 0x00 byte was. and since clearing a chunk is
103+ * relatively efficient, i.e. doesn't leak much, we always allocate and copy
104+ * a value and then clear it if the structure was invalid */
105+ m_index = constant_time_select(sep_index + 1, 11, valid);
106
107- if (stripped.len == 0)
108+ *plain = chunk_alloc(this->k);
109+ for (i = 0, j = 0; i < em.len; i++)
110 {
111- DBG1(DBG_LIB, "no plaintext data");
112- goto end;
113+ plain->ptr[j] = em.ptr[i];
114+ j += constant_time_ge(i, m_index);
115 }
116+ plain->len = j;
117
118- *plain = chunk_clone(stripped);
119- success = TRUE;
120-
121-end:
122+ if (!valid)
123+ {
124+ chunk_clear(plain);
125+ }
126 chunk_clear(&em);
127- return success;
128+ return valid;
129 }
130
131 METHOD(private_key_t, get_keysize, int,
132diff --git a/src/libstrongswan/utils/utils.h b/src/libstrongswan/utils/utils.h
133index 42d0114..ab0be72 100644
134--- a/src/libstrongswan/utils/utils.h
135+++ b/src/libstrongswan/utils/utils.h
136@@ -53,6 +53,7 @@
137 #include "utils/atomics.h"
138 #include "utils/align.h"
139 #include "utils/byteorder.h"
140+#include "utils/constant_time.h"
141 #include "utils/string.h"
142 #include "utils/memory.h"
143 #include "utils/strerror.h"
144diff --git a/src/libstrongswan/utils/utils/constant_time.h b/src/libstrongswan/utils/utils/constant_time.h
145new file mode 100644
146index 0000000..0c2c6a2
147--- /dev/null
148+++ b/src/libstrongswan/utils/utils/constant_time.h
149@@ -0,0 +1,103 @@
150+/*
151+ * Copyright (C) 2026 Tobias Brunner
152+ *
153+ * Copyright (C) secunet Security Networks AG
154+ *
155+ * This program is free software; you can redistribute it and/or modify it
156+ * under the terms of the GNU General Public License as published by the
157+ * Free Software Foundation; either version 2 of the License, or (at your
158+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
159+ *
160+ * This program is distributed in the hope that it will be useful, but
161+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
162+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
163+ * for more details.
164+ */
165+
166+/**
167+ * @defgroup constant_time_i constant_time
168+ * @{ @ingroup constant_time_i
169+ */
170+
171+#ifndef CONSTANT_TIME_H_
172+#define CONSTANT_TIME_H_
173+
174+#include <stdint.h>
175+
176+/**
177+ * Check if the given values are not equal in constant time.
178+ *
179+ * @param x first value to check
180+ * @param y second value to check
181+ * @return 1 if values are not equal, 0 otherwise
182+ */
183+static inline u_int constant_time_neq(uint32_t x, uint32_t y)
184+{
185+ return ((x-y) | (y-x)) >> 31;
186+}
187+
188+/**
189+ * Check if the given values are equal in constant time.
190+ *
191+ * @param x first value to check
192+ * @param y second value to check
193+ * @return 1 if values are equal, 0 otherwise
194+ */
195+static inline u_int constant_time_eq(uint32_t x, uint32_t y)
196+{
197+ return 1 ^ constant_time_neq(x, y);
198+}
199+
200+/**
201+ * Compare the two values and return 1 if the first argument is lower than
202+ * the second in constant time.
203+ *
204+ * @param x first value to check
205+ * @param y second value to check
206+ * @return 1 if first value is lower than second
207+ */
208+static inline u_int constant_time_lt(uint32_t x, uint32_t y)
209+{
210+ return (x ^ ((x^y) | ((x-y) ^ y))) >> 31;
211+}
212+
213+/**
214+ * Compare the two values and return 1 if the first argument greater or equal to
215+ * the second in constant time.
216+ *
217+ * @param x first value to check
218+ * @param y second value to check
219+ * @return 1 if first value is greater or equal to the second
220+ */
221+static inline u_int constant_time_ge(uint32_t x, uint32_t y)
222+{
223+ return 1 ^ constant_time_lt(x, y);
224+}
225+
226+/**
227+ * Return a 32-bit all bit-set mask if the given value is not 0.
228+ *
229+ * @param x value to check
230+ * @return 0xffffffff if value is != 0, 0 otherwise
231+ */
232+static inline uint32_t constant_time_mask(uint32_t x)
233+{
234+ return -(uint32_t)constant_time_neq(x, 0);
235+}
236+
237+/**
238+ * Select one of two values depending on whether the condition is != 0 or not.
239+ * Basically equivalent to 'c ? x : y'.
240+ *
241+ * @param x first value to select
242+ * @param y second value to select
243+ * @param c condition
244+ * @return x if c is != 0, y otherwise
245+ */
246+static inline uint32_t constant_time_select(uint32_t x, uint32_t y, uint32_t c)
247+{
248+ uint32_t m = constant_time_mask(c);
249+ return (x & m) | (y & ~m);
250+}
251+
252+#endif /** CONSTANT_TIME_H_ @} */
253--
2542.50.1
255
diff --git a/meta-networking/recipes-support/strongswan/strongswan_5.9.14.bb b/meta-networking/recipes-support/strongswan/strongswan_5.9.14.bb
index 820a1ad9e8..7cc67e4d92 100644
--- a/meta-networking/recipes-support/strongswan/strongswan_5.9.14.bb
+++ b/meta-networking/recipes-support/strongswan/strongswan_5.9.14.bb
@@ -11,6 +11,7 @@ DEPENDS:append = "${@bb.utils.contains('DISTRO_FEATURES', 'tpm2', ' tpm2-tss',
11SRC_URI = "https://download.strongswan.org/strongswan-${PV}.tar.bz2 \ 11SRC_URI = "https://download.strongswan.org/strongswan-${PV}.tar.bz2 \
12 file://CVE-2025-62291.patch \ 12 file://CVE-2025-62291.patch \
13 file://CVE-2026-25075.patch \ 13 file://CVE-2026-25075.patch \
14 file://CVE-2026-35334.patch \
14 " 15 "
15 16
16SRC_URI[sha256sum] = "728027ddda4cb34c67c4cec97d3ddb8c274edfbabdaeecf7e74693b54fc33678" 17SRC_URI[sha256sum] = "728027ddda4cb34c67c4cec97d3ddb8c274edfbabdaeecf7e74693b54fc33678"