aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2020-10-23 16:31:03 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2020-10-23 16:31:03 +0900
commit2d4de4b6f06c87cd0f72b2a0d09950e1b50841b2 (patch)
tree9faa40f8ed13ff74dea166d30f05fcfff67b31bb
parentc8cc35dd2c106d91a793667690c0b200560d5d2d (diff)
downloadgnupg-2d4de4b6f06c87cd0f72b2a0d09950e1b50841b2.tar.gz
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>
-rw-r--r--scd/app-common.h1
-rw-r--r--scd/app-openpgp.c33
-rw-r--r--scd/app.c45
3 files changed, 72 insertions, 7 deletions
diff --git a/scd/app-common.h b/scd/app-common.h
index d245b8b0a..a9a6bd065 100644
--- a/scd/app-common.h
+++ b/scd/app-common.h
@@ -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);
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 8085fa812..b75ee6457 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -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 *
diff --git a/scd/app.c b/scd/app.c
index 837738095..8f054a81f 100644
--- a/scd/app.c
+++ b/scd/app.c
@@ -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;
}