mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-24 05:34:45 -07:00
fetch wplugins
This commit is contained in:
@@ -311,3 +311,118 @@ uint8_t mf_classic_read_card(
|
||||
|
||||
return sectors_read;
|
||||
}
|
||||
|
||||
bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_rx) {
|
||||
furi_assert(emulator);
|
||||
furi_assert(tx_rx);
|
||||
|
||||
// Get first frame
|
||||
tx_rx->tx_bits = 0;
|
||||
tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault;
|
||||
furi_hal_nfc_tx_rx(tx_rx, 300);
|
||||
|
||||
// TODO support all commands
|
||||
uint8_t cmd = tx_rx->rx_data[0];
|
||||
if(!(cmd == 0x60 || cmd == 0x61)) {
|
||||
FURI_LOG_E(TAG, "Unsupported command");
|
||||
return false;
|
||||
}
|
||||
uint8_t block = tx_rx->rx_data[1];
|
||||
uint64_t key = 0;
|
||||
// TODO Now works only for 1k!!!
|
||||
uint8_t sector_trailer_block = block | 0x03;
|
||||
MfClassicSectorTrailer* sector_trailer =
|
||||
(MfClassicSectorTrailer*)emulator->data.block[sector_trailer_block].value;
|
||||
if(cmd & 0x01) {
|
||||
key = nfc_util_bytes2num(sector_trailer->key_b, 6);
|
||||
} else {
|
||||
key = nfc_util_bytes2num(sector_trailer->key_a, 6);
|
||||
}
|
||||
|
||||
uint32_t nonce = prng_successor(DWT->CYCCNT, 32);
|
||||
uint8_t nt[4];
|
||||
uint8_t nt_keystream[4];
|
||||
nfc_util_num2bytes(nonce, 4, nt);
|
||||
nfc_util_num2bytes(nonce ^ emulator->cuid, 4, nt_keystream);
|
||||
crypto1_init(&emulator->crypto, key);
|
||||
crypto1_word(&emulator->crypto, emulator->cuid ^ nonce, 0);
|
||||
|
||||
memcpy(tx_rx->tx_data, nt, sizeof(nt));
|
||||
tx_rx->tx_bits = sizeof(nt) * 8;
|
||||
tx_rx->tx_rx_type = FuriHalNfcTxRxTypeRxRaw;
|
||||
if(!furi_hal_nfc_tx_rx(tx_rx, 500)) {
|
||||
FURI_LOG_E(TAG, "Error in 1st data exchange");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(tx_rx->rx_bits != 64) {
|
||||
FURI_LOG_E(TAG, "Incorrect nr + ar");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t nr = nfc_util_bytes2num(tx_rx->rx_data, 4);
|
||||
uint32_t ar = nfc_util_bytes2num(&tx_rx->rx_data[4], 4);
|
||||
crypto1_word(&emulator->crypto, nr, 1);
|
||||
uint32_t cardRr = ar ^ crypto1_word(&emulator->crypto, 0, 0);
|
||||
if(cardRr != prng_successor(nonce, 64)) {
|
||||
FURI_LOG_E(TAG, "Wrong AUTH! %08X != %08X", cardRr, prng_successor(nonce, 64));
|
||||
// Don't send NACK, as tag don't send it
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t ans = prng_successor(nonce, 96);
|
||||
uint8_t responce[4] = {};
|
||||
nfc_util_num2bytes(ans, 4, responce);
|
||||
tx_rx->tx_parity[0] = 0;
|
||||
for(uint8_t i = 0; i < 4; i++) {
|
||||
tx_rx->tx_data[i] = crypto1_byte(&emulator->crypto, 0, 0) ^ responce[i];
|
||||
tx_rx->tx_parity[0] |=
|
||||
(((crypto1_filter(emulator->crypto.odd) ^ nfc_util_odd_parity8(responce[i])) & 0x01)
|
||||
<< (7 - (i & 0x0007)));
|
||||
}
|
||||
|
||||
tx_rx->tx_bits = 8 * 4;
|
||||
tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent;
|
||||
|
||||
if(!furi_hal_nfc_tx_rx(tx_rx, 500)) {
|
||||
FURI_LOG_E(TAG, "Error in 2nd data exchange");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t decrypted_cmd[4] = {};
|
||||
for(uint8_t i = 0; i < 4; i++) {
|
||||
decrypted_cmd[i] = crypto1_byte(&emulator->crypto, 0, 0) ^ tx_rx->rx_data[i];
|
||||
}
|
||||
|
||||
// FURI_LOG_I(TAG, "Decrypted: %02X %02X", decrypted_cmd[0], decrypted_cmd[1]);
|
||||
if(decrypted_cmd[0] != 0x30) {
|
||||
FURI_LOG_W(TAG, "Not read command");
|
||||
return false;
|
||||
}
|
||||
uint16_t block_num = decrypted_cmd[1];
|
||||
|
||||
// Send 0 block
|
||||
uint8_t block_data[18] = {};
|
||||
memcpy(block_data, emulator->data.block[block_num].value, MF_CLASSIC_BLOCK_SIZE);
|
||||
nfca_append_crc16(block_data, 16);
|
||||
tx_rx->tx_parity[0] = 0;
|
||||
tx_rx->tx_parity[1] = 0;
|
||||
tx_rx->tx_parity[2] = 0;
|
||||
|
||||
for(uint8_t i = 0; i < 18; i++) {
|
||||
tx_rx->tx_data[i] = crypto1_byte(&emulator->crypto, 0, 0) ^ block_data[i];
|
||||
tx_rx->tx_parity[i >> 3] |=
|
||||
(((crypto1_filter(emulator->crypto.odd) ^ nfc_util_odd_parity8(block_data[i])) & 0x01)
|
||||
<< (7 - (i & 0x0007)));
|
||||
}
|
||||
|
||||
tx_rx->tx_bits = 18 * 8;
|
||||
tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent;
|
||||
|
||||
if(!furi_hal_nfc_tx_rx(tx_rx, 500)) {
|
||||
FURI_LOG_E(TAG, "Error in Block emulation data exchange");
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user