OSEC

Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com
[Muscle] [PATCH] Support extended APDU for OmniKey 3021/3121

From: Max Vozeler (max.vozelerlsexperts.de)
Date: Mon Feb 01 2010 - 05:20:43 CST


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
Musclelists.musclecard.com
http://lists.drizzle.com/mailman/listinfo/muscle