Mifare Sim

Compilation OK
Emulation 1k OK with android
This commit is contained in:
vratiskol 2019-03-27 14:18:26 +01:00
commit a068f7c2bc
6 changed files with 208 additions and 151 deletions

View file

@ -42,7 +42,7 @@ static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t act
case AC_KEYA_WRITE: { case AC_KEYA_WRITE: {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYA_WRITE"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYA_WRITE");
return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01)) return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01))
|| (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03))); || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03)));
} }
case AC_KEYB_READ: { case AC_KEYB_READ: {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_READ"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_READ");
@ -51,17 +51,17 @@ static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t act
case AC_KEYB_WRITE: { case AC_KEYB_WRITE: {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_WRITE"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_WRITE");
return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x04)) return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x04))
|| (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03))); || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03)));
} }
case AC_AC_READ: { case AC_AC_READ: {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_AC_READ"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_AC_READ");
return ((keytype == AUTHKEYA) return ((keytype == AUTHKEYA)
|| (keytype == AUTHKEYB && !(AC == 0x00 || AC == 0x02 || AC == 0x01))); || (keytype == AUTHKEYB && !(AC == 0x00 || AC == 0x02 || AC == 0x01)));
} }
case AC_AC_WRITE: { case AC_AC_WRITE: {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_AC_WRITE"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_AC_WRITE");
return ((keytype == AUTHKEYA && (AC == 0x01)) return ((keytype == AUTHKEYA && (AC == 0x01))
|| (keytype == AUTHKEYB && (AC == 0x03 || AC == 0x05))); || (keytype == AUTHKEYB && (AC == 0x03 || AC == 0x05)));
} }
default: default:
return false; return false;
@ -73,7 +73,7 @@ static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action
uint8_t sector_trailer[16]; uint8_t sector_trailer[16];
emlGetMem(sector_trailer, SectorTrailer(blockNo), 1); emlGetMem(sector_trailer, SectorTrailer(blockNo), 1);
uint8_t sector_block; uint8_t sector_block;
if (blockNo <= MIFARE_2K_MAXBLOCK) { if (blockNo <= MIFARE_2K_MAXBLOCK) {
sector_block = blockNo & 0x03; sector_block = blockNo & 0x03;
@ -85,22 +85,22 @@ static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action
switch (sector_block) { switch (sector_block) {
case 0x00: { case 0x00: {
AC = ((sector_trailer[7] >> 2) & 0x04) AC = ((sector_trailer[7] >> 2) & 0x04)
| ((sector_trailer[8] << 1) & 0x02) | ((sector_trailer[8] << 1) & 0x02)
| ((sector_trailer[8] >> 4) & 0x01); | ((sector_trailer[8] >> 4) & 0x01);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsDataAccessAllowed: case 0x00 - %02x", AC); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsDataAccessAllowed: case 0x00 - %02x", AC);
break; break;
} }
case 0x01: { case 0x01: {
AC = ((sector_trailer[7] >> 3) & 0x04) AC = ((sector_trailer[7] >> 3) & 0x04)
| ((sector_trailer[8] >> 0) & 0x02) | ((sector_trailer[8] >> 0) & 0x02)
| ((sector_trailer[8] >> 5) & 0x01); | ((sector_trailer[8] >> 5) & 0x01);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsDataAccessAllowed: case 0x01 - %02x", AC); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsDataAccessAllowed: case 0x01 - %02x", AC);
break; break;
} }
case 0x02: { case 0x02: {
AC = ((sector_trailer[7] >> 4) & 0x04) AC = ((sector_trailer[7] >> 4) & 0x04)
| ((sector_trailer[8] >> 1) & 0x02) | ((sector_trailer[8] >> 1) & 0x02)
| ((sector_trailer[8] >> 6) & 0x01); | ((sector_trailer[8] >> 6) & 0x01);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsDataAccessAllowed: case 0x02 - %02x", AC); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsDataAccessAllowed: case 0x02 - %02x", AC);
break; break;
} }
@ -376,6 +376,11 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
uint8_t blockNo; uint8_t blockNo;
uint32_t nr;
uint32_t ar;
bool encrypted_data;
uint8_t cardWRBL = 0; uint8_t cardWRBL = 0;
uint8_t cardAUTHSC = 0; uint8_t cardAUTHSC = 0;
uint8_t cardAUTHKEY = AUTHKEYNONE; // no authentication uint8_t cardAUTHKEY = AUTHKEYNONE; // no authentication
@ -495,10 +500,10 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
// init crypto block // init crypto block
crypto1_destroy(pcs); crypto1_destroy(pcs);
cardAUTHKEY = AUTHKEYNONE; cardAUTHKEY = AUTHKEYNONE;
//nonce = prng_successor(selTimer, 32) // RRG Repo, same as prand() ??? //nonce = bytes_to_num(rAUTH_NT, 4);
if (( flags & FLAG_RANDOM_NONCE) == FLAG_RANDOM_NONCE ) { nonce = prng_successor(selTimer, 32);
nonce = prand(); if ((flags & FLAG_RANDOM_NONCE) == FLAG_RANDOM_NONCE) nonce = prand();
}
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
cardSTATE = MFEMUL_SELECT1; cardSTATE = MFEMUL_SELECT1;
@ -516,7 +521,6 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
break; break;
} }
// The anti-collision sequence, which is a mandatory part of the card activation sequence. // The anti-collision sequence, which is a mandatory part of the card activation sequence.
// It auto with 4-byte UID (= Single Size UID), // It auto with 4-byte UID (= Single Size UID),
// 7 -byte UID (= Double Size UID) or 10-byte UID (= Triple Size UID). // 7 -byte UID (= Double Size UID) or 10-byte UID (= Triple Size UID).
@ -549,6 +553,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
receivedCmd[1] == 0x70 && receivedCmd[1] == 0x70 &&
memcmp(&receivedCmd[2], responses[UIDBCC1].response, 4) == 0)) { memcmp(&receivedCmd[2], responses[UIDBCC1].response, 4) == 0)) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SELECT CL1 %02x%02x%02x%02x received", receivedCmd[2], receivedCmd[3], receivedCmd[4], receivedCmd[5]); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SELECT CL1 %02x%02x%02x%02x received", receivedCmd[2], receivedCmd[3], receivedCmd[4], receivedCmd[5]);
// Send SAK according UID len
switch (uid_len) { switch (uid_len) {
case 4: case 4:
switch (MifareCardType) { switch (MifareCardType) {
@ -568,27 +574,30 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
LED_B_ON(); LED_B_ON();
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_WORK"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_WORK");
continue; break;
case 7: case 7:
// SAK => Need another select round // SAK => Need another select round
EmSendPrecompiledCmd(&responses[SAK1]); EmSendPrecompiledCmd(&responses[SAK1]);
cardSTATE = MFEMUL_SELECT2; cardSTATE = MFEMUL_SELECT2;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_SELECT2"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_SELECT2");
continue; break;
case 10: case 10:
// SAK => Need another select round // SAK => Need another select round
EmSendPrecompiledCmd(&responses[SAK1]); EmSendPrecompiledCmd(&responses[SAK1]);
cardSTATE = MFEMUL_SELECT2; cardSTATE = MFEMUL_SELECT2;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_SELECT2"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_SELECT2");
continue; break;
default: default:
break; break;
} } // End Switch (uid_len)
}
// IDLE } else {
cardSTATE_TO_IDLE(); // IDLE
cardSTATE_TO_IDLE();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_IDLE");
}
// Break Case MFEMUL_SELECT1
break; break;
} }
@ -612,9 +621,9 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
case MFEMUL_SELECT2: { case MFEMUL_SELECT2: {
if (receivedCmd_len == 2 && if (receivedCmd_len == 2 &&
(receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x20)) { (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x20)) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SELECT ALL CL2 received"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] SELECT ALL CL2 received");
EmSendPrecompiledCmd(&responses[UIDBCC2]); EmSendPrecompiledCmd(&responses[UIDBCC2]);
continue; break;
} }
// select cl2 card - 0x95 0x70 xxxxxxxxxxxx // select cl2 card - 0x95 0x70 xxxxxxxxxxxx
@ -625,7 +634,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
switch (uid_len) { switch (uid_len) {
case 7: case 7:
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SELECT CL2 %02x%02x%02x%02x received", receivedCmd[2], receivedCmd[3], receivedCmd[4], receivedCmd[5]); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] SELECT CL2 %02x%02x%02x%02x received", receivedCmd[2], receivedCmd[3], receivedCmd[4], receivedCmd[5]);
switch (MifareCardType) { switch (MifareCardType) {
case 0: case 0:
@ -648,13 +657,15 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
// SAK => Need another select round // SAK => Need another select round
EmSendPrecompiledCmd(&responses[SAK1]); EmSendPrecompiledCmd(&responses[SAK1]);
cardSTATE = MFEMUL_SELECT3; cardSTATE = MFEMUL_SELECT3;
continue; if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] cardSTATE = MFEMUL_SELECT3");
break;
default: default:
break; break;
} }
} }
cardSTATE_TO_IDLE(); cardSTATE_TO_IDLE();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] cardSTATE = MFEMUL_IDLE");
break; break;
} }
@ -697,71 +708,122 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
LED_B_ON(); LED_B_ON();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("--> WORK. anticol3 time: %d", GetTickCount() - selTimer); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
break; Dbprintf("[MFEMUL_SELECT3] --> WORK. anticol3 time: %d", GetTickCount() - selTimer);
Dbprintf("[MFEMUL_SELECT3] cardSTATE = MFEMUL_WORK");
}
continue;
} }
cardSTATE_TO_IDLE(); cardSTATE_TO_IDLE();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT3] cardSTATE = MFEMUL_IDLE");
break; break;
} }
// WORK
case MFEMUL_WORK: { case MFEMUL_WORK: {
if (receivedCmd_len == 0) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Enter in case");
if (receivedCmd_len != 4) {
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("All commands must have exactly 4 bytes: receivedCmd_len=%d", receivedCmd_len); mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] All commands must have exactly 4 bytes: receivedCmd_len=%d - Cmd: %02X", receivedCmd_len, receivedCmd_dec);
break; break;
} }
bool encrypted_data = (cardAUTHKEY != AUTHKEYNONE) ; if (receivedCmd_len == 0) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] NO CMD received");
break;
}
encrypted_data = (cardAUTHKEY != AUTHKEYNONE);
if (encrypted_data) { if (encrypted_data) {
// decrypt seqence // decrypt seqence
mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec); mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("decrypt seqence"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Decrypt seqence");
} else { } else {
// Data in clear
memcpy(receivedCmd_dec, receivedCmd, receivedCmd_len); memcpy(receivedCmd_dec, receivedCmd, receivedCmd_len);
} }
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_NA)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("All commands must have a valid CRC %d", receivedCmd_dec); if (MF_DBGLEVEL >= 1) Dbprintf("[MFEMUL_WORK] All commands must have a valid CRC %02X (%d)", receivedCmd_dec, receivedCmd_len);
break; break;
} }
if (receivedCmd_len == 4 && (receivedCmd_dec[0] == MIFARE_AUTH_KEYA || receivedCmd_dec[0] == MIFARE_AUTH_KEYB)) { if (receivedCmd_len == 4 && (receivedCmd_dec[0] == MIFARE_AUTH_KEYA || receivedCmd_dec[0] == MIFARE_AUTH_KEYB)) {
// Reader asks for AUTH: 6X XX
// RCV: 60 XX => Using KEY A
// RCV: 61 XX => Using KEY B
// XX: Block number
// 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] > MIFARE_4K_MAXBLOCK && !((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK)) { if (receivedCmd_dec[1] > MIFARE_4K_MAXBLOCK && !((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK)) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
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]); 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 = receivedCmd_dec[1] / 4; // received block num, Need to check if ok for 4k card ???
authTimer = GetTickCount();
// received block num -> sector
// Example: 6X [00]
cardAUTHSC = receivedCmd_dec[1] / 4;
// cardAUTHKEY: 60 => Auth use Key A
// cardAUTHKEY: 61 => Auth use Key B
cardAUTHKEY = receivedCmd_dec[0] & 0x01; cardAUTHKEY = receivedCmd_dec[0] & 0x01;
crypto1_destroy(pcs);
crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY)); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] KEY: %02X%02X", emlGetKey(cardAUTHSC, cardAUTHKEY));
// first authentication // first authentication
crypto1_destroy(pcs);
// Load key into crypto
crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY));
if (!encrypted_data) { if (!encrypted_data) {
crypto1_word(pcs, cuid ^ nonce, 0); //Update crypto state // Receive Cmd in clear txt
num_to_bytes(nonce, 4, rAUTH_AT); // Send nonce // Update crypto state (UID ^ NONCE)
if (MF_DBGLEVEL >= 2) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d - %s", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY, emlGetKey(cardAUTHSC, cardAUTHKEY)); crypto1_word(pcs, cuid ^ nonce, 0);
} else { // nested authentication // prepare nonce
if (MF_DBGLEVEL >= 2) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %d", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY); num_to_bytes(nonce, 4, rAUTH_AT);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader authenticating for block %d (0x%02x) with key %d - nonce: %02X - ciud: %02X", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY, rAUTH_AT, cuid);
} else {
// nested authentication
ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0); ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0);
num_to_bytes(ans, 4, rAUTH_AT); num_to_bytes(ans, 4, rAUTH_AT);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader doing nested authentication for block %d (0x%02x) with key %d", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY);
} }
EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
cardSTATE = MFEMUL_AUTH1; cardSTATE = MFEMUL_AUTH1;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_AUTH1 - rAUTH_AT: %02X", rAUTH_AT);
Dbprintf("cardSTATE = MFEMUL_AUTH1"); continue;
}
break;
} }
if (!encrypted_data) { // all other commands must be encrypted (authenticated)
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Commands must be encrypted (authenticated)"); // rule 13 of 7.5.3. in ISO 14443-4. chaining shall be continued
// BUT... ACK --> NACK
if (receivedCmd_len == 1 && receivedCmd_dec[0] == CARD_ACK) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
break; break;
} }
// if Cmd is Read, Write, Inc, Dec, Restore, Transfert // rule 12 of 7.5.3. in ISO 14443-4. R(NAK) --> R(ACK)
if (receivedCmd_len == 1 && receivedCmd_dec[0] == CARD_NACK_NA) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
break;
}
// if (!encrypted_data) { // all other commands must be encrypted (authenticated)
// if (MF_DBGLEVEL >= 0) Dbprintf("Commands must be encrypted (authenticated)");
// break;
// }
// case MFEMUL_WORK => if Cmd is Read, Write, Inc, Dec, Restore, Transfert
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
@ -771,84 +833,85 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
// Check if Block num is not too far // Check if Block num is not too far
if (receivedCmd_dec[1] > MIFARE_4K_MAXBLOCK) { if (receivedCmd_dec[1] > MIFARE_4K_MAXBLOCK) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
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]); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] 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 (receivedCmd_dec[1] / 4 != cardAUTHSC) { if (receivedCmd_dec[1] / 4 != cardAUTHSC) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
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); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] 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;
} }
} }
// CMD READ block // case MFEMUL_WORK => CMD READ block
if (receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK) { if (receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK) {
blockNo = receivedCmd_dec[1]; blockNo = receivedCmd_dec[1];
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader reading block %d (0x%02x)", blockNo, blockNo); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader reading block %d (0x%02x)", blockNo, blockNo);
emlGetMem(response, blockNo, 1); emlGetMem(response, blockNo, 1);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("[ISO14443A_CMD_READBLOCK] Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo, Dbprintf("[MFEMUL_WORK - ISO14443A_CMD_READBLOCK] Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo,
response[0], response[1], response[2], response[3], response[4], response[5], response[6], response[0], response[1], response[2], response[3], response[4], response[5], response[6],
response[7], response[8], response[9], response[10], response[11], response[12], response[13], response[7], response[8], response[9], response[10], response[11], response[12], response[13],
response[14],response[15]); response[14], response[15]);
} }
if (IsSectorTrailer(blockNo)) { if (IsSectorTrailer(blockNo)) {
if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_KEYA_READ)) { if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_KEYA_READ)) {
memset(response, 0x00, 6); // keyA can never be read, Why ??? Need source ? memset(response, 0x00, 6); // keyA can never be read, Why ??? Need source ?
// a0a1a2a3a4a561e789c1b0b1b2b3b4b5 => 00000000000061e789c1b0b1b2b3b4b5 // a0a1a2a3a4a561e789c1b0b1b2b3b4b5 => 00000000000061e789c1b0b1b2b3b4b5
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[IsSectorTrailer] keyA can never be read - block %d (0x%02x)", blockNo, blockNo); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsSectorTrailer] keyA can never be read - block %d (0x%02x)", blockNo, blockNo);
} }
if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_KEYB_READ)) { if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_KEYB_READ)) {
memset(response + 10, 0x00, 6); // keyB cannot be read memset(response + 10, 0x00, 6); // keyB cannot be read
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[IsSectorTrailer] keyB cannot be read - block %d (0x%02x)", blockNo, blockNo); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsSectorTrailer] keyB cannot be read - block %d (0x%02x)", blockNo, blockNo);
} }
if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_AC_READ)) { if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_AC_READ)) {
memset(response + 6, 0x00, 4); // AC bits cannot be read memset(response + 6, 0x00, 4); // AC bits cannot be read
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[IsAccessAllowed] AC bits cannot be read - block %d (0x%02x)", blockNo, blockNo); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsAccessAllowed] AC bits cannot be read - block %d (0x%02x)", blockNo, blockNo);
} }
} else { } else {
if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_DATA_READ)) { if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_DATA_READ)) {
memset(response, 0x00, 16); // datablock cannot be read memset(response, 0x00, 16); // datablock cannot be read
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[IsAccessAllowed] Data block %d (0x%02x) cannot be read", blockNo, blockNo); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsAccessAllowed] Data block %d (0x%02x) cannot be read", blockNo, blockNo);
} }
} }
AppendCrc14443a(response, 16); AppendCrc14443a(response, 16);
mf_crypto1_encrypt(pcs, response, MAX_MIFARE_FRAME_SIZE, response_par); mf_crypto1_encrypt(pcs, response, MAX_MIFARE_FRAME_SIZE, response_par);
EmSendCmdPar(response, MAX_MIFARE_FRAME_SIZE, response_par); EmSendCmdPar(response, MAX_MIFARE_FRAME_SIZE, response_par);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("[EmSendCmdPar] Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo, Dbprintf("[MFEMUL_WORK - EmSendCmdPar] Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo,
response[0], response[1], response[2], response[3], response[4], response[5], response[6], response[0], response[1], response[2], response[3], response[4], response[5], response[6],
response[7], response[8], response[9], response[10], response[11], response[12], response[13], response[7], response[8], response[9], response[10], response[11], response[12], response[13],
response[14],response[15]); response[14], response[15]);
} }
numReads++; numReads++;
if (exitAfterNReads > 0 && numReads == exitAfterNReads) { if (exitAfterNReads > 0 && numReads == exitAfterNReads) {
Dbprintf("%d reads done, exiting", numReads); Dbprintf("[MFEMUL_WORK] %d reads done, exiting", numReads);
finished = true; finished = true;
} }
break; break;
}
// CMD WRITEBLOCK } // End receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK
// case MFEMUL_WORK => CMD WRITEBLOCK
if (receivedCmd_dec[0] == ISO14443A_CMD_WRITEBLOCK) { if (receivedCmd_dec[0] == ISO14443A_CMD_WRITEBLOCK) {
blockNo = receivedCmd_dec[1]; blockNo = receivedCmd_dec[1];
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("RECV 0xA0 write block %d (%02x)", blockNo, blockNo); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RECV 0xA0 write block %d (%02x)", blockNo, blockNo);
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
cardWRBL = blockNo; cardWRBL = blockNo;
cardSTATE = MFEMUL_WRITEBL2; cardSTATE = MFEMUL_WRITEBL2;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_WRITEBL2");
break; break;
} }
// CMD INC/DEC/RES // case MFEMUL_WORK => CMD INC/DEC/REST
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) {
blockNo = receivedCmd_dec[1]; blockNo = receivedCmd_dec[1];
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("[MFEMUL_WORK] 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 >= MF_DBG_EXTENDED) Dbprintf("Reader tried to operate on block, but emlCheckValBl failed, nacking"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] 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));
break; break;
} }
@ -858,27 +921,29 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
// INC // INC
if (receivedCmd_dec[0] == MIFARE_CMD_INC) { if (receivedCmd_dec[0] == MIFARE_CMD_INC) {
cardSTATE = MFEMUL_INTREG_INC; cardSTATE = MFEMUL_INTREG_INC;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_INTREG_INC"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_INTREG_INC");
} }
// DEC // DEC
if (receivedCmd_dec[0] == MIFARE_CMD_DEC) { if (receivedCmd_dec[0] == MIFARE_CMD_DEC) {
cardSTATE = MFEMUL_INTREG_DEC; cardSTATE = MFEMUL_INTREG_DEC;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_INTREG_DEC"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_INTREG_DEC");
} }
// REST // REST
if (receivedCmd_dec[0] == MIFARE_CMD_RESTORE) { if (receivedCmd_dec[0] == MIFARE_CMD_RESTORE) {
cardSTATE = MFEMUL_INTREG_REST; cardSTATE = MFEMUL_INTREG_REST;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_INTREG_REST"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_INTREG_REST");
break;
} }
} break;
// TRANSFER } // End case MFEMUL_WORK => CMD INC/DEC/REST
// case MFEMUL_WORK => CMD TRANSFER
if (receivedCmd_dec[0] == MIFARE_CMD_TRANSFER) { if (receivedCmd_dec[0] == MIFARE_CMD_TRANSFER) {
blockNo = receivedCmd_dec[1]; blockNo = receivedCmd_dec[1];
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("RECV 0x%02x transfer block %d (%02x)", receivedCmd_dec[0], blockNo, blockNo); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] 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
@ -886,42 +951,46 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
break; break;
} }
// HALT // case MFEMUL_WORK => CMD HALT
if (receivedCmd_dec[0] == ISO14443A_CMD_HALT && receivedCmd[1] == 0x00) { if (receivedCmd_dec[0] == ISO14443A_CMD_HALT && receivedCmd[1] == 0x00) {
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
cardSTATE = MFEMUL_HALTED; cardSTATE = MFEMUL_HALTED;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_HALTED;"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_HALTED");
break; break;
} }
// RATS // case MFEMUL_WORK => CMD RATS
if (receivedCmd[0] == ISO14443A_CMD_RATS) { if (receivedCmd[0] == ISO14443A_CMD_RATS) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
if (MF_DBGLEVEL >= 1) Dbprintf("[MFEMUL_WORK] RCV RATS => NACK");
break; break;
} }
// command not allowed // case MFEMUL_WORK => command not allowed
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) 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;
} }
// AUTH1
case MFEMUL_AUTH1: { case MFEMUL_AUTH1: {
if (receivedCmd_len != 8) { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_AUTH1] Enter case");
cardSTATE_TO_IDLE();
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("MFEMUL_AUTH1: receivedCmd_len != 8 => cardSTATE_TO_IDLE())");
break;
}
uint32_t nr = bytes_to_num(receivedCmd, 4); // if (receivedCmd_len != 4) {
uint32_t ar = bytes_to_num(&receivedCmd[4], 4); // cardSTATE_TO_IDLE();
// LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
// if (MF_DBGLEVEL >= 0) Dbprintf("MFEMUL_AUTH1: receivedCmd_len != 8 (%d) => cardSTATE_TO_IDLE())", receivedCmd_len);
// break;
// }
nr = bytes_to_num(receivedCmd, 4);
ar = bytes_to_num(&receivedCmd[4], 4);
// Collect AR/NR per keytype & sector // Collect AR/NR per keytype & sector
if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) { if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
if (MF_DBGLEVEL >= 0) Dbprintf("FLAG_NR_AR_ATTACK");
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 + mM] == 0 || ((cardAUTHSC == ar_nr_resp[i + mM].sector) && (cardAUTHKEY == ar_nr_resp[i + mM].keytype) && (ar_nr_collected[i + mM] > 0))) { if (ar_nr_collected[i + mM] == 0 || ((cardAUTHSC == ar_nr_resp[i + mM].sector) && (cardAUTHKEY == ar_nr_resp[i + mM].keytype) && (ar_nr_collected[i + mM] > 0))) {
// if first auth for sector, or matches sector and keytype of previous auth // if first auth for sector, or matches sector and keytype of previous auth
@ -986,10 +1055,10 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
crypto1_word(pcs, nr, 1); crypto1_word(pcs, nr, 1);
cardRr = ar ^ crypto1_word(pcs, 0, 0); cardRr = ar ^ crypto1_word(pcs, 0, 0);
// test if auth OK // test if auth KO
if (cardRr != prng_successor(nonce, 64)) { if (cardRr != prng_successor(nonce, 64)) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("AUTH FAILED for sector %d with key %c. [nr=%08x cardRr=%08x] [nt=%08x succ=%08x]" Dbprintf("[MFEMUL_AUTH1] AUTH FAILED for sector %d with key %c. [nr=%08x cardRr=%08x] [nt=%08x succ=%08x]"
, cardAUTHSC , cardAUTHSC
, (cardAUTHKEY == 0) ? 'A' : 'B' , (cardAUTHKEY == 0) ? 'A' : 'B'
, nr , nr
@ -998,18 +1067,23 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
, prng_successor(nonce, 64) , prng_successor(nonce, 64)
); );
} }
cardAUTHKEY = AUTHKEYNONE; // not authenticated cardAUTHKEY = AUTHKEYNONE; // not authenticated
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
cardSTATE_TO_IDLE(); cardSTATE_TO_IDLE();
break; break;
} }
ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0); //ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0);
//num_to_bytes(ans, 4, rAUTH_AT);
//EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
ans = prng_successor(nonce, 96);
num_to_bytes(ans, 4, rAUTH_AT); num_to_bytes(ans, 4, rAUTH_AT);
EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); mf_crypto1_encrypt(pcs, rAUTH_AT, 4, response_par);
EmSendCmdPar(rAUTH_AT, 4, response_par);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("AUTH COMPLETED for sector %d with key %c. time=%d", Dbprintf("[MFEMUL_AUTH1] AUTH COMPLETED for sector %d with key %c. time=%d",
cardAUTHSC, cardAUTHSC,
cardAUTHKEY == 0 ? 'A' : 'B', cardAUTHKEY == 0 ? 'A' : 'B',
GetTickCount() - authTimer GetTickCount() - authTimer
@ -1017,11 +1091,10 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
} }
LED_C_ON(); LED_C_ON();
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_WORK"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_AUTH1] cardSTATE = MFEMUL_WORK");
break; break;
} }
// WRITE BL2 // WRITE BL2
case MFEMUL_WRITEBL2: { case MFEMUL_WRITEBL2: {
if (receivedCmd_len == MAX_MIFARE_FRAME_SIZE) { if (receivedCmd_len == MAX_MIFARE_FRAME_SIZE) {
@ -1046,12 +1119,13 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, 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?
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WRITEBL2] cardSTATE = MFEMUL_WORK");
break; break;
} }
} else {
cardSTATE_TO_IDLE();
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
} }
cardSTATE_TO_IDLE();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WRITEBL2] cardSTATE = MFEMUL_IDLE");
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
break; break;
} }
@ -1068,13 +1142,15 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
cardINTREG = cardINTREG + ans; cardINTREG = cardINTREG + ans;
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_INTREG_INC] cardSTATE = MFEMUL_WORK");
break; break;
} }
} }
// DEC // DEC
case MFEMUL_INTREG_DEC: { case MFEMUL_INTREG_DEC: {
if (receivedCmd_len == 6) { if (receivedCmd_len == 6) { // Data is encrypted
// Decrypted cmd
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));
@ -1085,6 +1161,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
cardINTREG = cardINTREG - ans; cardINTREG = cardINTREG - ans;
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_INTREG_DEC] cardSTATE = MFEMUL_WORK");
break; break;
} }
@ -1098,6 +1175,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
} }
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_INTREG_REST] cardSTATE = MFEMUL_WORK");
break; break;
} }
@ -1144,12 +1222,11 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", get_tracing(), BigBuf_get_traceLen()); Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", get_tracing(), BigBuf_get_traceLen());
} }
// Need to be debug - Card not recognize by my phone if uncommented
//if ((flags &FLAG_INTERACTIVE) == FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK
//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)); if ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK
//} //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));
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();

