mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-07-13 08:33:16 -07:00
Cleanup arm-side reader-mode mifare classic block read/write code.
This commit is contained in:
parent
5de6fa443c
commit
edd8e36d80
10 changed files with 249 additions and 523 deletions
|
@ -821,7 +821,7 @@ int e_MifareECardLoad(uint32_t numofsectors, uint8_t keytype) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(s); blockNo++) {
|
for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(s); blockNo++) {
|
||||||
if (isOK && mifare_classic_readblock(pcs, colin_cjcuid, FirstBlockOfSector(s) + blockNo, dataoutbuf)) {
|
if (isOK && mifare_classic_readblock(pcs, FirstBlockOfSector(s) + blockNo, dataoutbuf)) {
|
||||||
isOK = false;
|
isOK = false;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
@ -838,7 +838,7 @@ int e_MifareECardLoad(uint32_t numofsectors, uint8_t keytype) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = mifare_classic_halt(pcs, colin_cjcuid);
|
int res = mifare_classic_halt(pcs);
|
||||||
(void)res;
|
(void)res;
|
||||||
|
|
||||||
crypto1_deinit(pcs);
|
crypto1_deinit(pcs);
|
||||||
|
@ -986,7 +986,7 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (mifare_classic_halt(NULL, colin_cjcuid)) {
|
if (mifare_classic_halt(NULL)) {
|
||||||
DbprintfEx(FLAG_NEWLINE, "Halt error");
|
DbprintfEx(FLAG_NEWLINE, "Halt error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
@ -1006,7 +1006,7 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (mifare_classic_halt(NULL, colin_cjcuid)) {
|
if (mifare_classic_halt(NULL)) {
|
||||||
DbprintfEx(FLAG_NEWLINE, "Halt error");
|
DbprintfEx(FLAG_NEWLINE, "Halt error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
@ -1043,7 +1043,7 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
|
||||||
};
|
};
|
||||||
|
|
||||||
if (workFlags & 0x04) {
|
if (workFlags & 0x04) {
|
||||||
if (mifare_classic_halt(NULL, colin_cjcuid)) {
|
if (mifare_classic_halt(NULL)) {
|
||||||
cjSetCursFRight();
|
cjSetCursFRight();
|
||||||
|
|
||||||
DbprintfEx(FLAG_NEWLINE, "Halt error");
|
DbprintfEx(FLAG_NEWLINE, "Halt error");
|
||||||
|
|
|
@ -109,7 +109,7 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (mifare_classic_halt(NULL, mattyrun_cuid)) {
|
if (mifare_classic_halt(NULL)) {
|
||||||
DbprintfEx(FLAG_NEWLINE, "Halt error");
|
DbprintfEx(FLAG_NEWLINE, "Halt error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
@ -129,7 +129,7 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (mifare_classic_halt(NULL, mattyrun_cuid)) {
|
if (mifare_classic_halt(NULL)) {
|
||||||
DbprintfEx(FLAG_NEWLINE, "Halt error");
|
DbprintfEx(FLAG_NEWLINE, "Halt error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
@ -165,7 +165,7 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_
|
||||||
};
|
};
|
||||||
|
|
||||||
if (workFlags & 0x04) {
|
if (workFlags & 0x04) {
|
||||||
if (mifare_classic_halt(NULL, mattyrun_cuid)) {
|
if (mifare_classic_halt(NULL)) {
|
||||||
DbprintfEx(FLAG_NEWLINE, "Halt error");
|
DbprintfEx(FLAG_NEWLINE, "Halt error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
@ -267,7 +267,7 @@ static int saMifareECardLoad(uint32_t numofsectors, uint8_t keytype) {
|
||||||
|
|
||||||
// failure to read one block, skips to next sector.
|
// failure to read one block, skips to next sector.
|
||||||
for (uint8_t blockNo = 0; blockNo < NumBlocksPerSector(s); blockNo++) {
|
for (uint8_t blockNo = 0; blockNo < NumBlocksPerSector(s); blockNo++) {
|
||||||
if (mifare_classic_readblock(pcs, mattyrun_cuid, FirstBlockOfSector(s) + blockNo, dataoutbuf)) {
|
if (mifare_classic_readblock(pcs, FirstBlockOfSector(s) + blockNo, dataoutbuf)) {
|
||||||
retval = PM3_ESOFT;
|
retval = PM3_ESOFT;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
@ -283,7 +283,7 @@ static int saMifareECardLoad(uint32_t numofsectors, uint8_t keytype) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = mifare_classic_halt(pcs, mattyrun_cuid);
|
int res = mifare_classic_halt(pcs);
|
||||||
(void)res;
|
(void)res;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
#include "ticks.h"
|
#include "ticks.h"
|
||||||
#include "commonutil.h"
|
#include "commonutil.h"
|
||||||
#include "crc16.h"
|
#include "crc16.h"
|
||||||
|
#include "protocols.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef WITH_LCD
|
#ifdef WITH_LCD
|
||||||
|
@ -1556,7 +1557,9 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
}
|
}
|
||||||
case CMD_HF_MIFARE_READBL: {
|
case CMD_HF_MIFARE_READBL: {
|
||||||
mf_readblock_t *payload = (mf_readblock_t *)packet->data.asBytes;
|
mf_readblock_t *payload = (mf_readblock_t *)packet->data.asBytes;
|
||||||
MifareReadBlock(payload->blockno, payload->keytype, payload->key);
|
uint8_t outbuf[16];
|
||||||
|
int16_t retval = mifare_cmd_readblocks(MIFARE_AUTH_KEYA + (payload->keytype & 1), payload->key, ISO14443A_CMD_READBLOCK, payload->blockno, 1, outbuf);
|
||||||
|
reply_ng(CMD_HF_MIFARE_READBL, retval, outbuf, sizeof(outbuf));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_MIFAREU_READBL: {
|
case CMD_HF_MIFAREU_READBL: {
|
||||||
|
@ -1580,7 +1583,19 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_MIFARE_WRITEBL: {
|
case CMD_HF_MIFARE_WRITEBL: {
|
||||||
MifareWriteBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
uint8_t block_no = packet->oldarg[0];
|
||||||
|
uint8_t key_type = packet->oldarg[1];
|
||||||
|
uint8_t *key = packet->data.asBytes;
|
||||||
|
uint8_t *block_data = packet->data.asBytes + 10;
|
||||||
|
|
||||||
|
int16_t retval = mifare_cmd_writeblocks(MIFARE_AUTH_KEYA + (key_type & 1), key, ISO14443A_CMD_WRITEBLOCK, block_no, 1, block_data);
|
||||||
|
|
||||||
|
// convert ng style retval to old status
|
||||||
|
if (retval >= 0) {
|
||||||
|
retval = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
reply_mix(CMD_ACK, retval, 0, 0, 0, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_MIFARE_VALUE: {
|
case CMD_HF_MIFARE_VALUE: {
|
||||||
|
@ -1740,7 +1755,9 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
uint8_t key[6];
|
uint8_t key[6];
|
||||||
} PACKED;
|
} PACKED;
|
||||||
struct p *payload = (struct p *) packet->data.asBytes;
|
struct p *payload = (struct p *) packet->data.asBytes;
|
||||||
MifareReadConfigBlockGDM(payload->key);
|
uint8_t outbuf[16];
|
||||||
|
int16_t retval = mifare_cmd_readblocks(MIFARE_MAGIC_GDM_AUTH_KEY, payload->key, MIFARE_MAGIC_GDM_READ_CFG, 0, 1, outbuf);
|
||||||
|
reply_ng(CMD_HF_MIFARE_G4_GDM_CONFIG, retval, outbuf, sizeof(outbuf));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_MIFARE_G4_GDM_WRCFG: {
|
case CMD_HF_MIFARE_G4_GDM_WRCFG: {
|
||||||
|
@ -1748,18 +1765,20 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
uint8_t data[16];
|
uint8_t data[16];
|
||||||
} PACKED;
|
} PACKED;
|
||||||
struct p *payload = (struct p *) packet->data.asBytes;
|
struct p *payload = (struct p *) packet->data.asBytes;
|
||||||
MifareWriteConfigBlockGDM(payload->data);
|
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
|
||||||
|
int16_t retval = mifare_cmd_writeblocks(MIFARE_MAGIC_GDM_AUTH_KEY, key, MIFARE_MAGIC_GDM_WRITE_CFG, 0, 1, payload->data);
|
||||||
|
reply_ng(CMD_HF_MIFARE_G4_GDM_WRCFG, retval, NULL, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_MIFARE_G4_GDM_WRBL: {
|
case CMD_HF_MIFARE_G4_GDM_WRBL: {
|
||||||
struct p {
|
struct p {
|
||||||
uint8_t blockno;
|
uint8_t blockno;
|
||||||
uint8_t keytype;
|
|
||||||
uint8_t key[6];
|
uint8_t key[6];
|
||||||
uint8_t data[16]; // data to be written
|
uint8_t data[16]; // data to be written
|
||||||
} PACKED;
|
} PACKED;
|
||||||
struct p *payload = (struct p *) packet->data.asBytes;
|
struct p *payload = (struct p *) packet->data.asBytes;
|
||||||
MifareWriteBlockGDM(payload->blockno, payload->keytype, payload->key, payload->data);
|
int16_t retval = mifare_cmd_writeblocks(MIFARE_MAGIC_GDM_AUTH_KEY, payload->key, MIFARE_MAGIC_GDM_WRITEBLOCK, payload->blockno, 1, payload->data);
|
||||||
|
reply_ng(CMD_HF_MIFARE_G4_GDM_WRBL, retval, NULL, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_MIFARE_PERSONALIZE_UID: {
|
case CMD_HF_MIFARE_PERSONALIZE_UID: {
|
||||||
|
|
|
@ -2538,7 +2538,7 @@ static int GetATQA(uint8_t *resp, uint8_t *resp_par, bool use_ecp, bool use_mags
|
||||||
|
|
||||||
bool first_try = true;
|
bool first_try = true;
|
||||||
uint32_t retry_timeout = use_ecp ? ECP_RETRY_TIMEOUT : WUPA_RETRY_TIMEOUT;
|
uint32_t retry_timeout = use_ecp ? ECP_RETRY_TIMEOUT : WUPA_RETRY_TIMEOUT;
|
||||||
uint32_t start_time = GetTickCount();
|
uint32_t start_time;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
// we may need several tries if we did send an unknown command or a wrong authentication before...
|
// we may need several tries if we did send an unknown command or a wrong authentication before...
|
||||||
|
@ -2562,6 +2562,11 @@ static int GetATQA(uint8_t *resp, uint8_t *resp_par, bool use_ecp, bool use_mags
|
||||||
// Receive the ATQA
|
// Receive the ATQA
|
||||||
len = ReaderReceive(resp, resp_par);
|
len = ReaderReceive(resp, resp_par);
|
||||||
|
|
||||||
|
// We set the start_time here otherwise in some cases we miss the window and only ever try once
|
||||||
|
if (first_try) {
|
||||||
|
start_time = GetTickCount();
|
||||||
|
}
|
||||||
|
|
||||||
first_try = false;
|
first_try = false;
|
||||||
} while (len == 0 && GetTickCountDelta(start_time) <= retry_timeout);
|
} while (len == 0 && GetTickCountDelta(start_time) <= retry_timeout);
|
||||||
|
|
||||||
|
@ -2830,10 +2835,9 @@ int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades) {
|
||||||
// which case we need to make a cascade 2 request and select - this is a long UID
|
// which case we need to make a cascade 2 request and select - this is a long UID
|
||||||
// While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
|
// While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
|
||||||
for (; sak & 0x04; cascade_level++) {
|
for (; sak & 0x04; cascade_level++) {
|
||||||
uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x20 };
|
|
||||||
uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
// SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97)
|
// SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97)
|
||||||
sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2;
|
sel_uid[0] = ISO14443A_CMD_ANTICOLL_OR_SELECT + cascade_level * 2;
|
||||||
|
|
||||||
if (cascade_level < num_cascades - 1) {
|
if (cascade_level < num_cascades - 1) {
|
||||||
uid_resp[0] = 0x88;
|
uid_resp[0] = 0x88;
|
||||||
|
|
|
@ -58,21 +58,19 @@ static uint8_t dummy_answer = 0;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Select, Authenticate, Read a MIFARE tag.
|
// Select, Authenticate, Read a MIFARE tag.
|
||||||
// read block
|
// key_auth_cmd is one of MIFARE_AUTH_KEYA, MIFARE_AUTH_KEYB, or MIFARE_MAGIC_GDM_AUTH_KEY
|
||||||
|
// read_cmd is one of ISO14443A_CMD_READBLOCK, MIFARE_MAGIC_GDM_READBLOCK, or MIFARE_MAGIC_GDM_READ_CFG
|
||||||
|
// block_data must be 16*count bytes large
|
||||||
|
// block_no through block_no+count-1 normally needs to be within the same sector
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain) {
|
int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_cmd, uint8_t block_no, uint8_t count, uint8_t *block_data) {
|
||||||
// params
|
|
||||||
uint64_t ui64Key = 0;
|
uint64_t ui64key = bytes_to_num(key, 6);
|
||||||
ui64Key = bytes_to_num(datain, 6);
|
|
||||||
|
|
||||||
// variables
|
|
||||||
uint8_t dataoutbuf[16] = {0x00};
|
|
||||||
uint8_t uid[10] = {0x00};
|
uint8_t uid[10] = {0x00};
|
||||||
uint32_t cuid = 0, status = PM3_EOPABORTED;
|
uint32_t cuid = 0;
|
||||||
|
|
||||||
struct Crypto1State mpcs = {0, 0};
|
struct Crypto1State mpcs = {0, 0};
|
||||||
struct Crypto1State *pcs;
|
struct Crypto1State *pcs = &mpcs;
|
||||||
pcs = &mpcs;
|
|
||||||
|
|
||||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||||
|
|
||||||
|
@ -83,41 +81,125 @@ void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain) {
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
LED_C_OFF();
|
LED_C_OFF();
|
||||||
|
|
||||||
while (true) {
|
int retval = PM3_SUCCESS;
|
||||||
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
|
if (iso14443a_select_card(uid, NULL, &cuid, true, 0, true) == false) {
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error");
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
|
||||||
break;
|
retval = PM3_ESOFT;
|
||||||
};
|
goto OUT;
|
||||||
|
|
||||||
if (mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) {
|
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Read block error");
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (mifare_classic_halt(pcs, cuid)) {
|
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error");
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
status = PM3_SUCCESS;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL)) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error");
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
goto OUT;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < count; i++) {
|
||||||
|
if (mifare_classic_readblock_ex(pcs, block_no + i, block_data + (i * 16), read_cmd)) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Read block error");
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
goto OUT;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mifare_classic_halt(pcs)) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error");
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
goto OUT;
|
||||||
|
};
|
||||||
|
|
||||||
|
OUT:
|
||||||
crypto1_deinit(pcs);
|
crypto1_deinit(pcs);
|
||||||
|
|
||||||
if (g_dbglevel >= 2) DbpString("READ BLOCK FINISHED");
|
|
||||||
|
|
||||||
LED_B_ON();
|
|
||||||
reply_ng(CMD_HF_MIFARE_READBL, status, dataoutbuf, 16);
|
|
||||||
LED_B_OFF();
|
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
|
set_tracing(false);
|
||||||
|
BigBuf_free();
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Select, Authenticate, Write a MIFARE tag.
|
||||||
|
// key_auth_cmd is one of MIFARE_AUTH_KEYA, MIFARE_AUTH_KEYB, or MIFARE_MAGIC_GDM_AUTH_KEY
|
||||||
|
// write_cmd is one of ISO14443A_CMD_WRITEBLOCK, MIFARE_MAGIC_GDM_WRITEBLOCK, or MIFARE_MAGIC_GDM_WRITE_CFG
|
||||||
|
// block_data must be 16*count bytes large
|
||||||
|
// block_no through block_no+count-1 normally needs to be within the same sector
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int16_t mifare_cmd_writeblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t write_cmd, uint8_t block_no, uint8_t count, uint8_t *block_data) {
|
||||||
|
|
||||||
|
uint64_t ui64key = bytes_to_num(key, 6);
|
||||||
|
|
||||||
|
uint8_t uid[10] = {0x00};
|
||||||
|
uint32_t cuid = 0;
|
||||||
|
struct Crypto1State mpcs = {0, 0};
|
||||||
|
struct Crypto1State *pcs = &mpcs;
|
||||||
|
|
||||||
|
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||||
|
|
||||||
|
clear_trace();
|
||||||
|
set_tracing(true);
|
||||||
|
|
||||||
|
LED_A_ON();
|
||||||
|
LED_B_OFF();
|
||||||
|
LED_C_OFF();
|
||||||
|
|
||||||
|
uint8_t retval = PM3_SUCCESS;
|
||||||
|
|
||||||
|
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
goto OUT;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL)) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error");
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
goto OUT;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < count; i++) {
|
||||||
|
int res = mifare_classic_writeblock_ex(pcs, block_no + i, block_data + (i * 16), write_cmd);
|
||||||
|
if (res == PM3_ETEAROFF) {
|
||||||
|
retval = PM3_ETEAROFF;
|
||||||
|
goto OUT;
|
||||||
|
} else if (res != PM3_SUCCESS) {
|
||||||
|
if (g_dbglevel >= DBG_INFO) Dbprintf("Write block error");
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
goto OUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mifare_classic_halt(pcs)) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error");
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
goto OUT;
|
||||||
|
};
|
||||||
|
|
||||||
|
OUT:
|
||||||
|
crypto1_deinit(pcs);
|
||||||
|
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
LEDsoff();
|
||||||
|
set_tracing(false);
|
||||||
|
BigBuf_free();
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Select, Authenticate, Read a MIFARE tag.
|
||||||
|
// read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes)
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void MifareReadSector(uint8_t sector_no, uint8_t key_type, uint8_t *key) {
|
||||||
|
uint8_t block_no = FirstBlockOfSector(sector_no);
|
||||||
|
uint8_t num_blocks = NumBlocksPerSector(sector_no);
|
||||||
|
|
||||||
|
uint8_t outbuf[16 * 16];
|
||||||
|
int16_t retval = mifare_cmd_readblocks(MIFARE_AUTH_KEYA + (key_type & 1), key, ISO14443A_CMD_READBLOCK, block_no, num_blocks, outbuf);
|
||||||
|
|
||||||
|
reply_old(CMD_ACK, retval == PM3_SUCCESS, 0, 0, outbuf, 16 * num_blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes) {
|
void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes) {
|
||||||
|
@ -214,131 +296,6 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MifareReadConfigBlockGDM(uint8_t *key) {
|
|
||||||
|
|
||||||
int retval = PM3_SUCCESS;
|
|
||||||
|
|
||||||
uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
|
|
||||||
if (par == NULL) {
|
|
||||||
retval = PM3_EMALLOC;
|
|
||||||
goto OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *uid = BigBuf_malloc(10);
|
|
||||||
if (uid == NULL) {
|
|
||||||
retval = PM3_EMALLOC;
|
|
||||||
goto OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
|
||||||
clear_trace();
|
|
||||||
set_tracing(true);
|
|
||||||
|
|
||||||
// variables
|
|
||||||
uint32_t cuid = 0;
|
|
||||||
struct Crypto1State mpcs = {0, 0};
|
|
||||||
struct Crypto1State *pcs;
|
|
||||||
pcs = &mpcs;
|
|
||||||
|
|
||||||
uint64_t ui64key = bytes_to_num(key, 6);
|
|
||||||
uint8_t outbuf[16] = {0x00};
|
|
||||||
|
|
||||||
if (iso14443a_select_card(uid, NULL, &cuid, true, 0, true) == false) {
|
|
||||||
retval = PM3_ESOFT;
|
|
||||||
goto OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mifare_classic_authex_2(pcs, cuid, 0, 0, ui64key, AUTH_FIRST, NULL, NULL, true)) {
|
|
||||||
retval = PM3_ESOFT;
|
|
||||||
goto OUT;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (mifare_classic_readblock_ex(pcs, cuid, 0, outbuf, MIFARE_MAGIC_GDM_READ_CFG)) {
|
|
||||||
retval = PM3_ESOFT;
|
|
||||||
goto OUT;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (mifare_classic_halt(pcs, cuid)) {
|
|
||||||
retval = PM3_ESOFT;
|
|
||||||
goto OUT;
|
|
||||||
};
|
|
||||||
|
|
||||||
OUT:
|
|
||||||
crypto1_deinit(pcs);
|
|
||||||
|
|
||||||
reply_ng(CMD_HF_MIFARE_G4_GDM_CONFIG, retval, outbuf, sizeof(outbuf));
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
LEDsoff();
|
|
||||||
set_tracing(false);
|
|
||||||
BigBuf_free();
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Select, Authenticate, Read a MIFARE tag.
|
|
||||||
// read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes)
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
|
||||||
// params
|
|
||||||
uint8_t sectorNo = arg0;
|
|
||||||
uint8_t keyType = arg1;
|
|
||||||
uint64_t ui64Key = 0;
|
|
||||||
ui64Key = bytes_to_num(datain, 6);
|
|
||||||
|
|
||||||
// variables
|
|
||||||
uint8_t isOK = 0;
|
|
||||||
uint8_t dataoutbuf[16 * 16];
|
|
||||||
uint8_t uid[10] = {0x00};
|
|
||||||
uint32_t cuid = 0;
|
|
||||||
struct Crypto1State mpcs = {0, 0};
|
|
||||||
struct Crypto1State *pcs;
|
|
||||||
pcs = &mpcs;
|
|
||||||
|
|
||||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
|
||||||
|
|
||||||
clear_trace();
|
|
||||||
set_tracing(true);
|
|
||||||
|
|
||||||
LED_A_ON();
|
|
||||||
LED_B_OFF();
|
|
||||||
LED_C_OFF();
|
|
||||||
|
|
||||||
isOK = 1;
|
|
||||||
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
|
||||||
isOK = 0;
|
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {
|
|
||||||
isOK = 0;
|
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
|
|
||||||
if (mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf + 16 * blockNo)) {
|
|
||||||
isOK = 0;
|
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mifare_classic_halt(pcs, cuid)) {
|
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_dbglevel >= 2) DbpString("READ SECTOR FINISHED");
|
|
||||||
|
|
||||||
crypto1_deinit(pcs);
|
|
||||||
|
|
||||||
LED_B_ON();
|
|
||||||
reply_old(CMD_ACK, isOK, 0, 0, dataoutbuf, 16 * NumBlocksPerSector(sectorNo));
|
|
||||||
LED_B_OFF();
|
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
LEDsoff();
|
|
||||||
set_tracing(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// arg0 = blockNo (start)
|
// arg0 = blockNo (start)
|
||||||
// arg1 = Pages (number of blocks)
|
// arg1 = Pages (number of blocks)
|
||||||
// arg2 = useKey
|
// arg2 = useKey
|
||||||
|
@ -438,210 +395,6 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
|
||||||
set_tracing(false);
|
set_tracing(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Select, Authenticate, Write a MIFARE tag.
|
|
||||||
// read block
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
|
||||||
// params
|
|
||||||
uint8_t blockNo = arg0;
|
|
||||||
uint8_t keyType = arg1;
|
|
||||||
uint64_t ui64Key = 0;
|
|
||||||
uint8_t blockdata[16] = {0x00};
|
|
||||||
|
|
||||||
ui64Key = bytes_to_num(datain, 6);
|
|
||||||
memcpy(blockdata, datain + 10, 16);
|
|
||||||
|
|
||||||
// variables
|
|
||||||
uint8_t uid[10] = {0x00};
|
|
||||||
uint32_t cuid = 0;
|
|
||||||
struct Crypto1State mpcs = {0, 0};
|
|
||||||
struct Crypto1State *pcs;
|
|
||||||
pcs = &mpcs;
|
|
||||||
|
|
||||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
|
||||||
|
|
||||||
clear_trace();
|
|
||||||
set_tracing(true);
|
|
||||||
|
|
||||||
LED_A_ON();
|
|
||||||
LED_B_OFF();
|
|
||||||
LED_C_OFF();
|
|
||||||
|
|
||||||
uint8_t retval = 0;
|
|
||||||
|
|
||||||
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
|
|
||||||
goto OUT;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
|
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error");
|
|
||||||
goto OUT;
|
|
||||||
};
|
|
||||||
|
|
||||||
int res = mifare_classic_writeblock(pcs, cuid, blockNo, blockdata);
|
|
||||||
if (res == PM3_ETEAROFF) {
|
|
||||||
retval = PM3_ETEAROFF;
|
|
||||||
goto OUT;
|
|
||||||
} else if (res != PM3_SUCCESS) {
|
|
||||||
if (g_dbglevel >= DBG_INFO) Dbprintf("Write block error");
|
|
||||||
retval = PM3_ESOFT;
|
|
||||||
goto OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mifare_classic_halt(pcs, cuid)) {
|
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error");
|
|
||||||
goto OUT;
|
|
||||||
};
|
|
||||||
|
|
||||||
retval = 1;
|
|
||||||
|
|
||||||
OUT:
|
|
||||||
crypto1_deinit(pcs);
|
|
||||||
|
|
||||||
reply_mix(CMD_ACK, retval, 0, 0, 0, 0);
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
LEDsoff();
|
|
||||||
set_tracing(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MifareWriteBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key, uint8_t *datain) {
|
|
||||||
|
|
||||||
int retval = PM3_SUCCESS;
|
|
||||||
|
|
||||||
// check args
|
|
||||||
if (datain == NULL) {
|
|
||||||
retval = PM3_EINVARG;
|
|
||||||
goto OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
|
|
||||||
if (par == NULL) {
|
|
||||||
retval = PM3_EMALLOC;
|
|
||||||
goto OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *uid = BigBuf_malloc(10);
|
|
||||||
if (uid == NULL) {
|
|
||||||
retval = PM3_EMALLOC;
|
|
||||||
goto OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
|
||||||
clear_trace();
|
|
||||||
set_tracing(true);
|
|
||||||
|
|
||||||
// variables
|
|
||||||
uint32_t cuid = 0;
|
|
||||||
struct Crypto1State mpcs = {0, 0};
|
|
||||||
struct Crypto1State *pcs;
|
|
||||||
pcs = &mpcs;
|
|
||||||
|
|
||||||
uint64_t ui64key = bytes_to_num(key, 6);
|
|
||||||
|
|
||||||
if (iso14443a_select_card(uid, NULL, &cuid, true, 0, true) == false) {
|
|
||||||
retval = PM3_ESOFT;
|
|
||||||
goto OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mifare_classic_authex_2(pcs, cuid, blockno, keytype, ui64key, AUTH_FIRST, NULL, NULL, true)) {
|
|
||||||
retval = PM3_ESOFT;
|
|
||||||
goto OUT;
|
|
||||||
};
|
|
||||||
|
|
||||||
int res = mifare_classic_writeblock_ex(pcs, cuid, blockno, datain, true);
|
|
||||||
if (res == PM3_ETEAROFF) {
|
|
||||||
retval = PM3_ETEAROFF;
|
|
||||||
goto OUT;
|
|
||||||
} else if (res != PM3_SUCCESS) {
|
|
||||||
retval = PM3_ESOFT;
|
|
||||||
goto OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mifare_classic_halt(pcs, cuid)) {
|
|
||||||
retval = PM3_ESOFT;
|
|
||||||
goto OUT;
|
|
||||||
};
|
|
||||||
|
|
||||||
OUT:
|
|
||||||
crypto1_deinit(pcs);
|
|
||||||
|
|
||||||
reply_ng(CMD_HF_MIFARE_G4_GDM_WRBL, retval, NULL, 0);
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
LEDsoff();
|
|
||||||
set_tracing(false);
|
|
||||||
BigBuf_free();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MifareWriteConfigBlockGDM(uint8_t *datain) {
|
|
||||||
|
|
||||||
int retval = PM3_SUCCESS;
|
|
||||||
|
|
||||||
// check args
|
|
||||||
if (datain == NULL) {
|
|
||||||
retval = PM3_EINVARG;
|
|
||||||
goto OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
|
|
||||||
if (par == NULL) {
|
|
||||||
retval = PM3_EMALLOC;
|
|
||||||
goto OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *uid = BigBuf_malloc(10);
|
|
||||||
if (uid == NULL) {
|
|
||||||
retval = PM3_EMALLOC;
|
|
||||||
goto OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
|
||||||
clear_trace();
|
|
||||||
set_tracing(true);
|
|
||||||
|
|
||||||
// variables
|
|
||||||
uint32_t cuid = 0;
|
|
||||||
struct Crypto1State mpcs = {0, 0};
|
|
||||||
struct Crypto1State *pcs;
|
|
||||||
pcs = &mpcs;
|
|
||||||
|
|
||||||
if (iso14443a_select_card(uid, NULL, &cuid, true, 0, true) == false) {
|
|
||||||
retval = PM3_ESOFT;
|
|
||||||
goto OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t key = 0;
|
|
||||||
if (mifare_classic_authex_2(pcs, cuid, 0, 0, key, AUTH_FIRST, NULL, NULL, true)) {
|
|
||||||
retval = PM3_ESOFT;
|
|
||||||
goto OUT;
|
|
||||||
};
|
|
||||||
|
|
||||||
int res = mifare_classic_write_cfg_block_gdm(pcs, cuid, datain);
|
|
||||||
if (res == PM3_ETEAROFF) {
|
|
||||||
retval = PM3_ETEAROFF;
|
|
||||||
goto OUT;
|
|
||||||
} else if (res) {
|
|
||||||
retval = PM3_ESOFT;
|
|
||||||
goto OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mifare_classic_halt(pcs, cuid)) {
|
|
||||||
retval = PM3_ESOFT;
|
|
||||||
goto OUT;
|
|
||||||
};
|
|
||||||
|
|
||||||
OUT:
|
|
||||||
crypto1_deinit(pcs);
|
|
||||||
|
|
||||||
reply_ng(CMD_HF_MIFARE_G4_GDM_WRCFG, retval, NULL, 0);
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
LEDsoff();
|
|
||||||
set_tracing(false);
|
|
||||||
BigBuf_free();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) {
|
void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) {
|
||||||
// params
|
// params
|
||||||
uint8_t blockNo = arg0;
|
uint8_t blockNo = arg0;
|
||||||
|
@ -688,7 +441,7 @@ void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (mifare_classic_value(pcs, cuid, blockNo, blockdata, action) != PM3_SUCCESS) {
|
if (mifare_classic_value(pcs, blockNo, blockdata, action) != PM3_SUCCESS) {
|
||||||
if (g_dbglevel >= DBG_INFO) Dbprintf("Write block error");
|
if (g_dbglevel >= DBG_INFO) Dbprintf("Write block error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
@ -708,7 +461,7 @@ void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mifare_classic_halt(pcs, cuid)) {
|
if (mifare_classic_halt(pcs)) {
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error");
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
@ -1145,7 +898,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
// nested authentication
|
// nested authentication
|
||||||
uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL);
|
uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, MIFARE_AUTH_KEYA + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL);
|
||||||
|
|
||||||
// wait for the card to become ready again
|
// wait for the card to become ready again
|
||||||
CHK_TIMEOUT();
|
CHK_TIMEOUT();
|
||||||
|
@ -1267,7 +1020,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare next select. No need to power down the card.
|
// prepare next select. No need to power down the card.
|
||||||
if (mifare_classic_halt(pcs, cuid)) {
|
if (mifare_classic_halt(pcs)) {
|
||||||
if (g_dbglevel >= DBG_INFO) Dbprintf("Nested: Halt error");
|
if (g_dbglevel >= DBG_INFO) Dbprintf("Nested: Halt error");
|
||||||
rtr--;
|
rtr--;
|
||||||
continue;
|
continue;
|
||||||
|
@ -1369,7 +1122,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare next select. No need to power down the card.
|
// prepare next select. No need to power down the card.
|
||||||
if (mifare_classic_halt(pcs, cuid)) {
|
if (mifare_classic_halt(pcs)) {
|
||||||
if (g_dbglevel >= DBG_INFO) Dbprintf("Nested: Halt error");
|
if (g_dbglevel >= DBG_INFO) Dbprintf("Nested: Halt error");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1491,7 +1244,7 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo,
|
||||||
// Main loop - get crypted nonces for target sector
|
// Main loop - get crypted nonces for target sector
|
||||||
for (uint8_t rtr = 0; rtr < 2; rtr++) {
|
for (uint8_t rtr = 0; rtr < 2; rtr++) {
|
||||||
|
|
||||||
if (mifare_classic_halt(pcs, cuid)) {
|
if (mifare_classic_halt(pcs)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1522,7 +1275,7 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo,
|
||||||
target_ks[0] = nt2 ^ target_nt[0];
|
target_ks[0] = nt2 ^ target_nt[0];
|
||||||
|
|
||||||
// second collection
|
// second collection
|
||||||
if (mifare_classic_halt(pcs, cuid)) {
|
if (mifare_classic_halt(pcs)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1618,7 +1371,7 @@ static uint8_t chkKey(struct chk_t *c) {
|
||||||
|
|
||||||
// if successful auth, send HALT
|
// if successful auth, send HALT
|
||||||
// if ( !res )
|
// if ( !res )
|
||||||
// mifare_classic_halt_ex(c->pcs);
|
// mifare_classic_halt(c->pcs);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
@ -1633,7 +1386,7 @@ static uint8_t chkKey_readb(struct chk_t *c, uint8_t *keyb) {
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
uint8_t data[16] = {0x00};
|
uint8_t data[16] = {0x00};
|
||||||
uint8_t res = mifare_classic_readblock(c->pcs, c->cuid, c->block, data);
|
uint8_t res = mifare_classic_readblock(c->pcs, c->block, data);
|
||||||
|
|
||||||
// successful read
|
// successful read
|
||||||
if (!res) {
|
if (!res) {
|
||||||
|
@ -1644,7 +1397,7 @@ static uint8_t chkKey_readb(struct chk_t *c, uint8_t *keyb) {
|
||||||
} else {
|
} else {
|
||||||
res = 3;
|
res = 3;
|
||||||
}
|
}
|
||||||
mifare_classic_halt_ex(c->pcs);
|
mifare_classic_halt(c->pcs);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -2229,7 +1982,7 @@ void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mifare_classic_halt(pcs, cuid)) {
|
if (mifare_classic_halt(pcs)) {
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error");
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2372,7 +2125,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
|
||||||
|
|
||||||
for (uint8_t r = 0; r < MAX_RETRIES; r++) {
|
for (uint8_t r = 0; r < MAX_RETRIES; r++) {
|
||||||
|
|
||||||
if (mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(s) + b, data)) {
|
if (mifare_classic_readblock(pcs, FirstBlockOfSector(s) + b, data)) {
|
||||||
retval |= PM3_EPARTIAL;
|
retval |= PM3_EPARTIAL;
|
||||||
if (g_dbglevel > DBG_ERROR) {
|
if (g_dbglevel > DBG_ERROR) {
|
||||||
Dbprintf("Error reading sector %2d block %2d", s, b);
|
Dbprintf("Error reading sector %2d block %2d", s, b);
|
||||||
|
@ -2398,7 +2151,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = mifare_classic_halt(pcs, cuid);
|
int res = mifare_classic_halt(pcs);
|
||||||
(void)res;
|
(void)res;
|
||||||
|
|
||||||
crypto1_deinit(pcs);
|
crypto1_deinit(pcs);
|
||||||
|
@ -2460,10 +2213,10 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
|
||||||
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
|
||||||
errormsg = MAGIC_UID;
|
errormsg = MAGIC_UID;
|
||||||
mifare_classic_halt_ex(NULL);
|
mifare_classic_halt(NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mifare_classic_halt_ex(NULL);
|
mifare_classic_halt(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wipe tag, fill it with zeros
|
// wipe tag, fill it with zeros
|
||||||
|
@ -2489,7 +2242,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
|
||||||
}
|
}
|
||||||
iso14a_set_timeout(old_timeout);
|
iso14a_set_timeout(old_timeout);
|
||||||
|
|
||||||
mifare_classic_halt_ex(NULL);
|
mifare_classic_halt(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// write block
|
// write block
|
||||||
|
@ -2528,7 +2281,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (workFlags & MAGIC_HALT)
|
if (workFlags & MAGIC_HALT)
|
||||||
mifare_classic_halt_ex(NULL);
|
mifare_classic_halt(NULL);
|
||||||
|
|
||||||
isOK = true;
|
isOK = true;
|
||||||
break;
|
break;
|
||||||
|
@ -2600,7 +2353,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
|
||||||
|
|
||||||
// send HALT
|
// send HALT
|
||||||
if (workFlags & MAGIC_HALT)
|
if (workFlags & MAGIC_HALT)
|
||||||
mifare_classic_halt_ex(NULL);
|
mifare_classic_halt(NULL);
|
||||||
|
|
||||||
isOK = true;
|
isOK = true;
|
||||||
break;
|
break;
|
||||||
|
@ -2628,7 +2381,7 @@ void MifareCIdent(bool is_mfc) {
|
||||||
uint8_t rats[4] = {ISO14443A_CMD_RATS, 0x80, 0x31, 0x73};
|
uint8_t rats[4] = {ISO14443A_CMD_RATS, 0x80, 0x31, 0x73};
|
||||||
uint8_t rdblf0[4] = {ISO14443A_CMD_READBLOCK, 0xF0, 0x8D, 0x5f};
|
uint8_t rdblf0[4] = {ISO14443A_CMD_READBLOCK, 0xF0, 0x8D, 0x5f};
|
||||||
uint8_t rdbl00[4] = {ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa8};
|
uint8_t rdbl00[4] = {ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa8};
|
||||||
uint8_t gen4gmd[4] = {MIFARE_MAGIC_GDM_AUTH_KEY, 0x00, 0x6C, 0x92};
|
uint8_t gen4gdm[4] = {MIFARE_MAGIC_GDM_AUTH_KEY, 0x00, 0x6C, 0x92};
|
||||||
uint8_t gen4GetConf[8] = {GEN_4GTU_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4GTU_GETCNF, 0, 0};
|
uint8_t gen4GetConf[8] = {GEN_4GTU_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4GTU_GETCNF, 0, 0};
|
||||||
uint8_t superGen1[9] = {0x0A, 0x00, 0x00, 0xA6, 0xB0, 0x00, 0x10, 0x14, 0x1D};
|
uint8_t superGen1[9] = {0x0A, 0x00, 0x00, 0xA6, 0xB0, 0x00, 0x10, 0x14, 0x1D};
|
||||||
|
|
||||||
|
@ -2782,7 +2535,7 @@ void MifareCIdent(bool is_mfc) {
|
||||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||||
if (res == 2) {
|
if (res == 2) {
|
||||||
ReaderTransmit(gen4gmd, sizeof(gen4gmd), NULL);
|
ReaderTransmit(gen4gdm, sizeof(gen4gdm), NULL);
|
||||||
res = ReaderReceive(buf, par);
|
res = ReaderReceive(buf, par);
|
||||||
if (res == 4) {
|
if (res == 4) {
|
||||||
isGen = MAGIC_GEN_4GDM;
|
isGen = MAGIC_GEN_4GDM;
|
||||||
|
@ -3227,12 +2980,12 @@ void MifareSetMod(uint8_t *datain) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int respLen;
|
int respLen;
|
||||||
if (((respLen = mifare_sendcmd_short(pcs, CRYPT_ALL, 0x43, mod, receivedAnswer, receivedAnswerPar, NULL)) != 1) || (receivedAnswer[0] != 0x0a)) {
|
if (((respLen = mifare_sendcmd_short(pcs, CRYPT_ALL, MIFARE_EV1_SETMOD, mod, receivedAnswer, receivedAnswerPar, NULL)) != 1) || (receivedAnswer[0] != 0x0a)) {
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("SetMod error; response[0]: %hhX, len: %d", receivedAnswer[0], respLen);
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("SetMod error; response[0]: %hhX, len: %d", receivedAnswer[0], respLen);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mifare_classic_halt(pcs, cuid)) {
|
if (mifare_classic_halt(pcs)) {
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error");
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,19 +19,18 @@
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain);
|
int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_cmd, uint8_t block_no, uint8_t count, uint8_t *block_data);
|
||||||
|
int16_t mifare_cmd_writeblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t write_cmd, uint8_t block_no, uint8_t count, uint8_t *block_data);
|
||||||
|
void MifareReadSector(uint8_t sector_no, uint8_t key_type, uint8_t *key);
|
||||||
|
void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
||||||
|
|
||||||
void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||||
void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes);
|
void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes);
|
||||||
void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
|
void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
|
||||||
void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
|
||||||
void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
|
||||||
void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
|
||||||
void MifareUWriteBlockCompat(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
void MifareUWriteBlockCompat(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||||
|
|
||||||
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||||
void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, bool calibrate, uint8_t *key);
|
|
||||||
|
|
||||||
|
void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, bool calibrate, uint8_t *key);
|
||||||
void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, uint8_t *key);
|
void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, uint8_t *key);
|
||||||
|
|
||||||
void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
|
void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
|
||||||
|
@ -58,11 +57,6 @@ void MifareGen3UID(uint8_t uidlen, uint8_t *uid); // Gen 3 magic card set UID wi
|
||||||
void MifareGen3Blk(uint8_t block_len, uint8_t *block); // Gen 3 magic card overwrite manufacturer block
|
void MifareGen3Blk(uint8_t block_len, uint8_t *block); // Gen 3 magic card overwrite manufacturer block
|
||||||
void MifareGen3Freez(void); // Gen 3 magic card lock further UID changes
|
void MifareGen3Freez(void); // Gen 3 magic card lock further UID changes
|
||||||
|
|
||||||
// MFC GEN4 GDM
|
|
||||||
void MifareReadConfigBlockGDM(uint8_t *key);
|
|
||||||
void MifareWriteConfigBlockGDM(uint8_t *datain);
|
|
||||||
void MifareWriteBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key, uint8_t *datain);
|
|
||||||
|
|
||||||
// MFC GEN4 GTU
|
// MFC GEN4 GTU
|
||||||
void MifareG4ReadBlk(uint8_t blockno, uint8_t *pwd, uint8_t workFlags);
|
void MifareG4ReadBlk(uint8_t blockno, uint8_t *pwd, uint8_t workFlags);
|
||||||
void MifareG4WriteBlk(uint8_t blockno, uint8_t *pwd, uint8_t *data, uint8_t workFlags);
|
void MifareG4WriteBlk(uint8_t blockno, uint8_t *pwd, uint8_t *data, uint8_t workFlags);
|
||||||
|
|
|
@ -139,9 +139,9 @@ int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo,
|
||||||
return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL);
|
return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL);
|
||||||
}
|
}
|
||||||
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) {
|
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) {
|
||||||
return mifare_classic_authex_2(pcs, uid, blockNo, keyType, ui64Key, isNested, ntptr, timing, false);
|
return mifare_classic_authex_cmd(pcs, uid, blockNo, keyType ? MIFARE_AUTH_KEYA : MIFARE_AUTH_KEYB, ui64Key, isNested, ntptr, timing);
|
||||||
}
|
}
|
||||||
int mifare_classic_authex_2(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing, bool is_gdm) {
|
int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) {
|
||||||
|
|
||||||
// "random" reader nonce:
|
// "random" reader nonce:
|
||||||
uint8_t nr[4];
|
uint8_t nr[4];
|
||||||
|
@ -150,9 +150,8 @@ int mifare_classic_authex_2(struct Crypto1State *pcs, uint32_t uid, uint8_t bloc
|
||||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
||||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
||||||
|
|
||||||
// Transmit MIFARE_CLASSIC_AUTH 0x60, 0x61 or GDM 0x80
|
// Transmit MIFARE_CLASSIC_AUTH, 0x60 for key A, 0x61 for key B, or 0x80 for GDM backdoor
|
||||||
uint8_t cmdbyte = (is_gdm) ? MIFARE_MAGIC_GDM_AUTH_KEY : MIFARE_AUTH_KEYA + (keyType & 0x01);
|
int len = mifare_sendcmd_short(pcs, isNested, cmd, blockNo, receivedAnswer, receivedAnswerPar, timing);
|
||||||
int len = mifare_sendcmd_short(pcs, isNested, cmdbyte, blockNo, receivedAnswer, receivedAnswerPar, timing);
|
|
||||||
if (len != 4) return 1;
|
if (len != 4) return 1;
|
||||||
|
|
||||||
// Save the tag nonce (nt)
|
// Save the tag nonce (nt)
|
||||||
|
@ -229,10 +228,10 @@ int mifare_classic_authex_2(struct Crypto1State *pcs, uint32_t uid, uint8_t bloc
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) {
|
int mifare_classic_readblock(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData) {
|
||||||
return mifare_classic_readblock_ex(pcs, uid, blockNo, blockData, ISO14443A_CMD_READBLOCK);
|
return mifare_classic_readblock_ex(pcs, blockNo, blockData, ISO14443A_CMD_READBLOCK);
|
||||||
}
|
}
|
||||||
int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t iso_byte) {
|
int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t iso_byte) {
|
||||||
|
|
||||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
||||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
||||||
|
@ -415,22 +414,18 @@ int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) {
|
int mifare_classic_writeblock(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData) {
|
||||||
return mifare_classic_writeblock_ex(pcs, uid, blockNo, blockData, false);
|
return mifare_classic_writeblock_ex(pcs, blockNo, blockData, ISO14443A_CMD_WRITEBLOCK);
|
||||||
}
|
}
|
||||||
int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, bool is_gdm) {
|
int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t cmd) {
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
||||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
||||||
|
|
||||||
// command MIFARE_MAGIC_GDM_WRITEBLOCK
|
// cmd is ISO14443A_CMD_WRITEBLOCK for normal tags, but could also be
|
||||||
uint16_t len;
|
// MIFARE_MAGIC_GDM_WRITEBLOCK or MIFARE_MAGIC_GDM_WRITE_CFG for certain magic tags
|
||||||
if (is_gdm) {
|
uint16_t len = mifare_sendcmd_short(pcs, 1, cmd, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
len = mifare_sendcmd_short(pcs, 1, MIFARE_MAGIC_GDM_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
|
||||||
} else {
|
|
||||||
len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
||||||
if (g_dbglevel >= DBG_INFO) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
if (g_dbglevel >= DBG_INFO) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||||
|
@ -441,15 +436,19 @@ int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t
|
||||||
memcpy(d_block, blockData, 16);
|
memcpy(d_block, blockData, 16);
|
||||||
AddCrc14A(d_block, 16);
|
AddCrc14A(d_block, 16);
|
||||||
|
|
||||||
// enough for 18 Bytes to send
|
if (pcs) {
|
||||||
uint8_t par[3] = {0x00, 0x00, 0x00};
|
// enough for 18 Bytes to send
|
||||||
// crypto
|
uint8_t par[3] = {0x00, 0x00, 0x00};
|
||||||
for (uint32_t pos = 0; pos < 18; pos++) {
|
// crypto
|
||||||
d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos];
|
for (uint32_t pos = 0; pos < 18; pos++) {
|
||||||
par[pos >> 3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos & 0x0007)));
|
d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos];
|
||||||
}
|
par[pos >> 3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos & 0x0007)));
|
||||||
|
}
|
||||||
|
|
||||||
ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL);
|
ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL);
|
||||||
|
} else {
|
||||||
|
ReaderTransmit(d_block, sizeof(d_block), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
// tearoff occurred
|
// tearoff occurred
|
||||||
if (tearoff_hook() == PM3_ETEAROFF) {
|
if (tearoff_hook() == PM3_ETEAROFF) {
|
||||||
|
@ -459,10 +458,14 @@ int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t
|
||||||
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
||||||
|
|
||||||
uint8_t res = 0;
|
uint8_t res = 0;
|
||||||
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 0)) << 0;
|
if (pcs) {
|
||||||
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 1)) << 1;
|
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 0)) << 0;
|
||||||
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 2)) << 2;
|
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 1)) << 1;
|
||||||
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3;
|
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 2)) << 2;
|
||||||
|
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3;
|
||||||
|
} else {
|
||||||
|
res = receivedAnswer[0];
|
||||||
|
}
|
||||||
|
|
||||||
if ((len != 1) || (res != 0x0A)) {
|
if ((len != 1) || (res != 0x0A)) {
|
||||||
if (g_dbglevel >= DBG_INFO) Dbprintf("Cmd send data2 Error: %02x", res);
|
if (g_dbglevel >= DBG_INFO) Dbprintf("Cmd send data2 Error: %02x", res);
|
||||||
|
@ -472,52 +475,7 @@ int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mifare_classic_write_cfg_block_gdm(struct Crypto1State *pcs, uint32_t uid, uint8_t *blockData) {
|
int mifare_classic_value(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t action) {
|
||||||
|
|
||||||
// variables
|
|
||||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
|
||||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
|
||||||
|
|
||||||
uint16_t len = mifare_sendcmd_short(pcs, 1, MIFARE_MAGIC_GDM_WRITE_CFG, 0, receivedAnswer, receivedAnswerPar, NULL);
|
|
||||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) {
|
|
||||||
return PM3_EFAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t d_block[18], d_block_enc[18];
|
|
||||||
memcpy(d_block, blockData, 16);
|
|
||||||
AddCrc14A(d_block, 16);
|
|
||||||
|
|
||||||
// enough for 18 Bytes to send
|
|
||||||
uint8_t par[3] = {0x00, 0x00, 0x00};
|
|
||||||
// crypto
|
|
||||||
for (uint32_t pos = 0; pos < 18; pos++) {
|
|
||||||
d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos];
|
|
||||||
par[pos >> 3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos & 0x0007)));
|
|
||||||
}
|
|
||||||
|
|
||||||
ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL);
|
|
||||||
|
|
||||||
// tearoff occurred
|
|
||||||
if (tearoff_hook() == PM3_ETEAROFF) {
|
|
||||||
return PM3_ETEAROFF;
|
|
||||||
} else {
|
|
||||||
// Receive the response
|
|
||||||
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
|
||||||
|
|
||||||
uint8_t res = 0;
|
|
||||||
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 0)) << 0;
|
|
||||||
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 1)) << 1;
|
|
||||||
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 2)) << 2;
|
|
||||||
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3;
|
|
||||||
|
|
||||||
if ((len != 1) || (res != 0x0A)) {
|
|
||||||
return PM3_EFAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mifare_classic_value(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t action) {
|
|
||||||
// variables
|
// variables
|
||||||
uint16_t len = 0;
|
uint16_t len = 0;
|
||||||
uint32_t pos = 0;
|
uint32_t pos = 0;
|
||||||
|
@ -625,7 +583,8 @@ int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) {
|
||||||
}
|
}
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
int mifare_classic_halt_ex(struct Crypto1State *pcs) {
|
|
||||||
|
int mifare_classic_halt(struct Crypto1State *pcs) {
|
||||||
uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00};
|
uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00};
|
||||||
uint16_t len = mifare_sendcmd_short(pcs, (pcs == NULL) ? CRYPT_NONE : CRYPT_ALL, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL);
|
uint16_t len = mifare_sendcmd_short(pcs, (pcs == NULL) ? CRYPT_NONE : CRYPT_ALL, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL);
|
||||||
if (len != 0) {
|
if (len != 0) {
|
||||||
|
@ -634,19 +593,9 @@ int mifare_classic_halt_ex(struct Crypto1State *pcs) {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) {
|
|
||||||
return mifare_classic_halt_ex(pcs);
|
|
||||||
}
|
|
||||||
|
|
||||||
int mifare_ultra_halt(void) {
|
int mifare_ultra_halt(void) {
|
||||||
uint16_t len = 0;
|
return mifare_classic_halt(NULL);
|
||||||
uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00};
|
|
||||||
len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL);
|
|
||||||
if (len != 0) {
|
|
||||||
if (g_dbglevel >= DBG_EXTENDED) Dbprintf("halt warning. response len: %x", len);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -72,17 +72,15 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t
|
||||||
// mifare classic
|
// mifare classic
|
||||||
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested);
|
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested);
|
||||||
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing);
|
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing);
|
||||||
int mifare_classic_authex_2(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing, bool is_gdm);
|
int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing);
|
||||||
|
|
||||||
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
int mifare_classic_readblock(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData);
|
||||||
int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t iso_byte);
|
int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t iso_byte);
|
||||||
|
|
||||||
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid);
|
int mifare_classic_halt(struct Crypto1State *pcs);
|
||||||
int mifare_classic_halt_ex(struct Crypto1State *pcs);
|
int mifare_classic_writeblock(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData);
|
||||||
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t cmd);
|
||||||
int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, bool is_gdm);
|
int mifare_classic_value(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t action);
|
||||||
int mifare_classic_value(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t action);
|
|
||||||
int mifare_classic_write_cfg_block_gdm(struct Crypto1State *pcs, uint32_t uid, uint8_t *blockData);
|
|
||||||
|
|
||||||
// Ultralight/NTAG...
|
// Ultralight/NTAG...
|
||||||
int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack);
|
int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack);
|
||||||
|
|
|
@ -910,11 +910,19 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||||
uint8_t crcc = iso14443A_CRC_check(hdr->isResponse, mfData, mfDataLen);
|
uint8_t crcc = iso14443A_CRC_check(hdr->isResponse, mfData, mfDataLen);
|
||||||
|
|
||||||
//iceman: colorise crc bytes here will need a refactor of code from above.
|
//iceman: colorise crc bytes here will need a refactor of code from above.
|
||||||
PrintAndLogEx(NORMAL, " | | * |%-*s | %-4s| %s",
|
if (hdr->isResponse) {
|
||||||
str_padder,
|
PrintAndLogEx(NORMAL, " | | * |%-*s | %-4s| %s",
|
||||||
sprint_hex_inrow_spaces(mfData, mfDataLen, 2),
|
str_padder,
|
||||||
(crcc == 0 ? _RED_(" !! ") : (crcc == 1 ? _GREEN_(" ok ") : " ")),
|
sprint_hex_inrow_spaces(mfData, mfDataLen, 2),
|
||||||
explanation);
|
(crcc == 0 ? _RED_(" !! ") : (crcc == 1 ? _GREEN_(" ok ") : " ")),
|
||||||
|
explanation);
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(NORMAL, " | | * |" _YELLOW_("%-*s")" | " _YELLOW_("%s") "| " _YELLOW_("%s"),
|
||||||
|
str_padder,
|
||||||
|
sprint_hex_inrow_spaces(mfData, mfDataLen, 2),
|
||||||
|
(crcc == 0 ? _RED_(" !! ") : (crcc == 1 ? _GREEN_(" ok ") : " ")),
|
||||||
|
explanation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -191,12 +191,13 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
||||||
#define MIFARE_CMD_TRANSFER 0xB0
|
#define MIFARE_CMD_TRANSFER 0xB0
|
||||||
|
|
||||||
#define MIFARE_MAGIC_GDM_AUTH_KEY 0x80
|
#define MIFARE_MAGIC_GDM_AUTH_KEY 0x80
|
||||||
|
#define MIFARE_MAGIC_GDM_READBLOCK 0x38
|
||||||
#define MIFARE_MAGIC_GDM_WRITEBLOCK 0xA8
|
#define MIFARE_MAGIC_GDM_WRITEBLOCK 0xA8
|
||||||
#define MIFARE_MAGIC_GDM_READ_CFG 0xE0
|
#define MIFARE_MAGIC_GDM_READ_CFG 0xE0
|
||||||
#define MIFARE_MAGIC_GDM_WRITE_CFG 0xE1
|
#define MIFARE_MAGIC_GDM_WRITE_CFG 0xE1
|
||||||
|
|
||||||
#define MIFARE_EV1_PERSONAL_UID 0x40
|
#define MIFARE_EV1_PERSONAL_UID 0x40
|
||||||
#define MIFARE_EV1_SETMODE 0x43
|
#define MIFARE_EV1_SETMOD 0x43
|
||||||
#define MIFARE_EV1_UIDF0 0x00
|
#define MIFARE_EV1_UIDF0 0x00
|
||||||
#define MIFARE_EV1_UIDF1 0x40
|
#define MIFARE_EV1_UIDF1 0x40
|
||||||
#define MIFARE_EV1_UIDF2 0x20
|
#define MIFARE_EV1_UIDF2 0x20
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue