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 //-----------------------------------------------------------------------------
17 #include <mbedtls/asn1.h>
18 #include <mbedtls/oid.h>
19 #include "emv/emv_tags.h"
21 #include "emv/emvjson.h"
23 #include "proxmark3.h"
25 #define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, " ");}
32 ASN1_TAG_OCTET_STRING
,
45 static const struct asn1_tag asn1_tags
[] = {
47 { 0x00 , "Unknown ???" },
50 { 0x01, "BOOLEAN", ASN1_TAG_BOOLEAN
},
51 { 0x02, "INTEGER", ASN1_TAG_INTEGER
},
52 { 0x03, "BIT STRING" },
53 { 0x04, "OCTET STRING", ASN1_TAG_OCTET_STRING
},
55 { 0x06, "OBJECT IDENTIFIER", ASN1_TAG_OBJECT_ID
},
56 { 0x07, "OBJECT DESCRIPTOR" },
59 { 0x0A, "ENUMERATED" },
60 { 0x0B, "EMBEDDED_PDV" },
61 { 0x0C, "UTF8String", ASN1_TAG_STRING
},
64 { 0x12, "NumericString", ASN1_TAG_STRING
},
65 { 0x13, "PrintableString", ASN1_TAG_STRING
},
66 { 0x14, "T61String" },
67 { 0x15, "VideotexString" },
68 { 0x16, "IA5String" },
69 { 0x17, "UTCTime", ASN1_TAG_UTC_TIME
},
70 { 0x18, "GeneralizedTime", ASN1_TAG_STR_TIME
},
71 { 0x19, "GraphicString" },
72 { 0x1A, "VisibleString", ASN1_TAG_STRING
},
73 { 0x1B, "GeneralString", ASN1_TAG_STRING
},
74 { 0x1C, "UniversalString", ASN1_TAG_STRING
},
75 { 0x1E, "BMPString" },
86 static int asn1_sort_tag(tlv_tag_t tag
) {
87 return (int)(tag
>= 0x100 ? tag
: tag
<< 8);
90 static int asn1_tlv_compare(const void *a
, const void *b
) {
91 const struct tlv
*tlv
= a
;
92 const struct asn1_tag
*tag
= b
;
94 return asn1_sort_tag(tlv
->tag
) - (asn1_sort_tag(tag
->tag
));
97 static const struct asn1_tag
*asn1_get_tag(const struct tlv
*tlv
) {
98 struct asn1_tag
*tag
= bsearch(tlv
, asn1_tags
, sizeof(asn1_tags
) / sizeof(asn1_tags
[0]),
99 sizeof(asn1_tags
[0]), asn1_tlv_compare
);
101 return tag
? tag
: &asn1_tags
[0];
104 static void asn1_tag_dump_str_time(const struct tlv
*tlv
, const struct asn1_tag
*tag
, FILE *f
, int level
, bool longyear
, bool *needdump
){
108 int startindx
= longyear
? 4 : 2;
111 fprintf(f
, "\tvalue: '");
116 fwrite(tlv
->value
, 1, longyear
? 4 : 2, f
);
118 if (len
< startindx
+ 2)
121 fwrite(&tlv
->value
[startindx
], 1, 2, f
);
123 if (len
< startindx
+ 4)
126 fwrite(&tlv
->value
[startindx
+ 2], 1, 2, f
);
128 if (len
< startindx
+ 6)
131 fwrite(&tlv
->value
[startindx
+ 4], 1, 2, f
);
133 if (len
< startindx
+ 8)
136 fwrite(&tlv
->value
[startindx
+ 6], 1, 2, f
);
138 if (len
< startindx
+ 10)
141 fwrite(&tlv
->value
[startindx
+ 8], 1, 2, f
);
142 if (len
< startindx
+ 11)
145 fprintf(f
, " zone: %.*s", len
- 10 - (longyear
? 4 : 2), &tlv
->value
[startindx
+ 10]);
156 static void asn1_tag_dump_string(const struct tlv
*tlv
, const struct asn1_tag
*tag
, FILE *f
, int level
){
157 fprintf(f
, "\tvalue: '");
158 fwrite(tlv
->value
, 1, tlv
->len
, f
);
162 static void asn1_tag_dump_octet_string(const struct tlv
*tlv
, const struct asn1_tag
*tag
, FILE *f
, int level
, bool *needdump
){
164 for (int i
= 0; i
< tlv
->len
; i
++)
165 if (!isspace(tlv
->value
[i
]) && !isprint(tlv
->value
[i
])){
174 asn1_tag_dump_string(tlv
, tag
, f
, level
);
178 static unsigned long asn1_value_integer(const struct tlv
*tlv
, unsigned start
, unsigned end
) {
179 unsigned long ret
= 0;
182 if (end
> tlv
->len
* 2)
188 ret
+= tlv
->value
[start
/2] & 0xf;
193 for (; i
< end
- 1; i
+= 2) {
195 ret
+= tlv
->value
[i
/2] >> 4;
197 ret
+= tlv
->value
[i
/2] & 0xf;
202 ret
+= tlv
->value
[end
/2] >> 4;
208 static void asn1_tag_dump_boolean(const struct tlv
*tlv
, const struct asn1_tag
*tag
, FILE *f
, int level
) {
211 fprintf(f
, "\tvalue: %s\n", tlv
->value
[0]?"true":"false");
217 static void asn1_tag_dump_integer(const struct tlv
*tlv
, const struct asn1_tag
*tag
, FILE *f
, int level
) {
221 for (int i
= 0; i
< tlv
->len
; i
++)
222 val
= (val
<< 8) + tlv
->value
[i
];
223 fprintf(f
, "\tvalue4b: %d\n", val
);
226 fprintf(f
, "\tvalue: %lu\n", asn1_value_integer(tlv
, 0, tlv
->len
* 2));
229 static char *asn1_oid_description(const char *oid
, bool with_group_desc
) {
232 char fname
[300] = {0};
233 static char res
[300];
234 memset(res
, 0x00, sizeof(res
));
236 strcpy(fname
, get_my_executable_directory());
237 strcat(fname
, "crypto/oids.json");
238 if (access(fname
, F_OK
) < 0) {
239 strcpy(fname
, get_my_executable_directory());
240 strcat(fname
, "oids.json");
241 if (access(fname
, F_OK
) < 0) {
242 goto error
; // file not found
247 root
= json_load_file(fname
, 0, &error
);
249 if (!root
|| !json_is_object(root
)) {
253 json_t
*elm
= json_object_get(root
, oid
);
258 if (JsonLoadStr(elm
, "$.d", res
))
261 char strext
[300] = {0};
262 if (!JsonLoadStr(elm
, "$.c", strext
)) {
277 static void asn1_tag_dump_object_id(const struct tlv
*tlv
, const struct asn1_tag
*tag
, FILE *f
, int level
) {
279 mbedtls_asn1_buf asn1_buf
;
280 asn1_buf
.len
= tlv
->len
;
281 asn1_buf
.p
= (uint8_t *)tlv
->value
;
283 mbedtls_oid_get_numeric_string(pstr
, sizeof(pstr
), &asn1_buf
);
284 fprintf(f
, " %s", pstr
);
286 char *jsondesc
= asn1_oid_description(pstr
, true);
288 fprintf(f
, " - %s", jsondesc
);
291 mbedtls_oid_get_attr_short_name(&asn1_buf
, &ppstr
);
292 if (ppstr
&& strnlen(ppstr
, 1)) {
293 fprintf(f
, " (%s)\n", ppstr
);
296 mbedtls_oid_get_sig_alg_desc(&asn1_buf
, &ppstr
);
297 if (ppstr
&& strnlen(ppstr
, 1)) {
298 fprintf(f
, " (%s)\n", ppstr
);
301 mbedtls_oid_get_extended_key_usage(&asn1_buf
, &ppstr
);
302 if (ppstr
&& strnlen(ppstr
, 1)) {
303 fprintf(f
, " (%s)\n", ppstr
);
310 bool asn1_tag_dump(const struct tlv
*tlv
, FILE *f
, int level
, bool *candump
) {
312 fprintf(f
, "NULL\n");
316 const struct asn1_tag
*tag
= asn1_get_tag(tlv
);
319 fprintf(f
, "--%2hx[%02zx] '%s':", tlv
->tag
, tlv
->len
, tag
->name
);
322 case ASN1_TAG_GENERIC
:
325 case ASN1_TAG_STRING
:
326 asn1_tag_dump_string(tlv
, tag
, f
, level
);
329 case ASN1_TAG_OCTET_STRING
:
330 asn1_tag_dump_octet_string(tlv
, tag
, f
, level
, candump
);
332 case ASN1_TAG_BOOLEAN
:
333 asn1_tag_dump_boolean(tlv
, tag
, f
, level
);
336 case ASN1_TAG_INTEGER
:
337 asn1_tag_dump_integer(tlv
, tag
, f
, level
);
340 case ASN1_TAG_UTC_TIME
:
341 asn1_tag_dump_str_time(tlv
, tag
, f
, level
, false, candump
);
343 case ASN1_TAG_STR_TIME
:
344 asn1_tag_dump_str_time(tlv
, tag
, f
, level
, true, candump
);
346 case ASN1_TAG_OBJECT_ID
:
347 asn1_tag_dump_object_id(tlv
, tag
, f
, level
);