aboutsummaryrefslogtreecommitdiffstats
path: root/scd/ccid-driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'scd/ccid-driver.c')
-rw-r--r--scd/ccid-driver.c50
1 files changed, 35 insertions, 15 deletions
diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index 854aca1b5..c159b5cd1 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -243,6 +243,7 @@ struct ccid_driver_s
int auto_ifsd;
int max_ifsd;
int ifsd;
+ int ifsc;
int powered_off;
int has_pinpad;
int apdu_level; /* Reader supports short APDU level exchange. */
@@ -1840,7 +1841,6 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
*nread = msglen = rc;
}
-
if (msglen < 10)
{
DEBUGOUT_1 ("bulk-in msg too short (%u)\n", (unsigned int)msglen);
@@ -1880,7 +1880,6 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
return CCID_DRIVER_ERR_INV_VALUE;
}
-
if (debug_level && (!no_debug || debug_level >= 3))
{
switch (buffer[0])
@@ -2326,6 +2325,11 @@ ccid_get_atr (ccid_driver_t handle,
if (rc)
DEBUGOUT ("SetParameters failed (ignored)\n");
+ if (!rc && msglen > 15 && msg[15] >= 16 && msg[15] <= 254 )
+ handle->ifsc = msg[15];
+ else
+ handle->ifsc = 128; /* Something went wrong, assume 128 bytes. */
+
handle->t1_ns = 0;
handle->t1_nr = 0;
@@ -2582,22 +2586,15 @@ ccid_transceive (ccid_driver_t handle,
assert (apdulen);
/* Construct an I-Block. */
- /* Fixme: I am not sure whether limiting the length to 259
- as per CCID spec is required. The code blow chops the
- APDU anyway into 128 byte blocks. Needs to be addressed
- when supporting extended length APDUs. */
- if (apdulen > 259)
- return CCID_DRIVER_ERR_INV_VALUE; /* Invalid length. */
-
tpdu = msg+10;
/* NAD: DAD=1, SAD=0 */
tpdu[0] = handle->nonnull_nad? ((1 << 4) | 0): 0;
tpdu[1] = ((handle->t1_ns & 1) << 6); /* I-block */
- if (apdulen > 128 /* fixme: replace by ifsc */)
+ if (apdulen > handle->ifsc )
{
- apdulen = 128;
- apdu_buf += 128;
- apdu_buflen -= 128;
+ apdulen = handle->ifsc;
+ apdu_buf += handle->ifsc;
+ apdu_buflen -= handle->ifsc;
tpdu[1] |= (1 << 5); /* Set more bit. */
}
tpdu[2] = apdulen;
@@ -2752,8 +2749,31 @@ ccid_transceive (ccid_driver_t handle,
DEBUGOUT_2 ("T=1 S-block %s received cmd=%d\n",
(tpdu[1] & 0x20)? "response": "request",
(tpdu[1] & 0x1f));
- if ( !(tpdu[1] & 0x20) && (tpdu[1] & 0x1f) == 3 && tpdu[2])
- { /* Wait time extension request. */
+ if ( !(tpdu[1] & 0x20) && (tpdu[1] & 0x1f) == 1 && tpdu[2] == 1)
+ {
+ /* Information field size request. */
+ unsigned char ifsc = tpdu[3];
+
+ if (ifsc < 16 || ifsc > 254)
+ return CCID_DRIVER_ERR_CARD_IO_ERROR;
+
+ msg = send_buffer;
+ tpdu = msg+10;
+ /* NAD: DAD=1, SAD=0 */
+ tpdu[0] = handle->nonnull_nad? ((1 << 4) | 0): 0;
+ tpdu[1] = (0xc0 | 0x20 | 1); /* S-block response */
+ tpdu[2] = 1;
+ tpdu[3] = ifsc;
+ tpdulen = 4;
+ edc = compute_edc (tpdu, tpdulen, use_crc);
+ if (use_crc)
+ tpdu[tpdulen++] = (edc >> 8);
+ tpdu[tpdulen++] = edc;
+ DEBUGOUT_1 ("T=1 requesting an ifsc=%d\n", ifsc);
+ }
+ else if ( !(tpdu[1] & 0x20) && (tpdu[1] & 0x1f) == 3 && tpdu[2])
+ {
+ /* Wait time extension request. */
unsigned char bwi = tpdu[3];
msg = send_buffer;
tpdu = msg+10;