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 //----------------------------------------------------------------------------- 
  19 #include "proxmark3.h" 
  22 static const ApplicationDataElm ApplicationData
[] = { 
  28 {0x5F24,  "ExpirationDate"}, 
  29 {0x5F25,  "EffectiveDate"}, 
  30 {0x5F28,  "IssuerCountryCode"}, 
  32 {0x50,    "ApplicationLabel"}, 
  33 {0x9F08,  "VersionNumber"}, 
  34 {0x9F42,  "CurrencyCode"}, 
  35 {0x5F2D,  "LanguagePreference"}, 
  36 {0x87,    "PriorityIndicator"}, 
  37 {0x9F36,  "ATC"}, //Application Transaction Counter 
  39 {0x5F20,  "CardholderName"}, 
  45 {0x9F07,  "AUC"},   // Application Usage Control 
  48 {0x9F0D,  "IACDefault"}, 
  50 {0x9F0F,  "IACOnline"}, 
  52 {0x8F,    "CertificationAuthorityPublicKeyIndex"}, 
  53 {0x9F32,  "IssuerPublicKeyExponent"}, 
  54 {0x92,    "IssuerPublicKeyRemainder"}, 
  55 {0x90,    "IssuerPublicKeyCertificate"}, 
  56 {0x9F47,  "ICCPublicKeyExponent"}, 
  57 {0x9F46,  "ICCPublicKeyCertificate"}, 
  61 int ApplicationDataLen 
= sizeof(ApplicationData
) / sizeof(ApplicationDataElm
); 
  63 char* GetApplicationDataName(tlv_tag_t tag
) { 
  64         for (int i 
= 0; i 
< ApplicationDataLen
; i
++) 
  65                 if (ApplicationData
[i
].Tag 
== tag
) 
  66                         return ApplicationData
[i
].Name
; 
  71 int JsonSaveJsonObject(json_t 
*root
, char *path
, json_t 
*value
) { 
  78                 if (json_path_set(root
, path
, value
, 0, &error
)) { 
  79                         PrintAndLog("ERROR: can't set json path: ", error
.text
); 
  85                 return json_object_set_new(root
, path
, value
); 
  89 int JsonSaveInt(json_t 
*root
, char *path
, int value
) { 
  90         return JsonSaveJsonObject(root
, path
, json_integer(value
)); 
  93 int JsonSaveStr(json_t 
*root
, char *path
, char *value
) { 
  94         return JsonSaveJsonObject(root
, path
, json_string(value
)); 
  97 int JsonSaveBufAsHexCompact(json_t 
*elm
, char *path
, uint8_t *data
, size_t datalen
) { 
  98         char * msg 
= sprint_hex_inrow(data
, datalen
); 
  99         if (msg 
&& strlen(msg
) && msg
[strlen(msg
) - 1] == ' ') 
 100                 msg
[strlen(msg
) - 1] = '\0'; 
 102         return JsonSaveStr(elm
, path
, msg
); 
 105 int JsonSaveBufAsHex(json_t 
*elm
, char *path
, uint8_t *data
, size_t datalen
) { 
 106         char * msg 
= sprint_hex(data
, datalen
); 
 107         if (msg 
&& strlen(msg
) && msg
[strlen(msg
) - 1] == ' ') 
 108                 msg
[strlen(msg
) - 1] = '\0'; 
 110         return JsonSaveStr(elm
, path
, msg
); 
 113 int JsonSaveHex(json_t 
*elm
, char *path
, uint64_t data
, int datalen
) { 
 114         uint8_t bdata
[8] = {0}; 
 117                 for (uint64_t u 
= 0xffffffffffffffff; u
; u 
= u 
<< 8) { 
 128         num_to_bytes(data
, len
, bdata
); 
 130         return JsonSaveBufAsHex(elm
, path
, bdata
, len
); 
 133 int JsonSaveTLVValue(json_t 
*root
, char *path
, struct tlvdb 
*tlvdbelm
) { 
 134         const struct tlv 
*tlvelm 
= tlvdb_get_tlv(tlvdbelm
); 
 136                 return JsonSaveBufAsHex(root
, path
, (uint8_t *)tlvelm
->value
, tlvelm
->len
); 
 141 int JsonSaveTLVElm(json_t 
*elm
, char *path
, struct tlv 
*tlvelm
, bool saveName
, bool saveValue
, bool saveAppDataLink
) { 
 144         if (strlen(path
) < 1 || !tlvelm
) 
 147         if (path
[0] == '$') { 
 149                 json_t 
*obj 
= json_path_get(elm
, path
); 
 153                         if (json_is_array(elm
)) { 
 154                                 if (json_array_append_new(elm
, obj
)) { 
 155                                         PrintAndLog("ERROR: can't append array: %s", path
); 
 159                                 if (json_path_set(elm
, path
, obj
, 0, &error
)) { 
 160                                         PrintAndLog("ERROR: can't set json path: ", error
.text
); 
 166                 if (saveAppDataLink
) { 
 167                         char * AppDataName 
= GetApplicationDataName(tlvelm
->tag
); 
 169                                 JsonSaveStr(obj
, "appdata", AppDataName
); 
 171                         char * name 
= emv_get_tag_name(tlvelm
); 
 172                         if (saveName 
&& name 
&& strlen(name
) > 0 && strncmp(name
, "Unknown", 7)) 
 173                                 JsonSaveStr(obj
, "name", emv_get_tag_name(tlvelm
)); 
 174                         JsonSaveHex(obj
, "tag", tlvelm
->tag
, 0); 
 176                                 JsonSaveHex(obj
, "length", tlvelm
->len
, 0); 
 177                                 JsonSaveBufAsHex(obj
, "value", (uint8_t *)tlvelm
->value
, tlvelm
->len
); 
 185 int JsonSaveTLVTreeElm(json_t 
*elm
, char *path
, struct tlvdb 
*tlvdbelm
, bool saveName
, bool saveValue
, bool saveAppDataLink
) { 
 186         return JsonSaveTLVElm(elm
, path
, (struct tlv 
*)tlvdb_get_tlv(tlvdbelm
), saveName
, saveValue
, saveAppDataLink
); 
 189 int JsonSaveTLVTree(json_t 
*root
, json_t 
*elm
, char *path
, struct tlvdb 
*tlvdbelm
) { 
 190         struct tlvdb 
*tlvp 
= tlvdbelm
; 
 192                 const struct tlv 
* tlvpelm 
= tlvdb_get_tlv(tlvp
); 
 193                 char * AppDataName 
= NULL
; 
 195                         AppDataName 
= GetApplicationDataName(tlvpelm
->tag
); 
 198                         char appdatalink
[200] = {0}; 
 199                         sprintf(appdatalink
, "$.ApplicationData.%s", AppDataName
); 
 200                         JsonSaveBufAsHex(root
, appdatalink
, (uint8_t *)tlvpelm
->value
, tlvpelm
->len
); 
 203                 json_t 
*pelm 
= json_path_get(elm
, path
); 
 204                 if (pelm 
&& json_is_array(pelm
)) { 
 205                         json_t 
*appendelm 
= json_object(); 
 206                         json_array_append_new(pelm
, appendelm
); 
 207                         JsonSaveTLVTreeElm(appendelm
, "$", tlvp
, !AppDataName
, !tlvdb_elm_get_children(tlvp
), AppDataName
); 
 210                         JsonSaveTLVTreeElm(elm
, path
, tlvp
, !AppDataName
, !tlvdb_elm_get_children(tlvp
), AppDataName
); 
 211                         pelm 
= json_path_get(elm
, path
); 
 214                 if (tlvdb_elm_get_children(tlvp
)) { 
 219                         // check childs element and add it if not found 
 220                         json_t 
*chjson 
= json_path_get(pelm
, "$.Childs"); 
 222                                 json_object_set_new(pelm
, "Childs", json_array()); 
 224                                 chjson 
= json_path_get(pelm
, "$.Childs"); 
 228                         if (!json_is_array(chjson
)) { 
 229                                 PrintAndLog("E->Internal logic error. `$.Childs` is not an array."); 
 234                         JsonSaveTLVTree(root
, chjson
, "$", tlvdb_elm_get_children(tlvp
)); 
 237                 tlvp 
= tlvdb_elm_get_next(tlvp
); 
 242 bool HexToBuffer(const char *errormsg
, const char *hexvalue
, uint8_t * buffer
, size_t maxbufferlen
, size_t *bufferlen
) { 
 245         switch(param_gethex_to_eol(hexvalue
, 0, buffer
, maxbufferlen
, &buflen
)) { 
 247                 PrintAndLog("%s Invalid HEX value.", errormsg
); 
 250                 PrintAndLog("%s Hex value too large.", errormsg
); 
 253                 PrintAndLog("%s Hex value must have even number of digits.", errormsg
); 
 257         if (buflen 
> maxbufferlen
) { 
 258                 PrintAndLog("%s HEX length (%d) more than %d", errormsg
, *bufferlen
, maxbufferlen
); 
 267 int JsonLoadBufAsHex(json_t 
*elm
, char *path
, uint8_t *data
, size_t maxbufferlen
, size_t *datalen
) { 
 271         json_t 
*jelm 
= json_path_get((const json_t 
*)elm
, path
); 
 272         if (!jelm 
|| !json_is_string(jelm
)) 
 275         if (!HexToBuffer("ERROR load", json_string_value(jelm
), data
, maxbufferlen
, datalen
)) 
 281 bool ParamLoadFromJson(struct tlvdb 
*tlv
) { 
 286                 PrintAndLog("ERROR load params: tlv tree is NULL."); 
 290         // current path + file name 
 291         const char *relfname 
= "emv/defparams.json";  
 292         char fname
[strlen(get_my_executable_directory()) + strlen(relfname
) + 1]; 
 293         strcpy(fname
, get_my_executable_directory()); 
 294         strcat(fname
, relfname
); 
 296         root 
= json_load_file(fname
, 0, &error
); 
 298                 PrintAndLog("Load params: json error on line %d: %s", error
.line
, error
.text
); 
 302         if (!json_is_array(root
)) { 
 303                 PrintAndLog("Load params: Invalid json format. root must be array."); 
 307         PrintAndLog("Load params: json(%d) OK", json_array_size(root
)); 
 309         for(int i 
= 0; i 
< json_array_size(root
); i
++) { 
 310                 json_t 
*data
, *jtag
, *jlength
, *jvalue
; 
 312                 data 
= json_array_get(root
, i
); 
 313                 if(!json_is_object(data
)) 
 315                         PrintAndLog("Load params: data [%d] is not an object", i 
+ 1); 
 320                 jtag 
= json_object_get(data
, "tag"); 
 321                 if(!json_is_string(jtag
)) 
 323                         PrintAndLog("Load params: data [%d] tag is not a string", i 
+ 1); 
 327                 const char *tlvTag 
= json_string_value(jtag
); 
 329                 jvalue 
= json_object_get(data
, "value"); 
 330                 if(!json_is_string(jvalue
)) 
 332                         PrintAndLog("Load params: data [%d] value is not a string", i 
+ 1); 
 336                 const char *tlvValue 
= json_string_value(jvalue
); 
 338                 jlength 
= json_object_get(data
, "length"); 
 339                 if(!json_is_number(jlength
)) 
 341                         PrintAndLog("Load params: data [%d] length is not a number", i 
+ 1); 
 346                 int tlvLength 
= json_integer_value(jlength
); 
 347                 if (tlvLength 
> 250) { 
 348                         PrintAndLog("Load params: data [%d] length more than 250", i 
+ 1); 
 353                 PrintAndLog("TLV param: %s[%d]=%s", tlvTag
, tlvLength
, tlvValue
); 
 354                 uint8_t buf
[251] = {0}; 
 357                 // here max length must be 4, but now tlv_tag_t is 2-byte var. so let it be 2 by now...  TODO: needs refactoring tlv_tag_t... 
 358                 if (!HexToBuffer("TLV Error type:", tlvTag
, buf
, 2, &buflen
)) {  
 363                 for (int i 
= 0; i 
< buflen
; i
++) { 
 364                         tag 
= (tag 
<< 8) + buf
[i
]; 
 367                 if (!HexToBuffer("TLV Error value:", tlvValue
, buf
, sizeof(buf
) - 1, &buflen
)) { 
 372                 if (buflen 
!= tlvLength
) { 
 373                         PrintAndLog("Load params: data [%d] length of HEX must(%d) be identical to length in TLV param(%d)", i 
+ 1, buflen
, tlvLength
); 
 378                 tlvdb_change_or_add_node(tlv
, tag
, tlvLength
, (const unsigned char *)buf
);