mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-07-11 15:56:09 -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
|
@ -42,6 +42,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||||
- Added downlink reference mode option r <mode> [ 0 - (or missing) default/fixed bit, 1 - long leading, 2 - leading 0 and 3 - 1 of 4 ] to `lf t55xx detect`, `lf t55xx read`, `lf t55xx write`, and `lf t55xx bruteforce`
|
- Added downlink reference mode option r <mode> [ 0 - (or missing) default/fixed bit, 1 - long leading, 2 - leading 0 and 3 - 1 of 4 ] to `lf t55xx detect`, `lf t55xx read`, `lf t55xx write`, and `lf t55xx bruteforce`
|
||||||
- Added special option `r 4` to bruteforce, to try all downlink modes (0,1,2 and 3) for each password
|
- Added special option `r 4` to bruteforce, to try all downlink modes (0,1,2 and 3) for each password
|
||||||
- `hf mfu info` now checks the NXP Originality Signature if availabe (piwi)
|
- `hf mfu info` now checks the NXP Originality Signature if availabe (piwi)
|
||||||
|
- Added `hf mf personalize` to personalize the UID option of Mifare Classic EV1 cards (piwi)
|
||||||
|
|
||||||
|
|
||||||
## [v3.1.0][2018-10-10]
|
## [v3.1.0][2018-10-10]
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "iso15693.h"
|
#include "iso15693.h"
|
||||||
#include "lfsampling.h"
|
#include "lfsampling.h"
|
||||||
#include "BigBuf.h"
|
#include "BigBuf.h"
|
||||||
|
#include "mifarecmd.h"
|
||||||
#include "mifareutil.h"
|
#include "mifareutil.h"
|
||||||
#include "mifaresim.h"
|
#include "mifaresim.h"
|
||||||
#include "pcf7931.h"
|
#include "pcf7931.h"
|
||||||
|
@ -1242,6 +1243,9 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
||||||
case CMD_MIFARE_WRITEBL:
|
case CMD_MIFARE_WRITEBL:
|
||||||
MifareWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
|
MifareWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
|
||||||
break;
|
break;
|
||||||
|
case CMD_MIFARE_PERSONALIZE_UID:
|
||||||
|
MifarePersonalizeUID(c->arg[0], c->arg[1], c->d.asBytes);
|
||||||
|
break;
|
||||||
//case CMD_MIFAREU_WRITEBL_COMPAT:
|
//case CMD_MIFAREU_WRITEBL_COMPAT:
|
||||||
//MifareUWriteBlockCompat(c->arg[0], c->d.asBytes);
|
//MifareUWriteBlockCompat(c->arg[0], c->d.asBytes);
|
||||||
//break;
|
//break;
|
||||||
|
|
|
@ -108,41 +108,14 @@ void RAMFUNC SniffMifare(uint8_t param);
|
||||||
void EPA_PACE_Collect_Nonce(UsbCommand * c);
|
void EPA_PACE_Collect_Nonce(UsbCommand * c);
|
||||||
void EPA_PACE_Replay(UsbCommand *c);
|
void EPA_PACE_Replay(UsbCommand *c);
|
||||||
|
|
||||||
// mifarecmd.h
|
|
||||||
void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data);
|
|
||||||
void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
|
||||||
void MifareUC_Auth(uint8_t arg0, uint8_t *datain);
|
|
||||||
void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
|
|
||||||
void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
|
||||||
void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
|
||||||
//void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain);
|
|
||||||
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
|
||||||
void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
|
||||||
void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
|
|
||||||
void MifareChkKeys(uint16_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
|
|
||||||
void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
|
||||||
void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
|
||||||
void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
|
||||||
void MifareEMemGet(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);
|
|
||||||
void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); // Work with "magic Chinese" card
|
|
||||||
void MifareCSetBlock(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);
|
|
||||||
void MifareCIdent(); // is "magic chinese" card?
|
|
||||||
void MifareUSetPwd(uint8_t arg0, uint8_t *datain);
|
|
||||||
|
|
||||||
//desfire
|
|
||||||
void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain);
|
|
||||||
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
|
|
||||||
|
|
||||||
// mifaredesfire.h
|
// mifaredesfire.h
|
||||||
bool InitDesfireCard();
|
bool InitDesfireCard();
|
||||||
void MifareSendCommand(uint8_t arg0,uint8_t arg1, uint8_t *datain);
|
void MifareSendCommand(uint8_t arg0,uint8_t arg1, uint8_t *datain);
|
||||||
void MifareDesfireGetInformation();
|
void MifareDesfireGetInformation();
|
||||||
void MifareDES_Auth1(uint8_t arg0,uint8_t arg1,uint8_t arg2, uint8_t *datain);
|
void MifareDES_Auth1(uint8_t arg0,uint8_t arg1,uint8_t arg2, uint8_t *datain);
|
||||||
void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t * datain);
|
void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t * datain);
|
||||||
int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout);
|
int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout);
|
||||||
size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout);
|
size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout);
|
||||||
|
|
||||||
|
|
||||||
/// iclass.h
|
/// iclass.h
|
||||||
|
@ -157,7 +130,7 @@ void iClass_ReadBlk(uint8_t blockNo);
|
||||||
bool iClass_ReadBlock(uint8_t blockNo, uint8_t *readdata);
|
bool iClass_ReadBlock(uint8_t blockNo, uint8_t *readdata);
|
||||||
void iClass_Dump(uint8_t blockno, uint8_t numblks);
|
void iClass_Dump(uint8_t blockno, uint8_t numblks);
|
||||||
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data);
|
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data);
|
||||||
void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType);
|
void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType);
|
||||||
|
|
||||||
// cmd.h
|
// cmd.h
|
||||||
bool cmd_receive(UsbCommand* cmd);
|
bool cmd_receive(UsbCommand* cmd);
|
||||||
|
|
|
@ -15,13 +15,23 @@
|
||||||
|
|
||||||
#include "mifarecmd.h"
|
#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 "util.h"
|
||||||
#include "parity.h"
|
#include "parity.h"
|
||||||
#include "crc.h"
|
#include "crc.h"
|
||||||
#include "fpgaloader.h"
|
#include "fpgaloader.h"
|
||||||
|
|
||||||
#define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
|
#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_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
|
||||||
|
@ -73,22 +83,22 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, 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;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
|
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;
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
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");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -99,7 +109,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||||
// ----------------------------- 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();
|
||||||
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);
|
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;
|
isOK = 1;
|
||||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||||
isOK = 0;
|
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)) {
|
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;
|
||||||
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;
|
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
|
||||||
|
@ -393,22 +403,22 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, 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;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
|
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;
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
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");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -419,7 +429,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||||
// ----------------------------- 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();
|
||||||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
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(mifare_ultra_writeblock_compat(blockNo, blockdata)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
|
||||||
OnError(0);
|
OnError(0);
|
||||||
return; };
|
return; };
|
||||||
|
|
||||||
if(mifare_ultra_halt()) {
|
if(mifare_ultra_halt()) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
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
|
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, true)) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
switch (card_info.uidlen) {
|
switch (card_info.uidlen) {
|
||||||
|
@ -684,7 +694,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
||||||
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, true)) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -696,14 +706,14 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
||||||
|
|
||||||
uint32_t nt1;
|
uint32_t nt1;
|
||||||
if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// nested authentication
|
// nested authentication
|
||||||
uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL);
|
uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL);
|
||||||
if (len != 4) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -712,7 +722,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
||||||
ReaderTransmit(dummy_answer, 1, NULL);
|
ReaderTransmit(dummy_answer, 1, NULL);
|
||||||
|
|
||||||
timeout = GetCountSspClk() + HARDNESTED_AUTHENTICATION_TIMEOUT;
|
timeout = GetCountSspClk() + HARDNESTED_AUTHENTICATION_TIMEOUT;
|
||||||
|
|
||||||
num_nonces++;
|
num_nonces++;
|
||||||
if (num_nonces % 2) {
|
if (num_nonces % 2) {
|
||||||
memcpy(buf+i, receivedAnswer, 4);
|
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));
|
cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf));
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished");
|
if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished");
|
||||||
|
|
||||||
if (field_off) {
|
if (field_off) {
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_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;
|
int16_t isOK = 0;
|
||||||
#define NESTED_MAX_TRIES 12
|
#define NESTED_MAX_TRIES 12
|
||||||
uint16_t unsuccessfull_tries = 0;
|
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();
|
LED_B_ON();
|
||||||
WDT_HIT();
|
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.
|
// 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");
|
||||||
rtr--;
|
rtr--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
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--;
|
rtr--;
|
||||||
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");
|
||||||
rtr--;
|
rtr--;
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
@ -836,12 +846,12 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
||||||
auth2_time = 0;
|
auth2_time = 0;
|
||||||
}
|
}
|
||||||
if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2, &auth2_time)) {
|
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--;
|
rtr--;
|
||||||
continue;
|
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++) {
|
for (i = 101; i < 1200; i++) {
|
||||||
nttmp = prng_successor(nttmp, 1);
|
nttmp = prng_successor(nttmp, 1);
|
||||||
if (nttmp == nt2) break;
|
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);
|
if (MF_DBGLEVEL >= 3) Dbprintf("Nested: calibrating... ntdist=%d", i);
|
||||||
} else {
|
} else {
|
||||||
unsuccessfull_tries++;
|
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;
|
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.
|
// 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");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
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;
|
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");
|
||||||
continue;
|
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;
|
auth2_time = auth1_time + delta_time;
|
||||||
len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time);
|
len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time);
|
||||||
if (len != 4) {
|
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;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -925,7 +935,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
||||||
ks1 = nt2 ^ nttest;
|
ks1 = nt2 ^ nttest;
|
||||||
|
|
||||||
if (valid_nonce(nttest, nt2, ks1, par_array)){
|
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);
|
if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (ambigous), ntdist=%d", i+1, j);
|
||||||
target_nt[i] = 0;
|
target_nt[i] = 0;
|
||||||
break;
|
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));
|
cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf));
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");
|
if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
|
@ -996,7 +1006,7 @@ void MifareChkKeys(uint16_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
|
||||||
if (set14aTimeout){
|
if (set14aTimeout){
|
||||||
iso14a_set_timeout(set14aTimeout * 10); // timeout: ms = x/106 35-minimum, 50-OK 106-recommended 500-safe
|
iso14a_set_timeout(set14aTimeout * 10); // timeout: ms = x/106 35-minimum, 50-OK 106-recommended 500-safe
|
||||||
}
|
}
|
||||||
|
|
||||||
if (multisectorCheck) {
|
if (multisectorCheck) {
|
||||||
TKeyIndex keyIndex = {{0}};
|
TKeyIndex keyIndex = {{0}};
|
||||||
uint8_t sectorCnt = blockNo;
|
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();
|
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
|
// 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)) {
|
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||||
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++) {
|
||||||
|
@ -1101,13 +1165,13 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
||||||
if (sectorNo == 0){
|
if (sectorNo == 0){
|
||||||
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 = false;
|
isOK = false;
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo);
|
if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) {
|
if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) {
|
||||||
isOK = false;
|
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;
|
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++) {
|
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;
|
||||||
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;
|
break;
|
||||||
};
|
};
|
||||||
if (isOK) {
|
if (isOK) {
|
||||||
if (blockNo < NumBlocksPerSector(sectorNo) - 1) {
|
if (blockNo < NumBlocksPerSector(sectorNo) - 1) {
|
||||||
emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 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);
|
emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);
|
||||||
memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);
|
memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);
|
||||||
emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);
|
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(mifare_classic_halt(pcs, cuid)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------- crypto1 destroy
|
// ----------------------------- 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 needWipe = cmdParams & 0x01;
|
||||||
bool needFill = cmdParams & 0x02;
|
bool needFill = cmdParams & 0x02;
|
||||||
bool gen1b = cmdParams & 0x04;
|
bool gen1b = cmdParams & 0x04;
|
||||||
|
|
||||||
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];
|
||||||
|
|
||||||
uint8_t block0[16] = {0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xAF};
|
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 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 blockK[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x77, 0x8F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||||
uint8_t d_block[18] = {0x00};
|
uint8_t d_block[18] = {0x00};
|
||||||
|
|
||||||
// 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 };
|
||||||
|
|
||||||
// iso14443 setup
|
// iso14443 setup
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
@ -1196,54 +1260,54 @@ void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
|
||||||
// tracing
|
// tracing
|
||||||
clear_trace();
|
clear_trace();
|
||||||
set_tracing(true);
|
set_tracing(true);
|
||||||
|
|
||||||
while (true){
|
while (true){
|
||||||
// wipe
|
// wipe
|
||||||
if (needWipe){
|
if (needWipe){
|
||||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
ReaderTransmit(wipeC, sizeof(wipeC), NULL);
|
ReaderTransmit(wipeC, sizeof(wipeC), NULL);
|
||||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if(mifare_classic_halt(NULL, 0)) {
|
if(mifare_classic_halt(NULL, 0)) {
|
||||||
if (MF_DBGLEVEL > 2) Dbprintf("Halt error");
|
if (MF_DBGLEVEL > 2) Dbprintf("Halt error");
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// put default data
|
// put default data
|
||||||
if (needFill){
|
if (needFill){
|
||||||
// select commands
|
// select commands
|
||||||
ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
|
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 (!gen1b) {
|
if (!gen1b) {
|
||||||
|
|
||||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||||
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] != CARD_ACK)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// send blocks command
|
// send blocks command
|
||||||
for (int blockNo = 0; blockNo < numBlocks; blockNo++) {
|
for (int blockNo = 0; blockNo < numBlocks; blockNo++) {
|
||||||
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
|
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");
|
if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
// check type of block and add crc
|
// check type of block and add crc
|
||||||
if (!isBlockTrailer(blockNo)){
|
if (!isBlockTrailer(blockNo)){
|
||||||
memcpy(d_block, block1, 16);
|
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
|
// send write command
|
||||||
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] != CARD_ACK)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// halt
|
// halt
|
||||||
// do no issue halt command for gen1b
|
// do no issue halt command for gen1b
|
||||||
if (!gen1b) {
|
if (!gen1b) {
|
||||||
if (mifare_classic_halt(NULL, 0)) {
|
if (mifare_classic_halt(NULL, 0)) {
|
||||||
if (MF_DBGLEVEL > 2) Dbprintf("Halt error");
|
if (MF_DBGLEVEL > 2) Dbprintf("Halt error");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// send USB response
|
// send USB response
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
cmd_send(CMD_ACK,isOK,0,0,NULL,0);
|
cmd_send(CMD_ACK,isOK,0,0,NULL,0);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
// reset fpga
|
// reset fpga
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1330,13 +1394,13 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
||||||
// get UID from chip
|
// get UID from chip
|
||||||
if (workFlags & 0x01) {
|
if (workFlags & 0x01) {
|
||||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, 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");
|
||||||
// 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.
|
// 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;
|
//break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if(mifare_classic_halt(NULL, cuid)) {
|
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.
|
// Continue, some magic tags misbehavies and send an answer to it.
|
||||||
// break;
|
// 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
|
// Wipe command don't work with gen1b
|
||||||
if (needWipe && !(workFlags & 0x40)){
|
if (needWipe && !(workFlags & 0x40)){
|
||||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
ReaderTransmit(wipeC, sizeof(wipeC), NULL);
|
ReaderTransmit(wipeC, sizeof(wipeC), NULL);
|
||||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if(mifare_classic_halt(NULL, 0)) {
|
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.
|
// 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) {
|
if (workFlags & 0x02) {
|
||||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
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 (!(workFlags & 0x40)) {
|
||||||
|
|
||||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||||
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] != CARD_ACK)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
|
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");
|
if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1393,8 +1457,8 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
||||||
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] != CARD_ACK)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");
|
||||||
break;
|
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)
|
// do no issue halt command for gen1b magic tag (#db# halt error. response len: 1)
|
||||||
if (!(workFlags & 0x40)) {
|
if (!(workFlags & 0x40)) {
|
||||||
if (mifare_classic_halt(NULL, 0)) {
|
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.
|
// Continue, some magic tags misbehavies and send an answer to it.
|
||||||
// break;
|
// break;
|
||||||
}
|
}
|
||||||
|
@ -1461,15 +1525,15 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
||||||
while (true) {
|
while (true) {
|
||||||
if (workFlags & 0x02) {
|
if (workFlags & 0x02) {
|
||||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
// do no issue for gen1b magic tag
|
// do no issue for gen1b magic tag
|
||||||
if (!(workFlags & 0x40)) {
|
if (!(workFlags & 0x40)) {
|
||||||
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
|
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
|
||||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1477,7 +1541,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
||||||
|
|
||||||
// read block
|
// read block
|
||||||
if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) {
|
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;
|
break;
|
||||||
};
|
};
|
||||||
memcpy(data, receivedAnswer, 18);
|
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)
|
// do no issue halt command for gen1b magic tag (#db# halt error. response len: 1)
|
||||||
if (!(workFlags & 0x40)) {
|
if (!(workFlags & 0x40)) {
|
||||||
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");
|
||||||
// Continue, some magic tags misbehavies and send an answer to it.
|
// 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 receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
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);
|
||||||
|
|
||||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||||
if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == 0x0a)) {
|
if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == CARD_ACK)) {
|
||||||
isOK = 2;
|
isOK = 2;
|
||||||
|
|
||||||
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
|
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
|
||||||
if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == 0x0a)) {
|
if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == CARD_ACK)) {
|
||||||
isOK = 1;
|
isOK = 1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_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");
|
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){
|
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){
|
||||||
|
|
|
@ -10,18 +10,36 @@
|
||||||
// Routines to support ISO 14443 type A.
|
// Routines to support ISO 14443 type A.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#ifndef __MIFARECMD_H
|
#ifndef MIFARECMD_H__
|
||||||
#define __MIFARECMD_H
|
#define MIFARECMD_H__
|
||||||
|
|
||||||
#include "proxmark3.h"
|
#include <stdint.h>
|
||||||
#include "apps.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
#include "iso14443crc.h"
|
extern void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data);
|
||||||
#include "iso14443a.h"
|
extern void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||||
#include "crapto1/crapto1.h"
|
extern void MifareUC_Auth(uint8_t arg0, uint8_t *datain);
|
||||||
#include "mifareutil.h"
|
extern void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
|
||||||
#include "common.h"
|
extern void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
||||||
|
extern void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
||||||
|
//extern void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain);
|
||||||
|
extern void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||||
|
extern void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||||
|
extern void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
|
||||||
|
extern void MifareChkKeys(uint16_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
|
||||||
|
extern void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||||
|
extern void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||||
|
extern void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||||
|
extern void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||||
|
extern void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||||
|
extern void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); // Work with "magic Chinese" card
|
||||||
|
extern void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||||
|
extern void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||||
|
extern void MifareCIdent(); // is "magic chinese" card?
|
||||||
|
extern void MifareUSetPwd(uint8_t arg0, uint8_t *datain);
|
||||||
|
extern void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint8_t *datain);
|
||||||
|
|
||||||
|
//desfire
|
||||||
|
extern void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain);
|
||||||
|
extern void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "iso14443a.h"
|
#include "iso14443a.h"
|
||||||
#include "crapto1/crapto1.h"
|
#include "crapto1/crapto1.h"
|
||||||
#include "mbedtls/des.h"
|
#include "mbedtls/des.h"
|
||||||
|
#include "protocols.h"
|
||||||
|
|
||||||
int MF_DBGLEVEL = MF_DBG_INFO;
|
int MF_DBGLEVEL = MF_DBG_INFO;
|
||||||
|
|
||||||
|
@ -163,7 +164,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
|
||||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
// Transmit MIFARE_CLASSIC_AUTH
|
// Transmit MIFARE_CLASSIC_AUTH
|
||||||
len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing);
|
len = mifare_sendcmd_short(pcs, isNested, keyType & 0x01 ? MIFARE_AUTH_KEYB : MIFARE_AUTH_KEYA, blockNo, receivedAnswer, receivedAnswerPar, timing);
|
||||||
if (MF_DBGLEVEL >= 4) Dbprintf("rand tag nonce len: %x", len);
|
if (MF_DBGLEVEL >= 4) Dbprintf("rand tag nonce len: %x", len);
|
||||||
if (len != 4) return 1;
|
if (len != 4) return 1;
|
||||||
|
|
||||||
|
@ -250,7 +251,7 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
|
||||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
// command MIFARE_CLASSIC_READBLOCK
|
// command MIFARE_CLASSIC_READBLOCK
|
||||||
len = mifare_sendcmd_short(pcs, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
len = mifare_sendcmd_short(pcs, 1, MIFARE_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
if (len == 1) {
|
if (len == 1) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -282,7 +283,7 @@ int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack){
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= MF_DBG_EXTENDED)
|
if (MF_DBGLEVEL >= MF_DBG_EXTENDED)
|
||||||
Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]);
|
Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]);
|
||||||
len = mifare_sendcmd(0x1B, key, sizeof(key), resp, respPar, NULL);
|
len = mifare_sendcmd(MIFARE_ULEV1_AUTH, key, sizeof(key), resp, respPar, NULL);
|
||||||
//len = mifare_sendcmd_short_mfuev1auth(NULL, 0, 0x1B, key, resp, respPar, NULL);
|
//len = mifare_sendcmd_short_mfuev1auth(NULL, 0, 0x1B, key, resp, respPar, NULL);
|
||||||
if (len != 4) {
|
if (len != 4) {
|
||||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len);
|
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len);
|
||||||
|
@ -314,7 +315,7 @@ int mifare_ultra_auth(uint8_t *keybytes){
|
||||||
uint8_t respPar[3] = {0,0,0};
|
uint8_t respPar[3] = {0,0,0};
|
||||||
|
|
||||||
// REQUEST AUTHENTICATION
|
// REQUEST AUTHENTICATION
|
||||||
len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, resp, respPar ,NULL);
|
len = mifare_sendcmd_short(NULL, 1, MIFARE_ULC_AUTH_1, 0x00, resp, respPar ,NULL);
|
||||||
if (len != 11) {
|
if (len != 11) {
|
||||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);
|
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -364,7 +365,7 @@ int mifare_ultra_auth(uint8_t *keybytes){
|
||||||
);
|
);
|
||||||
|
|
||||||
//len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, resp, respPar, NULL);
|
//len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, resp, respPar, NULL);
|
||||||
len = mifare_sendcmd(0xAF, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL);
|
len = mifare_sendcmd(MIFARE_ULC_AUTH_2, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL);
|
||||||
if (len != 11) {
|
if (len != 11) {
|
||||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);
|
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -421,7 +422,7 @@ int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData)
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
for (retries = 0; retries < MFU_MAX_RETRIES; retries++) {
|
for (retries = 0; retries < MFU_MAX_RETRIES; retries++) {
|
||||||
len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
len = mifare_sendcmd_short(NULL, 1, MIFARE_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
if (len == 1) {
|
if (len == 1) {
|
||||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||||
result = 1;
|
result = 1;
|
||||||
|
@ -468,7 +469,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
|
||||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
// command MIFARE_CLASSIC_WRITEBLOCK
|
||||||
len = mifare_sendcmd_short(pcs, 1, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
len = mifare_sendcmd_short(pcs, 1, MIFARE_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
|
|
||||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||||
|
@ -511,7 +512,7 @@ int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData)
|
||||||
uint8_t receivedAnswer[MAX_FRAME_SIZE];
|
uint8_t receivedAnswer[MAX_FRAME_SIZE];
|
||||||
uint8_t receivedAnswerPar[MAX_PARITY_SIZE];
|
uint8_t receivedAnswerPar[MAX_PARITY_SIZE];
|
||||||
|
|
||||||
len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
len = mifare_sendcmd_short(NULL, true, MIFARE_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
|
|
||||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
||||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||||
|
@ -563,7 +564,7 @@ int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
|
||||||
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];
|
||||||
|
|
||||||
len = mifare_sendcmd_short(pcs, pcs == NULL ? false:true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);
|
len = mifare_sendcmd_short(pcs, pcs == NULL ? false:true, ISO14443A_CMD_HALT, 0x00, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
if (len != 0) {
|
if (len != 0) {
|
||||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||||
Dbprintf("halt error. response len: %x", len);
|
Dbprintf("halt error. response len: %x", len);
|
||||||
|
@ -579,7 +580,7 @@ int mifare_ultra_halt()
|
||||||
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];
|
||||||
|
|
||||||
len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);
|
len = mifare_sendcmd_short(NULL, true, ISO14443A_CMD_HALT, 0x00, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
if (len != 0) {
|
if (len != 0) {
|
||||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||||
Dbprintf("halt error. response len: %x", len);
|
Dbprintf("halt error. response len: %x", len);
|
||||||
|
|
212
client/cmdhfmf.c
212
client/cmdhfmf.c
|
@ -34,6 +34,7 @@
|
||||||
#include "mifare/mad.h"
|
#include "mifare/mad.h"
|
||||||
#include "mifare/ndef.h"
|
#include "mifare/ndef.h"
|
||||||
#include "emv/dump.h"
|
#include "emv/dump.h"
|
||||||
|
#include "protocols.h"
|
||||||
|
|
||||||
#define NESTED_SECTOR_RETRY 10 // how often we try mfested() until we give up
|
#define NESTED_SECTOR_RETRY 10 // how often we try mfested() until we give up
|
||||||
|
|
||||||
|
@ -92,10 +93,10 @@ int CmdHF14AMfWrBl(const char *Cmd)
|
||||||
PrintAndLog("--block no:%d, key type:%c, key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6));
|
PrintAndLog("--block no:%d, key type:%c, key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6));
|
||||||
PrintAndLog("--data: %s", sprint_hex(bldata, 16));
|
PrintAndLog("--data: %s", sprint_hex(bldata, 16));
|
||||||
|
|
||||||
UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
|
UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
|
||||||
memcpy(c.d.asBytes, key, 6);
|
memcpy(c.d.asBytes, key, 6);
|
||||||
memcpy(c.d.asBytes + 10, bldata, 16);
|
memcpy(c.d.asBytes + 10, bldata, 16);
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
|
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||||
|
@ -136,9 +137,9 @@ int CmdHF14AMfRdBl(const char *Cmd)
|
||||||
}
|
}
|
||||||
PrintAndLog("--block no:%d, key type:%c, key:%s ", blockNo, keyType?'B':'A', sprint_hex(key, 6));
|
PrintAndLog("--block no:%d, key type:%c, key:%s ", blockNo, keyType?'B':'A', sprint_hex(key, 6));
|
||||||
|
|
||||||
UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
|
UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
|
||||||
memcpy(c.d.asBytes, key, 6);
|
memcpy(c.d.asBytes, key, 6);
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
|
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||||
|
@ -167,7 +168,7 @@ int CmdHF14AMfRdBl(const char *Cmd)
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdHF14AMfRdSc(const char *Cmd)
|
int CmdHF14AMfRdSc(const char *Cmd)
|
||||||
|
@ -233,7 +234,7 @@ int CmdHF14AMfRdSc(const char *Cmd)
|
||||||
PrintAndLog("Command execute timeout");
|
PrintAndLog("Command execute timeout");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t FirstBlockOfSector(uint8_t sectorNo)
|
uint8_t FirstBlockOfSector(uint8_t sectorNo)
|
||||||
|
@ -1086,7 +1087,7 @@ int CmdHF14AMfChk(const char *Cmd)
|
||||||
bool createDumpFile = 0;
|
bool createDumpFile = 0;
|
||||||
bool singleBlock = false; // Flag to ID if a single or multi key check
|
bool singleBlock = false; // Flag to ID if a single or multi key check
|
||||||
uint8_t keyFoundCount = 0; // Counter to display the number of keys found/transfered to emulator
|
uint8_t keyFoundCount = 0; // Counter to display the number of keys found/transfered to emulator
|
||||||
|
|
||||||
sector_t *e_sector = NULL;
|
sector_t *e_sector = NULL;
|
||||||
|
|
||||||
keyBlock = calloc(stKeyBlock, 6);
|
keyBlock = calloc(stKeyBlock, 6);
|
||||||
|
@ -1132,7 +1133,7 @@ int CmdHF14AMfChk(const char *Cmd)
|
||||||
return 1;
|
return 1;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
parseParamTDS(Cmd, 2, &transferToEml, &createDumpFile, &btimeout14a);
|
parseParamTDS(Cmd, 2, &transferToEml, &createDumpFile, &btimeout14a);
|
||||||
|
|
||||||
if (singleBlock & createDumpFile) {
|
if (singleBlock & createDumpFile) {
|
||||||
|
@ -1244,7 +1245,7 @@ int CmdHF14AMfChk(const char *Cmd)
|
||||||
uint32_t max_keys = keycnt > USB_CMD_DATA_SIZE / 6 ? USB_CMD_DATA_SIZE / 6 : keycnt;
|
uint32_t max_keys = keycnt > USB_CMD_DATA_SIZE / 6 ? USB_CMD_DATA_SIZE / 6 : keycnt;
|
||||||
|
|
||||||
// !SingleKey, so all key check (if SectorsCnt > 0)
|
// !SingleKey, so all key check (if SectorsCnt > 0)
|
||||||
if (!singleBlock) {
|
if (!singleBlock) {
|
||||||
PrintAndLog("To cancel this operation press the button on the proxmark...");
|
PrintAndLog("To cancel this operation press the button on the proxmark...");
|
||||||
printf("--");
|
printf("--");
|
||||||
for (uint32_t c = 0; c < keycnt; c += max_keys) {
|
for (uint32_t c = 0; c < keycnt; c += max_keys) {
|
||||||
|
@ -1265,7 +1266,7 @@ int CmdHF14AMfChk(const char *Cmd)
|
||||||
PrintAndLog("Command execute timeout");
|
PrintAndLog("Command execute timeout");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int keyAB = keyType;
|
int keyAB = keyType;
|
||||||
do {
|
do {
|
||||||
for (uint32_t c = 0; c < keycnt; c += max_keys) {
|
for (uint32_t c = 0; c < keycnt; c += max_keys) {
|
||||||
|
@ -1275,16 +1276,16 @@ int CmdHF14AMfChk(const char *Cmd)
|
||||||
clearTraceLog = false;
|
clearTraceLog = false;
|
||||||
|
|
||||||
if (res != 1) {
|
if (res != 1) {
|
||||||
if (!res) {
|
if (!res) {
|
||||||
// Use the common format below
|
// Use the common format below
|
||||||
// PrintAndLog("Found valid key:[%d:%c]%012" PRIx64, blockNo, (keyAB & 0x01)?'B':'A', key64);
|
// PrintAndLog("Found valid key:[%d:%c]%012" PRIx64, blockNo, (keyAB & 0x01)?'B':'A', key64);
|
||||||
foundAKey = true;
|
foundAKey = true;
|
||||||
|
|
||||||
// Store the Single Key for display list
|
// Store the Single Key for display list
|
||||||
// For a single block check, SectorsCnt = Sector that contains the block
|
// For a single block check, SectorsCnt = Sector that contains the block
|
||||||
e_sector[SectorsCnt-1].foundKey[(keyAB & 0x01)] = true; // flag key found
|
e_sector[SectorsCnt-1].foundKey[(keyAB & 0x01)] = true; // flag key found
|
||||||
e_sector[SectorsCnt-1].Key[(keyAB & 0x01)] = key64; // Save key data
|
e_sector[SectorsCnt-1].Key[(keyAB & 0x01)] = key64; // Save key data
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PrintAndLog("Command execute timeout");
|
PrintAndLog("Command execute timeout");
|
||||||
|
@ -1327,7 +1328,7 @@ int CmdHF14AMfChk(const char *Cmd)
|
||||||
for (uint16_t t = 0; t < 2; t++) {
|
for (uint16_t t = 0; t < 2; t++) {
|
||||||
if (e_sector[sectorNo].foundKey[t]) {
|
if (e_sector[sectorNo].foundKey[t]) {
|
||||||
num_to_bytes(e_sector[sectorNo].Key[t], 6, block + t * 10);
|
num_to_bytes(e_sector[sectorNo].Key[t], 6, block + t * 10);
|
||||||
keyFoundCount++; // Key found count for information
|
keyFoundCount++; // Key found count for information
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mfEmlSetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
|
mfEmlSetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
|
||||||
|
@ -1355,7 +1356,7 @@ int CmdHF14AMfChk(const char *Cmd)
|
||||||
fclose(fkeys);
|
fclose(fkeys);
|
||||||
PrintAndLog("Found keys have been dumped to file dumpkeys.bin. 0xffffffffffff has been inserted for unknown keys.");
|
PrintAndLog("Found keys have been dumped to file dumpkeys.bin. 0xffffffffffff has been inserted for unknown keys.");
|
||||||
}
|
}
|
||||||
|
|
||||||
free(e_sector);
|
free(e_sector);
|
||||||
free(keyBlock);
|
free(keyBlock);
|
||||||
PrintAndLog("");
|
PrintAndLog("");
|
||||||
|
@ -1710,10 +1711,10 @@ int CmdHF14AMfDbg(const char *Cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
UsbCommand c = {CMD_MIFARE_SET_DBGMODE, {dbgMode, 0, 0}};
|
UsbCommand c = {CMD_MIFARE_SET_DBGMODE, {dbgMode, 0, 0}};
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdHF14AMfEGet(const char *Cmd)
|
int CmdHF14AMfEGet(const char *Cmd)
|
||||||
|
@ -1736,7 +1737,7 @@ int CmdHF14AMfEGet(const char *Cmd)
|
||||||
PrintAndLog("Command execute timeout");
|
PrintAndLog("Command execute timeout");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdHF14AMfEClear(const char *Cmd)
|
int CmdHF14AMfEClear(const char *Cmd)
|
||||||
|
@ -1747,9 +1748,9 @@ int CmdHF14AMfEClear(const char *Cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
UsbCommand c = {CMD_MIFARE_EML_MEMCLR, {0, 0, 0}};
|
UsbCommand c = {CMD_MIFARE_EML_MEMCLR, {0, 0, 0}};
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1956,7 +1957,7 @@ int CmdHF14AMfESave(const char *Cmd)
|
||||||
|
|
||||||
PrintAndLog("Saved %d blocks to file: %s", numBlocks, filename);
|
PrintAndLog("Saved %d blocks to file: %s", numBlocks, filename);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2026,7 +2027,7 @@ int CmdHF14AMfEKeyPrn(const char *Cmd)
|
||||||
case '\0': numSectors = 16; break;
|
case '\0': numSectors = 16; break;
|
||||||
case '2' : numSectors = 32; break;
|
case '2' : numSectors = 32; break;
|
||||||
case '4' : numSectors = 40; break;
|
case '4' : numSectors = 40; break;
|
||||||
case 'd' :
|
case 'd' :
|
||||||
case 'D' : createDumpFile = true; break;
|
case 'D' : createDumpFile = true; break;
|
||||||
}
|
}
|
||||||
cmdp++;
|
cmdp++;
|
||||||
|
@ -3009,51 +3010,130 @@ int CmdHFMFNDEF(const char *cmd) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static command_t CommandTable[] =
|
int CmdHFMFPersonalize(const char *cmd) {
|
||||||
{
|
|
||||||
{"help", CmdHelp, 1, "This help"},
|
CLIParserInit("hf mf personalize",
|
||||||
{"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},
|
"Personalize the UID of a Mifare Classic EV1 card. This is only possible if it is a 7Byte UID card and if it is not already personalized.",
|
||||||
{"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},
|
"Usage:\n\thf mf personalize UIDF0 -> double size UID according to ISO/IEC14443-3\n"
|
||||||
{"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},
|
"\thf mf personalize UIDF1 -> double size UID according to ISO/IEC14443-3, optional usage of selection process shortcut\n"
|
||||||
{"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"},
|
"\thf mf personalize UIDF2 -> single size random ID according to ISO/IEC14443-3\n"
|
||||||
{"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},
|
"\thf mf personalize UIDF3 -> single size NUID according to ISO/IEC14443-3\n"
|
||||||
{"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"},
|
"\thf mf personalize -t B -k B0B1B2B3B4B5 UIDF3 -> use key B = 0xB0B1B2B3B4B5 instead of default key A\n");
|
||||||
{"auth4", CmdHF14AMfAuth4, 0, "ISO14443-4 AES authentication"},
|
|
||||||
{"chk", CmdHF14AMfChk, 0, "Test block keys"},
|
void *argtable[] = {
|
||||||
{"mifare", CmdHF14AMifare, 0, "Read parity error messages."},
|
arg_param_begin,
|
||||||
{"hardnested", CmdHF14AMfNestedHard, 0, "Nested attack for hardened Mifare cards"},
|
arg_str0("tT", "keytype", "<A|B>", "key type (A or B) to authenticate sector 0 (default: A)"),
|
||||||
{"nested", CmdHF14AMfNested, 0, "Test nested authentication"},
|
arg_str0("kK", "key", "<key (hex 6 Bytes)>", "key to authenticate sector 0 (default: FFFFFFFFFFFF)"),
|
||||||
{"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},
|
arg_str1(NULL, NULL, "<UIDF0|UIDF1|UIDF2|UIDF3>", "Personalization Option"),
|
||||||
{"sim", CmdHF14AMfSim, 0, "Simulate MIFARE card"},
|
arg_param_end
|
||||||
{"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory"},
|
};
|
||||||
{"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"},
|
CLIExecWithReturn(cmd, argtable, true);
|
||||||
{"eset", CmdHF14AMfESet, 0, "Set simulator memory block"},
|
|
||||||
{"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"},
|
char keytypestr[2] = "A";
|
||||||
{"esave", CmdHF14AMfESave, 0, "Save to file emul dump"},
|
uint8_t keytype = 0x00;
|
||||||
{"ecfill", CmdHF14AMfECFill, 0, "Fill simulator memory with help of keys from simulator"},
|
int keytypestr_len;
|
||||||
{"ekeyprn", CmdHF14AMfEKeyPrn, 0, "Print keys from simulator memory"},
|
int res = CLIParamStrToBuf(arg_get_str(1), (uint8_t*)keytypestr, 1, &keytypestr_len);
|
||||||
{"cwipe", CmdHF14AMfCWipe, 0, "Wipe magic Chinese card"},
|
if (res || (keytypestr[0] != 'a' && keytypestr[0] != 'A' && keytypestr[0] != 'b' && keytypestr[0] != 'B')) {
|
||||||
{"csetuid", CmdHF14AMfCSetUID, 0, "Set UID for magic Chinese card"},
|
PrintAndLog("ERROR: not a valid key type. Key type must be A or B");
|
||||||
{"csetblk", CmdHF14AMfCSetBlk, 0, "Write block - Magic Chinese card"},
|
CLIParserFree();
|
||||||
{"cgetblk", CmdHF14AMfCGetBlk, 0, "Read block - Magic Chinese card"},
|
return 1;
|
||||||
{"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"},
|
}
|
||||||
{"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"},
|
if (keytypestr[0] == 'B' || keytypestr[0] == 'b') {
|
||||||
{"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"},
|
keytype = 0x01;
|
||||||
{"decrypt", CmdDecryptTraceCmds, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"},
|
}
|
||||||
{"mad", CmdHF14AMfMAD, 0, "Checks and prints MAD"},
|
|
||||||
{"ndef", CmdHFMFNDEF, 0, "Prints NDEF records from card"},
|
uint8_t key[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||||
{NULL, NULL, 0, NULL}
|
int key_len;
|
||||||
|
res = CLIParamHexToBuf(arg_get_str(2), key, 6, &key_len);
|
||||||
|
if (res || (!res && key_len > 0 && key_len != 6)) {
|
||||||
|
PrintAndLog("ERROR: not a valid key. Key must be 12 hex digits");
|
||||||
|
CLIParserFree();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char pers_optionstr[6];
|
||||||
|
int opt_len;
|
||||||
|
uint8_t pers_option;
|
||||||
|
res = CLIParamStrToBuf(arg_get_str(3), (uint8_t*)pers_optionstr, 5, &opt_len);
|
||||||
|
if (res || (!res && opt_len > 0 && opt_len != 5)
|
||||||
|
|| (strncmp(pers_optionstr, "UIDF0", 5) && strncmp(pers_optionstr, "UIDF1", 5) && strncmp(pers_optionstr, "UIDF2", 5) && strncmp(pers_optionstr, "UIDF3", 5))) {
|
||||||
|
PrintAndLog("ERROR: invalid personalization option. Must be one of UIDF0, UIDF1, UIDF2, or UIDF3");
|
||||||
|
CLIParserFree();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!strncmp(pers_optionstr, "UIDF0", 5)) {
|
||||||
|
pers_option = MIFARE_EV1_UIDF0;
|
||||||
|
} else if (!strncmp(pers_optionstr, "UIDF1", 5)) {
|
||||||
|
pers_option = MIFARE_EV1_UIDF1;
|
||||||
|
} else if (!strncmp(pers_optionstr, "UIDF2", 5)) {
|
||||||
|
pers_option = MIFARE_EV1_UIDF2;
|
||||||
|
} else {
|
||||||
|
pers_option = MIFARE_EV1_UIDF3;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLIParserFree();
|
||||||
|
|
||||||
|
UsbCommand c = {CMD_MIFARE_PERSONALIZE_UID, {keytype, pers_option, 0}};
|
||||||
|
memcpy(c.d.asBytes, key, 6);
|
||||||
|
SendCommand(&c);
|
||||||
|
|
||||||
|
UsbCommand resp;
|
||||||
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||||
|
uint8_t isOK = resp.arg[0] & 0xff;
|
||||||
|
PrintAndLog("Personalization %s", isOK ? "FAILED" : "SUCCEEDED");
|
||||||
|
} else {
|
||||||
|
PrintAndLog("Command execute timeout");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static command_t CommandTable[] = {
|
||||||
|
{"help", CmdHelp, 1, "This help"},
|
||||||
|
{"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},
|
||||||
|
{"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},
|
||||||
|
{"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},
|
||||||
|
{"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"},
|
||||||
|
{"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},
|
||||||
|
{"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"},
|
||||||
|
{"auth4", CmdHF14AMfAuth4, 0, "ISO14443-4 AES authentication"},
|
||||||
|
{"chk", CmdHF14AMfChk, 0, "Test block keys"},
|
||||||
|
{"mifare", CmdHF14AMifare, 0, "Read parity error messages."},
|
||||||
|
{"hardnested", CmdHF14AMfNestedHard, 0, "Nested attack for hardened Mifare cards"},
|
||||||
|
{"nested", CmdHF14AMfNested, 0, "Test nested authentication"},
|
||||||
|
{"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},
|
||||||
|
{"sim", CmdHF14AMfSim, 0, "Simulate MIFARE card"},
|
||||||
|
{"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory"},
|
||||||
|
{"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"},
|
||||||
|
{"eset", CmdHF14AMfESet, 0, "Set simulator memory block"},
|
||||||
|
{"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"},
|
||||||
|
{"esave", CmdHF14AMfESave, 0, "Save to file emul dump"},
|
||||||
|
{"ecfill", CmdHF14AMfECFill, 0, "Fill simulator memory with help of keys from simulator"},
|
||||||
|
{"ekeyprn", CmdHF14AMfEKeyPrn, 0, "Print keys from simulator memory"},
|
||||||
|
{"cwipe", CmdHF14AMfCWipe, 0, "Wipe magic Chinese card"},
|
||||||
|
{"csetuid", CmdHF14AMfCSetUID, 0, "Set UID for magic Chinese card"},
|
||||||
|
{"csetblk", CmdHF14AMfCSetBlk, 0, "Write block - Magic Chinese card"},
|
||||||
|
{"cgetblk", CmdHF14AMfCGetBlk, 0, "Read block - Magic Chinese card"},
|
||||||
|
{"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"},
|
||||||
|
{"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"},
|
||||||
|
{"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"},
|
||||||
|
{"decrypt", CmdDecryptTraceCmds, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"},
|
||||||
|
{"mad", CmdHF14AMfMAD, 0, "Checks and prints MAD"},
|
||||||
|
{"ndef", CmdHFMFNDEF, 0, "Prints NDEF records from card"},
|
||||||
|
{"personalize", CmdHFMFPersonalize, 0, "Personalize UID (Mifare Classic EV1 only)"},
|
||||||
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
int CmdHFMF(const char *Cmd)
|
|
||||||
{
|
int CmdHFMF(const char *Cmd) {
|
||||||
(void)WaitForResponseTimeout(CMD_ACK,NULL,100);
|
(void)WaitForResponseTimeout(CMD_ACK,NULL,100);
|
||||||
CmdsParse(CommandTable, Cmd);
|
CmdsParse(CommandTable, Cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdHelp(const char *Cmd)
|
|
||||||
{
|
int CmdHelp(const char *Cmd) {
|
||||||
CmdsHelp(CommandTable);
|
CmdsHelp(CommandTable);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
274
client/util.c
274
client/util.c
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
int ukbhit(void)
|
int ukbhit(void)
|
||||||
|
@ -42,11 +42,11 @@ int ukbhit(void)
|
||||||
Ntty.c_oflag = 0x0000; // output mode
|
Ntty.c_oflag = 0x0000; // output mode
|
||||||
Ntty.c_lflag &= ~ICANON; // control mode = raw
|
Ntty.c_lflag &= ~ICANON; // control mode = raw
|
||||||
Ntty.c_cc[VMIN] = 1; // return if at least 1 character is in the queue
|
Ntty.c_cc[VMIN] = 1; // return if at least 1 character is in the queue
|
||||||
Ntty.c_cc[VTIME] = 0; // no timeout. Wait forever
|
Ntty.c_cc[VTIME] = 0; // no timeout. Wait forever
|
||||||
|
|
||||||
if (0 == (error = tcsetattr(STDIN_FILENO, TCSANOW, &Ntty))) { // set new attributes
|
if (0 == (error = tcsetattr(STDIN_FILENO, TCSANOW, &Ntty))) { // set new attributes
|
||||||
error += ioctl(STDIN_FILENO, FIONREAD, &cnt); // get number of characters availabe
|
error += ioctl(STDIN_FILENO, FIONREAD, &cnt); // get number of characters availabe
|
||||||
error += tcsetattr(STDIN_FILENO, TCSANOW, &Otty); // reset attributes
|
error += tcsetattr(STDIN_FILENO, TCSANOW, &Otty); // reset attributes
|
||||||
}
|
}
|
||||||
|
|
||||||
return ( error == 0 ? cnt : -1 );
|
return ( error == 0 ? cnt : -1 );
|
||||||
|
@ -78,13 +78,13 @@ int ukbhit(void) {
|
||||||
// log files functions
|
// log files functions
|
||||||
void AddLogLine(char *file, char *extData, char *c) {
|
void AddLogLine(char *file, char *extData, char *c) {
|
||||||
FILE *fLog = NULL;
|
FILE *fLog = NULL;
|
||||||
char filename[FILE_PATH_SIZE] = {0x00};
|
char filename[FILE_PATH_SIZE] = {0x00};
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
|
len = strlen(file);
|
||||||
|
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
|
||||||
|
memcpy(filename, file, len);
|
||||||
|
|
||||||
len = strlen(file);
|
|
||||||
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
|
|
||||||
memcpy(filename, file, len);
|
|
||||||
|
|
||||||
fLog = fopen(filename, "a");
|
fLog = fopen(filename, "a");
|
||||||
if (!fLog) {
|
if (!fLog) {
|
||||||
printf("Could not append log file %s", filename);
|
printf("Could not append log file %s", filename);
|
||||||
|
@ -119,10 +119,10 @@ void AddLogCurrentDT(char *fileName) {
|
||||||
|
|
||||||
void FillFileNameByUID(char *fileName, uint8_t *uid, char *ext, int byteCount) {
|
void FillFileNameByUID(char *fileName, uint8_t *uid, char *ext, int byteCount) {
|
||||||
char * fnameptr = fileName;
|
char * fnameptr = fileName;
|
||||||
|
|
||||||
for (int j = 0; j < byteCount; j++, fnameptr += 2)
|
for (int j = 0; j < byteCount; j++, fnameptr += 2)
|
||||||
sprintf(fnameptr, "%02x", (unsigned int) uid[j]);
|
sprintf(fnameptr, "%02x", (unsigned int) uid[j]);
|
||||||
sprintf(fnameptr, "%s", ext);
|
sprintf(fnameptr, "%s", ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fill buffer from structure [{uint8_t data, size_t length},...]
|
// fill buffer from structure [{uint8_t data, size_t length},...]
|
||||||
|
@ -130,25 +130,25 @@ int FillBuffer(uint8_t *data, size_t maxDataLength, size_t *dataLength, ...) {
|
||||||
*dataLength = 0;
|
*dataLength = 0;
|
||||||
va_list valist;
|
va_list valist;
|
||||||
va_start(valist, dataLength);
|
va_start(valist, dataLength);
|
||||||
|
|
||||||
uint8_t *vdata = NULL;
|
uint8_t *vdata = NULL;
|
||||||
size_t vlength = 0;
|
size_t vlength = 0;
|
||||||
do{
|
do{
|
||||||
vdata = va_arg(valist, uint8_t *);
|
vdata = va_arg(valist, uint8_t *);
|
||||||
if (!vdata)
|
if (!vdata)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
vlength = va_arg(valist, size_t);
|
vlength = va_arg(valist, size_t);
|
||||||
if (*dataLength + vlength > maxDataLength) {
|
if (*dataLength + vlength > maxDataLength) {
|
||||||
va_end(valist);
|
va_end(valist);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&data[*dataLength], vdata, vlength);
|
memcpy(&data[*dataLength], vdata, vlength);
|
||||||
*dataLength += vlength;
|
*dataLength += vlength;
|
||||||
|
|
||||||
} while (vdata);
|
} while (vdata);
|
||||||
|
|
||||||
va_end(valist);
|
va_end(valist);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -161,13 +161,13 @@ bool CheckStringIsHEXValue(const char *value) {
|
||||||
|
|
||||||
if (strlen(value) % 2)
|
if (strlen(value) % 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, const size_t hex_max_len,
|
void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, const size_t hex_max_len,
|
||||||
const size_t min_str_len, const size_t spaces_between, bool uppercase) {
|
const size_t min_str_len, const size_t spaces_between, bool uppercase) {
|
||||||
|
|
||||||
char *tmp = (char *)buf;
|
char *tmp = (char *)buf;
|
||||||
size_t i;
|
size_t i;
|
||||||
memset(tmp, 0x00, hex_max_len);
|
memset(tmp, 0x00, hex_max_len);
|
||||||
|
@ -175,17 +175,17 @@ void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex
|
||||||
int maxLen = ( hex_len > hex_max_len) ? hex_max_len : hex_len;
|
int maxLen = ( hex_len > hex_max_len) ? hex_max_len : hex_len;
|
||||||
|
|
||||||
for (i = 0; i < maxLen; ++i, tmp += 2 + spaces_between) {
|
for (i = 0; i < maxLen; ++i, tmp += 2 + spaces_between) {
|
||||||
sprintf(tmp, (uppercase) ? "%02X" : "%02x", (unsigned int) hex_data[i]);
|
sprintf(tmp, (uppercase) ? "%02X" : "%02x", (unsigned int) hex_data[i]);
|
||||||
|
|
||||||
for (int j = 0; j < spaces_between; j++)
|
for (int j = 0; j < spaces_between; j++)
|
||||||
sprintf(tmp + 2 + j, " ");
|
sprintf(tmp + 2 + j, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
i *= (2 + spaces_between);
|
i *= (2 + spaces_between);
|
||||||
int minStrLen = min_str_len > i ? min_str_len : 0;
|
int minStrLen = min_str_len > i ? min_str_len : 0;
|
||||||
if (minStrLen > hex_max_len)
|
if (minStrLen > hex_max_len)
|
||||||
minStrLen = hex_max_len;
|
minStrLen = hex_max_len;
|
||||||
for(; i < minStrLen; i++, tmp += 1)
|
for(; i < minStrLen; i++, tmp += 1)
|
||||||
sprintf(tmp, " ");
|
sprintf(tmp, " ");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -195,7 +195,7 @@ void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex
|
||||||
|
|
||||||
char *sprint_hex(const uint8_t *data, const size_t len) {
|
char *sprint_hex(const uint8_t *data, const size_t len) {
|
||||||
static char buf[4097] = {0};
|
static char buf[4097] = {0};
|
||||||
|
|
||||||
hex_to_buffer((uint8_t *)buf, data, len, sizeof(buf) - 1, 0, 1, false);
|
hex_to_buffer((uint8_t *)buf, data, len, sizeof(buf) - 1, 0, 1, false);
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
|
@ -259,16 +259,16 @@ char *sprint_ascii_ex(const uint8_t *data, const size_t len, const size_t min_st
|
||||||
tmp[i] = ((c < 32) || (c == 127)) ? '.' : c;
|
tmp[i] = ((c < 32) || (c == 127)) ? '.' : c;
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
int minStrLen = min_str_len > i ? min_str_len : 0;
|
int minStrLen = min_str_len > i ? min_str_len : 0;
|
||||||
for(; i < minStrLen; ++i)
|
for(; i < minStrLen; ++i)
|
||||||
tmp[i] = ' ';
|
tmp[i] = ' ';
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *sprint_ascii(const uint8_t *data, const size_t len) {
|
char *sprint_ascii(const uint8_t *data, const size_t len) {
|
||||||
return sprint_ascii_ex(data, len, 0);
|
return sprint_ascii_ex(data, len, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest)
|
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest)
|
||||||
|
@ -290,7 +290,7 @@ uint64_t bytes_to_num(uint8_t* src, size_t len)
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest) {
|
void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest) {
|
||||||
while (len--) {
|
while (len--) {
|
||||||
dest[len] = n & 1;
|
dest[len] = n & 1;
|
||||||
n >>= 1;
|
n >>= 1;
|
||||||
|
@ -333,22 +333,22 @@ uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockS
|
||||||
//assumes little endian
|
//assumes little endian
|
||||||
char *printBits(size_t const size, void const * const ptr)
|
char *printBits(size_t const size, void const * const ptr)
|
||||||
{
|
{
|
||||||
unsigned char *b = (unsigned char*) ptr;
|
unsigned char *b = (unsigned char*) ptr;
|
||||||
unsigned char byte;
|
unsigned char byte;
|
||||||
static char buf[1024];
|
static char buf[1024];
|
||||||
char *tmp = buf;
|
char *tmp = buf;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
for (i=size-1;i>=0;i--)
|
for (i=size-1;i>=0;i--)
|
||||||
{
|
{
|
||||||
for (j=7;j>=0;j--)
|
for (j=7;j>=0;j--)
|
||||||
{
|
{
|
||||||
byte = b[i] & (1<<j);
|
byte = b[i] & (1<<j);
|
||||||
byte >>= j;
|
byte >>= j;
|
||||||
sprintf(tmp, "%u", (unsigned int)byte);
|
sprintf(tmp, "%u", (unsigned int)byte);
|
||||||
tmp++;
|
tmp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,10 +382,10 @@ int param_getptr(const char *line, int *bg, int *en, int paramnum)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int len = strlen(line);
|
int len = strlen(line);
|
||||||
|
|
||||||
*bg = 0;
|
*bg = 0;
|
||||||
*en = 0;
|
*en = 0;
|
||||||
|
|
||||||
// skip spaces
|
// skip spaces
|
||||||
while (line[*bg] ==' ' || line[*bg]=='\t') (*bg)++;
|
while (line[*bg] ==' ' || line[*bg]=='\t') (*bg)++;
|
||||||
if (*bg >= len) {
|
if (*bg >= len) {
|
||||||
|
@ -395,13 +395,13 @@ int param_getptr(const char *line, int *bg, int *en, int paramnum)
|
||||||
for (i = 0; i < paramnum; i++) {
|
for (i = 0; i < paramnum; i++) {
|
||||||
while (line[*bg]!=' ' && line[*bg]!='\t' && line[*bg] != '\0') (*bg)++;
|
while (line[*bg]!=' ' && line[*bg]!='\t' && line[*bg] != '\0') (*bg)++;
|
||||||
while (line[*bg]==' ' || line[*bg]=='\t') (*bg)++;
|
while (line[*bg]==' ' || line[*bg]=='\t') (*bg)++;
|
||||||
|
|
||||||
if (line[*bg] == '\0') return 1;
|
if (line[*bg] == '\0') return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*en = *bg;
|
*en = *bg;
|
||||||
while (line[*en] != ' ' && line[*en] != '\t' && line[*en] != '\0') (*en)++;
|
while (line[*en] != ' ' && line[*en] != '\t' && line[*en] != '\0') (*en)++;
|
||||||
|
|
||||||
(*en)--;
|
(*en)--;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -411,7 +411,7 @@ int param_getptr(const char *line, int *bg, int *en, int paramnum)
|
||||||
int param_getlength(const char *line, int paramnum)
|
int param_getlength(const char *line, int paramnum)
|
||||||
{
|
{
|
||||||
int bg, en;
|
int bg, en;
|
||||||
|
|
||||||
if (param_getptr(line, &bg, &en, paramnum)) return 0;
|
if (param_getptr(line, &bg, &en, paramnum)) return 0;
|
||||||
|
|
||||||
return en - bg + 1;
|
return en - bg + 1;
|
||||||
|
@ -423,12 +423,12 @@ char param_getchar(const char *line, int paramnum) {
|
||||||
|
|
||||||
char param_getchar_indx(const char *line, int indx, int paramnum) {
|
char param_getchar_indx(const char *line, int indx, int paramnum) {
|
||||||
int bg, en;
|
int bg, en;
|
||||||
|
|
||||||
if (param_getptr(line, &bg, &en, paramnum)) return 0x00;
|
if (param_getptr(line, &bg, &en, paramnum)) return 0x00;
|
||||||
|
|
||||||
if (bg + indx > en)
|
if (bg + indx > en)
|
||||||
return '\0';
|
return '\0';
|
||||||
|
|
||||||
return line[bg + indx];
|
return line[bg + indx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,7 +461,7 @@ uint8_t param_isdec(const char *line, int paramnum)
|
||||||
int bg, en;
|
int bg, en;
|
||||||
//TODO, check more thorougly
|
//TODO, check more thorougly
|
||||||
if (!param_getptr(line, &bg, &en, paramnum)) return 1;
|
if (!param_getptr(line, &bg, &en, paramnum)) return 1;
|
||||||
// return strtoul(&line[bg], NULL, 10) & 0xff;
|
// return strtoul(&line[bg], NULL, 10) & 0xff;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -470,7 +470,7 @@ uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base)
|
||||||
{
|
{
|
||||||
int bg, en;
|
int bg, en;
|
||||||
|
|
||||||
if (!param_getptr(line, &bg, &en, paramnum))
|
if (!param_getptr(line, &bg, &en, paramnum))
|
||||||
return strtoul(&line[bg], NULL, base) & 0xff;
|
return strtoul(&line[bg], NULL, base) & 0xff;
|
||||||
else
|
else
|
||||||
return deflt;
|
return deflt;
|
||||||
|
@ -480,7 +480,7 @@ uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base)
|
||||||
{
|
{
|
||||||
int bg, en;
|
int bg, en;
|
||||||
|
|
||||||
if (!param_getptr(line, &bg, &en, paramnum))
|
if (!param_getptr(line, &bg, &en, paramnum))
|
||||||
return strtoul(&line[bg], NULL, base);
|
return strtoul(&line[bg], NULL, base);
|
||||||
else
|
else
|
||||||
return deflt;
|
return deflt;
|
||||||
|
@ -490,30 +490,30 @@ uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base)
|
||||||
{
|
{
|
||||||
int bg, en;
|
int bg, en;
|
||||||
|
|
||||||
if (!param_getptr(line, &bg, &en, paramnum))
|
if (!param_getptr(line, &bg, &en, paramnum))
|
||||||
return strtoull(&line[bg], NULL, base);
|
return strtoull(&line[bg], NULL, base);
|
||||||
else
|
else
|
||||||
return deflt;
|
return deflt;
|
||||||
}
|
}
|
||||||
|
|
||||||
int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt)
|
int param_gethex(const char *line, int paramnum, uint8_t *data, int hexcnt)
|
||||||
{
|
{
|
||||||
int bg, en, temp, i;
|
int bg, en, temp, i;
|
||||||
|
|
||||||
if (hexcnt % 2)
|
if (hexcnt % 2)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (param_getptr(line, &bg, &en, paramnum)) return 1;
|
if (param_getptr(line, &bg, &en, paramnum)) return 1;
|
||||||
|
|
||||||
if (en - bg + 1 != hexcnt)
|
if (en - bg + 1 != hexcnt)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
for(i = 0; i < hexcnt; i += 2) {
|
for(i = 0; i < hexcnt; i += 2) {
|
||||||
if (!(isxdigit((unsigned char)line[bg + i]) && isxdigit((unsigned char)line[bg + i + 1])) ) return 1;
|
if (!(isxdigit((unsigned char)line[bg + i]) && isxdigit((unsigned char)line[bg + i + 1])) ) return 1;
|
||||||
|
|
||||||
sscanf((char[]){line[bg + i], line[bg + i + 1], 0}, "%X", &temp);
|
sscanf((char[]){line[bg + i], line[bg + i + 1], 0}, "%X", &temp);
|
||||||
data[i / 2] = temp & 0xff;
|
data[i / 2] = temp & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -523,22 +523,22 @@ int param_gethex_ex(const char *line, int paramnum, uint8_t *data, int *hexcnt)
|
||||||
int bg, en, temp, i;
|
int bg, en, temp, i;
|
||||||
|
|
||||||
//if (hexcnt % 2)
|
//if (hexcnt % 2)
|
||||||
// return 1;
|
// return 1;
|
||||||
|
|
||||||
if (param_getptr(line, &bg, &en, paramnum)) return 1;
|
if (param_getptr(line, &bg, &en, paramnum)) return 1;
|
||||||
|
|
||||||
if (en - bg + 1 > *hexcnt) return 1;
|
if (en - bg + 1 > *hexcnt) return 1;
|
||||||
|
|
||||||
*hexcnt = en - bg + 1;
|
*hexcnt = en - bg + 1;
|
||||||
if (*hexcnt % 2) //error if not complete hex bytes
|
if (*hexcnt % 2) //error if not complete hex bytes
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
for(i = 0; i < *hexcnt; i += 2) {
|
for(i = 0; i < *hexcnt; i += 2) {
|
||||||
if (!(isxdigit((unsigned char)line[bg + i]) && isxdigit((unsigned char)line[bg + i + 1])) ) return 1;
|
if (!(isxdigit((unsigned char)line[bg + i]) && isxdigit((unsigned char)line[bg + i + 1])) ) return 1;
|
||||||
|
|
||||||
sscanf((char[]){line[bg + i], line[bg + i + 1], 0}, "%X", &temp);
|
sscanf((char[]){line[bg + i], line[bg + i + 1], 0}, "%X", &temp);
|
||||||
data[i / 2] = temp & 0xff;
|
data[i / 2] = temp & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -551,21 +551,21 @@ int param_gethex_to_eol(const char *line, int paramnum, uint8_t * data, int maxd
|
||||||
if (param_getptr(line, &bg, &en, paramnum)) return 1;
|
if (param_getptr(line, &bg, &en, paramnum)) return 1;
|
||||||
|
|
||||||
*datalen = 0;
|
*datalen = 0;
|
||||||
|
|
||||||
int indx = bg;
|
int indx = bg;
|
||||||
while (line[indx]) {
|
while (line[indx]) {
|
||||||
if (line[indx] == '\t' || line[indx] == ' ') {
|
if (line[indx] == '\t' || line[indx] == ' ') {
|
||||||
indx++;
|
indx++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isxdigit((unsigned char)line[indx])) {
|
if (isxdigit((unsigned char)line[indx])) {
|
||||||
buf[strlen(buf) + 1] = 0x00;
|
buf[strlen(buf) + 1] = 0x00;
|
||||||
buf[strlen(buf)] = line[indx];
|
buf[strlen(buf)] = line[indx];
|
||||||
} else {
|
} else {
|
||||||
// if we have symbols other than spaces and hex
|
// if we have symbols other than spaces and hex
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*datalen >= maxdatalen) {
|
if (*datalen >= maxdatalen) {
|
||||||
// if we dont have space in buffer and have symbols to translate
|
// if we dont have space in buffer and have symbols to translate
|
||||||
|
@ -578,14 +578,14 @@ int param_gethex_to_eol(const char *line, int paramnum, uint8_t * data, int maxd
|
||||||
*buf = 0;
|
*buf = 0;
|
||||||
(*datalen)++;
|
(*datalen)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
indx++;
|
indx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(buf) > 0)
|
if (strlen(buf) > 0)
|
||||||
//error when not completed hex bytes
|
//error when not completed hex bytes
|
||||||
return 3;
|
return 3;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,7 +593,7 @@ int param_getstr(const char *line, int paramnum, char * str, size_t buffersize)
|
||||||
{
|
{
|
||||||
int bg, en;
|
int bg, en;
|
||||||
|
|
||||||
if (param_getptr(line, &bg, &en, paramnum)) {
|
if (param_getptr(line, &bg, &en, paramnum)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -602,10 +602,10 @@ int param_getstr(const char *line, int paramnum, char * str, size_t buffersize)
|
||||||
printf("out of bounds error: want %d bytes have %zd bytes\n", en - bg + 1 + 1, buffersize);
|
printf("out of bounds error: want %d bytes have %zd bytes\n", en - bg + 1 + 1, buffersize);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(str, line + bg, en - bg + 1);
|
memcpy(str, line + bg, en - bg + 1);
|
||||||
str[en - bg + 1] = 0;
|
str[en - bg + 1] = 0;
|
||||||
|
|
||||||
return en - bg + 1;
|
return en - bg + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,100 +618,100 @@ https://github.com/ApertureLabsLtd/RFIDler/blob/master/firmware/Pic32/RFIDler.X/
|
||||||
// returns number of bits converted
|
// returns number of bits converted
|
||||||
int hextobinarray(char *target, char *source)
|
int hextobinarray(char *target, char *source)
|
||||||
{
|
{
|
||||||
int length, i, count= 0;
|
int length, i, count= 0;
|
||||||
char* start = source;
|
char* start = source;
|
||||||
char x;
|
char x;
|
||||||
|
|
||||||
length = strlen(source);
|
length = strlen(source);
|
||||||
// process 4 bits (1 hex digit) at a time
|
// process 4 bits (1 hex digit) at a time
|
||||||
while(length--)
|
while(length--)
|
||||||
{
|
{
|
||||||
x= *(source++);
|
x= *(source++);
|
||||||
// capitalize
|
// capitalize
|
||||||
if (x >= 'a' && x <= 'f')
|
if (x >= 'a' && x <= 'f')
|
||||||
x -= 32;
|
x -= 32;
|
||||||
// convert to numeric value
|
// convert to numeric value
|
||||||
if (x >= '0' && x <= '9')
|
if (x >= '0' && x <= '9')
|
||||||
x -= '0';
|
x -= '0';
|
||||||
else if (x >= 'A' && x <= 'F')
|
else if (x >= 'A' && x <= 'F')
|
||||||
x -= 'A' - 10;
|
x -= 'A' - 10;
|
||||||
else {
|
else {
|
||||||
printf("Discovered unknown character %c %d at idx %tu of %s\n", x, x, source - start, start);
|
printf("Discovered unknown character %c %d at idx %tu of %s\n", x, x, source - start, start);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// output
|
// output
|
||||||
for(i= 0 ; i < 4 ; ++i, ++count)
|
for(i= 0 ; i < 4 ; ++i, ++count)
|
||||||
*(target++)= (x >> (3 - i)) & 1;
|
*(target++)= (x >> (3 - i)) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert binary array of 0x00/0x01 values to hex (safe to do in place as target will always be shorter than source)
|
// convert binary array of 0x00/0x01 values to hex (safe to do in place as target will always be shorter than source)
|
||||||
// return number of bits converted
|
// return number of bits converted
|
||||||
int binarraytohex(char *target,char *source, int length)
|
int binarraytohex(char *target,char *source, int length)
|
||||||
{
|
{
|
||||||
unsigned char i, x;
|
unsigned char i, x;
|
||||||
int j = length;
|
int j = length;
|
||||||
|
|
||||||
if(j % 4)
|
if(j % 4)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
while(j)
|
while(j)
|
||||||
{
|
{
|
||||||
for(i= x= 0 ; i < 4 ; ++i)
|
for(i= x= 0 ; i < 4 ; ++i)
|
||||||
x += ( source[i] << (3 - i));
|
x += ( source[i] << (3 - i));
|
||||||
sprintf(target,"%X", (unsigned int)x);
|
sprintf(target,"%X", (unsigned int)x);
|
||||||
++target;
|
++target;
|
||||||
source += 4;
|
source += 4;
|
||||||
j -= 4;
|
j -= 4;
|
||||||
}
|
}
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return parity bit required to match type
|
// return parity bit required to match type
|
||||||
uint8_t GetParity( uint8_t *bits, uint8_t type, int length)
|
uint8_t GetParity( uint8_t *bits, uint8_t type, int length)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
for(x= 0 ; length > 0 ; --length)
|
for(x= 0 ; length > 0 ; --length)
|
||||||
x += bits[length - 1];
|
x += bits[length - 1];
|
||||||
x %= 2;
|
x %= 2;
|
||||||
|
|
||||||
return x ^ type;
|
return x ^ type;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add HID parity to binary array: EVEN prefix for 1st half of ID, ODD suffix for 2nd half
|
// add HID parity to binary array: EVEN prefix for 1st half of ID, ODD suffix for 2nd half
|
||||||
void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length)
|
void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length)
|
||||||
{
|
{
|
||||||
*(target++)= GetParity(source, EVEN, length / 2);
|
*(target++)= GetParity(source, EVEN, length / 2);
|
||||||
memcpy(target, source, length);
|
memcpy(target, source, length);
|
||||||
target += length;
|
target += length;
|
||||||
*(target)= GetParity(source + length / 2, ODD, length / 2);
|
*(target)= GetParity(source + length / 2, ODD, length / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// xor two arrays together for len items. The dst array contains the new xored values.
|
// xor two arrays together for len items. The dst array contains the new xored values.
|
||||||
void xor(unsigned char *dst, unsigned char *src, size_t len) {
|
void xor(unsigned char *dst, unsigned char *src, size_t len) {
|
||||||
for( ; len > 0; len--,dst++,src++)
|
for( ; len > 0; len--,dst++,src++)
|
||||||
*dst ^= *src;
|
*dst ^= *src;
|
||||||
}
|
}
|
||||||
|
|
||||||
// RotateLeft - Ultralight, Desfire, works on byte level
|
// RotateLeft - Ultralight, Desfire, works on byte level
|
||||||
// 00-01-02 >> 01-02-00
|
// 00-01-02 >> 01-02-00
|
||||||
void rol(uint8_t *data, const size_t len){
|
void rol(uint8_t *data, const size_t len){
|
||||||
uint8_t first = data[0];
|
uint8_t first = data[0];
|
||||||
for (size_t i = 0; i < len-1; i++) {
|
for (size_t i = 0; i < len-1; i++) {
|
||||||
data[i] = data[i+1];
|
data[i] = data[i+1];
|
||||||
}
|
}
|
||||||
data[len-1] = first;
|
data[len-1] = first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Replace unprintable characters with a dot in char buffer
|
// Replace unprintable characters with a dot in char buffer
|
||||||
void clean_ascii(unsigned char *buf, size_t len) {
|
void clean_ascii(unsigned char *buf, size_t len) {
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
if (!isprint(buf[i]))
|
if (!isprint(buf[i]))
|
||||||
buf[i] = '.';
|
buf[i] = '.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -724,8 +724,8 @@ void strcleanrn(char *buf, size_t len) {
|
||||||
// replace char in buffer
|
// replace char in buffer
|
||||||
void strcreplace(char *buf, size_t len, char from, char to) {
|
void strcreplace(char *buf, size_t len, char from, char to) {
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
if (buf[i] == from)
|
if (buf[i] == from)
|
||||||
buf[i] = to;
|
buf[i] = to;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -734,7 +734,7 @@ char *strmcopy(char *buf) {
|
||||||
if ((str = (char*) malloc(strlen(buf) + 1)) != NULL) {
|
if ((str = (char*) malloc(strlen(buf) + 1)) != NULL) {
|
||||||
memset(str, 0, strlen(buf) + 1);
|
memset(str, 0, strlen(buf) + 1);
|
||||||
strcpy(str, buf);
|
strcpy(str, buf);
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,10 @@ NXP/Philips CUSTOM COMMANDS
|
||||||
#define MIFARE_CMD_TRANSFER 0xB0
|
#define MIFARE_CMD_TRANSFER 0xB0
|
||||||
|
|
||||||
#define MIFARE_EV1_PERSONAL_UID 0x40
|
#define MIFARE_EV1_PERSONAL_UID 0x40
|
||||||
|
#define MIFARE_EV1_UIDF0 0x00
|
||||||
|
#define MIFARE_EV1_UIDF1 0x40
|
||||||
|
#define MIFARE_EV1_UIDF2 0x20
|
||||||
|
#define MIFARE_EV1_UIDF3 0x60
|
||||||
#define MIFARE_EV1_SETMODE 0x43
|
#define MIFARE_EV1_SETMODE 0x43
|
||||||
|
|
||||||
#define MIFARE_ULC_WRITE 0xA2
|
#define MIFARE_ULC_WRITE 0xA2
|
||||||
|
|
|
@ -197,17 +197,17 @@ typedef struct{
|
||||||
#define CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES 0x0613
|
#define CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES 0x0613
|
||||||
|
|
||||||
#define CMD_MIFARE_READBL 0x0620
|
#define CMD_MIFARE_READBL 0x0620
|
||||||
#define CMD_MIFAREU_READBL 0x0720
|
|
||||||
#define CMD_MIFARE_READSC 0x0621
|
#define CMD_MIFARE_READSC 0x0621
|
||||||
#define CMD_MIFAREU_READCARD 0x0721
|
|
||||||
#define CMD_MIFARE_WRITEBL 0x0622
|
#define CMD_MIFARE_WRITEBL 0x0622
|
||||||
|
#define CMD_MIFARE_CHKKEYS 0x0623
|
||||||
|
#define CMD_MIFARE_PERSONALIZE_UID 0x0624
|
||||||
|
#define CMD_MIFARE_SNIFFER 0x0630
|
||||||
|
|
||||||
|
//ultralightC
|
||||||
|
#define CMD_MIFAREU_READBL 0x0720
|
||||||
|
#define CMD_MIFAREU_READCARD 0x0721
|
||||||
#define CMD_MIFAREU_WRITEBL 0x0722
|
#define CMD_MIFAREU_WRITEBL 0x0722
|
||||||
#define CMD_MIFAREU_WRITEBL_COMPAT 0x0723
|
#define CMD_MIFAREU_WRITEBL_COMPAT 0x0723
|
||||||
|
|
||||||
#define CMD_MIFARE_CHKKEYS 0x0623
|
|
||||||
|
|
||||||
#define CMD_MIFARE_SNIFFER 0x0630
|
|
||||||
//ultralightC
|
|
||||||
#define CMD_MIFAREUC_AUTH 0x0724
|
#define CMD_MIFAREUC_AUTH 0x0724
|
||||||
//0x0725 and 0x0726 no longer used
|
//0x0725 and 0x0726 no longer used
|
||||||
#define CMD_MIFAREUC_SETPWD 0x0727
|
#define CMD_MIFAREUC_SETPWD 0x0727
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue