emv/sc fixes and modifications: (#780)
authorpwpiwi <pwpiwi@users.noreply.github.com>
Sat, 9 Feb 2019 14:15:17 +0000 (15:15 +0100)
committerGitHub <noreply@github.com>
Sat, 9 Feb 2019 14:15:17 +0000 (15:15 +0100)
* print selected Smartcard Reader in PrintChannel()
* implement 'sc sel <readername>'. Readername can include wildcards * and ?
* fixing EMV APDU exchange (again)
* use EMVExchangeEx() instead of EMVExchange() in fidocore.c

client/cmdhffido.c
client/emv/cmdemv.c
client/emv/emvcore.c
client/emv/emvcore.h
client/fido/cbortools.c
client/fido/fidocore.c
client/pcsc.c

index 92f5d6cdbe24da6e5b0f85b173f1e6e436cbabd1..8a98cf19fdfdf41bd513b4c4bac3966e4a8c1df3 100644 (file)
@@ -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"
index 627b4ab29e87e5d71f2b967853484d9ab9765306..abb84d438d35e8500d8e4ffdeede4d3d86988d0b 100644 (file)
 #include "cmdemv.h"
 
 #include <ctype.h>
+#include <string.h>
 #include "proxmark3.h"
 #include "cmdparser.h"
+#include "ui.h"
+#include "util.h"
 #include "mifare.h"
 #include "emvjson.h"
 #include "emv_pki.h"
 #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;
 }
 
index 8deb4aa69eaabf5e8ed8114c8ba79b54491650f5..93235f5e62f49f96e26456ef96c965156ade071d 100644 (file)
@@ -9,13 +9,27 @@
 //-----------------------------------------------------------------------------
 
 #include "emvcore.h"
+
+#include <string.h>
 #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 + <data = Nc> + 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;
index 010315ba9a19f77024e6801ac0e12ad4119eb8e9..19f26028ae9ce97850108afbddb98374a1aaacb9 100644 (file)
 #ifndef EMVCORE_H__
 #define EMVCORE_H__
 
-#include <stdio.h>
 #include <stdint.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <string.h>
-#include <jansson.h>
-#include "util.h"
-#include "common.h"
-#include "ui.h"
-#include "cmdhf14a.h"
-#include "apduinfo.h"
+#include <stdbool.h>
 #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);
index 01691dad10444b68e1aab308d46d8aad4021d419..4674afc9a55d606ae5f73417c30b3c9056cc3236 100644 (file)
 //
 
 #include "cbortools.h"
+
 #include <stdlib.h>
+#include <inttypes.h>
+
 #include "emv/emvjson.h"
 #include "util.h"
 #include "fidocore.h"
index 5498c9d22c64e43d02d0c6efc4d0f4b403629d49..13768b756dbb5dbbe28e8abf75c5eae197c9a4c5 100644 (file)
 #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;
 }
 
index 7d03d05212085b161e912c2cefe4a914bc0f0e6f..c54efacc1448568a3f928a31ec74eadaa72aaea5 100644 (file)
@@ -19,7 +19,7 @@
 #include <PCSC/winscard.h>
 #include <PCSC/wintypes.h>
 #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 <winscard.h>
@@ -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);
Impressum, Datenschutz