[pkg-opensc-maint] Bug#1091207: bookworm-pu: package opensc/0.23.0-0.3+deb12u2

Guilhem Moulin guilhem at debian.org
Mon Dec 23 14:12:26 GMT 2024


Package: release.debian.org
Severity: normal
Tags: bookworm
X-Debbugs-Cc: opensc at packages.debian.org
Control: affects -1 + src:opensc
User: release.debian.org at packages.debian.org
Usertags: pu

[ Reason ]

Fix 9 no-dsa vulnerabilities (CVE-2023-5992, CVE-2024-1454, -8443 and
-45615 to -45620).

[ Impact ]

Users will remain vulnerable.  Furthermore the issues are about to be
patched in Bullseye LTS, leading to a regression when upgrading.

[ Tests ]

Only the fixes for CVE-2023-5992 (Marvin attack, a side-channel leak)
come with a unit test.  It is not run at build time, but I manually
checked that it passes.

The remaining issues are of type use after free, use of uninitialized
values, or heap buffer overflow, and stem for missing/incorrect bound
checks or initialization.  Upstream extended test suite is not run at
build time but doesn't yield any regression (also under valgrind).

[ Risks ]

There are a lot of patches but besides CVE-2023-5992/*.patch all of them
are trivial bound checks and/or variable initialization following
fuzzing and coverity results.

All patches come from upstream's 0.25 and 0.26 releases and trivially
apply to 0.23.0-0.3+deb12u1.

[ Checklist ]

  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach patch-applied debdiff against the package in stable
  [x] the issue is verified as fixed in unstable

[ Changes ]

  * Fix CVE-2023-5992: Side-channel leaks while stripping encryption PKCS#1.5
    padding in OpenSC. (Closes: #1064189)
  * Fix CVE-2024-1454: Memory use after free in AuthentIC driver when updating
    token info.
  * Fix CVE-2024-8443: Heap buffer overflow in OpenPGP driver when generating
    key. (Closes: #1082853)
  * Fix CVE-2024-45615: Usage of uninitialized values in libopensc and
    pkcs15init. (Closes: #1082859)
  * Fix CVE-2024-45616: Uninitialized values after incorrect check or usage of
    APDU response values in libopensc. (Closes: #1082860)
  * Fix CVE-2024-45617: Uninitialized values after incorrect or missing
    checking return values of functions in libopensc. (Closes: #1082861)
  * Fix CVE-2024-45618: Uninitialized values after incorrect or missing
    checking return values of functions in pkcs15init. (Closes: #1082862)
  * Fix CVE-2024-45619: Incorrect handling length of buffers or files in
    libopensc. (Closes: #1082863)
  * Fix CVE-2024-45620: Incorrect handling length of buffers or files in
    pkcs15init. (Closes: #1082864)
  * Add d/salsa-ci.yml for Salsa CI.

-- 
Guilhem.
-------------- next part --------------
diff -Nru --exclude '*.patch' opensc-0.23.0/debian/changelog opensc-0.23.0/debian/changelog
--- opensc-0.23.0/debian/changelog	2023-11-08 00:26:46.000000000 +0000
+++ opensc-0.23.0/debian/changelog	2024-12-22 18:35:04.000000000 +0000
@@ -1,3 +1,28 @@
+opensc (0.23.0-0.3+deb12u2) bookworm; urgency=medium
+
+  * Non-maintainer upload.
+  * Fix CVE-2023-5992: Side-channel leaks while stripping encryption PKCS#1.5
+    padding in OpenSC. (Closes: #1064189)
+  * Fix CVE-2024-1454: Memory use after free in AuthentIC driver when updating
+    token info.
+  * Fix CVE-2024-8443: Heap buffer overflow in OpenPGP driver when generating
+    key. (Closes: #1082853)
+  * Fix CVE-2024-45615: Usage of uninitialized values in libopensc and
+    pkcs15init. (Closes: #1082859)
+  * Fix CVE-2024-45616: Uninitialized values after incorrect check or usage of
+    APDU response values in libopensc. (Closes: #1082860)
+  * Fix CVE-2024-45617: Uninitialized values after incorrect or missing
+    checking return values of functions in libopensc. (Closes: #1082861)
+  * Fix CVE-2024-45618: Uninitialized values after incorrect or missing
+    checking return values of functions in pkcs15init. (Closes: #1082862)
+  * Fix CVE-2024-45619: Incorrect handling length of buffers or files in
+    libopensc. (Closes: #1082863)
+  * Fix CVE-2024-45620: Incorrect handling length of buffers or files in
+    pkcs15init. (Closes: #1082864)
+  * Add d/salsa-ci.yml for Salsa CI.
+
+ -- Guilhem Moulin <guilhem at debian.org>  Sun, 22 Dec 2024 19:35:04 +0100
+
 opensc (0.23.0-0.3+deb12u1) bookworm; urgency=medium
 
   * Team upload
diff -Nru --exclude '*.patch' opensc-0.23.0/debian/patches/series opensc-0.23.0/debian/patches/series
--- opensc-0.23.0/debian/patches/series	2023-11-08 00:26:46.000000000 +0000
+++ opensc-0.23.0/debian/patches/series	2024-12-22 18:35:04.000000000 +0000
@@ -12,3 +12,50 @@
 0013-CVE-2023-40661.patch
 0014-CVE-2023-40661.patch
 0015-CVE-2023-40661.patch
+CVE-2023-5992/01-e8883b1.patch
+CVE-2023-5992/02-bfe0e05.patch
+CVE-2023-5992/03-2ee8730.patch
+CVE-2023-5992/04-0494e46.patch
+CVE-2023-5992/05-5b5fcc9.patch
+CVE-2023-5992/06-e018f19.patch
+CVE-2023-5992/07-2d84cec.patch
+CVE-2023-5992/08-b31f82b.patch
+CVE-2023-5992/09-5747804.patch
+CVE-2023-5992/10-c153e2f.patch
+CVE-2023-5992/11-556cbf3.patch
+CVE-2023-5992/12-21a0a25.patch
+CVE-2023-5992/13-29a98e5.patch
+CVE-2023-5992/14-7471dd2.patch
+0029-authentic-Avoid-memory-leaks.patch
+CVE-2024-1454.patch
+CVE-2024-8443/01-b28a3ce.patch
+CVE-2024-8443/02-02e8474.patch
+CVE-2024-45616/01-76115e3.patch
+CVE-2024-45615/01-bde991b.patch
+CVE-2024-45616/02-e7177c7.patch
+CVE-2024-45615/02-5e4f26b.patch
+CVE-2024-45616/03-1d3b410.patch
+CVE-2024-45616/04-cccdfc4.patch
+CVE-2024-45616/05-5fa7587.patch
+CVE-2024-45616/06-3562969.patch
+CVE-2024-45615/03-bb3dedb.patch
+CVE-2024-45616/07-16ada9d.patch
+CVE-2024-45617/01-fdb9e90.patch
+CVE-2024-45619/01-f01bfbd.patch
+CVE-2024-45617/02-21d869b.patch
+CVE-2024-45615/04-7d68a7f.patch
+CVE-2024-45615/05-42d718d.patch
+CVE-2024-45619/02-6730656.patch
+CVE-2024-45617/03-efbc14f.patch
+CVE-2024-45618/01-8632ec1.patch
+CVE-2024-45619/03-a1d8c01.patch
+CVE-2024-45618/02-f9d6866.patch
+CVE-2024-45620/01-a1bcc65.patch
+CVE-2024-45620/02-6baa195.patch
+CVE-2024-45616/08-ef7b10a.patch
+CVE-2024-45619/04-e20ca25.patch
+CVE-2024-45620/03-468a314.patch
+CVE-2024-45619/05-2b6cd52.patch
+CVE-2024-45619/06-dd554a2.patch
+CVE-2024-45616/09-aa102cd.patch
+CVE-2024-45616/10-265b283.patch
diff -Nru --exclude '*.patch' opensc-0.23.0/debian/salsa-ci.yml opensc-0.23.0/debian/salsa-ci.yml
--- opensc-0.23.0/debian/salsa-ci.yml	1970-01-01 00:00:00.000000000 +0000
+++ opensc-0.23.0/debian/salsa-ci.yml	2024-12-22 18:35:04.000000000 +0000
@@ -0,0 +1,8 @@
+---
+include:
+  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml
+
+variables:
+  RELEASE: 'bookworm'
+  SALSA_CI_DISABLE_REPROTEST: 1
+  SALSA_CI_DISABLE_LINTIAN: 1
diff -Nru --exclude '*.patch' opensc-0.23.0/src/common/Makefile.am opensc-0.23.0/src/common/Makefile.am
--- opensc-0.23.0/src/common/Makefile.am	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/common/Makefile.am	2024-12-23 02:03:20.000000000 +0000
@@ -8,7 +8,8 @@
 	LICENSE.compat_getopt compat_getopt.txt \
 	compat_getopt_main.c \
 	README.compat_strlcpy compat_strlcpy.3
-noinst_HEADERS = compat_strlcat.h compat_strlcpy.h compat_strnlen.h compat_getpass.h compat_getopt.h simclist.h libpkcs11.h libscdl.h
+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
 
 AM_CPPFLAGS = -I$(top_srcdir)/src
 
@@ -41,7 +42,8 @@
 	compat_report_rangecheckfailure.c \
 	compat___iob_func.c \
 	simclist.c simclist.h \
-	libpkcs11.c libscdl.c
+	libpkcs11.c libscdl.c \
+	constant-time.h
 
 check-local:
 	if [ -x "$(CLANGTIDY)" ]; then clang-tidy -config='' --checks='$(TIDY_CHECKS)' -header-filter=.* $(addprefix $(srcdir)/,$(TIDY_FILES)) -- $(TIDY_FLAGS); fi
diff -Nru --exclude '*.patch' opensc-0.23.0/src/common/constant-time.h opensc-0.23.0/src/common/constant-time.h
--- opensc-0.23.0/src/common/constant-time.h	1970-01-01 00:00:00.000000000 +0000
+++ opensc-0.23.0/src/common/constant-time.h	2024-12-23 02:03:20.000000000 +0000
@@ -0,0 +1,134 @@
+/* Original source: https://github.com/openssl/openssl/blob/9890cc42daff5e2d0cad01ac4bf78c391f599a6e/include/internal/constant_time.h */
+
+#ifndef CONSTANT_TIME_H
+#define CONSTANT_TIME_H
+
+#include <stdlib.h>
+#include <string.h>
+
+#if !defined(inline)
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define constant_inline inline
+#elif defined(__GNUC__) && __GNUC__ >= 2
+#elif defined(__GNUC__) && __GNUC__ >= 2
+#elif defined(_MSC_VER)
+#define constant_inline __inline
+#else
+#define constant_inline
+#endif
+#else			       /* use what caller wants as inline  may be from config.h */
+#define constant_inline inline /* inline */
+#endif
+
+/*-
+ * The boolean methods return a bitmask of all ones (0xff...f) for true
+ * and 0 for false. For example,
+ *      if (a < b) {
+ *        c = a;
+ *      } else {
+ *        c = b;
+ *      }
+ * can be written as
+ *      unsigned int lt = constant_time_lt(a, b);
+ *      c = constant_time_select(lt, a, b);
+ */
+
+static constant_inline unsigned int
+value_barrier(unsigned int a)
+{
+	volatile unsigned int r = a;
+	return r;
+}
+
+static constant_inline size_t
+value_barrier_s(size_t a)
+{
+	volatile size_t r = a;
+	return r;
+}
+
+/* MSB */
+static constant_inline size_t
+constant_time_msb_s(size_t a)
+{
+	return 0 - (a >> (sizeof(a) * 8 - 1));
+}
+
+static constant_inline unsigned int
+constant_time_msb(unsigned int a)
+{
+	return 0 - (a >> (sizeof(a) * 8 - 1));
+}
+
+/* Select */
+static constant_inline unsigned int
+constant_time_select(unsigned int mask, unsigned int a, unsigned int b)
+{
+	return (value_barrier(mask) & a) | (value_barrier(~mask) & b);
+}
+
+static constant_inline unsigned char
+constant_time_select_8(unsigned char mask, unsigned char a, unsigned char b)
+{
+	return (unsigned char)constant_time_select(mask, a, b);
+}
+
+static constant_inline size_t
+constant_time_select_s(size_t mask, size_t a, size_t b)
+{
+	return (value_barrier_s(mask) & a) | (value_barrier_s(~mask) & b);
+}
+
+/* Zero */
+static constant_inline unsigned int
+constant_time_is_zero(unsigned int a)
+{
+	return constant_time_msb(~a & (a - 1));
+}
+
+static constant_inline size_t
+constant_time_is_zero_s(size_t a)
+{
+	return constant_time_msb_s(~a & (a - 1));
+}
+
+/* Comparison*/
+static constant_inline size_t
+constant_time_lt_s(size_t a, size_t b)
+{
+	return constant_time_msb_s(a ^ ((a ^ b) | ((a - b) ^ b)));
+}
+
+static constant_inline unsigned int
+constant_time_lt(unsigned int a, unsigned int b)
+{
+	return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b)));
+}
+
+static constant_inline unsigned int
+constant_time_ge(unsigned int a, unsigned int b)
+{
+	return ~constant_time_lt(a, b);
+}
+
+/* Equality*/
+
+static constant_inline unsigned int
+constant_time_eq(unsigned int a, unsigned int b)
+{
+	return constant_time_is_zero(a ^ b);
+}
+
+static constant_inline size_t
+constant_time_eq_s(size_t a, size_t b)
+{
+	return constant_time_is_zero_s(a ^ b);
+}
+
+static constant_inline unsigned int
+constant_time_eq_i(int a, int b)
+{
+	return constant_time_eq((unsigned int)a, (unsigned int)b);
+}
+
+#endif /* CONSTANT_TIME_H */
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/asn1.c opensc-0.23.0/src/libopensc/asn1.c
--- opensc-0.23.0/src/libopensc/asn1.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/asn1.c	2024-12-23 02:03:20.000000000 +0000
@@ -68,7 +68,7 @@
 
 	*buf = NULL;
 
