- changed default ccid command buffer size to support sending extended apdus in a single transmit (only for ccid-1.3.11 necessary) git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@276 96b47cad-a561-4643-ad3b-153ac7d7599c
496 lines
17 KiB
Diff
496 lines
17 KiB
Diff
Index: ccid-1.3.11/src/ifdhandler.c
|
|
===================================================================
|
|
--- ccid-1.3.11/src/ifdhandler.c (Revision 4347)
|
|
+++ ccid-1.3.11/src/ifdhandler.c (Arbeitskopie)
|
|
@@ -1266,6 +1266,16 @@
|
|
iBytesReturned += sizeof(PCSC_TLV_STRUCTURE);
|
|
}
|
|
|
|
+ if (get_ccid_descriptor(reader_index) -> bPINSupport & CCID_CLASS_PIN_PACE_CAPABILITIES)
|
|
+ {
|
|
+ pcsc_tlv -> tag = FEATURE_EXECUTE_PACE;
|
|
+ pcsc_tlv -> length = 0x04; /* always 0x04 */
|
|
+ pcsc_tlv -> value = htonl(IOCTL_FEATURE_EXECUTE_PACE);
|
|
+
|
|
+ pcsc_tlv++;
|
|
+ iBytesReturned += sizeof(PCSC_TLV_STRUCTURE);
|
|
+ }
|
|
+
|
|
#ifdef FEATURE_IFD_PIN_PROPERTIES
|
|
/* We can always forward wLcdLayout */
|
|
pcsc_tlv -> tag = FEATURE_IFD_PIN_PROPERTIES;
|
|
@@ -1365,6 +1375,43 @@
|
|
}
|
|
}
|
|
|
|
+ if (IOCTL_FEATURE_EXECUTE_PACE == dwControlCode)
|
|
+ {
|
|
+ if (TxLength < 3 || !TxBuffer) {
|
|
+ DEBUG_CRITICAL("Buffer too small, could not determine length of "
|
|
+ "input data");
|
|
+ return_value = IFD_COMMUNICATION_ERROR;
|
|
+ } else {
|
|
+ uint16_t lengthInputData;
|
|
+ memcpy(&lengthInputData, &TxBuffer[1], 2);
|
|
+
|
|
+ if (TxLength != 3+lengthInputData) {
|
|
+ DEBUG_CRITICAL3("Buffer too small or too big to contain only "
|
|
+ "function index and input data (expected %u, got %u)",
|
|
+ 3+lengthInputData, TxLength);
|
|
+ return_value = IFD_COMMUNICATION_ERROR;
|
|
+ } else {
|
|
+ unsigned int iBytesReturned;
|
|
+ iBytesReturned = RxLength;
|
|
+
|
|
+ if (*TxBuffer == 1) {
|
|
+ return_value = SecurePINPACECapabilities(reader_index,
|
|
+ TxBuffer + 3, lengthInputData,
|
|
+ RxBuffer, &iBytesReturned);
|
|
+ *pdwBytesReturned = iBytesReturned;
|
|
+ } else if (*TxBuffer == 2) {
|
|
+ return_value = SecurePINPACEVerify(reader_index,
|
|
+ TxBuffer + 3, lengthInputData,
|
|
+ RxBuffer, &iBytesReturned);
|
|
+ *pdwBytesReturned = iBytesReturned;
|
|
+ } else {
|
|
+ DEBUG_CRITICAL2("Unknown PACE function %u", *TxBuffer);
|
|
+ return_value = IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
if (IFD_SUCCESS != return_value)
|
|
*pdwBytesReturned = 0;
|
|
|
|
Index: ccid-1.3.11/src/commands.c
|
|
===================================================================
|
|
--- ccid-1.3.11/src/commands.c (Revision 4347)
|
|
+++ ccid-1.3.11/src/commands.c (Arbeitskopie)
|
|
@@ -68,7 +68,19 @@
|
|
unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
|
|
unsigned char rx_buffer[]);
|
|
|
|
+static RESPONSECODE SecurePINPACE(unsigned int reader_index,
|
|
+ unsigned char TxBuffer[], unsigned int TxLength,
|
|
+ unsigned char RxBuffer[], unsigned int *RxLength,
|
|
+ unsigned char bPINOperation);
|
|
+
|
|
+static RESPONSECODE transform_EstablishPACEChannel_InputData(
|
|
+ unsigned char input[], unsigned int input_length);
|
|
+
|
|
+static RESPONSECODE transform_EstablishPACEChannel_OutputData(
|
|
+ unsigned char output[], unsigned int output_length);
|
|
+
|
|
static void i2dw(int value, unsigned char *buffer);
|
|
+static void i2w(uint16_t value, unsigned char *buffer);
|
|
|
|
|
|
/*****************************************************************************
|
|
@@ -691,7 +703,306 @@
|
|
return ret;
|
|
} /* SecurePINModify */
|
|
|
|
+static RESPONSECODE transform_EstablishPACEChannel_InputData(
|
|
+ unsigned char input[], unsigned int input_length)
|
|
+{
|
|
+ uint8_t lengthCHAT, lengthPIN;
|
|
+ uint16_t lengthCertificateDescription;
|
|
+ size_t parsed = 0;
|
|
|
|
+ /* transform length fields of input data to little endian */
|
|
+
|
|
+ if (input_length < parsed+1) {
|
|
+ DEBUG_CRITICAL("Malformed Establish PACE Channel input data.");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+ switch (input[parsed]) {
|
|
+ case 0x01:
|
|
+ DEBUG_COMM("Initiating PACE with MRZ");
|
|
+ break;
|
|
+ case 0x02:
|
|
+ DEBUG_COMM("Initiating PACE with CAN");
|
|
+ break;
|
|
+ case 0x03:
|
|
+ DEBUG_COMM("Initiating PACE with PIN");
|
|
+ break;
|
|
+ case 0x04:
|
|
+ DEBUG_COMM("Initiating PACE with PUK");
|
|
+ break;
|
|
+ default:
|
|
+ DEBUG_COMM("Initiating PACE with unknown PACE secret type");
|
|
+ break;
|
|
+ }
|
|
+ parsed += 1;
|
|
+
|
|
+ if (input_length < parsed+1) {
|
|
+ DEBUG_CRITICAL("Malformed Establish PACE Channel input data.");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+ lengthCHAT = input[parsed];
|
|
+ parsed += 1;
|
|
+
|
|
+ if (input_length < parsed+lengthCHAT) {
|
|
+ DEBUG_CRITICAL("Malformed Establish PACE Channel input data.");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+ if (lengthCHAT)
|
|
+ DEBUG_INFO_XXD("CHAT:\n", &input[parsed], lengthCHAT);
|
|
+ parsed += lengthCHAT;
|
|
+
|
|
+ if (input_length < parsed+1) {
|
|
+ DEBUG_CRITICAL("Malformed Establish PACE Channel input data.");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+ lengthPIN = input[parsed];
|
|
+ parsed += 1;
|
|
+
|
|
+ if (input_length < parsed+lengthPIN) {
|
|
+ DEBUG_CRITICAL("Malformed Establish PACE Channel input data.");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+#if 0
|
|
+ /* dont print secrets... */
|
|
+ if (lengthPIN)
|
|
+ DEBUG_INFO_XXD("PIN:\n", &input[parsed], lengthPIN);
|
|
+#endif
|
|
+ parsed += lengthPIN;
|
|
+
|
|
+ if (input_length < parsed+2) {
|
|
+ DEBUG_CRITICAL("Malformed Establish PACE Channel input data.");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+ memcpy(&lengthCertificateDescription, &input[parsed], 2);
|
|
+ i2w(lengthCertificateDescription, &input[parsed]);
|
|
+ parsed += 2;
|
|
+
|
|
+ if (input_length < parsed+lengthCertificateDescription) {
|
|
+ DEBUG_CRITICAL("Malformed Establish PACE Channel input data.");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+ if (lengthCertificateDescription)
|
|
+ DEBUG_INFO_XXD("Certificate description:\n", &input[parsed], lengthCertificateDescription);
|
|
+ parsed += lengthCertificateDescription;
|
|
+
|
|
+ if (parsed < input_length) {
|
|
+ DEBUG_CRITICAL2("Overrun by %u bytes", input_length - parsed);
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+
|
|
+ return IFD_SUCCESS;
|
|
+}
|
|
+
|
|
+static RESPONSECODE transform_EstablishPACEChannel_OutputData(
|
|
+ unsigned char output[], unsigned int output_length)
|
|
+{
|
|
+ uint8_t lengthCAR, lengthCARprev;
|
|
+ uint16_t lengthEF_CardAccess, length_IDicc;
|
|
+ size_t parsed = 0;
|
|
+
|
|
+ if (parsed+2 > output_length) {
|
|
+ DEBUG_CRITICAL("Malformed Establish PACE Channel output data.");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+ DEBUG_INFO3("MSE:Set AT Statusbytes: %02X %02X",
|
|
+ output[parsed+0], output[parsed+1]);
|
|
+ parsed += 2;
|
|
+
|
|
+ if (parsed+2 > output_length) {
|
|
+ DEBUG_CRITICAL("Malformed Establish PACE Channel output data.");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+ lengthEF_CardAccess = w2i(output, parsed);
|
|
+ memcpy(&output[parsed], &lengthEF_CardAccess, 2);
|
|
+ parsed += 2;
|
|
+
|
|
+ if (parsed+lengthEF_CardAccess > output_length) {
|
|
+ DEBUG_CRITICAL("Malformed Establish PACE Channel output data.");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+ if (lengthEF_CardAccess)
|
|
+ DEBUG_INFO_XXD("EF.CardAccess:\n", &output[parsed], lengthEF_CardAccess);
|
|
+ parsed += lengthEF_CardAccess;
|
|
+
|
|
+ if (parsed+1 > output_length) {
|
|
+ DEBUG_CRITICAL("Malformed Establish PACE Channel output data.");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+ lengthCAR = output[parsed];
|
|
+ parsed += 1;
|
|
+
|
|
+ if (parsed+lengthCAR > output_length) {
|
|
+ DEBUG_CRITICAL("Malformed Establish PACE Channel output data.");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+ if (lengthCAR)
|
|
+ DEBUG_INFO_XXD("Recent Certificate Authority:\n",
|
|
+ &output[parsed], lengthCAR);
|
|
+ parsed += lengthCAR;
|
|
+
|
|
+ if (parsed+1 > output_length) {
|
|
+ DEBUG_CRITICAL("Malformed Establish PACE Channel output data.");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+ lengthCARprev = output[parsed];
|
|
+ parsed += 1;
|
|
+
|
|
+ if (parsed+lengthCARprev > output_length) {
|
|
+ DEBUG_CRITICAL("Malformed Establish PACE Channel output data.");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+ if (lengthCARprev)
|
|
+ DEBUG_INFO_XXD("Previous Certificate Authority:\n",
|
|
+ &output[parsed], lengthCARprev);
|
|
+ parsed += lengthCARprev;
|
|
+
|
|
+ if (parsed+2 > output_length) {
|
|
+ DEBUG_CRITICAL("Malformed Establish PACE Channel output data.");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+ length_IDicc = w2i(output, parsed);
|
|
+ memcpy(&output[parsed], &length_IDicc, 2);
|
|
+ parsed += 2;
|
|
+
|
|
+ if (parsed+length_IDicc > output_length) {
|
|
+ DEBUG_CRITICAL("Malformed Establish PACE Channel output data.");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+ if (length_IDicc)
|
|
+ DEBUG_INFO_XXD("IDicc:\n", &output[parsed], length_IDicc);
|
|
+ parsed += length_IDicc;
|
|
+
|
|
+ if (parsed < output_length) {
|
|
+ DEBUG_CRITICAL2("Overrun by %u bytes", output_length - parsed);
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+
|
|
+ return IFD_SUCCESS;
|
|
+}
|
|
+
|
|
+RESPONSECODE SecurePINPACEVerify(unsigned int reader_index,
|
|
+ unsigned char TxBuffer[], unsigned int TxLength,
|
|
+ unsigned char RxBuffer[], unsigned int *RxLength)
|
|
+{
|
|
+ RESPONSECODE return_value;
|
|
+ int old_read_timeout;
|
|
+ _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
|
|
+
|
|
+ old_read_timeout= ccid_descriptor -> readTimeout;
|
|
+ ccid_descriptor -> readTimeout = 30*1000; /* 30 seconds */
|
|
+
|
|
+ return_value = transform_EstablishPACEChannel_InputData(TxBuffer, TxLength);
|
|
+ if (IFD_SUCCESS != return_value)
|
|
+ goto err;
|
|
+
|
|
+ /* bPINOperation: PIN PACE Capabilities */
|
|
+ return_value = SecurePINPACE(reader_index, TxBuffer, TxLength, RxBuffer,
|
|
+ RxLength, CCID_CLASS_PIN_PACE_EXECUTE);
|
|
+ if (IFD_SUCCESS != return_value)
|
|
+ goto err;
|
|
+
|
|
+ if (*RxLength < 6) {
|
|
+ DEBUG_CRITICAL("Malformed Establish PACE output buffer.");
|
|
+ return_value = IFD_COMMUNICATION_ERROR;
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ return_value = transform_EstablishPACEChannel_OutputData(RxBuffer+6, (*RxLength)-6);
|
|
+ if (IFD_SUCCESS != return_value)
|
|
+ goto err;
|
|
+
|
|
+err:
|
|
+ ccid_descriptor -> readTimeout = old_read_timeout;
|
|
+ return return_value;
|
|
+}
|
|
+
|
|
+RESPONSECODE SecurePINPACECapabilities(unsigned int reader_index,
|
|
+ unsigned char TxBuffer[], unsigned int TxLength,
|
|
+ unsigned char RxBuffer[], unsigned int *RxLength)
|
|
+{
|
|
+ /* bPINOperation: PIN PACE Capabilities */
|
|
+ return SecurePINPACE(reader_index, TxBuffer, TxLength, RxBuffer,
|
|
+ RxLength, CCID_CLASS_PIN_PACE_CAPABILITIES);
|
|
+}
|
|
+
|
|
+static RESPONSECODE SecurePINPACE(unsigned int reader_index,
|
|
+ unsigned char TxBuffer[], unsigned int TxLength,
|
|
+ unsigned char RxBuffer[], unsigned int *RxLength,
|
|
+ unsigned char bPINOperation)
|
|
+{
|
|
+ unsigned char cmd[1024];
|
|
+ unsigned int length;
|
|
+ _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
|
|
+ status_t res;
|
|
+
|
|
+ cmd[0] = 0x69; /* Secure */
|
|
+ i2dw(TxLength, cmd+1); /* dwLength */
|
|
+ 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] = bPINOperation;
|
|
+
|
|
+ memcpy(cmd + 11, TxBuffer, TxLength);
|
|
+
|
|
+ res = WritePort(reader_index, 11 + TxLength, cmd);
|
|
+ if (res != STATUS_SUCCESS)
|
|
+ {
|
|
+ DEBUG_CRITICAL("");
|
|
+ if (STATUS_NO_SUCH_DEVICE == res)
|
|
+ return IFD_NO_SUCH_DEVICE;
|
|
+ DEBUG_CRITICAL("");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+
|
|
+ length = sizeof(cmd);
|
|
+ res = ReadPort(reader_index, &length, cmd);
|
|
+ if (res != STATUS_SUCCESS)
|
|
+ {
|
|
+ DEBUG_CRITICAL("");
|
|
+ if (STATUS_NO_SUCH_DEVICE == res)
|
|
+ return IFD_NO_SUCH_DEVICE;
|
|
+ DEBUG_CRITICAL("");
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+
|
|
+ if (length < STATUS_OFFSET+1)
|
|
+ {
|
|
+ DEBUG_CRITICAL2("Not enough data received: %d bytes", length);
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+
|
|
+ if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
|
|
+ {
|
|
+ ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__); /* bError */
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+
|
|
+ /* we have read less (or more) data than the CCID frame says to contain */
|
|
+ if (length-10 != dw2i(cmd, 1))
|
|
+ {
|
|
+ DEBUG_CRITICAL3("Can't read all data (%d out of %d expected)",
|
|
+ length-10, dw2i(cmd, 1));
|
|
+ return IFD_COMMUNICATION_ERROR;
|
|
+ }
|
|
+
|
|
+ length = dw2i(cmd, 1);
|
|
+ if (length + 6 <= *RxLength)
|
|
+ *RxLength = length + 6;
|
|
+ else
|
|
+ {
|
|
+ DEBUG_CRITICAL2("overrun by %d bytes", length + 6 - *RxLength);
|
|
+ return IFD_ERROR_INSUFFICIENT_BUFFER;
|
|
+ }
|
|
+ uint32_t s = 0x00000000; /* "Kein Fehler" */
|
|
+ memcpy(RxBuffer, &s, 4);
|
|
+ memcpy(RxBuffer+4, &length, 2); /* lengthOutputData */
|
|
+ memcpy(RxBuffer+6, &cmd[10], length);
|
|
+
|
|
+ return IFD_SUCCESS;
|
|
+}
|
|
+
|
|
+
|
|
/*****************************************************************************
|
|
*
|
|
* Escape
|
|
@@ -2081,3 +2392,15 @@
|
|
buffer[3] = (value >> 24) & 0xFF;
|
|
} /* i2dw */
|
|
|
|
+
|
|
+/*****************************************************************************
|
|
+ *
|
|
+ * i2w
|
|
+ *
|
|
+ ****************************************************************************/
|
|
+static void i2w(uint16_t value, unsigned char buffer[])
|
|
+{
|
|
+ buffer[0] = value & 0xFF;
|
|
+ buffer[1] = (value >> 8) & 0xFF;
|
|
+} /* i2w */
|
|
+
|
|
Index: ccid-1.3.11/src/commands.h
|
|
===================================================================
|
|
--- ccid-1.3.11/src/commands.h (Revision 4347)
|
|
+++ ccid-1.3.11/src/commands.h (Arbeitskopie)
|
|
@@ -37,6 +37,14 @@
|
|
unsigned char TxBuffer[], unsigned int TxLength,
|
|
unsigned char RxBuffer[], unsigned int *RxLength);
|
|
|
|
+RESPONSECODE SecurePINPACECapabilities(unsigned int reader_index,
|
|
+ unsigned char TxBuffer[], unsigned int TxLength,
|
|
+ unsigned char RxBuffer[], unsigned int *RxLength);
|
|
+
|
|
+RESPONSECODE SecurePINPACEVerify(unsigned int reader_index,
|
|
+ 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);
|
|
Index: ccid-1.3.11/src/ccid.h
|
|
===================================================================
|
|
--- ccid-1.3.11/src/ccid.h (Revision 4347)
|
|
+++ ccid-1.3.11/src/ccid.h (Arbeitskopie)
|
|
@@ -137,8 +137,10 @@
|
|
#define CCID_CLASS_EXCHANGE_MASK 0x00070000
|
|
|
|
/* Features from bPINSupport */
|
|
-#define CCID_CLASS_PIN_VERIFY 0x01
|
|
-#define CCID_CLASS_PIN_MODIFY 0x02
|
|
+#define CCID_CLASS_PIN_VERIFY 0x01
|
|
+#define CCID_CLASS_PIN_MODIFY 0x02
|
|
+#define CCID_CLASS_PIN_PACE_CAPABILITIES 0x10
|
|
+#define CCID_CLASS_PIN_PACE_EXECUTE 0x20
|
|
|
|
/* See CCID specs ch. 4.2.1 */
|
|
#define CCID_ICC_PRESENT_ACTIVE 0x00 /* 00 0000 00 */
|
|
@@ -216,6 +218,8 @@
|
|
|
|
/* convert a 4 byte integer in USB format into an int */
|
|
#define dw2i(a, x) (unsigned int)((((((a[x+3] << 8) + a[x+2]) << 8) + a[x+1]) << 8) + a[x])
|
|
+/* convert a 2 byte integer in USB format into an int */
|
|
+#define w2i(a, x) (unsigned int)(((a[x+1]) << 8) + a[x])
|
|
|
|
/* all the data rates specified by ISO 7816-3 Fi/Di tables */
|
|
#define ISO_DATA_RATES 10753, 14337, 15625, 17204, \
|
|
Index: ccid-1.3.11/src/defs.h
|
|
===================================================================
|
|
--- ccid-1.3.11/src/defs.h (Revision 4347)
|
|
+++ ccid-1.3.11/src/defs.h (Arbeitskopie)
|
|
@@ -66,16 +66,10 @@
|
|
/* Flag set when a power down is requested */
|
|
#define MASK_POWERFLAGS_PDWN 0x02
|
|
|
|
-/* Kobil readers does not support APDU chaining for T=1 so you can't send an
|
|
- * extended APDU. The readers supports a command of up to 512 or 420 bytes.
|
|
- * For a Kobil KAAN Base/advanced reader you should use
|
|
- * #define CMD_BUF_SIZE 420
|
|
- * For the other models you should use
|
|
- * #define CMD_BUF_SIZE 512
|
|
- * Kobil is aware of the problem and do not plan to solve it.
|
|
- */
|
|
-/* Communication buffer size (max=adpu+Lc+data+Le) */
|
|
-#define CMD_BUF_SIZE (4+1+256+1)
|
|
+/* Communication buffer size (max=adpu+Lc+data+Le)
|
|
+ * * we use a 64kB for extended APDU on APDU mode readers */
|
|
+#define CMD_BUF_SIZE (4 +3 +64*1024 +3)
|
|
+
|
|
/* Larger communication buffer size (max=reader status+data+sw) */
|
|
#define RESP_BUF_SIZE (1+256+2)
|
|
|
|
Index: ccid-1.3.11/src/ccid_ifdhandler.h
|
|
===================================================================
|
|
--- ccid-1.3.11/src/ccid_ifdhandler.h (Revision 4347)
|
|
+++ ccid-1.3.11/src/ccid_ifdhandler.h (Arbeitskopie)
|
|
@@ -38,6 +38,8 @@
|
|
#define IOCTL_FEATURE_IFD_PIN_PROPERTIES \
|
|
SCARD_CTL_CODE(FEATURE_IFD_PIN_PROPERTIES + CLASS2_IOCTL_MAGIC)
|
|
#endif
|
|
+#define IOCTL_FEATURE_EXECUTE_PACE \
|
|
+ SCARD_CTL_CODE(FEATURE_EXECUTE_PACE + CLASS2_IOCTL_MAGIC)
|
|
|
|
#define DRIVER_OPTION_CCID_EXCHANGE_AUTHORIZED 1
|
|
#define DRIVER_OPTION_GEMPC_TWIN_KEY_APDU 2
|