From 41bdfce385e2c614a55c3e13734c307c03b6ffed Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Sat, 9 Feb 2019 15:15:17 +0100 Subject: [PATCH] emv/sc fixes and modifications: (#780) * print selected Smartcard Reader in PrintChannel() * implement 'sc sel '. Readername can include wildcards * and ? * fixing EMV APDU exchange (again) * use EMVExchangeEx() instead of EMVExchange() in fidocore.c --- client/cmdhffido.c | 1 + client/emv/cmdemv.c | 71 ++++++++++++++--------------------- client/emv/emvcore.c | 71 +++++++++++++++++++++++------------ client/emv/emvcore.h | 21 +++-------- client/fido/cbortools.c | 3 ++ client/fido/fidocore.c | 33 ++++++++-------- client/pcsc.c | 83 +++++++++++++++++++++++++++++++---------- 7 files changed, 165 insertions(+), 118 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 92f5d6cd..8a98cf19 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -40,6 +40,7 @@ #include "emv/emvcore.h" #include "emv/emvjson.h" #include "emv/dump.h" +#include "emv/apduinfo.h" #include "cliparser/cliparser.h" #include "crypto/asn1utils.h" #include "crypto/libpcrypto.h" diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 627b4ab2..abb84d43 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -11,8 +11,11 @@ #include "cmdemv.h" #include +#include #include "proxmark3.h" #include "cmdparser.h" +#include "ui.h" +#include "util.h" #include "mifare.h" #include "emvjson.h" #include "emv_pki.h" @@ -21,7 +24,11 @@ #include "cliparser/cliparser.h" #include "jansson.h" #include "emv_roca.h" - +#include "pcsc.h" +#include "apduinfo.h" +#include "dol.h" +#include "emv_tags.h" +#include "cmdhf14a.h" #define TLV_ADD(tag, value)( tlvdb_change_or_add_node(tlvRoot, tag, sizeof(value) - 1, (const unsigned char *)value) ) void ParamLoadDefaults(struct tlvdb *tlvRoot) { @@ -53,7 +60,7 @@ void PrintChannel(EMVCommandChannel channel) { PrintAndLogEx(INFO, "Channel: CONTACTLESS"); break; case ECC_CONTACT: - PrintAndLogEx(INFO, "Channel: CONTACT"); + PrintAndLogEx(INFO, "Channel: CONTACT, using %s", getAlternativeSmartcardReader()); break; } } @@ -667,7 +674,7 @@ int CmdEMVInternalAuthenticate(const char *cmd) { return 0; } -#define dreturn(n) {free(pdol_data_tlv);tlvdb_free(tlvSelect);tlvdb_free(tlvRoot);DropField();return n;} +#define dreturn(n) {free(pdol_data_tlv); tlvdb_free(tlvSelect); tlvdb_free(tlvRoot); DropFieldEx( channel ); return n;} void InitTransactionParameters(struct tlvdb *tlvRoot, bool paramLoadJSON, enum TransactionType TrType, bool GenACGPO) { @@ -1255,12 +1262,11 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "* * Host Response: `%s`", HostResponse); tlvdb_change_or_add_node(tlvRoot, 0x8a, sizeof(HostResponse) - 1, (const unsigned char *)HostResponse); - } - if (channel == ECC_CONTACTLESS) { - DropField(); } + DropFieldEx( channel ); + // Destroy TLV's free(pdol_data_tlv); tlvdb_free(tlvSelect); @@ -1368,9 +1374,7 @@ int CmdEMVScan(const char *cmd) { } // drop field at start - if (channel == ECC_CONTACTLESS) { - DropField(); - } + DropFieldEx( channel ); // iso 14443 select PrintAndLogEx(NORMAL, "--> GET UID, ATS."); @@ -1423,7 +1427,7 @@ int CmdEMVScan(const char *cmd) { if (EMVSearch(channel, false, true, decodeTLV, tlvSelect)) { PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit..."); tlvdb_free(tlvSelect); - DropField(); + DropFieldEx( channel ); return 3; } @@ -1439,9 +1443,7 @@ int CmdEMVScan(const char *cmd) { if (!AIDlen) { PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit..."); - if (channel == ECC_CONTACTLESS) { - DropField(); - } + DropFieldEx( channel ); return 4; } @@ -1460,7 +1462,7 @@ int CmdEMVScan(const char *cmd) { if (res) { PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res); tlvdb_free(tlvRoot); - DropField(); + DropFieldEx( channel ); return 5; } @@ -1488,9 +1490,7 @@ int CmdEMVScan(const char *cmd) { if (!pdol_data_tlv){ PrintAndLogEx(ERR, "Can't create PDOL TLV."); tlvdb_free(tlvRoot); - if (channel == ECC_CONTACTLESS) { - DropField(); - } + DropFieldEx( channel ); return 6; } @@ -1499,7 +1499,7 @@ int CmdEMVScan(const char *cmd) { if (!pdol_data_tlv_data) { PrintAndLogEx(ERR, "Can't create PDOL data."); tlvdb_free(tlvRoot); - DropField(); + DropFieldEx( channel ); return 6; } PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); @@ -1513,9 +1513,7 @@ int CmdEMVScan(const char *cmd) { if (res) { PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw); tlvdb_free(tlvRoot); - if (channel == ECC_CONTACTLESS) { - DropField(); - } + DropFieldEx( channel ); return 7; } ProcessGPOResponseFormat1(tlvRoot, buf, len, decodeTLV); @@ -1607,9 +1605,7 @@ int CmdEMVScan(const char *cmd) { // free tlv object tlvdb_free(tlvRoot); - if (channel == ECC_CONTACTLESS) { - DropField(); - } + DropFieldEx( channel ); res = json_dump_file(root, fname, JSON_INDENT(2)); if (res) { @@ -1683,7 +1679,7 @@ int CmdEMVRoca(const char *cmd) { if (EMVSearch(channel, false, true, false, tlvSelect)) { PrintAndLogEx(ERR, "Couldn't find any known EMV AID. Exit..."); tlvdb_free(tlvSelect); - DropField(); + DropFieldEx( channel ); return 3; } @@ -1692,16 +1688,14 @@ int CmdEMVRoca(const char *cmd) { } // EMV SELECT application - SetAPDULogging(true); + SetAPDULogging(false); EMVSelectApplication(tlvSelect, AID, &AIDlen); tlvdb_free(tlvSelect); if (!AIDlen) { PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit..."); - if (channel == ECC_CONTACTLESS) { - DropField(); - } + DropFieldEx( channel ); return 4; } @@ -1716,9 +1710,7 @@ int CmdEMVRoca(const char *cmd) { if (res) { PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res); tlvdb_free(tlvRoot); - if (channel == ECC_CONTACTLESS) { - DropField(); - } + DropFieldEx( channel ); return 5; } @@ -1730,9 +1722,7 @@ int CmdEMVRoca(const char *cmd) { if (!pdol_data_tlv){ PrintAndLogEx(ERR, "Can't create PDOL TLV."); tlvdb_free(tlvRoot); - if (channel == ECC_CONTACTLESS) { - DropField(); - } + DropFieldEx( channel ); return 6; } @@ -1741,7 +1731,7 @@ int CmdEMVRoca(const char *cmd) { if (!pdol_data_tlv_data) { PrintAndLogEx(ERR, "Can't create PDOL data."); tlvdb_free(tlvRoot); - DropField(); + DropFieldEx( channel ); return 6; } PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); @@ -1755,9 +1745,7 @@ int CmdEMVRoca(const char *cmd) { if (res) { PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw); tlvdb_free(tlvRoot); - if (channel == ECC_CONTACTLESS) { - DropField(); - } + DropFieldEx( channel ); return 7; } ProcessGPOResponseFormat1(tlvRoot, buf, len, false); @@ -1859,10 +1847,7 @@ out: // free tlv object tlvdb_free(tlvRoot); - if (channel == ECC_CONTACTLESS) { - DropField(); - } - + DropFieldEx( channel ); return 0; } diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 8deb4aa6..93235f5e 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -9,13 +9,27 @@ //----------------------------------------------------------------------------- #include "emvcore.h" + +#include #include "emvjson.h" #include "util_posix.h" #include "protocols.h" +#include "ui.h" +#include "util.h" +#include "emv_tags.h" +#include "emv_pk.h" +#include "emv_pki.h" +#include "cmdhf14a.h" +#include "apduinfo.h" +#include "tlv.h" +#include "dump.h" +#include "dol.h" + #ifdef WITH_SMARTCARD #include "cmdsmartcard.h" #endif + // Got from here. Thanks) // https://eftlab.co.uk/index.php/site-map/knowledge-base/211-emv-aid-rid-pix static const char *PSElist [] = { @@ -129,6 +143,12 @@ void SetAPDULogging(bool logging) { APDULogging = logging; } +void DropFieldEx(EMVCommandChannel channel) { + if (channel == ECC_CONTACTLESS) { + DropField(); + } +} + enum CardPSVendor GetCardPSVendor(uint8_t * AID, size_t AIDlen) { char buf[100] = {0}; if (AIDlen < 1) @@ -267,39 +287,38 @@ struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2) { } -static int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *apdu, int apdu_len, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) +int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *apdu, int apdu_len, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { *ResultLen = 0; if (sw) *sw = 0; uint16_t isw = 0; int res = 0; - if (ActivateField && channel == ECC_CONTACTLESS) { - DropField(); + if (ActivateField) { + DropFieldEx( channel ); msleep(50); } if (APDULogging) PrintAndLogEx(SUCCESS, ">>>> %s", sprint_hex(apdu, apdu_len)); +#ifdef WITH_SMARTCARD switch(channel) { case ECC_CONTACTLESS: // 6 byes + data = INS + CLA + P1 + P2 + Lc + + Le(?IncludeLe) res = ExchangeAPDU14a(apdu, apdu_len, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); - if (res) { - return res; - } break; case ECC_CONTACT: - //int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); -#ifdef WITH_SMARTCARD res = ExchangeAPDUSC(apdu, apdu_len, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); - if (res) { - return res; - } -#endif break; } +#else + res = ExchangeAPDU14a(apdu, apdu_len, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); +#endif + + if (res) { + return res; + } if (APDULogging) PrintAndLogEx(SUCCESS, "<<<< %s", sprint_hex(Result, *ResultLen)); @@ -308,13 +327,18 @@ static int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool Lea return 200; } -/* if (Result[*ResultLen-2] == 0x61) { + if (Result[*ResultLen-2] == 0x61) { uint8_t La = Result[*ResultLen-1]; uint8_t get_response[5] = {apdu[0], ISO7816_GET_RESPONSE, 0x00, 0x00, La}; - return EMVExchangeEx(channel, false, LeaveFieldON, get_response, sizeof(get_response), Result, MaxResultLen, ResultLen, sw, tlv); - }*/ + size_t oldlen = *ResultLen; + res = EMVExchangeEx(channel, false, LeaveFieldON, get_response, sizeof(get_response), &Result[oldlen-2], MaxResultLen-oldlen+2, ResultLen, sw, tlv); + *ResultLen += oldlen; + } + + if (res) return res; *ResultLen -= 2; + isw = Result[*ResultLen] * 0x0100 + Result[*ResultLen + 1]; if (sw) *sw = isw; @@ -335,19 +359,18 @@ static int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool Lea return 0; } -int EMVExchange(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *apdu, int apdu_len, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) +static int EMVExchange(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *apdu, int apdu_len, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { uint8_t APDU[APDU_COMMAND_LEN]; memcpy(APDU, apdu, apdu_len); APDU[apdu_len] = 0x00; if (channel == ECC_CONTACTLESS) { - if (apdu_len == 5 && apdu[4] == 0) { - // there is no Lc but an Le == 0 already + if (apdu_len == 5) { + // there is no Lc but an Le already } else if (apdu_len > 5 && apdu_len == 5 + apdu[4] + 1) { // there is Lc, data and Le } else { - if (apdu[1] != 0xc0) - apdu_len++; // no Le, add Le = 0x00 because some vendors require it for contactless + apdu_len++; // no Le, add Le = 0x00 because some vendors require it for contactless } } return EMVExchangeEx(channel, false, LeaveFieldON, APDU, apdu_len, Result, MaxResultLen, ResultLen, sw, tlv); @@ -539,8 +562,8 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO PrintAndLogEx(WARNING, "%s ERROR: Can't select PPSE AID. Error: %d", PSE_or_PPSE, res); } - if(!LeaveFieldON && channel == ECC_CONTACTLESS) - DropField(); + if (!LeaveFieldON) + DropFieldEx( channel ); return res; } @@ -696,7 +719,7 @@ struct emv_pk *get_ca_pk(struct tlvdb *db) { if (!df_tlv || !caidx_tlv || df_tlv->len < 6 || caidx_tlv->len != 1) return NULL; - PrintAndLogEx(NORMAL, "CA public key index 0x%0x", caidx_tlv->value[0]); + PrintAndLogEx(NORMAL, "CA Public Key index 0x%0x", caidx_tlv->value[0]); return emv_pk_get_ca_pk(df_tlv->value, caidx_tlv->value[0]); } @@ -1016,7 +1039,7 @@ int trCDA(struct tlvdb *tlv, struct tlvdb *ac_tlv, struct tlv *pdol_data_tlv, st struct emv_pk *icc_pk = emv_pki_recover_icc_cert(issuer_pk, tlv, sda_tlv); if (!icc_pk) { - PrintAndLogEx(WARNING, "Error: ICC setrificate not found. Exit."); + PrintAndLogEx(WARNING, "Error: ICC certificate not found. Exit."); emv_pk_free(pk); emv_pk_free(issuer_pk); return 2; diff --git a/client/emv/emvcore.h b/client/emv/emvcore.h index 010315ba..19f26028 100644 --- a/client/emv/emvcore.h +++ b/client/emv/emvcore.h @@ -11,23 +11,10 @@ #ifndef EMVCORE_H__ #define EMVCORE_H__ -#include #include -#include -#include -#include -#include -#include "util.h" -#include "common.h" -#include "ui.h" -#include "cmdhf14a.h" -#include "apduinfo.h" +#include #include "tlv.h" -#include "dol.h" -#include "dump.h" -#include "emv_tags.h" -#include "emv_pk.h" -#include "emv_pki.h" +#include "jansson.h" // maximum APDU lengths. Long APDUs not yet supported/needed #define APDU_DATA_LEN 255 @@ -60,6 +47,8 @@ enum CardPSVendor { }; extern enum CardPSVendor GetCardPSVendor(uint8_t * AID, size_t AIDlen); +extern void DropFieldEx(EMVCommandChannel channel); + extern bool TLVPrintFromBuffer(uint8_t *data, int datalen); extern void TLVPrintFromTLV(struct tlvdb *tlv); extern void TLVPrintFromTLVLev(struct tlvdb *tlv, int level); @@ -71,7 +60,7 @@ extern struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2); extern void SetAPDULogging(bool logging); // exchange -extern int EMVExchange(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *APDU, int APDU_len, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); +extern int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *apdu, int apdu_len, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); // search application extern int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv); diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index 01691dad..4674afc9 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -11,7 +11,10 @@ // #include "cbortools.h" + #include +#include + #include "emv/emvjson.h" #include "util.h" #include "fidocore.h" diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 5498c9d2..13768b75 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -22,7 +22,10 @@ #include "crypto/libpcrypto.h" #include "fido/additional_ca.h" #include "fido/cose.h" +#include "emv/dump.h" #include "protocols.h" +#include "ui.h" +#include "util.h" typedef struct { @@ -176,22 +179,22 @@ int FIDOSelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t Ma } int FIDOExchange(uint8_t* apdu, int apdulen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - int res = EMVExchange(ECC_CONTACTLESS, true, apdu, apdulen, Result, MaxResultLen, ResultLen, sw, NULL); - if (res == 5) // apdu result (sw) not a 0x9000 - res = 0; - // software chaining - while (!res && (*sw >> 8) == 0x61) { - uint8_t La = *sw & 0xff; - uint8_t get_response_APDU[5] = {apdu[0], ISO7816_GET_RESPONSE, 0x00, 0x00, La}; - size_t oldlen = *ResultLen; - res = EMVExchange(ECC_CONTACTLESS, true, get_response_APDU, sizeof(get_response_APDU), &Result[oldlen], MaxResultLen - oldlen, ResultLen, sw, NULL); - if (res == 5) // apdu result (sw) not a 0x9000 - res = 0; + int res = EMVExchangeEx(ECC_CONTACTLESS, false, true, apdu, apdulen, Result, MaxResultLen, ResultLen, sw, NULL); + // if (res == 5) // apdu result (sw) not a 0x9000 + // res = 0; + // // software chaining + // while (!res && (*sw >> 8) == 0x61) { + // uint8_t La = *sw & 0xff; + // uint8_t get_response_APDU[5] = {apdu[0], ISO7816_GET_RESPONSE, 0x00, 0x00, La}; + // size_t oldlen = *ResultLen; + // res = EMVExchange(ECC_CONTACTLESS, true, get_response_APDU, sizeof(get_response_APDU), &Result[oldlen], MaxResultLen - oldlen, ResultLen, sw, NULL); + // if (res == 5) // apdu result (sw) not a 0x9000 + // res = 0; - *ResultLen += oldlen; - if (*ResultLen > MaxResultLen) - return 100; - } + // *ResultLen += oldlen; + // if (*ResultLen > MaxResultLen) + // return 100; + // } return res; } diff --git a/client/pcsc.c b/client/pcsc.c index 7d03d052..c54efacc 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,6 +32,8 @@ #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; @@ -40,7 +42,7 @@ static char* AlternativeSmartcardReader = NULL; char *getAlternativeSmartcardReader(void) { - return AlternativeSmartcardReader; + return AlternativeSmartcardReader ? AlternativeSmartcardReader : PM3_SMARTCARD_DEFAULT_NAME; } @@ -62,7 +64,7 @@ bool pcscCheckForCardReaders(void) SCardReleaseContext(SC_Context); return false; } - + return true; } @@ -70,7 +72,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 +81,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 +104,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; - + +} + + +static bool matchString(char *string, const char *search) +{ + 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; } -char *matchString(LPTSTR readerlist, const char *readername) +static char *matchReader(LPTSTR readerlist, const char *readername) { - return pickReader(readerlist); + 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 +173,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,7 +186,8 @@ bool pcscSelectAlternativeCardReader(const char *readername) free(AlternativeSmartcardReader); AlternativeSmartcardReader = malloc((strlen(selected_readername) + 1) * sizeof(char)); strcpy(AlternativeSmartcardReader, selected_readername); - + + free(readerlist); return true; } @@ -154,7 +197,7 @@ bool pcscGetATR(smart_card_atr_t *card) if (!card) { return false; } - + card->atr_len = 0; memset(card->atr, 0, sizeof(card->atr)); @@ -170,10 +213,10 @@ bool pcscGetATR(smart_card_atr_t *card) return false; } card->atr_len = atr_len; - + // TODO: LogTrace without device - - return true; + + return true; } @@ -192,7 +235,7 @@ void pcscTransmit(uint8_t *data, uint32_t data_len, uint32_t flags, uint8_t *res // 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,7 +243,7 @@ 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); -- 2.39.5