diff --git a/ccid/src/ccid.c b/ccid/src/ccid.c index 6e30a7b..1e14ca9 100644 --- a/ccid/src/ccid.c +++ b/ccid/src/ccid.c @@ -71,23 +71,22 @@ ccid_desc = { .dwSynchProtocols = __constant_cpu_to_le32(0), .dwMechanical = __constant_cpu_to_le32(0), .dwFeatures = __constant_cpu_to_le32( - 0x2| // Automatic parameter configuration based on ATR data - 0x4| // Automatic activation of ICC on inserting - 0x8| // Automatic ICC voltage selection - 0x10| // Automatic ICC clock frequency change - 0x20| // Automatic baud rate change - 0x40| // Automatic parameters negotiation - 0x80| // Automatic PPS - 0x20000| // Short APDU level exchange - 0x100000),// USB Wake up signaling supported + 0x00000002| // Automatic parameter configuration based on ATR data + 0x00000004| // Automatic activation of ICC on inserting + 0x00000008| // Automatic ICC voltage selection + 0x00000010| // Automatic ICC clock frequency change + 0x00000020| // Automatic baud rate change + 0x00000040| // Automatic parameters negotiation + 0x00000080| // Automatic PPS + 0x00020000| // Short APDU level exchange + /*0x00040000| // Extended APDU level exchange*/ + 0x00100000), // USB Wake up signaling supported .dwMaxCCIDMessageLength = __constant_cpu_to_le32(261+10), .bClassGetResponse = 0xFF, .bclassEnvelope = 0xFF, .wLcdLayout = __constant_cpu_to_le16( - //0), 0xFF00| // Number of lines for the LCD display 0x00FF), // Number of characters per line - //.bPINSupport = 0, .bPINSupport = 0x1| // PIN Verification supported 0x2| // PIN Modification supported 0x10| // PIN PACE Capabilities supported @@ -116,12 +115,10 @@ detect_card_presence(int slot) if (sc_result == 0 && card_in_slot[slot] && sc_card_valid(card_in_slot[slot])) { - sc_reset(card_in_slot[slot]); sc_disconnect_card(card_in_slot[slot], 0); sc_debug(ctx, "Card removed from slot %d", slot); } if (sc_result & SC_SLOT_CARD_CHANGED) { - sc_reset(card_in_slot[slot]); sc_disconnect_card(card_in_slot[slot], 0); sc_debug(ctx, "Card exchanged in slot %d", slot); } @@ -166,7 +163,6 @@ void ccid_shutdown() int i; for (i = 0; i < sizeof *card_in_slot; i++) { if (card_in_slot[i] && sc_card_valid(card_in_slot[i])) { - sc_reset(card_in_slot[i]); sc_disconnect_card(card_in_slot[i], 0); } } diff --git a/ccid/src/scutil.c b/ccid/src/scutil.c index 2cd553f..06e5519 100644 --- a/ccid/src/scutil.c +++ b/ccid/src/scutil.c @@ -80,13 +80,13 @@ int build_apdu(sc_context_t *ctx, const u8 *buf, size_t len, sc_apdu_t *apdu) const u8 *p; size_t len0; - if (!buf || !apdu) - return SC_ERROR_INVALID_ARGUMENTS; + if (!buf || !apdu) + return SC_ERROR_INVALID_ARGUMENTS; len0 = len; if (len < 4) { - sc_error(ctx, "APDU too short (must be at least 4 bytes)"); - return SC_ERROR_INVALID_DATA; + sc_error(ctx, "APDU too short (must be at least 4 bytes)"); + return SC_ERROR_INVALID_DATA; } memset(apdu, 0, sizeof(*apdu)); @@ -97,30 +97,68 @@ int build_apdu(sc_context_t *ctx, const u8 *buf, size_t len, sc_apdu_t *apdu) apdu->p2 = *p++; len -= 4; if (len > 1) { - apdu->lc = *p++; - len--; - apdu->data = p; - apdu->datalen = apdu->lc; - if (len < apdu->lc) { - sc_error(ctx, "APDU too short (need %lu bytes)\n", - (unsigned long) apdu->lc - len); - return SC_ERROR_INVALID_DATA; - } - len -= apdu->lc; - p += apdu->lc; - if (len) { - apdu->le = *p++; - if (apdu->le == 0) - apdu->le = 256; - len--; - apdu->cse = SC_APDU_CASE_4_SHORT; + /* case 2 with le=0 and case 4 with lc=0 are the only short APDUs, + * where the next byte is 0. Their length (without header) is 1 and + * 2 respectively */ + if (*p == 0 && len > 2) { + /* ...must be an extended length APDU */ + p++; + apdu->lc = (*p++)<<8; + apdu->lc += *p++; + len -= 3; + if (len < apdu->lc) { + sc_error(ctx, "APDU too short (need %lu bytes)\n", + (unsigned long) apdu->lc - len); + return SC_ERROR_INVALID_DATA; + } + len -= apdu->lc; + p += apdu->lc; + if (len) { + if (*p++ != 0) { + sc_error(ctx, "Extended APDU needs Lc, that begins with 0x00)\n", + (unsigned long) apdu->lc - len); + return SC_ERROR_INVALID_DATA; + } + apdu->le = (*p++)<<8; + apdu->le += *p++; + if (apdu->le == 0) + apdu->le = 0xffff; + len -= 3; + apdu->cse = SC_APDU_CASE_4_EXT; + } else { + apdu->cse = SC_APDU_CASE_3_EXT; + } + if (len) { + sc_error(ctx, "APDU too long (%lu bytes extra)\n", + (unsigned long) len); + return SC_ERROR_INVALID_DATA; + } } else { - apdu->cse = SC_APDU_CASE_3_SHORT; - } - if (len) { - sc_error(ctx, "APDU too long (%lu bytes extra)\n", - (unsigned long) len); - return SC_ERROR_INVALID_DATA; + apdu->lc = *p++; + len--; + apdu->data = p; + apdu->datalen = apdu->lc; + if (len < apdu->lc) { + sc_error(ctx, "APDU too short (need %lu bytes)\n", + (unsigned long) apdu->lc - len); + return SC_ERROR_INVALID_DATA; + } + len -= apdu->lc; + p += apdu->lc; + if (len) { + apdu->le = *p++; + if (apdu->le == 0) + apdu->le = 0xff; + len--; + apdu->cse = SC_APDU_CASE_4_SHORT; + } else { + apdu->cse = SC_APDU_CASE_3_SHORT; + } + if (len) { + sc_error(ctx, "APDU too long (%lu bytes extra)\n", + (unsigned long) len); + return SC_ERROR_INVALID_DATA; + } } } else if (len == 1) { apdu->le = *p++; @@ -132,12 +170,12 @@ int build_apdu(sc_context_t *ctx, const u8 *buf, size_t len, sc_apdu_t *apdu) apdu->cse = SC_APDU_CASE_1; } - apdu->flags = SC_APDU_FLAGS_NO_GET_RESP|SC_APDU_FLAGS_NO_RETRY_WL; + apdu->flags = SC_APDU_FLAGS_NO_GET_RESP|SC_APDU_FLAGS_NO_RETRY_WL; - sc_debug(ctx, "APDU, %d bytes:\tins=%02x p1=%02x p2=%02x", - (unsigned int) len0, apdu->ins, apdu->p1, apdu->p2); + sc_debug(ctx, "APDU, %d bytes:\tins=%02x p1=%02x p2=%02x", + (unsigned int) len0, apdu->ins, apdu->p1, apdu->p2); - return SC_SUCCESS; + return SC_SUCCESS; } void _bin_log(sc_context_t *ctx, int type, const char *file, int line, diff --git a/ccid/src/usb.c b/ccid/src/usb.c index 8ae721e..64b377a 100644 --- a/ccid/src/usb.c +++ b/ccid/src/usb.c @@ -989,6 +989,8 @@ static void *ccid (void *param) char *source_name = names[0]; char *sink_name = names[1]; int result; + size_t bufsize = sizeof(PC_to_RDR_XfrBlock_t) + 0xffff; + __u8 inbuf[bufsize]; source_fd = source_open (source_name); if (source_fd < 0) { @@ -1010,14 +1012,6 @@ static void *ccid (void *param) __u8 *outbuf = NULL; pthread_cleanup_push (free, outbuf); - size_t bufsize = 512; - __u8 *inbuf = malloc(bufsize); - pthread_cleanup_push (free, inbuf); - if (inbuf == NULL) { - if (verbose > 1) - perror("malloc"); - goto error; - } do { @@ -1053,7 +1047,6 @@ static void *ccid (void *param) pthread_cleanup_pop (1); pthread_cleanup_pop (1); pthread_cleanup_pop (1); - pthread_cleanup_pop (1); fflush (stdout); fflush (stderr);