From c45c90a337a3126f8e37031a552c23578d298c0b Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 20 Apr 2015 16:18:11 +0200 Subject: [PATCH 1/7] sc_pkcs11_close_all_sessions: close all sessions even if closing one fails --- src/pkcs11/pkcs11-session.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pkcs11/pkcs11-session.c b/src/pkcs11/pkcs11-session.c index e6edf25c..143ab56e 100644 --- a/src/pkcs11/pkcs11-session.c +++ b/src/pkcs11/pkcs11-session.c @@ -120,17 +120,17 @@ static CK_RV sc_pkcs11_close_session(CK_SESSION_HANDLE hSession) * the global lock held */ CK_RV sc_pkcs11_close_all_sessions(CK_SLOT_ID slotID) { - CK_RV rv = CKR_OK; + CK_RV rv = CKR_OK, error; struct sc_pkcs11_session *session; unsigned int i; sc_log(context, "real C_CloseAllSessions(0x%lx) %d", slotID, list_size(&sessions)); for (i = 0; i < list_size(&sessions); i++) { session = list_get_at(&sessions, i); if (session->slot->id == slotID) - if ((rv = sc_pkcs11_close_session(session->handle)) != CKR_OK) - return rv; + if ((error = sc_pkcs11_close_session(session->handle)) != CKR_OK) + rv = error; } - return CKR_OK; + return rv; } CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) From 54f285d57ada65fc7774e82e2f0d10c35060d7ed Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 20 Apr 2015 23:30:06 +0200 Subject: [PATCH 2/7] correctly handle readers that have been removed --- src/libopensc/opensc.h | 1 + src/libopensc/reader-pcsc.c | 23 +++++++++++++++-------- src/pkcs11/slot.c | 14 +++++++++----- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 7964b311..90f0e2e0 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -286,6 +286,7 @@ struct sc_reader_driver { #define SC_READER_CARD_INUSE 0x00000004 #define SC_READER_CARD_EXCLUSIVE 0x00000008 #define SC_READER_HAS_WAITING_AREA 0x00000010 +#define SC_READER_REMOVED 0x00000020 /* reader capabilities */ #define SC_READER_CAP_DISPLAY 0x00000001 diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 06192cf3..32007394 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -949,6 +949,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) char *reader_buf = NULL, *reader_name; const char *mszGroups = NULL; int ret = SC_ERROR_INTERNAL; + size_t i; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); @@ -958,7 +959,13 @@ static int pcsc_detect_readers(sc_context_t *ctx) goto out; } - sc_log(ctx, "Probing pcsc readers"); + /* temporarily mark all readers as removed */ + for (i=0;i < sc_ctx_get_reader_count(ctx);i++) { + sc_reader_t *reader = sc_ctx_get_reader(ctx, i); + reader->flags |= SC_READER_REMOVED; + } + + sc_log(ctx, "Probing PC/SC readers"); do { if (gpriv->pcsc_ctx == -1) { @@ -980,7 +987,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) goto out; } - sc_log(ctx, "Establish pcsc context"); + sc_log(ctx, "Establish PC/SC context"); rv = gpriv->SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &gpriv->pcsc_ctx); @@ -1007,28 +1014,28 @@ static int pcsc_detect_readers(sc_context_t *ctx) goto out; } for (reader_name = reader_buf; *reader_name != '\x0'; reader_name += strlen(reader_name) + 1) { - sc_reader_t *reader = NULL; + sc_reader_t *reader = NULL, *old_reader; struct pcsc_private_data *priv = NULL; - unsigned int i; int found = 0; for (i=0;i < sc_ctx_get_reader_count(ctx) && !found;i++) { - sc_reader_t *reader2 = sc_ctx_get_reader(ctx, i); - if (reader2 == NULL) { + old_reader = sc_ctx_get_reader(ctx, i); + if (old_reader == NULL) { ret = SC_ERROR_INTERNAL; goto err1; } - if (!strcmp(reader2->name, reader_name)) { + if (!strcmp(old_reader->name, reader_name)) { found = 1; } } /* Reader already available, skip */ if (found) { + old_reader->flags &= ~SC_READER_REMOVED; continue; } - sc_log(ctx, "Found new pcsc reader '%s'", reader_name); + sc_log(ctx, "Found new PC/SC reader '%s'", reader_name); if ((reader = calloc(1, sizeof(sc_reader_t))) == NULL) { ret = SC_ERROR_OUT_OF_MEMORY; diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index 87b1e3dd..9f2ae484 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -330,9 +330,13 @@ card_detect_all(void) /* 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); - if (!reader_get_slot(reader)) - initialize_reader(reader); - card_detect(sc_ctx_get_reader(context, i)); + if (reader->flags & SC_READER_REMOVED) { + card_removed(reader); + } else { + if (!reader_get_slot(reader)) + initialize_reader(reader); + card_detect(sc_ctx_get_reader(context, i)); + } } sc_log(context, "All cards detected"); return CKR_OK; @@ -420,7 +424,7 @@ CK_RV slot_token_removed(CK_SLOT_ID id) /* Release framework stuff */ if (slot->card != NULL) { if (slot->fw_data != NULL && - slot->card->framework != NULL && slot->card->framework->release_token != NULL) + slot->card->framework != NULL && slot->card->framework->release_token != NULL) slot->card->framework->release_token(slot->card, slot->fw_data); } @@ -446,7 +450,7 @@ CK_RV slot_find_changed(CK_SLOT_ID_PTR idp, int mask) sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); sc_log(context, "slot 0x%lx token: %d events: 0x%02X",slot->id, (slot->slot_info.flags & CKF_TOKEN_PRESENT), slot->events); if ((slot->events & SC_EVENT_CARD_INSERTED) - && !(slot->slot_info.flags & CKF_TOKEN_PRESENT)) { + && !(slot->slot_info.flags & CKF_TOKEN_PRESENT)) { /* If a token has not been initialized, clear the inserted event */ slot->events &= ~SC_EVENT_CARD_INSERTED; } From c8a7c8bc7aec67f95254dd900f394f6c55429f4e Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 20 Apr 2015 22:44:33 +0200 Subject: [PATCH 3/7] fixed typo --- src/pkcs15init/pkcs15-myeid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pkcs15init/pkcs15-myeid.c b/src/pkcs15init/pkcs15-myeid.c index 5bf7d2b2..063fd2c4 100644 --- a/src/pkcs15init/pkcs15-myeid.c +++ b/src/pkcs15init/pkcs15-myeid.c @@ -646,7 +646,7 @@ myeid_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, memcpy(pubkey->u.rsa.modulus.data, raw_pubkey, pubkey->u.rsa.modulus.len); } else if (object->type == SC_PKCS15_TYPE_PRKEY_EC) { - struct sc_ec_parameters *ecparams = (struct sc_pkcs15_ec_parameters *)key_info->params.data; + struct sc_ec_parameters *ecparams = (struct sc_ec_parameters *)key_info->params.data; sc_log(ctx, "curve '%s', len %i, oid '%s'", ecparams->named_curve, ecparams->field_length, sc_dump_oid(&(ecparams->id))); pubkey->algorithm = SC_ALGORITHM_EC; From cbc43eeb88c619b1f488dd937d89b2fc5546ef83 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 20 Apr 2015 23:04:47 +0200 Subject: [PATCH 4/7] fixed compiler warning --- src/libopensc/card-iasecc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index 45fe1f53..43974897 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -572,6 +572,7 @@ iasecc_init_amos(struct sc_card *card) LOG_FUNC_RETURN(ctx, SC_SUCCESS); } +static int iasecc_mi_match(struct sc_card *card) { struct sc_context *ctx = card->ctx; @@ -2060,6 +2061,7 @@ iasecc_chv_change_pinpad(struct sc_card *card, unsigned reference, int *tries_le } +#if 0 static int iasecc_chv_set_pinpad(struct sc_card *card, unsigned char reference) { @@ -2105,6 +2107,7 @@ iasecc_chv_set_pinpad(struct sc_card *card, unsigned char reference) rv = iso_ops->pin_cmd(card, &pin_cmd, NULL); LOG_FUNC_RETURN(ctx, rv); } +#endif static int From e359b2a310c739c8f7f2447d716a65268cbb40cd Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 21 Apr 2015 00:57:22 +0200 Subject: [PATCH 5/7] handle unexpected meltdown of PC/SC service --- src/libopensc/reader-pcsc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 32007394..0765885c 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -979,6 +979,13 @@ static int pcsc_detect_readers(sc_context_t *ctx) else { rv = gpriv->SCardListReaders(gpriv->pcsc_ctx, NULL, NULL, (LPDWORD) &reader_buf_size); + if (rv == SCARD_E_NO_SERVICE) { + gpriv->SCardReleaseContext(gpriv->pcsc_ctx); + gpriv->pcsc_ctx = -1; + gpriv->pcsc_wait_ctx = -1; + /* reconnecting below may may restart PC/SC service */ + rv = SCARD_E_INVALID_HANDLE; + } } if (rv != SCARD_S_SUCCESS) { if (rv != (LONG)SCARD_E_INVALID_HANDLE) { From 02f3997632d147ad3e55a51a74794602d38144eb Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 21 Apr 2015 01:32:37 +0200 Subject: [PATCH 6/7] added error handling to print_ssh_key --- src/tools/pkcs15-tool.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index de3e6b33..4f7c0e36 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -803,6 +803,8 @@ static void print_ssh_key(FILE *outf, const char * alg, struct sc_pkcs15_object if (opt_rfc4716) { r = sc_base64_encode(buf, len, uu, 2*len, 64); + if (r < 0) + return; fprintf(outf,"---- BEGIN SSH2 PUBLIC KEY ----\n"); @@ -815,6 +817,9 @@ static void print_ssh_key(FILE *outf, const char * alg, struct sc_pkcs15_object // Old style openssh - [ [ anything else] // r = sc_base64_encode(buf, len, uu, 2*len, 0); + if (r < 0) + return; + if (obj->label && strlen(obj->label)) fprintf(outf,"ssh-%s %s %s\n", alg, uu, obj->label); else From 9f318b829fb9e2fa42d875a4e2afd576d5fc73ad Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 21 Apr 2015 02:00:06 +0200 Subject: [PATCH 7/7] remove slots of removed readers --- src/libopensc/internal.h | 1 - src/libopensc/libopensc.exports | 1 + src/libopensc/opensc.h | 2 ++ src/pkcs11/slot.c | 16 ++++++++++++++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/libopensc/internal.h b/src/libopensc/internal.h index 2658428b..418e4179 100644 --- a/src/libopensc/internal.h +++ b/src/libopensc/internal.h @@ -74,7 +74,6 @@ struct sc_atr_table { /* Internal use only */ int _sc_add_reader(struct sc_context *ctx, struct sc_reader *reader); -int _sc_delete_reader(struct sc_context *ctx, struct sc_reader *reader); int _sc_parse_atr(struct sc_reader *reader); /* Add an ATR to the card driver's struct sc_atr_table */ diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports index 0da5c53b..cea8d42f 100644 --- a/src/libopensc/libopensc.exports +++ b/src/libopensc/libopensc.exports @@ -77,6 +77,7 @@ sc_ctx_get_reader_by_name sc_ctx_get_reader_count sc_ctx_log_to_file sc_ctx_use_reader +_sc_delete_reader sc_decipher sc_delete_file sc_delete_record diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 90f0e2e0..ad5405d5 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -803,6 +803,8 @@ sc_reader_t *sc_ctx_get_reader_by_id(sc_context_t *ctx, unsigned int id); */ unsigned int sc_ctx_get_reader_count(sc_context_t *ctx); +int _sc_delete_reader(sc_context_t *ctx, sc_reader_t *reader); + /** * Redirects OpenSC debug log to the specified file * @param ctx existing OpenSC context diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index 9f2ae484..1d9c1a41 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -20,6 +20,7 @@ */ #include "config.h" +#include "libopensc/opensc.h" #include #include @@ -100,6 +101,15 @@ CK_RV create_slot(sc_reader_t *reader) return CKR_OK; } +void delete_slot(struct sc_pkcs11_slot *slot) +{ + if (slot) { + list_destroy(&slot->objects); + list_delete(&virtual_slots, slot); + free(slot); + } +} + /* create slots associated with a reader, called whenever a reader is seen. */ CK_RV initialize_reader(sc_reader_t *reader) @@ -331,7 +341,13 @@ card_detect_all(void) for (i=0; i< sc_ctx_get_reader_count(context); i++) { sc_reader_t *reader = sc_ctx_get_reader(context, i); if (reader->flags & SC_READER_REMOVED) { + struct sc_pkcs11_slot *slot; card_removed(reader); + while ((slot = reader_get_slot(reader))) { + delete_slot(slot); + } + _sc_delete_reader(context, reader); + i--; } else { if (!reader_get_slot(reader)) initialize_reader(reader);