]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
Add support for standard USB Smartcard Readers (#765)
authorpwpiwi <pwpiwi@users.noreply.github.com>
Mon, 28 Jan 2019 20:54:34 +0000 (21:54 +0100)
committerGitHub <noreply@github.com>
Mon, 28 Jan 2019 20:54:34 +0000 (21:54 +0100)
* add PCSC interface (pcsc.c and pcsc.h)
* new command 'sc select' to choose an USB Smartcard Reader
* updated CI/.travis.yml accordingly
* remove TCK CRC check in i2c.c It is done in PrintATR() anyway
* Fix TCK CRC check in PrintATR()
* Add PCSC reader support to 'sc info'

14 files changed:
CI/.travis.yml
armsrc/appmain.c
armsrc/i2c.c
client/Makefile
client/cmdhw.c
client/cmdhw.h
client/cmdsmartcard.c
client/pcsc.c [new file with mode: 0644]
client/pcsc.h [new file with mode: 0644]
client/proxmark3.c
client/util.c
client/util.h
include/smartcard.h
include/usb_cmd.h

index f5fed7a62b9e67718d3811645466e719af660bb2..0c02c250b8c3a1fd7932d22f0767ea472f22b0c4 100644 (file)
@@ -26,7 +26,7 @@ before_install:
   echo $REPOSITORY_EP;
   if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then 
     sudo apt-get update -qq;
   echo $REPOSITORY_EP;
   if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then 
     sudo apt-get update -qq;
-    sudo apt-get install -y gcc-arm-none-eabi;
+    sudo apt-get install -y gcc-arm-none-eabi libpcsclite-dev;
   elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
     brew update;
     if [[ "$REPOSITORY_EP" == "" ]]; then
   elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
     brew update;
     if [[ "$REPOSITORY_EP" == "" ]]; then
index 1348ef0473124bb8317689c97d8a55bbad9fc8c3..cdc784c089fa2f6e13d684cb3e03d68438e9bdd0 100644 (file)
@@ -34,6 +34,7 @@
  #include "LCD.h"
 #endif
 
  #include "LCD.h"
 #endif
 
+static uint32_t hw_capabilities;
 
 // Craig Young - 14a stand-alone code
 #ifdef WITH_ISO14443a
 
 // Craig Young - 14a stand-alone code
 #ifdef WITH_ISO14443a
@@ -312,8 +313,22 @@ extern struct version_information version_information;
 extern char *_bootphase1_version_pointer, _flash_start, _flash_end, _bootrom_start, _bootrom_end, __data_src_start__;
 
 
 extern char *_bootphase1_version_pointer, _flash_start, _flash_end, _bootrom_start, _bootrom_end, __data_src_start__;
 
 
+void set_hw_capabilities(void)
+{
+       if (I2C_is_available()) {
+               hw_capabilities |= HAS_SMARTCARD_SLOT;
+       }
+       
+       if (false) { // TODO: implement a test
+               hw_capabilities |= HAS_EXTRA_FLASH_MEM;
+       }
+}      
+
+
 void SendVersion(void)
 {
 void SendVersion(void)
 {
+       set_hw_capabilities();
+       
        char temp[USB_CMD_DATA_SIZE]; /* Limited data payload in USB packets */
        char VersionString[USB_CMD_DATA_SIZE] = { '\0' };
 
        char temp[USB_CMD_DATA_SIZE]; /* Limited data payload in USB packets */
        char VersionString[USB_CMD_DATA_SIZE] = { '\0' };
 
@@ -347,7 +362,7 @@ void SendVersion(void)
        // Send Chip ID and used flash memory
        uint32_t text_and_rodata_section_size = (uint32_t)&__data_src_start__ - (uint32_t)&_flash_start;
        uint32_t compressed_data_section_size = common_area.arg1;
        // Send Chip ID and used flash memory
        uint32_t text_and_rodata_section_size = (uint32_t)&__data_src_start__ - (uint32_t)&_flash_start;
        uint32_t compressed_data_section_size = common_area.arg1;
-       cmd_send(CMD_ACK, *(AT91C_DBGU_CIDR), text_and_rodata_section_size + compressed_data_section_size, 0, VersionString, strlen(VersionString));
+       cmd_send(CMD_ACK, *(AT91C_DBGU_CIDR), text_and_rodata_section_size + compressed_data_section_size, hw_capabilities, VersionString, strlen(VersionString));
 }
 
 // measure the USB Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time.
 }
 
 // measure the USB Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time.
index 0560d306b508d1c6fb648da9ed75761c7e666371..7ef0c9c035ce767bfe8cd39b7f4e6a2cec021d5e 100644 (file)
@@ -656,28 +656,6 @@ static bool GetATR(smart_card_atr_t *card_ptr) {
        if ( !sc_rx_bytes(card_ptr->atr, &len) )                
                return false;
 
        if ( !sc_rx_bytes(card_ptr->atr, &len) )                
                return false;
 
-       uint8_t pos_td = 1;
-       if ( (card_ptr->atr[1] & 0x10) == 0x10) pos_td++;
-       if ( (card_ptr->atr[1] & 0x20) == 0x20) pos_td++;
-       if ( (card_ptr->atr[1] & 0x40) == 0x40) pos_td++;
-       
-       // T0 indicate presence T=0 vs T=1.  T=1 has checksum TCK
-       if ( (card_ptr->atr[1] & 0x80) == 0x80) {
-               
-               pos_td++;
-       
-               // 1 == T1 ,  presence of checksum TCK
-               if ( (card_ptr->atr[pos_td] & 0x01) == 0x01) {
-                       uint8_t chksum = 0;
-                       // xor property.  will be zero when xored with chksum.
-                       for (uint8_t i = 1; i < len; ++i)
-                               chksum ^= card_ptr->atr[i];
-                       if ( chksum ) {
-                               if ( MF_DBGLEVEL > 2) DbpString("Wrong ATR checksum");
-                       }
-               }
-       }
-
        card_ptr->atr_len = len;
        LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false);
 
        card_ptr->atr_len = len;
        LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false);
 
