mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-06-15 20:01:54 -07:00
WIP
This commit is contained in:
@@ -4,7 +4,9 @@
|
||||
enum SubmenuIndex {
|
||||
/*
|
||||
SubmenuIndexUnlock,
|
||||
*/
|
||||
SubmenuIndexSave,
|
||||
/*
|
||||
SubmenuIndexEmulate,
|
||||
*/
|
||||
SubmenuIndexInfo,
|
||||
@@ -24,8 +26,10 @@ void nfc_scene_felica_menu_on_enter(void* context) {
|
||||
/*
|
||||
submenu_add_item(
|
||||
submenu, "Unlock", SubmenuIndexUnlock, nfc_scene_felica_menu_submenu_callback, nfc);
|
||||
*/
|
||||
submenu_add_item(
|
||||
submenu, "Save", SubmenuIndexSave, nfc_scene_felica_menu_submenu_callback, nfc);
|
||||
/*
|
||||
submenu_add_item(
|
||||
submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_felica_menu_submenu_callback, nfc);
|
||||
*/
|
||||
@@ -43,13 +47,13 @@ bool nfc_scene_felica_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
/*
|
||||
if(event.event == SubmenuIndexSave) {
|
||||
nfc->dev->format = NfcDeviceSaveFormatFelica;
|
||||
// Clear device name
|
||||
nfc_device_set_name(nfc->dev, "");
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
consumed = true;
|
||||
/*
|
||||
} else if(event.event == SubmenuIndexEmulate) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaEmulate);
|
||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetType)) {
|
||||
@@ -61,9 +65,8 @@ bool nfc_scene_felica_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
} else if(event.event == SubmenuIndexUnlock) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaUnlockMenu);
|
||||
consumed = true;
|
||||
} else
|
||||
*/
|
||||
if(event.event == SubmenuIndexInfo) {
|
||||
} else if(event.event == SubmenuIndexInfo) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaInfoSelect);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
+1
-1
Submodule lib/STM32CubeWB updated: 06b8133fa2...a9e29b431f
+214
-20
@@ -20,6 +20,7 @@ static const uint32_t nfc_keys_file_version = 1;
|
||||
// Protocols format versions
|
||||
static const uint32_t nfc_mifare_classic_data_format_version = 2;
|
||||
static const uint32_t nfc_mifare_ultralight_data_format_version = 1;
|
||||
static const uint32_t nfc_felica_data_format_version = 1;
|
||||
|
||||
NfcDevice* nfc_device_alloc() {
|
||||
NfcDevice* nfc_dev = malloc(sizeof(NfcDevice));
|
||||
@@ -58,6 +59,8 @@ static void nfc_device_prepare_format_string(NfcDevice* dev, FuriString* format_
|
||||
furi_string_set(format_string, "Mifare Classic");
|
||||
} else if(dev->format == NfcDeviceSaveFormatMifareDesfire) {
|
||||
furi_string_set(format_string, "Mifare DESFire");
|
||||
} else if(dev->format == NfcDeviceSaveFormatFelica) {
|
||||
furi_string_set(format_string, "FeliCa");
|
||||
} else {
|
||||
furi_string_set(format_string, "Unknown");
|
||||
}
|
||||
@@ -781,6 +784,192 @@ static bool nfc_device_save_mifare_classic_data(FlipperFormat* file, NfcDevice*
|
||||
return saved;
|
||||
}
|
||||
|
||||
static bool nfc_device_save_felica_lite(FlipperFormat* file, FelicaLiteInfo* info) {
|
||||
bool saved = false;
|
||||
FuriString* key = furi_string_alloc();
|
||||
|
||||
do {
|
||||
flipper_format_write_comment_cstr(file, "Lite(-S) System");
|
||||
flipper_format_write_hex(file, "Data Format Code", info->data_format_code, sizeof(uint16_t));
|
||||
flipper_format_write_hex(file, "ID Arbitrary Value", info->ID_value, 6);
|
||||
flipper_format_write_hex(file, "Memory Config", info->memory_config, FELICA_BLOCK_SIZE);
|
||||
|
||||
for(uint8_t block_num = 0; block_num < 14; block_num++) {
|
||||
FuriString* spad_str = furi_string_alloc();
|
||||
for(size_t i = 0; i < FELICA_BLOCK_SIZE; i++) {
|
||||
if(info->S_PAD[block_num] != NULL) {
|
||||
furi_string_cat_printf(spad_str, "%02X ", info->S_PAD[block_num][i]);
|
||||
} else {
|
||||
furi_string_cat_printf(spad_str, "?? ");
|
||||
}
|
||||
}
|
||||
|
||||
furi_string_printf(key, "S_PAD%d", block_num);
|
||||
flipper_format_write_string(file, furi_string_get_cstr(key), spad_str);
|
||||
}
|
||||
|
||||
FuriString* reg_str = furi_string_alloc();
|
||||
for(size_t i = 0; i < FELICA_BLOCK_SIZE; i++) {
|
||||
if(info->REG != NULL) {
|
||||
furi_string_cat_printf(reg_str, "%02X ", info->REG[i]);
|
||||
} else {
|
||||
furi_string_cat_printf(reg_str, "?? ");
|
||||
}
|
||||
}
|
||||
flipper_format_write_string(file, "REG", reg_str);
|
||||
|
||||
flipper_format_write_hex(file, "Card Key Version", &info->card_key_version, sizeof(uint16_t));
|
||||
FuriString* ck1_str = furi_string_alloc();
|
||||
for(size_t i = 0; i < FELICA_BLOCK_SIZE; i++) {
|
||||
if(info->REG != NULL) {
|
||||
furi_string_cat_printf(ck1_str, "%02X ", info->card_key_1[i]);
|
||||
} else {
|
||||
furi_string_cat_printf(ck1_str, "?? ");
|
||||
}
|
||||
}
|
||||
flipper_format_write_string(file, "Card Key 1", ck1_str);
|
||||
|
||||
FuriString* ck2_str = furi_string_alloc();
|
||||
for(size_t i = 0; i < FELICA_BLOCK_SIZE; i++) {
|
||||
if(info->REG != NULL) {
|
||||
furi_string_cat_printf(ck2_str, "%02X ", info->card_key_2[i]);
|
||||
} else {
|
||||
furi_string_cat_printf(ck2_str, "?? ");
|
||||
}
|
||||
}
|
||||
flipper_format_write_string(file, "Card Key 2", ck2_str);
|
||||
|
||||
flipper_format_write_hex(file, "Fixed Challenge MAC Response", info->MAC, 8);
|
||||
|
||||
flipper_format_write_bool(file, "Is Lite-S", &info->is_lite_s, 1);
|
||||
if (info->is_lite_s) {
|
||||
flipper_format_write_hex(file, "Fixed Challenge MAC-A Response", info->MAC_A, 8);
|
||||
flipper_format_write_uint32(file, "Write Count", &info->write_count, 1);
|
||||
}
|
||||
|
||||
} while(false);
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
static bool nfc_device_save_felica_area(FlipperFormat* file, FelicaArea* area) {
|
||||
bool saved = false;
|
||||
FuriString* prefix = furi_string_alloc_printf("Area %d", area->number);
|
||||
FuriString* key = furi_string_alloc();
|
||||
|
||||
do {
|
||||
furi_string_printf(key, "%s Can Create Subareas", prefix);
|
||||
flipper_format_write_bool(file, furi_string_get_cstr(key), &area->can_create_subareas, 1);
|
||||
furi_string_printf(key, "%s End Service Code", prefix);
|
||||
flipper_format_write_hex(file, furi_string_get_cstr(key), (uint8_t*)&area->end_service_code, sizeof(uint16_t));
|
||||
|
||||
bool node_saved = true;
|
||||
for
|
||||
M_EACH(node, area->nodes, FelicaNodeArray_t) {
|
||||
if (nfc_device_save_felica_node(file, node)) {
|
||||
node_saved = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!node_saved) break;
|
||||
saved = true;
|
||||
} while(false);
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
static bool nfc_device_save_felica_service(FlipperFormat* file, FelicaService* service) {
|
||||
bool saved = false;
|
||||
FuriString* prefix = furi_string_alloc_printf("Service %d", service->number);
|
||||
FuriString* key = furi_string_alloc();
|
||||
|
||||
do {
|
||||
furi_string_printf(key, "%s Is Extended Overlap", prefix);
|
||||
flipper_format_write_bool(file, furi_string_get_cstr(key), &service->is_extended_overlap, 1);
|
||||
if (service->is_extended_overlap) {
|
||||
furi_string_printf(key, "%s Overlap Target", prefix);
|
||||
flipper_format_write_hex(file, furi_string_get_cstr(key), (uint8_t*)&service->overlap_target, sizeof(uint16_t));
|
||||
|
||||
furi_string_printf(key, "%s Block Start", prefix);
|
||||
const uint32_t block_start = service->block_start;
|
||||
flipper_format_write_uint32(file, furi_string_get_cstr(key), &block_start, 1);
|
||||
|
||||
furi_string_printf(key, "%s Block Count", prefix);
|
||||
const uint32_t block_count = service->block_count;
|
||||
flipper_format_write_uint32(file, furi_string_get_cstr(key), &block_count, 1);
|
||||
|
||||
uint32_t i = 0;
|
||||
for
|
||||
M_EACH(block, service->blocks, FelicaBlockArray_t) {
|
||||
furi_string_printf(key, "%s Block %d", prefix, i);
|
||||
flipper_format_write_hex(file, furi_string_get_cstr(key), block->data, FELICA_BLOCK_SIZE);
|
||||
}
|
||||
} else {
|
||||
furi_string_printf(key, "%s Block Count", prefix);
|
||||
uint32_t block_count = FelicaBlockArray_size(service->blocks);
|
||||
flipper_format_write_uint32(file, furi_string_get_cstr(key), &block_count, 1);
|
||||
uint32_t i = 0;
|
||||
for
|
||||
M_EACH(block, service->blocks, FelicaBlockArray_t) {
|
||||
furi_string_printf(key, "%s Block %d", prefix, i);
|
||||
flipper_format_write_hex(file, furi_string_get_cstr(key), block->data, FELICA_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
saved = true;
|
||||
} while(false);
|
||||
|
||||
}
|
||||
|
||||
static bool nfc_device_save_felica_node(FlipperFormat* file, FelicaNode* node) {
|
||||
bool saved = false;
|
||||
FuriString* key = furi_string_alloc();
|
||||
|
||||
do {
|
||||
if(node->type == FelicaNodeTypeArea) {
|
||||
if(!nfc_device_save_felica_node(file, node->area)) {
|
||||
saved = false;
|
||||
break;
|
||||
}
|
||||
} else if(node->type == FelicaNodeTypeService) {
|
||||
if(!nfc_device_save_felica_service(file, node->area)) {
|
||||
saved = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
saved = true;
|
||||
} while(false);
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
static bool nfc_device_save_felica_data(FlipperFormat* file, NfcDevice* dev) {
|
||||
bool saved = false;
|
||||
FelicaData* data = &dev->dev_data.felica_data;
|
||||
// Save FeliCa specific data
|
||||
do {
|
||||
if(!flipper_format_write_comment_cstr(file, "FeliCa specific data")) break;
|
||||
if(!flipper_format_write_uint32(
|
||||
file, "Data format version", &nfc_felica_data_format_version, 1))
|
||||
break;
|
||||
|
||||
for
|
||||
M_EACH(system, data->systems, FelicaSystemArray_t) {
|
||||
flipper_format_write_hex(file, "System", &system->number, sizeof(uint8_t));
|
||||
flipper_format_write_hex(file, "Code", (uint8_t*)&system->code, sizeof(uint16_t));
|
||||
if (system->code == LITE_SYSTEM_CODE) {
|
||||
nfc_device_save_felica_lite(file, &system->lite_info);
|
||||
} else {
|
||||
nfc_device_save_felica_node(file, &system->root);
|
||||
}
|
||||
}
|
||||
} while(false);
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
static void nfc_device_load_mifare_classic_block(
|
||||
FuriString* block_str,
|
||||
MfClassicData* data,
|
||||
@@ -1069,30 +1258,35 @@ bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
|
||||
if(!flipper_format_write_header_cstr(file, nfc_file_header, nfc_file_version)) break;
|
||||
// Write nfc device type
|
||||
if(!flipper_format_write_comment_cstr(
|
||||
file, "Nfc device type can be UID, Mifare Ultralight, Mifare Classic"))
|
||||
file, "Nfc device type can be UID, Mifare Ultralight, Mifare Classic, FeliCa"))
|
||||
break;
|
||||
nfc_device_prepare_format_string(dev, temp_str);
|
||||
if(!flipper_format_write_string(file, "Device type", temp_str)) break;
|
||||
// Write UID, ATQA, SAK
|
||||
if(!flipper_format_write_comment_cstr(file, "UID, ATQA and SAK are common for all formats"))
|
||||
break;
|
||||
if(!flipper_format_write_hex(file, "UID", data->uid, data->uid_len)) break;
|
||||
// Save ATQA in MSB order for correct companion apps display
|
||||
uint8_t atqa[2] = {data->a_data.atqa[1], data->a_data.atqa[0]};
|
||||
if(!flipper_format_write_hex(file, "ATQA", atqa, 2)) break;
|
||||
if(!flipper_format_write_hex(file, "SAK", &data->a_data.sak, 1)) break;
|
||||
// Save more data if necessary
|
||||
if(dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||
if(!nfc_device_save_mifare_ul_data(file, dev)) break;
|
||||
} else if(dev->format == NfcDeviceSaveFormatMifareDesfire) {
|
||||
if(!nfc_device_save_mifare_df_data(file, dev)) break;
|
||||
} else if(dev->format == NfcDeviceSaveFormatMifareClassic) {
|
||||
// Save data
|
||||
if(!nfc_device_save_mifare_classic_data(file, dev)) break;
|
||||
// Save keys cache
|
||||
if(!nfc_device_save_mifare_classic_keys(dev)) break;
|
||||
if(data->type == FuriHalNfcTypeA) {
|
||||
// Write UID, ATQA, SAK
|
||||
if(!flipper_format_write_comment_cstr(
|
||||
file, "UID, ATQA and SAK are common for all A formats"))
|
||||
break;
|
||||
if(!flipper_format_write_hex(file, "UID", data->uid, data->uid_len)) break;
|
||||
// Save ATQA in MSB order for correct companion apps display
|
||||
uint8_t atqa[2] = {data->a_data.atqa[1], data->a_data.atqa[0]};
|
||||
if(!flipper_format_write_hex(file, "ATQA", atqa, 2)) break;
|
||||
if(!flipper_format_write_hex(file, "SAK", &data->a_data.sak, 1)) break;
|
||||
// Save more data if necessary
|
||||
if(dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||
if(!nfc_device_save_mifare_ul_data(file, dev)) break;
|
||||
} else if(dev->format == NfcDeviceSaveFormatMifareDesfire) {
|
||||
if(!nfc_device_save_mifare_df_data(file, dev)) break;
|
||||
} else if(dev->format == NfcDeviceSaveFormatMifareClassic) {
|
||||
// Save data
|
||||
if(!nfc_device_save_mifare_classic_data(file, dev)) break;
|
||||
// Save keys cache
|
||||
if(!nfc_device_save_mifare_classic_keys(dev)) break;
|
||||
}
|
||||
saved = true;
|
||||
} else if(data->type == FuriHalNfcTypeF) {
|
||||
if(!nfc_device_save_felica_data(file, dev)) break;
|
||||
}
|
||||
saved = true;
|
||||
} while(0);
|
||||
|
||||
if(!saved) { //-V547
|
||||
|
||||
@@ -799,6 +799,7 @@ bool felica_lite_dump_data(
|
||||
}
|
||||
}
|
||||
if(data->type == FelicaICTypeLiteS) {
|
||||
lite_info->is_lite_s = true;
|
||||
const uint8_t fixed_s_blocks[] = {
|
||||
CARD_KEY_LITE_BLOCK,
|
||||
MAC_A_LITE_BLOCK,
|
||||
|
||||
@@ -206,6 +206,7 @@ typedef struct {
|
||||
uint16_t card_key_version;
|
||||
uint8_t memory_config[FELICA_BLOCK_SIZE];
|
||||
|
||||
bool is_lite_s;
|
||||
// Lite-S only
|
||||
uint8_t MAC_A[8];
|
||||
uint32_t write_count;
|
||||
@@ -294,8 +295,6 @@ uint8_t felica_lite_prepare_unencrypted_write(
|
||||
const uint8_t* block_data);
|
||||
bool felica_parse_unencrypted_write(uint8_t* buf, uint8_t len, FelicaReader* reader);
|
||||
|
||||
bool felica_lite_can_read_without_mac(uint8_t* mc_r_restr, uint8_t block_number);
|
||||
|
||||
void felica_define_normal_block(FelicaService* service, uint16_t number, uint8_t* data);
|
||||
void felica_push_normal_block(FelicaService* service, uint8_t* data);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user