From 48da8970b19ca181a58cbf8dfac3946162555229 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 16 Aug 2021 20:21:42 +0300 Subject: [PATCH 01/17] fix 14a exchange --- client/src/cmdhf14a.c | 39 ++++----------------------------------- 1 file changed, 4 insertions(+), 35 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 6e97b2815..8783da0d6 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -776,41 +776,10 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav *dataoutlen = 0; if (activateField) { - PacketResponseNG resp; - responseNum = 0; - - // Anticollision + SELECT card - SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - if (!silentMode) PrintAndLogEx(ERR, "Proxmark3 connection timeout."); - return 1; - } - - // check result - if (resp.oldarg[0] == 0) { - if (!silentMode) PrintAndLogEx(ERR, "No card in field."); - return 1; - } - - if (resp.oldarg[0] != 1 && resp.oldarg[0] != 2) { - if (!silentMode) PrintAndLogEx(ERR, "Card not in iso14443-4. res=%" PRId64 ".", resp.oldarg[0]); - return 1; - } - - if (resp.oldarg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - // get ATS - uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 - SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0, rats, sizeof(rats)); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - if (!silentMode) PrintAndLogEx(ERR, "Proxmark3 connection timeout."); - return 1; - } - - if (resp.oldarg[0] == 0) { // ats_len - if (!silentMode) PrintAndLogEx(ERR, "Can't get ATS."); - return 1; - } - } + // select with no disconnect and set g_frame_len + int selres = SelectCard14443A_4(false, !silentMode, NULL); + if (selres != PM3_SUCCESS) + return selres; } if (leaveSignalON) From 220749eebe9cf1a21bd76e95caf1e09bf53b1284 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 16 Aug 2021 20:22:29 +0300 Subject: [PATCH 02/17] anticollision instead of select aid=0, printfilesettings formatting fix --- client/src/mifare/desfirecore.c | 35 +++++++++++++++++++++++---------- client/src/mifare/desfirecore.h | 1 + 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 82fa4f81c..4651bce08 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -887,14 +887,25 @@ int DesfireSelectAndAuthenticateEx(DesfireContext *dctx, DesfireSecureChannel se if (verbose) PrintAndLogEx(INFO, "Switch to " _CYAN_("native") " for select"); } - - int res = DesfireSelectAIDHex(dctx, aid, false, 0); - if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); - return 200; + + int res; + if (aid == 0x000000) { + res = DesfireAnticollision(verbose); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire anticollision " _RED_("error") "."); + return 200; + } + if (verbose) + PrintAndLogEx(INFO, "Anticollision " _GREEN_("ok")); + } else { + res = DesfireSelectAIDHex(dctx, aid, false, 0); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); + return 200; + } + if (verbose) + PrintAndLogEx(INFO, "App %06x " _GREEN_("selected"), aid); } - if (verbose) - PrintAndLogEx(INFO, "App %06x " _GREEN_("selected"), aid); if (isosw) dctx->cmdSet = DCCISO; @@ -2219,8 +2230,8 @@ void DesfirePrintFileSettingsOneLine(FileSettingsS *fsettings) { void DesfirePrintFileSettingsTable(bool printheader, uint8_t id, bool isoidavail, uint16_t isoid, FileSettingsS *fsettings) { if (printheader) { - PrintAndLogEx(SUCCESS, " ID |ISO ID| File type | Mode | Rights: raw, r w rw ch | File settings "); - PrintAndLogEx(SUCCESS, "----------------------------------------------------------------------------------------------------------"); + PrintAndLogEx(SUCCESS, " ID |ISO ID| File type | Mode | Rights: raw, r w rw ch | File settings "); + PrintAndLogEx(SUCCESS, "------------------------------------------------------------------------------------------------------------"); } PrintAndLogEx(SUCCESS, " " _GREEN_("%02x") " |" NOLF, id); if (isoidavail) { @@ -2232,7 +2243,7 @@ void DesfirePrintFileSettingsTable(bool printheader, uint8_t id, bool isoidavail PrintAndLogEx(NORMAL, " |" NOLF); } - PrintAndLogEx(NORMAL, "0x%02x " _CYAN_("%-13s") " |" NOLF, fsettings->fileType, GetDesfireFileType(fsettings->fileType)); + PrintAndLogEx(NORMAL, "0x%02x " _CYAN_("%-15s") " |" NOLF, fsettings->fileType, GetDesfireFileType(fsettings->fileType)); PrintAndLogEx(NORMAL, " %-5s |" NOLF, GetDesfireCommunicationMode(fsettings->fileCommMode)); PrintAndLogEx(NORMAL, "%04x, %-4s %-4s %-4s %-4s |" NOLF, @@ -2728,6 +2739,10 @@ int DesfireGetCardUID(DesfireContext *ctx) { return PM3_SUCCESS; } +int DesfireAnticollision(bool verbose) { + return SelectCard14443A_4(false, verbose, NULL); +} + int DesfireSelectEx(DesfireContext *ctx, bool fieldon, DesfireISOSelectWay way, uint32_t id, char *dfname) { uint8_t resp[250] = {0}; size_t resplen = 0; diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 2838fe023..c52aecf42 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -161,6 +161,7 @@ int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uin int DesfireReadSignature(DesfireContext *dctx, uint8_t sid, uint8_t *resp, size_t *resplen); +int DesfireAnticollision(bool verbose); int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2); int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2); int DesfireSelectAIDHexNoFieldOn(DesfireContext *ctx, uint32_t aid); From 95ed9c3543fe15c330052a5f6d819f8859781e16 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 17 Aug 2021 15:06:04 +0300 Subject: [PATCH 03/17] add lrp channel --- client/src/cmdhfmfdes.c | 66 +++++++++++++-------------- client/src/mifare/desfirecore.c | 1 + client/src/mifare/desfirecrypto.c | 3 ++ client/src/mifare/desfirecrypto.h | 3 +- client/src/mifare/desfiresecurechan.c | 2 + 5 files changed, 41 insertions(+), 34 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index ce8844aae..c171a1169 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -488,7 +488,7 @@ static int CmdHF14ADesDefault(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -1311,7 +1311,7 @@ static int CmdHF14aDesDetect(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "dict", "", "File with keys dictionary"), arg_lit0(NULL, "save", "save found key and parameters to defaults"), @@ -1567,7 +1567,7 @@ static int CmdHF14aDesMAD(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID of issuer info file, (non-standard feature!) (3 hex bytes, big endian)"), arg_lit0(NULL, "auth", "Authenticate to get info from GetApplicationIDs command (non-standard feature!)"), arg_param_end @@ -1709,7 +1709,7 @@ static int CmdHF14ADesSelectApp(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID of application for some parameters (3 hex bytes, big endian)"), arg_str0(NULL, "dfname", "", "Application DF Name (string, max 16 chars). Selects application via ISO SELECT command"), arg_lit0(NULL, "mf", "Select MF (master file) via ISO channel"), @@ -1935,7 +1935,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID of application for some parameters (3 hex bytes, big endian)"), arg_lit0(NULL, "save", "saves channels parameters to defaults if authentication succeeds"), arg_param_end @@ -2022,7 +2022,7 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID of application for some parameters (3 hex bytes, big endian)"), arg_str0("p", "param", "", "Parameter id (HEX 1 byte)"), arg_str0("d", "data", "", "Data for parameter (HEX 1..30 bytes)"), @@ -2112,7 +2112,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID of application (3 hex bytes, big endian)"), arg_str0(NULL, "oldalgo", "", "Old key crypto algorithm: DES, 2TDEA, 3TDEA, AES"), arg_str0(NULL, "oldkey", "", "Old key (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), @@ -2271,7 +2271,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "rawdata", "", "Rawdata that sends to command"), arg_str0(NULL, "aid", "", "Application ID for create. Mandatory. (3 hex bytes, big endian)"), arg_str0(NULL, "fid", "", "ISO file ID. Forbidden values: 0000 3F00, 3FFF, FFFF. (2 hex bytes, big endian). If specified - enable iso file id over all the files in the app."), @@ -2435,7 +2435,7 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID of delegated application (3 hex bytes, big endian)"), arg_param_end }; @@ -2497,7 +2497,7 @@ static int CmdHF14ADesGetUID(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -2572,7 +2572,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID of delegated application (3 hex bytes, big endian)"), arg_param_end }; @@ -2629,7 +2629,7 @@ static int CmdHF14ADesGetFreeMem(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end }; @@ -2690,7 +2690,7 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0("d", "data", "", "Key settings (HEX 1 byte)"), arg_param_end @@ -2762,7 +2762,7 @@ static int CmdHF14ADesGetKeyVersions(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "keynum", "", "Key number/count (HEX 1 byte). Default 0x00."), arg_str0(NULL, "keyset", "", "Keyset number (HEX 1 byte)"), @@ -2859,7 +2859,7 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_param_end }; @@ -2937,7 +2937,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end }; @@ -3003,7 +3003,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end }; @@ -3075,7 +3075,7 @@ static int CmdHF14ADesGetFileIDs(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end @@ -3144,7 +3144,7 @@ static int CmdHF14ADesGetFileISOIDs(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end @@ -3213,7 +3213,7 @@ static int CmdHF14ADesGetFileSettings(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "fid", "", "File ID (1 hex byte). default: 1"), arg_lit0(NULL, "no-auth", "execute without authentication"), @@ -3383,7 +3383,7 @@ static int CmdHF14ADesChFileSettings(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "fid", "", "File ID (1 hex byte)"), arg_str0(NULL, "rawdata", "", "File settings (HEX > 5 bytes). Have priority over the other settings."), @@ -3523,7 +3523,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "fid", "", "File ID (1 hex byte)"), arg_str0(NULL, "isofid", "", "ISO File ID (2 hex bytes)"), @@ -3661,7 +3661,7 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "fid", "", "File ID (1 hex byte)"), arg_str0(NULL, "amode", "", "File access mode: plain/mac/encrypt"), @@ -3787,7 +3787,7 @@ static int CmdHF14ADesCreateRecordFile(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "fid", "", "File ID (1 hex byte)"), arg_str0(NULL, "isofid", "", "ISO File ID (2 hex bytes)"), @@ -3904,7 +3904,7 @@ static int CmdHF14ADesCreateTrMACFile(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "fid", "", "File ID (1 hex byte)"), arg_str0(NULL, "amode", "", "File access mode: plain/mac/encrypt"), @@ -4017,7 +4017,7 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "fid", "", "File ID (1 hex byte)"), arg_lit0(NULL, "no-auth", "execute without authentication"), @@ -4090,7 +4090,7 @@ static int CmdHF14ADesValueOperations(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "fid", "", "File ID (1 hex byte)"), arg_str0("o", "op", "", "Operation: get(default)/credit/limcredit(limited credit)/debit/clear. Operation clear: get-getopt-debit to min value"), @@ -4248,7 +4248,7 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "fid", "", "File ID for clearing (1 hex byte)"), arg_lit0(NULL, "no-auth", "execute without authentication"), @@ -4582,7 +4582,7 @@ static int CmdHF14ADesReadData(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "fid", "", "File ID (1 hex byte)"), arg_lit0(NULL, "no-auth", "execute without authentication"), @@ -4758,7 +4758,7 @@ static int CmdHF14ADesWriteData(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "fid", "", "File ID (1 hex byte)"), arg_lit0(NULL, "no-auth", "execute without authentication"), @@ -5094,7 +5094,7 @@ static int CmdHF14ADesLsFiles(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end @@ -5164,7 +5164,7 @@ static int CmdHF14ADesLsApp(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_lit0(NULL, "no-auth", "execute without authentication"), arg_lit0(NULL, "no-deep", "not to check authentication commands that avail for any application"), arg_lit0(NULL, "files", "scan files and print file settings for each application"), @@ -5229,7 +5229,7 @@ static int CmdHF14ADesDump(const char *Cmd) { arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), - arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 4651bce08..46a655cfd 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -72,6 +72,7 @@ const CLIParserOption DesfireSecureChannelOpts[] = { {DACd40, "d40"}, {DACEV1, "ev1"}, {DACEV2, "ev2"}, + {DACLRP, "lrp"}, {0, NULL}, }; const size_t DesfireSecureChannelOptsLen = ARRAY_LENGTH(DesfireSecureChannelOpts); diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index d4b1a311f..e1b0210be 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -118,6 +118,9 @@ size_t DesfireGetMACLength(DesfireContext *ctx) { case DACEV2: mac_length = 8; break; + case DACLRP: + mac_length = 8; + break; } return mac_length; } diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index a5de60a87..57fee9792 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -45,7 +45,8 @@ typedef enum { DACNone, DACd40, DACEV1, - DACEV2 + DACEV2, + DACLRP, } DesfireSecureChannel; typedef enum { diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 45730ffad..551250e7a 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -387,6 +387,7 @@ void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcda case DACEV2: DesfireSecureChannelEncodeEV2(ctx, cmd, srcdata, srcdatalen, dstdata, dstdatalen); break; + case DACLRP: case DACNone: memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -603,6 +604,7 @@ void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t sr case DACEV2: DesfireSecureChannelDecodeEV2(ctx, srcdata, srcdatalen, respcode, dstdata, dstdatalen); break; + case DACLRP: case DACNone: memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; From b9108d5453abee43cc0188a85ef897610d748ac5 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 17 Aug 2021 17:22:06 +0300 Subject: [PATCH 04/17] add iso file id to default parameters, add select/no file to iso select --- client/src/cmdhfmfdes.c | 109 ++++++++++++++++++++------------ client/src/mifare/desfirecore.c | 18 +++--- client/src/mifare/desfirecore.h | 2 +- 3 files changed, 79 insertions(+), 50 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index c171a1169..f318cf87b 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -385,9 +385,11 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct uint8_t kdfid, uint8_t kdfiid, uint8_t cmodeid, uint8_t ccsetid, uint8_t schannid, uint8_t appid, + uint8_t appisoid, int *securechannel, DesfireCommunicationMode defcommmode, - uint32_t *aid) { + uint32_t *id, + DesfireISOSelectWay *selectway) { uint8_t keynum = defaultKeyNum; int algores = defaultAlgoId; @@ -457,10 +459,25 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct return PM3_ESOFT; } - if (appid && aid) { - *aid = 0x000000; - if (CLIGetUint32Hex(ctx, appid, 0x000000, aid, NULL, 3, "AID must have 3 bytes length")) + if (appid && id) { + *id = 0x000000; + if (CLIGetUint32Hex(ctx, appid, 0x000000, id, NULL, 3, "AID must have 3 bytes length")) return PM3_EINVARG; + if (selectway) + *selectway = ISW6bAID; + } + + if (appisoid && id) { + uint32_t xisoid = 0x0000; + bool isoidpresent = false; + if (CLIGetUint32Hex(ctx, appisoid, 0x0000, &xisoid, &isoidpresent, 2, "Application ISO ID (for EF) must have 2 bytes length")) + return PM3_EINVARG; + + if (isoidpresent) { + *id = xisoid & 0xffff; + if (selectway) + *selectway = ISWIsoID; + } } DesfireSetKey(dctx, keynum, algores, key); @@ -495,7 +512,7 @@ static int CmdHF14ADesDefault(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; - int res = CmdDesGetSessionParameters(ctx, &dctx, 1, 2, 3, 4, 5, 6, 7, 8, 0, &securechann, DCMNone, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, &securechann, DCMNone, NULL, NULL); if (res) { CLIParserFree(ctx); return res; @@ -1325,7 +1342,7 @@ static int CmdHF14aDesDetect(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -1581,7 +1598,7 @@ static int CmdHF14aDesMAD(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMPlain, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMPlain, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -1696,7 +1713,8 @@ static int CmdHF14ADesSelectApp(const char *Cmd) { "hf mfdes selectapp --mf -> select master file (PICC level)\n" "hf mfdes selectapp --dfname aid123456 -> select application aid123456 by DF name\n" "hf mfdes selectapp --isoid 1111 -> select application 1111 by ISO ID\n" - "hf mfdes selectapp --isoid 1111 --fileisoid 2222 -> select application 1111 file 2222 by ISO ID"); + "hf mfdes selectapp --isoid 1111 --fileisoid 2222 -> select application 1111 file 2222 by ISO ID\n" + "hf mfdes selectapp --isoid 01df --fileisoid 00ef -> select file 00 on the Desfire Light"); void *argtable[] = { arg_param_begin, @@ -1725,7 +1743,7 @@ static int CmdHF14ADesSelectApp(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMPlain, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMPlain, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -1847,7 +1865,7 @@ static int CmdHF14ADesBruteApps(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; - int res = CmdDesGetSessionParameters(ctx, &dctx, 0, 0, 0, 0, 0, 0, 0, 0, 0, &securechann, DCMNone, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &securechann, DCMNone, NULL, NULL); if (res) { CLIParserFree(ctx); return res; @@ -1938,6 +1956,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID of application for some parameters (3 hex bytes, big endian)"), arg_lit0(NULL, "save", "saves channels parameters to defaults if authentication succeeds"), + arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -1948,7 +1967,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMPlain, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, &securechann, DCMPlain, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -1956,9 +1975,17 @@ static int CmdHF14ADesAuth(const char *Cmd) { bool save = arg_get_lit(ctx, 12); + uint32_t appisoid = 0x0000; + bool isoidpresent = false; + if (CLIGetUint32Hex(ctx, 13, 0x0000, &appisoid, &isoidpresent, 2, "Application ISO ID (for EF) must have 2 bytes length")) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + SetAPDULogging(APDULogging); CLIParserFree(ctx); + //res = DesfireSelectAndAuthenticateISO(&dctx, securechann, (appid != 0), appid, appisoid, false, 0, noauth, verbose); res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, false, verbose); if (res != PM3_SUCCESS) { DropField(); @@ -2036,7 +2063,7 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMEncrypted, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMEncrypted, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -2130,7 +2157,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMEncrypted, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMEncrypted, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -2290,7 +2317,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 12, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 12, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -2447,7 +2474,7 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -2507,7 +2534,7 @@ static int CmdHF14ADesGetUID(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, DCMEncrypted, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, &securechann, DCMEncrypted, NULL, NULL); if (res) { CLIParserFree(ctx); return res; @@ -2584,7 +2611,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -2642,7 +2669,7 @@ static int CmdHF14ADesGetFreeMem(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, (noauth) ? DCMPlain : DCMMACed, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, &securechann, (noauth) ? DCMPlain : DCMMACed, NULL, NULL); if (res) { CLIParserFree(ctx); return res; @@ -2703,7 +2730,7 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMEncrypted, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMEncrypted, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -2776,7 +2803,7 @@ static int CmdHF14ADesGetKeyVersions(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -2871,7 +2898,7 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -2949,7 +2976,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, DCMMACed, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, &securechann, DCMMACed, NULL, NULL); if (res) { CLIParserFree(ctx); return res; @@ -3015,7 +3042,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, DCMMACed, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, &securechann, DCMMACed, NULL, NULL); if (res) { CLIParserFree(ctx); return res; @@ -3089,7 +3116,7 @@ static int CmdHF14ADesGetFileIDs(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -3158,7 +3185,7 @@ static int CmdHF14ADesGetFileISOIDs(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -3228,7 +3255,7 @@ static int CmdHF14ADesGetFileSettings(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -3405,7 +3432,7 @@ static int CmdHF14ADesChFileSettings(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMEncrypted, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMEncrypted, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -3551,7 +3578,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -3688,7 +3715,7 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -3815,7 +3842,7 @@ static int CmdHF14ADesCreateRecordFile(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -3929,7 +3956,7 @@ static int CmdHF14ADesCreateTrMACFile(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMEncrypted, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMEncrypted, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -4032,7 +4059,7 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -4107,7 +4134,7 @@ static int CmdHF14ADesValueOperations(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -4263,7 +4290,7 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -4602,7 +4629,7 @@ static int CmdHF14ADesReadData(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -4661,7 +4688,7 @@ static int CmdHF14ADesReadData(const char *Cmd) { return res; } } else { - res = DesfireSelectAndAuthenticateISO(&dctx, securechann, (appid != 0), appid, appisoid, fileisoid, noauth, verbose); + res = DesfireSelectAndAuthenticateISO(&dctx, securechann, (appid != 0), appid, appisoid, true, fileisoid, noauth, verbose); if (res != PM3_SUCCESS) { DropField(); return res; @@ -4783,7 +4810,7 @@ static int CmdHF14ADesWriteData(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMPlain, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMPlain, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -4872,7 +4899,7 @@ static int CmdHF14ADesWriteData(const char *Cmd) { return res; } } else { - res = DesfireSelectAndAuthenticateISO(&dctx, securechann, (appid != 0), appid, appisoid, fileisoid, noauth, verbose); + res = DesfireSelectAndAuthenticateISO(&dctx, securechann, (appid != 0), appid, appisoid, true, fileisoid, noauth, verbose); if (res != PM3_SUCCESS) { DropField(); return res; @@ -5108,7 +5135,7 @@ static int CmdHF14ADesLsFiles(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -5180,7 +5207,7 @@ static int CmdHF14ADesLsApp(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, (noauth) ? DCMPlain : DCMMACed, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, &securechann, (noauth) ? DCMPlain : DCMMACed, NULL, NULL); if (res) { CLIParserFree(ctx); return res; @@ -5243,7 +5270,7 @@ static int CmdHF14ADesDump(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, (noauth) ? DCMPlain : DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, (noauth) ? DCMPlain : DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 46a655cfd..0ed81421b 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -933,7 +933,7 @@ int DesfireSelectAndAuthenticate(DesfireContext *dctx, DesfireSecureChannel secu return DesfireSelectAndAuthenticateEx(dctx, secureChannel, aid, false, verbose); } -int DesfireSelectAndAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool useaid, uint32_t aid, uint16_t isoappid, uint16_t isofileid, bool noauth, bool verbose) { +int DesfireSelectAndAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool useaid, uint32_t aid, uint16_t isoappid, bool selectfile, uint16_t isofileid, bool noauth, bool verbose) { if (verbose) DesfirePrintContext(dctx); @@ -961,14 +961,16 @@ int DesfireSelectAndAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel s if (verbose) PrintAndLogEx(INFO, "Application iso id %04x is " _GREEN_("selected"), isoappid); - res = DesfireSelectEx(dctx, false, ISWIsoID, isofileid, NULL); - if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire iso file select " _RED_("error") "."); - return 203; - } + if (selectfile) { + res = DesfireSelectEx(dctx, false, ISWIsoID, isofileid, NULL); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire iso file select " _RED_("error") "."); + return 203; + } - if (verbose) - PrintAndLogEx(INFO, "Application iso id %04x file iso id %04x is " _GREEN_("selected"), isoappid, isofileid); + if (verbose) + PrintAndLogEx(INFO, "Application iso id %04x file iso id %04x is " _GREEN_("selected"), isoappid, isofileid); + } } if (!noauth) { diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index c52aecf42..324940ece 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -176,7 +176,7 @@ int DesfireSelect(DesfireContext *ctx, DesfireISOSelectWay way, uint32_t id, cha const char *DesfireAuthErrorToStr(int error); int DesfireSelectAndAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel, uint32_t aid, bool verbose); int DesfireSelectAndAuthenticateEx(DesfireContext *dctx, DesfireSecureChannel secureChannel, uint32_t aid, bool noauth, bool verbose); -int DesfireSelectAndAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool useaid, uint32_t aid, uint16_t isoappid, uint16_t isofileid, bool noauth, bool verbose); +int DesfireSelectAndAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool useaid, uint32_t aid, uint16_t isoappid, bool selectfile, uint16_t isofileid, bool noauth, bool verbose); int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool verbose); void DesfireCheckAuthCommands(uint32_t appAID, char *dfname, uint8_t keyNum, AuthCommandsChk *authCmdCheck); void DesfireCheckAuthCommandsPrint(AuthCommandsChk *authCmdCheck); From af26a397a76bcb8ac6dd2d7c8aa31fe82091dd83 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 17 Aug 2021 17:59:53 +0300 Subject: [PATCH 05/17] add select way commands --- client/src/mifare/desfirecore.c | 32 ++++++++++++++++++++++++++++++++ client/src/mifare/desfirecore.h | 2 ++ 2 files changed, 34 insertions(+) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 0ed81421b..f9725887a 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -290,6 +290,38 @@ const char *DesfireAuthErrorToStr(int error) { return ""; } +const char *DesfireSelectWayToStr(DesfireISOSelectWay way) { + switch (way) { + case ISW6bAID: + return "AID"; + case ISWMF: + return "MF"; + case ISWIsoID: + return "ISO ID"; + case ISWDFName: + return "DF Name"; + default: + break; + } + return ""; +} + +bool DesfireMFSelected(DesfireISOSelectWay way, uint32_t id) { + switch (way) { + case ISW6bAID: + return (id == 0x000000); + case ISWMF: + return true; + case ISWIsoID: + return (id == 0x3f00); + case ISWDFName: + return false; + default: + break; + } + return false; +} + uint32_t DesfireAIDByteToUint(uint8_t *data) { return data[0] + (data[1] << 8) + (data[2] << 16); } diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 324940ece..8efc3052e 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -170,6 +170,8 @@ void DesfirePrintMADAID(uint32_t appid, bool verbose); int DesfireGetCardUID(DesfireContext *ctx); +const char *DesfireSelectWayToStr(DesfireISOSelectWay way); +bool DesfireMFSelected(DesfireISOSelectWay way, uint32_t id); int DesfireSelectEx(DesfireContext *ctx, bool fieldon, DesfireISOSelectWay way, uint32_t id, char *dfname); int DesfireSelect(DesfireContext *ctx, DesfireISOSelectWay way, uint32_t id, char *dfname); From 2f3c9969aa844d8cfd1ceeec3368d35f77deb746 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 17 Aug 2021 18:00:22 +0300 Subject: [PATCH 06/17] fix info, fix select --- client/src/cmdhfmfdes.c | 49 ++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index f318cf87b..f4c7eb421 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -563,12 +563,14 @@ static int CmdHF14ADesInfo(const char *Cmd) { mfdes_info_res_t info; int res = mfdes_get_info(&info); if (res != PM3_SUCCESS) { + DropField(); return res; } nxp_cardtype_t cardtype = getCardType(info.versionHW[3], info.versionHW[4]); if (cardtype == PLUS_EV1) { PrintAndLogEx(INFO, "Card seems to be MIFARE Plus EV1. Try " _YELLOW_("`hf mfp info`")); + DropField(); return PM3_SUCCESS; } @@ -622,18 +624,6 @@ static int CmdHF14ADesInfo(const char *Cmd) { DesfireContext dctx = {0}; dctx.commMode = DCMPlain; dctx.cmdSet = DCCNative; - res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); - if (res != PM3_SUCCESS) - return res; - - PICCInfoS PICCInfo = {0}; - - uint8_t aidbuf[250] = {0}; - size_t aidbuflen = 0; - res = DesfireGetAIDList(&dctx, aidbuf, &aidbuflen); - if (res == PM3_SUCCESS) { - PICCInfo.appCount = aidbuflen / 3; - } if (cardtype == DESFIRE_EV2 || cardtype == DESFIRE_LIGHT || @@ -656,6 +646,21 @@ static int CmdHF14ADesInfo(const char *Cmd) { } } + res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } + + PICCInfoS PICCInfo = {0}; + + uint8_t aidbuf[250] = {0}; + size_t aidbuflen = 0; + res = DesfireGetAIDList(&dctx, aidbuf, &aidbuflen); + if (res == PM3_SUCCESS) { + PICCInfo.appCount = aidbuflen / 3; + } + if (aidbuflen > 2) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, "--- " _CYAN_("AID list")); @@ -1966,8 +1971,9 @@ static int CmdHF14ADesAuth(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; - uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, &securechann, DCMPlain, &appid, NULL); + uint32_t id = 0x000000; + DesfireISOSelectWay selectway = ISW6bAID; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, &securechann, DCMPlain, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -1975,28 +1981,21 @@ static int CmdHF14ADesAuth(const char *Cmd) { bool save = arg_get_lit(ctx, 12); - uint32_t appisoid = 0x0000; - bool isoidpresent = false; - if (CLIGetUint32Hex(ctx, 13, 0x0000, &appisoid, &isoidpresent, 2, "Application ISO ID (for EF) must have 2 bytes length")) { - CLIParserFree(ctx); - return PM3_EINVARG; - } - SetAPDULogging(APDULogging); CLIParserFree(ctx); //res = DesfireSelectAndAuthenticateISO(&dctx, securechann, (appid != 0), appid, appisoid, false, 0, noauth, verbose); - res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, false, verbose); + res = DesfireSelectAndAuthenticateEx(&dctx, securechann, id, false, verbose); if (res != PM3_SUCCESS) { DropField(); - PrintAndLogEx(FAILED, "Select or authentication 0x%06x " _RED_("failed") ". Result [%d] %s", appid, res, DesfireAuthErrorToStr(res)); + PrintAndLogEx(FAILED, "Select or authentication %s 0x%06x " _RED_("failed") ". Result [%d] %s", DesfireSelectWayToStr(selectway), id, res, DesfireAuthErrorToStr(res)); return res; } - if (appid == 0x000000) + if (DesfireMFSelected(selectway, id)) PrintAndLogEx(SUCCESS, "PICC selected and authenticated " _GREEN_("succesfully")); else - PrintAndLogEx(SUCCESS, "Application " _CYAN_("%06x") " selected and authenticated " _GREEN_("succesfully"), appid); + PrintAndLogEx(SUCCESS, "Application %s " _CYAN_("%06x") " selected and authenticated " _GREEN_("succesfully"), DesfireSelectWayToStr(selectway), id); PrintAndLogEx(SUCCESS, _CYAN_("Context: ")); DesfirePrintContext(&dctx); From 627d775331a86b13dacb867bb5666de6d4d1a652 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 17 Aug 2021 18:03:54 +0300 Subject: [PATCH 07/17] info fix --- client/src/cmdhfmfdes.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index f4c7eb421..904f2adab 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -625,6 +625,12 @@ static int CmdHF14ADesInfo(const char *Cmd) { dctx.commMode = DCMPlain; dctx.cmdSet = DCCNative; + res = DesfireAnticollision(false); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } + if (cardtype == DESFIRE_EV2 || cardtype == DESFIRE_LIGHT || cardtype == DESFIRE_EV3 || @@ -646,12 +652,6 @@ static int CmdHF14ADesInfo(const char *Cmd) { } } - res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); - if (res != PM3_SUCCESS) { - DropField(); - return res; - } - PICCInfoS PICCInfo = {0}; uint8_t aidbuf[250] = {0}; From b2022b17212ffee95058838c45389df265ae0098 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 17 Aug 2021 19:19:50 +0300 Subject: [PATCH 08/17] fix auth select and iso select --- client/src/cmdhfmfdes.c | 5 ++--- client/src/mifare/desfirecore.c | 36 ++++++++++++++++++--------------- client/src/mifare/desfirecore.h | 1 + 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 904f2adab..f257e9354 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1984,8 +1984,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - //res = DesfireSelectAndAuthenticateISO(&dctx, securechann, (appid != 0), appid, appisoid, false, 0, noauth, verbose); - res = DesfireSelectAndAuthenticateEx(&dctx, securechann, id, false, verbose); + res = DesfireSelectAndAuthenticateW(&dctx, securechann, selectway, id, false, 0, false, verbose); if (res != PM3_SUCCESS) { DropField(); PrintAndLogEx(FAILED, "Select or authentication %s 0x%06x " _RED_("failed") ". Result [%d] %s", DesfireSelectWayToStr(selectway), id, res, DesfireAuthErrorToStr(res)); @@ -1995,7 +1994,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { if (DesfireMFSelected(selectway, id)) PrintAndLogEx(SUCCESS, "PICC selected and authenticated " _GREEN_("succesfully")); else - PrintAndLogEx(SUCCESS, "Application %s " _CYAN_("%06x") " selected and authenticated " _GREEN_("succesfully"), DesfireSelectWayToStr(selectway), id); + PrintAndLogEx(SUCCESS, "Application %s " _CYAN_("%0*x") " selected and authenticated " _GREEN_("succesfully"), DesfireSelectWayToStr(selectway), selectway == ISW6bAID ? 6 : 4, id); PrintAndLogEx(SUCCESS, _CYAN_("Context: ")); DesfirePrintContext(&dctx); diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index f9725887a..fbdde02e5 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -965,44 +965,44 @@ int DesfireSelectAndAuthenticate(DesfireContext *dctx, DesfireSecureChannel secu return DesfireSelectAndAuthenticateEx(dctx, secureChannel, aid, false, verbose); } -int DesfireSelectAndAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool useaid, uint32_t aid, uint16_t isoappid, bool selectfile, uint16_t isofileid, bool noauth, bool verbose) { +int DesfireSelectAndAuthenticateW(DesfireContext *dctx, DesfireSecureChannel secureChannel, DesfireISOSelectWay way, uint32_t id, bool selectfile, uint16_t isofileid, bool noauth, bool verbose) { if (verbose) DesfirePrintContext(dctx); int res = 0; - if (useaid) { + if (way == ISW6bAID && dctx->cmdSet == DCCISO) { dctx->cmdSet = DCCNativeISO; if (verbose) PrintAndLogEx(INFO, "Select via " _CYAN_("native iso wrapping") " interface"); - res = DesfireSelectAIDHex(dctx, aid, false, 0); + res = DesfireSelectAIDHex(dctx, id, false, 0); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); return 200; } if (verbose) - PrintAndLogEx(INFO, "App %06x via native iso channel is " _GREEN_("selected"), aid); + PrintAndLogEx(INFO, "App %06x via native iso channel is " _GREEN_("selected"), id); dctx->cmdSet = DCCISO; } else { - res = DesfireSelectEx(dctx, true, ISWIsoID, isoappid, NULL); + res = DesfireSelectEx(dctx, true, way, id, NULL); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire iso application select " _RED_("error") "."); + PrintAndLogEx(ERR, "Desfire %s select " _RED_("error") ".", DesfireSelectWayToStr(way)); return 202; } if (verbose) - PrintAndLogEx(INFO, "Application iso id %04x is " _GREEN_("selected"), isoappid); + PrintAndLogEx(INFO, "%s %0*x is " _GREEN_("selected"), DesfireSelectWayToStr(way), way == ISW6bAID ? 6 : 4, id); + } - if (selectfile) { - res = DesfireSelectEx(dctx, false, ISWIsoID, isofileid, NULL); - if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire iso file select " _RED_("error") "."); - return 203; - } - - if (verbose) - PrintAndLogEx(INFO, "Application iso id %04x file iso id %04x is " _GREEN_("selected"), isoappid, isofileid); + if (selectfile) { + res = DesfireSelectEx(dctx, false, ISWIsoID, isofileid, NULL); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire iso file select " _RED_("error") "."); + return 203; } + + if (verbose) + PrintAndLogEx(INFO, "Application %s %04x file iso id %04x is " _GREEN_("selected"), DesfireSelectWayToStr(way), id, isofileid); } if (!noauth) { @@ -1023,6 +1023,10 @@ int DesfireSelectAndAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel s return PM3_SUCCESS; } +int DesfireSelectAndAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool useaid, uint32_t aid, uint16_t isoappid, bool selectfile, uint16_t isofileid, bool noauth, bool verbose) { + return DesfireSelectAndAuthenticateW(dctx, secureChannel, useaid ? ISW6bAID : ISWIsoID, useaid ? aid : isoappid, selectfile, isofileid, noauth, verbose); +} + static int DesfireAuthenticateEV1(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool verbose) { // 3 different way to authenticate AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32) // 4 different crypto arg1 DES, 3DES, 3K3DES, AES diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 8efc3052e..300ebe8d6 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -178,6 +178,7 @@ int DesfireSelect(DesfireContext *ctx, DesfireISOSelectWay way, uint32_t id, cha const char *DesfireAuthErrorToStr(int error); int DesfireSelectAndAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel, uint32_t aid, bool verbose); int DesfireSelectAndAuthenticateEx(DesfireContext *dctx, DesfireSecureChannel secureChannel, uint32_t aid, bool noauth, bool verbose); +int DesfireSelectAndAuthenticateW(DesfireContext *dctx, DesfireSecureChannel secureChannel, DesfireISOSelectWay way, uint32_t id, bool selectfile, uint16_t isofileid, bool noauth, bool verbose); int DesfireSelectAndAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool useaid, uint32_t aid, uint16_t isoappid, bool selectfile, uint16_t isofileid, bool noauth, bool verbose); int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool verbose); void DesfireCheckAuthCommands(uint32_t appAID, char *dfname, uint8_t keyNum, AuthCommandsChk *authCmdCheck); From e28b6cfe83cf684ee0671c0a5f631edad5141d4b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 17 Aug 2021 23:31:42 +0300 Subject: [PATCH 09/17] set config works auth lrp checks --- client/src/cmdhfmfdes.c | 33 ++++---- client/src/mifare/desfirecore.c | 131 ++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+), 15 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index f257e9354..929ccb800 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1960,8 +1960,8 @@ static int CmdHF14ADesAuth(const char *Cmd) { arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID of application for some parameters (3 hex bytes, big endian)"), - arg_lit0(NULL, "save", "saves channels parameters to defaults if authentication succeeds"), arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), + arg_lit0(NULL, "save", "saves channels parameters to defaults if authentication succeeds"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -1973,13 +1973,13 @@ static int CmdHF14ADesAuth(const char *Cmd) { int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, &securechann, DCMPlain, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMPlain, &id, &selectway); if (res) { CLIParserFree(ctx); return res; } - bool save = arg_get_lit(ctx, 12); + bool save = arg_get_lit(ctx, 13); SetAPDULogging(APDULogging); CLIParserFree(ctx); @@ -2026,15 +2026,16 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) { "02h ATS update.\n" "03h SAK update\n" "04h Secure Messaging Configuration.\n" - "05h Capability data. (here change for LRP in the Desfire Light)\n" - "06h DF Name renaming\n" - "08h File renaming\n" - "09h Value file configuration\n" + "05h Capability data. (here change for LRP in the Desfire Light [00000000010000000000])\n" + "06h DF Name renaming (one-time)\n" + "08h File renaming (one-time)\n" + "09h Value file configuration (one-time)\n" "0Ah Failed authentication counter setting\n" "0Bh HW configuration\n" "\n" "hf mfdes setconfig --param 03 --data 0428 -> set SAK\n" - "hf mfdes setconfig --param 02 --data 0875778102637264 -> set ATS (first byte - length)"); + "hf mfdes setconfig --param 02 --data 0875778102637264 -> set ATS (first byte - length)\n" + "hf mfdes setconfig --appisoid 01df -t aes -s ev2 --param 05 --data 00000000020000000000 -> set LRP mode enable for Desfire Light"); void *argtable[] = { arg_param_begin, @@ -2049,6 +2050,7 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) { arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID of application for some parameters (3 hex bytes, big endian)"), + arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), arg_str0("p", "param", "", "Parameter id (HEX 1 byte)"), arg_str0("d", "data", "", "Data for parameter (HEX 1..30 bytes)"), arg_param_end @@ -2060,22 +2062,23 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; - uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMEncrypted, &appid, NULL); + uint32_t id = 0x000000; + DesfireISOSelectWay selectway = ISW6bAID; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMEncrypted, &id, &selectway); if (res) { CLIParserFree(ctx); return res; } uint32_t paramid = 0; - if (CLIGetUint32Hex(ctx, 12, 0, ¶mid, NULL, 1, "Parameter ID must have 1 bytes length")) { + if (CLIGetUint32Hex(ctx, 13, 0, ¶mid, NULL, 1, "Parameter ID must have 1 bytes length")) { CLIParserFree(ctx); return PM3_EINVARG; } uint8_t param[250] = {0}; int paramlen = sizeof(param); - CLIGetHexWithReturn(ctx, 13, param, ¶mlen); + CLIGetHexWithReturn(ctx, 14, param, ¶mlen); if (paramlen == 0) { PrintAndLogEx(ERR, "Parameter must have a data."); CLIParserFree(ctx); @@ -2091,13 +2094,13 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) { CLIParserFree(ctx); if (verbose) { - if (appid == 0x000000) + if (DesfireMFSelected(selectway, id)) PrintAndLogEx(INFO, _CYAN_("PICC") " param ID: 0x%02x param[%d]: %s", paramid, paramlen, sprint_hex(param, paramlen)); else - PrintAndLogEx(INFO, _CYAN_("Application %06x") " param ID: 0x%02x param[%d]: %s", appid, paramid, paramlen, sprint_hex(param, paramlen)); + PrintAndLogEx(INFO, _CYAN_("%s %06x") " param ID: 0x%02x param[%d]: %s", DesfireSelectWayToStr(selectway), id, paramid, paramlen, sprint_hex(param, paramlen)); } - res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose); + res = DesfireSelectAndAuthenticateW(&dctx, securechann, selectway, id, false, 0, false, verbose); if (res != PM3_SUCCESS) { DropField(); return res; diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index fbdde02e5..721900072 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1373,6 +1373,134 @@ static int DesfireAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel sec return PM3_SUCCESS; } +static int DesfireAuthenticateLRP(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool firstauth, bool verbose) { + // Crypt constants + uint8_t IV[16] = {0}; + uint8_t RndA[CRYPTO_AES_BLOCK_SIZE] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}; + uint8_t RndB[CRYPTO_AES_BLOCK_SIZE] = {0}; + uint8_t encRndB[CRYPTO_AES_BLOCK_SIZE] = {0}; + uint8_t rotRndA[CRYPTO_AES_BLOCK_SIZE] = {0}; //RndA' + uint8_t rotRndB[CRYPTO_AES_BLOCK_SIZE] = {0}; //RndB' + uint8_t both[CRYPTO_AES_BLOCK_SIZE * 2 + 1] = {0}; // ek/dk_keyNo(RndA+RndB') + + uint8_t subcommand = firstauth ? MFDES_AUTHENTICATE_EV2F : MFDES_AUTHENTICATE_EV2NF; + uint8_t *key = dctx->key; + + size_t recv_len = 0; + uint8_t respcode = 0; + uint8_t recv_data[256] = {0}; + + if (verbose) + PrintAndLogEx(INFO, _CYAN_("Auth %s:") " cmd: 0x%02x keynum: 0x%02x key: %s", (firstauth) ? "first" : "non-first", subcommand, dctx->keyNum, sprint_hex(key, 16)); + + // Let's send our auth command + uint8_t cdata[] = {dctx->keyNum, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}; + int res = DesfireExchangeEx(false, dctx, subcommand, cdata, (firstauth) ? sizeof(cdata) : 1, &respcode, recv_data, &recv_len, false, 0); + if (res != PM3_SUCCESS) { + return 1; + } + + if (!recv_len) { + return 2; + } + + if (respcode != MFDES_ADDITIONAL_FRAME) { + return 3; + } + + if (recv_len != CRYPTO_AES_BLOCK_SIZE) { + return 4; + } + + // Part 2 + memcpy(encRndB, recv_data, 16); + + // Part 3 + if (aes_decode(IV, key, encRndB, RndB, CRYPTO_AES_BLOCK_SIZE)) + return 5; + + if (g_debugMode > 1) { + PrintAndLogEx(DEBUG, "encRndB: %s", sprint_hex(encRndB, CRYPTO_AES_BLOCK_SIZE)); + PrintAndLogEx(DEBUG, "RndB: %s", sprint_hex(RndB, CRYPTO_AES_BLOCK_SIZE)); + } + + // - Rotate RndB by 8 bits + memcpy(rotRndB, RndB, CRYPTO_AES_BLOCK_SIZE); + rol(rotRndB, CRYPTO_AES_BLOCK_SIZE); + + // - Encrypt our response + uint8_t tmp[32] = {0x00}; + memcpy(tmp, RndA, CRYPTO_AES_BLOCK_SIZE); + memcpy(tmp + CRYPTO_AES_BLOCK_SIZE, rotRndB, CRYPTO_AES_BLOCK_SIZE); + if (g_debugMode > 1) { + PrintAndLogEx(DEBUG, "rotRndB: %s", sprint_hex(rotRndB, CRYPTO_AES_BLOCK_SIZE)); + PrintAndLogEx(DEBUG, "Both: %s", sprint_hex(tmp, CRYPTO_AES_BLOCK_SIZE * 2)); + } + + if (aes_encode(IV, key, tmp, both, CRYPTO_AES_BLOCK_SIZE * 2)) + return 6; + if (g_debugMode > 1) { + PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, CRYPTO_AES_BLOCK_SIZE * 2)); + } + + res = DesfireExchangeEx(false, dctx, MFDES_ADDITIONAL_FRAME, both, CRYPTO_AES_BLOCK_SIZE * 2, &respcode, recv_data, &recv_len, false, 0); + if (res != PM3_SUCCESS) { + return 7; + } + + if (!recv_len) { + return 8; + } + + if (respcode != MFDES_S_OPERATION_OK) { + return 9; + } + + // Part 4 + uint8_t data[32] = {0}; + + if (aes_decode(IV, key, recv_data, data, recv_len)) + return 10; + + // rotate rndA to check + memcpy(rotRndA, RndA, CRYPTO_AES_BLOCK_SIZE); + rol(rotRndA, CRYPTO_AES_BLOCK_SIZE); + + uint8_t *recRndA = (firstauth) ? &data[4] : data; + + if (memcmp(rotRndA, recRndA, CRYPTO_AES_BLOCK_SIZE) != 0) { + if (g_debugMode > 1) { + PrintAndLogEx(DEBUG, "Expected_RndA' : %s", sprint_hex(rotRndA, CRYPTO_AES_BLOCK_SIZE)); + PrintAndLogEx(DEBUG, "Generated_RndA' : %s", sprint_hex(recRndA, CRYPTO_AES_BLOCK_SIZE)); + } + return 11; + } + + if (firstauth) { + dctx->cmdCntr = 0; + memcpy(dctx->TI, data, 4); + } + DesfireClearIV(dctx); + DesfireGenSessionKeyEV2(dctx->key, RndA, RndB, true, dctx->sessionKeyEnc); + DesfireGenSessionKeyEV2(dctx->key, RndA, RndB, false, dctx->sessionKeyMAC); + dctx->secureChannel = secureChannel; + + if (verbose) { + if (firstauth) { + PrintAndLogEx(INFO, "TI : %s", sprint_hex(data, 4)); + PrintAndLogEx(INFO, "pic : %s", sprint_hex(&data[20], 6)); + PrintAndLogEx(INFO, "pcd : %s", sprint_hex(&data[26], 6)); + } else { + PrintAndLogEx(INFO, "TI : %s", sprint_hex(dctx->TI, 4)); + } + PrintAndLogEx(INFO, "session key ENC: %s", sprint_hex(dctx->sessionKeyEnc, 16)); + PrintAndLogEx(INFO, "session key MAC: %s", sprint_hex(dctx->sessionKeyMAC, 16)); + } + + return PM3_SUCCESS; +} + + int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool verbose) { if (dctx->kdfAlgo == MFDES_KDF_ALGO_AN10922) { MifareKdfAn10922(dctx, DCOMasterKey, dctx->kdfInput, dctx->kdfInputLen); @@ -1399,6 +1527,9 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel if (secureChannel == DACEV2) return DesfireAuthenticateEV2(dctx, secureChannel, (DesfireIsAuthenticated(dctx) == false), verbose); // non first auth if there is a working secure channel + if (secureChannel == DACLRP) + return DesfireAuthenticateLRP(dctx, secureChannel, (DesfireIsAuthenticated(dctx) == false), verbose); + return 100; } From 8aaeb6b542e4d34ab8ee9d78e84f98f10c68e6e5 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 18 Aug 2021 13:15:20 +0300 Subject: [PATCH 10/17] lrp cmac 8 --- client/src/mifare/lrpcrypto.c | 10 ++++++++++ client/src/mifare/lrpcrypto.h | 1 + 2 files changed, 11 insertions(+) diff --git a/client/src/mifare/lrpcrypto.c b/client/src/mifare/lrpcrypto.c index e274b660b..9b1d0e0df 100644 --- a/client/src/mifare/lrpcrypto.c +++ b/client/src/mifare/lrpcrypto.c @@ -265,3 +265,13 @@ void LRPCMAC(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *cmac) { LRPEvalLRP(ctx, y, CRYPTO_AES128_KEY_SIZE * 2, true, cmac); } + +void LRPCMAC8(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *cmac) { + uint8_t cmac_tmp[16] = {0}; + memset(cmac, 0x00, 8); + + LRPCMAC(ctx, data, datalen, cmac_tmp); + + for (int i = 0; i < 8; i++) + cmac[i] = cmac_tmp[i * 2 + 1]; +} diff --git a/client/src/mifare/lrpcrypto.h b/client/src/mifare/lrpcrypto.h index cf1653865..d3834b6c6 100644 --- a/client/src/mifare/lrpcrypto.h +++ b/client/src/mifare/lrpcrypto.h @@ -56,5 +56,6 @@ void LRPEncode(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *resp, si void LRPDecode(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen); void LRPGenSubkeys(uint8_t *key, uint8_t *sk1, uint8_t *sk2); void LRPCMAC(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *cmac); +void LRPCMAC8(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *cmac); #endif // __LRPCRYPTO_H From a6a80bf952e5d84167b18cdb07a228e5b716fbc9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 18 Aug 2021 13:16:15 +0300 Subject: [PATCH 11/17] set config text --- client/src/cmdhfmfdes.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 929ccb800..004d788a1 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -2026,16 +2026,17 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) { "02h ATS update.\n" "03h SAK update\n" "04h Secure Messaging Configuration.\n" - "05h Capability data. (here change for LRP in the Desfire Light [00000000010000000000])\n" + "05h Capability data. (here change for LRP in the Desfire Light [enable 00000000010000000000])\n" "06h DF Name renaming (one-time)\n" "08h File renaming (one-time)\n" "09h Value file configuration (one-time)\n" - "0Ah Failed authentication counter setting\n" + "0Ah Failed authentication counter setting [disable 00ffffffff]\n" "0Bh HW configuration\n" "\n" "hf mfdes setconfig --param 03 --data 0428 -> set SAK\n" "hf mfdes setconfig --param 02 --data 0875778102637264 -> set ATS (first byte - length)\n" - "hf mfdes setconfig --appisoid 01df -t aes -s ev2 --param 05 --data 00000000020000000000 -> set LRP mode enable for Desfire Light"); + "hf mfdes setconfig --appisoid 01df -t aes -s ev2 --param 05 --data 00000000020000000000 -> set LRP mode enable for Desfire Light\n" + "hf mfdes setconfig --appisoid 01df -t aes -s ev2 --param 0a --data 00ffffffff -> Disable failed auth counters for Desfire Light"); void *argtable[] = { arg_param_begin, From 67d198d9463030ad9b666417286d209c158d999d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 18 Aug 2021 19:05:28 +0300 Subject: [PATCH 12/17] LRPSessionKeys and TestLRPSessionKeys --- client/src/mifare/desfirecrypto.c | 41 +++++++++++++++++++++++++++---- client/src/mifare/desfirecrypto.h | 7 +++++- client/src/mifare/lrpcrypto.c | 10 ++++++++ client/src/mifare/lrpcrypto.h | 1 + 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index e1b0210be..f5c172c8a 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -31,12 +31,13 @@ #include "crc16.h" // crc16 ccitt #include "crc32.h" #include "commonutil.h" -#include "crypto/libpcrypto.h" void DesfireClearContext(DesfireContext *ctx) { ctx->keyNum = 0; ctx->keyType = T_DES; memset(ctx->key, 0, sizeof(ctx->key)); + + LRPClearContext(&ctx->lrpCtx); ctx->secureChannel = DACNone; ctx->cmdSet = DCCNative; @@ -260,11 +261,16 @@ void DesfireCryptoEncDecEx(DesfireContext *ctx, DesfireCryptoOpKeyType key_type, if (key == NULL) return; - size_t offset = 0; - while (offset < srcdatalen) { - DesfireCryptoEncDecSingleBlock(key, ctx->keyType, srcdata + offset, data + offset, xiv, dir_to_send, encode); + if (ctx->secureChannel == DACLRP) { + size_t dstlen = 0; + LRPEncDec(key, iv, encode, srcdata, srcdatalen, data, &dstlen); + } else { + size_t offset = 0; + while (offset < srcdatalen) { + DesfireCryptoEncDecSingleBlock(key, ctx->keyType, srcdata + offset, data + offset, xiv, dir_to_send, encode); - offset += block_size; + offset += block_size; + } } if (iv == NULL) @@ -585,6 +591,31 @@ void DesfireGenSessionKeyEV2(uint8_t *key, uint8_t *rndA, uint8_t *rndB, bool en memcpy(sessionkey, cmac, CRYPTO_AES_BLOCK_SIZE); } +// https://www.nxp.com/docs/en/data-sheet/MF2DLHX0.pdf +// page 35 +void DesfireGenSessionKeyLRP(uint8_t *key, uint8_t *rndA, uint8_t *rndB, bool enckey, uint8_t *sessionkey) { + uint8_t data[64] = {0}; + memset(sessionkey, 0, CRYPTO_AES_BLOCK_SIZE); + + data[1] = 0x01; + data[3] = 0x80; + memcpy(data + 4, rndA, 8); + bin_xor(data + 6, rndB, 6); // xor rndb 6b + memcpy(data + 12, rndB + 6, 10); + memcpy(data + 22, rndA + 8, 8); + data[30] = 0x96; + data[31] = 0x69; + +PrintAndLogEx(INFO, "rndA: %s", sprint_hex(rndA, CRYPTO_AES_BLOCK_SIZE)); +PrintAndLogEx(INFO, "rndB: %s", sprint_hex(rndB, CRYPTO_AES_BLOCK_SIZE)); +PrintAndLogEx(INFO, "data: %s", sprint_hex(data, 32)); + + LRPContext ctx = {0}; + LRPSetKey(&ctx, key, 0, true); + LRPCMAC(&ctx, data, 32, sessionkey); +PrintAndLogEx(INFO, "mk: %s", sprint_hex(sessionkey, CRYPTO_AES_BLOCK_SIZE)); +} + void DesfireEV2FillIV(DesfireContext *ctx, bool ivforcommand, uint8_t *iv) { uint8_t xiv[CRYPTO_AES_BLOCK_SIZE] = {0}; diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index 57fee9792..817989f75 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -23,6 +23,7 @@ #include "common.h" #include "crypto/libpcrypto.h" +#include "mifare/lrpcrypto.h" #define MAX_CRYPTO_BLOCK_SIZE 16 #define DESFIRE_MAX_CRYPTO_BLOCK_SIZE 16 @@ -36,7 +37,7 @@ enum DESFIRE_CRYPTOALGO { T_DES = 0x00, T_3DES = 0x01, //aka 2K3DES T_3K3DES = 0x02, - T_AES = 0x03 + T_AES = 0x03, }; typedef enum DESFIRE_CRYPTOALGO DesfireCryptoAlgorythm; @@ -76,6 +77,8 @@ typedef struct DesfireContextS { DesfireCryptoAlgorythm keyType; // des/2tdea/3tdea/aes uint8_t key[DESFIRE_MAX_KEY_SIZE]; uint8_t masterKey[DESFIRE_MAX_KEY_SIZE]; // source for kdf + + LRPContext lrpCtx; // KDF finction uint8_t kdfAlgo; @@ -123,6 +126,8 @@ void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, void DesfireCryptoCMACEx(DesfireContext *ctx, DesfireCryptoOpKeyType key_type, uint8_t *data, size_t len, size_t minlen, uint8_t *cmac); void MifareKdfAn10922(DesfireContext *ctx, DesfireCryptoOpKeyType key_type, const uint8_t *data, size_t len); +void DesfireGenSessionKeyLRP(uint8_t *key, uint8_t *rndA, uint8_t *rndB, bool enckey, uint8_t *sessionkey); + void DesfireDESKeySetVersion(uint8_t *key, DesfireCryptoAlgorythm keytype, uint8_t version); uint8_t DesfireDESKeyGetVersion(uint8_t *key); diff --git a/client/src/mifare/lrpcrypto.c b/client/src/mifare/lrpcrypto.c index 9b1d0e0df..cd4236ca0 100644 --- a/client/src/mifare/lrpcrypto.c +++ b/client/src/mifare/lrpcrypto.c @@ -192,6 +192,16 @@ void LRPDecode(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *resp, si } } +void LRPEncDec(uint8_t *key, uint8_t *iv, bool encode, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen) { + LRPContext ctx = {0}; + + LRPSetKeyEx(&ctx, key, iv, 4 * 2, 0, false); + if (encode) + LRPEncode(&ctx, data, datalen, resp, resplen); + else + LRPDecode(&ctx, data, datalen, resp, resplen); +} + static bool shiftLeftBe(uint8_t *data, size_t length) { if (length == 0) return false; diff --git a/client/src/mifare/lrpcrypto.h b/client/src/mifare/lrpcrypto.h index d3834b6c6..9b2e8b650 100644 --- a/client/src/mifare/lrpcrypto.h +++ b/client/src/mifare/lrpcrypto.h @@ -54,6 +54,7 @@ void LRPEvalLRP(LRPContext *ctx, uint8_t *iv, size_t ivlen, bool final, uint8_t void LRPIncCounter(uint8_t *ctr, size_t ctrlen); void LRPEncode(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen); void LRPDecode(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen); +void LRPEncDec(uint8_t *key, uint8_t *iv, bool encode, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen); void LRPGenSubkeys(uint8_t *key, uint8_t *sk1, uint8_t *sk2); void LRPCMAC(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *cmac); void LRPCMAC8(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *cmac); From 10457726f1140b842617f8391b68c1380dfae5cd Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 18 Aug 2021 19:06:41 +0300 Subject: [PATCH 13/17] test and remove debug --- client/src/mifare/desfirecrypto.c | 5 ----- client/src/mifare/desfiretest.c | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index f5c172c8a..296d88da1 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -606,14 +606,9 @@ void DesfireGenSessionKeyLRP(uint8_t *key, uint8_t *rndA, uint8_t *rndB, bool en data[30] = 0x96; data[31] = 0x69; -PrintAndLogEx(INFO, "rndA: %s", sprint_hex(rndA, CRYPTO_AES_BLOCK_SIZE)); -PrintAndLogEx(INFO, "rndB: %s", sprint_hex(rndB, CRYPTO_AES_BLOCK_SIZE)); -PrintAndLogEx(INFO, "data: %s", sprint_hex(data, 32)); - LRPContext ctx = {0}; LRPSetKey(&ctx, key, 0, true); LRPCMAC(&ctx, data, 32, sessionkey); -PrintAndLogEx(INFO, "mk: %s", sprint_hex(sessionkey, CRYPTO_AES_BLOCK_SIZE)); } void DesfireEV2FillIV(DesfireContext *ctx, bool ivforcommand, uint8_t *iv) { diff --git a/client/src/mifare/desfiretest.c b/client/src/mifare/desfiretest.c index 8ebb66428..a18babae4 100644 --- a/client/src/mifare/desfiretest.c +++ b/client/src/mifare/desfiretest.c @@ -857,6 +857,28 @@ static bool TestLRPCMAC(void) { return res; } +// https://www.nxp.com/docs/en/application-note/AN12343.pdf +// page 33-34 +static bool TestLRPSessionKeys(void) { + bool res = true; + + uint8_t key[16] = {0}; + uint8_t rnda[] = {0x74, 0xD7, 0xDF, 0x6A, 0x2C, 0xEC, 0x0B, 0x72, 0xB4, 0x12, 0xDE, 0x0D, 0x2B, 0x11, 0x17, 0xE6}; + uint8_t rndb[] = {0x56, 0x10, 0x9A, 0x31, 0x97, 0x7C, 0x85, 0x53, 0x19, 0xCD, 0x46, 0x18, 0xC9, 0xD2, 0xAE, 0xD2}; + uint8_t sessionkeyres[] = {0x13, 0x2D, 0x7E, 0x6F, 0x35, 0xBA, 0x86, 0x1F, 0x39, 0xB3, 0x72, 0x21, 0x21, 0x4E, 0x25, 0xA5}; + + uint8_t sessionkey[16] = {0}; + DesfireGenSessionKeyLRP(key, rnda, rndb, true, sessionkey); + res = res && (memcmp(sessionkey, sessionkeyres, sizeof(sessionkeyres)) == 0); + + if (res) + PrintAndLogEx(INFO, "LRP session keys.. " _GREEN_("passed")); + else + PrintAndLogEx(ERR, "LRP session keys.. " _RED_("fail")); + + return res; +} + bool DesfireTest(bool verbose) { bool res = true; @@ -883,6 +905,7 @@ bool DesfireTest(bool verbose) { res = res && TestLRPDecode(); res = res && TestLRPSubkeys(); res = res && TestLRPCMAC(); + res = res && TestLRPSessionKeys(); PrintAndLogEx(INFO, "---------------------------"); if (res) From 1c3f4d7e2205be2520410d11c6d95eb982ea2287 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 18 Aug 2021 19:07:22 +0300 Subject: [PATCH 14/17] fix page --- client/src/mifare/desfiretest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/mifare/desfiretest.c b/client/src/mifare/desfiretest.c index a18babae4..05df8da68 100644 --- a/client/src/mifare/desfiretest.c +++ b/client/src/mifare/desfiretest.c @@ -858,7 +858,7 @@ static bool TestLRPCMAC(void) { } // https://www.nxp.com/docs/en/application-note/AN12343.pdf -// page 33-34 +// page 49 static bool TestLRPSessionKeys(void) { bool res = true; From df8f5c4655f9d7f8ef84a523ccb724fb2bc4d0f1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 18 Aug 2021 19:44:48 +0300 Subject: [PATCH 15/17] LRP auth works --- client/src/mifare/desfirecore.c | 107 ++++++++++++++++++-------------- client/src/mifare/lrpcrypto.c | 2 +- 2 files changed, 60 insertions(+), 49 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 721900072..1c5748d91 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -258,6 +258,8 @@ const char *DesfireAuthErrorToStr(int error) { return "mbedtls_aes_setkey_dec failed"; case 11: return "Authentication failed. Cannot verify Session Key."; + case 12: + return "Authentication failed. Cannot verify CMAC."; case 100: return "Can't find auth method for provided channel parameters."; case 200: @@ -1210,7 +1212,7 @@ static int DesfireAuthenticateEV2(DesfireContext *dctx, DesfireSecureChannel sec PrintAndLogEx(INFO, _CYAN_("Auth %s:") " cmd: 0x%02x keynum: 0x%02x key: %s", (firstauth) ? "first" : "non-first", subcommand, dctx->keyNum, sprint_hex(key, 16)); // Let's send our auth command - uint8_t cdata[2] = {dctx->keyNum, 0x00}; + uint8_t cdata[] = {dctx->keyNum, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; int res = DesfireExchangeEx(false, dctx, subcommand, cdata, (firstauth) ? sizeof(cdata) : 1, &respcode, recv_data, &recv_len, false, 0); if (res != PM3_SUCCESS) { return 1; @@ -1224,12 +1226,16 @@ static int DesfireAuthenticateEV2(DesfireContext *dctx, DesfireSecureChannel sec return 3; } + size_t rdataindx = 0; if (recv_len != CRYPTO_AES_BLOCK_SIZE) { - return 4; + if (recv_len == CRYPTO_AES_BLOCK_SIZE + 1) + rdataindx = 1; + else + return 4; } // Part 2 - memcpy(encRndB, recv_data, 16); + memcpy(encRndB, &recv_data[rdataindx], 16); // Part 3 if (aes_decode(IV, key, encRndB, RndB, CRYPTO_AES_BLOCK_SIZE)) @@ -1375,12 +1381,8 @@ static int DesfireAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel sec static int DesfireAuthenticateLRP(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool firstauth, bool verbose) { // Crypt constants - uint8_t IV[16] = {0}; uint8_t RndA[CRYPTO_AES_BLOCK_SIZE] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}; uint8_t RndB[CRYPTO_AES_BLOCK_SIZE] = {0}; - uint8_t encRndB[CRYPTO_AES_BLOCK_SIZE] = {0}; - uint8_t rotRndA[CRYPTO_AES_BLOCK_SIZE] = {0}; //RndA' - uint8_t rotRndB[CRYPTO_AES_BLOCK_SIZE] = {0}; //RndB' uint8_t both[CRYPTO_AES_BLOCK_SIZE * 2 + 1] = {0}; // ek/dk_keyNo(RndA+RndB') uint8_t subcommand = firstauth ? MFDES_AUTHENTICATE_EV2F : MFDES_AUTHENTICATE_EV2NF; @@ -1394,7 +1396,7 @@ static int DesfireAuthenticateLRP(DesfireContext *dctx, DesfireSecureChannel sec PrintAndLogEx(INFO, _CYAN_("Auth %s:") " cmd: 0x%02x keynum: 0x%02x key: %s", (firstauth) ? "first" : "non-first", subcommand, dctx->keyNum, sprint_hex(key, 16)); // Let's send our auth command - uint8_t cdata[] = {dctx->keyNum, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}; + uint8_t cdata[] = {dctx->keyNum, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}; int res = DesfireExchangeEx(false, dctx, subcommand, cdata, (firstauth) ? sizeof(cdata) : 1, &respcode, recv_data, &recv_len, false, 0); if (res != PM3_SUCCESS) { return 1; @@ -1408,39 +1410,40 @@ static int DesfireAuthenticateLRP(DesfireContext *dctx, DesfireSecureChannel sec return 3; } - if (recv_len != CRYPTO_AES_BLOCK_SIZE) { + if (recv_len != CRYPTO_AES_BLOCK_SIZE + 1) { return 4; } + + if (recv_data[0] != 0x01) { + PrintAndLogEx(WARNING, "NOT LRP! rec data[0]=: 0x%02x", recv_data[0]); + //return 50; + } - // Part 2 - memcpy(encRndB, recv_data, 16); - - // Part 3 - if (aes_decode(IV, key, encRndB, RndB, CRYPTO_AES_BLOCK_SIZE)) - return 5; + // PICC return RndB in plain + memcpy(RndB, &recv_data[1], 16); if (g_debugMode > 1) { - PrintAndLogEx(DEBUG, "encRndB: %s", sprint_hex(encRndB, CRYPTO_AES_BLOCK_SIZE)); PrintAndLogEx(DEBUG, "RndB: %s", sprint_hex(RndB, CRYPTO_AES_BLOCK_SIZE)); } - // - Rotate RndB by 8 bits - memcpy(rotRndB, RndB, CRYPTO_AES_BLOCK_SIZE); - rol(rotRndB, CRYPTO_AES_BLOCK_SIZE); + // cmac(sessionkey, rnda+rndb) + uint8_t sessionkey[32] = {0}; + DesfireGenSessionKeyLRP(key, RndA, RndB, false, sessionkey); - // - Encrypt our response - uint8_t tmp[32] = {0x00}; + uint8_t tmp[CRYPTO_AES_BLOCK_SIZE * 4] = {0}; memcpy(tmp, RndA, CRYPTO_AES_BLOCK_SIZE); - memcpy(tmp + CRYPTO_AES_BLOCK_SIZE, rotRndB, CRYPTO_AES_BLOCK_SIZE); - if (g_debugMode > 1) { - PrintAndLogEx(DEBUG, "rotRndB: %s", sprint_hex(rotRndB, CRYPTO_AES_BLOCK_SIZE)); - PrintAndLogEx(DEBUG, "Both: %s", sprint_hex(tmp, CRYPTO_AES_BLOCK_SIZE * 2)); - } + memcpy(tmp + CRYPTO_AES_BLOCK_SIZE, RndB, CRYPTO_AES_BLOCK_SIZE); - if (aes_encode(IV, key, tmp, both, CRYPTO_AES_BLOCK_SIZE * 2)) - return 6; + uint8_t cmac[CRYPTO_AES_BLOCK_SIZE] = {0}; + LRPContext ctx = {0}; + LRPSetKey(&ctx, sessionkey, 0, true); + LRPCMAC(&ctx, tmp, 32, cmac); + + // response = rnda + cmac(sessionkey, rnda+rndb) + memcpy(both, RndA, CRYPTO_AES_BLOCK_SIZE); + memcpy(both + CRYPTO_AES_BLOCK_SIZE, cmac, CRYPTO_AES_BLOCK_SIZE); if (g_debugMode > 1) { - PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, CRYPTO_AES_BLOCK_SIZE * 2)); + PrintAndLogEx(DEBUG, "Both: %s", sprint_hex(tmp, CRYPTO_AES_BLOCK_SIZE * 2)); } res = DesfireExchangeEx(false, dctx, MFDES_ADDITIONAL_FRAME, both, CRYPTO_AES_BLOCK_SIZE * 2, &respcode, recv_data, &recv_len, false, 0); @@ -1457,39 +1460,47 @@ static int DesfireAuthenticateLRP(DesfireContext *dctx, DesfireSecureChannel sec } // Part 4 - uint8_t data[32] = {0}; + uint8_t data[64] = {0}; - if (aes_decode(IV, key, recv_data, data, recv_len)) - return 10; - - // rotate rndA to check - memcpy(rotRndA, RndA, CRYPTO_AES_BLOCK_SIZE); - rol(rotRndA, CRYPTO_AES_BLOCK_SIZE); - - uint8_t *recRndA = (firstauth) ? &data[4] : data; - - if (memcmp(rotRndA, recRndA, CRYPTO_AES_BLOCK_SIZE) != 0) { + // clear IV here + DesfireClearIV(dctx); + + // check mac + memcpy(tmp, RndB, CRYPTO_AES_BLOCK_SIZE); + memcpy(tmp + CRYPTO_AES_BLOCK_SIZE, RndA, CRYPTO_AES_BLOCK_SIZE); + memcpy(tmp + CRYPTO_AES_BLOCK_SIZE * 2, recv_data, CRYPTO_AES_BLOCK_SIZE); + LRPSetKey(&ctx, sessionkey, 0, true); + LRPCMAC(&ctx, tmp, CRYPTO_AES_BLOCK_SIZE * 3, cmac); + if (memcmp(&recv_data[CRYPTO_AES_BLOCK_SIZE], cmac, CRYPTO_AES_BLOCK_SIZE) != 0) { if (g_debugMode > 1) { - PrintAndLogEx(DEBUG, "Expected_RndA' : %s", sprint_hex(rotRndA, CRYPTO_AES_BLOCK_SIZE)); - PrintAndLogEx(DEBUG, "Generated_RndA' : %s", sprint_hex(recRndA, CRYPTO_AES_BLOCK_SIZE)); + PrintAndLogEx(DEBUG, "Expected cmac : %s", sprint_hex(&recv_data[CRYPTO_AES_BLOCK_SIZE], CRYPTO_AES_BLOCK_SIZE)); + PrintAndLogEx(DEBUG, "Generated cmac : %s", sprint_hex(cmac, CRYPTO_AES_BLOCK_SIZE)); } - return 11; + return 12; } + // decode data + LRPSetKeyEx(&ctx, sessionkey, dctx->IV, 4 * 2, 1, false); + size_t declen = 0; + LRPDecode(&ctx, recv_data, 16, data, &declen); + memcpy(dctx->IV, ctx.counter, 4); +PrintAndLogEx(INFO, "--decoded <%d>: %s", declen, sprint_hex(data, 16)); +PrintAndLogEx(INFO, "iv : %s", sprint_hex(dctx->IV, 4)); + if (firstauth) { dctx->cmdCntr = 0; memcpy(dctx->TI, data, 4); } - DesfireClearIV(dctx); - DesfireGenSessionKeyEV2(dctx->key, RndA, RndB, true, dctx->sessionKeyEnc); - DesfireGenSessionKeyEV2(dctx->key, RndA, RndB, false, dctx->sessionKeyMAC); + + memcpy(dctx->sessionKeyEnc, sessionkey, CRYPTO_AES_BLOCK_SIZE); + memcpy(dctx->sessionKeyMAC, sessionkey, CRYPTO_AES_BLOCK_SIZE); dctx->secureChannel = secureChannel; if (verbose) { if (firstauth) { PrintAndLogEx(INFO, "TI : %s", sprint_hex(data, 4)); - PrintAndLogEx(INFO, "pic : %s", sprint_hex(&data[20], 6)); - PrintAndLogEx(INFO, "pcd : %s", sprint_hex(&data[26], 6)); + PrintAndLogEx(INFO, "pic : %s", sprint_hex(&data[4], 6)); + PrintAndLogEx(INFO, "pcd : %s", sprint_hex(&data[10], 6)); } else { PrintAndLogEx(INFO, "TI : %s", sprint_hex(dctx->TI, 4)); } diff --git a/client/src/mifare/lrpcrypto.c b/client/src/mifare/lrpcrypto.c index cd4236ca0..98809ecdd 100644 --- a/client/src/mifare/lrpcrypto.c +++ b/client/src/mifare/lrpcrypto.c @@ -195,7 +195,7 @@ void LRPDecode(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *resp, si void LRPEncDec(uint8_t *key, uint8_t *iv, bool encode, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen) { LRPContext ctx = {0}; - LRPSetKeyEx(&ctx, key, iv, 4 * 2, 0, false); + LRPSetKeyEx(&ctx, key, iv, 4 * 2, 0, true); if (encode) LRPEncode(&ctx, data, datalen, resp, resplen); else From afadc088d75b4e2ca92e89a3a58d22630fa9ef09 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 19 Aug 2021 00:40:30 +0300 Subject: [PATCH 16/17] non first lrp authenticate works --- client/src/mifare/desfirecore.c | 42 ++++++++++++++++----------- client/src/mifare/desfiresecurechan.c | 4 +++ 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 1c5748d91..1a99ab59d 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -260,6 +260,10 @@ const char *DesfireAuthErrorToStr(int error) { return "Authentication failed. Cannot verify Session Key."; case 12: return "Authentication failed. Cannot verify CMAC."; + case 50: + return "PICC returned not an AES answer"; + case 51: + return "PICC returned not an LRP answer"; case 100: return "Can't find auth method for provided channel parameters."; case 200: @@ -1212,7 +1216,7 @@ static int DesfireAuthenticateEV2(DesfireContext *dctx, DesfireSecureChannel sec PrintAndLogEx(INFO, _CYAN_("Auth %s:") " cmd: 0x%02x keynum: 0x%02x key: %s", (firstauth) ? "first" : "non-first", subcommand, dctx->keyNum, sprint_hex(key, 16)); // Let's send our auth command - uint8_t cdata[] = {dctx->keyNum, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t cdata[] = {dctx->keyNum, 0x00}; int res = DesfireExchangeEx(false, dctx, subcommand, cdata, (firstauth) ? sizeof(cdata) : 1, &respcode, recv_data, &recv_len, false, 0); if (res != PM3_SUCCESS) { return 1; @@ -1228,10 +1232,13 @@ static int DesfireAuthenticateEV2(DesfireContext *dctx, DesfireSecureChannel sec size_t rdataindx = 0; if (recv_len != CRYPTO_AES_BLOCK_SIZE) { - if (recv_len == CRYPTO_AES_BLOCK_SIZE + 1) + if (recv_len == CRYPTO_AES_BLOCK_SIZE + 1) { + if (recv_data[0] != 0x00) + return 50; rdataindx = 1; - else + } else { return 4; + } } // Part 2 @@ -1396,7 +1403,7 @@ static int DesfireAuthenticateLRP(DesfireContext *dctx, DesfireSecureChannel sec PrintAndLogEx(INFO, _CYAN_("Auth %s:") " cmd: 0x%02x keynum: 0x%02x key: %s", (firstauth) ? "first" : "non-first", subcommand, dctx->keyNum, sprint_hex(key, 16)); // Let's send our auth command - uint8_t cdata[] = {dctx->keyNum, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t cdata[] = {dctx->keyNum, 0x01, 0x02}; int res = DesfireExchangeEx(false, dctx, subcommand, cdata, (firstauth) ? sizeof(cdata) : 1, &respcode, recv_data, &recv_len, false, 0); if (res != PM3_SUCCESS) { return 1; @@ -1414,10 +1421,8 @@ static int DesfireAuthenticateLRP(DesfireContext *dctx, DesfireSecureChannel sec return 4; } - if (recv_data[0] != 0x01) { - PrintAndLogEx(WARNING, "NOT LRP! rec data[0]=: 0x%02x", recv_data[0]); - //return 50; - } + if (recv_data[0] != 0x01) + return 51; // PICC return RndB in plain memcpy(RndB, &recv_data[1], 16); @@ -1468,26 +1473,29 @@ static int DesfireAuthenticateLRP(DesfireContext *dctx, DesfireSecureChannel sec // check mac memcpy(tmp, RndB, CRYPTO_AES_BLOCK_SIZE); memcpy(tmp + CRYPTO_AES_BLOCK_SIZE, RndA, CRYPTO_AES_BLOCK_SIZE); - memcpy(tmp + CRYPTO_AES_BLOCK_SIZE * 2, recv_data, CRYPTO_AES_BLOCK_SIZE); + if (firstauth) + memcpy(tmp + CRYPTO_AES_BLOCK_SIZE * 2, recv_data, CRYPTO_AES_BLOCK_SIZE); + LRPSetKey(&ctx, sessionkey, 0, true); - LRPCMAC(&ctx, tmp, CRYPTO_AES_BLOCK_SIZE * 3, cmac); - if (memcmp(&recv_data[CRYPTO_AES_BLOCK_SIZE], cmac, CRYPTO_AES_BLOCK_SIZE) != 0) { + LRPCMAC(&ctx, tmp, (firstauth) ? CRYPTO_AES_BLOCK_SIZE * 3 : CRYPTO_AES_BLOCK_SIZE * 2, cmac); + uint8_t *recCMAC = &recv_data[(firstauth) ? CRYPTO_AES_BLOCK_SIZE : 0]; + if (memcmp(recCMAC, cmac, CRYPTO_AES_BLOCK_SIZE) != 0) { if (g_debugMode > 1) { - PrintAndLogEx(DEBUG, "Expected cmac : %s", sprint_hex(&recv_data[CRYPTO_AES_BLOCK_SIZE], CRYPTO_AES_BLOCK_SIZE)); + PrintAndLogEx(DEBUG, "Expected cmac : %s", sprint_hex(recCMAC, CRYPTO_AES_BLOCK_SIZE)); PrintAndLogEx(DEBUG, "Generated cmac : %s", sprint_hex(cmac, CRYPTO_AES_BLOCK_SIZE)); } return 12; } // decode data - LRPSetKeyEx(&ctx, sessionkey, dctx->IV, 4 * 2, 1, false); - size_t declen = 0; - LRPDecode(&ctx, recv_data, 16, data, &declen); - memcpy(dctx->IV, ctx.counter, 4); + if (firstauth) { + LRPSetKeyEx(&ctx, sessionkey, dctx->IV, 4 * 2, 1, false); + size_t declen = 0; + LRPDecode(&ctx, recv_data, 16, data, &declen); + memcpy(dctx->IV, ctx.counter, 4); PrintAndLogEx(INFO, "--decoded <%d>: %s", declen, sprint_hex(data, 16)); PrintAndLogEx(INFO, "iv : %s", sprint_hex(dctx->IV, 4)); - if (firstauth) { dctx->cmdCntr = 0; memcpy(dctx->TI, data, 4); } diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 551250e7a..5a232b921 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -137,6 +137,10 @@ static const AllowedChannelModesS AllowedChannelModes[] = { {ISO7816_READ_BINARY, DACEV1, DCCISO, DCMMACed}, {ISO7816_READ_RECORDS, DACEV1, DCCISO, DCMMACed}, + + // LRP channel separately + {MFDES_AUTHENTICATE_EV2F, DACLRP, DCCNative, DCMPlain}, + {MFDES_AUTHENTICATE_EV2NF, DACLRP, DCCNative, DCMPlain}, }; #define CMD_HEADER_LEN_ALL 0xffff From 1ebeb9b151a1a0234a7d052282cbe66710502c9f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 19 Aug 2021 00:44:26 +0300 Subject: [PATCH 17/17] remove debug --- client/src/mifare/desfirecore.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 1a99ab59d..f081bc8a1 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1493,8 +1493,6 @@ static int DesfireAuthenticateLRP(DesfireContext *dctx, DesfireSecureChannel sec size_t declen = 0; LRPDecode(&ctx, recv_data, 16, data, &declen); memcpy(dctx->IV, ctx.counter, 4); -PrintAndLogEx(INFO, "--decoded <%d>: %s", declen, sprint_hex(data, 16)); -PrintAndLogEx(INFO, "iv : %s", sprint_hex(dctx->IV, 4)); dctx->cmdCntr = 0; memcpy(dctx->TI, data, 4);