index 81b46f235a7e817ec88c9bde5dba6e9fc2f4cace..aafbe3751ad887c5834d3d37bb1c326e90d3c1cc 100644 (file)
@@ -35,13 +35,27 @@ APP_CFLAGS =
 include ../common/Makefile_Enabled_Options.common
 CFLAGS += $(APP_CFLAGS)
 ifneq (,$(findstring WITH_SMARTCARD,$(APP_CFLAGS)))
 include ../common/Makefile_Enabled_Options.common
 CFLAGS += $(APP_CFLAGS)
 ifneq (,$(findstring WITH_SMARTCARD,$(APP_CFLAGS)))
-       SRC_SMARTCARD = cmdsmartcard.c
+       SRC_SMARTCARD = cmdsmartcard.c pcsc.c
 else
        SRC_SMARTCARD = 
 endif
 
 else
        SRC_SMARTCARD = 
 endif
 
-LUAPLATFORM = generic
 platform = $(shell uname)
 platform = $(shell uname)
+
+ifneq (,$(findstring MINGW,$(platform)))
+       PCSC_INCLUDES :=
+       PCSC_LIBS = -lwinscard
+else
+       ifeq ($(platform),Darwin)
+               PCSC_INCLUDES = 
+               PCSC_LIBS = -framework PCSC
+       else
+               PCSC_INCLUDES := $(shell pkg-config --cflags libpcsclite)
+               PCSC_LIBS := $(shell pkg-config --libs libpcsclite)
+       endif
+endif
+
+LUAPLATFORM = generic
 ifneq (,$(findstring MINGW,$(platform)))
                LUAPLATFORM = mingw
 else
 ifneq (,$(findstring MINGW,$(platform)))
                LUAPLATFORM = mingw
 else
@@ -259,7 +273,7 @@ all: lua_build jansson_build mbedtls_build cbor_build $(BINS)
 all-static: LDLIBS:=-static $(LDLIBS)
 all-static: proxmark3 flasher fpga_compress
 
 all-static: LDLIBS:=-static $(LDLIBS)
 all-static: proxmark3 flasher fpga_compress
 
-proxmark3: LDLIBS+=$(LUALIB) $(JANSSONLIB) $(MBEDTLSLIB) $(CBORLIB) $(QTLDLIBS)
+proxmark3: LDLIBS+=$(LUALIB) $(JANSSONLIB) $(MBEDTLSLIB) $(CBORLIB) $(QTLDLIBS) $(PCSC_LIBS)
 proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) lualibs/usb_cmd.lua
        $(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) $(LDLIBS) -o $@
 
 proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) lualibs/usb_cmd.lua
        $(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) $(LDLIBS) -o $@
 
@@ -328,7 +342,7 @@ $(OBJDIR)/%_AVX512.o : %.c $(OBJDIR)/%.d
 
 %.o: %.c
 $(OBJDIR)/%.o : %.c $(OBJDIR)/%.d
 
 %.o: %.c
 $(OBJDIR)/%.o : %.c $(OBJDIR)/%.d
-       $(CC) $(DEPFLAGS) $(CFLAGS) $(ZLIBFLAGS) -c -o $@ $<
+       $(CC) $(DEPFLAGS) $(CFLAGS) $(ZLIBFLAGS) $(PCSC_INCLUDES) -c -o $@ $<
        $(POSTCOMPILE)
 
 %.o: %.cpp
        $(POSTCOMPILE)
 
 %.o: %.cpp
