[Pcsclite-cvs-commit] r1630 - trunk/Drivers/ccid/src
Ludovic Rousseau
rousseau at costa.debian.org
Thu Sep 1 09:11:31 UTC 2005
Author: rousseau
Date: 2005-09-01 09:11:30 +0000 (Thu, 01 Sep 2005)
New Revision: 1630
Modified:
trunk/Drivers/ccid/src/ccid_ifdhandler.h
trunk/Drivers/ccid/src/commands.c
trunk/Drivers/ccid/src/commands.h
trunk/Drivers/ccid/src/ifdhandler.c
Log:
add support of PC/SC v2 part 10 CM_IOCTL_GET_FEATURE_REQUEST
add support of FEATURE_VERIFY_PIN_DIRECT and FEATURE_MODIFY_PIN_DIRECT
remove support of IOCTL_SMARTCARD_VENDOR_VERIFY_PIN (now obsoleted)
Modified: trunk/Drivers/ccid/src/ccid_ifdhandler.h
===================================================================
--- trunk/Drivers/ccid/src/ccid_ifdhandler.h 2005-09-01 08:25:50 UTC (rev 1629)
+++ trunk/Drivers/ccid/src/ccid_ifdhandler.h 2005-09-01 09:11:30 UTC (rev 1630)
@@ -25,8 +25,13 @@
#define _ccid_ifd_handler_h_
#define IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE SCARD_CTL_CODE(1)
-#define IOCTL_SMARTCARD_VENDOR_VERIFY_PIN SCARD_CTL_CODE(2)
+#define CLASS2_IOCTL_MAGIC 0x330000
+#define IOCTL_FEATURE_VERIFY_PIN_DIRECT \
+ SCARD_CTL_CODE(FEATURE_VERIFY_PIN_DIRECT + CLASS2_IOCTL_MAGIC)
+#define IOCTL_FEATURE_MODIFY_PIN_DIRECT \
+ SCARD_CTL_CODE(FEATURE_MODIFY_PIN_DIRECT + CLASS2_IOCTL_MAGIC)
+
#define DRIVER_OPTION_CCID_EXCHANGE_AUTHORIZED 1
#define DRIVER_OPTION_GEMPC_TWIN_KEY_APDU 2
#define DRIVER_OPTION_USE_BOGUS_FIRMWARE 4
Modified: trunk/Drivers/ccid/src/commands.c
===================================================================
--- trunk/Drivers/ccid/src/commands.c 2005-09-01 08:25:50 UTC (rev 1629)
+++ trunk/Drivers/ccid/src/commands.c 2005-09-01 09:11:30 UTC (rev 1630)
@@ -155,18 +155,18 @@
/*****************************************************************************
*
- * SecurePIN
+ * SecurePINVerify
*
****************************************************************************/
-RESPONSECODE SecurePIN(unsigned int reader_index,
+RESPONSECODE SecurePINVerify(unsigned int reader_index,
const unsigned char TxBuffer[], unsigned int TxLength,
unsigned char RxBuffer[], unsigned int *RxLength)
{
unsigned char cmd[11+14+CMD_BUF_SIZE];
+ unsigned int a, b;
_ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
cmd[0] = 0x69; /* Secure */
- i2dw(TxLength+1, cmd+1); /* command length (includes bPINOperation) */
cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
cmd[6] = (*ccid_descriptor->pbSeq)++;
cmd[7] = 0; /* bBWI */
@@ -174,18 +174,52 @@
cmd[9] = 0;
cmd[10] = 0; /* bPINOperation: PIN Verification */
- /* check that the command is not too large */
- if (TxLength > 14+CMD_BUF_SIZE)
+ /* 16 is the size of the PCSC PIN verify structure
+ * The equivalent CCID structure is only 14-bytes long */
+ if (TxLength > 16+CMD_BUF_SIZE) /* command too large? */
+ {
+ DEBUG_INFO3("Command too long: %d > %d", TxLength, 16+CMD_BUF_SIZE);
+ *RxLength = 0;
return IFD_NOT_SUPPORTED;
+ }
- /* CCID data structure + APDU */
- memcpy(cmd + 11, TxBuffer, TxLength);
+ if (TxLength < 16+4 /* 4 = APDU size */) /* command too short? */
+ {
+ DEBUG_INFO3("Command too short: %d < %d", TxLength, 16+4);
+ *RxLength = 0;
+ return IFD_NOT_SUPPORTED;
+ }
+ if (TxBuffer[15] + 16 != TxLength) /* ulDataLength field coherency */
+ {
+ DEBUG_INFO3("Wrong lengths: %d %d", TxBuffer[15] + 16, TxLength);
+ *RxLength = 0;
+ return IFD_NOT_SUPPORTED;
+ }
+
+ /* Build a CCID block from a PC/SC V2.1.2 Part 10 block */
+ for (a = 11, b = 0; b < TxLength; b++)
+ {
+ if (1 == b) /* bTimeOut2 field */
+ /* Ignore the second timeout as there's nothing we can do with
+ * it currently */
+ continue;
+
+ if (15 == b) /* ulDataLength field */
+ /* the ulDataLength field is not present in the CCID frame
+ * so do not copy */
+ continue;
+
+ /* copy the CCID block 'verbatim' */
+ cmd[a] = TxBuffer[b];
+ a++;
+ }
+
/* SPR532 and Case 1 APDU */
- if ((SPR532 == ccid_descriptor->readerID) && (TxLength - 14 == 4))
+ if ((SPR532 == ccid_descriptor->readerID) && (TxBuffer[15] == 4))
{
RESPONSECODE return_value;
- unsigned char cmd[] = { 0x80,0x02, 0x00 };
+ unsigned char cmd[] = { 0x80, 0x02, 0x00 };
unsigned char res[1];
unsigned int res_length = sizeof(res);
@@ -199,15 +233,96 @@
}
}
- if (WritePort(reader_index, TxLength+1+10, cmd) != STATUS_SUCCESS)
+ i2dw(a - 10, cmd + 1); /* CCID message length */
+
+ if (WritePort(reader_index, a, cmd) != STATUS_SUCCESS)
return IFD_COMMUNICATION_ERROR;
return CCID_Receive(reader_index, RxLength, RxBuffer);
-} /* SecurePIN */
+} /* SecurePINVerify */
/*****************************************************************************
*
+ * SecurePINModify
+ *
+ ****************************************************************************/
+RESPONSECODE SecurePINModify(unsigned int reader_index,
+ const unsigned char TxBuffer[], unsigned int TxLength,
+ unsigned char RxBuffer[], unsigned int *RxLength)
+{
+ unsigned char cmd[11+19+CMD_BUF_SIZE];
+ unsigned int a, b;
+ _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
+
+ cmd[0] = 0x69; /* Secure */
+ cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
+ cmd[6] = (*ccid_descriptor->pbSeq)++;
+ cmd[7] = 0; /* bBWI */
+ cmd[8] = 0; /* wLevelParameter */
+ cmd[9] = 0;
+ cmd[10] = 1; /* bPINOperation: PIN Modification */
+
+ /* 21 is the size of the PCSC PIN modify structure
+ * The equivalent CCID structure is only 18 or 19-bytes long */
+ if ((TxLength > 19+CMD_BUF_SIZE) /* command too large? */
+ || (TxLength < 18+4 /* 4 = APDU size */) /* command too short? */
+ || (TxBuffer[20] + 21 != TxLength)) /* ulDataLength field coherency */
+ return IFD_NOT_SUPPORTED;
+
+ /* Make sure in the beginning if bNumberMessage is valid or not */
+ if (TxBuffer[11] > 3)
+ return IFD_NOT_SUPPORTED;
+
+ /* Build a CCID block from a PC/SC V2.1.2 Part 10 block */
+
+ /* Do adjustments as needed - CCID spec is not exact with some
+ * details in the format of the structure, per-reader adaptions
+ * might be needed.
+ */
+ for (a = 11, b = 0; b < TxLength; b++)
+ {
+ if (1 == b) /* bTimeOut2 */
+ /* Ignore the second timeout as there's nothing we can do with it
+ * currently */
+ continue;
+
+ if (16 == b) /* bMsgIndex3 */
+ {
+ /*
+ * SPR 532 has no display but requires _all_ bMsgIndex
+ * fields with bNumberMessage set to 0.
+ */
+ if (SPR532 == ccid_descriptor->readerID)
+ {
+ cmd[21] = 0x00; /* set bNumberMessages to 0 */
+ cmd[a] = cmd[a-1] = cmd[a-2] = 0; /* bMsgIndex123 */
+ a++;
+ continue;
+ }
+
+ /* in CCID the bMsgIndex3 is present only if bNumberMessage == 3 */
+ if (TxBuffer[11] < 3)
+ continue;
+ }
+
+ /* copy to the CCID block 'verbatim' */
+ cmd[a] = TxBuffer[b];
+ a++;
+ }
+
+ /* We know the size of the CCID message now */
+ i2dw(a - 10, cmd + 1); /* command length (includes bPINOperation) */
+
+ if (WritePort(reader_index, a, cmd) != STATUS_SUCCESS)
+ return IFD_COMMUNICATION_ERROR;
+
+ return CCID_Receive(reader_index, RxLength, RxBuffer);
+} /* SecurePINModify */
+
+
+/*****************************************************************************
+ *
* Escape
*
****************************************************************************/
@@ -496,11 +611,32 @@
if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
{
ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__); /* bError */
- *rx_length = 0; /* nothing received */
- if (0xFD == cmd[ERROR_OFFSET]) /* Parity error during exchange */
- return IFD_PARITY_ERROR;
- else
- return IFD_COMMUNICATION_ERROR;
+ switch (cmd[ERROR_OFFSET])
+ {
+ case 0xEF: /* cancel */
+ if (*rx_length < 2)
+ return IFD_COMMUNICATION_ERROR;
+ rx_buffer[0]= 0x64;
+ rx_buffer[1]= 0x01;
+ *rx_length = 2;
+ return IFD_SUCCESS;
+
+ case 0xF0: /* timeout */
+ if (*rx_length < 2)
+ return IFD_COMMUNICATION_ERROR;
+ rx_buffer[0]= 0x64;
+ rx_buffer[1]= 0x00;
+ *rx_length = 2;
+ return IFD_SUCCESS;
+
+ case 0xFD: /* Parity error during exchange */
+ *rx_length = 0; /* nothing received */
+ return IFD_PARITY_ERROR;
+
+ default:
+ *rx_length = 0; /* nothing received */
+ return IFD_COMMUNICATION_ERROR;
+ }
}
if (cmd[STATUS_OFFSET] & CCID_TIME_EXTENSION)
Modified: trunk/Drivers/ccid/src/commands.h
===================================================================
--- trunk/Drivers/ccid/src/commands.h 2005-09-01 08:25:50 UTC (rev 1629)
+++ trunk/Drivers/ccid/src/commands.h 2005-09-01 09:11:30 UTC (rev 1630)
@@ -28,10 +28,14 @@
RESPONSECODE CmdPowerOn(unsigned int reader_index, unsigned int * nlength,
unsigned char buffer[]);
-RESPONSECODE SecurePIN(unsigned int reader_index,
+RESPONSECODE SecurePINVerify(unsigned int reader_index,
const unsigned char TxBuffer[], unsigned int TxLength,
unsigned char RxBuffer[], unsigned int *RxLength);
+RESPONSECODE SecurePINModify(unsigned int reader_index,
+ const unsigned char TxBuffer[], unsigned int TxLength,
+ unsigned char RxBuffer[], unsigned int *RxLength);
+
RESPONSECODE CmdEscape(unsigned int reader_index,
const unsigned char TxBuffer[], unsigned int TxLength,
unsigned char RxBuffer[], unsigned int *RxLength);
Modified: trunk/Drivers/ccid/src/ifdhandler.c
===================================================================
--- trunk/Drivers/ccid/src/ifdhandler.c 2005-09-01 08:25:50 UTC (rev 1629)
+++ trunk/Drivers/ccid/src/ifdhandler.c 2005-09-01 09:11:30 UTC (rev 1630)
@@ -301,14 +301,6 @@
}
break;
- case IOCTL_SMARTCARD_VENDOR_VERIFY_PIN:
- if (*Length >= 1)
- {
- *Length = 1;
- *Value = get_ccid_descriptor(reader_index) -> bPINSupport & CCID_CLASS_PIN_VERIFY;
- }
- break;
-
default:
return IFD_ERROR_TAG;
}
@@ -897,16 +889,66 @@
}
}
- if (IOCTL_SMARTCARD_VENDOR_VERIFY_PIN == dwControlCode)
+ /* Implement the PC/SC v2.1.2 Part 10 IOCTL mechanism */
+
+ /* Query for features */
+ if (CM_IOCTL_GET_FEATURE_REQUEST == dwControlCode)
{
+ unsigned int iBytesReturned = 0;
+ PCSC_TLV_STRUCTURE *pcsc_tlv = (PCSC_TLV_STRUCTURE *)RxBuffer;
+
+ /* we need room for two records */
+ if (RxLength < 2 * sizeof(PCSC_TLV_STRUCTURE))
+ return IFD_COMMUNICATION_ERROR;
+
+ /* We can only support direct verify and/or modify currently */
+ if (get_ccid_descriptor(reader_index) -> bPINSupport
+ & CCID_CLASS_PIN_VERIFY)
+ {
+ pcsc_tlv -> tag = FEATURE_VERIFY_PIN_DIRECT;
+ pcsc_tlv -> length = 0x04; /* always 0x04 */
+ pcsc_tlv -> value = IOCTL_FEATURE_VERIFY_PIN_DIRECT;
+
+ pcsc_tlv++;
+ iBytesReturned += 6;
+ }
+
+ if (get_ccid_descriptor(reader_index) -> bPINSupport
+ & CCID_CLASS_PIN_MODIFY)
+ {
+ pcsc_tlv -> tag = FEATURE_MODIFY_PIN_DIRECT;
+ pcsc_tlv -> length = 0x04; /* always 0x04 */
+ pcsc_tlv -> value = IOCTL_FEATURE_MODIFY_PIN_DIRECT;
+
+ pcsc_tlv++;
+ iBytesReturned += 6;
+ }
+ *pdwBytesReturned = iBytesReturned;
+ return_value = IFD_SUCCESS;
+ }
+
+ /* Verify a PIN, plain CCID */
+ if (IOCTL_FEATURE_VERIFY_PIN_DIRECT == dwControlCode)
+ {
unsigned int iBytesReturned;
iBytesReturned = RxLength;
- return_value = SecurePIN(reader_index, TxBuffer, TxLength, RxBuffer,
- &iBytesReturned);
+ return_value = SecurePINVerify(reader_index, TxBuffer, TxLength,
+ RxBuffer, &iBytesReturned);
*pdwBytesReturned = iBytesReturned;
}
+ /* Modify a PIN, plain CCID */
+ if (IOCTL_FEATURE_MODIFY_PIN_DIRECT == dwControlCode)
+ {
+ unsigned int iBytesReturned;
+
+ iBytesReturned = RxLength;
+ return_value = SecurePINModify(reader_index, TxBuffer, TxLength,
+ RxBuffer, &iBytesReturned);
+ *pdwBytesReturned = iBytesReturned;
+ }
+
return return_value;
} /* IFDHControl */
More information about the Pcsclite-cvs-commit
mailing list