scd: Handle Yubikey's multiple apps and serialno.

* scd/app-common.h (yubikey_get_serialno): New.
* scd/app-openpgp.c (yubikey_get_serialno): New.
* scd/app.c (card_get_serialno): Use OpenPGP app's serialno,
when it's enabled for Yubikey.
(send_serialno_and_app_status): Use card_get_serialno, not
directly accessing ->serialno.

--

GnuPG-bug-id: 5100
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2020-10-23 16:31:03 +09:00
parent c8cc35dd2c
commit 2d4de4b6f0
3 changed files with 72 additions and 7 deletions

View File

@ -237,6 +237,7 @@ gpg_error_t app_send_card_list (ctrl_t ctrl);
gpg_error_t app_send_active_apps (card_t card, ctrl_t ctrl);
char *card_get_serialno (card_t card);
char *app_get_serialno (app_t app);
char *yubikey_get_serialno (app_t app);
void app_dump_state (void);
void application_notify_card_reset (int slot);

View File

@ -1383,6 +1383,39 @@ get_disp_name (app_t app)
}
/*
* Yubikey has its own serial number at app->serialno. When Yubikey
* is used for OpenPGP card app, we get the serial number for OpenPGP
* card from its AID data object.
*/
char *
yubikey_get_serialno (app_t app)
{
void *relptr;
unsigned char *buffer;
size_t buflen;
char *serial;
relptr = get_one_do (app, 0x004F, &buffer, &buflen, NULL);
if (!relptr)
return NULL;
if (buflen != 16)
{
xfree (relptr);
return NULL;
}
serial = xtrymalloc (32 + 1);
if (!serial)
return NULL;
serial[32] = 0;
bin2hex (buffer, buflen, serial);
xfree (relptr);
return serial;
}
/* Return the pretty formatted serialnumber. On error NULL is
* returned. */
static char *

View File

@ -1191,7 +1191,30 @@ card_get_serialno (card_t card)
if (!card->serialnolen)
serial = xtrystrdup ("FF7F00");
else if (card->cardtype == CARDTYPE_YUBIKEY)
{
app_t a;
for (a = card->app; a; a = a->next)
if (a->apptype == APPTYPE_OPENPGP)
break;
/* Found the OpenPGP app */
if (a->apptype == APPTYPE_OPENPGP)
{
if (card->app != a)
run_reselect (NULL, card, a, card->app);
serial = yubikey_get_serialno (a);
if (card->app != a)
run_reselect (NULL, card, card->app, a);
}
else
goto other;
}
else
other:
serial = bin2hex (card->serialno, card->serialnolen, NULL);
return serial;
@ -2107,15 +2130,15 @@ send_serialno_and_app_status (card_t card, int with_apps, ctrl_t ctrl)
{
gpg_error_t err;
app_t a;
char buf[65];
char *serial;
char *p;
membuf_t mb;
int any = 0;
if (DIM (buf) < 2 * card->serialnolen + 1)
serial = card_get_serialno (card);
if (!serial)
return 0; /* Oops. */
bin2hex (card->serialno, card->serialnolen, buf);
if (with_apps)
{
/* Note that in case the additional applications have not yet been
@ -2123,10 +2146,13 @@ send_serialno_and_app_status (card_t card, int with_apps, ctrl_t ctrl)
* "SERIALNO --all", we do that here. */
err = select_all_additional_applications_internal (ctrl, card);
if (err)
return err;
{
xfree (serial);
return err;
}
init_membuf (&mb, 256);
put_membuf_str (&mb, buf);
put_membuf_str (&mb, serial);
for (a = card->app; a; a = a->next)
{
if (!a->fnc.with_keygrip)
@ -2145,13 +2171,18 @@ send_serialno_and_app_status (card_t card, int with_apps, ctrl_t ctrl)
put_membuf (&mb, "", 1);
p = get_membuf (&mb, NULL);
if (!p)
return gpg_error_from_syserror ();
{
err = gpg_error_from_syserror ();
xfree (serial);
return err;
}
send_status_direct (ctrl, "SERIALNO", p);
xfree (p);
}
else
send_status_direct (ctrl, "SERIALNO", buf);
send_status_direct (ctrl, "SERIALNO", serial);
xfree (serial);
return 0;
}