This commit is contained in:
nullableVoidPtr
2023-04-29 08:24:45 +08:00
parent 3235c2115c
commit f36beec01b
5 changed files with 223 additions and 26 deletions
@@ -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;
}
+214 -20
View File
@@ -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
+1
View File
@@ -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,
+1 -2
View File
@@ -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);