MX 1 год назад
Родитель
Сommit
4cdff7d56a
7 измененных файлов с 204 добавлено и 9 удалено
  1. 31 0
      lib/asn1/NoArguments.c
  2. 43 0
      lib/asn1/NoArguments.h
  3. 14 4
      lib/asn1/SamCommand.c
  4. 5 2
      lib/asn1/SamCommand.h
  5. 1 1
      readme.md
  6. 107 1
      sam_api.c
  7. 3 1
      seader.asn1

+ 31 - 0
lib/asn1/NoArguments.c

@@ -0,0 +1,31 @@
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "Seader"
+ * 	found in "seader.asn1"
+ * 	`asn1c -D ./lib/asn1 -no-gen-example -pdu=all`
+ */
+
+#include "NoArguments.h"
+
+/*
+ * This type is implemented using NULL,
+ * so here we adjust the DEF accordingly.
+ */
+static const ber_tlv_tag_t asn_DEF_NoArguments_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (5 << 2))
+};
+asn_TYPE_descriptor_t asn_DEF_NoArguments = {
+	"NoArguments",
+	"NoArguments",
+	&asn_OP_NULL,
+	asn_DEF_NoArguments_tags_1,
+	sizeof(asn_DEF_NoArguments_tags_1)
+		/sizeof(asn_DEF_NoArguments_tags_1[0]), /* 1 */
+	asn_DEF_NoArguments_tags_1,	/* Same as above */
+	sizeof(asn_DEF_NoArguments_tags_1)
+		/sizeof(asn_DEF_NoArguments_tags_1[0]), /* 1 */
+	{ 0, 0, NULL_constraint },
+	0, 0,	/* No members */
+	0	/* No specifics */
+};
+

+ 43 - 0
lib/asn1/NoArguments.h

@@ -0,0 +1,43 @@
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "Seader"
+ * 	found in "seader.asn1"
+ * 	`asn1c -D ./lib/asn1 -no-gen-example -pdu=all`
+ */
+
+#ifndef	_NoArguments_H_
+#define	_NoArguments_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <NULL.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NoArguments */
+typedef NULL_t	 NoArguments_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_NoArguments;
+asn_struct_free_f NoArguments_free;
+asn_struct_print_f NoArguments_print;
+asn_constr_check_f NoArguments_constraint;
+ber_type_decoder_f NoArguments_decode_ber;
+der_type_encoder_f NoArguments_encode_der;
+xer_type_decoder_f NoArguments_decode_xer;
+xer_type_encoder_f NoArguments_encode_xer;
+oer_type_decoder_f NoArguments_decode_oer;
+oer_type_encoder_f NoArguments_encode_oer;
+per_type_decoder_f NoArguments_decode_uper;
+per_type_encoder_f NoArguments_encode_uper;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _NoArguments_H_ */
+#include <asn_internal.h>

+ 14 - 4
lib/asn1/SamCommand.c

@@ -11,7 +11,7 @@ static asn_oer_constraints_t asn_OER_type_SamCommand_constr_1 CC_NOTUSED = {
 	{ 0, 0 },
 	-1};
 asn_per_constraints_t asn_PER_type_SamCommand_constr_1 CC_NOTUSED = {
-	{ APC_CONSTRAINED,	 2,  2,  0,  2 }	/* (0..2) */,
+	{ APC_CONSTRAINED,	 2,  2,  0,  3 }	/* (0..3) */,
 	{ APC_UNCONSTRAINED,	-1, -1,  0,  0 },
 	0, 0	/* No PER value map */
 };
@@ -43,11 +43,21 @@ asn_TYPE_member_t asn_MBR_SamCommand_1[] = {
 		0, 0, /* No default value */
 		"cardDetected"
 		},
