From 87cdfcb08c7450d003786ad73ee28dfa7636b346 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 19 Jan 2018 23:55:35 +0100 Subject: [PATCH] OpenPGP: Implemented "keep alive" command --- etc/opensc.conf.in | 32 ++++++++++++++++++++++++++------ src/libopensc/card-openpgp.c | 15 +++++++++++++++ src/libopensc/ctx.c | 2 ++ src/libopensc/dir.c | 6 ++---- src/libopensc/opensc.h | 1 + src/libopensc/pkcs15.c | 11 ++++------- 6 files changed, 50 insertions(+), 17 deletions(-) diff --git a/etc/opensc.conf.in b/etc/opensc.conf.in index a417fe22..939901e0 100644 --- a/etc/opensc.conf.in +++ b/etc/opensc.conf.in @@ -272,8 +272,9 @@ app default { # can be specified as strings: # # rng - On-board random number source + # keep_alive - Request the card driver to send a "keep alive" command before each transaction to make sure that the required applet is still selected. # - # flags = "rng", "0x80000000"; + # flags = "rng", "keep_alive", "0x80000000"; # Enable pkcs11 initialization. # Default: no @@ -373,11 +374,30 @@ app default { # notify_pin_bad_text = "bad text"; # } - # PIV cards need an entry similar to this one: - # card_atr 3B:7D:96:00:00:80:31:80:65:B0:83:11:00:AC:83:00:90:00 { - # name = "PIV-II"; - # driver = "piv"; - # } + # Yubikey is known to have the PIV applet and the OpenPGP applet. OpenSC + # can handle both to access keys and certificates, but only one at a time. + card_atr 3b:f8:13:00:00:81:31:fe:15:59:75:62:69:6b:65:79:34:d4 { + name = "Yubikey 4"; + # Select the PKI applet to use ("PIV-II" or "openpgp") + driver = "PIV-II"; + # Recover from other applications accessing a different applet + flags = "keep_alive"; + } + card_atr 3b:fc:13:00:00:81:31:fe:15:59:75:62:69:6b:65:79:4e:45:4f:72:33:e1 { + name = "Yubikey Neo"; + # Select the PKI applet to use ("PIV-II" or "openpgp") + driver = "PIV-II"; + # Recover from other applications accessing a different applet + flags = "keep_alive"; + } + card_atr 3b:8c:80:01:59:75:62:69:6b:65:79:4e:45:4f:72:33:58 { + atrmask = "FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:00:00"; + name = "Yubikey Neo"; + # Select the PKI applet to use ("PIV-II" or "openpgp") + driver = "PIV-II"; + # Recover from other applications accessing a different applet + flags = "keep_alive"; + } # Micardo driver sometimes only play together with T=0 # In theory only the 'cold' ATR should be specified, as T=0 will diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index e66cf87f..fb6ae526 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -2870,10 +2870,25 @@ pgp_update_binary(sc_card_t *card, unsigned int idx, static int pgp_card_reader_lock_obtained(sc_card_t *card, int was_reset) { + struct pgp_priv_data *priv = DRVDATA(card); /* may be null during initialization */ int r = SC_SUCCESS; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + if (card->flags & SC_CARD_FLAG_KEEP_ALIVE + && was_reset <= 0 + && priv != NULL && priv->mf && priv->mf->file) { + /* check whether applet is still selected */ + unsigned char aid[16]; + + r = sc_get_data(card, 0x004F, aid, sizeof aid); + if ((size_t) r != priv->mf->file->namelen + || 0 != memcmp(aid, priv->mf->file->name, r)) { + /* reselect is required */ + was_reset = 1; + } + } + if (was_reset > 0) { sc_file_t *file = NULL; sc_path_t path; diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c index 0a40b79b..3f4e73d3 100644 --- a/src/libopensc/ctx.c +++ b/src/libopensc/ctx.c @@ -631,6 +631,8 @@ static int load_card_atrs(sc_context_t *ctx) if (!strcmp(list->data, "rng")) flags = SC_CARD_FLAG_RNG; + else if (!strcmp(list->data, "keep_alive")) + flags = SC_CARD_FLAG_KEEP_ALIVE; else if (sscanf(list->data, "%x", &flags) != 1) flags = 0; diff --git a/src/libopensc/dir.c b/src/libopensc/dir.c index 59e988d7..12751bd7 100644 --- a/src/libopensc/dir.c +++ b/src/libopensc/dir.c @@ -259,10 +259,8 @@ void sc_free_apps(sc_card_t *card) int i; for (i = 0; i < card->app_count; i++) { - if (card->app[i]->label) - free(card->app[i]->label); - if (card->app[i]->ddo.value) - free(card->app[i]->ddo.value); + free(card->app[i]->label); + free(card->app[i]->ddo.value); free(card->app[i]); } card->app_count = -1; diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 3024919d..943d55da 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -453,6 +453,7 @@ struct sc_reader_operations { /* Hint SC_CARD_CAP_RNG */ #define SC_CARD_FLAG_RNG 0x00000002 +#define SC_CARD_FLAG_KEEP_ALIVE 0x00000004 /* * Card capabilities diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index c520cd50..3e058863 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -790,15 +790,12 @@ sc_pkcs15_free_tokeninfo(struct sc_pkcs15_tokeninfo *tokeninfo) void sc_pkcs15_free_app(struct sc_pkcs15_card *p15card) { - if (!p15card || !p15card->app) - return; - - if (p15card->app->label) + if (p15card && p15card->app) { free(p15card->app->label); - if (p15card->app->ddo.value) free(p15card->app->ddo.value); - free(p15card->app); - p15card->app = NULL; + free(p15card->app); + p15card->app = NULL; + } }