added loading params from GPO

This commit is contained in:
merlokk 2018-10-01 21:36:05 +03:00
commit 6f888272c2

View file

@ -14,6 +14,31 @@
#include "cliparser/cliparser.h" #include "cliparser/cliparser.h"
#include <jansson.h> #include <jansson.h>
bool HexToBuffer(const char *errormsg, const char *hexvalue, uint8_t * buffer, size_t maxbufferlen, size_t *bufferlen) {
int buflen = 0;
switch(param_gethex_to_eol(hexvalue, 0, buffer, maxbufferlen, &buflen)) {
case 1:
PrintAndLog("%s Invalid HEX value.", errormsg);
return false;
case 2:
PrintAndLog("%s Hex value too large.", errormsg);
return false;
case 3:
PrintAndLog("%s Hex value must have even number of digits.", errormsg);
return false;
}
if (buflen > maxbufferlen) {
PrintAndLog("%s HEX length (%d) more than %d", errormsg, *bufferlen, maxbufferlen);
return false;
}
*bufferlen = buflen;
return true;
}
#define TLV_ADD(tag, value)( tlvdb_change_or_add_node(tlvRoot, tag, sizeof(value) - 1, (const unsigned char *)value) ) #define TLV_ADD(tag, value)( tlvdb_change_or_add_node(tlvRoot, tag, sizeof(value) - 1, (const unsigned char *)value) )
void ParamLoadDefaults(struct tlvdb *tlvRoot) { void ParamLoadDefaults(struct tlvdb *tlvRoot) {
//9F02:(Amount, authorized (Numeric)) len:6 //9F02:(Amount, authorized (Numeric)) len:6
@ -35,6 +60,111 @@ void ParamLoadDefaults(struct tlvdb *tlvRoot) {
TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC
} }
bool ParamLoadFromJson(struct tlvdb *tlv) {
json_t *root;
json_error_t error;
if (!tlv) {
PrintAndLog("ERROR load params: tlv tree is NULL.");
return false;
}
// current path + file name
const char *relfname = "emv/defparams.json";
char fname[strlen(get_my_executable_directory()) + strlen(relfname) + 1];
strcpy(fname, get_my_executable_directory());
strcat(fname, relfname);
root = json_load_file(fname, 0, &error);
if (!root) {
PrintAndLog("Load params: json error on line %d: %s", error.line, error.text);
return false;
}
if (!json_is_array(root)) {
PrintAndLog("Load params: Invalid json format. root must be array.");
return false;
}
PrintAndLog("Load params: json OK");
for(int i = 0; i < json_array_size(root); i++) {
json_t *data, *jtype, *jlength, *jvalue;
data = json_array_get(root, i);
if(!json_is_object(data))
{
PrintAndLog("Load params: data [%d] is not an object", i + 1);
json_decref(root);
return false;
}
jtype = json_object_get(data, "type");
if(!json_is_string(jtype))
{
PrintAndLog("Load params: data [%d] type is not a string", i + 1);
json_decref(root);
return false;
}
const char *tlvType = json_string_value(jtype);
jvalue = json_object_get(data, "value");
if(!json_is_string(jvalue))
{
PrintAndLog("Load params: data [%d] value is not a string", i + 1);
json_decref(root);
return false;
}
const char *tlvValue = json_string_value(jvalue);
jlength = json_object_get(data, "length");
if(!json_is_number(jlength))
{
PrintAndLog("Load params: data [%d] length is not a number", i + 1);
json_decref(root);
return false;
}
int tlvLength = json_integer_value(jlength);
if (tlvLength > 250) {
PrintAndLog("Load params: data [%d] length more than 250", i + 1);
json_decref(root);
return false;
}
PrintAndLog("TLV param: %s[%d]=%s", tlvType, tlvLength, tlvValue);
uint8_t buf[251] = {0};
size_t buflen = 0;
// 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...
if (!HexToBuffer("TLV Error type:", tlvType, buf, 2, &buflen)) {
json_decref(root);
return false;
}
tlv_tag_t tag = 0;
for (int i = 0; i < buflen; i++) {
tag = (tag << 8) + buf[i];
}
if (!HexToBuffer("TLV Error value:", tlvValue, buf, sizeof(buf) - 1, &buflen)) {
json_decref(root);
return false;
}
if (buflen != tlvLength) {
PrintAndLog("Load params: data [%d] length of HEX must(%d) be identical to length in TLV param(%d)", i + 1, buflen, tlvLength);
json_decref(root);
return false;
}
tlvdb_change_or_add_node(tlv, tag, tlvLength, (const unsigned char *)buf);
}
json_decref(root);
return true;
}
int CmdHFEMVSelect(const char *cmd) { int CmdHFEMVSelect(const char *cmd) {
uint8_t data[APDU_AID_LEN] = {0}; uint8_t data[APDU_AID_LEN] = {0};
int datalen = 0; int datalen = 0;
@ -189,8 +319,8 @@ int CmdHFEMVGPO(const char *cmd) {
void* argtable[] = { void* argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("kK", "keep", "keep field ON for next command"), arg_lit0("kK", "keep", "keep field ON for next command"),
arg_lit0("pP", "params", "load parameters for PDOL making from `emv/defparams.json` file (by default uses default parameters) (NOT WORK!!!)"), arg_lit0("pP", "params", "load parameters for PDOL making from `emv/defparams.json` file (by default uses default parameters)"),
arg_lit0("mM", "make", "make PDOLdata from PDOL (tag 9F38) and parameters (NOT WORK!!!)"), arg_lit0("mM", "make", "make PDOLdata from PDOL (tag 9F38) and parameters"),
arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("aA", "apdu", "show APDU reqests and responses"),
arg_lit0("tT", "tlv", "TLV decode results of selected applets"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
arg_strx0(NULL, NULL, "<HEX PDOLdata/PDOL>", NULL), arg_strx0(NULL, NULL, "<HEX PDOLdata/PDOL>", NULL),
@ -220,20 +350,19 @@ int CmdHFEMVGPO(const char *cmd) {
.value = (uint8_t *)data, .value = (uint8_t *)data,
}; };
if (dataMakeFromPDOL) { if (dataMakeFromPDOL) {
// TODO
PrintAndLog("Make PDOL data not implemented!");
ParamLoadDefaults(tlvRoot); ParamLoadDefaults(tlvRoot);
if (paramsLoadFromFile) { if (paramsLoadFromFile) {
PrintAndLog("Params loading from file...");
ParamLoadFromJson(tlvRoot);
}; };
/* pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
pdol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x9f38, datalen, data), tlvRoot, 0x83);
if (!pdol_data_tlv){ if (!pdol_data_tlv){
PrintAndLog("ERROR: can't create PDOL TLV."); PrintAndLog("ERROR: can't create PDOL TLV.");
tlvdb_free(tlvRoot); tlvdb_free(tlvRoot);
return 4; return 4;
}*/ }
return 0;
} else { } else {
pdol_data_tlv = &data_tlv; pdol_data_tlv = &data_tlv;
} }
@ -493,136 +622,6 @@ int CmdHFEMVInternalAuthenticate(const char *cmd) {
#define dreturn(n) {free(pdol_data_tlv);tlvdb_free(tlvSelect);tlvdb_free(tlvRoot);DropField();return n;} #define dreturn(n) {free(pdol_data_tlv);tlvdb_free(tlvSelect);tlvdb_free(tlvRoot);DropField();return n;}
bool HexToBuffer(const char *errormsg, const char *hexvalue, uint8_t * buffer, size_t maxbufferlen, size_t *bufferlen) {
int buflen = 0;
switch(param_gethex_to_eol(hexvalue, 0, buffer, maxbufferlen, &buflen)) {
case 1:
PrintAndLog("%s Invalid HEX value.", errormsg);
return false;
case 2:
PrintAndLog("%s Hex value too large.", errormsg);
return false;
case 3:
PrintAndLog("%s Hex value must have even number of digits.", errormsg);
return false;
}
if (buflen > maxbufferlen) {
PrintAndLog("%s HEX length (%d) more than %d", errormsg, *bufferlen, maxbufferlen);
return false;
}
*bufferlen = buflen;
return true;
}
bool ParamLoadFromJson(struct tlvdb *tlv) {
json_t *root;
json_error_t error;
if (!tlv) {
PrintAndLog("ERROR load params: tlv tree is NULL.");
return false;
}
// current path + file name
const char *relfname = "emv/defparams.json";
char fname[strlen(get_my_executable_directory()) + strlen(relfname) + 1];
strcpy(fname, get_my_executable_directory());
strcat(fname, relfname);
root = json_load_file(fname, 0, &error);
if (!root) {
PrintAndLog("Load params: json error on line %d: %s", error.line, error.text);
return false;
}
if (!json_is_array(root)) {
PrintAndLog("Load params: Invalid json format. root must be array.");
return false;
}
PrintAndLog("Load params: json OK");
for(int i = 0; i < json_array_size(root); i++) {
json_t *data, *jtype, *jlength, *jvalue;
data = json_array_get(root, i);
if(!json_is_object(data))
{
PrintAndLog("Load params: data [%d] is not an object", i + 1);
json_decref(root);
return false;
}
jtype = json_object_get(data, "type");
if(!json_is_string(jtype))
{
PrintAndLog("Load params: data [%d] type is not a string", i + 1);
json_decref(root);
return false;
}
const char *tlvType = json_string_value(jtype);
jvalue = json_object_get(data, "value");
if(!json_is_string(jvalue))
{
PrintAndLog("Load params: data [%d] value is not a string", i + 1);
json_decref(root);
return false;
}
const char *tlvValue = json_string_value(jvalue);
jlength = json_object_get(data, "length");
if(!json_is_number(jlength))
{
PrintAndLog("Load params: data [%d] length is not a number", i + 1);
json_decref(root);
return false;
}
int tlvLength = json_integer_value(jlength);
if (tlvLength > 250) {
PrintAndLog("Load params: data [%d] length more than 250", i + 1);
json_decref(root);
return false;
}
PrintAndLog("TLV param: %s[%d]=%s", tlvType, tlvLength, tlvValue);
uint8_t buf[251] = {0};
size_t buflen = 0;
// 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...
if (!HexToBuffer("TLV Error type:", tlvType, buf, 2, &buflen)) {
json_decref(root);
return false;
}
tlv_tag_t tag = 0;
for (int i = 0; i < buflen; i++) {
tag = (tag << 8) + buf[i];
}
if (!HexToBuffer("TLV Error value:", tlvValue, buf, sizeof(buf) - 1, &buflen)) {
json_decref(root);
return false;
}
if (buflen != tlvLength) {
PrintAndLog("Load params: data [%d] length of HEX must(%d) be identical to length in TLV param(%d)", i + 1, buflen, tlvLength);
json_decref(root);
return false;
}
tlvdb_change_or_add_node(tlv, tag, tlvLength, (const unsigned char *)buf);
}
json_decref(root);
return true;
}
int CmdHFEMVExec(const char *cmd) { int CmdHFEMVExec(const char *cmd) {
uint8_t buf[APDU_RES_LEN] = {0}; uint8_t buf[APDU_RES_LEN] = {0};
size_t len = 0; size_t len = 0;