- renamed Special PIN Verification/Capabilities to PACE Verification/Capabilities

- fixed PIN PACE support in ccid descriptor
- using uint16_t instead of WORD in PACE structures
- fixed lengthInputData to host byteorder
- fixed parsing input buffer of SCardControl with FEATURE_EXECUTE_PACE
- parsing input buffer for PACE verification and adjusting the byteorder                   
- added 30s timeout to for PACE verification
- triggering PACE via PC/SC now works although quite unstable


git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@155 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
frankmorgner
2010-06-18 21:20:25 +00:00
parent b495a3da9b
commit d931be9df0
3 changed files with 111 additions and 58 deletions

View File

@@ -18,7 +18,7 @@ Index: Drivers/ccid/src/ifdhandler.c
iBytesReturned += sizeof(PCSC_TLV_STRUCTURE); iBytesReturned += sizeof(PCSC_TLV_STRUCTURE);
} }
+ if (ccid_descriptor -> bPINSupport & CCID_CLASS_PIN_SPECIAL_CAPABILITIES) + if (ccid_descriptor -> bPINSupport & CCID_CLASS_PIN_PACE_CAPABILITIES)
+ { + {
+ pcsc_tlv -> tag = FEATURE_EXECUTE_PACE; + pcsc_tlv -> tag = FEATURE_EXECUTE_PACE;
+ pcsc_tlv -> length = 0x04; /* always 0x04 */ + pcsc_tlv -> length = 0x04; /* always 0x04 */
@@ -31,37 +31,46 @@ Index: Drivers/ccid/src/ifdhandler.c
/* We can always forward wLcdLayout */ /* We can always forward wLcdLayout */
pcsc_tlv -> tag = FEATURE_IFD_PIN_PROPERTIES; pcsc_tlv -> tag = FEATURE_IFD_PIN_PROPERTIES;
pcsc_tlv -> length = 0x04; /* always 0x04 */ pcsc_tlv -> length = 0x04; /* always 0x04 */
@@ -1548,6 +1558,34 @@ @@ -1548,6 +1558,43 @@
} }
} }
+ if (IOCTL_FEATURE_EXECUTE_PACE == dwControlCode) + if (IOCTL_FEATURE_EXECUTE_PACE == dwControlCode)
+ { + {
+ if (TxLength < 3 || !TxBuffer) { + if (TxLength < 3 || !TxBuffer) {
+ DEBUG_INFO("PACE Command refused by driver"); + DEBUG_CRITICAL("Buffer too small, could not determine length of "
+ "input data");
+ return_value = IFD_COMMUNICATION_ERROR;
+ } else {
+ uint16_t lengthInputData;
+ lengthInputData = *((uint16_t *) (TxBuffer + 1));
+
+ 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; + return_value = IFD_COMMUNICATION_ERROR;
+ } else { + } else {
+ unsigned int iBytesReturned; + unsigned int iBytesReturned;
+ uint16_t lengthInputData;
+
+ iBytesReturned = RxLength; + iBytesReturned = RxLength;
+ lengthInputData = (uint16_t *) TxBuffer + 1; +
+ if (*TxBuffer == 1) { + if (*TxBuffer == 1) {
+ return_value = SecurePINSpecialCapabilities(reader_index, + return_value = SecurePINPACECapabilities(reader_index,
+ TxBuffer + 3, lengthInputData, + TxBuffer + 3, lengthInputData,
+ RxBuffer, &iBytesReturned); + RxBuffer, &iBytesReturned);
+ *pdwBytesReturned = iBytesReturned; + *pdwBytesReturned = iBytesReturned;
+ } else if (*TxBuffer == 2) { + } else if (*TxBuffer == 2) {
+ return_value = SecurePINSpecialVerify(reader_index, + return_value = SecurePINPACEVerify(reader_index,
+ TxBuffer + 3, lengthInputData, + TxBuffer + 3, lengthInputData,
+ RxBuffer, &iBytesReturned); + RxBuffer, &iBytesReturned);
+ *pdwBytesReturned = iBytesReturned; + *pdwBytesReturned = iBytesReturned;
+ } else { + } else {
+ DEBUG_INFO("PACE Command refused by driver"); + DEBUG_CRITICAL2("Unknown PACE function %u", *TxBuffer);
+ return_value = IFD_COMMUNICATION_ERROR; + return_value = IFD_COMMUNICATION_ERROR;
+ } + }
+ } + }
+ } + }
+ }
+ +
if (IFD_SUCCESS != return_value) if (IFD_SUCCESS != return_value)
*pdwBytesReturned = 0; *pdwBytesReturned = 0;
@@ -74,45 +83,93 @@ Index: Drivers/ccid/src/commands.c
unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length, unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
unsigned char rx_buffer[]); unsigned char rx_buffer[]);
+static RESPONSECODE SecurePINSpecial(unsigned int reader_index, +static RESPONSECODE SecurePINPACE(unsigned int reader_index,
+ const unsigned char TxBuffer[], unsigned int TxLength, + unsigned char TxBuffer[], unsigned int TxLength,
+ unsigned char RxBuffer[], unsigned int *RxLength, + unsigned char RxBuffer[], unsigned int *RxLength,
+ unsigned char bPINOperation); + unsigned char bPINOperation);
+ +
static void i2dw(int value, unsigned char *buffer); static void i2dw(int value, unsigned char *buffer);
+static void i2w(int value, unsigned char *buffer); +static void i2w(uint16_t value, unsigned char *buffer);
/***************************************************************************** /*****************************************************************************
@@ -712,7 +718,96 @@ @@ -712,7 +718,144 @@
return ret; return ret;
} /* SecurePINModify */ } /* SecurePINModify */
+RESPONSECODE SecurePINSpecialVerify(unsigned int reader_index, +RESPONSECODE SecurePINPACEVerify(unsigned int reader_index,
+ const unsigned char TxBuffer[], unsigned int TxLength, + unsigned char TxBuffer[], unsigned int TxLength,
+ unsigned char RxBuffer[], unsigned int *RxLength) + unsigned char RxBuffer[], unsigned int *RxLength)
+{ +{
+ /* bPINOperation: PIN Special Capabilities */ + RESPONSECODE return_value;
+ return SecurePINSpecial(reader_index, TxBuffer, TxLength, RxBuffer, + unsigned char lengthCHAT, lengthPIN;
+ RxLength, 0x11); + uint16_t lengthCertificateDescription;
+} + int old_read_timeout;
+ _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
+RESPONSECODE SecurePINSpecialCapabilities(unsigned int reader_index, + old_read_timeout= ccid_descriptor -> readTimeout;
+ const unsigned char TxBuffer[], unsigned int TxLength, + ccid_descriptor -> readTimeout = 30*1000; /* 30 seconds */
+ unsigned char RxBuffer[], unsigned int *RxLength) +
+{ + if (TxLength < 2) {
+ /* bPINOperation: PIN Special Capabilities */ + DEBUG_CRITICAL("Buffer too small, could not determine length of "
+ return SecurePINSpecial(reader_index, TxBuffer, TxLength, RxBuffer, + "CHAT");
+ RxLength, 0x10); + return_value = IFD_COMMUNICATION_ERROR;
+ goto err;
+ }
+ lengthCHAT = *(TxBuffer + 1);
+
+ if (TxLength < 2+lengthCHAT) {
+ DEBUG_CRITICAL("Buffer too small, could not determine length of "
+ "PIN");
+ return_value = IFD_COMMUNICATION_ERROR;
+ goto err;
+ }
+ lengthPIN = *(TxBuffer + 1 + lengthCHAT);
+
+ if (TxLength < 3+lengthCHAT+lengthPIN) {
+ DEBUG_CRITICAL("Buffer too small, could not determine length of "
+ "certificate description");
+ return_value = IFD_COMMUNICATION_ERROR;
+ goto err;
+ }
+ lengthCertificateDescription = *((uint16_t *)
+ (TxBuffer + 1 + lengthCHAT + lengthPIN));
+
+ if (TxLength != 4+lengthCHAT+lengthPIN+lengthCertificateDescription) {
+ DEBUG_CRITICAL3("Buffer too small or too big to contain only "
+ "CHAT, PIN and certificate description (expected %u, got %u)",
+ 4+lengthCHAT+lengthPIN+lengthCertificateDescription, TxLength);
+ return_value = IFD_COMMUNICATION_ERROR;
+ goto err;
+ }
+
+ i2w(lengthCertificateDescription, TxBuffer + 1 + lengthCHAT + lengthPIN);
+
+ /* bPINOperation: PIN PACE Capabilities */
+ return_value = SecurePINPACE(reader_index, TxBuffer, TxLength, RxBuffer,
+ RxLength, CCID_CLASS_PIN_PACE_CAPABILITIES);
+
+err:
+ ccid_descriptor -> readTimeout = old_read_timeout;
+ return return_value;
+} +}
+ +
+static RESPONSECODE SecurePINSpecial(unsigned int reader_index, +RESPONSECODE SecurePINPACECapabilities(unsigned int reader_index,
+ const unsigned char TxBuffer[], unsigned int TxLength, + 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_EXECUTE);
+}
+
+static RESPONSECODE SecurePINPACE(unsigned int reader_index,
+ unsigned char TxBuffer[], unsigned int TxLength,
+ unsigned char RxBuffer[], unsigned int *RxLength, + unsigned char RxBuffer[], unsigned int *RxLength,
+ unsigned char bPINOperation) + unsigned char bPINOperation)
+{ +{
+ unsigned char cmd[11+CMD_BUF_SIZE]; + unsigned char cmd[11+CMD_BUF_SIZE];
+ int length; + unsigned int length;
+ _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); + _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
+ status_t res; + status_t res;
+ +
@@ -181,16 +238,7 @@ Index: Drivers/ccid/src/commands.c
/***************************************************************************** /*****************************************************************************
* *
* Escape * Escape
@@ -729,7 +824,7 @@ @@ -2113,3 +2256,15 @@
int old_read_timeout;
_ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
- old_read_timeout = ccid_descriptor -> readTimeout;
+ old_read_timeout= ccid_descriptor -> readTimeout;
ccid_descriptor -> readTimeout = 30*1000; /* 30 seconds */
again:
@@ -2113,3 +2208,15 @@
buffer[3] = (value >> 24) & 0xFF; buffer[3] = (value >> 24) & 0xFF;
} /* i2dw */ } /* i2dw */
@@ -200,7 +248,7 @@ Index: Drivers/ccid/src/commands.c
+ * i2w + * i2w
+ * + *
+ ****************************************************************************/ + ****************************************************************************/
+static void i2w(int value, unsigned char buffer[]) +static void i2w(uint16_t value, unsigned char buffer[])
+{ +{
+ buffer[0] = value & 0xFF; + buffer[0] = value & 0xFF;
+ buffer[1] = (value >> 8) & 0xFF; + buffer[1] = (value >> 8) & 0xFF;
@@ -214,12 +262,12 @@ Index: Drivers/ccid/src/commands.h
unsigned char TxBuffer[], unsigned int TxLength, unsigned char TxBuffer[], unsigned int TxLength,
unsigned char RxBuffer[], unsigned int *RxLength); unsigned char RxBuffer[], unsigned int *RxLength);
+RESPONSECODE SecurePINSpecialCapabilities(unsigned int reader_index, +RESPONSECODE SecurePINPACECapabilities(unsigned int reader_index,
+ const unsigned char TxBuffer[], unsigned int TxLength, + unsigned char TxBuffer[], unsigned int TxLength,
+ unsigned char RxBuffer[], unsigned int *RxLength); + unsigned char RxBuffer[], unsigned int *RxLength);
+ +
+RESPONSECODE SecurePINSpecialVerify(unsigned int reader_index, +RESPONSECODE SecurePINPACEVerify(unsigned int reader_index,
+ const unsigned char TxBuffer[], unsigned int TxLength, + unsigned char TxBuffer[], unsigned int TxLength,
+ unsigned char RxBuffer[], unsigned int *RxLength); + unsigned char RxBuffer[], unsigned int *RxLength);
+ +
RESPONSECODE CmdEscape(unsigned int reader_index, RESPONSECODE CmdEscape(unsigned int reader_index,
@@ -237,8 +285,8 @@ Index: Drivers/ccid/src/ccid.h
-#define CCID_CLASS_PIN_MODIFY 0x02 -#define CCID_CLASS_PIN_MODIFY 0x02
+#define CCID_CLASS_PIN_VERIFY 0x01 +#define CCID_CLASS_PIN_VERIFY 0x01
+#define CCID_CLASS_PIN_MODIFY 0x02 +#define CCID_CLASS_PIN_MODIFY 0x02
+#define CCID_CLASS_PIN_SPECIAL_CAPABILITIES 0x10 +#define CCID_CLASS_PIN_PACE_CAPABILITIES 0x10
+#define CCID_CLASS_PIN_SPECIAL_EXECUTE 0x11 +#define CCID_CLASS_PIN_PACE_EXECUTE 0x20
/* See CCID specs ch. 4.2.1 */ /* See CCID specs ch. 4.2.1 */
#define CCID_ICC_PRESENT_ACTIVE 0x00 /* 00 0000 00 */ #define CCID_ICC_PRESENT_ACTIVE 0x00 /* 00 0000 00 */

View File

@@ -43,7 +43,7 @@ main(int argc, char *argv[])
BYTE pbSendBufferEstablish [] = { BYTE pbSendBufferEstablish [] = {
0x02, /* idxFunction = EstabishPACEChannel */ 0x02, /* idxFunction = EstabishPACEChannel */
0x00, /* lengthInputData */ 0x00, /* lengthInputData */
0x04, /* lengthInputData */ 0x00, /* lengthInputData */
0x03, /* PACE with PIN */ 0x03, /* PACE with PIN */
0x00, /* length CHAT */ 0x00, /* length CHAT */
0x00, /* length certificate description */ 0x00, /* length certificate description */
@@ -52,6 +52,9 @@ main(int argc, char *argv[])
BYTE pbRecvBuffer[1024]; BYTE pbRecvBuffer[1024];
DWORD dwActiveProtocol, dwRecvLength, dwReaders; DWORD dwActiveProtocol, dwRecvLength, dwReaders;
uint16_t lengthInputData = 4;
memcpy(pbSendBufferEstablish + 1, &lengthInputData, 2);
if (argc > 1) { if (argc > 1) {
if (argc > 2 || sscanf(argv[1], "%d", &num) != 1) { if (argc > 2 || sscanf(argv[1], "%d", &num) != 1) {
fprintf(stderr, "Usage: %s [reader_num]\n", argv[0]); fprintf(stderr, "Usage: %s [reader_num]\n", argv[0]);

View File

@@ -78,7 +78,8 @@ ccid_desc = {
//.bPINSupport = 0, //.bPINSupport = 0,
.bPINSupport = 0x1| // PIN Verification supported .bPINSupport = 0x1| // PIN Verification supported
0x2| // PIN Modification supported 0x2| // PIN Modification supported
0x10, // PIN Special supported 0x10| // PIN PACE Capabilities supported
0x20, // PIN PACE Verification supported
.bMaxCCIDBusySlots = 0x01, .bMaxCCIDBusySlots = 0x01,
}; };
@@ -776,6 +777,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, __u8** out, size_t *outlen)
goto err; goto err;
if (request->wLevelParameter != CCID_WLEVEL_DIRECT) { if (request->wLevelParameter != CCID_WLEVEL_DIRECT) {
sc_error(ctx, "Chained security commands not supported.");
sc_result = SC_ERROR_NOT_SUPPORTED; sc_result = SC_ERROR_NOT_SUPPORTED;
goto err; goto err;
} }
@@ -818,7 +820,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, __u8** out, size_t *outlen)
abData + 1, &abDataOut, &resplen); abData + 1, &abDataOut, &resplen);
goto err; goto err;
break; break;
case 0x11: case 0x20:
sc_result = EstablishPACEChannel(&sctx, sc_result = EstablishPACEChannel(&sctx,
card_in_slot[request->bSlot], abData + 1, &abDataOut, card_in_slot[request->bSlot], abData + 1, &abDataOut,
&resplen, &sctx); &resplen, &sctx);