index f994e938778cae8dffa590432240a053173e78d0..b6a0d11f2bbd27852bd35cf2384de46630563950 100644 (file)
@@ -20,7 +20,8 @@
 #include "cmdmain.h"
 #include "cmddata.h"
 
 #include "cmdmain.h"
 #include "cmddata.h"
 
-/* low-level hardware control */
+
+static uint32_t hw_capabilities = 0;
 
 static int CmdHelp(const char *Cmd);
 
 
 static int CmdHelp(const char *Cmd);
 
@@ -403,6 +404,10 @@ int CmdTune(const char *Cmd)
     return CmdTuneSamples(Cmd);
 }
 
     return CmdTuneSamples(Cmd);
 }
 
+bool PM3hasSmartcardSlot(void) {
+       return (hw_capabilities & HAS_SMARTCARD_SLOT);
+}
+
 int CmdVersion(const char *Cmd)
 {
 
 int CmdVersion(const char *Cmd)
 {
 
@@ -411,10 +416,11 @@ int CmdVersion(const char *Cmd)
        UsbCommand resp = {0, {0, 0, 0}};
 
        SendCommand(&c);
        UsbCommand resp = {0, {0, 0, 0}};
 
        SendCommand(&c);
-       if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
+       if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {
                PrintAndLog("Prox/RFID mark3 RFID instrument");
                PrintAndLog((char*)resp.d.asBytes);
                lookupChipID(resp.arg[0], resp.arg[1]);
                PrintAndLog("Prox/RFID mark3 RFID instrument");
                PrintAndLog((char*)resp.d.asBytes);
                lookupChipID(resp.arg[0], resp.arg[1]);
+               hw_capabilities = resp.arg[2];
        }
        return 0;
 }
        }
        return 0;
 }
index b8e10f748d5bcb97257c110263b6f02266971540..2db2fecc46d066eb1cfbad9f2ec6c9ce48ace8dd 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef CMDHW_H__
 #define CMDHW_H__
 
 #ifndef CMDHW_H__
 #define CMDHW_H__
 
+#include <stdbool.h>
+
 int CmdHW(const char *Cmd);
 
 int CmdDetectReader(const char *Cmd);
 int CmdHW(const char *Cmd);
 
 int CmdDetectReader(const char *Cmd);
@@ -23,5 +25,6 @@ int CmdSetDivisor(const char *Cmd);
 int CmdSetMux(const char *Cmd);
 int CmdTune(const char *Cmd);
 int CmdVersion(const char *Cmd);
 int CmdSetMux(const char *Cmd);
 int CmdTune(const char *Cmd);
 int CmdVersion(const char *Cmd);
+bool PM3hasSmartcardSlot(void);
 
 #endif
 
 #endif
index edd51b7237cea5dfedb75f427e1da767b2b7e770..a1793240e5db78a04acd35e02430055998c15e14 100644 (file)
 #include "smartcard.h"
 #include "comms.h"
 #include "protocols.h"
 #include "smartcard.h"
 #include "comms.h"
 #include "protocols.h"
+#include "cmdhw.h"
 #include "cmdhflist.h"
 #include "emv/apduinfo.h"       // APDUcode description
 #include "emv/emvcore.h"        // decodeTVL
 #include "crypto/libpcrypto.h" // sha512hash
 #include "emv/dump.h"                  // dump_buffer
 #include "cmdhflist.h"
 #include "emv/apduinfo.h"       // APDUcode description
 #include "emv/emvcore.h"        // decodeTVL
 #include "crypto/libpcrypto.h" // sha512hash
 #include "emv/dump.h"                  // dump_buffer
+#include "pcsc.h"
 
 #define SC_UPGRADE_FILES_DIRECTORY          "sc_upgrade_firmware/"
 
 
 #define SC_UPGRADE_FILES_DIRECTORY          "sc_upgrade_firmware/"
 
