1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
17 //-----------------------------------------------------------------------------
21 #include "commonutil.h" // ARRAYLEN
28 #include <mbedtls/asn1.h>
29 #include "mbedtls/bignum.h" // big num
30 #include <mbedtls/oid.h>
31 #include "emv/emv_tags.h"
32 #include "emv/emvjson.h"
34 #include "proxmark3.h"
35 #include "fileutils.h"
43 ASN1_TAG_OCTET_STRING
,
58 static const struct asn1_tag asn1_tags
[] = {
60 { 0x00, "elem", ASN1_TAG_GENERIC
}, // PRIMITIVE
61 { 0x20, "CONSTRUCTED", ASN1_TAG_GENERIC
}, // CONSTRUCTED, the sequence has multiple elements
62 { 0x80, "CONTEXT SPECIFIC", ASN1_TAG_GENERIC
},
65 { 0x01, "BOOLEAN", ASN1_TAG_BOOLEAN
},
66 { 0x02, "INTEGER", ASN1_TAG_INTEGER
},
67 { 0x03, "BIT STRING", ASN1_TAG_BIT_STRING
},
68 { 0x04, "OCTET STRING", ASN1_TAG_OCTET_STRING
},
69 { 0x05, "NULL", ASN1_TAG_GENERIC
},
70 { 0x06, "OBJECT IDENTIFIER", ASN1_TAG_OBJECT_ID
},
71 { 0x07, "OBJECT DESCRIPTOR", ASN1_TAG_GENERIC
},
72 { 0x08, "EXTERNAL", ASN1_TAG_GENERIC
},
73 { 0x09, "REAL", ASN1_TAG_GENERIC
},
74 { 0x0A, "ENUMERATED", ASN1_TAG_GENERIC
},
75 { 0x0B, "EMBEDDED_PDV", ASN1_TAG_GENERIC
},
76 { 0x0C, "UTF8String", ASN1_TAG_STRING
},
77 { 0x10, "SEQUENCE", ASN1_TAG_GENERIC
},
78 { 0x11, "SET", ASN1_TAG_GENERIC
},
79 { 0x12, "NumericString", ASN1_TAG_STRING
},
80 { 0x13, "PrintableString", ASN1_TAG_STRING
},
81 { 0x14, "T61String", ASN1_TAG_GENERIC
},
82 { 0x15, "VideotexString", ASN1_TAG_GENERIC
},
83 { 0x16, "IA5String", ASN1_TAG_GENERIC
},
84 { 0x17, "UTCTime", ASN1_TAG_UTC_TIME
},
85 { 0x18, "GeneralizedTime", ASN1_TAG_STR_TIME
},
86 { 0x19, "GraphicString", ASN1_TAG_GENERIC
},
87 { 0x1A, "VisibleString", ASN1_TAG_STRING
},
88 { 0x1B, "GeneralString", ASN1_TAG_STRING
},
89 { 0x1C, "UniversalString", ASN1_TAG_STRING
},
90 { 0x1E, "BMPString", ASN1_TAG_GENERIC
},
91 { 0x30, "SEQUENCE", ASN1_TAG_GENERIC
},
92 { 0x31, "SET", ASN1_TAG_GENERIC
},
93 { 0xa0, "[0]", ASN1_TAG_GENERIC
},
94 { 0xa1, "[1]", ASN1_TAG_GENERIC
},
95 { 0xa2, "[2]", ASN1_TAG_GENERIC
},
96 { 0xa3, "[3]", ASN1_TAG_GENERIC
},
97 { 0xa4, "[4]", ASN1_TAG_GENERIC
},
98 { 0xa5, "[5]", ASN1_TAG_GENERIC
},
101 static int asn1_sort_tag(tlv_tag_t tag
) {
102 return (int)(tag
>= 0x100 ? tag
: tag
<< 8);
105 static int asn1_tlv_compare(const void *a
, const void *b
) {
106 const struct tlv
*tlv
= a
;
107 const struct asn1_tag
*tag
= b
;
109 return asn1_sort_tag(tlv
->tag
) - (asn1_sort_tag(tag
->tag
));
112 static const struct asn1_tag
*asn1_get_tag(const struct tlv
*tlv
) {
113 struct asn1_tag
*tag
= bsearch(tlv
, asn1_tags
, ARRAYLEN(asn1_tags
), sizeof(asn1_tags
[0]), asn1_tlv_compare
);
114 return tag
? tag
: &asn1_tags
[0];
117 static void asn1_tag_dump_str_time(const struct tlv
*tlv
, const struct asn1_tag
*tag
, int level
, bool longyear
, bool *needdump
) {
121 int startidx
= longyear
? 4 : 2;
124 PrintAndLogEx(NORMAL
, " value: '" NOLF
);
128 if (longyear
== false) {
129 int short_year
= (tlv
->value
[0] - '0') * 10 + (tlv
->value
[1] - '0');
130 if (short_year
>= 0 && short_year
<= 99) {
131 if (short_year
> 50) {
132 PrintAndLogEx(NORMAL
, "19" NOLF
);
134 PrintAndLogEx(NORMAL
, "20" NOLF
);
139 PrintAndLogEx(NORMAL
, "%.*s-" NOLF
, startidx
, tlv
->value
);
140 if (len
< startidx
+ 2)
144 PrintAndLogEx(NORMAL
, "%.*s-" NOLF
, 2, tlv
->value
+ startidx
);
145 if (len
< startidx
+ 4)
149 PrintAndLogEx(NORMAL
, "%.*s " NOLF
, 2, tlv
->value
+ startidx
+ 2);
150 if (len
< startidx
+ 6)
154 PrintAndLogEx(NORMAL
, "%.*s:" NOLF
, 2, tlv
->value
+ startidx
+ 4);
155 if (len
< startidx
+ 8)
159 PrintAndLogEx(NORMAL
, "%.*s:" NOLF
, 2, tlv
->value
+ startidx
+ 6);
160 if (len
< startidx
+ 10)
164 PrintAndLogEx(NORMAL
, "%.*s" NOLF
, 2, tlv
->value
+ startidx
+ 8);
165 if (len
< startidx
+ 12)
169 PrintAndLogEx(NORMAL
, " zone: UTC %.*s" NOLF
, len
- startidx
- 10, tlv
->value
+ startidx
+ 10);
172 PrintAndLogEx(NORMAL
, "'");
174 PrintAndLogEx(NORMAL
, "");
179 static void asn1_tag_dump_string(const struct tlv
*tlv
, const struct asn1_tag
*tag
, int level
) {
180 PrintAndLogEx(NORMAL
, " value: '" _GREEN_("%.*s") "' hex: '%s'", (int)tlv
->len
, tlv
->value
, sprint_hex(tlv
->value
, tlv
->len
));
183 static void asn1_tag_dump_bitstring(const struct tlv
*tlv
, const struct asn1_tag
*tag
, int level
) {
185 size_t len
= tlv
->len
;
186 size_t n
= (len
* 8);
189 if (tlv
->value
[0] == 0) {
195 uint8_t *d
= calloc(n
, sizeof(uint8_t));
201 bytes_to_bytebits(tlv
->value
+ 1, len
, d
);
203 bytes_to_bytebits(tlv
->value
, len
, d
);
206 PrintAndLogEx(NORMAL
, " (%zu bit)", n
);
207 PrintAndLogEx(INFO
, "%*s" NOLF
, 1 + (level
* 4), "");
209 for (int i
= 0; i
< n
; i
++) {
218 PrintAndLogEx(NORMAL
, "%c" NOLF
, c
);
220 if (((i
+ 1) % 64) == 0) {
221 PrintAndLogEx(NORMAL
, "");
222 PrintAndLogEx(INFO
, "%*s" NOLF
, 1 + (level
* 4), "");
228 PrintAndLogEx(NORMAL
, "");
231 static void asn1_tag_dump_hex(const struct tlv
*tlv
, const struct asn1_tag
*tag
, int level
) {
232 PrintAndLogEx(NORMAL
, " value: '%s'", sprint_hex_inrow(tlv
->value
, tlv
->len
));
235 static void asn1_tag_dump_octet_string(const struct tlv
*tlv
, const struct asn1_tag
*tag
, int level
) {
237 for (size_t i = 0; i < tlv->len; i++) {
238 if (!isspace(tlv->value[i]) && !isprint(tlv->value[i])) {
244 PrintAndLogEx(NORMAL
, " " NOLF
);
245 asn1_tag_dump_string(tlv
, tag
, level
);
248 static void asn1_tag_dump_boolean(const struct tlv
*tlv
, const struct asn1_tag
*tag
, int level
) {
249 PrintAndLogEx(NORMAL
, "%*s" NOLF
, (level
* 4), " ");
251 PrintAndLogEx(NORMAL
, " value: %s", tlv
->value
[0] ? "true" : "false");
253 PrintAndLogEx(NORMAL
, "n/a");
257 static void asn1_tag_dump_integer(const struct tlv
*tlv
, const struct asn1_tag
*tag
, int level
) {
259 size_t n
= (tlv
->len
* 2);
260 char *hex
= calloc(n
+ 1, sizeof(uint8_t));
265 hex_to_buffer((uint8_t *)hex
, tlv
->value
, tlv
->len
, tlv
->len
, 0, 0, false);
267 // results for MPI actions
270 // container of big number
272 mbedtls_mpi_init(&N
);
274 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N
, 16, hex
));
278 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(&N
, 10, s
, sizeof(s
), &slen
));
280 PrintAndLogEx(NORMAL
, "%*s value: %s", (level
), "", s
);
284 mbedtls_mpi_free(&N
);
288 static char *asn1_oid_description(const char *oid
, bool with_group_desc
) {
291 static char res
[300];
292 memset(res
, 0x00, sizeof(res
));
295 if (searchFile(&path
, RESOURCES_SUBDIR
, "oids", ".json", false) != PM3_SUCCESS
) {
300 root
= json_load_file(path
, 0, &error
);
303 if (!root
|| !json_is_object(root
)) {
307 json_t
*elm
= json_object_get(root
, oid
);
312 if (JsonLoadStr(elm
, "$.d", res
))
315 char strext
[300] = {0};
316 if (!JsonLoadStr(elm
, "$.c", strext
)) {
331 static void asn1_tag_dump_object_id(const struct tlv
*tlv
, const struct asn1_tag
*tag
, int level
) {
333 mbedtls_asn1_buf asn1_buf
;
334 asn1_buf
.len
= tlv
->len
;
335 asn1_buf
.p
= (uint8_t *)tlv
->value
;
337 mbedtls_oid_get_numeric_string(pstr
, sizeof(pstr
), &asn1_buf
);
339 PrintAndLogEx(NORMAL
, "%*s %s" NOLF
, (level
), " ", pstr
);
341 char *jsondesc
= asn1_oid_description(pstr
, true);
343 PrintAndLogEx(NORMAL
, " - %s" NOLF
, jsondesc
);
345 const char *ppstr
= NULL
;
346 mbedtls_oid_get_attr_short_name(&asn1_buf
, &ppstr
);
347 if (ppstr
&& str_nlen(ppstr
, 1)) {
348 PrintAndLogEx(NORMAL
, " (%s)", ppstr
);
351 mbedtls_oid_get_sig_alg_desc(&asn1_buf
, &ppstr
);
352 if (ppstr
&& str_nlen(ppstr
, 1)) {
353 PrintAndLogEx(NORMAL
, " (%s)", ppstr
);
356 mbedtls_oid_get_extended_key_usage(&asn1_buf
, &ppstr
);
357 if (ppstr
&& str_nlen(ppstr
, 1)) {
358 PrintAndLogEx(NORMAL
, " (%s)", ppstr
);
362 PrintAndLogEx(NORMAL
, "");
365 bool asn1_tag_dump(const struct tlv
*tlv
, int level
, bool *candump
) {
367 PrintAndLogEx(FAILED
, "NULL\n");
371 const struct asn1_tag
*tag
= asn1_get_tag(tlv
);
374 if ((tlv->tag & 0x20) == 0x20 ) {
375 } else if ((tlv->tag & 0x80) == 0x80 ) {
381 "%*s-- %02X [%02zX] '"_YELLOW_("%s") "'" NOLF
390 case ASN1_TAG_GENERIC
:
391 PrintAndLogEx(NORMAL
, "");
392 // maybe print number of elements?
394 case ASN1_TAG_STRING
:
395 asn1_tag_dump_string(tlv
, tag
, level
);
398 case ASN1_TAG_OCTET_STRING
:
399 asn1_tag_dump_octet_string(tlv
, tag
, level
);
402 case ASN1_TAG_BOOLEAN
:
403 asn1_tag_dump_boolean(tlv
, tag
, level
);
406 case ASN1_TAG_INTEGER
:
407 asn1_tag_dump_integer(tlv
, tag
, level
);
410 case ASN1_TAG_UTC_TIME
:
411 asn1_tag_dump_str_time(tlv
, tag
, level
, false, candump
);
413 case ASN1_TAG_STR_TIME
:
414 asn1_tag_dump_str_time(tlv
, tag
, level
, true, candump
);
416 case ASN1_TAG_OBJECT_ID
:
417 asn1_tag_dump_object_id(tlv
, tag
, level
);
421 asn1_tag_dump_hex(tlv
, tag
, level
);
424 case ASN1_TAG_BIT_STRING
:
425 asn1_tag_dump_bitstring(tlv
, tag
, level
);