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

Look for jpeg header in first 100 bytes of DG2

Eric Betts 9 месяцев назад
Родитель
Сommit
89e36f2e4e
2 измененных файлов с 90 добавлено и 5 удалено
  1. 60 0
      memmem.c
  2. 30 5
      passy_reader.c

+ 60 - 0
memmem.c

@@ -0,0 +1,60 @@
+/* Copyright (C) 1991-2025 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/*
+
+@deftypefn Supplemental void* memmem (const void *@var{haystack}, @
+  size_t @var{haystack_len} const void *@var{needle}, size_t @var{needle_len})
+
+Returns a pointer to the first occurrence of @var{needle} (length
+@var{needle_len}) in @var{haystack} (length @var{haystack_len}).
+Returns @code{NULL} if not found.
+
+@end deftypefn
+
+*/
+
+#include <stddef.h>
+#include <string.h>
+
+#ifndef _LIBC
+#define __builtin_expect(expr, val) (expr)
+#endif
+
+#undef memmem
+
+/* Return the first occurrence of NEEDLE in HAYSTACK.  */
+void* memmem(const void* haystack, size_t haystack_len, const void* needle, size_t needle_len) {
+    const char* begin;
+    const char* const last_possible = (const char*)haystack + haystack_len - needle_len;
+
+    if(needle_len == 0)
+        /* The first occurrence of the empty string is deemed to occur at
+       the beginning of the string.  */
+        return (void*)haystack;
+
+    /* Sanity check, otherwise the loop might search through the whole
+     memory.  */
+    if(__builtin_expect(haystack_len < needle_len, 0)) return NULL;
+
+    for(begin = (const char*)haystack; begin <= last_possible; ++begin)
+        if(begin[0] == ((const char*)needle)[0] &&
+           !memcmp((const void*)&begin[1], (const void*)((const char*)needle + 1), needle_len - 1))
+            return (void*)begin;
+
+    return NULL;
+}

+ 30 - 5
passy_reader.c

@@ -11,6 +11,10 @@ static uint8_t get_challenge[] = {0x00, 0x84, 0x00, 0x00, 0x08};
 
 static uint8_t SW_success[] = {0x90, 0x00};
 
+static const uint8_t jpeg_header[4] = {0xFF, 0xD8, 0xFF, 0xE0};
+static const uint8_t jpeg2k_header[6] = {0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50};
+static const uint8_t jpeg2k_cs_header[4] = {0xFF, 0x4F, 0xFF, 0x51};
+
 size_t asn1_length(uint8_t data[3]) {
     if(data[0] <= 0x7F) {
         return data[0];
@@ -369,7 +373,7 @@ NfcCommand passy_reader_state_machine(Passy* passy, PassyReader* passy_reader) {
         if(passy->read_type == PassyReadDG1) {
             bit_buffer_reset(passy->DG1);
             uint8_t header[4];
-            ret = passy_reader_read_binary(passy_reader, 0x00, 0x04, header);
+            ret = passy_reader_read_binary(passy_reader, 0x00, sizeof(header), header);
             if(ret != NfcCommandContinue) {
                 view_dispatcher_send_custom_event(
                     passy->view_dispatcher, PassyCustomEventReaderError);
@@ -403,8 +407,8 @@ NfcCommand passy_reader_state_machine(Passy* passy, PassyReader* passy_reader) {
                 break;
             }
 
-            uint8_t header[4];
-            ret = passy_reader_read_binary(passy_reader, 0x00, 0x04, header);
+            uint8_t header[100];
+            ret = passy_reader_read_binary(passy_reader, 0x00, sizeof(header), header);
             if(ret != NfcCommandContinue) {
                 view_dispatcher_send_custom_event(
                     passy->view_dispatcher, PassyCustomEventReaderError);
@@ -416,15 +420,36 @@ NfcCommand passy_reader_state_machine(Passy* passy, PassyReader* passy_reader) {
             size_t body_size = asn1_length(header + 1);
             FURI_LOG_I(TAG, "DG2 length: %d", body_size);
 
+            void* jpeg = memmem(header, sizeof(header), jpeg_header, sizeof(jpeg_header));
+            void* jpeg2k = memmem(header, sizeof(header), jpeg2k_header, sizeof(jpeg2k_header));
+            void* jpeg2k_cs =
+                memmem(header, sizeof(header), jpeg2k_cs_header, sizeof(jpeg2k_cs_header));
+
             FuriString* path = furi_string_alloc();
-            furi_string_printf(path, "%s/%s%s", STORAGE_APP_DATA_PATH_PREFIX, "DG2", ".bin");
+            uint8_t start = 0;
+
+            if(jpeg) {
+                furi_string_printf(path, "%s/%s%s", STORAGE_APP_DATA_PATH_PREFIX, "DG2", ".jpeg");
+                start = (uint8_t*)jpeg - header;
+            } else if(jpeg2k) {
+                furi_string_printf(path, "%s/%s%s", STORAGE_APP_DATA_PATH_PREFIX, "DG2", ".jp2");
+                start = (uint8_t*)jpeg2k - header;
+            } else if(jpeg2k_cs) {
+                furi_string_printf(path, "%s/%s%s", STORAGE_APP_DATA_PATH_PREFIX, "DG2", ".jpc");
+                start = (uint8_t*)jpeg2k_cs - header;
+            } else {
+                furi_string_printf(path, "%s/%s%s", STORAGE_APP_DATA_PATH_PREFIX, "DG2", ".bin");
+                start = 0;
+                passy_log_buffer(TAG, "header", header, sizeof(header));
+            }
+            FURI_LOG_I(TAG, "Writing offset %d to %s", start, furi_string_get_cstr(path));
 
             Storage* storage = furi_record_open(RECORD_STORAGE);
             Stream* stream = file_stream_alloc(storage);
             file_stream_open(stream, furi_string_get_cstr(path), FSAM_WRITE, FSOM_OPEN_ALWAYS);
 
             uint8_t chunk[PASSY_READER_DG2_CHUNK_SIZE];
-            size_t body_offset = sizeof(header);
+            size_t body_offset = start;
             size_t chunk_count = (body_size + sizeof(chunk) - 1) / sizeof(chunk);
             size_t i = 0;
             do {