Skip to content

Commit

Permalink
Merge pull request #13 from RogueMaster/dev-MuddleBoxUnlocks
Browse files Browse the repository at this point in the history
mifare classic and icon/menu changes
  • Loading branch information
RogueMaster authored May 18, 2022
2 parents 3401d47 + 843c9c6 commit bbf37eb
Show file tree
Hide file tree
Showing 16 changed files with 604 additions and 10 deletions.
23 changes: 23 additions & 0 deletions applications/nfc/nfc_worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <lib/nfc_protocols/mifare_ultralight.h>
#include <lib/nfc_protocols/mifare_classic.h>
#include <lib/nfc_protocols/mifare_desfire.h>
#include <lib/nfc_protocols/nfca.h>

#include "helpers/nfc_mf_classic_dict.h"

Expand Down Expand Up @@ -104,6 +105,8 @@ int32_t nfc_worker_task(void* context) {
nfc_worker_emulate_mifare_ul(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateReadMifareClassic) {
nfc_worker_mifare_classic_dict_attack(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateEmulateMifareClassic) {
nfc_worker_emulate_mifare_classic(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateReadMifareDesfire) {
nfc_worker_read_mifare_desfire(nfc_worker);
}
Expand Down Expand Up @@ -474,6 +477,26 @@ void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) {
stream_free(nfc_worker->dict_stream);
}

void nfc_worker_emulate_mifare_classic(NfcWorker* nfc_worker) {
FuriHalNfcTxRxContext tx_rx;
FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
MfClassicEmulator emulator = {
.cuid = nfc_util_bytes2num(&nfc_data->uid[nfc_data->uid_len - 4], 4),
.data = nfc_worker->dev_data->mf_classic_data,
};
NfcaSignal* nfca_signal = nfca_signal_alloc();
tx_rx.nfca_signal = nfca_signal;

while(nfc_worker->state == NfcWorkerStateEmulateMifareClassic) {
if(furi_hal_nfc_listen(
nfc_data->uid, nfc_data->uid_len, nfc_data->atqa, nfc_data->sak, true, 4000)) {
mf_classic_emulator(&emulator, &tx_rx);
}
}

nfca_signal_free(nfca_signal);
}

void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) {
ReturnCode err;
uint8_t tx_buff[64] = {};
Expand Down
1 change: 1 addition & 0 deletions applications/nfc/nfc_worker.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ typedef enum {
NfcWorkerStateReadMifareUltralight,
NfcWorkerStateEmulateMifareUltralight,
NfcWorkerStateReadMifareClassic,
NfcWorkerStateEmulateMifareClassic,
NfcWorkerStateReadMifareDesfire,
// Transition
NfcWorkerStateStop,
Expand Down
1 change: 1 addition & 0 deletions applications/nfc/scenes/nfc_scene_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ ADD_SCENE(nfc, restore_original, RestoreOriginal)
ADD_SCENE(nfc, debug, Debug)
ADD_SCENE(nfc, field, Field)
ADD_SCENE(nfc, read_mifare_classic, ReadMifareClassic)
ADD_SCENE(nfc, emulate_mifare_classic, EmulateMifareClassic)
ADD_SCENE(nfc, dict_not_found, DictNotFound)
64 changes: 64 additions & 0 deletions applications/nfc/scenes/nfc_scene_emulate_mifare_classic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "../nfc_i.h"
#include <dolphin/dolphin.h>

#define NFC_MF_CLASSIC_DATA_NOT_CHANGED (0UL)
#define NFC_MF_CLASSIC_DATA_CHANGED (1UL)

void nfc_emulate_mifare_classic_worker_callback(NfcWorkerEvent event, void* context) {
UNUSED(event);
Nfc* nfc = context;

scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneEmulateMifareUl, NFC_MF_CLASSIC_DATA_CHANGED);
}

void nfc_scene_emulate_mifare_classic_on_enter(void* context) {
Nfc* nfc = context;
DOLPHIN_DEED(DolphinDeedNfcEmulate);

// Setup view
Popup* popup = nfc->popup;
if(strcmp(nfc->dev->dev_name, "")) {
nfc_text_store_set(nfc, "%s", nfc->dev->dev_name);
}
popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61);
popup_set_header(popup, "Emulating\nMf Classic", 56, 31, AlignLeft, AlignTop);

// Setup and start worker
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
nfc_worker_start(
nfc->worker,
NfcWorkerStateEmulateMifareClassic,
&nfc->dev->dev_data,
nfc_emulate_mifare_classic_worker_callback,
nfc);
}

bool nfc_scene_emulate_mifare_classic_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;

if(event.type == SceneManagerEventTypeTick) {
notification_message(nfc->notifications, &sequence_blink_blue_10);
consumed = true;
} else if(event.type == SceneManagerEventTypeBack) {
// Stop worker
nfc_worker_stop(nfc->worker);
// Check if data changed and save in shadow file
if(scene_manager_get_scene_state(nfc->scene_manager, NfcSceneEmulateMifareUl) ==
NFC_MF_CLASSIC_DATA_CHANGED) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneEmulateMifareUl, NFC_MF_CLASSIC_DATA_NOT_CHANGED);
nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name);
}
consumed = false;
}
return consumed;
}

