mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-13 03:08:35 -07:00
NFC: slight FeliCa refactor
This commit is contained in:
@@ -39,11 +39,12 @@
|
|||||||
|
|
||||||
#include "rpc/rpc_app.h"
|
#include "rpc/rpc_app.h"
|
||||||
|
|
||||||
|
#include <m-list.h>
|
||||||
#include <m-array.h>
|
#include <m-array.h>
|
||||||
|
|
||||||
ARRAY_DEF(FelicaAreaPath, FelicaArea*, M_PTR_OPLIST);
|
ARRAY_DEF(FelicaAreaPath, FelicaArea*, M_PTR_OPLIST)
|
||||||
ARRAY_DEF(FuriStringStack, FuriString*, M_PTR_OPLIST);
|
LIST_DEF(FuriStringStack, FuriString*, FURI_STRING_OPLIST)
|
||||||
ARRAY_DEF(MfClassicUserKeys, char*, M_PTR_OPLIST);
|
ARRAY_DEF(MfClassicUserKeys, char*, M_PTR_OPLIST)
|
||||||
|
|
||||||
#define NFC_TEXT_STORE_SIZE 128
|
#define NFC_TEXT_STORE_SIZE 128
|
||||||
#define NFC_APP_FOLDER ANY_PATH("nfc")
|
#define NFC_APP_FOLDER ANY_PATH("nfc")
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
#include "../nfc_i.h"
|
#include "../nfc_i.h"
|
||||||
#include <dolphin/dolphin.h>
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
#define SYSTEM_EVENT
|
|
||||||
|
|
||||||
void nfc_scene_felica_info_select_submenu_callback(void* context, uint32_t index) {
|
void nfc_scene_felica_info_select_submenu_callback(void* context, uint32_t index) {
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
|
|
||||||
@@ -20,7 +18,7 @@ void nfc_scene_felica_info_select_on_enter(void* context) {
|
|||||||
|
|
||||||
submenu_add_item(submenu, "[Actions]", 0, nfc_scene_felica_info_select_submenu_callback, nfc);
|
submenu_add_item(submenu, "[Actions]", 0, nfc_scene_felica_info_select_submenu_callback, nfc);
|
||||||
uint8_t i = 1;
|
uint8_t i = 1;
|
||||||
if(state->selected_system == NULL) {
|
if(state->selected_system == NULL || state->selected_system->code == LITE_SYSTEM_CODE) {
|
||||||
submenu_set_header(submenu, "Systems");
|
submenu_set_header(submenu, "Systems");
|
||||||
FelicaSystemList_it_t it;
|
FelicaSystemList_it_t it;
|
||||||
for(FelicaSystemList_it(it, data->systems); !FelicaSystemList_end_p(it);
|
for(FelicaSystemList_it(it, data->systems); !FelicaSystemList_end_p(it);
|
||||||
@@ -59,8 +57,7 @@ void nfc_scene_felica_info_select_on_enter(void* context) {
|
|||||||
FelicaNodeList_next(it)) {
|
FelicaNodeList_next(it)) {
|
||||||
FelicaNode* node = *FelicaNodeList_ref(it);
|
FelicaNode* node = *FelicaNodeList_ref(it);
|
||||||
if(node->type == FelicaNodeTypeArea) {
|
if(node->type == FelicaNodeTypeArea) {
|
||||||
FuriString* area_name =
|
FuriString* area_name = furi_string_alloc_printf("Area %d", node->area->number);
|
||||||
furi_string_alloc_printf("Area %d", node->ptr.area->number);
|
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu,
|
submenu,
|
||||||
furi_string_get_cstr(area_name),
|
furi_string_get_cstr(area_name),
|
||||||
@@ -69,7 +66,7 @@ void nfc_scene_felica_info_select_on_enter(void* context) {
|
|||||||
nfc);
|
nfc);
|
||||||
FuriStringStack_push_back(state->strings, area_name);
|
FuriStringStack_push_back(state->strings, area_name);
|
||||||
} else {
|
} else {
|
||||||
uint16_t service_code = node->ptr.service->number << 6;
|
uint16_t service_code = node->service->number << 6;
|
||||||
FuriString* service_name = furi_string_alloc_printf("Service %04X", service_code);
|
FuriString* service_name = furi_string_alloc_printf("Service %04X", service_code);
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu,
|
submenu,
|
||||||
@@ -106,7 +103,11 @@ bool nfc_scene_felica_info_select_on_event(void* context, SceneManagerEvent even
|
|||||||
index -= 1;
|
index -= 1;
|
||||||
if(state->selected_system == NULL) {
|
if(state->selected_system == NULL) {
|
||||||
state->selected_system = *FelicaSystemList_get(data->systems, index);
|
state->selected_system = *FelicaSystemList_get(data->systems, index);
|
||||||
|
if(state->selected_system->code == LITE_SYSTEM_CODE) {
|
||||||
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaServiceData);
|
||||||
|
} else {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaInfoSelect);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaInfoSelect);
|
||||||
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else {
|
} else {
|
||||||
FelicaNode* selected_node = NULL;
|
FelicaNode* selected_node = NULL;
|
||||||
@@ -119,11 +120,11 @@ bool nfc_scene_felica_info_select_on_event(void* context, SceneManagerEvent even
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(selected_node->type == FelicaNodeTypeArea) {
|
if(selected_node->type == FelicaNodeTypeArea) {
|
||||||
FelicaAreaPath_push_back(state->selected_areas, selected_node->ptr.area);
|
FelicaAreaPath_push_back(state->selected_areas, selected_node->area);
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaInfoSelect);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaInfoSelect);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(selected_node->type == FelicaNodeTypeService) {
|
} else if(selected_node->type == FelicaNodeTypeService) {
|
||||||
state->selected_service = selected_node->ptr.service;
|
state->selected_service = selected_node->service;
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaServiceData);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaServiceData);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
@@ -146,10 +147,6 @@ void nfc_scene_felica_info_select_on_exit(void* context) {
|
|||||||
|
|
||||||
// Clear view
|
// Clear view
|
||||||
FelicaAreaPath_clear(nfc->felica_select.selected_areas);
|
FelicaAreaPath_clear(nfc->felica_select.selected_areas);
|
||||||
FuriStringStack_it_t it;
|
FuriStringStack_clear(nfc->felica_select.strings);
|
||||||
for(FuriStringStack_it(it, nfc->felica_select.strings); !FuriStringStack_end_p(it);
|
|
||||||
FuriStringStack_next(it)) {
|
|
||||||
furi_string_free(*FuriStringStack_ref(it));
|
|
||||||
}
|
|
||||||
submenu_reset(nfc->submenu);
|
submenu_reset(nfc->submenu);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,21 +4,22 @@ void nfc_scene_felica_service_data_on_enter(void* context) {
|
|||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
FelicaSelectState* select_state = &nfc->felica_select;
|
FelicaSelectState* select_state = &nfc->felica_select;
|
||||||
FelicaSystem* system = select_state->selected_system;
|
FelicaSystem* system = select_state->selected_system;
|
||||||
FelicaService* service = select_state->selected_service;
|
//FelicaService* service = select_state->selected_service;
|
||||||
TextBox* text_box = nfc->text_box;
|
TextBox* text_box = nfc->text_box;
|
||||||
|
|
||||||
if(system->code == LITE_SYSTEM_CODE && service->number == 0) {
|
if(system->code == LITE_SYSTEM_CODE) {
|
||||||
|
FelicaLiteInfo* lite_info = &system->lite_info;
|
||||||
|
uint8_t* data;
|
||||||
text_box_set_font(text_box, TextBoxFontHex);
|
text_box_set_font(text_box, TextBoxFontHex);
|
||||||
furi_string_cat_str(nfc->text_box_store, "S_PAD:\n");
|
furi_string_cat_str(nfc->text_box_store, "S_PAD:\n");
|
||||||
for(int i = 0; i < REG_LITE_BLOCK; i++) {
|
for(int i = 0; i < REG_LITE_BLOCK; i++) {
|
||||||
FelicaBlock* block = *FelicaBlockList_cget(service->blocks, i);
|
data = lite_info->S_PAD[i];
|
||||||
for(uint16_t i = 0; i < FELICA_BLOCK_SIZE; i += 2) {
|
for(uint16_t i = 0; i < FELICA_BLOCK_SIZE; i += 2) {
|
||||||
if(!(i % 8) && i) {
|
if(!(i % 8) && i) {
|
||||||
furi_string_push_back(nfc->text_box_store, '\n');
|
furi_string_push_back(nfc->text_box_store, '\n');
|
||||||
}
|
}
|
||||||
if(block != NULL) {
|
if(data != NULL) {
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(nfc->text_box_store, "%02X%02X ", data[i], data[i + 1]);
|
||||||
nfc->text_box_store, "%02X%02X ", block->data[i], block->data[i + 1]);
|
|
||||||
} else {
|
} else {
|
||||||
furi_string_cat_printf(nfc->text_box_store, "???? ");
|
furi_string_cat_printf(nfc->text_box_store, "???? ");
|
||||||
}
|
}
|
||||||
@@ -26,107 +27,56 @@ void nfc_scene_felica_service_data_on_enter(void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
furi_string_cat_str(nfc->text_box_store, "REG:\n");
|
furi_string_cat_str(nfc->text_box_store, "REG:\n");
|
||||||
FelicaBlock* block = *FelicaBlockList_cget(service->blocks, REG_LITE_BLOCK);
|
data = lite_info->REG;
|
||||||
for(uint16_t i = 0; i < FELICA_BLOCK_SIZE; i += 2) {
|
for(uint16_t i = 0; i < FELICA_BLOCK_SIZE; i += 2) {
|
||||||
if(!(i % 8) && i) {
|
if(!(i % 8) && i) {
|
||||||
furi_string_push_back(nfc->text_box_store, '\n');
|
furi_string_push_back(nfc->text_box_store, '\n');
|
||||||
}
|
}
|
||||||
if(block != NULL) {
|
if(data != NULL) {
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(nfc->text_box_store, "%02X%02X ", data[i], data[i + 1]);
|
||||||
nfc->text_box_store, "%02X%02X ", block->data[i], block->data[i + 1]);
|
|
||||||
} else {
|
} else {
|
||||||
furi_string_cat_printf(nfc->text_box_store, "???? ");
|
furi_string_cat_printf(nfc->text_box_store, "???? ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_string_cat_str(nfc->text_box_store, "RC:\n");
|
|
||||||
block = *FelicaBlockList_cget(service->blocks, RC_LITE_BLOCK);
|
|
||||||
for(uint16_t i = 0; i < FELICA_BLOCK_SIZE; i += 2) {
|
|
||||||
if(!(i % 8) && i) {
|
|
||||||
furi_string_push_back(nfc->text_box_store, '\n');
|
|
||||||
}
|
|
||||||
furi_string_cat_printf(
|
|
||||||
nfc->text_box_store, "%02X%02X ", block->data[i], block->data[i + 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
furi_string_cat_str(nfc->text_box_store, "MAC:\n");
|
furi_string_cat_str(nfc->text_box_store, "MAC:\n");
|
||||||
block = *FelicaBlockList_cget(service->blocks, MAC_LITE_BLOCK);
|
data = lite_info->MAC;
|
||||||
for(uint16_t i = 0; i < FELICA_BLOCK_SIZE; i += 2) {
|
for(uint16_t i = 0; i < 8; i += 2) {
|
||||||
if(!(i % 8) && i) {
|
if(!(i % 8) && i) {
|
||||||
furi_string_push_back(nfc->text_box_store, '\n');
|
furi_string_push_back(nfc->text_box_store, '\n');
|
||||||
}
|
}
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(nfc->text_box_store, "%02X%02X ", data[i], data[i + 1]);
|
||||||
nfc->text_box_store, "%02X%02X ", block->data[i], block->data[i + 1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_string_cat_str(nfc->text_box_store, "ID:\n");
|
furi_string_cat_printf(nfc->text_box_store, "DFC: %04X\n", lite_info->data_format_code);
|
||||||
block = *FelicaBlockList_cget(service->blocks, ID_LITE_BLOCK);
|
|
||||||
for(uint16_t i = 0; i < FELICA_BLOCK_SIZE; i += 2) {
|
|
||||||
if(!(i % 8) && i) {
|
|
||||||
furi_string_push_back(nfc->text_box_store, '\n');
|
|
||||||
}
|
|
||||||
furi_string_cat_printf(
|
|
||||||
nfc->text_box_store, "%02X%02X ", block->data[i], block->data[i + 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
furi_string_cat_str(nfc->text_box_store, "D_ID:\n");
|
furi_string_cat_str(nfc->text_box_store, "ID data:\n");
|
||||||
block = *FelicaBlockList_cget(service->blocks, DEVICE_ID_LITE_BLOCK);
|
data = lite_info->ID_value;
|
||||||
for(uint16_t i = 0; i < FELICA_BLOCK_SIZE; i += 2) {
|
for(uint16_t i = 0; i < 6; i += 2) {
|
||||||
if(!(i % 8) && i) {
|
furi_string_cat_printf(nfc->text_box_store, "%02X%02X ", data[i], data[i + 1]);
|
||||||
furi_string_push_back(nfc->text_box_store, '\n');
|
|
||||||
}
|
|
||||||
furi_string_cat_printf(
|
|
||||||
nfc->text_box_store, "%02X%02X ", block->data[i], block->data[i + 1]);
|
|
||||||
}
|
}
|
||||||
|
furi_string_cat_str(nfc->text_box_store, "\n");
|
||||||
|
|
||||||
furi_string_cat_str(nfc->text_box_store, "CKV:\n");
|
furi_string_cat_printf(nfc->text_box_store, "CKV: %04X\n", lite_info->card_key_version);
|
||||||
block = *FelicaBlockList_cget(service->blocks, CARD_KEY_VER_LITE_BLOCK);
|
|
||||||
for(uint16_t i = 0; i < FELICA_BLOCK_SIZE; i += 2) {
|
|
||||||
if(!(i % 8) && i) {
|
|
||||||
furi_string_push_back(nfc->text_box_store, '\n');
|
|
||||||
}
|
|
||||||
furi_string_cat_printf(
|
|
||||||
nfc->text_box_store, "%02X%02X ", block->data[i], block->data[i + 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
furi_string_cat_str(nfc->text_box_store, "MC:\n");
|
furi_string_cat_str(nfc->text_box_store, "MC:\n");
|
||||||
block = *FelicaBlockList_cget(service->blocks, MEM_CONFIG_LITE_BLOCK);
|
data = lite_info->memory_config;
|
||||||
for(uint16_t i = 0; i < FELICA_BLOCK_SIZE; i += 2) {
|
for(uint16_t i = 0; i < FELICA_BLOCK_SIZE; i += 2) {
|
||||||
if(!(i % 8) && i) {
|
if(!(i % 8) && i) {
|
||||||
furi_string_push_back(nfc->text_box_store, '\n');
|
furi_string_push_back(nfc->text_box_store, '\n');
|
||||||
}
|
}
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(nfc->text_box_store, "%02X%02X ", data[i], data[i + 1]);
|
||||||
nfc->text_box_store, "%02X%02X ", block->data[i], block->data[i + 1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_string_cat_str(nfc->text_box_store, "WCNT:\n");
|
furi_string_cat_printf(nfc->text_box_store, "WCNT: %06lX\n", lite_info->write_count);
|
||||||
block = *FelicaBlockList_cget(service->blocks, WRITE_COUNT_LITE_BLOCK);
|
|
||||||
for(uint16_t i = 0; i < FELICA_BLOCK_SIZE; i += 2) {
|
|
||||||
if(!(i % 8) && i) {
|
|
||||||
furi_string_push_back(nfc->text_box_store, '\n');
|
|
||||||
}
|
|
||||||
furi_string_cat_printf(
|
|
||||||
nfc->text_box_store, "%02X%02X ", block->data[i], block->data[i + 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
furi_string_cat_str(nfc->text_box_store, "MAC_A:\n");
|
furi_string_cat_str(nfc->text_box_store, "MAC_A:\n");
|
||||||
block = *FelicaBlockList_cget(service->blocks, MAC_A_LITE_BLOCK);
|
data = lite_info->MAC_A;
|
||||||
for(uint16_t i = 0; i < FELICA_BLOCK_SIZE; i += 2) {
|
for(uint16_t i = 0; i < 8; i += 2) {
|
||||||
if(!(i % 8) && i) {
|
if(!(i % 8) && i) {
|
||||||
furi_string_push_back(nfc->text_box_store, '\n');
|
furi_string_push_back(nfc->text_box_store, '\n');
|
||||||
}
|
}
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(nfc->text_box_store, "%02X%02X ", data[i], data[i + 1]);
|
||||||
nfc->text_box_store, "%02X%02X ", block->data[i], block->data[i + 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
furi_string_cat_str(nfc->text_box_store, "CRC_CHECK:\n");
|
|
||||||
block = *FelicaBlockList_cget(service->blocks, CRC_CHECK_LITE_BLOCK);
|
|
||||||
for(uint16_t i = 0; i < FELICA_BLOCK_SIZE; i += 2) {
|
|
||||||
if(!(i % 8) && i) {
|
|
||||||
furi_string_push_back(nfc->text_box_store, '\n');
|
|
||||||
}
|
|
||||||
furi_string_cat_printf(
|
|
||||||
nfc->text_box_store, "%02X%02X ", block->data[i], block->data[i + 1]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
text_box_set_text(text_box, furi_string_get_cstr(nfc->text_box_store));
|
text_box_set_text(text_box, furi_string_get_cstr(nfc->text_box_store));
|
||||||
|
|||||||
@@ -189,8 +189,8 @@ uint8_t felica_lite_prepare_unencrypted_read(
|
|||||||
dest[9] = 1;
|
dest[9] = 1;
|
||||||
uint8_t msg_len = 10;
|
uint8_t msg_len = 10;
|
||||||
uint8_t service_code =
|
uint8_t service_code =
|
||||||
RANDOM_TYPE_SERVICE_ATTRIBUTE |
|
FelicaServiceTypeRandom |
|
||||||
((is_read_only) ? UNAUTH_RO_SERVICE_ATTRIBUTE : UNAUTH_RW_SERVICE_ATTRIBUTE);
|
((is_read_only) ? FelicaServiceAttributeUnauthRO : FelicaServiceAttributeUnauthRO);
|
||||||
|
|
||||||
dest[msg_len++] = service_code & 0xFF;
|
dest[msg_len++] = service_code & 0xFF;
|
||||||
dest[msg_len++] = service_code >> 8;
|
dest[msg_len++] = service_code >> 8;
|
||||||
@@ -240,7 +240,7 @@ uint16_t felica_parse_unencrypted_read(
|
|||||||
if(len < 1) {
|
if(len < 1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
uint16_t data_length = *buf * 16;
|
uint16_t data_length = *buf * FELICA_BLOCK_SIZE;
|
||||||
len--;
|
len--;
|
||||||
buf++;
|
buf++;
|
||||||
|
|
||||||
@@ -296,7 +296,7 @@ uint8_t felica_lite_prepare_unencrypted_write(
|
|||||||
|
|
||||||
dest[9] = 1;
|
dest[9] = 1;
|
||||||
uint8_t msg_len = 10;
|
uint8_t msg_len = 10;
|
||||||
uint8_t service_code = RANDOM_TYPE_SERVICE_ATTRIBUTE | UNAUTH_RW_SERVICE_ATTRIBUTE;
|
uint8_t service_code = FelicaServiceTypeRandom | FelicaServiceAttributeUnauthRW;
|
||||||
dest[msg_len++] = service_code & 0xFF;
|
dest[msg_len++] = service_code & 0xFF;
|
||||||
dest[msg_len++] = service_code >> 8;
|
dest[msg_len++] = service_code >> 8;
|
||||||
|
|
||||||
@@ -367,7 +367,6 @@ 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_define_normal_block(FelicaService* service, uint16_t number, uint8_t* data) {
|
||||||
FelicaBlock* block = malloc(sizeof(FelicaBlock));
|
FelicaBlock* block = malloc(sizeof(FelicaBlock));
|
||||||
block->type = FelicaBlockTypeNormal;
|
|
||||||
memcpy(block->data, data, FELICA_BLOCK_SIZE);
|
memcpy(block->data, data, FELICA_BLOCK_SIZE);
|
||||||
FelicaBlockList_set_at(service->blocks, number, block);
|
FelicaBlockList_set_at(service->blocks, number, block);
|
||||||
}
|
}
|
||||||
@@ -377,12 +376,13 @@ bool felica_read_lite_system(
|
|||||||
FelicaReader* reader,
|
FelicaReader* reader,
|
||||||
FelicaData* data,
|
FelicaData* data,
|
||||||
FelicaSystem* system) {
|
FelicaSystem* system) {
|
||||||
const uint8_t fixed_services[] = {
|
const uint8_t fixed_blocks[] = {
|
||||||
SYS_CODE_LITE_BLOCK,
|
SYS_CODE_LITE_BLOCK,
|
||||||
RC_LITE_BLOCK,
|
|
||||||
ID_LITE_BLOCK,
|
|
||||||
MAC_LITE_BLOCK,
|
|
||||||
DEVICE_ID_LITE_BLOCK,
|
DEVICE_ID_LITE_BLOCK,
|
||||||
|
ID_LITE_BLOCK,
|
||||||
|
RC_LITE_BLOCK,
|
||||||
|
CARD_KEY_LITE_BLOCK,
|
||||||
|
MAC_LITE_BLOCK,
|
||||||
CARD_KEY_VER_LITE_BLOCK,
|
CARD_KEY_VER_LITE_BLOCK,
|
||||||
MEM_CONFIG_LITE_BLOCK,
|
MEM_CONFIG_LITE_BLOCK,
|
||||||
};
|
};
|
||||||
@@ -390,7 +390,7 @@ bool felica_read_lite_system(
|
|||||||
uint8_t block_data[FELICA_BLOCK_SIZE * 4];
|
uint8_t block_data[FELICA_BLOCK_SIZE * 4];
|
||||||
|
|
||||||
tx_rx->tx_bits =
|
tx_rx->tx_bits =
|
||||||
8 * felica_lite_prepare_unencrypted_read(tx_rx->tx_data, reader, true, fixed_services, 1);
|
8 * felica_lite_prepare_unencrypted_read(tx_rx->tx_data, reader, true, fixed_blocks, 1);
|
||||||
if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
|
if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
|
||||||
FURI_LOG_W(TAG, "Bad exchange verifying Lite system code");
|
FURI_LOG_W(TAG, "Bad exchange verifying Lite system code");
|
||||||
return false;
|
return false;
|
||||||
@@ -401,33 +401,56 @@ bool felica_read_lite_system(
|
|||||||
FURI_LOG_W(TAG, "Bad response to Read without Encryption (SYS_C)");
|
FURI_LOG_W(TAG, "Bad response to Read without Encryption (SYS_C)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(block_data[0] != (LITE_SYSTEM_CODE >> 8) && block_data[1] != (LITE_SYSTEM_CODE & 0xFF)) {
|
if(nfc_util_bytes2num(block_data, 2) != LITE_SYSTEM_CODE) {
|
||||||
FURI_LOG_W(TAG, "Unexpected SYS_C value");
|
FURI_LOG_W(TAG, "Unexpected SYS_C value");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
system->code = LITE_SYSTEM_CODE;
|
|
||||||
|
|
||||||
FelicaArea* area = &system->root_area;
|
tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_read(
|
||||||
FelicaService* service = malloc(sizeof(FelicaService));
|
tx_rx->tx_data, reader, true, &fixed_blocks[1], 1);
|
||||||
FelicaBlockList_init(service->blocks);
|
if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
|
||||||
for(int i = 0; i < CRC_CHECK_LITE_BLOCK; i++) {
|
FURI_LOG_W(TAG, "Bad exchange reading D_ID");
|
||||||
FelicaBlockList_push_back(service->blocks, NULL);
|
return false;
|
||||||
|
}
|
||||||
|
if(felica_parse_unencrypted_read(
|
||||||
|
tx_rx->rx_data, tx_rx->rx_bits / 8, reader, block_data, sizeof(block_data)) !=
|
||||||
|
FELICA_BLOCK_SIZE) {
|
||||||
|
FURI_LOG_W(TAG, "Bad response to Read without Encryption (D_ID)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(memcmp(system->idm, block_data, 8) != 0 || memcmp(system->pmm, block_data + 8, 8) != 0) {
|
||||||
|
FURI_LOG_W(TAG, "Mismatching values for D_ID");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
area->number = 0;
|
system->code = LITE_SYSTEM_CODE;
|
||||||
area->end_service_code = 0x000f;
|
|
||||||
FelicaNodeList_init(area->nodes);
|
|
||||||
FelicaNode* node = malloc(sizeof(node));
|
|
||||||
node->type = FelicaNodeTypeService, node->ptr.service = service;
|
|
||||||
FelicaNodeList_push_back(area->nodes, node);
|
|
||||||
|
|
||||||
service->number = 0;
|
FelicaLiteInfo* lite_info = &system->lite_info;
|
||||||
|
lite_info->card_key_1 = NULL;
|
||||||
|
lite_info->card_key_2 = NULL;
|
||||||
|
|
||||||
felica_define_normal_block(service, SYS_CODE_LITE_BLOCK, block_data);
|
tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_read(
|
||||||
|
tx_rx->tx_data, reader, true, &fixed_blocks[2], 1);
|
||||||
|
if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
|
||||||
|
FURI_LOG_W(TAG, "Bad exchange reading ID");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(felica_parse_unencrypted_read(
|
||||||
|
tx_rx->rx_data, tx_rx->rx_bits / 8, reader, block_data, sizeof(block_data)) !=
|
||||||
|
FELICA_BLOCK_SIZE) {
|
||||||
|
FURI_LOG_W(TAG, "Bad response to Read without Encryption (ID)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
lite_info->data_format_code = nfc_util_bytes2num(block_data + 8, 2);
|
||||||
|
memcpy(lite_info->ID_value, block_data + 10, 6);
|
||||||
|
FURI_LOG_I(TAG, "ID:");
|
||||||
|
for(int i = 0; i < FELICA_BLOCK_SIZE; i++) {
|
||||||
|
FURI_LOG_I(TAG, "%02X", block_data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
memset(block_data, 0, FELICA_BLOCK_SIZE);
|
memset(block_data, 0, FELICA_BLOCK_SIZE);
|
||||||
tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_write(
|
tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_write(
|
||||||
tx_rx->tx_data, reader, &fixed_services[1], 1, block_data);
|
tx_rx->tx_data, reader, &fixed_blocks[3], 1, block_data);
|
||||||
if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
|
if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
|
||||||
FURI_LOG_W(TAG, "Bad exchange writing random challenge");
|
FURI_LOG_W(TAG, "Bad exchange writing random challenge");
|
||||||
return false;
|
return false;
|
||||||
@@ -436,51 +459,49 @@ bool felica_read_lite_system(
|
|||||||
FURI_LOG_W(TAG, "Bad response to Write without Encryption (RC)");
|
FURI_LOG_W(TAG, "Bad response to Write without Encryption (RC)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
felica_define_normal_block(service, RC_LITE_BLOCK, block_data);
|
|
||||||
|
|
||||||
tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_read(
|
tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_read(
|
||||||
tx_rx->tx_data, reader, true, &fixed_services[2], 2);
|
tx_rx->tx_data, reader, true, &fixed_blocks[4], 2);
|
||||||
if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
|
if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
|
||||||
FURI_LOG_W(TAG, "Bad exchange reading ID with MAC");
|
FURI_LOG_W(TAG, "Bad exchange reading CK and MAC");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(felica_parse_unencrypted_read(
|
if(felica_parse_unencrypted_read(
|
||||||
tx_rx->rx_data, tx_rx->rx_bits / 8, reader, block_data, sizeof(block_data)) !=
|
tx_rx->rx_data, tx_rx->rx_bits / 8, reader, block_data, sizeof(block_data)) !=
|
||||||
FELICA_BLOCK_SIZE * 2) {
|
FELICA_BLOCK_SIZE * 2) {
|
||||||
FURI_LOG_W(TAG, "Bad response to Read without Encryption (ID, MAC)");
|
FURI_LOG_W(TAG, "Bad response to Read without Encryption (CK, MAC)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
felica_define_normal_block(service, ID_LITE_BLOCK, block_data);
|
memcpy(lite_info->MAC, block_data + FELICA_BLOCK_SIZE, 8);
|
||||||
felica_define_normal_block(service, MAC_LITE_BLOCK, block_data + FELICA_BLOCK_SIZE);
|
|
||||||
FURI_LOG_I(TAG, "ID:");
|
|
||||||
for(int i = 0; i < 16; i++) {
|
|
||||||
FURI_LOG_I(TAG, "%02X", block_data[i]);
|
|
||||||
}
|
|
||||||
FURI_LOG_I(TAG, "MAC:");
|
FURI_LOG_I(TAG, "MAC:");
|
||||||
for(int i = 0; i < 16; i++) {
|
for(int i = 0; i < FELICA_BLOCK_SIZE; i++) {
|
||||||
FURI_LOG_I(TAG, "%02X", block_data[i + FELICA_BLOCK_SIZE]);
|
FURI_LOG_I(TAG, "%02X", block_data[i + FELICA_BLOCK_SIZE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_read(
|
tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_read(
|
||||||
tx_rx->tx_data, reader, true, &fixed_services[4], 3);
|
tx_rx->tx_data, reader, true, &fixed_blocks[6], 2);
|
||||||
if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
|
if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
|
||||||
FURI_LOG_W(TAG, "Bad exchange reading blocks");
|
FURI_LOG_W(TAG, "Bad exchange reading CKV and MC");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(felica_parse_unencrypted_read(
|
if(felica_parse_unencrypted_read(
|
||||||
tx_rx->rx_data, tx_rx->rx_bits / 8, reader, block_data, sizeof(block_data)) !=
|
tx_rx->rx_data, tx_rx->rx_bits / 8, reader, block_data, sizeof(block_data)) !=
|
||||||
FELICA_BLOCK_SIZE * 3) {
|
FELICA_BLOCK_SIZE * 2) {
|
||||||
FURI_LOG_W(TAG, "Bad response to Read without Encryption (D_ID, CKV, MC)");
|
FURI_LOG_W(TAG, "Bad response to Read without Encryption (CKV, MC)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
felica_define_normal_block(service, DEVICE_ID_LITE_BLOCK, block_data);
|
lite_info->card_key_version = nfc_util_bytes2num(block_data, 2);
|
||||||
felica_define_normal_block(service, CARD_KEY_VER_LITE_BLOCK, block_data + FELICA_BLOCK_SIZE);
|
memcpy(lite_info->memory_config, block_data + FELICA_BLOCK_SIZE, FELICA_BLOCK_SIZE);
|
||||||
felica_define_normal_block(service, MEM_CONFIG_LITE_BLOCK, block_data + FELICA_BLOCK_SIZE * 2);
|
|
||||||
|
|
||||||
// Read SPAD and REG accordingly to MC
|
// Read SPAD and REG accordingly to MC
|
||||||
uint8_t* mc_data = block_data + (FELICA_BLOCK_SIZE * 2);
|
uint8_t* mc_data = lite_info->memory_config;
|
||||||
for(uint8_t block_number = 0; block_number <= REG_LITE_BLOCK; block_number++) {
|
for(uint8_t block_number = 0; block_number <= REG_LITE_BLOCK; block_number++) {
|
||||||
if(!felica_lite_can_read_without_mac(mc_data + 6, block_number)) {
|
if(!felica_lite_can_read_without_mac(mc_data + 6, block_number)) {
|
||||||
|
if(block_number < REG_LITE_BLOCK) {
|
||||||
|
lite_info->S_PAD[block_number] = NULL;
|
||||||
|
} else {
|
||||||
|
lite_info->REG = NULL;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,18 +517,24 @@ bool felica_read_lite_system(
|
|||||||
FURI_LOG_W(TAG, "Bad response to Read without Encryption (block %d)", block_number);
|
FURI_LOG_W(TAG, "Bad response to Read without Encryption (block %d)", block_number);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
felica_define_normal_block(service, block_number, block_data);
|
uint8_t* block = malloc(FELICA_BLOCK_SIZE);
|
||||||
|
memcpy(block, block_data, FELICA_BLOCK_SIZE);
|
||||||
|
if(block_number < REG_LITE_BLOCK) {
|
||||||
|
lite_info->S_PAD[block_number] = block;
|
||||||
|
} else {
|
||||||
|
lite_info->REG = block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(data->type == FelicaICTypeLiteS) {
|
if(data->type == FelicaICTypeLiteS) {
|
||||||
const uint8_t fixed_s_services[] = {
|
const uint8_t fixed_s_blocks[] = {
|
||||||
ID_LITE_BLOCK,
|
CARD_KEY_LITE_BLOCK,
|
||||||
MAC_A_LITE_BLOCK,
|
MAC_A_LITE_BLOCK,
|
||||||
WRITE_COUNT_LITE_BLOCK,
|
WRITE_COUNT_LITE_BLOCK,
|
||||||
CRC_CHECK_LITE_BLOCK,
|
CRC_CHECK_LITE_BLOCK,
|
||||||
};
|
};
|
||||||
|
|
||||||
tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_read(
|
tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_read(
|
||||||
tx_rx->tx_data, reader, true, fixed_s_services, 2);
|
tx_rx->tx_data, reader, true, fixed_s_blocks, 2);
|
||||||
if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
|
if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
|
||||||
FURI_LOG_W(TAG, "Bad exchange reading ID with MAC_A");
|
FURI_LOG_W(TAG, "Bad exchange reading ID with MAC_A");
|
||||||
return false;
|
return false;
|
||||||
@@ -515,14 +542,13 @@ bool felica_read_lite_system(
|
|||||||
if(felica_parse_unencrypted_read(
|
if(felica_parse_unencrypted_read(
|
||||||
tx_rx->rx_data, tx_rx->rx_bits / 8, reader, block_data, sizeof(block_data)) !=
|
tx_rx->rx_data, tx_rx->rx_bits / 8, reader, block_data, sizeof(block_data)) !=
|
||||||
FELICA_BLOCK_SIZE * 2) {
|
FELICA_BLOCK_SIZE * 2) {
|
||||||
FURI_LOG_W(TAG, "Bad response to Read without Encryption (ID, MAC_A)");
|
FURI_LOG_W(TAG, "Bad response to Read without Encryption (CK, MAC_A)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
felica_define_normal_block(service, ID_LITE_BLOCK, block_data);
|
memcpy(lite_info->MAC_A, block_data + FELICA_BLOCK_SIZE, FELICA_BLOCK_SIZE);
|
||||||
felica_define_normal_block(service, MAC_A_LITE_BLOCK, block_data + FELICA_BLOCK_SIZE);
|
|
||||||
|
|
||||||
tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_read(
|
tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_read(
|
||||||
tx_rx->tx_data, reader, true, &fixed_s_services[2], 2);
|
tx_rx->tx_data, reader, true, &fixed_s_blocks[2], 2);
|
||||||
if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
|
if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
|
||||||
FURI_LOG_W(TAG, "Bad exchange reading ID with MAC_A");
|
FURI_LOG_W(TAG, "Bad exchange reading ID with MAC_A");
|
||||||
return false;
|
return false;
|
||||||
@@ -533,8 +559,8 @@ bool felica_read_lite_system(
|
|||||||
FURI_LOG_W(TAG, "Bad response to Read without Encryption (WC, CRC_CHECK)");
|
FURI_LOG_W(TAG, "Bad response to Read without Encryption (WC, CRC_CHECK)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
felica_define_normal_block(service, WRITE_COUNT_LITE_BLOCK, block_data);
|
lite_info->write_count = nfc_util_bytes2num(block_data, 3);
|
||||||
felica_define_normal_block(service, CRC_CHECK_LITE_BLOCK, block_data + FELICA_BLOCK_SIZE);
|
lite_info->crc_valid = block_data[FELICA_BLOCK_SIZE] == 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -582,14 +608,34 @@ void felica_service_clear(FelicaService* service) {
|
|||||||
FelicaBlockList_clear(service->blocks);
|
FelicaBlockList_clear(service->blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void felica_lite_clear(FelicaLiteInfo* lite_info) {
|
||||||
|
for(int i = 0; i < REG_LITE_BLOCK; i++) {
|
||||||
|
uint8_t* block = lite_info->S_PAD[i];
|
||||||
|
if(block != NULL) {
|
||||||
|
free(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lite_info->REG != NULL) {
|
||||||
|
free(lite_info->REG);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lite_info->card_key_1 != NULL) {
|
||||||
|
free(lite_info->card_key_1);
|
||||||
|
}
|
||||||
|
if(lite_info->card_key_2 != NULL) {
|
||||||
|
free(lite_info->card_key_2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void felica_area_clear(FelicaArea* area) {
|
void felica_area_clear(FelicaArea* area) {
|
||||||
FelicaNodeList_it_t it;
|
FelicaNodeList_it_t it;
|
||||||
for(FelicaNodeList_it(it, area->nodes); !FelicaNodeList_end_p(it); FelicaNodeList_next(it)) {
|
for(FelicaNodeList_it(it, area->nodes); !FelicaNodeList_end_p(it); FelicaNodeList_next(it)) {
|
||||||
FelicaNode* node = *FelicaNodeList_ref(it);
|
FelicaNode* node = *FelicaNodeList_ref(it);
|
||||||
if(node->type == FelicaNodeTypeArea) {
|
if(node->type == FelicaNodeTypeArea) {
|
||||||
felica_area_clear(node->ptr.area);
|
felica_area_clear(node->area);
|
||||||
} else if(node->type == FelicaNodeTypeService) {
|
} else if(node->type == FelicaNodeTypeService) {
|
||||||
felica_service_clear(node->ptr.service);
|
felica_service_clear(node->service);
|
||||||
}
|
}
|
||||||
free(node);
|
free(node);
|
||||||
}
|
}
|
||||||
@@ -601,7 +647,12 @@ void felica_clear(FelicaData* data) {
|
|||||||
for(FelicaSystemList_it(it, data->systems); !FelicaSystemList_end_p(it);
|
for(FelicaSystemList_it(it, data->systems); !FelicaSystemList_end_p(it);
|
||||||
FelicaSystemList_next(it)) {
|
FelicaSystemList_next(it)) {
|
||||||
FelicaSystem* system = *FelicaSystemList_ref(it);
|
FelicaSystem* system = *FelicaSystemList_ref(it);
|
||||||
|
if(system->code == LITE_SYSTEM_CODE) {
|
||||||
|
felica_lite_clear(&system->lite_info);
|
||||||
|
;
|
||||||
|
} else {
|
||||||
felica_area_clear(&system->root_area);
|
felica_area_clear(&system->root_area);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
FelicaSystemList_clear(data->systems);
|
FelicaSystemList_clear(data->systems);
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <furi_hal_nfc.h>
|
#include <furi_hal_nfc.h>
|
||||||
#include <m-array.h>
|
#include <m-array.h>
|
||||||
|
#include <m-dict.h>
|
||||||
|
|
||||||
#define NFCF_F_SIG (13560000.0)
|
#define NFCF_F_SIG (13560000.0)
|
||||||
#define MRT_T_SIG 302064.89 //ns, 256 * 16 / NFC_F_SIG * 1e9
|
#define MRT_T_SIG 302064.89 //ns, 256 * 16 / NFC_F_SIG * 1e9
|
||||||
@@ -9,21 +10,29 @@
|
|||||||
#define MRT_T_SIG_x16 4833038.24 //ns, MRT_T_SIG * (4 ** 2)
|
#define MRT_T_SIG_x16 4833038.24 //ns, MRT_T_SIG * (4 ** 2)
|
||||||
#define MRT_T_SIG_x64 19332152.96 //ns, MRT_T_SIG * (4 ** 2)
|
#define MRT_T_SIG_x64 19332152.96 //ns, MRT_T_SIG * (4 ** 2)
|
||||||
|
|
||||||
|
#define FELICA_VARIABLE_MRT 0
|
||||||
|
#define FELICA_FIXED_MRT 1
|
||||||
|
#define FELICA_MUTUAL_AUTH_MRT 2
|
||||||
|
#define FELICA_READ_MRT 3
|
||||||
|
#define FELICA_WRITE_MRT 4
|
||||||
|
#define FELICA_OTHER_MRT 5
|
||||||
|
|
||||||
#define FELICA_BLOCK_SIZE 16
|
#define FELICA_BLOCK_SIZE 16
|
||||||
|
|
||||||
#define SUICA_SYSTEM_CODE 0x0003
|
#define CYBERNET_SYSTEM_CODE 0x0003
|
||||||
#define NDEF_SYSTEM_CODE 0x12fc
|
#define NDEF_SYSTEM_CODE 0x12fc
|
||||||
#define HCE_F_SYSTEM_CODE 0x4000
|
#define HCE_F_SYSTEM_CODE 0x4000
|
||||||
#define OCTOPUS_SYSTEM_CODE 0x8008
|
#define OCTOPUS_SYSTEM_CODE 0x8008
|
||||||
|
#define IRUCA_SYSTEM_CODE 0x80de
|
||||||
#define EDY_SYSTEM_CODE 0x811d
|
#define EDY_SYSTEM_CODE 0x811d
|
||||||
#define PASPY_SYSTEM_CODE 0x8592
|
#define PASPY_SYSTEM_CODE 0x8592
|
||||||
#define BLACKBOARD_SYSTEM_CODE 0x8620
|
#define BLACKBOARD_SYSTEM_CODE 0x8620
|
||||||
#define SAPICA_SYSTEM_CODE 0x865e
|
#define SAPICA_SYSTEM_CODE 0x865e
|
||||||
|
#define SUICA_SYSTEM_CODE 0x86a7
|
||||||
#define LITE_SYSTEM_CODE 0x88b4
|
#define LITE_SYSTEM_CODE 0x88b4
|
||||||
#define RYUTO_SYSTEM_CODE 0x8b5d
|
#define RYUTO_SYSTEM_CODE 0x8b5d
|
||||||
#define OKICA_SYSTEM_CODE 0x8fc1
|
#define OKICA_SYSTEM_CODE 0x8fc1
|
||||||
#define SECURE_ID_SYSTEM_CODE 0x957a
|
#define SECURE_ID_SYSTEM_CODE 0x957a
|
||||||
#define IRUCA_SYSTEM_CODE 0xde80
|
|
||||||
#define COMMON_AREA_SYSTEM_CODE 0xfe00
|
#define COMMON_AREA_SYSTEM_CODE 0xfe00
|
||||||
#define PLUG_SYSTEM_CODE 0xfee1
|
#define PLUG_SYSTEM_CODE 0xfee1
|
||||||
|
|
||||||
@@ -42,24 +51,6 @@
|
|||||||
#define STATE_LITE_BLOCK 0x92
|
#define STATE_LITE_BLOCK 0x92
|
||||||
#define CRC_CHECK_LITE_BLOCK 0xA0
|
#define CRC_CHECK_LITE_BLOCK 0xA0
|
||||||
|
|
||||||
#define RANDOM_TYPE_SERVICE_ATTRIBUTE (0b0010 << 2)
|
|
||||||
#define CYCLIC_TYPE_SERVICE_ATTRIBUTE (0b0011 << 2)
|
|
||||||
#define PURSE_TYPE_SERVICE_ATTRIBUTE (0b010 << 3)
|
|
||||||
|
|
||||||
#define AUTH_RW_SERVICE_ATTRIBUTE (0b00)
|
|
||||||
#define UNAUTH_RW_SERVICE_ATTRIBUTE (0b01)
|
|
||||||
#define AUTH_RO_SERVICE_ATTRIBUTE (0b10)
|
|
||||||
#define UNAUTH_RO_SERVICE_ATTRIBUTE (0b11)
|
|
||||||
|
|
||||||
#define AUTH_DIRECT_ACCESS_SERVICE_ATTRIBUTE (0b000)
|
|
||||||
#define UNAUTH_DIRECT_ACCESS_SERVICE_ATTRIBUTE (0b001)
|
|
||||||
#define AUTH_CASHBACK_DECREMENT_SERVICE_ATTRIBUTE (0b010)
|
|
||||||
#define UNAUTH_CASHBACK_DECREMENT_SERVICE_ATTRIBUTE (0b011)
|
|
||||||
#define AUTH_DECREMENT_SERVICE_ATTRIBUTE (0b100)
|
|
||||||
#define UNAUTH_DECREMENT_SERVICE_ATTRIBUTE (0b101)
|
|
||||||
#define AUTH_RO_PURSE_SERVICE_ATTRIBUTE (0b110)
|
|
||||||
#define UNAUTH_RO_PURSE_SERVICE_ATTRIBUTE (0b111)
|
|
||||||
|
|
||||||
#define IS_2_BYTE_BLOCK_LIST_ELEMENT 0x80
|
#define IS_2_BYTE_BLOCK_LIST_ELEMENT 0x80
|
||||||
|
|
||||||
#define FELICA_UNENCRYPTED_READ_CMD 0x06
|
#define FELICA_UNENCRYPTED_READ_CMD 0x06
|
||||||
@@ -105,35 +96,51 @@ typedef struct {
|
|||||||
} FelicaMRTParts;
|
} FelicaMRTParts;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FelicaMRTCommandTypeVariable = 0,
|
FelicaServiceTypeRandom = (0b0010 << 2),
|
||||||
FelicaMRTCommandTypeFixed = 1,
|
FelicaServiceTypeCyclic = (0b0011 << 2),
|
||||||
FelicaMRTCommandTypeMutualAuth = 2,
|
FelicaServiceTypePurse = (0b010 << 3),
|
||||||
FelicaMRTCommandTypeDataRead = 3,
|
} FelicaServiceType;
|
||||||
FelicaMRTCommandTypeDataWrite = 4,
|
typedef enum {
|
||||||
FelicaMRTCommandTypeDataOther = 4,
|
FelicaServiceAttributeAuthRW = 0b00,
|
||||||
} FelicaMRTCommandType;
|
FelicaServiceAttributeUnauthRW = 0b01,
|
||||||
|
FelicaServiceAttributeAuthRO = 0b10,
|
||||||
|
FelicaServiceAttributeUnauthRO = 0b11,
|
||||||
|
|
||||||
|
FelicaServiceAttributeAuthDirectAccess = 0b000,
|
||||||
|
FelicaServiceAttributeUnauthDirectAccess = 0b001,
|
||||||
|
FelicaServiceAttributeAuthCashbackDecrement = 0b010,
|
||||||
|
FelicaServiceAttributeUnauthCashbackDecrement = 0b011,
|
||||||
|
FelicaServiceAttributeAuthDecrement = 0b100,
|
||||||
|
FelicaServiceAttributeUnauthDecrement = 0b101,
|
||||||
|
FelicaServiceAttributeAuthPurseRO = 0b110,
|
||||||
|
FelicaServiceAttributeUnauthPurseRO = 0b111,
|
||||||
|
} FelicaServiceAttribute;
|
||||||
|
|
||||||
|
DICT_SET_DEF(
|
||||||
|
FelicaServiceAttributeList,
|
||||||
|
FelicaServiceAttribute,
|
||||||
|
M_ENUM_OPLIST(FelicaServiceAttribute, FelicaServiceAttributeAuthRW))
|
||||||
|
|
||||||
typedef FelicaMRTParts FelicaMRTParameters[6];
|
typedef FelicaMRTParts FelicaMRTParameters[6];
|
||||||
typedef enum {
|
|
||||||
FelicaBlockTypeNormal,
|
|
||||||
FelicaBlockTypeOverlap,
|
|
||||||
FelicaBlockTypeExtended,
|
|
||||||
} FelicaBlockType;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FelicaBlockType type;
|
|
||||||
union {
|
|
||||||
uint8_t data[FELICA_BLOCK_SIZE];
|
uint8_t data[FELICA_BLOCK_SIZE];
|
||||||
};
|
|
||||||
} FelicaBlock;
|
} FelicaBlock;
|
||||||
|
|
||||||
// typedef struct {} FelicaOverlapBlock;
|
ARRAY_DEF(FelicaBlockList, FelicaBlock*, M_PTR_OPLIST)
|
||||||
|
|
||||||
ARRAY_DEF(FelicaBlockList, FelicaBlock*, M_PTR_OPLIST);
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t number;
|
uint16_t number;
|
||||||
|
FelicaServiceAttributeList_t access_control_list; // accounts for overlap services
|
||||||
|
bool is_extended_overlap;
|
||||||
|
union {
|
||||||
FelicaBlockList_t blocks;
|
FelicaBlockList_t blocks;
|
||||||
|
struct {
|
||||||
|
uint16_t overlap_target;
|
||||||
|
uint8_t block_start;
|
||||||
|
uint8_t block_count;
|
||||||
|
};
|
||||||
|
};
|
||||||
} FelicaService;
|
} FelicaService;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -147,9 +154,10 @@ typedef struct {
|
|||||||
union {
|
union {
|
||||||
struct _FelicaArea_t* area;
|
struct _FelicaArea_t* area;
|
||||||
FelicaService* service;
|
FelicaService* service;
|
||||||
} ptr;
|
};
|
||||||
} FelicaNode;
|
} FelicaNode;
|
||||||
ARRAY_DEF(FelicaNodeList, FelicaNode*, M_PTR_OPLIST);
|
|
||||||
|
ARRAY_DEF(FelicaNodeList, FelicaNode*, M_PTR_OPLIST)
|
||||||
|
|
||||||
typedef struct _FelicaArea_t {
|
typedef struct _FelicaArea_t {
|
||||||
uint16_t number;
|
uint16_t number;
|
||||||
@@ -157,9 +165,26 @@ typedef struct _FelicaArea_t {
|
|||||||
uint16_t end_service_code;
|
uint16_t end_service_code;
|
||||||
|
|
||||||
FelicaNodeList_t nodes;
|
FelicaNodeList_t nodes;
|
||||||
|
|
||||||
} FelicaArea;
|
} FelicaArea;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t* S_PAD[14];
|
||||||
|
uint8_t* REG;
|
||||||
|
// MACs of all zero bytes (read from CK)
|
||||||
|
uint8_t MAC[8];
|
||||||
|
uint16_t data_format_code;
|
||||||
|
uint8_t ID_value[6];
|
||||||
|
uint8_t* card_key_1;
|
||||||
|
uint8_t* card_key_2;
|
||||||
|
uint16_t card_key_version;
|
||||||
|
uint8_t memory_config[FELICA_BLOCK_SIZE];
|
||||||
|
|
||||||
|
// Lite-S only
|
||||||
|
uint8_t MAC_A[8];
|
||||||
|
uint32_t write_count;
|
||||||
|
bool crc_valid;
|
||||||
|
} FelicaLiteInfo;
|
||||||
|
|
||||||
typedef struct _FelicaSystem_t {
|
typedef struct _FelicaSystem_t {
|
||||||
uint8_t number;
|
uint8_t number;
|
||||||
uint16_t code;
|
uint16_t code;
|
||||||
@@ -167,13 +192,13 @@ typedef struct _FelicaSystem_t {
|
|||||||
uint8_t pmm[8];
|
uint8_t pmm[8];
|
||||||
FelicaMRTParameters maximum_response_times;
|
FelicaMRTParameters maximum_response_times;
|
||||||
|
|
||||||
/** This struct represents area 0,
|
union {
|
||||||
* which always exists on a given system
|
FelicaLiteInfo lite_info;
|
||||||
*/
|
|
||||||
FelicaArea root_area;
|
FelicaArea root_area;
|
||||||
|
};
|
||||||
} FelicaSystem;
|
} FelicaSystem;
|
||||||
|
|
||||||
ARRAY_DEF(FelicaSystemList, FelicaSystem*, M_PTR_OPLIST);
|
ARRAY_DEF(FelicaSystemList, FelicaSystem*, M_PTR_OPLIST)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FelicaICType type;
|
FelicaICType type;
|
||||||
|
|||||||
Reference in New Issue
Block a user