card: New option --shadow for command list.

* tools/card-call-scd.c (scd_readkey): Add arg create_shadow.
* tools/gpg-card.c (list_one_kinfo): Add arg create_shadow and pass it
down to scd-readkey.  Change all callers to convey this arg.
(cmd_list): Add option --shadow.
This commit is contained in:
Werner Koch 2021-04-21 21:03:57 +02:00
parent 8f2c9cb735
commit 2fce99d73a
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
3 changed files with 50 additions and 29 deletions

View File

@ -1511,9 +1511,10 @@ scd_readcert (const char *certidstr, void **r_buf, size_t *r_buflen)
/* Send a READKEY command to the SCdaemon. On success a new /* Send a READKEY command to the SCdaemon. On success a new
* s-expression is stored at R_RESULT. */ * s-expression is stored at R_RESULT. If CREATE_SHADOW is set stub
* keys will be created if they do not exist. */
gpg_error_t gpg_error_t
scd_readkey (const char *keyrefstr, gcry_sexp_t *r_result) scd_readkey (const char *keyrefstr, int create_shadow, gcry_sexp_t *r_result)
{ {
gpg_error_t err; gpg_error_t err;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
@ -1527,7 +1528,10 @@ scd_readkey (const char *keyrefstr, gcry_sexp_t *r_result)
return err; return err;
init_membuf (&data, 1024); init_membuf (&data, 1024);
snprintf (line, DIM(line), "SCD READKEY %s", keyrefstr); if (create_shadow)
snprintf (line, DIM(line), "READKEY --card -- %s", keyrefstr);
else
snprintf (line, DIM(line), "SCD READKEY %s", keyrefstr);
err = assuan_transact (agent_ctx, line, err = assuan_transact (agent_ctx, line,
put_membuf_cb, &data, put_membuf_cb, &data,
NULL, NULL, NULL, NULL,

View File

@ -1,5 +1,5 @@
/* gpg-card.c - An interactive tool to work with cards. /* gpg-card.c - An interactive tool to work with cards.
* Copyright (C) 2019, 2020 g10 Code GmbH * Copyright (C) 2019, 2020, 2021 g10 Code GmbH
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -657,7 +657,8 @@ mem_is_zero (const char *mem, unsigned int memlen)
* reference if no info is available; it may be NULL. */ * reference if no info is available; it may be NULL. */
static void static void
list_one_kinfo (card_info_t info, key_info_t kinfo, list_one_kinfo (card_info_t info, key_info_t kinfo,
const char *label_keyref, estream_t fp, int no_key_lookup) const char *label_keyref, estream_t fp, int no_key_lookup,
int create_shadow)
{ {
gpg_error_t err; gpg_error_t err;
key_info_t firstkinfo = info->kinfo; key_info_t firstkinfo = info->kinfo;
@ -705,7 +706,7 @@ list_one_kinfo (card_info_t info, key_info_t kinfo,
if (kinfo->label) if (kinfo->label)
tty_fprintf (fp, " label ......: %s\n", kinfo->label); tty_fprintf (fp, " label ......: %s\n", kinfo->label);
if (!(err = scd_readkey (kinfo->keyref, &s_pkey))) if (!(err = scd_readkey (kinfo->keyref, create_shadow, &s_pkey)))
{ {
char *tmp = pubkey_algo_string (s_pkey, NULL); char *tmp = pubkey_algo_string (s_pkey, NULL);
tty_fprintf (fp, " algorithm ..: %s\n", nullnone (tmp)); tty_fprintf (fp, " algorithm ..: %s\n", nullnone (tmp));
@ -813,7 +814,7 @@ list_one_kinfo (card_info_t info, key_info_t kinfo,
/* List all keyinfo in INFO using the list of LABELS. */ /* List all keyinfo in INFO using the list of LABELS. */
static void static void
list_all_kinfo (card_info_t info, keyinfolabel_t labels, estream_t fp, list_all_kinfo (card_info_t info, keyinfolabel_t labels, estream_t fp,
int no_key_lookup) int no_key_lookup, int create_shadow)
{ {
key_info_t kinfo; key_info_t kinfo;
int idx, i, j; int idx, i, j;
@ -829,7 +830,7 @@ list_all_kinfo (card_info_t info, keyinfolabel_t labels, estream_t fp,
tty_fprintf (fp, "%s", labels[idx].label); tty_fprintf (fp, "%s", labels[idx].label);
kinfo = find_kinfo (info, labels[idx].keyref); kinfo = find_kinfo (info, labels[idx].keyref);
list_one_kinfo (info, kinfo, labels[idx].keyref, list_one_kinfo (info, kinfo, labels[idx].keyref,
fp, no_key_lookup); fp, no_key_lookup, create_shadow);
if (kinfo) if (kinfo)
kinfo->xflag = 1; kinfo->xflag = 1;
} }
@ -842,7 +843,7 @@ list_all_kinfo (card_info_t info, keyinfolabel_t labels, estream_t fp,
for (i=4+strlen (kinfo->keyref), j=0; i < 18; i++, j=1) for (i=4+strlen (kinfo->keyref), j=0; i < 18; i++, j=1)
tty_fprintf (fp, j? ".":" "); tty_fprintf (fp, j? ".":" ");
tty_fprintf (fp, ":"); tty_fprintf (fp, ":");
list_one_kinfo (info, kinfo, NULL, fp, no_key_lookup); list_one_kinfo (info, kinfo, NULL, fp, no_key_lookup, create_shadow);
} }
} }
@ -880,7 +881,8 @@ list_retry_counter (card_info_t info, estream_t fp)
/* List OpenPGP card specific data. */ /* List OpenPGP card specific data. */
static void static void
list_openpgp (card_info_t info, estream_t fp, int no_key_lookup) list_openpgp (card_info_t info, estream_t fp,
int no_key_lookup, int create_shadow)
{ {
static struct keyinfolabel_s keyinfolabels[] = { static struct keyinfolabel_s keyinfolabels[] = {
{ "Signature key ....:", "OPENPGP.1" }, { "Signature key ....:", "OPENPGP.1" },
@ -958,14 +960,14 @@ list_openpgp (card_info_t info, estream_t fp, int no_key_lookup)
info->uif[2] ? (info->uif[0]==2? "permanent": "on") : "off"); info->uif[2] ? (info->uif[0]==2? "permanent": "on") : "off");
} }
list_all_kinfo (info, keyinfolabels, fp, no_key_lookup); list_all_kinfo (info, keyinfolabels, fp, no_key_lookup, create_shadow);
} }
/* List PIV card specific data. */ /* List PIV card specific data. */
static void static void
list_piv (card_info_t info, estream_t fp, int no_key_lookup) list_piv (card_info_t info, estream_t fp, int no_key_lookup, int create_shadow)
{ {
static struct keyinfolabel_s keyinfolabels[] = { static struct keyinfolabel_s keyinfolabels[] = {
{ "PIV authentication:", "PIV.9A" }, { "PIV authentication:", "PIV.9A" },
@ -998,33 +1000,33 @@ list_piv (card_info_t info, estream_t fp, int no_key_lookup)
} }
list_retry_counter (info, fp); list_retry_counter (info, fp);
list_all_kinfo (info, keyinfolabels, fp, no_key_lookup); list_all_kinfo (info, keyinfolabels, fp, no_key_lookup, create_shadow);
} }
/* List Netkey card specific data. */ /* List Netkey card specific data. */
static void static void
list_nks (card_info_t info, estream_t fp, int no_key_lookup) list_nks (card_info_t info, estream_t fp, int no_key_lookup, int create_shadow)
{ {
static struct keyinfolabel_s keyinfolabels[] = { static struct keyinfolabel_s keyinfolabels[] = {
{ NULL, NULL } { NULL, NULL }
}; };
list_retry_counter (info, fp); list_retry_counter (info, fp);
list_all_kinfo (info, keyinfolabels, fp, no_key_lookup); list_all_kinfo (info, keyinfolabels, fp, no_key_lookup, create_shadow);
} }
/* List PKCS#15 card specific data. */ /* List PKCS#15 card specific data. */
static void static void
list_p15 (card_info_t info, estream_t fp, int no_key_lookup) list_p15 (card_info_t info, estream_t fp, int no_key_lookup, int create_shadow)
{ {
static struct keyinfolabel_s keyinfolabels[] = { static struct keyinfolabel_s keyinfolabels[] = {
{ NULL, NULL } { NULL, NULL }
}; };
list_retry_counter (info, fp); list_retry_counter (info, fp);
list_all_kinfo (info, keyinfolabels, fp, no_key_lookup); list_all_kinfo (info, keyinfolabels, fp, no_key_lookup, create_shadow);
} }
@ -1052,7 +1054,7 @@ print_a_version (estream_t fp, const char *prefix, unsigned int value)
* NO_KEY_LOOKUP the sometimes expensive listing of all matching * NO_KEY_LOOKUP the sometimes expensive listing of all matching
* OpenPGP and X.509 keys is not done */ * OpenPGP and X.509 keys is not done */
static void static void
list_card (card_info_t info, int no_key_lookup) list_card (card_info_t info, int no_key_lookup, int create_shadow)
{ {
estream_t fp = opt.interactive? NULL : es_stdout; estream_t fp = opt.interactive? NULL : es_stdout;
@ -1084,10 +1086,18 @@ list_card (card_info_t info, int no_key_lookup)
switch (info->apptype) switch (info->apptype)
{ {
case APP_TYPE_OPENPGP: list_openpgp (info, fp, no_key_lookup); break; case APP_TYPE_OPENPGP:
case APP_TYPE_PIV: list_piv (info, fp, no_key_lookup); break; list_openpgp (info, fp, no_key_lookup, create_shadow);
case APP_TYPE_NKS: list_nks (info, fp, no_key_lookup); break; break;
case APP_TYPE_P15: list_p15 (info, fp, no_key_lookup); break; case APP_TYPE_PIV:
list_piv (info, fp, no_key_lookup, create_shadow);
break;
case APP_TYPE_NKS:
list_nks (info, fp, no_key_lookup, create_shadow);
break;
case APP_TYPE_P15:
list_p15 (info, fp, no_key_lookup, create_shadow);
break;
default: break; default: break;
} }
} }
@ -1131,6 +1141,7 @@ cmd_list (card_info_t info, char *argstr)
{ {
gpg_error_t err; gpg_error_t err;
int opt_cards, opt_apps, opt_info, opt_reread, opt_no_key_lookup; int opt_cards, opt_apps, opt_info, opt_reread, opt_no_key_lookup;
int opt_shadow;
strlist_t cards = NULL; strlist_t cards = NULL;
strlist_t sl; strlist_t sl;
estream_t fp = opt.interactive? NULL : es_stdout; estream_t fp = opt.interactive? NULL : es_stdout;
@ -1141,27 +1152,32 @@ cmd_list (card_info_t info, char *argstr)
if (!info) if (!info)
return print_help return print_help
("LIST [--cards] [--apps] [--info] [--reread]" ("LIST [--cards] [--apps] [--info] [--reread] [--shadow]"
" [--no-key-lookup] [N] [APP]\n\n" " [--no-key-lookup] [N] [APP]\n\n"
"Show the content of the current card.\n" "Show the content of the current card.\n"
"With N given select and list the N-th card;\n" "With N given select and list the N-th card;\n"
"with APP also given select that application.\n" "with APP also given select that application.\n"
"To select an APP on the current card use '-' for N.\n" "To select an APP on the current card use '-' for N.\n"
"The S/N of the card may be used instead of N.\n" "The S/N of the card may be used instead of N.\n"
" --cards lists available cards\n" " --cards list available cards\n"
" --apps lists additional card applications\n" " --apps list additional card applications\n"
" --info selects a card and prints its s/n\n" " --info select a card and prints its s/n\n"
" --reread read infos from PCKS#15 cards again\n" " --reread read infos from PCKS#15 cards again\n"
" --no-key-lookup does not list matching OpenPGP or X.509 keys\n" " --shadow create shadow keys for all card keys\n"
" --no-key-lookup do not list matching OpenPGP or X.509 keys\n"
, 0); , 0);
opt_cards = has_leading_option (argstr, "--cards"); opt_cards = has_leading_option (argstr, "--cards");
opt_apps = has_leading_option (argstr, "--apps"); opt_apps = has_leading_option (argstr, "--apps");
opt_info = has_leading_option (argstr, "--info"); opt_info = has_leading_option (argstr, "--info");
opt_reread = has_leading_option (argstr, "--reread"); opt_reread = has_leading_option (argstr, "--reread");
opt_shadow = has_leading_option (argstr, "--shadow");
opt_no_key_lookup = has_leading_option (argstr, "--no-key-lookup"); opt_no_key_lookup = has_leading_option (argstr, "--no-key-lookup");
argstr = skip_options (argstr); argstr = skip_options (argstr);
if (opt_shadow)
opt_no_key_lookup = 1;
if (opt.no_key_lookup) if (opt.no_key_lookup)
opt_no_key_lookup = 1; opt_no_key_lookup = 1;
@ -1332,7 +1348,7 @@ cmd_list (card_info_t info, char *argstr)
goto leave; goto leave;
} }
list_card (info, opt_no_key_lookup); list_card (info, opt_no_key_lookup, opt_shadow);
} }
} }

View File

@ -240,7 +240,8 @@ gpg_error_t scd_serialno (char **r_serialno, const char *demand);
gpg_error_t scd_readcert (const char *certidstr, gpg_error_t scd_readcert (const char *certidstr,
void **r_buf, size_t *r_buflen); void **r_buf, size_t *r_buflen);
gpg_error_t scd_readkey (const char *keyrefstr, gcry_sexp_t *r_result); gpg_error_t scd_readkey (const char *keyrefstr, int create_shadow,
gcry_sexp_t *r_result);
gpg_error_t scd_cardlist (strlist_t *result); gpg_error_t scd_cardlist (strlist_t *result);
gpg_error_t scd_applist (strlist_t *result, int all); gpg_error_t scd_applist (strlist_t *result, int all);
gpg_error_t scd_change_pin (const char *pinref, int reset_mode, int nullpin); gpg_error_t scd_change_pin (const char *pinref, int reset_mode, int nullpin);