mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 05:13:46 -07:00
chg, hf fido remake
This commit is contained in:
parent
17d6ce5007
commit
12425aaf60
1 changed files with 86 additions and 91 deletions
|
@ -18,14 +18,12 @@
|
||||||
// https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html
|
// https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
#include "cmdhffido.h"
|
#include "cmdhffido.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "cmdparser.h" // command_t
|
#include "cmdparser.h" // command_t
|
||||||
#include "commonutil.h"
|
#include "commonutil.h"
|
||||||
|
|
||||||
#include "comms.h"
|
#include "comms.h"
|
||||||
#include "proxmark3.h"
|
#include "proxmark3.h"
|
||||||
#include "emv/emvcore.h"
|
#include "emv/emvcore.h"
|
||||||
|
@ -50,7 +48,7 @@ static int CmdHFFidoInfo(const char *cmd) {
|
||||||
infoHF14A(false, false, false);
|
infoHF14A(false, false, false);
|
||||||
|
|
||||||
// FIDO info
|
// FIDO info
|
||||||
PrintAndLogEx(NORMAL, "--------------------------------------------");
|
PrintAndLogEx(INFO, "-----------" _CYAN_("FIDO Info") "---------------------------------");
|
||||||
SetAPDULogging(false);
|
SetAPDULogging(false);
|
||||||
|
|
||||||
uint8_t buf[APDU_RES_LEN] = {0};
|
uint8_t buf[APDU_RES_LEN] = {0};
|
||||||
|
@ -70,7 +68,7 @@ static int CmdHFFidoInfo(const char *cmd) {
|
||||||
PrintAndLogEx(ERR, "APDU exchange error. Card returns 0x0000.");
|
PrintAndLogEx(ERR, "APDU exchange error. Card returns 0x0000.");
|
||||||
|
|
||||||
DropField();
|
DropField();
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strncmp((char *)buf, "U2F_V2", 7)) {
|
if (!strncmp((char *)buf, "U2F_V2", 7)) {
|
||||||
|
@ -92,13 +90,12 @@ static int CmdHFFidoInfo(const char *cmd) {
|
||||||
}
|
}
|
||||||
if (sw != 0x9000) {
|
if (sw != 0x9000) {
|
||||||
PrintAndLogEx(ERR, "FIDO2 version doesn't exist (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
PrintAndLogEx(ERR, "FIDO2 version doesn't exist (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||||
|
return PM3_SUCCESS;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[0]) {
|
if (buf[0]) {
|
||||||
PrintAndLogEx(ERR, "FIDO2 get version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
|
PrintAndLogEx(ERR, "FIDO2 get version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len > 1) {
|
if (len > 1) {
|
||||||
|
@ -107,7 +104,7 @@ static int CmdHFFidoInfo(const char *cmd) {
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(ERR, "FIDO2 version length error");
|
PrintAndLogEx(ERR, "FIDO2 version length error");
|
||||||
}
|
}
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static json_t *OpenJson(CLIParserContext *ctx, int paramnum, char *fname, void *argtable[], bool *err) {
|
static json_t *OpenJson(CLIParserContext *ctx, int paramnum, char *fname, void *argtable[], bool *err) {
|
||||||
|
@ -115,7 +112,7 @@ static json_t *OpenJson(CLIParserContext *ctx, int paramnum, char *fname, void *
|
||||||
json_error_t error;
|
json_error_t error;
|
||||||
*err = false;
|
*err = false;
|
||||||
|
|
||||||
uint8_t jsonname[250] = {0};
|
uint8_t jsonname[FILE_PATH_SIZE] = {0};
|
||||||
char *cjsonname = (char *)jsonname;
|
char *cjsonname = (char *)jsonname;
|
||||||
int jsonnamelen = 0;
|
int jsonnamelen = 0;
|
||||||
|
|
||||||
|
@ -159,7 +156,6 @@ static int CmdHFFidoRegister(const char *cmd) {
|
||||||
uint8_t cdata[250] = {0};
|
uint8_t cdata[250] = {0};
|
||||||
int applen = 0;
|
int applen = 0;
|
||||||
uint8_t adata[250] = {0};
|
uint8_t adata[250] = {0};
|
||||||
json_t *root = NULL;
|
|
||||||
|
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf fido reg",
|
CLIParserInit(&ctx, "hf fido reg",
|
||||||
|
@ -187,12 +183,12 @@ static int CmdHFFidoRegister(const char *cmd) {
|
||||||
bool paramsPlain = arg_get_lit(3);
|
bool paramsPlain = arg_get_lit(3);
|
||||||
bool showDERTLV = arg_get_lit(4);
|
bool showDERTLV = arg_get_lit(4);
|
||||||
|
|
||||||
char fname[250] = {0};
|
char fname[FILE_PATH_SIZE] = {0};
|
||||||
bool err;
|
bool err;
|
||||||
root = OpenJson(ctx, 5, fname, argtable, &err);
|
json_t *root = OpenJson(ctx, 5, fname, argtable, &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return 1;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
if (root) {
|
if (root) {
|
||||||
size_t jlen;
|
size_t jlen;
|
||||||
|
@ -205,13 +201,13 @@ static int CmdHFFidoRegister(const char *cmd) {
|
||||||
CLIGetStrWithReturn(ctx, 6, cdata, &chlen);
|
CLIGetStrWithReturn(ctx, 6, cdata, &chlen);
|
||||||
if (chlen > 16) {
|
if (chlen > 16) {
|
||||||
PrintAndLogEx(ERR, "ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", chlen);
|
PrintAndLogEx(ERR, "ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", chlen);
|
||||||
return 1;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CLIGetHexWithReturn(ctx, 6, cdata, &chlen);
|
CLIGetHexWithReturn(ctx, 6, cdata, &chlen);
|
||||||
if (chlen && chlen != 32) {
|
if (chlen && chlen != 32) {
|
||||||
PrintAndLogEx(ERR, "ERROR: challenge parameter length must be 32 bytes only.");
|
PrintAndLogEx(ERR, "ERROR: challenge parameter length must be 32 bytes only.");
|
||||||
return 1;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (chlen)
|
if (chlen)
|
||||||
|
@ -223,13 +219,13 @@ static int CmdHFFidoRegister(const char *cmd) {
|
||||||
CLIGetStrWithReturn(ctx, 7, adata, &applen);
|
CLIGetStrWithReturn(ctx, 7, adata, &applen);
|
||||||
if (applen > 16) {
|
if (applen > 16) {
|
||||||
PrintAndLogEx(ERR, "ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", applen);
|
PrintAndLogEx(ERR, "ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", applen);
|
||||||
return 1;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CLIGetHexWithReturn(ctx, 7, adata, &applen);
|
CLIGetHexWithReturn(ctx, 7, adata, &applen);
|
||||||
if (applen && applen != 32) {
|
if (applen && applen != 32) {
|
||||||
PrintAndLogEx(ERR, "ERROR: application parameter length must be 32 bytes only.");
|
PrintAndLogEx(ERR, "ERROR: application parameter length must be 32 bytes only.");
|
||||||
return 1;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (applen)
|
if (applen)
|
||||||
|
@ -258,7 +254,7 @@ static int CmdHFFidoRegister(const char *cmd) {
|
||||||
if (sw != 0x9000) {
|
if (sw != 0x9000) {
|
||||||
PrintAndLogEx(ERR, "Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
PrintAndLogEx(ERR, "Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||||
DropField();
|
DropField();
|
||||||
return 2;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = FIDORegister(data, buf, sizeof(buf), &len, &sw);
|
res = FIDORegister(data, buf, sizeof(buf), &len, &sw);
|
||||||
|
@ -270,22 +266,24 @@ static int CmdHFFidoRegister(const char *cmd) {
|
||||||
|
|
||||||
if (sw != 0x9000) {
|
if (sw != 0x9000) {
|
||||||
PrintAndLogEx(ERR, "ERROR execute register command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
PrintAndLogEx(ERR, "ERROR execute register command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||||
return 3;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
if (APDULogging)
|
if (APDULogging)
|
||||||
PrintAndLogEx(NORMAL, "---------------------------------------------------------------");
|
PrintAndLogEx(INFO, "---------------------------------------------------------------");
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "data len: %zu", len);
|
PrintAndLogEx(NORMAL, "data len: %zu", len);
|
||||||
|
|
||||||
if (verbose2) {
|
if (verbose2) {
|
||||||
PrintAndLogEx(NORMAL, "--------------data----------------------");
|
PrintAndLogEx(INFO, "------------ " _CYAN_("data") " ----------------------");
|
||||||
dump_buffer((const unsigned char *)buf, len, NULL, 0);
|
dump_buffer((const unsigned char *)buf, len, NULL, 0);
|
||||||
PrintAndLogEx(NORMAL, "--------------data----------------------");
|
PrintAndLogEx(INFO, "-------------" _CYAN_("data") " ----------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[0] != 0x05) {
|
if (buf[0] != 0x05) {
|
||||||
PrintAndLogEx(ERR, "ERROR: First byte must be 0x05, but it %2x", buf[0]);
|
PrintAndLogEx(ERR, "ERROR: First byte must be 0x05, but it %2x", buf[0]);
|
||||||
return 5;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(SUCCESS, "User public key: %s", sprint_hex(&buf[1], 65));
|
PrintAndLogEx(SUCCESS, "User public key: %s", sprint_hex(&buf[1], 65));
|
||||||
|
|
||||||
|
@ -357,12 +355,11 @@ static int CmdHFFidoRegister(const char *cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "\nauth command: ");
|
PrintAndLogEx(INFO, "\nauth command: ");
|
||||||
printf("hf fido auth %s%s", paramsPlain ? "-p " : "", sprint_hex_inrow(&buf[67], keyHandleLen));
|
PrintAndLogEx(INFO, "hf fido auth %s%s", paramsPlain ? "-p " : "", sprint_hex_inrow(&buf[67], keyHandleLen));
|
||||||
if (chlen || applen)
|
if (chlen || applen)
|
||||||
printf(" %s", paramsPlain ? (char *)cdata : sprint_hex_inrow(cdata, 32));
|
PrintAndLogEx(INFO, " %s", paramsPlain ? (char *)cdata : sprint_hex_inrow(cdata, 32));
|
||||||
if (applen)
|
if (applen)
|
||||||
printf(" %s", paramsPlain ? (char *)adata : sprint_hex_inrow(adata, 32));
|
PrintAndLogEx(INFO, " %s", paramsPlain ? (char *)adata : sprint_hex_inrow(adata, 32));
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
if (root) {
|
if (root) {
|
||||||
JsonSaveBufAsHex(root, "ChallengeParam", data, 32);
|
JsonSaveBufAsHex(root, "ChallengeParam", data, 32);
|
||||||
|
@ -375,16 +372,15 @@ static int CmdHFFidoRegister(const char *cmd) {
|
||||||
res = json_dump_file(root, fname, JSON_INDENT(2));
|
res = json_dump_file(root, fname, JSON_INDENT(2));
|
||||||
if (res) {
|
if (res) {
|
||||||
PrintAndLogEx(ERR, "ERROR: can't save the file: %s", fname);
|
PrintAndLogEx(ERR, "ERROR: can't save the file: %s", fname);
|
||||||
return 200;
|
return PM3_EFILE;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(SUCCESS, "File " _YELLOW_("`%s`") " saved.", fname);
|
PrintAndLogEx(SUCCESS, "File " _YELLOW_("`%s`") " saved.", fname);
|
||||||
|
|
||||||
// free json object
|
// free json object
|
||||||
json_decref(root);
|
json_decref(root);
|
||||||
}
|
}
|
||||||
|
return PM3_SUCCESS;
|
||||||
return 0;
|
}
|
||||||
};
|
|
||||||
|
|
||||||
static int CmdHFFidoAuthenticate(const char *cmd) {
|
static int CmdHFFidoAuthenticate(const char *cmd) {
|
||||||
uint8_t data[512] = {0};
|
uint8_t data[512] = {0};
|
||||||
|
@ -393,7 +389,6 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
|
||||||
uint8_t public_key[65] = {0};
|
uint8_t public_key[65] = {0};
|
||||||
int hdatalen = 0;
|
int hdatalen = 0;
|
||||||
uint8_t keyHandleLen = 0;
|
uint8_t keyHandleLen = 0;
|
||||||
json_t *root = NULL;
|
|
||||||
|
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf fido auth",
|
CLIParserInit(&ctx, "hf fido auth",
|
||||||
|
@ -430,11 +425,12 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
|
||||||
|
|
||||||
char fname[250] = {0};
|
char fname[250] = {0};
|
||||||
bool err;
|
bool err;
|
||||||
root = OpenJson(ctx, 7, fname, argtable, &err);
|
json_t *root = OpenJson(ctx, 7, fname, argtable, &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return 1;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root) {
|
if (root) {
|
||||||
size_t jlen;
|
size_t jlen;
|
||||||
JsonLoadBufAsHex(root, "$.ChallengeParam", data, 32, &jlen);
|
JsonLoadBufAsHex(root, "$.ChallengeParam", data, 32, &jlen);
|
||||||
|
@ -450,7 +446,7 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
|
||||||
CLIGetHexWithReturn(ctx, 8, hdata, &hdatalen);
|
CLIGetHexWithReturn(ctx, 8, hdata, &hdatalen);
|
||||||
if (hdatalen && hdatalen != 65) {
|
if (hdatalen && hdatalen != 65) {
|
||||||
PrintAndLogEx(ERR, "ERROR: public key length must be 65 bytes only.");
|
PrintAndLogEx(ERR, "ERROR: public key length must be 65 bytes only.");
|
||||||
return 1;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
if (hdatalen) {
|
if (hdatalen) {
|
||||||
memmove(public_key, hdata, hdatalen);
|
memmove(public_key, hdata, hdatalen);
|
||||||
|
@ -460,7 +456,7 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
|
||||||
CLIGetHexWithReturn(ctx, 9, hdata, &hdatalen);
|
CLIGetHexWithReturn(ctx, 9, hdata, &hdatalen);
|
||||||
if (hdatalen > 255) {
|
if (hdatalen > 255) {
|
||||||
PrintAndLogEx(ERR, "ERROR: application parameter length must be less than 255.");
|
PrintAndLogEx(ERR, "ERROR: application parameter length must be less than 255.");
|
||||||
return 1;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
if (hdatalen) {
|
if (hdatalen) {
|
||||||
keyHandleLen = hdatalen;
|
keyHandleLen = hdatalen;
|
||||||
|
@ -473,13 +469,13 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
|
||||||
CLIGetStrWithReturn(ctx, 9, hdata, &hdatalen);
|
CLIGetStrWithReturn(ctx, 9, hdata, &hdatalen);
|
||||||
if (hdatalen > 16) {
|
if (hdatalen > 16) {
|
||||||
PrintAndLogEx(ERR, "ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen);
|
PrintAndLogEx(ERR, "ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen);
|
||||||
return 1;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CLIGetHexWithReturn(ctx, 10, hdata, &hdatalen);
|
CLIGetHexWithReturn(ctx, 10, hdata, &hdatalen);
|
||||||
if (hdatalen && hdatalen != 32) {
|
if (hdatalen && hdatalen != 32) {
|
||||||
PrintAndLogEx(ERR, "ERROR: challenge parameter length must be 32 bytes only.");
|
PrintAndLogEx(ERR, "ERROR: challenge parameter length must be 32 bytes only.");
|
||||||
return 1;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hdatalen)
|
if (hdatalen)
|
||||||
|
@ -490,13 +486,15 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
|
||||||
CLIGetStrWithReturn(ctx, 11, hdata, &hdatalen);
|
CLIGetStrWithReturn(ctx, 11, hdata, &hdatalen);
|
||||||
if (hdatalen > 16) {
|
if (hdatalen > 16) {
|
||||||
PrintAndLogEx(ERR, "ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen);
|
PrintAndLogEx(ERR, "ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen);
|
||||||
return 1;
|
CLIParserFree(ctx);
|
||||||
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CLIGetHexWithReturn(ctx, 10, hdata, &hdatalen);
|
CLIGetHexWithReturn(ctx, 10, hdata, &hdatalen);
|
||||||
if (hdatalen && hdatalen != 32) {
|
if (hdatalen && hdatalen != 32) {
|
||||||
PrintAndLogEx(ERR, "ERROR: application parameter length must be 32 bytes only.");
|
PrintAndLogEx(ERR, "ERROR: application parameter length must be 32 bytes only.");
|
||||||
return 1;
|
CLIParserFree(ctx);
|
||||||
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hdatalen)
|
if (hdatalen)
|
||||||
|
@ -530,7 +528,7 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
|
||||||
if (sw != 0x9000) {
|
if (sw != 0x9000) {
|
||||||
PrintAndLogEx(ERR, "Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
PrintAndLogEx(ERR, "Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||||
DropField();
|
DropField();
|
||||||
return 2;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = FIDOAuthentication(data, datalen, controlByte, buf, sizeof(buf), &len, &sw);
|
res = FIDOAuthentication(data, datalen, controlByte, buf, sizeof(buf), &len, &sw);
|
||||||
|
@ -542,7 +540,7 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
|
||||||
|
|
||||||
if (sw != 0x9000) {
|
if (sw != 0x9000) {
|
||||||
PrintAndLogEx(ERR, "ERROR execute authentication command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
PrintAndLogEx(ERR, "ERROR execute authentication command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||||
return 3;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "---------------------------------------------------------------");
|
PrintAndLogEx(NORMAL, "---------------------------------------------------------------");
|
||||||
|
@ -598,15 +596,15 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
|
||||||
res = json_dump_file(root, fname, JSON_INDENT(2));
|
res = json_dump_file(root, fname, JSON_INDENT(2));
|
||||||
if (res) {
|
if (res) {
|
||||||
PrintAndLogEx(ERR, "ERROR: can't save the file: %s", fname);
|
PrintAndLogEx(ERR, "ERROR: can't save the file: %s", fname);
|
||||||
return 200;
|
return PM3_EFILE;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(SUCCESS, "File " _YELLOW_("`%s`") " saved.", fname);
|
PrintAndLogEx(SUCCESS, "File " _YELLOW_("`%s`") " saved.", fname);
|
||||||
|
|
||||||
// free json object
|
// free json object
|
||||||
json_decref(root);
|
json_decref(root);
|
||||||
}
|
}
|
||||||
return 0;
|
return PM3_ESOFT;
|
||||||
};
|
}
|
||||||
|
|
||||||
static void CheckSlash(char *fileName) {
|
static void CheckSlash(char *fileName) {
|
||||||
if ((fileName[strlen(fileName) - 1] != '/') &&
|
if ((fileName[strlen(fileName) - 1] != '/') &&
|
||||||
|
@ -614,6 +612,7 @@ static void CheckSlash(char *fileName) {
|
||||||
strcat(fileName, "/");
|
strcat(fileName, "/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//iceman, todo: use searchfile..
|
||||||
static int GetExistsFileNameJson(const char *prefixDir, const char *reqestedFileName, char *fileName) {
|
static int GetExistsFileNameJson(const char *prefixDir, const char *reqestedFileName, char *fileName) {
|
||||||
fileName[0] = 0x00;
|
fileName[0] = 0x00;
|
||||||
strcpy(fileName, get_my_executable_directory());
|
strcpy(fileName, get_my_executable_directory());
|
||||||
|
@ -635,16 +634,15 @@ static int GetExistsFileNameJson(const char *prefixDir, const char *reqestedFile
|
||||||
strcat(fileName, ".json");
|
strcat(fileName, ".json");
|
||||||
|
|
||||||
if (access(fileName, F_OK) < 0) {
|
if (access(fileName, F_OK) < 0) {
|
||||||
return 1; // file not found
|
return PM3_EFILE; // file not found
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdHFFido2MakeCredential(const char *cmd) {
|
static int CmdHFFido2MakeCredential(const char *cmd) {
|
||||||
json_error_t error;
|
json_error_t error;
|
||||||
json_t *root = NULL;
|
char fname[FILE_PATH_SIZE] = {0};
|
||||||
char fname[300] = {0};
|
|
||||||
|
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf fido make",
|
CLIParserInit(&ctx, "hf fido make",
|
||||||
|
@ -669,7 +667,7 @@ static int CmdHFFido2MakeCredential(const char *cmd) {
|
||||||
bool showDERTLV = arg_get_lit(3);
|
bool showDERTLV = arg_get_lit(3);
|
||||||
bool showCBOR = arg_get_lit(4);
|
bool showCBOR = arg_get_lit(4);
|
||||||
|
|
||||||
uint8_t jsonname[250] = {0};
|
uint8_t jsonname[FILE_PATH_SIZE] = {0};
|
||||||
char *cjsonname = (char *)jsonname;
|
char *cjsonname = (char *)jsonname;
|
||||||
int jsonnamelen = 0;
|
int jsonnamelen = 0;
|
||||||
CLIGetStrWithReturn(ctx, 5, jsonname, &jsonnamelen);
|
CLIGetStrWithReturn(ctx, 5, jsonname, &jsonnamelen);
|
||||||
|
@ -684,15 +682,15 @@ static int CmdHFFido2MakeCredential(const char *cmd) {
|
||||||
SetAPDULogging(APDULogging);
|
SetAPDULogging(APDULogging);
|
||||||
|
|
||||||
int res = GetExistsFileNameJson("fido", cjsonname, fname);
|
int res = GetExistsFileNameJson("fido", cjsonname, fname);
|
||||||
if (res) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "ERROR: Can't found the json file.");
|
PrintAndLogEx(ERR, "ERROR: Can't found the json file.");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "fname: %s\n", fname);
|
PrintAndLogEx(NORMAL, "fname: %s\n", fname);
|
||||||
root = json_load_file(fname, 0, &error);
|
json_t *root = json_load_file(fname, 0, &error);
|
||||||
if (!root) {
|
if (!root) {
|
||||||
PrintAndLogEx(ERR, "ERROR: json error on line %d: %s", error.line, error.text);
|
PrintAndLogEx(ERR, "ERROR: json error on line %d: %s", error.line, error.text);
|
||||||
return 1;
|
return PM3_EFILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t data[2048] = {0};
|
uint8_t data[2048] = {0};
|
||||||
|
@ -703,7 +701,6 @@ static int CmdHFFido2MakeCredential(const char *cmd) {
|
||||||
|
|
||||||
DropField();
|
DropField();
|
||||||
res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw);
|
res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw);
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
PrintAndLogEx(ERR, "Can't select authenticator. res=%x. Exit...", res);
|
PrintAndLogEx(ERR, "Can't select authenticator. res=%x. Exit...", res);
|
||||||
DropField();
|
DropField();
|
||||||
|
@ -713,7 +710,7 @@ static int CmdHFFido2MakeCredential(const char *cmd) {
|
||||||
if (sw != 0x9000) {
|
if (sw != 0x9000) {
|
||||||
PrintAndLogEx(ERR, "Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
PrintAndLogEx(ERR, "Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||||
DropField();
|
DropField();
|
||||||
return 2;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = FIDO2CreateMakeCredentionalReq(root, data, sizeof(data), &datalen);
|
res = FIDO2CreateMakeCredentionalReq(root, data, sizeof(data), &datalen);
|
||||||
|
@ -722,9 +719,9 @@ static int CmdHFFido2MakeCredential(const char *cmd) {
|
||||||
|
|
||||||
if (showCBOR) {
|
if (showCBOR) {
|
||||||
PrintAndLogEx(INFO, "CBOR make credential request:");
|
PrintAndLogEx(INFO, "CBOR make credential request:");
|
||||||
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
|
PrintAndLogEx(INFO, "---------------- " _CYAN_("CBOR") " ------------------");
|
||||||
TinyCborPrintFIDOPackage(fido2CmdMakeCredential, false, data, datalen);
|
TinyCborPrintFIDOPackage(fido2CmdMakeCredential, false, data, datalen);
|
||||||
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
|
PrintAndLogEx(INFO, "---------------- " _CYAN_("CBOR") " ------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
res = FIDO2MakeCredential(data, datalen, buf, sizeof(buf), &len, &sw);
|
res = FIDO2MakeCredential(data, datalen, buf, sizeof(buf), &len, &sw);
|
||||||
|
@ -736,20 +733,20 @@ static int CmdHFFido2MakeCredential(const char *cmd) {
|
||||||
|
|
||||||
if (sw != 0x9000) {
|
if (sw != 0x9000) {
|
||||||
PrintAndLogEx(ERR, "ERROR execute make credential command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
PrintAndLogEx(ERR, "ERROR execute make credential command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||||
return 3;
|
return PM3_EFILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[0]) {
|
if (buf[0]) {
|
||||||
PrintAndLogEx(ERR, "FIDO2 make credential error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
|
PrintAndLogEx(ERR, "FIDO2 make credential error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "MakeCredential result (%zu b) OK.", len);
|
PrintAndLogEx(SUCCESS, "MakeCredential result (%zu b) OK.", len);
|
||||||
if (showCBOR) {
|
if (showCBOR) {
|
||||||
PrintAndLogEx(SUCCESS, "CBOR make credential response:");
|
PrintAndLogEx(SUCCESS, "CBOR make credential response:");
|
||||||
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
|
PrintAndLogEx(INFO, "---------------- " _CYAN_("CBOR") " ------------------");
|
||||||
TinyCborPrintFIDOPackage(fido2CmdMakeCredential, true, &buf[1], len - 1);
|
TinyCborPrintFIDOPackage(fido2CmdMakeCredential, true, &buf[1], len - 1);
|
||||||
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
|
PrintAndLogEx(INFO, "---------------- " _CYAN_("CBOR") " ------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse returned cbor
|
// parse returned cbor
|
||||||
|
@ -759,19 +756,18 @@ static int CmdHFFido2MakeCredential(const char *cmd) {
|
||||||
res = json_dump_file(root, fname, JSON_INDENT(2));
|
res = json_dump_file(root, fname, JSON_INDENT(2));
|
||||||
if (res) {
|
if (res) {
|
||||||
PrintAndLogEx(ERR, "ERROR: can't save the file: %s", fname);
|
PrintAndLogEx(ERR, "ERROR: can't save the file: %s", fname);
|
||||||
return 200;
|
return PM3_EFILE;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(SUCCESS, "File " _YELLOW_("`%s`") " saved.", fname);
|
PrintAndLogEx(SUCCESS, "File " _YELLOW_("`%s`") " saved.", fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
json_decref(root);
|
json_decref(root);
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
};
|
}
|
||||||
|
|
||||||
static int CmdHFFido2GetAssertion(const char *cmd) {
|
static int CmdHFFido2GetAssertion(const char *cmd) {
|
||||||
json_error_t error;
|
json_error_t error;
|
||||||
json_t *root = NULL;
|
char fname[FILE_PATH_SIZE] = {0};
|
||||||
char fname[300] = {0};
|
|
||||||
|
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf fido assert",
|
CLIParserInit(&ctx, "hf fido assert",
|
||||||
|
@ -796,7 +792,7 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
|
||||||
bool showCBOR = arg_get_lit(3);
|
bool showCBOR = arg_get_lit(3);
|
||||||
bool createAllowList = arg_get_lit(4);
|
bool createAllowList = arg_get_lit(4);
|
||||||
|
|
||||||
uint8_t jsonname[250] = {0};
|
uint8_t jsonname[FILE_PATH_SIZE] = {0};
|
||||||
char *cjsonname = (char *)jsonname;
|
char *cjsonname = (char *)jsonname;
|
||||||
int jsonnamelen = 0;
|
int jsonnamelen = 0;
|
||||||
CLIGetStrWithReturn(ctx, 5, jsonname, &jsonnamelen);
|
CLIGetStrWithReturn(ctx, 5, jsonname, &jsonnamelen);
|
||||||
|
@ -811,15 +807,15 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
|
||||||
SetAPDULogging(APDULogging);
|
SetAPDULogging(APDULogging);
|
||||||
|
|
||||||
int res = GetExistsFileNameJson("fido", cjsonname, fname);
|
int res = GetExistsFileNameJson("fido", cjsonname, fname);
|
||||||
if (res) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "ERROR: Can't found the json file.");
|
PrintAndLogEx(ERR, "ERROR: Can't found the json file.");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "fname: %s\n", fname);
|
PrintAndLogEx(NORMAL, "fname: %s\n", fname);
|
||||||
root = json_load_file(fname, 0, &error);
|
json_t *root = json_load_file(fname, 0, &error);
|
||||||
if (!root) {
|
if (!root) {
|
||||||
PrintAndLogEx(ERR, "ERROR: json error on line %d: %s", error.line, error.text);
|
PrintAndLogEx(ERR, "ERROR: json error on line %d: %s", error.line, error.text);
|
||||||
return 1;
|
return PM3_EFILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t data[2048] = {0};
|
uint8_t data[2048] = {0};
|
||||||
|
@ -830,9 +826,8 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
|
||||||
|
|
||||||
DropField();
|
DropField();
|
||||||
res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw);
|
res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw);
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
PrintAndLogEx(ERR, "Can't select authenticator. res=%x. Exit...", res);
|
PrintAndLogEx(ERR, "Can't select authenticator. res=%x. exiting...", res);
|
||||||
DropField();
|
DropField();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -840,7 +835,7 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
|
||||||
if (sw != 0x9000) {
|
if (sw != 0x9000) {
|
||||||
PrintAndLogEx(ERR, "Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
PrintAndLogEx(ERR, "Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||||
DropField();
|
DropField();
|
||||||
return 2;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = FIDO2CreateGetAssertionReq(root, data, sizeof(data), &datalen, createAllowList);
|
res = FIDO2CreateGetAssertionReq(root, data, sizeof(data), &datalen, createAllowList);
|
||||||
|
@ -849,9 +844,9 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
|
||||||
|
|
||||||
if (showCBOR) {
|
if (showCBOR) {
|
||||||
PrintAndLogEx(SUCCESS, "CBOR get assertion request:");
|
PrintAndLogEx(SUCCESS, "CBOR get assertion request:");
|
||||||
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
|
PrintAndLogEx(NORMAL, "---------------- " _CYAN_("CBOR") " ------------------");
|
||||||
TinyCborPrintFIDOPackage(fido2CmdGetAssertion, false, data, datalen);
|
TinyCborPrintFIDOPackage(fido2CmdGetAssertion, false, data, datalen);
|
||||||
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
|
PrintAndLogEx(NORMAL, "---------------- " _CYAN_("CBOR") " ------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
res = FIDO2GetAssertion(data, datalen, buf, sizeof(buf), &len, &sw);
|
res = FIDO2GetAssertion(data, datalen, buf, sizeof(buf), &len, &sw);
|
||||||
|
@ -863,20 +858,20 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
|
||||||
|
|
||||||
if (sw != 0x9000) {
|
if (sw != 0x9000) {
|
||||||
PrintAndLogEx(ERR, "ERROR execute get assertion command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
PrintAndLogEx(ERR, "ERROR execute get assertion command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||||
return 3;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[0]) {
|
if (buf[0]) {
|
||||||
PrintAndLogEx(ERR, "FIDO2 get assertion error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
|
PrintAndLogEx(ERR, "FIDO2 get assertion error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
|
||||||
return 0;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "GetAssertion result (%zu b) OK.", len);
|
PrintAndLogEx(SUCCESS, "GetAssertion result (%zu b) OK.", len);
|
||||||
if (showCBOR) {
|
if (showCBOR) {
|
||||||
PrintAndLogEx(SUCCESS, "CBOR get assertion response:");
|
PrintAndLogEx(SUCCESS, "CBOR get assertion response:");
|
||||||
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
|
PrintAndLogEx(NORMAL, "---------------- " _CYAN_("CBOR") " ------------------");
|
||||||
TinyCborPrintFIDOPackage(fido2CmdGetAssertion, true, &buf[1], len - 1);
|
TinyCborPrintFIDOPackage(fido2CmdGetAssertion, true, &buf[1], len - 1);
|
||||||
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
|
PrintAndLogEx(NORMAL, "---------------- " _CYAN_("CBOR") " ------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse returned cbor
|
// parse returned cbor
|
||||||
|
@ -886,32 +881,32 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
|
||||||
res = json_dump_file(root, fname, JSON_INDENT(2));
|
res = json_dump_file(root, fname, JSON_INDENT(2));
|
||||||
if (res) {
|
if (res) {
|
||||||
PrintAndLogEx(ERR, "ERROR: can't save the file: %s", fname);
|
PrintAndLogEx(ERR, "ERROR: can't save the file: %s", fname);
|
||||||
return 200;
|
return PM3_EFILE;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(SUCCESS, "File " _YELLOW_("`%s`") " saved.", fname);
|
PrintAndLogEx(SUCCESS, "File " _YELLOW_("`%s`") " saved.", fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
json_decref(root);
|
json_decref(root);
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
};
|
}
|
||||||
|
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help."},
|
{"help", CmdHelp, AlwaysAvailable, "This help."},
|
||||||
{"info", CmdHFFidoInfo, IfPm3Iso14443a, "Info about FIDO tag."},
|
{"info", CmdHFFidoInfo, IfPm3Iso14443a, "Info about FIDO tag."},
|
||||||
{"reg", CmdHFFidoRegister, IfPm3Iso14443a, "FIDO U2F Registration Message."},
|
{"reg", CmdHFFidoRegister, IfPm3Iso14443a, "FIDO U2F Registration Message."},
|
||||||
{"auth", CmdHFFidoAuthenticate, IfPm3Iso14443a, "FIDO U2F Authentication Message."},
|
{"auth", CmdHFFidoAuthenticate, IfPm3Iso14443a, "FIDO U2F Authentication Message."},
|
||||||
{"make", CmdHFFido2MakeCredential, IfPm3Iso14443a, "FIDO2 MakeCredential command."},
|
{"make", CmdHFFido2MakeCredential, IfPm3Iso14443a, "FIDO2 MakeCredential command."},
|
||||||
{"assert", CmdHFFido2GetAssertion, IfPm3Iso14443a, "FIDO2 GetAssertion command."},
|
{"assert", CmdHFFido2GetAssertion, IfPm3Iso14443a, "FIDO2 GetAssertion command."},
|
||||||
{NULL, NULL, 0, NULL}
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
int CmdHFFido(const char *Cmd) {
|
int CmdHFFido(const char *Cmd) {
|
||||||
(void)WaitForResponseTimeout(CMD_ACK, NULL, 100);
|
clearCommandBuffer();
|
||||||
return CmdsParse(CommandTable, Cmd);
|
return CmdsParse(CommandTable, Cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdHelp(const char *Cmd) {
|
int CmdHelp(const char *Cmd) {
|
||||||
(void)Cmd; // Cmd is not used so far
|
(void)Cmd; // Cmd is not used so far
|
||||||
CmdsHelp(CommandTable);
|
CmdsHelp(CommandTable);
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue