Eric Betts 9 месяцев назад
Родитель
Сommit
ef0a925ec9
8 измененных файлов с 169 добавлено и 62 удалено
  1. 2 0
      passy.c
  2. 1 0
      passy_i.h
  3. 4 37
      passy_reader.c
  4. 1 0
      passy_reader.h
  5. 143 0
      scenes/passy_scene_advanced_menu.c
  6. 1 0
      scenes/passy_scene_config.h
  7. 12 24
      scenes/passy_scene_main_menu.c
  8. 5 1
      scenes/passy_scene_read.c

+ 2 - 0
passy.c

@@ -192,6 +192,7 @@ Passy* passy_alloc() {
     passy->load_path = furi_string_alloc();
 
     passy->DG1 = bit_buffer_alloc(PASSY_DG1_MAX_LENGTH);
+    passy->COM = bit_buffer_alloc(PASSY_DG1_MAX_LENGTH);
 
     return passy;
 }
@@ -252,6 +253,7 @@ void passy_free(Passy* passy) {
     furi_record_close(RECORD_DIALOGS);
 
     bit_buffer_free(passy->DG1);
+    bit_buffer_free(passy->COM);
 
     free(passy);
 }

+ 1 - 0
passy_i.h

@@ -88,6 +88,7 @@ struct Passy {
     char date_of_expiry[PASSY_DOE_MAX_LENGTH + 1];
 
     BitBuffer* DG1;
+    BitBuffer* COM;
 
     PassyReadType read_type;
 

+ 4 - 37
passy_reader.c

@@ -47,6 +47,7 @@ PassyReader* passy_reader_alloc(Passy* passy) {
     furi_assert(passy);
     passy_reader->passy = passy;
     passy_reader->DG1 = passy->DG1;
+    passy_reader->COM = passy->COM;
     passy_reader->tx_buffer = bit_buffer_alloc(PASSY_READER_MAX_BUFFER_SIZE);
     passy_reader->rx_buffer = bit_buffer_alloc(PASSY_READER_MAX_BUFFER_SIZE);
 
@@ -317,6 +318,7 @@ NfcCommand passy_reader_state_machine(PassyReader* passy_reader) {
         }
 
         if(passy->read_type == PassyReadCOM) {
+            bit_buffer_reset(passy_reader->COM);
             uint8_t header[4];
             ret = passy_reader_read_binary(passy_reader, 0x00, sizeof(header), header);
             if(ret != NfcCommandContinue) {
@@ -327,9 +329,7 @@ NfcCommand passy_reader_state_machine(PassyReader* passy_reader) {
             }
             size_t body_size = 1 + asn1_length_length(header + 1) + asn1_length(header + 1);
             uint8_t body_offset = sizeof(header);
-
-            BitBuffer* com_buffer = bit_buffer_alloc(body_size);
-            bit_buffer_append_bytes(com_buffer, header, sizeof(header));
+            bit_buffer_append_bytes(passy_reader->COM, header, sizeof(header));
             do {
                 view_dispatcher_send_custom_event(
                     passy->view_dispatcher, PassyCustomEventReaderReading);
@@ -342,43 +342,10 @@ NfcCommand passy_reader_state_machine(PassyReader* passy_reader) {
                         passy->view_dispatcher, PassyCustomEventReaderError);
                     break;
                 }
-                bit_buffer_append_bytes(com_buffer, chunk, Le);
+                bit_buffer_append_bytes(passy_reader->COM, chunk, Le);
                 body_offset += Le;
             } while(body_offset < body_size);
 
-            COM_t* com = 0;
-            com = calloc(1, sizeof *com);
-            assert(com);
-            asn_dec_rval_t rval = asn_decode(
-                0,
-                ATS_DER,
-                &asn_DEF_COM,
-                (void**)&com,
-                bit_buffer_get_data(com_buffer),
-                bit_buffer_get_size_bytes(com_buffer));
-
-            if(rval.code == RC_OK) {
-                FURI_LOG_I(TAG, "ASN.1 decode success");
-
-                char payloadDebug[384] = {0};
-                memset(payloadDebug, 0, sizeof(payloadDebug));
-                (&asn_DEF_COM)
-                    ->op->print_struct(&asn_DEF_COM, com, 1, print_struct_callback, payloadDebug);
-                if(strlen(payloadDebug) > 0) {
-                    FURI_LOG_D(TAG, "COM: %s", payloadDebug);
-                } else {
-                    FURI_LOG_D(TAG, "Received empty Payload");
-                }
-
-            } else {
-                FURI_LOG_E(TAG, "ASN.1 decode failed: %d.  %d consumed", rval.code, rval.consumed);
-                passy_log_bitbuffer(TAG, "COM", com_buffer);
-            }
-
-            bit_buffer_free(com_buffer);
-            free(com);
-            com = 0;
-
         } else if(passy->read_type == PassyReadDG1) {
             bit_buffer_reset(passy->DG1);
             uint8_t header[4];

+ 1 - 0
passy_reader.h

@@ -28,6 +28,7 @@ typedef struct {
     BitBuffer* rx_buffer;
 
     BitBuffer* DG1;
+    BitBuffer* COM;
 
     SecureMessaging* secure_messaging;
 

+ 143 - 0
scenes/passy_scene_advanced_menu.c

@@ -0,0 +1,143 @@
+#include "../passy_i.h"
+
+#define ASN_EMIT_DEBUG 0
+#include <lib/asn1/COM.h>
+
+#define TAG "SceneAdvancedMenu"
+
+static const char* dg_names[] = {
+    "DG3",
+    "DG4",
+    "DG5",
+    "DG6",
+    "DG7",
+    "DG8",
+    "DG9",
+    "DG10",
+    "DG11",
+    "DG12",
+    "DG13",
+    "DG14",
+    "DG15"};
+static const uint8_t dg_ids[] =
+    {0x63, 0x76, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x77, 0x42};
+static const uint16_t dg_file_ids[] = {
+    0x0103,
+    0x0104,
+    0x0105,
+    0x0106,
+    0x0107,
+    0x0108,
+    0x0109,
+    0x010A,
+    0x010B,
+    0x010C,
+    0x010D,
+    0x010E,
+    0x010F};
+enum SubmenuIndex {
+    SubmenuIndexReadDG3 = 0,
+    SubmenuIndexReadDG4,
+    SubmenuIndexReadDG5,
+    SubmenuIndexReadDG6,
+    SubmenuIndexReadDG7,
+    SubmenuIndexReadDG8,
+    SubmenuIndexReadDG9,
+    SubmenuIndexReadDG10,
+    SubmenuIndexReadDG11,
+    SubmenuIndexReadDG12,
+    SubmenuIndexReadDG13,
+    SubmenuIndexReadDG14,
+    SubmenuIndexReadDG15,
+};
+
+void passy_scene_advanced_menu_submenu_callback(void* context, uint32_t index) {
+    Passy* passy = context;
+    view_dispatcher_send_custom_event(passy->view_dispatcher, index);
+}
+
+void passy_scene_advanced_menu_on_enter(void* context) {
+    Passy* passy = context;
+    Submenu* submenu = passy->submenu;
+    submenu_reset(submenu);
+
+    COM_t* com = 0;
+    com = calloc(1, sizeof *com);
+    assert(com);
+    asn_dec_rval_t rval = asn_decode(
+        0,
+        ATS_DER,
+        &asn_DEF_COM,
+        (void**)&com,
+        bit_buffer_get_data(passy->COM),
+        bit_buffer_get_size_bytes(passy->COM));
+
+    if(rval.code == RC_OK) {
+        FURI_LOG_I(TAG, "ASN.1 decode success");
+
+        char payloadDebug[384] = {0};
+        memset(payloadDebug, 0, sizeof(payloadDebug));
+        (&asn_DEF_COM)->op->print_struct(&asn_DEF_COM, com, 1, print_struct_callback, payloadDebug);
+        if(strlen(payloadDebug) > 0) {
+            FURI_LOG_D(TAG, "COM: %s", payloadDebug);
+        } else {
+            FURI_LOG_D(TAG, "Received empty Payload");
+        }
+    } else {
+        FURI_LOG_E(TAG, "ASN.1 decode failed: %d.  %d consumed", rval.code, rval.consumed);
+        passy_log_bitbuffer(TAG, "COM", passy->COM);
+    }
+
+    for(size_t i = 0; i < com->dataGroups.size; i++) {
+        uint8_t value = com->dataGroups.buf[i];
+        int8_t dg_id = -1;
+        for(size_t j = 0; j < sizeof(dg_ids); j++) {
+            if(value == dg_ids[j]) {
+                dg_id = j;
+                break;
+            }
+        }
+
+        if(dg_id == -1) {
+            continue;
+        }
+        FuriString* dg_name = furi_string_alloc();
+        furi_string_printf(dg_name, "Read %s", dg_names[dg_id]);
+        submenu_add_item(
+            submenu,
+            furi_string_get_cstr(dg_name),
+            dg_id, // using the index requires that the enum aligns with the dg_id
+            passy_scene_advanced_menu_submenu_callback,
+            passy);
+        furi_string_free(dg_name);
+    }
+
+    free(com);
+    com = 0;
+
+    view_dispatcher_switch_to_view(passy->view_dispatcher, PassyViewMenu);
+}
+
+bool passy_scene_advanced_menu_on_event(void* context, SceneManagerEvent event) {
+    Passy* passy = context;
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_set_scene_state(passy->scene_manager, PassySceneAdvancedMenu, event.event);
+        passy->read_type = dg_file_ids[event.event];
+        scene_manager_next_scene(passy->scene_manager, PassySceneRead);
+        consumed = true;
+    } else if(event.type == SceneManagerEventTypeBack) {
+        scene_manager_search_and_switch_to_previous_scene(
+            passy->scene_manager, PassySceneMainMenu);
+        consumed = true;
+    }
+
+    return consumed;
+}
+
+void passy_scene_advanced_menu_on_exit(void* context) {
+    Passy* passy = context;
+
+    submenu_reset(passy->submenu);
+}

+ 1 - 0
scenes/passy_scene_config.h

@@ -7,3 +7,4 @@ ADD_SCENE(passy, dob_input, DoBInput)
 ADD_SCENE(passy, doe_input, DoEInput)
 ADD_SCENE(passy, delete, Delete)
 ADD_SCENE(passy, delete_success, DeleteSuccess)
+ADD_SCENE(passy, advanced_menu, AdvancedMenu)

+ 12 - 24
scenes/passy_scene_main_menu.c

@@ -4,11 +4,10 @@
 
 enum SubmenuIndex {
     SubmenuIndexEnterMRZInfo,
-    SubmenuIndexDeleteMRZInfo,
-    SubmenuIndexReadCOM,
     SubmenuIndexReadDG1,
     SubmenuIndexReadDG2,
-    SubmenuIndexReadDG7,
+    SubmenuIndexReadAdvanced,
+    SubmenuIndexDeleteMRZInfo,
 };
 
 void passy_scene_main_menu_submenu_callback(void* context, uint32_t index) {
@@ -31,19 +30,6 @@ void passy_scene_main_menu_on_enter(void* context) {
         passy);
     if(strlen(passy->passport_number) > 0 && strlen(passy->date_of_birth) > 0 &&
        strlen(passy->date_of_expiry) > 0) {
-        submenu_add_item(
-            submenu,
-            "Delete MRZ Info",
-            SubmenuIndexDeleteMRZInfo,
-            passy_scene_main_menu_submenu_callback,
-            passy);
-
-        submenu_add_item(
-            submenu,
-            "Read COM",
-            SubmenuIndexReadCOM,
-            passy_scene_main_menu_submenu_callback,
-            passy);
         submenu_add_item(
             submenu,
             "Read DG1",
@@ -58,8 +44,14 @@ void passy_scene_main_menu_on_enter(void* context) {
             passy);
         submenu_add_item(
             submenu,
-            "Read DG7",
-            SubmenuIndexReadDG7,
+            "Read Advanced",
+            SubmenuIndexReadAdvanced,
+            passy_scene_main_menu_submenu_callback,
+            passy);
+        submenu_add_item(
+            submenu,
+            "Delete MRZ Info",
+            SubmenuIndexDeleteMRZInfo,
             passy_scene_main_menu_submenu_callback,
             passy);
     }
@@ -79,10 +71,6 @@ bool passy_scene_main_menu_on_event(void* context, SceneManagerEvent event) {
         } else if(event.event == SubmenuIndexDeleteMRZInfo) {
             scene_manager_next_scene(passy->scene_manager, PassySceneDelete);
             consumed = true;
-        } else if(event.event == SubmenuIndexReadCOM) {
-            passy->read_type = PassyReadCOM;
-            scene_manager_next_scene(passy->scene_manager, PassySceneRead);
-            consumed = true;
         } else if(event.event == SubmenuIndexReadDG1) {
             passy->read_type = PassyReadDG1;
             scene_manager_next_scene(passy->scene_manager, PassySceneRead);
@@ -91,8 +79,8 @@ bool passy_scene_main_menu_on_event(void* context, SceneManagerEvent event) {
             passy->read_type = PassyReadDG2;
             scene_manager_next_scene(passy->scene_manager, PassySceneRead);
             consumed = true;
-        } else if(event.event == SubmenuIndexReadDG7) {
-            passy->read_type = PassyReadDG7;
+        } else if(event.event == SubmenuIndexReadAdvanced) {
+            passy->read_type = PassyReadCOM;
             scene_manager_next_scene(passy->scene_manager, PassySceneRead);
             consumed = true;
         }

+ 5 - 1
scenes/passy_scene_read.c

@@ -32,7 +32,11 @@ bool passy_scene_read_on_event(void* context, SceneManagerEvent event) {
 
     if(event.type == SceneManagerEventTypeCustom) {
         if(event.event == PassyCustomEventReaderSuccess) {
-            scene_manager_next_scene(passy->scene_manager, PassySceneReadSuccess);
+            if(passy->read_type == PassyReadCOM) {
+                scene_manager_next_scene(passy->scene_manager, PassySceneAdvancedMenu);
+            } else {
+                scene_manager_next_scene(passy->scene_manager, PassySceneReadSuccess);
+            }
             consumed = true;
         } else if(event.event == PassyCustomEventReaderError) {
             passy->last_sw = passy_reader->last_sw;