summaryrefslogtreecommitdiffstats
path: root/g10/call-agent.c
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2020-01-16 05:01:46 +0100
committerNIIBE Yutaka <gniibe@fsij.org>2020-01-16 05:01:46 +0100
commit8240a70c31a8e1617de64c42168cf3299b85b39e (patch)
treeaf01b490fa8d06ba9d69baf24dc78d71c68cc2ef /g10/call-agent.c
parentgpg: default-key: Simply don't limit by capability. (diff)
downloadgnupg2-8240a70c31a8e1617de64c42168cf3299b85b39e.tar.xz
gnupg2-8240a70c31a8e1617de64c42168cf3299b85b39e.zip
gpg: Add agent_scd_keyinfo to retrieve available card keys.
* g10/call-agent.c (card_keyinfo_cb, agent_scd_free_keyinfo) (agent_scd_keyinfo): New. * g10/call-agent.h: Define new functions. Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
Diffstat (limited to 'g10/call-agent.c')
-rw-r--r--g10/call-agent.c163
1 files changed, 163 insertions, 0 deletions
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 9e510ae98..c71d50a56 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -1493,8 +1493,171 @@ agent_scd_cardlist (strlist_t *result)
return 0;
}
+
+struct card_keyinfo_parm_s {
+ int error;
+ struct card_key_info_s *list;
+};
+
+/* Callback function for agent_card_keylist. */
+static gpg_error_t
+card_keyinfo_cb (void *opaque, const char *line)
+{
+ gpg_error_t err = 0;
+ struct card_keyinfo_parm_s *parm = opaque;
+ const char *keyword = line;
+ int keywordlen;
+
+ for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
+ ;
+ while (spacep (line))
+ line++;
+
+ if (keywordlen == 7 && !memcmp (keyword, "KEYINFO", keywordlen))
+ {
+ const char *s;
+ int n;
+ struct card_key_info_s *keyinfo;
+ struct card_key_info_s **l_p = &parm->list;
+
+ while ((*l_p))
+ l_p = &(*l_p)->next;
+
+ keyinfo = xtrycalloc (1, sizeof *keyinfo);
+ if (!keyinfo)
+ {
+ alloc_error:
+ if (!parm->error)
+ parm->error = gpg_error_from_syserror ();
+ return 0;
+ }
+
+ for (n=0,s=line; hexdigitp (s); s++, n++)
+ ;
+
+ if (n != 40)
+ {
+ parm_error:
+ if (!parm->error)
+ parm->error = gpg_error (GPG_ERR_ASS_PARAMETER);
+ return 0;
+ }
+
+ memcpy (keyinfo->keygrip, line, 40);
+ keyinfo->keygrip[40] = 0;
+
+ line = s;
+
+ if (!*line)
+ goto parm_error;
+
+ while (spacep (line))
+ line++;
+
+ if (*line++ != 'T')
+ goto parm_error;
+
+ if (!*line)
+ goto parm_error;
+
+ while (spacep (line))
+ line++;
+
+ for (n=0,s=line; hexdigitp (s); s++, n++)
+ ;
+
+ if (!n)
+ goto parm_error;
+
+ keyinfo->serialno = xtrymalloc (n+1);
+ if (!keyinfo->serialno)
+ goto alloc_error;
+
+ memcpy (keyinfo->serialno, line, n);
+ keyinfo->serialno[n] = 0;
+
+ line = s;
+ if (!*line)
+ goto parm_error;
+ while (spacep (line))
+ line++;
+
+ if (!*line)
+ goto parm_error;
+
+ keyinfo->idstr = xtrystrdup (line);
+ if (!keyinfo->idstr)
+ goto alloc_error;
+
+ *l_p = keyinfo;
+ }
+
+ return err;
+}
+
+
+void
+agent_scd_free_keyinfo (struct card_key_info_s *l)
+{
+ struct card_key_info_s *l_next;
+
+ for (; l; l = l_next)
+ {
+ l_next = l->next;
+ xfree (l->serialno);
+ xfree (l->idstr);
+ xfree (l);
+ }
+}
+
+/* Call the scdaemon to check if a key of KEYGRIP is available, or
+ retrieve list of available keys on cards. With CAP, we can limit
+ keys with specified capability. On success, the allocated
+ structure is stored at RESULT. On error, an error code is returned
+ and NULL is stored at RESULT. */
+gpg_error_t
+agent_scd_keyinfo (const char *keygrip, int cap,
+ struct card_key_info_s **result)
+{
+ int err;
+ struct card_keyinfo_parm_s parm;
+ char line[ASSUAN_LINELENGTH];
+ char *list_option;
+
+ *result = NULL;
+
+ switch (cap)
+ {
+ case 0: list_option = "--list"; break;
+ case GCRY_PK_USAGE_SIGN: list_option = "--list=sign"; break;
+ case GCRY_PK_USAGE_ENCR: list_option = "--list=encr"; break;
+ case GCRY_PK_USAGE_AUTH: list_option = "--list=auth"; break;
+ default: return gpg_error (GPG_ERR_INV_VALUE);
+ }
+
+ memset (&parm, 0, sizeof parm);
+ snprintf (line, sizeof line, "SCD KEYINFO %s",
+ keygrip ? keygrip : list_option);
+
+ err = start_agent (NULL, 1 | FLAG_FOR_CARD_SUPPRESS_ERRORS);
+ if (err)
+ return err;
+
+ err = assuan_transact (agent_ctx, line,
+ NULL, NULL, NULL, NULL,
+ card_keyinfo_cb, &parm);
+ if (!err && parm.error)
+ err = parm.error;
+
+ if (!err)
+ *result = parm.list;
+ else
+ agent_scd_free_keyinfo (parm.list);
+
+ return err;
+}
/* Change the PIN of an OpenPGP card or reset the retry counter.
* CHVNO 1: Change the PIN