mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-31 11:41:32 +01:00
scd: Add an re-select mechanism to switch apps.
* scd/app-common.h (struct app_ctx_s): Add func ptr 'reselect'. * scd/app-piv.c (do_reselect): New. (app_select_piv): Move AID constant to file scope. * scd/app-openpgp.c (do_reselect): New. (app_select_openpgp): Move AID constant to file scope. * scd/app.c (apptype_from_name): New. (check_application_conflict): Check against all apps of the card. Always set current_apptype. (select_additional_application): New. (maybe_switch_app): New. (app_write_learn_status, app_readcert, app_readkey, app_getattr) (app_setattr, app_sign, app_auth, app_decipher, app_writecert) (app_writekey, app_genkey, app_change_pin, app_check_pin): Use it here. (app_do_with_keygrip): Force reselect on success. (app_new_register): Move setting of CURRENT_APPTYPE to ... (select_application): here so that it will be set to the requested card. * scd/command.c (open_card_with_request): Select additional application if possible. -- Noet that we will likely need to rework this even more so to get well defined semantics for card access. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
d7d1ff4557
commit
d803b3bb3c
@ -132,6 +132,7 @@ struct app_ctx_s {
|
||||
struct app_local_s *app_local; /* Local to the application. */
|
||||
struct {
|
||||
void (*deinit) (app_t app);
|
||||
gpg_error_t (*reselect) (app_t app, ctrl_t ctrl);
|
||||
gpg_error_t (*learn_status) (app_t app, ctrl_t ctrl, unsigned int flags);
|
||||
gpg_error_t (*readcert) (app_t app, const char *certid,
|
||||
unsigned char **cert, size_t *certlen);
|
||||
@ -233,6 +234,7 @@ gpg_error_t card_reset (card_t card, ctrl_t ctrl, int send_reset);
|
||||
gpg_error_t select_application (ctrl_t ctrl, const char *name, card_t *r_app,
|
||||
int scan, const unsigned char *serialno_bin,
|
||||
size_t serialno_bin_len);
|
||||
gpg_error_t select_additional_application (ctrl_t ctrl, const char *name);
|
||||
char *get_supported_applications (void);
|
||||
|
||||
card_t card_ref (card_t card);
|
||||
|
@ -557,6 +557,7 @@ app_select_dinsig (app_t app)
|
||||
{
|
||||
app->apptype = APPTYPE_DINSIG;
|
||||
|
||||
app->fnc.reselect = NULL;
|
||||
app->fnc.learn_status = do_learn_status;
|
||||
app->fnc.readcert = do_readcert;
|
||||
app->fnc.getattr = NULL;
|
||||
|
@ -313,6 +313,7 @@ app_select_geldkarte (app_t app)
|
||||
|
||||
app->apptype = APPTYPE_GELDKARTE;
|
||||
app->fnc.deinit = do_deinit;
|
||||
app->fnc.reselect = NULL;
|
||||
|
||||
/* If we don't have a serialno yet construct it from the EF_ID. */
|
||||
if (!app->card->serialno)
|
||||
|
@ -1424,6 +1424,7 @@ app_select_nks (app_t app)
|
||||
log_info ("Detected NKS version: %d\n", app->app_local->nks_version);
|
||||
|
||||
app->fnc.deinit = do_deinit;
|
||||
app->fnc.reselect = NULL;
|
||||
app->fnc.learn_status = do_learn_status;
|
||||
app->fnc.readcert = do_readcert;
|
||||
app->fnc.readkey = do_readkey;
|
||||
|
@ -59,6 +59,11 @@
|
||||
#include "../common/openpgpdefs.h"
|
||||
|
||||
|
||||
|
||||
/* The AID of this application. */
|
||||
static char const openpgp_aid[] = { 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01 };
|
||||
|
||||
|
||||
/* A table describing the DOs of the card. */
|
||||
static struct {
|
||||
int tag;
|
||||
@ -5204,12 +5209,35 @@ parse_algorithm_attribute (app_t app, int keyno)
|
||||
xfree (relptr);
|
||||
}
|
||||
|
||||
|
||||
/* Reselect the application. This is used by cards which support
|
||||
* on-the-fly switching between applications. */
|
||||
static gpg_error_t
|
||||
do_reselect (app_t app, ctrl_t ctrl)
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
(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
|
||||
* approriate cards. */
|
||||
if (app->card->cardtype != CARDTYPE_YUBIKEY)
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
|
||||
/* Note that the card can't cope with P2=0xCO, thus we need to pass
|
||||
* a special flag value. */
|
||||
err = iso7816_select_application (app_get_slot (app),
|
||||
openpgp_aid, sizeof openpgp_aid, 0x0001);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Select the OpenPGP application on the card in SLOT. This function
|
||||
must be used before any other OpenPGP application functions. */
|
||||
gpg_error_t
|
||||
app_select_openpgp (app_t app)
|
||||
{
|
||||
static char const aid[] = { 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01 };
|
||||
int slot = app_get_slot (app);
|
||||
int rc;
|
||||
unsigned char *buffer;
|
||||
@ -5218,7 +5246,8 @@ app_select_openpgp (app_t app)
|
||||
|
||||
/* Note that the card can't cope with P2=0xCO, thus we need to pass a
|
||||
special flag value. */
|
||||
rc = iso7816_select_application (slot, aid, sizeof aid, 0x0001);
|
||||
rc = iso7816_select_application (slot,
|
||||
openpgp_aid, sizeof openpgp_aid, 0x0001);
|
||||
if (!rc)
|
||||
{
|
||||
unsigned int manufacturer;
|
||||
@ -5353,6 +5382,7 @@ app_select_openpgp (app_t app)
|
||||
dump_all_do (slot);
|
||||
|
||||
app->fnc.deinit = do_deinit;
|
||||
app->fnc.reselect = do_reselect;
|
||||
app->fnc.learn_status = do_learn_status;
|
||||
app->fnc.readcert = do_readcert;
|
||||
app->fnc.readkey = do_readkey;
|
||||
|
@ -3415,6 +3415,7 @@ app_select_p15 (app_t app)
|
||||
}
|
||||
|
||||
app->fnc.deinit = do_deinit;
|
||||
app->fnc.reselect = NULL;
|
||||
app->fnc.learn_status = do_learn_status;
|
||||
app->fnc.readcert = do_readcert;
|
||||
app->fnc.getattr = do_getattr;
|
||||
|
@ -81,6 +81,10 @@
|
||||
#define PIV_ALGORITHM_ECC_P384 0x14
|
||||
|
||||
|
||||
/* The AID for PIV. */
|
||||
static char const piv_aid[] = { 0xA0, 0x00, 0x00, 0x03, 0x08, /* RID=NIST */
|
||||
0x00, 0x00, 0x10, 0x00 /* PIX=PIV */ };
|
||||
|
||||
|
||||
/* A table describing the DOs of a PIV card. */
|
||||
struct data_object_s
|
||||
@ -3390,13 +3394,32 @@ do_with_keygrip (app_t app, ctrl_t ctrl, int action,
|
||||
}
|
||||
|
||||
|
||||
/* Reselect the application. This is used by cards which support
|
||||
* on-the-fly switching between applications. */
|
||||
static gpg_error_t
|
||||
do_reselect (app_t app, ctrl_t ctrl)
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
(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
|
||||
* approriate 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;
|
||||
}
|
||||
|
||||
|
||||
/* Select the PIV application on the card in SLOT. This function must
|
||||
* be used before any other PIV application functions. */
|
||||
gpg_error_t
|
||||
app_select_piv (app_t app)
|
||||
{
|
||||
static char const aid[] = { 0xA0, 0x00, 0x00, 0x03, 0x08, /* RID=NIST */
|
||||
0x00, 0x00, 0x10, 0x00 /* PIX=PIV */ };
|
||||
int slot = app_get_slot (app);
|
||||
gpg_error_t err;
|
||||
unsigned char *apt = NULL;
|
||||
@ -3407,7 +3430,7 @@ app_select_piv (app_t app)
|
||||
/* Note that we select using the AID without the 2 octet version
|
||||
* number. This allows for better reporting of future specs. We
|
||||
* need to use the use-zero-for-P2-flag. */
|
||||
err = iso7816_select_application_ext (slot, aid, sizeof aid, 0x0001,
|
||||
err = iso7816_select_application_ext (slot, piv_aid, sizeof piv_aid, 0x0001,
|
||||
&apt, &aptlen);
|
||||
if (err)
|
||||
goto leave;
|
||||
@ -3427,7 +3450,7 @@ app_select_piv (app_t app)
|
||||
}
|
||||
|
||||
s = find_tlv (apt, aptlen, 0x4F, &n);
|
||||
if (!s || n != 6 || memcmp (s, aid+5, 4))
|
||||
if (!s || n != 6 || memcmp (s, piv_aid+5, 4))
|
||||
{
|
||||
/* The PIX does not match. */
|
||||
log_error ("piv: missing or invalid DO 0x4F in APT\n");
|
||||
@ -3450,7 +3473,7 @@ app_select_piv (app_t app)
|
||||
goto leave;
|
||||
}
|
||||
s = find_tlv (s, n, 0x4F, &n);
|
||||
if (!s || n != 5 || memcmp (s, aid, 5))
|
||||
if (!s || n != 5 || memcmp (s, piv_aid, 5))
|
||||
{
|
||||
/* The RID does not match. */
|
||||
log_error ("piv: missing or invalid DO 0x79.4F in APT\n");
|
||||
@ -3475,6 +3498,7 @@ app_select_piv (app_t app)
|
||||
dump_all_do (slot);
|
||||
|
||||
app->fnc.deinit = do_deinit;
|
||||
app->fnc.reselect = do_reselect;
|
||||
app->fnc.learn_status = do_learn_status;
|
||||
app->fnc.readcert = do_readcert;
|
||||
app->fnc.readkey = do_readkey;
|
||||
|
@ -2069,6 +2069,7 @@ app_select_sc_hsm (app_t app)
|
||||
goto leave;
|
||||
|
||||
app->fnc.deinit = do_deinit;
|
||||
app->fnc.reselect = NULL;
|
||||
app->fnc.learn_status = do_learn_status;
|
||||
app->fnc.readcert = do_readcert;
|
||||
app->fnc.getattr = do_getattr;
|
||||
|
234
scd/app.c
234
scd/app.c
@ -91,6 +91,24 @@ strapptype (apptype_t t)
|
||||
}
|
||||
|
||||
|
||||
/* Return the apptype for NAME. */
|
||||
static apptype_t
|
||||
apptype_from_name (const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!name)
|
||||
return APPTYPE_NONE;
|
||||
|
||||
for (i=0; app_priority_list[i].apptype; i++)
|
||||
if (!ascii_strcasecmp (app_priority_list[i].name, name))
|
||||
return app_priority_list[i].apptype;
|
||||
if (!ascii_strcasecmp ("undefined", name))
|
||||
return APPTYPE_UNDEFINED;
|
||||
return APPTYPE_NONE;
|
||||
}
|
||||
|
||||
|
||||
/* Initialization function to change the default app_priority_list.
|
||||
* LIST is a list of comma or space separated strings with application
|
||||
* names. Unknown names will only result in warning message.
|
||||
@ -247,14 +265,18 @@ is_app_allowed (const char *name)
|
||||
gpg_error_t
|
||||
check_application_conflict (card_t card, const char *name)
|
||||
{
|
||||
app_t app;
|
||||
|
||||
if (!card || !name)
|
||||
return 0;
|
||||
if (!card->app)
|
||||
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); /* Should not happen. */
|
||||
|
||||
if (!card->app->apptype
|
||||
|| !ascii_strcasecmp (strapptype (card->app->apptype), name))
|
||||
return 0;
|
||||
/* Check whether the requested NAME matches any already selected
|
||||
* application. */
|
||||
for (app = card->app; app; app = app->next)
|
||||
if (!ascii_strcasecmp (strapptype (app->apptype), name))
|
||||
return 0;
|
||||
|
||||
if (card->app->apptype == APPTYPE_UNDEFINED)
|
||||
return 0;
|
||||
@ -535,10 +557,6 @@ app_new_register (int slot, ctrl_t ctrl, const char *name,
|
||||
card->next = card_top;
|
||||
card_top = card;
|
||||
|
||||
/* If no current apptype is known for this session, set it now. */
|
||||
if (!ctrl->current_apptype)
|
||||
ctrl->current_apptype = app->apptype;
|
||||
|
||||
unlock_card (card);
|
||||
return 0;
|
||||
}
|
||||
@ -632,7 +650,9 @@ select_application (ctrl_t ctrl, const char *name, card_t *r_card,
|
||||
card->next = card_top;
|
||||
card_top = card;
|
||||
}
|
||||
}
|
||||
|
||||
ctrl->current_apptype = card->app ? card->app->apptype : 0;
|
||||
}
|
||||
unlock_card (card);
|
||||
}
|
||||
else
|
||||
@ -644,6 +664,82 @@ select_application (ctrl_t ctrl, const char *name, card_t *r_card,
|
||||
}
|
||||
|
||||
|
||||
/* This function needs to be called with the NAME of the new
|
||||
* application to be selected on CARD. On success the application is
|
||||
* added to the list of the card's active applications as currently
|
||||
* active application. On error no new application is allocated.
|
||||
* Selecting an already selected application has no effect. */
|
||||
gpg_error_t
|
||||
select_additional_application (ctrl_t ctrl, const char *name)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
apptype_t req_apptype;
|
||||
card_t card;
|
||||
app_t app = NULL;
|
||||
int i;
|
||||
|
||||
req_apptype = apptype_from_name (name);
|
||||
if (!req_apptype)
|
||||
err = gpg_error (GPG_ERR_NOT_FOUND);
|
||||
|
||||
card = ctrl->card_ctx;
|
||||
if (!card)
|
||||
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
|
||||
err = lock_card (card, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Check that the requested app has not yet been put onto the list. */
|
||||
for (app = card->app; app; app = app->next)
|
||||
if (app->apptype == req_apptype)
|
||||
{
|
||||
/* We already got this one. Note that in this case we don't
|
||||
* make it the current one but it doesn't matter because
|
||||
* maybe_switch_app will do that anyway. */
|
||||
err = 0;
|
||||
app = NULL;
|
||||
goto leave;
|
||||
}
|
||||
app = NULL;
|
||||
|
||||
/* Allocate a new app object. */
|
||||
app = xtrycalloc (1, sizeof *app);
|
||||
if (!app)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_info ("error allocating app context: %s\n", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Find the app and run the select. */
|
||||
for (i=0; app_priority_list[i].apptype; i++)
|
||||
{
|
||||
if (app_priority_list[i].apptype == req_apptype
|
||||
&& is_app_allowed (app_priority_list[i].name))
|
||||
err = app_priority_list[i].select_func (app);
|
||||
}
|
||||
if (!app_priority_list[i].apptype
|
||||
|| (err && gpg_err_code (err) != GPG_ERR_OBJ_TERM_STATE))
|
||||
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
/* Add this app. We make it the current one to avoid an extra
|
||||
* reselect by maybe_switch_app after the select we just did. */
|
||||
app->next = card->app;
|
||||
card->app = app;
|
||||
ctrl->current_apptype = app->apptype;
|
||||
log_error ("added app '%s' to the card context\n", strapptype(app->apptype));
|
||||
|
||||
leave:
|
||||
unlock_card (card);
|
||||
xfree (app);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
get_supported_applications (void)
|
||||
{
|
||||
@ -831,6 +927,63 @@ app_get_serialno (app_t app)
|
||||
}
|
||||
|
||||
|
||||
/* 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
|
||||
* CARD->app. Thus function must be called with the card lock held. */
|
||||
static gpg_error_t
|
||||
maybe_switch_app (ctrl_t ctrl, card_t card)
|
||||
{
|
||||
gpg_error_t err;
|
||||
app_t app, app_prev;
|
||||
|
||||
if (!card->ref_count || !card->app)
|
||||
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
if (!ctrl->current_apptype)
|
||||
{
|
||||
/* For whatever reasons the current apptype has not been set -
|
||||
* fix that and use the current app. */
|
||||
ctrl->current_apptype = card->app->apptype;
|
||||
return 0;
|
||||
}
|
||||
log_debug ("card=%p want=%s card->app=%s\n",
|
||||
card, strapptype (ctrl->current_apptype),
|
||||
strapptype (card->app->apptype));
|
||||
app_dump_state ();
|
||||
if (ctrl->current_apptype == card->app->apptype)
|
||||
return 0; /* No need to switch. */
|
||||
app_prev = card->app;
|
||||
for (app = app_prev->next; app; app_prev = app, app = app->next)
|
||||
if (app->apptype == ctrl->current_apptype)
|
||||
break;
|
||||
if (!app)
|
||||
return gpg_error (GPG_ERR_WRONG_CARD);
|
||||
|
||||
if (!app->fnc.reselect)
|
||||
{
|
||||
log_error ("oops: reselect function missing for '%s'\n",
|
||||
strapptype(app->apptype));
|
||||
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
}
|
||||
err = app->fnc.reselect (app, ctrl);
|
||||
if (err)
|
||||
{
|
||||
log_error ("error re-selecting '%s': %s\n",
|
||||
strapptype(app->apptype), gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
/* Swap APP with the head of the app list. Note that APP is not the
|
||||
* head of the list. */
|
||||
app_prev->next = app->next;
|
||||
app->next = card->app;
|
||||
card->app = app;
|
||||
ctrl->current_apptype = app->apptype;
|
||||
log_error ("switched to '%s'\n", strapptype(app->apptype));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Write out the application specific status lines for the LEARN
|
||||
command. */
|
||||
gpg_error_t
|
||||
@ -846,13 +999,14 @@ app_write_learn_status (card_t card, ctrl_t ctrl, unsigned int flags)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
app = card->app;
|
||||
if (!app)
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
else if (!app->fnc.learn_status)
|
||||
if ((err = maybe_switch_app (ctrl, card)))
|
||||
;
|
||||
else if (!card->app->fnc.learn_status)
|
||||
err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
else
|
||||
{
|
||||
app = card->app;
|
||||
|
||||
/* We do not send CARD and APPTYPE if only keypairinfo is requested. */
|
||||
if (!(flags &1))
|
||||
{
|
||||
@ -891,8 +1045,8 @@ app_readcert (card_t card, ctrl_t ctrl, const char *certid,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!card->ref_count || !card->app)
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
if ((err = maybe_switch_app (ctrl, card)))
|
||||
;
|
||||
else if (!card->app->fnc.readcert)
|
||||
err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
else
|
||||
@ -928,8 +1082,8 @@ app_readkey (card_t card, ctrl_t ctrl, const char *keyid, unsigned int flags,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!card->ref_count || !card->app)
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
if ((err = maybe_switch_app (ctrl, card)))
|
||||
;
|
||||
else if (!card->app->fnc.readkey)
|
||||
err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
else
|
||||
@ -952,8 +1106,8 @@ app_getattr (card_t card, ctrl_t ctrl, const char *name)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!card->ref_count || !card->app)
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
if ((err = maybe_switch_app (ctrl, card)))
|
||||
;
|
||||
else if (name && !strcmp (name, "CARDTYPE"))
|
||||
{
|
||||
send_status_direct (ctrl, "CARDTYPE", strcardtype (card->cardtype));
|
||||
@ -1000,8 +1154,8 @@ app_setattr (card_t card, ctrl_t ctrl, const char *name,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!card->ref_count || !card->app)
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
if ((err = maybe_switch_app (ctrl, card)))
|
||||
;
|
||||
else if (!card->app->fnc.setattr)
|
||||
err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
else
|
||||
@ -1031,8 +1185,8 @@ app_sign (card_t card, ctrl_t ctrl, const char *keyidstr, int hashalgo,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!card->ref_count || !card->app)
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
if ((err = maybe_switch_app (ctrl, card)))
|
||||
;
|
||||
else if (!card->app->fnc.sign)
|
||||
err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
else
|
||||
@ -1067,8 +1221,8 @@ app_auth (card_t card, ctrl_t ctrl, const char *keyidstr,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!card->ref_count || !card->app)
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
if ((err = maybe_switch_app (ctrl, card)))
|
||||
;
|
||||
else if (!card->app->fnc.auth)
|
||||
err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
else
|
||||
@ -1105,8 +1259,8 @@ app_decipher (card_t card, ctrl_t ctrl, const char *keyidstr,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!card->ref_count || !card->app)
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
if ((err = maybe_switch_app (ctrl, card)))
|
||||
;
|
||||
else if (!card->app->fnc.decipher)
|
||||
err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
else
|
||||
@ -1139,8 +1293,8 @@ app_writecert (card_t card, ctrl_t ctrl,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!card->ref_count || !card->app)
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
if ((err = maybe_switch_app (ctrl, card)))
|
||||
;
|
||||
else if (!card->app->fnc.writecert)
|
||||
err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
else
|
||||
@ -1170,8 +1324,8 @@ app_writekey (card_t card, ctrl_t ctrl,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!card->ref_count || !card->app)
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
if ((err = maybe_switch_app (ctrl, card)))
|
||||
;
|
||||
else if (!card->app->fnc.writekey)
|
||||
err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
else
|
||||
@ -1200,8 +1354,8 @@ app_genkey (card_t card, ctrl_t ctrl, const char *keynostr,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!card->ref_count || !card->app)
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
if ((err = maybe_switch_app (ctrl, card)))
|
||||
;
|
||||
else if (!card->app->fnc.genkey)
|
||||
err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
else
|
||||
@ -1255,8 +1409,8 @@ app_change_pin (card_t card, ctrl_t ctrl, const char *chvnostr,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!card->ref_count || !card->app)
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
if ((err = maybe_switch_app (ctrl, card)))
|
||||
;
|
||||
else if (!card->app->fnc.change_pin)
|
||||
err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
else
|
||||
@ -1286,8 +1440,8 @@ app_check_pin (card_t card, ctrl_t ctrl, const char *keyidstr,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!card->ref_count || !card->app)
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
if ((err = maybe_switch_app (ctrl, card)))
|
||||
;
|
||||
else if (!card->app->fnc.check_pin)
|
||||
err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
else
|
||||
@ -1513,8 +1667,12 @@ app_do_with_keygrip (ctrl_t ctrl, int action, const char *keygrip_str)
|
||||
|
||||
/* FIXME: Add app switching logic. The above code assumes that the
|
||||
* actions can be performend without switching. This needs to be
|
||||
* checked. For a lookup we also need to reorder the apps so that
|
||||
* the selected one will be used. */
|
||||
* checked. */
|
||||
|
||||
/* Force switching of the app if the selected one is not the current
|
||||
* one. Changing the current apptype is sufficient to do this. */
|
||||
if (c && c->app && c->app->apptype != a->apptype)
|
||||
ctrl->current_apptype = a->apptype;
|
||||
|
||||
npth_mutex_unlock (&card_list_lock);
|
||||
return c;
|
||||
|
@ -231,9 +231,16 @@ open_card_with_request (ctrl_t ctrl,
|
||||
/* If we are already initialized for one specific application we
|
||||
need to check that the client didn't requested a specific
|
||||
application different from the one in use before we continue. */
|
||||
/* FIXME: Extend to allow switching between apps. */
|
||||
if (apptypestr && ctrl->card_ctx)
|
||||
return check_application_conflict (ctrl->card_ctx, apptypestr);
|
||||
{
|
||||
err = check_application_conflict (ctrl->card_ctx, apptypestr);
|
||||
if (gpg_err_code (err) == GPG_ERR_FALSE)
|
||||
{
|
||||
/* Different application but switching is supported. */
|
||||
err = select_additional_application (ctrl, apptypestr);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Re-scan USB devices. Release CARD, before the scan. */
|
||||
/* FIXME: Is a card_unref sufficient or do we need to deallocate? */
|
||||
@ -2084,7 +2091,6 @@ scd_clear_current_app (card_t card)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Send a line with status information via assuan and escape all given
|
||||
buffers. The variable elements are pairs of (char *, size_t),
|
||||
terminated with a (NULL, 0). */
|
||||
|
@ -107,7 +107,7 @@ struct server_control_s
|
||||
struct card_ctx_s *card_ctx;
|
||||
|
||||
/* The currently active application for this context. We need to
|
||||
* knw this for cards which are abale to swicth on the fly between
|
||||
* know this for cards which are able to switch on the fly between
|
||||
* apps. */
|
||||
apptype_t current_apptype;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user