+	{ ATF_NOFLAGS, 0, offsetof(struct SamCommand, choice.serialNumber),
+		(ASN_TAG_CLASS_CONTEXT | (22 << 2)),
+		-1,	/* IMPLICIT tag at current level */
+		&asn_DEF_NoArguments,
+		0,
+		{ 0, 0, 0 },
+		0, 0, /* No default value */
+		"serialNumber"
+		},
 };
 static const asn_TYPE_tag2member_t asn_MAP_SamCommand_tag2el_1[] = {
     { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 0 }, /* requestPacs */
     { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 1, 0, 0 }, /* version */
-    { (ASN_TAG_CLASS_CONTEXT | (13 << 2)), 2, 0, 0 } /* cardDetected */
+    { (ASN_TAG_CLASS_CONTEXT | (13 << 2)), 2, 0, 0 }, /* cardDetected */
+    { (ASN_TAG_CLASS_CONTEXT | (22 << 2)), 3, 0, 0 } /* serialNumber */
 };
 asn_CHOICE_specifics_t asn_SPC_SamCommand_specs_1 = {
 	sizeof(struct SamCommand),
@@ -55,7 +65,7 @@ asn_CHOICE_specifics_t asn_SPC_SamCommand_specs_1 = {
 	offsetof(struct SamCommand, present),
 	sizeof(((struct SamCommand *)0)->present),
 	asn_MAP_SamCommand_tag2el_1,
-	3,	/* Count of tags in the map */
+	4,	/* Count of tags in the map */
 	0, 0,
 	-1	/* Extensions start */
 };
@@ -69,7 +79,7 @@ asn_TYPE_descriptor_t asn_DEF_SamCommand = {
 	0,	/* No tags (count) */
 	{ &asn_OER_type_SamCommand_constr_1, &asn_PER_type_SamCommand_constr_1, CHOICE_constraint },
 	asn_MBR_SamCommand_1,
-	3,	/* Elements count */
+	4,	/* Elements count */
 	&asn_SPC_SamCommand_specs_1	/* Additional specs */
 };
 

+ 5 - 2
lib/asn1/SamCommand.h

@@ -15,6 +15,7 @@
 #include "RequestPacs.h"
 #include <NULL.h>
 #include "CardDetected.h"
+#include "NoArguments.h"
 #include <constr_CHOICE.h>
 
 #ifdef __cplusplus
@@ -26,7 +27,8 @@ typedef enum SamCommand_PR {
 	SamCommand_PR_NOTHING,	/* No components present */
 	SamCommand_PR_requestPacs,
 	SamCommand_PR_version,
-	SamCommand_PR_cardDetected
+	SamCommand_PR_cardDetected,
+	SamCommand_PR_serialNumber
 } SamCommand_PR;
 
 /* SamCommand */
@@ -36,6 +38,7 @@ typedef struct SamCommand {
 		RequestPacs_t	 requestPacs;
 		NULL_t	 version;
 		CardDetected_t	 cardDetected;
+		NoArguments_t	 serialNumber;
 	} choice;
 	
 	/* Context for parsing across buffer boundaries */
@@ -45,7 +48,7 @@ typedef struct SamCommand {
 /* Implementation */
 extern asn_TYPE_descriptor_t asn_DEF_SamCommand;
 extern asn_CHOICE_specifics_t asn_SPC_SamCommand_specs_1;
-extern asn_TYPE_member_t asn_MBR_SamCommand_1[3];
+extern asn_TYPE_member_t asn_MBR_SamCommand_1[4];
 extern asn_per_constraints_t asn_PER_type_SamCommand_constr_1;
 
 #ifdef __cplusplus

+ 1 - 1
readme.md

@@ -19,7 +19,7 @@ Optionally 3d print a [case designed by Antiklesys](https://www.printables.com/m
 
 ### Option 2: Smart Card 2 Click
 
-Put SAM ([USA](https://www.cdw.com/product/hp-sim-for-hid-iclass-for-hip2-reader-security-sim/4854794) [EU](https://www.rfideas-shop.com/en/kt-sim-se-sim-card-hid-iclass-and-seos-for-sphip-r.html) [CA](https://www.pc-canada.com/item/hp-sim-for-hid-iclass-se-and-hid-iclass-seos-for-hip2-reader/y7c07a)) into **[adapter](https://a.co/d/1E9Zk1h)** (because of chip on top) and plug into **[reader](https://www.mikroe.com/smart-card-2-click)**. Connect reader to Flipper Zero (See `Connections` below).
+Put SAM ([USA](https://www.cdw.com/product/hp-sim-for-hid-iclass-for-hip2-reader-security-sim/4854794) [EU](https://www.rfideas-shop.com/en/kt-sim-se-sim-card-hid-iclass-and-seos-for-sphip-r.html) [CA](https://www.pc-canada.com/item/hp-sim-for-hid-iclass-se-and-hid-iclass-seos-for-hip2-reader/y7c07a)) into **[adapter](https://a.co/d/1E9Zk1h)** (because of chip on top) and plug into **[reader](https://www.mikroe.com/smart-card-2-click)** (alt: [digikey](https://www.digikey.com/en/products/detail/mikroelektronika/MIKROE-5492/20840872) with cheaper US shipping). Connect reader to Flipper Zero (See `Connections` below).
 
 Optionally 3d print a [case designed by sean](https://www.printables.com/model/543149-case-for-flipper-zero-devboard-smart2click-samsim)
 

+ 107 - 1
sam_api.c

@@ -1,5 +1,6 @@
 
 #include "sam_api.h"
+#include <toolbox/path.h>
 
 #define TAG "SAMAPI"
 
@@ -7,6 +8,7 @@
 #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};
 
@@ -258,6 +260,27 @@ void sendRequestPacs(SeaderUartBridge* seader_uart) {
     ASN_STRUCT_FREE(asn_DEF_Payload, payload);
 }
 
+void seader_worker_send_serial_number(SeaderWorker* seader_worker) {
+    SeaderUartBridge* seader_uart = seader_worker->uart;
+    SamCommand_t* samCommand = 0;
+    samCommand = calloc(1, sizeof *samCommand);
+    assert(samCommand);
+
+    samCommand->present = SamCommand_PR_serialNumber;
+
+    Payload_t* payload = 0;
+    payload = calloc(1, sizeof *payload);
+    assert(payload);
+
+    payload->present = Payload_PR_samCommand;
+    payload->choice.samCommand = *samCommand;
+
+    seader_send_payload(seader_uart, payload, 0x44, 0x0a, 0x44);
+
+    ASN_STRUCT_FREE(asn_DEF_SamCommand, samCommand);
+    ASN_STRUCT_FREE(asn_DEF_Payload, payload);
+}
+
 void seader_worker_send_version(SeaderWorker* seader_worker) {
     SeaderUartBridge* seader_uart = seader_worker->uart;
     SamCommand_t* samCommand = 0;
@@ -386,7 +409,7 @@ bool seader_parse_version(SeaderWorker* seader_worker, uint8_t* buf, size_t size
             ->op->print_struct(
                 &asn_DEF_SamVersion, version, 1, seader_print_struct_callback, versionDebug);
         if(strlen(versionDebug) > 0) {
-            // FURI_LOG_D(TAG, "Received version: %s", versionDebug);
+            FURI_LOG_D(TAG, "Received version: %s", versionDebug);
         }
         if(version->version.size == 2) {
             memcpy(seader_worker->sam_version, version->version.buf, version->version.size);
@@ -399,6 +422,87 @@ bool seader_parse_version(SeaderWorker* seader_worker, uint8_t* buf, size_t size
     return rtn;
 }
 
+bool seader_sam_save_serial(Seader* seader, uint8_t* buf, size_t size) {
+    SeaderCredential* cred = seader->credential;
+
+    const char* file_header = "SAM Serial Number";
+    const uint32_t file_version = 1;
+    bool use_load_path = true;
+    bool saved = false;
+    FlipperFormat* file = flipper_format_file_alloc(cred->storage);
+    FuriString* temp_str;
+    temp_str = furi_string_alloc();
+
+    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", SEADER_SERIAL_FILE_NAME, ".txt");
+        } else {
+            furi_string_printf(
+                temp_str, "%s/%s%s", STORAGE_APP_DATA_PATH_PREFIX, SEADER_SERIAL_FILE_NAME, ".txt");
+        }
+        // Open file
+        if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break;
+        if(!flipper_format_write_header_cstr(file, file_header, file_version)) break;
+
+        if(!flipper_format_write_hex(file, "Chip Serial Number", buf, size)) break;
+        saved = true;
+    } while(false);
+
+    if(!saved) {
+        dialog_message_show_storage_error(cred->dialogs, "Can not save\nserial file");
+    }
+    furi_string_free(temp_str);
+    flipper_format_free(file);
+    return saved;
+}
+
+bool seader_sam_save_serial_QR(Seader* seader, char* serial) {
+    SeaderCredential* cred = seader->credential;
+
+    const char* file_header = "QRCode";
+    const uint32_t file_version = 0;
+
+    bool saved = false;
+    FlipperFormat* file = flipper_format_file_alloc(cred->storage);
+    FuriString* temp_str;
+    temp_str = furi_string_alloc();
+
+    do {
+        storage_simply_mkdir(cred->storage, EXT_PATH("qrcodes"));
+        furi_string_printf(
+            temp_str, "%s/%s%s", EXT_PATH("qrcodes"), "seader_sam_serial", ".qrcode");
+
+        // Open file
+        if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break;
+        if(!flipper_format_write_header_cstr(file, file_header, file_version)) break;
+
+        if(!flipper_format_write_string_cstr(file, "Message", serial)) break;
+        saved = true;
+    } while(false);
+
+    if(!saved) {
+        dialog_message_show_storage_error(cred->dialogs, "Can not save\nQR file");
+    }
+    furi_string_free(temp_str);
+    flipper_format_free(file);
+    return saved;
+}
+
+bool seader_parse_serial_number(Seader* seader, uint8_t* buf, size_t size) {
+    memset(display, 0, sizeof(display));
+    for(uint8_t i = 0; i < size; i++) {
+        snprintf(display + (i * 2), sizeof(display), "%02x", buf[i]);
+    }
+
+    FURI_LOG_D(TAG, "Received serial: %s", display);
+
+    seader_sam_save_serial_QR(seader, display);
+    return seader_sam_save_serial(seader, buf, size);
+}
+
 bool seader_parse_sam_response(Seader* seader, SamResponse_t* samResponse) {
     SeaderWorker* seader_worker = seader->worker;
     SeaderUartBridge* seader_uart = seader_worker->uart;
@@ -415,6 +519,8 @@ bool seader_parse_sam_response(Seader* seader, SamResponse_t* samResponse) {
                 seader->view_dispatcher, SeaderCustomEventWorkerExit);
         }
     } else if(seader_parse_version(seader_worker, samResponse->buf, samResponse->size)) {
+        seader_worker_send_serial_number(seader_worker);
+    } else if(seader_parse_serial_number(seader, samResponse->buf, samResponse->size)) {
         // no-op
     } else if(seader_unpack_pacs(seader, samResponse->buf, samResponse->size)) {
         view_dispatcher_send_custom_event(seader->view_dispatcher, SeaderCustomEventPollerSuccess);

+ 3 - 1
seader.asn1

@@ -6,6 +6,7 @@ RfStatus ::= OCTET STRING
 SamResponse ::= OCTET STRING
 -- omnikey_5326_dfr_softwaredeveloperguide 4.2
 PAC ::= BIT STRING
+NoArguments ::= NULL
 
 -- omnikey_5326_dfr_softwaredeveloperguide 3.3
 Payload ::= CHOICE {
@@ -23,7 +24,8 @@ ErrorResponse ::= SEQUENCE {
 SamCommand ::= CHOICE {
   requestPacs [1] IMPLICIT RequestPacs,
   version [2] IMPLICIT NULL,
-  cardDetected [13] IMPLICIT CardDetected
+  cardDetected [13] IMPLICIT CardDetected,
+  serialNumber [22] IMPLICIT NoArguments
 }
 
 CardDetected ::= SEQUENCE {