Просмотр исходного кода

Picopass: Save unknown blocks with ?? (#196)

Co-authored-by: あく <alleteam@gmail.com>
Eric Betts 1 год назад
Родитель
Сommit
97423fc365

+ 70 - 15
picopass_device.c

@@ -5,6 +5,7 @@
 #include <picopass_icons.h>
 
 #include <toolbox/protocols/protocol_dict.h>
+#include <toolbox/hex.h>
 #include <lfrfid/protocols/lfrfid_protocols.h>
 #include <lfrfid/lfrfid_dict_file.h>
 
@@ -15,6 +16,7 @@ static const uint32_t picopass_file_version = 1;
 
 const uint8_t picopass_iclass_decryptionkey[] =
     {0xb4, 0x21, 0x2c, 0xca, 0xb7, 0xed, 0x21, 0x0f, 0x7b, 0x93, 0xd4, 0x59, 0x39, 0xc7, 0xdd, 0x36};
+const char unknown_block[] = "?? ?? ?? ?? ?? ?? ?? ??";
 
 PicopassDevice* picopass_device_alloc() {
     PicopassDevice* picopass_dev = malloc(sizeof(PicopassDevice));
@@ -169,6 +171,7 @@ static bool picopass_device_save_file(
     if(dev->format == PicopassDeviceSaveFormatPartial) {
         // Clear key that may have been set when doing key tests for legacy
         memset(card_data[PICOPASS_SECURE_KD_BLOCK_INDEX].data, 0, PICOPASS_BLOCK_LEN);
+        card_data[PICOPASS_SECURE_KD_BLOCK_INDEX].valid = false;
     }
 
     do {
@@ -203,13 +206,21 @@ static bool picopass_device_save_file(
                                    PICOPASS_MAX_APP_LIMIT;
             for(size_t i = 0; i < app_limit; i++) {
                 furi_string_printf(temp_str, "Block %d", i);
-                if(!flipper_format_write_hex(
-                       file,
-                       furi_string_get_cstr(temp_str),
-                       card_data[i].data,
-                       PICOPASS_BLOCK_LEN)) {
-                    block_saved = false;
-                    break;
+                if(card_data[i].valid) {
+                    if(!flipper_format_write_hex(
+                           file,
+                           furi_string_get_cstr(temp_str),
+                           card_data[i].data,
+                           PICOPASS_BLOCK_LEN)) {
+                        block_saved = false;
+                        break;
+                    }
+                } else {
+                    if(!flipper_format_write_string_cstr(
+                           file, furi_string_get_cstr(temp_str), unknown_block)) {
+                        block_saved = false;
+                        break;
+                    }
                 }
             }
             if(!block_saved) break;
@@ -246,6 +257,19 @@ bool picopass_device_save(PicopassDevice* dev, const char* dev_name) {
     return false;
 }
 
+bool picopass_hex_str_to_uint8(const char* value_str, uint8_t* value) {
+    furi_check(value_str);
+    furi_check(value);
+
+    bool parse_success = false;
+    while(*value_str && value_str[1]) {
+        parse_success = hex_char_to_uint8(*value_str, value_str[1], value++);
+        if(!parse_success) break;
+        value_str += 3;
+    }
+    return parse_success;
+}
+
 static bool picopass_device_load_data(PicopassDevice* dev, FuriString* path, bool show_dialog) {
     bool parsed = false;
     FlipperFormat* file = flipper_format_file_alloc(dev->storage);
@@ -260,26 +284,39 @@ static bool picopass_device_load_data(PicopassDevice* dev, FuriString* path, boo
     }
 
     do {
+        picopass_device_data_clear(&dev->dev_data);
         if(!flipper_format_file_open_existing(file, furi_string_get_cstr(path))) break;
 
         // Read and verify file header
         uint32_t version = 0;
         if(!flipper_format_read_header(file, temp_str, &version)) break;
-        if(furi_string_cmp_str(temp_str, picopass_file_header) ||
+        if(!furi_string_equal_str(temp_str, picopass_file_header) ||
            (version != picopass_file_version)) {
             deprecated_version = true;
             break;
         }
 
+        FuriString* block_str = furi_string_alloc();
         // Parse header blocks
         bool block_read = true;
         for(size_t i = 0; i < 6; i++) {
             furi_string_printf(temp_str, "Block %d", i);
-            if(!flipper_format_read_hex(
-                   file, furi_string_get_cstr(temp_str), card_data[i].data, PICOPASS_BLOCK_LEN)) {
+            if(!flipper_format_read_string(file, furi_string_get_cstr(temp_str), block_str)) {
                 block_read = false;
                 break;
             }
+            if(furi_string_equal_str(block_str, unknown_block)) {
+                FURI_LOG_D(TAG, "Block %i: %s (unknown)", i, furi_string_get_cstr(block_str));
+                card_data[i].valid = false;
+                memset(card_data[i].data, 0, PICOPASS_BLOCK_LEN);
+            } else {
+                FURI_LOG_D(TAG, "Block %i: %s (hex)", i, furi_string_get_cstr(block_str));
+                if(!picopass_hex_str_to_uint8(furi_string_get_cstr(block_str), card_data[i].data)) {
+                    block_read = false;
+                    break;
+                }
+                card_data[i].valid = true;
+            }
         }
 
         size_t app_limit = card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[0];
@@ -287,16 +324,29 @@ static bool picopass_device_load_data(PicopassDevice* dev, FuriString* path, boo
         if(app_limit > PICOPASS_MAX_APP_LIMIT) app_limit = PICOPASS_MAX_APP_LIMIT;
         for(size_t i = 6; i < app_limit; i++) {
             furi_string_printf(temp_str, "Block %d", i);
-            if(!flipper_format_read_hex(
-                   file, furi_string_get_cstr(temp_str), card_data[i].data, PICOPASS_BLOCK_LEN)) {
+            if(!flipper_format_read_string(file, furi_string_get_cstr(temp_str), block_str)) {
                 block_read = false;
                 break;
             }
+            if(furi_string_equal_str(block_str, unknown_block)) {
+                FURI_LOG_D(TAG, "Block %i: %s (unknown)", i, furi_string_get_cstr(block_str));
+                card_data[i].valid = false;
+                memset(card_data[i].data, 0, PICOPASS_BLOCK_LEN);
+            } else {
+                FURI_LOG_D(TAG, "Block %i: %s (hex)", i, furi_string_get_cstr(block_str));
+                if(!picopass_hex_str_to_uint8(furi_string_get_cstr(block_str), card_data[i].data)) {
+                    block_read = false;
+                    break;
+                }
+                card_data[i].valid = true;
+            }
         }
         if(!block_read) break;
 
-        picopass_device_parse_credential(card_data, pacs);
-        picopass_device_parse_wiegand(pacs->credential, pacs);
+        if(card_data[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].valid) {
+            picopass_device_parse_credential(card_data, pacs);
+            picopass_device_parse_wiegand(pacs);
+        }
 
         parsed = true;
     } while(false);
@@ -371,10 +421,14 @@ void picopass_device_data_clear(PicopassDeviceData* dev_data) {
         memset(dev_data->card_data[i].data, 0, sizeof(dev_data->card_data[i].data));
         dev_data->card_data[i].valid = false;
     }
+
+    memset(dev_data->pacs.credential, 0, sizeof(dev_data->pacs.credential));
     dev_data->pacs.legacy = false;
     dev_data->pacs.se_enabled = false;
     dev_data->pacs.elite_kdf = false;
+    dev_data->pacs.sio = false;
     dev_data->pacs.pin_length = 0;
+    dev_data->pacs.bitLength = 0;
 }
 
 bool picopass_device_delete(PicopassDevice* dev, bool use_load_path) {
@@ -450,7 +504,8 @@ void picopass_device_parse_credential(PicopassBlock* card_data, PicopassPacs* pa
     pacs->sio = (card_data[10].data[0] == 0x30); // rough check
 }
 
-void picopass_device_parse_wiegand(uint8_t* credential, PicopassPacs* pacs) {
+void picopass_device_parse_wiegand(PicopassPacs* pacs) {
+    uint8_t* credential = pacs->credential;
     uint32_t* halves = (uint32_t*)credential;
     if(halves[0] == 0) {
         uint8_t leading0s = __builtin_clz(REVERSE_BYTES_U32(halves[1]));

+ 1 - 1
picopass_device.h

@@ -150,5 +150,5 @@ void picopass_device_set_loading_callback(
     void* context);
 
 void picopass_device_parse_credential(PicopassBlock* card_data, PicopassPacs* pacs);
-void picopass_device_parse_wiegand(uint8_t* credential, PicopassPacs* pacs);
+void picopass_device_parse_wiegand(PicopassPacs* pacs);
 bool picopass_device_hid_csn(PicopassDevice* dev);

+ 1 - 1
protocol/picopass_listener.c

@@ -378,7 +378,7 @@ PicopassListenerCommand
         uint8_t rmac[4] = {};
         uint8_t tmac[4] = {};
         const uint8_t* key = instance->data->card_data[instance->key_block_num].data;
-        bool no_key = picopass_is_memset(key, 0x00, PICOPASS_BLOCK_LEN);
+        bool no_key = !instance->data->card_data[instance->key_block_num].valid;
         const uint8_t* rx_data = bit_buffer_get_data(buf);
 
         if(no_key) {

+ 1 - 1
protocol/picopass_poller.c

@@ -463,7 +463,7 @@ NfcCommand picopass_poller_parse_credential_handler(PicopassPoller* instance) {
 NfcCommand picopass_poller_parse_wiegand_handler(PicopassPoller* instance) {
     NfcCommand command = NfcCommandContinue;
 
-    picopass_device_parse_wiegand(instance->data->pacs.credential, &instance->data->pacs);
+    picopass_device_parse_wiegand(&instance->data->pacs);
     instance->state = PicopassPollerStateSuccess;
     return command;
 }

+ 1 - 2
scenes/picopass_scene_card_menu.c

@@ -28,8 +28,7 @@ void picopass_scene_card_menu_on_enter(void* context) {
     bool zero_config = picopass_is_memset(
         card_data[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].data, 0x00, PICOPASS_BLOCK_LEN);
     bool no_credential = picopass_is_memset(pacs->credential, 0x00, sizeof(pacs->credential));
-    bool no_key = picopass_is_memset(
-        card_data[PICOPASS_SECURE_KD_BLOCK_INDEX].data, 0xFF, PICOPASS_BLOCK_LEN);
+    bool no_key = !card_data[PICOPASS_SECURE_KD_BLOCK_INDEX].valid;
 
     if(secured && zero_config) {
         submenu_add_item(

+ 1 - 2
scenes/picopass_scene_device_info.c

@@ -102,8 +102,7 @@ bool picopass_scene_device_info_on_event(void* context, SceneManagerEvent event)
             consumed = true;
         }
     } else if(event.type == SceneManagerEventTypeBack) {
-        view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget);
-        consumed = true;
+        consumed = scene_manager_previous_scene(picopass->scene_manager);
     }
     return consumed;
 }

+ 6 - 2
scenes/picopass_scene_more_info.c

@@ -19,8 +19,12 @@ void picopass_scene_more_info_on_enter(void* context) {
 
     for(size_t i = 0; i < app_limit; i++) {
         for(size_t j = 0; j < PICOPASS_BLOCK_LEN; j += 2) {
-            furi_string_cat_printf(
-                str, "%02X%02X ", card_data[i].data[j], card_data[i].data[j + 1]);
+            if(card_data[i].valid) {
+                furi_string_cat_printf(
+                    str, "%02X%02X ", card_data[i].data[j], card_data[i].data[j + 1]);
+            } else {
+                furi_string_cat_printf(str, "???? ");
+            }
         }
     }
 

+ 1 - 2
scenes/picopass_scene_read_card_success.c

@@ -133,8 +133,7 @@ void picopass_scene_read_card_success_on_enter(void* context) {
             furi_string_cat_printf(credential_str, " +SIO");
         }
 
-        bool no_key = picopass_is_memset(
-            card_data[PICOPASS_SECURE_KD_BLOCK_INDEX].data, 0xFF, PICOPASS_BLOCK_LEN);
+        bool no_key = !card_data[PICOPASS_SECURE_KD_BLOCK_INDEX].valid;
 
         if(no_key) {
             furi_string_cat_printf(key_str, "No Key: used NR-MAC");