summaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-support/opensc/files
diff options
context:
space:
mode:
authorZhang Peng <peng.zhang1.cn@windriver.com>2025-10-31 17:14:45 +0800
committerGyorgy Sarvari <skandigraun@gmail.com>2025-11-02 15:09:01 +0100
commit4cbf9d8d2c9fc3cae387c20d9d7f7c1fb622ee2d (patch)
tree93988325dc978842afe389d6dd089f6f006f619b /meta-oe/recipes-support/opensc/files
parent01b7c42dfd25f1308113a4de540cfc03a6ae94cb (diff)
downloadmeta-openembedded-4cbf9d8d2c9fc3cae387c20d9d7f7c1fb622ee2d.tar.gz
opensc: fix CVE-2023-5992
CVE-2023-5992: A vulnerability was found in OpenSC where PKCS#1 encryption padding removal is not implemented as side-channel resistant. This issue may result in the potential leak of private data. Reference: [https://nvd.nist.gov/vuln/detail/CVE-2023-5992] [https://github.com/OpenSC/OpenSC/wiki/CVE-2023-5992] Upstream patches: [https://github.com/OpenSC/OpenSC/pull/2948] [https://github.com/OpenSC/OpenSC/pull/3016] Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com> Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
Diffstat (limited to 'meta-oe/recipes-support/opensc/files')
-rw-r--r--meta-oe/recipes-support/opensc/files/CVE-2023-5992-0001.patch359
-rw-r--r--meta-oe/recipes-support/opensc/files/CVE-2023-5992-0002.patch269
-rw-r--r--meta-oe/recipes-support/opensc/files/CVE-2023-5992-0003.patch41
-rw-r--r--meta-oe/recipes-support/opensc/files/CVE-2023-5992-0004.patch109
-rw-r--r--meta-oe/recipes-support/opensc/files/CVE-2023-5992-0005.patch63
-rw-r--r--meta-oe/recipes-support/opensc/files/CVE-2023-5992-0006.patch118
-rw-r--r--meta-oe/recipes-support/opensc/files/CVE-2023-5992-0007.patch50
-rw-r--r--meta-oe/recipes-support/opensc/files/CVE-2023-5992-0008.patch37
-rw-r--r--meta-oe/recipes-support/opensc/files/CVE-2023-5992-0009.patch123
-rw-r--r--meta-oe/recipes-support/opensc/files/CVE-2023-5992-0010.patch75
10 files changed, 1244 insertions, 0 deletions
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0001.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0001.patch
new file mode 100644
index 0000000000..4798ab56ae
--- /dev/null
+++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0001.patch
@@ -0,0 +1,359 @@
1From 9c14d6d996e526ebfda75de7b577255acf7ad86d Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
3Date: Mon, 13 Nov 2023 13:54:54 +0100
4Subject: [PATCH 01/10] Reimplement removing of PKCS#1 v1.5 padding to be time
5 constant
6
7CVE: CVE-2023-5992
8Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/2948]
9
10Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com>
11---
12 src/common/Makefile.am | 5 +-
13 src/common/constant-time.h | 128 ++++++++++++++++++++++++++++++++++++
14 src/libopensc/internal.h | 4 +-
15 src/libopensc/padding.c | 102 +++++++++++++++++++---------
16 src/libopensc/pkcs15-sec.c | 5 +-
17 src/minidriver/minidriver.c | 4 +-
18 6 files changed, 209 insertions(+), 39 deletions(-)
19 create mode 100644 src/common/constant-time.h
20
21diff --git a/src/common/Makefile.am b/src/common/Makefile.am
22index 83a40e1c2..c4cfff185 100644
23--- a/src/common/Makefile.am
24+++ b/src/common/Makefile.am
25@@ -8,7 +8,7 @@ dist_noinst_DATA = \
26 LICENSE.compat_getopt compat_getopt.txt \
27 compat_getopt_main.c \
28 README.compat_strlcpy compat_strlcpy.3
29-noinst_HEADERS = compat_strlcat.h compat_strlcpy.h compat_strnlen.h compat_getpass.h compat_getopt.h simclist.h libpkcs11.h libscdl.h
30+noinst_HEADERS = compat_strlcat.h compat_strlcpy.h compat_strnlen.h compat_getpass.h compat_getopt.h simclist.h libpkcs11.h libscdl.h constant-time.h
31
32 AM_CPPFLAGS = -I$(top_srcdir)/src
33
34@@ -40,7 +40,8 @@ TIDY_FILES = \
35 compat_report_rangecheckfailure.c \
36 compat___iob_func.c \
37 simclist.c simclist.h \
38- libpkcs11.c libscdl.c
39+ libpkcs11.c libscdl.c \
40+ constant-time.h
41
42 check-local:
43 if [ -x "$(CLANGTIDY)" ]; then clang-tidy -config='' --checks='$(TIDY_CHECKS)' -header-filter=.* $(addprefix $(srcdir)/,$(TIDY_FILES)) -- $(TIDY_FLAGS); fi
44diff --git a/src/common/constant-time.h b/src/common/constant-time.h
45new file mode 100644
46index 000000000..40c3e500c
47--- /dev/null
48+++ b/src/common/constant-time.h
49@@ -0,0 +1,128 @@
50+/* Original source: https://github.com/openssl/openssl/blob/9890cc42daff5e2d0cad01ac4bf78c391f599a6e/include/internal/constant_time.h */
51+
52+#ifndef CONSTANT_TIME_H
53+#define CONSTANT_TIME_H
54+
55+#include <stdlib.h>
56+#include <string.h>
57+
58+#if !defined(inline)
59+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
60+#define constant_inline inline
61+#elif defined(__GNUC__) && __GNUC__ >= 2
62+#elif defined(__GNUC__) && __GNUC__ >= 2
63+#elif defined(_MSC_VER)
64+#define constant_inline __inline
65+#else
66+#define constant_inline
67+#endif
68+#else /* use what caller wants as inline may be from config.h */
69+#define constant_inline inline /* inline */
70+#endif
71+
72+/*-
73+ * The boolean methods return a bitmask of all ones (0xff...f) for true
74+ * and 0 for false. For example,
75+ * if (a < b) {
76+ * c = a;
77+ * } else {
78+ * c = b;
79+ * }
80+ * can be written as
81+ * unsigned int lt = constant_time_lt(a, b);
82+ * c = constant_time_select(lt, a, b);
83+ */
84+
85+static constant_inline unsigned int
86+value_barrier(unsigned int a)
87+{
88+ volatile unsigned int r = a;
89+ return r;
90+}
91+
92+static constant_inline size_t
93+value_barrier_s(size_t a)
94+{
95+ volatile size_t r = a;
96+ return r;
97+}
98+
99+/* MSB */
100+static constant_inline size_t
101+constant_time_msb_s(size_t a)
102+{
103+ return 0 - (a >> (sizeof(a) * 8 - 1));
104+}
105+
106+static constant_inline unsigned int
107+constant_time_msb(unsigned int a)
108+{
109+ return 0 - (a >> (sizeof(a) * 8 - 1));
110+}
111+
112+/* Select */
113+static constant_inline unsigned int
114+constant_time_select(unsigned int mask, unsigned int a, unsigned int b)
115+{
116+ return (value_barrier(mask) & a) | (value_barrier(~mask) & b);
117+}
118+
119+static constant_inline unsigned char
120+constant_time_select_8(unsigned char mask, unsigned char a, unsigned char b)
121+{
122+ return (unsigned char)constant_time_select(mask, a, b);
123+}
124+
125+static constant_inline size_t
126+constant_time_select_s(size_t mask, size_t a, size_t b)
127+{
128+ return (value_barrier_s(mask) & a) | (value_barrier_s(~mask) & b);
129+}
130+
131+/* Zero */
132+static constant_inline unsigned int
133+constant_time_is_zero(unsigned int a)
134+{
135+ return constant_time_msb(~a & (a - 1));
136+}
137+
138+static constant_inline size_t
139+constant_time_is_zero_s(size_t a)
140+{
141+ return constant_time_msb_s(~a & (a - 1));
142+}
143+
144+/* Comparison*/
145+static constant_inline size_t
146+constant_time_lt_s(size_t a, size_t b)
147+{
148+ return constant_time_msb_s(a ^ ((a ^ b) | ((a - b) ^ b)));
149+}
150+
151+static constant_inline unsigned int
152+constant_time_lt(unsigned int a, unsigned int b)
153+{
154+ return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b)));
155+}
156+
157+static constant_inline unsigned int
158+constant_time_ge(unsigned int a, unsigned int b)
159+{
160+ return ~constant_time_lt(a, b);
161+}
162+
163+/* Equality*/
164+
165+static constant_inline unsigned int
166+constant_time_eq(unsigned int a, unsigned int b)
167+{
168+ return constant_time_is_zero(a ^ b);
169+}
170+
171+static constant_inline size_t
172+constant_time_eq_s(size_t a, size_t b)
173+{
174+ return constant_time_is_zero_s(a ^ b);
175+}
176+
177+#endif /* CONSTANT_TIME_H */
178diff --git a/src/libopensc/internal.h b/src/libopensc/internal.h
179index e7ac63ccf..57568d311 100644
180--- a/src/libopensc/internal.h
181+++ b/src/libopensc/internal.h
182@@ -166,8 +166,8 @@ int _sc_card_add_xeddsa_alg(struct sc_card *card, unsigned int key_length,
183
184 int sc_pkcs1_strip_01_padding(struct sc_context *ctx, const u8 *in_dat, size_t in_len,
185 u8 *out_dat, size_t *out_len);
186-int sc_pkcs1_strip_02_padding(struct sc_context *ctx, const u8 *data, size_t len,
187- u8 *out_dat, size_t *out_len);
188+int sc_pkcs1_strip_02_padding_constant_time(sc_context_t *ctx, unsigned int n, const u8 *data,
189+ unsigned int data_len, u8 *out, unsigned int *out_len);
190 int sc_pkcs1_strip_digest_info_prefix(unsigned int *algorithm,
191 const u8 *in_dat, size_t in_len, u8 *out_dat, size_t *out_len);
192
193diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c
194index e4940ea2b..3a8b81c3f 100644
195--- a/src/libopensc/padding.c
196+++ b/src/libopensc/padding.c
197@@ -32,10 +32,13 @@
198 #include <string.h>
199 #include <stdlib.h>
200
201+#include "common/constant-time.h"
202 #include "internal.h"
203
204 /* TODO doxygen comments */
205
206+#define SC_PKCS1_PADDING_MIN_SIZE 11
207+
208 /*
209 * Prefixes for pkcs-v1 signatures
210 */
211@@ -143,45 +146,82 @@ sc_pkcs1_strip_01_padding(struct sc_context *ctx, const u8 *in_dat, size_t in_le
212 return SC_SUCCESS;
213 }
214
215-
216-/* remove pkcs1 BT02 padding (adding BT02 padding is currently not
217- * needed/implemented) */
218+/* Remove pkcs1 BT02 padding (adding BT02 padding is currently not
219+ * needed/implemented) in constant-time.
220+ * Original source: https://github.com/openssl/openssl/blob/9890cc42daff5e2d0cad01ac4bf78c391f599a6e/crypto/rsa/rsa_pk1.c#L171 */
221 int
222-sc_pkcs1_strip_02_padding(sc_context_t *ctx, const u8 *data, size_t len, u8 *out, size_t *out_len)
223+sc_pkcs1_strip_02_padding_constant_time(sc_context_t *ctx, unsigned int n, const u8 *data, unsigned int data_len, u8 *out, unsigned int *out_len)
224 {
225- unsigned int n = 0;
226-
227+ unsigned int i = 0;
228+ u8 *msg, *msg_orig = NULL;
229+ unsigned int good, found_zero_byte, mask;
230+ unsigned int zero_index = 0, msg_index, mlen = -1, len = 0;
231 LOG_FUNC_CALLED(ctx);
232- if (data == NULL || len < 3)
233+
234+ if (data == NULL || data_len <= 0 || data_len > n || n < SC_PKCS1_PADDING_MIN_SIZE)
235 LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
236
237- /* skip leading zero byte */
238- if (*data == 0) {
239- data++;
240- len--;
241+ msg = msg_orig = calloc(n, sizeof(u8));
242+ if (msg == NULL)
243+ LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
244+
245+ /*
246+ * We can not check length of input data straight away and still we need to read
247+ * from input even when the input is not as long as needed to keep the time constant.
248+ * If data has wrong size, it is padded by zeroes from left and the following checks
249+ * do not pass.
250+ */
251+ len = data_len;
252+ for (data += len, msg += n, i = 0; i < n; i++) {
253+ mask = ~constant_time_is_zero(len);
254+ len -= 1 & mask;
255+ data -= 1 & mask;
256+ *--msg = *data & mask;
257+ }
258+ // check first byte to be 0x00
259+ good = constant_time_is_zero(msg[0]);
260+ // check second byte to be 0x02
261+ good &= constant_time_eq(msg[1], 2);
262+
263+ // find zero byte after random data in padding
264+ found_zero_byte = 0;
265+ for (i = 2; i < n; i++) {
266+ unsigned int equals0 = constant_time_is_zero(msg[i]);
267+ zero_index = constant_time_select(~found_zero_byte & equals0, i, zero_index);
268+ found_zero_byte |= equals0;
269 }
270- if (data[0] != 0x02)
271- LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING);
272- /* skip over padding bytes */
273- for (n = 1; n < len && data[n]; n++)
274- ;
275- /* Must be at least 8 pad bytes */
276- if (n >= len || n < 9)
277- LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING);
278- n++;
279- if (out == NULL)
280- /* just check the padding */
281- LOG_FUNC_RETURN(ctx, SC_SUCCESS);
282
283- /* Now move decrypted contents to head of buffer */
284- if (*out_len < len - n)
285- LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
286- *out_len = len - n;
287- memmove(out, data + n, *out_len);
288+ // zero_index stands for index of last found zero
289+ good &= constant_time_ge(zero_index, 2 + 8);
290+
291+ // start of the actual message in data
292+ msg_index = zero_index + 1;
293+
294+ // length of message
295+ mlen = data_len - msg_index;
296+
297+ // check that message fits into out buffer
298+ good &= constant_time_ge(*out_len, mlen);
299+
300+ // move the result in-place by |num|-SC_PKCS1_PADDING_MIN_SIZE-|mlen| bytes to the left.
301+ *out_len = constant_time_select(constant_time_lt(n - SC_PKCS1_PADDING_MIN_SIZE, *out_len),
302+ n - SC_PKCS1_PADDING_MIN_SIZE, *out_len);
303+ for (msg_index = 1; msg_index < n - SC_PKCS1_PADDING_MIN_SIZE; msg_index <<= 1) {
304+ mask = ~constant_time_eq(msg_index & (n - SC_PKCS1_PADDING_MIN_SIZE - mlen), 0);
305+ for (i = SC_PKCS1_PADDING_MIN_SIZE; i < n - msg_index; i++)
306+ msg[i] = constant_time_select_8(mask, msg[i + msg_index], msg[i]);
307+ }
308+ // move message into out buffer, if good
309+ for (i = 0; i < *out_len; i++) {
310+ unsigned int msg_index;
311+ // when out is longer than message in data, use some bogus index in msg
312+ mask = good & constant_time_lt(i, mlen);
313+ msg_index = constant_time_select(mask, i + SC_PKCS1_PADDING_MIN_SIZE, 0); // to now overflow msg buffer
314+ out[i] = constant_time_select_8(mask, msg[msg_index], out[i]);
315+ }
316
317- sc_log(ctx, "stripped output(%"SC_FORMAT_LEN_SIZE_T"u): %s", len - n,
318- sc_dump_hex(out, len - n));
319- LOG_FUNC_RETURN(ctx, len - n);
320+ free(msg_orig);
321+ return constant_time_select(good, mlen, SC_ERROR_WRONG_PADDING);
322 }
323
324 /* add/remove DigestInfo prefix */
325diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c
326index b86cb77c3..cea46798a 100644
327--- a/src/libopensc/pkcs15-sec.c
328+++ b/src/libopensc/pkcs15-sec.c
329@@ -308,8 +308,9 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
330
331 /* Strip any padding */
332 if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
333- size_t s = r;
334- r = sc_pkcs1_strip_02_padding(ctx, out, s, out, &s);
335+ int s = r;
336+ int key_size = alg_info->key_length;
337+ r = sc_pkcs1_strip_02_padding_constant_time(ctx, key_size / 8, out, s, out, &s);
338 LOG_TEST_RET(ctx, r, "Invalid PKCS#1 padding");
339 }
340
341diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c
342index 0c089feab..e4d693a09 100644
343--- a/src/minidriver/minidriver.c
344+++ b/src/minidriver/minidriver.c
345@@ -4582,9 +4582,9 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData,
346 "sc_pkcs15_decipher: DECRYPT-INFO dwVersion=%lu\n",
347 (unsigned long)pInfo->dwVersion);
348 if (pInfo->dwPaddingType == CARD_PADDING_PKCS1) {
349- size_t temp = pInfo->cbData;
350+ unsigned int temp = pInfo->cbData;
351 logprintf(pCardData, 2, "sc_pkcs15_decipher: stripping PKCS1 padding\n");
352- r = sc_pkcs1_strip_02_padding(vs->ctx, pbuf2, pInfo->cbData, pbuf2, &temp);
353+ r = sc_pkcs1_strip_02_padding_constant_time(vs->ctx, prkey_info->modulus_length / 8, pbuf2, pInfo->cbData, pbuf2, &temp);
354 pInfo->cbData = (DWORD) temp;
355 if (r < 0) {
356 logprintf(pCardData, 2, "Cannot strip PKCS1 padding: %i\n", r);
357--
3582.50.0
359
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0002.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0002.patch
new file mode 100644
index 0000000000..6f3ca502ee
--- /dev/null
+++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0002.patch
@@ -0,0 +1,269 @@
1From c5ffd28572765a957ecadc8593c0bf0a596f535f Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
3Date: Mon, 13 Nov 2023 14:31:08 +0100
4Subject: [PATCH 02/10] Add unit tests for PKCS#1 v1.5 de-padding
5
6CVE: CVE-2023-5992
7Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/2948]
8
9Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com>
10---
11 src/tests/unittests/Makefile.am | 5 +-
12 src/tests/unittests/Makefile.mak | 5 +-
13 src/tests/unittests/strip_pkcs1_2_padding.c | 204 ++++++++++++++++++++
14 3 files changed, 210 insertions(+), 4 deletions(-)
15 create mode 100644 src/tests/unittests/strip_pkcs1_2_padding.c
16
17diff --git a/src/tests/unittests/Makefile.am b/src/tests/unittests/Makefile.am
18index 03019c324..4ef1c7206 100644
19--- a/src/tests/unittests/Makefile.am
20+++ b/src/tests/unittests/Makefile.am
21@@ -6,8 +6,8 @@ include $(top_srcdir)/aminclude_static.am
22 clean-local: code-coverage-clean
23 distclean-local: code-coverage-dist-clean
24
25-noinst_PROGRAMS = asn1 simpletlv cachedir
26-TESTS = asn1 simpletlv cachedir
27+noinst_PROGRAMS = asn1 simpletlv cachedir strip_pkcs1_2_padding
28+TESTS = asn1 simpletlv cachedir strip_pkcs1_2_padding
29
30 noinst_HEADERS = torture.h
31
32@@ -23,6 +23,7 @@ LDADD = $(top_builddir)/src/libopensc/libopensc.la \
33 asn1_SOURCES = asn1.c
34 simpletlv_SOURCES = simpletlv.c
35 cachedir_SOURCES = cachedir.c
36+strip_pkcs1_2_padding = strip_pkcs1_2_padding.c
37
38 if ENABLE_ZLIB
39 noinst_PROGRAMS += compression
40diff --git a/src/tests/unittests/Makefile.mak b/src/tests/unittests/Makefile.mak
41index 41762fdbf..a04086a67 100644
42--- a/src/tests/unittests/Makefile.mak
43+++ b/src/tests/unittests/Makefile.mak
44@@ -1,9 +1,10 @@
45 TOPDIR = ..\..\..
46
47-TARGETS = asn1 compression
48+TARGETS = asn1 compression strip_pkcs1_2_padding
49
50 OBJECTS = asn1.obj \
51- compression.obj
52+ compression.obj \
53+ strip_pkcs1_2_padding.obj \
54 $(TOPDIR)\win32\versioninfo.res
55
56 all: $(TARGETS)
57diff --git a/src/tests/unittests/strip_pkcs1_2_padding.c b/src/tests/unittests/strip_pkcs1_2_padding.c
58new file mode 100644
59index 000000000..f9561b936
60--- /dev/null
61+++ b/src/tests/unittests/strip_pkcs1_2_padding.c
62@@ -0,0 +1,204 @@
63+#include "common/compat_strlcpy.c"
64+#include "libopensc/log.c"
65+#include "libopensc/padding.c"
66+#include "torture.h"
67+#include <cmocka.h>
68+
69+static void
70+torture_long_output_buffer(void **state)
71+{
72+ unsigned int n = 14;
73+ unsigned int in_len = 14;
74+ unsigned char in[] = {0x00, 0x02,
75+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
76+ 0x00,
77+ 'm', 's', 'g'};
78+ unsigned int out_len = 3;
79+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
80+ unsigned char result_msg[] = {'m', 's', 'g'};
81+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
82+ assert_int_equal(r, 3);
83+ assert_memory_equal(out, result_msg, r);
84+ free(out);
85+}
86+
87+static void
88+torture_short_output_buffer(void **state)
89+{
90+ unsigned int n = 14;
91+ unsigned int in_len = 14;
92+ unsigned char in[] = {0x00, 0x02,
93+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
94+ 0x00,
95+ 'm', 's', 'g'};
96+ unsigned int out_len = 1;
97+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
98+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
99+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
100+ free(out);
101+}
102+
103+static void
104+torture_short_message_correct_padding(void **state)
105+{
106+ unsigned int n = 14;
107+ unsigned int in_len = 14;
108+ unsigned char in[] = {0x00, 0x02,
109+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
110+ 0x00,
111+ 'm', 's', 'g'};
112+ unsigned int out_len = 3;
113+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
114+ unsigned char result_msg[] = {'m', 's', 'g'};
115+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
116+ assert_int_equal(r, 3);
117+ assert_memory_equal(out, result_msg, r);
118+ free(out);
119+}
120+
121+static void
122+torture_missing_first_zero(void **state)
123+{
124+ unsigned int n = 13;
125+ unsigned int in_len = 13;
126+ unsigned char in[] = {0x02,
127+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
128+ 0x00,
129+ 'm', 's', 'g'};
130+ unsigned int out_len = 10;
131+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
132+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
133+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
134+ free(out);
135+}
136+
137+static void
138+torture_missing_two(void **state)
139+{
140+ unsigned int n = 13;
141+ unsigned int in_len = 13;
142+ unsigned char in[] = {0x00,
143+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
144+ 0x00,
145+ 'm', 's', 'g'};
146+ unsigned int out_len = 10;
147+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
148+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
149+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
150+ free(out);
151+}
152+
153+static void
154+torture_short_padding(void **state)
155+{
156+ unsigned int n = 13;
157+ unsigned int in_len = 13;
158+ unsigned char in[] = {0x00, 0x02,
159+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
160+ 0x00,
161+ 'm', 's', 'g'};
162+ unsigned int out_len = 10;
163+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
164+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
165+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
166+ free(out);
167+}
168+
169+static void
170+torture_missing_second_zero(void **state)
171+{
172+ unsigned int n = 13;
173+ unsigned int in_len = 13;
174+ unsigned char in[] = {0x00, 0x02,
175+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
176+ 'm', 's', 'g'};
177+ unsigned int out_len = 10;
178+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
179+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
180+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
181+ free(out);
182+}
183+
184+static void
185+torture_missing_message(void **state)
186+{
187+ unsigned int n = 20;
188+ unsigned int in_len = 11;
189+ unsigned char in[] = {0x00, 0x02,
190+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
191+ 0x00};
192+ unsigned int out_len = 11;
193+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
194+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
195+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
196+ free(out);
197+}
198+
199+static void
200+torture_one_byte_message(void **state)
201+{
202+ unsigned int n = 12;
203+ unsigned int in_len = 12;
204+ unsigned char in[] = {0x00, 0x02,
205+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
206+ 0x00,
207+ 'm'};
208+ unsigned int out_len = 1;
209+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
210+ unsigned char result_msg[] = {'m'};
211+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
212+ assert_int_equal(r, 1);
213+ assert_memory_equal(out, result_msg, r);
214+ free(out);
215+}
216+
217+static void
218+torture_longer_padding(void **state)
219+{
220+ unsigned int n = 26;
221+ unsigned int in_len = 26;
222+ unsigned char in[] = {0x00, 0x02,
223+ 0x0e, 0x38, 0x97, 0x18, 0x16, 0x57, 0x9e, 0x30, 0xb6, 0xa5, 0x78, 0x13, 0x20, 0xca, 0x11,
224+ 0x00,
225+ 0x9d, 0x98, 0x3d, 0xca, 0xa9, 0xa7, 0x11, 0x0a};
226+ unsigned int out_len = 8;
227+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
228+ unsigned char result_msg[] = {0x9d, 0x98, 0x3d, 0xca, 0xa9, 0xa7, 0x11, 0x0a};
229+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
230+ assert_int_equal(r, 8);
231+ assert_memory_equal(out, result_msg, r);
232+ free(out);
233+}
234+
235+static void
236+torture_empty_message(void **state)
237+{
238+ unsigned int n = 18;
239+ unsigned int in_len = 18;
240+ unsigned char in[] = {0x00, 0x02,
241+ 0x0e, 0x38, 0x97, 0x18, 0x16, 0x57, 0x9e, 0x30, 0xb6, 0xa5, 0x78, 0x13, 0x20, 0xca, 0x11,
242+ 0x00};
243+ unsigned int out_len = 8;
244+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
245+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
246+ assert_int_equal(r, 0);
247+ free(out);
248+}
249+
250+int
251+main(void)
252+{
253+ const struct CMUnitTest tests[] = {
254+ cmocka_unit_test(torture_long_output_buffer),
255+ cmocka_unit_test(torture_short_output_buffer),
256+ cmocka_unit_test(torture_short_message_correct_padding),
257+ cmocka_unit_test(torture_missing_first_zero),
258+ cmocka_unit_test(torture_missing_two),
259+ cmocka_unit_test(torture_short_padding),
260+ cmocka_unit_test(torture_missing_second_zero),
261+ cmocka_unit_test(torture_missing_message),
262+ cmocka_unit_test(torture_one_byte_message),
263+ cmocka_unit_test(torture_longer_padding),
264+ cmocka_unit_test(torture_empty_message)};
265+ return cmocka_run_group_tests(tests, NULL, NULL);
266+}
267--
2682.50.0
269
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0003.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0003.patch
new file mode 100644
index 0000000000..52a73064dc
--- /dev/null
+++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0003.patch
@@ -0,0 +1,41 @@
1From 7266f151bb5896b9213d4cf0a298859a53cfb750 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
3Date: Thu, 16 Nov 2023 10:38:12 +0100
4Subject: [PATCH 03/10] pkcs15-sec: Remove logging after PKCS#1 v1.5 depadding
5
6To prevent Marvin attack on RSA PKCS#1 v1.5 padding
7when logging the return value, signaling the padding error.
8
9CVE: CVE-2023-5992
10Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/2948]
11
12Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com>
13---
14 src/libopensc/pkcs15-sec.c | 8 ++++----
15 1 file changed, 4 insertions(+), 4 deletions(-)
16
17diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c
18index cea46798a..b04856b4d 100644
19--- a/src/libopensc/pkcs15-sec.c
20+++ b/src/libopensc/pkcs15-sec.c
21@@ -308,13 +308,13 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
22
23 /* Strip any padding */
24 if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
25- int s = r;
26- int key_size = alg_info->key_length;
27+ unsigned int s = r;
28+ unsigned int key_size = (unsigned int)alg_info->key_length;
29 r = sc_pkcs1_strip_02_padding_constant_time(ctx, key_size / 8, out, s, out, &s);
30- LOG_TEST_RET(ctx, r, "Invalid PKCS#1 padding");
31+ /* for keeping PKCS#1 v1.5 depadding constant-time, do not log error here */
32 }
33
34- LOG_FUNC_RETURN(ctx, r);
35+ return r;
36 }
37
38 /* derive one key from another. RSA can use decipher, so this is for only ECDH
39--
402.50.0
41
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0004.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0004.patch
new file mode 100644
index 0000000000..459e1d2a61
--- /dev/null
+++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0004.patch
@@ -0,0 +1,109 @@
1From 663dcbae0d92a05eba28ca56b80346b2fbe5a6d5 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
3Date: Thu, 16 Nov 2023 15:49:15 +0100
4Subject: [PATCH 04/10] framework-pkcs15.c: Handle PKCS#1 v1.5 depadding
5 constant-time
6
7In order to not disclose time side-channel when the depadding
8fails, do the same operations as for case when depadding ends
9with success.
10
11CVE: CVE-2023-5992
12Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/2948]
13
14Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com>
15---
16 src/pkcs11/framework-pkcs15.c | 54 ++++++++++++++++++++++++++---------
17 1 file changed, 41 insertions(+), 13 deletions(-)
18
19diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c
20index 4fc8f13ab..8376057ea 100644
21--- a/src/pkcs11/framework-pkcs15.c
22+++ b/src/pkcs11/framework-pkcs15.c
23@@ -18,6 +18,7 @@
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27+#include "common/constant-time.h"
28 #include "config.h"
29 #include <stdlib.h>
30 #include <string.h>
31@@ -4341,7 +4342,8 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *session, void *obj,
32 struct pkcs15_fw_data *fw_data = NULL;
33 struct pkcs15_prkey_object *prkey;
34 unsigned char decrypted[512]; /* FIXME: Will not work for keys above 4096 bits */
35- int buff_too_small, rv, flags = 0, prkey_has_path = 0;
36+ int rv, flags = 0, prkey_has_path = 0;
37+ CK_ULONG mask, good, rv_pkcs11;
38
39 sc_log(context, "Initiating decryption.");
40
41@@ -4415,27 +4417,53 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *session, void *obj,
42 rv = sc_pkcs15_decipher(fw_data->p15_card, prkey->prv_p15obj, flags,
43 pEncryptedData, ulEncryptedDataLen, decrypted, sizeof(decrypted));
44
45- if (rv < 0 && !sc_pkcs11_conf.lock_login && !prkey_has_path)
46+ /* skip for PKCS#1 v1.5 padding prevent side channel attack */
47+ if (!(flags & SC_ALGORITHM_RSA_PAD_PKCS1) &&
48+ rv < 0 && !sc_pkcs11_conf.lock_login && !prkey_has_path)
49 if (reselect_app_df(fw_data->p15_card) == SC_SUCCESS)
50 rv = sc_pkcs15_decipher(fw_data->p15_card, prkey->prv_p15obj, flags,
51 pEncryptedData, ulEncryptedDataLen, decrypted, sizeof(decrypted));
52
53 sc_unlock(p11card->card);
54
55- sc_log(context, "Decryption complete. Result %d.", rv);
56+ sc_log(context, "Decryption complete.");
57
58- if (rv < 0)
59- return sc_to_cryptoki_error(rv, "C_Decrypt");
60+ /* Handle following code in constant-time
61+ * to prevent Marvin attack for PKCS#1 v1.5 padding. */
62
63- buff_too_small = (*pulDataLen < (CK_ULONG)rv);
64- *pulDataLen = rv;
65- if (pData == NULL_PTR)
66- return CKR_OK;
67- if (buff_too_small)
68- return CKR_BUFFER_TOO_SMALL;
69- memcpy(pData, decrypted, *pulDataLen);
70+ /* only padding error must be handled in constant-time way,
71+ * other error can be returned straight away */
72+ if ((~constant_time_eq_s(rv, SC_ERROR_WRONG_PADDING) & constant_time_lt_s(sizeof(decrypted), rv)))
73+ return sc_to_cryptoki_error(rv, "C_Decrypt");
74
75- return CKR_OK;
76+ /* check rv for padding error */
77+ good = ~constant_time_eq_s(rv, SC_ERROR_WRONG_PADDING);
78+ rv_pkcs11 = sc_to_cryptoki_error(SC_ERROR_WRONG_PADDING, "C_Decrypt");
79+ rv_pkcs11 = constant_time_select_s(good, CKR_OK, rv_pkcs11);
80+
81+ if (pData == NULL_PTR) {
82+ /* set length only if no error */
83+ *pulDataLen = constant_time_select_s(good, rv, *pulDataLen);
84+ /* return error only if original rv < 0 */
85+ return rv_pkcs11;
86+ }
87+
88+ /* check whether *pulDataLen < rv and set return value for small output buffer */
89+ mask = good & constant_time_lt_s(*pulDataLen, rv);
90+ rv_pkcs11 = constant_time_select_s(mask, CKR_BUFFER_TOO_SMALL, rv_pkcs11);
91+ good &= ~mask;
92+
93+ /* move everything from decrypted into out buffer constant-time, if rv is ok */
94+ for (CK_ULONG i = 0; i < *pulDataLen; i++) { /* iterate over whole pData to not disclose real depadded length */
95+ CK_ULONG msg_index;
96+ mask = good & constant_time_lt_s(i, sizeof(decrypted)); /* i should be in the bounds of decrypted */
97+ mask &= constant_time_lt_s(i, constant_time_select_s(good, rv, 0)); /* check that is in bounds of depadded message */
98+ msg_index = constant_time_select_s(mask, i, 0);
99+ pData[i] = constant_time_select_8(mask, decrypted[msg_index], pData[i]);
100+ }
101+ *pulDataLen = constant_time_select_s(good, rv, *pulDataLen);
102+ /* do not log error code to prevent side channel attack */
103+ return rv_pkcs11;
104 }
105
106
107--
1082.50.0
109
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0005.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0005.patch
new file mode 100644
index 0000000000..a52b964306
--- /dev/null
+++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0005.patch
@@ -0,0 +1,63 @@
1From f7fc30b02090d657b9ba64cbb5168cb5a94592ef Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
3Date: Mon, 8 Jan 2024 14:59:22 +0100
4Subject: [PATCH 05/10] mechanism: Handle PKCS#1 v1.5 depadding constant-time
5
6CVE: CVE-2023-5992
7Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/2948]
8
9Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com>
10---
11 src/pkcs11/mechanism.c | 15 +++++++++++++--
12 1 file changed, 13 insertions(+), 2 deletions(-)
13
14diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c
15index c5959b36b..b3fce1714 100644
16--- a/src/pkcs11/mechanism.c
17+++ b/src/pkcs11/mechanism.c
18@@ -23,6 +23,7 @@
19 #include <stdlib.h>
20 #include <string.h>
21
22+#include "common/constant-time.h"
23 #include "sc-pkcs11.h"
24
25 /* Also used for verification data */
26@@ -844,7 +845,9 @@ sc_pkcs11_decr(struct sc_pkcs11_session *session,
27 rv = op->type->decrypt(op, pEncryptedData, ulEncryptedDataLen,
28 pData, pulDataLen);
29
30- if (rv != CKR_BUFFER_TOO_SMALL && pData != NULL)
31+ /* terminate session for any return value except CKR_BUFFER_TOO_SMALL,
32+ * perform check in time side-channel free way to prevent Marvin attack */
33+ if (!constant_time_eq_s(rv, CKR_BUFFER_TOO_SMALL) && pData != NULL)
34 session_stop_operation(session, SC_PKCS11_OPERATION_DECRYPT);
35
36 return rv;
37@@ -1084,14 +1087,22 @@ sc_pkcs11_decrypt(sc_pkcs11_operation_t *operation,
38 {
39 struct signature_data *data;
40 struct sc_pkcs11_object *key;
41+ CK_RV rv;
42
43 data = (struct signature_data*) operation->priv_data;
44
45 key = data->key;
46- return key->ops->decrypt(operation->session,
47+ rv = key->ops->decrypt(operation->session,
48 key, &operation->mechanism,
49 pEncryptedData, ulEncryptedDataLen,
50 pData, pulDataLen);
51+
52+ /* Skip DecryptFinalize for PKCS#1 v1.5 padding to prevent time side-channel leakage */
53+ if (((CK_MECHANISM_PTR)&operation->mechanism)->mechanism == CKM_RSA_PKCS)
54+ return rv;
55+
56+ if (rv != CKR_OK)
57+ return rv;
58 }
59
60 static CK_RV
61--
622.50.0
63
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0006.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0006.patch
new file mode 100644
index 0000000000..b9c1f8ce3e
--- /dev/null
+++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0006.patch
@@ -0,0 +1,118 @@
1From 224a5a9bb32a8eb575dc30f18004c069c62fc8b1 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
3Date: Wed, 22 Nov 2023 15:02:57 +0100
4Subject: [PATCH 06/10] minidriver: Make CardRSADecrypt constant-time
5
6CVE: CVE-2023-5992
7Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/2948]
8
9Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com>
10---
11 src/minidriver/minidriver.c | 36 +++++++++++++++++++++++-------------
12 1 file changed, 23 insertions(+), 13 deletions(-)
13
14diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c
15index e4d693a09..37e576ba2 100644
16--- a/src/minidriver/minidriver.c
17+++ b/src/minidriver/minidriver.c
18@@ -41,6 +41,7 @@
19 #include "cardmod.h"
20
21 #include "common/compat_strlcpy.h"
22+#include "common/constant-time.h"
23 #include "libopensc/asn1.h"
24 #include "libopensc/cardctl.h"
25 #include "libopensc/opensc.h"
26@@ -4463,13 +4464,15 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData,
27
28 {
29 DWORD dwret;
30- int r, opt_crypt_flags = 0;
31+ int r, opt_crypt_flags = 0, good = 0;
32 unsigned ui;
33 VENDOR_SPECIFIC *vs;
34 struct sc_pkcs15_prkey_info *prkey_info;
35 BYTE *pbuf = NULL, *pbuf2 = NULL;
36 struct sc_pkcs15_object *pkey = NULL;
37 struct sc_algorithm_info *alg_info = NULL;
38+ unsigned int wrong_padding = 0;
39+ unsigned int pbufLen = 0;
40
41 MD_FUNC_CALLED(pCardData, 1);
42
43@@ -4570,10 +4573,11 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData,
44 goto err;
45 }
46
47+ pbufLen = pInfo->cbData;
48 if (alg_info->flags & SC_ALGORITHM_RSA_RAW) {
49 logprintf(pCardData, 2, "sc_pkcs15_decipher: using RSA-RAW mechanism\n");
50 r = sc_pkcs15_decipher(vs->p15card, pkey, opt_crypt_flags, pbuf, pInfo->cbData, pbuf2, pInfo->cbData);
51- logprintf(pCardData, 2, "sc_pkcs15_decipher returned %d\n", r);
52+ /* do not log return value to not leak it */
53
54 if (r > 0) {
55 /* Need to handle padding */
56@@ -4586,13 +4590,9 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData,
57 logprintf(pCardData, 2, "sc_pkcs15_decipher: stripping PKCS1 padding\n");
58 r = sc_pkcs1_strip_02_padding_constant_time(vs->ctx, prkey_info->modulus_length / 8, pbuf2, pInfo->cbData, pbuf2, &temp);
59 pInfo->cbData = (DWORD) temp;
60- if (r < 0) {
61- logprintf(pCardData, 2, "Cannot strip PKCS1 padding: %i\n", r);
62- pCardData->pfnCspFree(pbuf);
63- pCardData->pfnCspFree(pbuf2);
64- dwret = SCARD_F_INTERNAL_ERROR;
65- goto err;
66- }
67+ wrong_padding = constant_time_eq_s(r, SC_ERROR_WRONG_PADDING);
68+ /* continue without returning error to not leak that padding is wrong
69+ to prevent time side-channel leak for Marvin attack*/
70 }
71 else if (pInfo->dwPaddingType == CARD_PADDING_OAEP) {
72 /* TODO: Handle OAEP padding if present - can call PFN_CSP_UNPAD_DATA */
73@@ -4640,28 +4640,38 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData,
74 goto err;
75 }
76
77- if ( r < 0) {
78+ good = constant_time_eq_s(r, 0);
79+ /* if no error or padding error, do not return here to prevent Marvin attack */
80+ if (!(good | wrong_padding) && r < 0) {
81 logprintf(pCardData, 2, "sc_pkcs15_decipher error(%i): %s\n", r, sc_strerror(r));
82 pCardData->pfnCspFree(pbuf);
83 pCardData->pfnCspFree(pbuf2);
84 dwret = md_translate_OpenSC_to_Windows_error(r, SCARD_E_INVALID_VALUE);
85 goto err;
86 }
87+ dwret = constant_time_select_s(good, SCARD_S_SUCCESS, SCARD_F_INTERNAL_ERROR);
88
89 logprintf(pCardData, 2, "decrypted data(%lu):\n",
90 (unsigned long)pInfo->cbData);
91 loghex(pCardData, 7, pbuf2, pInfo->cbData);
92
93 /*inversion donnees */
94- for(ui = 0; ui < pInfo->cbData; ui++)
95- pInfo->pbData[ui] = pbuf2[pInfo->cbData-ui-1];
96+ /* copy data in constant-time way to prevent leak */
97+ for (ui = 0; ui < pbufLen; ui++) {
98+ unsigned int mask, msg_index, inv_ui;
99+ mask = good & constant_time_lt_s(ui, pInfo->cbData); /* ui should be in the bounds of pbuf2 */
100+ inv_ui = pInfo->cbData - ui - 1;
101+ msg_index = constant_time_select_s(mask, inv_ui, 0);
102+ pInfo->pbData[ui] = constant_time_select_8(mask, pbuf2[msg_index], pInfo->pbData[ui]);
103+ }
104
105 pCardData->pfnCspFree(pbuf);
106 pCardData->pfnCspFree(pbuf2);
107
108 err:
109 unlock(pCardData);
110- MD_FUNC_RETURN(pCardData, 1, dwret);
111+ /* do not log return value to not leak it */
112+ return dwret;
113 }
114
115
116--
1172.50.0
118
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0007.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0007.patch
new file mode 100644
index 0000000000..ccd44833fa
--- /dev/null
+++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0007.patch
@@ -0,0 +1,50 @@
1From 65f81aa8cdb8fa7e3c54165c9c800e6dae5591c7 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
3Date: Fri, 24 Nov 2023 20:59:07 +0100
4Subject: [PATCH 07/10] pkcs11-object: Remove return value logging
5
6To prevent Marvin attack on RSA PKCS#1 v1.5 padding
7when logging the return value, signaling the padding error.
8
9CVE: CVE-2023-5992
10Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/2948]
11
12Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com>
13---
14 src/pkcs11/pkcs11-object.c | 3 ++-
15 src/pkcs11/sc-pkcs11.h | 5 +++++
16 2 files changed, 7 insertions(+), 1 deletion(-)
17
18diff --git a/src/pkcs11/pkcs11-object.c b/src/pkcs11/pkcs11-object.c
19index c5cf78a2b..aae149b86 100644
20--- a/src/pkcs11/pkcs11-object.c
21+++ b/src/pkcs11/pkcs11-object.c
22@@ -930,7 +930,8 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, /* the session's handle */
23 rv = reset_login_state(session->slot, rv);
24 }
25
26- sc_log(context, "C_Decrypt() = %s", lookup_enum ( RV_T, rv ));
27+ /* do not log error code to prevent side channel attack */
28+ SC_LOG("C_Decrypt()");
29 sc_pkcs11_unlock();
30 return rv;
31 }
32diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h
33index 3c6b92ba4..35c8d5eb3 100644
34--- a/src/pkcs11/sc-pkcs11.h
35+++ b/src/pkcs11/sc-pkcs11.h
36@@ -226,6 +226,11 @@ struct sc_pkcs11_slot {
37 };
38 typedef struct sc_pkcs11_slot sc_pkcs11_slot_t;
39
40+#define SC_LOG(fmt) \
41+ do { \
42+ sc_log(context, (fmt)); \
43+ } while (0)
44+
45 /* Debug virtual slots. S is slot to be highlighted or NULL
46 * C is a comment format string and args It will be preceded by "VSS " */
47 #define DEBUG_VSS(S, ...) do { sc_log(context,"VSS " __VA_ARGS__); _debug_virtual_slots(S); } while (0)
48--
492.50.0
50
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0008.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0008.patch
new file mode 100644
index 0000000000..d50337902d
--- /dev/null
+++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0008.patch
@@ -0,0 +1,37 @@
1From 60f1966c06ed5fbe9e9e1edeefa2d280f5341484 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
3Date: Fri, 24 Nov 2023 21:00:23 +0100
4Subject: [PATCH 08/10] misc: Compare return value constant-time
5
6CVE: CVE-2023-5992
7Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/2948]
8
9Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com>
10---
11 src/pkcs11/misc.c | 3 ++-
12 1 file changed, 2 insertions(+), 1 deletion(-)
13
14diff --git a/src/pkcs11/misc.c b/src/pkcs11/misc.c
15index c3f5bb4e1..c0fd07240 100644
16--- a/src/pkcs11/misc.c
17+++ b/src/pkcs11/misc.c
18@@ -23,6 +23,7 @@
19 #include <stdlib.h>
20 #include <string.h>
21
22+#include "common/constant-time.h"
23 #include "sc-pkcs11.h"
24
25 #define DUMP_TEMPLATE_MAX 32
26@@ -172,7 +173,7 @@ CK_RV reset_login_state(struct sc_pkcs11_slot *slot, CK_RV rv)
27 slot->p11card->framework->logout(slot);
28 }
29
30- if (rv == CKR_USER_NOT_LOGGED_IN) {
31+ if (constant_time_eq_s(rv, CKR_USER_NOT_LOGGED_IN)) {
32 slot->login_user = -1;
33 pop_all_login_states(slot);
34 }
35--
362.50.0
37
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0009.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0009.patch
new file mode 100644
index 0000000000..d65555bca9
--- /dev/null
+++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0009.patch
@@ -0,0 +1,123 @@
1From e5f77a60bf22d76f695e360cc5c13c5c9ea8ba0c Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
3Date: Mon, 5 Feb 2024 11:30:11 +0100
4Subject: [PATCH 09/10] unittests: Do not use uninitialized memory
5
6Thanks Coverity CID 414676, 414677, 414678,
7414679, 414680, 414681, 414682, 414683, 414684,
8414685, 414686
9
10CVE: CVE-2023-5992
11Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/3016]
12
13Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com>
14---
15 src/tests/unittests/strip_pkcs1_2_padding.c | 22 ++++++++++-----------
16 1 file changed, 11 insertions(+), 11 deletions(-)
17
18diff --git a/src/tests/unittests/strip_pkcs1_2_padding.c b/src/tests/unittests/strip_pkcs1_2_padding.c
19index f9561b936..990e94a38 100644
20--- a/src/tests/unittests/strip_pkcs1_2_padding.c
21+++ b/src/tests/unittests/strip_pkcs1_2_padding.c
22@@ -14,7 +14,7 @@ torture_long_output_buffer(void **state)
23 0x00,
24 'm', 's', 'g'};
25 unsigned int out_len = 3;
26- unsigned char *out = malloc(out_len * sizeof(unsigned char));
27+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
28 unsigned char result_msg[] = {'m', 's', 'g'};
29 int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
30 assert_int_equal(r, 3);
31@@ -32,7 +32,7 @@ torture_short_output_buffer(void **state)
32 0x00,
33 'm', 's', 'g'};
34 unsigned int out_len = 1;
35- unsigned char *out = malloc(out_len * sizeof(unsigned char));
36+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
37 int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
38 assert_int_equal(r, SC_ERROR_WRONG_PADDING);
39 free(out);
40@@ -48,7 +48,7 @@ torture_short_message_correct_padding(void **state)
41 0x00,
42 'm', 's', 'g'};
43 unsigned int out_len = 3;
44- unsigned char *out = malloc(out_len * sizeof(unsigned char));
45+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
46 unsigned char result_msg[] = {'m', 's', 'g'};
47 int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
48 assert_int_equal(r, 3);
49@@ -66,7 +66,7 @@ torture_missing_first_zero(void **state)
50 0x00,
51 'm', 's', 'g'};
52 unsigned int out_len = 10;
53- unsigned char *out = malloc(out_len * sizeof(unsigned char));
54+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
55 int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
56 assert_int_equal(r, SC_ERROR_WRONG_PADDING);
57 free(out);
58@@ -82,7 +82,7 @@ torture_missing_two(void **state)
59 0x00,
60 'm', 's', 'g'};
61 unsigned int out_len = 10;
62- unsigned char *out = malloc(out_len * sizeof(unsigned char));
63+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
64 int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
65 assert_int_equal(r, SC_ERROR_WRONG_PADDING);
66 free(out);
67@@ -98,7 +98,7 @@ torture_short_padding(void **state)
68 0x00,
69 'm', 's', 'g'};
70 unsigned int out_len = 10;
71- unsigned char *out = malloc(out_len * sizeof(unsigned char));
72+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
73 int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
74 assert_int_equal(r, SC_ERROR_WRONG_PADDING);
75 free(out);
76@@ -113,7 +113,7 @@ torture_missing_second_zero(void **state)
77 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
78 'm', 's', 'g'};
79 unsigned int out_len = 10;
80- unsigned char *out = malloc(out_len * sizeof(unsigned char));
81+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
82 int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
83 assert_int_equal(r, SC_ERROR_WRONG_PADDING);
84 free(out);
85@@ -128,7 +128,7 @@ torture_missing_message(void **state)
86 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
87 0x00};
88 unsigned int out_len = 11;
89- unsigned char *out = malloc(out_len * sizeof(unsigned char));
90+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
91 int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
92 assert_int_equal(r, SC_ERROR_WRONG_PADDING);
93 free(out);
94@@ -144,7 +144,7 @@ torture_one_byte_message(void **state)
95 0x00,
96 'm'};
97 unsigned int out_len = 1;
98- unsigned char *out = malloc(out_len * sizeof(unsigned char));
99+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
100 unsigned char result_msg[] = {'m'};
101 int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
102 assert_int_equal(r, 1);
103@@ -162,7 +162,7 @@ torture_longer_padding(void **state)
104 0x00,
105 0x9d, 0x98, 0x3d, 0xca, 0xa9, 0xa7, 0x11, 0x0a};
106 unsigned int out_len = 8;
107- unsigned char *out = malloc(out_len * sizeof(unsigned char));
108+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
109 unsigned char result_msg[] = {0x9d, 0x98, 0x3d, 0xca, 0xa9, 0xa7, 0x11, 0x0a};
110 int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
111 assert_int_equal(r, 8);
112@@ -179,7 +179,7 @@ torture_empty_message(void **state)
113 0x0e, 0x38, 0x97, 0x18, 0x16, 0x57, 0x9e, 0x30, 0xb6, 0xa5, 0x78, 0x13, 0x20, 0xca, 0x11,
114 0x00};
115 unsigned int out_len = 8;
116- unsigned char *out = malloc(out_len * sizeof(unsigned char));
117+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
118 int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
119 assert_int_equal(r, 0);
120 free(out);
121--
1222.50.0
123
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0010.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0010.patch
new file mode 100644
index 0000000000..2585406b56
--- /dev/null
+++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0010.patch
@@ -0,0 +1,75 @@
1From 0039fe386c996faffaa2cf2d728c176cc239468b Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
3Date: Mon, 5 Feb 2024 13:33:05 +0100
4Subject: [PATCH 10/10] Fix constant-time comparison of negative values
5
6Thanks Coverity CID 414687
7
8CVE: CVE-2023-5992
9Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/3016]
10
11Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com>
12---
13 src/common/constant-time.h | 6 ++++++
14 src/minidriver/minidriver.c | 4 ++--
15 src/pkcs11/framework-pkcs15.c | 4 ++--
16 3 files changed, 10 insertions(+), 4 deletions(-)
17
18diff --git a/src/common/constant-time.h b/src/common/constant-time.h
19index 40c3e500c..3f4446d4d 100644
20--- a/src/common/constant-time.h
21+++ b/src/common/constant-time.h
22@@ -125,4 +125,10 @@ constant_time_eq_s(size_t a, size_t b)
23 return constant_time_is_zero_s(a ^ b);
24 }
25
26+static constant_inline unsigned int
27+constant_time_eq_i(int a, int b)
28+{
29+ return constant_time_eq((unsigned int)a, (unsigned int)b);
30+}
31+
32 #endif /* CONSTANT_TIME_H */
33diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c
34index 37e576ba2..e2be9e53d 100644
35--- a/src/minidriver/minidriver.c
36+++ b/src/minidriver/minidriver.c
37@@ -4590,7 +4590,7 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData,
38 logprintf(pCardData, 2, "sc_pkcs15_decipher: stripping PKCS1 padding\n");
39 r = sc_pkcs1_strip_02_padding_constant_time(vs->ctx, prkey_info->modulus_length / 8, pbuf2, pInfo->cbData, pbuf2, &temp);
40 pInfo->cbData = (DWORD) temp;
41- wrong_padding = constant_time_eq_s(r, SC_ERROR_WRONG_PADDING);
42+ wrong_padding = constant_time_eq_i(r, SC_ERROR_WRONG_PADDING);
43 /* continue without returning error to not leak that padding is wrong
44 to prevent time side-channel leak for Marvin attack*/
45 }
46@@ -4640,7 +4640,7 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData,
47 goto err;
48 }
49
50- good = constant_time_eq_s(r, 0);
51+ good = constant_time_eq_i(r, 0);
52 /* if no error or padding error, do not return here to prevent Marvin attack */
53 if (!(good | wrong_padding) && r < 0) {
54 logprintf(pCardData, 2, "sc_pkcs15_decipher error(%i): %s\n", r, sc_strerror(r));
55diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c
56index 8376057ea..8b0a63b10 100644
57--- a/src/pkcs11/framework-pkcs15.c
58+++ b/src/pkcs11/framework-pkcs15.c
59@@ -4433,11 +4433,11 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *session, void *obj,
60
61 /* only padding error must be handled in constant-time way,
62 * other error can be returned straight away */
63- if ((~constant_time_eq_s(rv, SC_ERROR_WRONG_PADDING) & constant_time_lt_s(sizeof(decrypted), rv)))
64+ if ((~constant_time_eq_i(rv, SC_ERROR_WRONG_PADDING) & constant_time_lt_s(sizeof(decrypted), (size_t)rv)))
65 return sc_to_cryptoki_error(rv, "C_Decrypt");
66
67 /* check rv for padding error */
68- good = ~constant_time_eq_s(rv, SC_ERROR_WRONG_PADDING);
69+ good = ~constant_time_eq_i(rv, SC_ERROR_WRONG_PADDING);
70 rv_pkcs11 = sc_to_cryptoki_error(SC_ERROR_WRONG_PADDING, "C_Decrypt");
71 rv_pkcs11 = constant_time_select_s(good, CKR_OK, rv_pkcs11);
72
73--
742.50.0
75