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