mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-13 01:56:59 -07:00
Add support for standard USB Smartcard Readers (#765)
* 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'
This commit is contained in:
parent
1511ea28a8
commit
a9104f7e31
14 changed files with 382 additions and 93 deletions
|
@ -26,7 +26,7 @@ before_install:
|
|||
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
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "LCD.h"
|
||||
#endif
|
||||
|
||||
static uint32_t hw_capabilities;
|
||||
|
||||
// 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__;
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
set_hw_capabilities();
|
||||
|
||||
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;
|
||||
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.
|
||||
|
|
22
armsrc/i2c.c
22
armsrc/i2c.c
|
@ -656,28 +656,6 @@ static bool GetATR(smart_card_atr_t *card_ptr) {
|
|||
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);
|
||||
|
||||
|
|
|
@ -35,13 +35,27 @@ 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
|
||||
|
||||
LUAPLATFORM = generic
|
||||
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
|
||||
|
@ -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
|
||||
|
||||
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 $@
|
||||
|
||||
|
@ -328,7 +342,7 @@ $(OBJDIR)/%_AVX512.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
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
#include "cmdmain.h"
|
||||
#include "cmddata.h"
|
||||
|
||||
/* low-level hardware control */
|
||||
|
||||
static uint32_t hw_capabilities = 0;
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
|
@ -403,6 +404,10 @@ int CmdTune(const char *Cmd)
|
|||
return CmdTuneSamples(Cmd);
|
||||
}
|
||||
|
||||
bool PM3hasSmartcardSlot(void) {
|
||||
return (hw_capabilities & HAS_SMARTCARD_SLOT);
|
||||
}
|
||||
|
||||
int CmdVersion(const char *Cmd)
|
||||
{
|
||||
|
||||
|
@ -411,10 +416,11 @@ int CmdVersion(const char *Cmd)
|
|||
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]);
|
||||
hw_capabilities = resp.arg[2];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#ifndef CMDHW_H__
|
||||
#define CMDHW_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
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);
|
||||
bool PM3hasSmartcardSlot(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,14 +18,18 @@
|
|||
#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 "pcsc.h"
|
||||
|
||||
#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) {
|
||||
|
@ -44,6 +48,17 @@ static int usage_sm_raw(void) {
|
|||
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");
|
||||
|
@ -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;
|
||||
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]);
|
||||
|
@ -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);
|
||||
protocol_T0_present = false;
|
||||
if ((TD1 & 0x0f) == 0) {
|
||||
protocol_T0_present = true;
|
||||
}
|
||||
if ((TD1 & 0x0f) == 15) {
|
||||
protocol_T15_present = true;
|
||||
}
|
||||
|
||||
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 ((TDi & 0x0f) == 0) {
|
||||
protocol_T0_present = true;
|
||||
}
|
||||
if ((TDi & 0x0f) == 15) {
|
||||
protocol_T15_present = 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]);
|
||||
|
||||
|
||||
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");
|
||||
|
@ -280,26 +312,38 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
|
|||
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);
|
||||
|
||||
uint8_t isok = resp.arg[0] & 0xFF;
|
||||
if (!isok) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -379,6 +423,32 @@ static int smart_response(uint8_t *data) {
|
|||
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;
|
||||
|
@ -756,23 +826,11 @@ int CmdSmartInfo(const char *Cmd){
|
|||
//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) {
|
||||
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));
|
||||
if (!smart_getATR(&card)) {
|
||||
if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// print header
|
||||
PrintAndLogEx(INFO, "--- Smartcard Information ---------");
|
||||
|
@ -830,22 +888,11 @@ int CmdSmartReader(const char *Cmd){
|
|||
//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) {
|
||||
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));
|
||||
if (!smart_getATR(&card)) {
|
||||
if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
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"},
|
||||
{"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"},
|
||||
|
|
177
client/pcsc.c
Normal file
177
client/pcsc.c
Normal file
|
@ -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;
|
||||
}
|
22
client/pcsc.h
Normal file
22
client/pcsc.h
Normal file
|
@ -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
|
|
@ -28,6 +28,8 @@
|
|||
#include "cmdhw.h"
|
||||
#include "whereami.h"
|
||||
#include "comms.h"
|
||||
#include "pcsc.h"
|
||||
|
||||
|
||||
void
|
||||
#ifdef __has_attribute
|
||||
|
@ -48,6 +50,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) {
|
|||
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
|
||||
|
|
|
@ -52,7 +52,22 @@ int ukbhit(void)
|
|||
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) {
|
||||
|
|
|
@ -76,6 +76,11 @@
|
|||
#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);
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#ifndef __SMARTCARD_H
|
||||
#define __SMARTCARD_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ISO 7618 Smart Card
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -33,6 +33,7 @@ typedef struct {
|
|||
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;
|
||||
|
@ -63,6 +64,9 @@ typedef struct{
|
|||
#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
|
||||
|
@ -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_SET_ADC_MUX 0x020F
|
||||
#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
|
||||
// misc extra
|
||||
#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
|
||||
|
@ -136,7 +135,6 @@ typedef struct{
|
|||
#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
|
||||
|
@ -144,7 +142,6 @@ typedef struct{
|
|||
#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
|
||||
|
@ -251,6 +248,10 @@ typedef struct{
|
|||
#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 */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue