aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2020-11-09 14:46:35 +0100
committerWerner Koch <wk@gnupg.org>2020-11-09 14:46:35 +0100
commit12fd10791f1dec4ec42810d7b92c69e1ae2327b9 (patch)
tree52dcec153b233ad0cebd827b1f78836fcf25f5c7
parent8fb0d5e3c775f40e321689b35431d81425406237 (diff)
downloadgnupg-12fd10791f1dec4ec42810d7b92c69e1ae2327b9.tar.gz
card: Run factory-reset in locked stated also in gpg-card.
* tools/card-call-scd.c (scd_apdu): Add more pseudo APDUs. * tools/card-misc.c (send_apdu): Handle them. * tools/gpg-card.c (cmd_factoryreset): Use lock commands. -- This is port of the code used with gpg-card-edit. Note that the command "apdu" now also understands some extra keywords. Signed-off-by: Werner Koch <wk@gnupg.org>
-rw-r--r--g10/call-agent.c5
-rw-r--r--tools/card-call-scd.c33
-rw-r--r--tools/card-misc.c9
-rw-r--r--tools/gpg-card.c22
4 files changed, 57 insertions, 12 deletions
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 01f59aca8..35fb615f0 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -974,8 +974,9 @@ agent_scd_keypairinfo (ctrl_t ctrl, const char *keyref, keypair_info_t *r_list)
/* 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. HEXAPDU may also be one of these special strings:
+ * stored at R_SW unless R_SQ is NULL. With HEXAPDU being NULL only a
+ * RESET command is send to scd. HEXAPDU may also be one of theseo
+ * special strings:
*
* "undefined" :: Send the command "SCD SERIALNO undefined"
* "lock" :: Send the command "SCD LOCK --wait"
diff --git a/tools/card-call-scd.c b/tools/card-call-scd.c
index b56f40a1c..1f7008902 100644
--- a/tools/card-call-scd.c
+++ b/tools/card-call-scd.c
@@ -421,9 +421,16 @@ store_serialno (const char *line)
/* Send an APDU to the current card. On success the status word is
* stored at R_SW inless R_SW is NULL. 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. If
- * R_DATA is not NULL the data without the status code is stored
+ * RESET command is send to scd. HEXAPDU may also be one of theseo
+ * special strings:
+ *
+ * "undefined" :: Send the command "SCD SERIALNO undefined"
+ * "lock" :: Send the command "SCD LOCK --wait"
+ * "trylock" :: Send the command "SCD LOCK"
+ * "unlock" :: Send the command "SCD UNLOCK"
+ * "reset-keep-lock" :: Send the command "SCD RESET --keep-lock"
+ *
+ * If R_DATA is not NULL the data without the status code is stored
* there. Caller must release it. If OPTIONS is not NULL, this will
* be passed verbatim to the SCDaemon's APDU command. */
gpg_error_t
@@ -447,6 +454,26 @@ scd_apdu (const char *hexapdu, const char *options, unsigned int *r_sw,
NULL, NULL, NULL, NULL, NULL, NULL);
}
+ else if (!strcmp (hexapdu, "reset-keep-lock"))
+ {
+ err = assuan_transact (agent_ctx, "SCD RESET --keep-lock",
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ }
+ else if (!strcmp (hexapdu, "lock"))
+ {
+ err = assuan_transact (agent_ctx, "SCD LOCK --wait",
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ }
+ else if (!strcmp (hexapdu, "trylock"))
+ {
+ err = assuan_transact (agent_ctx, "SCD LOCK",
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ }
+ else if (!strcmp (hexapdu, "unlock"))
+ {
+ err = assuan_transact (agent_ctx, "SCD UNLOCK",
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ }
else if (!strcmp (hexapdu, "undefined"))
{
err = assuan_transact (agent_ctx, "SCD SERIALNO undefined",
diff --git a/tools/card-misc.c b/tools/card-misc.c
index bbb2b4810..6466e98b2 100644
--- a/tools/card-misc.c
+++ b/tools/card-misc.c
@@ -92,8 +92,13 @@ send_apdu (const char *hexapdu, const char *desc, unsigned int ignore,
if (err)
log_error ("sending card command %s failed: %s\n", desc,
gpg_strerror (err));
- else if (!hexapdu || !strcmp (hexapdu, "undefined"))
- ;
+ else if (!hexapdu
+ || !strcmp (hexapdu, "undefined")
+ || !strcmp (hexapdu, "reset-keep-lock")
+ || !strcmp (hexapdu, "lock")
+ || !strcmp (hexapdu, "trylock")
+ || !strcmp (hexapdu, "unlock"))
+ ; /* Ignore pseudo APDUs. */
else if (ignore == 0xffff)
; /* Ignore all status words. */
else if (sw != 0x9000)
diff --git a/tools/gpg-card.c b/tools/gpg-card.c
index 7c30ad3aa..9898c5e31 100644
--- a/tools/gpg-card.c
+++ b/tools/gpg-card.c
@@ -2922,6 +2922,7 @@ cmd_factoryreset (card_info_t info)
int termstate = 0;
int any_apdu = 0;
int is_yubikey = 0;
+ int locked = 0;
int i;
@@ -3026,7 +3027,7 @@ cmd_factoryreset (card_info_t info)
if (is_yubikey)
{
- /* The PIV application si already selected, we only need to
+ /* If the PIV application is already selected, we only need to
* send the special reset APDU after having blocked PIN and
* PUK. Note that blocking the PUK is done using the
* unblock PIN command. */
@@ -3044,9 +3045,15 @@ cmd_factoryreset (card_info_t info)
else /* OpenPGP card. */
{
any_apdu = 1;
- /* We need to select a card application before we can send APDUs
- * to the card without scdaemon doing anything on its own. */
- err = send_apdu (NULL, "RESET", 0, NULL, NULL);
+ /* We need to select a card application before we can send
+ * APDUs to the card without scdaemon doing anything on its
+ * own. We then lock the connection so that other tools
+ * (e.g. Kleopatra) don't try a new select. */
+ err = send_apdu ("lock", "locking connection ", 0, NULL, NULL);
+ if (err)
+ goto leave;
+ locked = 1;
+ err = send_apdu ("reset-keep-lock", "reset", 0, NULL, NULL);
if (err)
goto leave;
err = send_apdu ("undefined", "dummy select ", 0, NULL, NULL);
@@ -3095,7 +3102,10 @@ cmd_factoryreset (card_info_t info)
}
/* Finally we reset the card reader once more. */
- err = send_apdu (NULL, "RESET", 0, NULL, NULL);
+ if (locked)
+ err = send_apdu ("reset-keep-lock", "reset", 0, NULL, NULL);
+ else
+ err = send_apdu (NULL, "RESET", 0, NULL, NULL);
if (err)
goto leave;
@@ -3123,6 +3133,8 @@ cmd_factoryreset (card_info_t info)
* scd serialno openpgp
*/
}
+ if (locked)
+ send_apdu ("unlock", "unlocking connection ", 0, NULL, NULL);
xfree (answer);
return err;
}