From 8d4af54ddd039d47e9c4803559193fcca97f0a46 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 5 Mar 2019 17:40:08 +0100 Subject: [PATCH] card: Print card version. Check for bad Yubikeys. * scd/app.c (app_new_register): Set card version for Yubikeys. (app_write_learn_status): Print CARDVERSION and APPVERSION. * tools/card-call-scd.c (learn_status_cb): Detect them. * tools/gpg-card.h (struct card_info_s): Add appversion and cardversion. * tools/gpg-card.c (list_openpgp): Remove version printing from serial number. (print_a_version): New. (list_card): Print card and app version. (cmd_generate): Do not allow broken Yubikeys. Signed-off-by: Werner Koch --- scd/app.c | 20 +++++++++++++++----- scd/command.c | 2 +- tools/card-call-scd.c | 16 +++++++++++++++- tools/gpg-card.c | 40 ++++++++++++++++++++++++++++++++++------ tools/gpg-card.h | 2 ++ 5 files changed, 67 insertions(+), 13 deletions(-) diff --git a/scd/app.c b/scd/app.c index ada1eb963..2ee104d9e 100644 --- a/scd/app.c +++ b/scd/app.c @@ -263,6 +263,9 @@ app_new_register (int slot, ctrl_t ctrl, const char *name, * set the serial number. */ } } + s1 = find_tlv (buf+1, buflen-1, 0x05, &n); /* version */ + if (s1 && n == 3) + app->cardversion = ((s1[0]<<16)|(s1[1]<<8)|s1[2]); } } xfree (buf); @@ -632,7 +635,7 @@ app_get_serialno (app_t app) } -/* Write out the application specifig status lines for the LEARN +/* Write out the application specific status lines for the LEARN command. */ gpg_error_t app_write_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) @@ -645,10 +648,17 @@ app_write_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); /* We do not send CARD and APPTYPE if only keypairinfo is requested. */ - if (app->cardtype && !(flags & 1)) - send_status_direct (ctrl, "CARDTYPE", app->cardtype); - if (app->apptype && !(flags & 1)) - send_status_direct (ctrl, "APPTYPE", app->apptype); + if (!(flags &1)) + { + if (app->cardtype) + send_status_direct (ctrl, "CARDTYPE", app->cardtype); + if (app->cardversion) + send_status_printf (ctrl, "CARDVERSION", "%X", app->cardversion); + if (app->apptype) + send_status_direct (ctrl, "APPTYPE", app->apptype); + if (app->appversion) + send_status_printf (ctrl, "APPVERSION", "%X", app->appversion); + } err = lock_app (app, ctrl); if (err) diff --git a/scd/command.c b/scd/command.c index 5b2ca6c29..0d1a5cd3f 100644 --- a/scd/command.c +++ b/scd/command.c @@ -1120,7 +1120,7 @@ static const char hlp_genkey[] = "\n" " 'p' and 'n' are the names of the RSA parameters; '-' is used to\n" " indicate that HEXDATA is the first chunk of a parameter given\n" - " by the next KEY-DATA.\n" + " by the next KEY-DATA. Only used by GnuPG version < 2.1.\n" "\n" "--force is required to overwrite an already existing key. The\n" "KEY-CREATED-AT is required for further processing because it is\n" diff --git a/tools/card-call-scd.c b/tools/card-call-scd.c index f7dbfd6ec..0a01bf5ca 100644 --- a/tools/card-call-scd.c +++ b/tools/card-call-scd.c @@ -818,7 +818,7 @@ learn_status_cb (void *opaque, const char *line) parm->chvusage[0] = byte1; parm->chvusage[1] = byte2; } - break; + break; case 10: if (!memcmp (keyword, "PUBKEY-URL", keywordlen)) @@ -880,6 +880,13 @@ learn_status_cb (void *opaque, const char *line) xfree (buf); } + else if (!memcmp (keyword, "APPVERSION", keywordlen)) + { + unsigned int val = 0; + + sscanf (line, "%x", &val); + parm->appversion = val; + } break; case 11: @@ -944,6 +951,13 @@ learn_status_cb (void *opaque, const char *line) } } } + else if (!memcmp (keyword, "CARDVERSION", keywordlen)) + { + unsigned int val = 0; + + sscanf (line, "%x", &val); + parm->cardversion = val; + } break; case 12: diff --git a/tools/gpg-card.c b/tools/gpg-card.c index bd450c0bb..89cefdeb6 100644 --- a/tools/gpg-card.c +++ b/tools/gpg-card.c @@ -781,11 +781,6 @@ list_openpgp (card_info_t info, estream_t fp) return; } - tty_fprintf (fp, "Version ..........: %.1s%c.%.1s%c\n", - info->serialno[12] == '0'?"":info->serialno+12, - info->serialno[13], - info->serialno[14] == '0'?"":info->serialno+14, - info->serialno[15]); tty_fprintf (fp, "Manufacturer .....: %s\n", get_manufacturer (xtoi_2(info->serialno+16)*256 + xtoi_2 (info->serialno+18))); @@ -941,6 +936,25 @@ list_piv (card_info_t info, estream_t fp) } + +static void +print_a_version (estream_t fp, const char *prefix, unsigned int value) +{ + unsigned int a, b, c, d; + a = ((value >> 24) & 0xff); + b = ((value >> 16) & 0xff); + c = ((value >> 8) & 0xff); + d = ((value ) & 0xff); + + if (a) + tty_fprintf (fp, "%s %u.%u.%u.%u\n", prefix, a, b, c, d); + else if (b) + tty_fprintf (fp, "%s %u.%u.%u\n", prefix, b, c, d); + else + tty_fprintf (fp, "%s %u.%u\n", prefix, c, d); +} + + /* Print all available information about the current card. */ static void list_card (card_info_t info) @@ -951,6 +965,8 @@ list_card (card_info_t info) info->reader? info->reader : "[none]"); if (info->cardtype) tty_fprintf (fp, "Card type ........: %s\n", info->cardtype); + if (info->cardversion) + print_a_version (fp, "Card firmware ....:", info->cardversion); tty_fprintf (fp, "Serial number ....: %s\n", info->serialno? info->serialno : "[none]"); tty_fprintf (fp, "Application type .: %s%s%s%s\n", @@ -959,9 +975,11 @@ list_card (card_info_t info) info->apptype == APP_TYPE_UNKNOWN && info->apptypestr ? info->apptypestr:"", info->apptype == APP_TYPE_UNKNOWN && info->apptypestr? ")":""); + if (info->appversion) + print_a_version (fp, "Version ..........:", info->appversion); if (info->serialno && info->dispserialno && strcmp (info->serialno, info->dispserialno)) - tty_fprintf (fp, "Displayed S/N ....: %s\n", info->dispserialno); + tty_fprintf (fp, "Displayed s/n ....: %s\n", info->dispserialno); switch (info->apptype) { @@ -2044,6 +2062,16 @@ cmd_generate (card_info_t info, char *argstr) keyref = keyref_buffer; } + /* Special checks. */ + if ((info->cardtype && !strcmp (info->cardtype, "yubikey")) + && info->cardversion >= 0x040200 && info->cardversion < 0x040305) + { + log_error ("On-chip key generation on this YubiKey has been blocked.\n"); + log_info ("Please see for details\n"); + err = gpg_error (GPG_ERR_NOT_SUPPORTED); + goto leave; + } + /* Divert to dedicated functions. */ if (info->apptype == APP_TYPE_OPENPGP) { diff --git a/tools/gpg-card.h b/tools/gpg-card.h index 3a86a67ec..099ea5448 100644 --- a/tools/gpg-card.h +++ b/tools/gpg-card.h @@ -142,8 +142,10 @@ struct card_info_s int error; /* private. */ char *reader; /* Reader information. */ char *cardtype; /* NULL or type of the card. */ + unsigned int cardversion; /* Firmware version of the card. */ char *apptypestr; /* Malloced application type string. */ app_type_t apptype;/* Translated from APPTYPESTR. */ + unsigned int appversion; /* Version of the application. */ char *serialno; /* malloced hex string. */ char *dispserialno;/* malloced string. */ char *disp_name; /* malloced. */