From d931be9df09bda24e0ac0967c10431d29873ad06 Mon Sep 17 00:00:00 2001 From: frankmorgner Date: Fri, 18 Jun 2010 21:20:25 +0000 Subject: [PATCH] - 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 --- ccid/pcsclite_trunk.patch | 158 +++++++++++++++++++++++++------------- ccid/src/ccid-test.c | 5 +- ccid/src/ccid.c | 6 +- 3 files changed, 111 insertions(+), 58 deletions(-) diff --git a/ccid/pcsclite_trunk.patch b/ccid/pcsclite_trunk.patch index af4f9d8..2ccb455 100644 --- a/ccid/pcsclite_trunk.patch +++ b/ccid/pcsclite_trunk.patch @@ -18,7 +18,7 @@ Index: Drivers/ccid/src/ifdhandler.c 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 -> length = 0x04; /* always 0x04 */ @@ -31,34 +31,43 @@ Index: Drivers/ccid/src/ifdhandler.c /* We can always forward wLcdLayout */ pcsc_tlv -> tag = FEATURE_IFD_PIN_PROPERTIES; pcsc_tlv -> length = 0x04; /* always 0x04 */ -@@ -1548,6 +1558,34 @@ +@@ -1548,6 +1558,43 @@ } } + if (IOCTL_FEATURE_EXECUTE_PACE == dwControlCode) + { + 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 { -+ unsigned int iBytesReturned; + uint16_t lengthInputData; ++ lengthInputData = *((uint16_t *) (TxBuffer + 1)); + -+ iBytesReturned = RxLength; -+ lengthInputData = (uint16_t *) TxBuffer + 1; -+ if (*TxBuffer == 1) { -+ return_value = SecurePINSpecialCapabilities(reader_index, -+ TxBuffer + 3, lengthInputData, -+ RxBuffer, &iBytesReturned); -+ *pdwBytesReturned = iBytesReturned; -+ } else if (*TxBuffer == 2) { -+ return_value = SecurePINSpecialVerify(reader_index, -+ TxBuffer + 3, lengthInputData, -+ RxBuffer, &iBytesReturned); -+ *pdwBytesReturned = iBytesReturned; -+ } else { -+ DEBUG_INFO("PACE Command refused by driver"); ++ 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; ++ } + } + } + } @@ -74,45 +83,93 @@ Index: Drivers/ccid/src/commands.c unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length, unsigned char rx_buffer[]); -+static RESPONSECODE SecurePINSpecial(unsigned int reader_index, -+ const unsigned char TxBuffer[], unsigned int TxLength, ++static RESPONSECODE SecurePINPACE(unsigned int reader_index, ++ unsigned char TxBuffer[], unsigned int TxLength, + unsigned char RxBuffer[], unsigned int *RxLength, + unsigned char bPINOperation); + 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; } /* SecurePINModify */ -+RESPONSECODE SecurePINSpecialVerify(unsigned int reader_index, -+ const unsigned char TxBuffer[], unsigned int TxLength, ++RESPONSECODE SecurePINPACEVerify(unsigned int reader_index, ++ unsigned char TxBuffer[], unsigned int TxLength, + unsigned char RxBuffer[], unsigned int *RxLength) +{ -+ /* bPINOperation: PIN Special Capabilities */ -+ return SecurePINSpecial(reader_index, TxBuffer, TxLength, RxBuffer, -+ RxLength, 0x11); -+} ++ RESPONSECODE return_value; ++ unsigned char lengthCHAT, lengthPIN; ++ uint16_t lengthCertificateDescription; ++ int old_read_timeout; ++ _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); -+RESPONSECODE SecurePINSpecialCapabilities(unsigned int reader_index, -+ const unsigned char TxBuffer[], unsigned int TxLength, -+ unsigned char RxBuffer[], unsigned int *RxLength) -+{ -+ /* bPINOperation: PIN Special Capabilities */ -+ return SecurePINSpecial(reader_index, TxBuffer, TxLength, RxBuffer, -+ RxLength, 0x10); ++ old_read_timeout= ccid_descriptor -> readTimeout; ++ ccid_descriptor -> readTimeout = 30*1000; /* 30 seconds */ ++ ++ if (TxLength < 2) { ++ DEBUG_CRITICAL("Buffer too small, could not determine length of " ++ "CHAT"); ++ 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, -+ const unsigned char TxBuffer[], unsigned int TxLength, ++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_EXECUTE); ++} ++ ++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[11+CMD_BUF_SIZE]; -+ int length; ++ unsigned int length; + _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); + status_t res; + @@ -181,16 +238,7 @@ Index: Drivers/ccid/src/commands.c /***************************************************************************** * * Escape -@@ -729,7 +824,7 @@ - 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 @@ +@@ -2113,3 +2256,15 @@ buffer[3] = (value >> 24) & 0xFF; } /* i2dw */ @@ -200,7 +248,7 @@ Index: Drivers/ccid/src/commands.c + * i2w + * + ****************************************************************************/ -+static void i2w(int value, unsigned char buffer[]) ++static void i2w(uint16_t value, unsigned char buffer[]) +{ + buffer[0] = value & 0xFF; + buffer[1] = (value >> 8) & 0xFF; @@ -214,12 +262,12 @@ Index: Drivers/ccid/src/commands.h unsigned char TxBuffer[], unsigned int TxLength, unsigned char RxBuffer[], unsigned int *RxLength); -+RESPONSECODE SecurePINSpecialCapabilities(unsigned int reader_index, -+ const unsigned char TxBuffer[], unsigned int TxLength, ++RESPONSECODE SecurePINPACECapabilities(unsigned int reader_index, ++ unsigned char TxBuffer[], unsigned int TxLength, + unsigned char RxBuffer[], unsigned int *RxLength); + -+RESPONSECODE SecurePINSpecialVerify(unsigned int reader_index, -+ const unsigned char TxBuffer[], unsigned int TxLength, ++RESPONSECODE SecurePINPACEVerify(unsigned int reader_index, ++ unsigned char TxBuffer[], unsigned int TxLength, + unsigned char RxBuffer[], unsigned int *RxLength); + 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_VERIFY 0x01 +#define CCID_CLASS_PIN_MODIFY 0x02 -+#define CCID_CLASS_PIN_SPECIAL_CAPABILITIES 0x10 -+#define CCID_CLASS_PIN_SPECIAL_EXECUTE 0x11 ++#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 */ diff --git a/ccid/src/ccid-test.c b/ccid/src/ccid-test.c index e2c2600..62782da 100644 --- a/ccid/src/ccid-test.c +++ b/ccid/src/ccid-test.c @@ -43,7 +43,7 @@ main(int argc, char *argv[]) BYTE pbSendBufferEstablish [] = { 0x02, /* idxFunction = EstabishPACEChannel */ 0x00, /* lengthInputData */ - 0x04, /* lengthInputData */ + 0x00, /* lengthInputData */ 0x03, /* PACE with PIN */ 0x00, /* length CHAT */ 0x00, /* length certificate description */ @@ -52,6 +52,9 @@ main(int argc, char *argv[]) BYTE pbRecvBuffer[1024]; DWORD dwActiveProtocol, dwRecvLength, dwReaders; + uint16_t lengthInputData = 4; + memcpy(pbSendBufferEstablish + 1, &lengthInputData, 2); + if (argc > 1) { if (argc > 2 || sscanf(argv[1], "%d", &num) != 1) { fprintf(stderr, "Usage: %s [reader_num]\n", argv[0]); diff --git a/ccid/src/ccid.c b/ccid/src/ccid.c index 13e9261..232197c 100644 --- a/ccid/src/ccid.c +++ b/ccid/src/ccid.c @@ -78,7 +78,8 @@ ccid_desc = { //.bPINSupport = 0, .bPINSupport = 0x1| // PIN Verification supported 0x2| // PIN Modification supported - 0x10, // PIN Special supported + 0x10| // PIN PACE Capabilities supported + 0x20, // PIN PACE Verification supported .bMaxCCIDBusySlots = 0x01, }; @@ -776,6 +777,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, __u8** out, size_t *outlen) goto err; if (request->wLevelParameter != CCID_WLEVEL_DIRECT) { + sc_error(ctx, "Chained security commands not supported."); sc_result = SC_ERROR_NOT_SUPPORTED; goto err; } @@ -818,7 +820,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, __u8** out, size_t *outlen) abData + 1, &abDataOut, &resplen); goto err; break; - case 0x11: + case 0x20: sc_result = EstablishPACEChannel(&sctx, card_in_slot[request->bSlot], abData + 1, &abDataOut, &resplen, &sctx);