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
24 #include "proxmark3.h"
26 #include "fileutils.h"
29 static const ApplicationDataElm_t ApplicationData
[] = {
35 {0x5F24, "ExpirationDate"},
36 {0x5F25, "EffectiveDate"},
37 {0x5F28, "IssuerCountryCode"},
39 {0x50, "ApplicationLabel"},
40 {0x9F08, "VersionNumber"},
41 {0x9F42, "CurrencyCode"},
42 {0x5F2D, "LanguagePreference"},
43 {0x87, "PriorityIndicator"},
44 {0x9F36, "ATC"}, //Application Transaction Counter
46 {0x5F20, "CardholderName"},
52 {0x9F07, "AUC"}, // Application Usage Control
55 {0x9F0D, "IACDefault"},
57 {0x9F0F, "IACOnline"},
59 {0x8F, "CertificationAuthorityPublicKeyIndex"},
60 {0x9F32, "IssuerPublicKeyExponent"},
61 {0x92, "IssuerPublicKeyRemainder"},
62 {0x90, "IssuerPublicKeyCertificate"},
63 {0x9F47, "ICCPublicKeyExponent"},
64 {0x9F46, "ICCPublicKeyCertificate"},
69 const char *GetApplicationDataName(tlv_tag_t tag
) {
70 for (int i
= 0; i
< ARRAYLEN(ApplicationData
); i
++)
71 if (ApplicationData
[i
].Tag
== tag
)
72 return ApplicationData
[i
].Name
;
77 int JsonSaveJsonObject(json_t
*root
, const char *path
, json_t
*value
) {
84 if (json_path_set_new(root
, path
, value
, 0, &error
)) {
85 PrintAndLogEx(ERR
, "ERROR: can't set json path: %s", error
.text
);
91 return json_object_set_new(root
, path
, value
);
95 int JsonSaveInt(json_t
*root
, const char *path
, int value
) {
96 return JsonSaveJsonObject(root
, path
, json_integer(value
));
99 int JsonSaveStr(json_t
*root
, const char *path
, const char *value
) {
100 return JsonSaveJsonObject(root
, path
, json_string(value
));
103 int JsonSaveBoolean(json_t
*root
, const char *path
, bool value
) {
104 return JsonSaveJsonObject(root
, path
, json_boolean(value
));
107 int JsonSaveBufAsHexCompact(json_t
*elm
, const char *path
, uint8_t *data
, size_t datalen
) {
108 char *msg
= sprint_hex_inrow(data
, datalen
);
109 if (msg
&& strlen(msg
) && msg
[strlen(msg
) - 1] == ' ')
110 msg
[strlen(msg
) - 1] = '\0';
112 return JsonSaveStr(elm
, path
, msg
);
115 int JsonSaveBufAsHex(json_t
*elm
, const char *path
, uint8_t *data
, size_t datalen
) {
116 char *msg
= sprint_hex(data
, datalen
);
117 if (msg
&& strlen(msg
) && msg
[strlen(msg
) - 1] == ' ')
118 msg
[strlen(msg
) - 1] = '\0';
120 return JsonSaveStr(elm
, path
, msg
);
123 int JsonSaveHex(json_t
*elm
, const char *path
, uint64_t data
, int datalen
) {
124 uint8_t bdata
[8] = {0};
127 for (uint64_t u
= 0xffffffffffffffff; u
; u
= u
<< 8) {
138 num_to_bytes(data
, len
, bdata
);
140 return JsonSaveBufAsHex(elm
, path
, bdata
, len
);
143 int JsonSaveTLVValue(json_t
*root
, const char *path
, struct tlvdb
*tlvdbelm
) {
144 const struct tlv
*tlvelm
= tlvdb_get_tlv(tlvdbelm
);
146 return JsonSaveBufAsHex(root
, path
, (uint8_t *)tlvelm
->value
, tlvelm
->len
);
151 int JsonSaveTLVElm(json_t
*elm
, const char *path
, struct tlv
*tlvelm
, bool saveName
, bool saveValue
, bool saveAppDataLink
) {
154 if (strlen(path
) < 1 || !tlvelm
)
157 if (path
[0] == '$') {
159 json_t
*obj
= json_path_get(elm
, path
);
163 if (json_is_array(elm
)) {
164 if (json_array_append_new(elm
, obj
)) {
165 PrintAndLogEx(ERR
, "ERROR: can't append array: %s", path
);
169 if (json_path_set(elm
, path
, obj
, 0, &error
)) {
170 PrintAndLogEx(ERR
, "ERROR: can't set json path: %s", error
.text
);
176 if (saveAppDataLink
) {
177 const char *AppDataName
= GetApplicationDataName(tlvelm
->tag
);
179 JsonSaveStr(obj
, "appdata", AppDataName
);
181 const char *name
= emv_get_tag_name(tlvelm
);
182 if (saveName
&& name
&& strlen(name
) > 0 && strncmp(name
, "Unknown", 7))
183 JsonSaveStr(obj
, "name", emv_get_tag_name(tlvelm
));
184 JsonSaveHex(obj
, "tag", tlvelm
->tag
, 0);
186 JsonSaveHex(obj
, "length", tlvelm
->len
, 0);
187 JsonSaveBufAsHex(obj
, "value", (uint8_t *)tlvelm
->value
, tlvelm
->len
);
195 int JsonSaveTLVTreeElm(json_t
*elm
, const char *path
, struct tlvdb
*tlvdbelm
, bool saveName
, bool saveValue
, bool saveAppDataLink
) {
196 return JsonSaveTLVElm(elm
, path
, (struct tlv
*)tlvdb_get_tlv(tlvdbelm
), saveName
, saveValue
, saveAppDataLink
);
199 int JsonSaveTLVTree(json_t
*root
, json_t
*elm
, const char *path
, struct tlvdb
*tlvdbelm
) {
200 struct tlvdb
*tlvp
= tlvdbelm
;
202 const struct tlv
*tlvpelm
= tlvdb_get_tlv(tlvp
);
203 const char *AppDataName
= NULL
;
205 AppDataName
= GetApplicationDataName(tlvpelm
->tag
);
208 char appdatalink
[200] = {0};
209 snprintf(appdatalink
, sizeof(appdatalink
), "$.ApplicationData.%s", AppDataName
);
210 JsonSaveBufAsHex(root
, appdatalink
, (uint8_t *)tlvpelm
->value
, tlvpelm
->len
);
213 json_t
*pelm
= json_path_get(elm
, path
);
214 if (pelm
&& json_is_array(pelm
)) {
215 json_t
*appendelm
= json_object();
216 json_array_append_new(pelm
, appendelm
);
217 JsonSaveTLVTreeElm(appendelm
, "$", tlvp
, !AppDataName
, !tlvdb_elm_get_children(tlvp
), AppDataName
);
220 JsonSaveTLVTreeElm(elm
, path
, tlvp
, !AppDataName
, !tlvdb_elm_get_children(tlvp
), AppDataName
);
221 pelm
= json_path_get(elm
, path
);
224 if (tlvdb_elm_get_children(tlvp
)) {
229 // check children element and add it if not found
230 json_t
*chjson
= json_path_get(pelm
, "$.Childs");
232 json_object_set_new(pelm
, "Childs", json_array());
234 chjson
= json_path_get(pelm
, "$.Childs");
238 if (!json_is_array(chjson
)) {
239 PrintAndLogEx(ERR
, "E->Internal logic error. `$.Childs` is not an array.");
244 JsonSaveTLVTree(root
, chjson
, "$", tlvdb_elm_get_children(tlvp
));
247 tlvp
= tlvdb_elm_get_next(tlvp
);
252 static bool HexToBuffer(const char *errormsg
, const char *hexvalue
, uint8_t *buffer
, size_t maxbufferlen
, size_t *bufferlen
) {
255 switch (param_gethex_to_eol(hexvalue
, 0, buffer
, maxbufferlen
, &buflen
)) {
257 PrintAndLogEx(ERR
, "%s Invalid HEX value.", errormsg
);
260 PrintAndLogEx(ERR
, "%s Hex value too large.", errormsg
);
263 PrintAndLogEx(ERR
, "%s Hex value must have even number of digits.", errormsg
);
267 if (buflen
> maxbufferlen
) {
268 PrintAndLogEx(ERR
, "%s HEX length (%zu) more than %zu", errormsg
, (bufferlen
) ? *bufferlen
: -1, maxbufferlen
);
278 int JsonLoadStr(json_t
*root
, const char *path
, char *value
) {
282 json_t
*jelm
= json_path_get((const json_t
*)root
, path
);
283 if (!jelm
|| !json_is_string(jelm
))
286 const char *strval
= json_string_value(jelm
);
290 memcpy(value
, strval
, strlen(strval
));
295 int JsonLoadBufAsHex(json_t
*elm
, const char *path
, uint8_t *data
, size_t maxbufferlen
, size_t *datalen
) {
299 json_t
*jelm
= json_path_get((const json_t
*)elm
, path
);
300 if (!jelm
|| !json_is_string(jelm
))
303 if (!HexToBuffer("ERROR load", json_string_value(jelm
), data
, maxbufferlen
, datalen
))
309 bool ParamLoadFromJson(struct tlvdb
*tlv
) {
314 PrintAndLogEx(ERR
, "ERROR load params: tlv tree is NULL.");
319 if (searchFile(&path
, RESOURCES_SUBDIR
, "emv_defparams", ".json", false) != PM3_SUCCESS
) {
322 root
= json_load_file(path
, 0, &error
);
325 PrintAndLogEx(ERR
, "Load params: json error on line " _YELLOW_("%d") ": %s", error
.line
, error
.text
);
329 if (!json_is_array(root
)) {
330 PrintAndLogEx(ERR
, "Load params: Invalid json format. root must be array.");
334 PrintAndLogEx(SUCCESS
, "Load params: json(%zu) ( %s )", json_array_size(root
), _GREEN_("ok"));
336 for (int i
= 0; i
< json_array_size(root
); i
++) {
337 json_t
*data
, *jtag
, *jlength
, *jvalue
;
339 data
= json_array_get(root
, i
);
340 if (!json_is_object(data
)) {
341 PrintAndLogEx(ERR
, "Load params: data [%d] is not an object", i
+ 1);
346 jtag
= json_object_get(data
, "tag");
347 if (!json_is_string(jtag
)) {
348 PrintAndLogEx(ERR
, "Load params: data [%d] tag is not a string", i
+ 1);
352 const char *tlvTag
= json_string_value(jtag
);
354 jvalue
= json_object_get(data
, "value");
355 if (!json_is_string(jvalue
)) {
356 PrintAndLogEx(ERR
, "Load params: data [%d] value is not a string", i
+ 1);
360 const char *tlvValue
= json_string_value(jvalue
);
362 jlength
= json_object_get(data
, "length");
363 if (!json_is_number(jlength
)) {
364 PrintAndLogEx(ERR
, "Load params: data [%d] length is not a number", i
+ 1);
369 int tlvLength
= json_integer_value(jlength
);
370 if (tlvLength
> 250) {
371 PrintAndLogEx(ERR
, "Load params: data [%d] length more than 250", i
+ 1);
376 PrintAndLogEx(SUCCESS
, "TLV param: %s[%d]=%s", tlvTag
, tlvLength
, tlvValue
);
377 uint8_t buf
[251] = {0};
380 if (!HexToBuffer("TLV Error type:", tlvTag
, buf
, 4, &buflen
)) {
385 for (int j
= 0; j
< buflen
; j
++) {
386 tag
= (tag
<< 8) | buf
[j
];
389 if (!HexToBuffer("TLV Error value:", tlvValue
, buf
, sizeof(buf
) - 1, &buflen
)) {
394 if (buflen
!= tlvLength
) {
395 PrintAndLogEx(ERR
, "Load params: data [%d] length of HEX must(%zu) be identical to length in TLV param(%d)", i
+ 1, buflen
, tlvLength
);
400 tlvdb_change_or_add_node(tlv
, tag
, tlvLength
, (const unsigned char *)buf
);