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

Add com reading and asn1 parsing

Eric Betts 9 месяцев назад
Родитель
Сommit
7238894af2

+ 9 - 0
eMRTD.asn1

@@ -2,9 +2,18 @@ Passport DEFINITIONS ::=
 BEGIN
 
 MRZ ::= VisibleString
+LDSVersion ::= VisibleString
+UnicodeVersion ::= VisibleString
+DataGroups ::= OCTET STRING
 
 DG1 ::= [APPLICATION 1] IMPLICIT SEQUENCE {
   mrz [APPLICATION 31] IMPLICIT MRZ
 }
 
+COM ::= [APPLICATION 0] IMPLICIT SEQUENCE {
+  ldsVersion [APPLICATION 1] IMPLICIT LDSVersion,
+  unicodeVersion [APPLICATION 54] IMPLICIT UnicodeVersion,
+  dataGroups [APPLICATION 28] IMPLICIT DataGroups
+}
+
 END

+ 71 - 0
lib/asn1/COM.c

@@ -0,0 +1,71 @@
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "Passport"
+ * 	found in "eMRTD.asn1"
+ * 	`asn1c -D ./lib/asn1 -no-gen-example -pdu=all`
+ */
+
+#include "COM.h"
+
+static asn_TYPE_member_t asn_MBR_COM_1[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct COM, ldsVersion),
+		(ASN_TAG_CLASS_APPLICATION | (1 << 2)),
+		-1,	/* IMPLICIT tag at current level */
+		&asn_DEF_LDSVersion,
+		0,
+		{ 0, 0, 0 },
+		0, 0, /* No default value */
+		"ldsVersion"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct COM, unicodeVersion),
+		(ASN_TAG_CLASS_APPLICATION | (54 << 2)),
+		-1,	/* IMPLICIT tag at current level */
+		&asn_DEF_UnicodeVersion,
+		0,
+		{ 0, 0, 0 },
+		0, 0, /* No default value */
+		"unicodeVersion"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct COM, dataGroups),
+		(ASN_TAG_CLASS_APPLICATION | (28 << 2)),
+		-1,	/* IMPLICIT tag at current level */
+		&asn_DEF_DataGroups,
+		0,
+		{ 0, 0, 0 },
+		0, 0, /* No default value */
+		"dataGroups"
+		},
+};
+static const ber_tlv_tag_t asn_DEF_COM_tags_1[] = {
+	(ASN_TAG_CLASS_APPLICATION | (0 << 2)),
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static const asn_TYPE_tag2member_t asn_MAP_COM_tag2el_1[] = {
+    { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 0, 0, 0 }, /* ldsVersion */
+    { (ASN_TAG_CLASS_APPLICATION | (28 << 2)), 2, 0, 0 }, /* dataGroups */
+    { (ASN_TAG_CLASS_APPLICATION | (54 << 2)), 1, 0, 0 } /* unicodeVersion */
+};
+static asn_SEQUENCE_specifics_t asn_SPC_COM_specs_1 = {
+	sizeof(struct COM),
+	offsetof(struct COM, _asn_ctx),
+	asn_MAP_COM_tag2el_1,
+	3,	/* Count of tags in the map */
+	0, 0, 0,	/* Optional elements (not needed) */
+	-1,	/* First extension addition */
+};
+asn_TYPE_descriptor_t asn_DEF_COM = {
+	"COM",
+	"COM",
+	&asn_OP_SEQUENCE,
+	asn_DEF_COM_tags_1,
+	sizeof(asn_DEF_COM_tags_1)
+		/sizeof(asn_DEF_COM_tags_1[0]) - 1, /* 1 */
+	asn_DEF_COM_tags_1,	/* Same as above */
+	sizeof(asn_DEF_COM_tags_1)
+		/sizeof(asn_DEF_COM_tags_1[0]), /* 2 */
+	{ 0, 0, SEQUENCE_constraint },
+	asn_MBR_COM_1,
+	3,	/* Elements count */
+	&asn_SPC_COM_specs_1	/* Additional specs */
+};
+

+ 42 - 0
lib/asn1/COM.h

@@ -0,0 +1,42 @@
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "Passport"
+ * 	found in "eMRTD.asn1"
+ * 	`asn1c -D ./lib/asn1 -no-gen-example -pdu=all`
+ */
+
+#ifndef	_COM_H_
+#define	_COM_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include "LDSVersion.h"
+#include "UnicodeVersion.h"
+#include "DataGroups.h"
+#include <constr_SEQUENCE.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* COM */
+typedef struct COM {
+	LDSVersion_t	 ldsVersion;
+	UnicodeVersion_t	 unicodeVersion;
+	DataGroups_t	 dataGroups;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} COM_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_COM;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _COM_H_ */
+#include <asn_internal.h>

+ 31 - 0
lib/asn1/DataGroups.c

@@ -0,0 +1,31 @@
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "Passport"
+ * 	found in "eMRTD.asn1"
+ * 	`asn1c -D ./lib/asn1 -no-gen-example -pdu=all`
+ */
+
+#include "DataGroups.h"
+
+/*
+ * This type is implemented using OCTET_STRING,
+ * so here we adjust the DEF accordingly.
+ */
+static const ber_tlv_tag_t asn_DEF_DataGroups_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
+};
+asn_TYPE_descriptor_t asn_DEF_DataGroups = {
+	"DataGroups",
+	"DataGroups",
+	&asn_OP_OCTET_STRING,
+	asn_DEF_DataGroups_tags_1,
+	sizeof(asn_DEF_DataGroups_tags_1)
+		/sizeof(asn_DEF_DataGroups_tags_1[0]), /* 1 */
+	asn_DEF_DataGroups_tags_1,	/* Same as above */
+	sizeof(asn_DEF_DataGroups_tags_1)
+		/sizeof(asn_DEF_DataGroups_tags_1[0]), /* 1 */
+	{ 0, 0, OCTET_STRING_constraint },
+	0, 0,	/* No members */
+	&asn_SPC_OCTET_STRING_specs	/* Additional specs */
+};
+

