aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--scd/app-common.h5
-rw-r--r--scd/app-openpgp.c42
-rw-r--r--scd/app-piv.c18
-rw-r--r--scd/app.c13
-rw-r--r--scd/command.c36
5 files changed, 79 insertions, 35 deletions
diff --git a/scd/app-common.h b/scd/app-common.h
index 87f63bb7e..99331b04e 100644
--- a/scd/app-common.h
+++ b/scd/app-common.h
@@ -188,7 +188,7 @@ struct app_ctx_s {
gpg_error_t (*pincb)(void*, const char *, char **),
void *pincb_arg);
gpg_error_t (*with_keygrip) (app_t app, ctrl_t ctrl, int action,
- const char *keygrip_str);
+ const char *keygrip_str, int capability);
} fnc;
};
@@ -301,7 +301,8 @@ gpg_error_t app_change_pin (card_t card, ctrl_t ctrl,
gpg_error_t app_check_pin (card_t card, ctrl_t ctrl, const char *keyidstr,
gpg_error_t (*pincb)(void*, const char *, char **),
void *pincb_arg);
-card_t app_do_with_keygrip (ctrl_t ctrl, int action, const char *keygrip_str);
+card_t app_do_with_keygrip (ctrl_t ctrl, int action, const char *keygrip_str,
+ int capability);
/*-- app-openpgp.c --*/
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 4f76caac3..cdd16fab2 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -4929,8 +4929,23 @@ do_check_pin (app_t app, const char *keyidstr,
return verify_chv2 (app, pincb, pincb_arg);
}
+static void
+send_keyinfo_if_available (app_t app, ctrl_t ctrl, char *serial,
+ int data, int i)
+{
+ char idbuf[50];
+
+ if (app->app_local->pk[i].read_done)
+ {
+ sprintf (idbuf, "OPENPGP.%d", i+1);
+ send_keyinfo (ctrl, data,
+ app->app_local->pk[i].keygrip_str, serial, idbuf);
+ }
+}
+
static gpg_error_t
-do_with_keygrip (app_t app, ctrl_t ctrl, int action, const char *keygrip_str)
+do_with_keygrip (app_t app, ctrl_t ctrl, int action, const char *keygrip_str,
+ int capability)
{
int i;
@@ -4950,7 +4965,6 @@ do_with_keygrip (app_t app, ctrl_t ctrl, int action, const char *keygrip_str)
}
else
{
- char idbuf[50];
char buf[65];
int data = (action == KEYGRIP_ACTION_SEND_DATA);
@@ -4961,13 +4975,17 @@ do_with_keygrip (app_t app, ctrl_t ctrl, int action, const char *keygrip_str)
if (keygrip_str == NULL)
{
- for (i = 0; i < 3; i++)
- if (app->app_local->pk[i].read_done)
- {
- sprintf (idbuf, "OPENPGP.%d", i+1);
- send_keyinfo (ctrl, data,
- app->app_local->pk[i].keygrip_str,buf, idbuf);
- }
+ if (capability == 0)
+ {
+ for (i = 0; i < 3; i++)
+ send_keyinfo_if_available (app, ctrl, buf, data, i);
+ }
+ else
+ {
+ i = capability - 1;
+ send_keyinfo_if_available (app, ctrl, buf, data, i);
+ }
+
/* Return an error so that the dispatcher keeps on looping
* over the other applications. Only for clarity we use a
* different error code than for the not_found case. */
@@ -4976,11 +4994,9 @@ do_with_keygrip (app_t app, ctrl_t ctrl, int action, const char *keygrip_str)
else
{
for (i = 0; i < 3; i++)
- if (app->app_local->pk[i].read_done
- && !strcmp (keygrip_str, app->app_local->pk[i].keygrip_str))
+ if (!strcmp (keygrip_str, app->app_local->pk[i].keygrip_str))
{
- sprintf (idbuf, "OPENPGP.%d", i+1);
- send_keyinfo (ctrl, data, keygrip_str, buf, idbuf);
+ send_keyinfo_if_available (app, ctrl, buf, data, i);
return 0;
}
}
diff --git a/scd/app-piv.c b/scd/app-piv.c
index 3cc7754df..0b1cb8208 100644
--- a/scd/app-piv.c
+++ b/scd/app-piv.c
@@ -3330,7 +3330,7 @@ do_writecert (app_t app, ctrl_t ctrl,
/* Process the various keygrip based info requests. */
static gpg_error_t
do_with_keygrip (app_t app, ctrl_t ctrl, int action,
- const char *want_keygripstr)
+ const char *want_keygripstr, int capability)
{
gpg_error_t err;
char *keygripstr = NULL;
@@ -3389,6 +3389,22 @@ do_with_keygrip (app_t app, ctrl_t ctrl, int action,
}
else if (!want_keygripstr || !strcmp (keygripstr, want_keygripstr))
{
+ if (capability == 1)
+ {
+ if (strcmp (data_objects[i].keyref, "9C"))
+ continue;
+ }
+ if (capability == 2)
+ {
+ if (strcmp (data_objects[i].keyref, "9D"))
+ continue;
+ }
+ if (capability == 3)
+ {
+ if (strcmp (data_objects[i].keyref, "9A"))
+ continue;
+ }
+
snprintf (idbuf, sizeof idbuf, "PIV.%s", data_objects[i].keyref);
send_keyinfo (ctrl, data, keygripstr, serialno, idbuf);
if (want_keygripstr)
diff --git a/scd/app.c b/scd/app.c
index fff2b307f..0fc155293 100644
--- a/scd/app.c
+++ b/scd/app.c
@@ -1138,7 +1138,7 @@ maybe_switch_app (ctrl_t ctrl, card_t card, const char *keyref)
for (app = card->app; app; app_prev = app, app = app->next)
if (app->fnc.with_keygrip
&& !app->fnc.with_keygrip (app, ctrl,
- KEYGRIP_ACTION_LOOKUP, keyref))
+ KEYGRIP_ACTION_LOOKUP, keyref, 0))
break;
if (!app_prev && ctrl->current_apptype == card->app->apptype)
return 0; /* Already the first app - no need to switch. */
@@ -1969,7 +1969,8 @@ app_send_card_list (ctrl_t ctrl)
* <keygrip> T <serialno> <idstr>
* If a match was found a pointer to the matching application is
* returned. With the KEYGRIP_STR given as NULL, lines for all
- * keys will be send and the return value is NULL.
+ * keys (with CAPABILITY) will be send and the return value is
+ * GPG_ERR_TRUE.
*
* - KEYGRIP_ACTION_WRITE_STATUS
*
@@ -1980,10 +1981,12 @@ app_send_card_list (ctrl_t ctrl)
*
* Returns a pointer to the application matching KEYGRIP_STR but
* does not emit any status or data lines. If no key with that
- * keygrip is available or KEYGRIP_STR is NULL, NULL is returned.
+ * keygrip is available or KEYGRIP_STR is NULL, GPG_ERR_NOT_FOUND
+ * is returned.
*/
card_t
-app_do_with_keygrip (ctrl_t ctrl, int action, const char *keygrip_str)
+app_do_with_keygrip (ctrl_t ctrl, int action, const char *keygrip_str,
+ int capability)
{
int locked = 0;
card_t c;
@@ -2005,7 +2008,7 @@ app_do_with_keygrip (ctrl_t ctrl, int action, const char *keygrip_str)
if (DBG_APP)
log_debug ("slot %d app %s: calling with_keygrip(action=%d)\n",
c->slot, xstrapptype (a), action);
- if (!a->fnc.with_keygrip (a, ctrl, action, keygrip_str))
+ if (!a->fnc.with_keygrip (a, ctrl, action, keygrip_str, capability))
goto leave_the_loop;
}
unlock_card (c);
diff --git a/scd/command.c b/scd/command.c
index 73a524b49..e5cf98fcb 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -830,7 +830,7 @@ cmd_pksign (assuan_context_t ctx, char *line)
ctrl->card_ctx. */
if (strlen (keyidstr) == 40)
{
- card = app_do_with_keygrip (ctrl, KEYGRIP_ACTION_LOOKUP, keyidstr);
+ card = app_do_with_keygrip (ctrl, KEYGRIP_ACTION_LOOKUP, keyidstr, 0);
direct = 1;
}
else
@@ -898,7 +898,7 @@ cmd_pkauth (assuan_context_t ctx, char *line)
ctrl->card_ctx. */
if (strlen (keyidstr) == 40)
{
- card = app_do_with_keygrip (ctrl, KEYGRIP_ACTION_LOOKUP, keyidstr);
+ card = app_do_with_keygrip (ctrl, KEYGRIP_ACTION_LOOKUP, keyidstr, 0);
direct = 1;
}
else
@@ -959,7 +959,7 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
ctrl->card_ctx. */
if (strlen (keyidstr) == 40)
{
- card = app_do_with_keygrip (ctrl, KEYGRIP_ACTION_LOOKUP, keyidstr);
+ card = app_do_with_keygrip (ctrl, KEYGRIP_ACTION_LOOKUP, keyidstr, 0);
direct = 1;
}
else
@@ -1893,12 +1893,13 @@ cmd_killscd (assuan_context_t ctx, char *line)
static const char hlp_keyinfo[] =
- "KEYINFO [--list] [--data] <keygrip>\n"
+ "KEYINFO [--list[=auth|encr|sign]] [--data] <keygrip>\n"
"\n"
"Return information about the key specified by the KEYGRIP. If the\n"
"key is not available GPG_ERR_NOT_FOUND is returned. If the option\n"
"--list is given the keygrip is ignored and information about all\n"
- "available keys are returned. Unless --data is given, the\n"
+ "available keys are returned. Capability may limit the listing.\n"
+ "Unless --data is given, the\n"
"information is returned as a status line using the format:\n"
"\n"
" KEYINFO <keygrip> T <serialno> <idstr>\n"
@@ -1916,30 +1917,37 @@ static const char hlp_keyinfo[] =
static gpg_error_t
cmd_keyinfo (assuan_context_t ctx, char *line)
{
- int list_mode;
+ int cap;
int opt_data;
int action;
char *keygrip_str;
ctrl_t ctrl = assuan_get_pointer (ctx);
card_t card;
- list_mode = has_option (line, "--list");
- opt_data = has_option (line, "--data");
- line = skip_options (line);
-
- if (list_mode)
- keygrip_str = NULL;
+ cap = 0;
+ keygrip_str = NULL;
+ if (has_option (line, "--list"))
+ cap = 0;
+ else if (has_option (line, "--list=sign"))
+ cap = 1;
+ else if (has_option (line, "--list=encr"))
+ cap = 2;
+ else if (has_option (line, "--list=auth"))
+ cap = 3;
else
keygrip_str = line;
+ opt_data = has_option (line, "--data");
+ line = skip_options (line);
+
if (opt_data)
action = KEYGRIP_ACTION_SEND_DATA;
else
action = KEYGRIP_ACTION_WRITE_STATUS;
- card = app_do_with_keygrip (ctrl, action, keygrip_str);
+ card = app_do_with_keygrip (ctrl, action, keygrip_str, cap);
- if (!list_mode && !card)
+ if (keygrip_str && !card)
return gpg_error (GPG_ERR_NOT_FOUND);
return 0;
}