+static bool UseAlternativeSmartcardReader = false;     // default: use PM3 RDV40 Smartcard Slot (if available)
+
 static int CmdHelp(const char *Cmd);
 
 static int usage_sm_raw(void) {
 static int CmdHelp(const char *Cmd);
 
 static int usage_sm_raw(void) {
@@ -44,6 +48,17 @@ static int usage_sm_raw(void) {
        return 0;
 }
 
        return 0;
 }
 
+static int usage_sm_select(void) {
+       PrintAndLogEx(NORMAL, "Usage: sc select [h|<reader name>] ");
+       PrintAndLogEx(NORMAL, "       h             :  this help");
+       PrintAndLogEx(NORMAL, "       <reader name> :  a card reader's name, wildcards allowed, leave empty to pick from available readers");
+       PrintAndLogEx(NORMAL, "");
+       PrintAndLogEx(NORMAL, "Examples:");
+       PrintAndLogEx(NORMAL, "        sc select          : list available card readers and pick");
+       PrintAndLogEx(NORMAL, "        sc select Gemalto* : select a connected Gemalto card reader" );
+       return 0;
+}
+
 static int usage_sm_reader(void) {
        PrintAndLogEx(NORMAL, "Usage: sc reader [h|s]");
        PrintAndLogEx(NORMAL, "       h          :  this help");
 static int usage_sm_reader(void) {
        PrintAndLogEx(NORMAL, "Usage: sc reader [h|s]");
        PrintAndLogEx(NORMAL, "       h          :  this help");
@@ -185,6 +200,8 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
        uint8_t T0 = atr[1];
        uint8_t K = T0 & 0x0F;
        uint8_t TD1 = 0, T1len = 0, TD1len = 0, TDilen = 0;
        uint8_t T0 = atr[1];
        uint8_t K = T0 & 0x0F;
        uint8_t TD1 = 0, T1len = 0, TD1len = 0, TDilen = 0;
+       bool protocol_T0_present = true;
+       bool protocol_T15_present = false;
 
        if (T0 & 0x10) {
                PrintAndLog("\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr[2 + T1len]);
 
        if (T0 & 0x10) {
                PrintAndLog("\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr[2 + T1len]);
@@ -204,6 +221,14 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
        if (T0 & 0x80) {
                TD1 = atr[2 + T1len];
                PrintAndLog("\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1, TD1 & 0x0f);
        if (T0 & 0x80) {
                TD1 = atr[2 + T1len];
                PrintAndLog("\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1, TD1 & 0x0f);
+               protocol_T0_present = false;
+               if ((TD1 & 0x0f) == 0) {
+                       protocol_T0_present = true;
+               }
+               if ((TD1 & 0x0f) == 15) {
+                       protocol_T15_present = true;
+               }
+               
                T1len++;
 
                if (TD1 & 0x10) {
                T1len++;
 
                if (TD1 & 0x10) {
@@ -221,6 +246,12 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
                if (TD1 & 0x80) {
                        uint8_t TDi = atr[2 + T1len + TD1len];
                        PrintAndLog("\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi, TDi & 0x0f);
                if (TD1 & 0x80) {
                        uint8_t TDi = atr[2 + T1len + TD1len];
                        PrintAndLog("\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi, TDi & 0x0f);
+                       if ((TDi & 0x0f) == 0) {
+                               protocol_T0_present = true;
+                       }
+                       if ((TDi & 0x0f) == 15) {
+                               protocol_T15_present = true;
+                       }
                        TD1len++;
 
                        bool nextCycle = true;
                        TD1len++;
 
                        bool nextCycle = true;
@@ -251,26 +282,27 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
                }
        }
 
                }
        }
 
-       uint8_t vxor = 0;
-       for (int i = 1; i < atrlen; i++)
-               vxor ^= atr[i];
+       if (!protocol_T0_present || protocol_T15_present) { // there is CRC Check Byte TCK
+               uint8_t vxor = 0;
+               for (int i = 1; i < atrlen; i++)
+                       vxor ^= atr[i];
+               
+               if (vxor)
+                       PrintAndLogEx(WARNING, "Check sum error. Must be 0 got 0x%02X", vxor);
+               else
+                       PrintAndLogEx(INFO, "Check sum OK.");
+       }
        
        
-       if (vxor)
-               PrintAndLogEx(WARNING, "Check summ error. Must be 0 got 0x%02X", vxor);
-       else
-               PrintAndLogEx(INFO, "Check summ OK.");
-
        if (atr[0] != 0x3b)
                PrintAndLogEx(WARNING, "Not a direct convention [ 0x%02x ]", atr[0]);
 
        if (atr[0] != 0x3b)
                PrintAndLogEx(WARNING, "Not a direct convention [ 0x%02x ]", atr[0]);
 
-       
        uint8_t calen = 2 + T1len + TD1len + TDilen + K;
 
        if (atrlen != calen && atrlen != calen + 1)  // may be CRC
                PrintAndLogEx(ERR, "ATR length error. len: %d, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen, T1len, TD1len, TDilen, K);
 
        if (K > 0)
        uint8_t calen = 2 + T1len + TD1len + TDilen + K;
 
        if (atrlen != calen && atrlen != calen + 1)  // may be CRC
                PrintAndLogEx(ERR, "ATR length error. len: %d, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen, T1len, TD1len, TDilen, K);
 
        if (K > 0)
-               PrintAndLogEx(INFO, "\nHistorical bytes | len 0x%02d | format %02x", K, atr[2 + T1len + TD1len + TDilen]);
+               PrintAndLogEx(INFO, "\nHistorical bytes | len %02d | format %02x", K, atr[2 + T1len + TD1len + TDilen]);
        
        if (K > 1) {
                PrintAndLogEx(INFO, "\tHistorical bytes");
        
        if (K > 1) {
                PrintAndLogEx(INFO, "\tHistorical bytes");
@@ -280,26 +312,38 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
        return 0;
 }
 
        return 0;
 }
 
-static bool smart_select(bool silent) {
-       UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}};
-       clearCommandBuffer();
-       SendCommand(&c);
-       UsbCommand resp;
-       if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) {
-               if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
-               return false;
+static bool smart_getATR(smart_card_atr_t *card)
+{
+       if (UseAlternativeSmartcardReader) {
+               return pcscGetATR(card);
+       } else {
+               UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}};
+               SendCommand(&c);
+
+               UsbCommand resp;
+               if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) {
+                       return false;
+               }
+
+               if (resp.arg[0] & 0xff) {
+                       return resp.arg[0] & 0xFF;
+               }
+
+               memcpy(card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t));
+
+               return true;
        }
        }
+}
 
 
-       uint8_t isok = resp.arg[0] & 0xFF;
-       if (!isok) {
+static bool smart_select(bool silent) {
+
+       smart_card_atr_t card;
+       if (!smart_getATR(&card)) {
                if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
                return false;
        }
 
        if (!silent) {
                if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
                return false;
        }
 
        if (!silent) {
-               smart_card_atr_t card;
-               memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t));
-
                PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len));
        }
 
                PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len));
        }
 
@@ -379,6 +423,32 @@ static int smart_response(uint8_t *data) {
        return datalen;
 }
 
        return datalen;
 }
 
+
+int CmdSmartSelect(const char *Cmd) {
+
+       const char *readername;
+       
+       if (tolower(param_getchar(Cmd, 0)) == 'h') {
+               return usage_sm_select();
+       }
+       
+       if (!PM3hasSmartcardSlot() && !pcscCheckForCardReaders()) {
+               PrintAndLogEx(WARNING, "No Smartcard Readers available");
+               UseAlternativeSmartcardReader = false;
+               return 1;
+       }
+       
+       int bg, en;
+       if (param_getptr(Cmd, &bg, &en, 0)) {
+               UseAlternativeSmartcardReader = pcscSelectAlternativeCardReader(NULL);
+       } else {
+               readername = Cmd + bg;
+               UseAlternativeSmartcardReader = pcscSelectAlternativeCardReader(readername);
+       }
+
+       return 0;
+}
+
 int CmdSmartRaw(const char *Cmd) {
 
        int hexlen = 0;
 int CmdSmartRaw(const char *Cmd) {
 
        int hexlen = 0;
@@ -756,24 +826,12 @@ int CmdSmartInfo(const char *Cmd){
        //Validations
        if (errors ) return usage_sm_info();
 
        //Validations
        if (errors ) return usage_sm_info();
 
-       UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}};
-       clearCommandBuffer();
-       SendCommand(&c);
-       UsbCommand resp;
-       if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) {
-               if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
-               return 1;
-       }
-
-       uint8_t isok = resp.arg[0] & 0xFF;
-       if (!isok) {
+       smart_card_atr_t card;
+       if (!smart_getATR(&card)) {
                if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
                return 1;
        }
 
                if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
                return 1;
        }
 
-       smart_card_atr_t card;
-       memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t));
-
        // print header
        PrintAndLogEx(INFO, "--- Smartcard Information ---------");
        PrintAndLogEx(INFO, "-------------------------------------------------------------");
        // print header
        PrintAndLogEx(INFO, "--- Smartcard Information ---------");
        PrintAndLogEx(INFO, "-------------------------------------------------------------");
@@ -830,22 +888,11 @@ int CmdSmartReader(const char *Cmd){
        //Validations
        if (errors ) return usage_sm_reader();
 
        //Validations
        if (errors ) return usage_sm_reader();
 
-       UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}};
-       clearCommandBuffer();
-       SendCommand(&c);
-       UsbCommand resp;
-       if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) {
-               if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
-               return 1;
-       }
-
-       uint8_t isok = resp.arg[0] & 0xFF;
-       if (!isok) {
+       smart_card_atr_t card;
+       if (!smart_getATR(&card)) {
                if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
                return 1;
        }
                if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
                return 1;
        }
