1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2018 Merlok
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
7 //-----------------------------------------------------------------------------
9 //-----------------------------------------------------------------------------
11 #define _POSIX_C_SOURCE 200809L // need for strnlen()
20 #include <mbedtls/asn1.h>
21 #include <mbedtls/oid.h>
22 #include "emv/emv_tags.h"
24 #include "emv/emvjson.h"
26 #include "proxmark3.h"
28 #define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, " ");}
35 ASN1_TAG_OCTET_STRING
,
48 static const struct asn1_tag asn1_tags
[] = {
50 { 0x00 , "Unknown ???" },
53 { 0x01, "BOOLEAN", ASN1_TAG_BOOLEAN
},
54 { 0x02, "INTEGER", ASN1_TAG_INTEGER
},
55 { 0x03, "BIT STRING" },
56 { 0x04, "OCTET STRING", ASN1_TAG_OCTET_STRING
},
58 { 0x06, "OBJECT IDENTIFIER", ASN1_TAG_OBJECT_ID
},
59 { 0x07, "OBJECT DESCRIPTOR" },
62 { 0x0A, "ENUMERATED" },
63 { 0x0B, "EMBEDDED_PDV" },
64 { 0x0C, "UTF8String", ASN1_TAG_STRING
},
67 { 0x12, "NumericString", ASN1_TAG_STRING
},
68 { 0x13, "PrintableString", ASN1_TAG_STRING
},
69 { 0x14, "T61String" },
70 { 0x15, "VideotexString" },
71 { 0x16, "IA5String" },
72 { 0x17, "UTCTime", ASN1_TAG_UTC_TIME
},
73 { 0x18, "GeneralizedTime", ASN1_TAG_STR_TIME
},
74 { 0x19, "GraphicString" },
75 { 0x1A, "VisibleString", ASN1_TAG_STRING
},
76 { 0x1B, "GeneralString", ASN1_TAG_STRING
},
77 { 0x1C, "UniversalString", ASN1_TAG_STRING
},
78 { 0x1E, "BMPString" },
89 static int asn1_sort_tag(tlv_tag_t tag
) {
90 return (int)(tag
>= 0x100 ? tag
: tag
<< 8);
93 static int asn1_tlv_compare(const void *a
, const void *b
) {
94 const struct tlv
*tlv
= a
;
95 const struct asn1_tag
*tag
= b
;
97 return asn1_sort_tag(tlv
->tag
) - (asn1_sort_tag(tag
->tag
));
100 static const struct asn1_tag
*asn1_get_tag(const struct tlv
*tlv
) {
101 struct asn1_tag
*tag
= bsearch(tlv
, asn1_tags
, sizeof(asn1_tags
) / sizeof(asn1_tags
[0]),
102 sizeof(asn1_tags
[0]), asn1_tlv_compare
);
104 return tag
? tag
: &asn1_tags
[0];
107 static void asn1_tag_dump_str_time(const struct tlv
*tlv
, const struct asn1_tag
*tag
, FILE *f
, int level
, bool longyear
, bool *needdump
){
111 int startindx
= longyear
? 4 : 2;
114 fprintf(f
, "\tvalue: '");
119 fwrite(tlv
->value
, 1, longyear
? 4 : 2, f
);
121 if (len
< startindx
+ 2)
124 fwrite(&tlv
->value
[startindx
], 1, 2, f
);
126 if (len
< startindx
+ 4)
129 fwrite(&tlv
->value
[startindx
+ 2], 1, 2, f
);
131 if (len
< startindx
+ 6)
134 fwrite(&tlv
->value
[startindx
+ 4], 1, 2, f
);
136 if (len
< startindx
+ 8)
139 fwrite(&tlv
->value
[startindx
+ 6], 1, 2, f
);
141 if (len
< startindx
+ 10)
144 fwrite(&tlv
->value
[startindx
+ 8], 1, 2, f
);
145 if (len
< startindx
+ 11)
148 fprintf(f
, " zone: %.*s", len
- 10 - (longyear
? 4 : 2), &tlv
->value
[startindx
+ 10]);
159 static void asn1_tag_dump_string(const struct tlv
*tlv
, const struct asn1_tag
*tag
, FILE *f
, int level
){
160 fprintf(f
, "\tvalue: '");
161 fwrite(tlv
->value
, 1, tlv
->len
, f
);
165 static void asn1_tag_dump_octet_string(const struct tlv
*tlv
, const struct asn1_tag
*tag
, FILE *f
, int level
, bool *needdump
){
167 for (int i
= 0; i
< tlv
->len
; i
++)
168 if (!isspace(tlv
->value
[i
]) && !isprint(tlv
->value
[i
])){
177 asn1_tag_dump_string(tlv
, tag
, f
, level
);
181 static unsigned long asn1_value_integer(const struct tlv
*tlv
, unsigned start
, unsigned end
) {
182 unsigned long ret
= 0;
185 if (end
> tlv
->len
* 2)
191 ret
+= tlv
->value
[start
/2] & 0xf;
196 for (; i
< end
- 1; i
+= 2) {
198 ret
+= tlv
->value
[i
/2] >> 4;
200 ret
+= tlv
->value
[i
/2] & 0xf;
205 ret
+= tlv
->value
[end
/2] >> 4;
211 static void asn1_tag_dump_boolean(const struct tlv
*tlv
, const struct asn1_tag
*tag
, FILE *f
, int level
) {
214 fprintf(f
, "\tvalue: %s\n", tlv
->value
[0]?"true":"false");
220 static void asn1_tag_dump_integer(const struct tlv
*tlv
, const struct asn1_tag
*tag
, FILE *f
, int level
) {
224 for (int i
= 0; i
< tlv
->len
; i
++)
225 val
= (val
<< 8) + tlv
->value
[i
];
226 fprintf(f
, "\tvalue4b: %d\n", val
);
229 fprintf(f
, "\tvalue: %lu\n", asn1_value_integer(tlv
, 0, tlv
->len
* 2));
232 static char *asn1_oid_description(const char *oid
, bool with_group_desc
) {
235 char fname
[300] = {0};
236 static char res
[300];
237 memset(res
, 0x00, sizeof(res
));
239 strcpy(fname
, get_my_executable_directory());
240 strcat(fname
, "crypto/oids.json");
241 if (access(fname
, F_OK
) < 0) {
242 strcpy(fname
, get_my_executable_directory());
243 strcat(fname
, "oids.json");
244 if (access(fname
, F_OK
) < 0) {
245 goto error
; // file not found
250 root
= json_load_file(fname
, 0, &error
);
252 if (!root
|| !json_is_object(root
)) {
256 json_t
*elm
= json_object_get(root
, oid
);
261 if (JsonLoadStr(elm
, "$.d", res
))
264 char strext
[300] = {0};
265 if (!JsonLoadStr(elm
, "$.c", strext
)) {
280 static void asn1_tag_dump_object_id(const struct tlv
*tlv
, const struct asn1_tag
*tag
, FILE *f
, int level
) {
282 mbedtls_asn1_buf asn1_buf
;
283 asn1_buf
.len
= tlv
->len
;
284 asn1_buf
.p
= (uint8_t *)tlv
->value
;
286 mbedtls_oid_get_numeric_string(pstr
, sizeof(pstr
), &asn1_buf
);
287 fprintf(f
, " %s", pstr
);
289 char *jsondesc
= asn1_oid_description(pstr
, true);
291 fprintf(f
, " - %s", jsondesc
);
294 mbedtls_oid_get_attr_short_name(&asn1_buf
, &ppstr
);
295 if (ppstr
&& strnlen(ppstr
, 1)) {
296 fprintf(f
, " (%s)\n", ppstr
);
299 mbedtls_oid_get_sig_alg_desc(&asn1_buf
, &ppstr
);
300 if (ppstr
&& strnlen(ppstr
, 1)) {
301 fprintf(f
, " (%s)\n", ppstr
);
304 mbedtls_oid_get_extended_key_usage(&asn1_buf
, &ppstr
);
305 if (ppstr
&& strnlen(ppstr
, 1)) {
306 fprintf(f
, " (%s)\n", ppstr
);
313 bool asn1_tag_dump(const struct tlv
*tlv
, FILE *f
, int level
, bool *candump
) {
315 fprintf(f
, "NULL\n");
319 const struct asn1_tag
*tag
= asn1_get_tag(tlv
);
322 fprintf(f
, "--%2hx[%02zx] '%s':", tlv
->tag
, tlv
->len
, tag
->name
);
325 case ASN1_TAG_GENERIC
:
328 case ASN1_TAG_STRING
:
329 asn1_tag_dump_string(tlv
, tag
, f
, level
);
332 case ASN1_TAG_OCTET_STRING
:
333 asn1_tag_dump_octet_string(tlv
, tag
, f
, level
, candump
);
335 case ASN1_TAG_BOOLEAN
:
336 asn1_tag_dump_boolean(tlv
, tag
, f
, level
);
339 case ASN1_TAG_INTEGER
:
340 asn1_tag_dump_integer(tlv
, tag
, f
, level
);
343 case ASN1_TAG_UTC_TIME
:
344 asn1_tag_dump_str_time(tlv
, tag
, f
, level
, false, candump
);
346 case ASN1_TAG_STR_TIME
:
347 asn1_tag_dump_str_time(tlv
, tag
, f
, level
, true, candump
);
349 case ASN1_TAG_OBJECT_ID
:
350 asn1_tag_dump_object_id(tlv
, tag
, f
, level
);