diff --git a/scd/app-common.h b/scd/app-common.h --- a/scd/app-common.h +++ b/scd/app-common.h @@ -186,14 +186,16 @@ gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg); gpg_error_t (*change_pin) (app_t app, ctrl_t ctrl, - const char *chvnostr, unsigned int flags, - gpg_error_t (*pincb)(void*, const char *, char **), - void *pincb_arg); + const char *chvnostr, unsigned int flags, + gpg_error_t (*pincb)(void*, const char *, char **), + void *pincb_arg); gpg_error_t (*check_pin) (app_t app, ctrl_t ctrl, const char *keyidstr, - gpg_error_t (*pincb)(void*, const char *, char **), - void *pincb_arg); + gpg_error_t (*pincb)(void*, const char *, char **), + void *pincb_arg); gpg_error_t (*with_keygrip) (app_t app, ctrl_t ctrl, int action, - const char *keygrip_str, int capability); + const char *keygrip_str, int capability); + gpg_error_t (*check_aid) (app_t app, ctrl_t ctrl, + const unsigned char *aid, size_t aidlen); } fnc; }; diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -6114,11 +6114,9 @@ (void)ctrl; - /* An extra check which should not be necessary because the caller - * should have made sure that a re-select is only called for - * appropriate cards. */ - if (APP_CARD(app)->cardtype != CARDTYPE_YUBIKEY) - return gpg_error (GPG_ERR_NOT_SUPPORTED); + /* All Card can be reselectioned without any problem + * This can slow down operation but if is bad applet + * it's OK because slow is more acceptable than error */ /* Note that the card can't cope with P2=0xCO, thus we need to pass * a special flag value. */ @@ -6134,6 +6132,17 @@ } +/* Check if AID is the correct one. */ +static gpg_error_t +do_check_aid (app_t app, ctrl_t ctrl, const unsigned char *aid, size_t aidlen) +{ + if (aidlen >= sizeof openpgp_aid + && memcmp (aid, openpgp_aid, sizeof openpgp_aid) == 0) + return 0; + + return gpg_error (GPG_ERR_WRONG_CARD); +} + /* Select the OpenPGP application on the card in SLOT. This function must be used before any other OpenPGP application functions. */ gpg_error_t @@ -6322,6 +6331,7 @@ app->fnc.change_pin = do_change_pin; app->fnc.check_pin = do_check_pin; app->fnc.with_keygrip = do_with_keygrip; + app->fnc.check_aid = do_check_aid; } leave: diff --git a/scd/app-piv.c b/scd/app-piv.c --- a/scd/app-piv.c +++ b/scd/app-piv.c @@ -3597,18 +3597,23 @@ (void)ctrl; - /* An extra check which should not be necessary because the caller - * should have made sure that a re-select is only called for - * appropriate cards. */ - if (!app->app_local->flags.yubikey) - return gpg_error (GPG_ERR_NOT_SUPPORTED); - err = iso7816_select_application (app_get_slot (app), piv_aid, sizeof piv_aid, 0x0001); return err; } +/* Check if AID is the correct one. */ +static gpg_error_t +do_check_aid (app_t app, ctrl_t ctrl, const unsigned char *aid, size_t aidlen) +{ + if (aidlen >= sizeof piv_aid + && memcmp (aid, piv_aid, sizeof piv_aid) == 0) + return 0; + + return gpg_error (GPG_ERR_WRONG_CARD); +} + /* Select the PIV application on the card in SLOT. This function must * be used before any other PIV application functions. */ gpg_error_t @@ -3713,7 +3718,7 @@ app->fnc.change_pin = do_change_chv; app->fnc.check_pin = do_check_chv; app->fnc.with_keygrip = do_with_keygrip; - + app->fnc.check_aid = do_check_aid; leave: xfree (apt); diff --git a/scd/app.c b/scd/app.c --- a/scd/app.c +++ b/scd/app.c @@ -1435,6 +1435,45 @@ } +/* + * Check external interference before each use of the application on + * card. Returns -1 when detecting some external interference. + * Returns 0 if not. + * + * Note: This kind of detection can't be perfect. At most, it may be + * possibly useful kludge, in some limited situations. + */ +static int +check_external_interference (app_t app, ctrl_t ctrl) +{ + /* + * Only when a user is using Yubikey with pcsc-shared configuration, + * we need this detection. Otherwise, the card/token is under full + * control of scdaemon, there's no problem at all. + */ + if (!opt.pcsc_shared) + return 0; + + if (app->fnc.check_aid) + { + unsigned char *aid; + size_t aidlen; + gpg_error_t err; + int slot = app_get_slot (app); + + err = iso7816_get_data (slot, 0, 0x004F, &aid, &aidlen); + if (err) + return -1; + + err = app->fnc.check_aid (app, ctrl, aid, aidlen); + xfree (aid); + if (err) + return -1; + } + + return 0; +} + /* Check that the card has been initialized and whether we need to * switch to another application on the same card. Switching means * that the new active app will be moved to the head of the list at @@ -1459,6 +1498,17 @@ ctrl->current_apptype = card->app->apptype; return 0; } + + /* This validate for interference before to be able to swith beteween + apps on the card. If it not possible to reselect the current apps + on card it's a bad card */ + if (check_external_interference (card->app, ctrl) != 0) + { + err = run_reselect (ctrl, card, card->app, card->app); + if (!err) + return err; + } + for (app = card->app; app; app = app->next) if (app->apptype == ctrl->current_apptype) break;