mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2025-02-17 05:48:33 +00:00
Merge branch 'ofw_dev' into dev
This commit is contained in:
commit
3e53e69827
4 changed files with 169 additions and 7 deletions
|
@ -200,6 +200,15 @@ App(
|
||||||
sources=["plugins/supported_cards/ndef.c"],
|
sources=["plugins/supported_cards/ndef.c"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
App(
|
||||||
|
appid="itso_parser",
|
||||||
|
apptype=FlipperAppType.PLUGIN,
|
||||||
|
entry_point="itso_plugin_ep",
|
||||||
|
targets=["f7"],
|
||||||
|
requires=["nfc"],
|
||||||
|
sources=["plugins/supported_cards/itso.c"],
|
||||||
|
)
|
||||||
|
|
||||||
App(
|
App(
|
||||||
appid="nfc_start",
|
appid="nfc_start",
|
||||||
targets=["f7"],
|
targets=["f7"],
|
||||||
|
|
|
@ -14,6 +14,7 @@ enum {
|
||||||
SubmenuIndexDetectReader = SubmenuIndexCommonMax,
|
SubmenuIndexDetectReader = SubmenuIndexCommonMax,
|
||||||
SubmenuIndexWrite,
|
SubmenuIndexWrite,
|
||||||
SubmenuIndexUpdate,
|
SubmenuIndexUpdate,
|
||||||
|
SubmenuIndexDictAttack
|
||||||
};
|
};
|
||||||
|
|
||||||
static void nfc_scene_info_on_enter_mf_classic(NfcApp* instance) {
|
static void nfc_scene_info_on_enter_mf_classic(NfcApp* instance) {
|
||||||
|
@ -120,6 +121,13 @@ static void nfc_scene_read_menu_on_enter_mf_classic(NfcApp* instance) {
|
||||||
SubmenuIndexDetectReader,
|
SubmenuIndexDetectReader,
|
||||||
nfc_protocol_support_common_submenu_callback,
|
nfc_protocol_support_common_submenu_callback,
|
||||||
instance);
|
instance);
|
||||||
|
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Unlock with Dictionary",
|
||||||
|
SubmenuIndexDictAttack,
|
||||||
|
nfc_protocol_support_common_submenu_callback,
|
||||||
|
instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,6 +159,13 @@ static void nfc_scene_saved_menu_on_enter_mf_classic(NfcApp* instance) {
|
||||||
SubmenuIndexDetectReader,
|
SubmenuIndexDetectReader,
|
||||||
nfc_protocol_support_common_submenu_callback,
|
nfc_protocol_support_common_submenu_callback,
|
||||||
instance);
|
instance);
|
||||||
|
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Unlock with Dictionary",
|
||||||
|
SubmenuIndexDictAttack,
|
||||||
|
nfc_protocol_support_common_submenu_callback,
|
||||||
|
instance);
|
||||||
}
|
}
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu,
|
submenu,
|
||||||
|
@ -158,6 +173,7 @@ static void nfc_scene_saved_menu_on_enter_mf_classic(NfcApp* instance) {
|
||||||
SubmenuIndexWrite,
|
SubmenuIndexWrite,
|
||||||
nfc_protocol_support_common_submenu_callback,
|
nfc_protocol_support_common_submenu_callback,
|
||||||
instance);
|
instance);
|
||||||
|
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu,
|
submenu,
|
||||||
"Update from Initial Card",
|
"Update from Initial Card",
|
||||||
|
@ -173,13 +189,20 @@ static void nfc_scene_emulate_on_enter_mf_classic(NfcApp* instance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool nfc_scene_read_menu_on_event_mf_classic(NfcApp* instance, SceneManagerEvent event) {
|
static bool nfc_scene_read_menu_on_event_mf_classic(NfcApp* instance, SceneManagerEvent event) {
|
||||||
if(event.type == SceneManagerEventTypeCustom && event.event == SubmenuIndexDetectReader) {
|
bool consumed = false;
|
||||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSaveConfirm);
|
|
||||||
dolphin_deed(DolphinDeedNfcDetectReader);
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
return true;
|
if(event.event == SubmenuIndexDetectReader) {
|
||||||
|
scene_manager_next_scene(instance->scene_manager, NfcSceneSaveConfirm);
|
||||||
|
dolphin_deed(DolphinDeedNfcDetectReader);
|
||||||
|
consumed = true;
|
||||||
|
} else if(event.event == SubmenuIndexDictAttack) {
|
||||||
|
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicDictAttack);
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool nfc_scene_saved_menu_on_event_mf_classic(NfcApp* instance, SceneManagerEvent event) {
|
static bool nfc_scene_saved_menu_on_event_mf_classic(NfcApp* instance, SceneManagerEvent event) {
|
||||||
|
@ -195,6 +218,9 @@ static bool nfc_scene_saved_menu_on_event_mf_classic(NfcApp* instance, SceneMana
|
||||||
} else if(event.event == SubmenuIndexUpdate) {
|
} else if(event.event == SubmenuIndexUpdate) {
|
||||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicUpdateInitial);
|
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicUpdateInitial);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
} else if(event.event == SubmenuIndexDictAttack) {
|
||||||
|
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicDictAttack);
|
||||||
|
consumed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
124
applications/main/nfc/plugins/supported_cards/itso.c
Normal file
124
applications/main/nfc/plugins/supported_cards/itso.c
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
/* itso.c - Parser for ITSO cards (United Kingdom). */
|
||||||
|
#include "nfc_supported_card_plugin.h"
|
||||||
|
|
||||||
|
#include <flipper_application/flipper_application.h>
|
||||||
|
#include <lib/nfc/protocols/mf_desfire/mf_desfire.h>
|
||||||
|
|
||||||
|
#include <applications/services/locale/locale.h>
|
||||||
|
#include <furi_hal_rtc.h>
|
||||||
|
|
||||||
|
static const MfDesfireApplicationId itso_app_id = {.data = {0x16, 0x02, 0xa0}};
|
||||||
|
static const MfDesfireFileId itso_file_id = 0x0f;
|
||||||
|
|
||||||
|
int64_t swap_int64(int64_t val) {
|
||||||
|
val = ((val << 8) & 0xFF00FF00FF00FF00ULL) | ((val >> 8) & 0x00FF00FF00FF00FFULL);
|
||||||
|
val = ((val << 16) & 0xFFFF0000FFFF0000ULL) | ((val >> 16) & 0x0000FFFF0000FFFFULL);
|
||||||
|
return (val << 32) | ((val >> 32) & 0xFFFFFFFFULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t swap_uint64(uint64_t val) {
|
||||||
|
val = ((val << 8) & 0xFF00FF00FF00FF00ULL) | ((val >> 8) & 0x00FF00FF00FF00FFULL);
|
||||||
|
val = ((val << 16) & 0xFFFF0000FFFF0000ULL) | ((val >> 16) & 0x0000FFFF0000FFFFULL);
|
||||||
|
return (val << 32) | (val >> 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool itso_parse(const NfcDevice* device, FuriString* parsed_data) {
|
||||||
|
furi_assert(device);
|
||||||
|
furi_assert(parsed_data);
|
||||||
|
|
||||||
|
bool parsed = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
const MfDesfireData* data = nfc_device_get_data(device, NfcProtocolMfDesfire);
|
||||||
|
|
||||||
|
const MfDesfireApplication* app = mf_desfire_get_application(data, &itso_app_id);
|
||||||
|
if(app == NULL) break;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t part1;
|
||||||
|
uint64_t part2;
|
||||||
|
uint64_t part3;
|
||||||
|
uint64_t part4;
|
||||||
|
} ItsoFile;
|
||||||
|
|
||||||
|
const MfDesfireFileSettings* file_settings =
|
||||||
|
mf_desfire_get_file_settings(app, &itso_file_id);
|
||||||
|
|
||||||
|
if(file_settings == NULL || file_settings->type != MfDesfireFileTypeStandard ||
|
||||||
|
file_settings->data.size < sizeof(ItsoFile))
|
||||||
|
break;
|
||||||
|
|
||||||
|
const MfDesfireFileData* file_data = mf_desfire_get_file_data(app, &itso_file_id);
|
||||||
|
if(file_data == NULL) break;
|
||||||
|
|
||||||
|
const ItsoFile* itso_file = simple_array_cget_data(file_data->data);
|
||||||
|
|
||||||
|
uint64_t x1 = swap_uint64(itso_file->part1);
|
||||||
|
uint64_t x2 = swap_uint64(itso_file->part2);
|
||||||
|
|
||||||
|
char cardBuff[32];
|
||||||
|
char dateBuff[18];
|
||||||
|
|
||||||
|
snprintf(cardBuff, sizeof(cardBuff), "%llx%llx", x1, x2);
|
||||||
|
snprintf(dateBuff, sizeof(dateBuff), "%llx", x2);
|
||||||
|
|
||||||
|
char* cardp = cardBuff + 4;
|
||||||
|
cardp[18] = '\0';
|
||||||
|
|
||||||
|
// All itso card numbers are prefixed with "633597"
|
||||||
|
if(strncmp(cardp, "633597", 6) != 0) break;
|
||||||
|
|
||||||
|
char* datep = dateBuff + 12;
|
||||||
|
dateBuff[17] = '\0';
|
||||||
|
|
||||||
|
// DateStamp is defined in BS EN 1545 - Days passed since 01/01/1997
|
||||||
|
uint32_t dateStamp = (int)strtol(datep, NULL, 16);
|
||||||
|
uint32_t unixTimestamp = dateStamp * 24 * 60 * 60 + 852076800U;
|
||||||
|
|
||||||
|
furi_string_set(parsed_data, "\e#ITSO Card\n");
|
||||||
|
|
||||||
|
// Digit count in each space-separated group
|
||||||
|
static const uint8_t digit_count[] = {6, 4, 4, 4};
|
||||||
|
|
||||||
|
for(uint32_t i = 0, k = 0; i < COUNT_OF(digit_count); k += digit_count[i++]) {
|
||||||
|
for(uint32_t j = 0; j < digit_count[i]; ++j) {
|
||||||
|
furi_string_push_back(parsed_data, cardp[j + k]);
|
||||||
|
}
|
||||||
|
furi_string_push_back(parsed_data, ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
FuriHalRtcDateTime timestamp = {0};
|
||||||
|
furi_hal_rtc_timestamp_to_datetime(unixTimestamp, ×tamp);
|
||||||
|
FuriString* timestamp_str = furi_string_alloc();
|
||||||
|
locale_format_date(timestamp_str, ×tamp, locale_get_date_format(), "-");
|
||||||
|
|
||||||
|
furi_string_cat(parsed_data, "\nExpiry: ");
|
||||||
|
furi_string_cat(parsed_data, timestamp_str);
|
||||||
|
|
||||||
|
furi_string_free(timestamp_str);
|
||||||
|
|
||||||
|
parsed = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Actual implementation of app<>plugin interface */
|
||||||
|
static const NfcSupportedCardsPlugin itso_plugin = {
|
||||||
|
.protocol = NfcProtocolMfDesfire,
|
||||||
|
.verify = NULL,
|
||||||
|
.read = NULL,
|
||||||
|
.parse = itso_parse,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Plugin descriptor to comply with basic plugin specification */
|
||||||
|
static const FlipperAppPluginDescriptor itso_plugin_descriptor = {
|
||||||
|
.appid = NFC_SUPPORTED_CARD_PLUGIN_APP_ID,
|
||||||
|
.ep_api_version = NFC_SUPPORTED_CARD_PLUGIN_API_VERSION,
|
||||||
|
.entry_point = &itso_plugin,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Plugin entry point - must return a pointer to const descriptor */
|
||||||
|
const FlipperAppPluginDescriptor* itso_plugin_ep() {
|
||||||
|
return &itso_plugin_descriptor;
|
||||||
|
}
|
|
@ -28,8 +28,11 @@ bool nfc_scene_retry_confirm_on_event(void* context, SceneManagerEvent event) {
|
||||||
if(event.event == DialogExResultRight) {
|
if(event.event == DialogExResultRight) {
|
||||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||||
} else if(event.event == DialogExResultLeft) {
|
} else if(event.event == DialogExResultLeft) {
|
||||||
if(scene_manager_has_previous_scene(
|
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicDictAttack)) {
|
||||||
nfc->scene_manager, NfcSceneMfUltralightUnlockWarn)) {
|
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||||
|
nfc->scene_manager, NfcSceneMfClassicDictAttack);
|
||||||
|
} else if(scene_manager_has_previous_scene(
|
||||||
|
nfc->scene_manager, NfcSceneMfUltralightUnlockWarn)) {
|
||||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||||
nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);
|
nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);
|
||||||
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneDetect)) {
|
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneDetect)) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue