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) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index ce8844aae..004d788a1 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); @@ -488,14 +505,14 @@ 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); 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; @@ -546,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; } @@ -605,17 +624,11 @@ 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) + + res = DesfireAnticollision(false); + 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 (cardtype == DESFIRE_EV2 || @@ -639,6 +652,15 @@ static int CmdHF14ADesInfo(const char *Cmd) { } } + 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")); @@ -1311,7 +1333,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"), @@ -1325,7 +1347,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; @@ -1567,7 +1589,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 @@ -1581,7 +1603,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 +1718,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, @@ -1709,7 +1732,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"), @@ -1725,7 +1748,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 +1870,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; @@ -1935,8 +1958,9 @@ 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_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 }; @@ -1947,29 +1971,30 @@ 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); + uint32_t id = 0x000000; + DesfireISOSelectWay selectway = ISW6bAID; + 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); - res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, false, verbose); + res = DesfireSelectAndAuthenticateW(&dctx, securechann, selectway, id, false, 0, 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_("%0*x") " selected and authenticated " _GREEN_("succesfully"), DesfireSelectWayToStr(selectway), selectway == ISW6bAID ? 6 : 4, id); PrintAndLogEx(SUCCESS, _CYAN_("Context: ")); DesfirePrintContext(&dctx); @@ -2001,15 +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)\n" - "06h DF Name renaming\n" - "08h File renaming\n" - "09h Value file configuration\n" - "0Ah Failed authentication counter setting\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 [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)"); + "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\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, @@ -2022,8 +2049,9 @@ 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(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 @@ -2035,22 +2063,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, &securechann, DCMEncrypted, &appid); + 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); @@ -2066,13 +2095,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; @@ -2112,7 +2141,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)"), @@ -2130,7 +2159,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; @@ -2271,7 +2300,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."), @@ -2290,7 +2319,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; @@ -2435,7 +2464,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 }; @@ -2447,7 +2476,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; @@ -2497,7 +2526,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); @@ -2507,7 +2536,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; @@ -2572,7 +2601,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 }; @@ -2584,7 +2613,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; @@ -2629,7 +2658,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 }; @@ -2642,7 +2671,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; @@ -2690,7 +2719,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 @@ -2703,7 +2732,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; @@ -2762,7 +2791,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)"), @@ -2776,7 +2805,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; @@ -2859,7 +2888,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 }; @@ -2871,7 +2900,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; @@ -2937,7 +2966,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 }; @@ -2949,7 +2978,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; @@ -3003,7 +3032,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 }; @@ -3015,7 +3044,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; @@ -3075,7 +3104,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 @@ -3089,7 +3118,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; @@ -3144,7 +3173,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 @@ -3158,7 +3187,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; @@ -3213,7 +3242,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"), @@ -3228,7 +3257,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; @@ -3383,7 +3412,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."), @@ -3405,7 +3434,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; @@ -3523,7 +3552,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)"), @@ -3551,7 +3580,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; @@ -3661,7 +3690,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"), @@ -3688,7 +3717,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; @@ -3787,7 +3816,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)"), @@ -3815,7 +3844,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; @@ -3904,7 +3933,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"), @@ -3929,7 +3958,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; @@ -4017,7 +4046,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"), @@ -4032,7 +4061,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; @@ -4090,7 +4119,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"), @@ -4107,7 +4136,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; @@ -4248,7 +4277,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"), @@ -4263,7 +4292,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; @@ -4582,7 +4611,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"), @@ -4602,7 +4631,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 +4690,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; @@ -4758,7 +4787,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"), @@ -4783,7 +4812,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 +4901,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; @@ -5094,7 +5123,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 @@ -5108,7 +5137,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; @@ -5164,7 +5193,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"), @@ -5180,7 +5209,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; @@ -5229,7 +5258,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 @@ -5243,7 +5272,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 82fa4f81c..f081bc8a1 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); @@ -257,6 +258,12 @@ 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 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: @@ -289,6 +296,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); } @@ -887,14 +926,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; @@ -921,34 +971,36 @@ 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 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") "."); @@ -956,7 +1008,7 @@ int DesfireSelectAndAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel s } if (verbose) - PrintAndLogEx(INFO, "Application iso id %04x file iso id %04x is " _GREEN_("selected"), isoappid, isofileid); + PrintAndLogEx(INFO, "Application %s %04x file iso id %04x is " _GREEN_("selected"), DesfireSelectWayToStr(way), id, isofileid); } if (!noauth) { @@ -977,6 +1029,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 @@ -1160,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[2] = {dctx->keyNum, 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; @@ -1174,12 +1230,19 @@ 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) { + if (recv_data[0] != 0x00) + return 50; + 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)) @@ -1323,6 +1386,138 @@ 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 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 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, 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; + } + + if (!recv_len) { + return 2; + } + + if (respcode != MFDES_ADDITIONAL_FRAME) { + return 3; + } + + if (recv_len != CRYPTO_AES_BLOCK_SIZE + 1) { + return 4; + } + + if (recv_data[0] != 0x01) + return 51; + + // PICC return RndB in plain + memcpy(RndB, &recv_data[1], 16); + + if (g_debugMode > 1) { + PrintAndLogEx(DEBUG, "RndB: %s", sprint_hex(RndB, CRYPTO_AES_BLOCK_SIZE)); + } + + // cmac(sessionkey, rnda+rndb) + uint8_t sessionkey[32] = {0}; + DesfireGenSessionKeyLRP(key, RndA, RndB, false, sessionkey); + + uint8_t tmp[CRYPTO_AES_BLOCK_SIZE * 4] = {0}; + memcpy(tmp, RndA, CRYPTO_AES_BLOCK_SIZE); + memcpy(tmp + CRYPTO_AES_BLOCK_SIZE, RndB, CRYPTO_AES_BLOCK_SIZE); + + 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, "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); + if (res != PM3_SUCCESS) { + return 7; + } + + if (!recv_len) { + return 8; + } + + if (respcode != MFDES_S_OPERATION_OK) { + return 9; + } + + // Part 4 + uint8_t data[64] = {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); + if (firstauth) + memcpy(tmp + CRYPTO_AES_BLOCK_SIZE * 2, recv_data, CRYPTO_AES_BLOCK_SIZE); + + LRPSetKey(&ctx, sessionkey, 0, true); + 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(recCMAC, CRYPTO_AES_BLOCK_SIZE)); + PrintAndLogEx(DEBUG, "Generated cmac : %s", sprint_hex(cmac, CRYPTO_AES_BLOCK_SIZE)); + } + return 12; + } + + // decode data + 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); + + dctx->cmdCntr = 0; + memcpy(dctx->TI, data, 4); + } + + 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[4], 6)); + PrintAndLogEx(INFO, "pcd : %s", sprint_hex(&data[10], 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); @@ -1349,6 +1544,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; } @@ -2219,8 +2417,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 +2430,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 +2926,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..300ebe8d6 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); @@ -169,13 +170,16 @@ 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); 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 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); void DesfireCheckAuthCommandsPrint(AuthCommandsChk *authCmdCheck); diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index d4b1a311f..296d88da1 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; @@ -118,6 +119,9 @@ size_t DesfireGetMACLength(DesfireContext *ctx) { case DACEV2: mac_length = 8; break; + case DACLRP: + mac_length = 8; + break; } return mac_length; } @@ -257,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) @@ -582,6 +591,26 @@ 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; + + LRPContext ctx = {0}; + LRPSetKey(&ctx, key, 0, true); + LRPCMAC(&ctx, data, 32, sessionkey); +} + 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 a5de60a87..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; @@ -45,7 +46,8 @@ typedef enum { DACNone, DACd40, DACEV1, - DACEV2 + DACEV2, + DACLRP, } DesfireSecureChannel; typedef enum { @@ -75,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; @@ -122,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/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 45730ffad..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 @@ -387,6 +391,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 +608,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; diff --git a/client/src/mifare/desfiretest.c b/client/src/mifare/desfiretest.c index 8ebb66428..05df8da68 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 49 +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) diff --git a/client/src/mifare/lrpcrypto.c b/client/src/mifare/lrpcrypto.c index e274b660b..98809ecdd 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, true); + 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; @@ -265,3 +275,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..9b2e8b650 100644 --- a/client/src/mifare/lrpcrypto.h +++ b/client/src/mifare/lrpcrypto.h @@ -54,7 +54,9 @@ 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); #endif // __LRPCRYPTO_H