From ff87f4e578f412332ae59fdab016f0a5304baaf9 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 1 Apr 2021 10:31:52 +0200 Subject: [PATCH] scd: New flag --reread for LEARN * scd/command.c (cmd_learn): Add flag --reread. * scd/app-common.h (struct app_ctx_s): New field need_reset. * scd/app.c (write_learn_status_core): Set need_reset if we notice an error after returning from a reread. Change all callers of card functions to return GPG_ERR_CARD_RESET so that that app is not anymore used. Signed-off-by: Werner Koch --- scd/app-common.h | 1 + scd/app.c | 119 ++++++++++++++++++++++++++++++++++------------- scd/command.c | 20 +++++--- 3 files changed, 101 insertions(+), 39 deletions(-) diff --git a/scd/app-common.h b/scd/app-common.h index c68fb8609..f194828a9 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -136,6 +136,7 @@ struct app_ctx_s { unsigned int force_chv1:1; /* True if the card does not cache CHV1. */ unsigned int did_chv2:1; unsigned int did_chv3:1; + unsigned int need_reset:1; /* Do't allow any functions but deinit. */ struct app_local_s *app_local; /* Local to the application. */ struct { void (*deinit) (app_t app); diff --git a/scd/app.c b/scd/app.c index e378f23b8..d0e990e48 100644 --- a/scd/app.c +++ b/scd/app.c @@ -1407,14 +1407,20 @@ run_reselect (ctrl_t ctrl, card_t c, app_t a, app_t a_prev) * required to always work. */ if (a_prev && a_prev->fnc.prep_reselect) { - err = a_prev->fnc.prep_reselect (a_prev, ctrl); + if (a_prev->need_reset) + err = gpg_error (GPG_ERR_CARD_RESET); + else + err = a_prev->fnc.prep_reselect (a_prev, ctrl); if (err) log_error ("slot %d, app %s: preparing re-select from %s failed: %s\n", c->slot, xstrapptype (a), xstrapptype (a_prev), gpg_strerror (err)); } - err = a->fnc.reselect (a, ctrl); + if (a->need_reset) + err = gpg_error (GPG_ERR_CARD_RESET); + else + err = a->fnc.reselect (a, ctrl); if (err) { log_error ("slot %d, app %s: error re-selecting: %s\n", @@ -1491,6 +1497,7 @@ maybe_switch_app (ctrl_t ctrl, card_t card, const char *keyref) * the corresponding app. */ for (app = card->app; app; app_prev = app, app = app->next) if (app->fnc.with_keygrip + && !app->need_reset && !app->fnc.with_keygrip (app, ctrl, KEYGRIP_ACTION_LOOKUP, keyref, 0)) break; @@ -1542,6 +1549,8 @@ static gpg_error_t write_learn_status_core (card_t card, app_t app, ctrl_t ctrl, unsigned int flags) { + gpg_error_t err; + /* We do not send CARD and APPTYPE if only keypairinfo is requested. */ if (!(flags & APP_LEARN_FLAG_KEYPAIRINFO)) { @@ -1555,7 +1564,15 @@ write_learn_status_core (card_t card, app_t app, ctrl_t ctrl, send_status_printf (ctrl, "APPVERSION", "%X", app->appversion); } - return app->fnc.learn_status (app, ctrl, flags); + if (app->need_reset) + err = gpg_error (GPG_ERR_CARD_RESET); + else + { + err = app->fnc.learn_status (app, ctrl, flags); + if (err && (flags & APP_LEARN_FLAG_REREAD)) + app->need_reset = 1; + } + return err; } @@ -1666,7 +1683,10 @@ app_readcert (card_t card, ctrl_t ctrl, const char *certid, if (DBG_APP) log_debug ("slot %d app %s: calling readcert(%s)\n", card->slot, xstrapptype (card->app), certid); - err = card->app->fnc.readcert (card->app, certid, cert, certlen); + if (card->app->need_reset) + err = gpg_error (GPG_ERR_CARD_RESET); + else + err = card->app->fnc.readcert (card->app, certid, cert, certlen); } unlock_card (card); @@ -1708,7 +1728,10 @@ app_readkey (card_t card, ctrl_t ctrl, const char *keyid, unsigned int flags, if (DBG_APP) log_debug ("slot %d app %s: calling readkey(%s)\n", card->slot, xstrapptype (card->app), keyid); - err = card->app->fnc.readkey (card->app, ctrl, keyid, flags, pk, pklen); + if (card->app->need_reset) + err = gpg_error (GPG_ERR_CARD_RESET); + else + err = card->app->fnc.readkey (card->app, ctrl, keyid, flags, pk, pklen); } unlock_card (card); @@ -1758,7 +1781,10 @@ app_getattr (card_t card, ctrl_t ctrl, const char *name) if (DBG_APP) log_debug ("slot %d app %s: calling getattr(%s)\n", card->slot, xstrapptype (card->app), name); - err = card->app->fnc.getattr (card->app, ctrl, name); + if (card->app->need_reset) + err = gpg_error (GPG_ERR_CARD_RESET); + else + err = card->app->fnc.getattr (card->app, ctrl, name); } unlock_card (card); @@ -1790,8 +1816,11 @@ app_setattr (card_t card, ctrl_t ctrl, const char *name, if (DBG_APP) log_debug ("slot %d app %s: calling setattr(%s)\n", card->slot, xstrapptype (card->app), name); - err = card->app->fnc.setattr (card->app, ctrl, name, pincb, pincb_arg, - value, valuelen); + if (card->app->need_reset) + err = gpg_error (GPG_ERR_CARD_RESET); + else + err = card->app->fnc.setattr (card->app, ctrl, name, pincb, pincb_arg, + value, valuelen); } unlock_card (card); @@ -1826,10 +1855,13 @@ app_sign (card_t card, ctrl_t ctrl, const char *keyidstr, int hashalgo, if (DBG_APP) log_debug ("slot %d app %s: calling sign(%s)\n", card->slot, xstrapptype (card->app), keyidstr); - err = card->app->fnc.sign (card->app, ctrl, keyidstr, hashalgo, - pincb, pincb_arg, - indata, indatalen, - outdata, outdatalen); + if (card->app->need_reset) + err = gpg_error (GPG_ERR_CARD_RESET); + else + err = card->app->fnc.sign (card->app, ctrl, keyidstr, hashalgo, + pincb, pincb_arg, + indata, indatalen, + outdata, outdatalen); } unlock_card (card); @@ -1867,10 +1899,13 @@ app_auth (card_t card, ctrl_t ctrl, const char *keyidstr, if (DBG_APP) log_debug ("slot %d app %s: calling auth(%s)\n", card->slot, xstrapptype (card->app), keyidstr); - err = card->app->fnc.auth (card->app, ctrl, keyidstr, - pincb, pincb_arg, - indata, indatalen, - outdata, outdatalen); + if (card->app->need_reset) + err = gpg_error (GPG_ERR_CARD_RESET); + else + err = card->app->fnc.auth (card->app, ctrl, keyidstr, + pincb, pincb_arg, + indata, indatalen, + outdata, outdatalen); } unlock_card (card); @@ -1910,11 +1945,14 @@ app_decipher (card_t card, ctrl_t ctrl, const char *keyidstr, if (DBG_APP) log_debug ("slot %d app %s: calling decipher(%s)\n", card->slot, xstrapptype (card->app), keyidstr); - err = card->app->fnc.decipher (card->app, ctrl, keyidstr, - pincb, pincb_arg, - indata, indatalen, - outdata, outdatalen, - r_info); + if (card->app->need_reset) + err = gpg_error (GPG_ERR_CARD_RESET); + else + err = card->app->fnc.decipher (card->app, ctrl, keyidstr, + pincb, pincb_arg, + indata, indatalen, + outdata, outdatalen, + r_info); } unlock_card (card); @@ -1949,8 +1987,11 @@ app_writecert (card_t card, ctrl_t ctrl, if (DBG_APP) log_debug ("slot %d app %s: calling writecert(%s)\n", card->slot, xstrapptype (card->app), certidstr); - err = card->app->fnc.writecert (card->app, ctrl, certidstr, - pincb, pincb_arg, data, datalen); + if (card->app->need_reset) + err = gpg_error (GPG_ERR_CARD_RESET); + else + err = card->app->fnc.writecert (card->app, ctrl, certidstr, + pincb, pincb_arg, data, datalen); } unlock_card (card); @@ -1985,8 +2026,11 @@ app_writekey (card_t card, ctrl_t ctrl, if (DBG_APP) log_debug ("slot %d app %s: calling writekey(%s)\n", card->slot, xstrapptype (card->app), keyidstr); - err = card->app->fnc.writekey (card->app, ctrl, keyidstr, flags, - pincb, pincb_arg, keydata, keydatalen); + if (card->app->need_reset) + err = gpg_error (GPG_ERR_CARD_RESET); + else + err = card->app->fnc.writekey (card->app, ctrl, keyidstr, flags, + pincb, pincb_arg, keydata, keydatalen); } unlock_card (card); @@ -2020,8 +2064,11 @@ app_genkey (card_t card, ctrl_t ctrl, const char *keynostr, if (DBG_APP) log_debug ("slot %d app %s: calling genkey(%s)\n", card->slot, xstrapptype (card->app), keynostr); - err = card->app->fnc.genkey (card->app, ctrl, keynostr, keytype, flags, - createtime, pincb, pincb_arg); + if (card->app->need_reset) + err = gpg_error (GPG_ERR_CARD_RESET); + else + err = card->app->fnc.genkey (card->app, ctrl, keynostr, keytype, flags, + createtime, pincb, pincb_arg); } unlock_card (card); @@ -2080,8 +2127,11 @@ app_change_pin (card_t card, ctrl_t ctrl, const char *chvnostr, if (DBG_APP) log_debug ("slot %d app %s: calling change_pin(%s)\n", card->slot, xstrapptype (card->app), chvnostr); - err = card->app->fnc.change_pin (card->app, ctrl, - chvnostr, flags, pincb, pincb_arg); + if (card->app->need_reset) + err = gpg_error (GPG_ERR_CARD_RESET); + else + err = card->app->fnc.change_pin (card->app, ctrl, + chvnostr, flags, pincb, pincb_arg); } unlock_card (card); @@ -2116,8 +2166,11 @@ app_check_pin (card_t card, ctrl_t ctrl, const char *keyidstr, if (DBG_APP) log_debug ("slot %d app %s: calling check_pin(%s)\n", card->slot, xstrapptype (card->app), keyidstr); - err = card->app->fnc.check_pin (card->app, ctrl, keyidstr, - pincb, pincb_arg); + if (card->app->need_reset) + err = gpg_error (GPG_ERR_CARD_RESET); + else + err = card->app->fnc.check_pin (card->app, ctrl, keyidstr, + pincb, pincb_arg); } unlock_card (card); @@ -2331,7 +2384,7 @@ send_serialno_and_app_status (card_t card, int with_apps, ctrl_t ctrl) put_membuf_str (&mb, serial); for (a = card->app; a; a = a->next) { - if (!a->fnc.with_keygrip) + if (!a->fnc.with_keygrip || a->need_reset) continue; any = 1; put_membuf (&mb, " ", 1); @@ -2517,7 +2570,7 @@ app_do_with_keygrip (ctrl_t ctrl, int action, const char *keygrip_str, a_prev = NULL; for (a = c->app; a; a = a->next) { - if (!a->fnc.with_keygrip) + if (!a->fnc.with_keygrip || a->need_reset) continue; /* Note that we need to do a re-select even for the current diff --git a/scd/command.c b/scd/command.c index 2be00bb40..fc1bb0145 100644 --- a/scd/command.c +++ b/scd/command.c @@ -420,7 +420,7 @@ cmd_switchapp (assuan_context_t ctx, char *line) static const char hlp_learn[] = - "LEARN [--force] [--keypairinfo] [--multi]\n" + "LEARN [--force] [--keypairinfo] [--reread] [--multi]\n" "\n" "Learn all useful information of the currently inserted card. When\n" "used without the force options, the command might do an INQUIRE\n" @@ -433,7 +433,8 @@ static const char hlp_learn[] = "error message.\n" "\n" "With the option --keypairinfo only KEYPAIRINFO status lines are\n" - "returned.\n" + "returned. With the option --reread information from the card are\n" + "read again without the need for a reset (sone some cards).\n" "\n" "The response of this command is a list of status lines formatted as\n" "this:\n" @@ -498,6 +499,8 @@ cmd_learn (assuan_context_t ctx, char *line) int rc = 0; int only_keypairinfo = has_option (line, "--keypairinfo"); int opt_multi = has_option (line, "--multi"); + int opt_reread = has_option (line, "--reread"); + unsigned int flags; if ((rc = open_card (ctrl))) return rc; @@ -559,11 +562,16 @@ cmd_learn (assuan_context_t ctx, char *line) /* Let the application print out its collection of useful status information. */ + flags = 0; + if (only_keypairinfo) + flags |= APP_LEARN_FLAG_KEYPAIRINFO; + if (opt_multi) + flags |= APP_LEARN_FLAG_MULTI; + if (opt_reread) + flags |= APP_LEARN_FLAG_REREAD; + if (!rc) - rc = app_write_learn_status - (ctrl->card_ctx, ctrl, - ( (only_keypairinfo? APP_LEARN_FLAG_KEYPAIRINFO : 0) - | (opt_multi? APP_LEARN_FLAG_MULTI : 0)) ); + rc = app_write_learn_status (ctrl->card_ctx, ctrl, flags); return rc; }