From 47a851df2ac62741c583a892e2821aaae02f5c31 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 15 Jun 2021 11:37:32 +0200 Subject: [PATCH 001/309] maur keys --- client/dictionaries/mfc_default_keys.dic | 46 +++++++++++++++++++++- client/dictionaries/mfdes_default_keys.dic | 1 + client/dictionaries/mfp_default_keys.dic | 1 + 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index d22d2e7c2..d2c41cbe7 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -6,7 +6,8 @@ ffffffffffff # Defaultkey(firstkeyusedbyprogramifnouserdefinedkey) 000000000000 # Blankkey a0a1a2a3a4a5 # NFC Forum MADkey -A5A4A3A2A1A0 # MAD access key (reversed) +A5A4A3A2A1A0 # MAD access key A (reversed) +89ECA97F8C2A # MAD access key B b0b1b2b3b4b5 c0c1c2c3c4c5 d0d1d2d3d4d5 @@ -289,6 +290,49 @@ c2b7ec7d4eb1 ac70ca327a04 eb0a8ff88ade # +# Transport system Metromoney +2803bcb0c7e1 +9c616585e26d +4fa9eb49f75e +2dade48942c5 +a160fcd5ec4c +112233445566 +361a62f35bc9 +# +# Transport system Spain +83f3cb98c258 +070d486bc555 +a9b018868cc1 +9dcdb136110c +749934cc8ed3 +506db955f161 +f088a85e71d7 +72b458d60363 +70c714869dc7 +b32464412ee3 +f253c30568c4 +1c68315674ac +cfe63749080a +c1e6f8afc9ec +dd0de3ba08a6 +3d923eb73534 +ff94f86b09a6 +d61707ffdfb1 +8223205047b6 +9951a273dee7 +c9449301af93 +66695a45c9fa +89aa9d743812 +c41514defc07 +c52876869800 +5353b3aecb53 +2e4169a5c79d +4bb747e48c2a +6285a1c8eb5c +5145c34dba19 +25352912cd8d +81b20c274c3f +# # Data from https://github.com/RadioWar/NFCGUI 44dd5a385aaf 21a600056cb0 diff --git a/client/dictionaries/mfdes_default_keys.dic b/client/dictionaries/mfdes_default_keys.dic index a26d13d32..9e0a50fd0 100644 --- a/client/dictionaries/mfdes_default_keys.dic +++ b/client/dictionaries/mfdes_default_keys.dic @@ -9,6 +9,7 @@ 6AC292FAA1315B4D858AB3A3D7D5933A 404142434445464748494a4b4c4d4e4f 3112B738D8862CCD34302EB299AAB456 # Gallagher AES (https://pastebin.com/GkbGLz8r) +47454D5850524553534F53414D504C45 # Gemalto 00112233445566778899aabbccddeeff 2b7e151628aed2a6abf7158809cf4f3c fbeed618357133667c85e08f7236a8de diff --git a/client/dictionaries/mfp_default_keys.dic b/client/dictionaries/mfp_default_keys.dic index a063e34ad..f8fcc6972 100644 --- a/client/dictionaries/mfp_default_keys.dic +++ b/client/dictionaries/mfp_default_keys.dic @@ -1,3 +1,4 @@ +47454D5850524553534F53414D504C45 # Gemalto ffffffffffffffffffffffffffffffff 00000000000000000000000000000000 a0a1a2a3a4a5a6a7a0a1a2a3a4a5a6a7 From 41c755e12b61ffca55c0df0c9f1fd0dc805da693 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 15 Jun 2021 11:38:06 +0200 Subject: [PATCH 002/309] some lua colors --- client/luascripts/hf_mfu_magicwrite.lua | 27 +++++++++++++------------ 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/client/luascripts/hf_mfu_magicwrite.lua b/client/luascripts/hf_mfu_magicwrite.lua index c01f043fe..199aec7c0 100644 --- a/client/luascripts/hf_mfu_magicwrite.lua +++ b/client/luascripts/hf_mfu_magicwrite.lua @@ -12,29 +12,30 @@ local err_lock = 'use -k or change cfg0 block' copyright = 'Copyright (c) 2017 IceSQL AB. All rights reserved.' author = 'Christian Herrmann' -version = 'v1.1.3' +version = 'v1.1.4' desc = 'This script enables easy programming of a MAGIC NTAG 21* card' example = [[ - -- wipe tag - script run hf_mfu_magicwrite -w - - -- wipe a locked down tag by giving the password - script run hf_mfu_magicwrite -k ffffffff -w - - --read magic tag configuration - script run hf_mfu_magicwrite -c + -- read magic tag configuration + ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -c ]]..ansicolors.reset..[[ -- set uid - script run hf_mfu_magicwrite -u 04112233445566 + ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -u 04112233445566 ]]..ansicolors.reset..[[ -- set pwd / pack - script run hf_mfu_magicwrite -p 11223344 -a 8080 + ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -p 11223344 -a 8080 ]]..ansicolors.reset..[[ -- set version to NTAG213 - script run hf_mfu_magicwrite -v 0004040201000f03 + ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -v 0004040201000f03 ]]..ansicolors.reset..[[ -- set signature - script run hf_mfu_magicwrite -s 1122334455667788990011223344556677889900112233445566778899001122 + ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -s 1122334455667788990011223344556677889900112233445566778899001122 ]]..ansicolors.reset..[[ + + -- wipe tag + ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -w ]]..ansicolors.reset..[[ + + -- wipe a locked down tag by giving the password + ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -k ffffffff -w ]]..ansicolors.reset..[[ + ]] usage = [[ script run hf_mfu_easywrite -h -k -c -w -u -t -p -a -s -o -v From 7bfc3d8f58de5bfeec67016c1ef388e7c178bbcd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 15 Jun 2021 11:38:59 +0200 Subject: [PATCH 003/309] fix spiffs comms --- client/src/scripting.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/scripting.c b/client/src/scripting.c index 37769bffe..0184c78a5 100644 --- a/client/src/scripting.c +++ b/client/src/scripting.c @@ -342,12 +342,12 @@ static int l_GetFromFlashMemSpiffs(lua_State *L) { return returnToLuaWithError(L, "Filename missing or invalid"); // get size from spiffs itself ! - SendCommandMIX(CMD_SPIFFS_STAT, 0, 0, 0, (uint8_t *)destfilename, 32); + SendCommandNG(CMD_SPIFFS_STAT, (uint8_t *)destfilename, 32); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) + if (!WaitForResponseTimeout(CMD_SPIFFS_STAT, &resp, 2000)) return returnToLuaWithError(L, "No response from the device"); - len = resp.oldarg[0]; + len = resp.data.asDwords[0]; if (len == 0) return returnToLuaWithError(L, "Filename invalid or empty"); From 0cc310df6242b7b246344951d92a31580e150629 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 17 Jun 2021 13:24:16 +0300 Subject: [PATCH 004/309] fixed cipurse `hf search` behavior and add some aid search to link to commands --- client/src/cmdhf.c | 11 ++-------- client/src/cmdhf14a.c | 48 ++++++++++++++++++++++++++++++++++++++++++- client/src/cmdhf14a.h | 8 ++++++++ 3 files changed, 57 insertions(+), 10 deletions(-) diff --git a/client/src/cmdhf.c b/client/src/cmdhf.c index 6fd9faaac..714847623 100644 --- a/client/src/cmdhf.c +++ b/client/src/cmdhf.c @@ -90,6 +90,8 @@ int CmdHFSearch(const char *Cmd) { if (infoHF14A(false, false, false) > 0) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 14443-A tag") " found\n"); res = PM3_SUCCESS; + + infoHF14A4Applications(); } } @@ -129,15 +131,6 @@ int CmdHFSearch(const char *Cmd) { } } - PROMPT_CLEARLINE; - PrintAndLogEx(INPLACE, " Searching for Cipurse tag..."); - if (IfPm3Iso14443a()) { - if (CheckCardCipurse()) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Cipurse tag") " found\n"); - res = PM3_SUCCESS; - } - } - // 14b is the longest test PROMPT_CLEARLINE; PrintAndLogEx(INPLACE, " Searching for ISO14443-B tag..."); diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 6396323ca..5f971abe2 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -169,6 +169,17 @@ const char *getTagInfo(uint8_t uid) { return manufactureMapping[ARRAYLEN(manufactureMapping) - 1].desc; } +static const hintAIDListT hintAIDList[] = { + // AID, AID len, name, hint - how to use + { "\xA0\x00\x00\x06\x47\x2F\x00\x01", 8, "FIDO", "try hf fido commands" }, + { "\xA0\x00\x00\x03\x08\x00\x00\x10\x00\x01\x00", 11, "PIV", "" }, + { "\xD2\x76\x00\x01\x24\x01", 8, "OpenPGP", "" }, + { "\x31\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31 (pse)", 14, "EMV", "try hf emv commands" }, + { "\x32\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31 (ppse)", 14, "EMV", "try hf emv commands" }, + { "\x41\x44\x20\x46\x31", 5, "CIPURSE", "try hf cipurse commands" }, + { "\xd2\x76\x00\x00\x85\x01\x00", 7, "desfire", "try hf mfdes commands" }, +}; + // iso14a apdu input frame length static uint16_t frameLength = 0; uint16_t atsFSC[] = {16, 24, 32, 40, 48, 64, 96, 128, 256}; @@ -865,7 +876,7 @@ int SelectCard14443A_4(bool disconnect, iso14a_card_select_t *card) { // check result if (resp.oldarg[0] == 0) { - PrintAndLogEx(ERR, "No card in field"); + PrintAndLogEx(ERR, "No card in fieldxx"); return PM3_ECARDEXCHANGE; } @@ -2131,6 +2142,41 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { return select_status; } +int infoHF14A4Applications(void) { + bool ActivateField = true; + bool found = false; + for (int i = 0; i < ARRAYLEN(hintAIDList); i++) { + uint16_t sw = 0; + uint8_t result[1024] = {0}; + size_t resultlen = 0; + int res = Iso7816Select(CC_CONTACTLESS, ActivateField, true, (uint8_t *)hintAIDList[i].aid, hintAIDList[i].aid_length, result, sizeof(result), &resultlen, &sw); + ActivateField = false; + if (res) + continue; + + if (sw == 0x9000 || sw == 0x6283 || sw == 0x6285) { + if (!found) { + PrintAndLogEx(INFO, "----------------- " _CYAN_("Short AID search") " -----------------"); + found = true; + } + + if (sw == 0x9000) { + PrintAndLogEx(SUCCESS, "Application " _CYAN_("%s") " ( " _GREEN_("ok") " )", hintAIDList[i].desc); + if (strlen(hintAIDList[i].hint)) + PrintAndLogEx(INFO, "%s", hintAIDList[i].hint); + } else { + PrintAndLogEx(WARNING, "Application " _CYAN_("%s") " ( " _RED_("blocked") " )", hintAIDList[i].desc); + } + } + } + + if (found) + PrintAndLogEx(INFO, "---------------------------------------------------"); + + DropField(); + return found; +} + static uint16_t get_sw(uint8_t *d, uint8_t n) { if (n < 2) { return 0; diff --git a/client/src/cmdhf14a.h b/client/src/cmdhf14a.h index 874a073c5..c9d98cff1 100644 --- a/client/src/cmdhf14a.h +++ b/client/src/cmdhf14a.h @@ -22,6 +22,13 @@ typedef struct { const char *desc; } manufactureName; +typedef struct { + const char *aid; + const uint8_t aid_length; + const char *desc; + const char *hint; +} hintAIDListT; + int CmdHF14A(const char *Cmd); int CmdHF14ASniff(const char *Cmd); // used by hf topaz sniff int CmdHF14ASim(const char *Cmd); // used by hf mfu sim @@ -30,6 +37,7 @@ int CmdHF14ANdefRead(const char *Cmd); int hf14a_getconfig(hf14a_config *config); int hf14a_setconfig(hf14a_config *config, bool verbose); int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search); +int infoHF14A4Applications(void); const char *getTagInfo(uint8_t uid); int Hf14443_4aGetCardData(iso14a_card_select_t *card); int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); From da8c33f4c050898d15e4052d557eb5ed0d187baa Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 17 Jun 2021 13:32:38 +0300 Subject: [PATCH 005/309] small fix --- client/src/cmdhf14a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 5f971abe2..2ec6358b5 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -876,7 +876,7 @@ int SelectCard14443A_4(bool disconnect, iso14a_card_select_t *card) { // check result if (resp.oldarg[0] == 0) { - PrintAndLogEx(ERR, "No card in fieldxx"); + PrintAndLogEx(ERR, "No card in field"); return PM3_ECARDEXCHANGE; } From c5f24a24a4e74b583407ff896a547f13e7a9f093 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 17 Jun 2021 13:44:14 +0300 Subject: [PATCH 006/309] make style and small fix --- client/luascripts/hf_14a_protectimus_nfc.lua | 24 ++++++++++---------- client/src/cipurse/cipursecore.c | 20 ++++++++-------- client/src/cmdhf.c | 2 +- client/src/cmdhf14a.c | 6 ++--- doc/commands.json | 4 ++-- tools/fpga_compress/fpga_compress.c | 4 ++-- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/client/luascripts/hf_14a_protectimus_nfc.lua b/client/luascripts/hf_14a_protectimus_nfc.lua index 77b595cd5..2ff3fec06 100644 --- a/client/luascripts/hf_14a_protectimus_nfc.lua +++ b/client/luascripts/hf_14a_protectimus_nfc.lua @@ -81,7 +81,7 @@ function getUnixTime(datetime) local datetime_pattern = "(%d+)-(%d+)-(%d+)T(%d+):(%d+):(%d+)+(%d+):(%d+)" local new_year, new_month, new_day, new_hour, new_minute, new_seconds, new_hour_offset, new_minute_offset = datetime:match(datetime_pattern) - if new_year == nil or new_month == nil or new_day == nil or + if new_year == nil or new_month == nil or new_day == nil or new_hour == nil or new_minute == nil or new_seconds == nil or new_hour_offset == nil or new_minute_offset == nil then @@ -111,7 +111,7 @@ function sendRaw(rawdata, options) -- arg1 is the defined flags for sending "raw" ISO 14443A package arg1 = flags, - + -- arg2 contains the length, which is half the length of the ASCII -- string data arg2 = string.len(rawdata) / 2, @@ -137,7 +137,7 @@ function readOTP(show_output) lib14a.disconnect() return oops(err) end - + -- parse the response local cmd_response = Command.parse(res) local len = tonumber(cmd_response.arg1) * 2 @@ -160,7 +160,7 @@ function readOTP(show_output) if show_output then print("[" .. ansicolors.green .. "+" .. ansicolors.reset .. "] OTP: " .. ansicolors.green .. otp_value .. ansicolors.reset) end - else + else print("[" .. ansicolors.red .. "-" .. ansicolors.reset .."] Error: Could not read the OTP") otp_value = nil end @@ -183,7 +183,7 @@ function readInfo(show_output) lib14a.disconnect() return oops(err) end - + -- parse the response local cmd_response = Command.parse(res) local len = tonumber(cmd_response.arg1) * 2 @@ -233,7 +233,7 @@ function readInfo(show_output) end return otp_interval - else + else print("[" .. ansicolors.red .. "-" .. ansicolors.reset .."] Error: Could not read the token info") otp_value = nil end @@ -261,7 +261,7 @@ function bruteforceCommands() lib14a.disconnect() return oops(err) end - + -- parse the response local cmd_response = Command.parse(res) local len = tonumber(cmd_response.arg1) * 2 @@ -287,7 +287,7 @@ function setTime(time, otp_interval) -- build the raw command data local data = "120000" ..string.format("%02x", otp_interval) .. string.format("%08x", time_var1) .. string.format("%02x", time_var2) - + -- calculate XOR checksum on data local checksum = 0 for i = 1, #data, 2 do @@ -306,7 +306,7 @@ function setTime(time, otp_interval) lib14a.disconnect() return oops(err) end - + -- parse the response local cmd_response = Command.parse(res) local len = tonumber(cmd_response.arg1) * 2 @@ -343,8 +343,8 @@ function timeTravelAttack(datetime_string, otp_interval) -- read the OTP local otp = readOTP(false) - print(string.format("[" .. ansicolors.green .. "+" .. ansicolors.reset .. "] The future OTP on " .. - ansicolors.yellow .. "%s (%d) " .. ansicolors.reset .. "is " .. + print(string.format("[" .. ansicolors.green .. "+" .. ansicolors.reset .. "] The future OTP on " .. + ansicolors.yellow .. "%s (%d) " .. ansicolors.reset .. "is " .. ansicolors.green .. "%s" .. ansicolors.reset, datetime_string, future_time, otp)) -- reset the current time @@ -372,7 +372,7 @@ function main(args) if o == 'h' then return help() end if o == 'i' then operation = READ_INFO end if o == 'r' then operation = READ_OTP end - if o == 't' then + if o == 't' then operation = TIME_TRAVELER_ATTACK target_time = a end diff --git a/client/src/cipurse/cipursecore.c b/client/src/cipurse/cipursecore.c index 70d2b51d3..03ab558af 100644 --- a/client/src/cipurse/cipursecore.c +++ b/client/src/cipurse/cipursecore.c @@ -218,23 +218,23 @@ static void CIPURSEPrintPersoMode(uint8_t data) { PrintAndLogEx(INFO, "Perso: EMV"); if (data & 0x04) PrintAndLogEx(INFO, "Perso: transaction supported"); - + } - + static void CIPURSEPrintProfileInfo(uint8_t data) { if (data & 0x01) PrintAndLogEx(INFO, "Profile: L"); if (data & 0x02) PrintAndLogEx(INFO, "Profile: S"); if (data & 0x04) - PrintAndLogEx(INFO, "Profile: T"); + PrintAndLogEx(INFO, "Profile: T"); } static void CIPURSEPrintManufacturerInfo(uint8_t data) { - if (data == 0) - PrintAndLogEx(INFO, "Manufacturer: n/a"); - else - PrintAndLogEx(INFO, "Manufacturer: %s", getTagInfo(data)); // getTagInfo from cmfhf14a.h + if (data == 0) + PrintAndLogEx(INFO, "Manufacturer: n/a"); + else + PrintAndLogEx(INFO, "Manufacturer: %s", getTagInfo(data)); // getTagInfo from cmfhf14a.h } void CIPURSEPrintInfoFile(uint8_t *data, size_t len) { @@ -245,13 +245,13 @@ void CIPURSEPrintInfoFile(uint8_t *data, size_t len) { PrintAndLogEx(INFO, "------------ INFO ------------"); PrintAndLogEx(INFO, "CIPURSE version %d revision %d", data[0], data[1]); - + if (len >= 3) CIPURSEPrintPersoMode(data[2]); - + if (len >= 4) CIPURSEPrintProfileInfo(data[3]); - + if (len >= 9) CIPURSEPrintManufacturerInfo(data[8]); } diff --git a/client/src/cmdhf.c b/client/src/cmdhf.c index 714847623..43c3f2258 100644 --- a/client/src/cmdhf.c +++ b/client/src/cmdhf.c @@ -90,7 +90,7 @@ int CmdHFSearch(const char *Cmd) { if (infoHF14A(false, false, false) > 0) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 14443-A tag") " found\n"); res = PM3_SUCCESS; - + infoHF14A4Applications(); } } diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 2ec6358b5..72f021b60 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -174,8 +174,8 @@ static const hintAIDListT hintAIDList[] = { { "\xA0\x00\x00\x06\x47\x2F\x00\x01", 8, "FIDO", "try hf fido commands" }, { "\xA0\x00\x00\x03\x08\x00\x00\x10\x00\x01\x00", 11, "PIV", "" }, { "\xD2\x76\x00\x01\x24\x01", 8, "OpenPGP", "" }, - { "\x31\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31 (pse)", 14, "EMV", "try hf emv commands" }, - { "\x32\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31 (ppse)", 14, "EMV", "try hf emv commands" }, + { "\x31\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31", 14, "EMV (pse)", "try hf emv commands" }, + { "\x32\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31", 14, "EMV (ppse)", "try hf emv commands" }, { "\x41\x44\x20\x46\x31", 5, "CIPURSE", "try hf cipurse commands" }, { "\xd2\x76\x00\x00\x85\x01\x00", 7, "desfire", "try hf mfdes commands" }, }; @@ -2159,7 +2159,7 @@ int infoHF14A4Applications(void) { PrintAndLogEx(INFO, "----------------- " _CYAN_("Short AID search") " -----------------"); found = true; } - + if (sw == 0x9000) { PrintAndLogEx(SUCCESS, "Application " _CYAN_("%s") " ( " _GREEN_("ok") " )", hintAIDList[i].desc); if (strlen(hintAIDList[i].hint)) diff --git a/doc/commands.json b/doc/commands.json index cc359e3c9..a5e3ce6ca 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -973,7 +973,7 @@ }, "help": { "command": "help", - "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log e:\\proxspace\\pm3/.proxmark3/logs/log_20210615.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", + "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log e:\\proxspace\\pm3/.proxmark3/logs/log_20210617.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", "notes": [ "auto" ], @@ -9180,6 +9180,6 @@ "metadata": { "commands_extracted": 570, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2021-06-15T12:04:40" + "extracted_on": "2021-06-17T10:40:34" } } \ No newline at end of file diff --git a/tools/fpga_compress/fpga_compress.c b/tools/fpga_compress/fpga_compress.c index 003236994..005f805c4 100644 --- a/tools/fpga_compress/fpga_compress.c +++ b/tools/fpga_compress/fpga_compress.c @@ -227,8 +227,8 @@ static int zlib_decompress(FILE *infile, FILE *outfiles[], uint8_t num_outfiles, total_size = 0; // FPGA bit file ends with 16 zeroes for (uint16_t j = 0; j < num_outfiles; j++) { - outfilesizes[j] += 16; - total_size += outfilesizes[j]; + outfilesizes[j] += 16; + total_size += outfilesizes[j]; } offset = 0; for (uint16_t k = 0; k < *outsize / (FPGA_INTERLEAVE_SIZE * num_outfiles); k++) { From b92ebfa4a460ac97eff8a2a74d8d8f1d22698a16 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 18 Jun 2021 11:59:48 +0300 Subject: [PATCH 007/309] added `hf search -v` and reworked fast aid search output --- client/src/cmdhf.c | 6 +++++- client/src/cmdhf14a.c | 46 +++++++++++++++++++++++++++++-------------- client/src/cmdhf14a.h | 2 +- 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/client/src/cmdhf.c b/client/src/cmdhf.c index 43c3f2258..8a7afeb2a 100644 --- a/client/src/cmdhf.c +++ b/client/src/cmdhf.c @@ -59,9 +59,13 @@ int CmdHFSearch(const char *Cmd) { ); void *argtable[] = { arg_param_begin, + arg_lit0("v", "verbose", "verbose output"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool verbose = arg_get_lit(ctx, 1); + CLIParserFree(ctx); int res = PM3_ESOFT; @@ -91,7 +95,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 14443-A tag") " found\n"); res = PM3_SUCCESS; - infoHF14A4Applications(); + infoHF14A4Applications(verbose); } } diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 72f021b60..2ce3e1345 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -171,13 +171,13 @@ const char *getTagInfo(uint8_t uid) { static const hintAIDListT hintAIDList[] = { // AID, AID len, name, hint - how to use - { "\xA0\x00\x00\x06\x47\x2F\x00\x01", 8, "FIDO", "try hf fido commands" }, + { "\xA0\x00\x00\x06\x47\x2F\x00\x01", 8, "FIDO", "hf fido" }, { "\xA0\x00\x00\x03\x08\x00\x00\x10\x00\x01\x00", 11, "PIV", "" }, { "\xD2\x76\x00\x01\x24\x01", 8, "OpenPGP", "" }, - { "\x31\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31", 14, "EMV (pse)", "try hf emv commands" }, - { "\x32\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31", 14, "EMV (ppse)", "try hf emv commands" }, - { "\x41\x44\x20\x46\x31", 5, "CIPURSE", "try hf cipurse commands" }, - { "\xd2\x76\x00\x00\x85\x01\x00", 7, "desfire", "try hf mfdes commands" }, + { "\x31\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31", 14, "EMV (pse)", "hf emv" }, + { "\x32\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31", 14, "EMV (ppse)", "hf emv" }, + { "\x41\x44\x20\x46\x31", 5, "CIPURSE", "hf cipurse" }, + { "\xd2\x76\x00\x00\x85\x01\x00", 7, "desfire", "hf mfdes" }, }; // iso14a apdu input frame length @@ -2142,9 +2142,10 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { return select_status; } -int infoHF14A4Applications(void) { +int infoHF14A4Applications(bool verbose) { + bool cardFound[ARRAYLEN(hintAIDList)] = {0}; bool ActivateField = true; - bool found = false; + int found = 0; for (int i = 0; i < ARRAYLEN(hintAIDList); i++) { uint16_t sw = 0; uint8_t result[1024] = {0}; @@ -2156,22 +2157,37 @@ int infoHF14A4Applications(void) { if (sw == 0x9000 || sw == 0x6283 || sw == 0x6285) { if (!found) { - PrintAndLogEx(INFO, "----------------- " _CYAN_("Short AID search") " -----------------"); - found = true; + if (verbose) + PrintAndLogEx(INFO, "----------------- " _CYAN_("Short AID search") " -----------------"); } + found++; if (sw == 0x9000) { - PrintAndLogEx(SUCCESS, "Application " _CYAN_("%s") " ( " _GREEN_("ok") " )", hintAIDList[i].desc); - if (strlen(hintAIDList[i].hint)) - PrintAndLogEx(INFO, "%s", hintAIDList[i].hint); + if (verbose) + PrintAndLogEx(SUCCESS, "Application " _CYAN_("%s") " ( " _GREEN_("ok") " )", hintAIDList[i].desc); + cardFound[i] = true; } else { - PrintAndLogEx(WARNING, "Application " _CYAN_("%s") " ( " _RED_("blocked") " )", hintAIDList[i].desc); + if (verbose) + PrintAndLogEx(WARNING, "Application " _CYAN_("%s") " ( " _RED_("blocked") " )", hintAIDList[i].desc); } } } - if (found) - PrintAndLogEx(INFO, "---------------------------------------------------"); + if (found) { + if (verbose) + PrintAndLogEx(INFO, "---------------------------------------------------"); + else + PrintAndLogEx(INFO, "Short AID search:"); + + if (found >= ARRAYLEN(hintAIDList) - 1) { + PrintAndLogEx(HINT, "Hint: card answers to all AID. It maybe the latest revision of plus/desfire/ultralight card."); + } else { + for (int i = 0; i < ARRAYLEN(hintAIDList); i++) { + if (cardFound[i] && strlen(hintAIDList[i].hint)) + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("%s") " commands", hintAIDList[i].hint); + } + } + } DropField(); return found; diff --git a/client/src/cmdhf14a.h b/client/src/cmdhf14a.h index c9d98cff1..484b43cfd 100644 --- a/client/src/cmdhf14a.h +++ b/client/src/cmdhf14a.h @@ -37,7 +37,7 @@ int CmdHF14ANdefRead(const char *Cmd); int hf14a_getconfig(hf14a_config *config); int hf14a_setconfig(hf14a_config *config, bool verbose); int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search); -int infoHF14A4Applications(void); +int infoHF14A4Applications(bool verbose); const char *getTagInfo(uint8_t uid); int Hf14443_4aGetCardData(iso14a_card_select_t *card); int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); From b2996aa69a8dd85a2d15598b6d7006746825804b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 18 Jun 2021 12:05:14 +0300 Subject: [PATCH 008/309] make style --- client/src/cmdhf14a.c | 4 ++-- doc/commands.json | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 2ce3e1345..fd8d9db9a 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -2178,9 +2178,9 @@ int infoHF14A4Applications(bool verbose) { PrintAndLogEx(INFO, "---------------------------------------------------"); else PrintAndLogEx(INFO, "Short AID search:"); - + if (found >= ARRAYLEN(hintAIDList) - 1) { - PrintAndLogEx(HINT, "Hint: card answers to all AID. It maybe the latest revision of plus/desfire/ultralight card."); + PrintAndLogEx(HINT, "Hint: card answers to all AID. It maybe the latest revision of plus/desfire/ultralight card."); } else { for (int i = 0; i < ARRAYLEN(hintAIDList); i++) { if (cardFound[i] && strlen(hintAIDList[i].hint)) diff --git a/doc/commands.json b/doc/commands.json index a5e3ce6ca..04f5535af 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -973,7 +973,7 @@ }, "help": { "command": "help", - "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log e:\\proxspace\\pm3/.proxmark3/logs/log_20210617.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", + "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log e:\\proxspace\\pm3/.proxmark3/logs/log_20210618.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", "notes": [ "auto" ], @@ -4726,9 +4726,10 @@ ], "offline": true, "options": [ - "-h, --help this help" + "-h, --help this help", + "-v, --verbose verbose output" ], - "usage": "hf search [-h]" + "usage": "hf search [-hv]" }, "hf seos help": { "command": "hf seos help", @@ -9180,6 +9181,6 @@ "metadata": { "commands_extracted": 570, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2021-06-17T10:40:34" + "extracted_on": "2021-06-18T09:04:45" } } \ No newline at end of file From 22d311e5fac1f29bc8a9815c02f8763406332bf5 Mon Sep 17 00:00:00 2001 From: mwalker33 <51802811+mwalker33@users.noreply.github.com> Date: Sat, 19 Jun 2021 11:05:59 +1000 Subject: [PATCH 009/309] Update cmdhfmfdes.c 3K3Des Authentication and Change Key patch Get Card UID (when authenticated for real UID 3Des session key patch when 1st half = 2nd Half --- client/src/cmdhfmfdes.c | 80 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 72 insertions(+), 8 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 7b6d3e26c..9cc8b402b 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -983,7 +983,10 @@ static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rp } // Part 4 - tag->session_key = &default_key; + // tag->session_key = &default_key; + tag->session_key = realloc (tag->session_key,sizeof(struct desfire_key)); + memset (tag->session_key, 0x00, sizeof(struct desfire_key)); + Desfire_session_key_new(RndA, RndB, key, tag->session_key); if (payload->mode != MFDES_AUTH_PICC) { @@ -1017,10 +1020,18 @@ static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rp } } + // If the 3Des key first 8 bytes = 2nd 8 Bytes then we are really using Singe Des + // As such we need to set the session key such that the 2nd 8 bytes = 1st 8 Bytes + if (payload->algo == MFDES_ALGO_3DES) { + if (memcmp(key->data,&key->data[8],8) == 0) + memcpy(&tag->session_key->data[8], tag->session_key->data, 8); + } + rpayload->sessionkeylen = payload->keylen; memcpy(rpayload->sessionkey, tag->session_key->data, rpayload->sessionkeylen); memset(tag->ivect, 0, MAX_CRYPTO_BLOCK_SIZE); tag->authenticated_key_no = payload->keyno; + if (tag->authentication_scheme == AS_NEW) { cmac_generate_subkeys(tag->session_key, MCD_RECEIVE); } @@ -1206,7 +1217,7 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n sAPDU apdu = {0x90, MFDES_CHANGE_KEY, 0x00, 0x00, 0x01, data}; // 0xC4 size_t cmdcnt = 0; - uint8_t csPkt[30] = {0x00}; // temp storage for AES first CheckSum + uint8_t csPkt[100] = {0x00}; // temp storage for AES/3K3Des packet to calculate checksum (size ????) uint8_t new_key_length = 16; switch (new_algo) { @@ -1264,6 +1275,11 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n memcpy(&csPkt[1], data, 18); desfire_crc32(csPkt, 19, data + 1 + cmdcnt); + } else if (new_algo == MFDES_ALGO_3K3DES) { + // 3K3Des checksum must cover : C4 + csPkt[0] = MFDES_CHANGE_KEY; + memcpy (&csPkt[1], data, 25); + desfire_crc32(csPkt, 26, data + 1 + cmdcnt); } else { desfire_crc32_append(data + 1, cmdcnt); } @@ -1281,11 +1297,16 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n break; case AS_NEW: if (new_algo == MFDES_ALGO_AES) { - // AES Checksum must cover : C4 + // AES Checksum must cover : C4 // C4 01 A0B08090E0F0C0D02030001060704050 03 - csPkt[0] = 0xC4; + csPkt[0] = MFDES_CHANGE_KEY; memcpy(&csPkt[1], data, 18); desfire_crc32(csPkt, 19, data + 1 + cmdcnt); + } else if (new_algo == MFDES_ALGO_3K3DES) { + // 3K3Des checksum must cover : C4 + csPkt[0] = MFDES_CHANGE_KEY; + memcpy (&csPkt[1], data, 25); + desfire_crc32(csPkt, 26, data + 1 + cmdcnt); } else { desfire_crc32_append(data + 1, cmdcnt); } @@ -1298,8 +1319,8 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n uint8_t *p = mifare_cryto_preprocess_data(tag, data + 1, (size_t *)&cmdcnt, 0, MDCM_ENCIPHERED | ENC_COMMAND | NO_CRC); apdu.Lc = (uint8_t)cmdcnt + 1; -// apdu.data = p; -// the above data pointed to from p did not have the key no. at the start, so copy preprocessed data after the key no. + // apdu.data = p; + // the above data pointed to from p did not have the key no. at the start, so copy preprocessed data after the key no. memcpy(&data[1], p, cmdcnt); apdu.data = data; @@ -1319,12 +1340,16 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n size_t sn = recv_len; - if (new_algo == MFDES_ALGO_AES) + if ((new_algo == MFDES_ALGO_AES) || (new_algo == MFDES_ALGO_3K3DES)) { // AES expects us to Calculate CMAC for status byte : OK 0x00 (0x91 00) // As such if we get this far without an error, we should be good // Since we are dropping the field, we dont need to maintain the CMAC etc. // Setting sn = 1 will allow the post process to just exit (as status only) + + // Simular 3K3Des has some work to validate, but as long as the reply code was 00 + // e.g. 02 fe ec 77 ca 13 e0 c2 06 [91 00 (OK)] 69 67 + sn = 1; } @@ -1609,6 +1634,15 @@ static int handler_desfire_getuid(uint8_t *uid) { sAPDU apdu = {0x90, MFDES_GET_UID, 0x00, 0x00, 0x00, NULL}; //0x51 uint32_t recv_len = 0; uint16_t sw = 0; + + // Setup the pre-process to update the IV etc. (not needed in the apdu to send to card) + size_t plen = 1; + uint8_t tmp_data[100] = { 0x00 }; // Note sure on size, but 100 is more then enough + tmp_data[0] = MFDES_GET_UID; + int8_t *p = mifare_cryto_preprocess_data(tag, tmp_data, &plen, 0, MDCM_PLAIN | CMAC_COMMAND); + (void)p; + + // Send request/apdu int res = send_desfire_cmd(&apdu, false, uid, &recv_len, &sw, 0, true); if (res != PM3_SUCCESS) @@ -1617,6 +1651,13 @@ static int handler_desfire_getuid(uint8_t *uid) { if (sw != status(MFDES_S_OPERATION_OK)) return PM3_ESOFT; + // decrypt response + size_t dlen = recv_len; + p = mifare_cryto_postprocess_data(tag, uid, &dlen, CMAC_COMMAND | CMAC_VERIFY | MAC_VERIFY | MDCM_ENCIPHERED); + (void)p; + + DropFieldDesfire(); + return res; } @@ -2390,7 +2431,27 @@ static int CmdHF14ADesGetUID(const char *Cmd) { PrintAndLogEx(ERR, "Error on getting uid."); return res; } - PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(uid, sizeof(uid))); + + // This could be done better. by the crc calc checks. + // Extract the Card UID length (needs rework to allow for 10 Byte UID + uint8_t uidlen = 16; + + // Get datalen + by removing padding. + while ((uidlen > 0) && (uid[uidlen] == 0x00)) + uidlen--; + + if (tag->authentication_scheme == AS_LEGACY) + uidlen -= 2; // 2 byte crc + else + uidlen -= 4; // 4 byte crc + + if (uidlen <= 4) // < incase we trimmed a CRC 00 or more + uidlen = 4; + else + uidlen = 7; + +// PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(uid, sizeof(uid))); + PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(uid, uidlen)); return res; } @@ -2840,6 +2901,9 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { memcpy(aid, (uint8_t *)&tag->selected_application, 3); } + // int res; + // a select here seems to invalidate the current authentication with AMK and create file fails if not open access. + // This will be managed when we track Authenticated or Note, so a place holder comment as a reminder. int res = handler_desfire_select_application(aid); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Couldn't select aid. Error %d", res); From 57729b604cc55f1f5af46a2c7e1a3f5c54198c98 Mon Sep 17 00:00:00 2001 From: mwalker33 <51802811+mwalker33@users.noreply.github.com> Date: Sat, 19 Jun 2021 13:12:10 +1000 Subject: [PATCH 010/309] Update cmdhfmfdes.c realloc update --- client/src/cmdhfmfdes.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 85748afd9..e2e315727 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -984,7 +984,14 @@ static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rp // Part 4 // tag->session_key = &default_key; - tag->session_key = realloc (tag->session_key,sizeof(struct desfire_key)); + struct desfire_key *p = realloc (tag->session_key,sizeof(struct desfire_key)); + if (!p) { + PrintAndLogEx(FAILED, "Cannot allocate memory for session keys"); + free(tag->session_key); + return PM3_EMALLOC; + } + tag->session_key = p; + memset (tag->session_key, 0x00, sizeof(struct desfire_key)); Desfire_session_key_new(RndA, RndB, key, tag->session_key); From cc63ba9f178c709737e39a48464aae800390a939 Mon Sep 17 00:00:00 2001 From: mwalker33 <51802811+mwalker33@users.noreply.github.com> Date: Sat, 19 Jun 2021 18:49:24 +1000 Subject: [PATCH 011/309] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4395946e9..158adc6ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - FIXED 'hf desfire' changekey, GetUID, 3DES sesson key tweak. (@mwalker33) - Fixed `hf fido` commands now works correctly (@merlokk) - Moved / renamed `client/resource/fido2_defparams.json` -> `client/resource/hf_fido2_defparams.json` (@merlokk) - Added `hf cipurse` commands to work with cipurse transport cards (@merlokk) From 996c7e3d8a9540f77500780c7810f5fbc794a8fb Mon Sep 17 00:00:00 2001 From: ikarus Date: Sat, 19 Jun 2021 21:29:24 +0200 Subject: [PATCH 012/309] fixed typo. --- client/src/cmdhfmf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 6731b6f79..ba9cb97c0 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -161,7 +161,7 @@ static void decode_print_st(uint16_t blockno, uint8_t *data) { PrintAndLogEx(INFO, "----------------------- " _CYAN_("Sector trailer decoder") " -----------------------"); PrintAndLogEx(INFO, "key A........ " _GREEN_("%s"), sprint_hex_inrow(data, 6)); PrintAndLogEx(INFO, "acr.......... " _GREEN_("%s"), sprint_hex_inrow(data + 6, 3)); - PrintAndLogEx(INFO, "user / gdb... " _GREEN_("%02x"), data[9]); + PrintAndLogEx(INFO, "user / gpb... " _GREEN_("%02x"), data[9]); PrintAndLogEx(INFO, "key B........ " _GREEN_("%s"), sprint_hex_inrow(data + 10, 6)); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, " # | Access rights"); From 57f9a009060aecaaa93a39bf7c760a12602122f5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 19 Jun 2021 22:15:35 +0200 Subject: [PATCH 013/309] ndef parser - now handles more ndef types --- CHANGELOG.md | 11 +- client/src/nfc/ndef.c | 389 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 351 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 158adc6ef..9d325f9d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,12 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] - - FIXED 'hf desfire' changekey, GetUID, 3DES sesson key tweak. (@mwalker33) - - Fixed `hf fido` commands now works correctly (@merlokk) + - Changed `hf nfc ndefread` - ndef parser now handles more types (@iceman1001) + - Fix `hf desfire` changekey, GetUID, 3DES sesson key tweak. (@mwalker33) + - Fix `hf fido` commands now works correctly (@merlokk) - Moved / renamed `client/resource/fido2_defparams.json` -> `client/resource/hf_fido2_defparams.json` (@merlokk) - Added `hf cipurse` commands to work with cipurse transport cards (@merlokk) - - Added '--gap' option to lf em 410x sim for more control over sim data (@mwalker) + - Added `--gap` option to lf em 410x sim for more control over sim data (@mwalker) - Changed `hf fido` - refactored load/save json objects (@iceman1001) - Moved / renamed `fido2.json` -> `client/resource/fido2_defparams.json` (@iceman1001) - Added openocd shikra support based on @ninjastyle82 patch to deprecated iceman fork (@iceman1001) @@ -17,8 +18,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added `data asn1` - a command to decode ASN1 byte arrays (@iceman1001) - Added `hf 15 disableprivacy` - from @g3gg0 fork *WIP* (@iceman1001) - Added `lf_ident_json.lua` - script to identify t55xx json dump files (@iceman1001) - - Fixed `hf iclass chk` - multithread concurrency issues solved (@iceman1001) - - Fixed hf_iceclass standalone - correct null terminator filename (@metalauricle) + - Fix `hf iclass chk` - multithread concurrency issues solved (@iceman1001) + - Fix hf_iceclass standalone - correct null terminator filename (@metalauricle) - Changed `trace list -t mfdes - added annotations for EV2, EV3 (@iceman1001)` - Changed `hf iclass lookup` - fixed swapped args (@iceman1001) - Changed `hf iclass decrypt` - added the possibility to decode the data as block6 if you have a cardhelper (@iceman1001) diff --git a/client/src/nfc/ndef.c b/client/src/nfc/ndef.c index bd1109e80..2b2dfc9c3 100644 --- a/client/src/nfc/ndef.c +++ b/client/src/nfc/ndef.c @@ -15,9 +15,16 @@ #include "ui.h" #include "util.h" // sprint_hex... #include "crypto/asn1utils.h" +#include "crypto/libpcrypto.h" +#include "ecp.h" +#include "commonutil.h" // ARRAYLEN #include "pm3_cmd.h" -#define STRBOOL(p) ((p) ? "+" : "-") +#define STRBOOL(p) ((p) ? "1" : "0") + +#define NDEF_WIFIAPPL "application/vnd.wfa" +#define NDEF_BLUEAPPL "application/vnd.bluetooth" +#define NDEF_VCARDTEXT "text/vcard" static const char *TypeNameFormat_s[] = { "Empty Record", @@ -91,6 +98,9 @@ static const char *URI_s[] = { "urn:nfc:" // 0x23 }; +static int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen); +static int ndefDecodePayload(NDEFHeader_t *ndef); + static uint16_t ndefTLVGetLength(uint8_t *data, size_t *indx) { uint16_t len = 0; if (data[0] == 0xff) { @@ -142,20 +152,123 @@ static int ndefDecodeHeader(uint8_t *data, size_t datalen, NDEFHeader_t *header) } static int ndefPrintHeader(NDEFHeader_t *header) { - PrintAndLogEx(INFO, "Header:"); + PrintAndLogEx(INFO, _CYAN_("Header info")); - PrintAndLogEx(SUCCESS, "\tMessage Begin: %s", STRBOOL(header->MessageBegin)); - PrintAndLogEx(SUCCESS, "\tMessage End: %s", STRBOOL(header->MessageEnd)); - PrintAndLogEx(SUCCESS, "\tChunk Flag: %s", STRBOOL(header->ChunkFlag)); - PrintAndLogEx(SUCCESS, "\tShort Record Bit: %s", STRBOOL(header->ShortRecordBit)); - PrintAndLogEx(SUCCESS, "\tID Len Present: %s", STRBOOL(header->IDLenPresent)); - PrintAndLogEx(SUCCESS, "\tType Name Format: [0x%02x] %s", header->TypeNameFormat, TypeNameFormat_s[header->TypeNameFormat]); + PrintAndLogEx(SUCCESS, " %s ....... Message begin", STRBOOL(header->MessageBegin)); + PrintAndLogEx(SUCCESS, " %s ...... Message end", STRBOOL(header->MessageEnd)); + PrintAndLogEx(SUCCESS, " %s ..... Chunk flag", STRBOOL(header->ChunkFlag)); + PrintAndLogEx(SUCCESS, " %s .... Short record bit", STRBOOL(header->ShortRecordBit)); + PrintAndLogEx(SUCCESS, " %s ... ID Len present", STRBOOL(header->IDLenPresent)); + PrintAndLogEx(SUCCESS, ""); - PrintAndLogEx(SUCCESS, "\tHeader length : %zu", header->len); - PrintAndLogEx(SUCCESS, "\tType length : %zu", header->TypeLen); - PrintAndLogEx(SUCCESS, "\tPayload length : %zu", header->PayloadLen); - PrintAndLogEx(SUCCESS, "\tID length : %zu", header->IDLen); - PrintAndLogEx(SUCCESS, "\tRecord length : %zu", header->RecLen); + PrintAndLogEx(SUCCESS, " Header length...... %zu", header->len); + PrintAndLogEx(SUCCESS, " Type length........ %zu", header->TypeLen); + PrintAndLogEx(SUCCESS, " Payload length..... %zu", header->PayloadLen); + PrintAndLogEx(SUCCESS, " ID length.......... %zu", header->IDLen); + PrintAndLogEx(SUCCESS, " Record length...... %zu", header->RecLen); + + PrintAndLogEx(SUCCESS, " Type name format... [ 0x%02x ] " _YELLOW_("%s"), header->TypeNameFormat, TypeNameFormat_s[header->TypeNameFormat]); + return PM3_SUCCESS; +} + +static const char *get_curve_name(mbedtls_ecp_group_id grp_id) { + switch (grp_id) { + case MBEDTLS_ECP_DP_NONE: + return ""; + case MBEDTLS_ECP_DP_SECP192R1: + return "SECP192R1"; // Domain parameters for the 192-bit curve defined by FIPS 186-4 and SEC1 + case MBEDTLS_ECP_DP_SECP224R1: + return "SECP224R1"; // Domain parameters for the 224-bit curve defined by FIPS 186-4 and SEC1 + case MBEDTLS_ECP_DP_SECP256R1: + return "SECP256R1"; // Domain parameters for the 256-bit curve defined by FIPS 186-4 and SEC1 + case MBEDTLS_ECP_DP_SECP384R1: + return "SECP384R1"; // Domain parameters for the 384-bit curve defined by FIPS 186-4 and SEC1 + case MBEDTLS_ECP_DP_SECP521R1: + return "SECP521R1"; // Domain parameters for the 521-bit curve defined by FIPS 186-4 and SEC1 + case MBEDTLS_ECP_DP_BP256R1: + return "BP256R1"; // Domain parameters for 256-bit Brainpool curve + case MBEDTLS_ECP_DP_BP384R1: + return "BP384R1"; // Domain parameters for 384-bit Brainpool curve + case MBEDTLS_ECP_DP_BP512R1: + return "BP512R1"; // Domain parameters for 512-bit Brainpool curve + case MBEDTLS_ECP_DP_CURVE25519: + return "CURVE25519"; // Domain parameters for Curve25519 + case MBEDTLS_ECP_DP_SECP192K1: + return "SECP192K1"; // Domain parameters for 192-bit "Koblitz" curve + case MBEDTLS_ECP_DP_SECP224K1: + return "SECP224K1"; // Domain parameters for 224-bit "Koblitz" curve + case MBEDTLS_ECP_DP_SECP256K1: + return "SECP256K1"; // Domain parameters for 256-bit "Koblitz" curve + case MBEDTLS_ECP_DP_CURVE448: + return "CURVE448"; // Domain parameters for Curve448 + case MBEDTLS_ECP_DP_SECP128R1: + return "SECP128R1"; // Domain parameters for the 128-bit curve used for NXP originality check + default : + return ""; + } + return ""; +} + +typedef struct { + mbedtls_ecp_group_id grp_id; + uint8_t keylen; + const char *desc; + const char *value; +} PACKED ndef_publickey_t; + +static int ndef_print_signature(uint8_t *data, uint8_t data_len, uint8_t *signature, uint8_t sign_len) { + + const ndef_publickey_t ndef_public_keys[] = { + { MBEDTLS_ECP_DP_SECP256R1, 65, "Minecraft Earth", "04760200b60315f31ff7951d0892b87930c34967dfbf57763afc775fc56a22b601f7b8fd9e47519524505322435b07d0782463f39400a39a9dbc06bab2225c082a"}, + }; + + uint8_t i; + int reason = 0; + bool is_valid = false; + for (i = 0; i < ARRAYLEN(ndef_public_keys); i++) { + + int dl = 0; + uint8_t key[ndef_public_keys[i].keylen]; + param_gethex_to_eol(ndef_public_keys[i].value, 0, key, ndef_public_keys[i].keylen, &dl); + + int res = ecdsa_signature_r_s_verify(ndef_public_keys[i].grp_id, key, data, data_len, signature, sign_len, false); + is_valid = (res == 0); + if (is_valid) { + reason = 1; + break; + } + + // try with sha256 + res = ecdsa_signature_r_s_verify(ndef_public_keys[i].grp_id, key, data, data_len, signature, sign_len, true); + is_valid = (res == 0); + if (is_valid) { + reason = 2; + break; + } + } + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "--- " _CYAN_("NDEF Signature")); + if (is_valid == false || i == ARRAYLEN(ndef_public_keys)) { + PrintAndLogEx(INFO, " Elliptic curve parameters: %s", get_curve_name(ndef_public_keys[i].grp_id)); + PrintAndLogEx(INFO, " NDEF Signature: %s", sprint_hex_inrow(signature, 32)); + PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed")); + return PM3_ESOFT; + } + + PrintAndLogEx(INFO, " IC signature public key name: %s", ndef_public_keys[i].desc); + PrintAndLogEx(INFO, "IC signature public key value: %s", ndef_public_keys[i].value); + PrintAndLogEx(INFO, " Elliptic curve parameters: %s", get_curve_name(ndef_public_keys[i].grp_id)); + PrintAndLogEx(INFO, " NDEF Signature: %s", sprint_hex_inrow(signature, 32)); + PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful")); + switch (reason) { + case 1: + PrintAndLogEx(INFO, " Params used: signature, plain"); + break; + case 2: + PrintAndLogEx(INFO, " Params used: signature, SHA256"); + break; + } return PM3_SUCCESS; } @@ -251,6 +364,8 @@ static int ndefDecodeSig2(uint8_t *sig, size_t siglen) { PrintAndLogEx(SUCCESS, "\tsignature : " _GREEN_("ECDSA-%d"), slen * 8); PrintAndLogEx(SUCCESS, "\t\tr: %s", sprint_hex(&sig[indx], slen)); PrintAndLogEx(SUCCESS, "\t\ts: %s", sprint_hex(&sig[indx + slen], slen)); + + ndef_print_signature(NULL, 0, NULL, 0); } } else { PrintAndLogEx(INFO, "\tsignature: unknown type"); @@ -301,18 +416,169 @@ static int ndefDecodeSig(uint8_t *sig, size_t siglen) { return PM3_ESOFT; } +static int ndefDecodePayloadDeviceInfo(uint8_t *payload, size_t len) { + if (payload == NULL) + return PM3_EINVARG; + if (len < 1) + return PM3_EINVARG; + + PrintAndLogEx(INFO, _CYAN_("Device information")); + uint8_t *p = payload; + p++; + uint8_t n = *(p++); + PrintAndLogEx(INFO, "Vendor........ " _YELLOW_("%.*s"), n, p); + p += n + 1; + n = *(p++); + PrintAndLogEx(INFO, "Model......... " _YELLOW_("%.*s"), n, p); + p += n + 1; + n = *(p++); + PrintAndLogEx(INFO, "Unique name... " _YELLOW_("%.*s"), n, p); + p += n + 1; + n = *(p++); + //uuid string + // record.uuid_string = '123e4567-e89b-12d3-a456-426655440000' + // 8-4-4-4-12 + char uuid[37] = {0}; + sprintf(uuid, "%s-", sprint_hex_inrow(p, 4)); + p += 4; + sprintf(uuid + strlen(uuid), "%s-", sprint_hex_inrow(p, 2)); + p += 2; + sprintf(uuid + strlen(uuid), "%s-", sprint_hex_inrow(p, 2)); + p += 2; + sprintf(uuid + strlen(uuid), "%s-", sprint_hex_inrow(p, 2)); + p += 2; + sprintf(uuid + strlen(uuid), "%s", sprint_hex_inrow(p, 6)); + p += 6; + PrintAndLogEx(INFO, "UUID.......... " _YELLOW_("%s"), uuid); + p++; + n = *(p++); + PrintAndLogEx(INFO, "Version....... " _YELLOW_("%.*s"), n, p); + PrintAndLogEx(NORMAL, ""); + return PM3_SUCCESS; +} + +static int ndefDecodePayloadSmartPoster(uint8_t *ndef, size_t ndeflen, bool print, bool verbose) { + if (print) { + PrintAndLogEx(INFO, _YELLOW_("Well Known Record - Smartposter {")); + } + + NDEFHeader_t NDEFHeader = {0}; + int res = ndefDecodeHeader(ndef, ndeflen, &NDEFHeader); + if (res != PM3_SUCCESS) { + PrintAndLogEx(FAILED, "decode header failed.."); + return res; + } + + if (verbose) { + ndefPrintHeader(&NDEFHeader); + } + + if (NDEFHeader.TypeLen && NDEFHeader.PayloadLen) { + ndefDecodePayload(&NDEFHeader); + } + + if (NDEFHeader.TypeLen) { + PrintAndLogEx(INFO, "Type data"); + print_buffer(NDEFHeader.Type, NDEFHeader.TypeLen, 1); + } + if (NDEFHeader.IDLen) { + PrintAndLogEx(INFO, "ID data"); + print_buffer(NDEFHeader.ID, NDEFHeader.IDLen, 1); + } + if (NDEFHeader.PayloadLen) { + PrintAndLogEx(INFO, "Payload data"); + print_buffer(NDEFHeader.Payload, NDEFHeader.PayloadLen, 1); + } + // recursive + if (NDEFHeader.MessageEnd == false) { + ndefDecodePayloadSmartPoster(ndef + NDEFHeader.RecLen, ndeflen - NDEFHeader.RecLen, false, false); + } + + if (print) { + PrintAndLogEx(INFO, _YELLOW_("}")); + } + return PM3_SUCCESS; +} + +static int ndefDecodeMime_wifi(NDEFHeader_t *ndef) { + PrintAndLogEx(INFO, _CYAN_("WiFi details")); + if (ndef->PayloadLen > 1) { + PrintAndLogEx(INFO, ">>> decorder, to be implemented <<<"); + } + return PM3_SUCCESS; +} + +static int ndefDecodeMime_vcard(NDEFHeader_t *ndef) { + PrintAndLogEx(INFO, _CYAN_("VCARD details")); + if (ndef->PayloadLen > 1) { + PrintAndLogEx(INFO, "Data... " _YELLOW_("%.*s"), (int)ndef->PayloadLen, ndef->Payload); + PrintAndLogEx(INFO, ">>> decorder, to be implemented <<<"); + } + return PM3_SUCCESS; +} + +static int ndefDecodeMime_bt(NDEFHeader_t *ndef) { + PrintAndLogEx(INFO, "Type............ " _YELLOW_("%.*s"), (int)ndef->TypeLen, ndef->Type ); + if (ndef->PayloadLen > 1) { + uint16_t ooblen = (ndef->Payload[1] << 8 | ndef->Payload[0]); + PrintAndLogEx(INFO, "OOB data len.... %u", ooblen); + PrintAndLogEx(INFO, "BT MAC.......... " _YELLOW_("%s"), sprint_hex(ndef->Payload + 2, 6)); + // Let's check payload[8]. Tells us a bit about the UUID's. If 0x07 then it tells us a service UUID is 128bit + switch (ndef->Payload[8]) { + case 0x02: + PrintAndLogEx(INFO, "Optional Data... incomplete list 16-bit UUID's"); + break; + case 0x03: + PrintAndLogEx(INFO, "Optional Data... complete list 16-bit UUID's"); + break; + case 0x04: + PrintAndLogEx(INFO, "Optional Data... incomplete list 32-bit UUID's"); + break; + case 0x05: + PrintAndLogEx(INFO, "Optional Data... complete list 32-bit UUID's"); + break; + case 0x06: + PrintAndLogEx(INFO, "Optional Data... incomplete list 128-bit UUID's"); + break; + case 0x07: + PrintAndLogEx(INFO, "Optional Data... complete list 128-bit UUID's"); + break; + default: + PrintAndLogEx(INFO, "Optional Data... [ %02x ]", ndef->Payload[8]); + break; + } + // Let's check payload[9]. If 0x08 then SHORT_NAME or if 0x09 then COMPLETE_NAME + if (ndef->Payload[9] == 0x08 ) { + PrintAndLogEx(INFO, "Short name...... " _YELLOW_("%s"), ndef->Payload + 10, ndef->PayloadLen - 10); + } else if (ndef->Payload[9] == 0x09 ) { + PrintAndLogEx(INFO, "Complete name... " _YELLOW_("%s"), ndef->Payload + 10, ndef->PayloadLen - 10); + } else { + PrintAndLogEx(INFO, "[ %02x ]", ndef->Payload[9]); + } + PrintAndLogEx(NORMAL, ""); + } + return PM3_SUCCESS; +} + static int ndefDecodePayload(NDEFHeader_t *ndef) { + PrintAndLogEx(INFO, ""); switch (ndef->TypeNameFormat) { + case tnfEmptyRecord: + PrintAndLogEx(INFO, "Empty Record"); + if (ndef->TypeLen != 0 || ndef->IDLen != 0 || ndef->PayloadLen != 0) { + PrintAndLogEx(FAILED, "unexpected data in TNF_EMPTY record"); + break; + } + break; case tnfWellKnownRecord: - PrintAndLogEx(INFO, "Well Known Record"); - PrintAndLogEx(INFO, "\ttype\t: %.*s", (int)ndef->TypeLen, ndef->Type); if (!strncmp((char *)ndef->Type, "T", ndef->TypeLen)) { + PrintAndLogEx(INFO, _CYAN_("Text")); uint8_t utf8 = (ndef->Payload[0] >> 7); uint8_t lc_len = ndef->Payload[0] & 0x3F; PrintAndLogEx(INFO, - "\tUTF %d\t: " _GREEN_("%.*s") ", " _GREEN_("%.*s"), + " UTF %d... " _GREEN_("%.*s") ", " _GREEN_("%.*s"), (utf8 == 0) ? 8 : 16, lc_len, ndef->Payload + 1, @@ -322,8 +588,9 @@ static int ndefDecodePayload(NDEFHeader_t *ndef) { } if (!strncmp((char *)ndef->Type, "U", ndef->TypeLen)) { + PrintAndLogEx(INFO, _CYAN_("URL")); PrintAndLogEx(INFO - , "\turi\t: " _GREEN_("%s%.*s") + , " uri... " _GREEN_("%s%.*s") , (ndef->Payload[0] <= 0x23 ? URI_s[ndef->Payload[0]] : "[err]") , (int)(ndef->PayloadLen - 1) , &ndef->Payload[1] @@ -331,34 +598,67 @@ static int ndefDecodePayload(NDEFHeader_t *ndef) { } if (!strncmp((char *)ndef->Type, "Sig", ndef->TypeLen)) { + PrintAndLogEx(INFO, _CYAN_("Signature")); ndefDecodeSig(ndef->Payload, ndef->PayloadLen); } + if (!strncmp((char *)ndef->Type, "Sp", ndef->TypeLen)) { + ndefDecodePayloadSmartPoster(ndef->Payload, ndef->PayloadLen, true, false); + } + + if (!strncmp((char *)ndef->Type, "Di", ndef->TypeLen)) { + ndefDecodePayloadDeviceInfo(ndef->Payload, ndef->PayloadLen); + } + + if (!strncmp((char *)ndef->Type, "Hc", ndef->TypeLen)) { + PrintAndLogEx(INFO, _CYAN_("Handover carrier")); + PrintAndLogEx(INFO, "- decoder to be impl -"); + } + + if (!strncmp((char *)ndef->Type, "Hr", ndef->TypeLen)) { + PrintAndLogEx(INFO, _CYAN_("Handover request")); + PrintAndLogEx(INFO, "- decoder to be impl -"); + } + + if (!strncmp((char *)ndef->Type, "Hs", ndef->TypeLen)) { + PrintAndLogEx(INFO, _CYAN_("Handover select")); + PrintAndLogEx(INFO, "- decoder to be impl -"); + } + + if (!strncmp((char *)ndef->Type, "ac", ndef->TypeLen)) { + PrintAndLogEx(INFO, _CYAN_("Alternative carrier")); + PrintAndLogEx(INFO, "- decoder to be impl -"); + } + break; + case tnfMIMEMediaRecord: + PrintAndLogEx(INFO, "MIME Media Record"); + + if (str_startswith((const char *)ndef->Type, NDEF_WIFIAPPL)) { + ndefDecodeMime_wifi(ndef); + } + if (str_startswith((const char *)ndef->Type, NDEF_VCARDTEXT)) { + ndefDecodeMime_vcard(ndef); + } + if (str_startswith((const char *)ndef->Type, NDEF_BLUEAPPL)) { + ndefDecodeMime_bt(ndef); + } + break; case tnfAbsoluteURIRecord: PrintAndLogEx(INFO, "Absolute URI Record"); - PrintAndLogEx(INFO, "\ttype : %.*s", (int)ndef->TypeLen, ndef->Type); - PrintAndLogEx(INFO, "\tpayload : %.*s", (int)ndef->PayloadLen, ndef->Payload); - break; - case tnfEmptyRecord: - PrintAndLogEx(INFO, "Empty Record"); - PrintAndLogEx(INFO, "\t -to be impl-"); - break; - case tnfMIMEMediaRecord: - PrintAndLogEx(INFO, "MIME Media Record"); - PrintAndLogEx(INFO, "\t -to be impl-"); + PrintAndLogEx(INFO, " payload : %.*s", (int)ndef->PayloadLen, ndef->Payload); break; case tnfExternalRecord: PrintAndLogEx(INFO, "External Record"); - PrintAndLogEx(INFO, "\t -to be impl-"); - break; - case tnfUnchangedRecord: - PrintAndLogEx(INFO, "Unchanged Record"); - PrintAndLogEx(INFO, "\t -to be impl-"); + PrintAndLogEx(INFO, "- decoder to be impl -"); break; case tnfUnknownRecord: PrintAndLogEx(INFO, "Unknown Record"); - PrintAndLogEx(INFO, "\t -to be impl-"); + PrintAndLogEx(INFO, "- decoder to be impl -"); + break; + case tnfUnchangedRecord: + PrintAndLogEx(INFO, "Unchanged Record"); + PrintAndLogEx(INFO, "- decoder to be impl -"); break; } return PM3_SUCCESS; @@ -371,19 +671,22 @@ static int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { return res; ndefPrintHeader(&NDEFHeader); + PrintAndLogEx(INFO, ""); + PrintAndLogEx(INFO, _CYAN_("Payload info")); if (NDEFHeader.TypeLen) { - PrintAndLogEx(INFO, "Type data:"); + PrintAndLogEx(INFO, "Type data"); print_buffer(NDEFHeader.Type, NDEFHeader.TypeLen, 1); } if (NDEFHeader.IDLen) { - PrintAndLogEx(INFO, "ID data:"); + PrintAndLogEx(INFO, "ID data"); print_buffer(NDEFHeader.ID, NDEFHeader.IDLen, 1); } if (NDEFHeader.PayloadLen) { - PrintAndLogEx(INFO, "Payload data:"); + PrintAndLogEx(INFO, "Payload data"); print_buffer(NDEFHeader.Payload, NDEFHeader.PayloadLen, 1); - if (NDEFHeader.TypeLen) + } + if (NDEFHeader.TypeLen && NDEFHeader.PayloadLen) { ndefDecodePayload(&NDEFHeader); } @@ -438,8 +741,6 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("NDEF parsing") " ----------------"); while (indx < ndefLen) { - - PrintAndLogEx(INFO, "-----------------------------------------------------"); switch (ndef[indx]) { case 0x00: { indx++; @@ -462,11 +763,11 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { uint8_t Size = ndef[indx + 1]; uint8_t BytesLockedPerLockBit = (ndef[indx + 2] >> 4) & 0x0f; uint8_t bytes_per_page = ndef[indx + 2] & 0x0f; - PrintAndLogEx(SUCCESS, " Pages addr (number of pages) : %d", pages_addr); - PrintAndLogEx(SUCCESS, "Byte offset (number of bytes) : %d", byte_offset); - PrintAndLogEx(SUCCESS, "Size in bits of the lock area : %d. bytes approx: %d", Size, Size / 8); - PrintAndLogEx(SUCCESS, " Number of bytes / page : %d", bytes_per_page); - PrintAndLogEx(SUCCESS, "Bytes Locked Per LockBit."); + PrintAndLogEx(SUCCESS, " Pages addr (number of pages)... %d", pages_addr); + PrintAndLogEx(SUCCESS, "Byte offset (number of bytes)... %d", byte_offset); + PrintAndLogEx(SUCCESS, "Size in bits of the lock area %d. bytes approx %d", Size, Size / 8); + PrintAndLogEx(SUCCESS, " Number of bytes / page... %d", bytes_per_page); + PrintAndLogEx(SUCCESS, "Bytes Locked Per LockBit"); PrintAndLogEx(SUCCESS, " number of bytes that each dynamic lock bit is able to lock: %d", BytesLockedPerLockBit); } indx += len; From 2f432788cfe6f0ebc39a6dd6442320286d2f0108 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 07:49:41 +0200 Subject: [PATCH 014/309] fix out-of-bounds access --- client/src/cmdhfmfdes.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index e2e315727..bec41af0b 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -2445,7 +2445,7 @@ static int CmdHF14ADesGetUID(const char *Cmd) { uint8_t uidlen = 16; // Get datalen + by removing padding. - while ((uidlen > 0) && (uid[uidlen] == 0x00)) + while ((uidlen > 0) && (uid[uidlen - 1] == 0x00)) uidlen--; if (tag->authentication_scheme == AS_LEGACY) @@ -2455,10 +2455,9 @@ static int CmdHF14ADesGetUID(const char *Cmd) { if (uidlen <= 4) // < incase we trimmed a CRC 00 or more uidlen = 4; - else + else uidlen = 7; -// PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(uid, sizeof(uid))); PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(uid, uidlen)); return res; } From b17a311c66c9342e9cc8537cb774d76a53976dd2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 07:58:29 +0200 Subject: [PATCH 015/309] various coverity fixes --- client/src/cmdhfcipurse.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/client/src/cmdhfcipurse.c b/client/src/cmdhfcipurse.c index 6ce7c8895..bc1651b6a 100644 --- a/client/src/cmdhfcipurse.c +++ b/client/src/cmdhfcipurse.c @@ -155,9 +155,9 @@ static int CmdHFCipurseAuth(const char *Cmd) { if (verbose == false) { if (bres) - PrintAndLogEx(INFO, "Authentication " _GREEN_("OK")); + PrintAndLogEx(INFO, "Authentication ( " _GREEN_("ok") " )"); else - PrintAndLogEx(ERR, "Authentication " _RED_("ERROR")); + PrintAndLogEx(ERR, "Authentication ( " _RED_("fail") " )"); } DropField(); @@ -170,7 +170,6 @@ static int CLIParseKeyAndSecurityLevels(CLIParserContext *ctx, size_t keyid, siz CLIGetHexWithReturn(ctx, keyid, hdata, &hdatalen); if (hdatalen && hdatalen != 16) { PrintAndLogEx(ERR, _RED_("ERROR:") " key length for AES128 must be 16 bytes only."); - CLIParserFree(ctx); return PM3_EINVARG; } if (hdatalen) @@ -292,7 +291,7 @@ static int CmdHFCipurseReadFile(const char *Cmd) { bool bres = CIPURSEChannelAuthenticate(keyId, key, verbose); if (bres == false) { if (verbose == false) - PrintAndLogEx(ERR, "Authentication " _RED_("ERROR")); + PrintAndLogEx(ERR, "Authentication ( " _RED_("fail") " )"); DropField(); return PM3_ESOFT; } @@ -321,9 +320,9 @@ static int CmdHFCipurseReadFile(const char *Cmd) { } if (len == 0) - PrintAndLogEx(INFO, "File id: %x is empty", fileId); + PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " is empty", fileId); else - PrintAndLogEx(INFO, "File id: %x data[%d]: %s", fileId, len, sprint_hex(buf, len)); + PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " data[%d]: %s", fileId, len, sprint_hex(buf, len)); DropField(); return PM3_SUCCESS; @@ -414,7 +413,7 @@ static int CmdHFCipurseWriteFile(const char *Cmd) { bool bres = CIPURSEChannelAuthenticate(keyId, key, verbose); if (bres == false) { if (verbose == false) - PrintAndLogEx(ERR, "Authentication " _RED_("ERROR")); + PrintAndLogEx(ERR, "Authentication ( " _RED_("fail") " )"); DropField(); return PM3_ESOFT; } @@ -442,7 +441,7 @@ static int CmdHFCipurseWriteFile(const char *Cmd) { return PM3_ESOFT; } - PrintAndLogEx(INFO, "File id: %x successfully written.", fileId); + PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " successfully written.", fileId); DropField(); return PM3_SUCCESS; @@ -524,7 +523,7 @@ static int CmdHFCipurseReadFileAttr(const char *Cmd) { bool bres = CIPURSEChannelAuthenticate(keyId, key, verbose); if (bres == false) { if (verbose == false) - PrintAndLogEx(ERR, "Authentication " _RED_("ERROR")); + PrintAndLogEx(ERR, "Authentication ( " _RED_("fail") " )"); DropField(); return PM3_ESOFT; } @@ -559,13 +558,13 @@ static int CmdHFCipurseReadFileAttr(const char *Cmd) { } if (len == 0) { - PrintAndLogEx(WARNING, "File id: %x attributes is empty", fileId); + PrintAndLogEx(WARNING, "File id " _YELLOW_("%x") " attributes is empty", fileId); DropField(); return PM3_SUCCESS; } if (verbose) - PrintAndLogEx(INFO, "File id: %x attributes[%d]: %s", fileId, len, sprint_hex(buf, len)); + PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " attributes[%d]: %s", fileId, len, sprint_hex(buf, len)); CIPURSEPrintFileAttr(buf, len); @@ -640,7 +639,7 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) { bool bres = CIPURSEChannelAuthenticate(keyId, key, verbose); if (bres == false) { if (verbose == false) - PrintAndLogEx(ERR, "Authentication " _RED_("ERROR")); + PrintAndLogEx(ERR, "Authentication ( " _RED_("fail") " )"); DropField(); return PM3_ESOFT; } @@ -656,7 +655,7 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) { return PM3_ESOFT; } - PrintAndLogEx(INFO, "File id: 04x deleted " _GREEN_("succesfully"), fileId); + PrintAndLogEx(INFO, "File id " _YELLOW_("%04x") " deleted " _GREEN_("succesfully"), fileId); DropField(); return PM3_SUCCESS; From e0fc80c539c9579805ae209410fbda80f428e7ce Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 08:01:01 +0200 Subject: [PATCH 016/309] fix coverity CID 349315 --- client/src/cmdhfcipurse.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfcipurse.c b/client/src/cmdhfcipurse.c index bc1651b6a..6fb3d42a3 100644 --- a/client/src/cmdhfcipurse.c +++ b/client/src/cmdhfcipurse.c @@ -73,7 +73,7 @@ static int CmdHFCipurseInfo(const char *Cmd) { return PM3_SUCCESS; } - PrintAndLogEx(INFO, "Cipurse card: " _GREEN_("OK")); + PrintAndLogEx(INFO, "Cipurse card ( " _GREEN_("ok") " )"); res = CIPURSESelectFile(0x2ff7, buf, sizeof(buf), &len, &sw); if (res != 0 || sw != 0x9000) { @@ -88,8 +88,8 @@ static int CmdHFCipurseInfo(const char *Cmd) { } if (len > 0) { - PrintAndLogEx(INFO, "Info file: " _GREEN_("OK")); - PrintAndLogEx(INFO, "[%d]: %s", len, sprint_hex(buf, len)); + PrintAndLogEx(INFO, "Info file ( " _GREEN_("ok") " )"); + PrintAndLogEx(INFO, "[%zu]: %s", len, sprint_hex(buf, len)); CIPURSEPrintInfoFile(buf, len); } From ea80ea21ad5bfba83a8c63d30b1bbfc4d8adde2b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 08:02:33 +0200 Subject: [PATCH 017/309] fix coverity CID 349314 --- client/src/cmdhfcipurse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfcipurse.c b/client/src/cmdhfcipurse.c index 6fb3d42a3..c4d2df247 100644 --- a/client/src/cmdhfcipurse.c +++ b/client/src/cmdhfcipurse.c @@ -285,7 +285,7 @@ static int CmdHFCipurseReadFile(const char *Cmd) { } if (verbose) - PrintAndLogEx(INFO, "File id: %x offset %d key id: %d key: %s", fileId, offset, keyId, sprint_hex(key, CIPURSE_AES_KEY_LENGTH)); + PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " offset " _YELLOW_("%zu") " key id " _YELLOW_("%d") " key " _YELLOW_("%s"), fileId, offset, keyId, sprint_hex(key, CIPURSE_AES_KEY_LENGTH)); if (noAuth == false) { bool bres = CIPURSEChannelAuthenticate(keyId, key, verbose); From 501a848034b8d0289dc9b1ec64c288b4d9bd5b2f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 08:05:21 +0200 Subject: [PATCH 018/309] fix coverity CID 349311 --- client/src/cmdhfemrtd.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 6f635fdb0..fb56aa4f6 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -843,9 +843,13 @@ static bool emrtd_dump_file(uint8_t *ks_enc, uint8_t *ks_mac, uint8_t *ssc, uint strncat(filepath, PATHSEP, 2); strcat(filepath, name); - PrintAndLogEx(INFO, "Read %s, len: %i.", name, resplen); - PrintAndLogEx(DEBUG, "Contents (may be incomplete over 2k chars): %s", sprint_hex_inrow(response, resplen)); + PrintAndLogEx(INFO, "Read " _YELLOW_("%s") " , len %zu", name, resplen); + PrintAndLogEx(DEBUG, "Contents (may be incomplete over 2k chars)"); + PrintAndLogEx(DEBUG, "------------------------------------------"); + PrintAndLogEx(DEBUG, "%s", sprint_hex_inrow(response, resplen)); + PrintAndLogEx(DEBUG, "------------------------------------------"); saveFile(filepath, ".BIN", response, resplen); + emrtd_dg_t *dg = emrtd_fileid_to_dg(file); if ((dg != NULL) && (dg->dumper != NULL)) { dg->dumper(response, resplen, path); From b5e7b6277f124446cad4414d1ad8a1c9ec545376 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 08:08:41 +0200 Subject: [PATCH 019/309] fix coverity CID 349310 --- client/src/nfc/ndef.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/nfc/ndef.c b/client/src/nfc/ndef.c index 2b2dfc9c3..43f0b085d 100644 --- a/client/src/nfc/ndef.c +++ b/client/src/nfc/ndef.c @@ -549,9 +549,9 @@ static int ndefDecodeMime_bt(NDEFHeader_t *ndef) { } // Let's check payload[9]. If 0x08 then SHORT_NAME or if 0x09 then COMPLETE_NAME if (ndef->Payload[9] == 0x08 ) { - PrintAndLogEx(INFO, "Short name...... " _YELLOW_("%s"), ndef->Payload + 10, ndef->PayloadLen - 10); + PrintAndLogEx(INFO, "Short name...... " _YELLOW_("%.*s"), ndef->PayloadLen - 10, ndef->Payload + 10); } else if (ndef->Payload[9] == 0x09 ) { - PrintAndLogEx(INFO, "Complete name... " _YELLOW_("%s"), ndef->Payload + 10, ndef->PayloadLen - 10); + PrintAndLogEx(INFO, "Complete name... " _YELLOW_("%.*s"), ndef->PayloadLen - 10, ndef->Payload + 10); } else { PrintAndLogEx(INFO, "[ %02x ]", ndef->Payload[9]); } From 48cfb255ef4b843cfbce9793bcec0ef09b304f7b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 08:10:41 +0200 Subject: [PATCH 020/309] fix coverity CID 349309 --- client/src/nfc/ndef.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client/src/nfc/ndef.c b/client/src/nfc/ndef.c index 43f0b085d..5ecddc09f 100644 --- a/client/src/nfc/ndef.c +++ b/client/src/nfc/ndef.c @@ -250,7 +250,6 @@ static int ndef_print_signature(uint8_t *data, uint8_t data_len, uint8_t *signat PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("NDEF Signature")); if (is_valid == false || i == ARRAYLEN(ndef_public_keys)) { - PrintAndLogEx(INFO, " Elliptic curve parameters: %s", get_curve_name(ndef_public_keys[i].grp_id)); PrintAndLogEx(INFO, " NDEF Signature: %s", sprint_hex_inrow(signature, 32)); PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed")); return PM3_ESOFT; From b1566bd9ae442eca21effa7b4202a186b4836e65 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 08:38:33 +0200 Subject: [PATCH 021/309] fix coverity CID 349305 and textual changes --- client/src/cmdhfcipurse.c | 247 ++++++++++++++++++++------------------ 1 file changed, 129 insertions(+), 118 deletions(-) diff --git a/client/src/cmdhfcipurse.c b/client/src/cmdhfcipurse.c index c4d2df247..faeea6dab 100644 --- a/client/src/cmdhfcipurse.c +++ b/client/src/cmdhfcipurse.c @@ -65,7 +65,7 @@ static int CmdHFCipurseInfo(const char *Cmd) { if (sw != 0x9000) { if (sw) - PrintAndLogEx(INFO, "Not a CIPURSE card! APDU response: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLogEx(INFO, "Not a CIPURSE card. APDU response: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); else PrintAndLogEx(ERR, "APDU exchange error. Card returns 0x0000."); @@ -98,40 +98,36 @@ static int CmdHFCipurseInfo(const char *Cmd) { } static int CmdHFCipurseAuth(const char *Cmd) { - uint8_t buf[APDU_RES_LEN] = {0}; - size_t len = 0; - uint16_t sw = 0; - uint8_t keyId = 1; - uint8_t key[] = {0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73}; - CLIParserContext *ctx; CLIParserInit(&ctx, "hf cipurse auth", - "Authenticate with key ID and key", - "hf cipurse auth -> Authenticate with keyID=1 and key = 7373...7373\n" - "hf cipurse auth -n 2 -k 65656565656565656565656565656565 -> Authenticate with key\n"); + "Authenticate with key ID and key. If no key is supplied, default key of 737373...7373 will be used", + "hf cipurse auth -> Authenticate with keyID 1, default key\n" + "hf cipurse auth -n 2 -k 65656565656565656565656565656565 -> Authenticate keyID 2 with key\n"); void *argtable[] = { arg_param_begin, arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("v", "verbose", "show technical data"), - arg_int0("n", "keyid", "", "key id"), - arg_str0("k", "key", "", "key for authenticate"), + arg_int0("n", NULL, "", "key ID"), + arg_str0("k", "key", "", "Auth key"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - keyId = arg_get_int_def(ctx, 3, 1); + uint8_t keyId = arg_get_int_def(ctx, 3, 1); uint8_t hdata[250] = {0}; int hdatalen = sizeof(hdata); CLIGetHexWithReturn(ctx, 4, hdata, &hdatalen); if (hdatalen && hdatalen != 16) { - PrintAndLogEx(ERR, _RED_("ERROR:") " key length for AES128 must be 16 bytes only."); + PrintAndLogEx(ERR, _RED_("ERROR:") " key length for AES128 must be 16 bytes only"); CLIParserFree(ctx); return PM3_EINVARG; } + + uint8_t key[] = {0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73}; if (hdatalen) memcpy(key, hdata, CIPURSE_AES_KEY_LENGTH); @@ -139,17 +135,26 @@ static int CmdHFCipurseAuth(const char *Cmd) { CLIParserFree(ctx); + size_t len = 0; + uint16_t sw = 0; + uint8_t buf[APDU_RES_LEN] = {0}; + int res = CIPURSESelect(true, true, buf, sizeof(buf), &len, &sw); if (res != 0 || sw != 0x9000) { - PrintAndLogEx(ERR, "Cipurse select " _RED_("error") ". Card returns 0x%04x.", sw); + PrintAndLogEx(ERR, "Cipurse select " _RED_("error") ". Card returns 0x%04x", sw); DropField(); return PM3_ESOFT; } uint8_t kvv[CIPURSE_KVV_LENGTH] = {0}; CipurseCGetKVV(key, kvv); - if (verbose) - PrintAndLogEx(INFO, "Key id: %d key: %s KVV: %s", keyId, sprint_hex(key, CIPURSE_AES_KEY_LENGTH), sprint_hex_inrow(kvv, CIPURSE_KVV_LENGTH)); + if (verbose) { + PrintAndLogEx(INFO, "Key id" _YELLOW_("%d") " key " _YELLOW_("%s") " KVV " _YELLOW_("%s") + , keyId + , sprint_hex(key, CIPURSE_AES_KEY_LENGTH) + , sprint_hex_inrow(kvv, CIPURSE_KVV_LENGTH) + ); + } bool bres = CIPURSEChannelAuthenticate(keyId, key, verbose); @@ -161,7 +166,7 @@ static int CmdHFCipurseAuth(const char *Cmd) { } DropField(); - return bres ? PM3_SUCCESS : PM3_ESOFT; + return (bres) ? PM3_SUCCESS : PM3_ESOFT; } static int CLIParseKeyAndSecurityLevels(CLIParserContext *ctx, size_t keyid, size_t sreqid, size_t srespid, uint8_t *key, CipurseChannelSecurityLevel *sreq, CipurseChannelSecurityLevel *sresp) { @@ -169,7 +174,7 @@ static int CLIParseKeyAndSecurityLevels(CLIParserContext *ctx, size_t keyid, siz int hdatalen = sizeof(hdata); CLIGetHexWithReturn(ctx, keyid, hdata, &hdatalen); if (hdatalen && hdatalen != 16) { - PrintAndLogEx(ERR, _RED_("ERROR:") " key length for AES128 must be 16 bytes only."); + PrintAndLogEx(ERR, _RED_("ERROR:") " key length for AES128 must be 16 bytes only"); return PM3_EINVARG; } if (hdatalen) @@ -191,7 +196,7 @@ static int CLIParseKeyAndSecurityLevels(CLIParserContext *ctx, size_t keyid, siz else if (strcmp(cdata, "enc") == 0 || strcmp(cdata, "encode") == 0 || strcmp(cdata, "encrypted") == 0) *sreq = CPSEncrypted; else { - PrintAndLogEx(ERR, _RED_("ERROR:") " security level can be only: plain|mac|encode."); + PrintAndLogEx(ERR, _RED_("ERROR:") " security level can be only: plain | mac | encode"); return PM3_EINVARG; } } @@ -209,7 +214,7 @@ static int CLIParseKeyAndSecurityLevels(CLIParserContext *ctx, size_t keyid, siz else if (strcmp(cdata, "enc") == 0 || strcmp(cdata, "encode") == 0 || strcmp(cdata, "encrypted") == 0) *sresp = CPSEncrypted; else { - PrintAndLogEx(ERR, _RED_("ERROR:") " security level can be only: plain|mac|encode."); + PrintAndLogEx(ERR, _RED_("ERROR:") " security level can be only: plain | mac | encode"); return PM3_EINVARG; } } @@ -218,24 +223,19 @@ static int CLIParseKeyAndSecurityLevels(CLIParserContext *ctx, size_t keyid, siz } static int CmdHFCipurseReadFile(const char *Cmd) { - uint8_t buf[APDU_RES_LEN] = {0}; - size_t len = 0; - uint16_t sw = 0; - uint8_t key[] = CIPURSE_DEFAULT_KEY; - CLIParserContext *ctx; CLIParserInit(&ctx, "hf cipurse read", - "Read file by file ID with key ID and key", - "hf cipurse read -f 2ff7 -> Authenticate with keyID=1 and key = 7373...7373 and read file with id 2ff7\n" - "hf cipurse read -n 2 -k 65656565656565656565656565656565 -f 2ff7 -> Authenticate with specified key and read file\n"); + "Read file by file ID with key ID and key. If no key is supplied, default key of 737373...7373 will be used", + "hf cipurse read -f 2ff7 -> Authenticate with keyID 1, read file with id 2ff7\n" + "hf cipurse read -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> Authenticate keyID 2 and read file\n"); void *argtable[] = { arg_param_begin, arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("v", "verbose", "show technical data"), - arg_int0("n", "keyid", "", "key id"), - arg_str0("k", "key", "", "key for authenticate"), - arg_str0("f", "file", "", "file ID"), + arg_int0("n", NULL, "", "key ID"), + arg_str0("k", "key", "", "Auth key"), + arg_str0(NULL, "fid", "", "file ID"), arg_int0("o", "offset", "", "offset for reading data from file"), arg_lit0(NULL, "noauth", "read file without authentication"), arg_str0(NULL, "sreq", "", "communication reader-PICC security level"), @@ -244,28 +244,30 @@ static int CmdHFCipurseReadFile(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, true); + bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); uint8_t keyId = arg_get_int_def(ctx, 3, 1); CipurseChannelSecurityLevel sreq = CPSMACed; CipurseChannelSecurityLevel sresp = CPSMACed; + uint8_t key[] = CIPURSE_DEFAULT_KEY; int res = CLIParseKeyAndSecurityLevels(ctx, 4, 8, 9, key, &sreq, &sresp); if (res) { CLIParserFree(ctx); return PM3_EINVARG; } - uint16_t fileId = 0x2ff7; - uint8_t hdata[250] = {0}; int hdatalen = sizeof(hdata); CLIGetHexWithReturn(ctx, 5, hdata, &hdatalen); if (hdatalen && hdatalen != 2) { - PrintAndLogEx(ERR, _RED_("ERROR:") " file id length must be 2 bytes only."); + PrintAndLogEx(ERR, _RED_("ERROR:") " file id length must be 2 bytes only"); CLIParserFree(ctx); return PM3_EINVARG; } + + uint16_t fileId = 0x2ff7; if (hdatalen) fileId = (hdata[0] << 8) + hdata[1]; @@ -277,9 +279,13 @@ static int CmdHFCipurseReadFile(const char *Cmd) { CLIParserFree(ctx); + size_t len = 0; + uint16_t sw = 0; + uint8_t buf[APDU_RES_LEN] = {0}; + res = CIPURSESelect(true, true, buf, sizeof(buf), &len, &sw); if (res != 0 || sw != 0x9000) { - PrintAndLogEx(ERR, "Cipurse select " _RED_("error") ". Card returns 0x%04x.", sw); + PrintAndLogEx(ERR, "Cipurse select " _RED_("error") ". Card returns 0x%04x", sw); DropField(); return PM3_ESOFT; } @@ -303,18 +309,18 @@ static int CmdHFCipurseReadFile(const char *Cmd) { res = CIPURSESelectFile(fileId, buf, sizeof(buf), &len, &sw); if (res != 0 || sw != 0x9000) { if (verbose == false) - PrintAndLogEx(ERR, "File select " _RED_("ERROR") ". Card returns 0x%04x.", sw); + PrintAndLogEx(ERR, "File select " _RED_("ERROR") ". Card returns 0x%04x", sw); DropField(); return PM3_ESOFT; } if (verbose) - PrintAndLogEx(INFO, "Select file 0x%x " _GREEN_("OK"), fileId); + PrintAndLogEx(INFO, "Select file 0x%x ( " _GREEN_("ok") " )", fileId); res = CIPURSEReadBinary(offset, buf, sizeof(buf), &len, &sw); if (res != 0 || sw != 0x9000) { if (verbose == false) - PrintAndLogEx(ERR, "File read " _RED_("ERROR") ". Card returns 0x%04x.", sw); + PrintAndLogEx(ERR, "File read " _RED_("ERROR") ". Card returns 0x%04x", sw); DropField(); return PM3_ESOFT; } @@ -322,36 +328,31 @@ static int CmdHFCipurseReadFile(const char *Cmd) { if (len == 0) PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " is empty", fileId); else - PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " data[%d]: %s", fileId, len, sprint_hex(buf, len)); + PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " data[%zu]: %s", fileId, len, sprint_hex(buf, len)); DropField(); return PM3_SUCCESS; } static int CmdHFCipurseWriteFile(const char *Cmd) { - uint8_t buf[APDU_RES_LEN] = {0}; - size_t len = 0; - uint16_t sw = 0; - uint8_t key[] = CIPURSE_DEFAULT_KEY; - CLIParserContext *ctx; CLIParserInit(&ctx, "hf cipurse write", - "Write file by file ID with key ID and key", - "hf cipurse write -f 2ff7 -> Authenticate with keyID=1 and key = 7373...7373 and write file with id 2ff7\n" - "hf cipurse write -n 2 -k 65656565656565656565656565656565 -f 2ff7 -> Authenticate with specified key and write file\n"); + "Write file by file ID with key ID and key. If no key is supplied, default key of 737373...7373 will be used", + "hf cipurse write -f 2ff7 -> Authenticate with keyID 1, write file with id 2ff7\n" + "hf cipurse write -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> Authenticate keyID 2 and write file\n"); void *argtable[] = { arg_param_begin, arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("v", "verbose", "show technical data"), - arg_int0("n", "keyid", "", "key id"), - arg_str0("k", "key", "", "key for authenticate"), - arg_str0("f", "file", "", "file ID"), + arg_int0("n", NULL, "", "key ID"), + arg_str0("k", "key", "", "Auth key"), + arg_str0(NULL, "fid", "", "file ID"), arg_int0("o", "offset", "", "offset for reading data from file"), arg_lit0(NULL, "noauth", "read file without authentication"), arg_str0(NULL, "sreq", "", "communication reader-PICC security level"), arg_str0(NULL, "sresp", "", "communication PICC-reader security level"), - arg_str0("c", "content", "", "new file content"), + arg_str0("d", "data", "", "hex data to write to new file"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -362,6 +363,8 @@ static int CmdHFCipurseWriteFile(const char *Cmd) { CipurseChannelSecurityLevel sreq = CPSMACed; CipurseChannelSecurityLevel sresp = CPSMACed; + + uint8_t key[] = CIPURSE_DEFAULT_KEY; int res = CLIParseKeyAndSecurityLevels(ctx, 4, 8, 9, key, &sreq, &sresp); if (res) { CLIParserFree(ctx); @@ -374,7 +377,7 @@ static int CmdHFCipurseWriteFile(const char *Cmd) { int hdatalen = sizeof(hdata); CLIGetHexWithReturn(ctx, 5, hdata, &hdatalen); if (hdatalen && hdatalen != 2) { - PrintAndLogEx(ERR, _RED_("ERROR:") " file id length must be 2 bytes only."); + PrintAndLogEx(ERR, _RED_("ERROR:") " file id length must be 2 bytes only"); CLIParserFree(ctx); return PM3_EINVARG; } @@ -388,7 +391,7 @@ static int CmdHFCipurseWriteFile(const char *Cmd) { hdatalen = sizeof(hdata); CLIGetHexWithReturn(ctx, 10, hdata, &hdatalen); if (hdatalen == 0) { - PrintAndLogEx(ERR, _RED_("ERROR:") " file content length must be more 0."); + PrintAndLogEx(ERR, _RED_("ERROR:") " file content length must be more 0"); CLIParserFree(ctx); return PM3_EINVARG; } @@ -397,15 +400,24 @@ static int CmdHFCipurseWriteFile(const char *Cmd) { CLIParserFree(ctx); + size_t len = 0; + uint16_t sw = 0; + uint8_t buf[APDU_RES_LEN] = {0}; + res = CIPURSESelect(true, true, buf, sizeof(buf), &len, &sw); if (res != 0 || sw != 0x9000) { - PrintAndLogEx(ERR, "Cipurse select " _RED_("error") ". Card returns 0x%04x.", sw); + PrintAndLogEx(ERR, "Cipurse select " _RED_("error") ". Card returns 0x%04x", sw); DropField(); return PM3_ESOFT; } if (verbose) { - PrintAndLogEx(INFO, "File id: %x offset %d key id: %d key: %s", fileId, offset, keyId, sprint_hex(key, CIPURSE_AES_KEY_LENGTH)); + PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " offset " _YELLOW_("%zu") " key id " _YELLOW_("%d") " key " _YELLOW_("%s") + , fileId + , offset + , keyId + , sprint_hex(key, CIPURSE_AES_KEY_LENGTH) + ); PrintAndLogEx(INFO, "data[%d]: %s", hdatalen, sprint_hex(hdata, hdatalen)); } @@ -425,52 +437,47 @@ static int CmdHFCipurseWriteFile(const char *Cmd) { res = CIPURSESelectFile(fileId, buf, sizeof(buf), &len, &sw); if (res != 0 || sw != 0x9000) { if (verbose == false) - PrintAndLogEx(ERR, "File select " _RED_("ERROR") ". Card returns 0x%04x.", sw); + PrintAndLogEx(ERR, "File select " _RED_("ERROR") ". Card returns 0x%04x", sw); DropField(); return PM3_ESOFT; } if (verbose) - PrintAndLogEx(INFO, "Select file 0x%x " _GREEN_("OK"), fileId); + PrintAndLogEx(INFO, "Select file 0x%x ( " _GREEN_("ok") " )", fileId); res = CIPURSEUpdateBinary(offset, hdata, hdatalen, buf, sizeof(buf), &len, &sw); if (res != 0 || sw != 0x9000) { if (verbose == false) - PrintAndLogEx(ERR, "File write " _RED_("ERROR") ". Card returns 0x%04x.", sw); + PrintAndLogEx(ERR, "File write " _RED_("ERROR") ". Card returns 0x%04x", sw); DropField(); return PM3_ESOFT; } - PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " successfully written.", fileId); + PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " successfully written", fileId); DropField(); return PM3_SUCCESS; } static int CmdHFCipurseReadFileAttr(const char *Cmd) { - uint8_t buf[APDU_RES_LEN] = {0}; - size_t len = 0; - uint16_t sw = 0; - uint8_t key[] = CIPURSE_DEFAULT_KEY; - CLIParserContext *ctx; CLIParserInit(&ctx, "hf cipurse aread", - "Read file attributes by file ID with key ID and key", - "hf cipurse aread -f 2ff7 -> Authenticate with keyID=1 and key = 7373...7373 and read file attributes with id 2ff7\n" - "hf cipurse aread -n 2 -k 65656565656565656565656565656565 -f 2ff7 -> Authenticate with specified key and read file attributes\n"); + "Read file attributes by file ID with key ID and key. If no key is supplied, default key of 737373...7373 will be used", + "hf cipurse aread -f 2ff7 -> Authenticate with keyID 1, read file attributes with id 2ff7\n" + "hf cipurse aread -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> Authenticate keyID 2, read file attributes\n"); void *argtable[] = { arg_param_begin, arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("v", "verbose", "show technical data"), - arg_int0("n", "keyid", "", "key id"), - arg_str0("k", "key", "", "key for authenticate"), - arg_str0("f", "file", "", "file ID"), + arg_int0("n", NULL, "", "key ID"), + arg_str0("k", "key", "", "Auth key"), + arg_str0(NULL, "fid", "", "file ID"), arg_lit0(NULL, "noauth", "read file attributes without authentication"), arg_str0(NULL, "sreq", "", "communication reader-PICC security level"), arg_str0(NULL, "sresp", "", "communication PICC-reader security level"), - arg_lit0(NULL, "sel-adf", "show info about ADF itself"), - arg_lit0(NULL, "sel-mf", "show info about master file"), + arg_lit0(NULL, "sel-adf", "show info about ADF itself"), + arg_lit0(NULL, "sel-mf", "show info about master file"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -481,27 +488,27 @@ static int CmdHFCipurseReadFileAttr(const char *Cmd) { CipurseChannelSecurityLevel sreq = CPSMACed; CipurseChannelSecurityLevel sresp = CPSMACed; + uint8_t key[] = CIPURSE_DEFAULT_KEY; int res = CLIParseKeyAndSecurityLevels(ctx, 4, 7, 8, key, &sreq, &sresp); if (res) { CLIParserFree(ctx); return PM3_EINVARG; } - uint16_t fileId = 0x2ff7; - uint8_t hdata[250] = {0}; int hdatalen = sizeof(hdata); CLIGetHexWithReturn(ctx, 5, hdata, &hdatalen); if (hdatalen && hdatalen != 2) { - PrintAndLogEx(ERR, _RED_("ERROR:") " file id length must be 2 bytes only."); + PrintAndLogEx(ERR, _RED_("ERROR:") " file id length must be 2 bytes only"); CLIParserFree(ctx); return PM3_EINVARG; } + + uint16_t fileId = 0x2ff7; if (hdatalen) fileId = (hdata[0] << 8) + hdata[1]; bool noAuth = arg_get_lit(ctx, 6); - bool seladf = arg_get_lit(ctx, 9); bool selmf = arg_get_lit(ctx, 10); @@ -509,15 +516,24 @@ static int CmdHFCipurseReadFileAttr(const char *Cmd) { CLIParserFree(ctx); + uint8_t buf[APDU_RES_LEN] = {0}; + size_t len = 0; + uint16_t sw = 0; + res = CIPURSESelect(true, true, buf, sizeof(buf), &len, &sw); if (res != 0 || sw != 0x9000) { - PrintAndLogEx(ERR, "Cipurse select " _RED_("error") ". Card returns 0x%04x.", sw); + PrintAndLogEx(ERR, "Cipurse select " _RED_("error") ". Card returns 0x%04x", sw); DropField(); return PM3_ESOFT; } - if (verbose) - PrintAndLogEx(INFO, "File id: %x key id: %d key: %s", fileId, keyId, sprint_hex(key, CIPURSE_AES_KEY_LENGTH)); + if (verbose) { + PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " key id " _YELLOW_("%d") " key " _YELLOW_("%s") + , fileId + , keyId + , sprint_hex(key, CIPURSE_AES_KEY_LENGTH) + ); + } if (noAuth == false) { bool bres = CIPURSEChannelAuthenticate(keyId, key, verbose); @@ -540,19 +556,19 @@ static int CmdHFCipurseReadFileAttr(const char *Cmd) { if (res != 0 || sw != 0x9000) { if (verbose == false) - PrintAndLogEx(ERR, "File select " _RED_("ERROR") ". Card returns 0x%04x.", sw); + PrintAndLogEx(ERR, "File select " _RED_("ERROR") ". Card returns 0x%04x", sw); DropField(); return PM3_ESOFT; } } if (verbose) - PrintAndLogEx(INFO, "Select file 0x%x " _GREEN_("OK"), fileId); + PrintAndLogEx(INFO, "Select file 0x%x ( " _GREEN_("ok") " )", fileId); res = CIPURSEReadFileAttributes(buf, sizeof(buf), &len, &sw); if (res != 0 || sw != 0x9000) { if (verbose == false) - PrintAndLogEx(ERR, "File read " _RED_("ERROR") ". Card returns 0x%04x.", sw); + PrintAndLogEx(ERR, "File read " _RED_("ERROR") ". Card returns 0x%04x", sw); DropField(); return PM3_ESOFT; } @@ -564,7 +580,7 @@ static int CmdHFCipurseReadFileAttr(const char *Cmd) { } if (verbose) - PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " attributes[%d]: %s", fileId, len, sprint_hex(buf, len)); + PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " attributes[%zu]: %s", fileId, len, sprint_hex(buf, len)); CIPURSEPrintFileAttr(buf, len); @@ -573,24 +589,19 @@ static int CmdHFCipurseReadFileAttr(const char *Cmd) { } static int CmdHFCipurseDeleteFile(const char *Cmd) { - uint8_t buf[APDU_RES_LEN] = {0}; - size_t len = 0; - uint16_t sw = 0; - uint8_t key[] = CIPURSE_DEFAULT_KEY; - CLIParserContext *ctx; CLIParserInit(&ctx, "hf cipurse delete", - "Read file by file ID with key ID and key", - "hf cipurse delete -f 2ff7 -> Authenticate with keyID=1 and key = 7373...7373 and delete file with id 2ff7\n" - "hf cipurse delete -n 2 -k 65656565656565656565656565656565 -f 2ff7 -> Authenticate with specified key and delete file\n"); + "Read file by file ID with key ID and key. If no key is supplied, default key of 737373...7373 will be used", + "hf cipurse delete -f 2ff7 -> Authenticate with keyID 1, delete file with id 2ff7\n" + "hf cipurse delete -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> Authenticate keyID 2 and delete file\n"); void *argtable[] = { arg_param_begin, arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("v", "verbose", "show technical data"), - arg_int0("n", "keyid", "", "key id"), - arg_str0("k", "key", "", "key for authenticate"), - arg_str0("f", "file", "", "file ID"), + arg_int0("n", NULL, "", "key ID"), + arg_str0("k", "key", "", "Auth key"), + arg_str0(NULL, "fid", "", "file ID"), arg_str0(NULL, "sreq", "", "communication reader-PICC security level"), arg_str0(NULL, "sresp", "", "communication PICC-reader security level"), arg_param_end @@ -603,22 +614,23 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) { CipurseChannelSecurityLevel sreq = CPSMACed; CipurseChannelSecurityLevel sresp = CPSMACed; + uint8_t key[] = CIPURSE_DEFAULT_KEY; int res = CLIParseKeyAndSecurityLevels(ctx, 4, 6, 7, key, &sreq, &sresp); if (res) { CLIParserFree(ctx); return PM3_EINVARG; } - uint16_t fileId = 0x2ff7; - uint8_t hdata[250] = {0}; int hdatalen = sizeof(hdata); CLIGetHexWithReturn(ctx, 5, hdata, &hdatalen); if (hdatalen && hdatalen != 2) { - PrintAndLogEx(ERR, _RED_("ERROR:") " file id length must be 2 bytes only."); + PrintAndLogEx(ERR, _RED_("ERROR:") " file id length must be 2 bytes only"); CLIParserFree(ctx); return PM3_EINVARG; } + + uint16_t fileId = 0x2ff7; if (hdatalen) fileId = (hdata[0] << 8) + hdata[1]; @@ -626,15 +638,24 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) { CLIParserFree(ctx); + uint8_t buf[APDU_RES_LEN] = {0}; + size_t len = 0; + uint16_t sw = 0; + res = CIPURSESelect(true, true, buf, sizeof(buf), &len, &sw); if (res != 0 || sw != 0x9000) { - PrintAndLogEx(ERR, "Cipurse select " _RED_("error") ". Card returns 0x%04x.", sw); + PrintAndLogEx(ERR, "Cipurse select " _RED_("error") ". Card returns 0x%04x", sw); DropField(); return PM3_ESOFT; } - if (verbose) - PrintAndLogEx(INFO, "File id: %x key id: %d key: %s", fileId, keyId, sprint_hex(key, CIPURSE_AES_KEY_LENGTH)); + if (verbose) { + PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " key id " _YELLOW_("%d") " key " _YELLOW_("%s") + , fileId + , keyId + , sprint_hex(key, CIPURSE_AES_KEY_LENGTH) + ); + } bool bres = CIPURSEChannelAuthenticate(keyId, key, verbose); if (bres == false) { @@ -650,7 +671,7 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) { res = CIPURSEDeleteFile(fileId, buf, sizeof(buf), &len, &sw); if (res != 0 || sw != 0x9000) { if (verbose == false) - PrintAndLogEx(ERR, "File select " _RED_("ERROR") ". Card returns 0x%04x.", sw); + PrintAndLogEx(ERR, "File select " _RED_("ERROR") ". Card returns 0x%04x", sw); DropField(); return PM3_ESOFT; } @@ -662,16 +683,6 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) { } - - - - - - - - - - bool CheckCardCipurse(void) { uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; @@ -683,12 +694,12 @@ bool CheckCardCipurse(void) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help."}, - {"info", CmdHFCipurseInfo, IfPm3Iso14443a, "Info about Cipurse tag."}, - {"auth", CmdHFCipurseAuth, IfPm3Iso14443a, "Authentication."}, - {"read", CmdHFCipurseReadFile, IfPm3Iso14443a, "Read binary file."}, - {"write", CmdHFCipurseWriteFile, IfPm3Iso14443a, "Write binary file."}, - {"aread", CmdHFCipurseReadFileAttr, IfPm3Iso14443a, "Read file attributes."}, - {"delete", CmdHFCipurseDeleteFile, IfPm3Iso14443a, "Delete file."}, + {"info", CmdHFCipurseInfo, IfPm3Iso14443a, "Get info about CIPURSE tag"}, + {"auth", CmdHFCipurseAuth, IfPm3Iso14443a, "Authenticate CIPURSE tag"}, + {"read", CmdHFCipurseReadFile, IfPm3Iso14443a, "Read binary file"}, + {"write", CmdHFCipurseWriteFile, IfPm3Iso14443a, "Write binary file"}, + {"aread", CmdHFCipurseReadFileAttr, IfPm3Iso14443a, "Read file attributes"}, + {"delete", CmdHFCipurseDeleteFile, IfPm3Iso14443a, "Delete file"}, {NULL, NULL, 0, NULL} }; From 5da59e55351fa23d768e73aecbe951ce53b7e374 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 08:40:32 +0200 Subject: [PATCH 022/309] fix coverity CID 349303 --- client/src/cmdhfemrtd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index fb56aa4f6..45ea6887b 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -698,18 +698,18 @@ static bool emrtd_lds_get_data_by_tag(uint8_t *datain, size_t datainlen, uint8_t static bool emrtd_select_and_read(uint8_t *dataout, size_t *dataoutlen, uint16_t file, uint8_t *ks_enc, uint8_t *ks_mac, uint8_t *ssc, bool use_secure) { if (use_secure) { if (emrtd_secure_select_file_by_ef(ks_enc, ks_mac, ssc, file) == false) { - PrintAndLogEx(ERR, "Failed to secure select %s.", file); + PrintAndLogEx(ERR, "Failed to secure select %04X", file); return false; } } else { if (emrtd_select_file_by_ef(file) == false) { - PrintAndLogEx(ERR, "Failed to select %04X.", file); + PrintAndLogEx(ERR, "Failed to select %04X", file); return false; } } if (emrtd_read_file(dataout, dataoutlen, ks_enc, ks_mac, ssc, use_secure) == false) { - PrintAndLogEx(ERR, "Failed to read %04X.", file); + PrintAndLogEx(ERR, "Failed to read %04X", file); return false; } return true; From b93de4388a442b68d43591a3119a7e97dde9ac36 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 08:41:18 +0200 Subject: [PATCH 023/309] textual --- client/src/cmdhfcipurse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfcipurse.c b/client/src/cmdhfcipurse.c index faeea6dab..427340ca4 100644 --- a/client/src/cmdhfcipurse.c +++ b/client/src/cmdhfcipurse.c @@ -67,7 +67,7 @@ static int CmdHFCipurseInfo(const char *Cmd) { if (sw) PrintAndLogEx(INFO, "Not a CIPURSE card. APDU response: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); else - PrintAndLogEx(ERR, "APDU exchange error. Card returns 0x0000."); + PrintAndLogEx(ERR, "APDU exchange error. Card returns 0x0000"); DropField(); return PM3_SUCCESS; From b8aedada544f08f7a97375f84cdde2734a5044f7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 08:56:06 +0200 Subject: [PATCH 024/309] text --- client/src/cmddata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 2a715325c..4371a0187 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -2702,7 +2702,7 @@ typedef struct { static int print_modulation(lf_modulation_t b) { PrintAndLogEx(INFO, " Modulation........ " _GREEN_("%s"), GetSelectedModulationStr(b.modulation)); PrintAndLogEx(INFO, " Bit clock......... " _GREEN_("RF/%d"), b.bitrate); - PrintAndLogEx(INFO, " Approx baudrate... " _GREEN_("%.f") "bauds", (125000 / (float)b.bitrate)); + PrintAndLogEx(INFO, " Approx baudrate... " _GREEN_("%.f") " baud", (125000 / (float)b.bitrate)); switch (b.modulation) { case DEMOD_PSK1: case DEMOD_PSK2: From 0fdcae66829547289b54ae0abeb08c4814c129a1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 10:11:11 +0200 Subject: [PATCH 025/309] maur keys --- client/dictionaries/mfc_default_keys.dic | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index d2c41cbe7..872954ac7 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -1416,3 +1416,8 @@ D1417E431949 3a471b2192bf a297ceb7d34b ae76242931f1 +# +# +124578ABFEDC +ABFEDC124578 +4578ABFEDC12 From 9a063d75fe2e0f9f2ab61d0029a6b7442157c8c8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 10:32:08 +0200 Subject: [PATCH 026/309] style, the return codes needs to be adjusted to follow the PM3_E* styled defines. --- client/src/iso7816/iso7816core.c | 115 +++++++++++++++++++++---------- client/src/iso7816/iso7816core.h | 13 ++-- 2 files changed, 85 insertions(+), 43 deletions(-) diff --git a/client/src/iso7816/iso7816core.c b/client/src/iso7816/iso7816core.c index fae43b9dd..9c336c0bc 100644 --- a/client/src/iso7816/iso7816core.c +++ b/client/src/iso7816/iso7816core.c @@ -37,7 +37,11 @@ static isodep_state_t isodep_state = ISODEP_INACTIVE; void SetISODEPState(isodep_state_t state) { isodep_state = state; if (APDULogging) { - PrintAndLogEx(SUCCESS, ">>>> ISODEP -> %s%s%s", isodep_state == ISODEP_INACTIVE ? "inactive" : "", isodep_state == ISODEP_NFCA ? "NFC-A" : "", isodep_state == ISODEP_NFCB ? "NFC-B" : ""); + PrintAndLogEx(SUCCESS, "Setting ISODEP -> %s%s%s" + , isodep_state == ISODEP_INACTIVE ? "inactive" : "" + , isodep_state == ISODEP_NFCA ? _GREEN_("NFC-A") : "" + , isodep_state == ISODEP_NFCB ? _GREEN_("NFC-B") : "" + ); } } @@ -51,46 +55,50 @@ int Iso7816Connect(Iso7816CommandChannel channel) { } // Try to 14a // select with no disconnect and set frameLength - int selres = SelectCard14443A_4(false, NULL); - if (selres == PM3_SUCCESS) { + int res = SelectCard14443A_4(false, NULL); + if (res == PM3_SUCCESS) { SetISODEPState(ISODEP_NFCA); return PM3_SUCCESS; } PrintAndLogEx(DEBUG, "No 14a tag spotted, trying 14b"); // If not 14a, try to 14b - selres = select_card_14443b_4(false, NULL); - if (selres == PM3_SUCCESS) { + res = select_card_14443b_4(false, NULL); + if (res == PM3_SUCCESS) { SetISODEPState(ISODEP_NFCB); return PM3_SUCCESS; } + PrintAndLogEx(DEBUG, "No 14b tag spotted, failed to find any tag."); - return selres; + return res; } -int Iso7816ExchangeEx(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool includeLe, uint16_t Le, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - uint8_t data[APDU_RES_LEN] = {0}; +int Iso7816ExchangeEx(Iso7816CommandChannel channel, bool activate_field, bool leave_field_on, + sAPDU apdu, bool include_le, uint16_t le, uint8_t *result, + size_t max_result_len, size_t *result_len, uint16_t *sw) { - *ResultLen = 0; - if (sw) *sw = 0; - uint16_t isw = 0; - int res = 0; + *result_len = 0; + if (sw) { + *sw = 0; + } - if (ActivateField) { + if (activate_field) { DropFieldEx(channel); msleep(50); } // COMPUTE APDU int datalen = 0; - if (includeLe) { - if (Le == 0) { - Le = 0x100; + if (include_le) { + if (le == 0) { + le = 0x100; } } else { - Le = 0; + le = 0; } - if (APDUEncodeS(&apdu, false, Le, data, &datalen)) { + + uint8_t data[APDU_RES_LEN] = {0}; + if (APDUEncodeS(&apdu, false, le, data, &datalen)) { PrintAndLogEx(ERR, "APDU encoding error."); return 201; } @@ -98,59 +106,68 @@ int Iso7816ExchangeEx(Iso7816CommandChannel channel, bool ActivateField, bool Le if (APDULogging) PrintAndLogEx(SUCCESS, ">>>> %s", sprint_hex(data, datalen)); + int res = 0; + switch (channel) { - case CC_CONTACTLESS: + case CC_CONTACTLESS: { + switch (GetISODEPState()) { case ISODEP_NFCA: - res = ExchangeAPDU14a(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); + res = ExchangeAPDU14a(data, datalen, activate_field, leave_field_on, result, (int)max_result_len, (int *)result_len); break; case ISODEP_NFCB: - res = exchange_14b_apdu(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen, 4000); + res = exchange_14b_apdu(data, datalen, activate_field, leave_field_on, result, (int)max_result_len, (int *)result_len, 4000); break; case ISODEP_INACTIVE: - if (! ActivateField) { + if (activate_field == false) { PrintAndLogEx(FAILED, "Field currently inactive, cannot send an APDU"); return PM3_EIO; } - res = ExchangeAPDU14a(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); + res = ExchangeAPDU14a(data, datalen, activate_field, leave_field_on, result, (int)max_result_len, (int *)result_len); if (res != PM3_SUCCESS) { - res = exchange_14b_apdu(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen, 4000); + res = exchange_14b_apdu(data, datalen, activate_field, leave_field_on, result, (int)max_result_len, (int *)result_len, 4000); } break; } + if (res != PM3_SUCCESS) { return res; } break; - case CC_CONTACT: + } + case CC_CONTACT: { res = 1; - if (IfPm3Smartcard()) - res = ExchangeAPDUSC(false, data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); + if (IfPm3Smartcard()) { + res = ExchangeAPDUSC(false, data, datalen, activate_field, leave_field_on, result, (int)max_result_len, (int *)result_len); + } if (res) { return res; } break; + } } if (APDULogging) - PrintAndLogEx(SUCCESS, "<<<< %s", sprint_hex(Result, *ResultLen)); + PrintAndLogEx(SUCCESS, "<<<< %s", sprint_hex(result, *result_len)); - if (*ResultLen < 2) { + if (*result_len < 2) { return 200; } - *ResultLen -= 2; - isw = Result[*ResultLen] * 0x0100 + Result[*ResultLen + 1]; - if (sw) + *result_len -= 2; + uint16_t isw = (result[*result_len] * 0x0100) + result[*result_len + 1]; + + if (sw) { *sw = isw; + } if (isw != 0x9000) { if (APDULogging) { if (*sw >> 8 == 0x61) { - PrintAndLogEx(ERR, "APDU chaining len:%02x -->", *sw & 0xff); + PrintAndLogEx(ERR, "APDU chaining len %02x", *sw & 0xFF); } else { - PrintAndLogEx(ERR, "APDU(%02x%02x) ERROR: [%4X] %s", apdu.CLA, apdu.INS, isw, GetAPDUCodeDescription(*sw >> 8, *sw & 0xff)); + PrintAndLogEx(ERR, "APDU(%02x%02x) ERROR: [%4X] %s", apdu.CLA, apdu.INS, isw, GetAPDUCodeDescription(*sw >> 8, *sw & 0xFF)); return 5; } } @@ -158,10 +175,32 @@ int Iso7816ExchangeEx(Iso7816CommandChannel channel, bool ActivateField, bool Le return PM3_SUCCESS; } -int Iso7816Exchange(Iso7816CommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - return Iso7816ExchangeEx(channel, false, LeaveFieldON, apdu, false, 0, Result, MaxResultLen, ResultLen, sw); +int Iso7816Exchange(Iso7816CommandChannel channel, bool leave_field_on, sAPDU apdu, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { + return Iso7816ExchangeEx(channel + , false + , leave_field_on + , apdu + , false + , 0 + , result + , max_result_len + , result_len + , sw + ); } -int Iso7816Select(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - return Iso7816ExchangeEx(channel, ActivateField, LeaveFieldON, (sAPDU) {0x00, 0xa4, 0x04, 0x00, AIDLen, AID}, (channel == CC_CONTACTLESS), 0, Result, MaxResultLen, ResultLen, sw); +int Iso7816Select(Iso7816CommandChannel channel, bool activate_field, bool leave_field_on, uint8_t *aid, size_t aid_len, + uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { + + return Iso7816ExchangeEx(channel + , activate_field + , leave_field_on + , (sAPDU) {0x00, 0xa4, 0x04, 0x00, aid_len, aid} + , (channel == CC_CONTACTLESS) + , 0 + , result + , max_result_len + , result_len + , sw + ); } diff --git a/client/src/iso7816/iso7816core.h b/client/src/iso7816/iso7816core.h index 8c0b44629..beb5e3e90 100644 --- a/client/src/iso7816/iso7816core.h +++ b/client/src/iso7816/iso7816core.h @@ -12,9 +12,7 @@ #define ISO7816CORE_H__ #include "common.h" - #include - #include "apduinfo.h" #define APDU_RES_LEN 260 @@ -41,9 +39,14 @@ isodep_state_t GetISODEPState(void); int Iso7816Connect(Iso7816CommandChannel channel); // exchange -int Iso7816Exchange(Iso7816CommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); -int Iso7816ExchangeEx(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool IncludeLe, uint16_t Le, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +int Iso7816Exchange(Iso7816CommandChannel channel, bool leave_field_on, sAPDU apdu, uint8_t *result, size_t max_result_len, + size_t *result_len, uint16_t *sw); + +int Iso7816ExchangeEx(Iso7816CommandChannel channel, bool activate_field, bool leave_field_on, sAPDU apdu, bool include_le, + uint16_t le, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); // search application -int Iso7816Select(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +int Iso7816Select(Iso7816CommandChannel channel, bool activate_field, bool leave_field_on, uint8_t *aid, size_t aid_len, + uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); + #endif From e8d5d811782b66a8d9eb40b2d94e0a398abc70b3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 10:41:47 +0200 Subject: [PATCH 027/309] code style, and make less output for hf search --- client/src/cmdhf14a.c | 70 ++++++++++++++++++++------------ client/src/cmdhf14a.h | 2 +- client/src/cmdhfmfdes.c | 2 +- client/src/iso7816/iso7816core.c | 2 +- 4 files changed, 46 insertions(+), 30 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index fd8d9db9a..b221869d7 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -181,7 +181,7 @@ static const hintAIDListT hintAIDList[] = { }; // iso14a apdu input frame length -static uint16_t frameLength = 0; +static uint16_t g_frame_len = 0; uint16_t atsFSC[] = {16, 24, 32, 40, 48, 64, 96, 128, 256}; static int CmdHF14AList(const char *Cmd) { @@ -857,31 +857,35 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav return 0; } -int SelectCard14443A_4(bool disconnect, iso14a_card_select_t *card) { - PacketResponseNG resp; +int SelectCard14443A_4(bool disconnect, bool verbose, iso14a_card_select_t *card) { - frameLength = 0; + // global vars should be prefixed with g_ + g_frame_len = 0; - if (card) + if (card) { memset(card, 0, sizeof(iso14a_card_select_t)); + } DropField(); // Anticollision + SELECT card + PacketResponseNG resp; SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) { - PrintAndLogEx(ERR, "Proxmark3 connection timeout"); + PrintAndLogEx(WARNING, "Command execute timeout"); return PM3_ETIMEOUT; } // check result if (resp.oldarg[0] == 0) { - PrintAndLogEx(ERR, "No card in field"); + if (verbose) { + PrintAndLogEx(FAILED, "No card in field"); + } return PM3_ECARDEXCHANGE; } if (resp.oldarg[0] != 1 && resp.oldarg[0] != 2) { - PrintAndLogEx(ERR, "Card not in iso14443-4, res=%" PRId64 ".", resp.oldarg[0]); + PrintAndLogEx(WARNING, "Card not in iso14443-4, res=%" PRId64 ".", resp.oldarg[0]); return PM3_ECARDEXCHANGE; } @@ -890,36 +894,44 @@ int SelectCard14443A_4(bool disconnect, iso14a_card_select_t *card) { uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, sizeof(rats), 0, rats, sizeof(rats)); if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) { - PrintAndLogEx(ERR, "Proxmark3 connection timeout"); + PrintAndLogEx(WARNING, "Command execute timeout"); return PM3_ETIMEOUT; } if (resp.oldarg[0] == 0) { // ats_len - PrintAndLogEx(ERR, "Can't get ATS"); + if (verbose) { + PrintAndLogEx(FAILED, "Can't get ATS"); + } return PM3_ECARDEXCHANGE; } // get frame length from ATS in data field if (resp.oldarg[0] > 1) { uint8_t fsci = resp.data.asBytes[1] & 0x0f; - if (fsci < ARRAYLEN(atsFSC)) - frameLength = atsFSC[fsci]; + if (fsci < ARRAYLEN(atsFSC)) { + g_frame_len = atsFSC[fsci]; + } } } else { // get frame length from ATS in card data structure iso14a_card_select_t *vcard = (iso14a_card_select_t *) resp.data.asBytes; if (vcard->ats_len > 1) { uint8_t fsci = vcard->ats[1] & 0x0f; - if (fsci < ARRAYLEN(atsFSC)) - frameLength = atsFSC[fsci]; + if (fsci < ARRAYLEN(atsFSC)) { + g_frame_len = atsFSC[fsci]; + } } - if (card) + if (card) { memcpy(card, vcard, sizeof(iso14a_card_select_t)); + } } + SetISODEPState(ISODEP_NFCA); - if (disconnect) + + if (disconnect) { DropField(); + } return PM3_SUCCESS; } @@ -928,8 +940,8 @@ static int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool *chainingout = false; if (activateField) { - // select with no disconnect and set frameLength - int selres = SelectCard14443A_4(false, NULL); + // select with no disconnect and set g_frame_len + int selres = SelectCard14443A_4(false, true, NULL); if (selres != PM3_SUCCESS) return selres; } @@ -965,7 +977,7 @@ static int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool } // I-block ACK - if ((res & 0xf2) == 0xa2) { + if ((res & 0xF2) == 0xA2) { *dataoutlen = 0; *chainingout = true; return PM3_SUCCESS; @@ -1015,13 +1027,14 @@ int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool lea // 3 byte here - 1b framing header, 2b crc16 if (APDUInFramingEnable && - ((frameLength && (datainlen > frameLength - 3)) || (datainlen > PM3_CMD_DATA_SIZE - 3))) { + ((g_frame_len && (datainlen > g_frame_len - 3)) || (datainlen > PM3_CMD_DATA_SIZE - 3))) { + int clen = 0; bool vActivateField = activateField; do { - int vlen = MIN(frameLength - 3, datainlen - clen); + int vlen = MIN(g_frame_len - 3, datainlen - clen); bool chainBlockNotLast = ((clen + vlen) < datainlen); *dataoutlen = 0; @@ -1045,17 +1058,19 @@ int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool lea clen += vlen; vActivateField = false; if (*dataoutlen) { - if (clen != datainlen) + if (clen != datainlen) { PrintAndLogEx(ERR, "APDU: I-block/R-block sequence error. Data len=%d, Sent=%d, Last packet len=%d", datainlen, clen, *dataoutlen); + } break; } } while (clen < datainlen); + } else { res = CmdExchangeAPDU(false, datain, datainlen, activateField, dataout, maxdataoutlen, dataoutlen, &chaining); if (res != PM3_SUCCESS) { - if (leaveSignalON == false) + if (leaveSignalON == false) { DropField(); - + } return res; } } @@ -1064,15 +1079,16 @@ int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool lea // I-block with chaining res = CmdExchangeAPDU(false, NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining); if (res != PM3_SUCCESS) { - if (leaveSignalON == false) + if (leaveSignalON == false) { DropField(); - + } return 100; } } - if (!leaveSignalON) + if (leaveSignalON == false) { DropField(); + } return PM3_SUCCESS; } diff --git a/client/src/cmdhf14a.h b/client/src/cmdhf14a.h index 484b43cfd..18e9fffd7 100644 --- a/client/src/cmdhf14a.h +++ b/client/src/cmdhf14a.h @@ -43,5 +43,5 @@ int Hf14443_4aGetCardData(iso14a_card_select_t *card); int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool silentMode); -int SelectCard14443A_4(bool disconnect, iso14a_card_select_t *card); +int SelectCard14443A_4(bool disconnect, bool verbose, iso14a_card_select_t *card); #endif diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index bec41af0b..52d26bb7f 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -3685,7 +3685,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { iso14a_card_select_t card; - res = SelectCard14443A_4(true, &card); + res = SelectCard14443A_4(true, false, &card); if (res == PM3_SUCCESS) { static const char STANDALONE_DESFIRE[] = { 0x75, 0x77, 0x81, 0x02}; static const char JCOP_DESFIRE[] = { 0x75, 0xf7, 0xb1, 0x02 }; diff --git a/client/src/iso7816/iso7816core.c b/client/src/iso7816/iso7816core.c index 9c336c0bc..3907d7744 100644 --- a/client/src/iso7816/iso7816core.c +++ b/client/src/iso7816/iso7816core.c @@ -55,7 +55,7 @@ int Iso7816Connect(Iso7816CommandChannel channel) { } // Try to 14a // select with no disconnect and set frameLength - int res = SelectCard14443A_4(false, NULL); + int res = SelectCard14443A_4(false, false, NULL); if (res == PM3_SUCCESS) { SetISODEPState(ISODEP_NFCA); return PM3_SUCCESS; From 861e06d8af874b1cfbbd6db85621aa9a4fc90abb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 10:47:23 +0200 Subject: [PATCH 028/309] fix coverity CID 322780 - out-of-bounds --- client/src/cmdhfmfdes.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 52d26bb7f..48cd15b5c 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -2033,18 +2033,24 @@ static int handler_desfire_writedata(mfdes_data_t *data, MFDES_FILE_TYPE_T type, if (data->fileno > 0x1F) { return PM3_EINVARG; } + uint32_t datatowrite = le24toh(data->length); uint32_t offset = le24toh(data->offset); uint32_t datasize, recvlen = 0; int res = PM3_SUCCESS; uint16_t sw = 0; - uint8_t tmp[60] = {0}; + mfdes_data_t sdata; sAPDU apdu = {0x90, MFDES_WRITE_DATA, 0x00, 0x00, 0, (uint8_t *) &sdata}; // 0x3D + + uint8_t tmp[61] = {0}; tmp[0] = MFDES_WRITE_DATA; tmp[1] = data->fileno; apdu.data = &tmp[1]; // tmp[0] is holding the OPCODE for macd calc, so we dont want it in the apdu - if (type == MFDES_RECORD_FILE) apdu.INS = MFDES_WRITE_RECORD; + + if (type == MFDES_RECORD_FILE) { + apdu.INS = MFDES_WRITE_RECORD; + } while (datatowrite) { From 70709ca0ed82af6c0c737343452438b155de3da8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 11:13:49 +0200 Subject: [PATCH 029/309] fix coverity CID 349306 - resource leak --- tools/fpga_compress/fpga_compress.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/fpga_compress/fpga_compress.c b/tools/fpga_compress/fpga_compress.c index 005f805c4..1726117fd 100644 --- a/tools/fpga_compress/fpga_compress.c +++ b/tools/fpga_compress/fpga_compress.c @@ -179,6 +179,9 @@ static int zlib_decompress(FILE *infile, FILE *outfiles[], uint8_t num_outfiles, fclose(outfiles[j]); } } + if (outbufall) { + free(outbufall); + } free(inbuf); return (EXIT_FAILURE); } @@ -247,6 +250,9 @@ static int zlib_decompress(FILE *infile, FILE *outfiles[], uint8_t num_outfiles, fclose(outfiles[j]); } } + if (outbufall) { + free(outbufall); + } return (EXIT_SUCCESS); } From 4d95cc2fdba6ac52c10a3812fb91570283490339 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 11:15:48 +0200 Subject: [PATCH 030/309] fix coverity CID 349307 --- client/src/cmdhfemrtd.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 45ea6887b..7791233dc 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1034,8 +1034,8 @@ int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab // Dump EF_CardAccess (if available) if (!emrtd_dump_file(ks_enc, ks_mac, ssc, dg_table[EF_CardAccess].fileid, dg_table[EF_CardAccess].filename, BAC, path)) { - PrintAndLogEx(INFO, "Couldn't dump EF_CardAccess, card does not support PACE."); - PrintAndLogEx(HINT, "This is expected behavior for cards without PACE, and isn't something to be worried about."); + PrintAndLogEx(INFO, "Couldn't dump EF_CardAccess, card does not support PACE"); + PrintAndLogEx(HINT, "This is expected behavior for cards without PACE, and isn't something to be worried about"); } // Authenticate with the eMRTD @@ -1046,7 +1046,7 @@ int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab // Select EF_COM if (!emrtd_select_and_read(response, &resplen, dg_table[EF_COM].fileid, ks_enc, ks_mac, ssc, BAC)) { - PrintAndLogEx(ERR, "Failed to read EF_COM."); + PrintAndLogEx(ERR, "Failed to read EF_COM"); DropField(); return PM3_ESOFT; } @@ -1055,11 +1055,12 @@ int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab char *filepath = calloc(strlen(path) + 100, sizeof(char)); if (filepath == NULL) return PM3_EMALLOC; + strcpy(filepath, path); strncat(filepath, PATHSEP, 2); strcat(filepath, dg_table[EF_COM].filename); - PrintAndLogEx(INFO, "Read EF_COM, len: %i.", resplen); + PrintAndLogEx(INFO, "Read EF_COM, len: %zu", resplen); PrintAndLogEx(DEBUG, "Contents (may be incomplete over 2k chars): %s", sprint_hex_inrow(response, resplen)); saveFile(filepath, ".BIN", response, resplen); @@ -1069,7 +1070,7 @@ int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab size_t filelistlen = 0; if (emrtd_lds_get_data_by_tag(response, resplen, filelist, &filelistlen, 0x5c, 0x00, false, true, 0) == false) { - PrintAndLogEx(ERR, "Failed to read file list from EF_COM."); + PrintAndLogEx(ERR, "Failed to read file list from EF_COM"); DropField(); return PM3_ESOFT; } From 6f2cb98ae498830ae63879d4dc43aa5fa8da80cf Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 11:17:23 +0200 Subject: [PATCH 031/309] fix coverity CID 349310 --- client/src/nfc/ndef.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/nfc/ndef.c b/client/src/nfc/ndef.c index 5ecddc09f..2bc841a23 100644 --- a/client/src/nfc/ndef.c +++ b/client/src/nfc/ndef.c @@ -548,9 +548,9 @@ static int ndefDecodeMime_bt(NDEFHeader_t *ndef) { } // Let's check payload[9]. If 0x08 then SHORT_NAME or if 0x09 then COMPLETE_NAME if (ndef->Payload[9] == 0x08 ) { - PrintAndLogEx(INFO, "Short name...... " _YELLOW_("%.*s"), ndef->PayloadLen - 10, ndef->Payload + 10); + PrintAndLogEx(INFO, "Short name...... " _YELLOW_("%.*s"), (int)(ndef->PayloadLen - 10), ndef->Payload + 10); } else if (ndef->Payload[9] == 0x09 ) { - PrintAndLogEx(INFO, "Complete name... " _YELLOW_("%.*s"), ndef->PayloadLen - 10, ndef->Payload + 10); + PrintAndLogEx(INFO, "Complete name... " _YELLOW_("%.*s"), (int)(ndef->PayloadLen - 10), ndef->Payload + 10); } else { PrintAndLogEx(INFO, "[ %02x ]", ndef->Payload[9]); } From f6534e18bee22e0f6ec334e47e0f5d73a1842726 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 16:36:31 +0200 Subject: [PATCH 032/309] style --- armsrc/desfire_crypto.c | 50 +++++++++++++------ client/src/mifare/desfire_crypto.c | 78 +++++++++++++++++++++--------- 2 files changed, 88 insertions(+), 40 deletions(-) diff --git a/armsrc/desfire_crypto.c b/armsrc/desfire_crypto.c index 782466be2..c32d6e4df 100644 --- a/armsrc/desfire_crypto.c +++ b/armsrc/desfire_crypto.c @@ -103,8 +103,9 @@ void tdes_nxp_send(const void *in, void *out, size_t length, const void *key, un uint8_t *tout = (uint8_t *) out; while (length > 0) { - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { tin[i] = (unsigned char)(tin[i] ^ iv[i]); + } mbedtls_des3_crypt_ecb(&ctx3, tin, tout); @@ -121,8 +122,9 @@ void tdes_nxp_send(const void *in, void *out, size_t length, const void *key, un void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key) { uint8_t data[8]; memcpy(data, value, 8); - for (int n = 0; n < 8; n++) - data[n] &= 0xfe; + for (int n = 0; n < 8; n++) { + data[n] &= 0xFE; + } Desfire_des_key_new_with_version(data, key); } @@ -138,10 +140,12 @@ void Desfire_des_key_new_with_version(const uint8_t value[8], desfirekey_t key) void Desfire_3des_key_new(const uint8_t value[16], desfirekey_t key) { uint8_t data[16]; memcpy(data, value, 16); - for (int n = 0; n < 8; n++) - data[n] &= 0xfe; - for (int n = 8; n < 16; n++) + for (int n = 0; n < 8; n++) { + data[n] &= 0xFE; + } + for (int n = 8; n < 16; n++) { data[n] |= 0x01; + } Desfire_3des_key_new_with_version(data, key); } @@ -156,8 +160,9 @@ void Desfire_3des_key_new_with_version(const uint8_t value[16], desfirekey_t key void Desfire_3k3des_key_new(const uint8_t value[24], desfirekey_t key) { uint8_t data[24]; memcpy(data, value, 24); - for (int n = 0; n < 8; n++) - data[n] &= 0xfe; + for (int n = 0; n < 8; n++) { + data[n] &= 0xFE; + } Desfire_3k3des_key_new_with_version(data, key); } @@ -194,13 +199,13 @@ uint8_t Desfire_key_get_version(desfirekey_t key) { void Desfire_key_set_version(desfirekey_t key, uint8_t version) { for (int n = 0; n < 8; n++) { uint8_t version_bit = ((version & (1 << (7 - n))) >> (7 - n)); - key->data[n] &= 0xfe; + key->data[n] &= 0xFE; key->data[n] |= version_bit; if (key->type == T_DES) { key->data[n + 8] = key->data[n]; } else { // Write ~version to avoid turning a 3DES key into a DES key - key->data[n + 8] &= 0xfe; + key->data[n + 8] &= 0xFE; key->data[n + 8] |= ~version_bit; } } @@ -267,23 +272,32 @@ void cmac_generate_subkeys(desfirekey_t key) { // Used to compute CMAC on complete blocks memcpy(key->cmac_sk1, l, kbs); + txor = l[0] & 0x80; + lsl(key->cmac_sk1, kbs); - if (txor) + + if (txor) { key->cmac_sk1[kbs - 1] ^= R; + } // Used to compute CMAC on the last block if non-complete memcpy(key->cmac_sk2, key->cmac_sk1, kbs); + txor = key->cmac_sk1[0] & 0x80; + lsl(key->cmac_sk2, kbs); - if (txor) + + if (txor) { key->cmac_sk2[kbs - 1] ^= R; + } } void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac) { int kbs = key_block_size(key); - if (kbs == 0) + if (kbs == 0) { return; + } uint8_t *buffer = BigBuf_malloc(padded_data_length(len, kbs)); @@ -306,8 +320,10 @@ void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t le } size_t key_block_size(const desfirekey_t key) { - if (key == NULL) + if (key == NULL) { return 0; + } + size_t block_size = 8; switch (key->type) { case T_DES: @@ -830,10 +846,12 @@ void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *i size_t block_size; if (tag) { - if (!key) + if (key == NULL) { key = DESFIRE(tag)->session_key; - if (!ivect) + } + if (ivect == NULL) { ivect = DESFIRE(tag)->ivect; + } switch (DESFIRE(tag)->authentication_scheme) { case AS_LEGACY: diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 1cf043a7b..01c233de3 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -66,10 +66,14 @@ void des_decrypt(void *out, const void *in, const void *key) { } void tdes_nxp_receive(const void *in, void *out, size_t length, const void *key, unsigned char iv[8], int keymode) { - if (length % 8) return; + if (length % 8) + return; + mbedtls_des3_context ctx3; - if (keymode == 2) mbedtls_des3_set2key_dec(&ctx3, key); - else mbedtls_des3_set3key_dec(&ctx3, key); + if (keymode == 2) + mbedtls_des3_set2key_dec(&ctx3, key); + else + mbedtls_des3_set3key_dec(&ctx3, key); uint8_t i; unsigned char temp[8]; @@ -81,8 +85,9 @@ void tdes_nxp_receive(const void *in, void *out, size_t length, const void *key, mbedtls_des3_crypt_ecb(&ctx3, tin, tout); - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { tout[i] = (unsigned char)(tout[i] ^ iv[i]); + } memcpy(iv, temp, 8); @@ -93,18 +98,24 @@ void tdes_nxp_receive(const void *in, void *out, size_t length, const void *key, } void tdes_nxp_send(const void *in, void *out, size_t length, const void *key, unsigned char iv[8], int keymode) { - if (length % 8) return; + if (length % 8) + return; + mbedtls_des3_context ctx3; - if (keymode == 2) mbedtls_des3_set2key_enc(&ctx3, key); - else mbedtls_des3_set3key_enc(&ctx3, key); + + if (keymode == 2) + mbedtls_des3_set2key_enc(&ctx3, key); + else + mbedtls_des3_set3key_enc(&ctx3, key); uint8_t i; uint8_t *tin = (uint8_t *) in; uint8_t *tout = (uint8_t *) out; while (length > 0) { - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { tin[i] = (unsigned char)(tin[i] ^ iv[i]); + } mbedtls_des3_crypt_ecb(&ctx3, tin, tout); @@ -120,8 +131,9 @@ void tdes_nxp_send(const void *in, void *out, size_t length, const void *key, un void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key) { uint8_t data[8]; memcpy(data, value, 8); - for (int n = 0; n < 8; n++) - data[n] &= 0xfe; + for (int n = 0; n < 8; n++) { + data[n] &= 0xFE; + } Desfire_des_key_new_with_version(data, key); } @@ -137,10 +149,12 @@ void Desfire_des_key_new_with_version(const uint8_t value[8], desfirekey_t key) void Desfire_3des_key_new(const uint8_t value[16], desfirekey_t key) { uint8_t data[16]; memcpy(data, value, 16); - for (int n = 0; n < 8; n++) - data[n] &= 0xfe; - for (int n = 8; n < 16; n++) + for (int n = 0; n < 8; n++) { + data[n] &= 0xFE; + } + for (int n = 8; n < 16; n++) { data[n] |= 0x01; + } Desfire_3des_key_new_with_version(data, key); } @@ -155,8 +169,9 @@ void Desfire_3des_key_new_with_version(const uint8_t value[16], desfirekey_t key void Desfire_3k3des_key_new(const uint8_t value[24], desfirekey_t key) { uint8_t data[24]; memcpy(data, value, 24); - for (int n = 0; n < 8; n++) - data[n] &= 0xfe; + for (int n = 0; n < 8; n++) { + data[n] &= 0xFE; + } Desfire_3k3des_key_new_with_version(data, key); } @@ -173,7 +188,6 @@ void Desfire_aes_key_new(const uint8_t value[16], desfirekey_t key) { } void Desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version, desfirekey_t key) { - if (key != NULL) { memcpy(key->data, value, 16); key->type = T_AES; @@ -193,13 +207,15 @@ uint8_t Desfire_key_get_version(desfirekey_t key) { void Desfire_key_set_version(desfirekey_t key, uint8_t version) { for (int n = 0; n < 8; n++) { uint8_t version_bit = ((version & (1 << (7 - n))) >> (7 - n)); - key->data[n] &= 0xfe; + + key->data[n] &= 0xFE; key->data[n] |= version_bit; + if (key->type == T_DES) { key->data[n + 8] = key->data[n]; } else { // Write ~version to avoid turning a 3DES key into a DES key - key->data[n + 8] &= 0xfe; + key->data[n + 8] &= 0xFE; key->data[n + 8] |= ~version_bit; } } @@ -268,15 +284,17 @@ void cmac_generate_subkeys(desfirekey_t key, MifareCryptoDirection direction) { memcpy(key->cmac_sk1, l, kbs); txor = l[0] & 0x80; lsl(key->cmac_sk1, kbs); - if (txor) + if (txor) { key->cmac_sk1[kbs - 1] ^= R; + } // Used to compute CMAC on the last block if non-complete memcpy(key->cmac_sk2, key->cmac_sk1, kbs); txor = key->cmac_sk1[0] & 0x80; lsl(key->cmac_sk2, kbs); - if (txor) + if (txor) { key->cmac_sk2[kbs - 1] ^= R; + } } void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac) { @@ -286,6 +304,10 @@ void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t le } uint8_t *buffer = calloc(padded_data_length(len, kbs), sizeof(uint8_t)); + if (buffer == NULL) { + PrintAndLogEx(WARNING, "failed to allocate memory"); + return; + } memcpy(buffer, data, len); @@ -315,10 +337,17 @@ void mifare_kdf_an10922(const desfirekey_t key, const uint8_t *data, size_t len) cmac_generate_subkeys(key, MCD_SEND); - uint8_t *buffer = calloc(kbs2, sizeof(uint8_t)); + // reserv atleast 32bytes. + uint8_t *buffer = calloc(len, sizeof(uint8_t)); + if (buffer == NULL) { + PrintAndLogEx(WARNING, "failed to allocate memory"); + return; + } uint8_t *ivect = calloc(kbs, sizeof(uint8_t)); - - memset(ivect, 0, kbs); + if (ivect == NULL) { + PrintAndLogEx(WARNING, "failed to allocate memory"); + return; + } buffer[0] = 0x01; memcpy(&buffer[1], data, len++); @@ -345,8 +374,9 @@ void mifare_kdf_an10922(const desfirekey_t key, const uint8_t *data, size_t len) } size_t key_block_size(const desfirekey_t key) { - if (key == NULL) + if (key == NULL) { return 0; + } size_t block_size = 8; switch (key->type) { case T_DES: From 9d02c2e94a4632edf66bfea44095d373fa9ffab4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 16:37:51 +0200 Subject: [PATCH 033/309] renamed 'hf mfdes readdata, writedata' to 'read/write' --- client/src/cmdhfmfdes.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 48cd15b5c..4a59c780a 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -3005,11 +3005,11 @@ static int CmdHF14ADesGetValueData(const char *Cmd) { static int CmdHF14ADesReadData(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes readdata", + CLIParserInit(&ctx, "hf mfdes read", "Read data from File\n" "Make sure to select aid or authenticate aid before running this command.", - "hf mfdes readdata -n 01 -t 0 -o 000000 -l 000000 -a 123456\n" - "hf mfdes readdata -n 01 -t 0 --> Read all data from standard file, fileno 01" + "hf mfdes read -n 1 -t 0 -o 000000 -l 000000 -a 123456\n" + "hf mfdes read -n 1 -t 0 --> Read all data from standard file, fileno 1" ); void *argtable[] = { @@ -3099,13 +3099,13 @@ static int CmdHF14ADesReadData(const char *Cmd) { if (res == PM3_SUCCESS) { uint32_t len = le24toh(ft.length); - PrintAndLogEx(SUCCESS, "Read %u bytes from file %d:", ft.fileno, len); + PrintAndLogEx(SUCCESS, "Read %u bytes from file %d", ft.fileno, len); PrintAndLogEx(INFO, "Offset | Data | Ascii"); PrintAndLogEx(INFO, "----------------------------------------------------------------------------"); for (uint32_t i = 0; i < len; i += 16) { uint32_t l = len - i; - PrintAndLogEx(INFO, "%02d/0x%02X | %s| %s", i, i, sprint_hex(&ft.data[i], l > 16 ? 16 : l), sprint_ascii(&ft.data[i], l > 16 ? 16 : l)); + PrintAndLogEx(INFO, "%3d/0x%02X | %s| %s", i, i, sprint_hex(&ft.data[i], l > 16 ? 16 : l), sprint_ascii(&ft.data[i], l > 16 ? 16 : l)); } } else { PrintAndLogEx(ERR, "Couldn't read data. Error %d", res); @@ -3209,10 +3209,10 @@ static int CmdHF14ADesChangeValue(const char *Cmd) { static int CmdHF14ADesWriteData(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes writedata", - "Write data to File\n" + CLIParserInit(&ctx, "hf mfdes write", + "Write data to file\n" "Make sure to select aid or authenticate aid before running this command.", - "hf mfdes writedata -n 01 -t 0 -o 000000 -d 3132333435363738" + "hf mfdes write -n 01 -t 0 -o 000000 -d 3132333435363738" ); void *argtable[] = { @@ -5143,8 +5143,8 @@ static command_t CommandTable[] = { {"deletefile", CmdHF14ADesDeleteFile, IfPm3Iso14443a, "Create Delete File"}, {"dump", CmdHF14ADesDump, IfPm3Iso14443a, "Dump all files"}, {"getvalue", CmdHF14ADesGetValueData, IfPm3Iso14443a, "Get value of file"}, - {"readdata", CmdHF14ADesReadData, IfPm3Iso14443a, "Read data from standard/backup/record file"}, - {"writedata", CmdHF14ADesWriteData, IfPm3Iso14443a, "Write data to standard/backup/record file"}, + {"read", CmdHF14ADesReadData, IfPm3Iso14443a, "Read data from standard/backup/record file"}, + {"write", CmdHF14ADesWriteData, IfPm3Iso14443a, "Write data to standard/backup/record file"}, {NULL, NULL, NULL, NULL} }; From 1ed21a3ae8b0c4a3e5fb32f55c12f7636778774f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 18:26:45 +0200 Subject: [PATCH 034/309] added more keys (@equipter) --- CHANGELOG.md | 1 + client/dictionaries/mfc_default_keys.dic | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d325f9d9..9c102b2a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added more keys (@equipter) - Changed `hf nfc ndefread` - ndef parser now handles more types (@iceman1001) - Fix `hf desfire` changekey, GetUID, 3DES sesson key tweak. (@mwalker33) - Fix `hf fido` commands now works correctly (@merlokk) diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index 872954ac7..4ac03904d 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -1413,6 +1413,7 @@ F678905568C3 D1417E431949 4BF6DE347FB6 # +# 3a471b2192bf a297ceb7d34b ae76242931f1 @@ -1421,3 +1422,8 @@ ae76242931f1 124578ABFEDC ABFEDC124578 4578ABFEDC12 +# +# Data from +# premier inn hotel chain +5e594208ef02 +af9e38d36582 From 08b583e2bbbe06a979284325ca31f36e9f1d1b4f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 21:28:33 +0200 Subject: [PATCH 035/309] fix param call in lf keri demod --- client/src/cmdlfkeri.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdlfkeri.c b/client/src/cmdlfkeri.c index 8bd471049..f5df3b392 100644 --- a/client/src/cmdlfkeri.c +++ b/client/src/cmdlfkeri.c @@ -154,7 +154,7 @@ int demodKeri(bool verbose) { raw1 = bytebits_to_byte(DemodBuffer, 32); raw2 = bytebits_to_byte(DemodBuffer + 32, 32); - CmdPrintDemodBuff("x"); + CmdPrintDemodBuff("-x"); } //get internal id From 3ec98d936cc9f34e27d44ca1514954e5d35008ab Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 21:39:52 +0200 Subject: [PATCH 036/309] textual --- client/src/cmdlf.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index ef7e916b7..25b304c9e 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -686,9 +686,12 @@ int lf_sniff(bool verbose, uint32_t samples) { int CmdLFSniff(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf sniff", - "Sniff low frequency signal.\n" + "Sniff low frequency signal. You need to configure the LF part on the Proxmark3 device manually.\n" + "Usually a trigger and skip samples is a good thing to set before doing a low frequency sniff.\n" + "\n" " - use " _YELLOW_("`lf config`") _CYAN_(" to set parameters.\n") - _CYAN_(" - use ") _YELLOW_("`data plot`") _CYAN_(" to look at it"), + _CYAN_(" - use ") _YELLOW_("`data plot`") _CYAN_(" to look at sniff signal.\n") + _CYAN_(" - use ") _YELLOW_("`lf search -1`") _CYAN_(" to see if signal can be automatic decoded\n"), "lf sniff -v\n" "lf sniff -s 3000 -@ --> oscilloscope style \n" ); From 0e7e13db7dd608ac5cf3c40db172ae054eeed23e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 20 Jun 2021 23:02:18 +0200 Subject: [PATCH 037/309] fix for client crash in lf hitag eload. Hitag simulation still now working (wip) --- armsrc/appmain.c | 10 ++-------- client/src/cmdlfhitag.c | 35 +++++++++++++++++++++++------------ include/pm3_cmd.h | 6 ++++++ 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index a419617d1..af5c01c72 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1114,15 +1114,9 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_LF_HITAG_ELOAD: { - /* - struct p { - uint16_t len; - uint8_t *data; - } PACKED; - struct p *payload = (struct p *) packet->data.asBytes; + lf_hitag_t *payload = (lf_hitag_t *) packet->data.asBytes; uint8_t *mem = BigBuf_get_EM_addr(); - memcpy((uint8_t *)mem.sectors, payload->data, payload->len); - */ + memcpy((uint8_t *)mem, payload->data, payload->len); break; } #endif diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index 232acf068..287f39f06 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -210,14 +210,15 @@ static int CmdLFHitagEload(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf hitag eload", "Loads hitag tag dump into emulator memory on device", - "lf hitag eload -f lf-hitag-11223344-dump.bin\n"); + "lf hitag eload -2 -f lf-hitag-11223344-dump.bin\n"); void *argtable[] = { arg_param_begin, arg_str1("f", "file", "", "filename of dump"), - arg_lit0("1", NULL, "simulate Hitag1"), - arg_lit0("2", NULL, "simulate Hitag2"), - arg_lit0("s", NULL, "simulate HitagS"), + arg_lit0("1", NULL, "Card type Hitag1"), + arg_lit0("2", NULL, "Card type Hitag2"), + arg_lit0("s", NULL, "Card type HitagS"), + arg_lit0("m", NULL, "Card type HitagM"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -229,9 +230,10 @@ static int CmdLFHitagEload(const char *Cmd) { bool use_ht1 = arg_get_lit(ctx, 2); bool use_ht2 = arg_get_lit(ctx, 3); bool use_hts = arg_get_lit(ctx, 4); + bool use_htm = arg_get_lit(ctx, 5); CLIParserFree(ctx); - uint8_t n = (use_ht1 + use_ht2 + use_hts); + uint8_t n = (use_ht1 + use_ht2 + use_hts + use_htm); if (n != 1) { PrintAndLogEx(ERR, "error, only specify one Hitag type"); return PM3_EINVARG; @@ -274,15 +276,24 @@ static int CmdLFHitagEload(const char *Cmd) { // check dump len.. if (dumplen == 48 || dumplen == 4 * 64) { - struct { - uint16_t len; - uint8_t *data; - } PACKED payload; - payload.len = dumplen; - memcpy(payload.data, dump, dumplen); + + lf_hitag_t *payload = calloc(1, sizeof(lf_hitag_t) + dumplen); + + if (use_ht1) + payload->type = 1; + if (use_ht2) + payload->type = 2; + if (use_hts) + payload->type = 3; + if (use_htm) + payload->type = 4; + + payload->len = dumplen; + memcpy(payload->data, dump, dumplen); clearCommandBuffer(); - SendCommandNG(CMD_LF_HITAG_ELOAD, (uint8_t *)&payload, 2 + dumplen); + SendCommandNG(CMD_LF_HITAG_ELOAD, (uint8_t *)payload, 3 + dumplen); + free(payload); } else { PrintAndLogEx(ERR, "error, wrong dump file size. got %zu", dumplen); } diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index ed96c8467..4e89e4f86 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -259,6 +259,12 @@ typedef struct { uint8_t data[]; } PACKED lf_nrzsim_t; +typedef struct { + uint8_t type; + uint16_t len; + uint8_t *data; +} PACKED lf_hitag_t; + typedef struct { uint8_t blockno; uint8_t keytype; From 0f6b6cb6505fbb1c94862f785e3f481fb4ec7a01 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 21 Jun 2021 07:30:46 +0200 Subject: [PATCH 038/309] fix coverity CID 349331 --- client/src/mifare/desfire_crypto.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 01c233de3..0699249ff 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -346,6 +346,7 @@ void mifare_kdf_an10922(const desfirekey_t key, const uint8_t *data, size_t len) uint8_t *ivect = calloc(kbs, sizeof(uint8_t)); if (ivect == NULL) { PrintAndLogEx(WARNING, "failed to allocate memory"); + free(buffer); return; } From 293cd21e28040d31d1b138e28c37d88bc81262fb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 21 Jun 2021 09:03:46 +0200 Subject: [PATCH 039/309] textual --- client/src/cmdhfmf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index ba9cb97c0..b08de964c 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -2577,9 +2577,9 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { "hf mf fchk --2k -k FFFFFFFFFFFF --> Key recovery against MIFARE 2k\n" "hf mf fchk --4k -k FFFFFFFFFFFF --> Key recovery against MIFARE 4k\n" "hf mf fchk --1k -f mfc_default_keys.dic --> Target 1K using default dictionary file\n" - "hf mf fchk --1k --emu --> Target 1K, write to emulator memory\n" - "hf mf fchk --1k --dump --> Target 1K, write to file\n" - "hf mf fchk --1k --mem --> Target 1K, use dictionary from flashmemory"); + "hf mf fchk --1k --emu --> Target 1K, write keys to emulator memory\n" + "hf mf fchk --1k --dump --> Target 1K, write keys to file\n" + "hf mf fchk --1k --mem --> Target 1K, use dictionary from flash memory"); void *argtable[] = { arg_param_begin, From ba76aabdf8d61a627988da8ced0d9c29d5f00708 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 21 Jun 2021 09:15:18 +0200 Subject: [PATCH 040/309] hf mf fchk - output style --- client/src/mifare/mifarehost.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index d068aaac0..9b0c20d36 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -197,16 +197,20 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory) { uint64_t t2 = msclock(); - uint32_t timeout = 0; // send keychunk clearCommandBuffer(); SendCommandOLD(CMD_HF_MIFARE_CHKKEYS_FAST, (sectorsCnt | (firstChunk << 8) | (lastChunk << 12)), ((use_flashmemory << 8) | strategy), size, keyBlock, 6 * size); PacketResponseNG resp; + uint32_t timeout = 0; while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + + PrintAndLogEx((timeout == 0) ? INFO : NORMAL, "." NOLF); + fflush(stdout); + timeout++; - PrintAndLogEx(NORMAL, "." NOLF); + // max timeout for one chunk of 85keys, 60*3sec = 180seconds // s70 with 40*2 keys to check, 80*85 = 6800 auth. // takes about 97s, still some margin before abort @@ -217,6 +221,10 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, } t2 = msclock() - t2; + if (timeout) { + PrintAndLogEx(NORMAL, ""); + } + // time to convert the returned data. uint8_t curr_keys = resp.oldarg[0]; From 4e0fe278e4db3e5a3103650a4863a2a7870379d3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 21 Jun 2021 10:40:39 +0200 Subject: [PATCH 041/309] added two tests for ndef parsing --- tools/pm3_tests.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/pm3_tests.sh b/tools/pm3_tests.sh index b812bdd03..38d66d23f 100755 --- a/tools/pm3_tests.sh +++ b/tools/pm3_tests.sh @@ -367,6 +367,8 @@ while true; do if ! CheckExecute "jooki encode test" "$CLIENTBIN -c 'hf jooki encode -t'" "04 28 F4 DA F0 4A 81 ( ok )"; then break; fi if ! CheckExecute "trace load/list 14a" "$CLIENTBIN -c 'trace load -f traces/hf_14a_mfu.trace; trace list -1 -t 14a;'" "READBLOCK(8)"; then break; fi if ! CheckExecute "trace load/list x" "$CLIENTBIN -c 'trace load -f traces/hf_14a_mfu.trace; trace list -x1 -t 14a;'" "0.0101840425"; then break; fi + if ! CheckExecute "nfc decode test - oob" "$CLIENTBIN -c 'nfc decode -d DA2010016170706C69636174696F6E2F766E642E626C7565746F6F74682E65702E6F6F62301000649201B96DFB0709466C65782032'" "Flex 2"; then break; fi + if ! CheckExecute "nfc decode test - device info" "$CLIENTBIN -c 'nfc decode -d d1025744690004536f6e79010752432d533338300220426c61636b204e46432052656164657220636f6e6e656374656420746f2050430310123e4567e89b12d3a45642665544000004124e464320506f72742d3130302076312e3032'" "NFC Port-100 v1.02"; then break; fi echo -e "\n${C_BLUE}Testing LF:${C_NC}" if ! CheckExecute "lf AWID test" "$CLIENTBIN -c 'data load -f traces/lf_AWID-15-259.pm3;lf search -1'" "AWID ID found"; then break; fi From 9458289c4e0ea7836522679b86812c486558e054 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 21 Jun 2021 16:33:56 +0200 Subject: [PATCH 042/309] added dorma kaba entry --- client/resources/mad.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/client/resources/mad.json b/client/resources/mad.json index aae377af8..8b1c4193c 100644 --- a/client/resources/mad.json +++ b/client/resources/mad.json @@ -5995,6 +5995,7 @@ "application": "(access control and security) VIGIK", "company": "CDV International", "mad": "0x4905", + "service_provider": "CDVI", "system_integrator": "CDVI" }, @@ -11836,6 +11837,13 @@ "service_provider": "HUG-Witschi AG", "system_integrator": "HUG-Witschi AG" }, + { + "application": "Access control - Hotel lodging system", + "company": "DORMA/KABA", + "mad": "0x9051", + "service_provider": "DORMA/KABA", + "system_integrator": "DORMA/KABA" + }, { "application": "FIDELIO CRUISE ship property management system, - materials management system, - meal counting system", "company": "FIDELIO CRUISE SOFTWARE GMBH", @@ -13558,4 +13566,4 @@ "service_provider": "Tech ID", "system_integrator": "Tech ID" } -] \ No newline at end of file +] From b69900725baf6e31e1baacffe4b8827e37f16432 Mon Sep 17 00:00:00 2001 From: Alexandru Turcanu Date: Mon, 21 Jun 2021 15:29:58 -0700 Subject: [PATCH 043/309] Update Mac-OS-X-Homebrew-Installation-Instructions.md --- .../Mac-OS-X-Homebrew-Installation-Instructions.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md b/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md index fc3b51c47..bdd13df49 100644 --- a/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md @@ -30,11 +30,12 @@ For further questions about Mac & Homebrew, contact [\@Chrisfu on Twitter](https 2. Tap this repo: `brew tap RfidResearchGroup/proxmark3` 3. Install Proxmark3: - - (Optional) `export HOMEBREW_PROXMARK3_PLATFORM=xxxxxx` to specify [platform](https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md#platform), default value is `PM3RDV4` if none - `brew install proxmark3` for stable release - `brew install --HEAD proxmark3` for latest non-stable from GitHub (use this if previous command fails) - `brew install --with-blueshark proxmark3` for blueshark support, stable release - `brew install --HEAD --with-blueshark proxmark3` for blueshark support, latest non-stable from GitHub (use this if previous command fails) + - `brew install --with-generic proxmark3`: for generic (non-RDV4) devices ([platform](https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md#platform)), stable release + - `brew install --HEAD --with-generic proxmark3`: for generic (non-RDV4) devices ([platform](https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md#platform)), latest non-stable from GitHub (use this if previous command fails) For more info, go to https://github.com/RfidResearchGroup/homebrew-proxmark3 From 88d9942d3f4a8cde819ee4392077a0c00f076ab3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 22 Jun 2021 07:49:17 +0200 Subject: [PATCH 044/309] fix little endian vs big endian in the macros --- client/src/cmdlfem4x50.c | 4 +++- client/src/cmdlfem4x70.c | 4 ++-- include/common.h | 10 ++++++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index 149ba0b42..2e85786eb 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -464,7 +464,9 @@ int CmdEM4x50Chk(const char *Cmd) { } size_t datalen = 0; - uint8_t data[100000] = {0x0}; + + // 2021 iceman: how many keys shall we reserv space for? The t55xx dictionary has 139 keys. + uint8_t data[2000 * 4] = {0x0}; uint8_t *keys = data; uint32_t key_count = 0; diff --git a/client/src/cmdlfem4x70.c b/client/src/cmdlfem4x70.c index 5c7d0d06a..59584a2bc 100644 --- a/client/src/cmdlfem4x70.c +++ b/client/src/cmdlfem4x70.c @@ -251,7 +251,7 @@ int CmdEM4x70Unlock(const char *Cmd) { return PM3_EINVARG; } - etd.pin = BYTES2UINT32(pin); + etd.pin = BYTES2UINT32_BE(pin); clearCommandBuffer(); SendCommandNG(CMD_LF_EM4X70_UNLOCK, (uint8_t *)&etd, sizeof(etd)); @@ -370,7 +370,7 @@ int CmdEM4x70WritePIN(const char *Cmd) { return PM3_EINVARG; } - etd.pin = BYTES2UINT32(pin); + etd.pin = BYTES2UINT32_BE(pin); clearCommandBuffer(); SendCommandNG(CMD_LF_EM4X70_WRITEPIN, (uint8_t *)&etd, sizeof(etd)); diff --git a/include/common.h b/include/common.h index 50d0aed69..95784acee 100644 --- a/include/common.h +++ b/include/common.h @@ -131,15 +131,21 @@ extern bool tearoff_enabled; #endif #endif -// convert 2 bytes to U16 +// convert 2 bytes to U16 in little endian #ifndef BYTES2UINT16 # define BYTES2UINT16(x) ((x[1] << 8) | (x[0])) #endif -// convert 4 bytes to U32 +// convert 4 bytes to U32 in little endian #ifndef BYTES2UINT32 # define BYTES2UINT32(x) ((x[3] << 24) | (x[2] << 16) | (x[1] << 8) | (x[0])) #endif +// convert 4 bytes to U32 in big endian +#ifndef BYTES2UINT32_BE +# define BYTES2UINT32_BE(x) ((x[0] << 24) | (x[1] << 16) | (x[2] << 8) | (x[3])) +#endif + + #define EVEN 0 #define ODD 1 From 083e557b9ffbd95b82b24d36e28f403b9b4b8487 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 22 Jun 2021 07:53:00 +0200 Subject: [PATCH 045/309] fix little endian vs big endian in the macros... again... but this time correct --- client/src/cmdlfem4x50.c | 28 ++++++++++++++-------------- client/src/cmdlfem4x70.c | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index 2e85786eb..89ee9efb0 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -344,7 +344,7 @@ int CmdEM4x50Login(const char *Cmd) { return PM3_EINVARG; } - uint32_t password = BYTES2UINT32(pwd); + uint32_t password = BYTES2UINT32_BE(pwd); // start clearCommandBuffer(); @@ -395,8 +395,8 @@ int CmdEM4x50Brute(const char *Cmd) { } em4x50_data_t etd; - etd.password1 = BYTES2UINT32(first); - etd.password2 = BYTES2UINT32(last); + etd.password1 = BYTES2UINT32_BE(first); + etd.password2 = BYTES2UINT32_BE(last); // 27 passwords/second (empirical value) const int speed = 27; @@ -624,7 +624,7 @@ int CmdEM4x50Read(const char *Cmd) { PrintAndLogEx(FAILED, "password length must be 4 bytes instead of %d", pwd_len); return PM3_EINVARG; } else { - etd.password1 = BYTES2UINT32(pwd); + etd.password1 = BYTES2UINT32_BE(pwd); etd.pwd_given = true; } } @@ -663,7 +663,7 @@ int CmdEM4x50Info(const char *Cmd) { PrintAndLogEx(FAILED, "password length must be 4 bytes instead of %d", pwd_len); return PM3_EINVARG; } else { - etd.password1 = BYTES2UINT32(pwd); + etd.password1 = BYTES2UINT32_BE(pwd); etd.pwd_given = true; } } @@ -775,7 +775,7 @@ int CmdEM4x50Dump(const char *Cmd) { CLIParserFree(ctx); return PM3_EINVARG; } else { - etd.password1 = BYTES2UINT32(pwd); + etd.password1 = BYTES2UINT32_BE(pwd); etd.pwd_given = true; } } @@ -867,14 +867,14 @@ int CmdEM4x50Write(const char *Cmd) { PrintAndLogEx(FAILED, "password length must be 4 bytes instead of %d", pwd_len); return PM3_EINVARG; } else { - etd.password1 = BYTES2UINT32(pwd); + etd.password1 = BYTES2UINT32_BE(pwd); etd.pwd_given = true; } } etd.addresses = (addr << 8) | addr; etd.addr_given = true; - etd.word = BYTES2UINT32(word); + etd.word = BYTES2UINT32_BE(word); clearCommandBuffer(); SendCommandNG(CMD_LF_EM4X50_WRITE, (uint8_t *)&etd, sizeof(etd)); @@ -936,14 +936,14 @@ int CmdEM4x50WritePwd(const char *Cmd) { PrintAndLogEx(FAILED, "password length must be 4 bytes instead of %d", pwd_len); return PM3_EINVARG; } else { - etd.password1 = BYTES2UINT32(pwd); + etd.password1 = BYTES2UINT32_BE(pwd); } if (npwd_len != 4) { PrintAndLogEx(FAILED, "password length must be 4 bytes instead of %d", npwd_len); return PM3_EINVARG; } else { - etd.password2 = BYTES2UINT32(npwd); + etd.password2 = BYTES2UINT32_BE(npwd); } PacketResponseNG resp; @@ -999,7 +999,7 @@ int CmdEM4x50Wipe(const char *Cmd) { em4x50_data_t etd = {.pwd_given = false, .word = 0x0, .password2 = 0x0}; - etd.password1 = BYTES2UINT32(pwd); + etd.password1 = BYTES2UINT32_BE(pwd); etd.pwd_given = true; // clear password @@ -1095,7 +1095,7 @@ int CmdEM4x50Restore(const char *Cmd) { PrintAndLogEx(FAILED, "password length must be 4 bytes instead of %d", pwd_len); return PM3_EINVARG; } else { - etd.password1 = BYTES2UINT32(pwd); + etd.password1 = BYTES2UINT32_BE(pwd); etd.pwd_given = true; // if password is available protection and control word can be restored startblock = EM4X50_PROTECTION; @@ -1122,7 +1122,7 @@ int CmdEM4x50Restore(const char *Cmd) { PrintAndLogEx(INPLACE, "Restoring block %i", i); etd.addresses = i << 8 | i; - etd.word = reflect32(BYTES2UINT32((data + 4 * i))); + etd.word = reflect32(BYTES2UINT32_BE((data + 4 * i))); PacketResponseNG resp; clearCommandBuffer(); @@ -1172,7 +1172,7 @@ int CmdEM4x50Sim(const char *Cmd) { PrintAndLogEx(FAILED, "password length must be 4 bytes, got %d", pwd_len); return PM3_EINVARG; } else { - password = BYTES2UINT32(pwd); + password = BYTES2UINT32_BE(pwd); } } diff --git a/client/src/cmdlfem4x70.c b/client/src/cmdlfem4x70.c index 59584a2bc..5c7d0d06a 100644 --- a/client/src/cmdlfem4x70.c +++ b/client/src/cmdlfem4x70.c @@ -251,7 +251,7 @@ int CmdEM4x70Unlock(const char *Cmd) { return PM3_EINVARG; } - etd.pin = BYTES2UINT32_BE(pin); + etd.pin = BYTES2UINT32(pin); clearCommandBuffer(); SendCommandNG(CMD_LF_EM4X70_UNLOCK, (uint8_t *)&etd, sizeof(etd)); @@ -370,7 +370,7 @@ int CmdEM4x70WritePIN(const char *Cmd) { return PM3_EINVARG; } - etd.pin = BYTES2UINT32_BE(pin); + etd.pin = BYTES2UINT32(pin); clearCommandBuffer(); SendCommandNG(CMD_LF_EM4X70_WRITEPIN, (uint8_t *)&etd, sizeof(etd)); From 5b8ddfc47ea2c374e8e1f2c5175e1b1dc6fff794 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 22 Jun 2021 07:53:43 +0200 Subject: [PATCH 046/309] little vs big endian, forgot one --- armsrc/em4x50.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/em4x50.c b/armsrc/em4x50.c index 4ed10bd1e..d775f02cc 100644 --- a/armsrc/em4x50.c +++ b/armsrc/em4x50.c @@ -1313,7 +1313,7 @@ static bool em4x50_sim_read_word(uint32_t *word) { } } - *word = BYTES2UINT32(bytes); + *word = BYTES2UINT32_BE(bytes); // check parities if ((parities == parities_calculated) && (stop_bit == 0)) { From 29b40ec93529b457402766df830b3d3af78041a5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 22 Jun 2021 07:58:30 +0200 Subject: [PATCH 047/309] text --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c102b2a7..87429b2ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fix `lf em 4x50/4x70 *` reverted a missunderstanding in byte order macros (@iceman1001) - Added more keys (@equipter) - Changed `hf nfc ndefread` - ndef parser now handles more types (@iceman1001) - Fix `hf desfire` changekey, GetUID, 3DES sesson key tweak. (@mwalker33) From 69e1afbda9dfb40da323f28b2ad6ff7b60ea351d Mon Sep 17 00:00:00 2001 From: mwalker33 <51802811+mwalker33@users.noreply.github.com> Date: Tue, 22 Jun 2021 17:15:04 +1000 Subject: [PATCH 048/309] Update cmdhfmfdes.c Coverity : 320356, 286670, 344402 --- 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 4a59c780a..545d3fe37 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1200,7 +1200,7 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n // PICC master key, keyalgo specific 2bit MSB switch (new_algo) { - case MFDES_ALGO_DES: + // case MFDES_ALGO_DES: // not needed as we patched des to 3des above. (coverty deadcode) case MFDES_ALGO_3DES: break; // 00xx xxx case MFDES_ALGO_3K3DES: @@ -1962,7 +1962,7 @@ static int handler_desfire_readdata(mfdes_data_t *data, MFDES_FILE_TYPE_T type, } // we need the CMD 0xBD to calc the CMAC - uint8_t tmp_data[8]; // Since the APDU is hardcoded to 7 bytes of payload 7+1 = 8 is enough. + uint8_t tmp_data[15]; // Since the APDU is hardcoded to 7 bytes of payload 7+1 = 8 + 4 bytes for CRC/CMAC should be enough. tmp_data[0] = apdu.INS; memcpy(&tmp_data[1], data, 7); @@ -2066,7 +2066,8 @@ static int handler_desfire_writedata(mfdes_data_t *data, MFDES_FILE_TYPE_T type, tmp[5] = datasize & 0xFF; tmp[6] = (datasize >> 8) & 0xFF; tmp[7] = (datasize >> 16) & 0xFF; - memcpy(&tmp[8], (uint8_t *)&data->data[offset], datasize); +// memcpy(&tmp[8], (uint8_t *)&data->data[offset], datasize); // Incorredt data offset, data to write should be in data (no offset) + memcpy(&tmp[8], (uint8_t *)data->data, datasize); size_t plen = datasize + 8; uint8_t *p = mifare_cryto_preprocess_data(tag, tmp, &plen, 8, cs | MAC_COMMAND | CMAC_COMMAND | ENC_COMMAND); From 1655cdd206100a7b520bce6f0a995bc928d5214e Mon Sep 17 00:00:00 2001 From: mwalker33 <51802811+mwalker33@users.noreply.github.com> Date: Tue, 22 Jun 2021 17:22:01 +1000 Subject: [PATCH 049/309] Update cmdhfmfdes.c Remove old code --- client/src/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 545d3fe37..36310e680 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -2066,7 +2066,7 @@ static int handler_desfire_writedata(mfdes_data_t *data, MFDES_FILE_TYPE_T type, tmp[5] = datasize & 0xFF; tmp[6] = (datasize >> 8) & 0xFF; tmp[7] = (datasize >> 16) & 0xFF; -// memcpy(&tmp[8], (uint8_t *)&data->data[offset], datasize); // Incorredt data offset, data to write should be in data (no offset) + memcpy(&tmp[8], (uint8_t *)data->data, datasize); size_t plen = datasize + 8; From 0d2cd089c0ca09fcebf0c888e4fac692ba4f30dc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 22 Jun 2021 10:43:48 +0200 Subject: [PATCH 050/309] coverity fix, textual, style --- client/src/cipurse/cipursecore.c | 270 +++++++++++++++++-------------- client/src/cipurse/cipursecore.h | 30 ++-- 2 files changed, 162 insertions(+), 138 deletions(-) diff --git a/client/src/cipurse/cipursecore.c b/client/src/cipurse/cipursecore.c index 03ab558af..c3024a9b2 100644 --- a/client/src/cipurse/cipursecore.c +++ b/client/src/cipurse/cipursecore.c @@ -18,23 +18,30 @@ #include "cmdhf14a.h" #include "emv/emvcore.h" #include "emv/emvjson.h" +#include "iso7816/apduinfo.h" #include "ui.h" #include "util.h" // context for secure channel CipurseContext cipurseContext; -static int CIPURSEExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool IncludeLe, uint16_t Le, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { +static int CIPURSEExchangeEx(bool activate_field, bool leave_field_on, sAPDU apdu, bool include_le, + uint16_t le, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { uint8_t data[APDU_RES_LEN] = {0}; uint8_t securedata[APDU_RES_LEN] = {0}; sAPDU secapdu; - *ResultLen = 0; - if (sw) *sw = 0; + if (result_len) { + *result_len = 0; + } + + if (sw) { + *sw = 0; + } uint16_t isw = 0; int res = 0; - if (ActivateField) { + if (activate_field) { DropField(); msleep(50); } @@ -45,11 +52,11 @@ static int CIPURSEExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, // COMPUTE APDU int datalen = 0; - uint16_t xle = IncludeLe ? 0x100 : 0x00; - if (xle == 0x100 && Le != 0) - xle = Le; + uint16_t xle = include_le ? 0x100 : 0x00; + if (xle == 0x100 && le != 0) + xle = le; - CipurseCAPDUReqEncode(&cipurseContext, &apdu, &secapdu, securedata, IncludeLe, Le); + CipurseCAPDUReqEncode(&cipurseContext, &apdu, &secapdu, securedata, include_le, le); if (APDUEncodeS(&secapdu, false, xle, data, &datalen)) { PrintAndLogEx(ERR, "APDU encoding error."); @@ -59,34 +66,36 @@ static int CIPURSEExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, if (GetAPDULogging()) PrintAndLogEx(SUCCESS, ">>>> %s", sprint_hex(data, datalen)); - res = ExchangeAPDU14a(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); + res = ExchangeAPDU14a(data, datalen, activate_field, leave_field_on, result, (int)max_result_len, (int *)result_len); if (res) { return res; } if (GetAPDULogging()) - PrintAndLogEx(SUCCESS, "<<<< %s", sprint_hex(Result, *ResultLen)); + PrintAndLogEx(SUCCESS, "<<<< %s", sprint_hex(result, *result_len)); - if (*ResultLen < 2) { + if (*result_len < 2) { return 200; } size_t rlen = 0; - if (*ResultLen == 2) { + if (*result_len == 2) { if (cipurseContext.RequestSecurity == CPSMACed || cipurseContext.RequestSecurity == CPSEncrypted) CipurseCClearContext(&cipurseContext); - isw = Result[0] * 0x0100 + Result[1]; + isw = result[0] * 0x0100 + result[1]; } else { - CipurseCAPDURespDecode(&cipurseContext, Result, *ResultLen, securedata, &rlen, &isw); - memcpy(Result, securedata, rlen); + CipurseCAPDURespDecode(&cipurseContext, result, *result_len, securedata, &rlen, &isw); + memcpy(result, securedata, rlen); } - if (ResultLen != NULL) - *ResultLen = rlen; + if (result_len != NULL) { + *result_len = rlen; + } - if (sw != NULL) + if (sw != NULL) { *sw = isw; + } if (isw != 0x9000) { if (GetAPDULogging()) { @@ -102,69 +111,69 @@ static int CIPURSEExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, return PM3_SUCCESS; } -static int CIPURSEExchange(sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - return CIPURSEExchangeEx(false, true, apdu, true, 0, Result, MaxResultLen, ResultLen, sw); +static int CIPURSEExchange(sAPDU apdu, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { + return CIPURSEExchangeEx(false, true, apdu, true, 0, result, max_result_len, result_len, sw); } -int CIPURSESelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { +int CIPURSESelect(bool activate_field, bool leave_field_on, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { uint8_t data[] = {0x41, 0x44, 0x20, 0x46, 0x31}; CipurseCClearContext(&cipurseContext); - return EMVSelect(CC_CONTACTLESS, ActivateField, LeaveFieldON, data, sizeof(data), Result, MaxResultLen, ResultLen, sw, NULL); + return EMVSelect(CC_CONTACTLESS, activate_field, leave_field_on, data, sizeof(data), result, max_result_len, result_len, sw, NULL); } -int CIPURSEChallenge(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - return CIPURSEExchangeEx(false, true, (sAPDU) {0x00, 0x84, 0x00, 0x00, 0x00, NULL}, true, 0x16, Result, MaxResultLen, ResultLen, sw); +int CIPURSEChallenge(uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { + return CIPURSEExchangeEx(false, true, (sAPDU) {0x00, 0x84, 0x00, 0x00, 0x00, NULL}, true, 0x16, result, max_result_len, result_len, sw); } -int CIPURSEMutalAuthenticate(uint8_t keyIndex, uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - return CIPURSEExchangeEx(false, true, (sAPDU) {0x00, 0x82, 0x00, keyIndex, paramslen, params}, true, 0x10, Result, MaxResultLen, ResultLen, sw); +int CIPURSEMutalAuthenticate(uint8_t keyindex, uint8_t *params, uint8_t paramslen, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { + return CIPURSEExchangeEx(false, true, (sAPDU) {0x00, 0x82, 0x00, keyindex, paramslen, params}, true, 0x10, result, max_result_len, result_len, sw); } -int CIPURSECreateFile(uint8_t *attr, uint16_t attrlen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - return CIPURSEExchangeEx(false, true, (sAPDU) {0x00, 0xe4, 0x00, 0x00, attrlen, attr}, false, 0, Result, MaxResultLen, ResultLen, sw); +int CIPURSECreateFile(uint8_t *attr, uint16_t attrlen, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { + return CIPURSEExchangeEx(false, true, (sAPDU) {0x00, 0xe4, 0x00, 0x00, attrlen, attr}, false, 0, result, max_result_len, result_len, sw); } -int CIPURSEDeleteFile(uint16_t fileID, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - uint8_t fileIdBin[] = {fileID >> 8, fileID & 0xff}; - return CIPURSEExchangeEx(false, true, (sAPDU) {0x00, 0xe4, 0x00, 0x00, 02, fileIdBin}, false, 0, Result, MaxResultLen, ResultLen, sw); +int CIPURSEDeleteFile(uint16_t fileid, uint8_t *Result, size_t max_result_len, size_t *result_len, uint16_t *sw) { + uint8_t fileIdBin[] = {fileid >> 8, fileid & 0xff}; + return CIPURSEExchangeEx(false, true, (sAPDU) {0x00, 0xe4, 0x00, 0x00, 02, fileIdBin}, false, 0, Result, max_result_len, result_len, sw); } -int CIPURSESelectFile(uint16_t fileID, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - uint8_t fileIdBin[] = {fileID >> 8, fileID & 0xff}; - return CIPURSEExchange((sAPDU) {0x00, 0xa4, 0x00, 0x00, 02, fileIdBin}, Result, MaxResultLen, ResultLen, sw); +int CIPURSESelectFile(uint16_t fileid, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { + uint8_t fileIdBin[] = {fileid >> 8, fileid & 0xff}; + return CIPURSEExchange((sAPDU) {0x00, 0xa4, 0x00, 0x00, 02, fileIdBin}, result, max_result_len, result_len, sw); } -int CIPURSESelectMFFile(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - return CIPURSEExchange((sAPDU) {0x00, 0xa4, 0x00, 0x00, 0, NULL}, Result, MaxResultLen, ResultLen, sw); +int CIPURSESelectMFFile(uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { + return CIPURSEExchange((sAPDU) {0x00, 0xa4, 0x00, 0x00, 0, NULL}, result, max_result_len, result_len, sw); } -int CIPURSEReadFileAttributes(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - return CIPURSEExchange((sAPDU) {0x80, 0xce, 0x00, 0x00, 0, NULL}, Result, MaxResultLen, ResultLen, sw); +int CIPURSEReadFileAttributes(uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { + return CIPURSEExchange((sAPDU) {0x80, 0xce, 0x00, 0x00, 0, NULL}, result, max_result_len, result_len, sw); } -int CIPURSEReadBinary(uint16_t offset, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - return CIPURSEExchange((sAPDU) {0x00, 0xb0, (offset >> 8) & 0x7f, offset & 0xff, 0, NULL}, Result, MaxResultLen, ResultLen, sw); +int CIPURSEReadBinary(uint16_t offset, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { + return CIPURSEExchange((sAPDU) {0x00, 0xb0, (offset >> 8) & 0x7f, offset & 0xff, 0, NULL}, result, max_result_len, result_len, sw); } -int CIPURSEUpdateBinary(uint16_t offset, uint8_t *data, uint16_t datalen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - return CIPURSEExchange((sAPDU) {0x00, 0xd6, (offset >> 8) & 0x7f, offset & 0xff, datalen, data}, Result, MaxResultLen, ResultLen, sw); +int CIPURSEUpdateBinary(uint16_t offset, uint8_t *data, uint16_t datalen, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { + return CIPURSEExchange((sAPDU) {0x00, 0xd6, (offset >> 8) & 0x7f, offset & 0xff, datalen, data}, result, max_result_len, result_len, sw); } -bool CIPURSEChannelAuthenticate(uint8_t keyIndex, uint8_t *key, bool verbose) { +bool CIPURSEChannelAuthenticate(uint8_t keyindex, uint8_t *key, bool verbose) { uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; CipurseContext cpc = {0}; - CipurseCSetKey(&cpc, keyIndex, key); + CipurseCSetKey(&cpc, keyindex, key); // get RP, rP int res = CIPURSEChallenge(buf, sizeof(buf), &len, &sw); if (res != 0 || len != 0x16) { - if (verbose) - PrintAndLogEx(ERR, "Cipurse get challenge " _RED_("error") ". Card returns 0x%04x.", sw); - + if (verbose) { + PrintAndLogEx(ERR, "Cipurse get challenge ( " _RED_("fail") " ). Card returns 0x%04x", sw); + } return false; } CipurseCSetRandomFromPICC(&cpc, buf); @@ -174,17 +183,20 @@ bool CIPURSEChannelAuthenticate(uint8_t keyIndex, uint8_t *key, bool verbose) { CipurseCAuthenticateHost(&cpc, authparams); // authenticate - res = CIPURSEMutalAuthenticate(keyIndex, authparams, sizeof(authparams), buf, sizeof(buf), &len, &sw); + res = CIPURSEMutalAuthenticate(keyindex, authparams, sizeof(authparams), buf, sizeof(buf), &len, &sw); if (res != 0 || sw != 0x9000 || len != 16) { if (sw == 0x6988) { - if (verbose) - PrintAndLogEx(ERR, "Cipurse authentication " _RED_("error") ". Wrong key."); + if (verbose) { + PrintAndLogEx(WARNING, "Authentication ( " _RED_("fail") " ). Wrong key"); + } } else if (sw == 0x6A88) { - if (verbose) - PrintAndLogEx(ERR, "Cipurse authentication " _RED_("error") ". Wrong key number."); + if (verbose) { + PrintAndLogEx(WARNING, "Authentication ( " _RED_("fail") " ). Wrong key number"); + } } else { - if (verbose) - PrintAndLogEx(ERR, "Cipurse authentication " _RED_("error") ". Card returns 0x%04x.", sw); + if (verbose) { + PrintAndLogEx(WARNING, "Authentication ( " _RED_("fail") " ). Card returns 0x%04x", sw); + } } CipurseCClearContext(&cipurseContext); @@ -192,15 +204,17 @@ bool CIPURSEChannelAuthenticate(uint8_t keyIndex, uint8_t *key, bool verbose) { } if (CipurseCCheckCT(&cpc, buf)) { - if (verbose) - PrintAndLogEx(INFO, "Authentication " _GREEN_("OK")); + if (verbose) { + PrintAndLogEx(SUCCESS, "Authentication ( " _GREEN_("ok") " )"); + } CipurseCChannelSetSecurityLevels(&cpc, CPSMACed, CPSMACed); memcpy(&cipurseContext, &cpc, sizeof(CipurseContext)); return true; } else { - if (verbose) - PrintAndLogEx(ERR, "Authentication " _RED_("ERROR") " card returned wrong CT"); + if (verbose) { + PrintAndLogEx(WARNING, "Authentication ( " _RED_("fail") " ) card returned wrong CT"); + } CipurseCClearContext(&cipurseContext); return false; @@ -212,21 +226,20 @@ void CIPURSECSetActChannelSecurityLevels(CipurseChannelSecurityLevel req, Cipurs } static void CIPURSEPrintPersoMode(uint8_t data) { - if (data & 0x01) + if ((data & 0x01) == 0x01) PrintAndLogEx(INFO, "Perso: filesystem"); - if (data & 0x02) + if ((data & 0x02) == 0x02) PrintAndLogEx(INFO, "Perso: EMV"); - if (data & 0x04) + if ((data & 0x04) == 0x04) PrintAndLogEx(INFO, "Perso: transaction supported"); - } static void CIPURSEPrintProfileInfo(uint8_t data) { - if (data & 0x01) + if ((data & 0x01) == 0x01) PrintAndLogEx(INFO, "Profile: L"); - if (data & 0x02) + if ((data & 0x02) == 0x02) PrintAndLogEx(INFO, "Profile: S"); - if (data & 0x04) + if ((data & 0x04) == 0x04) PrintAndLogEx(INFO, "Profile: T"); } @@ -239,12 +252,13 @@ static void CIPURSEPrintManufacturerInfo(uint8_t data) { void CIPURSEPrintInfoFile(uint8_t *data, size_t len) { if (len < 2) { - PrintAndLogEx(ERR, "Info file length " _RED_("ERROR")); + PrintAndLogEx(FAILED, "Info file length too short"); return; } - PrintAndLogEx(INFO, "------------ INFO ------------"); - PrintAndLogEx(INFO, "CIPURSE version %d revision %d", data[0], data[1]); + PrintAndLogEx(INFO, "--- " _CYAN_("CIPURSE Information") "---------------------"); + PrintAndLogEx(INFO, "version.... " _YELLOW_("%d"), data[0]); + PrintAndLogEx(INFO, "revision... " _YELLOW_("%d"), data[1]); if (len >= 3) CIPURSEPrintPersoMode(data[2]); @@ -278,101 +292,111 @@ static void CIPURSEPrintFileDescriptor(uint8_t desc) { } static void CIPURSEPrintKeyAttrib(uint8_t *attr) { - PrintAndLogEx(INFO, "-------- KEY ATTRIBUTES --------"); - PrintAndLogEx(INFO, "Additional info: 0x%02x", attr[0]); - PrintAndLogEx(INFO, "Key length: %d", attr[1]); - PrintAndLogEx(INFO, "Algorithm ID: 0x%02x", attr[2]); - PrintAndLogEx(INFO, "Security attr: 0x%02x", attr[3]); - PrintAndLogEx(INFO, "KVV: 0x%02x%02x%02x", attr[4], attr[5], attr[6]); - PrintAndLogEx(INFO, "-------------------------------"); + PrintAndLogEx(INFO, "--- " _CYAN_("Key Attributes") "---------------------"); + PrintAndLogEx(INFO, "Additional info... 0x%02x", attr[0]); + PrintAndLogEx(INFO, "Key length........ %d", attr[1]); + PrintAndLogEx(INFO, "Algorithm ID...... 0x%02x", attr[2]); + PrintAndLogEx(INFO, "Security attr..... 0x%02x", attr[3]); + PrintAndLogEx(INFO, "KVV............... 0x%02x%02x%02x", attr[4], attr[5], attr[6]); + PrintAndLogEx(NORMAL, ""); } -void CIPURSEPrintFileAttr(uint8_t *fileAttr, size_t len) { +void CIPURSEPrintFileAttr(uint8_t *attr, size_t len) { if (len < 7) { - PrintAndLogEx(ERR, "Attributes length " _RED_("ERROR")); + PrintAndLogEx(FAILED, "Attributes length too short"); return; } - PrintAndLogEx(INFO, "--------- FILE ATTRIBUTES ---------"); - if (fileAttr[0] == 0x38) { - PrintAndLogEx(INFO, "Type: MF, ADF"); - if (fileAttr[1] == 0x00) { - PrintAndLogEx(INFO, "Type: MF"); + PrintAndLogEx(INFO, "--- " _CYAN_("File Attributes") "---------------------"); + if (attr[0] == 0x38) { + PrintAndLogEx(INFO, "Type... MF, ADF"); + + if (attr[1] == 0x00) { + PrintAndLogEx(INFO, "Type... MF"); } else { - if ((fileAttr[1] & 0xe0) == 0x00) - PrintAndLogEx(INFO, "Type: Unknown"); - if ((fileAttr[1] & 0xe0) == 0x20) - PrintAndLogEx(INFO, "Type: CIPURSE L"); - if ((fileAttr[1] & 0xe0) == 0x40) - PrintAndLogEx(INFO, "Type: CIPURSE S"); - if ((fileAttr[1] & 0xe0) == 0x60) - PrintAndLogEx(INFO, "Type: CIPURSE T"); - if ((fileAttr[1] & 0x02) == 0x00) + if ((attr[1] & 0xe0) == 0x00) + PrintAndLogEx(INFO, "Type... Unknown"); + + if ((attr[1] & 0xe0) == 0x20) + PrintAndLogEx(INFO, "Type... CIPURSE L"); + + if ((attr[1] & 0xe0) == 0x40) + PrintAndLogEx(INFO, "Type... CIPURSE S"); + + if ((attr[1] & 0xe0) == 0x60) + PrintAndLogEx(INFO, "Type... CIPURSE T"); + + if ((attr[1] & 0x02) == 0x00) PrintAndLogEx(INFO, "Autoselect on PxSE select OFF"); else PrintAndLogEx(INFO, "Autoselect on PxSE select ON"); - if ((fileAttr[1] & 0x01) == 0x00) + + if ((attr[1] & 0x01) == 0x00) PrintAndLogEx(INFO, "PxSE select returns FCPTemplate OFF"); else PrintAndLogEx(INFO, "PxSE select returns FCPTemplate ON"); } - PrintAndLogEx(INFO, "File ID: 0x%02x%02x", fileAttr[2], fileAttr[3]); + PrintAndLogEx(INFO, "File ID................... 0x%02x%02x", attr[2], attr[3]); + PrintAndLogEx(INFO, "Maximum # custom EFs...... %d", attr[4]); + PrintAndLogEx(INFO, "Maximum # EFs with SFID... %d", attr[5]); - PrintAndLogEx(INFO, "Maximum number of custom EFs: %d", fileAttr[4]); - PrintAndLogEx(INFO, "Maximum number of EFs with SFID: %d", fileAttr[5]); - uint8_t keyNum = fileAttr[6]; - PrintAndLogEx(INFO, "Keys assigned: %d", keyNum); + uint8_t keynum = attr[6]; + PrintAndLogEx(INFO, "Keys assigned... %d", keynum); if (len >= 9) { - PrintAndLogEx(INFO, "SMR entries: %02x%02x", fileAttr[7], fileAttr[8]); + PrintAndLogEx(INFO, "SMR entries... %02x%02x", attr[7], attr[8]); } - if (len >= 10 + keyNum + 1) { - PrintAndLogEx(INFO, "ART: %s", sprint_hex(&fileAttr[9], keyNum + 1)); + if (len >= 10 + keynum + 1) { + PrintAndLogEx(INFO, "ART... %s", sprint_hex(&attr[9], keynum + 1)); } - if (len >= 11 + keyNum + 1 + keyNum * 7) { - for (int i = 0; i < keyNum; i++) { - PrintAndLogEx(INFO, "Key %d Attributes: %s", i, sprint_hex(&fileAttr[11 + keyNum + 1 + i * 7], 7)); - CIPURSEPrintKeyAttrib(&fileAttr[11 + keyNum + 1 + i * 7]); + if (len >= 11 + keynum + 1 + keynum * 7) { + for (int i = 0; i < keynum; i++) { + PrintAndLogEx(INFO, "Key %d Attributes... %s", i, sprint_hex(&attr[11 + keynum + 1 + i * 7], 7)); + CIPURSEPrintKeyAttrib(&attr[11 + keynum + 1 + i * 7]); } } // MF - if (fileAttr[1] == 0x00) { - PrintAndLogEx(INFO, "Total memory size: %d", (fileAttr[len - 6] << 16) + (fileAttr[len - 1] << 5) + fileAttr[len - 4]); - PrintAndLogEx(INFO, "Free memory size: %d", (fileAttr[len - 3] << 16) + (fileAttr[len - 2] << 8) + fileAttr[len - 1]); + if (attr[1] == 0x00) { + PrintAndLogEx(INFO, "Total memory size... %d", (attr[len - 6] << 16) + (attr[len - 1] << 5) + attr[len - 4]); + PrintAndLogEx(INFO, "Free memory size.... %d", (attr[len - 3] << 16) + (attr[len - 2] << 8) + attr[len - 1]); } else { - int ptr = 11 + keyNum + 1 + keyNum * 7; - if (len > ptr) - PrintAndLogEx(INFO, "TLV file control: %s", sprint_hex(&fileAttr[ptr], len - ptr)); + int ptr = 11 + keynum + 1 + keynum * 7; + if (len > ptr) { + PrintAndLogEx(INFO, "TLV file control... %s", sprint_hex(&attr[ptr], len - ptr)); + } } } else { - PrintAndLogEx(INFO, "Type: EF"); - CIPURSEPrintFileDescriptor(fileAttr[0]); - if (fileAttr[1] == 0) - PrintAndLogEx(INFO, "SFI: not assigned"); + PrintAndLogEx(INFO, "Type... EF"); + CIPURSEPrintFileDescriptor(attr[0]); + + if (attr[1] == 0) + PrintAndLogEx(INFO, "SFI.... not assigned"); else - PrintAndLogEx(INFO, "SFI: 0x%02x", fileAttr[1]); + PrintAndLogEx(INFO, "SFI.... 0x%02x", attr[1]); - PrintAndLogEx(INFO, "File ID: 0x%02x%02x", fileAttr[2], fileAttr[3]); + PrintAndLogEx(INFO, "File ID... 0x%02x%02x", attr[2], attr[3]); - if (fileAttr[0] == 0x01 || fileAttr[0] == 0x11) - PrintAndLogEx(INFO, "File size: %d", (fileAttr[4] << 8) + fileAttr[5]); + if (attr[0] == 0x01 || attr[0] == 0x11) + PrintAndLogEx(INFO, "File size... %d", (attr[4] << 8) + attr[5]); else - PrintAndLogEx(INFO, "Record num: %d record size: %d", fileAttr[4], fileAttr[5]); + PrintAndLogEx(INFO, "Record num " _YELLOW_("%d") " record size " _YELLOW_("%d"), attr[4], attr[5]); - PrintAndLogEx(INFO, "Keys assigned: %d", fileAttr[6]); + PrintAndLogEx(INFO, "Keys assigned... %d", attr[6]); if (len >= 9) { - PrintAndLogEx(INFO, "SMR entries: %02x%02x", fileAttr[7], fileAttr[8]); + PrintAndLogEx(INFO, "SMR entries... %02x%02x", attr[7], attr[8]); } if (len >= 10) { - PrintAndLogEx(INFO, "ART: %s", sprint_hex(&fileAttr[9], len - 9)); - if (fileAttr[6] + 1 != len - 9) + PrintAndLogEx(INFO, "ART... %s", sprint_hex(&attr[9], len - 9)); + + if (attr[6] + 1 != len - 9) { PrintAndLogEx(WARNING, "ART length is wrong"); + } } } diff --git a/client/src/cipurse/cipursecore.h b/client/src/cipurse/cipursecore.h index 7ace29ea5..e16a931c2 100644 --- a/client/src/cipurse/cipursecore.h +++ b/client/src/cipurse/cipursecore.h @@ -11,10 +11,10 @@ #ifndef __CIPURSECORE_H__ #define __CIPURSECORE_H__ -#include "common.h" - #include -#include "iso7816/apduinfo.h" // sAPDU +#include +#include "common.h" +#include "iso7816/apduinfo.h" // sAPDU #include "cipurse/cipursecrypto.h" @@ -22,23 +22,23 @@ void CIPURSEPrintInfoFile(uint8_t *data, size_t len); -int CIPURSESelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +int CIPURSESelect(bool activate_field, bool leave_field_on, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); -int CIPURSEChallenge(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); -int CIPURSEMutalAuthenticate(uint8_t keyIndex, uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +int CIPURSEChallenge(uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); +int CIPURSEMutalAuthenticate(uint8_t keyIndex, uint8_t *params, uint8_t paramslen, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); -int CIPURSECreateFile(uint8_t *attr, uint16_t attrlen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); -int CIPURSEDeleteFile(uint16_t fileID, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +int CIPURSECreateFile(uint8_t *attr, uint16_t attrlen, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); +int CIPURSEDeleteFile(uint16_t fileid, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); -int CIPURSESelectMFFile(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) ; -int CIPURSESelectFile(uint16_t fileID, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); -int CIPURSEReadFileAttributes(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); -int CIPURSEReadBinary(uint16_t offset, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); -int CIPURSEUpdateBinary(uint16_t offset, uint8_t *data, uint16_t datalen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +int CIPURSESelectMFFile(uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) ; +int CIPURSESelectFile(uint16_t fileid, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); +int CIPURSEReadFileAttributes(uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); +int CIPURSEReadBinary(uint16_t offset, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); +int CIPURSEUpdateBinary(uint16_t offset, uint8_t *data, uint16_t datalen, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); -bool CIPURSEChannelAuthenticate(uint8_t keyIndex, uint8_t *key, bool verbose); +bool CIPURSEChannelAuthenticate(uint8_t keyindex, uint8_t *key, bool verbose); void CIPURSECSetActChannelSecurityLevels(CipurseChannelSecurityLevel req, CipurseChannelSecurityLevel resp); -void CIPURSEPrintFileAttr(uint8_t *fileAttr, size_t len); +void CIPURSEPrintFileAttr(uint8_t *attr, size_t len); #endif /* __CIPURSECORE_H__ */ From d330d22c482c1db1b620f25bb8b928b0c5cd9057 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 22 Jun 2021 10:46:21 +0200 Subject: [PATCH 051/309] text --- client/src/cipurse/cipursecore.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/client/src/cipurse/cipursecore.c b/client/src/cipurse/cipursecore.c index c3024a9b2..3d5cd7e8b 100644 --- a/client/src/cipurse/cipursecore.c +++ b/client/src/cipurse/cipursecore.c @@ -227,27 +227,28 @@ void CIPURSECSetActChannelSecurityLevels(CipurseChannelSecurityLevel req, Cipurs static void CIPURSEPrintPersoMode(uint8_t data) { if ((data & 0x01) == 0x01) - PrintAndLogEx(INFO, "Perso: filesystem"); + PrintAndLogEx(INFO, "Perso... " _YELLOW_("filesystem")); if ((data & 0x02) == 0x02) - PrintAndLogEx(INFO, "Perso: EMV"); + PrintAndLogEx(INFO, "Perso... " _YELLOW_("EMV")); if ((data & 0x04) == 0x04) - PrintAndLogEx(INFO, "Perso: transaction supported"); + PrintAndLogEx(INFO, "Perso... " _YELLOW_("transaction supported")); } +// 2021 iceman: what is the description text of profile L,S,T ? static void CIPURSEPrintProfileInfo(uint8_t data) { if ((data & 0x01) == 0x01) - PrintAndLogEx(INFO, "Profile: L"); + PrintAndLogEx(INFO, "Profile... L"); if ((data & 0x02) == 0x02) - PrintAndLogEx(INFO, "Profile: S"); + PrintAndLogEx(INFO, "Profile... S"); if ((data & 0x04) == 0x04) - PrintAndLogEx(INFO, "Profile: T"); + PrintAndLogEx(INFO, "Profile... T"); } static void CIPURSEPrintManufacturerInfo(uint8_t data) { if (data == 0) - PrintAndLogEx(INFO, "Manufacturer: n/a"); + PrintAndLogEx(INFO, "Manufacturer... n/a"); else - PrintAndLogEx(INFO, "Manufacturer: %s", getTagInfo(data)); // getTagInfo from cmfhf14a.h + PrintAndLogEx(INFO, "Manufacturer... %s", getTagInfo(data)); // getTagInfo from cmfhf14a.h } void CIPURSEPrintInfoFile(uint8_t *data, size_t len) { From 4facebb34d6f474f578fdf566940ad6326100303 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 22 Jun 2021 10:52:08 +0200 Subject: [PATCH 052/309] input sanitizing --- client/src/cipurse/cipursecore.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/client/src/cipurse/cipursecore.c b/client/src/cipurse/cipursecore.c index 3d5cd7e8b..a72011717 100644 --- a/client/src/cipurse/cipursecore.c +++ b/client/src/cipurse/cipursecore.c @@ -27,14 +27,14 @@ CipurseContext cipurseContext; static int CIPURSEExchangeEx(bool activate_field, bool leave_field_on, sAPDU apdu, bool include_le, uint16_t le, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { - uint8_t data[APDU_RES_LEN] = {0}; - uint8_t securedata[APDU_RES_LEN] = {0}; - sAPDU secapdu; - if (result_len) { - *result_len = 0; + if (result_len == NULL) { + PrintAndLogEx(FAILED, "CIPURSEExchangeEx, result_len is NULL"); + return PM3_EINVARG; } + *result_len = 0; + if (sw) { *sw = 0; } @@ -53,26 +53,32 @@ static int CIPURSEExchangeEx(bool activate_field, bool leave_field_on, sAPDU apd // COMPUTE APDU int datalen = 0; uint16_t xle = include_le ? 0x100 : 0x00; - if (xle == 0x100 && le != 0) + if (xle == 0x100 && le != 0) { xle = le; + } + sAPDU secapdu; + uint8_t securedata[APDU_RES_LEN] = {0}; CipurseCAPDUReqEncode(&cipurseContext, &apdu, &secapdu, securedata, include_le, le); + uint8_t data[APDU_RES_LEN] = {0}; if (APDUEncodeS(&secapdu, false, xle, data, &datalen)) { PrintAndLogEx(ERR, "APDU encoding error."); return 201; } - if (GetAPDULogging()) + if (GetAPDULogging()) { PrintAndLogEx(SUCCESS, ">>>> %s", sprint_hex(data, datalen)); + } res = ExchangeAPDU14a(data, datalen, activate_field, leave_field_on, result, (int)max_result_len, (int *)result_len); if (res) { return res; } - if (GetAPDULogging()) + if (GetAPDULogging()) { PrintAndLogEx(SUCCESS, "<<<< %s", sprint_hex(result, *result_len)); + } if (*result_len < 2) { return 200; @@ -80,10 +86,12 @@ static int CIPURSEExchangeEx(bool activate_field, bool leave_field_on, sAPDU apd size_t rlen = 0; if (*result_len == 2) { - if (cipurseContext.RequestSecurity == CPSMACed || cipurseContext.RequestSecurity == CPSEncrypted) + if (cipurseContext.RequestSecurity == CPSMACed || cipurseContext.RequestSecurity == CPSEncrypted) { CipurseCClearContext(&cipurseContext); + } isw = result[0] * 0x0100 + result[1]; + } else { CipurseCAPDURespDecode(&cipurseContext, result, *result_len, securedata, &rlen, &isw); memcpy(result, securedata, rlen); From bcc137af1d10a369c7105bba08151223944d2cc2 Mon Sep 17 00:00:00 2001 From: mwalker33 <51802811+mwalker33@users.noreply.github.com> Date: Tue, 22 Jun 2021 18:55:23 +1000 Subject: [PATCH 053/309] Update desfire_crypto.c Coverty 344484 - ensure AES IV is at least 16 bytes long. --- client/src/mifare/desfire_crypto.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 0699249ff..24a05825f 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -335,6 +335,10 @@ void mifare_kdf_an10922(const desfirekey_t key, const uint8_t *data, size_t len) return; } + // AES uses 16 byte IV + if (kbs < 16) + kbs = 16; + cmac_generate_subkeys(key, MCD_SEND); // reserv atleast 32bytes. From 11362c66f1a48d1f561ce38260990037ba16a4a7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 22 Jun 2021 13:51:31 +0200 Subject: [PATCH 054/309] fix coverity CID 301400|301401 --- client/src/cmdhfwaveshare.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfwaveshare.c b/client/src/cmdhfwaveshare.c index d2a0e7b6e..b4c418329 100644 --- a/client/src/cmdhfwaveshare.c +++ b/client/src/cmdhfwaveshare.c @@ -92,8 +92,10 @@ static model_t models[] = { static int CmdHelp(const char *Cmd); static int picture_bit_depth(const uint8_t *bmp, const size_t bmpsize, const uint8_t model_nr) { - if (bmpsize < sizeof(BMP_HEADER)) + if (bmpsize < sizeof(BMP_HEADER)) { return PM3_ESOFT; + } + BMP_HEADER *pbmpheader = (BMP_HEADER *)bmp; PrintAndLogEx(DEBUG, "colorsused = %d", pbmpheader->colorsused); PrintAndLogEx(DEBUG, "pbmpheader->bpp = %d", pbmpheader->bpp); @@ -403,14 +405,14 @@ static int read_bmp_rgb(uint8_t *bmp, const size_t bmpsize, uint8_t model_nr, ui if ((model_nr == M1in54B) || (model_nr == M2in13B)) { // for BW+Red screens: - uint8_t *mapBlack = calloc(width * height, sizeof(uint8_t)); + uint8_t *mapBlack = calloc((uint32_t)(width * height), sizeof(uint8_t)); if (mapBlack == NULL) { free(chanR); free(chanG); free(chanB); return PM3_EMALLOC; } - uint8_t *mapRed = calloc(width * height, sizeof(uint8_t)); + uint8_t *mapRed = calloc((uint32_t)(width * height), sizeof(uint8_t)); if (mapRed == NULL) { free(chanR); free(chanG); From ab140b926aeee8fbae20cdba8d4ef31d51454416 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 23 Jun 2021 09:52:29 +0200 Subject: [PATCH 055/309] fix tip --- client/src/cmdtrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index 977a7483b..97910109f 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -498,7 +498,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr static int download_trace(void) { if (IfPm3Present() == false) { - PrintAndLogEx(FAILED, "You requested a trace upload in offline mode, consider using parameter '1' for working from Tracebuffer"); + PrintAndLogEx(FAILED, "You requested a trace upload in offline mode, consider using parameter '-1' for working from Tracebuffer"); return PM3_EINVARG; } From 66d35ae0b13500aba850357a0399e47835c5d0a8 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 23 Jun 2021 09:53:27 +0200 Subject: [PATCH 056/309] fix tip --- client/src/cmdtrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index 97910109f..f9f34ce20 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -753,7 +753,7 @@ int CmdTraceList(const char *Cmd) { if (use_buffer == false) { download_trace(); } else if (g_traceLen == 0) { - PrintAndLogEx(FAILED, "You requested a trace list in offline mode but there is no trace, consider using 'trace load' or removing parameter '1'"); + PrintAndLogEx(FAILED, "You requested a trace list in offline mode but there is no trace, consider using 'trace load' or removing parameter '-1'"); return PM3_EINVARG; } From 8afd8fd2b6ec351ff2b309709a15eec0b8c1c548 Mon Sep 17 00:00:00 2001 From: rioux Date: Wed, 23 Jun 2021 10:00:56 +0200 Subject: [PATCH 057/309] Standalone update for lf nexwatch --- CHANGELOG.md | 1 + armsrc/Standalone/Makefile.hal | 7 +- armsrc/Standalone/Makefile.inc | 4 + armsrc/Standalone/lf_nexid.c | 343 +++++++++++++++++++++++++++++++++ 4 files changed, 353 insertions(+), 2 deletions(-) create mode 100644 armsrc/Standalone/lf_nexid.c diff --git a/CHANGELOG.md b/CHANGELOG.md index 87429b2ea..fddd51abe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added Standalone mode for nexwatch ID credentials (@Guilhem7, @MaximeBosca) - Fix `lf em 4x50/4x70 *` reverted a missunderstanding in byte order macros (@iceman1001) - Added more keys (@equipter) - Changed `hf nfc ndefread` - ndef parser now handles more types (@iceman1001) diff --git a/armsrc/Standalone/Makefile.hal b/armsrc/Standalone/Makefile.hal index b413b1ac6..8a51a39e8 100644 --- a/armsrc/Standalone/Makefile.hal +++ b/armsrc/Standalone/Makefile.hal @@ -29,6 +29,9 @@ define KNOWN_STANDALONE_DEFINITIONS | LF_ICEHID | LF HID collector to flashmem | | (RDV4 only) | | +----------------------------------------------------------+ +| LF_NEXID | LF Nexwatch collector to flashmem | +| (RDV4 only) | | ++----------------------------------------------------------+ | LF_PROXBRUTE | HID ProxII bruteforce | | | - Brad Antoniewicz | +----------------------------------------------------------+ @@ -76,10 +79,10 @@ define KNOWN_STANDALONE_DEFINITIONS +----------------------------------------------------------+ endef -STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RWC LF_HIDBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN LF_THAREXDE +STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RWC LF_HIDBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN LF_THAREXDE LF_NEXID STANDALONE_MODES += HF_14ASNIFF HF_AVEFUL HF_BOG HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_TCPRST HF_TMUDFORD HF_YOUNG STANDALONE_MODES_REQ_SMARTCARD := -STANDALONE_MODES_REQ_FLASH := LF_ICEHID LF_THAREXDE HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS +STANDALONE_MODES_REQ_FLASH := LF_ICEHID LF_NEXID LF_THAREXDE HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),) STANDALONE_PLATFORM_DEFS += -DWITH_STANDALONE_$(STANDALONE) ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_SMARTCARD)),) diff --git a/armsrc/Standalone/Makefile.inc b/armsrc/Standalone/Makefile.inc index c4590866f..79c6ab979 100644 --- a/armsrc/Standalone/Makefile.inc +++ b/armsrc/Standalone/Makefile.inc @@ -49,6 +49,10 @@ endif ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS))) SRC_STANDALONE = lf_icehid.c endif +# WITH_STANDALONE_LF_NEXID +ifneq (,$(findstring WITH_STANDALONE_LF_NEXID,$(APP_CFLAGS))) + SRC_STANDALONE = lf_nexid.c +endif # WITH_STANDALONE_LF_EM4100EMUL ifneq (,$(findstring WITH_STANDALONE_LF_EM4100EMUL,$(APP_CFLAGS))) SRC_STANDALONE = lf_em4100emul.c diff --git a/armsrc/Standalone/lf_nexid.c b/armsrc/Standalone/lf_nexid.c new file mode 100644 index 000000000..9ee423b79 --- /dev/null +++ b/armsrc/Standalone/lf_nexid.c @@ -0,0 +1,343 @@ +//----------------------------------------------------------------------------- +// BOSCA Maxime, RIOUX Guilhem 2021 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// main code for Nexwatch ID / Magic number collector. +//----------------------------------------------------------------------------- + +#include +#include "standalone.h" // standalone definitions +#include "proxmark3_arm.h" +#include "appmain.h" +#include "lfops.h" +#include "lfsampling.h" +#include "BigBuf.h" +#include "fpgaloader.h" +#include "util.h" +#include "dbprint.h" +#include "printf.h" +#include "spiffs.h" +#include "ticks.h" +#include "lfdemod.h" +#include "commonutil.h" + +/* + * `lf_nexid` sniffs after LF Nexwatch ID credentials, and stores them in internal + * flash. It requires RDV4 hardware (for flash and battery). + * + * On entering stand-alone mode, this module will start reading/record LF Nexwatch ID credentials. + * Every found / collected credential will be written/appended to the logfile in flash + * as a text string. + * + * LEDs: + * - LED A: reading / record + * - LED B: writing to flash + * - LED C: unmounting/sync'ing flash (normally < 100ms) + * + * To retrieve log file from flash: + * + * 1. mem spiffs dump -s lf_nexcollect.log -d lf_nexcollect.log + * Copies log file from flash to your client. + * + * 2. exit the Proxmark3 client + * + * 3. more lf_nexcollect.log + * + * This module emits debug strings during normal operation -- so try it out in + * the lab connected to PM3 client before taking it into the field. + * + * To delete the log file from flash: + * + * 1. mem spiffs remove -f lf_nexcollect.log + */ + +#define LF_NEXCOLLECT_LOGFILE "lf_nexcollect.log" +typedef enum { + SCRAMBLE, + DESCRAMBLE +} NexWatchScramble_t; + + +static void DownloadLogInstructions(void) { + Dbprintf(""); + Dbprintf("[=] To get the logfile from flash and display it:"); + Dbprintf("[=] " _YELLOW_("1.") " mem spiffs dump -s "LF_NEXCOLLECT_LOGFILE" -d "LF_NEXCOLLECT_LOGFILE); + Dbprintf("[=] " _YELLOW_("2.") " exit proxmark3 client"); + Dbprintf("[=] " _YELLOW_("3.") " cat "LF_NEXCOLLECT_LOGFILE); +} + +bool log_exists; + +// scramble parity (1234) -> (4231) +static uint8_t nexwatch_parity_swap(uint8_t parity) { + uint8_t a = (((parity >> 3) & 1)); + a |= (((parity >> 1) & 1) << 1); + a |= (((parity >> 2) & 1) << 2); + a |= ((parity & 1) << 3); + return a; +} +// parity check +// from 32b hex id, 4b mode, +static uint8_t nexwatch_parity(uint8_t hexid[5]) { + uint8_t p = 0; + for (uint8_t i = 0; i < 5; i++) { + p ^= NIBBLE_HIGH(hexid[i]); + p ^= NIBBLE_LOW(hexid[i]); + } + return nexwatch_parity_swap(p); +} + +/// NETWATCH checksum +/// @param magic = 0xBE Quadrakey, 0x88 Nexkey +/// @param id = descrambled id (printed card number) +/// @param parity = the parity based upon the scrambled raw id. +static uint8_t nexwatch_checksum(uint8_t magic, uint32_t id, uint8_t parity) { + uint8_t a = ((id >> 24) & 0xFF); + a -= ((id >> 16) & 0xFF); + a -= ((id >> 8) & 0xFF); + a -= (id & 0xFF); + a -= magic; + a -= (reflect8(parity) >> 4); + return reflect8(a); +} + +// Scrambled id ( 88 bit cardnumber format) +// ref:: http://www.proxmark.org/forum/viewtopic.php?pid=14662#p14662 +static int nexwatch_scamble(NexWatchScramble_t action, uint32_t *id, uint32_t *scambled) { + + // 255 = Not used/Unknown other values are the bit offset in the ID/FC values + uint8_t hex_2_id [] = { + 31, 27, 23, 19, 15, 11, 7, 3, + 30, 26, 22, 18, 14, 10, 6, 2, + 29, 25, 21, 17, 13, 9, 5, 1, + 28, 24, 20, 16, 12, 8, 4, 0 + }; + + switch (action) { + case DESCRAMBLE: { + *id = 0; + for (uint8_t idx = 0; idx < 32; idx++) { + + if (hex_2_id[idx] == 255) + continue; + + bool bit_state = (*scambled >> hex_2_id[idx]) & 1; + *id |= (bit_state << (31 - idx)); + } + break; + } + case SCRAMBLE: { + *scambled = 0; + for (uint8_t idx = 0; idx < 32; idx++) { + + if (hex_2_id[idx] == 255) + continue; + + bool bit_state = (*id >> idx) & 1; + *scambled |= (bit_state << (31 - hex_2_id[idx])); + } + break; + } + default: + break; + } + return PM3_SUCCESS; +} + + +static void append(uint8_t *entry, size_t entry_len) { + + LED_B_ON(); + if (log_exists == false) { + rdv40_spiffs_write(LF_NEXCOLLECT_LOGFILE, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE); + log_exists = true; + } else { + rdv40_spiffs_append(LF_NEXCOLLECT_LOGFILE, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE); + } + LED_B_OFF(); +} + + +static int detectNexWatch(uint8_t *dest, size_t *size, bool *invert) { + + uint8_t preamble[28] = {0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + // sanity check. + if (*size < 96) return -1; + + size_t startIdx = 0; + + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) { + // if didn't find preamble try again inverting + uint8_t preamble_i[28] = {1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + if (!preambleSearch(dest, preamble_i, sizeof(preamble_i), size, &startIdx)) return -4; + *invert ^= 1; + } + // size tests? + return (int) startIdx; +} + +static uint32_t PSKDemod(uint8_t *dest, size_t *size, int *startIdx) { + //buffer for result + int clk = 0, invert = 0; + //checks if the signal is just noise + if (getSignalProperties()->isnoise) { + return PM3_ESOFT; + } + + //int pskRawDemod_ext(uint8_t *dest, size_t *size, int *clock, int *invert, int *startIdx) + int errCnt = pskRawDemod_ext(dest, size, &clk, &invert, startIdx); + if (errCnt > 100) { + BigBuf_free(); + return PM3_ESOFT; + } + return PM3_SUCCESS; +} + +static int demodNexWatch(void) { + uint8_t *dest = BigBuf_get_addr(); + size_t size = MIN(16385, BigBuf_max_traceLen()); + int startIdx = 0; + + if (PSKDemod(dest, &size, &startIdx) != PM3_SUCCESS) { + return PM3_ESOFT; + } + bool invert = false; + int idx = detectNexWatch(dest, &size, &invert); + if (idx < 0) { + return PM3_ESOFT; + } + + // skip the 4 first bits from the nexwatch preamble identification (we use 4 extra zeros..) + idx += 4; + + // size = size -idx; + dest = dest + idx; + Dbprintf("[+] Id: %d, Size: %d", idx, size); + //setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock)); + + if (invert) { + Dbprintf("Inverted the demodulated data"); + for (size_t i = 0; i < size; i++) + dest[i] ^= 1; + } + + //got a good demod + uint32_t raw1 = bytebits_to_byte(dest, 32); + uint32_t raw2 = bytebits_to_byte(dest + 32, 32); + uint32_t raw3 = bytebits_to_byte(dest + 32 + 32, 32); + + // get rawid + uint32_t rawid = 0; + for (uint8_t k = 0; k < 4; k++) { + for (uint8_t m = 0; m < 8; m++) { + rawid = (rawid << 1) | dest[m + k + (m * 4)]; + } + } + + // descrambled id + uint32_t cn = 0; + uint32_t scambled = bytebits_to_byte(dest + 8 + 32, 32); + nexwatch_scamble(DESCRAMBLE, &cn, &scambled); + + uint8_t mode = bytebits_to_byte(dest + 72, 4); + uint8_t chk = bytebits_to_byte(dest + 80, 8); + + // parity check + // from 32b hex id, 4b mode + uint8_t hex[5] = {0}; + for (uint8_t i = 0; i < 5; i++) { + hex[i] = bytebits_to_byte(dest + 8 + 32 + (i * 8), 8); + } + // mode is only 4 bits. + hex[4] &= 0xf0; + uint8_t calc_parity = nexwatch_parity(hex); + + uint8_t magic = 0; + // output + Dbprintf(" NexWatch raw id : " _YELLOW_("0x%08"PRIx32), rawid); + + uint8_t temp_checksum; + for (; magic < 255; magic++) { + temp_checksum = nexwatch_checksum(magic, cn, calc_parity); + if (temp_checksum == chk) { + Dbprintf(" Magic number : " _GREEN_("0x%X"), magic); + break; + } + } + + Dbprintf(" 88bit id : " _YELLOW_("%"PRIu32) " (" _YELLOW_("0x%08"PRIx32)")", cn, cn); + Dbprintf(" mode : %x", mode); + + Dbprintf(" Raw : " _YELLOW_("%08"PRIX32"%08"PRIX32"%08"PRIX32), raw1, raw2, raw3); + + uint8_t entry[81]; + memset(entry, 0, sizeof(entry)); + + sprintf((char *)entry, "Nexwatch ID: %"PRIu32", Magic bytes: 0x%X, Mode: %x\n", + cn, + magic, + mode); + + append(entry, strlen((char *)entry)); + Dbprintf("%s", entry); + + BigBuf_free(); + return PM3_SUCCESS; +} + +void ModInfo(void) { + DbpString(_YELLOW_(" Nexwatch credentials detection module") " - a.k.a NexID (jrjgjk & Zolorah)"); +} + +void RunMod(void) { + + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + LFSetupFPGAForADC(LF_DIVISOR_125, true); + BigBuf_Clear(); + + StandAloneMode(); + + Dbprintf(_YELLOW_("[=] Standalone mode nexid started")); + + rdv40_spiffs_lazy_mount(); + + log_exists = exists_in_spiffs(LF_NEXCOLLECT_LOGFILE); + + // the main loop for your standalone mode + for (;;) { + WDT_HIT(); + + // exit from IceHID, send a usbcommand. + if (data_available()) break; + + // Was our button held down or pressed? + int button_pressed = BUTTON_HELD(280); + if (button_pressed == BUTTON_HOLD) + break; + + LED_A_ON(); + + uint32_t res; + + + size_t size = MIN(16385, BigBuf_max_traceLen()); + DoAcquisition_config(false, size); + res = demodNexWatch(); + if (res == PM3_SUCCESS) { + LED_A_OFF(); + continue; + } + + } + + LED_C_ON(); + rdv40_spiffs_lazy_unmount(); + LED_C_OFF(); + + LEDsoff(); + DownloadLogInstructions(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); +} From c8e007c9a38d263523c47c4c57d6eb659e037c0a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 23 Jun 2021 11:42:33 +0200 Subject: [PATCH 058/309] text --- armsrc/Standalone/lf_nexid.c | 2 +- doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/armsrc/Standalone/lf_nexid.c b/armsrc/Standalone/lf_nexid.c index 9ee423b79..819811223 100644 --- a/armsrc/Standalone/lf_nexid.c +++ b/armsrc/Standalone/lf_nexid.c @@ -289,7 +289,7 @@ static int demodNexWatch(void) { } void ModInfo(void) { - DbpString(_YELLOW_(" Nexwatch credentials detection module") " - a.k.a NexID (jrjgjk & Zolorah)"); + DbpString(_YELLOW_(" Nexwatch credentials detection mode") " - a.k.a NexID (jrjgjk & Zolorah)"); } void RunMod(void) { diff --git a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md index 4ed8a22a4..f7f955de7 100644 --- a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md +++ b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md @@ -78,15 +78,16 @@ Here are the supported values you can assign to `STANDALONE` in `Makefile.platfo | STANDALONE | DESCRIPTION | |-----------------|----------------------------------------| | | No standalone mode -| LF_SKELETON | standalone mode skeleton - Iceman1001 -| LF_THAREXDE | LF EM4x50 simulator/read standalone mode - tharexde | LF_EM4100EMUL | LF EM4100 simulator standalone mode - temskiy | LF_EM4100RSWB | LF EM4100 read/write/clone/brute mode - Monster1024 | LF_EM4100RWC | LF EM4100 read/write/clone mode - temskiy | LF_HIDBRUTE | HID corporate 1000 bruteforce - Federico dotta & Maurizio Agazzini | LF_ICEHID | LF HID collector to flashmem - Iceman1001 +| LF_NEXID | Nexwatch credentials detection mode - jrjgjk & Zolorah | LF_PROXBRUTE | HID ProxII bruteforce - Brad Antoniewicz | LF_SAMYRUN | HID26 read/clone/sim - Samy Kamkar +| LF_SKELETON | standalone mode skeleton - Iceman1001 +| LF_THAREXDE | LF EM4x50 simulator/read standalone mode - tharexde | HF_14ASNIFF | 14a sniff storing to flashmem - Micolous | HF_AVEFUL | MIFARE Ultralight read/simulation - Ave Ozkal | HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth storing in flashmem - Bogito From ca9fe92fb82facc4c17f81926cb665e2b7dd41d2 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 23 Jun 2021 14:50:02 +0300 Subject: [PATCH 059/309] fix error show in the `hf search` --- client/src/cmdhf.c | 6 ++++-- client/src/cmdhf14a.c | 6 +++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhf.c b/client/src/cmdhf.c index 8a7afeb2a..83b551e33 100644 --- a/client/src/cmdhf.c +++ b/client/src/cmdhf.c @@ -91,11 +91,13 @@ int CmdHFSearch(const char *Cmd) { PROMPT_CLEARLINE; PrintAndLogEx(INPLACE, " Searching for ISO14443-A tag..."); if (IfPm3Iso14443a()) { - if (infoHF14A(false, false, false) > 0) { + int sel_state = infoHF14A(false, false, false); + if (sel_state > 0) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 14443-A tag") " found\n"); res = PM3_SUCCESS; - infoHF14A4Applications(verbose); + if (sel_state == 1) + infoHF14A4Applications(verbose); } } diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index b221869d7..c1e0612f0 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -1807,6 +1807,8 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { memcpy(card.ats, resp.data.asBytes, resp.oldarg[0]); card.ats_len = resp.oldarg[0]; // note: ats_len includes CRC Bytes + if (card.ats_len > 3) + select_status = 1; } if (card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes @@ -2097,6 +2099,8 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if ((card.sak & 0x20) == 0x20) { PrintAndLogEx(INFO, "--> SAK incorrectly claims that card supports RATS <--"); } + if (select_status == 1) + select_status = 2; } int isMagic = 0; @@ -2169,7 +2173,7 @@ int infoHF14A4Applications(bool verbose) { int res = Iso7816Select(CC_CONTACTLESS, ActivateField, true, (uint8_t *)hintAIDList[i].aid, hintAIDList[i].aid_length, result, sizeof(result), &resultlen, &sw); ActivateField = false; if (res) - continue; + break; if (sw == 0x9000 || sw == 0x6283 || sw == 0x6285) { if (!found) { From c23552f255c369cdc81677c57415f8c308258f36 Mon Sep 17 00:00:00 2001 From: rioux Date: Wed, 23 Jun 2021 14:49:59 +0200 Subject: [PATCH 060/309] TODO --- client/src/cmdlfnexwatch.c | 219 ++++++++++++++++++++++++++++++++----- 1 file changed, 189 insertions(+), 30 deletions(-) diff --git a/client/src/cmdlfnexwatch.c b/client/src/cmdlfnexwatch.c index d46c40046..c73f8ef04 100644 --- a/client/src/cmdlfnexwatch.c +++ b/client/src/cmdlfnexwatch.c @@ -24,6 +24,8 @@ #include "cmdlft55xx.h" // clone.. #include "cmdlfem4x05.h" // #include "cliparser.h" +#include + typedef enum { SCRAMBLE, @@ -52,7 +54,7 @@ static uint8_t nexwatch_parity(uint8_t hexid[5]) { } /// NETWATCH checksum -/// @param magic = 0xBE Quadrakey, 0x88 Nexkey +/// @param magic = 0xBE Quadrakey, 0x88 Nexkey, 0x86 EC /// @param id = descrambled id (printed card number) /// @param parity = the parity based upon the scrambled raw id. static uint8_t nexwatch_checksum(uint8_t magic, uint32_t id, uint8_t parity) { @@ -108,6 +110,21 @@ static int nexwatch_scamble(NexWatchScramble_t action, uint32_t *id, uint32_t *s return PM3_SUCCESS; } +static int nexwatch_magic_bruteforce(uint32_t cn, uint8_t calc_parity, uint8_t chk) { + uint8_t magic = 0; + uint8_t temp_checksum; + for (; magic < 255; magic++) { + temp_checksum = nexwatch_checksum(magic, cn, calc_parity); + if (temp_checksum == chk) { + PrintAndLogEx(SUCCESS, " Magic number : " _GREEN_("0x%X"), magic); + return PM3_SUCCESS; + } + } + PrintAndLogEx(DEBUG, "DEBUG: Error - Magic number not found"); + return PM3_ESOFT; +} + + int demodNexWatch(bool verbose) { (void) verbose; // unused so far if (PSKDemod(0, 0, 100, false) != PM3_SUCCESS) { @@ -138,6 +155,7 @@ int demodNexWatch(bool verbose) { idx += 4; setDemodBuff(DemodBuffer, size, idx); + PrintAndLogEx(SUCCESS, "Indice: %x %s", DemodBuffer, DemodBuffer); setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock)); if (invert) { @@ -204,9 +222,13 @@ int demodNexWatch(bool verbose) { if (m_idx < ARRAYLEN(items)) { PrintAndLogEx(SUCCESS, " fingerprint : " _GREEN_("%s"), items[m_idx].desc); + } else { + nexwatch_magic_bruteforce(cn, calc_parity, chk); } - PrintAndLogEx(SUCCESS, " 88bit id : " _YELLOW_("%"PRIu32) " (" _YELLOW_("0x%08"PRIx32)")", cn, cn); PrintAndLogEx(SUCCESS, " mode : %x", mode); + PrintAndLogEx(SUCCESS, " 88bit id : " _YELLOW_("%"PRIu32) " (" _YELLOW_("0x%08"PRIx32)")", cn, cn); + PrintAndLogEx(SUCCESS, " Scambled : " _YELLOW_("%"PRIu32) " (" _YELLOW_("0x%08"PRIx32)")", scambled, scambled); + if (parity == calc_parity) { PrintAndLogEx(DEBUG, " parity : %s (0x%X)", _GREEN_("ok"), parity); @@ -257,12 +279,90 @@ static int CmdNexWatchReader(const char *Cmd) { } do { - lf_read(false, 20000); + lf_read(true, 20000); demodNexWatch(!cm); } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } +//TOCHANGE +static unsigned int bin2int(unsigned char *b, int size) { + unsigned int val = 0; + for (int i = 0; i < size; i++) { + if (b[i] == '1') { + val += pow(2, size - 1 - i); + } + } + return val; +} +static BYTE xor_parity(BYTE *stream_, int bit_number) { + BYTE parity_res = '0'; + for (int i = bit_number - 1; i < 36; i += 4) { + if (stream_[i] == parity_res) { + parity_res = '0'; + } else { + parity_res = '1'; + } + } + return parity_res; +} + +static BYTE *parity(BYTE *stream_) { + BYTE *parity_res = malloc(4 * sizeof(BYTE)); + parity_res[0] = xor_parity(stream_, 4); + parity_res[1] = xor_parity(stream_, 2); + parity_res[2] = xor_parity(stream_, 3); + parity_res[3] = xor_parity(stream_, 1); + return parity_res; +} + +static BYTE *convertUint8toByte(uint8_t number) { + BYTE *res = malloc(8 * sizeof(char)); + uint8_t temp = number; + for (int i = 1; i < 9; i++) { + if (temp % 2) { + res[8 - i] = '1'; + } else { + res[8 - i] = '0'; + } + temp = temp / 2; + } + return res; +} + +static BYTE *convertUint32toByte(uint32_t number) { + BYTE *res = malloc(32 * sizeof(char)); + uint32_t temp = number; + for (int i = 0; i < 32; i++) { + res[i] = '0'; + } + for (int i = 1; i < 33; i++) { + if (temp % 2) { + res[32 - i] = '1'; + } else { + res[32 - i] = '0'; + } + temp = temp / 2; + } + return res; +} + + +static void TOpsk2(BYTE *bits, size_t size) { + BYTE lastbit = '0'; + for (size_t i = 1; i < size; i++) { + //ignore errors + if (bits[i] == 7) continue; + + if (lastbit != bits[i]) { + lastbit = bits[i]; + bits[i] = '1'; + } else { + bits[i] = '0'; + } + } +} +//ENDTOCHANGE static int CmdNexWatchClone(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf nexwatch clone", @@ -285,6 +385,8 @@ static int CmdNexWatchClone(const char *Cmd) { arg_lit0(NULL, "hc", "Honeywell credential"), arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"), arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"), + arg_str0(NULL, "magic", "", "optional - magic hex data. 1 byte"), + arg_lit0(NULL, "psk2", "optional - specify writing a tag in psk2 modulation"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -301,6 +403,10 @@ static int CmdNexWatchClone(const char *Cmd) { bool use_unk = arg_get_lit(ctx, 6); bool q5 = arg_get_lit(ctx, 7); bool em = arg_get_lit(ctx, 8); + bool use_psk2 = arg_get_lit(ctx, 10); + uint8_t magic_arg; + int magic_len = 0; + CLIGetHexWithReturn(ctx, 9, &magic_arg, &magic_len); CLIParserFree(ctx); if (use_nexkey && use_quadrakey) { @@ -316,6 +422,13 @@ static int CmdNexWatchClone(const char *Cmd) { // 56000000 00213C9F 8F150C00 bool use_raw = (raw_len != 0); + bool use_custom_magic = (magic_len != 0); + + if (magic_len > 1) { + PrintAndLogEx(FAILED, "Can't specify a magic number bigger than one byte"); + return PM3_EINVARG; + } + if (use_raw && cn != -1) { PrintAndLogEx(FAILED, "Can't specify both Raw and Card id at the same time"); return PM3_EINVARG; @@ -325,6 +438,7 @@ static int CmdNexWatchClone(const char *Cmd) { uint32_t scrambled; nexwatch_scamble(SCRAMBLE, &cn, &scrambled); num_to_bytes(scrambled, 4, raw + 5); + PrintAndLogEx(SUCCESS, "Scrambled : %u", scrambled); } if (mode != -1) { @@ -336,42 +450,85 @@ static int CmdNexWatchClone(const char *Cmd) { } uint8_t magic = 0xBE; - if (use_nexkey) - magic = 0x88; + if (use_custom_magic) { + magic = magic_arg; + } else { + if (use_nexkey) + magic = 0x88; - if (use_quadrakey) - magic = 0xBE; + if (use_quadrakey) + magic = 0xBE; - if (use_unk) - magic = 0x86; + if (use_unk) + magic = 0x86; - uint32_t blocks[4]; + } + PrintAndLogEx(INFO, "Magic byte selected : 0x%X", magic); - //Nexwatch - compat mode, PSK, data rate 40, 3 data blocks - blocks[0] = T55x7_MODULATION_PSK1 | T55x7_BITRATE_RF_32 | 3 << T55x7_MAXBLOCK_SHIFT; char cardtype[16] = {"T55x7"}; - // Q5 - if (q5) { - blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT; - snprintf(cardtype, sizeof(cardtype), "Q5/T5555"); - } + uint32_t blocks[4]; + if (use_psk2) { + uint32_t scrambled; + nexwatch_scamble(SCRAMBLE, &cn, &scrambled); + num_to_bytes(scrambled, 4, raw + 5); + PrintAndLogEx(SUCCESS, "Scrambled : %u", scrambled); + blocks[0] = 270464; + raw[0] = 0xFA; + BYTE *byteId = convertUint32toByte(scrambled); + BYTE newmode[4] = "0001"; + BYTE idAndMode[36]; + memcpy(idAndMode, byteId, 32 * sizeof(BYTE)); + memcpy(&idAndMode[32], newmode, 4 * sizeof(BYTE)); + BYTE *newparity = parity(idAndMode); + uint8_t par = bin2int(newparity, 4); + uint8_t checksum = nexwatch_checksum(magic, cn, par); + printf("\x1b[1;92m[+]\x1b[0m Checksum : %s --> %u\n", convertUint8toByte(checksum), checksum); + BYTE Psk_card[128]; + BYTE Psk2_card[128]; + memcpy(Psk_card, "00000000000000000000000000000000", 32 * sizeof(BYTE)); + memcpy(&Psk_card[32], "0101011000000000000000000000000000000000", 40 * sizeof(BYTE)); + memcpy(&Psk_card[72], byteId, 32 * sizeof(BYTE)); + memcpy(&Psk_card[104], newmode, 4 * sizeof(BYTE)); + memcpy(&Psk_card[108], newparity, 4 * sizeof(BYTE)); + memcpy(&Psk_card[112], convertUint8toByte(checksum), 8 * sizeof(BYTE)); + memcpy(&Psk_card[120], "00000000", 8 * sizeof(BYTE)); + TOpsk2(Psk_card, 128); + memcpy(&Psk2_card[31], &Psk_card[32], 96 * sizeof(BYTE)); + Psk2_card[127] = '0'; + memcpy(Psk2_card, "00000000000001000010000010000000", 32 * sizeof(BYTE)); + blocks[0] = bin2int(&Psk2_card[0], 32); + blocks[1] = bin2int(&Psk2_card[32], 32); + blocks[2] = bin2int(&Psk2_card[64], 32); + blocks[3] = bin2int(&Psk2_card[96], 32); + } else { + //Nexwatch - compat mode, PSK, data rate 40, 3 data blocks + blocks[0] = T55x7_MODULATION_PSK1 | T55x7_BITRATE_RF_16 | 3 << T55x7_MAXBLOCK_SHIFT; - // EM4305 - if (em) { - blocks[0] = EM4305_NEXWATCH_CONFIG_BLOCK; - snprintf(cardtype, sizeof(cardtype), "EM4305/4469"); - } + // Q5 + if (q5) { + blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT; + snprintf(cardtype, sizeof(cardtype), "Q5/T5555"); + } - if (use_raw == false) { - uint8_t parity = nexwatch_parity(raw + 5) & 0xF; - raw[9] |= parity; - raw[10] |= nexwatch_checksum(magic, cn, parity); - } + // EM4305 + if (em) { + blocks[0] = EM4305_NEXWATCH_CONFIG_BLOCK; + snprintf(cardtype, sizeof(cardtype), "EM4305/4469"); + } - for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) { - blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t)); - } + if (use_raw == false) { + uint8_t parity = nexwatch_parity(raw + 5) & 0xF; + raw[9] |= parity; + raw[10] |= nexwatch_checksum(magic, cn, parity); + } + if (use_unk) + magic = 0x86; + + for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) { + blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t)); + } + } PrintAndLogEx(INFO, "Preparing to clone NexWatch to " _YELLOW_("%s") " raw " _YELLOW_("%s"), cardtype, sprint_hex_inrow(raw, sizeof(raw))); print_blocks(blocks, ARRAYLEN(blocks)); @@ -408,6 +565,8 @@ static int CmdNexWatchSim(const char *Cmd) { arg_lit0(NULL, "nc", "Nexkey credential"), arg_lit0(NULL, "qc", "Quadrakey credential"), arg_lit0(NULL, "hc", "Honeywell credential"), + arg_str0(NULL, "magic", "", "optional - magic hex data. 1 byte"), + arg_lit0(NULL, "psk2", "optional - specify writing a tag in psk2 modulation"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); From 17d6b76931db0c2f06814827dface9a0a1a6458b Mon Sep 17 00:00:00 2001 From: MaximeBosca Date: Wed, 23 Jun 2021 14:55:22 +0200 Subject: [PATCH 061/309] test --- client/src/cmdlfnexwatch.c | 54 +++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/client/src/cmdlfnexwatch.c b/client/src/cmdlfnexwatch.c index c73f8ef04..465b61b9b 100644 --- a/client/src/cmdlfnexwatch.c +++ b/client/src/cmdlfnexwatch.c @@ -295,8 +295,8 @@ static unsigned int bin2int(unsigned char *b, int size) { } return val; } -static BYTE xor_parity(BYTE *stream_, int bit_number) { - BYTE parity_res = '0'; +static uint8_t xor_parity uint8_t *stream_, int bit_number) { + uint8_t parity_res = '0'; for (int i = bit_number - 1; i < 36; i += 4) { if (stream_[i] == parity_res) { parity_res = '0'; @@ -307,8 +307,8 @@ static BYTE xor_parity(BYTE *stream_, int bit_number) { return parity_res; } -static BYTE *parity(BYTE *stream_) { - BYTE *parity_res = malloc(4 * sizeof(BYTE)); +static uint8_t *parity uint8_t *stream_) { + uint8_t *parity_res = malloc(4 * sizeof uint8_t)); parity_res[0] = xor_parity(stream_, 4); parity_res[1] = xor_parity(stream_, 2); parity_res[2] = xor_parity(stream_, 3); @@ -316,8 +316,8 @@ static BYTE *parity(BYTE *stream_) { return parity_res; } -static BYTE *convertUint8toByte(uint8_t number) { - BYTE *res = malloc(8 * sizeof(char)); +static uint8_t *convertUint8toByte(uint8_t number) { + uint8_t *res = malloc(8 * sizeof(char)); uint8_t temp = number; for (int i = 1; i < 9; i++) { if (temp % 2) { @@ -330,8 +330,8 @@ static BYTE *convertUint8toByte(uint8_t number) { return res; } -static BYTE *convertUint32toByte(uint32_t number) { - BYTE *res = malloc(32 * sizeof(char)); +static uint8_t *convertUint32toByte(uint32_t number) { + uint8_t *res = malloc(32 * sizeof(char)); uint32_t temp = number; for (int i = 0; i < 32; i++) { res[i] = '0'; @@ -348,8 +348,8 @@ static BYTE *convertUint32toByte(uint32_t number) { } -static void TOpsk2(BYTE *bits, size_t size) { - BYTE lastbit = '0'; +static void TOpsk2 uint8_t *bits, size_t size) { + uint8_t lastbit = '0'; for (size_t i = 1; i < size; i++) { //ignore errors if (bits[i] == 7) continue; @@ -474,28 +474,28 @@ static int CmdNexWatchClone(const char *Cmd) { PrintAndLogEx(SUCCESS, "Scrambled : %u", scrambled); blocks[0] = 270464; raw[0] = 0xFA; - BYTE *byteId = convertUint32toByte(scrambled); - BYTE newmode[4] = "0001"; - BYTE idAndMode[36]; - memcpy(idAndMode, byteId, 32 * sizeof(BYTE)); - memcpy(&idAndMode[32], newmode, 4 * sizeof(BYTE)); - BYTE *newparity = parity(idAndMode); + uint8_t *byteId = convertUint32toByte(scrambled); + uint8_t newmode[4] = "0001"; + uint8_t idAndMode[36]; + memcpy(idAndMode, byteId, 32 * sizeof uint8_t)); + memcpy(&idAndMode[32], newmode, 4 * sizeof uint8_t)); + uint8_t *newparity = parity(idAndMode); uint8_t par = bin2int(newparity, 4); uint8_t checksum = nexwatch_checksum(magic, cn, par); printf("\x1b[1;92m[+]\x1b[0m Checksum : %s --> %u\n", convertUint8toByte(checksum), checksum); - BYTE Psk_card[128]; - BYTE Psk2_card[128]; - memcpy(Psk_card, "00000000000000000000000000000000", 32 * sizeof(BYTE)); - memcpy(&Psk_card[32], "0101011000000000000000000000000000000000", 40 * sizeof(BYTE)); - memcpy(&Psk_card[72], byteId, 32 * sizeof(BYTE)); - memcpy(&Psk_card[104], newmode, 4 * sizeof(BYTE)); - memcpy(&Psk_card[108], newparity, 4 * sizeof(BYTE)); - memcpy(&Psk_card[112], convertUint8toByte(checksum), 8 * sizeof(BYTE)); - memcpy(&Psk_card[120], "00000000", 8 * sizeof(BYTE)); + uint8_t Psk_card[128]; + uint8_t Psk2_card[128]; + memcpy(Psk_card, "00000000000000000000000000000000", 32 * sizeof uint8_t)); + memcpy(&Psk_card[32], "0101011000000000000000000000000000000000", 40 * sizeof uint8_t)); + memcpy(&Psk_card[72], byteId, 32 * sizeof uint8_t)); + memcpy(&Psk_card[104], newmode, 4 * sizeof uint8_t)); + memcpy(&Psk_card[108], newparity, 4 * sizeof uint8_t)); + memcpy(&Psk_card[112], convertUint8toByte(checksum), 8 * sizeof uint8_t)); + memcpy(&Psk_card[120], "00000000", 8 * sizeof uint8_t)); TOpsk2(Psk_card, 128); - memcpy(&Psk2_card[31], &Psk_card[32], 96 * sizeof(BYTE)); + memcpy(&Psk2_card[31], &Psk_card[32], 96 * sizeof uint8_t)); Psk2_card[127] = '0'; - memcpy(Psk2_card, "00000000000001000010000010000000", 32 * sizeof(BYTE)); + memcpy(Psk2_card, "00000000000001000010000010000000", 32 * sizeof uint8_t)); blocks[0] = bin2int(&Psk2_card[0], 32); blocks[1] = bin2int(&Psk2_card[32], 32); blocks[2] = bin2int(&Psk2_card[64], 32); From 12bd44c3a862f76671f3d97b9de25655217099f4 Mon Sep 17 00:00:00 2001 From: MaximeBosca Date: Wed, 23 Jun 2021 15:04:00 +0200 Subject: [PATCH 062/309] test --- client/src/cmdlfnexwatch.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/client/src/cmdlfnexwatch.c b/client/src/cmdlfnexwatch.c index 465b61b9b..1d0f9cc28 100644 --- a/client/src/cmdlfnexwatch.c +++ b/client/src/cmdlfnexwatch.c @@ -295,7 +295,7 @@ static unsigned int bin2int(unsigned char *b, int size) { } return val; } -static uint8_t xor_parity uint8_t *stream_, int bit_number) { +static uint8_t xor_parity(uint8_t *stream_, int bit_number) { uint8_t parity_res = '0'; for (int i = bit_number - 1; i < 36; i += 4) { if (stream_[i] == parity_res) { @@ -307,8 +307,8 @@ static uint8_t xor_parity uint8_t *stream_, int bit_number) { return parity_res; } -static uint8_t *parity uint8_t *stream_) { - uint8_t *parity_res = malloc(4 * sizeof uint8_t)); +static uint8_t *parity(uint8_t *stream_) { + uint8_t *parity_res = malloc(4 * sizeof(uint8_t)); parity_res[0] = xor_parity(stream_, 4); parity_res[1] = xor_parity(stream_, 2); parity_res[2] = xor_parity(stream_, 3); @@ -348,7 +348,7 @@ static uint8_t *convertUint32toByte(uint32_t number) { } -static void TOpsk2 uint8_t *bits, size_t size) { +static void TOpsk2(uint8_t *bits, size_t size) { uint8_t lastbit = '0'; for (size_t i = 1; i < size; i++) { //ignore errors @@ -477,25 +477,25 @@ static int CmdNexWatchClone(const char *Cmd) { uint8_t *byteId = convertUint32toByte(scrambled); uint8_t newmode[4] = "0001"; uint8_t idAndMode[36]; - memcpy(idAndMode, byteId, 32 * sizeof uint8_t)); - memcpy(&idAndMode[32], newmode, 4 * sizeof uint8_t)); + memcpy(idAndMode, byteId, 32 * sizeof(uint8_t)); + memcpy(&idAndMode[32], newmode, 4 * sizeof(uint8_t)); uint8_t *newparity = parity(idAndMode); uint8_t par = bin2int(newparity, 4); uint8_t checksum = nexwatch_checksum(magic, cn, par); printf("\x1b[1;92m[+]\x1b[0m Checksum : %s --> %u\n", convertUint8toByte(checksum), checksum); uint8_t Psk_card[128]; uint8_t Psk2_card[128]; - memcpy(Psk_card, "00000000000000000000000000000000", 32 * sizeof uint8_t)); - memcpy(&Psk_card[32], "0101011000000000000000000000000000000000", 40 * sizeof uint8_t)); - memcpy(&Psk_card[72], byteId, 32 * sizeof uint8_t)); - memcpy(&Psk_card[104], newmode, 4 * sizeof uint8_t)); - memcpy(&Psk_card[108], newparity, 4 * sizeof uint8_t)); - memcpy(&Psk_card[112], convertUint8toByte(checksum), 8 * sizeof uint8_t)); - memcpy(&Psk_card[120], "00000000", 8 * sizeof uint8_t)); + memcpy(Psk_card, "00000000000000000000000000000000", 32 * sizeof(uint8_t)); + memcpy(&Psk_card[32], "0101011000000000000000000000000000000000", 40 * sizeof(uint8_t)); + memcpy(&Psk_card[72], byteId, 32 * sizeof(uint8_t)); + memcpy(&Psk_card[104], newmode, 4 * sizeof(uint8_t)); + memcpy(&Psk_card[108], newparity, 4 * sizeof(uint8_t)); + memcpy(&Psk_card[112], convertUint8toByte(checksum), 8 * sizeof(uint8_t)); + memcpy(&Psk_card[120], "00000000", 8 * sizeof(uint8_t)); TOpsk2(Psk_card, 128); - memcpy(&Psk2_card[31], &Psk_card[32], 96 * sizeof uint8_t)); + memcpy(&Psk2_card[31], &Psk_card[32], 96 * sizeof(uint8_t)); Psk2_card[127] = '0'; - memcpy(Psk2_card, "00000000000001000010000010000000", 32 * sizeof uint8_t)); + memcpy(Psk2_card, "00000000000001000010000010000000", 32 * sizeof(uint8_t)); blocks[0] = bin2int(&Psk2_card[0], 32); blocks[1] = bin2int(&Psk2_card[32], 32); blocks[2] = bin2int(&Psk2_card[64], 32); From 01632eb9b0ade135173320b649f89cf231e9206c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 23 Jun 2021 16:18:05 +0300 Subject: [PATCH 063/309] make style --- client/src/cmdhf14a.c | 2 +- client/src/cmdhfcipurse.c | 36 +++++++++++------------ client/src/iso7816/iso7816core.c | 50 ++++++++++++++++---------------- client/src/iso7816/iso7816core.h | 6 ++-- 4 files changed, 47 insertions(+), 47 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index c1e0612f0..b471ed9fd 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -1027,7 +1027,7 @@ int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool lea // 3 byte here - 1b framing header, 2b crc16 if (APDUInFramingEnable && - ((g_frame_len && (datainlen > g_frame_len - 3)) || (datainlen > PM3_CMD_DATA_SIZE - 3))) { + ((g_frame_len && (datainlen > g_frame_len - 3)) || (datainlen > PM3_CMD_DATA_SIZE - 3))) { int clen = 0; diff --git a/client/src/cmdhfcipurse.c b/client/src/cmdhfcipurse.c index 427340ca4..882bc797b 100644 --- a/client/src/cmdhfcipurse.c +++ b/client/src/cmdhfcipurse.c @@ -126,7 +126,7 @@ static int CmdHFCipurseAuth(const char *Cmd) { CLIParserFree(ctx); return PM3_EINVARG; } - + uint8_t key[] = {0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73}; if (hdatalen) memcpy(key, hdata, CIPURSE_AES_KEY_LENGTH); @@ -150,10 +150,10 @@ static int CmdHFCipurseAuth(const char *Cmd) { CipurseCGetKVV(key, kvv); if (verbose) { PrintAndLogEx(INFO, "Key id" _YELLOW_("%d") " key " _YELLOW_("%s") " KVV " _YELLOW_("%s") - , keyId - , sprint_hex(key, CIPURSE_AES_KEY_LENGTH) - , sprint_hex_inrow(kvv, CIPURSE_KVV_LENGTH) - ); + , keyId + , sprint_hex(key, CIPURSE_AES_KEY_LENGTH) + , sprint_hex_inrow(kvv, CIPURSE_KVV_LENGTH) + ); } bool bres = CIPURSEChannelAuthenticate(keyId, key, verbose); @@ -413,11 +413,11 @@ static int CmdHFCipurseWriteFile(const char *Cmd) { if (verbose) { PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " offset " _YELLOW_("%zu") " key id " _YELLOW_("%d") " key " _YELLOW_("%s") - , fileId - , offset - , keyId - , sprint_hex(key, CIPURSE_AES_KEY_LENGTH) - ); + , fileId + , offset + , keyId + , sprint_hex(key, CIPURSE_AES_KEY_LENGTH) + ); PrintAndLogEx(INFO, "data[%d]: %s", hdatalen, sprint_hex(hdata, hdatalen)); } @@ -529,10 +529,10 @@ static int CmdHFCipurseReadFileAttr(const char *Cmd) { if (verbose) { PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " key id " _YELLOW_("%d") " key " _YELLOW_("%s") - , fileId - , keyId - , sprint_hex(key, CIPURSE_AES_KEY_LENGTH) - ); + , fileId + , keyId + , sprint_hex(key, CIPURSE_AES_KEY_LENGTH) + ); } if (noAuth == false) { @@ -651,10 +651,10 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) { if (verbose) { PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " key id " _YELLOW_("%d") " key " _YELLOW_("%s") - , fileId - , keyId - , sprint_hex(key, CIPURSE_AES_KEY_LENGTH) - ); + , fileId + , keyId + , sprint_hex(key, CIPURSE_AES_KEY_LENGTH) + ); } bool bres = CIPURSEChannelAuthenticate(keyId, key, verbose); diff --git a/client/src/iso7816/iso7816core.c b/client/src/iso7816/iso7816core.c index 3907d7744..4168036a4 100644 --- a/client/src/iso7816/iso7816core.c +++ b/client/src/iso7816/iso7816core.c @@ -38,10 +38,10 @@ void SetISODEPState(isodep_state_t state) { isodep_state = state; if (APDULogging) { PrintAndLogEx(SUCCESS, "Setting ISODEP -> %s%s%s" - , isodep_state == ISODEP_INACTIVE ? "inactive" : "" - , isodep_state == ISODEP_NFCA ? _GREEN_("NFC-A") : "" - , isodep_state == ISODEP_NFCB ? _GREEN_("NFC-B") : "" - ); + , isodep_state == ISODEP_INACTIVE ? "inactive" : "" + , isodep_state == ISODEP_NFCA ? _GREEN_("NFC-A") : "" + , isodep_state == ISODEP_NFCB ? _GREEN_("NFC-B") : "" + ); } } @@ -79,7 +79,7 @@ int Iso7816ExchangeEx(Iso7816CommandChannel channel, bool activate_field, bool l *result_len = 0; if (sw) { - *sw = 0; + *sw = 0; } if (activate_field) { @@ -177,30 +177,30 @@ int Iso7816ExchangeEx(Iso7816CommandChannel channel, bool activate_field, bool l int Iso7816Exchange(Iso7816CommandChannel channel, bool leave_field_on, sAPDU apdu, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { return Iso7816ExchangeEx(channel - , false - , leave_field_on - , apdu - , false - , 0 - , result - , max_result_len - , result_len - , sw - ); + , false + , leave_field_on + , apdu + , false + , 0 + , result + , max_result_len + , result_len + , sw + ); } int Iso7816Select(Iso7816CommandChannel channel, bool activate_field, bool leave_field_on, uint8_t *aid, size_t aid_len, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { return Iso7816ExchangeEx(channel - , activate_field - , leave_field_on - , (sAPDU) {0x00, 0xa4, 0x04, 0x00, aid_len, aid} - , (channel == CC_CONTACTLESS) - , 0 - , result - , max_result_len - , result_len - , sw - ); + , activate_field + , leave_field_on + , (sAPDU) {0x00, 0xa4, 0x04, 0x00, aid_len, aid} + , (channel == CC_CONTACTLESS) + , 0 + , result + , max_result_len + , result_len + , sw + ); } diff --git a/client/src/iso7816/iso7816core.h b/client/src/iso7816/iso7816core.h index beb5e3e90..003db1256 100644 --- a/client/src/iso7816/iso7816core.h +++ b/client/src/iso7816/iso7816core.h @@ -40,13 +40,13 @@ int Iso7816Connect(Iso7816CommandChannel channel); // exchange int Iso7816Exchange(Iso7816CommandChannel channel, bool leave_field_on, sAPDU apdu, uint8_t *result, size_t max_result_len, - size_t *result_len, uint16_t *sw); + size_t *result_len, uint16_t *sw); int Iso7816ExchangeEx(Iso7816CommandChannel channel, bool activate_field, bool leave_field_on, sAPDU apdu, bool include_le, - uint16_t le, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); + uint16_t le, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); // search application int Iso7816Select(Iso7816CommandChannel channel, bool activate_field, bool leave_field_on, uint8_t *aid, size_t aid_len, - uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); + uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); #endif From 31e4d69853e18ac9f56a02ebf253ed9d82417ea5 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 23 Jun 2021 17:24:27 +0300 Subject: [PATCH 064/309] fix cipurse coverity and textual --- client/src/cmdhfcipurse.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/client/src/cmdhfcipurse.c b/client/src/cmdhfcipurse.c index 882bc797b..9a8db0274 100644 --- a/client/src/cmdhfcipurse.c +++ b/client/src/cmdhfcipurse.c @@ -172,7 +172,9 @@ static int CmdHFCipurseAuth(const char *Cmd) { static int CLIParseKeyAndSecurityLevels(CLIParserContext *ctx, size_t keyid, size_t sreqid, size_t srespid, uint8_t *key, CipurseChannelSecurityLevel *sreq, CipurseChannelSecurityLevel *sresp) { uint8_t hdata[250] = {0}; int hdatalen = sizeof(hdata); - CLIGetHexWithReturn(ctx, keyid, hdata, &hdatalen); + if (CLIParamHexToBuf(arg_get_str(ctx, keyid), hdata, hdatalen, &hdatalen)) + return PM3_ESOFT; + if (hdatalen && hdatalen != 16) { PrintAndLogEx(ERR, _RED_("ERROR:") " key length for AES128 must be 16 bytes only"); return PM3_EINVARG; @@ -186,7 +188,9 @@ static int CLIParseKeyAndSecurityLevels(CLIParserContext *ctx, size_t keyid, siz char cdata[250] = {0}; int cdatalen = sizeof(cdata); cdatalen--; // for trailer 0x00 - CLIGetStrWithReturn(ctx, sreqid, (uint8_t *)cdata, &cdatalen); + if (CLIParamStrToBuf(arg_get_str(ctx, sreqid), (uint8_t *)cdata, cdatalen, &cdatalen)) + return PM3_ESOFT; + if (cdatalen) { str_lower(cdata); if (strcmp(cdata, "plain") == 0) @@ -204,7 +208,9 @@ static int CLIParseKeyAndSecurityLevels(CLIParserContext *ctx, size_t keyid, siz cdatalen = sizeof(cdata); memset(cdata, 0, cdatalen); cdatalen--; // for trailer 0x00 - CLIGetStrWithReturn(ctx, srespid, (uint8_t *)cdata, &cdatalen); + if (CLIParamStrToBuf(arg_get_str(ctx, srespid), (uint8_t *)cdata, cdatalen, &cdatalen)) + return PM3_ESOFT; + if (cdatalen) { str_lower(cdata); if (strcmp(cdata, "plain") == 0) @@ -226,7 +232,7 @@ static int CmdHFCipurseReadFile(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf cipurse read", "Read file by file ID with key ID and key. If no key is supplied, default key of 737373...7373 will be used", - "hf cipurse read -f 2ff7 -> Authenticate with keyID 1, read file with id 2ff7\n" + "hf cipurse read --fid 2ff7 -> Authenticate with keyID 1, read file with id 2ff7\n" "hf cipurse read -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> Authenticate keyID 2 and read file\n"); void *argtable[] = { @@ -235,7 +241,7 @@ static int CmdHFCipurseReadFile(const char *Cmd) { arg_lit0("v", "verbose", "show technical data"), arg_int0("n", NULL, "", "key ID"), arg_str0("k", "key", "", "Auth key"), - arg_str0(NULL, "fid", "", "file ID"), + arg_str0(NULL, "fid", "", "file ID"), arg_int0("o", "offset", "", "offset for reading data from file"), arg_lit0(NULL, "noauth", "read file without authentication"), arg_str0(NULL, "sreq", "", "communication reader-PICC security level"), @@ -338,7 +344,7 @@ static int CmdHFCipurseWriteFile(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf cipurse write", "Write file by file ID with key ID and key. If no key is supplied, default key of 737373...7373 will be used", - "hf cipurse write -f 2ff7 -> Authenticate with keyID 1, write file with id 2ff7\n" + "hf cipurse write --fid 2ff7 -> Authenticate with keyID 1, write file with id 2ff7\n" "hf cipurse write -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> Authenticate keyID 2 and write file\n"); void *argtable[] = { @@ -347,7 +353,7 @@ static int CmdHFCipurseWriteFile(const char *Cmd) { arg_lit0("v", "verbose", "show technical data"), arg_int0("n", NULL, "", "key ID"), arg_str0("k", "key", "", "Auth key"), - arg_str0(NULL, "fid", "", "file ID"), + arg_str0(NULL, "fid", "", "file ID"), arg_int0("o", "offset", "", "offset for reading data from file"), arg_lit0(NULL, "noauth", "read file without authentication"), arg_str0(NULL, "sreq", "", "communication reader-PICC security level"), @@ -463,7 +469,7 @@ static int CmdHFCipurseReadFileAttr(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf cipurse aread", "Read file attributes by file ID with key ID and key. If no key is supplied, default key of 737373...7373 will be used", - "hf cipurse aread -f 2ff7 -> Authenticate with keyID 1, read file attributes with id 2ff7\n" + "hf cipurse aread --fid 2ff7 -> Authenticate with keyID 1, read file attributes with id 2ff7\n" "hf cipurse aread -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> Authenticate keyID 2, read file attributes\n"); void *argtable[] = { @@ -592,7 +598,7 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf cipurse delete", "Read file by file ID with key ID and key. If no key is supplied, default key of 737373...7373 will be used", - "hf cipurse delete -f 2ff7 -> Authenticate with keyID 1, delete file with id 2ff7\n" + "hf cipurse delete --fid 2ff7 -> Authenticate with keyID 1, delete file with id 2ff7\n" "hf cipurse delete -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> Authenticate keyID 2 and delete file\n"); void *argtable[] = { From 6a5a5f7397e11b940f2f249e9bdb26224fcb6e3e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 23 Jun 2021 17:41:14 +0300 Subject: [PATCH 065/309] make style --- client/src/cmdhfcipurse.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfcipurse.c b/client/src/cmdhfcipurse.c index 9a8db0274..e0c79bdca 100644 --- a/client/src/cmdhfcipurse.c +++ b/client/src/cmdhfcipurse.c @@ -174,7 +174,7 @@ static int CLIParseKeyAndSecurityLevels(CLIParserContext *ctx, size_t keyid, siz int hdatalen = sizeof(hdata); if (CLIParamHexToBuf(arg_get_str(ctx, keyid), hdata, hdatalen, &hdatalen)) return PM3_ESOFT; - + if (hdatalen && hdatalen != 16) { PrintAndLogEx(ERR, _RED_("ERROR:") " key length for AES128 must be 16 bytes only"); return PM3_EINVARG; @@ -190,7 +190,7 @@ static int CLIParseKeyAndSecurityLevels(CLIParserContext *ctx, size_t keyid, siz cdatalen--; // for trailer 0x00 if (CLIParamStrToBuf(arg_get_str(ctx, sreqid), (uint8_t *)cdata, cdatalen, &cdatalen)) return PM3_ESOFT; - + if (cdatalen) { str_lower(cdata); if (strcmp(cdata, "plain") == 0) @@ -210,7 +210,7 @@ static int CLIParseKeyAndSecurityLevels(CLIParserContext *ctx, size_t keyid, siz cdatalen--; // for trailer 0x00 if (CLIParamStrToBuf(arg_get_str(ctx, srespid), (uint8_t *)cdata, cdatalen, &cdatalen)) return PM3_ESOFT; - + if (cdatalen) { str_lower(cdata); if (strcmp(cdata, "plain") == 0) From 8aee9468953acd3d4a2d3f65e1910111f50e6945 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 23 Jun 2021 18:20:30 +0300 Subject: [PATCH 066/309] add command `hf cipurse test` --- client/CMakeLists.txt | 1 + client/Makefile | 1 + client/src/cipurse/cipursetest.c | 16 ++++++++++++++++ client/src/cipurse/cipursetest.h | 20 ++++++++++++++++++++ client/src/cmdhfcipurse.c | 8 ++++++++ tools/pm3_tests.sh | 1 + 6 files changed, 47 insertions(+) create mode 100644 client/src/cipurse/cipursetest.c create mode 100644 client/src/cipurse/cipursetest.h diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 5c826790d..a81682337 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -213,6 +213,7 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/iso7816/iso7816core.c ${PM3_ROOT}/client/src/cipurse/cipursecrypto.c ${PM3_ROOT}/client/src/cipurse/cipursecore.c + ${PM3_ROOT}/client/src/cipurse/cipursetest.c ${PM3_ROOT}/client/src/loclass/cipher.c ${PM3_ROOT}/client/src/loclass/cipherutils.c ${PM3_ROOT}/client/src/loclass/elite_crack.c diff --git a/client/Makefile b/client/Makefile index c0f87e0a7..9ed3feb86 100644 --- a/client/Makefile +++ b/client/Makefile @@ -559,6 +559,7 @@ SRCS = aiddesfire.c \ fido/fidocore.c \ cipurse/cipursecore.c \ cipurse/cipursecrypto.c \ + cipurse/cipursetest.c \ fileutils.c \ flash.c \ generator.c \ diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c new file mode 100644 index 000000000..d10213aac --- /dev/null +++ b/client/src/cipurse/cipursetest.c @@ -0,0 +1,16 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2021 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// tests for crypto +//----------------------------------------------------------------------------- + +#include "cipursetest.h" + +bool CIPURSETest(bool verbose) { + + return true; +} diff --git a/client/src/cipurse/cipursetest.h b/client/src/cipurse/cipursetest.h new file mode 100644 index 000000000..561539eae --- /dev/null +++ b/client/src/cipurse/cipursetest.h @@ -0,0 +1,20 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2021 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// tests for crypto +//----------------------------------------------------------------------------- + +#ifndef __CIPURSETEST_H__ +#define __CIPURSETEST_H__ + +#include +#include "common.h" +#include "cipurse/cipursecrypto.h" + +bool CIPURSETest(bool verbose); + +#endif /* __CIPURSETEST_H__ */ \ No newline at end of file diff --git a/client/src/cmdhfcipurse.c b/client/src/cmdhfcipurse.c index e0c79bdca..44c6e3bbe 100644 --- a/client/src/cmdhfcipurse.c +++ b/client/src/cmdhfcipurse.c @@ -25,6 +25,7 @@ #include "cmdhfcipurse.h" #include "cipurse/cipursecore.h" #include "cipurse/cipursecrypto.h" +#include "cipurse/cipursetest.h" #include "ui.h" #include "cmdhf14a.h" #include "cmdtrace.h" @@ -698,6 +699,12 @@ bool CheckCardCipurse(void) { return (res == 0 && sw == 0x9000); } +static int CmdHFCipurseTest(const char *Cmd) { + CIPURSETest(true); + + return PM3_SUCCESS; +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help."}, {"info", CmdHFCipurseInfo, IfPm3Iso14443a, "Get info about CIPURSE tag"}, @@ -706,6 +713,7 @@ static command_t CommandTable[] = { {"write", CmdHFCipurseWriteFile, IfPm3Iso14443a, "Write binary file"}, {"aread", CmdHFCipurseReadFileAttr, IfPm3Iso14443a, "Read file attributes"}, {"delete", CmdHFCipurseDeleteFile, IfPm3Iso14443a, "Delete file"}, + {"test", CmdHFCipurseTest, IfPm3Iso14443a, "Tests"}, {NULL, NULL, 0, NULL} }; diff --git a/tools/pm3_tests.sh b/tools/pm3_tests.sh index 38d66d23f..3ed9ee82b 100755 --- a/tools/pm3_tests.sh +++ b/tools/pm3_tests.sh @@ -491,6 +491,7 @@ while true; do if ! $SLOWTESTS; then if ! CheckExecute "hf iclass loclass test" "$CLIENTBIN -c 'hf iclass loclass --test'" "key diversification (ok)"; then break; fi if ! CheckExecute "emv test" "$CLIENTBIN -c 'emv test'" "Test(s) \[ ok"; then break; fi + if ! CheckExecute "hf cipurse test" "$CLIENTBIN -c 'hf cipurse test'" "Test(s) \[ ok"; then break; fi fi fi echo -e "\n------------------------------------------------------------" From fb9d19e43a889f836493753fbc00c6219b137dc2 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 23 Jun 2021 18:43:57 +0300 Subject: [PATCH 067/309] kvv test added --- client/src/cipurse/cipursetest.c | 41 ++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index d10213aac..12a6e47e9 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -10,7 +10,44 @@ #include "cipursetest.h" -bool CIPURSETest(bool verbose) { +#include +#include // memcpy memset +#include "fileutils.h" + +#include "cipurse/cipursecrypto.h" +#include "cipurse/cipursecore.h" + +uint8_t Key[] = CIPURSE_DEFAULT_KEY; +uint8_t KeyKvv[CIPURSE_KVV_LENGTH] = {0x5f, 0xd6, 0x7b, 0xcb}; + +static bool TestKVV(void) { + uint8_t kvv[CIPURSE_KVV_LENGTH] = {0}; + CipurseCGetKVV(Key, kvv); + //PrintAndLogEx(INFO, "kvv: %s", sprint_hex(kvv, 4)); + bool res = memcmp(KeyKvv, kvv, CIPURSE_KVV_LENGTH) == 0; - return true; + if (res) + PrintAndLogEx(INFO, "kvv: " _GREEN_("passed")); + else + PrintAndLogEx(INFO, "kvv: " _RED_("fail")); + + return res; +} + +bool CIPURSETest(bool verbose) { + bool res = true; + + PrintAndLogEx(INFO, "------ " _CYAN_("CIPURSE TESTS") " ------"); + + res = res && TestKVV(); + + + + PrintAndLogEx(INFO, "---------------------------"); + if (res) + PrintAndLogEx(SUCCESS, "\tTest(s) [ %s ]", _GREEN_("ok")); + else + PrintAndLogEx(FAILED, "\tTest(s) [ %s ]", _RED_("fail")); + + return res; } From bbe0fa1a35aa8baf78b36fa469f356acb807f00a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 23 Jun 2021 19:12:13 +0300 Subject: [PATCH 068/309] fix tests --- client/src/cipurse/cipursetest.c | 4 ++-- client/src/cmdhfcipurse.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index 12a6e47e9..c84147002 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -45,9 +45,9 @@ bool CIPURSETest(bool verbose) { PrintAndLogEx(INFO, "---------------------------"); if (res) - PrintAndLogEx(SUCCESS, "\tTest(s) [ %s ]", _GREEN_("ok")); + PrintAndLogEx(SUCCESS, " Test(s) [ %s ]", _GREEN_("ok")); else - PrintAndLogEx(FAILED, "\tTest(s) [ %s ]", _RED_("fail")); + PrintAndLogEx(FAILED, " Test(s) [ %s ]", _RED_("fail")); return res; } diff --git a/client/src/cmdhfcipurse.c b/client/src/cmdhfcipurse.c index 44c6e3bbe..141b78784 100644 --- a/client/src/cmdhfcipurse.c +++ b/client/src/cmdhfcipurse.c @@ -713,7 +713,7 @@ static command_t CommandTable[] = { {"write", CmdHFCipurseWriteFile, IfPm3Iso14443a, "Write binary file"}, {"aread", CmdHFCipurseReadFileAttr, IfPm3Iso14443a, "Read file attributes"}, {"delete", CmdHFCipurseDeleteFile, IfPm3Iso14443a, "Delete file"}, - {"test", CmdHFCipurseTest, IfPm3Iso14443a, "Tests"}, + {"test", CmdHFCipurseTest, AlwaysAvailable, "Tests"}, {NULL, NULL, 0, NULL} }; From c126f02b95912d76e2bf557db1b999b9beaf81a4 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 23 Jun 2021 19:22:31 +0300 Subject: [PATCH 069/309] added TestISO9797M2 --- client/src/cipurse/cipursetest.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index c84147002..8ef19207f 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -20,6 +20,9 @@ uint8_t Key[] = CIPURSE_DEFAULT_KEY; uint8_t KeyKvv[CIPURSE_KVV_LENGTH] = {0x5f, 0xd6, 0x7b, 0xcb}; +uint8_t TestData[16] = {0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +uint8_t TestDataPadded[16] = {0x11, 0x22, 0x33, 0x44, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + static bool TestKVV(void) { uint8_t kvv[CIPURSE_KVV_LENGTH] = {0}; CipurseCGetKVV(Key, kvv); @@ -34,12 +37,32 @@ static bool TestKVV(void) { return res; } +static bool TestISO9797M2(void) { + uint8_t data[32] = {0}; + + size_t ddatalen = 0; + AddISO9797M2Padding(data, &ddatalen, TestData, 4, 16); + bool res = (ddatalen == 16); + res = res && (memcmp(data, TestDataPadded, ddatalen) == 0); + + res = res && (FindISO9797M2PaddingDataLen(data, ddatalen) == 4); + + if (res) + PrintAndLogEx(INFO, "ISO9797M2: " _GREEN_("passed")); + else + PrintAndLogEx(INFO, "ISO9797M2: " _RED_("fail")); + + return res; +} + + bool CIPURSETest(bool verbose) { bool res = true; PrintAndLogEx(INFO, "------ " _CYAN_("CIPURSE TESTS") " ------"); res = res && TestKVV(); + res = res && TestISO9797M2(); From 50c40e4ce5498984d150b0b560cf30ab37ccc891 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 23 Jun 2021 19:34:22 +0300 Subject: [PATCH 070/309] added smi test --- client/src/cipurse/cipursetest.c | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index 8ef19207f..11eb09853 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -55,6 +55,41 @@ static bool TestISO9797M2(void) { return res; } +static bool TestSMI(void) { + CipurseContext ctx = {0}; + CipurseCClearContext(&ctx); + + bool res = (isCipurseCChannelSecuritySet(&ctx) == false); + + CipurseCChannelSetSecurityLevels(&ctx, CPSPlain, CPSPlain); + res = res && (CipurseCGetSMI(&ctx, false) == 0x00); + res = res && (CipurseCGetSMI(&ctx, true) == 0x01); + + CipurseCChannelSetSecurityLevels(&ctx, CPSPlain, CPSMACed); + res = res && (CipurseCGetSMI(&ctx, false) == 0x04); + res = res && (CipurseCGetSMI(&ctx, true) == 0x05); + + CipurseCChannelSetSecurityLevels(&ctx, CPSMACed, CPSMACed); + res = res && (CipurseCGetSMI(&ctx, false) == 0x44); + res = res && (CipurseCGetSMI(&ctx, true) == 0x45); + + CipurseCChannelSetSecurityLevels(&ctx, CPSMACed, CPSEncrypted); + res = res && (CipurseCGetSMI(&ctx, false) == 0x48); + res = res && (CipurseCGetSMI(&ctx, true) == 0x49); + + CipurseCChannelSetSecurityLevels(&ctx, CPSEncrypted, CPSEncrypted); + res = res && (CipurseCGetSMI(&ctx, false) == 0x88); + res = res && (CipurseCGetSMI(&ctx, true) == 0x89); + + if (res) + PrintAndLogEx(INFO, "SMI: " _GREEN_("passed")); + else + PrintAndLogEx(ERR, "SMI: " _RED_("fail")); + + return res; +} + + bool CIPURSETest(bool verbose) { bool res = true; @@ -63,6 +98,7 @@ bool CIPURSETest(bool verbose) { res = res && TestKVV(); res = res && TestISO9797M2(); + res = res && TestSMI(); From 99979c6609e24416232979eab6be6076ff444487 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 23 Jun 2021 19:58:37 +0300 Subject: [PATCH 071/309] added TestAuth --- client/src/cipurse/cipursetest.c | 49 ++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index 11eb09853..49e3d20a6 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -26,13 +26,13 @@ uint8_t TestDataPadded[16] = {0x11, 0x22, 0x33, 0x44, 0x80, 0x00, 0x00, 0x00, 0x static bool TestKVV(void) { uint8_t kvv[CIPURSE_KVV_LENGTH] = {0}; CipurseCGetKVV(Key, kvv); - //PrintAndLogEx(INFO, "kvv: %s", sprint_hex(kvv, 4)); + bool res = memcmp(KeyKvv, kvv, CIPURSE_KVV_LENGTH) == 0; if (res) PrintAndLogEx(INFO, "kvv: " _GREEN_("passed")); else - PrintAndLogEx(INFO, "kvv: " _RED_("fail")); + PrintAndLogEx(ERR, "kvv: " _RED_("fail")); return res; } @@ -50,7 +50,7 @@ static bool TestISO9797M2(void) { if (res) PrintAndLogEx(INFO, "ISO9797M2: " _GREEN_("passed")); else - PrintAndLogEx(INFO, "ISO9797M2: " _RED_("fail")); + PrintAndLogEx(ERR, "ISO9797M2: " _RED_("fail")); return res; } @@ -89,6 +89,48 @@ static bool TestSMI(void) { return res; } +static bool TestAuth(void) { + CipurseContext ctx = {0}; + CipurseCClearContext(&ctx); + + bool res = (isCipurseCChannelSecuritySet(&ctx) == false); + + CipurseCSetKey(&ctx, 1, Key); + res = res && (memcmp(ctx.key, Key, 16) == 0); + res = res && (ctx.keyId == 1); + + uint8_t random[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22}; + CipurseCSetRandomFromPICC(&ctx, random); + res = res && (memcmp(ctx.RP, random, 16) == 0); + res = res && (memcmp(ctx.rP, &random[16], 6) == 0); + + uint8_t hrandom[] = {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; + CipurseCSetRandomHost(&ctx); + res = res && (memcmp(ctx.RT, hrandom, 16) == 0); + res = res && (memcmp(ctx.rT, &hrandom[16], 6) == 0); + + uint8_t authparams[16 + 16 + 6] = {0}; + CipurseCAuthenticateHost(&ctx, authparams); + uint8_t aparamstest[] = {0x12, 0xAA, 0x79, 0xA9, 0x03, 0xC5, 0xB4, 0x6A, 0x27, 0x1B, 0x13, 0xAE, 0x02, 0x50, 0x1C, 0x99, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; + res = res && (memcmp(authparams, aparamstest, sizeof(authparams)) == 0); + + uint8_t ct[] = {0xBE, 0x10, 0x6B, 0xB9, 0xAD, 0x84, 0xBC, 0xE1, 0x9F, 0xAE, 0x0C, 0x62, 0xCC, 0xC7, 0x0D, 0x41}; + res = res && CipurseCCheckCT(&ctx, ct); + PrintAndLogEx(INFO, "SMI: %s", sprint_hex(ctx.CT, 16)); + + CipurseCChannelSetSecurityLevels(&ctx, CPSMACed, CPSMACed); + res = res && (isCipurseCChannelSecuritySet(&ctx) == true); + + if (res) + PrintAndLogEx(INFO, "Auth: " _GREEN_("passed")); + else + PrintAndLogEx(ERR, "Auth: " _RED_("fail")); + + return res; +} + + bool CIPURSETest(bool verbose) { @@ -99,6 +141,7 @@ bool CIPURSETest(bool verbose) { res = res && TestKVV(); res = res && TestISO9797M2(); res = res && TestSMI(); + res = res && TestAuth(); From 1832a5b37008eee7ca105ec04ff49b72470f7554 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 23 Jun 2021 20:08:18 +0300 Subject: [PATCH 072/309] added TestMIC --- client/src/cipurse/cipursetest.c | 36 +++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index 49e3d20a6..60768142c 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -89,6 +89,30 @@ static bool TestSMI(void) { return res; } +static bool TestMIC(void) { + uint8_t mic[4] = {0}; + + CipurseCGenerateMIC(TestData, 4, mic); + uint8_t valid_mic4[4] = {0xD4, 0x71, 0xA7, 0x73}; + bool res = (memcmp(mic, valid_mic4, 4) == 0); + + res = res && (CipurseCCheckMIC(TestData, 4, mic)); + + CipurseCGenerateMIC(TestData, 6, mic); + uint8_t valid_mic6[4] = {0xAA, 0x90, 0xFC, 0x5A}; + res = res && (memcmp(mic, valid_mic6, 4) == 0); + + res = res && (CipurseCCheckMIC(TestData, 6, mic)); + + if (res) + PrintAndLogEx(INFO, "MIC: " _GREEN_("passed")); + else + PrintAndLogEx(ERR, "MIC: " _RED_("fail")); + + return res; +} + + static bool TestAuth(void) { CipurseContext ctx = {0}; CipurseCClearContext(&ctx); @@ -117,7 +141,6 @@ static bool TestAuth(void) { uint8_t ct[] = {0xBE, 0x10, 0x6B, 0xB9, 0xAD, 0x84, 0xBC, 0xE1, 0x9F, 0xAE, 0x0C, 0x62, 0xCC, 0xC7, 0x0D, 0x41}; res = res && CipurseCCheckCT(&ctx, ct); - PrintAndLogEx(INFO, "SMI: %s", sprint_hex(ctx.CT, 16)); CipurseCChannelSetSecurityLevels(&ctx, CPSMACed, CPSMACed); res = res && (isCipurseCChannelSecuritySet(&ctx) == true); @@ -130,8 +153,18 @@ static bool TestAuth(void) { return res; } +// PrintAndLogEx(INFO, "SMI: %s", sprint_hex(ctx.CT, 16)); +//void CipurseCGenerateMAC(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *mac); +//void CipurseCCalcMACPadded(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *mac); +//bool CipurseCCheckMACPadded(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *mac); +//void CipurseCEncryptDecrypt(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *dstdata, bool isEncrypt); +//void CipurseCChannelEncrypt(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *encdata, size_t *encdatalen); +//void CipurseCChannelDecrypt(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *plaindata, size_t *plaindatalen); + +//void CipurseCAPDUReqEncode(CipurseContext *ctx, sAPDU *srcapdu, sAPDU *dstapdu, uint8_t *dstdatabuf, bool includeLe, uint8_t Le); +//void CipurseCAPDURespDecode(CipurseContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen, uint16_t *sw); bool CIPURSETest(bool verbose) { bool res = true; @@ -141,6 +174,7 @@ bool CIPURSETest(bool verbose) { res = res && TestKVV(); res = res && TestISO9797M2(); res = res && TestSMI(); + res = res && TestMIC(); res = res && TestAuth(); From 7fa4f740f420dd3e01b2ca01a43e12d6bde6b2fb Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 23 Jun 2021 20:22:57 +0300 Subject: [PATCH 073/309] added TestMAC --- client/src/cipurse/cipursetest.c | 54 +++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index 60768142c..356b49161 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -20,6 +20,8 @@ uint8_t Key[] = CIPURSE_DEFAULT_KEY; uint8_t KeyKvv[CIPURSE_KVV_LENGTH] = {0x5f, 0xd6, 0x7b, 0xcb}; +uint8_t TestRandom[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22}; + uint8_t TestData[16] = {0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t TestDataPadded[16] = {0x11, 0x22, 0x33, 0x44, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; @@ -123,10 +125,9 @@ static bool TestAuth(void) { res = res && (memcmp(ctx.key, Key, 16) == 0); res = res && (ctx.keyId == 1); - uint8_t random[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22}; - CipurseCSetRandomFromPICC(&ctx, random); - res = res && (memcmp(ctx.RP, random, 16) == 0); - res = res && (memcmp(ctx.rP, &random[16], 6) == 0); + CipurseCSetRandomFromPICC(&ctx, TestRandom); + res = res && (memcmp(ctx.RP, TestRandom, 16) == 0); + res = res && (memcmp(ctx.rP, &TestRandom[16], 6) == 0); uint8_t hrandom[] = {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; CipurseCSetRandomHost(&ctx); @@ -153,11 +154,45 @@ static bool TestAuth(void) { return res; } -// PrintAndLogEx(INFO, "SMI: %s", sprint_hex(ctx.CT, 16)); +static bool TestMAC(void) { + CipurseContext ctx = {0}; -//void CipurseCGenerateMAC(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *mac); -//void CipurseCCalcMACPadded(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *mac); -//bool CipurseCCheckMACPadded(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *mac); + // authentication + CipurseCClearContext(&ctx); + CipurseCSetKey(&ctx, 1, Key); + CipurseCSetRandomFromPICC(&ctx, TestRandom); + uint8_t authparams[16 + 16 + 6] = {0}; + CipurseCAuthenticateHost(&ctx, authparams); + uint8_t ct[] = {0xBE, 0x10, 0x6B, 0xB9, 0xAD, 0x84, 0xBC, 0xE1, 0x9F, 0xAE, 0x0C, 0x62, 0xCC, 0xC7, 0x0D, 0x41}; + bool res = CipurseCCheckCT(&ctx, ct); + CipurseCChannelSetSecurityLevels(&ctx, CPSMACed, CPSMACed); + res = res && (isCipurseCChannelSecuritySet(&ctx) == true); + + // check MAC + uint8_t mac[8] = {0}; + + CipurseCGenerateMAC(&ctx, TestData, 4, mac); + uint8_t testmac1[8] = {0xAB, 0x5C, 0x86, 0x18, 0x7F, 0x73, 0xEC, 0x4E}; + res = res && (memcmp(mac, testmac1, 8) == 0); + + CipurseCCalcMACPadded(&ctx, TestData, 4, mac); + uint8_t testmac2[8] = {0x9F, 0xE9, 0x54, 0xBF, 0xFC, 0xA0, 0x7D, 0x75}; + res = res && (memcmp(mac, testmac2, 8) == 0); + + CipurseCCalcMACPadded(&ctx, TestData, 4, mac); + uint8_t testmac3[8] = {0x15, 0x6F, 0x08, 0x5C, 0x0F, 0x80, 0xE7, 0x07}; + res = res && (memcmp(mac, testmac3, 8) == 0); + + uint8_t testmac4[8] = {0x0E, 0xF0, 0x70, 0xA6, 0xA1, 0x15, 0x9A, 0xB6}; + res = res && CipurseCCheckMACPadded(&ctx, TestData, 4, testmac4); + + if (res) + PrintAndLogEx(INFO, "channel MAC: " _GREEN_("passed")); + else + PrintAndLogEx(ERR, "channel MAC: " _RED_("fail")); + + return res; +} //void CipurseCEncryptDecrypt(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *dstdata, bool isEncrypt); //void CipurseCChannelEncrypt(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *encdata, size_t *encdatalen); @@ -166,6 +201,8 @@ static bool TestAuth(void) { //void CipurseCAPDUReqEncode(CipurseContext *ctx, sAPDU *srcapdu, sAPDU *dstapdu, uint8_t *dstdatabuf, bool includeLe, uint8_t Le); //void CipurseCAPDURespDecode(CipurseContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen, uint16_t *sw); +// PrintAndLogEx(INFO, "SMI: %s", sprint_hex(ctx.CT, 16)); + bool CIPURSETest(bool verbose) { bool res = true; @@ -176,6 +213,7 @@ bool CIPURSETest(bool verbose) { res = res && TestSMI(); res = res && TestMIC(); res = res && TestAuth(); + res = res && TestMAC(); From 0ca3a5d644f8816b594552f80e0533603093f657 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 23 Jun 2021 20:35:54 +0300 Subject: [PATCH 074/309] added part of TestEncDec --- client/src/cipurse/cipursetest.c | 44 +++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index 356b49161..cf2b86e11 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -194,9 +194,47 @@ static bool TestMAC(void) { return res; } -//void CipurseCEncryptDecrypt(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *dstdata, bool isEncrypt); //void CipurseCChannelEncrypt(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *encdata, size_t *encdatalen); //void CipurseCChannelDecrypt(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *plaindata, size_t *plaindatalen); +static bool TestEncDec(void) { + CipurseContext ctx = {0}; + + // authentication + CipurseCClearContext(&ctx); + CipurseCSetKey(&ctx, 1, Key); + CipurseCSetRandomFromPICC(&ctx, TestRandom); + uint8_t authparams[16 + 16 + 6] = {0}; + CipurseCAuthenticateHost(&ctx, authparams); + uint8_t ct[] = {0xBE, 0x10, 0x6B, 0xB9, 0xAD, 0x84, 0xBC, 0xE1, 0x9F, 0xAE, 0x0C, 0x62, 0xCC, 0xC7, 0x0D, 0x41}; + bool res = CipurseCCheckCT(&ctx, ct); + CipurseCChannelSetSecurityLevels(&ctx, CPSMACed, CPSMACed); + res = res && (isCipurseCChannelSecuritySet(&ctx) == true); + + // check Encode-Decode + uint8_t dstdata[32] = {0}; + + CipurseCEncryptDecrypt(&ctx, TestData, 16, dstdata, true); + uint8_t tested1[16] = {0x5F, 0x01, 0x18, 0x79, 0xE0, 0x57, 0xA7, 0xE5, 0x34, 0x39, 0x6E, 0x32, 0x62, 0xF2, 0x71, 0x27}; + res = res && (memcmp(dstdata, tested1, 16) == 0); + //PrintAndLogEx(INFO, "SMI: %s", sprint_hex(dstdata, 16)); + + uint8_t tested2[16] = {0xA6, 0x22, 0xB5, 0xCF, 0xE8, 0x6E, 0x67, 0xF4, 0xAA, 0x88, 0xB1, 0x19, 0x87, 0xCF, 0xC9, 0xD2}; + CipurseCEncryptDecrypt(&ctx, tested2, 16, dstdata, false); + res = res && (memcmp(dstdata, TestData, 16) == 0); + + + + + + + + if (res) + PrintAndLogEx(INFO, "channel EncDec: " _GREEN_("passed")); + else + PrintAndLogEx(ERR, "channel EncDec: " _RED_("fail")); + + return res; +} //void CipurseCAPDUReqEncode(CipurseContext *ctx, sAPDU *srcapdu, sAPDU *dstapdu, uint8_t *dstdatabuf, bool includeLe, uint8_t Le); //void CipurseCAPDURespDecode(CipurseContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen, uint16_t *sw); @@ -214,8 +252,8 @@ bool CIPURSETest(bool verbose) { res = res && TestMIC(); res = res && TestAuth(); res = res && TestMAC(); - - + res = res && TestEncDec(); + res = res && true; PrintAndLogEx(INFO, "---------------------------"); if (res) From 8e822e967760db110d2527536ceea07106555613 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 23 Jun 2021 20:45:14 +0300 Subject: [PATCH 075/309] added TestEncDec --- client/src/cipurse/cipursetest.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index cf2b86e11..f9d5c83e9 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -194,8 +194,6 @@ static bool TestMAC(void) { return res; } -//void CipurseCChannelEncrypt(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *encdata, size_t *encdatalen); -//void CipurseCChannelDecrypt(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *plaindata, size_t *plaindatalen); static bool TestEncDec(void) { CipurseContext ctx = {0}; @@ -212,22 +210,28 @@ static bool TestEncDec(void) { // check Encode-Decode uint8_t dstdata[32] = {0}; + size_t dstdatalen = 0; CipurseCEncryptDecrypt(&ctx, TestData, 16, dstdata, true); uint8_t tested1[16] = {0x5F, 0x01, 0x18, 0x79, 0xE0, 0x57, 0xA7, 0xE5, 0x34, 0x39, 0x6E, 0x32, 0x62, 0xF2, 0x71, 0x27}; res = res && (memcmp(dstdata, tested1, 16) == 0); - //PrintAndLogEx(INFO, "SMI: %s", sprint_hex(dstdata, 16)); uint8_t tested2[16] = {0xA6, 0x22, 0xB5, 0xCF, 0xE8, 0x6E, 0x67, 0xF4, 0xAA, 0x88, 0xB1, 0x19, 0x87, 0xCF, 0xC9, 0xD2}; CipurseCEncryptDecrypt(&ctx, tested2, 16, dstdata, false); res = res && (memcmp(dstdata, TestData, 16) == 0); + CipurseCChannelEncrypt(&ctx, TestData, 16, dstdata, &dstdatalen); + uint8_t tested3[32] = {0x1E, 0x0C, 0xD1, 0xF5, 0x8E, 0x0B, 0xAE, 0xF0, 0x06, 0xC6, 0xED, 0x73, 0x3F, 0x8A, 0x87, 0xCF, + 0x36, 0xCC, 0xF2, 0xF4, 0x7D, 0x33, 0x50, 0xF1, 0x8E, 0xFF, 0xD1, 0x7D, 0x42, 0x88, 0xD5, 0xEE}; + res = res && (dstdatalen == 32); + res = res && (memcmp(dstdata, tested3, 32) == 0); + uint8_t tested4[32] = {0xC0, 0x42, 0xDB, 0xD9, 0x53, 0xFF, 0x01, 0xE5, 0xCC, 0x49, 0x8C, 0x9C, 0xDA, 0x60, 0x73, 0xA7, + 0xE1, 0xEB, 0x14, 0x69, 0xF6, 0x39, 0xF3, 0xE1, 0x07, 0x03, 0x32, 0xF4, 0x27, 0xF9, 0x48, 0x3D}; + CipurseCChannelDecrypt(&ctx, tested4, 32, dstdata, &dstdatalen); + res = res && (dstdatalen == 16); + res = res && (memcmp(dstdata, TestData, 16) == 0); - - - - if (res) PrintAndLogEx(INFO, "channel EncDec: " _GREEN_("passed")); else From f26b4178f32b83a0286f7eddd580bf66a7c5622f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 23 Jun 2021 20:56:22 +0300 Subject: [PATCH 076/309] part of TestAPDU --- client/src/cipurse/cipursetest.c | 48 ++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index f9d5c83e9..f7e1dc373 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -242,8 +242,52 @@ static bool TestEncDec(void) { //void CipurseCAPDUReqEncode(CipurseContext *ctx, sAPDU *srcapdu, sAPDU *dstapdu, uint8_t *dstdatabuf, bool includeLe, uint8_t Le); //void CipurseCAPDURespDecode(CipurseContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen, uint16_t *sw); +static bool TestAPDU(void) { + CipurseContext ctx = {0}; -// PrintAndLogEx(INFO, "SMI: %s", sprint_hex(ctx.CT, 16)); + // authentication + CipurseCClearContext(&ctx); + CipurseCSetKey(&ctx, 1, Key); + CipurseCSetRandomFromPICC(&ctx, TestRandom); + uint8_t authparams[16 + 16 + 6] = {0}; + CipurseCAuthenticateHost(&ctx, authparams); + uint8_t ct[] = {0xBE, 0x10, 0x6B, 0xB9, 0xAD, 0x84, 0xBC, 0xE1, 0x9F, 0xAE, 0x0C, 0x62, 0xCC, 0xC7, 0x0D, 0x41}; + bool res = CipurseCCheckCT(&ctx, ct); + CipurseCChannelSetSecurityLevels(&ctx, CPSMACed, CPSMACed); + res = res && (isCipurseCChannelSecuritySet(&ctx) == true); + + // check APDU formatting + sAPDU srcAPDU = {0}; + sAPDU dstAPDU = {0}; + uint8_t dstdata[32] = {0}; + //size_t dstdatalen = 0; + + srcAPDU.CLA = 0x00; + srcAPDU.INS = 0x55; + srcAPDU.P1 = 0x11; + srcAPDU.P2 = 0x22; + srcAPDU.data = TestData; + srcAPDU.Lc = 5; + + CipurseCAPDUReqEncode(&ctx, &srcAPDU, &dstAPDU, dstdata, true, 0x88); + uint8_t test1[] = {0x45, 0x11, 0x22, 0x33, 0x44, 0x00, 0x88, 0x79, 0x2B, 0xB7, 0xDD, 0xD1, 0x69, 0xA6, 0x66}; + res = res && (dstAPDU.Lc == sizeof(test1)); + res = res && (memcmp(dstdata, test1, sizeof(test1)) == 0); + PrintAndLogEx(INFO, "dstAPDU.data: %s", sprint_hex(dstAPDU.data, dstAPDU.Lc)); + + + + + + + + if (res) + PrintAndLogEx(INFO, "apdu: " _GREEN_("passed")); + else + PrintAndLogEx(ERR, "apdu: " _RED_("fail")); + + return res; +} bool CIPURSETest(bool verbose) { bool res = true; @@ -257,7 +301,7 @@ bool CIPURSETest(bool verbose) { res = res && TestAuth(); res = res && TestMAC(); res = res && TestEncDec(); - res = res && true; + res = res && TestAPDU(); PrintAndLogEx(INFO, "---------------------------"); if (res) From f3bdd52cf190da9bab2db121948bc6ce3c7a1419 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 23 Jun 2021 20:59:37 +0300 Subject: [PATCH 077/309] check apdu copy --- client/src/cipurse/cipursetest.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index f7e1dc373..496a39ec1 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -271,6 +271,10 @@ static bool TestAPDU(void) { CipurseCAPDUReqEncode(&ctx, &srcAPDU, &dstAPDU, dstdata, true, 0x88); uint8_t test1[] = {0x45, 0x11, 0x22, 0x33, 0x44, 0x00, 0x88, 0x79, 0x2B, 0xB7, 0xDD, 0xD1, 0x69, 0xA6, 0x66}; + res = res && ((srcAPDU.CLA | 0x04) == dstAPDU.CLA); + res = res && (srcAPDU.INS == dstAPDU.INS); + res = res && (srcAPDU.P1 == dstAPDU.P1); + res = res && (srcAPDU.P2 == dstAPDU.P2); res = res && (dstAPDU.Lc == sizeof(test1)); res = res && (memcmp(dstdata, test1, sizeof(test1)) == 0); PrintAndLogEx(INFO, "dstAPDU.data: %s", sprint_hex(dstAPDU.data, dstAPDU.Lc)); From e0d1656ea14927f008809125ee6845c45d4b9790 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 23 Jun 2021 21:06:46 +0300 Subject: [PATCH 078/309] add plain apdu encode --- client/src/cipurse/cipursetest.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index 496a39ec1..525d67599 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -262,6 +262,7 @@ static bool TestAPDU(void) { uint8_t dstdata[32] = {0}; //size_t dstdatalen = 0; + // MACED APDU srcAPDU.CLA = 0x00; srcAPDU.INS = 0x55; srcAPDU.P1 = 0x11; @@ -281,8 +282,19 @@ static bool TestAPDU(void) { + // Plain APDU + CipurseCChannelSetSecurityLevels(&ctx, CPSPlain, CPSPlain); + CipurseCAPDUReqEncode(&ctx, &srcAPDU, &dstAPDU, dstdata, true, 0x55); + uint8_t test2[] = {0x01, 0x11, 0x22, 0x33, 0x44, 0x00, 0x55}; + res = res && ((srcAPDU.CLA | 0x04) == dstAPDU.CLA); + res = res && (srcAPDU.INS == dstAPDU.INS); + res = res && (srcAPDU.P1 == dstAPDU.P1); + res = res && (srcAPDU.P2 == dstAPDU.P2); + res = res && (dstAPDU.Lc == sizeof(test2)); + res = res && (memcmp(dstdata, test2, sizeof(test2)) == 0); - + // Encrypted APDU + //CipurseCChannelSetSecurityLevels(&ctx, CPSEncrypted, CPSEncrypted); if (res) From 85986e5994919cdb794b11aaac5b15e16a950cf0 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 24 Jun 2021 10:18:01 +0300 Subject: [PATCH 079/309] part ot test encrypt --- client/src/cipurse/cipursetest.c | 33 +++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index 525d67599..7eb13bbcc 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -260,7 +260,7 @@ static bool TestAPDU(void) { sAPDU srcAPDU = {0}; sAPDU dstAPDU = {0}; uint8_t dstdata[32] = {0}; - //size_t dstdatalen = 0; + size_t dstdatalen = 0; // MACED APDU srcAPDU.CLA = 0x00; @@ -278,23 +278,42 @@ static bool TestAPDU(void) { res = res && (srcAPDU.P2 == dstAPDU.P2); res = res && (dstAPDU.Lc == sizeof(test1)); res = res && (memcmp(dstdata, test1, sizeof(test1)) == 0); - PrintAndLogEx(INFO, "dstAPDU.data: %s", sprint_hex(dstAPDU.data, dstAPDU.Lc)); - + uint16_t sw = 0; + uint8_t test2[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x9D, 0x80, 0xE7, 0xE3, 0x34, 0xE9, 0x97, 0x82, 0xdd, 0xee}; + CipurseCAPDURespDecode(&ctx, test2, sizeof(test2), dstdata, &dstdatalen, &sw); + res = res && (dstdatalen == 6); + res = res && (memcmp(test2, dstdata, dstdatalen) == 0); + res = res && (sw == 0xddee); // Plain APDU CipurseCChannelSetSecurityLevels(&ctx, CPSPlain, CPSPlain); CipurseCAPDUReqEncode(&ctx, &srcAPDU, &dstAPDU, dstdata, true, 0x55); - uint8_t test2[] = {0x01, 0x11, 0x22, 0x33, 0x44, 0x00, 0x55}; + uint8_t test3[] = {0x01, 0x11, 0x22, 0x33, 0x44, 0x00, 0x55}; res = res && ((srcAPDU.CLA | 0x04) == dstAPDU.CLA); res = res && (srcAPDU.INS == dstAPDU.INS); res = res && (srcAPDU.P1 == dstAPDU.P1); res = res && (srcAPDU.P2 == dstAPDU.P2); - res = res && (dstAPDU.Lc == sizeof(test2)); - res = res && (memcmp(dstdata, test2, sizeof(test2)) == 0); + res = res && (dstAPDU.Lc == sizeof(test3)); + res = res && (memcmp(dstdata, test3, sizeof(test3)) == 0); + + uint8_t test4[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xcc, 0xdd}; + CipurseCAPDURespDecode(&ctx, test4, sizeof(test4), dstdata, &dstdatalen, &sw); + res = res && (dstdatalen == 6); + res = res && (memcmp(test4, dstdata, dstdatalen) == 0); + res = res && (sw == 0xccdd); // Encrypted APDU - //CipurseCChannelSetSecurityLevels(&ctx, CPSEncrypted, CPSEncrypted); + CipurseCChannelSetSecurityLevels(&ctx, CPSEncrypted, CPSEncrypted); + CipurseCAPDUReqEncode(&ctx, &srcAPDU, &dstAPDU, dstdata, true, 0x55); + uint8_t test5[] = {0x89, 0x7D, 0xED, 0x0D, 0x04, 0x8E, 0xE1, 0x99, 0x08, 0x70, 0x56, 0x7C, 0xEE, 0x67, 0xB3, 0x33, 0x6F, 0x00}; + res = res && ((srcAPDU.CLA | 0x04) == dstAPDU.CLA); + res = res && (srcAPDU.INS == dstAPDU.INS); + res = res && (srcAPDU.P1 == dstAPDU.P1); + res = res && (srcAPDU.P2 == dstAPDU.P2); + res = res && (dstAPDU.Lc == sizeof(test5)); + res = res && (memcmp(dstdata, test5, sizeof(test5)) == 0); + //PrintAndLogEx(INFO, "dstAPDU.data: %s", sprint_hex(dstAPDU.data, dstAPDU.Lc)); if (res) From 8b9271fc7d05920c18ec83786fff3e9766cce8a6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 24 Jun 2021 10:49:36 +0300 Subject: [PATCH 080/309] added frame key checking --- client/src/cipurse/cipursetest.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index 7eb13bbcc..bddc7135f 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -146,6 +146,9 @@ static bool TestAuth(void) { CipurseCChannelSetSecurityLevels(&ctx, CPSMACed, CPSMACed); res = res && (isCipurseCChannelSecuritySet(&ctx) == true); + uint8_t framekey[] = {0xCF, 0x6F, 0x3A, 0x47, 0xFC, 0xAC, 0x8D, 0x38, 0x25, 0x75, 0x8B, 0xFC, 0x8B, 0x61, 0x68, 0xF3}; + res = res && (memcmp(ctx.frameKey, framekey, sizeof(framekey)) == 0); + if (res) PrintAndLogEx(INFO, "Auth: " _GREEN_("passed")); else @@ -175,16 +178,28 @@ static bool TestMAC(void) { uint8_t testmac1[8] = {0xAB, 0x5C, 0x86, 0x18, 0x7F, 0x73, 0xEC, 0x4E}; res = res && (memcmp(mac, testmac1, 8) == 0); + uint8_t framekey1[] = {0x7D, 0x6F, 0x31, 0x40, 0xC8, 0x47, 0xED, 0x3F, 0x0A, 0x21, 0xE6, 0xFB, 0xC7, 0xDB, 0x27, 0xB0}; + res = res && (memcmp(ctx.frameKey, framekey1, sizeof(framekey1)) == 0); + CipurseCCalcMACPadded(&ctx, TestData, 4, mac); uint8_t testmac2[8] = {0x9F, 0xE9, 0x54, 0xBF, 0xFC, 0xA0, 0x7D, 0x75}; res = res && (memcmp(mac, testmac2, 8) == 0); + uint8_t framekey2[] = {0x1E, 0xD4, 0xB6, 0x87, 0x85, 0x93, 0x5B, 0xAF, 0xA9, 0xF2, 0xF0, 0x8F, 0xA9, 0xF0, 0xA5, 0xFB}; + res = res && (memcmp(ctx.frameKey, framekey2, sizeof(framekey2)) == 0); + CipurseCCalcMACPadded(&ctx, TestData, 4, mac); uint8_t testmac3[8] = {0x15, 0x6F, 0x08, 0x5C, 0x0F, 0x80, 0xE7, 0x07}; res = res && (memcmp(mac, testmac3, 8) == 0); + uint8_t framekey3[] = {0x0C, 0x42, 0x93, 0x73, 0x88, 0x8F, 0x63, 0xB3, 0x10, 0x8E, 0xDF, 0xDB, 0xC1, 0x20, 0x63, 0x4C}; + res = res && (memcmp(ctx.frameKey, framekey3, sizeof(framekey3)) == 0); + uint8_t testmac4[8] = {0x0E, 0xF0, 0x70, 0xA6, 0xA1, 0x15, 0x9A, 0xB6}; res = res && CipurseCCheckMACPadded(&ctx, TestData, 4, testmac4); + + uint8_t framekey4[] = {0xA0, 0x65, 0x1A, 0x62, 0x56, 0x5D, 0xD7, 0xC9, 0x32, 0xAE, 0x1D, 0xE0, 0xCF, 0x8D, 0xC1, 0xB9}; + res = res && (memcmp(ctx.frameKey, framekey4, sizeof(framekey4)) == 0); if (res) PrintAndLogEx(INFO, "channel MAC: " _GREEN_("passed")); From c522de5b79dfb6f6eb64a72054d80a05af26db93 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 24 Jun 2021 14:59:33 +0200 Subject: [PATCH 081/309] added "hf mf gview" to view contents of a magic gen3 gtu card --- CHANGELOG.md | 1 + armsrc/appmain.c | 8 +++ armsrc/mifarecmd.c | 36 +++++++++++ armsrc/mifarecmd.h | 3 + client/src/cmdhfmf.c | 107 ++++++++++++++++++++++++++++++++- client/src/mifare/mifarehost.c | 21 +++++++ client/src/mifare/mifarehost.h | 2 + include/pm3_cmd.h | 3 + 8 files changed, 180 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fddd51abe..c5cb2eba4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added `hf mf gview` - view contents of a magic Gen3 GTU (@iceman1001) - Added Standalone mode for nexwatch ID credentials (@Guilhem7, @MaximeBosca) - Fix `lf em 4x50/4x70 *` reverted a missunderstanding in byte order macros (@iceman1001) - Added more keys (@equipter) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index af5c01c72..cfa77249f 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1568,6 +1568,14 @@ static void PacketReceived(PacketCommandNG *packet) { MifareGen3Freez(); break; } + case CMD_HF_MIFARE_G3_RDBL: { + struct p { + uint8_t blockno; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + MifareG3ReadBlk(payload->blockno); + break; + } case CMD_HF_MIFARE_PERSONALIZE_UID: { struct p { uint8_t keytype; diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 4330f2c4f..2a8642f82 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -2594,6 +2594,42 @@ OUT: BigBuf_free(); } +void MifareG3ReadBlk(uint8_t blockno) { + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + clear_trace(); + set_tracing(true); + + int retval = PM3_SUCCESS; + uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE); + uint8_t *buf = BigBuf_malloc(PM3_CMD_DATA_SIZE); + uint8_t *uid = BigBuf_malloc(10); + if (iso14443a_select_card(uid, NULL, NULL, true, 0, true) == false) { + retval = PM3_ESOFT; + goto OUT; + } + + LED_B_ON(); + uint32_t save_iso14a_timeout = iso14a_get_timeout(); + iso14a_set_timeout(13560000 / 1000 / (8 * 16) * 1000); // 2 seconds timeout + + uint8_t cmd[] = { 0xCF, 0x00, 0x00, 0x00, 0x00, 0xCE, blockno, 0x00, 0x00}; + AddCrc14A(cmd, sizeof(cmd) - 2); + + ReaderTransmit(cmd, sizeof(cmd), NULL); + int res = ReaderReceive(buf, par); + if (res != 18) { + retval = PM3_ESOFT; + } + iso14a_set_timeout(save_iso14a_timeout); + LED_B_OFF(); + +OUT: + reply_ng(CMD_HF_MIFARE_G3_RDBL, retval, buf, 18); + // turns off + OnSuccessMagic(); + BigBuf_free(); +} + void MifareSetMod(uint8_t *datain) { uint8_t mod = datain[0]; diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index baf3d9e31..bacb8405e 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -49,6 +49,9 @@ void MifareGen3UID(uint8_t uidlen, uint8_t *uid); // Gen 3 magic card set UID wi void MifareGen3Blk(uint8_t block_len, uint8_t *block); // Gen 3 magic card overwrite manufacturer block void MifareGen3Freez(void); // Gen 3 magic card lock further UID changes +// MFC GEN3 GTU +void MifareG3ReadBlk(uint8_t blockno); + void MifareSetMod(uint8_t *datain); void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key); diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index b08de964c..bcb9c52c2 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -6007,6 +6007,110 @@ static int CmdHF14AMfView(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHF14AGen3View(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf gview", + "View `magic gen3 gtu` card memory", + "hf mf gview\n" + "hf mf gview --4k" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"), + arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"), + arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"), + arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + bool m0 = arg_get_lit(ctx, 1); + bool m1 = arg_get_lit(ctx, 2); + bool m2 = arg_get_lit(ctx, 3); + bool m4 = arg_get_lit(ctx, 4); + CLIParserFree(ctx); + + // validations + if ((m0 + m1 + m2 + m4) > 1) { + PrintAndLogEx(WARNING, "Only specify one MIFARE Type"); + return PM3_EINVARG; + } else if ((m0 + m1 + m2 + m4) == 0) { + m1 = true; + } + + char s[6]; + memset(s, 0, sizeof(s)); + uint16_t block_cnt = MIFARE_1K_MAXBLOCK; + if (m0) { + block_cnt = MIFARE_MINI_MAXBLOCK; + strncpy(s, "Mini", 5); + } else if (m1) { + block_cnt = MIFARE_1K_MAXBLOCK; + strncpy(s, "1K", 3); + } else if (m2) { + block_cnt = MIFARE_2K_MAXBLOCK; + strncpy(s, "2K", 3); + } else if (m4) { + block_cnt = MIFARE_4K_MAXBLOCK; + strncpy(s, "4K", 3); + } else { + PrintAndLogEx(WARNING, "Please specify a MIFARE Type"); + return PM3_EINVARG; + } + PrintAndLogEx(SUCCESS, "View magic gen3 GTU MIFARE Classic " _GREEN_("%s"), s); + PrintAndLogEx(INFO, "." NOLF); + + // Select card to get UID/UIDLEN information + clearCommandBuffer(); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) { + PrintAndLogEx(WARNING, "iso14443a card select timeout"); + return PM3_ETIMEOUT; + } + + /* + 0: couldn't read + 1: OK, with ATS + 2: OK, no ATS + 3: proprietary Anticollision + */ + uint64_t select_status = resp.oldarg[0]; + + if (select_status == 0) { + PrintAndLogEx(WARNING, "iso14443a card select failed"); + return select_status; + } + + iso14a_card_select_t card; + memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); + + // reserve memory + uint16_t bytes = block_cnt * MFBLOCK_SIZE; + uint8_t *dump = calloc(bytes, sizeof(uint8_t)); + if (dump == NULL) { + PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); + return PM3_EMALLOC; + } + + for (uint16_t i = 0; i < block_cnt; i++) { + + if (mfG3GetBlock(i, dump + (i * MFBLOCK_SIZE)) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "Can't get magic card block: %u", i); + PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position"); + free(dump); + return PM3_ESOFT; + } + PrintAndLogEx(NORMAL, "." NOLF); + fflush(stdout); + } + + PrintAndLogEx(NORMAL, ""); + mf_print_blocks(block_cnt, dump); + free(dump); + return PM3_SUCCESS; +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"list", CmdHF14AMfList, AlwaysAvailable, "List MIFARE history"}, @@ -6059,7 +6163,8 @@ static command_t CommandTable[] = { {"gen3uid", CmdHf14AGen3UID, IfPm3Iso14443a, "Set UID without changing manufacturer block"}, {"gen3blk", CmdHf14AGen3Block, IfPm3Iso14443a, "Overwrite manufacturer block"}, {"gen3freeze", CmdHf14AGen3Freeze, IfPm3Iso14443a, "Perma lock UID changes. irreversible"}, - + {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen3 GTU") " -----------------------"}, + {"gview", CmdHF14AGen3View, IfPm3Iso14443a, "View card"}, // {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("i") " -----------------------"}, // {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"}, {NULL, NULL, NULL, NULL} diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index 9b0c20d36..cf46fc05f 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -1050,6 +1050,27 @@ int mfGen3Freeze(void) { } } +int mfG3GetBlock(uint8_t blockno, uint8_t *data) { + struct p { + uint8_t blockno; + } PACKED payload; + payload.blockno = blockno; + + clearCommandBuffer(); + SendCommandNG(CMD_HF_MIFARE_G3_RDBL, (uint8_t*)&payload, sizeof(payload)); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_HF_MIFARE_G3_RDBL, &resp, 1500)) { + if (resp.status != PM3_SUCCESS) + return PM3_EUNDEF; + memcpy(data, resp.data.asBytes, 16); + } else { + PrintAndLogEx(WARNING, "command execute timeout"); + return PM3_ETIMEOUT; + } + return PM3_SUCCESS; +} + + // variables uint32_t cuid = 0; // uid part used for crypto1. diff --git a/client/src/mifare/mifarehost.h b/client/src/mifare/mifarehost.h index 49adc8cbe..8f5f215fd 100644 --- a/client/src/mifare/mifarehost.h +++ b/client/src/mifare/mifarehost.h @@ -85,6 +85,8 @@ int mfGen3UID(uint8_t *uid, uint8_t uidlen, uint8_t *oldUid); int mfGen3Block(uint8_t *block, int blockLen, uint8_t *newBlock); int mfGen3Freeze(void); +int mfG3GetBlock(uint8_t blockno, uint8_t *data); + int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len); int detect_classic_prng(void); diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 4e89e4f86..53343c5e1 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -740,6 +740,9 @@ typedef struct { #define CMD_HF_MIFARE_GEN3BLK 0x0851 #define CMD_HF_MIFARE_GEN3FREEZ 0x0852 +// Gen 3 GTU magic cards +#define CMD_HF_MIFARE_G3_RDBL 0x0860 + #define CMD_UNKNOWN 0xFFFF //Mifare simulation flags From ffddfea841f4b8d2952217d436d47d19dc404a8b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 24 Jun 2021 15:09:11 +0200 Subject: [PATCH 082/309] textual --- client/src/mifare/mifarehost.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index cf46fc05f..5285a4d94 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -56,6 +56,8 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { return PM3_EOPABORTED; } + PrintAndLogEx(INFO, "." NOLF); + // wait cycle while (true) { PrintAndLogEx(NORMAL, "." NOLF); @@ -546,7 +548,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, PrintAndLogEx(SUCCESS, "\ntarget block:%3u key type: %c -- found valid key [ " _GREEN_("%s") "]", package->block, package->keytype ? 'B' : 'A', - sprint_hex(resultKey, 6) + sprint_hex_inrow(resultKey, 6) ); return PM3_SUCCESS; } @@ -725,7 +727,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [ " _GREEN_("%s") "]", package->block, package->keytype ? 'B' : 'A', - sprint_hex(resultKey, 6) + sprint_hex_inrow(resultKey, 6) ); return PM3_SUCCESS; } else if (res == PM3_ETIMEOUT || res == PM3_EOPABORTED) { From aa880239a116de3d03e92430506a3d112351a986 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 24 Jun 2021 17:39:23 +0300 Subject: [PATCH 083/309] add error check in the crypto stream --- client/src/cipurse/cipursecrypto.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/src/cipurse/cipursecrypto.c b/client/src/cipurse/cipursecrypto.c index e68adc14f..9761fb1e3 100644 --- a/client/src/cipurse/cipursecrypto.c +++ b/client/src/cipurse/cipursecrypto.c @@ -506,6 +506,11 @@ void CipurseCAPDURespDecode(CipurseContext *ctx, uint8_t *srcdata, size_t srcdat CipurseCChannelDecrypt(ctx, srcdata, srcdatalen, buf, &buflen); //PrintAndLogEx(INFO, "data plain[%d]: %s", buflen, sprint_hex(buf, buflen)); + if (buflen == 0) { + PrintAndLogEx(ERR, "APDU can't decode crypto stream"); + break; + } + micdatalen = buflen - 2 - CIPURSE_MIC_LENGTH; memcpy(micdata, buf, buflen); memcpy(&micdata[micdatalen], &buf[buflen - 2], 2); From 4ba61c62371ef7f248a760ae0d88d2fb21149e10 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 24 Jun 2021 17:39:58 +0300 Subject: [PATCH 084/309] test apdu in the encode mode --- client/src/cipurse/cipursetest.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index bddc7135f..56d833690 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -274,7 +274,7 @@ static bool TestAPDU(void) { // check APDU formatting sAPDU srcAPDU = {0}; sAPDU dstAPDU = {0}; - uint8_t dstdata[32] = {0}; + uint8_t dstdata[256] = {0}; size_t dstdatalen = 0; // MACED APDU @@ -328,8 +328,16 @@ static bool TestAPDU(void) { res = res && (srcAPDU.P2 == dstAPDU.P2); res = res && (dstAPDU.Lc == sizeof(test5)); res = res && (memcmp(dstdata, test5, sizeof(test5)) == 0); - //PrintAndLogEx(INFO, "dstAPDU.data: %s", sprint_hex(dstAPDU.data, dstAPDU.Lc)); + uint8_t test6[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x7E, 0x4B, 0xA0, 0xB7, 0xcc, 0xdd}; + //CipurseCChannelEncrypt(&ctx, test6, sizeof(test6), dstdata, &dstdatalen); + //PrintAndLogEx(INFO, "dstdata[%d]: %s", dstdatalen, sprint_hex(dstdata, dstdatalen)); + + uint8_t test7[] = {0x07, 0xEF, 0x16, 0x91, 0xE7, 0x0F, 0xB5, 0x10, 0x63, 0xCE, 0x66, 0xDB, 0x3B, 0xC6, 0xD4, 0xE0, 0x90, 0x00}; + CipurseCAPDURespDecode(&ctx, test7, sizeof(test7), dstdata, &dstdatalen, &sw); + res = res && (dstdatalen == 8); + res = res && (memcmp(test6, dstdata, dstdatalen) == 0); + res = res && (sw == 0xccdd); if (res) PrintAndLogEx(INFO, "apdu: " _GREEN_("passed")); From a4643516f8a0748946be76e86e0c1f4af90dcafc Mon Sep 17 00:00:00 2001 From: rad1game Date: Thu, 24 Jun 2021 19:05:35 +0400 Subject: [PATCH 085/309] Update cmdlfem4x05.c Typo fix --- client/src/cmdlfem4x05.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index 1a2fc8255..781244164 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -1857,7 +1857,7 @@ int CmdEM4x05Unlock(const char *Cmd) { // compute number of bits flipped PrintAndLogEx(INFO, "Bitflips: %2u events => %s", bitcount32(bitflips), bitstring); PrintAndLogEx(INFO, "New protection word => " _CYAN_("%08X") "\n", word14b); - PrintAndLogEx(INFO, "Try " _YELLOW_("`lf em 4x05_dump`")); + PrintAndLogEx(INFO, "Try " _YELLOW_("`lf em 4x05 dump`")); } if (verbose) { From b993236be2761c0277299739e18c743dd3c27712 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 24 Jun 2021 17:20:48 +0200 Subject: [PATCH 086/309] send sync signal to clock when reset --- armsrc/hitag2.c | 7 +++++ armsrc/lfadc.c | 3 ++ armsrc/pcf7931.c | 75 +++++++++++++++++++++++++++++++----------------- armsrc/ticks.c | 2 ++ 4 files changed, 60 insertions(+), 27 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 063ed6c07..e771ad885 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1148,6 +1148,9 @@ void SniffHitag2(void) { // Enable and reset counter AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Assert a sync signal. This sets all timers to 0 on next active clock edge + AT91C_BASE_TCB->TCB_BCR = 1; + int frame_count = 0, response = 0, overflow = 0, lastbit = 1, tag_sof = 4; bool rising_edge = false, reader_frame = false, bSkip = true; uint8_t rx[HITAG_FRAME_LEN]; @@ -1293,11 +1296,15 @@ void SniffHitag2(void) { // Reset the timer to restart while-loop that receives frames AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; + + // Assert a sync signal. This sets all timers to 0 on next active clock edge + AT91C_BASE_TCB->TCB_BCR = 1; } LEDsoff(); AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); set_tracing(false); diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index 6a351bfca..2bfe41529 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -246,6 +246,9 @@ void lf_init(bool reader, bool simulate) { AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Assert a sync signal. This sets all timers to 0 on next active clock edge + AT91C_BASE_TCB->TCB_BCR = 1; + // Prepare data trace uint32_t bufsize = 10000; diff --git a/armsrc/pcf7931.c b/armsrc/pcf7931.c index 6ad44d7c4..5528bf596 100644 --- a/armsrc/pcf7931.c +++ b/armsrc/pcf7931.c @@ -14,13 +14,17 @@ #define ALLOC 16 size_t DemodPCF7931(uint8_t **outBlocks) { + + // 2021 iceman, memor uint8_t bits[256] = {0x00}; uint8_t blocks[8][16]; + uint8_t *dest = BigBuf_get_addr(); int GraphTraceLen = BigBuf_max_traceLen(); - if (GraphTraceLen > 18000) + if (GraphTraceLen > 18000) { GraphTraceLen = 18000; + } int i = 2, j, lastval, bitidx, half_switch; int clock = 64; @@ -38,15 +42,17 @@ size_t DemodPCF7931(uint8_t **outBlocks) { /* Find first local max/min */ if (dest[1] > dest[0]) { while (i < GraphTraceLen) { - if (!(dest[i] > dest[i - 1]) && dest[i] > lmax) + if (!(dest[i] > dest[i - 1]) && dest[i] > lmax) { break; + } i++; } dir = 0; } else { while (i < GraphTraceLen) { - if (!(dest[i] < dest[i - 1]) && dest[i] < lmin) + if (!(dest[i] < dest[i - 1]) && dest[i] < lmin) { break; + } i++; } dir = 1; @@ -58,6 +64,7 @@ size_t DemodPCF7931(uint8_t **outBlocks) { block_done = 0; for (bitidx = 0; i < GraphTraceLen; i++) { + if ((dest[i - 1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i - 1] < dest[i] && dir == 0 && dest[i] < lmin)) { lc = i - lastval; lastval = i; @@ -66,8 +73,8 @@ size_t DemodPCF7931(uint8_t **outBlocks) { // Tolerance is 1/8 of clock rate (arbitrary) if (ABS(lc - clock / 4) < tolerance) { // 16T0 - if ((i - pmc) == lc) { /* 16T0 was previous one */ - /* It's a PMC ! */ + if ((i - pmc) == lc) { // 16T0 was previous one + // It's a PMC i += (128 + 127 + 16 + 32 + 33 + 16) - 1; lastval = i; pmc = 0; @@ -77,8 +84,8 @@ size_t DemodPCF7931(uint8_t **outBlocks) { } } else if (ABS(lc - clock / 2) < tolerance) { // 32TO - if ((i - pmc) == lc) { /* 16T0 was previous one */ - /* It's a PMC ! */ + if ((i - pmc) == lc) { // 16T0 was previous one + // It's a PMC ! i += (128 + 127 + 16 + 32 + 33) - 1; lastval = i; pmc = 0; @@ -95,8 +102,9 @@ size_t DemodPCF7931(uint8_t **outBlocks) { // Error if (++warnings > 10) { - if (DBGLEVEL >= DBG_EXTENDED) - Dbprintf("Error: too many detection errors, aborting."); + if (DBGLEVEL >= DBG_EXTENDED) { + Dbprintf("Error: too many detection errors, aborting"); + } return 0; } @@ -122,13 +130,19 @@ size_t DemodPCF7931(uint8_t **outBlocks) { block_done = 0; half_switch = 0; } - if (i < GraphTraceLen) + + if (i < GraphTraceLen) { dir = (dest[i - 1] > dest[i]) ? 0 : 1; + } } - if (bitidx == 255) + + if (bitidx == 255) { bitidx = 0; - warnings = 0; - if (num_blocks == 4) break; + } + + if (num_blocks == 4) { + break; + } } memcpy(outBlocks, blocks, 16 * num_blocks); return num_blocks; @@ -138,10 +152,11 @@ bool IsBlock0PCF7931(uint8_t *block) { // assuming all RFU bits are set to 0 // if PAC is enabled password is set to 0 if (block[7] == 0x01) { - if (!memcmp(block, "\x00\x00\x00\x00\x00\x00\x00", 7) - && !memcmp(block + 9, "\x00\x00\x00\x00\x00\x00\x00", 7)) { + if (!memcmp(block, "\x00\x00\x00\x00\x00\x00\x00", 7) && + !memcmp(block + 9, "\x00\x00\x00\x00\x00\x00\x00", 7)) { return true; } + } else if (block[7] == 0x00) { if (!memcmp(block + 9, "\x00\x00\x00\x00\x00\x00\x00", 7)) { return true; @@ -158,14 +173,14 @@ bool IsBlock1PCF7931(uint8_t *block) { uint8_t rlb = block[15]; if (block[10] == 0 - && block[11] == 0 - && block[12] == 0 - && block[13] == 0) { + && block[11] == 0 + && block[12] == 0 + && block[13] == 0) { // block 1 is sent only if (RLB >= 1 && RFB <= 1) or RB1 enabled if (rfb <= rlb - && rfb <= 9 - && rlb <= 9 - && ((rfb <= 1 && rlb >= 1) || rb1)) { + && rfb <= 9 + && rlb <= 9 + && ((rfb <= 1 && rlb >= 1) || rb1)) { return true; } } @@ -211,8 +226,9 @@ void ReadPCF7931(void) { // exit if too many errors during reading if (tries > 50 && (2 * errors > tries)) { - if (DBGLEVEL >= DBG_INFO) + if (DBGLEVEL >= DBG_INFO) { Dbprintf("[!!] Error reading the tag, only partial content"); + } goto end; } @@ -461,27 +477,32 @@ void SendCmdPCF7931(uint32_t *tab) { //initialization of the timer AT91C_BASE_PMC->PMC_PCER |= (0x1 << AT91C_ID_TC0); AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE; - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; //clock at 48/32 MHz + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; // clock at 48/32 MHz AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN; + + // Assert a sync signal. This sets all timers to 0 on next active clock edge AT91C_BASE_TCB->TCB_BCR = 1; tempo = AT91C_BASE_TC0->TC_CV; for (u = 0; tab[u] != 0; u += 3) { // modulate antenna HIGH(GPIO_SSC_DOUT); - while (tempo != tab[u]) + while (tempo != tab[u]) { tempo = AT91C_BASE_TC0->TC_CV; + } // stop modulating antenna LOW(GPIO_SSC_DOUT); - while (tempo != tab[u + 1]) + while (tempo != tab[u + 1]) { tempo = AT91C_BASE_TC0->TC_CV; + } // modulate antenna HIGH(GPIO_SSC_DOUT); - while (tempo != tab[u + 2]) + while (tempo != tab[u + 2]) { tempo = AT91C_BASE_TC0->TC_CV; + } } LED_A_OFF(); diff --git a/armsrc/ticks.c b/armsrc/ticks.c index 9b563cc54..8f15afa12 100644 --- a/armsrc/ticks.c +++ b/armsrc/ticks.c @@ -125,6 +125,8 @@ void StartCountUS(void) { AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + + // Assert a sync signal. This sets all timers to 0 on next active clock edge AT91C_BASE_TCB->TCB_BCR = 1; while (AT91C_BASE_TC1->TC_CV > 0); From f02daaa1cb5f58c2f4310b3e3eed043aeb3e3570 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 24 Jun 2021 17:34:37 +0200 Subject: [PATCH 087/309] ndef parser vcard now handles xvcard --- client/src/nfc/ndef.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/client/src/nfc/ndef.c b/client/src/nfc/ndef.c index 2bc841a23..9c3c42330 100644 --- a/client/src/nfc/ndef.c +++ b/client/src/nfc/ndef.c @@ -25,6 +25,7 @@ #define NDEF_WIFIAPPL "application/vnd.wfa" #define NDEF_BLUEAPPL "application/vnd.bluetooth" #define NDEF_VCARDTEXT "text/vcard" +#define NDEF_XVCARDTEXT "text/x-vcard" static const char *TypeNameFormat_s[] = { "Empty Record", @@ -510,8 +511,8 @@ static int ndefDecodeMime_wifi(NDEFHeader_t *ndef) { static int ndefDecodeMime_vcard(NDEFHeader_t *ndef) { PrintAndLogEx(INFO, _CYAN_("VCARD details")); if (ndef->PayloadLen > 1) { - PrintAndLogEx(INFO, "Data... " _YELLOW_("%.*s"), (int)ndef->PayloadLen, ndef->Payload); - PrintAndLogEx(INFO, ">>> decorder, to be implemented <<<"); + PrintAndLogEx(INFO, ""); + PrintAndLogEx(INFO, "%.*s", (int)ndef->PayloadLen, ndef->Payload); } return PM3_SUCCESS; } @@ -629,20 +630,29 @@ static int ndefDecodePayload(NDEFHeader_t *ndef) { PrintAndLogEx(INFO, "- decoder to be impl -"); } break; - case tnfMIMEMediaRecord: + case tnfMIMEMediaRecord: { PrintAndLogEx(INFO, "MIME Media Record"); + if (ndef->TypeLen == 0) { + PrintAndLogEx(INFO, "type length is zero"); + break; + } - if (str_startswith((const char *)ndef->Type, NDEF_WIFIAPPL)) { + char begin[ndef->TypeLen]; + memcpy(begin, ndef->Type, ndef->TypeLen); + str_lower(begin); + + if (str_startswith(begin, NDEF_WIFIAPPL)) { ndefDecodeMime_wifi(ndef); } - if (str_startswith((const char *)ndef->Type, NDEF_VCARDTEXT)) { + if (str_startswith(begin, NDEF_VCARDTEXT) || str_startswith(begin, NDEF_XVCARDTEXT)) { ndefDecodeMime_vcard(ndef); } - if (str_startswith((const char *)ndef->Type, NDEF_BLUEAPPL)) { + if (str_startswith(begin, NDEF_BLUEAPPL)) { ndefDecodeMime_bt(ndef); } break; + } case tnfAbsoluteURIRecord: PrintAndLogEx(INFO, "Absolute URI Record"); PrintAndLogEx(INFO, " payload : %.*s", (int)ndef->PayloadLen, ndef->Payload); From ebd9f24af4a9bd2fefb397a2cfcc578ac656b3fc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 24 Jun 2021 17:38:17 +0200 Subject: [PATCH 088/309] fix hf iclass config - now uses a default config card data if no config card present on device. --- client/src/cmdhficlass.c | 79 ++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 08c4e9360..37120f29b 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -37,6 +37,9 @@ #define ICLASS_AUTH_RETRY 10 #define ICLASS_DECRYPTION_BIN "iclass_decryptionkey.bin" +static void print_picopass_info(const picopass_hdr_t *hdr); +void print_picopass_header(const picopass_hdr_t *hdr); + static picopass_hdr_t iclass_last_known_card; static void iclass_set_last_known_card(picopass_hdr_t *card) { memcpy(&iclass_last_known_card, card, sizeof(picopass_hdr_t)); @@ -129,7 +132,7 @@ static void iclass_upload_emul(uint8_t *d, uint16_t n, uint16_t *bytes_sent) { uint16_t bytes_remaining = n; while (bytes_remaining > 0) { - uint32_t bytes_in_packet = MIN(PM3_CMD_DATA_SIZE, bytes_remaining); + uint32_t bytes_in_packet = MIN(PM3_CMD_DATA_SIZE - 4, bytes_remaining); if (bytes_in_packet == bytes_remaining) { // Disable fast mode on last packet conn.block_after_ACK = false; @@ -244,8 +247,8 @@ static void print_config_cards(void) { static void print_config_card(const iclass_config_card_item_t *o) { if (check_config_card(o)) { - PrintAndLogEx(INFO, "description... %s", o->desc); - PrintAndLogEx(INFO, "data....... " _YELLOW_("%s"), sprint_hex_inrow(o->data, sizeof(o->data))); + PrintAndLogEx(INFO, "description... " _YELLOW_("%s") , o->desc); + PrintAndLogEx(INFO, "data.......... " _YELLOW_("%s"), sprint_hex_inrow(o->data, sizeof(o->data))); } } @@ -253,20 +256,37 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke if (check_config_card(o) == false) { return PM3_EINVARG; } + + // generated config card header + picopass_hdr_t configcard; + memset(&configcard, 0xFF, sizeof(picopass_hdr_t)); + memcpy(configcard.csn, "\x41\x87\x66\x00\xFB\xFF\x12\xE0", 8); + memcpy(&configcard.conf, "\xFF\xFF\xFF\xFF\xF9\xFF\xFF\xBC", 8); + memcpy(&configcard.epurse, "\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8); + // defaulting to known AA1 key + HFiClassCalcDivKey(configcard.csn, iClass_Key_Table[0], configcard.key_d, false); + + // reference + picopass_hdr_t *cc = &configcard; + // get header from card - //bool have = memcmp(iclass_last_known_card.csn, "\x00\x00\x00\x00\x00\x00\x00\x00", 8); PrintAndLogEx(INFO, "trying to read a card.."); int res = read_iclass_csn(false, false); - if (res != PM3_SUCCESS) { - PrintAndLogEx(FAILED, "Put a card on antenna and try again..."); - return res; + if (res == PM3_SUCCESS) { + cc = &iclass_last_known_card; + // calc diversified key for selected card + HFiClassCalcDivKey(cc->csn, iClass_Key_Table[0], cc->key_d, false); + } else { + PrintAndLogEx(INFO, "failed to read a card, will use default config card data"); } // generate dump file - uint8_t app1_limit = iclass_last_known_card.conf.app_limit; + uint8_t app1_limit = cc->conf.app_limit; uint8_t old_limit = app1_limit; - uint8_t tot_bytes = (app1_limit + 1) * 8; + uint16_t tot_bytes = (app1_limit + 1) * 8; + PrintAndLogEx(INFO, " APP1 limit: %u", app1_limit); + PrintAndLogEx(INFO, "total bytes: %u", tot_bytes); // normal size uint8_t *data = calloc(1, tot_bytes); if (data == NULL) { @@ -274,12 +294,9 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke return PM3_EMALLOC; } + memcpy(data, cc, sizeof(picopass_hdr_t)); - // calc diversified key for selected card - HFiClassCalcDivKey(iclass_last_known_card.csn, iClass_Key_Table[0], iclass_last_known_card.key_d, false); - - memset(data, 0x00, tot_bytes); - memcpy(data, (uint8_t *)&iclass_last_known_card, sizeof(picopass_hdr_t)); + print_picopass_header(cc); // Keyrolling configuration cards are special. if (strstr(o->desc, "Keyroll") != NULL) { @@ -295,7 +312,7 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke PrintAndLogEx(WARNING, "Adapting applimit1 for KEY rolling.."); app1_limit = 0x16; - iclass_last_known_card.conf.app_limit = 0x16; + cc->conf.app_limit = 0x16; tot_bytes = (app1_limit + 1) * 8; uint8_t *p = realloc(data, tot_bytes); @@ -308,25 +325,22 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke memset(data, 0xFF, tot_bytes); } - // need to encrypt - PrintAndLogEx(INFO, "Detecting cardhelper..."); - if (IsCardHelperPresent(false) == false) { - PrintAndLogEx(FAILED, "failed to detect cardhelper"); - free(data); - return PM3_ENODATA; - } - + // KEYROLL need to encrypt uint8_t ffs[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; if (Encrypt(ffs, ffs) == false) { PrintAndLogEx(WARNING, "failed to encrypt FF"); } + // local key copy + uint8_t lkey[8]; + memcpy(lkey, key, sizeof(lkey)); + uint8_t enckey1[8]; - if (Encrypt(key, enckey1) == false) { + if (Encrypt(lkey, enckey1) == false) { PrintAndLogEx(WARNING, "failed to encrypt key1"); } - memcpy(data, &iclass_last_known_card, sizeof(picopass_hdr_t)); + memcpy(data, cc, sizeof(picopass_hdr_t)); memcpy(data + (6 * 8), o->data, sizeof(o->data)); // encrypted keyroll key 0D @@ -338,7 +352,7 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke // encrypted partial keyroll key 14 uint8_t foo[8] = {0x15}; - memcpy(foo + 1, key, 7); + memcpy(foo + 1, lkey, 7); uint8_t enckey2[8]; if (Encrypt(foo, enckey2) == false) { PrintAndLogEx(WARNING, "failed to encrypt partial 1"); @@ -347,7 +361,7 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke // encrypted partial keyroll key 15 memset(foo, 0xFF, sizeof(foo)); - foo[0] = key[7]; + foo[0] = lkey[7]; if (Encrypt(foo, enckey2) == false) { PrintAndLogEx(WARNING, "failed to encrypt partial 2"); } @@ -358,12 +372,11 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke memcpy(data + (i * 8), ffs, sizeof(ffs)); } - // revert potential modified app1_limit - iclass_last_known_card.conf.app_limit = old_limit; + cc->conf.app_limit = old_limit; } else { - memcpy(data, &iclass_last_known_card, sizeof(picopass_hdr_t)); + memcpy(data, cc, sizeof(picopass_hdr_t)); memcpy(data + (6 * 8), o->data, sizeof(o->data)); } @@ -532,13 +545,13 @@ static void mem_app_config(const picopass_hdr_t *hdr) { } } -static void print_picopass_info(const picopass_hdr_t *hdr) { +void print_picopass_info(const picopass_hdr_t *hdr) { PrintAndLogEx(INFO, "-------------------- " _CYAN_("card configuration") " --------------------"); fuse_config(hdr); mem_app_config(hdr); } -static void print_picopass_header(const picopass_hdr_t *hdr) { +void print_picopass_header(const picopass_hdr_t *hdr) { PrintAndLogEx(INFO, "--------------------------- " _CYAN_("card") " ---------------------------"); PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " uid", sprint_hex(hdr->csn, sizeof(hdr->csn))); PrintAndLogEx(SUCCESS, " Config: %s Card configuration", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf))); @@ -3859,6 +3872,8 @@ int CmdHFiClass(const char *Cmd) { // SR | 6,7,8,9, | AA1, Access control payload | 2 // | 10,11,12,13,14,15,16 | AA1, Secure identity object (SIO) | // SEOS | | | +// MFC SIO| | | +// DESFIRE| | | //} int info_iclass(void) { From 681d72952889ef9cf93564fe9b9fb6c533262ff8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 24 Jun 2021 17:40:13 +0200 Subject: [PATCH 089/309] text --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5cb2eba4..1d13cad28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fix `hf iclass config` - now fallback to default config card configuration (@iceman1001) + - Changed `nfc parser` - now also identify xvcard types (@iceman1001) - Added `hf mf gview` - view contents of a magic Gen3 GTU (@iceman1001) - Added Standalone mode for nexwatch ID credentials (@Guilhem7, @MaximeBosca) - Fix `lf em 4x50/4x70 *` reverted a missunderstanding in byte order macros (@iceman1001) From e50c7db17d8f331c2555327a9e3d14ab71cef541 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 24 Jun 2021 18:11:46 +0200 Subject: [PATCH 090/309] fix coverity CID 322762 --- tools/mf_nonce_brute/mf_nonce_brute.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/mf_nonce_brute/mf_nonce_brute.c b/tools/mf_nonce_brute/mf_nonce_brute.c index b064f3683..973989eda 100644 --- a/tools/mf_nonce_brute/mf_nonce_brute.c +++ b/tools/mf_nonce_brute/mf_nonce_brute.c @@ -417,6 +417,7 @@ static void *brute_thread(void *arguments) { if (isOK == false) { printf(_RED_("<-- not a valid cmd\n")); pthread_mutex_unlock(&print_lock); + free(revstate); continue; } @@ -425,6 +426,7 @@ static void *brute_thread(void *arguments) { if (isOK == false) { printf(_RED_("<-- not a valid crc\n")); pthread_mutex_unlock(&print_lock); + free(revstate); continue; } else { printf("<-- valid cmd\n"); From eed0ca4796308b667c37cf3bfc58f09320666e74 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 24 Jun 2021 18:23:10 +0200 Subject: [PATCH 091/309] textual --- client/src/cipurse/cipursetest.c | 39 ++++++++++++++++---------------- client/src/cmdhfcipurse.c | 1 - tools/pm3_tests.sh | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index 56d833690..065947bf5 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -32,9 +32,9 @@ static bool TestKVV(void) { bool res = memcmp(KeyKvv, kvv, CIPURSE_KVV_LENGTH) == 0; if (res) - PrintAndLogEx(INFO, "kvv: " _GREEN_("passed")); + PrintAndLogEx(INFO, "kvv.............. " _GREEN_("passed")); else - PrintAndLogEx(ERR, "kvv: " _RED_("fail")); + PrintAndLogEx(ERR, "kvv.............. " _RED_("fail")); return res; } @@ -50,9 +50,9 @@ static bool TestISO9797M2(void) { res = res && (FindISO9797M2PaddingDataLen(data, ddatalen) == 4); if (res) - PrintAndLogEx(INFO, "ISO9797M2: " _GREEN_("passed")); + PrintAndLogEx(INFO, "ISO9797M2........ " _GREEN_("passed")); else - PrintAndLogEx(ERR, "ISO9797M2: " _RED_("fail")); + PrintAndLogEx(ERR, "ISO9797M2........ " _RED_("fail")); return res; } @@ -84,9 +84,9 @@ static bool TestSMI(void) { res = res && (CipurseCGetSMI(&ctx, true) == 0x89); if (res) - PrintAndLogEx(INFO, "SMI: " _GREEN_("passed")); + PrintAndLogEx(INFO, "SMI.............. " _GREEN_("passed")); else - PrintAndLogEx(ERR, "SMI: " _RED_("fail")); + PrintAndLogEx(ERR, "SMI.............. " _RED_("fail")); return res; } @@ -107,9 +107,9 @@ static bool TestMIC(void) { res = res && (CipurseCCheckMIC(TestData, 6, mic)); if (res) - PrintAndLogEx(INFO, "MIC: " _GREEN_("passed")); + PrintAndLogEx(INFO, "MIC.............. " _GREEN_("passed")); else - PrintAndLogEx(ERR, "MIC: " _RED_("fail")); + PrintAndLogEx(ERR, "MIC.............. " _RED_("fail")); return res; } @@ -150,9 +150,9 @@ static bool TestAuth(void) { res = res && (memcmp(ctx.frameKey, framekey, sizeof(framekey)) == 0); if (res) - PrintAndLogEx(INFO, "Auth: " _GREEN_("passed")); + PrintAndLogEx(INFO, "Auth............. " _GREEN_("passed")); else - PrintAndLogEx(ERR, "Auth: " _RED_("fail")); + PrintAndLogEx(ERR, "Auth............. " _RED_("fail")); return res; } @@ -202,9 +202,9 @@ static bool TestMAC(void) { res = res && (memcmp(ctx.frameKey, framekey4, sizeof(framekey4)) == 0); if (res) - PrintAndLogEx(INFO, "channel MAC: " _GREEN_("passed")); + PrintAndLogEx(INFO, "channel MAC...... " _GREEN_("passed")); else - PrintAndLogEx(ERR, "channel MAC: " _RED_("fail")); + PrintAndLogEx(ERR, "channel MAC...... " _RED_("fail")); return res; } @@ -248,9 +248,9 @@ static bool TestEncDec(void) { res = res && (memcmp(dstdata, TestData, 16) == 0); if (res) - PrintAndLogEx(INFO, "channel EncDec: " _GREEN_("passed")); + PrintAndLogEx(INFO, "channel EncDec... " _GREEN_("passed")); else - PrintAndLogEx(ERR, "channel EncDec: " _RED_("fail")); + PrintAndLogEx(ERR, "channel EncDec... " _RED_("fail")); return res; } @@ -340,9 +340,9 @@ static bool TestAPDU(void) { res = res && (sw == 0xccdd); if (res) - PrintAndLogEx(INFO, "apdu: " _GREEN_("passed")); + PrintAndLogEx(INFO, "apdu............. " _GREEN_("passed")); else - PrintAndLogEx(ERR, "apdu: " _RED_("fail")); + PrintAndLogEx(ERR, "apdu............. " _RED_("fail")); return res; } @@ -350,7 +350,7 @@ static bool TestAPDU(void) { bool CIPURSETest(bool verbose) { bool res = true; - PrintAndLogEx(INFO, "------ " _CYAN_("CIPURSE TESTS") " ------"); + PrintAndLogEx(INFO, "------ " _CYAN_("CIPURSE Tests") " ------"); res = res && TestKVV(); res = res && TestISO9797M2(); @@ -363,9 +363,10 @@ bool CIPURSETest(bool verbose) { PrintAndLogEx(INFO, "---------------------------"); if (res) - PrintAndLogEx(SUCCESS, " Test(s) [ %s ]", _GREEN_("ok")); + PrintAndLogEx(SUCCESS, " Tests [ %s ]", _GREEN_("ok")); else - PrintAndLogEx(FAILED, " Test(s) [ %s ]", _RED_("fail")); + PrintAndLogEx(FAILED, " Tests [ %s ]", _RED_("fail")); + PrintAndLogEx(NORMAL, ""); return res; } diff --git a/client/src/cmdhfcipurse.c b/client/src/cmdhfcipurse.c index 141b78784..841181732 100644 --- a/client/src/cmdhfcipurse.c +++ b/client/src/cmdhfcipurse.c @@ -689,7 +689,6 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) { return PM3_SUCCESS; } - bool CheckCardCipurse(void) { uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; diff --git a/tools/pm3_tests.sh b/tools/pm3_tests.sh index 3ed9ee82b..41882f2e5 100755 --- a/tools/pm3_tests.sh +++ b/tools/pm3_tests.sh @@ -491,7 +491,7 @@ while true; do if ! $SLOWTESTS; then if ! CheckExecute "hf iclass loclass test" "$CLIENTBIN -c 'hf iclass loclass --test'" "key diversification (ok)"; then break; fi if ! CheckExecute "emv test" "$CLIENTBIN -c 'emv test'" "Test(s) \[ ok"; then break; fi - if ! CheckExecute "hf cipurse test" "$CLIENTBIN -c 'hf cipurse test'" "Test(s) \[ ok"; then break; fi + if ! CheckExecute "hf cipurse test" "$CLIENTBIN -c 'hf cipurse test'" "Tests \[ ok"; then break; fi fi fi echo -e "\n------------------------------------------------------------" From 791a4e885bd7e9ae49ca8f715571344052f6c57d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 24 Jun 2021 19:29:36 +0300 Subject: [PATCH 092/309] fix coverity 305864 --- client/src/emv/emvcore.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/emv/emvcore.c b/client/src/emv/emvcore.c index 7d0ab8ce4..2522aa8b5 100644 --- a/client/src/emv/emvcore.c +++ b/client/src/emv/emvcore.c @@ -758,6 +758,7 @@ int trDDA(Iso7816CommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { tlvdb_free(atc_db); return 9; } + tlvdb_free(atc_db); } else { struct tlvdb *dac_db = emv_pki_recover_dac(issuer_pk, tlv, sda_tlv); From e2ca0a4abddc3181ba8fe21621fb209a8bf2ca1e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 24 Jun 2021 18:47:11 +0200 Subject: [PATCH 093/309] style --- armsrc/appmain.c | 2 +- armsrc/hitag2.c | 2 +- armsrc/pcf7931.c | 16 +-- client/luascripts/hf_mfu_magicwrite.lua | 14 +- client/src/cipurse/cipursetest.c | 69 +++++----- client/src/cipurse/cipursetest.h | 2 +- client/src/cmdhfcipurse.c | 1 - client/src/cmdhficlass.c | 2 +- client/src/cmdhfmfdes.c | 17 ++- client/src/cmdlfhitag.c | 2 +- client/src/mifare/desfire_crypto.c | 4 +- client/src/mifare/mifarehost.c | 2 +- client/src/nfc/ndef.c | 50 ++++---- doc/commands.json | 164 +++++++++++++----------- doc/commands.md | 18 +-- 15 files changed, 193 insertions(+), 172 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index cfa77249f..b6781ac6d 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1573,7 +1573,7 @@ static void PacketReceived(PacketCommandNG *packet) { uint8_t blockno; } PACKED; struct p *payload = (struct p *) packet->data.asBytes; - MifareG3ReadBlk(payload->blockno); + MifareG3ReadBlk(payload->blockno); break; } case CMD_HF_MIFARE_PERSONALIZE_UID: { diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index e771ad885..8aa7178cb 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1304,7 +1304,7 @@ void SniffHitag2(void) { LEDsoff(); AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); set_tracing(false); diff --git a/armsrc/pcf7931.c b/armsrc/pcf7931.c index 5528bf596..bb96ea97e 100644 --- a/armsrc/pcf7931.c +++ b/armsrc/pcf7931.c @@ -152,8 +152,8 @@ bool IsBlock0PCF7931(uint8_t *block) { // assuming all RFU bits are set to 0 // if PAC is enabled password is set to 0 if (block[7] == 0x01) { - if (!memcmp(block, "\x00\x00\x00\x00\x00\x00\x00", 7) && - !memcmp(block + 9, "\x00\x00\x00\x00\x00\x00\x00", 7)) { + if (!memcmp(block, "\x00\x00\x00\x00\x00\x00\x00", 7) && + !memcmp(block + 9, "\x00\x00\x00\x00\x00\x00\x00", 7)) { return true; } @@ -173,14 +173,14 @@ bool IsBlock1PCF7931(uint8_t *block) { uint8_t rlb = block[15]; if (block[10] == 0 - && block[11] == 0 - && block[12] == 0 - && block[13] == 0) { + && block[11] == 0 + && block[12] == 0 + && block[13] == 0) { // block 1 is sent only if (RLB >= 1 && RFB <= 1) or RB1 enabled if (rfb <= rlb - && rfb <= 9 - && rlb <= 9 - && ((rfb <= 1 && rlb >= 1) || rb1)) { + && rfb <= 9 + && rlb <= 9 + && ((rfb <= 1 && rlb >= 1) || rb1)) { return true; } } diff --git a/client/luascripts/hf_mfu_magicwrite.lua b/client/luascripts/hf_mfu_magicwrite.lua index 199aec7c0..803f3f224 100644 --- a/client/luascripts/hf_mfu_magicwrite.lua +++ b/client/luascripts/hf_mfu_magicwrite.lua @@ -16,25 +16,25 @@ version = 'v1.1.4' desc = 'This script enables easy programming of a MAGIC NTAG 21* card' example = [[ -- read magic tag configuration - ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -c ]]..ansicolors.reset..[[ + ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -c ]]..ansicolors.reset..[[ -- set uid - ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -u 04112233445566 ]]..ansicolors.reset..[[ + ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -u 04112233445566 ]]..ansicolors.reset..[[ -- set pwd / pack - ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -p 11223344 -a 8080 ]]..ansicolors.reset..[[ + ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -p 11223344 -a 8080 ]]..ansicolors.reset..[[ -- set version to NTAG213 - ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -v 0004040201000f03 ]]..ansicolors.reset..[[ + ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -v 0004040201000f03 ]]..ansicolors.reset..[[ -- set signature - ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -s 1122334455667788990011223344556677889900112233445566778899001122 ]]..ansicolors.reset..[[ + ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -s 1122334455667788990011223344556677889900112233445566778899001122 ]]..ansicolors.reset..[[ -- wipe tag - ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -w ]]..ansicolors.reset..[[ + ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -w ]]..ansicolors.reset..[[ -- wipe a locked down tag by giving the password - ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -k ffffffff -w ]]..ansicolors.reset..[[ + ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -k ffffffff -w ]]..ansicolors.reset..[[ ]] usage = [[ diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index 065947bf5..6ccd4f91d 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -12,7 +12,7 @@ #include #include // memcpy memset -#include "fileutils.h" +#include "fileutils.h" #include "cipurse/cipursecrypto.h" #include "cipurse/cipursecore.h" @@ -30,7 +30,7 @@ static bool TestKVV(void) { CipurseCGetKVV(Key, kvv); bool res = memcmp(KeyKvv, kvv, CIPURSE_KVV_LENGTH) == 0; - + if (res) PrintAndLogEx(INFO, "kvv.............. " _GREEN_("passed")); else @@ -41,14 +41,14 @@ static bool TestKVV(void) { static bool TestISO9797M2(void) { uint8_t data[32] = {0}; - + size_t ddatalen = 0; AddISO9797M2Padding(data, &ddatalen, TestData, 4, 16); bool res = (ddatalen == 16); res = res && (memcmp(data, TestDataPadded, ddatalen) == 0); res = res && (FindISO9797M2PaddingDataLen(data, ddatalen) == 4); - + if (res) PrintAndLogEx(INFO, "ISO9797M2........ " _GREEN_("passed")); else @@ -60,9 +60,9 @@ static bool TestISO9797M2(void) { static bool TestSMI(void) { CipurseContext ctx = {0}; CipurseCClearContext(&ctx); - + bool res = (isCipurseCChannelSecuritySet(&ctx) == false); - + CipurseCChannelSetSecurityLevels(&ctx, CPSPlain, CPSPlain); res = res && (CipurseCGetSMI(&ctx, false) == 0x00); res = res && (CipurseCGetSMI(&ctx, true) == 0x01); @@ -82,7 +82,7 @@ static bool TestSMI(void) { CipurseCChannelSetSecurityLevels(&ctx, CPSEncrypted, CPSEncrypted); res = res && (CipurseCGetSMI(&ctx, false) == 0x88); res = res && (CipurseCGetSMI(&ctx, true) == 0x89); - + if (res) PrintAndLogEx(INFO, "SMI.............. " _GREEN_("passed")); else @@ -105,7 +105,7 @@ static bool TestMIC(void) { res = res && (memcmp(mic, valid_mic6, 4) == 0); res = res && (CipurseCCheckMIC(TestData, 6, mic)); - + if (res) PrintAndLogEx(INFO, "MIC.............. " _GREEN_("passed")); else @@ -118,34 +118,35 @@ static bool TestMIC(void) { static bool TestAuth(void) { CipurseContext ctx = {0}; CipurseCClearContext(&ctx); - + bool res = (isCipurseCChannelSecuritySet(&ctx) == false); - + CipurseCSetKey(&ctx, 1, Key); res = res && (memcmp(ctx.key, Key, 16) == 0); res = res && (ctx.keyId == 1); - + CipurseCSetRandomFromPICC(&ctx, TestRandom); res = res && (memcmp(ctx.RP, TestRandom, 16) == 0); res = res && (memcmp(ctx.rP, &TestRandom[16], 6) == 0); - + uint8_t hrandom[] = {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; CipurseCSetRandomHost(&ctx); res = res && (memcmp(ctx.RT, hrandom, 16) == 0); res = res && (memcmp(ctx.rT, &hrandom[16], 6) == 0); - + uint8_t authparams[16 + 16 + 6] = {0}; CipurseCAuthenticateHost(&ctx, authparams); - uint8_t aparamstest[] = {0x12, 0xAA, 0x79, 0xA9, 0x03, 0xC5, 0xB4, 0x6A, 0x27, 0x1B, 0x13, 0xAE, 0x02, 0x50, 0x1C, 0x99, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; + uint8_t aparamstest[] = {0x12, 0xAA, 0x79, 0xA9, 0x03, 0xC5, 0xB4, 0x6A, 0x27, 0x1B, 0x13, 0xAE, 0x02, 0x50, 0x1C, 0x99, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 + }; res = res && (memcmp(authparams, aparamstest, sizeof(authparams)) == 0); - + uint8_t ct[] = {0xBE, 0x10, 0x6B, 0xB9, 0xAD, 0x84, 0xBC, 0xE1, 0x9F, 0xAE, 0x0C, 0x62, 0xCC, 0xC7, 0x0D, 0x41}; res = res && CipurseCCheckCT(&ctx, ct); - + CipurseCChannelSetSecurityLevels(&ctx, CPSMACed, CPSMACed); res = res && (isCipurseCChannelSecuritySet(&ctx) == true); - + uint8_t framekey[] = {0xCF, 0x6F, 0x3A, 0x47, 0xFC, 0xAC, 0x8D, 0x38, 0x25, 0x75, 0x8B, 0xFC, 0x8B, 0x61, 0x68, 0xF3}; res = res && (memcmp(ctx.frameKey, framekey, sizeof(framekey)) == 0); @@ -200,7 +201,7 @@ static bool TestMAC(void) { uint8_t framekey4[] = {0xA0, 0x65, 0x1A, 0x62, 0x56, 0x5D, 0xD7, 0xC9, 0x32, 0xAE, 0x1D, 0xE0, 0xCF, 0x8D, 0xC1, 0xB9}; res = res && (memcmp(ctx.frameKey, framekey4, sizeof(framekey4)) == 0); - + if (res) PrintAndLogEx(INFO, "channel MAC...... " _GREEN_("passed")); else @@ -236,13 +237,15 @@ static bool TestEncDec(void) { res = res && (memcmp(dstdata, TestData, 16) == 0); CipurseCChannelEncrypt(&ctx, TestData, 16, dstdata, &dstdatalen); - uint8_t tested3[32] = {0x1E, 0x0C, 0xD1, 0xF5, 0x8E, 0x0B, 0xAE, 0xF0, 0x06, 0xC6, 0xED, 0x73, 0x3F, 0x8A, 0x87, 0xCF, - 0x36, 0xCC, 0xF2, 0xF4, 0x7D, 0x33, 0x50, 0xF1, 0x8E, 0xFF, 0xD1, 0x7D, 0x42, 0x88, 0xD5, 0xEE}; + uint8_t tested3[32] = {0x1E, 0x0C, 0xD1, 0xF5, 0x8E, 0x0B, 0xAE, 0xF0, 0x06, 0xC6, 0xED, 0x73, 0x3F, 0x8A, 0x87, 0xCF, + 0x36, 0xCC, 0xF2, 0xF4, 0x7D, 0x33, 0x50, 0xF1, 0x8E, 0xFF, 0xD1, 0x7D, 0x42, 0x88, 0xD5, 0xEE + }; res = res && (dstdatalen == 32); res = res && (memcmp(dstdata, tested3, 32) == 0); - uint8_t tested4[32] = {0xC0, 0x42, 0xDB, 0xD9, 0x53, 0xFF, 0x01, 0xE5, 0xCC, 0x49, 0x8C, 0x9C, 0xDA, 0x60, 0x73, 0xA7, - 0xE1, 0xEB, 0x14, 0x69, 0xF6, 0x39, 0xF3, 0xE1, 0x07, 0x03, 0x32, 0xF4, 0x27, 0xF9, 0x48, 0x3D}; + uint8_t tested4[32] = {0xC0, 0x42, 0xDB, 0xD9, 0x53, 0xFF, 0x01, 0xE5, 0xCC, 0x49, 0x8C, 0x9C, 0xDA, 0x60, 0x73, 0xA7, + 0xE1, 0xEB, 0x14, 0x69, 0xF6, 0x39, 0xF3, 0xE1, 0x07, 0x03, 0x32, 0xF4, 0x27, 0xF9, 0x48, 0x3D + }; CipurseCChannelDecrypt(&ctx, tested4, 32, dstdata, &dstdatalen); res = res && (dstdatalen == 16); res = res && (memcmp(dstdata, TestData, 16) == 0); @@ -276,7 +279,7 @@ static bool TestAPDU(void) { sAPDU dstAPDU = {0}; uint8_t dstdata[256] = {0}; size_t dstdatalen = 0; - + // MACED APDU srcAPDU.CLA = 0x00; srcAPDU.INS = 0x55; @@ -293,14 +296,14 @@ static bool TestAPDU(void) { res = res && (srcAPDU.P2 == dstAPDU.P2); res = res && (dstAPDU.Lc == sizeof(test1)); res = res && (memcmp(dstdata, test1, sizeof(test1)) == 0); - + uint16_t sw = 0; uint8_t test2[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x9D, 0x80, 0xE7, 0xE3, 0x34, 0xE9, 0x97, 0x82, 0xdd, 0xee}; CipurseCAPDURespDecode(&ctx, test2, sizeof(test2), dstdata, &dstdatalen, &sw); res = res && (dstdatalen == 6); res = res && (memcmp(test2, dstdata, dstdatalen) == 0); res = res && (sw == 0xddee); - + // Plain APDU CipurseCChannelSetSecurityLevels(&ctx, CPSPlain, CPSPlain); CipurseCAPDUReqEncode(&ctx, &srcAPDU, &dstAPDU, dstdata, true, 0x55); @@ -317,7 +320,7 @@ static bool TestAPDU(void) { res = res && (dstdatalen == 6); res = res && (memcmp(test4, dstdata, dstdatalen) == 0); res = res && (sw == 0xccdd); - + // Encrypted APDU CipurseCChannelSetSecurityLevels(&ctx, CPSEncrypted, CPSEncrypted); CipurseCAPDUReqEncode(&ctx, &srcAPDU, &dstAPDU, dstdata, true, 0x55); @@ -328,17 +331,17 @@ static bool TestAPDU(void) { res = res && (srcAPDU.P2 == dstAPDU.P2); res = res && (dstAPDU.Lc == sizeof(test5)); res = res && (memcmp(dstdata, test5, sizeof(test5)) == 0); - - uint8_t test6[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x7E, 0x4B, 0xA0, 0xB7, 0xcc, 0xdd}; + + uint8_t test6[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x7E, 0x4B, 0xA0, 0xB7, 0xcc, 0xdd}; //CipurseCChannelEncrypt(&ctx, test6, sizeof(test6), dstdata, &dstdatalen); //PrintAndLogEx(INFO, "dstdata[%d]: %s", dstdatalen, sprint_hex(dstdata, dstdatalen)); - + uint8_t test7[] = {0x07, 0xEF, 0x16, 0x91, 0xE7, 0x0F, 0xB5, 0x10, 0x63, 0xCE, 0x66, 0xDB, 0x3B, 0xC6, 0xD4, 0xE0, 0x90, 0x00}; CipurseCAPDURespDecode(&ctx, test7, sizeof(test7), dstdata, &dstdatalen, &sw); res = res && (dstdatalen == 8); res = res && (memcmp(test6, dstdata, dstdatalen) == 0); res = res && (sw == 0xccdd); - + if (res) PrintAndLogEx(INFO, "apdu............. " _GREEN_("passed")); else @@ -351,7 +354,7 @@ bool CIPURSETest(bool verbose) { bool res = true; PrintAndLogEx(INFO, "------ " _CYAN_("CIPURSE Tests") " ------"); - + res = res && TestKVV(); res = res && TestISO9797M2(); res = res && TestSMI(); @@ -366,7 +369,7 @@ bool CIPURSETest(bool verbose) { PrintAndLogEx(SUCCESS, " Tests [ %s ]", _GREEN_("ok")); else PrintAndLogEx(FAILED, " Tests [ %s ]", _RED_("fail")); - + PrintAndLogEx(NORMAL, ""); return res; } diff --git a/client/src/cipurse/cipursetest.h b/client/src/cipurse/cipursetest.h index 561539eae..1f69a3abc 100644 --- a/client/src/cipurse/cipursetest.h +++ b/client/src/cipurse/cipursetest.h @@ -17,4 +17,4 @@ bool CIPURSETest(bool verbose); -#endif /* __CIPURSETEST_H__ */ \ No newline at end of file +#endif /* __CIPURSETEST_H__ */ diff --git a/client/src/cmdhfcipurse.c b/client/src/cmdhfcipurse.c index 841181732..41dd9062d 100644 --- a/client/src/cmdhfcipurse.c +++ b/client/src/cmdhfcipurse.c @@ -700,7 +700,6 @@ bool CheckCardCipurse(void) { static int CmdHFCipurseTest(const char *Cmd) { CIPURSETest(true); - return PM3_SUCCESS; } diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 37120f29b..9d95834ca 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -247,7 +247,7 @@ static void print_config_cards(void) { static void print_config_card(const iclass_config_card_item_t *o) { if (check_config_card(o)) { - PrintAndLogEx(INFO, "description... " _YELLOW_("%s") , o->desc); + PrintAndLogEx(INFO, "description... " _YELLOW_("%s"), o->desc); PrintAndLogEx(INFO, "data.......... " _YELLOW_("%s"), sprint_hex_inrow(o->data, sizeof(o->data))); } } diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 36310e680..2608a29eb 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -984,7 +984,7 @@ static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rp // Part 4 // tag->session_key = &default_key; - struct desfire_key *p = realloc (tag->session_key,sizeof(struct desfire_key)); + struct desfire_key *p = realloc(tag->session_key, sizeof(struct desfire_key)); if (!p) { PrintAndLogEx(FAILED, "Cannot allocate memory for session keys"); free(tag->session_key); @@ -992,7 +992,7 @@ static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rp } tag->session_key = p; - memset (tag->session_key, 0x00, sizeof(struct desfire_key)); + memset(tag->session_key, 0x00, sizeof(struct desfire_key)); Desfire_session_key_new(RndA, RndB, key, tag->session_key); @@ -1030,7 +1030,7 @@ static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rp // If the 3Des key first 8 bytes = 2nd 8 Bytes then we are really using Singe Des // As such we need to set the session key such that the 2nd 8 bytes = 1st 8 Bytes if (payload->algo == MFDES_ALGO_3DES) { - if (memcmp(key->data,&key->data[8],8) == 0) + if (memcmp(key->data, &key->data[8], 8) == 0) memcpy(&tag->session_key->data[8], tag->session_key->data, 8); } @@ -1285,7 +1285,7 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n } else if (new_algo == MFDES_ALGO_3K3DES) { // 3K3Des checksum must cover : C4 csPkt[0] = MFDES_CHANGE_KEY; - memcpy (&csPkt[1], data, 25); + memcpy(&csPkt[1], data, 25); desfire_crc32(csPkt, 26, data + 1 + cmdcnt); } else { desfire_crc32_append(data + 1, cmdcnt); @@ -1309,10 +1309,10 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n csPkt[0] = MFDES_CHANGE_KEY; memcpy(&csPkt[1], data, 18); desfire_crc32(csPkt, 19, data + 1 + cmdcnt); - } else if (new_algo == MFDES_ALGO_3K3DES) { + } else if (new_algo == MFDES_ALGO_3K3DES) { // 3K3Des checksum must cover : C4 csPkt[0] = MFDES_CHANGE_KEY; - memcpy (&csPkt[1], data, 25); + memcpy(&csPkt[1], data, 25); desfire_crc32(csPkt, 26, data + 1 + cmdcnt); } else { desfire_crc32_append(data + 1, cmdcnt); @@ -1348,13 +1348,12 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n size_t sn = recv_len; - if ((new_algo == MFDES_ALGO_AES) || (new_algo == MFDES_ALGO_3K3DES)) - { + if ((new_algo == MFDES_ALGO_AES) || (new_algo == MFDES_ALGO_3K3DES)) { // AES expects us to Calculate CMAC for status byte : OK 0x00 (0x91 00) // As such if we get this far without an error, we should be good // Since we are dropping the field, we dont need to maintain the CMAC etc. // Setting sn = 1 will allow the post process to just exit (as status only) - + // Simular 3K3Des has some work to validate, but as long as the reply code was 00 // e.g. 02 fe ec 77 ca 13 e0 c2 06 [91 00 (OK)] 69 67 diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index 287f39f06..b6e2ccbef 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -278,7 +278,7 @@ static int CmdLFHitagEload(const char *Cmd) { if (dumplen == 48 || dumplen == 4 * 64) { lf_hitag_t *payload = calloc(1, sizeof(lf_hitag_t) + dumplen); - + if (use_ht1) payload->type = 1; if (use_ht2) diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 24a05825f..e3e785e6c 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -68,7 +68,7 @@ void des_decrypt(void *out, const void *in, const void *key) { void tdes_nxp_receive(const void *in, void *out, size_t length, const void *key, unsigned char iv[8], int keymode) { if (length % 8) return; - + mbedtls_des3_context ctx3; if (keymode == 2) mbedtls_des3_set2key_dec(&ctx3, key); @@ -98,7 +98,7 @@ void tdes_nxp_receive(const void *in, void *out, size_t length, const void *key, } void tdes_nxp_send(const void *in, void *out, size_t length, const void *key, unsigned char iv[8], int keymode) { - if (length % 8) + if (length % 8) return; mbedtls_des3_context ctx3; diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index 5285a4d94..cba4d5ac7 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -1059,7 +1059,7 @@ int mfG3GetBlock(uint8_t blockno, uint8_t *data) { payload.blockno = blockno; clearCommandBuffer(); - SendCommandNG(CMD_HF_MIFARE_G3_RDBL, (uint8_t*)&payload, sizeof(payload)); + SendCommandNG(CMD_HF_MIFARE_G3_RDBL, (uint8_t *)&payload, sizeof(payload)); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_HF_MIFARE_G3_RDBL, &resp, 1500)) { if (resp.status != PM3_SUCCESS) diff --git a/client/src/nfc/ndef.c b/client/src/nfc/ndef.c index 9c3c42330..ac131b221 100644 --- a/client/src/nfc/ndef.c +++ b/client/src/nfc/ndef.c @@ -437,7 +437,7 @@ static int ndefDecodePayloadDeviceInfo(uint8_t *payload, size_t len) { n = *(p++); //uuid string // record.uuid_string = '123e4567-e89b-12d3-a456-426655440000' - // 8-4-4-4-12 + // 8-4-4-4-12 char uuid[37] = {0}; sprintf(uuid, "%s-", sprint_hex_inrow(p, 4)); p += 4; @@ -451,7 +451,7 @@ static int ndefDecodePayloadDeviceInfo(uint8_t *payload, size_t len) { p += 6; PrintAndLogEx(INFO, "UUID.......... " _YELLOW_("%s"), uuid); p++; - n = *(p++); + n = *(p++); PrintAndLogEx(INFO, "Version....... " _YELLOW_("%.*s"), n, p); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; @@ -491,7 +491,7 @@ static int ndefDecodePayloadSmartPoster(uint8_t *ndef, size_t ndeflen, bool prin } // recursive if (NDEFHeader.MessageEnd == false) { - ndefDecodePayloadSmartPoster(ndef + NDEFHeader.RecLen, ndeflen - NDEFHeader.RecLen, false, false); + ndefDecodePayloadSmartPoster(ndef + NDEFHeader.RecLen, ndeflen - NDEFHeader.RecLen, false, false); } if (print) { @@ -518,41 +518,41 @@ static int ndefDecodeMime_vcard(NDEFHeader_t *ndef) { } static int ndefDecodeMime_bt(NDEFHeader_t *ndef) { - PrintAndLogEx(INFO, "Type............ " _YELLOW_("%.*s"), (int)ndef->TypeLen, ndef->Type ); + PrintAndLogEx(INFO, "Type............ " _YELLOW_("%.*s"), (int)ndef->TypeLen, ndef->Type); if (ndef->PayloadLen > 1) { uint16_t ooblen = (ndef->Payload[1] << 8 | ndef->Payload[0]); PrintAndLogEx(INFO, "OOB data len.... %u", ooblen); PrintAndLogEx(INFO, "BT MAC.......... " _YELLOW_("%s"), sprint_hex(ndef->Payload + 2, 6)); - // Let's check payload[8]. Tells us a bit about the UUID's. If 0x07 then it tells us a service UUID is 128bit - switch (ndef->Payload[8]) { - case 0x02: + // Let's check payload[8]. Tells us a bit about the UUID's. If 0x07 then it tells us a service UUID is 128bit + switch (ndef->Payload[8]) { + case 0x02: PrintAndLogEx(INFO, "Optional Data... incomplete list 16-bit UUID's"); - break; - case 0x03: + break; + case 0x03: PrintAndLogEx(INFO, "Optional Data... complete list 16-bit UUID's"); - break; - case 0x04: + break; + case 0x04: PrintAndLogEx(INFO, "Optional Data... incomplete list 32-bit UUID's"); - break; - case 0x05: + break; + case 0x05: PrintAndLogEx(INFO, "Optional Data... complete list 32-bit UUID's"); - break; - case 0x06: + break; + case 0x06: PrintAndLogEx(INFO, "Optional Data... incomplete list 128-bit UUID's"); - break; - case 0x07: + break; + case 0x07: PrintAndLogEx(INFO, "Optional Data... complete list 128-bit UUID's"); - break; - default: + break; + default: PrintAndLogEx(INFO, "Optional Data... [ %02x ]", ndef->Payload[8]); break; - } - // Let's check payload[9]. If 0x08 then SHORT_NAME or if 0x09 then COMPLETE_NAME - if (ndef->Payload[9] == 0x08 ) { + } + // Let's check payload[9]. If 0x08 then SHORT_NAME or if 0x09 then COMPLETE_NAME + if (ndef->Payload[9] == 0x08) { PrintAndLogEx(INFO, "Short name...... " _YELLOW_("%.*s"), (int)(ndef->PayloadLen - 10), ndef->Payload + 10); - } else if (ndef->Payload[9] == 0x09 ) { + } else if (ndef->Payload[9] == 0x09) { PrintAndLogEx(INFO, "Complete name... " _YELLOW_("%.*s"), (int)(ndef->PayloadLen - 10), ndef->Payload + 10); - } else { + } else { PrintAndLogEx(INFO, "[ %02x ]", ndef->Payload[9]); } PrintAndLogEx(NORMAL, ""); @@ -696,7 +696,7 @@ static int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { print_buffer(NDEFHeader.Payload, NDEFHeader.PayloadLen, 1); } if (NDEFHeader.TypeLen && NDEFHeader.PayloadLen) { - ndefDecodePayload(&NDEFHeader); + ndefDecodePayload(&NDEFHeader); } return PM3_SUCCESS; diff --git a/doc/commands.json b/doc/commands.json index 04f5535af..81575389d 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -973,7 +973,7 @@ }, "help": { "command": "help", - "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log e:\\proxspace\\pm3/.proxmark3/logs/log_20210618.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", + "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log /home/osboxes/.proxmark3/logs/log_20210624.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", "notes": [ "auto" ], @@ -1684,67 +1684,67 @@ }, "hf cipurse aread": { "command": "hf cipurse aread", - "description": "read file attributes by file id with key id and key", + "description": "read file attributes by file id with key id and key. if no key is supplied, default key of 737373...7373 will be used", "notes": [ - "hf cipurse aread -f 2ff7 -> authenticate with keyid=1 and key = 7373...7373 and read file attributes with id 2ff7", - "hf cipurse aread -n 2 -k 65656565656565656565656565656565 -f 2ff7 -> authenticate with specified key and read file attributes" + "hf cipurse aread --fid 2ff7 -> authenticate with keyid 1, read file attributes with id 2ff7", + "hf cipurse aread -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> authenticate keyid 2, read file attributes" ], "offline": false, "options": [ "-h, --help this help", "-a, --apdu show apdu requests and responses", "-v, --verbose show technical data", - "-n, --keyid key id", - "-k, --key key for authenticate", - "-f, --file file id", + "-n key id", + "-k, --key auth key", + "--fid file id", "--noauth read file attributes without authentication", "--sreq communication reader-picc security level", "--sresp communication picc-reader security level", "--sel-adf show info about adf itself", "--sel-mf show info about master file" ], - "usage": "hf cipurse aread [-hav] [-n ] [-k ] [-f ] [--noauth] [--sreq ] [--sresp ] [--sel-adf] [--sel-mf]" + "usage": "hf cipurse aread [-hav] [-n ] [-k ] [--fid ] [--noauth] [--sreq ] [--sresp ] [--sel-adf] [--sel-mf]" }, "hf cipurse auth": { "command": "hf cipurse auth", - "description": "authenticate with key id and key", + "description": "authenticate with key id and key. if no key is supplied, default key of 737373...7373 will be used", "notes": [ - "hf cipurse auth -> authenticate with keyid=1 and key = 7373...7373", - "hf cipurse auth -n 2 -k 65656565656565656565656565656565 -> authenticate with key" + "hf cipurse auth -> authenticate with keyid 1, default key", + "hf cipurse auth -n 2 -k 65656565656565656565656565656565 -> authenticate keyid 2 with key" ], "offline": false, "options": [ "-h, --help this help", "-a, --apdu show apdu requests and responses", "-v, --verbose show technical data", - "-n, --keyid key id", - "-k, --key key for authenticate" + "-n key id", + "-k, --key auth key" ], "usage": "hf cipurse auth [-hav] [-n ] [-k ]" }, "hf cipurse delete": { "command": "hf cipurse delete", - "description": "read file by file id with key id and key", + "description": "read file by file id with key id and key. if no key is supplied, default key of 737373...7373 will be used", "notes": [ - "hf cipurse delete -f 2ff7 -> authenticate with keyid=1 and key = 7373...7373 and delete file with id 2ff7", - "hf cipurse delete -n 2 -k 65656565656565656565656565656565 -f 2ff7 -> authenticate with specified key and delete file" + "hf cipurse delete --fid 2ff7 -> authenticate with keyid 1, delete file with id 2ff7", + "hf cipurse delete -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> authenticate keyid 2 and delete file" ], "offline": false, "options": [ "-h, --help this help", "-a, --apdu show apdu requests and responses", "-v, --verbose show technical data", - "-n, --keyid key id", - "-k, --key key for authenticate", - "-f, --file file id", + "-n key id", + "-k, --key auth key", + "--fid file id", "--sreq communication reader-picc security level", "--sresp communication picc-reader security level" ], - "usage": "hf cipurse delete [-hav] [-n ] [-k ] [-f ] [--sreq ] [--sresp ]" + "usage": "hf cipurse delete [-hav] [-n ] [-k ] [--fid ] [--sreq ] [--sresp ]" }, "hf cipurse help": { "command": "hf cipurse help", - "description": "help this help. --------------------------------------------------------------------------------------- hf cipurse info available offline: no get info from cipurse tags", + "description": "help this help. test tests --------------------------------------------------------------------------------------- hf cipurse info available offline: no get info from cipurse tags", "notes": [ "hf cipurse info" ], @@ -1756,48 +1756,63 @@ }, "hf cipurse read": { "command": "hf cipurse read", - "description": "read file by file id with key id and key", + "description": "read file by file id with key id and key. if no key is supplied, default key of 737373...7373 will be used", "notes": [ - "hf cipurse read -f 2ff7 -> authenticate with keyid=1 and key = 7373...7373 and read file with id 2ff7", - "hf cipurse read -n 2 -k 65656565656565656565656565656565 -f 2ff7 -> authenticate with specified key and read file" + "hf cipurse read --fid 2ff7 -> authenticate with keyid 1, read file with id 2ff7", + "hf cipurse read -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> authenticate keyid 2 and read file" ], "offline": false, "options": [ "-h, --help this help", "-a, --apdu show apdu requests and responses", "-v, --verbose show technical data", - "-n, --keyid key id", - "-k, --key key for authenticate", - "-f, --file file id", + "-n key id", + "-k, --key auth key", + "--fid file id", "-o, --offset offset for reading data from file", "--noauth read file without authentication", "--sreq communication reader-picc security level", "--sresp communication picc-reader security level" ], - "usage": "hf cipurse read [-hav] [-n ] [-k ] [-f ] [-o ] [--noauth] [--sreq ] [--sresp ]" + "usage": "hf cipurse read [-hav] [-n ] [-k ] [--fid ] [-o ] [--noauth] [--sreq ] [--sresp ]" + }, + "hf cipurse test": { + "command": "hf cipurse test", + "description": "[=] ------ cipurse tests ------ [=] kvv.............. passed [=] iso9797m2........ passed [=] smi.............. passed [=] mic.............. passed [=] auth............. passed [=] channel mac...... passed [=] channel encdec... passed [=] apdu............. passed [=] --------------------------- [+] tests [ ok ] ======================================================================================= hf epa { german identification card... } --------------------------------------------------------------------------------------- hf epa help available offline: yes help this help --------------------------------------------------------------------------------------- hf epa cnonces available offline: no tries to collect nonces when doing part of pace protocol.", + "notes": [ + "hf epa cnonces --size 4 --num 4 --delay 1" + ], + "offline": true, + "options": [ + "-h, --help this help", + "--size nonce size", + "--num number of nonces to collect", + "-d, --delay delay between attempts" + ], + "usage": "hf epa cnonces [-h] --size --num -d " }, "hf cipurse write": { "command": "hf cipurse write", - "description": "write file by file id with key id and key", + "description": "write file by file id with key id and key. if no key is supplied, default key of 737373...7373 will be used", "notes": [ - "hf cipurse write -f 2ff7 -> authenticate with keyid=1 and key = 7373...7373 and write file with id 2ff7", - "hf cipurse write -n 2 -k 65656565656565656565656565656565 -f 2ff7 -> authenticate with specified key and write file" + "hf cipurse write --fid 2ff7 -> authenticate with keyid 1, write file with id 2ff7", + "hf cipurse write -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> authenticate keyid 2 and write file" ], "offline": false, "options": [ "-h, --help this help", "-a, --apdu show apdu requests and responses", "-v, --verbose show technical data", - "-n, --keyid key id", - "-k, --key key for authenticate", - "-f, --file file id", + "-n key id", + "-k, --key auth key", + "--fid file id", "-o, --offset offset for reading data from file", "--noauth read file without authentication", "--sreq communication reader-picc security level", "--sresp communication picc-reader security level", - "-c, --content new file content" + "-d, --data hex data to write to new file" ], - "usage": "hf cipurse write [-hav] [-n ] [-k ] [-f ] [-o ] [--noauth] [--sreq ] [--sresp ] [-c ]" + "usage": "hf cipurse write [-hav] [-n ] [-k ] [--fid ] [-o ] [--noauth] [--sreq ] [--sresp ] [-d ]" }, "hf emrtd help": { "command": "hf emrtd help", @@ -1854,21 +1869,6 @@ ], "usage": "hf emrtd list [-h1fcrux] [--dict ]..." }, - "hf epa help": { - "command": "hf epa help", - "description": "help this help --------------------------------------------------------------------------------------- hf epa cnonces available offline: no tries to collect nonces when doing part of pace protocol.", - "notes": [ - "hf epa cnonces --size 4 --num 4 --delay 1" - ], - "offline": true, - "options": [ - "-h, --help this help", - "--size nonce size", - "--num number of nonces to collect", - "-d, --delay delay between attempts" - ], - "usage": "hf epa cnonces [-h] --size --num -d " - }, "hf epa preplay": { "command": "hf epa preplay", "description": "perform pace protocol by replaying given apdus", @@ -3491,9 +3491,9 @@ "hf mf fchk --2k -k ffffffffffff -> key recovery against mifare 2k", "hf mf fchk --4k -k ffffffffffff -> key recovery against mifare 4k", "hf mf fchk --1k -f mfc_default_keys.dic -> target 1k using default dictionary file", - "hf mf fchk --1k --emu -> target 1k, write to emulator memory", - "hf mf fchk --1k --dump -> target 1k, write to file", - "hf mf fchk --1k --mem -> target 1k, use dictionary from flashmemory" + "hf mf fchk --1k --emu -> target 1k, write keys to emulator memory", + "hf mf fchk --1k --dump -> target 1k, write keys to file", + "hf mf fchk --1k --mem -> target 1k, use dictionary from flash memory" ], "offline": false, "options": [ @@ -3553,6 +3553,23 @@ ], "usage": "hf mf gen3uid [-h] [-u ]" }, + "hf mf gview": { + "command": "hf mf gview", + "description": "view `magic gen3 gtu` card memory", + "notes": [ + "hf mf gview", + "hf mf gview --4k" + ], + "offline": false, + "options": [ + "-h, --help this help", + "--mini mifare classic mini / s20", + "--1k mifare classic 1k / s50 (def)", + "--2k mifare classic/plus 2k", + "--4k mifare classic 4k / s70" + ], + "usage": "hf mf gview [-h] [--mini] [--1k] [--2k] [--4k]" + }, "hf mf hardnested": { "command": "hf mf hardnested", "description": "nested attack for hardened mifare classic cards. `--i` set type of simd instructions. without this flag programs autodetect it. or hf mf hardnested -r --tk [known target key] add the known target key to check if it is present in the remaining key space hf mf hardnested --blk 0 -a -k a0a1a2a3a4a5 --tblk 4 --ta --tk ffffffffffff", @@ -4219,12 +4236,12 @@ ], "usage": "hf mfdes list [-h1fcrux] [--dict ]..." }, - "hf mfdes readdata": { - "command": "hf mfdes readdata", + "hf mfdes read": { + "command": "hf mfdes read", "description": "read data from file make sure to select aid or authenticate aid before running this command.", "notes": [ - "hf mfdes readdata -n 01 -t 0 -o 000000 -l 000000 -a 123456", - "hf mfdes readdata -n 01 -t 0 -> read all data from standard file, fileno 01" + "hf mfdes read -n 1 -t 0 -o 000000 -l 000000 -a 123456", + "hf mfdes read -n 1 -t 0 -> read all data from standard file, fileno 1" ], "offline": false, "options": [ @@ -4235,7 +4252,7 @@ "-t, --type file type (0 = standard / backup, 1 = record)", "-a, --aid app id to select (3 hex bytes, big endian)" ], - "usage": "hf mfdes readdata [-h] [-n ] [-o ]... [-l ]... [-t ] [-a ]..." + "usage": "hf mfdes read [-h] [-n ] [-o ]... [-l ]... [-t ] [-a ]..." }, "hf mfdes selectaid": { "command": "hf mfdes selectaid", @@ -4250,11 +4267,11 @@ ], "usage": "hf mfdes selectaid [-h] [-a ]..." }, - "hf mfdes writedata": { - "command": "hf mfdes writedata", + "hf mfdes write": { + "command": "hf mfdes write", "description": "write data to file make sure to select aid or authenticate aid before running this command.", "notes": [ - "hf mfdes writedata -n 01 -t 0 -o 000000 -d 3132333435363738" + "hf mfdes write -n 01 -t 0 -o 000000 -d 3132333435363738" ], "offline": false, "options": [ @@ -4265,7 +4282,7 @@ "-t, --type file type (0 = standard / backup, 1 = record)", "-a, --aid app id to select as hex bytes (3 bytes, big endian)" ], - "usage": "hf mfdes writedata [-h] [-n ] [-o ]... [-d ]... [-t ] [-a ]..." + "usage": "hf mfdes write [-h] [-n ] [-o ]... [-d ]... [-t ] [-a ]..." }, "hf mfp auth": { "command": "hf mfp auth", @@ -5061,8 +5078,8 @@ "command": "hw connect", "description": "connects to a proxmark3 device via specified serial port. baudrate here is only for physical uart or uart-bt, not for usb-cdc or blue shark add-on", "notes": [ - "hw connect -p com3", - "hw connect -p com3 -b 115200" + "hw connect -p /dev/ttyacm0", + "hw connect -p /dev/ttyacm0 -b 115200" ], "offline": true, "options": [ @@ -6441,17 +6458,18 @@ "command": "lf hitag help", "description": "help this help list list hitag trace history --------------------------------------------------------------------------------------- lf hitag eload available offline: no loads hitag tag dump into emulator memory on device", "notes": [ - "lf hitag eload -f lf-hitag-11223344-dump.bin" + "lf hitag eload -2 -f lf-hitag-11223344-dump.bin" ], "offline": true, "options": [ "-h, --help this help", "-f, --file filename of dump", - "-1 simulate hitag1", - "-2 simulate hitag2", - "-s simulate hitags" + "-1 card type hitag1", + "-2 card type hitag2", + "-s card type hitags", + "-m card type hitagm" ], - "usage": "lf hitag eload [-h12s] -f " + "usage": "lf hitag eload [-h12sm] -f " }, "lf hitag info": { "command": "lf hitag info", @@ -7586,7 +7604,7 @@ }, "lf sniff": { "command": "lf sniff", - "description": "sniff low frequency signal. - use `lf config` to set parameters. - use `data plot` to look at it", + "description": "sniff low frequency signal. you need to configure the lf part on the proxmark3 device manually. usually a trigger and skip samples is a good thing to set before doing a low frequency sniff. - use `lf config` to set parameters. - use `data plot` to look at sniff signal. - use `lf search -1` to see if signal can be automatic decoded", "notes": [ "lf sniff -v", "lf sniff -s 3000 -@ -> oscilloscope style" @@ -9179,8 +9197,8 @@ } }, "metadata": { - "commands_extracted": 570, + "commands_extracted": 571, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2021-06-18T09:04:45" + "extracted_on": "2021-06-24T16:45:08" } } \ No newline at end of file diff --git a/doc/commands.md b/doc/commands.md index 32f98bdef..a510cd5f4 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -241,12 +241,13 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- |`hf cipurse help `|Y |`This help.` -|`hf cipurse info `|N |`Info about Cipurse tag.` -|`hf cipurse auth `|N |`Authentication.` -|`hf cipurse read `|N |`Read binary file.` -|`hf cipurse write `|N |`Write binary file.` -|`hf cipurse aread `|N |`Read file attributes.` -|`hf cipurse delete `|N |`Delete file.` +|`hf cipurse info `|N |`Get info about CIPURSE tag` +|`hf cipurse auth `|N |`Authenticate CIPURSE tag` +|`hf cipurse read `|N |`Read binary file` +|`hf cipurse write `|N |`Write binary file` +|`hf cipurse aread `|N |`Read file attributes` +|`hf cipurse delete `|N |`Delete file` +|`hf cipurse test `|Y |`Tests` ### hf epa @@ -445,6 +446,7 @@ Check column "offline" for their availability. |`hf mf gen3uid `|N |`Set UID without changing manufacturer block` |`hf mf gen3blk `|N |`Overwrite manufacturer block` |`hf mf gen3freeze `|N |`Perma lock UID changes. irreversible` +|`hf mf gview `|N |`View card` ### hf mfp @@ -518,8 +520,8 @@ Check column "offline" for their availability. |`hf mfdes deletefile `|N |`Create Delete File` |`hf mfdes dump `|N |`Dump all files` |`hf mfdes getvalue `|N |`Get value of file` -|`hf mfdes readdata `|N |`Read data from standard/backup/record file` -|`hf mfdes writedata `|N |`Write data to standard/backup/record file` +|`hf mfdes read `|N |`Read data from standard/backup/record file` +|`hf mfdes write `|N |`Write data to standard/backup/record file` ### hf seos From 3b9da365a0d92c1ad3abc4cd997638db2771c364 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 24 Jun 2021 19:27:12 +0200 Subject: [PATCH 094/309] textual --- client/src/cmdlfem4x50.c | 66 ++++++++++++++++++++-------------------- doc/commands.json | 14 ++++----- doc/commands.md | 30 +++++++++--------- 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index 89ee9efb0..a0460ad3a 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -100,8 +100,6 @@ static void print_info_result(uint8_t *data, bool verbose) { PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------"); // data section - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, _YELLOW_("EM4x50 data:")); if (verbose) { print_result(words, 0, EM4X50_NO_WORDS - 1); } else { @@ -112,16 +110,16 @@ static void print_info_result(uint8_t *data, bool verbose) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "---- " _CYAN_("Configuration") " ----"); - PrintAndLogEx(INFO, "first word read %3i", fwr); - PrintAndLogEx(INFO, "last word read %3i", lwr); - PrintAndLogEx(INFO, "password check %3s", (bpwc) ? _RED_("on") : _GREEN_("off")); - PrintAndLogEx(INFO, "read after write %3s", (braw) ? "on" : "off"); + PrintAndLogEx(INFO, "first word read.... " _YELLOW_("%i"), fwr); + PrintAndLogEx(INFO, "last word read..... " _YELLOW_("%i"), lwr); + PrintAndLogEx(INFO, "password check..... %s", (bpwc) ? _RED_("on") : _GREEN_("off")); + PrintAndLogEx(INFO, "read after write... %s", (braw) ? "on" : "off"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--------- " _CYAN_("Protection") " ---------"); - PrintAndLogEx(INFO, "first word read protected %3i", fwrp); - PrintAndLogEx(INFO, "last word read protected %3i", lwrp); - PrintAndLogEx(INFO, "first word write inhibited %3i", fwwi); - PrintAndLogEx(INFO, "last word write inhibited %3i", lwwi); + PrintAndLogEx(INFO, "--------- " _CYAN_("Protection") " ------------"); + PrintAndLogEx(INFO, "first word read protected.... %i", fwrp); + PrintAndLogEx(INFO, "last word read protected..... %i", lwrp); + PrintAndLogEx(INFO, "first word write inhibited... %i", fwwi); + PrintAndLogEx(INFO, "last word write inhibited.... %i", lwwi); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "zero values may indicate read protection"); PrintAndLogEx(NORMAL, ""); @@ -364,9 +362,9 @@ int CmdEM4x50Login(const char *Cmd) { int CmdEM4x50Brute(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf em 4x50 brute", - "Tries to bruteforce the password of a EM4x50.\n" + "Tries to bruteforce the password of a EM4x50 card.\n" "Function can be stopped by pressing pm3 button.", - "lf em 4x50 brute --first 12330000 --last 12340000 -> tries pwds from 0x12330000 to 0x1234000000\n" + "lf em 4x50 brute --first 12330000 --last 12340000 -> tries pwds from 0x12330000 to 0x1234000000\n" ); void *argtable[] = { @@ -435,7 +433,7 @@ int CmdEM4x50Brute(const char *Cmd) { int CmdEM4x50Chk(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf em 4x50 chk", - "Dictionary attack against EM4x50.", + "Run dictionary key recovery against EM4x50 card.", "lf em 4x50 chk -> uses T55xx default dictionary\n" "lf em 4x50 chk -f my.dic" ); @@ -639,8 +637,8 @@ int CmdEM4x50Info(const char *Cmd) { CLIParserInit(&ctx, "lf em 4x50 info", "Tag information EM4x50.", "lf em 4x50 info\n" - "lf em 4x50 info -v -> show data section\n" - "lf em 4x50 info -p 12345678 -> uses pwd 0x12345678\n" + "lf em 4x50 info -v -> show data section\n" + "lf em 4x50 info -p 12345678 -> uses pwd 0x12345678\n" ); void *argtable[] = { @@ -908,9 +906,9 @@ int CmdEM4x50Write(const char *Cmd) { // envokes changing the password of EM4x50 tag int CmdEM4x50WritePwd(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "lf em 4x50 writepwd", + CLIParserInit(&ctx, "lf em 4x50 wrpwd", "Writes EM4x50 password.", - "lf em 4x50 writepwd -p 4f22e7ff -n 12345678" + "lf em 4x50 wrpwd -p 4f22e7ff -n 12345678" ); void *argtable[] = { @@ -1210,21 +1208,23 @@ int CmdEM4x50Sim(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"brute", CmdEM4x50Brute, IfPm3EM4x50, "guess password of EM4x50"}, - {"chk", CmdEM4x50Chk, IfPm3EM4x50, "check passwords from dictionary"}, - {"dump", CmdEM4x50Dump, IfPm3EM4x50, "dump EM4x50 tag"}, - {"info", CmdEM4x50Info, IfPm3EM4x50, "tag information EM4x50"}, - {"login", CmdEM4x50Login, IfPm3EM4x50, "login into EM4x50"}, - {"rdbl", CmdEM4x50Read, IfPm3EM4x50, "read word data from EM4x50"}, - {"wrbl", CmdEM4x50Write, IfPm3EM4x50, "write word data to EM4x50"}, - {"writepwd", CmdEM4x50WritePwd, IfPm3EM4x50, "change password of EM4x50"}, - {"wipe", CmdEM4x50Wipe, IfPm3EM4x50, "wipe EM4x50 tag"}, - {"reader", CmdEM4x50Reader, IfPm3EM4x50, "show standard read mode data of EM4x50"}, - {"restore", CmdEM4x50Restore, IfPm3EM4x50, "restore EM4x50 dump to tag"}, - {"sim", CmdEM4x50Sim, IfPm3EM4x50, "simulate EM4x50 tag"}, - {"eload", CmdEM4x50ELoad, IfPm3EM4x50, "upload dump of EM4x50 to emulator memory"}, - {"esave", CmdEM4x50ESave, IfPm3EM4x50, "save emulator memory to file"}, - {"eview", CmdEM4x50EView, IfPm3EM4x50, "view EM4x50 content in emulator memory"}, + {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("operations") " ---------------------"}, + {"brute", CmdEM4x50Brute, IfPm3EM4x50, "Simple bruteforce attack to find password"}, + {"chk", CmdEM4x50Chk, IfPm3EM4x50, "Check passwords from dictionary"}, + {"dump", CmdEM4x50Dump, IfPm3EM4x50, "Dump EM4x50 tag"}, + {"info", CmdEM4x50Info, IfPm3EM4x50, "Tag information"}, + {"login", CmdEM4x50Login, IfPm3EM4x50, "Login into EM4x50 tag"}, + {"rdbl", CmdEM4x50Read, IfPm3EM4x50, "Read EM4x50 word data"}, + {"reader", CmdEM4x50Reader, IfPm3EM4x50, "Show standard read mode data"}, + {"restore", CmdEM4x50Restore, IfPm3EM4x50, "Restore EM4x50 dump to tag"}, + {"wrbl", CmdEM4x50Write, IfPm3EM4x50, "Write EM4x50 word data"}, + {"wrpwd", CmdEM4x50WritePwd, IfPm3EM4x50, "Change EM4x50 password"}, + {"wipe", CmdEM4x50Wipe, IfPm3EM4x50, "Wipe EM4x50 tag"}, + {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("simulation") " ---------------------"}, + {"eload", CmdEM4x50ELoad, IfPm3EM4x50, "Upload EM4x50 dump to emulator memory"}, + {"esave", CmdEM4x50ESave, IfPm3EM4x50, "Save emulator memory to file"}, + {"eview", CmdEM4x50EView, IfPm3EM4x50, "View EM4x50 content in emulator memory"}, + {"sim", CmdEM4x50Sim, IfPm3EM4x50, "Simulate EM4x50 tag"}, {NULL, NULL, NULL, NULL} }; diff --git a/doc/commands.json b/doc/commands.json index 81575389d..2cb01b6e1 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -5778,7 +5778,7 @@ }, "lf em 4x50 chk": { "command": "lf em 4x50 chk", - "description": "dictionary attack against em4x50.", + "description": "run dictionary key recovery against em4x50 card.", "notes": [ "lf em 4x50 chk -> uses t55xx default dictionary", "lf em 4x50 chk -f my.dic" @@ -5848,7 +5848,7 @@ }, "lf em 4x50 help": { "command": "lf em 4x50 help", - "description": "help this help --------------------------------------------------------------------------------------- lf em 4x50 brute available offline: no tries to bruteforce the password of a em4x50. function can be stopped by pressing pm3 button.", + "description": "help this help ----------- --------------------- operations --------------------- ----------- --------------------- simulation --------------------- --------------------------------------------------------------------------------------- lf em 4x50 brute available offline: no tries to bruteforce the password of a em4x50 card. function can be stopped by pressing pm3 button.", "notes": [ "lf em 4x50 brute --first 12330000 --last 12340000 -> tries pwds from 0x12330000 to 0x1234000000" ], @@ -5979,11 +5979,11 @@ ], "usage": "lf em 4x50 wrbl [-h] -b -d [-p ]" }, - "lf em 4x50 writepwd": { - "command": "lf em 4x50 writepwd", + "lf em 4x50 wrpwd": { + "command": "lf em 4x50 wrpwd", "description": "writes em4x50 password.", "notes": [ - "lf em 4x50 writepwd -p 4f22e7ff -n 12345678" + "lf em 4x50 wrpwd -p 4f22e7ff -n 12345678" ], "offline": false, "options": [ @@ -5991,7 +5991,7 @@ "-p, --pwd password, 4 hex bytes, lsb", "-n, --new new password, 4 hex bytes, lsb" ], - "usage": "lf em 4x50 writepwd [-h] -p -n " + "usage": "lf em 4x50 wrpwd [-h] -p -n " }, "lf em 4x70 auth": { "command": "lf em 4x70 auth", @@ -9199,6 +9199,6 @@ "metadata": { "commands_extracted": 571, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2021-06-24T16:45:08" + "extracted_on": "2021-06-24T17:24:39" } } \ No newline at end of file diff --git a/doc/commands.md b/doc/commands.md index a510cd5f4..433b44e26 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -724,21 +724,21 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- |`lf em 4x50 help `|Y |`This help` -|`lf em 4x50 brute `|N |`guess password of EM4x50` -|`lf em 4x50 chk `|N |`check passwords from dictionary` -|`lf em 4x50 dump `|N |`dump EM4x50 tag` -|`lf em 4x50 info `|N |`tag information EM4x50` -|`lf em 4x50 login `|N |`login into EM4x50` -|`lf em 4x50 rdbl `|N |`read word data from EM4x50` -|`lf em 4x50 wrbl `|N |`write word data to EM4x50` -|`lf em 4x50 writepwd `|N |`change password of EM4x50` -|`lf em 4x50 wipe `|N |`wipe EM4x50 tag` -|`lf em 4x50 reader `|N |`show standard read mode data of EM4x50` -|`lf em 4x50 restore `|N |`restore EM4x50 dump to tag` -|`lf em 4x50 sim `|N |`simulate EM4x50 tag` -|`lf em 4x50 eload `|N |`upload dump of EM4x50 to emulator memory` -|`lf em 4x50 esave `|N |`save emulator memory to file` -|`lf em 4x50 eview `|N |`view EM4x50 content in emulator memory` +|`lf em 4x50 brute `|N |`Simple bruteforce attack to find password` +|`lf em 4x50 chk `|N |`Check passwords from dictionary` +|`lf em 4x50 dump `|N |`Dump EM4x50 tag` +|`lf em 4x50 info `|N |`Tag information` +|`lf em 4x50 login `|N |`Login into EM4x50 tag` +|`lf em 4x50 rdbl `|N |`Read EM4x50 word data` +|`lf em 4x50 reader `|N |`Show standard read mode data` +|`lf em 4x50 restore `|N |`Restore EM4x50 dump to tag` +|`lf em 4x50 wrbl `|N |`Write EM4x50 word data` +|`lf em 4x50 wrpwd `|N |`Change EM4x50 password` +|`lf em 4x50 wipe `|N |`Wipe EM4x50 tag` +|`lf em 4x50 eload `|N |`Upload EM4x50 dump to emulator memory` +|`lf em 4x50 esave `|N |`Save emulator memory to file` +|`lf em 4x50 eview `|N |`View EM4x50 content in emulator memory` +|`lf em 4x50 sim `|N |`Simulate EM4x50 tag` ### lf em 4x70 From cfd13e16e9a209a58eae2bf670f5d80ff0011afb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 24 Jun 2021 19:28:24 +0200 Subject: [PATCH 095/309] text --- doc/commands.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/commands.json b/doc/commands.json index 2cb01b6e1..571c53d13 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -9199,6 +9199,6 @@ "metadata": { "commands_extracted": 571, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2021-06-24T17:24:39" + "extracted_on": "2021-06-24T17:28:12" } } \ No newline at end of file From 3d663be25aa47211d91cd6b13f28ae4ed56c6049 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 24 Jun 2021 21:31:43 +0200 Subject: [PATCH 096/309] fix "lf hitag reader --23" - now allows 6bytes --- client/src/cmdlfhitag.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index b6e2ccbef..96cb8782f 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -570,8 +570,8 @@ static int CmdLFHitagReader(const char *Cmd) { } // sanity checks - if (keylen != 0 && keylen != 4) { - PrintAndLogEx(WARNING, "Wrong KEY len expected 0 or 4, got %d", keylen); + if (keylen != 0 && keylen != 4 && keylen != 6) { + PrintAndLogEx(WARNING, "Wrong KEY len expected 0,4 or 6, got %d", keylen); return PM3_EINVARG; } From d7421369ad1dfdfd815a811fc1f3c44bcf2e7982 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 09:43:39 +0200 Subject: [PATCH 097/309] text --- client/src/cmdlfhitag.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index 96cb8782f..50fcf1c24 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -571,7 +571,7 @@ static int CmdLFHitagReader(const char *Cmd) { // sanity checks if (keylen != 0 && keylen != 4 && keylen != 6) { - PrintAndLogEx(WARNING, "Wrong KEY len expected 0,4 or 6, got %d", keylen); + PrintAndLogEx(WARNING, "Wrong KEY len expected 0, 4 or 6, got %d", keylen); return PM3_EINVARG; } From 5f9f623627c6e78d13d0b7d08b8e9d66dfa109ab Mon Sep 17 00:00:00 2001 From: MaximeBosca Date: Fri, 25 Jun 2021 09:56:30 +0200 Subject: [PATCH 098/309] new clone --- client/src/cmdlfnexwatch.c | 88 +++++++++++++------------------------- 1 file changed, 29 insertions(+), 59 deletions(-) diff --git a/client/src/cmdlfnexwatch.c b/client/src/cmdlfnexwatch.c index 1d0f9cc28..3bb44402b 100644 --- a/client/src/cmdlfnexwatch.c +++ b/client/src/cmdlfnexwatch.c @@ -467,68 +467,38 @@ static int CmdNexWatchClone(const char *Cmd) { char cardtype[16] = {"T55x7"}; uint32_t blocks[4]; - if (use_psk2) { - uint32_t scrambled; - nexwatch_scamble(SCRAMBLE, &cn, &scrambled); - num_to_bytes(scrambled, 4, raw + 5); - PrintAndLogEx(SUCCESS, "Scrambled : %u", scrambled); - blocks[0] = 270464; - raw[0] = 0xFA; - uint8_t *byteId = convertUint32toByte(scrambled); - uint8_t newmode[4] = "0001"; - uint8_t idAndMode[36]; - memcpy(idAndMode, byteId, 32 * sizeof(uint8_t)); - memcpy(&idAndMode[32], newmode, 4 * sizeof(uint8_t)); - uint8_t *newparity = parity(idAndMode); - uint8_t par = bin2int(newparity, 4); - uint8_t checksum = nexwatch_checksum(magic, cn, par); - printf("\x1b[1;92m[+]\x1b[0m Checksum : %s --> %u\n", convertUint8toByte(checksum), checksum); - uint8_t Psk_card[128]; - uint8_t Psk2_card[128]; - memcpy(Psk_card, "00000000000000000000000000000000", 32 * sizeof(uint8_t)); - memcpy(&Psk_card[32], "0101011000000000000000000000000000000000", 40 * sizeof(uint8_t)); - memcpy(&Psk_card[72], byteId, 32 * sizeof(uint8_t)); - memcpy(&Psk_card[104], newmode, 4 * sizeof(uint8_t)); - memcpy(&Psk_card[108], newparity, 4 * sizeof(uint8_t)); - memcpy(&Psk_card[112], convertUint8toByte(checksum), 8 * sizeof(uint8_t)); - memcpy(&Psk_card[120], "00000000", 8 * sizeof(uint8_t)); - TOpsk2(Psk_card, 128); - memcpy(&Psk2_card[31], &Psk_card[32], 96 * sizeof(uint8_t)); - Psk2_card[127] = '0'; - memcpy(Psk2_card, "00000000000001000010000010000000", 32 * sizeof(uint8_t)); - blocks[0] = bin2int(&Psk2_card[0], 32); - blocks[1] = bin2int(&Psk2_card[32], 32); - blocks[2] = bin2int(&Psk2_card[64], 32); - blocks[3] = bin2int(&Psk2_card[96], 32); - } else { - //Nexwatch - compat mode, PSK, data rate 40, 3 data blocks - blocks[0] = T55x7_MODULATION_PSK1 | T55x7_BITRATE_RF_16 | 3 << T55x7_MAXBLOCK_SHIFT; - // Q5 - if (q5) { - blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT; - snprintf(cardtype, sizeof(cardtype), "Q5/T5555"); - } + //Nexwatch - compat mode, PSK, data rate 40, 3 data blocks + blocks[0] = T55x7_MODULATION_PSK1 | T55x7_BITRATE_RF_16 | 3 << T55x7_MAXBLOCK_SHIFT; - // EM4305 - if (em) { - blocks[0] = EM4305_NEXWATCH_CONFIG_BLOCK; - snprintf(cardtype, sizeof(cardtype), "EM4305/4469"); - } - - if (use_raw == false) { - uint8_t parity = nexwatch_parity(raw + 5) & 0xF; - raw[9] |= parity; - raw[10] |= nexwatch_checksum(magic, cn, parity); - } - - if (use_unk) - magic = 0x86; - - for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) { - blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t)); - } + // Q5 + if (q5) { + blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT; + snprintf(cardtype, sizeof(cardtype), "Q5/T5555"); } + + // EM4305 + if (em) { + blocks[0] = EM4305_NEXWATCH_CONFIG_BLOCK; + snprintf(cardtype, sizeof(cardtype), "EM4305/4469"); + } + + if (use_raw == false) { + uint8_t parity = nexwatch_parity(raw + 5) & 0xF; + raw[9] |= parity; + raw[10] |= nexwatch_checksum(magic, cn, parity); + } + + if (use_psk2) { + blocks[0] = 270464; + psk1TOpsk2(raw, 12); + } + + + for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) { + blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t)); + } + PrintAndLogEx(INFO, "Preparing to clone NexWatch to " _YELLOW_("%s") " raw " _YELLOW_("%s"), cardtype, sprint_hex_inrow(raw, sizeof(raw))); print_blocks(blocks, ARRAYLEN(blocks)); From fc822109deaaf3b1fa41197cd6c745273e71e8b7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 10:02:30 +0200 Subject: [PATCH 099/309] unifiy file name param / textual --- client/src/cmdhfcryptorf.c | 4 ++-- client/src/cmdhflegic.c | 4 ++-- client/src/cmdhflto.c | 2 +- client/src/cmdhfmf.c | 4 ++-- client/src/cmdlfem4x50.c | 26 +++++++++++++++++--------- client/src/cmdlfhitag.c | 2 +- client/src/cmdlft55xx.c | 2 +- 7 files changed, 26 insertions(+), 18 deletions(-) diff --git a/client/src/cmdhfcryptorf.c b/client/src/cmdhfcryptorf.c index bbfb00c0e..412fc4421 100644 --- a/client/src/cmdhfcryptorf.c +++ b/client/src/cmdhfcryptorf.c @@ -260,7 +260,7 @@ static int CmdHFCryptoRFDump(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "filename to save dump to"), + arg_str0("f", "file", "", "filename to save dump to"), arg_lit0(NULL, "64", "64byte / 512bit memory"), arg_lit0(NULL, "512", "512byte / 4096bit memory"), arg_param_end @@ -486,7 +486,7 @@ static int CmdHFCryptoRFESave(const char *Cmd) { ); void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "filename of dumpfile"), + arg_str0("f", "file", "", "filename of dumpfile"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); diff --git a/client/src/cmdhflegic.c b/client/src/cmdhflegic.c index c1ada36a3..3e079cbb4 100644 --- a/client/src/cmdhflegic.c +++ b/client/src/cmdhflegic.c @@ -762,7 +762,7 @@ static int CmdLegicDump(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "specify a filename for dump file"), + arg_str0("f", "file", "", "specify a filename for dump file"), arg_lit0(NULL, "de", "deobfuscate dump data (xor with MCC)"), arg_param_end }; @@ -1032,7 +1032,7 @@ static int CmdLegicESave(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "Specify a filename to save"), + arg_str0("f", "file", "", "Specify a filename to save"), arg_int0("t", "type", "", "Tag type"), arg_lit0(NULL, "deobfuscate", "De-obfuscate dump data (xor with MCC)"), arg_param_end diff --git a/client/src/cmdhflto.c b/client/src/cmdhflto.c index 2ea818b0b..727da2548 100644 --- a/client/src/cmdhflto.c +++ b/client/src/cmdhflto.c @@ -650,7 +650,7 @@ static int CmdHfLTODump(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "specify a filename for dumpfile"), + arg_str0("f", "file", "", "specify a filename for dumpfile"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index bcb9c52c2..ace8d2d0b 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -2885,7 +2885,7 @@ static int CmdHF14AMfChk(const char *Cmd) { arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"), arg_lit0(NULL, "emu", "Fill simulator keys from found keys"), arg_lit0(NULL, "dump", "Dump found keys to binary file"), - arg_str0("f", "file", "", "filename of dictionary"), + arg_str0("f", "file", "", "filename of dictionary"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -5031,7 +5031,7 @@ static int CmdHF14AMfice(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "filename of nonce dump"), + arg_str0("f", "file", "", "filename of nonce dump"), arg_u64_0(NULL, "limit", "", "nonces to be collected"), arg_param_end }; diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index a0460ad3a..7ecf281bc 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -14,6 +14,7 @@ #include "cmdlfem4x50.h" #include #include "cmdparser.h" // command_t +#include "util_posix.h" // msclock #include "fileutils.h" #include "commonutil.h" #include "pmflash.h" @@ -236,7 +237,7 @@ int CmdEM4x50ESave(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "filename", "", "data filename"), + arg_str0("f", "file", "", "save filename"), arg_param_end }; @@ -406,12 +407,12 @@ int CmdEM4x50Brute(const char *Cmd) { int dur_m = (dur_s - dur_h * 3600) / 60; dur_s -= dur_h * 3600 + dur_m * 60; - PrintAndLogEx(INFO, "Trying %i passwords in range [0x%08x, 0x%08x]" + PrintAndLogEx(INFO, "Trying " _YELLOW_("%i") " passwords in range [0x%08x, 0x%08x]" , no_iter , etd.password1 , etd.password2 ); - PrintAndLogEx(INFO, "Estimated duration: %ih%im%is", dur_h, dur_m, dur_s); + PrintAndLogEx(INFO, "Estimated duration: %ih %im %is", dur_h, dur_m, dur_s); // start clearCommandBuffer(); @@ -421,9 +422,9 @@ int CmdEM4x50Brute(const char *Cmd) { // print response if (resp.status == PM3_SUCCESS) - PrintAndLogEx(SUCCESS, "Password " _GREEN_("found") ": 0x%08x", resp.data.asDwords[0]); + PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", resp.data.asDwords[0]); else - PrintAndLogEx(FAILED, "Password: " _RED_("not found")); + PrintAndLogEx(WARNING, "brute pwd failed"); return PM3_SUCCESS; } @@ -440,7 +441,7 @@ int CmdEM4x50Chk(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "filename", "", "dictionary filename"), + arg_str0("f", "file", "", "dictionary filename"), arg_param_end }; @@ -461,6 +462,8 @@ int CmdEM4x50Chk(const char *Cmd) { PrintAndLogEx(INFO, "treating file as T55xx keys"); } + uint64_t t1 = msclock(); + size_t datalen = 0; // 2021 iceman: how many keys shall we reserv space for? The t55xx dictionary has 139 keys. @@ -508,17 +511,22 @@ int CmdEM4x50Chk(const char *Cmd) { // print response if (status == PM3_SUCCESS) { + /* PrintAndLogEx(SUCCESS, "Key " _GREEN_("found: %02x %02x %02x %02x"), resp.data.asBytes[3], resp.data.asBytes[2], resp.data.asBytes[1], resp.data.asBytes[0] ); + */ + uint32_t pwd = BYTES2UINT32(resp.data.asBytes); + PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", pwd); } else { PrintAndLogEx(FAILED, "No key found"); } - PrintAndLogEx(INFO, "Done"); + t1 = msclock() - t1; + PrintAndLogEx(SUCCESS, "\ntime in check pwd " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0); return PM3_SUCCESS; } @@ -750,7 +758,7 @@ int CmdEM4x50Dump(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "filename", "", "dump filename (bin/eml/json)"), + arg_str0("f", "file", "", "dump filename (bin/eml/json)"), arg_str0("p", "pwd", "", "password, 4 hex bytes, lsb"), arg_param_end }; @@ -1061,7 +1069,7 @@ int CmdEM4x50Restore(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0("u", "uid", "", "uid, 4 hex bytes, msb"), - arg_str0("f", "filename", "", "dump filename (bin/eml/json)"), + arg_str0("f", "file", "", "dump filename (bin/eml/json)"), arg_str0("p", "pwd", "", "password, 4 hex bytes, lsb"), arg_param_end }; diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index 50fcf1c24..c90637b6c 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -657,7 +657,7 @@ static int CmdLFHitagCheckChallenges(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "filename", "", "filename to load from"), + arg_str0("f", "file", "", "filename to load ( w/o ext )"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index e7ae82ed3..254149756 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -2210,7 +2210,7 @@ static int CmdT55xxDump(const char *Cmd) { // 1 (help) + 3 (two user specified params) + (5 T55XX_DLMODE_SINGLE) void *argtable[4 + 5] = { arg_param_begin, - arg_str0("f", "filename", "", "filename (default is generated on blk 0)"), + arg_str0("f", "file", "", "filename (default is generated on blk 0)"), arg_lit0("o", "override", "override, force pwd read despite danger to card"), arg_str0("p", "pwd", "", "password (4 hex bytes)"), }; From 0747abfe0f99f6c7ca94e1741b06c6173b8ad40f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 10:03:14 +0200 Subject: [PATCH 100/309] lf em 4x05 brute/chk - fixes input arguments, unify file name text --- client/src/cmdlfem4x05.c | 41 +++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index 781244164..f8074f8b4 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -1319,13 +1319,13 @@ int CmdEM4x05Chk(const char *Cmd) { CLIParserInit(&ctx, "lf em 4x05 chk", "This command uses a dictionary attack against EM4205/4305/4469/4569", "lf em 4x05 chk\n" - "lf em 4x05 chk -e 000022B8 -> remember to use 0x for hex\n" + "lf em 4x05 chk -e 000022B8 -> check password 000022B8\n" "lf em 4x05 chk -f t55xx_default_pwds -> use T55xx default dictionary" ); void *argtable[] = { arg_param_begin, - arg_strx0("f", "file", "<*.dic>", "loads a default keys dictionary file <*.dic>"), + arg_str0("f", "file", "", "loads a default keys dictionary file <*.dic>"), arg_str0("e", "em", "", "try the calculated password from some cloners based on EM4100 ID"), arg_param_end }; @@ -1334,7 +1334,18 @@ int CmdEM4x05Chk(const char *Cmd) { char filename[FILE_PATH_SIZE] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); - uint64_t card_id = arg_get_u64_hexstr_def(ctx, 2, 0); + uint64_t card_id = 0; + int res = arg_get_u64_hexstr_def_nlen(ctx, 2, 0, &card_id, 5, true); + if (res == 2) { + CLIParserFree(ctx); + PrintAndLogEx(WARNING, "EM4100 ID must be 5 hex bytes"); + return PM3_EINVARG; + } + if (res == 0) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + CLIParserFree(ctx); if (strlen(filename) == 0) { @@ -1418,22 +1429,30 @@ int CmdEM4x05Chk(const char *Cmd) { int CmdEM4x05Brute(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf em 4x05 brute", - "This command tries to bruteforce the password of a EM4205/4305/4469/4569\n", + "This command tries to bruteforce the password of a EM4205/4305/4469/4569\n" + "The loop is running on device side, press Proxmark3 button to abort\n", "Note: if you get many false positives, change position on the antenna" "lf em 4x05 brute\n" - "lf em 4x05 brute -n 1 -> stop after first candidate found\n" - "lf em 4x05 brute -s 000022B8 -> remember to use 0x for hex" + "lf em 4x05 brute -n 1 -> stop after first candidate found\n" + "lf em 4x05 brute -s 000022AA -> start at 000022AA" ); void *argtable[] = { arg_param_begin, - arg_u64_0("s", "start", "", "Start bruteforce enumeration from this password value"), - arg_int0("n", NULL, "", "Stop after having found n candidates. Default: 0 => infinite"), + arg_str0("s", "start", "", "Start bruteforce enumeration from this password value"), + arg_u64_0("n", NULL, "", "Stop after having found n candidates. Default: 0 (infinite)"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - uint32_t start_pwd = arg_get_u64_hexstr_def(ctx, 1, 0); - uint32_t n = arg_get_int_def(ctx, 2, 0); + uint32_t start_pwd = 0; + int res = arg_get_u32_hexstr_def(ctx, 1, 0, &start_pwd); + if (res != 1) { + CLIParserFree(ctx); + PrintAndLogEx(WARNING, "check `start_pwd` parameter"); + return PM3_EINVARG; + } + + uint32_t n = arg_get_u32_def(ctx, 2, 0); CLIParserFree(ctx); PrintAndLogEx(NORMAL, ""); @@ -1449,7 +1468,7 @@ int CmdEM4x05Brute(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_LF_EM4X_BF, (uint8_t *)&payload, sizeof(payload)); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_LF_EM4X_BF, &resp, 1000)) { + if (WaitForResponseTimeout(CMD_LF_EM4X_BF, &resp, 1000) == false) { PrintAndLogEx(WARNING, "(EM4x05 Bruteforce) timeout while waiting for reply."); return PM3_ETIMEOUT; } From b1e361619f9658b3a440d32676b56ffe9199b2a2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 10:04:29 +0200 Subject: [PATCH 101/309] fix shadow --- client/src/cmdlfem4x05.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index f8074f8b4..c9a25ac2d 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -1377,7 +1377,7 @@ int CmdEM4x05Chk(const char *Cmd) { uint32_t keycount = 0; - int res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock, 4, &keycount); + res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock, 4, &keycount); if (res != PM3_SUCCESS || keycount == 0 || keyBlock == NULL) { PrintAndLogEx(WARNING, "no keys found in file"); if (keyBlock != NULL) From 4b2ab94b26c277eedc212a36cca53005ea6112c5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 10:34:12 +0200 Subject: [PATCH 102/309] hw setmux - improved user feedback --- client/src/cmdhw.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhw.c b/client/src/cmdhw.c index eed42dff5..d475ba76e 100644 --- a/client/src/cmdhw.c +++ b/client/src/cmdhw.c @@ -539,7 +539,7 @@ static int CmdSetMux(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hw setmux", "Set the ADC mux to a specific value", - "hw setmux --hiraw -> set HIGH RAW" + "hw setmux --hipkd -> set HIGH PEAK\n" ); void *argtable[] = { @@ -562,6 +562,13 @@ static int CmdSetMux(const char *Cmd) { return PM3_EINVARG; } +#ifdef WITH_FPC_USART + if (loraw || hiraw) { + PrintAndLogEx(INFO, "this ADC mux option is unavailable on RDV4 compiled with FPC USART"); + return PM3_EINVARG; + } +#endif + uint8_t arg = 0; if (lopkd) arg = 0; From a859597f33dcb6d01ba69661b898a51e39959d2e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 10:37:43 +0200 Subject: [PATCH 103/309] text --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d13cad28..1532b044b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Changed `hw setmux` - improve user feedback for special case (@iceman1001) + - Changed 'filename' - unified file name param across client (@iceman1001) + - Fix `lf em 4x05 brute/chk` - fixed input params crash (@iceman1001) + - Fix `lf hitag reader --23` - now accepts 6bytes key (@iceman1001) + - Fix coverity scans findigs (@merlokk, @iceman1001) - Fix `hf iclass config` - now fallback to default config card configuration (@iceman1001) - Changed `nfc parser` - now also identify xvcard types (@iceman1001) - Added `hf mf gview` - view contents of a magic Gen3 GTU (@iceman1001) From cbc8d9144773b25d5459d2d9b47cdab5f4de57f5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 11:27:41 +0200 Subject: [PATCH 104/309] text - updated link to libera irc --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4ef8f7de0..d5a7ea055 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ The [public roadmap](https://github.com/RfidResearchGroup/proxmark3/wiki/Public- ## Supported operative systems This repo compiles nicely on - WSL1 on Windows 10 - - Proxspace v3.9 [release v3.9](https://github.com/Gator96100/ProxSpace/releases) + - Proxspace enviroment [release v3.9](https://github.com/Gator96100/ProxSpace/releases) - Windows/MinGW environment - Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, NetHunter, Arch Linux, Fedora, Debian, Raspbian - Android / Termux @@ -155,7 +155,7 @@ We don't maintain any precompiled binaries in this repo. There is community effo ## Official channels Where do you find the community? - [RFID Hacking community discord server](https://discord.gg/QfPvGFRQxH) - - [Proxmark3 IRC channel](http://webchat.freenode.net/?channels=#proxmark3) + - [Proxmark3 IRC channel](https://web.libera.chat/?channels=#proxmark3) - [Proxmark3 sub reddit](https://www.reddit.com/r/proxmark3/) - [Proxmark3 forum](http://www.proxmark.org/forum/index.php) From e33f2a76aa7b10ce9230cb6f0669acae22158bf7 Mon Sep 17 00:00:00 2001 From: rioux Date: Fri, 25 Jun 2021 12:00:29 +0200 Subject: [PATCH 105/309] lf nexwatch with psk2 --- client/src/cmdlfnexwatch.c | 87 +++----------------------------------- common/lfdemod.c | 11 +++++ common/lfdemod.h | 2 + 3 files changed, 20 insertions(+), 80 deletions(-) diff --git a/client/src/cmdlfnexwatch.c b/client/src/cmdlfnexwatch.c index 3bb44402b..3ad4e1183 100644 --- a/client/src/cmdlfnexwatch.c +++ b/client/src/cmdlfnexwatch.c @@ -279,90 +279,12 @@ static int CmdNexWatchReader(const char *Cmd) { } do { - lf_read(true, 20000); + lf_read(false, 20000); demodNexWatch(!cm); } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } -//TOCHANGE -static unsigned int bin2int(unsigned char *b, int size) { - unsigned int val = 0; - for (int i = 0; i < size; i++) { - if (b[i] == '1') { - val += pow(2, size - 1 - i); - } - } - return val; -} -static uint8_t xor_parity(uint8_t *stream_, int bit_number) { - uint8_t parity_res = '0'; - for (int i = bit_number - 1; i < 36; i += 4) { - if (stream_[i] == parity_res) { - parity_res = '0'; - } else { - parity_res = '1'; - } - } - return parity_res; -} - -static uint8_t *parity(uint8_t *stream_) { - uint8_t *parity_res = malloc(4 * sizeof(uint8_t)); - parity_res[0] = xor_parity(stream_, 4); - parity_res[1] = xor_parity(stream_, 2); - parity_res[2] = xor_parity(stream_, 3); - parity_res[3] = xor_parity(stream_, 1); - return parity_res; -} - -static uint8_t *convertUint8toByte(uint8_t number) { - uint8_t *res = malloc(8 * sizeof(char)); - uint8_t temp = number; - for (int i = 1; i < 9; i++) { - if (temp % 2) { - res[8 - i] = '1'; - } else { - res[8 - i] = '0'; - } - temp = temp / 2; - } - return res; -} - -static uint8_t *convertUint32toByte(uint32_t number) { - uint8_t *res = malloc(32 * sizeof(char)); - uint32_t temp = number; - for (int i = 0; i < 32; i++) { - res[i] = '0'; - } - for (int i = 1; i < 33; i++) { - if (temp % 2) { - res[32 - i] = '1'; - } else { - res[32 - i] = '0'; - } - temp = temp / 2; - } - return res; -} - - -static void TOpsk2(uint8_t *bits, size_t size) { - uint8_t lastbit = '0'; - for (size_t i = 1; i < size; i++) { - //ignore errors - if (bits[i] == 7) continue; - - if (lastbit != bits[i]) { - lastbit = bits[i]; - bits[i] = '1'; - } else { - bits[i] = '0'; - } - } -} -//ENDTOCHANGE static int CmdNexWatchClone(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf nexwatch clone", @@ -491,7 +413,12 @@ static int CmdNexWatchClone(const char *Cmd) { if (use_psk2) { blocks[0] = 270464; - psk1TOpsk2(raw, 12); + uint8_t * res_shifted = malloc(96 * sizeof(uint8_t)); + uint8_t * res = byte_to_bytebits(raw, 12); + psk1TOpsk2(res, 96); + memcpy(res_shifted, &res[1], 95 * sizeof(uint8_t)); + res_shifted[95] = 0; + bits_to_array(res_shifted, 96, raw); } diff --git a/common/lfdemod.c b/common/lfdemod.c index 3c32834f6..350944314 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -295,6 +295,17 @@ int bits_to_array(const uint8_t *bits, size_t size, uint8_t *dest) { return PM3_SUCCESS; } +// Ex: 0x56 and numbytes = 1 ==> return res = {0,1,0,1,0,1,1,0} +uint8_t * byte_to_bytebits(uint8_t * bits, size_t numbytes){ + uint8_t * result = malloc(numbytes * 8 * (sizeof(uint8_t))); + for(int i=0;i Date: Fri, 25 Jun 2021 12:09:40 +0200 Subject: [PATCH 106/309] lf nexwatch with psk2 --- client/src/cmdlfnexwatch.c | 12 ++++-------- common/lfdemod.h | 1 - 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/client/src/cmdlfnexwatch.c b/client/src/cmdlfnexwatch.c index 3ad4e1183..a32a00a8c 100644 --- a/client/src/cmdlfnexwatch.c +++ b/client/src/cmdlfnexwatch.c @@ -24,7 +24,6 @@ #include "cmdlft55xx.h" // clone.. #include "cmdlfem4x05.h" // #include "cliparser.h" -#include typedef enum { @@ -54,7 +53,7 @@ static uint8_t nexwatch_parity(uint8_t hexid[5]) { } /// NETWATCH checksum -/// @param magic = 0xBE Quadrakey, 0x88 Nexkey, 0x86 EC +/// @param magic = 0xBE Quadrakey, 0x88 Nexkey, 0x86 Honeywell /// @param id = descrambled id (printed card number) /// @param parity = the parity based upon the scrambled raw id. static uint8_t nexwatch_checksum(uint8_t magic, uint32_t id, uint8_t parity) { @@ -155,7 +154,6 @@ int demodNexWatch(bool verbose) { idx += 4; setDemodBuff(DemodBuffer, size, idx); - PrintAndLogEx(SUCCESS, "Indice: %x %s", DemodBuffer, DemodBuffer); setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock)); if (invert) { @@ -225,9 +223,8 @@ int demodNexWatch(bool verbose) { } else { nexwatch_magic_bruteforce(cn, calc_parity, chk); } - PrintAndLogEx(SUCCESS, " mode : %x", mode); PrintAndLogEx(SUCCESS, " 88bit id : " _YELLOW_("%"PRIu32) " (" _YELLOW_("0x%08"PRIx32)")", cn, cn); - PrintAndLogEx(SUCCESS, " Scambled : " _YELLOW_("%"PRIu32) " (" _YELLOW_("0x%08"PRIx32)")", scambled, scambled); + PrintAndLogEx(SUCCESS, " mode : %x", mode); if (parity == calc_parity) { @@ -360,7 +357,6 @@ static int CmdNexWatchClone(const char *Cmd) { uint32_t scrambled; nexwatch_scamble(SCRAMBLE, &cn, &scrambled); num_to_bytes(scrambled, 4, raw + 5); - PrintAndLogEx(SUCCESS, "Scrambled : %u", scrambled); } if (mode != -1) { @@ -387,11 +383,11 @@ static int CmdNexWatchClone(const char *Cmd) { } PrintAndLogEx(INFO, "Magic byte selected : 0x%X", magic); - char cardtype[16] = {"T55x7"}; uint32_t blocks[4]; //Nexwatch - compat mode, PSK, data rate 40, 3 data blocks - blocks[0] = T55x7_MODULATION_PSK1 | T55x7_BITRATE_RF_16 | 3 << T55x7_MAXBLOCK_SHIFT; + blocks[0] = T55x7_MODULATION_PSK1 | T55x7_BITRATE_RF_32 | 3 << T55x7_MAXBLOCK_SHIFT; + char cardtype[16] = {"T55x7"}; // Q5 if (q5) { diff --git a/common/lfdemod.h b/common/lfdemod.h index e8fc57746..4ead8b9e4 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -81,5 +81,4 @@ int Em410xDecode(uint8_t *bits, size_t *size, size_t *start_idx, uint32_t *hi, u int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx); int detectIOProx(uint8_t *dest, size_t *size, int *waveStartIdx); - #endif From 22add5e108f163ea39a87062bd88124508cd2766 Mon Sep 17 00:00:00 2001 From: Guilhem7 <48909214+Guilhem7@users.noreply.github.com> Date: Fri, 25 Jun 2021 12:12:54 +0200 Subject: [PATCH 107/309] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1532b044b..f7cd6d8d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added bruteforce function for the magic byte in `cmdlfnexwatch.c` and ability to clone with psk2 modulation (@Guilhem7, @MaximeBosca) - Changed `hw setmux` - improve user feedback for special case (@iceman1001) - Changed 'filename' - unified file name param across client (@iceman1001) - Fix `lf em 4x05 brute/chk` - fixed input params crash (@iceman1001) From f7c4336645fbcb82e4a06c2467f2ec82db33f8e9 Mon Sep 17 00:00:00 2001 From: rioux Date: Fri, 25 Jun 2021 13:26:16 +0200 Subject: [PATCH 108/309] last update askip --- client/src/cmdlfnexwatch.c | 14 ++++++++------ common/lfdemod.c | 11 ----------- common/lfdemod.h | 1 - 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/client/src/cmdlfnexwatch.c b/client/src/cmdlfnexwatch.c index a32a00a8c..39a3ff7cc 100644 --- a/client/src/cmdlfnexwatch.c +++ b/client/src/cmdlfnexwatch.c @@ -24,6 +24,7 @@ #include "cmdlft55xx.h" // clone.. #include "cmdlfem4x05.h" // #include "cliparser.h" +#include "util.h" typedef enum { @@ -110,9 +111,8 @@ static int nexwatch_scamble(NexWatchScramble_t action, uint32_t *id, uint32_t *s } static int nexwatch_magic_bruteforce(uint32_t cn, uint8_t calc_parity, uint8_t chk) { - uint8_t magic = 0; - uint8_t temp_checksum; - for (; magic < 255; magic++) { + for (uint8_t magic = 0; magic < 255; magic++) { + uint8_t temp_checksum; temp_checksum = nexwatch_checksum(magic, cn, calc_parity); if (temp_checksum == chk) { PrintAndLogEx(SUCCESS, " Magic number : " _GREEN_("0x%X"), magic); @@ -409,12 +409,14 @@ static int CmdNexWatchClone(const char *Cmd) { if (use_psk2) { blocks[0] = 270464; - uint8_t * res_shifted = malloc(96 * sizeof(uint8_t)); - uint8_t * res = byte_to_bytebits(raw, 12); + uint8_t * res_shifted = calloc(96, sizeof(uint8_t)); + uint8_t * res = calloc(96, sizeof(uint8_t)); + bytes_to_bytebits(raw, 12, res); psk1TOpsk2(res, 96); memcpy(res_shifted, &res[1], 95 * sizeof(uint8_t)); - res_shifted[95] = 0; + free(res); bits_to_array(res_shifted, 96, raw); + free(res_shifted); } diff --git a/common/lfdemod.c b/common/lfdemod.c index 350944314..3c32834f6 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -295,17 +295,6 @@ int bits_to_array(const uint8_t *bits, size_t size, uint8_t *dest) { return PM3_SUCCESS; } -// Ex: 0x56 and numbytes = 1 ==> return res = {0,1,0,1,0,1,1,0} -uint8_t * byte_to_bytebits(uint8_t * bits, size_t numbytes){ - uint8_t * result = malloc(numbytes * 8 * (sizeof(uint8_t))); - for(int i=0;i Date: Fri, 25 Jun 2021 17:21:50 +0200 Subject: [PATCH 109/309] text --- .../Windows-Installation-Instructions.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md index 25d9bebc3..b31e0773b 100644 --- a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md @@ -83,7 +83,10 @@ Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmar # Installing pre-compiled binaries with ProxSpace ^[Top](#top) -to be done (tcprst) +There are a community effort by @gator96100 to make up-to-date precompiled version of the offical repository and this repository. +[www.proxmarkbuilds.org](https://www.proxmarkbuilds.org/) + +It has excellent instructions to follow. From a86bd9464fcaa778752e530110bb4aafaf02f8ad Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 17:22:09 +0200 Subject: [PATCH 110/309] text --- client/src/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/util.c b/client/src/util.c index c8cc26752..77ce9cf2f 100644 --- a/client/src/util.c +++ b/client/src/util.c @@ -450,7 +450,7 @@ void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest) { } } -//least significant bit first +// least significant bit (lsb) first void num_to_bytebitsLSBF(uint64_t n, size_t len, uint8_t *dest) { for (size_t i = 0 ; i < len ; ++i) { dest[i] = n & 1; From a10c92267eefae49574e464af09762758971bf93 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 19:45:25 +0200 Subject: [PATCH 111/309] allow for 24 bytes keys to be loaded from dictionary --- client/src/fileutils.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/src/fileutils.c b/client/src/fileutils.c index 415a0bb3c..2f18e0845 100644 --- a/client/src/fileutils.c +++ b/client/src/fileutils.c @@ -1292,12 +1292,13 @@ out: } int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, uint8_t keylen, uint32_t *keycnt) { - // t5577 == 4bytes + // t5577 == 4 bytes // mifare == 6 bytes // mf plus == 16 bytes + // mf desfire == 3des3k 24 bytes // iclass == 8 bytes // default to 6 bytes. - if (keylen != 4 && keylen != 6 && keylen != 8 && keylen != 16) { + if (keylen != 4 && keylen != 6 && keylen != 8 && keylen != 16 && keylen != 24) { keylen = 6; } @@ -1404,9 +1405,10 @@ int loadFileDICTIONARY_safe(const char *preferredName, void **pdata, uint8_t key // t5577 == 4bytes // mifare == 6 bytes // mf plus == 16 bytes + // mf desfire == 3des3k 24 bytes // iclass == 8 bytes // default to 6 bytes. - if (keylen != 4 && keylen != 6 && keylen != 8 && keylen != 16) { + if (keylen != 4 && keylen != 6 && keylen != 8 && keylen != 16 && keylen != 24) { keylen = 6; } From 26b37ce64ff8204ca3e8423c2f1ff97c946e72cf Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 19:46:12 +0200 Subject: [PATCH 112/309] reworked "lf em 4x50 chk" to use dynamic memory for dictionary --- client/src/cmdlfem4x50.c | 48 ++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index 7ecf281bc..0861365a9 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -462,34 +462,32 @@ int CmdEM4x50Chk(const char *Cmd) { PrintAndLogEx(INFO, "treating file as T55xx keys"); } + // load keys + uint8_t *keys = NULL; + uint32_t key_count = 0; + int res = loadFileDICTIONARY_safe(filename, (void **)&keys, 4, &key_count); + if (res != PM3_SUCCESS || key_count == 0) { + free(keys); + return res; + } + uint64_t t1 = msclock(); - size_t datalen = 0; - - // 2021 iceman: how many keys shall we reserv space for? The t55xx dictionary has 139 keys. - uint8_t data[2000 * 4] = {0x0}; - uint8_t *keys = data; - uint32_t key_count = 0; - - int res = loadFileDICTIONARY(filename, data, &datalen, 4, &key_count); - if ((res != PM3_SUCCESS) || (key_count == 0)) - return PM3_EFILE; - PrintAndLogEx(INFO, "You can cancel this operation by pressing the pm3 button"); - - int status = PM3_EFAILED; - int keyblock = 2000; // block with 2000 bytes -> 500 keys + + // block with 2000 bytes -> 500 keys uint8_t destfn[32] = "em4x50_chk.bin"; - PacketResponseNG resp; - int bytes_remaining = datalen; + int bytes_remaining = key_count * 4; + int status = PM3_EFAILED; + while (bytes_remaining > 0) { PrintAndLogEx(INPLACE, "Remaining keys: %i ", bytes_remaining / 4); // upload to flash. - datalen = MIN(bytes_remaining, keyblock); - res = flashmem_spiffs_load((char *)destfn, keys, datalen); + size_t n = MIN(bytes_remaining, 2000); + res = flashmem_spiffs_load((char *)destfn, keys, n); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, "SPIFFS upload failed"); return res; @@ -503,22 +501,14 @@ int CmdEM4x50Chk(const char *Cmd) { if ((status == PM3_SUCCESS) || (status == PM3_EOPABORTED)) break; - bytes_remaining -= keyblock; - keys += keyblock; + bytes_remaining -= n; + keys += n; } + free(keys); PrintAndLogEx(NORMAL, ""); - // print response if (status == PM3_SUCCESS) { - /* - PrintAndLogEx(SUCCESS, "Key " _GREEN_("found: %02x %02x %02x %02x"), - resp.data.asBytes[3], - resp.data.asBytes[2], - resp.data.asBytes[1], - resp.data.asBytes[0] - ); - */ uint32_t pwd = BYTES2UINT32(resp.data.asBytes); PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", pwd); } else { From 015e02a9bf9f943babe305dd6d8a3885ef25efb9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 22:13:41 +0200 Subject: [PATCH 113/309] free start pointer --- CHANGELOG.md | 2 ++ client/src/cmdlfem4x50.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7cd6d8d4..f52221119 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + +## [midsummer][2021-06-25] - Added bruteforce function for the magic byte in `cmdlfnexwatch.c` and ability to clone with psk2 modulation (@Guilhem7, @MaximeBosca) - Changed `hw setmux` - improve user feedback for special case (@iceman1001) - Changed 'filename' - unified file name param across client (@iceman1001) diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index 0861365a9..a67ffbc7e 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -471,6 +471,8 @@ int CmdEM4x50Chk(const char *Cmd) { return res; } + uint8_t *pkeys = keys; + uint64_t t1 = msclock(); PrintAndLogEx(INFO, "You can cancel this operation by pressing the pm3 button"); @@ -505,7 +507,7 @@ int CmdEM4x50Chk(const char *Cmd) { keys += n; } - free(keys); + free(pkeys); PrintAndLogEx(NORMAL, ""); if (status == PM3_SUCCESS) { From 6dcef71fdab8ddb79b3c6cfe3d30a7ec78ec469e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 22:43:27 +0200 Subject: [PATCH 114/309] textual --- .github/ISSUE_TEMPLATE/checklist-for-release.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/checklist-for-release.md b/.github/ISSUE_TEMPLATE/checklist-for-release.md index 27fde4573..e9b488e26 100644 --- a/.github/ISSUE_TEMPLATE/checklist-for-release.md +++ b/.github/ISSUE_TEMPLATE/checklist-for-release.md @@ -36,7 +36,8 @@ sudo make install; pushd /tmp; proxmark3 -c 'data load -f lf_EM4x05.pm3;lf searc - [ ] RPI Zero - [ ] WSL -- [ ] PSv3.3 +- [ ] PSv3.9 +- [ ] Archlinux - [ ] Kali - [ ] Debian - [ ] Ubuntu20 From 94d12f8bbf4de11fef2d04fd0aacf8fe1d6d3d68 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 22:43:54 +0200 Subject: [PATCH 115/309] fix coverity CID 350102 --- client/src/cmdlfnexwatch.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/client/src/cmdlfnexwatch.c b/client/src/cmdlfnexwatch.c index 39a3ff7cc..0a85ada67 100644 --- a/client/src/cmdlfnexwatch.c +++ b/client/src/cmdlfnexwatch.c @@ -319,13 +319,16 @@ static int CmdNexWatchClone(const char *Cmd) { uint32_t mode = arg_get_u32_def(ctx, 3, -1); bool use_nexkey = arg_get_lit(ctx, 4); bool use_quadrakey = arg_get_lit(ctx, 5); - bool use_unk = arg_get_lit(ctx, 6); + bool use_honeywell = arg_get_lit(ctx, 6); bool q5 = arg_get_lit(ctx, 7); bool em = arg_get_lit(ctx, 8); + + uint8_t magic_arg[2]; + int mlen = 0; + CLIGetHexWithReturn(ctx, 9, magic_arg, &mlen); + bool use_psk2 = arg_get_lit(ctx, 10); - uint8_t magic_arg; - int magic_len = 0; - CLIGetHexWithReturn(ctx, 9, &magic_arg, &magic_len); + CLIParserFree(ctx); if (use_nexkey && use_quadrakey) { @@ -341,9 +344,9 @@ static int CmdNexWatchClone(const char *Cmd) { // 56000000 00213C9F 8F150C00 bool use_raw = (raw_len != 0); - bool use_custom_magic = (magic_len != 0); + bool use_custom_magic = (mlen != 0); - if (magic_len > 1) { + if (mlen > 1) { PrintAndLogEx(FAILED, "Can't specify a magic number bigger than one byte"); return PM3_EINVARG; } @@ -369,7 +372,7 @@ static int CmdNexWatchClone(const char *Cmd) { uint8_t magic = 0xBE; if (use_custom_magic) { - magic = magic_arg; + magic = magic_arg[0]; } else { if (use_nexkey) magic = 0x88; @@ -377,11 +380,11 @@ static int CmdNexWatchClone(const char *Cmd) { if (use_quadrakey) magic = 0xBE; - if (use_unk) + if (use_honeywell) magic = 0x86; } - PrintAndLogEx(INFO, "Magic byte selected : 0x%X", magic); + PrintAndLogEx(INFO, "Magic byte selected... " _YELLOW_("0x%X"), magic); uint32_t blocks[4]; @@ -408,9 +411,11 @@ static int CmdNexWatchClone(const char *Cmd) { } if (use_psk2) { - blocks[0] = 270464; - uint8_t * res_shifted = calloc(96, sizeof(uint8_t)); - uint8_t * res = calloc(96, sizeof(uint8_t)); + blocks[0] = 0x00042080; + + uint8_t *res_shifted = calloc(96, sizeof(uint8_t)); + uint8_t *res = calloc(96, sizeof(uint8_t)); + bytes_to_bytebits(raw, 12, res); psk1TOpsk2(res, 96); memcpy(res_shifted, &res[1], 95 * sizeof(uint8_t)); From 93cc64a8e39199cd42514063b0d56820559ee5b6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 23:04:55 +0200 Subject: [PATCH 116/309] fix uninitialized gcc7.5 opensuse warning --- client/src/cmdhftopaz.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhftopaz.c b/client/src/cmdhftopaz.c index 45724ac5d..32b7fc749 100644 --- a/client/src/cmdhftopaz.c +++ b/client/src/cmdhftopaz.c @@ -571,10 +571,10 @@ int CmdHFTopaz(const char *Cmd) { int readTopazUid(bool verbose) { - uint8_t atqa[2]; - uint8_t rid_response[8]; + uint8_t atqa[2] = {0}; + uint8_t rid_response[8] = {0}; uint8_t *uid_echo = &rid_response[2]; - uint8_t rall_response[124]; + uint8_t rall_response[124] = {0}; int status = topaz_select(atqa, sizeof(atqa), rid_response, sizeof(rid_response), verbose); if (status == PM3_ESOFT) { From 589c304142c9c473184f780f58fa9b3b761b5788 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 23:09:48 +0200 Subject: [PATCH 117/309] fix uninitialized gcc7.5 opensuse warning --- client/src/cmdhftopaz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhftopaz.c b/client/src/cmdhftopaz.c index 32b7fc749..9dc7d2257 100644 --- a/client/src/cmdhftopaz.c +++ b/client/src/cmdhftopaz.c @@ -133,7 +133,7 @@ static int topaz_rall(uint8_t *uid, uint8_t *response) { static int topaz_read_block(uint8_t *uid, uint8_t blockno, uint8_t *block_data) { uint16_t resp_len = 0; uint8_t read8_cmd[] = {TOPAZ_READ8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - uint8_t read8_response[11]; + uint8_t read8_response[11] = {0}; read8_cmd[1] = blockno; memcpy(&read8_cmd[10], uid, 4); From 2552286d6f59b5181b680193dd2c26d813130b90 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 25 Jun 2021 22:50:19 +0200 Subject: [PATCH 118/309] Notes on running tests on Docker Archlinux --- docker/archlinux/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docker/archlinux/README.md b/docker/archlinux/README.md index 67bf501e5..f1bb08523 100644 --- a/docker/archlinux/README.md +++ b/docker/archlinux/README.md @@ -26,3 +26,14 @@ sudo pacman -S staging/gcc sudo pacman -S testing/gcc sudo pacman -S gcc ``` + +# Notes to run tests + +Add first the mirrors, see above + +``` +sudo pacman -S python +sudo pacman -S python-pip +python3 -m pip install ansicolors sslcrypto +tools/pm3_tests.sh --long +``` From 1a38c7b72494c98ab2ffc5f7b68f95fd6613dec9 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 25 Jun 2021 22:51:31 +0200 Subject: [PATCH 119/309] Notes on running tests on Docker Debian Buster --- docker/debian-buster/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 docker/debian-buster/README.md diff --git a/docker/debian-buster/README.md b/docker/debian-buster/README.md new file mode 100644 index 000000000..c6fce658c --- /dev/null +++ b/docker/debian-buster/README.md @@ -0,0 +1,9 @@ +# Notes to run tests + +``` +sudo apt update +sudo apt install python3-minimal +sudo apt install python3-pip +python3 -m pip install ansicolors sslcrypto +tools/pm3_tests.sh --long +``` From e595195198b67de2b32c8e3f338cf2415c042dc1 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 25 Jun 2021 22:51:48 +0200 Subject: [PATCH 120/309] Notes on running tests on Docker Fedora --- docker/fedora-34/README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 docker/fedora-34/README.md diff --git a/docker/fedora-34/README.md b/docker/fedora-34/README.md new file mode 100644 index 000000000..31e409af7 --- /dev/null +++ b/docker/fedora-34/README.md @@ -0,0 +1,26 @@ +# Notes to run tests + +``` +sudo yum -y update +sudo yum -y install python-pip +python3 -m pip install ansicolors sslcrypto +tools/pm3_tests.sh --long +``` + +Warning, no idea how to manage to run `recover_pk` on Fedora... +Tried the followings: +``` +python3 -m pip install pyopenssl +sudo yum -y install openssl-devel libffi-devel +``` +Error is: +``` + File "/home/rrg/.local/lib/python3.9/site-packages/sslcrypto/_ecc.py", line 202, in get_curve + return EllipticCurve(self._backend, params, self._aes, nid) + File "/home/rrg/.local/lib/python3.9/site-packages/sslcrypto/_ecc.py", line 211, in __init__ + self._backend = backend_factory(**params) + File "/home/rrg/.local/lib/python3.9/site-packages/sslcrypto/openssl/ecc.py", line 221, in __init__ + raise ValueError("Could not create group object") +``` + +So just comment the "recover_pk test" for now, until someone figures out how to solve the issue. From 73fc526312a7ccf5e95a874ba19f4f750ae97aa9 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 25 Jun 2021 23:27:37 +0200 Subject: [PATCH 121/309] Remove cross compiler from Docker Opensuse Leap --- docker/opensuse-leap/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/opensuse-leap/Dockerfile b/docker/opensuse-leap/Dockerfile index cf860aeff..2fa63c4ad 100644 --- a/docker/opensuse-leap/Dockerfile +++ b/docker/opensuse-leap/Dockerfile @@ -2,7 +2,7 @@ FROM opensuse/leap ENV LANG C # libqt5-qtbase-devel skipped -RUN zypper --non-interactive install --no-recommends shadow sudo git patterns-devel-base-devel_basis gcc-c++ readline-devel libbz2-devel cross-arm-none-gcc9 cross-arm-none-newlib-devel +RUN zypper --non-interactive install --no-recommends shadow sudo git patterns-devel-base-devel_basis gcc-c++ readline-devel libbz2-devel # Create rrg user RUN useradd -ms /bin/bash rrg From c2a845e0dfbfeeacbcecfaff39cad41f78946ed7 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 25 Jun 2021 23:31:19 +0200 Subject: [PATCH 122/309] Notes on running tests on Docker Opensuse Tumbleweed --- docker/opensuse-tumbleweed/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 docker/opensuse-tumbleweed/README.md diff --git a/docker/opensuse-tumbleweed/README.md b/docker/opensuse-tumbleweed/README.md new file mode 100644 index 000000000..091f2144b --- /dev/null +++ b/docker/opensuse-tumbleweed/README.md @@ -0,0 +1,8 @@ +# Notes to run tests + +``` +sudo zypper --non-interactive install python3 +sudo zypper --non-interactive install python3-pip +python3 -m pip install ansicolors sslcrypto +tools/pm3_tests.sh --long +``` From aee2b43b8c78b1b10870e53cd6d6cb5924adf025 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 25 Jun 2021 23:34:29 +0200 Subject: [PATCH 123/309] Notes on running tests on Docker Ubuntu 18.04 --- docker/ubuntu-18.04/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 docker/ubuntu-18.04/README.md diff --git a/docker/ubuntu-18.04/README.md b/docker/ubuntu-18.04/README.md new file mode 100644 index 000000000..c6fce658c --- /dev/null +++ b/docker/ubuntu-18.04/README.md @@ -0,0 +1,9 @@ +# Notes to run tests + +``` +sudo apt update +sudo apt install python3-minimal +sudo apt install python3-pip +python3 -m pip install ansicolors sslcrypto +tools/pm3_tests.sh --long +``` From a115ff07574e4ff59ead22da6ea19311f4f8ad54 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 23:35:36 +0200 Subject: [PATCH 124/309] style --- client/src/cmdlfem4x50.c | 2 +- doc/commands.json | 64 +++++++++++++++++++++------------------- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index a67ffbc7e..33c447da0 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -476,7 +476,7 @@ int CmdEM4x50Chk(const char *Cmd) { uint64_t t1 = msclock(); PrintAndLogEx(INFO, "You can cancel this operation by pressing the pm3 button"); - + // block with 2000 bytes -> 500 keys uint8_t destfn[32] = "em4x50_chk.bin"; PacketResponseNG resp; diff --git a/doc/commands.json b/doc/commands.json index 571c53d13..d5c903f99 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -973,7 +973,7 @@ }, "help": { "command": "help", - "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log /home/osboxes/.proxmark3/logs/log_20210624.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", + "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log /home/osboxes/.proxmark3/logs/log_20210625.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", "notes": [ "auto" ], @@ -2826,10 +2826,10 @@ "offline": false, "options": [ "-h, --help this help", - "-f, --file specify a filename for dump file", + "-f, --file specify a filename for dump file", "--de deobfuscate dump data (xor with mcc)" ], - "usage": "hf legic dump [-h] [-f ] [--de]" + "usage": "hf legic dump [-h] [-f ] [--de]" }, "hf legic eload": { "command": "hf legic eload", @@ -2860,11 +2860,11 @@ "offline": true, "options": [ "-h, --help this help", - "-f, --file specify a filename to save", + "-f, --file specify a filename to save", "-t, --type tag type", "--deobfuscate de-obfuscate dump data (xor with mcc)" ], - "usage": "hf legic esave [-h] [-f ] [-t ] [--deobfuscate]" + "usage": "hf legic esave [-h] [-f ] [-t ] [--deobfuscate]" }, "hf legic help": { "command": "hf legic help", @@ -2996,9 +2996,9 @@ "offline": true, "options": [ "-h, --help this help", - "-f, --file specify a filename for dumpfile" + "-f, --file specify a filename for dumpfile" ], - "usage": "hf lto dump [-h] [-f ]" + "usage": "hf lto dump [-h] [-f ]" }, "hf lto info": { "command": "hf lto info", @@ -3175,9 +3175,9 @@ "--4k mifare classic 4k / s70", "--emu fill simulator keys from found keys", "--dump dump found keys to binary file", - "-f, --file filename of dictionary" + "-f, --file filename of dictionary" ], - "usage": "hf mf chk [-hab*] [-k ]... [--blk ] [--mini] [--1k] [--2k] [--4k] [--emu] [--dump] [-f ]" + "usage": "hf mf chk [-hab*] [-k ]... [--blk ] [--mini] [--1k] [--2k] [--4k] [--emu] [--dump] [-f ]" }, "hf mf cload": { "command": "hf mf cload", @@ -5226,7 +5226,7 @@ "command": "hw setmux", "description": "set the adc mux to a specific value", "notes": [ - "hw setmux --hiraw -> set high raw" + "hw setmux --hipkd -> set high peak" ], "offline": false, "options": [ @@ -5620,16 +5620,16 @@ "description": "this command uses a dictionary attack against em4205/4305/4469/4569", "notes": [ "lf em 4x05 chk", - "lf em 4x05 chk -e 000022b8 -> remember to use 0x for hex", + "lf em 4x05 chk -e 000022b8 -> check password 000022b8", "lf em 4x05 chk -f t55xx_default_pwds -> use t55xx default dictionary" ], "offline": false, "options": [ "-h, --help this help", - "-f, --file <*.dic> loads a default keys dictionary file <*.dic>", + "-f, --file loads a default keys dictionary file <*.dic>", "-e, --em try the calculated password from some cloners based on em4100 id" ], - "usage": "lf em 4x05 chk [-h] [-f <*.dic>]... [-e ]" + "usage": "lf em 4x05 chk [-h] [-f ] [-e ]" }, "lf em 4x05 demod": { "command": "lf em 4x05 demod", @@ -5661,19 +5661,19 @@ }, "lf em 4x05 help": { "command": "lf em 4x05 help", - "description": "help this help demod demodulate a em4x05/em4x69 tag from the graphbuffer sniff attempt to recover em4x05 commands from sample buffer --------------------------------------------------------------------------------------- lf em 4x05 brute available offline: no this command tries to bruteforce the password of a em4205/4305/4469/4569", + "description": "help this help demod demodulate a em4x05/em4x69 tag from the graphbuffer sniff attempt to recover em4x05 commands from sample buffer --------------------------------------------------------------------------------------- lf em 4x05 brute available offline: no this command tries to bruteforce the password of a em4205/4305/4469/4569 the loop is running on device side, press proxmark3 button to abort", "notes": [ "note: if you get many false positives, change position on the antennalf em 4x05 brute", "lf em 4x05 brute -n 1 -> stop after first candidate found", - "lf em 4x05 brute -s 000022b8 -> remember to use 0x for hex" + "lf em 4x05 brute -s 000022aa -> start at 000022aa" ], "offline": true, "options": [ "-h, --help this help", - "-s, --start start bruteforce enumeration from this password value", - "-n stop after having found n candidates. default: 0 => infinite" + "-s, --start start bruteforce enumeration from this password value", + "-n stop after having found n candidates. default: 0 (infinite)" ], - "usage": "lf em 4x05 brute [-h] [-s ] [-n ]" + "usage": "lf em 4x05 brute [-h] [-s ] [-n ]" }, "lf em 4x05 info": { "command": "lf em 4x05 info", @@ -5786,7 +5786,7 @@ "offline": false, "options": [ "-h, --help this help", - "-f, --filename dictionary filename" + "-f, --file dictionary filename" ], "usage": "lf em 4x50 chk [-h] [-f ]" }, @@ -5802,7 +5802,7 @@ "offline": false, "options": [ "-h, --help this help", - "-f, --filename dump filename (bin/eml/json)", + "-f, --file dump filename (bin/eml/json)", "-p, --pwd password, 4 hex bytes, lsb" ], "usage": "lf em 4x50 dump [-h] [-f ] [-p ]" @@ -5830,7 +5830,7 @@ "offline": false, "options": [ "-h, --help this help", - "-f, --filename data filename" + "-f, --file save filename" ], "usage": "lf em 4x50 esave [-h] [-f ]" }, @@ -5931,7 +5931,7 @@ "options": [ "-h, --help this help", "-u, --uid uid, 4 hex bytes, msb", - "-f, --filename dump filename (bin/eml/json)", + "-f, --file dump filename (bin/eml/json)", "-p, --pwd password, 4 hex bytes, lsb" ], "usage": "lf em 4x50 restore [-h] [-u ] [-f ] [-p ]" @@ -6434,9 +6434,9 @@ "offline": false, "options": [ "-h, --help this help", - "-f, --filename filename to load from" + "-f, --file filename to load ( w/o ext )" ], - "usage": "lf hitag cc [-h] [-f ]" + "usage": "lf hitag cc [-h] [-f ]" }, "lf hitag dump": { "command": "lf hitag dump", @@ -7034,9 +7034,11 @@ "--qc quadrakey credential", "--hc honeywell credential", "--q5 optional - specify writing to q5/t5555 tag", - "--em optional - specify writing to em4305/4469 tag" + "--em optional - specify writing to em4305/4469 tag", + "--magic optional - magic hex data. 1 byte", + "--psk2 optional - specify writing a tag in psk2 modulation" ], - "usage": "lf nexwatch clone [-h] [-r ] [--cn ] [-m ] [--nc] [--qc] [--hc] [--q5] [--em]" + "usage": "lf nexwatch clone [-h] [-r ] [--cn ] [-m ] [--nc] [--qc] [--hc] [--q5] [--em] [--magic ] [--psk2]" }, "lf nexwatch help": { "command": "lf nexwatch help", @@ -7080,9 +7082,11 @@ "-m, --mode mode (decimal) (0-15, defaults to 1)", "--nc nexkey credential", "--qc quadrakey credential", - "--hc honeywell credential" + "--hc honeywell credential", + "--magic optional - magic hex data. 1 byte", + "--psk2 optional - specify writing a tag in psk2 modulation" ], - "usage": "lf nexwatch sim [-h] [-r ] [--cn ] [-m ] [--nc] [--qc] [--hc]" + "usage": "lf nexwatch sim [-h] [-r ] [--cn ] [-m ] [--nc] [--qc] [--hc] [--magic ] [--psk2]" }, "lf noralsy clone": { "command": "lf noralsy clone", @@ -7767,7 +7771,7 @@ "offline": false, "options": [ "-h, --help this help", - "-f, --filename filename (default is generated on blk 0)", + "-f, --file filename (default is generated on blk 0)", "-o, --override override, force pwd read despite danger to card", "-p, --pwd password (4 hex bytes)", "--r0 downlink - fixed bit length", @@ -9199,6 +9203,6 @@ "metadata": { "commands_extracted": 571, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2021-06-24T17:28:12" + "extracted_on": "2021-06-25T21:34:48" } } \ No newline at end of file From 55e1b6714b7cccaf177285572d4c60db7d305255 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 23:39:10 +0200 Subject: [PATCH 125/309] Release v4.13441 - midsummer --- Makefile.defs | 4 ++-- armsrc/Makefile | 2 +- bootrom/Makefile | 2 +- client/CMakeLists.txt | 4 ++-- client/Makefile | 4 ++-- client/deps/amiibo.cmake | 2 +- client/deps/cliparser.cmake | 2 +- client/deps/hardnested.cmake | 14 +++++++------- client/deps/jansson.cmake | 2 +- client/deps/lua.cmake | 2 +- client/deps/mbedtls.cmake | 2 +- client/deps/reveng.cmake | 2 +- client/deps/tinycbor.cmake | 2 +- client/deps/whereami.cmake | 2 +- client/src/proxmark3.c | 2 +- common/default_version_pm3.c | 11 ++++++----- common_arm/Makefile.common | 2 +- 17 files changed, 31 insertions(+), 30 deletions(-) diff --git a/Makefile.defs b/Makefile.defs index 5a6993228..40fb49b8b 100644 --- a/Makefile.defs +++ b/Makefile.defs @@ -67,8 +67,8 @@ ifeq ($(DEBUG),1) DEFCFLAGS = -g -O0 -fstrict-aliasing -pipe DEFLDFLAGS = else - DEFCXXFLAGS = -Wall -Werror -O3 -pipe - DEFCFLAGS = -Wall -Werror -O3 -fstrict-aliasing -pipe + DEFCXXFLAGS = -Wall -O3 -pipe + DEFCFLAGS = -Wall -O3 -fstrict-aliasing -pipe DEFLDFLAGS = endif diff --git a/armsrc/Makefile b/armsrc/Makefile index 219b176c1..e1c650505 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -166,7 +166,7 @@ showinfo: # version_pm3.c should be remade on every time fullimage.stage1.elf should be remade version_pm3.c: default_version_pm3.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) $(info [-] GEN $@) - $(Q)$(SH) ../tools/mkversion.sh > $@ || $(PERL) ../tools/mkversion.pl > $@ || $(CP) $< $@ + $(Q)$(CP) $< $@ fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) $(info [-] GEN $@) diff --git a/bootrom/Makefile b/bootrom/Makefile index 255ebeb1c..9022a4eec 100644 --- a/bootrom/Makefile +++ b/bootrom/Makefile @@ -39,7 +39,7 @@ OBJS = $(OBJDIR)/bootrom.s19 # version_pm3.c should be remade on every compilation version_pm3.c: default_version_pm3.c $(info [=] GEN $@) - $(Q)$(SH) ../tools/mkversion.sh > $@ || $(PERL) ../tools/mkversion.pl > $@ || $(CP) $< $@ + $(Q)$(CP) $< $@ all: showinfo $(OBJS) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index a81682337..e0623fa1a 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -326,7 +326,7 @@ set (TARGET_SOURCES add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c - COMMAND sh ${PM3_ROOT}/tools/mkversion.sh > ${CMAKE_BINARY_DIR}/version_pm3.c || perl ${PM3_ROOT}/tools/mkversion.pl > ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c + COMMAND ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c DEPENDS ${PM3_ROOT}/common/default_version_pm3.c ) @@ -507,7 +507,7 @@ add_executable(proxmark3 ${ADDITIONAL_SRC} ) -target_compile_options(proxmark3 PUBLIC -Wall -Werror -O3) +target_compile_options(proxmark3 PUBLIC -Wall -O3) if (EMBED_READLINE) if (NOT SKIPREADLINE EQUAL 1) add_dependencies(proxmark3 ncurses readline) diff --git a/client/Makefile b/client/Makefile index 9ed3feb86..bf46792ee 100644 --- a/client/Makefile +++ b/client/Makefile @@ -336,7 +336,7 @@ ifeq ($(SWIG_PYTHON_FOUND),1) PM3CFLAGS += -DHAVE_PYTHON_SWIG endif -CXXFLAGS ?= -Wall -Werror -O3 +CXXFLAGS ?= -Wall -O3 PM3CXXFLAGS = $(CXXFLAGS) PM3CXXFLAGS += -I../include -I./include @@ -783,7 +783,7 @@ src/pm3_pywrap.c: pm3.i # version_pm3.c should be remade on every compilation src/version_pm3.c: default_version_pm3.c $(info [=] GEN $@) - $(Q)$(SH) ../tools/mkversion.sh > $@ || $(PERL) ../tools/mkversion.pl > $@ || $(CP) $< $@ + $(Q)$(CP) $< $@ # easy printing of MAKE VARIABLES print-%: ; @echo $* = $($*) diff --git a/client/deps/amiibo.cmake b/client/deps/amiibo.cmake index c946c0682..8c524c170 100644 --- a/client/deps/amiibo.cmake +++ b/client/deps/amiibo.cmake @@ -19,7 +19,7 @@ target_link_libraries(pm3rrg_rdv4_amiibo PRIVATE m pm3rrg_rdv4_mbedtls) -target_compile_options(pm3rrg_rdv4_amiibo PRIVATE -Wall -Werror -O3) +target_compile_options(pm3rrg_rdv4_amiibo PRIVATE -Wall -O3) set_property(TARGET pm3rrg_rdv4_amiibo PROPERTY POSITION_INDEPENDENT_CODE ON) target_include_directories(pm3rrg_rdv4_amiibo PRIVATE amiitool diff --git a/client/deps/cliparser.cmake b/client/deps/cliparser.cmake index fccae33b7..a85cc2374 100644 --- a/client/deps/cliparser.cmake +++ b/client/deps/cliparser.cmake @@ -9,5 +9,5 @@ target_include_directories(pm3rrg_rdv4_cliparser PRIVATE ../../include ../src) target_include_directories(pm3rrg_rdv4_cliparser INTERFACE cliparser) -target_compile_options(pm3rrg_rdv4_cliparser PRIVATE -Wall -Werror -O3) +target_compile_options(pm3rrg_rdv4_cliparser PRIVATE -Wall -O3) set_property(TARGET pm3rrg_rdv4_cliparser PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/client/deps/hardnested.cmake b/client/deps/hardnested.cmake index dc569641c..67be099fa 100644 --- a/client/deps/hardnested.cmake +++ b/client/deps/hardnested.cmake @@ -2,7 +2,7 @@ add_library(pm3rrg_rdv4_hardnested_nosimd OBJECT hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c) -target_compile_options(pm3rrg_rdv4_hardnested_nosimd PRIVATE -Wall -Werror -O3) +target_compile_options(pm3rrg_rdv4_hardnested_nosimd PRIVATE -Wall -O3) set_property(TARGET pm3rrg_rdv4_hardnested_nosimd PROPERTY POSITION_INDEPENDENT_CODE ON) target_include_directories(pm3rrg_rdv4_hardnested_nosimd PRIVATE @@ -28,7 +28,7 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS) hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c) - target_compile_options(pm3rrg_rdv4_hardnested_mmx PRIVATE -Wall -Werror -O3) + target_compile_options(pm3rrg_rdv4_hardnested_mmx PRIVATE -Wall -O3) target_compile_options(pm3rrg_rdv4_hardnested_mmx BEFORE PRIVATE -mmmx -mno-sse2 -mno-avx -mno-avx2 -mno-avx512f) set_property(TARGET pm3rrg_rdv4_hardnested_mmx PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -43,7 +43,7 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS) hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c) - target_compile_options(pm3rrg_rdv4_hardnested_sse2 PRIVATE -Wall -Werror -O3) + target_compile_options(pm3rrg_rdv4_hardnested_sse2 PRIVATE -Wall -O3) target_compile_options(pm3rrg_rdv4_hardnested_sse2 BEFORE PRIVATE -mmmx -msse2 -mno-avx -mno-avx2 -mno-avx512f) set_property(TARGET pm3rrg_rdv4_hardnested_sse2 PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -58,7 +58,7 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS) hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c) - target_compile_options(pm3rrg_rdv4_hardnested_avx PRIVATE -Wall -Werror -O3) + target_compile_options(pm3rrg_rdv4_hardnested_avx PRIVATE -Wall -O3) target_compile_options(pm3rrg_rdv4_hardnested_avx BEFORE PRIVATE -mmmx -msse2 -mavx -mno-avx2 -mno-avx512f) set_property(TARGET pm3rrg_rdv4_hardnested_avx PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -73,7 +73,7 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS) hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c) - target_compile_options(pm3rrg_rdv4_hardnested_avx2 PRIVATE -Wall -Werror -O3) + target_compile_options(pm3rrg_rdv4_hardnested_avx2 PRIVATE -Wall -O3) target_compile_options(pm3rrg_rdv4_hardnested_avx2 BEFORE PRIVATE -mmmx -msse2 -mavx -mavx2 -mno-avx512f) set_property(TARGET pm3rrg_rdv4_hardnested_avx2 PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -88,7 +88,7 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS) hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c) - target_compile_options(pm3rrg_rdv4_hardnested_avx512 PRIVATE -Wall -Werror -O3) + target_compile_options(pm3rrg_rdv4_hardnested_avx512 PRIVATE -Wall -O3) target_compile_options(pm3rrg_rdv4_hardnested_avx512 BEFORE PRIVATE -mmmx -msse2 -mavx -mavx2 -mavx512f) set_property(TARGET pm3rrg_rdv4_hardnested_avx512 PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -113,7 +113,7 @@ add_library(pm3rrg_rdv4_hardnested STATIC hardnested/hardnested_bruteforce.c $ ${SIMD_TARGETS}) -target_compile_options(pm3rrg_rdv4_hardnested PRIVATE -Wall -Werror -O3) +target_compile_options(pm3rrg_rdv4_hardnested PRIVATE -Wall -O3) set_property(TARGET pm3rrg_rdv4_hardnested PROPERTY POSITION_INDEPENDENT_CODE ON) target_include_directories(pm3rrg_rdv4_hardnested PRIVATE ../../common diff --git a/client/deps/jansson.cmake b/client/deps/jansson.cmake index c91a47047..42c701d5e 100644 --- a/client/deps/jansson.cmake +++ b/client/deps/jansson.cmake @@ -14,5 +14,5 @@ add_library(pm3rrg_rdv4_jansson STATIC target_compile_definitions(pm3rrg_rdv4_jansson PRIVATE HAVE_STDINT_H) target_include_directories(pm3rrg_rdv4_jansson INTERFACE jansson) -target_compile_options(pm3rrg_rdv4_jansson PRIVATE -Wall -Werror -Wno-unused-function -O3) +target_compile_options(pm3rrg_rdv4_jansson PRIVATE -Wall -Wno-unused-function -O3) set_property(TARGET pm3rrg_rdv4_jansson PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/client/deps/lua.cmake b/client/deps/lua.cmake index 12870342e..5cf33d724 100644 --- a/client/deps/lua.cmake +++ b/client/deps/lua.cmake @@ -52,5 +52,5 @@ if (NOT MINGW) endif (NOT MINGW) target_include_directories(pm3rrg_rdv4_lua INTERFACE liblua) -target_compile_options(pm3rrg_rdv4_lua PRIVATE -Wall -Werror -O3) +target_compile_options(pm3rrg_rdv4_lua PRIVATE -Wall -O3) set_property(TARGET pm3rrg_rdv4_lua PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/client/deps/mbedtls.cmake b/client/deps/mbedtls.cmake index 40929e1ea..c726ddeba 100644 --- a/client/deps/mbedtls.cmake +++ b/client/deps/mbedtls.cmake @@ -44,5 +44,5 @@ add_library(pm3rrg_rdv4_mbedtls STATIC target_include_directories(pm3rrg_rdv4_mbedtls PRIVATE ../../common) target_include_directories(pm3rrg_rdv4_mbedtls INTERFACE ../../common/mbedtls) -target_compile_options(pm3rrg_rdv4_mbedtls PRIVATE -Wall -Werror -O3) +target_compile_options(pm3rrg_rdv4_mbedtls PRIVATE -Wall -O3) set_property(TARGET pm3rrg_rdv4_mbedtls PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/client/deps/reveng.cmake b/client/deps/reveng.cmake index d7e3cfd8a..1040730f1 100644 --- a/client/deps/reveng.cmake +++ b/client/deps/reveng.cmake @@ -13,5 +13,5 @@ target_include_directories(pm3rrg_rdv4_reveng PRIVATE ../src ../../include) target_include_directories(pm3rrg_rdv4_reveng INTERFACE reveng) -target_compile_options(pm3rrg_rdv4_reveng PRIVATE -Wall -Werror -O3) +target_compile_options(pm3rrg_rdv4_reveng PRIVATE -Wall -O3) set_property(TARGET pm3rrg_rdv4_reveng PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/client/deps/tinycbor.cmake b/client/deps/tinycbor.cmake index 5a6abda25..c74618149 100644 --- a/client/deps/tinycbor.cmake +++ b/client/deps/tinycbor.cmake @@ -11,5 +11,5 @@ add_library(pm3rrg_rdv4_tinycbor STATIC target_include_directories(pm3rrg_rdv4_tinycbor INTERFACE tinycbor) # Strange errors on Mingw when compiling with -O3 -target_compile_options(pm3rrg_rdv4_tinycbor PRIVATE -Wall -Werror -O2) +target_compile_options(pm3rrg_rdv4_tinycbor PRIVATE -Wall -O2) set_property(TARGET pm3rrg_rdv4_tinycbor PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/client/deps/whereami.cmake b/client/deps/whereami.cmake index d2d6a5b2a..721873066 100644 --- a/client/deps/whereami.cmake +++ b/client/deps/whereami.cmake @@ -2,5 +2,5 @@ add_library(pm3rrg_rdv4_whereami STATIC whereami/whereami.c) target_compile_definitions(pm3rrg_rdv4_whereami PRIVATE WAI_PM3_TUNED) target_include_directories(pm3rrg_rdv4_whereami INTERFACE whereami) -target_compile_options(pm3rrg_rdv4_whereami PRIVATE -Wall -Werror -O3) +target_compile_options(pm3rrg_rdv4_whereami PRIVATE -Wall -O3) set_property(TARGET pm3rrg_rdv4_whereami PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/client/src/proxmark3.c b/client/src/proxmark3.c index d1507923a..33a108811 100644 --- a/client/src/proxmark3.c +++ b/client/src/proxmark3.c @@ -38,7 +38,7 @@ #ifndef LIBPM3 #define BANNERMSG1 " Iceman :coffee:" #define BANNERMSG2 " :snowflake: bleeding edge" -#define BANNERMSG3 " https://github.com/rfidresearchgroup/proxmark3/" +#define BANNERMSG3 "Release v4.13441 - midsummer" typedef enum LogoMode { UTF8, ANSI, ASCII } LogoMode; diff --git a/common/default_version_pm3.c b/common/default_version_pm3.c index 8547182dc..7ca58e992 100644 --- a/common/default_version_pm3.c +++ b/common/default_version_pm3.c @@ -1,5 +1,5 @@ #include "common.h" -/* This is the default version_pm3.c file that Makefile.common falls back to if neither sh nor perl are available */ +/* Generated file, do not edit */ #ifndef ON_DEVICE #define SECTVERSINFO #else @@ -8,8 +8,9 @@ const struct version_information SECTVERSINFO version_information = { VERSION_INFORMATION_MAGIC, - 1, /* version 1 */ - 0, /* version information not present */ - 2, /* cleanliness couldn't be determined */ - /* Remaining fields: zero */ + 1, + 1, + 1, + "RRG/Iceman/master/v4.13441", + "2021-06-25 23:39:10", }; diff --git a/common_arm/Makefile.common b/common_arm/Makefile.common index e6d1636e9..2f5c52b5f 100644 --- a/common_arm/Makefile.common +++ b/common_arm/Makefile.common @@ -40,7 +40,7 @@ VPATH = . ../common_arm ../common ../common/crapto1 ../common/mbedtls ../common/ INCLUDES = ../include/proxmark3_arm.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/pm3_cmd.h ARMCFLAGS = -mthumb-interwork -fno-builtin -DEFCFLAGS = -Wall -Werror -Os -pedantic -fstrict-aliasing -pipe +DEFCFLAGS = -Wall -Os -pedantic -fstrict-aliasing -pipe # Some more warnings we want as errors: DEFCFLAGS += -Wbad-function-cast -Wchar-subscripts -Wundef -Wunused -Wuninitialized -Wpointer-arith -Wformat -Wformat-security -Winit-self -Wmissing-include-dirs -Wnested-externs -Wempty-body -Wignored-qualifiers -Wmissing-field-initializers -Wtype-limits From f0c16654276c5a2d529360933463726fd49b5755 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 23:39:10 +0200 Subject: [PATCH 126/309] Revert "Release v4.13441 - midsummer" This reverts commit 55e1b6714b7cccaf177285572d4c60db7d305255. --- Makefile.defs | 4 ++-- armsrc/Makefile | 2 +- bootrom/Makefile | 2 +- client/CMakeLists.txt | 4 ++-- client/Makefile | 4 ++-- client/deps/amiibo.cmake | 2 +- client/deps/cliparser.cmake | 2 +- client/deps/hardnested.cmake | 14 +++++++------- client/deps/jansson.cmake | 2 +- client/deps/lua.cmake | 2 +- client/deps/mbedtls.cmake | 2 +- client/deps/reveng.cmake | 2 +- client/deps/tinycbor.cmake | 2 +- client/deps/whereami.cmake | 2 +- client/src/proxmark3.c | 2 +- common/default_version_pm3.c | 11 +++++------ common_arm/Makefile.common | 2 +- 17 files changed, 30 insertions(+), 31 deletions(-) diff --git a/Makefile.defs b/Makefile.defs index 40fb49b8b..5a6993228 100644 --- a/Makefile.defs +++ b/Makefile.defs @@ -67,8 +67,8 @@ ifeq ($(DEBUG),1) DEFCFLAGS = -g -O0 -fstrict-aliasing -pipe DEFLDFLAGS = else - DEFCXXFLAGS = -Wall -O3 -pipe - DEFCFLAGS = -Wall -O3 -fstrict-aliasing -pipe + DEFCXXFLAGS = -Wall -Werror -O3 -pipe + DEFCFLAGS = -Wall -Werror -O3 -fstrict-aliasing -pipe DEFLDFLAGS = endif diff --git a/armsrc/Makefile b/armsrc/Makefile index e1c650505..219b176c1 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -166,7 +166,7 @@ showinfo: # version_pm3.c should be remade on every time fullimage.stage1.elf should be remade version_pm3.c: default_version_pm3.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) $(info [-] GEN $@) - $(Q)$(CP) $< $@ + $(Q)$(SH) ../tools/mkversion.sh > $@ || $(PERL) ../tools/mkversion.pl > $@ || $(CP) $< $@ fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) $(info [-] GEN $@) diff --git a/bootrom/Makefile b/bootrom/Makefile index 9022a4eec..255ebeb1c 100644 --- a/bootrom/Makefile +++ b/bootrom/Makefile @@ -39,7 +39,7 @@ OBJS = $(OBJDIR)/bootrom.s19 # version_pm3.c should be remade on every compilation version_pm3.c: default_version_pm3.c $(info [=] GEN $@) - $(Q)$(CP) $< $@ + $(Q)$(SH) ../tools/mkversion.sh > $@ || $(PERL) ../tools/mkversion.pl > $@ || $(CP) $< $@ all: showinfo $(OBJS) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index e0623fa1a..a81682337 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -326,7 +326,7 @@ set (TARGET_SOURCES add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c - COMMAND ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c + COMMAND sh ${PM3_ROOT}/tools/mkversion.sh > ${CMAKE_BINARY_DIR}/version_pm3.c || perl ${PM3_ROOT}/tools/mkversion.pl > ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c DEPENDS ${PM3_ROOT}/common/default_version_pm3.c ) @@ -507,7 +507,7 @@ add_executable(proxmark3 ${ADDITIONAL_SRC} ) -target_compile_options(proxmark3 PUBLIC -Wall -O3) +target_compile_options(proxmark3 PUBLIC -Wall -Werror -O3) if (EMBED_READLINE) if (NOT SKIPREADLINE EQUAL 1) add_dependencies(proxmark3 ncurses readline) diff --git a/client/Makefile b/client/Makefile index bf46792ee..9ed3feb86 100644 --- a/client/Makefile +++ b/client/Makefile @@ -336,7 +336,7 @@ ifeq ($(SWIG_PYTHON_FOUND),1) PM3CFLAGS += -DHAVE_PYTHON_SWIG endif -CXXFLAGS ?= -Wall -O3 +CXXFLAGS ?= -Wall -Werror -O3 PM3CXXFLAGS = $(CXXFLAGS) PM3CXXFLAGS += -I../include -I./include @@ -783,7 +783,7 @@ src/pm3_pywrap.c: pm3.i # version_pm3.c should be remade on every compilation src/version_pm3.c: default_version_pm3.c $(info [=] GEN $@) - $(Q)$(CP) $< $@ + $(Q)$(SH) ../tools/mkversion.sh > $@ || $(PERL) ../tools/mkversion.pl > $@ || $(CP) $< $@ # easy printing of MAKE VARIABLES print-%: ; @echo $* = $($*) diff --git a/client/deps/amiibo.cmake b/client/deps/amiibo.cmake index 8c524c170..c946c0682 100644 --- a/client/deps/amiibo.cmake +++ b/client/deps/amiibo.cmake @@ -19,7 +19,7 @@ target_link_libraries(pm3rrg_rdv4_amiibo PRIVATE m pm3rrg_rdv4_mbedtls) -target_compile_options(pm3rrg_rdv4_amiibo PRIVATE -Wall -O3) +target_compile_options(pm3rrg_rdv4_amiibo PRIVATE -Wall -Werror -O3) set_property(TARGET pm3rrg_rdv4_amiibo PROPERTY POSITION_INDEPENDENT_CODE ON) target_include_directories(pm3rrg_rdv4_amiibo PRIVATE amiitool diff --git a/client/deps/cliparser.cmake b/client/deps/cliparser.cmake index a85cc2374..fccae33b7 100644 --- a/client/deps/cliparser.cmake +++ b/client/deps/cliparser.cmake @@ -9,5 +9,5 @@ target_include_directories(pm3rrg_rdv4_cliparser PRIVATE ../../include ../src) target_include_directories(pm3rrg_rdv4_cliparser INTERFACE cliparser) -target_compile_options(pm3rrg_rdv4_cliparser PRIVATE -Wall -O3) +target_compile_options(pm3rrg_rdv4_cliparser PRIVATE -Wall -Werror -O3) set_property(TARGET pm3rrg_rdv4_cliparser PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/client/deps/hardnested.cmake b/client/deps/hardnested.cmake index 67be099fa..dc569641c 100644 --- a/client/deps/hardnested.cmake +++ b/client/deps/hardnested.cmake @@ -2,7 +2,7 @@ add_library(pm3rrg_rdv4_hardnested_nosimd OBJECT hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c) -target_compile_options(pm3rrg_rdv4_hardnested_nosimd PRIVATE -Wall -O3) +target_compile_options(pm3rrg_rdv4_hardnested_nosimd PRIVATE -Wall -Werror -O3) set_property(TARGET pm3rrg_rdv4_hardnested_nosimd PROPERTY POSITION_INDEPENDENT_CODE ON) target_include_directories(pm3rrg_rdv4_hardnested_nosimd PRIVATE @@ -28,7 +28,7 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS) hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c) - target_compile_options(pm3rrg_rdv4_hardnested_mmx PRIVATE -Wall -O3) + target_compile_options(pm3rrg_rdv4_hardnested_mmx PRIVATE -Wall -Werror -O3) target_compile_options(pm3rrg_rdv4_hardnested_mmx BEFORE PRIVATE -mmmx -mno-sse2 -mno-avx -mno-avx2 -mno-avx512f) set_property(TARGET pm3rrg_rdv4_hardnested_mmx PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -43,7 +43,7 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS) hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c) - target_compile_options(pm3rrg_rdv4_hardnested_sse2 PRIVATE -Wall -O3) + target_compile_options(pm3rrg_rdv4_hardnested_sse2 PRIVATE -Wall -Werror -O3) target_compile_options(pm3rrg_rdv4_hardnested_sse2 BEFORE PRIVATE -mmmx -msse2 -mno-avx -mno-avx2 -mno-avx512f) set_property(TARGET pm3rrg_rdv4_hardnested_sse2 PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -58,7 +58,7 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS) hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c) - target_compile_options(pm3rrg_rdv4_hardnested_avx PRIVATE -Wall -O3) + target_compile_options(pm3rrg_rdv4_hardnested_avx PRIVATE -Wall -Werror -O3) target_compile_options(pm3rrg_rdv4_hardnested_avx BEFORE PRIVATE -mmmx -msse2 -mavx -mno-avx2 -mno-avx512f) set_property(TARGET pm3rrg_rdv4_hardnested_avx PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -73,7 +73,7 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS) hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c) - target_compile_options(pm3rrg_rdv4_hardnested_avx2 PRIVATE -Wall -O3) + target_compile_options(pm3rrg_rdv4_hardnested_avx2 PRIVATE -Wall -Werror -O3) target_compile_options(pm3rrg_rdv4_hardnested_avx2 BEFORE PRIVATE -mmmx -msse2 -mavx -mavx2 -mno-avx512f) set_property(TARGET pm3rrg_rdv4_hardnested_avx2 PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -88,7 +88,7 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS) hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c) - target_compile_options(pm3rrg_rdv4_hardnested_avx512 PRIVATE -Wall -O3) + target_compile_options(pm3rrg_rdv4_hardnested_avx512 PRIVATE -Wall -Werror -O3) target_compile_options(pm3rrg_rdv4_hardnested_avx512 BEFORE PRIVATE -mmmx -msse2 -mavx -mavx2 -mavx512f) set_property(TARGET pm3rrg_rdv4_hardnested_avx512 PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -113,7 +113,7 @@ add_library(pm3rrg_rdv4_hardnested STATIC hardnested/hardnested_bruteforce.c $ ${SIMD_TARGETS}) -target_compile_options(pm3rrg_rdv4_hardnested PRIVATE -Wall -O3) +target_compile_options(pm3rrg_rdv4_hardnested PRIVATE -Wall -Werror -O3) set_property(TARGET pm3rrg_rdv4_hardnested PROPERTY POSITION_INDEPENDENT_CODE ON) target_include_directories(pm3rrg_rdv4_hardnested PRIVATE ../../common diff --git a/client/deps/jansson.cmake b/client/deps/jansson.cmake index 42c701d5e..c91a47047 100644 --- a/client/deps/jansson.cmake +++ b/client/deps/jansson.cmake @@ -14,5 +14,5 @@ add_library(pm3rrg_rdv4_jansson STATIC target_compile_definitions(pm3rrg_rdv4_jansson PRIVATE HAVE_STDINT_H) target_include_directories(pm3rrg_rdv4_jansson INTERFACE jansson) -target_compile_options(pm3rrg_rdv4_jansson PRIVATE -Wall -Wno-unused-function -O3) +target_compile_options(pm3rrg_rdv4_jansson PRIVATE -Wall -Werror -Wno-unused-function -O3) set_property(TARGET pm3rrg_rdv4_jansson PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/client/deps/lua.cmake b/client/deps/lua.cmake index 5cf33d724..12870342e 100644 --- a/client/deps/lua.cmake +++ b/client/deps/lua.cmake @@ -52,5 +52,5 @@ if (NOT MINGW) endif (NOT MINGW) target_include_directories(pm3rrg_rdv4_lua INTERFACE liblua) -target_compile_options(pm3rrg_rdv4_lua PRIVATE -Wall -O3) +target_compile_options(pm3rrg_rdv4_lua PRIVATE -Wall -Werror -O3) set_property(TARGET pm3rrg_rdv4_lua PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/client/deps/mbedtls.cmake b/client/deps/mbedtls.cmake index c726ddeba..40929e1ea 100644 --- a/client/deps/mbedtls.cmake +++ b/client/deps/mbedtls.cmake @@ -44,5 +44,5 @@ add_library(pm3rrg_rdv4_mbedtls STATIC target_include_directories(pm3rrg_rdv4_mbedtls PRIVATE ../../common) target_include_directories(pm3rrg_rdv4_mbedtls INTERFACE ../../common/mbedtls) -target_compile_options(pm3rrg_rdv4_mbedtls PRIVATE -Wall -O3) +target_compile_options(pm3rrg_rdv4_mbedtls PRIVATE -Wall -Werror -O3) set_property(TARGET pm3rrg_rdv4_mbedtls PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/client/deps/reveng.cmake b/client/deps/reveng.cmake index 1040730f1..d7e3cfd8a 100644 --- a/client/deps/reveng.cmake +++ b/client/deps/reveng.cmake @@ -13,5 +13,5 @@ target_include_directories(pm3rrg_rdv4_reveng PRIVATE ../src ../../include) target_include_directories(pm3rrg_rdv4_reveng INTERFACE reveng) -target_compile_options(pm3rrg_rdv4_reveng PRIVATE -Wall -O3) +target_compile_options(pm3rrg_rdv4_reveng PRIVATE -Wall -Werror -O3) set_property(TARGET pm3rrg_rdv4_reveng PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/client/deps/tinycbor.cmake b/client/deps/tinycbor.cmake index c74618149..5a6abda25 100644 --- a/client/deps/tinycbor.cmake +++ b/client/deps/tinycbor.cmake @@ -11,5 +11,5 @@ add_library(pm3rrg_rdv4_tinycbor STATIC target_include_directories(pm3rrg_rdv4_tinycbor INTERFACE tinycbor) # Strange errors on Mingw when compiling with -O3 -target_compile_options(pm3rrg_rdv4_tinycbor PRIVATE -Wall -O2) +target_compile_options(pm3rrg_rdv4_tinycbor PRIVATE -Wall -Werror -O2) set_property(TARGET pm3rrg_rdv4_tinycbor PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/client/deps/whereami.cmake b/client/deps/whereami.cmake index 721873066..d2d6a5b2a 100644 --- a/client/deps/whereami.cmake +++ b/client/deps/whereami.cmake @@ -2,5 +2,5 @@ add_library(pm3rrg_rdv4_whereami STATIC whereami/whereami.c) target_compile_definitions(pm3rrg_rdv4_whereami PRIVATE WAI_PM3_TUNED) target_include_directories(pm3rrg_rdv4_whereami INTERFACE whereami) -target_compile_options(pm3rrg_rdv4_whereami PRIVATE -Wall -O3) +target_compile_options(pm3rrg_rdv4_whereami PRIVATE -Wall -Werror -O3) set_property(TARGET pm3rrg_rdv4_whereami PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/client/src/proxmark3.c b/client/src/proxmark3.c index 33a108811..d1507923a 100644 --- a/client/src/proxmark3.c +++ b/client/src/proxmark3.c @@ -38,7 +38,7 @@ #ifndef LIBPM3 #define BANNERMSG1 " Iceman :coffee:" #define BANNERMSG2 " :snowflake: bleeding edge" -#define BANNERMSG3 "Release v4.13441 - midsummer" +#define BANNERMSG3 " https://github.com/rfidresearchgroup/proxmark3/" typedef enum LogoMode { UTF8, ANSI, ASCII } LogoMode; diff --git a/common/default_version_pm3.c b/common/default_version_pm3.c index 7ca58e992..8547182dc 100644 --- a/common/default_version_pm3.c +++ b/common/default_version_pm3.c @@ -1,5 +1,5 @@ #include "common.h" -/* Generated file, do not edit */ +/* This is the default version_pm3.c file that Makefile.common falls back to if neither sh nor perl are available */ #ifndef ON_DEVICE #define SECTVERSINFO #else @@ -8,9 +8,8 @@ const struct version_information SECTVERSINFO version_information = { VERSION_INFORMATION_MAGIC, - 1, - 1, - 1, - "RRG/Iceman/master/v4.13441", - "2021-06-25 23:39:10", + 1, /* version 1 */ + 0, /* version information not present */ + 2, /* cleanliness couldn't be determined */ + /* Remaining fields: zero */ }; diff --git a/common_arm/Makefile.common b/common_arm/Makefile.common index 2f5c52b5f..e6d1636e9 100644 --- a/common_arm/Makefile.common +++ b/common_arm/Makefile.common @@ -40,7 +40,7 @@ VPATH = . ../common_arm ../common ../common/crapto1 ../common/mbedtls ../common/ INCLUDES = ../include/proxmark3_arm.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/pm3_cmd.h ARMCFLAGS = -mthumb-interwork -fno-builtin -DEFCFLAGS = -Wall -Os -pedantic -fstrict-aliasing -pipe +DEFCFLAGS = -Wall -Werror -Os -pedantic -fstrict-aliasing -pipe # Some more warnings we want as errors: DEFCFLAGS += -Wbad-function-cast -Wchar-subscripts -Wundef -Wunused -Wuninitialized -Wpointer-arith -Wformat -Wformat-security -Winit-self -Wmissing-include-dirs -Wnested-externs -Wempty-body -Wignored-qualifiers -Wmissing-field-initializers -Wtype-limits From 3ea3b5cd9c0327a5b17787f38aeb4b4ab904a568 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jun 2021 23:57:07 +0200 Subject: [PATCH 127/309] instructions --- .github/ISSUE_TEMPLATE/checklist-for-release.md | 10 ++++++++++ CHANGELOG.md | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/checklist-for-release.md b/.github/ISSUE_TEMPLATE/checklist-for-release.md index e9b488e26..ac5aba883 100644 --- a/.github/ISSUE_TEMPLATE/checklist-for-release.md +++ b/.github/ISSUE_TEMPLATE/checklist-for-release.md @@ -47,3 +47,13 @@ sudo make install; pushd /tmp; proxmark3 -c 'data load -f lf_EM4x05.pm3;lf searc - [ ] OSX - [ ] Android - [ ] Termux + +# creating release +`make release RELEASE_NAME="ice awesome"` +last line of output, gives you next command to run +Sample: `git push && git push origin v4.15000` + + +Go to Github releases, create release based on the new created tag and publish + + diff --git a/CHANGELOG.md b/CHANGELOG.md index f52221119..fad7487c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] -## [midsummer][2021-06-25] +## [midsummer.4.13441][2021-06-25] - Added bruteforce function for the magic byte in `cmdlfnexwatch.c` and ability to clone with psk2 modulation (@Guilhem7, @MaximeBosca) - Changed `hw setmux` - improve user feedback for special case (@iceman1001) - Changed 'filename' - unified file name param across client (@iceman1001) From 079b6168d9a848c39dfc301ecb7720ebbb112f48 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 26 Jun 2021 00:45:54 +0200 Subject: [PATCH 128/309] text - update homebrew file --- .github/ISSUE_TEMPLATE/checklist-for-release.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/checklist-for-release.md b/.github/ISSUE_TEMPLATE/checklist-for-release.md index ac5aba883..eaf469cc7 100644 --- a/.github/ISSUE_TEMPLATE/checklist-for-release.md +++ b/.github/ISSUE_TEMPLATE/checklist-for-release.md @@ -55,5 +55,4 @@ Sample: `git push && git push origin v4.15000` Go to Github releases, create release based on the new created tag and publish - - +update homebrew repo, file `proxmark3.rb` with a SHA256 sum of the file `v4.15000.tar.gz` From 35ddebc03caecc968dc34207b1f76432bd648274 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 26 Jun 2021 01:23:08 +0200 Subject: [PATCH 129/309] updated gen3 gtu card text --- doc/magic_cards_notes.md | 153 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 151 insertions(+), 2 deletions(-) diff --git a/doc/magic_cards_notes.md b/doc/magic_cards_notes.md index a5056d6fa..0fbb3b027 100644 --- a/doc/magic_cards_notes.md +++ b/doc/magic_cards_notes.md @@ -14,7 +14,8 @@ Useful docs: * [MIFARE Classic DirectWrite, FUID version aka 1-write](#mifare-classic-directwrite-fuid-version-aka-1-write) * [MIFARE Classic DirectWrite, UFUID version](#mifare-classic-directwrite-ufuid-version) * [MIFARE Classic, other versions](#mifare-classic-other-versions) - * [MIFARE Classic APDU aka Gen3](#mifare-classic-apdu-aka-gen3) + * [MIFARE Classic Gen3 aka APDU](#mifare-classic-gen3-aka-apdu) + * [MIFARE Classic Gen3 aka GTU](#mifare-classic-gen3-aka-gtu) * [MIFARE Classic Super](#mifare-classic-super) - [MIFARE Ultralight](#mifare-ultralight) * [MIFARE Ultralight blocks 0..2](#mifare-ultralight-blocks-02) @@ -400,7 +401,7 @@ hf 14a raw -c 85000000000000000000000000000008 * ZXUID, EUID, ICUID ? * Some cards exhibit a specific SAK=28 ?? -## MIFARE Classic APDU aka Gen3 +## MIFARE Classic Gen3 aka APDU ### Identify @@ -467,6 +468,154 @@ hf 14a raw -s -c -t 2000 90F0CCCC10 041219c3219316984200e32000000000 # lock (uid/block0?) forever: hf 14a raw -s -c 90FD111100 ``` +--------- +## MIFARE Classic Gen3 aka GTU + +### Identify + +Tag doesn't get identified by latest Proxmark3 client correct but instead mislabled as Gen2/CUID + +``` +hf 14a info +... +[+] Magic capabilities : Gen 2 / CUID +``` + + +### Magic commands + +Android compatible - unknown status + +* issue special APDUs + +``` +cla ins p1 p2 len + CF 00 00 00 00 32 + CF 00 00 00 00 35 + CF 00 00 00 00 34 + CF 00 00 00 00 68 + CF 00 00 00 00 69 <00> + CF 00 00 00 00 CE // Backdoor read card + CF 00 00 00 00 CD // Backdoor write card + CF 00 00 00 00 FE aabbccdd // set password to AABBCCDD + CF 00 00 00 00 F1 // fuse is set ??? + CF 00 00 00 00 F0 // fuse ??? +``` +Note: It doesn't seem to follow a APDU structure per default, + + +### Characteristics + +* UID: 4b, 7b and 10b versions +* ATQA/SAK: changeable +* BCC: +* ATS: changable +* Card Type: changeable +* Shadow mode: GTU +* Backdoor password mode: + +#### Possible card types +Known Preset Change Available: +* MIFARE Mini +* MIFARE 1k S50 4 byte UID +* MIFARE 1k S50 7 byte UID +* MIFARE 1k S50 10 byte UID +* MIFARE 4k S70 4 byte UID +* MIFARE 4k S70 7 byte UID +* MIFARE 4k S70 10 byte UID +* Ultralight +* Ultralight-C +* Ultralight Ev1 +* NTAG + + + +### Proxmark3 commands + +``` +# view contents of tag memory: +hf mf gview +``` + +Equivalent: + + +change ATQA / SAK +================= +``` +hf 14a raw -s -c -t 1000 cf0000000035 +hf 14a raw -s -c -t 1000 cf0000000035440028 // ATQA 00 44 SAK 28 +``` + +change ATS +========== +It should be noted that when SAK=20,28, ATS must be turned on, otherwise the card will not be recognized! + +``` +hf 14a raw -s -c -t 1000 cf0000000034 +hf 14a raw -s -c -t 1000 cf000000003406067577810280 // ATS to 0606757781028002F0 +``` + * length 0, ATS is not sent + * when SAK is 20 or 28, ATS must be set, otherwise the card cannot be read + * the last two digits of ATS are CRC and cannot be counted as length + +set UID length (4, 7, 10) +========================= +``` +hf 14a raw -s -c -t 1000 cf0000000068 +hf 14a raw -s -c -t 1000 cf000000006801 // set UID length to 7 bytes +``` + * param=00: 4 bytes 01: 7 bytes 02: 10 bytes + +Set 14443A/B-UID +================ +--> missing instructions. + + + +Set Ultralight mode +=================== +``` +hf 14a raw -s -c -t 1000 cf0000000069<00> +``` + * 01: UL agreement opened + * 00: UL agreement closed + * in this mode, if SAK=00 ATQA=0044 (Pm3 sequence), it can become an Ultralight card + + +set shadow mode (GTU) +===================== + +This mode is divided into four states: off (pre-write), on (on restore), don’t care, and high-speed read and write. +If you use it, please enter the pre-write mode first. At this time, write the full card data. +After writing, set it to on. At this time, after writing the data, the first time you read the data just written, the next time you read It is the pre-written data. All modes support this operation. It should be noted that using any block to read and write in this mode may give wrong results. + +``` +hf 14a raw -s -c -t 1000 cf0000000032 +``` +Param | Description + 00 | Closed, shadow data can be written at this time + 01 | Open, start restore + 02 | Turn it off completely, as a normal card + 03 | High-speed read and write mode + +Any block read and write +======================== +Using the backdoor command can read and write any area without password, similar to UID card, it should be noted that this command must be used to modify UID. + +``` +hf 14a raw -s -c -t 1000 cf00000000CE // Backdoor read card +hf 14a raw -s -c -t 1000 cf00000000CD // Backdoor write card +``` + +set backdoor password +===================== +All backdoor operations are protected by passwords. If password is forgotten, the card will be scrapped +default password is 00000000 +``` +hf 14a raw -s -c -t 1000 cf00000000feaabbccdd // set password to AABBCCDD +``` + ## MIFARE Classic Super From 6f579e5b6c00e962b3c7250467f0033eb8fd9629 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 29 Jun 2021 01:56:16 +0200 Subject: [PATCH 130/309] mfkeys --- client/dictionaries/mfc_default_keys.dic | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index 4ac03904d..688165fbe 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -21,6 +21,9 @@ d3f7d3f7d3f7 # key A Wien a0478cc39091 533cb6c723f6 8fd0a4f256e9 +e00000000000 # iCopy-X +e7d6064c5860 +b27ccab30dbd # d2ece8b9395e # lib / Nat Bieb # NSCP default key From adb207268db4d83c4b0b1c3fb30afa26f74b1bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nemanja=20Nedeljkovi=C4=87?= Date: Tue, 29 Jun 2021 12:52:35 +0200 Subject: [PATCH 131/309] Change in hf 15 raw broke support hf_15_magic.lua There was a change in `hf 15 raw` and this script was not updated to support that change --- client/luascripts/hf_15_magic.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/luascripts/hf_15_magic.lua b/client/luascripts/hf_15_magic.lua index 173cf1ee7..e7c6bf1ce 100644 --- a/client/luascripts/hf_15_magic.lua +++ b/client/luascripts/hf_15_magic.lua @@ -68,10 +68,10 @@ end --- Set UID on magic command enabled on a ICEMAN based REPO local function magicUID_iceman(b0, b1) print('Using backdoor Magic tag function') - core.console('hf 15 raw -2 -c 02213E00000000') - core.console('hf 15 raw -2 -c 02213F69960000') - core.console('hf 15 raw -2 -c 022138'..b1) - core.console('hf 15 raw -2 -c 022139'..b0) + core.console('hf 15 raw -2 -c -d 02213E00000000') + core.console('hf 15 raw -2 -c -d 02213F69960000') + core.console('hf 15 raw -2 -c -d 022138'..b1) + core.console('hf 15 raw -2 -c -d 022139'..b0) end -- --- Set UID on magic command enabled, OFFICAL REPO From 9af8c003d88d124acd81b28eae1a242db3c74b56 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 29 Jun 2021 15:00:15 +0200 Subject: [PATCH 132/309] Termux: fix instructions, thanks @ysard --- doc/termux_notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/termux_notes.md b/doc/termux_notes.md index da737b608..ae7207ddf 100644 --- a/doc/termux_notes.md +++ b/doc/termux_notes.md @@ -99,7 +99,7 @@ pkg install proxmark3-git ``` ### Optional: Building Proxmark3 client from source ``` -pkg install make clang clang++ readline libc++ git +pkg install make clang readline libc++ git git clone https://github.com/RfidResearchGroup/proxmark3.git cd proxmark make clean && make client From 9487953359caaf8fa5ef41a2fc7d8fc68cfe2404 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 29 Jun 2021 19:59:42 +0300 Subject: [PATCH 133/309] asn1_value_integer now works in pure hex to int instead of BCD --- client/src/crypto/asn1dump.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/crypto/asn1dump.c b/client/src/crypto/asn1dump.c index 84ff1d4a2..808f77c5e 100644 --- a/client/src/crypto/asn1dump.c +++ b/client/src/crypto/asn1dump.c @@ -197,14 +197,14 @@ static unsigned long asn1_value_integer(const struct tlv *tlv, unsigned start, u i = start; for (; i < end - 1; i += 2) { - ret *= 10; + ret = ret << 4; // was: ret*=10 ret += tlv->value[i / 2] >> 4; - ret *= 10; + ret = ret << 4; // was: ret*=10 ret += tlv->value[i / 2] & 0xf; } if (end & 1) { - ret *= 10; + ret = ret << 4; // was: ret*=10 ret += tlv->value[end / 2] >> 4; } From d6e55a2f40ae008620206254c99345597e4d178c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 29 Jun 2021 22:23:39 +0200 Subject: [PATCH 134/309] textual --- client/src/crypto/asn1dump.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/src/crypto/asn1dump.c b/client/src/crypto/asn1dump.c index 808f77c5e..46f7a5beb 100644 --- a/client/src/crypto/asn1dump.c +++ b/client/src/crypto/asn1dump.c @@ -1,4 +1,4 @@ -//----------------------------------------------------------------------------- +// //----------------------------------------------------------------------------- // Copyright (C) 2018 Merlok // // This code is licensed to you under the terms of the GNU GPL, version 2 or, @@ -227,10 +227,11 @@ static void asn1_tag_dump_integer(const struct tlv *tlv, const struct asn1_tag * for (size_t i = 0; i < tlv->len; i++) { val = (val << 8) + tlv->value[i]; } - PrintAndLogEx(NORMAL, " value4b: %d", val); + PrintAndLogEx(NORMAL, " value: %d (0x%08X)", val, val); return; } - PrintAndLogEx(NORMAL, " value: %lu", asn1_value_integer(tlv, 0, tlv->len * 2)); + uint32_t val = asn1_value_integer(tlv, 0, tlv->len * 2); + PrintAndLogEx(NORMAL, " value: %lu (0x%X)", val, val); } static char *asn1_oid_description(const char *oid, bool with_group_desc) { @@ -326,7 +327,7 @@ bool asn1_tag_dump(const struct tlv *tlv, int level, bool *candump) { */ PrintAndLogEx(INFO, - "%*s-- %2x [%02zx] '"_YELLOW_("%s") "'" NOLF + "%*s-- %02X [%02X] '"_YELLOW_("%s") "'" NOLF , (level * 4) , " " , tlv->tag From 97f3a972d4b0931b1f929c4ee6a8ad24456e07d7 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 30 Jun 2021 12:19:12 +0300 Subject: [PATCH 135/309] added default parameters for `hf cipurse`. now not needs to enter them each time --- client/src/cmdhfcipurse.c | 92 ++++++++++++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 15 deletions(-) diff --git a/client/src/cmdhfcipurse.c b/client/src/cmdhfcipurse.c index 41dd9062d..f27c7c1f2 100644 --- a/client/src/cmdhfcipurse.c +++ b/client/src/cmdhfcipurse.c @@ -32,6 +32,10 @@ #include "util.h" #include "fileutils.h" // laodFileJSONroot +static uint8_t defaultKeyId = 1; +static uint8_t defaultKey[CIPURSE_AES_KEY_LENGTH] = CIPURSE_DEFAULT_KEY; +static uint16_t defaultFileId = 0x2ff7; + static int CmdHelp(const char *Cmd); static int CmdHFCipurseInfo(const char *Cmd) { @@ -117,7 +121,7 @@ static int CmdHFCipurseAuth(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - uint8_t keyId = arg_get_int_def(ctx, 3, 1); + uint8_t keyId = arg_get_int_def(ctx, 3, defaultKeyId); uint8_t hdata[250] = {0}; int hdatalen = sizeof(hdata); @@ -128,9 +132,11 @@ static int CmdHFCipurseAuth(const char *Cmd) { return PM3_EINVARG; } - uint8_t key[] = {0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73}; + uint8_t key[CIPURSE_AES_KEY_LENGTH] = {0}; if (hdatalen) memcpy(key, hdata, CIPURSE_AES_KEY_LENGTH); + else + memcpy(key, defaultKey, sizeof(defaultKey)); SetAPDULogging(APDULogging); @@ -150,7 +156,7 @@ static int CmdHFCipurseAuth(const char *Cmd) { uint8_t kvv[CIPURSE_KVV_LENGTH] = {0}; CipurseCGetKVV(key, kvv); if (verbose) { - PrintAndLogEx(INFO, "Key id" _YELLOW_("%d") " key " _YELLOW_("%s") " KVV " _YELLOW_("%s") + PrintAndLogEx(INFO, "Key id " _YELLOW_("%d") " key " _YELLOW_("%s") " KVV " _YELLOW_("%s") , keyId , sprint_hex(key, CIPURSE_AES_KEY_LENGTH) , sprint_hex_inrow(kvv, CIPURSE_KVV_LENGTH) @@ -182,6 +188,8 @@ static int CLIParseKeyAndSecurityLevels(CLIParserContext *ctx, size_t keyid, siz } if (hdatalen) memcpy(key, hdata, CIPURSE_AES_KEY_LENGTH); + else + memcpy(key, defaultKey, sizeof(defaultKey)); *sreq = CPSMACed; *sresp = CPSMACed; @@ -254,11 +262,11 @@ static int CmdHFCipurseReadFile(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - uint8_t keyId = arg_get_int_def(ctx, 3, 1); + uint8_t keyId = arg_get_int_def(ctx, 3, defaultKeyId); CipurseChannelSecurityLevel sreq = CPSMACed; CipurseChannelSecurityLevel sresp = CPSMACed; - uint8_t key[] = CIPURSE_DEFAULT_KEY; + uint8_t key[CIPURSE_AES_KEY_LENGTH] = {0}; int res = CLIParseKeyAndSecurityLevels(ctx, 4, 8, 9, key, &sreq, &sresp); if (res) { CLIParserFree(ctx); @@ -274,7 +282,7 @@ static int CmdHFCipurseReadFile(const char *Cmd) { return PM3_EINVARG; } - uint16_t fileId = 0x2ff7; + uint16_t fileId = defaultFileId; if (hdatalen) fileId = (hdata[0] << 8) + hdata[1]; @@ -366,19 +374,19 @@ static int CmdHFCipurseWriteFile(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - uint8_t keyId = arg_get_int_def(ctx, 3, 1); + uint8_t keyId = arg_get_int_def(ctx, 3, defaultKeyId); CipurseChannelSecurityLevel sreq = CPSMACed; CipurseChannelSecurityLevel sresp = CPSMACed; - uint8_t key[] = CIPURSE_DEFAULT_KEY; + uint8_t key[CIPURSE_AES_KEY_LENGTH] = {0}; int res = CLIParseKeyAndSecurityLevels(ctx, 4, 8, 9, key, &sreq, &sresp); if (res) { CLIParserFree(ctx); return PM3_EINVARG; } - uint16_t fileId = 0x2ff7; + uint16_t fileId = defaultFileId; uint8_t hdata[250] = {0}; int hdatalen = sizeof(hdata); @@ -491,11 +499,11 @@ static int CmdHFCipurseReadFileAttr(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - uint8_t keyId = arg_get_int_def(ctx, 3, 1); + uint8_t keyId = arg_get_int_def(ctx, 3, defaultKeyId); CipurseChannelSecurityLevel sreq = CPSMACed; CipurseChannelSecurityLevel sresp = CPSMACed; - uint8_t key[] = CIPURSE_DEFAULT_KEY; + uint8_t key[CIPURSE_AES_KEY_LENGTH] = {0}; int res = CLIParseKeyAndSecurityLevels(ctx, 4, 7, 8, key, &sreq, &sresp); if (res) { CLIParserFree(ctx); @@ -511,7 +519,7 @@ static int CmdHFCipurseReadFileAttr(const char *Cmd) { return PM3_EINVARG; } - uint16_t fileId = 0x2ff7; + uint16_t fileId = defaultFileId; if (hdatalen) fileId = (hdata[0] << 8) + hdata[1]; @@ -617,11 +625,11 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - uint8_t keyId = arg_get_int_def(ctx, 3, 1); + uint8_t keyId = arg_get_int_def(ctx, 3, defaultKeyId); CipurseChannelSecurityLevel sreq = CPSMACed; CipurseChannelSecurityLevel sresp = CPSMACed; - uint8_t key[] = CIPURSE_DEFAULT_KEY; + uint8_t key[CIPURSE_AES_KEY_LENGTH] = {0}; int res = CLIParseKeyAndSecurityLevels(ctx, 4, 6, 7, key, &sreq, &sresp); if (res) { CLIParserFree(ctx); @@ -637,7 +645,7 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) { return PM3_EINVARG; } - uint16_t fileId = 0x2ff7; + uint16_t fileId = defaultFileId; if (hdatalen) fileId = (hdata[0] << 8) + hdata[1]; @@ -703,6 +711,59 @@ static int CmdHFCipurseTest(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHFCipurseDefault(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf cipurse default", + "Set default parameters for access to cipurse card", + "hf cipurse default -n 1 -k 65656565656565656565656565656565 --fid 2ff7 -> Set key, key id and file id\n"); + + void *argtable[] = { + arg_param_begin, + arg_int0("n", NULL, "", "Key ID"), + arg_str0("k", "key", "", "Authentication key"), + arg_str0(NULL, "fid", "", "File ID"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + defaultKeyId = arg_get_int_def(ctx, 1, defaultKeyId); + + uint8_t hdata[250] = {0}; + int hdatalen = sizeof(hdata); + CLIGetHexWithReturn(ctx, 2, hdata, &hdatalen); + if (hdatalen && hdatalen != 16) { + PrintAndLogEx(ERR, _RED_("ERROR:") " key length for AES128 must be 16 bytes only"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + if (hdatalen) + memcpy(defaultKey, hdata, CIPURSE_AES_KEY_LENGTH); + + memset(hdata, 0, sizeof(hdata)); + hdatalen = sizeof(hdata); + CLIGetHexWithReturn(ctx, 3, hdata, &hdatalen); + if (hdatalen && hdatalen != 2) { + PrintAndLogEx(ERR, _RED_("ERROR:") " file id length must be 2 bytes only"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + if (hdatalen) + defaultFileId = (hdata[0] << 8) + hdata[1]; + + CLIParserFree(ctx); + + + PrintAndLogEx(INFO, "-----------" _CYAN_("Default parameters") "---------------------------------"); + + PrintAndLogEx(INFO, "Key ID : %d", defaultKeyId); + PrintAndLogEx(INFO, "Key : %s", sprint_hex(defaultKey, sizeof(defaultKey))); + PrintAndLogEx(INFO, "File ID: 0x%04x", defaultFileId); + + return PM3_SUCCESS; +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help."}, {"info", CmdHFCipurseInfo, IfPm3Iso14443a, "Get info about CIPURSE tag"}, @@ -711,6 +772,7 @@ static command_t CommandTable[] = { {"write", CmdHFCipurseWriteFile, IfPm3Iso14443a, "Write binary file"}, {"aread", CmdHFCipurseReadFileAttr, IfPm3Iso14443a, "Read file attributes"}, {"delete", CmdHFCipurseDeleteFile, IfPm3Iso14443a, "Delete file"}, + {"default", CmdHFCipurseDefault, IfPm3Iso14443a, "Set default key and file id for all the other commands"}, {"test", CmdHFCipurseTest, AlwaysAvailable, "Tests"}, {NULL, NULL, 0, NULL} }; From 9c65dacb5069839703855c2c58b8dc407fe8e2bb Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 30 Jun 2021 12:26:08 +0300 Subject: [PATCH 136/309] added clear parameter --- client/src/cmdhfcipurse.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfcipurse.c b/client/src/cmdhfcipurse.c index f27c7c1f2..a4278695f 100644 --- a/client/src/cmdhfcipurse.c +++ b/client/src/cmdhfcipurse.c @@ -719,6 +719,7 @@ static int CmdHFCipurseDefault(const char *Cmd) { void *argtable[] = { arg_param_begin, + arg_lit0(NULL, "clear", "resets to defaults"), arg_int0("n", NULL, "", "Key ID"), arg_str0("k", "key", "", "Authentication key"), arg_str0(NULL, "fid", "", "File ID"), @@ -726,11 +727,19 @@ static int CmdHFCipurseDefault(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, true); - defaultKeyId = arg_get_int_def(ctx, 1, defaultKeyId); + bool clearing = arg_get_lit(ctx, 1); + if (clearing) { + defaultKeyId = 1; + defaultFileId = 0x2ff7; + uint8_t ckey[CIPURSE_AES_KEY_LENGTH] = CIPURSE_DEFAULT_KEY; + memcpy(defaultKey, ckey, CIPURSE_AES_KEY_LENGTH); + } + + defaultKeyId = arg_get_int_def(ctx, 2, defaultKeyId); uint8_t hdata[250] = {0}; int hdatalen = sizeof(hdata); - CLIGetHexWithReturn(ctx, 2, hdata, &hdatalen); + CLIGetHexWithReturn(ctx, 3, hdata, &hdatalen); if (hdatalen && hdatalen != 16) { PrintAndLogEx(ERR, _RED_("ERROR:") " key length for AES128 must be 16 bytes only"); CLIParserFree(ctx); @@ -742,7 +751,7 @@ static int CmdHFCipurseDefault(const char *Cmd) { memset(hdata, 0, sizeof(hdata)); hdatalen = sizeof(hdata); - CLIGetHexWithReturn(ctx, 3, hdata, &hdatalen); + CLIGetHexWithReturn(ctx, 4, hdata, &hdatalen); if (hdatalen && hdatalen != 2) { PrintAndLogEx(ERR, _RED_("ERROR:") " file id length must be 2 bytes only"); CLIParserFree(ctx); From d43f6ffc441adbb7271f6e05f598c48b199bf786 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 30 Jun 2021 12:32:52 +0300 Subject: [PATCH 137/309] make style --- client/src/cmdhfcipurse.c | 4 ++-- doc/commands.json | 26 +++++++++++++++++++++----- doc/commands.md | 1 + 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/client/src/cmdhfcipurse.c b/client/src/cmdhfcipurse.c index a4278695f..02010e454 100644 --- a/client/src/cmdhfcipurse.c +++ b/client/src/cmdhfcipurse.c @@ -734,7 +734,7 @@ static int CmdHFCipurseDefault(const char *Cmd) { uint8_t ckey[CIPURSE_AES_KEY_LENGTH] = CIPURSE_DEFAULT_KEY; memcpy(defaultKey, ckey, CIPURSE_AES_KEY_LENGTH); } - + defaultKeyId = arg_get_int_def(ctx, 2, defaultKeyId); uint8_t hdata[250] = {0}; @@ -765,7 +765,7 @@ static int CmdHFCipurseDefault(const char *Cmd) { PrintAndLogEx(INFO, "-----------" _CYAN_("Default parameters") "---------------------------------"); - + PrintAndLogEx(INFO, "Key ID : %d", defaultKeyId); PrintAndLogEx(INFO, "Key : %s", sprint_hex(defaultKey, sizeof(defaultKey))); PrintAndLogEx(INFO, "File ID: 0x%04x", defaultFileId); diff --git a/doc/commands.json b/doc/commands.json index d5c903f99..c52b3bbf5 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -973,7 +973,7 @@ }, "help": { "command": "help", - "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log /home/osboxes/.proxmark3/logs/log_20210625.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", + "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log e:\\proxspace\\pm3/.proxmark3/logs/log_20210630.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", "notes": [ "auto" ], @@ -1722,6 +1722,22 @@ ], "usage": "hf cipurse auth [-hav] [-n ] [-k ]" }, + "hf cipurse default": { + "command": "hf cipurse default", + "description": "set default parameters for access to cipurse card", + "notes": [ + "hf cipurse default -n 1 -k 65656565656565656565656565656565 --fid 2ff7 -> set key, key id and file id" + ], + "offline": false, + "options": [ + "-h, --help this help", + "--clear resets to defaults", + "-n key id", + "-k, --key authentication key", + "--fid file id" + ], + "usage": "hf cipurse default [-h] [--clear] [-n ] [-k ] [--fid ]" + }, "hf cipurse delete": { "command": "hf cipurse delete", "description": "read file by file id with key id and key. if no key is supplied, default key of 737373...7373 will be used", @@ -5078,8 +5094,8 @@ "command": "hw connect", "description": "connects to a proxmark3 device via specified serial port. baudrate here is only for physical uart or uart-bt, not for usb-cdc or blue shark add-on", "notes": [ - "hw connect -p /dev/ttyacm0", - "hw connect -p /dev/ttyacm0 -b 115200" + "hw connect -p com3", + "hw connect -p com3 -b 115200" ], "offline": true, "options": [ @@ -9201,8 +9217,8 @@ } }, "metadata": { - "commands_extracted": 571, + "commands_extracted": 572, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2021-06-25T21:34:48" + "extracted_on": "2021-06-30T09:30:39" } } \ No newline at end of file diff --git a/doc/commands.md b/doc/commands.md index 433b44e26..a0625577c 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -247,6 +247,7 @@ Check column "offline" for their availability. |`hf cipurse write `|N |`Write binary file` |`hf cipurse aread `|N |`Read file attributes` |`hf cipurse delete `|N |`Delete file` +|`hf cipurse default `|N |`Set default key and file id for all the other commands` |`hf cipurse test `|Y |`Tests` From 2fa6c4643e62e23511ffc5c7a2f2ef52114790d5 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 1 Jul 2021 19:53:57 +0300 Subject: [PATCH 138/309] desfire channel sketch --- client/CMakeLists.txt | 1 + client/Makefile | 1 + client/src/cmdhfmfdes.c | 117 ++++++++++++++ client/src/mifare/desfire_crypto.c | 11 ++ client/src/mifare/desfire_crypto.h | 2 + client/src/mifare/desfirecore.c | 236 +++++++++++++++++++++++++++++ client/src/mifare/desfirecore.h | 75 +++++++++ include/protocols.h | 1 + 8 files changed, 444 insertions(+) create mode 100644 client/src/mifare/desfirecore.c create mode 100644 client/src/mifare/desfirecore.h diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index a81682337..0030df688 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -226,6 +226,7 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/mifare/mifarehost.c ${PM3_ROOT}/client/src/nfc/ndef.c ${PM3_ROOT}/client/src/mifare/desfire_crypto.c + ${PM3_ROOT}/client/src/mifare/desfirecore.c ${PM3_ROOT}/client/src/uart/uart_posix.c ${PM3_ROOT}/client/src/uart/uart_win32.c ${PM3_ROOT}/client/src/ui/overlays.ui diff --git a/client/Makefile b/client/Makefile index 9ed3feb86..ef8130c7d 100644 --- a/client/Makefile +++ b/client/Makefile @@ -572,6 +572,7 @@ SRCS = aiddesfire.c \ loclass/elite_crack.c \ loclass/ikeys.c \ mifare/desfire_crypto.c \ + mifare/desfirecore.c \ mifare/mad.c \ mifare/mfkey.c \ mifare/mifare4.c \ diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 2608a29eb..04079eba3 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5116,6 +5116,121 @@ static int CmdHF14aDesMAD(const char *Cmd) { } */ +static int CmdHF14ADesGetAIDs(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes getaids", + "Get Application IDs list from card. Master key needs to be provided.", + "hf mfdes getaids -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "apdu", "show APDU requests and responses"), + arg_lit0("v", "verbose", "show technical data"), + arg_int0("n", "keyno", "", "Key number"), + arg_int0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), + arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_int0("f", "kdf", "", "Key Derivation Function (KDF): None(default), AN10922, Gallagher"), + arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + +/* + int aidlength = 0; + uint8_t aid[3] = {0}; + CLIGetHexWithReturn(ctx, 1, aid, &aidlength); + swap24(aid); + uint8_t vkey[16] = {0}; + int vkeylen = 0; + CLIGetHexWithReturn(ctx, 2, vkey, &vkeylen); + + if (vkeylen > 0) { + if (vkeylen == 8) { + memcpy(&deskeyList[deskeyListLen], vkey, 8); + deskeyListLen++; + } else if (vkeylen == 16) { + memcpy(&aeskeyList[aeskeyListLen], vkey, 16); + aeskeyListLen++; + } else if (vkeylen == 24) { + memcpy(&k3kkeyList[k3kkeyListLen], vkey, 16); + k3kkeyListLen++; + } else { + PrintAndLogEx(ERR, "Specified key must have 8, 16 or 24 bytes length."); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } + + uint8_t dict_filename[FILE_PATH_SIZE + 2] = {0}; + int dict_filenamelen = 0; + if (CLIParamStrToBuf(arg_get_str(ctx, 3), dict_filename, FILE_PATH_SIZE, &dict_filenamelen)) { + PrintAndLogEx(FAILED, "File name too long or invalid."); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + bool pattern1b = arg_get_lit(ctx, 4); + bool pattern2b = arg_get_lit(ctx, 5); + + if (pattern1b && pattern2b) { + PrintAndLogEx(ERR, "Pattern search mode must be 2-byte or 1-byte only."); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + if (dict_filenamelen && (pattern1b || pattern2b)) { + PrintAndLogEx(ERR, "Pattern search mode and dictionary mode can't be used in one command."); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + uint32_t startPattern = 0x0000; + uint8_t vpattern[2]; + int vpatternlen = 0; + CLIGetHexWithReturn(ctx, 6, vpattern, &vpatternlen); + if (vpatternlen > 0) { + if (vpatternlen <= 2) { + startPattern = (vpattern[0] << 8) + vpattern[1]; + } else { + PrintAndLogEx(ERR, "Pattern must be 2-byte length."); + CLIParserFree(ctx); + return PM3_EINVARG; + } + if (!pattern2b) + PrintAndLogEx(WARNING, "Pattern entered, but search mode not is 2-byte search."); + } + + uint8_t jsonname[250] = {0}; + int jsonnamelen = 0; + if (CLIParamStrToBuf(arg_get_str(ctx, 7), jsonname, sizeof(jsonname), &jsonnamelen)) { + PrintAndLogEx(ERR, "Invalid json name."); + CLIParserFree(ctx); + return PM3_EINVARG; + } + jsonname[jsonnamelen] = 0; + + bool verbose = arg_get_lit(ctx, 8); + + // Get KDF input + uint8_t kdfInput[31] = {0}; + int kdfInputLen = 0; + uint8_t cmdKDFAlgo = arg_get_int_def(ctx, 9, 0); + CLIGetHexWithReturn(ctx, 10, kdfInput, &kdfInputLen); +*/ + CLIParserFree(ctx); + + + + + return PM3_SUCCESS; +} + +// {"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "Get Applications list"}, +static int CmdHF14ADesGetAppNames(const char *Cmd) { + return PM3_SUCCESS; +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"-----------", CmdHelp, IfPm3Iso14443a, "---------------------- " _CYAN_("general") " ----------------------"}, @@ -5134,6 +5249,8 @@ static command_t CommandTable[] = { {"createaid", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application ID"}, {"deleteaid", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "Delete Application ID"}, {"selectaid", CmdHF14ADesSelectApp, IfPm3Iso14443a, "Select Application ID"}, + {"getaids", CmdHF14ADesGetAIDs, IfPm3Iso14443a, "Get Application IDs list"}, + {"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "Get Applications list"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("Files") " -----------------------"}, {"changevalue", CmdHF14ADesChangeValue, IfPm3Iso14443a, "Write value of a value file (credit/debit/clear)"}, {"clearfile", CmdHF14ADesClearRecordFile, IfPm3Iso14443a, "Clear record File"}, diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index e3e785e6c..1767c9c47 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -51,6 +51,17 @@ static inline void update_key_schedules(desfirekey_t key) { // } } +int desfire_get_key_length(enum DESFIRE_CRYPTOALGO key_type) { + switch (key_type) { + case T_DES: return 8; + case T_3DES: return 16; + case T_3K3DES: return 24; + case T_AES: return 16; + } + return 0; +} + + /******************************************************************************/ void des_encrypt(void *out, const void *in, const void *key) { diff --git a/client/src/mifare/desfire_crypto.h b/client/src/mifare/desfire_crypto.h index ecc6fc4a5..9c67b1182 100644 --- a/client/src/mifare/desfire_crypto.h +++ b/client/src/mifare/desfire_crypto.h @@ -60,6 +60,8 @@ enum DESFIRE_CRYPTOALGO { T_AES = 0x03 }; +int desfire_get_key_length(enum DESFIRE_CRYPTOALGO key_type); + enum DESFIRE_AUTH_SCHEME { AS_LEGACY, AS_NEW diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c new file mode 100644 index 000000000..dbd77e1ca --- /dev/null +++ b/client/src/mifare/desfirecore.c @@ -0,0 +1,236 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2010 Romain Tartiere. +// Copyright (C) 2014 Iceman +// Copyright (C) 2021 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency Desfire core functions +//----------------------------------------------------------------------------- +// Info from here and many other soursec from the internet +// https://github.com/revk/DESFireAES +// https://github.com/step21/desfire_rfid +// https://github.com/patsys/desfire-python/blob/master/Desfire/DESFire.py +//----------------------------------------------------------------------------- + +#include "desfirecore.h" +#include +#include +#include +#include "ui.h" +#include "protocols.h" +#include "cmdhf14a.h" +#include "iso7816/apduinfo.h" // APDU manipulation / errorcodes +#include "iso7816/iso7816core.h" // APDU logging +#include "util_posix.h" // msleep +#include "mifare/desfire_crypto.h" + +void DesfireClearContext(DesfireContext *ctx) { + ctx->keyNum = 0; + ctx->keyType = T_DES; + memset(ctx->key, 0, sizeof(ctx->key)); + + ctx->authChannel = DACNone; + ctx->cmdChannel = DCCNative; + ctx->commMode = DCMNone; + + memset(ctx->sessionKeyMAC, 0, sizeof(ctx->sessionKeyMAC)); + memset(ctx->sessionKeyEnc, 0, sizeof(ctx->sessionKeyEnc)); + memset(ctx->lastIV, 0, sizeof(ctx->lastIV)); + ctx->cntrTx = 0; + ctx->cntrRx = 0; + memset(ctx->TI, 0, sizeof(ctx->TI)); +} + +void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key) { + DesfireClearContext(ctx); + + ctx->keyNum = keyNum; + ctx->keyType = keyType; + memcpy(ctx->key, key, desfire_get_key_length(keyType)); +} + +static int DESFIRESendApdu(bool activate_field, sAPDU apdu, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint16_t *sw) { + if (result_len) *result_len = 0; + if (sw) *sw = 0; + + uint16_t isw = 0; + int res = 0; + + if (activate_field) { + DropField(); + msleep(50); + } + + uint8_t data[APDU_RES_LEN] = {0}; + + // COMPUTE APDU + int datalen = 0; + if (APDUEncodeS(&apdu, false, 0x100, data, &datalen)) { // 100 == with Le + PrintAndLogEx(ERR, "APDU encoding error."); + return PM3_EAPDU_ENCODEFAIL; + } + + if (GetAPDULogging()) + PrintAndLogEx(SUCCESS, ">>>> %s", sprint_hex(data, datalen)); + + res = ExchangeAPDU14a(data, datalen, activate_field, true, result, max_result_len, (int *)result_len); + if (res != PM3_SUCCESS) { + return res; + } + + if (GetAPDULogging()) + PrintAndLogEx(SUCCESS, "<<<< %s", sprint_hex(result, *result_len)); + + if (*result_len < 2) { + return PM3_SUCCESS; + } + + *result_len -= 2; + isw = (result[*result_len] << 8) + result[*result_len + 1]; + if (sw) + *sw = isw; + + if (isw != 0x9000 && + isw != DESFIRE_GET_ISO_STATUS(MFDES_S_OPERATION_OK) && + isw != DESFIRE_GET_ISO_STATUS(MFDES_S_SIGNATURE) && + isw != DESFIRE_GET_ISO_STATUS(MFDES_S_ADDITIONAL_FRAME) && + isw != DESFIRE_GET_ISO_STATUS(MFDES_S_NO_CHANGES)) { + if (GetAPDULogging()) { + if (isw >> 8 == 0x61) { + PrintAndLogEx(ERR, "APDU chaining len: 0x%02x -->", isw & 0xff); + } else { + PrintAndLogEx(ERR, "APDU(%02x%02x) ERROR: [0x%4X] %s", apdu.CLA, apdu.INS, isw, GetAPDUCodeDescription(isw >> 8, isw & 0xff)); + return PM3_EAPDU_FAIL; + } + } + return PM3_EAPDU_FAIL; + } + return PM3_SUCCESS; +} + +static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, bool enable_chaining) { + + return PM3_SUCCESS; +} + +static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, bool enable_chaining) { + if (resplen) + *resplen = 0; + + // TODO !!! + size_t splitbysize = 0; + + uint16_t sw = 0; + uint8_t buf[255 * 5] = {0x00}; + uint32_t buflen = 0; + uint32_t pos = 0; + uint32_t i = 1; + + sAPDU apdu = {0}; + apdu.CLA = MFDES_NATIVE_ISO7816_WRAP_CLA; //0x90 + apdu.INS = cmd; + apdu.Lc = datalen; + apdu.P1 = 0; + apdu.P2 = 0; + apdu.data = data; + + int res = DESFIRESendApdu(activate_field, apdu, buf, sizeof(buf), &buflen, &sw); + if (res != PM3_SUCCESS) { + //PrintAndLogEx(DEBUG, "error DESFIRESendApdu %s", GetErrorString(res, &sw)); + return res; + } + if (resp) + memcpy(resp, buf, buflen); + + pos += buflen; + if (!enable_chaining) { + if (sw == DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) { + if (resplen) + *resplen = pos; + return PM3_SUCCESS; + } + return res; + } + + while (sw == DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) { + apdu.CLA = MFDES_NATIVE_ISO7816_WRAP_CLA; //0x90 + apdu.INS = MFDES_ADDITIONAL_FRAME; //0xAF + apdu.Lc = 0; + apdu.P1 = 0; + apdu.P2 = 0; + apdu.data = NULL; + + res = DESFIRESendApdu(false, apdu, buf, sizeof(buf), &buflen, &sw); + if (res != PM3_SUCCESS) { + //PrintAndLogEx(DEBUG, "error DESFIRESendApdu %s", GetErrorString(res, &sw)); + return res; + } + + if (resp != NULL) { + if (splitbysize) { + memcpy(&resp[i * splitbysize], buf, buflen); + i += 1; + } else { + memcpy(&resp[pos], buf, buflen); + } + } + pos += buflen; + + if (sw != DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) break; + } + + if (resplen) + *resplen = (splitbysize) ? i : pos; + return PM3_SUCCESS; +} + +int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, bool enable_chaining) { + int res = PM3_SUCCESS; + + switch(ctx->cmdChannel) { + case DCCNative: + res = DesfireExchangeNative(activate_field, ctx, cmd, data, datalen, resp, resplen, enable_chaining); + break; + case DCCNativeISO: + res = DesfireExchangeISO(activate_field, ctx, cmd, data, datalen, resp, resplen, enable_chaining); + break; + case DCCISO: + return PM3_EAPDU_FAIL; + break; + } + + return res; +} + +int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen) { + return DesfireExchangeEx(false, ctx, cmd, data, datalen, resp, resplen, true); +} + +int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2) { + if (aid1 == NULL) + return PM3_EINVARG; + + uint8_t data[6] = {0}; + memcpy(data, aid1, 3); + if (aid2 != NULL) + memcpy(&data[3], aid2, 3); + uint8_t resp[257] = {0}; + size_t resplen = 0; + int res = DesfireExchangeEx(true, ctx, MFDES_SELECT_APPLICATION, data, (aid2 == NULL) ? 3 : 6, resp, &resplen, true); + if (res == PM3_SUCCESS && resplen != 0) + return PM3_ECARDEXCHANGE; + return res; +} + +int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2) { + uint8_t data[6] = {0}; + // TODO !!!! + data[0] = aid1 & 0xff; + data[1] = (aid1 >> 8) & 0xff; + data[2] = (aid1 >> 16) & 0xff; + return DesfireSelectAID(ctx, data, (select_two) ? &data[3] : NULL); +} + diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h new file mode 100644 index 000000000..12acb7e8c --- /dev/null +++ b/client/src/mifare/desfirecore.h @@ -0,0 +1,75 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2010 Romain Tartiere. +// Copyright (C) 2014 Iceman +// Copyright (C) 2021 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency Desfire core functions +//----------------------------------------------------------------------------- + +#ifndef __DESFIRECORE_H +#define __DESFIRECORE_H + +#include "common.h" +#include "mifare/desfire_crypto.h" +#include "mifare/mifare4.h" + +#define DESF_MAX_KEY_LEN 24 + +#define DESFIRE_GET_ISO_STATUS(x) ( ((uint16_t)(0x91<<8)) + (uint16_t)x ) + +typedef enum { + DACNone, + DACd40, + DACEV1, + DACEV2 +} DesfireAuthChannel; + +typedef enum { + DCCNative, + DCCNativeISO, + DCCISO +} DesfireCommandChannel; + +typedef enum { + DCMNone, + DCMPlain, + DCMMACed, + DCMEncrypted +} DesfireCommunicationMode; + + +typedef struct DesfireContextS { + uint8_t keyNum; + enum DESFIRE_CRYPTOALGO keyType; // des,2tdea,3tdea,aes + uint8_t key[DESF_MAX_KEY_LEN]; + + // KDF finction + // KDF input + + DesfireAuthChannel authChannel; // none/d40/ev1/ev2 + DesfireCommandChannel cmdChannel; // native/nativeiso/iso + DesfireCommunicationMode commMode; // plain/mac/enc + + uint8_t sessionKeyMAC[DESF_MAX_KEY_LEN]; + uint8_t sessionKeyEnc[DESF_MAX_KEY_LEN]; // look at mifare4.h - mf4Session_t + uint8_t lastIV[DESF_MAX_KEY_LEN]; + //mf4Session_t AESSession; + uint16_t cntrTx; // for AES + uint16_t cntrRx; // for AES + uint8_t TI[4]; // for AES +} DesfireContext; + +void DesfireClearContext(DesfireContext *ctx); +void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key); + +int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2); +int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2); +int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen); +int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, bool enable_chaining); + + +#endif // __DESFIRECORE_H diff --git a/include/protocols.h b/include/protocols.h index 4b3cf763f..66385bcb9 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -459,6 +459,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define MFDES_GET_FILE_SETTINGS 0xF5 #define MFDES_FORMAT_PICC 0xFC #define MFDES_VERIFY_PC 0xFD +#define MFDES_NATIVE_ISO7816_WRAP_CLA 0x90 // MIFARE DESFire status & error codes: #define MFDES_S_OPERATION_OK 0x00 From ecfcc21ded5b4669a86b0bd5d0fe8665024b0783 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 1 Jul 2021 20:06:33 +0300 Subject: [PATCH 139/309] select works (somehow) --- client/src/cmdhfmfdes.c | 21 +++++++++++++++++++++ client/src/mifare/desfirecore.c | 5 +++++ 2 files changed, 26 insertions(+) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 04079eba3..fa22eabaa 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -28,6 +28,7 @@ #include "iso7816/iso7816core.h" // APDU logging #include "util_posix.h" // msleep #include "mifare/desfire_crypto.h" +#include "mifare/desfirecore.h" #include "crapto1/crapto1.h" #include "fileutils.h" #include "mifare/mifaredefault.h" // default keys @@ -5218,11 +5219,31 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { uint8_t cmdKDFAlgo = arg_get_int_def(ctx, 9, 0); CLIGetHexWithReturn(ctx, 10, kdfInput, &kdfInputLen); */ +// SetAPDULogging(APDULogging); + SetAPDULogging(true); CLIParserFree(ctx); + uint8_t key[24] = {0}; + DesfireContext dctx; + DesfireSetKey(&dctx, 1, T_DES, key); + dctx.cmdChannel = DCCNativeISO; + + + //size_t len = 0; + uint16_t sw = 0; + //uint8_t buf[APDU_RES_LEN] = {0}; + + int res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); + if (res != 0 || sw != 0x9000) { + PrintAndLogEx(ERR, "Desfire select " _RED_("error") ". Card returns 0x%02x", sw); + DropField(); + return PM3_ESOFT; + } + + DropField(); return PM3_SUCCESS; } diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index dbd77e1ca..6116db41e 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -231,6 +231,11 @@ int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uin data[0] = aid1 & 0xff; data[1] = (aid1 >> 8) & 0xff; data[2] = (aid1 >> 16) & 0xff; + + data[3] = aid2 & 0xff; + data[4] = (aid2 >> 8) & 0xff; + data[5] = (aid2 >> 16) & 0xff; + return DesfireSelectAID(ctx, data, (select_two) ? &data[3] : NULL); } From 73db86bcc7819408f9322ec68178b8ee6634ba89 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 1 Jul 2021 20:32:04 +0300 Subject: [PATCH 140/309] exchange returns result. select works --- client/src/cmdhfmfdes.c | 6 ++--- client/src/mifare/desfirecore.c | 41 ++++++++++++++++++++++++--------- client/src/mifare/desfirecore.h | 4 ++-- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index fa22eabaa..046187dcb 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5230,12 +5230,12 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { //size_t len = 0; - uint16_t sw = 0; + //uint16_t sw = 0; //uint8_t buf[APDU_RES_LEN] = {0}; int res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); - if (res != 0 || sw != 0x9000) { - PrintAndLogEx(ERR, "Desfire select " _RED_("error") ". Card returns 0x%02x", sw); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); DropField(); return PM3_ESOFT; } diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 6116db41e..3d910a0da 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -111,14 +111,16 @@ static int DESFIRESendApdu(bool activate_field, sAPDU apdu, uint8_t *result, uin return PM3_SUCCESS; } -static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, bool enable_chaining) { +static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining) { return PM3_SUCCESS; } -static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, bool enable_chaining) { +static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining) { if (resplen) *resplen = 0; + if (respcode) + *respcode = 0xff; // TODO !!! size_t splitbysize = 0; @@ -142,6 +144,10 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t //PrintAndLogEx(DEBUG, "error DESFIRESendApdu %s", GetErrorString(res, &sw)); return res; } + + if (respcode != NULL && ((sw & 0xff00) == 0x9100)) + *respcode = sw & 0xff; + if (resp) memcpy(resp, buf, buflen); @@ -169,6 +175,9 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t return res; } + if (respcode != NULL && ((sw & 0xff00) == 0x9100)) + *respcode = sw & 0xff; + if (resp != NULL) { if (splitbysize) { memcpy(&resp[i * splitbysize], buf, buflen); @@ -187,15 +196,15 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t return PM3_SUCCESS; } -int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, bool enable_chaining) { +int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining) { int res = PM3_SUCCESS; switch(ctx->cmdChannel) { case DCCNative: - res = DesfireExchangeNative(activate_field, ctx, cmd, data, datalen, resp, resplen, enable_chaining); + res = DesfireExchangeNative(activate_field, ctx, cmd, data, datalen, respcode, resp, resplen, enable_chaining); break; case DCCNativeISO: - res = DesfireExchangeISO(activate_field, ctx, cmd, data, datalen, resp, resplen, enable_chaining); + res = DesfireExchangeISO(activate_field, ctx, cmd, data, datalen, respcode, resp, resplen, enable_chaining); break; case DCCISO: return PM3_EAPDU_FAIL; @@ -205,8 +214,8 @@ int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uin return res; } -int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen) { - return DesfireExchangeEx(false, ctx, cmd, data, datalen, resp, resplen, true); +int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen) { + return DesfireExchangeEx(false, ctx, cmd, data, datalen, respcode, resp, resplen, true); } int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2) { @@ -219,15 +228,25 @@ int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2) { memcpy(&data[3], aid2, 3); uint8_t resp[257] = {0}; size_t resplen = 0; - int res = DesfireExchangeEx(true, ctx, MFDES_SELECT_APPLICATION, data, (aid2 == NULL) ? 3 : 6, resp, &resplen, true); - if (res == PM3_SUCCESS && resplen != 0) - return PM3_ECARDEXCHANGE; + uint8_t respcode = 0; + + int res = DesfireExchangeEx(true, ctx, MFDES_SELECT_APPLICATION, data, (aid2 == NULL) ? 3 : 6, &respcode, resp, &resplen, true); + if (res == PM3_SUCCESS) { + if (resplen != 0) + return PM3_ECARDEXCHANGE; + + // select operation fail + if (respcode != MFDES_S_OPERATION_OK) + return PM3_EAPDU_FAIL; + + return PM3_SUCCESS; + } return res; } int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2) { uint8_t data[6] = {0}; - // TODO !!!! + data[0] = aid1 & 0xff; data[1] = (aid1 >> 8) & 0xff; data[2] = (aid1 >> 16) & 0xff; diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 12acb7e8c..fa212174c 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -68,8 +68,8 @@ void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2); int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2); -int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen); -int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, bool enable_chaining); +int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen); +int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining); #endif // __DESFIRECORE_H From b5ee999c73db635644c7a4f9e2be37e82ddb5faf Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 1 Jul 2021 20:47:02 +0300 Subject: [PATCH 141/309] rename GetErrorString -> DesfireGetErrorString --- client/src/cmdhfmfdes.c | 167 +++++--------------------------- client/src/mifare/desfirecore.c | 125 +++++++++++++++++++++++- client/src/mifare/desfirecore.h | 2 + 3 files changed, 148 insertions(+), 146 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 046187dcb..f51bbdd57 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -509,125 +509,6 @@ static int DESFIRESendApdu(bool activate_field, bool leavefield_on, sAPDU apdu, return PM3_SUCCESS; } -static const char *getstatus(uint16_t *sw) { - if (sw == NULL) return "--> sw argument error. This should never happen !"; - if (((*sw >> 8) & 0xFF) == 0x91) { - switch (*sw & 0xFF) { - case MFDES_E_OUT_OF_EEPROM: - return "Out of Eeprom, insufficient NV-Memory to complete command"; - case MFDES_E_ILLEGAL_COMMAND_CODE: - return "Command code not supported"; - - case MFDES_E_INTEGRITY_ERROR: - return "CRC or MAC does not match data / Padding bytes invalid"; - - case MFDES_E_NO_SUCH_KEY: - return "Invalid key number specified"; - - case MFDES_E_LENGTH: - return "Length of command string invalid"; - - case MFDES_E_PERMISSION_DENIED: - return "Current configuration/status does not allow the requested command"; - - case MFDES_E_PARAMETER_ERROR: - return "Value of the parameter(s) invalid"; - - case MFDES_E_APPLICATION_NOT_FOUND: - return "Requested AID not present on PICC"; - - case MFDES_E_APPL_INTEGRITY: - return "Application integrity error, application will be disabled"; - - case MFDES_E_AUTHENTIFICATION_ERROR: - return "Current authentication status does not allow the requested command"; - - case MFDES_E_BOUNDARY: - return "Attempted to read/write data from/to beyond the file's/record's limit"; - - case MFDES_E_PICC_INTEGRITY: - return "PICC integrity error, PICC will be disabled"; - - case MFDES_E_COMMAND_ABORTED: - return "Previous command was not fully completed / Not all Frames were requested or provided by the PCD"; - - case MFDES_E_PICC_DISABLED: - return "PICC was disabled by an unrecoverable error"; - - case MFDES_E_COUNT: - return "Application count is limited to 28, not addition CreateApplication possible"; - - case MFDES_E_DUPLICATE: - return "Duplicate entry: File/Application/ISO Text does already exist"; - - case MFDES_E_EEPROM: - return "Eeprom error due to loss of power, internal backup/rollback mechanism activated"; - - case MFDES_E_FILE_NOT_FOUND: - return "Specified file number does not exist"; - - case MFDES_E_FILE_INTEGRITY: - return "File integrity error, file will be disabled"; - - default: - return "Unknown error"; - } - } - return "Unknown error"; -} - -static const char *GetErrorString(int res, uint16_t *sw) { - switch (res) { - case PM3_EAPDU_FAIL: - return getstatus(sw); - case PM3_EUNDEF: - return "Undefined error"; - case PM3_EINVARG: - return "Invalid argument(s)"; - case PM3_EDEVNOTSUPP: - return "Operation not supported by device"; - case PM3_ETIMEOUT: - return "Operation timed out"; - case PM3_EOPABORTED: - return "Operation aborted (by user)"; - case PM3_ENOTIMPL: - return "Not (yet) implemented"; - case PM3_ERFTRANS: - return "Error while RF transmission"; - case PM3_EIO: - return "Input / output error"; - case PM3_EOVFLOW: - return "Buffer overflow"; - case PM3_ESOFT: - return "Software error"; - case PM3_EFLASH: - return "Flash error"; - case PM3_EMALLOC: - return "Memory allocation error"; - case PM3_EFILE: - return "File error"; - case PM3_ENOTTY: - return "Generic TTY error"; - case PM3_EINIT: - return "Initialization error"; - case PM3_EWRONGANSWER: - return "Expected a different answer error"; - case PM3_EOUTOFBOUND: - return "Memory out-of-bounds error"; - case PM3_ECARDEXCHANGE: - return "Exchange with card error"; - case PM3_EAPDU_ENCODEFAIL: - return "Failed to create APDU"; - case PM3_ENODATA: - return "No data"; - case PM3_EFATAL: - return "Fatal error"; - default: - break; - } - return ""; -} - static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, uint32_t *recv_len, uint16_t *sw, uint32_t splitbysize, bool readalldata) { if (apdu == NULL) { PrintAndLogEx(DEBUG, "APDU=NULL"); @@ -649,7 +530,7 @@ static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, uint32_t *r uint32_t i = 1; int res = DESFIRESendApdu(select, true, *apdu, data, sizeof(data), &resplen, sw); if (res != PM3_SUCCESS) { - PrintAndLogEx(DEBUG, "%s", GetErrorString(res, sw)); + PrintAndLogEx(DEBUG, "%s", DesfireGetErrorString(res, sw)); DropFieldDesfire(); return res; } @@ -674,7 +555,7 @@ static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, uint32_t *r res = DESFIRESendApdu(false, true, *apdu, data, sizeof(data), &resplen, sw); if (res != PM3_SUCCESS) { - PrintAndLogEx(DEBUG, "%s", GetErrorString(res, sw)); + PrintAndLogEx(DEBUG, "%s", DesfireGetErrorString(res, sw)); DropFieldDesfire(); return res; } @@ -1341,7 +1222,7 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n int res = send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_("can't change key -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_("can't change key -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } @@ -1771,7 +1652,7 @@ static int handler_desfire_select_application(uint8_t *aid) { PrintAndLogEx(WARNING, _RED_(" Can't select AID 0x%X -> %s"), (aid[2] << 16) + (aid[1] << 8) + aid[0], - GetErrorString(res, &sw) + DesfireGetErrorString(res, &sw) ); DropFieldDesfire(); return res; @@ -1814,7 +1695,7 @@ static int handler_desfire_fileids(uint8_t *dest, uint32_t *file_ids_len) { *file_ids_len = 0; int res = send_desfire_cmd(&apdu, false, dest, &recv_len, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't get file ids -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't get file ids -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } @@ -1833,7 +1714,7 @@ static int handler_desfire_filesettings(uint8_t file_id, uint8_t *dest, uint32_t uint16_t sw = 0; int res = send_desfire_cmd(&apdu, false, dest, destlen, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't get file settings -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't get file settings -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } @@ -1873,7 +1754,7 @@ static int handler_desfire_createapp(aidhdr_t *aidhdr, bool usename, bool usefid free(data); } if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't create aid -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't create aid -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); } return res; @@ -1888,7 +1769,7 @@ static int handler_desfire_deleteapp(const uint8_t *aid) { uint32_t recvlen = 0; int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't delete aid -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't delete aid -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); } return res; @@ -1906,7 +1787,7 @@ static int handler_desfire_credit(mfdes_value_t *value, uint8_t cs) { int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't credit value -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't credit value -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } @@ -1925,7 +1806,7 @@ static int handler_desfire_limitedcredit(mfdes_value_t *value, uint8_t cs) { int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't credit limited value -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't credit limited value -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } @@ -1944,7 +1825,7 @@ static int handler_desfire_debit(mfdes_value_t *value, uint8_t cs) { int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't debit value -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't debit value -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } @@ -1982,7 +1863,7 @@ static int handler_desfire_readdata(mfdes_data_t *data, MFDES_FILE_TYPE_T type, uint32_t resplen = 0; int res = send_desfire_cmd(&apdu, false, data->data, &resplen, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't read data -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't read data -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } @@ -2014,7 +1895,7 @@ static int handler_desfire_getvalue(mfdes_value_t *value, uint32_t *resplen, uin int res = send_desfire_cmd(&apdu, false, value->value, resplen, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't read data -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't read data -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } @@ -2090,7 +1971,7 @@ static int handler_desfire_writedata(mfdes_data_t *data, MFDES_FILE_TYPE_T type, res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't write data -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't write data -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } @@ -2099,7 +1980,7 @@ static int handler_desfire_writedata(mfdes_data_t *data, MFDES_FILE_TYPE_T type, } if (type == MFDES_RECORD_FILE) { if (handler_desfire_commit_transaction() != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't commit transaction -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't commit transaction -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } @@ -2116,7 +1997,7 @@ static int handler_desfire_deletefile(uint8_t file_no) { uint32_t recvlen = 0; int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't delete file -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't delete file -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } @@ -2132,13 +2013,13 @@ static int handler_desfire_clear_record_file(uint8_t file_no) { uint32_t recvlen = 0; int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't clear record file -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't clear record file -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } else { res = handler_desfire_commit_transaction(); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't commit transaction -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't commit transaction -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } @@ -2155,7 +2036,7 @@ static int handler_desfire_create_value_file(mfdes_value_file_t *value) { uint32_t recvlen = 0; int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't create value -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't create value -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } @@ -2172,7 +2053,7 @@ static int handler_desfire_create_std_file(mfdes_file_t *file) { uint32_t recvlen = 0; int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't create file -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't create file -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } @@ -2190,7 +2071,7 @@ static int handler_desfire_create_linearrecordfile(mfdes_linear_t *file) { uint32_t recvlen = 0; int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't create linear record file -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't create linear record file -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } @@ -2210,7 +2091,7 @@ static int handler_desfire_create_cyclicrecordfile(mfdes_linear_t *file) { uint32_t recvlen = 0; int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't create cyclic record file -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't create cyclic record file -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } @@ -2226,7 +2107,7 @@ static int handler_desfire_create_backup_file(mfdes_file_t *file) { uint32_t recvlen = 0; int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't create backup file -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't create backup file -> %s"), DesfireGetErrorString(res, &sw)); DropFieldDesfire(); return res; } @@ -3573,7 +3454,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { uint32_t recvlen = 0; int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't format picc -> %s"), GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't format picc -> %s"), DesfireGetErrorString(res, &sw)); } else { PrintAndLogEx(INFO, "Card successfully reset"); } diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 3d910a0da..b619e2638 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -25,7 +25,126 @@ #include "iso7816/apduinfo.h" // APDU manipulation / errorcodes #include "iso7816/iso7816core.h" // APDU logging #include "util_posix.h" // msleep -#include "mifare/desfire_crypto.h" +#include "mifare/desfire_crypto.h"\ + +static const char *getstatus(uint16_t *sw) { + if (sw == NULL) return "--> sw argument error. This should never happen !"; + if (((*sw >> 8) & 0xFF) == 0x91) { + switch (*sw & 0xFF) { + case MFDES_E_OUT_OF_EEPROM: + return "Out of Eeprom, insufficient NV-Memory to complete command"; + case MFDES_E_ILLEGAL_COMMAND_CODE: + return "Command code not supported"; + + case MFDES_E_INTEGRITY_ERROR: + return "CRC or MAC does not match data / Padding bytes invalid"; + + case MFDES_E_NO_SUCH_KEY: + return "Invalid key number specified"; + + case MFDES_E_LENGTH: + return "Length of command string invalid"; + + case MFDES_E_PERMISSION_DENIED: + return "Current configuration/status does not allow the requested command"; + + case MFDES_E_PARAMETER_ERROR: + return "Value of the parameter(s) invalid"; + + case MFDES_E_APPLICATION_NOT_FOUND: + return "Requested AID not present on PICC"; + + case MFDES_E_APPL_INTEGRITY: + return "Application integrity error, application will be disabled"; + + case MFDES_E_AUTHENTIFICATION_ERROR: + return "Current authentication status does not allow the requested command"; + + case MFDES_E_BOUNDARY: + return "Attempted to read/write data from/to beyond the file's/record's limit"; + + case MFDES_E_PICC_INTEGRITY: + return "PICC integrity error, PICC will be disabled"; + + case MFDES_E_COMMAND_ABORTED: + return "Previous command was not fully completed / Not all Frames were requested or provided by the PCD"; + + case MFDES_E_PICC_DISABLED: + return "PICC was disabled by an unrecoverable error"; + + case MFDES_E_COUNT: + return "Application count is limited to 28, not addition CreateApplication possible"; + + case MFDES_E_DUPLICATE: + return "Duplicate entry: File/Application/ISO Text does already exist"; + + case MFDES_E_EEPROM: + return "Eeprom error due to loss of power, internal backup/rollback mechanism activated"; + + case MFDES_E_FILE_NOT_FOUND: + return "Specified file number does not exist"; + + case MFDES_E_FILE_INTEGRITY: + return "File integrity error, file will be disabled"; + + default: + return "Unknown error"; + } + } + return "Unknown error"; +} + +const char *DesfireGetErrorString(int res, uint16_t *sw) { + switch (res) { + case PM3_EAPDU_FAIL: + return getstatus(sw); + case PM3_EUNDEF: + return "Undefined error"; + case PM3_EINVARG: + return "Invalid argument(s)"; + case PM3_EDEVNOTSUPP: + return "Operation not supported by device"; + case PM3_ETIMEOUT: + return "Operation timed out"; + case PM3_EOPABORTED: + return "Operation aborted (by user)"; + case PM3_ENOTIMPL: + return "Not (yet) implemented"; + case PM3_ERFTRANS: + return "Error while RF transmission"; + case PM3_EIO: + return "Input / output error"; + case PM3_EOVFLOW: + return "Buffer overflow"; + case PM3_ESOFT: + return "Software error"; + case PM3_EFLASH: + return "Flash error"; + case PM3_EMALLOC: + return "Memory allocation error"; + case PM3_EFILE: + return "File error"; + case PM3_ENOTTY: + return "Generic TTY error"; + case PM3_EINIT: + return "Initialization error"; + case PM3_EWRONGANSWER: + return "Expected a different answer error"; + case PM3_EOUTOFBOUND: + return "Memory out-of-bounds error"; + case PM3_ECARDEXCHANGE: + return "Exchange with card error"; + case PM3_EAPDU_ENCODEFAIL: + return "Failed to create APDU"; + case PM3_ENODATA: + return "No data"; + case PM3_EFATAL: + return "Fatal error"; + default: + break; + } + return ""; +} void DesfireClearContext(DesfireContext *ctx) { ctx->keyNum = 0; @@ -141,7 +260,7 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t int res = DESFIRESendApdu(activate_field, apdu, buf, sizeof(buf), &buflen, &sw); if (res != PM3_SUCCESS) { - //PrintAndLogEx(DEBUG, "error DESFIRESendApdu %s", GetErrorString(res, &sw)); + PrintAndLogEx(DEBUG, "error DESFIRESendApdu %s", DesfireGetErrorString(res, &sw)); return res; } @@ -171,7 +290,7 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t res = DESFIRESendApdu(false, apdu, buf, sizeof(buf), &buflen, &sw); if (res != PM3_SUCCESS) { - //PrintAndLogEx(DEBUG, "error DESFIRESendApdu %s", GetErrorString(res, &sw)); + PrintAndLogEx(DEBUG, "error DESFIRESendApdu %s", DesfireGetErrorString(res, &sw)); return res; } diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index fa212174c..2d102fb45 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -66,6 +66,8 @@ typedef struct DesfireContextS { void DesfireClearContext(DesfireContext *ctx); void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key); +const char *DesfireGetErrorString(int res, uint16_t *sw); + int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2); int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2); int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen); From 732644fb9b169b90e532e9b6f3f3e2d6983647c2 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 1 Jul 2021 21:59:59 +0200 Subject: [PATCH 142/309] hf_mfu_magicwrite -c: add version info --- client/luascripts/hf_mfu_magicwrite.lua | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/client/luascripts/hf_mfu_magicwrite.lua b/client/luascripts/hf_mfu_magicwrite.lua index 803f3f224..2919562db 100644 --- a/client/luascripts/hf_mfu_magicwrite.lua +++ b/client/luascripts/hf_mfu_magicwrite.lua @@ -191,11 +191,27 @@ local function read_config() elseif cardtype == '02' then typestr = 'NTAG 216' end + local versionstr = 'unknown' + if version == '0004030101000B03' then versionstr = 'UL EV1 48b' + elseif version == '0004030101000E03' then versionstr = 'UL EV1 128b' + elseif version == '0004040101000B03' then versionstr = 'NTAG 210' + elseif version == '0004040101000E03' then versionstr = 'NTAG 212' + elseif version == '0004040201000F03' then versionstr = 'NTAG 213' + elseif version == '0004040201001103' then versionstr = 'NTAG 215' + elseif version == '0004040201001303' then versionstr = 'NTAG 216' + elseif version == '0004040502011303' then versionstr = 'NTAG I2C 1K' + elseif version == '0004040502011503' then versionstr = 'NTAG I2C 2K' + elseif version == '0004040502021303' then versionstr = 'NTAG I2C 1K PLUS' + elseif version == '0004040502021503' then versionstr = 'NTAG I2C 2K PLUS' + elseif version == '0004040401000F03' then versionstr = 'NTAG 213F' + elseif version == '0004040401001303' then versionstr = 'NTAG 216F' + end + print('Magic NTAG 21* Configuration') print(' - Type ', typestr, '(genuine cardtype)') print(' - Password', pwd) print(' - Pack ', pack) - print(' - Version ', version) + print(' - Version ', version, '(' .. versionstr .. ')') print(' - Signature', signature1..signature2) lib14a.disconnect() From e5d24ff81f8df7fa9d8fdbb460b210922c78541b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 2 Jul 2021 17:37:15 +0300 Subject: [PATCH 143/309] authentication works --- client/src/cmdhfmfdes.c | 16 +- client/src/mifare/desfirecore.c | 301 +++++++++++++++++++++++++++++++- client/src/mifare/desfirecore.h | 15 +- 3 files changed, 319 insertions(+), 13 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index f51bbdd57..67674a5df 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5106,8 +5106,8 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { uint8_t key[24] = {0}; DesfireContext dctx; - DesfireSetKey(&dctx, 1, T_DES, key); - dctx.cmdChannel = DCCNativeISO; + DesfireSetKey(&dctx, 0, T_DES, key); // T_DES T_3DES T_3K3DES T_AES + DesfireSetCommandChannel(&dctx, DCCNativeISO); //size_t len = 0; @@ -5120,6 +5120,18 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { DropField(); return PM3_ESOFT; } + + res = DesfireAuthenticate(&dctx, DACd40); //DACd40 DACEV1 + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + if (DesfireIsAuthenticated(&dctx)) + PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated") , res); + else + return PM3_ESOFT; diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index b619e2638..b43e6e7bb 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -19,13 +19,15 @@ #include #include #include +#include "aes.h" #include "ui.h" #include "protocols.h" +#include "commonutil.h" #include "cmdhf14a.h" -#include "iso7816/apduinfo.h" // APDU manipulation / errorcodes -#include "iso7816/iso7816core.h" // APDU logging -#include "util_posix.h" // msleep -#include "mifare/desfire_crypto.h"\ +#include "iso7816/apduinfo.h" // APDU manipulation / errorcodes +#include "iso7816/iso7816core.h" // APDU logging +#include "util_posix.h" // msleep +#include "mifare/desfire_crypto.h" static const char *getstatus(uint16_t *sw) { if (sw == NULL) return "--> sw argument error. This should never happen !"; @@ -155,6 +157,16 @@ void DesfireClearContext(DesfireContext *ctx) { ctx->cmdChannel = DCCNative; ctx->commMode = DCMNone; + ctx->kdfAlgo = 0; + ctx->kdfInputLen = 0; + memset(ctx->kdfInput, 0, sizeof(ctx->kdfInput)); + + DesfireClearSession(ctx); +} + +void DesfireClearSession(DesfireContext *ctx) { + ctx->authChannel = DACNone; // here none - not authenticared + memset(ctx->sessionKeyMAC, 0, sizeof(ctx->sessionKeyMAC)); memset(ctx->sessionKeyEnc, 0, sizeof(ctx->sessionKeyEnc)); memset(ctx->lastIV, 0, sizeof(ctx->lastIV)); @@ -171,6 +183,10 @@ void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO memcpy(ctx->key, key, desfire_get_key_length(keyType)); } +void DesfireSetCommandChannel(DesfireContext *ctx, DesfireCommandChannel cmdChannel) { + ctx->cmdChannel = cmdChannel; +} + static int DESFIRESendApdu(bool activate_field, sAPDU apdu, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint16_t *sw) { if (result_len) *result_len = 0; if (sw) *sw = 0; @@ -272,12 +288,12 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t pos += buflen; if (!enable_chaining) { - if (sw == DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) { + if (sw == DESFIRE_GET_ISO_STATUS(MFDES_S_OPERATION_OK) || + sw == DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) { if (resplen) *resplen = pos; - return PM3_SUCCESS; } - return res; + return PM3_SUCCESS; } while (sw == DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) { @@ -312,6 +328,7 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t if (resplen) *resplen = (splitbysize) ? i : pos; + return PM3_SUCCESS; } @@ -377,3 +394,273 @@ int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uin return DesfireSelectAID(ctx, data, (select_two) ? &data[3] : NULL); } +bool DesfireIsAuthenticated(DesfireContext *dctx) { + return dctx->authChannel != DACNone; +} + +int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel) { + // 3 different way to authenticate AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32) + // 4 different crypto arg1 DES, 3DES, 3K3DES, AES + // 3 different communication modes, PLAIN,MAC,CRYPTO + + DesfireClearSession(dctx); + + if (authChannel == DACNone) + return PM3_SUCCESS; + + mbedtls_aes_context ctx; + + uint8_t keybytes[24] = {0}; + // Crypt constants + uint8_t IV[16] = {0}; + uint8_t RndA[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}; + uint8_t RndB[16] = {0}; + uint8_t encRndB[16] = {0}; + uint8_t rotRndB[16] = {0}; //RndB' + uint8_t both[32 + 1] = {0}; // ek/dk_keyNo(RndA+RndB') + + // Part 1 + memcpy(keybytes, dctx->key, desfire_get_key_length(dctx->keyType)); + + struct desfire_key dkey = {0}; + desfirekey_t key = &dkey; + + if (dctx->keyType == T_AES) { + mbedtls_aes_init(&ctx); + Desfire_aes_key_new(keybytes, key); + } else if (dctx->keyType == T_3DES) { + Desfire_3des_key_new_with_version(keybytes, key); + } else if (dctx->keyType == T_DES) { + Desfire_des_key_new(keybytes, key); + } else if (dctx->keyType == T_3K3DES) { + Desfire_3k3des_key_new_with_version(keybytes, key); + } + + if (dctx->kdfAlgo == MFDES_KDF_ALGO_AN10922) { + mifare_kdf_an10922(key, dctx->kdfInput, dctx->kdfInputLen); + PrintAndLogEx(DEBUG, " Derrived key: " _GREEN_("%s"), sprint_hex(key->data, key_block_size(key))); + } else if (dctx->kdfAlgo == MFDES_KDF_ALGO_GALLAGHER) { + // We will overrite any provided KDF input since a gallagher specific KDF was requested. + dctx->kdfInputLen = 11; + + /*if (mfdes_kdf_input_gallagher(tag->info.uid, tag->info.uidlen, dctx->keyNum, tag->selected_application, dctx->kdfInput, &dctx->kdfInputLen) != PM3_SUCCESS) { + PrintAndLogEx(FAILED, "Could not generate Gallagher KDF input"); + }*/ + + mifare_kdf_an10922(key, dctx->kdfInput, dctx->kdfInputLen); + PrintAndLogEx(DEBUG, " KDF Input: " _YELLOW_("%s"), sprint_hex(dctx->kdfInput, dctx->kdfInputLen)); + PrintAndLogEx(DEBUG, " Derrived key: " _GREEN_("%s"), sprint_hex(key->data, key_block_size(key))); + + } + + uint8_t subcommand = MFDES_AUTHENTICATE; + dctx->authChannel = authChannel; + if (dctx->authChannel == DACEV1) { + if (dctx->keyType == T_AES) + subcommand = MFDES_AUTHENTICATE_AES; + else + subcommand = MFDES_AUTHENTICATE_ISO; + } + + uint32_t recv_len = 0; + uint8_t respcode = 0; + uint8_t recv_data[256] = {0}; + + // Let's send our auth command + int res = DesfireExchangeEx(false, dctx, subcommand, &dctx->keyNum, 1, &respcode, recv_data, &recv_len, false); + if (res != PM3_SUCCESS) { + return 1; + } + + if (!recv_len) { + return 2; + } + + if (respcode != MFDES_ADDITIONAL_FRAME) { + return 3; + } + + uint32_t expectedlen = 8; + if (dctx->keyType == T_AES || dctx->keyType == T_3K3DES) { + expectedlen = 16; + } + + if (recv_len != expectedlen) { + return 4; + } + + // Part 2 + uint32_t rndlen = recv_len; + memcpy(encRndB, recv_data, rndlen); + + + // Part 3 + if (dctx->keyType == T_AES) { + if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) { + return 5; + } + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, rndlen, IV, encRndB, RndB); + } else if (dctx->keyType == T_DES) + des_decrypt(RndB, encRndB, key->data); + else if (dctx->keyType == T_3DES) + tdes_nxp_receive(encRndB, RndB, rndlen, key->data, IV, 2); + else if (dctx->keyType == T_3K3DES) { + tdes_nxp_receive(encRndB, RndB, rndlen, key->data, IV, 3); + } + + if (g_debugMode > 1) { + PrintAndLogEx(DEBUG, "encRndB: %s", sprint_hex(encRndB, 8)); + PrintAndLogEx(DEBUG, "RndB: %s", sprint_hex(RndB, 8)); + } + + // - Rotate RndB by 8 bits + memcpy(rotRndB, RndB, rndlen); + rol(rotRndB, rndlen); + + uint8_t encRndA[16] = {0x00}; + + // - Encrypt our response + if (dctx->authChannel == DACd40) { + des_decrypt(encRndA, RndA, key->data); + memcpy(both, encRndA, rndlen); + + for (uint32_t x = 0; x < rndlen; x++) { + rotRndB[x] = rotRndB[x] ^ encRndA[x]; + } + + des_decrypt(encRndB, rotRndB, key->data); + memcpy(both + rndlen, encRndB, rndlen); + } else if (dctx->authChannel == DACEV1 && dctx->keyType != T_AES) { + if (dctx->keyType == T_3DES) { + uint8_t tmp[16] = {0x00}; + memcpy(tmp, RndA, rndlen); + memcpy(tmp + rndlen, rotRndB, rndlen); + if (g_debugMode > 1) { + PrintAndLogEx(DEBUG, "rotRndB: %s", sprint_hex(rotRndB, rndlen)); + PrintAndLogEx(DEBUG, "Both: %s", sprint_hex(tmp, 16)); + } + tdes_nxp_send(tmp, both, 16, key->data, IV, 2); + if (g_debugMode > 1) { + PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, 16)); + } + } else if (dctx->keyType == T_3K3DES) { + uint8_t tmp[32] = {0x00}; + memcpy(tmp, RndA, rndlen); + memcpy(tmp + rndlen, rotRndB, rndlen); + if (g_debugMode > 1) { + PrintAndLogEx(DEBUG, "rotRndB: %s", sprint_hex(rotRndB, rndlen)); + PrintAndLogEx(DEBUG, "Both3k3: %s", sprint_hex(tmp, 32)); + } + tdes_nxp_send(tmp, both, 32, key->data, IV, 3); + if (g_debugMode > 1) { + PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, 32)); + } + } + } else if (dctx->authChannel == DACEV1 && dctx->keyType == T_AES) { + uint8_t tmp[32] = {0x00}; + memcpy(tmp, RndA, rndlen); + memcpy(tmp + rndlen, rotRndB, rndlen); + if (g_debugMode > 1) { + PrintAndLogEx(DEBUG, "rotRndB: %s", sprint_hex(rotRndB, rndlen)); + PrintAndLogEx(DEBUG, "Both3k3: %s", sprint_hex(tmp, 32)); + } + if (dctx->keyType == T_AES) { + if (mbedtls_aes_setkey_enc(&ctx, key->data, 128) != 0) { + return 6; + } + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, 32, IV, tmp, both); + if (g_debugMode > 1) { + PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, 32)); + } + } + } + + uint32_t bothlen = 16; + if (dctx->keyType == T_AES || dctx->keyType == T_3K3DES) { + bothlen = 32; + } + + res = DesfireExchangeEx(false, dctx, MFDES_ADDITIONAL_FRAME, both, bothlen, &respcode, recv_data, &recv_len, false); + if (res != PM3_SUCCESS) { + return 7; + } + + if (!recv_len) { + return 8; + } + + if (respcode != MFDES_S_OPERATION_OK) { + return 9; + } + + // Part 4 + memcpy(encRndA, recv_data, rndlen); + + // tag->session_key = &default_key; + /*struct desfire_key *p = realloc(tag->session_key, sizeof(struct desfire_key)); + if (!p) { + PrintAndLogEx(FAILED, "Cannot allocate memory for session keys"); + free(tag->session_key); + return PM3_EMALLOC; + } + tag->session_key = p; + + memset(tag->session_key, 0x00, sizeof(struct desfire_key)); + */ + struct desfire_key sesskey = {0}; + + Desfire_session_key_new(RndA, RndB, key, &sesskey); + memcpy(dctx->sessionKeyEnc, sesskey.data, desfire_get_key_length(dctx->keyType)); + +PrintAndLogEx(INFO, "encRndA : %s", sprint_hex(encRndA, rndlen)); + if (dctx->keyType == T_DES) + des_decrypt(encRndA, encRndA, key->data); + else if (dctx->keyType == T_3DES) + tdes_nxp_receive(encRndA, encRndA, rndlen, key->data, IV, 2); + else if (dctx->keyType == T_3K3DES) + tdes_nxp_receive(encRndA, encRndA, rndlen, key->data, IV, 3); + else if (dctx->keyType == T_AES) { + if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) { + return 10; + } + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, rndlen, IV, encRndA, encRndA); + } + + rol(RndA, rndlen); +PrintAndLogEx(INFO, "Expected_RndA : %s", sprint_hex(RndA, rndlen)); +PrintAndLogEx(INFO, "Generated_RndA : %s", sprint_hex(encRndA, rndlen)); + for (uint32_t x = 0; x < rndlen; x++) { + if (RndA[x] != encRndA[x]) { + if (g_debugMode > 1) { + PrintAndLogEx(DEBUG, "Expected_RndA : %s", sprint_hex(RndA, rndlen)); + PrintAndLogEx(DEBUG, "Generated_RndA : %s", sprint_hex(encRndA, rndlen)); + } + return 11; + } + } + + // If the 3Des key first 8 bytes = 2nd 8 Bytes then we are really using Singe Des + // As such we need to set the session key such that the 2nd 8 bytes = 1st 8 Bytes + if (dctx->keyType == T_3DES) { + if (memcmp(key->data, &key->data[8], 8) == 0) + memcpy(&dctx->sessionKeyEnc[8], dctx->sessionKeyEnc, 8); + } + +// rpayload->sessionkeylen = payload->keylen; + // memcpy(rpayload->sessionkey, tag->session_key->data, rpayload->sessionkeylen); + // memset(tag->ivect, 0, MAX_CRYPTO_BLOCK_SIZE); + // tag->authenticated_key_no = payload->keyno; + + if (dctx->authChannel == DACEV1) { + cmac_generate_subkeys(&sesskey, MCD_RECEIVE); + //key->cmac_sk1 and key->cmac_sk2 + //memcpy(dctx->sessionKeyEnc, sesskey.data, desfire_get_key_length(dctx->keyType)); + } + + memcpy(dctx->sessionKeyMAC, dctx->sessionKeyEnc, desfire_get_key_length(dctx->keyType)); +PrintAndLogEx(INFO, "sessionKeyEnc : %s", sprint_hex(dctx->sessionKeyEnc, desfire_get_key_length(dctx->keyType))); + + return PM3_SUCCESS; +} + + diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 2d102fb45..529315405 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -44,11 +44,13 @@ typedef enum { typedef struct DesfireContextS { uint8_t keyNum; - enum DESFIRE_CRYPTOALGO keyType; // des,2tdea,3tdea,aes + enum DESFIRE_CRYPTOALGO keyType; // des/2tdea/3tdea/aes uint8_t key[DESF_MAX_KEY_LEN]; // KDF finction - // KDF input + uint8_t kdfAlgo; + uint8_t kdfInputLen; + uint8_t kdfInput[31]; DesfireAuthChannel authChannel; // none/d40/ev1/ev2 DesfireCommandChannel cmdChannel; // native/nativeiso/iso @@ -64,14 +66,19 @@ typedef struct DesfireContextS { } DesfireContext; void DesfireClearContext(DesfireContext *ctx); +void DesfireClearSession(DesfireContext *ctx); void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key); +void DesfireSetCommandChannel(DesfireContext *ctx, DesfireCommandChannel cmdChannel); const char *DesfireGetErrorString(int res, uint16_t *sw); -int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2); -int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2); int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen); int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining); +int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2); +int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2); +int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel); +bool DesfireIsAuthenticated(DesfireContext *dctx); + #endif // __DESFIRECORE_H From 636a1dd457a59311a541751fb7649fab847fce1a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 2 Jul 2021 18:06:13 +0300 Subject: [PATCH 144/309] DesfireGetAIDList works --- client/src/cmdhfmfdes.c | 14 ++++++++++---- client/src/mifare/desfirecore.c | 29 +++++++++++++++++++++-------- client/src/mifare/desfirecore.h | 6 ++++++ 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 67674a5df..ce3d45f4f 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5110,10 +5110,6 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { DesfireSetCommandChannel(&dctx, DCCNativeISO); - //size_t len = 0; - //uint16_t sw = 0; - //uint8_t buf[APDU_RES_LEN] = {0}; - int res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); @@ -5133,8 +5129,18 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { else return PM3_ESOFT; + uint8_t buf[APDU_RES_LEN] = {0}; + size_t buflen = 0; + res = DesfireGetAIDList(&dctx, buf, &buflen); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire GetAIDList command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + for (int i = 0; i < buflen; i += 3) + PrintAndLogEx(INFO, "AID: %06x", DesfireAIDByteToUint(&buf[i])); DropField(); return PM3_SUCCESS; diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index b43e6e7bb..24e6bfa2a 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -148,6 +148,16 @@ const char *DesfireGetErrorString(int res, uint16_t *sw) { return ""; } +uint32_t DesfireAIDByteToUint(uint8_t *data) { + return data[0] + (data[1] << 8) + (data[2] << 16); +} + +void DesfireAIDUintToByte(uint32_t aid, uint8_t *data) { + data[0] = aid & 0xff; + data[1] = (aid >> 8) & 0xff; + data[2] = (aid >> 16) & 0xff; +} + void DesfireClearContext(DesfireContext *ctx) { ctx->keyNum = 0; ctx->keyType = T_DES; @@ -383,13 +393,8 @@ int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2) { int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2) { uint8_t data[6] = {0}; - data[0] = aid1 & 0xff; - data[1] = (aid1 >> 8) & 0xff; - data[2] = (aid1 >> 16) & 0xff; - - data[3] = aid2 & 0xff; - data[4] = (aid2 >> 8) & 0xff; - data[5] = (aid2 >> 16) & 0xff; + DesfireAIDUintToByte(aid1, data); + DesfireAIDUintToByte(aid2, &data[3]); return DesfireSelectAID(ctx, data, (select_two) ? &data[3] : NULL); } @@ -663,4 +668,12 @@ PrintAndLogEx(INFO, "sessionKeyEnc : %s", sprint_hex(dctx->sessionKeyEnc, desfir return PM3_SUCCESS; } - +int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { + uint8_t respcode = 0xff; + int res = DesfireExchange(dctx, MFDES_GET_APPLICATION_IDS, NULL, 0, &respcode, resp, resplen); + if (res != PM3_SUCCESS) + return res; + if (respcode != MFDES_S_OPERATION_OK) + return PM3_EAPDU_FAIL; + return PM3_SUCCESS; +} diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 529315405..cae333015 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -71,14 +71,20 @@ void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO void DesfireSetCommandChannel(DesfireContext *ctx, DesfireCommandChannel cmdChannel); const char *DesfireGetErrorString(int res, uint16_t *sw); +uint32_t DesfireAIDByteToUint(uint8_t *data); +void DesfireAIDUintToByte(uint32_t aid, uint8_t *data); int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen); int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining); int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2); int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2); + int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel); bool DesfireIsAuthenticated(DesfireContext *dctx); +int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); +int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); + #endif // __DESFIRECORE_H From d354ac90fd9cb6f3219230ea7ced870b647824f7 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 2 Jul 2021 18:07:46 +0300 Subject: [PATCH 145/309] fix warning --- client/src/mifare/desfirecore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 24e6bfa2a..db4d728fc 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -467,7 +467,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel) { subcommand = MFDES_AUTHENTICATE_ISO; } - uint32_t recv_len = 0; + size_t recv_len = 0; uint8_t respcode = 0; uint8_t recv_data[256] = {0}; From 0aad993711c8788cb0d6c7249a95567ac3b8acb0 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 2 Jul 2021 18:17:21 +0300 Subject: [PATCH 146/309] remove comments and text fixes --- client/src/cmdhfmfdes.c | 23 +++++++++++++++-------- client/src/mifare/desfirecore.c | 16 ---------------- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index ce3d45f4f..89c08ef37 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5017,6 +5017,9 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, false); + bool APDULogging = arg_get_lit(ctx, 1); + bool verbose = arg_get_lit(ctx, 2); + uint8_t keyNum = arg_get_int_def(ctx, 3, 0); // defaultKeyId /* int aidlength = 0; @@ -5100,13 +5103,12 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { uint8_t cmdKDFAlgo = arg_get_int_def(ctx, 9, 0); CLIGetHexWithReturn(ctx, 10, kdfInput, &kdfInputLen); */ -// SetAPDULogging(APDULogging); - SetAPDULogging(true); + SetAPDULogging(APDULogging); CLIParserFree(ctx); uint8_t key[24] = {0}; DesfireContext dctx; - DesfireSetKey(&dctx, 0, T_DES, key); // T_DES T_3DES T_3K3DES T_AES + DesfireSetKey(&dctx, keyNum, T_DES, key); // T_DES T_3DES T_3K3DES T_AES DesfireSetCommandChannel(&dctx, DCCNativeISO); @@ -5124,10 +5126,12 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { return PM3_ESOFT; } - if (DesfireIsAuthenticated(&dctx)) - PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated") , res); - else + if (DesfireIsAuthenticated(&dctx)) { + if (verbose) + PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated") , res); + } else { return PM3_ESOFT; + } uint8_t buf[APDU_RES_LEN] = {0}; size_t buflen = 0; @@ -5139,8 +5143,11 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { return PM3_ESOFT; } - for (int i = 0; i < buflen; i += 3) - PrintAndLogEx(INFO, "AID: %06x", DesfireAIDByteToUint(&buf[i])); + if (buflen >= 3) { + PrintAndLogEx(INFO, "---- " _CYAN_("AID list") " ----"); + for (int i = 0; i < buflen; i += 3) + PrintAndLogEx(INFO, "AID: %06x", DesfireAIDByteToUint(&buf[i])); + } DropField(); return PM3_SUCCESS; diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index db4d728fc..de71db69f 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -601,17 +601,6 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel) { // Part 4 memcpy(encRndA, recv_data, rndlen); - // tag->session_key = &default_key; - /*struct desfire_key *p = realloc(tag->session_key, sizeof(struct desfire_key)); - if (!p) { - PrintAndLogEx(FAILED, "Cannot allocate memory for session keys"); - free(tag->session_key); - return PM3_EMALLOC; - } - tag->session_key = p; - - memset(tag->session_key, 0x00, sizeof(struct desfire_key)); - */ struct desfire_key sesskey = {0}; Desfire_session_key_new(RndA, RndB, key, &sesskey); @@ -651,11 +640,6 @@ PrintAndLogEx(INFO, "Generated_RndA : %s", sprint_hex(encRndA, rndlen)); memcpy(&dctx->sessionKeyEnc[8], dctx->sessionKeyEnc, 8); } -// rpayload->sessionkeylen = payload->keylen; - // memcpy(rpayload->sessionkey, tag->session_key->data, rpayload->sessionkeylen); - // memset(tag->ivect, 0, MAX_CRYPTO_BLOCK_SIZE); - // tag->authenticated_key_no = payload->keyno; - if (dctx->authChannel == DACEV1) { cmac_generate_subkeys(&sesskey, MCD_RECEIVE); //key->cmac_sk1 and key->cmac_sk2 From a29282c06c9ccc65d4b6e3c143ee2cb61e8a8792 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 2 Jul 2021 20:09:27 +0200 Subject: [PATCH 147/309] python script to verify basic status and init of RDV4 device --- tools/pm3_online_check.py | 449 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 449 insertions(+) create mode 100755 tools/pm3_online_check.py diff --git a/tools/pm3_online_check.py b/tools/pm3_online_check.py new file mode 100755 index 000000000..73959d32d --- /dev/null +++ b/tools/pm3_online_check.py @@ -0,0 +1,449 @@ +#!/usr/bin/env python3 + +''' + +# pm3_online_check.py +# Christian Herrmann, Iceman, 2020 +# version = 'v1.0.5' +# +# This code is copyright (c) Christian Herrmann, 2020, All rights reserved. +# For non-commercial use only, the following terms apply - for all other +# uses, please contact the author: +# +# This code is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This code is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# +# Dependecies: +# +# pip3 install pexpect ansicolors +# +''' +import pexpect +from colors import color +import requests +import string +import re +import time +import argparse + +def pm3_flashbootrom(): + flbootrom = pexpect.spawnu('./pm3-flash-bootrom') + flbootrom.expect(pexpect.EOF) + msg = escape_ansi(str(flbootrom.before)) + if 'Have a nice day!'.lower() in msg: + print("Flashing bootrom ", color('[OK]', fg='green')) + else: + print("Flashing bootrom ", color('[FAIL]', fg='red')) + + time.sleep(20) + +def pm3_flashfullimage(): + flimage = pexpect.spawnu('./pm3-flash-fullimage') + flimage.expect(pexpect.EOF) + msg = escape_ansi(str(flimage.before)) + if 'Have a nice day!'.lower() in msg: + print("Flashing fullimage ", color('[OK]', fg='green')) + else: + print("Flashing fullimage ", color('[FAIL]', fg='red')) + + time.sleep(20) + +def escape_ansi(line): + ansi_escape = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]') + return ansi_escape.sub('', str(line)).lower() + +def pm3_initrdv4(child): + child.sendline('script run init_rdv4') + i = child.expect('pm3 --> ') + + msg = escape_ansi(str(child.before)) + if 'finished init_rdv4'.lower() in msg: + print("Init RDV4 ", color('[OK]', fg='green')) + else: + print("Init RDV4 ", color('[FAIL]', fg='red')) + +# LF T55x7 wipe/clone/read/wipe test +def pm3_lf_t55xx(child): + + try: + print("[=] starting lf t55xx tests...") + + # wipe t55xx + child.sendline('lf t55xx wipe') + i = child.expect('pm3 --> ') + + msg = escape_ansi(str(child.before)) + if 'Writing page 0 block: 07 data: 0x00000000'.lower() in msg: + print("[+] LF T55XX WIPE ", color('[OK]', fg='green')) + else: + print("[-] LF T55XX WIPE ", color('[FAIL]', fg='red')) + + # clone HID + child.sendline('lf hid clone -r 2006ec0c86') + i = child.expect('pm3 --> ') + + msg = escape_ansi(str(child.before)) + if 'Done'.lower() in msg: + print("[+] LF HID CLONE ", color('[OK]', fg='green')) + else: + print("[-] LF HID CLONE ", color('[FAIL]', fg='red')) + + # read HID + child.sendline('lf hid read') + i = child.expect('pm3 --> ') + + msg = escape_ansi(str(child.before)) + if "HID H10301 26-bit; FC: 118 CN: 1603 parity: valid".lower() in msg: + print("[+] LF HID READ ", color('[OK]', fg='green')) + else: + print("[-] LF HID READ ", color('[FAIL]', fg='red')) + + # wipe t55xx + child.sendline('lf t55xx wipe') + i = child.expect('pm3 --> ') + return True + + except: + print(color("[!] exception for LF T55XX", fg='red')) + msg = escape_ansi(str(child.before)) + print(msg) + child.sendline('quit') + child.expect(pexpect.EOF) + return False + +def pm3_flash_sm(child): + try: + print("[+] Updating smart card fw") + child.sendline('smart upgrade -f sim011.bin') + i = child.expect('pm3 --> ') + msg = escape_ansi(str(child.before)) + print("================") + print(" smart card upgrade") + print("==== msg ========") + print(msg) + if "successful" in msg: + print("[+] Smart card firmware upgrade ", color('[OK]', fg='green')) + return True + else: + print("[-] Smart card firmware upgrade ", color('[FAIL]', fg='red')) + return False + except: + print(color("[!] exception for SMART UPGRADE", fg='red')) + msg = escape_ansi(str(child.before)) + print(msg) + child.sendline('quit') + child.expect(pexpect.EOF) + return False + +def main(): + + parser = argparse.ArgumentParser() + parser.add_argument("--flash", help="flash bootrom & fullimage", action="store_true") + parser.add_argument("--init", help="run init rdv4 script", action="store_true") + parser.add_argument("-y", help="automatic yes to prompts", action="store_true") + args = parser.parse_args() + + print("-----------", color('Proxmark3 online test script v1.0.3', fg='cyan'), "------------") + print("This script will run some series of test against a connected Proxmark3 device") + print("Steps:"); + print(" 1. flash bootrom, fullimage"); + print(" 2. init_rdv4 / flash smartcard"); + print(" 3. check device mismatch message"); + print(" 4. check smart card fw, flash memory"); + print(" if needed, flash flash smartcard reader firmware"); + print(" 5. check antenna tuning"); + print(" 6. check LF T55x7 functionality"); + print(" 7. check HF search"); + print(" 8. check SPIFFS"); + print(" 9. check HF iCLASS functionality"); + print("\n"); + + # result + res = 0 + total_tests = 12 + must_update_fw = 0 + msg = '' + + if args.flash: + print("-----------------------", color('Flashing phase', fg='cyan'), "---------------------") + print("flashing bootrom - don't touch the device or cables") + pm3_flashbootrom() + + print("flashing fullimage - don't touch the device or cables") + pm3_flashfullimage() + print("\n") + + # start pm3 + child = pexpect.spawnu('./pm3') + i = child.expect('pm3 --> ') + print("[+] Proxmark3 client open") + + if args.init: + print("------------------------", color('Init phase', fg='cyan'), "------------------------") + print("Running init rdv4 script - don't touch the device or cables") + pm3_initrdv4(child) + print("flashing smartcard - don't touch the device or cables") + pm3_flash_sm(child) + print("\n") + + print("------------------------", color('Test phase', fg='cyan'), "------------------------") + + + # check device mismatch + signature_msg = "device.................... RDV4".lower() + + # check flashmemory + flash_mem = "baudrate................24 mhz".lower() + + # check smartcard fw version + sm_version = "version.................v3.11".lower() + + # check LF + lf_search = "valid hid prox id found!".lower() + + # check HF + hf_search = "Valid iCLASS tag / PicoPass tag found".lower() + + # mem spiffs info + mem_spiffs = "max path length............32 chars".lower() + + # lf antenna tuning + lf_tune = "LF antenna is OK".lower() + + # hf antenna tuning + hf_tune = "HF antenna is OK".lower() + + try: + # HW VERSION checks + child.sendline('hw version') + i = child.expect('pm3 --> ') + msg = escape_ansi(str(child.before)) + + if signature_msg in msg: + print("[+] RDV4 signature ", color('[OK]', fg='green')) + res += 1 + else: + print("[-] RDV4 signature ", color('[FAIL]', fg='red')) + + + # HW STATUS checks + child.sendline('hw status') + i = child.expect('pm3 --> ') + msg = escape_ansi(str(child.before)) + + if sm_version in msg: + print("[+] Smart card firmware version ", color('[OK]', fg='green')) + res += 1 + else: + print("[-] Smart card firmware version ", color('[FAIL]', fg='red'), " will upgrade fw in the next step") + must_update_fw = 1 + + if flash_mem in msg: + print("[+] Flash memory accessable ", color('[OK]', fg='green')) + res += 1 + else: + print("[-] Flash memory accessable ", color('[FAIL]', fg='red')) + + # extract slow clock and verify its OK... + # slow clock check: + # Slow clock..............30057 Hz + for line in msg.splitlines(): + match_slow = line.find('slow clock..............') + + if match_slow > -1: + match = re.search(r'\d+', line) + if match: + clock = int(match[0]) + if clock < 29000: + print("[-] Warning, Slow clock too slow (%d Hz)" % (clock), color('[FAIL]', fg='red')) + elif clock > 33000: + print("[-] Warning, Slow clock too fast (%d Hz)" % (clock), color('[FAIL]', fg='red')) + else: + print("[+] Slow clock within acceptable range (%d Hz)" % (clock), color('[OK]', fg='green')) + res += 1 + except: + print(color("[!] exception for HW STATUS", fg='red')) + msg = escape_ansi(str(child.before)) + print(msg) + child.sendline('quit') + child.expect(pexpect.EOF) + return + + if must_update_fw == 1: + if pm3_flash_sm(child): + res += 1 + + try: + print("[=] starting antenna tune tests, this takes some time and plot window will flash up...") + # HW TUNE checks + child.sendline('hw tune') + i = child.expect('pm3 --> ') + + msg = escape_ansi(str(child.before)) + if lf_tune in msg: + print("[+] LF antenna tuning ", color('[OK]', fg='green')) + res += 1 + else: + print("[-] LF antenna tuning ", color('[FAIL]', fg='red')) + + if hf_tune in msg: + print("[+] HF antenna tuning ", color('[OK]', fg='green')) + res += 1 + else: + print("[-] HF antenna tuning ", color('[FAIL]', fg='red')) + + except: + print(color("[!] exception for hw tune", fg='red')) + msg = escape_ansi(str(child.before)) + print(msg) + child.sendline('quit') + child.expect(pexpect.EOF) + return + + # hide plot window again + child.sendline('data hide') + i = child.expect('pm3 --> ') + + ans = '' + + while ans != 'y' and args.y == False: + + ans = (input(color('>>> Put LF card and HF card on Proxmark3 antenna', fg='yellow') + ' [Y/n/q] ') or "y") + + if ans == 'q': + child.sendline('quit') + child.expect(pexpect.EOF) + print('[!] Aborted all tests ', color('[USER ABORTED]', fg='red')) + return + + # LF T55X7 WIPE/CLONE/READ TESTS + if pm3_lf_t55xx(child): + res += 1 + + # HF SEARCH TESTS + try: + print("[=] starting HF SEARCH tests...") + + # HF SEARCH Test + child.sendline('hf search') + i = child.expect('pm3 --> ') + + msg = escape_ansi(str(child.before)) + if hf_search in msg: + print("[+] HF SEARCH ", color('[OK]', fg='green')) + res += 1 + else: + print("[-] HF SEARCH ", color('[FAIL]', fg='red')) + + except: + print(color("[!] exception for HF SEARCH", fg='red')) + msg = escape_ansi(str(child.before)) + print(msg) + child.sendline('quit') + child.expect(pexpect.EOF) + return + + # MEM Tree test + child.sendline('mem spiffs info') + i = child.expect('/', timeout=10) + + msg = escape_ansi(str(child.before)) + if mem_spiffs in msg: + print("[+] MEM SPIFFS INFO ", color('[OK]', fg='green')) + res += 1 + else: + print("[-] MEM SPIFFS INFO ", color('[FAIL]', fg='red')) + + + ans = '' + while ans != 'y' and args.y == False: + + ans = (input(color('>>> Put iCLASS legacy card on Proxmark3 antenna', fg='yellow') + ' [Y/n/q] ') or "y") + + if ans == 'q': + child.sendline('quit') + child.expect(pexpect.EOF) + print('[!] Aborted all tests ', color('[USER ABORTED]', fg='red')) + return + + # iCLASS read/write test + try: + print("[=] starting iCLASS info/read/write tests...") + child.sendline('hf iclass info') + i = child.expect('pm3 --> ') + + # iclass info / read / write checks + iclass_info = 'Credential... iCLASS legacy'.lower() + + iclass_ok = False + msg = escape_ansi(str(child.before)) + if iclass_info in msg: + print("[+] HF ICLASS INFO ", color('[OK]', fg='green')) + res += 1 + iclass_ok = True + else: + print("[-] HF ICLASS INFO ", color('[FAIL]', fg='red')) + + if iclass_ok: + + child.sendline('hf iclass rdbl -b 10 --ki 0') + i = child.expect('pm3 --> ') + msg = escape_ansi(str(child.before)) + for line in msg.splitlines(): + iclass_read = 'block 10'.lower() + if iclass_read in line: + res += 1 + print("[+] HF ICLASS RDBL ", color('[OK]', fg='green')) + old_b10 = line[16:].replace(" ","") + + child.sendline('hf iclass wrbl -b 10 --ki 0 -d 0102030405060708') + i = child.expect('pm3 --> ') + msg = escape_ansi(str(child.before)) + iclass_write = 'wrote block 10 successful'.lower() + if iclass_write in msg: + res += 1 + print("[+] HF ICLASS WRBL ", color('[OK]', fg='green')) + child.sendline('hf iclass wrbl -b 10 --ki 0 -d %s' % (old_b10)) + i = child.expect('pm3 --> ') + else: + print("[-] HF ICLASS WRBL ", color('[FAIL]', fg='red')) + + break; + + else: + print("[-] skipping iclass read/write") + + except: + print(color("[!] exception iCLASS read/write", fg='red')) + msg = escape_ansi(str(child.before)) + print(msg) + child.sendline('quit') + child.expect(pexpect.EOF) + return + + + # exit Proxmark3 client + child.sendline('quit') + i = child.expect(pexpect.EOF) + + print("[+] PM3 client closed\n") + + # validate test results + + print("-------------------------", color('Results', fg='cyan'), "-------------------------") + if res == total_tests: + print('[+] Passed ', color('[OK]', fg='green')) + else: + print('[-] failed test ', color('[FAIL]', fg='red'), '(%d / %d tests)' % (res, total_tests)) + print("") + +if __name__ == "__main__": + main() From 15c36d550c38b2ae972f68646922a95e4010b8a7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 2 Jul 2021 20:10:42 +0200 Subject: [PATCH 148/309] text --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fad7487c5..6ec140043 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added `pm3_online_check.py` - a script to verify and initialize a Proxmark3 RDV4 device (@iceman1001) ## [midsummer.4.13441][2021-06-25] - Added bruteforce function for the magic byte in `cmdlfnexwatch.c` and ability to clone with psk2 modulation (@Guilhem7, @MaximeBosca) From a73c6ef90a041379e620059a4a685c6eedf71bee Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 2 Jul 2021 22:13:45 +0300 Subject: [PATCH 149/309] add array_length --- client/src/util.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/util.h b/client/src/util.h index 2730ed44f..9357eb1d0 100644 --- a/client/src/util.h +++ b/client/src/util.h @@ -16,6 +16,8 @@ #include #endif +#define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) ) + // used for save/load files #ifndef FILE_PATH_SIZE # define FILE_PATH_SIZE 1000 From 850e36ab3168c7ca2d665d57631475f18e3c2486 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 3 Jul 2021 00:07:21 +0300 Subject: [PATCH 150/309] cli parser text options --- client/deps/cliparser/cliparser.c | 52 +++++++++++++++++++++++++++++++ client/deps/cliparser/cliparser.h | 12 +++++++ 2 files changed, 64 insertions(+) diff --git a/client/deps/cliparser/cliparser.c b/client/deps/cliparser/cliparser.c index ec9f50e20..265c97103 100644 --- a/client/deps/cliparser/cliparser.c +++ b/client/deps/cliparser/cliparser.c @@ -298,6 +298,58 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int return 0; } +int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array, size_t option_array_len, int *value) { + char data[200] = {0}; + int datalen = 0; + int res = CLIParamStrToBuf(argstr, (uint8_t *)data, sizeof(data), &datalen); + if (res) + return res; + + // no data to check - we do not touch *value, just return + if (datalen == 0) + return 0; + + str_lower(data); + + int val = -1; + int cntr = 0; + for (int i = 0; i < option_array_len; i++) { + // exact match + if (strcmp(option_array[i].text, data) == 0) { + *value = option_array[i].code; + return 0; + } + // partial match + if (strncmp(option_array[i].text, data, datalen) == 0) { + val = option_array[i].code; + cntr++; + } + } + + // check partial match + if (cntr == 0) { + PrintAndLogEx(ERR, "Parameter error: No similar option to `%s`. Valid options: %s\n", argstr->sval[0], argstr->hdr.datatype); + return 20; + } + if (cntr > 1) { + PrintAndLogEx(ERR, "Parameter error: Several options fit to `%s`. Valid options: %s\n", argstr->sval[0], argstr->hdr.datatype); + return 21; + } + + *value = val; + return 0; +} + +const char *CLIGetOptionListStr(const CLIParserOption *option_array, size_t option_array_len, int value) { + static const char *errmsg = "n/a"; + + for (int i = 0; i < option_array_len; i++) + if (option_array[i].code == value) + return option_array[i].text; + return errmsg; +} + + // hexstr -> u64, w optional len input and default value fallback. // 0 = failed // 1 = OK diff --git a/client/deps/cliparser/cliparser.h b/client/deps/cliparser/cliparser.h index 39a5792f8..f4f9b7dcf 100644 --- a/client/deps/cliparser/cliparser.h +++ b/client/deps/cliparser/cliparser.h @@ -51,6 +51,8 @@ #define CLIGetStrWithReturn(ctx, paramnum, data, datalen) if (CLIParamStrToBuf(arg_get_str((ctx), (paramnum)), (data), (*datalen), (datalen))) {CLIParserFree((ctx)); return PM3_ESOFT;} +#define CLIGetOptionListWithReturn(ctx, paramnum, option_array, option_array_len, value) if (CLIGetOptionList(arg_get_str((ctx), (paramnum)), (option_array), (option_array_len), (value))) {CLIParserFree((ctx)); return PM3_ESOFT;} + typedef struct { void **argtable; size_t argtableLen; @@ -59,6 +61,12 @@ typedef struct { const char *programHelp; char buf[1024 + 60]; } CLIParserContext; + +typedef struct { + int code; + const char *text; +} CLIParserOption; + int CLIParserInit(CLIParserContext **ctx, const char *vprogramName, const char *vprogramHint, const char *vprogramHelp); void CLIParserPrintHelp(CLIParserContext *ctx); int CLIParserParseString(CLIParserContext *ctx, const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec); @@ -69,6 +77,10 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); int CLIParamBinToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); +// names in the CLIParserOption array must be in the lowercase format +int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array, size_t option_array_len, int *value); +const char *CLIGetOptionListStr(const CLIParserOption *option_array, size_t option_array_len, int value); + uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def); int arg_get_u64_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint64_t def, uint64_t *out, uint8_t nlen, bool optional); int arg_get_u32_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint32_t def, uint32_t *out); From 7af924eadd3bfff1a6eb1084691bdcecb903c5a3 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 3 Jul 2021 00:07:55 +0300 Subject: [PATCH 151/309] add get key size function --- client/src/mifare/desfire_crypto.c | 18 ++++++++++++++++++ client/src/mifare/desfire_crypto.h | 1 + 2 files changed, 19 insertions(+) diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 1767c9c47..6ec606227 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -407,6 +407,24 @@ size_t key_block_size(const desfirekey_t key) { return block_size; } +size_t key_size(const enum DESFIRE_CRYPTOALGO algo) { + switch (algo) { + case T_DES: + return 8; + break; + case T_3DES: + return 16; + break; + case T_3K3DES: + return 24; + break; + case T_AES: + return 16; + break; + } + return 0; +} + /* * Size of MACing produced with the key. */ diff --git a/client/src/mifare/desfire_crypto.h b/client/src/mifare/desfire_crypto.h index 9c67b1182..71d17aea7 100644 --- a/client/src/mifare/desfire_crypto.h +++ b/client/src/mifare/desfire_crypto.h @@ -126,6 +126,7 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size); void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation); size_t key_block_size(const desfirekey_t key); +size_t key_size(const enum DESFIRE_CRYPTOALGO algo); size_t padded_data_length(const size_t nbytes, const size_t block_size); size_t maced_data_length(const desfirekey_t key, const size_t nbytes); size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int communication_settings); From acca624752d93b2bd23d2cd23ae33462d5c6fdf0 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 3 Jul 2021 00:08:45 +0300 Subject: [PATCH 152/309] added cli text options to command --- client/src/cmdhfmfdes.c | 140 ++++++++++++++------------------ client/src/mifare/desfirecore.h | 2 + 2 files changed, 61 insertions(+), 81 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 89c08ef37..49958e060 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5009,10 +5009,12 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("v", "verbose", "show technical data"), arg_int0("n", "keyno", "", "Key number"), - arg_int0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), + arg_str0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), - arg_int0("f", "kdf", "", "Key Derivation Function (KDF): None(default), AN10922, Gallagher"), + arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None(default), AN10922, Gallagher"), arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), + arg_str0("m", "cmode", "", "Commpunicaton mode: plain(default)/mac/encrypt"), + arg_str0("c", "commc", "", "Commpunicaton channel: native/niso(default)/iso"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -5021,95 +5023,71 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { bool verbose = arg_get_lit(ctx, 2); uint8_t keyNum = arg_get_int_def(ctx, 3, 0); // defaultKeyId -/* - int aidlength = 0; - uint8_t aid[3] = {0}; - CLIGetHexWithReturn(ctx, 1, aid, &aidlength); - swap24(aid); - uint8_t vkey[16] = {0}; - int vkeylen = 0; - CLIGetHexWithReturn(ctx, 2, vkey, &vkeylen); - if (vkeylen > 0) { - if (vkeylen == 8) { - memcpy(&deskeyList[deskeyListLen], vkey, 8); - deskeyListLen++; - } else if (vkeylen == 16) { - memcpy(&aeskeyList[aeskeyListLen], vkey, 16); - aeskeyListLen++; - } else if (vkeylen == 24) { - memcpy(&k3kkeyList[k3kkeyListLen], vkey, 16); - k3kkeyListLen++; - } else { - PrintAndLogEx(ERR, "Specified key must have 8, 16 or 24 bytes length."); - CLIParserFree(ctx); - return PM3_EINVARG; - } + const CLIParserOption algo_opts[] = { + {T_DES, "des"}, + {T_3DES, "2tdea"}, + {T_3K3DES, "3tdea"}, + {T_AES, "aes"}, + }; + + int ares = T_DES; + CLIGetOptionListWithReturn(ctx, 4, algo_opts, ARRAY_LENGTH(algo_opts), &ares); + PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), ares)); + + int keylen = 0; + uint8_t key[200] = {0}; + CLIGetHexWithReturn(ctx, 5, key, &keylen); + if (keylen == 0) { + keylen = key_size(ares); + //memcpy(key, defaultkey, key_size(ares)); } - - uint8_t dict_filename[FILE_PATH_SIZE + 2] = {0}; - int dict_filenamelen = 0; - if (CLIParamStrToBuf(arg_get_str(ctx, 3), dict_filename, FILE_PATH_SIZE, &dict_filenamelen)) { - PrintAndLogEx(FAILED, "File name too long or invalid."); + if (keylen != key_size(ares)) { + PrintAndLogEx(ERR, "%s key must have %d bytes length instead of %d.", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), ares), key_size(ares), keylen); CLIParserFree(ctx); return PM3_EINVARG; } - - bool pattern1b = arg_get_lit(ctx, 4); - bool pattern2b = arg_get_lit(ctx, 5); - - if (pattern1b && pattern2b) { - PrintAndLogEx(ERR, "Pattern search mode must be 2-byte or 1-byte only."); - CLIParserFree(ctx); - return PM3_EINVARG; - } - - if (dict_filenamelen && (pattern1b || pattern2b)) { - PrintAndLogEx(ERR, "Pattern search mode and dictionary mode can't be used in one command."); - CLIParserFree(ctx); - return PM3_EINVARG; - } - - uint32_t startPattern = 0x0000; - uint8_t vpattern[2]; - int vpatternlen = 0; - CLIGetHexWithReturn(ctx, 6, vpattern, &vpatternlen); - if (vpatternlen > 0) { - if (vpatternlen <= 2) { - startPattern = (vpattern[0] << 8) + vpattern[1]; - } else { - PrintAndLogEx(ERR, "Pattern must be 2-byte length."); - CLIParserFree(ctx); - return PM3_EINVARG; - } - if (!pattern2b) - PrintAndLogEx(WARNING, "Pattern entered, but search mode not is 2-byte search."); - } - - uint8_t jsonname[250] = {0}; - int jsonnamelen = 0; - if (CLIParamStrToBuf(arg_get_str(ctx, 7), jsonname, sizeof(jsonname), &jsonnamelen)) { - PrintAndLogEx(ERR, "Invalid json name."); - CLIParserFree(ctx); - return PM3_EINVARG; - } - jsonname[jsonnamelen] = 0; - - bool verbose = arg_get_lit(ctx, 8); - - // Get KDF input - uint8_t kdfInput[31] = {0}; + + const CLIParserOption kdf_opts[] = { + {MFDES_KDF_ALGO_NONE, "none"}, + {MFDES_KDF_ALGO_AN10922, "an10922"}, + {MFDES_KDF_ALGO_GALLAGHER, "gallagher"}, + }; + + int kres = MFDES_KDF_ALGO_NONE; + CLIGetOptionListWithReturn(ctx, 6, kdf_opts, ARRAY_LENGTH(kdf_opts), &kres); + PrintAndLogEx(INFO, "kdf funct: %s", CLIGetOptionListStr(kdf_opts, ARRAY_LENGTH(kdf_opts), kres)); + int kdfInputLen = 0; - uint8_t cmdKDFAlgo = arg_get_int_def(ctx, 9, 0); - CLIGetHexWithReturn(ctx, 10, kdfInput, &kdfInputLen); -*/ + uint8_t kdfInput[50] = {0}; + CLIGetHexWithReturn(ctx, 7, kdfInput, &kdfInputLen); + + const CLIParserOption cmode_opts[] = { + {DCMPlain, "plain"}, + {DCMMACed, "mac"}, + {DCMEncrypted, "encrypt"}, + }; + + int commmode = DCMPlain; + CLIGetOptionListWithReturn(ctx, 8, cmode_opts, ARRAY_LENGTH(cmode_opts), &commmode); + PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(cmode_opts, ARRAY_LENGTH(cmode_opts), commmode)); + + const CLIParserOption commc_opts[] = { + {DCCNative, "native"}, + {DCCNativeISO, "niso"}, + {DCCISO, "iso"}, + }; + + int commchann = DCCNativeISO; + CLIGetOptionListWithReturn(ctx, 8, commc_opts, ARRAY_LENGTH(commc_opts), &commchann); + PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(commc_opts, ARRAY_LENGTH(commc_opts), commchann)); + SetAPDULogging(APDULogging); CLIParserFree(ctx); - uint8_t key[24] = {0}; DesfireContext dctx; - DesfireSetKey(&dctx, keyNum, T_DES, key); // T_DES T_3DES T_3K3DES T_AES - DesfireSetCommandChannel(&dctx, DCCNativeISO); + DesfireSetKey(&dctx, keyNum, ares, key); // T_DES T_3DES T_3K3DES T_AES + DesfireSetCommandChannel(&dctx, commchann); int res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index cae333015..bffcda7bd 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -21,6 +21,8 @@ #define DESFIRE_GET_ISO_STATUS(x) ( ((uint16_t)(0x91<<8)) + (uint16_t)x ) +typedef enum DESFIRE_CRYPTOALGO DesfireCryptoAlgorythm; + typedef enum { DACNone, DACd40, From f9e006f2e3a091d4cde927b72991a236685bceef Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 3 Jul 2021 12:21:29 +0300 Subject: [PATCH 153/309] added authchann otion --- client/src/cmdhfmfdes.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 49958e060..c8721433b 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5011,10 +5011,11 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { arg_int0("n", "keyno", "", "Key number"), arg_str0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), - arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None(default), AN10922, Gallagher"), + arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None, AN10922, Gallagher"), arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), - arg_str0("m", "cmode", "", "Commpunicaton mode: plain(default)/mac/encrypt"), - arg_str0("c", "commc", "", "Commpunicaton channel: native/niso(default)/iso"), + arg_str0("m", "cmode", "", "Commpunicaton mode: plain/mac/encrypt"), + arg_str0("c", "commc", "", "Commpunicaton channel: native/niso/iso"), + arg_str0("u", "authc", "", "Authentication channel: d40/ev1/ev2"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -5082,6 +5083,16 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { CLIGetOptionListWithReturn(ctx, 8, commc_opts, ARRAY_LENGTH(commc_opts), &commchann); PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(commc_opts, ARRAY_LENGTH(commc_opts), commchann)); + const CLIParserOption authc_opts[] = { + {DACd40, "d40"}, + {DACEV1, "ev1"}, + {DACEV2, "ev2"}, + }; + + int authchann = DACEV1; + CLIGetOptionListWithReturn(ctx, 9, authc_opts, ARRAY_LENGTH(authc_opts), &authchann); + PrintAndLogEx(INFO, "auth channel: %s", CLIGetOptionListStr(authc_opts, ARRAY_LENGTH(authc_opts), authchann)); + SetAPDULogging(APDULogging); CLIParserFree(ctx); @@ -5097,7 +5108,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { return PM3_ESOFT; } - res = DesfireAuthenticate(&dctx, DACd40); //DACd40 DACEV1 + res = DesfireAuthenticate(&dctx, authchann); //DACd40 DACEV1 if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res); DropField(); From 0d00f567779f1f531e7f838cd3c64026511e48f7 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 3 Jul 2021 13:11:17 +0300 Subject: [PATCH 154/309] CmdHF14ADesGetAppNames works --- client/src/cmdhfmfdes.c | 150 +++++++++++++++++++++++++++++++- client/src/mifare/desfirecore.c | 31 ++++--- client/src/mifare/desfirecore.h | 2 +- 3 files changed, 167 insertions(+), 16 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index c8721433b..384e67049 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5080,7 +5080,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { }; int commchann = DCCNativeISO; - CLIGetOptionListWithReturn(ctx, 8, commc_opts, ARRAY_LENGTH(commc_opts), &commchann); + CLIGetOptionListWithReturn(ctx, 9, commc_opts, ARRAY_LENGTH(commc_opts), &commchann); PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(commc_opts, ARRAY_LENGTH(commc_opts), commchann)); const CLIParserOption authc_opts[] = { @@ -5090,7 +5090,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { }; int authchann = DACEV1; - CLIGetOptionListWithReturn(ctx, 9, authc_opts, ARRAY_LENGTH(authc_opts), &authchann); + CLIGetOptionListWithReturn(ctx, 10, authc_opts, ARRAY_LENGTH(authc_opts), &authchann); PrintAndLogEx(INFO, "auth channel: %s", CLIGetOptionListStr(authc_opts, ARRAY_LENGTH(authc_opts), authchann)); SetAPDULogging(APDULogging); @@ -5142,8 +5142,152 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { return PM3_SUCCESS; } -// {"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "Get Applications list"}, static int CmdHF14ADesGetAppNames(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes getappnames", + "Get Application IDs, ISO IDs and DF names from card. Master key needs to be provided.", + "hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "apdu", "show APDU requests and responses"), + arg_lit0("v", "verbose", "show technical data"), + arg_int0("n", "keyno", "", "Key number"), + arg_str0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), + arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None, AN10922, Gallagher"), + arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), + arg_str0("m", "cmode", "", "Commpunicaton mode: plain/mac/encrypt"), + arg_str0("c", "commc", "", "Commpunicaton channel: native/niso/iso"), + arg_str0("u", "authc", "", "Authentication channel: d40/ev1/ev2"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + bool APDULogging = arg_get_lit(ctx, 1); + bool verbose = arg_get_lit(ctx, 2); + uint8_t keyNum = arg_get_int_def(ctx, 3, 0); // defaultKeyId + + + const CLIParserOption algo_opts[] = { + {T_DES, "des"}, + {T_3DES, "2tdea"}, + {T_3K3DES, "3tdea"}, + {T_AES, "aes"}, + }; + + int ares = T_DES; + CLIGetOptionListWithReturn(ctx, 4, algo_opts, ARRAY_LENGTH(algo_opts), &ares); + PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), ares)); + + int keylen = 0; + uint8_t key[200] = {0}; + CLIGetHexWithReturn(ctx, 5, key, &keylen); + if (keylen == 0) { + keylen = key_size(ares); + //memcpy(key, defaultkey, key_size(ares)); + } + if (keylen != key_size(ares)) { + PrintAndLogEx(ERR, "%s key must have %d bytes length instead of %d.", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), ares), key_size(ares), keylen); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + const CLIParserOption kdf_opts[] = { + {MFDES_KDF_ALGO_NONE, "none"}, + {MFDES_KDF_ALGO_AN10922, "an10922"}, + {MFDES_KDF_ALGO_GALLAGHER, "gallagher"}, + }; + + int kres = MFDES_KDF_ALGO_NONE; + CLIGetOptionListWithReturn(ctx, 6, kdf_opts, ARRAY_LENGTH(kdf_opts), &kres); + PrintAndLogEx(INFO, "kdf funct: %s", CLIGetOptionListStr(kdf_opts, ARRAY_LENGTH(kdf_opts), kres)); + + int kdfInputLen = 0; + uint8_t kdfInput[50] = {0}; + CLIGetHexWithReturn(ctx, 7, kdfInput, &kdfInputLen); + + const CLIParserOption cmode_opts[] = { + {DCMPlain, "plain"}, + {DCMMACed, "mac"}, + {DCMEncrypted, "encrypt"}, + }; + + int commmode = DCMPlain; + CLIGetOptionListWithReturn(ctx, 8, cmode_opts, ARRAY_LENGTH(cmode_opts), &commmode); + PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(cmode_opts, ARRAY_LENGTH(cmode_opts), commmode)); + + const CLIParserOption commc_opts[] = { + {DCCNative, "native"}, + {DCCNativeISO, "niso"}, + {DCCISO, "iso"}, + }; + + int commchann = DCCNativeISO; + CLIGetOptionListWithReturn(ctx, 9, commc_opts, ARRAY_LENGTH(commc_opts), &commchann); + PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(commc_opts, ARRAY_LENGTH(commc_opts), commchann)); + + const CLIParserOption authc_opts[] = { + {DACd40, "d40"}, + {DACEV1, "ev1"}, + {DACEV2, "ev2"}, + }; + + int authchann = DACEV1; + CLIGetOptionListWithReturn(ctx, 10, authc_opts, ARRAY_LENGTH(authc_opts), &authchann); + PrintAndLogEx(INFO, "auth channel: %s", CLIGetOptionListStr(authc_opts, ARRAY_LENGTH(authc_opts), authchann)); + + SetAPDULogging(APDULogging); + CLIParserFree(ctx); + + DesfireContext dctx; + DesfireSetKey(&dctx, keyNum, ares, key); + DesfireSetCommandChannel(&dctx, commchann); + + + int res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); + DropField(); + return PM3_ESOFT; + } + + res = DesfireAuthenticate(&dctx, authchann); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + if (DesfireIsAuthenticated(&dctx)) { + if (verbose) + PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated") , res); + } else { + return PM3_ESOFT; + } + + uint8_t buf[APDU_RES_LEN] = {0}; + size_t buflen = 0; + + // result bytes: 3, 2, 1-16. total record size = 24 + res = DesfireGetDFList(&dctx, buf, &buflen); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire DesfireGetDFList command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + if (buflen > 0) { + PrintAndLogEx(INFO, "----------------------- " _CYAN_("File list") " -----------------------"); + for (int i = 0; i < buflen; i++) + PrintAndLogEx(INFO, "AID: %06x ISO file id: %02x%02x ISO DF name[%d]: %s", + DesfireAIDByteToUint(&buf[i * 24]), + buf[i * 24 + 3], buf[i * 24 + 4], + strlen((char *)&buf[i * 24 + 5]), + &buf[i * 24 + 5]); + } + + DropField(); return PM3_SUCCESS; } diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index de71db69f..18aa09265 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -256,20 +256,17 @@ static int DESFIRESendApdu(bool activate_field, sAPDU apdu, uint8_t *result, uin return PM3_SUCCESS; } -static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining) { +static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { return PM3_SUCCESS; } -static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining) { +static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { if (resplen) *resplen = 0; if (respcode) *respcode = 0xff; - // TODO !!! - size_t splitbysize = 0; - uint16_t sw = 0; uint8_t buf[255 * 5] = {0x00}; uint32_t buflen = 0; @@ -342,15 +339,15 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t return PM3_SUCCESS; } -int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining) { +int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { int res = PM3_SUCCESS; switch(ctx->cmdChannel) { case DCCNative: - res = DesfireExchangeNative(activate_field, ctx, cmd, data, datalen, respcode, resp, resplen, enable_chaining); + res = DesfireExchangeNative(activate_field, ctx, cmd, data, datalen, respcode, resp, resplen, enable_chaining, splitbysize); break; case DCCNativeISO: - res = DesfireExchangeISO(activate_field, ctx, cmd, data, datalen, respcode, resp, resplen, enable_chaining); + res = DesfireExchangeISO(activate_field, ctx, cmd, data, datalen, respcode, resp, resplen, enable_chaining, splitbysize); break; case DCCISO: return PM3_EAPDU_FAIL; @@ -361,7 +358,7 @@ int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uin } int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen) { - return DesfireExchangeEx(false, ctx, cmd, data, datalen, respcode, resp, resplen, true); + return DesfireExchangeEx(false, ctx, cmd, data, datalen, respcode, resp, resplen, true, 0); } int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2) { @@ -376,7 +373,7 @@ int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2) { size_t resplen = 0; uint8_t respcode = 0; - int res = DesfireExchangeEx(true, ctx, MFDES_SELECT_APPLICATION, data, (aid2 == NULL) ? 3 : 6, &respcode, resp, &resplen, true); + int res = DesfireExchangeEx(true, ctx, MFDES_SELECT_APPLICATION, data, (aid2 == NULL) ? 3 : 6, &respcode, resp, &resplen, true, 0); if (res == PM3_SUCCESS) { if (resplen != 0) return PM3_ECARDEXCHANGE; @@ -472,7 +469,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel) { uint8_t recv_data[256] = {0}; // Let's send our auth command - int res = DesfireExchangeEx(false, dctx, subcommand, &dctx->keyNum, 1, &respcode, recv_data, &recv_len, false); + int res = DesfireExchangeEx(false, dctx, subcommand, &dctx->keyNum, 1, &respcode, recv_data, &recv_len, false, 0); if (res != PM3_SUCCESS) { return 1; } @@ -585,7 +582,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel) { bothlen = 32; } - res = DesfireExchangeEx(false, dctx, MFDES_ADDITIONAL_FRAME, both, bothlen, &respcode, recv_data, &recv_len, false); + res = DesfireExchangeEx(false, dctx, MFDES_ADDITIONAL_FRAME, both, bothlen, &respcode, recv_data, &recv_len, false, 0); if (res != PM3_SUCCESS) { return 7; } @@ -661,3 +658,13 @@ int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { return PM3_EAPDU_FAIL; return PM3_SUCCESS; } + +int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { + uint8_t respcode = 0xff; + int res = DesfireExchangeEx(false, dctx, MFDES_GET_DF_NAMES, NULL, 0, &respcode, resp, resplen, true, 24); + if (res != PM3_SUCCESS) + return res; + if (respcode != MFDES_S_OPERATION_OK) + return PM3_EAPDU_FAIL; + return PM3_SUCCESS; +} diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index bffcda7bd..a0b31babb 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -77,7 +77,7 @@ uint32_t DesfireAIDByteToUint(uint8_t *data); void DesfireAIDUintToByte(uint32_t aid, uint8_t *data); int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen); -int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining); +int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize); int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2); int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2); From 24a2a9434185fc07528278a64835a368683babbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ya=C4=9F=C4=B1ztegin=20Ero=C4=9Flu?= Date: Sat, 3 Jul 2021 17:07:53 +0300 Subject: [PATCH 155/309] add experimental support for macs with macports installed currently requires symlinking python{version}(-embed).pc to python(embed).pc or python3(-embed).pc under /opt/local/lib/pkgconfig --- Makefile.defs | 5 ++++- client/Makefile | 33 +++++++++++++++++++++++++-------- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/Makefile.defs b/Makefile.defs index 5a6993228..5cce62f1d 100644 --- a/Makefile.defs +++ b/Makefile.defs @@ -59,7 +59,10 @@ else endif ifeq ($(USE_BREW),1) - BREW_PREFIX = $(shell brew --prefix) + BREW_PREFIX = $(shell brew --prefix 2>/dev/null) + ifeq ($(BREW_PREFIX),) + MACPORTS_PREFIX = /opt/local + endif endif ifeq ($(DEBUG),1) diff --git a/client/Makefile b/client/Makefile index 9ed3feb86..507a3a7a8 100644 --- a/client/Makefile +++ b/client/Makefile @@ -14,10 +14,18 @@ vpath %.dic dictionaries OBJDIR = obj ifeq ($(USE_BREW),1) - INCLUDES += -I$(BREW_PREFIX)/include - LDLIBS += -L$(BREW_PREFIX)/lib - PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(BREW_PREFIX)/opt/qt/lib/pkgconfig - PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(BREW_PREFIX)/opt/qt5/lib/pkgconfig + ifdef MACPORTS_PREFIX + INCLUDES += -I$(MACPORTS_PREFIX)/include + LDLIBS += -L$(MACPORTS_PREFIX)/lib + PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(MACPORTS_PREFIX)/lib/pkgconfig + PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(MACPORTS_PREFIX)/libexec/qt/lib/pkgconfig + PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(MACPORTS_PREFIX)/libexec/qt5/lib/pkgconfig + else + INCLUDES += -I$(BREW_PREFIX)/include + LDLIBS += -L$(BREW_PREFIX)/lib + PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(BREW_PREFIX)/opt/qt/lib/pkgconfig + PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(BREW_PREFIX)/opt/qt5/lib/pkgconfig + endif endif ################### @@ -117,8 +125,13 @@ INCLUDES += $(HARDNESTEDLIBINC) ## Lua ifneq ($(SKIPLUASYSTEM),1) - LUAINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags lua5.2 2>/dev/null) - LUALDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs lua5.2 2>/dev/null) + ifdef MACPORTS_PREFIX + LUAINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags lua-5.2 2>/dev/null) + LUALDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs lua-5.2 2>/dev/null) + else + LUAINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags lua5.2 2>/dev/null) + LUALDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs lua5.2 2>/dev/null) + endif ifneq ($(LUALDLIBS),) LUALIB = LUALIBLD = $(LUALDLIBS) @@ -279,8 +292,12 @@ CXXINCLUDES += $(QTINCLUDES) ## Readline ifneq ($(SKIPREADLINE),1) ifeq ($(USE_BREW),1) - LDLIBS += -L$(BREW_PREFIX)/opt/readline/lib - INCLUDES += -I$(BREW_PREFIX)/opt/readline/include + ifdef MACPORTS_PREFIX + INCLUDES += -I$(MACPORTS_PREFIX)/include/readline + else + LDLIBS += -L$(BREW_PREFIX)/opt/readline/lib + INCLUDES += -I$(BREW_PREFIX)/opt/readline/include + endif endif LDLIBS += -lreadline READLINE_FOUND = 1 From 1b2442ec36a701272e417f51ffdaff966074351a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 3 Jul 2021 17:31:12 +0300 Subject: [PATCH 156/309] regactoring desfire commands. textual fixes --- client/src/cmdhfmfdes.c | 312 ++++++++++++++--------------- client/src/cmdhfmfdes.h | 3 +- client/src/mifare/desfire_crypto.c | 1 + client/src/mifare/desfire_crypto.h | 23 ++- client/src/mifare/desfirecore.c | 48 +++-- client/src/mifare/desfirecore.h | 17 +- 6 files changed, 223 insertions(+), 181 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 384e67049..c29f74cc6 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1,5 +1,6 @@ //----------------------------------------------------------------------------- // Copyright (C) 2014 Iceman +// Copyright (C) 2021 Merlok // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -4997,6 +4998,133 @@ static int CmdHF14aDesMAD(const char *Cmd) { return PM3_SUCCESS; } */ +static uint8_t defaultKeyNum = 0; +static enum DESFIRE_CRYPTOALGO defaultAlgoId = T_DES; +static uint8_t defaultKey[DESFIRE_MAX_KEY_SIZE] = {0}; +static int defaultKdfAlgo = MFDES_KDF_ALGO_NONE; +static int defaultKdfInputLen = 0; +static uint8_t defaultKdfInput[50] = {0}; +static DesfireSecureChannel defaultSecureChannel = DACEV1; +static DesfireCommandSet defaultCommSet = DCCNativeISO; +static DesfireCommunicationMode defaultCommMode = DCMPlain; + +static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dctx, + uint8_t keynoid, uint8_t algoid, uint8_t keyid, + uint8_t kdfid, uint8_t kdfiid, + uint8_t cmodeid, uint8_t ccsetid, uint8_t schannid, + int *securechannel) { + + uint8_t keynum = defaultKeyNum; + int algores = defaultAlgoId; + uint8_t key[DESFIRE_MAX_KEY_SIZE] = {0}; + memcpy(key, defaultKey, DESFIRE_MAX_KEY_SIZE); + int kdfAlgo = defaultKdfAlgo; + int kdfInputLen = defaultKdfInputLen; + uint8_t kdfInput[50] = {0}; + memcpy(kdfInput, defaultKdfInput, defaultKdfInputLen); + int commmode = defaultCommMode; + int commset = defaultCommSet; + int secchann = defaultSecureChannel; + + if (keynoid) { + keynum = arg_get_int_def(ctx, keynoid, keynum); + } + + const CLIParserOption algo_opts[] = { + {T_DES, "des"}, + {T_3DES, "2tdea"}, + {T_3K3DES, "3tdea"}, + {T_AES, "aes"}, + }; + + if (algoid) { + if (CLIGetOptionList(arg_get_str(ctx, algoid), algo_opts, ARRAY_LENGTH(algo_opts), &algores)) + return PM3_ESOFT; + PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), algores)); + } + + if (keyid) { + int keylen = 0; + uint8_t keydata[200] = {0}; + if (CLIParamHexToBuf(arg_get_str(ctx, keyid), keydata, sizeof(keydata), &keylen)) + return PM3_ESOFT; + if (keylen && keylen != key_size(algores)) { + PrintAndLogEx(ERR, "%s key must have %d bytes length instead of %d.", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), algores), key_size(algores), keylen); + return PM3_EINVARG; + } + if (keylen) + memcpy(key, keydata, keylen); + } + + if (kdfid) { + const CLIParserOption kdf_opts[] = { + {MFDES_KDF_ALGO_NONE, "none"}, + {MFDES_KDF_ALGO_AN10922, "an10922"}, + {MFDES_KDF_ALGO_GALLAGHER, "gallagher"}, + }; + + if (CLIGetOptionList(arg_get_str(ctx, kdfid), kdf_opts, ARRAY_LENGTH(kdf_opts), &kdfAlgo)) + return PM3_ESOFT; + PrintAndLogEx(INFO, "kdf funct: %s", CLIGetOptionListStr(kdf_opts, ARRAY_LENGTH(kdf_opts), kdfAlgo)); + + } + + if (kdfiid) { + int datalen = kdfInputLen; + uint8_t data[200] = {0}; + if (CLIParamHexToBuf(arg_get_str(ctx, kdfiid), data, sizeof(data), &datalen)) + return PM3_ESOFT; + if (datalen) { + kdfInputLen = datalen; + memcpy(kdfInput, data, datalen); + } + } + + if (cmodeid) { + const CLIParserOption cmode_opts[] = { + {DCMPlain, "plain"}, + {DCMMACed, "mac"}, + {DCMEncrypted, "encrypt"}, + }; + + if (CLIGetOptionList(arg_get_str(ctx, cmodeid), cmode_opts, ARRAY_LENGTH(cmode_opts), &commmode)) + return PM3_ESOFT; + PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(cmode_opts, ARRAY_LENGTH(cmode_opts), commmode)); + } + + if (ccsetid) { + const CLIParserOption commc_opts[] = { + {DCCNative, "native"}, + {DCCNativeISO, "niso"}, + {DCCISO, "iso"}, + }; + + if (CLIGetOptionList(arg_get_str(ctx, ccsetid), commc_opts, ARRAY_LENGTH(commc_opts), &commset)) + return PM3_ESOFT; + PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(commc_opts, ARRAY_LENGTH(commc_opts), commset)); + } + + if (schannid) { + const CLIParserOption authc_opts[] = { + {DACd40, "d40"}, + {DACEV1, "ev1"}, + {DACEV2, "ev2"}, + }; + + if (CLIGetOptionList(arg_get_str(ctx, schannid), authc_opts, ARRAY_LENGTH(authc_opts), &secchann)) + return PM3_ESOFT; + PrintAndLogEx(INFO, "auth channel: %s", CLIGetOptionListStr(authc_opts, ARRAY_LENGTH(authc_opts), secchann)); + } + + DesfireSetKey(dctx, keynum, algores, key); + DesfireSetKdf(dctx, kdfAlgo, kdfInput, kdfInputLen); + DesfireSetCommandSet(dctx, commset); + DesfireSetCommMode(dctx, commmode); + if (securechannel) + *securechannel = secchann; + + return PM3_SUCCESS; +} static int CmdHF14ADesGetAIDs(const char *Cmd) { CLIParserContext *ctx; @@ -5013,102 +5141,38 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None, AN10922, Gallagher"), arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), - arg_str0("m", "cmode", "", "Commpunicaton mode: plain/mac/encrypt"), - arg_str0("c", "commc", "", "Commpunicaton channel: native/niso/iso"), - arg_str0("u", "authc", "", "Authentication channel: d40/ev1/ev2"), + 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_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - uint8_t keyNum = arg_get_int_def(ctx, 3, 0); // defaultKeyId - - - const CLIParserOption algo_opts[] = { - {T_DES, "des"}, - {T_3DES, "2tdea"}, - {T_3K3DES, "3tdea"}, - {T_AES, "aes"}, - }; - int ares = T_DES; - CLIGetOptionListWithReturn(ctx, 4, algo_opts, ARRAY_LENGTH(algo_opts), &ares); - PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), ares)); - - int keylen = 0; - uint8_t key[200] = {0}; - CLIGetHexWithReturn(ctx, 5, key, &keylen); - if (keylen == 0) { - keylen = key_size(ares); - //memcpy(key, defaultkey, key_size(ares)); - } - if (keylen != key_size(ares)) { - PrintAndLogEx(ERR, "%s key must have %d bytes length instead of %d.", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), ares), key_size(ares), keylen); + DesfireContext dctx; + int securechann = defaultSecureChannel; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, &securechann); + if (res) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } - const CLIParserOption kdf_opts[] = { - {MFDES_KDF_ALGO_NONE, "none"}, - {MFDES_KDF_ALGO_AN10922, "an10922"}, - {MFDES_KDF_ALGO_GALLAGHER, "gallagher"}, - }; - - int kres = MFDES_KDF_ALGO_NONE; - CLIGetOptionListWithReturn(ctx, 6, kdf_opts, ARRAY_LENGTH(kdf_opts), &kres); - PrintAndLogEx(INFO, "kdf funct: %s", CLIGetOptionListStr(kdf_opts, ARRAY_LENGTH(kdf_opts), kres)); - - int kdfInputLen = 0; - uint8_t kdfInput[50] = {0}; - CLIGetHexWithReturn(ctx, 7, kdfInput, &kdfInputLen); - - const CLIParserOption cmode_opts[] = { - {DCMPlain, "plain"}, - {DCMMACed, "mac"}, - {DCMEncrypted, "encrypt"}, - }; - - int commmode = DCMPlain; - CLIGetOptionListWithReturn(ctx, 8, cmode_opts, ARRAY_LENGTH(cmode_opts), &commmode); - PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(cmode_opts, ARRAY_LENGTH(cmode_opts), commmode)); - - const CLIParserOption commc_opts[] = { - {DCCNative, "native"}, - {DCCNativeISO, "niso"}, - {DCCISO, "iso"}, - }; - - int commchann = DCCNativeISO; - CLIGetOptionListWithReturn(ctx, 9, commc_opts, ARRAY_LENGTH(commc_opts), &commchann); - PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(commc_opts, ARRAY_LENGTH(commc_opts), commchann)); - - const CLIParserOption authc_opts[] = { - {DACd40, "d40"}, - {DACEV1, "ev1"}, - {DACEV2, "ev2"}, - }; - - int authchann = DACEV1; - CLIGetOptionListWithReturn(ctx, 10, authc_opts, ARRAY_LENGTH(authc_opts), &authchann); - PrintAndLogEx(INFO, "auth channel: %s", CLIGetOptionListStr(authc_opts, ARRAY_LENGTH(authc_opts), authchann)); - SetAPDULogging(APDULogging); CLIParserFree(ctx); - DesfireContext dctx; - DesfireSetKey(&dctx, keyNum, ares, key); // T_DES T_3DES T_3K3DES T_AES - DesfireSetCommandChannel(&dctx, commchann); + if (verbose) + DesfirePrintContext(&dctx); - - int res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); + res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); DropField(); return PM3_ESOFT; } - res = DesfireAuthenticate(&dctx, authchann); //DACd40 DACEV1 + res = DesfireAuthenticate(&dctx, securechann); //DACd40 DACEV1 if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res); DropField(); @@ -5157,102 +5221,38 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None, AN10922, Gallagher"), arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), - arg_str0("m", "cmode", "", "Commpunicaton mode: plain/mac/encrypt"), - arg_str0("c", "commc", "", "Commpunicaton channel: native/niso/iso"), - arg_str0("u", "authc", "", "Authentication channel: d40/ev1/ev2"), + 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_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - uint8_t keyNum = arg_get_int_def(ctx, 3, 0); // defaultKeyId - - - const CLIParserOption algo_opts[] = { - {T_DES, "des"}, - {T_3DES, "2tdea"}, - {T_3K3DES, "3tdea"}, - {T_AES, "aes"}, - }; - - int ares = T_DES; - CLIGetOptionListWithReturn(ctx, 4, algo_opts, ARRAY_LENGTH(algo_opts), &ares); - PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), ares)); - - int keylen = 0; - uint8_t key[200] = {0}; - CLIGetHexWithReturn(ctx, 5, key, &keylen); - if (keylen == 0) { - keylen = key_size(ares); - //memcpy(key, defaultkey, key_size(ares)); - } - if (keylen != key_size(ares)) { - PrintAndLogEx(ERR, "%s key must have %d bytes length instead of %d.", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), ares), key_size(ares), keylen); - CLIParserFree(ctx); - return PM3_EINVARG; - } - - const CLIParserOption kdf_opts[] = { - {MFDES_KDF_ALGO_NONE, "none"}, - {MFDES_KDF_ALGO_AN10922, "an10922"}, - {MFDES_KDF_ALGO_GALLAGHER, "gallagher"}, - }; - - int kres = MFDES_KDF_ALGO_NONE; - CLIGetOptionListWithReturn(ctx, 6, kdf_opts, ARRAY_LENGTH(kdf_opts), &kres); - PrintAndLogEx(INFO, "kdf funct: %s", CLIGetOptionListStr(kdf_opts, ARRAY_LENGTH(kdf_opts), kres)); - - int kdfInputLen = 0; - uint8_t kdfInput[50] = {0}; - CLIGetHexWithReturn(ctx, 7, kdfInput, &kdfInputLen); - - const CLIParserOption cmode_opts[] = { - {DCMPlain, "plain"}, - {DCMMACed, "mac"}, - {DCMEncrypted, "encrypt"}, - }; - - int commmode = DCMPlain; - CLIGetOptionListWithReturn(ctx, 8, cmode_opts, ARRAY_LENGTH(cmode_opts), &commmode); - PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(cmode_opts, ARRAY_LENGTH(cmode_opts), commmode)); - - const CLIParserOption commc_opts[] = { - {DCCNative, "native"}, - {DCCNativeISO, "niso"}, - {DCCISO, "iso"}, - }; - - int commchann = DCCNativeISO; - CLIGetOptionListWithReturn(ctx, 9, commc_opts, ARRAY_LENGTH(commc_opts), &commchann); - PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(commc_opts, ARRAY_LENGTH(commc_opts), commchann)); - - const CLIParserOption authc_opts[] = { - {DACd40, "d40"}, - {DACEV1, "ev1"}, - {DACEV2, "ev2"}, - }; - - int authchann = DACEV1; - CLIGetOptionListWithReturn(ctx, 10, authc_opts, ARRAY_LENGTH(authc_opts), &authchann); - PrintAndLogEx(INFO, "auth channel: %s", CLIGetOptionListStr(authc_opts, ARRAY_LENGTH(authc_opts), authchann)); - - SetAPDULogging(APDULogging); - CLIParserFree(ctx); DesfireContext dctx; - DesfireSetKey(&dctx, keyNum, ares, key); - DesfireSetCommandChannel(&dctx, commchann); + int securechann = defaultSecureChannel; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, &securechann); + if (res) { + CLIParserFree(ctx); + return res; + } + SetAPDULogging(APDULogging); + CLIParserFree(ctx); - int res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); + if (verbose) + DesfirePrintContext(&dctx); + + res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); DropField(); return PM3_ESOFT; } - res = DesfireAuthenticate(&dctx, authchann); + res = DesfireAuthenticate(&dctx, securechann); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res); DropField(); diff --git a/client/src/cmdhfmfdes.h b/client/src/cmdhfmfdes.h index eb4dd77e0..60ef9c35f 100644 --- a/client/src/cmdhfmfdes.h +++ b/client/src/cmdhfmfdes.h @@ -1,5 +1,6 @@ //----------------------------------------------------------------------------- -// Iceman, 2014 +// Copyright (C) Iceman, 2014 +// Copyright (C) 2021 Merlok // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 6ec606227..43c0ae3bf 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -1,5 +1,6 @@ /*- * Copyright (C) 2010, Romain Tartiere. + * Copyright (C) 2021 Merlok * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the diff --git a/client/src/mifare/desfire_crypto.h b/client/src/mifare/desfire_crypto.h index 71d17aea7..281b33978 100644 --- a/client/src/mifare/desfire_crypto.h +++ b/client/src/mifare/desfire_crypto.h @@ -1,4 +1,24 @@ -#ifndef __DESFIRE_CRYPTO_H +/*- + * Copyright (C) 2010, Romain Tartiere. + * Copyright (C) 2021 Merlok + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see + * + * $Id$ + */ + + #ifndef __DESFIRE_CRYPTO_H #define __DESFIRE_CRYPTO_H #include "common.h" @@ -7,6 +27,7 @@ #define MAX_CRYPTO_BLOCK_SIZE 16 +#define DESFIRE_MAX_KEY_SIZE 24 /* Mifare DESFire EV1 Application crypto operations */ #define APPLICATION_CRYPTO_DES 0x00 #define APPLICATION_CRYPTO_3K3DES 0x40 diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 18aa09265..f4bf93d0a 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -9,7 +9,7 @@ //----------------------------------------------------------------------------- // High frequency Desfire core functions //----------------------------------------------------------------------------- -// Info from here and many other soursec from the internet +// Info from here and many other sources from the public internet sites // https://github.com/revk/DESFireAES // https://github.com/step21/desfire_rfid // https://github.com/patsys/desfire-python/blob/master/Desfire/DESFire.py @@ -163,8 +163,8 @@ void DesfireClearContext(DesfireContext *ctx) { ctx->keyType = T_DES; memset(ctx->key, 0, sizeof(ctx->key)); - ctx->authChannel = DACNone; - ctx->cmdChannel = DCCNative; + ctx->secureChannel = DACNone; + ctx->cmdSet = DCCNative; ctx->commMode = DCMNone; ctx->kdfAlgo = 0; @@ -175,7 +175,7 @@ void DesfireClearContext(DesfireContext *ctx) { } void DesfireClearSession(DesfireContext *ctx) { - ctx->authChannel = DACNone; // here none - not authenticared + ctx->secureChannel = DACNone; // here none - not authenticared memset(ctx->sessionKeyMAC, 0, sizeof(ctx->sessionKeyMAC)); memset(ctx->sessionKeyEnc, 0, sizeof(ctx->sessionKeyEnc)); @@ -185,6 +185,11 @@ void DesfireClearSession(DesfireContext *ctx) { memset(ctx->TI, 0, sizeof(ctx->TI)); } +void DesfirePrintContext(DesfireContext *ctx) { + //PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), algores)); + PrintAndLogEx(INFO, "Key num: %d Key type: %d Key[%d]: %s", ctx->keyNum, ctx->keyType, key_size(ctx->keyType), sprint_hex(ctx->key, key_size(ctx->keyType))); +} + void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key) { DesfireClearContext(ctx); @@ -193,8 +198,19 @@ void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO memcpy(ctx->key, key, desfire_get_key_length(keyType)); } -void DesfireSetCommandChannel(DesfireContext *ctx, DesfireCommandChannel cmdChannel) { - ctx->cmdChannel = cmdChannel; +void DesfireSetCommandSet(DesfireContext *ctx, DesfireCommandSet cmdSet) { + ctx->cmdSet = cmdSet; +} + +void DesfireSetCommMode(DesfireContext *ctx, DesfireCommunicationMode commMode) { + ctx->commMode = commMode; +} + +void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo, uint8_t *kdfInput, uint8_t kdfInputLen) { + ctx->kdfAlgo = kdfAlgo; + ctx->kdfInputLen = kdfInputLen; + if (kdfInputLen) + memcpy(ctx->kdfInput, kdfInput, kdfInputLen); } static int DESFIRESendApdu(bool activate_field, sAPDU apdu, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint16_t *sw) { @@ -342,7 +358,7 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { int res = PM3_SUCCESS; - switch(ctx->cmdChannel) { + switch(ctx->cmdSet) { case DCCNative: res = DesfireExchangeNative(activate_field, ctx, cmd, data, datalen, respcode, resp, resplen, enable_chaining, splitbysize); break; @@ -397,17 +413,17 @@ int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uin } bool DesfireIsAuthenticated(DesfireContext *dctx) { - return dctx->authChannel != DACNone; + return dctx->secureChannel != DACNone; } -int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel) { +int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel) { // 3 different way to authenticate AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32) // 4 different crypto arg1 DES, 3DES, 3K3DES, AES // 3 different communication modes, PLAIN,MAC,CRYPTO DesfireClearSession(dctx); - if (authChannel == DACNone) + if (secureChannel == DACNone) return PM3_SUCCESS; mbedtls_aes_context ctx; @@ -456,8 +472,8 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel) { } uint8_t subcommand = MFDES_AUTHENTICATE; - dctx->authChannel = authChannel; - if (dctx->authChannel == DACEV1) { + dctx->secureChannel = secureChannel; + if (dctx->secureChannel == DACEV1) { if (dctx->keyType == T_AES) subcommand = MFDES_AUTHENTICATE_AES; else @@ -522,7 +538,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel) { uint8_t encRndA[16] = {0x00}; // - Encrypt our response - if (dctx->authChannel == DACd40) { + if (dctx->secureChannel == DACd40) { des_decrypt(encRndA, RndA, key->data); memcpy(both, encRndA, rndlen); @@ -532,7 +548,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel) { des_decrypt(encRndB, rotRndB, key->data); memcpy(both + rndlen, encRndB, rndlen); - } else if (dctx->authChannel == DACEV1 && dctx->keyType != T_AES) { + } else if (dctx->secureChannel == DACEV1 && dctx->keyType != T_AES) { if (dctx->keyType == T_3DES) { uint8_t tmp[16] = {0x00}; memcpy(tmp, RndA, rndlen); @@ -558,7 +574,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel) { PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, 32)); } } - } else if (dctx->authChannel == DACEV1 && dctx->keyType == T_AES) { + } else if (dctx->secureChannel == DACEV1 && dctx->keyType == T_AES) { uint8_t tmp[32] = {0x00}; memcpy(tmp, RndA, rndlen); memcpy(tmp + rndlen, rotRndB, rndlen); @@ -637,7 +653,7 @@ PrintAndLogEx(INFO, "Generated_RndA : %s", sprint_hex(encRndA, rndlen)); memcpy(&dctx->sessionKeyEnc[8], dctx->sessionKeyEnc, 8); } - if (dctx->authChannel == DACEV1) { + if (dctx->secureChannel == DACEV1) { cmac_generate_subkeys(&sesskey, MCD_RECEIVE); //key->cmac_sk1 and key->cmac_sk2 //memcpy(dctx->sessionKeyEnc, sesskey.data, desfire_get_key_length(dctx->keyType)); diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index a0b31babb..079c0efe6 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -28,13 +28,13 @@ typedef enum { DACd40, DACEV1, DACEV2 -} DesfireAuthChannel; +} DesfireSecureChannel; typedef enum { DCCNative, DCCNativeISO, DCCISO -} DesfireCommandChannel; +} DesfireCommandSet; typedef enum { DCMNone, @@ -54,9 +54,9 @@ typedef struct DesfireContextS { uint8_t kdfInputLen; uint8_t kdfInput[31]; - DesfireAuthChannel authChannel; // none/d40/ev1/ev2 - DesfireCommandChannel cmdChannel; // native/nativeiso/iso - DesfireCommunicationMode commMode; // plain/mac/enc + DesfireSecureChannel secureChannel; // none/d40/ev1/ev2 + DesfireCommandSet cmdSet; // native/nativeiso/iso + DesfireCommunicationMode commMode; // plain/mac/enc uint8_t sessionKeyMAC[DESF_MAX_KEY_LEN]; uint8_t sessionKeyEnc[DESF_MAX_KEY_LEN]; // look at mifare4.h - mf4Session_t @@ -68,9 +68,12 @@ typedef struct DesfireContextS { } DesfireContext; void DesfireClearContext(DesfireContext *ctx); +void DesfirePrintContext(DesfireContext *ctx); void DesfireClearSession(DesfireContext *ctx); void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key); -void DesfireSetCommandChannel(DesfireContext *ctx, DesfireCommandChannel cmdChannel); +void DesfireSetCommandSet(DesfireContext *ctx, DesfireCommandSet cmdSet); +void DesfireSetCommMode(DesfireContext *ctx, DesfireCommunicationMode commMode); +void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo,uint8_t *kdfInput, uint8_t kdfInputLen); const char *DesfireGetErrorString(int res, uint16_t *sw); uint32_t DesfireAIDByteToUint(uint8_t *data); @@ -82,7 +85,7 @@ int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uin int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2); int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2); -int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel); +int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel); bool DesfireIsAuthenticated(DesfireContext *dctx); int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); From 3cd109f475a2a1f6bc1260ac6e9ab397e399752c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ya=C4=9F=C4=B1ztegin=20Ero=C4=9Flu?= Date: Sat, 3 Jul 2021 20:46:20 +0300 Subject: [PATCH 157/309] add macports instructions, experimental as always --- ...OS-X-MacPorts-Installation-Instructions.md | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md diff --git a/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md b/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md new file mode 100644 index 000000000..d2917d260 --- /dev/null +++ b/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md @@ -0,0 +1,72 @@ +# MacPorts (Mac OS X), developer installation, ***experimental*** + +

These insturctions are not tested on Apple Silicon!

+ +## Prerequisites + +These instructions will show how to setup the environment on OSX to the point where you'll be able to clone and compile the repo by yourself, as on Linux, Windows, etc. + +1. Have MacPorts installed. Visit https://www.macports.org/ for more information. + + * MacPorts may require a bit more setup. Such as setting up new include environments like: + + ```bash + export C_INCLUDE_PATH="/opt/local/include" + export CPLUS_INCLUDE_PATH="/opt/local/include" + export LIBRARY_PATH="/opt/local/lib" + export LDFLAGS="-L/opt/local/lib" + export CFLAGS="-I/opt/local/include" + export CPPFLAGS="-isystem/opt/local/include -I/opt/local/include" + ``` + + other than just modifying PATH variable to `/opt/local/bin:/opt/local/sbin:/usr/local/bin:/usr/local/sbin:$PATH`. + +2. Install dependencies: + + ``` + sudo port install readline qt5 qt5-qtbase pkgconfig arm-none-eabi-gcc arm-none-eabi-binutils lua52 + ``` + +3. Clamp Python version for pkg-config + + MacPorts doesn't handle Python version defaults when it comes to pkg-config. So even if you have done: + + ``` + sudo port install python39 cython39 + + sudo port select --set python python39 # this also makes calls to "python" operate on python3.9 + sudo port select --set python3 python39 + sudo port select --set cython cython39 + ``` + + This won't set a default python3.pc (and python3-embed.pc) under the MacPorts pkgconfig includes folder. + + To fix that, follow these steps: + + ``` + cd /opt/local/lib/pkgconfig + sudo ln -svf python3.pc python-3.9.pc + sudo ln -svf python3-embed.pc python-3.9-embed.pc + ``` + +4. (optional) Install makefile dependencies: + + ``` + sudo port install recode + sudo port install astyle + ``` + + +## Compile and use the project + +To use the compiled client, the only difference is that the Proxmark3 port is `/dev/tty.usbmodemiceman1`, so commands become: + +```sh +proxmark3 /dev/ttyACM0 => proxmark3 /dev/tty.usbmodemiceman1 +``` + +Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md). + +To flash on OS X, better to enter the bootloader mode manually, else you may experience errors. +With your Proxmark3 unplugged from your machine, press and hold the button on your Proxmark3 as you plug it into a USB port. You can release the button, two of the four LEDs should stay on. You're in bootloader mode, ready for the next step. In case the two LEDs don't stay on when you're releasing the button, you've an old bootloader, start over and keep the button pressed during the whole flashing procedure. +From there, you can follow the original compilation instructions. \ No newline at end of file From 668936845e45b303fb0b9af0435938ed3b56aaf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ya=C4=9F=C4=B1ztegin=20Ero=C4=9Flu?= Date: Sat, 3 Jul 2021 20:48:04 +0300 Subject: [PATCH 158/309] fix typo --- .../Mac-OS-X-MacPorts-Installation-Instructions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md b/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md index d2917d260..513134273 100644 --- a/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md @@ -39,7 +39,7 @@ These instructions will show how to setup the environment on OSX to the point wh sudo port select --set cython cython39 ``` - This won't set a default python3.pc (and python3-embed.pc) under the MacPorts pkgconfig includes folder. + This won't set a default python3.pc (and python3-embed.pc) under the MacPorts pkgconfig includes folder. To fix that, follow these steps: From 7fd5070c4207c32a5a252dccc69dec9ba0df086f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ya=C4=9F=C4=B1ztegin=20Ero=C4=9Flu?= Date: Sat, 3 Jul 2021 20:50:13 +0300 Subject: [PATCH 159/309] lets make sure BREW_PREFIX is actually empty --- Makefile.defs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.defs b/Makefile.defs index 5cce62f1d..5f4c65c68 100644 --- a/Makefile.defs +++ b/Makefile.defs @@ -60,7 +60,7 @@ endif ifeq ($(USE_BREW),1) BREW_PREFIX = $(shell brew --prefix 2>/dev/null) - ifeq ($(BREW_PREFIX),) + ifeq ($(strip $(BREW_PREFIX)),) MACPORTS_PREFIX = /opt/local endif endif From 0f965d5c659861b253b05ec6297d0328c3c06b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ya=C4=9F=C4=B1ztegin=20Ero=C4=9Flu?= Date: Sat, 3 Jul 2021 21:41:43 +0300 Subject: [PATCH 160/309] update readme to link macports doc --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d5a7ea055..cc8fc9772 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ ||[Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md)|[More cheat sheets](https://github.com/RfidResearchGroup/proxmark3/wiki/More-cheat-sheets)| ||**[Troubleshooting](/doc/md/Installation_Instructions/Troubleshooting.md)**|[Complete client command set](/doc/commands.md)| ||**[JTAG](/doc/jtag_notes.md)**|[T5577 Introduction Guide](/doc/T5577_Guide.md)| +||**[MacPorts (Mac OS X, experimental)](/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md)** | ## Notes / helpful documents @@ -135,7 +136,7 @@ This repo compiles nicely on - Windows/MinGW environment - Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, NetHunter, Arch Linux, Fedora, Debian, Raspbian - Android / Termux - - Mac OS X / Homebrew / Apple Silicon M1 + - Mac OS X / Homebrew (or MacPorts, experimental) / Apple Silicon M1 - Docker container - [ RRG / Iceman repo based ubuntu 18.04 container ](https://hub.docker.com/r/secopsconsult/proxmark3) - [ Iceman fork based container v1.7 ](https://hub.docker.com/r/iceman1001/proxmark3/) From 2b176c53cc22181244045c093dd023c20d24c3a0 Mon Sep 17 00:00:00 2001 From: Pat Cunningham Date: Sat, 3 Jul 2021 19:35:28 -0700 Subject: [PATCH 161/309] handel incorrect picopass config found on unpersonalized cards and AA1s grater than 250 blocks --- client/src/cmdhficlass.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 9d95834ca..0facfa41f 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -1653,6 +1653,9 @@ static int CmdHFiClassDump(const char *Cmd) { app_limit1 = card_app2_limit[type]; app_limit2 = 0; + } else if (hdr->conf.app_limit >= hdr->conf.mem_config) { + PrintAndLogEx(WARNING, "AA1 config is >= card size, using card size as AA1 limit"); + app_limit1 = card_app2_limit[type]; } else { app_limit1 = hdr->conf.app_limit; app_limit2 = card_app2_limit[type]; @@ -1674,7 +1677,12 @@ static int CmdHFiClassDump(const char *Cmd) { PrintAndLogEx(FAILED, "Run command with keys"); return PM3_ESOFT; } - PrintAndLogEx(INFO, "Card has atleast 2 application areas. AA1 limit %u (0x%02X) AA2 limit %u (0x%02X)", app_limit1, app_limit1, app_limit2, app_limit2); + + if (app_limit2 != 0) { + PrintAndLogEx(INFO, "Card has at least 2 application areas. AA1 limit %u (0x%02X) AA2 limit %u (0x%02X)", app_limit1, app_limit1, app_limit2, app_limit2); + } else { + PrintAndLogEx(INFO, "Card has 1 application area. AA1 limit %u (0x%02X)", app_limit1, app_limit1); + } } iclass_dump_req_t payload = { @@ -1750,7 +1758,7 @@ static int CmdHFiClassDump(const char *Cmd) { // AIA data memcpy(tag_data + (8 * 5), tempbuf + (8 * 5), 8); // AA1 data - memcpy(tag_data + (8 * 6), tempbuf + (8 * 6), (blocks_read * 8)); + memcpy(tag_data + (8 * 6), tempbuf + (8 * 6), ((blocks_read - 6) * 8)); } uint16_t bytes_got = (app_limit1 + 1) * 8; @@ -1758,7 +1766,7 @@ static int CmdHFiClassDump(const char *Cmd) { // try AA2 Kc, Credit bool aa2_success = false; - if (have_credit_key && pagemap != 0x01) { + if (have_credit_key && pagemap != PICOPASS_NON_SECURE_PAGEMODE && app_limit2 != 0) { // AA2 authenticate credit key memcpy(payload.req.key, credit_key, 8); From fe5f9ec9d59f3e6cb5e363a598892f17144e5485 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 4 Jul 2021 11:21:31 +0300 Subject: [PATCH 162/309] native channel works --- client/src/mifare/desfirecore.c | 109 +++++++++++++++++++++++++++++++- 1 file changed, 108 insertions(+), 1 deletion(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index f4bf93d0a..8220a77b8 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -272,11 +272,118 @@ static int DESFIRESendApdu(bool activate_field, sAPDU apdu, uint8_t *result, uin return PM3_SUCCESS; } -static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { +static int DESFIRESendRaw(bool activate_field, uint8_t *data, size_t datalen, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint8_t *respcode) { + *result_len = 0; + if (respcode) *respcode = 0xff; + if (activate_field) { + DropField(); + msleep(50); + } + + if (GetAPDULogging()) + PrintAndLogEx(SUCCESS, "raw>> %s", sprint_hex(data, datalen)); + + int res = ExchangeRAW14a(data, datalen, activate_field, true, result, max_result_len, (int *)result_len, true); + if (res != PM3_SUCCESS) { + return res; + } + + if (GetAPDULogging()) + PrintAndLogEx(SUCCESS, "raw<< %s", sprint_hex(result, *result_len)); + + if (*result_len < 1) { + return PM3_SUCCESS; + } + + *result_len -= 1 + 2; + uint8_t rcode = result[0]; + if (respcode) *respcode = rcode; + memmove(&result[0], &result[1], *result_len); + + if (rcode != MFDES_S_OPERATION_OK && + rcode != MFDES_S_SIGNATURE && + rcode != MFDES_S_ADDITIONAL_FRAME && + rcode != MFDES_S_NO_CHANGES) { + if (GetAPDULogging()) + PrintAndLogEx(ERR, "Command (%02x) ERROR: 0x%02x", data[0], rcode); + return PM3_EAPDU_FAIL; + } return PM3_SUCCESS; } +static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { + if (resplen) + *resplen = 0; + if (respcode) + *respcode = 0xff; + + uint8_t buf[255 * 5] = {0x00}; + uint32_t buflen = 0; + uint32_t pos = 0; + uint32_t i = 1; + + uint8_t rcode = 0xff; + uint8_t cdata[255] = {0}; + uint32_t cdatalen = 0; + cdata[0] = cmd; + memcpy(&cdata[1], data, datalen); + cdatalen = datalen + 1; + + int res = DESFIRESendRaw(activate_field, cdata, cdatalen, buf, sizeof(buf), &buflen, &rcode); + if (res != PM3_SUCCESS) { + uint16_t ssw = DESFIRE_GET_ISO_STATUS(rcode); + PrintAndLogEx(DEBUG, "error DESFIRESendRaw %s", DesfireGetErrorString(res, &ssw)); + return res; + } + + if (resp) + memcpy(resp, buf, buflen); + if (respcode != NULL) + *respcode = rcode; + + pos += buflen; + if (!enable_chaining) { + if (rcode == MFDES_S_OPERATION_OK || + rcode == MFDES_ADDITIONAL_FRAME) { + if (resplen) + *resplen = pos; + } + return PM3_SUCCESS; + } + + while (rcode == MFDES_ADDITIONAL_FRAME) { + cdata[0] = MFDES_ADDITIONAL_FRAME; //0xAF + + res = DESFIRESendRaw(false, cdata, 1, buf, sizeof(buf), &buflen, &rcode); + if (res != PM3_SUCCESS) { + uint16_t ssw = DESFIRE_GET_ISO_STATUS(rcode); + PrintAndLogEx(DEBUG, "error DESFIRESendRaw %s", DesfireGetErrorString(res, &ssw)); + return res; + } + + if (respcode != NULL) + *respcode = rcode; + + if (resp != NULL) { + if (splitbysize) { + memcpy(&resp[i * splitbysize], buf, buflen); + i += 1; + } else { + memcpy(&resp[pos], buf, buflen); + } + } + pos += buflen; + + if (rcode != MFDES_ADDITIONAL_FRAME) break; + } + + if (resplen) + *resplen = (splitbysize) ? i : pos; + + return PM3_SUCCESS; +} + static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { if (resplen) *resplen = 0; From 2abd930ef7be71630e7f80840efd36789b8439fc Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 4 Jul 2021 12:20:09 +0300 Subject: [PATCH 163/309] simplify cliparser optinlist. added `mfdes default` --- client/deps/cliparser/cliparser.c | 14 ++-- client/deps/cliparser/cliparser.h | 5 +- client/src/cmdhfmfdes.c | 108 ++++++++++++++++++------------ client/src/mifare/desfirecore.c | 43 +++++++++++- client/src/mifare/desfirecore.h | 7 ++ 5 files changed, 128 insertions(+), 49 deletions(-) diff --git a/client/deps/cliparser/cliparser.c b/client/deps/cliparser/cliparser.c index 265c97103..ad89856cd 100644 --- a/client/deps/cliparser/cliparser.c +++ b/client/deps/cliparser/cliparser.c @@ -298,7 +298,7 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int return 0; } -int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array, size_t option_array_len, int *value) { +int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array, int *value) { char data[200] = {0}; int datalen = 0; int res = CLIParamStrToBuf(argstr, (uint8_t *)data, sizeof(data), &datalen); @@ -313,7 +313,10 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array int val = -1; int cntr = 0; - for (int i = 0; i < option_array_len; i++) { + for (int i = 0; i < CLI_MAX_OPTLIST_LEN; i++) { + // end of array + if (option_array[i].text == NULL) + break; // exact match if (strcmp(option_array[i].text, data) == 0) { *value = option_array[i].code; @@ -340,12 +343,15 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array return 0; } -const char *CLIGetOptionListStr(const CLIParserOption *option_array, size_t option_array_len, int value) { +const char *CLIGetOptionListStr(const CLIParserOption *option_array, int value) { static const char *errmsg = "n/a"; - for (int i = 0; i < option_array_len; i++) + for (int i = 0; i < CLI_MAX_OPTLIST_LEN; i++) { + if (option_array[i].text == NULL) + break; if (option_array[i].code == value) return option_array[i].text; + } return errmsg; } diff --git a/client/deps/cliparser/cliparser.h b/client/deps/cliparser/cliparser.h index f4f9b7dcf..d75f43dff 100644 --- a/client/deps/cliparser/cliparser.h +++ b/client/deps/cliparser/cliparser.h @@ -62,6 +62,7 @@ typedef struct { char buf[1024 + 60]; } CLIParserContext; +#define CLI_MAX_OPTLIST_LEN 50 typedef struct { int code; const char *text; @@ -78,8 +79,8 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int int CLIParamBinToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); // names in the CLIParserOption array must be in the lowercase format -int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array, size_t option_array_len, int *value); -const char *CLIGetOptionListStr(const CLIParserOption *option_array, size_t option_array_len, int value); +int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array, int *value); +const char *CLIGetOptionListStr(const CLIParserOption *option_array, int value); uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def); int arg_get_u64_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint64_t def, uint64_t *out, uint8_t nlen, bool optional); diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index c29f74cc6..255283211 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5030,17 +5030,10 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct keynum = arg_get_int_def(ctx, keynoid, keynum); } - const CLIParserOption algo_opts[] = { - {T_DES, "des"}, - {T_3DES, "2tdea"}, - {T_3K3DES, "3tdea"}, - {T_AES, "aes"}, - }; - if (algoid) { - if (CLIGetOptionList(arg_get_str(ctx, algoid), algo_opts, ARRAY_LENGTH(algo_opts), &algores)) + if (CLIGetOptionList(arg_get_str(ctx, algoid), DesfireAlgoOpts, &algores)) return PM3_ESOFT; - PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), algores)); + PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(DesfireAlgoOpts, algores)); } if (keyid) { @@ -5049,7 +5042,7 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct if (CLIParamHexToBuf(arg_get_str(ctx, keyid), keydata, sizeof(keydata), &keylen)) return PM3_ESOFT; if (keylen && keylen != key_size(algores)) { - PrintAndLogEx(ERR, "%s key must have %d bytes length instead of %d.", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), algores), key_size(algores), keylen); + PrintAndLogEx(ERR, "%s key must have %d bytes length instead of %d.", CLIGetOptionListStr(DesfireAlgoOpts, algores), key_size(algores), keylen); return PM3_EINVARG; } if (keylen) @@ -5057,15 +5050,9 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct } if (kdfid) { - const CLIParserOption kdf_opts[] = { - {MFDES_KDF_ALGO_NONE, "none"}, - {MFDES_KDF_ALGO_AN10922, "an10922"}, - {MFDES_KDF_ALGO_GALLAGHER, "gallagher"}, - }; - - if (CLIGetOptionList(arg_get_str(ctx, kdfid), kdf_opts, ARRAY_LENGTH(kdf_opts), &kdfAlgo)) + if (CLIGetOptionList(arg_get_str(ctx, kdfid), DesfireKDFAlgoOpts, &kdfAlgo)) return PM3_ESOFT; - PrintAndLogEx(INFO, "kdf funct: %s", CLIGetOptionListStr(kdf_opts, ARRAY_LENGTH(kdf_opts), kdfAlgo)); + PrintAndLogEx(INFO, "kdf funct: %s", CLIGetOptionListStr(DesfireKDFAlgoOpts, kdfAlgo)); } @@ -5081,39 +5068,21 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct } if (cmodeid) { - const CLIParserOption cmode_opts[] = { - {DCMPlain, "plain"}, - {DCMMACed, "mac"}, - {DCMEncrypted, "encrypt"}, - }; - - if (CLIGetOptionList(arg_get_str(ctx, cmodeid), cmode_opts, ARRAY_LENGTH(cmode_opts), &commmode)) + if (CLIGetOptionList(arg_get_str(ctx, cmodeid), DesfireCommunicationModeOpts, &commmode)) return PM3_ESOFT; - PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(cmode_opts, ARRAY_LENGTH(cmode_opts), commmode)); + PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(DesfireCommunicationModeOpts, commmode)); } if (ccsetid) { - const CLIParserOption commc_opts[] = { - {DCCNative, "native"}, - {DCCNativeISO, "niso"}, - {DCCISO, "iso"}, - }; - - if (CLIGetOptionList(arg_get_str(ctx, ccsetid), commc_opts, ARRAY_LENGTH(commc_opts), &commset)) + if (CLIGetOptionList(arg_get_str(ctx, ccsetid), DesfireCommandSetOpts, &commset)) return PM3_ESOFT; - PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(commc_opts, ARRAY_LENGTH(commc_opts), commset)); + PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(DesfireCommandSetOpts, commset)); } if (schannid) { - const CLIParserOption authc_opts[] = { - {DACd40, "d40"}, - {DACEV1, "ev1"}, - {DACEV2, "ev2"}, - }; - - if (CLIGetOptionList(arg_get_str(ctx, schannid), authc_opts, ARRAY_LENGTH(authc_opts), &secchann)) + if (CLIGetOptionList(arg_get_str(ctx, schannid), DesfireSecureChannelOpts, &secchann)) return PM3_ESOFT; - PrintAndLogEx(INFO, "auth channel: %s", CLIGetOptionListStr(authc_opts, ARRAY_LENGTH(authc_opts), secchann)); + PrintAndLogEx(INFO, "auth channel: %s", CLIGetOptionListStr(DesfireSecureChannelOpts, secchann)); } DesfireSetKey(dctx, keynum, algores, key); @@ -5126,6 +5095,60 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct return PM3_SUCCESS; } +static int CmdHF14ADesDefault(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes default", + "Get Application IDs, ISO IDs and DF names from card. Master key needs to be provided.", + "hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup"); + + void *argtable[] = { + arg_param_begin, + arg_int0("n", "keyno", "", "Key number"), + arg_str0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), + arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None, AN10922, Gallagher"), + 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_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, &securechann); + if (res) { + CLIParserFree(ctx); + return res; + } + + CLIParserFree(ctx); + + defaultKeyNum = dctx.keyNum; + defaultAlgoId = dctx.keyType; + memcpy(defaultKey, dctx.key, DESFIRE_MAX_KEY_SIZE); + defaultKdfAlgo = dctx.kdfAlgo; + defaultKdfInputLen = dctx.kdfInputLen; + memcpy(defaultKdfInput, dctx.kdfInput, sizeof(dctx.kdfInput)); + defaultSecureChannel = securechann; + defaultCommSet = dctx.cmdSet; + defaultCommMode = dctx.commMode; + + PrintAndLogEx(INFO, "-----------" _CYAN_("Default parameters") "---------------------------------"); + + PrintAndLogEx(INFO, "Key Num : %d", defaultKeyNum); + PrintAndLogEx(INFO, "Algo : %s", CLIGetOptionListStr(DesfireAlgoOpts, defaultAlgoId)); + PrintAndLogEx(INFO, "Key : %s", sprint_hex(defaultKey, key_size(defaultAlgoId))); + PrintAndLogEx(INFO, "KDF algo : %s", CLIGetOptionListStr(DesfireKDFAlgoOpts, defaultKdfAlgo)); + PrintAndLogEx(INFO, "KDF input : [%d] %s", defaultKdfInputLen, sprint_hex(defaultKdfInput, defaultKdfInputLen)); + PrintAndLogEx(INFO, "Secure chan : %s", CLIGetOptionListStr(DesfireSecureChannelOpts, defaultSecureChannel)); + PrintAndLogEx(INFO, "Command set : %s", CLIGetOptionListStr(DesfireCommandSetOpts, defaultCommSet)); + PrintAndLogEx(INFO, "Comm mode : %s", CLIGetOptionListStr(DesfireCommunicationModeOpts, defaultCommMode)); + + return PM3_SUCCESS; +} + static int CmdHF14ADesGetAIDs(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes getaids", @@ -5294,6 +5317,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"-----------", CmdHelp, IfPm3Iso14443a, "---------------------- " _CYAN_("general") " ----------------------"}, + {"default", CmdHF14ADesDefault, IfPm3Iso14443a, "Set defaults for all the commands"}, {"auth", CmdHF14ADesAuth, IfPm3Iso14443a, "Tries a MIFARE DesFire Authentication"}, {"changekey", CmdHF14ADesChangeKey, IfPm3Iso14443a, "Change Key"}, {"chk", CmdHF14aDesChk, IfPm3Iso14443a, "Check keys"}, diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 8220a77b8..bab818a39 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -29,6 +29,47 @@ #include "util_posix.h" // msleep #include "mifare/desfire_crypto.h" +const CLIParserOption DesfireAlgoOpts[] = { + {T_DES, "des"}, + {T_3DES, "2tdea"}, + {T_3K3DES, "3tdea"}, + {T_AES, "aes"}, + {0, NULL}, +}; +const size_t DesfireAlgoOptsLen = ARRAY_LENGTH(DesfireAlgoOpts); + +const CLIParserOption DesfireKDFAlgoOpts[] = { + {MFDES_KDF_ALGO_NONE, "none"}, + {MFDES_KDF_ALGO_AN10922, "an10922"}, + {MFDES_KDF_ALGO_GALLAGHER, "gallagher"}, + {0, NULL}, +}; +const size_t DesfireKDFAlgoOptsLen = ARRAY_LENGTH(DesfireKDFAlgoOpts); + +const CLIParserOption DesfireCommunicationModeOpts[] = { + {DCMPlain, "plain"}, + {DCMMACed, "mac"}, + {DCMEncrypted, "encrypt"}, + {0, NULL}, +}; +const size_t DesfireCommunicationModeOptsLen = ARRAY_LENGTH(DesfireCommunicationModeOpts); + +const CLIParserOption DesfireCommandSetOpts[] = { + {DCCNative, "native"}, + {DCCNativeISO, "niso"}, + {DCCISO, "iso"}, + {0, NULL}, +}; +const size_t DesfireCommandSetOptsLen = ARRAY_LENGTH(DesfireCommandSetOpts); + +const CLIParserOption DesfireSecureChannelOpts[] = { + {DACd40, "d40"}, + {DACEV1, "ev1"}, + {DACEV2, "ev2"}, + {0, NULL}, +}; +const size_t DesfireSecureChannelOptsLen = ARRAY_LENGTH(DesfireSecureChannelOpts); + static const char *getstatus(uint16_t *sw) { if (sw == NULL) return "--> sw argument error. This should never happen !"; if (((*sw >> 8) & 0xFF) == 0x91) { @@ -187,7 +228,7 @@ void DesfireClearSession(DesfireContext *ctx) { void DesfirePrintContext(DesfireContext *ctx) { //PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), algores)); - PrintAndLogEx(INFO, "Key num: %d Key type: %d Key[%d]: %s", ctx->keyNum, ctx->keyType, key_size(ctx->keyType), sprint_hex(ctx->key, key_size(ctx->keyType))); + PrintAndLogEx(INFO, "Key num: %d Key algo: %s Key[%d]: %s", ctx->keyNum, CLIGetOptionListStr(DesfireAlgoOpts, ctx->keyType), key_size(ctx->keyType), sprint_hex(ctx->key, key_size(ctx->keyType))); } void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key) { diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 079c0efe6..d03e8e908 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -14,6 +14,7 @@ #define __DESFIRECORE_H #include "common.h" +#include "cliparser.h" #include "mifare/desfire_crypto.h" #include "mifare/mifare4.h" @@ -67,6 +68,12 @@ typedef struct DesfireContextS { uint8_t TI[4]; // for AES } DesfireContext; +extern const CLIParserOption DesfireAlgoOpts[]; +extern const CLIParserOption DesfireKDFAlgoOpts[]; +extern const CLIParserOption DesfireCommunicationModeOpts[]; +extern const CLIParserOption DesfireCommandSetOpts[]; +extern const CLIParserOption DesfireSecureChannelOpts[]; + void DesfireClearContext(DesfireContext *ctx); void DesfirePrintContext(DesfireContext *ctx); void DesfireClearSession(DesfireContext *ctx); From 5271cb96c3099f3270e90a605c7f137c855e8cfe Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 4 Jul 2021 12:25:34 +0300 Subject: [PATCH 164/309] add commant, remove debug --- client/deps/cliparser/cliparser.h | 1 + client/src/cmdhfmfdes.c | 6 ------ 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/client/deps/cliparser/cliparser.h b/client/deps/cliparser/cliparser.h index d75f43dff..f50fec2ee 100644 --- a/client/deps/cliparser/cliparser.h +++ b/client/deps/cliparser/cliparser.h @@ -63,6 +63,7 @@ typedef struct { } CLIParserContext; #define CLI_MAX_OPTLIST_LEN 50 +// option list needs to have NULL at the last record int the field `text` typedef struct { int code; const char *text; diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 255283211..1a3c82166 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5033,7 +5033,6 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct if (algoid) { if (CLIGetOptionList(arg_get_str(ctx, algoid), DesfireAlgoOpts, &algores)) return PM3_ESOFT; - PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(DesfireAlgoOpts, algores)); } if (keyid) { @@ -5052,8 +5051,6 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct if (kdfid) { if (CLIGetOptionList(arg_get_str(ctx, kdfid), DesfireKDFAlgoOpts, &kdfAlgo)) return PM3_ESOFT; - PrintAndLogEx(INFO, "kdf funct: %s", CLIGetOptionListStr(DesfireKDFAlgoOpts, kdfAlgo)); - } if (kdfiid) { @@ -5070,19 +5067,16 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct if (cmodeid) { if (CLIGetOptionList(arg_get_str(ctx, cmodeid), DesfireCommunicationModeOpts, &commmode)) return PM3_ESOFT; - PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(DesfireCommunicationModeOpts, commmode)); } if (ccsetid) { if (CLIGetOptionList(arg_get_str(ctx, ccsetid), DesfireCommandSetOpts, &commset)) return PM3_ESOFT; - PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(DesfireCommandSetOpts, commset)); } if (schannid) { if (CLIGetOptionList(arg_get_str(ctx, schannid), DesfireSecureChannelOpts, &secchann)) return PM3_ESOFT; - PrintAndLogEx(INFO, "auth channel: %s", CLIGetOptionListStr(DesfireSecureChannelOpts, secchann)); } DesfireSetKey(dctx, keynum, algores, key); From 6124b49c9913e9b63ce451147553c1f1b4dd93c7 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 4 Jul 2021 12:47:09 +0300 Subject: [PATCH 165/309] DesfirePrintContext prints session state --- client/src/cmdhfmfdes.c | 2 +- client/src/mifare/desfire_crypto.c | 14 +++++++++----- client/src/mifare/desfire_crypto.h | 1 + client/src/mifare/desfirecore.c | 28 +++++++++++++++++++++++++--- 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 1a3c82166..c7a195db5 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5195,7 +5195,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { DropField(); return PM3_ESOFT; } - + if (DesfireIsAuthenticated(&dctx)) { if (verbose) PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated") , res); diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 43c0ae3bf..079e7c897 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -390,12 +390,9 @@ void mifare_kdf_an10922(const desfirekey_t key, const uint8_t *data, size_t len) free(buffer); } -size_t key_block_size(const desfirekey_t key) { - if (key == NULL) { - return 0; - } +size_t desfire_get_key_block_length(enum DESFIRE_CRYPTOALGO key_type) { size_t block_size = 8; - switch (key->type) { + switch (key_type) { case T_DES: case T_3DES: case T_3K3DES: @@ -408,6 +405,13 @@ size_t key_block_size(const desfirekey_t key) { return block_size; } +size_t key_block_size(const desfirekey_t key) { + if (key == NULL) { + return 0; + } + return desfire_get_key_block_length(key->type); +} + size_t key_size(const enum DESFIRE_CRYPTOALGO algo) { switch (algo) { case T_DES: diff --git a/client/src/mifare/desfire_crypto.h b/client/src/mifare/desfire_crypto.h index 281b33978..1a1f6375c 100644 --- a/client/src/mifare/desfire_crypto.h +++ b/client/src/mifare/desfire_crypto.h @@ -82,6 +82,7 @@ enum DESFIRE_CRYPTOALGO { }; int desfire_get_key_length(enum DESFIRE_CRYPTOALGO key_type); +size_t desfire_get_key_block_length(enum DESFIRE_CRYPTOALGO key_type); enum DESFIRE_AUTH_SCHEME { AS_LEGACY, diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index bab818a39..6fead2fdb 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -227,9 +227,31 @@ void DesfireClearSession(DesfireContext *ctx) { } void DesfirePrintContext(DesfireContext *ctx) { - //PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), algores)); - PrintAndLogEx(INFO, "Key num: %d Key algo: %s Key[%d]: %s", ctx->keyNum, CLIGetOptionListStr(DesfireAlgoOpts, ctx->keyType), key_size(ctx->keyType), sprint_hex(ctx->key, key_size(ctx->keyType))); -} + PrintAndLogEx(INFO, "Key num: %d Key algo: %s Key[%d]: %s", + ctx->keyNum, + CLIGetOptionListStr(DesfireAlgoOpts, ctx->keyType), + key_size(ctx->keyType), + sprint_hex(ctx->key, + key_size(ctx->keyType))); + + if (ctx->kdfAlgo != MFDES_KDF_ALGO_NONE) + PrintAndLogEx(INFO, "KDF algo: %s KDF input[%d]: %s", CLIGetOptionListStr(DesfireKDFAlgoOpts, ctx->kdfAlgo), ctx->kdfInputLen, sprint_hex(ctx->kdfInput, ctx->kdfInputLen)); + + PrintAndLogEx(INFO, "Secure channel: %s Command set: %s Communication mode: %s", + CLIGetOptionListStr(DesfireSecureChannelOpts, ctx->secureChannel), + CLIGetOptionListStr(DesfireCommandSetOpts, ctx->cmdSet), + CLIGetOptionListStr(DesfireCommunicationModeOpts, ctx->commMode)); + + if (DesfireIsAuthenticated(ctx)) { + PrintAndLogEx(INFO, "Session key MAC [%d]: %s ENC: %s IV [%d]: %s", + key_size(ctx->keyType), + sprint_hex(ctx->sessionKeyMAC, key_size(ctx->keyType)), + sprint_hex(ctx->sessionKeyEnc, key_size(ctx->keyType)), + desfire_get_key_block_length(ctx->keyType), + sprint_hex(ctx->sessionKeyEnc, desfire_get_key_block_length(ctx->keyType))); + + } + } void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key) { DesfireClearContext(ctx); From 3dc7afa593a02389d6c95e838a0f8a0853c44713 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 4 Jul 2021 11:52:26 +0200 Subject: [PATCH 166/309] text --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ec140043..fea82e2b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added `pm3_online_check.py` - a script to verify and initialize a Proxmark3 RDV4 device (@iceman1001) ## [midsummer.4.13441][2021-06-25] + - Fix `hf iclass` - a crash when AA1 limit was larger than AA2 (@pcunning) - Added bruteforce function for the magic byte in `cmdlfnexwatch.c` and ability to clone with psk2 modulation (@Guilhem7, @MaximeBosca) - Changed `hw setmux` - improve user feedback for special case (@iceman1001) - Changed 'filename' - unified file name param across client (@iceman1001) From 86e1ef483e6ba58b6d56c7747d6fcc96bf10a36a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ya=C4=9F=C4=B1ztegin=20Ero=C4=9Flu?= Date: Sun, 4 Jul 2021 12:59:48 +0300 Subject: [PATCH 167/309] handle MACPORTS_PREFIX entries before make execution --- Makefile.defs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.defs b/Makefile.defs index 5f4c65c68..493c50ccd 100644 --- a/Makefile.defs +++ b/Makefile.defs @@ -61,7 +61,7 @@ endif ifeq ($(USE_BREW),1) BREW_PREFIX = $(shell brew --prefix 2>/dev/null) ifeq ($(strip $(BREW_PREFIX)),) - MACPORTS_PREFIX = /opt/local + MACPORTS_PREFIX ?= /opt/local endif endif From e07c8472cfd06bb0ee13ecd63acfe524bfad04df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ya=C4=9F=C4=B1ztegin=20Ero=C4=9Flu?= Date: Sun, 4 Jul 2021 13:00:30 +0300 Subject: [PATCH 168/309] change docs for macports --- ...ac-OS-X-MacPorts-Installation-Instructions.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md b/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md index 513134273..e402db158 100644 --- a/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md @@ -8,7 +8,13 @@ These instructions will show how to setup the environment on OSX to the point wh 1. Have MacPorts installed. Visit https://www.macports.org/ for more information. - * MacPorts may require a bit more setup. Such as setting up new include environments like: + * MacPorts may require a bit more setup. You first need to set up your PATH variable: + + ```bash + export "/opt/local/bin:/opt/local/sbin:/usr/local/bin:/usr/local/sbin:$PATH" + ``` + + Although it is optional for proxmark3 repository, you can also set include variables: ```bash export C_INCLUDE_PATH="/opt/local/include" @@ -19,8 +25,6 @@ These instructions will show how to setup the environment on OSX to the point wh export CPPFLAGS="-isystem/opt/local/include -I/opt/local/include" ``` - other than just modifying PATH variable to `/opt/local/bin:/opt/local/sbin:/usr/local/bin:/usr/local/sbin:$PATH`. - 2. Install dependencies: ``` @@ -59,11 +63,7 @@ These instructions will show how to setup the environment on OSX to the point wh ## Compile and use the project -To use the compiled client, the only difference is that the Proxmark3 port is `/dev/tty.usbmodemiceman1`, so commands become: - -```sh -proxmark3 /dev/ttyACM0 => proxmark3 /dev/tty.usbmodemiceman1 -``` +To use the compiled client, you can use `pm3` script, it is a wrapper of the proxmark3 client that handles automatic detection of your proxmark. Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md). From f76e7f8ba722dab40a049af3668bbb5ee6558123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ya=C4=9F=C4=B1ztegin=20Ero=C4=9Flu?= Date: Sun, 4 Jul 2021 13:10:00 +0300 Subject: [PATCH 169/309] add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ec140043..e0585baa7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added experimental support for macOS users utilizing MacPorts instead of Homebrew (@linuxgemini) - Added `pm3_online_check.py` - a script to verify and initialize a Proxmark3 RDV4 device (@iceman1001) ## [midsummer.4.13441][2021-06-25] From 430f82730d9764562d71ea2fa09287caaa03e0db Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 4 Jul 2021 13:38:12 +0300 Subject: [PATCH 170/309] fix DesfireAuthenticate for d40/ev1 mode --- client/src/mifare/desfirecore.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 6fead2fdb..41b168277 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -708,18 +708,18 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel uint8_t encRndA[16] = {0x00}; // - Encrypt our response - if (dctx->secureChannel == DACd40) { - des_decrypt(encRndA, RndA, key->data); - memcpy(both, encRndA, rndlen); + if ((dctx->secureChannel == DACEV1 || dctx->secureChannel == DACd40) && dctx->keyType != T_AES) { + if (dctx->keyType == T_DES) { + des_decrypt(encRndA, RndA, key->data); + memcpy(both, encRndA, rndlen); - for (uint32_t x = 0; x < rndlen; x++) { - rotRndB[x] = rotRndB[x] ^ encRndA[x]; - } + for (uint32_t x = 0; x < rndlen; x++) { + rotRndB[x] = rotRndB[x] ^ encRndA[x]; + } - des_decrypt(encRndB, rotRndB, key->data); - memcpy(both + rndlen, encRndB, rndlen); - } else if (dctx->secureChannel == DACEV1 && dctx->keyType != T_AES) { - if (dctx->keyType == T_3DES) { + des_decrypt(encRndB, rotRndB, key->data); + memcpy(both + rndlen, encRndB, rndlen); + } else if (dctx->keyType == T_3DES) { uint8_t tmp[16] = {0x00}; memcpy(tmp, RndA, rndlen); memcpy(tmp + rndlen, rotRndB, rndlen); @@ -731,7 +731,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel if (g_debugMode > 1) { PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, 16)); } - } else if (dctx->keyType == T_3K3DES) { + } else if (dctx->secureChannel == DACEV1 && dctx->keyType == T_3K3DES) { uint8_t tmp[32] = {0x00}; memcpy(tmp, RndA, rndlen); memcpy(tmp + rndlen, rotRndB, rndlen); From db87af3bf840c64c8c153d33177f217dda0972e9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 4 Jul 2021 14:00:35 +0300 Subject: [PATCH 171/309] Revert "fix DesfireAuthenticate for d40/ev1 mode" This reverts commit 430f82730d9764562d71ea2fa09287caaa03e0db. --- client/src/mifare/desfirecore.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 41b168277..6fead2fdb 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -708,18 +708,18 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel uint8_t encRndA[16] = {0x00}; // - Encrypt our response - if ((dctx->secureChannel == DACEV1 || dctx->secureChannel == DACd40) && dctx->keyType != T_AES) { - if (dctx->keyType == T_DES) { - des_decrypt(encRndA, RndA, key->data); - memcpy(both, encRndA, rndlen); + if (dctx->secureChannel == DACd40) { + des_decrypt(encRndA, RndA, key->data); + memcpy(both, encRndA, rndlen); - for (uint32_t x = 0; x < rndlen; x++) { - rotRndB[x] = rotRndB[x] ^ encRndA[x]; - } + for (uint32_t x = 0; x < rndlen; x++) { + rotRndB[x] = rotRndB[x] ^ encRndA[x]; + } - des_decrypt(encRndB, rotRndB, key->data); - memcpy(both + rndlen, encRndB, rndlen); - } else if (dctx->keyType == T_3DES) { + des_decrypt(encRndB, rotRndB, key->data); + memcpy(both + rndlen, encRndB, rndlen); + } else if (dctx->secureChannel == DACEV1 && dctx->keyType != T_AES) { + if (dctx->keyType == T_3DES) { uint8_t tmp[16] = {0x00}; memcpy(tmp, RndA, rndlen); memcpy(tmp + rndlen, rotRndB, rndlen); @@ -731,7 +731,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel if (g_debugMode > 1) { PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, 16)); } - } else if (dctx->secureChannel == DACEV1 && dctx->keyType == T_3K3DES) { + } else if (dctx->keyType == T_3K3DES) { uint8_t tmp[32] = {0x00}; memcpy(tmp, RndA, rndlen); memcpy(tmp + rndlen, rotRndB, rndlen); From 1adfad07bdc3913eaeb3c5a40366481fd08ccd7b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 4 Jul 2021 14:14:43 +0300 Subject: [PATCH 172/309] move des encrypt/decrypt to lib --- client/src/cmdhfmf.c | 7 ------- client/src/crypto/libpcrypto.c | 14 ++++++++++++++ client/src/crypto/libpcrypto.h | 3 +++ client/src/mifare/desfire_crypto.c | 12 ------------ client/src/mifare/desfire_crypto.h | 4 ++-- 5 files changed, 19 insertions(+), 21 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index ace8d2d0b..985d156db 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -24,7 +24,6 @@ #include "protocols.h" #include "util_posix.h" // msclock #include "cmdhfmfhard.h" -#include "des.h" // des ecb #include "crapto1/crapto1.h" // prng_successor #include "cmdhf14a.h" // exchange APDU #include "crypto/libpcrypto.h" @@ -5645,12 +5644,6 @@ static int CmdHf14AGen3Freeze(const char *Cmd) { return res; } -static void des_decrypt(void *out, const void *in, const void *key) { - mbedtls_des_context ctx; - mbedtls_des_setkey_dec(&ctx, key); - mbedtls_des_crypt_ecb(&ctx, in, out); -} - static int CmdHf14AMfSuperCard(const char *Cmd) { CLIParserContext *ctx; diff --git a/client/src/crypto/libpcrypto.c b/client/src/crypto/libpcrypto.c index 723753d5f..f80eedcf0 100644 --- a/client/src/crypto/libpcrypto.c +++ b/client/src/crypto/libpcrypto.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,19 @@ #include #include "util.h" #include "ui.h" + +void des_encrypt(void *out, const void *in, const void *key) { + mbedtls_des_context ctx; + mbedtls_des_setkey_enc(&ctx, key); + mbedtls_des_crypt_ecb(&ctx, in, out); +} + +void des_decrypt(void *out, const void *in, const void *key) { + mbedtls_des_context ctx; + mbedtls_des_setkey_dec(&ctx, key); + mbedtls_des_crypt_ecb(&ctx, in, out); +} + // NIST Special Publication 800-38A — Recommendation for block cipher modes of operation: methods and techniques, 2001. int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length) { uint8_t iiv[16] = {0}; diff --git a/client/src/crypto/libpcrypto.h b/client/src/crypto/libpcrypto.h index 099fd4423..b1c4b4eee 100644 --- a/client/src/crypto/libpcrypto.h +++ b/client/src/crypto/libpcrypto.h @@ -16,6 +16,9 @@ #include #include +void des_encrypt(void *out, const void *in, const void *key); +void des_decrypt(void *out, const void *in, const void *key); + int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length); diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 079e7c897..d941ae09e 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -65,18 +65,6 @@ int desfire_get_key_length(enum DESFIRE_CRYPTOALGO key_type) { /******************************************************************************/ -void des_encrypt(void *out, const void *in, const void *key) { - mbedtls_des_context ctx; - mbedtls_des_setkey_enc(&ctx, key); - mbedtls_des_crypt_ecb(&ctx, in, out); -} - -void des_decrypt(void *out, const void *in, const void *key) { - mbedtls_des_context ctx; - mbedtls_des_setkey_dec(&ctx, key); - mbedtls_des_crypt_ecb(&ctx, in, out); -} - void tdes_nxp_receive(const void *in, void *out, size_t length, const void *key, unsigned char iv[8], int keymode) { if (length % 8) return; diff --git a/client/src/mifare/desfire_crypto.h b/client/src/mifare/desfire_crypto.h index 1a1f6375c..1aa938017 100644 --- a/client/src/mifare/desfire_crypto.h +++ b/client/src/mifare/desfire_crypto.h @@ -24,6 +24,7 @@ #include "common.h" #include "mifare.h" // structs #include "crc32.h" +#include "crypto/libpcrypto.h" #define MAX_CRYPTO_BLOCK_SIZE 16 @@ -126,8 +127,7 @@ typedef unsigned long DES3_KS[48][2]; /* Triple-DES key schedule */ extern int Asmversion; /* 1 if we're linked with an asm version, 0 if C */ -void des_encrypt(void *out, const void *in, const void *key); -void des_decrypt(void *out, const void *in, const void *key); + void tdes_nxp_receive(const void *in, void *out, size_t length, const void *key, unsigned char iv[8], int keymode); void tdes_nxp_send(const void *in, void *out, size_t length, const void *key, unsigned char iv[8], int keymode); void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key); From fce8affd4881883d96cd8dbaf162efd2eb57b77f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 4 Jul 2021 15:43:57 +0300 Subject: [PATCH 173/309] fix des authentication --- client/src/crypto/libpcrypto.c | 12 ++++++++ client/src/crypto/libpcrypto.h | 2 ++ client/src/mifare/desfirecore.c | 51 ++++++++++++++++++++++++--------- 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/client/src/crypto/libpcrypto.c b/client/src/crypto/libpcrypto.c index f80eedcf0..d3df5dfda 100644 --- a/client/src/crypto/libpcrypto.c +++ b/client/src/crypto/libpcrypto.c @@ -41,6 +41,18 @@ void des_decrypt(void *out, const void *in, const void *key) { mbedtls_des_crypt_ecb(&ctx, in, out); } +void des_encrypt_cbc(void *out, const void *in, const int length, const void *key, uint8_t *iv) { + mbedtls_des_context ctx; + mbedtls_des_setkey_enc(&ctx, key); + mbedtls_des_crypt_cbc(&ctx, MBEDTLS_DES_ENCRYPT, length, iv, in, out); +} + +void des_decrypt_cbc(void *out, const void *in, const int length, const void *key, uint8_t *iv) { + mbedtls_des_context ctx; + mbedtls_des_setkey_dec(&ctx, key); + mbedtls_des_crypt_cbc(&ctx, MBEDTLS_DES_DECRYPT, length, iv, in, out); +} + // NIST Special Publication 800-38A — Recommendation for block cipher modes of operation: methods and techniques, 2001. int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length) { uint8_t iiv[16] = {0}; diff --git a/client/src/crypto/libpcrypto.h b/client/src/crypto/libpcrypto.h index b1c4b4eee..1c7c745dc 100644 --- a/client/src/crypto/libpcrypto.h +++ b/client/src/crypto/libpcrypto.h @@ -18,6 +18,8 @@ void des_encrypt(void *out, const void *in, const void *key); void des_decrypt(void *out, const void *in, const void *key); +void des_encrypt_cbc(void *out, const void *in, const int length, const void *key, uint8_t *iv); +void des_decrypt_cbc(void *out, const void *in, const int length, const void *key, uint8_t *iv); int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 6fead2fdb..118e30109 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -688,9 +688,12 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel return 5; } mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, rndlen, IV, encRndB, RndB); - } else if (dctx->keyType == T_DES) - des_decrypt(RndB, encRndB, key->data); - else if (dctx->keyType == T_3DES) + } else if (dctx->keyType == T_DES) { + if (dctx->secureChannel == DACd40) + des_decrypt(RndB, encRndB, key->data); + if (dctx->secureChannel == DACEV1) + des_decrypt_cbc(RndB, encRndB, rndlen, key->data, IV); + } else if (dctx->keyType == T_3DES) tdes_nxp_receive(encRndB, RndB, rndlen, key->data, IV, 2); else if (dctx->keyType == T_3K3DES) { tdes_nxp_receive(encRndB, RndB, rndlen, key->data, IV, 3); @@ -709,17 +712,33 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel // - Encrypt our response if (dctx->secureChannel == DACd40) { - des_decrypt(encRndA, RndA, key->data); - memcpy(both, encRndA, rndlen); + if (dctx->keyType == T_DES) { + des_decrypt(encRndA, RndA, key->data); + memcpy(both, encRndA, rndlen); - for (uint32_t x = 0; x < rndlen; x++) { - rotRndB[x] = rotRndB[x] ^ encRndA[x]; + for (uint32_t x = 0; x < rndlen; x++) { + rotRndB[x] = rotRndB[x] ^ encRndA[x]; + } + + des_decrypt(encRndB, rotRndB, key->data); + memcpy(both + rndlen, encRndB, rndlen); + } else if (dctx->keyType == T_3DES) { + //TODO } - - des_decrypt(encRndB, rotRndB, key->data); - memcpy(both + rndlen, encRndB, rndlen); } else if (dctx->secureChannel == DACEV1 && dctx->keyType != T_AES) { - if (dctx->keyType == T_3DES) { + if (dctx->keyType == T_DES) { + uint8_t tmp[16] = {0x00}; + memcpy(tmp, RndA, rndlen); + memcpy(tmp + rndlen, rotRndB, rndlen); + if (g_debugMode > 1) { + PrintAndLogEx(DEBUG, "rotRndB: %s", sprint_hex(rotRndB, rndlen)); + PrintAndLogEx(DEBUG, "Both: %s", sprint_hex(tmp, 16)); + } + des_encrypt_cbc(both, tmp, 16, key->data, IV); + if (g_debugMode > 1) { + PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, 16)); + } + } else if (dctx->keyType == T_3DES) { uint8_t tmp[16] = {0x00}; memcpy(tmp, RndA, rndlen); memcpy(tmp + rndlen, rotRndB, rndlen); @@ -790,9 +809,13 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel memcpy(dctx->sessionKeyEnc, sesskey.data, desfire_get_key_length(dctx->keyType)); PrintAndLogEx(INFO, "encRndA : %s", sprint_hex(encRndA, rndlen)); - if (dctx->keyType == T_DES) - des_decrypt(encRndA, encRndA, key->data); - else if (dctx->keyType == T_3DES) +PrintAndLogEx(INFO, "IV : %s", sprint_hex(IV, rndlen)); + if (dctx->keyType == T_DES){ + if (dctx->secureChannel == DACd40) + des_decrypt(encRndA, encRndA, key->data); + if (dctx->secureChannel == DACEV1) + des_decrypt_cbc(encRndA, encRndA, rndlen, key->data, IV); + } else if (dctx->keyType == T_3DES) tdes_nxp_receive(encRndA, encRndA, rndlen, key->data, IV, 2); else if (dctx->keyType == T_3K3DES) tdes_nxp_receive(encRndA, encRndA, rndlen, key->data, IV, 3); From aa8c4b3dcaee8d9ee4847fb121b1416b6ac17ac4 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 4 Jul 2021 17:49:11 +0300 Subject: [PATCH 174/309] secure channel sketch --- client/src/mifare/desfirecore.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 118e30109..82ec7ccd2 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -525,15 +525,32 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t return PM3_SUCCESS; } +static void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; +} + +static void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; +} + int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { int res = PM3_SUCCESS; + uint8_t databuf[250 * 5] = {0}; + size_t databuflen = 0; + switch(ctx->cmdSet) { case DCCNative: - res = DesfireExchangeNative(activate_field, ctx, cmd, data, datalen, respcode, resp, resplen, enable_chaining, splitbysize); + DesfireSecureChannelEncode(ctx, cmd, data, datalen, databuf, &databuflen); + res = DesfireExchangeNative(activate_field, ctx, cmd, databuf, databuflen, respcode, databuf, &databuflen, enable_chaining, splitbysize); + DesfireSecureChannelDecode(ctx, databuf, databuflen, *respcode, resp, resplen); break; case DCCNativeISO: - res = DesfireExchangeISO(activate_field, ctx, cmd, data, datalen, respcode, resp, resplen, enable_chaining, splitbysize); + DesfireSecureChannelEncode(ctx, cmd, data, datalen, databuf, &databuflen); + res = DesfireExchangeISO(activate_field, ctx, cmd, databuf, databuflen, respcode, databuf, &databuflen, enable_chaining, splitbysize); + DesfireSecureChannelDecode(ctx, databuf, databuflen, *respcode, resp, resplen); break; case DCCISO: return PM3_EAPDU_FAIL; From 998538a60ad10175868820c316815be2799c53ed Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 4 Jul 2021 22:15:53 +0300 Subject: [PATCH 175/309] libcrypto des encrypt/decrypt ecb and change cmdhfemtrd to use des from libcrypto --- client/src/cmdhfemrtd.c | 23 ++++------------------- client/src/crypto/libpcrypto.c | 12 ++++++++++++ client/src/crypto/libpcrypto.h | 2 ++ 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 7791233dc..312099268 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -19,8 +19,7 @@ #include "protocols.h" // definitions of ISO14A/7816 protocol #include "iso7816/apduinfo.h" // GetAPDUCodeDescription #include "iso7816/iso7816core.h" // Iso7816ExchangeEx etc -#include "crypto/libpcrypto.h" // Hash calculation (sha1, sha256, sha512) -#include "mifare/desfire_crypto.h" // des_encrypt/des_decrypt +#include "crypto/libpcrypto.h" // Hash calculation (sha1, sha256, sha512), des_encrypt/des_decrypt #include "des.h" // mbedtls_des_key_set_parity #include "crapto1/crapto1.h" // prng_successor #include "commonutil.h" // num_to_bytes @@ -263,20 +262,6 @@ static int emrtd_get_asn1_field_length(uint8_t *datain, int datainlen, int offse return 0; } -static void des_encrypt_ecb(uint8_t *key, uint8_t *input, uint8_t *output) { - mbedtls_des_context ctx_enc; - mbedtls_des_setkey_enc(&ctx_enc, key); - mbedtls_des_crypt_ecb(&ctx_enc, input, output); - mbedtls_des_free(&ctx_enc); -} - -static void des_decrypt_ecb(uint8_t *key, uint8_t *input, uint8_t *output) { - mbedtls_des_context ctx_dec; - mbedtls_des_setkey_dec(&ctx_dec, key); - mbedtls_des_crypt_ecb(&ctx_dec, input, output); - mbedtls_des_free(&ctx_dec); -} - static void des3_encrypt_cbc(uint8_t *iv, uint8_t *key, uint8_t *input, int inputlen, uint8_t *output) { mbedtls_des3_context ctx; mbedtls_des3_set2key_enc(&ctx, key); @@ -345,15 +330,15 @@ static void retail_mac(uint8_t *key, uint8_t *input, int inputlen, uint8_t *outp intermediate[x] = intermediate[x] ^ block[x]; } - des_encrypt_ecb(k0, intermediate, intermediate_des); + des_encrypt(intermediate_des, intermediate, k0); memcpy(intermediate, intermediate_des, 8); } - des_decrypt_ecb(k1, intermediate, intermediate_des); + des_decrypt(intermediate_des, intermediate, k1); memcpy(intermediate, intermediate_des, 8); - des_encrypt_ecb(k0, intermediate, intermediate_des); + des_encrypt(intermediate_des, intermediate, k0); memcpy(output, intermediate_des, 8); } diff --git a/client/src/crypto/libpcrypto.c b/client/src/crypto/libpcrypto.c index d3df5dfda..af15c1f5e 100644 --- a/client/src/crypto/libpcrypto.c +++ b/client/src/crypto/libpcrypto.c @@ -33,12 +33,24 @@ void des_encrypt(void *out, const void *in, const void *key) { mbedtls_des_context ctx; mbedtls_des_setkey_enc(&ctx, key); mbedtls_des_crypt_ecb(&ctx, in, out); + mbedtls_des_free(&ctx); } void des_decrypt(void *out, const void *in, const void *key) { mbedtls_des_context ctx; mbedtls_des_setkey_dec(&ctx, key); mbedtls_des_crypt_ecb(&ctx, in, out); + mbedtls_des_free(&ctx); +} + +void des_encrypt_ecb(void *out, const void *in, const int length, const void *key) { + for (int i = 0; i < length; i += 8) + des_encrypt((uint8_t *)out + i, (uint8_t *)in + i, key); +} + +void des_decrypt_ecb(void *out, const void *in, const int length, const void *key) { + for (int i = 0; i < length; i += 8) + des_decrypt((uint8_t *)out + i, (uint8_t *)in + i, key); } void des_encrypt_cbc(void *out, const void *in, const int length, const void *key, uint8_t *iv) { diff --git a/client/src/crypto/libpcrypto.h b/client/src/crypto/libpcrypto.h index 1c7c745dc..d5f7b809b 100644 --- a/client/src/crypto/libpcrypto.h +++ b/client/src/crypto/libpcrypto.h @@ -18,6 +18,8 @@ void des_encrypt(void *out, const void *in, const void *key); void des_decrypt(void *out, const void *in, const void *key); +void des_encrypt_ecb(void *out, const void *in, const int length, const void *key); +void des_decrypt_ecb(void *out, const void *in, const int length, const void *key); void des_encrypt_cbc(void *out, const void *in, const int length, const void *key, uint8_t *iv); void des_decrypt_cbc(void *out, const void *in, const int length, const void *key, uint8_t *iv); From 5d8fa054e5df8c8fe6bc9ddebd90d6dd404d66ad Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 4 Jul 2021 22:16:43 +0300 Subject: [PATCH 176/309] added channel logic to d40 mode --- client/src/mifare/desfirecore.c | 102 +++++++++++++++++++++++++++++++- client/src/mifare/desfirecore.h | 1 + 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 82ec7ccd2..656b32889 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -21,6 +21,9 @@ #include #include "aes.h" #include "ui.h" +#include "crc.h" +#include "crc16.h" // crc16 ccitt +#include "crc32.h" #include "protocols.h" #include "commonutil.h" #include "cmdhf14a.h" @@ -218,6 +221,7 @@ void DesfireClearContext(DesfireContext *ctx) { void DesfireClearSession(DesfireContext *ctx) { ctx->secureChannel = DACNone; // here none - not authenticared + memset(ctx->IV, 0, sizeof(ctx->IV)); memset(ctx->sessionKeyMAC, 0, sizeof(ctx->sessionKeyMAC)); memset(ctx->sessionKeyEnc, 0, sizeof(ctx->sessionKeyEnc)); memset(ctx->lastIV, 0, sizeof(ctx->lastIV)); @@ -525,9 +529,105 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t return PM3_SUCCESS; } -static void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { +static void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { + uint8_t data[1024] = {0}; + + switch(ctx->keyType) { + case T_DES: + if (ctx->secureChannel == DACd40) { + if (encode) + des_encrypt_ecb(data, srcdata, srcdatalen, ctx->key); + else + des_decrypt_ecb(data, srcdata, srcdatalen, ctx->key); + } if (ctx->secureChannel == DACEV1) { + if (encode) + des_encrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); + else + des_decrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); + } + + if (dstdata) + memcpy(dstdata, data, srcdatalen); + break; + case T_3DES: + break; + case T_3K3DES: + break; + case T_AES: + if (encode) + aes_encode(ctx->IV, ctx->key, srcdata, data, srcdatalen); + else + aes_decode(ctx->IV, ctx->key, srcdata, data, srcdatalen); + if (dstdata) + memcpy(dstdata, data, srcdatalen); + break; + } +} + +static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; + + uint8_t data[1024] = {0}; + size_t rlen = 0; + + switch(ctx->commMode) { + case DCMPlain: + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + break; + case DCMMACed: + if (srcdatalen == 0) + break; + + rlen = padded_data_length(srcdatalen, desfire_get_key_block_length(ctx->keyType)); + memcpy(data, srcdata, srcdatalen); + DesfireCryptoEncDec(ctx, data, rlen, NULL, true); + memcpy(dstdata, srcdata, srcdatalen); + memcpy(&dstdata[srcdatalen], ctx->IV, desfire_get_key_block_length(ctx->keyType)); + *dstdatalen = rlen; + break; + case DCMEncrypted: + rlen = padded_data_length(srcdatalen + 2, desfire_get_key_block_length(ctx->keyType)); // 2 - crc16 + memcpy(data, srcdata, srcdatalen); + compute_crc(CRC_14443_A, data, srcdatalen, &data[srcdatalen], &data[srcdatalen + 1]); + DesfireCryptoEncDec(ctx, data, rlen, dstdata, true); + *dstdatalen = rlen; + break; + case DCMNone:; + } +} + +static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + + switch(ctx->commMode) { + case DCMPlain: + case DCMMACed: + + break; + case DCMEncrypted: + break; + case DCMNone:; + } +} + +static void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { + switch(ctx->secureChannel) { + case DACd40: + DesfireSecureChannelEncodeD40(ctx, cmd, srcdata, srcdatalen, dstdata, dstdatalen); + break; + case DACEV1: + DesfireSecureChannelEncodeEV1(ctx, cmd, srcdata, srcdatalen, dstdata, dstdatalen); + break; + case DACEV2: + break; + case DACNone: + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + break; + } } static void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index d03e8e908..873e365a8 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -59,6 +59,7 @@ typedef struct DesfireContextS { DesfireCommandSet cmdSet; // native/nativeiso/iso DesfireCommunicationMode commMode; // plain/mac/enc + uint8_t IV[DESF_MAX_KEY_LEN]; uint8_t sessionKeyMAC[DESF_MAX_KEY_LEN]; uint8_t sessionKeyEnc[DESF_MAX_KEY_LEN]; // look at mifare4.h - mf4Session_t uint8_t lastIV[DESF_MAX_KEY_LEN]; From 1aedfc7b6e7c8db221165df92c21b9b7635ab964 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 4 Jul 2021 22:37:27 +0300 Subject: [PATCH 177/309] ev1 mac decode placeholder --- client/src/mifare/desfirecore.c | 72 ++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 11 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 656b32889..a461fb254 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -630,9 +630,59 @@ static void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t } } -static void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { +static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; + + switch(ctx->commMode) { + case DCMMACed: + + break; + case DCMEncrypted: + break; + case DCMPlain: + case DACNone: + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + break; + } +} + +static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + + switch(ctx->commMode) { + case DCMPlain: + case DCMMACed: + memcpy(dstdata, srcdata, srcdatalen - 8); + *dstdatalen = srcdatalen - 8; + + break; + case DCMEncrypted: + break; + case DACNone: + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + break; + } +} + +static void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { + switch(ctx->secureChannel) { + case DACd40: + DesfireSecureChannelDecodeD40(ctx, srcdata, srcdatalen, respcode, dstdata, dstdatalen); + break; + case DACEV1: + DesfireSecureChannelDecodeEV1(ctx, srcdata, srcdatalen, respcode, dstdata, dstdatalen); + break; + case DACEV2: + break; + case DACNone: + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + break; + } } int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { @@ -759,8 +809,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel } uint8_t subcommand = MFDES_AUTHENTICATE; - dctx->secureChannel = secureChannel; - if (dctx->secureChannel == DACEV1) { + if (secureChannel == DACEV1) { if (dctx->keyType == T_AES) subcommand = MFDES_AUTHENTICATE_AES; else @@ -806,9 +855,9 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel } mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, rndlen, IV, encRndB, RndB); } else if (dctx->keyType == T_DES) { - if (dctx->secureChannel == DACd40) + if (secureChannel == DACd40) des_decrypt(RndB, encRndB, key->data); - if (dctx->secureChannel == DACEV1) + if (secureChannel == DACEV1) des_decrypt_cbc(RndB, encRndB, rndlen, key->data, IV); } else if (dctx->keyType == T_3DES) tdes_nxp_receive(encRndB, RndB, rndlen, key->data, IV, 2); @@ -828,7 +877,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel uint8_t encRndA[16] = {0x00}; // - Encrypt our response - if (dctx->secureChannel == DACd40) { + if (secureChannel == DACd40) { if (dctx->keyType == T_DES) { des_decrypt(encRndA, RndA, key->data); memcpy(both, encRndA, rndlen); @@ -842,7 +891,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel } else if (dctx->keyType == T_3DES) { //TODO } - } else if (dctx->secureChannel == DACEV1 && dctx->keyType != T_AES) { + } else if (secureChannel == DACEV1 && dctx->keyType != T_AES) { if (dctx->keyType == T_DES) { uint8_t tmp[16] = {0x00}; memcpy(tmp, RndA, rndlen); @@ -880,7 +929,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, 32)); } } - } else if (dctx->secureChannel == DACEV1 && dctx->keyType == T_AES) { + } else if (secureChannel == DACEV1 && dctx->keyType == T_AES) { uint8_t tmp[32] = {0x00}; memcpy(tmp, RndA, rndlen); memcpy(tmp + rndlen, rotRndB, rndlen); @@ -928,9 +977,9 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel PrintAndLogEx(INFO, "encRndA : %s", sprint_hex(encRndA, rndlen)); PrintAndLogEx(INFO, "IV : %s", sprint_hex(IV, rndlen)); if (dctx->keyType == T_DES){ - if (dctx->secureChannel == DACd40) + if (secureChannel == DACd40) des_decrypt(encRndA, encRndA, key->data); - if (dctx->secureChannel == DACEV1) + if (secureChannel == DACEV1) des_decrypt_cbc(encRndA, encRndA, rndlen, key->data, IV); } else if (dctx->keyType == T_3DES) tdes_nxp_receive(encRndA, encRndA, rndlen, key->data, IV, 2); @@ -963,12 +1012,13 @@ PrintAndLogEx(INFO, "Generated_RndA : %s", sprint_hex(encRndA, rndlen)); memcpy(&dctx->sessionKeyEnc[8], dctx->sessionKeyEnc, 8); } - if (dctx->secureChannel == DACEV1) { + if (secureChannel == DACEV1) { cmac_generate_subkeys(&sesskey, MCD_RECEIVE); //key->cmac_sk1 and key->cmac_sk2 //memcpy(dctx->sessionKeyEnc, sesskey.data, desfire_get_key_length(dctx->keyType)); } + dctx->secureChannel = secureChannel; memcpy(dctx->sessionKeyMAC, dctx->sessionKeyEnc, desfire_get_key_length(dctx->keyType)); PrintAndLogEx(INFO, "sessionKeyEnc : %s", sprint_hex(dctx->sessionKeyEnc, desfire_get_key_length(dctx->keyType))); From afbd80b90661bb6c3b75e5c80b673ebbb3f78aff Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 11:59:07 +0300 Subject: [PATCH 178/309] cliparser CLIGetOptionList --- client/deps/cliparser/cliparser.c | 58 +++++++++++++++++++++++++++++++ client/deps/cliparser/cliparser.h | 14 ++++++++ 2 files changed, 72 insertions(+) diff --git a/client/deps/cliparser/cliparser.c b/client/deps/cliparser/cliparser.c index ec9f50e20..ad89856cd 100644 --- a/client/deps/cliparser/cliparser.c +++ b/client/deps/cliparser/cliparser.c @@ -298,6 +298,64 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int return 0; } +int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array, int *value) { + char data[200] = {0}; + int datalen = 0; + int res = CLIParamStrToBuf(argstr, (uint8_t *)data, sizeof(data), &datalen); + if (res) + return res; + + // no data to check - we do not touch *value, just return + if (datalen == 0) + return 0; + + str_lower(data); + + int val = -1; + int cntr = 0; + for (int i = 0; i < CLI_MAX_OPTLIST_LEN; i++) { + // end of array + if (option_array[i].text == NULL) + break; + // exact match + if (strcmp(option_array[i].text, data) == 0) { + *value = option_array[i].code; + return 0; + } + // partial match + if (strncmp(option_array[i].text, data, datalen) == 0) { + val = option_array[i].code; + cntr++; + } + } + + // check partial match + if (cntr == 0) { + PrintAndLogEx(ERR, "Parameter error: No similar option to `%s`. Valid options: %s\n", argstr->sval[0], argstr->hdr.datatype); + return 20; + } + if (cntr > 1) { + PrintAndLogEx(ERR, "Parameter error: Several options fit to `%s`. Valid options: %s\n", argstr->sval[0], argstr->hdr.datatype); + return 21; + } + + *value = val; + return 0; +} + +const char *CLIGetOptionListStr(const CLIParserOption *option_array, int value) { + static const char *errmsg = "n/a"; + + for (int i = 0; i < CLI_MAX_OPTLIST_LEN; i++) { + if (option_array[i].text == NULL) + break; + if (option_array[i].code == value) + return option_array[i].text; + } + return errmsg; +} + + // hexstr -> u64, w optional len input and default value fallback. // 0 = failed // 1 = OK diff --git a/client/deps/cliparser/cliparser.h b/client/deps/cliparser/cliparser.h index 39a5792f8..f50fec2ee 100644 --- a/client/deps/cliparser/cliparser.h +++ b/client/deps/cliparser/cliparser.h @@ -51,6 +51,8 @@ #define CLIGetStrWithReturn(ctx, paramnum, data, datalen) if (CLIParamStrToBuf(arg_get_str((ctx), (paramnum)), (data), (*datalen), (datalen))) {CLIParserFree((ctx)); return PM3_ESOFT;} +#define CLIGetOptionListWithReturn(ctx, paramnum, option_array, option_array_len, value) if (CLIGetOptionList(arg_get_str((ctx), (paramnum)), (option_array), (option_array_len), (value))) {CLIParserFree((ctx)); return PM3_ESOFT;} + typedef struct { void **argtable; size_t argtableLen; @@ -59,6 +61,14 @@ typedef struct { const char *programHelp; char buf[1024 + 60]; } CLIParserContext; + +#define CLI_MAX_OPTLIST_LEN 50 +// option list needs to have NULL at the last record int the field `text` +typedef struct { + int code; + const char *text; +} CLIParserOption; + int CLIParserInit(CLIParserContext **ctx, const char *vprogramName, const char *vprogramHint, const char *vprogramHelp); void CLIParserPrintHelp(CLIParserContext *ctx); int CLIParserParseString(CLIParserContext *ctx, const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec); @@ -69,6 +79,10 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); int CLIParamBinToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); +// names in the CLIParserOption array must be in the lowercase format +int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array, int *value); +const char *CLIGetOptionListStr(const CLIParserOption *option_array, int value); + uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def); int arg_get_u64_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint64_t def, uint64_t *out, uint8_t nlen, bool optional); int arg_get_u32_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint32_t def, uint32_t *out); From 7d06c09d173e69bfcffd9d3af8fbd2eae1937ba1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 11:59:24 +0300 Subject: [PATCH 179/309] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c2c5db58..0b3a1a7d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added `CLIGetOptionList` to cliparser that makes it easier to implement text options in the cli (@merlokk) - Added experimental support for macOS users utilizing MacPorts instead of Homebrew (@linuxgemini) - Added `pm3_online_check.py` - a script to verify and initialize a Proxmark3 RDV4 device (@iceman1001) From 2fb090e560f9b4e75552fc013030133a5372de48 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 12:01:43 +0300 Subject: [PATCH 180/309] move des functions to pcrypto --- client/src/crypto/libpcrypto.c | 38 ++++++++++++++++++++++++++++++++++ client/src/crypto/libpcrypto.h | 7 +++++++ 2 files changed, 45 insertions(+) diff --git a/client/src/crypto/libpcrypto.c b/client/src/crypto/libpcrypto.c index 723753d5f..af15c1f5e 100644 --- a/client/src/crypto/libpcrypto.c +++ b/client/src/crypto/libpcrypto.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,43 @@ #include #include "util.h" #include "ui.h" + +void des_encrypt(void *out, const void *in, const void *key) { + mbedtls_des_context ctx; + mbedtls_des_setkey_enc(&ctx, key); + mbedtls_des_crypt_ecb(&ctx, in, out); + mbedtls_des_free(&ctx); +} + +void des_decrypt(void *out, const void *in, const void *key) { + mbedtls_des_context ctx; + mbedtls_des_setkey_dec(&ctx, key); + mbedtls_des_crypt_ecb(&ctx, in, out); + mbedtls_des_free(&ctx); +} + +void des_encrypt_ecb(void *out, const void *in, const int length, const void *key) { + for (int i = 0; i < length; i += 8) + des_encrypt((uint8_t *)out + i, (uint8_t *)in + i, key); +} + +void des_decrypt_ecb(void *out, const void *in, const int length, const void *key) { + for (int i = 0; i < length; i += 8) + des_decrypt((uint8_t *)out + i, (uint8_t *)in + i, key); +} + +void des_encrypt_cbc(void *out, const void *in, const int length, const void *key, uint8_t *iv) { + mbedtls_des_context ctx; + mbedtls_des_setkey_enc(&ctx, key); + mbedtls_des_crypt_cbc(&ctx, MBEDTLS_DES_ENCRYPT, length, iv, in, out); +} + +void des_decrypt_cbc(void *out, const void *in, const int length, const void *key, uint8_t *iv) { + mbedtls_des_context ctx; + mbedtls_des_setkey_dec(&ctx, key); + mbedtls_des_crypt_cbc(&ctx, MBEDTLS_DES_DECRYPT, length, iv, in, out); +} + // NIST Special Publication 800-38A — Recommendation for block cipher modes of operation: methods and techniques, 2001. int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length) { uint8_t iiv[16] = {0}; diff --git a/client/src/crypto/libpcrypto.h b/client/src/crypto/libpcrypto.h index 099fd4423..d5f7b809b 100644 --- a/client/src/crypto/libpcrypto.h +++ b/client/src/crypto/libpcrypto.h @@ -16,6 +16,13 @@ #include #include +void des_encrypt(void *out, const void *in, const void *key); +void des_decrypt(void *out, const void *in, const void *key); +void des_encrypt_ecb(void *out, const void *in, const int length, const void *key); +void des_decrypt_ecb(void *out, const void *in, const int length, const void *key); +void des_encrypt_cbc(void *out, const void *in, const int length, const void *key, uint8_t *iv); +void des_decrypt_cbc(void *out, const void *in, const int length, const void *key, uint8_t *iv); + int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length); From 93a19fb953dc8b9f855ded10c920a0f80ba1447d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 12:03:50 +0300 Subject: [PATCH 181/309] cmdhfemrtd uses libcrypto --- client/src/cmdhfemrtd.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 7791233dc..312099268 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -19,8 +19,7 @@ #include "protocols.h" // definitions of ISO14A/7816 protocol #include "iso7816/apduinfo.h" // GetAPDUCodeDescription #include "iso7816/iso7816core.h" // Iso7816ExchangeEx etc -#include "crypto/libpcrypto.h" // Hash calculation (sha1, sha256, sha512) -#include "mifare/desfire_crypto.h" // des_encrypt/des_decrypt +#include "crypto/libpcrypto.h" // Hash calculation (sha1, sha256, sha512), des_encrypt/des_decrypt #include "des.h" // mbedtls_des_key_set_parity #include "crapto1/crapto1.h" // prng_successor #include "commonutil.h" // num_to_bytes @@ -263,20 +262,6 @@ static int emrtd_get_asn1_field_length(uint8_t *datain, int datainlen, int offse return 0; } -static void des_encrypt_ecb(uint8_t *key, uint8_t *input, uint8_t *output) { - mbedtls_des_context ctx_enc; - mbedtls_des_setkey_enc(&ctx_enc, key); - mbedtls_des_crypt_ecb(&ctx_enc, input, output); - mbedtls_des_free(&ctx_enc); -} - -static void des_decrypt_ecb(uint8_t *key, uint8_t *input, uint8_t *output) { - mbedtls_des_context ctx_dec; - mbedtls_des_setkey_dec(&ctx_dec, key); - mbedtls_des_crypt_ecb(&ctx_dec, input, output); - mbedtls_des_free(&ctx_dec); -} - static void des3_encrypt_cbc(uint8_t *iv, uint8_t *key, uint8_t *input, int inputlen, uint8_t *output) { mbedtls_des3_context ctx; mbedtls_des3_set2key_enc(&ctx, key); @@ -345,15 +330,15 @@ static void retail_mac(uint8_t *key, uint8_t *input, int inputlen, uint8_t *outp intermediate[x] = intermediate[x] ^ block[x]; } - des_encrypt_ecb(k0, intermediate, intermediate_des); + des_encrypt(intermediate_des, intermediate, k0); memcpy(intermediate, intermediate_des, 8); } - des_decrypt_ecb(k1, intermediate, intermediate_des); + des_decrypt(intermediate_des, intermediate, k1); memcpy(intermediate, intermediate_des, 8); - des_encrypt_ecb(k0, intermediate, intermediate_des); + des_encrypt(intermediate_des, intermediate, k0); memcpy(output, intermediate_des, 8); } From 3cc199ea34d00923d5614020b75a1182ff4f2cbc Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 12:04:36 +0300 Subject: [PATCH 182/309] cmdhfmf uses libcrypto --- client/src/cmdhfmf.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index ace8d2d0b..985d156db 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -24,7 +24,6 @@ #include "protocols.h" #include "util_posix.h" // msclock #include "cmdhfmfhard.h" -#include "des.h" // des ecb #include "crapto1/crapto1.h" // prng_successor #include "cmdhf14a.h" // exchange APDU #include "crypto/libpcrypto.h" @@ -5645,12 +5644,6 @@ static int CmdHf14AGen3Freeze(const char *Cmd) { return res; } -static void des_decrypt(void *out, const void *in, const void *key) { - mbedtls_des_context ctx; - mbedtls_des_setkey_dec(&ctx, key); - mbedtls_des_crypt_ecb(&ctx, in, out); -} - static int CmdHf14AMfSuperCard(const char *Cmd) { CLIParserContext *ctx; From 4db3862cd7daf0edfe33fcf00b6b3ea4d320a478 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 12:06:07 +0300 Subject: [PATCH 183/309] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c2c5db58..1cfc2d76f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fix - move des functions to libcrypto (@merlokk) - Added experimental support for macOS users utilizing MacPorts instead of Homebrew (@linuxgemini) - Added `pm3_online_check.py` - a script to verify and initialize a Proxmark3 RDV4 device (@iceman1001) From dece2b1bbde0a842e6ef399a45f99c74b4894bc4 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 12:09:08 +0300 Subject: [PATCH 184/309] delete des from desfire_crypto --- client/src/mifare/desfire_crypto.c | 12 ------------ client/src/mifare/desfire_crypto.h | 2 -- 2 files changed, 14 deletions(-) diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index e3e785e6c..3c27e1ca4 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -53,18 +53,6 @@ static inline void update_key_schedules(desfirekey_t key) { /******************************************************************************/ -void des_encrypt(void *out, const void *in, const void *key) { - mbedtls_des_context ctx; - mbedtls_des_setkey_enc(&ctx, key); - mbedtls_des_crypt_ecb(&ctx, in, out); -} - -void des_decrypt(void *out, const void *in, const void *key) { - mbedtls_des_context ctx; - mbedtls_des_setkey_dec(&ctx, key); - mbedtls_des_crypt_ecb(&ctx, in, out); -} - void tdes_nxp_receive(const void *in, void *out, size_t length, const void *key, unsigned char iv[8], int keymode) { if (length % 8) return; diff --git a/client/src/mifare/desfire_crypto.h b/client/src/mifare/desfire_crypto.h index ecc6fc4a5..b58372004 100644 --- a/client/src/mifare/desfire_crypto.h +++ b/client/src/mifare/desfire_crypto.h @@ -102,8 +102,6 @@ typedef unsigned long DES3_KS[48][2]; /* Triple-DES key schedule */ extern int Asmversion; /* 1 if we're linked with an asm version, 0 if C */ -void des_encrypt(void *out, const void *in, const void *key); -void des_decrypt(void *out, const void *in, const void *key); void tdes_nxp_receive(const void *in, void *out, size_t length, const void *key, unsigned char iv[8], int keymode); void tdes_nxp_send(const void *in, void *out, size_t length, const void *key, unsigned char iv[8], int keymode); void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key); From 5937fd4217ed15c099ff50724dda7ca889d3220e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 12:12:42 +0300 Subject: [PATCH 185/309] added lib --- client/src/mifare/desfire_crypto.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 3c27e1ca4..34f38ef73 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -30,6 +30,7 @@ #include #include #include "commonutil.h" +#include "crypto/libpcrypto.h" #include "aes.h" #include "des.h" #include "ui.h" From 003a0b0de4916b85435b3755b2e802008e1e5151 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 12:40:07 +0300 Subject: [PATCH 186/309] splitbysize now put length of message at the first bytes of array's memory --- client/src/cmdhfmfdes.c | 8 ++++---- client/src/mifare/desfirecore.c | 26 ++++++++++++++++++++------ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index c7a195db5..3560d5bf3 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5298,10 +5298,10 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { PrintAndLogEx(INFO, "----------------------- " _CYAN_("File list") " -----------------------"); for (int i = 0; i < buflen; i++) PrintAndLogEx(INFO, "AID: %06x ISO file id: %02x%02x ISO DF name[%d]: %s", - DesfireAIDByteToUint(&buf[i * 24]), - buf[i * 24 + 3], buf[i * 24 + 4], - strlen((char *)&buf[i * 24 + 5]), - &buf[i * 24 + 5]); + DesfireAIDByteToUint(&buf[i * 24 + 1]), + buf[i * 24 + 1 + 3], buf[i * 24 + 1 + 4], + strlen((char *)&buf[i * 24 + 1 + 5]), + &buf[i * 24 + 1 + 5]); } DropField(); diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index a461fb254..fee49ca5a 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -404,8 +404,14 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8 return res; } - if (resp) - memcpy(resp, buf, buflen); + if (resp) { + if (splitbysize) { + resp[0] = buflen; + memcpy(&resp[1], buf, buflen); + } else { + memcpy(resp, buf, buflen); + } + } if (respcode != NULL) *respcode = rcode; @@ -434,7 +440,8 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8 if (resp != NULL) { if (splitbysize) { - memcpy(&resp[i * splitbysize], buf, buflen); + resp[i * splitbysize] = buflen; + memcpy(&resp[i * splitbysize + 1], buf, buflen); i += 1; } else { memcpy(&resp[pos], buf, buflen); @@ -480,8 +487,14 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t if (respcode != NULL && ((sw & 0xff00) == 0x9100)) *respcode = sw & 0xff; - if (resp) - memcpy(resp, buf, buflen); + if (resp) { + if (splitbysize) { + resp[0] = buflen; + memcpy(&resp[1], buf, buflen); + } else { + memcpy(resp, buf, buflen); + } + } pos += buflen; if (!enable_chaining) { @@ -512,7 +525,8 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t if (resp != NULL) { if (splitbysize) { - memcpy(&resp[i * splitbysize], buf, buflen); + resp[i * splitbysize] = buflen; + memcpy(&resp[i * splitbysize + 1], buf, buflen); i += 1; } else { memcpy(&resp[pos], buf, buflen); From 36c0ddc91a86c0f63f8446e5fc2176c8f7bfa702 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Jul 2021 12:36:43 +0200 Subject: [PATCH 187/309] increase output size in order to avoid crash in emrtd info --- client/src/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/util.c b/client/src/util.c index 77ce9cf2f..ed6ca6e7c 100644 --- a/client/src/util.c +++ b/client/src/util.c @@ -25,7 +25,7 @@ #include "ui.h" // PrintAndLog -#define UTIL_BUFFER_SIZE_SPRINT 4097 +#define UTIL_BUFFER_SIZE_SPRINT 8193 // global client debug variable uint8_t g_debugMode = 0; // global client disable logging variable From 96d18a1cd7f70c6a8b0fe6644f16631bb5b1f16c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 14:00:51 +0300 Subject: [PATCH 188/309] splitbysize works correctly in the all the cases --- client/src/mifare/desfirecore.c | 52 +++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index fee49ca5a..449f144e2 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -699,6 +699,32 @@ static void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, si } } +// move data from blockdata [format: ...] to single data block +static void DesfireJoinBlockToBytes(uint8_t *blockdata, size_t blockdatacount, size_t blockdatasize, uint8_t *dstdata, size_t *dstdatalen) { + *dstdatalen = 0; + for(int i = 0; i < blockdatacount; i++) { + memcpy(&dstdata[*dstdatalen], &blockdata[i * blockdatasize + 1], blockdata[i * blockdatasize]); + *dstdatalen += blockdata[i * blockdatasize]; + } +} + +// move data from single data block to blockdata [format: ...] +// lengths in the blockdata is not changed. result - in the blockdata +static void DesfireSplitBytesToBlock(uint8_t *blockdata, size_t *blockdatacount, size_t blockdatasize, uint8_t *dstdata, size_t dstdatalen) { + size_t len = 0; + for(int i = 0; i < *blockdatacount; i++) { + size_t tlen = len + blockdata[i * blockdatasize]; + if (tlen > dstdatalen) + tlen = dstdatalen; + if (len == tlen) { + *blockdatacount = i; + break; + } + memcpy(&blockdata[i * blockdatasize + 1], &dstdata[len], tlen - len); + len = tlen; + } +} + int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { int res = PM3_SUCCESS; @@ -707,14 +733,28 @@ int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uin switch(ctx->cmdSet) { case DCCNative: - DesfireSecureChannelEncode(ctx, cmd, data, datalen, databuf, &databuflen); - res = DesfireExchangeNative(activate_field, ctx, cmd, databuf, databuflen, respcode, databuf, &databuflen, enable_chaining, splitbysize); - DesfireSecureChannelDecode(ctx, databuf, databuflen, *respcode, resp, resplen); - break; case DCCNativeISO: DesfireSecureChannelEncode(ctx, cmd, data, datalen, databuf, &databuflen); - res = DesfireExchangeISO(activate_field, ctx, cmd, databuf, databuflen, respcode, databuf, &databuflen, enable_chaining, splitbysize); - DesfireSecureChannelDecode(ctx, databuf, databuflen, *respcode, resp, resplen); + + if (ctx->cmdSet == DCCNative) + res = DesfireExchangeNative(activate_field, ctx, cmd, databuf, databuflen, respcode, databuf, &databuflen, enable_chaining, splitbysize); + else + res = DesfireExchangeISO(activate_field, ctx, cmd, databuf, databuflen, respcode, databuf, &databuflen, enable_chaining, splitbysize); + + if (splitbysize) { + uint8_t sdata[250 * 5] = {0}; + size_t sdatalen = 0; + DesfireJoinBlockToBytes(databuf, databuflen, splitbysize, sdata, &sdatalen); + + //PrintAndLogEx(INFO, "block : %s", sprint_hex(sdata, sdatalen)); + DesfireSecureChannelDecode(ctx, sdata, sdatalen, *respcode, resp, resplen); + + DesfireSplitBytesToBlock(databuf, &databuflen, splitbysize, resp, *resplen); + memcpy(resp, databuf, databuflen * splitbysize); + *resplen = databuflen; + } else { + DesfireSecureChannelDecode(ctx, databuf, databuflen, *respcode, resp, resplen); + } break; case DCCISO: return PM3_EAPDU_FAIL; From e9b8e1843039d6dbd7479dc4a2cc448cabd02d64 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 14:15:39 +0300 Subject: [PATCH 189/309] remove key_size --- client/src/cmdhfmfdes.c | 6 +++--- client/src/mifare/desfire_crypto.c | 18 ------------------ client/src/mifare/desfire_crypto.h | 1 - client/src/mifare/desfirecore.c | 10 +++++----- 4 files changed, 8 insertions(+), 27 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 3560d5bf3..79c770348 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5040,8 +5040,8 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct uint8_t keydata[200] = {0}; if (CLIParamHexToBuf(arg_get_str(ctx, keyid), keydata, sizeof(keydata), &keylen)) return PM3_ESOFT; - if (keylen && keylen != key_size(algores)) { - PrintAndLogEx(ERR, "%s key must have %d bytes length instead of %d.", CLIGetOptionListStr(DesfireAlgoOpts, algores), key_size(algores), keylen); + if (keylen && keylen != desfire_get_key_length(algores)) { + PrintAndLogEx(ERR, "%s key must have %d bytes length instead of %d.", CLIGetOptionListStr(DesfireAlgoOpts, algores), desfire_get_key_length(algores), keylen); return PM3_EINVARG; } if (keylen) @@ -5133,7 +5133,7 @@ static int CmdHF14ADesDefault(const char *Cmd) { PrintAndLogEx(INFO, "Key Num : %d", defaultKeyNum); PrintAndLogEx(INFO, "Algo : %s", CLIGetOptionListStr(DesfireAlgoOpts, defaultAlgoId)); - PrintAndLogEx(INFO, "Key : %s", sprint_hex(defaultKey, key_size(defaultAlgoId))); + PrintAndLogEx(INFO, "Key : %s", sprint_hex(defaultKey, desfire_get_key_length(defaultAlgoId))); PrintAndLogEx(INFO, "KDF algo : %s", CLIGetOptionListStr(DesfireKDFAlgoOpts, defaultKdfAlgo)); PrintAndLogEx(INFO, "KDF input : [%d] %s", defaultKdfInputLen, sprint_hex(defaultKdfInput, defaultKdfInputLen)); PrintAndLogEx(INFO, "Secure chan : %s", CLIGetOptionListStr(DesfireSecureChannelOpts, defaultSecureChannel)); diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index d941ae09e..85abb4c43 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -400,24 +400,6 @@ size_t key_block_size(const desfirekey_t key) { return desfire_get_key_block_length(key->type); } -size_t key_size(const enum DESFIRE_CRYPTOALGO algo) { - switch (algo) { - case T_DES: - return 8; - break; - case T_3DES: - return 16; - break; - case T_3K3DES: - return 24; - break; - case T_AES: - return 16; - break; - } - return 0; -} - /* * Size of MACing produced with the key. */ diff --git a/client/src/mifare/desfire_crypto.h b/client/src/mifare/desfire_crypto.h index 1aa938017..98f835f4e 100644 --- a/client/src/mifare/desfire_crypto.h +++ b/client/src/mifare/desfire_crypto.h @@ -148,7 +148,6 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size); void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation); size_t key_block_size(const desfirekey_t key); -size_t key_size(const enum DESFIRE_CRYPTOALGO algo); size_t padded_data_length(const size_t nbytes, const size_t block_size); size_t maced_data_length(const desfirekey_t key, const size_t nbytes); size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int communication_settings); diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 449f144e2..9b80ede51 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -234,9 +234,9 @@ void DesfirePrintContext(DesfireContext *ctx) { PrintAndLogEx(INFO, "Key num: %d Key algo: %s Key[%d]: %s", ctx->keyNum, CLIGetOptionListStr(DesfireAlgoOpts, ctx->keyType), - key_size(ctx->keyType), + desfire_get_key_length(ctx->keyType), sprint_hex(ctx->key, - key_size(ctx->keyType))); + desfire_get_key_length(ctx->keyType))); if (ctx->kdfAlgo != MFDES_KDF_ALGO_NONE) PrintAndLogEx(INFO, "KDF algo: %s KDF input[%d]: %s", CLIGetOptionListStr(DesfireKDFAlgoOpts, ctx->kdfAlgo), ctx->kdfInputLen, sprint_hex(ctx->kdfInput, ctx->kdfInputLen)); @@ -248,9 +248,9 @@ void DesfirePrintContext(DesfireContext *ctx) { if (DesfireIsAuthenticated(ctx)) { PrintAndLogEx(INFO, "Session key MAC [%d]: %s ENC: %s IV [%d]: %s", - key_size(ctx->keyType), - sprint_hex(ctx->sessionKeyMAC, key_size(ctx->keyType)), - sprint_hex(ctx->sessionKeyEnc, key_size(ctx->keyType)), + desfire_get_key_length(ctx->keyType), + sprint_hex(ctx->sessionKeyMAC, desfire_get_key_length(ctx->keyType)), + sprint_hex(ctx->sessionKeyEnc, desfire_get_key_length(ctx->keyType)), desfire_get_key_block_length(ctx->keyType), sprint_hex(ctx->sessionKeyEnc, desfire_get_key_block_length(ctx->keyType))); From d6dc117ed3ac7c55c52a6ea2615f28be05993002 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 14:18:05 +0300 Subject: [PATCH 190/309] mark commands with `new` sign --- client/src/cmdhfmfdes.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 79c770348..d141a22b8 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5311,7 +5311,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"-----------", CmdHelp, IfPm3Iso14443a, "---------------------- " _CYAN_("general") " ----------------------"}, - {"default", CmdHF14ADesDefault, IfPm3Iso14443a, "Set defaults for all the commands"}, + {"default", CmdHF14ADesDefault, IfPm3Iso14443a, "[new]Set defaults for all the commands"}, {"auth", CmdHF14ADesAuth, IfPm3Iso14443a, "Tries a MIFARE DesFire Authentication"}, {"changekey", CmdHF14ADesChangeKey, IfPm3Iso14443a, "Change Key"}, {"chk", CmdHF14aDesChk, IfPm3Iso14443a, "Check keys"}, @@ -5327,8 +5327,8 @@ static command_t CommandTable[] = { {"createaid", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application ID"}, {"deleteaid", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "Delete Application ID"}, {"selectaid", CmdHF14ADesSelectApp, IfPm3Iso14443a, "Select Application ID"}, - {"getaids", CmdHF14ADesGetAIDs, IfPm3Iso14443a, "Get Application IDs list"}, - {"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "Get Applications list"}, + {"getaids", CmdHF14ADesGetAIDs, IfPm3Iso14443a, "[new]Get Application IDs list"}, + {"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "[new]Get Applications list"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("Files") " -----------------------"}, {"changevalue", CmdHF14ADesChangeValue, IfPm3Iso14443a, "Write value of a value file (credit/debit/clear)"}, {"clearfile", CmdHF14ADesClearRecordFile, IfPm3Iso14443a, "Clear record File"}, From 20fe52f8eb2cebe65ebe75683d4ad34ce20f3c4c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Jul 2021 13:42:33 +0200 Subject: [PATCH 191/309] added a picture viewer in QT to be used with `hf emrtd` --- CHANGELOG.md | 1 + client/CMakeLists.txt | 1 + client/Makefile | 10 ++-- client/src/cmdhfemrtd.c | 69 ++++++++++++++++++++++-- client/src/cmdhfemrtd.h | 8 +++ client/src/guidummy.cpp | 12 +++++ client/src/proxgui.cpp | 31 +++++++++++ client/src/proxgui.h | 6 +++ client/src/proxguiqt.cpp | 114 +++++++++++++++++++++++++++++++++++++++ client/src/proxguiqt.h | 28 +++++++++- client/src/ui/image.ui | 33 ++++++++++++ 11 files changed, 306 insertions(+), 7 deletions(-) create mode 100644 client/src/ui/image.ui diff --git a/CHANGELOG.md b/CHANGELOG.md index 41880a244..86b8a4a9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added a picture viewer in QT. To be used with `hf emrtd info` (@iceman1001) - Fix - move des functions to libcrypto (@merlokk) - Added `CLIGetOptionList` to cliparser that makes it easier to implement text options in the cli (@merlokk) - Added experimental support for macOS users utilizing MacPorts instead of Homebrew (@linuxgemini) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index a81682337..f7920b4e0 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -229,6 +229,7 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/uart/uart_posix.c ${PM3_ROOT}/client/src/uart/uart_win32.c ${PM3_ROOT}/client/src/ui/overlays.ui + ${PM3_ROOT}/client/src/ui/image.ui ${PM3_ROOT}/client/src/aiddesfire.c ${PM3_ROOT}/client/src/aidsearch.c ${PM3_ROOT}/client/src/cmdanalyse.c diff --git a/client/Makefile b/client/Makefile index 507a3a7a8..526bf21b0 100644 --- a/client/Makefile +++ b/client/Makefile @@ -657,9 +657,9 @@ OBJS += $(OBJCSRCS:%.m=$(OBJDIR)/%.o) BINS = proxmark3 -CLEAN = $(BINS) src/version_pm3.c src/*.moc.cpp src/ui/ui_overlays.h lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua +CLEAN = $(BINS) src/version_pm3.c src/*.moc.cpp src/ui/ui_overlays.h src/ui/ui_image.h lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua # transition: cleaning also old path stuff -CLEAN += flasher *.moc.cpp ui/ui_overlays.h +CLEAN += flasher *.moc.cpp ui/ui_overlays.h ui/ui_image.h ########### # targets # @@ -675,7 +675,7 @@ proxmark3: $(OBJS) $(STATICLIBS) lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lu $(info [=] LD $@) $(Q)$(LD) $(PM3LDFLAGS) $(OBJS) $(STATICLIBS) $(LDLIBS) -o $@ -src/proxgui.cpp: src/ui/ui_overlays.h +src/proxgui.cpp: src/ui/ui_overlays.h src/ui/ui_image.h src/proxguiqt.moc.cpp: src/proxguiqt.h $(info [-] MOC $@) @@ -685,6 +685,10 @@ src/ui/ui_overlays.h: src/ui/overlays.ui $(info [-] UIC $@) $(Q)$(UIC) $^ > $@ +src/ui/ui_image.h: src/ui/image.ui + $(info [-] UIC $@) + $(Q)$(UIC) $^ > $@ + lualibs/pm3_cmd.lua: ../include/pm3_cmd.h $(info [=] GEN $@) $(Q)awk -f pm3_cmd_h2lua.awk $^ > $@ diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 312099268..2cda5e1da 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -24,6 +24,8 @@ #include "crapto1/crapto1.h" // prng_successor #include "commonutil.h" // num_to_bytes #include "util_posix.h" // msclock +#include "ui.h" // searchhomedirectory +#include "proxgui.h" // Picture Window // Max file size in bytes. Used in several places. // Average EF_DG2 seems to be around 20-25kB or so, but ICAO doesn't set an upper limit @@ -53,6 +55,7 @@ static int emrtd_dump_ef_dg7(uint8_t *file_contents, size_t file_length, const c static int emrtd_dump_ef_sod(uint8_t *file_contents, size_t file_length, const char *path); static int emrtd_print_ef_com_info(uint8_t *data, size_t datalen); static int emrtd_print_ef_dg1_info(uint8_t *data, size_t datalen); +static int emrtd_print_ef_dg2_info(uint8_t *data, size_t datalen); static int emrtd_print_ef_dg11_info(uint8_t *data, size_t datalen); static int emrtd_print_ef_dg12_info(uint8_t *data, size_t datalen); static int emrtd_print_ef_cardaccess_info(uint8_t *data, size_t datalen); @@ -84,7 +87,7 @@ static emrtd_dg_t dg_table[] = { // tag dg# fileid filename desc pace eac req fast parser dumper {0x60, 0, 0x011E, "EF_COM", "Header and Data Group Presence Information", false, false, true, true, emrtd_print_ef_com_info, NULL}, {0x61, 1, 0x0101, "EF_DG1", "Details recorded in MRZ", false, false, true, true, emrtd_print_ef_dg1_info, NULL}, - {0x75, 2, 0x0102, "EF_DG2", "Encoded Face", false, false, true, false, NULL, emrtd_dump_ef_dg2}, + {0x75, 2, 0x0102, "EF_DG2", "Encoded Face", false, false, true, false, emrtd_print_ef_dg2_info, emrtd_dump_ef_dg2}, {0x63, 3, 0x0103, "EF_DG3", "Encoded Finger(s)", false, true, false, false, NULL, NULL}, {0x76, 4, 0x0104, "EF_DG4", "Encoded Eye(s)", false, true, false, false, NULL, NULL}, {0x65, 5, 0x0105, "EF_DG5", "Displayed Portrait", false, false, false, false, NULL, emrtd_dump_ef_dg5}, @@ -1398,6 +1401,65 @@ static int emrtd_print_ef_dg1_info(uint8_t *data, size_t datalen) { return PM3_SUCCESS; } +static int emrtd_print_ef_dg2_info(uint8_t *data, size_t datalen) { + + int offset = 0; + + // This is a hacky impl that just looks for the image header. I'll improve it eventually. + // based on mrpkey.py + // Note: Doing datalen - 6 to account for the longest data we're checking. + // Checks first byte before the rest to reduce overhead + for (offset = 0; offset < datalen - 6; offset++) { + if ((data[offset] == 0xFF && memcmp(jpeg_header, data + offset, 4) == 0) || + (data[offset] == 0x00 && memcmp(jpeg2k_header, data + offset, 6) == 0)) { + datalen = datalen - offset; + break; + } + } + + // If we didn't get any data, return false. + if (datalen == 0) { + return PM3_ESOFT; + } + + bool is_jpg = (data[offset] == 0xFF); + + char *fn = calloc( strlen(dg_table[EF_DG2].filename) + 4 + 1, sizeof(uint8_t)); + if (fn == NULL) + return PM3_EMALLOC; + + sprintf(fn, "%s.%s", dg_table[EF_DG2].filename, (is_jpg) ? "jpg" : "jp2"); + + PrintAndLogEx(DEBUG, "image filename `" _YELLOW_("%s") "`", fn); + + char *path; + if (searchHomeFilePath(&path, NULL, fn, false) != PM3_SUCCESS) { + free(fn); + return PM3_EFILE; + } + free(fn); + + // remove old file + if (fileExists(path)) { + PrintAndLogEx(DEBUG, "Delete old temp file `" _YELLOW_("%s") "`", path); + remove(path); + } + + // temp file. + PrintAndLogEx(DEBUG, "Save temp file `" _YELLOW_("%s") "`", path); + saveFile(path, "", data + offset, datalen); + + PrintAndLogEx(DEBUG, "view temp file `" _YELLOW_("%s") "`", path); + ShowPictureWindow(path); + msleep(500); + + // delete temp file + PrintAndLogEx(DEBUG, "Deleting temp file `" _YELLOW_("%s") "`", path); + remove(path); + //free(path); + return PM3_SUCCESS; +} + static int emrtd_print_ef_dg11_info(uint8_t *data, size_t datalen) { uint8_t taglist[100] = { 0x00 }; size_t taglistlen = 0; @@ -1930,6 +1992,7 @@ int infoHF_EMRTD_offline(const char *path) { if (loadFile_safeEx(filepath, ".BIN", (void **)&data, (size_t *)&datalen, false) == PM3_SUCCESS) { emrtd_print_ef_cardaccess_info(data, datalen); + free(data); } else { PrintAndLogEx(HINT, "The error above this is normal. It just means that your eMRTD lacks PACE."); } @@ -2184,12 +2247,12 @@ static int CmdHFeMRTDInfo(const char *Cmd) { } } uint8_t path[FILENAME_MAX] = { 0x00 }; - bool offline = CLIParamStrToBuf(arg_get_str(ctx, 5), path, sizeof(path), &slen) == 0 && slen > 0; + bool is_offline = CLIParamStrToBuf(arg_get_str(ctx, 5), path, sizeof(path), &slen) == 0 && slen > 0; CLIParserFree(ctx); if (error) { return PM3_ESOFT; } - if (offline) { + if (is_offline) { return infoHF_EMRTD_offline((const char *)path); } else { bool restore_apdu_logging = GetAPDULogging(); diff --git a/client/src/cmdhfemrtd.h b/client/src/cmdhfemrtd.h index 81f59b88c..45d0d28df 100644 --- a/client/src/cmdhfemrtd.h +++ b/client/src/cmdhfemrtd.h @@ -13,6 +13,10 @@ #include "common.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct emrtd_dg_s { uint8_t tag; uint8_t dgnum; @@ -53,4 +57,8 @@ int CmdHFeMRTD(const char *Cmd); int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_available, const char *path); int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_available); int infoHF_EMRTD_offline(const char *path); + +#ifdef __cplusplus +} +#endif #endif diff --git a/client/src/guidummy.cpp b/client/src/guidummy.cpp index 8557b0015..886bc1516 100644 --- a/client/src/guidummy.cpp +++ b/client/src/guidummy.cpp @@ -21,6 +21,18 @@ extern "C" void ShowGraphWindow(void) { extern "C" void HideGraphWindow(void) {} extern "C" void RepaintGraphWindow(void) {} + +extern "C" void ShowPictureWindow(char *fn) { + static int warned = 0; + + if (!warned) { + printf("No GUI in this build!\n"); + warned = 1; + } +} +extern "C" void HidePictureWindow(void) {} +extern "C" void RepaintPictureWindow(void) {} + extern "C" void MainGraphics() {} extern "C" void InitGraphics(int argc, char **argv) {} extern "C" void ExitGraphics(void) {} diff --git a/client/src/proxgui.cpp b/client/src/proxgui.cpp index f8dd10fa4..0fe941133 100644 --- a/client/src/proxgui.cpp +++ b/client/src/proxgui.cpp @@ -40,6 +40,7 @@ extern "C" void ShowGraphWindow(void) { } gui->ShowGraphWindow(); + } extern "C" void HideGraphWindow(void) { @@ -56,6 +57,36 @@ extern "C" void RepaintGraphWindow(void) { gui->RepaintGraphWindow(); } + +// hook up picture viewer +extern "C" void ShowPictureWindow(char *fn) { + if (!gui) { + // Show a notice if X11/XQuartz isn't available +#if defined(__MACH__) && defined(__APPLE__) + PrintAndLogEx(WARNING, "You appear to be on a MacOS device without XQuartz.\nYou may need to install XQuartz (https://www.xquartz.org/) to make the plot work."); +#else + PrintAndLogEx(WARNING, "You appear to be on an environment without an X11 server or without DISPLAY environment variable set.\nPlot may not work until you resolve these issues."); +#endif + return; + } + + gui->ShowPictureWindow(fn); +} + +extern "C" void HidePictureWindow(void) { + if (!gui) + return; + + gui->HidePictureWindow(); +} + +extern "C" void RepaintPictureWindow(void) { + if (!gui) + return; + + gui->RepaintPictureWindow(); +} + extern "C" void MainGraphics(void) { if (!gui) return; diff --git a/client/src/proxgui.h b/client/src/proxgui.h index 887a0e36d..d62c08d39 100644 --- a/client/src/proxgui.h +++ b/client/src/proxgui.h @@ -22,6 +22,12 @@ extern "C" { void ShowGraphWindow(void); void HideGraphWindow(void); void RepaintGraphWindow(void); + +// hook up picture viewer +void ShowPictureWindow(char *fn); +void HidePictureWindow(void); +void RepaintPictureWindow(void); + void MainGraphics(void); void InitGraphics(int argc, char **argv, char *script_cmds_file, char *script_cmd, bool stayInCommandLoop); void ExitGraphics(void); diff --git a/client/src/proxguiqt.cpp b/client/src/proxguiqt.cpp index 6ba6b7ab7..2194b8bdc 100644 --- a/client/src/proxguiqt.cpp +++ b/client/src/proxguiqt.cpp @@ -12,6 +12,7 @@ #include #include #include +//#include #include #include #include @@ -32,6 +33,7 @@ #include "graph.h" #include "cmddata.h" #include "util_darwin.h" +//#include "fileutils.h" extern "C" int preferences_save(void); @@ -54,6 +56,19 @@ void ProxGuiQT::HideGraphWindow(void) { emit HideGraphWindowSignal(); } +// emit picture viewer signals +void ProxGuiQT::ShowPictureWindow(char *fn) { + emit ShowPictureWindowSignal(fn); +} + +void ProxGuiQT::RepaintPictureWindow(void) { + emit RepaintPictureWindowSignal(); +} + +void ProxGuiQT::HidePictureWindow(void) { + emit HidePictureWindowSignal(); +} + void ProxGuiQT::Exit(void) { emit ExitSignal(); } @@ -71,6 +86,7 @@ void ProxGuiQT::_ShowGraphWindow(void) { plotwidget = new ProxWidget(); } plotwidget->show(); + } void ProxGuiQT::_RepaintGraphWindow(void) { @@ -87,10 +103,80 @@ void ProxGuiQT::_HideGraphWindow(void) { plotwidget->hide(); } +// picture viewer +void ProxGuiQT::_ShowPictureWindow(char *fn) { + if (fn == NULL) + return; + size_t slen = strlen(fn); + if (slen == 0) + return; + + char *myfn = (char*)calloc(slen + 1, sizeof(uint8_t)); + if (myfn == NULL) + return; + + memcpy(myfn, fn, slen); + + if (!plotapp) + return; + + if (!pictureWidget) { + +#if defined(__MACH__) && defined(__APPLE__) + makeFocusable(); +#endif + + pictureWidget = new QWidget(); + } + + QPixmap pm; + if(pm.load(myfn) == false){ + qWarning("Failed to load %s", myfn); + } + free(myfn); + free(fn); + + //QPixmap newPixmap = pm.scaled(QSize(50,50), Qt::KeepAspectRatio); + //pm = pm.scaled(pictureController->lbl_pm->size(), Qt::KeepAspectRatio); + + pictureController->lbl_pm->setPixmap(pm); + pictureController->lbl_pm->setScaledContents(false); + pictureController->lbl_pm->setAlignment(Qt::AlignCenter); + + QString s = QString("w: %1 h: %2") + .arg(pm.size().width()) + .arg(pm.size().height() + ); + pictureController->lbl_sz->setText(s); + pictureWidget->show(); +} + +void ProxGuiQT::_RepaintPictureWindow(void) { + if (!plotapp || !pictureWidget) + return; + + pictureWidget->update(); +} + +void ProxGuiQT::_HidePictureWindow(void) { + if (!plotapp || !pictureWidget) + return; + + pictureWidget->hide(); +} + void ProxGuiQT::_Exit(void) { delete this; } +void ProxGuiQT::closeEvent(QCloseEvent *event) { + event->ignore(); + pictureWidget->hide(); +} +void ProxGuiQT::hideEvent(QHideEvent *event) { + pictureWidget->hide(); +} + void ProxGuiQT::_StartProxmarkThread(void) { if (!proxmarkThread) return; @@ -105,11 +191,23 @@ void ProxGuiQT::_StartProxmarkThread(void) { void ProxGuiQT::MainLoop() { plotapp = new QApplication(argc, argv); + // Setup the picture widget + pictureWidget = new QWidget(); + pictureController = new Ui::PictureForm(); + pictureController->setupUi(pictureWidget); + connect(this, SIGNAL(ShowGraphWindowSignal()), this, SLOT(_ShowGraphWindow())); connect(this, SIGNAL(RepaintGraphWindowSignal()), this, SLOT(_RepaintGraphWindow())); connect(this, SIGNAL(HideGraphWindowSignal()), this, SLOT(_HideGraphWindow())); + connect(this, SIGNAL(ExitSignal()), this, SLOT(_Exit())); + // hook up picture viewer signals + connect(this, SIGNAL(ShowPictureWindowSignal(char*)), this, SLOT(_ShowPictureWindow(char*))); + connect(this, SIGNAL(RepaintPictureWindowSignal()), this, SLOT(_RepaintPictureWindow())); + connect(this, SIGNAL(HidePictureWindowSignal()), this, SLOT(_HidePictureWindow())); + + //start proxmark thread after starting event loop QTimer::singleShot(200, this, SLOT(_StartProxmarkThread())); @@ -127,6 +225,18 @@ ProxGuiQT::ProxGuiQT(int argc, char **argv, WorkerThread *wthread) : plotapp(NUL } ProxGuiQT::~ProxGuiQT(void) { + + if (pictureController) { + delete pictureController; + pictureController = NULL; + } + + if (pictureWidget) { + pictureWidget->close(); + delete pictureWidget; + pictureWidget = NULL; + } + if (plotapp) { plotapp->quit(); plotapp = NULL; @@ -197,6 +307,8 @@ void ProxWidget::vchange_dthr_down(int v) { g_useOverlays = true; RepaintGraphWindow(); } + + ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) { this->master = master; // Set the initail postion and size from settings @@ -207,6 +319,7 @@ ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) { // Setup the controller widget controlWidget = new SliderWidget(); //new QWidget(); + opsController = new Ui::Form(); opsController->setupUi(controlWidget); //Due to quirks in QT Designer, we need to fiddle a bit @@ -295,6 +408,7 @@ void ProxWidget::showEvent(QShowEvent *event) { controlWidget->show(); else controlWidget->hide(); + plot->show(); } void ProxWidget::moveEvent(QMoveEvent *event) { diff --git a/client/src/proxguiqt.h b/client/src/proxguiqt.h index 168b1b9eb..513300d89 100644 --- a/client/src/proxguiqt.h +++ b/client/src/proxguiqt.h @@ -22,6 +22,7 @@ #include #include "ui/ui_overlays.h" +#include "ui/ui_image.h" class ProxWidget; @@ -81,8 +82,8 @@ class ProxWidget : public QWidget { ProxGuiQT *master; Plot *plot; Ui::Form *opsController; -// QWidget *controlWidget; SliderWidget *controlWidget; + public: ProxWidget(QWidget *parent = 0, ProxGuiQT *master = NULL); ~ProxWidget(void); @@ -125,6 +126,10 @@ class ProxGuiQT : public QObject { private: QApplication *plotapp; ProxWidget *plotwidget; + + Ui::PictureForm *pictureController; + QWidget *pictureWidget; + int argc; char **argv; //void (*main_func)(void); @@ -136,13 +141,29 @@ class ProxGuiQT : public QObject { void ShowGraphWindow(void); void RepaintGraphWindow(void); void HideGraphWindow(void); + + // hook up picture viewer + void ShowPictureWindow(char *fn); + void HidePictureWindow(void); + void RepaintPictureWindow(void); + void MainLoop(void); void Exit(void); + protected: + void closeEvent(QCloseEvent *event); + void hideEvent(QHideEvent *event); + private slots: void _ShowGraphWindow(void); void _RepaintGraphWindow(void); void _HideGraphWindow(void); + + // hook up picture viewer + void _ShowPictureWindow(char *fn); + void _HidePictureWindow(void); + void _RepaintPictureWindow(void); + void _Exit(void); void _StartProxmarkThread(void); @@ -151,6 +172,11 @@ class ProxGuiQT : public QObject { void RepaintGraphWindowSignal(void); void HideGraphWindowSignal(void); void ExitSignal(void); + + // hook up picture viewer signals + void ShowPictureWindowSignal(char *fn); + void HidePictureWindowSignal(void); + void RepaintPictureWindowSignal(void); }; #endif // PROXGUI_QT diff --git a/client/src/ui/image.ui b/client/src/ui/image.ui new file mode 100644 index 000000000..cb28d7700 --- /dev/null +++ b/client/src/ui/image.ui @@ -0,0 +1,33 @@ + + + PictureForm + + + + 0 + 0 + 400 + 400 + + + + Picture Viewer + + + + + + + + + + Image size + + + + + + + + + From cfb6e98a8e07a1bc0340694453baddc47e082f72 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Jul 2021 13:45:45 +0200 Subject: [PATCH 192/309] forgot to push some android adaptions --- client/android/pm3_main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/android/pm3_main.c b/client/android/pm3_main.c index 74019b0cd..1fe2f7d32 100644 --- a/client/android/pm3_main.c +++ b/client/android/pm3_main.c @@ -60,6 +60,12 @@ void HideGraphWindow(void) {} void RepaintGraphWindow(void) {} +void ShowPictureWindow(char *fn) {} + +void HidePictureWindow(void) {} + +void RepaintPictureWindow(void) {} + int push_cmdscriptfile(char *path, bool stayafter) { return PM3_SUCCESS; } static bool OpenPm3(void) { From be9db1885206cc1d3f41de75be8d373754f04de2 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 15:22:33 +0300 Subject: [PATCH 193/309] fix coverity 350572 --- client/src/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index d141a22b8..f773b4268 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5198,7 +5198,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { if (DesfireIsAuthenticated(&dctx)) { if (verbose) - PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated") , res); + PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated")); } else { return PM3_ESOFT; } From 84eb4e45978c34926988f627e99fad4bfcf1794a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 15:35:53 +0300 Subject: [PATCH 194/309] try to fix coverity --- client/deps/cliparser/cliparser.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/client/deps/cliparser/cliparser.c b/client/deps/cliparser/cliparser.c index ad89856cd..5f5c34bc6 100644 --- a/client/deps/cliparser/cliparser.c +++ b/client/deps/cliparser/cliparser.c @@ -313,10 +313,7 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array int val = -1; int cntr = 0; - for (int i = 0; i < CLI_MAX_OPTLIST_LEN; i++) { - // end of array - if (option_array[i].text == NULL) - break; + for (int i = 0; i < CLI_MAX_OPTLIST_LEN && option_array[i].text != NULL; i++) { // exact match if (strcmp(option_array[i].text, data) == 0) { *value = option_array[i].code; @@ -346,9 +343,7 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array const char *CLIGetOptionListStr(const CLIParserOption *option_array, int value) { static const char *errmsg = "n/a"; - for (int i = 0; i < CLI_MAX_OPTLIST_LEN; i++) { - if (option_array[i].text == NULL) - break; + for (int i = 0; i < CLI_MAX_OPTLIST_LEN && option_array[i].text != NULL; i++) { if (option_array[i].code == value) return option_array[i].text; } From b026fc64f0b2734d9c6a571caf73326a2e97773a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Jul 2021 17:14:14 +0200 Subject: [PATCH 195/309] fix coverity CID 350152 --- client/src/crypto/asn1dump.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/crypto/asn1dump.c b/client/src/crypto/asn1dump.c index 46f7a5beb..f09c4284f 100644 --- a/client/src/crypto/asn1dump.c +++ b/client/src/crypto/asn1dump.c @@ -231,7 +231,7 @@ static void asn1_tag_dump_integer(const struct tlv *tlv, const struct asn1_tag * return; } uint32_t val = asn1_value_integer(tlv, 0, tlv->len * 2); - PrintAndLogEx(NORMAL, " value: %lu (0x%X)", val, val); + PrintAndLogEx(NORMAL, " value: %" PRIu32 " (0x%X)", val, val); } static char *asn1_oid_description(const char *oid, bool with_group_desc) { @@ -327,7 +327,7 @@ bool asn1_tag_dump(const struct tlv *tlv, int level, bool *candump) { */ PrintAndLogEx(INFO, - "%*s-- %02X [%02X] '"_YELLOW_("%s") "'" NOLF + "%*s-- %02X [%02ZX] '"_YELLOW_("%s") "'" NOLF , (level * 4) , " " , tlv->tag From b0c1ce714f96d7cf09eec99d5edf8b9193bff719 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Jul 2021 17:14:47 +0200 Subject: [PATCH 196/309] fix coverity CID 350569 --- client/src/proxguiqt.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/client/src/proxguiqt.cpp b/client/src/proxguiqt.cpp index 2194b8bdc..db092c550 100644 --- a/client/src/proxguiqt.cpp +++ b/client/src/proxguiqt.cpp @@ -105,8 +105,13 @@ void ProxGuiQT::_HideGraphWindow(void) { // picture viewer void ProxGuiQT::_ShowPictureWindow(char *fn) { + + if (!plotapp) + return; + if (fn == NULL) return; + size_t slen = strlen(fn); if (slen == 0) return; @@ -117,9 +122,6 @@ void ProxGuiQT::_ShowPictureWindow(char *fn) { memcpy(myfn, fn, slen); - if (!plotapp) - return; - if (!pictureWidget) { #if defined(__MACH__) && defined(__APPLE__) @@ -191,11 +193,6 @@ void ProxGuiQT::_StartProxmarkThread(void) { void ProxGuiQT::MainLoop() { plotapp = new QApplication(argc, argv); - // Setup the picture widget - pictureWidget = new QWidget(); - pictureController = new Ui::PictureForm(); - pictureController->setupUi(pictureWidget); - connect(this, SIGNAL(ShowGraphWindowSignal()), this, SLOT(_ShowGraphWindow())); connect(this, SIGNAL(RepaintGraphWindowSignal()), this, SLOT(_RepaintGraphWindow())); connect(this, SIGNAL(HideGraphWindowSignal()), this, SLOT(_HideGraphWindow())); @@ -222,6 +219,11 @@ void ProxGuiQT::MainLoop() { ProxGuiQT::ProxGuiQT(int argc, char **argv, WorkerThread *wthread) : plotapp(NULL), plotwidget(NULL), argc(argc), argv(argv), proxmarkThread(wthread) { + + // Setup the picture widget + pictureWidget = new QWidget(); + pictureController = new Ui::PictureForm(); + pictureController->setupUi(pictureWidget); } ProxGuiQT::~ProxGuiQT(void) { From 36af584e1b62288007ccc02566abf4c531e44597 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Jul 2021 17:23:02 +0200 Subject: [PATCH 197/309] fix CID 350569 --- client/src/proxguiqt.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/src/proxguiqt.cpp b/client/src/proxguiqt.cpp index db092c550..eef4f8c9e 100644 --- a/client/src/proxguiqt.cpp +++ b/client/src/proxguiqt.cpp @@ -192,7 +192,12 @@ void ProxGuiQT::_StartProxmarkThread(void) { void ProxGuiQT::MainLoop() { plotapp = new QApplication(argc, argv); - + + // Setup the picture widget + pictureWidget = new QWidget(); + pictureController = new Ui::PictureForm(); + pictureController->setupUi(pictureWidget); + connect(this, SIGNAL(ShowGraphWindowSignal()), this, SLOT(_ShowGraphWindow())); connect(this, SIGNAL(RepaintGraphWindowSignal()), this, SLOT(_RepaintGraphWindow())); connect(this, SIGNAL(HideGraphWindowSignal()), this, SLOT(_HideGraphWindow())); @@ -213,17 +218,12 @@ void ProxGuiQT::MainLoop() { makeUnfocusable(); #endif - plotapp->exec(); } -ProxGuiQT::ProxGuiQT(int argc, char **argv, WorkerThread *wthread) : plotapp(NULL), plotwidget(NULL), - argc(argc), argv(argv), proxmarkThread(wthread) { +ProxGuiQT::ProxGuiQT(int argc, char **argv, WorkerThread *wthread) : + plotapp(NULL), plotwidget(NULL), pictureController(NULL), pictureWidget(NULL), argc(argc), argv(argv), proxmarkThread(wthread) { - // Setup the picture widget - pictureWidget = new QWidget(); - pictureController = new Ui::PictureForm(); - pictureController->setupUi(pictureWidget); } ProxGuiQT::~ProxGuiQT(void) { From 7882a2dbaabed16d08b53a2e42ab8df091252195 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 19:03:41 +0300 Subject: [PATCH 198/309] fix coverity 350557 --- client/src/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index f773b4268..a20f196b4 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5297,7 +5297,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { if (buflen > 0) { PrintAndLogEx(INFO, "----------------------- " _CYAN_("File list") " -----------------------"); for (int i = 0; i < buflen; i++) - PrintAndLogEx(INFO, "AID: %06x ISO file id: %02x%02x ISO DF name[%d]: %s", + PrintAndLogEx(INFO, "AID: %06x ISO file id: %02x%02x ISO DF name[%" PRIu32 "]: %s", DesfireAIDByteToUint(&buf[i * 24 + 1]), buf[i * 24 + 1 + 3], buf[i * 24 + 1 + 4], strlen((char *)&buf[i * 24 + 1 + 5]), From b63a991bc3fe04bff44713cdf829edc893f639b8 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 19:04:41 +0300 Subject: [PATCH 199/309] fix coverity 350561 --- client/src/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index a20f196b4..085a85cff 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5278,7 +5278,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { if (DesfireIsAuthenticated(&dctx)) { if (verbose) - PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated") , res); + PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated")); } else { return PM3_ESOFT; } From d2491d342d05bb4fcf8f18329dd64a06f0b10d83 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 19:31:42 +0300 Subject: [PATCH 200/309] move secure channel functions to separate file --- client/CMakeLists.txt | 1 + client/Makefile | 1 + client/src/mifare/desfirecore.c | 157 +--------------------- client/src/mifare/desfiresecurechan.c | 180 ++++++++++++++++++++++++++ client/src/mifare/desfiresecurechan.h | 27 ++++ 5 files changed, 210 insertions(+), 156 deletions(-) create mode 100644 client/src/mifare/desfiresecurechan.c create mode 100644 client/src/mifare/desfiresecurechan.h diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 0aa5f2dc3..4879e953b 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -226,6 +226,7 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/mifare/mifarehost.c ${PM3_ROOT}/client/src/nfc/ndef.c ${PM3_ROOT}/client/src/mifare/desfire_crypto.c + ${PM3_ROOT}/client/src/mifare/desfiresecurechan.c ${PM3_ROOT}/client/src/mifare/desfirecore.c ${PM3_ROOT}/client/src/uart/uart_posix.c ${PM3_ROOT}/client/src/uart/uart_win32.c diff --git a/client/Makefile b/client/Makefile index 9a2ef3c5c..45ddffe31 100644 --- a/client/Makefile +++ b/client/Makefile @@ -590,6 +590,7 @@ SRCS = aiddesfire.c \ loclass/ikeys.c \ mifare/desfire_crypto.c \ mifare/desfirecore.c \ + mifare/desfiresecurechan.c \ mifare/mad.c \ mifare/mfkey.c \ mifare/mifare4.c \ diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 9b80ede51..ef8830302 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -31,6 +31,7 @@ #include "iso7816/iso7816core.h" // APDU logging #include "util_posix.h" // msleep #include "mifare/desfire_crypto.h" +#include "desfiresecurechan.h" const CLIParserOption DesfireAlgoOpts[] = { {T_DES, "des"}, @@ -543,162 +544,6 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t return PM3_SUCCESS; } -static void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { - uint8_t data[1024] = {0}; - - switch(ctx->keyType) { - case T_DES: - if (ctx->secureChannel == DACd40) { - if (encode) - des_encrypt_ecb(data, srcdata, srcdatalen, ctx->key); - else - des_decrypt_ecb(data, srcdata, srcdatalen, ctx->key); - } if (ctx->secureChannel == DACEV1) { - if (encode) - des_encrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); - else - des_decrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); - } - - if (dstdata) - memcpy(dstdata, data, srcdatalen); - break; - case T_3DES: - break; - case T_3K3DES: - break; - case T_AES: - if (encode) - aes_encode(ctx->IV, ctx->key, srcdata, data, srcdatalen); - else - aes_decode(ctx->IV, ctx->key, srcdata, data, srcdatalen); - if (dstdata) - memcpy(dstdata, data, srcdatalen); - break; - } -} - -static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - - uint8_t data[1024] = {0}; - size_t rlen = 0; - - switch(ctx->commMode) { - case DCMPlain: - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - break; - case DCMMACed: - if (srcdatalen == 0) - break; - - rlen = padded_data_length(srcdatalen, desfire_get_key_block_length(ctx->keyType)); - memcpy(data, srcdata, srcdatalen); - DesfireCryptoEncDec(ctx, data, rlen, NULL, true); - memcpy(dstdata, srcdata, srcdatalen); - memcpy(&dstdata[srcdatalen], ctx->IV, desfire_get_key_block_length(ctx->keyType)); - *dstdatalen = rlen; - break; - case DCMEncrypted: - rlen = padded_data_length(srcdatalen + 2, desfire_get_key_block_length(ctx->keyType)); // 2 - crc16 - memcpy(data, srcdata, srcdatalen); - compute_crc(CRC_14443_A, data, srcdatalen, &data[srcdatalen], &data[srcdatalen + 1]); - DesfireCryptoEncDec(ctx, data, rlen, dstdata, true); - *dstdatalen = rlen; - break; - case DCMNone:; - } -} - -static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - - switch(ctx->commMode) { - case DCMPlain: - case DCMMACed: - - break; - case DCMEncrypted: - break; - case DCMNone:; - } -} - -static void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { - switch(ctx->secureChannel) { - case DACd40: - DesfireSecureChannelEncodeD40(ctx, cmd, srcdata, srcdatalen, dstdata, dstdatalen); - break; - case DACEV1: - DesfireSecureChannelEncodeEV1(ctx, cmd, srcdata, srcdatalen, dstdata, dstdatalen); - break; - case DACEV2: - break; - case DACNone: - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - break; - } -} - -static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - - switch(ctx->commMode) { - case DCMMACed: - - break; - case DCMEncrypted: - break; - case DCMPlain: - case DACNone: - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - break; - } -} - -static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - - switch(ctx->commMode) { - case DCMPlain: - case DCMMACed: - memcpy(dstdata, srcdata, srcdatalen - 8); - *dstdatalen = srcdatalen - 8; - - break; - case DCMEncrypted: - break; - case DACNone: - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - break; - } -} - -static void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { - switch(ctx->secureChannel) { - case DACd40: - DesfireSecureChannelDecodeD40(ctx, srcdata, srcdatalen, respcode, dstdata, dstdatalen); - break; - case DACEV1: - DesfireSecureChannelDecodeEV1(ctx, srcdata, srcdatalen, respcode, dstdata, dstdatalen); - break; - case DACEV2: - break; - case DACNone: - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - break; - } -} - // move data from blockdata [format: ...] to single data block static void DesfireJoinBlockToBytes(uint8_t *blockdata, size_t blockdatacount, size_t blockdatasize, uint8_t *dstdata, size_t *dstdatalen) { *dstdatalen = 0; diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c new file mode 100644 index 000000000..1838a000a --- /dev/null +++ b/client/src/mifare/desfiresecurechan.c @@ -0,0 +1,180 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2010 Romain Tartiere. +// Copyright (C) 2014 Iceman +// Copyright (C) 2021 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency Desfire secure channel functions +//----------------------------------------------------------------------------- + +#include "desfiresecurechan.h" + +#include +#include +#include +#include "ui.h" +#include "crc.h" +#include "crc16.h" // crc16 ccitt +#include "crc32.h" +#include "commonutil.h" +#include "mifare/desfire_crypto.h" + + +void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { + uint8_t data[1024] = {0}; + + switch(ctx->keyType) { + case T_DES: + if (ctx->secureChannel == DACd40) { + if (encode) + des_encrypt_ecb(data, srcdata, srcdatalen, ctx->key); + else + des_decrypt_ecb(data, srcdata, srcdatalen, ctx->key); + } if (ctx->secureChannel == DACEV1) { + if (encode) + des_encrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); + else + des_decrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); + } + + if (dstdata) + memcpy(dstdata, data, srcdatalen); + break; + case T_3DES: + break; + case T_3K3DES: + break; + case T_AES: + if (encode) + aes_encode(ctx->IV, ctx->key, srcdata, data, srcdatalen); + else + aes_decode(ctx->IV, ctx->key, srcdata, data, srcdatalen); + if (dstdata) + memcpy(dstdata, data, srcdatalen); + break; + } +} + +static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + + uint8_t data[1024] = {0}; + size_t rlen = 0; + + switch(ctx->commMode) { + case DCMPlain: + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + break; + case DCMMACed: + if (srcdatalen == 0) + break; + + rlen = padded_data_length(srcdatalen, desfire_get_key_block_length(ctx->keyType)); + memcpy(data, srcdata, srcdatalen); + DesfireCryptoEncDec(ctx, data, rlen, NULL, true); + memcpy(dstdata, srcdata, srcdatalen); + memcpy(&dstdata[srcdatalen], ctx->IV, 4); + *dstdatalen = rlen; + break; + case DCMEncrypted: + rlen = padded_data_length(srcdatalen + 2, desfire_get_key_block_length(ctx->keyType)); // 2 - crc16 + memcpy(data, srcdata, srcdatalen); + compute_crc(CRC_14443_A, data, srcdatalen, &data[srcdatalen], &data[srcdatalen + 1]); + DesfireCryptoEncDec(ctx, data, rlen, dstdata, true); + *dstdatalen = rlen; + break; + case DCMNone:; + } +} + +static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + + switch(ctx->commMode) { + case DCMPlain: + case DCMMACed: + + break; + case DCMEncrypted: + break; + case DCMNone:; + } +} + +void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { + switch(ctx->secureChannel) { + case DACd40: + DesfireSecureChannelEncodeD40(ctx, cmd, srcdata, srcdatalen, dstdata, dstdatalen); + break; + case DACEV1: + DesfireSecureChannelEncodeEV1(ctx, cmd, srcdata, srcdatalen, dstdata, dstdatalen); + break; + case DACEV2: + break; + case DACNone: + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + break; + } +} + +static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + + switch(ctx->commMode) { + case DCMMACed: + + break; + case DCMEncrypted: + break; + case DCMPlain: + case DACNone: + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + break; + } +} + +static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + + switch(ctx->commMode) { + case DCMPlain: + case DCMMACed: + memcpy(dstdata, srcdata, srcdatalen - 8); + *dstdatalen = srcdatalen - 8; + + break; + case DCMEncrypted: + break; + case DACNone: + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + break; + } +} + +void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { + switch(ctx->secureChannel) { + case DACd40: + DesfireSecureChannelDecodeD40(ctx, srcdata, srcdatalen, respcode, dstdata, dstdatalen); + break; + case DACEV1: + DesfireSecureChannelDecodeEV1(ctx, srcdata, srcdatalen, respcode, dstdata, dstdatalen); + break; + case DACEV2: + break; + case DACNone: + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + break; + } +} diff --git a/client/src/mifare/desfiresecurechan.h b/client/src/mifare/desfiresecurechan.h new file mode 100644 index 000000000..df997eb54 --- /dev/null +++ b/client/src/mifare/desfiresecurechan.h @@ -0,0 +1,27 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2010 Romain Tartiere. +// Copyright (C) 2014 Iceman +// Copyright (C) 2021 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency Desfire secure channel functions +//----------------------------------------------------------------------------- + +#ifndef __DESFIRESECURECHAN_H +#define __DESFIRESECURECHAN_H + +#include "common.h" +#include "mifare/desfirecore.h" +#include "mifare/desfire_crypto.h" +#include "mifare/mifare4.h" + +void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode); + +void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen); +void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen); + + +#endif // __DESFIRESECURECHAN_H From 918630e22e67064fbe16b345615c28a271d7d5b7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Jul 2021 19:09:16 +0200 Subject: [PATCH 201/309] fixes closing picture viewer exits client --- client/src/proxguiqt.cpp | 46 +++++++++++++++++++++++++++------------- client/src/proxguiqt.h | 17 +++++++++------ 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/client/src/proxguiqt.cpp b/client/src/proxguiqt.cpp index eef4f8c9e..0f133e052 100644 --- a/client/src/proxguiqt.cpp +++ b/client/src/proxguiqt.cpp @@ -128,7 +128,7 @@ void ProxGuiQT::_ShowPictureWindow(char *fn) { makeFocusable(); #endif - pictureWidget = new QWidget(); + pictureWidget = new PictureWidget(); } QPixmap pm; @@ -171,14 +171,6 @@ void ProxGuiQT::_Exit(void) { delete this; } -void ProxGuiQT::closeEvent(QCloseEvent *event) { - event->ignore(); - pictureWidget->hide(); -} -void ProxGuiQT::hideEvent(QHideEvent *event) { - pictureWidget->hide(); -} - void ProxGuiQT::_StartProxmarkThread(void) { if (!proxmarkThread) return; @@ -194,10 +186,18 @@ void ProxGuiQT::MainLoop() { plotapp = new QApplication(argc, argv); // Setup the picture widget - pictureWidget = new QWidget(); + pictureWidget = new PictureWidget(); pictureController = new Ui::PictureForm(); pictureController->setupUi(pictureWidget); - +// pictureWidget->setAttribute(Qt::WA_DeleteOnClose,true); + + // Set picture widget position if no settings. + if (session.preferences_loaded == false) { + // Move controller widget below plot + //pictureController->move(x(), y() + frameSize().height()); + //pictureController->resize(size().width(), 200); + } + connect(this, SIGNAL(ShowGraphWindowSignal()), this, SLOT(_ShowGraphWindow())); connect(this, SIGNAL(RepaintGraphWindowSignal()), this, SLOT(_RepaintGraphWindow())); connect(this, SIGNAL(HideGraphWindowSignal()), this, SLOT(_HideGraphWindow())); @@ -209,7 +209,6 @@ void ProxGuiQT::MainLoop() { connect(this, SIGNAL(RepaintPictureWindowSignal()), this, SLOT(_RepaintPictureWindow())); connect(this, SIGNAL(HidePictureWindowSignal()), this, SLOT(_HidePictureWindow())); - //start proxmark thread after starting event loop QTimer::singleShot(200, this, SLOT(_StartProxmarkThread())); @@ -245,6 +244,24 @@ ProxGuiQT::~ProxGuiQT(void) { } } +// ------------------------------------------------- +// Slider Widget form based on a class to enable +// Event override functions +// ------------------------------------------------- +PictureWidget::PictureWidget() { + // Set the initail postion and size from settings +// if (session.preferences_loaded) +// setGeometry(session.pw.x, session.pw.y, session.pw.w, session.pw.h); +// else + resize(400, 400); +} + +void PictureWidget::closeEvent(QCloseEvent *event) { + this->hide(); + event->ignore(); +} + + // ------------------------------------------------- // Slider Widget form based on a class to enable // Event override functions @@ -320,8 +337,7 @@ ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) { resize(800, 400); // Setup the controller widget - controlWidget = new SliderWidget(); //new QWidget(); - + controlWidget = new SliderWidget(); opsController = new Ui::Form(); opsController->setupUi(controlWidget); //Due to quirks in QT Designer, we need to fiddle a bit @@ -357,7 +373,7 @@ ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) { show(); // Set Slider/Overlay position if no settings. - if (!session.preferences_loaded) { + if (session.preferences_loaded == false) { // Move controller widget below plot controlWidget->move(x(), y() + frameSize().height()); controlWidget->resize(size().width(), 200); diff --git a/client/src/proxguiqt.h b/client/src/proxguiqt.h index 513300d89..d9f3f204b 100644 --- a/client/src/proxguiqt.h +++ b/client/src/proxguiqt.h @@ -71,6 +71,14 @@ class SliderWidget : public QWidget { SliderWidget(); }; +// Added class for SliderWidget to allow move/resize event override +class PictureWidget : public QWidget { + protected: + void closeEvent(QCloseEvent *event); + public: + PictureWidget(); +}; + /** * The window with plot and controls */ @@ -126,10 +134,9 @@ class ProxGuiQT : public QObject { private: QApplication *plotapp; ProxWidget *plotwidget; - Ui::PictureForm *pictureController; - QWidget *pictureWidget; - + PictureWidget *pictureWidget; + int argc; char **argv; //void (*main_func)(void); @@ -150,10 +157,6 @@ class ProxGuiQT : public QObject { void MainLoop(void); void Exit(void); - protected: - void closeEvent(QCloseEvent *event); - void hideEvent(QHideEvent *event); - private slots: void _ShowGraphWindow(void); void _RepaintGraphWindow(void); From c5faa57833706f027999eea97cc4944373f14220 Mon Sep 17 00:00:00 2001 From: scott4290 Date: Mon, 5 Jul 2021 17:27:05 -0400 Subject: [PATCH 202/309] Update t55xx_default_pwds.dic ID/HID blue copier with a light-blue inlay sticker purchased circa 2014. I tested with two different T5577 codes and the same password was set. --- client/dictionaries/t55xx_default_pwds.dic | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/dictionaries/t55xx_default_pwds.dic b/client/dictionaries/t55xx_default_pwds.dic index ce916dfe8..beeeca8cf 100644 --- a/client/dictionaries/t55xx_default_pwds.dic +++ b/client/dictionaries/t55xx_default_pwds.dic @@ -38,6 +38,8 @@ E9920427 50520901 # iCopy-X 20206666 +# ID/HID CARD COPER SK-663 +65857569 # Default pwd, simple: 00000000 11111111 From 366014706af7b3751e99d79557b622f6150fde04 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 6 Jul 2021 07:56:42 +0200 Subject: [PATCH 203/309] fix hf_msdsal standalone patch from @nexting --- armsrc/Standalone/hf_msdsal.c | 183 ++++++++++++++++++++++------------ 1 file changed, 119 insertions(+), 64 deletions(-) diff --git a/armsrc/Standalone/hf_msdsal.c b/armsrc/Standalone/hf_msdsal.c index b5585c188..dbb033915 100644 --- a/armsrc/Standalone/hf_msdsal.c +++ b/armsrc/Standalone/hf_msdsal.c @@ -52,36 +52,40 @@ void ModInfo(void) { * technologies. Be brave enough to share your knowledge & inspire others. Salvador Mendoza. */ -static uint8_t ppdol [255] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00}; // Default GET PROCESSING + // Default GET PROCESSING +static uint8_t ppdol [255] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00}; + +// Generate GET PROCESSING +static uint8_t treatPDOL(uint8_t *apdu) { -static uint8_t treatPDOL(uint8_t *apdu) { //Generate GET PROCESSING uint8_t plen = 7; - //PDOL Format: 80 A8 00 00 + (PDOL Length+2) + 83 + PDOL Length + PDOL + 00 - for (uint8_t i = 1; i <= apdu[0]; i++) { //Magic stuff, the generation order is important - if (apdu[i] == 0x9F && apdu[i + 1] == 0x66) { //Terminal Transaction Qualifiers + + // PDOL Format: 80 A8 00 00 + (PDOL Length+2) + 83 + PDOL Length + PDOL + 00 + for (uint8_t i = 1; i <= apdu[0]; i++) { // Magic stuff, the generation order is important + if (apdu[i] == 0x9F && apdu[i + 1] == 0x66) { // Terminal Transaction Qualifiers ppdol[plen] = 0xF6; ppdol[plen + 1] = 0x20; ppdol[plen + 2] = 0xC0; ppdol[plen + 3] = 0x00; plen += 4; i += 2; - } else if (apdu[i] == 0x9F && apdu[i + 1] == 0x1A) { //Terminal Country Code + } else if (apdu[i] == 0x9F && apdu[i + 1] == 0x1A) { // Terminal Country Code ppdol[plen] = 0x9F; ppdol[plen + 1] = 0x1A; plen += 2; i += 2; - } else if (apdu[i] == 0x5F && apdu[i + 1] == 0x2A) { //Transaction Currency Code + } else if (apdu[i] == 0x5F && apdu[i + 1] == 0x2A) { // Transaction Currency Code ppdol[plen] = 0x5F; ppdol[plen + 1] = 0x2A; plen += 2; i += 2; - } else if (apdu[i] == 0x9A) { //Transaction Date + } else if (apdu[i] == 0x9A) { // Transaction Date ppdol[plen] = 0x9A; ppdol[plen + 1] = 0x9A; ppdol[plen + 2] = 0x9A; plen += 3; i += 1; - } else if (apdu[i] == 0x95) { //Terminal Verification Results + } else if (apdu[i] == 0x95) { // Terminal Verification Results ppdol[plen] = 0x95; ppdol[plen + 1] = 0x95; ppdol[plen + 2] = 0x95; @@ -89,18 +93,18 @@ static uint8_t treatPDOL(uint8_t *apdu) { //Generate GET PROCES ppdol[plen + 4] = 0x95; plen += 5; i += 1; - } else if (apdu[i] == 0x9C) { //Transaction Type + } else if (apdu[i] == 0x9C) { // Transaction Type ppdol[plen] = 0x9C; plen += 1; i += 1; - } else if (apdu[i] == 0x9F && apdu[i + 1] == 0x37) { //Unpredictable Number + } else if (apdu[i] == 0x9F && apdu[i + 1] == 0x37) { // Unpredictable Number ppdol[plen] = 0x9F; ppdol[plen + 1] = 0x37; ppdol[plen + 2] = 0x9F; ppdol[plen + 3] = 0x37; plen += 4; i += 2; - } else { //To the others, add "0" to complete the format depending on its range + } else { // To the others, add "0" to complete the format depending on its range uint8_t u = apdu[i + 2]; while (u > 0) { ppdol[plen] = 0; @@ -124,16 +128,25 @@ void RunMod(void) { //For reading process iso14a_card_select_t card_a_info; + uint8_t apdubuffer[MAX_FRAME_SIZE] = { 0x00 }; //Specific for Visa cards: select ppse, select Visa AID, GET PROCESSING, SFI - uint8_t ppse[20] = {0x00, 0xA4, 0x04, 0x00, 0x0e, 0x32, 0x50, 0x41, 0x59, 0x2e, 0x53, 0x59, 0x53, 0x2e, 0x44, 0x44, 0x46, 0x30, 0x31, 0x00}; - uint8_t visa[13] = {0x00, 0xA4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0x00}; + uint8_t ppse[20] = { + 0x00, 0xA4, 0x04, 0x00, 0x0e, 0x32, 0x50, 0x41, + 0x59, 0x2e, 0x53, 0x59, 0x53, 0x2e, 0x44, 0x44, + 0x46, 0x30, 0x31, 0x00 + }; + uint8_t visa[13] = { + 0x00, 0xA4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, + 0x00, 0x03, 0x10, 0x10, 0x00 + }; + uint8_t processing [8] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00}; uint8_t sfi[5] = {0x00, 0xb2, 0x01, 0x0c, 0x00}; uint8_t *apdus[4] = {ppse, visa, processing, sfi}; - uint8_t apdusLen [4] = { sizeof(ppse), sizeof(visa), sizeof(processing), sizeof(sfi)}; + uint8_t apduslen[4] = { sizeof(ppse), sizeof(visa), sizeof(processing), sizeof(sfi)}; uint8_t pdol[50], plen = 8; @@ -153,20 +166,15 @@ void RunMod(void) { char token[19] = {0x00}; bool chktoken = false; -//For emulation steps -#define ATQA 0 -#define UIDC1 1 -#define SAKC1 3 -#define RATS 5 -#define SIGNATURE 7 + // Allocate 512 bytes for the dynamic modulation, created when the reader queries for it + // Such a response is less time critical, so we can prepare them on the fly + #define DYNAMIC_RESPONSE_BUFFER_SIZE 64 + #define DYNAMIC_MODULATION_BUFFER_SIZE 512 -// Allocate 512 bytes for the dynamic modulation, created when the reader queries for it -// Such a response is less time critical, so we can prepare them on the fly -#define DYNAMIC_RESPONSE_BUFFER_SIZE 64 -#define DYNAMIC_MODULATION_BUFFER_SIZE 512 - - uint8_t flags = FLAG_4B_UID_IN_DATA; //UID 4 bytes(could be 7 bytes if needed it) - uint8_t data[PM3_CMD_DATA_SIZE] = {0x00}; // in case there is a read command received we shouldn't break + // UID 4 bytes(could be 7 bytes if needed it) + uint8_t flags = FLAG_4B_UID_IN_DATA; + // in case there is a read command received we shouldn't break + uint8_t data[PM3_CMD_DATA_SIZE] = {0x00}; uint8_t visauid[7] = {0x01, 0x02, 0x03, 0x04}; memcpy(data, visauid, 4); @@ -203,7 +211,7 @@ void RunMod(void) { uint8_t state = STATE_READ; - //Checking if the user wants to go directly to emulation mode using a hardcoded track 2 + // Checking if the user wants to go directly to emulation mode using a hardcoded track 2 if (chktoken == true && token[0] != 0x00) { state = STATE_EMU; DbpString(_YELLOW_("[ ") "Initialized emulation mode" _YELLOW_(" ]")); @@ -222,11 +230,14 @@ void RunMod(void) { // Was our button held down or pressed? int button_pressed = BUTTON_HELD(1000); - if (button_pressed == BUTTON_HOLD) //Holding down the button + + if (button_pressed == BUTTON_HOLD) break; - else if (button_pressed == BUTTON_SINGLE_CLICK) { //Pressing one time change between reading & emulation + else if (button_pressed == BUTTON_SINGLE_CLICK) { + // pressing one time change between reading & emulation if (state == STATE_READ) { - if (chktoken == true && token[0] != 0x00) { //Only change to emulation if it saved a track 2 in memory + if (chktoken == true && token[0] != 0x00) { + // only change to emulation if it saved a track 2 in memory state = STATE_EMU; DbpString(_YELLOW_("[ ") "In emulation mode" _YELLOW_(" ]")); } else @@ -254,28 +265,33 @@ void RunMod(void) { chktoken = false; LED_C_OFF(); LED_B_ON(); - uint8_t apdulen = iso14_apdu(apdus[i], (uint16_t) apdusLen[i], false, apdubuffer, NULL); + uint8_t apdulen = iso14_apdu(apdus[i], (uint16_t) apduslen[i], false, apdubuffer, NULL); if (apdulen > 0) { DbpString(_YELLOW_("[ ") "Proxmark command" _YELLOW_(" ]")); - Dbhexdump(apdusLen[i], apdus[i], false); + Dbhexdump(apduslen[i], apdus[i], false); DbpString(_GREEN_("[ ") "Card answer" _GREEN_(" ]")); Dbhexdump(apdulen - 2, apdubuffer, false); DbpString("----"); for (uint8_t u = 0; u < apdulen; u++) { if (i == 1) { - if (apdubuffer[u] == 0x9F && apdubuffer[u + 1] == 0x38) { //Check for PDOL + + // check for PDOL + if (apdubuffer[u] == 0x9F && apdubuffer[u + 1] == 0x38) { for (uint8_t e = 0; e <= apdubuffer[u + 2]; e++) pdol[e] = apdubuffer[u + e + 2]; - plen = treatPDOL(pdol); //Generate a challenge + // generate a challenge + plen = treatPDOL(pdol); apdus[2] = ppdol; - apdusLen[2] = plen; + apduslen[2] = plen; existpdol = true; } } else if (i == 3) { - if (apdubuffer[u] == 0x57 && apdubuffer[u + 1] == 0x13 && !chktoken) { //Find track 2 + + // find track 2 + if (apdubuffer[u] == 0x57 && apdubuffer[u + 1] == 0x13 && !chktoken) { chktoken = true; memcpy(&token, &apdubuffer[u + 2], 19); break; @@ -307,6 +323,7 @@ void RunMod(void) { } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); + } else if (state == STATE_EMU) { LED_A_OFF(); LED_C_ON(); @@ -328,15 +345,18 @@ void RunMod(void) { // We need to listen to the high-frequency, peak-detected path. iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); - int len = 0; // command length - int retval = PM3_SUCCESS; // to check emulation status + // command length + int len = 0; + // to check emulation status + int retval = PM3_SUCCESS; + bool odd_reply = true; clear_trace(); set_tracing(true); for (;;) { LED_B_OFF(); - // Clean receive command buffer + // clean receive command buffer if (!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) { DbpString(_YELLOW_("!!") "Emulator stopped"); retval = PM3_EOPABORTED; @@ -348,50 +368,84 @@ void RunMod(void) { // dynamic_response_info will be in charge of responses dynamic_response_info.response_n = 0; - // Checking the commands order is important and elemental - if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) { // Received a REQUEST - DbpString(_YELLOW_("+") "REQUEST Received"); - p_response = &responses[ATQA]; - } else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) { // Received a HALT + // received a REQUEST + if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) { + odd_reply = !odd_reply; + if (odd_reply) { + p_response = &responses[RESP_INDEX_ATQA]; + } + + // received a HALT + } else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) { DbpString(_YELLOW_("+") "Received a HALT"); p_response = NULL; - } else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) { // Received a WAKEUP //Este!! + + // received a WAKEUP + } else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) { DbpString(_YELLOW_("+") "WAKEUP Received"); - p_response = &responses[ATQA]; prevCmd = 0; - } else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 2) { // Received request for UID (cascade 1) + p_response = &responses[RESP_INDEX_ATQA]; + + // received request for UID (cascade 1) + } else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 2) { DbpString(_YELLOW_("+") "Request for UID C1"); - p_response = &responses[UIDC1]; - } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) { // Received a SELECT (cascade 1) + p_response = &responses[RESP_INDEX_UIDC1]; + + // received a SELECT (cascade 1) + } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) { DbpString(_YELLOW_("+") "Request for SELECT S1"); - p_response = &responses[SAKC1]; - } else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request + p_response = &responses[RESP_INDEX_SAKC1]; + + // received a RATS request + } else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { DbpString(_YELLOW_("+") "Request for RATS"); - p_response = &responses[RATS]; + prevCmd = 0; + p_response = &responses[RESP_INDEX_RATS]; + } else { DbpString(_YELLOW_("[ ") "Card reader command" _YELLOW_(" ]")); Dbhexdump(len, receivedCmd, false); - if (receivedCmd[0] == 0x02 || receivedCmd[0] == 0x03) { //Emulate a Visa MSD(Magnetic stripe data) card + // emulate a Visa MSD(Magnetic stripe data) card + if (receivedCmd[0] == 0x02 || receivedCmd[0] == 0x03) { dynamic_response_info.response[0] = receivedCmd[0]; - //Depending on card reader commands, the Proxmark will answer to fool the reader - if (receivedCmd[2] == 0xA4 && receivedCmd[6] == 0x32 && prevCmd == 0) { //Respond with PPSE - uint8_t ppsea[39] = {0x6F, 0x23, 0x84, 0x0E, 0x32, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31, 0xA5, 0x11, 0xBF, 0x0C, 0x0E, 0x61, 0x0C, 0x4F, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0x87, 0x01, 0x01, 0x90, 0x00}; + // depending on card reader commands, the Proxmark will answer to fool the reader + // respond with PPSE + if (receivedCmd[2] == 0xA4 && receivedCmd[6] == 0x32 && prevCmd == 0) { + uint8_t ppsea[39] = { + 0x6F, 0x23, 0x84, 0x0E, 0x32, 0x50, 0x41, 0x59, + 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, + 0x30, 0x31, 0xA5, 0x11, 0xBF, 0x0C, 0x0E, 0x61, + 0x0C, 0x4F, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03, + 0x10, 0x10, 0x87, 0x01, 0x01, 0x90, 0x00 + }; memcpy(&dynamic_response_info.response[1], ppsea, sizeof(ppsea)); dynamic_response_info.response_n = sizeof(ppsea) + 1; prevCmd++; - } else if (receivedCmd[2] == 0xA4 && receivedCmd[10] == 0x03 && receivedCmd[11] == 0x10 && prevCmd == 1) { //Respond Visa AID - uint8_t visauid_long[34] = {0x6F, 0x1E, 0x84, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0xA5, 0x13, 0x50, 0x0B, 0x56, 0x49, 0x53, 0x41, 0x20, 0x43, 0x52, 0x45, 0x44, 0x49, 0x54, 0x9F, 0x38, 0x03, 0x9F, 0x66, 0x02, 0x90, 0x00}; + + // respond Visa AID + } else if (receivedCmd[2] == 0xA4 && receivedCmd[10] == 0x03 && receivedCmd[11] == 0x10 && prevCmd == 1) { + uint8_t visauid_long[34] = { + 0x6F, 0x1E, 0x84, 0x07, 0xA0, 0x00, 0x00, 0x00, + 0x03, 0x10, 0x10, 0xA5, 0x13, 0x50, 0x0B, 0x56, + 0x49, 0x53, 0x41, 0x20, 0x43, 0x52, 0x45, 0x44, + 0x49, 0x54, 0x9F, 0x38, 0x03, 0x9F, 0x66, 0x02, + 0x90, 0x00 + }; memcpy(&dynamic_response_info.response[1], visauid_long, sizeof(visauid_long)); dynamic_response_info.response_n = sizeof(visauid_long) + 1; prevCmd++; - } else if (receivedCmd[1] == 0x80 && receivedCmd[2] == 0xA8 && receivedCmd[6] == 0x83 && prevCmd == 2) { //GET PROCESSING + + // GET PROCESSING + } else if (receivedCmd[1] == 0x80 && receivedCmd[2] == 0xA8 && receivedCmd[6] == 0x83 && prevCmd == 2) { uint8_t processing_long[10] = {0x80, 0x06, 0x00, 0x80, 0x08, 0x01, 0x01, 0x00, 0x90, 0x00}; memcpy(&dynamic_response_info.response[1], processing_long, sizeof(processing_long)); dynamic_response_info.response_n = sizeof(processing_long) + 1; prevCmd++; - } else if (receivedCmd[1] == 0x00 && receivedCmd[2] == 0xB2 && prevCmd == 3) { //SFI + + // SFI + } else if (receivedCmd[1] == 0x00 && receivedCmd[2] == 0xB2 && prevCmd == 3) { uint8_t last[4] = {0x70, 0x15, 0x57, 0x13}; uint8_t statusapdu[2] = {0x90, 0x00}; uint8_t card[25]; @@ -401,6 +455,7 @@ void RunMod(void) { memcpy(&dynamic_response_info.response[1], card, sizeof(card)); dynamic_response_info.response_n = sizeof(card) + 1; prevCmd++; + } else { uint8_t finished[2] = {0x6f, 0x00}; memcpy(&dynamic_response_info.response[1], finished, sizeof(finished)); @@ -424,7 +479,7 @@ void RunMod(void) { Dbhexdump(dynamic_response_info.response_n, dynamic_response_info.response, false); DbpString("----"); - // Add CRC bytes, always used in ISO 14443A-4 compliant cards + // add CRC bytes, always used in ISO 14443A-4 compliant cards AddCrc14A(dynamic_response_info.response, dynamic_response_info.response_n); dynamic_response_info.response_n += 2; @@ -449,4 +504,4 @@ void RunMod(void) { } DbpString(_YELLOW_("[=]") "exiting"); LEDsoff(); -} +} \ No newline at end of file From 994df2fd9a603bea9b03b1ee68827546a7934ee2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 6 Jul 2021 08:05:10 +0200 Subject: [PATCH 204/309] textual --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86b8a4a9e..c8c37a07c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added one new key from gun cloner found in wild (@scott4290) + - Fix `hf_msdsal` standalone in simulation flow (@netxing) - Added a picture viewer in QT. To be used with `hf emrtd info` (@iceman1001) - Fix - move des functions to libcrypto (@merlokk) - Added `CLIGetOptionList` to cliparser that makes it easier to implement text options in the cli (@merlokk) From 56d7efdbb5ac979f9bd73b54ae9457c97fe437f2 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 6 Jul 2021 12:05:38 +0300 Subject: [PATCH 205/309] move some functions from cipurse to libcrypto --- client/src/cipurse/cipursecrypto.c | 23 ----------------------- client/src/cipurse/cipursecrypto.h | 4 ---- client/src/cipurse/cipursetest.c | 1 + client/src/crypto/libpcrypto.c | 23 +++++++++++++++++++++++ client/src/crypto/libpcrypto.h | 7 +++++++ 5 files changed, 31 insertions(+), 27 deletions(-) diff --git a/client/src/cipurse/cipursecrypto.c b/client/src/cipurse/cipursecrypto.c index 9761fb1e3..cbf084ef4 100644 --- a/client/src/cipurse/cipursecrypto.c +++ b/client/src/cipurse/cipursecrypto.c @@ -40,11 +40,6 @@ uint8_t CipurseCSecurityLevelEnc(CipurseChannelSecurityLevel lvl) { } } -static void bin_xor(uint8_t *d1, uint8_t *d2, size_t len) { - for (size_t i = 0; i < len; i++) - d1[i] = d1[i] ^ d2[i]; -} - static void bin_ext(uint8_t *dst, size_t dstlen, uint8_t *src, size_t srclen) { if (srclen > dstlen) memcpy(dst, &src[srclen - dstlen], dstlen); @@ -218,24 +213,6 @@ bool CipurseCCheckCT(CipurseContext *ctx, uint8_t *CT) { return (memcmp(CT, ctx->CT, CIPURSE_AES_KEY_LENGTH) == 0); } -void AddISO9797M2Padding(uint8_t *ddata, size_t *ddatalen, uint8_t *sdata, size_t sdatalen, size_t blocklen) { - *ddatalen = sdatalen + 1; - *ddatalen += blocklen - *ddatalen % blocklen; - memset(ddata, 0, *ddatalen); - memcpy(ddata, sdata, sdatalen); - ddata[sdatalen] = ISO9797_M2_PAD_BYTE; -} - -size_t FindISO9797M2PaddingDataLen(uint8_t *data, size_t datalen) { - for (int i = datalen; i > 0; i--) { - if (data[i - 1] == 0x80) - return i - 1; - if (data[i - 1] != 0x00) - return 0; - } - return 0; -} - static uint16_t CipurseCComputeMICCRC(uint8_t *data, size_t len) { uint16_t initCRC = 0x6363; for (size_t i = 0; i < len; i++) { diff --git a/client/src/cipurse/cipursecrypto.h b/client/src/cipurse/cipursecrypto.h index 7790eb600..aba244830 100644 --- a/client/src/cipurse/cipursecrypto.h +++ b/client/src/cipurse/cipursecrypto.h @@ -21,7 +21,6 @@ #define CIPURSE_MAC_LENGTH 8 #define CIPURSE_MIC_LENGTH 4 #define CIPURSE_POLY 0x35b088cce172UL -#define ISO9797_M2_PAD_BYTE 0x80 #define member_size(type, member) sizeof(((type *)0)->member) @@ -66,9 +65,6 @@ bool CipurseCCheckCT(CipurseContext *ctx, uint8_t *CT); void CipurseCChannelSetSecurityLevels(CipurseContext *ctx, CipurseChannelSecurityLevel req, CipurseChannelSecurityLevel resp); bool isCipurseCChannelSecuritySet(CipurseContext *ctx); -void AddISO9797M2Padding(uint8_t *ddata, size_t *ddatalen, uint8_t *sdata, size_t sdatalen, size_t blocklen); -size_t FindISO9797M2PaddingDataLen(uint8_t *data, size_t datalen); - void CipurseCGenerateMAC(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *mac); void CipurseCCalcMACPadded(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *mac); bool CipurseCCheckMACPadded(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *mac); diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index 6ccd4f91d..5de6be161 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -14,6 +14,7 @@ #include // memcpy memset #include "fileutils.h" +#include "crypto/libpcrypto.h" #include "cipurse/cipursecrypto.h" #include "cipurse/cipursecore.h" diff --git a/client/src/crypto/libpcrypto.c b/client/src/crypto/libpcrypto.c index af15c1f5e..32686b199 100644 --- a/client/src/crypto/libpcrypto.c +++ b/client/src/crypto/libpcrypto.c @@ -536,3 +536,26 @@ exit: PrintAndLogEx(NORMAL, _RED_("failed\n")); return res; } + +void bin_xor(uint8_t *d1, uint8_t *d2, size_t len) { + for (size_t i = 0; i < len; i++) + d1[i] = d1[i] ^ d2[i]; +} + +void AddISO9797M2Padding(uint8_t *ddata, size_t *ddatalen, uint8_t *sdata, size_t sdatalen, size_t blocklen) { + *ddatalen = sdatalen + 1; + *ddatalen += blocklen - *ddatalen % blocklen; + memset(ddata, 0, *ddatalen); + memcpy(ddata, sdata, sdatalen); + ddata[sdatalen] = ISO9797_M2_PAD_BYTE; +} + +size_t FindISO9797M2PaddingDataLen(uint8_t *data, size_t datalen) { + for (int i = datalen; i > 0; i--) { + if (data[i - 1] == 0x80) + return i - 1; + if (data[i - 1] != 0x00) + return 0; + } + return 0; +} diff --git a/client/src/crypto/libpcrypto.h b/client/src/crypto/libpcrypto.h index d5f7b809b..3f3bdb45b 100644 --- a/client/src/crypto/libpcrypto.h +++ b/client/src/crypto/libpcrypto.h @@ -42,4 +42,11 @@ char *ecdsa_get_error(int ret); int ecdsa_nist_test(bool verbose); +void bin_xor(uint8_t *d1, uint8_t *d2, size_t len); + +#define ISO9797_M2_PAD_BYTE 0x80 +void AddISO9797M2Padding(uint8_t *ddata, size_t *ddatalen, uint8_t *sdata, size_t sdatalen, size_t blocklen); +size_t FindISO9797M2PaddingDataLen(uint8_t *data, size_t datalen); + + #endif /* libpcrypto.h */ From 0a51eb445d3f93346de4aa6d059c1177fb0b8ad7 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 6 Jul 2021 12:05:59 +0300 Subject: [PATCH 206/309] add mac sketch --- client/src/mifare/desfiresecurechan.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 1838a000a..90aa643ce 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -22,7 +22,6 @@ #include "commonutil.h" #include "mifare/desfire_crypto.h" - void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { uint8_t data[1024] = {0}; @@ -93,13 +92,25 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint } static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { + uint8_t data[1024] = {0}; + size_t rlen = 0; + memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; switch(ctx->commMode) { case DCMPlain: case DCMMACed: + data[0] = cmd; + rlen = padded_data_length(srcdatalen + 1, desfire_get_key_block_length(ctx->keyType)); + memcpy(&data[1], srcdata, srcdatalen); + DesfireCryptoEncDec(ctx, data, rlen, NULL, true); + memcpy(dstdata, srcdata, srcdatalen); + if (srcdatalen != 0 && ctx->commMode == DCMMACed) { + memcpy(&dstdata[srcdatalen], ctx->IV, 4); + *dstdatalen = rlen; + } break; case DCMEncrypted: break; From 20696fb44a408abe31e852129af3a4777632f886 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 6 Jul 2021 12:16:19 +0300 Subject: [PATCH 207/309] make style --- client/deps/cliparser/cliparser.c | 16 +-- client/src/cmdhfemrtd.c | 4 +- client/src/cmdhfmfdes.c | 106 +++++++++--------- client/src/mifare/desfire_crypto.c | 14 ++- client/src/mifare/desfire_crypto.h | 4 +- client/src/mifare/desfirecore.c | 152 +++++++++++++------------- client/src/mifare/desfirecore.h | 6 +- client/src/mifare/desfiresecurechan.c | 39 ++++--- doc/commands.json | 102 +++++++++++++---- doc/commands.md | 3 + 10 files changed, 260 insertions(+), 186 deletions(-) diff --git a/client/deps/cliparser/cliparser.c b/client/deps/cliparser/cliparser.c index ad89856cd..93636a02b 100644 --- a/client/deps/cliparser/cliparser.c +++ b/client/deps/cliparser/cliparser.c @@ -304,13 +304,13 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array int res = CLIParamStrToBuf(argstr, (uint8_t *)data, sizeof(data), &datalen); if (res) return res; - + // no data to check - we do not touch *value, just return if (datalen == 0) return 0; - + str_lower(data); - + int val = -1; int cntr = 0; for (int i = 0; i < CLI_MAX_OPTLIST_LEN; i++) { @@ -328,7 +328,7 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array cntr++; } } - + // check partial match if (cntr == 0) { PrintAndLogEx(ERR, "Parameter error: No similar option to `%s`. Valid options: %s\n", argstr->sval[0], argstr->hdr.datatype); @@ -338,14 +338,14 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array PrintAndLogEx(ERR, "Parameter error: Several options fit to `%s`. Valid options: %s\n", argstr->sval[0], argstr->hdr.datatype); return 21; } - - *value = val; - return 0; + + *value = val; + return 0; } const char *CLIGetOptionListStr(const CLIParserOption *option_array, int value) { static const char *errmsg = "n/a"; - + for (int i = 0; i < CLI_MAX_OPTLIST_LEN; i++) { if (option_array[i].text == NULL) break; diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 2cda5e1da..d9f487ec8 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1424,7 +1424,7 @@ static int emrtd_print_ef_dg2_info(uint8_t *data, size_t datalen) { bool is_jpg = (data[offset] == 0xFF); - char *fn = calloc( strlen(dg_table[EF_DG2].filename) + 4 + 1, sizeof(uint8_t)); + char *fn = calloc(strlen(dg_table[EF_DG2].filename) + 4 + 1, sizeof(uint8_t)); if (fn == NULL) return PM3_EMALLOC; @@ -1435,7 +1435,7 @@ static int emrtd_print_ef_dg2_info(uint8_t *data, size_t datalen) { char *path; if (searchHomeFilePath(&path, NULL, fn, false) != PM3_SUCCESS) { free(fn); - return PM3_EFILE; + return PM3_EFILE; } free(fn); diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 085a85cff..4204b8a3c 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4998,23 +4998,23 @@ static int CmdHF14aDesMAD(const char *Cmd) { return PM3_SUCCESS; } */ -static uint8_t defaultKeyNum = 0; +static uint8_t defaultKeyNum = 0; static enum DESFIRE_CRYPTOALGO defaultAlgoId = T_DES; static uint8_t defaultKey[DESFIRE_MAX_KEY_SIZE] = {0}; static int defaultKdfAlgo = MFDES_KDF_ALGO_NONE; static int defaultKdfInputLen = 0; static uint8_t defaultKdfInput[50] = {0}; -static DesfireSecureChannel defaultSecureChannel = DACEV1; -static DesfireCommandSet defaultCommSet = DCCNativeISO; +static DesfireSecureChannel defaultSecureChannel = DACEV1; +static DesfireCommandSet defaultCommSet = DCCNativeISO; static DesfireCommunicationMode defaultCommMode = DCMPlain; -static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dctx, - uint8_t keynoid, uint8_t algoid, uint8_t keyid, - uint8_t kdfid, uint8_t kdfiid, - uint8_t cmodeid, uint8_t ccsetid, uint8_t schannid, - int *securechannel) { - - uint8_t keynum = defaultKeyNum; +static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dctx, + uint8_t keynoid, uint8_t algoid, uint8_t keyid, + uint8_t kdfid, uint8_t kdfiid, + uint8_t cmodeid, uint8_t ccsetid, uint8_t schannid, + int *securechannel) { + + uint8_t keynum = defaultKeyNum; int algores = defaultAlgoId; uint8_t key[DESFIRE_MAX_KEY_SIZE] = {0}; memcpy(key, defaultKey, DESFIRE_MAX_KEY_SIZE); @@ -5029,17 +5029,17 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct if (keynoid) { keynum = arg_get_int_def(ctx, keynoid, keynum); } - + if (algoid) { if (CLIGetOptionList(arg_get_str(ctx, algoid), DesfireAlgoOpts, &algores)) - return PM3_ESOFT; + return PM3_ESOFT; } - + if (keyid) { int keylen = 0; uint8_t keydata[200] = {0}; if (CLIParamHexToBuf(arg_get_str(ctx, keyid), keydata, sizeof(keydata), &keylen)) - return PM3_ESOFT; + return PM3_ESOFT; if (keylen && keylen != desfire_get_key_length(algores)) { PrintAndLogEx(ERR, "%s key must have %d bytes length instead of %d.", CLIGetOptionListStr(DesfireAlgoOpts, algores), desfire_get_key_length(algores), keylen); return PM3_EINVARG; @@ -5047,45 +5047,45 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct if (keylen) memcpy(key, keydata, keylen); } - + if (kdfid) { if (CLIGetOptionList(arg_get_str(ctx, kdfid), DesfireKDFAlgoOpts, &kdfAlgo)) - return PM3_ESOFT; + return PM3_ESOFT; } - + if (kdfiid) { int datalen = kdfInputLen; uint8_t data[200] = {0}; if (CLIParamHexToBuf(arg_get_str(ctx, kdfiid), data, sizeof(data), &datalen)) - return PM3_ESOFT; + return PM3_ESOFT; if (datalen) { kdfInputLen = datalen; memcpy(kdfInput, data, datalen); } } - + if (cmodeid) { if (CLIGetOptionList(arg_get_str(ctx, cmodeid), DesfireCommunicationModeOpts, &commmode)) - return PM3_ESOFT; + return PM3_ESOFT; } if (ccsetid) { if (CLIGetOptionList(arg_get_str(ctx, ccsetid), DesfireCommandSetOpts, &commset)) - return PM3_ESOFT; + return PM3_ESOFT; } if (schannid) { if (CLIGetOptionList(arg_get_str(ctx, schannid), DesfireSecureChannelOpts, &secchann)) - return PM3_ESOFT; + return PM3_ESOFT; } - + DesfireSetKey(dctx, keynum, algores, key); DesfireSetKdf(dctx, kdfAlgo, kdfInput, kdfInputLen); DesfireSetCommandSet(dctx, commset); DesfireSetCommMode(dctx, commmode); if (securechannel) *securechannel = secchann; - + return PM3_SUCCESS; } @@ -5116,17 +5116,17 @@ static int CmdHF14ADesDefault(const char *Cmd) { CLIParserFree(ctx); return res; } - + CLIParserFree(ctx); - - defaultKeyNum = dctx.keyNum; + + defaultKeyNum = dctx.keyNum; defaultAlgoId = dctx.keyType; memcpy(defaultKey, dctx.key, DESFIRE_MAX_KEY_SIZE); defaultKdfAlgo = dctx.kdfAlgo; defaultKdfInputLen = dctx.kdfInputLen; memcpy(defaultKdfInput, dctx.kdfInput, sizeof(dctx.kdfInput)); - defaultSecureChannel = securechann; - defaultCommSet = dctx.cmdSet; + defaultSecureChannel = securechann; + defaultCommSet = dctx.cmdSet; defaultCommMode = dctx.commMode; PrintAndLogEx(INFO, "-----------" _CYAN_("Default parameters") "---------------------------------"); @@ -5139,7 +5139,7 @@ static int CmdHF14ADesDefault(const char *Cmd) { PrintAndLogEx(INFO, "Secure chan : %s", CLIGetOptionListStr(DesfireSecureChannelOpts, defaultSecureChannel)); PrintAndLogEx(INFO, "Command set : %s", CLIGetOptionListStr(DesfireCommandSetOpts, defaultCommSet)); PrintAndLogEx(INFO, "Comm mode : %s", CLIGetOptionListStr(DesfireCommunicationModeOpts, defaultCommMode)); - + return PM3_SUCCESS; } @@ -5167,7 +5167,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - + DesfireContext dctx; int securechann = defaultSecureChannel; int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, &securechann); @@ -5175,27 +5175,27 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { CLIParserFree(ctx); return res; } - + SetAPDULogging(APDULogging); CLIParserFree(ctx); - + if (verbose) DesfirePrintContext(&dctx); - + res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); DropField(); return PM3_ESOFT; } - + res = DesfireAuthenticate(&dctx, securechann); //DACd40 DACEV1 if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } - + if (DesfireIsAuthenticated(&dctx)) { if (verbose) PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated")); @@ -5205,20 +5205,20 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { uint8_t buf[APDU_RES_LEN] = {0}; size_t buflen = 0; - + res = DesfireGetAIDList(&dctx, buf, &buflen); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire GetAIDList command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } - + if (buflen >= 3) { PrintAndLogEx(INFO, "---- " _CYAN_("AID list") " ----"); for (int i = 0; i < buflen; i += 3) PrintAndLogEx(INFO, "AID: %06x", DesfireAIDByteToUint(&buf[i])); } - + DropField(); return PM3_SUCCESS; } @@ -5247,7 +5247,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - + DesfireContext dctx; int securechann = defaultSecureChannel; int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, &securechann); @@ -5255,27 +5255,27 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { CLIParserFree(ctx); return res; } - + SetAPDULogging(APDULogging); CLIParserFree(ctx); if (verbose) DesfirePrintContext(&dctx); - + res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); DropField(); return PM3_ESOFT; } - - res = DesfireAuthenticate(&dctx, securechann); + + res = DesfireAuthenticate(&dctx, securechann); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } - + if (DesfireIsAuthenticated(&dctx)) { if (verbose) PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated")); @@ -5285,7 +5285,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { uint8_t buf[APDU_RES_LEN] = {0}; size_t buflen = 0; - + // result bytes: 3, 2, 1-16. total record size = 24 res = DesfireGetDFList(&dctx, buf, &buflen); if (res != PM3_SUCCESS) { @@ -5293,17 +5293,17 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { DropField(); return PM3_ESOFT; } - + if (buflen > 0) { PrintAndLogEx(INFO, "----------------------- " _CYAN_("File list") " -----------------------"); for (int i = 0; i < buflen; i++) - PrintAndLogEx(INFO, "AID: %06x ISO file id: %02x%02x ISO DF name[%" PRIu32 "]: %s", - DesfireAIDByteToUint(&buf[i * 24 + 1]), - buf[i * 24 + 1 + 3], buf[i * 24 + 1 + 4], - strlen((char *)&buf[i * 24 + 1 + 5]), - &buf[i * 24 + 1 + 5]); + PrintAndLogEx(INFO, "AID: %06x ISO file id: %02x%02x ISO DF name[%" PRIu32 "]: %s", + DesfireAIDByteToUint(&buf[i * 24 + 1]), + buf[i * 24 + 1 + 3], buf[i * 24 + 1 + 4], + strlen((char *)&buf[i * 24 + 1 + 5]), + &buf[i * 24 + 1 + 5]); } - + DropField(); return PM3_SUCCESS; } diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 2414d83ef..935083ab4 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -31,7 +31,7 @@ #include #include #include "commonutil.h" -#include "crypto/libpcrypto.h" +#include "crypto/libpcrypto.h" #include "aes.h" #include "des.h" #include "ui.h" @@ -55,10 +55,14 @@ static inline void update_key_schedules(desfirekey_t key) { int desfire_get_key_length(enum DESFIRE_CRYPTOALGO key_type) { switch (key_type) { - case T_DES: return 8; - case T_3DES: return 16; - case T_3K3DES: return 24; - case T_AES: return 16; + case T_DES: + return 8; + case T_3DES: + return 16; + case T_3K3DES: + return 24; + case T_AES: + return 16; } return 0; } diff --git a/client/src/mifare/desfire_crypto.h b/client/src/mifare/desfire_crypto.h index 0d3baa5c3..71f3acb23 100644 --- a/client/src/mifare/desfire_crypto.h +++ b/client/src/mifare/desfire_crypto.h @@ -17,8 +17,8 @@ * * $Id$ */ - - #ifndef __DESFIRE_CRYPTO_H + +#ifndef __DESFIRE_CRYPTO_H #define __DESFIRE_CRYPTO_H #include "common.h" diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index ef8830302..9c4bb721b 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -207,7 +207,7 @@ void DesfireClearContext(DesfireContext *ctx) { ctx->keyNum = 0; ctx->keyType = T_DES; memset(ctx->key, 0, sizeof(ctx->key)); - + ctx->secureChannel = DACNone; ctx->cmdSet = DCCNative; ctx->commMode = DCMNone; @@ -226,41 +226,41 @@ void DesfireClearSession(DesfireContext *ctx) { memset(ctx->sessionKeyMAC, 0, sizeof(ctx->sessionKeyMAC)); memset(ctx->sessionKeyEnc, 0, sizeof(ctx->sessionKeyEnc)); memset(ctx->lastIV, 0, sizeof(ctx->lastIV)); - ctx->cntrTx = 0; + ctx->cntrTx = 0; ctx->cntrRx = 0; memset(ctx->TI, 0, sizeof(ctx->TI)); } void DesfirePrintContext(DesfireContext *ctx) { - PrintAndLogEx(INFO, "Key num: %d Key algo: %s Key[%d]: %s", - ctx->keyNum, - CLIGetOptionListStr(DesfireAlgoOpts, ctx->keyType), - desfire_get_key_length(ctx->keyType), - sprint_hex(ctx->key, - desfire_get_key_length(ctx->keyType))); - + PrintAndLogEx(INFO, "Key num: %d Key algo: %s Key[%d]: %s", + ctx->keyNum, + CLIGetOptionListStr(DesfireAlgoOpts, ctx->keyType), + desfire_get_key_length(ctx->keyType), + sprint_hex(ctx->key, + desfire_get_key_length(ctx->keyType))); + if (ctx->kdfAlgo != MFDES_KDF_ALGO_NONE) PrintAndLogEx(INFO, "KDF algo: %s KDF input[%d]: %s", CLIGetOptionListStr(DesfireKDFAlgoOpts, ctx->kdfAlgo), ctx->kdfInputLen, sprint_hex(ctx->kdfInput, ctx->kdfInputLen)); - - PrintAndLogEx(INFO, "Secure channel: %s Command set: %s Communication mode: %s", - CLIGetOptionListStr(DesfireSecureChannelOpts, ctx->secureChannel), - CLIGetOptionListStr(DesfireCommandSetOpts, ctx->cmdSet), - CLIGetOptionListStr(DesfireCommunicationModeOpts, ctx->commMode)); - + + PrintAndLogEx(INFO, "Secure channel: %s Command set: %s Communication mode: %s", + CLIGetOptionListStr(DesfireSecureChannelOpts, ctx->secureChannel), + CLIGetOptionListStr(DesfireCommandSetOpts, ctx->cmdSet), + CLIGetOptionListStr(DesfireCommunicationModeOpts, ctx->commMode)); + if (DesfireIsAuthenticated(ctx)) { - PrintAndLogEx(INFO, "Session key MAC [%d]: %s ENC: %s IV [%d]: %s", - desfire_get_key_length(ctx->keyType), - sprint_hex(ctx->sessionKeyMAC, desfire_get_key_length(ctx->keyType)), - sprint_hex(ctx->sessionKeyEnc, desfire_get_key_length(ctx->keyType)), - desfire_get_key_block_length(ctx->keyType), - sprint_hex(ctx->sessionKeyEnc, desfire_get_key_block_length(ctx->keyType))); - + PrintAndLogEx(INFO, "Session key MAC [%d]: %s ENC: %s IV [%d]: %s", + desfire_get_key_length(ctx->keyType), + sprint_hex(ctx->sessionKeyMAC, desfire_get_key_length(ctx->keyType)), + sprint_hex(ctx->sessionKeyEnc, desfire_get_key_length(ctx->keyType)), + desfire_get_key_block_length(ctx->keyType), + sprint_hex(ctx->sessionKeyEnc, desfire_get_key_block_length(ctx->keyType))); + } - } +} void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key) { DesfireClearContext(ctx); - + ctx->keyNum = keyNum; ctx->keyType = keyType; memcpy(ctx->key, key, desfire_get_key_length(keyType)); @@ -322,11 +322,11 @@ static int DESFIRESendApdu(bool activate_field, sAPDU apdu, uint8_t *result, uin if (sw) *sw = isw; - if (isw != 0x9000 && - isw != DESFIRE_GET_ISO_STATUS(MFDES_S_OPERATION_OK) && - isw != DESFIRE_GET_ISO_STATUS(MFDES_S_SIGNATURE) && - isw != DESFIRE_GET_ISO_STATUS(MFDES_S_ADDITIONAL_FRAME) && - isw != DESFIRE_GET_ISO_STATUS(MFDES_S_NO_CHANGES)) { + if (isw != 0x9000 && + isw != DESFIRE_GET_ISO_STATUS(MFDES_S_OPERATION_OK) && + isw != DESFIRE_GET_ISO_STATUS(MFDES_S_SIGNATURE) && + isw != DESFIRE_GET_ISO_STATUS(MFDES_S_ADDITIONAL_FRAME) && + isw != DESFIRE_GET_ISO_STATUS(MFDES_S_NO_CHANGES)) { if (GetAPDULogging()) { if (isw >> 8 == 0x61) { PrintAndLogEx(ERR, "APDU chaining len: 0x%02x -->", isw & 0xff); @@ -343,7 +343,7 @@ static int DESFIRESendApdu(bool activate_field, sAPDU apdu, uint8_t *result, uin static int DESFIRESendRaw(bool activate_field, uint8_t *data, size_t datalen, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint8_t *respcode) { *result_len = 0; if (respcode) *respcode = 0xff; - + if (activate_field) { DropField(); msleep(50); @@ -369,21 +369,21 @@ static int DESFIRESendRaw(bool activate_field, uint8_t *data, size_t datalen, ui if (respcode) *respcode = rcode; memmove(&result[0], &result[1], *result_len); - if (rcode != MFDES_S_OPERATION_OK && - rcode != MFDES_S_SIGNATURE && - rcode != MFDES_S_ADDITIONAL_FRAME && - rcode != MFDES_S_NO_CHANGES) { + if (rcode != MFDES_S_OPERATION_OK && + rcode != MFDES_S_SIGNATURE && + rcode != MFDES_S_ADDITIONAL_FRAME && + rcode != MFDES_S_NO_CHANGES) { if (GetAPDULogging()) - PrintAndLogEx(ERR, "Command (%02x) ERROR: 0x%02x", data[0], rcode); + PrintAndLogEx(ERR, "Command (%02x) ERROR: 0x%02x", data[0], rcode); return PM3_EAPDU_FAIL; } return PM3_SUCCESS; } static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { - if (resplen) + if (resplen) *resplen = 0; - if (respcode) + if (respcode) *respcode = 0xff; uint8_t buf[255 * 5] = {0x00}; @@ -397,14 +397,14 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8 cdata[0] = cmd; memcpy(&cdata[1], data, datalen); cdatalen = datalen + 1; - + int res = DESFIRESendRaw(activate_field, cdata, cdatalen, buf, sizeof(buf), &buflen, &rcode); if (res != PM3_SUCCESS) { uint16_t ssw = DESFIRE_GET_ISO_STATUS(rcode); PrintAndLogEx(DEBUG, "error DESFIRESendRaw %s", DesfireGetErrorString(res, &ssw)); return res; } - + if (resp) { if (splitbysize) { resp[0] = buflen; @@ -419,8 +419,8 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8 pos += buflen; if (!enable_chaining) { if (rcode == MFDES_S_OPERATION_OK || - rcode == MFDES_ADDITIONAL_FRAME) { - if (resplen) + rcode == MFDES_ADDITIONAL_FRAME) { + if (resplen) *resplen = pos; } return PM3_SUCCESS; @@ -456,13 +456,13 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8 if (resplen) *resplen = (splitbysize) ? i : pos; - return PM3_SUCCESS; + return PM3_SUCCESS; } static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { - if (resplen) + if (resplen) *resplen = 0; - if (respcode) + if (respcode) *respcode = 0xff; uint16_t sw = 0; @@ -484,7 +484,7 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t PrintAndLogEx(DEBUG, "error DESFIRESendApdu %s", DesfireGetErrorString(res, &sw)); return res; } - + if (respcode != NULL && ((sw & 0xff00) == 0x9100)) *respcode = sw & 0xff; @@ -500,8 +500,8 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t pos += buflen; if (!enable_chaining) { if (sw == DESFIRE_GET_ISO_STATUS(MFDES_S_OPERATION_OK) || - sw == DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) { - if (resplen) + sw == DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) { + if (resplen) *resplen = pos; } return PM3_SUCCESS; @@ -541,23 +541,23 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t if (resplen) *resplen = (splitbysize) ? i : pos; - return PM3_SUCCESS; + return PM3_SUCCESS; } // move data from blockdata [format: ...] to single data block static void DesfireJoinBlockToBytes(uint8_t *blockdata, size_t blockdatacount, size_t blockdatasize, uint8_t *dstdata, size_t *dstdatalen) { *dstdatalen = 0; - for(int i = 0; i < blockdatacount; i++) { + for (int i = 0; i < blockdatacount; i++) { memcpy(&dstdata[*dstdatalen], &blockdata[i * blockdatasize + 1], blockdata[i * blockdatasize]); *dstdatalen += blockdata[i * blockdatasize]; } } -// move data from single data block to blockdata [format: ...] +// move data from single data block to blockdata [format: ...] // lengths in the blockdata is not changed. result - in the blockdata static void DesfireSplitBytesToBlock(uint8_t *blockdata, size_t *blockdatacount, size_t blockdatasize, uint8_t *dstdata, size_t dstdatalen) { size_t len = 0; - for(int i = 0; i < *blockdatacount; i++) { + for (int i = 0; i < *blockdatacount; i++) { size_t tlen = len + blockdata[i * blockdatasize]; if (tlen > dstdatalen) tlen = dstdatalen; @@ -572,20 +572,20 @@ static void DesfireSplitBytesToBlock(uint8_t *blockdata, size_t *blockdatacount, int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { int res = PM3_SUCCESS; - + uint8_t databuf[250 * 5] = {0}; size_t databuflen = 0; - - switch(ctx->cmdSet) { + + switch (ctx->cmdSet) { case DCCNative: case DCCNativeISO: DesfireSecureChannelEncode(ctx, cmd, data, datalen, databuf, &databuflen); - + if (ctx->cmdSet == DCCNative) res = DesfireExchangeNative(activate_field, ctx, cmd, databuf, databuflen, respcode, databuf, &databuflen, enable_chaining, splitbysize); else res = DesfireExchangeISO(activate_field, ctx, cmd, databuf, databuflen, respcode, databuf, &databuflen, enable_chaining, splitbysize); - + if (splitbysize) { uint8_t sdata[250 * 5] = {0}; size_t sdatalen = 0; @@ -600,12 +600,12 @@ int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uin } else { DesfireSecureChannelDecode(ctx, databuf, databuflen, *respcode, resp, resplen); } - break; + break; case DCCISO: return PM3_EAPDU_FAIL; - break; - } - + break; + } + return res; } @@ -616,24 +616,24 @@ int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t data int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2) { if (aid1 == NULL) return PM3_EINVARG; - + uint8_t data[6] = {0}; memcpy(data, aid1, 3); - if (aid2 != NULL) + if (aid2 != NULL) memcpy(&data[3], aid2, 3); uint8_t resp[257] = {0}; size_t resplen = 0; uint8_t respcode = 0; - + int res = DesfireExchangeEx(true, ctx, MFDES_SELECT_APPLICATION, data, (aid2 == NULL) ? 3 : 6, &respcode, resp, &resplen, true, 0); if (res == PM3_SUCCESS) { if (resplen != 0) return PM3_ECARDEXCHANGE; - + // select operation fail if (respcode != MFDES_S_OPERATION_OK) return PM3_EAPDU_FAIL; - + return PM3_SUCCESS; } return res; @@ -644,7 +644,7 @@ int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uin DesfireAIDUintToByte(aid1, data); DesfireAIDUintToByte(aid2, &data[3]); - + return DesfireSelectAID(ctx, data, (select_two) ? &data[3] : NULL); } @@ -656,9 +656,9 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel // 3 different way to authenticate AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32) // 4 different crypto arg1 DES, 3DES, 3K3DES, AES // 3 different communication modes, PLAIN,MAC,CRYPTO - + DesfireClearSession(dctx); - + if (secureChannel == DACNone) return PM3_SUCCESS; @@ -745,7 +745,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel // Part 2 uint32_t rndlen = recv_len; memcpy(encRndB, recv_data, rndlen); - + // Part 3 if (dctx->keyType == T_AES) { @@ -873,9 +873,9 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel Desfire_session_key_new(RndA, RndB, key, &sesskey); memcpy(dctx->sessionKeyEnc, sesskey.data, desfire_get_key_length(dctx->keyType)); -PrintAndLogEx(INFO, "encRndA : %s", sprint_hex(encRndA, rndlen)); -PrintAndLogEx(INFO, "IV : %s", sprint_hex(IV, rndlen)); - if (dctx->keyType == T_DES){ + PrintAndLogEx(INFO, "encRndA : %s", sprint_hex(encRndA, rndlen)); + PrintAndLogEx(INFO, "IV : %s", sprint_hex(IV, rndlen)); + if (dctx->keyType == T_DES) { if (secureChannel == DACd40) des_decrypt(encRndA, encRndA, key->data); if (secureChannel == DACEV1) @@ -892,8 +892,8 @@ PrintAndLogEx(INFO, "IV : %s", sprint_hex(IV, rndlen)); } rol(RndA, rndlen); -PrintAndLogEx(INFO, "Expected_RndA : %s", sprint_hex(RndA, rndlen)); -PrintAndLogEx(INFO, "Generated_RndA : %s", sprint_hex(encRndA, rndlen)); + PrintAndLogEx(INFO, "Expected_RndA : %s", sprint_hex(RndA, rndlen)); + PrintAndLogEx(INFO, "Generated_RndA : %s", sprint_hex(encRndA, rndlen)); for (uint32_t x = 0; x < rndlen; x++) { if (RndA[x] != encRndA[x]) { if (g_debugMode > 1) { @@ -916,10 +916,10 @@ PrintAndLogEx(INFO, "Generated_RndA : %s", sprint_hex(encRndA, rndlen)); //key->cmac_sk1 and key->cmac_sk2 //memcpy(dctx->sessionKeyEnc, sesskey.data, desfire_get_key_length(dctx->keyType)); } - + dctx->secureChannel = secureChannel; memcpy(dctx->sessionKeyMAC, dctx->sessionKeyEnc, desfire_get_key_length(dctx->keyType)); -PrintAndLogEx(INFO, "sessionKeyEnc : %s", sprint_hex(dctx->sessionKeyEnc, desfire_get_key_length(dctx->keyType))); + PrintAndLogEx(INFO, "sessionKeyEnc : %s", sprint_hex(dctx->sessionKeyEnc, desfire_get_key_length(dctx->keyType))); return PM3_SUCCESS; } diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 873e365a8..f7d9b485c 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -49,12 +49,12 @@ typedef struct DesfireContextS { uint8_t keyNum; enum DESFIRE_CRYPTOALGO keyType; // des/2tdea/3tdea/aes uint8_t key[DESF_MAX_KEY_LEN]; - + // KDF finction uint8_t kdfAlgo; uint8_t kdfInputLen; uint8_t kdfInput[31]; - + DesfireSecureChannel secureChannel; // none/d40/ev1/ev2 DesfireCommandSet cmdSet; // native/nativeiso/iso DesfireCommunicationMode commMode; // plain/mac/enc @@ -81,7 +81,7 @@ void DesfireClearSession(DesfireContext *ctx); void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key); void DesfireSetCommandSet(DesfireContext *ctx, DesfireCommandSet cmdSet); void DesfireSetCommMode(DesfireContext *ctx, DesfireCommunicationMode commMode); -void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo,uint8_t *kdfInput, uint8_t kdfInputLen); +void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo, uint8_t *kdfInput, uint8_t kdfInputLen); const char *DesfireGetErrorString(int res, uint16_t *sw); uint32_t DesfireAIDByteToUint(uint8_t *data); diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 90aa643ce..49e3e6b05 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -25,20 +25,21 @@ void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { uint8_t data[1024] = {0}; - switch(ctx->keyType) { + switch (ctx->keyType) { case T_DES: if (ctx->secureChannel == DACd40) { if (encode) des_encrypt_ecb(data, srcdata, srcdatalen, ctx->key); else des_decrypt_ecb(data, srcdata, srcdatalen, ctx->key); - } if (ctx->secureChannel == DACEV1) { + } + if (ctx->secureChannel == DACEV1) { if (encode) des_encrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); else des_decrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); } - + if (dstdata) memcpy(dstdata, data, srcdatalen); break; @@ -60,11 +61,11 @@ void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatale static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; - + uint8_t data[1024] = {0}; size_t rlen = 0; - switch(ctx->commMode) { + switch (ctx->commMode) { case DCMPlain: memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -72,7 +73,7 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint case DCMMACed: if (srcdatalen == 0) break; - + rlen = padded_data_length(srcdatalen, desfire_get_key_block_length(ctx->keyType)); memcpy(data, srcdata, srcdatalen); DesfireCryptoEncDec(ctx, data, rlen, NULL, true); @@ -87,7 +88,8 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint DesfireCryptoEncDec(ctx, data, rlen, dstdata, true); *dstdatalen = rlen; break; - case DCMNone:; + case DCMNone: + ; } } @@ -98,28 +100,29 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; - switch(ctx->commMode) { + switch (ctx->commMode) { case DCMPlain: case DCMMACed: data[0] = cmd; rlen = padded_data_length(srcdatalen + 1, desfire_get_key_block_length(ctx->keyType)); memcpy(&data[1], srcdata, srcdatalen); DesfireCryptoEncDec(ctx, data, rlen, NULL, true); - + memcpy(dstdata, srcdata, srcdatalen); if (srcdatalen != 0 && ctx->commMode == DCMMACed) { memcpy(&dstdata[srcdatalen], ctx->IV, 4); *dstdatalen = rlen; - } + } break; case DCMEncrypted: break; - case DCMNone:; + case DCMNone: + ; } } void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { - switch(ctx->secureChannel) { + switch (ctx->secureChannel) { case DACd40: DesfireSecureChannelEncodeD40(ctx, cmd, srcdata, srcdatalen, dstdata, dstdatalen); break; @@ -139,7 +142,7 @@ static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; - switch(ctx->commMode) { + switch (ctx->commMode) { case DCMMACed: break; @@ -150,19 +153,19 @@ static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; break; - } + } } static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; - switch(ctx->commMode) { + switch (ctx->commMode) { case DCMPlain: case DCMMACed: memcpy(dstdata, srcdata, srcdatalen - 8); *dstdatalen = srcdatalen - 8; - + break; case DCMEncrypted: break; @@ -170,11 +173,11 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; break; - } + } } void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { - switch(ctx->secureChannel) { + switch (ctx->secureChannel) { case DACd40: DesfireSecureChannelDecodeD40(ctx, srcdata, srcdatalen, respcode, dstdata, dstdatalen); break; diff --git a/doc/commands.json b/doc/commands.json index c52b3bbf5..8f191e302 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -973,7 +973,7 @@ }, "help": { "command": "help", - "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log e:\\proxspace\\pm3/.proxmark3/logs/log_20210630.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", + "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log e:\\proxspace\\pm3/.proxmark3/logs/log_20210706.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", "notes": [ "auto" ], @@ -3938,6 +3938,31 @@ ], "usage": "hf mf wrbl [-hab] --blk [-k ] [-d ]" }, + "hf mfdes auth": { + "command": "hf mfdes auth", + "description": "authenticates mifare desfire using key", + "notes": [ + "hf mfdes auth -m 3 -t 4 -a 808301 -n 0 -k 00000000000000000000000000000000 -> aes,keynumber 0, aid 0x803201", + "hf mfdes auth -m 2 -t 2 -a 000000 -n 1 -k 00000000000000000000000000000000 -> 3des,keynumber 1, aid 0x000000", + "hf mfdes auth -m 1 -t 1 -a 000000 -n 2 -k 0000000000000000 -> des,keynumber 2, aid 0x000000", + "hf mfdes auth -m 1 -t 1 -a 000000 -n 0 -> des, defaultkey, aid 0x000000", + "hf mfdes auth -m 2 -t 2 -a 000000 -n 0 -> 3des, defaultkey, aid 0x000000", + "hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> 3k3des, defaultkey, aid 0x000000", + "hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> aes, defaultkey, aid 0x000000" + ], + "offline": false, + "options": [ + "-h, --help this help", + "-m, --type auth type (1=normal, 2=iso, 3=aes)", + "-t, --algo crypt algo (1=des, 2=3des(2k2des), 3=3k3des, 4=aes)", + "-a, --aid aid used for authentification (hex 3 bytes)", + "-n, --keyno key number used for authentification", + "-k, --key key for checking (hex 8-24 bytes)", + "-d, --kdf key derivation function (kdf) (0=none, 1=an10922, 2=gallagher)", + "-i, --kdfi kdf input (hex 1-31 bytes)" + ], + "usage": "hf mfdes auth [-h] [-m ] [-t ] [-a ]... [-n ] [-k ] [-d ] [-i ]" + }, "hf mfdes bruteaid": { "command": "hf mfdes bruteaid", "description": "recover aids by bruteforce. warning: this command takes a long time", @@ -4168,6 +4193,50 @@ ], "usage": "hf mfdes formatpicc [-h]" }, + "hf mfdes getaids": { + "command": "hf mfdes getaids", + "description": "get application ids list from card. master key needs to be provided.", + "notes": [ + "hf mfdes getaids -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup" + ], + "offline": false, + "options": [ + "-h, --help this help", + "-a, --apdu show apdu requests and responses", + "-v, --verbose show technical data", + "-n, --keyno key number", + "-t, --algo crypt algo: des, 2tdea, 3tdea, aes", + "-k, --key key for authenticate (hex 8(des), 16(2tdea or aes) or 24(3tdea) bytes)", + "-f, --kdf key derivation function (kdf): none, an10922, gallagher", + "-i, --kdfi kdf input (hex 1-31 bytes)", + "-m, --cmode communicaton mode: plain/mac/encrypt", + "-c, --ccset communicaton command set: native/niso/iso", + "-s, --schann secure channel: d40/ev1/ev2" + ], + "usage": "hf mfdes getaids [-hav] [-n ] [-t ] [-k ] [-f ] [-i ] [-m ] [-c ] [-s ]" + }, + "hf mfdes getappnames": { + "command": "hf mfdes getappnames", + "description": "get application ids, iso ids and df names from card. master key needs to be provided.", + "notes": [ + "hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup" + ], + "offline": false, + "options": [ + "-h, --help this help", + "-a, --apdu show apdu requests and responses", + "-v, --verbose show technical data", + "-n, --keyno key number", + "-t, --algo crypt algo: des, 2tdea, 3tdea, aes", + "-k, --key key for authenticate (hex 8(des), 16(2tdea or aes) or 24(3tdea) bytes)", + "-f, --kdf key derivation function (kdf): none, an10922, gallagher", + "-i, --kdfi kdf input (hex 1-31 bytes)", + "-m, --cmode communicaton mode: plain/mac/encrypt", + "-c, --ccset communicaton command set: native/niso/iso", + "-s, --schann secure channel: d40/ev1/ev2" + ], + "usage": "hf mfdes getappnames [-hav] [-n ] [-t ] [-k ] [-f ] [-i ] [-m ] [-c ] [-s ]" + }, "hf mfdes getuid": { "command": "hf mfdes getuid", "description": "get uid from a mifare desfire tag", @@ -4196,28 +4265,23 @@ }, "hf mfdes help": { "command": "hf mfdes help", - "description": "help this help list list desfire (iso 14443a) history --------------------------------------------------------------------------------------- hf mfdes auth available offline: no authenticates mifare desfire using key", + "description": "help this help list list desfire (iso 14443a) history --------------------------------------------------------------------------------------- hf mfdes default available offline: no get application ids, iso ids and df names from card. master key needs to be provided.", "notes": [ - "hf mfdes auth -m 3 -t 4 -a 808301 -n 0 -k 00000000000000000000000000000000 -> aes,keynumber 0, aid 0x803201", - "hf mfdes auth -m 2 -t 2 -a 000000 -n 1 -k 00000000000000000000000000000000 -> 3des,keynumber 1, aid 0x000000", - "hf mfdes auth -m 1 -t 1 -a 000000 -n 2 -k 0000000000000000 -> des,keynumber 2, aid 0x000000", - "hf mfdes auth -m 1 -t 1 -a 000000 -n 0 -> des, defaultkey, aid 0x000000", - "hf mfdes auth -m 2 -t 2 -a 000000 -n 0 -> 3des, defaultkey, aid 0x000000", - "hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> 3k3des, defaultkey, aid 0x000000", - "hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> aes, defaultkey, aid 0x000000" + "hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup" ], "offline": true, "options": [ "-h, --help this help", - "-m, --type auth type (1=normal, 2=iso, 3=aes)", - "-t, --algo crypt algo (1=des, 2=3des(2k2des), 3=3k3des, 4=aes)", - "-a, --aid aid used for authentification (hex 3 bytes)", - "-n, --keyno key number used for authentification", - "-k, --key key for checking (hex 8-24 bytes)", - "-d, --kdf key derivation function (kdf) (0=none, 1=an10922, 2=gallagher)", - "-i, --kdfi kdf input (hex 1-31 bytes)" + "-n, --keyno key number", + "-t, --algo crypt algo: des, 2tdea, 3tdea, aes", + "-k, --key key for authenticate (hex 8(des), 16(2tdea or aes) or 24(3tdea) bytes)", + "-f, --kdf key derivation function (kdf): none, an10922, gallagher", + "-i, --kdfi kdf input (hex 1-31 bytes)", + "-m, --cmode communicaton mode: plain/mac/encrypt", + "-c, --ccset communicaton command set: native/niso/iso", + "-s, --schann secure channel: d40/ev1/ev2" ], - "usage": "hf mfdes auth [-h] [-m ] [-t ] [-a ]... [-n ] [-k ] [-d ] [-i ]" + "usage": "hf mfdes default [-h] [-n ] [-t ] [-k ] [-f ] [-i ] [-m ] [-c ] [-s ]" }, "hf mfdes info": { "command": "hf mfdes info", @@ -9217,8 +9281,8 @@ } }, "metadata": { - "commands_extracted": 572, + "commands_extracted": 575, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2021-06-30T09:30:39" + "extracted_on": "2021-07-06T09:14:57" } } \ No newline at end of file diff --git a/doc/commands.md b/doc/commands.md index a0625577c..c3b056e47 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -501,6 +501,7 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- |`hf mfdes help `|Y |`This help` +|`hf mfdes default `|N |`[new]Set defaults for all the commands` |`hf mfdes auth `|N |`Tries a MIFARE DesFire Authentication` |`hf mfdes changekey `|N |`Change Key` |`hf mfdes chk `|N |`Check keys` @@ -513,6 +514,8 @@ Check column "offline" for their availability. |`hf mfdes createaid `|N |`Create Application ID` |`hf mfdes deleteaid `|N |`Delete Application ID` |`hf mfdes selectaid `|N |`Select Application ID` +|`hf mfdes getaids `|N |`[new]Get Application IDs list` +|`hf mfdes getappnames `|N |`[new]Get Applications list` |`hf mfdes changevalue `|N |`Write value of a value file (credit/debit/clear)` |`hf mfdes clearfile `|N |`Clear record File` |`hf mfdes createfile `|N |`Create Standard/Backup File` From c22050b63835ff8584b83262fa5bfb826e0f8551 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 6 Jul 2021 12:39:06 +0300 Subject: [PATCH 208/309] create new desfirecrypto --- client/CMakeLists.txt | 1 + client/Makefile | 1 + client/src/mifare/desfirecore.c | 55 ------------ client/src/mifare/desfirecore.h | 63 +------------ client/src/mifare/desfirecrypto.c | 123 ++++++++++++++++++++++++++ client/src/mifare/desfirecrypto.h | 91 +++++++++++++++++++ client/src/mifare/desfiresecurechan.c | 36 -------- client/src/mifare/desfiresecurechan.h | 3 +- 8 files changed, 220 insertions(+), 153 deletions(-) create mode 100644 client/src/mifare/desfirecrypto.c create mode 100644 client/src/mifare/desfirecrypto.h diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 4879e953b..536464d18 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -226,6 +226,7 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/mifare/mifarehost.c ${PM3_ROOT}/client/src/nfc/ndef.c ${PM3_ROOT}/client/src/mifare/desfire_crypto.c + ${PM3_ROOT}/client/src/mifare/desfirecrypto.c ${PM3_ROOT}/client/src/mifare/desfiresecurechan.c ${PM3_ROOT}/client/src/mifare/desfirecore.c ${PM3_ROOT}/client/src/uart/uart_posix.c diff --git a/client/Makefile b/client/Makefile index 45ddffe31..7d09586a0 100644 --- a/client/Makefile +++ b/client/Makefile @@ -589,6 +589,7 @@ SRCS = aiddesfire.c \ loclass/elite_crack.c \ loclass/ikeys.c \ mifare/desfire_crypto.c \ + mifare/desfirecrypto.c \ mifare/desfirecore.c \ mifare/desfiresecurechan.c \ mifare/mad.c \ diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 9c4bb721b..7fd1f2b28 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -203,34 +203,6 @@ void DesfireAIDUintToByte(uint32_t aid, uint8_t *data) { data[2] = (aid >> 16) & 0xff; } -void DesfireClearContext(DesfireContext *ctx) { - ctx->keyNum = 0; - ctx->keyType = T_DES; - memset(ctx->key, 0, sizeof(ctx->key)); - - ctx->secureChannel = DACNone; - ctx->cmdSet = DCCNative; - ctx->commMode = DCMNone; - - ctx->kdfAlgo = 0; - ctx->kdfInputLen = 0; - memset(ctx->kdfInput, 0, sizeof(ctx->kdfInput)); - - DesfireClearSession(ctx); -} - -void DesfireClearSession(DesfireContext *ctx) { - ctx->secureChannel = DACNone; // here none - not authenticared - - memset(ctx->IV, 0, sizeof(ctx->IV)); - memset(ctx->sessionKeyMAC, 0, sizeof(ctx->sessionKeyMAC)); - memset(ctx->sessionKeyEnc, 0, sizeof(ctx->sessionKeyEnc)); - memset(ctx->lastIV, 0, sizeof(ctx->lastIV)); - ctx->cntrTx = 0; - ctx->cntrRx = 0; - memset(ctx->TI, 0, sizeof(ctx->TI)); -} - void DesfirePrintContext(DesfireContext *ctx) { PrintAndLogEx(INFO, "Key num: %d Key algo: %s Key[%d]: %s", ctx->keyNum, @@ -258,29 +230,6 @@ void DesfirePrintContext(DesfireContext *ctx) { } } -void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key) { - DesfireClearContext(ctx); - - ctx->keyNum = keyNum; - ctx->keyType = keyType; - memcpy(ctx->key, key, desfire_get_key_length(keyType)); -} - -void DesfireSetCommandSet(DesfireContext *ctx, DesfireCommandSet cmdSet) { - ctx->cmdSet = cmdSet; -} - -void DesfireSetCommMode(DesfireContext *ctx, DesfireCommunicationMode commMode) { - ctx->commMode = commMode; -} - -void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo, uint8_t *kdfInput, uint8_t kdfInputLen) { - ctx->kdfAlgo = kdfAlgo; - ctx->kdfInputLen = kdfInputLen; - if (kdfInputLen) - memcpy(ctx->kdfInput, kdfInput, kdfInputLen); -} - static int DESFIRESendApdu(bool activate_field, sAPDU apdu, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint16_t *sw) { if (result_len) *result_len = 0; if (sw) *sw = 0; @@ -648,10 +597,6 @@ int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uin return DesfireSelectAID(ctx, data, (select_two) ? &data[3] : NULL); } -bool DesfireIsAuthenticated(DesfireContext *dctx) { - return dctx->secureChannel != DACNone; -} - int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel) { // 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 f7d9b485c..e33cfa7aa 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -15,78 +15,22 @@ #include "common.h" #include "cliparser.h" +#include "mifare/desfirecrypto.h" #include "mifare/desfire_crypto.h" #include "mifare/mifare4.h" -#define DESF_MAX_KEY_LEN 24 - -#define DESFIRE_GET_ISO_STATUS(x) ( ((uint16_t)(0x91<<8)) + (uint16_t)x ) - -typedef enum DESFIRE_CRYPTOALGO DesfireCryptoAlgorythm; - -typedef enum { - DACNone, - DACd40, - DACEV1, - DACEV2 -} DesfireSecureChannel; - -typedef enum { - DCCNative, - DCCNativeISO, - DCCISO -} DesfireCommandSet; - -typedef enum { - DCMNone, - DCMPlain, - DCMMACed, - DCMEncrypted -} DesfireCommunicationMode; - - -typedef struct DesfireContextS { - uint8_t keyNum; - enum DESFIRE_CRYPTOALGO keyType; // des/2tdea/3tdea/aes - uint8_t key[DESF_MAX_KEY_LEN]; - - // KDF finction - uint8_t kdfAlgo; - uint8_t kdfInputLen; - uint8_t kdfInput[31]; - - DesfireSecureChannel secureChannel; // none/d40/ev1/ev2 - DesfireCommandSet cmdSet; // native/nativeiso/iso - DesfireCommunicationMode commMode; // plain/mac/enc - - uint8_t IV[DESF_MAX_KEY_LEN]; - uint8_t sessionKeyMAC[DESF_MAX_KEY_LEN]; - uint8_t sessionKeyEnc[DESF_MAX_KEY_LEN]; // look at mifare4.h - mf4Session_t - uint8_t lastIV[DESF_MAX_KEY_LEN]; - //mf4Session_t AESSession; - uint16_t cntrTx; // for AES - uint16_t cntrRx; // for AES - uint8_t TI[4]; // for AES -} DesfireContext; - extern const CLIParserOption DesfireAlgoOpts[]; extern const CLIParserOption DesfireKDFAlgoOpts[]; extern const CLIParserOption DesfireCommunicationModeOpts[]; extern const CLIParserOption DesfireCommandSetOpts[]; extern const CLIParserOption DesfireSecureChannelOpts[]; -void DesfireClearContext(DesfireContext *ctx); -void DesfirePrintContext(DesfireContext *ctx); -void DesfireClearSession(DesfireContext *ctx); -void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key); -void DesfireSetCommandSet(DesfireContext *ctx, DesfireCommandSet cmdSet); -void DesfireSetCommMode(DesfireContext *ctx, DesfireCommunicationMode commMode); -void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo, uint8_t *kdfInput, uint8_t kdfInputLen); - const char *DesfireGetErrorString(int res, uint16_t *sw); uint32_t DesfireAIDByteToUint(uint8_t *data); void DesfireAIDUintToByte(uint32_t aid, uint8_t *data); +void DesfirePrintContext(DesfireContext *ctx); + int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen); int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize); @@ -94,7 +38,6 @@ int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2); int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2); int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel); -bool DesfireIsAuthenticated(DesfireContext *dctx); int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c new file mode 100644 index 000000000..55c957932 --- /dev/null +++ b/client/src/mifare/desfirecrypto.c @@ -0,0 +1,123 @@ +/*- + * Copyright (C) 2010, Romain Tartiere. + * Copyright (C) 2021 Merlok + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see + * + * $Id$ + */ + +#include "desfirecrypto.h" + +#include +#include +#include +#include "ui.h" +#include "crc.h" +#include "crc16.h" // crc16 ccitt +#include "crc32.h" +#include "commonutil.h" +#include "mifare/desfire_crypto.h" + +void DesfireClearContext(DesfireContext *ctx) { + ctx->keyNum = 0; + ctx->keyType = T_DES; + memset(ctx->key, 0, sizeof(ctx->key)); + + ctx->secureChannel = DACNone; + ctx->cmdSet = DCCNative; + ctx->commMode = DCMNone; + + ctx->kdfAlgo = 0; + ctx->kdfInputLen = 0; + memset(ctx->kdfInput, 0, sizeof(ctx->kdfInput)); + + DesfireClearSession(ctx); +} + +void DesfireClearSession(DesfireContext *ctx) { + ctx->secureChannel = DACNone; // here none - not authenticared + + memset(ctx->IV, 0, sizeof(ctx->IV)); + memset(ctx->sessionKeyMAC, 0, sizeof(ctx->sessionKeyMAC)); + memset(ctx->sessionKeyEnc, 0, sizeof(ctx->sessionKeyEnc)); + memset(ctx->lastIV, 0, sizeof(ctx->lastIV)); + ctx->cntrTx = 0; + ctx->cntrRx = 0; + memset(ctx->TI, 0, sizeof(ctx->TI)); +} + +void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key) { + DesfireClearContext(ctx); + + ctx->keyNum = keyNum; + ctx->keyType = keyType; + memcpy(ctx->key, key, desfire_get_key_length(keyType)); +} + +void DesfireSetCommandSet(DesfireContext *ctx, DesfireCommandSet cmdSet) { + ctx->cmdSet = cmdSet; +} + +void DesfireSetCommMode(DesfireContext *ctx, DesfireCommunicationMode commMode) { + ctx->commMode = commMode; +} + +void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo, uint8_t *kdfInput, uint8_t kdfInputLen) { + ctx->kdfAlgo = kdfAlgo; + ctx->kdfInputLen = kdfInputLen; + if (kdfInputLen) + memcpy(ctx->kdfInput, kdfInput, kdfInputLen); +} + +bool DesfireIsAuthenticated(DesfireContext *dctx) { + return dctx->secureChannel != DACNone; +} + +void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { + uint8_t data[1024] = {0}; + + switch (ctx->keyType) { + case T_DES: + if (ctx->secureChannel == DACd40) { + if (encode) + des_encrypt_ecb(data, srcdata, srcdatalen, ctx->key); + else + des_decrypt_ecb(data, srcdata, srcdatalen, ctx->key); + } + if (ctx->secureChannel == DACEV1) { + if (encode) + des_encrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); + else + des_decrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); + } + + if (dstdata) + memcpy(dstdata, data, srcdatalen); + break; + case T_3DES: + break; + case T_3K3DES: + break; + case T_AES: + if (encode) + aes_encode(ctx->IV, ctx->key, srcdata, data, srcdatalen); + else + aes_decode(ctx->IV, ctx->key, srcdata, data, srcdatalen); + if (dstdata) + memcpy(dstdata, data, srcdatalen); + break; + } +} + diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h new file mode 100644 index 000000000..9fc3d61e0 --- /dev/null +++ b/client/src/mifare/desfirecrypto.h @@ -0,0 +1,91 @@ +/*- + * Copyright (C) 2010, Romain Tartiere. + * Copyright (C) 2021 Merlok + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see + * + * $Id$ + */ + +#ifndef __DESFIRECRYPTO_H +#define __DESFIRECRYPTO_H + +#include "common.h" +#include "mifare/desfire_crypto.h" +#include "mifare/mifare4.h" + +#define DESF_MAX_KEY_LEN 24 + +#define DESFIRE_GET_ISO_STATUS(x) ( ((uint16_t)(0x91<<8)) + (uint16_t)x ) + +typedef enum DESFIRE_CRYPTOALGO DesfireCryptoAlgorythm; + +typedef enum { + DACNone, + DACd40, + DACEV1, + DACEV2 +} DesfireSecureChannel; + +typedef enum { + DCCNative, + DCCNativeISO, + DCCISO +} DesfireCommandSet; + +typedef enum { + DCMNone, + DCMPlain, + DCMMACed, + DCMEncrypted +} DesfireCommunicationMode; + + +typedef struct DesfireContextS { + uint8_t keyNum; + enum DESFIRE_CRYPTOALGO keyType; // des/2tdea/3tdea/aes + uint8_t key[DESF_MAX_KEY_LEN]; + + // KDF finction + uint8_t kdfAlgo; + uint8_t kdfInputLen; + uint8_t kdfInput[31]; + + DesfireSecureChannel secureChannel; // none/d40/ev1/ev2 + DesfireCommandSet cmdSet; // native/nativeiso/iso + DesfireCommunicationMode commMode; // plain/mac/enc + + uint8_t IV[DESF_MAX_KEY_LEN]; + uint8_t sessionKeyMAC[DESF_MAX_KEY_LEN]; + uint8_t sessionKeyEnc[DESF_MAX_KEY_LEN]; // look at mifare4.h - mf4Session_t + uint8_t lastIV[DESF_MAX_KEY_LEN]; + //mf4Session_t AESSession; + uint16_t cntrTx; // for AES + uint16_t cntrRx; // for AES + uint8_t TI[4]; // for AES +} DesfireContext; + +void DesfireClearContext(DesfireContext *ctx); +void DesfireClearSession(DesfireContext *ctx); +void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key); +void DesfireSetCommandSet(DesfireContext *ctx, DesfireCommandSet cmdSet); +void DesfireSetCommMode(DesfireContext *ctx, DesfireCommunicationMode commMode); +void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo, uint8_t *kdfInput, uint8_t kdfInputLen); +bool DesfireIsAuthenticated(DesfireContext *dctx); + + +void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode); + + +#endif // __DESFIRECRYPTO_H diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 49e3e6b05..f7e7d22ea 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -22,42 +22,6 @@ #include "commonutil.h" #include "mifare/desfire_crypto.h" -void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { - uint8_t data[1024] = {0}; - - switch (ctx->keyType) { - case T_DES: - if (ctx->secureChannel == DACd40) { - if (encode) - des_encrypt_ecb(data, srcdata, srcdatalen, ctx->key); - else - des_decrypt_ecb(data, srcdata, srcdatalen, ctx->key); - } - if (ctx->secureChannel == DACEV1) { - if (encode) - des_encrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); - else - des_decrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); - } - - if (dstdata) - memcpy(dstdata, data, srcdatalen); - break; - case T_3DES: - break; - case T_3K3DES: - break; - case T_AES: - if (encode) - aes_encode(ctx->IV, ctx->key, srcdata, data, srcdatalen); - else - aes_decode(ctx->IV, ctx->key, srcdata, data, srcdatalen); - if (dstdata) - memcpy(dstdata, data, srcdatalen); - break; - } -} - static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; diff --git a/client/src/mifare/desfiresecurechan.h b/client/src/mifare/desfiresecurechan.h index df997eb54..23810c791 100644 --- a/client/src/mifare/desfiresecurechan.h +++ b/client/src/mifare/desfiresecurechan.h @@ -15,11 +15,10 @@ #include "common.h" #include "mifare/desfirecore.h" +#include "mifare/desfirecrypto.h" #include "mifare/desfire_crypto.h" #include "mifare/mifare4.h" -void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode); - void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen); void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen); From 5f0f6b8032be89df04e1dbf277c9993d6f320fcc Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 6 Jul 2021 16:22:01 +0300 Subject: [PATCH 209/309] update crypto encode/decode --- client/src/mifare/desfire_crypto.h | 10 +- client/src/mifare/desfirecrypto.c | 163 ++++++++++++++++++++++---- client/src/mifare/desfirecrypto.h | 27 +++-- client/src/mifare/desfiresecurechan.c | 6 +- 4 files changed, 161 insertions(+), 45 deletions(-) diff --git a/client/src/mifare/desfire_crypto.h b/client/src/mifare/desfire_crypto.h index 71f3acb23..346a7e50c 100644 --- a/client/src/mifare/desfire_crypto.h +++ b/client/src/mifare/desfire_crypto.h @@ -25,10 +25,9 @@ #include "mifare.h" // structs #include "crc32.h" #include "crypto/libpcrypto.h" +#include "mifare/desfirecrypto.h" -#define MAX_CRYPTO_BLOCK_SIZE 16 -#define DESFIRE_MAX_KEY_SIZE 24 /* Mifare DESFire EV1 Application crypto operations */ #define APPLICATION_CRYPTO_DES 0x00 #define APPLICATION_CRYPTO_3K3DES 0x40 @@ -75,13 +74,6 @@ typedef enum { /* Error code managed by the library */ #define CRYPTO_ERROR 0x01 -enum DESFIRE_CRYPTOALGO { - T_DES = 0x00, - T_3DES = 0x01, //aka 2K3DES - T_3K3DES = 0x02, - T_AES = 0x03 -}; - int desfire_get_key_length(enum DESFIRE_CRYPTOALGO key_type); size_t desfire_get_key_block_length(enum DESFIRE_CRYPTOALGO key_type); diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 55c957932..e0a886b62 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -24,6 +24,8 @@ #include #include #include "ui.h" +#include "aes.h" +#include "des.h" #include "crc.h" #include "crc16.h" // crc16 ccitt #include "crc32.h" @@ -85,39 +87,152 @@ bool DesfireIsAuthenticated(DesfireContext *dctx) { return dctx->secureChannel != DACNone; } -void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { - uint8_t data[1024] = {0}; +static void DesfireCryptoEncDecSingleBlock(uint8_t *key, DesfireCryptoAlgorythm keyType, uint8_t *data, uint8_t *dstdata, uint8_t *ivect, bool dir_to_send, bool encode) { + size_t block_size = desfire_get_key_block_length(keyType); + uint8_t sdata[MAX_CRYPTO_BLOCK_SIZE] = {0}; + memcpy(sdata, data, block_size); + if (dir_to_send) { + bin_xor(sdata, ivect, block_size); + } - switch (ctx->keyType) { + uint8_t edata[MAX_CRYPTO_BLOCK_SIZE] = {0}; + + switch (keyType) { case T_DES: - if (ctx->secureChannel == DACd40) { - if (encode) - des_encrypt_ecb(data, srcdata, srcdatalen, ctx->key); - else - des_decrypt_ecb(data, srcdata, srcdatalen, ctx->key); - } - if (ctx->secureChannel == DACEV1) { - if (encode) - des_encrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); - else - des_decrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); - } - - if (dstdata) - memcpy(dstdata, data, srcdatalen); + if (encode) + des_encrypt(edata, sdata, key); + else + des_decrypt(edata, sdata, key); break; case T_3DES: + if (encode) { + mbedtls_des3_context ctx3; + mbedtls_des3_set2key_enc(&ctx3, key); + mbedtls_des3_crypt_ecb(&ctx3, sdata, edata); + } else { + mbedtls_des3_context ctx3; + mbedtls_des3_set2key_dec(&ctx3, key); + mbedtls_des3_crypt_ecb(&ctx3, sdata, edata); + } break; case T_3K3DES: + if (encode) { + mbedtls_des3_context ctx3; + mbedtls_des3_set3key_enc(&ctx3, key); + mbedtls_des3_crypt_ecb(&ctx3, sdata, edata); + } else { + mbedtls_des3_context ctx3; + mbedtls_des3_set3key_dec(&ctx3, key); + mbedtls_des3_crypt_ecb(&ctx3, sdata, edata); + } break; case T_AES: - if (encode) - aes_encode(ctx->IV, ctx->key, srcdata, data, srcdatalen); - else - aes_decode(ctx->IV, ctx->key, srcdata, data, srcdatalen); - if (dstdata) - memcpy(dstdata, data, srcdatalen); + if (encode) { + mbedtls_aes_context actx; + mbedtls_aes_init(&actx); + mbedtls_aes_setkey_enc(&actx, key, 128); + mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_ENCRYPT, sdata, edata); + mbedtls_aes_free(&actx); + } else { + mbedtls_aes_context actx; + mbedtls_aes_init(&actx); + mbedtls_aes_setkey_dec(&actx, key, 128); + mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_DECRYPT, sdata, edata); + mbedtls_aes_free(&actx); + } break; } + + memcpy(dstdata, edata, block_size); + + if (dir_to_send) { + memcpy(ivect, sdata, block_size); + } else { + memcpy(ivect, data, block_size); + } +} + +void DesfireCryptoEncDec(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { + uint8_t data[1024] = {0}; + + if (ctx->secureChannel == DACd40) + memset(ctx->IV, 0, DESFIRE_MAX_CRYPTO_BLOCK_SIZE); + + size_t block_size = desfire_get_key_block_length(ctx->keyType); + size_t offset = 0; + while (offset < srcdatalen) { + //mifare_cypher_single_block(key, data + offset, ivect, direction, operation, block_size); + if (use_session_key) + DesfireCryptoEncDecSingleBlock(ctx->sessionKeyMAC, ctx->keyType, srcdata + offset, data, ctx->IV, encode, encode); + else + DesfireCryptoEncDecSingleBlock(ctx->key, ctx->keyType, srcdata + offset, data, ctx->IV, encode, encode); + offset += block_size; + } + + if (dstdata) + memcpy(dstdata, data, srcdatalen); +} + +static void DesfireCMACGenerateSubkeys(DesfireContext *ctx, uint8_t *sk1, uint8_t *sk2) { + int kbs = desfire_get_key_block_length(ctx->keyType); + const uint8_t R = (kbs == 8) ? 0x1B : 0x87; + + uint8_t l[kbs]; + memset(l, 0, kbs); + + uint8_t ivect[kbs]; + memset(ivect, 0, kbs); + + //mifare_cypher_blocks_chained(NULL, key, ivect, l, kbs, MCD_SEND, MCO_ENCYPHER); + DesfireCryptoEncDec(ctx, true, l, kbs, NULL, true); + + bool txor = false; + + // Used to compute CMAC on complete blocks + memcpy(sk1, l, kbs); + txor = l[0] & 0x80; + lsl(sk1, kbs); + if (txor) { + sk1[kbs - 1] ^= R; + } + + // Used to compute CMAC on the last block if non-complete + memcpy(sk2, sk1, kbs); + txor = sk1[0] & 0x80; + lsl(sk2, kbs); + if (txor) { + sk2[kbs - 1] ^= R; + } +} + +void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *data, size_t len, uint8_t *cmac) { + int kbs = desfire_get_key_block_length(ctx->keyType); + if (kbs == 0) + return; + + uint8_t buffer[kbs]; + memset(buffer, 0, kbs); + + uint8_t sk1[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + uint8_t sk2[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + DesfireCMACGenerateSubkeys(ctx, sk1, sk2); + + memcpy(buffer, data, len); + + if ((!len) || (len % kbs)) { + buffer[len++] = 0x80; + while (len % kbs) { + buffer[len++] = 0x00; + } + bin_xor(buffer + len - kbs, sk2, kbs); + } else { + bin_xor(buffer + len - kbs, sk1, kbs); + } + + //mifare_cypher_blocks_chained(NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER); + DesfireCryptoEncDec(ctx, true, buffer, len, NULL, true); + + memcpy(cmac, ctx->IV, kbs); + } diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index 9fc3d61e0..236601406 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -22,13 +22,21 @@ #define __DESFIRECRYPTO_H #include "common.h" -#include "mifare/desfire_crypto.h" #include "mifare/mifare4.h" -#define DESF_MAX_KEY_LEN 24 +#define MAX_CRYPTO_BLOCK_SIZE 16 +#define DESFIRE_MAX_CRYPTO_BLOCK_SIZE 16 +#define DESFIRE_MAX_KEY_SIZE 24 #define DESFIRE_GET_ISO_STATUS(x) ( ((uint16_t)(0x91<<8)) + (uint16_t)x ) +enum DESFIRE_CRYPTOALGO { + T_DES = 0x00, + T_3DES = 0x01, //aka 2K3DES + T_3K3DES = 0x02, + T_AES = 0x03 +}; + typedef enum DESFIRE_CRYPTOALGO DesfireCryptoAlgorythm; typedef enum { @@ -54,8 +62,8 @@ typedef enum { typedef struct DesfireContextS { uint8_t keyNum; - enum DESFIRE_CRYPTOALGO keyType; // des/2tdea/3tdea/aes - uint8_t key[DESF_MAX_KEY_LEN]; + DesfireCryptoAlgorythm keyType; // des/2tdea/3tdea/aes + uint8_t key[DESFIRE_MAX_KEY_SIZE]; // KDF finction uint8_t kdfAlgo; @@ -66,10 +74,10 @@ typedef struct DesfireContextS { DesfireCommandSet cmdSet; // native/nativeiso/iso DesfireCommunicationMode commMode; // plain/mac/enc - uint8_t IV[DESF_MAX_KEY_LEN]; - uint8_t sessionKeyMAC[DESF_MAX_KEY_LEN]; - uint8_t sessionKeyEnc[DESF_MAX_KEY_LEN]; // look at mifare4.h - mf4Session_t - uint8_t lastIV[DESF_MAX_KEY_LEN]; + uint8_t IV[DESFIRE_MAX_KEY_SIZE]; + uint8_t sessionKeyMAC[DESFIRE_MAX_KEY_SIZE]; + uint8_t sessionKeyEnc[DESFIRE_MAX_KEY_SIZE]; // look at mifare4.h - mf4Session_t + uint8_t lastIV[DESFIRE_MAX_KEY_SIZE]; //mf4Session_t AESSession; uint16_t cntrTx; // for AES uint16_t cntrRx; // for AES @@ -85,7 +93,8 @@ void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo, uint8_t *kdfInput, uint bool DesfireIsAuthenticated(DesfireContext *dctx); -void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode); +void DesfireCryptoEncDec(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode); +void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *cmac); #endif // __DESFIRECRYPTO_H diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index f7e7d22ea..51f2af365 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -40,7 +40,7 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint rlen = padded_data_length(srcdatalen, desfire_get_key_block_length(ctx->keyType)); memcpy(data, srcdata, srcdatalen); - DesfireCryptoEncDec(ctx, data, rlen, NULL, true); + DesfireCryptoEncDec(ctx, true, data, rlen, NULL, true); memcpy(dstdata, srcdata, srcdatalen); memcpy(&dstdata[srcdatalen], ctx->IV, 4); *dstdatalen = rlen; @@ -49,7 +49,7 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint rlen = padded_data_length(srcdatalen + 2, desfire_get_key_block_length(ctx->keyType)); // 2 - crc16 memcpy(data, srcdata, srcdatalen); compute_crc(CRC_14443_A, data, srcdatalen, &data[srcdatalen], &data[srcdatalen + 1]); - DesfireCryptoEncDec(ctx, data, rlen, dstdata, true); + DesfireCryptoEncDec(ctx, true, data, rlen, dstdata, true); *dstdatalen = rlen; break; case DCMNone: @@ -70,7 +70,7 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint data[0] = cmd; rlen = padded_data_length(srcdatalen + 1, desfire_get_key_block_length(ctx->keyType)); memcpy(&data[1], srcdata, srcdatalen); - DesfireCryptoEncDec(ctx, data, rlen, NULL, true); + DesfireCryptoEncDec(ctx, true, data, rlen, NULL, true); memcpy(dstdata, srcdata, srcdatalen); if (srcdatalen != 0 && ctx->commMode == DCMMACed) { From fffef000eac4aa733d77a4ef04e4ad35a212c20d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 6 Jul 2021 16:46:05 +0300 Subject: [PATCH 210/309] mac des/ev1 calculated --- client/src/mifare/desfirecrypto.c | 5 ++++- client/src/mifare/desfiresecurechan.c | 21 +++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index e0a886b62..98a095b0c 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -184,7 +184,8 @@ static void DesfireCMACGenerateSubkeys(DesfireContext *ctx, uint8_t *sk1, uint8_ memset(ivect, 0, kbs); //mifare_cypher_blocks_chained(NULL, key, ivect, l, kbs, MCD_SEND, MCO_ENCYPHER); - DesfireCryptoEncDec(ctx, true, l, kbs, NULL, true); + DesfireCryptoEncDec(ctx, true, l, kbs, l, true); +//PrintAndLogEx(INFO, "i: %s", sprint_hex(l, kbs)); bool txor = false; @@ -218,6 +219,8 @@ void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *data, size_t len, uint8_t * DesfireCMACGenerateSubkeys(ctx, sk1, sk2); memcpy(buffer, data, len); +PrintAndLogEx(INFO, "sk1: %s", sprint_hex(sk1, 8)); +PrintAndLogEx(INFO, "sk2: %s", sprint_hex(sk2, 8)); if ((!len) || (len % kbs)) { buffer[len++] = 0x80; diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 51f2af365..c1924c2fd 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -70,11 +70,13 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint data[0] = cmd; rlen = padded_data_length(srcdatalen + 1, desfire_get_key_block_length(ctx->keyType)); memcpy(&data[1], srcdata, srcdatalen); - DesfireCryptoEncDec(ctx, true, data, rlen, NULL, true); + uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + DesfireCryptoCMAC(ctx, data, rlen, cmac); +PrintAndLogEx(INFO, "MAC: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); memcpy(dstdata, srcdata, srcdatalen); if (srcdatalen != 0 && ctx->commMode == DCMMACed) { - memcpy(&dstdata[srcdatalen], ctx->IV, 4); + memcpy(&dstdata[srcdatalen], cmac, 8); *dstdatalen = rlen; } break; @@ -121,6 +123,9 @@ static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, } static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { + uint8_t data[1024] = {0}; + size_t rlen = 0; + memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -129,6 +134,18 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, case DCMMACed: memcpy(dstdata, srcdata, srcdatalen - 8); *dstdatalen = srcdatalen - 8; + + memcpy(data, srcdata, *dstdatalen); + data[*dstdatalen] = respcode; + rlen = padded_data_length(*dstdatalen + 1, desfire_get_key_block_length(ctx->keyType)); + + uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + DesfireCryptoCMAC(ctx, data, rlen, cmac); +PrintAndLogEx(INFO, "MACp: %s", sprint_hex(&srcdata[*dstdatalen], desfire_get_key_block_length(ctx->keyType))); +PrintAndLogEx(INFO, "MACc: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); + if (memcmp(&srcdata[*dstdatalen], cmac, desfire_get_key_block_length(ctx->keyType)) != 0) { + PrintAndLogEx(WARNING, "Received MAC is not match with calculated"); + } break; case DCMEncrypted: From ae53e38335145ae75d6518e8f681656df52568b6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 6 Jul 2021 18:41:52 +0300 Subject: [PATCH 211/309] add application create/delete commands --- client/src/mifare/desfirecore.c | 28 ++++++++++++++++++++++++++++ client/src/mifare/desfirecore.h | 2 ++ 2 files changed, 30 insertions(+) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 7fd1f2b28..96d5f66cd 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -862,6 +862,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel //memcpy(dctx->sessionKeyEnc, sesskey.data, desfire_get_key_length(dctx->keyType)); } + memset(dctx->IV, 0, DESFIRE_MAX_KEY_SIZE); dctx->secureChannel = secureChannel; memcpy(dctx->sessionKeyMAC, dctx->sessionKeyEnc, desfire_get_key_length(dctx->keyType)); PrintAndLogEx(INFO, "sessionKeyEnc : %s", sprint_hex(dctx->sessionKeyEnc, desfire_get_key_length(dctx->keyType))); @@ -888,3 +889,30 @@ int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { return PM3_EAPDU_FAIL; return PM3_SUCCESS; } + +int DesfireCreateApplication(DesfireContext *dctx, uint8_t *appdata, size_t appdatalen) { + uint8_t respcode = 0xff; + uint8_t resp[257] = {0}; + size_t resplen = 0; + int res = DesfireExchangeEx(false, dctx, MFDES_CREATE_APPLICATION, appdata, appdatalen, &respcode, resp, &resplen, true, 24); + if (res != PM3_SUCCESS) + return res; + if (respcode != MFDES_S_OPERATION_OK || resplen != 0) + return PM3_EAPDU_FAIL; + return PM3_SUCCESS; +} + +int DesfireDeleteApplication(DesfireContext *dctx, uint32_t aid) { + uint8_t respcode = 0xff; + uint8_t data[3] = {0}; + DesfireAIDUintToByte(aid, data); + uint8_t resp[257] = {0}; + size_t resplen = 0; + int res = DesfireExchangeEx(false, dctx, MFDES_DELETE_APPLICATION, data, sizeof(data), &respcode, resp, &resplen, true, 24); + if (res != PM3_SUCCESS) + return res; + if (respcode != MFDES_S_OPERATION_OK || resplen != 0) + return PM3_EAPDU_FAIL; + return PM3_SUCCESS; +} + diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index e33cfa7aa..9eaa74f9a 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -42,5 +42,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); +int DesfireCreateApplication(DesfireContext *dctx, uint8_t *appdata, size_t appdatalen); +int DesfireDeleteApplication(DesfireContext *dctx, uint32_t aid); #endif // __DESFIRECORE_H From cc146f4bc2c6056cf6b1f8b2e3efc94344c377c3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 7 Jul 2021 11:26:54 +0200 Subject: [PATCH 212/309] correct gh user --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8c37a07c..16a931ddc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] - Added one new key from gun cloner found in wild (@scott4290) - - Fix `hf_msdsal` standalone in simulation flow (@netxing) + - Fix `hf_msdsal` standalone in simulation flow (@salmg) - Added a picture viewer in QT. To be used with `hf emrtd info` (@iceman1001) - Fix - move des functions to libcrypto (@merlokk) - Added `CLIGetOptionList` to cliparser that makes it easier to implement text options in the cli (@merlokk) From 2c9851d751d08874ce4d01c23cff9c1612afe642 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 7 Jul 2021 13:36:23 +0200 Subject: [PATCH 213/309] added new standalone mode `hf_reblay` by @salmg --- CHANGELOG.md | 1 + armsrc/Standalone/Makefile.hal | 9 +- armsrc/Standalone/Makefile.inc | 4 + armsrc/Standalone/hf_reblay.c | 415 ++++++++++++++++++ .../4_Advanced-compilation-parameters.md | 1 + 5 files changed, 429 insertions(+), 1 deletion(-) create mode 100644 armsrc/Standalone/hf_reblay.c diff --git a/CHANGELOG.md b/CHANGELOG.md index 16a931ddc..321bef66c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Add new standalone mode `hf_reblay` - relay 14a over bt (@salmg) - Added one new key from gun cloner found in wild (@scott4290) - Fix `hf_msdsal` standalone in simulation flow (@salmg) - Added a picture viewer in QT. To be used with `hf emrtd info` (@iceman1001) diff --git a/armsrc/Standalone/Makefile.hal b/armsrc/Standalone/Makefile.hal index 8a51a39e8..498300ac7 100644 --- a/armsrc/Standalone/Makefile.hal +++ b/armsrc/Standalone/Makefile.hal @@ -68,6 +68,9 @@ define KNOWN_STANDALONE_DEFINITIONS | HF_MSDSAL | Read and emulate MSD Visa cards | | (default) | - Salvador Mendoza | +----------------------------------------------------------+ +| HF_REBLAY | 14A Relay over BT | +| (RDV4 only) | - Salvador Mendoza | ++----------------------------------------------------------+ | HF_TCPRST | IKEA Rothult read/sim/dump/emul | | | - Nick Draffen | +----------------------------------------------------------+ @@ -80,7 +83,8 @@ define KNOWN_STANDALONE_DEFINITIONS endef STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RWC LF_HIDBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN LF_THAREXDE LF_NEXID -STANDALONE_MODES += HF_14ASNIFF HF_AVEFUL HF_BOG HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_TCPRST HF_TMUDFORD HF_YOUNG +STANDALONE_MODES += HF_14ASNIFF HF_AVEFUL HF_BOG HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_TCPRST HF_TMUDFORD HF_YOUNG HF_REBLAY +STANDALONE_MODES_REQ_BT := HF_REBLAY STANDALONE_MODES_REQ_SMARTCARD := STANDALONE_MODES_REQ_FLASH := LF_ICEHID LF_NEXID LF_THAREXDE HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),) @@ -91,6 +95,9 @@ ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),) ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_FLASH)),) STANDALONE_REQ_DEFS += -DWITH_FLASH endif + ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_BT)),) + STANDALONE_REQ_DEFS += -DWITH_FPC_USART_HOST + endif else ifneq ($(STANDALONE),) $(error Invalid STANDALONE: $(STANDALONE). $(KNOWN_DEFINITIONS)) endif diff --git a/armsrc/Standalone/Makefile.inc b/armsrc/Standalone/Makefile.inc index 79c6ab979..510c56a48 100644 --- a/armsrc/Standalone/Makefile.inc +++ b/armsrc/Standalone/Makefile.inc @@ -89,3 +89,7 @@ endif ifneq (,$(findstring WITH_STANDALONE_HF_TMUDFORD,$(APP_CFLAGS))) SRC_STANDALONE = hf_tmudford.c endif + # WITH_STANDALONE_HF_REBLAY +ifneq (,$(findstring WITH_STANDALONE_HF_REBLAY,$(APP_CFLAGS))) + SRC_STANDALONE = hf_reblay.c +endif \ No newline at end of file diff --git a/armsrc/Standalone/hf_reblay.c b/armsrc/Standalone/hf_reblay.c new file mode 100644 index 000000000..65bf07988 --- /dev/null +++ b/armsrc/Standalone/hf_reblay.c @@ -0,0 +1,415 @@ +//----------------------------------------------------------------------------- +// Salvador Mendoza (salmg.net) - January 01, 2021 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Code to relay 14a technology data aka reblay by Salvador Mendoza +//----------------------------------------------------------------------------- +#include "standalone.h" +#include "proxmark3_arm.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "util.h" +#include "dbprint.h" +#include "ticks.h" +#include "string.h" +#include "BigBuf.h" +#include "iso14443a.h" +#include "protocols.h" +#include "cmd.h" + +#include "usart.h" // Bluetooth reading & writing + +void ModInfo(void) { + DbpString(" HF - Relaying ISO/14443A data over Bluetooth - (Salvador Mendoza)"); +} +/* This standalone implements two different modes: reading & emulating, to switch between them +* just press the button. +* +* Reading ISO-14443A technology is not limited to payment cards. This example +* was designed to open new possibilities relaying ISO-14443A data over Bluetooth. +* +* Instructions: +* +* I recommend setting up & run the other end before start sending or receving data in this Proxmark3 +* standalone. +* +* For the reading mode: +* - Set up and run the other end first, to where the Proxmark will send the data. +* - After the card is detected, Proxmark3 will send a package. The first byte will be the package +* length, then, the card data. Use the first length byte to read the whole package. +* - Proxmark3 will expect a raw APDU from the other end, then it will be sent to the card. +* - The answer of the card will be sent back to the connection, repeating the cycle. +* +* For the emulation mode: +* - Set up and run the other end first, from where the Proxmark will receive the data. +* - When the Proxmark3 detected the terminal, it will send the command to the connection. +* - The first byte will be the package length, then, the terminal command. Use the first +* length byte to read the whole package. +* - Proxmark3 will expect a raw APDU from the other end, then it will be sent to the terminal. +* - The command of the terminal will be sent back to the connection, repeating the cycle. +* +* Notes: +* - The emulation mode was tested in a real SumUp payment terminal. This does not mean +* that it will work in all the terminals around the world. +* - The emulation mode implements different techniques to try to keep the connection alive: +* WTX or ACK for NACK requests. Some of these requests could be denied depending on +* the reader configuration. +* +* +* Be brave enough to share your knowledge & inspire others. +*/ + +void RunMod() { + StandAloneMode(); + Dbprintf(_YELLOW_(">>") "Relaying ISO/14443A data over Bluetooth a.k.a. reblay Started<<"); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + +// Allocate 512 bytes for the dynamic modulation, created when the reader queries for it +// Such a response is less time critical, so we can prepare them on the fly +#define DYNAMIC_RESPONSE_BUFFER_SIZE 512 +#define DYNAMIC_MODULATION_BUFFER_SIZE 1024 + + uint8_t flags = FLAG_4B_UID_IN_DATA; //UID 4 bytes(could be 7 bytes if needed it) + uint8_t data[PM3_CMD_DATA_SIZE] = {0x00}; // in case there is a read command received we shouldn't break + + uint8_t visauid[7] = {0x01, 0x02, 0x03, 0x04}; + memcpy(data, visauid, 4); + + // to initialize the emulation + uint8_t tagType = 4; // 4 = ISO/IEC 14443-4 - javacard (JCOP) + tag_response_info_t *responses; + + uint32_t cuid = 0; + uint32_t counters[3] = { 0x00, 0x00, 0x00 }; + uint8_t tearings[3] = { 0xbd, 0xbd, 0xbd }; + uint8_t pages = 0; + + + // For received Bluetooth package + uint8_t rpacket[MAX_FRAME_SIZE] = { 0x00 }; + uint16_t lenpacket = 0; + + // For answering the commands + uint8_t apdubuffer[MAX_FRAME_SIZE] = { 0x00 }; + uint8_t apdulen = 0; + + // Buffer for Bluetooth data + uint8_t buffert[MAX_FRAME_SIZE] = { 0x00 }; + uint8_t bufferlen = 0; + + // Reading card + iso14a_card_select_t card_a_info; + + // For init ping process + uint8_t sak = {0x0}; + uint8_t atqa[2] = { 0x00, 0x00 }; + uint8_t uidc[10] = { 0x00 }; + uint8_t uidlen = 0; + uint8_t ats[MAX_FRAME_SIZE] = { 0x00 }; + uint8_t atsl = 0; + + uint8_t rdata[14] = { 0x00 }; + + // Command buffers + uint8_t receivedCmd[MAX_FRAME_SIZE] = { 0x00 }; + uint8_t receivedCmdPar[MAX_PARITY_SIZE] = { 0x00 }; + + uint8_t dynamic_response_buffer[DYNAMIC_RESPONSE_BUFFER_SIZE] = {0}; + uint8_t dynamic_modulation_buffer[DYNAMIC_MODULATION_BUFFER_SIZE] = {0}; + + // Command response - handler + tag_response_info_t dynamic_response_info = { + .response = dynamic_response_buffer, + .response_n = 0, + .modulation = dynamic_modulation_buffer, + .modulation_n = 0 + }; + +#define STATE_READ 0 +#define STATE_EMU 1 + + uint8_t state = STATE_READ; + + if (state == STATE_READ) { + DbpString(_YELLOW_("[ ") "In reading mode" _YELLOW_(" ]")); + } else { + DbpString(_YELLOW_("[ ") "In emulation mode" _YELLOW_(" ]")); + } + + for (;;) { + WDT_HIT(); + + // Exit from RunMod, send a usbcommand. + if (data_available()) break; + + // Button held down or pressed? + int button_pressed = BUTTON_HELD(1000); + + if (button_pressed == BUTTON_HOLD) // Holding down the button + break; + else if (button_pressed == BUTTON_SINGLE_CLICK) { // Pressing one time change between reading & emulation + if (state == STATE_READ) { + state = STATE_EMU; + DbpString(_YELLOW_("[ ") "In emulation mode" _YELLOW_(" ]")); + } else { + state = STATE_READ; + DbpString(_YELLOW_("[ ") "In reading mode" _YELLOW_(" ]")); + } + } + + SpinDelay(500); + + if (state == STATE_READ) { + LED_A_ON(); + clear_trace(); + set_tracing(true); + + iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); + if (iso14443a_select_card(NULL, &card_a_info, NULL, true, 0, false)) { + LED_B_ON(); + + // Get data to send a ping with UID + ATQA + SAK + sak = card_a_info.sak; + uidlen = card_a_info.uidlen; + atsl = card_a_info.ats_len; + + memcpy(uidc, card_a_info.uid, uidlen); + memcpy(atqa, card_a_info.atqa, 2); + memcpy(ats, card_a_info.ats, atsl); + + DbpString(_YELLOW_("[ ") "UID:" _YELLOW_(" ]")); + Dbhexdump(uidlen, uidc, false); + DbpString(_YELLOW_("[ ") "ATQA:" _YELLOW_(" ]")); + Dbhexdump(2, atqa, false); + Dbprintf(_YELLOW_("[ ") "SAK: %x "_YELLOW_(" ]"), sak); + DbpString(_YELLOW_("[ ") "ATS:" _YELLOW_(" ]")); + Dbhexdump(atsl, ats, false); + + memcpy(&rdata[1], uidc, uidlen); + memcpy(&rdata[uidlen + 1], atqa, 2); + memcpy(&rdata[uidlen + 3], &sak, 1); + + rdata[0] = uidlen + 3; + + // ping = UID + ATQA + SAK + DbpString(_YELLOW_("[ ") "Ping:" _YELLOW_(" ]")); + Dbhexdump(uidlen + 4, rdata, false); + + DbpString(_YELLOW_("[ ") "Sending ping" _YELLOW_(" ]")); + if (usart_writebuffer_sync(rdata, uidlen + 4) == PM3_SUCCESS) { + DbpString(_YELLOW_("[ ") "Sent!" _YELLOW_(" ]")); + + for (;;) { + if (usart_rxdata_available()) { + lenpacket = usart_read_ng(rpacket, sizeof(rpacket)); + + if (lenpacket > 1) { + DbpString(_YELLOW_("[ ") "Bluetooth data:" _YELLOW_(" ]")); + Dbhexdump(lenpacket, rpacket, false); + + apdulen = iso14_apdu(rpacket, (uint16_t) lenpacket, false, apdubuffer, NULL); + + DbpString(_YELLOW_("[ ") "Card response:" _YELLOW_(" ]")); + Dbhexdump(apdulen - 2, apdubuffer, false); + + bufferlen = apdulen - 2; + + memcpy(&buffert[0], &bufferlen, 1); + memcpy(&buffert[1], apdubuffer, bufferlen); + + DbpString(_YELLOW_("[ ") "Buffer:" _YELLOW_(" ]")); + Dbhexdump(bufferlen, buffert, false); + + usart_writebuffer_sync(buffert, bufferlen + 1); + + + } else if (lenpacket == 1) { + DbpString(_YELLOW_("[ ") "Done!" _YELLOW_(" ]")); + LED_C_ON(); + + for (uint8_t i = 0; i < 3; i++) + SpinDelay(1000); + + break; + } + } + LED_B_OFF(); + } + } else { + DbpString(_YELLOW_("[ ") "Cannot send it!" _YELLOW_(" ]")); + SpinDelay(1000); + } + } + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); + } else if (state == STATE_EMU) { + LED_A_OFF(); + LED_C_ON(); + + // free eventually allocated BigBuf memory but keep Emulator Memory + BigBuf_free_keep_EM(); + + if (SimulateIso14443aInit(tagType, flags, data, &responses, &cuid, counters, tearings, &pages) == false) { + BigBuf_free_keep_EM(); + reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0); + DbpString(_YELLOW_("!!") "Error initializing the emulation process!"); + SpinDelay(500); + state = STATE_READ; + DbpString(_YELLOW_("[ ") "Initialized reading mode" _YELLOW_(" ]")); + break; + } + + // We need to listen to the high-frequency, peak-detected path. + iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); + + int len = 0; // Command length + int retval = PM3_SUCCESS; // Check emulation status + + uint8_t resp = 0; // Bluetooth response + lenpacket = 0; + + uint8_t prevcmd = 0x00; // Keep track of last terminal type command + + clear_trace(); + set_tracing(true); + + for (;;) { + LED_B_OFF(); + // Clean receive command buffer + if (!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) { + DbpString(_YELLOW_("!!") "Emulator stopped"); + retval = PM3_EOPABORTED; + break; + } + tag_response_info_t *p_response = NULL; + LED_B_ON(); + + // dynamic_response_info will be in charge of responses + dynamic_response_info.response_n = 0; + + if (lenpacket == 0 && resp == 2) { // Check for Bluetooth packages + if (usart_rxdata_available()) { + lenpacket = usart_read_ng(rpacket, sizeof(rpacket)); + + if (lenpacket > 0) { + DbpString(_YELLOW_("[ ") "Received Bluetooth data" _YELLOW_(" ]")); + Dbhexdump(lenpacket, rpacket, false); + memcpy(&dynamic_response_info.response[1], rpacket, lenpacket); + dynamic_response_info.response[0] = prevcmd; + dynamic_response_info.response_n = lenpacket + 1; + resp = 1; + } + } + } + if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) { // Received a REQUEST + DbpString(_YELLOW_("+") "REQUEST Received"); + p_response = &responses[RESP_INDEX_ATQA]; + } else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) { // Received a HALT + DbpString(_YELLOW_("+") "Received a HALT"); + p_response = NULL; + resp = 0; + } else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) { // Received a WAKEUP + DbpString(_YELLOW_("+") "WAKEUP Received"); + p_response = &responses[RESP_INDEX_ATQA]; + resp = 0; + } else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 2) { // Received request for UID (cascade 1) + DbpString(_YELLOW_("+") "Request for UID C1"); + p_response = &responses[RESP_INDEX_UIDC1]; + } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) { // Received a SELECT (cascade 1) + DbpString(_YELLOW_("+") "Request for SELECT S1"); + p_response = &responses[RESP_INDEX_SAKC1]; + } else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request + DbpString(_YELLOW_("+") "Request for RATS"); + p_response = &responses[RESP_INDEX_RATS]; + resp = 1; + } else if (receivedCmd[0] == 0xf2 && len == 4) { // ACKed - Time extension + DbpString(_YELLOW_("!!") "Reader accepted time extension!"); + p_response = NULL; + } else if ((receivedCmd[0] == 0xb2 || receivedCmd[0] == 0xb3) && len == 3) { //NACK - Request more time WTX + DbpString(_YELLOW_("!!") "NACK - time extension request?"); + if (resp == 2 && lenpacket == 0) { + DbpString(_YELLOW_("!!") "Requesting more time - WTX"); + dynamic_response_info.response_n = 2; + dynamic_response_info.response[0] = 0xf2; + dynamic_response_info.response[1] = 0x0b; // Requesting the maximum amount of time + } else if (lenpacket == 0) { + DbpString(_YELLOW_("!!") "NACK - ACK - Resend last command!"); // To burn some time as well + dynamic_response_info.response[0] = 0xa3; + dynamic_response_info.response_n = 1; + } else { + DbpString(_YELLOW_("!!") "Avoiding request - Bluetooth data already in memory!!"); + } + } else { + DbpString(_GREEN_("[ ") "Card reader command" _GREEN_(" ]")); + Dbhexdump(len - 2, &receivedCmd[1], false); + + if ((receivedCmd[0] == 0x02 || receivedCmd[0] == 0x03) && len > 3) { // Process reader commands + + if (resp == 1) { + prevcmd = receivedCmd[0]; + bufferlen = len - 3; + memcpy(&buffert[0], &bufferlen, 1); + memcpy(&buffert[1], &receivedCmd[1], bufferlen); + resp = 2; + } + if (lenpacket > 0) { + DbpString(_YELLOW_("[ ") "Answering using Bluetooth data!" _YELLOW_(" ]")); + memcpy(&dynamic_response_info.response[1], rpacket, lenpacket); + dynamic_response_info.response[0] = receivedCmd[0]; + dynamic_response_info.response_n = lenpacket + 1; + lenpacket = 0; + resp = 1; + } else { + DbpString(_YELLOW_("[ ") "New command: sent it & waiting for Bluetooth response!" _YELLOW_(" ]")); + usart_writebuffer_sync(buffert, bufferlen + 1); + p_response = NULL; + } + + } else { + if (lenpacket == 0) { + DbpString(_YELLOW_("!!") "Received unknown command!"); + memcpy(dynamic_response_info.response, receivedCmd, len); + dynamic_response_info.response_n = len; + } else { + DbpString(_YELLOW_("!!") "Avoiding unknown command - Bluetooth data already in memory!!"); + } + } + } + if (dynamic_response_info.response_n > 0) { + DbpString(_GREEN_("[ ") "Proxmark3 answer" _GREEN_(" ]")); + Dbhexdump(dynamic_response_info.response_n, dynamic_response_info.response, false); + DbpString("----"); + if (lenpacket > 0) { + lenpacket = 0; + resp = 1; + } + // Add CRC bytes, always used in ISO 14443A-4 compliant cards + AddCrc14A(dynamic_response_info.response, dynamic_response_info.response_n); + dynamic_response_info.response_n += 2; + + if (prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE) == false) { + Dbprintf(_YELLOW_("[ ") "Buffer size: %d "_YELLOW_(" ]"), dynamic_response_info.response_n); + SpinDelay(500); + DbpString(_YELLOW_("!!") "Error preparing Proxmark to answer!"); + continue; + } + p_response = &dynamic_response_info; + } + + if (p_response != NULL) { + EmSendPrecompiledCmd(p_response); + } + } + switch_off(); + + set_tracing(false); + BigBuf_free_keep_EM(); + reply_ng(CMD_HF_MIFARE_SIMULATE, retval, NULL, 0); + } + } + DbpString(_YELLOW_("[=]") "exiting"); + LEDsoff(); +} diff --git a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md index f7f955de7..d2b934e98 100644 --- a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md +++ b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md @@ -97,6 +97,7 @@ Here are the supported values you can assign to `STANDALONE` in `Makefile.platfo | HF_LEGIC | HF Legic Prime standalone - uhei | HF_MATTYRUN | Mifare sniff/clone - Matías A. Ré Medina | HF_MSDSAL (def)| EMV Read and emulation - Salvador Mendoza +| HF_REBLAY | 14A relay over BT - Salvador Mendoza | HF_TCPRST | IKEA Rothult ST25TA, Standalone Master Key Dump/Emulation - Nick Draffen | HF_TMUDFORD | Read and emulate ISO15693 card UID - Tim Mudford | HF_YOUNG | Mifare sniff/simulation - Craig Young From 94236fa02c4e20f4e2cf6a5a60b6e840b55d95e8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 7 Jul 2021 13:39:52 +0200 Subject: [PATCH 214/309] added ht_reblay support python scripts (@salmg) --- CHANGELOG.md | 1 + tools/pm3_reblay-emulating.py | 55 ++++++++++++++++++++++++++++ tools/pm3_reblay-reading.py | 69 +++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 tools/pm3_reblay-emulating.py create mode 100644 tools/pm3_reblay-reading.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 321bef66c..17d45f1e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added support python scripts (@salmg) - Add new standalone mode `hf_reblay` - relay 14a over bt (@salmg) - Added one new key from gun cloner found in wild (@scott4290) - Fix `hf_msdsal` standalone in simulation flow (@salmg) diff --git a/tools/pm3_reblay-emulating.py b/tools/pm3_reblay-emulating.py new file mode 100644 index 000000000..280d5ccb2 --- /dev/null +++ b/tools/pm3_reblay-emulating.py @@ -0,0 +1,55 @@ +""" +//----------------------------------------------------------------------------- +// Salvador Mendoza (salmg.net), 2021 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Code to test Proxmark3 Standalone mode aka reblay by Salvador Mendoza +//----------------------------------------------------------------------------- +""" + +import serial +from smartcard.util import toHexString, toBytes +from smartcard.CardType import AnyCardType +from smartcard.CardRequest import CardRequest + +ser = serial.Serial('/dev/rfcomm0') # open Proxmark3 Bluetooth port + +def pd(data): + rapdu = map(ord, data) + return rapdu + +apdu = [ + [0x6F, 0x23, 0x84, 0x0E, 0x32, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31, 0xA5, 0x11, 0xBF, 0x0C, 0x0E, 0x61, 0x0C, 0x4F, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0x87, 0x01, 0x01, 0x90, 0x00], + [0x6F, 0x1E, 0x84, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0xA5, 0x13, 0x50, 0x0B, 0x56, 0x49, 0x53, 0x41, 0x20, 0x43, 0x52, 0x45, 0x44, 0x49, 0x54, 0x9F, 0x38, 0x03, 0x9F, 0x66, 0x02, 0x90, 0x00], + [0x80, 0x06, 0x00, 0x80, 0x08, 0x01, 0x01, 0x00, 0x90, 0x00], + [0x70,0x15,0x57,0x13,0x46,0x50,0x98,0x29,0x81,0x62,0x29,0x58,0xd2,0x40,0x32,0x01,0x14,0x69,0x00,0x00,0x13,0x83,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8f,0x90,0x00], + [0x6f, 0x00], + [0x6f, 0x00] +] + +print('Testing code: bluetooth has to be connected with the right rfcomm port!') +print('Waiting for data...') +initd = ser.read(1) + +bufferlen = pd(initd)[0] +rping = ser.read(bufferlen) +ping = pd(rping) + +print('Terminal command:'), +print(toHexString(ping)) + +for x in apdu: + print('Sending cmd: '), + ser.write(x) + print(toHexString(x)) + print('--') + + lenpk = ser.read(1) #first byte is the buffer length + bufferlen = pd(lenpk)[0] + + buffer = pd(ser.read(bufferlen)) + print('Terminal command:'), + print(toHexString(buffer)) diff --git a/tools/pm3_reblay-reading.py b/tools/pm3_reblay-reading.py new file mode 100644 index 000000000..b7a2fa615 --- /dev/null +++ b/tools/pm3_reblay-reading.py @@ -0,0 +1,69 @@ +""" +//----------------------------------------------------------------------------- +// Salvador Mendoza (salmg.net), 2021 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Code to test Proxmark3 Standalone mode aka reblay by Salvador Mendoza +//----------------------------------------------------------------------------- +""" + +import serial +from smartcard.util import toHexString + +ser = serial.Serial('/dev/rfcomm0') # open Proxmark3 Bluetooth port + +def pd(data): + rapdu = map(ord, data) + return rapdu + +apdu = [ + [0x00, 0xA4, 0x04, 0x00, 0x0e, 0x32, 0x50, 0x41, 0x59, 0x2e, 0x53, 0x59, 0x53, 0x2e, 0x44, 0x44, 0x46, 0x30, 0x31, 0x00], # PPSE + [0x00, 0xA4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0x00], # Visa card + [0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00], # GET PROCESSING + [0x00, 0xb2, 0x01, 0x0c, 0x00] # SFI +] + +print('Testing code: bluetooth has to be connected with the right rfcomm port!') +print('Waiting for data...') +initd = ser.read(1) + +bufferlen = pd(initd)[0] +rping = ser.read(bufferlen) + +ping = pd(rping) +if (len(ping) == 7): + print('UID:'), + print(toHexString(ping[:4])) + print('ATQA:'), + print(toHexString(ping[4:-1])) + print('SAK:'), + print(toHexString(ping[-1:])) +elif (len(ping) == 10): + print('UID:'), + print(toHexString(ping[:7])) + print('ATQA:'), + print(toHexString(ping[7:-1])) + print('SAK:'), + print(toHexString(ping[-1:])) +else: + print('got ping, no sure what it means: '), + print(ping) + +for x in apdu: + print('Sending cmd: '), + ser.write(x) + print(toHexString(x)) + + lenpk = ser.read(1) #first byte is the buffer length + bufferlen = pd(lenpk)[0] + + buffer = pd(ser.read(bufferlen)) + print('Card Response:'), + print(toHexString(buffer)) + print('--') + +ser.write(b'1') #tell Proxmark3 that we finish the communication +ser.close() From 857ce0ea1714546a4d1c412a3013d834c98396e4 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Jul 2021 16:16:45 +0300 Subject: [PATCH 215/309] fix multiple sprint_hex --- client/src/mifare/desfirecore.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 96d5f66cd..862723587 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -220,12 +220,14 @@ void DesfirePrintContext(DesfireContext *ctx) { CLIGetOptionListStr(DesfireCommunicationModeOpts, ctx->commMode)); if (DesfireIsAuthenticated(ctx)) { - PrintAndLogEx(INFO, "Session key MAC [%d]: %s ENC: %s IV [%d]: %s", + PrintAndLogEx(INFO, "Session key MAC [%d]: %s ", desfire_get_key_length(ctx->keyType), - sprint_hex(ctx->sessionKeyMAC, desfire_get_key_length(ctx->keyType)), - sprint_hex(ctx->sessionKeyEnc, desfire_get_key_length(ctx->keyType)), + sprint_hex(ctx->sessionKeyMAC, desfire_get_key_length(ctx->keyType))); + PrintAndLogEx(INFO, " ENC: %s", + sprint_hex(ctx->sessionKeyEnc, desfire_get_key_length(ctx->keyType))); + PrintAndLogEx(INFO, " IV [%d]: %s", desfire_get_key_block_length(ctx->keyType), - sprint_hex(ctx->sessionKeyEnc, desfire_get_key_block_length(ctx->keyType))); + sprint_hex(ctx->IV, desfire_get_key_block_length(ctx->keyType))); } } From 0f0ef4435ed05d5cc4dc5e6cbdf829578adc3b71 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Jul 2021 16:17:35 +0300 Subject: [PATCH 216/309] add mac length and fix encode/decode --- client/src/mifare/desfirecrypto.c | 58 ++++++++++++++++++++++++++----- client/src/mifare/desfirecrypto.h | 2 ++ 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 98a095b0c..6982cff6f 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -26,6 +26,7 @@ #include "ui.h" #include "aes.h" #include "des.h" +#include #include "crc.h" #include "crc16.h" // crc16 ccitt #include "crc32.h" @@ -87,6 +88,25 @@ bool DesfireIsAuthenticated(DesfireContext *dctx) { return dctx->secureChannel != DACNone; } +size_t DesfireGetMACLength(DesfireContext *ctx) { + size_t mac_length = MAC_LENGTH; + switch (ctx->secureChannel) { + case DACNone: + mac_length = 0; + break; + case DACd40: + mac_length = 4; + break; + case DACEV1: + mac_length = 8; + break; + case DACEV2: + mac_length = 8; + break; + } + return mac_length; +} + static void DesfireCryptoEncDecSingleBlock(uint8_t *key, DesfireCryptoAlgorythm keyType, uint8_t *data, uint8_t *dstdata, uint8_t *ivect, bool dir_to_send, bool encode) { size_t block_size = desfire_get_key_block_length(keyType); uint8_t sdata[MAX_CRYPTO_BLOCK_SIZE] = {0}; @@ -146,33 +166,49 @@ static void DesfireCryptoEncDecSingleBlock(uint8_t *key, DesfireCryptoAlgorythm memcpy(dstdata, edata, block_size); if (dir_to_send) { - memcpy(ivect, sdata, block_size); + memcpy(ivect, edata, block_size); } else { memcpy(ivect, data, block_size); } } -void DesfireCryptoEncDec(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { +void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode, uint8_t *iv) { uint8_t data[1024] = {0}; + uint8_t xiv[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; if (ctx->secureChannel == DACd40) memset(ctx->IV, 0, DESFIRE_MAX_CRYPTO_BLOCK_SIZE); - + size_t block_size = desfire_get_key_block_length(ctx->keyType); + + if (iv == NULL) + memcpy(xiv, ctx->IV, block_size); + else + memcpy(xiv, iv, block_size); + size_t offset = 0; while (offset < srcdatalen) { //mifare_cypher_single_block(key, data + offset, ivect, direction, operation, block_size); if (use_session_key) - DesfireCryptoEncDecSingleBlock(ctx->sessionKeyMAC, ctx->keyType, srcdata + offset, data, ctx->IV, encode, encode); + DesfireCryptoEncDecSingleBlock(ctx->sessionKeyMAC, ctx->keyType, srcdata + offset, data, xiv, encode, encode); else - DesfireCryptoEncDecSingleBlock(ctx->key, ctx->keyType, srcdata + offset, data, ctx->IV, encode, encode); + DesfireCryptoEncDecSingleBlock(ctx->key, ctx->keyType, srcdata + offset, data, xiv, encode, encode); offset += block_size; } + if (iv == NULL) + memcpy(ctx->IV, xiv, block_size); + else + memcpy(iv, xiv, block_size); + if (dstdata) memcpy(dstdata, data, srcdatalen); } +void DesfireCryptoEncDec(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { + DesfireCryptoEncDecEx(ctx, use_session_key, srcdata, srcdatalen, dstdata, encode, NULL); +} + static void DesfireCMACGenerateSubkeys(DesfireContext *ctx, uint8_t *sk1, uint8_t *sk2) { int kbs = desfire_get_key_block_length(ctx->keyType); const uint8_t R = (kbs == 8) ? 0x1B : 0x87; @@ -184,7 +220,7 @@ static void DesfireCMACGenerateSubkeys(DesfireContext *ctx, uint8_t *sk1, uint8_ memset(ivect, 0, kbs); //mifare_cypher_blocks_chained(NULL, key, ivect, l, kbs, MCD_SEND, MCO_ENCYPHER); - DesfireCryptoEncDec(ctx, true, l, kbs, l, true); + DesfireCryptoEncDecEx(ctx, true, l, kbs, l, true, ivect); //PrintAndLogEx(INFO, "i: %s", sprint_hex(l, kbs)); bool txor = false; @@ -211,14 +247,15 @@ void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *data, size_t len, uint8_t * if (kbs == 0) return; - uint8_t buffer[kbs]; - memset(buffer, 0, kbs); + uint8_t buffer[padded_data_length(len, kbs)]; + memset(buffer, 0, sizeof(buffer)); uint8_t sk1[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; uint8_t sk2[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; DesfireCMACGenerateSubkeys(ctx, sk1, sk2); memcpy(buffer, data, len); +PrintAndLogEx(INFO, "key: %s", sprint_hex(ctx->sessionKeyMAC, 24)); PrintAndLogEx(INFO, "sk1: %s", sprint_hex(sk1, 8)); PrintAndLogEx(INFO, "sk2: %s", sprint_hex(sk2, 8)); @@ -227,15 +264,18 @@ PrintAndLogEx(INFO, "sk2: %s", sprint_hex(sk2, 8)); while (len % kbs) { buffer[len++] = 0x00; } +PrintAndLogEx(INFO, "befode xor sk1: %s", sprint_hex(buffer, len)); bin_xor(buffer + len - kbs, sk2, kbs); } else { +PrintAndLogEx(INFO, "befode xor sk2: %s", sprint_hex(buffer, len)); bin_xor(buffer + len - kbs, sk1, kbs); } +PrintAndLogEx(INFO, "cbuf: %s", sprint_hex(buffer, len)); +PrintAndLogEx(INFO, "iv: %s", sprint_hex(ctx->IV, kbs)); //mifare_cypher_blocks_chained(NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER); DesfireCryptoEncDec(ctx, true, buffer, len, NULL, true); memcpy(cmac, ctx->IV, kbs); - } diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index 236601406..b9f28f31a 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -91,9 +91,11 @@ void DesfireSetCommandSet(DesfireContext *ctx, DesfireCommandSet cmdSet); void DesfireSetCommMode(DesfireContext *ctx, DesfireCommunicationMode commMode); void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo, uint8_t *kdfInput, uint8_t kdfInputLen); bool DesfireIsAuthenticated(DesfireContext *dctx); +size_t DesfireGetMACLength(DesfireContext *ctx); void DesfireCryptoEncDec(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode); +void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode, uint8_t *iv); void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *cmac); From 81028914916671cf107b1134f9dbfea4414d71db Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Jul 2021 16:18:12 +0300 Subject: [PATCH 217/309] ev1/mac and ev1/plain works --- client/src/mifare/desfiresecurechan.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index c1924c2fd..b437ebc07 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -59,7 +59,6 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { uint8_t data[1024] = {0}; - size_t rlen = 0; memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -68,16 +67,14 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint case DCMPlain: case DCMMACed: data[0] = cmd; - rlen = padded_data_length(srcdatalen + 1, desfire_get_key_block_length(ctx->keyType)); memcpy(&data[1], srcdata, srcdatalen); uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; - DesfireCryptoCMAC(ctx, data, rlen, cmac); -PrintAndLogEx(INFO, "MAC: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); + DesfireCryptoCMAC(ctx, data, srcdatalen + 1, cmac); memcpy(dstdata, srcdata, srcdatalen); if (srcdatalen != 0 && ctx->commMode == DCMMACed) { - memcpy(&dstdata[srcdatalen], cmac, 8); - *dstdatalen = rlen; + memcpy(&dstdata[srcdatalen], cmac, DesfireGetMACLength(ctx)); + *dstdatalen = srcdatalen + DesfireGetMACLength(ctx); } break; case DCMEncrypted: @@ -124,7 +121,6 @@ static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { uint8_t data[1024] = {0}; - size_t rlen = 0; memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -132,19 +128,21 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, switch (ctx->commMode) { case DCMPlain: case DCMMACed: - memcpy(dstdata, srcdata, srcdatalen - 8); - *dstdatalen = srcdatalen - 8; + if (srcdatalen < DesfireGetMACLength(ctx)) + break; + + memcpy(dstdata, srcdata, srcdatalen - DesfireGetMACLength(ctx)); + *dstdatalen = srcdatalen - DesfireGetMACLength(ctx); memcpy(data, srcdata, *dstdatalen); data[*dstdatalen] = respcode; - rlen = padded_data_length(*dstdatalen + 1, desfire_get_key_block_length(ctx->keyType)); uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; - DesfireCryptoCMAC(ctx, data, rlen, cmac); -PrintAndLogEx(INFO, "MACp: %s", sprint_hex(&srcdata[*dstdatalen], desfire_get_key_block_length(ctx->keyType))); -PrintAndLogEx(INFO, "MACc: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); - if (memcmp(&srcdata[*dstdatalen], cmac, desfire_get_key_block_length(ctx->keyType)) != 0) { + DesfireCryptoCMAC(ctx, data, *dstdatalen + 1, cmac); + if (memcmp(&srcdata[*dstdatalen], cmac, DesfireGetMACLength(ctx)) != 0) { PrintAndLogEx(WARNING, "Received MAC is not match with calculated"); + PrintAndLogEx(INFO, " received MAC: %s", sprint_hex(&srcdata[*dstdatalen], desfire_get_key_block_length(ctx->keyType))); + PrintAndLogEx(INFO, " calculated MAC: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); } break; From d963ec833242632a97ecfbada1285dec1ecf6c7b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Jul 2021 16:25:26 +0300 Subject: [PATCH 218/309] remove debug --- client/src/mifare/desfirecrypto.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 6982cff6f..187744ec7 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -188,7 +188,6 @@ void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *s size_t offset = 0; while (offset < srcdatalen) { - //mifare_cypher_single_block(key, data + offset, ivect, direction, operation, block_size); if (use_session_key) DesfireCryptoEncDecSingleBlock(ctx->sessionKeyMAC, ctx->keyType, srcdata + offset, data, xiv, encode, encode); else @@ -219,9 +218,7 @@ static void DesfireCMACGenerateSubkeys(DesfireContext *ctx, uint8_t *sk1, uint8_ uint8_t ivect[kbs]; memset(ivect, 0, kbs); - //mifare_cypher_blocks_chained(NULL, key, ivect, l, kbs, MCD_SEND, MCO_ENCYPHER); DesfireCryptoEncDecEx(ctx, true, l, kbs, l, true, ivect); -//PrintAndLogEx(INFO, "i: %s", sprint_hex(l, kbs)); bool txor = false; @@ -255,25 +252,17 @@ void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *data, size_t len, uint8_t * DesfireCMACGenerateSubkeys(ctx, sk1, sk2); memcpy(buffer, data, len); -PrintAndLogEx(INFO, "key: %s", sprint_hex(ctx->sessionKeyMAC, 24)); -PrintAndLogEx(INFO, "sk1: %s", sprint_hex(sk1, 8)); -PrintAndLogEx(INFO, "sk2: %s", sprint_hex(sk2, 8)); if ((!len) || (len % kbs)) { buffer[len++] = 0x80; while (len % kbs) { buffer[len++] = 0x00; } -PrintAndLogEx(INFO, "befode xor sk1: %s", sprint_hex(buffer, len)); bin_xor(buffer + len - kbs, sk2, kbs); } else { -PrintAndLogEx(INFO, "befode xor sk2: %s", sprint_hex(buffer, len)); bin_xor(buffer + len - kbs, sk1, kbs); } -PrintAndLogEx(INFO, "cbuf: %s", sprint_hex(buffer, len)); -PrintAndLogEx(INFO, "iv: %s", sprint_hex(ctx->IV, kbs)); - //mifare_cypher_blocks_chained(NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER); DesfireCryptoEncDec(ctx, true, buffer, len, NULL, true); memcpy(cmac, ctx->IV, kbs); From 6e207be3acae5800544fef0d997ebd9be5bea668 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Jul 2021 16:31:23 +0300 Subject: [PATCH 219/309] added `there is no applications` message if it there is no app) --- client/src/cmdhfmfdes.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 4204b8a3c..7526207e3 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5217,6 +5217,8 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { PrintAndLogEx(INFO, "---- " _CYAN_("AID list") " ----"); for (int i = 0; i < buflen; i += 3) PrintAndLogEx(INFO, "AID: %06x", DesfireAIDByteToUint(&buf[i])); + } else { + PrintAndLogEx(INFO, "There is no applications on the card"); } DropField(); @@ -5302,12 +5304,15 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { buf[i * 24 + 1 + 3], buf[i * 24 + 1 + 4], strlen((char *)&buf[i * 24 + 1 + 5]), &buf[i * 24 + 1 + 5]); + } else { + PrintAndLogEx(INFO, "There is no applications on the card"); } DropField(); return PM3_SUCCESS; } + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"-----------", CmdHelp, IfPm3Iso14443a, "---------------------- " _CYAN_("general") " ----------------------"}, @@ -5340,6 +5345,8 @@ static command_t CommandTable[] = { {"getvalue", CmdHF14ADesGetValueData, IfPm3Iso14443a, "Get value of file"}, {"read", CmdHF14ADesReadData, IfPm3Iso14443a, "Read data from standard/backup/record file"}, {"write", CmdHF14ADesWriteData, IfPm3Iso14443a, "Write data to standard/backup/record file"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("System") " -----------------------"}, +// {"test", CmdHF14ADesTest, IfPm3Iso14443a, "Test crypto"}, {NULL, NULL, NULL, NULL} }; From c99002c5e07c384945579872039d84e76e9e7183 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Jul 2021 17:59:42 +0300 Subject: [PATCH 220/309] add Get UID command --- client/src/mifare/desfirecore.c | 10 ++++++++++ client/src/mifare/desfirecore.h | 1 + 2 files changed, 11 insertions(+) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 862723587..ad4c6c545 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -872,6 +872,16 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel return PM3_SUCCESS; } +int DesfireGetUID(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { + uint8_t respcode = 0xff; + int res = DesfireExchange(dctx, MFDES_GET_UID, NULL, 0, &respcode, resp, resplen); + if (res != PM3_SUCCESS) + return res; + if (respcode != MFDES_S_OPERATION_OK) + return PM3_EAPDU_FAIL; + return PM3_SUCCESS; +} + int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { uint8_t respcode = 0xff; int res = DesfireExchange(dctx, MFDES_GET_APPLICATION_IDS, NULL, 0, &respcode, resp, resplen); diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 9eaa74f9a..080fed18d 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -39,6 +39,7 @@ int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uin int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel); +int DesfireGetUID(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); From ca983f1473f10f233b4cf8adbd1466ac804f08e9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Jul 2021 18:06:38 +0300 Subject: [PATCH 221/309] cmac can be NULL --- client/src/mifare/desfirecrypto.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 187744ec7..8960b8b96 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -265,6 +265,7 @@ void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *data, size_t len, uint8_t * DesfireCryptoEncDec(ctx, true, buffer, len, NULL, true); - memcpy(cmac, ctx->IV, kbs); + if (cmac != NULL) + memcpy(cmac, ctx->IV, kbs); } From ebcb86570e4b213e66075631ff58e4ab157f6eeb Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Jul 2021 18:41:20 +0300 Subject: [PATCH 222/309] fix length bug in the encode/decode --- client/src/mifare/desfirecrypto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 8960b8b96..f6e316096 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -189,9 +189,9 @@ void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *s size_t offset = 0; while (offset < srcdatalen) { if (use_session_key) - DesfireCryptoEncDecSingleBlock(ctx->sessionKeyMAC, ctx->keyType, srcdata + offset, data, xiv, encode, encode); + DesfireCryptoEncDecSingleBlock(ctx->sessionKeyMAC, ctx->keyType, srcdata + offset, data + offset, xiv, encode, encode); else - DesfireCryptoEncDecSingleBlock(ctx->key, ctx->keyType, srcdata + offset, data, xiv, encode, encode); + DesfireCryptoEncDecSingleBlock(ctx->key, ctx->keyType, srcdata + offset, data + offset, xiv, encode, encode); offset += block_size; } From 3c31ee793dba08d7fe93aae3269ea0a0bd9d1037 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 8 Jul 2021 09:53:50 +0200 Subject: [PATCH 223/309] make style --- armsrc/Standalone/hf_msdsal.c | 78 ++++++++-------- armsrc/Standalone/hf_reblay.c | 12 +-- client/deps/cliparser/cliparser.c | 2 +- client/src/mifare/desfirecrypto.c | 12 +-- client/src/mifare/desfirecrypto.h | 2 +- client/src/mifare/desfiresecurechan.c | 6 +- client/src/proxgui.cpp | 2 +- client/src/proxgui.h | 2 +- client/src/proxguiqt.cpp | 22 ++--- client/src/proxguiqt.h | 6 +- doc/commands.json | 122 +++++--------------------- doc/commands.md | 4 - tools/pm3_online_check.py | 4 +- tools/pm3_reblay-emulating.py | 6 +- tools/pm3_reblay-reading.py | 6 +- 15 files changed, 101 insertions(+), 185 deletions(-) diff --git a/armsrc/Standalone/hf_msdsal.c b/armsrc/Standalone/hf_msdsal.c index dbb033915..2b836c8da 100644 --- a/armsrc/Standalone/hf_msdsal.c +++ b/armsrc/Standalone/hf_msdsal.c @@ -52,7 +52,7 @@ void ModInfo(void) { * technologies. Be brave enough to share your knowledge & inspire others. Salvador Mendoza. */ - // Default GET PROCESSING +// Default GET PROCESSING static uint8_t ppdol [255] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00}; // Generate GET PROCESSING @@ -133,14 +133,14 @@ void RunMod(void) { //Specific for Visa cards: select ppse, select Visa AID, GET PROCESSING, SFI uint8_t ppse[20] = { - 0x00, 0xA4, 0x04, 0x00, 0x0e, 0x32, 0x50, 0x41, - 0x59, 0x2e, 0x53, 0x59, 0x53, 0x2e, 0x44, 0x44, - 0x46, 0x30, 0x31, 0x00 - }; + 0x00, 0xA4, 0x04, 0x00, 0x0e, 0x32, 0x50, 0x41, + 0x59, 0x2e, 0x53, 0x59, 0x53, 0x2e, 0x44, 0x44, + 0x46, 0x30, 0x31, 0x00 + }; uint8_t visa[13] = { - 0x00, 0xA4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, - 0x00, 0x03, 0x10, 0x10, 0x00 - }; + 0x00, 0xA4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, + 0x00, 0x03, 0x10, 0x10, 0x00 + }; uint8_t processing [8] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00}; uint8_t sfi[5] = {0x00, 0xb2, 0x01, 0x0c, 0x00}; @@ -168,12 +168,12 @@ void RunMod(void) { // Allocate 512 bytes for the dynamic modulation, created when the reader queries for it // Such a response is less time critical, so we can prepare them on the fly - #define DYNAMIC_RESPONSE_BUFFER_SIZE 64 - #define DYNAMIC_MODULATION_BUFFER_SIZE 512 +#define DYNAMIC_RESPONSE_BUFFER_SIZE 64 +#define DYNAMIC_MODULATION_BUFFER_SIZE 512 // UID 4 bytes(could be 7 bytes if needed it) - uint8_t flags = FLAG_4B_UID_IN_DATA; - // in case there is a read command received we shouldn't break + uint8_t flags = FLAG_4B_UID_IN_DATA; + // in case there is a read command received we shouldn't break uint8_t data[PM3_CMD_DATA_SIZE] = {0x00}; uint8_t visauid[7] = {0x01, 0x02, 0x03, 0x04}; @@ -231,10 +231,10 @@ void RunMod(void) { int button_pressed = BUTTON_HELD(1000); - if (button_pressed == BUTTON_HOLD) + if (button_pressed == BUTTON_HOLD) break; else if (button_pressed == BUTTON_SINGLE_CLICK) { - // pressing one time change between reading & emulation + // pressing one time change between reading & emulation if (state == STATE_READ) { if (chktoken == true && token[0] != 0x00) { // only change to emulation if it saved a track 2 in memory @@ -277,7 +277,7 @@ void RunMod(void) { for (uint8_t u = 0; u < apdulen; u++) { if (i == 1) { - // check for PDOL + // check for PDOL if (apdubuffer[u] == 0x9F && apdubuffer[u + 1] == 0x38) { for (uint8_t e = 0; e <= apdubuffer[u + 2]; e++) pdol[e] = apdubuffer[u + e + 2]; @@ -346,8 +346,8 @@ void RunMod(void) { iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); // command length - int len = 0; - // to check emulation status + int len = 0; + // to check emulation status int retval = PM3_SUCCESS; bool odd_reply = true; @@ -375,28 +375,28 @@ void RunMod(void) { p_response = &responses[RESP_INDEX_ATQA]; } - // received a HALT + // received a HALT } else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) { DbpString(_YELLOW_("+") "Received a HALT"); p_response = NULL; - // received a WAKEUP + // received a WAKEUP } else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) { DbpString(_YELLOW_("+") "WAKEUP Received"); prevCmd = 0; p_response = &responses[RESP_INDEX_ATQA]; - // received request for UID (cascade 1) + // received request for UID (cascade 1) } else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 2) { DbpString(_YELLOW_("+") "Request for UID C1"); p_response = &responses[RESP_INDEX_UIDC1]; - // received a SELECT (cascade 1) + // received a SELECT (cascade 1) } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) { DbpString(_YELLOW_("+") "Request for SELECT S1"); p_response = &responses[RESP_INDEX_SAKC1]; - // received a RATS request + // received a RATS request } else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { DbpString(_YELLOW_("+") "Request for RATS"); prevCmd = 0; @@ -412,39 +412,39 @@ void RunMod(void) { // depending on card reader commands, the Proxmark will answer to fool the reader // respond with PPSE - if (receivedCmd[2] == 0xA4 && receivedCmd[6] == 0x32 && prevCmd == 0) { + if (receivedCmd[2] == 0xA4 && receivedCmd[6] == 0x32 && prevCmd == 0) { uint8_t ppsea[39] = { - 0x6F, 0x23, 0x84, 0x0E, 0x32, 0x50, 0x41, 0x59, - 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, - 0x30, 0x31, 0xA5, 0x11, 0xBF, 0x0C, 0x0E, 0x61, - 0x0C, 0x4F, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03, - 0x10, 0x10, 0x87, 0x01, 0x01, 0x90, 0x00 - }; + 0x6F, 0x23, 0x84, 0x0E, 0x32, 0x50, 0x41, 0x59, + 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, + 0x30, 0x31, 0xA5, 0x11, 0xBF, 0x0C, 0x0E, 0x61, + 0x0C, 0x4F, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03, + 0x10, 0x10, 0x87, 0x01, 0x01, 0x90, 0x00 + }; memcpy(&dynamic_response_info.response[1], ppsea, sizeof(ppsea)); dynamic_response_info.response_n = sizeof(ppsea) + 1; prevCmd++; - // respond Visa AID + // respond Visa AID } else if (receivedCmd[2] == 0xA4 && receivedCmd[10] == 0x03 && receivedCmd[11] == 0x10 && prevCmd == 1) { uint8_t visauid_long[34] = { - 0x6F, 0x1E, 0x84, 0x07, 0xA0, 0x00, 0x00, 0x00, - 0x03, 0x10, 0x10, 0xA5, 0x13, 0x50, 0x0B, 0x56, - 0x49, 0x53, 0x41, 0x20, 0x43, 0x52, 0x45, 0x44, - 0x49, 0x54, 0x9F, 0x38, 0x03, 0x9F, 0x66, 0x02, - 0x90, 0x00 - }; + 0x6F, 0x1E, 0x84, 0x07, 0xA0, 0x00, 0x00, 0x00, + 0x03, 0x10, 0x10, 0xA5, 0x13, 0x50, 0x0B, 0x56, + 0x49, 0x53, 0x41, 0x20, 0x43, 0x52, 0x45, 0x44, + 0x49, 0x54, 0x9F, 0x38, 0x03, 0x9F, 0x66, 0x02, + 0x90, 0x00 + }; memcpy(&dynamic_response_info.response[1], visauid_long, sizeof(visauid_long)); dynamic_response_info.response_n = sizeof(visauid_long) + 1; prevCmd++; - // GET PROCESSING + // GET PROCESSING } else if (receivedCmd[1] == 0x80 && receivedCmd[2] == 0xA8 && receivedCmd[6] == 0x83 && prevCmd == 2) { uint8_t processing_long[10] = {0x80, 0x06, 0x00, 0x80, 0x08, 0x01, 0x01, 0x00, 0x90, 0x00}; memcpy(&dynamic_response_info.response[1], processing_long, sizeof(processing_long)); dynamic_response_info.response_n = sizeof(processing_long) + 1; prevCmd++; - // SFI + // SFI } else if (receivedCmd[1] == 0x00 && receivedCmd[2] == 0xB2 && prevCmd == 3) { uint8_t last[4] = {0x70, 0x15, 0x57, 0x13}; uint8_t statusapdu[2] = {0x90, 0x00}; @@ -504,4 +504,4 @@ void RunMod(void) { } DbpString(_YELLOW_("[=]") "exiting"); LEDsoff(); -} \ No newline at end of file +} diff --git a/armsrc/Standalone/hf_reblay.c b/armsrc/Standalone/hf_reblay.c index 65bf07988..ac85c2d70 100644 --- a/armsrc/Standalone/hf_reblay.c +++ b/armsrc/Standalone/hf_reblay.c @@ -33,12 +33,12 @@ void ModInfo(void) { * * Instructions: * -* I recommend setting up & run the other end before start sending or receving data in this Proxmark3 +* I recommend setting up & run the other end before start sending or receving data in this Proxmark3 * standalone. * * For the reading mode: * - Set up and run the other end first, to where the Proxmark will send the data. -* - After the card is detected, Proxmark3 will send a package. The first byte will be the package +* - After the card is detected, Proxmark3 will send a package. The first byte will be the package * length, then, the card data. Use the first length byte to read the whole package. * - Proxmark3 will expect a raw APDU from the other end, then it will be sent to the card. * - The answer of the card will be sent back to the connection, repeating the cycle. @@ -46,16 +46,16 @@ void ModInfo(void) { * For the emulation mode: * - Set up and run the other end first, from where the Proxmark will receive the data. * - When the Proxmark3 detected the terminal, it will send the command to the connection. -* - The first byte will be the package length, then, the terminal command. Use the first +* - The first byte will be the package length, then, the terminal command. Use the first * length byte to read the whole package. * - Proxmark3 will expect a raw APDU from the other end, then it will be sent to the terminal. * - The command of the terminal will be sent back to the connection, repeating the cycle. * -* Notes: -* - The emulation mode was tested in a real SumUp payment terminal. This does not mean +* Notes: +* - The emulation mode was tested in a real SumUp payment terminal. This does not mean * that it will work in all the terminals around the world. * - The emulation mode implements different techniques to try to keep the connection alive: -* WTX or ACK for NACK requests. Some of these requests could be denied depending on +* WTX or ACK for NACK requests. Some of these requests could be denied depending on * the reader configuration. * * diff --git a/client/deps/cliparser/cliparser.c b/client/deps/cliparser/cliparser.c index 4fa709c8f..2a5804550 100644 --- a/client/deps/cliparser/cliparser.c +++ b/client/deps/cliparser/cliparser.c @@ -342,7 +342,7 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array const char *CLIGetOptionListStr(const CLIParserOption *option_array, int value) { static const char *errmsg = "n/a"; - + for (int i = 0; i < CLI_MAX_OPTLIST_LEN && option_array[i].text != NULL; i++) { if (option_array[i].code == value) return option_array[i].text; diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 187744ec7..c3fa5b67e 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -175,17 +175,17 @@ static void DesfireCryptoEncDecSingleBlock(uint8_t *key, DesfireCryptoAlgorythm void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode, uint8_t *iv) { uint8_t data[1024] = {0}; uint8_t xiv[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; - + if (ctx->secureChannel == DACd40) memset(ctx->IV, 0, DESFIRE_MAX_CRYPTO_BLOCK_SIZE); size_t block_size = desfire_get_key_block_length(ctx->keyType); - + if (iv == NULL) memcpy(xiv, ctx->IV, block_size); else memcpy(xiv, iv, block_size); - + size_t offset = 0; while (offset < srcdatalen) { if (use_session_key) @@ -243,14 +243,14 @@ void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *data, size_t len, uint8_t * int kbs = desfire_get_key_block_length(ctx->keyType); if (kbs == 0) return; - + uint8_t buffer[padded_data_length(len, kbs)]; memset(buffer, 0, sizeof(buffer)); - + uint8_t sk1[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; uint8_t sk2[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; DesfireCMACGenerateSubkeys(ctx, sk1, sk2); - + memcpy(buffer, data, len); if ((!len) || (len % kbs)) { diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index b9f28f31a..8ff77c377 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -17,7 +17,7 @@ * * $Id$ */ - + #ifndef __DESFIRECRYPTO_H #define __DESFIRECRYPTO_H diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index b437ebc07..9e440fad4 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -130,13 +130,13 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, case DCMMACed: if (srcdatalen < DesfireGetMACLength(ctx)) break; - + memcpy(dstdata, srcdata, srcdatalen - DesfireGetMACLength(ctx)); *dstdatalen = srcdatalen - DesfireGetMACLength(ctx); - + memcpy(data, srcdata, *dstdatalen); data[*dstdatalen] = respcode; - + uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; DesfireCryptoCMAC(ctx, data, *dstdatalen + 1, cmac); if (memcmp(&srcdata[*dstdatalen], cmac, DesfireGetMACLength(ctx)) != 0) { diff --git a/client/src/proxgui.cpp b/client/src/proxgui.cpp index 0fe941133..b8d19b10a 100644 --- a/client/src/proxgui.cpp +++ b/client/src/proxgui.cpp @@ -58,7 +58,7 @@ extern "C" void RepaintGraphWindow(void) { } -// hook up picture viewer +// hook up picture viewer extern "C" void ShowPictureWindow(char *fn) { if (!gui) { // Show a notice if X11/XQuartz isn't available diff --git a/client/src/proxgui.h b/client/src/proxgui.h index d62c08d39..f5942e926 100644 --- a/client/src/proxgui.h +++ b/client/src/proxgui.h @@ -23,7 +23,7 @@ void ShowGraphWindow(void); void HideGraphWindow(void); void RepaintGraphWindow(void); -// hook up picture viewer +// hook up picture viewer void ShowPictureWindow(char *fn); void HidePictureWindow(void); void RepaintPictureWindow(void); diff --git a/client/src/proxguiqt.cpp b/client/src/proxguiqt.cpp index 0f133e052..54e431a3f 100644 --- a/client/src/proxguiqt.cpp +++ b/client/src/proxguiqt.cpp @@ -103,10 +103,10 @@ void ProxGuiQT::_HideGraphWindow(void) { plotwidget->hide(); } -// picture viewer +// picture viewer void ProxGuiQT::_ShowPictureWindow(char *fn) { - if (!plotapp) + if (!plotapp) return; if (fn == NULL) @@ -116,7 +116,7 @@ void ProxGuiQT::_ShowPictureWindow(char *fn) { if (slen == 0) return; - char *myfn = (char*)calloc(slen + 1, sizeof(uint8_t)); + char *myfn = (char *)calloc(slen + 1, sizeof(uint8_t)); if (myfn == NULL) return; @@ -132,7 +132,7 @@ void ProxGuiQT::_ShowPictureWindow(char *fn) { } QPixmap pm; - if(pm.load(myfn) == false){ + if (pm.load(myfn) == false) { qWarning("Failed to load %s", myfn); } free(myfn); @@ -146,9 +146,9 @@ void ProxGuiQT::_ShowPictureWindow(char *fn) { pictureController->lbl_pm->setAlignment(Qt::AlignCenter); QString s = QString("w: %1 h: %2") - .arg(pm.size().width()) - .arg(pm.size().height() - ); + .arg(pm.size().width()) + .arg(pm.size().height() + ); pictureController->lbl_sz->setText(s); pictureWidget->show(); } @@ -184,7 +184,7 @@ void ProxGuiQT::_StartProxmarkThread(void) { void ProxGuiQT::MainLoop() { plotapp = new QApplication(argc, argv); - + // Setup the picture widget pictureWidget = new PictureWidget(); pictureController = new Ui::PictureForm(); @@ -205,7 +205,7 @@ void ProxGuiQT::MainLoop() { connect(this, SIGNAL(ExitSignal()), this, SLOT(_Exit())); // hook up picture viewer signals - connect(this, SIGNAL(ShowPictureWindowSignal(char*)), this, SLOT(_ShowPictureWindow(char*))); + connect(this, SIGNAL(ShowPictureWindowSignal(char *)), this, SLOT(_ShowPictureWindow(char *))); connect(this, SIGNAL(RepaintPictureWindowSignal()), this, SLOT(_RepaintPictureWindow())); connect(this, SIGNAL(HidePictureWindowSignal()), this, SLOT(_HidePictureWindow())); @@ -220,7 +220,7 @@ void ProxGuiQT::MainLoop() { plotapp->exec(); } -ProxGuiQT::ProxGuiQT(int argc, char **argv, WorkerThread *wthread) : +ProxGuiQT::ProxGuiQT(int argc, char **argv, WorkerThread *wthread) : plotapp(NULL), plotwidget(NULL), pictureController(NULL), pictureWidget(NULL), argc(argc), argv(argv), proxmarkThread(wthread) { } @@ -253,7 +253,7 @@ PictureWidget::PictureWidget() { // if (session.preferences_loaded) // setGeometry(session.pw.x, session.pw.y, session.pw.w, session.pw.h); // else - resize(400, 400); + resize(400, 400); } void PictureWidget::closeEvent(QCloseEvent *event) { diff --git a/client/src/proxguiqt.h b/client/src/proxguiqt.h index d9f3f204b..326274ae8 100644 --- a/client/src/proxguiqt.h +++ b/client/src/proxguiqt.h @@ -149,7 +149,7 @@ class ProxGuiQT : public QObject { void RepaintGraphWindow(void); void HideGraphWindow(void); - // hook up picture viewer + // hook up picture viewer void ShowPictureWindow(char *fn); void HidePictureWindow(void); void RepaintPictureWindow(void); @@ -162,7 +162,7 @@ class ProxGuiQT : public QObject { void _RepaintGraphWindow(void); void _HideGraphWindow(void); - // hook up picture viewer + // hook up picture viewer void _ShowPictureWindow(char *fn); void _HidePictureWindow(void); void _RepaintPictureWindow(void); @@ -175,7 +175,7 @@ class ProxGuiQT : public QObject { void RepaintGraphWindowSignal(void); void HideGraphWindowSignal(void); void ExitSignal(void); - + // hook up picture viewer signals void ShowPictureWindowSignal(char *fn); void HidePictureWindowSignal(void); diff --git a/doc/commands.json b/doc/commands.json index 8f191e302..f426c4160 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -973,7 +973,7 @@ }, "help": { "command": "help", - "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log e:\\proxspace\\pm3/.proxmark3/logs/log_20210706.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", + "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log /home/phil/.proxmark3/logs/log_20210708.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", "notes": [ "auto" ], @@ -1722,22 +1722,6 @@ ], "usage": "hf cipurse auth [-hav] [-n ] [-k ]" }, - "hf cipurse default": { - "command": "hf cipurse default", - "description": "set default parameters for access to cipurse card", - "notes": [ - "hf cipurse default -n 1 -k 65656565656565656565656565656565 --fid 2ff7 -> set key, key id and file id" - ], - "offline": false, - "options": [ - "-h, --help this help", - "--clear resets to defaults", - "-n key id", - "-k, --key authentication key", - "--fid file id" - ], - "usage": "hf cipurse default [-h] [--clear] [-n ] [-k ] [--fid ]" - }, "hf cipurse delete": { "command": "hf cipurse delete", "description": "read file by file id with key id and key. if no key is supplied, default key of 737373...7373 will be used", @@ -3938,31 +3922,6 @@ ], "usage": "hf mf wrbl [-hab] --blk [-k ] [-d ]" }, - "hf mfdes auth": { - "command": "hf mfdes auth", - "description": "authenticates mifare desfire using key", - "notes": [ - "hf mfdes auth -m 3 -t 4 -a 808301 -n 0 -k 00000000000000000000000000000000 -> aes,keynumber 0, aid 0x803201", - "hf mfdes auth -m 2 -t 2 -a 000000 -n 1 -k 00000000000000000000000000000000 -> 3des,keynumber 1, aid 0x000000", - "hf mfdes auth -m 1 -t 1 -a 000000 -n 2 -k 0000000000000000 -> des,keynumber 2, aid 0x000000", - "hf mfdes auth -m 1 -t 1 -a 000000 -n 0 -> des, defaultkey, aid 0x000000", - "hf mfdes auth -m 2 -t 2 -a 000000 -n 0 -> 3des, defaultkey, aid 0x000000", - "hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> 3k3des, defaultkey, aid 0x000000", - "hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> aes, defaultkey, aid 0x000000" - ], - "offline": false, - "options": [ - "-h, --help this help", - "-m, --type auth type (1=normal, 2=iso, 3=aes)", - "-t, --algo crypt algo (1=des, 2=3des(2k2des), 3=3k3des, 4=aes)", - "-a, --aid aid used for authentification (hex 3 bytes)", - "-n, --keyno key number used for authentification", - "-k, --key key for checking (hex 8-24 bytes)", - "-d, --kdf key derivation function (kdf) (0=none, 1=an10922, 2=gallagher)", - "-i, --kdfi kdf input (hex 1-31 bytes)" - ], - "usage": "hf mfdes auth [-h] [-m ] [-t ] [-a ]... [-n ] [-k ] [-d ] [-i ]" - }, "hf mfdes bruteaid": { "command": "hf mfdes bruteaid", "description": "recover aids by bruteforce. warning: this command takes a long time", @@ -4193,50 +4152,6 @@ ], "usage": "hf mfdes formatpicc [-h]" }, - "hf mfdes getaids": { - "command": "hf mfdes getaids", - "description": "get application ids list from card. master key needs to be provided.", - "notes": [ - "hf mfdes getaids -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup" - ], - "offline": false, - "options": [ - "-h, --help this help", - "-a, --apdu show apdu requests and responses", - "-v, --verbose show technical data", - "-n, --keyno key number", - "-t, --algo crypt algo: des, 2tdea, 3tdea, aes", - "-k, --key key for authenticate (hex 8(des), 16(2tdea or aes) or 24(3tdea) bytes)", - "-f, --kdf key derivation function (kdf): none, an10922, gallagher", - "-i, --kdfi kdf input (hex 1-31 bytes)", - "-m, --cmode communicaton mode: plain/mac/encrypt", - "-c, --ccset communicaton command set: native/niso/iso", - "-s, --schann secure channel: d40/ev1/ev2" - ], - "usage": "hf mfdes getaids [-hav] [-n ] [-t ] [-k ] [-f ] [-i ] [-m ] [-c ] [-s ]" - }, - "hf mfdes getappnames": { - "command": "hf mfdes getappnames", - "description": "get application ids, iso ids and df names from card. master key needs to be provided.", - "notes": [ - "hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup" - ], - "offline": false, - "options": [ - "-h, --help this help", - "-a, --apdu show apdu requests and responses", - "-v, --verbose show technical data", - "-n, --keyno key number", - "-t, --algo crypt algo: des, 2tdea, 3tdea, aes", - "-k, --key key for authenticate (hex 8(des), 16(2tdea or aes) or 24(3tdea) bytes)", - "-f, --kdf key derivation function (kdf): none, an10922, gallagher", - "-i, --kdfi kdf input (hex 1-31 bytes)", - "-m, --cmode communicaton mode: plain/mac/encrypt", - "-c, --ccset communicaton command set: native/niso/iso", - "-s, --schann secure channel: d40/ev1/ev2" - ], - "usage": "hf mfdes getappnames [-hav] [-n ] [-t ] [-k ] [-f ] [-i ] [-m ] [-c ] [-s ]" - }, "hf mfdes getuid": { "command": "hf mfdes getuid", "description": "get uid from a mifare desfire tag", @@ -4265,23 +4180,28 @@ }, "hf mfdes help": { "command": "hf mfdes help", - "description": "help this help list list desfire (iso 14443a) history --------------------------------------------------------------------------------------- hf mfdes default available offline: no get application ids, iso ids and df names from card. master key needs to be provided.", + "description": "help this help list list desfire (iso 14443a) history --------------------------------------------------------------------------------------- hf mfdes auth available offline: no authenticates mifare desfire using key", "notes": [ - "hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup" + "hf mfdes auth -m 3 -t 4 -a 808301 -n 0 -k 00000000000000000000000000000000 -> aes,keynumber 0, aid 0x803201", + "hf mfdes auth -m 2 -t 2 -a 000000 -n 1 -k 00000000000000000000000000000000 -> 3des,keynumber 1, aid 0x000000", + "hf mfdes auth -m 1 -t 1 -a 000000 -n 2 -k 0000000000000000 -> des,keynumber 2, aid 0x000000", + "hf mfdes auth -m 1 -t 1 -a 000000 -n 0 -> des, defaultkey, aid 0x000000", + "hf mfdes auth -m 2 -t 2 -a 000000 -n 0 -> 3des, defaultkey, aid 0x000000", + "hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> 3k3des, defaultkey, aid 0x000000", + "hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> aes, defaultkey, aid 0x000000" ], "offline": true, "options": [ "-h, --help this help", - "-n, --keyno key number", - "-t, --algo crypt algo: des, 2tdea, 3tdea, aes", - "-k, --key key for authenticate (hex 8(des), 16(2tdea or aes) or 24(3tdea) bytes)", - "-f, --kdf key derivation function (kdf): none, an10922, gallagher", - "-i, --kdfi kdf input (hex 1-31 bytes)", - "-m, --cmode communicaton mode: plain/mac/encrypt", - "-c, --ccset communicaton command set: native/niso/iso", - "-s, --schann secure channel: d40/ev1/ev2" + "-m, --type auth type (1=normal, 2=iso, 3=aes)", + "-t, --algo crypt algo (1=des, 2=3des(2k2des), 3=3k3des, 4=aes)", + "-a, --aid aid used for authentification (hex 3 bytes)", + "-n, --keyno key number used for authentification", + "-k, --key key for checking (hex 8-24 bytes)", + "-d, --kdf key derivation function (kdf) (0=none, 1=an10922, 2=gallagher)", + "-i, --kdfi kdf input (hex 1-31 bytes)" ], - "usage": "hf mfdes default [-h] [-n ] [-t ] [-k ] [-f ] [-i ] [-m ] [-c ] [-s ]" + "usage": "hf mfdes auth [-h] [-m ] [-t ] [-a ]... [-n ] [-k ] [-d ] [-i ]" }, "hf mfdes info": { "command": "hf mfdes info", @@ -5158,8 +5078,8 @@ "command": "hw connect", "description": "connects to a proxmark3 device via specified serial port. baudrate here is only for physical uart or uart-bt, not for usb-cdc or blue shark add-on", "notes": [ - "hw connect -p com3", - "hw connect -p com3 -b 115200" + "hw connect -p /dev/ttyacm0", + "hw connect -p /dev/ttyacm0 -b 115200" ], "offline": true, "options": [ @@ -9281,8 +9201,8 @@ } }, "metadata": { - "commands_extracted": 575, + "commands_extracted": 571, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2021-07-06T09:14:57" + "extracted_on": "2021-07-08T07:53:00" } } \ No newline at end of file diff --git a/doc/commands.md b/doc/commands.md index c3b056e47..433b44e26 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -247,7 +247,6 @@ Check column "offline" for their availability. |`hf cipurse write `|N |`Write binary file` |`hf cipurse aread `|N |`Read file attributes` |`hf cipurse delete `|N |`Delete file` -|`hf cipurse default `|N |`Set default key and file id for all the other commands` |`hf cipurse test `|Y |`Tests` @@ -501,7 +500,6 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- |`hf mfdes help `|Y |`This help` -|`hf mfdes default `|N |`[new]Set defaults for all the commands` |`hf mfdes auth `|N |`Tries a MIFARE DesFire Authentication` |`hf mfdes changekey `|N |`Change Key` |`hf mfdes chk `|N |`Check keys` @@ -514,8 +512,6 @@ Check column "offline" for their availability. |`hf mfdes createaid `|N |`Create Application ID` |`hf mfdes deleteaid `|N |`Delete Application ID` |`hf mfdes selectaid `|N |`Select Application ID` -|`hf mfdes getaids `|N |`[new]Get Application IDs list` -|`hf mfdes getappnames `|N |`[new]Get Applications list` |`hf mfdes changevalue `|N |`Write value of a value file (credit/debit/clear)` |`hf mfdes clearfile `|N |`Clear record File` |`hf mfdes createfile `|N |`Create Standard/Backup File` diff --git a/tools/pm3_online_check.py b/tools/pm3_online_check.py index 73959d32d..ac7ef152b 100755 --- a/tools/pm3_online_check.py +++ b/tools/pm3_online_check.py @@ -226,7 +226,7 @@ def main(): child.sendline('hw version') i = child.expect('pm3 --> ') msg = escape_ansi(str(child.before)) - + if signature_msg in msg: print("[+] RDV4 signature ", color('[OK]', fg='green')) res += 1 @@ -238,7 +238,7 @@ def main(): child.sendline('hw status') i = child.expect('pm3 --> ') msg = escape_ansi(str(child.before)) - + if sm_version in msg: print("[+] Smart card firmware version ", color('[OK]', fg='green')) res += 1 diff --git a/tools/pm3_reblay-emulating.py b/tools/pm3_reblay-emulating.py index 280d5ccb2..27b88f06b 100644 --- a/tools/pm3_reblay-emulating.py +++ b/tools/pm3_reblay-emulating.py @@ -47,9 +47,9 @@ for x in apdu: print(toHexString(x)) print('--') - lenpk = ser.read(1) #first byte is the buffer length - bufferlen = pd(lenpk)[0] + lenpk = ser.read(1) #first byte is the buffer length + bufferlen = pd(lenpk)[0] - buffer = pd(ser.read(bufferlen)) + buffer = pd(ser.read(bufferlen)) print('Terminal command:'), print(toHexString(buffer)) diff --git a/tools/pm3_reblay-reading.py b/tools/pm3_reblay-reading.py index b7a2fa615..26fa96844 100644 --- a/tools/pm3_reblay-reading.py +++ b/tools/pm3_reblay-reading.py @@ -57,10 +57,10 @@ for x in apdu: ser.write(x) print(toHexString(x)) - lenpk = ser.read(1) #first byte is the buffer length - bufferlen = pd(lenpk)[0] + lenpk = ser.read(1) #first byte is the buffer length + bufferlen = pd(lenpk)[0] - buffer = pd(ser.read(bufferlen)) + buffer = pd(ser.read(bufferlen)) print('Card Response:'), print(toHexString(buffer)) print('--') From 567cbadc58ef76b2805c1cc085d2254a6cac99ee Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 8 Jul 2021 17:04:44 +0300 Subject: [PATCH 224/309] add some session params --- client/src/mifare/desfirecrypto.c | 2 ++ client/src/mifare/desfirecrypto.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index f6e316096..9beeefe7b 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -56,6 +56,8 @@ void DesfireClearSession(DesfireContext *ctx) { memset(ctx->sessionKeyMAC, 0, sizeof(ctx->sessionKeyMAC)); memset(ctx->sessionKeyEnc, 0, sizeof(ctx->sessionKeyEnc)); memset(ctx->lastIV, 0, sizeof(ctx->lastIV)); + ctx->lastCommand = 0; + ctx->lastRequestZeroLen = false; ctx->cntrTx = 0; ctx->cntrRx = 0; memset(ctx->TI, 0, sizeof(ctx->TI)); diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index b9f28f31a..4c0eb0a2f 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -78,6 +78,8 @@ typedef struct DesfireContextS { uint8_t sessionKeyMAC[DESFIRE_MAX_KEY_SIZE]; uint8_t sessionKeyEnc[DESFIRE_MAX_KEY_SIZE]; // look at mifare4.h - mf4Session_t uint8_t lastIV[DESFIRE_MAX_KEY_SIZE]; + uint8_t lastCommand; + bool lastRequestZeroLen; //mf4Session_t AESSession; uint16_t cntrTx; // for AES uint16_t cntrRx; // for AES From 8fd896478e9e23261eee73f8f9fc735c72b11eb9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 8 Jul 2021 17:07:02 +0300 Subject: [PATCH 225/309] ev1 channel reorganized --- client/src/mifare/desfiresecurechan.c | 101 ++++++++++++++------------ 1 file changed, 53 insertions(+), 48 deletions(-) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index b437ebc07..58b7dd4f1 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -60,31 +60,34 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { uint8_t data[1024] = {0}; - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; + // we calc MAC anyway + // if encypted channel and no data - we only calc MAC + if (ctx->commMode == DCMPlain || ctx->commMode == DCMMACed || (ctx->commMode == DCMEncrypted && srcdatalen == 0)) { + data[0] = cmd; + memcpy(&data[1], srcdata, srcdatalen); + uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + DesfireCryptoCMAC(ctx, data, srcdatalen + 1, cmac); +PrintAndLogEx(INFO, "mac iv: %s", sprint_hex(ctx->IV, 16)); - switch (ctx->commMode) { - case DCMPlain: - case DCMMACed: - data[0] = cmd; - memcpy(&data[1], srcdata, srcdatalen); - uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; - DesfireCryptoCMAC(ctx, data, srcdatalen + 1, cmac); - - memcpy(dstdata, srcdata, srcdatalen); - if (srcdatalen != 0 && ctx->commMode == DCMMACed) { - memcpy(&dstdata[srcdatalen], cmac, DesfireGetMACLength(ctx)); - *dstdatalen = srcdatalen + DesfireGetMACLength(ctx); - } - break; - case DCMEncrypted: - break; - case DCMNone: - ; + memcpy(dstdata, srcdata, srcdatalen); + if (srcdatalen != 0 && ctx->commMode == DCMMACed) { + memcpy(&dstdata[srcdatalen], cmac, DesfireGetMACLength(ctx)); + *dstdatalen = srcdatalen + DesfireGetMACLength(ctx); + } + } else if (ctx->commMode == DCMEncrypted) { + + + + } else { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; } } void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { + ctx->lastCommand = cmd; + ctx->lastRequestZeroLen = (srcdatalen == 0); + switch (ctx->secureChannel) { case DACd40: DesfireSecureChannelEncodeD40(ctx, cmd, srcdata, srcdatalen, dstdata, dstdatalen); @@ -122,36 +125,38 @@ static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { uint8_t data[1024] = {0}; - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - - switch (ctx->commMode) { - case DCMPlain: - case DCMMACed: - if (srcdatalen < DesfireGetMACLength(ctx)) - break; - - memcpy(dstdata, srcdata, srcdatalen - DesfireGetMACLength(ctx)); - *dstdatalen = srcdatalen - DesfireGetMACLength(ctx); - - memcpy(data, srcdata, *dstdatalen); - data[*dstdatalen] = respcode; - - uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; - DesfireCryptoCMAC(ctx, data, *dstdatalen + 1, cmac); - if (memcmp(&srcdata[*dstdatalen], cmac, DesfireGetMACLength(ctx)) != 0) { - PrintAndLogEx(WARNING, "Received MAC is not match with calculated"); - PrintAndLogEx(INFO, " received MAC: %s", sprint_hex(&srcdata[*dstdatalen], desfire_get_key_block_length(ctx->keyType))); - PrintAndLogEx(INFO, " calculated MAC: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); - } - - break; - case DCMEncrypted: - break; - case DACNone: + // if comm mode = plain --> response with MAC + // if request is not zero length --> response MAC + if (ctx->commMode == DCMPlain || ctx->commMode == DCMMACed || (ctx->commMode == DCMEncrypted && !ctx->lastRequestZeroLen)) { + if (srcdatalen < DesfireGetMACLength(ctx)) { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; - break; + return; + } + + memcpy(dstdata, srcdata, srcdatalen - DesfireGetMACLength(ctx)); + *dstdatalen = srcdatalen - DesfireGetMACLength(ctx); + + memcpy(data, srcdata, *dstdatalen); + data[*dstdatalen] = respcode; + + uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + DesfireCryptoCMAC(ctx, data, *dstdatalen + 1, cmac); + if (memcmp(&srcdata[*dstdatalen], cmac, DesfireGetMACLength(ctx)) != 0) { + PrintAndLogEx(WARNING, "Received MAC is not match with calculated"); + PrintAndLogEx(INFO, " received MAC: %s", sprint_hex(&srcdata[*dstdatalen], desfire_get_key_block_length(ctx->keyType))); + PrintAndLogEx(INFO, " calculated MAC: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); + } + } else if (ctx->commMode == DCMEncrypted) { + //mifare_cypher_blocks_chained(tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER); +PrintAndLogEx(INFO, "data: %s", sprint_hex(srcdata, srcdatalen)); +PrintAndLogEx(INFO, "dec iv: %s", sprint_hex(ctx->IV, 16)); + DesfireCryptoEncDec(ctx, true, srcdata, srcdatalen, dstdata, false); +PrintAndLogEx(INFO, "dec iv: %s", sprint_hex(ctx->IV, 16)); + PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); + } else { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; } } From cf7949c1f8e48556cced08d4cf73062469444d9e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 8 Jul 2021 18:26:07 +0300 Subject: [PATCH 226/309] fix chaining --- client/src/mifare/desfirecrypto.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 5cd045713..b65512b23 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -165,13 +165,14 @@ static void DesfireCryptoEncDecSingleBlock(uint8_t *key, DesfireCryptoAlgorythm break; } - memcpy(dstdata, edata, block_size); - if (dir_to_send) { memcpy(ivect, edata, block_size); } else { + bin_xor(edata, ivect, block_size); memcpy(ivect, data, block_size); } + + memcpy(dstdata, edata, block_size); } void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode, uint8_t *iv) { From 0fa708acb2eb5222855e77cf401e282b2b9b6af3 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 01:26:47 +0300 Subject: [PATCH 227/309] add crc32 check --- client/src/mifare/desfire_crypto.c | 6 ++++++ client/src/mifare/desfire_crypto.h | 1 + 2 files changed, 7 insertions(+) diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 935083ab4..137eb8089 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -976,6 +976,12 @@ void desfire_crc32_append(uint8_t *data, const size_t len) { crc32_ex(data, len, data + len); } +bool desfire_crc32_check(uint8_t *data, const size_t len, uint8_t *crc) { + uint8_t ccrc[4] = {0}; + crc32_ex(data, len, ccrc); + return (memcmp(ccrc, crc, 4) == 0); +} + void iso14443a_crc_append(uint8_t *data, size_t len) { return compute_crc(CRC_14443_A, data, len, data + len, data + len + 1); } diff --git a/client/src/mifare/desfire_crypto.h b/client/src/mifare/desfire_crypto.h index 346a7e50c..8cdf76ab6 100644 --- a/client/src/mifare/desfire_crypto.h +++ b/client/src/mifare/desfire_crypto.h @@ -149,6 +149,7 @@ void mifare_kdf_an10922(const desfirekey_t key, const uint8_t *data, size_t len) void desfire_crc32(const uint8_t *data, const size_t len, uint8_t *crc); void desfire_crc32_append(uint8_t *data, const size_t len); +bool desfire_crc32_check(uint8_t *data, const size_t len, uint8_t *crc); void iso14443a_crc_append(uint8_t *data, size_t len); void iso14443a_crc(uint8_t *data, size_t len, uint8_t *pbtCrc); #endif From 2fde5d90aea63047a6e74e137100762dbf8ad910 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 01:27:28 +0300 Subject: [PATCH 228/309] crc32 ok, ev1/enc channel ok. --- client/src/mifare/desfiresecurechan.c | 49 ++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 58b7dd4f1..c854ce861 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -67,7 +67,6 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint memcpy(&data[1], srcdata, srcdatalen); uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; DesfireCryptoCMAC(ctx, data, srcdatalen + 1, cmac); -PrintAndLogEx(INFO, "mac iv: %s", sprint_hex(ctx->IV, 16)); memcpy(dstdata, srcdata, srcdatalen); if (srcdatalen != 0 && ctx->commMode == DCMMACed) { @@ -148,12 +147,52 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, PrintAndLogEx(INFO, " calculated MAC: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); } } else if (ctx->commMode == DCMEncrypted) { - //mifare_cypher_blocks_chained(tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER); -PrintAndLogEx(INFO, "data: %s", sprint_hex(srcdata, srcdatalen)); -PrintAndLogEx(INFO, "dec iv: %s", sprint_hex(ctx->IV, 16)); + if (srcdatalen < desfire_get_key_block_length(ctx->keyType)) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + return; + } + DesfireCryptoEncDec(ctx, true, srcdata, srcdatalen, dstdata, false); -PrintAndLogEx(INFO, "dec iv: %s", sprint_hex(ctx->IV, 16)); PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); + + size_t crcpos = srcdatalen - 1; + while (crcpos > 0) + if (dstdata[crcpos] == 0) + crcpos--; + else + break; + crcpos++; // crc may be 0x00000000 + *dstdatalen = crcpos; + PrintAndLogEx(INFO, "crcpos: %d", crcpos); + if (crcpos < 4) { + PrintAndLogEx(WARNING, "No space for crc. pos: %d", crcpos); + return; + } + + uint8_t crcdata[1024] = {0}; + bool crcok = false; + for (int i = 0; i < 5; i++) { + if (crcpos == 0) + break; + if (crcpos - i + 4 > srcdatalen) + continue; + + memcpy(crcdata, dstdata, crcpos - i); + crcdata[crcpos - i] = respcode; + if (desfire_crc32_check(crcdata, crcpos - i + 1, &dstdata[crcpos - i])) { + crcpos -= i; + crcok = true; + break; + } + } + + if (crcok) { + *dstdatalen = crcpos; + } else { + PrintAndLogEx(WARNING, "CRC32 error. pos: %d", crcpos); + } + } else { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; From 70bedbd7d10b7ac7aba0eba4fdaa34ce7ae705d5 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 01:41:25 +0300 Subject: [PATCH 229/309] fix some d40 channel conditions --- client/src/mifare/desfiresecurechan.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index c854ce861..5f9fec5a9 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -40,15 +40,20 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint rlen = padded_data_length(srcdatalen, desfire_get_key_block_length(ctx->keyType)); memcpy(data, srcdata, srcdatalen); + memset(ctx->IV, 0, sizeof(ctx->IV)); DesfireCryptoEncDec(ctx, true, data, rlen, NULL, true); memcpy(dstdata, srcdata, srcdatalen); memcpy(&dstdata[srcdatalen], ctx->IV, 4); *dstdatalen = rlen; break; case DCMEncrypted: + if (srcdatalen == 0) + break; + rlen = padded_data_length(srcdatalen + 2, desfire_get_key_block_length(ctx->keyType)); // 2 - crc16 memcpy(data, srcdata, srcdatalen); compute_crc(CRC_14443_A, data, srcdatalen, &data[srcdatalen], &data[srcdatalen + 1]); + memset(ctx->IV, 0, sizeof(ctx->IV)); DesfireCryptoEncDec(ctx, true, data, rlen, dstdata, true); *dstdatalen = rlen; break; From ec79e35dcc916c53568286cf6df272c9dd5500ac Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 13:08:49 +0300 Subject: [PATCH 230/309] add crc16 check --- client/src/mifare/desfire_crypto.c | 8 +++++++- client/src/mifare/desfire_crypto.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 137eb8089..23c8b1fd9 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -978,7 +978,7 @@ void desfire_crc32_append(uint8_t *data, const size_t len) { bool desfire_crc32_check(uint8_t *data, const size_t len, uint8_t *crc) { uint8_t ccrc[4] = {0}; - crc32_ex(data, len, ccrc); + desfire_crc32(data, len, ccrc); return (memcmp(ccrc, crc, 4) == 0); } @@ -989,3 +989,9 @@ void iso14443a_crc_append(uint8_t *data, size_t len) { void iso14443a_crc(uint8_t *data, size_t len, uint8_t *pbtCrc) { return compute_crc(CRC_14443_A, data, len, pbtCrc, pbtCrc + 1); } + +bool iso14443a_crc_check(uint8_t *data, const size_t len, uint8_t *crc) { + uint8_t ccrc[2] = {0}; + iso14443a_crc(data, len, ccrc); + return (memcmp(ccrc, crc, 2) == 0); +} diff --git a/client/src/mifare/desfire_crypto.h b/client/src/mifare/desfire_crypto.h index 8cdf76ab6..689c0d56c 100644 --- a/client/src/mifare/desfire_crypto.h +++ b/client/src/mifare/desfire_crypto.h @@ -152,4 +152,5 @@ void desfire_crc32_append(uint8_t *data, const size_t len); bool desfire_crc32_check(uint8_t *data, const size_t len, uint8_t *crc); void iso14443a_crc_append(uint8_t *data, size_t len); void iso14443a_crc(uint8_t *data, size_t len, uint8_t *pbtCrc); +bool iso14443a_crc_check(uint8_t *data, const size_t len, uint8_t *crc); #endif From a7f39a1b79f3800960de69db948ebb0b83ed4134 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 13:09:59 +0300 Subject: [PATCH 231/309] move crc search function to desfirecrypto --- client/src/mifare/desfirecrypto.c | 44 +++++++++++++++++++++++++++ client/src/mifare/desfirecrypto.h | 1 + client/src/mifare/desfiresecurechan.c | 39 +++--------------------- 3 files changed, 50 insertions(+), 34 deletions(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index b65512b23..246545e9e 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -109,6 +109,50 @@ size_t DesfireGetMACLength(DesfireContext *ctx) { return mac_length; } +size_t DesfireSearchCRCPos(uint8_t *data, size_t datalen, uint8_t respcode, uint8_t crclen) { + size_t crcpos = datalen - 1; + while (crcpos > 0) + if (data[crcpos] == 0) + crcpos--; + else + break; + crcpos++; // crc may be 0x00000000 or 0x0000 + PrintAndLogEx(INFO, "crcpos: %d", crcpos); + if (crcpos < crclen) { + PrintAndLogEx(WARNING, "No space for crc. pos: %d", crcpos); + return 0; + } + + uint8_t crcdata[1024] = {0}; + bool crcok = false; + for (int i = 0; i < crclen + 1; i++) { + PrintAndLogEx(INFO, "--crcpos: %d", crcpos - i); + if (crcpos - i == 0) + break; + if (crcpos - i + crclen > datalen) + continue; + PrintAndLogEx(INFO, "--crcposcheck: %d", crcpos - i); + + memcpy(crcdata, data, crcpos - i); + crcdata[crcpos - i] = respcode; + bool res; + if (crclen == 4) + res = desfire_crc32_check(crcdata, crcpos - i + 1, &data[crcpos - i]); + else + res = iso14443a_crc_check(crcdata, crcpos - i + 1, &data[crcpos - i]); + if (res) { + PrintAndLogEx(INFO, "--crc OK pos: %d", crcpos - i); + crcpos -= i; + crcok = true; + break; + } + } + if (!crcok) + crcpos = 0; + + return crcpos; +} + static void DesfireCryptoEncDecSingleBlock(uint8_t *key, DesfireCryptoAlgorythm keyType, uint8_t *data, uint8_t *dstdata, uint8_t *ivect, bool dir_to_send, bool encode) { size_t block_size = desfire_get_key_block_length(keyType); uint8_t sdata[MAX_CRYPTO_BLOCK_SIZE] = {0}; diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index ff12335e6..824225b39 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -95,6 +95,7 @@ void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo, uint8_t *kdfInput, uint bool DesfireIsAuthenticated(DesfireContext *dctx); size_t DesfireGetMACLength(DesfireContext *ctx); +size_t DesfireSearchCRCPos(uint8_t *data, size_t datalen, uint8_t respcode, uint8_t crclen); void DesfireCryptoEncDec(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode); void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode, uint8_t *iv); diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 5f9fec5a9..b62a0a056 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -161,41 +161,12 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, DesfireCryptoEncDec(ctx, true, srcdata, srcdatalen, dstdata, false); PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); - size_t crcpos = srcdatalen - 1; - while (crcpos > 0) - if (dstdata[crcpos] == 0) - crcpos--; - else - break; - crcpos++; // crc may be 0x00000000 - *dstdatalen = crcpos; - PrintAndLogEx(INFO, "crcpos: %d", crcpos); - if (crcpos < 4) { - PrintAndLogEx(WARNING, "No space for crc. pos: %d", crcpos); - return; - } - - uint8_t crcdata[1024] = {0}; - bool crcok = false; - for (int i = 0; i < 5; i++) { - if (crcpos == 0) - break; - if (crcpos - i + 4 > srcdatalen) - continue; - - memcpy(crcdata, dstdata, crcpos - i); - crcdata[crcpos - i] = respcode; - if (desfire_crc32_check(crcdata, crcpos - i + 1, &dstdata[crcpos - i])) { - crcpos -= i; - crcok = true; - break; - } - } - - if (crcok) { - *dstdatalen = crcpos; + size_t puredatalen = DesfireSearchCRCPos(dstdata, srcdatalen, respcode, 4); + if (puredatalen != 0) { + *dstdatalen = puredatalen; } else { - PrintAndLogEx(WARNING, "CRC32 error. pos: %d", crcpos); + PrintAndLogEx(WARNING, "CRC32 error."); + *dstdatalen = srcdatalen; } } else { From bed25108f6c52b3895794b77b5356a75ad1ccf41 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 13:14:42 +0300 Subject: [PATCH 232/309] d40/enc works --- client/src/mifare/desfiresecurechan.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index b62a0a056..dd66b9e54 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -117,6 +117,22 @@ static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, break; case DCMEncrypted: + if (srcdatalen < desfire_get_key_block_length(ctx->keyType)) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + return; + } + + DesfireCryptoEncDec(ctx, true, srcdata, srcdatalen, dstdata, false); + PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); + + size_t puredatalen = DesfireSearchCRCPos(dstdata, srcdatalen, respcode, 2); + if (puredatalen != 0) { + *dstdatalen = puredatalen; + } else { + PrintAndLogEx(WARNING, "CRC32 error."); + *dstdatalen = srcdatalen; + } break; case DCMPlain: case DACNone: From 77a66a024b108cfa9bcb8e4db9f95169a43c9ee0 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 14:01:22 +0300 Subject: [PATCH 233/309] remove debug --- client/src/mifare/desfiresecurechan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index dd66b9e54..c2001bdf0 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -124,13 +124,13 @@ static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, } DesfireCryptoEncDec(ctx, true, srcdata, srcdatalen, dstdata, false); - PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); + //PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); size_t puredatalen = DesfireSearchCRCPos(dstdata, srcdatalen, respcode, 2); if (puredatalen != 0) { *dstdatalen = puredatalen; } else { - PrintAndLogEx(WARNING, "CRC32 error."); + PrintAndLogEx(WARNING, "CRC16 error."); *dstdatalen = srcdatalen; } break; @@ -175,7 +175,7 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, } DesfireCryptoEncDec(ctx, true, srcdata, srcdatalen, dstdata, false); - PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); + //PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); size_t puredatalen = DesfireSearchCRCPos(dstdata, srcdatalen, respcode, 4); if (puredatalen != 0) { From 08d8ac4f9f42096752d70cc7a2ecbb73a80b1680 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 14:01:57 +0300 Subject: [PATCH 234/309] fix bug with false-positive crc16 and remove debug --- client/src/mifare/desfirecrypto.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 246545e9e..87fb4e1a1 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -117,21 +117,18 @@ size_t DesfireSearchCRCPos(uint8_t *data, size_t datalen, uint8_t respcode, uint else break; crcpos++; // crc may be 0x00000000 or 0x0000 - PrintAndLogEx(INFO, "crcpos: %d", crcpos); if (crcpos < crclen) { PrintAndLogEx(WARNING, "No space for crc. pos: %d", crcpos); return 0; } uint8_t crcdata[1024] = {0}; - bool crcok = false; + size_t crcposfound = 0; for (int i = 0; i < crclen + 1; i++) { - PrintAndLogEx(INFO, "--crcpos: %d", crcpos - i); if (crcpos - i == 0) break; if (crcpos - i + crclen > datalen) continue; - PrintAndLogEx(INFO, "--crcposcheck: %d", crcpos - i); memcpy(crcdata, data, crcpos - i); crcdata[crcpos - i] = respcode; @@ -139,18 +136,13 @@ size_t DesfireSearchCRCPos(uint8_t *data, size_t datalen, uint8_t respcode, uint if (crclen == 4) res = desfire_crc32_check(crcdata, crcpos - i + 1, &data[crcpos - i]); else - res = iso14443a_crc_check(crcdata, crcpos - i + 1, &data[crcpos - i]); + res = iso14443a_crc_check(data, crcpos - i, &data[crcpos - i]); if (res) { - PrintAndLogEx(INFO, "--crc OK pos: %d", crcpos - i); - crcpos -= i; - crcok = true; - break; + crcposfound = crcpos - i; } } - if (!crcok) - crcpos = 0; - return crcpos; + return crcposfound; } static void DesfireCryptoEncDecSingleBlock(uint8_t *key, DesfireCryptoAlgorythm keyType, uint8_t *data, uint8_t *dstdata, uint8_t *ivect, bool dir_to_send, bool encode) { From 50264dcbf1a3be4fe977c7961cb246328976ded6 Mon Sep 17 00:00:00 2001 From: Iceman Date: Fri, 9 Jul 2021 13:14:02 +0200 Subject: [PATCH 235/309] Update 0_Compilation-Instructions.md `make -j` is the preferred way. --- doc/md/Use_of_Proxmark/0_Compilation-Instructions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md b/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md index c40d18458..2196bff39 100644 --- a/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md +++ b/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md @@ -21,7 +21,7 @@ git pull ## Clean and compile everything ```sh -make clean && make all +make clean && make -j ``` ### if you got an error From 370c4cf5a43f5a5dd3afd15d0162c8442e8bfc96 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 14:43:12 +0300 Subject: [PATCH 236/309] make style --- client/src/mifare/desfirecrypto.c | 4 +- client/src/mifare/desfiresecurechan.c | 48 ++++----- doc/commands.json | 146 ++++++++++++++++++++------ doc/commands.md | 5 + 4 files changed, 144 insertions(+), 59 deletions(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 87fb4e1a1..64773c229 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -129,7 +129,7 @@ size_t DesfireSearchCRCPos(uint8_t *data, size_t datalen, uint8_t respcode, uint break; if (crcpos - i + crclen > datalen) continue; - + memcpy(crcdata, data, crcpos - i); crcdata[crcpos - i] = respcode; bool res; @@ -141,7 +141,7 @@ size_t DesfireSearchCRCPos(uint8_t *data, size_t datalen, uint8_t respcode, uint crcposfound = crcpos - i; } } - + return crcposfound; } diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index c2001bdf0..2d47022cf 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -79,9 +79,9 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint *dstdatalen = srcdatalen + DesfireGetMACLength(ctx); } } else if (ctx->commMode == DCMEncrypted) { - - - + + + } else { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -122,7 +122,7 @@ static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, *dstdatalen = srcdatalen; return; } - + DesfireCryptoEncDec(ctx, true, srcdata, srcdatalen, dstdata, false); //PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); @@ -153,13 +153,13 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, *dstdatalen = srcdatalen; return; } - + memcpy(dstdata, srcdata, srcdatalen - DesfireGetMACLength(ctx)); *dstdatalen = srcdatalen - DesfireGetMACLength(ctx); - + memcpy(data, srcdata, *dstdatalen); data[*dstdatalen] = respcode; - + uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; DesfireCryptoCMAC(ctx, data, *dstdatalen + 1, cmac); if (memcmp(&srcdata[*dstdatalen], cmac, DesfireGetMACLength(ctx)) != 0) { @@ -168,23 +168,23 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, PrintAndLogEx(INFO, " calculated MAC: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); } } else if (ctx->commMode == DCMEncrypted) { - if (srcdatalen < desfire_get_key_block_length(ctx->keyType)) { - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - return; - } - - DesfireCryptoEncDec(ctx, true, srcdata, srcdatalen, dstdata, false); - //PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); - - size_t puredatalen = DesfireSearchCRCPos(dstdata, srcdatalen, respcode, 4); - if (puredatalen != 0) { - *dstdatalen = puredatalen; - } else { - PrintAndLogEx(WARNING, "CRC32 error."); - *dstdatalen = srcdatalen; - } - + if (srcdatalen < desfire_get_key_block_length(ctx->keyType)) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + return; + } + + DesfireCryptoEncDec(ctx, true, srcdata, srcdatalen, dstdata, false); + //PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); + + size_t puredatalen = DesfireSearchCRCPos(dstdata, srcdatalen, respcode, 4); + if (puredatalen != 0) { + *dstdatalen = puredatalen; + } else { + PrintAndLogEx(WARNING, "CRC32 error."); + *dstdatalen = srcdatalen; + } + } else { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; diff --git a/doc/commands.json b/doc/commands.json index f426c4160..b050766e5 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -973,7 +973,7 @@ }, "help": { "command": "help", - "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log /home/phil/.proxmark3/logs/log_20210708.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", + "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log e:\\proxspace\\pm3/.proxmark3/logs/log_20210709.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", "notes": [ "auto" ], @@ -1722,6 +1722,22 @@ ], "usage": "hf cipurse auth [-hav] [-n ] [-k ]" }, + "hf cipurse default": { + "command": "hf cipurse default", + "description": "set default parameters for access to cipurse card", + "notes": [ + "hf cipurse default -n 1 -k 65656565656565656565656565656565 --fid 2ff7 -> set key, key id and file id" + ], + "offline": false, + "options": [ + "-h, --help this help", + "--clear resets to defaults", + "-n key id", + "-k, --key authentication key", + "--fid file id" + ], + "usage": "hf cipurse default [-h] [--clear] [-n ] [-k ] [--fid ]" + }, "hf cipurse delete": { "command": "hf cipurse delete", "description": "read file by file id with key id and key. if no key is supplied, default key of 737373...7373 will be used", @@ -3922,6 +3938,31 @@ ], "usage": "hf mf wrbl [-hab] --blk [-k ] [-d ]" }, + "hf mfdes auth": { + "command": "hf mfdes auth", + "description": "authenticates mifare desfire using key", + "notes": [ + "hf mfdes auth -m 3 -t 4 -a 808301 -n 0 -k 00000000000000000000000000000000 -> aes,keynumber 0, aid 0x803201", + "hf mfdes auth -m 2 -t 2 -a 000000 -n 1 -k 00000000000000000000000000000000 -> 3des,keynumber 1, aid 0x000000", + "hf mfdes auth -m 1 -t 1 -a 000000 -n 2 -k 0000000000000000 -> des,keynumber 2, aid 0x000000", + "hf mfdes auth -m 1 -t 1 -a 000000 -n 0 -> des, defaultkey, aid 0x000000", + "hf mfdes auth -m 2 -t 2 -a 000000 -n 0 -> 3des, defaultkey, aid 0x000000", + "hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> 3k3des, defaultkey, aid 0x000000", + "hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> aes, defaultkey, aid 0x000000" + ], + "offline": false, + "options": [ + "-h, --help this help", + "-m, --type auth type (1=normal, 2=iso, 3=aes)", + "-t, --algo crypt algo (1=des, 2=3des(2k2des), 3=3k3des, 4=aes)", + "-a, --aid aid used for authentification (hex 3 bytes)", + "-n, --keyno key number used for authentification", + "-k, --key key for checking (hex 8-24 bytes)", + "-d, --kdf key derivation function (kdf) (0=none, 1=an10922, 2=gallagher)", + "-i, --kdfi kdf input (hex 1-31 bytes)" + ], + "usage": "hf mfdes auth [-h] [-m ] [-t ] [-a ]... [-n ] [-k ] [-d ] [-i ]" + }, "hf mfdes bruteaid": { "command": "hf mfdes bruteaid", "description": "recover aids by bruteforce. warning: this command takes a long time", @@ -4152,6 +4193,50 @@ ], "usage": "hf mfdes formatpicc [-h]" }, + "hf mfdes getaids": { + "command": "hf mfdes getaids", + "description": "get application ids list from card. master key needs to be provided.", + "notes": [ + "hf mfdes getaids -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup" + ], + "offline": false, + "options": [ + "-h, --help this help", + "-a, --apdu show apdu requests and responses", + "-v, --verbose show technical data", + "-n, --keyno key number", + "-t, --algo crypt algo: des, 2tdea, 3tdea, aes", + "-k, --key key for authenticate (hex 8(des), 16(2tdea or aes) or 24(3tdea) bytes)", + "-f, --kdf key derivation function (kdf): none, an10922, gallagher", + "-i, --kdfi kdf input (hex 1-31 bytes)", + "-m, --cmode communicaton mode: plain/mac/encrypt", + "-c, --ccset communicaton command set: native/niso/iso", + "-s, --schann secure channel: d40/ev1/ev2" + ], + "usage": "hf mfdes getaids [-hav] [-n ] [-t ] [-k ] [-f ] [-i ] [-m ] [-c ] [-s ]" + }, + "hf mfdes getappnames": { + "command": "hf mfdes getappnames", + "description": "get application ids, iso ids and df names from card. master key needs to be provided.", + "notes": [ + "hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup" + ], + "offline": false, + "options": [ + "-h, --help this help", + "-a, --apdu show apdu requests and responses", + "-v, --verbose show technical data", + "-n, --keyno key number", + "-t, --algo crypt algo: des, 2tdea, 3tdea, aes", + "-k, --key key for authenticate (hex 8(des), 16(2tdea or aes) or 24(3tdea) bytes)", + "-f, --kdf key derivation function (kdf): none, an10922, gallagher", + "-i, --kdfi kdf input (hex 1-31 bytes)", + "-m, --cmode communicaton mode: plain/mac/encrypt", + "-c, --ccset communicaton command set: native/niso/iso", + "-s, --schann secure channel: d40/ev1/ev2" + ], + "usage": "hf mfdes getappnames [-hav] [-n ] [-t ] [-k ] [-f ] [-i ] [-m ] [-c ] [-s ]" + }, "hf mfdes getuid": { "command": "hf mfdes getuid", "description": "get uid from a mifare desfire tag", @@ -4180,28 +4265,23 @@ }, "hf mfdes help": { "command": "hf mfdes help", - "description": "help this help list list desfire (iso 14443a) history --------------------------------------------------------------------------------------- hf mfdes auth available offline: no authenticates mifare desfire using key", + "description": "help this help list list desfire (iso 14443a) history --------------------------------------------------------------------------------------- hf mfdes default available offline: no get application ids, iso ids and df names from card. master key needs to be provided.", "notes": [ - "hf mfdes auth -m 3 -t 4 -a 808301 -n 0 -k 00000000000000000000000000000000 -> aes,keynumber 0, aid 0x803201", - "hf mfdes auth -m 2 -t 2 -a 000000 -n 1 -k 00000000000000000000000000000000 -> 3des,keynumber 1, aid 0x000000", - "hf mfdes auth -m 1 -t 1 -a 000000 -n 2 -k 0000000000000000 -> des,keynumber 2, aid 0x000000", - "hf mfdes auth -m 1 -t 1 -a 000000 -n 0 -> des, defaultkey, aid 0x000000", - "hf mfdes auth -m 2 -t 2 -a 000000 -n 0 -> 3des, defaultkey, aid 0x000000", - "hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> 3k3des, defaultkey, aid 0x000000", - "hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> aes, defaultkey, aid 0x000000" + "hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup" ], "offline": true, "options": [ "-h, --help this help", - "-m, --type auth type (1=normal, 2=iso, 3=aes)", - "-t, --algo crypt algo (1=des, 2=3des(2k2des), 3=3k3des, 4=aes)", - "-a, --aid aid used for authentification (hex 3 bytes)", - "-n, --keyno key number used for authentification", - "-k, --key key for checking (hex 8-24 bytes)", - "-d, --kdf key derivation function (kdf) (0=none, 1=an10922, 2=gallagher)", - "-i, --kdfi kdf input (hex 1-31 bytes)" + "-n, --keyno key number", + "-t, --algo crypt algo: des, 2tdea, 3tdea, aes", + "-k, --key key for authenticate (hex 8(des), 16(2tdea or aes) or 24(3tdea) bytes)", + "-f, --kdf key derivation function (kdf): none, an10922, gallagher", + "-i, --kdfi kdf input (hex 1-31 bytes)", + "-m, --cmode communicaton mode: plain/mac/encrypt", + "-c, --ccset communicaton command set: native/niso/iso", + "-s, --schann secure channel: d40/ev1/ev2" ], - "usage": "hf mfdes auth [-h] [-m ] [-t ] [-a ]... [-n ] [-k ] [-d ] [-i ]" + "usage": "hf mfdes default [-h] [-n ] [-t ] [-k ] [-f ] [-i ] [-m ] [-c ] [-s ]" }, "hf mfdes info": { "command": "hf mfdes info", @@ -4267,6 +4347,18 @@ ], "usage": "hf mfdes selectaid [-h] [-a ]..." }, + "hf mfdes test": { + "command": "hf mfdes test", + "description": "[=] key num: 0 key algo: des key[8]: 00 00 00 00 00 00 00 00 [=] secure channel: n/a command set: niso communication mode: encrypt [+] setting isodep -> inactive [=] sending bytes to proxmark failed - offline [+] >>>> 90 5a 00 00 03 00 00 00 00 [+] setting isodep -> inactive [=] sending bytes to proxmark failed - offline [=] sending bytes to proxmark failed - offline [!] command execute timeout [+] setting isodep -> inactive [=] sending bytes to proxmark failed - offline ======================================================================================= hf seos { seos rfids... } --------------------------------------------------------------------------------------- hf seos help available offline: yes help this help list list seos history --------------------------------------------------------------------------------------- hf seos info available offline: no get info from seos tags", + "notes": [ + "hf seos info" + ], + "offline": false, + "options": [ + "-h, --help this help" + ], + "usage": "hf seos info [-h]" + }, "hf mfdes write": { "command": "hf mfdes write", "description": "write data to file make sure to select aid or authenticate aid before running this command.", @@ -4748,18 +4840,6 @@ ], "usage": "hf search [-hv]" }, - "hf seos help": { - "command": "hf seos help", - "description": "help this help list list seos history --------------------------------------------------------------------------------------- hf seos info available offline: no get info from seos tags", - "notes": [ - "hf seos info" - ], - "offline": true, - "options": [ - "-h, --help this help" - ], - "usage": "hf seos info [-h]" - }, "hf seos list": { "command": "hf seos list", "description": "alias of `trace list -t 7816` with selected protocol data to annotate trace buffer you can load a trace from file (see `trace load -h`) or it be downloaded from device by default it accepts all other arguments of `trace list`. note that some might not be relevant for this specific protocol", @@ -5078,8 +5158,8 @@ "command": "hw connect", "description": "connects to a proxmark3 device via specified serial port. baudrate here is only for physical uart or uart-bt, not for usb-cdc or blue shark add-on", "notes": [ - "hw connect -p /dev/ttyacm0", - "hw connect -p /dev/ttyacm0 -b 115200" + "hw connect -p com3", + "hw connect -p com3 -b 115200" ], "offline": true, "options": [ @@ -9201,8 +9281,8 @@ } }, "metadata": { - "commands_extracted": 571, + "commands_extracted": 575, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2021-07-08T07:53:00" + "extracted_on": "2021-07-09T11:42:14" } } \ No newline at end of file diff --git a/doc/commands.md b/doc/commands.md index 433b44e26..2bd429d15 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -247,6 +247,7 @@ Check column "offline" for their availability. |`hf cipurse write `|N |`Write binary file` |`hf cipurse aread `|N |`Read file attributes` |`hf cipurse delete `|N |`Delete file` +|`hf cipurse default `|N |`Set default key and file id for all the other commands` |`hf cipurse test `|Y |`Tests` @@ -500,6 +501,7 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- |`hf mfdes help `|Y |`This help` +|`hf mfdes default `|N |`[new]Set defaults for all the commands` |`hf mfdes auth `|N |`Tries a MIFARE DesFire Authentication` |`hf mfdes changekey `|N |`Change Key` |`hf mfdes chk `|N |`Check keys` @@ -512,6 +514,8 @@ Check column "offline" for their availability. |`hf mfdes createaid `|N |`Create Application ID` |`hf mfdes deleteaid `|N |`Delete Application ID` |`hf mfdes selectaid `|N |`Select Application ID` +|`hf mfdes getaids `|N |`[new]Get Application IDs list` +|`hf mfdes getappnames `|N |`[new]Get Applications list` |`hf mfdes changevalue `|N |`Write value of a value file (credit/debit/clear)` |`hf mfdes clearfile `|N |`Clear record File` |`hf mfdes createfile `|N |`Create Standard/Backup File` @@ -522,6 +526,7 @@ Check column "offline" for their availability. |`hf mfdes getvalue `|N |`Get value of file` |`hf mfdes read `|N |`Read data from standard/backup/record file` |`hf mfdes write `|N |`Write data to standard/backup/record file` +|`hf mfdes test `|N |`Test crypto` ### hf seos From fff1c8fae16811c89db44675f3bac2059362c60b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 15:15:16 +0300 Subject: [PATCH 237/309] add test command and crc tests --- client/CMakeLists.txt | 1 + client/Makefile | 1 + client/src/cmdhfmfdes.c | 9 ++- client/src/mifare/desfiretest.c | 102 ++++++++++++++++++++++++++++++++ client/src/mifare/desfiretest.h | 19 ++++++ 5 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 client/src/mifare/desfiretest.c create mode 100644 client/src/mifare/desfiretest.h diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 536464d18..c7892ba7c 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -229,6 +229,7 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/mifare/desfirecrypto.c ${PM3_ROOT}/client/src/mifare/desfiresecurechan.c ${PM3_ROOT}/client/src/mifare/desfirecore.c + ${PM3_ROOT}/client/src/mifare/desfiretest.c ${PM3_ROOT}/client/src/uart/uart_posix.c ${PM3_ROOT}/client/src/uart/uart_win32.c ${PM3_ROOT}/client/src/ui/overlays.ui diff --git a/client/Makefile b/client/Makefile index 7d09586a0..51f7cb2df 100644 --- a/client/Makefile +++ b/client/Makefile @@ -592,6 +592,7 @@ SRCS = aiddesfire.c \ mifare/desfirecrypto.c \ mifare/desfirecore.c \ mifare/desfiresecurechan.c \ + mifare/desfiretest.c \ mifare/mad.c \ mifare/mfkey.c \ mifare/mifare4.c \ diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 7526207e3..73c4eb14c 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -30,9 +30,10 @@ #include "util_posix.h" // msleep #include "mifare/desfire_crypto.h" #include "mifare/desfirecore.h" +#include "mifare/desfiretest.h" +#include "mifare/mifaredefault.h" // default keys #include "crapto1/crapto1.h" #include "fileutils.h" -#include "mifare/mifaredefault.h" // default keys #include "nfc/ndef.h" // NDEF #include "mifare/mad.h" #include "generator.h" @@ -5312,6 +5313,10 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHF14ADesTest(const char *Cmd) { + DesfireTest(true); + return PM3_SUCCESS; +} static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, @@ -5346,7 +5351,7 @@ static command_t CommandTable[] = { {"read", CmdHF14ADesReadData, IfPm3Iso14443a, "Read data from standard/backup/record file"}, {"write", CmdHF14ADesWriteData, IfPm3Iso14443a, "Write data to standard/backup/record file"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("System") " -----------------------"}, -// {"test", CmdHF14ADesTest, IfPm3Iso14443a, "Test crypto"}, + {"test", CmdHF14ADesTest, IfPm3Iso14443a, "Test crypto"}, {NULL, NULL, NULL, NULL} }; diff --git a/client/src/mifare/desfiretest.c b/client/src/mifare/desfiretest.c new file mode 100644 index 000000000..f60623daa --- /dev/null +++ b/client/src/mifare/desfiretest.c @@ -0,0 +1,102 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2021 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// tests for desfire +//----------------------------------------------------------------------------- + +#include "desfiretest.h" + +#include +#include // memcpy memset +#include "fileutils.h" + +#include "crypto/libpcrypto.h" +#include "mifare/desfirecrypto.h" + +static bool TestCRC16(void) { + uint8_t data[] = {0x04, 0x44, 0x0F, 0x32, 0x76, 0x31, 0x80, 0x27, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + bool res = true; + size_t len = DesfireSearchCRCPos(data, 16, 0x00, 2); + res = res && (len == 7); + + len = DesfireSearchCRCPos(data, 7 + 2, 0x00, 2); + res = res && (len == 7); + + len = DesfireSearchCRCPos(data, 7, 0x00, 2); + res = res && (len == 0); + + len = DesfireSearchCRCPos(data, 3, 0x00, 2); + res = res && (len == 0); + + len = DesfireSearchCRCPos(data, 1, 0x00, 2); + res = res && (len == 0); + + if (res) + PrintAndLogEx(INFO, "crc16............ " _GREEN_("passed")); + else + PrintAndLogEx(ERR, "crc16............ " _RED_("fail")); + + return res; +} + +static bool TestCRC32(void) { + uint8_t data[] = {0x04, 0x44, 0x0F, 0x32, 0x76, 0x31, 0x80, 0x99, 0xCE, 0x1A, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00}; + + bool res = true; + size_t len = DesfireSearchCRCPos(data, 16, 0x00, 4); + res = res && (len == 7); + + len = DesfireSearchCRCPos(data, 7 + 4, 0x00, 4); + res = res && (len == 7); + + len = DesfireSearchCRCPos(data, 5, 0x00, 4); + res = res && (len == 0); + + len = DesfireSearchCRCPos(data, 4, 0x00, 4); + res = res && (len == 0); + + len = DesfireSearchCRCPos(data, 2, 0x00, 4); + res = res && (len == 0); + + if (res) + PrintAndLogEx(INFO, "crc32............ " _GREEN_("passed")); + else + PrintAndLogEx(ERR, "crc32............ " _RED_("fail")); + + return res; +} +static bool TestCMAC(void) { + bool res = true; + + + if (res) + PrintAndLogEx(INFO, "CMAC............. " _GREEN_("passed")); + else + PrintAndLogEx(ERR, "CMAC............. " _RED_("fail")); + + return res; +} + +bool DesfireTest(bool verbose) { + bool res = true; + + PrintAndLogEx(INFO, "------ " _CYAN_("Desfire Tests") " ------"); + + res = res && TestCRC16(); + res = res && TestCRC32(); + res = res && TestCMAC(); + + PrintAndLogEx(INFO, "---------------------------"); + if (res) + PrintAndLogEx(SUCCESS, " Tests [ %s ]", _GREEN_("ok")); + else + PrintAndLogEx(FAILED, " Tests [ %s ]", _RED_("fail")); + + PrintAndLogEx(NORMAL, ""); + return res; +} diff --git a/client/src/mifare/desfiretest.h b/client/src/mifare/desfiretest.h new file mode 100644 index 000000000..e89330899 --- /dev/null +++ b/client/src/mifare/desfiretest.h @@ -0,0 +1,19 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2021 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// tests for desfire +//----------------------------------------------------------------------------- + +#ifndef __CIPURSETEST_H__ +#define __CIPURSETEST_H__ + +#include +#include "common.h" + +bool DesfireTest(bool verbose); + +#endif /* __CIPURSETEST_H__ */ From 8403624bb1fc447ee078ddec24b188b13590b517 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 15:50:40 +0300 Subject: [PATCH 238/309] cmac tests --- client/src/mifare/desfiretest.c | 131 +++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 4 deletions(-) diff --git a/client/src/mifare/desfiretest.c b/client/src/mifare/desfiretest.c index f60623daa..8bad6683f 100644 --- a/client/src/mifare/desfiretest.c +++ b/client/src/mifare/desfiretest.c @@ -17,6 +17,12 @@ #include "crypto/libpcrypto.h" #include "mifare/desfirecrypto.h" +static uint8_t CMACData[] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51}; + + static bool TestCRC16(void) { uint8_t data[] = {0x04, 0x44, 0x0F, 0x32, 0x76, 0x31, 0x80, 0x27, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; @@ -70,14 +76,129 @@ static bool TestCRC32(void) { return res; } -static bool TestCMAC(void) { + +// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/TDES_CMAC.pdf +static bool TestCMAC3TDEA(void) { bool res = true; + + uint8_t key[DESFIRE_MAX_KEY_SIZE] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, + 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23}; + DesfireContext dctx; + DesfireSetKey(&dctx, 0, T_3K3DES, key); + memcpy(dctx.sessionKeyMAC, key, DESFIRE_MAX_KEY_SIZE); + uint8_t cmac[DESFIRE_MAX_KEY_SIZE] = {0}; + uint8_t cmac1[] = {0x7D, 0xB0, 0xD3, 0x7D, 0xF9, 0x36, 0xC5, 0x50}; + memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); + DesfireCryptoCMAC(&dctx, CMACData, 0, cmac); + res = res && (memcmp(cmac, cmac1, sizeof(cmac1)) == 0); + + uint8_t cmac2[] = {0x30, 0x23, 0x9C, 0xF1, 0xF5, 0x2E, 0x66, 0x09}; + memset(cmac, 0, sizeof(cmac)); + memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); + DesfireCryptoCMAC(&dctx, CMACData, 16, cmac); + res = res && (memcmp(cmac, cmac2, sizeof(cmac1)) == 0); + + uint8_t cmac3[] = {0x6C, 0x9F, 0x3E, 0xE4, 0x92, 0x3F, 0x6B, 0xE2}; + memset(cmac, 0, sizeof(cmac)); + memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); + DesfireCryptoCMAC(&dctx, CMACData, 20, cmac); + res = res && (memcmp(cmac, cmac3, sizeof(cmac1)) == 0); + + uint8_t cmac4[] = {0x99, 0x42, 0x9B, 0xD0, 0xBF, 0x79, 0x04, 0xE5}; + memset(cmac, 0, sizeof(cmac)); + memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); + DesfireCryptoCMAC(&dctx, CMACData, 32, cmac); + res = res && (memcmp(cmac, cmac4, sizeof(cmac1)) == 0); if (res) - PrintAndLogEx(INFO, "CMAC............. " _GREEN_("passed")); + PrintAndLogEx(INFO, "CMAC 3TDEA....... " _GREEN_("passed")); else - PrintAndLogEx(ERR, "CMAC............. " _RED_("fail")); + PrintAndLogEx(ERR, "CMAC 3TDEA....... " _RED_("fail")); + + return res; +} + +// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/TDES_CMAC.pdf +static bool TestCMAC2TDEA(void) { + bool res = true; + + uint8_t key[DESFIRE_MAX_KEY_SIZE] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01}; + DesfireContext dctx; + DesfireSetKey(&dctx, 0, T_3DES, key); + memcpy(dctx.sessionKeyMAC, key, DESFIRE_MAX_KEY_SIZE); + uint8_t cmac[DESFIRE_MAX_KEY_SIZE] = {0}; + + uint8_t cmac1[] = {0x79, 0xCE, 0x52, 0xA7, 0xF7, 0x86, 0xA9, 0x60}; + memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); + DesfireCryptoCMAC(&dctx, CMACData, 0, cmac); +// PrintAndLogEx(INFO, "cmac: %s", sprint_hex(cmac, 16)); + res = res && (memcmp(cmac, cmac1, sizeof(cmac1)) == 0); + + uint8_t cmac2[] = {0xCC, 0x18, 0xA0, 0xB7, 0x9A, 0xF2, 0x41, 0x3B}; + memset(cmac, 0, sizeof(cmac)); + memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); + DesfireCryptoCMAC(&dctx, CMACData, 16, cmac); + res = res && (memcmp(cmac, cmac2, sizeof(cmac1)) == 0); + + uint8_t cmac3[] = {0xC0, 0x6D, 0x37, 0x7E, 0xCD, 0x10, 0x19, 0x69}; + memset(cmac, 0, sizeof(cmac)); + memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); + DesfireCryptoCMAC(&dctx, CMACData, 20, cmac); + res = res && (memcmp(cmac, cmac3, sizeof(cmac1)) == 0); + + uint8_t cmac4[] = {0x9C, 0xD3, 0x35, 0x80, 0xF9, 0xB6, 0x4D, 0xFB}; + memset(cmac, 0, sizeof(cmac)); + memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); + DesfireCryptoCMAC(&dctx, CMACData, 32, cmac); + res = res && (memcmp(cmac, cmac4, sizeof(cmac1)) == 0); + + if (res) + PrintAndLogEx(INFO, "CMAC 2TDEA....... " _GREEN_("passed")); + else + PrintAndLogEx(ERR, "CMAC 2TDEA....... " _RED_("fail")); + + return res; +} + +static bool TestCMACDES(void) { + bool res = true; + + uint8_t key[DESFIRE_MAX_KEY_SIZE] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}; + DesfireContext dctx; + DesfireSetKey(&dctx, 0, T_DES, key); + memcpy(dctx.sessionKeyMAC, key, DESFIRE_MAX_KEY_SIZE); + uint8_t cmac[DESFIRE_MAX_KEY_SIZE] = {0}; + + uint8_t cmac1[] = {0x86, 0xF7, 0x9C, 0x13, 0xFD, 0x30, 0x6E, 0x67}; + memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); + DesfireCryptoCMAC(&dctx, CMACData, 0, cmac); + res = res && (memcmp(cmac, cmac1, sizeof(cmac1)) == 0); + + uint8_t cmac2[] = {0xBE, 0xA4, 0x21, 0x22, 0x92, 0x46, 0x2A, 0x85}; + memset(cmac, 0, sizeof(cmac)); + memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); + DesfireCryptoCMAC(&dctx, CMACData, 16, cmac); + res = res && (memcmp(cmac, cmac2, sizeof(cmac1)) == 0); + + uint8_t cmac3[] = {0x3E, 0x2F, 0x83, 0x10, 0xC5, 0x69, 0x27, 0x5E}; + memset(cmac, 0, sizeof(cmac)); + memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); + DesfireCryptoCMAC(&dctx, CMACData, 20, cmac); + res = res && (memcmp(cmac, cmac3, sizeof(cmac1)) == 0); + + uint8_t cmac4[] = {0x9D, 0x1F, 0xC4, 0xD4, 0xC0, 0x25, 0x91, 0x32}; + memset(cmac, 0, sizeof(cmac)); + memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); + DesfireCryptoCMAC(&dctx, CMACData, 32, cmac); + res = res && (memcmp(cmac, cmac4, sizeof(cmac1)) == 0); + + if (res) + PrintAndLogEx(INFO, "CMAC DES......... " _GREEN_("passed")); + else + PrintAndLogEx(ERR, "CMAC DES......... " _RED_("fail")); return res; } @@ -89,7 +210,9 @@ bool DesfireTest(bool verbose) { res = res && TestCRC16(); res = res && TestCRC32(); - res = res && TestCMAC(); + res = res && TestCMAC3TDEA(); + res = res && TestCMAC2TDEA(); + res = res && TestCMACDES(); PrintAndLogEx(INFO, "---------------------------"); if (res) From 48a96366795bc7fd4586dbd1cc31a80dc52a32c4 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 15:56:18 +0300 Subject: [PATCH 239/309] style --- client/src/mifare/desfiretest.c | 45 ++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/client/src/mifare/desfiretest.c b/client/src/mifare/desfiretest.c index 8bad6683f..b89963352 100644 --- a/client/src/mifare/desfiretest.c +++ b/client/src/mifare/desfiretest.c @@ -17,15 +17,16 @@ #include "crypto/libpcrypto.h" #include "mifare/desfirecrypto.h" -static uint8_t CMACData[] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, - 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, - 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, - 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51}; +static uint8_t CMACData[] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 + }; static bool TestCRC16(void) { uint8_t data[] = {0x04, 0x44, 0x0F, 0x32, 0x76, 0x31, 0x80, 0x27, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - + bool res = true; size_t len = DesfireSearchCRCPos(data, 16, 0x00, 2); res = res && (len == 7); @@ -52,7 +53,7 @@ static bool TestCRC16(void) { static bool TestCRC32(void) { uint8_t data[] = {0x04, 0x44, 0x0F, 0x32, 0x76, 0x31, 0x80, 0x99, 0xCE, 0x1A, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00}; - + bool res = true; size_t len = DesfireSearchCRCPos(data, 16, 0x00, 4); res = res && (len == 7); @@ -81,14 +82,15 @@ static bool TestCRC32(void) { static bool TestCMAC3TDEA(void) { bool res = true; - uint8_t key[DESFIRE_MAX_KEY_SIZE] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, - 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23}; + uint8_t key[DESFIRE_MAX_KEY_SIZE] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, + 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 + }; DesfireContext dctx; DesfireSetKey(&dctx, 0, T_3K3DES, key); memcpy(dctx.sessionKeyMAC, key, DESFIRE_MAX_KEY_SIZE); uint8_t cmac[DESFIRE_MAX_KEY_SIZE] = {0}; - + uint8_t cmac1[] = {0x7D, 0xB0, 0xD3, 0x7D, 0xF9, 0x36, 0xC5, 0x50}; memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); DesfireCryptoCMAC(&dctx, CMACData, 0, cmac); @@ -99,7 +101,7 @@ static bool TestCMAC3TDEA(void) { memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); DesfireCryptoCMAC(&dctx, CMACData, 16, cmac); res = res && (memcmp(cmac, cmac2, sizeof(cmac1)) == 0); - + uint8_t cmac3[] = {0x6C, 0x9F, 0x3E, 0xE4, 0x92, 0x3F, 0x6B, 0xE2}; memset(cmac, 0, sizeof(cmac)); memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); @@ -111,7 +113,7 @@ static bool TestCMAC3TDEA(void) { memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); DesfireCryptoCMAC(&dctx, CMACData, 32, cmac); res = res && (memcmp(cmac, cmac4, sizeof(cmac1)) == 0); - + if (res) PrintAndLogEx(INFO, "CMAC 3TDEA....... " _GREEN_("passed")); else @@ -124,17 +126,18 @@ static bool TestCMAC3TDEA(void) { static bool TestCMAC2TDEA(void) { bool res = true; - uint8_t key[DESFIRE_MAX_KEY_SIZE] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01}; + uint8_t key[DESFIRE_MAX_KEY_SIZE] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01 + }; DesfireContext dctx; DesfireSetKey(&dctx, 0, T_3DES, key); memcpy(dctx.sessionKeyMAC, key, DESFIRE_MAX_KEY_SIZE); uint8_t cmac[DESFIRE_MAX_KEY_SIZE] = {0}; - + uint8_t cmac1[] = {0x79, 0xCE, 0x52, 0xA7, 0xF7, 0x86, 0xA9, 0x60}; memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); DesfireCryptoCMAC(&dctx, CMACData, 0, cmac); -// PrintAndLogEx(INFO, "cmac: %s", sprint_hex(cmac, 16)); +// PrintAndLogEx(INFO, "cmac: %s", sprint_hex(cmac, 16)); res = res && (memcmp(cmac, cmac1, sizeof(cmac1)) == 0); uint8_t cmac2[] = {0xCC, 0x18, 0xA0, 0xB7, 0x9A, 0xF2, 0x41, 0x3B}; @@ -142,7 +145,7 @@ static bool TestCMAC2TDEA(void) { memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); DesfireCryptoCMAC(&dctx, CMACData, 16, cmac); res = res && (memcmp(cmac, cmac2, sizeof(cmac1)) == 0); - + uint8_t cmac3[] = {0xC0, 0x6D, 0x37, 0x7E, 0xCD, 0x10, 0x19, 0x69}; memset(cmac, 0, sizeof(cmac)); memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); @@ -154,7 +157,7 @@ static bool TestCMAC2TDEA(void) { memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); DesfireCryptoCMAC(&dctx, CMACData, 32, cmac); res = res && (memcmp(cmac, cmac4, sizeof(cmac1)) == 0); - + if (res) PrintAndLogEx(INFO, "CMAC 2TDEA....... " _GREEN_("passed")); else @@ -171,7 +174,7 @@ static bool TestCMACDES(void) { DesfireSetKey(&dctx, 0, T_DES, key); memcpy(dctx.sessionKeyMAC, key, DESFIRE_MAX_KEY_SIZE); uint8_t cmac[DESFIRE_MAX_KEY_SIZE] = {0}; - + uint8_t cmac1[] = {0x86, 0xF7, 0x9C, 0x13, 0xFD, 0x30, 0x6E, 0x67}; memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); DesfireCryptoCMAC(&dctx, CMACData, 0, cmac); @@ -182,7 +185,7 @@ static bool TestCMACDES(void) { memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); DesfireCryptoCMAC(&dctx, CMACData, 16, cmac); res = res && (memcmp(cmac, cmac2, sizeof(cmac1)) == 0); - + uint8_t cmac3[] = {0x3E, 0x2F, 0x83, 0x10, 0xC5, 0x69, 0x27, 0x5E}; memset(cmac, 0, sizeof(cmac)); memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); @@ -194,7 +197,7 @@ static bool TestCMACDES(void) { memset(dctx.IV, 0, DESFIRE_MAX_KEY_SIZE); DesfireCryptoCMAC(&dctx, CMACData, 32, cmac); res = res && (memcmp(cmac, cmac4, sizeof(cmac1)) == 0); - + if (res) PrintAndLogEx(INFO, "CMAC DES......... " _GREEN_("passed")); else From 65b92e03526965bb64b233a79ccb20dbff7452d9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 15:59:45 +0300 Subject: [PATCH 240/309] add tests to CI --- tools/pm3_tests.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/pm3_tests.sh b/tools/pm3_tests.sh index 41882f2e5..aba88f922 100755 --- a/tools/pm3_tests.sh +++ b/tools/pm3_tests.sh @@ -492,6 +492,7 @@ while true; do if ! CheckExecute "hf iclass loclass test" "$CLIENTBIN -c 'hf iclass loclass --test'" "key diversification (ok)"; then break; fi if ! CheckExecute "emv test" "$CLIENTBIN -c 'emv test'" "Test(s) \[ ok"; then break; fi if ! CheckExecute "hf cipurse test" "$CLIENTBIN -c 'hf cipurse test'" "Tests \[ ok"; then break; fi + if ! CheckExecute "hf mfdes test" "$CLIENTBIN -c 'hf mfdes test'" "Tests \[ ok"; then break; fi fi fi echo -e "\n------------------------------------------------------------" From aa1d98ba55aae1a0e156cdd9270935a71afcc1ff Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 16:06:18 +0300 Subject: [PATCH 241/309] fix test AlwaysAvailable --- client/src/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 73c4eb14c..b4c84e832 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5351,7 +5351,7 @@ static command_t CommandTable[] = { {"read", CmdHF14ADesReadData, IfPm3Iso14443a, "Read data from standard/backup/record file"}, {"write", CmdHF14ADesWriteData, IfPm3Iso14443a, "Write data to standard/backup/record file"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("System") " -----------------------"}, - {"test", CmdHF14ADesTest, IfPm3Iso14443a, "Test crypto"}, + {"test", CmdHF14ADesTest, AlwaysAvailable, "Test crypto"}, {NULL, NULL, NULL, NULL} }; From f606cc5fb50fd8e7c392f28e2a5516e88c247941 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 18:03:34 +0300 Subject: [PATCH 242/309] added check channel --- client/src/mifare/desfiresecurechan.c | 75 +++++++++++++++++++++++++++ client/src/mifare/desfiresecurechan.h | 8 +++ include/protocols.h | 2 + 3 files changed, 85 insertions(+) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 2d47022cf..197769472 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -20,8 +20,42 @@ #include "crc16.h" // crc16 ccitt #include "crc32.h" #include "commonutil.h" +#include "protocols.h" #include "mifare/desfire_crypto.h" +AllowedChannelModesS AllowedChannelModes[] = { + {MFDES_CREATE_APPLICATION, DACd40, DCCNative, DCMPlain}, + {MFDES_DELETE_APPLICATION, DACd40, DCCNative, DCMPlain}, + {MFDES_GET_APPLICATION_IDS, DACd40, DCCNative, DCMPlain}, + {MFDES_GET_DF_NAMES, DACd40, DCCNative, DCMPlain}, + + {MFDES_READ_DATA, DACd40, DCCNative, DCMMACed}, + {MFDES_WRITE_DATA, DACd40, DCCNative, DCMMACed}, + {MFDES_GET_VALUE, DACd40, DCCNative, DCMMACed}, + {MFDES_CREDIT, DACd40, DCCNative, DCMMACed}, + {MFDES_DEBIT, DACd40, DCCNative, DCMMACed}, + {MFDES_LIMITED_CREDIT, DACd40, DCCNative, DCMMACed}, + {MFDES_READ_RECORDS, DACd40, DCCNative, DCMMACed}, + {MFDES_WRITE_RECORD, DACd40, DCCNative, DCMMACed}, + {MFDES_UPDATE_RECORD1, DACd40, DCCNative, DCMMACed}, + {MFDES_UPDATE_RECORD2, DACd40, DCCNativeISO, DCMMACed}, + {MFDES_INIT_KEY_SETTINGS, DACd40, DCCNative, DCMMACed}, + {MFDES_FINALIZE_KEY_SETTINGS, DACd40, DCCNative, DCMMACed}, + {MFDES_ROLL_KEY_SETTINGS, DACd40, DCCNative, DCMMACed}, + {MFDES_COMMIT_READER_ID, DACd40, DCCNative, DCMMACed}, + + {MFDES_GET_UID, DACd40, DCCNative, DCMEncrypted}, + {MFDES_READ_DATA, DACd40, DCCNative, DCMEncrypted}, + {MFDES_WRITE_DATA, DACd40, DCCNative, DCMEncrypted}, + + {MFDES_CREATE_APPLICATION, DACEV1, DCCNative, DCMMACed}, + {MFDES_DELETE_APPLICATION, DACEV1, DCCNative, DCMMACed}, + {MFDES_GET_APPLICATION_IDS, DACEV1, DCCNative, DCMMACed}, + {MFDES_GET_DF_NAMES, DACEV1, DCCNative, DCMMACed}, + + {MFDES_GET_UID, DACEV1, DCCNative, DCMEncrypted}, +}; + static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -207,3 +241,44 @@ void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t sr break; } } + +bool PrintChannelModeWarning(uint8_t cmd, DesfireSecureChannel secureChannel, DesfireCommandSet cmdSet, DesfireCommunicationMode commMode) { + if (commMode == DCMNone) { + PrintAndLogEx(WARNING, "Communication mode can't be NONE. command: %02x", cmd); + return false; + } + + // no security set + if (secureChannel == DACNone) + return true; + + bool found = false; + for (int i = 0; i < ARRAY_LENGTH(AllowedChannelModes); i++) + if (AllowedChannelModes[i].cmd == cmd) { + // full compare + if (AllowedChannelModes[i].secureChannel == secureChannel && + (AllowedChannelModes[i].cmdSet == cmdSet || (AllowedChannelModes[i].cmdSet == DCCNative && cmdSet == DCCNativeISO)) && + AllowedChannelModes[i].commMode == commMode){ + + found = true; + break; + } + + // ev1 plain and mac are the same + if (AllowedChannelModes[i].secureChannel == secureChannel && + AllowedChannelModes[i].secureChannel == DACEV1 && + (AllowedChannelModes[i].cmdSet == cmdSet || (AllowedChannelModes[i].cmdSet == DCCNative && cmdSet == DCCNativeISO)) && + (commMode == DCMPlain || commMode == DCMMACed)){ + + found = true; + break; + } + + } + + if (!found) + PrintAndLogEx(WARNING, "Wrong communication mode. Check settings. command: %02x", cmd); + + return found; +} + diff --git a/client/src/mifare/desfiresecurechan.h b/client/src/mifare/desfiresecurechan.h index 23810c791..aa056323a 100644 --- a/client/src/mifare/desfiresecurechan.h +++ b/client/src/mifare/desfiresecurechan.h @@ -19,8 +19,16 @@ #include "mifare/desfire_crypto.h" #include "mifare/mifare4.h" +typedef struct { + uint8_t cmd; + DesfireSecureChannel secureChannel; + DesfireCommandSet cmdSet; + DesfireCommunicationMode commMode; +} AllowedChannelModesS; + void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen); void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen); +bool PrintChannelModeWarning(uint8_t cmd, DesfireSecureChannel secureChannel, DesfireCommandSet cmdSet, DesfireCommunicationMode commMode); #endif // __DESFIRESECURECHAN_H diff --git a/include/protocols.h b/include/protocols.h index 66385bcb9..58bd7e90f 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -436,6 +436,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define MFDES_GET_FILE_IDS 0x6F #define MFDES_ABORT_TRANSACTION 0xA7 #define MFDES_ADDITIONAL_FRAME 0xAF +#define MFDES_UPDATE_RECORD1 0xBA #define MFDES_READ_RECORDS 0xBB #define MFDES_READ_DATA 0xBD #define MFDES_CREATE_CYCLIC_RECORD_FILE 0xC0 @@ -451,6 +452,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define MFDES_CREATE_STD_DATA_FILE 0xCD #define MFDES_CREATE_TRANS_MAC_FILE 0xCE #define MFDES_DELETE_APPLICATION 0xDA +#define MFDES_UPDATE_RECORD2 0xDB #define MFDES_DEBIT 0xDC #define MFDES_DELETE_FILE 0xDF #define MFDES_CLEAR_RECORD_FILE 0xEB From d67ea92e2ee22457bb647514e472ec9004047ff0 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 18:04:27 +0300 Subject: [PATCH 243/309] implement check channel, add 2 new commands --- client/src/cmdhfmfdes.c | 20 +++++++++++++++++--- client/src/mifare/desfirecore.c | 13 ++++++++----- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index b4c84e832..d10d910bb 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -31,6 +31,7 @@ #include "mifare/desfire_crypto.h" #include "mifare/desfirecore.h" #include "mifare/desfiretest.h" +#include "mifare/desfiresecurechan.h" #include "mifare/mifaredefault.h" // default keys #include "crapto1/crapto1.h" #include "fileutils.h" @@ -5143,6 +5144,16 @@ static int CmdHF14ADesDefault(const char *Cmd) { return PM3_SUCCESS; } +// {"chkeysetings", CmdHF14ADesChKeySettings, IfPm3Iso14443a, "Change Key Settings"}, +static int CmdHF14ADesChKeySettings(const char *Cmd) { + + return PM3_SUCCESS; +} + //{"getkeysetings", CmdHF14ADesGetKeySettings, IfPm3Iso14443a, "Get Key Settings"}, +static int CmdHF14ADesGetKeySettings(const char *Cmd) { + + return PM3_SUCCESS; +} static int CmdHF14ADesGetAIDs(const char *Cmd) { CLIParserContext *ctx; @@ -5170,7 +5181,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { bool verbose = arg_get_lit(ctx, 2); DesfireContext dctx; - int securechann = defaultSecureChannel; + int securechann = DCMPlain; int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, &securechann); if (res) { CLIParserFree(ctx); @@ -5252,7 +5263,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { bool verbose = arg_get_lit(ctx, 2); DesfireContext dctx; - int securechann = defaultSecureChannel; + int securechann = DCMPlain; int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, &securechann); if (res) { CLIParserFree(ctx); @@ -5323,7 +5334,6 @@ static command_t CommandTable[] = { {"-----------", CmdHelp, IfPm3Iso14443a, "---------------------- " _CYAN_("general") " ----------------------"}, {"default", CmdHF14ADesDefault, IfPm3Iso14443a, "[new]Set defaults for all the commands"}, {"auth", CmdHF14ADesAuth, IfPm3Iso14443a, "Tries a MIFARE DesFire Authentication"}, - {"changekey", CmdHF14ADesChangeKey, IfPm3Iso14443a, "Change Key"}, {"chk", CmdHF14aDesChk, IfPm3Iso14443a, "Check keys"}, {"enum", CmdHF14ADesEnumApplications, IfPm3Iso14443a, "Tries enumerate all applications"}, {"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "Format PICC"}, @@ -5332,6 +5342,10 @@ static command_t CommandTable[] = { {"list", CmdHF14ADesList, AlwaysAvailable, "List DESFire (ISO 14443A) history"}, // {"ndefread", CmdHF14aDesNDEFRead, IfPm3Iso14443a, "Prints NDEF records from card"}, // {"mad", CmdHF14aDesMAD, IfPm3Iso14443a, "Prints MAD records from card"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "------------------------ " _CYAN_("Keys") " -----------------------"}, + {"changekey", CmdHF14ADesChangeKey, IfPm3Iso14443a, "Change Key"}, + {"chkeysetings", CmdHF14ADesChKeySettings, IfPm3Iso14443a, "Change Key Settings"}, + {"getkeysetings", CmdHF14ADesGetKeySettings, IfPm3Iso14443a, "Get Key Settings"}, {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("Applications") " -------------------"}, {"bruteaid", CmdHF14ADesBruteApps, IfPm3Iso14443a, "Recover AIDs by bruteforce"}, {"createaid", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application ID"}, diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index ad4c6c545..540e5d6b8 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -523,6 +523,9 @@ static void DesfireSplitBytesToBlock(uint8_t *blockdata, size_t *blockdatacount, int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { int res = PM3_SUCCESS; + + if (!PrintChannelModeWarning(cmd, ctx->secureChannel, ctx->cmdSet, ctx->commMode)) + DesfirePrintContext(ctx); uint8_t databuf[250 * 5] = {0}; size_t databuflen = 0; @@ -820,8 +823,8 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel Desfire_session_key_new(RndA, RndB, key, &sesskey); memcpy(dctx->sessionKeyEnc, sesskey.data, desfire_get_key_length(dctx->keyType)); - PrintAndLogEx(INFO, "encRndA : %s", sprint_hex(encRndA, rndlen)); - PrintAndLogEx(INFO, "IV : %s", sprint_hex(IV, rndlen)); + //PrintAndLogEx(INFO, "encRndA : %s", sprint_hex(encRndA, rndlen)); + //PrintAndLogEx(INFO, "IV : %s", sprint_hex(IV, rndlen)); if (dctx->keyType == T_DES) { if (secureChannel == DACd40) des_decrypt(encRndA, encRndA, key->data); @@ -839,8 +842,8 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel } rol(RndA, rndlen); - PrintAndLogEx(INFO, "Expected_RndA : %s", sprint_hex(RndA, rndlen)); - PrintAndLogEx(INFO, "Generated_RndA : %s", sprint_hex(encRndA, rndlen)); + //PrintAndLogEx(INFO, "Expected_RndA : %s", sprint_hex(RndA, rndlen)); + //PrintAndLogEx(INFO, "Generated_RndA : %s", sprint_hex(encRndA, rndlen)); for (uint32_t x = 0; x < rndlen; x++) { if (RndA[x] != encRndA[x]) { if (g_debugMode > 1) { @@ -867,7 +870,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel memset(dctx->IV, 0, DESFIRE_MAX_KEY_SIZE); dctx->secureChannel = secureChannel; memcpy(dctx->sessionKeyMAC, dctx->sessionKeyEnc, desfire_get_key_length(dctx->keyType)); - PrintAndLogEx(INFO, "sessionKeyEnc : %s", sprint_hex(dctx->sessionKeyEnc, desfire_get_key_length(dctx->keyType))); + PrintAndLogEx(INFO, "Session key : %s", sprint_hex(dctx->sessionKeyEnc, desfire_get_key_length(dctx->keyType))); return PM3_SUCCESS; } From 23bcc7515a23fad1e0e37ccb782a7000a86dd195 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 9 Jul 2021 17:51:08 +0200 Subject: [PATCH 244/309] allow some tests to run also under --long --- tools/pm3_tests.sh | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tools/pm3_tests.sh b/tools/pm3_tests.sh index aba88f922..499673c80 100755 --- a/tools/pm3_tests.sh +++ b/tools/pm3_tests.sh @@ -487,13 +487,10 @@ while true; do if ! CheckExecute slow "emv long test" "$CLIENTBIN -c 'emv test -l'" "Test(s) \[ ok"; then break; fi if ! CheckExecute "hf iclass lookup test" "$CLIENTBIN -c 'hf iclass lookup --csn 9655a400f8ff12e0 --epurse f0ffffffffffffff --macs 0000000089cb984b -f $DICPATH/iclass_default_keys.dic'" \ "valid key AE A6 84 A6 DA B2 32 78"; then break; fi - - if ! $SLOWTESTS; then - if ! CheckExecute "hf iclass loclass test" "$CLIENTBIN -c 'hf iclass loclass --test'" "key diversification (ok)"; then break; fi - if ! CheckExecute "emv test" "$CLIENTBIN -c 'emv test'" "Test(s) \[ ok"; then break; fi - if ! CheckExecute "hf cipurse test" "$CLIENTBIN -c 'hf cipurse test'" "Tests \[ ok"; then break; fi - if ! CheckExecute "hf mfdes test" "$CLIENTBIN -c 'hf mfdes test'" "Tests \[ ok"; then break; fi - fi + if ! CheckExecute "hf iclass loclass test" "$CLIENTBIN -c 'hf iclass loclass --test'" "key diversification (ok)"; then break; fi + if ! CheckExecute "emv test" "$CLIENTBIN -c 'emv test'" "Test(s) \[ ok"; then break; fi + if ! CheckExecute "hf cipurse test" "$CLIENTBIN -c 'hf cipurse test'" "Tests \[ ok"; then break; fi + if ! CheckExecute "hf mfdes test" "$CLIENTBIN -c 'hf mfdes test'" "Tests \[ ok"; then break; fi fi echo -e "\n------------------------------------------------------------" echo -e "Tests [ ${C_GREEN}OK${C_NC} ] ${C_OK}\n" From cbffdd7552cbcd38450ddfc221c74c0fbeb55989 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 19:26:15 +0300 Subject: [PATCH 245/309] add print keysettings --- client/src/mifare/desfirecore.c | 101 +++++++++++++++++++++++++- client/src/mifare/desfirecore.h | 5 ++ client/src/mifare/desfiresecurechan.c | 2 + 3 files changed, 106 insertions(+), 2 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 540e5d6b8..fd1fe6256 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -909,7 +909,7 @@ int DesfireCreateApplication(DesfireContext *dctx, uint8_t *appdata, size_t appd uint8_t respcode = 0xff; uint8_t resp[257] = {0}; size_t resplen = 0; - int res = DesfireExchangeEx(false, dctx, MFDES_CREATE_APPLICATION, appdata, appdatalen, &respcode, resp, &resplen, true, 24); + int res = DesfireExchangeEx(false, dctx, MFDES_CREATE_APPLICATION, appdata, appdatalen, &respcode, resp, &resplen, true, 0); if (res != PM3_SUCCESS) return res; if (respcode != MFDES_S_OPERATION_OK || resplen != 0) @@ -923,7 +923,7 @@ int DesfireDeleteApplication(DesfireContext *dctx, uint32_t aid) { DesfireAIDUintToByte(aid, data); uint8_t resp[257] = {0}; size_t resplen = 0; - int res = DesfireExchangeEx(false, dctx, MFDES_DELETE_APPLICATION, data, sizeof(data), &respcode, resp, &resplen, true, 24); + int res = DesfireExchangeEx(false, dctx, MFDES_DELETE_APPLICATION, data, sizeof(data), &respcode, resp, &resplen, true, 0); if (res != PM3_SUCCESS) return res; if (respcode != MFDES_S_OPERATION_OK || resplen != 0) @@ -931,3 +931,100 @@ int DesfireDeleteApplication(DesfireContext *dctx, uint32_t aid) { return PM3_SUCCESS; } +int DesfireGetKeySettings(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { + uint8_t respcode = 0xff; + int res = DesfireExchange(dctx, MFDES_GET_KEY_SETTINGS, NULL, 0, &respcode, resp, resplen); + if (res != PM3_SUCCESS) + return res; + if (respcode != MFDES_S_OPERATION_OK) + return PM3_EAPDU_FAIL; + return PM3_SUCCESS; +} + +int DesfireGetKeyVersion(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { + uint8_t respcode = 0xff; + int res = DesfireExchange(dctx, MFDES_GET_KEY_VERSION, NULL, 0, &respcode, resp, resplen); + if (res != PM3_SUCCESS) + return res; + if (respcode != MFDES_S_OPERATION_OK) + return PM3_EAPDU_FAIL; + return PM3_SUCCESS; +} + +int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len) { + uint8_t respcode = 0xff; + uint8_t resp[257] = {0}; + size_t resplen = 0; + int res = DesfireExchange(dctx, MFDES_CHANGE_KEY_SETTINGS, data, len, &respcode, resp, &resplen); + if (res != PM3_SUCCESS) + return res; + if (respcode != MFDES_S_OPERATION_OK || resplen != 0) + return PM3_EAPDU_FAIL; + return PM3_SUCCESS; +} + +static void PrintKeyType(uint8_t keytype) { + switch(keytype) { + case 00: + PrintAndLogEx(SUCCESS, "Key: 2TDEA"); + break; + case 01: + PrintAndLogEx(SUCCESS, "Key: 3TDEA"); + break; + case 02: + PrintAndLogEx(SUCCESS, "Key: AES"); + break; + default: + PrintAndLogEx(SUCCESS, "Key: unknown: 0x%02x", keytype); + break; + } +} + +static void PrintKeySettingsPICC(uint8_t keysettings, uint8_t numkeys) { + PrintAndLogEx(SUCCESS, "PICC level rights:"); + PrintAndLogEx(SUCCESS, "[%c...] CMK Configuration changeable : %s", (keysettings & (1 << 3)) ? '1' : '0', (keysettings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)"); + PrintAndLogEx(SUCCESS, "[.%c..] CMK required for create/delete : %s", (keysettings & (1 << 2)) ? '1' : '0', (keysettings & (1 << 2)) ? _GREEN_("NO") : "YES"); + PrintAndLogEx(SUCCESS, "[..%c.] Directory list access with CMK : %s", (keysettings & (1 << 1)) ? '1' : '0', (keysettings & (1 << 1)) ? _GREEN_("NO") : "YES"); + PrintAndLogEx(SUCCESS, "[...%c] CMK is changeable : %s", (keysettings & (1 << 0)) ? '1' : '0', (keysettings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)"); + + PrintAndLogEx(SUCCESS, "\nkey count: %d", numkeys & 0x0f); +} + +static void PrintKeySettingsApp(uint8_t keysettings, uint8_t numkeys) { + // Access rights. + PrintAndLogEx(SUCCESS, "Application level rights:"); + uint8_t rights = ((keysettings >> 4) & 0x0F); + switch (rights) { + case 0x0: + PrintAndLogEx(SUCCESS, "-- AMK authentication is necessary to change any key (default)"); + break; + case 0xE: + PrintAndLogEx(SUCCESS, "-- Authentication with the key to be changed (same KeyNo) is necessary to change a key"); + break; + case 0xF: + PrintAndLogEx(SUCCESS, "-- All keys (except AMK,see Bit0) within this application are frozen"); + break; + default: + PrintAndLogEx(SUCCESS, + "-- Authentication with the specified key is necessary to change any key.\n" + "A change key and a PICC master key (CMK) can only be changed after authentication with the master key.\n" + "For keys other then the master or change key, an authentication with the same key is needed." + ); + break; + } + + PrintAndLogEx(SUCCESS, "[%c...] AMK Configuration changeable : %s", (keysettings & (1 << 3)) ? '1' : '0', (keysettings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)"); + PrintAndLogEx(SUCCESS, "[.%c..] AMK required for create/delete : %s", (keysettings & (1 << 2)) ? '1' : '0', (keysettings & (1 << 2)) ? "NO" : "YES"); + PrintAndLogEx(SUCCESS, "[..%c.] Directory list access with AMK : %s", (keysettings & (1 << 1)) ? '1' : '0', (keysettings & (1 << 1)) ? "NO" : "YES"); + PrintAndLogEx(SUCCESS, "[...%c] AMK is changeable : %s", (keysettings & (1 << 0)) ? '1' : '0', (keysettings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)"); + + PrintKeyType(numkeys >> 6); + PrintAndLogEx(SUCCESS, "\nkey count: %d", numkeys & 0x0f); +} + +void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel) { + if (applevel) + PrintKeySettingsApp(keysettings, numkeys); + else + PrintKeySettingsPICC(keysettings, numkeys); +} diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 080fed18d..8943fd971 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -46,4 +46,9 @@ int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireCreateApplication(DesfireContext *dctx, uint8_t *appdata, size_t appdatalen); int DesfireDeleteApplication(DesfireContext *dctx, uint32_t aid); +int DesfireGetKeyVersion(DesfireContext *dctx, uint8_t *resp, size_t *resplen); +int DesfireGetKeySettings(DesfireContext *dctx, uint8_t *resp, size_t *resplen); +int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len); +void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel); + #endif // __DESFIRECORE_H diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 197769472..607a42f25 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -28,6 +28,7 @@ AllowedChannelModesS AllowedChannelModes[] = { {MFDES_DELETE_APPLICATION, DACd40, DCCNative, DCMPlain}, {MFDES_GET_APPLICATION_IDS, DACd40, DCCNative, DCMPlain}, {MFDES_GET_DF_NAMES, DACd40, DCCNative, DCMPlain}, + {MFDES_GET_KEY_SETTINGS, DACd40, DCCNative, DCMPlain}, {MFDES_READ_DATA, DACd40, DCCNative, DCMMACed}, {MFDES_WRITE_DATA, DACd40, DCCNative, DCMMACed}, @@ -52,6 +53,7 @@ AllowedChannelModesS AllowedChannelModes[] = { {MFDES_DELETE_APPLICATION, DACEV1, DCCNative, DCMMACed}, {MFDES_GET_APPLICATION_IDS, DACEV1, DCCNative, DCMMACed}, {MFDES_GET_DF_NAMES, DACEV1, DCCNative, DCMMACed}, + {MFDES_GET_KEY_SETTINGS, DACEV1, DCCNative, DCMMACed}, {MFDES_GET_UID, DACEV1, DCCNative, DCMEncrypted}, }; From c8777ebea8e5eadf8d66a32746f45247d3fe8012 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 19:26:41 +0300 Subject: [PATCH 246/309] add getkeysettings command --- client/src/cmdhfmfdes.c | 129 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 122 insertions(+), 7 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index d10d910bb..c2ab80b64 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5014,7 +5014,9 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct uint8_t keynoid, uint8_t algoid, uint8_t keyid, uint8_t kdfid, uint8_t kdfiid, uint8_t cmodeid, uint8_t ccsetid, uint8_t schannid, - int *securechannel) { + uint8_t appid, + int *securechannel, + uint32_t *aid) { uint8_t keynum = defaultKeyNum; int algores = defaultAlgoId; @@ -5080,6 +5082,14 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct if (CLIGetOptionList(arg_get_str(ctx, schannid), DesfireSecureChannelOpts, &secchann)) return PM3_ESOFT; } + + if (appid && aid) { + *aid = 0x000000; + + //int arg_get_u32_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint32_t def, uint32_t *out, uint8_t nlen, bool optional); + // if (arg_get_u32_hexstr_def_nlen(ctx, appid, 0x000000, aid, 3, true)) + // return PM3_ESOFT; + } DesfireSetKey(dctx, keynum, algores, key); DesfireSetKdf(dctx, kdfAlgo, kdfInput, kdfInputLen); @@ -5113,7 +5123,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, &securechann); + int res = CmdDesGetSessionParameters(ctx, &dctx, 1, 2, 3, 4, 5, 6, 7, 8, 0, &securechann, NULL); if (res) { CLIParserFree(ctx); return res; @@ -5149,9 +5159,114 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { return PM3_SUCCESS; } - //{"getkeysetings", CmdHF14ADesGetKeySettings, IfPm3Iso14443a, "Get Key Settings"}, + static int CmdHF14ADesGetKeySettings(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes getkeysetings", + "Get key settings for card level or application level.", + "hf mfdes getkeysetings -> execute with default factory setup"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "apdu", "show APDU requests and responses"), + arg_lit0("v", "verbose", "show technical data"), + arg_int0("n", "keyno", "", "Key number"), + arg_str0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), + arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None, AN10922, Gallagher"), + 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_int0(NULL, "appid", "", "Application ID (HEX 3 bytes)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + bool APDULogging = arg_get_lit(ctx, 1); + bool verbose = arg_get_lit(ctx, 2); + + DesfireContext dctx; + int securechann = DCMPlain; + uint32_t appid = 0x000000; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, &appid); + if (res) { + CLIParserFree(ctx); + return res; + } + + SetAPDULogging(APDULogging); + CLIParserFree(ctx); + + if (verbose) + DesfirePrintContext(&dctx); + + res = DesfireSelectAIDHex(&dctx, appid, false, 0); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); + DropField(); + return PM3_ESOFT; + } + + res = DesfireAuthenticate(&dctx, securechann); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + if (DesfireIsAuthenticated(&dctx)) { + if (verbose) + PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated")); + } else { + return PM3_ESOFT; + } + + uint8_t buf[APDU_RES_LEN] = {0}; + size_t buflen = 0; + + res = DesfireGetKeySettings(&dctx, buf, &buflen); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire DesfireGetKeySettings command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } +// if (verbose) + PrintAndLogEx(INFO, "DesfireGetKeySettings[%d]: %s", buflen, sprint_hex(buf, buflen)); + + if (buflen < 2) { + PrintAndLogEx(ERR, "Command DesfireGetKeySettings returned wrong length: %d", buflen); + DropField(); + return PM3_ESOFT; + } + + PrintAndLogEx(INFO, "----------------------- " _CYAN_("Key settings") " -----------------------"); + PrintKeySettings(buf[0], buf[1], (appid != 0x000000)); + if (buflen > 2) + PrintAndLogEx(INFO, "ak ver: %d", buf[2]); + if (buflen > 3) + PrintAndLogEx(INFO, "num keysets: %d", buf[3]); + if (buflen > 4) + PrintAndLogEx(INFO, "max keysize: %d", buf[4]); + if (buflen > 5) + PrintAndLogEx(INFO, "app key settings: 0x%02x", buf[5]); + + + + /*if (buflen > 0) { + PrintAndLogEx(INFO, "----------------------- " _CYAN_("File list") " -----------------------"); + for (int i = 0; i < buflen; i++) + PrintAndLogEx(INFO, "AID: %06x ISO file id: %02x%02x ISO DF name[%" PRIu32 "]: %s", + DesfireAIDByteToUint(&buf[i * 24 + 1]), + buf[i * 24 + 1 + 3], buf[i * 24 + 1 + 4], + strlen((char *)&buf[i * 24 + 1 + 5]), + &buf[i * 24 + 1 + 5]); + } else { + PrintAndLogEx(INFO, "There is no applications on the card"); + }*/ + + DropField(); return PM3_SUCCESS; } @@ -5182,7 +5297,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { DesfireContext dctx; int securechann = DCMPlain; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, &securechann); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, NULL); if (res) { CLIParserFree(ctx); return res; @@ -5264,7 +5379,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { DesfireContext dctx; int securechann = DCMPlain; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, &securechann); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, NULL); if (res) { CLIParserFree(ctx); return res; @@ -5344,8 +5459,8 @@ static command_t CommandTable[] = { // {"mad", CmdHF14aDesMAD, IfPm3Iso14443a, "Prints MAD records from card"}, {"-----------", CmdHelp, IfPm3Iso14443a, "------------------------ " _CYAN_("Keys") " -----------------------"}, {"changekey", CmdHF14ADesChangeKey, IfPm3Iso14443a, "Change Key"}, - {"chkeysetings", CmdHF14ADesChKeySettings, IfPm3Iso14443a, "Change Key Settings"}, - {"getkeysetings", CmdHF14ADesGetKeySettings, IfPm3Iso14443a, "Get Key Settings"}, + {"chkeysetings", CmdHF14ADesChKeySettings, IfPm3Iso14443a, "[new]Change Key Settings"}, + {"getkeysetings", CmdHF14ADesGetKeySettings, IfPm3Iso14443a, "[new]Get Key Settings"}, {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("Applications") " -------------------"}, {"bruteaid", CmdHF14ADesBruteApps, IfPm3Iso14443a, "Recover AIDs by bruteforce"}, {"createaid", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application ID"}, From eadf5882d84cfa4d91ad9211d98c3ee8b28f3746 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 9 Jul 2021 19:03:54 +0200 Subject: [PATCH 247/309] text --- doc/md/Use_of_Proxmark/0_Compilation-Instructions.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md b/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md index 2196bff39..c282a810f 100644 --- a/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md +++ b/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md @@ -7,9 +7,14 @@ Nevertheless, the firmware can be tuned depending on the Proxmark3 platform and Indeed, the RRG/Iceman fork can be used on other Proxmark3 hardware platforms as well. -Via some definitions, you can adjust the firmware for a given platform, but also to add features like the support of the Blue Shark add-on or to select which standalone mode to embed. +Via some definitions, you can adjust the firmware for a given platform, but also to add features like the support of the Blue Shark add-on or to select which standalone mode to embed. To learn how to adjust the firmware, please read [Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md). + +### for Proxmark3 RDV4 +The repo defaults for compiling a firmware and client suitable for Proxmark3 RDV4. + +## for generic Proxmark3 platforms +In order to build this repo for generic Proxmark3 platforms we urge you to read [Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md) -To learn how to adjust the firmware, please read [Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md). ## Get the latest commits From d4ff3e802f7d457a5ca2603990317e08b9778dfa Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 9 Jul 2021 19:04:53 +0200 Subject: [PATCH 248/309] text --- doc/md/Use_of_Proxmark/0_Compilation-Instructions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md b/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md index c282a810f..0f7cc52fd 100644 --- a/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md +++ b/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md @@ -32,7 +32,7 @@ make clean && make -j ### if you got an error Read the [troubleshooting guide](/doc/md/Installation_Instructions/Troubleshooting.md), -For instance, on WSl-1 you usually get the _libQt5Core.so.5 not found_ message +For instance, on WSl-1 you usually get the `libQt5Core.so.5 not found` message [solution](/doc/md/Installation_Instructions/Troubleshooting.md#libQt5Coreso5-not-found) From 0b13efc9a0e93d67b489b89ba656cb2e67efc3fa Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 9 Jul 2021 19:05:46 +0200 Subject: [PATCH 249/309] text --- doc/md/Use_of_Proxmark/0_Compilation-Instructions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md b/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md index 0f7cc52fd..00659d71e 100644 --- a/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md +++ b/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md @@ -9,10 +9,10 @@ Indeed, the RRG/Iceman fork can be used on other Proxmark3 hardware platforms as Via some definitions, you can adjust the firmware for a given platform, but also to add features like the support of the Blue Shark add-on or to select which standalone mode to embed. To learn how to adjust the firmware, please read [Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md). -### for Proxmark3 RDV4 +### Compile for Proxmark3 RDV4 The repo defaults for compiling a firmware and client suitable for Proxmark3 RDV4. -## for generic Proxmark3 platforms +### Compile for generic Proxmark3 platforms In order to build this repo for generic Proxmark3 platforms we urge you to read [Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md) From 200a08e0914144c500ef02d179fae7c47eac835b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 9 Jul 2021 19:06:45 +0200 Subject: [PATCH 250/309] text --- doc/md/Use_of_Proxmark/0_Compilation-Instructions.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md b/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md index 00659d71e..9ac9472ea 100644 --- a/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md +++ b/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md @@ -79,6 +79,9 @@ proxmark3 /dev/ttyACM0 --flash --unlock-bootloader --image /tmp/my-bootrom.elf - ## Run the client In most cases, you can run the script `pm3` which try to auto-detect the port to use, on several OS. +```sh +./pm3 +``` For the other cases, specify the port by yourself. For example, for a Proxmark3 connected via USB under Linux: From ed5945d382455298d7b0531b1a99f70e24a95987 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 9 Jul 2021 19:15:37 +0200 Subject: [PATCH 251/309] textual --- doc/md/Use_of_Proxmark/1_Validation.md | 12 ++++++------ .../2_Configuration-and-Verification.md | 4 ++-- doc/md/Use_of_Proxmark/3_Commands-and-Features.md | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/md/Use_of_Proxmark/1_Validation.md b/doc/md/Use_of_Proxmark/1_Validation.md index 6f644d206..7e75a12c3 100644 --- a/doc/md/Use_of_Proxmark/1_Validation.md +++ b/doc/md/Use_of_Proxmark/1_Validation.md @@ -3,9 +3,9 @@ If all went well you should get some information about the firmware and memory usage as well as the prompt, something like this. ``` -[=] Session log /home/iceman/.proxmark3/log_20200521.txt +[=] Session log /home/iceman/.proxmark3/log_20210708.txt [+] loaded from JSON file /home/iceman/.proxmark3/preferences.json -[=] Using UART port /dev/ttyS7 +[=] Using UART port /dev/ttyS3 [=] Communicating with PM3 over USB-CDC @@ -21,8 +21,8 @@ If all went well you should get some information about the firmware and memory u [ Proxmark3 RFID instrument ] [ CLIENT ] - client: RRG/Iceman/master/v4.9237-2-g2cb19874 2020-05-21 22:00:00 - compiled with GCC 9.3.0 OS:Linux ARCH:x86_64 + client: RRG/Iceman/master/v4.13441-129-g60d132fcc 2021-07-08 22:00:00 + compiled with GCC 10.3.0 OS:Linux ARCH:x86_64 [ PROXMARK RDV4 ] device.................... RDV4 @@ -32,8 +32,8 @@ If all went well you should get some information about the firmware and memory u FPC USART for BT add-on... absent [ ARM ] - bootrom: RRG/Iceman/master/v4.9237-2-g2cb19874 2020-05-21 22:00:10 - os: RRG/Iceman/master/v4.9237-2-g2cb19874 2019-05-21 22:00:26 + bootrom: RRG/Iceman/master/v4.13441 2020-05-21 22:00:10 + os: RRG/Iceman/master/v4.13441 2019-05-21 22:00:26 compiled with GCC 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] [ FPGA ] diff --git a/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md b/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md index 55e05af92..8ed9adf2b 100644 --- a/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md +++ b/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md @@ -1,6 +1,6 @@ -### First things on your RDV40 +### First things on your Proxmark3 RDV4 -You will need to run these commands to make sure your rdv4 is prepared +You will need to run these commands to make sure your RDV4 is prepared ``` [usb] pm3 --> script run init_rdv4 ``` diff --git a/doc/md/Use_of_Proxmark/3_Commands-and-Features.md b/doc/md/Use_of_Proxmark/3_Commands-and-Features.md index d2786956a..59be59127 100644 --- a/doc/md/Use_of_Proxmark/3_Commands-and-Features.md +++ b/doc/md/Use_of_Proxmark/3_Commands-and-Features.md @@ -9,7 +9,7 @@ Please make sure you've gone through the following pages firstly: ## To get interactive help -As seen before, for basic help type `help`. Or for help on a set of sub commands type the command followed by `help`. For example `hf mf help`. Many commands uses the `h` / `-h` parameter to show a help text. +As seen before, for basic help type `help`. Or for help on a set of sub commands type the command followed by `help`. For example `hf mf help`. Many commands uses the `-h` / `--help` parameter to show a help text. ## New Features in RDV4 From 3634fb40913450bc16bca878137a09a8d738844e Mon Sep 17 00:00:00 2001 From: scott4290 Date: Sat, 10 Jul 2021 00:00:42 -0400 Subject: [PATCH 252/309] Update cmdlft55xx.c Fixed two bugs: >= preventing users from testing one password (start_password=end_password) and reporting that the start password is greater than the end password. The second issue is when the end password _is_ the correct password, the found password reported was curr -1. --- client/src/cmdlft55xx.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 254149756..765f966e4 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -3301,7 +3301,7 @@ static int CmdT55xxBruteForce(const char *Cmd) { uint32_t curr = 0; uint8_t found = 0; // > 0 if found xx1 xx downlink needed, 1 found - if (start_password >= end_password) { + if (start_password > end_password) { PrintAndLogEx(FAILED, "Error, start larger then end password"); return PM3_EINVARG; } @@ -3331,7 +3331,10 @@ static int CmdT55xxBruteForce(const char *Cmd) { PrintAndLogEx(NORMAL, ""); if (found) { - PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08X") " ]", curr - 1); + if (curr != end_password) { + PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08X") " ]", curr - 1); + } else + PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08X") " ]", curr); T55xx_Print_DownlinkMode((found >> 1) & 3); } else PrintAndLogEx(WARNING, "Bruteforce failed, last tried: [ " _YELLOW_("%08X") " ]", curr); From 13892a31f198bfd5f66b7c10e43fadd59b32dff0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 10 Jul 2021 08:29:42 +0200 Subject: [PATCH 253/309] text --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17d45f1e5..f01b04150 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fix `lf t55xx brute` - now correctly prints last key if it was correct (@scott4290) - Added support python scripts (@salmg) - Add new standalone mode `hf_reblay` - relay 14a over bt (@salmg) - Added one new key from gun cloner found in wild (@scott4290) From 6fdb5f190beae5bf63fcf343a11fe87a06700fbd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 10 Jul 2021 09:31:53 +0200 Subject: [PATCH 254/309] text --- doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md index d2b934e98..b28fcf64e 100644 --- a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md +++ b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md @@ -71,7 +71,7 @@ If you have installed a Blue Shark add-on on your RDV4, define `PLATFORM_EXTRAS= ## STANDALONE -The RRG/Iceman fork gives you to easily choose which standalone mode to embed in the firmware. +The RRG/Iceman repository gives you to easily choose which standalone mode to embed in the firmware. Here are the supported values you can assign to `STANDALONE` in `Makefile.platform`: @@ -136,6 +136,7 @@ a series of `SKIP_*` allow to skip some of the functionalities and to get a smal |SKIP_HFSNIFF=1 | 0.5kb |SKIP_HFPLOT=1 | 0.3kb + So for example, at the time of writing, this is a valid `Makefile.platform` compiling an image for 256k: ``` PLATFORM=PM3GENERIC From a609733dd77cc4426f50c79f582bb47aa738caab Mon Sep 17 00:00:00 2001 From: Iceman Date: Sat, 10 Jul 2021 12:06:52 +0200 Subject: [PATCH 255/309] Update README.md text --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cc8fc9772..5e070c52a 100644 --- a/README.md +++ b/README.md @@ -60,12 +60,13 @@ We define generic Proxmark3 platforms as following devices. - **Note**: unknown pin assignments. - ⚠ Ryscorp Proxmark3 Pro - **Note**: device has different fpga and unknown pin assignments. + - ⚠ i-copy + - **Note**: reversed hw, experimental support maintained in [icopyx-community pm3 repo](https://github.com/iCopy-X-Community/icopyx-community-pm3) **Unknown support status** - ⚠ VX - **Note**: unknown device hw - - ⚠ i-copy - - **Note**: unknown device hw + **256kb flash memory size of generic Proxmark3 platforms** From 67d7d29d740c0dbe8e5f997e2b55539bf7f15454 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 10 Jul 2021 15:07:51 +0300 Subject: [PATCH 256/309] CmdHF14ADesGetKeySettings works --- client/src/cmdhfmfdes.c | 14 +++++++++----- client/src/mifare/desfirecore.c | 6 ++++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index c2ab80b64..ac4fbb1b5 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5085,10 +5085,14 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct if (appid && aid) { *aid = 0x000000; - - //int arg_get_u32_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint32_t def, uint32_t *out, uint8_t nlen, bool optional); - // if (arg_get_u32_hexstr_def_nlen(ctx, appid, 0x000000, aid, 3, true)) - // return PM3_ESOFT; + int res = arg_get_u32_hexstr_def_nlen(ctx, appid, 0x000000, aid, 3, true); + if (res == 0) + return PM3_ESOFT; + if (res == 2) { + PrintAndLogEx(ERR, "AID length must have 3 bytes length"); + return PM3_EINVARG; + } + PrintAndLogEx(INFO, "--aid: %x", *aid); } DesfireSetKey(dctx, keynum, algores, key); @@ -5178,7 +5182,7 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { 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_int0(NULL, "appid", "", "Application ID (HEX 3 bytes)"), + arg_str0(NULL, "appid", "", "Application ID (HEX 3 bytes)"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index fd1fe6256..3d09fc58a 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -986,8 +986,9 @@ static void PrintKeySettingsPICC(uint8_t keysettings, uint8_t numkeys) { PrintAndLogEx(SUCCESS, "[.%c..] CMK required for create/delete : %s", (keysettings & (1 << 2)) ? '1' : '0', (keysettings & (1 << 2)) ? _GREEN_("NO") : "YES"); PrintAndLogEx(SUCCESS, "[..%c.] Directory list access with CMK : %s", (keysettings & (1 << 1)) ? '1' : '0', (keysettings & (1 << 1)) ? _GREEN_("NO") : "YES"); PrintAndLogEx(SUCCESS, "[...%c] CMK is changeable : %s", (keysettings & (1 << 0)) ? '1' : '0', (keysettings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)"); + PrintAndLogEx(SUCCESS, ""); - PrintAndLogEx(SUCCESS, "\nkey count: %d", numkeys & 0x0f); + PrintAndLogEx(SUCCESS, "key count: %d", numkeys & 0x0f); } static void PrintKeySettingsApp(uint8_t keysettings, uint8_t numkeys) { @@ -1017,9 +1018,10 @@ static void PrintKeySettingsApp(uint8_t keysettings, uint8_t numkeys) { PrintAndLogEx(SUCCESS, "[.%c..] AMK required for create/delete : %s", (keysettings & (1 << 2)) ? '1' : '0', (keysettings & (1 << 2)) ? "NO" : "YES"); PrintAndLogEx(SUCCESS, "[..%c.] Directory list access with AMK : %s", (keysettings & (1 << 1)) ? '1' : '0', (keysettings & (1 << 1)) ? "NO" : "YES"); PrintAndLogEx(SUCCESS, "[...%c] AMK is changeable : %s", (keysettings & (1 << 0)) ? '1' : '0', (keysettings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)"); + PrintAndLogEx(SUCCESS, ""); PrintKeyType(numkeys >> 6); - PrintAndLogEx(SUCCESS, "\nkey count: %d", numkeys & 0x0f); + PrintAndLogEx(SUCCESS, "key count: %d", numkeys & 0x0f); } void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel) { From b6e6070bfe6cb93518a214ba0e01f7cfb5646a50 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 10 Jul 2021 15:08:39 +0300 Subject: [PATCH 257/309] remove debug --- client/src/cmdhfmfdes.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index ac4fbb1b5..81a5d8a16 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5092,7 +5092,6 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct PrintAndLogEx(ERR, "AID length must have 3 bytes length"); return PM3_EINVARG; } - PrintAndLogEx(INFO, "--aid: %x", *aid); } DesfireSetKey(dctx, keynum, algores, key); @@ -5236,7 +5235,7 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { return PM3_ESOFT; } -// if (verbose) + if (verbose) PrintAndLogEx(INFO, "DesfireGetKeySettings[%d]: %s", buflen, sprint_hex(buf, buflen)); if (buflen < 2) { From e54f0e3a33faad679287a2d620f47f5ce1b2fb99 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 10 Jul 2021 15:10:15 +0300 Subject: [PATCH 258/309] move crc to new file --- client/src/mifare/desfire_crypto.c | 28 ---------------------------- client/src/mifare/desfire_crypto.h | 6 ------ client/src/mifare/desfirecrypto.c | 28 ++++++++++++++++++++++++++++ client/src/mifare/desfirecrypto.h | 6 ++++++ 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 23c8b1fd9..fd3cb427d 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -967,31 +967,3 @@ void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *i offset += block_size; } } - -void desfire_crc32(const uint8_t *data, const size_t len, uint8_t *crc) { - crc32_ex(data, len, crc); -} - -void desfire_crc32_append(uint8_t *data, const size_t len) { - crc32_ex(data, len, data + len); -} - -bool desfire_crc32_check(uint8_t *data, const size_t len, uint8_t *crc) { - uint8_t ccrc[4] = {0}; - desfire_crc32(data, len, ccrc); - return (memcmp(ccrc, crc, 4) == 0); -} - -void iso14443a_crc_append(uint8_t *data, size_t len) { - return compute_crc(CRC_14443_A, data, len, data + len, data + len + 1); -} - -void iso14443a_crc(uint8_t *data, size_t len, uint8_t *pbtCrc) { - return compute_crc(CRC_14443_A, data, len, pbtCrc, pbtCrc + 1); -} - -bool iso14443a_crc_check(uint8_t *data, const size_t len, uint8_t *crc) { - uint8_t ccrc[2] = {0}; - iso14443a_crc(data, len, ccrc); - return (memcmp(ccrc, crc, 2) == 0); -} diff --git a/client/src/mifare/desfire_crypto.h b/client/src/mifare/desfire_crypto.h index 689c0d56c..c4c879ef3 100644 --- a/client/src/mifare/desfire_crypto.h +++ b/client/src/mifare/desfire_crypto.h @@ -147,10 +147,4 @@ void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t l void mifare_kdf_an10922(const desfirekey_t key, const uint8_t *data, size_t len); -void desfire_crc32(const uint8_t *data, const size_t len, uint8_t *crc); -void desfire_crc32_append(uint8_t *data, const size_t len); -bool desfire_crc32_check(uint8_t *data, const size_t len, uint8_t *crc); -void iso14443a_crc_append(uint8_t *data, size_t len); -void iso14443a_crc(uint8_t *data, size_t len, uint8_t *pbtCrc); -bool iso14443a_crc_check(uint8_t *data, const size_t len, uint8_t *crc); #endif diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 64773c229..04c6d7dfb 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -308,3 +308,31 @@ void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *data, size_t len, uint8_t * memcpy(cmac, ctx->IV, kbs); } + +void desfire_crc32(const uint8_t *data, const size_t len, uint8_t *crc) { + crc32_ex(data, len, crc); +} + +void desfire_crc32_append(uint8_t *data, const size_t len) { + crc32_ex(data, len, data + len); +} + +bool desfire_crc32_check(uint8_t *data, const size_t len, uint8_t *crc) { + uint8_t ccrc[4] = {0}; + desfire_crc32(data, len, ccrc); + return (memcmp(ccrc, crc, 4) == 0); +} + +void iso14443a_crc_append(uint8_t *data, size_t len) { + return compute_crc(CRC_14443_A, data, len, data + len, data + len + 1); +} + +void iso14443a_crc(uint8_t *data, size_t len, uint8_t *pbtCrc) { + return compute_crc(CRC_14443_A, data, len, pbtCrc, pbtCrc + 1); +} + +bool iso14443a_crc_check(uint8_t *data, const size_t len, uint8_t *crc) { + uint8_t ccrc[2] = {0}; + iso14443a_crc(data, len, ccrc); + return (memcmp(ccrc, crc, 2) == 0); +} diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index 824225b39..6bffa376e 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -101,5 +101,11 @@ void DesfireCryptoEncDec(DesfireContext *ctx, bool use_session_key, uint8_t *src void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode, uint8_t *iv); void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *cmac); +void desfire_crc32(const uint8_t *data, const size_t len, uint8_t *crc); +void desfire_crc32_append(uint8_t *data, const size_t len); +bool desfire_crc32_check(uint8_t *data, const size_t len, uint8_t *crc); +void iso14443a_crc_append(uint8_t *data, size_t len); +void iso14443a_crc(uint8_t *data, size_t len, uint8_t *pbtCrc); +bool iso14443a_crc_check(uint8_t *data, const size_t len, uint8_t *crc); #endif // __DESFIRECRYPTO_H From 1cd467e1f35fc139bea84608f61ef1d70a5c124f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 10 Jul 2021 15:16:06 +0300 Subject: [PATCH 259/309] change param name --- client/src/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 81a5d8a16..71b224264 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5181,7 +5181,7 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { 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(NULL, "appid", "", "Application ID (HEX 3 bytes)"), + arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); From 5367cb4e23999d832722acc8294365853d803d7f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 10 Jul 2021 16:05:40 +0300 Subject: [PATCH 260/309] CmdHF14ADesChKeySettings command --- client/src/cmdhfmfdes.c | 85 +++++++++++++++++++++++++++++++-- client/src/mifare/desfirecore.c | 19 ++++---- client/src/mifare/desfirecore.h | 2 +- 3 files changed, 94 insertions(+), 12 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 71b224264..2f11f2f5b 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5157,8 +5157,86 @@ static int CmdHF14ADesDefault(const char *Cmd) { return PM3_SUCCESS; } -// {"chkeysetings", CmdHF14ADesChKeySettings, IfPm3Iso14443a, "Change Key Settings"}, + static int CmdHF14ADesChKeySettings(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes chkeysetings", + "Change key settings for card level or application level. WARNING: card level changes may block card!", + "hf mfdes chkeysetings -d 0e -> set picc key settings with default key/channel setup\n"\ + "hf mfdes chkeysetings --aid 123456 -d 0e -> set app 123456 key settings with default key/channel setup"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "apdu", "show APDU requests and responses"), + arg_lit0("v", "verbose", "show technical data"), + arg_int0("n", "keyno", "", "Key number"), + arg_str0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), + arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None, AN10922, Gallagher"), + 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(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), + arg_str0("d", "data", "", "Key settings (HEX 1 byte)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool APDULogging = arg_get_lit(ctx, 1); + bool verbose = arg_get_lit(ctx, 2); + + DesfireContext dctx; + int securechann = DCMPlain; + uint32_t appid = 0x000000; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, &appid); + if (res) { + CLIParserFree(ctx); + return res; + } + + uint32_t ksett32 = 0; + res = arg_get_u32_hexstr_def_nlen(ctx, 12, 0x000000, &ksett32, 1, false); + if (res == 0) + return PM3_ESOFT; + if (res == 2) { + PrintAndLogEx(ERR, "Key settings must have 1 byte length"); + return PM3_EINVARG; + } + + SetAPDULogging(APDULogging); + CLIParserFree(ctx); + + if (verbose) { + DesfirePrintContext(&dctx); + PrintAndLogEx(SUCCESS, "\nNew key settings:"); + PrintKeySettings(ksett32, 0, (appid != 0x000000), false); + } + + res = DesfireSelectAIDHex(&dctx, appid, false, 0); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); + DropField(); + return PM3_ESOFT; + } + + res = DesfireAuthenticate(&dctx, securechann); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + if (DesfireIsAuthenticated(&dctx)) { + if (verbose) + PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated")); + } else { + return PM3_ESOFT; + } + + + + return PM3_SUCCESS; } @@ -5167,7 +5245,8 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes getkeysetings", "Get key settings for card level or application level.", - "hf mfdes getkeysetings -> execute with default factory setup"); + "hf mfdes getkeysetings -> get picc key settings with default key/channel setup\n"\ + "hf mfdes getkeysetings --aid 123456 -> get app 123456 key settings with default key/channel setup"); void *argtable[] = { arg_param_begin, @@ -5245,7 +5324,7 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { } PrintAndLogEx(INFO, "----------------------- " _CYAN_("Key settings") " -----------------------"); - PrintKeySettings(buf[0], buf[1], (appid != 0x000000)); + PrintKeySettings(buf[0], buf[1], (appid != 0x000000), true); if (buflen > 2) PrintAndLogEx(INFO, "ak ver: %d", buf[2]); if (buflen > 3) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 3d09fc58a..29454e018 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -980,7 +980,7 @@ static void PrintKeyType(uint8_t keytype) { } } -static void PrintKeySettingsPICC(uint8_t keysettings, uint8_t numkeys) { +static void PrintKeySettingsPICC(uint8_t keysettings, uint8_t numkeys, bool print2ndbyte) { PrintAndLogEx(SUCCESS, "PICC level rights:"); PrintAndLogEx(SUCCESS, "[%c...] CMK Configuration changeable : %s", (keysettings & (1 << 3)) ? '1' : '0', (keysettings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)"); PrintAndLogEx(SUCCESS, "[.%c..] CMK required for create/delete : %s", (keysettings & (1 << 2)) ? '1' : '0', (keysettings & (1 << 2)) ? _GREEN_("NO") : "YES"); @@ -988,10 +988,11 @@ static void PrintKeySettingsPICC(uint8_t keysettings, uint8_t numkeys) { PrintAndLogEx(SUCCESS, "[...%c] CMK is changeable : %s", (keysettings & (1 << 0)) ? '1' : '0', (keysettings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)"); PrintAndLogEx(SUCCESS, ""); - PrintAndLogEx(SUCCESS, "key count: %d", numkeys & 0x0f); + if (print2ndbyte) + PrintAndLogEx(SUCCESS, "key count: %d", numkeys & 0x0f); } -static void PrintKeySettingsApp(uint8_t keysettings, uint8_t numkeys) { +static void PrintKeySettingsApp(uint8_t keysettings, uint8_t numkeys, bool print2ndbyte) { // Access rights. PrintAndLogEx(SUCCESS, "Application level rights:"); uint8_t rights = ((keysettings >> 4) & 0x0F); @@ -1020,13 +1021,15 @@ static void PrintKeySettingsApp(uint8_t keysettings, uint8_t numkeys) { PrintAndLogEx(SUCCESS, "[...%c] AMK is changeable : %s", (keysettings & (1 << 0)) ? '1' : '0', (keysettings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)"); PrintAndLogEx(SUCCESS, ""); - PrintKeyType(numkeys >> 6); - PrintAndLogEx(SUCCESS, "key count: %d", numkeys & 0x0f); + if (print2ndbyte) { + PrintKeyType(numkeys >> 6); + PrintAndLogEx(SUCCESS, "key count: %d", numkeys & 0x0f); + } } -void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel) { +void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel, bool print2ndbyte) { if (applevel) - PrintKeySettingsApp(keysettings, numkeys); + PrintKeySettingsApp(keysettings, numkeys, print2ndbyte); else - PrintKeySettingsPICC(keysettings, numkeys); + PrintKeySettingsPICC(keysettings, numkeys, print2ndbyte); } diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 8943fd971..bdabc11fd 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -49,6 +49,6 @@ int DesfireDeleteApplication(DesfireContext *dctx, uint32_t aid); int DesfireGetKeyVersion(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetKeySettings(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len); -void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel); +void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel, bool print2ndbyte); #endif // __DESFIRECORE_H From 3f7f343f6fd2359faa8c46286ce333d673731579 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 10 Jul 2021 16:11:44 +0300 Subject: [PATCH 261/309] DesfireChangeKeySettings works --- client/src/cmdhfmfdes.c | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 2f11f2f5b..6f63e7a5b 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5229,14 +5229,20 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { if (DesfireIsAuthenticated(&dctx)) { if (verbose) - PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated")); + PrintAndLogEx(INFO, "Desfire " _GREEN_("authenticated")); } else { return PM3_ESOFT; } + uint8_t keysett = ksett32 & 0x0f; + res = DesfireChangeKeySettings(&dctx, &keysett, 1); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire DesfireChangeKeySettings command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } - - + PrintAndLogEx(INFO, "Key settings " _GREEN_("changed")); return PM3_SUCCESS; } @@ -5299,7 +5305,7 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { if (DesfireIsAuthenticated(&dctx)) { if (verbose) - PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated")); + PrintAndLogEx(INFO, "Desfire " _GREEN_("authenticated")); } else { return PM3_ESOFT; } @@ -5334,20 +5340,6 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { if (buflen > 5) PrintAndLogEx(INFO, "app key settings: 0x%02x", buf[5]); - - - /*if (buflen > 0) { - PrintAndLogEx(INFO, "----------------------- " _CYAN_("File list") " -----------------------"); - for (int i = 0; i < buflen; i++) - PrintAndLogEx(INFO, "AID: %06x ISO file id: %02x%02x ISO DF name[%" PRIu32 "]: %s", - DesfireAIDByteToUint(&buf[i * 24 + 1]), - buf[i * 24 + 1 + 3], buf[i * 24 + 1 + 4], - strlen((char *)&buf[i * 24 + 1 + 5]), - &buf[i * 24 + 1 + 5]); - } else { - PrintAndLogEx(INFO, "There is no applications on the card"); - }*/ - DropField(); return PM3_SUCCESS; } @@ -5407,7 +5399,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { if (DesfireIsAuthenticated(&dctx)) { if (verbose) - PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated")); + PrintAndLogEx(INFO, "Desfire " _GREEN_("authenticated")); } else { return PM3_ESOFT; } @@ -5489,7 +5481,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { if (DesfireIsAuthenticated(&dctx)) { if (verbose) - PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated")); + PrintAndLogEx(INFO, "Desfire " _GREEN_("authenticated")); } else { return PM3_ESOFT; } From d8a8c015bcfe7a4368671f05361511b3e9b24d2d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 11 Jul 2021 18:14:27 +0300 Subject: [PATCH 262/309] channel d40/encode works --- client/src/cmdhfmfdes.c | 5 ++++- client/src/mifare/desfirecrypto.c | 9 ++++++--- client/src/mifare/desfiresecurechan.c | 22 ++++++++++++++-------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 6f63e7a5b..88152b932 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5029,6 +5029,8 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct int commmode = defaultCommMode; int commset = defaultCommSet; int secchann = defaultSecureChannel; + if (securechannel) + secchann = *securechannel; if (keynoid) { keynum = arg_get_int_def(ctx, keynoid, keynum); @@ -5079,6 +5081,7 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct } if (schannid) { + if (CLIGetOptionList(arg_get_str(ctx, schannid), DesfireSecureChannelOpts, &secchann)) return PM3_ESOFT; } @@ -5187,7 +5190,7 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { bool verbose = arg_get_lit(ctx, 2); DesfireContext dctx; - int securechann = DCMPlain; + int securechann = DCMEncrypted; uint32_t appid = 0x000000; int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, &appid); if (res) { diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 04c6d7dfb..d3955f92d 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -215,8 +215,11 @@ void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *s uint8_t data[1024] = {0}; uint8_t xiv[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; - if (ctx->secureChannel == DACd40) + bool xencode = encode; + if (ctx->secureChannel == DACd40) { memset(ctx->IV, 0, DESFIRE_MAX_CRYPTO_BLOCK_SIZE); + xencode = false; + } size_t block_size = desfire_get_key_block_length(ctx->keyType); @@ -228,9 +231,9 @@ void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *s size_t offset = 0; while (offset < srcdatalen) { if (use_session_key) - DesfireCryptoEncDecSingleBlock(ctx->sessionKeyMAC, ctx->keyType, srcdata + offset, data + offset, xiv, encode, encode); + DesfireCryptoEncDecSingleBlock(ctx->sessionKeyMAC, ctx->keyType, srcdata + offset, data + offset, xiv, encode, xencode); else - DesfireCryptoEncDecSingleBlock(ctx->key, ctx->keyType, srcdata + offset, data + offset, xiv, encode, encode); + DesfireCryptoEncDecSingleBlock(ctx->key, ctx->keyType, srcdata + offset, data + offset, xiv, encode, xencode); offset += block_size; } diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 607a42f25..4104b32ef 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -46,6 +46,7 @@ AllowedChannelModesS AllowedChannelModes[] = { {MFDES_COMMIT_READER_ID, DACd40, DCCNative, DCMMACed}, {MFDES_GET_UID, DACd40, DCCNative, DCMEncrypted}, + {MFDES_CHANGE_KEY_SETTINGS, DACd40, DCCNative, DCMEncrypted}, {MFDES_READ_DATA, DACd40, DCCNative, DCMEncrypted}, {MFDES_WRITE_DATA, DACd40, DCCNative, DCMEncrypted}, @@ -56,6 +57,7 @@ AllowedChannelModesS AllowedChannelModes[] = { {MFDES_GET_KEY_SETTINGS, DACEV1, DCCNative, DCMMACed}, {MFDES_GET_UID, DACEV1, DCCNative, DCMEncrypted}, + {MFDES_CHANGE_KEY_SETTINGS, DACEV1, DCCNative, DCMEncrypted}, }; static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { @@ -74,10 +76,9 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint if (srcdatalen == 0) break; - rlen = padded_data_length(srcdatalen, desfire_get_key_block_length(ctx->keyType)); + rlen = srcdatalen + DesfireGetMACLength(ctx); memcpy(data, srcdata, srcdatalen); - memset(ctx->IV, 0, sizeof(ctx->IV)); - DesfireCryptoEncDec(ctx, true, data, rlen, NULL, true); + DesfireCryptoEncDec(ctx, true, data, srcdatalen, NULL, true); memcpy(dstdata, srcdata, srcdatalen); memcpy(&dstdata[srcdatalen], ctx->IV, 4); *dstdatalen = rlen; @@ -89,7 +90,6 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint rlen = padded_data_length(srcdatalen + 2, desfire_get_key_block_length(ctx->keyType)); // 2 - crc16 memcpy(data, srcdata, srcdatalen); compute_crc(CRC_14443_A, data, srcdatalen, &data[srcdatalen], &data[srcdatalen + 1]); - memset(ctx->IV, 0, sizeof(ctx->IV)); DesfireCryptoEncDec(ctx, true, data, rlen, dstdata, true); *dstdatalen = rlen; break; @@ -100,7 +100,8 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { uint8_t data[1024] = {0}; - + size_t rlen = 0; + // we calc MAC anyway // if encypted channel and no data - we only calc MAC if (ctx->commMode == DCMPlain || ctx->commMode == DCMMACed || (ctx->commMode == DCMEncrypted && srcdatalen == 0)) { @@ -110,14 +111,19 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint DesfireCryptoCMAC(ctx, data, srcdatalen + 1, cmac); memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; if (srcdatalen != 0 && ctx->commMode == DCMMACed) { memcpy(&dstdata[srcdatalen], cmac, DesfireGetMACLength(ctx)); *dstdatalen = srcdatalen + DesfireGetMACLength(ctx); } } else if (ctx->commMode == DCMEncrypted) { - - - + rlen = padded_data_length(srcdatalen + 4, desfire_get_key_block_length(ctx->keyType)); + memcpy(data, srcdata, srcdatalen); + desfire_crc32_append(data, srcdatalen); + PrintAndLogEx(INFO, "decoded[%d]: %s", rlen, sprint_hex(data, rlen)); + DesfireCryptoEncDec(ctx, true, data, rlen, dstdata, true); + + *dstdatalen = rlen; } else { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; From cc3883a770c9597e155dd80a64a06820727f9534 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 11 Jul 2021 18:27:29 +0300 Subject: [PATCH 263/309] ev1/enc tx side works --- client/src/mifare/desfiresecurechan.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 4104b32ef..a56af3493 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -118,10 +118,11 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint } } else if (ctx->commMode == DCMEncrypted) { rlen = padded_data_length(srcdatalen + 4, desfire_get_key_block_length(ctx->keyType)); - memcpy(data, srcdata, srcdatalen); - desfire_crc32_append(data, srcdatalen); - PrintAndLogEx(INFO, "decoded[%d]: %s", rlen, sprint_hex(data, rlen)); - DesfireCryptoEncDec(ctx, true, data, rlen, dstdata, true); + data[0] = cmd; + memcpy(&data[1], srcdata, srcdatalen); + desfire_crc32_append(data, srcdatalen + 1); + + DesfireCryptoEncDec(ctx, true, &data[1], rlen, dstdata, true); *dstdatalen = rlen; } else { From e4bdecf30ecaff4581bad90df274544fbf59579d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 11 Jul 2021 18:57:44 +0300 Subject: [PATCH 264/309] style --- client/src/mifare/desfirecore.c | 30 ++++++++++++------------- client/src/mifare/desfiresecurechan.c | 32 +++++++++++++-------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 29454e018..26c21494f 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -523,7 +523,7 @@ static void DesfireSplitBytesToBlock(uint8_t *blockdata, size_t *blockdatacount, int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { int res = PM3_SUCCESS; - + if (!PrintChannelModeWarning(cmd, ctx->secureChannel, ctx->cmdSet, ctx->commMode)) DesfirePrintContext(ctx); @@ -964,19 +964,19 @@ int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len) { } static void PrintKeyType(uint8_t keytype) { - switch(keytype) { - case 00: - PrintAndLogEx(SUCCESS, "Key: 2TDEA"); - break; - case 01: - PrintAndLogEx(SUCCESS, "Key: 3TDEA"); - break; - case 02: - PrintAndLogEx(SUCCESS, "Key: AES"); - break; - default: - PrintAndLogEx(SUCCESS, "Key: unknown: 0x%02x", keytype); - break; + switch (keytype) { + case 00: + PrintAndLogEx(SUCCESS, "Key: 2TDEA"); + break; + case 01: + PrintAndLogEx(SUCCESS, "Key: 3TDEA"); + break; + case 02: + PrintAndLogEx(SUCCESS, "Key: AES"); + break; + default: + PrintAndLogEx(SUCCESS, "Key: unknown: 0x%02x", keytype); + break; } } @@ -1014,7 +1014,7 @@ static void PrintKeySettingsApp(uint8_t keysettings, uint8_t numkeys, bool print ); break; } - + PrintAndLogEx(SUCCESS, "[%c...] AMK Configuration changeable : %s", (keysettings & (1 << 3)) ? '1' : '0', (keysettings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)"); PrintAndLogEx(SUCCESS, "[.%c..] AMK required for create/delete : %s", (keysettings & (1 << 2)) ? '1' : '0', (keysettings & (1 << 2)) ? "NO" : "YES"); PrintAndLogEx(SUCCESS, "[..%c.] Directory list access with AMK : %s", (keysettings & (1 << 1)) ? '1' : '0', (keysettings & (1 << 1)) ? "NO" : "YES"); diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index a56af3493..ce24b22d2 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -101,7 +101,7 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { uint8_t data[1024] = {0}; size_t rlen = 0; - + // we calc MAC anyway // if encypted channel and no data - we only calc MAC if (ctx->commMode == DCMPlain || ctx->commMode == DCMMACed || (ctx->commMode == DCMEncrypted && srcdatalen == 0)) { @@ -121,9 +121,9 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint data[0] = cmd; memcpy(&data[1], srcdata, srcdatalen); desfire_crc32_append(data, srcdatalen + 1); - + DesfireCryptoEncDec(ctx, true, &data[1], rlen, dstdata, true); - + *dstdatalen = rlen; } else { memcpy(dstdata, srcdata, srcdatalen); @@ -256,38 +256,38 @@ bool PrintChannelModeWarning(uint8_t cmd, DesfireSecureChannel secureChannel, De PrintAndLogEx(WARNING, "Communication mode can't be NONE. command: %02x", cmd); return false; } - + // no security set if (secureChannel == DACNone) return true; - + bool found = false; for (int i = 0; i < ARRAY_LENGTH(AllowedChannelModes); i++) if (AllowedChannelModes[i].cmd == cmd) { // full compare - if (AllowedChannelModes[i].secureChannel == secureChannel && - (AllowedChannelModes[i].cmdSet == cmdSet || (AllowedChannelModes[i].cmdSet == DCCNative && cmdSet == DCCNativeISO)) && - AllowedChannelModes[i].commMode == commMode){ + if (AllowedChannelModes[i].secureChannel == secureChannel && + (AllowedChannelModes[i].cmdSet == cmdSet || (AllowedChannelModes[i].cmdSet == DCCNative && cmdSet == DCCNativeISO)) && + AllowedChannelModes[i].commMode == commMode) { found = true; break; } - + // ev1 plain and mac are the same - if (AllowedChannelModes[i].secureChannel == secureChannel && - AllowedChannelModes[i].secureChannel == DACEV1 && - (AllowedChannelModes[i].cmdSet == cmdSet || (AllowedChannelModes[i].cmdSet == DCCNative && cmdSet == DCCNativeISO)) && - (commMode == DCMPlain || commMode == DCMMACed)){ + if (AllowedChannelModes[i].secureChannel == secureChannel && + AllowedChannelModes[i].secureChannel == DACEV1 && + (AllowedChannelModes[i].cmdSet == cmdSet || (AllowedChannelModes[i].cmdSet == DCCNative && cmdSet == DCCNativeISO)) && + (commMode == DCMPlain || commMode == DCMMACed)) { found = true; break; } - + } - + if (!found) PrintAndLogEx(WARNING, "Wrong communication mode. Check settings. command: %02x", cmd); - + return found; } From 88e573d0720cab89cdc4e22c4fc6b336d6803b86 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 11 Jul 2021 18:58:26 +0300 Subject: [PATCH 265/309] add default channel settings to commands --- client/src/cmdhfmfdes.c | 49 +++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 88152b932..679619d10 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5016,6 +5016,7 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct uint8_t cmodeid, uint8_t ccsetid, uint8_t schannid, uint8_t appid, int *securechannel, + DesfireCommunicationMode defcommmode, uint32_t *aid) { uint8_t keynum = defaultKeyNum; @@ -5027,10 +5028,10 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct uint8_t kdfInput[50] = {0}; memcpy(kdfInput, defaultKdfInput, defaultKdfInputLen); int commmode = defaultCommMode; + if (defcommmode != DCMNone) + commmode = defcommmode; int commset = defaultCommSet; int secchann = defaultSecureChannel; - if (securechannel) - secchann = *securechannel; if (keynoid) { keynum = arg_get_int_def(ctx, keynoid, keynum); @@ -5081,11 +5082,11 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct } if (schannid) { - + if (CLIGetOptionList(arg_get_str(ctx, schannid), DesfireSecureChannelOpts, &secchann)) return PM3_ESOFT; } - + if (appid && aid) { *aid = 0x000000; int res = arg_get_u32_hexstr_def_nlen(ctx, appid, 0x000000, aid, 3, true); @@ -5129,7 +5130,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, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 1, 2, 3, 4, 5, 6, 7, 8, 0, &securechann, DCMNone, NULL); if (res) { CLIParserFree(ctx); return res; @@ -5190,9 +5191,9 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { bool verbose = arg_get_lit(ctx, 2); DesfireContext dctx; - int securechann = DCMEncrypted; + int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMEncrypted, &appid); if (res) { CLIParserFree(ctx); return res; @@ -5211,9 +5212,9 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { CLIParserFree(ctx); if (verbose) { - DesfirePrintContext(&dctx); - PrintAndLogEx(SUCCESS, "\nNew key settings:"); - PrintKeySettings(ksett32, 0, (appid != 0x000000), false); + DesfirePrintContext(&dctx); + PrintAndLogEx(SUCCESS, "\nNew key settings:"); + PrintKeySettings(ksett32, 0, (appid != 0x000000), false); } res = DesfireSelectAIDHex(&dctx, appid, false, 0); @@ -5246,7 +5247,7 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { } PrintAndLogEx(INFO, "Key settings " _GREEN_("changed")); - + return PM3_SUCCESS; } @@ -5272,15 +5273,15 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_param_end }; - CLIExecWithReturn(ctx, Cmd, argtable, false); + CLIExecWithReturn(ctx, Cmd, argtable, true); bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); DesfireContext dctx; - int securechann = DCMPlain; + int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); if (res) { CLIParserFree(ctx); return res; @@ -5322,10 +5323,10 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { DropField(); return PM3_ESOFT; } - + if (verbose) PrintAndLogEx(INFO, "DesfireGetKeySettings[%d]: %s", buflen, sprint_hex(buf, buflen)); - + if (buflen < 2) { PrintAndLogEx(ERR, "Command DesfireGetKeySettings returned wrong length: %d", buflen); DropField(); @@ -5342,7 +5343,7 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { PrintAndLogEx(INFO, "max keysize: %d", buf[4]); if (buflen > 5) PrintAndLogEx(INFO, "app key settings: 0x%02x", buf[5]); - + DropField(); return PM3_SUCCESS; } @@ -5367,14 +5368,14 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), arg_param_end }; - CLIExecWithReturn(ctx, Cmd, argtable, false); + CLIExecWithReturn(ctx, Cmd, argtable, true); bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); DesfireContext dctx; - int securechann = DCMPlain; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, NULL); + int securechann = defaultSecureChannel; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, DCMMACed, NULL); if (res) { CLIParserFree(ctx); return res; @@ -5393,7 +5394,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { return PM3_ESOFT; } - res = DesfireAuthenticate(&dctx, securechann); //DACd40 DACEV1 + res = DesfireAuthenticate(&dctx, securechann); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res); DropField(); @@ -5449,14 +5450,14 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), arg_param_end }; - CLIExecWithReturn(ctx, Cmd, argtable, false); + CLIExecWithReturn(ctx, Cmd, argtable, true); bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); DesfireContext dctx; - int securechann = DCMPlain; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, NULL); + int securechann = defaultSecureChannel; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, DCMMACed, NULL); if (res) { CLIParserFree(ctx); return res; From 33b48ae2056a1d9fbfc801994e614f8c8cb06899 Mon Sep 17 00:00:00 2001 From: scott4290 Date: Sun, 11 Jul 2021 16:17:51 -0400 Subject: [PATCH 266/309] Update flash.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding a suggested step to point the user in the right direction. [+] Loading usable ELF segments: [+] 0: V 0x00102000 P 0x00102000 (0x00040888->0x00040888) [R X] @0x94 [!!] 🚨 Error: PHDR is not contained in Flash [!!] 🚨 Firmware probably too big for your device [=] The flashing procedure failed, follow the suggested steps! [+] All done --- client/src/flash.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/flash.c b/client/src/flash.c index 2f5f037c3..6bca04d43 100644 --- a/client/src/flash.c +++ b/client/src/flash.c @@ -123,7 +123,8 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, if (paddr < FLASH_START || (paddr + filesz) > flash_end) { PrintAndLogEx(ERR, "Error: PHDR is not contained in Flash"); if ((paddr + filesz) > flash_end) { - PrintAndLogEx(ERR, "Firmware probably too big for your device"); + PrintAndLogEx(ERR, "Firmware is probably too big for your device"); + PrintAndLogEx(ERR, "See README.md for information on compiling for platforms with 256KB of flash memory"); } return PM3_EFILE; } From 30b70d135e74344c7b9982ac5d234746298acfc1 Mon Sep 17 00:00:00 2001 From: scott4290 Date: Mon, 12 Jul 2021 03:10:24 -0400 Subject: [PATCH 267/309] Update bt_manual_v10.md --- doc/bt_manual_v10.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/doc/bt_manual_v10.md b/doc/bt_manual_v10.md index bdc371250..ee8ab34bb 100644 --- a/doc/bt_manual_v10.md +++ b/doc/bt_manual_v10.md @@ -204,7 +204,24 @@ Discovery started [agent] Enter PIN code: 1234 [bluetooth]# quit ``` - +If bluetoothctl fails to pair without prompting you for a PIN code, use the remove command to remove it, turn off pairable, turn off scanning, and try the bluetoothctl commands above: +```[bluetooth]# pair aa:bb:cc:dd:ee:ff +Attempting to pair with aa:bb:cc:dd:ee:ff +Failed to pair: org.bluez.Error.ConnectionAttemptFailed +[bluetooth]# pair aa:bb:cc:dd:ee:ff +Attempting to pair with aa:bb:cc:dd:ee:ff +Failed to pair: org.bluez.Error.ConnectionAttemptFailed +[bluetooth]# remove aa:bb:cc:dd:ee:ff +[DEL] Device aa:bb:cc:dd:ee:ff aa-bb-cc-dd-ee-ff +Device has been removed +[bluetooth]# pairable off +Changing pairable off succeeded +[CHG] Controller 00:00:00:00:00:00 Pairable: no +[bluetooth]# scan off +[CHG] Controller 00:00:00:00:00:00 Discovering: no +Discovery stopped +``` + #### 5.2.2 Fast connection using dedicated USB Bluetooth adapter under Linux ^[Top](#top) From a0ec56cdc4790128c8cde2db88229bc1763cc27b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 11:15:50 +0300 Subject: [PATCH 268/309] 350557 --- client/src/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 679619d10..35ab81d60 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5504,7 +5504,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { if (buflen > 0) { PrintAndLogEx(INFO, "----------------------- " _CYAN_("File list") " -----------------------"); for (int i = 0; i < buflen; i++) - PrintAndLogEx(INFO, "AID: %06x ISO file id: %02x%02x ISO DF name[%" PRIu32 "]: %s", + PrintAndLogEx(INFO, "AID: %06x ISO file id: %02x%02x ISO DF name[%zu]: %s", DesfireAIDByteToUint(&buf[i * 24 + 1]), buf[i * 24 + 1 + 3], buf[i * 24 + 1 + 4], strlen((char *)&buf[i * 24 + 1 + 5]), From a3acb921c77f0ae60fb6cbd47e6aed26b22137a2 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 11:18:55 +0300 Subject: [PATCH 269/309] 350563 --- client/src/mifare/desfirecore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 26c21494f..ddcc513eb 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -225,7 +225,7 @@ void DesfirePrintContext(DesfireContext *ctx) { sprint_hex(ctx->sessionKeyMAC, desfire_get_key_length(ctx->keyType))); PrintAndLogEx(INFO, " ENC: %s", sprint_hex(ctx->sessionKeyEnc, desfire_get_key_length(ctx->keyType))); - PrintAndLogEx(INFO, " IV [%d]: %s", + PrintAndLogEx(INFO, " IV [%zu]: %s", desfire_get_key_block_length(ctx->keyType), sprint_hex(ctx->IV, desfire_get_key_block_length(ctx->keyType))); From 7cb089f11bfbe58587b30d2768b06748bfb91269 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 11:19:48 +0300 Subject: [PATCH 270/309] 350861 --- client/src/mifare/desfirecrypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index d3955f92d..11b29b9db 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -118,7 +118,7 @@ size_t DesfireSearchCRCPos(uint8_t *data, size_t datalen, uint8_t respcode, uint break; crcpos++; // crc may be 0x00000000 or 0x0000 if (crcpos < crclen) { - PrintAndLogEx(WARNING, "No space for crc. pos: %d", crcpos); + PrintAndLogEx(WARNING, "No space for crc. pos: %zu", crcpos); return 0; } From 72ef378cd150e39a43b5836ea91389efbe155d9f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 11:20:50 +0300 Subject: [PATCH 271/309] 350888 --- client/src/cmdhfmfdes.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 35ab81d60..2cec9fd90 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5205,6 +5205,7 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { return PM3_ESOFT; if (res == 2) { PrintAndLogEx(ERR, "Key settings must have 1 byte length"); + CLIParserFree(ctx); return PM3_EINVARG; } From 2d5cc6aec7c9eee5e227fcd853a64b956a686539 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 11:21:48 +0300 Subject: [PATCH 272/309] 350889 --- client/src/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 2cec9fd90..440cab4c1 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5326,7 +5326,7 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { } if (verbose) - PrintAndLogEx(INFO, "DesfireGetKeySettings[%d]: %s", buflen, sprint_hex(buf, buflen)); + PrintAndLogEx(INFO, "DesfireGetKeySettings[%zu]: %s", buflen, sprint_hex(buf, buflen)); if (buflen < 2) { PrintAndLogEx(ERR, "Command DesfireGetKeySettings returned wrong length: %d", buflen); From 55b6ff8e051a69fe677f84256e6c4cd19a6ccd8c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 17:53:17 +0300 Subject: [PATCH 273/309] make select-and-authenticate function --- client/src/cmdhfmfdes.c | 89 ++++++--------------------------- client/src/mifare/desfirecore.c | 26 ++++++++++ client/src/mifare/desfirecore.h | 1 + 3 files changed, 41 insertions(+), 75 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 440cab4c1..ef87ab36a 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5213,30 +5213,14 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { CLIParserFree(ctx); if (verbose) { - DesfirePrintContext(&dctx); PrintAndLogEx(SUCCESS, "\nNew key settings:"); PrintKeySettings(ksett32, 0, (appid != 0x000000), false); } - res = DesfireSelectAIDHex(&dctx, appid, false, 0); + res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); DropField(); - return PM3_ESOFT; - } - - res = DesfireAuthenticate(&dctx, securechann); - if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res); - DropField(); - return PM3_ESOFT; - } - - if (DesfireIsAuthenticated(&dctx)) { - if (verbose) - PrintAndLogEx(INFO, "Desfire " _GREEN_("authenticated")); - } else { - return PM3_ESOFT; + return res; } uint8_t keysett = ksett32 & 0x0f; @@ -5252,6 +5236,11 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHF14ADesGetKeyVersions(const char *Cmd) { + + return PM3_SUCCESS; +} + static int CmdHF14ADesGetKeySettings(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes getkeysetings", @@ -5291,28 +5280,10 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - if (verbose) - DesfirePrintContext(&dctx); - - res = DesfireSelectAIDHex(&dctx, appid, false, 0); + res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); DropField(); - return PM3_ESOFT; - } - - res = DesfireAuthenticate(&dctx, securechann); - if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res); - DropField(); - return PM3_ESOFT; - } - - if (DesfireIsAuthenticated(&dctx)) { - if (verbose) - PrintAndLogEx(INFO, "Desfire " _GREEN_("authenticated")); - } else { - return PM3_ESOFT; + return res; } uint8_t buf[APDU_RES_LEN] = {0}; @@ -5385,28 +5356,10 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - if (verbose) - DesfirePrintContext(&dctx); - - res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); + res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); DropField(); - return PM3_ESOFT; - } - - res = DesfireAuthenticate(&dctx, securechann); - if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res); - DropField(); - return PM3_ESOFT; - } - - if (DesfireIsAuthenticated(&dctx)) { - if (verbose) - PrintAndLogEx(INFO, "Desfire " _GREEN_("authenticated")); - } else { - return PM3_ESOFT; + return res; } uint8_t buf[APDU_RES_LEN] = {0}; @@ -5470,25 +5423,10 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { if (verbose) DesfirePrintContext(&dctx); - res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); + res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); DropField(); - return PM3_ESOFT; - } - - res = DesfireAuthenticate(&dctx, securechann); - if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res); - DropField(); - return PM3_ESOFT; - } - - if (DesfireIsAuthenticated(&dctx)) { - if (verbose) - PrintAndLogEx(INFO, "Desfire " _GREEN_("authenticated")); - } else { - return PM3_ESOFT; + return res; } uint8_t buf[APDU_RES_LEN] = {0}; @@ -5540,6 +5478,7 @@ static command_t CommandTable[] = { {"changekey", CmdHF14ADesChangeKey, IfPm3Iso14443a, "Change Key"}, {"chkeysetings", CmdHF14ADesChKeySettings, IfPm3Iso14443a, "[new]Change Key Settings"}, {"getkeysetings", CmdHF14ADesGetKeySettings, IfPm3Iso14443a, "[new]Get Key Settings"}, + {"getkeyversions", CmdHF14ADesGetKeyVersions, IfPm3Iso14443a, "[new]Get Key Versions"}, {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("Applications") " -------------------"}, {"bruteaid", CmdHF14ADesBruteApps, IfPm3Iso14443a, "Recover AIDs by bruteforce"}, {"createaid", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application ID"}, diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index ddcc513eb..6eedd5ad1 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -602,6 +602,32 @@ int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uin return DesfireSelectAID(ctx, data, (select_two) ? &data[3] : NULL); } +int DesfireSelectAndAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel, uint32_t aid, bool verbose) { + if (verbose) + DesfirePrintContext(dctx); + + int res = DesfireSelectAIDHex(dctx, aid, false, 0); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); + return PM3_ESOFT; + } + + res = DesfireAuthenticate(dctx, secureChannel); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res); + return PM3_ESOFT; + } + + if (DesfireIsAuthenticated(dctx)) { + if (verbose) + PrintAndLogEx(INFO, "Desfire " _GREEN_("authenticated")); + } else { + return PM3_ESOFT; + } + + return PM3_SUCCESS; +} + int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel) { // 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 bdabc11fd..9a31a53e9 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -37,6 +37,7 @@ int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uin int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2); int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2); +int DesfireSelectAndAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel, uint32_t aid, bool verbose); int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel); int DesfireGetUID(DesfireContext *dctx, uint8_t *resp, size_t *resplen); From 9c320dc24151dcfbafb92d660b3ffa249040431f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 18:45:59 +0300 Subject: [PATCH 274/309] getkeyversion works --- client/src/cmdhfmfdes.c | 105 +++++++++++++++++++++++++- client/src/mifare/desfirecore.c | 4 +- client/src/mifare/desfirecore.h | 2 +- client/src/mifare/desfiresecurechan.c | 3 + 4 files changed, 110 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index ef87ab36a..4a760daeb 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5201,8 +5201,10 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { uint32_t ksett32 = 0; res = arg_get_u32_hexstr_def_nlen(ctx, 12, 0x000000, &ksett32, 1, false); - if (res == 0) + if (res == 0) { + CLIParserFree(ctx); return PM3_ESOFT; + } if (res == 2) { PrintAndLogEx(ERR, "Key settings must have 1 byte length"); CLIParserFree(ctx); @@ -5237,6 +5239,107 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { } static int CmdHF14ADesGetKeyVersions(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes getkeyversions", + "Get key versions for card level or application level.", + "hf mfdes getkeyversions -> get picc key settings with default key/channel setup\n"\ + "hf mfdes getkeyversions --aid 123456 -> get app 123456 key settings with default key/channel setup"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "apdu", "show APDU requests and responses"), + arg_lit0("v", "verbose", "show technical data"), + arg_int0("n", "keyno", "", "Key number for authentication"), + arg_str0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), + arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None, AN10922, Gallagher"), + 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(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), + arg_str0(NULL, "keynum", "", "Key number (HEX 1 byte). App level: 00..0d - key num, 21..23 vc keys. PICC level: key number, default 0x00."), + arg_str0(NULL, "keyset", "", "Keyset number (HEX 1 byte)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool APDULogging = arg_get_lit(ctx, 1); + bool verbose = arg_get_lit(ctx, 2); + + 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); // DCMMACed + if (res) { + CLIParserFree(ctx); + return res; + } + + uint32_t keynum32 = 0x00; + res = arg_get_u32_hexstr_def_nlen(ctx, 12, 0x00, &keynum32, 1, false); + if (res == 0) { + keynum32 = 0x00; + } + if (res == 2) { + PrintAndLogEx(ERR, "Key number must have 1 byte length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + uint32_t keysetnum32 = 0x00; + bool keysetpresent = true; + res = arg_get_u32_hexstr_def_nlen(ctx, 13, 0x00, &keysetnum32, 1, false); + if (res == 0) { + keysetpresent = false; + } + if (res == 2) { + PrintAndLogEx(ERR, "Keyset number must have 1 byte length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + if (keysetpresent && appid == 0x000000) { + PrintAndLogEx(WARNING, "Keyset only at Application level"); + keysetpresent = false; + } + + SetAPDULogging(APDULogging); + CLIParserFree(ctx); + + res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } + + uint8_t buf[APDU_RES_LEN] = {0}; + size_t buflen = 0; + + uint8_t data[2] = {0}; + data[0] = keynum32 & 0xff; + if (keysetpresent) { + data[0] |= 0x40; + data[1] = keysetnum32 & 0xff; + } + + res = DesfireGetKeyVersion(&dctx, data, (keysetpresent) ? 2 : 1, buf, &buflen); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire DesfireGetKeyVersion command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + if (verbose) + PrintAndLogEx(INFO, "DesfireGetKeyVersion[%zu]: %s", buflen, sprint_hex(buf, buflen)); + + if (buflen > 0) { + PrintAndLogEx(INFO, "----------------------- " _CYAN_("Key Versions") " -----------------------"); + for (int i = 0; i < buflen; i++) + PrintAndLogEx(INFO, "Key 0x%02x version 0x%02x", i, buf[i]); + } else { + PrintAndLogEx(INFO, "No key versions returned."); + } return PM3_SUCCESS; } diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 6eedd5ad1..e797d78b0 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -967,9 +967,9 @@ int DesfireGetKeySettings(DesfireContext *dctx, uint8_t *resp, size_t *resplen) return PM3_SUCCESS; } -int DesfireGetKeyVersion(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { +int DesfireGetKeyVersion(DesfireContext *dctx, uint8_t *data, size_t len, uint8_t *resp, size_t *resplen) { uint8_t respcode = 0xff; - int res = DesfireExchange(dctx, MFDES_GET_KEY_VERSION, NULL, 0, &respcode, resp, resplen); + int res = DesfireExchange(dctx, MFDES_GET_KEY_VERSION, data, len, &respcode, resp, resplen); if (res != PM3_SUCCESS) return res; if (respcode != MFDES_S_OPERATION_OK) diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 9a31a53e9..4fd55909c 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -47,7 +47,7 @@ int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireCreateApplication(DesfireContext *dctx, uint8_t *appdata, size_t appdatalen); int DesfireDeleteApplication(DesfireContext *dctx, uint32_t aid); -int DesfireGetKeyVersion(DesfireContext *dctx, uint8_t *resp, size_t *resplen); +int DesfireGetKeyVersion(DesfireContext *dctx, uint8_t *data, size_t len, uint8_t *resp, size_t *resplen); int DesfireGetKeySettings(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len); void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel, bool print2ndbyte); diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index ce24b22d2..c60ef1bb6 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -29,6 +29,7 @@ AllowedChannelModesS AllowedChannelModes[] = { {MFDES_GET_APPLICATION_IDS, DACd40, DCCNative, DCMPlain}, {MFDES_GET_DF_NAMES, DACd40, DCCNative, DCMPlain}, {MFDES_GET_KEY_SETTINGS, DACd40, DCCNative, DCMPlain}, + {MFDES_GET_KEY_VERSION, DACd40, DCCNative, DCMPlain}, {MFDES_READ_DATA, DACd40, DCCNative, DCMMACed}, {MFDES_WRITE_DATA, DACd40, DCCNative, DCMMACed}, @@ -50,6 +51,8 @@ AllowedChannelModesS AllowedChannelModes[] = { {MFDES_READ_DATA, DACd40, DCCNative, DCMEncrypted}, {MFDES_WRITE_DATA, DACd40, DCCNative, DCMEncrypted}, + {MFDES_GET_KEY_VERSION, DACEV1, DCCNative, DCMPlain}, + {MFDES_CREATE_APPLICATION, DACEV1, DCCNative, DCMMACed}, {MFDES_DELETE_APPLICATION, DACEV1, DCCNative, DCMMACed}, {MFDES_GET_APPLICATION_IDS, DACEV1, DCCNative, DCMMACed}, From 81740b3494b2ebca59abd560ae2a94f005ca929a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 18:47:26 +0300 Subject: [PATCH 275/309] cov 350889 --- client/src/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 4a760daeb..c7a57c060 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5403,7 +5403,7 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { PrintAndLogEx(INFO, "DesfireGetKeySettings[%zu]: %s", buflen, sprint_hex(buf, buflen)); if (buflen < 2) { - PrintAndLogEx(ERR, "Command DesfireGetKeySettings returned wrong length: %d", buflen); + PrintAndLogEx(ERR, "Command DesfireGetKeySettings returned wrong length: %zu", buflen); DropField(); return PM3_ESOFT; } From 10409c3fdc44f8490b625b73a82d51cb3a725640 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 18:56:30 +0300 Subject: [PATCH 276/309] help 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 c7a57c060..ac1c2b0b7 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5242,8 +5242,9 @@ static int CmdHF14ADesGetKeyVersions(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes getkeyversions", "Get key versions for card level or application level.", - "hf mfdes getkeyversions -> get picc key settings with default key/channel setup\n"\ - "hf mfdes getkeyversions --aid 123456 -> get app 123456 key settings with default key/channel setup"); + "--keynum parameter: App level: key number. PICC level: 00..0d - keys count, 21..23 vc keys, default 0x00.\n"\ + "hf mfdes getkeyversions --keynum 00 -> get picc master key version with default key/channel setup\n"\ + "hf mfdes getkeyversions --aid 123456 --keynum 0d -> get app 123456 all key versions with default key/channel setup"); void *argtable[] = { arg_param_begin, @@ -5258,7 +5259,7 @@ static int CmdHF14ADesGetKeyVersions(const char *Cmd) { arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), - arg_str0(NULL, "keynum", "", "Key number (HEX 1 byte). App level: 00..0d - key num, 21..23 vc keys. PICC level: key number, default 0x00."), + arg_str0(NULL, "keynum", "", "Key number/count (HEX 1 byte). Default 0x00."), arg_str0(NULL, "keyset", "", "Keyset number (HEX 1 byte)"), arg_param_end }; From 5bca74e5c8a278eeb185878b76e269d217c39308 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 19:12:47 +0300 Subject: [PATCH 277/309] DropField --- client/src/cmdhfmfdes.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index ac1c2b0b7..a91d65874 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5235,6 +5235,7 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { PrintAndLogEx(INFO, "Key settings " _GREEN_("changed")); + DropField(); return PM3_SUCCESS; } @@ -5342,6 +5343,7 @@ static int CmdHF14ADesGetKeyVersions(const char *Cmd) { PrintAndLogEx(INFO, "No key versions returned."); } + DropField(); return PM3_SUCCESS; } From 7bff67dceb31d82e793f094a251973112e235be9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 19:27:24 +0300 Subject: [PATCH 278/309] new getuid works --- client/src/cmdhfmfdes.c | 64 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index a91d65874..631efd884 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1518,6 +1518,7 @@ static int handler_desfire_getkeysettings(uint8_t *key_settings, uint8_t *num_ke return res; } +/* static int handler_desfire_getuid(uint8_t *uid) { if (uid == NULL) { PrintAndLogEx(DEBUG, "UID=NULL"); @@ -1552,6 +1553,7 @@ static int handler_desfire_getuid(uint8_t *uid) { return res; } +*/ static int handler_desfire_commit_transaction(void) { sAPDU apdu = {0x90, MFDES_COMMIT_TRANSACTION, 0x00, 0x00, 0x00, NULL}; //0xC7 @@ -2310,6 +2312,7 @@ static int desfire_authenticate(int cmdAuthMode, int cmdAuthAlgo, uint8_t *aid, return error; } +/* static int CmdHF14ADesGetUID(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes getuid", @@ -2352,6 +2355,7 @@ static int CmdHF14ADesGetUID(const char *Cmd) { PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(uid, uidlen)); return res; } +*/ static int CmdHF14ADesSelectApp(const char *Cmd) { CLIParserContext *ctx; @@ -5162,6 +5166,64 @@ static int CmdHF14ADesDefault(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHF14ADesGetUID(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes getaids", + "Get Application IDs list from card. Master key needs to be provided.", + "hf mfdes getaids -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "apdu", "show APDU requests and responses"), + arg_lit0("v", "verbose", "show technical data"), + arg_int0("n", "keyno", "", "Key number"), + arg_str0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), + arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None, AN10922, Gallagher"), + 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_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool APDULogging = arg_get_lit(ctx, 1); + bool verbose = arg_get_lit(ctx, 2); + + DesfireContext dctx; + int securechann = defaultSecureChannel; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, DCMEncrypted, NULL); + if (res) { + CLIParserFree(ctx); + return res; + } + + SetAPDULogging(APDULogging); + CLIParserFree(ctx); + + res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } + + uint8_t buf[APDU_RES_LEN] = {0}; + size_t buflen = 0; + + res = DesfireGetUID(&dctx, buf, &buflen); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire DesfireGetUID command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + PrintAndLogEx(SUCCESS, "Desfire UID[%d]: %s", buflen, sprint_hex(buf, buflen)); + + DropField(); + return PM3_SUCCESS; +} + static int CmdHF14ADesChKeySettings(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes chkeysetings", @@ -5575,7 +5637,7 @@ static command_t CommandTable[] = { {"chk", CmdHF14aDesChk, IfPm3Iso14443a, "Check keys"}, {"enum", CmdHF14ADesEnumApplications, IfPm3Iso14443a, "Tries enumerate all applications"}, {"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "Format PICC"}, - {"getuid", CmdHF14ADesGetUID, IfPm3Iso14443a, "Get random uid"}, + {"getuid", CmdHF14ADesGetUID, IfPm3Iso14443a, "[new]Get uid from card"}, {"info", CmdHF14ADesInfo, IfPm3Iso14443a, "Tag information"}, {"list", CmdHF14ADesList, AlwaysAvailable, "List DESFire (ISO 14443A) history"}, // {"ndefread", CmdHF14aDesNDEFRead, IfPm3Iso14443a, "Prints NDEF records from card"}, From 90fe298b3313b1c7f8ad426fbd201ccb14b7c21f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 19:28:29 +0300 Subject: [PATCH 279/309] remove todo that is done --- client/src/cmdhfmfdes.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 631efd884..b6812c282 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5686,10 +5686,7 @@ int CmdHFMFDes(const char *Cmd) { Native Cmds ----------- - ChangeKeySettings 0x5F SetConfiguration - GetISOFileIDs - GetCardUID ChangeFileSettings ISO/IEC 7816 Cmds From 6f66a97cb358ae617c1e867fc463fd37dc7bcf8d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 21:50:02 +0300 Subject: [PATCH 280/309] help text --- client/src/cmdhfmfdes.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index b6812c282..64ce354b3 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5168,10 +5168,10 @@ static int CmdHF14ADesDefault(const char *Cmd) { static int CmdHF14ADesGetUID(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes getaids", - "Get Application IDs list from card. Master key needs to be provided.", - "hf mfdes getaids -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup"); - + CLIParserInit(&ctx, "hf mfdes getuid", + "Get UID from card. Get the real UID if the random UID bit is on and get the same UID as in anticollision if not. Master key needs to be provided. ", + "hf mfdes getuid -> execute with default factory setup"); + void *argtable[] = { arg_param_begin, arg_lit0("a", "apdu", "show APDU requests and responses"), From e03501bc8606a4a8f828db078fe50f8ebb55cc77 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 22:38:25 +0300 Subject: [PATCH 281/309] formatpicc command --- client/src/mifare/desfirecore.c | 12 ++++++++++++ client/src/mifare/desfirecore.h | 1 + 2 files changed, 13 insertions(+) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index e797d78b0..778d48d9d 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -901,6 +901,18 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel return PM3_SUCCESS; } +int DesfireFormatPICC(DesfireContext *dctx) { + uint8_t respcode = 0xff; + uint8_t resp[257] = {0}; + size_t resplen = 0; + int res = DesfireExchange(dctx, MFDES_GET_UID, NULL, 0, &respcode, resp, &resplen); + if (res != PM3_SUCCESS) + return res; + if (respcode != MFDES_S_OPERATION_OK || resplen != 0) + return PM3_EAPDU_FAIL; + return PM3_SUCCESS; +} + int DesfireGetUID(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { uint8_t respcode = 0xff; int res = DesfireExchange(dctx, MFDES_GET_UID, NULL, 0, &respcode, resp, resplen); diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 4fd55909c..0da4fcbfe 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -40,6 +40,7 @@ int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uin int DesfireSelectAndAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel, uint32_t aid, bool verbose); int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel); +int DesfireFormatPICC(DesfireContext *dctx); int DesfireGetUID(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); From 9c63d09179f6fa68621ffade55ee3b50b29fac4b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 22:40:22 +0300 Subject: [PATCH 282/309] cmdcode --- client/src/mifare/desfirecore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 778d48d9d..608059882 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -905,7 +905,7 @@ int DesfireFormatPICC(DesfireContext *dctx) { uint8_t respcode = 0xff; uint8_t resp[257] = {0}; size_t resplen = 0; - int res = DesfireExchange(dctx, MFDES_GET_UID, NULL, 0, &respcode, resp, &resplen); + int res = DesfireExchange(dctx, MFDES_FORMAT_PICC, NULL, 0, &respcode, resp, &resplen); if (res != PM3_SUCCESS) return res; if (respcode != MFDES_S_OPERATION_OK || resplen != 0) From 64422239378f5f4af0f0a7e86b47f961e2a29d72 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 22:46:55 +0300 Subject: [PATCH 283/309] getfreemem --- client/src/mifare/desfirecore.c | 14 ++++++++++++++ client/src/mifare/desfirecore.h | 1 + 2 files changed, 15 insertions(+) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 608059882..2e0654c30 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -913,6 +913,20 @@ int DesfireFormatPICC(DesfireContext *dctx) { return PM3_SUCCESS; } +int DesfireGetFreeMem(DesfireContext *dctx, uint32_t *freemem) { + *freemem = 0; + uint8_t respcode = 0xff; + uint8_t resp[257] = {0}; + size_t resplen = 0; + int res = DesfireExchange(dctx, MFDES_GET_FREE_MEMORY, NULL, 0, &respcode, resp, &resplen); + if (res != PM3_SUCCESS) + return res; + if (respcode != MFDES_S_OPERATION_OK || resplen != 3) + return PM3_EAPDU_FAIL; + *freemem = DesfireAIDByteToUint(resp); + return PM3_SUCCESS; +} + int DesfireGetUID(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { uint8_t respcode = 0xff; int res = DesfireExchange(dctx, MFDES_GET_UID, NULL, 0, &respcode, resp, resplen); diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 0da4fcbfe..acc7bd7af 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -41,6 +41,7 @@ int DesfireSelectAndAuthenticate(DesfireContext *dctx, DesfireSecureChannel secu int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel); int DesfireFormatPICC(DesfireContext *dctx); +int DesfireGetFreeMem(DesfireContext *dctx, uint32_t *freemem); int DesfireGetUID(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); From cf96dc3acba32c87a331cdc4557307d40b78936d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 23:33:13 +0300 Subject: [PATCH 284/309] get free mem an format icc commands --- client/src/cmdhfmfdes.c | 131 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 64ce354b3..d6d44b534 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -3442,7 +3442,7 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { DropFieldDesfire(); return res; } - +/* static int CmdHF14ADesFormatPICC(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes formatpicc", @@ -3467,7 +3467,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { } DropFieldDesfire(); return res; -} +}*/ static int CmdHF14ADesInfo(const char *Cmd) { CLIParserContext *ctx; @@ -5224,6 +5224,130 @@ static int CmdHF14ADesGetUID(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHF14ADesFormatPICC(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes formatpicc", + "Format card. Can be done only if enabled in the configuration. Master key needs to be provided. ", + "hf mfdes formatpicc -> execute with default factory setup"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "apdu", "show APDU requests and responses"), + arg_lit0("v", "verbose", "show technical data"), + arg_int0("n", "keyno", "", "Key number"), + arg_str0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), + arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None, AN10922, Gallagher"), + 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_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool APDULogging = arg_get_lit(ctx, 1); + bool verbose = arg_get_lit(ctx, 2); + + DesfireContext dctx; + int securechann = defaultSecureChannel; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, DCMMACed, NULL); + if (res) { + CLIParserFree(ctx); + return res; + } + + SetAPDULogging(APDULogging); + CLIParserFree(ctx); + + res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } + + res = DesfireFormatPICC(&dctx); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire DesfireFormatPICC command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + PrintAndLogEx(SUCCESS, "Desfire format: " _GREEN_("done")); + + DropField(); + return PM3_SUCCESS; +} + +static int CmdHF14ADesGetFreeMem(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes getfreemem", + "Get card's free memory. Can be doe with ot without authentication. Master key may be provided. ", + "hf mfdes getfreemem -> execute with default factory setup"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "apdu", "show APDU requests and responses"), + arg_lit0("v", "verbose", "show technical data"), + arg_int0("n", "keyno", "", "Key number"), + arg_str0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), + arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None, AN10922, Gallagher"), + 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_lit0(NULL, "no-auth", "execute without authentication"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool APDULogging = arg_get_lit(ctx, 1); + bool verbose = arg_get_lit(ctx, 2); + + bool noauth = arg_get_lit(ctx, 11); + + DesfireContext dctx; + int securechann = defaultSecureChannel; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, (noauth) ? DCMPlain : DCMMACed, NULL); + if (res) { + CLIParserFree(ctx); + return res; + } + + SetAPDULogging(APDULogging); + CLIParserFree(ctx); + + if (noauth) { + res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); + DropField(); + return res; + } + } else { + res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } + } + + uint32_t freemem = 0; + + res = DesfireGetFreeMem(&dctx, &freemem); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire DesfireGetFreeMem command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + PrintAndLogEx(SUCCESS, "Free memory 0x%06x, %d bytes", freemem, freemem); + + DropField(); + return PM3_SUCCESS; +} + static int CmdHF14ADesChKeySettings(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes chkeysetings", @@ -5636,7 +5760,8 @@ static command_t CommandTable[] = { {"auth", CmdHF14ADesAuth, IfPm3Iso14443a, "Tries a MIFARE DesFire Authentication"}, {"chk", CmdHF14aDesChk, IfPm3Iso14443a, "Check keys"}, {"enum", CmdHF14ADesEnumApplications, IfPm3Iso14443a, "Tries enumerate all applications"}, - {"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "Format PICC"}, + {"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "[new]Format PICC"}, + {"getfreemem", CmdHF14ADesGetFreeMem, IfPm3Iso14443a, "[new]Get free memory size"}, {"getuid", CmdHF14ADesGetUID, IfPm3Iso14443a, "[new]Get uid from card"}, {"info", CmdHF14ADesInfo, IfPm3Iso14443a, "Tag information"}, {"list", CmdHF14ADesList, AlwaysAvailable, "List DESFire (ISO 14443A) history"}, From 12969cf728f690d51e3e1a67e73b0c341942392d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 23:36:25 +0300 Subject: [PATCH 285/309] text --- client/src/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index d6d44b534..5a9e54f83 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5342,7 +5342,7 @@ static int CmdHF14ADesGetFreeMem(const char *Cmd) { return PM3_ESOFT; } - PrintAndLogEx(SUCCESS, "Free memory 0x%06x, %d bytes", freemem, freemem); + PrintAndLogEx(SUCCESS, "Free memory [0x%06x] %d bytes", freemem, freemem); DropField(); return PM3_SUCCESS; From 8e68dafa3aad0e5c89141f27235df817e6a96c4b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 23:53:38 +0300 Subject: [PATCH 286/309] freemem conditions --- client/src/mifare/desfiresecurechan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index c60ef1bb6..2e49ce5ac 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -30,6 +30,7 @@ AllowedChannelModesS AllowedChannelModes[] = { {MFDES_GET_DF_NAMES, DACd40, DCCNative, DCMPlain}, {MFDES_GET_KEY_SETTINGS, DACd40, DCCNative, DCMPlain}, {MFDES_GET_KEY_VERSION, DACd40, DCCNative, DCMPlain}, + {MFDES_GET_FREE_MEMORY, DACd40, DCCNative, DCMPlain}, {MFDES_READ_DATA, DACd40, DCCNative, DCMMACed}, {MFDES_WRITE_DATA, DACd40, DCCNative, DCMMACed}, @@ -52,6 +53,7 @@ AllowedChannelModesS AllowedChannelModes[] = { {MFDES_WRITE_DATA, DACd40, DCCNative, DCMEncrypted}, {MFDES_GET_KEY_VERSION, DACEV1, DCCNative, DCMPlain}, + {MFDES_GET_FREE_MEMORY, DACEV1, DCCNative, DCMPlain}, {MFDES_CREATE_APPLICATION, DACEV1, DCCNative, DCMMACed}, {MFDES_DELETE_APPLICATION, DACEV1, DCCNative, DCMMACed}, From d4646ce6d6956978722e2f4e72c60c8682e3831f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Jul 2021 23:53:57 +0300 Subject: [PATCH 287/309] add aid to formatpicc --- client/src/cmdhfmfdes.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 5a9e54f83..a3e02c779 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5242,6 +5242,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { 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(NULL, "aid", "", "Application ID of delegated application (3 hex bytes, big endian)"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -5251,7 +5252,8 @@ static int CmdHF14ADesFormatPICC(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); + uint32_t appid = 0x000000; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); if (res) { CLIParserFree(ctx); return res; @@ -5260,7 +5262,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); + res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose); if (res != PM3_SUCCESS) { DropField(); return res; @@ -5761,7 +5763,7 @@ static command_t CommandTable[] = { {"chk", CmdHF14aDesChk, IfPm3Iso14443a, "Check keys"}, {"enum", CmdHF14ADesEnumApplications, IfPm3Iso14443a, "Tries enumerate all applications"}, {"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "[new]Format PICC"}, - {"getfreemem", CmdHF14ADesGetFreeMem, IfPm3Iso14443a, "[new]Get free memory size"}, + {"freemem", CmdHF14ADesGetFreeMem, IfPm3Iso14443a, "[new]Get free memory size"}, {"getuid", CmdHF14ADesGetUID, IfPm3Iso14443a, "[new]Get uid from card"}, {"info", CmdHF14ADesInfo, IfPm3Iso14443a, "Tag information"}, {"list", CmdHF14ADesList, AlwaysAvailable, "List DESFire (ISO 14443A) history"}, From afbe5deda216e39c111dfa86f97c9c15c20ee729 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Jul 2021 00:59:07 +0300 Subject: [PATCH 288/309] commands refactoring --- client/src/mifare/desfirecore.c | 91 +++++++++++++++------------------ 1 file changed, 42 insertions(+), 49 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 2e0654c30..5a8a06745 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -901,60 +901,65 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel return PM3_SUCCESS; } -int DesfireFormatPICC(DesfireContext *dctx) { +static int DesfireCommand(DesfireContext *dctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, int checklength) { + if (resplen) + *resplen = 0; + uint8_t respcode = 0xff; - uint8_t resp[257] = {0}; - size_t resplen = 0; - int res = DesfireExchange(dctx, MFDES_FORMAT_PICC, NULL, 0, &respcode, resp, &resplen); + uint8_t xresp[257] = {0}; + size_t xresplen = 0; + int res = DesfireExchange(dctx, cmd, data, datalen, &respcode, xresp, &xresplen); if (res != PM3_SUCCESS) return res; - if (respcode != MFDES_S_OPERATION_OK || resplen != 0) + if (respcode != MFDES_S_OPERATION_OK) return PM3_EAPDU_FAIL; + if (checklength >= 0 && xresplen != checklength) + return PM3_EAPDU_FAIL; + + if (resplen) + *resplen = xresplen; + if (resp) + memcpy(resp, xresp, xresplen); return PM3_SUCCESS; } +static int DesfireCommandNoData(DesfireContext *dctx, uint8_t cmd) { + return DesfireCommand(dctx, cmd, NULL, 0, NULL, NULL, 0); +} +/* +static int DesfireCommandTxData(DesfireContext *dctx, uint8_t cmd, uint8_t *data, size_t datalen, int checklength) { + return DesfireCommand(dctx, cmd, data, 0, datalen, NULL, checklength); +} +*/ +static int DesfireCommandRxData(DesfireContext *dctx, uint8_t cmd, uint8_t *resp, size_t *resplen, int checklength) { + return DesfireCommand(dctx, cmd, NULL, 0, resp, resplen, checklength); +} + +int DesfireFormatPICC(DesfireContext *dctx) { + return DesfireCommandNoData(dctx, MFDES_FORMAT_PICC); +} + int DesfireGetFreeMem(DesfireContext *dctx, uint32_t *freemem) { *freemem = 0; - uint8_t respcode = 0xff; + uint8_t resp[257] = {0}; - size_t resplen = 0; - int res = DesfireExchange(dctx, MFDES_GET_FREE_MEMORY, NULL, 0, &respcode, resp, &resplen); - if (res != PM3_SUCCESS) - return res; - if (respcode != MFDES_S_OPERATION_OK || resplen != 3) - return PM3_EAPDU_FAIL; - *freemem = DesfireAIDByteToUint(resp); - return PM3_SUCCESS; + size_t resplen = 0; + int res = DesfireCommandRxData(dctx, MFDES_GET_FREE_MEMORY, resp, &resplen, 3); + if (res == PM3_SUCCESS) + *freemem = DesfireAIDByteToUint(resp); + return res; } int DesfireGetUID(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { - uint8_t respcode = 0xff; - int res = DesfireExchange(dctx, MFDES_GET_UID, NULL, 0, &respcode, resp, resplen); - if (res != PM3_SUCCESS) - return res; - if (respcode != MFDES_S_OPERATION_OK) - return PM3_EAPDU_FAIL; - return PM3_SUCCESS; + return DesfireCommandRxData(dctx, MFDES_GET_UID, resp, resplen, -1); } int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { - uint8_t respcode = 0xff; - int res = DesfireExchange(dctx, MFDES_GET_APPLICATION_IDS, NULL, 0, &respcode, resp, resplen); - if (res != PM3_SUCCESS) - return res; - if (respcode != MFDES_S_OPERATION_OK) - return PM3_EAPDU_FAIL; - return PM3_SUCCESS; + return DesfireCommandRxData(dctx, MFDES_GET_APPLICATION_IDS, resp, resplen, -1); } int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { - uint8_t respcode = 0xff; - int res = DesfireExchangeEx(false, dctx, MFDES_GET_DF_NAMES, NULL, 0, &respcode, resp, resplen, true, 24); - if (res != PM3_SUCCESS) - return res; - if (respcode != MFDES_S_OPERATION_OK) - return PM3_EAPDU_FAIL; - return PM3_SUCCESS; + return DesfireCommandRxData(dctx, MFDES_GET_DF_NAMES, resp, resplen, -1); } int DesfireCreateApplication(DesfireContext *dctx, uint8_t *appdata, size_t appdatalen) { @@ -984,23 +989,11 @@ int DesfireDeleteApplication(DesfireContext *dctx, uint32_t aid) { } int DesfireGetKeySettings(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { - uint8_t respcode = 0xff; - int res = DesfireExchange(dctx, MFDES_GET_KEY_SETTINGS, NULL, 0, &respcode, resp, resplen); - if (res != PM3_SUCCESS) - return res; - if (respcode != MFDES_S_OPERATION_OK) - return PM3_EAPDU_FAIL; - return PM3_SUCCESS; + return DesfireCommandRxData(dctx, MFDES_GET_KEY_SETTINGS, resp, resplen, -1); } int DesfireGetKeyVersion(DesfireContext *dctx, uint8_t *data, size_t len, uint8_t *resp, size_t *resplen) { - uint8_t respcode = 0xff; - int res = DesfireExchange(dctx, MFDES_GET_KEY_VERSION, data, len, &respcode, resp, resplen); - if (res != PM3_SUCCESS) - return res; - if (respcode != MFDES_S_OPERATION_OK) - return PM3_EAPDU_FAIL; - return PM3_SUCCESS; + return DesfireCommandRxData(dctx, MFDES_GET_KEY_VERSION, resp, resplen, -1); } int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len) { From 89e9897200d3071745038b2bda2a3e617feed65b Mon Sep 17 00:00:00 2001 From: TheArchitect0880 <78969377+TheArchitect0880@users.noreply.github.com> Date: Tue, 13 Jul 2021 00:04:02 +0200 Subject: [PATCH 289/309] Update cmdhf14a.c changed "hf emv" to "emv" since its not under hf commands anymore --- client/src/cmdhf14a.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index b471ed9fd..c19941ed6 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -174,8 +174,8 @@ static const hintAIDListT hintAIDList[] = { { "\xA0\x00\x00\x06\x47\x2F\x00\x01", 8, "FIDO", "hf fido" }, { "\xA0\x00\x00\x03\x08\x00\x00\x10\x00\x01\x00", 11, "PIV", "" }, { "\xD2\x76\x00\x01\x24\x01", 8, "OpenPGP", "" }, - { "\x31\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31", 14, "EMV (pse)", "hf emv" }, - { "\x32\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31", 14, "EMV (ppse)", "hf emv" }, + { "\x31\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31", 14, "EMV (pse)", "emv" }, + { "\x32\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31", 14, "EMV (ppse)", "emv" }, { "\x41\x44\x20\x46\x31", 5, "CIPURSE", "hf cipurse" }, { "\xd2\x76\x00\x00\x85\x01\x00", 7, "desfire", "hf mfdes" }, }; From 55f9a0b6921040cfe06bbefa04421c444aef0207 Mon Sep 17 00:00:00 2001 From: scott4290 Date: Tue, 13 Jul 2021 00:35:43 -0400 Subject: [PATCH 290/309] Update bt_manual_v10.md I realized I can replace an entire troubleshooting stanza with a preemptive remove command in the original instructions. [bluetooth]# remove aa:bb:cc:dd:ee:ff Pull if you think this is a cleaner approach. Either is good with me. --- doc/bt_manual_v10.md | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/doc/bt_manual_v10.md b/doc/bt_manual_v10.md index ee8ab34bb..bf9fc0fdb 100644 --- a/doc/bt_manual_v10.md +++ b/doc/bt_manual_v10.md @@ -190,10 +190,11 @@ The first time, your OS will ask you for pairing. The default PIN is 1234. If PIN is not typed in quickly, the client might timeout. Simply restart it again after pairing. -If your OS doesn't prompt you for pairing, you can do it in command line, e.g. (again, replace with your addon MAC address): +If your OS doesn't prompt you for pairing or if the device connects and immediately disconnects, you can pair it in command line, e.g. (again, replace with your addon MAC address): ```sh bluetoothctl +[bluetooth]# remove aa:bb:cc:dd:ee:ff [bluetooth]# pairable on [bluetooth]# scan on Discovery started @@ -204,24 +205,7 @@ Discovery started [agent] Enter PIN code: 1234 [bluetooth]# quit ``` -If bluetoothctl fails to pair without prompting you for a PIN code, use the remove command to remove it, turn off pairable, turn off scanning, and try the bluetoothctl commands above: -```[bluetooth]# pair aa:bb:cc:dd:ee:ff -Attempting to pair with aa:bb:cc:dd:ee:ff -Failed to pair: org.bluez.Error.ConnectionAttemptFailed -[bluetooth]# pair aa:bb:cc:dd:ee:ff -Attempting to pair with aa:bb:cc:dd:ee:ff -Failed to pair: org.bluez.Error.ConnectionAttemptFailed -[bluetooth]# remove aa:bb:cc:dd:ee:ff -[DEL] Device aa:bb:cc:dd:ee:ff aa-bb-cc-dd-ee-ff -Device has been removed -[bluetooth]# pairable off -Changing pairable off succeeded -[CHG] Controller 00:00:00:00:00:00 Pairable: no -[bluetooth]# scan off -[CHG] Controller 00:00:00:00:00:00 Discovering: no -Discovery stopped -``` - + #### 5.2.2 Fast connection using dedicated USB Bluetooth adapter under Linux ^[Top](#top) From 89450c2feed180bab37a605a0ec48a6e46007d1b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Jul 2021 11:56:12 +0300 Subject: [PATCH 291/309] commands refactoring --- client/src/mifare/desfirecore.c | 50 ++++++++++----------------------- 1 file changed, 15 insertions(+), 35 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 5a8a06745..f1328a568 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -901,14 +901,14 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel return PM3_SUCCESS; } -static int DesfireCommand(DesfireContext *dctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, int checklength) { +static int DesfireCommandEx(DesfireContext *dctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, int checklength, size_t splitbysize) { if (resplen) *resplen = 0; uint8_t respcode = 0xff; uint8_t xresp[257] = {0}; size_t xresplen = 0; - int res = DesfireExchange(dctx, cmd, data, datalen, &respcode, xresp, &xresplen); + int res = DesfireExchangeEx(false, dctx, cmd, data, datalen, &respcode, xresp, &xresplen, true, splitbysize); if (res != PM3_SUCCESS) return res; if (respcode != MFDES_S_OPERATION_OK) @@ -923,14 +923,18 @@ static int DesfireCommand(DesfireContext *dctx, uint8_t cmd, uint8_t *data, size return PM3_SUCCESS; } +static int DesfireCommand(DesfireContext *dctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, int checklength) { + return DesfireCommandEx(dctx, cmd, data, datalen, resp, resplen, checklength, 0); +} + static int DesfireCommandNoData(DesfireContext *dctx, uint8_t cmd) { return DesfireCommand(dctx, cmd, NULL, 0, NULL, NULL, 0); } -/* -static int DesfireCommandTxData(DesfireContext *dctx, uint8_t cmd, uint8_t *data, size_t datalen, int checklength) { - return DesfireCommand(dctx, cmd, data, 0, datalen, NULL, checklength); + +static int DesfireCommandTxData(DesfireContext *dctx, uint8_t cmd, uint8_t *data, size_t datalen) { + return DesfireCommand(dctx, cmd, data, datalen, NULL, NULL, 0); } -*/ + static int DesfireCommandRxData(DesfireContext *dctx, uint8_t cmd, uint8_t *resp, size_t *resplen, int checklength) { return DesfireCommand(dctx, cmd, NULL, 0, resp, resplen, checklength); } @@ -959,33 +963,17 @@ int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { } int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { - return DesfireCommandRxData(dctx, MFDES_GET_DF_NAMES, resp, resplen, -1); + return DesfireCommandEx(dctx, MFDES_GET_DF_NAMES, NULL, 0, resp, resplen, -1, 24); } int DesfireCreateApplication(DesfireContext *dctx, uint8_t *appdata, size_t appdatalen) { - uint8_t respcode = 0xff; - uint8_t resp[257] = {0}; - size_t resplen = 0; - int res = DesfireExchangeEx(false, dctx, MFDES_CREATE_APPLICATION, appdata, appdatalen, &respcode, resp, &resplen, true, 0); - if (res != PM3_SUCCESS) - return res; - if (respcode != MFDES_S_OPERATION_OK || resplen != 0) - return PM3_EAPDU_FAIL; - return PM3_SUCCESS; + return DesfireCommandTxData(dctx, MFDES_CREATE_APPLICATION, appdata, appdatalen); } int DesfireDeleteApplication(DesfireContext *dctx, uint32_t aid) { - uint8_t respcode = 0xff; uint8_t data[3] = {0}; DesfireAIDUintToByte(aid, data); - uint8_t resp[257] = {0}; - size_t resplen = 0; - int res = DesfireExchangeEx(false, dctx, MFDES_DELETE_APPLICATION, data, sizeof(data), &respcode, resp, &resplen, true, 0); - if (res != PM3_SUCCESS) - return res; - if (respcode != MFDES_S_OPERATION_OK || resplen != 0) - return PM3_EAPDU_FAIL; - return PM3_SUCCESS; + return DesfireCommandTxData(dctx, MFDES_DELETE_APPLICATION, data, sizeof(data)); } int DesfireGetKeySettings(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { @@ -993,19 +981,11 @@ int DesfireGetKeySettings(DesfireContext *dctx, uint8_t *resp, size_t *resplen) } int DesfireGetKeyVersion(DesfireContext *dctx, uint8_t *data, size_t len, uint8_t *resp, size_t *resplen) { - return DesfireCommandRxData(dctx, MFDES_GET_KEY_VERSION, resp, resplen, -1); + return DesfireCommand(dctx, MFDES_GET_KEY_VERSION, data, len, resp, resplen, -1); } int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len) { - uint8_t respcode = 0xff; - uint8_t resp[257] = {0}; - size_t resplen = 0; - int res = DesfireExchange(dctx, MFDES_CHANGE_KEY_SETTINGS, data, len, &respcode, resp, &resplen); - if (res != PM3_SUCCESS) - return res; - if (respcode != MFDES_S_OPERATION_OK || resplen != 0) - return PM3_EAPDU_FAIL; - return PM3_SUCCESS; + return DesfireCommandTxData(dctx, MFDES_CHANGE_KEY_SETTINGS, data, len); } static void PrintKeyType(uint8_t keytype) { From 3e86c15a33afd1086404c8028244b13cf8b52044 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Jul 2021 12:16:30 +0300 Subject: [PATCH 292/309] cov 351017 --- client/src/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index a3e02c779..609381ace 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5218,7 +5218,7 @@ static int CmdHF14ADesGetUID(const char *Cmd) { return PM3_ESOFT; } - PrintAndLogEx(SUCCESS, "Desfire UID[%d]: %s", buflen, sprint_hex(buf, buflen)); + PrintAndLogEx(SUCCESS, "Desfire UID[%zu]: %s", buflen, sprint_hex(buf, buflen)); DropField(); return PM3_SUCCESS; From 2505b17912df19dc27f5f79269f6ab53a7eaaa3d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Jul 2021 13:32:38 +0300 Subject: [PATCH 293/309] delete aid ok --- client/src/cmdhfmfdes.c | 75 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 6 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 609381ace..9ce75ae38 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1764,7 +1764,7 @@ static int handler_desfire_createapp(aidhdr_t *aidhdr, bool usename, bool usefid } return res; } - +/* static int handler_desfire_deleteapp(const uint8_t *aid) { if (aid == NULL) { return PM3_EINVARG; @@ -1778,7 +1778,7 @@ static int handler_desfire_deleteapp(const uint8_t *aid) { DropFieldDesfire(); } return res; -} +}*/ static int handler_desfire_credit(mfdes_value_t *value, uint8_t cs) { sAPDU apdu = {0x90, MFDES_CREDIT, 0x00, 0x00, 1 + 4, (uint8_t *)value}; // 0x0C @@ -2538,7 +2538,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { } return res; } - +/* static int CmdHF14ADesDeleteApp(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes deleteaid", @@ -2574,7 +2574,7 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) { PrintAndLogEx(SUCCESS, "Successfully deleted aid."); } return res; -} +}*/ static int selectfile(uint8_t *aid, uint8_t fileno, uint8_t *cs) { if (handler_desfire_select_application(aid) != PM3_SUCCESS) { @@ -5166,6 +5166,69 @@ static int CmdHF14ADesDefault(const char *Cmd) { return PM3_SUCCESS; } + +static int CmdHF14ADesDeleteApp(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes deleteaid", + "Delete application by its 3-byte AID. Master key needs to be provided. ", + "hf mfdes deleteaid --aid 123456 -> execute with default factory setup"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "apdu", "show APDU requests and responses"), + arg_lit0("v", "verbose", "show technical data"), + arg_int0("n", "keyno", "", "Key number"), + arg_str0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), + arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None, AN10922, Gallagher"), + 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(NULL, "aid", "", "Application ID of delegated application (3 hex bytes, big endian)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool APDULogging = arg_get_lit(ctx, 1); + bool verbose = arg_get_lit(ctx, 2); + + 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); + if (res) { + CLIParserFree(ctx); + return res; + } + + SetAPDULogging(APDULogging); + CLIParserFree(ctx); + + if (appid == 0x000000) { + PrintAndLogEx(WARNING, "Deleting the root aid (0x000000) is " _RED_("forbidden")); + return PM3_ESOFT; + } + + res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } + + res = DesfireDeleteApplication(&dctx, appid); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire DesfireDeleteApplication command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + PrintAndLogEx(SUCCESS, "Desfire application %06x " _GREEN_("deleted"), appid); + + DropField(); + return PM3_SUCCESS; +} + static int CmdHF14ADesGetUID(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes getuid", @@ -5776,8 +5839,8 @@ static command_t CommandTable[] = { {"getkeyversions", CmdHF14ADesGetKeyVersions, IfPm3Iso14443a, "[new]Get Key Versions"}, {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("Applications") " -------------------"}, {"bruteaid", CmdHF14ADesBruteApps, IfPm3Iso14443a, "Recover AIDs by bruteforce"}, - {"createaid", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application ID"}, - {"deleteaid", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "Delete Application ID"}, + {"createaid", CmdHF14ADesCreateApp, IfPm3Iso14443a, "[new]Create Application ID"}, + {"deleteaid", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "[new]Delete Application ID"}, {"selectaid", CmdHF14ADesSelectApp, IfPm3Iso14443a, "Select Application ID"}, {"getaids", CmdHF14ADesGetAIDs, IfPm3Iso14443a, "[new]Get Application IDs list"}, {"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "[new]Get Applications list"}, From 9fe785f9188f3bde27684208f8157d313f24206d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Jul 2021 13:34:35 +0300 Subject: [PATCH 294/309] remove code --- client/src/cmdhfmfdes.c | 134 ---------------------------------------- 1 file changed, 134 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 9ce75ae38..84a17e967 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1518,43 +1518,6 @@ static int handler_desfire_getkeysettings(uint8_t *key_settings, uint8_t *num_ke return res; } -/* -static int handler_desfire_getuid(uint8_t *uid) { - if (uid == NULL) { - PrintAndLogEx(DEBUG, "UID=NULL"); - return PM3_EINVARG; - } - sAPDU apdu = {0x90, MFDES_GET_UID, 0x00, 0x00, 0x00, NULL}; //0x51 - uint32_t recv_len = 0; - uint16_t sw = 0; - - // Setup the pre-process to update the IV etc. (not needed in the apdu to send to card) - size_t plen = 1; - uint8_t tmp_data[100] = { 0x00 }; // Note sure on size, but 100 is more then enough - tmp_data[0] = MFDES_GET_UID; - int8_t *p = mifare_cryto_preprocess_data(tag, tmp_data, &plen, 0, MDCM_PLAIN | CMAC_COMMAND); - (void)p; - - // Send request/apdu - int res = send_desfire_cmd(&apdu, false, uid, &recv_len, &sw, 0, true); - - if (res != PM3_SUCCESS) - return res; - - if (sw != status(MFDES_S_OPERATION_OK)) - return PM3_ESOFT; - - // decrypt response - size_t dlen = recv_len; - p = mifare_cryto_postprocess_data(tag, uid, &dlen, CMAC_COMMAND | CMAC_VERIFY | MAC_VERIFY | MDCM_ENCIPHERED); - (void)p; - - DropFieldDesfire(); - - return res; -} -*/ - static int handler_desfire_commit_transaction(void) { sAPDU apdu = {0x90, MFDES_COMMIT_TRANSACTION, 0x00, 0x00, 0x00, NULL}; //0xC7 uint32_t recv_len = 0; @@ -1764,21 +1727,6 @@ static int handler_desfire_createapp(aidhdr_t *aidhdr, bool usename, bool usefid } return res; } -/* -static int handler_desfire_deleteapp(const uint8_t *aid) { - if (aid == NULL) { - return PM3_EINVARG; - } - sAPDU apdu = {0x90, MFDES_DELETE_APPLICATION, 0x00, 0x00, 3, (uint8_t *)aid}; // 0xDA - uint16_t sw = 0; - uint32_t recvlen = 0; - int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); - if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't delete aid -> %s"), DesfireGetErrorString(res, &sw)); - DropFieldDesfire(); - } - return res; -}*/ static int handler_desfire_credit(mfdes_value_t *value, uint8_t cs) { sAPDU apdu = {0x90, MFDES_CREDIT, 0x00, 0x00, 1 + 4, (uint8_t *)value}; // 0x0C @@ -2312,51 +2260,6 @@ static int desfire_authenticate(int cmdAuthMode, int cmdAuthAlgo, uint8_t *aid, return error; } -/* -static int CmdHF14ADesGetUID(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes getuid", - "Get UID from a MIFARE DESfire tag", - "hf mfdes getuid"); - - void *argtable[] = { - arg_param_begin, - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, true); - CLIParserFree(ctx); - - uint8_t uid[16] = {0}; - int res = handler_desfire_getuid(uid); - if (res != PM3_SUCCESS) { - DropFieldDesfire(); - PrintAndLogEx(ERR, "Error on getting uid."); - return res; - } - - // This could be done better. by the crc calc checks. - // Extract the Card UID length (needs rework to allow for 10 Byte UID - uint8_t uidlen = 16; - - // Get datalen + by removing padding. - while ((uidlen > 0) && (uid[uidlen - 1] == 0x00)) - uidlen--; - - if (tag->authentication_scheme == AS_LEGACY) - uidlen -= 2; // 2 byte crc - else - uidlen -= 4; // 4 byte crc - - if (uidlen <= 4) // < incase we trimmed a CRC 00 or more - uidlen = 4; - else - uidlen = 7; - - PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(uid, uidlen)); - return res; -} -*/ - static int CmdHF14ADesSelectApp(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes selectaid", @@ -2538,43 +2441,6 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { } return res; } -/* -static int CmdHF14ADesDeleteApp(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes deleteaid", - "Delete Application ID", - "hf mfdes deleteaid -a 123456" - ); - - void *argtable[] = { - arg_param_begin, - arg_strx0("a", "aid", "", "App ID to delete (3 hex bytes, big endian)"), - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, false); - int aidlength = 3; - uint8_t aid[3] = {0}; - CLIGetHexWithReturn(ctx, 1, aid, &aidlength); - CLIParserFree(ctx); - swap24(aid); - if (aidlength != 3) { - PrintAndLogEx(ERR, "AID must have 3 bytes length."); - return PM3_EINVARG; - } - - if (memcmp(aid, "\x00\x00\x00", 3) == 0) { - PrintAndLogEx(WARNING, _RED_(" Deleting root aid 000000 is forbidden.")); - return PM3_ESOFT; - } - - int res = handler_desfire_deleteapp(aid); - DropFieldDesfire(); - - if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Successfully deleted aid."); - } - return res; -}*/ static int selectfile(uint8_t *aid, uint8_t fileno, uint8_t *cs) { if (handler_desfire_select_application(aid) != PM3_SUCCESS) { From 7ce5fa53f4c5c8218f1fd9115fa13d39c8dd5de6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Jul 2021 14:56:56 +0300 Subject: [PATCH 295/309] createapp help and textual changes --- client/src/cmdhfmfdes.c | 298 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 275 insertions(+), 23 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 84a17e967..47a532089 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1689,7 +1689,7 @@ static int handler_desfire_filesettings(uint8_t file_id, uint8_t *dest, uint32_t return res; } -static int handler_desfire_createapp(aidhdr_t *aidhdr, bool usename, bool usefid) { +/*static int handler_desfire_createapp(aidhdr_t *aidhdr, bool usename, bool usefid) { if (aidhdr == NULL) return PM3_EINVARG; sAPDU apdu = {0x90, MFDES_CREATE_APPLICATION, 0x00, 0x00, sizeof(aidhdr_t), (uint8_t *)aidhdr}; // 0xCA @@ -1726,7 +1726,7 @@ static int handler_desfire_createapp(aidhdr_t *aidhdr, bool usename, bool usefid DropFieldDesfire(); } return res; -} +}*/ static int handler_desfire_credit(mfdes_value_t *value, uint8_t cs) { sAPDU apdu = {0x90, MFDES_CREDIT, 0x00, 0x00, 1 + 4, (uint8_t *)value}; // 0x0C @@ -2294,7 +2294,7 @@ static int CmdHF14ADesSelectApp(const char *Cmd) { } return res; } - +/* static int CmdHF14ADesCreateApp(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes createaid", @@ -2312,7 +2312,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); - /* KeySetting 1 (AMK Setting): + KeySetting 1 (AMK Setting): 0: Allow change master key 1: Free Directory list access without master key 0: AMK auth needed for GetFileSettings and GetKeySettings @@ -2329,8 +2329,8 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { 0xE: Auth with the key to be changed (same KeyNo) is necessary to change a key 0xF: All Keys within this application are frozen - */ - /* KeySetting 2: + + KeySetting 2: 0..3: Number of keys stored within the application (max. 14 keys) 4: RFU 5: Use of 2 byte ISO FID, 0: No, 1: Yes @@ -2339,7 +2339,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { 2E = FID, DES, 14 keys 6E = FID, 3K3DES, 14 keys AE = FID, AES, 14 keys - */ + int aidlength = 3; uint8_t aid[3] = {0}; CLIGetHexWithReturn(ctx, 1, aid, &aidlength); @@ -2394,11 +2394,11 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { if (namelen == 0) usename = false; //90 ca 00 00 0e 3cb849 09 22 10e1 d27600 00850101 00 - /*char name[]="Test"; + *char name[]="Test"; uint8_t aid[]={0x12,0x34,0x56}; uint8_t fid[]={0x11,0x22}; uint8_t keysetting1=0xEE; - uint8_t keysetting2=0xEE;*/ + uint8_t keysetting2=0xEE; if (memcmp(aid, "\x00\x00\x00", 3) == 0) { PrintAndLogEx(WARNING, _RED_(" Creating root aid 000000 is forbidden")); @@ -2425,14 +2425,14 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { if (usename) PrintAndLogEx(INFO, "DF Name %s", aidhdr.name); - /* + uint8_t rootaid[3] = {0x00, 0x00, 0x00}; int res = handler_desfire_select_application(rootaid); if (res != PM3_SUCCESS) { DropFieldDesfire(); return res; } - */ + int res = handler_desfire_createapp(&aidhdr, usename, usefid); DropFieldDesfire(); @@ -2441,7 +2441,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { } return res; } - +*/ static int selectfile(uint8_t *aid, uint8_t fileno, uint8_t *cs) { if (handler_desfire_select_application(aid) != PM3_SUCCESS) { PrintAndLogEx(ERR, _RED_(" Couldn't select aid.")); @@ -5032,6 +5032,258 @@ static int CmdHF14ADesDefault(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHF14ADesCreateApp(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes createid", + "Create application. Master key needs to be provided.", + "option rawdata have priority over the rest settings, and options ks1 and ks2 have priority over corresponded key settings\n" + "\n"\ + "KeySetting 1 (AMK Setting, ks1):\n"\ + " 0: Allow change master key. 1 - allow, 0 - frozen\n"\ + " 1: Free Directory list access without master key\n"\ + " 0: AMK auth needed for GetFileSettings and GetKeySettings\n"\ + " 1: No AMK auth needed for GetFileIDs, GetISOFileIDs, GetFileSettings, GetKeySettings\n"\ + " 2: Free create/delete without master key\n"\ + " 0: CreateFile/DeleteFile only with AMK auth\n"\ + " 1: CreateFile/DeleteFile always\n"\ + " 3: Configuration changable\n"\ + " 0: Configuration frozen\n"\ + " 1: Configuration changable if authenticated with AMK (default)\n"\ + " 4-7: ChangeKey Access Rights\n"\ + " 0: Application master key needed (default)\n"\ + " 0x1..0xD: Auth with specific key needed to change any key\n"\ + " 0xE: Auth with the key to be changed (same KeyNo) is necessary to change a key\n"\ + " 0xF: All Keys within this application are frozen\n"\ + "\n"\ + "KeySetting 2 (ks2):\n"\ + " 0..3: Number of keys stored within the application (max. 14 keys)\n"\ + " 4: ks3 is present\n"\ + " 5: Use of 2 byte ISO FID, 0: No, 1: Yes\n"\ + " 6..7: Crypto Method 00: DES/2TDEA, 01: 3TDEA, 10: AES, 11: RFU\n"\ + " Example:\n"\ + " 2E = with FID, DES/2TDEA, 14 keys\n"\ + " 6E = with FID, 3TDEA, 14 keys\n"\ + " AE = with FID, AES, 14 keys\n"\ + "\n"\ + "hf mfdes createid --rawdata 123456 -> execute create by rawdata\n"\ + "hf mfdes createid --aid 123456 --fid 2345 --dfname aid123456 -> app aid, iso file id, and iso df name is specified\n" + "hf mfdes createid --aid 123456 --fid 2345 --dfname aid123456 --dstalgo aes -> with algorithm for key AES"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "apdu", "show APDU requests and responses"), + arg_lit0("v", "verbose", "show technical data"), + arg_int0("n", "keyno", "", "Key number"), + arg_str0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), + arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None, AN10922, Gallagher"), + 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(NULL, "rawdata", "", "Rawdata that sends to command"), + arg_str0(NULL, "aid", "", "Application ID of delegated application (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."), + arg_str0(NULL, "dfname", "", "ISO DF Name 1..16 chars string"), + arg_str0(NULL, "ks1", "", "Key settings 1 (HEX 1 byte). Application Master Key Settings. default 0x2e"), + arg_str0(NULL, "ks2", "", "Key settings 2 (HEX 1 byte). default 0x0f"), + arg_str0(NULL, "dstalgo", "", "Application key crypt algo: DES, 2TDEA, 3TDEA, AES. default DES"), + arg_int0(NULL, "numkeys", "", "Keys count. 0x00..0x0e. default 0x0e"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + bool APDULogging = arg_get_lit(ctx, 1); + bool verbose = arg_get_lit(ctx, 2); + + DesfireContext dctx; + int securechann = defaultSecureChannel; + uint32_t appid = 0x000000; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 12, &securechann, DCMPlain, &appid); + if (res) { + CLIParserFree(ctx); + return res; + } + + SetAPDULogging(APDULogging); + CLIParserFree(ctx); + + if (appid == 0x000000) { + PrintAndLogEx(WARNING, "Creating the root aid (0x000000) is " _RED_("forbidden")); + return PM3_ESOFT; + } + + res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } + + res = DesfireCreateApplication(&dctx, appid); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire CreateApplication command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + PrintAndLogEx(SUCCESS, "Desfire application %06x successfully " _GREEN_("created"), appid); + + DropField(); + return PM3_SUCCESS; + + + + + + + + + + /*CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes createaid", + "Create Application ID", + "hf mfdes createaid -a 123456 -f 1111 -k 0E -l 2E --name Test" + ); + + void *argtable[] = { + arg_param_begin, + arg_strx0("a", "aid", "", "App ID to create as hex bytes (3 hex bytes)"), + arg_strx0("f", "fid", "", "File ID to create"), + arg_strx0("k", "ks1", "", "Key Setting 1 (Application Master Key Settings)"), + arg_strx0("l", "ks2", "", "Key Setting 2"), + arg_str0(NULL, "name", "", "App ISO-4 Name"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + KeySetting 1 (AMK Setting): + 0: Allow change master key + 1: Free Directory list access without master key + 0: AMK auth needed for GetFileSettings and GetKeySettings + 1: No AMK auth needed for GetFileIDs, GetISOFileIDs, GetFileSettings, GetKeySettings + 2: Free create/delete without master key + 0: CreateFile/DeleteFile only with AMK auth + 1: CreateFile/DeleteFile always + 3: Configuration changable + 0: Configuration frozen + 1: Configuration changable if authenticated with AMK (default) + 4-7: ChangeKey Access Rights + 0: Application master key needed (default) + 0x1..0xD: Auth with specific key needed to change any key + 0xE: Auth with the key to be changed (same KeyNo) is necessary to change a key + 0xF: All Keys within this application are frozen + + + KeySetting 2: + 0..3: Number of keys stored within the application (max. 14 keys) + 4: RFU + 5: Use of 2 byte ISO FID, 0: No, 1: Yes + 6..7: Crypto Method 00: DES/3DES, 01: 3K3DES, 10: AES + Example: + 2E = FID, DES, 14 keys + 6E = FID, 3K3DES, 14 keys + AE = FID, AES, 14 keys + + int aidlength = 3; + uint8_t aid[3] = {0}; + CLIGetHexWithReturn(ctx, 1, aid, &aidlength); + + int fidlength = 2; + uint8_t fid[2] = {0}; + CLIGetHexWithReturn(ctx, 2, fid, &fidlength); + + int keylen1 = 1; + uint8_t keysetting1[1] = {0}; + CLIGetHexWithReturn(ctx, 3, keysetting1, &keylen1); + + int keylen2 = 1; + uint8_t keysetting2[1] = {0}; + CLIGetHexWithReturn(ctx, 4, keysetting2, &keylen2); + + int namelen = 16; + uint8_t name[16] = {0}; + CLIGetStrWithReturn(ctx, 5, name, &namelen); + CLIParserFree(ctx); + + swap24(aid); + swap16(fid); + + if (aidlength != 3) { + PrintAndLogEx(ERR, "AID must have 3 bytes length"); + return PM3_EINVARG; + } + + if (fidlength != 2 && fidlength != 0) { + PrintAndLogEx(ERR, "FID must have 2 bytes length"); + return PM3_EINVARG; + } + + bool usefid = (fidlength != 0); + + if (keylen1 != 1) { + PrintAndLogEx(ERR, "Keysetting1 must have 1 byte length"); + return PM3_EINVARG; + } + + if (keylen2 != 1) { + PrintAndLogEx(ERR, "Keysetting2 must have 1 byte length"); + return PM3_EINVARG; + } + + if (namelen > 16) { + PrintAndLogEx(ERR, "Name has a max. of 16 bytes length"); + return PM3_EINVARG; + } + bool usename = true; + if (namelen == 0) usename = false; + + //90 ca 00 00 0e 3cb849 09 22 10e1 d27600 00850101 00 + *char name[]="Test"; + uint8_t aid[]={0x12,0x34,0x56}; + uint8_t fid[]={0x11,0x22}; + uint8_t keysetting1=0xEE; + uint8_t keysetting2=0xEE; + + if (memcmp(aid, "\x00\x00\x00", 3) == 0) { + PrintAndLogEx(WARNING, _RED_(" Creating root aid 000000 is forbidden")); + return PM3_ESOFT; + } + + aidhdr_t aidhdr; + memcpy(aidhdr.aid, aid, sizeof(aid)); + aidhdr.keysetting1 = keysetting1[0]; + aidhdr.keysetting2 = keysetting2[0]; + + if (usefid) + memcpy(aidhdr.fid, fid, sizeof(aidhdr.fid)); + + if (usename) + memcpy(aidhdr.name, name, sizeof(aidhdr.name)); + + PrintAndLogEx(INFO, "Creating AID using:"); + PrintAndLogEx(INFO, "AID %s", sprint_hex_inrow(aidhdr.aid, sizeof(aidhdr.aid))); + PrintAndLogEx(INFO, "Key set1 0x%02X", aidhdr.keysetting1); + PrintAndLogEx(INFO, "Key Set2 0x%02X", aidhdr.keysetting2); + if (usefid) + PrintAndLogEx(INFO, "FID %s", sprint_hex_inrow(aidhdr.fid, sizeof(aidhdr.fid))); + if (usename) + PrintAndLogEx(INFO, "DF Name %s", aidhdr.name); + + + uint8_t rootaid[3] = {0x00, 0x00, 0x00}; + int res = handler_desfire_select_application(rootaid); + if (res != PM3_SUCCESS) { + DropFieldDesfire(); + return res; + } + + + int res = handler_desfire_createapp(&aidhdr, usename, usefid); + DropFieldDesfire(); + if (res == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "Successfully created aid."); + } + return res;*/ +} static int CmdHF14ADesDeleteApp(const char *Cmd) { CLIParserContext *ctx; @@ -5084,7 +5336,7 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) { res = DesfireDeleteApplication(&dctx, appid); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire DesfireDeleteApplication command " _RED_("error") ". Result: %d", res); + PrintAndLogEx(ERR, "Desfire DeleteApplication command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } @@ -5142,7 +5394,7 @@ static int CmdHF14ADesGetUID(const char *Cmd) { res = DesfireGetUID(&dctx, buf, &buflen); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire DesfireGetUID command " _RED_("error") ". Result: %d", res); + PrintAndLogEx(ERR, "Desfire GetUID command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } @@ -5199,7 +5451,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { res = DesfireFormatPICC(&dctx); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire DesfireFormatPICC command " _RED_("error") ". Result: %d", res); + PrintAndLogEx(ERR, "Desfire FormatPICC command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } @@ -5268,7 +5520,7 @@ static int CmdHF14ADesGetFreeMem(const char *Cmd) { res = DesfireGetFreeMem(&dctx, &freemem); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire DesfireGetFreeMem command " _RED_("error") ". Result: %d", res); + PrintAndLogEx(ERR, "Desfire GetFreeMem command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } @@ -5345,7 +5597,7 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { uint8_t keysett = ksett32 & 0x0f; res = DesfireChangeKeySettings(&dctx, &keysett, 1); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire DesfireChangeKeySettings command " _RED_("error") ". Result: %d", res); + PrintAndLogEx(ERR, "Desfire ChangeKeySettings command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } @@ -5444,13 +5696,13 @@ static int CmdHF14ADesGetKeyVersions(const char *Cmd) { res = DesfireGetKeyVersion(&dctx, data, (keysetpresent) ? 2 : 1, buf, &buflen); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire DesfireGetKeyVersion command " _RED_("error") ". Result: %d", res); + PrintAndLogEx(ERR, "Desfire GetKeyVersion command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } if (verbose) - PrintAndLogEx(INFO, "DesfireGetKeyVersion[%zu]: %s", buflen, sprint_hex(buf, buflen)); + PrintAndLogEx(INFO, "GetKeyVersion[%zu]: %s", buflen, sprint_hex(buf, buflen)); if (buflen > 0) { PrintAndLogEx(INFO, "----------------------- " _CYAN_("Key Versions") " -----------------------"); @@ -5514,16 +5766,16 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { res = DesfireGetKeySettings(&dctx, buf, &buflen); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire DesfireGetKeySettings command " _RED_("error") ". Result: %d", res); + PrintAndLogEx(ERR, "Desfire GetKeySettings command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } if (verbose) - PrintAndLogEx(INFO, "DesfireGetKeySettings[%zu]: %s", buflen, sprint_hex(buf, buflen)); + PrintAndLogEx(INFO, "GetKeySettings[%zu]: %s", buflen, sprint_hex(buf, buflen)); if (buflen < 2) { - PrintAndLogEx(ERR, "Command DesfireGetKeySettings returned wrong length: %zu", buflen); + PrintAndLogEx(ERR, "Command GetKeySettings returned wrong length: %zu", buflen); DropField(); return PM3_ESOFT; } @@ -5658,7 +5910,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { // result bytes: 3, 2, 1-16. total record size = 24 res = DesfireGetDFList(&dctx, buf, &buflen); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire DesfireGetDFList command " _RED_("error") ". Result: %d", res); + PrintAndLogEx(ERR, "Desfire GetDFList command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } From e00fc93c20bb3448542a80eacbbf8d966475ed69 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Jul 2021 16:51:50 +0300 Subject: [PATCH 296/309] createfile works --- client/src/cmdhfmfdes.c | 105 +++++++++++++++++++++++++++++--- client/src/mifare/desfirecore.c | 3 + 2 files changed, 99 insertions(+), 9 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 47a532089..29816cc70 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5082,11 +5082,11 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), arg_str0(NULL, "rawdata", "", "Rawdata that sends to command"), - arg_str0(NULL, "aid", "", "Application ID of delegated application (3 hex bytes, big endian)"), + 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."), arg_str0(NULL, "dfname", "", "ISO DF Name 1..16 chars string"), - arg_str0(NULL, "ks1", "", "Key settings 1 (HEX 1 byte). Application Master Key Settings. default 0x2e"), - arg_str0(NULL, "ks2", "", "Key settings 2 (HEX 1 byte). default 0x0f"), + arg_str0(NULL, "ks1", "", "Key settings 1 (HEX 1 byte). Application Master Key Settings. default 0x2f"), + arg_str0(NULL, "ks2", "", "Key settings 2 (HEX 1 byte). default 0x0e"), arg_str0(NULL, "dstalgo", "", "Application key crypt algo: DES, 2TDEA, 3TDEA, AES. default DES"), arg_int0(NULL, "numkeys", "", "Keys count. 0x00..0x0e. default 0x0e"), arg_param_end @@ -5105,21 +5105,111 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { return res; } + uint8_t rawdata[250] = {0}; + int rawdatalen = sizeof(rawdata); + CLIGetHexWithReturn(ctx, 11, rawdata, &rawdatalen); + + uint32_t fileid = 0x0000; + res = arg_get_u32_hexstr_def_nlen(ctx, 13, 0x0000, &fileid, 2, true); + bool fileidpresent = (res == 1); + if (res == 2) { + PrintAndLogEx(ERR, "ISO file ID must have 2 bytes length"); + return PM3_EINVARG; + } + + uint8_t dfname[250] = {0}; + int dfnamelen = 16; + CLIGetStrWithReturn(ctx, 14, dfname, &dfnamelen); + + uint32_t ks1 = 0x2f; + res = arg_get_u32_hexstr_def_nlen(ctx, 15, 0x2f, &ks1, 1, true); + if (res == 2) { + PrintAndLogEx(ERR, "Key settings 1 must have 1 byte length"); + return PM3_EINVARG; + } + + uint32_t ks2 = 0x0e; + res = arg_get_u32_hexstr_def_nlen(ctx, 16, 0x0e, &ks2, 1, true); + bool ks2present = (res == 1); + if (res == 2) { + PrintAndLogEx(ERR, "Key settings 2 must have 1 byte length"); + return PM3_EINVARG; + } + + int dstalgo = T_DES; + if (CLIGetOptionList(arg_get_str(ctx, 17), DesfireAlgoOpts, &dstalgo)) + return PM3_ESOFT; + + int keycount = arg_get_int_def(ctx, 18, 0x0e); + SetAPDULogging(APDULogging); CLIParserFree(ctx); if (appid == 0x000000) { - PrintAndLogEx(WARNING, "Creating the root aid (0x000000) is " _RED_("forbidden")); + PrintAndLogEx(ERR, "Creating the root aid (0x000000) is " _RED_("forbidden")); return PM3_ESOFT; } - res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose); + if ((fileidpresent || (ks2 & 0x20) != 0) && fileid == 0x0000) { + PrintAndLogEx(ERR, "Creating the application with ISO file ID 0x0000 is " _RED_("forbidden")); + return PM3_ESOFT; + } + + if (keycount > 0x0e || keycount < 1) { + PrintAndLogEx(ERR, "Key count must be in the range 0x01..0x0e"); + return PM3_ESOFT; + } + + res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); if (res != PM3_SUCCESS) { DropField(); return res; } + + uint8_t data[250] = {0}; + size_t datalen = 0; + if (rawdatalen > 0) { + memcpy(data, rawdata, rawdatalen); + datalen = rawdatalen; + } else { + DesfireAIDUintToByte(appid, &data[0]); + data[3] = ks1 & 0xff; + data[4] = ks2 & 0xff; + + if (!ks2present) { + if (keycount > 0) { + //data[4] keycount + } + //data[4] dstalgo + } + + + datalen = 5; + if (fileidpresent || (data[4] & 0x20) != 0) { + data[5] = fileid & 0xff; + data[6] = (fileid >> 8) & 0xff; + data[4] |= 0x20; // set bit FileID in the ks2 + memcpy(&data[7], dfname, dfnamelen); + datalen = 7 + 16; + } + } - res = DesfireCreateApplication(&dctx, appid); + if (verbose) { + PrintAndLogEx(INFO, "---------------------------"); + PrintAndLogEx(INFO, _CYAN_("Creating Application using:")); + PrintAndLogEx(INFO, "AID 0x%02X%02X%02X", data[2], data[1], data[0]); + PrintAndLogEx(INFO, "Key Set 1 0x%02X", data[3]); + PrintAndLogEx(INFO, "Key Set 2 0x%02X", data[4]); + PrintAndLogEx(INFO, "ISO file ID %s", (data[4] & 0x20) ? "enabled" : "disabled"); + if ((data[4] & 0x20)) { + PrintAndLogEx(INFO, "FID 0x%02x%02x", data[5], data[6]); + PrintAndLogEx(INFO, "DF Name[%02d] %s\n", strnlen((char *)&data[7], 16), (char *)&data[7]); + } + PrintKeySettings(data[3], data[4], true, true); + PrintAndLogEx(INFO, "---------------------------"); + } + + res = DesfireCreateApplication(&dctx, data, datalen); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire CreateApplication command " _RED_("error") ". Result: %d", res); DropField(); @@ -5895,9 +5985,6 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - if (verbose) - DesfirePrintContext(&dctx); - res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); if (res != PM3_SUCCESS) { DropField(); diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index f1328a568..b2fc493a5 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1049,6 +1049,9 @@ static void PrintKeySettingsApp(uint8_t keysettings, uint8_t numkeys, bool print if (print2ndbyte) { PrintKeyType(numkeys >> 6); PrintAndLogEx(SUCCESS, "key count: %d", numkeys & 0x0f); + if (numkeys & 0x20) + PrintAndLogEx(SUCCESS, "iso file id: enabled"); + PrintAndLogEx(SUCCESS, ""); } } From 9b70ebc01ffec8710a83baa1fd7aa61a6eb07d40 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Jul 2021 16:56:28 +0300 Subject: [PATCH 297/309] fix cmd default test --- client/src/cmdhfmfdes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 29816cc70..5048ea58a 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4981,8 +4981,8 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct static int CmdHF14ADesDefault(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes default", - "Get Application IDs, ISO IDs and DF names from card. Master key needs to be provided.", - "hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup"); + "Set default parameters for access to desfire card.", + "hf mfdes default -n 0 -t des -k 0000000000000000 -f none -> save to the default factory setup"); void *argtable[] = { arg_param_begin, From 668650b8cd61107a752fa73f86e0c17506e2815a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Jul 2021 17:23:29 +0300 Subject: [PATCH 298/309] fix bugs --- 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 5048ea58a..593469590 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4982,7 +4982,7 @@ static int CmdHF14ADesDefault(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes default", "Set default parameters for access to desfire card.", - "hf mfdes default -n 0 -t des -k 0000000000000000 -f none -> save to the default factory setup"); + "hf mfdes default -n 0 -t des -k 0000000000000000 -f none -> save to the default parameters"); void *argtable[] = { arg_param_begin, @@ -5625,8 +5625,8 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes chkeysetings", "Change key settings for card level or application level. WARNING: card level changes may block card!", - "hf mfdes chkeysetings -d 0e -> set picc key settings with default key/channel setup\n"\ - "hf mfdes chkeysetings --aid 123456 -d 0e -> set app 123456 key settings with default key/channel setup"); + "hf mfdes chkeysetings -d 0f -> set picc key settings with default key/channel setup\n"\ + "hf mfdes chkeysetings --aid 123456 -d 0f -> set app 123456 key settings with default key/channel setup"); void *argtable[] = { arg_param_begin, @@ -5644,7 +5644,7 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { arg_str0("d", "data", "", "Key settings (HEX 1 byte)"), arg_param_end }; - CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIExecWithReturn(ctx, Cmd, argtable, false); bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); @@ -5659,7 +5659,7 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { } uint32_t ksett32 = 0; - res = arg_get_u32_hexstr_def_nlen(ctx, 12, 0x000000, &ksett32, 1, false); + res = arg_get_u32_hexstr_def_nlen(ctx, 12, 0x0f, &ksett32, 1, false); if (res == 0) { CLIParserFree(ctx); return PM3_ESOFT; @@ -5684,7 +5684,7 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { return res; } - uint8_t keysett = ksett32 & 0x0f; + uint8_t keysett = ksett32 & 0xff; res = DesfireChangeKeySettings(&dctx, &keysett, 1); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire ChangeKeySettings command " _RED_("error") ". Result: %d", res); From 741f560a8d7f15228d944580f5e35eefd123d0bd Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Jul 2021 17:29:45 +0300 Subject: [PATCH 299/309] hf mfdes getaids -- no-auth --- client/src/cmdhfmfdes.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 593469590..c453393f3 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5624,7 +5624,7 @@ static int CmdHF14ADesGetFreeMem(const char *Cmd) { static int CmdHF14ADesChKeySettings(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes chkeysetings", - "Change key settings for card level or application level. WARNING: card level changes may block card!", + "Change key settings for card level or application level. WARNING: card level changes may block the card!", "hf mfdes chkeysetings -d 0f -> set picc key settings with default key/channel setup\n"\ "hf mfdes chkeysetings --aid 123456 -d 0f -> set app 123456 key settings with default key/channel setup"); @@ -5903,12 +5903,14 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { 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_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); + bool noauth = arg_get_lit(ctx, 11); DesfireContext dctx; int securechann = defaultSecureChannel; @@ -5921,10 +5923,19 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); - if (res != PM3_SUCCESS) { - DropField(); - return res; + if (noauth) { + res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); + DropField(); + return res; + } + } else { + res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } } uint8_t buf[APDU_RES_LEN] = {0}; From 5a72b5367694c57d01e5dec6f205c7aff1858a80 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Jul 2021 17:36:27 +0300 Subject: [PATCH 300/309] fix DesfireCommandEx --- client/src/mifare/desfirecore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index b2fc493a5..df9427941 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -919,7 +919,7 @@ static int DesfireCommandEx(DesfireContext *dctx, uint8_t cmd, uint8_t *data, si if (resplen) *resplen = xresplen; if (resp) - memcpy(resp, xresp, xresplen); + memcpy(resp, xresp, (splitbysize == 0) ? xresplen : xresplen * splitbysize); return PM3_SUCCESS; } From 2f2942c7db84a01bad39d944585fe5c7a218842e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Jul 2021 17:42:10 +0300 Subject: [PATCH 301/309] CmdHF14ADesGetAppNames --no-auth --- client/src/cmdhfmfdes.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index c453393f3..09b9974f7 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5888,7 +5888,7 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { static int CmdHF14ADesGetAIDs(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes getaids", - "Get Application IDs list from card. Master key needs to be provided.", + "Get Application IDs list from card. Master key needs to be provided or flag --no-auth set.", "hf mfdes getaids -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup"); void *argtable[] = { @@ -5963,7 +5963,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { static int CmdHF14ADesGetAppNames(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes getappnames", - "Get Application IDs, ISO IDs and DF names from card. Master key needs to be provided.", + "Get Application IDs, ISO IDs and DF names from card. Master key needs to be provided or flag --no-auth set.", "hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup"); void *argtable[] = { @@ -5978,12 +5978,14 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { 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_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); + bool noauth = arg_get_lit(ctx, 11); DesfireContext dctx; int securechann = defaultSecureChannel; @@ -5996,10 +5998,19 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); - if (res != PM3_SUCCESS) { - DropField(); - return res; + if (noauth) { + res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); + DropField(); + return res; + } + } else { + res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } } uint8_t buf[APDU_RES_LEN] = {0}; From 1b3e34c928d48e4f4a02ffa831fe6d10212bdc3f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Jul 2021 18:13:29 +0300 Subject: [PATCH 302/309] createapp fully works --- client/src/cmdhfmfdes.c | 27 +++++++++++++++++---------- client/src/mifare/desfirecore.c | 9 +++++++++ client/src/mifare/desfirecore.h | 1 + 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 09b9974f7..fe07ab53e 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5034,7 +5034,7 @@ static int CmdHF14ADesDefault(const char *Cmd) { static int CmdHF14ADesCreateApp(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes createid", + CLIParserInit(&ctx, "hf mfdes createaid", "Create application. Master key needs to be provided.", "option rawdata have priority over the rest settings, and options ks1 and ks2 have priority over corresponded key settings\n" "\n"\ @@ -5065,9 +5065,9 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { " 6E = with FID, 3TDEA, 14 keys\n"\ " AE = with FID, AES, 14 keys\n"\ "\n"\ - "hf mfdes createid --rawdata 123456 -> execute create by rawdata\n"\ - "hf mfdes createid --aid 123456 --fid 2345 --dfname aid123456 -> app aid, iso file id, and iso df name is specified\n" - "hf mfdes createid --aid 123456 --fid 2345 --dfname aid123456 --dstalgo aes -> with algorithm for key AES"); + "hf mfdes createaid --rawdata 123456 -> execute create by rawdata\n"\ + "hf mfdes createaid --aid 123456 --fid 2345 --dfname aid123456 -> app aid, iso file id, and iso df name is specified\n" + "hf mfdes createaid --aid 123456 --fid 2345 --dfname aid123456 --dstalgo aes -> with algorithm for key AES"); void *argtable[] = { arg_param_begin, @@ -5156,9 +5156,14 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { } if (keycount > 0x0e || keycount < 1) { - PrintAndLogEx(ERR, "Key count must be in the range 0x01..0x0e"); + PrintAndLogEx(ERR, "Key count must be in the range 1..14"); return PM3_ESOFT; } + + if (dfnamelen > 16) { + PrintAndLogEx(ERR, "DF name must be a maximum of 16 bytes in length"); + return PM3_EINVARG; + } res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); if (res != PM3_SUCCESS) { @@ -5178,11 +5183,13 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { if (!ks2present) { if (keycount > 0) { - //data[4] keycount + data[4] &= 0xf0; + data[4] |= keycount & 0x0f; } - //data[4] dstalgo - } - + uint8_t kt = DesfireKeyAlgoToType(dstalgo); + data[4] &= 0x3f; + data[4] |= (kt & 0x03) << 6; + } datalen = 5; if (fileidpresent || (data[4] & 0x20) != 0) { @@ -5190,7 +5197,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { data[6] = (fileid >> 8) & 0xff; data[4] |= 0x20; // set bit FileID in the ks2 memcpy(&data[7], dfname, dfnamelen); - datalen = 7 + 16; + datalen = 7 + dfnamelen; } } diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index df9427941..216a62a1a 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -988,6 +988,15 @@ int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len) { return DesfireCommandTxData(dctx, MFDES_CHANGE_KEY_SETTINGS, data, len); } +uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType) { + switch(keyType) { + case T_DES: return 0x00; + case T_3DES: return 0x00; + case T_3K3DES: return 0x01; + case T_AES: return 0x02; + } + return 0; +} static void PrintKeyType(uint8_t keytype) { switch (keytype) { case 00: diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index acc7bd7af..c6b092b59 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -53,5 +53,6 @@ int DesfireGetKeyVersion(DesfireContext *dctx, uint8_t *data, size_t len, uint8_ int DesfireGetKeySettings(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len); void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel, bool print2ndbyte); +uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType); #endif // __DESFIRECORE_H From 480bd87207c18868e1627c589e665343f5d57d7b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Jul 2021 18:20:22 +0300 Subject: [PATCH 303/309] make style --- client/src/cmdhfmfdes.c | 205 ++++---------------------------- client/src/mifare/desfirecore.c | 22 ++-- 2 files changed, 39 insertions(+), 188 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index fe07ab53e..cf347abab 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -2329,7 +2329,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { 0xE: Auth with the key to be changed (same KeyNo) is necessary to change a key 0xF: All Keys within this application are frozen - + KeySetting 2: 0..3: Number of keys stored within the application (max. 14 keys) 4: RFU @@ -2339,7 +2339,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { 2E = FID, DES, 14 keys 6E = FID, 3K3DES, 14 keys AE = FID, AES, 14 keys - + int aidlength = 3; uint8_t aid[3] = {0}; CLIGetHexWithReturn(ctx, 1, aid, &aidlength); @@ -2425,14 +2425,14 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { if (usename) PrintAndLogEx(INFO, "DF Name %s", aidhdr.name); - + uint8_t rootaid[3] = {0x00, 0x00, 0x00}; int res = handler_desfire_select_application(rootaid); if (res != PM3_SUCCESS) { DropFieldDesfire(); return res; } - + int res = handler_desfire_createapp(&aidhdr, usename, usefid); DropFieldDesfire(); @@ -5068,7 +5068,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { "hf mfdes createaid --rawdata 123456 -> execute create by rawdata\n"\ "hf mfdes createaid --aid 123456 --fid 2345 --dfname aid123456 -> app aid, iso file id, and iso df name is specified\n" "hf mfdes createaid --aid 123456 --fid 2345 --dfname aid123456 --dstalgo aes -> with algorithm for key AES"); - + void *argtable[] = { arg_param_begin, arg_lit0("a", "apdu", "show APDU requests and responses"), @@ -5116,11 +5116,11 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { PrintAndLogEx(ERR, "ISO file ID must have 2 bytes length"); return PM3_EINVARG; } - + uint8_t dfname[250] = {0}; int dfnamelen = 16; CLIGetStrWithReturn(ctx, 14, dfname, &dfnamelen); - + uint32_t ks1 = 0x2f; res = arg_get_u32_hexstr_def_nlen(ctx, 15, 0x2f, &ks1, 1, true); if (res == 2) { @@ -5135,16 +5135,16 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { PrintAndLogEx(ERR, "Key settings 2 must have 1 byte length"); return PM3_EINVARG; } - + int dstalgo = T_DES; if (CLIGetOptionList(arg_get_str(ctx, 17), DesfireAlgoOpts, &dstalgo)) return PM3_ESOFT; - + int keycount = arg_get_int_def(ctx, 18, 0x0e); SetAPDULogging(APDULogging); CLIParserFree(ctx); - + if (appid == 0x000000) { PrintAndLogEx(ERR, "Creating the root aid (0x000000) is " _RED_("forbidden")); return PM3_ESOFT; @@ -5159,7 +5159,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { PrintAndLogEx(ERR, "Key count must be in the range 1..14"); return PM3_ESOFT; } - + if (dfnamelen > 16) { PrintAndLogEx(ERR, "DF name must be a maximum of 16 bytes in length"); return PM3_EINVARG; @@ -5170,7 +5170,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { DropField(); return res; } - + uint8_t data[250] = {0}; size_t datalen = 0; if (rawdatalen > 0) { @@ -5180,7 +5180,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { DesfireAIDUintToByte(appid, &data[0]); data[3] = ks1 & 0xff; data[4] = ks2 & 0xff; - + if (!ks2present) { if (keycount > 0) { data[4] &= 0xf0; @@ -5189,14 +5189,14 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { uint8_t kt = DesfireKeyAlgoToType(dstalgo); data[4] &= 0x3f; data[4] |= (kt & 0x03) << 6; - } - + } + datalen = 5; if (fileidpresent || (data[4] & 0x20) != 0) { data[5] = fileid & 0xff; data[6] = (fileid >> 8) & 0xff; data[4] |= 0x20; // set bit FileID in the ks2 - memcpy(&data[7], dfname, dfnamelen); + memcpy(&data[7], dfname, dfnamelen); datalen = 7 + dfnamelen; } } @@ -5227,159 +5227,6 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { DropField(); return PM3_SUCCESS; - - - - - - - - - - /*CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes createaid", - "Create Application ID", - "hf mfdes createaid -a 123456 -f 1111 -k 0E -l 2E --name Test" - ); - - void *argtable[] = { - arg_param_begin, - arg_strx0("a", "aid", "", "App ID to create as hex bytes (3 hex bytes)"), - arg_strx0("f", "fid", "", "File ID to create"), - arg_strx0("k", "ks1", "", "Key Setting 1 (Application Master Key Settings)"), - arg_strx0("l", "ks2", "", "Key Setting 2"), - arg_str0(NULL, "name", "", "App ISO-4 Name"), - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, false); - KeySetting 1 (AMK Setting): - 0: Allow change master key - 1: Free Directory list access without master key - 0: AMK auth needed for GetFileSettings and GetKeySettings - 1: No AMK auth needed for GetFileIDs, GetISOFileIDs, GetFileSettings, GetKeySettings - 2: Free create/delete without master key - 0: CreateFile/DeleteFile only with AMK auth - 1: CreateFile/DeleteFile always - 3: Configuration changable - 0: Configuration frozen - 1: Configuration changable if authenticated with AMK (default) - 4-7: ChangeKey Access Rights - 0: Application master key needed (default) - 0x1..0xD: Auth with specific key needed to change any key - 0xE: Auth with the key to be changed (same KeyNo) is necessary to change a key - 0xF: All Keys within this application are frozen - - - KeySetting 2: - 0..3: Number of keys stored within the application (max. 14 keys) - 4: RFU - 5: Use of 2 byte ISO FID, 0: No, 1: Yes - 6..7: Crypto Method 00: DES/3DES, 01: 3K3DES, 10: AES - Example: - 2E = FID, DES, 14 keys - 6E = FID, 3K3DES, 14 keys - AE = FID, AES, 14 keys - - int aidlength = 3; - uint8_t aid[3] = {0}; - CLIGetHexWithReturn(ctx, 1, aid, &aidlength); - - int fidlength = 2; - uint8_t fid[2] = {0}; - CLIGetHexWithReturn(ctx, 2, fid, &fidlength); - - int keylen1 = 1; - uint8_t keysetting1[1] = {0}; - CLIGetHexWithReturn(ctx, 3, keysetting1, &keylen1); - - int keylen2 = 1; - uint8_t keysetting2[1] = {0}; - CLIGetHexWithReturn(ctx, 4, keysetting2, &keylen2); - - int namelen = 16; - uint8_t name[16] = {0}; - CLIGetStrWithReturn(ctx, 5, name, &namelen); - CLIParserFree(ctx); - - swap24(aid); - swap16(fid); - - if (aidlength != 3) { - PrintAndLogEx(ERR, "AID must have 3 bytes length"); - return PM3_EINVARG; - } - - if (fidlength != 2 && fidlength != 0) { - PrintAndLogEx(ERR, "FID must have 2 bytes length"); - return PM3_EINVARG; - } - - bool usefid = (fidlength != 0); - - if (keylen1 != 1) { - PrintAndLogEx(ERR, "Keysetting1 must have 1 byte length"); - return PM3_EINVARG; - } - - if (keylen2 != 1) { - PrintAndLogEx(ERR, "Keysetting2 must have 1 byte length"); - return PM3_EINVARG; - } - - if (namelen > 16) { - PrintAndLogEx(ERR, "Name has a max. of 16 bytes length"); - return PM3_EINVARG; - } - bool usename = true; - if (namelen == 0) usename = false; - - //90 ca 00 00 0e 3cb849 09 22 10e1 d27600 00850101 00 - *char name[]="Test"; - uint8_t aid[]={0x12,0x34,0x56}; - uint8_t fid[]={0x11,0x22}; - uint8_t keysetting1=0xEE; - uint8_t keysetting2=0xEE; - - if (memcmp(aid, "\x00\x00\x00", 3) == 0) { - PrintAndLogEx(WARNING, _RED_(" Creating root aid 000000 is forbidden")); - return PM3_ESOFT; - } - - aidhdr_t aidhdr; - memcpy(aidhdr.aid, aid, sizeof(aid)); - aidhdr.keysetting1 = keysetting1[0]; - aidhdr.keysetting2 = keysetting2[0]; - - if (usefid) - memcpy(aidhdr.fid, fid, sizeof(aidhdr.fid)); - - if (usename) - memcpy(aidhdr.name, name, sizeof(aidhdr.name)); - - PrintAndLogEx(INFO, "Creating AID using:"); - PrintAndLogEx(INFO, "AID %s", sprint_hex_inrow(aidhdr.aid, sizeof(aidhdr.aid))); - PrintAndLogEx(INFO, "Key set1 0x%02X", aidhdr.keysetting1); - PrintAndLogEx(INFO, "Key Set2 0x%02X", aidhdr.keysetting2); - if (usefid) - PrintAndLogEx(INFO, "FID %s", sprint_hex_inrow(aidhdr.fid, sizeof(aidhdr.fid))); - if (usename) - PrintAndLogEx(INFO, "DF Name %s", aidhdr.name); - - - uint8_t rootaid[3] = {0x00, 0x00, 0x00}; - int res = handler_desfire_select_application(rootaid); - if (res != PM3_SUCCESS) { - DropFieldDesfire(); - return res; - } - - - int res = handler_desfire_createapp(&aidhdr, usename, usefid); - DropFieldDesfire(); - if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Successfully created aid."); - } - return res;*/ } static int CmdHF14ADesDeleteApp(const char *Cmd) { @@ -5387,7 +5234,7 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) { CLIParserInit(&ctx, "hf mfdes deleteaid", "Delete application by its 3-byte AID. Master key needs to be provided. ", "hf mfdes deleteaid --aid 123456 -> execute with default factory setup"); - + void *argtable[] = { arg_param_begin, arg_lit0("a", "apdu", "show APDU requests and responses"), @@ -5419,7 +5266,7 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - + if (appid == 0x000000) { PrintAndLogEx(WARNING, "Deleting the root aid (0x000000) is " _RED_("forbidden")); return PM3_ESOFT; @@ -5449,7 +5296,7 @@ static int CmdHF14ADesGetUID(const char *Cmd) { CLIParserInit(&ctx, "hf mfdes getuid", "Get UID from card. Get the real UID if the random UID bit is on and get the same UID as in anticollision if not. Master key needs to be provided. ", "hf mfdes getuid -> execute with default factory setup"); - + void *argtable[] = { arg_param_begin, arg_lit0("a", "apdu", "show APDU requests and responses"), @@ -5507,7 +5354,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { CLIParserInit(&ctx, "hf mfdes formatpicc", "Format card. Can be done only if enabled in the configuration. Master key needs to be provided. ", "hf mfdes formatpicc -> execute with default factory setup"); - + void *argtable[] = { arg_param_begin, arg_lit0("a", "apdu", "show APDU requests and responses"), @@ -5564,7 +5411,7 @@ static int CmdHF14ADesGetFreeMem(const char *Cmd) { CLIParserInit(&ctx, "hf mfdes getfreemem", "Get card's free memory. Can be doe with ot without authentication. Master key may be provided. ", "hf mfdes getfreemem -> execute with default factory setup"); - + void *argtable[] = { arg_param_begin, arg_lit0("a", "apdu", "show APDU requests and responses"), @@ -5604,7 +5451,7 @@ static int CmdHF14ADesGetFreeMem(const char *Cmd) { PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); DropField(); return res; - } + } } else { res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); if (res != PM3_SUCCESS) { @@ -5783,7 +5630,7 @@ static int CmdHF14ADesGetKeyVersions(const char *Cmd) { uint8_t buf[APDU_RES_LEN] = {0}; size_t buflen = 0; - + uint8_t data[2] = {0}; data[0] = keynum32 & 0xff; if (keysetpresent) { @@ -5808,7 +5655,7 @@ static int CmdHF14ADesGetKeyVersions(const char *Cmd) { } else { PrintAndLogEx(INFO, "No key versions returned."); } - + DropField(); return PM3_SUCCESS; } @@ -5936,7 +5783,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); DropField(); return res; - } + } } else { res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); if (res != PM3_SUCCESS) { @@ -6011,7 +5858,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); DropField(); return res; - } + } } else { res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); if (res != PM3_SUCCESS) { diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 216a62a1a..b0c4d9b8d 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -624,7 +624,7 @@ int DesfireSelectAndAuthenticate(DesfireContext *dctx, DesfireSecureChannel secu } else { return PM3_ESOFT; } - + return PM3_SUCCESS; } @@ -904,7 +904,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel static int DesfireCommandEx(DesfireContext *dctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, int checklength, size_t splitbysize) { if (resplen) *resplen = 0; - + uint8_t respcode = 0xff; uint8_t xresp[257] = {0}; size_t xresplen = 0; @@ -945,9 +945,9 @@ int DesfireFormatPICC(DesfireContext *dctx) { int DesfireGetFreeMem(DesfireContext *dctx, uint32_t *freemem) { *freemem = 0; - + uint8_t resp[257] = {0}; - size_t resplen = 0; + size_t resplen = 0; int res = DesfireCommandRxData(dctx, MFDES_GET_FREE_MEMORY, resp, &resplen, 3); if (res == PM3_SUCCESS) *freemem = DesfireAIDByteToUint(resp); @@ -989,11 +989,15 @@ int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len) { } uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType) { - switch(keyType) { - case T_DES: return 0x00; - case T_3DES: return 0x00; - case T_3K3DES: return 0x01; - case T_AES: return 0x02; + switch (keyType) { + case T_DES: + return 0x00; + case T_3DES: + return 0x00; + case T_3K3DES: + return 0x01; + case T_AES: + return 0x02; } return 0; } From bd96dc48443b48bdd153867be831258d76ce9672 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Jul 2021 18:36:07 +0300 Subject: [PATCH 304/309] small fixes --- client/src/cmdhfmfdes.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index cf347abab..61d8a4193 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5065,7 +5065,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { " 6E = with FID, 3TDEA, 14 keys\n"\ " AE = with FID, AES, 14 keys\n"\ "\n"\ - "hf mfdes createaid --rawdata 123456 -> execute create by rawdata\n"\ + "hf mfdes createaid --rawdata 5634122F2E4523616964313233343536 -> execute create by rawdata\n"\ "hf mfdes createaid --aid 123456 --fid 2345 --dfname aid123456 -> app aid, iso file id, and iso df name is specified\n" "hf mfdes createaid --aid 123456 --fid 2345 --dfname aid123456 --dstalgo aes -> with algorithm for key AES"); @@ -5145,12 +5145,12 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - if (appid == 0x000000) { + if (rawdatalen == 0 && appid == 0x000000) { PrintAndLogEx(ERR, "Creating the root aid (0x000000) is " _RED_("forbidden")); return PM3_ESOFT; } - if ((fileidpresent || (ks2 & 0x20) != 0) && fileid == 0x0000) { + if (rawdatalen == 0 && (fileidpresent || (ks2 & 0x20) != 0) && fileid == 0x0000) { PrintAndLogEx(ERR, "Creating the application with ISO file ID 0x0000 is " _RED_("forbidden")); return PM3_ESOFT; } @@ -5209,7 +5209,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { PrintAndLogEx(INFO, "Key Set 2 0x%02X", data[4]); PrintAndLogEx(INFO, "ISO file ID %s", (data[4] & 0x20) ? "enabled" : "disabled"); if ((data[4] & 0x20)) { - PrintAndLogEx(INFO, "FID 0x%02x%02x", data[5], data[6]); + PrintAndLogEx(INFO, "FID 0x%02x%02x", data[6], data[5]); PrintAndLogEx(INFO, "DF Name[%02d] %s\n", strnlen((char *)&data[7], 16), (char *)&data[7]); } PrintKeySettings(data[3], data[4], true, true); From 1317fa8e32e6da998231d6cafb0353cd6fc23e90 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Jul 2021 18:42:03 +0300 Subject: [PATCH 305/309] command renamings, remove code --- client/src/cmdhfmfdes.c | 183 ++++------------------------------------ 1 file changed, 18 insertions(+), 165 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 61d8a4193..3c4cce49a 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -2294,154 +2294,7 @@ static int CmdHF14ADesSelectApp(const char *Cmd) { } return res; } -/* -static int CmdHF14ADesCreateApp(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes createaid", - "Create Application ID", - "hf mfdes createaid -a 123456 -f 1111 -k 0E -l 2E --name Test" - ); - void *argtable[] = { - arg_param_begin, - arg_strx0("a", "aid", "", "App ID to create as hex bytes (3 hex bytes)"), - arg_strx0("f", "fid", "", "File ID to create"), - arg_strx0("k", "ks1", "", "Key Setting 1 (Application Master Key Settings)"), - arg_strx0("l", "ks2", "", "Key Setting 2"), - arg_str0(NULL, "name", "", "App ISO-4 Name"), - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, false); - KeySetting 1 (AMK Setting): - 0: Allow change master key - 1: Free Directory list access without master key - 0: AMK auth needed for GetFileSettings and GetKeySettings - 1: No AMK auth needed for GetFileIDs, GetISOFileIDs, GetFileSettings, GetKeySettings - 2: Free create/delete without master key - 0: CreateFile/DeleteFile only with AMK auth - 1: CreateFile/DeleteFile always - 3: Configuration changable - 0: Configuration frozen - 1: Configuration changable if authenticated with AMK (default) - 4-7: ChangeKey Access Rights - 0: Application master key needed (default) - 0x1..0xD: Auth with specific key needed to change any key - 0xE: Auth with the key to be changed (same KeyNo) is necessary to change a key - 0xF: All Keys within this application are frozen - - - KeySetting 2: - 0..3: Number of keys stored within the application (max. 14 keys) - 4: RFU - 5: Use of 2 byte ISO FID, 0: No, 1: Yes - 6..7: Crypto Method 00: DES/3DES, 01: 3K3DES, 10: AES - Example: - 2E = FID, DES, 14 keys - 6E = FID, 3K3DES, 14 keys - AE = FID, AES, 14 keys - - int aidlength = 3; - uint8_t aid[3] = {0}; - CLIGetHexWithReturn(ctx, 1, aid, &aidlength); - - int fidlength = 2; - uint8_t fid[2] = {0}; - CLIGetHexWithReturn(ctx, 2, fid, &fidlength); - - int keylen1 = 1; - uint8_t keysetting1[1] = {0}; - CLIGetHexWithReturn(ctx, 3, keysetting1, &keylen1); - - int keylen2 = 1; - uint8_t keysetting2[1] = {0}; - CLIGetHexWithReturn(ctx, 4, keysetting2, &keylen2); - - int namelen = 16; - uint8_t name[16] = {0}; - CLIGetStrWithReturn(ctx, 5, name, &namelen); - CLIParserFree(ctx); - - swap24(aid); - swap16(fid); - - if (aidlength != 3) { - PrintAndLogEx(ERR, "AID must have 3 bytes length"); - return PM3_EINVARG; - } - - if (fidlength != 2 && fidlength != 0) { - PrintAndLogEx(ERR, "FID must have 2 bytes length"); - return PM3_EINVARG; - } - - bool usefid = (fidlength != 0); - - if (keylen1 != 1) { - PrintAndLogEx(ERR, "Keysetting1 must have 1 byte length"); - return PM3_EINVARG; - } - - if (keylen2 != 1) { - PrintAndLogEx(ERR, "Keysetting2 must have 1 byte length"); - return PM3_EINVARG; - } - - if (namelen > 16) { - PrintAndLogEx(ERR, "Name has a max. of 16 bytes length"); - return PM3_EINVARG; - } - bool usename = true; - if (namelen == 0) usename = false; - - //90 ca 00 00 0e 3cb849 09 22 10e1 d27600 00850101 00 - *char name[]="Test"; - uint8_t aid[]={0x12,0x34,0x56}; - uint8_t fid[]={0x11,0x22}; - uint8_t keysetting1=0xEE; - uint8_t keysetting2=0xEE; - - if (memcmp(aid, "\x00\x00\x00", 3) == 0) { - PrintAndLogEx(WARNING, _RED_(" Creating root aid 000000 is forbidden")); - return PM3_ESOFT; - } - - aidhdr_t aidhdr; - memcpy(aidhdr.aid, aid, sizeof(aid)); - aidhdr.keysetting1 = keysetting1[0]; - aidhdr.keysetting2 = keysetting2[0]; - - if (usefid) - memcpy(aidhdr.fid, fid, sizeof(aidhdr.fid)); - - if (usename) - memcpy(aidhdr.name, name, sizeof(aidhdr.name)); - - PrintAndLogEx(INFO, "Creating AID using:"); - PrintAndLogEx(INFO, "AID %s", sprint_hex_inrow(aidhdr.aid, sizeof(aidhdr.aid))); - PrintAndLogEx(INFO, "Key set1 0x%02X", aidhdr.keysetting1); - PrintAndLogEx(INFO, "Key Set2 0x%02X", aidhdr.keysetting2); - if (usefid) - PrintAndLogEx(INFO, "FID %s", sprint_hex_inrow(aidhdr.fid, sizeof(aidhdr.fid))); - if (usename) - PrintAndLogEx(INFO, "DF Name %s", aidhdr.name); - - - uint8_t rootaid[3] = {0x00, 0x00, 0x00}; - int res = handler_desfire_select_application(rootaid); - if (res != PM3_SUCCESS) { - DropFieldDesfire(); - return res; - } - - - int res = handler_desfire_createapp(&aidhdr, usename, usefid); - DropFieldDesfire(); - if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Successfully created aid."); - } - return res; -} -*/ static int selectfile(uint8_t *aid, uint8_t fileno, uint8_t *cs) { if (handler_desfire_select_application(aid) != PM3_SUCCESS) { PrintAndLogEx(ERR, _RED_(" Couldn't select aid.")); @@ -5034,7 +4887,7 @@ static int CmdHF14ADesDefault(const char *Cmd) { static int CmdHF14ADesCreateApp(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes createaid", + CLIParserInit(&ctx, "hf mfdes createapp", "Create application. Master key needs to be provided.", "option rawdata have priority over the rest settings, and options ks1 and ks2 have priority over corresponded key settings\n" "\n"\ @@ -5065,9 +4918,9 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { " 6E = with FID, 3TDEA, 14 keys\n"\ " AE = with FID, AES, 14 keys\n"\ "\n"\ - "hf mfdes createaid --rawdata 5634122F2E4523616964313233343536 -> execute create by rawdata\n"\ - "hf mfdes createaid --aid 123456 --fid 2345 --dfname aid123456 -> app aid, iso file id, and iso df name is specified\n" - "hf mfdes createaid --aid 123456 --fid 2345 --dfname aid123456 --dstalgo aes -> with algorithm for key AES"); + "hf mfdes createapp --rawdata 5634122F2E4523616964313233343536 -> execute create by rawdata\n"\ + "hf mfdes createapp --aid 123456 --fid 2345 --dfname aid123456 -> app aid, iso file id, and iso df name is specified\n" + "hf mfdes createapp --aid 123456 --fid 2345 --dfname aid123456 --dstalgo aes -> with algorithm for key AES"); void *argtable[] = { arg_param_begin, @@ -5231,9 +5084,9 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { static int CmdHF14ADesDeleteApp(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes deleteaid", + CLIParserInit(&ctx, "hf mfdes deleteapp", "Delete application by its 3-byte AID. Master key needs to be provided. ", - "hf mfdes deleteaid --aid 123456 -> execute with default factory setup"); + "hf mfdes deleteapp --aid 123456 -> execute with default factory setup"); void *argtable[] = { arg_param_begin, @@ -5250,7 +5103,7 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) { arg_str0(NULL, "aid", "", "Application ID of delegated application (3 hex bytes, big endian)"), arg_param_end }; - CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIExecWithReturn(ctx, Cmd, argtable, false); bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); @@ -5409,7 +5262,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { static int CmdHF14ADesGetFreeMem(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes getfreemem", - "Get card's free memory. Can be doe with ot without authentication. Master key may be provided. ", + "Get card's free memory. Can be done with ot without authentication. Master key may be provided.", "hf mfdes getfreemem -> execute with default factory setup"); void *argtable[] = { @@ -5477,10 +5330,10 @@ static int CmdHF14ADesGetFreeMem(const char *Cmd) { static int CmdHF14ADesChKeySettings(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes chkeysetings", + CLIParserInit(&ctx, "hf mfdes chkeysettings", "Change key settings for card level or application level. WARNING: card level changes may block the card!", - "hf mfdes chkeysetings -d 0f -> set picc key settings with default key/channel setup\n"\ - "hf mfdes chkeysetings --aid 123456 -d 0f -> set app 123456 key settings with default key/channel setup"); + "hf mfdes chkeysettings -d 0f -> set picc key settings with default key/channel setup\n"\ + "hf mfdes chkeysettings --aid 123456 -d 0f -> set app 123456 key settings with default key/channel setup"); void *argtable[] = { arg_param_begin, @@ -5662,10 +5515,10 @@ static int CmdHF14ADesGetKeyVersions(const char *Cmd) { static int CmdHF14ADesGetKeySettings(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes getkeysetings", + CLIParserInit(&ctx, "hf mfdes getkeysettings", "Get key settings for card level or application level.", - "hf mfdes getkeysetings -> get picc key settings with default key/channel setup\n"\ - "hf mfdes getkeysetings --aid 123456 -> get app 123456 key settings with default key/channel setup"); + "hf mfdes getkeysettings -> get picc key settings with default key/channel setup\n"\ + "hf mfdes getkeysettings --aid 123456 -> get app 123456 key settings with default key/channel setup"); void *argtable[] = { arg_param_begin, @@ -5915,13 +5768,13 @@ static command_t CommandTable[] = { // {"mad", CmdHF14aDesMAD, IfPm3Iso14443a, "Prints MAD records from card"}, {"-----------", CmdHelp, IfPm3Iso14443a, "------------------------ " _CYAN_("Keys") " -----------------------"}, {"changekey", CmdHF14ADesChangeKey, IfPm3Iso14443a, "Change Key"}, - {"chkeysetings", CmdHF14ADesChKeySettings, IfPm3Iso14443a, "[new]Change Key Settings"}, - {"getkeysetings", CmdHF14ADesGetKeySettings, IfPm3Iso14443a, "[new]Get Key Settings"}, + {"chkeysettings", CmdHF14ADesChKeySettings, IfPm3Iso14443a, "[new]Change Key Settings"}, + {"getkeysettings", CmdHF14ADesGetKeySettings, IfPm3Iso14443a, "[new]Get Key Settings"}, {"getkeyversions", CmdHF14ADesGetKeyVersions, IfPm3Iso14443a, "[new]Get Key Versions"}, {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("Applications") " -------------------"}, {"bruteaid", CmdHF14ADesBruteApps, IfPm3Iso14443a, "Recover AIDs by bruteforce"}, - {"createaid", CmdHF14ADesCreateApp, IfPm3Iso14443a, "[new]Create Application ID"}, - {"deleteaid", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "[new]Delete Application ID"}, + {"createapp", CmdHF14ADesCreateApp, IfPm3Iso14443a, "[new]Create Application"}, + {"deleteapp", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "[new]Delete Application"}, {"selectaid", CmdHF14ADesSelectApp, IfPm3Iso14443a, "Select Application ID"}, {"getaids", CmdHF14ADesGetAIDs, IfPm3Iso14443a, "[new]Get Application IDs list"}, {"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "[new]Get Applications list"}, From d7da384f69799d6dc1eaf360185ed5c193a747be Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 14 Jul 2021 01:35:18 +0200 Subject: [PATCH 306/309] CMake and cross-compilation: restrict CFLAGS=--target to Android (probably to clang) --- client/CMakeLists.txt | 4 +++- client/experimental_lib/CMakeLists.txt | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index c7892ba7c..21ebf9efd 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -76,7 +76,9 @@ endif (NOT SKIPPYTHON EQUAL 1) # If cross-compiled, we need to init source and build. if (CMAKE_TOOLCHAIN_FILE) - set(CFLAGS_EXTERNAL_LIB "CFLAGS=--target=${CMAKE_C_COMPILER_TARGET} -w") + if (ANDROID) + set(CFLAGS_EXTERNAL_LIB "CFLAGS=--target=${CMAKE_C_COMPILER_TARGET} -w") + endif (ANDROID) set(EMBED_READLINE ON) set(EMBED_BZIP2 ON) endif (CMAKE_TOOLCHAIN_FILE) diff --git a/client/experimental_lib/CMakeLists.txt b/client/experimental_lib/CMakeLists.txt index 084259d34..dcf17a367 100644 --- a/client/experimental_lib/CMakeLists.txt +++ b/client/experimental_lib/CMakeLists.txt @@ -76,7 +76,9 @@ endif (NOT SKIPPYTHON EQUAL 1) # If cross-compiled, we need to init source and build. if (CMAKE_TOOLCHAIN_FILE) - set(CFLAGS_EXTERNAL_LIB "CFLAGS=--target=${CMAKE_C_COMPILER_TARGET} -w") + if (ANDROID) + set(CFLAGS_EXTERNAL_LIB "CFLAGS=--target=${CMAKE_C_COMPILER_TARGET} -w") + endif (ANDROID) set(EMBED_READLINE ON) set(EMBED_BZIP2 ON) endif (CMAKE_TOOLCHAIN_FILE) From 28eec73445237638e57b5f3c0a09ea524cdf028c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 14 Jul 2021 09:57:16 +0200 Subject: [PATCH 307/309] added a client preference for delay of execution. This a global delay before each command is parsed. You can unset it with by setting delay to ZERO. The purpose of this setting is for users who want to use the pm3 against a implanted implant where you have to get a good position and arrange the pm3 while pressing . --- CHANGELOG.md | 1 + client/src/cmdmain.c | 2 +- client/src/cmdparser.c | 6 ++++ client/src/preferences.c | 60 +++++++++++++++++++++++++++++++++++++++- client/src/ui.h | 1 + 5 files changed, 68 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f01b04150..3d8fd7363 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added a new client preference, delay of execution, a delay in ms before a cmd is sent. Good for implants (@iceman1001) - Fix `lf t55xx brute` - now correctly prints last key if it was correct (@scott4290) - Added support python scripts (@salmg) - Add new standalone mode `hf_reblay` - relay 14a over bt (@salmg) diff --git a/client/src/cmdmain.c b/client/src/cmdmain.c index f291b6dfb..8b7c6b29f 100644 --- a/client/src/cmdmain.c +++ b/client/src/cmdmain.c @@ -17,7 +17,7 @@ #include #include -#include // MingW +#include // MingW #include // calloc #include "comms.h" diff --git a/client/src/cmdparser.c b/client/src/cmdparser.c index f67e18608..0d79ebc36 100644 --- a/client/src/cmdparser.c +++ b/client/src/cmdparser.c @@ -15,6 +15,7 @@ #include "ui.h" #include "comms.h" +#include "util_posix.h" // msleep bool AlwaysAvailable(void) { return true; @@ -193,6 +194,11 @@ void CmdsHelp(const command_t Commands[]) { } int CmdsParse(const command_t Commands[], const char *Cmd) { + + if (session.client_exe_delay != 0) { + msleep(session.client_exe_delay); + } + // Help dump children if (strcmp(Cmd, "XX_internal_command_dump_XX") == 0) { dumpCommandsRecursive(Commands, 0, false); diff --git a/client/src/preferences.c b/client/src/preferences.c index 3228498f4..f34d535e3 100644 --- a/client/src/preferences.c +++ b/client/src/preferences.c @@ -243,6 +243,8 @@ void preferences_save_callback(json_t *root) { JsonSaveStr(root, "logging.level", "NORMAL"); } */ + JsonSaveInt(root, "client.exe.delay", session.client_exe_delay); + } void preferences_load_callback(json_t *root) { json_error_t up_error = {0}; @@ -331,6 +333,9 @@ void preferences_load_callback(json_t *root) { if (strncmp(tempStr, "extended", 8) == 0) session.device_debug_level = ddbEXTENDED; } */ + // client command execution delay + if (json_unpack_ex(root, &up_error, 0, "{s:i}", "client.exe.delay", &i1) == 0) + session.client_exe_delay = i1; } // Help Functions @@ -502,6 +507,11 @@ static void showBarModeState(prefShowOpt_t opt) { } } +static void showClientExeDelayState(void) { + PrintAndLogEx(INFO, " Cmd execution delay.... "_GREEN_("%u"), session.client_exe_delay); +} + + static int setCmdEmoji(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "prefs set emoji ", @@ -718,6 +728,35 @@ static int setCmdDeviceDebug (const char *Cmd) } */ + +static int setCmdExeDelay(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "prefs set clientdelay", + "Set presistent preference of delay before executing a command in the client", + "prefs set clientdelay --ms 0 --> unsets any delay\n" + "prefs set clientdelay --ms 1000 --> sets 1000ms delay" + ); + + void *argtable[] = { + arg_param_begin, + arg_int0(NULL, "ms", "", "delay in micro seconds"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + uint16_t new_value = (uint16_t)arg_get_int_def(ctx, 1, 0); + CLIParserFree(ctx); + + if (session.client_exe_delay != new_value) { + showClientExeDelayState(); + session.client_exe_delay = new_value; + showClientExeDelayState(); + preferences_save(); + } else { + showClientExeDelayState(); + } + return PM3_SUCCESS; +} + static int setCmdHint(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "prefs set hints ", @@ -1045,9 +1084,26 @@ static int getCmdSavePaths(const char *Cmd) { return PM3_SUCCESS; } +static int getCmdExeDelay(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "prefs get clientdelay", + "Get preference of delay time before execution of a command in the client", + "prefs get clientdelay" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + showClientExeDelayState(); + return PM3_SUCCESS; +} + static command_t CommandTableGet[] = { {"barmode", getCmdBarMode, AlwaysAvailable, "Get bar mode preference"}, {"clientdebug", getCmdDebug, AlwaysAvailable, "Get client debug level preference"}, + {"clientdelay", getCmdExeDelay, AlwaysAvailable, "Get client execution delay preference"}, {"color", getCmdColor, AlwaysAvailable, "Get color support preference"}, {"savepaths", getCmdSavePaths, AlwaysAvailable, "Get file folder "}, // {"devicedebug", getCmdDeviceDebug, AlwaysAvailable, "Get device debug level"}, @@ -1061,6 +1117,7 @@ static command_t CommandTableSet[] = { {"help", setCmdHelp, AlwaysAvailable, "This help"}, {"barmode", setCmdBarMode, AlwaysAvailable, "Set bar mode"}, {"clientdebug", setCmdDebug, AlwaysAvailable, "Set client debug level"}, + {"clientdelay", setCmdExeDelay, AlwaysAvailable, "Set client execution delay"}, {"color", setCmdColor, AlwaysAvailable, "Set color support"}, {"emoji", setCmdEmoji, AlwaysAvailable, "Set emoji display"}, {"hints", setCmdHint, AlwaysAvailable, "Set hint display"}, @@ -1120,8 +1177,9 @@ static int CmdPrefShow(const char *Cmd) { showClientDebugState(prefShowNone); showPlotSliderState(prefShowNone); // showDeviceDebugState(prefShowNone); - showBarModeState(prefShowNone); + showClientExeDelayState(); + PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } diff --git a/client/src/ui.h b/client/src/ui.h index 632a818d3..21ad74be7 100644 --- a/client/src/ui.h +++ b/client/src/ui.h @@ -48,6 +48,7 @@ typedef struct { clientdebugLevel_t client_debug_level; barMode_t bar_mode; // uint8_t device_debug_level; + uint16_t client_exe_delay; char *history_path; pm3_device *current_device; } session_arg_t; From 67a3a3fbb905d25ca65dbe8c8c550ffc04e1b994 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 14 Jul 2021 09:58:04 +0200 Subject: [PATCH 308/309] text --- .../Windows-Installation-Instructions.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md index b31e0773b..123d415d5 100644 --- a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md @@ -20,7 +20,7 @@ We have listed three ways to use these two setups (dev environment vs pre-compi ^[Top](#top) ## Video Installation guide -_note: this video is a bit out-of-date but still informative_ +_note: this video is out-of-date but still informative_ [![Windows Installation tutorial](https://raw.githubusercontent.com/Chrissy-Morgan/Proxmark3-RDV4-ParrotOS/master/screenshot-www.youtube.com-2019.03.17-20-44-33.png)](https://youtu.be/zzF0NCMJnYU "Windows Installation Tutorial") ## Driver Installation ( Windows 7 ) @@ -107,7 +107,9 @@ Make sure your WSL can launch Windows processes to get the `pm3` scripts working ## X Server Installation -If you want to run the graphical components of the Proxmark3 client, you need to install a X Server such as [VcXsrv](https://sourceforge.net/projects/vcxsrv/) or [Xming](https://sourceforge.net/projects/xming/) and launch it, e.g. by executing XLaunch. +If you want to run the graphical components of the Proxmark3 client, you need to install a X Server such as in the list below, and launch it, e.g. by executing XLaunch. + * [VcXsrv](https://sourceforge.net/projects/vcxsrv/) + * [Xming](https://sourceforge.net/projects/xming/) ## Windows Terminal Installation @@ -117,7 +119,7 @@ It is also open sourced (see [github.com/microsoft/terminal](https://github.com/ ## Dependencies -Enter WSL prompt (`wsl` or Start Windows Terminal) and from there, follow the [Linux Installation Instructions](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) for Ubuntu, summarized here below: +Enter WSL prompt (`wsl` or Start Windows Terminal with `wt`) and from there, follow the [Linux Installation Instructions](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) for Ubuntu, summarized here below: Make sure your WSL guest OS is up-to-date first: From 8073930129815be445daf34d310a08d6e236afdb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 14 Jul 2021 10:37:22 +0200 Subject: [PATCH 309/309] maur pwd --- client/dictionaries/t55xx_default_pwds.dic | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/dictionaries/t55xx_default_pwds.dic b/client/dictionaries/t55xx_default_pwds.dic index beeeca8cf..65e0ebbc2 100644 --- a/client/dictionaries/t55xx_default_pwds.dic +++ b/client/dictionaries/t55xx_default_pwds.dic @@ -40,6 +40,8 @@ E9920427 20206666 # ID/HID CARD COPER SK-663 65857569 +# password found on discord +5469616E # Default pwd, simple: 00000000 11111111