'hf mf sim' - bugs fix, refactoring

This commit is contained in:
Eloff 2019-04-04 23:17:01 +03:00
parent 19cf50a6ff
commit 791ff18381
3 changed files with 124 additions and 81 deletions

View file

@ -2317,7 +2317,7 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, u
*res = data_bytes[0];
// crc check
if (len >= 3 && !check_crc(CRC_14443_A, data_bytes, len)) {
if (len >= 3 && !CheckCrc14A(data_bytes, len)) {
return -1;
}
@ -2979,6 +2979,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
int cardSTATE = MFEMUL_NOFIELD;
int _UID_LEN = 0; // 4, 7, 10
int _SECTORS = 16; // 16, 32, 40
int vHf = 0; // in mV
int res = 0;
uint32_t selTimer = 0;
@ -2996,6 +2997,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
pcs = &mpcs;
uint32_t numReads = 0; // Counts numer of times reader read a block
uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t decryptedCmd[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t receivedCmd_par[MAX_MIFARE_PARITY_SIZE] = {0x00};
uint8_t response[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t response_par[MAX_MIFARE_PARITY_SIZE] = {0x00};
@ -3012,11 +3014,11 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
// TAG Nonce - Authenticate response
uint8_t rAUTH_NT[4];
uint32_t nonce = prng_successor(GetTickCount(), 32);
num_to_bytes(nonce, 4, rAUTH_NT);
uint8_t rAUTH_NT_keystream[4];
uint32_t nonce = 0;
// uint8_t rAUTH_NT[] = {0x55, 0x41, 0x49, 0x92};// nonce from nested? why this?
uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00};
// uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00};
// Here, we collect CUID, NT, NR, AR, CUID2, NT2, NR2, AR2
// This can be used in a reader-only attack.
@ -3113,9 +3115,9 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
break;
}
// calc some crcs
compute_crc(CRC_14443_A, sak_4, 1, &sak_4[1], &sak_4[2]);
compute_crc(CRC_14443_A, sak_7, 1, &sak_7[1], &sak_7[2]);
compute_crc(CRC_14443_A, sak_10, 1, &sak_10[1], &sak_10[2]);
AddCrc14A(sak_4, sizeof(sak_4) - 2);
AddCrc14A(sak_7, sizeof(sak_7) - 2);
AddCrc14A(sak_10, sizeof(sak_10) - 2);
// We need to listen to the high-frequency, peak-detected path.
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
@ -3160,6 +3162,8 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
crypto1_destroy(pcs);
cardAUTHKEY = 0xff;
nonce = prng_successor(selTimer, 32);
num_to_bytes(nonce, 4, rAUTH_NT);
num_to_bytes(cuid ^ nonce, 4, rAUTH_NT_keystream);
continue;
}
@ -3338,12 +3342,9 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
, prng_successor(nonce, 64)
);
}
// Shouldn't we respond anything here?
// Right now, we don't nack or anything, which causes the
// reader to do a WUPA after a while. /Martin
// -- which is the correct response. /piwi
// sends encrypted NACK response to do no wait timeout
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);
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
break;
}
@ -3377,16 +3378,33 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
break;
}
bool encrypted_data = (cardAUTHKEY != 0xFF) ;
uint8_t *pRecvCmd = receivedCmd;
if (encrypted_data)
mf_crypto1_decrypt(pcs, receivedCmd, len);
if (encrypted_data) {
// decrypt request to separate buffer, trace log saves encrypted source sequence
mf_crypto1_decryptEx(pcs, receivedCmd, len, decryptedCmd);
pRecvCmd = decryptedCmd;
}
if (len == 4 && (receivedCmd[0] == MIFARE_AUTH_KEYA ||
receivedCmd[0] == MIFARE_AUTH_KEYB)) {
uint8_t block = 0;
uint8_t sector = 0;
if (len == 4 && (pRecvCmd[0] == MIFARE_AUTH_KEYA ||
pRecvCmd[0] == MIFARE_AUTH_KEYB)) {
// received block -> sector
block = pRecvCmd[1];
sector = MifareBlockToSector(block);
if (cardAUTHSC >= _SECTORS) {
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_IV) : CARD_NACK_IV);
if (MF_DBGLEVEL >= 4) Dbprintf("Reader tried to operate (0x%02) on out of range block: %d (0x%02x), nacking", pRecvCmd[0], block, block);
break;
}
authTimer = GetTickCount();
cardAUTHSC = receivedCmd[1] / 4; // received block -> sector
cardAUTHKEY = receivedCmd[0] & 0x1;
cardAUTHSC = sector;
cardAUTHKEY = pRecvCmd[0] & 0x1;
crypto1_destroy(pcs);
// load key into crypto
@ -3396,62 +3414,92 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
// first authentication
// Update crypto state init (UID ^ NONCE)
crypto1_word(pcs, cuid ^ nonce, 0);
num_to_bytes(nonce, 4, rAUTH_AT);
EmSendCmd(rAUTH_NT, sizeof(rAUTH_NT));
} 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);
*/
mf_crypto1_encryptEx(pcs, rAUTH_NT, rAUTH_NT_keystream, response, 4, response_par);
EmSendCmdPar(response, 4, response_par);
if (MF_DBGLEVEL >= 3) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %c", receivedCmd[1], receivedCmd[1], cardAUTHKEY == 0 ? 'A' : 'B');
if (MF_DBGLEVEL >= 3) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %c", block, block, cardAUTHKEY == 0 ? 'A' : 'B');
}
EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
cardSTATE = MFEMUL_AUTH1;
break;
}
// rule 13 of 7.5.3. in ISO 14443-4. chaining shall be continued
// BUT... ACK --> NACK
if (len == 1 && receivedCmd[0] == CARD_ACK) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
if (len == 1 && pRecvCmd[0] == CARD_ACK) {
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
break;
}
// rule 12 of 7.5.3. in ISO 14443-4. R(NAK) --> R(ACK)
if (len == 1 && receivedCmd[0] == CARD_NACK_NA) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
if (len == 1 && pRecvCmd[0] == CARD_NACK_NA) {
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_ACK) : CARD_ACK);
break;
}
if (len != 4) {
// halt
if (len > 1 && pRecvCmd[0] == ISO14443A_CMD_HALT && pRecvCmd[1] == 0x00) {
LED_B_OFF();
LED_C_OFF();
cardSTATE = MFEMUL_HALTED;
if (MF_DBGLEVEL >= 4) Dbprintf("--> HALTED. Selected time: %d ms", GetTickCount() - selTimer);
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
cardAUTHKEY = 0xff;
break;
}
if (receivedCmd[0] == ISO14443A_CMD_READBLOCK ||
receivedCmd[0] == ISO14443A_CMD_WRITEBLOCK ||
receivedCmd[0] == MIFARE_CMD_INC ||
receivedCmd[0] == MIFARE_CMD_DEC ||
receivedCmd[0] == MIFARE_CMD_RESTORE ||
receivedCmd[0] == MIFARE_CMD_TRANSFER) {
// RATS
if (pRecvCmd[0] == ISO14443A_CMD_RATS) {
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
break;
}
if (receivedCmd[1] >= 16 * 4) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
if (MF_DBGLEVEL >= 4) Dbprintf("Reader tried to operate (0x%02) on out of range block: %d (0x%02x), nacking", receivedCmd[0], receivedCmd[1], receivedCmd[1]);
if (pRecvCmd[0] == ISO14443A_CMD_READBLOCK ||
pRecvCmd[0] == ISO14443A_CMD_WRITEBLOCK ||
pRecvCmd[0] == MIFARE_CMD_INC ||
pRecvCmd[0] == MIFARE_CMD_DEC ||
pRecvCmd[0] == MIFARE_CMD_RESTORE ||
pRecvCmd[0] == MIFARE_CMD_TRANSFER) {
if (!encrypted_data) {
EmSend4bit(CARD_NACK_NA);
if (MF_DBGLEVEL >= 4) Dbprintf("Reader tried to operate (0x%02) under non-encrypted state, nacking", pRecvCmd[0]);
break;
}
if (receivedCmd[1] / 4 != cardAUTHSC) {
if (len != 4) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
if (MF_DBGLEVEL >= 4) Dbprintf("Reader tried to operate (0x%02) on block (0x%02x) not authenticated for (0x%02x), nacking", receivedCmd[0], receivedCmd[1], cardAUTHSC);
if (MF_DBGLEVEL >= 4) Dbprintf("Request (0x%02) has invalid length, nacking", pRecvCmd[0]);
break;
}
block = pRecvCmd[1];
sector = MifareBlockToSector(block);
if (sector >= _SECTORS) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
if (MF_DBGLEVEL >= 4) Dbprintf("Reader tried to operate (0x%02) on out of range block: %d (0x%02x), nacking", pRecvCmd[0], block, block);
break;
}
if (sector != cardAUTHSC) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
if (MF_DBGLEVEL >= 4) Dbprintf("Reader tried to operate (0x%02) on block (0x%02x) not authenticated for (0x%02x) sector, nacking", pRecvCmd[0], block, cardAUTHSC);
break;
}
}
// read block
if (receivedCmd[0] == ISO14443A_CMD_READBLOCK) {
if (MF_DBGLEVEL >= 4) Dbprintf("Reader reading block %d (0x%02x)", receivedCmd[1], receivedCmd[1]);
if (pRecvCmd[0] == ISO14443A_CMD_READBLOCK) {
if (MF_DBGLEVEL >= 4) Dbprintf("Reader reading block %d (0x%02x)", block, block);
emlGetMem(response, receivedCmd[1], 1);
emlGetMem(response, block, 1);
AddCrc14A(response, 16);
mf_crypto1_encrypt(pcs, response, 18, response_par);
EmSendCmdPar(response, 18, response_par);
@ -3463,64 +3511,50 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
break;
}
// write block
if (receivedCmd[0] == ISO14443A_CMD_WRITEBLOCK) {
if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0xA0 write block %d (%02x)", receivedCmd[1], receivedCmd[1]);
if (pRecvCmd[0] == ISO14443A_CMD_WRITEBLOCK) {
if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0xA0 write block %d (%02x)", block, block);
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
cardSTATE = MFEMUL_WRITEBL2;
cardWRBL = receivedCmd[1];
cardWRBL = block;
break;
}
// increment, decrement, restore
if (receivedCmd[0] == MIFARE_CMD_INC ||
receivedCmd[0] == MIFARE_CMD_DEC ||
receivedCmd[0] == MIFARE_CMD_RESTORE) {
if (pRecvCmd[0] == MIFARE_CMD_INC ||
pRecvCmd[0] == MIFARE_CMD_DEC ||
pRecvCmd[0] == MIFARE_CMD_RESTORE) {
if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)", receivedCmd[0], receivedCmd[1], receivedCmd[1]);
if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)", pRecvCmd[0], block, block);
if (emlCheckValBl(receivedCmd[1])) {
if (emlCheckValBl(block)) {
if (MF_DBGLEVEL >= 4) Dbprintf("Reader tried to operate on block, but emlCheckValBl failed, nacking");
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
break;
}
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
if (receivedCmd[0] == MIFARE_CMD_INC) cardSTATE = MFEMUL_INTREG_INC;
if (receivedCmd[0] == MIFARE_CMD_DEC) cardSTATE = MFEMUL_INTREG_DEC;
if (receivedCmd[0] == MIFARE_CMD_RESTORE) cardSTATE = MFEMUL_INTREG_REST;
cardWRBL = receivedCmd[1];
if (pRecvCmd[0] == MIFARE_CMD_INC) cardSTATE = MFEMUL_INTREG_INC;
if (pRecvCmd[0] == MIFARE_CMD_DEC) cardSTATE = MFEMUL_INTREG_DEC;
if (pRecvCmd[0] == MIFARE_CMD_RESTORE) cardSTATE = MFEMUL_INTREG_REST;
cardWRBL = block;
break;
}
// transfer
if (receivedCmd[0] == MIFARE_CMD_TRANSFER) {
if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x transfer block %d (%02x)", receivedCmd[0], receivedCmd[1], receivedCmd[1]);
if (emlSetValBl(cardINTREG, cardINTBLOCK, receivedCmd[1]))
if (pRecvCmd[0] == MIFARE_CMD_TRANSFER) {
if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x transfer block %d (%02x)", pRecvCmd[0], block, block);
if (emlSetValBl(cardINTREG, cardINTBLOCK, block))
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
else
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
break;
}
// halt
if (receivedCmd[0] == ISO14443A_CMD_HALT && receivedCmd[1] == 0x00) {
LED_B_OFF();
LED_C_OFF();
cardSTATE = MFEMUL_HALTED;
if (MF_DBGLEVEL >= 4) Dbprintf("--> HALTED. Selected time: %d ms", GetTickCount() - selTimer);
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
break;
}
// RATS
if (receivedCmd[0] == ISO14443A_CMD_RATS) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
break;
}
// command not allowed
if (MF_DBGLEVEL >= 4) Dbprintf("Received command not allowed, nacking");
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
break;
}
case MFEMUL_WRITEBL2: {
if (len == 18) {
mf_crypto1_decrypt(pcs, receivedCmd, len);
emlSetMem(receivedCmd, cardWRBL, 1);
mf_crypto1_decryptEx(pcs, receivedCmd, len, decryptedCmd);
emlSetMem(decryptedCmd, cardWRBL, 1);
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
cardSTATE = MFEMUL_WORK;
} else {
@ -3530,8 +3564,8 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
break;
}
case MFEMUL_INTREG_INC: {
mf_crypto1_decrypt(pcs, receivedCmd, len);
memcpy(&ans, receivedCmd, 4);
mf_crypto1_decryptEx(pcs, receivedCmd, len, decryptedCmd);
memcpy(&ans, decryptedCmd, 4);
if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
cardSTATE_TO_IDLE();
@ -3543,8 +3577,8 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
break;
}
case MFEMUL_INTREG_DEC: {
mf_crypto1_decrypt(pcs, receivedCmd, len);
memcpy(&ans, receivedCmd, 4);
mf_crypto1_decryptEx(pcs, receivedCmd, len, decryptedCmd);
memcpy(&ans, decryptedCmd, 4);
if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
cardSTATE_TO_IDLE();
@ -3556,8 +3590,8 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
break;
}
case MFEMUL_INTREG_REST: {
mf_crypto1_decrypt(pcs, receivedCmd, len);
memcpy(&ans, receivedCmd, 4);
mf_crypto1_decryptEx(pcs, receivedCmd, len, decryptedCmd);
memcpy(&ans, decryptedCmd, 4);
if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
cardSTATE_TO_IDLE();

View file

@ -35,13 +35,17 @@ void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len) {
}
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par) {
mf_crypto1_encryptEx(pcs, data, NULL, data, len, par);
}
void mf_crypto1_encryptEx(struct Crypto1State *pcs, uint8_t *data_in, uint8_t *keystream, uint8_t *data_out, uint16_t len, uint8_t *par) {
uint8_t bt = 0;
int i;
par[0] = 0;
for (i = 0; i < len; i++) {
bt = data[i];
data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i];
bt = data_in[i];
data_out[i] = crypto1_byte(pcs, keystream ? keystream[i] : 0x00, 0) ^ data_in[i];
if ((i & 0x0007) == 0)
par[ i >> 3 ] = 0;
par[ i >> 3 ] |= (((filter(pcs->odd) ^ oddparity8(bt)) & 0x01) << (7 - (i & 0x0007)));

View file

@ -57,6 +57,10 @@
#define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF();
#ifndef MifareBlockToSector
#define MifareBlockToSector(block) (block < 128 ? block / 4 : (block - 128) / 16 + 32)
#endif
//functions
int mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);
@ -87,6 +91,7 @@ int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData);
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len);
void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out);
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par);
void mf_crypto1_encryptEx(struct Crypto1State *pcs, uint8_t *data_in, uint8_t *keystream, uint8_t *data_out, uint16_t len, uint8_t *par);
uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data);
// Mifare memory structure