-	if (left == 0 || !p)
+	if (left == 0 || !p || buflen == 0)
 		return SC_ERROR_INVALID_ASN1_OBJECT;
 	if (*p == 0xff || *p == 0) {
 		/* end of data reached */
@@ -83,6 +83,8 @@
 	 */
 	cla = (*p & SC_ASN1_TAG_CLASS) | (*p & SC_ASN1_TAG_CONSTRUCTED);
 	tag = *p & SC_ASN1_TAG_PRIMITIVE;
+	if (left < 1)
+		return SC_ERROR_INVALID_ASN1_OBJECT;
 	p++;
 	left--;
 	if (tag == SC_ASN1_TAG_PRIMITIVE) {
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/card-cac.c opensc-0.23.0/src/libopensc/card-cac.c
--- opensc-0.23.0/src/libopensc/card-cac.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/card-cac.c	2024-12-23 02:03:20.000000000 +0000
@@ -255,7 +255,7 @@
 	size_t * recvbuflen)
 {
 	int r;
-	sc_apdu_t apdu;
+	sc_apdu_t apdu = {0};
 	u8 rbufinitbuf[CAC_MAX_SIZE];
 	u8 *rbuf;
 	size_t rbuflen;
@@ -392,13 +392,13 @@
 static int cac_read_file(sc_card_t *card, int file_type, u8 **out_buf, size_t *out_len)
 {
 	u8 params[2];
-	u8 count[2];
+	u8 count[2] = {0};
 	u8 *out = NULL;
-	u8 *out_ptr;
+	u8 *out_ptr = NULL;
 	size_t offset = 0;
 	size_t size = 0;
 	size_t left = 0;
-	size_t len;
+	size_t len = 0;
 	int r;
 
 	params[0] = file_type;
@@ -461,7 +461,7 @@
 	const u8 *tl_ptr, *val_ptr, *tl_start;
 	u8 *tlv_ptr;
 	const u8 *cert_ptr;
-	size_t tl_len, val_len, tlv_len;
+	size_t tl_len = 0, val_len = 0, tlv_len;
 	size_t len, tl_head_len, cert_len;
 	u8 cert_type, tag;
 
@@ -1302,10 +1302,10 @@
 	/* Call without OID set will just select the AID without subsequent
 	 * OID selection, which we need to figure out just now
 	 */
-	cac_select_file_by_type(card, &new_object.path, NULL);
+	r = cac_select_file_by_type(card, &new_object.path, NULL);
+	LOG_TEST_RET(card->ctx, r, "Cannot select AID");
 	r = cac_get_properties(card, &prop);
-	if (r < 0)
-		return SC_ERROR_INTERNAL;
+	LOG_TEST_RET(card->ctx, r, "Cannot get CAC properties");
 
 	for (i = 0; i < prop.num_objects; i++) {
 		/* don't fail just because we have more certs than we can support */
@@ -1528,7 +1528,7 @@
 static int cac_process_CCC(sc_card_t *card, cac_private_data_t *priv, int depth)
 {
 	u8 *tl = NULL, *val = NULL;
-	size_t tl_len, val_len;
+	size_t tl_len = 0, val_len = 0;
 	int r;
 
 	if (depth > CAC_MAX_CCC_DEPTH) {
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/card-cac1.c opensc-0.23.0/src/libopensc/card-cac1.c
--- opensc-0.23.0/src/libopensc/card-cac1.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/card-cac1.c	2024-12-23 02:03:20.000000000 +0000
@@ -95,12 +95,12 @@
 		if (apdu.sw1 != 0x63 || apdu.sw2 < 1)  {
 			/* we've either finished reading, or hit an error, break */
 			r = sc_check_sw(card, apdu.sw1, apdu.sw2);
-			left -= len;
+			left -= apdu.resplen;
 			break;
 		}
 		/* Adjust the lengths */
-		left -= len;
-		out_ptr += len;
+		left -= apdu.resplen;
+		out_ptr += apdu.resplen;
 		len = MIN(left, apdu.sw2);
 	}
 	if (r < 0) {
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/card-cardos.c opensc-0.23.0/src/libopensc/card-cardos.c
--- opensc-0.23.0/src/libopensc/card-cardos.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/card-cardos.c	2024-12-23 02:03:20.000000000 +0000
@@ -94,14 +94,14 @@
 
 static int cardos_match_card(sc_card_t *card)
 {
-	unsigned char atr[SC_MAX_ATR_SIZE];
+	unsigned char atr[SC_MAX_ATR_SIZE] = {0};
 	int i;
 
 	i = _sc_match_atr(card, cardos_atrs, &card->type);
 	if (i < 0)
 		return 0;
 
-	memcpy(atr, card->atr.value, sizeof(atr));
+	memcpy(atr, card->atr.value, card->atr.len);
 
 	/* Do not change card type for CIE! */
 	if (card->type == SC_CARD_TYPE_CARDOS_CIE_V1)
@@ -114,8 +114,8 @@
 		return 1;
 	if (card->type == SC_CARD_TYPE_CARDOS_M4_2) {
 		int rv;
-		sc_apdu_t apdu;
-		u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
+		sc_apdu_t apdu = {0};
+		u8 rbuf[SC_MAX_APDU_BUFFER_SIZE] = {0};
 		/* first check some additional ATR bytes */
 		if ((atr[4] != 0xff && atr[4] != 0x02) ||
 		    (atr[6] != 0x10 && atr[6] != 0x0a) ||
@@ -131,7 +131,7 @@
 		apdu.lc = 0;
 		rv = sc_transmit_apdu(card, &apdu);
 		LOG_TEST_RET(card->ctx, rv, "APDU transmit failed");
-		if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
+		if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00 || apdu.resplen < 2)
 			return 0;
 		if (apdu.resp[0] != atr[10] ||
 		    apdu.resp[1] != atr[11])
@@ -1278,7 +1278,7 @@
 	LOG_TEST_RET(card->ctx, r, "Card returned error");
 
 	if (apdu.resplen < 1) {
-		LOG_TEST_RET(card->ctx, r, "Lifecycle byte not in response");
+		LOG_TEST_RET(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Lifecycle byte not in response");
 	}
 
 	r = SC_SUCCESS;
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/card-coolkey.c opensc-0.23.0/src/libopensc/card-coolkey.c
--- opensc-0.23.0/src/libopensc/card-coolkey.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/card-coolkey.c	2024-12-23 02:03:20.000000000 +0000
@@ -1684,6 +1684,7 @@
 	u8 key_number;
 	size_t params_len;
 	u8 buf[MAX_COMPUTE_BUF + 2];
+	size_t buf_len;
 	u8 *buf_out;
 
 	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
@@ -1724,8 +1725,6 @@
 		ushort2bebytes(params.init.buf_len, 0);
 	} else {
 		/* The data fits in APDU. Copy it to the params object */
-		size_t buf_len;
-
 		params.init.location = COOLKEY_CRYPT_LOCATION_APDU;
 
 		params_len = sizeof(params.init) + datalen;
@@ -1745,6 +1744,7 @@
 	if (r < 0) {
 		goto done;
 	}
+	buf_len = crypt_out_len_p;
 
 	if (datalen > MAX_COMPUTE_BUF) {
 		u8 len_buf[2];
@@ -1763,7 +1763,12 @@
 					priv->nonce, sizeof(priv->nonce));
 
 	} else {
-		size_t out_length = bebytes2ushort(buf);
+		size_t out_length;
+		if (buf_len < 2) {
+			r = SC_ERROR_WRONG_LENGTH;
+			goto done;
+		}
+		out_length = bebytes2ushort(buf);
 		if (out_length > sizeof buf - 2) {
 			r = SC_ERROR_WRONG_LENGTH;
 			goto done;
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/card-dnie.c opensc-0.23.0/src/libopensc/card-dnie.c
--- opensc-0.23.0/src/libopensc/card-dnie.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/card-dnie.c	2024-12-23 02:03:20.000000000 +0000
@@ -1185,12 +1185,16 @@
 
 	if (file_out) {
 		/* finally process FCI response */
+		size_t len = apdu.resp[1];
 		sc_file_free(*file_out);
 		*file_out = sc_file_new();
 		if (*file_out == NULL) {
 			LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
 		}
-		res = card->ops->process_fci(card, *file_out, apdu.resp + 2, apdu.resp[1]);
+		if (apdu.resplen - 2 < len || len < 1) {
+			LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
+		}
+		res = card->ops->process_fci(card, *file_out, apdu.resp + 2, len);
 	}
 	LOG_FUNC_RETURN(ctx, res);
 }
@@ -1948,7 +1952,7 @@
 	int *op = df_acl;
 	int n = 0;
 	sc_context_t *ctx = NULL;
-	if ((card == NULL) || (card->ctx == NULL) || (file == NULL))
+	if ((card == NULL) || (card->ctx == NULL) || (file == NULL) || buflen == 0)
 		return SC_ERROR_INVALID_ARGUMENTS;
 	ctx = card->ctx;
 	LOG_FUNC_CALLED(ctx);
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/card-entersafe.c opensc-0.23.0/src/libopensc/card-entersafe.c
--- opensc-0.23.0/src/libopensc/card-entersafe.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/card-entersafe.c	2024-12-23 02:03:20.000000000 +0000
@@ -1453,6 +1453,8 @@
 	r=entersafe_transmit_apdu(card, &apdu,0,0,0,0);
 	LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
 	LOG_TEST_RET(card->ctx, sc_check_sw(card,apdu.sw1,apdu.sw2),"EnterSafe get SN failed");
+	if (apdu.resplen != 8)
+		LOG_TEST_RET(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid length of SN");
 
 	card->serialnr.len=serial->len=8;
 	memcpy(card->serialnr.value,rbuf,8);
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/card-gids.c opensc-0.23.0/src/libopensc/card-gids.c
--- opensc-0.23.0/src/libopensc/card-gids.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/card-gids.c	2024-12-23 02:03:20.000000000 +0000
@@ -231,6 +231,7 @@
 	size_t datasize = 0;
 	const u8* p;
 	u8 buffer[MAX_GIDS_FILE_SIZE];
+	size_t buffer_len = sizeof(buffer);
 
 	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
 	sc_log(card->ctx, 
@@ -244,14 +245,15 @@
 	apdu.data = data;
 	apdu.datalen = 04;
 	apdu.resp = buffer;
-	apdu.resplen = sizeof(buffer);
+	apdu.resplen = buffer_len;
 	apdu.le = 256;
 
 	r = sc_transmit_apdu(card, &apdu);
 	LOG_TEST_RET(card->ctx, r, "gids get data failed");
 	LOG_TEST_RET(card->ctx,  sc_check_sw(card, apdu.sw1, apdu.sw2), "invalid return");
+	buffer_len = apdu.resplen;
 
-	p = sc_asn1_find_tag(card->ctx, buffer, sizeof(buffer), dataObjectIdentifier, &datasize);
+	p = sc_asn1_find_tag(card->ctx, buffer, buffer_len, dataObjectIdentifier, &datasize);
 	if (!p) {
 		LOG_FUNC_RETURN(card->ctx, SC_ERROR_FILE_NOT_FOUND);
 	}
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/card-jpki.c opensc-0.23.0/src/libopensc/card-jpki.c
--- opensc-0.23.0/src/libopensc/card-jpki.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/card-jpki.c	2024-12-23 02:03:20.000000000 +0000
@@ -195,6 +195,8 @@
 		u8 buf[4];
 		rc = sc_read_binary(card, 0, buf, 4, 0);
 		LOG_TEST_RET(card->ctx, rc, "SW Check failed");
+		if (rc < 4)
+			LOG_TEST_RET(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Received data too short");
 		file = sc_file_new();
 		if (!file) {
 			LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/card-mcrd.c opensc-0.23.0/src/libopensc/card-mcrd.c
--- opensc-0.23.0/src/libopensc/card-mcrd.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/card-mcrd.c	2024-12-23 02:03:20.000000000 +0000
@@ -634,10 +634,12 @@
 		}
 	}
 
-	if (p2 == 0x04 && apdu.resp[0] == 0x62) {
+	if (p2 == 0x04 && apdu.resplen > 2 && apdu.resp[0] == 0x62) {
 		*file = sc_file_new();
 		if (!*file)
 			LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
+		if (apdu.resp[1] > apdu.resplen - 2)
+			LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA);
 		/* EstEID v3.0 cards are buggy and sometimes return a double 0x62 tag */
 		if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V30 && apdu.resp[2] == 0x62)
 			process_fcp(card, *file, apdu.resp + 4, apdu.resp[3]);
@@ -646,12 +648,13 @@
 		return SC_SUCCESS;
 	}
 
-	if (p2 != 0x0C && apdu.resp[0] == 0x6F) {
+	if (p2 != 0x0C && apdu.resplen > 2 && apdu.resp[0] == 0x6F) {
 		*file = sc_file_new();
 		if (!*file)
 			LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
-		if (apdu.resp[1] <= apdu.resplen)
-			process_fcp(card, *file, apdu.resp + 2, apdu.resp[1]);
+		if (apdu.resp[1] > apdu.resplen - 2)
+			LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA);
+		process_fcp(card, *file, apdu.resp + 2, apdu.resp[1]);
 		return SC_SUCCESS;
 	}
 	return SC_SUCCESS;
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/card-oberthur.c opensc-0.23.0/src/libopensc/card-oberthur.c
--- opensc-0.23.0/src/libopensc/card-oberthur.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/card-oberthur.c	2024-12-23 02:03:20.000000000 +0000
@@ -148,7 +148,7 @@
 {
 	struct sc_apdu apdu;
 	unsigned char apdu_resp[SC_MAX_APDU_BUFFER_SIZE];
-	struct auth_private_data *data =  (struct auth_private_data *) card->drv_data;
+	struct auth_private_data *data = (struct auth_private_data *)card->drv_data;
 	int rv, ii;
 	struct sc_path tmp_path;
 
@@ -165,6 +165,9 @@
 
 	rv = sc_transmit_apdu(card, &apdu);
 	LOG_TEST_RET(card->ctx, rv, "APDU transmit failed");
+	if (apdu.resplen < 20) {
+		LOG_TEST_RET(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Serial number has incorrect length");
+	}
 	card->serialnr.len = 4;
 	memcpy(card->serialnr.value, apdu.resp+15, 4);
 
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/card-openpgp.c opensc-0.23.0/src/libopensc/card-openpgp.c
--- opensc-0.23.0/src/libopensc/card-openpgp.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/card-openpgp.c	2024-12-23 02:03:20.000000000 +0000
@@ -2756,14 +2756,21 @@
 	/* update the blob containing fingerprints (00C5) */
 	sc_log(card->ctx, "Updating fingerprint blob 00C5.");
 	fpseq_blob = pgp_find_blob(card, 0x00C5);
-	if (fpseq_blob == NULL)
-		LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot find blob 00C5");
+	if (fpseq_blob == NULL) {
+		r = SC_ERROR_OUT_OF_MEMORY;
+		LOG_TEST_GOTO_ERR(card->ctx, r, "Cannot find blob 00C5");
+	}
+	if (20 * key_info->key_id > fpseq_blob->len) {
+		r = SC_ERROR_OBJECT_NOT_VALID;
+		LOG_TEST_GOTO_ERR(card->ctx, r, "The 00C5 blob is not large enough");
+	}
 
 	/* save the fingerprints sequence */
 	newdata = malloc(fpseq_blob->len);
-	if (newdata == NULL)
-		LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_OUT_OF_MEMORY,
-			"Not enough memory to update fingerprint blob 00C5");
+	if (newdata == NULL) {
+		r = SC_ERROR_OUT_OF_MEMORY;
+		LOG_TEST_GOTO_ERR(card->ctx, r, "Not enough memory to update fingerprint blob 00C5");
+	}
 
 	memcpy(newdata, fpseq_blob->data, fpseq_blob->len);
 	/* move p to the portion holding the fingerprint of the current key */
@@ -2877,6 +2884,9 @@
 
 		/* RSA modulus */
 		if (tag == 0x0081) {
+			if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA) {
+				LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
+			}
 			if ((BYTES4BITS(key_info->u.rsa.modulus_len) < len)  /* modulus_len is in bits */
 				|| key_info->u.rsa.modulus == NULL) {
 
@@ -2892,6 +2902,9 @@
 		}
 		/* RSA public exponent */
 		else if (tag == 0x0082) {
+			if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA) {
+				LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
+			}
 			if ((BYTES4BITS(key_info->u.rsa.exponent_len) < len)  /* exponent_len is in bits */
 				|| key_info->u.rsa.exponent == NULL) {
 
@@ -2907,6 +2920,10 @@
 		}
 		/* ECC public key */
 		else if (tag == 0x0086) {
+			if (key_info->algorithm != SC_OPENPGP_KEYALGO_ECDSA &&
+					key_info->algorithm != SC_OPENPGP_KEYALGO_ECDH) {
+				LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
+			}
 			/* set the output data */
 			/* len is ecpoint length + format byte
 			 * see section 7.2.14 of 3.3.1 specs */
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/card-piv.c opensc-0.23.0/src/libopensc/card-piv.c
--- opensc-0.23.0/src/libopensc/card-piv.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/card-piv.c	2024-12-23 02:03:20.000000000 +0000
@@ -2241,7 +2241,7 @@
 	const u8 *p;
 	size_t out_len = 0;
 	int r;
-	unsigned int tag, cla;
+	unsigned int tag = 0, cla = 0;
 	piv_private_data_t * priv = PIV_DATA(card);
 
 	LOG_FUNC_CALLED(card->ctx);
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/iasecc-sdo.c opensc-0.23.0/src/libopensc/iasecc-sdo.c
--- opensc-0.23.0/src/libopensc/iasecc-sdo.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/iasecc-sdo.c	2024-12-23 02:03:20.000000000 +0000
@@ -324,16 +324,25 @@
 
 	LOG_FUNC_CALLED(ctx);
 
+	if (data_len < 1)
+		LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
+
 	if (*data == IASECC_SDO_TEMPLATE_TAG)   {
 		size_size = iasecc_parse_size(data + 1, &size);
 		LOG_TEST_RET(ctx, size_size, "parse error: invalid size data of IASECC_SDO_TEMPLATE");
 
+		if (data_len - 1 < size)
+			LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
+
 		data += size_size + 1;
 		data_len = size;
 		sc_log(ctx,
 		       "IASECC_SDO_TEMPLATE: size %"SC_FORMAT_LEN_SIZE_T"u, size_size %"SC_FORMAT_LEN_SIZE_T"u",
 		       size, size_size);
 
+		if (data_len < 3)
+			LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
+
 		if (*data != IASECC_SDO_TAG_HEADER)
 			LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
 
@@ -729,6 +738,9 @@
 
 	LOG_FUNC_CALLED(ctx);
 
+	if (data == NULL || data_len < 2)
+		LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
+
 	if (*data == IASECC_SDO_TEMPLATE_TAG)   {
 		size_size = iasecc_parse_size(data + 1, &size);
 		LOG_TEST_RET(ctx, size_size, "parse error: invalid size data of IASECC_SDO_TEMPLATE");
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/internal.h opensc-0.23.0/src/libopensc/internal.h
--- opensc-0.23.0/src/libopensc/internal.h	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/internal.h	2024-12-23 02:03:20.000000000 +0000
@@ -166,8 +166,8 @@
 
 int sc_pkcs1_strip_01_padding(struct sc_context *ctx, const u8 *in_dat, size_t in_len,
 		u8 *out_dat, size_t *out_len);
-int sc_pkcs1_strip_02_padding(struct sc_context *ctx, const u8 *data, size_t len,
-		u8 *out_dat, size_t *out_len);
+int 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);
 int sc_pkcs1_strip_digest_info_prefix(unsigned int *algorithm,
 		const u8 *in_dat, size_t in_len, u8 *out_dat, size_t *out_len);
 #ifdef ENABLE_OPENSSL
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/muscle.c opensc-0.23.0/src/libopensc/muscle.c
--- opensc-0.23.0/src/libopensc/muscle.c	2024-12-23 02:03:20.000000000 +0000
+++ opensc-0.23.0/src/libopensc/muscle.c	2024-12-23 02:03:20.000000000 +0000
@@ -92,33 +92,34 @@
 	apdu.resp = data; 
 	r = sc_transmit_apdu(card, &apdu);
 	LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
-	if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
-		return dataLength;
-	if(apdu.sw1 == 0x9C) {
-		if(apdu.sw2 == 0x07) {
+	if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00 && dataLength <= apdu.resplen)
+		return (int)dataLength;
+	if (apdu.sw1 == 0x9C) {
+		if (apdu.sw2 == 0x07) {
 			SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_FILE_NOT_FOUND);
-		} else if(apdu.sw2 == 0x06) {
+		} else if (apdu.sw2 == 0x06) {
 			SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_ALLOWED);
-		} else if(apdu.sw2 == 0x0F) {
+		} else if (apdu.sw2 == 0x0F) {
 			/* GUESSED */
 			SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
 		}
 	}
 	sc_log(card->ctx, 
 		"got strange SWs: 0x%02X 0x%02X\n", apdu.sw1, apdu.sw2);
-	return dataLength;
-	
+	SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_UNKNOWN_DATA_RECEIVED);
 }
 
 int msc_read_object(sc_card_t *card, msc_id objectId, int offset, u8 *data, size_t dataLength)
 {
-	int r;
+	int r = 0;
 	size_t i;
 	size_t max_read_unit = MSC_MAX_READ;
 
-	for(i = 0; i < dataLength; i += max_read_unit) {
+	for (i = 0; i < dataLength; i += r) {
 		r = msc_partial_read_object(card, objectId, offset + i, data + i, MIN(dataLength - i, max_read_unit));
 		LOG_TEST_RET(card->ctx, r, "Error in partial object read");
+		if (r == 0)
+			break;
 	}
 	return dataLength;
 }
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/padding.c opensc-0.23.0/src/libopensc/padding.c
--- opensc-0.23.0/src/libopensc/padding.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/padding.c	2024-12-23 02:03:20.000000000 +0000
@@ -32,10 +32,13 @@
 #include <string.h>
 #include <stdlib.h>
 
+#include "common/constant-time.h"
 #include "internal.h"
 #include "pkcs11/pkcs11.h"
 /* TODO doxygen comments */
 
+#define SC_PKCS1_PADDING_MIN_SIZE 11
+
 /*
  * Prefixes for pkcs-v1 signatures
  */
@@ -143,45 +146,85 @@
 	return SC_SUCCESS;
 }
 
-
-/* remove pkcs1 BT02 padding (adding BT02 padding is currently not
- * needed/implemented) */
+/* Remove pkcs1 BT02 padding (adding BT02 padding is currently not
+ * needed/implemented) in constant-time.
+ * Original source: https://github.com/openssl/openssl/blob/9890cc42daff5e2d0cad01ac4bf78c391f599a6e/crypto/rsa/rsa_pk1.c#L171 */
 int
-sc_pkcs1_strip_02_padding(sc_context_t *ctx, const u8 *data, size_t len, u8 *out, size_t *out_len)
+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)
 {
-	unsigned int	n = 0;
-
+	unsigned int i = 0;
+	u8 *msg, *msg_orig = NULL;
+	unsigned int good, found_zero_byte, mask, tmp_outlen;
+	unsigned int zero_index = 0, msg_index, mlen = -1, len = 0;
 	LOG_FUNC_CALLED(ctx);
-	if (data == NULL || len < 3)
+
+	if (data == NULL || data_len <= 0 || data_len > n ||
+			n < SC_PKCS1_PADDING_MIN_SIZE || out_len == NULL)
 		LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
 
-	/* skip leading zero byte */
-	if (*data == 0) {
-		data++;
-		len--;
+	tmp_outlen = *out_len;
+	msg = msg_orig = calloc(n, sizeof(u8));
+	if (msg == NULL)
+		LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
+
+	/*
+	 * We can not check length of input data straight away and still we need to read
+	 * from input even when the input is not as long as needed to keep the time constant.
+	 * If data has wrong size, it is padded by zeroes from left and the following checks
+	 * do not pass.
+	 */
+	len = data_len;
+	for (data += len, msg += n, i = 0; i < n; i++) {
+		mask = ~constant_time_is_zero(len);
+		len -= 1 & mask;
+		data -= 1 & mask;
+		*--msg = *data & mask;
+	}
+	// check first byte to be 0x00
+	good = constant_time_is_zero(msg[0]);
+	// check second byte to be 0x02
+	good &= constant_time_eq(msg[1], 2);
+
+	// find zero byte after random data in padding
+	found_zero_byte = 0;
+	for (i = 2; i < n; i++) {
+		unsigned int equals0 = constant_time_is_zero(msg[i]);
+		zero_index = constant_time_select(~found_zero_byte & equals0, i, zero_index);
+		found_zero_byte |= equals0;
 	}
-	if (data[0] != 0x02)
-		LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING);
-	/* skip over padding bytes */
-	for (n = 1; n < len && data[n]; n++)
-		;
-	/* Must be at least 8 pad bytes */
-	if (n >= len || n < 9)
-		LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING);
-	n++;
-	if (out == NULL)
-		/* just check the padding */
-		LOG_FUNC_RETURN(ctx, SC_SUCCESS);
 
-	/* Now move decrypted contents to head of buffer */
-	if (*out_len < len - n)
-		LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
-	*out_len = len - n;
-	memmove(out, data + n, *out_len);
+	// zero_index stands for index of last found zero
+	good &= constant_time_ge(zero_index, 2 + 8);
+
+	// start of the actual message in data
+	msg_index = zero_index + 1;
+
+	// length of message
+	mlen = data_len - msg_index;
+
+	// check that message fits into out buffer
+	good &= constant_time_ge(tmp_outlen, mlen);
+
+	// move the result in-place by |num|-SC_PKCS1_PADDING_MIN_SIZE-|mlen| bytes to the left.
+	tmp_outlen = constant_time_select(constant_time_lt(n - SC_PKCS1_PADDING_MIN_SIZE, tmp_outlen),
+			n - SC_PKCS1_PADDING_MIN_SIZE, tmp_outlen);
+	for (msg_index = 1; msg_index < n - SC_PKCS1_PADDING_MIN_SIZE; msg_index <<= 1) {
+		mask = ~constant_time_eq(msg_index & (n - SC_PKCS1_PADDING_MIN_SIZE - mlen), 0);
+		for (i = SC_PKCS1_PADDING_MIN_SIZE; i < n - msg_index; i++)
+			msg[i] = constant_time_select_8(mask, msg[i + msg_index], msg[i]);
+	}
+	// move message into out buffer, if good
+	for (i = 0; i < tmp_outlen; i++) {
+		unsigned int msg_index;
+		// when out is longer than message in data, use some bogus index in msg
+		mask = good & constant_time_lt(i, mlen);
+		msg_index = constant_time_select(mask, i + SC_PKCS1_PADDING_MIN_SIZE, 0); // to now overflow msg buffer
+		out[i] = constant_time_select_8(mask, msg[msg_index], out[i]);
+	}
 
-	sc_log(ctx, "stripped output(%"SC_FORMAT_LEN_SIZE_T"u): %s", len - n,
-	       sc_dump_hex(out, len - n));
-	LOG_FUNC_RETURN(ctx, len - n);
+	*out_len = constant_time_select(good, mlen, *out_len);
+	free(msg_orig);
+	return constant_time_select(good, mlen, SC_ERROR_WRONG_PADDING);
 }
 
 #ifdef ENABLE_OPENSSL
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/pkcs15-cert.c opensc-0.23.0/src/libopensc/pkcs15-cert.c
--- opensc-0.23.0/src/libopensc/pkcs15-cert.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/pkcs15-cert.c	2024-12-23 02:03:20.000000000 +0000
@@ -169,7 +169,7 @@
 	for (next_ava = rdn, next_ava_len = rdn_len; next_ava_len; ) {
 		const u8 *ava, *dummy, *oidp;
 		struct sc_object_id oid;
-		size_t ava_len, dummy_len, oid_len;
+		size_t ava_len = 0, dummy_len, oid_len = 0;
 
 		/* unwrap the set and point to the next ava */
 		ava = sc_asn1_skip_tag(ctx, &next_ava, &next_ava_len, SC_ASN1_TAG_SET | SC_ASN1_CONS, &ava_len);
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/pkcs15-gemsafeV1.c opensc-0.23.0/src/libopensc/pkcs15-gemsafeV1.c
--- opensc-0.23.0/src/libopensc/pkcs15-gemsafeV1.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/pkcs15-gemsafeV1.c	2024-12-23 02:03:20.000000000 +0000
@@ -168,6 +168,7 @@
 	struct sc_file *file;
 	size_t objlen, certlen;
 	unsigned int ind, i=0;
+	int read_len;
 
 	sc_format_path(GEMSAFE_PATH, &path);
 	r = sc_select_file(card, &path, &file);
@@ -176,9 +177,11 @@
 	sc_file_free(file);
 
 	/* Initial read */
-	r = sc_read_binary(card, 0, ibuf, GEMSAFE_READ_QUANTUM, 0);
-	if (r < 0)
+	read_len = sc_read_binary(card, 0, ibuf, GEMSAFE_READ_QUANTUM, 0);
+	if (read_len <= 2) {
+		sc_log(card->ctx, "Invalid size of object data: %d", read_len);
 		return SC_ERROR_INTERNAL;
+	}
 
 	/* Actual stored object size is encoded in first 2 bytes
 	 * (allocated EF space is much greater!)
@@ -207,7 +210,7 @@
 	 * the private key.
 	 */
 	ind = 2; /* skip length */
-	while (ibuf[ind] == 0x01 && i < gemsafe_cert_max) {
+	while (ind + 1 < (size_t)read_len && ibuf[ind] == 0x01 && i < gemsafe_cert_max) {
 		if (ibuf[ind+1] == 0xFE) {
 			gemsafe_prkeys[i].ref = ibuf[ind+4];
 			sc_log(card->ctx, "Key container %d is allocated and uses key_ref %d",
@@ -234,7 +237,7 @@
 	/* Read entire file, then dissect in memory.
 	 * Gemalto ClassicClient seems to do it the same way.
 	 */
-	iptr = ibuf + GEMSAFE_READ_QUANTUM;
+	iptr = ibuf + read_len;
 	while ((size_t)(iptr - ibuf) < objlen) {
 		r = sc_read_binary(card, iptr - ibuf, iptr,
 				   MIN(GEMSAFE_READ_QUANTUM, objlen - (iptr - ibuf)), 0);
@@ -242,7 +245,14 @@
 			sc_log(card->ctx, "Could not read cert object");
 			return SC_ERROR_INTERNAL;
 		}
-		iptr += GEMSAFE_READ_QUANTUM;
+		if (r == 0)
+			break;
+		read_len += r;
+		iptr += r;
+	}
+	if ((size_t)read_len < objlen) {
+		sc_log(card->ctx, "Could not read cert object");
+		return SC_ERROR_INTERNAL;
 	}
 
 	/* Search buffer for certificates, they start with 0x3082. */
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/pkcs15-sc-hsm.c opensc-0.23.0/src/libopensc/pkcs15-sc-hsm.c
--- opensc-0.23.0/src/libopensc/pkcs15-sc-hsm.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/pkcs15-sc-hsm.c	2024-12-23 02:03:20.000000000 +0000
@@ -386,7 +386,7 @@
 	struct sc_asn1_entry asn1_cvcert[C_ASN1_CVCERT_SIZE];
 	struct sc_asn1_entry asn1_cvc_body[C_ASN1_CVC_BODY_SIZE];
 	struct sc_asn1_entry asn1_cvc_pubkey[C_ASN1_CVC_PUBKEY_SIZE];
-	unsigned int cla,tag;
+	unsigned int cla = 0, tag = 0;
 	size_t taglen;
 	const u8 *tbuf;
 	int r;
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/pkcs15-sec.c opensc-0.23.0/src/libopensc/pkcs15-sec.c
--- opensc-0.23.0/src/libopensc/pkcs15-sec.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/pkcs15-sec.c	2024-12-23 02:03:20.000000000 +0000
@@ -308,9 +308,10 @@
 
 	/* Strip any padding */
 	if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
-		size_t s = r;
-		r = sc_pkcs1_strip_02_padding(ctx, out, s, out, &s);
-		LOG_TEST_RET(ctx, r, "Invalid PKCS#1 padding");
+		unsigned int s = r;
+		unsigned int key_size = (unsigned int)alg_info->key_length;
+		r = sc_pkcs1_strip_02_padding_constant_time(ctx, key_size / 8, out, s, out, &s);
+		/* for keeping PKCS#1 v1.5 depadding constant-time, do not log error here */
 	}
 #ifdef ENABLE_OPENSSL
 	if (pad_flags & SC_ALGORITHM_RSA_PAD_OAEP)
@@ -332,7 +333,8 @@
 		LOG_TEST_RET(ctx, r, "Invalid OAEP padding");
 	}
 #endif
-	LOG_FUNC_RETURN(ctx, r);
+	/* do not log error code to prevent side channel attack */
+	return r;
 }
 
 /* derive one key from another. RSA can use decipher, so this is for only ECDH
diff -Nru --exclude '*.patch' opensc-0.23.0/src/libopensc/pkcs15-tcos.c opensc-0.23.0/src/libopensc/pkcs15-tcos.c
--- opensc-0.23.0/src/libopensc/pkcs15-tcos.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/libopensc/pkcs15-tcos.c	2024-12-23 02:03:20.000000000 +0000
@@ -45,6 +45,7 @@
 	struct sc_pkcs15_cert_info cert_info;
 	struct sc_pkcs15_object cert_obj;
 	unsigned char cert[20];
+	size_t cert_len = 0;
 	int r;
 
 	memset(&cert_info, 0, sizeof(cert_info));
@@ -57,24 +58,31 @@
 	strlcpy(cert_obj.label, label, sizeof(cert_obj.label));
 	cert_obj.flags = writable ? SC_PKCS15_CO_FLAG_MODIFIABLE : 0;
 
-	if(sc_select_file(card, &cert_info.path, NULL)!=SC_SUCCESS){
-		sc_log(ctx, 
-			"Select(%s) failed\n", path);
+	if (sc_select_file(card, &cert_info.path, NULL) != SC_SUCCESS) {
+		sc_log(ctx, "Select(%s) failed", path);
 		return 1;
 	}
-	if(sc_read_binary(card, 0, cert, sizeof(cert), 0)<0){
-		sc_log(ctx, 
-			"ReadBinary(%s) failed\n", path);
+	r = sc_read_binary(card, 0, cert, sizeof(cert), 0);
+	if (r <= 0) {
+		sc_log(ctx, "ReadBinary(%s) failed\n", path);
 		return 2;
 	}
-	if(cert[0]!=0x30 || cert[1]!=0x82){
-		sc_log(ctx, 
-			"Invalid Cert: %02X:%02X:...\n", cert[0], cert[1]);
+	cert_len = r; /* actual number of read bytes */
+	if (cert_len < 7 || (size_t)(7 + cert[5]) > cert_len) {
+		sc_log(ctx, "Invalid certificate length");
+		return 3;
+	}
+	if (cert[0] != 0x30 || cert[1] != 0x82) {
+		sc_log(ctx, "Invalid Cert: %02X:%02X:...\n", cert[0], cert[1]);
 		return 3;
 	}
 
 	/* some certificates are prefixed by an OID */
-	if(cert[4]==0x06 && cert[5]<10 && cert[6+cert[5]]==0x30 && cert[7+cert[5]]==0x82){
+	if (cert[4] == 0x06 && cert[5] < 10 && cert[6 + cert[5]] == 0x30 && cert[7 + cert[5]] == 0x82) {
+		if ((size_t)(9 + cert[5]) > cert_len) {
+			sc_log(ctx, "Invalid certificate length");
+			return 3;
+		}
 		cert_info.path.index=6+cert[5];
 		cert_info.path.count=(cert[8+cert[5]]<<8) + cert[9+cert[5]] + 4;
 	} else {
@@ -82,12 +90,12 @@
 		cert_info.path.count=(cert[2]<<8) + cert[3] + 4;
 	}
 
-	r=sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
-	if(r!=SC_SUCCESS){
-		sc_log(ctx,  "sc_pkcs15emu_add_x509_cert(%s) failed\n", path);
+	r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
+	if (r != SC_SUCCESS) {
+		sc_log(ctx, "sc_pkcs15emu_add_x509_cert(%s) failed", path);
 		return 4;
 	}
-	sc_log(ctx,  "%s: OK, Index=%d, Count=%d\n", path, cert_info.path.index, cert_info.path.count);
+	sc_log(ctx, "%s: OK, Index=%d, Count=%d", path, cert_info.path.index, cert_info.path.count);
 	return 0;
 }
 
@@ -530,10 +538,15 @@
 	/* get the card serial number */
 	r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serialnr);
 	if (r < 0) {
-		sc_log(ctx,  "unable to get ICCSN\n");
+		sc_log(ctx, "unable to get ICCSN");
 		return SC_ERROR_WRONG_CARD;
 	}
-	sc_bin_to_hex(serialnr.value, serialnr.len , serial, sizeof(serial), 0);
+	r = sc_bin_to_hex(serialnr.value, serialnr.len, serial, sizeof(serial), 0);
+	if (r != SC_SUCCESS) {
+		sc_log(ctx, "serial number invalid");
+		return SC_ERROR_INTERNAL;
+	}
+
 	serial[19] = '\0';
 	set_string(&p15card->tokeninfo->serial_number, serial);
 
diff -Nru --exclude '*.patch' opensc-0.23.0/src/minidriver/minidriver.c opensc-0.23.0/src/minidriver/minidriver.c
--- opensc-0.23.0/src/minidriver/minidriver.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/minidriver/minidriver.c	2024-12-23 02:03:20.000000000 +0000
@@ -41,6 +41,7 @@
 #include "cardmod.h"
 
 #include "common/compat_strlcpy.h"
+#include "common/constant-time.h"
 #include "libopensc/asn1.h"
 #include "libopensc/cardctl.h"
 #include "libopensc/opensc.h"
@@ -4487,13 +4488,15 @@
 
 {
 	DWORD dwret;
-	int r, opt_crypt_flags = 0;
+	int r, opt_crypt_flags = 0, good = 0;
 	unsigned ui;
 	VENDOR_SPECIFIC *vs;
 	struct sc_pkcs15_prkey_info *prkey_info;
 	BYTE *pbuf = NULL, *pbuf2 = NULL;
 	struct sc_pkcs15_object *pkey = NULL;
 	struct sc_algorithm_info *alg_info = NULL;
+	unsigned int wrong_padding = 0;
+	unsigned int pbufLen = 0;
 
 	MD_FUNC_CALLED(pCardData, 1);
 
@@ -4594,11 +4597,11 @@
 		goto err;
 	}
 
+	pbufLen = pInfo->cbData;
 	if (alg_info->flags & SC_ALGORITHM_RSA_RAW)   {
 		logprintf(pCardData, 2, "sc_pkcs15_decipher: using RSA-RAW mechanism\n");
 		r = sc_pkcs15_decipher(vs->p15card, pkey, opt_crypt_flags, pbuf, pInfo->cbData, pbuf2, pInfo->cbData, NULL);
-		logprintf(pCardData, 2, "sc_pkcs15_decipher returned %d\n", r);
-
+		/* do not log return value to not leak it */
 		if (r > 0) {
 			/* Need to handle padding */
 			if (pInfo->dwVersion >= CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO) {
@@ -4606,17 +4609,13 @@
 					  "sc_pkcs15_decipher: DECRYPT-INFO dwVersion=%lu\n",
 					  (unsigned long)pInfo->dwVersion);
 				if (pInfo->dwPaddingType == CARD_PADDING_PKCS1)   {
-					size_t temp = pInfo->cbData;
+					unsigned int temp = pInfo->cbData;
 					logprintf(pCardData, 2, "sc_pkcs15_decipher: stripping PKCS1 padding\n");
-					r = sc_pkcs1_strip_02_padding(vs->ctx, pbuf2, pInfo->cbData, pbuf2, &temp);
+					r = sc_pkcs1_strip_02_padding_constant_time(vs->ctx, prkey_info->modulus_length / 8, pbuf2, pInfo->cbData, pbuf2, &temp);
 					pInfo->cbData = (DWORD) temp;
-					if (r < 0)   {
-						logprintf(pCardData, 2, "Cannot strip PKCS1 padding: %i\n", r);
-						pCardData->pfnCspFree(pbuf);
-						pCardData->pfnCspFree(pbuf2);
-						dwret = SCARD_F_INTERNAL_ERROR;
-						goto err;
-					}
+					wrong_padding = constant_time_eq_i(r, SC_ERROR_WRONG_PADDING);
+					/* continue without returning error to not leak that padding is wrong
+					   to prevent time side-channel leak for Marvin attack*/
 				}
 				else if (pInfo->dwPaddingType == CARD_PADDING_OAEP)   {
 					/* TODO: Handle OAEP padding if present - can call PFN_CSP_UNPAD_DATA */
@@ -4664,28 +4663,36 @@
 		goto err;
 	}
 
-	if ( r < 0)   {
+	good = constant_time_ge(r, 1);
+	/* if no error or padding error, do not return here to prevent Marvin attack */
+	if (!(good | wrong_padding) && r < 0)   {
 		logprintf(pCardData, 2, "sc_pkcs15_decipher error(%i): %s\n", r, sc_strerror(r));
 		pCardData->pfnCspFree(pbuf);
 		pCardData->pfnCspFree(pbuf2);
 		dwret = md_translate_OpenSC_to_Windows_error(r, SCARD_E_INVALID_VALUE);
 		goto err;
 	}
-
-	logprintf(pCardData, 2, "decrypted data(%lu):\n",
-		  (unsigned long)pInfo->cbData);
-	loghex(pCardData, 7, pbuf2, pInfo->cbData);
+	dwret = constant_time_select_s(good, SCARD_S_SUCCESS, SCARD_F_INTERNAL_ERROR);
 
 	/*inversion donnees */
-	for(ui = 0; ui < pInfo->cbData; ui++)
-		pInfo->pbData[ui] = pbuf2[pInfo->cbData-ui-1];
+	/* copy data in constant-time way to prevent leak */
+	for (ui = 0; ui < pbufLen; ui++) {
+		unsigned int mask, inv_ui;
+		unsigned char msg_byte, orig_byte;
+		mask = good & constant_time_lt_s(ui, pInfo->cbData);	 /* ui should be in bounds of decrypted message */
+		inv_ui = pInfo->cbData - ui - 1;			 /* compute inversed ui index */
+		msg_byte = pbuf2[constant_time_select(mask, inv_ui, 0)]; /* if in range of decrypted message, read on inversed index otherwise read some bogus value */
+		orig_byte = pInfo->pbData[ui];
+		pInfo->pbData[ui] = constant_time_select_s(mask, msg_byte, orig_byte); /* store message byte only if in correct range */
+	}
 
 	pCardData->pfnCspFree(pbuf);
 	pCardData->pfnCspFree(pbuf2);
 
 err:
 	unlock(pCardData);
-	MD_FUNC_RETURN(pCardData, 1, dwret);
+	/* do not log return value to not leak it */
+	return dwret;
 }
 
 
diff -Nru --exclude '*.patch' opensc-0.23.0/src/pkcs11/framework-pkcs15.c opensc-0.23.0/src/pkcs11/framework-pkcs15.c
--- opensc-0.23.0/src/pkcs11/framework-pkcs15.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/pkcs11/framework-pkcs15.c	2024-12-23 02:03:20.000000000 +0000
@@ -18,6 +18,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include "common/constant-time.h"
 #include "config.h"
 #include <stdlib.h>
 #include <string.h>
@@ -4395,7 +4396,8 @@
 	struct pkcs15_fw_data *fw_data = NULL;
 	struct pkcs15_prkey_object *prkey;
 	unsigned char decrypted[512]; /* FIXME: Will not work for keys above 4096 bits */
-	int	buff_too_small, rv, flags = 0, prkey_has_path = 0;
+	int rv, flags = 0, prkey_has_path = 0;
+	CK_ULONG mask, good, rv_pkcs11;
 
 	if (pulDataLen == NULL) {
 		/* This is call from the C_DecyptInit function */
@@ -4484,27 +4486,53 @@
 	rv = sc_pkcs15_decipher(fw_data->p15_card, prkey->prv_p15obj, flags,
 			pEncryptedData, ulEncryptedDataLen, decrypted, sizeof(decrypted), pMechanism);
 
-	if (rv < 0 && !sc_pkcs11_conf.lock_login && !prkey_has_path)
+	/* skip for PKCS#1 v1.5 padding prevent side channel attack */
+	if (!(flags & SC_ALGORITHM_RSA_PAD_PKCS1) &&
+			rv < 0 && !sc_pkcs11_conf.lock_login && !prkey_has_path)
 		if (reselect_app_df(fw_data->p15_card) == SC_SUCCESS)
 			rv = sc_pkcs15_decipher(fw_data->p15_card, prkey->prv_p15obj, flags,
 					pEncryptedData, ulEncryptedDataLen, decrypted, sizeof(decrypted), pMechanism);
 
 	sc_unlock(p11card->card);
 
-	sc_log(context, "Decryption complete. Result %d.", rv);
+	sc_log(context, "Decryption complete.");
 
-	if (rv < 0)
-		return sc_to_cryptoki_error(rv, "C_Decrypt");
+	/* Handle following code in constant-time
+	 * to prevent Marvin attack for PKCS#1 v1.5 padding. */
 
-	buff_too_small = (*pulDataLen < (CK_ULONG)rv);
-	*pulDataLen = rv;
-	if (pData == NULL_PTR)
-		return CKR_OK;
-	if (buff_too_small)
-		return CKR_BUFFER_TOO_SMALL;
-	memcpy(pData, decrypted, *pulDataLen);
+	/* only padding error must be handled in constant-time way,
+	 * other error can be returned straight away */
+	if ((~constant_time_eq_i(rv, SC_ERROR_WRONG_PADDING) & constant_time_lt_s(sizeof(decrypted), (size_t)rv)))
+		return sc_to_cryptoki_error(rv, "C_Decrypt");
 
-	return CKR_OK;
+	/* check rv for padding error */
+	good = ~constant_time_eq_i(rv, SC_ERROR_WRONG_PADDING);
+	rv_pkcs11 = sc_to_cryptoki_error(SC_ERROR_WRONG_PADDING, "C_Decrypt");
+	rv_pkcs11 = constant_time_select_s(good, CKR_OK, rv_pkcs11);
+
+	if (pData == NULL_PTR) {
+		/* set length only if no error */
+		*pulDataLen = constant_time_select_s(good, rv, *pulDataLen);
+		/* return error only if original rv < 0 */
+		return rv_pkcs11;
+	}
+
+	/* check whether *pulDataLen < rv and set return value for small output buffer */
+	mask = good & constant_time_lt_s(*pulDataLen, rv);
+	rv_pkcs11 = constant_time_select_s(mask, CKR_BUFFER_TOO_SMALL, rv_pkcs11);
+	good &= ~mask;
+
+	/* move everything from decrypted into out buffer constant-time, if rv is ok */
+	for (CK_ULONG i = 0; i < *pulDataLen; i++) { /* iterate over whole pData to not disclose real depadded length */
+		CK_ULONG msg_index;
+		mask = good & constant_time_lt_s(i, sizeof(decrypted));		    /* i should be in the bounds of decrypted */
+		mask &= constant_time_lt_s(i, constant_time_select_s(good, rv, 0)); /* check that is in bounds of depadded message */
+		msg_index = constant_time_select_s(mask, i, 0);
+		pData[i] = constant_time_select_8(mask, decrypted[msg_index], pData[i]);
+	}
+	*pulDataLen = constant_time_select_s(good, rv, *pulDataLen);
+	/* do not log error code to prevent side channel attack */
+	return rv_pkcs11;
 }
 
 
diff -Nru --exclude '*.patch' opensc-0.23.0/src/pkcs11/mechanism.c opensc-0.23.0/src/pkcs11/mechanism.c
--- opensc-0.23.0/src/pkcs11/mechanism.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/pkcs11/mechanism.c	2024-12-23 02:03:20.000000000 +0000
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "common/constant-time.h"
 #include "sc-pkcs11.h"
 
 /* Also used for verification data */
@@ -1089,7 +1090,9 @@
 	rv = op->type->decrypt(op, pEncryptedData, ulEncryptedDataLen,
 	                       pData, pulDataLen);
 
-	if (rv != CKR_BUFFER_TOO_SMALL && pData != NULL)
+	/* terminate session for any return value except CKR_BUFFER_TOO_SMALL,
+	 * perform check in time side-channel free way to prevent Marvin attack */
+	if (!constant_time_eq_s(rv, CKR_BUFFER_TOO_SMALL) && pData != NULL)
 		session_stop_operation(session, SC_PKCS11_OPERATION_DECRYPT);
 
 	return rv;
@@ -1110,10 +1113,12 @@
 	rv = op->type->decrypt_update(op, pEncryptedData, ulEncryptedDataLen,
 			pData, pulDataLen);
 
-	/* terminate session for any error except CKR_BUFFER_TOO_SMALL */
-	if (rv != CKR_OK && rv != CKR_BUFFER_TOO_SMALL)
+	/* terminate session for any return value except CKR_BUFFER_TOO_SMALL,
+	 * perform check in time side-channel free way to prevent Marvin attack */
+	if (~constant_time_eq_s(rv, CKR_OK) & ~constant_time_eq_s(rv, CKR_BUFFER_TOO_SMALL))
 		session_stop_operation(session, SC_PKCS11_OPERATION_DECRYPT);
-	LOG_FUNC_RETURN(context, (int)rv);
+	/* do not log error code to prevent side channel attack */
+	return rv;
 }
 
 CK_RV
@@ -1530,6 +1535,10 @@
 	if (pulDataLen)
 		*pulDataLen = ulDataLen;
 
+	/* Skip DecryptFinalize for PKCS#1 v1.5 padding to prevent time side-channel leakage */
+	if (((CK_MECHANISM_PTR)&operation->mechanism)->mechanism == CKM_RSA_PKCS)
+		return rv;
+
 	if (rv != CKR_OK)
 		return rv;
 
diff -Nru --exclude '*.patch' opensc-0.23.0/src/pkcs11/misc.c opensc-0.23.0/src/pkcs11/misc.c
--- opensc-0.23.0/src/pkcs11/misc.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/pkcs11/misc.c	2024-12-23 02:03:20.000000000 +0000
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "common/constant-time.h"
 #include "sc-pkcs11.h"
 
 #define DUMP_TEMPLATE_MAX	32
@@ -174,7 +175,7 @@
 			slot->p11card->framework->logout(slot);
 		}
 
-		if (rv == CKR_USER_NOT_LOGGED_IN) {
+		if (constant_time_eq_s(rv, CKR_USER_NOT_LOGGED_IN)) {
 			slot->login_user = -1;
 			pop_all_login_states(slot);
 		}
diff -Nru --exclude '*.patch' opensc-0.23.0/src/pkcs11/pkcs11-object.c opensc-0.23.0/src/pkcs11/pkcs11-object.c
--- opensc-0.23.0/src/pkcs11/pkcs11-object.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/pkcs11/pkcs11-object.c	2024-12-23 02:03:20.000000000 +0000
@@ -1034,7 +1034,8 @@
 		rv = reset_login_state(session->slot, rv);
 	}
 
-	SC_LOG_RV("C_Decrypt() = %s", rv);
+	/* do not log error code to prevent side channel attack */
+	SC_LOG("C_Decrypt()");
 	sc_pkcs11_unlock();
 	return rv;
 }
@@ -1058,7 +1059,8 @@
 		rv = sc_pkcs11_decr_update(session, pEncryptedPart, ulEncryptedPartLen,
 				pPart, pulPartLen);
 
-	SC_LOG_RV("C_DecryptUpdate() = %s", rv);
+	/* do not log error code to prevent side channel attack */
+	SC_LOG("C_DecryptUpdate()");
 	sc_pkcs11_unlock();
 	return rv;
 }
@@ -1086,7 +1088,8 @@
 		rv = reset_login_state(session->slot, rv);
 	}
 
-	SC_LOG_RV("C_DecryptFinal() = %s", rv);
+	/* do not log error code to prevent side channel attack */
+	SC_LOG("C_DecryptFinal()");
 	sc_pkcs11_unlock();
 	return rv;
 }
diff -Nru --exclude '*.patch' opensc-0.23.0/src/pkcs11/sc-pkcs11.h opensc-0.23.0/src/pkcs11/sc-pkcs11.h
--- opensc-0.23.0/src/pkcs11/sc-pkcs11.h	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/pkcs11/sc-pkcs11.h	2024-12-23 02:03:20.000000000 +0000
@@ -245,6 +245,11 @@
         }\
 } while(0)
 
+#define SC_LOG(fmt) \
+	do { \
+		sc_log(context, (fmt)); \
+	} while (0)
+
 /* Debug virtual slots. S is slot to be highlighted or NULL
  * C is a comment format string and args It will be preceded by "VSS " */
 #define DEBUG_VSS(S, ...) do { sc_log(context,"VSS " __VA_ARGS__); _debug_virtual_slots(S); } while (0)
diff -Nru --exclude '*.patch' opensc-0.23.0/src/pkcs15init/pkcs15-authentic.c opensc-0.23.0/src/pkcs15init/pkcs15-authentic.c
--- opensc-0.23.0/src/pkcs15init/pkcs15-authentic.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/pkcs15init/pkcs15-authentic.c	2024-12-23 02:03:20.000000000 +0000
@@ -854,17 +854,19 @@
 	unsigned char buffer[8];
 	int rv,len;
 
-        sc_format_path(AUTHENTIC_CACHE_TIMESTAMP_PATH, &path);
-        rv = sc_select_file(p15card->card, &path, &file);
-        if (!rv)   {
+	sc_format_path(AUTHENTIC_CACHE_TIMESTAMP_PATH, &path);
+	rv = sc_select_file(p15card->card, &path, &file);
+	if (!rv) {
 		rv = sc_get_challenge(p15card->card, buffer, sizeof(buffer));
-		LOG_TEST_RET(ctx, rv, "Get challenge error");
+		if (rv < 0) {
+			sc_file_free(file);
+			LOG_TEST_RET(ctx, rv, "Get challenge error");
+		}
 
 		len = file->size > sizeof(buffer) ? sizeof(buffer) : file->size;
-	        rv = sc_update_binary(p15card->card, 0, buffer, len, 0);
-		LOG_TEST_RET(ctx, rv, "Update binary error");
-
+		rv = sc_update_binary(p15card->card, 0, buffer, len, 0);
 		sc_file_free(file);
+		LOG_TEST_RET(ctx, rv, "Update binary error");
 	}
 
 	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
diff -Nru --exclude '*.patch' opensc-0.23.0/src/pkcs15init/pkcs15-lib.c opensc-0.23.0/src/pkcs15init/pkcs15-lib.c
--- opensc-0.23.0/src/pkcs15init/pkcs15-lib.c	2024-12-23 02:03:20.000000000 +0000
+++ opensc-0.23.0/src/pkcs15init/pkcs15-lib.c	2024-12-23 02:03:20.000000000 +0000
@@ -3767,13 +3767,15 @@
 	if (callbacks.get_key)   {
 		rv = callbacks.get_key(profile, type, reference, defbuf, defsize, pinbuf, pinsize);
 		LOG_TEST_RET(ctx, rv, "Cannot get key");
-	}
-	else if (rv >= 0)  {
+	} else if (rv >= 0) {
 		if (*pinsize < defsize)
 			LOG_TEST_RET(ctx, SC_ERROR_BUFFER_TOO_SMALL, "Get transport key error");
 
 		memcpy(pinbuf, data.key_data, data.len);
 		*pinsize = data.len;
+	} else {
+		/* pinbuf and pinsize were not filled */
+		LOG_TEST_RET(ctx, SC_ERROR_INTERNAL, "Get transport key error");
 	}
 
 	memset(&auth_info, 0, sizeof(auth_info));
diff -Nru --exclude '*.patch' opensc-0.23.0/src/pkcs15init/pkcs15-sc-hsm.c opensc-0.23.0/src/pkcs15init/pkcs15-sc-hsm.c
--- opensc-0.23.0/src/pkcs15init/pkcs15-sc-hsm.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/pkcs15init/pkcs15-sc-hsm.c	2024-12-23 02:03:20.000000000 +0000
@@ -140,7 +140,7 @@
 	LOG_TEST_RET(card->ctx, filelistlength, "Could not enumerate file and key identifier");
 
 	for (j = 0; j < 256; j++) {
-		for (i = 0; i < filelistlength; i += 2) {
+		for (i = 0; i + 1 < filelistlength; i += 2) {
 			if ((filelist[i] == range) && (filelist[i + 1] == j)) {
 				break;
 			}
diff -Nru --exclude '*.patch' opensc-0.23.0/src/pkcs15init/pkcs15-setcos.c opensc-0.23.0/src/pkcs15init/pkcs15-setcos.c
--- opensc-0.23.0/src/pkcs15init/pkcs15-setcos.c	2024-12-23 02:03:20.000000000 +0000
+++ opensc-0.23.0/src/pkcs15init/pkcs15-setcos.c	2024-12-23 02:03:20.000000000 +0000
@@ -491,6 +491,9 @@
 		r = sc_card_ctl(p15card->card, SC_CARDCTL_SETCOS_GETDATA, &data_obj);
 		LOG_TEST_RET(ctx, r, "Cannot get key modulus: 'SETCOS_GETDATA' failed");
 
+		if (data_obj.DataLen < 3 || data_obj.DataLen < pubkey->u.rsa.modulus.len)
+			LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Cannot get key modulus: wrong length of raw key");
+
 		keybits = ((raw_pubkey[0] * 256) + raw_pubkey[1]);  /* modulus bit length */
 		if (keybits != key_info->modulus_length)  {
 			sc_log(ctx, 
diff -Nru --exclude '*.patch' opensc-0.23.0/src/pkcs15init/pkcs15-starcos.c opensc-0.23.0/src/pkcs15init/pkcs15-starcos.c
--- opensc-0.23.0/src/pkcs15init/pkcs15-starcos.c	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/pkcs15init/pkcs15-starcos.c	2024-12-23 02:03:20.000000000 +0000
@@ -670,6 +670,8 @@
 		return r;
 	len = tfile->size;
 	sc_file_free(tfile);
+	if (len == 0)
+		return SC_ERROR_INTERNAL;
 	buf = malloc(len);
 	if (!buf)
 		return SC_ERROR_OUT_OF_MEMORY;
@@ -682,7 +684,7 @@
 	if (num_keys == 0xff)
 		num_keys = 0;
 	/* encode public key */
-	keylen  = starcos_encode_pukey(rsa, NULL, kinfo);
+	keylen = starcos_encode_pukey(rsa, NULL, kinfo);
 	if (!keylen) {
 		free(buf);
 		return SC_ERROR_INTERNAL;
diff -Nru --exclude '*.patch' opensc-0.23.0/src/pkcs15init/profile.c opensc-0.23.0/src/pkcs15init/profile.c
--- opensc-0.23.0/src/pkcs15init/profile.c	2024-12-23 02:03:20.000000000 +0000
+++ opensc-0.23.0/src/pkcs15init/profile.c	2024-12-23 02:03:20.000000000 +0000
@@ -1807,7 +1807,7 @@
 static int
 do_pin_flags(struct state *cur, int argc, char **argv)
 {
-	unsigned int	flags;
+	unsigned int	flags = 0;
 	int		i, r;
 
 	if (cur->pin->pin.auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
diff -Nru --exclude '*.patch' opensc-0.23.0/src/tests/unittests/Makefile.am opensc-0.23.0/src/tests/unittests/Makefile.am
--- opensc-0.23.0/src/tests/unittests/Makefile.am	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/tests/unittests/Makefile.am	2024-12-23 02:03:20.000000000 +0000
@@ -6,8 +6,10 @@
 clean-local: code-coverage-clean
 distclean-local: code-coverage-dist-clean
 
-noinst_PROGRAMS = asn1 simpletlv cachedir pkcs15filter openpgp-tool hextobin decode_ecdsa_signature
-TESTS = asn1 simpletlv cachedir pkcs15filter openpgp-tool hextobin decode_ecdsa_signature
+noinst_PROGRAMS = asn1 simpletlv cachedir pkcs15filter openpgp-tool hextobin \
+	decode_ecdsa_signature strip_pkcs1_2_padding
+TESTS = asn1 simpletlv cachedir pkcs15filter openpgp-tool hextobin \
+	decode_ecdsa_signature strip_pkcs1_2_padding
 
 noinst_HEADERS = torture.h
 
@@ -28,6 +30,7 @@
 openpgp_tool_SOURCES = openpgp-tool.c $(top_builddir)/src/tools/openpgp-tool-helpers.c
 hextobin_SOURCES = hextobin.c
 decode_ecdsa_signature_SOURCES = decode_ecdsa_signature.c
+strip_pkcs1_2_padding = strip_pkcs1_2_padding.c
 
 if ENABLE_ZLIB
 noinst_PROGRAMS += compression
diff -Nru --exclude '*.patch' opensc-0.23.0/src/tests/unittests/Makefile.mak opensc-0.23.0/src/tests/unittests/Makefile.mak
--- opensc-0.23.0/src/tests/unittests/Makefile.mak	2022-11-29 08:34:43.000000000 +0000
+++ opensc-0.23.0/src/tests/unittests/Makefile.mak	2024-12-23 02:03:20.000000000 +0000
@@ -4,7 +4,8 @@
 
 OBJECTS = asn1.obj \
 	compression.obj \
-	pkcs15-emulator-filter.obj
+	pkcs15-emulator-filter.obj \
+	strip_pkcs1_2_padding.obj
 	$(TOPDIR)\win32\versioninfo.res
 
 all: $(TARGETS)
diff -Nru --exclude '*.patch' opensc-0.23.0/src/tests/unittests/strip_pkcs1_2_padding.c opensc-0.23.0/src/tests/unittests/strip_pkcs1_2_padding.c
--- opensc-0.23.0/src/tests/unittests/strip_pkcs1_2_padding.c	1970-01-01 00:00:00.000000000 +0000
+++ opensc-0.23.0/src/tests/unittests/strip_pkcs1_2_padding.c	2024-12-23 02:03:20.000000000 +0000
@@ -0,0 +1,215 @@
+#include "common/compat_strlcpy.c"
+#include "libopensc/log.c"
+#include "libopensc/padding.c"
+#include "torture.h"
+#include <cmocka.h>
+
+static void
+torture_long_output_buffer(void **state)
+{
+	unsigned int n = 14;
+	unsigned int in_len = 14;
+	unsigned char in[] = {0x00, 0x02,
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+			0x00,
+			'm', 's', 'g'};
+	unsigned int out_len = 3;
+	unsigned char *out = calloc(out_len, sizeof(unsigned char));
+	unsigned char result_msg[] = {'m', 's', 'g'};
+	int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+	assert_int_equal(r, 3);
+	assert_int_equal(r, (int)out_len);
+	assert_memory_equal(out, result_msg, r);
+	free(out);
+}
+
+static void
+torture_short_output_buffer(void **state)
+{
+	unsigned int n = 14;
+	unsigned int in_len = 14;
+	unsigned char in[] = {0x00, 0x02,
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+			0x00,
+			'm', 's', 'g'};
+	unsigned int out_len = 1;
+	unsigned char *out = calloc(out_len, sizeof(unsigned char));
+	int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+	assert_int_equal((int)out_len, 1);
+	assert_int_equal(r, SC_ERROR_WRONG_PADDING);
+	free(out);
+}
+
+static void
+torture_short_message_correct_padding(void **state)
+{
+	unsigned int n = 14;
+	unsigned int in_len = 14;
+	unsigned char in[] = {0x00, 0x02,
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+			0x00,
+			'm', 's', 'g'};
+	unsigned int out_len = 3;
+	unsigned char *out = calloc(out_len, sizeof(unsigned char));
+	unsigned char result_msg[] = {'m', 's', 'g'};
+	int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+	assert_int_equal(r, 3);
+	assert_int_equal(r, (int)out_len);
+	assert_memory_equal(out, result_msg, r);
+	free(out);
+}
+
+static void
+torture_missing_first_zero(void **state)
+{
+	unsigned int n = 13;
+	unsigned int in_len = 13;
+	unsigned char in[] = {0x02,
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+			0x00,
+			'm', 's', 'g'};
+	unsigned int out_len = 10;
+	unsigned char *out = calloc(out_len, sizeof(unsigned char));
+	int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+	assert_int_equal((int)out_len, 10);
+	assert_int_equal(r, SC_ERROR_WRONG_PADDING);
+	free(out);
+}
+
+static void
+torture_missing_two(void **state)
+{
+	unsigned int n = 13;
+	unsigned int in_len = 13;
+	unsigned char in[] = {0x00,
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+			0x00,
+			'm', 's', 'g'};
+	unsigned int out_len = 10;
+	unsigned char *out = calloc(out_len, sizeof(unsigned char));
+	int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+	assert_int_equal((int)out_len, 10);
+	assert_int_equal(r, SC_ERROR_WRONG_PADDING);
+	free(out);
+}
+
+static void
+torture_short_padding(void **state)
+{
+	unsigned int n = 13;
+	unsigned int in_len = 13;
+	unsigned char in[] = {0x00, 0x02,
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x00,
+			'm', 's', 'g'};
+	unsigned int out_len = 10;
+	unsigned char *out = calloc(out_len, sizeof(unsigned char));
+	int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+	assert_int_equal((int)out_len, 10);
+	assert_int_equal(r, SC_ERROR_WRONG_PADDING);
+	free(out);
+}
+
+static void
+torture_missing_second_zero(void **state)
+{
+	unsigned int n = 13;
+	unsigned int in_len = 13;
+	unsigned char in[] = {0x00, 0x02,
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+			'm', 's', 'g'};
+	unsigned int out_len = 10;
+	unsigned char *out = calloc(out_len, sizeof(unsigned char));
+	int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+	assert_int_equal((int)out_len, 10);
+	assert_int_equal(r, SC_ERROR_WRONG_PADDING);
+	free(out);
+}
+
+static void
+torture_missing_message(void **state)
+{
+	unsigned int n = 20;
+	unsigned int in_len = 11;
+	unsigned char in[] = {0x00, 0x02,
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+			0x00};
+	unsigned int out_len = 11;
+	unsigned char *out = calloc(out_len, sizeof(unsigned char));
+	int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+	assert_int_equal((int)out_len, 11);
+	assert_int_equal(r, SC_ERROR_WRONG_PADDING);
+	free(out);
+}
+
+static void
+torture_one_byte_message(void **state)
+{
+	unsigned int n = 12;
+	unsigned int in_len = 12;
+	unsigned char in[] = {0x00, 0x02,
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+			0x00,
+			'm'};
+	unsigned int out_len = 1;
+	unsigned char *out = calloc(out_len, sizeof(unsigned char));
+	unsigned char result_msg[] = {'m'};
+	int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+	assert_int_equal(r, 1);
+	assert_int_equal(r, (int)out_len);
+	assert_memory_equal(out, result_msg, r);
+	free(out);
+}
+
+static void
+torture_longer_padding(void **state)
+{
+	unsigned int n = 26;
+	unsigned int in_len = 26;
+	unsigned char in[] = {0x00, 0x02,
+			0x0e, 0x38, 0x97, 0x18, 0x16, 0x57, 0x9e, 0x30, 0xb6, 0xa5, 0x78, 0x13, 0x20, 0xca, 0x11,
+			0x00,
+			0x9d, 0x98, 0x3d, 0xca, 0xa9, 0xa7, 0x11, 0x0a};
+	unsigned int out_len = 8;
+	unsigned char *out = calloc(out_len, sizeof(unsigned char));
+	unsigned char result_msg[] = {0x9d, 0x98, 0x3d, 0xca, 0xa9, 0xa7, 0x11, 0x0a};
+	int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+	assert_int_equal(r, 8);
+	assert_int_equal(r, (int)out_len);
+	assert_memory_equal(out, result_msg, r);
+	free(out);
+}
+
+static void
+torture_empty_message(void **state)
+{
+	unsigned int n = 18;
+	unsigned int in_len = 18;
+	unsigned char in[] = {0x00, 0x02,
+			0x0e, 0x38, 0x97, 0x18, 0x16, 0x57, 0x9e, 0x30, 0xb6, 0xa5, 0x78, 0x13, 0x20, 0xca, 0x11,
+			0x00};
+	unsigned int out_len = 8;
+	unsigned char *out = calloc(out_len, sizeof(unsigned char));
+	int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+	assert_int_equal((int)out_len, 0);
+	assert_int_equal(r, 0);
+	free(out);
+}
+
+int
+main(void)
+{
+	const struct CMUnitTest tests[] = {
+			cmocka_unit_test(torture_long_output_buffer),
+			cmocka_unit_test(torture_short_output_buffer),
+			cmocka_unit_test(torture_short_message_correct_padding),
+			cmocka_unit_test(torture_missing_first_zero),
+			cmocka_unit_test(torture_missing_two),
+			cmocka_unit_test(torture_short_padding),
+			cmocka_unit_test(torture_missing_second_zero),
+			cmocka_unit_test(torture_missing_message),
+			cmocka_unit_test(torture_one_byte_message),
+			cmocka_unit_test(torture_longer_padding),
+			cmocka_unit_test(torture_empty_message)};
+	return cmocka_run_group_tests(tests, NULL, NULL);
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://alioth-lists.debian.net/pipermail/pkg-opensc-maint/attachments/20241223/2f26a94f/attachment-0001.sig>


More information about the pkg-opensc-maint mailing list