-       smart_card_atr_t card;
-       memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t));
 
        PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len));
        return 0;
 
        PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len));
        return 0;
@@ -970,6 +1017,7 @@ int CmdSmartBruteforceSFI(const char *Cmd) {
 
 static command_t CommandTable[] = {
        {"help",     CmdHelp,               1, "This help"},
 
 static command_t CommandTable[] = {
        {"help",     CmdHelp,               1, "This help"},
+       {"select",   CmdSmartSelect,        1, "Select the Smartcard Reader to use"},
        {"list",     CmdSmartList,          0, "List ISO 7816 history"},
        {"info",     CmdSmartInfo,          0, "Tag information"},
        {"reader",   CmdSmartReader,        0, "Act like an IS07816 reader"},
        {"list",     CmdSmartList,          0, "List ISO 7816 history"},
        {"info",     CmdSmartInfo,          0, "Tag information"},
        {"reader",   CmdSmartReader,        0, "Act like an IS07816 reader"},
diff --git a/client/pcsc.c b/client/pcsc.c
new file mode 100644 (file)
index 0000000..dd331d0
--- /dev/null
@@ -0,0 +1,177 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2019 piwi
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// PCSC functions to use alternative Smartcard Readers
+//-----------------------------------------------------------------------------
+
+#include "pcsc.h"
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#if defined (__APPLE__)
+#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_ATTR_ATR_STRING SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0303)
+#elif defined (_WIN32)
+#include <winscard.h>
+#else
+#include <winscard.h>
+#include <reader.h>
+#endif
+
+#include "ui.h"
+#include "util.h"
+#include "cmdhw.h"
+
+static SCARDCONTEXT SC_Context;
+static SCARDHANDLE SC_Card;
+static DWORD SC_Protocol;
+static char* AlternativeSmartcardReader = NULL;
+
+
+char *getAlternativeSmartcardReader(void)
+{
+       return AlternativeSmartcardReader;
+}
+
+
+bool pcscCheckForCardReaders(void)
+{
+       LONG res = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &SC_Context);
+       if (res != SCARD_S_SUCCESS) {
+               return false;
+       }
+
+       DWORD pcchReaders;
+       res = SCardListReaders(SC_Context, NULL, NULL, &pcchReaders);
+       if (res != SCARD_S_SUCCESS) {
+               SCardReleaseContext(SC_Context);
+               return false;
+       }
+
+       if (res == SCARD_E_NO_READERS_AVAILABLE || res == SCARD_E_NO_SERVICE) {
+               SCardReleaseContext(SC_Context);
+               return false;
+       }
+       
+       return true;
+}
+
+
+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)");
+
+       int num = 1;
+       for (LPTSTR p = readerlist; *p != '\0'; ) {
+               PrintAndLogEx(NORMAL, "  [%1d] %s", num++, p);
+               while (*p++ != '\0') ; // advance to next entry
+       }
+
+       num--;
+       
+       if (num == 1) {
+               printf("Your choice (0 or 1)?");
+       } else {
+               printf("Your choice (0...%d)? ", num);
+       }
+       int selection = getch() - '0';
+       printf("\n");   
+
+       if (selection == 0) {
+               PrintAndLogEx(INFO, "Selected RDV40 Smartcard Slot");
+               return NULL;
+       }
+
+       if (selection >= 1 && selection <= num) {
+               LPTSTR p = readerlist;
+               for (int i = 1; i < selection; i++) {
+                       while (*p++ != '\0') ; // advance to next entry
+               }
+               PrintAndLogEx(INFO, "Selected %s", p);
+               return p;
+       }
+
+       PrintAndLogEx(INFO, "Invalid selection. Using RDV40 Smartcard Slot");
+       return NULL;
+       
+}
+
+
+char *matchString(LPTSTR readerlist, const char *readername)
+{
+       return pickReader(readerlist);
+}
+
+       
+bool pcscSelectAlternativeCardReader(const char *readername)
+{
+       DWORD readerlist_len;
+       LONG res = SCardListReaders(SC_Context, NULL, NULL, &readerlist_len);
+       if (res != SCARD_S_SUCCESS) {
+               return false;
+       }
+
+       LPTSTR readerlist = calloc(readerlist_len, sizeof(char));
+       res = SCardListReaders(SC_Context, NULL, readerlist, &readerlist_len);
+       if (res != SCARD_S_SUCCESS) {
+               free(readerlist);
+               return false;
+       }
+
+       char *selected_readername = NULL;
+       if (readername) {
+               selected_readername = matchString(readerlist, readername);
+       } else {
+               selected_readername = pickReader(readerlist);
+       }
+
+       if (selected_readername == NULL) {
+               free(readerlist);
+               return false;
+       }
+
+       free(AlternativeSmartcardReader);
+       AlternativeSmartcardReader = malloc((strlen(selected_readername) + 1) * sizeof(char));
+       strcpy(AlternativeSmartcardReader, selected_readername);
+       
+       return true;
+}
+
+
+bool pcscGetATR(smart_card_atr_t *card)
+{
+       if (!card) {
+               return false;
+       }
+       
+       card->atr_len = 0;
+       memset(card->atr, 0, sizeof(card->atr));
+
+       LONG res = SCardConnect(SC_Context, AlternativeSmartcardReader, SCARD_SHARE_SHARED,
+                               SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &SC_Card, &SC_Protocol);
+       if (res != SCARD_S_SUCCESS) {
+               return false;
+       }
+
+       DWORD atr_len = sizeof(card->atr);
+       res = SCardGetAttrib(SC_Card, SCARD_ATTR_ATR_STRING, card->atr, &atr_len);
+       if (res != SCARD_S_SUCCESS) {
+               return false;
+       }
+       card->atr_len = atr_len;
+       
+       // TODO: LogTrace without device
+       
+       return true;    
+}
diff --git a/client/pcsc.h b/client/pcsc.h
new file mode 100644 (file)
index 0000000..3dae06c
--- /dev/null
@@ -0,0 +1,22 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2019 piwi
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// PCSC functions to use alternative Smartcard Readers
+//-----------------------------------------------------------------------------
+
+#ifndef PCSC_H__
+#define PCSC_H__
+
+#include <stdbool.h>
+#include "smartcard.h"
+
+char *getAlternativeSmartcardReader(void);
+bool pcscCheckForCardReaders(void);
+bool pcscSelectAlternativeCardReader(const char *readername);
+bool pcscGetATR(smart_card_atr_t *card);
+
+#endif
index 6fb066e8a5dbdaf5e4b7c8bbda22eafd6f6c27b5..a25ecb4111ec2b6aaacad3b7f618cfcabbe72b01 100644 (file)
@@ -28,6 +28,8 @@
 #include "cmdhw.h"
 #include "whereami.h"
 #include "comms.h"
 #include "cmdhw.h"
 #include "whereami.h"
 #include "comms.h"
