From 7c06243f93b0aac2f487cf6f54e822eed00d5300 Mon Sep 17 00:00:00 2001 From: eabdullin Date: Mon, 18 Dec 2023 08:37:04 +0000 Subject: [PATCH] import CS opensc-0.20.0-7.el8 --- SOURCES/opensc-0.20.0-CVE-2023-2977.patch | 50 + SOURCES/opensc-0.20.0-idprime.patch | 25 + SOURCES/opensc-0.20.0-reader-removal.patch | 2173 +++++++++++++++++ SOURCES/opensc-0.23.0-cache-offsets.patch | 96 + .../opensc-0.23.0-constant-time-pkcs1.patch | 417 ++++ SOURCES/opensc-0.23.0-pin-bypass.patch | 107 + SOURCES/opensc-0.23.0-pkcs15init.patch | 855 +++++++ SPECS/opensc.spec | 72 +- 8 files changed, 3793 insertions(+), 2 deletions(-) create mode 100644 SOURCES/opensc-0.20.0-CVE-2023-2977.patch create mode 100644 SOURCES/opensc-0.20.0-idprime.patch create mode 100644 SOURCES/opensc-0.20.0-reader-removal.patch create mode 100644 SOURCES/opensc-0.23.0-cache-offsets.patch create mode 100644 SOURCES/opensc-0.23.0-constant-time-pkcs1.patch create mode 100644 SOURCES/opensc-0.23.0-pin-bypass.patch create mode 100644 SOURCES/opensc-0.23.0-pkcs15init.patch diff --git a/SOURCES/opensc-0.20.0-CVE-2023-2977.patch b/SOURCES/opensc-0.20.0-CVE-2023-2977.patch new file mode 100644 index 0000000..8d3d4fd --- /dev/null +++ b/SOURCES/opensc-0.20.0-CVE-2023-2977.patch @@ -0,0 +1,50 @@ +From 81944d1529202bd28359bede57c0a15deb65ba8a Mon Sep 17 00:00:00 2001 +From: fullwaywang +Date: Mon, 29 May 2023 10:38:48 +0800 +Subject: [PATCH] pkcs15init: correct left length calculation to fix buffer + overrun bug. Fixes #2785 + +--- + src/pkcs15init/pkcs15-cardos.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/pkcs15init/pkcs15-cardos.c b/src/pkcs15init/pkcs15-cardos.c +index 9715cf390f..f41f73c349 100644 +--- a/src/pkcs15init/pkcs15-cardos.c ++++ b/src/pkcs15init/pkcs15-cardos.c +@@ -872,7 +872,7 @@ static int cardos_have_verifyrc_package(sc_card_t *card) + sc_apdu_t apdu; + u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; + int r; +- const u8 *p = rbuf, *q; ++ const u8 *p = rbuf, *q, *pp; + size_t len, tlen = 0, ilen = 0; + + sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x88); +@@ -888,13 +888,13 @@ static int cardos_have_verifyrc_package(sc_card_t *card) + return 0; + + while (len != 0) { +- p = sc_asn1_find_tag(card->ctx, p, len, 0xe1, &tlen); +- if (p == NULL) ++ pp = sc_asn1_find_tag(card->ctx, p, len, 0xe1, &tlen); ++ if (pp == NULL) + return 0; + if (card->type == SC_CARD_TYPE_CARDOS_M4_3) { + /* the verifyRC package on CardOS 4.3B use Manufacturer ID 0x01 */ + /* and Package Number 0x07 */ +- q = sc_asn1_find_tag(card->ctx, p, tlen, 0x01, &ilen); ++ q = sc_asn1_find_tag(card->ctx, pp, tlen, 0x01, &ilen); + if (q == NULL || ilen != 4) + return 0; + if (q[0] == 0x07) +@@ -902,7 +902,7 @@ static int cardos_have_verifyrc_package(sc_card_t *card) + } else if (card->type == SC_CARD_TYPE_CARDOS_M4_4) { + /* the verifyRC package on CardOS 4.4 use Manufacturer ID 0x03 */ + /* and Package Number 0x02 */ +- q = sc_asn1_find_tag(card->ctx, p, tlen, 0x03, &ilen); ++ q = sc_asn1_find_tag(card->ctx, pp, tlen, 0x03, &ilen); + if (q == NULL || ilen != 4) + return 0; + if (q[0] == 0x02) + diff --git a/SOURCES/opensc-0.20.0-idprime.patch b/SOURCES/opensc-0.20.0-idprime.patch new file mode 100644 index 0000000..7b9b346 --- /dev/null +++ b/SOURCES/opensc-0.20.0-idprime.patch @@ -0,0 +1,25 @@ +From 34dad7f543f006ad269ce1f935a9e8d3e3a83db7 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Mon, 3 Feb 2020 16:40:51 +0100 +Subject: [PATCH] idprime: Add missing terminator in ATR list + +Thanks oss-fuzz + +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20510 +--- + src/libopensc/card-idprime.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/libopensc/card-idprime.c b/src/libopensc/card-idprime.c +index 744d5189b9..9f5adde9d2 100644 +--- a/src/libopensc/card-idprime.c ++++ b/src/libopensc/card-idprime.c +@@ -52,6 +52,7 @@ static const struct sc_atr_table idprime_atrs[] = { + "ff:ff:00:ff:ff:ff:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:ff:ff", + "Gemalto IDPrime MD 8840, 3840, 3810, 840 and 830 Cards", + SC_CARD_TYPE_IDPRIME_GENERIC, 0, NULL }, ++ { NULL, NULL, NULL, 0, 0, NULL } + }; + + static const sc_path_t idprime_path = { + diff --git a/SOURCES/opensc-0.20.0-reader-removal.patch b/SOURCES/opensc-0.20.0-reader-removal.patch new file mode 100644 index 0000000..b2951dc --- /dev/null +++ b/SOURCES/opensc-0.20.0-reader-removal.patch @@ -0,0 +1,2173 @@ +From 31d8c2dfd14ed01b430def2f46cc718ef4b595fc Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Wed, 19 Feb 2020 16:09:20 +0100 +Subject: [PATCH] Revert "pkcs11: fixed slotIDs when a new slot list is + requested" + +This reverts commit 7fb72ccf7bf3ca2ff3979b7ffbb690eed41ddb5f. +--- + src/pkcs11/pkcs11-global.c | 22 +--------------------- + src/pkcs11/slot.c | 2 +- + 2 files changed, 2 insertions(+), 22 deletions(-) + +diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c +index 71e13831..c51f2fb9 100644 +--- a/src/pkcs11/pkcs11-global.c ++++ b/src/pkcs11/pkcs11-global.c +@@ -451,13 +451,8 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese + pSlotList==NULL_PTR? "plug-n-play":"refresh"); + + /* Slot list can only change in v2.20 */ +- if (pSlotList == NULL_PTR) { ++ if (pSlotList == NULL_PTR) + sc_ctx_detect_readers(context); +- for (i=0; iflags &= ~SC_PKCS11_SLOT_FLAG_SEEN; +- } +- } + + card_detect_all(); + +@@ -488,21 +483,6 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese + prev_reader = slot->reader; + } + +- /* Slot list can only change in v2.20 */ +- if (pSlotList == NULL_PTR) { +- /* slot->id is derived from its location in the list virtual_slots. +- * When the slot list changes, so does slot->id, so we reindex the +- * slots here the same way it is done in `create_slot()` +- * +- * TODO use a persistent CK_SLOT_ID, e.g. by using something like +- * `slot->id = sc_crc32(slot, sizeof *slot);` (this example, however, +- * is currently not thread safe). */ +- for (i=0; iid = (CK_SLOT_ID) list_locate(&virtual_slots, slot); +- } +- } +- + if (pSlotList == NULL_PTR) { + sc_log(context, "was only a size inquiry (%lu)\n", numMatches); + *pulCount = numMatches; +diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c +index 423457b4..12dea459 100644 +--- a/src/pkcs11/slot.c ++++ b/src/pkcs11/slot.c +@@ -115,6 +115,7 @@ CK_RV create_slot(sc_reader_t *reader) + } + + slot->login_user = -1; ++ slot->id = (CK_SLOT_ID) list_locate(&virtual_slots, slot); + init_slot_info(&slot->slot_info, reader); + sc_log(context, "Initializing slot with id 0x%lx", slot->id); + +@@ -125,7 +126,6 @@ CK_RV create_slot(sc_reader_t *reader) + slot->slot_info.hardwareVersion.major = reader->version_major; + slot->slot_info.hardwareVersion.minor = reader->version_minor; + } +- slot->id = (CK_SLOT_ID) list_locate(&virtual_slots, slot); + + return CKR_OK; + } +-- +2.40.1 + +From 8f4a6c703b5ae7d4f44cf33c85330171afa917bf Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Thu, 20 Feb 2020 01:42:18 +0100 +Subject: [PATCH] align comment with implementation order + +--- + src/pkcs11/pkcs11-global.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c +index c51f2fb9..b1e0ab57 100644 +--- a/src/pkcs11/pkcs11-global.c ++++ b/src/pkcs11/pkcs11-global.c +@@ -469,8 +469,8 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese + slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); + /* the list of available slots contains: + * - if present, virtual hotplug slot; +- * - any slot with token; + * - without token(s), one empty slot per reader; ++ * - any slot with token; + * - any slot that has already been seen; + */ + if ((!tokenPresent && !slot->reader) +@@ -504,10 +504,7 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese + sc_log(context, "returned %lu slots\n", numMatches); + + out: +- if (found != NULL) { +- free (found); +- found = NULL; +- } ++ free (found); + sc_pkcs11_unlock(); + return rv; + } +-- +2.40.1 + + + + +From bae42473f68e7ca15fcf273348019361ccdc4e59 Mon Sep 17 00:00:00 2001 +From: Doug Engert +Date: Tue, 25 Feb 2020 20:24:00 -0600 +Subject: [PATCH 2/7] Improved Handling of PKCS11 Slots + +OpenSC PKCS11 now retains slots even when the reader is removed. +It can do this because existing OpenSC reader handling in ctx.c, +reader-pcsc.c and PC/SC allow OpenSC to do this. + +This simplifies the code, and allow a reader to be reinserted +and use the existing slot. This matching is actually done +in reader-pcsc.c because PC/SC returns the unique ids based on +the OS reader names. This is then used as the manufacturerID + +By not deleting slots the slot list can only increase which is a +restriction of Firefox. It does not fix all the Firefox issues, but +it does not go into a loop, when all the readers are removed. + +The defaults in opensc.conf for max-virtual-readers and slots-per-card +allow for 4 different readers used during one session. + + On branch PKCS11-SLOTS-3 + Changes to be committed: + modified: sc-pkcs11.h + modified: slot.c +--- + src/pkcs11/sc-pkcs11.h | 5 +++++ + src/pkcs11/slot.c | 43 ++++++++++++++++++++++++------------------ + 2 files changed, 30 insertions(+), 18 deletions(-) + +diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h +index 4309b63116..55236d2163 100644 +--- a/src/pkcs11/sc-pkcs11.h ++++ b/src/pkcs11/sc-pkcs11.h +@@ -206,6 +206,11 @@ struct sc_pkcs11_card { + * the application calls `C_GetSlotList` with `NULL`. This flag tracks the + * visibility to the application */ + #define SC_PKCS11_SLOT_FLAG_SEEN 1 ++/* reader-pcsc.c can reuse a removed reader, as the ctx->reader list contains ++ * readers which have been removed retain removed readers. ++ * Take advantage of this feature to allow for reinsertion of a reader*/ ++#define SC_PKCS11_SLOT_FLAG_READER_REMOVED 2 ++ + + struct sc_pkcs11_slot { + CK_SLOT_ID id; /* ID of the slot */ +diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c +index 12dea4599c..daaac6bb19 100644 +--- a/src/pkcs11/slot.c ++++ b/src/pkcs11/slot.c +@@ -133,18 +133,8 @@ CK_RV create_slot(sc_reader_t *reader) + void empty_slot(struct sc_pkcs11_slot *slot) + { + if (slot) { +- if (slot->flags & SC_PKCS11_SLOT_FLAG_SEEN) { +- /* Keep the slot visible to the application. The slot's state has +- * already been reset by `slot_token_removed()`, lists have been +- * emptied. We replace the reader with a virtual hotplug slot. */ +- slot->reader = NULL; +- init_slot_info(&slot->slot_info, NULL); +- } else { +- list_destroy(&slot->objects); +- list_destroy(&slot->logins); +- list_delete(&virtual_slots, slot); +- free(slot); +- } ++ list_clear(&slot->objects); ++ list_clear(&slot->logins); + } + } + +@@ -383,21 +373,38 @@ CK_RV card_detect(sc_reader_t *reader) + CK_RV + card_detect_all(void) + { +- unsigned int i; ++ unsigned int i, j; + + sc_log(context, "Detect all cards"); + /* Detect cards in all initialized readers */ + for (i=0; i< sc_ctx_get_reader_count(context); i++) { + sc_reader_t *reader = sc_ctx_get_reader(context, i); ++ int removed = 0; /* have we called card_removed for this reader */ ++ + if (reader->flags & SC_READER_REMOVED) { + struct sc_pkcs11_slot *slot; +- card_removed(reader); +- while ((slot = reader_get_slot(reader))) { +- empty_slot(slot); ++ /* look at all slots to call card_removed amd empty_slot */ ++ for (j = 0; jreader == reader) { ++ if (!removed) { ++ card_removed(reader); ++ removed = 1; /* only need to call once for this reader */ ++ } ++ if (slot->flags & SC_PKCS11_SLOT_FLAG_READER_REMOVED) { ++ empty_slot(slot); ++ slot->flags |= SC_PKCS11_SLOT_FLAG_READER_REMOVED; ++ } ++ } + } +- _sc_delete_reader(context, reader); +- i--; + } else { ++ struct sc_pkcs11_slot *slot; ++ for (j = 0; jreader == reader) ++ slot->flags &= ~SC_PKCS11_SLOT_FLAG_READER_REMOVED; ++ } ++ + if (!reader_get_slot(reader)) + initialize_reader(reader); + else + +From cf4f21236060c35e566de2712a6a54ea0e2eabe5 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Mon, 2 Mar 2020 22:24:54 +0100 +Subject: [PATCH 3/7] pkcs11: simpify reader removal + +- reader (slot) description is already initialized init_slot_info() +- objects and logins are already released in slot_token_removed +--- + src/pkcs11/pkcs11-global.c | 4 +--- + src/pkcs11/sc-pkcs11.h | 11 ---------- + src/pkcs11/slot.c | 43 ++++++-------------------------------- + 3 files changed, 7 insertions(+), 51 deletions(-) + +diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c +index b1e0ab57c9..25c4cd362e 100644 +--- a/src/pkcs11/pkcs11-global.c ++++ b/src/pkcs11/pkcs11-global.c +@@ -475,10 +475,8 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese + */ + if ((!tokenPresent && !slot->reader) + || (!tokenPresent && slot->reader != prev_reader) +- || (slot->slot_info.flags & CKF_TOKEN_PRESENT) +- || (slot->flags & SC_PKCS11_SLOT_FLAG_SEEN)) { ++ || (slot->slot_info.flags & CKF_TOKEN_PRESENT)) { + found[numMatches++] = slot->id; +- slot->flags |= SC_PKCS11_SLOT_FLAG_SEEN; + } + prev_reader = slot->reader; + } +diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h +index 55236d2163..16e8fdf797 100644 +--- a/src/pkcs11/sc-pkcs11.h ++++ b/src/pkcs11/sc-pkcs11.h +@@ -201,16 +201,6 @@ struct sc_pkcs11_card { + unsigned int nmechanisms; + }; + +-/* If the slot did already show with `C_GetSlotList`, then we need to keep this +- * slot alive. PKCS#11 2.30 allows allows adding but not removing slots until +- * the application calls `C_GetSlotList` with `NULL`. This flag tracks the +- * visibility to the application */ +-#define SC_PKCS11_SLOT_FLAG_SEEN 1 +-/* reader-pcsc.c can reuse a removed reader, as the ctx->reader list contains +- * readers which have been removed retain removed readers. +- * Take advantage of this feature to allow for reinsertion of a reader*/ +-#define SC_PKCS11_SLOT_FLAG_READER_REMOVED 2 +- + + struct sc_pkcs11_slot { + CK_SLOT_ID id; /* ID of the slot */ +@@ -232,7 +222,6 @@ struct sc_pkcs11_slot { + }; + typedef struct sc_pkcs11_slot sc_pkcs11_slot_t; + +- + /* Forward decl */ + typedef struct sc_pkcs11_operation sc_pkcs11_operation_t; + +diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c +index daaac6bb19..2fb495d295 100644 +--- a/src/pkcs11/slot.c ++++ b/src/pkcs11/slot.c +@@ -121,24 +121,11 @@ CK_RV create_slot(sc_reader_t *reader) + + if (reader != NULL) { + slot->reader = reader; +- strcpy_bp(slot->slot_info.manufacturerID, reader->vendor, 32); +- strcpy_bp(slot->slot_info.slotDescription, reader->name, 64); +- slot->slot_info.hardwareVersion.major = reader->version_major; +- slot->slot_info.hardwareVersion.minor = reader->version_minor; + } + + return CKR_OK; + } + +-void empty_slot(struct sc_pkcs11_slot *slot) +-{ +- if (slot) { +- list_clear(&slot->objects); +- list_clear(&slot->logins); +- } +-} +- +- + /* create slots associated with a reader, called whenever a reader is seen. */ + CK_RV initialize_reader(sc_reader_t *reader) + { +@@ -373,38 +360,20 @@ CK_RV card_detect(sc_reader_t *reader) + CK_RV + card_detect_all(void) + { +- unsigned int i, j; ++ unsigned int i; + + sc_log(context, "Detect all cards"); + /* Detect cards in all initialized readers */ + for (i=0; i< sc_ctx_get_reader_count(context); i++) { + sc_reader_t *reader = sc_ctx_get_reader(context, i); +- int removed = 0; /* have we called card_removed for this reader */ + + if (reader->flags & SC_READER_REMOVED) { +- struct sc_pkcs11_slot *slot; +- /* look at all slots to call card_removed amd empty_slot */ +- for (j = 0; jreader == reader) { +- if (!removed) { +- card_removed(reader); +- removed = 1; /* only need to call once for this reader */ +- } +- if (slot->flags & SC_PKCS11_SLOT_FLAG_READER_REMOVED) { +- empty_slot(slot); +- slot->flags |= SC_PKCS11_SLOT_FLAG_READER_REMOVED; +- } +- } +- } ++ card_removed(reader); ++ /* do not remove slots related to this reader which would be ++ * possible according to PKCS#11 2.20 and later, because NSS can't ++ * handle a shrinking slot list ++ * https://bugzilla.mozilla.org/show_bug.cgi?id=1613632 */ + } else { +- struct sc_pkcs11_slot *slot; +- for (j = 0; jreader == reader) +- slot->flags &= ~SC_PKCS11_SLOT_FLAG_READER_REMOVED; +- } +- + if (!reader_get_slot(reader)) + initialize_reader(reader); + else + +From 87d2798e72ab940b7f7a57490663751ae4dc8842 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Tue, 3 Mar 2020 12:38:37 +0100 +Subject: [PATCH 4/7] removed unused plug_and_play parameter + +see 1fb741338a010515b35f28cd9c769561f3e574a2 +--- + src/pkcs11/sc-pkcs11.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h +index 16e8fdf797..c3a13934bc 100644 +--- a/src/pkcs11/sc-pkcs11.h ++++ b/src/pkcs11/sc-pkcs11.h +@@ -65,7 +65,6 @@ struct sc_pkcs11_slot; + struct sc_pkcs11_card; + + struct sc_pkcs11_config { +- unsigned int plug_and_play; + unsigned int max_virtual_slots; + unsigned int slots_per_card; + unsigned char lock_login; + +From cc4d4ff0b069c5517cce1ccbd374b6a18d61e020 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Tue, 3 Mar 2020 15:09:17 +0100 +Subject: [PATCH 5/7] pkcs11: reclaim unused slots based on reader description + +When a reader is removed and reattached, this re-uses the old slot +without relying on the fact that the sc_reader_t is unchanged. +--- + src/pkcs11/pkcs11-global.c | 5 ++--- + src/pkcs11/slot.c | 46 ++++++++++++++++++++++++++++++++------ + 2 files changed, 41 insertions(+), 10 deletions(-) + +diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c +index 25c4cd362e..95c37f3c72 100644 +--- a/src/pkcs11/pkcs11-global.c ++++ b/src/pkcs11/pkcs11-global.c +@@ -468,8 +468,7 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese + for (i=0; iname, 64); ++ strcpy_bp(manufacturerID, reader->vendor, 32); + + /* Locate a slot related to the reader */ + for (i = 0; ireader == reader) + return slot; ++ if (slot->reader == NULL && reader != NULL ++ && 0 == memcmp(slot->slot_info.slotDescription, slotDescription, 64) ++ && 0 == memcmp(slot->slot_info.manufacturerID, manufacturerID, 32) ++ && slot->slot_info.hardwareVersion.major == reader->version_major ++ && slot->slot_info.hardwareVersion.minor == reader->version_minor) ++ return slot; + } + return NULL; + } +@@ -82,8 +93,8 @@ static int object_list_seeker(const void *el, const void *key) + + CK_RV create_slot(sc_reader_t *reader) + { +- /* find unused virtual hotplug slots */ +- struct sc_pkcs11_slot *slot = reader_get_slot(NULL); ++ /* find unused slots previously allocated for the same reader */ ++ struct sc_pkcs11_slot *slot = reader_reclaim_slot(reader); + + /* create a new slot if no empty slot is available */ + if (!slot) { +@@ -373,11 +384,32 @@ card_detect_all(void) + * possible according to PKCS#11 2.20 and later, because NSS can't + * handle a shrinking slot list + * https://bugzilla.mozilla.org/show_bug.cgi?id=1613632 */ ++ ++ /* Instead, remove the releation between reader and slot */ ++ for (i = 0; ireader == reader) { ++ slot->reader = NULL; ++ } ++ } + } else { +- if (!reader_get_slot(reader)) +- initialize_reader(reader); +- else +- card_detect(sc_ctx_get_reader(context, i)); ++ /* Locate a slot related to the reader */ ++ int found = 0; ++ for (i = 0; ireader == reader) { ++ found = 1; ++ break; ++ } ++ } ++ if (!found) { ++ for (i = 0; i < sc_pkcs11_conf.slots_per_card; i++) { ++ CK_RV rv = create_slot(reader); ++ if (rv != CKR_OK) ++ return rv; ++ } ++ } ++ card_detect(reader); + } + } + sc_log(context, "All cards detected"); + +From 61a2c6aaff0aa3add222f8560a8075637ee9b1fd Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Mon, 13 Jan 2020 17:21:18 +0100 +Subject: [PATCH 6/7] reader-pcsc: fixed handling of detatching events + +- allows re-attatching a reader to an existing reader object by +resetting the SC_READER_REMOVED flag +- readers that are flagged with SC_READER_REMOVED are not used for +SCardGetStatusChange to avoid SCARD_E_UNKNOWN_READER + +fixes https://github.com/OpenSC/OpenSC/issues/1903 +--- + src/libopensc/reader-pcsc.c | 48 ++++++++++++++++++++++++------------- + 1 file changed, 31 insertions(+), 17 deletions(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 66b426e436..14e3b4e0ec 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -181,6 +181,9 @@ static int pcsc_to_opensc_error(LONG rv) + return SC_ERROR_READER_LOCKED; + case SCARD_E_NO_READERS_AVAILABLE: + return SC_ERROR_NO_READERS_FOUND; ++ case SCARD_E_UNKNOWN_READER: ++ return SC_ERROR_READER_DETACHED; ++ + case SCARD_E_NO_SERVICE: + /* If the service is (auto)started, there could be readers later */ + return SC_ERROR_NO_READERS_FOUND; +@@ -1467,8 +1470,13 @@ static int pcsc_detect_readers(sc_context_t *ctx) + + for (reader_name = reader_buf; *reader_name != '\x0'; + reader_name += strlen(reader_name) + 1) { +- if (!strcmp(reader->name, reader_name)) ++ if (!strcmp(reader->name, reader_name)) { ++ if (reader->flags & SC_READER_REMOVED) { ++ reader->flags &= ~SC_READER_REMOVED; ++ refresh_attributes(reader); ++ } + break; ++ } + } + + if (*reader_name != '\x0') { +@@ -1546,7 +1554,7 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + LONG rv; + SCARD_READERSTATE *rgReaderStates; + size_t i; +- unsigned int num_watch; ++ unsigned int num_watch, count; + int r = SC_ERROR_INTERNAL; + DWORD dwtimeout; + +@@ -1565,22 +1573,30 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + + /* Find out the current status */ +- num_watch = sc_ctx_get_reader_count(ctx); +- sc_log(ctx, "Trying to watch %d readers", num_watch); +- for (i = 0; i < num_watch; i++) { +- rgReaderStates[i].szReader = sc_ctx_get_reader(ctx, i)->name; +- rgReaderStates[i].dwCurrentState = SCARD_STATE_UNAWARE; +- rgReaderStates[i].dwEventState = SCARD_STATE_UNAWARE; ++ num_watch = 0; ++ count = sc_ctx_get_reader_count(ctx); ++ for (i = 0; i < count; i++) { ++ sc_reader_t *reader = sc_ctx_get_reader(ctx, i); ++ if (reader->flags & SC_READER_REMOVED) ++ continue; ++ rgReaderStates[num_watch].szReader = reader->name; ++ rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE; ++ rgReaderStates[num_watch].dwEventState = SCARD_STATE_UNAWARE; ++ num_watch++; + } +-#ifndef __APPLE__ +- /* OS X 10.6.2 - 10.12.6 do not support PnP notification */ ++ sc_log(ctx, "Trying to watch %d reader%s", num_watch, num_watch == 1 ? "" : "s"); + if (event_mask & SC_EVENT_READER_ATTACHED) { +- rgReaderStates[i].szReader = "\\\\?PnP?\\Notification"; +- rgReaderStates[i].dwCurrentState = SCARD_STATE_UNAWARE; +- rgReaderStates[i].dwEventState = SCARD_STATE_UNAWARE; ++#ifdef __APPLE__ ++ /* OS X 10.6.2 - 10.12.6 do not support PnP notification */ ++ sc_log(ctx, "PnP notification not supported"); ++#else ++ rgReaderStates[num_watch].szReader = "\\\\?PnP?\\Notification"; ++ rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE; ++ rgReaderStates[num_watch].dwEventState = SCARD_STATE_UNAWARE; + num_watch++; +- } ++ sc_log(ctx, "Trying to detect new readers"); + #endif ++ } + } + else { + rgReaderStates = (SCARD_READERSTATE *)(*reader_states); +@@ -1606,14 +1622,12 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + goto out; + } + +-#ifdef __APPLE__ + if (num_watch == 0) { +- sc_log(ctx, "No readers available, PnP notification not supported"); ++ sc_log(ctx, "No readers available to be watched"); + *event_reader = NULL; + r = SC_ERROR_NO_READERS_FOUND; + goto out; + } +-#endif + + rv = gpriv->SCardGetStatusChange(gpriv->pcsc_wait_ctx, 0, rgReaderStates, num_watch); + if (rv != SCARD_S_SUCCESS) { + +From 2901a2d040ec13b70c9cd212f7cbf9ad4ef8c602 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Mon, 13 Jan 2020 17:25:38 +0100 +Subject: [PATCH] opensc-notify: handle reader insertion/removal events + +- If readers are attatched, the new reader is probed for a card to check +if a notification needs to be sent +- removal of readers are not notified to the user, we assume that PC/SC +sends the correct card removal event +- The list of readers to be monitored is adjusted once a reader (dis)appears +- On macOS, without PnP notification, we always check for new/removed +readers with SCardListReaders +- fixes interrupt handling in opensc-notify on Unix + +fixes https://github.com/OpenSC/OpenSC/issues/1874 +--- + src/libopensc/errors.c | 4 +- + src/libopensc/internal-winscard.h | 1 + + src/libopensc/opensc.h | 33 +++-- + src/libopensc/reader-pcsc.c | 205 +++++++++++++++++++++--------- + src/tools/opensc-notify.c | 125 ++++++++++-------- + src/ui/strings.c | 10 +- + 6 files changed, 248 insertions(+), 130 deletions(-) + +diff --git a/src/libopensc/errors.c b/src/libopensc/errors.c +index 5b58b7ea6c..03cb79dd1f 100644 +--- a/src/libopensc/errors.c ++++ b/src/libopensc/errors.c +@@ -45,8 +45,8 @@ const char *sc_strerror(int error) + "Message too long (keypad)", + "Timeout while waiting for event from card reader", + "Unresponsive card (correctly inserted?)", +- "Reader detached (hotplug device?)", +- "Reader reattached (hotplug device?)", ++ "Reader detached", ++ "Reader reattached", + "Reader in use by another application" + }; + const int rdr_base = -SC_ERROR_READER; +diff --git a/src/libopensc/internal-winscard.h b/src/libopensc/internal-winscard.h +index edc315ca2f..6b2a21c569 100644 +--- a/src/libopensc/internal-winscard.h ++++ b/src/libopensc/internal-winscard.h +@@ -100,6 +100,7 @@ typedef unsigned __int8 uint8_t; + #define SCARD_E_NOT_TRANSACTED 0x80100016 /**< An attempt was made to end a non-existent transaction. */ + #define SCARD_E_READER_UNAVAILABLE 0x80100017 /**< The specified reader is not currently available for use. */ + #define SCARD_E_NO_SERVICE 0x8010001D /**< The Smart card resource manager is not running. */ ++#define SCARD_E_SERVICE_STOPPED 0x8010001E /**< The smart card resource manager has shut down. */ + #define SCARD_E_NO_READERS_AVAILABLE 0x8010002E /**< Cannot find a smart card reader. */ + #define SCARD_W_UNRESPONSIVE_CARD 0x80100066 /**< The smart card is not responding to a reset. */ + #define SCARD_W_UNPOWERED_CARD 0x80100067 /**< Power has been removed from the smart card, so that further communication is not possible. */ +diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h +index 10bea0a013..9e764665b2 100644 +--- a/src/libopensc/opensc.h ++++ b/src/libopensc/opensc.h +@@ -213,10 +213,10 @@ extern "C" { + /* Event masks for sc_wait_for_event() */ + #define SC_EVENT_CARD_INSERTED 0x0001 + #define SC_EVENT_CARD_REMOVED 0x0002 +-#define SC_EVENT_CARD_EVENTS SC_EVENT_CARD_INSERTED|SC_EVENT_CARD_REMOVED ++#define SC_EVENT_CARD_EVENTS (SC_EVENT_CARD_INSERTED|SC_EVENT_CARD_REMOVED) + #define SC_EVENT_READER_ATTACHED 0x0004 + #define SC_EVENT_READER_DETACHED 0x0008 +-#define SC_EVENT_READER_EVENTS SC_EVENT_READER_ATTACHED|SC_EVENT_READER_DETACHED ++#define SC_EVENT_READER_EVENTS (SC_EVENT_READER_ATTACHED|SC_EVENT_READER_DETACHED) + + #define MAX_FILE_SIZE 65535 + +@@ -1024,18 +1024,25 @@ int sc_disconnect_card(struct sc_card *card); + int sc_detect_card_presence(sc_reader_t *reader); + + /** +- * Waits for an event on readers. Note: only the event is detected, +- * there is no update of any card or other info. +- * NOTE: Only PC/SC backend implements this. +- * @param ctx pointer to a Context structure +- * @param event_mask The types of events to wait for; this should +- * be ORed from one of the following +- * SC_EVENT_CARD_REMOVED +- * SC_EVENT_CARD_INSERTED +- * SC_EVENT_READER_ATTACHED +- * @param event_reader (OUT) the reader on which the event was detected, or NULL if new reader ++ * Waits for an event on readers. ++ * ++ * In case of a reader event (attached/detached), the list of reader is ++ * adjusted accordingly. This means that a subsequent call to ++ * `sc_ctx_detect_readers()` is not needed. ++ * ++ * @note Only PC/SC backend implements this. An infinite timeout on macOS does ++ * not detect reader events (use a limited timeout instead if needed). ++ * ++ * @param ctx (IN) pointer to a Context structure ++ * @param event_mask (IN) The types of events to wait for; this should ++ * be ORed from one of the following: ++ * - SC_EVENT_CARD_REMOVED ++ * - SC_EVENT_CARD_INSERTED ++ * - SC_EVENT_READER_ATTACHED ++ * - SC_EVENT_READER_DETACHED ++ * @param event_reader (OUT) the reader on which the event was detected + * @param event (OUT) the events that occurred. This is also ORed +- * from the SC_EVENT_CARD_* constants listed above. ++ * from the constants listed above. + * @param timeout Amount of millisecs to wait; -1 means forever + * @retval < 0 if an error occurred + * @retval = 0 if a an event happened +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 14e3b4e0ec..34dc821bfa 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -127,6 +127,9 @@ struct pcsc_global_private_data { + SCardTransmit_t SCardTransmit; + SCardListReaders_t SCardListReaders; + SCardGetAttrib_t SCardGetAttrib; ++ ++ sc_reader_t *attached_reader; ++ sc_reader_t *removed_reader; + }; + + struct pcsc_private_data { +@@ -185,6 +188,7 @@ static int pcsc_to_opensc_error(LONG rv) + return SC_ERROR_READER_DETACHED; + + case SCARD_E_NO_SERVICE: ++ case SCARD_E_SERVICE_STOPPED: + /* If the service is (auto)started, there could be readers later */ + return SC_ERROR_NO_READERS_FOUND; + case SCARD_E_NO_SMARTCARD: +@@ -358,7 +362,7 @@ static int refresh_attributes(sc_reader_t *reader) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + +- if (priv->reader_state.szReader == NULL) { ++ if (priv->reader_state.szReader == NULL || reader->ctx->flags & SC_READER_REMOVED) { + priv->reader_state.szReader = reader->name; + priv->reader_state.dwCurrentState = SCARD_STATE_UNAWARE; + priv->reader_state.dwEventState = SCARD_STATE_UNAWARE; +@@ -382,12 +386,11 @@ static int refresh_attributes(sc_reader_t *reader) + } + + /* the system could not detect the reader. It means, the prevoiusly attached reader is disconnected. */ +- if ( ++ if (rv == (LONG)SCARD_E_UNKNOWN_READER + #ifdef SCARD_E_NO_READERS_AVAILABLE +- (rv == (LONG)SCARD_E_NO_READERS_AVAILABLE) || ++ || rv == (LONG)SCARD_E_NO_READERS_AVAILABLE + #endif +- (rv == (LONG)SCARD_E_UNKNOWN_READER) || (rv == (LONG)SCARD_E_SERVICE_STOPPED)) { +- ++ || rv == (LONG)SCARD_E_SERVICE_STOPPED) { + if (old_flags & SC_READER_CARD_PRESENT) { + reader->flags |= SC_READER_CARD_CHANGED; + } +@@ -1143,7 +1146,7 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) + return; + + rv = gpriv->SCardControl(card_handle, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, feature_buf, sizeof(feature_buf), &feature_len); +- if (rv != (LONG)SCARD_S_SUCCESS) { ++ if (rv != SCARD_S_SUCCESS) { + PCSC_TRACE(reader, "SCardControl failed", rv); + return; + } +@@ -1382,6 +1385,8 @@ static int pcsc_detect_readers(sc_context_t *ctx) + } + + sc_log(ctx, "Probing PC/SC readers"); ++ gpriv->attached_reader = NULL; ++ gpriv->removed_reader = NULL; + + do { + if (gpriv->pcsc_ctx == (SCARDCONTEXT)-1) { +@@ -1399,12 +1404,11 @@ static int pcsc_detect_readers(sc_context_t *ctx) + * All readers have disappeared, so mark them as + * such so we don't keep polling them over and over. + */ +- if ( ++ if (rv == (LONG)SCARD_E_NO_SERVICE + #ifdef SCARD_E_NO_READERS_AVAILABLE +- (rv == (LONG)SCARD_E_NO_READERS_AVAILABLE) || ++ || rv == (LONG)SCARD_E_NO_READERS_AVAILABLE + #endif +- (rv == (LONG)SCARD_E_NO_SERVICE) || (rv == (LONG)SCARD_E_SERVICE_STOPPED)) { +- ++ || rv == (LONG)SCARD_E_SERVICE_STOPPED) { + for (i = 0; i < sc_ctx_get_reader_count(ctx); i++) { + sc_reader_t *reader = sc_ctx_get_reader(ctx, i); + +@@ -1414,6 +1418,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) + } + + reader->flags |= SC_READER_REMOVED; ++ gpriv->removed_reader = reader; + } + } + +@@ -1473,6 +1478,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) + if (!strcmp(reader->name, reader_name)) { + if (reader->flags & SC_READER_REMOVED) { + reader->flags &= ~SC_READER_REMOVED; ++ gpriv->attached_reader = reader; + refresh_attributes(reader); + } + break; +@@ -1487,8 +1493,11 @@ static int pcsc_detect_readers(sc_context_t *ctx) + (reader_buf + reader_buf_size) - next_reader_name); + reader_buf_size -= (next_reader_name - reader_name); + } else { +- /* existing reader not found */ +- reader->flags |= SC_READER_REMOVED; ++ if (!(reader->flags & SC_READER_REMOVED)) { ++ /* existing reader not found */ ++ reader->flags |= SC_READER_REMOVED; ++ gpriv->removed_reader = reader; ++ } + } + } + +@@ -1503,6 +1512,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) + _sc_delete_reader(ctx, reader); + continue; + } ++ gpriv->attached_reader = reader; + + /* check for pinpad support early, to allow opensc-tool -l display accurate information */ + priv = reader->drv_data; +@@ -1555,7 +1565,7 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + SCARD_READERSTATE *rgReaderStates; + size_t i; + unsigned int num_watch, count; +- int r = SC_ERROR_INTERNAL; ++ int r = SC_ERROR_INTERNAL, detect_readers = 0, detected_hotplug = 0; + DWORD dwtimeout; + + LOG_FUNC_CALLED(ctx); +@@ -1579,8 +1589,13 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + sc_reader_t *reader = sc_ctx_get_reader(ctx, i); + if (reader->flags & SC_READER_REMOVED) + continue; ++ struct pcsc_private_data *priv = reader->drv_data; + rgReaderStates[num_watch].szReader = reader->name; +- rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE; ++ if (priv->reader_state.szReader == NULL) { ++ rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE; ++ } else { ++ rgReaderStates[num_watch].dwCurrentState = priv->reader_state.dwEventState; ++ } + rgReaderStates[num_watch].dwEventState = SCARD_STATE_UNAWARE; + num_watch++; + } +@@ -1589,6 +1604,12 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + #ifdef __APPLE__ + /* OS X 10.6.2 - 10.12.6 do not support PnP notification */ + sc_log(ctx, "PnP notification not supported"); ++ /* Always check on new readers as if a hotplug ++ * event was detected. This overwrites a ++ * SC_ERROR_EVENT_TIMEOUT if a new reader is ++ * detected with SC_SUCCESS. */ ++ detect_readers = 1; ++ detected_hotplug = 1; + #else + rgReaderStates[num_watch].szReader = "\\\\?PnP?\\Notification"; + rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE; +@@ -1622,9 +1643,11 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + goto out; + } + ++ *event_reader = NULL; ++ *event = 0; ++ + if (num_watch == 0) { + sc_log(ctx, "No readers available to be watched"); +- *event_reader = NULL; + r = SC_ERROR_NO_READERS_FOUND; + goto out; + } +@@ -1646,7 +1669,6 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + + /* Scan the current state of all readers to see if they + * match any of the events we're polling for */ +- *event = 0; + for (i = 0, rsp = rgReaderStates; i < num_watch; i++, rsp++) { + DWORD state, prev_state; + sc_log(ctx, "'%s' before=0x%08X now=0x%08X", +@@ -1657,51 +1679,72 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + state = rsp->dwEventState; + rsp->dwCurrentState = rsp->dwEventState; + if (state & SCARD_STATE_CHANGED) { +- + /* check for hotplug events */ +- if (!strcmp(rgReaderStates[i].szReader, "\\\\?PnP?\\Notification")) { ++ if (!strcmp(rsp->szReader, "\\\\?PnP?\\Notification")) { + sc_log(ctx, "detected hotplug event"); +- *event |= SC_EVENT_READER_ATTACHED; +- *event_reader = NULL; +- } ++ /* Windows sends hotplug event on both, attaching and ++ * detaching a reader. pcscd only sends it in case of ++ * attaching a reader. We'll detect later in which case we ++ * are. */ ++ detect_readers = 1; ++ detected_hotplug = 1; ++ ++ /* Windows wants us to manually reset the changed state */ ++ rsp->dwEventState &= ~SCARD_STATE_CHANGED; ++ ++ /* By default, ignore a hotplug event as if a timout ++ * occurred, since it may be an unrequested removal or ++ * false alarm. Just continue to loop and check at the end ++ * of this function whether we need to return the attached ++ * reader or not. */ ++ r = SC_ERROR_EVENT_TIMEOUT; ++ } else { ++ sc_reader_t *reader = sc_ctx_get_reader_by_name(ctx, rsp->szReader); ++ if (reader) { ++ /* copy the state so we know what to watch out for */ ++ struct pcsc_private_data *priv = reader->drv_data; ++ priv->reader_state.dwEventState = state; ++ priv->reader_state.dwCurrentState = prev_state; ++ } + +- if ((state & SCARD_STATE_PRESENT) && !(prev_state & SCARD_STATE_PRESENT)) { +- sc_log(ctx, "card inserted event"); +- *event |= SC_EVENT_CARD_INSERTED; +- } ++ if ((state & SCARD_STATE_PRESENT) && !(prev_state & SCARD_STATE_PRESENT)) { ++ sc_log(ctx, "card inserted event"); ++ *event |= SC_EVENT_CARD_INSERTED; ++ } + +- if ((prev_state & SCARD_STATE_PRESENT) && !(state & SCARD_STATE_PRESENT)) { +- sc_log(ctx, "card removed event"); +- *event |= SC_EVENT_CARD_REMOVED; +- } ++ if ((prev_state & SCARD_STATE_PRESENT) && !(state & SCARD_STATE_PRESENT)) { ++ sc_log(ctx, "card removed event"); ++ *event |= SC_EVENT_CARD_REMOVED; ++ } + +- if ((state & SCARD_STATE_UNKNOWN) && !(prev_state & SCARD_STATE_UNKNOWN)) { +- sc_log(ctx, "reader detached event"); +- *event |= SC_EVENT_READER_DETACHED; +- } ++ if ((state & SCARD_STATE_UNKNOWN) && !(prev_state & SCARD_STATE_UNKNOWN)) { ++ sc_log(ctx, "reader detached event"); ++ *event |= SC_EVENT_READER_DETACHED; ++ detect_readers = 1; ++ } + +- if ((prev_state & SCARD_STATE_UNKNOWN) && !(state & SCARD_STATE_UNKNOWN)) { +- sc_log(ctx, "reader re-attached event"); +- *event |= SC_EVENT_READER_ATTACHED; +- } ++ if ((state & SCARD_STATE_IGNORE) && !(prev_state & SCARD_STATE_IGNORE)) { ++ sc_log(ctx, "reader detached event"); ++ *event |= SC_EVENT_READER_DETACHED; ++ detect_readers = 1; ++ } + +- if (*event & event_mask) { +- sc_log(ctx, "Matching event 0x%02X in reader %s", *event, rsp->szReader); +- *event_reader = sc_ctx_get_reader_by_name(ctx, rsp->szReader); +- r = SC_SUCCESS; +- goto out; +- } ++ if ((prev_state & SCARD_STATE_UNKNOWN) && !(state & SCARD_STATE_UNKNOWN)) { ++ sc_log(ctx, "reader re-attached event"); ++ *event |= SC_EVENT_READER_ATTACHED; ++ detect_readers = 1; ++ } + ++ if (*event & event_mask) { ++ sc_log(ctx, "Matching event 0x%02X in reader %s", *event, rsp->szReader); ++ *event_reader = reader; ++ r = SC_SUCCESS; ++ goto out; ++ } else { ++ *event = 0; ++ } ++ } + } +- +- /* No match - copy the state so pcscd knows +- * what to watch out for */ +- /* rsp->dwCurrentState = rsp->dwEventState; */ +- } +- +- if (timeout == 0) { +- r = SC_ERROR_EVENT_TIMEOUT; +- goto out; + } + + /* Set the timeout if caller wants to time out */ +@@ -1713,13 +1756,13 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + + rv = gpriv->SCardGetStatusChange(gpriv->pcsc_wait_ctx, dwtimeout, rgReaderStates, num_watch); + +- if (rv == (LONG) SCARD_E_CANCELLED) { ++ if (rv == (LONG)SCARD_E_CANCELLED) { + /* C_Finalize was called, events don't matter */ + r = SC_ERROR_EVENT_TIMEOUT; + goto out; + } + +- if (rv == (LONG) SCARD_E_TIMEOUT) { ++ if (rv == (LONG)SCARD_E_TIMEOUT) { + r = SC_ERROR_EVENT_TIMEOUT; + goto out; + } +@@ -1731,12 +1774,54 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + } + } + out: +- if (!reader_states) { +- free(rgReaderStates); ++ /* in case of an error re-detect all readers */ ++ if (r < 0 && r != SC_ERROR_EVENT_TIMEOUT) ++ detect_readers = 1; ++ ++ if (detect_readers) { ++ pcsc_detect_readers(ctx); + } +- else if (*reader_states == NULL) { +- sc_log(ctx, "return allocated 'reader states'"); +- *reader_states = rgReaderStates; ++ ++ if (detected_hotplug) { ++ if (gpriv->attached_reader) { ++ if (event_reader && event && !*event) { ++ /* no other event has been detected, yet */ ++ *event_reader = gpriv->attached_reader; ++ *event = SC_EVENT_READER_ATTACHED; ++ r = SC_SUCCESS; ++ } ++ gpriv->attached_reader = NULL; ++ } else if (gpriv->removed_reader) { ++ /* Normally, we only check the hotplug event for attached readers. ++ * However, Windows also notifies on removal. Check, if the latter ++ * was requested by the caller. */ ++ if (event_mask & SC_EVENT_READER_DETACHED ++ && event_reader && event && !*event) { ++ /* no other event has been detected, yet */ ++ *event_reader = gpriv->removed_reader; ++ *event = SC_EVENT_READER_DETACHED; ++ r = SC_SUCCESS; ++ } ++ gpriv->removed_reader = NULL; ++ } else { ++ /* false alarm, there was no reader attached or removed, ++ * avoid re-initialize the reader states by resetting detect_readers */ ++ detect_readers = 0; ++ } ++ } ++ ++ if (detect_readers) { ++ free(rgReaderStates); ++ if (reader_states && *reader_states) ++ *reader_states = NULL; ++ } else { ++ if (!reader_states) { ++ free(rgReaderStates); ++ } ++ else if (*reader_states == NULL) { ++ sc_log(ctx, "return allocated reader states"); ++ *reader_states = rgReaderStates; ++ } + } + + LOG_FUNC_RETURN(ctx, r); +@@ -2449,6 +2534,7 @@ int pcsc_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_c + } + + sc_log(ctx, "Probing PC/SC reader"); ++ gpriv->attached_reader = NULL; + + gpriv->pcsc_ctx = *(SCARDCONTEXT *)pcsc_context_handle; + card_handle = *(SCARDHANDLE *)pcsc_card_handle; +@@ -2467,6 +2553,7 @@ int pcsc_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_c + } else { + _sc_delete_reader(ctx, reader); + } ++ gpriv->attached_reader = reader; + } + + out: +diff --git a/src/tools/opensc-notify.c b/src/tools/opensc-notify.c +index afc24353a8..87d66c6721 100644 +--- a/src/tools/opensc-notify.c ++++ b/src/tools/opensc-notify.c +@@ -49,26 +49,21 @@ void Sleep(unsigned int Milliseconds) + } + #endif + +-void stop_daemon() +-{ +-#ifdef PCSCLITE_GOOD +- sc_cancel(ctx); +-#endif +- run_daemon = 0; +-} +- + void notify_daemon() + { + int r; +- const unsigned int event_mask = SC_EVENT_CARD_EVENTS; ++ const unsigned int event_mask = SC_EVENT_CARD_EVENTS|SC_EVENT_READER_EVENTS; + unsigned int event; + struct sc_reader *event_reader = NULL; +- size_t error_count = 0; ++ void *reader_states = NULL; ++#ifndef __APPLE__ + /* timeout adjusted to the maximum response time for WM_CLOSE in case + * canceling doesn't work */ + const int timeout = 20000; +- struct sc_atr old_atr; +- void *reader_states = NULL; ++#else ++ /* lower timeout, because Apple doesn't support hotplug events */ ++ const int timeout = 2000; ++#endif + + r = sc_establish_context(&ctx, "opensc-notify"); + if (r < 0 || !ctx) { +@@ -76,50 +71,51 @@ void notify_daemon() + return; + } + +- while (run_daemon && error_count < 1000) { ++ while (run_daemon) { ++ + r = sc_wait_for_event(ctx, event_mask, + &event_reader, &event, timeout, &reader_states); + if (r < 0) { + if (r == SC_ERROR_NO_READERS_FOUND) { +- /* No readers available, PnP notification not supported */ +- Sleep(200); +- } else { +- error_count++; ++ Sleep(timeout); ++ continue; + } +- continue; + } + +- error_count = 0; +- +- if (event & SC_EVENT_CARD_REMOVED) { +- sc_notify_id(ctx, &old_atr, NULL, NOTIFY_CARD_REMOVED); +- } +- if (event & SC_EVENT_CARD_INSERTED) { +- if (event_reader) { +- /* FIXME `pcsc_wait_for_event` has all the information that's +- * requested again with `pcsc_detect_card_presence`, but it +- * doesn't use the ATR, for example, to refresh the reader's +- * attributes. To get the ATR we need to call +- * sc_detect_card_presence. Eventually this should be fixed. */ +- sc_detect_card_presence(event_reader); +- memcpy(old_atr.value, event_reader->atr.value, +- event_reader->atr.len); +- old_atr.len = event_reader->atr.len; +- } else { +- old_atr.len = 0; ++ if (event_reader) { ++ if (event & SC_EVENT_CARD_REMOVED ++ || (event & SC_EVENT_READER_DETACHED ++ && event_reader->flags & SC_READER_CARD_PRESENT)) { ++ /* sc_notify_id uses only the reader's name for displaying on ++ * removal, so use a dummy card here to get that information ++ * into the notification */ ++ struct sc_pkcs15_card p15card; ++ sc_card_t card; ++ memset(&card, 0, sizeof card); ++ card.reader = event_reader; ++ memset(&p15card, 0, sizeof p15card); ++ p15card.card = &card; ++ sc_notify_id(ctx, &event_reader->atr, &p15card, NOTIFY_CARD_REMOVED); ++ } else if (event & SC_EVENT_CARD_INSERTED ++ || (event & SC_EVENT_READER_ATTACHED ++ && event_reader->flags & SC_READER_CARD_PRESENT)) { ++ /* sc_notify_id prevers the reader's name for displaying on ++ * insertion, so use a dummy card here to get that information ++ * into the notification */ ++ struct sc_pkcs15_card p15card; ++ sc_card_t card; ++ memset(&card, 0, sizeof card); ++ card.reader = event_reader; ++ memset(&p15card, 0, sizeof p15card); ++ p15card.card = &card; ++ sc_notify_id(ctx, &event_reader->atr, &p15card, NOTIFY_CARD_INSERTED); + } +- sc_notify_id(ctx, old_atr.len ? &old_atr : NULL, NULL, +- NOTIFY_CARD_INSERTED); + } + } + + if (ctx) { +- if (error_count >= 1000) { +- sc_log(ctx, "Too many errors; aborting."); +- } + /* free `reader_states` */ + sc_wait_for_event(ctx, 0, NULL, NULL, 0, &reader_states); +- reader_states = NULL; + sc_release_context(ctx); + ctx = NULL; + } +@@ -132,7 +128,8 @@ void notify_daemon() + LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) + { + if (message == WM_CLOSE || message == WM_QUIT) { +- stop_daemon(); ++ run_daemon = 0; ++ sc_cancel(ctx); + return TRUE; + } + +@@ -182,32 +179,54 @@ WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR lpCmdLine, int nShowC + + #else + +-#ifdef HAVE_SIGACTION ++#if defined(HAVE_SIGACTION) && defined(HAVE_PTHREAD) ++#include ++#include + #include ++#include ++ ++static int cancellation_fd[] = {-1, -1}; + + void sig_handler(int sig) { +- stop_daemon(); ++ run_daemon = 0; ++ write(cancellation_fd[1], &sig, sizeof sig); + } + +-void set_sa_handler(void) ++static void *cancellation_proc(void *arg) + { +- struct sigaction new_sig, old_sig; ++ (void)arg; ++ while (run_daemon) { ++ int sig; ++ if (sizeof sig == read(cancellation_fd[0], &sig, sizeof sig)) { ++ break; ++ } ++ } ++ sc_cancel(ctx); ++ return NULL; ++} + +- /* Register signal handlers */ ++void setup_cancellation(void) ++{ ++ pthread_t cancellation_thread; ++ struct sigaction new_sig, old_sig; + new_sig.sa_handler = sig_handler; + sigemptyset(&new_sig.sa_mask); + new_sig.sa_flags = SA_RESTART; +- if ((sigaction(SIGINT, &new_sig, &old_sig) < 0) +- || (sigaction(SIGTERM, &new_sig, &old_sig) < 0)) { +- fprintf(stderr, "Failed to create signal handler: %s", strerror(errno)); ++ ++ if (pipe(cancellation_fd) != 0 ++ || (errno = pthread_create(&cancellation_thread, NULL, cancellation_proc, NULL)) != 0 ++ || sigaction(SIGINT, &new_sig, &old_sig) != 0 ++ || sigaction(SIGTERM, &new_sig, &old_sig) != 0) { ++ fprintf(stderr, "Failed to setup cancellation: %s", strerror(errno)); + } + } + + #else + +-void set_sa_handler(void) ++void setup_cancellation(void) + { + } ++ + #endif + + #include "opensc-notify-cmdline.h" +@@ -244,8 +263,8 @@ main (int argc, char **argv) + + if ((!cmdline.customized_mode_counter && !cmdline.standard_mode_counter) + || cmdline.daemon_mode_counter) { +- set_sa_handler(); + run_daemon = 1; ++ setup_cancellation(); + notify_daemon(); + } else { + /* give the notification process some time to spawn */ +diff --git a/src/ui/strings.c b/src/ui/strings.c +index ea1d3ba650..90dbc0f964 100644 +--- a/src/ui/strings.c ++++ b/src/ui/strings.c +@@ -34,8 +34,12 @@ static const char *get_inserted_text(struct sc_pkcs15_card *p15card, struct sc_a + static char text[3*SC_MAX_ATR_SIZE] = {0}; + const char prefix[] = "ATR: "; + +- if (p15card && p15card->card && p15card->card->name) { ++ if (p15card && p15card->card ++ && p15card->card->name) { + return p15card->card->name; ++ } else if (p15card && p15card->card ++ && p15card->card->reader && p15card->card->reader->name) { ++ return p15card->card->reader->name; + } + + if (!atr) +@@ -192,7 +196,7 @@ const char *ui_get_str(struct sc_context *ctx, struct sc_atr *atr, + str = "Dieses Fenster wird automatisch geschlossen, wenn die PIN am PIN-Pad eingegeben wurde (Timeout typischerweise nach 30 Sekunden)."; + break; + case NOTIFY_CARD_INSERTED: +- if (p15card) { ++ if (p15card && p15card->card && p15card->card->name) { + str = "Smartcard kann jetzt verwendet werden"; + } else { + str = "Smartcard erkannt"; +@@ -260,7 +264,7 @@ const char *ui_get_str(struct sc_context *ctx, struct sc_atr *atr, + str = "This window will be closed automatically after the PIN has been submitted on the PIN pad (timeout typically after 30 seconds)."; + break; + case NOTIFY_CARD_INSERTED: +- if (p15card) { ++ if (p15card && p15card->card && p15card->card->name) { + str = "Smart card is ready to use"; + } else { + str = "Smart card detected"; + + +From a87c4c68cdc272a65cff0a77b5e48b6b0d921387 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Fri, 5 Jun 2020 14:57:00 +0200 +Subject: [PATCH 1/3] Unbreak wait for events + +By Jabuk Jelen + +Fixes https://github.com/OpenSC/OpenSC/issues/2021 +--- + src/libopensc/reader-pcsc.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index b3da6fc88b..808b75530b 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -1700,12 +1700,6 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + r = SC_ERROR_EVENT_TIMEOUT; + } else { + sc_reader_t *reader = sc_ctx_get_reader_by_name(ctx, rsp->szReader); +- if (reader) { +- /* copy the state so we know what to watch out for */ +- struct pcsc_private_data *priv = reader->drv_data; +- priv->reader_state.dwEventState = state; +- priv->reader_state.dwCurrentState = prev_state; +- } + + if ((state & SCARD_STATE_PRESENT) && !(prev_state & SCARD_STATE_PRESENT)) { + sc_log(ctx, "card inserted event"); + +From fb84c16ebadcefcb4dcd68780a1cbe9adb2671bc Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Fri, 5 Jun 2020 15:50:31 +0200 +Subject: [PATCH 2/3] pcsc: immediately exit on hotplug events + +fixes delayed notification for removed readers + +closes https://github.com/OpenSC/OpenSC/issues/2021 +--- + src/libopensc/reader-pcsc.c | 4 ++++ + src/ui/notify.c | 9 +++++++++ + 2 files changed, 13 insertions(+) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 808b75530b..56da7816ef 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -1741,6 +1741,10 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + } + } + ++ /* if a reader was detected, we need to create a new list of readers */ ++ if (detected_hotplug) ++ goto out; ++ + /* Set the timeout if caller wants to time out */ + if (timeout == -1) { + dwtimeout = INFINITE; +diff --git a/src/ui/notify.c b/src/ui/notify.c +index 90e7778c10..897ea21ca3 100644 +--- a/src/ui/notify.c ++++ b/src/ui/notify.c +@@ -437,6 +437,7 @@ void sc_notify_id(struct sc_context *ctx, struct sc_atr *atr, + #elif defined(ENABLE_NOTIFY) && defined(ENABLE_GIO2) + + #include ++#include "libopensc/log.h" + + static GApplication *application = NULL; + +@@ -481,6 +482,14 @@ static void notify_gio(struct sc_context *ctx, + } + } + ++ if (ctx) { ++ sc_log(ctx, "%s %s %s %s", ++ title ? title : "", ++ text ? text : "", ++ icon ? icon : "", ++ group ? group : ""); ++ } ++ + g_application_send_notification(application, group, notification); + + if (gicon) { + +From 00f7f3d87ed3d5d981440e5f53e8520d067a9864 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Mon, 8 Jun 2020 17:04:49 +0200 +Subject: [PATCH 3/3] pkcs11: fixed notifying twice in case of an attached + reader + +before 14e396273 sc_wait_for_event() only notified in case of a new +reader, but didn't add it to the internal list of readers. That's why +PKCS#11 needed to bail out early in this case (and the application had +to call C_WaitForSlotEvent a second time to actually get the related +slot). Since sc_wait_for_event() can now handle insertion correctly, we +can now immediately check (and reset) the events on the slots. +--- + src/pkcs11/pkcs11-global.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c +index 671890309f..6985bc21ea 100644 +--- a/src/pkcs11/pkcs11-global.c ++++ b/src/pkcs11/pkcs11-global.c +@@ -730,13 +730,6 @@ CK_RV C_WaitForSlotEvent(CK_FLAGS flags, /* blocking/nonblocking flag */ + sc_log(context, "C_WaitForSlotEvent() reader_states:%p", reader_states); + sc_pkcs11_unlock(); + r = sc_wait_for_event(context, mask, &found, &events, -1, &reader_states); +- if (events & SC_EVENT_READER_ATTACHED) { +- rv = sc_pkcs11_lock(); +- if (rv != CKR_OK) +- return rv; +- +- goto out; +- } + /* Was C_Finalize called ? */ + if (in_finalize == 1) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + +From 4cfa4f334d6cbf3f730b5d6b0e5c0daeeffd2da6 Mon Sep 17 00:00:00 2001 +From: Zoltan Kelemen +Date: Sun, 12 Jul 2020 22:07:13 +0200 +Subject: [PATCH] Fix for issue #1999: - Reset context to undefined handle + value on error since call may alter output parameter. - Continue to assume + -1 as undefined handle value in all PCSC implementations, to keep this fix + as small and surgical as possible. + +--- + src/libopensc/reader-pcsc.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 56da7816ef..6443d2a9c9 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -1424,7 +1424,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) + + if ((rv == (LONG)SCARD_E_NO_SERVICE) || (rv == (LONG)SCARD_E_SERVICE_STOPPED)) { + gpriv->SCardReleaseContext(gpriv->pcsc_ctx); +- gpriv->pcsc_ctx = 0; ++ gpriv->pcsc_ctx = -1; + gpriv->pcsc_wait_ctx = -1; + /* reconnecting below may may restart PC/SC service */ + rv = SCARD_E_INVALID_HANDLE; +@@ -1441,6 +1441,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) + + rv = gpriv->SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &gpriv->pcsc_ctx); + if (rv != SCARD_S_SUCCESS) { ++ gpriv->pcsc_ctx = -1; + PCSC_LOG(ctx, "SCardEstablishContext failed", rv); + ret = pcsc_to_opensc_error(rv); + goto out; +@@ -1451,7 +1452,8 @@ static int pcsc_detect_readers(sc_context_t *ctx) + } + } while (rv != SCARD_S_SUCCESS); + +- reader_buf = malloc(sizeof(char) * reader_buf_size); ++ /* The +2 below is to make sure we have zero terminators, in case we get invalid data */ ++ reader_buf = calloc(reader_buf_size+2, sizeof(char)); + if (!reader_buf) { + ret = SC_ERROR_OUT_OF_MEMORY; + goto out; +@@ -1629,6 +1631,7 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + if (gpriv->pcsc_wait_ctx == (SCARDCONTEXT)-1) { + rv = gpriv->SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &gpriv->pcsc_wait_ctx); + if (rv != SCARD_S_SUCCESS) { ++ gpriv->pcsc_wait_ctx = -1; + PCSC_LOG(ctx, "SCardEstablishContext(wait) failed", rv); + r = pcsc_to_opensc_error(rv); + goto out; + + +From 8c5d4ec47f9c3f48bd5b2d7747030b8ffc39a2c6 Mon Sep 17 00:00:00 2001 +From: Frida Flodin +Date: Wed, 6 Oct 2021 09:05:48 +0000 +Subject: [PATCH 1/4] Fix detect_card_presence return value + +In opensc.h the documentation states that the function +detect_card_presence should return 0 if no card is present, which is +reasonable. This was not the case before since more flags could be set +even if SC_READER_CARD_PRESENT is not. This was probably missed before +since more flags has been added since this function was first written. + +Signed-off-by: Frida Flodin +--- + src/libopensc/reader-pcsc.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 99887852d7..54d8cf30c7 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -476,7 +476,12 @@ static int pcsc_detect_card_presence(sc_reader_t *reader) + rv = refresh_attributes(reader); + if (rv != SC_SUCCESS) + LOG_FUNC_RETURN(reader->ctx, rv); +- LOG_FUNC_RETURN(reader->ctx, reader->flags); ++ ++ // Return 0 if the card is not present ++ if (reader->flags & SC_READER_CARD_PRESENT) ++ LOG_FUNC_RETURN(reader->ctx, reader->flags); ++ else ++ LOG_FUNC_RETURN(reader->ctx, 0); + } + + static int check_forced_protocol(sc_reader_t *reader, DWORD *protocol) + +From ffb5c82ea3724462a5a23e6b2b34bec30af4eb70 Mon Sep 17 00:00:00 2001 +From: Frida Flodin +Date: Wed, 6 Oct 2021 09:05:52 +0000 +Subject: [PATCH 2/4] Handle when reader is detached on macOS + +refresh_attributes returns SC_SUCCESS if we can't detect the reader. The +same should happen if the reader is unknown/detached. + +This was found when detaching reader on macOS. Then we don't get +SCARD_E_UNKNOWN_READER from SCardGetStatusChange. We notice it later +from that the state of the reader is SCARD_STATE_UNKNOWN. This resulted +in C_WaitForSlotEvent not noticing that the reader, and thus the card, +was removed. + +Signed-off-by: Frida Flodin +--- + src/libopensc/reader-pcsc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 54d8cf30c7..40f994a514 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -415,7 +415,8 @@ static int refresh_attributes(sc_reader_t *reader) + * XXX: We'll hit it again, as no readers are removed currently. + */ + reader->flags &= ~(SC_READER_CARD_PRESENT); +- return SC_ERROR_READER_DETACHED; ++ sc_log(reader->ctx, "Reader unknown: %s", sc_strerror(SC_ERROR_READER_DETACHED)); ++ SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS); + } + + reader->flags &= ~(SC_READER_CARD_CHANGED|SC_READER_CARD_INUSE|SC_READER_CARD_EXCLUSIVE); + +From 20d11ef10abc3728f7eb21c6452e2b373fc4bbb1 Mon Sep 17 00:00:00 2001 +From: Frida Flodin +Date: Wed, 6 Oct 2021 09:05:56 +0000 +Subject: [PATCH 3/4] Fix incorrect use of SC_READER_CARD_CHANGED + +Looking in opensc.h the flag SC_READER_CARD_CHANGED should be set if the +card was exchanged. In other words if a card is present but it is not +the same card as before. It looks like SC_READER_CARD_CHANGED was +misinterpreted as a flag for when the card was removed and thus that the +status has changed. + +Signed-off-by: Frida Flodin +--- + src/libopensc/reader-pcsc.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 40f994a514..664042a199 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -393,10 +393,7 @@ static int refresh_attributes(sc_reader_t *reader) + || rv == (LONG)SCARD_E_NO_READERS_AVAILABLE + #endif + || rv == (LONG)SCARD_E_SERVICE_STOPPED) { +- if (old_flags & SC_READER_CARD_PRESENT) { +- reader->flags |= SC_READER_CARD_CHANGED; +- } +- ++ reader->flags &= ~(SC_READER_CARD_PRESENT); + SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS); + } + +@@ -459,8 +456,6 @@ static int refresh_attributes(sc_reader_t *reader) + } + } else { + reader->flags &= ~SC_READER_CARD_PRESENT; +- if (old_flags & SC_READER_CARD_PRESENT) +- reader->flags |= SC_READER_CARD_CHANGED; + } + sc_log(reader->ctx, "card %s%s", + reader->flags & SC_READER_CARD_PRESENT ? "present" : "absent", + +From 26bbbe7bb6ab3198ffb50f7dfb9757b3b3d471a1 Mon Sep 17 00:00:00 2001 +From: Frida Flodin +Date: Wed, 6 Oct 2021 09:05:59 +0000 +Subject: [PATCH 4/4] Sanity check detect_card_presence return value + +The return value from detect_card_presence should be 0 if no card is +present. Therefore the flag SC_READER_CARD_PRESENT is not allowed to be +0 if detect_card_presence has non-zero return value. + +Signed-off-by: Frida Flodin +--- + src/libopensc/sc.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/libopensc/sc.c b/src/libopensc/sc.c +index 29f6b86895..40b9646fe2 100644 +--- a/src/libopensc/sc.c ++++ b/src/libopensc/sc.c +@@ -337,6 +337,12 @@ int sc_detect_card_presence(sc_reader_t *reader) + LOG_FUNC_RETURN(reader->ctx, SC_ERROR_NOT_SUPPORTED); + + r = reader->ops->detect_card_presence(reader); ++ ++ // Check that we get sane return value from backend ++ // detect_card_presence should return 0 if no card is present. ++ if (r && !(r & SC_READER_CARD_PRESENT)) ++ LOG_FUNC_RETURN(reader->ctx, SC_ERROR_INTERNAL); ++ + LOG_FUNC_RETURN(reader->ctx, r); + } + +From 62cf2c496eec26b7bc6a2c55bb3b9b88db462962 Mon Sep 17 00:00:00 2001 +From: Veronika Hanulikova +Date: Fri, 2 Sep 2022 16:19:26 +0200 +Subject: [PATCH] Keep pcsc reader flags when disconnected + +When the reader is removed, the reader->flags are set to +SC_READER_REMOVED. card_detect_all() then frees resources and +sets slot->reader to NULL. During this, sc_card_disconnect() +is called, setting reader->flags to 0. In a subsequent call +to card_detect_all() with the reader still removed, the corresponding +slot is reclaimed, and slot->reader set back to the removed reader, +but slot->events is overwritten, which causes the C_WaitForSlot() +not to recognize event on the slot. +--- + src/libopensc/reader-pcsc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 1efd8a0d31..40bfd293d3 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -672,7 +672,7 @@ static int pcsc_disconnect(sc_reader_t * reader) + LONG rv = priv->gpriv->SCardDisconnect(priv->pcsc_card, priv->gpriv->disconnect_action); + PCSC_TRACE(reader, "SCardDisconnect returned", rv); + } +- reader->flags = 0; ++ reader->flags &= SC_READER_REMOVED; + return SC_SUCCESS; + } + + +From c2e00e9071952b30ed6d58d9b7670eb3d93ea6fb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Timo=20Ter=C3=A4s?= +Date: Fri, 20 May 2022 14:26:44 +0300 +Subject: [PATCH] pkcs11-session: fix C_GetSessionInfo in 'atomic' mode + +The device is always in logged-out mode with PIN cached, so ignore +the logged-in check. + +Since the token is now guaranteed to be logged-in or have sessions +removed, simplify the further checks to match the session state. + +Fixes: 4bd8cda96604 "pkcs11-session: When we notice logout in lower layers..." +--- + src/pkcs11/pkcs11-session.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/src/pkcs11/pkcs11-session.c b/src/pkcs11/pkcs11-session.c +index 7fb9cb36..e9388183 100644 +--- a/src/pkcs11/pkcs11-session.c ++++ b/src/pkcs11/pkcs11-session.c +@@ -252,7 +252,6 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_RV rv; + struct sc_pkcs11_session *session; + struct sc_pkcs11_slot *slot; +- int logged_out; + + if (pInfo == NULL_PTR) + return CKR_ARGUMENTS_BAD; +@@ -276,16 +275,16 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */ + pInfo->ulDeviceError = 0; + + slot = session->slot; +- logged_out = (slot_get_logged_in_state(slot) == SC_PIN_STATE_LOGGED_OUT); +- if (logged_out && slot->login_user >= 0) { ++ if (!sc_pkcs11_conf.atomic && slot->login_user >= 0 && ++ slot_get_logged_in_state(slot) == SC_PIN_STATE_LOGGED_OUT) { + slot->login_user = -1; + sc_pkcs11_close_all_sessions(session->slot->id); + rv = CKR_SESSION_HANDLE_INVALID; + goto out; + } +- if (slot->login_user == CKU_SO && !logged_out) { ++ if (slot->login_user == CKU_SO) { + pInfo->state = CKS_RW_SO_FUNCTIONS; +- } else if ((slot->login_user == CKU_USER && !logged_out) || (!(slot->token_info.flags & CKF_LOGIN_REQUIRED))) { ++ } else if (slot->login_user == CKU_USER || !(slot->token_info.flags & CKF_LOGIN_REQUIRED)) { + pInfo->state = (session->flags & CKF_RW_SESSION) + ? CKS_RW_USER_FUNCTIONS : CKS_RO_USER_FUNCTIONS; + } else { +-- +2.40.1 + + + +From 12ac33d6e0f01a334c792b341b7ea27f10ba0b98 Mon Sep 17 00:00:00 2001 +From: Veronika Hanulikova +Date: Wed, 22 Mar 2023 16:19:07 +0100 +Subject: [PATCH 1/6] Add function for getting current card status in PKCS15 + layer + +By using sc_detect_card_presence() function and observing status flags. +--- + src/pkcs11/framework-pkcs15.c | 29 +++++++++++++++++++++++++++++ + src/pkcs11/sc-pkcs11.h | 1 + + 2 files changed, 30 insertions(+) + +diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c +index 97daefcb47..11ea867023 100644 +--- a/src/pkcs11/framework-pkcs15.c ++++ b/src/pkcs11/framework-pkcs15.c +@@ -1401,6 +1401,35 @@ int slot_get_logged_in_state(struct sc_pkcs11_slot *slot) + return logged_in; + } + ++int slot_get_card_state(struct sc_pkcs11_slot *slot) ++{ ++ struct pkcs15_fw_data *fw_data = NULL; ++ struct sc_pkcs15_card *p15card = NULL; ++ int rv = 0; ++ ++ if (slot->p11card == NULL) { ++ goto out; ++ } ++ ++ fw_data = (struct pkcs15_fw_data *) slot->p11card->fws_data[slot->fw_data_idx]; ++ if (!fw_data) ++ goto out; ++ p15card = fw_data->p15_card; ++ if (!p15card) ++ goto out; ++ ++ if ((rv = sc_detect_card_presence(p15card->card->reader)) <= 0) ++ goto out; ++ if (rv & SC_READER_CARD_CHANGED) ++ return SC_READER_CARD_CHANGED; ++ else if (rv & SC_READER_REMOVED) ++ return SC_READER_REMOVED; ++ else if (rv & SC_READER_CARD_PRESENT) ++ return SC_READER_CARD_PRESENT; ++out: ++ return 0; ++} ++ + + struct sc_pkcs15_object * + _get_auth_object_by_name(struct sc_pkcs15_card *p15card, char *name) +diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h +index bc7baa7e74..4a8dac8de6 100644 +--- a/src/pkcs11/sc-pkcs11.h ++++ b/src/pkcs11/sc-pkcs11.h +@@ -413,6 +413,7 @@ CK_RV slot_token_removed(CK_SLOT_ID id); + CK_RV slot_allocate(struct sc_pkcs11_slot **, struct sc_pkcs11_card *); + CK_RV slot_find_changed(CK_SLOT_ID_PTR idp, int mask); + int slot_get_logged_in_state(struct sc_pkcs11_slot *slot); ++int slot_get_card_state(struct sc_pkcs11_slot *slot); + + /* Login tracking functions */ + CK_RV restore_login_state(struct sc_pkcs11_slot *slot); + +From 2dcb0ee396c5283380a76fa1c4518176e832e6c0 Mon Sep 17 00:00:00 2001 +From: Veronika Hanulikova +Date: Wed, 22 Mar 2023 16:19:25 +0100 +Subject: [PATCH 2/6] Differentiate between changed and logged out card in + C_GetSessionInfo + +Do not delete all sessions, when the card was logged out during operation. +Instead, check whether the card was changed and by logging out only set +correct flag. +--- + src/pkcs11/pkcs11-session.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/src/pkcs11/pkcs11-session.c b/src/pkcs11/pkcs11-session.c +index e938818376..d32e7a5789 100644 +--- a/src/pkcs11/pkcs11-session.c ++++ b/src/pkcs11/pkcs11-session.c +@@ -253,6 +253,7 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_RV rv; + struct sc_pkcs11_session *session; + struct sc_pkcs11_slot *slot; ++ int card_status = 0, logged_out = 0; + + if (pInfo == NULL_PTR) + return CKR_ARGUMENTS_BAD; +@@ -275,16 +276,20 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */ + pInfo->ulDeviceError = 0; + + slot = session->slot; +- if (!sc_pkcs11_conf.atomic && slot->login_user >= 0 && +- slot_get_logged_in_state(slot) == SC_PIN_STATE_LOGGED_OUT) { ++ card_status = slot_get_card_state(slot); ++ if (card_status != SC_READER_CARD_PRESENT) { ++ /* Card was removed or reinserted, invalidate all sessions */ + slot->login_user = -1; + sc_pkcs11_close_all_sessions(session->slot->id); + rv = CKR_SESSION_HANDLE_INVALID; + goto out; + } +- if (slot->login_user == CKU_SO) { ++ ++ /* Check whether the user is logged in the card */ ++ logged_out = (slot_get_logged_in_state(slot) == SC_PIN_STATE_LOGGED_OUT); ++ if (slot->login_user == CKU_SO && !logged_out) { + pInfo->state = CKS_RW_SO_FUNCTIONS; +- } else if (slot->login_user == CKU_USER || !(slot->token_info.flags & CKF_LOGIN_REQUIRED)) { ++ } else if ((slot->login_user == CKU_USER && !logged_out) || !(slot->token_info.flags & CKF_LOGIN_REQUIRED)) { + pInfo->state = (session->flags & CKF_RW_SESSION) + ? CKS_RW_USER_FUNCTIONS : CKS_RO_USER_FUNCTIONS; + } else { + +From c528c27616881e6cc3afef2da50193603a572c00 Mon Sep 17 00:00:00 2001 +From: Veronika Hanulikova +Date: Fri, 14 Apr 2023 14:52:10 +0200 +Subject: [PATCH 3/6] Return all flags when checking the card presence + +--- + src/pkcs11/framework-pkcs15.c | 7 +------ + src/pkcs11/pkcs11-session.c | 2 +- + 2 files changed, 2 insertions(+), 7 deletions(-) + +diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c +index 11ea867023..e35324c805 100644 +--- a/src/pkcs11/framework-pkcs15.c ++++ b/src/pkcs11/framework-pkcs15.c +@@ -1420,12 +1420,7 @@ int slot_get_card_state(struct sc_pkcs11_slot *slot) + + if ((rv = sc_detect_card_presence(p15card->card->reader)) <= 0) + goto out; +- if (rv & SC_READER_CARD_CHANGED) +- return SC_READER_CARD_CHANGED; +- else if (rv & SC_READER_REMOVED) +- return SC_READER_REMOVED; +- else if (rv & SC_READER_CARD_PRESENT) +- return SC_READER_CARD_PRESENT; ++ return rv; + out: + return 0; + } +diff --git a/src/pkcs11/pkcs11-session.c b/src/pkcs11/pkcs11-session.c +index d32e7a5789..01ce7676c9 100644 +--- a/src/pkcs11/pkcs11-session.c ++++ b/src/pkcs11/pkcs11-session.c +@@ -277,7 +277,7 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */ + + slot = session->slot; + card_status = slot_get_card_state(slot); +- if (card_status != SC_READER_CARD_PRESENT) { ++ if (!(card_status & SC_READER_CARD_PRESENT)) { + /* Card was removed or reinserted, invalidate all sessions */ + slot->login_user = -1; + sc_pkcs11_close_all_sessions(session->slot->id); + +From 3d21cba957cc6972a1a672e8a508e1e6b5f5bba1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= +Date: Tue, 9 May 2023 09:52:51 +0200 +Subject: [PATCH 4/6] Remove session when card is changed + +--- + src/pkcs11/pkcs11-session.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/pkcs11/pkcs11-session.c b/src/pkcs11/pkcs11-session.c +index 01ce7676c9..68b6c57b8d 100644 +--- a/src/pkcs11/pkcs11-session.c ++++ b/src/pkcs11/pkcs11-session.c +@@ -277,7 +277,7 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */ + + slot = session->slot; + card_status = slot_get_card_state(slot); +- if (!(card_status & SC_READER_CARD_PRESENT)) { ++ if (!(card_status & SC_READER_CARD_PRESENT) || card_status & SC_READER_CARD_CHANGED) { + /* Card was removed or reinserted, invalidate all sessions */ + slot->login_user = -1; + sc_pkcs11_close_all_sessions(session->slot->id); + +From ecd845c2f7190afc46f39ebbae0dda7b55019994 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= +Date: Tue, 9 May 2023 09:53:20 +0200 +Subject: [PATCH 5/6] Fix PCSC handling when reader is removed + +--- + src/libopensc/reader-pcsc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 04d5ac8fdd..8c2f98c9b1 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -364,7 +364,7 @@ static int refresh_attributes(sc_reader_t *reader) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + +- if (priv->reader_state.szReader == NULL || reader->ctx->flags & SC_READER_REMOVED) { ++ if (priv->reader_state.szReader == NULL || reader->flags & SC_READER_REMOVED) { + priv->reader_state.szReader = reader->name; + priv->reader_state.dwCurrentState = SCARD_STATE_UNAWARE; + priv->reader_state.dwEventState = SCARD_STATE_UNAWARE; +@@ -394,6 +394,8 @@ static int refresh_attributes(sc_reader_t *reader) + #endif + || rv == (LONG)SCARD_E_SERVICE_STOPPED) { + reader->flags &= ~(SC_READER_CARD_PRESENT); ++ reader->flags |= SC_READER_REMOVED; ++ priv->gpriv->removed_reader = reader; + SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS); + } + + +From d04ec3ea3c7cb3b47de28492b4eea5ed1be2cc0c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= +Date: Thu, 18 May 2023 14:18:04 +0200 +Subject: [PATCH 6/6] Remove unnecessary goto statement + +--- + src/pkcs11/framework-pkcs15.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c +index e35324c805..9c7ec67fb4 100644 +--- a/src/pkcs11/framework-pkcs15.c ++++ b/src/pkcs11/framework-pkcs15.c +@@ -1408,21 +1408,19 @@ int slot_get_card_state(struct sc_pkcs11_slot *slot) + int rv = 0; + + if (slot->p11card == NULL) { +- goto out; ++ return 0; + } + + fw_data = (struct pkcs15_fw_data *) slot->p11card->fws_data[slot->fw_data_idx]; + if (!fw_data) +- goto out; ++ return 0; + p15card = fw_data->p15_card; + if (!p15card) +- goto out; ++ return 0; + + if ((rv = sc_detect_card_presence(p15card->card->reader)) <= 0) +- goto out; ++ return 0; + return rv; +-out: +- return 0; + } + + + +From 5e79a2a4abdd523cfff19824718bbb0d8ced7320 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Thu, 9 Apr 2020 16:29:44 +0200 +Subject: [PATCH] fixed compiler warning + +--- + src/tools/opensc-notify.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/tools/opensc-notify.c b/src/tools/opensc-notify.c +index 87d66c67..b1afc62d 100644 +--- a/src/tools/opensc-notify.c ++++ b/src/tools/opensc-notify.c +@@ -189,7 +189,9 @@ static int cancellation_fd[] = {-1, -1}; + + void sig_handler(int sig) { + run_daemon = 0; +- write(cancellation_fd[1], &sig, sizeof sig); ++ if (-1 == write(cancellation_fd[1], &sig, sizeof sig)) { ++ fprintf(stderr, "Failed immediate cancellation: %s", strerror(errno)); ++ } + } + + static void *cancellation_proc(void *arg) +-- +2.40.1 + +From 843779fe6e0f345f483f9ce9c9739913502391eb Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Thu, 23 Apr 2020 08:45:24 +0200 +Subject: [PATCH] opensc-notify: respect signal safety + +Thanks, Marcin. +https://github.com/OpenSC/OpenSC/commit/5e79a2a4abdd523cfff19824718bbb0d8ced7320#r38486829 +--- + src/tools/opensc-notify.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/src/tools/opensc-notify.c b/src/tools/opensc-notify.c +index b1afc62d..75767aba 100644 +--- a/src/tools/opensc-notify.c ++++ b/src/tools/opensc-notify.c +@@ -189,9 +189,7 @@ static int cancellation_fd[] = {-1, -1}; + + void sig_handler(int sig) { + run_daemon = 0; +- if (-1 == write(cancellation_fd[1], &sig, sizeof sig)) { +- fprintf(stderr, "Failed immediate cancellation: %s", strerror(errno)); +- } ++ (void)write(cancellation_fd[1], &sig, sizeof sig); + } + + static void *cancellation_proc(void *arg) +-- +2.40.1 + +From 7936bdef15c71139a6a6159cabaf9e6101565add Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Wed, 29 Apr 2020 01:25:33 +0200 +Subject: [PATCH] resolve unused variable warning on newer gcc + +--- + src/tools/opensc-notify.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/tools/opensc-notify.c b/src/tools/opensc-notify.c +index 75767aba..3b61c498 100644 +--- a/src/tools/opensc-notify.c ++++ b/src/tools/opensc-notify.c +@@ -189,7 +189,10 @@ static int cancellation_fd[] = {-1, -1}; + + void sig_handler(int sig) { + run_daemon = 0; ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-variable" + (void)write(cancellation_fd[1], &sig, sizeof sig); ++#pragma GCC diagnostic pop + } + + static void *cancellation_proc(void *arg) +-- +2.40.1 + +From 1202eceeefd5ffab45648d41ed0a3076cac10920 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Wed, 29 Apr 2020 15:16:31 +0200 +Subject: [PATCH] fixed wrong error + +--- + src/tools/opensc-notify.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/tools/opensc-notify.c b/src/tools/opensc-notify.c +index 3b61c498..c67212b3 100644 +--- a/src/tools/opensc-notify.c ++++ b/src/tools/opensc-notify.c +@@ -190,7 +190,7 @@ static int cancellation_fd[] = {-1, -1}; + void sig_handler(int sig) { + run_daemon = 0; + #pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wunused-variable" ++#pragma GCC diagnostic ignored "-Wunused-result" + (void)write(cancellation_fd[1], &sig, sizeof sig); + #pragma GCC diagnostic pop + } +-- +2.40.1 + + +From 295f399304644e6b0acde267ac410d0aae4a1aee Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 24 Apr 2020 10:18:03 +0200 +Subject: [PATCH] reader-pcsc: Avoid use after free (CID 355473) + +--- + src/libopensc/reader-pcsc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 34dc821bf..b3da6fc88 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -2550,10 +2550,10 @@ int pcsc_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_c + priv->pcsc_card = card_handle; + detect_protocol(reader, card_handle); + detect_reader_features(reader, card_handle); ++ gpriv->attached_reader = reader; + } else { + _sc_delete_reader(ctx, reader); + } +- gpriv->attached_reader = reader; + } + + out: +-- +2.41.0 + +From ca01aa7a8edc8280a5ceadebb472c2e3c198d8c2 Mon Sep 17 00:00:00 2001 +From: Peter Popovec +Date: Thu, 20 Jan 2022 12:26:19 +0100 +Subject: [PATCH] Coverity Scan fix, CID 374840: Null pointer dereferences + (REVERSE_INULL) + + modified: src/pkcs11/slot.c +--- + src/pkcs11/slot.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c +index ea8a3ac2a..86cb3b884 100644 +--- a/src/pkcs11/slot.c ++++ b/src/pkcs11/slot.c +@@ -69,15 +69,17 @@ static struct sc_pkcs11_slot * reader_reclaim_slot(sc_reader_t *reader) + CK_UTF8CHAR slotDescription[64]; + CK_UTF8CHAR manufacturerID[32]; + ++ if (reader == NULL) ++ return NULL; + strcpy_bp(slotDescription, reader->name, 64); + strcpy_bp(manufacturerID, reader->vendor, 32); + + /* Locate a slot related to the reader */ + for (i = 0; ireader == reader) + return slot; +- if (slot->reader == NULL && reader != NULL ++ if (slot->reader == NULL + && 0 == memcmp(slot->slot_info.slotDescription, slotDescription, 64) + && 0 == memcmp(slot->slot_info.manufacturerID, manufacturerID, 32) + && slot->slot_info.hardwareVersion.major == reader->version_major +-- +2.41.0 + diff --git a/SOURCES/opensc-0.23.0-cache-offsets.patch b/SOURCES/opensc-0.23.0-cache-offsets.patch new file mode 100644 index 0000000..752be35 --- /dev/null +++ b/SOURCES/opensc-0.23.0-cache-offsets.patch @@ -0,0 +1,96 @@ +From bff98ff078a99e6864ba1a598fd7dc9af4a9476b Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Thu, 7 Sep 2023 13:23:04 +0200 +Subject: [PATCH] cache: Honor the file offset when writing cache + +When the reads are not consecutive, avoid caching anything after the gaps. + +Signed-off-by: Jakub Jelen +--- + src/libopensc/pkcs15-cache.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/src/libopensc/pkcs15-cache.c b/src/libopensc/pkcs15-cache.c +index 6ebe35a8af..61af35fc5a 100644 +--- a/src/libopensc/pkcs15-cache.c ++++ b/src/libopensc/pkcs15-cache.c +@@ -195,6 +195,7 @@ int sc_pkcs15_cache_file(struct sc_pkcs15_card *p15card, + { + char fname[PATH_MAX]; + int r; ++ long len; + FILE *f; + size_t c; + +@@ -202,22 +203,33 @@ int sc_pkcs15_cache_file(struct sc_pkcs15_card *p15card, + if (r != 0) + return r; + +- f = fopen(fname, "wb"); ++ f = fopen(fname, "ab"); + /* If the open failed because the cache directory does + * not exist, create it and a re-try the fopen() call. + */ + if (f == NULL && errno == ENOENT) { + if ((r = sc_make_cache_dir(p15card->card->ctx)) < 0) + return r; +- f = fopen(fname, "wb"); ++ f = fopen(fname, "ab"); + } + if (f == NULL) + return 0; + ++ /* we opened the file for appending so we should be at the end of file. ++ * The ftell() will give use the length of the file */ ++ len = ftell(f); ++ if (len > path->index) { ++ /* override previous cache records on this location */ ++ fseek(f, path->index, SEEK_SET); ++ } else if (path->index > len) { ++ /* We miss some bytes so we will not cache this chunk */ ++ return 0; ++ } ++ + c = fwrite(buf, 1, bufsize, f); + fclose(f); + if (c != bufsize) { +- sc_log(p15card->card->ctx, ++ sc_log(p15card->card->ctx, + "fwrite() wrote only %"SC_FORMAT_LEN_SIZE_T"u bytes", + c); + unlink(fname); + +From 0875c69295ef28b45fb682b37cede58fc36b7a1a Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 15 Sep 2023 19:17:53 +0200 +Subject: [PATCH] pkcs15-cache: Avoid fd leaks and check return values + +CID 401725 +CID 401726 + +Thanks coverity +--- + src/libopensc/pkcs15-cache.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/libopensc/pkcs15-cache.c b/src/libopensc/pkcs15-cache.c +index 61af35fc5a..bae5797fe2 100644 +--- a/src/libopensc/pkcs15-cache.c ++++ b/src/libopensc/pkcs15-cache.c +@@ -220,9 +220,14 @@ int sc_pkcs15_cache_file(struct sc_pkcs15_card *p15card, + len = ftell(f); + if (len > path->index) { + /* override previous cache records on this location */ +- fseek(f, path->index, SEEK_SET); ++ r = fseek(f, path->index, SEEK_SET); ++ if (r != 0) { ++ fclose(f); ++ return 0; ++ } + } else if (path->index > len) { + /* We miss some bytes so we will not cache this chunk */ ++ fclose(f); + return 0; + } + + diff --git a/SOURCES/opensc-0.23.0-constant-time-pkcs1.patch b/SOURCES/opensc-0.23.0-constant-time-pkcs1.patch new file mode 100644 index 0000000..9c22c34 --- /dev/null +++ b/SOURCES/opensc-0.23.0-constant-time-pkcs1.patch @@ -0,0 +1,417 @@ +diff --git a/src/common/Makefile.am b/src/common/Makefile.am +index 5153428dc..9ecbffe8f 100644 +--- a/src/common/Makefile.am ++++ b/src/common/Makefile.am +@@ -8,7 +8,8 @@ dist_noinst_DATA = \ + 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 + +@@ -43,7 +44,8 @@ TIDY_FILES = \ + 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='' -header-filter=.* $(TIDY_FILES) -- $(TIDY_FLAGS); fi +diff --git a/src/common/constant-time.h b/src/common/constant-time.h +new file mode 100644 +index 000000000..f70251f5d +--- /dev/null ++++ b/src/common/constant-time.h +@@ -0,0 +1,108 @@ ++/* Original source: https://github.com/openssl/openssl/blob/9890cc42daff5e2d0cad01ac4bf78c391f599a6e/include/internal/constant_time.h */ ++ ++#ifndef CONSTANT_TIME_H ++# define CONSTANT_TIME_H ++ ++# include ++# include ++ ++#if !defined(inline) ++# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L ++# define constant_inline inline ++# elif defined(__GNUC__) && __GNUC__>=2 ++# define constant_inline __inline__ ++# 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 ++ ++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); ++} ++ ++#endif /* CONSTANT_TIME_H */ +diff --git a/src/libopensc/internal.h b/src/libopensc/internal.h +index 74014235a..13eccfa1a 100644 +--- a/src/libopensc/internal.h ++++ b/src/libopensc/internal.h +@@ -168,6 +168,8 @@ int sc_pkcs1_strip_01_padding(struct sc_context *ctx, const u8 *in_dat, size_t i + 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); + +diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c +index 283746699..ceb2a1e21 100644 +--- a/src/libopensc/padding.c ++++ b/src/libopensc/padding.c +@@ -33,9 +33,12 @@ + #include + + #include "internal.h" ++#include "common/constant-time.h" + + /* TODO doxygen comments */ + ++#define SC_PKCS1_PADDING_MIN_SIZE 11 ++ + /* + * Prefixes for pkcs-v1 signatures + */ +@@ -184,6 +187,84 @@ sc_pkcs1_strip_02_padding(sc_context_t *ctx, const u8 *data, size_t len, u8 *out + LOG_FUNC_RETURN(ctx, len - n); + } + ++/* Original source: https://github.com/openssl/openssl/blob/9890cc42daff5e2d0cad01ac4bf78c391f599a6e/crypto/rsa/rsa_pk1.c#L171 */ ++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) ++{ ++ unsigned int i = 0; ++ u8 *msg = NULL; ++ unsigned int good, found_zero_byte, mask; ++ unsigned int zero_index = 0, msg_index, mlen = -1, len = 0; ++ LOG_FUNC_CALLED(ctx); ++ ++ if (data == NULL || data_len <= 0 || data_len > n || n < SC_PKCS1_PADDING_MIN_SIZE) ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); ++ ++ msg = 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; ++ } ++ ++ // 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 there is a message after padding ++ good &= constant_time_ge(mlen, 1); ++ // check that message fits into out buffer ++ good &= constant_time_ge(*out_len, mlen); ++ ++ // move the result in-place by |num|-SC_PKCS1_PADDING_MIN_SIZE-|mlen| bytes to the left. ++ *out_len = constant_time_select(constant_time_lt(n - SC_PKCS1_PADDING_MIN_SIZE, *out_len), ++ n - SC_PKCS1_PADDING_MIN_SIZE, *out_len); ++ 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 < *out_len; 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]); ++ } ++ ++ free(msg); ++ return constant_time_select(good, mlen, SC_ERROR_WRONG_PADDING); ++} ++ + /* add/remove DigestInfo prefix */ + static int sc_pkcs1_add_digest_info_prefix(unsigned int algorithm, + const u8 *in, size_t in_len, u8 *out, size_t *out_len) +diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c +index 7c3a39432..b5e492fe2 100644 +--- a/src/libopensc/pkcs15-sec.c ++++ b/src/libopensc/pkcs15-sec.c +@@ -308,12 +308,13 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card, + + /* 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 = 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 */ + } + +- LOG_FUNC_RETURN(ctx, r); ++ return r; + } + + /* derive one key from another. RSA can use decipher, so this is for only ECDH +diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c +index 809cd72d9..9c75759a0 100644 +--- a/src/pkcs11/framework-pkcs15.c ++++ b/src/pkcs11/framework-pkcs15.c +@@ -28,6 +28,7 @@ + #include "libopensc/cardctl.h" + #include "ui/notify.h" + #include "common/compat_strnlen.h" ++#include "common/constant-time.h" + #ifdef ENABLE_OPENSSL + #include + #else +@@ -4603,15 +4604,51 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *session, void *obj, + rv = sc_pkcs15_decipher(fw_data->p15_card, prkey->prv_p15obj, flags, + pEncryptedData, ulEncryptedDataLen, decrypted, sizeof(decrypted)); + +- if (rv < 0 && !sc_pkcs11_conf.lock_login && !prkey_has_path) ++ if (!((flags & SC_ALGORITHM_RSA_PAD_PKCS1) && constant_time_eq_s(rv, SC_ERROR_WRONG_PADDING)) && ++ 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)); + + sc_unlock(p11card->card); + +- sc_log(context, "Decryption complete. Result %d.", rv); ++ /* Handle buffer after PKCS#1 v1.5 depadding constant-time */ ++ if (flags & SC_ALGORITHM_RSA_PAD_PKCS1) { ++ CK_ULONG mask, good, rv_pkcs11; ++ ++ sc_log(context, "Decryption complete."); ++ /* only padding error must be handled in constant-time way */ ++ if ((~constant_time_eq_s(rv, SC_ERROR_WRONG_PADDING) & constant_time_lt_s(sizeof(decrypted), rv))) ++ return sc_to_cryptoki_error(rv, "C_Decrypt"); ++ ++ /* check rv for error */ ++ good = ~constant_time_eq_s(rv, SC_ERROR_WRONG_PADDING); ++ rv_pkcs11 = constant_time_select_s(good, CKR_OK, SC_ERROR_WRONG_PADDING); ++ if (pData == NULL_PTR) { ++ /* set length only if rv good */ ++ *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 accordingly */ ++ 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, 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); ++ return rv_pkcs11; ++ } ++ ++ sc_log(context, "Decryption complete. Result %d.", rv); + if (rv < 0) + return sc_to_cryptoki_error(rv, "C_Decrypt"); + +@@ -4622,7 +4659,6 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *session, void *obj, + if (buff_too_small) + return CKR_BUFFER_TOO_SMALL; + memcpy(pData, decrypted, *pulDataLen); +- + return CKR_OK; + } + +diff --git a/src/pkcs11/misc.c b/src/pkcs11/misc.c +index 5ca1176b1..2893b2bf3 100644 +--- a/src/pkcs11/misc.c ++++ b/src/pkcs11/misc.c +@@ -24,6 +24,7 @@ + #include + + #include "sc-pkcs11.h" ++#include "common/constant-time.h" + + #define DUMP_TEMPLATE_MAX 32 + +@@ -174,7 +175,7 @@ CK_RV reset_login_state(struct sc_pkcs11_slot *slot, CK_RV rv) + 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 --git a/src/pkcs11/pkcs11-object.c b/src/pkcs11/pkcs11-object.c +index f04c0b4c5..93cc319c2 100644 +--- a/src/pkcs11/pkcs11-object.c ++++ b/src/pkcs11/pkcs11-object.c +@@ -1034,7 +1034,7 @@ C_Decrypt(CK_SESSION_HANDLE hSession, /* the session's handle */ + rv = reset_login_state(session->slot, rv); + } + +- sc_log(context, "C_Decrypt() = %s", lookup_enum ( RV_T, rv )); ++ sc_log(context, "C_Decrypt()"); + sc_pkcs11_unlock(); + return rv; + } + +diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c +index ceb2a1e21..c2cc58d47 100644 +--- a/src/libopensc/padding.c ++++ b/src/libopensc/padding.c +@@ -192,7 +192,7 @@ 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) + { + unsigned int i = 0; +- u8 *msg = NULL; ++ u8 *msg, *msg_orig = NULL; + unsigned int good, found_zero_byte, mask; + unsigned int zero_index = 0, msg_index, mlen = -1, len = 0; + LOG_FUNC_CALLED(ctx); +@@ -200,7 +200,7 @@ sc_pkcs1_strip_02_padding_constant_time(sc_context_t *ctx, unsigned int n, const + if (data == NULL || data_len <= 0 || data_len > n || n < SC_PKCS1_PADDING_MIN_SIZE) + LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); + +- msg = calloc(n, sizeof(u8)); ++ msg = msg_orig = calloc(n, sizeof(u8)); + if (msg == NULL) + LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); + +@@ -261,7 +261,7 @@ sc_pkcs1_strip_02_padding_constant_time(sc_context_t *ctx, unsigned int n, const + out[i] = constant_time_select_8(mask, msg[msg_index], out[i]); + } + +- free(msg); ++ free(msg_orig); + return constant_time_select(good, mlen, SC_ERROR_WRONG_PADDING); + } + +-- +2.43.0 diff --git a/SOURCES/opensc-0.23.0-pin-bypass.patch b/SOURCES/opensc-0.23.0-pin-bypass.patch new file mode 100644 index 0000000..de871d4 --- /dev/null +++ b/SOURCES/opensc-0.23.0-pin-bypass.patch @@ -0,0 +1,107 @@ +From 868f76fb31255fd3fdacfc3e476452efeb61c3e7 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Wed, 21 Jun 2023 12:27:23 +0200 +Subject: [PATCH] Fixed PIN authentication bypass + +If two processes are accessing a token, then one process may leave the +card usable with an authenticated PIN so that a key may sign/decrypt any +data. This is especially the case if the token does not support a way of +resetting the authentication status (logout). + +We have some tracking of the authentication status in software via +PKCS#11, Minidriver (os-wise) and CryptoTokenKit, which is why a +PIN-prompt will appear even though the card may technically be unlocked +as described in the above example. However, before this change, an empty +PIN was not verified (likely yielding an error during PIN-verification), +but it was just checked whether the PIN is authenticated. This defeats +the purpose of the PIN verification, because an empty PIN is not the +correct one. Especially during OS Logon, we don't want that kind of +shortcut, but we want the user to verify the correct PIN (even though +the token was left unattended and authentication at the computer). + +This essentially reverts commit e6f7373ef066cfab6e3162e8b5f692683db23864. +--- + src/libopensc/pkcs15-pin.c | 13 ------------- + 1 file changed, 13 deletions(-) + +diff --git a/src/libopensc/pkcs15-pin.c b/src/libopensc/pkcs15-pin.c +index 80a185fecd..393234efe4 100644 +--- a/src/libopensc/pkcs15-pin.c ++++ b/src/libopensc/pkcs15-pin.c +@@ -307,19 +307,6 @@ sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *pi + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_PIN_REFERENCE); + auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data; + +- /* +- * if pin cache is disabled, we can get here with no PIN data. +- * in this case, to avoid error or unnecessary pin prompting on pinpad, +- * check if the PIN has been already verified and the access condition +- * is still open on card. +- */ +- if (pinlen == 0) { +- r = sc_pkcs15_get_pin_info(p15card, pin_obj); +- +- if (r == SC_SUCCESS && auth_info->logged_in == SC_PIN_STATE_LOGGED_IN) +- LOG_FUNC_RETURN(ctx, r); +- } +- + r = _validate_pin(p15card, auth_info, pinlen); + + if (r) + +From 80cc5d30635f0d2c92b5099c0f9dc680d0ffce2f Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 24 Oct 2023 11:13:08 +0200 +Subject: [PATCH] pkcs15init: Check login status before asking for a pin + +The original code block from e6f7373 is still needed when pkcs15init +layer checks ACLs for PKCS#15 objects, but it should be kept out of +the libopensc, which is used for more authentication code paths +and can be used for PIN bypass. +--- + src/libopensc/pkcs15-pin.c | 1 + + src/pkcs15init/pkcs15-lib.c | 16 ++++++++++++++++ + 2 files changed, 17 insertions(+) + +diff --git a/src/libopensc/pkcs15-pin.c b/src/libopensc/pkcs15-pin.c +index 393234efe..b26e57236 100644 +--- a/src/libopensc/pkcs15-pin.c ++++ b/src/libopensc/pkcs15-pin.c +@@ -307,6 +307,7 @@ sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *pi + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_PIN_REFERENCE); + auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data; + ++ /* Check the provided pin matches pin requirements */ + r = _validate_pin(p15card, auth_info, pinlen); + + if (r) +diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c +index 9148b83b5..cca11d1f1 100644 +--- a/src/pkcs15init/pkcs15-lib.c ++++ b/src/pkcs15init/pkcs15-lib.c +@@ -3958,6 +3958,22 @@ sc_pkcs15init_verify_secret(struct sc_profile *profile, struct sc_pkcs15_card *p + + found: + if (pin_obj) { ++ /* ++ * If pin cache is disabled or the reader is using pinpad, we can get here ++ * with no PIN data. This is ok as we can not asynchronously invoke the prompt ++ * (unless the pinpad is in use). ++ * In this case, check if the PIN has been already verified and ++ * the access condition is still open on card. ++ */ ++ if (pinsize == 0) { ++ r = sc_pkcs15_get_pin_info(p15card, pin_obj); ++ /* update local copy of auth info */ ++ memcpy(&auth_info, pin_obj->data, sizeof(auth_info)); ++ ++ if (r == SC_SUCCESS && auth_info.logged_in == SC_PIN_STATE_LOGGED_IN) ++ LOG_FUNC_RETURN(ctx, r); ++ } ++ + r = sc_pkcs15_verify_pin(p15card, pin_obj, use_pinpad || pinsize == 0 ? NULL : pinbuf, use_pinpad ? 0 : pinsize); + LOG_TEST_RET(ctx, r, "Cannot validate pkcs15 PIN"); + } +-- +2.43.0 + diff --git a/SOURCES/opensc-0.23.0-pkcs15init.patch b/SOURCES/opensc-0.23.0-pkcs15init.patch new file mode 100644 index 0000000..b715d04 --- /dev/null +++ b/SOURCES/opensc-0.23.0-pkcs15init.patch @@ -0,0 +1,855 @@ +From 245efe608d083fd4e4ec96793fdefd218e26fde7 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Thu, 17 Aug 2023 13:54:42 +0200 +Subject: [PATCH] pkcs15: Avoid buffer overflow when getting last update + +Thanks oss-fuzz + +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60769 +--- + src/libopensc/pkcs15.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c +index eb7fc6afc..4215b733a 100644 +--- a/src/libopensc/pkcs15.c ++++ b/src/libopensc/pkcs15.c +@@ -532,7 +532,7 @@ sc_pkcs15_get_lastupdate(struct sc_pkcs15_card *p15card) + struct sc_context *ctx = p15card->card->ctx; + struct sc_file *file = NULL; + struct sc_asn1_entry asn1_last_update[C_ASN1_LAST_UPDATE_SIZE]; +- unsigned char *content, last_update[32]; ++ unsigned char *content, last_update[32] = {0}; + size_t lupdate_len = sizeof(last_update) - 1; + int r, content_len; + size_t size; +@@ -569,9 +569,11 @@ sc_pkcs15_get_lastupdate(struct sc_pkcs15_card *p15card) + if (r < 0) + return NULL; + +- p15card->tokeninfo->last_update.gtime = strdup((char *)last_update); +- if (!p15card->tokeninfo->last_update.gtime) +- return NULL; ++ if (asn1_last_update[0].flags & SC_ASN1_PRESENT) { ++ p15card->tokeninfo->last_update.gtime = strdup((char *)last_update); ++ if (!p15card->tokeninfo->last_update.gtime) ++ return NULL; ++ } + done: + sc_log(ctx, "lastUpdate.gtime '%s'", p15card->tokeninfo->last_update.gtime); + return p15card->tokeninfo->last_update.gtime; +2.41.0 + +From 440ca666eff10cc7011901252d20f3fc4ea23651 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Thu, 17 Aug 2023 13:41:36 +0200 +Subject: [PATCH] setcos: Avoid buffer underflow + +Thanks oss-fuzz + +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60672 +--- + src/pkcs15init/pkcs15-setcos.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/pkcs15init/pkcs15-setcos.c b/src/pkcs15init/pkcs15-setcos.c +index 1b56afe6d..1907b47f9 100644 +--- a/src/pkcs15init/pkcs15-setcos.c ++++ b/src/pkcs15init/pkcs15-setcos.c +@@ -349,6 +349,10 @@ setcos_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, + + /* Replace the path of instantiated key template by the path from the object data. */ + memcpy(&file->path, &key_info->path, sizeof(file->path)); ++ if (file->path.len < 2) { ++ sc_file_free(file); ++ LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Invalid path"); ++ } + file->id = file->path.value[file->path.len - 2] * 0x100 + + file->path.value[file->path.len - 1]; + +-- +2.41.0 + +From 41d61da8481582e12710b5858f8b635e0a71ab5e Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Wed, 20 Sep 2023 10:13:57 +0200 +Subject: [PATCH] oberthur: Avoid buffer overflow + +Thanks oss-fuzz + +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60650 +--- + src/pkcs15init/pkcs15-oberthur.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/pkcs15init/pkcs15-oberthur.c b/src/pkcs15init/pkcs15-oberthur.c +index ad2cabd53..c441ab1e7 100644 +--- a/src/pkcs15init/pkcs15-oberthur.c ++++ b/src/pkcs15init/pkcs15-oberthur.c +@@ -715,6 +715,9 @@ cosm_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, + if (object->type != SC_PKCS15_TYPE_PRKEY_RSA) + LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Create key failed: RSA only supported"); + ++ if (key_info->path.len < 2) ++ LOG_TEST_RET(ctx, SC_ERROR_OBJECT_NOT_VALID, "The path needs to be at least to bytes long"); ++ + sc_log(ctx, "create private key ID:%s", sc_pkcs15_print_id(&key_info->id)); + /* Here, the path of private key file should be defined. + * Nevertheless, we need to instantiate private key to get the ACLs. */ +-- +2.41.0 + + +From 88880db0307a07e33cf2e1592bb029e9c170dfea Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= +Date: Wed, 21 Jun 2023 15:48:27 +0200 +Subject: [PATCH] pkcs15-pubkey: free DER value when parsing public key fails + +The der value might be allocated in asn1_decode_entry() +but it is not released when errror occurs. + +Thanks OSS-Fuzz +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=59615 +--- + src/libopensc/pkcs15-pubkey.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c +index 4a0ddffbe..7107c47cb 100644 +--- a/src/libopensc/pkcs15-pubkey.c ++++ b/src/libopensc/pkcs15-pubkey.c +@@ -351,6 +351,8 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card, + err: + if (r < 0) { + sc_pkcs15_free_pubkey_info(info); ++ if (der->len) ++ free(der->value); + } + + LOG_FUNC_RETURN(ctx, r); +-- +2.41.0 + +From 638a5007a5d240d6fa901aa822cfeef94fe36e85 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= +Date: Thu, 10 Aug 2023 12:20:33 +0200 +Subject: [PATCH] pkcs15-pubkey.c: Avoid double-free + +Thanks OSS-Fuzz +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60616 +--- + src/libopensc/pkcs15-pubkey.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c +index 7107c47cb..49b514968 100644 +--- a/src/libopensc/pkcs15-pubkey.c ++++ b/src/libopensc/pkcs15-pubkey.c +@@ -351,8 +351,12 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card, + err: + if (r < 0) { + sc_pkcs15_free_pubkey_info(info); +- if (der->len) ++ if (der->len) { + free(der->value); ++ /* der points to obj->content */ ++ obj->content.value = NULL; ++ obj->content.len = 0; ++ } + } + + LOG_FUNC_RETURN(ctx, r); +-- +2.41.0 +From c449a181a6988cc1e8dc8764d23574e48cdc3fa6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= +Date: Mon, 19 Jun 2023 16:14:51 +0200 +Subject: [PATCH] pkcs15-cflex: check path length to prevent underflow + +Thanks OSS-Fuzz +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=58932 +--- + src/pkcs15init/pkcs15-cflex.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/pkcs15init/pkcs15-cflex.c b/src/pkcs15init/pkcs15-cflex.c +index d06568073..ce1d48e62 100644 +--- a/src/pkcs15init/pkcs15-cflex.c ++++ b/src/pkcs15init/pkcs15-cflex.c +@@ -56,6 +56,9 @@ cflex_delete_file(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *d + int r = 0; + /* Select the parent DF */ + path = df->path; ++ if (path.len < 2) { ++ return SC_ERROR_INVALID_ARGUMENTS; ++ } + path.len -= 2; + r = sc_select_file(p15card->card, &path, &parent); + if (r < 0) +-- +2.41.0 + +From 5631e9843c832a99769def85b7b9b68b4e3e3959 Mon Sep 17 00:00:00 2001 +From: Veronika Hanulikova +Date: Fri, 3 Mar 2023 16:07:38 +0100 +Subject: [PATCH] Check length of string before making copy + +Thanks OSS-Fuzz +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=55851 +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=55998 +--- + src/pkcs15init/profile.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/pkcs15init/profile.c b/src/pkcs15init/profile.c +index 2b793b028..3bad1e853 100644 +--- a/src/pkcs15init/profile.c ++++ b/src/pkcs15init/profile.c +@@ -1575,7 +1575,10 @@ do_acl(struct state *cur, int argc, char **argv) + while (argc--) { + unsigned int op, method, id; + ++ if (strlen(*argv) >= sizeof(oper)) ++ goto bad; + strlcpy(oper, *argv++, sizeof(oper)); ++ + if ((what = strchr(oper, '=')) == NULL) + goto bad; + *what++ = '\0'; +@@ -2288,6 +2291,9 @@ get_authid(struct state *cur, const char *value, + return get_uint(cur, value, type); + } + ++ if (strlen(value) >= sizeof(temp)) ++ return 1; ++ + n = strcspn(value, "0123456789x"); + strlcpy(temp, value, (sizeof(temp) > n) ? n + 1 : sizeof(temp)); + +-- +2.41.0 + +From e7f81d86dcdc751f4737f4b29a99bfc54d29c5c9 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Thu, 8 Dec 2022 00:45:31 +0100 +Subject: [PATCH] muscle: prevent out of bounds write + +fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=53631 +--- + src/libopensc/muscle.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/libopensc/muscle.c b/src/libopensc/muscle.c +index 7af279a0a..61a4ec24d 100644 +--- a/src/libopensc/muscle.c ++++ b/src/libopensc/muscle.c +@@ -127,7 +127,7 @@ int msc_zero_object(sc_card_t *card, msc_id objectId, size_t dataLength) + { + u8 zeroBuffer[MSC_MAX_APDU]; + size_t i; +- size_t max_write_unit = MSC_MAX_SEND - 9; /* - 9 for object ID+length */ ++ size_t max_write_unit = MIN(MSC_MAX_APDU, MSC_MAX_SEND - 9); /* - 9 for object ID+length */ + + memset(zeroBuffer, 0, max_write_unit); + for(i = 0; i < dataLength; i += max_write_unit) { +-- +2.41.0 + +From df5a176bfdf8c52ba89c7fef1f82f6f3b9312bc1 Mon Sep 17 00:00:00 2001 +From: Veronika Hanulikova +Date: Fri, 10 Feb 2023 11:47:34 +0100 +Subject: [PATCH] Check array bounds + +Thanks OSS-Fuzz +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=54312 +--- + src/libopensc/muscle.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/libopensc/muscle.c b/src/libopensc/muscle.c +index 61a4ec24d..9d01e0c11 100644 +--- a/src/libopensc/muscle.c ++++ b/src/libopensc/muscle.c +@@ -181,6 +181,9 @@ int msc_partial_update_object(sc_card_t *card, msc_id objectId, int offset, cons + sc_apdu_t apdu; + int r; + ++ if (dataLength + 9 > MSC_MAX_APDU) ++ return SC_ERROR_INVALID_ARGUMENTS; ++ + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x54, 0x00, 0x00); + apdu.lc = dataLength + 9; + if (card->ctx->debug >= 2) +-- +2.41.0 + +From 578aed8391ef117ca64a9e0cba8e5c264368a0ec Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Thu, 8 Dec 2022 00:27:18 +0100 +Subject: [PATCH] sc_pkcs15init_rmdir: prevent out of bounds write + +fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=53927 +--- + src/pkcs15init/pkcs15-lib.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c +index 91cee3731..3df03c6e1 100644 +--- a/src/pkcs15init/pkcs15-lib.c ++++ b/src/pkcs15init/pkcs15-lib.c +@@ -685,6 +685,8 @@ sc_pkcs15init_rmdir(struct sc_pkcs15_card *p15card, struct sc_profile *profile, + + path = df->path; + path.len += 2; ++ if (path.len > SC_MAX_PATH_SIZE) ++ return SC_ERROR_INTERNAL; + + nfids = r / 2; + while (r >= 0 && nfids--) { +-- +2.41.0 + +From 4013a807492568bf9907cfb3df41f130ac83c7b9 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Wed, 15 Nov 2023 10:53:46 +0100 +Subject: [PATCH] setcos: Avoid writing behind the path buffer end + +The path->value buffer is fixed to 16 bytes so it is not always possible +to append 2 more bytes. Doing so overruns the buffer, writing into the +ACL block, crashing during the cleanup. + +Thanks oss-fuzz + +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=64181 +--- + src/pkcs15init/pkcs15-setcos.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/pkcs15init/pkcs15-setcos.c b/src/pkcs15init/pkcs15-setcos.c +index 70a28048b..1eeeda064 100644 +--- a/src/pkcs15init/pkcs15-setcos.c ++++ b/src/pkcs15init/pkcs15-setcos.c +@@ -287,6 +287,10 @@ setcos_new_file(sc_profile_t *profile, sc_card_t *card, + file->id += num; + p = &file->path; + *p = profile->df_info->file->path; ++ if (p->len + 2 > SC_MAX_PATH_SIZE) { ++ sc_file_free(file); ++ return SC_ERROR_INVALID_DATA; ++ } + p->value[p->len++] = (u8) (file->id / 256); + p->value[p->len++] = (u8) (file->id % 256); + +-- +2.42.0 + +From 8fc2c20c3f895569eeb58328bb882aec07325d3b Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 7 Nov 2023 17:48:27 +0100 +Subject: [PATCH] iasecc: Avoid another buffer overflow + +thanks oss-fuzz + +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=63949 +--- + src/libopensc/iasecc-sdo.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/src/libopensc/iasecc-sdo.c b/src/libopensc/iasecc-sdo.c +index a41c3c2d3..86032f5a8 100644 +--- a/src/libopensc/iasecc-sdo.c ++++ b/src/libopensc/iasecc-sdo.c +@@ -44,7 +44,8 @@ iasecc_parse_acls(struct sc_card *card, struct iasecc_sdo_docp *docp, int flags) + { + struct sc_context *ctx = card->ctx; + struct iasecc_extended_tlv *acls = &docp->acls_contact; +- int ii, offs; ++ int ii; ++ size_t offs; + unsigned char mask = 0x40; + + if (flags) +@@ -56,8 +57,12 @@ iasecc_parse_acls(struct sc_card *card, struct iasecc_sdo_docp *docp, int flags) + docp->amb = *(acls->value + 0); + memset(docp->scbs, 0xFF, sizeof(docp->scbs)); + for (ii=0, offs = 1; ii<7; ii++, mask >>= 1) +- if (mask & docp->amb) ++ if (mask & docp->amb) { ++ if (offs >= acls->size) { ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); ++ } + docp->scbs[ii] = *(acls->value + offs++); ++ } + + sc_log(ctx, "iasecc_parse_docp() SCBs %02X:%02X:%02X:%02X:%02X:%02X:%02X", + docp->scbs[0],docp->scbs[1],docp->scbs[2],docp->scbs[3], +-- +2.42.0 + +From 83b9129bd3cfc6ac57d5554e015c3df85f5076dc Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Wed, 11 Oct 2023 08:57:45 +0200 +Subject: [PATCH] iassecc: Verify buffer lengths before use + +Thanks oss-fuzz + +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=63163 +--- + src/libopensc/iasecc-sdo.c | 55 +++++++++++++++++++++----------------- + 1 file changed, 31 insertions(+), 24 deletions(-) + +diff --git a/src/libopensc/iasecc-sdo.c b/src/libopensc/iasecc-sdo.c +index 3eeb03b91..a6e6c2677 100644 +--- a/src/libopensc/iasecc-sdo.c ++++ b/src/libopensc/iasecc-sdo.c +@@ -36,7 +36,7 @@ + #include "iasecc.h" + #include "iasecc-sdo.h" + +-static int iasecc_parse_size(unsigned char *data, size_t *out); ++static int iasecc_parse_size(unsigned char *data, size_t data_len, size_t *out); + + + static int +@@ -330,7 +330,7 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru + LOG_FUNC_CALLED(ctx); + + if (*data == IASECC_SDO_TEMPLATE_TAG) { +- size_size = iasecc_parse_size(data + 1, &size); ++ size_size = iasecc_parse_size(data + 1, data_len - 1, &size); + LOG_TEST_RET(ctx, size_size, "parse error: invalid size data of IASECC_SDO_TEMPLATE"); + + data += size_size + 1; +@@ -345,7 +345,7 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru + if ((*(data + 1) & 0x7F) != IASECC_SDO_CLASS_SE) + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); + +- size_size = iasecc_parse_size(data + 3, &size); ++ size_size = iasecc_parse_size(data + 3, data_len - 3, &size); + LOG_TEST_RET(ctx, size_size, "parse error: invalid SDO SE data size"); + + if (data_len != size + size_size + 3) +@@ -365,7 +365,7 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru + LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); + } + +- size_size = iasecc_parse_size(data + 1, &size); ++ size_size = iasecc_parse_size(data + 1, data_len - 1, &size); + LOG_TEST_RET(ctx, size_size, "parse error: invalid size data"); + + if (data_len != size + size_size + 1) +@@ -387,17 +387,17 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru + + + static int +-iasecc_parse_size(unsigned char *data, size_t *out) ++iasecc_parse_size(unsigned char *data, size_t data_len, size_t *out) + { +- if (*data < 0x80) { ++ if (*data < 0x80 && data_len > 0) { + *out = *data; + return 1; + } +- else if (*data == 0x81) { ++ else if (*data == 0x81 && data_len > 1) { + *out = *(data + 1); + return 2; + } +- else if (*data == 0x82) { ++ else if (*data == 0x82 && data_len > 2) { + *out = *(data + 1) * 0x100 + *(data + 2); + return 3; + } +@@ -407,14 +407,18 @@ iasecc_parse_size(unsigned char *data, size_t *out) + + + static int +-iasecc_parse_get_tlv(struct sc_card *card, unsigned char *data, struct iasecc_extended_tlv *tlv) ++iasecc_parse_get_tlv(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_extended_tlv *tlv) + { + struct sc_context *ctx = card->ctx; + size_t size_len, tag_len; + + memset(tlv, 0, sizeof(*tlv)); + sc_log(ctx, "iasecc_parse_get_tlv() called for tag 0x%X", *data); ++ if (data_len < 1) ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); + if ((*data == 0x7F) || (*data == 0x5F)) { ++ if (data_len < 2) ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); + tlv->tag = *data * 0x100 + *(data + 1); + tag_len = 2; + } +@@ -424,8 +428,11 @@ iasecc_parse_get_tlv(struct sc_card *card, unsigned char *data, struct iasecc_ex + } + + sc_log(ctx, "iasecc_parse_get_tlv() tlv->tag 0x%X", tlv->tag); +- size_len = iasecc_parse_size(data + tag_len, &tlv->size); ++ size_len = iasecc_parse_size(data + tag_len, data_len - tag_len, &tlv->size); + LOG_TEST_RET(ctx, size_len, "parse error: invalid size data"); ++ if (tag_len + size_len + tlv->size > data_len) { ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); ++ } + + tlv->value = calloc(1, tlv->size); + if (!tlv->value) +@@ -452,7 +459,7 @@ iasecc_parse_chv(struct sc_card *card, unsigned char *data, size_t data_len, str + while(offs < data_len) { + struct iasecc_extended_tlv tlv; + +- rv = iasecc_parse_get_tlv(card, data + offs, &tlv); ++ rv = iasecc_parse_get_tlv(card, data + offs, data_len - offs, &tlv); + LOG_TEST_RET(ctx, rv, "iasecc_parse_chv() get and parse TLV error"); + + sc_log(ctx, +@@ -486,7 +493,7 @@ iasecc_parse_prvkey(struct sc_card *card, unsigned char *data, size_t data_len, + while(offs < data_len) { + struct iasecc_extended_tlv tlv; + +- rv = iasecc_parse_get_tlv(card, data + offs, &tlv); ++ rv = iasecc_parse_get_tlv(card, data + offs, data_len - offs, &tlv); + LOG_TEST_RET(ctx, rv, "iasecc_parse_prvkey() get and parse TLV error"); + + sc_log(ctx, +@@ -516,7 +523,7 @@ iasecc_parse_pubkey(struct sc_card *card, unsigned char *data, size_t data_len, + while(offs < data_len) { + struct iasecc_extended_tlv tlv; + +- rv = iasecc_parse_get_tlv(card, data + offs, &tlv); ++ rv = iasecc_parse_get_tlv(card, data + offs, data_len - offs, &tlv); + LOG_TEST_RET(ctx, rv, "iasecc_parse_pubkey() get and parse TLV error"); + + sc_log(ctx, +@@ -554,7 +561,7 @@ iasecc_parse_keyset(struct sc_card *card, unsigned char *data, size_t data_len, + while(offs < data_len) { + struct iasecc_extended_tlv tlv; + +- rv = iasecc_parse_get_tlv(card, data + offs, &tlv); ++ rv = iasecc_parse_get_tlv(card, data + offs, data_len - offs, &tlv); + LOG_TEST_RET(ctx, rv, "iasecc_parse_keyset() get and parse TLV error"); + + sc_log(ctx, +@@ -586,7 +593,7 @@ iasecc_parse_docp(struct sc_card *card, unsigned char *data, size_t data_len, st + while(offs < data_len) { + struct iasecc_extended_tlv tlv; + +- rv = iasecc_parse_get_tlv(card, data + offs, &tlv); ++ rv = iasecc_parse_get_tlv(card, data + offs, data_len - offs, &tlv); + LOG_TEST_RET(ctx, rv, "iasecc_parse_get_tlv() get and parse TLV error"); + + sc_log(ctx, +@@ -641,7 +648,7 @@ iasecc_parse_docp(struct sc_card *card, unsigned char *data, size_t data_len, st + + + static int +-iasecc_sdo_parse_data(struct sc_card *card, unsigned char *data, struct iasecc_sdo *sdo) ++iasecc_sdo_parse_data(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_sdo *sdo) + { + struct sc_context *ctx = card->ctx; + struct iasecc_extended_tlv tlv; +@@ -650,7 +657,7 @@ iasecc_sdo_parse_data(struct sc_card *card, unsigned char *data, struct iasecc_s + LOG_FUNC_CALLED(ctx); + sc_log(ctx, "iasecc_sdo_parse_data() class %X; ref %X", sdo->sdo_class, sdo->sdo_ref); + +- tlv_size = iasecc_parse_get_tlv(card, data, &tlv); ++ tlv_size = iasecc_parse_get_tlv(card, data, data_len, &tlv); + LOG_TEST_RET(ctx, tlv_size, "parse error: get TLV"); + + sc_log(ctx, "iasecc_sdo_parse_data() tlv.tag 0x%X", tlv.tag); +@@ -735,7 +742,7 @@ iasecc_sdo_parse(struct sc_card *card, unsigned char *data, size_t data_len, str + LOG_FUNC_CALLED(ctx); + + if (*data == IASECC_SDO_TEMPLATE_TAG) { +- size_size = iasecc_parse_size(data + 1, &size); ++ size_size = iasecc_parse_size(data + 1, data_len - 1, &size); + LOG_TEST_RET(ctx, size_size, "parse error: invalid size data of IASECC_SDO_TEMPLATE"); + + data += size_size + 1; +@@ -754,7 +761,7 @@ iasecc_sdo_parse(struct sc_card *card, unsigned char *data, size_t data_len, str + if (sdo->sdo_ref != (*(data + 2) & 0x3F)) + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); + +- size_size = iasecc_parse_size(data + 3, &size); ++ size_size = iasecc_parse_size(data + 3, data_len - 3, &size); + LOG_TEST_RET(ctx, size_size, "parse error: invalid size data"); + + if (data_len != size + size_size + 3) +@@ -766,7 +773,7 @@ iasecc_sdo_parse(struct sc_card *card, unsigned char *data, size_t data_len, str + + offs = 3 + size_size; + for (; offs < data_len;) { +- rv = iasecc_sdo_parse_data(card, data + offs, sdo); ++ rv = iasecc_sdo_parse_data(card, data + offs, data_len - offs, sdo); + LOG_TEST_RET(ctx, rv, "parse error: invalid SDO data"); + + offs += rv; +@@ -812,7 +819,7 @@ iasecc_sdo_allocate_and_parse(struct sc_card *card, unsigned char *data, size_t + if (data_len == 3) + LOG_FUNC_RETURN(ctx, SC_SUCCESS); + +- size_size = iasecc_parse_size(data + 3, &size); ++ size_size = iasecc_parse_size(data + 3, data_len - 3, &size); + LOG_TEST_RET(ctx, size_size, "parse error: invalid size data"); + + if (data_len != size + size_size + 3) +@@ -824,7 +831,7 @@ iasecc_sdo_allocate_and_parse(struct sc_card *card, unsigned char *data, size_t + + offs = 3 + size_size; + for (; offs < data_len;) { +- rv = iasecc_sdo_parse_data(card, data + offs, sdo); ++ rv = iasecc_sdo_parse_data(card, data + offs, data_len - offs, sdo); + LOG_TEST_RET(ctx, rv, "parse error: invalid SDO data"); + + offs += rv; +@@ -1222,7 +1229,7 @@ iasecc_sdo_parse_card_answer(struct sc_context *ctx, unsigned char *data, size_t + + memset(out, 0, sizeof(*out)); + for (offs=0; offs sizeof(out->data)) +@@ -1293,7 +1300,7 @@ iasecc_docp_copy(struct sc_context *ctx, struct iasecc_sdo_docp *in, struct iase + int rv; + + LOG_FUNC_CALLED(ctx); +- if (!in || !out) ++ if (!in || !out) + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + + memset(out, 0, sizeof(struct iasecc_sdo_docp)); +-- +2.42.0 + +From fbda61d0d276dc98b9d1d1e6810bbd21d19e3859 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 27 Oct 2023 13:23:18 +0200 +Subject: [PATCH] iasecc: Avoid buffer overflow with invalid data + +Thanks oss-fuzz + +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=63587 +--- + src/libopensc/iasecc-sdo.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/libopensc/iasecc-sdo.c b/src/libopensc/iasecc-sdo.c +index 1e01c0df5..479b3c23b 100644 +--- a/src/libopensc/iasecc-sdo.c ++++ b/src/libopensc/iasecc-sdo.c +@@ -371,15 +371,15 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru + static int + iasecc_parse_size(unsigned char *data, size_t data_len, size_t *out) + { +- if (*data < 0x80 && data_len > 0) { ++ if (data_len > 0 && *data < 0x80) { + *out = *data; + return 1; + } +- else if (*data == 0x81 && data_len > 1) { ++ else if (data_len > 1 && *data == 0x81) { + *out = *(data + 1); + return 2; + } +- else if (*data == 0x82 && data_len > 2) { ++ else if (data_len > 2 && *data == 0x82) { + *out = *(data + 1) * 0x100 + *(data + 2); + return 3; + } +-- +2.42.0 + +From 2a4921ab23fd0853f327517636c50de947548161 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= +Date: Tue, 29 Aug 2023 14:40:21 +0200 +Subject: [PATCH] iasecc: Check length of data when parsing crt + +Thanks OSS-Fuzz +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=61797 +--- + src/libopensc/iasecc-sdo.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/src/libopensc/iasecc-sdo.c b/src/libopensc/iasecc-sdo.c +index b3e567dd5..3eeb03b91 100644 +--- a/src/libopensc/iasecc-sdo.c ++++ b/src/libopensc/iasecc-sdo.c +@@ -204,7 +204,7 @@ iasecc_sdo_free(struct sc_card *card, struct iasecc_sdo *sdo) + + + static int +-iasecc_crt_parse(struct sc_card *card, unsigned char *data, struct iasecc_se_info *se) ++iasecc_crt_parse(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_se_info *se) + { + struct sc_context *ctx = card->ctx; + struct sc_crt crt; +@@ -212,11 +212,16 @@ iasecc_crt_parse(struct sc_card *card, unsigned char *data, struct iasecc_se_inf + + sc_log(ctx, "iasecc_crt_parse(0x%X) called", *data); + ++ if (data_len < 2) ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); ++ + memset(&crt, 0, sizeof(crt)); + crt.tag = *(data + 0); + len = *(data + 1); + + for(offs = 2; offs < len + 2; offs += 3) { ++ if ((size_t) offs + 2 >= data_len) ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); + sc_log(ctx, "iasecc_crt_parse(0x%X) CRT %X -> %X", *data, *(data + offs), *(data + offs + 2)); + if (*(data + offs) == IASECC_CRT_TAG_USAGE) { + crt.usage = *(data + offs + 2); +@@ -368,7 +373,7 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru + + offs = 1 + size_size; + for (; offs < data_len;) { +- rv = iasecc_crt_parse(card, data + offs, se); ++ rv = iasecc_crt_parse(card, data + offs, data_len - offs, se); + LOG_TEST_RET(ctx, rv, "parse error: invalid SE data"); + + offs += rv; +-- +2.42.0 + +From 6085994384a7171c5c68f6718d9db10ed77c5af1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= +Date: Thu, 10 Aug 2023 13:56:24 +0200 +Subject: [PATCH] card-entersafe.c: Free modulus buffer in case of error + +Thanks OSS-Fuzz +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60680 +--- + src/libopensc/card-entersafe.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/src/libopensc/card-entersafe.c b/src/libopensc/card-entersafe.c +index eb31f7146..168894abd 100644 +--- a/src/libopensc/card-entersafe.c ++++ b/src/libopensc/card-entersafe.c +@@ -1423,12 +1423,18 @@ static int entersafe_gen_key(sc_card_t *card, sc_entersafe_gen_key_data *data) + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_OUT_OF_MEMORY); + + p=rbuf; +- if (*p!='E') ++ if (*p!='E') { ++ free(data->modulus); ++ data->modulus = NULL; + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); ++ } + p+=2+p[1]; + /* N */ +- if (*p!='N') ++ if (*p!='N') { ++ free(data->modulus); ++ data->modulus = NULL; + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); ++ } + ++p; + if(*p++>0x80) + { +-- +2.42.0 + +From 50f0985f6343eeac4044661d56807ee9286db42c Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Sun, 8 Oct 2023 19:08:39 +0200 +Subject: [PATCH] entersafe: Avoid buffer overflow during keygen + +Thanks oss-fuzz + +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=63104 +--- + src/libopensc/card-entersafe.c | 54 ++++++++++++++++++++-------------- + 1 file changed, 32 insertions(+), 22 deletions(-) + +diff --git a/src/libopensc/card-entersafe.c b/src/libopensc/card-entersafe.c +index 168894abd..feb9ebe18 100644 +--- a/src/libopensc/card-entersafe.c ++++ b/src/libopensc/card-entersafe.c +@@ -1374,8 +1374,9 @@ static int entersafe_gen_key(sc_card_t *card, sc_entersafe_gen_key_data *data) + int r; + size_t len = data->key_length >> 3; + sc_apdu_t apdu; +- u8 rbuf[300]; ++ u8 rbuf[300] = {0}; + u8 sbuf[4],*p; ++ size_t plen = 0; + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + +@@ -1418,40 +1419,49 @@ static int entersafe_gen_key(sc_card_t *card, sc_entersafe_gen_key_data *data) + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + LOG_TEST_RET(card->ctx, sc_check_sw(card,apdu.sw1,apdu.sw2),"EnterSafe get pukey failed"); + +- data->modulus = malloc(len); +- if (!data->modulus) +- SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_OUT_OF_MEMORY); +- +- p=rbuf; +- if (*p!='E') { +- free(data->modulus); +- data->modulus = NULL; ++ p = rbuf; ++ plen = apdu.resplen; ++ if (*p != 'E') { + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); + } +- p+=2+p[1]; ++ if ((size_t)(p - rbuf) + 2 + p[1] >= plen) { ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); ++ } ++ p += 2 + p[1]; + /* N */ +- if (*p!='N') { +- free(data->modulus); +- data->modulus = NULL; ++ if (*p != 'N') { ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); ++ } ++ if ((size_t)(p - rbuf) + 2 >= plen) { + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); + } + ++p; +- if(*p++>0x80) ++ if (*p++ > 0x80) + { +- u8 len_bytes=(*(p-1))&0x0f; +- size_t module_len=0; +- while(len_bytes!=0) ++ u8 len_bytes = (*(p - 1)) & 0x0f; ++ size_t module_len = 0; ++ if ((size_t)(p - rbuf) + len_bytes >= plen) { ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); ++ } ++ while (len_bytes != 0) + { +- module_len=module_len<<8; +- module_len+=*p++; ++ module_len = module_len << 8; ++ module_len += *p++; + --len_bytes; + } + } + +- entersafe_reverse_buffer(p,len); +- memcpy(data->modulus,p,len); ++ if ((p - rbuf) + len >= plen) { ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); ++ } + +- SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS); ++ data->modulus = malloc(len); ++ if (!data->modulus) ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_OUT_OF_MEMORY); ++ entersafe_reverse_buffer(p, len); ++ memcpy(data->modulus, p, len); ++ ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS); + } + + static int entersafe_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) +-- +2.42.0 + diff --git a/SPECS/opensc.spec b/SPECS/opensc.spec index e7a2759..bf77ed6 100644 --- a/SPECS/opensc.spec +++ b/SPECS/opensc.spec @@ -3,7 +3,7 @@ Name: opensc Version: 0.20.0 -Release: 4%{?dist} +Release: 7%{?dist} Summary: Smart card library and applications Group: System Environment/Libraries @@ -32,7 +32,54 @@ Patch15: opensc-0.20.0-calloc0.patch # https://github.com/OpenSC/OpenSC/pull/2148 # + configuration change by default Patch16: opensc-0.20.0-file-cache.patch - +# https://github.com/OpenSC/OpenSC/pull/1929 +Patch17: opensc-0.20.0-idprime.patch +# https://github.com/OpenSC/OpenSC/pull/2787 +Patch18: opensc-0.20.0-CVE-2023-2977.patch +# 31d8c2dfd14ed01b430def2f46cc718ef4b595fc +# 8f4a6c703b5ae7d4f44cf33c85330171afa917bf +# https://github.com/OpenSC/OpenSC/pull/1970 without the first and last commits +# https://github.com/OpenSC/OpenSC/pull/1923 +# https://github.com/OpenSC/OpenSC/pull/2051 +# https://github.com/OpenSC/OpenSC/pull/2077 +# https://github.com/OpenSC/OpenSC/pull/2418 +# https://github.com/OpenSC/OpenSC/pull/2600 +# c2e00e9071952b30ed6d58d9b7670eb3d93ea6fb +# https://github.com/OpenSC/OpenSC/pull/2740 +## OpenSC notify build issues +# 5e79a2a4abdd523cfff19824718bbb0d8ced7320 +# 843779fe6e0f345f483f9ce9c9739913502391eb +# 7936bdef15c71139a6a6159cabaf9e6101565add +# 1202eceeefd5ffab45648d41ed0a3076cac10920 +# 295f399304644e6b0acde267ac410d0aae4a1aee +# ca01aa7a8edc8280a5ceadebb472c2e3c198d8c2 +Patch19: opensc-0.20.0-reader-removal.patch +# https://github.com/OpenSC/OpenSC/commit/bff98ff078a99e6864ba1a598fd7dc9af4a9476b +# https://github.com/OpenSC/OpenSC/commit/0875c69295ef28b45fb682b37cede58fc36b7a1a +Patch20: %{name}-0.23.0-cache-offsets.patch +# https://github.com/OpenSC/OpenSC/commit/868f76fb31255fd3fdacfc3e476452efeb61c3e7 +# https://github.com/OpenSC/OpenSC/commit/80cc5d30635f0d2c92b5099c0f9dc680d0ffce2f +Patch21: %{name}-0.23.0-pin-bypass.patch +# https://github.com/OpenSC/OpenSC/commit/245efe608d083fd4e4ec96793fdefd218e26fde7 +# https://github.com/OpenSC/OpenSC/commit/440ca666eff10cc7011901252d20f3fc4ea23651 +# https://github.com/OpenSC/OpenSC/commit/41d61da8481582e12710b5858f8b635e0a71ab5e +# https://github.com/OpenSC/OpenSC/commit/88880db0307a07e33cf2e1592bb029e9c170dfea +# https://github.com/OpenSC/OpenSC/commit/638a5007a5d240d6fa901aa822cfeef94fe36e85 +# https://github.com/OpenSC/OpenSC/commit/c449a181a6988cc1e8dc8764d23574e48cdc3fa6 +# https://github.com/OpenSC/OpenSC/commit/5631e9843c832a99769def85b7b9b68b4e3e3959 +# https://github.com/OpenSC/OpenSC/commit/e7f81d86dcdc751f4737f4b29a99bfc54d29c5c9 +# https://github.com/OpenSC/OpenSC/commit/df5a176bfdf8c52ba89c7fef1f82f6f3b9312bc1 +# https://github.com/OpenSC/OpenSC/commit/578aed8391ef117ca64a9e0cba8e5c264368a0ec +# https://github.com/OpenSC/OpenSC/commit/013a807492568bf9907cfb3df41f130ac83c7b9 +# https://github.com/OpenSC/OpenSC/commit/fc2c20c3f895569eeb58328bb882aec07325d3b +# https://github.com/OpenSC/OpenSC/commit/3b9129bd3cfc6ac57d5554e015c3df85f5076dc +# https://github.com/OpenSC/OpenSC/commit/bda61d0d276dc98b9d1d1e6810bbd21d19e3859 +# https://github.com/OpenSC/OpenSC/commit/a4921ab23fd0853f327517636c50de947548161 +# https://github.com/OpenSC/OpenSC/commit/085994384a7171c5c68f6718d9db10ed77c5af1 +# https://github.com/OpenSC/OpenSC/commit/0f0985f6343eeac4044661d56807ee9286db42c +Patch22: %{name}-0.23.0-pkcs15init.patch +# https://github.com/OpenSC/OpenSC/pull/2948 +Patch23: %{name}-0.23.0-constant-time-pkcs1.patch BuildRequires: pcsc-lite-devel BuildRequires: readline-devel @@ -71,6 +118,13 @@ every software/card that does so, too. %patch14 -p1 -b .padding %patch15 -p1 -b .calloc0 %patch16 -p1 -b .file-cache +%patch17 -p1 -b .idprime +%patch18 -p1 -b .CVE-2023-2977 +%patch19 -p1 -b .reader-removal +%patch20 -p1 -b .cache-offsets +%patch21 -p1 -b .pin-bypass +%patch22 -p1 -b .pkcs15init +%patch23 -p1 -b .constant-time-pkcs1.5 cp -p src/pkcs15init/README ./README.pkcs15init cp -p src/scconf/README.scconf . @@ -229,6 +283,20 @@ fi %changelog +* Thu Nov 30 2023 Jakub Jelen - 0.20.0-7 +- Fix file caching with different offsets (RHEL-4077) +- Fix CVE-2023-40660: Potential PIN bypass +- Fix CVE-2023-40661: Dynamic analyzers reports in pkcs15init +- Fix CVE-2023-5992: Marvin: Side-channel leaks while stripping encryption PKCS#1.5 padding + +* Tue Jul 11 2023 Jakub Jelen - 0.20.0-6 +- Fix introduced issues tagged by coverity (RHEL-765) + +* Thu Jun 15 2023 Jakub Jelen - 0.20.0-5 +- Avoid potential crash because of missing list terminator (#2196234) +- Fix CVE-2023-2977: potential buffer overrun in pkcs15 cardos_have_verifyrc_package (#2211093) +- Backport upstream changes regarding to reader removal (#2097048) + * Fri Nov 20 2020 Jakub Jelen - 0.20.0-4 - Use file cache by default (#1892810) - Avoid calloc with 0 argument (#1895401)