|
Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com |
From: Max Vozeler (max.vozeler
lsexperts.de)
Date: Mon Feb 01 2010 - 05:20:43 CST
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
This adds support for a custom escape command that allows
OmniKey Cardman 3021/3121 (and likely other Omnikey readers)
to handle extended T=1 APDUs.
Note that this patch was written in a way that would minimize
the source changes. It could probably be abstracted away in
a much nicer way.
--- ccid-1.3.11/src/commands.c
+++ ccid-1.3.11/src/commands.c

-81,6 +81,11 
enum {
* Makes us map HW_ERROR to "no card inserted".
*/
QUIRK_SLOTSTATUS_HWERR = 1,
+
+ /*
+ * Escape for extended APDUs
+ */
+ QUIRK_ESC_T1_TPDU = 2,
};
struct ccid_quirk {

-102,6 +107,11 
static struct ccid_quirk ccid_quirktab[] = {
*/
{ 0x0a5c5800, QUIRK_SLOTSTATUS_HWERR },
{ 0x0a5c5801, QUIRK_SLOTSTATUS_HWERR },
+
+ /*
+ * OmniKey CardMan 3021/3121
+ */
+ { 0x076b3021, QUIRK_ESC_T1_TPDU },
};
static int ccid_quirk_lookup(_ccid_descriptor *ccid, unsigned int *quirks)

-1144,8 +1154,13 
RESPONSECODE CmdXfrBlock(unsigned int reader_index, unsigned int tx_length,
break;
case CCID_CLASS_SHORT_APDU:
- return_value = CmdXfrBlockTPDU_T0(reader_index,
- tx_length, tx_buffer, rx_length, rx_buffer);
+ if (ccid_quirk_required(ccid_descriptor, QUIRK_ESC_T1_TPDU) && protocol == T_1)
+ return_value = CmdXfrBlockTPDU_T1(reader_index, tx_length,
+ tx_buffer, rx_length, rx_buffer);
+ else
+ return_value = CmdXfrBlockTPDU_T0(reader_index,
+ tx_length, tx_buffer, rx_length, rx_buffer);
+
break;
case CCID_CLASS_EXTENDED_APDU:

-1181,7 +1196,8 
RESPONSECODE CmdXfrBlock(unsigned int reader_index, unsigned int tx_length,
RESPONSECODE CCID_Transmit(unsigned int reader_index, unsigned int tx_length,
const unsigned char tx_buffer[], unsigned short rx_length, unsigned char bBWI)
{
- unsigned char cmd[10+CMD_BUF_SIZE]; /* CCID + APDU buffer */
+ unsigned char cmd[11+CMD_BUF_SIZE]; /* CCID + APDU buffer */
+ size_t cmdlen;
_ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
status_t ret;

-1227,13 +1243,30 
RESPONSECODE CCID_Transmit(unsigned int reader_index, unsigned int tx_length,
}
#endif
- cmd[0] = 0x6F; /* XfrBlock */
- i2dw(tx_length, cmd+1); /* APDU length */
- cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
- cmd[6] = (*ccid_descriptor->pbSeq)++;
- cmd[7] = bBWI; /* extend block waiting timeout */
- cmd[8] = rx_length & 0xFF; /* Expected length, in character mode only */
- cmd[9] = (rx_length >> 8) & 0xFF;
+ if (ccid_quirk_required(ccid_descriptor, QUIRK_ESC_T1_TPDU) &&
+ ccid_descriptor->cardProtocol == SCARD_PROTOCOL_T1)
+ {
+ cmd[0] = 0x6B; /* Escape */
+ i2dw(tx_length+1, cmd+1); /* APDU length */
+ cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
+ cmd[6] = (*ccid_descriptor->pbSeq)++;
+ cmd[7] = cmd[8] = cmd[9] = 0x00; /* RFU */
+ cmd[10] = 0x1A; /* custom cmd "send TPDU" */
+
+ cmdlen = 11;
+ }
+ else
+ {
+ cmd[0] = 0x6F; /* XfrBlock */
+ i2dw(tx_length, cmd+1); /* APDU length */
+ cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
+ cmd[6] = (*ccid_descriptor->pbSeq)++;
+ cmd[7] = bBWI; /* extend block waiting timeout */
+ cmd[8] = rx_length & 0xFF; /* Expected length, in character mode only */
+ cmd[9] = (rx_length >> 8) & 0xFF;
+
+ cmdlen = 10;
+ }
/* check that the command is not too large */
if (tx_length > CMD_BUF_SIZE)

-1242,9 +1275,9 
RESPONSECODE CCID_Transmit(unsigned int reader_index, unsigned int tx_length,
return IFD_NOT_SUPPORTED;
}
- memcpy(cmd+10, tx_buffer, tx_length);
+ memcpy(cmd+cmdlen, tx_buffer, tx_length);
- ret = WritePort(reader_index, 10+tx_length, cmd);
+ ret = WritePort(reader_index, cmdlen+tx_length, cmd);
if (STATUS_NO_SUCH_DEVICE == ret)
return IFD_NO_SUCH_DEVICE;
if (ret != STATUS_SUCCESS)

-1262,7 +1295,7 
RESPONSECODE CCID_Transmit(unsigned int reader_index, unsigned int tx_length,
RESPONSECODE CCID_Receive(unsigned int reader_index, unsigned int *rx_length,
unsigned char rx_buffer[], unsigned char *chain_parameter)
{
- unsigned char cmd[10+CMD_BUF_SIZE]; /* CCID + APDU buffer */
+ unsigned char cmd[11+CMD_BUF_SIZE]; /* CCID + APDU buffer */
unsigned int length;
RESPONSECODE return_value = IFD_SUCCESS;
status_t ret;

-1438,8 +1471,13 
time_request:
}
length = dw2i(cmd, 1);
- if (length <= *rx_length)
+ if (length <= *rx_length) {
*rx_length = length;
+
+ if (ccid_quirk_required(ccid_descriptor, QUIRK_ESC_T1_TPDU) &&
+ ccid_descriptor->cardProtocol == SCARD_PROTOCOL_T1)
+ *rx_length--;
+ }
else
{
DEBUG_CRITICAL2("overrun by %d bytes", length - *rx_length);

-1454,7 +1492,13 
time_request:
return_value = IFD_COMMUNICATION_ERROR;
}
else
- memcpy(rx_buffer, cmd+10, length);
+ {
+ if (ccid_quirk_required(ccid_descriptor, QUIRK_ESC_T1_TPDU) &&
+ ccid_descriptor->cardProtocol == SCARD_PROTOCOL_T1)
+ memcpy(rx_buffer, cmd+11, length-1);
+ else
+ memcpy(rx_buffer, cmd+10, length);
+ }
/* Extended case?
* Only valid for RDR_to_PC_DataBlock frames */

-1636,6 +1680,12 
static RESPONSECODE CmdXfrBlockTPDU_T0(unsigned int reader_index,
}
else
#endif
+ if (ccid_quirk_required(ccid_descriptor, QUIRK_ESC_T1_TPDU))
+ {
+ DEBUG_CRITICAL3("Ignoring dwMaxCCDMessageLength (tx=%d, max=%d)",
+ tx_length, ccid_descriptor->dwMaxCCIDMessageLength-10);
+ }
+ else
{
DEBUG_CRITICAL3("Command too long (%d bytes) for max: %d bytes",
tx_length, ccid_descriptor->dwMaxCCIDMessageLength-10);
_______________________________________________
Muscle mailing list
Muscle
lists.musclecard.com
http://lists.drizzle.com/mailman/listinfo/muscle
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]