]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - client/cmdhf14a.c
Merge branch 'master' into fix_iso15693_fpga
[proxmark3-svn] / client / cmdhf14a.c
index 9611a2d175153dab1b7b0f62f4e80a28e50f54f6..58315582742ed8850c15e1277f7f9f065cfa0791 100644 (file)
@@ -27,7 +27,7 @@
 #include "cmdmain.h"
 #include "mifare.h"
 #include "cmdhfmfu.h"
 #include "cmdmain.h"
 #include "mifare.h"
 #include "cmdhfmfu.h"
-#include "mifarehost.h"
+#include "mifare/mifarehost.h"
 #include "cliparser/cliparser.h"
 #include "emv/apduinfo.h"
 #include "emv/emvcore.h"
 #include "cliparser/cliparser.h"
 #include "emv/apduinfo.h"
 #include "emv/emvcore.h"
@@ -46,28 +46,28 @@ int CmdHF14AList(const char *Cmd)
        return 0;
 }
 
        return 0;
 }
 
-int Hf14443_4aGetCardData(iso14a_card_select_t * card) {
+int Hf14443_4aGetCardData(iso14a_card_select_t *card) {
        UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};
        SendCommand(&c);
 
        UsbCommand resp;
        UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};
        SendCommand(&c);
 
        UsbCommand resp;
