Skip to content
This repository has been archived by the owner on Jul 28, 2024. It is now read-only.

Commit

Permalink
MagSpoof read PoC
Browse files Browse the repository at this point in the history
  • Loading branch information
hummusec committed May 19, 2023
1 parent a4df68c commit be79a9e
Show file tree
Hide file tree
Showing 11 changed files with 314 additions and 8 deletions.
6 changes: 3 additions & 3 deletions application.fam
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
App(
appid="mag",
name="MagSpoof WIP",
name="MagSpoof",
apptype=FlipperAppType.EXTERNAL,
entry_point="mag_app",
cdefines=["APP_MAG"],
Expand All @@ -11,10 +11,10 @@ App(
"dialogs",
],
provides=[],
stack_size=5 * 1024,
stack_size=6 * 1024,
order=64, # keep it at the bottom of the list while still WIP
fap_icon="icons/mag_10px.png",
fap_category="Tools",
fap_category="GPIO",
fap_icon_assets="icons",
fap_version=(0, 5), # major, minor
fap_description="WIP MagSpoof port using the RFID subsystem",
Expand Down
13 changes: 8 additions & 5 deletions helpers/mag_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

#define TAG "MagHelpers"

#define GPIO_PIN_A &gpio_ext_pa6
#define GPIO_PIN_B &gpio_ext_pa7
// Haviv Board - pins gpio_ext_pa7 & gpio_ext_pa6 was swapped.
#define GPIO_PIN_A &gpio_ext_pa7
#define GPIO_PIN_B &gpio_ext_pa6
#define GPIO_PIN_ENABLE &gpio_ext_pa4
#define RFID_PIN_OUT &gpio_rfid_carrier_out

Expand Down Expand Up @@ -126,10 +127,12 @@ void tx_init_rfid() {
// initialize RFID system for TX

// OTG needed for RFID? Or just legacy from GPIO?
furi_hal_power_enable_otg();
// furi_hal_power_enable_otg();
furi_hal_ibutton_pin_configure();

// furi_hal_ibutton_start_drive();
furi_hal_ibutton_pin_write(false);

furi_hal_ibutton_start_drive();
furi_hal_ibutton_pin_low();

// Initializing at GpioSpeedLow seems sufficient for our needs; no improvements seen by increasing speed setting

Expand Down
7 changes: 7 additions & 0 deletions helpers/mag_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,10 @@ typedef enum {
MagTxCC1101_434,
MagTxCC1101_868,
} MagTxState;


typedef enum {
UART_TerminalEventRefreshConsoleOutput = 0,
UART_TerminalEventStartConsole,
UART_TerminalEventStartKeyboard,
} UART_TerminalCustomEvent;
71 changes: 71 additions & 0 deletions mag_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,77 @@ bool mag_device_delete(MagDevice* mag_dev, bool use_load_path) {
return deleted;
}

bool mag_device_parse_card_string(MagDevice* mag_dev, FuriString* f_card_str) {
furi_assert(mag_dev);
FURI_LOG_D(TAG, "mag_device_parse_card_string");

const char* card_str = furi_string_get_cstr(f_card_str);

FURI_LOG_D(TAG, "Parsing card string: %s", card_str);

// Track 1
const char* track1_start = strchr(card_str, '%');
if(!track1_start) {
FURI_LOG_D(TAG, "Could not find track 1 start");
return false;
}
track1_start++;
const char* track1_end = strchr(track1_start, '?');
if(!track1_end) {
FURI_LOG_D(TAG, "Could not find track 1 end");
return false;
}
size_t track1_len = track1_end - track1_start;

FURI_LOG_D(TAG, "Track 1: %.*s", track1_len, track1_start);

mag_dev->dev_data.track[0].len = track1_len;
furi_string_printf(mag_dev->dev_data.track[0].str, "%%%.*s?", track1_len, track1_start);

// Track 2
const char* track2_start = strchr(track1_end, ';');
if (!track2_start) {
FURI_LOG_D(TAG, "Could not find track 2 start");
return true;
}

track2_start++;
const char* track2_end = strchr(track2_start, '?');
if(!track2_end) {
FURI_LOG_D(TAG, "Could not find track 2 end");
return true;
}
size_t track2_len = track2_end - track2_start;

FURI_LOG_D(TAG, "Track 2: %.*s", track2_len, track2_start);

mag_dev->dev_data.track[1].len = track2_len;
furi_string_printf(mag_dev->dev_data.track[1].str, "%%%.*s?", track2_len, track2_start);

// Track 3
const char* track3_start = strchr(track2_end, ';');
if (!track3_start) {
FURI_LOG_D(TAG, "Could not find track 3 start");
return true;
}

track3_start++;
const char* track3_end = strchr(track3_start, '?');
if(!track3_end) {
FURI_LOG_D(TAG, "Could not find track 3 end");
return true;
}
size_t track3_len = track3_end - track3_start;

FURI_LOG_D(TAG, "Track 3: %.*s", track3_len, track3_start);

mag_dev->dev_data.track[2].len = track3_len;
furi_string_printf(mag_dev->dev_data.track[2].str, "%%%.*s?", track3_len, track3_start);

return true;
}


void mag_device_set_loading_callback(
MagDevice* mag_dev,
MagLoadingCallback callback,
Expand Down
3 changes: 3 additions & 0 deletions mag_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ typedef void (*MagLoadingCallback)(void* context, bool state);

typedef struct {
FuriString* str;
size_t len;
} MagTrack;

typedef struct {
Expand Down Expand Up @@ -49,6 +50,8 @@ void mag_device_clear(MagDevice* mag_dev);

bool mag_device_delete(MagDevice* mag_dev, bool use_load_path);

bool mag_device_parse_card_string(MagDevice* mag_dev, FuriString* card_str);

void mag_device_set_loading_callback(
MagDevice* mag_dev,
MagLoadingCallback callback,
Expand Down
13 changes: 13 additions & 0 deletions mag_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <toolbox/value_index.h>

#include "scenes/mag_scene.h"
#include "scenes/mag_scene_read.h"

#define MAG_TEXT_STORE_SIZE 150

Expand All @@ -50,6 +51,7 @@ typedef struct {
uint32_t us_interpacket;
} MagSetting;


typedef struct {
ViewDispatcher* view_dispatcher;
Gui* gui;
Expand All @@ -76,6 +78,17 @@ typedef struct {

// Custom views
Mag_TextInput* mag_text_input;

// UART
FuriThread* uart_rx_thread;
FuriStreamBuffer* uart_rx_stream;
uint8_t uart_rx_buf[UART_RX_BUF_SIZE + 1];
void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context);

char uart_text_input_store[UART_TERMINAL_TEXT_INPUT_STORE_SIZE + 1];
FuriString* uart_text_box_store;
size_t uart_text_box_store_strlen;
// UART_TextInput* text_input;
} Mag;

void mag_text_store_set(Mag* mag, const char* text, ...);
Expand Down
1 change: 1 addition & 0 deletions scenes/mag_scene_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ ADD_SCENE(mag, delete_success, DeleteSuccess)
ADD_SCENE(mag, delete_confirm, DeleteConfirm)
ADD_SCENE(mag, exit_confirm, ExitConfirm)
ADD_SCENE(mag, under_construction, UnderConstruction)
ADD_SCENE(mag, read, Read)
178 changes: 178 additions & 0 deletions scenes/mag_scene_read.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
// Creator: Hummus@FlipperGang

#include "../mag_i.h"
#include "../helpers/mag_helpers.h"

#include "mag_scene_read.h"

#define TAG "MagSceneRead"

void uart_callback(UartIrqEvent event, uint8_t data, void *context) {
Mag* mag = context;
if(event == UartIrqEventRXNE) {
furi_stream_buffer_send(mag->uart_rx_stream, &data, 1, 0);
furi_thread_flags_set(furi_thread_get_id(mag->uart_rx_thread), WorkerEvtRxDone);
}
}

static int32_t uart_worker(void* context) {
Mag* mag = context;
mag->uart_rx_stream = furi_stream_buffer_alloc(UART_RX_BUF_SIZE, 1);
mag->uart_text_box_store_strlen = 0;

while (1) {
uint32_t events = furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
// furi_check((events & FuriFlagError) == 0);

if(events & WorkerEvtStop) break;
if(events & WorkerEvtRxDone) {
FURI_LOG_D(TAG, "WorkerEvtRxDone");
// notification_message(mag->notifications, &sequence_success);
size_t len = furi_stream_buffer_receive(mag->uart_rx_stream, mag->uart_rx_buf, UART_RX_BUF_SIZE, 200);
FURI_LOG_D(TAG, "UART RX len: %d", len);

if (len > 0) {
// If text box store gets too big, then truncate it
mag->uart_text_box_store_strlen += len;

if(mag->uart_text_box_store_strlen >= UART_TERMINAL_TEXT_BOX_STORE_SIZE - 1) {
furi_string_right(mag->uart_text_box_store, mag->uart_text_box_store_strlen / 2);
mag->uart_text_box_store_strlen = furi_string_size(mag->uart_text_box_store) + len;
}

// Add '\0' to the end of the string, and then add the new data
mag->uart_rx_buf[len] = '\0';
furi_string_cat_printf(mag->uart_text_box_store, "%s", mag->uart_rx_buf);

FURI_LOG_D(TAG, "UART RX buf: %*.s", len, mag->uart_rx_buf);
FURI_LOG_D(TAG, "UART RX store: %s", furi_string_get_cstr(mag->uart_text_box_store));

}

FURI_LOG_D(TAG, "UARTEventRxData");

view_dispatcher_send_custom_event(
mag->view_dispatcher, UARTEventRxData);

}
}

furi_stream_buffer_free(mag->uart_rx_stream);

return 0;
}

void update_widgets(Mag* mag) {
// Clear widget from all elements
widget_reset(mag->widget);

// Titlebar
widget_add_icon_element(mag->widget, 38, -1, &I_mag_file_10px);
widget_add_string_element(mag->widget, 64, 0, AlignCenter, AlignTop, FontPrimary, "READ");
widget_add_icon_element(mag->widget, 81, -1, &I_mag_file_10px);

// Text box
widget_add_text_scroll_element(mag->widget, 0, 10, 128, 40, furi_string_get_cstr(mag->uart_text_box_store));

// Buttons
widget_add_button_element(mag->widget, GuiButtonTypeLeft, "Clear", mag_widget_callback, mag);
widget_add_button_element(mag->widget, GuiButtonTypeRight, "Parse", mag_widget_callback, mag);
}

void mag_scene_read_on_enter(void* context) {
Mag* mag = context;
FuriString* message = furi_string_alloc();
furi_string_printf(message, "Flipper Elite, swipe a card!\n");
mag->uart_text_box_store = message;

view_dispatcher_switch_to_view(mag->view_dispatcher, MagViewWidget);

update_widgets(mag);


// Initialize UART
// furi_hal_console_disable();
furi_hal_uart_deinit(FuriHalUartIdUSART1);
furi_hal_uart_init(FuriHalUartIdUSART1, 9600);
furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_callback, mag);
FURI_LOG_D(TAG, "UART initialized");

mag->uart_rx_thread = furi_thread_alloc();
furi_thread_set_name(mag->uart_rx_thread, "UartRx");
furi_thread_set_stack_size(mag->uart_rx_thread, 1024);
furi_thread_set_context(mag->uart_rx_thread, mag);
furi_thread_set_callback(mag->uart_rx_thread, uart_worker);

furi_thread_start(mag->uart_rx_thread);
FURI_LOG_D(TAG, "UART worker started");
}

bool mag_scene_read_on_event(void* context, SceneManagerEvent event) {
Mag* mag = context;

bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
FURI_LOG_D(TAG, "Custom event: %ld", event.event);

switch(event.event) {
case GuiButtonTypeLeft: // Clear
consumed = true;
// Clear text box store
furi_string_reset(mag->uart_text_box_store);
mag->uart_text_box_store_strlen = 0;
break;

case GuiButtonTypeRight: // Parse
consumed = true;
FURI_LOG_D(TAG, "Trying to parse");
MagDevice* mag_dev = mag->mag_dev;

bool res = mag_device_parse_card_string(mag_dev, mag->uart_text_box_store);
furi_string_reset(mag->uart_text_box_store);
if(res) {
notification_message(mag->notifications, &sequence_success);

furi_string_printf(mag->uart_text_box_store, "Track 1: %.*s\nTrack 2: %.*s\nTrack 3: %.*s",
mag_dev->dev_data.track[0].len, furi_string_get_cstr(mag_dev->dev_data.track[0].str),
mag_dev->dev_data.track[1].len, furi_string_get_cstr(mag_dev->dev_data.track[1].str),
mag_dev->dev_data.track[2].len, furi_string_get_cstr(mag_dev->dev_data.track[2].str));

// Switch to saved menu scene
scene_manager_next_scene(mag->scene_manager, MagSceneSavedMenu);

} else {
furi_string_printf(mag->uart_text_box_store, "Failed to parse! Try again\n");
notification_message(mag->notifications, &sequence_error);
}

break;
}

update_widgets(mag);
}

return consumed;
}

void mag_scene_read_on_exit(void* context) {
Mag* mag = context;
// notification_message(mag->notifications, &sequence_blink_stop);
widget_reset(mag->widget);
// view_dispatcher_remove_view(mag->view_dispatcher, MagViewWidget);

// Stop UART worker
FURI_LOG_D(TAG, "Stopping UART worker");
furi_thread_flags_set(furi_thread_get_id(mag->uart_rx_thread), WorkerEvtStop);
furi_thread_join(mag->uart_rx_thread);
furi_thread_free(mag->uart_rx_thread);
FURI_LOG_D(TAG, "UART worker stopped");

furi_string_free(mag->uart_text_box_store);

furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, NULL, NULL);
furi_hal_uart_deinit(FuriHalUartIdUSART1);
// furi_hal_console_enable();

notification_message(mag->notifications, &sequence_blink_stop);
}
21 changes: 21 additions & 0 deletions scenes/mag_scene_read.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include <gui/modules/text_box.h>

#define UART_RX_BUF_SIZE (320)
#define UART_TERMINAL_TEXT_BOX_STORE_SIZE (4096)
#define UART_TERMINAL_TEXT_INPUT_STORE_SIZE (512)
#define UART_CH (FuriHalUartIdUSART1)
#define UART_BAUDRATE (9600)

typedef enum {
WorkerEvtStop = (1 << 0),
WorkerEvtRxDone = (1 << 1),
} WorkerEvtFlags;

typedef enum {
UARTEventRxData = 100,
} UARTEvents;


#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone)
Loading

0 comments on commit be79a9e

Please sign in to comment.