mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
gave 14b commands some serious love and overhaul. package handling for APDU and different selects is improved. return codes now consequent
This commit is contained in:
+1
-1
@@ -1429,7 +1429,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
uint8_t blockno;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
ReadSTBlock(payload->blockno);
|
||||
read_14b_st_block(payload->blockno);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO14443B_SNIFF: {
|
||||
|
||||
+1
-1
@@ -155,7 +155,7 @@ static int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response, uint16_t re
|
||||
#endif
|
||||
case 'b':
|
||||
#ifdef WITH_ISO14443b
|
||||
return iso14443b_apdu(apdu, length, false, response, respmaxlen, NULL);
|
||||
return iso14443b_apdu(apdu, length, false, response, respmaxlen, NULL, NULL);
|
||||
#else
|
||||
(void) apdu;
|
||||
(void) length;
|
||||
|
||||
+145
-122
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -35,13 +35,13 @@
|
||||
#endif
|
||||
|
||||
void iso14443b_setup(void);
|
||||
int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void *rxdata, uint16_t rxmaxlen, uint8_t *res);
|
||||
int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void *rxdata, uint16_t rxmaxlen, uint8_t *res, int * responselen);
|
||||
|
||||
int iso14443b_select_card(iso14b_card_select_t *card);
|
||||
|
||||
void SimulateIso14443bTag(const uint8_t *pupi);
|
||||
void AcquireRawAdcSamplesIso14443b(uint32_t parameter);
|
||||
void ReadSTBlock(uint8_t blocknr);
|
||||
void read_14b_st_block(uint8_t blocknr);
|
||||
void SniffIso14443b(void);
|
||||
void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]);
|
||||
void SendRawCommand14443B_Ex(iso14b_raw_cmd_t *p);
|
||||
|
||||
@@ -29,6 +29,9 @@ Check there for details about data format and how commands are interpreted on th
|
||||
device-side.
|
||||
]]
|
||||
|
||||
local PM3_SUCCESS = 0
|
||||
|
||||
-- iceman, todo: return payload from ISO14b APDU is a struct now. iso14b_raw_apdu_response_t
|
||||
local function calypso_parse(result)
|
||||
if result.Oldarg0 >= 0 then
|
||||
local len = result.Oldarg0 * 2
|
||||
@@ -112,9 +115,7 @@ end
|
||||
local function calypso_send_cmd_raw(data, ignoreresponse )
|
||||
|
||||
local flags = lib14b.ISO14B_COMMAND.ISO14B_APDU
|
||||
-- flags = lib14b.ISO14B_COMMAND.ISO14B_RAW +
|
||||
-- lib14b.ISO14B_COMMAND.ISO14B_APPEND_CRC
|
||||
local flags = lib14b.ISO14B_COMMAND.ISO14B_APDU
|
||||
|
||||
data = data or ""
|
||||
-- LEN of data, half the length of the ASCII-string hex string
|
||||
-- 2 bytes flags
|
||||
@@ -129,7 +130,7 @@ local function calypso_send_cmd_raw(data, ignoreresponse )
|
||||
local c = Command:newNG{cmd = cmds.CMD_HF_ISO14443B_COMMAND, data = senddata}
|
||||
local result, err = c:sendNG(ignoreresponse, 2000)
|
||||
if result then
|
||||
if result.Oldarg0 >= 0 then
|
||||
if result.status == PM3_SUCCESS then
|
||||
return calypso_parse(result)
|
||||
else
|
||||
err = 'card response failed'
|
||||
@@ -144,7 +145,7 @@ end
|
||||
-- writes it in the tree in decimal format.
|
||||
local function calypso_card_num(card)
|
||||
if not card then return end
|
||||
local card_num = tonumber( card.uid:sub(1,8),16 )
|
||||
local card_num = tonumber( card.uid:sub(1, 8), 16)
|
||||
print('')
|
||||
print('Card UID ' ..ansicolors.green..card.uid:format('%x')..ansicolors.reset)
|
||||
print('Card Number ' ..ansicolors.green..string.format('%u', card_num)..ansicolors.reset)
|
||||
@@ -156,7 +157,7 @@ local function calypso_apdu_status(apdu)
|
||||
-- last two is CRC
|
||||
-- next two is APDU status bytes.
|
||||
local mess = 'FAIL'
|
||||
local sw = apdu:sub( #apdu-7, #apdu-4)
|
||||
local sw = apdu:sub( #apdu - 7 , #apdu - 4)
|
||||
desc, err = iso7816.tostring(sw)
|
||||
--print ('SW', sw, desc, err )
|
||||
local status = ( sw == '9000' )
|
||||
@@ -250,7 +251,7 @@ function main(args)
|
||||
for i, apdu in spairs(_calypso_cmds) do
|
||||
print('>> '..ansicolors.yellow..i..ansicolors.reset)
|
||||
apdu = apdu:gsub('%s+', '')
|
||||
data, err = calypso_send_cmd_raw(apdu , false)
|
||||
data, err = calypso_send_cmd_raw(apdu, false)
|
||||
if err then
|
||||
print('<< '..err)
|
||||
else
|
||||
|
||||
@@ -30,6 +30,7 @@ Check there for details about data format and how commands are interpreted on th
|
||||
device-side.
|
||||
]]
|
||||
|
||||
-- iceman, todo: return payload from ISO14b APDU is a struct now. iso14b_raw_apdu_response_t
|
||||
local function mobib_parse(result)
|
||||
if result.Oldarg0 >= 0 then
|
||||
local len = result.Oldarg0 * 2
|
||||
@@ -126,7 +127,7 @@ local function mobib_send_cmd_raw(data, ignoreresponse )
|
||||
|
||||
local result, err = c:sendNG(ignoreresponse, 2000)
|
||||
if result then
|
||||
if result.Oldarg0 >= 0 then
|
||||
if result.status == PM3_SUCCESS then
|
||||
return mobib_parse(result)
|
||||
else
|
||||
err = 'card response failed'
|
||||
|
||||
+148
-169
File diff suppressed because it is too large
Load Diff
+21
-25
@@ -116,15 +116,16 @@ static bool get_14b_UID(iso14b_card_select_t *card) {
|
||||
SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)&packet, sizeof(iso14b_raw_cmd_t));
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
||||
if (resp.oldarg[0] == 0) {
|
||||
if (resp.status == PM3_SUCCESS) {
|
||||
memcpy(card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} // retry
|
||||
|
||||
if (retry <= 0)
|
||||
if (retry <= 0) {
|
||||
PrintAndLogEx(FAILED, "command execution timeout");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -148,22 +149,20 @@ static int infoHFCryptoRF(bool verbose) {
|
||||
return false;
|
||||
}
|
||||
|
||||
iso14b_card_select_t card;
|
||||
memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t));
|
||||
|
||||
uint64_t status = resp.oldarg[0];
|
||||
|
||||
switch (status) {
|
||||
case 0:
|
||||
switch (resp.status) {
|
||||
case PM3_SUCCESS: {
|
||||
iso14b_card_select_t card;
|
||||
memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, " UID : %s", sprint_hex(card.uid, card.uidlen));
|
||||
PrintAndLogEx(SUCCESS, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb)));
|
||||
PrintAndLogEx(SUCCESS, " CHIPID : %02X", card.chipid);
|
||||
return PM3_SUCCESS;
|
||||
case 2:
|
||||
}
|
||||
case PM3_ELENGTH:
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail");
|
||||
break;
|
||||
case 3:
|
||||
case PM3_ECRC:
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail");
|
||||
break;
|
||||
default:
|
||||
@@ -209,16 +208,16 @@ int readHFCryptoRF(bool loop, bool verbose) {
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
|
||||
uint8_t status = resp.oldarg[0] & 0xFF;
|
||||
|
||||
if (loop) {
|
||||
if (status != 0) {
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// when not in continuous mode
|
||||
if (status != 0) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "cryptoRF / ISO14443-b card select failed");
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(WARNING, "cryptoRF / ISO14443-b card select failed");
|
||||
}
|
||||
res = PM3_EOPABORTED;
|
||||
break;
|
||||
}
|
||||
@@ -322,11 +321,9 @@ static int CmdHFCryptoRFDump(const char *Cmd) {
|
||||
PacketResponseNG resp;
|
||||
|
||||
// select
|
||||
int status;
|
||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) {
|
||||
status = resp.oldarg[0];
|
||||
if (status < 0) {
|
||||
PrintAndLogEx(FAILED, "failed to select %" PRId64 "]", resp.oldarg[0]);
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
PrintAndLogEx(FAILED, "failed to select %" PRId64 "]", resp.status);
|
||||
free(packet);
|
||||
return switch_off_field_cryptorf();
|
||||
}
|
||||
@@ -350,13 +347,12 @@ static int CmdHFCryptoRFDump(const char *Cmd) {
|
||||
SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)&packet, sizeof(iso14b_raw_cmd_t) + 2);
|
||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) {
|
||||
|
||||
status = resp.oldarg[0];
|
||||
if (status < 0) {
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
PrintAndLogEx(FAILED, "retrying one more time");
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16_t len = (resp.oldarg[1] & 0xFFFF);
|
||||
uint16_t len = resp.length;
|
||||
uint8_t *recv = resp.data.asBytes;
|
||||
|
||||
if (check_crc(CRC_14443_B, recv, len) == false) {
|
||||
@@ -446,7 +442,7 @@ static int CmdHFCryptoRFELoad(const char *Cmd) {
|
||||
size_t datalen = CRYPTORF_MEM_SIZE;
|
||||
// set up buffer
|
||||
uint8_t *data = calloc(datalen, sizeof(uint8_t));
|
||||
if (!data) {
|
||||
if (data == NULL) {
|
||||
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
@@ -477,7 +473,7 @@ static int CmdHFCryptoRFELoad(const char *Cmd) {
|
||||
}
|
||||
*/
|
||||
free(data);
|
||||
PrintAndLogEx(SUCCESS, "sent %d bytes of data to device emulator memory", bytes_sent);
|
||||
PrintAndLogEx(SUCCESS, "sent " _YELLOW_("%d") " bytes of data to device emulator memory", bytes_sent);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
+14
-9
@@ -383,8 +383,9 @@ static int switch_off_field(void) {
|
||||
|
||||
static int findXerox(iso14b_card_select_t *card, bool disconnect) {
|
||||
|
||||
if (card == NULL)
|
||||
if (card == NULL) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
int8_t retry = 3;
|
||||
while (retry--) {
|
||||
@@ -399,10 +400,10 @@ static int findXerox(iso14b_card_select_t *card, bool disconnect) {
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
||||
|
||||
if (resp.oldarg[0] == 0) {
|
||||
if (resp.status == PM3_SUCCESS) {
|
||||
memcpy(card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t));
|
||||
}
|
||||
return resp.oldarg[0];
|
||||
return resp.length;
|
||||
}
|
||||
} // retry
|
||||
|
||||
@@ -513,7 +514,7 @@ static int CmdHFXeroxInfo(const char *Cmd) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(FAILED, "Fuji/Xerox tag select failed");
|
||||
}
|
||||
return PM3_ERFTRANS;
|
||||
return status;
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
@@ -551,7 +552,7 @@ static int CmdHFXeroxInfo(const char *Cmd) {
|
||||
*/
|
||||
|
||||
// 14b raw command send data_len instead of status
|
||||
if (/*resp.status != 0 ||*/ resp.length < 7) {
|
||||
if (resp.length < 7) {
|
||||
PrintAndLogEx(FAILED, "retrying one more time");
|
||||
continue;
|
||||
}
|
||||
@@ -655,7 +656,8 @@ static int CmdHFXeroxDump(const char *Cmd) {
|
||||
resp.cmd, resp.length, resp.magic, resp.status, resp.crc, resp.oldarg[0], resp.oldarg[1], resp.oldarg[2],
|
||||
resp.data.asBytes[0], resp.data.asBytes[1], resp.data.asBytes[2], resp.ng ? 't' : 'f');
|
||||
*/
|
||||
if (/*resp.status != 0 ||*/ resp.length < 7) { // 14b raw command send data_len instead of status
|
||||
|
||||
if (resp.length < 7) {
|
||||
PrintAndLogEx(FAILED, "retrying one more time");
|
||||
continue;
|
||||
}
|
||||
@@ -689,8 +691,9 @@ static int CmdHFXeroxDump(const char *Cmd) {
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
if (blocknum != 0x100)
|
||||
if (blocknum != 0x100) {
|
||||
PrintAndLogEx(FAILED, "dump failed at block %d", blocknum);
|
||||
}
|
||||
|
||||
if (decrypt) {
|
||||
PrintAndLogEx(INFO, "Decrypting secret blocks...");
|
||||
@@ -744,12 +747,14 @@ static int CmdHFXeroxDump(const char *Cmd) {
|
||||
uint16_t cs, csd;
|
||||
|
||||
// calc checksum
|
||||
for (b = 0, cs = 0; b < sizeof(decr) - 2; b += 2) cs += decr[b] | (decr[b + 1] << 8);
|
||||
for (b = 0, cs = 0; b < sizeof(decr) - 2; b += 2) {
|
||||
cs += decr[b] | (decr[b + 1] << 8);
|
||||
}
|
||||
cs = ~cs;
|
||||
csd = (decr[7] << 8) | decr[6];
|
||||
|
||||
if (cs != csd) {
|
||||
PrintAndLogEx(FAILED, "secret block %02X checksum failed.", dadr);
|
||||
PrintAndLogEx(FAILED, "Secret block %02X checksum " _RED_("failed"), dadr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,11 @@ typedef struct {
|
||||
uint8_t raw[];
|
||||
} PACKED iso14b_raw_cmd_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t response_byte;
|
||||
uint16_t datalen;
|
||||
uint8_t data[];
|
||||
} PACKED iso14b_raw_apdu_response_t;
|
||||
|
||||
#define US_TO_SSP(x) ( (int32_t) ((x) * 3.39) )
|
||||
#define SSP_TO_US(x) ( (int32_t)((x) / 3.39) )
|
||||
|
||||
@@ -820,6 +820,9 @@ typedef struct {
|
||||
// No PACS data pm3: when using HID SAM to retried PACS data
|
||||
#define PM3_ENOPACS -26
|
||||
|
||||
// Got wrong length error pm3: when received wrong length of data
|
||||
#define PM3_ELENGTH -27
|
||||
|
||||
// No data pm3: no data available, no host frame available (not really an error)
|
||||
#define PM3_ENODATA -98
|
||||
// Quit program client: reserved, order to quit the program
|
||||
|
||||
Reference in New Issue
Block a user