+ 43 - 0
lib/asn1/DataGroups.h

@@ -0,0 +1,43 @@
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "Passport"
+ * 	found in "eMRTD.asn1"
+ * 	`asn1c -D ./lib/asn1 -no-gen-example -pdu=all`
+ */
+
+#ifndef	_DataGroups_H_
+#define	_DataGroups_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <OCTET_STRING.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* DataGroups */
+typedef OCTET_STRING_t	 DataGroups_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_DataGroups;
+asn_struct_free_f DataGroups_free;
+asn_struct_print_f DataGroups_print;
+asn_constr_check_f DataGroups_constraint;
+ber_type_decoder_f DataGroups_decode_ber;
+der_type_encoder_f DataGroups_encode_der;
+xer_type_decoder_f DataGroups_decode_xer;
+xer_type_encoder_f DataGroups_encode_xer;
+oer_type_decoder_f DataGroups_decode_oer;
+oer_type_encoder_f DataGroups_encode_oer;
+per_type_decoder_f DataGroups_decode_uper;
+per_type_encoder_f DataGroups_encode_uper;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _DataGroups_H_ */
+#include <asn_internal.h>

+ 36 - 0
lib/asn1/LDSVersion.c

@@ -0,0 +1,36 @@
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "Passport"
+ * 	found in "eMRTD.asn1"
+ * 	`asn1c -D ./lib/asn1 -no-gen-example -pdu=all`
+ */
+
+#include "LDSVersion.h"
+
+/*
+ * This type is implemented using VisibleString,
+ * so here we adjust the DEF accordingly.
+ */
+asn_per_constraints_t asn_PER_type_LDSVersion_constr_1 CC_NOTUSED = {
+	{ APC_CONSTRAINED,	 7,  7,  32,  126 }	/* (32..126) */,
+	{ APC_SEMI_CONSTRAINED,	-1, -1,  0,  0 }	/* (SIZE(0..MAX)) */,
+	0, 0	/* No PER character map necessary */
+};
+static const ber_tlv_tag_t asn_DEF_LDSVersion_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (26 << 2))
+};
+asn_TYPE_descriptor_t asn_DEF_LDSVersion = {
+	"LDSVersion",
+	"LDSVersion",
+	&asn_OP_VisibleString,
+	asn_DEF_LDSVersion_tags_1,
+	sizeof(asn_DEF_LDSVersion_tags_1)
+		/sizeof(asn_DEF_LDSVersion_tags_1[0]), /* 1 */
+	asn_DEF_LDSVersion_tags_1,	/* Same as above */
+	sizeof(asn_DEF_LDSVersion_tags_1)
+		/sizeof(asn_DEF_LDSVersion_tags_1[0]), /* 1 */
+	{ 0, &asn_PER_type_LDSVersion_constr_1, VisibleString_constraint },
+	0, 0,	/* No members */
+	0	/* No specifics */
+};
+

