scd: Add new command: KEYINFO.
authorNIIBE Yutaka <gniibe@fsij.org>
Thu, 25 Apr 2019 05:49:49 +0000 (14:49 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Thu, 25 Apr 2019 05:49:49 +0000 (14:49 +0900)
* scd/app-common.h (struct app_ctx_s): Add with_keygrip function.
* scd/app-openpgp.c (do_with_keygrip): New.
* scd/app.c (app_do_with_keygrip): New.
* scd/command.c (cmd_keyinfo): New.
(send_keyinfo): New.

--

KEYGRIP_ACTION_LOOKUP is not yet used.  It will be used for directly
asking PK* action to determine an APP.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
scd/app-common.h
scd/app-openpgp.c
scd/app.c
scd/command.c
scd/scdaemon.h

index 6bb8eba..8a25cda 100644 (file)
@@ -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 --*/
index 02d3886..c1c9035 100644 (file)
@@ -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:
index 1f3808f..4fe60cb 100644 (file)
--- 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;
+}
index 28c739d..33e1985 100644 (file)
@@ -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;
+}
 \f
 /* 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;
index 73589ad..230653b 100644 (file)
@@ -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);