diff --git a/scd/app-common.h b/scd/app-common.h --- a/scd/app-common.h +++ b/scd/app-common.h @@ -194,6 +194,8 @@ void *pincb_arg); gpg_error_t (*with_keygrip) (app_t app, ctrl_t ctrl, int action, 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 @@ -6134,6 +6134,18 @@ } +/* 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 +6334,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 @@ -3609,6 +3609,18 @@ } +/* 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,6 +3725,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: diff --git a/scd/app.c b/scd/app.c --- a/scd/app.c +++ b/scd/app.c @@ -1435,6 +1435,46 @@ } +/* + * 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 || app->card->cardtype != CARDTYPE_YUBIKEY) + 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 @@ -1490,7 +1530,8 @@ if (app->apptype == apptype) break; if (!app_prev && ctrl->current_apptype == card->app->apptype) - return 0; /* Already the first app - no need to switch. */ + if (check_external_interference (app, ctrl) == 0) + return 0; /* Already the first app - no need to switch. */ } else if (strlen (keyref) == 40) { @@ -1503,7 +1544,8 @@ KEYGRIP_ACTION_LOOKUP, keyref, 0)) break; if (!app_prev && ctrl->current_apptype == card->app->apptype) - return 0; /* Already the first app - no need to switch. */ + if (check_external_interference (app, ctrl) == 0) + return 0; /* Already the first app - no need to switch. */ } }