fiddled with pm3 client informative text

This commit is contained in:
iceman1001 2025-03-22 13:09:55 +01:00
commit c0af6cd7d2
6 changed files with 248 additions and 164 deletions

View file

@ -79,21 +79,24 @@ static bool mifare_wakeup_auth(struct Crypto1State *pcs, MifareWakeupType wakeup
LED_C_OFF(); LED_C_OFF();
switch (wakeup) { switch (wakeup) {
case MF_WAKE_NONE: case MF_WAKE_NONE: {
break; break;
case MF_WAKE_WUPA: }
if (!iso14443a_select_cardEx(NULL, NULL, &cuid, true, 0, true, &WUPA_POLLING_PARAMETERS)) { case MF_WAKE_WUPA: {
if (iso14443a_select_cardEx(NULL, NULL, &cuid, true, 0, true, &WUPA_POLLING_PARAMETERS) == 0) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
return false; return false;
}; };
break; break;
case MF_WAKE_REQA: }
if (!iso14443a_select_cardEx(NULL, NULL, &cuid, true, 0, true, &REQA_POLLING_PARAMETERS)) { case MF_WAKE_REQA: {
if (iso14443a_select_cardEx(NULL, NULL, &cuid, true, 0, true, &REQA_POLLING_PARAMETERS) == 0) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
return false; return false;
}; };
break; break;
case MF_WAKE_GEN1A: }
case MF_WAKE_GEN1A: {
ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); ReaderTransmitBitsPar(wupC1, 7, NULL, NULL);
if ((ReaderReceive(receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar) == 0) || (receivedAnswer[0] != 0x0a)) { if ((ReaderReceive(receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar) == 0) || (receivedAnswer[0] != 0x0a)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("wupC1 error"); if (g_dbglevel >= DBG_ERROR) Dbprintf("wupC1 error");
@ -105,14 +108,16 @@ static bool mifare_wakeup_auth(struct Crypto1State *pcs, MifareWakeupType wakeup
if (g_dbglevel >= DBG_INFO) Dbprintf("Assuming Magic Gen 1B tag. [wupC2 failed]"); if (g_dbglevel >= DBG_INFO) Dbprintf("Assuming Magic Gen 1B tag. [wupC2 failed]");
} }
break; break;
case MF_WAKE_GEN1B: }
case MF_WAKE_GEN1B: {
ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); ReaderTransmitBitsPar(wupC1, 7, NULL, NULL);
if ((ReaderReceive(receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar) == 0) || (receivedAnswer[0] != 0x0a)) { if ((ReaderReceive(receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar) == 0) || (receivedAnswer[0] != 0x0a)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("wupC1 error"); if (g_dbglevel >= DBG_ERROR) Dbprintf("wupC1 error");
return false; return false;
} }
break; break;
case MF_WAKE_GDM_ALT: }
case MF_WAKE_GDM_ALT: {
ReaderTransmitBitsPar(wupGDM1, 7, NULL, NULL); ReaderTransmitBitsPar(wupGDM1, 7, NULL, NULL);
if ((ReaderReceive(receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar) == 0) || (receivedAnswer[0] != 0x0a)) { if ((ReaderReceive(receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar) == 0) || (receivedAnswer[0] != 0x0a)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("wupGDM1 error"); if (g_dbglevel >= DBG_ERROR) Dbprintf("wupGDM1 error");
@ -125,6 +130,7 @@ static bool mifare_wakeup_auth(struct Crypto1State *pcs, MifareWakeupType wakeup
} }
break; break;
} }
}
if (key_auth_cmd != 0) { if (key_auth_cmd != 0) {
uint64_t ui64key = bytes_to_num(key, 6); uint64_t ui64key = bytes_to_num(key, 6);
@ -158,9 +164,9 @@ int16_t mifare_cmd_readblocks(MifareWakeupType wakeup, uint8_t key_auth_cmd, uin
goto OUT; goto OUT;
} }
// frame waiting time (FWT) in 1/fc // frame waiting time (FWT) in 1/fc (524288)
uint32_t fwt = 256 * 16 * (1 << 7); uint32_t fwt = 256 * 16 * (1 << 7);
iso14a_set_timeout(fwt / (8 * 16)); iso14a_set_timeout(fwt / (8 * 16)); // 4096
for (uint8_t i = 0; i < count; i++) { for (uint8_t i = 0; i < count; i++) {
if (mifare_classic_readblock_ex(pcs, block_no + i, block_data + (i * 16), read_cmd)) { if (mifare_classic_readblock_ex(pcs, block_no + i, block_data + (i * 16), read_cmd)) {
@ -262,7 +268,7 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes) {
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { if (iso14443a_select_card(NULL, NULL, NULL, true, 0, true) == 0) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
OnError(0); OnError(0);
return; return;
@ -292,7 +298,7 @@ void MifareUL_AES_Auth(bool turn_off_field, uint8_t keyno, uint8_t *keybytes) {
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { if (iso14443a_select_card(NULL, NULL, NULL, true, 0, true) == 0) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
OnErrorNG(CMD_HF_MIFAREULAES_AUTH, PM3_ESOFT); OnErrorNG(CMD_HF_MIFAREULAES_AUTH, PM3_ESOFT);
return; return;
@ -327,9 +333,8 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true); if (iso14443a_select_card(NULL, NULL, NULL, true, 0, true) == 0) {
if (!len) { if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card (RC:%02X)", len);
OnError(1); OnError(1);
return; return;
} }
@ -401,8 +406,8 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
} }
int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true); int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true);
if (!len) { if (len == 0) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card (RC:%d)", len); if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
OnError(1); OnError(1);
return; return;
} }
@ -412,7 +417,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
uint8_t key[16] = {0x00}; uint8_t key[16] = {0x00};
memcpy(key, datain, sizeof(key)); memcpy(key, datain, sizeof(key));
if (!mifare_ultra_auth(key)) { if (mifare_ultra_auth(key) == 0) {
OnError(1); OnError(1);
return; return;
} }
@ -424,7 +429,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
memcpy(pwd, datain, sizeof(pwd)); memcpy(pwd, datain, sizeof(pwd));
uint8_t pack[4] = {0, 0, 0, 0}; uint8_t pack[4] = {0, 0, 0, 0};
if (!mifare_ul_ev1_auth(pwd, pack)) { if (mifare_ul_ev1_auth(pwd, pack) == 0) {
OnError(1); OnError(1);
return; return;
} }
@ -507,7 +512,8 @@ void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) {
LED_C_OFF(); LED_C_OFF();
while (true) { while (true) {
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
if (iso14443a_select_card(uid, NULL, &cuid, true, 0, true) == 0) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
break; break;
}; };
@ -578,7 +584,7 @@ static void MifareUWriteBlockEx(uint8_t arg0, uint8_t arg1, uint8_t *datain, boo
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { if (iso14443a_select_card(NULL, NULL, NULL, true, 0, true) == 0) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
OnError(0); OnError(0);
return; return;
@ -589,7 +595,7 @@ static void MifareUWriteBlockEx(uint8_t arg0, uint8_t arg1, uint8_t *datain, boo
uint8_t key[16] = {0x00}; uint8_t key[16] = {0x00};
memcpy(key, datain + 4, sizeof(key)); memcpy(key, datain + 4, sizeof(key));
if (!mifare_ultra_auth(key)) { if (mifare_ultra_auth(key) == 0) {
OnError(1); OnError(1);
return; return;
} }
@ -600,7 +606,7 @@ static void MifareUWriteBlockEx(uint8_t arg0, uint8_t arg1, uint8_t *datain, boo
uint8_t pwd[4] = {0x00}; uint8_t pwd[4] = {0x00};
memcpy(pwd, datain + 4, 4); memcpy(pwd, datain + 4, 4);
uint8_t pack[4] = {0, 0, 0, 0}; uint8_t pack[4] = {0, 0, 0, 0};
if (!mifare_ul_ev1_auth(pwd, pack)) { if (mifare_ul_ev1_auth(pwd, pack) == 0) {
OnError(1); OnError(1);
return; return;
} }
@ -620,8 +626,9 @@ static void MifareUWriteBlockEx(uint8_t arg0, uint8_t arg1, uint8_t *datain, boo
if (g_dbglevel >= 2) DbpString("WRITE BLOCK FINISHED"); if (g_dbglevel >= 2) DbpString("WRITE BLOCK FINISHED");
if (reply) if (reply) {
reply_mix(CMD_ACK, 1, 0, 0, 0, 0); reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();
set_tracing(false); set_tracing(false);
@ -652,7 +659,7 @@ void MifareUWriteBlockCompat(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { if (iso14443a_select_card(NULL, NULL, NULL, true, 0, true) == 0) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
OnError(0); OnError(0);
return; return;
@ -663,7 +670,7 @@ void MifareUWriteBlockCompat(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
uint8_t key[16] = {0x00}; uint8_t key[16] = {0x00};
memcpy(key, datain + 16, sizeof(key)); memcpy(key, datain + 16, sizeof(key));
if (!mifare_ultra_auth(key)) { if (mifare_ultra_auth(key) == 0) {
OnError(1); OnError(1);
return; return;
} }
@ -715,7 +722,7 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain) {
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { if (iso14443a_select_card(NULL, NULL, NULL, true, 0, true) == 0) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
OnError(0); OnError(0);
return; return;
@ -805,8 +812,9 @@ void MifareAcquireNonces(uint32_t arg0, uint32_t flags) {
BigBuf_Clear_ext(false); BigBuf_Clear_ext(false);
set_tracing(true); set_tracing(true);
if (initialize) if (initialize) {
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
}
LED_C_ON(); LED_C_ON();
@ -918,8 +926,9 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
BigBuf_Clear_ext(false); BigBuf_Clear_ext(false);
set_tracing(false); set_tracing(false);
if (initialize) if (initialize) {
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
}
LED_C_ON(); LED_C_ON();
@ -1730,16 +1739,18 @@ typedef struct chk_t {
// fast select, tries 5 times to select // fast select, tries 5 times to select
// //
// return: // return:
// 2 = failed to select. // 4 = failed to select
// 1 = wrong key // 3 = failed auth
// 0 = correct key // 2 = timeout
// 1 = failed auth
// 0 = correct
static uint8_t chkKey(struct chk_t *c) { static uint8_t chkKey(struct chk_t *c) {
uint8_t i = 0, res = 2; uint8_t i = 0, res = 2;
bool selected = false; bool selected = false;
while (i < 5) { while (i < 5) {
// this part is from Piwi's faster nonce collecting part in Hardnested. // this part is from Piwi's faster nonce collecting part in Hardnested.
// assume: fast select // assume: fast select
if (!iso14443a_fast_select_card(c->uid, c->cl)) { if (iso14443a_fast_select_card(c->uid, c->cl) == 0) {
++i; ++i;
continue; continue;
} }
@ -1755,27 +1766,29 @@ static uint8_t chkKey(struct chk_t *c) {
} }
if (selected == false) { if (selected == false) {
Dbprintf("chkKey: Failed at fast selecting the card!"); Dbprintf("chkKey: Failed at fast selecting the card!");
res = 4;
} }
return res; return res;
} }
static uint8_t chkKey_readb(struct chk_t *c, uint8_t *keyb) { static uint8_t chkKey_readb(struct chk_t *c, uint8_t *keyb) {
if (!iso14443a_fast_select_card(c->uid, c->cl)) if (iso14443a_fast_select_card(c->uid, c->cl) == 0) {
return 2; return 2;
}
if (mifare_classic_authex(c->pcs, c->cuid, c->block, 0, c->key, AUTH_FIRST, NULL, NULL)) if (mifare_classic_authex(c->pcs, c->cuid, c->block, 0, c->key, AUTH_FIRST, NULL, NULL)) {
return 1; return 1;
}
uint8_t data[16] = {0x00}; uint8_t data[16] = {0x00};
uint8_t res = mifare_classic_readblock(c->pcs, c->block, data); uint8_t res = mifare_classic_readblock(c->pcs, c->block, data);
// successful read // successful read
if (!res) { if (res == 0) {
// data was something else than zeros. // data was something else than zeros.
if (memcmp(data + 10, "\x00\x00\x00\x00\x00\x00", 6) != 0) { if (memcmp(data + 10, "\x00\x00\x00\x00\x00\x00", 6) != 0) {
memcpy(keyb, data + 10, 6); memcpy(keyb, data + 10, 6);
res = 0;
} else { } else {
res = 3; res = 3;
} }
@ -1788,11 +1801,19 @@ static void chkKey_scanA(struct chk_t *c, struct sector_t *k_sector, uint8_t *fo
for (uint8_t s = 0; s < *sectorcnt; s++) { for (uint8_t s = 0; s < *sectorcnt; s++) {
// skip already found A keys // skip already found A keys
if (found[(s * 2)]) if (found[(s * 2)]) {
continue; continue;
}
c->block = FirstBlockOfSector(s); c->block = FirstBlockOfSector(s);
if (chkKey(c) == 0) {
uint8_t res = chkKey(c);
if (res == 4) {
// failed to select, return immediately
return;
}
if (res == 0) {
num_to_bytes(c->key, 6, k_sector[s].keyA); num_to_bytes(c->key, 6, k_sector[s].keyA);
found[(s * 2)] = 1; found[(s * 2)] = 1;
++*foundkeys; ++*foundkeys;
@ -1806,11 +1827,19 @@ static void chkKey_scanB(struct chk_t *c, struct sector_t *k_sector, uint8_t *fo
for (uint8_t s = 0; s < *sectorcnt; s++) { for (uint8_t s = 0; s < *sectorcnt; s++) {
// skip already found B keys // skip already found B keys
if (found[(s * 2) + 1]) if (found[(s * 2) + 1]) {
continue; continue;
}
c->block = FirstBlockOfSector(s); c->block = FirstBlockOfSector(s);
if (chkKey(c) == 0) {
uint8_t res = chkKey(c);
if (res == 4) {
// failed to select, return immediately
return;
}
if (res == 0) {
num_to_bytes(c->key, 6, k_sector[s].keyB); num_to_bytes(c->key, 6, k_sector[s].keyB);
found[(s * 2) + 1] = 1; found[(s * 2) + 1] = 1;
++*foundkeys; ++*foundkeys;
@ -1827,8 +1856,9 @@ static void chkKey_loopBonly(struct chk_t *c, struct sector_t *k_sector, uint8_t
// read Block B, if A is found. // read Block B, if A is found.
for (uint8_t s = 0; s < *sectorcnt; ++s) { for (uint8_t s = 0; s < *sectorcnt; ++s) {
if (found[(s * 2)] && found[(s * 2) + 1]) if (found[(s * 2)] && found[(s * 2) + 1]) {
continue; continue;
}
c->block = (FirstBlockOfSector(s) + NumBlocksPerSector(s) - 1); c->block = (FirstBlockOfSector(s) + NumBlocksPerSector(s) - 1);
@ -1885,7 +1915,7 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
static uint8_t foundkeys = 0; static uint8_t foundkeys = 0;
static sector_t k_sector[80]; static sector_t k_sector[80];
static uint8_t found[80]; static uint8_t found[80];
static uint8_t *uid; static uint8_t uid[10] = {0};
int oldbg = g_dbglevel; int oldbg = g_dbglevel;
@ -1896,29 +1926,31 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
if (exists_in_spiffs(MF_KEYS_FILE)) { if (exists_in_spiffs(MF_KEYS_FILE)) {
size = size_in_spiffs(MF_KEYS_FILE); size = size_in_spiffs(MF_KEYS_FILE);
} }
if ((size == 0) || (size < MF_KEY_LENGTH)) { if ((size == 0) || (size < MF_KEY_LENGTH)) {
Dbprintf("Spiffs file: %s does not exists or empty.", MF_KEYS_FILE); Dbprintf("Spiffs file `" _RED_("%s") "` does not exists or empty", MF_KEYS_FILE);
goto OUT; goto OUT;
} }
// Compute how many keys can fit in bigbuff // Compute how many keys can fit in bigbuf
// a key is 6bytes // a key is 6 bytes
uint16_t key_mem_available = MIN(BigBuf_get_size() / MF_KEY_LENGTH, keyCount + (size / MF_KEY_LENGTH)); uint16_t key_mem_available = MIN( (BigBuf_get_size() / MF_KEY_LENGTH), (keyCount + (size / MF_KEY_LENGTH)));
uint8_t *dictkeys = BigBuf_malloc(key_mem_available * MF_KEY_LENGTH); uint8_t *dictkeys = BigBuf_calloc(key_mem_available * MF_KEY_LENGTH);
if (dictkeys == NULL) if (dictkeys == NULL) {
goto OUT; goto OUT;
}
// Put user and hard-coded keys first // Put user and hard-coded keys first
memcpy(dictkeys, datain, keyCount * MF_KEY_LENGTH); memcpy(dictkeys, datain, keyCount * MF_KEY_LENGTH);
// Now append the SPI flash dictionnary // Now append the SPI flash dictionnary
if (SPIFFS_OK == rdv40_spiffs_read_as_filetype(MF_KEYS_FILE, dictkeys + keyCount * MF_KEY_LENGTH, (key_mem_available - keyCount) * MF_KEY_LENGTH, RDV40_SPIFFS_SAFETY_SAFE)) { if (SPIFFS_OK == rdv40_spiffs_read_as_filetype(MF_KEYS_FILE, dictkeys + (keyCount * MF_KEY_LENGTH), (key_mem_available - keyCount) * MF_KEY_LENGTH, RDV40_SPIFFS_SAFETY_SAFE)) {
if (g_dbglevel >= DBG_ERROR) { if (g_dbglevel >= DBG_ERROR) {
Dbprintf("Loaded %u keys from spiffs file: %s", key_mem_available, MF_KEYS_FILE); Dbprintf("loaded " _GREEN_("%u") " keys from spiffs file `" _YELLOW_("%s") "`", key_mem_available, MF_KEYS_FILE);
} }
} else { } else {
Dbprintf("Spiffs file: %s cannot be read.", MF_KEYS_FILE); Dbprintf("Spiffs file `" _RED_("%s") "` cannot be read", MF_KEYS_FILE);
goto OUT; goto OUT;
} }
// Replace client provided keys // Replace client provided keys
@ -1926,12 +1958,6 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
} }
#endif #endif
if (uid == NULL || firstchunk) {
uid = BigBuf_malloc(10);
if (uid == NULL)
goto OUT;
}
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
LEDsoff(); LEDsoff();
@ -1946,7 +1972,7 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
foundkeys = 0; foundkeys = 0;
iso14a_card_select_t card_info; iso14a_card_select_t card_info;
if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { if (iso14443a_select_card(uid, &card_info, &cuid, true, 0, true) == 0) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("ChkKeys_fast: Can't select card (ALL)"); if (g_dbglevel >= DBG_ERROR) Dbprintf("ChkKeys_fast: Can't select card (ALL)");
goto OUT; goto OUT;
} }
@ -1991,10 +2017,10 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
WDT_HIT(); WDT_HIT();
chk_data.key = bytes_to_num(datain + i * 6, 6); chk_data.key = bytes_to_num(datain + (i * MF_KEY_LENGTH), MF_KEY_LENGTH);
if (chkKey(&chk_data) == 0) { if (chkKey(&chk_data) == 0) {
foundkeys++; foundkeys++;
reply_old(CMD_ACK, 1, 0, 0, datain + i * 6, 6); reply_old(CMD_ACK, 1, 0, 0, datain + (i * MF_KEY_LENGTH), MF_KEY_LENGTH);
goto out; goto out;
} }
} }
@ -2024,8 +2050,9 @@ out:
// keep track of how many sectors on card. // keep track of how many sectors on card.
for (uint8_t s = 0; s < sectorcnt; ++s) { for (uint8_t s = 0; s < sectorcnt; ++s) {
if (found[(s * 2)] && found[(s * 2) + 1]) if (found[(s * 2)] && found[(s * 2) + 1]) {
continue; continue;
}
for (uint16_t i = s_point; i < keyCount; ++i) { for (uint16_t i = s_point; i < keyCount; ++i) {
@ -2035,8 +2062,9 @@ out:
} }
// found all keys? // found all keys?
if (foundkeys == allkeys) if (foundkeys == allkeys) {
goto OUT; goto OUT;
}
WDT_HIT(); WDT_HIT();
@ -2044,14 +2072,21 @@ out:
chk_data.block = FirstBlockOfSector(s); chk_data.block = FirstBlockOfSector(s);
// new key // new key
chk_data.key = bytes_to_num(datain + i * 6, 6); chk_data.key = bytes_to_num(datain + (i * MF_KEY_LENGTH), MF_KEY_LENGTH);
// skip already found A keys // skip already found A keys
if (!found[(s * 2)]) { if (!found[(s * 2)]) {
chk_data.keyType = 0; chk_data.keyType = 0;
status = chkKey(&chk_data); status = chkKey(&chk_data);
if (status == 4) {
// failed to select, return immediately
goto OUT;
}
if (status == 0) { if (status == 0) {
memcpy(k_sector[s].keyA, datain + i * 6, 6); memcpy(k_sector[s].keyA, datain + (i * MF_KEY_LENGTH), MF_KEY_LENGTH);
found[(s * 2)] = 1; found[(s * 2)] = 1;
++foundkeys; ++foundkeys;
@ -2080,10 +2115,17 @@ out:
// skip already found B keys // skip already found B keys
if (!found[(s * 2) + 1]) { if (!found[(s * 2) + 1]) {
chk_data.keyType = 1; chk_data.keyType = 1;
status = chkKey(&chk_data); status = chkKey(&chk_data);
if (status == 4) {
// failed to select, return immediately
goto OUT;
}
if (status == 0) { if (status == 0) {
memcpy(k_sector[s].keyB, datain + i * 6, 6); memcpy(k_sector[s].keyB, datain + (i * MF_KEY_LENGTH), MF_KEY_LENGTH);
found[(s * 2) + 1] = 1; found[(s * 2) + 1] = 1;
++foundkeys; ++foundkeys;
@ -2101,20 +2143,23 @@ out:
} }
} }
if (found[(s * 2)] && found[(s * 2) + 1]) if (found[(s * 2)] && found[(s * 2) + 1]) {
break; break;
}
} // end keys test loop - depth first } // end keys test loop - depth first
// assume1. if no keys found in first sector, get next keychunk from client // assume1. if no keys found in first sector, get next keychunk from client
if (!use_flashmem && (newfound - foundkeys == 0)) if (!use_flashmem && (newfound - foundkeys == 0)) {
goto OUT; goto OUT;
}
} // end loop - sector } // end loop - sector
} // end strategy 1 } // end strategy 1
if (foundkeys == allkeys) if (foundkeys == allkeys) {
goto OUT; goto OUT;
}
if (strategy == 2 || use_flashmem) { if (strategy == 2 || use_flashmem) {
@ -2122,36 +2167,43 @@ out:
for (uint16_t i = 0; i < keyCount; i++) { for (uint16_t i = 0; i < keyCount; i++) {
// Allow button press / usb cmd to interrupt device // Allow button press / usb cmd to interrupt device
if (BUTTON_PRESS() || data_available()) break; if (BUTTON_PRESS() || data_available()) {
break;
}
// found all keys? // found all keys?
if (foundkeys == allkeys) if (foundkeys == allkeys) {
goto OUT; goto OUT;
}
WDT_HIT(); WDT_HIT();
// new key // new key
chk_data.key = bytes_to_num(datain + i * 6, 6); chk_data.key = bytes_to_num(datain + (i * MF_KEY_LENGTH), MF_KEY_LENGTH);
// Sector main loop // Sector main loop
// keep track of how many sectors on card. // keep track of how many sectors on card.
for (uint8_t s = 0; s < sectorcnt; ++s) { for (uint8_t s = 0; s < sectorcnt; ++s) {
if (found[(s * 2)] && found[(s * 2) + 1]) continue; if (found[(s * 2)] && found[(s * 2) + 1]) {
continue;
}
// found all keys? // found all keys?
if (foundkeys == allkeys) if (foundkeys == allkeys) {
goto OUT; goto OUT;
}
// assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector // assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector
chk_data.block = FirstBlockOfSector(s); chk_data.block = FirstBlockOfSector(s);
// skip already found A keys // skip already found A keys
if (!found[(s * 2)]) { if (found[(s * 2)] == 0) {
chk_data.keyType = 0;
chk_data.keyType = MF_KEY_A;
status = chkKey(&chk_data); status = chkKey(&chk_data);
if (status == 0) { if (status == 0) {
memcpy(k_sector[s].keyA, datain + i * 6, 6); memcpy(k_sector[s].keyA, datain + (i * MF_KEY_LENGTH), MF_KEY_LENGTH);
found[(s * 2)] = 1; found[(s * 2)] = 1;
++foundkeys; ++foundkeys;
@ -2165,11 +2217,12 @@ out:
} }
// skip already found B keys // skip already found B keys
if (!found[(s * 2) + 1]) { if (found[(s * 2) + 1] == 0) {
chk_data.keyType = 1;
chk_data.keyType = MF_KEY_B;
status = chkKey(&chk_data); status = chkKey(&chk_data);
if (status == 0) { if (status == 0) {
memcpy(k_sector[s].keyB, datain + i * 6, 6); memcpy(k_sector[s].keyB, datain + (i * MF_KEY_LENGTH), MF_KEY_LENGTH);
found[(s * 2) + 1] = 1; found[(s * 2) + 1] = 1;
++foundkeys; ++foundkeys;
@ -2226,8 +2279,8 @@ OUT:
// get ST // get ST
emlGetMem_xt(block, blockno, 1, MIFARE_BLOCK_SIZE); emlGetMem_xt(block, blockno, 1, MIFARE_BLOCK_SIZE);
memcpy(block, k_sector[i].keyA, 6); memcpy(block, k_sector[i].keyA, MF_KEY_LENGTH);
memcpy(block + 10, k_sector[i].keyB, 6); memcpy(block + 10, k_sector[i].keyB, MF_KEY_LENGTH);
emlSetMem_xt(block, blockno, 1, sizeof(block)); emlSetMem_xt(block, blockno, 1, sizeof(block));
} }
@ -2257,7 +2310,7 @@ void MifareChkKeys(uint8_t *datain, uint8_t reserved_mem) {
uint32_t cuid = 0; uint32_t cuid = 0;
uint8_t cascade_levels = 0; uint8_t cascade_levels = 0;
struct { struct {
uint8_t key[6]; uint8_t key[MF_KEY_LENGTH];
bool found; bool found;
} PACKED keyresult; } PACKED keyresult;
keyresult.found = false; keyresult.found = false;
@ -2272,11 +2325,11 @@ void MifareChkKeys(uint8_t *datain, uint8_t reserved_mem) {
uint16_t key_mem_available; uint16_t key_mem_available;
if (reserved_mem) if (reserved_mem)
key_mem_available = key_count * 6; key_mem_available = key_count * MF_KEY_LENGTH;
else else
key_mem_available = MIN((PM3_CMD_DATA_SIZE - 5), key_count * 6); key_mem_available = MIN((PM3_CMD_DATA_SIZE - 5), (key_count * MF_KEY_LENGTH));
key_count = key_mem_available / 6; key_count = (key_mem_available / MF_KEY_LENGTH);
datain += 5; datain += 5;
@ -2331,7 +2384,7 @@ void MifareChkKeys(uint8_t *datain, uint8_t reserved_mem) {
continue; continue;
} }
memcpy(keyresult.key, datain + i * 6, 6); memcpy(keyresult.key, datain + (i * MF_KEY_LENGTH), MF_KEY_LENGTH);
keyresult.found = true; keyresult.found = true;
break; break;
} }
@ -2471,7 +2524,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
// increase time-out. Magic card etc are slow // increase time-out. Magic card etc are slow
uint32_t timeout = iso14a_get_timeout(); uint32_t timeout = iso14a_get_timeout();
// frame waiting time (FWT) in 1/fc // frame waiting time (FWT) in 1/fc
uint32_t fwt = 256 * 16 * (1 << 6); uint32_t fwt = 256 * 16 * (1 << 7);
iso14a_set_timeout(fwt / (8 * 16)); iso14a_set_timeout(fwt / (8 * 16));
for (uint8_t s = 0; s < sectorcnt; s++) { for (uint8_t s = 0; s < sectorcnt; s++) {
@ -2873,15 +2926,19 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
} }
// if MAGIC_DATAIN, the data stays on device side. // if MAGIC_DATAIN, the data stays on device side.
if (workFlags & MAGIC_DATAIN) { if (workFlags & MAGIC_DATAIN) {
if (isOK) { if (isOK) {
memcpy(datain, data, sizeof(data)); memcpy(datain, data, sizeof(data));
} }
} else { } else {
if (isOK) { if (isOK) {
reply_old(CMD_ACK, 1, 0, 0, data, sizeof(data)); reply_old(CMD_ACK, 1, 0, 0, data, sizeof(data));
} else { } else {
OnErrorMagic(errormsg); OnErrorMagic(errormsg);
} }
} }
if (workFlags & MAGIC_OFF) { if (workFlags & MAGIC_OFF) {
@ -2908,13 +2965,12 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
uint8_t gen4gdmGetMagicBlock[4] = {MIFARE_MAGIC_GDM_READBLOCK, 0x00, 0xC2, 0x66}; uint8_t gen4gdmGetMagicBlock[4] = {MIFARE_MAGIC_GDM_READBLOCK, 0x00, 0xC2, 0x66};
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};
bool isGen2 = false; uint8_t uid[10];
uint8_t *par = BigBuf_calloc(MAX_PARITY_SIZE); uint8_t *par = BigBuf_calloc(MAX_PARITY_SIZE);
uint8_t *buf = BigBuf_calloc(PM3_CMD_DATA_SIZE); uint8_t *buf = BigBuf_calloc(PM3_CMD_DATA_SIZE);
uint8_t *uid = BigBuf_calloc(10);
iso14a_card_select_t *card = (iso14a_card_select_t *) BigBuf_calloc(sizeof(iso14a_card_select_t)); iso14a_card_select_t *card = (iso14a_card_select_t *) BigBuf_calloc(sizeof(iso14a_card_select_t));
bool isGen2 = false;
uint16_t flag = MAGIC_FLAG_NONE; uint16_t flag = MAGIC_FLAG_NONE;
uint32_t cuid = 0; uint32_t cuid = 0;
int res = 0; int res = 0;
@ -3121,9 +3177,7 @@ void MifareHasStaticNonce(void) {
// variables // variables
int retval = PM3_SUCCESS; int retval = PM3_SUCCESS;
uint32_t nt = 0; uint32_t nt = 0;
uint8_t *uid = BigBuf_malloc(10); uint8_t uid[10] = {0};
memset(uid, 0x00, 10);
uint8_t data[1] = { NONCE_FAIL }; uint8_t data[1] = { NONCE_FAIL };
struct Crypto1State mpcs = {0, 0}; struct Crypto1State mpcs = {0, 0};
@ -3135,7 +3189,7 @@ void MifareHasStaticNonce(void) {
uint8_t counter = 0; uint8_t counter = 0;
for (uint8_t i = 0; i < 3; i++) { for (uint8_t i = 0; i < 3; i++) {
if (!iso14443a_select_card(uid, NULL, NULL, true, 0, true)) { if (iso14443a_select_card(uid, NULL, NULL, true, 0, true) == 0) {
retval = PM3_ESOFT; retval = PM3_ESOFT;
goto OUT; goto OUT;
} }
@ -3219,6 +3273,7 @@ void MifareHasStaticEncryptedNonce(uint8_t block_no, uint8_t key_type, uint8_t *
uint32_t ntenc = 0; uint32_t ntenc = 0;
uint8_t ntencpar = 0; uint8_t ntencpar = 0;
bool is_last_auth_first_auth = true; bool is_last_auth_first_auth = true;
if (nr_nested == 0) { if (nr_nested == 0) {
cuid = 0; cuid = 0;
if (iso14443a_select_card(NULL, NULL, &cuid, true, 0, true) == false) { if (iso14443a_select_card(NULL, NULL, &cuid, true, 0, true) == false) {
@ -3232,8 +3287,11 @@ void MifareHasStaticEncryptedNonce(uint8_t block_no, uint8_t key_type, uint8_t *
goto OUT; goto OUT;
}; };
first_nt_counter++; first_nt_counter++;
} else { } else {
for (uint8_t i = 0; i < nr_nested; i++) { for (uint8_t i = 0; i < nr_nested; i++) {
if (need_first_auth) { if (need_first_auth) {
cuid = 0; cuid = 0;
@ -3246,43 +3304,55 @@ void MifareHasStaticEncryptedNonce(uint8_t block_no, uint8_t key_type, uint8_t *
SpinDelay(150); SpinDelay(150);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
} }
if (g_dbglevel >= DBG_EXTENDED) { if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("select"); Dbprintf("select");
} }
if (iso14443a_select_card(NULL, NULL, &cuid, true, 0, true) == false) { if (iso14443a_select_card(NULL, NULL, &cuid, true, 0, true) == false) {
retval = PM3_ESOFT; retval = PM3_ESOFT;
goto OUT; goto OUT;
} }
if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, &nt_first, NULL, NULL, NULL, corruptnrar, corruptnrarparity)) { if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, &nt_first, NULL, NULL, NULL, corruptnrar, corruptnrarparity)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error");
retval = PM3_ESOFT; retval = PM3_ESOFT;
goto OUT; goto OUT;
}; };
is_last_auth_first_auth = true; is_last_auth_first_auth = true;
first_nt_counter++; first_nt_counter++;
if ((first_nt_counter > 1) && (old_nt_first == nt_first)) { if ((first_nt_counter > 1) && (old_nt_first == nt_first)) {
first_nt_repetition_counter++; first_nt_repetition_counter++;
} }
old_nt_first = nt_first; old_nt_first = nt_first;
if (!reset && !hardreset) { if (!reset && !hardreset) {
need_first_auth = false; need_first_auth = false;
} }
if (addread) { if (addread) {
uint8_t dataread[16] = {0x00}; uint8_t dataread[16] = {0x00};
mifare_classic_readblock(pcs, block_no, dataread); mifare_classic_readblock(pcs, block_no, dataread);
} }
if (addauth) { if (addauth) {
if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_NESTED, &nt, NULL, NULL, NULL, false, false)) { if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_NESTED, &nt, NULL, NULL, NULL, false, false)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error");
retval = PM3_ESOFT; retval = PM3_ESOFT;
goto OUT; goto OUT;
} else if (g_dbglevel >= DBG_EXTENDED) { } else if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("Nonce distance: %5i (first nonce <> nested nonce)", nonce_distance(nt_first, nt)); Dbprintf("Nonce distance: %5i (first nonce <> nested nonce)", nonce_distance(nt_first, nt));
} }
is_last_auth_first_auth = false; is_last_auth_first_auth = false;
if (nt == nt_first) { if (nt == nt_first) {
first_and_nested_nt_repetition_counter++; first_and_nested_nt_repetition_counter++;
} }
old_nt = nt; old_nt = nt;
} }
} }
@ -3290,21 +3360,26 @@ void MifareHasStaticEncryptedNonce(uint8_t block_no, uint8_t key_type, uint8_t *
nt = 0; nt = 0;
ntenc = 0; ntenc = 0;
if (mifare_classic_authex_cmd(pcs, cuid, incblk2 ? block_no_nested + (i * 4) : block_no_nested, key_auth_cmd_nested, ui64key_nested, AUTH_NESTED, &nt, &ntenc, &ntencpar, NULL, false, false)) { if (mifare_classic_authex_cmd(pcs, cuid, incblk2 ? block_no_nested + (i * 4) : block_no_nested, key_auth_cmd_nested, ui64key_nested, AUTH_NESTED, &nt, &ntenc, &ntencpar, NULL, false, false)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Nested auth error"); if (g_dbglevel >= DBG_ERROR) Dbprintf("Nested auth error");
need_first_auth = true; need_first_auth = true;
} else if (g_dbglevel >= DBG_EXTENDED) { } else if (g_dbglevel >= DBG_EXTENDED) {
if (is_last_auth_first_auth) { if (is_last_auth_first_auth) {
Dbprintf("Nonce distance: %5i (first nonce <> nested nonce)", nonce_distance(nt_first, nt)); Dbprintf("Nonce distance: %5i (first nonce <> nested nonce)", nonce_distance(nt_first, nt));
} else { } else {
Dbprintf("Nonce distance: %5i", nonce_distance(old_nt, nt)); Dbprintf("Nonce distance: %5i", nonce_distance(old_nt, nt));
} }
} }
nested_nt_session_counter++; nested_nt_session_counter++;
is_last_auth_first_auth = false; is_last_auth_first_auth = false;
old_nt = nt; old_nt = nt;
if (nt == nt_first) { if (nt == nt_first) {
first_and_nested_nt_repetition_counter++; first_and_nested_nt_repetition_counter++;
} }
if ((nested_nt_session_counter > 1) && (oldntenc == ntenc)) { if ((nested_nt_session_counter > 1) && (oldntenc == ntenc)) {
nested_nt_repetition_counter++; nested_nt_repetition_counter++;
} }
@ -3316,18 +3391,21 @@ void MifareHasStaticEncryptedNonce(uint8_t block_no, uint8_t key_type, uint8_t *
data[2] = (cuid >> 16) & 0xFF; data[2] = (cuid >> 16) & 0xFF;
data[3] = (cuid >> 8) & 0xFF; data[3] = (cuid >> 8) & 0xFF;
data[4] = (cuid >> 0) & 0xFF; data[4] = (cuid >> 0) & 0xFF;
if (first_and_nested_nt_repetition_counter) { if (first_and_nested_nt_repetition_counter) {
data[0] = NONCE_SUPERSTATIC; data[0] = NONCE_SUPERSTATIC;
data[5] = (nt >> 24) & 0xFF; data[5] = (nt >> 24) & 0xFF;
data[6] = (nt >> 16) & 0xFF; data[6] = (nt >> 16) & 0xFF;
data[7] = (nt >> 8) & 0xFF; data[7] = (nt >> 8) & 0xFF;
data[8] = (nt >> 0) & 0xFF; data[8] = (nt >> 0) & 0xFF;
} else if (first_nt_repetition_counter) { } else if (first_nt_repetition_counter) {
data[0] = NONCE_STATIC; data[0] = NONCE_STATIC;
data[5] = (nt_first >> 24) & 0xFF; data[5] = (nt_first >> 24) & 0xFF;
data[6] = (nt_first >> 16) & 0xFF; data[6] = (nt_first >> 16) & 0xFF;
data[7] = (nt_first >> 8) & 0xFF; data[7] = (nt_first >> 8) & 0xFF;
data[8] = (nt_first >> 0) & 0xFF; data[8] = (nt_first >> 0) & 0xFF;
} else if (nested_nt_repetition_counter) { } else if (nested_nt_repetition_counter) {
data[0] = NONCE_STATIC_ENC; data[0] = NONCE_STATIC_ENC;
data[5] = (nt >> 24) & 0xFF; data[5] = (nt >> 24) & 0xFF;
@ -3339,6 +3417,7 @@ void MifareHasStaticEncryptedNonce(uint8_t block_no, uint8_t key_type, uint8_t *
data[11] = (ntenc >> 8) & 0xFF; data[11] = (ntenc >> 8) & 0xFF;
data[12] = (ntenc >> 0) & 0xFF; data[12] = (ntenc >> 0) & 0xFF;
data[13] = ntencpar; data[13] = ntencpar;
} else { } else {
data[0] = NONCE_NORMAL; data[0] = NONCE_NORMAL;
data[5] = (nt >> 24) & 0xFF; data[5] = (nt >> 24) & 0xFF;

View file

@ -156,7 +156,9 @@ int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
// Transmit MIFARE_CLASSIC_AUTH, 0x60 for key A, 0x61 for key B, or 0x80 for GDM backdoor // Transmit MIFARE_CLASSIC_AUTH, 0x60 for key A, 0x61 for key B, or 0x80 for GDM backdoor
int len = mifare_sendcmd_short(pcs, isNested, cmd, blockNo, receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar, timing); int len = mifare_sendcmd_short(pcs, isNested, cmd, blockNo, receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar, timing);
if (len != 4) return 1; if (len != 4) {
return 1;
}
// Save the tag nonce (nt) // Save the tag nonce (nt)
uint32_t nt = bytes_to_num(receivedAnswer, 4); uint32_t nt = bytes_to_num(receivedAnswer, 4);
@ -334,8 +336,9 @@ int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack) {
return 0; return 0;
} }
if (g_dbglevel >= DBG_EXTENDED) if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0], resp[1], resp[2], resp[3]); Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0], resp[1], resp[2], resp[3]);
}
memcpy(pack, resp, 4); memcpy(pack, resp, 4);
return 1; return 1;
@ -490,6 +493,7 @@ int mifare_ultra_aes_auth(uint8_t keyno, uint8_t *keybytes) {
memset(IV, 0, 16); memset(IV, 0, 16);
mbedtls_aes_setkey_dec(&actx, key, 128); mbedtls_aes_setkey_dec(&actx, key, 128);
mbedtls_aes_crypt_cbc(&actx, MBEDTLS_AES_DECRYPT, sizeof(random_b), IV, resp + 1, random_b); mbedtls_aes_crypt_cbc(&actx, MBEDTLS_AES_DECRYPT, sizeof(random_b), IV, resp + 1, random_b);
mbedtls_aes_free(&actx);
if (memcmp(random_b, random_a, 16) != 0) { if (memcmp(random_b, random_a, 16) != 0) {
if (g_dbglevel >= DBG_INFO) Dbprintf("failed authentication"); if (g_dbglevel >= DBG_INFO) Dbprintf("failed authentication");
@ -507,8 +511,6 @@ int mifare_ultra_aes_auth(uint8_t keyno, uint8_t *keybytes) {
Dbprintf("B:"); Dbprintf("B:");
Dbhexdump(16, random_b, false); Dbhexdump(16, random_b, false);
} }
mbedtls_aes_free(&actx);
return 1; return 1;
} }

View file

@ -577,19 +577,25 @@ int rdv40_spiffs_make_symlink(const char *linkdest, const char *filename, RDV40S
// preexistence, avoiding a link being created if filename exists, or avoiding a file being created if // preexistence, avoiding a link being created if filename exists, or avoiding a file being created if
// symlink exists with same name // symlink exists with same name
int rdv40_spiffs_read_as_filetype(const char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level) { int rdv40_spiffs_read_as_filetype(const char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level) {
RDV40_SPIFFS_SAFE_FUNCTION( RDV40_SPIFFS_SAFE_FUNCTION(
RDV40SpiFFSFileType filetype = filetype_in_spiffs((char *)filename); RDV40SpiFFSFileType filetype = filetype_in_spiffs((char *)filename);
switch (filetype) { switch (filetype) {
case RDV40_SPIFFS_FILETYPE_REAL: case RDV40_SPIFFS_FILETYPE_REAL: {
rdv40_spiffs_read(filename, dst, size, level); rdv40_spiffs_read(filename, dst, size, level);
break; break;
case RDV40_SPIFFS_FILETYPE_SYMLINK: }
case RDV40_SPIFFS_FILETYPE_SYMLINK: {
rdv40_spiffs_read_as_symlink(filename, dst, size, level); rdv40_spiffs_read_as_symlink(filename, dst, size, level);
break; break;
}
case RDV40_SPIFFS_FILETYPE_BOTH: case RDV40_SPIFFS_FILETYPE_BOTH:
case RDV40_SPIFFS_FILETYPE_UNKNOWN: case RDV40_SPIFFS_FILETYPE_UNKNOWN:
default: default: {
break; break;
}
} }
) )
} }

View file

@ -240,47 +240,47 @@ int CmdHFSearch(const char *Cmd) {
// no need to print 14A hints, since it will print itself // no need to print 14A hints, since it will print itself
if (success[THINFILM]) { if (success[THINFILM]) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf thinfilm") "` commands\n"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf thinfilm") "` commands\n");
} }
if (success[LTO]) { if (success[LTO]) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf lto") "` commands\n"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf lto") "` commands\n");
} }
if (success[LEGIC]) { if (success[LEGIC]) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf legic") "` commands\n"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf legic") "` commands\n");
} }
if (success[TOPAZ]) { if (success[TOPAZ]) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf topaz") "` commands\n"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf topaz") "` commands\n");
} }
if (success[PROTO_TEXKOM]) { if (success[PROTO_TEXKOM]) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf texkom") "` commands\n"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf texkom") "` commands\n");
} }
if (success[PROTO_XEROX]) { if (success[PROTO_XEROX]) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf xerox") "` commands\n"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf xerox") "` commands\n");
} }
if (success[ISO_14443B]) { if (success[ISO_14443B]) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf 14b") "` commands\n"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf 14b") "` commands\n");
} }
if (success[ISO_15693]) { if (success[ISO_15693]) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf 15") "` commands\n"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf 15") "` commands\n");
} }
if (success[ICLASS]) { if (success[ICLASS]) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf iclass") "` commands\n"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf iclass") "` commands\n");
} }
if (success[FELICA]) { if (success[FELICA]) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf felica") "` commands\n"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf felica") "` commands\n");
} }
if (success[PROTO_CRYPTORF]) { if (success[PROTO_CRYPTORF]) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf cryptorf") "` commands\n"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf cryptorf") "` commands\n");
} }
} }

View file

@ -520,7 +520,7 @@ int Hf14443_4aGetCardData(iso14a_card_select_t *card) {
PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision"); PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision");
// identify TOPAZ // identify TOPAZ
if (card->atqa[1] == 0x0C && card->atqa[0] == 0x00) { if (card->atqa[1] == 0x0C && card->atqa[0] == 0x00) {
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf topaz info`")); PrintAndLogEx(HINT, "Hint: Try " _YELLOW_("`hf topaz info`"));
} else { } else {
PrintAndLogEx(SUCCESS, "\tATQA : %02X %02X", card->atqa[1], card->atqa[0]); PrintAndLogEx(SUCCESS, "\tATQA : %02X %02X", card->atqa[1], card->atqa[0]);
} }
@ -685,7 +685,7 @@ static int CmdHF14AReader(const char *Cmd) {
// identify TOPAZ // identify TOPAZ
if (card.atqa[1] == 0x0C && card.atqa[0] == 0x00) { if (card.atqa[1] == 0x0C && card.atqa[0] == 0x00) {
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf topaz info`")); PrintAndLogEx(HINT, "Hint: Try " _YELLOW_("`hf topaz info`"));
} else { } else {
PrintAndLogEx(SUCCESS, "ATQA: %02X %02X", card.atqa[1], card.atqa[0]); PrintAndLogEx(SUCCESS, "ATQA: %02X %02X", card.atqa[1], card.atqa[0]);
} }
@ -2161,7 +2161,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
// identify TOPAZ // identify TOPAZ
if (card.atqa[1] == 0x0C && card.atqa[0] == 0x00) { if (card.atqa[1] == 0x0C && card.atqa[0] == 0x00) {
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf topaz info`")); PrintAndLogEx(HINT, "Hint: Try " _YELLOW_("`hf topaz info`"));
} }
DropField(); DropField();
@ -2746,42 +2746,42 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
if (isMifareUltralight) { if (isMifareUltralight) {
if (((isMagic & MAGIC_FLAG_GEN_1A) == MAGIC_FLAG_GEN_1A) || ((isMagic & MAGIC_FLAG_GEN_1B) == MAGIC_FLAG_GEN_1B)) { if (((isMagic & MAGIC_FLAG_GEN_1A) == MAGIC_FLAG_GEN_1A) || ((isMagic & MAGIC_FLAG_GEN_1B) == MAGIC_FLAG_GEN_1B)) {
PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mfu *") "` magic commands"); PrintAndLogEx(HINT, "Hint: Use `" _YELLOW_("hf mfu *") "` magic commands");
} }
if ((isMagic & MAGIC_FLAG_NTAG21X) == MAGIC_FLAG_NTAG21X) { if ((isMagic & MAGIC_FLAG_NTAG21X) == MAGIC_FLAG_NTAG21X) {
PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mfu *") "` magic commands"); PrintAndLogEx(HINT, "Hint: Use `" _YELLOW_("hf mfu *") "` magic commands");
} }
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfu info") "`"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf mfu info") "`");
} }
if (isMifarePlus && (isMagic == MAGIC_FLAG_NONE)) { if (isMifarePlus && (isMagic == MAGIC_FLAG_NONE)) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfp info") "`"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf mfp info") "`");
} }
if (isMifareDESFire && (isMagic == MAGIC_FLAG_NONE) && isEMV == false) { if (isMifareDESFire && (isMagic == MAGIC_FLAG_NONE) && isEMV == false) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfdes info") "`"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf mfdes info") "`");
} }
if (isST) { if (isST) {
if (card.ats_len > 0) { if (card.ats_len > 0) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf st25ta info") "`"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf st25ta info") "`");
} else { } else {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfu info") "`"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf mfu info") "`");
} }
} }
if (isEMV) { if (isEMV) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("emv reader") "`"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("emv reader") "`");
} }
if (isSEOS) { if (isSEOS) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf seos info") "`"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf seos info") "`");
} }
if (isFUDAN) { if (isFUDAN) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf fudan dump") "`"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf fudan dump") "`");
/* /*
PrintAndLogEx(HINT, " hf 14a raw -a -b 7 -k 26"); PrintAndLogEx(HINT, " hf 14a raw -a -b 7 -k 26");
PrintAndLogEx(HINT, " hf 14a raw -k -c 3000"); PrintAndLogEx(HINT, " hf 14a raw -k -c 3000");
@ -2796,7 +2796,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
} }
if (isNTAG424) { if (isNTAG424) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf ntag424 info") "`"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf ntag424 info") "`");
} }
if (isMifareClassic || isMifareMini) { if (isMifareClassic || isMifareMini) {

View file

@ -151,8 +151,6 @@ static void lookup_chipid_short(uint32_t iChipID, uint32_t mem_used) {
, mem_avail , mem_avail
, mem_avail == 0 ? 0.0f : (float)mem_used / (mem_avail * 1024) * 100 , mem_avail == 0 ? 0.0f : (float)mem_used / (mem_avail * 1024) * 100
); );
PrintAndLogEx(NORMAL, "");
} }
static void lookupChipID(uint32_t iChipID, uint32_t mem_used) { static void lookupChipID(uint32_t iChipID, uint32_t mem_used) {
@ -1571,6 +1569,23 @@ void pm3_version_short(void) {
lookup_chipid_short(payload->id, payload->section_size); lookup_chipid_short(payload->id, payload->section_size);
if (IfPm3Rdv4Fw()) {
bool is_genuine_rdv4 = false;
// validate signature data
rdv40_validation_t mem;
if (rdv4_get_signature(&mem) == PM3_SUCCESS) {
if (rdv4_validate(&mem) == PM3_SUCCESS) {
is_genuine_rdv4 = true;
}
}
PrintAndLogEx(NORMAL, " Target.... %s", (is_genuine_rdv4) ? _YELLOW_("RDV4") : _RED_("device / fw mismatch"));
} else {
PrintAndLogEx(NORMAL, " Target.... %s", _YELLOW_("PM3 GENERIC"));
}
PrintAndLogEx(NORMAL, "");
// client // client
char temp[PM3_CMD_DATA_SIZE - 12]; // same limit as for ARM image char temp[PM3_CMD_DATA_SIZE - 12]; // same limit as for ARM image
format_version_information_short(temp, sizeof(temp), &g_version_information); format_version_information_short(temp, sizeof(temp), &g_version_information);
@ -1588,42 +1603,24 @@ void pm3_version_short(void) {
} }
// bootrom // bootrom
ptr = strstr(payload->versionstr, " bootrom: "); ptr = strstr(payload->versionstr, "Bootrom.... ");
if (ptr != NULL) { if (ptr != NULL) {
char *ptr_end = strstr(ptr, "\n"); char *ptr_end = strstr(ptr, "\n");
if (ptr_end != NULL) { if (ptr_end != NULL) {
uint8_t len = ptr_end - 19 - ptr; uint8_t len = ptr_end - 19 - ptr;
PrintAndLogEx(NORMAL, " Bootrom... %.*s", len, ptr + 10); PrintAndLogEx(NORMAL, " Bootrom... %.*s", len, ptr + 12);
} }
} }
// os: // os:
ptr = strstr(payload->versionstr, " os: "); ptr = strstr(payload->versionstr, "OS......... ");
if (ptr != NULL) { if (ptr != NULL) {
char *ptr_end = strstr(ptr, "\n"); char *ptr_end = strstr(ptr, "\n");
if (ptr_end != NULL) { if (ptr_end != NULL) {
uint8_t len = ptr_end - 14 - ptr; uint8_t len = ptr_end - 14 - ptr;
PrintAndLogEx(NORMAL, " OS........ %.*s", len, ptr + 5); PrintAndLogEx(NORMAL, " OS........ %.*s", len, ptr + 12);
} }
} }
if (IfPm3Rdv4Fw()) {
bool is_genuine_rdv4 = false;
// validate signature data
rdv40_validation_t mem;
if (rdv4_get_signature(&mem) == PM3_SUCCESS) {
if (rdv4_validate(&mem) == PM3_SUCCESS) {
is_genuine_rdv4 = true;
}
}
PrintAndLogEx(NORMAL, " Target.... %s", (is_genuine_rdv4) ? _YELLOW_("RDV4") : _RED_("device / fw mismatch"));
} else {
PrintAndLogEx(NORMAL, " Target.... %s", _YELLOW_("PM3 GENERIC"));
}
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
if (armsrc_mismatch) { if (armsrc_mismatch) {
@ -1643,7 +1640,7 @@ void pm3_version(bool verbose, bool oneliner) {
if (oneliner) { if (oneliner) {
// For "proxmark3 -v", simple printf, avoid logging // For "proxmark3 -v", simple printf, avoid logging
FormatVersionInformation(temp, sizeof(temp), "Client: ", &g_version_information); FormatVersionInformation(temp, sizeof(temp), "Client: ", &g_version_information);
PrintAndLogEx(NORMAL, "%s compiled with " PM3CLIENTCOMPILER __VERSION__ " OS:" PM3HOSTOS " ARCH:" PM3HOSTARCH "\n", temp); PrintAndLogEx(NORMAL, "%s compiler: " PM3CLIENTCOMPILER __VERSION__ " OS:" PM3HOSTOS " ARCH:" PM3HOSTARCH "\n", temp);
return; return;
} }
@ -1655,8 +1652,8 @@ void pm3_version(bool verbose, bool oneliner) {
PrintAndLogEx(NORMAL, "\n [ " _YELLOW_("Client") " ]"); PrintAndLogEx(NORMAL, "\n [ " _YELLOW_("Client") " ]");
FormatVersionInformation(temp, sizeof(temp), " ", &g_version_information); FormatVersionInformation(temp, sizeof(temp), " ", &g_version_information);
PrintAndLogEx(NORMAL, "%s", temp); PrintAndLogEx(NORMAL, "%s", temp);
PrintAndLogEx(NORMAL, " compiled with............. " PM3CLIENTCOMPILER __VERSION__); PrintAndLogEx(NORMAL, " Compiler.................. " PM3CLIENTCOMPILER __VERSION__);
PrintAndLogEx(NORMAL, " platform.................. " PM3HOSTOS " / " PM3HOSTARCH); PrintAndLogEx(NORMAL, " Platform.................. " PM3HOSTOS " / " PM3HOSTARCH);
#if defined(HAVE_READLINE) #if defined(HAVE_READLINE)
PrintAndLogEx(NORMAL, " Readline support.......... " _GREEN_("present")); PrintAndLogEx(NORMAL, " Readline support.......... " _GREEN_("present"));
#elif defined(HAVE_LINENOISE) #elif defined(HAVE_LINENOISE)
@ -1670,9 +1667,9 @@ void pm3_version(bool verbose, bool oneliner) {
PrintAndLogEx(NORMAL, " QT GUI support............ " _YELLOW_("absent")); PrintAndLogEx(NORMAL, " QT GUI support............ " _YELLOW_("absent"));
#endif #endif
#ifdef HAVE_BLUEZ #ifdef HAVE_BLUEZ
PrintAndLogEx(NORMAL, " native BT support......... " _GREEN_("present")); PrintAndLogEx(NORMAL, " Native BT support......... " _GREEN_("present"));
#else #else
PrintAndLogEx(NORMAL, " native BT support......... " _YELLOW_("absent")); PrintAndLogEx(NORMAL, " Native BT support......... " _YELLOW_("absent"));
#endif #endif
#ifdef HAVE_PYTHON #ifdef HAVE_PYTHON
PrintAndLogEx(NORMAL, " Python script support..... " _GREEN_("present") " ( " _YELLOW_(PY_VERSION) " )"); PrintAndLogEx(NORMAL, " Python script support..... " _GREEN_("present") " ( " _YELLOW_(PY_VERSION) " )");
@ -1692,7 +1689,7 @@ void pm3_version(bool verbose, bool oneliner) {
#endif #endif
if (g_session.pm3_present) { if (g_session.pm3_present) {
PrintAndLogEx(NORMAL, "\n [ " _YELLOW_("Proxmark3") " ]"); PrintAndLogEx(NORMAL, "\n [ " _YELLOW_("Model") " ]");
PacketResponseNG resp; PacketResponseNG resp;
clearCommandBuffer(); clearCommandBuffer();
@ -1710,15 +1707,15 @@ void pm3_version(bool verbose, bool oneliner) {
} }
} }
PrintAndLogEx(NORMAL, " device.................... %s", (is_genuine_rdv4) ? _GREEN_("RDV4") : _RED_("device / fw mismatch")); PrintAndLogEx(NORMAL, " Device.................... %s", (is_genuine_rdv4) ? _GREEN_("RDV4") : _RED_("device / fw mismatch"));
PrintAndLogEx(NORMAL, " firmware.................. %s", (is_genuine_rdv4) ? _GREEN_("RDV4") : _YELLOW_("RDV4")); PrintAndLogEx(NORMAL, " Firmware.................. %s", (is_genuine_rdv4) ? _GREEN_("RDV4") : _YELLOW_("RDV4"));
PrintAndLogEx(NORMAL, " external flash............ %s", IfPm3Flash() ? _GREEN_("present") : _YELLOW_("absent")); PrintAndLogEx(NORMAL, " External flash............ %s", IfPm3Flash() ? _GREEN_("present") : _YELLOW_("absent"));
PrintAndLogEx(NORMAL, " smartcard reader.......... %s", IfPm3Smartcard() ? _GREEN_("present") : _YELLOW_("absent")); PrintAndLogEx(NORMAL, " Smartcard reader.......... %s", IfPm3Smartcard() ? _GREEN_("present") : _YELLOW_("absent"));
PrintAndLogEx(NORMAL, " FPC USART for BT add-on... %s", IfPm3FpcUsartHost() ? _GREEN_("present") : _YELLOW_("absent")); PrintAndLogEx(NORMAL, " FPC USART for BT add-on... %s", IfPm3FpcUsartHost() ? _GREEN_("present") : _YELLOW_("absent"));
} else { } else {
PrintAndLogEx(NORMAL, " firmware.................. %s", _YELLOW_("PM3 GENERIC")); PrintAndLogEx(NORMAL, " Firmware.................. %s", _YELLOW_("PM3 GENERIC"));
if (IfPm3Flash()) { if (IfPm3Flash()) {
PrintAndLogEx(NORMAL, " external flash............ %s", _GREEN_("present")); PrintAndLogEx(NORMAL, " External flash............ %s", _GREEN_("present"));
} }
if (IfPm3FpcUsartHost()) { if (IfPm3FpcUsartHost()) {
@ -1742,7 +1739,7 @@ void pm3_version(bool verbose, bool oneliner) {
struct p *payload = (struct p *)&resp.data.asBytes; struct p *payload = (struct p *)&resp.data.asBytes;
bool armsrc_mismatch = false; bool armsrc_mismatch = false;
char *ptr = strstr(payload->versionstr, " os: "); char *ptr = strstr(payload->versionstr, "OS......... ");
if (ptr != NULL) { if (ptr != NULL) {
ptr = strstr(ptr, "\n"); ptr = strstr(ptr, "\n");
if ((ptr != NULL) && (strlen(g_version_information.armsrc) == 9)) { if ((ptr != NULL) && (strlen(g_version_information.armsrc) == 9)) {