mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-19 21:03:23 -07:00
add: 'hf mf personalize' (personalize UID on Mifare Classic EV1 7byte UID cards)
* add/use some #defines * whitespace fixes * #include refactoring * add line to CHANGELOG.md
This commit is contained in:
parent
cfa9c98d57
commit
0b4efbdef2
10 changed files with 514 additions and 369 deletions
|
@ -15,13 +15,23 @@
|
|||
|
||||
#include "mifarecmd.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "cmd.h"
|
||||
#include "crapto1/crapto1.h"
|
||||
#include "iso14443a.h"
|
||||
#include "BigBuf.h"
|
||||
#include "mifareutil.h"
|
||||
#include "apps.h"
|
||||
#include "protocols.h"
|
||||
#include "util.h"
|
||||
#include "parity.h"
|
||||
#include "crc.h"
|
||||
#include "fpgaloader.h"
|
||||
|
||||
#define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
|
||||
#define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication
|
||||
#define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
|
||||
#define HARDNESTED_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
|
||||
|
@ -73,22 +83,22 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
|
||||
while (true) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
break;
|
||||
};
|
||||
|
||||
if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");
|
||||
break;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
if(mifare_classic_halt(pcs, cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
break;
|
||||
};
|
||||
|
||||
|
@ -99,7 +109,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
// ----------------------------- crypto1 destroy
|
||||
crypto1_destroy(pcs);
|
||||
|
||||
if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
|
||||
if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
|
||||
|
||||
LED_B_ON();
|
||||
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);
|
||||
|
@ -230,25 +240,25 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
isOK = 1;
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||
isOK = 0;
|
||||
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)) {
|
||||
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++) {
|
||||
if(mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf + 16 * blockNo)) {
|
||||
isOK = 0;
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo);
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(mifare_classic_halt(pcs, cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
}
|
||||
|
||||
// ----------------------------- crypto1 destroy
|
||||
|
@ -393,22 +403,22 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
|
||||
while (true) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
break;
|
||||
};
|
||||
|
||||
if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");
|
||||
break;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
if(mifare_classic_halt(pcs, cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
break;
|
||||
};
|
||||
|
||||
|
@ -419,7 +429,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
// ----------------------------- crypto1 destroy
|
||||
crypto1_destroy(pcs);
|
||||
|
||||
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
||||
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
||||
|
||||
LED_B_ON();
|
||||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
||||
|
@ -455,7 +465,7 @@ void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain)
|
|||
if(mifare_ultra_writeblock_compat(blockNo, blockdata)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
|
||||
OnError(0);
|
||||
return; };
|
||||
return; };
|
||||
|
||||
if(mifare_ultra_halt()) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
|
@ -672,7 +682,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
|
||||
iso14a_card_select_t card_info;
|
||||
if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)");
|
||||
continue;
|
||||
}
|
||||
switch (card_info.uidlen) {
|
||||
|
@ -684,7 +694,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
|||
have_uid = true;
|
||||
} else { // no need for anticollision. We can directly select the card
|
||||
if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -696,14 +706,14 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
|||
|
||||
uint32_t nt1;
|
||||
if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth1 error");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth1 error");
|
||||
continue;
|
||||
}
|
||||
|
||||
// nested authentication
|
||||
uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL);
|
||||
if (len != 4) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len);
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -712,7 +722,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
|||
ReaderTransmit(dummy_answer, 1, NULL);
|
||||
|
||||
timeout = GetCountSspClk() + HARDNESTED_AUTHENTICATION_TIMEOUT;
|
||||
|
||||
|
||||
num_nonces++;
|
||||
if (num_nonces % 2) {
|
||||
memcpy(buf+i, receivedAnswer, 4);
|
||||
|
@ -737,7 +747,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
|||
cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf));
|
||||
LED_B_OFF();
|
||||
|
||||
if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished");
|
||||
if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished");
|
||||
|
||||
if (field_off) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
@ -794,7 +804,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
|||
int16_t isOK = 0;
|
||||
#define NESTED_MAX_TRIES 12
|
||||
uint16_t unsuccessfull_tries = 0;
|
||||
if (calibrate) { // for first call only. Otherwise reuse previous calibration
|
||||
if (calibrate) { // for first call only. Otherwise reuse previous calibration
|
||||
LED_B_ON();
|
||||
WDT_HIT();
|
||||
|
||||
|
@ -812,20 +822,20 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
|||
|
||||
// prepare next select. No need to power down the card.
|
||||
if(mifare_classic_halt(pcs, cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error");
|
||||
rtr--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card");
|
||||
rtr--;
|
||||
continue;
|
||||
};
|
||||
|
||||
auth1_time = 0;
|
||||
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");
|
||||
rtr--;
|
||||
continue;
|
||||
};
|
||||
|
@ -836,12 +846,12 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
|||
auth2_time = 0;
|
||||
}
|
||||
if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2, &auth2_time)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error");
|
||||
rtr--;
|
||||
continue;
|
||||
};
|
||||
|
||||
nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160
|
||||
nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160
|
||||
for (i = 101; i < 1200; i++) {
|
||||
nttmp = prng_successor(nttmp, 1);
|
||||
if (nttmp == nt2) break;
|
||||
|
@ -859,7 +869,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
|||
if (MF_DBGLEVEL >= 3) Dbprintf("Nested: calibrating... ntdist=%d", i);
|
||||
} else {
|
||||
unsuccessfull_tries++;
|
||||
if (unsuccessfull_tries > NESTED_MAX_TRIES) { // card isn't vulnerable to nested attack (random numbers are not predictable)
|
||||
if (unsuccessfull_tries > NESTED_MAX_TRIES) { // card isn't vulnerable to nested attack (random numbers are not predictable)
|
||||
isOK = -3;
|
||||
}
|
||||
}
|
||||
|
@ -887,18 +897,18 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
|||
|
||||
// prepare next select. No need to power down the card.
|
||||
if(mifare_classic_halt(pcs, cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card");
|
||||
continue;
|
||||
};
|
||||
|
||||
auth1_time = 0;
|
||||
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");
|
||||
continue;
|
||||
};
|
||||
|
||||
|
@ -906,7 +916,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
|||
auth2_time = auth1_time + delta_time;
|
||||
len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time);
|
||||
if (len != 4) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error len=%d", len);
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error len=%d", len);
|
||||
continue;
|
||||
};
|
||||
|
||||
|
@ -925,7 +935,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
|||
ks1 = nt2 ^ nttest;
|
||||
|
||||
if (valid_nonce(nttest, nt2, ks1, par_array)){
|
||||
if (ncount > 0) { // we are only interested in disambiguous nonces, try again
|
||||
if (ncount > 0) { // we are only interested in disambiguous nonces, try again
|
||||
if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (ambigous), ntdist=%d", i+1, j);
|
||||
target_nt[i] = 0;
|
||||
break;
|
||||
|
@ -961,7 +971,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
|||
cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf));
|
||||
LED_B_OFF();
|
||||
|
||||
if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");
|
||||
if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
|
@ -996,7 +1006,7 @@ void MifareChkKeys(uint16_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
if (set14aTimeout){
|
||||
iso14a_set_timeout(set14aTimeout * 10); // timeout: ms = x/106 35-minimum, 50-OK 106-recommended 500-safe
|
||||
}
|
||||
|
||||
|
||||
if (multisectorCheck) {
|
||||
TKeyIndex keyIndex = {{0}};
|
||||
uint8_t sectorCnt = blockNo;
|
||||
|
@ -1026,6 +1036,60 @@ void MifareChkKeys(uint16_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
LED_A_OFF();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MIFARE Personalize UID. Only for Mifare Classic EV1 7Byte UID
|
||||
//-----------------------------------------------------------------------------
|
||||
void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint8_t *data) {
|
||||
|
||||
uint8_t uid[10];
|
||||
uint32_t cuid;
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
|
||||
LED_A_ON();
|
||||
clear_trace();
|
||||
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
||||
bool isOK = false;
|
||||
while (true) {
|
||||
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t block_number = 0;
|
||||
uint64_t key = bytes_to_num(data, 6);
|
||||
if (mifare_classic_auth(pcs, cuid, block_number, keyType, key, AUTH_FIRST)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
int len = mifare_sendcmd_short(pcs, true, MIFARE_EV1_PERSONAL_UID, perso_option, receivedAnswer, receivedAnswerPar, NULL);
|
||||
if (len != 1 || receivedAnswer[0] != CARD_ACK) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||
break;;
|
||||
}
|
||||
isOK = true;
|
||||
break;
|
||||
}
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LED_D_OFF();
|
||||
|
||||
crypto1_destroy(pcs);
|
||||
|
||||
if (MF_DBGLEVEL >= 2) DbpString("PERSONALIZE UID FINISHED");
|
||||
|
||||
cmd_send(CMD_ACK, isOK, 0, 0, NULL, 0);
|
||||
|
||||
LED_A_OFF();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MIFARE commands set debug level
|
||||
//
|
||||
|
@ -1093,7 +1157,7 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||
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++) {
|
||||
|
@ -1101,13 +1165,13 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
if (sectorNo == 0){
|
||||
if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {
|
||||
isOK = false;
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo);
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) {
|
||||
isOK = false;
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth nested error", sectorNo);
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth nested error", sectorNo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1115,13 +1179,13 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
|
||||
if(isOK && mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) {
|
||||
isOK = false;
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo);
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo);
|
||||
break;
|
||||
};
|
||||
if (isOK) {
|
||||
if (blockNo < NumBlocksPerSector(sectorNo) - 1) {
|
||||
emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1);
|
||||
} else { // sector trailer, keep the keys, set only the AC
|
||||
} else { // sector trailer, keep the keys, set only the AC
|
||||
emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);
|
||||
memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);
|
||||
emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);
|
||||
|
@ -1132,7 +1196,7 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
}
|
||||
|
||||
if(mifare_classic_halt(pcs, cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
};
|
||||
|
||||
// ----------------------------- crypto1 destroy
|
||||
|
@ -1173,20 +1237,20 @@ void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
|
|||
bool needWipe = cmdParams & 0x01;
|
||||
bool needFill = cmdParams & 0x02;
|
||||
bool gen1b = cmdParams & 0x04;
|
||||
|
||||
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
|
||||
|
||||
uint8_t block0[16] = {0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xAF};
|
||||
uint8_t block1[16] = {0x00};
|
||||
uint8_t blockK[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x77, 0x8F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
uint8_t d_block[18] = {0x00};
|
||||
|
||||
|
||||
// card commands
|
||||
uint8_t wupC1[] = { 0x40 };
|
||||
uint8_t wupC2[] = { 0x43 };
|
||||
uint8_t wipeC[] = { 0x41 };
|
||||
|
||||
|
||||
// iso14443 setup
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
|
@ -1196,54 +1260,54 @@ void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
|
|||
// tracing
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
|
||||
while (true){
|
||||
// wipe
|
||||
if (needWipe){
|
||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||
break;
|
||||
};
|
||||
|
||||
ReaderTransmit(wipeC, sizeof(wipeC), NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");
|
||||
break;
|
||||
};
|
||||
|
||||
if(mifare_classic_halt(NULL, 0)) {
|
||||
if (MF_DBGLEVEL > 2) Dbprintf("Halt error");
|
||||
if (MF_DBGLEVEL > 2) Dbprintf("Halt error");
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// put default data
|
||||
if (needFill){
|
||||
// select commands
|
||||
ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
|
||||
|
||||
// gen1b magic tag : do no issue wupC2 and don't expect 0x0a response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command)
|
||||
if (!gen1b) {
|
||||
// gen1b magic tag : do no issue wupC2 and don't expect CARD_ACK response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command)
|
||||
if (!gen1b) {
|
||||
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||
break;
|
||||
};
|
||||
|
||||
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
// send blocks command
|
||||
for (int blockNo = 0; blockNo < numBlocks; blockNo++) {
|
||||
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");
|
||||
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != CARD_ACK)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");
|
||||
break;
|
||||
};
|
||||
|
||||
|
||||
// check type of block and add crc
|
||||
if (!isBlockTrailer(blockNo)){
|
||||
memcpy(d_block, block1, 16);
|
||||
|
@ -1257,33 +1321,33 @@ void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
|
|||
|
||||
// send write command
|
||||
ReaderTransmit(d_block, sizeof(d_block), NULL);
|
||||
if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");
|
||||
if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != CARD_ACK)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// halt
|
||||
// do no issue halt command for gen1b
|
||||
// do no issue halt command for gen1b
|
||||
if (!gen1b) {
|
||||
if (mifare_classic_halt(NULL, 0)) {
|
||||
if (MF_DBGLEVEL > 2) Dbprintf("Halt error");
|
||||
if (MF_DBGLEVEL > 2) Dbprintf("Halt error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// send USB response
|
||||
LED_B_ON();
|
||||
cmd_send(CMD_ACK,isOK,0,0,NULL,0);
|
||||
LED_B_OFF();
|
||||
|
||||
|
||||
// reset fpga
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1330,13 +1394,13 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
// get UID from chip
|
||||
if (workFlags & 0x01) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
// Continue, if we set wrong UID or wrong UID checksum or some ATQA or SAK we will can't select card. But we need to write block 0 to make card work.
|
||||
//break;
|
||||
};
|
||||
|
||||
if(mifare_classic_halt(NULL, cuid)) {
|
||||
if (MF_DBGLEVEL > 2) Dbprintf("Halt error");
|
||||
if (MF_DBGLEVEL > 2) Dbprintf("Halt error");
|
||||
// Continue, some magic tags misbehavies and send an answer to it.
|
||||
// break;
|
||||
};
|
||||
|
@ -1346,21 +1410,21 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
// Wipe command don't work with gen1b
|
||||
if (needWipe && !(workFlags & 0x40)){
|
||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||
break;
|
||||
};
|
||||
|
||||
ReaderTransmit(wipeC, sizeof(wipeC), NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");
|
||||
break;
|
||||
};
|
||||
|
||||
if(mifare_classic_halt(NULL, 0)) {
|
||||
if (MF_DBGLEVEL > 2) Dbprintf("Halt error");
|
||||
if (MF_DBGLEVEL > 2) Dbprintf("Halt error");
|
||||
// Continue, some magic tags misbehavies and send an answer to it.
|
||||
// break;
|
||||
// break;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -1368,24 +1432,24 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
if (workFlags & 0x02) {
|
||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||
|
||||
// gen1b magic tag : do no issue wupC2 and don't expect 0x0a response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command)
|
||||
// gen1b magic tag : do no issue wupC2 and don't expect CARD_ACK response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command)
|
||||
if (!(workFlags & 0x40)) {
|
||||
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||
break;
|
||||
};
|
||||
|
||||
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");
|
||||
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != CARD_ACK)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");
|
||||
break;
|
||||
};
|
||||
|
||||
|
@ -1393,8 +1457,8 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
AppendCrc14443a(d_block, 16);
|
||||
|
||||
ReaderTransmit(d_block, sizeof(d_block), NULL);
|
||||
if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");
|
||||
if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != CARD_ACK)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");
|
||||
break;
|
||||
};
|
||||
|
||||
|
@ -1402,7 +1466,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
// do no issue halt command for gen1b magic tag (#db# halt error. response len: 1)
|
||||
if (!(workFlags & 0x40)) {
|
||||
if (mifare_classic_halt(NULL, 0)) {
|
||||
if (MF_DBGLEVEL > 2) Dbprintf("Halt error");
|
||||
if (MF_DBGLEVEL > 2) Dbprintf("Halt error");
|
||||
// Continue, some magic tags misbehavies and send an answer to it.
|
||||
// break;
|
||||
}
|
||||
|
@ -1461,15 +1525,15 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
while (true) {
|
||||
if (workFlags & 0x02) {
|
||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||
break;
|
||||
};
|
||||
// do no issue for gen1b magic tag
|
||||
if (!(workFlags & 0x40)) {
|
||||
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
@ -1477,7 +1541,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
|
||||
// read block
|
||||
if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("read block send command error");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("read block send command error");
|
||||
break;
|
||||
};
|
||||
memcpy(data, receivedAnswer, 18);
|
||||
|
@ -1486,9 +1550,9 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
// do no issue halt command for gen1b magic tag (#db# halt error. response len: 1)
|
||||
if (!(workFlags & 0x40)) {
|
||||
if (mifare_classic_halt(NULL, cuid)) {
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("Halt error");
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("Halt error");
|
||||
// Continue, some magic tags misbehavies and send an answer to it.
|
||||
// break;
|
||||
// break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1523,34 +1587,34 @@ void MifareCIdent(){
|
|||
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
|
||||
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
set_tracing(true);
|
||||
|
||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||
if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == 0x0a)) {
|
||||
if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == CARD_ACK)) {
|
||||
isOK = 2;
|
||||
|
||||
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
|
||||
if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == 0x0a)) {
|
||||
if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == CARD_ACK)) {
|
||||
isOK = 1;
|
||||
};
|
||||
};
|
||||
|
||||
// From iceman1001: removed the if, since some magic tags misbehavies and send an answer to it.
|
||||
mifare_classic_halt(NULL, 0);
|
||||
|
||||
|
||||
LED_B_ON();
|
||||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
||||
LED_B_OFF();
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
LEDsoff();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -1580,7 +1644,7 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){
|
|||
}
|
||||
|
||||
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED");
|
||||
cmd_send(CMD_ACK,1,cuid,0,dataout, sizeof(dataout));
|
||||
cmd_send(CMD_ACK,1,cuid,0,dataout, sizeof(dataout));
|
||||
}
|
||||
|
||||
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue