mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-22 06:13:27 -07:00
added loading params from GPO
This commit is contained in:
parent
11146fc1e1
commit
6f888272c2
1 changed files with 137 additions and 138 deletions
|
@ -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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue