Package: release.debian.org
Severity: normal
Tags: bookworm
X-Debbugs-Cc: [email protected]
Control: affects -1 + src:opensc
User: [email protected]
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 <[email protected]>  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

Reply via email to