fix hf mf sim

* NAK on unknown commands
* allow unencrypted HALT
* don't display messages during simulation (or we will miss next reader command)
This commit is contained in:
pwpiwi 2019-04-08 19:51:53 +02:00
commit ab71bc71cf
5 changed files with 80 additions and 73 deletions

View file

@ -30,6 +30,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Added `hf plot` (piwi) - Added `hf plot` (piwi)
- Added `hf mfp mad` `hf mf mad` parsing MAD1 and MAD2 (Merlok) - Added `hf mfp mad` `hf mf mad` parsing MAD1 and MAD2 (Merlok)
- Added `hf mfp ndef` `hf mf ndef` parsing NDEF records (Merlok) - Added `hf mfp ndef` `hf mf ndef` parsing NDEF records (Merlok)
- Added Mifare Mini, Mifare 2K and 4K support to `hf mf sim` (piwi)
## [v3.1.0][2018-10-10] ## [v3.1.0][2018-10-10]

View file

@ -884,7 +884,6 @@ static int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int
} }
static int EmSend4bitEx(uint8_t resp);
int EmSend4bit(uint8_t resp); int EmSend4bit(uint8_t resp);
static int EmSendCmdExPar(uint8_t *resp, uint16_t respLen, uint8_t *par); static int EmSendCmdExPar(uint8_t *resp, uint16_t respLen, uint8_t *par);
int EmSendCmdEx(uint8_t *resp, uint16_t respLen); int EmSendCmdEx(uint8_t *resp, uint16_t respLen);
@ -1413,16 +1412,14 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity)
UartInit(received, parity); UartInit(received, parity);
// Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN // Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN
do { while (GetCountSspClk() < LastTimeProxToAirStart + LastProxToAirDuration + (FpgaSendQueueDelay>>3)) /* wait */ ;
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = SEC_F;
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; (void) b;
}
} while (GetCountSspClk() < LastTimeProxToAirStart + LastProxToAirDuration + (FpgaSendQueueDelay>>3));
// Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen
// only, since we are receiving, not transmitting). // only, since we are receiving, not transmitting).
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
// Clear RXRDY
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; (void)b;
for(;;) { for(;;) {
WDT_HIT(); WDT_HIT();
@ -1522,7 +1519,7 @@ static int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen)
} }
static int EmSend4bitEx(uint8_t resp){ int EmSend4bit(uint8_t resp){
Code4bitAnswerAsTag(resp); Code4bitAnswerAsTag(resp);
int res = EmSendCmd14443aRaw(ToSend, ToSendMax); int res = EmSendCmd14443aRaw(ToSend, ToSendMax);
// do the tracing for the previous reader request and this tag answer: // do the tracing for the previous reader request and this tag answer:
@ -1531,11 +1528,6 @@ static int EmSend4bitEx(uint8_t resp){
} }
int EmSend4bit(uint8_t resp){
return EmSend4bitEx(resp);
}
static int EmSendCmdExPar(uint8_t *resp, uint16_t respLen, uint8_t *par){ static int EmSendCmdExPar(uint8_t *resp, uint16_t respLen, uint8_t *par){
CodeIso14443aAsTagPar(resp, respLen, par); CodeIso14443aAsTagPar(resp, respLen, par);
int res = EmSendCmd14443aRaw(ToSend, ToSendMax); int res = EmSendCmd14443aRaw(ToSend, ToSendMax);

View file

@ -221,7 +221,7 @@ static void MifareSimInit(uint8_t flags, uint8_t *datain, tag_response_info_t **
case 4: case 4:
*cuid = bytes_to_num(rUIDBCC1, 4); *cuid = bytes_to_num(rUIDBCC1, 4);
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
if (MF_DBGLEVEL >= 2) { if (MF_DBGLEVEL >= MF_DBG_INFO) {
Dbprintf("4B UID: %02x%02x%02x%02x", Dbprintf("4B UID: %02x%02x%02x%02x",
rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3] ); rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3] );
} }
@ -230,7 +230,7 @@ static void MifareSimInit(uint8_t flags, uint8_t *datain, tag_response_info_t **
*cuid = bytes_to_num(rUIDBCC2, 4); *cuid = bytes_to_num(rUIDBCC2, 4);
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
if (MF_DBGLEVEL >= 2) { if (MF_DBGLEVEL >= MF_DBG_INFO) {
Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x", Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x",
rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], rUIDBCC2[0], rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3] ); rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], rUIDBCC2[0], rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3] );
} }
@ -247,12 +247,12 @@ static void MifareSimInit(uint8_t flags, uint8_t *datain, tag_response_info_t **
default: rSAKfinal[0] = 0x08; // Mifare 1K default: rSAKfinal[0] = 0x08; // Mifare 1K
} }
ComputeCrc14443(CRC_14443_A, rSAKfinal, 1, rSAKfinal + 1, rSAKfinal + 2); ComputeCrc14443(CRC_14443_A, rSAKfinal, 1, rSAKfinal + 1, rSAKfinal + 2);
if (MF_DBGLEVEL >= 2) { if (MF_DBGLEVEL >= MF_DBG_INFO) {
Dbprintf("SAK: %02x", rSAKfinal[0]); Dbprintf("SAK: %02x", rSAKfinal[0]);
} }
// set SAK for incomplete UID // set SAK for incomplete UID
rSAK1[0] = 0x04; // Bit 3 indicates incomplete UID rSAK1[0] = 0x04; // Bit 3 indicates incomplete UID
ComputeCrc14443(CRC_14443_A, rSAK1, 1, rSAK1 + 1, rSAK1 + 2); ComputeCrc14443(CRC_14443_A, rSAK1, 1, rSAK1 + 1, rSAK1 + 2);
// set ATQA based on cardsize and UIDlen // set ATQA based on cardsize and UIDlen
@ -264,10 +264,10 @@ static void MifareSimInit(uint8_t flags, uint8_t *datain, tag_response_info_t **
if (*uid_len == 7) { if (*uid_len == 7) {
rATQA[0] |= 0x40; rATQA[0] |= 0x40;
} }
if (MF_DBGLEVEL >= 2) { if (MF_DBGLEVEL >= MF_DBG_INFO) {
Dbprintf("ATQA: %02x %02x", rATQA[1], rATQA[0]); Dbprintf("ATQA: %02x %02x", rATQA[1], rATQA[0]);
} }
static tag_response_info_t responses_init[TAG_RESPONSE_COUNT] = { static tag_response_info_t responses_init[TAG_RESPONSE_COUNT] = {
{ .response = rATQA, .response_n = sizeof(rATQA) }, // Answer to request - respond with card type { .response = rATQA, .response_n = sizeof(rATQA) }, // Answer to request - respond with card type
{ .response = rUIDBCC1, .response_n = sizeof(rUIDBCC1) }, // Anticollision cascade1 - respond with first part of uid { .response = rUIDBCC1, .response_n = sizeof(rUIDBCC1) }, // Anticollision cascade1 - respond with first part of uid
@ -322,7 +322,7 @@ static bool HasValidCRC(uint8_t *receivedCmd, uint16_t receivedCmd_len) {
void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t *datain) void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t *datain)
{ {
LED_A_ON(); LED_A_ON();
tag_response_info_t *responses; tag_response_info_t *responses;
uint8_t uid_len = 4; uint8_t uid_len = 4;
uint32_t cuid = 0; uint32_t cuid = 0;
@ -349,7 +349,7 @@ void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t
uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00}; uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00};
int num_blocks = ParamCardSizeBlocks(cardsize); int num_blocks = ParamCardSizeBlocks(cardsize);
// Here we collect UID, sector, keytype, NT, AR, NR, NT2, AR2, NR2 // Here we collect UID, sector, keytype, NT, AR, NR, NT2, AR2, NR2
// This will be used in the reader-only attack. // This will be used in the reader-only attack.
@ -405,15 +405,17 @@ void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t
continue; continue;
} }
FpgaEnableTracing();
//Now, get data //Now, get data
FpgaEnableTracing();
int res = EmGetCmd(receivedCmd, &receivedCmd_len, receivedCmd_par); int res = EmGetCmd(receivedCmd, &receivedCmd_len, receivedCmd_par);
if (res == 2) { //Field is off! if (res == 2) { //Field is off!
FpgaDisableTracing();
LED_D_OFF(); LED_D_OFF();
cardSTATE = MFEMUL_NOFIELD; cardSTATE = MFEMUL_NOFIELD;
continue; continue;
} else if (res == 1) { // button pressed } else if (res == 1) { // button pressed
FpgaDisableTracing();
button_pushed = true; button_pushed = true;
break; break;
} }
@ -439,48 +441,48 @@ void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t
case MFEMUL_IDLE:{ case MFEMUL_IDLE:{
break; break;
} }
case MFEMUL_SELECT1:{ case MFEMUL_SELECT1:{
// select all - 0x93 0x20 // select all - 0x93 0x20
if (receivedCmd_len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x20)) { if (receivedCmd_len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x20)) {
if (MF_DBGLEVEL >= 4) Dbprintf("SELECT ALL CL1 received");
EmSendPrecompiledCmd(&responses[UIDBCC1]); EmSendPrecompiledCmd(&responses[UIDBCC1]);
FpgaDisableTracing(); FpgaDisableTracing();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SELECT ALL CL1 received");
break; break;
} }
// select card - 0x93 0x70 ... // select card - 0x93 0x70 ...
if (receivedCmd_len == 9 && if (receivedCmd_len == 9 &&
(receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], responses[UIDBCC1].response, 4) == 0)) { (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], responses[UIDBCC1].response, 4) == 0)) {
if (MF_DBGLEVEL >= 4) Dbprintf("SELECT CL1 %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]);
if (uid_len == 4) { if (uid_len == 4) {
EmSendPrecompiledCmd(&responses[SAKfinal]); EmSendPrecompiledCmd(&responses[SAKfinal]);
FpgaDisableTracing();
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
break;
} else if (uid_len == 7) { } else if (uid_len == 7) {
EmSendPrecompiledCmd(&responses[SAK1]); EmSendPrecompiledCmd(&responses[SAK1]);
FpgaDisableTracing(); cardSTATE = MFEMUL_SELECT2;
cardSTATE = MFEMUL_SELECT2;
break;
} }
FpgaDisableTracing();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SELECT CL1 %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]);
break;
} }
cardSTATE = MFEMUL_IDLE; cardSTATE = MFEMUL_IDLE;
break; break;
} }
case MFEMUL_SELECT2:{ case MFEMUL_SELECT2:{
// select all cl2 - 0x95 0x20 // select all cl2 - 0x95 0x20
if (receivedCmd_len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x20)) { if (receivedCmd_len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x20)) {
if (MF_DBGLEVEL >= 4) Dbprintf("SELECT ALL CL2 received");
EmSendPrecompiledCmd(&responses[UIDBCC2]); EmSendPrecompiledCmd(&responses[UIDBCC2]);
FpgaDisableTracing(); FpgaDisableTracing();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SELECT ALL CL2 received");
break; break;
} }
// select cl2 card - 0x95 0x70 xxxxxxxxxxxx // select cl2 card - 0x95 0x70 xxxxxxxxxxxx
if (receivedCmd_len == 9 && if (receivedCmd_len == 9 &&
(receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], responses[UIDBCC2].response, 4) == 0)) { (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], responses[UIDBCC2].response, 4) == 0)) {
if (uid_len == 7) { if (uid_len == 7) {
if (MF_DBGLEVEL >= 4) Dbprintf("SELECT CL2 %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]);
EmSendPrecompiledCmd(&responses[SAKfinal]); EmSendPrecompiledCmd(&responses[SAKfinal]);
FpgaDisableTracing(); FpgaDisableTracing();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SELECT CL2 %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]);
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
break; break;
} }
@ -488,9 +490,9 @@ void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t
cardSTATE = MFEMUL_IDLE; cardSTATE = MFEMUL_IDLE;
break; break;
} }
case MFEMUL_WORK:{ case MFEMUL_WORK:{
if (receivedCmd_len != 4) { // all commands must have exactly 4 bytes if (receivedCmd_len != 4) { // all commands must have exactly 4 bytes
FpgaDisableTracing();
break; break;
} }
bool encrypted_data = (cardAUTHKEY != AUTHKEYNONE) ; bool encrypted_data = (cardAUTHKEY != AUTHKEYNONE) ;
@ -502,16 +504,16 @@ void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t
} }
if (!HasValidCRC(receivedCmd_dec, receivedCmd_len)) { // all commands must have a valid CRC if (!HasValidCRC(receivedCmd_dec, receivedCmd_len)) { // all commands must have a valid CRC
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_TR)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_TR));
FpgaDisableTracing();
break; break;
} }
if (receivedCmd_dec[0] == MIFARE_AUTH_KEYA || receivedCmd_dec[0] == MIFARE_AUTH_KEYB) { if (receivedCmd_dec[0] == MIFARE_AUTH_KEYA || receivedCmd_dec[0] == MIFARE_AUTH_KEYB) {
// if authenticating to a block that shouldn't exist - as long as we are not doing the reader attack // if authenticating to a block that shouldn't exist - as long as we are not doing the reader attack
if (receivedCmd_dec[1] >= num_blocks && !(flags & FLAG_NR_AR_ATTACK)) { if (receivedCmd_dec[1] >= num_blocks && !(flags & FLAG_NR_AR_ATTACK)) {
//is this the correct response to an auth on a out of range block? marshmellow //is this the correct response to an auth on a out of range block? marshmellow
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
FpgaDisableTracing(); FpgaDisableTracing();
if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], receivedCmd_dec[1]); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], receivedCmd_dec[1]);
break; break;
} }
cardAUTHSC = BlockToSector(receivedCmd_dec[1]); // received block num cardAUTHSC = BlockToSector(receivedCmd_dec[1]); // received block num
@ -519,27 +521,31 @@ void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t
crypto1_destroy(pcs);//Added by martin crypto1_destroy(pcs);//Added by martin
crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY)); crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY));
if (!encrypted_data) { // first authentication if (!encrypted_data) { // first authentication
if (MF_DBGLEVEL >= 4) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY);
crypto1_word(pcs, cuid ^ nonce, 0); // Update crypto state crypto1_word(pcs, cuid ^ nonce, 0); // Update crypto state
num_to_bytes(nonce, 4, rAUTH_AT); // Send unencrypted nonce num_to_bytes(nonce, 4, rAUTH_AT); // Send unencrypted nonce
EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
FpgaDisableTracing();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY);
} else { // nested authentication } else { // nested authentication
if (MF_DBGLEVEL >= 4) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %d", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY);
num_to_bytes(nonce, sizeof(nonce), response); num_to_bytes(nonce, sizeof(nonce), response);
uint8_t pcs_in[4] = {0}; uint8_t pcs_in[4] = {0};
num_to_bytes(cuid ^ nonce, sizeof(nonce), pcs_in); num_to_bytes(cuid ^ nonce, sizeof(nonce), pcs_in);
mf_crypto1_encryptEx(pcs, response, pcs_in, sizeof(nonce), response_par); mf_crypto1_encryptEx(pcs, response, pcs_in, sizeof(nonce), response_par);
EmSendCmdPar(response, sizeof(nonce), response_par); // send encrypted nonce EmSendCmdPar(response, sizeof(nonce), response_par); // send encrypted nonce
FpgaDisableTracing();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %d", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY);
} }
FpgaDisableTracing();
cardSTATE = MFEMUL_AUTH1; cardSTATE = MFEMUL_AUTH1;
break; break;
} }
if (!encrypted_data) { // all other commands must be encrypted (authenticated) // halt can be sent encrypted or in clear
FpgaDisableTracing(); if (receivedCmd_dec[0] == ISO14443A_CMD_HALT && receivedCmd_dec[1] == 0x00) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("--> HALTED.");
cardSTATE = MFEMUL_HALTED;
break; break;
} }
if(receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK if(receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK
|| receivedCmd_dec[0] == ISO14443A_CMD_WRITEBLOCK || receivedCmd_dec[0] == ISO14443A_CMD_WRITEBLOCK
|| receivedCmd_dec[0] == MIFARE_CMD_INC || receivedCmd_dec[0] == MIFARE_CMD_INC
@ -549,21 +555,19 @@ void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t
if (receivedCmd_dec[1] >= num_blocks) { if (receivedCmd_dec[1] >= num_blocks) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
FpgaDisableTracing(); FpgaDisableTracing();
if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking",receivedCmd_dec[0],receivedCmd_dec[1],receivedCmd_dec[1]); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking",receivedCmd_dec[0],receivedCmd_dec[1],receivedCmd_dec[1]);
break; break;
} }
if (BlockToSector(receivedCmd_dec[1]) != cardAUTHSC) { if (BlockToSector(receivedCmd_dec[1]) != cardAUTHSC) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
FpgaDisableTracing(); FpgaDisableTracing();
if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02x) on block (0x%02x) not authenticated for (0x%02x), nacking",receivedCmd_dec[0],receivedCmd_dec[1],cardAUTHSC); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader tried to operate (0x%02x) on block (0x%02x) not authenticated for (0x%02x), nacking",receivedCmd_dec[0],receivedCmd_dec[1],cardAUTHSC);
break; break;
} }
} }
if (receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK) { if (receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK) {
uint8_t blockNo = receivedCmd_dec[1]; uint8_t blockNo = receivedCmd_dec[1];
if (MF_DBGLEVEL >= 4) {
Dbprintf("Reader reading block %d (0x%02x)", blockNo, blockNo);
}
emlGetMem(response, blockNo, 1); emlGetMem(response, blockNo, 1);
if (IsSectorTrailer(blockNo)) { if (IsSectorTrailer(blockNo)) {
memset(response, 0x00, 6); // keyA can never be read memset(response, 0x00, 6); // keyA can never be read
@ -582,6 +586,9 @@ void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t
mf_crypto1_encrypt(pcs, response, 18, response_par); mf_crypto1_encrypt(pcs, response, 18, response_par);
EmSendCmdPar(response, 18, response_par); EmSendCmdPar(response, 18, response_par);
FpgaDisableTracing(); FpgaDisableTracing();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("Reader reading block %d (0x%02x)", blockNo, blockNo);
}
numReads++; numReads++;
if(exitAfterNReads > 0 && numReads == exitAfterNReads) { if(exitAfterNReads > 0 && numReads == exitAfterNReads) {
Dbprintf("%d reads done, exiting", numReads); Dbprintf("%d reads done, exiting", numReads);
@ -589,26 +596,33 @@ void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t
} }
break; break;
} }
if (receivedCmd_dec[0] == ISO14443A_CMD_WRITEBLOCK) { if (receivedCmd_dec[0] == ISO14443A_CMD_WRITEBLOCK) {
uint8_t blockNo = receivedCmd_dec[1]; uint8_t blockNo = receivedCmd_dec[1];
if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0xA0 write block %d (%02x)", blockNo, blockNo);
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
FpgaDisableTracing(); FpgaDisableTracing();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("RECV 0xA0 write block %d (%02x)", blockNo, blockNo);
cardWRBL = blockNo; cardWRBL = blockNo;
cardSTATE = MFEMUL_WRITEBL2; cardSTATE = MFEMUL_WRITEBL2;
break; break;
} }
if (receivedCmd_dec[0] == MIFARE_CMD_INC || receivedCmd_dec[0] == MIFARE_CMD_DEC || receivedCmd_dec[0] == MIFARE_CMD_RESTORE) { if (receivedCmd_dec[0] == MIFARE_CMD_INC || receivedCmd_dec[0] == MIFARE_CMD_DEC || receivedCmd_dec[0] == MIFARE_CMD_RESTORE) {
uint8_t blockNo = receivedCmd_dec[1]; uint8_t blockNo = receivedCmd_dec[1];
if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)",receivedCmd_dec[0], blockNo, blockNo);
if (emlCheckValBl(blockNo)) { if (emlCheckValBl(blockNo)) {
if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate on block, but emlCheckValBl failed, nacking");
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
FpgaDisableTracing(); FpgaDisableTracing();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)",receivedCmd_dec[0], blockNo, blockNo);
}
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader tried to operate on block, but emlCheckValBl failed, nacking");
break; break;
} }
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
FpgaDisableTracing(); FpgaDisableTracing();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)",receivedCmd_dec[0], blockNo, blockNo);
}
cardWRBL = blockNo; cardWRBL = blockNo;
if (receivedCmd_dec[0] == MIFARE_CMD_INC) if (receivedCmd_dec[0] == MIFARE_CMD_INC)
cardSTATE = MFEMUL_INTREG_INC; cardSTATE = MFEMUL_INTREG_INC;
@ -618,27 +632,24 @@ void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t
cardSTATE = MFEMUL_INTREG_REST; cardSTATE = MFEMUL_INTREG_REST;
break; break;
} }
if (receivedCmd_dec[0] == MIFARE_CMD_TRANSFER) { if (receivedCmd_dec[0] == MIFARE_CMD_TRANSFER) {
uint8_t blockNo = receivedCmd_dec[1]; uint8_t blockNo = receivedCmd_dec[1];
if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x transfer block %d (%02x)",receivedCmd_dec[0], blockNo, blockNo);
if (emlSetValBl(cardINTREG, cardINTBLOCK, receivedCmd_dec[1])) if (emlSetValBl(cardINTREG, cardINTBLOCK, receivedCmd_dec[1]))
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
else else
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
FpgaDisableTracing(); FpgaDisableTracing();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("RECV 0x%02x transfer block %d (%02x)",receivedCmd_dec[0], blockNo, blockNo);
break; break;
} }
// halt
if (receivedCmd_dec[0] == ISO14443A_CMD_HALT && receivedCmd_dec[1] == 0x00) {
if (MF_DBGLEVEL >= 4) Dbprintf("--> HALTED.");
cardSTATE = MFEMUL_HALTED;
break;
}
// command not allowed // command not allowed
if (MF_DBGLEVEL >= 4) Dbprintf("Received command not allowed, nacking"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Received command not allowed, nacking");
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
break; break;
} }
case MFEMUL_AUTH1:{ case MFEMUL_AUTH1:{
if (receivedCmd_len != 8) { if (receivedCmd_len != 8) {
cardSTATE = MFEMUL_IDLE; cardSTATE = MFEMUL_IDLE;
@ -716,7 +727,7 @@ void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t
// test if auth OK // test if auth OK
if (cardRr != prng_successor(nonce, 64)){ if (cardRr != prng_successor(nonce, 64)){
if (MF_DBGLEVEL >= 2) Dbprintf("AUTH FAILED for sector %d with key %c. cardRr=%08x, succ=%08x", if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("AUTH FAILED for sector %d with key %c. cardRr=%08x, succ=%08x",
cardAUTHSC, cardAUTHKEY == AUTHKEYA ? 'A' : 'B', cardAUTHSC, cardAUTHKEY == AUTHKEYA ? 'A' : 'B',
cardRr, prng_successor(nonce, 64)); cardRr, prng_successor(nonce, 64));
// Shouldn't we respond anything here? // Shouldn't we respond anything here?
@ -732,10 +743,11 @@ void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t
mf_crypto1_encrypt(pcs, response, 4, response_par); mf_crypto1_encrypt(pcs, response, 4, response_par);
EmSendCmdPar(response, 4, response_par); EmSendCmdPar(response, 4, response_par);
FpgaDisableTracing(); FpgaDisableTracing();
if (MF_DBGLEVEL >= 4) Dbprintf("AUTH COMPLETED for sector %d with key %c.", cardAUTHSC, cardAUTHKEY == AUTHKEYA ? 'A' : 'B'); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("AUTH COMPLETED for sector %d with key %c.", cardAUTHSC, cardAUTHKEY == AUTHKEYA ? 'A' : 'B');
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
break; break;
} }
case MFEMUL_WRITEBL2:{ case MFEMUL_WRITEBL2:{
if (receivedCmd_len == 18) { if (receivedCmd_len == 18) {
mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec); mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec);
@ -758,7 +770,6 @@ void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t
} }
emlSetMem(receivedCmd_dec, cardWRBL, 1); emlSetMem(receivedCmd_dec, cardWRBL, 1);
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); // always ACK? EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); // always ACK?
FpgaDisableTracing();
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
break; break;
} }
@ -766,12 +777,12 @@ void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t
cardSTATE = MFEMUL_IDLE; cardSTATE = MFEMUL_IDLE;
break; break;
} }
case MFEMUL_INTREG_INC:{ case MFEMUL_INTREG_INC:{
if (receivedCmd_len == 6) { if (receivedCmd_len == 6) {
mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t*)&ans); mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t*)&ans);
if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
FpgaDisableTracing();
cardSTATE = MFEMUL_IDLE; cardSTATE = MFEMUL_IDLE;
break; break;
} }
@ -780,12 +791,12 @@ void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
break; break;
} }
case MFEMUL_INTREG_DEC:{ case MFEMUL_INTREG_DEC:{
if (receivedCmd_len == 6) { if (receivedCmd_len == 6) {
mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t*)&ans); mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t*)&ans);
if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
FpgaDisableTracing();
cardSTATE = MFEMUL_IDLE; cardSTATE = MFEMUL_IDLE;
break; break;
} }
@ -794,25 +805,28 @@ void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
break; break;
} }
case MFEMUL_INTREG_REST:{ case MFEMUL_INTREG_REST:{
mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t*)&ans); mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t*)&ans);
if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
FpgaDisableTracing();
cardSTATE = MFEMUL_IDLE; cardSTATE = MFEMUL_IDLE;
break; break;
} }
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
break; break;
} }
}
} // end of switch
FpgaDisableTracing();
button_pushed = BUTTON_PRESS(); button_pushed = BUTTON_PRESS();
}
} // end of while
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();
if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1) { if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= MF_DBG_INFO) {
for ( uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { for ( uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
if (ar_nr_collected[i] == 2) { if (ar_nr_collected[i] == 2) {
Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i<ATTACK_KEY_COUNT/2) ? "keyA" : "keyB", ar_nr_resp[i].sector); Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i<ATTACK_KEY_COUNT/2) ? "keyA" : "keyB", ar_nr_resp[i].sector);
@ -841,12 +855,12 @@ void MifareSim(uint8_t flags, uint8_t exitAfterNReads, uint8_t cardsize, uint8_t
} }
} }
} }
if (MF_DBGLEVEL >= 1) Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", get_tracing(), BigBuf_get_traceLen()); if (MF_DBGLEVEL >= MF_DBG_INFO) Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", get_tracing(), BigBuf_get_traceLen());
if(flags & FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK if(flags & FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK
//Send the collected ar_nr in the response //Send the collected ar_nr in the response
cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, button_pushed, 0, &ar_nr_resp, sizeof(ar_nr_resp)); cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, button_pushed, 0, &ar_nr_resp, sizeof(ar_nr_resp));
} }
LED_A_OFF(); LED_A_OFF();
} }

View file

@ -23,7 +23,7 @@
#include "crapto1/crapto1.h" #include "crapto1/crapto1.h"
#include "mbedtls/des.h" #include "mbedtls/des.h"
int MF_DBGLEVEL = MF_DBG_ALL; int MF_DBGLEVEL = MF_DBG_INFO;
// crypto1 helpers // crypto1 helpers
void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out){ void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out){

View file

@ -34,11 +34,11 @@
#define MF_MINFIELDV 4000 #define MF_MINFIELDV 4000
// debug // debug
// 0 - no debug messages 1 - error messages 2 - all messages 4 - extended debug mode #define MF_DBG_NONE 0 // no messages
#define MF_DBG_NONE 0 #define MF_DBG_ERROR 1 // errors only
#define MF_DBG_ERROR 1 #define MF_DBG_INFO 2 // errors + info messages
#define MF_DBG_ALL 2 #define MF_DBG_DEBUG 3 // errors + info + debug messages
#define MF_DBG_EXTENDED 4 #define MF_DBG_EXTENDED 4 // errors + info + debug + breaking debug messages
extern int MF_DBGLEVEL; extern int MF_DBGLEVEL;