+ 44 - 0
lib/asn1/LDSVersion.h

@@ -0,0 +1,44 @@
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "Passport"
+ * 	found in "eMRTD.asn1"
+ * 	`asn1c -D ./lib/asn1 -no-gen-example -pdu=all`
+ */
+
+#ifndef	_LDSVersion_H_
+#define	_LDSVersion_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <VisibleString.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* LDSVersion */
+typedef VisibleString_t	 LDSVersion_t;
+
+/* Implementation */
+extern asn_per_constraints_t asn_PER_type_LDSVersion_constr_1;
+extern asn_TYPE_descriptor_t asn_DEF_LDSVersion;
+asn_struct_free_f LDSVersion_free;
+asn_struct_print_f LDSVersion_print;
+asn_constr_check_f LDSVersion_constraint;
+ber_type_decoder_f LDSVersion_decode_ber;
+der_type_encoder_f LDSVersion_encode_der;
+xer_type_decoder_f LDSVersion_decode_xer;
+xer_type_encoder_f LDSVersion_encode_xer;
+oer_type_decoder_f LDSVersion_decode_oer;
+oer_type_encoder_f LDSVersion_encode_oer;
+per_type_decoder_f LDSVersion_decode_uper;
+per_type_encoder_f LDSVersion_encode_uper;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _LDSVersion_H_ */
+#include <asn_internal.h>

+ 10 - 2
lib/asn1/Makefile.am.libasncodec

@@ -1,10 +1,18 @@
 ASN_MODULE_SRCS=	\
 	./lib/asn1/MRZ.c	\
-	./lib/asn1/DG1.c
+	./lib/asn1/LDSVersion.c	\
+	./lib/asn1/UnicodeVersion.c	\
+	./lib/asn1/DataGroups.c	\
+	./lib/asn1/DG1.c	\
+	./lib/asn1/COM.c
 
 ASN_MODULE_HDRS=	\
 	./lib/asn1/MRZ.h	\
-	./lib/asn1/DG1.h
+	./lib/asn1/LDSVersion.h	\
+	./lib/asn1/UnicodeVersion.h	\
+	./lib/asn1/DataGroups.h	\
+	./lib/asn1/DG1.h	\
+	./lib/asn1/COM.h
 
 ASN_MODULE_HDRS+=./lib/asn1/OPEN_TYPE.h
 ASN_MODULE_SRCS+=./lib/asn1/OPEN_TYPE.c

+ 36 - 0
lib/asn1/UnicodeVersion.c

@@ -0,0 +1,36 @@
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "Passport"
+ * 	found in "eMRTD.asn1"
+ * 	`asn1c -D ./lib/asn1 -no-gen-example -pdu=all`
+ */
+
+#include "UnicodeVersion.h"
+
+/*
+ * This type is implemented using VisibleString,
+ * so here we adjust the DEF accordingly.
+ */
+asn_per_constraints_t asn_PER_type_UnicodeVersion_constr_1 CC_NOTUSED = {
+	{ APC_CONSTRAINED,	 7,  7,  32,  126 }	/* (32..126) */,
+	{ APC_SEMI_CONSTRAINED,	-1, -1,  0,  0 }	/* (SIZE(0..MAX)) */,
+	0, 0	/* No PER character map necessary */
+};
+static const ber_tlv_tag_t asn_DEF_UnicodeVersion_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (26 << 2))
+};
+asn_TYPE_descriptor_t asn_DEF_UnicodeVersion = {
+	"UnicodeVersion",
+	"UnicodeVersion",
+	&asn_OP_VisibleString,
+	asn_DEF_UnicodeVersion_tags_1,
+	sizeof(asn_DEF_UnicodeVersion_tags_1)
+		/sizeof(asn_DEF_UnicodeVersion_tags_1[0]), /* 1 */
+	asn_DEF_UnicodeVersion_tags_1,	/* Same as above */
+	sizeof(asn_DEF_UnicodeVersion_tags_1)
+		/sizeof(asn_DEF_UnicodeVersion_tags_1[0]), /* 1 */
+	{ 0, &asn_PER_type_UnicodeVersion_constr_1, VisibleString_constraint },
+	0, 0,	/* No members */
+	0	/* No specifics */
+};
+

