mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
Merge pull request #1468 from merlokk/lrp_read
Lrp data read/write commands
This commit is contained in:
commit
f6cee14f14
6 changed files with 187 additions and 99 deletions
|
@ -3952,7 +3952,9 @@ static int CmdHF14ADesCreateTrMACFile(const char *Cmd) {
|
||||||
"\n"
|
"\n"
|
||||||
"hf mfdes createmacfile --aid 123456 --fid 01 --rawrights 0FF0 --mackey 00112233445566778899aabbccddeeff --mackeyver 01 -> create transaction mac file with parameters. Rights from default. Authentication with defaults from `default` command\n"
|
"hf mfdes createmacfile --aid 123456 --fid 01 --rawrights 0FF0 --mackey 00112233445566778899aabbccddeeff --mackeyver 01 -> create transaction mac file with parameters. Rights from default. Authentication with defaults from `default` command\n"
|
||||||
"hf mfdes createmacfile --aid 123456 --fid 01 --amode plain --rrights free --wrights deny --rwrights free --chrights key0 --mackey 00112233445566778899aabbccddeeff -> create file app=123456, file=01, with key, and mentioned rights with defaults from `default` command\n"
|
"hf mfdes createmacfile --aid 123456 --fid 01 --amode plain --rrights free --wrights deny --rwrights free --chrights key0 --mackey 00112233445566778899aabbccddeeff -> create file app=123456, file=01, with key, and mentioned rights with defaults from `default` command\n"
|
||||||
"hf mfdes createmacfile -n 0 -t des -k 0000000000000000 -f none --aid 123456 --fid 01 -> execute with default factory setup. key and keyver == 0x00..00");
|
"hf mfdes createmacfile -n 0 -t des -k 0000000000000000 -f none --aid 123456 --fid 01 -> execute with default factory setup. key and keyver == 0x00..00\n"
|
||||||
|
"hf mfdes createmacfile --appisoid df01 --fid 0f -s lrp -t aes --rawrights 0FF0 --mackey 00112233445566778899aabbccddeeff --mackeyver 01 -> create transaction mac file via lrp channel\n"
|
||||||
|
"hf mfdes createmacfile --appisoid df01 --fid 0f -s lrp -t aes --rawrights 0F10 --mackey 00112233445566778899aabbccddeeff --mackeyver 01 -> create transaction mac file via lrp channel with CommitReaderID command enable");
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
|
@ -3967,6 +3969,7 @@ static int CmdHF14ADesCreateTrMACFile(const char *Cmd) {
|
||||||
arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"),
|
arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"),
|
||||||
arg_str0("s", "schann", "<d40/ev1/ev2/lrp>", "Secure channel: d40/ev1/ev2/lrp"),
|
arg_str0("s", "schann", "<d40/ev1/ev2/lrp>", "Secure channel: d40/ev1/ev2/lrp"),
|
||||||
arg_str0(NULL, "aid", "<app id hex>", "Application ID (3 hex bytes, big endian)"),
|
arg_str0(NULL, "aid", "<app id hex>", "Application ID (3 hex bytes, big endian)"),
|
||||||
|
arg_str0(NULL, "appisoid", "<isoid hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."),
|
||||||
arg_str0(NULL, "fid", "<file id hex>", "File ID (1 hex byte)"),
|
arg_str0(NULL, "fid", "<file id hex>", "File ID (1 hex byte)"),
|
||||||
arg_str0(NULL, "amode", "<plain/mac/encrypt>", "File access mode: plain/mac/encrypt"),
|
arg_str0(NULL, "amode", "<plain/mac/encrypt>", "File access mode: plain/mac/encrypt"),
|
||||||
arg_str0(NULL, "rawrights", "<access rights HEX>", "Access rights for file (HEX 2 byte) R/W/RW/Chg, 0x0 - 0xD Key, 0xE Free, 0xF Denied"),
|
arg_str0(NULL, "rawrights", "<access rights HEX>", "Access rights for file (HEX 2 byte) R/W/RW/Chg, 0x0 - 0xD Key, 0xE Free, 0xF Denied"),
|
||||||
|
@ -3983,20 +3986,21 @@ static int CmdHF14ADesCreateTrMACFile(const char *Cmd) {
|
||||||
|
|
||||||
bool APDULogging = arg_get_lit(ctx, 1);
|
bool APDULogging = arg_get_lit(ctx, 1);
|
||||||
bool verbose = arg_get_lit(ctx, 2);
|
bool verbose = arg_get_lit(ctx, 2);
|
||||||
bool noauth = arg_get_lit(ctx, 19);
|
bool noauth = arg_get_lit(ctx, 20);
|
||||||
|
|
||||||
uint8_t filetype = 0x05; // transaction mac file
|
uint8_t filetype = 0x05; // transaction mac file
|
||||||
|
|
||||||
DesfireContext dctx;
|
DesfireContext dctx;
|
||||||
int securechann = defaultSecureChannel;
|
int securechann = defaultSecureChannel;
|
||||||
uint32_t appid = 0x000000;
|
uint32_t id = 0x000000;
|
||||||
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMEncrypted, &appid, NULL);
|
DesfireISOSelectWay selectway = ISW6bAID;
|
||||||
|
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMEncrypted, &id, &selectway);
|
||||||
if (res) {
|
if (res) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appid == 0x000000) {
|
if (DesfireMFSelected(selectway, id)) {
|
||||||
PrintAndLogEx(ERR, "Can't create files at card level.");
|
PrintAndLogEx(ERR, "Can't create files at card level.");
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
|
@ -4005,7 +4009,7 @@ static int CmdHF14ADesCreateTrMACFile(const char *Cmd) {
|
||||||
uint8_t data[250] = {0};
|
uint8_t data[250] = {0};
|
||||||
size_t datalen = 0;
|
size_t datalen = 0;
|
||||||
|
|
||||||
res = DesfireCreateFileParameters(ctx, 12, 0, 13, 14, 15, 16, 17, 18, data, &datalen);
|
res = DesfireCreateFileParameters(ctx, 13, 0, 14, 15, 16, 17, 18, 19, data, &datalen);
|
||||||
if (res) {
|
if (res) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return res;
|
return res;
|
||||||
|
@ -4013,7 +4017,7 @@ static int CmdHF14ADesCreateTrMACFile(const char *Cmd) {
|
||||||
|
|
||||||
uint8_t sdata[250] = {0};
|
uint8_t sdata[250] = {0};
|
||||||
int sdatalen = sizeof(sdata);
|
int sdatalen = sizeof(sdata);
|
||||||
CLIGetHexWithReturn(ctx, 20, sdata, &sdatalen);
|
CLIGetHexWithReturn(ctx, 21, sdata, &sdatalen);
|
||||||
if (sdatalen != 0 && sdatalen != 16) {
|
if (sdatalen != 0 && sdatalen != 16) {
|
||||||
PrintAndLogEx(ERR, "AES-128 key must be 16 bytes instead of %d.", sdatalen);
|
PrintAndLogEx(ERR, "AES-128 key must be 16 bytes instead of %d.", sdatalen);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
@ -4021,7 +4025,7 @@ static int CmdHF14ADesCreateTrMACFile(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t keyver = 0x00;
|
uint32_t keyver = 0x00;
|
||||||
if (CLIGetUint32Hex(ctx, 21, 0x00, &keyver, NULL, 1, "Key version must have 1 bytes length")) {
|
if (CLIGetUint32Hex(ctx, 22, 0x00, &keyver, NULL, 1, "Key version must have 1 bytes length")) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
@ -4037,16 +4041,17 @@ static int CmdHF14ADesCreateTrMACFile(const char *Cmd) {
|
||||||
data[datalen] = keyver & 0xff;
|
data[datalen] = keyver & 0xff;
|
||||||
datalen++;
|
datalen++;
|
||||||
|
|
||||||
res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, noauth, verbose);
|
res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
DropField();
|
DropField();
|
||||||
|
PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(INFO, "App: %06x. File num: 0x%02x type: 0x%02x data[%zu]: %s", appid, data[0], filetype, datalen, sprint_hex(data, datalen));
|
PrintAndLogEx(INFO, "%s. File num: 0x%02x type: 0x%02x data[%zu]: %s", DesfireWayIDStr(selectway, id), data[0], filetype, datalen, sprint_hex(data, datalen));
|
||||||
DesfirePrintCreateFileSettings(filetype, data, datalen);
|
|
||||||
|
|
||||||
|
DesfirePrintCreateFileSettings(filetype, data, datalen);
|
||||||
|
|
||||||
res = DesfireCreateFile(&dctx, filetype, data, datalen, true);
|
res = DesfireCreateFile(&dctx, filetype, data, datalen, true);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
|
@ -4055,7 +4060,7 @@ static int CmdHF14ADesCreateTrMACFile(const char *Cmd) {
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "%s file %02x in the app %06x created " _GREEN_("successfully"), GetDesfireFileType(filetype), data[0], appid);
|
PrintAndLogEx(SUCCESS, "%s file %02x in the %s created " _GREEN_("successfully"), GetDesfireFileType(filetype), data[0], DesfireWayIDStr(selectway, id));
|
||||||
|
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
|
@ -4065,7 +4070,8 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf mfdes deletefile",
|
CLIParserInit(&ctx, "hf mfdes deletefile",
|
||||||
"Delete file from application. Master key needs to be provided or flag --no-auth set (depend on cards settings).",
|
"Delete file from application. Master key needs to be provided or flag --no-auth set (depend on cards settings).",
|
||||||
"hf mfdes deletefile --aid 123456 --fid 01 -> delete file for: app=123456, file=01 with defaults from `default` command");
|
"hf mfdes deletefile --aid 123456 --fid 01 -> delete file for: app=123456, file=01 with defaults from `default` command\n"
|
||||||
|
"hf mfdes deletefile --appisoid df01 --fid 0f -s lrp -t aes -> delete file for lrp channel");
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
|
@ -4080,6 +4086,7 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) {
|
||||||
arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"),
|
arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"),
|
||||||
arg_str0("s", "schann", "<d40/ev1/ev2/lrp>", "Secure channel: d40/ev1/ev2/lrp"),
|
arg_str0("s", "schann", "<d40/ev1/ev2/lrp>", "Secure channel: d40/ev1/ev2/lrp"),
|
||||||
arg_str0(NULL, "aid", "<app id hex>", "Application ID (3 hex bytes, big endian)"),
|
arg_str0(NULL, "aid", "<app id hex>", "Application ID (3 hex bytes, big endian)"),
|
||||||
|
arg_str0(NULL, "appisoid", "<isoid hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."),
|
||||||
arg_str0(NULL, "fid", "<file id hex>", "File ID (1 hex byte)"),
|
arg_str0(NULL, "fid", "<file id hex>", "File ID (1 hex byte)"),
|
||||||
arg_lit0(NULL, "no-auth", "execute without authentication"),
|
arg_lit0(NULL, "no-auth", "execute without authentication"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
|
@ -4088,19 +4095,20 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) {
|
||||||
|
|
||||||
bool APDULogging = arg_get_lit(ctx, 1);
|
bool APDULogging = arg_get_lit(ctx, 1);
|
||||||
bool verbose = arg_get_lit(ctx, 2);
|
bool verbose = arg_get_lit(ctx, 2);
|
||||||
bool noauth = arg_get_lit(ctx, 13);
|
bool noauth = arg_get_lit(ctx, 14);
|
||||||
|
|
||||||
DesfireContext dctx;
|
DesfireContext dctx;
|
||||||
int securechann = defaultSecureChannel;
|
int securechann = defaultSecureChannel;
|
||||||
uint32_t appid = 0x000000;
|
uint32_t id = 0x000000;
|
||||||
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL);
|
DesfireISOSelectWay selectway = ISW6bAID;
|
||||||
|
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway);
|
||||||
if (res) {
|
if (res) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t fnum = 1;
|
uint32_t fnum = 1;
|
||||||
if (CLIGetUint32Hex(ctx, 12, 1, &fnum, NULL, 1, "File ID must have 1 byte length")) {
|
if (CLIGetUint32Hex(ctx, 13, 1, &fnum, NULL, 1, "File ID must have 1 byte length")) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
@ -4113,9 +4121,10 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, noauth, verbose);
|
res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
DropField();
|
DropField();
|
||||||
|
PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4126,7 +4135,7 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) {
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "File %02x in the app %06x deleted " _GREEN_("successfully"), fnum, appid);
|
PrintAndLogEx(SUCCESS, "File %02x in the %s deleted " _GREEN_("successfully"), fnum, DesfireWayIDStr(selectway, id));
|
||||||
|
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
|
@ -4153,6 +4162,7 @@ static int CmdHF14ADesValueOperations(const char *Cmd) {
|
||||||
arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"),
|
arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"),
|
||||||
arg_str0("s", "schann", "<d40/ev1/ev2/lrp>", "Secure channel: d40/ev1/ev2/lrp"),
|
arg_str0("s", "schann", "<d40/ev1/ev2/lrp>", "Secure channel: d40/ev1/ev2/lrp"),
|
||||||
arg_str0(NULL, "aid", "<app id hex>", "Application ID (3 hex bytes, big endian)"),
|
arg_str0(NULL, "aid", "<app id hex>", "Application ID (3 hex bytes, big endian)"),
|
||||||
|
arg_str0(NULL, "appisoid", "<isoid hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."),
|
||||||
arg_str0(NULL, "fid", "<file id hex>", "File ID (1 hex byte)"),
|
arg_str0(NULL, "fid", "<file id hex>", "File ID (1 hex byte)"),
|
||||||
arg_str0("o", "op", "<get/credit/limcredit/debit/clear>", "Operation: get(default)/credit/limcredit(limited credit)/debit/clear. Operation clear: get-getopt-debit to min value"),
|
arg_str0("o", "op", "<get/credit/limcredit/debit/clear>", "Operation: get(default)/credit/limcredit(limited credit)/debit/clear. Operation clear: get-getopt-debit to min value"),
|
||||||
arg_str0("d", "data", "<value HEX>", "Value for operation (HEX 4 bytes)"),
|
arg_str0("d", "data", "<value HEX>", "Value for operation (HEX 4 bytes)"),
|
||||||
|
@ -4163,31 +4173,32 @@ static int CmdHF14ADesValueOperations(const char *Cmd) {
|
||||||
|
|
||||||
bool APDULogging = arg_get_lit(ctx, 1);
|
bool APDULogging = arg_get_lit(ctx, 1);
|
||||||
bool verbose = arg_get_lit(ctx, 2);
|
bool verbose = arg_get_lit(ctx, 2);
|
||||||
bool noauth = arg_get_lit(ctx, 15);
|
bool noauth = arg_get_lit(ctx, 16);
|
||||||
|
|
||||||
DesfireContext dctx;
|
DesfireContext dctx;
|
||||||
int securechann = defaultSecureChannel;
|
int securechann = defaultSecureChannel;
|
||||||
uint32_t appid = 0x000000;
|
uint32_t id = 0x000000;
|
||||||
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL);
|
DesfireISOSelectWay selectway = ISW6bAID;
|
||||||
|
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway);
|
||||||
if (res) {
|
if (res) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t fileid = 1;
|
uint32_t fileid = 1;
|
||||||
if (CLIGetUint32Hex(ctx, 12, 1, &fileid, NULL, 1, "File ID must have 1 byte length")) {
|
if (CLIGetUint32Hex(ctx, 13, 1, &fileid, NULL, 1, "File ID must have 1 byte length")) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
int op = MFDES_GET_VALUE;
|
int op = MFDES_GET_VALUE;
|
||||||
if (CLIGetOptionList(arg_get_str(ctx, 13), DesfireValueFileOperOpts, &op)) {
|
if (CLIGetOptionList(arg_get_str(ctx, 14), DesfireValueFileOperOpts, &op)) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t value = 0;
|
uint32_t value = 0;
|
||||||
if (CLIGetUint32Hex(ctx, 14, 0, &value, NULL, 4, "Value must have 4 byte length")) {
|
if (CLIGetUint32Hex(ctx, 15, 0, &value, NULL, 4, "Value must have 4 byte length")) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
@ -4195,14 +4206,19 @@ static int CmdHF14ADesValueOperations(const char *Cmd) {
|
||||||
SetAPDULogging(APDULogging);
|
SetAPDULogging(APDULogging);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, noauth, verbose);
|
// iso chaining works in the lrp mode
|
||||||
|
dctx.isoChaining |= (dctx.secureChannel == DACLRP);
|
||||||
|
|
||||||
|
// select
|
||||||
|
res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
DropField();
|
DropField();
|
||||||
|
PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(INFO, "app %06x file %02x operation: %s value: 0x%08x", appid, fileid, CLIGetOptionListStr(DesfireValueFileOperOpts, op), value);
|
PrintAndLogEx(INFO, "%s file %02x operation: %s value: 0x%08x", DesfireWayIDStr(selectway, id), fileid, CLIGetOptionListStr(DesfireValueFileOperOpts, op), value);
|
||||||
|
|
||||||
if (op != 0xff) {
|
if (op != 0xff) {
|
||||||
res = DesfireValueFileOperations(&dctx, fileid, op, &value);
|
res = DesfireValueFileOperations(&dctx, fileid, op, &value);
|
||||||
|
@ -4215,6 +4231,7 @@ static int CmdHF14ADesValueOperations(const char *Cmd) {
|
||||||
if (op == MFDES_GET_VALUE) {
|
if (op == MFDES_GET_VALUE) {
|
||||||
PrintAndLogEx(SUCCESS, "Value: " _GREEN_("%d (0x%08x)"), value, value);
|
PrintAndLogEx(SUCCESS, "Value: " _GREEN_("%d (0x%08x)"), value, value);
|
||||||
} else {
|
} else {
|
||||||
|
DesfireSetCommMode(&dctx, DCMMACed);
|
||||||
res = DesfireCommitTransaction(&dctx, false, 0);
|
res = DesfireCommitTransaction(&dctx, false, 0);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "Desfire CommitTransaction command " _RED_("error") ". Result: %d", res);
|
PrintAndLogEx(ERR, "Desfire CommitTransaction command " _RED_("error") ". Result: %d", res);
|
||||||
|
@ -4271,6 +4288,7 @@ static int CmdHF14ADesValueOperations(const char *Cmd) {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(INFO, "Value debited");
|
PrintAndLogEx(INFO, "Value debited");
|
||||||
|
|
||||||
|
DesfireSetCommMode(&dctx, DCMMACed);
|
||||||
res = DesfireCommitTransaction(&dctx, false, 0);
|
res = DesfireCommitTransaction(&dctx, false, 0);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "Desfire CommitTransaction command " _RED_("error") ". Result: %d", res);
|
PrintAndLogEx(ERR, "Desfire CommitTransaction command " _RED_("error") ". Result: %d", res);
|
||||||
|
@ -4296,7 +4314,8 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf mfdes clearrecfile",
|
CLIParserInit(&ctx, "hf mfdes clearrecfile",
|
||||||
"Clear record file. Master key needs to be provided or flag --no-auth set (depend on cards settings).",
|
"Clear record file. Master key needs to be provided or flag --no-auth set (depend on cards settings).",
|
||||||
"hf mfdes clearrecfile --aid 123456 --fid 01 -> clear record file for: app=123456, file=01 with defaults from `default` command");
|
"hf mfdes clearrecfile --aid 123456 --fid 01 -> clear record file for: app=123456, file=01 with defaults from `default` command\n"
|
||||||
|
"hf mfdes clearrecfile --appisoid df01 --fid 01 -s lrp -t aes -n 3 -> clear record file for lrp channel with key number 3");
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
|
@ -4311,6 +4330,7 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) {
|
||||||
arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"),
|
arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"),
|
||||||
arg_str0("s", "schann", "<d40/ev1/ev2/lrp>", "Secure channel: d40/ev1/ev2/lrp"),
|
arg_str0("s", "schann", "<d40/ev1/ev2/lrp>", "Secure channel: d40/ev1/ev2/lrp"),
|
||||||
arg_str0(NULL, "aid", "<app id hex>", "Application ID (3 hex bytes, big endian)"),
|
arg_str0(NULL, "aid", "<app id hex>", "Application ID (3 hex bytes, big endian)"),
|
||||||
|
arg_str0(NULL, "appisoid", "<isoid hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."),
|
||||||
arg_str0(NULL, "fid", "<file id hex>", "File ID for clearing (1 hex byte)"),
|
arg_str0(NULL, "fid", "<file id hex>", "File ID for clearing (1 hex byte)"),
|
||||||
arg_lit0(NULL, "no-auth", "execute without authentication"),
|
arg_lit0(NULL, "no-auth", "execute without authentication"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
|
@ -4319,19 +4339,20 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) {
|
||||||
|
|
||||||
bool APDULogging = arg_get_lit(ctx, 1);
|
bool APDULogging = arg_get_lit(ctx, 1);
|
||||||
bool verbose = arg_get_lit(ctx, 2);
|
bool verbose = arg_get_lit(ctx, 2);
|
||||||
bool noauth = arg_get_lit(ctx, 13);
|
bool noauth = arg_get_lit(ctx, 14);
|
||||||
|
|
||||||
DesfireContext dctx;
|
DesfireContext dctx;
|
||||||
int securechann = defaultSecureChannel;
|
int securechann = defaultSecureChannel;
|
||||||
uint32_t appid = 0x000000;
|
uint32_t id = 0x000000;
|
||||||
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL);
|
DesfireISOSelectWay selectway = ISW6bAID;
|
||||||
|
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway);
|
||||||
if (res) {
|
if (res) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t fnum = 1;
|
uint32_t fnum = 1;
|
||||||
if (CLIGetUint32Hex(ctx, 12, 1, &fnum, NULL, 1, "File ID must have 1 byte length")) {
|
if (CLIGetUint32Hex(ctx, 13, 1, &fnum, NULL, 1, "File ID must have 1 byte length")) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
@ -4344,9 +4365,10 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, noauth, verbose);
|
res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
DropField();
|
DropField();
|
||||||
|
PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4357,7 +4379,21 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) {
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "File %02x in the app %06x cleared " _GREEN_("successfully"), fnum, appid);
|
if (verbose)
|
||||||
|
PrintAndLogEx(INFO, "File cleared");
|
||||||
|
|
||||||
|
DesfireSetCommMode(&dctx, DCMMACed);
|
||||||
|
res = DesfireCommitTransaction(&dctx, false, 0);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(ERR, "Desfire CommitTransaction command " _RED_("error") ". Result: %d", res);
|
||||||
|
DropField();
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
PrintAndLogEx(INFO, "Transaction commited");
|
||||||
|
|
||||||
|
PrintAndLogEx(SUCCESS, "File %02x in the %s cleared " _GREEN_("successfully"), fnum, DesfireWayIDStr(selectway, id));
|
||||||
|
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
|
@ -4462,6 +4498,9 @@ static int DesfileReadFileAndPrint(DesfireContext *dctx, uint8_t fnum, int filet
|
||||||
// length of record for record file
|
// length of record for record file
|
||||||
size_t reclen = 0;
|
size_t reclen = 0;
|
||||||
|
|
||||||
|
// iso chaining works in the lrp mode
|
||||||
|
dctx->isoChaining |= (dctx->secureChannel == DACLRP);
|
||||||
|
|
||||||
// get file settings
|
// get file settings
|
||||||
if (filetype == RFTAuto) {
|
if (filetype == RFTAuto) {
|
||||||
FileSettingsS fsettings;
|
FileSettingsS fsettings;
|
||||||
|
@ -4502,7 +4541,7 @@ static int DesfileReadFileAndPrint(DesfireContext *dctx, uint8_t fnum, int filet
|
||||||
if (fsettings.fileCommMode != 0 && noauth)
|
if (fsettings.fileCommMode != 0 && noauth)
|
||||||
PrintAndLogEx(WARNING, "File needs communication mode `%s` but there is no authentication", CLIGetOptionListStr(DesfireCommunicationModeOpts, fsettings.commMode));
|
PrintAndLogEx(WARNING, "File needs communication mode `%s` but there is no authentication", CLIGetOptionListStr(DesfireCommunicationModeOpts, fsettings.commMode));
|
||||||
|
|
||||||
if ((fsettings.rAccess < 0x0e && fsettings.rAccess != dctx->keyNum) || (fsettings.rwAccess < 0x0e && fsettings.rwAccess != dctx->keyNum))
|
if ((fsettings.rAccess < 0x0e && fsettings.rAccess != dctx->keyNum) && (fsettings.rwAccess < 0x0e && fsettings.rwAccess != dctx->keyNum))
|
||||||
PrintAndLogEx(WARNING, "File needs to be authenticated with key 0x%02x or 0x%02x but current authentication key is 0x%02x", fsettings.rAccess, fsettings.rwAccess, dctx->keyNum);
|
PrintAndLogEx(WARNING, "File needs to be authenticated with key 0x%02x or 0x%02x but current authentication key is 0x%02x", fsettings.rAccess, fsettings.rwAccess, dctx->keyNum);
|
||||||
|
|
||||||
if (fsettings.rAccess == 0x0f && fsettings.rwAccess == 0x0f)
|
if (fsettings.rAccess == 0x0f && fsettings.rwAccess == 0x0f)
|
||||||
|
@ -4605,7 +4644,16 @@ static int DesfileReadFileAndPrint(DesfireContext *dctx, uint8_t fnum, int filet
|
||||||
} else {
|
} else {
|
||||||
uint32_t cnt = MemLeToUint4byte(&resp[0]);
|
uint32_t cnt = MemLeToUint4byte(&resp[0]);
|
||||||
transactionCounter = cnt;
|
transactionCounter = cnt;
|
||||||
|
if (dctx->secureChannel != DACLRP) {
|
||||||
PrintAndLogEx(SUCCESS, "Transaction counter: %d (0x%08x)", cnt, cnt);
|
PrintAndLogEx(SUCCESS, "Transaction counter: %d (0x%08x)", cnt, cnt);
|
||||||
|
} else {
|
||||||
|
// For composing TMC the two subparts are concatenated as follows: actTMC || sesTMC. Both subparts are represented LSB first.
|
||||||
|
// MF2DLHX0.pdf, 10.3.2.1 Transaction MAC Counter, page 41
|
||||||
|
uint32_t actTMC = MemLeToUint2byte(&resp[0]);
|
||||||
|
uint32_t sessTMC = MemLeToUint2byte(&resp[2]);
|
||||||
|
PrintAndLogEx(SUCCESS, "Session tr counter : %d (0x%08x)", sessTMC, sessTMC);
|
||||||
|
PrintAndLogEx(SUCCESS, "Actual tr counter : %d (0x%08x)", actTMC, actTMC);
|
||||||
|
}
|
||||||
PrintAndLogEx(SUCCESS, "Transaction MAC : %s", sprint_hex(&resp[4], 8));
|
PrintAndLogEx(SUCCESS, "Transaction MAC : %s", sprint_hex(&resp[4], 8));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -4630,7 +4678,9 @@ static int CmdHF14ADesReadData(const char *Cmd) {
|
||||||
"hf mfdes read --aid 123456 --fileisoid 1000 --type data -c iso -> read file via ISO channel: app=123456, iso id=1000, offset=0. Select via native ISO wrapper\n"
|
"hf mfdes read --aid 123456 --fileisoid 1000 --type data -c iso -> read file via ISO channel: app=123456, iso id=1000, offset=0. Select via native ISO wrapper\n"
|
||||||
"hf mfdes read --appisoid 0102 --fileisoid 1000 --type data -c iso -> read file via ISO channel: app iso id=0102, iso id=1000, offset=0. Select via ISO commands\n"
|
"hf mfdes read --appisoid 0102 --fileisoid 1000 --type data -c iso -> read file via ISO channel: app iso id=0102, iso id=1000, offset=0. Select via ISO commands\n"
|
||||||
"hf mfdes read --appisoid 0102 --fileisoid 1100 --type record -c iso --offset 000005 --length 000001 -> get one record (number 5) from file 1100 via iso commands\n"
|
"hf mfdes read --appisoid 0102 --fileisoid 1100 --type record -c iso --offset 000005 --length 000001 -> get one record (number 5) from file 1100 via iso commands\n"
|
||||||
"hf mfdes read --appisoid 0102 --fileisoid 1100 --type record -c iso --offset 000005 --length 000000 -> get all record (from 5 to 1) from file 1100 via iso commands");
|
"hf mfdes read --appisoid 0102 --fileisoid 1100 --type record -c iso --offset 000005 --length 000000 -> get all record (from 5 to 1) from file 1100 via iso commands\n"
|
||||||
|
"hf mfdes read --appisoid df01 --fid 00 -s lrp -t aes --length 000010 -> read via lrp channel\n"
|
||||||
|
"hf mfdes read --appisoid df01 --fid 00 -s ev2 -t aes --length 000010 --isochain -> read Desfire Light via ev2 channel");
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
|
@ -4652,6 +4702,7 @@ static int CmdHF14ADesReadData(const char *Cmd) {
|
||||||
arg_str0("l", "length", "<hex>", "Length to read (3 hex bytes, big endian -> 000000 = Read all data). For records - records count (0 - all). Default 0."),
|
arg_str0("l", "length", "<hex>", "Length to read (3 hex bytes, big endian -> 000000 = Read all data). For records - records count (0 - all). Default 0."),
|
||||||
arg_str0(NULL, "appisoid", "<isoid hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."),
|
arg_str0(NULL, "appisoid", "<isoid hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."),
|
||||||
arg_str0(NULL, "fileisoid", "<isoid hex>", "File ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."),
|
arg_str0(NULL, "fileisoid", "<isoid hex>", "File ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."),
|
||||||
|
arg_lit0(NULL, "isochain", "use iso chaining commands. Switched on by default if secure channel = lrp"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
@ -4662,8 +4713,9 @@ static int CmdHF14ADesReadData(const char *Cmd) {
|
||||||
|
|
||||||
DesfireContext dctx;
|
DesfireContext dctx;
|
||||||
int securechann = defaultSecureChannel;
|
int securechann = defaultSecureChannel;
|
||||||
uint32_t appid = 0x000000;
|
uint32_t id = 0x000000;
|
||||||
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL);
|
DesfireISOSelectWay selectway = ISW6bAID;
|
||||||
|
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 17, &securechann, DCMMACed, &id, &selectway);
|
||||||
if (res) {
|
if (res) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return res;
|
return res;
|
||||||
|
@ -4693,13 +4745,6 @@ static int CmdHF14ADesReadData(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t appisoid = 0x0000;
|
|
||||||
bool isoidpresent = false;
|
|
||||||
if (CLIGetUint32Hex(ctx, 17, 0x0000, &appisoid, &isoidpresent, 2, "Application ISO ID (for EF) must have 2 bytes length")) {
|
|
||||||
CLIParserFree(ctx);
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t fileisoid = 0x0000;
|
uint32_t fileisoid = 0x0000;
|
||||||
bool fileisoidpresent = false;
|
bool fileisoidpresent = false;
|
||||||
if (CLIGetUint32Hex(ctx, 18, 0x0000, &fileisoid, &fileisoidpresent, 2, "File ISO ID (for DF) must have 2 bytes length")) {
|
if (CLIGetUint32Hex(ctx, 18, 0x0000, &fileisoid, &fileisoidpresent, 2, "File ISO ID (for DF) must have 2 bytes length")) {
|
||||||
|
@ -4707,6 +4752,8 @@ static int CmdHF14ADesReadData(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dctx.isoChaining = arg_get_lit(ctx, 19);
|
||||||
|
|
||||||
SetAPDULogging(APDULogging);
|
SetAPDULogging(APDULogging);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
@ -4715,19 +4762,12 @@ static int CmdHF14ADesReadData(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isoidpresent) {
|
res = DesfireSelectAndAuthenticateW(&dctx, securechann, selectway, id, noauth, true, fileisoid, verbose);
|
||||||
res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, noauth, verbose);
|
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
DropField();
|
DropField();
|
||||||
|
PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
res = DesfireSelectAndAuthenticateISO(&dctx, securechann, (appid != 0), appid, appisoid, true, fileisoid, noauth, verbose);
|
|
||||||
if (res != PM3_SUCCESS) {
|
|
||||||
DropField();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dctx.cmdSet != DCCISO)
|
if (dctx.cmdSet != DCCISO)
|
||||||
res = DesfileReadFileAndPrint(&dctx, fnum, op, offset, length, noauth, verbose);
|
res = DesfileReadFileAndPrint(&dctx, fnum, op, offset, length, noauth, verbose);
|
||||||
|
@ -4843,8 +4883,9 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
|
||||||
|
|
||||||
DesfireContext dctx;
|
DesfireContext dctx;
|
||||||
int securechann = defaultSecureChannel;
|
int securechann = defaultSecureChannel;
|
||||||
uint32_t appid = 0x000000;
|
uint32_t id = 0x000000;
|
||||||
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMPlain, &appid, NULL);
|
DesfireISOSelectWay selectway = ISW6bAID;
|
||||||
|
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 20, &securechann, DCMMACed, &id, &selectway);
|
||||||
if (res) {
|
if (res) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return res;
|
return res;
|
||||||
|
@ -4882,13 +4923,6 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
|
||||||
|
|
||||||
int updaterecno = arg_get_int_def(ctx, 19, -1);
|
int updaterecno = arg_get_int_def(ctx, 19, -1);
|
||||||
|
|
||||||
uint32_t appisoid = 0x0000;
|
|
||||||
bool isoidpresent = false;
|
|
||||||
if (CLIGetUint32Hex(ctx, 20, 0x0000, &appisoid, &isoidpresent, 2, "Application ISO ID (for EF) must have 2 bytes length")) {
|
|
||||||
CLIParserFree(ctx);
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t fileisoid = 0x0000;
|
uint32_t fileisoid = 0x0000;
|
||||||
bool fileisoidpresent = false;
|
bool fileisoidpresent = false;
|
||||||
if (CLIGetUint32Hex(ctx, 21, 0x0000, &fileisoid, &fileisoidpresent, 2, "File ISO ID (for DF) must have 2 bytes length")) {
|
if (CLIGetUint32Hex(ctx, 21, 0x0000, &fileisoid, &fileisoidpresent, 2, "File ISO ID (for DF) must have 2 bytes length")) {
|
||||||
|
@ -4926,19 +4960,12 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
|
||||||
if (trkeylen > 0)
|
if (trkeylen > 0)
|
||||||
DesfireGetCardUID(&dctx);
|
DesfireGetCardUID(&dctx);
|
||||||
|
|
||||||
if (!isoidpresent) {
|
res = DesfireSelectAndAuthenticateW(&dctx, securechann, selectway, id, noauth, true, fileisoid, verbose);
|
||||||
res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, noauth, verbose);
|
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
DropField();
|
DropField();
|
||||||
|
PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
res = DesfireSelectAndAuthenticateISO(&dctx, securechann, (appid != 0), appid, appisoid, true, fileisoid, noauth, verbose);
|
|
||||||
if (res != PM3_SUCCESS) {
|
|
||||||
DropField();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ISO command set
|
// ISO command set
|
||||||
if (dctx.cmdSet == DCCISO) {
|
if (dctx.cmdSet == DCCISO) {
|
||||||
|
@ -4999,6 +5026,12 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
|
||||||
if (fsettings.fileCommMode != 0 && noauth)
|
if (fsettings.fileCommMode != 0 && noauth)
|
||||||
PrintAndLogEx(WARNING, "File needs communication mode `%s` but there is no authentication", CLIGetOptionListStr(DesfireCommunicationModeOpts, fsettings.commMode));
|
PrintAndLogEx(WARNING, "File needs communication mode `%s` but there is no authentication", CLIGetOptionListStr(DesfireCommunicationModeOpts, fsettings.commMode));
|
||||||
|
|
||||||
|
if ((fsettings.rAccess < 0x0e && fsettings.rAccess != dctx.keyNum) && (fsettings.rwAccess < 0x0e && fsettings.rwAccess != dctx.keyNum))
|
||||||
|
PrintAndLogEx(WARNING, "File needs to be authenticated with key 0x%02x or 0x%02x but current authentication key is 0x%02x", fsettings.rAccess, fsettings.rwAccess, dctx.keyNum);
|
||||||
|
|
||||||
|
if (fsettings.rAccess == 0x0f && fsettings.rwAccess == 0x0f)
|
||||||
|
PrintAndLogEx(WARNING, "File access denied. All read access rights is 0x0f.");
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(INFO, "Got file type: %s. Option: %s. comm mode: %s",
|
PrintAndLogEx(INFO, "Got file type: %s. Option: %s. comm mode: %s",
|
||||||
GetDesfireFileType(fsettings.fileType),
|
GetDesfireFileType(fsettings.fileType),
|
||||||
|
@ -5025,13 +5058,9 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
|
||||||
PrintAndLogEx(INFO, "Prev reader id encoded [%zu]: %s", resplen, sprint_hex(resp, resplen));
|
PrintAndLogEx(INFO, "Prev reader id encoded [%zu]: %s", resplen, sprint_hex(resp, resplen));
|
||||||
|
|
||||||
if (trkeylen > 0) {
|
if (trkeylen > 0) {
|
||||||
uint8_t sessionkey[16] = {0};
|
uint8_t prevReaderID[CRYPTO_AES_BLOCK_SIZE] = {0};
|
||||||
uint8_t uid[7] = {0};
|
DesfireDecodePrevReaderID(&dctx, trkey, transactionCounter, resp, prevReaderID);
|
||||||
memcpy(uid, dctx.uid, MAX(dctx.uidlen, 7));
|
PrintAndLogEx(INFO, "Prev reader id: %s", resplen, sprint_hex(prevReaderID, CRYPTO_AES_BLOCK_SIZE));
|
||||||
DesfireGenTransSessionKey(trkey, transactionCounter, uid, false, sessionkey);
|
|
||||||
|
|
||||||
aes_decode(NULL, sessionkey, resp, resp, CRYPTO_AES_BLOCK_SIZE);
|
|
||||||
PrintAndLogEx(INFO, "Prev reader id [%zu]: %s", resplen, sprint_hex(resp, resplen));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
readeridpushed = true;
|
readeridpushed = true;
|
||||||
|
@ -5041,6 +5070,9 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
|
||||||
PrintAndLogEx(WARNING, "Desfire CommitReaderID command " _RED_("error") ". Result: %d", res);
|
PrintAndLogEx(WARNING, "Desfire CommitReaderID command " _RED_("error") ". Result: %d", res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// iso chaining works in the lrp mode
|
||||||
|
dctx.isoChaining |= (dctx.secureChannel == DACLRP);
|
||||||
|
|
||||||
// write
|
// write
|
||||||
if (op == RFTData) {
|
if (op == RFTData) {
|
||||||
res = DesfireWriteFile(&dctx, fnum, offset, datalen, data);
|
res = DesfireWriteFile(&dctx, fnum, offset, datalen, data);
|
||||||
|
|
|
@ -2083,7 +2083,7 @@ int DesfireReadFile(DesfireContext *dctx, uint8_t fnum, uint32_t offset, uint32_
|
||||||
Uint3byteToMemLe(&data[1], offset);
|
Uint3byteToMemLe(&data[1], offset);
|
||||||
Uint3byteToMemLe(&data[4], len);
|
Uint3byteToMemLe(&data[4], len);
|
||||||
|
|
||||||
return DesfireCommand(dctx, MFDES_READ_DATA, data, 7, resp, resplen, -1);
|
return DesfireCommand(dctx, (dctx->isoChaining) ? MFDES_READ_DATA2 : MFDES_READ_DATA, data, 7, resp, resplen, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int DesfireWriteFile(DesfireContext *dctx, uint8_t fnum, uint32_t offset, uint32_t len, uint8_t *data) {
|
int DesfireWriteFile(DesfireContext *dctx, uint8_t fnum, uint32_t offset, uint32_t len, uint8_t *data) {
|
||||||
|
@ -2093,7 +2093,7 @@ int DesfireWriteFile(DesfireContext *dctx, uint8_t fnum, uint32_t offset, uint32
|
||||||
Uint3byteToMemLe(&xdata[4], len);
|
Uint3byteToMemLe(&xdata[4], len);
|
||||||
memcpy(&xdata[7], data, len);
|
memcpy(&xdata[7], data, len);
|
||||||
|
|
||||||
return DesfireCommandTxData(dctx, MFDES_WRITE_DATA, xdata, 7 + len);
|
return DesfireCommandTxData(dctx, (dctx->isoChaining) ? MFDES_WRITE_DATA2 : MFDES_WRITE_DATA, xdata, 7 + len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int DesfireValueFileOperations(DesfireContext *dctx, uint8_t fid, uint8_t operation, uint32_t *value) {
|
int DesfireValueFileOperations(DesfireContext *dctx, uint8_t fid, uint8_t operation, uint32_t *value) {
|
||||||
|
@ -2119,7 +2119,7 @@ int DesfireReadRecords(DesfireContext *dctx, uint8_t fnum, uint32_t recnum, uint
|
||||||
Uint3byteToMemLe(&data[1], recnum);
|
Uint3byteToMemLe(&data[1], recnum);
|
||||||
Uint3byteToMemLe(&data[4], reccount);
|
Uint3byteToMemLe(&data[4], reccount);
|
||||||
|
|
||||||
return DesfireCommand(dctx, MFDES_READ_RECORDS, data, 7, resp, resplen, -1);
|
return DesfireCommand(dctx, (dctx->isoChaining) ? MFDES_READ_RECORDS2 : MFDES_READ_RECORDS, data, 7, resp, resplen, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int DesfireWriteRecord(DesfireContext *dctx, uint8_t fnum, uint32_t offset, uint32_t len, uint8_t *data) {
|
int DesfireWriteRecord(DesfireContext *dctx, uint8_t fnum, uint32_t offset, uint32_t len, uint8_t *data) {
|
||||||
|
@ -2129,7 +2129,7 @@ int DesfireWriteRecord(DesfireContext *dctx, uint8_t fnum, uint32_t offset, uint
|
||||||
Uint3byteToMemLe(&xdata[4], len);
|
Uint3byteToMemLe(&xdata[4], len);
|
||||||
memcpy(&xdata[7], data, len);
|
memcpy(&xdata[7], data, len);
|
||||||
|
|
||||||
return DesfireCommandTxData(dctx, MFDES_WRITE_RECORD, xdata, 7 + len);
|
return DesfireCommandTxData(dctx, (dctx->isoChaining) ? MFDES_WRITE_RECORD2 : MFDES_WRITE_RECORD, xdata, 7 + len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int DesfireUpdateRecord(DesfireContext *dctx, uint8_t fnum, uint32_t recnum, uint32_t offset, uint32_t len, uint8_t *data) {
|
int DesfireUpdateRecord(DesfireContext *dctx, uint8_t fnum, uint32_t recnum, uint32_t offset, uint32_t len, uint8_t *data) {
|
||||||
|
@ -2140,7 +2140,7 @@ int DesfireUpdateRecord(DesfireContext *dctx, uint8_t fnum, uint32_t recnum, uin
|
||||||
Uint3byteToMemLe(&xdata[7], len);
|
Uint3byteToMemLe(&xdata[7], len);
|
||||||
memcpy(&xdata[10], data, len);
|
memcpy(&xdata[10], data, len);
|
||||||
|
|
||||||
return DesfireCommandTxData(dctx, MFDES_UPDATE_RECORD, xdata, 10 + len);
|
return DesfireCommandTxData(dctx, (dctx->isoChaining) ? MFDES_UPDATE_RECORD2 : MFDES_UPDATE_RECORD, xdata, 10 + len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintKeySettingsPICC(uint8_t keysettings, uint8_t numkeys, bool print2ndbyte) {
|
static void PrintKeySettingsPICC(uint8_t keysettings, uint8_t numkeys, bool print2ndbyte) {
|
||||||
|
|
|
@ -37,12 +37,11 @@ void DesfireClearContext(DesfireContext *ctx) {
|
||||||
ctx->keyType = T_DES;
|
ctx->keyType = T_DES;
|
||||||
memset(ctx->key, 0, sizeof(ctx->key));
|
memset(ctx->key, 0, sizeof(ctx->key));
|
||||||
|
|
||||||
LRPClearContext(&ctx->lrpCtx);
|
|
||||||
|
|
||||||
ctx->secureChannel = DACNone;
|
ctx->secureChannel = DACNone;
|
||||||
ctx->cmdSet = DCCNative;
|
ctx->cmdSet = DCCNative;
|
||||||
ctx->commMode = DCMNone;
|
ctx->commMode = DCMNone;
|
||||||
|
|
||||||
|
ctx->isoChaining = false;
|
||||||
ctx->appSelected = false;
|
ctx->appSelected = false;
|
||||||
ctx->selectedAID = 0;
|
ctx->selectedAID = 0;
|
||||||
|
|
||||||
|
@ -650,7 +649,7 @@ int DesfireEV2CalcCMAC(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t d
|
||||||
|
|
||||||
// https://www.nxp.com/docs/en/data-sheet/MF2DLHX0.pdf
|
// https://www.nxp.com/docs/en/data-sheet/MF2DLHX0.pdf
|
||||||
// page 42
|
// page 42
|
||||||
void DesfireGenTransSessionKey(uint8_t *key, uint32_t trCntr, uint8_t *uid, bool forMAC, uint8_t *sessionkey) {
|
void DesfireGenTransSessionKeyEV2(uint8_t *key, uint32_t trCntr, uint8_t *uid, bool forMAC, uint8_t *sessionkey) {
|
||||||
uint8_t xiv[CRYPTO_AES_BLOCK_SIZE] = {0};
|
uint8_t xiv[CRYPTO_AES_BLOCK_SIZE] = {0};
|
||||||
|
|
||||||
if (forMAC) {
|
if (forMAC) {
|
||||||
|
@ -668,6 +667,41 @@ void DesfireGenTransSessionKey(uint8_t *key, uint32_t trCntr, uint8_t *uid, bool
|
||||||
DesfireCryptoCMACEx(&ctx, DCOMainKey, xiv, 16, 0, sessionkey);
|
DesfireCryptoCMACEx(&ctx, DCOMainKey, xiv, 16, 0, sessionkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://www.nxp.com/docs/en/data-sheet/MF2DLHX0.pdf
|
||||||
|
// page 43
|
||||||
|
void DesfireGenTransSessionKeyLRP(uint8_t *key, uint32_t trCntr, uint8_t *uid, bool forMAC, uint8_t *sessionkey) {
|
||||||
|
uint8_t data[CRYPTO_AES_BLOCK_SIZE] = {0};
|
||||||
|
|
||||||
|
data[1] = 0x01;
|
||||||
|
data[3] = 0x80;
|
||||||
|
Uint4byteToMemLe(&data[4], trCntr + 0x00010001);
|
||||||
|
memcpy(&data[8], uid, 7);
|
||||||
|
if (forMAC) {
|
||||||
|
data[15] = 0x5a;
|
||||||
|
} else {
|
||||||
|
data[15] = 0xa5;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRPContext lctx = {0};
|
||||||
|
LRPSetKey(&lctx, key, 0, true);
|
||||||
|
LRPCMAC(&lctx, data, sizeof(data), sessionkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DesfireDecodePrevReaderID(DesfireContext *ctx, uint8_t *key, uint32_t trCntr, uint8_t *encPrevReaderID, uint8_t *prevReaderID) {
|
||||||
|
uint8_t sessionkey[16] = {0};
|
||||||
|
uint8_t uid[7] = {0};
|
||||||
|
memcpy(uid, ctx->uid, MAX(ctx->uidlen, 7));
|
||||||
|
|
||||||
|
if (ctx->secureChannel == DACEV2) {
|
||||||
|
DesfireGenTransSessionKeyEV2(key, trCntr, uid, false, sessionkey);
|
||||||
|
|
||||||
|
aes_decode(NULL, sessionkey, encPrevReaderID, prevReaderID, CRYPTO_AES_BLOCK_SIZE);
|
||||||
|
} else if (ctx->secureChannel == DACLRP) {
|
||||||
|
DesfireGenTransSessionKeyLRP(key, trCntr, uid, false, sessionkey);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int DesfireLRPCalcCMAC(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *mac) {
|
int DesfireLRPCalcCMAC(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *mac) {
|
||||||
uint8_t mdata[1050] = {0};
|
uint8_t mdata[1050] = {0};
|
||||||
size_t mdatalen = 0;
|
size_t mdatalen = 0;
|
||||||
|
|
|
@ -78,8 +78,6 @@ typedef struct DesfireContextS {
|
||||||
uint8_t key[DESFIRE_MAX_KEY_SIZE];
|
uint8_t key[DESFIRE_MAX_KEY_SIZE];
|
||||||
uint8_t masterKey[DESFIRE_MAX_KEY_SIZE]; // source for kdf
|
uint8_t masterKey[DESFIRE_MAX_KEY_SIZE]; // source for kdf
|
||||||
|
|
||||||
LRPContext lrpCtx;
|
|
||||||
|
|
||||||
// KDF finction
|
// KDF finction
|
||||||
uint8_t kdfAlgo;
|
uint8_t kdfAlgo;
|
||||||
uint8_t kdfInputLen;
|
uint8_t kdfInputLen;
|
||||||
|
@ -89,6 +87,7 @@ typedef struct DesfireContextS {
|
||||||
DesfireCommandSet cmdSet; // native/nativeiso/iso
|
DesfireCommandSet cmdSet; // native/nativeiso/iso
|
||||||
DesfireCommunicationMode commMode; // plain/mac/enc
|
DesfireCommunicationMode commMode; // plain/mac/enc
|
||||||
|
|
||||||
|
bool isoChaining;
|
||||||
bool appSelected; // for iso auth
|
bool appSelected; // for iso auth
|
||||||
uint32_t selectedAID;
|
uint32_t selectedAID;
|
||||||
|
|
||||||
|
@ -142,7 +141,10 @@ void DesfireGenSessionKeyEV1(const uint8_t rnda[], const uint8_t rndb[], Desfire
|
||||||
void DesfireGenSessionKeyEV2(uint8_t *key, uint8_t *rndA, uint8_t *rndB, bool enckey, uint8_t *sessionkey);
|
void DesfireGenSessionKeyEV2(uint8_t *key, uint8_t *rndA, uint8_t *rndB, bool enckey, uint8_t *sessionkey);
|
||||||
void DesfireEV2FillIV(DesfireContext *ctx, bool ivforcommand, uint8_t *iv);
|
void DesfireEV2FillIV(DesfireContext *ctx, bool ivforcommand, uint8_t *iv);
|
||||||
int DesfireEV2CalcCMAC(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *mac);
|
int DesfireEV2CalcCMAC(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *mac);
|
||||||
void DesfireGenTransSessionKey(uint8_t *key, uint32_t trCntr, uint8_t *uid, bool forMAC, uint8_t *sessionkey);
|
|
||||||
|
void DesfireGenTransSessionKeyEV2(uint8_t *key, uint32_t trCntr, uint8_t *uid, bool forMAC, uint8_t *sessionkey);
|
||||||
|
void DesfireGenTransSessionKeyLRP(uint8_t *key, uint32_t trCntr, uint8_t *uid, bool forMAC, uint8_t *sessionkey);
|
||||||
|
void DesfireDecodePrevReaderID(DesfireContext *ctx, uint8_t *key, uint32_t trCntr, uint8_t *encPrevReaderID, uint8_t *prevReaderID);
|
||||||
|
|
||||||
int DesfireLRPCalcCMAC(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *mac);
|
int DesfireLRPCalcCMAC(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *mac);
|
||||||
|
|
||||||
|
|
|
@ -25,11 +25,16 @@
|
||||||
static const uint8_t CommandsCanUseAnyChannel[] = {
|
static const uint8_t CommandsCanUseAnyChannel[] = {
|
||||||
MFDES_S_ADDITIONAL_FRAME,
|
MFDES_S_ADDITIONAL_FRAME,
|
||||||
MFDES_READ_DATA,
|
MFDES_READ_DATA,
|
||||||
|
MFDES_READ_DATA2,
|
||||||
MFDES_WRITE_DATA,
|
MFDES_WRITE_DATA,
|
||||||
|
MFDES_WRITE_DATA2,
|
||||||
MFDES_GET_VALUE,
|
MFDES_GET_VALUE,
|
||||||
MFDES_READ_RECORDS,
|
MFDES_READ_RECORDS,
|
||||||
|
MFDES_READ_RECORDS2,
|
||||||
MFDES_WRITE_RECORD,
|
MFDES_WRITE_RECORD,
|
||||||
|
MFDES_WRITE_RECORD2,
|
||||||
MFDES_UPDATE_RECORD,
|
MFDES_UPDATE_RECORD,
|
||||||
|
MFDES_UPDATE_RECORD2,
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool CommandCanUseAnyChannel(uint8_t cmd) {
|
static bool CommandCanUseAnyChannel(uint8_t cmd) {
|
||||||
|
@ -148,10 +153,12 @@ static const AllowedChannelModesS AllowedChannelModes[] = {
|
||||||
{MFDES_GET_ISOFILE_IDS, DACLRP, DCCNative, DCMMACed},
|
{MFDES_GET_ISOFILE_IDS, DACLRP, DCCNative, DCMMACed},
|
||||||
{MFDES_GET_FILE_SETTINGS, DACLRP, DCCNative, DCMMACed},
|
{MFDES_GET_FILE_SETTINGS, DACLRP, DCCNative, DCMMACed},
|
||||||
{MFDES_GET_KEY_VERSION, DACLRP, DCCNative, DCMMACed},
|
{MFDES_GET_KEY_VERSION, DACLRP, DCCNative, DCMMACed},
|
||||||
|
{MFDES_CLEAR_RECORD_FILE, DACLRP, DCCNative, DCMMACed},
|
||||||
|
|
||||||
{MFDES_GET_UID, DACLRP, DCCNative, DCMEncrypted},
|
{MFDES_GET_UID, DACLRP, DCCNative, DCMEncrypted},
|
||||||
{MFDES_CHANGE_FILE_SETTINGS, DACLRP, DCCNative, DCMEncrypted},
|
{MFDES_CHANGE_FILE_SETTINGS, DACLRP, DCCNative, DCMEncrypted},
|
||||||
{MFDES_CHANGE_CONFIGURATION, DACLRP, DCCNative, DCMEncrypted},
|
{MFDES_CHANGE_CONFIGURATION, DACLRP, DCCNative, DCMEncrypted},
|
||||||
|
{MFDES_CREATE_TRANS_MAC_FILE, DACLRP, DCCNative, DCMEncrypted},
|
||||||
|
|
||||||
{MFDES_CHANGE_KEY, DACLRP, DCCNative, DCMEncryptedPlain},
|
{MFDES_CHANGE_KEY, DACLRP, DCCNative, DCMEncryptedPlain},
|
||||||
};
|
};
|
||||||
|
@ -167,10 +174,15 @@ static const CmdHeaderLengthsS CmdHeaderLengths[] = {
|
||||||
{MFDES_CHANGE_FILE_SETTINGS, 1},
|
{MFDES_CHANGE_FILE_SETTINGS, 1},
|
||||||
{MFDES_CREATE_TRANS_MAC_FILE, 5},
|
{MFDES_CREATE_TRANS_MAC_FILE, 5},
|
||||||
{MFDES_READ_DATA, 7},
|
{MFDES_READ_DATA, 7},
|
||||||
|
{MFDES_READ_DATA2, 7},
|
||||||
{MFDES_WRITE_DATA, 7},
|
{MFDES_WRITE_DATA, 7},
|
||||||
|
{MFDES_WRITE_DATA2, 7},
|
||||||
{MFDES_READ_RECORDS, 7},
|
{MFDES_READ_RECORDS, 7},
|
||||||
|
{MFDES_READ_RECORDS2, 7},
|
||||||
{MFDES_WRITE_RECORD, 7},
|
{MFDES_WRITE_RECORD, 7},
|
||||||
|
{MFDES_WRITE_RECORD2, 7},
|
||||||
{MFDES_UPDATE_RECORD, 10},
|
{MFDES_UPDATE_RECORD, 10},
|
||||||
|
{MFDES_UPDATE_RECORD2, 10},
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint8_t DesfireGetCmdHeaderLen(uint8_t cmd) {
|
static uint8_t DesfireGetCmdHeaderLen(uint8_t cmd) {
|
||||||
|
@ -251,6 +263,8 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint
|
||||||
*dstdatalen = srcdatalen;
|
*dstdatalen = srcdatalen;
|
||||||
|
|
||||||
uint8_t hdrlen = DesfireGetCmdHeaderLen(cmd);
|
uint8_t hdrlen = DesfireGetCmdHeaderLen(cmd);
|
||||||
|
if (srcdatalen < hdrlen)
|
||||||
|
hdrlen = srcdatalen;
|
||||||
|
|
||||||
if (ctx->commMode == DCMMACed || (ctx->commMode == DCMEncrypted && srcdatalen <= hdrlen)) {
|
if (ctx->commMode == DCMMACed || (ctx->commMode == DCMEncrypted && srcdatalen <= hdrlen)) {
|
||||||
if (srcdatalen == 0)
|
if (srcdatalen == 0)
|
||||||
|
@ -307,6 +321,8 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint
|
||||||
*dstdatalen = srcdatalen;
|
*dstdatalen = srcdatalen;
|
||||||
|
|
||||||
uint8_t hdrlen = DesfireGetCmdHeaderLen(cmd);
|
uint8_t hdrlen = DesfireGetCmdHeaderLen(cmd);
|
||||||
|
if (srcdatalen < hdrlen)
|
||||||
|
hdrlen = srcdatalen;
|
||||||
|
|
||||||
// we calc MAC anyway
|
// we calc MAC anyway
|
||||||
// if encypted channel and no data - we only calc MAC
|
// if encypted channel and no data - we only calc MAC
|
||||||
|
@ -361,6 +377,8 @@ static void DesfireSecureChannelEncodeEV2(DesfireContext *ctx, uint8_t cmd, uint
|
||||||
*dstdatalen = srcdatalen;
|
*dstdatalen = srcdatalen;
|
||||||
|
|
||||||
uint8_t hdrlen = DesfireGetCmdHeaderLen(cmd);
|
uint8_t hdrlen = DesfireGetCmdHeaderLen(cmd);
|
||||||
|
if (srcdatalen < hdrlen)
|
||||||
|
hdrlen = srcdatalen;
|
||||||
|
|
||||||
if (ctx->commMode == DCMMACed) {
|
if (ctx->commMode == DCMMACed) {
|
||||||
uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0};
|
uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0};
|
||||||
|
@ -398,6 +416,8 @@ static void DesfireSecureChannelEncodeLRP(DesfireContext *ctx, uint8_t cmd, uint
|
||||||
*dstdatalen = srcdatalen;
|
*dstdatalen = srcdatalen;
|
||||||
|
|
||||||
uint8_t hdrlen = DesfireGetCmdHeaderLen(cmd);
|
uint8_t hdrlen = DesfireGetCmdHeaderLen(cmd);
|
||||||
|
if (srcdatalen < hdrlen)
|
||||||
|
hdrlen = srcdatalen;
|
||||||
|
|
||||||
if (ctx->commMode == DCMMACed) {
|
if (ctx->commMode == DCMMACed) {
|
||||||
uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0};
|
uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0};
|
||||||
|
|
|
@ -462,11 +462,11 @@ static bool TestTransSessionKeys(void) {
|
||||||
uint32_t trCntr = 8;
|
uint32_t trCntr = 8;
|
||||||
|
|
||||||
uint8_t sessionkey[16] = {0};
|
uint8_t sessionkey[16] = {0};
|
||||||
DesfireGenTransSessionKey(key, trCntr, uid, true, sessionkey);
|
DesfireGenTransSessionKeyEV2(key, trCntr, uid, true, sessionkey);
|
||||||
uint8_t keymac[] = {0x7C, 0x1A, 0xD2, 0xD9, 0xC5, 0xC0, 0x81, 0x54, 0xA0, 0xA4, 0x91, 0x4B, 0x40, 0x1A, 0x65, 0x98};
|
uint8_t keymac[] = {0x7C, 0x1A, 0xD2, 0xD9, 0xC5, 0xC0, 0x81, 0x54, 0xA0, 0xA4, 0x91, 0x4B, 0x40, 0x1A, 0x65, 0x98};
|
||||||
res = res && (memcmp(sessionkey, keymac, sizeof(keymac)) == 0);
|
res = res && (memcmp(sessionkey, keymac, sizeof(keymac)) == 0);
|
||||||
|
|
||||||
DesfireGenTransSessionKey(key, trCntr, uid, false, sessionkey);
|
DesfireGenTransSessionKeyEV2(key, trCntr, uid, false, sessionkey);
|
||||||
uint8_t keyenc[] = {0x11, 0x9B, 0x90, 0x2A, 0x07, 0xB1, 0x8A, 0x86, 0x5B, 0x8E, 0x1B, 0x00, 0x60, 0x59, 0x47, 0x84};
|
uint8_t keyenc[] = {0x11, 0x9B, 0x90, 0x2A, 0x07, 0xB1, 0x8A, 0x86, 0x5B, 0x8E, 0x1B, 0x00, 0x60, 0x59, 0x47, 0x84};
|
||||||
res = res && (memcmp(sessionkey, keyenc, sizeof(keyenc)) == 0);
|
res = res && (memcmp(sessionkey, keyenc, sizeof(keyenc)) == 0);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue