MX 1 год назад
Родитель
Сommit
6538283631

+ 13 - 11
application.fam

@@ -7,25 +7,27 @@ App(
     entry_point="seader_app",
     cdefines=["APP_SEADER"],
     requires=[
-        "gui", "storage", "nfc",
+        "gui",
+        "storage",
+        "nfc",
     ],
     stack_size=5 * 1024,
     order=20,
     sources=[
-      "*.c",
-      "aeabi_uldivmod.sx",
-      "!plugin/*.c",
+        "*.c",
+        "aeabi_uldivmod.sx",
+        "!plugin/*.c",
     ],
     fap_icon="icons/logo.png",
     fap_category="NFC",
-    fap_version="2.10",
+    fap_version="3.1",
     fap_author="bettse",
-#    fap_extbuild=(
-#        ExtFile(
-#            path="${FAP_SRC_DIR}/lib/asn1/asn_system.h",
-#            command="asn1c -D ${FAP_SRC_DIR}/lib/asn1 -no-gen-example -pdu=all ${FAP_SRC_DIR}/seader.asn1"
-#        ),
-#    ),
+    #    fap_extbuild=(
+    #        ExtFile(
+    #            path="${FAP_SRC_DIR}/lib/asn1/asn_system.h",
+    #            command="asn1c -D ${FAP_SRC_DIR}/lib/asn1 -no-gen-example -pdu=all ${FAP_SRC_DIR}/seader.asn1"
+    #        ),
+    #    ),
     fap_libs=["mbedtls"],
     fap_private_libs=[
         Lib(

+ 1 - 1
lib/asn1/asn_internal.h

@@ -42,7 +42,7 @@ int get_asn1c_environment_version(void);	/* Run-time version */
  * You may enable or override it.
  */
 #ifndef	ASN_DEBUG	/* If debugging code is not defined elsewhere... */
-#if defined(ASN_EMIT_DEBUG) && ASN_EMIT_DEBUG == 1	/* And it was asked to emit this code... */
+#if	defined(ASN_EMIT_DEBUG) && ASN_EMIT_DEBUG == 1	/* And it was asked to emit this code... */
 #if __STDC_VERSION__ >= 199901L
 #ifdef	ASN_THREAD_SAFE
 /* Thread safety requires sacrifice in output indentation:

+ 1 - 1
plugin/interface.h

@@ -10,7 +10,7 @@
 #include <stddef.h>
 #include <furi.h>
 
-#define PLUGIN_APP_ID "plugin_wiegand"
+#define PLUGIN_APP_ID      "plugin_wiegand"
 #define PLUGIN_API_VERSION 1
 
 typedef struct {

+ 17 - 0
readme.md

@@ -7,6 +7,21 @@ A [Flipper Zero](https://flipperzero.one/) application (aka "fap") to interface
 
 File issues in [GitHub](https://github.com/bettse/seader/issues).
 
+
+## Formats
+
+Seader can save from the Source(top) formats to the Destination(left) formats.
+
+| | Seos | Desfire Ev2 | Desfire Ev1 | MFC SE | MFC (legacy) | iClass SE | iClass SR | iClass (legacy) |
+| ----------- | ---- | ----------- | ----------- | ------ | ------------ | --------- | --------- | --------------- |
+| Seader (no SIO) | x | x | x | x | x | x | x | x |
+| LFRFID | x | x | x | x | x | x | x | x |
+| iClass (legacy) | X | x | x | X | X | x | x | X |
+| MFC (legacy) | X | x | x | X | X | x | x | X |
+| Seader (with SIO) | | x | x | | | x | x | |
+| iClass SR (emulation only) | | x | x | | | x | x | |
+
+
 ## Hardware
 
 ### Option 1: NARD flipper add-on
@@ -58,3 +73,5 @@ Optionally 3d print a [case designed by sean](https://www.printables.com/model/5
 - `arm-none-eabi-nm ~/.ufbt/build/seader.fap -CS --size-sort`
 - `arm-none-eabi-readelf ~/.ufbt/build/seader.fap -t`
 - `ufbt cli` -> `free_blocks`
+
+

+ 14 - 2
sam_api.c

@@ -1,20 +1,23 @@
-
 #include "sam_api.h"
 #include <toolbox/path.h>
 #include <toolbox/version.h>
 #include <bit_lib/bit_lib.h>
 
+//#define ASN1_DEBUG                      true
+
 #define TAG "SAMAPI"
 
 #define ASN1_PREFIX                     6
-#define ASN1_DEBUG                      true
 #define SEADER_ICLASS_SR_SIO_BASE_BLOCK 10
 #define SEADER_SERIAL_FILE_NAME         "sam_serial"
 
 const uint8_t picopass_iclass_key[] = {0xaf, 0xa7, 0x85, 0xa7, 0xda, 0xb3, 0x33, 0x78};
 
 static char display[SEADER_UART_RX_BUF_SIZE * 2 + 1] = {0};
+
+#ifdef ASN1_DEBUG
 char asn1_log[SEADER_UART_RX_BUF_SIZE] = {0};
+#endif
 
 uint8_t read4Block6[] = {RFAL_PICOPASS_CMD_READ4, 0x06, 0x45, 0x56};
 uint8_t read4Block9[] = {RFAL_PICOPASS_CMD_READ4, 0x09, 0xB2, 0xAE};
@@ -195,6 +198,7 @@ bool seader_send_apdu(
     return true;
 }
 
+#ifdef ASN1_DEBUG
 static int seader_print_struct_callback(const void* buffer, size_t size, void* app_key) {
     if(app_key) {
         char* str = (char*)app_key;
@@ -206,6 +210,14 @@ static int seader_print_struct_callback(const void* buffer, size_t size, void* a
     }
     return 0;
 }
+#else
+static int seader_print_struct_callback(const void* buffer, size_t size, void* app_key) {
+    UNUSED(buffer);
+    UNUSED(size);
+    UNUSED(app_key);
+    return 0;
+}
+#endif
 
 void seader_send_payload(
     Seader* seader,

+ 1 - 19
scenes/seader_scene_card_menu.c

@@ -1,7 +1,6 @@
 #include "../seader_i.h"
 
 enum SubmenuIndex {
-    SubmenuIndexParse,
     SubmenuIndexSave,
     SubmenuIndexSavePicopass,
     SubmenuIndexSaveRFID,
@@ -18,21 +17,8 @@ void seader_scene_card_menu_submenu_callback(void* context, uint32_t index) {
 void seader_scene_card_menu_on_enter(void* context) {
     Seader* seader = context;
     SeaderCredential* credential = seader->credential;
-    PluginWiegand* plugin = seader->plugin_wiegand;
     Submenu* submenu = seader->submenu;
 
-    if(plugin) {
-        size_t format_count = plugin->count(credential->bit_length, credential->credential);
-        if(format_count > 0) {
-            submenu_add_item(
-                submenu,
-                "Parse",
-                SubmenuIndexParse,
-                seader_scene_card_menu_submenu_callback,
-                seader);
-        }
-    }
-
     submenu_add_item(
         submenu, "Save", SubmenuIndexSave, seader_scene_card_menu_submenu_callback, seader);
     submenu_add_item(
@@ -73,6 +59,7 @@ bool seader_scene_card_menu_on_event(void* context, SceneManagerEvent event) {
         if(event.event == SubmenuIndexSave) {
             scene_manager_set_scene_state(
                 seader->scene_manager, SeaderSceneCardMenu, SubmenuIndexSave);
+            seader->credential->save_format = SeaderCredentialSaveFormatAgnostic;
             scene_manager_next_scene(seader->scene_manager, SeaderSceneSaveName);
             consumed = true;
         } else if(event.event == SubmenuIndexSavePicopass) {
@@ -99,11 +86,6 @@ bool seader_scene_card_menu_on_event(void* context, SceneManagerEvent event) {
             seader->credential->save_format = SeaderCredentialSaveFormatMFC;
             scene_manager_next_scene(seader->scene_manager, SeaderSceneSaveName);
             consumed = true;
-        } else if(event.event == SubmenuIndexParse) {
-            scene_manager_set_scene_state(
-                seader->scene_manager, SeaderSceneCardMenu, SubmenuIndexParse);
-            scene_manager_next_scene(seader->scene_manager, SeaderSceneFormats);
-            consumed = true;
         }
     } else if(event.type == SceneManagerEventTypeBack) {
         consumed = scene_manager_search_and_switch_to_previous_scene(

+ 16 - 0
scenes/seader_scene_read_card_success.c

@@ -16,6 +16,7 @@ void seader_scene_read_card_success_widget_callback(
 void seader_scene_read_card_success_on_enter(void* context) {
     Seader* seader = context;
     SeaderCredential* credential = seader->credential;
+    PluginWiegand* plugin = seader->plugin_wiegand;
     Widget* widget = seader->widget;
 
     FuriString* type_str = furi_string_alloc();
@@ -58,6 +59,18 @@ void seader_scene_read_card_success_on_enter(void* context) {
     widget_add_button_element(
         widget, GuiButtonTypeRight, "More", seader_scene_read_card_success_widget_callback, seader);
 
+    if(plugin) {
+        size_t format_count = plugin->count(credential->bit_length, credential->credential);
+        if(format_count > 0) {
+            widget_add_button_element(
+                seader->widget,
+                GuiButtonTypeCenter,
+                "Parse",
+                seader_scene_read_card_success_widget_callback,
+                seader);
+        }
+    }
+
     widget_add_string_element(
         widget, 64, 5, AlignCenter, AlignCenter, FontPrimary, furi_string_get_cstr(type_str));
     widget_add_string_element(
@@ -100,6 +113,9 @@ bool seader_scene_read_card_success_on_event(void* context, SceneManagerEvent ev
         } else if(event.event == GuiButtonTypeRight) {
             scene_manager_next_scene(seader->scene_manager, SeaderSceneCardMenu);
             consumed = true;
+        } else if(event.event == GuiButtonTypeCenter) {
+            scene_manager_next_scene(seader->scene_manager, SeaderSceneFormats);
+            consumed = true;
         }
     } else if(event.type == SceneManagerEventTypeBack) {
         scene_manager_search_and_switch_to_previous_scene(

+ 12 - 20
seader_credential.c

@@ -12,6 +12,7 @@
 
 static const char* seader_file_header = "Flipper Seader Credential";
 static const uint32_t seader_file_version = 1;
+extern const uint8_t picopass_iclass_key[];
 
 SeaderCredential* seader_credential_alloc() {
     SeaderCredential* seader_dev = malloc(sizeof(SeaderCredential));
@@ -197,7 +198,6 @@ bool seader_credential_save_mfc(SeaderCredential* cred, const char* name) {
     uint8_t empty_block[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
     uint8_t pacs_block[16] = {0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
-    bool use_load_path = true;
     bool saved = false;
     FlipperFormat* file = flipper_format_file_alloc(cred->storage);
     FuriString* temp_str;
@@ -208,15 +208,8 @@ bool seader_credential_save_mfc(SeaderCredential* cred, const char* name) {
     memcpy(pacs_block + 8, &swapped, sizeof(swapped));
 
     do {
-        if(use_load_path && !furi_string_empty(cred->load_path)) {
-            // Get directory name
-            path_extract_dirname(furi_string_get_cstr(cred->load_path), temp_str);
-            // Make path to file to save
-            furi_string_cat_printf(temp_str, "/%s%s", name, SEADER_APP_MFC_EXTENSION);
-        } else {
-            furi_string_printf(
-                temp_str, "%s/%s%s", SEADER_APP_MFC_FOLDER, name, SEADER_APP_MFC_EXTENSION);
-        }
+        furi_string_printf(
+            temp_str, "%s/%s%s", SEADER_APP_MFC_FOLDER, name, SEADER_APP_MFC_EXTENSION);
 
         FURI_LOG_D(TAG, "Save as MFC [%s]", furi_string_get_cstr(temp_str));
 
@@ -354,6 +347,9 @@ bool seader_credential_save_agnostic(SeaderCredential* cred, const char* name) {
             furi_string_printf(
                 temp_str, "%s/%s%s", STORAGE_APP_DATA_PATH_PREFIX, name, SEADER_APP_EXTENSION);
         }
+
+        FURI_LOG_D(TAG, "Save as Seader [%s]", furi_string_get_cstr(temp_str));
+
         // Open file
         if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break;
 
@@ -391,21 +387,17 @@ bool seader_credential_save_picopass(SeaderCredential* cred, const char* name) {
     uint8_t aia[PICOPASS_BLOCK_LEN] = {0xFF, 0xff, 0xff, 0xff, 0xFF, 0xFf, 0xff, 0xFF};
     uint8_t pacs_cfg[PICOPASS_BLOCK_LEN] = {0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0xe0, 0x14};
 
-    bool use_load_path = true;
     bool saved = false;
     bool withSIO = cred->save_format == SeaderCredentialSaveFormatSR;
+    if(withSIO) {
+        loclass_iclass_calc_div_key(cred->diversifier, picopass_iclass_key, debit_key, false);
+    }
+
     FlipperFormat* file = flipper_format_file_alloc(cred->storage);
     FuriString* temp_str = furi_string_alloc();
 
     storage_simply_mkdir(cred->storage, EXT_PATH("apps_data/picopass"));
-    if(use_load_path && !furi_string_empty(cred->load_path)) {
-        // Get directory name
-        path_extract_dirname(furi_string_get_cstr(cred->load_path), temp_str);
-        // Make path to file to save
-        furi_string_cat_printf(temp_str, "/%s%s", name, ".picopass");
-    } else {
-        furi_string_printf(temp_str, "%s/%s%s", EXT_PATH("apps_data/picopass"), name, ".picopass");
-    }
+    furi_string_printf(temp_str, "%s/%s%s", EXT_PATH("apps_data/picopass"), name, ".picopass");
 
     FURI_LOG_D(TAG, "Save as Picopass [%s]", furi_string_get_cstr(temp_str));
     uint64_t sentinel = 1ULL << cred->bit_length;
@@ -529,7 +521,7 @@ bool seader_credential_save_picopass(SeaderCredential* cred, const char* name) {
 bool seader_credential_save_rfid(SeaderCredential* cred, const char* name) {
     bool result = false;
     FuriString* file_path = furi_string_alloc();
-    furi_string_printf(file_path, "%s/%s%s", ANY_PATH("lfrfid"), name, ".rfid");
+    furi_string_printf(file_path, "%s/%s%s", EXT_PATH("lfrfid"), name, ".rfid");
     ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
     ProtocolId protocol = LFRFIDProtocolHidGeneric;
 

+ 3 - 1
seader_credential.h

@@ -5,11 +5,13 @@
 #include <storage/storage.h>
 #include <dialogs/dialogs.h>
 #include "protocol/picopass_protocol.h"
+#include <optimized_ikeys.h>
+#include <optimized_cipher.h>
 
 #define SEADER_CRED_NAME_MAX_LEN 22
 #define SEADER_APP_EXTENSION     ".credential"
 #define SEADER_APP_MFC_EXTENSION ".nfc"
-#define SEADER_APP_MFC_FOLDER    ANY_PATH("nfc")
+#define SEADER_APP_MFC_FOLDER    EXT_PATH("nfc")
 
 typedef void (*SeaderLoadingCallback)(void* context, bool state);
 

+ 1 - 0
seader_i.h

@@ -1,4 +1,5 @@
 #pragma once
+#define ASN_EMIT_DEBUG 0
 
 #include <stdlib.h> // malloc
 #include <stdint.h> // uint32_t

+ 1 - 0
seader_worker_i.h

@@ -1,4 +1,5 @@
 #pragma once
+#define ASN_EMIT_DEBUG 0
 
 #include "seader_i.h"
 #include "seader_worker.h"