Magic s50/1k tag halt error correction for cload and csave

This commit is contained in:
Fl0-0 2017-07-05 15:47:35 +02:00
commit 0c4ef3ed44

View file

@ -21,8 +21,8 @@
#include "crc.h" #include "crc.h"
#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) #define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication #define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication
// the block number for the ISO14443-4 PCB // the block number for the ISO14443-4 PCB
static uint8_t pcb_blocknum = 0; static uint8_t pcb_blocknum = 0;
@ -30,7 +30,7 @@ static uint8_t pcb_blocknum = 0;
static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4}; static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Select, Authenticate, Read a MIFARE tag. // Select, Authenticate, Read a MIFARE tag.
// read block // read block
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
@ -40,7 +40,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
uint8_t keyType = arg1; uint8_t keyType = arg1;
uint64_t ui64Key = 0; uint64_t ui64Key = 0;
ui64Key = bytes_to_num(datain, 6); ui64Key = bytes_to_num(datain, 6);
// variables // variables
byte_t isOK = 0; byte_t isOK = 0;
byte_t dataoutbuf[16]; byte_t dataoutbuf[16];
@ -68,7 +68,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");
break; break;
}; };
if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) { if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Read block error"); if (MF_DBGLEVEL >= 1) Dbprintf("Read block error");
break; break;
@ -78,14 +78,14 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
break; break;
}; };
isOK = 1; isOK = 1;
break; break;
} }
// ----------------------------- crypto1 destroy // ----------------------------- crypto1 destroy
crypto1_destroy(pcs); crypto1_destroy(pcs);
if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED"); if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
LED_B_ON(); LED_B_ON();
@ -111,7 +111,7 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){
OnError(0); OnError(0);
return; return;
}; };
if(!mifare_ultra_auth(keybytes)){ if(!mifare_ultra_auth(keybytes)){
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed"); if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed");
OnError(1); OnError(1);
@ -168,7 +168,7 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
OnError(1); OnError(1);
return; return;
} }
} }
if( mifare_ultra_readblock(blockNo, dataout) ) { if( mifare_ultra_readblock(blockNo, dataout) ) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error"); if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error");
@ -188,7 +188,7 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Select, Authenticate, Read a MIFARE tag. // Select, Authenticate, Read a MIFARE tag.
// read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes) // 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 arg2, uint8_t *datain) void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
@ -198,7 +198,7 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
uint8_t keyType = arg1; uint8_t keyType = arg1;
uint64_t ui64Key = 0; uint64_t ui64Key = 0;
ui64Key = bytes_to_num(datain, 6); ui64Key = bytes_to_num(datain, 6);
// variables // variables
byte_t isOK = 0; byte_t isOK = 0;
byte_t dataoutbuf[16 * 16]; byte_t dataoutbuf[16 * 16];
@ -222,12 +222,12 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
} }
if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {
isOK = 0; isOK = 0;
if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");
} }
for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
if(mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf + 16 * blockNo)) { if(mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf + 16 * blockNo)) {
isOK = 0; isOK = 0;
@ -235,14 +235,14 @@ void MifareReadSector(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, cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
} }
// ----------------------------- crypto1 destroy // ----------------------------- crypto1 destroy
crypto1_destroy(pcs); crypto1_destroy(pcs);
if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED"); if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED");
LED_B_ON(); LED_B_ON();
@ -307,7 +307,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
if (!mifare_ul_ev1_auth(pwd, pack)){ if (!mifare_ul_ev1_auth(pwd, pack)){
OnError(1); OnError(1);
return; return;
} }
} }
@ -316,7 +316,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
Dbprintf("Data exceeds buffer!!"); Dbprintf("Data exceeds buffer!!");
break; break;
} }
len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i); len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i);
if (len) { if (len) {
@ -352,7 +352,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Select, Authenticate, Write a MIFARE tag. // Select, Authenticate, Write a MIFARE tag.
// read block // read block
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
@ -365,7 +365,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
ui64Key = bytes_to_num(datain, 6); ui64Key = bytes_to_num(datain, 6);
memcpy(blockdata, datain + 10, 16); memcpy(blockdata, datain + 10, 16);
// variables // variables
byte_t isOK = 0; byte_t isOK = 0;
uint8_t uid[10]; uint8_t uid[10];
@ -392,7 +392,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");
break; break;
}; };
if(mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) { if(mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
break; break;
@ -402,14 +402,14 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
break; break;
}; };
isOK = 1; isOK = 1;
break; break;
} }
// ----------------------------- crypto1 destroy // ----------------------------- crypto1 destroy
crypto1_destroy(pcs); crypto1_destroy(pcs);
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
LED_B_ON(); LED_B_ON();
@ -422,7 +422,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
LEDsoff(); LEDsoff();
} }
/* // Command not needed but left for future testing /* // Command not needed but left for future testing
void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain) void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain)
{ {
uint8_t blockNo = arg0; uint8_t blockNo = arg0;
@ -476,7 +476,7 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
byte_t blockdata[4] = {0x00}; byte_t blockdata[4] = {0x00};
memcpy(blockdata, datain,4); memcpy(blockdata, datain,4);
LEDsoff(); LEDsoff();
LED_A_ON(); LED_A_ON();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
@ -499,7 +499,7 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
return; return;
} }
} }
// UL-EV1 / NTAG authentication // UL-EV1 / NTAG authentication
if (usePwd) { if (usePwd) {
uint8_t pwd[4] = {0x00}; uint8_t pwd[4] = {0x00};
@ -531,12 +531,12 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
} }
void MifareUSetPwd(uint8_t arg0, uint8_t *datain){ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){
uint8_t pwd[16] = {0x00}; uint8_t pwd[16] = {0x00};
byte_t blockdata[4] = {0x00}; byte_t blockdata[4] = {0x00};
memcpy(pwd, datain, 16); memcpy(pwd, datain, 16);
LED_A_ON(); LED_B_OFF(); LED_C_OFF(); LED_A_ON(); LED_B_OFF(); LED_C_OFF();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
@ -586,7 +586,7 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
OnError(47); OnError(47);
return; return;
}; };
if(mifare_ultra_halt()) { if(mifare_ultra_halt()) {
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
@ -610,7 +610,7 @@ int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// acquire encrypted nonces in order to perform the attack described in // acquire encrypted nonces in order to perform the attack described in
// Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened // Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened
// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on // Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on
// Computer and Communications Security, 2015 // Computer and Communications Security, 2015
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
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)
@ -628,7 +628,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
uint8_t nt_par_enc = 0; uint8_t nt_par_enc = 0;
uint8_t buf[USB_CMD_DATA_SIZE]; uint8_t buf[USB_CMD_DATA_SIZE];
uint32_t timeout; uint32_t timeout;
uint8_t blockNo = arg0 & 0xff; uint8_t blockNo = arg0 & 0xff;
uint8_t keyType = (arg0 >> 8) & 0xff; uint8_t keyType = (arg0 >> 8) & 0xff;
uint8_t targetBlockNo = arg1 & 0xff; uint8_t targetBlockNo = arg1 & 0xff;
@ -637,7 +637,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
bool initialize = flags & 0x0001; bool initialize = flags & 0x0001;
bool slow = flags & 0x0002; bool slow = flags & 0x0002;
bool field_off = flags & 0x0004; bool field_off = flags & 0x0004;
LED_A_ON(); LED_A_ON();
LED_C_OFF(); LED_C_OFF();
@ -646,9 +646,9 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
} }
LED_C_ON(); LED_C_ON();
uint16_t num_nonces = 0; uint16_t num_nonces = 0;
bool have_uid = false; bool have_uid = false;
for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE - 9; ) { for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE - 9; ) {
@ -661,7 +661,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
} }
if (!have_uid) { // need a full select cycle to get the uid first if (!have_uid) { // need a full select cycle to get the uid first
iso14a_card_select_t card_info; iso14a_card_select_t card_info;
if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0)) { if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0)) {
if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)");
continue; continue;
@ -672,14 +672,14 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
case 10: cascade_levels = 3; break; case 10: cascade_levels = 3; break;
default: break; default: break;
} }
have_uid = true; have_uid = true;
} else { // no need for anticollision. We can directly select the card } else { // no need for anticollision. We can directly select the card
if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels)) { if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels)) {
if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)");
continue; continue;
} }
} }
if (slow) { if (slow) {
timeout = GetCountSspClk() + PRE_AUTHENTICATION_LEADTIME; timeout = GetCountSspClk() + PRE_AUTHENTICATION_LEADTIME;
while(GetCountSspClk() < timeout); while(GetCountSspClk() < timeout);
@ -697,12 +697,12 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len); if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len);
continue; continue;
} }
// send a dummy byte as reader response in order to trigger the cards authentication timeout // send a dummy byte as reader response in order to trigger the cards authentication timeout
uint8_t dummy_answer = 0; uint8_t dummy_answer = 0;
ReaderTransmit(&dummy_answer, 1, NULL); ReaderTransmit(&dummy_answer, 1, NULL);
timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT; timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT;
num_nonces++; num_nonces++;
if (num_nonces % 2) { if (num_nonces % 2) {
memcpy(buf+i, receivedAnswer, 4); memcpy(buf+i, receivedAnswer, 4);
@ -716,13 +716,13 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
// wait for the card to become ready again // wait for the card to become ready again
while(GetCountSspClk() < timeout); while(GetCountSspClk() < timeout);
} }
LED_C_OFF(); LED_C_OFF();
crypto1_destroy(pcs); crypto1_destroy(pcs);
LED_B_ON(); LED_B_ON();
cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf)); cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf));
LED_B_OFF(); LED_B_OFF();
@ -737,8 +737,8 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// MIFARE nested authentication. // MIFARE nested authentication.
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *datain) void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *datain)
{ {
@ -750,7 +750,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
uint64_t ui64Key = 0; uint64_t ui64Key = 0;
ui64Key = bytes_to_num(datain, 6); ui64Key = bytes_to_num(datain, 6);
// variables // variables
uint16_t rtr, i, j, len; uint16_t rtr, i, j, len;
uint16_t davg; uint16_t davg;
@ -759,7 +759,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
uint32_t cuid, nt1, nt2, nttmp, nttest, ks1; uint32_t cuid, nt1, nt2, nttmp, nttest, ks1;
uint8_t par[1]; uint8_t par[1];
uint32_t target_nt[2], target_ks[2]; uint32_t target_nt[2], target_ks[2];
uint8_t par_array[4]; uint8_t par_array[4];
uint16_t ncount = 0; uint16_t ncount = 0;
struct Crypto1State mpcs = {0, 0}; struct Crypto1State mpcs = {0, 0};
@ -779,7 +779,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
if (calibrate) clear_trace(); if (calibrate) clear_trace();
set_tracing(true); set_tracing(true);
// statistics on nonce distance // statistics on nonce distance
int16_t isOK = 0; int16_t isOK = 0;
#define NESTED_MAX_TRIES 12 #define NESTED_MAX_TRIES 12
@ -791,7 +791,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
davg = dmax = 0; davg = dmax = 0;
dmin = 2000; dmin = 2000;
delta_time = 0; delta_time = 0;
for (rtr = 0; rtr < 17; rtr++) { for (rtr = 0; rtr < 17; rtr++) {
// Test if the action was cancelled // Test if the action was cancelled
@ -856,17 +856,17 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
} }
davg = (davg + (rtr - 1)/2) / (rtr - 1); davg = (davg + (rtr - 1)/2) / (rtr - 1);
if (MF_DBGLEVEL >= 3) Dbprintf("rtr=%d isOK=%d min=%d max=%d avg=%d, delta_time=%d", rtr, isOK, dmin, dmax, davg, delta_time); if (MF_DBGLEVEL >= 3) Dbprintf("rtr=%d isOK=%d min=%d max=%d avg=%d, delta_time=%d", rtr, isOK, dmin, dmax, davg, delta_time);
dmin = davg - 2; dmin = davg - 2;
dmax = davg + 2; dmax = davg + 2;
LED_B_OFF(); LED_B_OFF();
} }
// ------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------
LED_C_ON(); LED_C_ON();
// get crypted nonces for target sector // get crypted nonces for target sector
@ -874,7 +874,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
target_nt[i] = 0; target_nt[i] = 0;
while(target_nt[i] == 0) { // continue until we have an unambiguous nonce while(target_nt[i] == 0) { // continue until we have an unambiguous nonce
// 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, cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error"); if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error");
@ -885,7 +885,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card"); if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card");
continue; continue;
}; };
auth1_time = 0; auth1_time = 0;
if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) { if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth1 error"); if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth1 error");
@ -899,15 +899,15 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error len=%d", len); if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error len=%d", len);
continue; continue;
}; };
nt2 = bytes_to_num(receivedAnswer, 4); nt2 = bytes_to_num(receivedAnswer, 4);
if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: Testing nt1=%08x nt2enc=%08x nt2par=%02x", i+1, nt1, nt2, par[0]); if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: Testing nt1=%08x nt2enc=%08x nt2par=%02x", i+1, nt1, nt2, par[0]);
// Parity validity check // Parity validity check
for (j = 0; j < 4; j++) { for (j = 0; j < 4; j++) {
par_array[j] = (oddparity8(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01)); par_array[j] = (oddparity8(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01));
} }
ncount = 0; ncount = 0;
nttest = prng_successor(nt1, dmin - 1); nttest = prng_successor(nt1, dmin - 1);
for (j = dmin; j < dmax + 1; j++) { for (j = dmin; j < dmax + 1; j++) {
@ -936,17 +936,17 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
} }
LED_C_OFF(); LED_C_OFF();
// ----------------------------- crypto1 destroy // ----------------------------- crypto1 destroy
crypto1_destroy(pcs); crypto1_destroy(pcs);
byte_t buf[4 + 4 * 4]; byte_t buf[4 + 4 * 4];
memcpy(buf, &cuid, 4); memcpy(buf, &cuid, 4);
memcpy(buf+4, &target_nt[0], 4); memcpy(buf+4, &target_nt[0], 4);
memcpy(buf+8, &target_ks[0], 4); memcpy(buf+8, &target_ks[0], 4);
memcpy(buf+12, &target_nt[1], 4); memcpy(buf+12, &target_nt[1], 4);
memcpy(buf+16, &target_ks[1], 4); memcpy(buf+16, &target_ks[1], 4);
LED_B_ON(); LED_B_ON();
cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf)); cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf));
LED_B_OFF(); LED_B_OFF();
@ -958,8 +958,8 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// MIFARE check keys. key count up to 85. // MIFARE check keys. key count up to 85.
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
{ {
@ -968,7 +968,7 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
bool clearTrace = arg1; bool clearTrace = arg1;
uint8_t keyCount = arg2; uint8_t keyCount = arg2;
uint64_t ui64Key = 0; uint64_t ui64Key = 0;
bool have_uid = false; bool have_uid = false;
uint8_t cascade_levels = 0; uint8_t cascade_levels = 0;
uint32_t timeout = 0; uint32_t timeout = 0;
@ -979,11 +979,11 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
struct Crypto1State mpcs = {0, 0}; struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs; struct Crypto1State *pcs;
pcs = &mpcs; pcs = &mpcs;
// clear debug level // clear debug level
int OLD_MF_DBGLEVEL = MF_DBGLEVEL; int OLD_MF_DBGLEVEL = MF_DBGLEVEL;
MF_DBGLEVEL = MF_DBG_NONE; MF_DBGLEVEL = MF_DBG_NONE;
LED_A_ON(); LED_A_ON();
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
@ -999,7 +999,7 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
// Iceman: use piwi's faster nonce collecting part in hardnested. // Iceman: use piwi's faster nonce collecting part in hardnested.
if (!have_uid) { // need a full select cycle to get the uid first if (!have_uid) { // need a full select cycle to get the uid first
iso14a_card_select_t card_info; iso14a_card_select_t card_info;
if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0)) { if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0)) {
if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card"); if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card");
--i; // try same key once again --i; // try same key once again
@ -1011,7 +1011,7 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
case 10: cascade_levels = 3; break; case 10: cascade_levels = 3; break;
default: break; default: break;
} }
have_uid = true; have_uid = true;
} else { // no need for anticollision. We can directly select the card } else { // no need for anticollision. We can directly select the card
if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels)) { if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels)) {
if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (UID)"); if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (UID)");
@ -1025,16 +1025,16 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
uint8_t dummy_answer = 0; uint8_t dummy_answer = 0;
ReaderTransmit(&dummy_answer, 1, NULL); ReaderTransmit(&dummy_answer, 1, NULL);
timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT; timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT;
// wait for the card to become ready again // wait for the card to become ready again
while(GetCountSspClk() < timeout); while(GetCountSspClk() < timeout);
continue; continue;
} }
isOK = 1; isOK = 1;
break; break;
} }
LED_B_ON(); LED_B_ON();
cmd_send(CMD_ACK,isOK,0,0,datain + i * 6,6); cmd_send(CMD_ACK,isOK,0,0,datain + i * 6,6);
LED_B_OFF(); LED_B_OFF();
@ -1043,12 +1043,12 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
LEDsoff(); LEDsoff();
// restore debug level // restore debug level
MF_DBGLEVEL = OLD_MF_DBGLEVEL; MF_DBGLEVEL = OLD_MF_DBGLEVEL;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// MIFARE commands set debug level // MIFARE commands set debug level
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
MF_DBGLEVEL = arg0; MF_DBGLEVEL = arg0;
@ -1057,7 +1057,7 @@ void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Work with emulator memory // Work with emulator memory
// //
// Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not // Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not
// involved in dealing with emulator memory. But if it is called later, it might // involved in dealing with emulator memory. But if it is called later, it might
// destroy the Emulator Memory. // destroy the Emulator Memory.
@ -1085,7 +1085,7 @@ void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Load a card into the emulator memory // Load a card into the emulator memory
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
uint8_t numSectors = arg0; uint8_t numSectors = arg0;
@ -1105,17 +1105,17 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace(); clear_trace();
set_tracing(false); set_tracing(false);
bool isOK = true; bool isOK = true;
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
isOK = false; isOK = false;
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
} }
for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) { for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) {
ui64Key = emlGetKey(sectorNo, keyType); ui64Key = emlGetKey(sectorNo, keyType);
if (sectorNo == 0){ if (sectorNo == 0){
@ -1131,7 +1131,7 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
break; break;
} }
} }
for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
if(isOK && mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) { if(isOK && mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) {
isOK = false; isOK = false;
@ -1160,7 +1160,7 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();
if (MF_DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED"); if (MF_DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED");
} }
@ -1168,10 +1168,10 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn) // Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
// params // params
uint8_t needWipe = arg0; uint8_t needWipe = arg0;
// bit 0 - need get UID // bit 0 - need get UID
@ -1181,18 +1181,18 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
// bit 4 - need reset FPGA and LED // bit 4 - need reset FPGA and LED
uint8_t workFlags = arg1; uint8_t workFlags = arg1;
uint8_t blockNo = arg2; uint8_t blockNo = arg2;
// card commands // card commands
uint8_t wupC1[] = { 0x40 }; uint8_t wupC1[] = { 0x40 };
uint8_t wupC2[] = { 0x43 }; uint8_t wupC2[] = { 0x43 };
uint8_t wipeC[] = { 0x41 }; uint8_t wipeC[] = { 0x41 };
// variables // variables
byte_t isOK = 0; byte_t isOK = 0;
uint8_t uid[10] = {0x00}; uint8_t uid[10] = {0x00};
uint8_t d_block[18] = {0x00}; uint8_t d_block[18] = {0x00};
uint32_t cuid; uint32_t cuid;
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
@ -1202,7 +1202,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
} }
@ -1218,10 +1218,11 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
if(mifare_classic_halt(NULL, cuid)) { if(mifare_classic_halt(NULL, cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
break; // Continue, some magic tags misbehavies and send an answer to it.
// break;
}; };
}; };
// reset chip // reset chip
if (needWipe){ if (needWipe){
ReaderTransmitBitsPar(wupC1,7,0, NULL); ReaderTransmitBitsPar(wupC1,7,0, NULL);
@ -1238,9 +1239,10 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
if(mifare_classic_halt(NULL, cuid)) { if(mifare_classic_halt(NULL, cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
break; // Continue, some magic tags misbehavies and send an answer to it.
// break;
}; };
}; };
// write block // write block
if (workFlags & 0x02) { if (workFlags & 0x02) {
@ -1261,27 +1263,28 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error"); if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");
break; break;
}; };
memcpy(d_block, datain, 16); memcpy(d_block, datain, 16);
AppendCrc14443a(d_block, 16); AppendCrc14443a(d_block, 16);
ReaderTransmit(d_block, sizeof(d_block), NULL); ReaderTransmit(d_block, sizeof(d_block), NULL);
if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) { if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {
if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error"); if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");
break; break;
}; };
if (workFlags & 0x04) { if (workFlags & 0x04) {
if (mifare_classic_halt(NULL, cuid)) { if (mifare_classic_halt(NULL, cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
break; // Continue, some magic tags misbehavies and send an answer to it.
// break;
}; };
} }
isOK = 1; isOK = 1;
break; break;
} }
LED_B_ON(); LED_B_ON();
cmd_send(CMD_ACK,isOK,0,0,uid,4); cmd_send(CMD_ACK,isOK,0,0,uid,4);
LED_B_OFF(); LED_B_OFF();
@ -1294,8 +1297,8 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
// params // params
// bit 1 - need wupC // bit 1 - need wupC
// bit 2 - need HALT after sequence // bit 2 - need HALT after sequence
// bit 3 - need init FPGA and field before sequence // bit 3 - need init FPGA and field before sequence
@ -1303,19 +1306,19 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
// bit 5 - need to set datain instead of issuing USB reply (called via ARM for StandAloneMode14a) // bit 5 - need to set datain instead of issuing USB reply (called via ARM for StandAloneMode14a)
uint8_t workFlags = arg0; uint8_t workFlags = arg0;
uint8_t blockNo = arg2; uint8_t blockNo = arg2;
// card commands // card commands
uint8_t wupC1[] = { 0x40 }; uint8_t wupC1[] = { 0x40 };
uint8_t wupC2[] = { 0x43 }; uint8_t wupC2[] = { 0x43 };
// variables // variables
byte_t isOK = 0; byte_t isOK = 0;
uint8_t data[18] = {0x00}; uint8_t data[18] = {0x00};
uint32_t cuid = 0; uint32_t cuid = 0;
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
if (workFlags & 0x08) { if (workFlags & 0x08) {
LED_A_ON(); LED_A_ON();
LED_B_OFF(); LED_B_OFF();
@ -1334,8 +1337,8 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
break; break;
}; };
ReaderTransmit(wupC2, sizeof(wupC2), NULL); ReaderTransmit(wupC2, sizeof(wupC2), NULL);
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error"); if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
break; break;
}; };
@ -1347,18 +1350,19 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
break; break;
}; };
memcpy(data, receivedAnswer, 18); memcpy(data, receivedAnswer, 18);
if (workFlags & 0x04) { if (workFlags & 0x04) {
if (mifare_classic_halt(NULL, cuid)) { if (mifare_classic_halt(NULL, cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
break; // Continue, some magic tags misbehavies and send an answer to it.
// break;
}; };
} }
isOK = 1; isOK = 1;
break; break;
} }
LED_B_ON(); LED_B_ON();
if (workFlags & 0x20) { if (workFlags & 0x20) {
if (isOK) if (isOK)
@ -1375,14 +1379,14 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
} }
void MifareCIdent(){ void MifareCIdent(){
// card commands // card commands
uint8_t wupC1[] = { 0x40 }; uint8_t wupC1[] = { 0x40 };
uint8_t wupC2[] = { 0x43 }; uint8_t wupC2[] = { 0x43 };
// variables // variables
byte_t isOK = 0; byte_t isOK = 0;
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
@ -1396,8 +1400,8 @@ void MifareCIdent(){
}; };
}; };
// From iceman1001: removed the if, since some magic tags misbehavies and send an answer to it. // From iceman1001: removed the if, since some magic tags misbehavies and send an answer to it.
mifare_classic_halt(NULL, 0); mifare_classic_halt(NULL, 0);
cmd_send(CMD_ACK,isOK,0,0,0,0); cmd_send(CMD_ACK,isOK,0,0,0,0);
} }
@ -1411,7 +1415,7 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){
byte_t dataout[11] = {0x00}; byte_t dataout[11] = {0x00};
uint8_t uid[10] = {0x00}; uint8_t uid[10] = {0x00};
uint32_t cuid; uint32_t cuid;
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace(); clear_trace();
@ -1438,13 +1442,13 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){
uint8_t key[16] = {0x00}; uint8_t key[16] = {0x00};
byte_t isOK = 0; byte_t isOK = 0;
byte_t dataout[12] = {0x00}; byte_t dataout[12] = {0x00};
memcpy(key, datain, 16); memcpy(key, datain, 16);
isOK = mifare_desfire_des_auth2(cuid, key, dataout); isOK = mifare_desfire_des_auth2(cuid, key, dataout);
if( isOK) { if( isOK) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed");
OnError(4); OnError(4);
return; return;
} }