X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/f2b0169cc69c9bb963c58d419bb8e313dcbe5b24..a2bb2735d5095aabeba4a891fe4ba867a9afc2b3:/client/cmdhf14a.c diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index c16a64bd..1a7f6970 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// 2011, Merlok +// 2011, 2017 Merlok // Copyright (C) 2010 iZsh , Hagen Fritsch // // This code is licensed to you under the terms of the GNU GPL, version 2 or, @@ -9,34 +9,11 @@ // High frequency ISO14443A commands //----------------------------------------------------------------------------- -#include -#include -#include -#include -#include -#include "util.h" -#include "util_posix.h" -#include "iso14443crc.h" -#include "data.h" -#include "proxmark3.h" -#include "ui.h" -#include "cmdparser.h" #include "cmdhf14a.h" -#include "common.h" -#include "cmdmain.h" -#include "mifare.h" -#include "cmdhfmfu.h" -#include "mifarehost.h" static int CmdHelp(const char *Cmd); static int waitCmd(uint8_t iLen); -// structure and database for uid -> tagtype lookups -typedef struct { - uint8_t uid; - char* desc; -} manufactureName; - const manufactureName manufactureMapping[] = { // ID, "Vendor Country" { 0x01, "Motorola UK" }, @@ -110,7 +87,6 @@ const manufactureName manufactureMapping[] = { { 0x00, "no tag-info available" } // must be the last entry }; - // get a product description based on the UID // uid[8] tag uid // returns description of the best match @@ -554,79 +530,11 @@ int CmdHF14ASnoop(const char *Cmd) { return 0; } -int CmdHF14AAPDU(const char *cmd) { +int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int *dataoutlen) { uint8_t data[USB_CMD_DATA_SIZE]; - uint16_t datalen = 0; + int datalen; uint8_t cmdc = 0; - char buf[5] = {0}; - int i = 0; - uint32_t temp; uint8_t first, second; - bool activateField = false; - bool leaveSignalON = false; - bool decodeTLV = false; - - if (strlen(cmd)<2) { - PrintAndLog("Usage: hf 14a apdu [-s] [-k] [-t] "); - PrintAndLog(" -s activate field and select card"); - PrintAndLog(" -k leave the signal field ON after receive response"); - PrintAndLog(" -t executes TLV decoder if it possible"); - return 0; - } - - // strip - while (*cmd==' ' || *cmd=='\t') cmd++; - - while (cmd[i]!='\0') { - if (cmd[i]==' ' || cmd[i]=='\t') { i++; continue; } - if (cmd[i]=='-') { - switch (cmd[i + 1]) { - case 's': - case 'S': - activateField = true; - break; - case 'k': - case 'K': - leaveSignalON = true; - break; - case 't': - case 'T': - decodeTLV = true; - break; - default: - PrintAndLog("Invalid option"); - return 1; - } - i += 2; - continue; - } - if ((cmd[i] >= '0' && cmd[i] <= '9') || - (cmd[i] >= 'a' && cmd[i] <= 'f') || - (cmd[i] >= 'A' && cmd[i] <= 'F') ) { - buf[strlen(buf) + 1] = 0x00; - buf[strlen(buf)] = cmd[i]; - i++; - - if (strlen(buf) >= 2) { - sscanf(buf, "%x", &temp); - data[datalen] = (uint8_t)(temp & 0xff); - *buf = 0; - if (datalen > sizeof(data) - 2) { - PrintAndLog("Buffer is full..."); - break; - } else { - datalen++; - } - } - continue; - } - PrintAndLog("Invalid char on input"); - return 1; - } - if (*buf) { - PrintAndLog("Hex must have even number of digits. Detected %d symbols.", datalen * 2 + strlen(buf)); - return 1; - } if (activateField) cmdc |= ISO14A_CONNECT; @@ -634,16 +542,14 @@ int CmdHF14AAPDU(const char *cmd) { cmdc |= ISO14A_NO_DISCONNECT; // ISO 14443 APDU frame: PCB [CID] [NAD] APDU CRC PCB=0x02 - memmove(data + 1, data, datalen); + memcpy(data + 1, datain, datainlen); data[0] = 0x02; // bnr,nad,cid,chn=0; i-block(0x00) - datalen++; + datalen = datainlen + 1; ComputeCrc14443(CRC_14443_A, data, datalen, &first, &second); data[datalen++] = first; data[datalen++] = second; - PrintAndLog("--%s %s %s >>>> %s", activateField ? "sel": "", leaveSignalON ? "keep": "", decodeTLV ? "TLV": "", sprint_hex(data, datalen)); - // "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes // https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size // here length USB_CMD_DATA_SIZE=512 @@ -657,52 +563,138 @@ int CmdHF14AAPDU(const char *cmd) { if (activateField) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) - return 2; + return 1; if (resp.arg[0] != 1) - return 2; + return 1; } if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { recv = resp.d.asBytes; uint8_t iLen = resp.arg[0]; + + *dataoutlen = iLen - 1 - 2; + if (*dataoutlen < 0) + *dataoutlen = 0; + memcpy(dataout, recv + 1, *dataoutlen); + if(!iLen) - return 2; + return 1; - PrintAndLog("<<<< %s", sprint_hex(recv, iLen)); - // check apdu length if (iLen < 5) { - PrintAndLog("ERROR: Small APDU response."); - return 3; + PrintAndLog("APDU ERROR: Small APDU response."); + return 2; } // check block if (data[0] != recv[0]) { - PrintAndLog("ERROR: Block type mismatch: %02x-%02x", data[0], recv[0]); - return 3; + PrintAndLog("APDU ERROR: Block type mismatch: %02x-%02x", data[0], recv[0]); + return 2; } // CRC Check ComputeCrc14443(CRC_14443_A, recv, iLen, &first, &second); if (first || second) { - PrintAndLog("ERROR: ISO 14443A CRC error."); + PrintAndLog("APDU ERROR: ISO 14443A CRC error."); return 3; } - PrintAndLog("APDU response: %02x %02x", recv[iLen - 4], recv[iLen - 3]); // TODO add APDU descriptions - - // here TLV decoder... - if (decodeTLV) { - } - } else { - PrintAndLog("ERROR: Reply timeout."); - return 3; + PrintAndLog("APDU ERROR: Reply timeout."); + return 4; } return 0; } +int CmdHF14AAPDU(const char *cmd) { + uint8_t data[USB_CMD_DATA_SIZE]; + int datalen = 0; + bool activateField = false; + bool leaveSignalON = false; + bool decodeTLV = false; + + if (strlen(cmd) < 2) { + PrintAndLog("Usage: hf 14a apdu [-s] [-k] [-t] "); + PrintAndLog(" -s activate field and select card"); + PrintAndLog(" -k leave the signal field ON after receive response"); + PrintAndLog(" -t executes TLV decoder if it possible. TODO!!!!"); + return 0; + } + + int cmdp = 0; + while(param_getchar(cmd, cmdp) != 0x00) { + char c = param_getchar(cmd, cmdp); + if ((c == '-') && (param_getlength(cmd, cmdp) == 2)) + switch (param_getchar_indx(cmd, 1, cmdp)) { + case 's': + case 'S': + activateField = true; + break; + case 'k': + case 'K': + leaveSignalON = true; + break; + case 't': + case 'T': + decodeTLV = true; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar_indx(cmd, 1, cmdp)); + return 1; + } + + if (isxdigit(c)) { + // len = data + PCB(1b) + CRC(2b) + switch(param_gethex_to_eol(cmd, cmdp, data, sizeof(data) - 1 - 2, &datalen)) { + case 1: + PrintAndLog("Invalid HEX value."); + return 1; + case 2: + PrintAndLog("APDU too large."); + return 1; + case 3: + PrintAndLog("Hex must have even number of digits."); + return 1; + } + + // we get all the hex to end of line with spaces + break; + } + + cmdp++; + } + + PrintAndLog("--%s %s %s >>>> %s", activateField ? "sel": "", leaveSignalON ? "keep": "", decodeTLV ? "TLV": "", sprint_hex(data, datalen)); + + switch(ExchangeAPDU14a(data, datalen, activateField, leaveSignalON, data, &datalen)) { + case 0: + break; + case 1: + PrintAndLog("APDU ERROR: Send APDU error."); + return 1; + case 2: + return 2; + case 3: + return 3; + case 4: + return 4; + default: + return 5; + } + + PrintAndLog("<<<< %s", sprint_hex(data, datalen)); + + PrintAndLog("APDU response: %02x %02x - %s", data[datalen - 2], data[datalen - 1], GetAPDUCodeDescription(data[datalen - 2], data[datalen - 1])); + + // here TLV decoder... + if (decodeTLV && datalen > 4) { + TLVPrintFromBuffer(data, datalen - 2); + } + + return 0; +} + int CmdHF14ACmdRaw(const char *cmd) { UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}}; bool reply=1;