aboutsummaryrefslogtreecommitdiffstats
path: root/g10/call-agent.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2014-12-15 16:38:40 +0000
committerWerner Koch <[email protected]>2014-12-15 16:38:40 +0000
commitdd65e21cb4934b40e6f2f7a8095f39fd6d9971bc (patch)
tree789d4242e852d337de44a0195badb5e577a1ccae /g10/call-agent.c
parentgpg: Fix regression in notation data regression. (diff)
downloadgnupg-dd65e21cb4934b40e6f2f7a8095f39fd6d9971bc.tar.gz
gnupg-dd65e21cb4934b40e6f2f7a8095f39fd6d9971bc.zip
gpg: Add sub-command "factory-reset" to --card-edit.
* common/util.h (GPG_ERR_OBJ_TERM_STATE): New. * scd/iso7816.c (map_sw): Add this error code. * scd/app-openpgp.c (do_getattr): Return the life cycle indicator. * scd/app.c (select_application): Allow a return value of GPG_ERR_OBJ_TERM_STATE. * scd/scdaemon.c (set_debug): Print the DBG_READER value. * g10/call-agent.c (start_agent): Print a status line for the termination state. (agent_scd_learn): Make arg "info" optional. (agent_scd_apdu): New. * g10/card-util.c (send_apdu): New. (factory_reset): New. (card_edit): Add command factory-reset. Signed-off-by: Werner Koch <[email protected]>
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)