diff --git a/client/Makefile b/client/Makefile index d4ac33b2..917dc767 100644 --- a/client/Makefile +++ b/client/Makefile @@ -82,7 +82,9 @@ POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d CORESRCS = uart_posix.c \ uart_win32.c \ util.c \ - util_posix.c + util_posix.c \ + ui.c \ + comms.c CMDSRCS = crapto1/crapto1.c\ crapto1/crypto1.c\ @@ -106,7 +108,6 @@ CMDSRCS = crapto1/crapto1.c\ iso14443crc.c \ iso15693tools.c \ graph.c \ - ui.c \ cmddata.c \ lfdemod.c \ emv/crypto_polarssl.c\ @@ -169,8 +170,7 @@ CMDSRCS = crapto1/crapto1.c\ cmdscript.c\ pm3_binlib.c\ pm3_bitlib.c\ - protocols.c\ - comms.c + protocols.c cpu_arch = $(shell uname -m) ifneq ($(findstring 86, $(cpu_arch)), ) diff --git a/client/cmddata.c b/client/cmddata.c index 471665b7..c4f0e8a3 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -8,14 +8,15 @@ // Data and Graph commands //----------------------------------------------------------------------------- +#include "cmddata.h" + #include // also included in util.h #include // also included in util.h #include #include // for CmdNorm INT_MIN && INT_MAX -#include "cmddata.h" #include "util.h" #include "cmdmain.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" // for show graph controls #include "graph.h" // for graph data #include "cmdparser.h"// already included in cmdmain.h diff --git a/client/cmdhf.c b/client/cmdhf.c index 4a672255..17c31209 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -9,17 +9,18 @@ // High frequency commands //----------------------------------------------------------------------------- +#include "cmdhf.h" + #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "util.h" #include "ui.h" #include "iso14443crc.h" #include "parity.h" #include "cmdmain.h" #include "cmdparser.h" -#include "cmdhf.h" #include "cmdhf14a.h" #include "cmdhf14b.h" #include "cmdhf15.h" diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 4684ae29..859dec2f 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -20,7 +20,7 @@ #include "util.h" #include "util_posix.h" #include "iso14443crc.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "cmdparser.h" #include "common.h" diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index bae40c09..ff0bf7c9 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -8,18 +8,19 @@ // High frequency ISO14443B commands //----------------------------------------------------------------------------- +#include "cmdhf14b.h" + #include #include #include #include #include #include "iso14443crc.h" -#include "proxmark3.h" +#include "comms.h" #include "graph.h" #include "util.h" #include "ui.h" #include "cmdparser.h" -#include "cmdhf14b.h" #include "cmdmain.h" #include "cmdhf14a.h" diff --git a/client/cmdhf14b.h b/client/cmdhf14b.h index a45b7434..4fcae927 100644 --- a/client/cmdhf14b.h +++ b/client/cmdhf14b.h @@ -11,6 +11,8 @@ #ifndef CMDHF14B_H__ #define CMDHF14B_H__ +#include + int CmdHF14B(const char *Cmd); int CmdHF14BList(const char *Cmd); int CmdHF14BInfo(const char *Cmd); diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 570a0420..08cc3b15 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -22,17 +22,18 @@ // the client. Signal Processing & decoding is done on the pc. This is the slowest // variant, but offers the possibility to analyze the waveforms directly. +#include "cmdhf15.h" + #include #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "graph.h" #include "ui.h" #include "util.h" #include "cmdparser.h" -#include "cmdhf15.h" #include "iso15693tools.h" #include "cmdmain.h" diff --git a/client/cmdhf15.h b/client/cmdhf15.h index c6264604..d0517fe5 100644 --- a/client/cmdhf15.h +++ b/client/cmdhf15.h @@ -11,6 +11,8 @@ #ifndef CMDHF15_H__ #define CMDHF15_H__ +#include + int CmdHF15(const char *Cmd); int CmdHF15Demod(const char *Cmd); diff --git a/client/cmdhfepa.c b/client/cmdhfepa.c index f3456afb..ac1f4268 100644 --- a/client/cmdhfepa.c +++ b/client/cmdhfepa.c @@ -17,7 +17,7 @@ #include #include "util.h" #include "util_posix.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "cmdparser.h" #include "common.h" diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index e99c3285..499f7aae 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -16,7 +16,7 @@ #include #include #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "cmdparser.h" #include "cmdhficlass.h" diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 9c9613ae..691e1978 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -8,15 +8,17 @@ // High frequency Legic commands //----------------------------------------------------------------------------- +#include "cmdhflegic.h" + #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "cmdparser.h" -#include "cmdhflegic.h" #include "cmdmain.h" #include "util.h" + static int CmdHelp(const char *Cmd); static command_t CommandTable[] = diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index a2da01c9..b50d6013 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -15,7 +15,7 @@ #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "cmdmain.h" #include "cmdhfmfhard.h" #include "parity.h" diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index cf19436c..be618d6e 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -25,6 +25,7 @@ #include #include #include "proxmark3.h" +#include "comms.h" #include "cmdmain.h" #include "ui.h" #include "util.h" diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index ac76c8dd..e4115d71 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -12,7 +12,7 @@ #include #include -#include "proxmark3.h" +#include "comms.h" #include "usb_cmd.h" #include "cmdmain.h" #include "ui.h" diff --git a/client/cmdhftopaz.c b/client/cmdhftopaz.c index 39ff1804..b0b8a3d2 100644 --- a/client/cmdhftopaz.c +++ b/client/cmdhftopaz.c @@ -8,17 +8,18 @@ // High frequency Topaz (NFC Type 1) commands //----------------------------------------------------------------------------- +#include "cmdhftopaz.h" + #include #include #include #include #include "cmdmain.h" #include "cmdparser.h" -#include "cmdhftopaz.h" #include "cmdhf14a.h" #include "ui.h" #include "mifare.h" -#include "proxmark3.h" +#include "comms.h" #include "iso14443crc.h" #include "protocols.h" diff --git a/client/cmdhw.c b/client/cmdhw.c index 4ede122f..bdab01eb 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -8,14 +8,15 @@ // Hardware commands //----------------------------------------------------------------------------- +#include "cmdhw.h" + #include #include #include #include #include "ui.h" -#include "proxmark3.h" +#include "comms.h" #include "cmdparser.h" -#include "cmdhw.h" #include "cmdmain.h" #include "cmddata.h" diff --git a/client/cmdlf.c b/client/cmdlf.c index 285d377a..c09a299c 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -8,14 +8,15 @@ // Low frequency commands //----------------------------------------------------------------------------- +#include "cmdlf.h" + #include #include #include #include #include #include -#include "proxmark3.h" -#include "cmdlf.h" +#include "comms.h" #include "lfdemod.h" // for psk2TOpsk1 #include "util.h" // for parsing cli command utils #include "ui.h" // for show graph controls diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index 141ba172..cde94555 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -11,10 +11,11 @@ // FSK2a, RF/50, 96 bits (complete) //----------------------------------------------------------------------------- +#include "cmdlfawid.h" + #include #include // sscanf -#include "proxmark3.h" // Definitions, USB controls, etc -#include "cmdlfawid.h" +#include "comms.h" // Definitions, USB controls, etc #include "ui.h" // PrintAndLog #include "cmdparser.h" // CmdsParse, CmdsHelp #include "lfdemod.h" // parityTest + diff --git a/client/cmdlfcotag.c b/client/cmdlfcotag.c index ca163480..d1808c9a 100644 --- a/client/cmdlfcotag.c +++ b/client/cmdlfcotag.c @@ -7,13 +7,15 @@ //----------------------------------------------------------------------------- // Low frequency COTAG commands //----------------------------------------------------------------------------- + +#include "cmdlfcotag.h" + #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "cmddata.h" -#include "cmdlfcotag.h" #include "lfdemod.h" #include "usb_cmd.h" #include "cmdmain.h" diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index ff2ae5b0..cdaeb5ed 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -8,11 +8,12 @@ // Low frequency EM4x commands //----------------------------------------------------------------------------- +#include "cmdlfem4x.h" + #include #include #include -#include "cmdlfem4x.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlffdx.c b/client/cmdlffdx.c index 2e2ee9fd..20f834ce 100644 --- a/client/cmdlffdx.c +++ b/client/cmdlffdx.c @@ -13,7 +13,7 @@ #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" // for PrintAndLog #include "util.h" #include "cmdparser.h" diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index 19b5a142..ca58d8ab 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -8,10 +8,11 @@ // Low frequency HID commands (known) //----------------------------------------------------------------------------- +#include "cmdlfhid.h" + #include #include -#include "cmdlfhid.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "graph.h" #include "cmdparser.h" diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 26ba9238..0fd8801b 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -8,10 +8,12 @@ // Low frequency Hitag support //----------------------------------------------------------------------------- +#include "cmdlfhitag.h" + #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "cmdparser.h" #include "common.h" diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 0a4f7834..b30231c5 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -8,10 +8,11 @@ // PSK1, rf/32, 64 or 224 bits (known) //----------------------------------------------------------------------------- +#include "cmdlfindala.h" + #include #include -#include "cmdlfindala.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "graph.h" #include "cmdparser.h" diff --git a/client/cmdlfio.c b/client/cmdlfio.c index f2f2df06..feb7d373 100644 --- a/client/cmdlfio.c +++ b/client/cmdlfio.c @@ -8,13 +8,14 @@ // FSK2a, rf/64, 64 bits (complete) //----------------------------------------------------------------------------- +#include "cmdlfio.h" + #include #include #include #include #include -#include "cmdlfio.h" -#include "proxmark3.h" +#include "comms.h" #include "graph.h" #include "ui.h" #include "cmdparser.h" diff --git a/client/cmdlfjablotron.c b/client/cmdlfjablotron.c index 9c69099e..4756266c 100644 --- a/client/cmdlfjablotron.c +++ b/client/cmdlfjablotron.c @@ -9,10 +9,11 @@ //----------------------------------------------------------------------------- #include "cmdlfjablotron.h" + #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlfnexwatch.c b/client/cmdlfnexwatch.c index caabe835..d44c2a27 100644 --- a/client/cmdlfnexwatch.c +++ b/client/cmdlfnexwatch.c @@ -7,12 +7,14 @@ // Low frequency Honeywell NexWatch tag commands // PSK1 RF/16, RF/2, 128 bits long (known) //----------------------------------------------------------------------------- + +#include "cmdlfnexwatch.h" + #include #include #include #include -#include "cmdlfnexwatch.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlfnoralsy.c b/client/cmdlfnoralsy.c index 2c90fa14..52c35081 100644 --- a/client/cmdlfnoralsy.c +++ b/client/cmdlfnoralsy.c @@ -7,11 +7,13 @@ // Low frequency Noralsy tag commands // ASK/Manchester, STT, RF/32, 96 bits long (some bits unknown) //----------------------------------------------------------------------------- + #include "cmdlfnoralsy.h" + #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlfpac.c b/client/cmdlfpac.c index ef6b394b..190361ec 100644 --- a/client/cmdlfpac.c +++ b/client/cmdlfpac.c @@ -7,10 +7,12 @@ // Low frequency Stanley/PAC tag commands // NRZ, RF/32, 128 bits long (unknown cs) //----------------------------------------------------------------------------- + #include "cmdlfpac.h" + #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlfpcf7931.c b/client/cmdlfpcf7931.c index ffaf946f..9c694b8d 100644 --- a/client/cmdlfpcf7931.c +++ b/client/cmdlfpcf7931.c @@ -8,9 +8,12 @@ //----------------------------------------------------------------------------- // Low frequency PCF7931 commands //----------------------------------------------------------------------------- + +#include "cmdlfpcf7931.h" + #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" @@ -18,7 +21,6 @@ #include "cmddata.h" #include "cmdmain.h" #include "cmdlf.h" -#include "cmdlfpcf7931.h" static int CmdHelp(const char *Cmd); diff --git a/client/cmdlfpcf7931.h b/client/cmdlfpcf7931.h index e093039c..8b24f03a 100644 --- a/client/cmdlfpcf7931.h +++ b/client/cmdlfpcf7931.h @@ -12,6 +12,8 @@ #ifndef CMDLFPCF7931_H__ #define CMDLFPCF7931_H__ +#include + struct pcf7931_config{ uint8_t Pwd[7]; uint16_t InitDelay; diff --git a/client/cmdlfpresco.c b/client/cmdlfpresco.c index 2f4bacfe..865b384b 100644 --- a/client/cmdlfpresco.c +++ b/client/cmdlfpresco.c @@ -7,11 +7,13 @@ // Low frequency Presco tag commands // ASK/Manchester, rf/32, 128 bits (complete) //----------------------------------------------------------------------------- + +#include "cmdlfpresco.h" + #include #include #include -#include "cmdlfpresco.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlfpyramid.c b/client/cmdlfpyramid.c index 366889f3..82367720 100644 --- a/client/cmdlfpyramid.c +++ b/client/cmdlfpyramid.c @@ -7,11 +7,13 @@ // Low frequency Farpoint / Pyramid tag commands // FSK2a, rf/50, 128 bits (complete) //----------------------------------------------------------------------------- + +#include "cmdlfpyramid.h" + #include #include #include -#include "cmdlfpyramid.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlfsecurakey.c b/client/cmdlfsecurakey.c index 8ae81250..44b77060 100644 --- a/client/cmdlfsecurakey.c +++ b/client/cmdlfsecurakey.c @@ -7,11 +7,13 @@ // Low frequency Securakey tag commands // ASK/Manchester, RF/40, 96 bits long (unknown cs) //----------------------------------------------------------------------------- + #include "cmdlfsecurakey.h" + #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index a9fbb71e..f53ff0d6 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -7,19 +7,20 @@ // Low frequency T55xx commands //----------------------------------------------------------------------------- +#include "cmdlft55xx.h" + #include #include #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "graph.h" #include "cmdmain.h" #include "cmdparser.h" #include "cmddata.h" #include "cmdlf.h" -#include "cmdlft55xx.h" #include "util.h" #include "lfdemod.h" #include "cmdhf14a.h" //for getTagInfo diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index 4f0fd21d..2ae3e69b 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -10,6 +10,9 @@ #ifndef CMDLFT55XX_H__ #define CMDLFT55XX_H__ +#include +#include + typedef struct { uint32_t bl1; uint32_t bl2; diff --git a/client/cmdlfti.c b/client/cmdlfti.c index 7e0af94b..ff463971 100644 --- a/client/cmdlfti.c +++ b/client/cmdlfti.c @@ -14,7 +14,7 @@ #include #include #include "crc16.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "graph.h" #include "cmdparser.h" diff --git a/client/cmdlfviking.c b/client/cmdlfviking.c index 779156c8..73a9126a 100644 --- a/client/cmdlfviking.c +++ b/client/cmdlfviking.c @@ -7,11 +7,13 @@ // Low frequency Viking tag commands (AKA FDI Matalec Transit) // ASK/Manchester, RF/32, 64 bits (complete) //----------------------------------------------------------------------------- + +#include "cmdlfviking.h" + #include #include #include -#include "proxmark3.h" -#include "cmdlfviking.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlfvisa2000.c b/client/cmdlfvisa2000.c index 04589ba5..33259794 100644 --- a/client/cmdlfvisa2000.c +++ b/client/cmdlfvisa2000.c @@ -13,7 +13,7 @@ #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdmain.c b/client/cmdmain.c index c3b46145..01d4c9a7 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -50,13 +50,13 @@ command_t* getTopLevelCommandTable() return CommandTable; } -int CmdHelp(const char *Cmd) +static int CmdHelp(const char *Cmd) { CmdsHelp(CommandTable); return 0; } -int CmdQuit(const char *Cmd) +static int CmdQuit(const char *Cmd) { return 99; } diff --git a/client/cmdmain.h b/client/cmdmain.h index a833b41e..42b49145 100644 --- a/client/cmdmain.h +++ b/client/cmdmain.h @@ -11,12 +11,7 @@ #ifndef CMDMAIN_H__ #define CMDMAIN_H__ -#include -#include -#include "usb_cmd.h" #include "cmdparser.h" -#include "comms.h" - extern int CommandReceived(char *Cmd); extern command_t* getTopLevelCommandTable(); diff --git a/client/comms.c b/client/comms.c index b62f6fda..be0cfd10 100644 --- a/client/comms.c +++ b/client/comms.c @@ -9,33 +9,42 @@ // Code for communicating with the proxmark3 hardware. //----------------------------------------------------------------------------- -#include - #include "comms.h" + +#include +#ifdef __linux__ +#include // for unlink() +#endif #include "uart.h" #include "ui.h" #include "common.h" #include "util_posix.h" -// Declare globals. // Serial port that we are communicating with the PM3 on. -static serial_port sp; +static serial_port sp = NULL; +static char *serial_port_name = NULL; // If TRUE, then there is no active connection to the PM3, and we will drop commands sent. static bool offline; +typedef struct { + bool run; // If TRUE, continue running the uart_communication thread + bool block_after_ACK; // if true, block after receiving an ACK package +} communication_arg_t; + +static communication_arg_t conn; +static pthread_t USB_communication_thread; + // Transmit buffer. -// TODO: Use locks and execute this on the main thread, rather than the receiver -// thread. Running on the main thread means we need to be careful in the -// flasher, as it means SendCommand is no longer async, and can't be used as a -// buffer for a pending command when the connection is re-established. -static UsbCommand txcmd; -volatile static bool txcmd_pending = false; +static UsbCommand txBuffer; +static bool txBuffer_pending = false; +static pthread_mutex_t txBufferMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t txBufferSig = PTHREAD_COND_INITIALIZER; // Used by UsbReceiveCommand as a ring buffer for messages that are yet to be // processed by a command handler (WaitForResponse{,Timeout}) -static UsbCommand cmdBuffer[CMD_BUFFER_SIZE]; +static UsbCommand rxBuffer[CMD_BUFFER_SIZE]; // Points to the next empty position to write to static int cmd_head = 0; @@ -43,8 +52,8 @@ static int cmd_head = 0; // Points to the position of the last unread command static int cmd_tail = 0; -// to lock cmdBuffer operations from different threads -static pthread_mutex_t cmdBufferMutex = PTHREAD_MUTEX_INITIALIZER; +// to lock rxBuffer operations from different threads +static pthread_mutex_t rxBufferMutex = PTHREAD_MUTEX_INITIALIZER; // These wrappers are required because it is not possible to access a static // global variable outside of the context of a single file. @@ -57,38 +66,6 @@ bool IsOffline() { return offline; } -bool OpenProxmark(char *portname, bool waitCOMPort, int timeout) { - if (!waitCOMPort) { - sp = uart_open(portname); - } else { - printf("Waiting for Proxmark to appear on %s ", portname); - fflush(stdout); - int openCount = 0; - do { - sp = uart_open(portname); - msleep(1000); - printf("."); - fflush(stdout); - } while(++openCount < timeout && (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT)); - printf("\n"); - } - - // check result of uart opening - if (sp == INVALID_SERIAL_PORT) { - printf("ERROR: invalid serial port\n"); - return false; - } else if (sp == CLAIMED_SERIAL_PORT) { - printf("ERROR: serial port is claimed by another process\n"); - return false; - } else { - return true; - } -} - -void CloseProxmark(void) { - uart_close(sp); -} - void SendCommand(UsbCommand *c) { #ifdef COMMS_DEBUG printf("Sending %04x cmd\n", c->cmd); @@ -98,15 +75,22 @@ void SendCommand(UsbCommand *c) { PrintAndLog("Sending bytes to proxmark failed - offline"); return; } - /** - The while-loop below causes hangups at times, when the pm3 unit is unresponsive - or disconnected. The main console thread is alive, but comm thread just spins here. - Not good.../holiman - **/ - while(txcmd_pending); - txcmd = *c; - txcmd_pending = true; + pthread_mutex_lock(&txBufferMutex); + /** + This causes hangups at times, when the pm3 unit is unresponsive or disconnected. The main console thread is alive, + but comm thread just spins here. Not good.../holiman + **/ + while (txBuffer_pending) { + pthread_cond_wait(&txBufferSig, &txBufferMutex); // wait for communication thread to complete sending a previous commmand + } + + txBuffer = *c; + txBuffer_pending = true; + pthread_cond_signal(&txBufferSig); // tell communication thread that a new command can be send + + pthread_mutex_unlock(&txBufferMutex); + } @@ -119,18 +103,18 @@ void SendCommand(UsbCommand *c) { void clearCommandBuffer() { //This is a very simple operation - pthread_mutex_lock(&cmdBufferMutex); + pthread_mutex_lock(&rxBufferMutex); cmd_tail = cmd_head; - pthread_mutex_unlock(&cmdBufferMutex); + pthread_mutex_unlock(&rxBufferMutex); } /** * @brief storeCommand stores a USB command in a circular buffer * @param UC */ -void storeCommand(UsbCommand *command) +static void storeCommand(UsbCommand *command) { - pthread_mutex_lock(&cmdBufferMutex); + pthread_mutex_lock(&rxBufferMutex); if( (cmd_head+1) % CMD_BUFFER_SIZE == cmd_tail) { // If these two are equal, we're about to overwrite in the @@ -139,11 +123,11 @@ void storeCommand(UsbCommand *command) } // Store the command at the 'head' location - UsbCommand* destination = &cmdBuffer[cmd_head]; + UsbCommand* destination = &rxBuffer[cmd_head]; memcpy(destination, command, sizeof(UsbCommand)); cmd_head = (cmd_head +1) % CMD_BUFFER_SIZE; //increment head and wrap - pthread_mutex_unlock(&cmdBufferMutex); + pthread_mutex_unlock(&rxBufferMutex); } @@ -152,22 +136,22 @@ void storeCommand(UsbCommand *command) * @param response location to write command * @return 1 if response was returned, 0 if nothing has been received */ -int getCommand(UsbCommand* response) +static int getCommand(UsbCommand* response) { - pthread_mutex_lock(&cmdBufferMutex); + pthread_mutex_lock(&rxBufferMutex); //If head == tail, there's nothing to read, or if we just got initialized if (cmd_head == cmd_tail){ - pthread_mutex_unlock(&cmdBufferMutex); + pthread_mutex_unlock(&rxBufferMutex); return 0; } //Pick out the next unread command - UsbCommand* last_unread = &cmdBuffer[cmd_tail]; + UsbCommand* last_unread = &rxBuffer[cmd_tail]; memcpy(response, last_unread, sizeof(UsbCommand)); //Increment tail - this is a circular buffer, so modulo buffer size cmd_tail = (cmd_tail + 1) % CMD_BUFFER_SIZE; - pthread_mutex_unlock(&cmdBufferMutex); + pthread_mutex_unlock(&rxBufferMutex); return 1; } @@ -202,35 +186,54 @@ static void UsbCommandReceived(UsbCommand *UC) } -void +static void #ifdef __has_attribute #if __has_attribute(force_align_arg_pointer) __attribute__((force_align_arg_pointer)) #endif #endif -*uart_receiver(void *targ) { - receiver_arg *conn = (receiver_arg*)targ; +*uart_communication(void *targ) { + communication_arg_t *conn = (communication_arg_t*)targ; size_t rxlen; - uint8_t rx[sizeof(UsbCommand)]; - uint8_t *prx = rx; + UsbCommand rx; + UsbCommand *prx = ℞ while (conn->run) { rxlen = 0; - if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-rx), &rxlen) && rxlen) { + bool ACK_received = false; + if (uart_receive(sp, (uint8_t *)prx, sizeof(UsbCommand) - (prx-&rx), &rxlen) && rxlen) { prx += rxlen; - if (prx-rx < sizeof(UsbCommand)) { + if (prx-&rx < sizeof(UsbCommand)) { continue; } - UsbCommandReceived((UsbCommand*)rx); + UsbCommandReceived(&rx); + if (rx.cmd == CMD_ACK) { + ACK_received = true; + } } - prx = rx; + prx = ℞ - if(txcmd_pending) { - if (!uart_send(sp, (uint8_t*) &txcmd, sizeof(UsbCommand))) { + + pthread_mutex_lock(&txBufferMutex); + + if (conn->block_after_ACK) { + // if we just received an ACK, wait here until a new command is to be transmitted + if (ACK_received) { + while (!txBuffer_pending) { + pthread_cond_wait(&txBufferSig, &txBufferMutex); + } + } + } + + if(txBuffer_pending) { + if (!uart_send(sp, (uint8_t*) &txBuffer, sizeof(UsbCommand))) { PrintAndLog("Sending bytes to proxmark failed"); } - txcmd_pending = false; + txBuffer_pending = false; + pthread_cond_signal(&txBufferSig); // tell main thread that txBuffer is empty } + + pthread_mutex_unlock(&txBufferMutex); } pthread_exit(NULL); @@ -238,7 +241,6 @@ __attribute__((force_align_arg_pointer)) } - /** * Data transfer from Proxmark to client. This method times out after * ms_timeout milliseconds. @@ -289,6 +291,66 @@ bool GetFromBigBuf(uint8_t *dest, int bytes, int start_index, UsbCommand *respon return false; } + +bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode) { + char *portname = (char *)port; + if (!wait_for_port) { + sp = uart_open(portname); + } else { + printf("Waiting for Proxmark to appear on %s ", portname); + fflush(stdout); + int openCount = 0; + do { + sp = uart_open(portname); + msleep(1000); + printf("."); + fflush(stdout); + } while(++openCount < timeout && (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT)); + printf("\n"); + } + + // check result of uart opening + if (sp == INVALID_SERIAL_PORT) { + printf("ERROR: invalid serial port\n"); + sp = NULL; + serial_port_name = NULL; + return false; + } else if (sp == CLAIMED_SERIAL_PORT) { + printf("ERROR: serial port is claimed by another process\n"); + sp = NULL; + serial_port_name = NULL; + return false; + } else { + // start the USB communication thread + serial_port_name = portname; + conn.run = true; + conn.block_after_ACK = flash_mode; + pthread_create(&USB_communication_thread, NULL, &uart_communication, &conn); + return true; + } +} + + +void CloseProxmark(void) { + conn.run = false; + pthread_join(USB_communication_thread, NULL); + + if (sp) { + uart_close(sp); + } + +#ifdef __linux__ + // Fix for linux, it seems that it is extremely slow to release the serial port file descriptor /dev/* + if (serial_port_name) { + unlink(serial_port_name); + } +#endif + + // Clean up our state + sp = NULL; + serial_port_name = NULL; +} + /** * Waits for a certain response type. This method waits for a maximum of diff --git a/client/comms.h b/client/comms.h index 111677ad..68981165 100644 --- a/client/comms.h +++ b/client/comms.h @@ -22,24 +22,14 @@ #define CMD_BUFFER_SIZE 50 #endif -typedef struct { - // If TRUE, continue running the uart_receiver thread - bool run; - - // Lock around serial port receives - pthread_mutex_t recv_lock; -} receiver_arg; - - void SetOffline(bool new_offline); bool IsOffline(); -bool OpenProxmark(char *portname, bool waitCOMPort, int timeout); +bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode); void CloseProxmark(void); void SendCommand(UsbCommand *c); -void *uart_receiver(void *targ); void clearCommandBuffer(); bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning); bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout); diff --git a/client/flash.c b/client/flash.c index e3714185..e43ebd1b 100644 --- a/client/flash.c +++ b/client/flash.c @@ -20,12 +20,7 @@ #include "elf.h" #include "proxendian.h" #include "usb_cmd.h" -#include "uart.h" - -void SendCommand(UsbCommand* txcmd); -void ReceiveCommand(UsbCommand* rxcmd); - -serial_port sp; +#include "comms.h" #define FLASH_START 0x100000 #define FLASH_SIZE (256*1024) @@ -42,22 +37,6 @@ static const uint8_t elf_ident[] = { EV_CURRENT }; -void CloseProxmark(const char *serial_port_name) { - // Clean up the port - uart_close(sp); - // Fix for linux, it seems that it is extremely slow to release the serial port file descriptor /dev/* - unlink(serial_port_name); -} - -bool OpenProxmark(size_t i, const char *serial_port_name) { - sp = uart_open(serial_port_name); - if (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT) { - //poll once a second - return false; - } - - return true; -} // Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent // unaligned segments if needed @@ -207,7 +186,7 @@ static int check_segs(flash_file_t *ctx, int can_write_bl) { } // Load an ELF file and prepare it for flashing -int flash_load(flash_file_t *ctx, const char *name, int can_write_bl) +int flash_load(flash_file_t *ctx, const char *name, bool can_write_bl) { FILE *fd = NULL; Elf32_Ehdr ehdr; @@ -295,7 +274,7 @@ static int get_proxmark_state(uint32_t *state) c.cmd = CMD_DEVICE_INFO; SendCommand(&c); UsbCommand resp; - ReceiveCommand(&resp); + WaitForResponse(CMD_UNKNOWN, &resp); // wait for any response. No timeout. // Three outcomes: // 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK @@ -355,17 +334,16 @@ static int enter_bootloader(char *serial_port_name) } msleep(100); - CloseProxmark(serial_port_name); + CloseProxmark(); - fprintf(stderr,"Waiting for Proxmark to reappear on %s",serial_port_name); - do { - sleep(1); - fprintf(stderr, "."); - } while (!OpenProxmark(0, serial_port_name)); - - fprintf(stderr," Found.\n"); - - return 0; + bool opened = OpenProxmark(serial_port_name, true, 120, true); // wait for 2 minutes + if (opened) { + fprintf(stderr," Found.\n"); + return 0; + } else { + fprintf(stderr,"Error: Proxmark not found.\n"); + return -1; + } } fprintf(stderr, "Error: Unknown Proxmark mode\n"); @@ -375,7 +353,7 @@ static int enter_bootloader(char *serial_port_name) static int wait_for_ack(void) { UsbCommand ack; - ReceiveCommand(&ack); + WaitForResponse(CMD_UNKNOWN, &ack); if (ack.cmd != CMD_ACK) { printf("Error: Unexpected reply 0x%04" PRIx64 " (expected ACK)\n", ack.cmd); return -1; @@ -424,12 +402,12 @@ static int write_block(uint32_t address, uint8_t *data, uint32_t length) memset(block_buf, 0xFF, BLOCK_SIZE); memcpy(block_buf, data, length); - UsbCommand c; + UsbCommand c; c.cmd = CMD_FINISH_WRITE; c.arg[0] = address; memcpy(c.d.asBytes, block_buf, length); - SendCommand(&c); - return wait_for_ack(); + SendCommand(&c); + return wait_for_ack(); } // Write a file's segments to Flash diff --git a/client/flash.h b/client/flash.h index f8ffd221..06c7c96e 100644 --- a/client/flash.h +++ b/client/flash.h @@ -10,8 +10,7 @@ #define __FLASH_H__ #include -#include "elf.h" -#include "uart.h" +#include typedef struct { void *data; @@ -26,14 +25,10 @@ typedef struct { flash_seg_t *segments; } flash_file_t; -int flash_load(flash_file_t *ctx, const char *name, int can_write_bl); +int flash_load(flash_file_t *ctx, const char *name, bool can_write_bl); int flash_start_flashing(int enable_bl_writes, char *serial_port_name); int flash_write(flash_file_t *ctx); void flash_free(flash_file_t *ctx); int flash_stop_flashing(void); -void CloseProxmark(const char *serial_port_name); -bool OpenProxmark(size_t i, const char *serial_port_name); - -extern serial_port sp; #endif diff --git a/client/flasher.c b/client/flasher.c index 2bb87df9..a008f7bc 100644 --- a/client/flasher.c +++ b/client/flasher.c @@ -10,18 +10,14 @@ #include #include #include +#include #include "proxmark3.h" #include "util.h" #include "util_posix.h" #include "flash.h" -#include "uart.h" +#include "comms.h" #include "usb_cmd.h" -#ifdef _WIN32 -# define unlink(x) -#else -# include -#endif void cmd_debug(UsbCommand* UC) { // Debug @@ -37,29 +33,6 @@ void cmd_debug(UsbCommand* UC) { printf("...\n"); } -void SendCommand(UsbCommand* txcmd) { -// printf("send: "); -// cmd_debug(txcmd); - if (!uart_send(sp,(uint8_t*)txcmd,sizeof(UsbCommand))) { - printf("Sending bytes to proxmark failed\n"); - exit(1); - } -} - -void ReceiveCommand(UsbCommand* rxcmd) { - uint8_t* prxcmd = (uint8_t*)rxcmd; - uint8_t* prx = prxcmd; - size_t rxlen; - while (true) { - if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-prxcmd), &rxlen)) { - prx += rxlen; - if ((prx-prxcmd) >= sizeof(UsbCommand)) { - return; - } - } - } -} - static void usage(char *argv0) { fprintf(stderr, "Usage: %s [-b] image.elf [image.elf...]\n\n", argv0); @@ -77,7 +50,7 @@ static void usage(char *argv0) int main(int argc, char **argv) { - int can_write_bl = 0; + int can_write_bl = false; int num_files = 0; int res; flash_file_t files[MAX_FILES]; @@ -92,7 +65,7 @@ int main(int argc, char **argv) for (int i = 2; i < argc; i++) { if (argv[i][0] == '-') { if (!strcmp(argv[i], "-b")) { - can_write_bl = 1; + can_write_bl = true; } else { usage(argv[0]); return -1; @@ -110,12 +83,12 @@ int main(int argc, char **argv) char* serial_port_name = argv[1]; - fprintf(stderr,"Waiting for Proxmark to appear on %s", serial_port_name); - do { - msleep(1000); - fprintf(stderr, "."); - } while (!OpenProxmark(0, serial_port_name)); - fprintf(stderr," Found.\n"); + if (!OpenProxmark(serial_port_name, true, 120, true)) { // wait for 2 minutes + fprintf(stderr, "Could not find Proxmark on %s.\n\n", serial_port_name); + return -1; + } else { + fprintf(stderr," Found.\n"); + } res = flash_start_flashing(can_write_bl, serial_port_name); if (res < 0) @@ -137,7 +110,8 @@ int main(int argc, char **argv) if (res < 0) return -1; - CloseProxmark(serial_port_name); + // Stop the command thread. + CloseProxmark(); fprintf(stderr, "All done.\n\n"); fprintf(stderr, "Have a nice day!\n"); diff --git a/client/mifarehost.c b/client/mifarehost.c index e1ced176..2d69cfae 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -16,7 +16,7 @@ #include #include "crapto1/crapto1.h" -#include "proxmark3.h" +#include "comms.h" #include "usb_cmd.h" #include "cmdmain.h" #include "ui.h" diff --git a/client/proxmark3.c b/client/proxmark3.c index 88cb5fa7..6fb066e8 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -9,6 +9,8 @@ // Main binary //----------------------------------------------------------------------------- +#include "proxmark3.h" + #include #include #include @@ -17,7 +19,6 @@ #include #include -#include "proxmark3.h" #include "util_posix.h" #include "proxgui.h" #include "cmdmain.h" @@ -26,7 +27,7 @@ #include "cmdparser.h" #include "cmdhw.h" #include "whereami.h" - +#include "comms.h" void #ifdef __has_attribute @@ -35,18 +36,12 @@ __attribute__((force_align_arg_pointer)) #endif #endif main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { - receiver_arg conn; char *cmd = NULL; - pthread_t reader_thread; bool execCommand = (script_cmd != NULL); bool stdinOnPipe = !isatty(STDIN_FILENO); - memset(&conn, 0, sizeof(receiver_arg)); - if (usb_present) { - conn.run = true; SetOffline(false); - pthread_create(&reader_thread, NULL, &uart_receiver, &conn); // cache Version information now: CmdVersion(NULL); } else { @@ -136,11 +131,6 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { } write_history(".history"); - - if (usb_present) { - conn.run = false; - pthread_join(reader_thread, NULL); - } if (script_file) { fclose(script_file); @@ -294,7 +284,7 @@ int main(int argc, char* argv[]) { set_my_executable_path(); // try to open USB connection to Proxmark - usb_present = OpenProxmark(argv[1], waitCOMPort, 20); + usb_present = OpenProxmark(argv[1], waitCOMPort, 20, false); #ifdef HAVE_GUI #ifdef _WIN32 diff --git a/client/proxmark3.h b/client/proxmark3.h index c6185c43..86d09bc0 100644 --- a/client/proxmark3.h +++ b/client/proxmark3.h @@ -20,7 +20,6 @@ extern "C" { #endif -void SendCommand(UsbCommand *c); const char *get_my_executable_path(void); const char *get_my_executable_directory(void); void main_loop(char *script_cmds_file, char *script_cmd, bool usb_present); diff --git a/client/scripting.c b/client/scripting.c index 0c761cb2..e73c7138 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -15,6 +15,7 @@ #include #include #include "proxmark3.h" +#include "comms.h" #include "usb_cmd.h" #include "cmdmain.h" #include "util.h" diff --git a/client/scripts/mifarePlus.lua b/client/scripts/mifarePlus.lua new file mode 100644 index 00000000..061ff736 --- /dev/null +++ b/client/scripts/mifarePlus.lua @@ -0,0 +1,340 @@ +local cmds = require('commands') +local lib14a = require('read14a') +getopt = require('getopt') -- Used to get command line arguments + +example = "script run mifarePlus" +author = "Dominic Celiano" +desc = +[[ +Purpose: Lua script to communicate with the Mifare Plus EV1, including personalization (setting the keys) and proximity check. Manually edit the file to add to the commands you can send the card. + +Please read the NXP manual before running this script to prevent making irreversible changes. Also note: + - The Mifare Plus must start in SL0 for personalization. Card can then be moved to SL1 or SL3. + - The keys are hardcoded in the script to "00...". Unless you change this, only use this script for testing purposes. + - Make sure you choose your card size correctly (2kB or 4kB). + +Small changes can be to made this script to communicate with the Mifare Plus S, X, or SE. + +Arguments: + -h : this help +]] + +SIXTEEN_BYTES_ZEROS = "00000000000000000000000000000000" + +GETVERS_INIT = "0360" -- Begins the GetVersion command +GETVERS_CONT = "03AF" -- Continues the GetVersion command +POWEROFF = "OFF" +WRITEPERSO = "03A8" +COMMITPERSO = "03AA" +AUTH_FIRST = "0370" +AUTH_CONT = "0372" +AUTH_NONFIRST = "0376" +PREPAREPC = "03F0" +PROXIMITYCHECK = "03F2" +VERIFYPC = "03FD" +READPLAINNOMACUNMACED = "0336" + +--- +-- This is only meant to be used when errors occur +function oops(err) + print("ERROR: ",err) +end + +--- +-- Usage help +function help() + print(desc) + print("Example usage") + print(example) +end + +--- +-- Used to send raw data to the firmware to subsequently forward the data to the card. +function sendRaw(rawdata, crc, power) + print((": %s"):format(rawdata)) + + local flags = lib14a.ISO14A_COMMAND.ISO14A_RAW + if crc then + flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC + end + if power then + flags = flags + lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + end + + local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, + arg1 = flags, -- Send raw + arg2 = string.len(rawdata) / 2, -- arg2 contains the length, which is half the length of the ASCII-string rawdata + data = rawdata} + local ignore_response = false + local result, err = lib14a.sendToDevice(command, ignore_response) + if result then + --unpack the first 4 parts of the result as longs, and the last as an extremely long string to later be cut down based on arg1, the number of bytes returned + local count,cmd,arg1,arg2,arg3,data = bin.unpack('LLLLH512',result) + returned_bytes = string.sub(data, 1, arg1 * 2) + if returned_bytes ~= "" then + print((": %s"):format(returned_bytes)) -- need to multiply by 2 because the hex digits are actually two bytes when they are strings + end + return returned_bytes + else + err = "Error sending the card raw data." + oops(err) + end +end + +function writePerso() + -- Used to write any data, including the keys (Key A and Key B), for all the sectors. + -- writePerso() command parameters: + -- 1 byte - 0xA8 - Command Code + -- 2 bytes - Address of the first block or key to be written to (40 blocks are numbered from 0x0000 to 0x00FF) + -- X bytes - The data bytes to be written, starting from the first block. Amount of data sent can be from 16 to 240 bytes in 16 byte increments. This allows + -- up to 15 blocks to be written at once. + -- response from PICC: + -- 0x90 - OK + -- 0x09 - targeted block is invalid for writes, i.e. block 0, which contains manufacturer data + -- 0x0B - command invalid + -- 0x0C - unexpected command length + + + + cardsize = 4 --need to set to 4 for 4k or 2 for 2k + if(cardsize == 4) then + numsectors = 39 + elseif(cardsize == 2) then + numsectors = 31 + else + oops("Invalid card size") + end + + -- Write to the AES sector keys + print("Setting AES Sector keys") + for i=0,numsectors do --for each sector number + local keyA_block = "40" .. string.format("%02x", i * 2) + local keyB_block = "40" .. string.format("%02x", (i * 2) + 1) + --Can also calculate the keys fancily to make them unique, if desired + keyA = SIXTEEN_BYTES_ZEROS + keyB = SIXTEEN_BYTES_ZEROS + writeBlock(keyA_block, keyA) + writeBlock(keyB_block, keyB) + end + print("Finished setting AES Sector keys") + + print("Setting misc keys which haven't been set yet.") + --CardMasterKey + blocknum = "9000" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --CardConfigurationKey + blocknum = "9001" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --L3SwitchKey + blocknum = "9003" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --SL1CardAuthKey + blocknum = "9004" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --L3SectorSwitchKey + blocknum = "9006" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --L1L3MixSectorSwitchKey + blocknum = "9007" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --VC Keys + --VCProximityKey + blocknum = "A001" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --VCSelectENCKey + blocknum = "A080" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --VCSelectMACKey + blocknum = "A081" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --TransactionMACKey1 + blocknum = "C000" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --TransactionMACConfKey1 + blocknum = "C001" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + print("Finished setting misc keys.") + + print("WritePerso finished! Card is ready to move into new security level.") +end + +function writeBlock(blocknum, data) + -- Method writes 16 bytes of the string sent (data) to the specified block number + -- The block numbers sent to the card need to be in little endian format (i.e. block 0x0001 is sent as 0x1000) + blocknum_little_endian = string.sub(blocknum, 3, 4) .. string.sub(blocknum, 1, 2) + commandString = WRITEPERSO .. blocknum_little_endian .. data --Write 16 bytes (32 hex chars). + response = sendRaw(commandString, true, true) --0x90 is returned upon success + if string.sub(response, 3, 4) ~= "90" then + oops(("error occurred while trying to write to block %s"):format(blocknum)) + end +end + +function authenticateAES() + -- Used to try to authenticate with the AES keys we programmed into the card, to ensure the authentication works correctly. + commandString = AUTH_FIRST + commandString = commandString .. "" +end + +function getVersion() + sendRaw(GETVERS_INIT, true, true) + sendRaw(GETVERS_CONT, true, true) + sendRaw(GETVERS_CONT, true, true) +end + +function commitPerso(SL) + --pass SL as "01" to move to SL1 or "03" to move to SL3. + commandString = COMMITPERSO .. SL + response = sendRaw(commandString, true, true) --0x90 is returned upon success + if string.sub(response, 3, 4) ~= "90" then + oops("error occurred while trying to switch security level") + end +end + +function calculateMAC(MAC_input) + -- Pad the input if it is not a multiple of 16 bytes (32 nibbles). + if(string.len(MAC_input) % 32 ~= 0) then + MAC_input = MAC_input .. "80" + end + while(string.len(MAC_input) % 32 ~= 0) do + MAC_input = MAC_input .. "0" + end + print("Padded MAC Input = " .. MAC_input .. ", length (bytes) = " .. string.len(MAC_input) / 2) + + --The MAC would actually be calculated here, and the output stored in raw_output + raw_output = "00010203040506070001020304050607" -- Dummy filler for now of 16-byte output. To be filled with actual MAC for testing purposes. + + -- The final 8-byte MAC output is a concatenation of every 2nd byte starting from the second MSB. + final_output = "" + j = 3 + for i = 1,8 do + final_output = final_output .. string.sub(RndR, j, j + 1) .. string.sub(RndC, j, j + 1) + j = j + 4 + end + return final_output +end + +function proximityCheck() + --PreparePC-- + commandString = PREPAREPC + response = sendRaw(commandString, true, true) + if(response == "") then + print("ERROR: This card does not support the Proximity Check command.") + return + end + OPT = string.sub(response, 5, 6) + if(tonumber(OPT) == 1) then + pps_present = true + else + pps_present = false + end + pubRespTime = string.sub(response, 7, 10) + if(pps_present == true) then + pps = string.sub(response, 11, 12) + else + pps = nil + end + print("OPT = " .. OPT .. " pubRespTime = " .. pubRespTime .. " pps = " .. pps) + + --PC-- + RndC = "0001020304050607" --Random Challenge + num_rounds = 8 --Needs to be 1, 2, 4, or 8 + part_len = 8 / num_rounds + j = 1 + RndR = "" + for i = 1,num_rounds do + pRndC = "" + for q = 1,(part_len*2) do + pRndC = pRndC .. string.sub(RndC,j,j) + j = j + 1 + end + commandString = PROXIMITYCHECK .. "0" .. tostring(part_len) .. pRndC + pRndR = string.sub(sendRaw(commandString, true, true), 3, 3+part_len) + RndR = RndR .. pRndR + end + print("RndC = " .. RndC .. " RndR = " .. RndR) + + --VerifyPC-- + MAC_input = "FD" .. OPT .. pubRespTime + if(pps_present == true) then + MAC_input = MAC_input .. pps + end + rnum_concat = "" + rnum_concat = RndR .. RndC --temporary (only works for when a single random challenge (8 bytes) is sent) + -- j = 1 + -- for i = 1,8 do + -- rnum_concat = rnum_concat .. string.sub(RndR, j, j + 1) .. string.sub(RndC, j, j + 1) + -- j = j + 2 + -- end + MAC_input = MAC_input .. rnum_concat + print("Concatenation of random numbers = " .. rnum_concat) + print("Final PCD concatenation before input into MAC function = " .. MAC_input) + MAC_tag = calculateMAC(MAC_input) + print("8-byte PCD MAC_tag (placeholder - currently incorrect) = " .. MAC_tag) + commandString = VERIFYPC .. MAC_tag + response = sendRaw(commandString, true, true) + print(response) + PICC_MAC = string.sub(response, 5, 20) + print("8-byte MAC returned by PICC = " .. PICC_MAC) + MAC_input = "90" .. string.sub(MAC_input, 3) + print("Final PICC concatenation before input into MAC function = " .. MAC_input) + MAC_tag = calculateMAC(MAC_input) + print("8-byte PICC MAC_tag (placeholder - currently incorrect) = " .. MAC_tag) + +end + +--- +-- The main entry point +function main(args) + print("") -- Print a blank line to make things look cleaner + for o, a in getopt.getopt(args, 'h') do -- Populate command line arguments + if o == "h" then help() return end + end + + -- Initialize the card using the already-present read14a library + info,err = lib14a.read14443a(true, false) + --Perform RATS and PPS (Protocol and Parameter Selection) check to finish the ISO 14443-4 protocol. + response = sendRaw("e050", true, true) + if(response == "") then + print("No response from RATS.") + end + response = sendRaw("D01100", true, true) + if(response == "") then + print("No response from PPS check.") + end + if err then + oops(err) + sendRaw(POWEROFF, false, false) + return + else + print(("Connected to card with a UID of %s."):format(info.uid)) + end + + + -- Now, the card is initialized and we can do more interesting things. + + --writePerso() + --commitPerso("03") --move to SL3 + --getVersion() + proximityCheck() + + --commandString = VERIFYPC .. "186EFDE8DDC7D30B" + -- MAC = f5180d6e 40fdeae8 e9dd6ac7 bcd3350b + -- response = sendRaw(commandString, true, true) + + -- attempt to read VCProximityKey at block A001 + -- commandString = READPLAINNOMACUNMACED .. "01A0" .. "01" + -- response = sendRaw(commandString, true, true) + + -- authenticate with CardConfigurationKey + -- commandString = AUTH_FIRST .. "0190" .. "00" + -- response = sendRaw(commandString, true, true) + + -- Power off the Proxmark + sendRaw(POWEROFF, false, false) + + + +end + + +main(args) -- Call the main function