aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2019-07-09 01:56:09 +0000
committerNIIBE Yutaka <[email protected]>2019-07-09 01:56:09 +0000
commitc51a5685554a06e00ae1e99070b44613b2f8d417 (patch)
tree691e0bb4b3a37fd632a3c70b98aaa91883c9f85a
parentscd: Fix keygrip search. (diff)
downloadgnupg-c51a5685554a06e00ae1e99070b44613b2f8d417.tar.gz
gnupg-c51a5685554a06e00ae1e99070b44613b2f8d417.zip
scd: ccid-driver: Initial getting ATR more robustly.
* scd/ccid-driver.c (send_power_off): New. (do_close_reader): Use send_power_off. (ccid_get_atr): Add error recovery. GnuPG-bug-id: 4616 Signed-off-by: NIIBE Yutaka <[email protected]>
-rw-r--r--scd/ccid-driver.c57
1 files changed, 39 insertions, 18 deletions
diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index e092a2b9a..f791c3ad5 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -1717,31 +1717,37 @@ ccid_require_get_status (ccid_driver_t handle)
return 1;
}
-
-static void
-do_close_reader (ccid_driver_t handle)
+static int
+send_power_off (ccid_driver_t handle)
{
int rc;
unsigned char msg[100];
size_t msglen;
unsigned char seqno;
- if (!handle->powered_off)
- {
- msg[0] = PC_to_RDR_IccPowerOff;
- msg[5] = 0; /* slot */
- msg[6] = seqno = handle->seqno++;
- msg[7] = 0; /* RFU */
- msg[8] = 0; /* RFU */
- msg[9] = 0; /* RFU */
- set_msg_len (msg, 0);
- msglen = 10;
+ msg[0] = PC_to_RDR_IccPowerOff;
+ msg[5] = 0; /* slot */
+ msg[6] = seqno = handle->seqno++;
+ msg[7] = 0; /* RFU */
+ msg[8] = 0; /* RFU */
+ msg[9] = 0; /* RFU */
+ set_msg_len (msg, 0);
+ msglen = 10;
- rc = bulk_out (handle, msg, msglen, 0);
- if (!rc)
- bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus,
- seqno, 2000, 0);
- }
+ rc = bulk_out (handle, msg, msglen, 0);
+ if (!rc)
+ bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus,
+ seqno, 2000, 0);
+ return rc;
+}
+
+static void
+do_close_reader (ccid_driver_t handle)
+{
+ int rc;
+
+ if (!handle->powered_off)
+ send_power_off (handle);
if (handle->transfer)
{
@@ -2597,6 +2603,21 @@ ccid_get_atr (ccid_driver_t handle,
NULL, 0, NULL))
goto again;
}
+ else if (statusbits == 0 && CCID_COMMAND_FAILED (msg))
+ {
+ /* Card was active already, and something went wrong with
+ PC_to_RDR_IccPowerOn command. It may be baud-rate mismatch
+ between the card and the reader. To recover from this state,
+ send PC_to_RDR_IccPowerOff command to reset the card and try
+ again.
+ */
+ rc = send_power_off (handle);
+ if (rc)
+ return rc;
+
+ statusbits = 1;
+ goto again;
+ }
else if (CCID_COMMAND_FAILED (msg))
return CCID_DRIVER_ERR_CARD_IO_ERROR;