mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-23 05:24:46 -07:00
separate ISO15693 basic and SLIX extensions a bit more
changed save format to reflect this executing emulation from browser now also works
This commit is contained in:
@@ -280,6 +280,9 @@ int32_t nfc_app(void* p) {
|
|||||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
|
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate);
|
||||||
DOLPHIN_DEED(DolphinDeedNfcEmulate);
|
DOLPHIN_DEED(DolphinDeedNfcEmulate);
|
||||||
|
} else if(nfc->dev->format == NfcDeviceSaveFormatNfcV) {
|
||||||
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateNfcV);
|
||||||
|
DOLPHIN_DEED(DolphinDeedNfcEmulate);
|
||||||
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
|
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -286,8 +286,11 @@ static void nfc_cli_st25r_trans(Cli* cli, FuriString* args) {
|
|||||||
.block_num = 8,
|
.block_num = 8,
|
||||||
.block_size = 4,
|
.block_size = 4,
|
||||||
.ic_ref = 3,
|
.ic_ref = 3,
|
||||||
.key_privacy = { 0x0F, 0x0F, 0x0F, 0x0F },
|
.type = NfcVTypeSlixL,
|
||||||
.privacy = false
|
.sub_data.slix_l = {
|
||||||
|
.key_privacy = { 0x0F, 0x0F, 0x0F, 0x0F },
|
||||||
|
.privacy = false
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
memset(nfcv_data.data, 0xAE, 4 * 8);
|
memset(nfcv_data.data, 0xAE, 4 * 8);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
|
|||||||
NfcProtocol protocol = dev_data->protocol;
|
NfcProtocol protocol = dev_data->protocol;
|
||||||
uint8_t text_scroll_height = 0;
|
uint8_t text_scroll_height = 0;
|
||||||
if((protocol == NfcDeviceProtocolMifareDesfire) || (protocol == NfcDeviceProtocolMifareUl)
|
if((protocol == NfcDeviceProtocolMifareDesfire) || (protocol == NfcDeviceProtocolMifareUl)
|
||||||
|| (protocol == NfcDeviceProtocolSlixL) || (protocol == NfcDeviceProtocolNfcV)) {
|
|| (protocol == NfcDeviceProtocolNfcV)) {
|
||||||
widget_add_button_element(
|
widget_add_button_element(
|
||||||
widget, GuiButtonTypeRight, "More", nfc_scene_nfc_data_info_widget_callback, nfc);
|
widget, GuiButtonTypeRight, "More", nfc_scene_nfc_data_info_widget_callback, nfc);
|
||||||
text_scroll_height = 52;
|
text_scroll_height = 52;
|
||||||
@@ -42,15 +42,33 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
|
|||||||
} else if(protocol == NfcDeviceProtocolMifareDesfire) {
|
} else if(protocol == NfcDeviceProtocolMifareDesfire) {
|
||||||
furi_string_cat_printf(temp_str, "\e#MIFARE DESfire\n");
|
furi_string_cat_printf(temp_str, "\e#MIFARE DESfire\n");
|
||||||
} else if(protocol == NfcDeviceProtocolNfcV) {
|
} else if(protocol == NfcDeviceProtocolNfcV) {
|
||||||
furi_string_cat_printf(temp_str, "\e#ISO15693\n");
|
switch (dev_data->nfcv_data.type)
|
||||||
} else if(protocol == NfcDeviceProtocolSlixL) {
|
{
|
||||||
furi_string_cat_printf(temp_str, "\e#ISO15693 SLIX-L\n");
|
case NfcVTypePlain:
|
||||||
|
furi_string_cat_printf(temp_str, "\e#ISO15693\n");
|
||||||
|
break;
|
||||||
|
case NfcVTypeSlix:
|
||||||
|
furi_string_cat_printf(temp_str, "\e#ISO15693 SLIX\n");
|
||||||
|
break;
|
||||||
|
case NfcVTypeSlixS:
|
||||||
|
furi_string_cat_printf(temp_str, "\e#ISO15693 SLIX-S\n");
|
||||||
|
break;
|
||||||
|
case NfcVTypeSlixL:
|
||||||
|
furi_string_cat_printf(temp_str, "\e#ISO15693 SLIX-L\n");
|
||||||
|
break;
|
||||||
|
case NfcVTypeSlix2:
|
||||||
|
furi_string_cat_printf(temp_str, "\e#ISO15693 SLIX2\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
furi_string_cat_printf(temp_str, "\e#ISO15693 (unknown)\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
furi_string_cat_printf(temp_str, "\e#Unknown ISO tag\n");
|
furi_string_cat_printf(temp_str, "\e#Unknown ISO tag\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set tag iso data
|
// Set tag iso data
|
||||||
if((protocol == NfcDeviceProtocolSlixL) || (protocol == NfcDeviceProtocolNfcV)) {
|
if(protocol == NfcDeviceProtocolNfcV) {
|
||||||
NfcVData* nfcv_data = &nfc->dev->dev_data.nfcv_data;
|
NfcVData* nfcv_data = &nfc->dev->dev_data.nfcv_data;
|
||||||
|
|
||||||
furi_string_cat_printf(temp_str, "UID:\n");
|
furi_string_cat_printf(temp_str, "UID:\n");
|
||||||
@@ -151,9 +169,6 @@ bool nfc_scene_nfc_data_info_on_event(void* context, SceneManagerEvent event) {
|
|||||||
} else if(protocol == NfcDeviceProtocolMifareUl) {
|
} else if(protocol == NfcDeviceProtocolMifareUl) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightData);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightData);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(protocol == NfcDeviceProtocolSlixL) {
|
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVMenu);
|
|
||||||
consumed = true;
|
|
||||||
} else if(protocol == NfcDeviceProtocolNfcV) {
|
} else if(protocol == NfcDeviceProtocolNfcV) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVMenu);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVMenu);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
|
|
||||||
void nfc_scene_nfcv_key_input_byte_input_callback(void* context) {
|
void nfc_scene_nfcv_key_input_byte_input_callback(void* context) {
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
|
NfcVSlixLData* data = &nfc->dev->dev_data.nfcv_data.sub_data.slix_l;
|
||||||
|
|
||||||
memcpy(nfc->dev->dev_data.nfcv_data.key_privacy, nfc->byte_input_store, 4);
|
memcpy(data->key_privacy, nfc->byte_input_store, 4);
|
||||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventByteInputDone);
|
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventByteInputDone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ bool nfc_scene_nfcv_menu_on_event(void* context, SceneManagerEvent event) {
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == SubmenuIndexSave) {
|
if(event.event == SubmenuIndexSave) {
|
||||||
nfc->dev->format = NfcDeviceSaveFormatSlixL;
|
nfc->dev->format = NfcDeviceSaveFormatNfcV;
|
||||||
// Clear device name
|
// Clear device name
|
||||||
nfc_device_set_name(nfc->dev, "");
|
nfc_device_set_name(nfc->dev, "");
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||||
|
|||||||
@@ -11,53 +11,15 @@ typedef enum {
|
|||||||
|
|
||||||
static bool nfc_scene_nfcv_unlock_worker_callback(NfcWorkerEvent event, void* context) {
|
static bool nfc_scene_nfcv_unlock_worker_callback(NfcWorkerEvent event, void* context) {
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
|
NfcVSlixLData* data = &nfc->dev->dev_data.nfcv_data.sub_data.slix_l;
|
||||||
|
|
||||||
if(event == NfcWorkerEventNfcVPassKey) {
|
if(event == NfcWorkerEventNfcVPassKey) {
|
||||||
memcpy(nfc->dev->dev_data.nfcv_data.key_privacy, nfc->byte_input_store, 4);
|
memcpy(data->key_privacy, nfc->byte_input_store, 4);
|
||||||
} else {
|
} else {
|
||||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, event);
|
view_dispatcher_send_custom_event(nfc->view_dispatcher, event);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
static void nfc_scene_nfcv_unlock_button_callback(GuiButtonType event, InputType type, void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
furi_assert(type);
|
|
||||||
Nfc* nfc = context;
|
|
||||||
|
|
||||||
if(event == GuiButtonTypeCenter) {
|
|
||||||
if(nfc_worker_get_state(nfc->worker) == NfcWorkerStateNfcVUnlockAndSave) {
|
|
||||||
nfc_worker_stop(nfc->worker);
|
|
||||||
nfc_worker_start(
|
|
||||||
nfc->worker,
|
|
||||||
NfcWorkerStateNfcVUnlock,
|
|
||||||
&nfc->dev->dev_data,
|
|
||||||
nfc_scene_nfcv_unlock_worker_callback,
|
|
||||||
nfc);
|
|
||||||
widget_add_button_element(
|
|
||||||
nfc->widget,
|
|
||||||
GuiButtonTypeCenter,
|
|
||||||
"Autosave",
|
|
||||||
nfc_scene_nfcv_unlock_button_callback,
|
|
||||||
nfc);
|
|
||||||
} else {
|
|
||||||
nfc_worker_stop(nfc->worker);
|
|
||||||
nfc_worker_start(
|
|
||||||
nfc->worker,
|
|
||||||
NfcWorkerStateNfcVUnlockAndSave,
|
|
||||||
&nfc->dev->dev_data,
|
|
||||||
nfc_scene_nfcv_unlock_worker_callback,
|
|
||||||
nfc);
|
|
||||||
widget_add_button_element(
|
|
||||||
nfc->widget,
|
|
||||||
GuiButtonTypeCenter,
|
|
||||||
"Unlock",
|
|
||||||
nfc_scene_nfcv_unlock_button_callback,
|
|
||||||
nfc);
|
|
||||||
}
|
|
||||||
notification_message(nfc->notifications, &sequence_single_vibro);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
void nfc_scene_nfcv_unlock_popup_callback(void* context) {
|
void nfc_scene_nfcv_unlock_popup_callback(void* context) {
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
@@ -82,10 +44,10 @@ void nfc_scene_nfcv_unlock_set_state(Nfc* nfc, NfcSceneNfcVUnlockState state) {
|
|||||||
|
|
||||||
if(nfc_worker_get_state(nfc->worker) == NfcWorkerStateNfcVUnlockAndSave) {
|
if(nfc_worker_get_state(nfc->worker) == NfcWorkerStateNfcVUnlockAndSave) {
|
||||||
nfc_text_store_set(nfc, "SLIX-L_%02X%02X%02X%02X%02X%02X%02X%02X",
|
nfc_text_store_set(nfc, "SLIX-L_%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||||
nfc_data->uid[7], nfc_data->uid[6], nfc_data->uid[5], nfc_data->uid[4],
|
nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3],
|
||||||
nfc_data->uid[3], nfc_data->uid[2], nfc_data->uid[1], nfc_data->uid[0]);
|
nfc_data->uid[4], nfc_data->uid[5], nfc_data->uid[6], nfc_data->uid[7]);
|
||||||
|
|
||||||
nfc->dev->format = NfcDeviceSaveFormatSlixL;
|
nfc->dev->format = NfcDeviceSaveFormatNfcV;
|
||||||
|
|
||||||
if(nfc_device_save(nfc->dev, nfc->text_store)) {
|
if(nfc_device_save(nfc->dev, nfc->text_store)) {
|
||||||
popup_set_header(popup, "Successfully\nsaved", 94, 3, AlignCenter, AlignTop);
|
popup_set_header(popup, "Successfully\nsaved", 94, 3, AlignCenter, AlignTop);
|
||||||
|
|||||||
@@ -55,6 +55,13 @@ bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||||||
&nfc->dev->dev_data,
|
&nfc->dev->dev_data,
|
||||||
nfc_scene_rpc_emulate_callback,
|
nfc_scene_rpc_emulate_callback,
|
||||||
nfc);
|
nfc);
|
||||||
|
} else if(nfc->dev->format == NfcDeviceSaveFormatNfcV) {
|
||||||
|
nfc_worker_start(
|
||||||
|
nfc->worker,
|
||||||
|
NfcWorkerStateNfcVEmulate,
|
||||||
|
&nfc->dev->dev_data,
|
||||||
|
nfc_scene_rpc_emulate_callback,
|
||||||
|
nfc);
|
||||||
} else {
|
} else {
|
||||||
nfc_worker_start(
|
nfc_worker_start(
|
||||||
nfc->worker, NfcWorkerStateUidEmulate, &nfc->dev->dev_data, NULL, nfc);
|
nfc->worker, NfcWorkerStateUidEmulate, &nfc->dev->dev_data, NULL, nfc);
|
||||||
|
|||||||
@@ -99,6 +99,8 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
|||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightEmulate);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightEmulate);
|
||||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
|
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate);
|
||||||
|
} else if(nfc->dev->format == NfcDeviceSaveFormatNfcV) {
|
||||||
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateNfcV);
|
||||||
} else {
|
} else {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ static void nfc_device_prepare_format_string(NfcDevice* dev, FuriString* format_
|
|||||||
furi_string_set(format_string, "Mifare Classic");
|
furi_string_set(format_string, "Mifare Classic");
|
||||||
} else if(dev->format == NfcDeviceSaveFormatMifareDesfire) {
|
} else if(dev->format == NfcDeviceSaveFormatMifareDesfire) {
|
||||||
furi_string_set(format_string, "Mifare DESFire");
|
furi_string_set(format_string, "Mifare DESFire");
|
||||||
} else if(dev->format == NfcDeviceSaveFormatSlixL) {
|
} else if(dev->format == NfcDeviceSaveFormatNfcV) {
|
||||||
furi_string_set(format_string, "NXP SLIX-L");
|
furi_string_set(format_string, "ISO15693");
|
||||||
} else {
|
} else {
|
||||||
furi_string_set(format_string, "Unknown");
|
furi_string_set(format_string, "Unknown");
|
||||||
}
|
}
|
||||||
@@ -87,9 +87,9 @@ static bool nfc_device_parse_format_string(NfcDevice* dev, FuriString* format_st
|
|||||||
dev->dev_data.protocol = NfcDeviceProtocolMifareDesfire;
|
dev->dev_data.protocol = NfcDeviceProtocolMifareDesfire;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(furi_string_start_with_str(format_string, "NXP SLIX-L")) {
|
if(furi_string_start_with_str(format_string, "ISO15693")) {
|
||||||
dev->format = NfcDeviceSaveFormatSlixL;
|
dev->format = NfcDeviceSaveFormatNfcV;
|
||||||
dev->dev_data.protocol = NfcDeviceProtocolSlixL;
|
dev->dev_data.protocol = NfcDeviceProtocolNfcV;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -643,21 +643,92 @@ bool nfc_device_load_mifare_df_data(FlipperFormat* file, NfcDevice* dev) {
|
|||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool nfc_device_save_slix_data(FlipperFormat* file, NfcDevice* dev) {
|
||||||
|
bool saved = false;
|
||||||
|
NfcVSlixData* data = &dev->dev_data.nfcv_data.sub_data.slix;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!flipper_format_write_comment_cstr(file, "SLIX specific data")) break;
|
||||||
|
if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) break;
|
||||||
|
saved = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nfc_device_load_slix_data(FlipperFormat* file, NfcDevice* dev) {
|
||||||
|
bool parsed = false;
|
||||||
|
NfcVSlixData* data = &dev->dev_data.nfcv_data.sub_data.slix;
|
||||||
|
memset(data, 0, sizeof(NfcVData));
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!flipper_format_read_hex(
|
||||||
|
file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
parsed = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool nfc_device_save_slix_s_data(FlipperFormat* file, NfcDevice* dev) {
|
||||||
|
bool saved = false;
|
||||||
|
NfcVSlixSData* data = &dev->dev_data.nfcv_data.sub_data.slix_s;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!flipper_format_write_comment_cstr(file, "SLIX-S specific data")) break;
|
||||||
|
if(!flipper_format_write_hex(file, "Password Read", data->key_read, sizeof(data->key_read))) break;
|
||||||
|
if(!flipper_format_write_hex(file, "Password Write", data->key_write, sizeof(data->key_write))) break;
|
||||||
|
if(!flipper_format_write_hex(file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) break;
|
||||||
|
if(!flipper_format_write_hex(file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) break;
|
||||||
|
if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) break;
|
||||||
|
if(!flipper_format_write_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
||||||
|
saved = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nfc_device_load_slix_s_data(FlipperFormat* file, NfcDevice* dev) {
|
||||||
|
bool parsed = false;
|
||||||
|
NfcVSlixSData* data = &dev->dev_data.nfcv_data.sub_data.slix_s;
|
||||||
|
memset(data, 0, sizeof(NfcVData));
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!flipper_format_read_hex(
|
||||||
|
file, "Password Read", data->key_read, sizeof(data->key_read)))
|
||||||
|
break;
|
||||||
|
if(!flipper_format_read_hex(
|
||||||
|
file, "Password Write", data->key_write, sizeof(data->key_write)))
|
||||||
|
break;
|
||||||
|
if(!flipper_format_read_hex(
|
||||||
|
file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy)))
|
||||||
|
break;
|
||||||
|
if(!flipper_format_read_hex(
|
||||||
|
file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy)))
|
||||||
|
break;
|
||||||
|
if(!flipper_format_read_hex(
|
||||||
|
file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
|
||||||
|
break;
|
||||||
|
if(!flipper_format_read_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
||||||
|
|
||||||
|
parsed = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
|
||||||
static bool nfc_device_save_slix_l_data(FlipperFormat* file, NfcDevice* dev) {
|
static bool nfc_device_save_slix_l_data(FlipperFormat* file, NfcDevice* dev) {
|
||||||
bool saved = false;
|
bool saved = false;
|
||||||
NfcVData* data = &dev->dev_data.nfcv_data;
|
NfcVSlixLData* data = &dev->dev_data.nfcv_data.sub_data.slix_l;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(!flipper_format_write_comment_cstr(file, "SLIX-L specific data")) break;
|
if(!flipper_format_write_comment_cstr(file, "SLIX-L specific data")) break;
|
||||||
if(!flipper_format_write_hex(file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) break;
|
if(!flipper_format_write_hex(file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) break;
|
||||||
if(!flipper_format_write_hex(file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) break;
|
if(!flipper_format_write_hex(file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) break;
|
||||||
if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) break;
|
if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) break;
|
||||||
if(!flipper_format_write_hex(file, "DSFID", &(data->dsfid), 1)) break;
|
if(!flipper_format_write_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
||||||
if(!flipper_format_write_hex(file, "AFI", &(data->afi), 1)) break;
|
|
||||||
if(!flipper_format_write_hex(file, "IC Reference", &(data->ic_ref), 1)) break;
|
|
||||||
if(!flipper_format_write_hex(file, "Block Count", &(data->block_num), 1)) break;
|
|
||||||
if(!flipper_format_write_hex(file, "Block Size", &(data->block_size), 1)) break;
|
|
||||||
if(!flipper_format_write_hex(file, "Data Content", data->data, data->block_num * data->block_size)) break;
|
|
||||||
saved = true;
|
saved = true;
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
@@ -666,7 +737,7 @@ static bool nfc_device_save_slix_l_data(FlipperFormat* file, NfcDevice* dev) {
|
|||||||
|
|
||||||
bool nfc_device_load_slix_l_data(FlipperFormat* file, NfcDevice* dev) {
|
bool nfc_device_load_slix_l_data(FlipperFormat* file, NfcDevice* dev) {
|
||||||
bool parsed = false;
|
bool parsed = false;
|
||||||
NfcVData* data = &dev->dev_data.nfcv_data;
|
NfcVSlixLData* data = &dev->dev_data.nfcv_data.sub_data.slix_l;
|
||||||
memset(data, 0, sizeof(NfcVData));
|
memset(data, 0, sizeof(NfcVData));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@@ -679,7 +750,108 @@ bool nfc_device_load_slix_l_data(FlipperFormat* file, NfcDevice* dev) {
|
|||||||
if(!flipper_format_read_hex(
|
if(!flipper_format_read_hex(
|
||||||
file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
|
file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
|
||||||
break;
|
break;
|
||||||
|
if(!flipper_format_read_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
||||||
|
|
||||||
|
parsed = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool nfc_device_save_slix2_data(FlipperFormat* file, NfcDevice* dev) {
|
||||||
|
bool saved = false;
|
||||||
|
NfcVSlix2Data* data = &dev->dev_data.nfcv_data.sub_data.slix2;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!flipper_format_write_comment_cstr(file, "SLIX2 specific data")) break;
|
||||||
|
if(!flipper_format_write_hex(file, "Password Read", data->key_read, sizeof(data->key_read))) break;
|
||||||
|
if(!flipper_format_write_hex(file, "Password Write", data->key_write, sizeof(data->key_write))) break;
|
||||||
|
if(!flipper_format_write_hex(file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) break;
|
||||||
|
if(!flipper_format_write_hex(file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) break;
|
||||||
|
if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) break;
|
||||||
|
if(!flipper_format_write_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
||||||
|
saved = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nfc_device_load_slix2_data(FlipperFormat* file, NfcDevice* dev) {
|
||||||
|
bool parsed = false;
|
||||||
|
NfcVSlix2Data* data = &dev->dev_data.nfcv_data.sub_data.slix2;
|
||||||
|
memset(data, 0, sizeof(NfcVData));
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!flipper_format_read_hex(
|
||||||
|
file, "Password Read", data->key_read, sizeof(data->key_read)))
|
||||||
|
break;
|
||||||
|
if(!flipper_format_read_hex(
|
||||||
|
file, "Password Write", data->key_write, sizeof(data->key_write)))
|
||||||
|
break;
|
||||||
|
if(!flipper_format_read_hex(
|
||||||
|
file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy)))
|
||||||
|
break;
|
||||||
|
if(!flipper_format_read_hex(
|
||||||
|
file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy)))
|
||||||
|
break;
|
||||||
|
if(!flipper_format_read_hex(
|
||||||
|
file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
|
||||||
|
break;
|
||||||
|
if(!flipper_format_read_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
||||||
|
|
||||||
|
parsed = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool nfc_device_save_nfcv_data(FlipperFormat* file, NfcDevice* dev) {
|
||||||
|
bool saved = false;
|
||||||
|
uint8_t temp_value = 0;
|
||||||
|
NfcVData* data = &dev->dev_data.nfcv_data;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!flipper_format_write_hex(file, "DSFID", &(data->dsfid), 1)) break;
|
||||||
|
if(!flipper_format_write_hex(file, "AFI", &(data->afi), 1)) break;
|
||||||
|
if(!flipper_format_write_hex(file, "IC Reference", &(data->ic_ref), 1)) break;
|
||||||
|
if(!flipper_format_write_hex(file, "Block Count", &(data->block_num), 1)) break;
|
||||||
|
if(!flipper_format_write_hex(file, "Block Size", &(data->block_size), 1)) break;
|
||||||
|
if(!flipper_format_write_hex(file, "Data Content", data->data, data->block_num * data->block_size)) break;
|
||||||
|
if(!flipper_format_write_comment_cstr(file, "Subtype of this card (0 = ISO15693, 1 = SLIX, 2 = SLIX-S, 3 = SLIX-L, 4 = SLIX2)")) break;
|
||||||
|
|
||||||
|
temp_value = data->type;
|
||||||
|
if(!flipper_format_write_hex(file, "Subtype", &temp_value, 1)) break;
|
||||||
|
|
||||||
|
switch(data->type) {
|
||||||
|
case NfcVTypePlain:
|
||||||
|
saved = true;
|
||||||
|
break;
|
||||||
|
case NfcVTypeSlix:
|
||||||
|
saved = nfc_device_save_slix_data(file, dev);
|
||||||
|
break;
|
||||||
|
case NfcVTypeSlixS:
|
||||||
|
saved = nfc_device_save_slix_s_data(file, dev);
|
||||||
|
break;
|
||||||
|
case NfcVTypeSlixL:
|
||||||
|
saved = nfc_device_save_slix_l_data(file, dev);
|
||||||
|
break;
|
||||||
|
case NfcVTypeSlix2:
|
||||||
|
saved = nfc_device_save_slix2_data(file, dev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nfc_device_load_nfcv_data(FlipperFormat* file, NfcDevice* dev) {
|
||||||
|
bool parsed = false;
|
||||||
|
uint8_t temp_value = 0;
|
||||||
|
NfcVData* data = &dev->dev_data.nfcv_data;
|
||||||
|
|
||||||
|
memset(data, 0, sizeof(NfcVData));
|
||||||
|
|
||||||
|
do {
|
||||||
if(!flipper_format_read_hex(file, "DSFID", &(data->dsfid), 1)) break;
|
if(!flipper_format_read_hex(file, "DSFID", &(data->dsfid), 1)) break;
|
||||||
if(!flipper_format_read_hex(file, "AFI", &(data->afi), 1)) break;
|
if(!flipper_format_read_hex(file, "AFI", &(data->afi), 1)) break;
|
||||||
if(!flipper_format_read_hex(file, "IC Reference", &(data->ic_ref), 1)) break;
|
if(!flipper_format_read_hex(file, "IC Reference", &(data->ic_ref), 1)) break;
|
||||||
@@ -688,8 +860,26 @@ bool nfc_device_load_slix_l_data(FlipperFormat* file, NfcDevice* dev) {
|
|||||||
if(!flipper_format_read_hex(
|
if(!flipper_format_read_hex(
|
||||||
file, "Data Content", data->data, data->block_num * data->block_size))
|
file, "Data Content", data->data, data->block_num * data->block_size))
|
||||||
break;
|
break;
|
||||||
|
if(!flipper_format_read_hex(file, "Subtype", &temp_value, 1)) break;
|
||||||
|
data->type = temp_value;
|
||||||
|
|
||||||
parsed = true;
|
switch(data->type) {
|
||||||
|
case NfcVTypePlain:
|
||||||
|
parsed = true;
|
||||||
|
break;
|
||||||
|
case NfcVTypeSlix:
|
||||||
|
parsed = nfc_device_load_slix_data(file, dev);
|
||||||
|
break;
|
||||||
|
case NfcVTypeSlixS:
|
||||||
|
parsed = nfc_device_load_slix_s_data(file, dev);
|
||||||
|
break;
|
||||||
|
case NfcVTypeSlixL:
|
||||||
|
parsed = nfc_device_load_slix_l_data(file, dev);
|
||||||
|
break;
|
||||||
|
case NfcVTypeSlix2:
|
||||||
|
parsed = nfc_device_load_slix2_data(file, dev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
return parsed;
|
return parsed;
|
||||||
@@ -1127,17 +1317,19 @@ static bool nfc_device_save_file(
|
|||||||
if(!flipper_format_write_header_cstr(file, nfc_file_header, nfc_file_version)) break;
|
if(!flipper_format_write_header_cstr(file, nfc_file_header, nfc_file_version)) break;
|
||||||
// Write nfc device type
|
// Write nfc device type
|
||||||
if(!flipper_format_write_comment_cstr(
|
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 or ISO15693"))
|
||||||
break;
|
break;
|
||||||
nfc_device_prepare_format_string(dev, temp_str);
|
nfc_device_prepare_format_string(dev, temp_str);
|
||||||
if(!flipper_format_write_string(file, "Device type", temp_str)) break;
|
if(!flipper_format_write_string(file, "Device type", temp_str)) break;
|
||||||
// Write UID
|
// Write UID
|
||||||
if(!flipper_format_write_comment_cstr(file, "UID, ATQA and SAK are common for all formats except ISO15693"))
|
if(!flipper_format_write_comment_cstr(file, "UID is common for all formats"))
|
||||||
break;
|
break;
|
||||||
if(!flipper_format_write_hex(file, "UID", data->uid, data->uid_len)) break;
|
if(!flipper_format_write_hex(file, "UID", data->uid, data->uid_len)) break;
|
||||||
|
|
||||||
if(dev->format != NfcDeviceSaveFormatSlixL) {
|
if(dev->format != NfcDeviceSaveFormatNfcV) {
|
||||||
// Write ATQA, SAK
|
// Write ATQA, SAK
|
||||||
|
if(!flipper_format_write_comment_cstr(file, "ISO14443 specific fields"))
|
||||||
|
break;
|
||||||
if(!flipper_format_write_hex(file, "ATQA", data->atqa, 2)) break;
|
if(!flipper_format_write_hex(file, "ATQA", data->atqa, 2)) break;
|
||||||
if(!flipper_format_write_hex(file, "SAK", &data->sak, 1)) break;
|
if(!flipper_format_write_hex(file, "SAK", &data->sak, 1)) break;
|
||||||
}
|
}
|
||||||
@@ -1146,8 +1338,8 @@ static bool nfc_device_save_file(
|
|||||||
if(!nfc_device_save_mifare_ul_data(file, dev)) break;
|
if(!nfc_device_save_mifare_ul_data(file, dev)) break;
|
||||||
} else if(dev->format == NfcDeviceSaveFormatMifareDesfire) {
|
} else if(dev->format == NfcDeviceSaveFormatMifareDesfire) {
|
||||||
if(!nfc_device_save_mifare_df_data(file, dev)) break;
|
if(!nfc_device_save_mifare_df_data(file, dev)) break;
|
||||||
} else if(dev->format == NfcDeviceSaveFormatSlixL) {
|
} else if(dev->format == NfcDeviceSaveFormatNfcV) {
|
||||||
if(!nfc_device_save_slix_l_data(file, dev)) break;
|
if(!nfc_device_save_nfcv_data(file, dev)) break;
|
||||||
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
|
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
|
||||||
if(!nfc_device_save_bank_card_data(file, dev)) break;
|
if(!nfc_device_save_bank_card_data(file, dev)) break;
|
||||||
} else if(dev->format == NfcDeviceSaveFormatMifareClassic) {
|
} else if(dev->format == NfcDeviceSaveFormatMifareClassic) {
|
||||||
@@ -1215,7 +1407,7 @@ static bool nfc_device_load_data(NfcDevice* dev, FuriString* path, bool show_dia
|
|||||||
if(!(data_cnt == 4 || data_cnt == 7 || data_cnt == 8)) break;
|
if(!(data_cnt == 4 || data_cnt == 7 || data_cnt == 8)) break;
|
||||||
data->uid_len = data_cnt;
|
data->uid_len = data_cnt;
|
||||||
if(!flipper_format_read_hex(file, "UID", data->uid, data->uid_len)) break;
|
if(!flipper_format_read_hex(file, "UID", data->uid, data->uid_len)) break;
|
||||||
if(dev->format != NfcDeviceSaveFormatSlixL) {
|
if(dev->format != NfcDeviceSaveFormatNfcV) {
|
||||||
if(!flipper_format_read_hex(file, "ATQA", data->atqa, 2)) break;
|
if(!flipper_format_read_hex(file, "ATQA", data->atqa, 2)) break;
|
||||||
if(!flipper_format_read_hex(file, "SAK", &data->sak, 1)) break;
|
if(!flipper_format_read_hex(file, "SAK", &data->sak, 1)) break;
|
||||||
}
|
}
|
||||||
@@ -1233,8 +1425,8 @@ static bool nfc_device_load_data(NfcDevice* dev, FuriString* path, bool show_dia
|
|||||||
if(!nfc_device_load_mifare_classic_data(file, dev)) break;
|
if(!nfc_device_load_mifare_classic_data(file, dev)) break;
|
||||||
} else if(dev->format == NfcDeviceSaveFormatMifareDesfire) {
|
} else if(dev->format == NfcDeviceSaveFormatMifareDesfire) {
|
||||||
if(!nfc_device_load_mifare_df_data(file, dev)) break;
|
if(!nfc_device_load_mifare_df_data(file, dev)) break;
|
||||||
} else if(dev->format == NfcDeviceSaveFormatSlixL) {
|
} else if(dev->format == NfcDeviceSaveFormatNfcV) {
|
||||||
if(!nfc_device_load_slix_l_data(file, dev)) break;
|
if(!nfc_device_load_nfcv_data(file, dev)) break;
|
||||||
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
|
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
|
||||||
if(!nfc_device_load_bank_card_data(file, dev)) break;
|
if(!nfc_device_load_bank_card_data(file, dev)) break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ typedef enum {
|
|||||||
NfcDeviceProtocolMifareUl,
|
NfcDeviceProtocolMifareUl,
|
||||||
NfcDeviceProtocolMifareClassic,
|
NfcDeviceProtocolMifareClassic,
|
||||||
NfcDeviceProtocolMifareDesfire,
|
NfcDeviceProtocolMifareDesfire,
|
||||||
NfcDeviceProtocolNfcV,
|
NfcDeviceProtocolNfcV
|
||||||
NfcDeviceProtocolSlixL,
|
|
||||||
} NfcProtocol;
|
} NfcProtocol;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -43,7 +42,7 @@ typedef enum {
|
|||||||
NfcDeviceSaveFormatMifareUl,
|
NfcDeviceSaveFormatMifareUl,
|
||||||
NfcDeviceSaveFormatMifareClassic,
|
NfcDeviceSaveFormatMifareClassic,
|
||||||
NfcDeviceSaveFormatMifareDesfire,
|
NfcDeviceSaveFormatMifareDesfire,
|
||||||
NfcDeviceSaveFormatSlixL,
|
NfcDeviceSaveFormatNfcV,
|
||||||
} NfcDeviceSaveFormat;
|
} NfcDeviceSaveFormat;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -176,11 +176,12 @@ void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) {
|
|||||||
|
|
||||||
if(nfcv_data->auth_method == NfcVAuthMethodManual) {
|
if(nfcv_data->auth_method == NfcVAuthMethodManual) {
|
||||||
uint32_t key = 0;
|
uint32_t key = 0;
|
||||||
|
uint8_t *key_data = nfc_worker->dev_data->nfcv_data.sub_data.slix_l.key_privacy;
|
||||||
|
|
||||||
key |= nfc_worker->dev_data->nfcv_data.key_privacy[0] << 24;
|
key |= key_data[0] << 24;
|
||||||
key |= nfc_worker->dev_data->nfcv_data.key_privacy[1] << 16;
|
key |= key_data[1] << 16;
|
||||||
key |= nfc_worker->dev_data->nfcv_data.key_privacy[2] << 8;
|
key |= key_data[2] << 8;
|
||||||
key |= nfc_worker->dev_data->nfcv_data.key_privacy[3] << 0;
|
key |= key_data[3] << 0;
|
||||||
ret = slix_l_unlock(4, rand, key);
|
ret = slix_l_unlock(4, rand, key);
|
||||||
} else {
|
} else {
|
||||||
ret = slix_l_unlock(4, rand, 0x7FFD6E5B);
|
ret = slix_l_unlock(4, rand, 0x7FFD6E5B);
|
||||||
@@ -493,17 +494,31 @@ static bool nfc_worker_read_nfcv(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* t
|
|||||||
furi_assert(tx_rx);
|
furi_assert(tx_rx);
|
||||||
|
|
||||||
FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
|
FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
|
||||||
|
NfcVData* nfcv_data = &nfc_worker->dev_data->nfcv_data;
|
||||||
|
|
||||||
bool card_read = false;
|
bool card_read = false;
|
||||||
furi_hal_nfc_sleep();
|
furi_hal_nfc_sleep();
|
||||||
if(slix_l_check_card_type(nfc_data->uid[7], nfc_data->uid[6], nfc_data->uid[5])) {
|
|
||||||
|
/* until here the UID field is reversed from the reader IC.
|
||||||
|
we will read it here again and it will get placed in the right order. */
|
||||||
|
card_read = nfc_worker_read_nfcv_content(nfc_worker, tx_rx);
|
||||||
|
|
||||||
|
nfc_worker->dev_data->protocol = NfcDeviceProtocolNfcV;
|
||||||
|
|
||||||
|
if(slix_check_card_type(nfc_data)) {
|
||||||
|
FURI_LOG_I(TAG, "NXP SLIX detected");
|
||||||
|
nfcv_data->type = NfcVTypeSlix;
|
||||||
|
} else if(slix2_check_card_type(nfc_data)) {
|
||||||
|
FURI_LOG_I(TAG, "NXP SLIX2 detected");
|
||||||
|
nfcv_data->type = NfcVTypeSlix2;
|
||||||
|
} else if(slix_s_check_card_type(nfc_data)) {
|
||||||
FURI_LOG_I(TAG, "NXP SLIX-L detected");
|
FURI_LOG_I(TAG, "NXP SLIX-L detected");
|
||||||
nfc_worker->dev_data->protocol = NfcDeviceProtocolSlixL;
|
nfcv_data->type = NfcVTypeSlixS;
|
||||||
card_read = nfc_worker_read_nfcv_content(nfc_worker, tx_rx);
|
} else if(slix_l_check_card_type(nfc_data)) {
|
||||||
|
FURI_LOG_I(TAG, "NXP SLIX-L detected");
|
||||||
|
nfcv_data->type = NfcVTypeSlixL;
|
||||||
} else {
|
} else {
|
||||||
FURI_LOG_I(TAG, "unknown detected");
|
nfcv_data->type = NfcVTypePlain;
|
||||||
nfc_worker->dev_data->protocol = NfcDeviceProtocolNfcV;
|
|
||||||
card_read = nfc_worker_read_nfcv_content(nfc_worker, tx_rx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return card_read;
|
return card_read;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include <lib/nfc/protocols/mifare_desfire.h>
|
#include <lib/nfc/protocols/mifare_desfire.h>
|
||||||
#include <lib/nfc/protocols/nfca.h>
|
#include <lib/nfc/protocols/nfca.h>
|
||||||
#include <lib/nfc/protocols/nfcv.h>
|
#include <lib/nfc/protocols/nfcv.h>
|
||||||
#include <lib/nfc/protocols/slix_l.h>
|
#include <lib/nfc/protocols/slix.h>
|
||||||
#include <lib/nfc/helpers/reader_analyzer.h>
|
#include <lib/nfc/helpers/reader_analyzer.h>
|
||||||
|
|
||||||
struct NfcWorker {
|
struct NfcWorker {
|
||||||
|
|||||||
@@ -8,6 +8,10 @@
|
|||||||
#include <furi_hal_resources.h>
|
#include <furi_hal_resources.h>
|
||||||
#include <st25r3916.h>
|
#include <st25r3916.h>
|
||||||
#include <st25r3916_irq.h>
|
#include <st25r3916_irq.h>
|
||||||
|
#include <stm32wbxx_ll_dma.h>
|
||||||
|
#include <stm32wbxx_ll_dmamux.h>
|
||||||
|
#include <stm32wbxx_ll_tim.h>
|
||||||
|
#include <stm32wbxx_ll_exti.h>
|
||||||
|
|
||||||
#include "nfcv.h"
|
#include "nfcv.h"
|
||||||
#include "nfc_util.h"
|
#include "nfc_util.h"
|
||||||
@@ -75,7 +79,7 @@ ReturnCode nfcv_read_sysinfo(FuriHalNfcDevData* nfc_data, NfcVData* data) {
|
|||||||
if(ret == ERR_NONE) {
|
if(ret == ERR_NONE) {
|
||||||
nfc_data->type = FuriHalNfcTypeV;
|
nfc_data->type = FuriHalNfcTypeV;
|
||||||
nfc_data->uid_len = 8;
|
nfc_data->uid_len = 8;
|
||||||
/* UID is stored reversed in this structure */
|
/* UID is stored reversed in this response */
|
||||||
for(int pos = 0; pos < nfc_data->uid_len; pos++) {
|
for(int pos = 0; pos < nfc_data->uid_len; pos++) {
|
||||||
nfc_data->uid[pos] = rxBuf[2 + (7 - pos)];
|
nfc_data->uid[pos] = rxBuf[2 + (7 - pos)];
|
||||||
}
|
}
|
||||||
@@ -316,41 +320,62 @@ void nfcv_emu_handle_packet(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, ui
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t response_buffer[32];
|
uint8_t response_buffer[32];
|
||||||
|
|
||||||
|
switch(nfcv_data->type) {
|
||||||
|
case NfcVTypeSlixL:
|
||||||
|
if(nfcv_data->sub_data.slix_l.privacy &&
|
||||||
|
command != ISO15693_CMD_NXP_GET_RANDOM_NUMBER &&
|
||||||
|
command != ISO15693_CMD_NXP_SET_PASSWORD) {
|
||||||
|
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "(command ignored, privacy)");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch(command) {
|
switch(command) {
|
||||||
case ISO15693_GET_SYSTEM_INFO:
|
|
||||||
{
|
|
||||||
if(nfcv_data->privacy) {
|
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SYSTEMINFO (ignored, privacy)");
|
|
||||||
} else {
|
|
||||||
response_buffer[0] = ISO15693_NOERROR;
|
|
||||||
response_buffer[1] = 0x0F;
|
|
||||||
nfcv_uidcpy(&response_buffer[2], nfc_data->uid);
|
|
||||||
response_buffer[10] = nfcv_data->dsfid; /* DSFID */
|
|
||||||
response_buffer[11] = nfcv_data->afi; /* AFI */
|
|
||||||
response_buffer[12] = nfcv_data->block_num - 1; /* number of blocks */
|
|
||||||
response_buffer[13] = nfcv_data->block_size - 1; /* block size */
|
|
||||||
response_buffer[14] = nfcv_data->ic_ref; /* IC reference */
|
|
||||||
|
|
||||||
nfcv_emu_send(response_buffer, 15);
|
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SYSTEMINFO");
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ISO15693_INVENTORY:
|
case ISO15693_INVENTORY:
|
||||||
{
|
{
|
||||||
if(nfcv_data->privacy) {
|
response_buffer[0] = ISO15693_NOERROR;
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "INVENTORY (ignored, privacy)");
|
response_buffer[1] = nfcv_data->dsfid; /* DSFID */
|
||||||
} else {
|
nfcv_uidcpy(&response_buffer[2], nfc_data->uid);
|
||||||
response_buffer[0] = ISO15693_NOERROR;
|
|
||||||
response_buffer[1] = nfcv_data->dsfid; /* DSFID */
|
|
||||||
nfcv_uidcpy(&response_buffer[2], nfc_data->uid);
|
|
||||||
|
|
||||||
nfcv_emu_send(response_buffer, 10);
|
nfcv_emu_send(response_buffer, 10);
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "INVENTORY");
|
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "INVENTORY");
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ISO15693_STAYQUIET:
|
||||||
|
{
|
||||||
|
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "STAYQUIET");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ISO15693_LOCKBLOCK:
|
||||||
|
{
|
||||||
|
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "LOCKBLOCK");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ISO15693_READ_MULTI_BLOCK:
|
||||||
|
{
|
||||||
|
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "READ_MULTI_BLOCK");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ISO15693_WRITE_MULTI_BLOCK:
|
||||||
|
{
|
||||||
|
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "WRITE_MULTI_BLOCK");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ISO15693_SELECT:
|
||||||
|
{
|
||||||
|
response_buffer[0] = ISO15693_NOERROR;
|
||||||
|
nfcv_emu_send(response_buffer, 1);
|
||||||
|
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SELECT");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,11 +411,31 @@ void nfcv_emu_handle_packet(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, ui
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ISO15693_GET_SYSTEM_INFO:
|
||||||
|
{
|
||||||
|
response_buffer[0] = ISO15693_NOERROR;
|
||||||
|
response_buffer[1] = 0x0F;
|
||||||
|
nfcv_uidcpy(&response_buffer[2], nfc_data->uid);
|
||||||
|
response_buffer[10] = nfcv_data->dsfid; /* DSFID */
|
||||||
|
response_buffer[11] = nfcv_data->afi; /* AFI */
|
||||||
|
response_buffer[12] = nfcv_data->block_num - 1; /* number of blocks */
|
||||||
|
response_buffer[13] = nfcv_data->block_size - 1; /* block size */
|
||||||
|
response_buffer[14] = nfcv_data->ic_ref; /* IC reference */
|
||||||
|
|
||||||
|
nfcv_emu_send(response_buffer, 15);
|
||||||
|
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SYSTEMINFO");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case ISO15693_CMD_NXP_GET_RANDOM_NUMBER:
|
case ISO15693_CMD_NXP_GET_RANDOM_NUMBER:
|
||||||
{
|
{
|
||||||
|
nfcv_data->sub_data.slix_l.rand[0] = 0x00;
|
||||||
|
nfcv_data->sub_data.slix_l.rand[1] = 0x00;
|
||||||
|
|
||||||
response_buffer[0] = ISO15693_NOERROR;
|
response_buffer[0] = ISO15693_NOERROR;
|
||||||
response_buffer[1] = 0x00; /* set number to 0x0000 so we get the key in plaintext */
|
response_buffer[1] = nfcv_data->sub_data.slix_l.rand[0];
|
||||||
response_buffer[2] = 0x00;
|
response_buffer[2] = nfcv_data->sub_data.slix_l.rand[1];
|
||||||
|
|
||||||
nfcv_emu_send(response_buffer, 3);
|
nfcv_emu_send(response_buffer, 3);
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "GET_RANDOM_NUMBER");
|
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "GET_RANDOM_NUMBER");
|
||||||
@@ -399,17 +444,43 @@ void nfcv_emu_handle_packet(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, ui
|
|||||||
|
|
||||||
case ISO15693_CMD_NXP_SET_PASSWORD:
|
case ISO15693_CMD_NXP_SET_PASSWORD:
|
||||||
{
|
{
|
||||||
uint32_t pass = (payload[payload_offset + 1] << 24)
|
uint8_t password_id = payload[payload_offset];
|
||||||
| (payload[payload_offset + 2] << 16)
|
uint8_t *password_xored = &payload[payload_offset + 1];
|
||||||
| (payload[payload_offset + 3] << 8)
|
uint8_t *rand = nfcv_data->sub_data.slix_l.rand;
|
||||||
| (payload[payload_offset + 4] << 0);
|
uint8_t status = ISO15693_ERROR_GENERIC;
|
||||||
|
uint8_t *password = NULL;
|
||||||
|
uint8_t password_rcv[4];
|
||||||
|
|
||||||
response_buffer[0] = ISO15693_NOERROR;
|
switch(password_id) {
|
||||||
|
case 4:
|
||||||
|
password = nfcv_data->sub_data.slix_l.key_privacy;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
password = nfcv_data->sub_data.slix_l.key_destroy;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
password = nfcv_data->sub_data.slix_l.key_eas;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int pos = 0; pos < 4; pos++) {
|
||||||
|
password_rcv[pos] = password_xored[pos] ^ rand[pos % 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!memcmp(password, password_rcv, 4)) {
|
||||||
|
status = ISO15693_NOERROR;
|
||||||
|
nfcv_data->sub_data.slix_l.privacy = false;
|
||||||
|
} else {
|
||||||
|
printf("pass mismatch: %08lX %08lX %02X", *((uint32_t *)password), *((uint32_t *)password_xored), *rand);
|
||||||
|
}
|
||||||
|
|
||||||
|
response_buffer[0] = status;
|
||||||
|
|
||||||
nfcv_emu_send(response_buffer, 1);
|
nfcv_emu_send(response_buffer, 1);
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SET_PASSWORD #%02X: %08lX", payload[payload_offset + 0], pass);
|
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SET_PASSWORD #%02X", password_id);
|
||||||
|
|
||||||
nfcv_data->privacy = false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,7 +491,7 @@ void nfcv_emu_handle_packet(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, ui
|
|||||||
nfcv_emu_send(response_buffer, 1);
|
nfcv_emu_send(response_buffer, 1);
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "ISO15693_CMD_NXP_ENABLE_PRIVACY");
|
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "ISO15693_CMD_NXP_ENABLE_PRIVACY");
|
||||||
|
|
||||||
nfcv_data->privacy = true;
|
nfcv_data->sub_data.slix_l.privacy = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,6 +501,10 @@ void nfcv_emu_handle_packet(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, ui
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define COUNT(x) ((sizeof(x))/(sizeof(x[0])))
|
||||||
|
uint32_t nfcv_timer_buffer_src[32];
|
||||||
|
uint32_t nfcv_timer_buffer[1024];
|
||||||
|
|
||||||
void nfcv_emu_init() {
|
void nfcv_emu_init() {
|
||||||
nfcv_emu_alloc();
|
nfcv_emu_alloc();
|
||||||
rfal_platform_spi_acquire();
|
rfal_platform_spi_acquire();
|
||||||
@@ -440,6 +515,53 @@ void nfcv_emu_init() {
|
|||||||
st25r3916ExecuteCommand(ST25R3916_CMD_TRANSPARENT_MODE);
|
st25r3916ExecuteCommand(ST25R3916_CMD_TRANSPARENT_MODE);
|
||||||
|
|
||||||
furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_nfc);
|
furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_nfc);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
memset(nfcv_timer_buffer_src, 0xEE, sizeof(nfcv_timer_buffer_src));
|
||||||
|
memset(nfcv_timer_buffer, 0xFA, sizeof(nfcv_timer_buffer));
|
||||||
|
|
||||||
|
/* configure DMA to read from a timer peripheral */
|
||||||
|
LL_DMA_InitTypeDef dma_config = {};
|
||||||
|
dma_config.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
|
||||||
|
dma_config.PeriphOrM2MSrcAddress = (uint32_t) &(TIM2->CNT);
|
||||||
|
dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
|
||||||
|
dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD;
|
||||||
|
dma_config.MemoryOrM2MDstAddress = (uint32_t) nfcv_timer_buffer;
|
||||||
|
dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
||||||
|
dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
|
||||||
|
dma_config.Mode = LL_DMA_MODE_NORMAL;
|
||||||
|
dma_config.NbData = 32; /* executes LL_DMA_SetDataLength */
|
||||||
|
dma_config.PeriphRequest = LL_DMAMUX_REQ_GENERATOR0; /* executes LL_DMA_SetPeriphRequest */
|
||||||
|
dma_config.Priority = LL_DMA_PRIORITY_VERYHIGH;
|
||||||
|
|
||||||
|
/* now set up DMA with these settings */
|
||||||
|
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_4);
|
||||||
|
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_4, &dma_config);
|
||||||
|
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_4);
|
||||||
|
|
||||||
|
/* make some noise on the counter */
|
||||||
|
LL_TIM_DisableCounter(TIM2);
|
||||||
|
LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP);
|
||||||
|
LL_TIM_SetClockDivision(TIM2, LL_TIM_CLOCKDIVISION_DIV1);
|
||||||
|
LL_TIM_SetPrescaler(TIM2, 0);
|
||||||
|
LL_TIM_SetAutoReload(TIM2, 0xFFF);
|
||||||
|
LL_TIM_SetCounter(TIM2, 0);
|
||||||
|
LL_TIM_EnableCounter(TIM2);
|
||||||
|
|
||||||
|
/* make sure request generation is disabled before modifying registers */
|
||||||
|
LL_DMAMUX_DisableRequestGen(NULL, LL_DMAMUX_REQ_GEN_0);
|
||||||
|
/* generator 0 gets fed by EXTI_LINE4 */
|
||||||
|
LL_DMAMUX_SetRequestSignalID(NULL, LL_DMAMUX_REQ_GEN_0, LL_DMAMUX_REQ_GEN_EXTI_LINE4);
|
||||||
|
/* trigger on any edge - for now. should be only one? */
|
||||||
|
LL_DMAMUX_SetRequestGenPolarity(NULL, LL_DMAMUX_REQ_GEN_0, LL_DMAMUX_REQ_GEN_POL_RISING);
|
||||||
|
/* now enable request generation again */
|
||||||
|
LL_DMAMUX_EnableRequestGen(NULL, LL_DMAMUX_REQ_GEN_0);
|
||||||
|
|
||||||
|
/* configure PB4 as source for EXTI_LINE4. shall it rain. */
|
||||||
|
LL_SYSCFG_SetEXTISource(LL_SYSCFG_EXTI_PORTB, LL_GPIO_PIN_4);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nfcv_emu_deinit() {
|
void nfcv_emu_deinit() {
|
||||||
@@ -469,6 +591,7 @@ bool nfcv_emu_loop(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint32_t ti
|
|||||||
bool in_critical = false;
|
bool in_critical = false;
|
||||||
FURI_CRITICAL_DEFINE();
|
FURI_CRITICAL_DEFINE();
|
||||||
|
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
|
|
||||||
bool state = furi_hal_gpio_read(&gpio_spi_r_miso);
|
bool state = furi_hal_gpio_read(&gpio_spi_r_miso);
|
||||||
@@ -633,6 +756,7 @@ bool nfcv_emu_loop(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint32_t ti
|
|||||||
if(timeout && cur_time > timeout) {
|
if(timeout && cur_time > timeout) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* might exit early on overflows. guess thats okay. */
|
/* might exit early on overflows. guess thats okay. */
|
||||||
if(cur_time > next_sleep) {
|
if(cur_time > next_sleep) {
|
||||||
break;
|
break;
|
||||||
@@ -659,8 +783,16 @@ bool nfcv_emu_loop(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint32_t ti
|
|||||||
nfcv_emu_handle_packet(nfc_data, nfcv_data, frame_payload, frame_pos);
|
nfcv_emu_handle_packet(nfc_data, nfcv_data, frame_payload, frame_pos);
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
furi_delay_ms(0);
|
printf("nfcv_timer_buffer: %ld", LL_DMA_GetDataLength(DMA1, LL_DMA_CHANNEL_4));
|
||||||
|
for(uint32_t pos = 0; pos < 64; pos++) {
|
||||||
|
if((pos % 4) == 0) {
|
||||||
|
printf("\r\n");
|
||||||
|
}
|
||||||
|
printf(" 0x%08lX ", nfcv_timer_buffer[pos]);
|
||||||
|
}
|
||||||
|
furi_delay_ms(100);
|
||||||
|
*/
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,31 +81,71 @@ typedef enum {
|
|||||||
} NfcVAuthMethod;
|
} NfcVAuthMethod;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NfcVTypeSlix,
|
NfcVTypePlain = 0,
|
||||||
NfcVTypeSlixS,
|
NfcVTypeSlix = 1,
|
||||||
NfcVTypeSlixL,
|
NfcVTypeSlixS = 2,
|
||||||
NfcVTypeSlix2,
|
NfcVTypeSlixL = 3,
|
||||||
|
NfcVTypeSlix2 = 4,
|
||||||
} NfcVType;
|
} NfcVType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
NfcVType type;
|
uint8_t key_eas[4];
|
||||||
NfcVAuthMethod auth_method;
|
uint8_t rand[2];
|
||||||
bool auth_success;
|
} NfcVSlixData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t key_read[4];
|
||||||
|
uint8_t key_write[4];
|
||||||
uint8_t key_privacy[4];
|
uint8_t key_privacy[4];
|
||||||
uint8_t key_destroy[4];
|
uint8_t key_destroy[4];
|
||||||
uint8_t key_eas[4];
|
uint8_t key_eas[4];
|
||||||
|
uint8_t rand[2];
|
||||||
|
bool privacy;
|
||||||
|
} NfcVSlix2Data;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t key_read[4];
|
||||||
|
uint8_t key_write[4];
|
||||||
|
uint8_t key_privacy[4];
|
||||||
|
uint8_t key_destroy[4];
|
||||||
|
uint8_t key_eas[4];
|
||||||
|
uint8_t rand[2];
|
||||||
|
bool privacy;
|
||||||
|
} NfcVSlixSData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t key_privacy[4];
|
||||||
|
uint8_t key_destroy[4];
|
||||||
|
uint8_t key_eas[4];
|
||||||
|
uint8_t rand[2];
|
||||||
|
bool privacy;
|
||||||
|
} NfcVSlixLData;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
NfcVSlixData slix;
|
||||||
|
NfcVSlix2Data slix2;
|
||||||
|
NfcVSlixSData slix_s;
|
||||||
|
NfcVSlixLData slix_l;
|
||||||
|
} NfcVSubtypeData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* common ISO15693 fields */
|
||||||
uint8_t dsfid;
|
uint8_t dsfid;
|
||||||
uint8_t afi;
|
uint8_t afi;
|
||||||
uint8_t ic_ref;
|
uint8_t ic_ref;
|
||||||
uint8_t block_num;
|
uint8_t block_num;
|
||||||
uint8_t block_size;
|
uint8_t block_size;
|
||||||
uint8_t data[NFCV_MAX_DUMP_SIZE];
|
uint8_t data[NFCV_MAX_DUMP_SIZE];
|
||||||
bool privacy;
|
|
||||||
|
|
||||||
char error[32];
|
/* specfic variant infos */
|
||||||
|
NfcVType type;
|
||||||
|
NfcVSubtypeData sub_data;
|
||||||
|
|
||||||
|
/* runtime data */
|
||||||
char last_command[128];
|
char last_command[128];
|
||||||
|
char error[32];
|
||||||
|
NfcVAuthMethod auth_method;
|
||||||
|
bool auth_success;
|
||||||
} NfcVData;
|
} NfcVData;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -1,14 +1,45 @@
|
|||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include "nfcv.h"
|
#include "nfcv.h"
|
||||||
#include "slix_l.h"
|
#include "slix.h"
|
||||||
#include "nfc_util.h"
|
#include "nfc_util.h"
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include "furi_hal_nfc.h"
|
#include "furi_hal_nfc.h"
|
||||||
|
|
||||||
|
|
||||||
bool slix_l_check_card_type(uint8_t UID0, uint8_t UID1, uint8_t UID2) {
|
bool slix_check_card_type(FuriHalNfcDevData* nfc_data) {
|
||||||
if((UID0 == 0xE0) && (UID1 == 0x04) && (UID2 == 0x03)) {
|
if((nfc_data->uid[0] == 0xE0)
|
||||||
|
&& (nfc_data->uid[1] == 0x04)
|
||||||
|
&& (nfc_data->uid[2] == 0x01)
|
||||||
|
&& (((nfc_data->uid[3] >> 4) & 3) == 2)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool slix2_check_card_type(FuriHalNfcDevData* nfc_data) {
|
||||||
|
if((nfc_data->uid[0] == 0xE0)
|
||||||
|
&& (nfc_data->uid[1] == 0x04)
|
||||||
|
&& (nfc_data->uid[2] == 0x01)
|
||||||
|
&& (((nfc_data->uid[3] >> 4) & 3) == 1)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool slix_s_check_card_type(FuriHalNfcDevData* nfc_data) {
|
||||||
|
if((nfc_data->uid[0] == 0xE0)
|
||||||
|
&& (nfc_data->uid[1] == 0x04)
|
||||||
|
&& (nfc_data->uid[2] == 0x02)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool slix_l_check_card_type(FuriHalNfcDevData* nfc_data) {
|
||||||
|
if((nfc_data->uid[0] == 0xE0)
|
||||||
|
&& (nfc_data->uid[1] == 0x04)
|
||||||
|
&& (nfc_data->uid[2] == 0x03)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -49,10 +80,10 @@ ReturnCode slix_l_unlock(uint32_t id, uint8_t* rand, uint32_t password) {
|
|||||||
uint8_t rxBuf[32];
|
uint8_t rxBuf[32];
|
||||||
uint8_t cmd_set_pass[] = {
|
uint8_t cmd_set_pass[] = {
|
||||||
id,
|
id,
|
||||||
rand[0] ^ ((password>>0) & 0xFF),
|
rand[0] ^ ((password >> 0) & 0xFF),
|
||||||
rand[1] ^ ((password>>8) & 0xFF),
|
rand[1] ^ ((password >> 8) & 0xFF),
|
||||||
rand[0] ^ ((password>>16) & 0xFF),
|
rand[0] ^ ((password >> 16) & 0xFF),
|
||||||
rand[1] ^ ((password>>24) & 0xFF)
|
rand[1] ^ ((password >> 24) & 0xFF)
|
||||||
};
|
};
|
||||||
|
|
||||||
ReturnCode ret = rfalNfcvPollerTransceiveReq(
|
ReturnCode ret = rfalNfcvPollerTransceiveReq(
|
||||||
@@ -10,8 +10,10 @@
|
|||||||
#define ISO15693_MANUFACTURER_NXP 0x04
|
#define ISO15693_MANUFACTURER_NXP 0x04
|
||||||
|
|
||||||
|
|
||||||
bool slix_l_check_card_type(uint8_t UID0, uint8_t UID1, uint8_t UID2);
|
bool slix_check_card_type(FuriHalNfcDevData* nfc_data);
|
||||||
|
bool slix2_check_card_type(FuriHalNfcDevData* nfc_data);
|
||||||
|
bool slix_s_check_card_type(FuriHalNfcDevData* nfc_data);
|
||||||
|
bool slix_l_check_card_type(FuriHalNfcDevData* nfc_data);
|
||||||
ReturnCode slix_l_get_random(uint8_t* rand);
|
ReturnCode slix_l_get_random(uint8_t* rand);
|
||||||
ReturnCode slix_l_unlock(uint32_t id, uint8_t* rand, uint32_t password);
|
ReturnCode slix_l_unlock(uint32_t id, uint8_t* rand, uint32_t password);
|
||||||
|
|
||||||
Reference in New Issue
Block a user