+ 44 - 0
lib/asn1/UnicodeVersion.h

@@ -0,0 +1,44 @@
+/*
+ * Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
+ * From ASN.1 module "Passport"
+ * 	found in "eMRTD.asn1"
+ * 	`asn1c -D ./lib/asn1 -no-gen-example -pdu=all`
+ */
+
+#ifndef	_UnicodeVersion_H_
+#define	_UnicodeVersion_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <VisibleString.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* UnicodeVersion */
+typedef VisibleString_t	 UnicodeVersion_t;
+
+/* Implementation */
+extern asn_per_constraints_t asn_PER_type_UnicodeVersion_constr_1;
+extern asn_TYPE_descriptor_t asn_DEF_UnicodeVersion;
+asn_struct_free_f UnicodeVersion_free;
+asn_struct_print_f UnicodeVersion_print;
+asn_constr_check_f UnicodeVersion_constraint;
+ber_type_decoder_f UnicodeVersion_decode_ber;
+der_type_encoder_f UnicodeVersion_encode_der;
+xer_type_decoder_f UnicodeVersion_decode_xer;
+xer_type_encoder_f UnicodeVersion_encode_xer;
+oer_type_decoder_f UnicodeVersion_decode_oer;
+oer_type_encoder_f UnicodeVersion_encode_oer;
+per_type_decoder_f UnicodeVersion_decode_uper;
+per_type_encoder_f UnicodeVersion_encode_uper;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _UnicodeVersion_H_ */
+#include <asn_internal.h>

+ 67 - 1
passy_reader.c

@@ -4,6 +4,9 @@
 #define PASSY_READER_DG1_CHUNK_SIZE 0x20
 #define PASSY_READER_DG2_CHUNK_SIZE 0x20
 
+#define ASN_EMIT_DEBUG 0
+#include <lib/asn1/COM.h>
+
 static uint8_t passport_aid[] = {0xA0, 0x00, 0x00, 0x02, 0x47, 0x10, 0x01};
 static uint8_t select_header[] = {0x00, 0xA4, 0x04, 0x0C};
 
@@ -313,7 +316,70 @@ NfcCommand passy_reader_state_machine(PassyReader* passy_reader) {
             break;
         }
 
-        if(passy->read_type == PassyReadDG1) {
+        if(passy->read_type == PassyReadCOM) {
+            uint8_t header[4];
+            ret = passy_reader_read_binary(passy_reader, 0x00, sizeof(header), header);
+            if(ret != NfcCommandContinue) {
+                view_dispatcher_send_custom_event(
+                    passy->view_dispatcher, PassyCustomEventReaderError);
+
+                break;
+            }
+            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));
+            do {
+                view_dispatcher_send_custom_event(
+                    passy->view_dispatcher, PassyCustomEventReaderReading);
+                uint8_t chunk[PASSY_READER_DG1_CHUNK_SIZE];
+                uint8_t Le = MIN(sizeof(chunk), (size_t)(body_size - body_offset));
+
+                ret = passy_reader_read_binary(passy_reader, body_offset, Le, chunk);
+                if(ret != NfcCommandContinue) {
+                    view_dispatcher_send_custom_event(
+                        passy->view_dispatcher, PassyCustomEventReaderError);
+                    break;
+                }
+                bit_buffer_append_bytes(com_buffer, 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];
             ret = passy_reader_read_binary(passy_reader, 0x00, sizeof(header), header);

+ 10 - 0
scenes/passy_scene_main_menu.c

@@ -38,6 +38,12 @@ void passy_scene_main_menu_on_enter(void* context) {
             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",
@@ -73,6 +79,10 @@ 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);