-       WaitForResponse(CMD_ACK,&resp);
+       WaitForResponse(CMD_NACK, &resp);
 
        memcpy(card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
 
        uint64_t select_status = resp.arg[0];       // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
 
 
        memcpy(card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
 
        uint64_t select_status = resp.arg[0];       // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
 
-       if(select_status == 0) {
+       if (select_status == 0) {
                PrintAndLog("E->iso14443a card select failed");
                return 1;
        }
 
                PrintAndLog("E->iso14443a card select failed");
                return 1;
        }
 
-       if(select_status == 2) {
+       if (select_status == 2) {
                PrintAndLog("E->Card doesn't support iso14443-4 mode");
                return 1;
        }
 
                PrintAndLog("E->Card doesn't support iso14443-4 mode");
                return 1;
        }
 
-       if(select_status == 3) {
+       if (select_status == 3) {
                PrintAndLog("E->Card doesn't support standard iso14443-3 anticollision");
                PrintAndLog("\tATQA : %02x %02x", card->atqa[1], card->atqa[0]);
                return 1;
                PrintAndLog("E->Card doesn't support standard iso14443-3 anticollision");
                PrintAndLog("\tATQA : %02x %02x", card->atqa[1], card->atqa[0]);
                return 1;
@@ -156,20 +156,24 @@ int CmdHF14AReader(const char *Cmd) {
        return 0;
 }
 
        return 0;
 }
 
-int CmdHF14AInfo(const char *Cmd)
-{
+
+int CmdHF14AInfo(const char *Cmd) {
+
        UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}};
        SendCommand(&c);
 
        UsbCommand resp;
        UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}};
        SendCommand(&c);
 
        UsbCommand resp;
-       WaitForResponse(CMD_ACK,&resp);
-
+       if (!WaitForResponseTimeout(CMD_NACK, &resp, 500)) {
+               if (Cmd[0] != 's') PrintAndLog("Error: No response from Proxmark.\n");
+               return 0;
+       }
+       
        iso14a_card_select_t card;
        memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
 
        uint64_t select_status = resp.arg[0];       // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
 
        iso14a_card_select_t card;
        memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
 
        uint64_t select_status = resp.arg[0];       // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
 
-       if(select_status == 0) {
+       if (select_status == 0) {
                if (Cmd[0] != 's') PrintAndLog("iso14443a card select failed");
                // disconnect
                c.arg[0] = 0;
                if (Cmd[0] != 's') PrintAndLog("iso14443a card select failed");
                // disconnect
                c.arg[0] = 0;
@@ -217,13 +221,13 @@ int CmdHF14AInfo(const char *Cmd)
                        SendCommand(&c);
 
                        UsbCommand resp;
                        SendCommand(&c);
 
                        UsbCommand resp;
-                       WaitForResponse(CMD_ACK,&resp);
+                       WaitForResponse(CMD_NACK,&resp);
 
                        memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
 
                        select_status = resp.arg[0];        // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
 
 
                        memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
 
                        select_status = resp.arg[0];        // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
 
-                       if(select_status == 0) {
+                       if (select_status == 0) {
                                //PrintAndLog("iso14443a card select failed");
                                // disconnect
                                c.arg[0] = 0;
                                //PrintAndLog("iso14443a card select failed");
                                // disconnect
                                c.arg[0] = 0;
@@ -272,7 +276,7 @@ int CmdHF14AInfo(const char *Cmd)
 
        // Double & triple sized UID, can be mapped to a manufacturer.
        // HACK: does this apply for Ultralight cards?
 
        // Double & triple sized UID, can be mapped to a manufacturer.
        // HACK: does this apply for Ultralight cards?
-       if ( card.uidlen > 4 ) {
+       if (card.uidlen > 4) {
                PrintAndLog("MANUFACTURER : %s", getManufacturerName(card.uid[0]));
        }
 
                PrintAndLog("MANUFACTURER : %s", getManufacturerName(card.uid[0]));
        }
 
@@ -430,7 +434,7 @@ int CmdHF14AInfo(const char *Cmd)
        (void)mfCIdentify();
 
        if (isMifareClassic) {
        (void)mfCIdentify();
 
        if (isMifareClassic) {
-               switch(DetectClassicPrng()) {
+               switch (DetectClassicPrng()) {
                case 0:
                        PrintAndLog("Prng detection: HARDENED (hardnested)");
                        break;
                case 0:
                        PrintAndLog("Prng detection: HARDENED (hardnested)");
                        break;
@@ -462,7 +466,7 @@ int CmdHF14ACUIDs(const char *Cmd)
                SendCommand(&c);
 
                UsbCommand resp;
                SendCommand(&c);
 
                UsbCommand resp;
-               WaitForResponse(CMD_ACK,&resp);
+               WaitForResponse(CMD_NACK,&resp);
 
                iso14a_card_select_t *card = (iso14a_card_select_t *) resp.d.asBytes;
 
 
                iso14a_card_select_t *card = (iso14a_card_select_t *) resp.d.asBytes;
 
@@ -921,20 +925,34 @@ int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool lea
 int CmdHF14AAPDU(const char *cmd) {
        uint8_t data[USB_CMD_DATA_SIZE];
        int datalen = 0;
 int CmdHF14AAPDU(const char *cmd) {
        uint8_t data[USB_CMD_DATA_SIZE];
        int datalen = 0;
+       uint8_t header[5];
+       int headerlen = 0;
        bool activateField = false;
        bool leaveSignalON = false;
        bool decodeTLV = false;
        bool activateField = false;
        bool leaveSignalON = false;
        bool decodeTLV = false;
+       bool decodeAPDU = false;
+       bool makeAPDU = false;
+       bool extendedAPDU = false;
+       int le = 0;
+       int res = 0;
 
        CLIParserInit("hf 14a apdu",
 
        CLIParserInit("hf 14a apdu",
-               "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL)",
-               "Sample:\n\thf 14a apdu -st 00A404000E325041592E5359532E444446303100\n");
+                                 "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL). Works with all APDU types from ISO 7816-4:2013",
+                                 "Examples:\n\thf 14a apdu -st 00A404000E325041592E5359532E444446303100\n"
+                                 "\thf 14a apdu -sd 00A404000E325041592E5359532E444446303100 - decode APDU\n"
+                                 "\thf 14a apdu -sm 00A40400 325041592E5359532E4444463031 -l 256 - encode standard APDU\n"
+                                 "\thf 14a apdu -sm 00A40400 325041592E5359532E4444463031 -el 65536 - encode extended APDU\n");
 
        void* argtable[] = {
                arg_param_begin,
 
        void* argtable[] = {
                arg_param_begin,
-               arg_lit0("sS",  "select",  "activate field and select card"),
-               arg_lit0("kK",  "keep",    "leave the signal field ON after receive response"),
-               arg_lit0("tT",  "tlv",     "executes TLV decoder if it possible"),
-               arg_strx1(NULL, NULL,      "<APDU (hex)>", NULL),
+               arg_lit0("sS",  "select",   "activate field and select card"),
+               arg_lit0("kK",  "keep",     "leave the signal field ON after receive response"),
+               arg_lit0("tT",  "tlv",      "executes TLV decoder if it possible"),
+               arg_lit0("dD",  "decapdu",  "decode APDU request if it possible"),
+               arg_str0("mM",  "make",     "<head (CLA INS P1 P2) hex>", "make APDU with head from this field and data from data field. Must be 4 bytes length: <CLA INS P1 P2>"),
+               arg_lit0("eE",  "extended", "make extended length APDU (requires `-m`)"),
+               arg_int0("lL",  "le",       "<Le (int)>", "Le APDU parameter (requires `-m`)"),
+               arg_strx1(NULL, NULL,       "<APDU (hex) | data (hex)>", "APDU (without `-m`), or data (with `-m`)"),
                arg_param_end
        };
        CLIExecWithReturn(cmd, argtable, false);
                arg_param_end
        };
        CLIExecWithReturn(cmd, argtable, false);
@@ -942,15 +960,71 @@ int CmdHF14AAPDU(const char *cmd) {
        activateField = arg_get_lit(1);
        leaveSignalON = arg_get_lit(2);
        decodeTLV = arg_get_lit(3);
        activateField = arg_get_lit(1);
        leaveSignalON = arg_get_lit(2);
        decodeTLV = arg_get_lit(3);
-       // len = data + PCB(1b) + CRC(2b)
-       CLIGetHexBLessWithReturn(4, data, &datalen, 1 + 2);
+       decodeAPDU = arg_get_lit(4);
+
+       res = CLIParamHexToBuf(arg_get_str(5), header, sizeof(header), &headerlen);
+       makeAPDU = headerlen > 0;
+       if (res || (makeAPDU && headerlen != 4)) {
+               PrintAndLogEx(ERR, "header length must be exactly 4 bytes");
+               CLIParserFree();
+               return 1;
+       }
+       extendedAPDU = arg_get_lit(6);
+       le = arg_get_int_def(7, 0);
+
+       if (makeAPDU) {
+               uint8_t apdudata[USB_CMD_DATA_SIZE] = {0};
+               int apdudatalen = 0;
+
+               CLIGetHexBLessWithReturn(8, apdudata, &apdudatalen, 1 + 2);
 
 
+               APDUStruct apdu;
+               apdu.cla = header[0];
+               apdu.ins = header[1];
+               apdu.p1 = header[2];
+               apdu.p2 = header[3];
+
+               apdu.lc = apdudatalen;
+               apdu.data = apdudata;
+
+               apdu.extended_apdu = extendedAPDU;
+               apdu.le = le;
+
+               if (APDUEncode(&apdu, data, &datalen)) {
+                       PrintAndLogEx(ERR, "can't make apdu with provided parameters.");
+                       CLIParserFree();
+                       return 2;
+               }
+       } else {
+               if (extendedAPDU) {
+                       PrintAndLogEx(ERR, "`-e` without `-m`.");
+                       CLIParserFree();
+                       return 3;
+               }
+               if (le > 0) {
+                       PrintAndLogEx(ERR, "`-l` without `-m`.");
+                       CLIParserFree();
+                       return 3;
+               }
+
+               // len = data + PCB(1b) + CRC(2b)
+               CLIGetHexBLessWithReturn(8, data, &datalen, 1 + 2);
+       }
 
        CLIParserFree();
 //  PrintAndLog("---str [%d] %s", arg_get_str(4)->count, arg_get_str(4)->sval[0]);
 
        CLIParserFree();
 //  PrintAndLog("---str [%d] %s", arg_get_str(4)->count, arg_get_str(4)->sval[0]);
-       PrintAndLog(">>>>[%s%s%s] %s", activateField ? "sel ": "", leaveSignalON ? "keep ": "", decodeTLV ? "TLV": "", sprint_hex(data, datalen));
+       PrintAndLogEx(NORMAL, ">>>>[%s%s%s] %s", activateField ? "sel ": "", leaveSignalON ? "keep ": "", decodeTLV ? "TLV": "", sprint_hex(data, datalen));
+
+       if (decodeAPDU) {
+               APDUStruct apdu;
+
+               if (APDUDecode(data, datalen, &apdu) == 0)
+                       APDUPrint(apdu);
+               else
+                       PrintAndLogEx(WARNING, "can't decode APDU.");
+       }
 
 
-       int res = ExchangeAPDU14a(data, datalen, activateField, leaveSignalON, data, USB_CMD_DATA_SIZE, &datalen);
+       res = ExchangeAPDU14a(data, datalen, activateField, leaveSignalON, data, USB_CMD_DATA_SIZE, &datalen);
 
        if (res)
                return res;
 
        if (res)
                return res;
Impressum, Datenschutz