+#include "pcsc.h"
+
 
 void
 #ifdef __has_attribute
 
 void
 #ifdef __has_attribute
@@ -48,6 +50,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) {
                SetOffline(true);
        }
 
                SetOffline(true);
        }
 
+
        // file with script
        FILE *script_file = NULL;
        char script_cmd_buf[256] = {0};  // iceman, needs lua script the same file_path_buffer as the rest
        // file with script
        FILE *script_file = NULL;
        char script_cmd_buf[256] = {0};  // iceman, needs lua script the same file_path_buffer as the rest
index dec7c5a1f4518dca7648356c30c1f3f157075b92..f13d730cbd984c5c89c0c4bcd2fa364e26848e2f 100644 (file)
@@ -52,7 +52,22 @@ int ukbhit(void)
   return ( error == 0 ? cnt : -1 );
 }
 
   return ( error == 0 ? cnt : -1 );
 }
 
-#else
+char getch(void)
+{
+       char c;
+       int error;
+       struct termios Otty, Ntty;
+       if ( tcgetattr(STDIN_FILENO, &Otty) == -1 ) return -1;
+       Ntty = Otty;
+       Ntty.c_lflag &= ~ICANON; /* disable buffered i/o */
+       if (0 == (error = tcsetattr(STDIN_FILENO, TCSANOW, &Ntty))) {   // set new attributes
+               c = getchar();
+               error += tcsetattr(STDIN_FILENO, TCSANOW, &Otty);           // reset attributes
+       }
+       return ( error == 0 ? c : -1 );
+}
+
+#else // _WIN32
 
 #include <conio.h>
 int ukbhit(void) {
 
 #include <conio.h>
 int ukbhit(void) {
index e3549c023fbee6507ee5456a93ba7c4cab2e39dd..29dd7d5c83a202467112b909b6c451e4e0b28732 100644 (file)
 #endif
 
 extern int ukbhit(void);
 #endif
 
 extern int ukbhit(void);
+#ifndef _WIN32
+extern char getch(void);
+#else
+#include <conio.h>
+#endif
 
 extern void AddLogLine(char *fileName, char *extData, char *c);
 extern void AddLogHex(char *fileName, char *extData, const uint8_t * data, const size_t len);
 
 extern void AddLogLine(char *fileName, char *extData, char *c);
 extern void AddLogHex(char *fileName, char *extData, const uint8_t * data, const size_t len);
index 70245a787961b430f3bac0c9d909295156febd40..82b346f5abb42ec1f06136e76d647a48c7be5173 100644 (file)
@@ -10,6 +10,8 @@
 #ifndef __SMARTCARD_H
 #define __SMARTCARD_H
 
 #ifndef __SMARTCARD_H
 #define __SMARTCARD_H
 
+#include <stdint.h>
+
 //-----------------------------------------------------------------------------
 // ISO 7618  Smart Card 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // ISO 7618  Smart Card 
 //-----------------------------------------------------------------------------
index 785435f03d0539a30ac19d6f90e8d1ec61dc3f9d..4c27ac85e4b4283fdd04b5f38670555ec31062da 100644 (file)
@@ -33,6 +33,7 @@ typedef struct {
     uint32_t asDwords[USB_CMD_DATA_SIZE/4];
   } d;
 } PACKED UsbCommand;
     uint32_t asDwords[USB_CMD_DATA_SIZE/4];
   } d;
 } PACKED UsbCommand;
