summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--scd/app-common.h10
-rw-r--r--scd/app-openpgp.c54
-rw-r--r--scd/app.c21
-rw-r--r--scd/command.c73
-rw-r--r--scd/scdaemon.h2
5 files changed, 159 insertions, 1 deletions
diff --git a/scd/app-common.h b/scd/app-common.h
index 6bb8eba50..8a25cda55 100644
--- a/scd/app-common.h
+++ b/scd/app-common.h
@@ -126,9 +126,18 @@ struct app_ctx_s {
gpg_error_t (*check_pin) (app_t app, const char *keyidstr,
gpg_error_t (*pincb)(void*, const char *, char **),
void *pincb_arg);
+ int (*with_keygrip) (app_t app, ctrl_t ctrl, int action,
+ const char *keygrip_str);
} fnc;
};
+enum
+ {
+ KEYGRIP_ACTION_SEND_DATA,
+ KEYGRIP_ACTION_WRITE_STATUS,
+ KEYGRIP_ACTION_LOOKUP
+ };
+
/*-- app-help.c --*/
unsigned int app_help_count_bits (const unsigned char *a, size_t len);
gpg_error_t app_help_get_keygrip_string_pk (const void *pk, size_t pklen,
@@ -206,6 +215,7 @@ gpg_error_t app_change_pin (app_t app, ctrl_t ctrl,
gpg_error_t app_check_pin (app_t app, ctrl_t ctrl, const char *keyidstr,
gpg_error_t (*pincb)(void*, const char *, char **),
void *pincb_arg);
+app_t app_do_with_keygrip (ctrl_t ctrl, int action, const char *keygrip_str);
/*-- app-openpgp.c --*/
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 02d388695..c1c90350b 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -4945,6 +4945,59 @@ do_check_pin (app_t app, const char *keyidstr,
return verify_chv2 (app, pincb, pincb_arg);
}
+static int
+do_with_keygrip (app_t app, ctrl_t ctrl, int action, const char *keygrip_str)
+{
+ int i;
+
+ if (action == KEYGRIP_ACTION_LOOKUP)
+ {
+ if (keygrip_str == NULL)
+ return 1;
+
+ for (i = 0; i < 3; i++)
+ if (app->app_local->pk[i].read_done
+ && !strcmp (keygrip_str, app->app_local->pk[i].keygrip_str))
+ return 0; /* Found */
+
+ return 1;
+ }
+ else
+ {
+ char idbuf[50];
+ char buf[65];
+ int data = (action == KEYGRIP_ACTION_SEND_DATA);
+
+ if (DIM (buf) < 2 * app->serialnolen + 1)
+ return 0;
+
+ bin2hex (app->serialno, app->serialnolen, buf);
+
+ 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);
+ }
+ }
+ 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))
+ {
+ sprintf (idbuf, "OPENPGP.%d", i+1);
+ send_keyinfo (ctrl, data, keygrip_str, buf, idbuf);
+ return 0;
+ }
+ }
+
+ return 1;
+ }
+}
/* Show information about card capabilities. */
static void
@@ -5327,6 +5380,7 @@ app_select_openpgp (app_t app)
app->fnc.decipher = do_decipher;
app->fnc.change_pin = do_change_pin;
app->fnc.check_pin = do_check_pin;
+ app->fnc.with_keygrip = do_with_keygrip;
}
leave:
diff --git a/scd/app.c b/scd/app.c
index 1f3808fd4..4fe60cbbb 100644
--- a/scd/app.c
+++ b/scd/app.c
@@ -1290,3 +1290,24 @@ app_send_card_list (ctrl_t ctrl)
}
npth_mutex_unlock (&app_list_lock);
}
+
+/* Execute an action for each app. ACTION can be one of:
+ KEYGRIP_ACTION_SEND_DATA: send data if KEYGRIP_STR matches
+ KEYGRIP_ACTION_WRITE_STATUS: write status if KEYGRIP_STR matches
+ KEYGRIP_ACTION_LOOKUP: Return matching APP
+ */
+app_t
+app_do_with_keygrip (ctrl_t ctrl, int action, const char *keygrip_str)
+{
+ app_t a;
+
+ npth_mutex_lock (&app_list_lock);
+
+ for (a = app_top; a; a = a->next)
+ if (a->fnc.with_keygrip
+ && !a->fnc.with_keygrip (a, ctrl, action, keygrip_str))
+ break;
+
+ npth_mutex_unlock (&app_list_lock);
+ return a;
+}
diff --git a/scd/command.c b/scd/command.c
index 28c739d93..33e1985b3 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -424,7 +424,7 @@ cmd_learn (assuan_context_t ctx, char *line)
serial = app_get_serialno (ctrl->app_ctx);
if (!serial)
- return gpg_error (GPG_ERR_INV_VALUE);
+ return gpg_error (GPG_ERR_INV_VALUE);
rc = assuan_write_status (ctx, "SERIALNO", serial);
if (rc < 0)
@@ -1757,6 +1757,76 @@ cmd_killscd (assuan_context_t ctx, char *line)
}
+static const char hlp_keyinfo[] =
+ "KEYINFO [--list] [--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"
+ "information is returned as a status line using the format:\n"
+ "\n"
+ " KEYINFO <keygrip> T <serialno> <idstr>\n"
+ "\n"
+ "KEYGRIP is the keygrip.\n"
+ "\n"
+ "SERIALNO is an ASCII string with the serial number of the\n"
+ " smartcard. If the serial number is not known a single\n"
+ " dash '-' is used instead.\n"
+ "\n"
+ "IDSTR is the IDSTR used to distinguish keys on a smartcard. If it\n"
+ " is not known a dash is used instead.\n"
+ "\n"
+ "More information may be added in the future.";
+static gpg_error_t
+cmd_keyinfo (assuan_context_t ctx, char *line)
+{
+ int list_mode;
+ int opt_data;
+ int action;
+ char *keygrip_str;
+ ctrl_t ctrl = assuan_get_pointer (ctx);
+
+ list_mode = has_option (line, "--list");
+ opt_data = has_option (line, "--data");
+ line = skip_options (line);
+
+ if (list_mode)
+ keygrip_str = NULL;
+ else
+ keygrip_str = line;
+
+ if (opt_data)
+ action = KEYGRIP_ACTION_SEND_DATA;
+ else
+ action = KEYGRIP_ACTION_WRITE_STATUS;
+
+ app_do_with_keygrip (ctrl, action, keygrip_str);
+
+ return 0;
+}
+
+void
+send_keyinfo (ctrl_t ctrl, int data, const char *keygrip_str,
+ const char *serialno, const char *idstr)
+{
+ char *string;
+ assuan_context_t ctx = ctrl->server_local->assuan_ctx;
+
+ string = xtryasprintf ("%s T %s %s\n", keygrip_str,
+ serialno? serialno : "-",
+ idstr? idstr : "-");
+ if (!string)
+ return;
+
+ if (!data)
+ assuan_write_status (ctx, "KEYINFO", string);
+ else
+ assuan_send_data (ctx, string, strlen (string));
+
+ xfree (string);
+ return;
+}
/* Tell the assuan library about our commands */
static int
@@ -1792,6 +1862,7 @@ register_commands (assuan_context_t ctx)
{ "DISCONNECT", cmd_disconnect,hlp_disconnect },
{ "APDU", cmd_apdu, hlp_apdu },
{ "KILLSCD", cmd_killscd, hlp_killscd },
+ { "KEYINFO", cmd_keyinfo, hlp_keyinfo },
{ NULL }
};
int i, rc;
diff --git a/scd/scdaemon.h b/scd/scdaemon.h
index 73589ade8..230653b11 100644
--- a/scd/scdaemon.h
+++ b/scd/scdaemon.h
@@ -125,6 +125,8 @@ void send_status_info (ctrl_t ctrl, const char *keyword, ...)
void send_status_direct (ctrl_t ctrl, const char *keyword, const char *args);
gpg_error_t send_status_printf (ctrl_t ctrl, const char *keyword,
const char *format, ...) GPGRT_ATTR_PRINTF(3,4);
+void send_keyinfo (ctrl_t ctrl, int data, const char *keygrip_str,
+ const char *serialno, const char *idstr);
void popup_prompt (void *opaque, int on);
void send_client_notifications (app_t app, int removal);