aboutsummaryrefslogtreecommitdiffstats
path: root/g10/call-agent.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/call-agent.c')
-rw-r--r--g10/call-agent.c69
1 files changed, 65 insertions, 4 deletions
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 43a5c4e12..0450b8165 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -343,6 +343,9 @@ start_agent (ctrl_t ctrl, int for_card)
case GPG_ERR_NO_SCDAEMON:
write_status_text (STATUS_CARDCTRL, "6");
break;
+ case GPG_ERR_OBJ_TERM_STATE:
+ write_status_text (STATUS_CARDCTRL, "7");
+ break;
default:
write_status_text (STATUS_CARDCTRL, "4");
log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc));
@@ -586,6 +589,8 @@ learn_status_cb (void *opaque, const char *line)
parm->extcap.ki = abool;
else if (!strcmp (p, "aac"))
parm->extcap.aac = abool;
+ else if (!strcmp (p, "si"))
+ parm->status_indicator = strtoul (p2, NULL, 10);
}
}
xfree (buf);
@@ -657,6 +662,9 @@ agent_scd_learn (struct agent_card_info_s *info)
struct default_inq_parm_s parm;
struct agent_card_info_s dummyinfo;
+ if (!info)
+ info = &dummyinfo;
+ memset (info, 0, sizeof *info);
memset (&parm, 0, sizeof parm);
rc = start_agent (NULL, 1);
@@ -675,11 +683,7 @@ agent_scd_learn (struct agent_card_info_s *info)
if (rc)
return rc;
- if (!info)
- info = &dummyinfo;
-
parm.ctx = agent_ctx;
- memset (info, 0, sizeof *info);
rc = assuan_transact (agent_ctx, "LEARN --sendinfo",
dummy_data_cb, NULL, default_inq_cb, &parm,
learn_status_cb, info);
@@ -694,6 +698,63 @@ agent_scd_learn (struct agent_card_info_s *info)
}
+/* Send an APDU to the current card. On success the status word is
+ stored at R_SW. With HEXAPDU being NULL only a RESET command is
+ send to scd. With HEXAPDU being the string "undefined" the command
+ "SERIALNO undefined" is send to scd. */
+gpg_error_t
+agent_scd_apdu (const char *hexapdu, unsigned int *r_sw)
+{
+ gpg_error_t err;
+
+ /* Start the agent but not with the card flag so that we do not
+ autoselect the openpgp application. */
+ err = start_agent (NULL, 0);
+ if (err)
+ return err;
+
+ if (!hexapdu)
+ {
+ err = assuan_transact (agent_ctx, "SCD RESET",
+ NULL, NULL, NULL, NULL, NULL, NULL);
+
+ }
+ else if (!strcmp (hexapdu, "undefined"))
+ {
+ err = assuan_transact (agent_ctx, "SCD SERIALNO undefined",
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ }
+ else
+ {
+ char line[ASSUAN_LINELENGTH];
+ membuf_t mb;
+ unsigned char *data;
+ size_t datalen;
+
+ init_membuf (&mb, 256);
+
+ snprintf (line, DIM(line)-1, "SCD APDU %s", hexapdu);
+ err = assuan_transact (agent_ctx, line,
+ membuf_data_cb, &mb, NULL, NULL, NULL, NULL);
+ if (!err)
+ {
+ data = get_membuf (&mb, &datalen);
+ if (!data)
+ err = gpg_error_from_syserror ();
+ else if (datalen < 2) /* Ooops */
+ err = gpg_error (GPG_ERR_CARD);
+ else
+ {
+ *r_sw = (data[datalen-2] << 8) | data[datalen-1];
+ }
+ xfree (data);
+ }
+ }
+
+ return err;
+}
+
+
int
agent_keytocard (const char *hexgrip, int keyno, int force,
const char *serialno, const char *timestamp)