From d0621a1f0b42a18fdd8bbf49be3e544584f7531b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 12 Aug 2021 16:25:52 +0300 Subject: [PATCH 01/13] fix text --- client/src/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 9933cf880..ac2883ce3 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -3886,7 +3886,7 @@ static int CmdHF14ADesCreateTrMACFile(const char *Cmd) { "Create Transaction MAC file in the application. Application master key needs to be provided or flag --no-auth set (depend on application settings).", "--rawrights have priority over the separate rights settings.\n" "Key/mode/etc of the authentication depends on application settings\n" - "hf mfdes createmacfile --aid 123456 --fid 01 --mackey --rawrights 1F30 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 1F30 --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 -n 0 -t des -k 0000000000000000 -f none --aid 123456 --fid 01 -> execute with default factory setup. key and keyver == 0x00..00"); From 9e18f74811b957f395c748401efe47b95449c53f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 12 Aug 2021 16:31:29 +0300 Subject: [PATCH 02/13] fix reassign of the commit --- client/src/cmdhfmfdes.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index ac2883ce3..c481d6c42 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4875,7 +4875,8 @@ static int CmdHF14ADesWriteData(const char *Cmd) { case 0x00: case 0x01: { op = RFTData; - commit = (fsettings.fileType == 0x01); + if (!commit) + commit = (fsettings.fileType == 0x01); break; } case 0x02: { From e7c0caabcf9b7976f6c5ca051a6dc12a35e351af Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 12 Aug 2021 17:28:29 +0300 Subject: [PATCH 03/13] add verbosity --- client/src/cmdhfmfdes.c | 4 +++- client/src/mifare/desfirecore.c | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index c481d6c42..4383ede4f 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -3886,7 +3886,9 @@ static int CmdHF14ADesCreateTrMACFile(const char *Cmd) { "Create Transaction MAC file in the application. Application master key needs to be provided or flag --no-auth set (depend on application settings).", "--rawrights have priority over the separate rights settings.\n" "Key/mode/etc of the authentication depends on application settings\n" - "hf mfdes createmacfile --aid 123456 --fid 01 --rawrights 1F30 --mackey 00112233445566778899aabbccddeeff --mackeyver 01 -> create transaction mac file with parameters. Rights from default. Authentication with defaults from `default` command\n" + "Write right should be always 0xF. Read-write right should be 0xF if you not need to submit CommitReaderID command each time transaction starts\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 --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"); diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 07f85170d..b422f564d 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -2424,6 +2424,28 @@ void DesfirePrintCreateFileSettings(uint8_t filetype, uint8_t *data, size_t len) PrintAndLogEx(SUCCESS, "Access rights : %04x", MemLeToUint2byte(&data[xlen])); DesfirePrintAccessRight(&data[xlen]); xlen += 2; + + // https://www.nxp.com/docs/en/data-sheet/MF2DLHX0.pdf + // page 14 + // TransactionMAC file + if (filetype == 0x05) { + uint8_t read = 0; + uint8_t write = 0; + uint8_t readwrite = 0; + uint8_t change = 0; + DesfireDecodeFileAcessMode(&data[xlen - 2], &read, &write, &readwrite, &change); + if (write != 0x0f) + PrintAndLogEx(WARNING, "descr. : Write right should be set to F because write " _RED_("not allowed") "."); + + if (readwrite == 0x0f) + PrintAndLogEx(SUCCESS, "descr. : ReadWrite right is %01X, CommitReaderID command disabled", readwrite); + else if (readwrite == 0x0e) + PrintAndLogEx(SUCCESS, "descr. : ReadWrite right is %01X, CommitReaderID command enabled with free access", readwrite); + else if (readwrite <= 0x04) + PrintAndLogEx(SUCCESS, "descr. : ReadWrite right is %01X, CommitReaderID command enabled with key 0x0%01x", readwrite, readwrite); + else + PrintAndLogEx(WARNING, "descr. : ReadWrite right must me 0..4,E,F instead of is %01X.", readwrite); + } uint8_t reclen = 0; DesfirePrintFileSettDynPart(filetype, &data[xlen], len - xlen, &reclen, true); From 66d3aa52e38e0d3bac9f02d2dd8980636cef1c3c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 12 Aug 2021 18:07:15 +0300 Subject: [PATCH 04/13] DesfireCommitReaderID command --- client/src/mifare/desfirecore.c | 7 +++++++ client/src/mifare/desfirecore.h | 1 + 2 files changed, 8 insertions(+) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index b422f564d..63a2bbb34 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1834,6 +1834,13 @@ int DesfireClearRecordFile(DesfireContext *dctx, uint8_t fnum) { return DesfireCommandTxData(dctx, MFDES_CLEAR_RECORD_FILE, &fnum, 1); } +int DesfireCommitReaderID(DesfireContext *dctx, uint8_t *readerid, size_t readeridlen, uint8_t *resp, size_t *resplen) { + uint8_t rid[16] = {0}; + // command use 16b reader id only + memcpy(rid, readerid, MIN(readeridlen, 16)); + return DesfireCommand(dctx, MFDES_COMMIT_READER_ID, rid, 16, resp, resplen, -1); +} + int DesfireCommitTransaction(DesfireContext *dctx, bool enable_options, uint8_t options) { if (enable_options) return DesfireCommandTxData(dctx, MFDES_COMMIT_TRANSACTION, &options, 1); diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index c19e19d1d..940a00ecf 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -229,6 +229,7 @@ void DesfirePrintCreateFileSettings(uint8_t filetype, uint8_t *data, size_t len) const char *GetDesfireFileType(uint8_t type); int DesfireCreateFile(DesfireContext *dctx, uint8_t ftype, uint8_t *fdata, size_t fdatalen, bool checklen); int DesfireDeleteFile(DesfireContext *dctx, uint8_t fnum); +int DesfireCommitReaderID(DesfireContext *dctx, uint8_t *readerid, size_t readeridlen, uint8_t *resp, size_t *resplen); int DesfireCommitTransaction(DesfireContext *dctx, bool enable_options, uint8_t options); int DesfireAbortTransaction(DesfireContext *dctx); From 20fd5e42c416a5f596d8dff49b11d4bcc9620c97 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 12 Aug 2021 19:08:53 +0300 Subject: [PATCH 05/13] add cmd to channel --- client/src/mifare/desfiresecurechan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 03106f24e..45730ffad 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -73,6 +73,7 @@ static const AllowedChannelModesS AllowedChannelModes[] = { {MFDES_FORMAT_PICC, DACd40, DCCNative, DCMMACed}, {MFDES_GET_FILE_IDS, DACd40, DCCNative, DCMMACed}, {MFDES_GET_ISOFILE_IDS, DACd40, DCCNative, DCMMACed}, + {MFDES_COMMIT_READER_ID, DACd40, DCCNative, DCMMACed}, {MFDES_GET_UID, DACd40, DCCNative, DCMEncrypted}, {MFDES_CHANGE_KEY_SETTINGS, DACd40, DCCNative, DCMEncrypted}, @@ -106,6 +107,7 @@ static const AllowedChannelModesS AllowedChannelModes[] = { {MFDES_DEBIT, DACEV1, DCCNative, DCMMACed}, {MFDES_COMMIT_TRANSACTION, DACEV1, DCCNative, DCMMACed}, {MFDES_CLEAR_RECORD_FILE, DACEV1, DCCNative, DCMMACed}, + {MFDES_COMMIT_READER_ID, DACEV1, DCCNative, DCMMACed}, {MFDES_GET_UID, DACEV1, DCCNative, DCMEncrypted}, {MFDES_CHANGE_KEY_SETTINGS, DACEV1, DCCNative, DCMEncrypted}, From e8c3211f25a51f19cbc9a3cb5cb8607dc5cf8e94 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 12 Aug 2021 19:09:21 +0300 Subject: [PATCH 06/13] fix commit transaction --- client/src/mifare/desfirecore.c | 10 ++++++++-- client/src/mifare/desfirecore.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 63a2bbb34..c0bf04219 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1841,13 +1841,19 @@ int DesfireCommitReaderID(DesfireContext *dctx, uint8_t *readerid, size_t reader return DesfireCommand(dctx, MFDES_COMMIT_READER_ID, rid, 16, resp, resplen, -1); } -int DesfireCommitTransaction(DesfireContext *dctx, bool enable_options, uint8_t options) { +int DesfireCommitTransactionEx(DesfireContext *dctx, bool enable_options, uint8_t options, uint8_t *resp, size_t *resplen) { if (enable_options) - return DesfireCommandTxData(dctx, MFDES_COMMIT_TRANSACTION, &options, 1); + return DesfireCommand(dctx, MFDES_COMMIT_TRANSACTION, &options, 1, resp, resplen, -1); else return DesfireCommandNoData(dctx, MFDES_COMMIT_TRANSACTION); } +int DesfireCommitTransaction(DesfireContext *dctx, bool enable_options, uint8_t options) { + uint8_t resp[250] = {0}; + size_t resplen = 0; + return DesfireCommitTransactionEx(dctx, enable_options, options, resp, &resplen); +} + int DesfireAbortTransaction(DesfireContext *dctx) { return DesfireCommandNoData(dctx, MFDES_ABORT_TRANSACTION); } diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 940a00ecf..2838fe023 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -230,6 +230,7 @@ const char *GetDesfireFileType(uint8_t type); int DesfireCreateFile(DesfireContext *dctx, uint8_t ftype, uint8_t *fdata, size_t fdatalen, bool checklen); int DesfireDeleteFile(DesfireContext *dctx, uint8_t fnum); int DesfireCommitReaderID(DesfireContext *dctx, uint8_t *readerid, size_t readeridlen, uint8_t *resp, size_t *resplen); +int DesfireCommitTransactionEx(DesfireContext *dctx, bool enable_options, uint8_t options, uint8_t *resp, size_t *resplen); int DesfireCommitTransaction(DesfireContext *dctx, bool enable_options, uint8_t options); int DesfireAbortTransaction(DesfireContext *dctx); From 69bc17a3c0ca24941d067894e272aaebbbe64302 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 12 Aug 2021 19:09:41 +0300 Subject: [PATCH 07/13] add commitreaderid to write --- client/src/cmdhfmfdes.c | 54 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 4383ede4f..b29f34ab2 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4735,12 +4735,13 @@ static int CmdHF14ADesWriteData(const char *Cmd) { "hf mfdes write --aid 123456 --fid 01 --type data -d 01020304 --commit -> write data to backup file with commit\n" "hf mfdes write --aid 123456 --fid 01 --type value -d 00000001 -> increment value file\n" "hf mfdes write --aid 123456 --fid 01 --type value -d 00000001 --debit -> decrement value file\n" - "hf mfdes write --aid 123456 --fid 01 -d 01020304 -> write data to record file with `auto` type\n" + "hf mfdes write --aid 123456 --fid 01 -d 01020304 -> write data to file with `auto` type\n" "hf mfdes write --aid 123456 --fid 01 --type record -d 01020304 -> write data to record file\n" "hf mfdes write --aid 123456 --fid 01 --type record -d 01020304 --updaterec 0 -> update record in the record file. record 0 - lastest record.\n" "hf mfdes write --aid 123456 --fid 01 --type record --offset 000000 -d 11223344 -> write record to record file. use default channel settings from `default` command\n" "hf mfdes write --appisoid 1234 --fileisoid 1000 --type data -c iso -d 01020304 -> write data to std/backup file via iso commandset\n" - "hf mfdes write --appisoid 1234 --fileisoid 2000 --type record -c iso -d 01020304 -> aend record to record file via iso commandset"); + "hf mfdes write --appisoid 1234 --fileisoid 2000 --type record -c iso -d 01020304 -> aend record to record file via iso commandset\n" + "hf mfdes write --aid 123456 --fid 01 -d 01020304 --readerid 010203 -> write data to file with CommitReaderID command before write and CommitTransaction after write"); void *argtable[] = { arg_param_begin, @@ -4765,6 +4766,7 @@ static int CmdHF14ADesWriteData(const char *Cmd) { arg_int0(NULL, "updaterec", "", "Record number for update record command. Updates record instead of write. Lastest record - 0"), arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), arg_str0(NULL, "fileisoid", "", "File ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), + arg_str0(NULL, "readerid", "", "reader id for CommitReaderID command. If present - the command issued before write command."), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -4828,6 +4830,15 @@ static int CmdHF14ADesWriteData(const char *Cmd) { return PM3_EINVARG; } + uint8_t readerid[250] = {0}; + int readeridlen = sizeof(data); + CLIGetHexWithReturn(ctx, 22, data, &datalen); + if (datalen > 16) { + PrintAndLogEx(ERR, "ReaderID must be up to 16 bytes length."); + CLIParserFree(ctx); + return PM3_EINVARG; + } + SetAPDULogging(APDULogging); CLIParserFree(ctx); @@ -4918,7 +4929,28 @@ static int CmdHF14ADesWriteData(const char *Cmd) { PrintAndLogEx(WARNING, "GetFileSettings error. Can't get file type."); } } + + // CommitReaderID command + bool readeridpushed = false; + if (readeridlen > 0) { + uint8_t resp[250] = {0}; + size_t resplen = 0; + DesfireCommunicationMode commMode = dctx.commMode; + DesfireSetCommMode(&dctx, DCMMACed); + res = DesfireCommitReaderID(&dctx, readerid, readeridlen, resp, &resplen); + DesfireSetCommMode(&dctx, commMode); + + if (res == PM3_SUCCESS) { + PrintAndLogEx(INFO, "Prev reader id[%d]: %s", resplen, sprint_hex(resp, resplen)); + readeridpushed = true; + if (verbose) + PrintAndLogEx(INFO, "CommitReaderID " _GREEN_("OK")); + } else + PrintAndLogEx(WARNING, "Desfire CommitReaderID command " _RED_("error") ". Result: %d", res); + } + + // write if (op == RFTData) { res = DesfireWriteFile(&dctx, fnum, offset, datalen, data); if (res != PM3_SUCCESS) { @@ -4983,16 +5015,28 @@ static int CmdHF14ADesWriteData(const char *Cmd) { } // commit phase - if (commit) { - res = DesfireCommitTransaction(&dctx, false, 0); + if (commit || readeridpushed) { + uint8_t resp[250] = {0}; + size_t resplen = 0; + res = DesfireCommitTransactionEx(&dctx, readeridpushed, 0x01, resp, &resplen); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire CommitTransaction command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } - if (verbose) + if (verbose) { + if (readeridpushed) + PrintAndLogEx(INFO, "TMC and TMV[%d]: %s", resplen, sprint_hex(resp, resplen)); PrintAndLogEx(INFO, "Commit " _GREEN_("OK")); + } + + if (resplen == 4 + 8) { + PrintAndLogEx(INFO, _GREEN_("Commit result:")); + uint32_t cnt = MemLeToUint4byte(&resp[0]); + PrintAndLogEx(SUCCESS, "Transaction counter: %d (0x%08x)", cnt, cnt); + PrintAndLogEx(SUCCESS, "Transaction MAC : %s", sprint_hex(&resp[4], 8)); + } } PrintAndLogEx(INFO, "Write %s file %02x " _GREEN_("success"), CLIGetOptionListStr(DesfireReadFileTypeOpts, op), fnum); From 707f436cac8d81c1bef16c0e0c7ba20268f95524 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 12 Aug 2021 19:30:44 +0300 Subject: [PATCH 08/13] fix bugs in write --- client/src/cmdhfmfdes.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index b29f34ab2..efc075995 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4832,7 +4832,7 @@ static int CmdHF14ADesWriteData(const char *Cmd) { uint8_t readerid[250] = {0}; int readeridlen = sizeof(data); - CLIGetHexWithReturn(ctx, 22, data, &datalen); + CLIGetHexWithReturn(ctx, 22, readerid, &readeridlen); if (datalen > 16) { PrintAndLogEx(ERR, "ReaderID must be up to 16 bytes length."); CLIParserFree(ctx); @@ -5018,6 +5018,7 @@ static int CmdHF14ADesWriteData(const char *Cmd) { if (commit || readeridpushed) { uint8_t resp[250] = {0}; size_t resplen = 0; + DesfireSetCommMode(&dctx, DCMMACed); res = DesfireCommitTransactionEx(&dctx, readeridpushed, 0x01, resp, &resplen); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire CommitTransaction command " _RED_("error") ". Result: %d", res); From 9e79326eed356dea9f54d3589362b6df8104f599 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 13 Aug 2021 00:00:24 +0300 Subject: [PATCH 09/13] test session keys --- client/src/mifare/desfirecrypto.c | 18 ++++++++++++++++++ client/src/mifare/desfirecrypto.h | 1 + 2 files changed, 19 insertions(+) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 7746ff4d3..f22d0b148 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -619,6 +619,24 @@ int DesfireEV2CalcCMAC(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t d return aes_cmac8(NULL, ctx->sessionKeyMAC, mdata, mac, mdatalen); } +void DesfireGenTransSessionKey(uint8_t *key, uint32_t trCntr, uint8_t *uid, bool forMAC, uint8_t *sessionkey) { + uint8_t xiv[CRYPTO_AES_BLOCK_SIZE] = {0}; + + if (forMAC) { + xiv[0] = 0x5a; + } else { + xiv[0] = 0xa5; + } + xiv[2] = 0x01; + xiv[4] = 0x80; + Uint4byteToMemLe(&xiv[5], trCntr + 1); + memcpy(&xiv[9], uid, 7); + + DesfireContext ctx = {0}; + DesfireSetKey(&ctx, 0, T_AES, key); + DesfireCryptoCMACEx(&ctx, DCOMainKey, xiv, 16, 0, sessionkey); +} + int desfire_get_key_length(DesfireCryptoAlgorythm key_type) { switch (key_type) { case T_DES: diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index 9fe486a3a..df5d22d71 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -137,6 +137,7 @@ 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 DesfireEV2FillIV(DesfireContext *ctx, bool ivforcommand, uint8_t *iv); 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); int desfire_get_key_length(DesfireCryptoAlgorythm key_type); size_t desfire_get_key_block_length(DesfireCryptoAlgorythm key_type); From 8d3cb46a39a95c83b66acd9317de96e050bec989 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 13 Aug 2021 00:00:49 +0300 Subject: [PATCH 10/13] test --- client/src/mifare/desfiretest.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/client/src/mifare/desfiretest.c b/client/src/mifare/desfiretest.c index dcf4ddd54..bd1d91ef0 100644 --- a/client/src/mifare/desfiretest.c +++ b/client/src/mifare/desfiretest.c @@ -450,6 +450,30 @@ static bool TestEV2MAC(void) { return res; } +static bool TestTransSessionKeys(void) { + bool res = true; + + uint8_t key[] = {0x66, 0xA8, 0xCB, 0x93, 0x26, 0x9D, 0xC9, 0xBC, 0x28, 0x85, 0xB7, 0xA9, 0x1B, 0x9C, 0x69, 0x7B}; + uint8_t uid[] = {0x04, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}; + uint32_t trCntr = 8; + + uint8_t sessionkey[16] = {0}; + DesfireGenTransSessionKey(key, trCntr, uid, true, sessionkey); + 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); + + DesfireGenTransSessionKey(key, trCntr, uid, false, sessionkey); + 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); + + if (res) + PrintAndLogEx(INFO, "Trans session key. " _GREEN_("passed")); + else + PrintAndLogEx(ERR, "Trans session key. " _RED_("fail")); + + return res; +} + bool DesfireTest(bool verbose) { bool res = true; @@ -467,6 +491,7 @@ bool DesfireTest(bool verbose) { res = res && TestEV2SessionKeys(); res = res && TestEV2IVEncode(); res = res && TestEV2MAC(); + res = res && TestTransSessionKeys(); PrintAndLogEx(INFO, "---------------------------"); if (res) From 6275c137f34d625f9d463d4da8599e30dac1aeda Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 13 Aug 2021 00:01:03 +0300 Subject: [PATCH 11/13] text --- client/src/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index efc075995..39984ca57 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4942,7 +4942,7 @@ static int CmdHF14ADesWriteData(const char *Cmd) { DesfireSetCommMode(&dctx, commMode); if (res == PM3_SUCCESS) { - PrintAndLogEx(INFO, "Prev reader id[%d]: %s", resplen, sprint_hex(resp, resplen)); + PrintAndLogEx(INFO, "Prev reader id encoded[%d]: %s", resplen, sprint_hex(resp, resplen)); readeridpushed = true; if (verbose) PrintAndLogEx(INFO, "CommitReaderID " _GREEN_("OK")); From 35a30647992392fd091a710b9ed1ebfab59be9ce Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 13 Aug 2021 00:38:16 +0300 Subject: [PATCH 12/13] decode --- client/src/cmdhfmfdes.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 39984ca57..447cb199f 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -378,6 +378,7 @@ static uint8_t defaultKdfInput[50] = {0}; static DesfireSecureChannel defaultSecureChannel = DACEV1; static DesfireCommandSet defaultCommSet = DCCNativeISO; static DesfireCommunicationMode defaultCommMode = DCMPlain; +static uint32_t transactionCounter = 0; static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dctx, uint8_t keynoid, uint8_t algoid, uint8_t keyid, @@ -4542,6 +4543,7 @@ static int DesfileReadFileAndPrint(DesfireContext *dctx, uint8_t fnum, int filet print_buffer_with_offset(resp, resplen, offset, true); } else { uint32_t cnt = MemLeToUint4byte(&resp[0]); + transactionCounter = cnt; PrintAndLogEx(SUCCESS, "Transaction counter: %d (0x%08x)", cnt, cnt); PrintAndLogEx(SUCCESS, "Transaction MAC : %s", sprint_hex(&resp[4], 8)); } @@ -4730,6 +4732,8 @@ static int CmdHF14ADesWriteData(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes write", "Write data from file. Key needs to be provided or flag --no-auth set (depend on file settings).", + "In the mode with CommitReaderID to decode previous reader id command needs to read transaction counter via dump/read command and specify --trkey\n" + "\n" "hf mfdes write --aid 123456 --fid 01 -d 01020304 -> write file: app=123456, file=01, offset=0, get file type from card. use default channel settings from `default` command\n" "hf mfdes write --aid 123456 --fid 01 --type data -d 01020304 --0ffset 000100 -> write data to std file with offset 0x100\n" "hf mfdes write --aid 123456 --fid 01 --type data -d 01020304 --commit -> write data to backup file with commit\n" @@ -4767,6 +4771,7 @@ static int CmdHF14ADesWriteData(const char *Cmd) { arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), arg_str0(NULL, "fileisoid", "", "File ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), arg_str0(NULL, "readerid", "", "reader id for CommitReaderID command. If present - the command issued before write command."), + arg_str0(NULL, "trkey", "", "key for decode previous reader id."), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -4831,13 +4836,22 @@ static int CmdHF14ADesWriteData(const char *Cmd) { } uint8_t readerid[250] = {0}; - int readeridlen = sizeof(data); + int readeridlen = sizeof(readerid); CLIGetHexWithReturn(ctx, 22, readerid, &readeridlen); - if (datalen > 16) { + if (readeridlen > 16) { PrintAndLogEx(ERR, "ReaderID must be up to 16 bytes length."); CLIParserFree(ctx); return PM3_EINVARG; } + + uint8_t trkey[250] = {0}; + int trkeylen = sizeof(trkey); + CLIGetHexWithReturn(ctx, 23, trkey, &trkeylen); + if (trkeylen > 0 && trkeylen != 16) { + PrintAndLogEx(ERR, "Transaction key must be 16 bytes length."); + CLIParserFree(ctx); + return PM3_EINVARG; + } SetAPDULogging(APDULogging); CLIParserFree(ctx); @@ -4846,6 +4860,10 @@ static int CmdHF14ADesWriteData(const char *Cmd) { PrintAndLogEx(ERR, "File number range is invalid (exp 0 - 31), got %d", fnum); return PM3_EINVARG; } + + // get uid + if (trkeylen > 0) + DesfireGetCardUID(&dctx); if (!isoidpresent) { res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, noauth, verbose); @@ -4942,7 +4960,19 @@ static int CmdHF14ADesWriteData(const char *Cmd) { DesfireSetCommMode(&dctx, commMode); if (res == PM3_SUCCESS) { - PrintAndLogEx(INFO, "Prev reader id encoded[%d]: %s", resplen, sprint_hex(resp, resplen)); + PrintAndLogEx(INFO, _GREEN_("Commit Reader ID: ")); + PrintAndLogEx(INFO, "Prev reader id encoded [%d]: %s", resplen, sprint_hex(resp, resplen)); + + if (trkeylen > 0) { + uint8_t sessionkey[16] = {0}; + uint8_t uid[7] = {0}; + memcpy(uid, dctx.uid, MAX(dctx.uidlen, 7)); + DesfireGenTransSessionKey(trkey, transactionCounter, uid, false, sessionkey); + + aes_decode(NULL, sessionkey, resp, resp, CRYPTO_AES_BLOCK_SIZE); + PrintAndLogEx(INFO, "Prev reader id [%d]: %s", resplen, sprint_hex(resp, resplen)); + } + readeridpushed = true; if (verbose) PrintAndLogEx(INFO, "CommitReaderID " _GREEN_("OK")); @@ -5035,6 +5065,7 @@ static int CmdHF14ADesWriteData(const char *Cmd) { if (resplen == 4 + 8) { PrintAndLogEx(INFO, _GREEN_("Commit result:")); uint32_t cnt = MemLeToUint4byte(&resp[0]); + transactionCounter = cnt; PrintAndLogEx(SUCCESS, "Transaction counter: %d (0x%08x)", cnt, cnt); PrintAndLogEx(SUCCESS, "Transaction MAC : %s", sprint_hex(&resp[4], 8)); } From a8f583af4dbab2f3ca37d6246a37ccc74d279749 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 13 Aug 2021 00:47:22 +0300 Subject: [PATCH 13/13] add hint --- client/src/mifare/desfirecrypto.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index f22d0b148..45d22387c 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -619,6 +619,8 @@ int DesfireEV2CalcCMAC(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t d return aes_cmac8(NULL, ctx->sessionKeyMAC, mdata, mac, mdatalen); } +// https://www.nxp.com/docs/en/data-sheet/MF2DLHX0.pdf +// page 42 void DesfireGenTransSessionKey(uint8_t *key, uint32_t trCntr, uint8_t *uid, bool forMAC, uint8_t *sessionkey) { uint8_t xiv[CRYPTO_AES_BLOCK_SIZE] = {0};