+
 // A struct used to send sample-configs over USB
 typedef struct{
        uint8_t decimation;
 // A struct used to send sample-configs over USB
 typedef struct{
        uint8_t decimation;
@@ -63,6 +64,9 @@ typedef struct{
 #define CMD_STATUS                                                        0x0108
 #define CMD_PING                                                          0x0109
 
 #define CMD_STATUS                                                        0x0108
 #define CMD_PING                                                          0x0109
 
+// controlling the ADC input multiplexer
+#define CMD_SET_ADC_MUX                                                   0x020F
+
 // RDV40,  Smart card operations
 #define CMD_SMART_RAW                                                     0x0140
 #define CMD_SMART_UPGRADE                                                 0x0141
 // RDV40,  Smart card operations
 #define CMD_SMART_RAW                                                     0x0140
 #define CMD_SMART_UPGRADE                                                 0x0141
@@ -86,7 +90,6 @@ typedef struct{
 #define CMD_HID_SIM_TAG                                                   0x020C
 #define CMD_SET_LF_DIVISOR                                                0x020D
 #define CMD_LF_SIMULATE_BIDIR                                             0x020E
 #define CMD_HID_SIM_TAG                                                   0x020C
 #define CMD_SET_LF_DIVISOR                                                0x020D
 #define CMD_LF_SIMULATE_BIDIR                                             0x020E
-#define CMD_SET_ADC_MUX                                                   0x020F
 #define CMD_HID_CLONE_TAG                                                 0x0210
 #define CMD_EM410X_WRITE_TAG                                              0x0211
 #define CMD_INDALA_CLONE_TAG                                              0x0212
 #define CMD_HID_CLONE_TAG                                                 0x0210
 #define CMD_EM410X_WRITE_TAG                                              0x0211
 #define CMD_INDALA_CLONE_TAG                                              0x0212
@@ -112,12 +115,8 @@ typedef struct{
 #define CMD_VIKING_CLONE_TAG                                              0x0223
 #define CMD_T55XX_WAKEUP                                                  0x0224
 #define CMD_COTAG                                                         0x0225
 #define CMD_VIKING_CLONE_TAG                                              0x0223
 #define CMD_T55XX_WAKEUP                                                  0x0224
 #define CMD_COTAG                                                         0x0225
-// misc extra
 #define CMD_PARADOX_CLONE_TAG                                             0x0226
 
 #define CMD_PARADOX_CLONE_TAG                                             0x0226
 
-
-/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
-
 // For the 13.56 MHz tags
 #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693                             0x0300
 #define CMD_READ_SRI512_TAG                                               0x0303
 // For the 13.56 MHz tags
 #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693                             0x0300
 #define CMD_READ_SRI512_TAG                                               0x0303
@@ -136,7 +135,6 @@ typedef struct{
 #define CMD_SNOOP_HITAG                                                   0x0370
 #define CMD_SIMULATE_HITAG                                                0x0371
 #define CMD_READER_HITAG                                                  0x0372
 #define CMD_SNOOP_HITAG                                                   0x0370
 #define CMD_SIMULATE_HITAG                                                0x0371
 #define CMD_READER_HITAG                                                  0x0372
-
 #define CMD_SIMULATE_HITAG_S                                              0x0368
 #define CMD_TEST_HITAGS_TRACES                                            0x0367
 #define CMD_READ_HITAG_S                                                  0x0373
 #define CMD_SIMULATE_HITAG_S                                              0x0368
 #define CMD_TEST_HITAGS_TRACES                                            0x0367
 #define CMD_READ_HITAG_S                                                  0x0373
@@ -144,7 +142,6 @@ typedef struct{
 #define CMD_WR_HITAG_S                                                    0x0375
 #define CMD_EMU_HITAG_S                                                   0x0376
 
 #define CMD_WR_HITAG_S                                                    0x0375
 #define CMD_EMU_HITAG_S                                                   0x0376
 
-
 #define CMD_SIMULATE_TAG_ISO_14443B                                       0x0381
 #define CMD_SNOOP_ISO_14443B                                              0x0382
 #define CMD_SNOOP_ISO_14443a                                              0x0383
 #define CMD_SIMULATE_TAG_ISO_14443B                                       0x0381
 #define CMD_SNOOP_ISO_14443B                                              0x0382
 #define CMD_SNOOP_ISO_14443a                                              0x0383
@@ -251,6 +248,10 @@ typedef struct{
 #define FLAG_TUNE_HF   2
 #define FLAG_TUNE_ALL  3
 
 #define FLAG_TUNE_HF   2
 #define FLAG_TUNE_ALL  3
 
+// Hardware capabilities
+#define HAS_EXTRA_FLASH_MEM    (1 << 0)
+#define HAS_SMARTCARD_SLOT     (1 << 1)
+
 
 // CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions:
 /* Whether a bootloader that understands the common_area is present */
 
 // CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions:
 /* Whether a bootloader that understands the common_area is present */
Impressum, Datenschutz