diff options
Diffstat (limited to 'g10/call-agent.c')
-rw-r--r-- | g10/call-agent.c | 69 |
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) |