diff --git a/client/cmdhffido.c b/client/cmdhffido.c index a5ad55536..13fc0eaf8 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -36,7 +36,6 @@ #include "util.h" #include "ui.h" #include "proxmark3.h" -#include "cmdhf14a.h" #include "mifare.h" #include "emv/emvcore.h" #include "emv/emvjson.h" @@ -50,57 +49,6 @@ static int CmdHelp(const char *Cmd); -int FIDOSelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - uint8_t data[] = {0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01}; - - return EMVSelect(ActivateField, LeaveFieldON, data, sizeof(data), Result, MaxResultLen, ResultLen, sw, NULL); -} - -int FIDOExchange(sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - int res = EMVExchange(true, apdu, Result, MaxResultLen, ResultLen, sw, NULL); - if (res == 5) // apdu result (sw) not a 0x9000 - res = 0; - // software chaining - while (!res && (*sw >> 8) == 0x61) { - size_t oldlen = *ResultLen; - res = EMVExchange(true, (sAPDU){0x00, 0xC0, 0x00, 0x00, 0x00, NULL}, &Result[oldlen], MaxResultLen - oldlen, ResultLen, sw, NULL); - if (res == 5) // apdu result (sw) not a 0x9000 - res = 0; - - *ResultLen += oldlen; - if (*ResultLen > MaxResultLen) - return 100; - } - return res; -} - -int FIDORegister(uint8_t *params, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - return FIDOExchange((sAPDU){0x00, 0x01, 0x03, 0x00, 64, params}, Result, MaxResultLen, ResultLen, sw); -} - -int FIDOAuthentication(uint8_t *params, uint8_t paramslen, uint8_t controlb, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - return FIDOExchange((sAPDU){0x00, 0x02, controlb, 0x00, paramslen, params}, Result, MaxResultLen, ResultLen, sw); -} - -int FIDO2GetInfo(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - uint8_t data[] = {fido2CmdGetInfo}; - return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); -} - -int FIDO2MakeCredential(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - uint8_t data[paramslen + 1]; - data[0] = fido2CmdMakeCredential; - memcpy(&data[1], params, paramslen); - return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); -} - -int FIDO2GetAssertion(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - uint8_t data[paramslen + 1]; - data[0] = fido2CmdGetAssertion; - memcpy(&data[1], params, paramslen); - return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); -} - int CmdHFFidoInfo(const char *cmd) { if (cmd && strlen(cmd) > 0) @@ -754,15 +702,13 @@ int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileNam } int CmdHFFido2MakeCredential(const char *cmd) { - - json_error_t error; json_t *root = NULL; char fname[300] = {0}; int res = GetExistsFileNameJson("fido", "fido2", fname); if(res) { - PrintAndLog("ERROR: Can't found json file."); + PrintAndLog("ERROR: Can't found the json file."); return res; } PrintAndLog("fname: %s\n", fname); @@ -793,6 +739,13 @@ int CmdHFFido2MakeCredential(const char *cmd) { return 2; } + res = FIDO2CreateMakeCredentionalReq(root, data, sizeof(data), &datalen); + if (res) + return res; + + PrintAndLog("CBOR make credentional request:"); + TinyCborPrintFIDOPackage(fido2CmdMakeCredential, data, datalen); + res = FIDO2MakeCredential(data, datalen, buf, sizeof(buf), &len, &sw); DropField(); if (res) { @@ -810,7 +763,11 @@ int CmdHFFido2MakeCredential(const char *cmd) { return 0; } - PrintAndLog("res[%d]: %s", len, sprint_hex(buf, len)); + PrintAndLog("MakeCredential result (%d) OK.", len); + PrintAndLog("CBOR make credentional response:"); + TinyCborPrintFIDOPackage(fido2CmdMakeCredential, &buf[1], len - 1); + + json_decref(root); return 0; }; diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 1b41d2722..0e4099a88 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -11,6 +11,10 @@ // #include "fidocore.h" +#include "emv/emvcore.h" +#include "emv/emvjson.h" +#include +#include "cbortools.h" typedef struct { uint8_t ErrorCode; @@ -122,3 +126,156 @@ char *fido2GetCmdMemberDescription(uint8_t cmdCode, uint8_t memberNum) { return NULL; } +int FIDOSelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + uint8_t data[] = {0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01}; + + return EMVSelect(ActivateField, LeaveFieldON, data, sizeof(data), Result, MaxResultLen, ResultLen, sw, NULL); +} + +int FIDOExchange(sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + int res = EMVExchange(true, apdu, Result, MaxResultLen, ResultLen, sw, NULL); + if (res == 5) // apdu result (sw) not a 0x9000 + res = 0; + // software chaining + while (!res && (*sw >> 8) == 0x61) { + size_t oldlen = *ResultLen; + res = EMVExchange(true, (sAPDU){0x00, 0xC0, 0x00, 0x00, 0x00, NULL}, &Result[oldlen], MaxResultLen - oldlen, ResultLen, sw, NULL); + if (res == 5) // apdu result (sw) not a 0x9000 + res = 0; + + *ResultLen += oldlen; + if (*ResultLen > MaxResultLen) + return 100; + } + return res; +} + +int FIDORegister(uint8_t *params, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + return FIDOExchange((sAPDU){0x00, 0x01, 0x03, 0x00, 64, params}, Result, MaxResultLen, ResultLen, sw); +} + +int FIDOAuthentication(uint8_t *params, uint8_t paramslen, uint8_t controlb, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + return FIDOExchange((sAPDU){0x00, 0x02, controlb, 0x00, paramslen, params}, Result, MaxResultLen, ResultLen, sw); +} + +int FIDO2GetInfo(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + uint8_t data[] = {fido2CmdGetInfo}; + return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); +} + +int FIDO2MakeCredential(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + uint8_t data[paramslen + 1]; + data[0] = fido2CmdMakeCredential; + memcpy(&data[1], params, paramslen); + return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); +} + +int FIDO2GetAssertion(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + uint8_t data[paramslen + 1]; + data[0] = fido2CmdGetAssertion; + memcpy(&data[1], params, paramslen); + return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); +} + +#define fido_check_if(r) if ((r) != CborNoError) {return r;} else +#define fido_check(r) if ((r) != CborNoError) return r; + +int CBOREncodeClientDataHash(json_t *root, CborEncoder *encoder) { + uint8_t buf[100] = {0}; + size_t jlen; + + JsonLoadBufAsHex(root, "$.ClientDataHash", buf, sizeof(buf), &jlen); + + // fill with 0x00 if not found + if (!jlen) + jlen = 32; + + int res = cbor_encode_byte_string(encoder, buf, jlen); + fido_check(res); + + return 0; +} + +int CBOREncodeRp(json_t *root, CborEncoder *encoder) { + json_t *elm = json_object_get(root, "RelyingPartyEntity"); + if (!elm) + return 1; + + JsonToCbor(elm, encoder); + + return 0; +} + +int CBOREncodeUser(json_t *root, CborEncoder *encoder) { + json_t *elm = json_object_get(root, "UserEntity"); + if (!elm) + return 1; + + JsonToCbor(elm, encoder); + + return 0; +} + +int CBOREncodePubKeyParams(json_t *root, CborEncoder *encoder) { + json_t *elm = json_object_get(root, "pubKeyCredParams"); + if (!elm) + return 1; + + JsonToCbor(elm, encoder); + + return 0; +} + +int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen) { + if (datalen) + *datalen = 0; + if (!root || !data || !maxdatalen) + return 1; + + int res; + CborEncoder encoder; + CborEncoder map; + + cbor_encoder_init(&encoder, data, maxdatalen, 0); + + // create main map + res = cbor_encoder_create_map(&encoder, &map, 4); + fido_check_if(res) { + // clientDataHash + res = cbor_encode_uint(&map, 1); + fido_check_if(res) { + res = CBOREncodeClientDataHash(root, &map); + fido_check(res); + } + + // rp + res = cbor_encode_uint(&map, 2); + fido_check_if(res) { + res = CBOREncodeRp(root, &map); + fido_check(res); + } + + // user + res = cbor_encode_uint(&map, 3); + fido_check_if(res) { + res = CBOREncodeUser(root, &map); + fido_check(res); + } + + // pubKeyCredParams + res = cbor_encode_uint(&map, 4); + fido_check_if(res) { + res = CBOREncodePubKeyParams(root, &map); + fido_check(res); + } + + } + res = cbor_encoder_close_container(&encoder, &map); + fido_check(res); + + size_t len = cbor_encoder_get_buffer_size(&encoder, data); + if (datalen) + *datalen = len; + + return 0; +} diff --git a/client/fido/fidocore.h b/client/fido/fidocore.h index 1ed5556cf..d16c42190 100644 --- a/client/fido/fidocore.h +++ b/client/fido/fidocore.h @@ -14,6 +14,8 @@ #include #include +#include +#include "cmdhf14a.h" typedef enum { fido2CmdMakeCredential = 0x01, @@ -30,7 +32,17 @@ typedef enum { ptResponse, } fido2PacketType; +extern int FIDOSelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +extern int FIDOExchange(sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +extern int FIDORegister(uint8_t *params, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +extern int FIDOAuthentication(uint8_t *params, uint8_t paramslen, uint8_t controlb, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +extern int FIDO2GetInfo(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +extern int FIDO2MakeCredential(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +extern int FIDO2GetAssertion(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); + extern char *fido2GetCmdMemberDescription(uint8_t cmdCode, uint8_t memberNum); extern char *fido2GetCmdErrorDescription(uint8_t errorCode); +extern int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen); + #endif /* __FIDOCORE_H__ */