From 9325c92284bb346d11c3591bb2ea88095989361a Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 29 Jan 2019 09:30:15 +0100 Subject: [PATCH] card: Print keyinfo for PIV cards. * scd/app-piv.c (do_learn_status): Print CHV-STATUS. * tools/card-tool.h (struct card_info_s): Rename chvretry to chvinfo. * tools/card-call-scd.c (learn_status_cb): Depend CHV-STATUS on app type. * tools/gpg-card-tool.c (list_piv): New. Signed-off-by: Werner Koch --- scd/app-piv.c | 5 ++++- tools/card-call-scd.c | 24 ++++++++++++++++++++---- tools/card-tool.h | 10 +++++----- tools/gpg-card-tool.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 70 insertions(+), 12 deletions(-) diff --git a/scd/app-piv.c b/scd/app-piv.c index 011b55229..69f12f43a 100644 --- a/scd/app-piv.c +++ b/scd/app-piv.c @@ -569,7 +569,7 @@ send_keypair_and_cert_info (app_t app, ctrl_t ctrl, data_object_t dobj, } -/* Handle the LEARN command for OpenPGP. */ +/* Handle the LEARN command. */ static gpg_error_t do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) { @@ -577,10 +577,13 @@ do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) (void)flags; + do_getattr (app, ctrl, "CHV-STATUS"); + for (i=0; data_objects[i].tag; i++) if (data_objects[i].keypair) send_keypair_and_cert_info (app, ctrl, data_objects + i, !!(flags & 1)); + return 0; } diff --git a/tools/card-call-scd.c b/tools/card-call-scd.c index abf35ed17..2551b19f6 100644 --- a/tools/card-call-scd.c +++ b/tools/card-call-scd.c @@ -808,9 +808,13 @@ learn_status_cb (void *opaque, const char *line) buf = p = unescape_status_string (line); if (buf) + while (spacep (p)) + p++; + + if (!buf) + ; + else if (parm->apptype == APP_TYPE_OPENPGP) { - while (spacep (p)) - p++; parm->chv1_cached = atoi (p); while (*p && !spacep (p)) p++; @@ -826,14 +830,26 @@ learn_status_cb (void *opaque, const char *line) } for (i=0; *p && i < 3; i++) { - parm->chvretry[i] = atoi (p); + parm->chvinfo[i] = atoi (p); while (*p && !spacep (p)) p++; while (spacep (p)) p++; } - xfree (buf); } + else if (parm->apptype == APP_TYPE_PIV) + { + for (i=0; *p && DIM (parm->chvinfo); i++) + { + parm->chvinfo[i] = atoi (p); + while (*p && !spacep (p)) + p++; + while (spacep (p)) + p++; + } + } + + xfree (buf); } break; diff --git a/tools/card-tool.h b/tools/card-tool.h index 0af618676..bcc257ce2 100644 --- a/tools/card-tool.h +++ b/tools/card-tool.h @@ -122,12 +122,12 @@ struct card_info_s char cafpr3[20]; key_info_t kinfo; /* Linked list with all keypair related data. */ unsigned long sig_counter; - int chv1_cached; /* True if a PIN is not required for each - signing. Note that the gpg-agent might cache - it anyway. */ - int is_v2; /* True if this is a v2 card. */ + int chv1_cached; /* For openpgp this is true if a PIN is not + required for each signing. Note that the + gpg-agent might cache it anyway. */ + int is_v2; /* True if this is a v2 openpgp card. */ int chvmaxlen[3]; /* Maximum allowed length of a CHV. */ - int chvretry[3]; /* Allowed retries for the CHV; 0 = blocked. */ + int chvinfo[3]; /* Allowed retries for the CHV; 0 = blocked. */ struct key_attr key_attr[3]; /* OpenPGP card key attributes. */ struct { unsigned int ki:1; /* Key import available. */ diff --git a/tools/gpg-card-tool.c b/tools/gpg-card-tool.c index 31d9c220e..5ba44fcbb 100644 --- a/tools/gpg-card-tool.c +++ b/tools/gpg-card-tool.c @@ -723,7 +723,7 @@ list_openpgp (card_info_t info, estream_t fp) tty_fprintf (fp, "Max. PIN lengths .: %d %d %d\n", info->chvmaxlen[0], info->chvmaxlen[1], info->chvmaxlen[2]); tty_fprintf (fp, "PIN retry counter : %d %d %d\n", - info->chvretry[0], info->chvretry[1], info->chvretry[2]); + info->chvinfo[0], info->chvinfo[1], info->chvinfo[2]); tty_fprintf (fp, "Signature counter : %lu\n", info->sig_counter); if (info->extcap.kdf) { @@ -758,6 +758,44 @@ list_openpgp (card_info_t info, estream_t fp) } +/* List PIV card specific data. */ +static void +list_piv (card_info_t info, estream_t fp) +{ + static struct keyinfolabel_s keyinfolabels[] = { + { "PIV Authentication:", "PIV.9A" }, + { "Card Authenticat. :", "PIV.9E" }, + { "Digital Signature :", "PIV.9C" }, + { "Key Management ...:", "PIV.9D" }, + { NULL, NULL } + }; + const char *s; + int i; + + tty_fprintf (fp, "PIN retry counter :"); + for (i=0; i < DIM (info->chvinfo); i++) + { + if (info->chvinfo[i] > 0) + tty_fprintf (fp, " %d", info->chvinfo[i]); + else + { + switch (info->chvinfo[i]) + { + case -1: s = "[error]"; break; + case -2: s = "-"; break; /* No such PIN */ + case -3: s = "[blocked]"; break; + case -5: s = "[verified]"; break; + default: s = "[?]"; break; + } + tty_fprintf (fp, " %s", s); + } + } + tty_fprintf (fp, "\n", s); + list_all_kinfo (info, keyinfolabels, fp); + +} + + /* Print all available information about the current card. */ static void list_card (card_info_t info) @@ -781,6 +819,7 @@ list_card (card_info_t info) switch (info->apptype) { case APP_TYPE_OPENPGP: list_openpgp (info, fp); break; + case APP_TYPE_PIV: list_piv (info, fp); break; default: break; } } @@ -1740,7 +1779,7 @@ cmd_unblock (card_info_t info) if (info->apptype == APP_TYPE_OPENPGP && !info->is_v2) log_error (_("This command is only available for version 2 cards\n")); - else if (info->apptype == APP_TYPE_OPENPGP && !info->chvretry[1]) + else if (info->apptype == APP_TYPE_OPENPGP && !info->chvinfo[1]) log_error (_("Reset Code not or not anymore available\n")); else if (info->apptype == APP_TYPE_OPENPGP) {