diff --git a/client/cmdhffido.c b/client/cmdhffido.c index b4b6c058..dbe05ffe 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -26,13 +26,17 @@ #include #include #include +#include +#include #include "comms.h" #include "cmdmain.h" #include "util.h" #include "ui.h" +#include "proxmark3.h" #include "cmdhf14a.h" #include "mifare.h" #include "emv/emvcore.h" +#include "emv/emvjson.h" #include "emv/dump.h" #include "cliparser/cliparser.h" @@ -142,6 +146,8 @@ int CmdHFFidoRegister(const char *cmd) { uint8_t cdata[250] = {0}; int applen = 0; uint8_t adata[250] = {0}; + json_t *root = NULL; + json_error_t error; CLIParserInit("hf fido reg", "Initiate a U2F token registration. Needs two 32-byte hash number. \nchallenge parameter (32b) and application parameter (32b).", @@ -154,6 +160,7 @@ int CmdHFFidoRegister(const char *cmd) { arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("vV", "verbose", "show technical data"), arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"), + arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."), arg_str0(NULL, NULL, "", NULL), arg_str0(NULL, NULL, "", NULL), arg_param_end @@ -163,15 +170,45 @@ int CmdHFFidoRegister(const char *cmd) { bool APDULogging = arg_get_lit(1); bool verbose = arg_get_lit(2); bool paramsPlain = arg_get_lit(3); + + uint8_t jsonname[250] ={0}; + char *cjsonname = (char *)jsonname; + int jsonnamelen = 0; + CLIGetStrWithReturn(4, jsonname, &jsonnamelen); + // current path + file name + if (!strstr(cjsonname, ".json")) + strcat(cjsonname, ".json"); + char fname[strlen(get_my_executable_directory()) + strlen(cjsonname) + 1]; + if (jsonnamelen) { + strcpy(fname, get_my_executable_directory()); + strcat(fname, cjsonname); + if (access(fname, F_OK) != -1) { + root = json_load_file(fname, 0, &error); + if (!root) { + PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); + return 1; + } + + if (!json_is_object(root)) { + PrintAndLog("ERROR: Invalid json format. root must be an object."); + return 1; + } + + + } else { + root = json_object(); + } + } + if (paramsPlain) { memset(cdata, 0x00, 32); - CLIGetStrWithReturn(4, cdata, &chlen); + CLIGetStrWithReturn(5, cdata, &chlen); if (chlen && chlen > 16) { PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", chlen); return 1; } } else { - CLIGetHexWithReturn(4, cdata, &chlen); + CLIGetHexWithReturn(5, cdata, &chlen); if (chlen && chlen != 32) { PrintAndLog("ERROR: challenge parameter length must be 32 bytes only."); return 1; @@ -183,13 +220,13 @@ int CmdHFFidoRegister(const char *cmd) { if (paramsPlain) { memset(adata, 0x00, 32); - CLIGetStrWithReturn(5, adata, &applen); + CLIGetStrWithReturn(6, adata, &applen); if (applen && applen > 16) { PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", applen); return 1; } } else { - CLIGetHexWithReturn(5, adata, &applen); + CLIGetHexWithReturn(6, adata, &applen); if (applen && applen != 32) { PrintAndLog("ERROR: application parameter length must be 32 bytes only."); return 1; @@ -280,6 +317,24 @@ int CmdHFFidoRegister(const char *cmd) { printf(" %s", paramsPlain?(char *)adata:sprint_hex_inrow(adata, 32)); printf("\n"); + if (root) { + JsonSaveBufAsHex(root, "ChallengeParam", data, 32); + JsonSaveBufAsHex(root, "ApplicationParam", &data[32], 32); + JsonSaveInt(root, "KeyHandleLen", keyHandleLen); + JsonSaveBufAsHexCompact(root, "KeyHandle", &buf[67], keyHandleLen); + JsonSaveBufAsHexCompact(root, "DER", &buf[67 + keyHandleLen], derLen); + + res = json_dump_file(root, fname, JSON_INDENT(2)); + if (res) { + PrintAndLog("ERROR: can't save the file: %s", fname); + return 200; + } + PrintAndLog("File `%s` saved.", fname); + + // free json object + json_decref(root); + } + return 0; }; diff --git a/client/emv/emvjson.c b/client/emv/emvjson.c index 02297435..9defce08 100644 --- a/client/emv/emvjson.c +++ b/client/emv/emvjson.c @@ -68,24 +68,40 @@ char* GetApplicationDataName(tlv_tag_t tag) { return NULL; } -int JsonSaveStr(json_t *root, char *path, char *value) { +int JsonSaveJsonObject(json_t *root, char *path, json_t *value) { json_error_t error; if (strlen(path) < 1) return 1; if (path[0] == '$') { - if (json_path_set(root, path, json_string(value), 0, &error)) { + if (json_path_set(root, path, value, 0, &error)) { PrintAndLog("ERROR: can't set json path: ", error.text); return 2; } else { return 0; } } else { - return json_object_set_new(root, path, json_string(value)); + return json_object_set_new(root, path, value); } +} + +int JsonSaveInt(json_t *root, char *path, int value) { + return JsonSaveJsonObject(root, path, json_integer(value)); +} + +int JsonSaveStr(json_t *root, char *path, char *value) { + return JsonSaveJsonObject(root, path, json_string(value)); }; +int JsonSaveBufAsHexCompact(json_t *elm, char *path, uint8_t *data, size_t datalen) { + char * msg = sprint_hex_inrow(data, datalen); + if (msg && strlen(msg) && msg[strlen(msg) - 1] == ' ') + msg[strlen(msg) - 1] = '\0'; + + return JsonSaveStr(elm, path, msg); +} + int JsonSaveBufAsHex(json_t *elm, char *path, uint8_t *data, size_t datalen) { char * msg = sprint_hex(data, datalen); if (msg && strlen(msg) && msg[strlen(msg) - 1] == ' ') @@ -248,6 +264,11 @@ bool HexToBuffer(const char *errormsg, const char *hexvalue, uint8_t * buffer, s return true; } +int JsonLoadBufAsHex(json_t *elm, char *path, uint8_t *data, size_t *datalen) { + + return 0; +}; + bool ParamLoadFromJson(struct tlvdb *tlv) { json_t *root; json_error_t error; diff --git a/client/emv/emvjson.h b/client/emv/emvjson.h index a518d7b9..7148ddd0 100644 --- a/client/emv/emvjson.h +++ b/client/emv/emvjson.h @@ -20,7 +20,10 @@ typedef struct { extern char* GetApplicationDataName(tlv_tag_t tag); +extern int JsonSaveJsonObject(json_t *root, char *path, json_t *value); extern int JsonSaveStr(json_t *root, char *path, char *value); +extern int JsonSaveInt(json_t *root, char *path, int value); +extern int JsonSaveBufAsHexCompact(json_t *elm, char *path, uint8_t *data, size_t datalen); extern int JsonSaveBufAsHex(json_t *elm, char *path, uint8_t *data, size_t datalen); extern int JsonSaveHex(json_t *elm, char *path, uint64_t data, int datalen); @@ -30,6 +33,8 @@ extern int JsonSaveTLVTreeElm(json_t *elm, char *path, struct tlvdb *tlvdbelm, b extern int JsonSaveTLVTree(json_t *root, json_t *elm, char *path, struct tlvdb *tlvdbelm); +extern int JsonLoadBufAsHex(json_t *elm, char *path, uint8_t *data, size_t *datalen); + extern bool ParamLoadFromJson(struct tlvdb *tlv); #endif \ No newline at end of file diff --git a/client/util.c b/client/util.c index d7c824d9..c6d5f0d6 100644 --- a/client/util.c +++ b/client/util.c @@ -139,7 +139,7 @@ void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex // printing and converting functions char *sprint_hex(const uint8_t *data, const size_t len) { - static char buf[1025] = {0}; + static char buf[4097] = {0}; hex_to_buffer((uint8_t *)buf, data, len, sizeof(buf) - 1, 0, 1, false); @@ -147,7 +147,7 @@ char *sprint_hex(const uint8_t *data, const size_t len) { } char *sprint_hex_inrow_ex(const uint8_t *data, const size_t len, const size_t min_str_len) { - static char buf[1025] = {0}; + static char buf[4097] = {0}; hex_to_buffer((uint8_t *)buf, data, len, sizeof(buf) - 1, min_str_len, 0, false);