Your message dated Sat, 11 Jan 2025 11:03:09 +0000
with message-id <e1twzgn-009ja1...@coccia.debian.org>
and subject line Close 1091207
has caused the Debian Bug report #1091207,
regarding bookworm-pu: package opensc/0.23.0-0.3+deb12u2
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact ow...@bugs.debian.org
immediately.)


-- 
1091207: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1091207
Debian Bug Tracking System
Contact ow...@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: bookworm
X-Debbugs-Cc: ope...@packages.debian.org
Control: affects -1 + src:opensc
User: release.debian....@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.
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 <guil...@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);
+}

Attachment: signature.asc
Description: PGP signature


--- End Message ---
--- Begin Message ---
Version: 12.9
This update has been released as part of 12.9. Thank you for your contribution.

--- End Message ---

Reply via email to