void nfc_scene_emulate_mifare_classic_on_exit(void* context) {
Nfc* nfc = context;

// Clear view
popup_reset(nfc->popup);
}
12 changes: 6 additions & 6 deletions applications/nfc/scenes/nfc_scene_saved_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,11 @@ void nfc_scene_saved_menu_on_enter(void* context) {
SubmenuIndexEmulate,
nfc_scene_saved_menu_submenu_callback,
nfc);
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
} else if(
nfc->dev->format == NfcDeviceSaveFormatMifareUl ||
nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
submenu_add_item(
submenu,
"Emulate Ultralight",
SubmenuIndexEmulate,
nfc_scene_saved_menu_submenu_callback,
nfc);
submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_saved_menu_submenu_callback, nfc);
}
submenu_add_item(
submenu, "Edit UID and Name", SubmenuIndexEdit, nfc_scene_saved_menu_submenu_callback, nfc);
Expand Down Expand Up @@ -64,6 +62,8 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
if(event.event == SubmenuIndexEmulate) {
if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl);
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareClassic);
} else {
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
}
Expand Down
89 changes: 87 additions & 2 deletions firmware/targets/f7/furi_hal/furi_hal_nfc.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#include "furi_hal_nfc.h"
#include <st25r3916.h>
#include <st25r3916_irq.h>
#include <rfal_rf.h>
#include <furi.h>
#include <m-string.h>
#include <lib/nfc_protocols/nfca.h>

#include <lib/digital_signal/digital_signal.h>
#include <furi_hal_delay.h>

#define TAG "FuriHalNfc"

Expand Down Expand Up @@ -394,6 +397,80 @@ ReturnCode furi_hal_nfc_data_exchange(
return ret;
}

static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) {
furi_assert(tx_rx->nfca_signal);

platformDisableIrqCallback();

bool ret = false;

// Start transparent mode
st25r3916ExecuteCommand(ST25R3916_CMD_TRANSPARENT_MODE);
// Reconfigure gpio
furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_nfc);
furi_hal_gpio_init(&gpio_spi_r_sck, GpioModeInput, GpioPullUp, GpioSpeedLow);
furi_hal_gpio_init(&gpio_spi_r_miso, GpioModeInput, GpioPullUp, GpioSpeedLow);
furi_hal_gpio_init(&gpio_nfc_cs, GpioModeInput, GpioPullUp, GpioSpeedLow);
furi_hal_gpio_init(&gpio_spi_r_mosi, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
furi_hal_gpio_write(&gpio_spi_r_mosi, false);

// Send signal
nfca_signal_encode(tx_rx->nfca_signal, tx_rx->tx_data, tx_rx->tx_bits / 8, tx_rx->tx_parity);
digital_signal_send(tx_rx->nfca_signal->tx_signal, &gpio_spi_r_mosi);
furi_hal_gpio_write(&gpio_spi_r_mosi, false);

// Configure gpio back to SPI and exit transparent
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc);
st25r3916ExecuteCommand(ST25R3916_CMD_UNMASK_RECEIVE_DATA);

// Manually wait for interrupt
furi_hal_gpio_init(&gpio_rfid_pull, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh);
st25r3916ClearAndEnableInterrupts(ST25R3916_IRQ_MASK_RXE);