View file

@ -17,21 +17,6 @@
extern void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain); extern void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain);
//mifare emulator states
#define MFEMUL_NOFIELD 0
#define MFEMUL_IDLE 1
#define MFEMUL_SELECT1 2
#define MFEMUL_SELECT2 3
#define MFEMUL_SELECT3 4
#define MFEMUL_AUTH1 5
#define MFEMUL_AUTH2 6
#define MFEMUL_WORK 7
#define MFEMUL_WRITEBL2 8
#define MFEMUL_INTREG_INC 9
#define MFEMUL_INTREG_DEC 10
#define MFEMUL_INTREG_REST 11
#define MFEMUL_HALTED 12
#define AC_DATA_READ 0 #define AC_DATA_READ 0
#define AC_DATA_WRITE 1 #define AC_DATA_WRITE 1
#define AC_DATA_INC 2 #define AC_DATA_INC 2

View file

@ -592,7 +592,7 @@ void emlClearMem(void) {
memset(emCARD, 0, CARD_MEMORY_SIZE); memset(emCARD, 0, CARD_MEMORY_SIZE);
// fill sectors trailer data // fill sectors trailer data
for (uint16_t b = 3; b <= MIFARE_4K_MAXBLOCK; ((b <= MIFARE_2K_MAXBLOCK ) ? (b += 4) : (b += 16))) for (uint16_t b = 3; b <= MIFARE_4K_MAXBLOCK; ((b <= MIFARE_2K_MAXBLOCK) ? (b += 4) : (b += 16)))
emlSetMem((uint8_t *)trailer, b, 1); emlSetMem((uint8_t *)trailer, b, 1);
// uid // uid
@ -602,7 +602,7 @@ void emlClearMem(void) {
uint8_t SectorTrailer(uint8_t blockNo) { uint8_t SectorTrailer(uint8_t blockNo) {
if (blockNo <= MIFARE_2K_MAXBLOCK) { if (blockNo <= MIFARE_2K_MAXBLOCK) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x03)); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x03));
return (blockNo | 0x03); return (blockNo | 0x03);
} else { } else {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x0f)); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x0f));

