#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"
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;
- 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
- if(select_status == 0) {
+ if (select_status == 0) {
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;
}
- 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;
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;
- 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
- if(select_status == 0) {
+ if (select_status == 0) {
if (Cmd[0] != 's') PrintAndLog("iso14443a card select failed");
// disconnect
c.arg[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));
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;
// 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]));
}
(void)mfCIdentify();
if (isMifareClassic) {
- switch(DetectClassicPrng()) {
+ switch (DetectClassicPrng()) {
case 0:
PrintAndLog("Prng detection: HARDENED (hardnested)");
break;
SendCommand(&c);
UsbCommand resp;
- WaitForResponse(CMD_ACK,&resp);
+ WaitForResponse(CMD_NACK,&resp);
iso14a_card_select_t *card = (iso14a_card_select_t *) resp.d.asBytes;
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 decodeAPDU = false;
+ bool makeAPDU = false;
+ bool extendedAPDU = false;
+ int le = 0;
+ int res = 0;
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,
- 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);
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]);
- 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;