uint32_t irq = 0;
uint8_t rxe = 0;
uint32_t start = DWT->CYCCNT;
while(true) {
if(furi_hal_gpio_read(&gpio_rfid_pull) == true) {
st25r3916ReadRegister(ST25R3916_REG_IRQ_MAIN, &rxe);
if(rxe & (1 << 4)) {
irq = 1;
break;
}
}
uint32_t timeout = DWT->CYCCNT - start;
if(timeout / furi_hal_delay_instructions_per_microsecond() > timeout_ms * 1000) {
FURI_LOG_D(TAG, "Interrupt waiting timeout");
break;
}
}
if(irq) {
uint8_t fifo_stat[2];
st25r3916ReadMultipleRegisters(
ST25R3916_REG_FIFO_STATUS1, fifo_stat, ST25R3916_FIFO_STATUS_LEN);
uint16_t len =
((((uint16_t)fifo_stat[1] & ST25R3916_REG_FIFO_STATUS2_fifo_b_mask) >>
ST25R3916_REG_FIFO_STATUS2_fifo_b_shift)
<< RFAL_BITS_IN_BYTE);
len |= (((uint16_t)fifo_stat[0]) & 0x00FFU);
uint8_t rx[100];
st25r3916ReadFifo(rx, len);

tx_rx->rx_bits = len * 8;
memcpy(tx_rx->rx_data, rx, len);

ret = true;
} else {
FURI_LOG_E(TAG, "Timeout error");
ret = false;
}

st25r3916ClearInterrupts();
platformEnableIrqCallback();

return ret;
}

static uint32_t furi_hal_nfc_tx_rx_get_flag(FuriHalNfcTxRxType type) {
uint32_t flags = 0;

Expand All @@ -405,6 +482,9 @@ static uint32_t furi_hal_nfc_tx_rx_get_flag(FuriHalNfcTxRxType type) {
} else if(type == FuriHalNfcTxRxTypeRaw) {
flags = RFAL_TXRX_FLAGS_CRC_TX_MANUAL | RFAL_TXRX_FLAGS_CRC_RX_KEEP |
RFAL_TXRX_FLAGS_PAR_RX_KEEP | RFAL_TXRX_FLAGS_PAR_TX_NONE;
} else if(type == FuriHalNfcTxRxTypeRxRaw) {
flags = RFAL_TXRX_FLAGS_CRC_TX_MANUAL | RFAL_TXRX_FLAGS_CRC_RX_KEEP |
RFAL_TXRX_FLAGS_PAR_RX_KEEP | RFAL_TXRX_FLAGS_PAR_TX_NONE;
}

return flags;
Expand Down Expand Up @@ -470,6 +550,10 @@ bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) {
uint8_t* temp_rx_buff = NULL;
uint16_t* temp_rx_bits = NULL;

if(tx_rx->tx_rx_type == FuriHalNfcTxRxTransparent) {
return furi_hal_nfc_transparent_tx_rx(tx_rx, timeout_ms);
}

// Prepare data for FIFO if necessary
uint32_t flags = furi_hal_nfc_tx_rx_get_flag(tx_rx->tx_rx_type);
if(tx_rx->tx_rx_type == FuriHalNfcTxRxTypeRaw) {
Expand Down Expand Up @@ -502,7 +586,8 @@ bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) {
osDelay(1);
}

if(tx_rx->tx_rx_type == FuriHalNfcTxRxTypeRaw) {
if(tx_rx->tx_rx_type == FuriHalNfcTxRxTypeRaw ||
tx_rx->tx_rx_type == FuriHalNfcTxRxTypeRxRaw) {
tx_rx->rx_bits = 8 * furi_hal_nfc_bitstream_to_data_and_parity(
temp_rx_buff, *temp_rx_bits, tx_rx->rx_data, tx_rx->rx_parity);
} else {
Expand Down
5 changes: 5 additions & 0 deletions firmware/targets/furi_hal_include/furi_hal_nfc.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include <stdbool.h>
#include <stdint.h>

#include <lib/nfc_protocols/nfca.h>

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -39,6 +41,8 @@ typedef enum {
FuriHalNfcTxRxTypeRxNoCrc,
FuriHalNfcTxRxTypeRxKeepPar,
FuriHalNfcTxRxTypeRaw,
FuriHalNfcTxRxTypeRxRaw,
FuriHalNfcTxRxTransparent,
} FuriHalNfcTxRxType;

typedef bool (*FuriHalNfcEmulateCallback)(
Expand Down Expand Up @@ -80,6 +84,7 @@ typedef struct {
uint8_t rx_parity[FURI_HAL_NFC_PARITY_BUFF_SIZE];
uint16_t rx_bits;
FuriHalNfcTxRxType tx_rx_type;
NfcaSignal* nfca_signal;
} FuriHalNfcTxRxContext;

/** Init nfc
Expand Down
Loading

0 comments on commit bbf37eb

Please sign in to comment.