View file

@ -33,11 +33,6 @@
#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) #define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication #define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication
// mifare 4bit card answers
#define CARD_ACK 0x0A // 1010 - ACK
#define CARD_NACK_NA 0x04 // 0100 - NACK, not allowed (command not allowed)
#define CARD_NACK_TR 0x05 // 0101 - NACK, transmission error
// reader voltage field detector // reader voltage field detector
#define MF_MINFIELDV 4000 #define MF_MINFIELDV 4000

View file

@ -84,11 +84,11 @@ void transform_D(uint8_t *ru) {
uint32_t v1 = ((ru[3] << 24) | (ru[2] << 16) | (ru[1] << 8) | ru[0]) + c_D[p++]; uint32_t v1 = ((ru[3] << 24) | (ru[2] << 16) | (ru[1] << 8) | ru[0]) + c_D[p++];
uint32_t v2 = ((ru[7] << 24) | (ru[6] << 16) | (ru[5] << 8) | ru[4]) + c_D[p++]; uint32_t v2 = ((ru[7] << 24) | (ru[6] << 16) | (ru[5] << 8) | ru[4]) + c_D[p++];
for (i = 0; i < 12; i += 2) { for (i = 0; i < 12; i += 2) {
uint32_t xor1 = v1 ^ v2; uint32_t xor1 = v1 ^ v2;
uint32_t t1 = ROTL(xor1, v2 & 0x1F) + c_D[p++]; uint32_t t1 = ROTL(xor1, v2 & 0x1F) + c_D[p++];
uint32_t xor2 = v2 ^ t1; uint32_t xor2 = v2 ^ t1;
uint32_t t2 = ROTL(xor2, t1 & 0x1F) + c_D[p++]; uint32_t t2 = ROTL(xor2, t1 & 0x1F) + c_D[p++];
uint32_t xor3 = t1 ^ t2; uint32_t xor3 = t1 ^ t2;
uint32_t xor4 = t2 ^ v1; uint32_t xor4 = t2 ^ v1;
v1 = ROTL(xor3, t2 & 0x1F) + c_D[p++]; v1 = ROTL(xor3, t2 & 0x1F) + c_D[p++];
@ -322,9 +322,9 @@ static int ul_read(uint8_t page, uint8_t *response, uint16_t responseLength) {
static int ul_comp_write(uint8_t page, uint8_t *data, uint8_t datalen) { static int ul_comp_write(uint8_t page, uint8_t *data, uint8_t datalen) {
if (data == NULL) if (data == NULL)
return -1; return -1;
uint8_t cmd[18]; uint8_t cmd[18];
memset(cmd, 0x00, sizeof(cmd)); memset(cmd, 0x00, sizeof(cmd));
datalen = (datalen > 16) ? 16 : datalen; datalen = (datalen > 16) ? 16 : datalen;

View file

@ -242,9 +242,9 @@ void mrev(model_t *model) {
void mnovel(model_t *model) { void mnovel(model_t *model) {
/* remove name and check string from modified model */ /* remove name and check string from modified model */
/* previous classification no longer applies */ /* previous classification no longer applies */
model->name = NULL; model->name = NULL;
model->flags &= ~P_CLMASK; model->flags &= ~P_CLMASK;
pfree(&model->check); pfree(&model->check);
pfree(&model->magic); pfree(&model->magic);
} }