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