X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/6b5105bea972d055bb2069bf8ca2c6d105b2ee8f..ac37ee816b0f00a5d02d9a860dc6180f71132675:/client/pcsc.c diff --git a/client/pcsc.c b/client/pcsc.c index 7d03d052..ca87eb34 100644 --- a/client/pcsc.c +++ b/client/pcsc.c @@ -19,7 +19,7 @@ #include #include #define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag))) -#define SCARD_CLASS_ICC_STATE 9 +#define SCARD_CLASS_ICC_STATE 9 #define SCARD_ATTR_ATR_STRING SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0303) #elif defined (_WIN32) #include @@ -32,15 +32,103 @@ #include "util.h" #include "cmdhw.h" +#define PM3_SMARTCARD_DEFAULT_NAME "PM3 RDV40 Smartcard Slot" + static SCARDCONTEXT SC_Context; static SCARDHANDLE SC_Card; static DWORD SC_Protocol; static char* AlternativeSmartcardReader = NULL; +#define PCSC_MAX_TRACELEN 60000 +static uint8_t pcsc_trace_buf[PCSC_MAX_TRACELEN]; +static bool tracing = false; +static uint32_t traceLen = 0; + + +uint8_t *pcsc_get_trace_addr(void) +{ + return pcsc_trace_buf; +} + + +uint32_t pcsc_get_traceLen(void) +{ + return traceLen; +} + + +static void pcsc_clear_trace(void) +{ + traceLen = 0; +} + + +static void pcsc_set_tracing(bool enable) { + tracing = enable; +} + + +static bool pcsc_LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, bool readerToTag) +{ + if (!tracing) return false; + + uint8_t *trace = pcsc_trace_buf; + + uint32_t num_paritybytes = (iLen-1)/8 + 1; // number of paritybytes + uint32_t duration = timestamp_end - timestamp_start; + + // Return when trace is full + if (traceLen + sizeof(iLen) + sizeof(timestamp_start) + sizeof(duration) + num_paritybytes + iLen >= PCSC_MAX_TRACELEN) { + tracing = false; // don't trace any more + return false; + } + // Traceformat: + // 32 bits timestamp (little endian) + // 16 bits duration (little endian) + // 16 bits data length (little endian, Highest Bit used as readerToTag flag) + // y Bytes data + // x Bytes parity (one byte per 8 bytes data) + + // timestamp (start) + trace[traceLen++] = ((timestamp_start >> 0) & 0xff); + trace[traceLen++] = ((timestamp_start >> 8) & 0xff); + trace[traceLen++] = ((timestamp_start >> 16) & 0xff); + trace[traceLen++] = ((timestamp_start >> 24) & 0xff); + + // duration + trace[traceLen++] = ((duration >> 0) & 0xff); + trace[traceLen++] = ((duration >> 8) & 0xff); + + // data length + trace[traceLen++] = ((iLen >> 0) & 0xff); + trace[traceLen++] = ((iLen >> 8) & 0xff); + + // readerToTag flag + if (!readerToTag) { + trace[traceLen - 1] |= 0x80; + } + + // data bytes + if (btBytes != NULL && iLen != 0) { + for (int i = 0; i < iLen; i++) { + trace[traceLen++] = *btBytes++; + } + } + + // dummy parity bytes + if (num_paritybytes != 0) { + for (int i = 0; i < num_paritybytes; i++) { + trace[traceLen++] = 0x00; + } + } + + return true; +} + char *getAlternativeSmartcardReader(void) { - return AlternativeSmartcardReader; + return AlternativeSmartcardReader ? AlternativeSmartcardReader : PM3_SMARTCARD_DEFAULT_NAME; } @@ -62,7 +150,7 @@ bool pcscCheckForCardReaders(void) SCardReleaseContext(SC_Context); return false; } - + return true; } @@ -70,7 +158,7 @@ bool pcscCheckForCardReaders(void) static char *pickReader(LPTSTR readerlist) { PrintAndLogEx(NORMAL, "Please select one of these:"); - PrintAndLogEx(NORMAL, " [0] PM3 RDV40 Smartcard Slot %s", PM3hasSmartcardSlot() ? "(default)" : "(default, not available)"); + PrintAndLogEx(NORMAL, " [0] %s %s", PM3_SMARTCARD_DEFAULT_NAME, PM3hasSmartcardSlot() ? "(default)" : "(default, not available)"); int num = 1; for (LPTSTR p = readerlist; *p != '\0'; ) { @@ -79,17 +167,17 @@ static char *pickReader(LPTSTR readerlist) } num--; - + if (num == 1) { printf("Your choice (0 or 1)?"); } else { printf("Your choice (0...%d)? ", num); } int selection = getch() - '0'; - printf("\n"); + printf("\n"); if (selection == 0) { - PrintAndLogEx(INFO, "Selected RDV40 Smartcard Slot"); + PrintAndLogEx(INFO, "Selected %s", PM3_SMARTCARD_DEFAULT_NAME); return NULL; } @@ -102,18 +190,58 @@ static char *pickReader(LPTSTR readerlist) return p; } - PrintAndLogEx(INFO, "Invalid selection. Using RDV40 Smartcard Slot"); + PrintAndLogEx(INFO, "Invalid selection. Using %s", PM3_SMARTCARD_DEFAULT_NAME); return NULL; - + } -char *matchString(LPTSTR readerlist, const char *readername) +static bool matchString(char *string, const char *search) { - return pickReader(readerlist); + if (search[0] == '*' && search[1] == '\0') { // the wildcard only string "*" matches everything + return true; + } + + if (search[0] == '\0' && string[0] != '\0') { // string is longer than pattern. No match. + return false; + } + + if (search[0] == '?' || search[0] == string[0]) { // wildcard '?' matches any character + return matchString(string + 1, search + 1); + } + + if (search[0] == '*') { // wildcard '*' matches any sequence of characters + for (size_t i = 0; i < strlen(string); i++) { + if (matchString(string + i, search + 1)) { + return true; + } + } + } + + return false; } - + +static char *matchReader(LPTSTR readerlist, const char *readername) +{ + if (matchString(PM3_SMARTCARD_DEFAULT_NAME, readername)) { + PrintAndLogEx(INFO, "Selected %s", PM3_SMARTCARD_DEFAULT_NAME); + return NULL; + } + + for (LPTSTR p = readerlist; *p != '\0'; ) { + if (matchString(p, readername)) { + PrintAndLogEx(INFO, "Selected %s", p); + return p; + } + while (*p++ != '\0') ; // advance to next entry + } + + PrintAndLogEx(INFO, "No match. Using %s", PM3_SMARTCARD_DEFAULT_NAME); + return NULL; +} + + bool pcscSelectAlternativeCardReader(const char *readername) { DWORD readerlist_len; @@ -131,7 +259,7 @@ bool pcscSelectAlternativeCardReader(const char *readername) char *selected_readername = NULL; if (readername) { - selected_readername = matchString(readerlist, readername); + selected_readername = matchReader(readerlist, readername); } else { selected_readername = pickReader(readerlist); } @@ -144,17 +272,21 @@ bool pcscSelectAlternativeCardReader(const char *readername) free(AlternativeSmartcardReader); AlternativeSmartcardReader = malloc((strlen(selected_readername) + 1) * sizeof(char)); strcpy(AlternativeSmartcardReader, selected_readername); - + + free(readerlist); return true; } bool pcscGetATR(smart_card_atr_t *card) { + pcsc_clear_trace(); + pcsc_set_tracing(true); + if (!card) { return false; } - + card->atr_len = 0; memset(card->atr, 0, sizeof(card->atr)); @@ -170,10 +302,12 @@ bool pcscGetATR(smart_card_atr_t *card) return false; } card->atr_len = atr_len; + + pcsc_LogTrace(card->atr, card->atr_len, 0, 0, false); - // TODO: LogTrace without device + pcsc_set_tracing(false); - return true; + return true; } @@ -186,13 +320,12 @@ void pcscTransmit(uint8_t *data, uint32_t data_len, uint32_t flags, uint8_t *res protocol = SCARD_PCI_RAW; } - // TODO: tracing - // if ((flags & SC_CONNECT)) - // clear_trace(); + if ((flags & SC_CONNECT)) + pcsc_clear_trace(); - // set_tracing(true); + pcsc_set_tracing(true); - if ((flags & SC_CONNECT || flags & SC_SELECT)) { + if ((flags & SC_CONNECT || flags & SC_SELECT)) { LONG res = SCardConnect(SC_Context, AlternativeSmartcardReader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &SC_Card, &SC_Protocol); if (res != SCARD_S_SUCCESS) { @@ -200,16 +333,17 @@ void pcscTransmit(uint8_t *data, uint32_t data_len, uint32_t flags, uint8_t *res return; } } - + if ((flags & SC_RAW) || (flags & SC_RAW_T0)) { - // TODO: tracing - // LogTrace(data, arg1, 0, 0, NULL, true); + pcsc_LogTrace(data, data_len, 0, 0, true); DWORD len = *response_len; LONG res = SCardTransmit(SC_Card, protocol, data, data_len, NULL, response, &len); if (res != SCARD_S_SUCCESS) { *response_len = -1; } else { + pcsc_LogTrace(response, len, 0, 0, false); *response_len = len; } } + pcsc_set_tracing(false); }