1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-04-17 15:44:34 +02:00

gpg: Use "SCD KEYINFO" to get available card keys.

* g10/skclist.c (enum_secret_keys): Don't use agent_scd_cardlist and
agent_scd_serialno, but agent_scd_keyinfo.

--

When there are multiple cards/tokens, this change can avoid switching
card of foreground access.

GnuPG-bug-id: 4784
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2020-01-16 13:05:27 +09:00
parent 8240a70c31
commit 8edd4b8b8c

View File

@ -330,10 +330,9 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk)
int eof; int eof;
int state; int state;
strlist_t sl; strlist_t sl;
strlist_t card_list; struct card_key_info_s *card_keyinfo;
char *serialno; struct card_key_info_s *card_keyinfo_list;
char fpr2[2 * MAX_FINGERPRINT_LEN + 3 ]; char fpr2[2 * MAX_FINGERPRINT_LEN + 2 ];
struct agent_card_info_s info;
kbnode_t keyblock; kbnode_t keyblock;
kbnode_t node; kbnode_t node;
getkey_ctx_t ctx; getkey_ctx_t ctx;
@ -360,8 +359,7 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk)
if (!sk) if (!sk)
{ {
/* Free the context. */ /* Free the context. */
xfree (c->serialno); agent_scd_free_keyinfo (c->card_keyinfo_list);
free_strlist (c->card_list);
release_sk_list (c->results); release_sk_list (c->results);
release_kbnode (c->keyblock); release_kbnode (c->keyblock);
getkey_end (ctrl, c->ctx); getkey_end (ctrl, c->ctx);
@ -411,87 +409,38 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk)
break; break;
case 3: /* Init list of card keys to try. */ case 3: /* Init list of card keys to try. */
err = agent_scd_cardlist (&c->card_list); c->card_keyinfo_list = NULL;
err = agent_scd_serialno (&serialno, NULL);
if (!err) if (!err)
agent_scd_serialno (&c->serialno, NULL); {
c->sl = c->card_list; xfree (serialno);
err = agent_scd_keyinfo (NULL, GCRY_PK_USAGE_ENCR,
&c->card_keyinfo_list);
}
c->card_keyinfo = c->card_keyinfo_list;
c->state++; c->state++;
break; break;
case 4: /* Get next item from card list. */ case 4: /* Get next item from card keyinfo. */
if (c->sl) if (c->card_keyinfo)
{ {
err = agent_scd_serialno (&serialno, c->sl->d); const char *s;
if (err) int i;
{
if (opt.verbose)
log_info (_("error getting serial number of card: %s\n"),
gpg_strerror (err));
c->sl = c->sl->next;
continue;
}
xfree (serialno); /* Get the key using the keygrip. */
c->info.fpr2len = 0; c->fpr2[0] = '&';
err = agent_scd_getattr ("KEY-FPR", &c->info); for (i=1, s = c->card_keyinfo->keygrip;
if (!err) (*s && *s != ' '
{ && i < sizeof c->fpr2 - 2);
if (c->info.fpr2len) s++, i++)
{ c->fpr2[i] = *s;
c->fpr2[0] = '0'; c->fpr2[i] = 0;
c->fpr2[1] = 'x'; name = c->fpr2;
bin2hex (c->info.fpr2, sizeof c->info.fpr2,
c->fpr2 + 2);
name = c->fpr2;
}
}
else if (gpg_err_code (err) == GPG_ERR_INV_NAME)
{
/* KEY-FPR not supported by the card - get
* the key using the keygrip. */
char *keyref;
strlist_t kplist;
const char *s;
int i;
err = agent_scd_getattr_one ("$ENCRKEYID", &keyref); c->card_keyinfo = c->card_keyinfo->next;
if (!err)
{
err = agent_scd_keypairinfo (ctrl, keyref,
&kplist);
if (!err)
{
c->fpr2[0] = '&';
for (i=1, s=kplist->d;
(*s && *s != ' '
&& i < sizeof c->fpr2 - 3);
s++, i++)
c->fpr2[i] = *s;
c->fpr2[i] = 0;
name = c->fpr2;
free_strlist (kplist);
}
xfree (keyref);
}
}
if (err)
log_error ("error retrieving key from card: %s\n",
gpg_strerror (err));
c->sl = c->sl->next;
} }
else else
{ c->state++;
serialno = c->serialno;
if (serialno)
{
/* Select the original card again. */
agent_scd_serialno (&c->serialno, serialno);
xfree (serialno);
}
c->state++;
}
break; break;
case 5: /* Init search context to enum all secret keys. */ case 5: /* Init search context to enum all secret keys. */