recover_pk.py: replace secp192r1 by prime192v1
[RRG-proxmark3.git] / client / src / emv / emvjson.c
blob448e05ba7b007ddb6a65cb3e8e9fe8e3c4dbddd5
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
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.
8 //
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 //-----------------------------------------------------------------------------
16 // EMV json logic
17 //-----------------------------------------------------------------------------
19 #include "emvjson.h"
20 #include <string.h>
21 #include "commonutil.h" // ARRAYLEN
22 #include "ui.h"
23 #include "util.h"
24 #include "proxmark3.h"
25 #include "emv_tags.h"
26 #include "fileutils.h"
27 #include "pm3_cmd.h"
29 static const ApplicationDataElm_t ApplicationData[] = {
30 {0x82, "AIP"},
31 {0x94, "AFL"},
33 {0x5A, "PAN"},
34 {0x5F34, "PANSeqNo"},
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"},
48 {0x9F38, "PDOL"},
49 {0x8C, "CDOL1"},
50 {0x8D, "CDOL2"},
52 {0x9F07, "AUC"}, // Application Usage Control
53 {0x9F6C, "CTQ"},
54 {0x8E, "CVMList"},
55 {0x9F0D, "IACDefault"},
56 {0x9F0E, "IACDeny"},
57 {0x9F0F, "IACOnline"},
59 {0x8F, "CertificationAuthorityPublicKeyIndex"},
60 {0x9F32, "IssuerPublicKeyExponent"},
61 {0x92, "IssuerPublicKeyRemainder"},
62 {0x90, "IssuerPublicKeyCertificate"},
63 {0x9F47, "ICCPublicKeyExponent"},
64 {0x9F46, "ICCPublicKeyCertificate"},
66 {0x00, "end..."}
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;
74 return NULL;
77 int JsonSaveJsonObject(json_t *root, const char *path, json_t *value) {
78 json_error_t error;
80 if (strlen(path) < 1)
81 return 1;
83 if (path[0] == '$') {
84 if (json_path_set_new(root, path, value, 0, &error)) {
85 PrintAndLogEx(ERR, "ERROR: can't set json path: %s", error.text);
86 return 2;
87 } else {
88 return 0;
90 } else {
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};
125 int len = 0;
126 if (!datalen) {
127 for (uint64_t u = 0xffffffffffffffff; u; u = u << 8) {
128 if (!(data & u)) {
129 break;
131 len++;
133 if (!len)
134 len = 1;
135 } else {
136 len = datalen;
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);
145 if (tlvelm)
146 return JsonSaveBufAsHex(root, path, (uint8_t *)tlvelm->value, tlvelm->len);
147 else
148 return 1;
151 int JsonSaveTLVElm(json_t *elm, const char *path, struct tlv *tlvelm, bool saveName, bool saveValue, bool saveAppDataLink) {
152 json_error_t error;
154 if (strlen(path) < 1 || !tlvelm)
155 return 1;
157 if (path[0] == '$') {
159 json_t *obj = json_path_get(elm, path);
160 if (!obj) {
161 obj = json_object();
163 if (json_is_array(elm)) {
164 if (json_array_append_new(elm, obj)) {
165 PrintAndLogEx(ERR, "ERROR: can't append array: %s", path);
166 return 2;
168 } else {
169 if (json_path_set(elm, path, obj, 0, &error)) {
170 PrintAndLogEx(ERR, "ERROR: can't set json path: %s", error.text);
171 return 2;
176 if (saveAppDataLink) {
177 const char *AppDataName = GetApplicationDataName(tlvelm->tag);
178 if (AppDataName)
179 JsonSaveStr(obj, "appdata", AppDataName);
180 } else {
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);
185 if (saveValue) {
186 JsonSaveHex(obj, "length", tlvelm->len, 0);
187 JsonSaveBufAsHex(obj, "value", (uint8_t *)tlvelm->value, tlvelm->len);
192 return 0;
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;
201 while (tlvp) {
202 const struct tlv *tlvpelm = tlvdb_get_tlv(tlvp);
203 const char *AppDataName = NULL;
204 if (tlvpelm)
205 AppDataName = GetApplicationDataName(tlvpelm->tag);
207 if (AppDataName) {
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);
218 pelm = appendelm;
219 } else {
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)) {
225 // get path element
226 if (!pelm)
227 return 1;
229 // check children element and add it if not found
230 json_t *chjson = json_path_get(pelm, "$.Childs");
231 if (!chjson) {
232 json_object_set_new(pelm, "Childs", json_array());
234 chjson = json_path_get(pelm, "$.Childs");
237 // check
238 if (!json_is_array(chjson)) {
239 PrintAndLogEx(ERR, "E->Internal logic error. `$.Childs` is not an array.");
240 break;
243 // Recursion
244 JsonSaveTLVTree(root, chjson, "$", tlvdb_elm_get_children(tlvp));
247 tlvp = tlvdb_elm_get_next(tlvp);
249 return 0;
252 static bool HexToBuffer(const char *errormsg, const char *hexvalue, uint8_t *buffer, size_t maxbufferlen, size_t *bufferlen) {
253 int buflen = 0;
255 switch (param_gethex_to_eol(hexvalue, 0, buffer, maxbufferlen, &buflen)) {
256 case 1:
257 PrintAndLogEx(ERR, "%s Invalid HEX value.", errormsg);
258 return false;
259 case 2:
260 PrintAndLogEx(ERR, "%s Hex value too large.", errormsg);
261 return false;
262 case 3:
263 PrintAndLogEx(ERR, "%s Hex value must have even number of digits.", errormsg);
264 return false;
267 if (buflen > maxbufferlen) {
268 PrintAndLogEx(ERR, "%s HEX length (%zu) more than %zu", errormsg, (bufferlen) ? *bufferlen : -1, maxbufferlen);
269 return false;
272 if (bufferlen)
273 *bufferlen = buflen;
275 return true;
278 int JsonLoadStr(json_t *root, const char *path, char *value) {
279 if (!value)
280 return 1;
282 json_t *jelm = json_path_get((const json_t *)root, path);
283 if (!jelm || !json_is_string(jelm))
284 return 2;
286 const char *strval = json_string_value(jelm);
287 if (!strval)
288 return 1;
290 memcpy(value, strval, strlen(strval));
292 return 0;
295 int JsonLoadBufAsHex(json_t *elm, const char *path, uint8_t *data, size_t maxbufferlen, size_t *datalen) {
296 if (datalen)
297 *datalen = 0;
299 json_t *jelm = json_path_get((const json_t *)elm, path);
300 if (!jelm || !json_is_string(jelm))
301 return 1;
303 if (!HexToBuffer("ERROR load", json_string_value(jelm), data, maxbufferlen, datalen))
304 return 2;
306 return 0;
309 bool ParamLoadFromJson(struct tlvdb *tlv) {
310 json_t *root;
311 json_error_t error;
313 if (!tlv) {
314 PrintAndLogEx(ERR, "ERROR load params: tlv tree is NULL.");
315 return false;
318 char *path;
319 if (searchFile(&path, RESOURCES_SUBDIR, "emv_defparams", ".json", false) != PM3_SUCCESS) {
320 return false;
322 root = json_load_file(path, 0, &error);
323 free(path);
324 if (!root) {
325 PrintAndLogEx(ERR, "Load params: json error on line " _YELLOW_("%d") ": %s", error.line, error.text);
326 return false;
329 if (!json_is_array(root)) {
330 PrintAndLogEx(ERR, "Load params: Invalid json format. root must be array.");
331 return false;
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);
342 json_decref(root);
343 return false;
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);
349 json_decref(root);
350 return false;
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);
357 json_decref(root);
358 return false;
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);
365 json_decref(root);
366 return false;
369 int tlvLength = json_integer_value(jlength);
370 if (tlvLength > 250) {
371 PrintAndLogEx(ERR, "Load params: data [%d] length more than 250", i + 1);
372 json_decref(root);
373 return false;
376 PrintAndLogEx(SUCCESS, "TLV param: %s[%d]=%s", tlvTag, tlvLength, tlvValue);
377 uint8_t buf[251] = {0};
378 size_t buflen = 0;
380 if (!HexToBuffer("TLV Error type:", tlvTag, buf, 4, &buflen)) {
381 json_decref(root);
382 return false;
384 tlv_tag_t tag = 0;
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)) {
390 json_decref(root);
391 return false;
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);
396 json_decref(root);
397 return false;
400 tlvdb_change_or_add_node(tlv, tag, tlvLength, (const unsigned char *)buf);
403 json_decref(root);
405 return true;