diff --git a/CHANGELOG.md b/CHANGELOG.md index 77ac7f3c5..5c7014d3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,34 +2,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] -- Changed from Bigbuf malloc to Bigbuf calloc calls on device side (@iceman1001) -- Added `lf t55xx view` - now viewing of T55XX dump files is possible (@iceman1001) -- Fixed `lf indala cone` - now writing the right bits when using `--fc` and `--cn` -- Changed readline hack logic for async dbg msg to be ready for readline 8.3 (@doegox) -- Improved To avoid conflicts with ModemManager on Linux, is recommended to masking the service (@grugnoymeme) -- Changed `data crypto` - now also handles AES-256 (@iceman1001) -- Changed `hf mfdes info` - add recognition of Swissbit iShield Key Mifare (@ah01) -- Changed `hf mf info` - add detection for unknown backdoor keys and for some backdoor variants (@doegox) -- Changed `mqtt` commnands - now honors preference settings (@iceman1001) -- Changed `prefs` - now handles MQTT settings too (@iceman1001) -- Fixed `mqtt` segfault and gdb warning under windows (proper thread stopping and socket handling). (@virtyvoid) -- Added `mqtt` - the pm3 client can now send and receive MQTT messages or json files. (@iceman1001) -- Changed `hf iclass wrbl` - replay behavior to use privilege escalation if the macs field is not passed empty(@antiklesys) -- Changed `hf iclass restore` - it now supports privilege escalation to restore card content using replay (@antiklesys) -- Fixed `hf 15 dump` - now reads sysinfo response correct (@iceman1001) -- Changed `make clean` - it now removes all __pycache__ folders (@iceman1001) -- Fixed `hf 15 readmulti` - fix block calculations (@iceman1001) -- Changed `mem load` - now handles UL-C and UL-AES dictionary files (@iceman1001) -- Changed `hf mfu sim` - now support UL-C simulation (@iceman1001) -- Added `!` - run system commands from inside the client. Potentially dangerous if running client as SUDO, SU, ROOT (@iceman1001) -- Implemented `hf felica scsvcode` - now dumps all service and area codes. (@zinongli) -- Added `hf felica liteauth` - now support FeliCa Lite-S authentication(@q0jt) -- Added `he felica dump` - partial support for dumping all blocks from unauth readable services (@zinongli) -- Changed `hf 14b calypso` - now don't break the file id loop when one file can't be selected or read. Add new file ids to iterate through (@zinongli) - - -## [Daddy Iceman.4.20469][2025-06-16] +## [Daddy Iceman][2025-06-16] - Fixed edge case in fm11rf08s key recovery tools (@doegox) - Removed `--par` from `lf em 4x70` commands. - Changed `hf 14a info` - refactored code to be able to detect card technology across the client easier (@iceman1001) diff --git a/Makefile b/Makefile index c985246d5..8518bbd61 100644 --- a/Makefile +++ b/Makefile @@ -32,9 +32,6 @@ endif all clean install uninstall check: %: client/% bootrom/% armsrc/% recovery/% mfc_card_only/% mfc_card_reader/% mfd_aes_brute/% fpga_compress/% cryptorf/% # hitag2crack toolsuite is not yet integrated in "all", it must be called explicitly: "make hitag2crack" #all clean install uninstall check: %: hitag2crack/% -clean: %: hitag2crack/% - find . -type d -name __pycache__ -exec rm -rfv \{\} + - INSTALLTOOLS=mfc/pm3_eml2lower.sh mfc/pm3_eml2upper.sh mfc/pm3_mfdread.py mfc/pm3_mfd2eml.py mfc/pm3_eml2mfd.py pm3_amii_bin2eml.pl pm3_reblay-emulating.py pm3_reblay-reading.py INSTALLSIMFW=sim011.bin sim011.sha512.txt sim013.bin sim013.sha512.txt sim014.bin sim014.sha512.txt @@ -372,12 +369,10 @@ release: @echo "# - Release Tag: $(VERSION)" @echo "# - Release Name: $(RELEASE_NAME)" # - Removing -Werror... - @find . \( -path "./Makefile.defs" -or -path "./client/Makefile" -or -path "./common_arm/Makefile.common" -or -path "./tools/hitag2crack/*/Makefile" -or -path "./client/deps/*/Makefile" \) -exec sed -i 's/ -Werror//' {} \; - @find . \( -path "./client/deps/*.cmake" -or -path "./client/CMakeLists.txt" -or -path "./client/experimental_lib/CMakeLists.txt" \) -exec sed -i 's/ -Werror//' {} \; + @find . \( -path "./Makefile.defs" -or -path "./client/Makefile" -or -path "./common_arm/Makefile.common" -or -path "./tools/hitag2crack/*/Makefile" \) -exec sed -i 's/ -Werror//' {} \; + @find . \( -path "./client/deps/*.cmake" -or -path "./client/CMakeLists.txt" \) -exec sed -i 's/ -Werror//' {} \; # - Changing banner... - @sed -i "s/^#define BANNERMSG2 .*/#define BANNERMSG2 \" -----------------------------------\"/" client/src/proxmark3.c @sed -i "s/^#define BANNERMSG3 .*/#define BANNERMSG3 \"Release $(VERSION) - $(RELEASE_NAME)\"/" client/src/proxmark3.c - @echo -n "# ";grep "^#define BANNERMSG2" client/src/proxmark3.c @echo -n "# ";grep "^#define BANNERMSG3" client/src/proxmark3.c # - Committing temporarily... @git commit -a -m "Release $(VERSION) - $(RELEASE_NAME)" diff --git a/Makefile.defs b/Makefile.defs index 2496057fa..0d6066489 100644 --- a/Makefile.defs +++ b/Makefile.defs @@ -112,8 +112,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/Makefile.platform.sample b/Makefile.platform.sample index b8850e76d..fb5114f5f 100644 --- a/Makefile.platform.sample +++ b/Makefile.platform.sample @@ -5,7 +5,7 @@ # Comment the line below and uncomment further down according to which device you have PLATFORM=PM3RDV4 -# For PM3 RDV1, RDV2, Easy or rysccorps etc +# For PM3 Easy: # uncomment the line below #PLATFORM=PM3GENERIC @@ -22,8 +22,8 @@ PLATFORM=PM3RDV4 #PLATFORM_EXTRAS=BTADDON #PLATFORM_EXTRAS=FLASH #PLATFORM_EXTRAS=SMARTCARD -#PLATFORM_EXTRAS=BTADDON FPC_USART_DEV FLASH -#STANDALONE=HF_UNISNIFF +#PLATFORM_EXTRAS=BTADDON FLASH +#STANDALONE=LF_SAMYRUN # Uncomment the line below to set the correct LED order on board Proxmark3 Easy diff --git a/README.md b/README.md index 9418c837a..64ae86137 100644 --- a/README.md +++ b/README.md @@ -60,8 +60,7 @@ The Proxmark3 is the swiss-army tool of RFID, allowing for interactions with the |[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode)|[Notes on Magic UID cards](/doc/magic_cards_notes.md)| |[Notes on Color usage](/doc/colors_notes.md)|[Makefile vs CMake](/doc/md/Development/Makefile-vs-CMake.md)|[Notes on Cloner guns](/doc/cloner_notes.md)| |[Notes on cliparser usage](/doc/cliparser.md)|[Notes on clocks](/doc/clocks.md)|[Notes on MIFARE DESFire](/doc/desfire.md)| -|[Notes on CIPURSE](/doc/cipurse.md)|[Notes on NDEF type4a](/doc/ndef_type4a.md)|[Unofficial MIFARE DESFire bible](/doc/unofficial_desfire_bible.md)| -[Notes on downgrade attacks](/doc/hid_downgrade.md)||| +|[Notes on CIPURSE](/doc/cipurse.md)|[Notes on NDEF type4a](/doc/ndef_type4a.md)|[Notes on downgrade attacks](/doc/hid_downgrade.md)| # How to build? @@ -97,14 +96,12 @@ We define generic Proxmark3 platforms as following devices. - **Note**: currently incompatible with iCopy-X GUI as Proxmark client commands using different syntax - **Note**: see also [icopyx-community repos](https://github.com/iCopy-X-Community/) for upstream sources, reversed hw etc. - **Note**: Uses DRM to lock down tags, ignores the open source licences. Use on your own risk. -- ⚠ Proxmark3 Ultimate - - **Note**: unknown device hw - - **Note**: FPGA images is building for it. Use on your own risk. **Unknown support status** - ⚠ VX - **Note**: unknown device hw - +- ⚠ Proxmark3 Ultimate + - **Note**: unknown device hw When it comes to these new unknown models we are depending on the community to report in if this repo works and what they did to make it work. @@ -183,11 +180,10 @@ We usually merge your contributions fast since we do like the idea of getting a The [public roadmap](https://github.com/RfidResearchGroup/proxmark3/wiki/Public-Roadmap) is an excellent start to read if you are interesting in contributing. -## Supported operating systems +## Supported operative systems This repo compiles nicely on - WSL1 on Windows 10 - - WSL2 on Windows 10/11 - Proxspace environment [release v3.xx](https://github.com/Gator96100/ProxSpace/releases) - Windows/MinGW environment - Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, NetHunter, Arch Linux, Fedora, Debian, Raspbian diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index d3478db53..b492b4205 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -354,7 +354,7 @@ int emlGet(uint8_t *out, uint32_t offset, uint32_t length) { tosend_t *get_tosend(void) { if (s_toSend.buf == NULL) { - s_toSend.buf = BigBuf_calloc(TOSEND_BUFFER_SIZE); + s_toSend.buf = BigBuf_malloc(TOSEND_BUFFER_SIZE); } return &s_toSend; } @@ -377,9 +377,8 @@ void tosend_stuffbit(int b) { s_toSend.bit = 0; } - if (b) { + if (b) s_toSend.buf[s_toSend.max] |= (1 << (7 - s_toSend.bit)); - } s_toSend.bit++; @@ -390,14 +389,15 @@ void tosend_stuffbit(int b) { dmabuf16_t *get_dma16(void) { if (s_dma_16.buf == NULL) { - s_dma_16.buf = (uint16_t *)BigBuf_calloc(DMA_BUFFER_SIZE * sizeof(uint16_t)); + s_dma_16.buf = (uint16_t *)BigBuf_malloc(DMA_BUFFER_SIZE * sizeof(uint16_t)); } + return &s_dma_16; } dmabuf8_t *get_dma8(void) { - if (s_dma_8.buf == NULL) { - s_dma_8.buf = BigBuf_calloc(DMA_BUFFER_SIZE); - } + if (s_dma_8.buf == NULL) + s_dma_8.buf = BigBuf_malloc(DMA_BUFFER_SIZE); + return &s_dma_8; } diff --git a/armsrc/Makefile b/armsrc/Makefile index 9929b3ae3..0f83596be 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -186,7 +186,7 @@ showinfo: # version_pm3.c should be checked 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) .FORCE $(info [-] CHECK $@) - $(Q)$(SH) ../tools/mkversion.sh $@ || $(CP) $< $@ + $(Q)$(CP) $< $@ fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) $(info [-] GEN $@) diff --git a/armsrc/Standalone/hf_aveful.c b/armsrc/Standalone/hf_aveful.c index d634f819c..626aa9d17 100644 --- a/armsrc/Standalone/hf_aveful.c +++ b/armsrc/Standalone/hf_aveful.c @@ -157,7 +157,7 @@ void RunMod(void) { if (button_pressed != BUTTON_NO_CLICK || data_available()) break; else if (state == STATE_SEARCH) { - if (iso14443a_select_card(NULL, &card, NULL, true, 0, true) == 0) { + if (!iso14443a_select_card(NULL, &card, NULL, true, 0, true)) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); SpinDelay(500); @@ -246,7 +246,7 @@ void RunMod(void) { FLAG_SET_UID_IN_DATA(flags, 7); Dbprintf("Starting simulation, press " _GREEN_("pm3 button") " to stop and go back to search state."); - SimulateIso14443aTag(7, flags, card.uid, 0, NULL, 0, false, false); + SimulateIso14443aTag(7, flags, card.uid, 0, NULL, 0); // Go back to search state if user presses pm3-button state = STATE_SEARCH; diff --git a/armsrc/Standalone/hf_bog.c b/armsrc/Standalone/hf_bog.c index d5d94fe0f..fe607f021 100644 --- a/armsrc/Standalone/hf_bog.c +++ b/armsrc/Standalone/hf_bog.c @@ -63,18 +63,18 @@ static void RAMFUNC SniffAndStore(uint8_t param) { set_tracing(true); // Array to store the authpwds - uint8_t *capturedPwds = BigBuf_calloc(4 * MAX_PWDS_PER_SESSION); + uint8_t *capturedPwds = BigBuf_malloc(4 * MAX_PWDS_PER_SESSION); // The command (reader -> tag) that we're receiving. - uint8_t *receivedCmd = BigBuf_calloc(MAX_FRAME_SIZE); - uint8_t *receivedCmdPar = BigBuf_calloc(MAX_PARITY_SIZE); + uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); + uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE); // The response (tag -> reader) that we're receiving. - uint8_t *receivedResp = BigBuf_calloc(MAX_FRAME_SIZE); - uint8_t *receivedRespPar = BigBuf_calloc(MAX_PARITY_SIZE); + uint8_t *receivedResp = BigBuf_malloc(MAX_FRAME_SIZE); + uint8_t *receivedRespPar = BigBuf_malloc(MAX_PARITY_SIZE); // The DMA buffer, used to stream samples from the FPGA - uint8_t *dmaBuf = BigBuf_calloc(DMA_BUFFER_SIZE); + uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); uint8_t *data = dmaBuf; uint8_t previous_data = 0; diff --git a/armsrc/Standalone/hf_cardhopper.c b/armsrc/Standalone/hf_cardhopper.c index d199dcdab..167e5b52f 100644 --- a/armsrc/Standalone/hf_cardhopper.c +++ b/armsrc/Standalone/hf_cardhopper.c @@ -234,7 +234,7 @@ static void become_card(void) { tag_response_info_t *canned; uint32_t cuid; uint8_t pages; - if (SimulateIso14443aInit(tagType, flags, data, NULL, 0, &canned, &cuid, &pages, NULL) == false) { + if (SimulateIso14443aInit(tagType, flags, data, NULL, 0, &canned, &cuid, &pages) == false) { DbpString(_RED_("Error initializing the emulation process!")); return; } diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index a5b761899..423e093f6 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -250,7 +250,7 @@ static char *ReadSchemasFromSPIFFS(char *filename) { int changed = rdv40_spiffs_lazy_mount(); uint32_t size = size_in_spiffs((char *)filename); - uint8_t *mem = BigBuf_calloc(size); + uint8_t *mem = BigBuf_malloc(size); rdv40_spiffs_read_as_filetype((char *)filename, (uint8_t *)mem, size, RDV40_SPIFFS_SAFETY_SAFE); if (changed) { @@ -292,7 +292,7 @@ static void ReadLastTagFromFlash(void) { DbprintfEx(FLAG_NEWLINE, "Button HELD ! Using LAST Known TAG for Simulation..."); cjSetCursLeft(); - uint8_t *mem = BigBuf_calloc(size); + uint8_t *mem = BigBuf_malloc(size); // this one will handle filetype (symlink or not) and resolving by itself rdv40_spiffs_read_as_filetype((char *)HFCOLIN_LASTTAG_SYMLINK, (uint8_t *)mem, len, RDV40_SPIFFS_SAFETY_SAFE); @@ -445,11 +445,11 @@ void RunMod(void) { }; // Can remember something like that in case of Bigbuf - keyBlock = BigBuf_calloc(ARRAYLEN(mfKeys) * MF_KEY_LENGTH); + keyBlock = BigBuf_malloc(ARRAYLEN(mfKeys) * 6); int mfKeysCnt = ARRAYLEN(mfKeys); for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) { - num_to_bytes(mfKeys[mfKeyCounter], MF_KEY_LENGTH, (uint8_t *)(keyBlock + (mfKeyCounter * MF_KEY_LENGTH))); + num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6)); } // TODO : remember why we actually had need to initialize this array in such specific case @@ -498,7 +498,7 @@ failtag: SpinOff(50); LED_A_ON(); - while (iso14443a_select_card(colin_cjuid, &colin_p_card, &colin_cjcuid, true, 0, true) == 0) { + while (!iso14443a_select_card(colin_cjuid, &colin_p_card, &colin_cjcuid, true, 0, true)) { WDT_HIT(); if (BUTTON_HELD(10) == BUTTON_HOLD) { WDT_HIT(); @@ -785,7 +785,7 @@ static int e_MifareECardLoad(uint32_t numofsectors, uint8_t keytype) { bool isOK = true; - if (iso14443a_select_card(colin_cjuid, &colin_p_card, &colin_cjcuid, true, 0, true) == 0) { + if (!iso14443a_select_card(colin_cjuid, &colin_p_card, &colin_cjcuid, true, 0, true)) { isOK = false; } @@ -844,7 +844,8 @@ static int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTr for (uint8_t i = 0; i < keyCount; i++) { /* no need for anticollision. just verify tag is still here */ - if (iso14443a_select_card(colin_cjuid, &colin_p_card, &colin_cjcuid, true, 0, true) == 0) { + // if (!iso14443a_fast_select_card(colin_cjuid, 0)) { + if (!iso14443a_select_card(colin_cjuid, &colin_p_card, &colin_cjcuid, true, 0, true)) { cjSetCursLeft(); DbprintfEx(FLAG_NEWLINE, "%sFATAL%s : E_MF_LOSTTAG", _XRED_, _XWHITE_); break; @@ -962,7 +963,7 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, const // get UID from chip if (workFlags & 0x01) { - if (iso14443a_select_card(colin_cjuid, &colin_p_card, &colin_cjcuid, true, 0, true) == 0) { + if (!iso14443a_select_card(colin_cjuid, &colin_p_card, &colin_cjcuid, true, 0, true)) { DbprintfEx(FLAG_NEWLINE, "Can't select card"); break; }; diff --git a/armsrc/Standalone/hf_craftbyte.c b/armsrc/Standalone/hf_craftbyte.c index 736e89aca..6eb2ae2a2 100644 --- a/armsrc/Standalone/hf_craftbyte.c +++ b/armsrc/Standalone/hf_craftbyte.c @@ -89,22 +89,22 @@ void RunMod(void) { Dbprintf("Starting simulation, press " _GREEN_("pm3 button") " to stop and go back to search state."); if (card.sak == 0x08 && card.atqa[0] == 0x04 && card.atqa[1] == 0) { DbpString("Mifare Classic 1k"); - SimulateIso14443aTag(1, flags, card.uid, 0, NULL, 0, false, false); + SimulateIso14443aTag(1, flags, card.uid, 0, NULL, 0); } else if (card.sak == 0x08 && card.atqa[0] == 0x44 && card.atqa[1] == 0) { DbpString("Mifare Classic 4k "); - SimulateIso14443aTag(8, flags, card.uid, 0, NULL, 0, false, false); + SimulateIso14443aTag(8, flags, card.uid, 0, NULL, 0); } else if (card.sak == 0x00 && card.atqa[0] == 0x44 && card.atqa[1] == 0) { DbpString("Mifare Ultralight"); - SimulateIso14443aTag(2, flags, card.uid, 0, NULL, 0, false, false); + SimulateIso14443aTag(2, flags, card.uid, 0, NULL, 0); } else if (card.sak == 0x20 && card.atqa[0] == 0x04 && card.atqa[1] == 0x03) { DbpString("Mifare DESFire"); - SimulateIso14443aTag(3, flags, card.uid, 0, NULL, 0, false, false); + SimulateIso14443aTag(3, flags, card.uid, 0, NULL, 0); } else if (card.sak == 0x20 && card.atqa[0] == 0x44 && card.atqa[1] == 0x03) { DbpString("Mifare DESFire Ev1/Plus/JCOP"); - SimulateIso14443aTag(3, flags, card.uid, 0, NULL, 0, false, false); + SimulateIso14443aTag(3, flags, card.uid, 0, NULL, 0); } else { Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation"); - SimulateIso14443aTag(1, flags, card.uid, 0, NULL, 0, false, false); + SimulateIso14443aTag(1, flags, card.uid, 0, NULL, 0); } // Go back to search state if user presses pm3-button diff --git a/armsrc/Standalone/hf_iceclass.c b/armsrc/Standalone/hf_iceclass.c index db7b922ac..c657d2e03 100644 --- a/armsrc/Standalone/hf_iceclass.c +++ b/armsrc/Standalone/hf_iceclass.c @@ -238,7 +238,7 @@ static int reader_attack_mode(void) { BigBuf_free(); uint16_t mac_response_len = 0; - uint8_t *mac_responses = BigBuf_calloc(MAC_RESPONSES_SIZE); + uint8_t *mac_responses = BigBuf_malloc(MAC_RESPONSES_SIZE); iclass_simulate(ICLASS_SIM_MODE_READER_ATTACK, NUM_CSNS, false, csns, mac_responses, &mac_response_len); @@ -250,7 +250,7 @@ static int reader_attack_mode(void) { size_t dumplen = NUM_CSNS * 24; - uint8_t *dump = BigBuf_calloc(dumplen); + uint8_t *dump = BigBuf_malloc(dumplen); if (dump == false) { Dbprintf("Failed to allocate memory"); return PM3_EMALLOC; @@ -305,7 +305,6 @@ static int reader_dump_mode(void) { BigBuf_free(); uint8_t *card_data = BigBuf_malloc(ICLASS_16KS_SIZE); - // Don't use calloc since we set allocated memory to 0xFF's memset(card_data, 0xFF, ICLASS_16KS_SIZE); if (BUTTON_PRESS()) { @@ -443,7 +442,6 @@ static int dump_sim_mode(void) { BigBuf_free(); uint8_t *card_data = BigBuf_malloc(ICLASS_16KS_SIZE); - // Don't use calloc since we set allocated memory to 0xFF's memset(card_data, 0xFF, ICLASS_16KS_SIZE); if (BUTTON_PRESS()) { diff --git a/armsrc/Standalone/hf_mattyrun.c b/armsrc/Standalone/hf_mattyrun.c index fa0710b02..c68d12075 100644 --- a/armsrc/Standalone/hf_mattyrun.c +++ b/armsrc/Standalone/hf_mattyrun.c @@ -247,7 +247,7 @@ void RunMod(void) { // usb_disable(); // Allocate dictionary buffer - uint64_t *const mfcKeys = (uint64_t *)BigBuf_calloc( + uint64_t *const mfcKeys = (uint64_t *)BigBuf_malloc( sizeof(uint64_t) * (ARRAYLEN(MATTYRUN_MFC_ESSENTIAL_KEYS) + ARRAYLEN(MATTYRUN_MFC_DEFAULT_KEYS) + MIFARE_4K_MAXSECTOR * 2)); diff --git a/armsrc/Standalone/hf_msdsal.c b/armsrc/Standalone/hf_msdsal.c index 6eb5b46b2..5e36a92c5 100644 --- a/armsrc/Standalone/hf_msdsal.c +++ b/armsrc/Standalone/hf_msdsal.c @@ -379,7 +379,7 @@ void RunMod(void) { BigBuf_free_keep_EM(); // tag type: 11 = ISO/IEC 14443-4 - javacard (JCOP) - if (SimulateIso14443aInit(11, flags, data, NULL, 0, &responses, &cuid, NULL, NULL) == false) { + if (SimulateIso14443aInit(11, flags, data, NULL, 0, &responses, &cuid, NULL) == false) { BigBuf_free_keep_EM(); reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0); DbpString(_RED_("Error initializing the emulation process!")); diff --git a/armsrc/Standalone/hf_reblay.c b/armsrc/Standalone/hf_reblay.c index 30db64f41..8ecba8cf4 100644 --- a/armsrc/Standalone/hf_reblay.c +++ b/armsrc/Standalone/hf_reblay.c @@ -268,7 +268,7 @@ void RunMod() { BigBuf_free_keep_EM(); // 4 = ISO/IEC 14443-4 - javacard (JCOP) - if (SimulateIso14443aInit(4, flags, data, NULL, 0, &responses, &cuid, NULL, NULL) == false) { + if (SimulateIso14443aInit(4, flags, data, NULL, 0, &responses, &cuid, NULL) == false) { BigBuf_free_keep_EM(); reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0); DbpString(_RED_("Error initializing the emulation process!")); diff --git a/armsrc/Standalone/hf_tcprst.c b/armsrc/Standalone/hf_tcprst.c index d8ced29d4..c2b3ff51d 100644 --- a/armsrc/Standalone/hf_tcprst.c +++ b/armsrc/Standalone/hf_tcprst.c @@ -191,7 +191,7 @@ void RunMod(void) { memcpy(data, stuid, sizeof(stuid)); - if (SimulateIso14443aInit(tagType, flags, data, NULL, 0, &responses, &cuid, &pages, NULL) == false) { + if (SimulateIso14443aInit(tagType, flags, data, NULL, 0, &responses, &cuid, &pages) == false) { BigBuf_free_keep_EM(); reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0); DbpString(_YELLOW_("!!") "Error initializing the simulation process!"); @@ -369,7 +369,7 @@ void RunMod(void) { memcpy(data, stuid, sizeof(stuid)); - if (SimulateIso14443aInit(tagType, flags, data, NULL, 0, &responses, &cuid, &pages, NULL) == false) { + if (SimulateIso14443aInit(tagType, flags, data, NULL, 0, &responses, &cuid, &pages) == false) { BigBuf_free_keep_EM(); reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0); DbpString(_YELLOW_("!!") "Error initializing the simulation process!"); diff --git a/armsrc/Standalone/hf_young.c b/armsrc/Standalone/hf_young.c index 83ad1999a..62d215dba 100644 --- a/armsrc/Standalone/hf_young.c +++ b/armsrc/Standalone/hf_young.c @@ -96,7 +96,7 @@ void RunMod(void) { } } - if (iso14443a_select_card(NULL, &card[selected], NULL, true, 0, true) == 0) { + if (!iso14443a_select_card(NULL, &card[selected], NULL, true, 0, true)) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); SpinDelay(500); @@ -253,25 +253,25 @@ void RunMod(void) { if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0) { DbpString("Mifare Classic 1k"); - SimulateIso14443aTag(1, flags, data, 0, NULL, 0, false, false); + SimulateIso14443aTag(1, flags, data, 0, NULL, 0); } else if (uids[selected].sak == 0x18 && uids[selected].atqa[0] == 0x02 && uids[selected].atqa[1] == 0) { DbpString("Mifare Classic 4k (4b uid)"); - SimulateIso14443aTag(8, flags, data, 0, NULL, 0, false, false); + SimulateIso14443aTag(8, flags, data, 0, NULL, 0); } else if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) { DbpString("Mifare Classic 4k (7b uid)"); - SimulateIso14443aTag(8, flags, data, 0, NULL, 0, false, false); + SimulateIso14443aTag(8, flags, data, 0, NULL, 0); } else if (uids[selected].sak == 0x00 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) { DbpString("Mifare Ultralight"); - SimulateIso14443aTag(2, flags, data, 0, NULL, 0, false, false); + SimulateIso14443aTag(2, flags, data, 0, NULL, 0); } else if (uids[selected].sak == 0x20 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0x03) { DbpString("Mifare DESFire"); - SimulateIso14443aTag(3, flags, data, 0, NULL, 0, false, false); + SimulateIso14443aTag(3, flags, data, 0, NULL, 0); } else if (uids[selected].sak == 0x20 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0x03) { DbpString("Mifare DESFire Ev1/Plus/JCOP"); - SimulateIso14443aTag(3, flags, data, 0, NULL, 0, false, false); + SimulateIso14443aTag(3, flags, data, 0, NULL, 0); } else { Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation"); - SimulateIso14443aTag(1, flags, data, 0, NULL, 0, false, false); + SimulateIso14443aTag(1, flags, data, 0, NULL, 0); } } else if (button_pressed == BUTTON_SINGLE_CLICK) { diff --git a/armsrc/Standalone/lf_icehid.c b/armsrc/Standalone/lf_icehid.c index c44069a12..05cf039c5 100644 --- a/armsrc/Standalone/lf_icehid.c +++ b/armsrc/Standalone/lf_icehid.c @@ -199,7 +199,7 @@ static uint32_t IceIOdemod(void) { size_t size = MIN(12000, BigBuf_max_traceLen()); -// uint8_t *dest = BigBuf_calloc(size); +// uint8_t *dest = BigBuf_malloc(size); uint8_t *dest = BigBuf_get_addr(); //fskdemod and get start index @@ -243,7 +243,7 @@ static uint32_t IceHIDDemod(void) { // large enough to catch 2 sequences of largest format // size_t size = 50 * 128 * 2; // 12800 bytes size_t size = MIN(12800, BigBuf_max_traceLen()); - //uint8_t *dest = BigBuf_calloc(size); + //uint8_t *dest = BigBuf_malloc(size); uint8_t *dest = BigBuf_get_addr(); // FSK demodulator diff --git a/armsrc/Standalone/lf_tharexde.c b/armsrc/Standalone/lf_tharexde.c index 735270328..b46ea69d8 100644 --- a/armsrc/Standalone/lf_tharexde.c +++ b/armsrc/Standalone/lf_tharexde.c @@ -103,9 +103,9 @@ static bool get_input_data_from_file(uint32_t *tag, char *inputfile) { if (exists_in_spiffs(inputfile)) { uint32_t size = size_in_spiffs(inputfile); - uint8_t *mem = BigBuf_calloc(size); + uint8_t *mem = BigBuf_malloc(size); - Dbprintf("found input file `" _YELLOW_("%s") "`", inputfile); + Dbprintf(_YELLOW_("found input file %s"), inputfile); rdv40_spiffs_read_as_filetype(inputfile, mem, size, RDV40_SPIFFS_SAFETY_SAFE); diff --git a/armsrc/appmain.c b/armsrc/appmain.c index db16394ab..9399592c9 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -480,32 +480,6 @@ static void SendStatus(uint32_t wait) { } else { Dbprintf(" iClass... "_RED_("%u")" keys - "_RED_("%s"), num, ICLASS_KEYS_FILE); } - - if (exists_in_spiffs(MFULC_KEYS_FILE)) { - num = size_in_spiffs(MFULC_KEYS_FILE) / MFULC_KEY_LENGTH; - } else { - num = 0; - } - - if (num > 0) { - Dbprintf(" UL-C..... "_YELLOW_("%u")" keys - "_GREEN_("%s"), num, MFULC_KEYS_FILE); - } else { - Dbprintf(" UL-C..... "_RED_("%u")" keys - "_RED_("%s"), num, MFULC_KEYS_FILE); - } - - if (exists_in_spiffs(MFULAES_KEYS_FILE)) { - num = size_in_spiffs(MFULAES_KEYS_FILE) / MFULAES_KEY_LENGTH; - } else { - num = 0; - } - - if (num > 0) { - Dbprintf(" UL-AES... "_YELLOW_("%u")" keys - "_GREEN_("%s"), num, MFULAES_KEYS_FILE); - } else { - Dbprintf(" UL-AES... "_RED_("%u")" keys - "_RED_("%s"), num, MFULAES_KEYS_FILE); - } - - #endif DbpString(""); reply_ng(CMD_STATUS, PM3_SUCCESS, NULL, 0); @@ -1749,13 +1723,10 @@ static void PacketReceived(PacketCommandNG *packet) { uint8_t uid[10]; uint8_t exitAfter; uint8_t rats[20]; - bool ulc_p1; - bool ulc_p2; } PACKED; struct p *payload = (struct p *) packet->data.asBytes; SimulateIso14443aTag(payload->tagtype, payload->flags, payload->uid, - payload->exitAfter, payload->rats, sizeof(payload->rats), - payload->ulc_p1, payload->ulc_p2); // ## Simulate iso14443a tag - pass tag type & UID + payload->exitAfter, payload->rats, sizeof(payload->rats)); // ## Simulate iso14443a tag - pass tag type & UID break; } case CMD_HF_ISO14443A_SIM_AID: { diff --git a/armsrc/dbprint.c b/armsrc/dbprint.c index 687bdfb90..42d96fc3e 100644 --- a/armsrc/dbprint.c +++ b/armsrc/dbprint.c @@ -102,7 +102,9 @@ void Dbhexdump(int len, const uint8_t *d, bool bAsci) { } #endif } -void print_result(const char *name, const uint8_t *d, size_t n) { +void print_result(const char *name, const uint8_t *d, size_t + + n) { const uint8_t *p = d; uint16_t tmp = n & 0xFFF0; diff --git a/armsrc/desfire_crypto.c b/armsrc/desfire_crypto.c index b27d19595..dccbd7bb6 100644 --- a/armsrc/desfire_crypto.c +++ b/armsrc/desfire_crypto.c @@ -334,7 +334,7 @@ void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t le return; } - uint8_t *buffer = BigBuf_calloc(padded_data_length(len, kbs)); + uint8_t *buffer = BigBuf_malloc(padded_data_length(len, kbs)); memcpy(buffer, data, len); diff --git a/armsrc/felica.c b/armsrc/felica.c index d924cc0b7..b7f8b01c0 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -497,7 +497,7 @@ static void iso18092_setup(uint8_t fpga_minor_mode) { BigBuf_Clear_ext(false); // Initialize Demod and Uart structs - // DemodInit(BigBuf_calloc(MAX_FRAME_SIZE)); + // DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); FelicaFrameinit(BigBuf_calloc(FELICA_MAX_FRAME_SIZE)); felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER; // 418 diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index b3d739a6d..d9e941705 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -523,11 +523,10 @@ void FpgaDownloadAndGo(int bitstream_target) { lz4_stream_t compressed_fpga_stream; LZ4_streamDecode_t lz4StreamDecode_body = {{ 0 }}; compressed_fpga_stream.lz4StreamDecode = &lz4StreamDecode_body; - uint8_t *output_buffer = BigBuf_calloc(FPGA_RING_BUFFER_BYTES); + uint8_t *output_buffer = BigBuf_malloc(FPGA_RING_BUFFER_BYTES); - if (reset_fpga_stream(bitstream_target, &compressed_fpga_stream, output_buffer) == false) { + if (!reset_fpga_stream(bitstream_target, &compressed_fpga_stream, output_buffer)) return; - } uint32_t bitstream_length; if (bitparse_find_section(bitstream_target, 'e', &bitstream_length, &compressed_fpga_stream, output_buffer)) { diff --git a/armsrc/frozen.c b/armsrc/frozen.c index b4f57aa74..874e81988 100644 --- a/armsrc/frozen.c +++ b/armsrc/frozen.c @@ -26,7 +26,7 @@ #include "nprintf.h" #include "BigBuf.h" -#define malloc(X) BigBuf_calloc(X) +#define malloc(X) BigBuf_malloc(X) #define free(X) #if !defined(WEAK) diff --git a/armsrc/hfsnoop.c b/armsrc/hfsnoop.c index 939ee4319..5443a617f 100644 --- a/armsrc/hfsnoop.c +++ b/armsrc/hfsnoop.c @@ -107,7 +107,7 @@ int HfSniff(uint32_t samplesToSkip, uint32_t triggersToSkip, uint16_t *len, uint SpinDelay(100); *len = BigBuf_max_traceLen(); - uint8_t *mem = BigBuf_calloc(*len); + uint8_t *mem = BigBuf_malloc(*len); uint32_t trigger_cnt = 0; uint16_t r = 0, interval = 0; diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 4a1563aea..5a4466567 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -917,9 +917,8 @@ send: LEDsoff(); - if (button_pressed) { + if (button_pressed) DbpString("button pressed"); - } return button_pressed; } @@ -1858,39 +1857,8 @@ static bool iclass_writeblock_sp(uint8_t blockno, uint8_t *data, uint8_t *mac, b return true; } -uint8_t credit_key[8] = {0xFD, 0xCB, 0x5A, 0x52, 0xEA, 0x8F, 0x30, 0x90}; - -static bool do_privilege_escalation(uint8_t *read_check_cc, size_t cc_len, uint32_t *eof_time) { - - int priv_esc_tries = 5; - - while (priv_esc_tries--) { - - uint16_t resp_len = 0; - uint8_t resp[10] = {0}; - //The privilege escalation is done with a readcheck and not just a normal read! - uint32_t start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; - - iclass_send_as_reader(read_check_cc, cc_len, &start_time, eof_time, false); - // expect a 8-byte response here - int res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len); - if (res == PM3_SUCCESS && resp_len == 8) { - return true; - } - } - - if (g_dbglevel == DBG_INFO) { - DbpString(""); - DbpString(_RED_("Unable to complete privilege escalation! Stopping.")); - } - return false; -} - // turn off afterwards void iClass_WriteBlock(uint8_t *msg) { - bool priv_esc = false; - uint8_t read_check_cc[] = { 0x10 | ICLASS_CMD_READCHECK, 0x18 }; - uint8_t div_cc[8] = {0}; LED_A_ON(); @@ -1910,9 +1878,6 @@ void iClass_WriteBlock(uint8_t *msg) { goto out; } - iclass_calc_div_key(hdr.csn, credit_key, div_cc, false); - read_check_cc[1] = hdr.conf.app_limit + 1; //first block of AA2 - uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; uint8_t mac[4] = {0}; @@ -1939,7 +1904,7 @@ void iClass_WriteBlock(uint8_t *msg) { write_len -= 2; } else { - if (payload->req.use_replay && (memcmp(payload->mac, "\x00\x00\x00\x00", 4) != 0)) { + if (payload->req.use_replay) { memcpy(write + 10, payload->mac, sizeof(payload->mac)); } else { // Secure tags uses MAC @@ -1947,17 +1912,10 @@ void iClass_WriteBlock(uint8_t *msg) { wb[0] = payload->req.blockno; memcpy(wb + 1, payload->data, PICOPASS_BLOCK_SIZE); - if (payload->req.use_credit_key) { + if (payload->req.use_credit_key) doMAC_N(wb, sizeof(wb), hdr.key_c, mac); - } else if (payload->req.use_replay) { - priv_esc = do_privilege_escalation(read_check_cc, sizeof(read_check_cc), &eof_time); - if (priv_esc == false) { - goto out; - } - doMAC_N(wb, sizeof(wb), div_cc, mac); - } else { + else doMAC_N(wb, sizeof(wb), hdr.key_d, mac); - } memcpy(write + 10, mac, sizeof(mac)); } @@ -2595,9 +2553,6 @@ out: } void iClass_Restore(iclass_restore_req_t *msg) { - bool priv_esc = false; - uint8_t read_check_cc[] = { 0x10 | ICLASS_CMD_READCHECK, 0x18 }; - uint8_t div_cc[8] = {0}; // sanitation if (msg == NULL) { @@ -2626,9 +2581,7 @@ void iClass_Restore(iclass_restore_req_t *msg) { if (res == false) { goto out; } - iclass_calc_div_key(hdr.csn, credit_key, div_cc, false); - read_check_cc[1] = hdr.conf.app_limit + 1; //first block of AA2 // authenticate uint8_t mac[4] = {0}; uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; @@ -2658,17 +2611,10 @@ void iClass_Restore(iclass_restore_req_t *msg) { wb[0] = item.blockno; memcpy(wb + 1, item.data, 8); - if (msg->req.use_credit_key) { + if (msg->req.use_credit_key) doMAC_N(wb, sizeof(wb), hdr.key_c, mac); - } else if (msg->req.use_replay) { - priv_esc = do_privilege_escalation(read_check_cc, sizeof(read_check_cc), &eof_time); - if (priv_esc == false) { - goto out; - } - doMAC_N(wb, sizeof(wb), div_cc, mac); - } else { + else doMAC_N(wb, sizeof(wb), hdr.key_d, mac); - } } // data + mac @@ -2692,7 +2638,7 @@ out: static void generate_single_key_block_inverted_opt(const uint8_t *startingKey, uint32_t index, uint8_t *keyBlock) { uint8_t bits_index = index / 16383; - uint8_t ending_bits[] = { // all possible 70 combinations of 4x0 and 4x1 as key ending bits + uint8_t ending_bits[] = { //all possible 70 combinations of 4x0 and 4x1 as key ending bits 0x0F, 0x17, 0x1B, 0x1D, 0x1E, 0x27, 0x2B, 0x2D, 0x2E, 0x33, 0x35, 0x36, 0x39, 0x3A, 0x3C, 0x47, 0x4B, 0x4D, 0x4E, 0x53, 0x55, 0x56, 0x59, 0x5A, 0x5C, 0x63, 0x65, 0x66, 0x69, 0x6A, @@ -2776,10 +2722,10 @@ void iClass_Recover(iclass_recover_req_t *msg) { uint8_t original_mac[8] = {0}; uint8_t mac1[4] = {0}; - while ((card_select == false) || (card_auth == false)) { + while (!card_select || !card_auth) { Iso15693InitReader(); //has to be at the top as it starts tracing - if (msg->debug == false) { + if (!msg->debug) { set_tracing(false); //disable tracing to prevent crashes - set to true for debugging } else { if (loops == 1) { @@ -2795,7 +2741,7 @@ void iClass_Recover(iclass_recover_req_t *msg) { } //Step 0A - The read_check_cc block has to be in AA2, set it by checking the card configuration - read_check_cc[1] = hdr.conf.app_limit + 1; //first block of AA2 + read_check_cc[1] = ((uint8_t *)&hdr.conf)[0] + 1; //first block of AA2 //Step1 Authenticate with AA1 using trace if (card_select) { @@ -2807,12 +2753,10 @@ void iClass_Recover(iclass_recover_req_t *msg) { card_auth = true; } } - - if ((card_select == false) || (card_auth == false)) { + if (!card_auth || !card_select) { reinit_tentatives++; switch_off(); } - if (reinit_tentatives == 5) { DbpString(""); DbpString(_RED_("Unable to select or authenticate with card multiple times! Stopping.")); @@ -2823,8 +2767,11 @@ void iClass_Recover(iclass_recover_req_t *msg) { while (bits_found == -1) { reinit_tentatives = 0; + int res2; + uint8_t resp[10] = {0}; uint8_t mac2[4] = {0}; res = false; + uint16_t resp_len = 0; if (BUTTON_PRESS() || loops > msg->loop) { if (loops > msg->loop) { @@ -2840,25 +2787,25 @@ void iClass_Recover(iclass_recover_req_t *msg) { if (msg->test) { Dbprintf(_YELLOW_("*Cycled Reader*") " TEST Index - Loops: "_YELLOW_("%3d / %3d") " *", loops, msg->loop); - } else if (msg->debug || ((card_select == false) && (card_auth == false))) { + } else if (msg->debug || (!card_select && !card_auth)) { Dbprintf(_YELLOW_("*Cycled Reader*") " Index: "_RED_("%3d")" Loops: "_YELLOW_("%3d / %3d") " *", index, loops, msg->loop); } else { DbprintfEx(FLAG_INPLACE, "[" _BLUE_("#") "] Index: "_CYAN_("%3d")" Loops: "_YELLOW_("%3d / %3d")" ", index, loops, msg->loop); } - while ((card_select == false) || (card_auth == false)) { + while (!card_select || !card_auth) { - Iso15693InitReader(); // has to be at the top as it starts tracing - set_tracing(false); // disable tracing to prevent crashes - set to true for debugging - // Step0 Card Select Routine - eof_time = 0; // reset eof time + Iso15693InitReader(); //has to be at the top as it starts tracing + set_tracing(false); //disable tracing to prevent crashes - set to true for debugging + //Step0 Card Select Routine + eof_time = 0; //reset eof time res = select_iclass_tag(&hdr, false, &eof_time, shallow_mod); if (res) { - status_message = 1; // card select successful + status_message = 1; //card select successful card_select = true; } - // Step1 Authenticate with AA1 using trace + //Step1 Authenticate with AA1 using trace if (card_select) { memcpy(original_mac, msg->req.key, 8); start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; @@ -2868,12 +2815,10 @@ void iClass_Recover(iclass_recover_req_t *msg) { card_auth = true; } } - - if ((card_select == false) || (card_auth == false)) { + if (!card_auth || !card_select) { reinit_tentatives++; switch_off(); } - if (reinit_tentatives == 5) { DbpString(""); DbpString(_RED_("Unable to select or authenticate with card multiple times! Stopping.")); @@ -2881,45 +2826,52 @@ void iClass_Recover(iclass_recover_req_t *msg) { } } - // Step2 Privilege Escalation: attempt to read AA2 with credentials for AA1 - if (priv_esc == false) { - priv_esc = do_privilege_escalation(read_check_cc, sizeof(read_check_cc), &eof_time); - if (priv_esc) { - status_message = 3; + //Step2 Privilege Escalation: attempt to read AA2 with credentials for AA1 + int priv_esc_tries = 0; + while (!priv_esc) { + //The privilege escalation is done with a readcheck and not just a normal read! + start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + iclass_send_as_reader(read_check_cc, sizeof(read_check_cc), &start_time, &eof_time, shallow_mod); + // expect a 8-byte response here + res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, &eof_time, false, true, &resp_len); + if (res2 != PM3_SUCCESS || resp_len != 8) { + priv_esc_tries++; } else { + status_message = 3; //privilege escalation successful + priv_esc = true; + } + if (priv_esc_tries == 5) { + DbpString(""); + DbpString(_RED_("Unable to complete privilege escalation! Stopping.")); goto out; } } - if (priv_esc && status_message != 3) { start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; iclass_send_as_reader(read_check_cc, sizeof(read_check_cc), &start_time, &eof_time, shallow_mod); status_message = 3; } - // Step3 Calculate New Key (Optimised Algo V2) + //Step3 Calculate New Key (Optimised Algo V2) generate_single_key_block_inverted_opt(zero_key, index, genkeyblock); if (msg->test) { memcpy(genkeyblock, zero_key, PICOPASS_BLOCK_SIZE); } - if (msg->fast) { // if we're skipping restoring the original key to gain speed, xor the new index key with the previous index key and update the difference and track restore values differently - + if (msg->fast) { //if we're skipping restoring the original key to gain speed, xor the new index key with the previous index key and update the difference and track restore values differently if (index > 0 && loops > 1) { generate_single_key_block_inverted_opt(zero_key, index - 1, fast_previous_key); } else { memcpy(fast_previous_key, zero_key, PICOPASS_BLOCK_SIZE); } - for (int i = 0; i < PICOPASS_BLOCK_SIZE; i++) { fast_current_key[i] = genkeyblock[i] ^ fast_previous_key[i]; fast_restore_key[i] = fast_restore_key[i] ^ fast_current_key[i]; } - memcpy(genkeyblock, fast_current_key, PICOPASS_BLOCK_SIZE); } - // Step4 Calculate New Mac + //Step4 Calculate New Mac uint8_t wb[9] = {0}; uint8_t blockno = 3; @@ -2928,18 +2880,16 @@ void iClass_Recover(iclass_recover_req_t *msg) { doMAC_N(wb, sizeof(wb), div_key2, mac2); bool written = false; bool write_error = false; - while (written == false && write_error == false) { - // Step5 Perform Write - start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + //Step5 Perform Write if (iclass_writeblock_sp(blockno, genkeyblock, mac2, shallow_mod, &start_time, &eof_time, short_delay)) { - status_message = 4; // wrote new key on the card - unverified + status_message = 4; //wrote new key on the card - unverified } - if (msg->fast == false) { // if we're going slow we check at every write that the write actually happened - // Reset cypher state + if (!msg->fast) { //if we're going slow we check at every write that the write actually happened + //Reset cypher state start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; iclass_send_as_reader(read_check_cc2, sizeof(read_check_cc2), &start_time, &eof_time, shallow_mod); - // try to authenticate with the original mac to verify the write happened + //try to authenticate with the original mac to verify the write happened memcpy(msg->req.key, original_mac, 8); start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1); @@ -2956,24 +2906,24 @@ void iClass_Recover(iclass_recover_req_t *msg) { } } else { if (res) { - write_error = true; // failed to update the key, the card's key is the original one + write_error = true; //failed to update the key, the card's key is the original one } else { - status_message = 5; // verified the card key was updated to the new one + status_message = 5; //verified the card key was updated to the new one written = true; } } - } else { // if we're going fast we can skip the above checks as we're just xorring the key over and over + } else { //if we're going fast we can skip the above checks as we're just xorring the key over and over status_message = 5; written = true; } } if (write_error == false) { - // Step6 Perform 8 authentication attempts + 1 to verify if we found the weak key + //Step6 Perform 8 authentication attempts + 1 to verify if we found the weak key for (int i = 0; i < 8 ; ++i) { start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; iclass_send_as_reader(read_check_cc2, sizeof(read_check_cc2), &start_time, &eof_time, shallow_mod); - // need to craft the authentication payload accordingly + //need to craft the authentication payload accordingly memcpy(msg->req.key, iclass_mac_table[i], 8); start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1); //mac1 here shouldn't matter @@ -2985,31 +2935,29 @@ void iClass_Recover(iclass_recover_req_t *msg) { bool reverted = false; uint8_t revert_retries = 0; - if (msg->fast) { // if we're going fast only restore the original key at the end + if (msg->fast) { //if we're going fast only restore the original key at the end if (recovered) { goto fast_restore; } } else { - // if we're NOT going fast, regardless of bits being found, restore the original key and verify it - while (reverted == false) { - // Regain privilege escalation with a readcheck + //if we're NOT going fast, regardless of bits being found, restore the original key and verify it + while (!reverted) { + //Regain privilege escalation with a readcheck start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; iclass_send_as_reader(read_check_cc, sizeof(read_check_cc), &start_time, &eof_time, shallow_mod); start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; if (iclass_writeblock_sp(blockno, genkeyblock, mac2, shallow_mod, &start_time, &eof_time, short_delay)) { - status_message = 6; // restore of original key successful but unverified + status_message = 6; //restore of original key successful but unverified } - // Do a readcheck first to reset the cypher state + //Do a readcheck first to reset the cypher state start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; iclass_send_as_reader(read_check_cc2, sizeof(read_check_cc2), &start_time, &eof_time, shallow_mod); - - // need to craft the authentication payload accordingly + //need to craft the authentication payload accordingly memcpy(msg->req.key, original_mac, 8); start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; - res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1); if (res == true) { - status_message = 7; // restore of original key verified - card usable again + status_message = 7; //restore of original key verified - card usable again reverted = true; if (recovered) { goto restore; @@ -3017,7 +2965,7 @@ void iClass_Recover(iclass_recover_req_t *msg) { } revert_retries++; - if (revert_retries >= 7) { // must always be an odd number! + if (revert_retries >= 7) { //must always be an odd number! DbpString(""); DbpString(_CYAN_("Last Written Key: ")); Dbhexdump(8, genkeyblock, false); @@ -3026,6 +2974,8 @@ void iClass_Recover(iclass_recover_req_t *msg) { } } } + + } if (msg->debug) { @@ -3054,7 +3004,7 @@ void iClass_Recover(iclass_recover_req_t *msg) { } } - if (write_error && (msg->debug || msg->test)) { // if there was a write error, re-run the loop for the same key index + if (write_error && (msg->debug || msg->test)) { //if there was a write error, re-run the loop for the same key index DbpString("Loop Error: "_RED_("Repeating Loop!")); card_select = false; card_auth = false; @@ -3065,45 +3015,39 @@ void iClass_Recover(iclass_recover_req_t *msg) { status_message = 2; } - }// end while + }//end while fast_restore: - ;// empty statement for compilation + ;//empty statement for compilation uint8_t mac2[4] = {0}; uint8_t wb[9] = {0}; uint8_t blockno = 3; wb[0] = blockno; bool reverted = false; uint8_t revert_retries = 0; - - while (reverted == false) { - // Regain privilege escalation with a readcheck + while (!reverted) { + //Regain privilege escalation with a readcheck start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; iclass_send_as_reader(read_check_cc, sizeof(read_check_cc), &start_time, &eof_time, shallow_mod); memcpy(wb + 1, fast_restore_key, 8); doMAC_N(wb, sizeof(wb), div_key2, mac2); - start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; if (iclass_writeblock_sp(blockno, fast_restore_key, mac2, shallow_mod, &start_time, &eof_time, short_delay)) { - status_message = 6; // restore of original key successful but unverified + status_message = 6; //restore of original key successful but unverified } - - // Do a readcheck first to reset the cypher state + //Do a readcheck first to reset the cypher state start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; iclass_send_as_reader(read_check_cc2, sizeof(read_check_cc2), &start_time, &eof_time, shallow_mod); - - // need to craft the authentication payload accordingly + //need to craft the authentication payload accordingly memcpy(msg->req.key, original_mac, 8); - start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1); if (res == true) { - status_message = 7; // restore of original key verified - card usable again + status_message = 7; //restore of original key verified - card usable again reverted = true; } - revert_retries++; - if (revert_retries >= 7) { // must always be an odd number! + if (revert_retries >= 7) { //must always be an odd number! DbpString(""); DbpString(_CYAN_("Last Written Key (fast): ")); Dbhexdump(8, fast_restore_key, false); @@ -3117,7 +3061,7 @@ fast_restore: } restore: - ;// empty statement for compilation + ;//empty statement for compilation uint8_t partialkey[PICOPASS_BLOCK_SIZE] = {0}; for (int i = 0; i < PICOPASS_BLOCK_SIZE; i++) { @@ -3128,11 +3072,11 @@ restore: } } - // Print the bits decimal value + //Print the bits decimal value DbpString(""); DbpString(_RED_("--------------------------------------------------------")); Dbprintf("Decimal Value of last 3 bits: " _GREEN_("[%3d]"), bits_found); - // Print the 24 bits found from k1 + //Print the 24 bits found from k1 DbpString(_RED_("--------------------------------------------------------")); DbpString(_RED_("SUCCESS! Raw Key Partial Bytes: ")); Dbhexdump(8, partialkey, false); @@ -3151,4 +3095,5 @@ out: } else { reply_ng(CMD_HF_ICLASS_RECOVER, PM3_ESOFT, NULL, 0); } + } diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 3f1f4595b..5a1e66b74 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -370,16 +370,16 @@ tUart14a *GetUart14a(void) { void Uart14aReset(void) { Uart.state = STATE_14A_UNSYNCD; - Uart.shiftReg = 0; // shiftreg to hold decoded data bits Uart.bitCount = 0; Uart.len = 0; // number of decoded data bytes - Uart.posCnt = 0; - Uart.syncBit = 9999; - Uart.parityBits = 0; // holds 8 parity bits Uart.parityLen = 0; // number of decoded parity bytes - Uart.fourBits = 0x00000000; // clear the buffer for 4 Bits + Uart.shiftReg = 0; // shiftreg to hold decoded data bits + Uart.parityBits = 0; // holds 8 parity bits Uart.startTime = 0; Uart.endTime = 0; + Uart.fourBits = 0x00000000; // clear the buffer for 4 Bits + Uart.posCnt = 0; + Uart.syncBit = 9999; } void Uart14aInit(uint8_t *d, uint16_t n, uint8_t *par) { @@ -697,9 +697,6 @@ RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_t static RAMFUNC int ManchesterDecoding_Thinfilm(uint8_t bit) { if (Demod.len == Demod.output_len) { - // Flush last parity bits - Demod.parityBits <<= (8 - (Demod.len & 0x0007)); // left align remaining parity bits - Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them return true; } @@ -1188,24 +1185,9 @@ bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_ } } -static void Simulate_reread_ulc_key(uint8_t *ulc_key) { - // copy UL-C key from emulator memory - - mfu_dump_t *mfu_header = (mfu_dump_t *) BigBuf_get_EM_addr(); - - memcpy(ulc_key, mfu_header->data + (0x2D * 4), 4); - memcpy(ulc_key + 4, mfu_header->data + (0x2C * 4), 4); - memcpy(ulc_key + 8, mfu_header->data + (0x2F * 4), 4); - memcpy(ulc_key + 12, mfu_header->data + (0x2E * 4), 4); - - reverse_array(ulc_key, 4); - reverse_array(ulc_key + 4, 4); - reverse_array(ulc_key + 8, 4); - reverse_array(ulc_key + 12, 4); -} bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t *ats, size_t ats_len, tag_response_info_t **responses, - uint32_t *cuid, uint8_t *pages, uint8_t *ulc_key) { + uint32_t *cuid, uint8_t *pages) { uint8_t sak = 0; // The first response contains the ATQA (note: bytes are transmitted in reverse order). static uint8_t rATQA[2] = { 0x00 }; @@ -1355,38 +1337,6 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, sak = 0x20; break; } - case 13: { // MIFARE Ultralight-C - - rATQA[0] = 0x44; - sak = 0x00; - - // some first pages of UL/NTAG dump is special data - mfu_dump_t *mfu_header = (mfu_dump_t *) BigBuf_get_EM_addr(); - *pages = MAX(mfu_header->pages, 47); - - // copy UL-C key from emulator memory - memcpy(ulc_key, mfu_header->data + (0x2D * 4), 4); - memcpy(ulc_key + 4, mfu_header->data + (0x2C * 4), 4); - memcpy(ulc_key + 8, mfu_header->data + (0x2F * 4), 4); - memcpy(ulc_key + 12, mfu_header->data + (0x2E * 4), 4); - - reverse_array(ulc_key, 4); - reverse_array(ulc_key + 4, 4); - reverse_array(ulc_key + 8, 4); - reverse_array(ulc_key + 12, 4); - - /* - Dbprintf("UL-C Pages....... %u ( 47 )", *pages); - DbpString("UL-C 3des key... "); - Dbhexdump(16, ulc_key, false); - */ - - if (IS_FLAG_UID_IN_DATA(flags, 7)) { - DbpString("UL-C UID........ "); - Dbhexdump(7, data, false); - } - break; - } default: { if (g_dbglevel >= DBG_ERROR) Dbprintf("Error: unknown tagtype (%d)", tagType); return false; @@ -1412,7 +1362,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, // if uid not supplied then get from emulator memory if ((memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 10) == 0) || IS_FLAG_UID_IN_EMUL(flags)) { - if (tagType == 2 || tagType == 7 || tagType == 13) { + if (tagType == 2 || tagType == 7) { uint16_t start = MFU_DUMP_PREFIX_LENGTH; uint8_t emdata[8]; emlGet(emdata, start, sizeof(emdata)); @@ -1579,18 +1529,13 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, // 'hf 14a sim' //----------------------------------------------------------------------------- void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *useruid, uint8_t exitAfterNReads, - uint8_t *ats, size_t ats_len, bool ulc_part1, bool ulc_part2) { + uint8_t *ats, size_t ats_len) { #define ATTACK_KEY_COUNT 16 -#define ULC_TAG_NONCE "\x01\x02\x03\x04\x05\x06\x07\x08" tag_response_info_t *responses; uint32_t cuid = 0; uint32_t nonce = 0; - /// Ultralight-C 3des2k - uint8_t ulc_key[16] = { 0x00 }; - uint8_t ulc_iv[8] = { 0x00 }; - bool ulc_reread_key = false; uint8_t pages = 0; // Here, we collect CUID, block1, keytype1, NT1, NR1, AR1, CUID, block2, keytyp2, NT2, NR2, AR2 @@ -1634,9 +1579,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *useruid, uin .modulation_n = 0 }; - if (SimulateIso14443aInit(tagType, flags, useruid, ats, ats_len - , &responses, &cuid, &pages - , ulc_key) == false) { + if (SimulateIso14443aInit(tagType, flags, useruid, ats, ats_len, &responses, &cuid, &pages) == false) { BigBuf_free_keep_EM(); reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0); return; @@ -1724,7 +1667,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *useruid, uin order = ORDER_NONE; // back to work state p_response = NULL; - } else if (order == ORDER_AUTH && len == 8 && tagType != 2 && tagType != 7 && tagType != 13) { + } else if (order == ORDER_AUTH && len == 8) { // Received {nr] and {ar} (part of authentication) LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); uint32_t nr = bytes_to_num(receivedCmd, 4); @@ -1814,7 +1757,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *useruid, uin } else if (receivedCmd[0] == ISO14443A_CMD_READBLOCK && len == 4) { // Received a (plain) READ uint8_t block = receivedCmd[1]; // if Ultralight or NTAG (4 byte blocks) - if (tagType == 7 || tagType == 2 || tagType == 13) { + if (tagType == 7 || tagType == 2) { if (block > pages) { // send NACK 0x0 == invalid argument EmSend4bit(CARD_NACK_IV); @@ -1863,7 +1806,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *useruid, uin EmSendCmd(emdata, len + 2); } p_response = NULL; - } else if (receivedCmd[0] == MIFARE_ULC_WRITE && len == 8 && (tagType == 2 || tagType == 7 || tagType == 13)) { // Received a WRITE + } else if (receivedCmd[0] == MIFARE_ULC_WRITE && len == 8 && (tagType == 2 || tagType == 7)) { // Received a WRITE p_response = NULL; @@ -1901,15 +1844,12 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *useruid, uin // send ACK EmSend4bit(CARD_ACK); - if (tagType == 13 && block >= 0x2c && block <= 0x2F) { - ulc_reread_key = true; - } } else { // send NACK 0x1 == crc/parity error EmSend4bit(CARD_NACK_PA); } goto jump; - } else if (receivedCmd[0] == MIFARE_ULC_COMP_WRITE && len == 4 && (tagType == 2 || tagType == 7 || tagType == 13)) { + } else if (receivedCmd[0] == MIFARE_ULC_COMP_WRITE && len == 4 && (tagType == 2 || tagType == 7)) { // cmd + block + 2 bytes crc if (CheckCrc14A(receivedCmd, len)) { wrblock = receivedCmd[1]; @@ -1983,7 +1923,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *useruid, uin p_response = &responses[RESP_INDEX_VERSION]; } else if (receivedCmd[0] == MFDES_GET_VERSION && len == 4 && (tagType == 3)) { p_response = &responses[RESP_INDEX_VERSION]; - } else if ((receivedCmd[0] == MIFARE_AUTH_KEYA || receivedCmd[0] == MIFARE_AUTH_KEYB) && len == 4 && tagType != 2 && tagType != 7 && tagType != 13) { // Received an authentication request + } else if ((receivedCmd[0] == MIFARE_AUTH_KEYA || receivedCmd[0] == MIFARE_AUTH_KEYB) && len == 4 && tagType != 2 && tagType != 7) { // Received an authentication request cardAUTHKEY = receivedCmd[0] - 0x60; cardAUTHSC = receivedCmd[1] / 4; // received block num @@ -2002,77 +1942,9 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *useruid, uin } else { p_response = &responses[RESP_INDEX_ATS]; } - } else if (receivedCmd[0] == MIFARE_ULC_AUTH_1 && len == 4 && tagType == 13) { // ULC authentication, or Desfire Authentication - - // reset IV to all zeros - memset(ulc_iv, 0x00, 8); - - if (ulc_reread_key) { - Simulate_reread_ulc_key(ulc_key); - ulc_reread_key = false; - } - - dynamic_response_info.response[0] = MIFARE_ULC_AUTH_2; - - // our very random TAG NONCE - memcpy(dynamic_response_info.response + 1, ULC_TAG_NONCE, 8); - - if (ulc_part1) { - memset(dynamic_response_info.response + 1, 0, 8); - } else { - // encrypt TAG NONCE - tdes_nxp_send(dynamic_response_info.response + 1, dynamic_response_info.response + 1, 8, ulc_key, ulc_iv, 2); - } - - // Add CRC - AddCrc14A(dynamic_response_info.response, 9); - - // prepare to send - dynamic_response_info.response_n = 1 + 8 + 2; - prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE); - p_response = &dynamic_response_info; - order = ORDER_AUTH; - - } else if (receivedCmd[0] == MIFARE_ULC_AUTH_2 && len == 19 && tagType == 13) { // ULC authentication, or Desfire Authentication - - uint8_t enc_rnd_ab[16] = { 0x00 }; - uint8_t rnd_ab[16] = { 0x00 }; - - // copy reader response - memcpy(enc_rnd_ab, receivedCmd + 1, 16); - - // decrypt - tdes_nxp_receive(enc_rnd_ab, rnd_ab, 16, ulc_key, ulc_iv, 2); - - ror(rnd_ab + 8, 8); - - if (memcmp(rnd_ab + 8, ULC_TAG_NONCE, 8) != 0) { - Dbprintf("failed authentication"); - } - - // OK response - dynamic_response_info.response[0] = 0x00; - - if (ulc_part2) { - // try empty auth but with correct CRC and 0x00 command - memset(dynamic_response_info.response + 1, 0, 8); - } else { - // rol RndA - rol(rnd_ab, 8); - - // encrypt RndA - tdes_nxp_send(rnd_ab, dynamic_response_info.response + 1, 8, ulc_key, ulc_iv, 2); - } - - // Add CRC - AddCrc14A(dynamic_response_info.response, 9); - - dynamic_response_info.response_n = 1 + 8 + 2; - - prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE); - p_response = &dynamic_response_info; - order = ORDER_NONE; - + } else if (receivedCmd[0] == MIFARE_ULC_AUTH_1) { // ULC authentication, or Desfire Authentication + LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + p_response = NULL; } else if (receivedCmd[0] == MIFARE_ULEV1_AUTH && len == 7 && tagType == 7) { // NTAG / EV-1 uint8_t pwd[4] = {0, 0, 0, 0}; emlGet(pwd, (pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(pwd)); @@ -2253,16 +2125,13 @@ jump: // of bits specified in the delay parameter. static void PrepareDelayedTransfer(uint16_t delay) { delay &= 0x07; - if (delay == 0) { - return; - } + if (!delay) return; uint8_t bitmask = 0; uint8_t bits_shifted = 0; - for (uint16_t i = 0; i < delay; i++) { + for (uint16_t i = 0; i < delay; i++) bitmask |= (0x01 << i); - } tosend_t *ts = get_tosend(); @@ -2291,7 +2160,6 @@ static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing Dbprintf("Warning: HF field is off"); return; } - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); if (timing) { @@ -2466,7 +2334,7 @@ int EmGetCmd(uint8_t *received, uint16_t received_max_len, uint16_t *len, uint8_ // button press, takes a bit time, might mess with simualtion if (checker-- == 0) { if (BUTTON_PRESS()) { - Dbprintf("----------- " _GREEN_("Button pressed, user aborted") " ----------"); + Dbprintf("----------- " _GREEN_("Breaking / User aborted") " ----------"); return false; } @@ -2644,9 +2512,9 @@ int EmSendPrecompiledCmd(tag_response_info_t *p_response) { return ret; } -bool EmLogTrace(const uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, - uint32_t reader_EndTime, const uint8_t *reader_Parity, const uint8_t *tag_data, - uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, const uint8_t *tag_Parity) { +bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, + uint32_t reader_EndTime, uint8_t *reader_Parity, uint8_t *tag_data, + uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity) { // we cannot exactly measure the end and start of a received command from reader. However we know that the delay from // end of the received command to start of the tag's (simulated by us) answer is n*128+20 or n*128+84 resp. @@ -2968,14 +2836,10 @@ static int GetATQA(uint8_t *resp, uint16_t resp_len, uint8_t *resp_par, const is int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) { - return iso14443a_select_cardEx(uid_ptr, p_card, cuid_ptr, anticollision, num_cascades, no_rats, NULL, false); -} -int iso14443a_select_card_for_magic(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades) { - // Bug fix: When SAK is 0x00, `iso14443a_select_cardEx` would return too early at - // line "if (hf14aconfig.forcerats == 0)".`force_rats` is used to force RATS execution and ATS retrieval. - return iso14443a_select_cardEx(uid_ptr, p_card, cuid_ptr, anticollision, num_cascades, false, NULL, true); + return iso14443a_select_cardEx(uid_ptr, p_card, cuid_ptr, anticollision, num_cascades, no_rats, NULL); } + // performs iso14443a anticollision (optional) and card select procedure // fills the uid and cuid pointer unless NULL // fills the card info record unless NULL @@ -2984,7 +2848,7 @@ int iso14443a_select_card_for_magic(uint8_t *uid_ptr, iso14a_card_select_t *p_ca // requests ATS unless no_rats is true int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats, - const iso14a_polling_parameters_t *polling_parameters, bool force_rats) { + iso14a_polling_parameters_t *polling_parameters) { uint8_t resp[MAX_FRAME_SIZE] = {0}; // theoretically. A usual RATS will be much smaller @@ -3039,9 +2903,8 @@ int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint if (anticollision) { // clear uid - if (uid_ptr) { + if (uid_ptr) memset(uid_ptr, 0, 10); - } } if (hf14aconfig.forceanticol == 0) { @@ -3202,18 +3065,18 @@ int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint p_card->sak = sak; } - if (hf14aconfig.forcerats == 0 && force_rats == false) { + if (hf14aconfig.forcerats == 0) { // PICC compliant with iso14443a-4 ---> (SAK & 0x20 != 0) if ((sak & 0x20) == 0) { return 2; } - } else if (hf14aconfig.forcerats == 2 && force_rats == false) { + } else if (hf14aconfig.forcerats == 2) { if ((sak & 0x20) != 0) Dbprintf("Skipping RATS according to hf 14a config"); return 2; } // else force RATS - if ((sak & 0x20) == 0 && force_rats == false) Dbprintf("Forcing RATS according to hf 14a config"); + if ((sak & 0x20) == 0) Dbprintf("Forcing RATS according to hf 14a config"); // RATS, Request for answer to select if (no_rats == false) { @@ -3239,7 +3102,7 @@ int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint return 1; } -int iso14443a_fast_select_card(const uint8_t *uid_ptr, uint8_t num_cascades) { +int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades) { uint8_t resp[3] = { 0 }; // theoretically. max 1 Byte SAK, 2 Byte CRC, 3 bytes is enough uint8_t resp_par[1] = {0}; @@ -3479,8 +3342,7 @@ void ReaderIso14443a(PacketCommandNG *c) { true, 0, ((param & ISO14A_NO_RATS) == ISO14A_NO_RATS), - ((param & ISO14A_USE_CUSTOM_POLLING) == ISO14A_USE_CUSTOM_POLLING) ? (iso14a_polling_parameters_t *)cmd : NULL, - false + ((param & ISO14A_USE_CUSTOM_POLLING) == ISO14A_USE_CUSTOM_POLLING) ? (iso14a_polling_parameters_t *)cmd : NULL ); // TODO: Improve by adding a cmd parser pointer and moving it by struct length to allow combining data with polling params FpgaDisableTracing(); @@ -3658,23 +3520,17 @@ OUT: // Therefore try in alternating directions. static int32_t dist_nt(uint32_t nt1, uint32_t nt2) { - if (nt1 == nt2) { - return 0; - } + if (nt1 == nt2) return 0; uint32_t nttmp1 = nt1; uint32_t nttmp2 = nt2; for (uint16_t i = 1; i < 32768; i++) { nttmp1 = prng_successor(nttmp1, 1); - if (nttmp1 == nt2) { - return i; - } + if (nttmp1 == nt2) return i; nttmp2 = prng_successor(nttmp2, 1); - if (nttmp2 == nt1) { - return -i; - } + if (nttmp2 == nt1) return -i; } return (-99999); // either nt1 or nt2 are invalid nonces @@ -3682,8 +3538,8 @@ static int32_t dist_nt(uint32_t nt1, uint32_t nt2) { #define PRNG_SEQUENCE_LENGTH (1 << 16) -#define MAX_UNEXPECTED_RANDOM (4) // maximum number of unexpected (i.e. real) random numbers when trying to sync. Then give up. -#define MAX_SYNC_TRIES (32) +#define MAX_UNEXPECTED_RANDOM 4 // maximum number of unexpected (i.e. real) random numbers when trying to sync. Then give up. +#define MAX_SYNC_TRIES 32 //----------------------------------------------------------------------------- // Recover several bits of the cypher stream. This implements (first stages of) @@ -3813,9 +3669,8 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time); // Receive the (4 Byte) "random" TAG nonce - if (ReaderReceive(receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar) != 4) { + if (ReaderReceive(receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar) != 4) continue; - } previous_nt = nt; nt = bytes_to_num(receivedAnswer, 4); @@ -3838,9 +3693,9 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { // we didn't calibrate our clock yet, // iceman: has to be calibrated every time. - if (previous_nt && (nt_attacked == 0)) { + if (previous_nt && !nt_attacked) { - int32_t nt_distance = dist_nt(previous_nt, nt); + int nt_distance = dist_nt(previous_nt, nt); // if no distance between, then we are in sync. if (nt_distance == 0) { @@ -3866,9 +3721,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { sync_cycles = (sync_cycles - nt_distance) / elapsed_prng_sequences; // no negative sync_cycles, and too small sync_cycles will result in continuous misses - if (sync_cycles <= 10) { - sync_cycles += PRNG_SEQUENCE_LENGTH; - } + if (sync_cycles <= 10) sync_cycles += PRNG_SEQUENCE_LENGTH; // reset sync_cycles if (sync_cycles > PRNG_SEQUENCE_LENGTH * 2) { @@ -3876,14 +3729,8 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { sync_time = GetCountSspClk() & 0xfffffff8; } - if (g_dbglevel >= DBG_EXTENDED) { - Dbprintf("calibrating in cycle %d. nt_distance=%d, elapsed_prng_sequences=%d, new sync_cycles: %d\n" - , i - , nt_distance - , elapsed_prng_sequences - , sync_cycles - ); - } + if (g_dbglevel >= DBG_EXTENDED) + Dbprintf("calibrating in cycle %d. nt_distance=%d, elapsed_prng_sequences=%d, new sync_cycles: %d\n", i, nt_distance, elapsed_prng_sequences, sync_cycles); continue; } @@ -3913,9 +3760,8 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { } else { sync_cycles += catch_up_cycles; - if (g_dbglevel >= DBG_EXTENDED) { + if (g_dbglevel >= DBG_EXTENDED) Dbprintf("Lost sync in cycle %d for the fourth time consecutively (nt_distance = %d). Adjusting sync_cycles to %d.\n", i, catch_up_cycles, sync_cycles); - } last_catch_up = 0; catch_up_cycles = 0; @@ -3928,9 +3774,8 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { if (received_nack) { catch_up_cycles = 8; // the PRNG is delayed by 8 cycles due to the NAC (4Bits = 0x05 encrypted) transfer - if (nt_diff == 0) { + if (nt_diff == 0) par_low = par[0] & 0xE0; // there is no need to check all parities for other nt_diff. Parity Bits for mf_nr_ar[0..2] won't change - } par_list[nt_diff] = reflect8(par[0]); ks_list[nt_diff] = receivedAnswer[0] ^ 0x05; // xor with NACK value to get keystream @@ -3949,15 +3794,12 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { } else { // No NACK. if (nt_diff == 0 && first_try) { - par[0]++; - if (par[0] == 0) { // tried all 256 possible parities without success. Card doesn't send NACK. isOK = 2; return_status = PM3_ESOFT; break; } - } else { // Why this? par[0] = ((par[0] & 0x1F) + 1) | par_low; @@ -4008,7 +3850,7 @@ void DetectNACKbug(void) { uint8_t uid[10] = { 0x00 }; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = { 0x00 }; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = { 0x00 }; - uint8_t par[2] = {0x00 }; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough + uint8_t par[1] = {0x00 }; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough uint32_t nt = 0, previous_nt = 0, nt_attacked = 0, cuid = 0; int32_t catch_up_cycles = 0, last_catch_up = 0; @@ -4059,9 +3901,9 @@ void DetectNACKbug(void) { ++checkbtn_cnt; // this part is from Piwi's faster nonce collecting part in Hardnested. - if (have_uid == false) { // need a full select cycle to get the uid first + if (!have_uid) { // need a full select cycle to get the uid first iso14a_card_select_t card_info; - if (iso14443a_select_card(uid, &card_info, &cuid, true, 0, true) == 0) { + if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { if (g_dbglevel >= DBG_INFO) Dbprintf("Mifare: Can't select card (ALL)"); i = 0; continue; @@ -4083,7 +3925,7 @@ void DetectNACKbug(void) { } have_uid = true; } else { // no need for anticollision. We can directly select the card - if (iso14443a_fast_select_card(uid, cascade_levels) == 0) { + if (!iso14443a_fast_select_card(uid, cascade_levels)) { if (g_dbglevel >= DBG_INFO) Dbprintf("Mifare: Can't select card (UID)"); i = 0; have_uid = false; @@ -4297,7 +4139,7 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid, .modulation_n = 0 }; - if (SimulateIso14443aInit(tagType, flags, uid, ats, ats_len, &responses, &cuid, &pages, NULL) == false) { + if (SimulateIso14443aInit(tagType, flags, uid, ats, ats_len, &responses, &cuid, &pages) == false) { BigBuf_free_keep_EM(); reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0); return; diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 5eb2e81ff..420d6e0c0 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -143,7 +143,7 @@ RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_t void RAMFUNC SniffIso14443a(uint8_t param); void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *useruid, uint8_t exitAfterNReads, - uint8_t *ats, size_t ats_len, bool ulc_part1, bool ulc_part2); + uint8_t *ats, size_t ats_len); void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid, uint8_t *ats, size_t ats_len, uint8_t *aid, size_t aid_len, @@ -152,8 +152,7 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid, bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t *ats, size_t ats_len, tag_response_info_t **responses, - uint32_t *cuid, uint8_t *pages, - uint8_t *ulc_key); + uint32_t *cuid, uint8_t *pages); bool GetIso14443aCommandFromReader(uint8_t *received, uint16_t received_maxlen, uint8_t *par, int *len); void iso14443a_antifuzz(uint32_t flags); @@ -166,11 +165,8 @@ uint16_t ReaderReceive(uint8_t *receivedAnswer, uint16_t answer_maxlen, uint8_t void iso14443a_setup(uint8_t fpga_minor_mode); int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint16_t data_len, uint8_t *res); int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats); -int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, - bool anticollision, uint8_t num_cascades, bool no_rats, - const iso14a_polling_parameters_t *polling_parameters, bool force_rats); -int iso14443a_select_card_for_magic(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades); -int iso14443a_fast_select_card(const uint8_t *uid_ptr, uint8_t num_cascades); +int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats, iso14a_polling_parameters_t *polling_parameters); +int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades); void iso14a_set_trigger(bool enable); int EmSendCmd14443aRaw(const uint8_t *resp, uint16_t respLen); @@ -185,9 +181,8 @@ int EmSendPrecompiledCmd(tag_response_info_t *p_response); bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *max_buffer_size); bool prepare_tag_modulation(tag_response_info_t *response_info, size_t max_buffer_size); -bool EmLogTrace(const uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, - uint32_t reader_EndTime, const uint8_t *reader_Parity, const uint8_t *tag_data, - uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, const uint8_t *tag_Parity); +bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity, + uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity); void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype); void DetectNACKbug(void); diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index 0a324ff30..ed440c0c0 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -786,14 +786,14 @@ void SimulateIso14443bTag(const uint8_t *pupi) { // prepare "ATQB" tag answer (encoded): CodeIso14443bAsTag(respATQB, sizeof(respATQB)); - uint8_t *encodedATQB = BigBuf_calloc(ts->max); + uint8_t *encodedATQB = BigBuf_malloc(ts->max); uint16_t encodedATQBLen = ts->max; memcpy(encodedATQB, ts->buf, ts->max); // prepare "OK" tag answer (encoded): CodeIso14443bAsTag(respOK, sizeof(respOK)); - uint8_t *encodedOK = BigBuf_calloc(ts->max); + uint8_t *encodedOK = BigBuf_malloc(ts->max); uint16_t encodedOKLen = ts->max; memcpy(encodedOK, ts->buf, ts->max); @@ -988,18 +988,18 @@ void Simulate_iso14443b_srx_tag(uint8_t *uid) { tosend_t *ts = get_tosend(); - uint8_t *receivedCmd = BigBuf_calloc(MAX_FRAME_SIZE); + uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); // prepare "ATQB" tag answer (encoded): CodeIso14443bAsTag(respATQB, sizeof(respATQB)); - uint8_t *encodedATQB = BigBuf_calloc(ts->max); + uint8_t *encodedATQB = BigBuf_malloc(ts->max); uint16_t encodedATQBLen = ts->max; memcpy(encodedATQB, ts->buf, ts->max); // prepare "OK" tag answer (encoded): CodeIso14443bAsTag(respOK, sizeof(respOK)); - uint8_t *encodedOK = BigBuf_calloc(ts->max); + uint8_t *encodedOK = BigBuf_malloc(ts->max); uint16_t encodedOKLen = ts->max; memcpy(encodedOK, ts->buf, ts->max); @@ -2405,8 +2405,8 @@ void SniffIso14443b(void) { uint8_t ua_buf[MAX_FRAME_SIZE] = {0}; Uart14bInit(ua_buf); - //Demod14bInit(BigBuf_calloc(MAX_FRAME_SIZE)); - //Uart14bInit(BigBuf_calloc(MAX_FRAME_SIZE)); + //Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE), MAX_FRAME_SIZE); + //Uart14bInit(BigBuf_malloc(MAX_FRAME_SIZE)); // Set FPGA in the appropriate mode FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_848_KHZ | FPGA_HF_READER_MODE_SNIFF_IQ); diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 14e3c785f..57e41a431 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -180,7 +180,8 @@ static void CodeIso15693AsReaderEOF(void) { static int get_uid_slix(uint32_t start_time, uint32_t *eof_time, uint8_t *uid) { - uint8_t *answer = BigBuf_calloc(ISO15693_MAX_RESPONSE_LENGTH); + uint8_t *answer = BigBuf_malloc(ISO15693_MAX_RESPONSE_LENGTH); + memset(answer, 0x00, ISO15693_MAX_RESPONSE_LENGTH); start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; @@ -984,11 +985,10 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo DecodeTagFSK_t dtfm = { 0 }; DecodeTagFSK_t *dtf = &dtfm; - if (fsk) { + if (fsk) DecodeTagFSKInit(dtf, response, max_len); - } else { + else DecodeTagInit(dt, response, max_len); - } // wait for last transfer to complete while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY)); @@ -1014,9 +1014,8 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo for (;;) { volatile uint16_t behindBy = ((uint16_t *)AT91C_BASE_PDC_SSC->PDC_RPR - upTo) & (DMA_BUFFER_SIZE - 1); - if (behindBy == 0) { + if (behindBy == 0) continue; - } samples++; if (samples == 1) { @@ -1483,7 +1482,7 @@ int GetIso15693CommandFromReader(uint8_t *received, size_t max_len, uint32_t *eo bool gotFrame = false; // the decoder data structure - DecodeReader_t *dr = (DecodeReader_t *)BigBuf_calloc(sizeof(DecodeReader_t)); + DecodeReader_t *dr = (DecodeReader_t *)BigBuf_malloc(sizeof(DecodeReader_t)); DecodeReaderInit(dr, received, max_len, 0, NULL); // wait for last transfer to complete @@ -1588,7 +1587,7 @@ void AcquireRawAdcSamplesIso15693(void) { LED_A_ON(); - uint8_t *dest = BigBuf_calloc(4096); + uint8_t *dest = BigBuf_malloc(4000); // switch field on FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER); @@ -2030,7 +2029,7 @@ void ReaderIso15693(iso15_card_select_t *p_card) { LED_A_ON(); set_tracing(true); - uint8_t *answer = BigBuf_calloc(ISO15693_MAX_RESPONSE_LENGTH); + uint8_t *answer = BigBuf_malloc(ISO15693_MAX_RESPONSE_LENGTH); memset(answer, 0x00, ISO15693_MAX_RESPONSE_LENGTH); // FIRST WE RUN AN INVENTORY TO GET THE TAG UID diff --git a/armsrc/lfops.c b/armsrc/lfops.c index ac65c425c..9fd9d8f58 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -340,7 +340,7 @@ t55xx_configurations_t *getT55xxConfig(void) { void loadT55xxConfig(void) { #ifdef WITH_FLASH - uint8_t *buf = BigBuf_calloc(T55XX_CONFIG_LEN); + uint8_t *buf = BigBuf_malloc(T55XX_CONFIG_LEN); uint32_t size = 0; if (exists_in_spiffs(T55XX_CONFIG_FILE)) { @@ -2912,7 +2912,7 @@ void Cotag(uint32_t arg0, bool ledcontrol) { break; } case 1: { - uint8_t *dest = BigBuf_calloc(COTAG_BITS); + uint8_t *dest = BigBuf_malloc(COTAG_BITS); uint16_t bits = doCotagAcquisitionManchester(dest, COTAG_BITS); reply_ng(CMD_LF_COTAG_READ, PM3_SUCCESS, dest, bits); break; diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index a07a6aae1..ffa1cbcd9 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -149,7 +149,7 @@ void initSampleBufferEx(uint32_t *sample_size, bool use_malloc) { data.buffer = BigBuf_get_addr(); } else { *sample_size = MIN(*sample_size, BigBuf_max_traceLen()); - data.buffer = BigBuf_calloc(*sample_size); + data.buffer = BigBuf_malloc(*sample_size); } } else { @@ -669,7 +669,7 @@ void doT55x7Acquisition(size_t sample_size, bool ledcontrol) { void doCotagAcquisition(void) { uint16_t bufsize = BigBuf_max_traceLen(); - uint8_t *dest = BigBuf_calloc(bufsize); + uint8_t *dest = BigBuf_malloc(bufsize); dest[0] = 0; diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 13e728be8..d0fe1e524 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -83,14 +83,14 @@ static bool mifare_wakeup_auth(struct Crypto1State *pcs, MifareWakeupType wakeup break; } case MF_WAKE_WUPA: { - if (iso14443a_select_cardEx(NULL, NULL, &cuid, true, 0, true, &WUPA_POLLING_PARAMETERS, false) == 0) { + if (iso14443a_select_cardEx(NULL, NULL, &cuid, true, 0, true, &WUPA_POLLING_PARAMETERS) == 0) { if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); return false; }; break; } case MF_WAKE_REQA: { - if (iso14443a_select_cardEx(NULL, NULL, &cuid, true, 0, true, &REQA_POLLING_PARAMETERS, false) == 0) { + if (iso14443a_select_cardEx(NULL, NULL, &cuid, true, 0, true, &REQA_POLLING_PARAMETERS) == 0) { if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); return false; }; @@ -274,7 +274,7 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes) { return; }; - if (mifare_ultra_auth(keybytes) == 0) { + if (!mifare_ultra_auth(keybytes)) { if (g_dbglevel >= DBG_ERROR) Dbprintf("Authentication failed"); OnError(1); return; @@ -304,7 +304,7 @@ void MifareUL_AES_Auth(bool turn_off_field, uint8_t keyno, uint8_t *keybytes) { return; }; - if (mifare_ultra_aes_auth(keyno, keybytes) == 0) { + if (!mifare_ultra_aes_auth(keyno, keybytes)) { if (g_dbglevel >= DBG_ERROR) Dbprintf("Authentication failed"); OnErrorNG(CMD_HF_MIFAREULAES_AUTH, PM3_ESOFT); return; @@ -344,7 +344,7 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) { uint8_t key[16] = {0x00}; memcpy(key, datain, sizeof(key)); - if (mifare_ultra_auth(key) == 0) { + if (!mifare_ultra_auth(key)) { OnError(1); return; } @@ -1947,7 +1947,7 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da // Now append the SPI flash dictionnary if (SPIFFS_OK == rdv40_spiffs_read_as_filetype(MF_KEYS_FILE, dictkeys + (keyCount * MF_KEY_LENGTH), (key_mem_available - keyCount) * MF_KEY_LENGTH, RDV40_SPIFFS_SAFETY_SAFE)) { if (g_dbglevel >= DBG_ERROR) { - Dbprintf("loaded " _GREEN_("%u") " keys from spiffs file `" _YELLOW_("%s") "`", key_mem_available - keyCount, MF_KEYS_FILE); + Dbprintf("loaded " _GREEN_("%u") " keys from spiffs file `" _YELLOW_("%s") "`", key_mem_available, MF_KEYS_FILE); } } else { Dbprintf("Spiffs file `" _RED_("%s") "` cannot be read", MF_KEYS_FILE); @@ -2252,7 +2252,7 @@ OUT: bar |= ((uint16_t)(found[m] & 1) << j++); } - uint8_t *tmp = BigBuf_calloc(480 + 10); + uint8_t *tmp = BigBuf_malloc(480 + 10); memcpy(tmp, k_sector, sectorcnt * sizeof(sector_t)); num_to_bytes(foo, 8, tmp + 480); tmp[488] = bar & 0xFF; @@ -2409,7 +2409,7 @@ void MifareChkKeys_file(uint8_t *fn) { int changed = rdv40_spiffs_lazy_mount(); uint32_t size = size_in_spiffs((char *)fn); - uint8_t *mem = BigBuf_calloc(size); + uint8_t *mem = BigBuf_malloc(size); rdv40_spiffs_read_as_filetype((char *)fn, mem, size, RDV40_SPIFFS_SAFETY_SAFE); @@ -3022,10 +3022,9 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) { // reset card mf_reset_card(); - // Use special magic detection function that always attempts RATS regardless of SAK - res = iso14443a_select_card_for_magic(uid, card, &cuid, true, 0); + + res = iso14443a_select_card(uid, card, &cuid, true, 0, false); if (res) { - mf_reset_card(); if (cuid == 0xAA55C396) { flag |= MAGIC_FLAG_GEN_UNFUSED; } @@ -3221,7 +3220,7 @@ void MifareHasStaticNonce(void) { } if (counter) { - Dbprintf("Static nonce....... " _YELLOW_("%08x"), nt); + Dbprintf("Static nonce......... " _YELLOW_("%08x"), nt); data[0] = NONCE_STATIC; } else { data[0] = NONCE_NORMAL; @@ -3562,7 +3561,7 @@ void MifareGen3Blk(uint8_t block_len, uint8_t *block) { AddCrc14A(cmd, sizeof(block_cmd) + MIFARE_BLOCK_SIZE); if (doReselect) { - if (iso14443a_select_card(NULL, NULL, NULL, true, 0, true) == 0) { + if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { retval = PM3_ESOFT; goto OUT; } @@ -3609,13 +3608,13 @@ void MifareG4ReadBlk(uint8_t blockno, uint8_t *pwd, uint8_t workFlags) { int res = 0; int retval = PM3_SUCCESS; - uint8_t *buf = BigBuf_calloc(PM3_CMD_DATA_SIZE); + uint8_t *buf = BigBuf_malloc(PM3_CMD_DATA_SIZE); if (buf == NULL) { retval = PM3_EMALLOC; goto OUT; } - uint8_t *par = BigBuf_calloc(MAX_PARITY_SIZE); + uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE); if (par == NULL) { retval = PM3_EMALLOC; goto OUT; @@ -3685,7 +3684,7 @@ void MifareG4WriteBlk(uint8_t blockno, uint8_t *pwd, uint8_t *data, uint8_t work int res = 0; int retval = PM3_SUCCESS; - uint8_t *buf = BigBuf_calloc(PM3_CMD_DATA_SIZE); + uint8_t *buf = BigBuf_malloc(PM3_CMD_DATA_SIZE); if (buf == NULL) { retval = PM3_EMALLOC; goto OUT; @@ -3697,7 +3696,7 @@ void MifareG4WriteBlk(uint8_t blockno, uint8_t *pwd, uint8_t *data, uint8_t work goto OUT; } - uint8_t *par = BigBuf_calloc(MAX_PARITY_SIZE); + uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE); if (par == NULL) { retval = PM3_EMALLOC; goto OUT; diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index cc2996b23..448f475dd 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -60,7 +60,7 @@ bool InitDesfireCard(void) { iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); set_tracing(true); - if (iso14443a_select_card(NULL, &card, NULL, true, 0, false) == 0) { + if (!iso14443a_select_card(NULL, &card, NULL, true, 0, false)) { if (g_dbglevel >= DBG_ERROR) DbpString("Can't select card"); OnError(1); return false; @@ -157,7 +157,7 @@ void MifareDesfireGetInformation(void) { pcb_blocknum = 0; // card select - information - if (iso14443a_select_card(NULL, &card, NULL, true, 0, false) == 0) { + if (!iso14443a_select_card(NULL, &card, NULL, true, 0, false)) { if (g_dbglevel >= DBG_ERROR) { DbpString("Can't select card"); } diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index b69ebe0c6..7b7a48550 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -459,7 +459,7 @@ bool MifareSimInit(uint16_t flags, uint8_t *uid, uint16_t atqa, uint8_t sak, tag // 53 * 8 data bits, 53 * 1 parity bits, 18 start bits, 18 stop bits, 18 correction bits -> need 571 bytes buffer #define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 571 - uint8_t *free_buffer = BigBuf_calloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE); + uint8_t *free_buffer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE); // modulation buffer pointer and current buffer free space size uint8_t *free_buffer_pointer = free_buffer; size_t free_buffer_size = ALLOCATED_TAG_MODULATION_BUFFER_SIZE; @@ -579,6 +579,21 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t counter++; } + /* + // find reader field + if (cardSTATE == MFEMUL_NOFIELD) { + + vHf = (MAX_ADC_HF_VOLTAGE * SumAdc(ADC_CHAN_HF, 32)) >> 15; + + if (vHf > MF_MINFIELDV) { + cardSTATE_TO_IDLE(); + LED_A_ON(); + } + button_pushed = BUTTON_PRESS(); + continue; + } + */ + FpgaEnableTracing(); //Now, get data int res = EmGetCmd(receivedCmd, sizeof(receivedCmd), &receivedCmd_len, receivedCmd_par); @@ -745,6 +760,10 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t // WORK case MFEMUL_WORK: { + if (g_dbglevel >= DBG_EXTENDED) { + // Dbprintf("[MFEMUL_WORK] Enter in case"); + } + if (receivedCmd_len == 0) { if (g_dbglevel >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] NO CMD received"); break; @@ -790,11 +809,10 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t if (g_dbglevel >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] KEY %c: %012" PRIx64, (cardAUTHKEY == 0) ? 'A' : 'B', emlGetKey(cardAUTHSC, cardAUTHKEY)); // sector out of range - do not respond - if ((cardAUTHSC >= cardMaxSEC) && (flags & FLAG_MF_ALLOW_OOB_AUTH) == 0) { + if (cardAUTHSC >= cardMaxSEC) { cardAUTHKEY = AUTHKEYNONE; // not authenticated cardSTATE_TO_IDLE(); - if (g_dbglevel >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Out of range sector %d(0x%02x) >= %d(0x%02x)", cardAUTHSC, cardAUTHSC, cardMaxSEC, cardMaxSEC); - LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true); + if (g_dbglevel >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Out of range sector %d(0x%02x)", cardAUTHSC, cardAUTHSC); break; } diff --git a/armsrc/sam_common.c b/armsrc/sam_common.c index bfa959bba..75a5c3527 100644 --- a/armsrc/sam_common.c +++ b/armsrc/sam_common.c @@ -229,8 +229,7 @@ int sam_get_version(bool info) { uint16_t response_len = ISO7816_MAX_FRAME; uint8_t payload[] = { - 0xa0, // <- SAM command - 0x02, // <- Length + 0xa0, 0x02, // <- SAM command 0x82, 0x00 // <- get version }; uint16_t payload_len = sizeof(payload); @@ -279,7 +278,7 @@ int sam_get_version(bool info) { } if (g_dbglevel >= DBG_INFO || info) { DbpString(_BLUE_("-- SAM Information --")); - Dbprintf(_YELLOW_("Firmware version: ")"%d.%d", sam_version_an[2], sam_version_an[3]); + Dbprintf(_YELLOW_("Firmware version: ")"%X.%X", sam_version_an[2], sam_version_an[3]); Dbprintf(_YELLOW_("Firmware ID: ")); Dbhexdump(sam_build_an[1], sam_build_an + 2, false); } @@ -310,8 +309,7 @@ int sam_get_serial_number(void) { uint16_t response_len = ISO7816_MAX_FRAME; uint8_t payload[] = { - 0xa0, // <- SAM command - 0x02, // <- Length + 0xa0, 0x02, // <- SAM command 0x96, 0x00 // <- get serial number }; uint16_t payload_len = sizeof(payload); diff --git a/armsrc/sam_picopass.c b/armsrc/sam_picopass.c index 84ddf549b..fe9393283 100644 --- a/armsrc/sam_picopass.c +++ b/armsrc/sam_picopass.c @@ -103,13 +103,10 @@ static int sam_send_request_iso15(const uint8_t *const request, const uint8_t re nfc_tx_len = sam_copy_payload_sam2nfc(nfc_tx_buf, sam_rx_buf); - bool is_cmd_check = ((nfc_tx_buf[0] & 0x0F) == ICLASS_CMD_CHECK); - + bool is_cmd_check = (nfc_tx_buf[0] & 0x0F) == ICLASS_CMD_CHECK; if (is_cmd_check && break_on_nr_mac) { - memcpy(response, nfc_tx_buf, nfc_tx_len); *response_len = nfc_tx_len; - if (g_dbglevel >= DBG_INFO) { DbpString("NR-MAC: "); Dbhexdump((*response_len) - 1, response + 1, false); @@ -118,8 +115,7 @@ static int sam_send_request_iso15(const uint8_t *const request, const uint8_t re goto out; } - bool is_cmd_update = ((nfc_tx_buf[0] & 0x0F) == ICLASS_CMD_UPDATE); - + bool is_cmd_update = (nfc_tx_buf[0] & 0x0F) == ICLASS_CMD_UPDATE; if (is_cmd_update && prevent_epurse_update && nfc_tx_buf[0] == 0x87 && nfc_tx_buf[1] == 0x02) { // block update(2) command and fake the response to prevent update of epurse @@ -227,27 +223,18 @@ static int sam_send_request_iso15(const uint8_t *const request, const uint8_t re // 07 // 90 00 if (request_len == 0) { - - if (!(sam_rx_buf[5] == 0xbd && sam_rx_buf[5 + 2] == 0x8a && sam_rx_buf[5 + 4] == 0x03) && - !(sam_rx_buf[5] == 0xbd && sam_rx_buf[5 + 2] == 0xb3 && sam_rx_buf[5 + 4] == 0xa0)) { - - if (g_dbglevel >= DBG_ERROR) { + if ( + !(sam_rx_buf[5] == 0xbd && sam_rx_buf[5 + 2] == 0x8a && sam_rx_buf[5 + 4] == 0x03) + && + !(sam_rx_buf[5] == 0xbd && sam_rx_buf[5 + 2] == 0xb3 && sam_rx_buf[5 + 4] == 0xa0) + ) { + if (g_dbglevel >= DBG_ERROR) Dbprintf("No PACS data in SAM response"); - } res = PM3_ESOFT; } } - if (sam_rx_buf[6] == 0x81 && sam_rx_buf[8] == 0x8a && sam_rx_buf[9] == 0x81) { //check if the response is an SNMP message - *response_len = sam_rx_buf[5 + 2] + 3; - } else { //if not, use the old logic - *response_len = sam_rx_buf[5 + 1] + 2; - } - - if (sam_rx_buf[5] == 0xBD && sam_rx_buf[4] != 0x00) { //secure channel flag is not 0x00 - Dbprintf(_YELLOW_("Secure channel flag set to: ")"%02x", sam_rx_buf[4]); - } - + *response_len = sam_rx_buf[5 + 1] + 2; memcpy(response, sam_rx_buf + 5, *response_len); goto out; @@ -374,14 +361,14 @@ int sam_picopass_get_pacs(PacketCommandNG *c) { goto out; } - if (skipDetect == false) { + if (!skipDetect) { // step 2: get card information picopass_hdr_t card_a_info; uint32_t eof_time = 0; // implicit StartSspClk() happens here Iso15693InitReader(); - if (select_iclass_tag(&card_a_info, false, &eof_time, shallow_mod) == false) { + if (!select_iclass_tag(&card_a_info, false, &eof_time, shallow_mod)) { goto err; } @@ -396,10 +383,8 @@ int sam_picopass_get_pacs(PacketCommandNG *c) { if (res != PM3_SUCCESS) { goto err; } - - if (g_dbglevel >= DBG_INFO) { + if (g_dbglevel >= DBG_INFO) print_result("Response data", sam_response, sam_response_len); - } goto out; diff --git a/bootrom/Makefile b/bootrom/Makefile index b6825530d..86c785cd1 100644 --- a/bootrom/Makefile +++ b/bootrom/Makefile @@ -56,7 +56,7 @@ OBJS = $(OBJDIR)/bootrom.s19 # version_pm3.c should be checked on every compilation version_pm3.c: default_version_pm3.c .FORCE $(info [=] CHECK $@) - $(Q)$(SH) ../tools/mkversion.sh $@ || $(CP) $< $@ + $(Q)$(CP) $< $@ all: showinfo $(OBJS) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 1f0410e31..615c581cf 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -402,7 +402,6 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/cmdlfvisa2000.c ${PM3_ROOT}/client/src/cmdlfzx8211.c ${PM3_ROOT}/client/src/cmdmain.c - ${PM3_ROOT}/client/src/cmdmqtt.c ${PM3_ROOT}/client/src/cmdnfc.c ${PM3_ROOT}/client/src/cmdparser.c ${PM3_ROOT}/client/src/cmdpiv.c @@ -435,7 +434,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 || ${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 ) @@ -693,7 +692,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) @@ -773,7 +772,6 @@ target_link_libraries(proxmark3 PRIVATE pm3rrg_rdv4_reveng pm3rrg_rdv4_hardnested pm3rrg_rdv4_id48 - pm3rrg_rdv4_mqtt ${ADDITIONAL_LNK}) if (NOT SKIPPTHREAD EQUAL 1) diff --git a/client/Makefile b/client/Makefile index 777343d07..89f7a17a4 100644 --- a/client/Makefile +++ b/client/Makefile @@ -17,8 +17,6 @@ ifeq ($(PLTNAME),) -include ../Makefile.platform -include ../.Makefile.options.cache -# Default platform if no platform specified - PLATFORM?=PM3RDV4 ifneq ($(PLATFORM), $(CACHED_PLATFORM)) $(error platform definitions have been changed, please "make clean" at the root of the project) endif @@ -133,12 +131,6 @@ WHEREAMILIBINC = -I$(WHEREAMILIBPATH) WHEREAMILIB = $(WHEREAMILIBPATH)/libwhereami.a WHEREAMILIBLD = -## MQTT -MQTTLIBPATH = ./deps/mqtt -MQTTLIBINC = -I$(MQTTLIBPATH) -MQTTLIB = $(MQTTLIBPATH)/mqtt.a -MQTTLIBLD = - ########################## # common local libraries # ########################## @@ -247,12 +239,6 @@ STATICLIBS += $(WHEREAMILIB) LDLIBS += $(WHEREAMILIBLD) PM3INCLUDES += $(WHEREAMILIBINC) -## MQTT -# not distributed as system library -STATICLIBS += $(MQTTLIB) -LDLIBS += $(MQTTLIBLD) -PM3INCLUDES += $(MQTTLIBINC) - #################### # system libraries # #################### @@ -454,14 +440,13 @@ endif ifeq ($(SWIG_LUA_FOUND),1) PM3CFLAGS += -DHAVE_LUA_SWIG endif - ifeq ($(SWIG_PYTHON_FOUND),1) PM3CFLAGS += -DHAVE_PYTHON_SWIG endif PM3CFLAGS += -DHAVE_SNPRINTF -CXXFLAGS ?= -Wall -Werror +CXXFLAGS ?= -Wall CXXFLAGS += $(MYDEFS) $(MYCXXFLAGS) $(MYINCLUDES) PM3CXXFLAGS = $(CXXFLAGS) @@ -597,7 +582,6 @@ endif ifeq ($(SWIG_LUA_FOUND),1) $(info Lua SWIG: wrapper found) endif - ifeq ($(SWIG_PYTHON_FOUND),1) $(info Python SWIG: wrapper found) endif @@ -698,7 +682,6 @@ SRCS = mifare/aiddesfire.c \ cmdlfvisa2000.c \ cmdlfzx8211.c \ cmdmain.c \ - cmdmqtt.c \ cmdnfc.c \ cmdparser.c \ cmdpiv.c \ @@ -894,7 +877,6 @@ endif $(Q)$(MAKE) --no-print-directory -C $(REVENGLIBPATH) clean $(Q)$(MAKE) --no-print-directory -C $(TINYCBORLIBPATH) clean $(Q)$(MAKE) --no-print-directory -C $(WHEREAMILIBPATH) clean - $(Q)$(MAKE) --no-print-directory -C $(MQTTLIBPATH) clean @# Just in case someone compiled within these dirs: $(Q)$(MAKE) --no-print-directory -C $(MBEDTLSLIBPATH) clean @@ -992,10 +974,6 @@ ifneq ($(WHEREAMI_FOUND),1) $(Q)$(MAKE) --no-print-directory -C $(WHEREAMILIBPATH) all endif -$(MQTTLIB): .FORCE - $(info [*] MAKE $@) - $(Q)$(MAKE) --no-print-directory -C $(MQTTLIBPATH) all - ######## # SWIG # ######## @@ -1017,7 +995,7 @@ src/pm3_pywrap.c: pm3.i # version_pm3.c should be checked on every compilation src/version_pm3.c: default_version_pm3.c .FORCE $(info [=] CHECK $@) - $(Q)$(SH) ../tools/mkversion.sh $@ || $(CP) $< $@ + $(Q)$(CP) $< $@ # easy printing of MAKE VARIABLES print-%: ; @echo $* = $($*) diff --git a/client/deps/CMakeLists.txt b/client/deps/CMakeLists.txt index c8f5b78c5..99a843d66 100644 --- a/client/deps/CMakeLists.txt +++ b/client/deps/CMakeLists.txt @@ -31,6 +31,3 @@ endif() if (NOT TARGET pm3rrg_rdv4_whereami) include(whereami.cmake) endif() -if (NOT TARGET pm3rrg_rdv4_mqtt) - include(mqtt.cmake) -endif() \ No newline at end of file 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 ec545e2a8..468ee4ef2 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 @@ -32,7 +32,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) @@ -47,7 +47,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) @@ -62,7 +62,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) @@ -77,7 +77,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) @@ -92,7 +92,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) @@ -116,7 +116,7 @@ elseif ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST ARM64_CPUS) hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c) - target_compile_options(pm3rrg_rdv4_hardnested_neon PRIVATE -Wall -Werror -O3) + target_compile_options(pm3rrg_rdv4_hardnested_neon PRIVATE -Wall -O3) set_property(TARGET pm3rrg_rdv4_hardnested_neon PROPERTY POSITION_INDEPENDENT_CODE ON) target_include_directories(pm3rrg_rdv4_hardnested_neon PRIVATE @@ -134,7 +134,7 @@ elseif ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST ARM32_CPUS) hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c) - target_compile_options(pm3rrg_rdv4_hardnested_neon PRIVATE -Wall -Werror -O3) + target_compile_options(pm3rrg_rdv4_hardnested_neon PRIVATE -Wall -O3) target_compile_options(pm3rrg_rdv4_hardnested_neon BEFORE PRIVATE -mfpu=neon) set_property(TARGET pm3rrg_rdv4_hardnested_neon PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -155,7 +155,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/hardnested/hardnested_bruteforce.c b/client/deps/hardnested/hardnested_bruteforce.c index c5d6aef43..655ef9dbb 100644 --- a/client/deps/hardnested/hardnested_bruteforce.c +++ b/client/deps/hardnested/hardnested_bruteforce.c @@ -177,15 +177,14 @@ crack_states_thread(void *x) { char progress_text[80]; char keystr[19]; - snprintf(keystr, sizeof(keystr), "%012" PRIX64, key); + snprintf(keystr, sizeof(keystr), "%012" PRIX64 " ", key); snprintf(progress_text, sizeof(progress_text), "Brute force phase completed. Key found: " _GREEN_("%s"), keystr); hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, 0.0, 0); - PrintAndLogEx(INFO, "---------+---------+---------------------------------------------------------+-----------------+-------"); break; } else if (keys_found) { break; } else { - if (thread_arg->silent == false) { + if (!thread_arg->silent) { char progress_text[80]; snprintf(progress_text, sizeof(progress_text), "Brute force phase: %6.02f%% ", 100.0 * (float)num_keys_tested / (float)(thread_arg->maximum_states)); float remaining_bruteforce = thread_arg->nonces[thread_arg->best_first_bytes[0]].expected_num_brute_force - (float)num_keys_tested / 2; @@ -338,7 +337,7 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint bucket_count = 0; for (statelist_t *p = candidates; p != NULL; p = p->next) { if (p->states[ODD_STATE] != NULL && p->states[EVEN_STATE] != NULL) { - if (ensure_buckets_alloc(bucket_count + 1) == false) { + if (!ensure_buckets_alloc(bucket_count + 1)) { PrintAndLogEx(ERR, "Can't allocate buckets, abort!"); return false; } @@ -376,7 +375,6 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint thread_args[i].best_first_bytes = best_first_bytes; pthread_create(&threads[i], NULL, crack_states_thread, (void *)&thread_args[i]); } - for (uint32_t i = 0; i < num_brute_force_threads; i++) { pthread_join(threads[i], 0); } @@ -387,13 +385,11 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint uint64_t elapsed_time = msclock() - start_time; - if (bf_rate != NULL) { + if (bf_rate != NULL) *bf_rate = (float)num_keys_tested / ((float)elapsed_time / 1000.0); - } - if (keys_found > 0) { + if (keys_found > 0) *found_key = found_bs_key; - } return (keys_found != 0); } diff --git a/client/deps/id48lib.cmake b/client/deps/id48lib.cmake index 47205d494..fa57d7855 100644 --- a/client/deps/id48lib.cmake +++ b/client/deps/id48lib.cmake @@ -3,7 +3,7 @@ add_library(pm3rrg_rdv4_id48 STATIC id48/id48_generator.c id48/id48_recover.c ) -target_compile_options( pm3rrg_rdv4_id48 PRIVATE -Wpedantic -Wall -Werror -O3 -Wno-unknown-pragmas -Wno-inline -Wno-unused-function -DID48_NO_STDIO) +target_compile_options( pm3rrg_rdv4_id48 PRIVATE -Wpedantic -Wall -O3 -Wno-unknown-pragmas -Wno-inline -Wno-unused-function -DID48_NO_STDIO) target_include_directories(pm3rrg_rdv4_id48 PRIVATE id48) target_include_directories(pm3rrg_rdv4_id48 INTERFACE id48) set_property(TARGET pm3rrg_rdv4_id48 PROPERTY POSITION_INDEPENDENT_CODE ON) 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/jansson/dump.c b/client/deps/jansson/dump.c index 9c04063e0..afdec8f7a 100644 --- a/client/deps/jansson/dump.c +++ b/client/deps/jansson/dump.c @@ -440,32 +440,33 @@ int json_dumpfd(const json_t *json, int output, size_t flags) { } int json_dump_file(const json_t *json, const char *path, size_t flags) { + int result; - FILE *f = fopen(path, "w"); - if (f == NULL) { - return -1; - } - - int res = json_dumpf(json, f, flags); - - if (fclose(f) != 0) + FILE *output = fopen(path, "w"); + if (!output) return -1; - return res; + result = json_dumpf(json, output, flags); + + if (fclose(output) != 0) + return -1; + + return result; } int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags) { + int res; + hashtable_t parents_set; + if (!(flags & JSON_ENCODE_ANY)) { - if (!json_is_array(json) && !json_is_object(json)) { + if (!json_is_array(json) && !json_is_object(json)) return -1; - } } - hashtable_t parents_set; - if (hashtable_init(&parents_set)) { + if (hashtable_init(&parents_set)) return -1; - } - int res = do_dump(json, flags, 0, &parents_set, callback, data); + res = do_dump(json, flags, 0, &parents_set, callback, data); hashtable_close(&parents_set); + return res; } diff --git a/client/deps/lua.cmake b/client/deps/lua.cmake index d89275be6..3bf85e1ce 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 f33d5ac51..7c72925ab 100644 --- a/client/deps/mbedtls.cmake +++ b/client/deps/mbedtls.cmake @@ -44,10 +44,10 @@ add_library(pm3rrg_rdv4_mbedtls STATIC ../../common/mbedtls/x509.c ../../common/mbedtls/x509_crl.c ../../common/mbedtls/x509_crt.c - ../../common/mbedtls/net_sockets.c + ../../common/mbedtls/net_sockets.c ) 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/mqtt.cmake b/client/deps/mqtt.cmake deleted file mode 100644 index f30e761c3..000000000 --- a/client/deps/mqtt.cmake +++ /dev/null @@ -1,9 +0,0 @@ -add_library(pm3rrg_rdv4_mqtt STATIC - mqtt/mqtt.c - mqtt/mqtt_pal.c - ) - -target_compile_definitions(pm3rrg_rdv4_mqtt PRIVATE WAI_PM3_TUNED) -target_include_directories(pm3rrg_rdv4_mqtt INTERFACE mqtt) -target_compile_options(pm3rrg_rdv4_mqtt PRIVATE -Wall -Werror -O3) -set_property(TARGET pm3rrg_rdv4_mqtt PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/client/deps/mqtt/LICENSE b/client/deps/mqtt/LICENSE deleted file mode 100644 index 0bbb84557..000000000 --- a/client/deps/mqtt/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018 Liam Bindle - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/client/deps/mqtt/Makefile b/client/deps/mqtt/Makefile deleted file mode 100644 index af4679674..000000000 --- a/client/deps/mqtt/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -MYSRCPATHS = -MYINCLUDES = -MYCFLAGS = -Wno-bad-function-cast -Wno-switch-enum -MYDEFS = -DWAI_PM3_TUNED -MYSRCS = \ - mqtt.c \ - mqtt_pal.c \ - -LIB_A = mqtt.a - -# Transition: remove old directories and objects -MYCLEANOLDPATH = ../../mqtt - -include ../../../Makefile.host diff --git a/client/deps/mqtt/mbedtls_sockets.h b/client/deps/mqtt/mbedtls_sockets.h deleted file mode 100644 index 1295152f9..000000000 --- a/client/deps/mqtt/mbedtls_sockets.h +++ /dev/null @@ -1,152 +0,0 @@ -#if !defined(__MBEDTLS_SOCKET_TEMPLATE_H__) -#define __MBEDTLS_SOCKET_TEMPLATE_H__ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#if !defined(MBEDTLS_NET_POLL_READ) -/* compat for older mbedtls */ -#define MBEDTLS_NET_POLL_READ 1 -#define MBEDTLS_NET_POLL_WRITE 1 - -int mbedtls_net_poll(mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout) { - /* XXX this is not ideal but good enough for an example */ - msleep(300); - return 1; -} -#endif - -struct mbedtls_context { - mbedtls_net_context net_ctx; - mbedtls_ssl_context ssl_ctx; - mbedtls_ssl_config ssl_conf; - mbedtls_x509_crt ca_crt; - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; -}; - -void failed(const char *fn, int rv); -void cert_verify_failed(uint32_t rv); -void open_nb_socket(struct mbedtls_context *ctx, - const char *hostname, - const char *port, - const char *ca_file); - - -void failed(const char *fn, int rv) { - char buf[100]; - mbedtls_strerror(rv, buf, sizeof(buf)); - printf("%s failed with %x (%s)\n", fn, -rv, buf); - exit(1); -} - -void cert_verify_failed(uint32_t rv) { - char buf[512]; - mbedtls_x509_crt_verify_info(buf, sizeof(buf), "\t", rv); - printf("Certificate verification failed (%0" PRIx32 ")\n%s\n", rv, buf); - exit(1); -} - -/* - A template for opening a non-blocking mbed TLS connection. -*/ -void open_nb_socket(struct mbedtls_context *ctx, - const char *hostname, - const char *port, - const char *ca_file) { - - const unsigned char *additional = (const unsigned char *)"Pm3 Client"; - size_t additional_len = 6; - int rv; - - mbedtls_net_context *net_ctx = &ctx->net_ctx; - mbedtls_ssl_context *ssl_ctx = &ctx->ssl_ctx; - mbedtls_ssl_config *ssl_conf = &ctx->ssl_conf; - mbedtls_x509_crt *ca_crt = &ctx->ca_crt; - mbedtls_entropy_context *entropy = &ctx->entropy; - mbedtls_ctr_drbg_context *ctr_drbg = &ctx->ctr_drbg; - - mbedtls_entropy_init(entropy); - mbedtls_ctr_drbg_init(ctr_drbg); - rv = mbedtls_ctr_drbg_seed(ctr_drbg, mbedtls_entropy_func, entropy, - additional, additional_len); - if (rv != 0) { - failed("mbedtls_ctr_drbg_seed", rv); - } - - mbedtls_x509_crt_init(ca_crt); - rv = mbedtls_x509_crt_parse_file(ca_crt, ca_file); - if (rv != 0) { - failed("mbedtls_x509_crt_parse_file", rv); - } - - mbedtls_ssl_config_init(ssl_conf); - rv = mbedtls_ssl_config_defaults(ssl_conf, MBEDTLS_SSL_IS_CLIENT, - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT); - if (rv != 0) { - failed("mbedtls_ssl_config_defaults", rv); - } - mbedtls_ssl_conf_ca_chain(ssl_conf, ca_crt, NULL); - mbedtls_ssl_conf_authmode(ssl_conf, MBEDTLS_SSL_VERIFY_OPTIONAL); - mbedtls_ssl_conf_rng(ssl_conf, mbedtls_ctr_drbg_random, ctr_drbg); - - mbedtls_net_init(net_ctx); - rv = mbedtls_net_connect(net_ctx, hostname, port, MBEDTLS_NET_PROTO_TCP); - if (rv != 0) { - failed("mbedtls_net_connect", rv); - } - rv = mbedtls_net_set_nonblock(net_ctx); - if (rv != 0) { - failed("mbedtls_net_set_nonblock", rv); - } - - mbedtls_ssl_init(ssl_ctx); - rv = mbedtls_ssl_setup(ssl_ctx, ssl_conf); - if (rv != 0) { - failed("mbedtls_ssl_setup", rv); - } - rv = mbedtls_ssl_set_hostname(ssl_ctx, hostname); - if (rv != 0) { - failed("mbedtls_ssl_set_hostname", rv); - } - mbedtls_ssl_set_bio(ssl_ctx, net_ctx, - mbedtls_net_send, mbedtls_net_recv, NULL); - - for (;;) { - rv = mbedtls_ssl_handshake(ssl_ctx); - uint32_t want = 0; - if (rv == MBEDTLS_ERR_SSL_WANT_READ) { - want |= MBEDTLS_NET_POLL_READ; - } else if (rv == MBEDTLS_ERR_SSL_WANT_WRITE) { - want |= MBEDTLS_NET_POLL_WRITE; - } else { - break; - } - rv = mbedtls_net_poll(net_ctx, want, (uint32_t) -1); - if (rv < 0) { - failed("mbedtls_net_poll", rv); - } - } - if (rv != 0) { - failed("mbedtls_ssl_handshake", rv); - } - uint32_t result = mbedtls_ssl_get_verify_result(ssl_ctx); - if (result != 0) { - if (result == (uint32_t) -1) { - failed("mbedtls_ssl_get_verify_result", (int)result); - } else { - cert_verify_failed(result); - } - } -} - -#endif diff --git a/client/deps/mqtt/mqtt.c b/client/deps/mqtt/mqtt.c deleted file mode 100644 index b29f9d9d4..000000000 --- a/client/deps/mqtt/mqtt.c +++ /dev/null @@ -1,1770 +0,0 @@ -/* -MIT License - -Copyright(c) 2018 Liam Bindle - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include "mqtt.h" - -/** - * @file - * @brief Implements the functionality of MQTT-C. - * @note The only files that are included are mqtt.h and mqtt_pal.h. - * - * @cond Doxygen_Suppress - */ - -enum MQTTErrors mqtt_sync(struct mqtt_client *client) { - /* Recover from any errors */ - enum MQTTErrors err; - int reconnecting = 0; - MQTT_PAL_MUTEX_LOCK(&client->mutex); - if (client->error != MQTT_ERROR_RECONNECTING && client->error != MQTT_OK && client->reconnect_callback != NULL) { - client->reconnect_callback(client, &client->reconnect_state); - if (client->error != MQTT_OK) { - client->error = MQTT_ERROR_RECONNECT_FAILED; - - /* normally unlocked during CONNECT */ - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - } - err = client->error; - - if (err != MQTT_OK) return err; - } else { - /* mqtt_reconnect will have queued the disconnect packet - that needs to be sent and then call reconnect */ - if (client->error == MQTT_ERROR_RECONNECTING) { - reconnecting = 1; - client->error = MQTT_OK; - } - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - } - - /* Call inspector callback if necessary */ - - if (client->inspector_callback != NULL) { - MQTT_PAL_MUTEX_LOCK(&client->mutex); - err = client->inspector_callback(client); - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - if (err != MQTT_OK) return err; - } - - /* Call receive */ - err = (enum MQTTErrors)__mqtt_recv(client); - if (err != MQTT_OK) return err; - - /* Call send */ - err = (enum MQTTErrors)__mqtt_send(client); - - /* mqtt_reconnect will essentially be a disconnect if there is no callback */ - if (reconnecting && client->reconnect_callback != NULL) { - MQTT_PAL_MUTEX_LOCK(&client->mutex); - client->reconnect_callback(client, &client->reconnect_state); - } - - return err; -} - -uint16_t __mqtt_next_pid(struct mqtt_client *client) { - int pid_exists = 0; - if (client->pid_lfsr == 0) { - client->pid_lfsr = 163u; - } - /* LFSR taps taken from: https://en.wikipedia.org/wiki/Linear-feedback_shift_register */ - - do { - struct mqtt_queued_message *curr; - unsigned lsb = client->pid_lfsr & 1; - (client->pid_lfsr) >>= 1; - if (lsb) { - client->pid_lfsr ^= 0xB400u; - } - - /* check that the PID is unique */ - pid_exists = 0; - for (curr = mqtt_mq_get(&(client->mq), 0); curr >= client->mq.queue_tail; --curr) { - if (curr->packet_id == client->pid_lfsr) { - pid_exists = 1; - break; - } - } - - } while (pid_exists); - return client->pid_lfsr; -} - -enum MQTTErrors mqtt_init(struct mqtt_client *client, - mqtt_pal_socket_handle sockfd, - uint8_t *sendbuf, size_t sendbufsz, - uint8_t *recvbuf, size_t recvbufsz, - void (*publish_response_callback)(void **state, struct mqtt_response_publish *publish)) { - if (client == NULL || sendbuf == NULL || recvbuf == NULL) { - return MQTT_ERROR_NULLPTR; - } - - /* initialize mutex */ - MQTT_PAL_MUTEX_INIT(&client->mutex); - MQTT_PAL_MUTEX_LOCK(&client->mutex); /* unlocked during CONNECT */ - - client->socketfd = sockfd; - - mqtt_mq_init(&client->mq, sendbuf, sendbufsz); - - client->recv_buffer.mem_start = recvbuf; - client->recv_buffer.mem_size = recvbufsz; - client->recv_buffer.curr = client->recv_buffer.mem_start; - client->recv_buffer.curr_sz = client->recv_buffer.mem_size; - - client->error = MQTT_ERROR_CONNECT_NOT_CALLED; - client->response_timeout = 30; - client->number_of_timeouts = 0; - client->number_of_keep_alives = 0; - client->typical_response_time = -1.0f; - client->publish_response_callback = publish_response_callback; - client->pid_lfsr = 0; - client->send_offset = 0; - - client->inspector_callback = NULL; - client->reconnect_callback = NULL; - client->reconnect_state = NULL; - - return MQTT_OK; -} - -void mqtt_init_reconnect(struct mqtt_client *client, - void (*reconnect)(struct mqtt_client *, void **), - void *reconnect_state, - void (*publish_response_callback)(void **state, struct mqtt_response_publish *publish)) { - /* initialize mutex */ - MQTT_PAL_MUTEX_INIT(&client->mutex); - - client->socketfd = (mqtt_pal_socket_handle) - 1; - - mqtt_mq_init(&client->mq, NULL, 0uL); - - client->recv_buffer.mem_start = NULL; - client->recv_buffer.mem_size = 0; - client->recv_buffer.curr = NULL; - client->recv_buffer.curr_sz = 0; - - client->error = MQTT_ERROR_INITIAL_RECONNECT; - client->response_timeout = 30; - client->number_of_timeouts = 0; - client->number_of_keep_alives = 0; - client->typical_response_time = -1.0f; - client->publish_response_callback = publish_response_callback; - client->pid_lfsr = 0; - client->send_offset = 0; - - client->inspector_callback = NULL; - client->reconnect_callback = reconnect; - client->reconnect_state = reconnect_state; -} - -void mqtt_reinit(struct mqtt_client *client, - mqtt_pal_socket_handle socketfd, - uint8_t *sendbuf, size_t sendbufsz, - uint8_t *recvbuf, size_t recvbufsz) { - client->error = MQTT_ERROR_CONNECT_NOT_CALLED; - client->socketfd = socketfd; - - mqtt_mq_init(&client->mq, sendbuf, sendbufsz); - - client->recv_buffer.mem_start = recvbuf; - client->recv_buffer.mem_size = recvbufsz; - client->recv_buffer.curr = client->recv_buffer.mem_start; - client->recv_buffer.curr_sz = client->recv_buffer.mem_size; -} - -/** - * A macro function that: - * 1) Checks that the client isn't in an error state. - * 2) Attempts to pack to client's message queue. - * a) handles errors - * b) if mq buffer is too small, cleans it and tries again - * 3) Upon successful pack, registers the new message. - */ -#define MQTT_CLIENT_TRY_PACK(tmp, msg, client, pack_call, release) \ - if (client->error < 0) { \ - if (release) MQTT_PAL_MUTEX_UNLOCK(&client->mutex); \ - return client->error; \ - } \ - tmp = pack_call; \ - if (tmp < 0) { \ - client->error = (enum MQTTErrors)tmp; \ - if (release) MQTT_PAL_MUTEX_UNLOCK(&client->mutex); \ - return (enum MQTTErrors)tmp; \ - } else if (tmp == 0) { \ - mqtt_mq_clean(&client->mq); \ - tmp = pack_call; \ - if (tmp < 0) { \ - client->error = (enum MQTTErrors)tmp; \ - if (release) MQTT_PAL_MUTEX_UNLOCK(&client->mutex); \ - return (enum MQTTErrors)tmp; \ - } else if(tmp == 0) { \ - client->error = MQTT_ERROR_SEND_BUFFER_IS_FULL; \ - if (release) MQTT_PAL_MUTEX_UNLOCK(&client->mutex); \ - return (enum MQTTErrors)MQTT_ERROR_SEND_BUFFER_IS_FULL; \ - } \ - } \ - msg = mqtt_mq_register(&client->mq, (size_t)tmp); \ - - -enum MQTTErrors mqtt_connect(struct mqtt_client *client, - const char *client_id, - const char *will_topic, - const void *will_message, - size_t will_message_size, - const char *user_name, - const char *password, - uint8_t connect_flags, - uint16_t keep_alive) { - ssize_t rv; - struct mqtt_queued_message *msg; - - /* Note: Current thread already has mutex locked. */ - - /* update the client's state */ - client->keep_alive = keep_alive; - if (client->error == MQTT_ERROR_CONNECT_NOT_CALLED) { - client->error = MQTT_OK; - } - - /* try to pack the message */ - MQTT_CLIENT_TRY_PACK(rv, msg, client, - mqtt_pack_connection_request( - client->mq.curr, client->mq.curr_sz, - client_id, will_topic, will_message, - will_message_size, user_name, password, - connect_flags, keep_alive - ), - 1 - ); - /* save the control type of the message */ - msg->control_type = MQTT_CONTROL_CONNECT; - - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - return MQTT_OK; -} - -enum MQTTErrors mqtt_publish(struct mqtt_client *client, - const char *topic_name, - const void *application_message, - size_t application_message_size, - uint8_t publish_flags) { - struct mqtt_queued_message *msg; - ssize_t rv; - uint16_t packet_id; - MQTT_PAL_MUTEX_LOCK(&client->mutex); - packet_id = __mqtt_next_pid(client); - - - /* try to pack the message */ - MQTT_CLIENT_TRY_PACK( - rv, msg, client, - mqtt_pack_publish_request( - client->mq.curr, client->mq.curr_sz, - topic_name, - packet_id, - application_message, - application_message_size, - publish_flags - ), - 1 - ); - /* save the control type and packet id of the message */ - msg->control_type = MQTT_CONTROL_PUBLISH; - msg->packet_id = packet_id; - - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - return MQTT_OK; -} - -ssize_t __mqtt_puback(struct mqtt_client *client, uint16_t packet_id) { - ssize_t rv; - struct mqtt_queued_message *msg; - - /* try to pack the message */ - MQTT_CLIENT_TRY_PACK( - rv, msg, client, - mqtt_pack_pubxxx_request( - client->mq.curr, client->mq.curr_sz, - MQTT_CONTROL_PUBACK, - packet_id - ), - 0 - ); - /* save the control type and packet id of the message */ - msg->control_type = MQTT_CONTROL_PUBACK; - msg->packet_id = packet_id; - - return MQTT_OK; -} - -ssize_t __mqtt_pubrec(struct mqtt_client *client, uint16_t packet_id) { - ssize_t rv; - struct mqtt_queued_message *msg; - - /* try to pack the message */ - MQTT_CLIENT_TRY_PACK( - rv, msg, client, - mqtt_pack_pubxxx_request( - client->mq.curr, client->mq.curr_sz, - MQTT_CONTROL_PUBREC, - packet_id - ), - 0 - ); - /* save the control type and packet id of the message */ - msg->control_type = MQTT_CONTROL_PUBREC; - msg->packet_id = packet_id; - - return MQTT_OK; -} - -ssize_t __mqtt_pubrel(struct mqtt_client *client, uint16_t packet_id) { - ssize_t rv; - struct mqtt_queued_message *msg; - - /* try to pack the message */ - MQTT_CLIENT_TRY_PACK( - rv, msg, client, - mqtt_pack_pubxxx_request( - client->mq.curr, client->mq.curr_sz, - MQTT_CONTROL_PUBREL, - packet_id - ), - 0 - ); - /* save the control type and packet id of the message */ - msg->control_type = MQTT_CONTROL_PUBREL; - msg->packet_id = packet_id; - - return MQTT_OK; -} - -ssize_t __mqtt_pubcomp(struct mqtt_client *client, uint16_t packet_id) { - ssize_t rv; - struct mqtt_queued_message *msg; - - /* try to pack the message */ - MQTT_CLIENT_TRY_PACK( - rv, msg, client, - mqtt_pack_pubxxx_request( - client->mq.curr, client->mq.curr_sz, - MQTT_CONTROL_PUBCOMP, - packet_id - ), - 0 - ); - /* save the control type and packet id of the message */ - msg->control_type = MQTT_CONTROL_PUBCOMP; - msg->packet_id = packet_id; - - return MQTT_OK; -} - -enum MQTTErrors mqtt_subscribe(struct mqtt_client *client, - const char *topic_name, - int max_qos_level) { - ssize_t rv; - uint16_t packet_id; - struct mqtt_queued_message *msg; - MQTT_PAL_MUTEX_LOCK(&client->mutex); - packet_id = __mqtt_next_pid(client); - - /* try to pack the message */ - MQTT_CLIENT_TRY_PACK( - rv, msg, client, - mqtt_pack_subscribe_request( - client->mq.curr, client->mq.curr_sz, - packet_id, - topic_name, - max_qos_level, - (const char *)NULL - ), - 1 - ); - /* save the control type and packet id of the message */ - msg->control_type = MQTT_CONTROL_SUBSCRIBE; - msg->packet_id = packet_id; - - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - return MQTT_OK; -} - -enum MQTTErrors mqtt_unsubscribe(struct mqtt_client *client, - const char *topic_name) { - uint16_t packet_id = __mqtt_next_pid(client); - ssize_t rv; - struct mqtt_queued_message *msg; - MQTT_PAL_MUTEX_LOCK(&client->mutex); - - /* try to pack the message */ - MQTT_CLIENT_TRY_PACK( - rv, msg, client, - mqtt_pack_unsubscribe_request( - client->mq.curr, client->mq.curr_sz, - packet_id, - topic_name, - (const char *)NULL - ), - 1 - ); - /* save the control type and packet id of the message */ - msg->control_type = MQTT_CONTROL_UNSUBSCRIBE; - msg->packet_id = packet_id; - - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - return MQTT_OK; -} - -enum MQTTErrors mqtt_ping(struct mqtt_client *client) { - enum MQTTErrors rv; - MQTT_PAL_MUTEX_LOCK(&client->mutex); - rv = __mqtt_ping(client); - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - return rv; -} - -enum MQTTErrors __mqtt_ping(struct mqtt_client *client) { - ssize_t rv; - struct mqtt_queued_message *msg; - - /* try to pack the message */ - MQTT_CLIENT_TRY_PACK( - rv, msg, client, - mqtt_pack_ping_request( - client->mq.curr, client->mq.curr_sz - ), - 0 - ); - /* save the control type and packet id of the message */ - msg->control_type = MQTT_CONTROL_PINGREQ; - - - return MQTT_OK; -} - -enum MQTTErrors mqtt_reconnect(struct mqtt_client *client) { - enum MQTTErrors err = mqtt_disconnect(client); - - if (err == MQTT_OK) { - MQTT_PAL_MUTEX_LOCK(&client->mutex); - client->error = MQTT_ERROR_RECONNECTING; - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - } - return err; -} - -enum MQTTErrors mqtt_disconnect(struct mqtt_client *client) { - ssize_t rv; - struct mqtt_queued_message *msg; - MQTT_PAL_MUTEX_LOCK(&client->mutex); - - /* try to pack the message */ - MQTT_CLIENT_TRY_PACK( - rv, msg, client, - mqtt_pack_disconnect( - client->mq.curr, client->mq.curr_sz - ), - 1 - ); - /* save the control type and packet id of the message */ - msg->control_type = MQTT_CONTROL_DISCONNECT; - - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - return MQTT_OK; -} - -ssize_t __mqtt_send(struct mqtt_client *client) { - uint8_t inspected; - ssize_t len; - int inflight_qos2 = 0; - int i = 0; - - MQTT_PAL_MUTEX_LOCK(&client->mutex); - - if (client->error < 0 && client->error != MQTT_ERROR_SEND_BUFFER_IS_FULL) { - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - return client->error; - } - - /* loop through all messages in the queue */ - len = mqtt_mq_length(&client->mq); - for (; i < len; ++i) { - struct mqtt_queued_message *msg = mqtt_mq_get(&client->mq, i); - int resend = 0; - if (msg->state == MQTT_QUEUED_UNSENT) { - /* message has not been sent to lets send it */ - resend = 1; - } else if (msg->state == MQTT_QUEUED_AWAITING_ACK) { - /* check for timeout */ - if (MQTT_PAL_TIME() > msg->time_sent + client->response_timeout) { - resend = 1; - client->number_of_timeouts += 1; - client->send_offset = 0; - } - } - - /* only send QoS 2 message if there are no inflight QoS 2 PUBLISH messages */ - if (msg->control_type == MQTT_CONTROL_PUBLISH - && (msg->state == MQTT_QUEUED_UNSENT || msg->state == MQTT_QUEUED_AWAITING_ACK)) { - inspected = 0x03 & ((msg->start[0]) >> 1); /* qos */ - if (inspected == 2) { - if (inflight_qos2) { - resend = 0; - } - inflight_qos2 = 1; - } - } - - /* goto next message if we don't need to send */ - if (!resend) { - continue; - } - - /* we're sending the message */ - { - ssize_t tmp = mqtt_pal_sendall(client->socketfd, msg->start + client->send_offset, msg->size - client->send_offset, 0); - if (tmp < 0) { - client->error = (enum MQTTErrors)tmp; - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - return tmp; - } else { - client->send_offset += (unsigned long)tmp; - if (client->send_offset < msg->size) { - /* partial sent. Await additional calls */ - break; - } else { - /* whole message has been sent */ - client->send_offset = 0; - } - - } - - } - - /* update timeout watcher */ - client->time_of_last_send = MQTT_PAL_TIME(); - msg->time_sent = client->time_of_last_send; - - /* - Determine the state to put the message in. - Control Types: - MQTT_CONTROL_CONNECT -> awaiting - MQTT_CONTROL_CONNACK -> n/a - MQTT_CONTROL_PUBLISH -> qos == 0 ? complete : awaiting - MQTT_CONTROL_PUBACK -> complete - MQTT_CONTROL_PUBREC -> awaiting - MQTT_CONTROL_PUBREL -> awaiting - MQTT_CONTROL_PUBCOMP -> complete - MQTT_CONTROL_SUBSCRIBE -> awaiting - MQTT_CONTROL_SUBACK -> n/a - MQTT_CONTROL_UNSUBSCRIBE -> awaiting - MQTT_CONTROL_UNSUBACK -> n/a - MQTT_CONTROL_PINGREQ -> awaiting - MQTT_CONTROL_PINGRESP -> n/a - MQTT_CONTROL_DISCONNECT -> complete - */ - switch (msg->control_type) { - case MQTT_CONTROL_PUBACK: - case MQTT_CONTROL_PUBCOMP: - case MQTT_CONTROL_DISCONNECT: - msg->state = MQTT_QUEUED_COMPLETE; - break; - case MQTT_CONTROL_PUBLISH: - inspected = (MQTT_PUBLISH_QOS_MASK & (msg->start[0])) >> 1; /* qos */ - if (inspected == 0) { - msg->state = MQTT_QUEUED_COMPLETE; - } else if (inspected == 1) { - msg->state = MQTT_QUEUED_AWAITING_ACK; - /*set DUP flag for subsequent sends [Spec MQTT-3.3.1-1] */ - msg->start[0] |= MQTT_PUBLISH_DUP; - } else { - msg->state = MQTT_QUEUED_AWAITING_ACK; - } - break; - case MQTT_CONTROL_CONNECT: - case MQTT_CONTROL_PUBREC: - case MQTT_CONTROL_PUBREL: - case MQTT_CONTROL_SUBSCRIBE: - case MQTT_CONTROL_UNSUBSCRIBE: - case MQTT_CONTROL_PINGREQ: - msg->state = MQTT_QUEUED_AWAITING_ACK; - break; - default: - client->error = MQTT_ERROR_MALFORMED_REQUEST; - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - return MQTT_ERROR_MALFORMED_REQUEST; - } - } - - /* check for keep-alive */ - { - mqtt_pal_time_t keep_alive_timeout = client->time_of_last_send + (mqtt_pal_time_t)((float)(client->keep_alive)); - if (MQTT_PAL_TIME() > keep_alive_timeout) { - ssize_t rv = __mqtt_ping(client); - if (rv != MQTT_OK) { - client->error = (enum MQTTErrors)rv; - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - return rv; - } - } - } - - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - return MQTT_OK; -} - -ssize_t __mqtt_recv(struct mqtt_client *client) { - struct mqtt_response response; - ssize_t mqtt_recv_ret = MQTT_OK; - MQTT_PAL_MUTEX_LOCK(&client->mutex); - - /* read until there is nothing left to read, or there was an error */ - while (mqtt_recv_ret == MQTT_OK) { - /* read in as many bytes as possible */ - ssize_t rv, consumed; - struct mqtt_queued_message *msg = NULL; - - rv = mqtt_pal_recvall(client->socketfd, client->recv_buffer.curr, client->recv_buffer.curr_sz, 0); - if (rv < 0) { - /* an error occurred */ - client->error = (enum MQTTErrors)rv; - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - return rv; - } else { - client->recv_buffer.curr += rv; - client->recv_buffer.curr_sz -= (unsigned long)rv; - } - - /* attempt to parse */ - consumed = mqtt_unpack_response(&response, client->recv_buffer.mem_start, (size_t)(client->recv_buffer.curr - client->recv_buffer.mem_start)); - - if (consumed < 0) { - client->error = (enum MQTTErrors)consumed; - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - return consumed; - } else if (consumed == 0) { - /* if curr_sz is 0 then the buffer is too small to ever fit the message */ - if (client->recv_buffer.curr_sz == 0) { - client->error = MQTT_ERROR_RECV_BUFFER_TOO_SMALL; - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - return MQTT_ERROR_RECV_BUFFER_TOO_SMALL; - } - - /* just need to wait for the rest of the data */ - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - return MQTT_OK; - } - - /* response was unpacked successfully */ - - /* - The switch statement below manages how the client responds to messages from the broker. - - Control Types (that we expect to receive from the broker): - MQTT_CONTROL_CONNACK: - -> release associated CONNECT - -> handle response - MQTT_CONTROL_PUBLISH: - -> stage response, none if qos==0, PUBACK if qos==1, PUBREC if qos==2 - -> call publish callback - MQTT_CONTROL_PUBACK: - -> release associated PUBLISH - MQTT_CONTROL_PUBREC: - -> release PUBLISH - -> stage PUBREL - MQTT_CONTROL_PUBREL: - -> release associated PUBREC - -> stage PUBCOMP - MQTT_CONTROL_PUBCOMP: - -> release PUBREL - MQTT_CONTROL_SUBACK: - -> release SUBSCRIBE - -> handle response - MQTT_CONTROL_UNSUBACK: - -> release UNSUBSCRIBE - MQTT_CONTROL_PINGRESP: - -> release PINGREQ - */ - switch (response.fixed_header.control_type) { - case MQTT_CONTROL_CONNACK: - /* release associated CONNECT */ - msg = mqtt_mq_find(&client->mq, MQTT_CONTROL_CONNECT, NULL); - if (msg == NULL) { - client->error = MQTT_ERROR_ACK_OF_UNKNOWN; - mqtt_recv_ret = MQTT_ERROR_ACK_OF_UNKNOWN; - break; - } - msg->state = MQTT_QUEUED_COMPLETE; - /* initialize typical response time */ - client->typical_response_time = (float)(MQTT_PAL_TIME() - msg->time_sent); - /* check that connection was successful */ - if (response.decoded.connack.return_code != MQTT_CONNACK_ACCEPTED) { - if (response.decoded.connack.return_code == MQTT_CONNACK_REFUSED_IDENTIFIER_REJECTED) { - client->error = MQTT_ERROR_CONNECT_CLIENT_ID_REFUSED; - mqtt_recv_ret = MQTT_ERROR_CONNECT_CLIENT_ID_REFUSED; - } else { - client->error = MQTT_ERROR_CONNECTION_REFUSED; - mqtt_recv_ret = MQTT_ERROR_CONNECTION_REFUSED; - } - break; - } - break; - case MQTT_CONTROL_PUBLISH: - /* stage response, none if qos==0, PUBACK if qos==1, PUBREC if qos==2 */ - if (response.decoded.publish.qos_level == 1) { - rv = __mqtt_puback(client, response.decoded.publish.packet_id); - if (rv != MQTT_OK) { - client->error = (enum MQTTErrors)rv; - mqtt_recv_ret = rv; - break; - } - } else if (response.decoded.publish.qos_level == 2) { - /* check if this is a duplicate */ - if (mqtt_mq_find(&client->mq, MQTT_CONTROL_PUBREC, &response.decoded.publish.packet_id) != NULL) { - break; - } - - rv = __mqtt_pubrec(client, response.decoded.publish.packet_id); - if (rv != MQTT_OK) { - client->error = (enum MQTTErrors)rv; - mqtt_recv_ret = rv; - break; - } - } - /* call publish callback */ - client->publish_response_callback(&client->publish_response_callback_state, &response.decoded.publish); - break; - case MQTT_CONTROL_PUBACK: - /* release associated PUBLISH */ - msg = mqtt_mq_find(&client->mq, MQTT_CONTROL_PUBLISH, &response.decoded.puback.packet_id); - if (msg == NULL) { - client->error = MQTT_ERROR_ACK_OF_UNKNOWN; - mqtt_recv_ret = MQTT_ERROR_ACK_OF_UNKNOWN; - break; - } - msg->state = MQTT_QUEUED_COMPLETE; - /* update response time */ - client->typical_response_time = 0.875f * (client->typical_response_time) + 0.125f * (float)(MQTT_PAL_TIME() - msg->time_sent); - break; - case MQTT_CONTROL_PUBREC: - /* check if this is a duplicate */ - if (mqtt_mq_find(&client->mq, MQTT_CONTROL_PUBREL, &response.decoded.pubrec.packet_id) != NULL) { - break; - } - /* release associated PUBLISH */ - msg = mqtt_mq_find(&client->mq, MQTT_CONTROL_PUBLISH, &response.decoded.pubrec.packet_id); - if (msg == NULL) { - client->error = MQTT_ERROR_ACK_OF_UNKNOWN; - mqtt_recv_ret = MQTT_ERROR_ACK_OF_UNKNOWN; - break; - } - msg->state = MQTT_QUEUED_COMPLETE; - /* update response time */ - client->typical_response_time = 0.875f * (client->typical_response_time) + 0.125f * (float)(MQTT_PAL_TIME() - msg->time_sent); - /* stage PUBREL */ - rv = __mqtt_pubrel(client, response.decoded.pubrec.packet_id); - if (rv != MQTT_OK) { - client->error = (enum MQTTErrors)rv; - mqtt_recv_ret = rv; - break; - } - break; - case MQTT_CONTROL_PUBREL: - /* release associated PUBREC */ - msg = mqtt_mq_find(&client->mq, MQTT_CONTROL_PUBREC, &response.decoded.pubrel.packet_id); - if (msg == NULL) { - client->error = MQTT_ERROR_ACK_OF_UNKNOWN; - mqtt_recv_ret = MQTT_ERROR_ACK_OF_UNKNOWN; - break; - } - msg->state = MQTT_QUEUED_COMPLETE; - /* update response time */ - client->typical_response_time = 0.875f * (client->typical_response_time) + 0.125f * (float)(MQTT_PAL_TIME() - msg->time_sent); - /* stage PUBCOMP */ - rv = __mqtt_pubcomp(client, response.decoded.pubrec.packet_id); - if (rv != MQTT_OK) { - client->error = (enum MQTTErrors)rv; - mqtt_recv_ret = rv; - break; - } - break; - case MQTT_CONTROL_PUBCOMP: - /* release associated PUBREL */ - msg = mqtt_mq_find(&client->mq, MQTT_CONTROL_PUBREL, &response.decoded.pubcomp.packet_id); - if (msg == NULL) { - client->error = MQTT_ERROR_ACK_OF_UNKNOWN; - mqtt_recv_ret = MQTT_ERROR_ACK_OF_UNKNOWN; - break; - } - msg->state = MQTT_QUEUED_COMPLETE; - /* update response time */ - client->typical_response_time = 0.875f * (client->typical_response_time) + 0.125f * (float)(MQTT_PAL_TIME() - msg->time_sent); - break; - case MQTT_CONTROL_SUBACK: - /* release associated SUBSCRIBE */ - msg = mqtt_mq_find(&client->mq, MQTT_CONTROL_SUBSCRIBE, &response.decoded.suback.packet_id); - if (msg == NULL) { - client->error = MQTT_ERROR_ACK_OF_UNKNOWN; - mqtt_recv_ret = MQTT_ERROR_ACK_OF_UNKNOWN; - break; - } - msg->state = MQTT_QUEUED_COMPLETE; - /* update response time */ - client->typical_response_time = 0.875f * (client->typical_response_time) + 0.125f * (float)(MQTT_PAL_TIME() - msg->time_sent); - /* check that subscription was successful (not currently only one subscribe at a time) */ - if (response.decoded.suback.return_codes[0] == MQTT_SUBACK_FAILURE) { - client->error = MQTT_ERROR_SUBSCRIBE_FAILED; - mqtt_recv_ret = MQTT_ERROR_SUBSCRIBE_FAILED; - break; - } - break; - case MQTT_CONTROL_UNSUBACK: - /* release associated UNSUBSCRIBE */ - msg = mqtt_mq_find(&client->mq, MQTT_CONTROL_UNSUBSCRIBE, &response.decoded.unsuback.packet_id); - if (msg == NULL) { - client->error = MQTT_ERROR_ACK_OF_UNKNOWN; - mqtt_recv_ret = MQTT_ERROR_ACK_OF_UNKNOWN; - break; - } - msg->state = MQTT_QUEUED_COMPLETE; - /* update response time */ - client->typical_response_time = 0.875f * (client->typical_response_time) + 0.125f * (float)(MQTT_PAL_TIME() - msg->time_sent); - break; - case MQTT_CONTROL_PINGRESP: - /* release associated PINGREQ */ - msg = mqtt_mq_find(&client->mq, MQTT_CONTROL_PINGREQ, NULL); - if (msg == NULL) { - client->error = MQTT_ERROR_ACK_OF_UNKNOWN; - mqtt_recv_ret = MQTT_ERROR_ACK_OF_UNKNOWN; - break; - } - msg->state = MQTT_QUEUED_COMPLETE; - /* update response time */ - client->typical_response_time = 0.875f * (client->typical_response_time) + 0.125f * (float)(MQTT_PAL_TIME() - msg->time_sent); - break; - default: - client->error = MQTT_ERROR_MALFORMED_RESPONSE; - mqtt_recv_ret = MQTT_ERROR_MALFORMED_RESPONSE; - break; - } - { - /* we've handled the response, now clean the buffer */ - void *dest = (unsigned char *)client->recv_buffer.mem_start; - void *src = (unsigned char *)client->recv_buffer.mem_start + consumed; - size_t n = (size_t)(client->recv_buffer.curr - client->recv_buffer.mem_start - consumed); - memmove(dest, src, n); - client->recv_buffer.curr -= consumed; - client->recv_buffer.curr_sz += (unsigned long)consumed; - } - } - - /* In case there was some error handling the (well formed) message, we end up here */ - MQTT_PAL_MUTEX_UNLOCK(&client->mutex); - return mqtt_recv_ret; -} - -/* FIXED HEADER */ - -#define MQTT_BITFIELD_RULE_VIOLOATION(bitfield, rule_value, rule_mask) ((bitfield ^ rule_value) & rule_mask) - -struct mqtt_fixed_header_rules_s { - uint8_t control_type_is_valid[16]; - uint8_t required_flags[16]; - uint8_t mask_required_flags[16]; -} ; - -static const struct mqtt_fixed_header_rules_s mqtt_fixed_header_rules = { - { - /* boolean value, true if type is valid */ - 0x00, /* MQTT_CONTROL_RESERVED */ - 0x01, /* MQTT_CONTROL_CONNECT */ - 0x01, /* MQTT_CONTROL_CONNACK */ - 0x01, /* MQTT_CONTROL_PUBLISH */ - 0x01, /* MQTT_CONTROL_PUBACK */ - 0x01, /* MQTT_CONTROL_PUBREC */ - 0x01, /* MQTT_CONTROL_PUBREL */ - 0x01, /* MQTT_CONTROL_PUBCOMP */ - 0x01, /* MQTT_CONTROL_SUBSCRIBE */ - 0x01, /* MQTT_CONTROL_SUBACK */ - 0x01, /* MQTT_CONTROL_UNSUBSCRIBE */ - 0x01, /* MQTT_CONTROL_UNSUBACK */ - 0x01, /* MQTT_CONTROL_PINGREQ */ - 0x01, /* MQTT_CONTROL_PINGRESP */ - 0x01, /* MQTT_CONTROL_DISCONNECT */ - 0x00 /* MQTT_CONTROL_RESERVED */ - }, - { - /* flags that must be set for the associated control type */ - 0x00, /* MQTT_CONTROL_RESERVED */ - 0x00, /* MQTT_CONTROL_CONNECT */ - 0x00, /* MQTT_CONTROL_CONNACK */ - 0x00, /* MQTT_CONTROL_PUBLISH */ - 0x00, /* MQTT_CONTROL_PUBACK */ - 0x00, /* MQTT_CONTROL_PUBREC */ - 0x02, /* MQTT_CONTROL_PUBREL */ - 0x00, /* MQTT_CONTROL_PUBCOMP */ - 0x02, /* MQTT_CONTROL_SUBSCRIBE */ - 0x00, /* MQTT_CONTROL_SUBACK */ - 0x02, /* MQTT_CONTROL_UNSUBSCRIBE */ - 0x00, /* MQTT_CONTROL_UNSUBACK */ - 0x00, /* MQTT_CONTROL_PINGREQ */ - 0x00, /* MQTT_CONTROL_PINGRESP */ - 0x00, /* MQTT_CONTROL_DISCONNECT */ - 0x00 /* MQTT_CONTROL_RESERVED */ - }, - { - /* mask of flags that must be specific values for the associated control type*/ - 0x00, /* MQTT_CONTROL_RESERVED */ - 0x0F, /* MQTT_CONTROL_CONNECT */ - 0x0F, /* MQTT_CONTROL_CONNACK */ - 0x00, /* MQTT_CONTROL_PUBLISH */ - 0x0F, /* MQTT_CONTROL_PUBACK */ - 0x0F, /* MQTT_CONTROL_PUBREC */ - 0x0F, /* MQTT_CONTROL_PUBREL */ - 0x0F, /* MQTT_CONTROL_PUBCOMP */ - 0x0F, /* MQTT_CONTROL_SUBSCRIBE */ - 0x0F, /* MQTT_CONTROL_SUBACK */ - 0x0F, /* MQTT_CONTROL_UNSUBSCRIBE */ - 0x0F, /* MQTT_CONTROL_UNSUBACK */ - 0x0F, /* MQTT_CONTROL_PINGREQ */ - 0x0F, /* MQTT_CONTROL_PINGRESP */ - 0x0F, /* MQTT_CONTROL_DISCONNECT */ - 0x00 /* MQTT_CONTROL_RESERVED */ - } -}; - -static ssize_t mqtt_fixed_header_rule_violation(const struct mqtt_fixed_header *fixed_header) { - uint8_t control_type; - uint8_t control_flags; - uint8_t required_flags; - uint8_t mask_required_flags; - - /* get value and rules */ - control_type = (uint8_t)fixed_header->control_type; - control_flags = fixed_header->control_flags; - required_flags = mqtt_fixed_header_rules.required_flags[control_type]; - mask_required_flags = mqtt_fixed_header_rules.mask_required_flags[control_type]; - - /* check for valid type */ - if (!mqtt_fixed_header_rules.control_type_is_valid[control_type]) { - return MQTT_ERROR_CONTROL_FORBIDDEN_TYPE; - } - - /* check that flags are appropriate */ - if (MQTT_BITFIELD_RULE_VIOLOATION(control_flags, required_flags, mask_required_flags)) { - return MQTT_ERROR_CONTROL_INVALID_FLAGS; - } - - return 0; -} - -ssize_t mqtt_unpack_fixed_header(struct mqtt_response *response, const uint8_t *buf, size_t bufsz) { - struct mqtt_fixed_header *fixed_header; - const uint8_t *start = buf; - int lshift; - ssize_t errcode; - - /* check for null pointers or empty buffer */ - if (response == NULL || buf == NULL) { - return MQTT_ERROR_NULLPTR; - } - fixed_header = &(response->fixed_header); - - /* check that bufsz is not zero */ - if (bufsz == 0) return 0; - - /* parse control type and flags */ - fixed_header->control_type = (enum MQTTControlPacketType)(*buf >> 4); - fixed_header->control_flags = (uint8_t)(*buf & 0x0F); - - /* parse remaining size */ - fixed_header->remaining_length = 0; - - lshift = 0; - do { - - /* MQTT spec (2.2.3) says the maximum length is 28 bits */ - if (lshift == 28) - return MQTT_ERROR_INVALID_REMAINING_LENGTH; - - /* consume byte and assert at least 1 byte left */ - --bufsz; - ++buf; - if (bufsz == 0) return 0; - - /* parse next byte*/ - fixed_header->remaining_length += (uint32_t)((*buf & 0x7F) << lshift); - lshift += 7; - } while (*buf & 0x80); /* while continue bit is set */ - - /* consume last byte */ - --bufsz; - ++buf; - - /* check that the fixed header is valid */ - errcode = mqtt_fixed_header_rule_violation(fixed_header); - if (errcode) { - return errcode; - } - - /* check that the buffer size if GT remaining length */ - if (bufsz < fixed_header->remaining_length) { - return 0; - } - - /* return how many bytes were consumed */ - return buf - start; -} - -ssize_t mqtt_pack_fixed_header(uint8_t *buf, size_t bufsz, const struct mqtt_fixed_header *fixed_header) { - const uint8_t *start = buf; - ssize_t errcode; - uint32_t remaining_length; - - /* check for null pointers or empty buffer */ - if (fixed_header == NULL || buf == NULL) { - return MQTT_ERROR_NULLPTR; - } - - /* check that the fixed header is valid */ - errcode = mqtt_fixed_header_rule_violation(fixed_header); - if (errcode) { - return errcode; - } - - /* check that bufsz is not zero */ - if (bufsz == 0) return 0; - - /* pack control type and flags */ - *buf = (uint8_t)((((uint8_t) fixed_header->control_type) << 4) & 0xF0); - *buf = (uint8_t)(*buf | (((uint8_t) fixed_header->control_flags) & 0x0F)); - - remaining_length = fixed_header->remaining_length; - - /* MQTT spec (2.2.3) says maximum remaining length is 2^28-1 */ - if (remaining_length >= 256 * 1024 * 1024) - return MQTT_ERROR_INVALID_REMAINING_LENGTH; - - do { - /* consume byte and assert at least 1 byte left */ - --bufsz; - ++buf; - if (bufsz == 0) return 0; - - /* pack next byte */ - *buf = remaining_length & 0x7F; - if (remaining_length > 127) *buf |= 0x80; - remaining_length = remaining_length >> 7; - } while (*buf & 0x80); - - /* consume last byte */ - --bufsz; - ++buf; - - /* check that there's still enough space in buffer for packet */ - if (bufsz < fixed_header->remaining_length) { - return 0; - } - - /* return how many bytes were consumed */ - return buf - start; -} - -/* CONNECT */ -ssize_t mqtt_pack_connection_request(uint8_t *buf, size_t bufsz, - const char *client_id, - const char *will_topic, - const void *will_message, - size_t will_message_size, - const char *user_name, - const char *password, - uint8_t connect_flags, - uint16_t keep_alive) { - struct mqtt_fixed_header fixed_header; - size_t remaining_length; - const uint8_t *const start = buf; - ssize_t rv; - - /* pack the fixed headr */ - fixed_header.control_type = MQTT_CONTROL_CONNECT; - fixed_header.control_flags = 0x00; - - /* calculate remaining length and build connect_flags at the same time */ - connect_flags = (uint8_t)(connect_flags & ~MQTT_CONNECT_RESERVED); - remaining_length = 10; /* size of variable header */ - - if (client_id == NULL) { - client_id = ""; - } - /* For an empty client_id, a clean session is required */ - if (client_id[0] == '\0' && !(connect_flags & MQTT_CONNECT_CLEAN_SESSION)) { - return MQTT_ERROR_CLEAN_SESSION_IS_REQUIRED; - } - /* mqtt_string length is strlen + 2 */ - remaining_length += __mqtt_packed_cstrlen(client_id); - - if (will_topic != NULL) { - uint8_t temp; - /* there is a will */ - connect_flags |= MQTT_CONNECT_WILL_FLAG; - remaining_length += __mqtt_packed_cstrlen(will_topic); - - if (will_message == NULL) { - /* if there's a will there MUST be a will message */ - return MQTT_ERROR_CONNECT_NULL_WILL_MESSAGE; - } - remaining_length += 2 + will_message_size; /* size of will_message */ - - /* assert that the will QOS is valid (i.e. not 3) */ - temp = connect_flags & 0x18; /* mask to QOS */ - if (temp == 0x18) { - /* bitwise equality with QoS 3 (invalid)*/ - return MQTT_ERROR_CONNECT_FORBIDDEN_WILL_QOS; - } - } else { - /* there is no will so set all will flags to zero */ - connect_flags &= (uint8_t)~MQTT_CONNECT_WILL_FLAG; - connect_flags &= (uint8_t)~0x18; - connect_flags &= (uint8_t)~MQTT_CONNECT_WILL_RETAIN; - } - - if (user_name != NULL) { - /* a user name is present */ - connect_flags |= MQTT_CONNECT_USER_NAME; - remaining_length += __mqtt_packed_cstrlen(user_name); - } else { - connect_flags &= (uint8_t)~MQTT_CONNECT_USER_NAME; - } - - if (password != NULL) { - /* a password is present */ - connect_flags |= MQTT_CONNECT_PASSWORD; - remaining_length += __mqtt_packed_cstrlen(password); - } else { - connect_flags &= (uint8_t)~MQTT_CONNECT_PASSWORD; - } - - /* fixed header length is now calculated*/ - fixed_header.remaining_length = (uint32_t)remaining_length; - - /* pack fixed header and perform error checks */ - rv = mqtt_pack_fixed_header(buf, bufsz, &fixed_header); - if (rv <= 0) { - /* something went wrong */ - return rv; - } - buf += rv; - bufsz -= (size_t)rv; - - /* check that the buffer has enough space to fit the remaining length */ - if (bufsz < fixed_header.remaining_length) { - return 0; - } - - /* pack the variable header */ - *buf++ = 0x00; - *buf++ = 0x04; - *buf++ = (uint8_t) 'M'; - *buf++ = (uint8_t) 'Q'; - *buf++ = (uint8_t) 'T'; - *buf++ = (uint8_t) 'T'; - *buf++ = MQTT_PROTOCOL_LEVEL; - *buf++ = connect_flags; - buf += __mqtt_pack_uint16(buf, keep_alive); - - /* pack the payload */ - buf += __mqtt_pack_str(buf, client_id); - if (will_topic != NULL) { - buf += __mqtt_pack_str(buf, will_topic); - buf += __mqtt_pack_uint16(buf, (uint16_t)will_message_size); - memcpy(buf, will_message, will_message_size); - buf += will_message_size; - } - if (user_name != NULL) { - buf += __mqtt_pack_str(buf, user_name); - } - if (password != NULL) { - buf += __mqtt_pack_str(buf, password); - } - - /* return the number of bytes that were consumed */ - return buf - start; -} - -/* CONNACK */ -ssize_t mqtt_unpack_connack_response(struct mqtt_response *mqtt_response, const uint8_t *buf) { - const uint8_t *const start = buf; - struct mqtt_response_connack *response; - - /* check that remaining length is 2 */ - if (mqtt_response->fixed_header.remaining_length != 2) { - return MQTT_ERROR_MALFORMED_RESPONSE; - } - - response = &(mqtt_response->decoded.connack); - /* unpack */ - if (*buf & 0xFE) { - /* only bit 1 can be set */ - return MQTT_ERROR_CONNACK_FORBIDDEN_FLAGS; - } else { - response->session_present_flag = *buf++; - } - - if (*buf > 5u) { - /* only bit 1 can be set */ - return MQTT_ERROR_CONNACK_FORBIDDEN_CODE; - } else { - response->return_code = (enum MQTTConnackReturnCode) * buf++; - } - return buf - start; -} - -/* DISCONNECT */ -ssize_t mqtt_pack_disconnect(uint8_t *buf, size_t bufsz) { - struct mqtt_fixed_header fixed_header; - fixed_header.control_type = MQTT_CONTROL_DISCONNECT; - fixed_header.control_flags = 0; - fixed_header.remaining_length = 0; - return mqtt_pack_fixed_header(buf, bufsz, &fixed_header); -} - -/* PING */ -ssize_t mqtt_pack_ping_request(uint8_t *buf, size_t bufsz) { - struct mqtt_fixed_header fixed_header; - fixed_header.control_type = MQTT_CONTROL_PINGREQ; - fixed_header.control_flags = 0; - fixed_header.remaining_length = 0; - return mqtt_pack_fixed_header(buf, bufsz, &fixed_header); -} - -/* PUBLISH */ -ssize_t mqtt_pack_publish_request(uint8_t *buf, size_t bufsz, - const char *topic_name, - uint16_t packet_id, - const void *application_message, - size_t application_message_size, - uint8_t publish_flags) { - const uint8_t *const start = buf; - ssize_t rv; - struct mqtt_fixed_header fixed_header; - uint32_t remaining_length; - uint8_t inspected_qos; - - /* check for null pointers */ - if (buf == NULL || topic_name == NULL) { - return MQTT_ERROR_NULLPTR; - } - - /* inspect QoS level */ - inspected_qos = (publish_flags & MQTT_PUBLISH_QOS_MASK) >> 1; /* mask */ - - /* build the fixed header */ - fixed_header.control_type = MQTT_CONTROL_PUBLISH; - - /* calculate remaining length */ - remaining_length = (uint32_t)__mqtt_packed_cstrlen(topic_name); - if (inspected_qos > 0) { - remaining_length += 2; - } - remaining_length += (uint32_t)application_message_size; - fixed_header.remaining_length = remaining_length; - - /* force dup to 0 if qos is 0 [Spec MQTT-3.3.1-2] */ - if (inspected_qos == 0) { - publish_flags &= (uint8_t)~MQTT_PUBLISH_DUP; - } - - /* make sure that qos is not 3 [Spec MQTT-3.3.1-4] */ - if (inspected_qos == 3) { - return MQTT_ERROR_PUBLISH_FORBIDDEN_QOS; - } - fixed_header.control_flags = publish_flags & 0x7; - - /* pack fixed header */ - rv = mqtt_pack_fixed_header(buf, bufsz, &fixed_header); - if (rv <= 0) { - /* something went wrong */ - return rv; - } - buf += rv; - bufsz -= (size_t)rv; - - /* check that buffer is big enough */ - if (bufsz < remaining_length) { - return 0; - } - - /* pack variable header */ - buf += __mqtt_pack_str(buf, topic_name); - if (inspected_qos > 0) { - buf += __mqtt_pack_uint16(buf, packet_id); - } - - /* pack payload */ - memcpy(buf, application_message, application_message_size); - buf += application_message_size; - - return buf - start; -} - -ssize_t mqtt_unpack_publish_response(struct mqtt_response *mqtt_response, const uint8_t *buf) { - const uint8_t *const start = buf; - struct mqtt_fixed_header *fixed_header; - struct mqtt_response_publish *response; - - fixed_header = &(mqtt_response->fixed_header); - response = &(mqtt_response->decoded.publish); - - /* get flags */ - response->dup_flag = (fixed_header->control_flags & MQTT_PUBLISH_DUP) >> 3; - response->qos_level = (fixed_header->control_flags & MQTT_PUBLISH_QOS_MASK) >> 1; - response->retain_flag = fixed_header->control_flags & MQTT_PUBLISH_RETAIN; - - /* make sure that remaining length is valid */ - if (mqtt_response->fixed_header.remaining_length < 4) { - return MQTT_ERROR_MALFORMED_RESPONSE; - } - - /* parse variable header */ - response->topic_name_size = __mqtt_unpack_uint16(buf); - buf += 2; - response->topic_name = buf; - buf += response->topic_name_size; - - if (response->qos_level > 0) { - response->packet_id = __mqtt_unpack_uint16(buf); - buf += 2; - } - - /* get payload */ - response->application_message = buf; - if (response->qos_level == 0) { - response->application_message_size = fixed_header->remaining_length - response->topic_name_size - 2; - } else { - response->application_message_size = fixed_header->remaining_length - response->topic_name_size - 4; - } - buf += response->application_message_size; - - /* return number of bytes consumed */ - return buf - start; -} - -/* PUBXXX */ -ssize_t mqtt_pack_pubxxx_request(uint8_t *buf, size_t bufsz, - enum MQTTControlPacketType control_type, - uint16_t packet_id) { - const uint8_t *const start = buf; - struct mqtt_fixed_header fixed_header; - ssize_t rv; - if (buf == NULL) { - return MQTT_ERROR_NULLPTR; - } - - /* pack fixed header */ - fixed_header.control_type = control_type; - if (control_type == MQTT_CONTROL_PUBREL) { - fixed_header.control_flags = 0x02; - } else { - fixed_header.control_flags = 0; - } - fixed_header.remaining_length = 2; - rv = mqtt_pack_fixed_header(buf, bufsz, &fixed_header); - if (rv <= 0) { - return rv; - } - buf += rv; - bufsz -= (size_t)rv; - - if (bufsz < fixed_header.remaining_length) { - return 0; - } - - buf += __mqtt_pack_uint16(buf, packet_id); - - return buf - start; -} - -ssize_t mqtt_unpack_pubxxx_response(struct mqtt_response *mqtt_response, const uint8_t *buf) { - const uint8_t *const start = buf; - uint16_t packet_id; - - /* assert remaining length is correct */ - if (mqtt_response->fixed_header.remaining_length != 2) { - return MQTT_ERROR_MALFORMED_RESPONSE; - } - - /* parse packet_id */ - packet_id = __mqtt_unpack_uint16(buf); - buf += 2; - - if (mqtt_response->fixed_header.control_type == MQTT_CONTROL_PUBACK) { - mqtt_response->decoded.puback.packet_id = packet_id; - } else if (mqtt_response->fixed_header.control_type == MQTT_CONTROL_PUBREC) { - mqtt_response->decoded.pubrec.packet_id = packet_id; - } else if (mqtt_response->fixed_header.control_type == MQTT_CONTROL_PUBREL) { - mqtt_response->decoded.pubrel.packet_id = packet_id; - } else { - mqtt_response->decoded.pubcomp.packet_id = packet_id; - } - - return buf - start; -} - -/* SUBACK */ -ssize_t mqtt_unpack_suback_response(struct mqtt_response *mqtt_response, const uint8_t *buf) { - const uint8_t *const start = buf; - uint32_t remaining_length = mqtt_response->fixed_header.remaining_length; - - /* assert remaining length is at least 3 (for packet id and at least 1 topic) */ - if (remaining_length < 3) { - return MQTT_ERROR_MALFORMED_RESPONSE; - } - - /* unpack packet_id */ - mqtt_response->decoded.suback.packet_id = __mqtt_unpack_uint16(buf); - buf += 2; - remaining_length -= 2; - - /* unpack return codes */ - mqtt_response->decoded.suback.num_return_codes = (size_t) remaining_length; - mqtt_response->decoded.suback.return_codes = buf; - buf += remaining_length; - - return buf - start; -} - -/* SUBSCRIBE */ -ssize_t mqtt_pack_subscribe_request(uint8_t *buf, size_t bufsz, unsigned int packet_id, ...) { - va_list args; - const uint8_t *const start = buf; - ssize_t rv; - struct mqtt_fixed_header fixed_header; - unsigned int num_subs = 0; - unsigned int i; - const char *topic[MQTT_SUBSCRIBE_REQUEST_MAX_NUM_TOPICS]; - uint8_t max_qos[MQTT_SUBSCRIBE_REQUEST_MAX_NUM_TOPICS]; - - /* parse all subscriptions */ - va_start(args, packet_id); - for (;;) { - topic[num_subs] = va_arg(args, const char *); - if (topic[num_subs] == NULL) { - /* end of list */ - break; - } - - max_qos[num_subs] = (uint8_t) va_arg(args, unsigned int); - - ++num_subs; - if (num_subs >= MQTT_SUBSCRIBE_REQUEST_MAX_NUM_TOPICS) { - va_end(args); - return MQTT_ERROR_SUBSCRIBE_TOO_MANY_TOPICS; - } - } - va_end(args); - - /* build the fixed header */ - fixed_header.control_type = MQTT_CONTROL_SUBSCRIBE; - fixed_header.control_flags = 2u; - fixed_header.remaining_length = 2u; /* size of variable header */ - for (i = 0; i < num_subs; ++i) { - /* payload is topic name + max qos (1 byte) */ - fixed_header.remaining_length += __mqtt_packed_cstrlen(topic[i]) + 1; - } - - /* pack the fixed header */ - rv = mqtt_pack_fixed_header(buf, bufsz, &fixed_header); - if (rv <= 0) { - return rv; - } - buf += rv; - bufsz -= (unsigned long)rv; - - /* check that the buffer has enough space */ - if (bufsz < fixed_header.remaining_length) { - return 0; - } - - - /* pack variable header */ - buf += __mqtt_pack_uint16(buf, (uint16_t)packet_id); - - - /* pack payload */ - for (i = 0; i < num_subs; ++i) { - buf += __mqtt_pack_str(buf, topic[i]); - *buf++ = max_qos[i]; - } - - return buf - start; -} - -/* UNSUBACK */ -ssize_t mqtt_unpack_unsuback_response(struct mqtt_response *mqtt_response, const uint8_t *buf) { - const uint8_t *const start = buf; - - if (mqtt_response->fixed_header.remaining_length != 2) { - return MQTT_ERROR_MALFORMED_RESPONSE; - } - - /* parse packet_id */ - mqtt_response->decoded.unsuback.packet_id = __mqtt_unpack_uint16(buf); - buf += 2; - - return buf - start; -} - -/* UNSUBSCRIBE */ -ssize_t mqtt_pack_unsubscribe_request(uint8_t *buf, size_t bufsz, unsigned int packet_id, ...) { - va_list args; - const uint8_t *const start = buf; - ssize_t rv; - struct mqtt_fixed_header fixed_header; - unsigned int num_subs = 0; - unsigned int i; - const char *topic[MQTT_UNSUBSCRIBE_REQUEST_MAX_NUM_TOPICS]; - - /* parse all subscriptions */ - va_start(args, packet_id); - for (;;) { - topic[num_subs] = va_arg(args, const char *); - if (topic[num_subs] == NULL) { - /* end of list */ - break; - } - - ++num_subs; - if (num_subs >= MQTT_UNSUBSCRIBE_REQUEST_MAX_NUM_TOPICS) { - va_end(args); - return MQTT_ERROR_UNSUBSCRIBE_TOO_MANY_TOPICS; - } - } - va_end(args); - - /* build the fixed header */ - fixed_header.control_type = MQTT_CONTROL_UNSUBSCRIBE; - fixed_header.control_flags = 2u; - fixed_header.remaining_length = 2u; /* size of variable header */ - for (i = 0; i < num_subs; ++i) { - /* payload is topic name */ - fixed_header.remaining_length += __mqtt_packed_cstrlen(topic[i]); - } - - /* pack the fixed header */ - rv = mqtt_pack_fixed_header(buf, bufsz, &fixed_header); - if (rv <= 0) { - return rv; - } - buf += rv; - bufsz -= (unsigned long)rv; - - /* check that the buffer has enough space */ - if (bufsz < fixed_header.remaining_length) { - return 0; - } - - /* pack variable header */ - buf += __mqtt_pack_uint16(buf, (uint16_t)packet_id); - - - /* pack payload */ - for (i = 0; i < num_subs; ++i) { - buf += __mqtt_pack_str(buf, topic[i]); - } - - return buf - start; -} - -/* MESSAGE QUEUE */ -void mqtt_mq_init(struct mqtt_message_queue *mq, void *buf, size_t bufsz) { - mq->mem_start = buf; - mq->mem_end = (uint8_t *)buf + bufsz; - mq->curr = (uint8_t *)buf; - mq->queue_tail = (struct mqtt_queued_message *)mq->mem_end; - mq->curr_sz = buf == NULL ? 0 : mqtt_mq_currsz(mq); -} - -struct mqtt_queued_message *mqtt_mq_register(struct mqtt_message_queue *mq, size_t nbytes) { - /* make queued message header */ - --(mq->queue_tail); - mq->queue_tail->start = mq->curr; - mq->queue_tail->size = nbytes; - mq->queue_tail->state = MQTT_QUEUED_UNSENT; - - /* move curr and recalculate curr_sz */ - mq->curr += nbytes; - mq->curr_sz = (size_t)(mqtt_mq_currsz(mq)); - - return mq->queue_tail; -} - -void mqtt_mq_clean(struct mqtt_message_queue *mq) { - struct mqtt_queued_message *new_head; - - for (new_head = mqtt_mq_get(mq, 0); new_head >= mq->queue_tail; --new_head) { - if (new_head->state != MQTT_QUEUED_COMPLETE) break; - } - - /* check if everything can be removed */ - if (new_head < mq->queue_tail) { - mq->curr = (uint8_t *)mq->mem_start; - mq->queue_tail = (struct mqtt_queued_message *)mq->mem_end; - mq->curr_sz = (size_t)(mqtt_mq_currsz(mq)); - return; - } else if (new_head == mqtt_mq_get(mq, 0)) { - /* do nothing */ - return; - } - - /* move buffered data */ - { - size_t n = (size_t)(mq->curr - new_head->start); - size_t removing = (size_t)(new_head->start - (uint8_t *) mq->mem_start); - memmove(mq->mem_start, new_head->start, n); - mq->curr = (unsigned char *)mq->mem_start + n; - - - /* move queue */ - { - ssize_t new_tail_idx = new_head - mq->queue_tail; - memmove(mqtt_mq_get(mq, new_tail_idx), mq->queue_tail, sizeof(struct mqtt_queued_message) * (size_t)((new_tail_idx + 1))); - mq->queue_tail = mqtt_mq_get(mq, new_tail_idx); - - { - /* bump back start's */ - ssize_t i = 0; - for (; i < new_tail_idx + 1; ++i) { - mqtt_mq_get(mq, i)->start -= removing; - } - } - } - } - - /* get curr_sz */ - mq->curr_sz = (size_t)(mqtt_mq_currsz(mq)); -} - -struct mqtt_queued_message *mqtt_mq_find(const struct mqtt_message_queue *mq, enum MQTTControlPacketType control_type, const uint16_t *packet_id) { - struct mqtt_queued_message *curr; - for (curr = mqtt_mq_get(mq, 0); curr >= mq->queue_tail; --curr) { - if (curr->control_type == control_type) { - if ((packet_id == NULL && curr->state != MQTT_QUEUED_COMPLETE) || - (packet_id != NULL && *packet_id == curr->packet_id)) { - return curr; - } - } - } - return NULL; -} - - -/* RESPONSE UNPACKING */ -ssize_t mqtt_unpack_response(struct mqtt_response *response, const uint8_t *buf, size_t bufsz) { - const uint8_t *const start = buf; - ssize_t rv = mqtt_unpack_fixed_header(response, buf, bufsz); - if (rv <= 0) return rv; - else buf += rv; - switch (response->fixed_header.control_type) { - case MQTT_CONTROL_CONNACK: - rv = mqtt_unpack_connack_response(response, buf); - break; - case MQTT_CONTROL_PUBLISH: - rv = mqtt_unpack_publish_response(response, buf); - break; - case MQTT_CONTROL_PUBACK: - rv = mqtt_unpack_pubxxx_response(response, buf); - break; - case MQTT_CONTROL_PUBREC: - rv = mqtt_unpack_pubxxx_response(response, buf); - break; - case MQTT_CONTROL_PUBREL: - rv = mqtt_unpack_pubxxx_response(response, buf); - break; - case MQTT_CONTROL_PUBCOMP: - rv = mqtt_unpack_pubxxx_response(response, buf); - break; - case MQTT_CONTROL_SUBACK: - rv = mqtt_unpack_suback_response(response, buf); - break; - case MQTT_CONTROL_UNSUBACK: - rv = mqtt_unpack_unsuback_response(response, buf); - break; - case MQTT_CONTROL_PINGRESP: - return rv; - default: - return MQTT_ERROR_RESPONSE_INVALID_CONTROL_TYPE; - } - - if (rv < 0) return rv; - buf += rv; - return buf - start; -} - -/* EXTRA DETAILS */ -ssize_t __mqtt_pack_uint16(uint8_t *buf, uint16_t integer) { - uint16_t integer_htons = MQTT_PAL_HTONS(integer); - memcpy(buf, &integer_htons, 2uL); - return 2; -} - -uint16_t __mqtt_unpack_uint16(const uint8_t *buf) { - uint16_t integer_htons; - memcpy(&integer_htons, buf, 2uL); - return MQTT_PAL_NTOHS(integer_htons); -} - -ssize_t __mqtt_pack_str(uint8_t *buf, const char *str) { - uint16_t length = (uint16_t)strlen(str); - int i = 0; - /* pack string length */ - buf += __mqtt_pack_uint16(buf, length); - - /* pack string */ - for (; i < length; ++i) { - *(buf++) = (uint8_t)str[i]; - } - - /* return number of bytes consumed */ - return length + 2; -} - -static const char *const MQTT_ERRORS_STR[] = { - "MQTT_UNKNOWN_ERROR", - __ALL_MQTT_ERRORS(GENERATE_STRING) -}; - -const char *mqtt_error_str(enum MQTTErrors error) { - int offset = error - MQTT_ERROR_UNKNOWN; - if (offset >= 0) { - return MQTT_ERRORS_STR[offset]; - } else if (error == 0) { - return "MQTT_ERROR: Buffer too small."; - } else if (error > 0) { - return "MQTT_OK"; - } else { - return MQTT_ERRORS_STR[0]; - } -} - -/** @endcond*/ diff --git a/client/deps/mqtt/mqtt.h b/client/deps/mqtt/mqtt.h deleted file mode 100644 index d3467cd27..000000000 --- a/client/deps/mqtt/mqtt.h +++ /dev/null @@ -1,1640 +0,0 @@ -#if !defined(__MQTT_H__) -#define __MQTT_H__ - -/* -MIT License - -Copyright(c) 2018 Liam Bindle - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#if defined(__cplusplus) -extern "C" { -#endif - -// Users can override mqtt_pal.h with their own configuration by defining -// MQTTC_PAL_FILE as a header file to include (-DMQTTC_PAL_FILE=my_mqtt_pal.h). -// -// If MQTTC_PAL_FILE is used, none of the default utils will be emitted and must be -// provided by the config file. To start, I would suggest copying mqtt_pal.h -// and modifying as needed. -#if defined(MQTTC_PAL_FILE) -#define MQTTC_STR2(x) #x -#define MQTTC_STR(x) MQTTC_STR2(x) -#include MQTTC_STR(MQTTC_PAL_FILE) -#else -#include "mqtt_pal.h" -#endif /* MQTT_PAL_FILE */ - -/** - * @file - * @brief Declares all the MQTT-C functions and datastructures. - * - * @note You should \#include . - * - * @example simple_publisher.c - * A simple program to that publishes the current time whenever ENTER is pressed. - * - * Usage: - * \code{.sh} - * ./bin/simple_publisher [address [port [topic]]] - * \endcode - * - * Where \c address is the address of the MQTT broker, \c port is the port number the - * MQTT broker is running on, and \c topic is the name of the topic to publish with. Note - * that all these arguments are optional and the defaults are \c address = \c "test.mosquitto.org", - * \c port = \c "1883", and \c topic = "datetime". - * - * @example simple_subscriber.c - * A simple program that subscribes to a single topic and prints all updates that are received. - * - * Usage: - * \code{.sh} - * ./bin/simple_subscriber [address [port [topic]]] - * \endcode - * - * Where \c address is the address of the MQTT broker, \c port is the port number the - * MQTT broker is running on, and \c topic is the name of the topic subscribe to. Note - * that all these arguments are optional and the defaults are \c address = \c "test.mosquitto.org", - * \c port = \c "1883", and \c topic = "datetime". - * - * @example reconnect_subscriber.c - * Same program as \ref simple_subscriber.c, but using the automatic reconnect functionality. - * - * @example bio_publisher.c - * Same program as \ref simple_publisher.c, but uses a unencrypted BIO socket. - * - * @example openssl_publisher.c - * Same program as \ref simple_publisher.c, but over an encrypted connection using OpenSSL. - * - * Usage: - * \code{.sh} - * ./bin/openssl_publisher ca_file [address [port [topic]]] - * \endcode - * - * - * @defgroup api API - * @brief Documentation of everything you need to know to use the MQTT-C client. - * - * This module contains everything you need to know to use MQTT-C in your application. - * For usage examples see: - * - @ref simple_publisher.c - * - @ref simple_subscriber.c - * - @ref reconnect_subscriber.c - * - @ref bio_publisher.c - * - @ref openssl_publisher.c - * - * @note MQTT-C can be used in both single-threaded and multi-threaded applications. All - * the functions in \ref api are thread-safe. - * - * @defgroup packers Control Packet Serialization - * @brief Developer documentation of the functions and datastructures used for serializing MQTT - * control packets. - * - * @defgroup unpackers Control Packet Deserialization - * @brief Developer documentation of the functions and datastructures used for deserializing MQTT - * control packets. - * - * @defgroup details Utilities - * @brief Developer documentation for the utilities used to implement the MQTT-C client. - * - * @note To deserialize a packet from a buffer use \ref mqtt_unpack_response (it's the only - * function you need). - */ - - -/** - * @brief An enumeration of the MQTT control packet types. - * @ingroup unpackers - * - * @see - * MQTT v3.1.1: MQTT Control Packet Types - * - */ -enum MQTTControlPacketType { - MQTT_CONTROL_CONNECT = 1u, - MQTT_CONTROL_CONNACK = 2u, - MQTT_CONTROL_PUBLISH = 3u, - MQTT_CONTROL_PUBACK = 4u, - MQTT_CONTROL_PUBREC = 5u, - MQTT_CONTROL_PUBREL = 6u, - MQTT_CONTROL_PUBCOMP = 7u, - MQTT_CONTROL_SUBSCRIBE = 8u, - MQTT_CONTROL_SUBACK = 9u, - MQTT_CONTROL_UNSUBSCRIBE = 10u, - MQTT_CONTROL_UNSUBACK = 11u, - MQTT_CONTROL_PINGREQ = 12u, - MQTT_CONTROL_PINGRESP = 13u, - MQTT_CONTROL_DISCONNECT = 14u -}; - -/** - * @brief A structure that I will use to keep track of some data needed - * to setup the connection to the broker. - * - * An instance of this struct will be created in my \c main(). Then, whenever - * \ref reconnect_client is called, this instance will be passed. - */ -struct reconnect_state_t { - const char *hostname; - const char *port; - const char *topic; - uint8_t *sendbuf; - size_t sendbufsz; - uint8_t *recvbuf; - size_t recvbufsz; -}; - -/** - * @brief The fixed header of an MQTT control packet. - * @ingroup unpackers - * - * @see - * MQTT v3.1.1: Fixed Header - * - */ -struct mqtt_fixed_header { - /** The type of packet. */ - enum MQTTControlPacketType control_type; - - /** The packets control flags.*/ - uint32_t control_flags: 4; - - /** The remaining size of the packet in bytes (i.e. the size of variable header and payload).*/ - uint32_t remaining_length; -}; - -/** - * @brief The protocol identifier for MQTT v3.1.1. - * @ingroup packers - * - * @see - * MQTT v3.1.1: CONNECT Variable Header. - * - */ -#define MQTT_PROTOCOL_LEVEL 0x04 - -/** - * @brief A macro used to declare the enum MQTTErrors and associated - * error messages (the members of the num) at the same time. - */ -#define __ALL_MQTT_ERRORS(MQTT_ERROR) \ - MQTT_ERROR(MQTT_ERROR_NULLPTR) \ - MQTT_ERROR(MQTT_ERROR_CONTROL_FORBIDDEN_TYPE) \ - MQTT_ERROR(MQTT_ERROR_CONTROL_INVALID_FLAGS) \ - MQTT_ERROR(MQTT_ERROR_CONTROL_WRONG_TYPE) \ - MQTT_ERROR(MQTT_ERROR_CONNECT_CLIENT_ID_REFUSED) \ - MQTT_ERROR(MQTT_ERROR_CONNECT_NULL_WILL_MESSAGE) \ - MQTT_ERROR(MQTT_ERROR_CONNECT_FORBIDDEN_WILL_QOS) \ - MQTT_ERROR(MQTT_ERROR_CONNACK_FORBIDDEN_FLAGS) \ - MQTT_ERROR(MQTT_ERROR_CONNACK_FORBIDDEN_CODE) \ - MQTT_ERROR(MQTT_ERROR_PUBLISH_FORBIDDEN_QOS) \ - MQTT_ERROR(MQTT_ERROR_SUBSCRIBE_TOO_MANY_TOPICS) \ - MQTT_ERROR(MQTT_ERROR_MALFORMED_RESPONSE) \ - MQTT_ERROR(MQTT_ERROR_UNSUBSCRIBE_TOO_MANY_TOPICS) \ - MQTT_ERROR(MQTT_ERROR_RESPONSE_INVALID_CONTROL_TYPE) \ - MQTT_ERROR(MQTT_ERROR_CONNECT_NOT_CALLED) \ - MQTT_ERROR(MQTT_ERROR_SEND_BUFFER_IS_FULL) \ - MQTT_ERROR(MQTT_ERROR_SOCKET_ERROR) \ - MQTT_ERROR(MQTT_ERROR_MALFORMED_REQUEST) \ - MQTT_ERROR(MQTT_ERROR_RECV_BUFFER_TOO_SMALL) \ - MQTT_ERROR(MQTT_ERROR_ACK_OF_UNKNOWN) \ - MQTT_ERROR(MQTT_ERROR_NOT_IMPLEMENTED) \ - MQTT_ERROR(MQTT_ERROR_CONNECTION_REFUSED) \ - MQTT_ERROR(MQTT_ERROR_SUBSCRIBE_FAILED) \ - MQTT_ERROR(MQTT_ERROR_CONNECTION_CLOSED) \ - MQTT_ERROR(MQTT_ERROR_INITIAL_RECONNECT) \ - MQTT_ERROR(MQTT_ERROR_INVALID_REMAINING_LENGTH) \ - MQTT_ERROR(MQTT_ERROR_CLEAN_SESSION_IS_REQUIRED) \ - MQTT_ERROR(MQTT_ERROR_RECONNECT_FAILED) \ - MQTT_ERROR(MQTT_ERROR_RECONNECTING) - -/* todo: add more connection refused errors */ - -/** - * @brief A macro used to generate the enum MQTTErrors from - * \ref __ALL_MQTT_ERRORS - * @see __ALL_MQTT_ERRORS -*/ -#define GENERATE_ENUM(ENUM) ENUM, - -/** - * @brief A macro used to generate the error messages associated with - * MQTTErrors from \ref __ALL_MQTT_ERRORS - * @see __ALL_MQTT_ERRORS -*/ -#define GENERATE_STRING(STRING) #STRING, - - -/** - * @brief An enumeration of error codes. Error messages can be retrieved by calling \ref mqtt_error_str. - * @ingroup api - * - * @see mqtt_error_str - */ -enum MQTTErrors { - MQTT_ERROR_UNKNOWN = INT_MIN, - __ALL_MQTT_ERRORS(GENERATE_ENUM) - MQTT_OK = 1 -}; - -/** - * @brief Returns an error message for error code, \p error. - * @ingroup api - * - * @param[in] error the error code. - * - * @returns The associated error message. - */ -const char *mqtt_error_str(enum MQTTErrors error); - -/** - * @brief Pack a MQTT 16 bit integer, given a native 16 bit integer . - * - * @param[out] buf the buffer that the MQTT integer will be written to. - * @param[in] integer the native integer to be written to \p buf. - * - * @warning This function provides no error checking. - * - * @returns 2 -*/ -ssize_t __mqtt_pack_uint16(uint8_t *buf, uint16_t integer); - -/** - * @brief Unpack a MQTT 16 bit integer to a native 16 bit integer. - * - * @param[in] buf the buffer that the MQTT integer will be read from. - * - * @warning This function provides no error checking and does not modify \p buf. - * - * @returns The native integer -*/ -uint16_t __mqtt_unpack_uint16(const uint8_t *buf); - -/** - * @brief Pack a MQTT string, given a c-string \p str. - * - * @param[out] buf the buffer that the MQTT string will be written to. - * @param[in] str the c-string to be written to \p buf. - * - * @warning This function provides no error checking. - * - * @returns strlen(str) + 2 -*/ -ssize_t __mqtt_pack_str(uint8_t *buf, const char *str); - -/** @brief A macro to get the MQTT string length from a c-string. */ -#define __mqtt_packed_cstrlen(x) (2 + (unsigned int)strlen(x)) - -/* RESPONSES */ - -/** - * @brief An enumeration of the return codes returned in a CONNACK packet. - * @ingroup unpackers - * - * @see - * MQTT v3.1.1: CONNACK return codes. - * - */ -enum MQTTConnackReturnCode { - MQTT_CONNACK_ACCEPTED = 0u, - MQTT_CONNACK_REFUSED_PROTOCOL_VERSION = 1u, - MQTT_CONNACK_REFUSED_IDENTIFIER_REJECTED = 2u, - MQTT_CONNACK_REFUSED_SERVER_UNAVAILABLE = 3u, - MQTT_CONNACK_REFUSED_BAD_USER_NAME_OR_PASSWORD = 4u, - MQTT_CONNACK_REFUSED_NOT_AUTHORIZED = 5u -}; - -/** - * @brief A connection response datastructure. - * @ingroup unpackers - * - * @see - * MQTT v3.1.1: CONNACK - Acknowledgement connection response. - * - */ -struct mqtt_response_connack { - /** - * @brief Allows client and broker to check if they have a consistent view about whether there is - * already a stored session state. - */ - uint8_t session_present_flag; - - /** - * @brief The return code of the connection request. - * - * @see MQTTConnackReturnCode - */ - enum MQTTConnackReturnCode return_code; -}; - -/** - * @brief A publish packet received from the broker. - * @ingroup unpackers - * - * A publish packet is received from the broker when a client publishes to a topic that the - * \em {local client} is subscribed to. - * - * @see - * MQTT v3.1.1: PUBLISH - Publish Message. - * - */ -struct mqtt_response_publish { - /** - * @brief The DUP flag. DUP flag is 0 if its the first attempt to send this publish packet. A DUP flag - * of 1 means that this might be a re-delivery of the packet. - */ - uint8_t dup_flag; - - /** - * @brief The quality of service level. - * - * @see - * MQTT v3.1.1: QoS Definitions - * - */ - uint8_t qos_level; - - /** @brief The retain flag of this publish message. */ - uint8_t retain_flag; - - /** @brief Size of the topic name (number of characters). */ - uint16_t topic_name_size; - - /** - * @brief The topic name. - * @note topic_name is not null terminated. Therefore topic_name_size must be used to get the - * string length. - */ - const void *topic_name; - - /** @brief The publish message's packet ID. */ - uint16_t packet_id; - - /** @brief The publish message's application message.*/ - const void *application_message; - - /** @brief The size of the application message in bytes. */ - size_t application_message_size; -}; - -/** - * @brief A publish acknowledgement for messages that were published with QoS level 1. - * @ingroup unpackers - * - * @see - * MQTT v3.1.1: PUBACK - Publish Acknowledgement. - * - * - */ -struct mqtt_response_puback { - /** @brief The published messages packet ID. */ - uint16_t packet_id; -}; - -/** - * @brief The response packet to a PUBLISH packet with QoS level 2. - * @ingroup unpackers - * - * @see - * MQTT v3.1.1: PUBREC - Publish Received. - * - * - */ -struct mqtt_response_pubrec { - /** @brief The published messages packet ID. */ - uint16_t packet_id; -}; - -/** - * @brief The response to a PUBREC packet. - * @ingroup unpackers - * - * @see - * MQTT v3.1.1: PUBREL - Publish Release. - * - * - */ -struct mqtt_response_pubrel { - /** @brief The published messages packet ID. */ - uint16_t packet_id; -}; - -/** - * @brief The response to a PUBREL packet. - * @ingroup unpackers - * - * @see - * MQTT v3.1.1: PUBCOMP - Publish Complete. - * - * - */ -struct mqtt_response_pubcomp { - /** T@brief he published messages packet ID. */ - uint16_t packet_id; -}; - -/** - * @brief An enumeration of subscription acknowledgement return codes. - * @ingroup unpackers - * - * @see - * MQTT v3.1.1: SUBACK Return Codes. - * - */ -enum MQTTSubackReturnCodes { - MQTT_SUBACK_SUCCESS_MAX_QOS_0 = 0u, - MQTT_SUBACK_SUCCESS_MAX_QOS_1 = 1u, - MQTT_SUBACK_SUCCESS_MAX_QOS_2 = 2u, - MQTT_SUBACK_FAILURE = 128u -}; - -/** - * @brief The response to a subscription request. - * @ingroup unpackers - * - * @see - * MQTT v3.1.1: SUBACK - Subscription Acknowledgement. - * - */ -struct mqtt_response_suback { - /** @brief The published messages packet ID. */ - uint16_t packet_id; - - /** - * Array of return codes corresponding to the requested subscribe topics. - * - * @see MQTTSubackReturnCodes - */ - const uint8_t *return_codes; - - /** The number of return codes. */ - size_t num_return_codes; -}; - -/** - * @brief The brokers response to a UNSUBSCRIBE request. - * @ingroup unpackers - * - * @see - * MQTT v3.1.1: UNSUBACK - Unsubscribe Acknowledgement. - * - */ -struct mqtt_response_unsuback { - /** @brief The published messages packet ID. */ - uint16_t packet_id; -}; - -/** - * @brief The response to a ping request. - * @ingroup unpackers - * - * @note This response contains no members. - * - * @see - * MQTT v3.1.1: PINGRESP - Ping Response. - * - */ -struct mqtt_response_pingresp { - int dummy; -}; - -/** - * @brief A struct used to deserialize/interpret an incoming packet from the broker. - * @ingroup unpackers - */ -struct mqtt_response { - /** @brief The mqtt_fixed_header of the deserialized packet. */ - struct mqtt_fixed_header fixed_header; - - /** - * @brief A union of the possible responses from the broker. - * - * @note The fixed_header contains the control type. This control type corresponds to the - * member of this union that should be accessed. For example if - * fixed_header#control_type == \c MQTT_CONTROL_PUBLISH then - * decoded#publish should be accessed. - */ - union { - struct mqtt_response_connack connack; - struct mqtt_response_publish publish; - struct mqtt_response_puback puback; - struct mqtt_response_pubrec pubrec; - struct mqtt_response_pubrel pubrel; - struct mqtt_response_pubcomp pubcomp; - struct mqtt_response_suback suback; - struct mqtt_response_unsuback unsuback; - struct mqtt_response_pingresp pingresp; - } decoded; -}; - -/** - * @brief Deserialize the contents of \p buf into an mqtt_fixed_header object. - * @ingroup unpackers - * - * @note This function performs complete error checking and a positive return value - * means the entire mqtt_response can be deserialized from \p buf. - * - * @param[out] response the response who's \ref mqtt_response.fixed_header will be initialized. - * @param[in] buf the buffer. - * @param[in] bufsz the total number of bytes in the buffer. - * - * @returns The number of bytes that were consumed, or 0 if the buffer does not contain enough - * bytes to parse the packet, or a negative value if there was a protocol violation. - */ -ssize_t mqtt_unpack_fixed_header(struct mqtt_response *response, const uint8_t *buf, size_t bufsz); - -/** - * @brief Deserialize a CONNACK response from \p buf. - * @ingroup unpackers - * - * @pre \ref mqtt_unpack_fixed_header must have returned a positive value and the control packet type - * must be \c MQTT_CONTROL_CONNACK. - * - * @param[out] mqtt_response the mqtt_response that will be initialized. - * @param[in] buf the buffer that contains the variable header and payload of the packet. The - * first byte of \p buf should be the first byte of the variable header. - * - * @relates mqtt_response_connack - * - * @returns The number of bytes that were consumed, or 0 if the buffer does not contain enough - * bytes to parse the packet, or a negative value if there was a protocol violation. - */ -ssize_t mqtt_unpack_connack_response(struct mqtt_response *mqtt_response, const uint8_t *buf); - -/** - * @brief Deserialize a publish response from \p buf. - * @ingroup unpackers - * - * @pre \ref mqtt_unpack_fixed_header must have returned a positive value and the mqtt_response must - * have a control type of \c MQTT_CONTROL_PUBLISH. - * - * @param[out] mqtt_response the response that is initialized from the contents of \p buf. - * @param[in] buf the buffer with the incoming data. - * - * @relates mqtt_response_publish - * - * @returns The number of bytes that were consumed, or 0 if the buffer does not contain enough - * bytes to parse the packet, or a negative value if there was a protocol violation. - */ -ssize_t mqtt_unpack_publish_response(struct mqtt_response *mqtt_response, const uint8_t *buf); - -/** - * @brief Deserialize a PUBACK/PUBREC/PUBREL/PUBCOMP packet from \p buf. - * @ingroup unpackers - * - * @pre \ref mqtt_unpack_fixed_header must have returned a positive value and the mqtt_response must - * have a control type of \c MQTT_CONTROL_PUBACK, \c MQTT_CONTROL_PUBREC, \c MQTT_CONTROL_PUBREL - * or \c MQTT_CONTROL_PUBCOMP. - * - * @param[out] mqtt_response the response that is initialized from the contents of \p buf. - * @param[in] buf the buffer with the incoming data. - * - * @relates mqtt_response_puback mqtt_response_pubrec mqtt_response_pubrel mqtt_response_pubcomp - * - * @returns The number of bytes that were consumed, or 0 if the buffer does not contain enough - * bytes to parse the packet, or a negative value if there was a protocol violation. - */ -ssize_t mqtt_unpack_pubxxx_response(struct mqtt_response *mqtt_response, const uint8_t *buf); - -/** - * @brief Deserialize a SUBACK packet from \p buf. - * @ingroup unpacker - * - * @pre \ref mqtt_unpack_fixed_header must have returned a positive value and the mqtt_response must - * have a control type of \c MQTT_CONTROL_SUBACK. - * - * @param[out] mqtt_response the response that is initialized from the contents of \p buf. - * @param[in] buf the buffer with the incoming data. - * - * @relates mqtt_response_suback - * - * @returns The number of bytes that were consumed, or 0 if the buffer does not contain enough - * bytes to parse the packet, or a negative value if there was a protocol violation. - */ -ssize_t mqtt_unpack_suback_response(struct mqtt_response *mqtt_response, const uint8_t *buf); - -/** - * @brief Deserialize an UNSUBACK packet from \p buf. - * @ingroup unpacker - * - * @pre \ref mqtt_unpack_fixed_header must have returned a positive value and the mqtt_response must - * have a control type of \c MQTT_CONTROL_UNSUBACK. - * - * @param[out] mqtt_response the response that is initialized from the contents of \p buf. - * @param[in] buf the buffer with the incoming data. - * - * @relates mqtt_response_unsuback - * - * @returns The number of bytes that were consumed, or 0 if the buffer does not contain enough - * bytes to parse the packet, or a negative value if there was a protocol violation. - */ -ssize_t mqtt_unpack_unsuback_response(struct mqtt_response *mqtt_response, const uint8_t *buf); - -/** - * @brief Deserialize a packet from the broker. - * @ingroup unpackers - * - * @param[out] response the mqtt_response that will be initialize from \p buf. - * @param[in] buf the incoming data buffer. - * @param[in] bufsz the number of bytes available in the buffer. - * - * @relates mqtt_response - * - * @returns The number of bytes consumed on success, zero \p buf does not contain enough bytes - * to deserialize the packet, a negative value if a protocol violation was encountered. - */ -ssize_t mqtt_unpack_response(struct mqtt_response *response, const uint8_t *buf, size_t bufsz); - -/* REQUESTS */ - -/** -* @brief Serialize an mqtt_fixed_header and write it to \p buf. -* @ingroup packers -* -* @note This function performs complete error checking and a positive return value -* guarantees the entire packet will fit into the given buffer. -* -* @param[out] buf the buffer to write to. -* @param[in] bufsz the maximum number of bytes that can be put in to \p buf. -* @param[in] fixed_header the fixed header that will be serialized. -* -* @returns The number of bytes written to \p buf, or 0 if \p buf is too small, or a -* negative value if there was a protocol violation. -*/ -ssize_t mqtt_pack_fixed_header(uint8_t *buf, size_t bufsz, const struct mqtt_fixed_header *fixed_header); - -/** - * @brief An enumeration of CONNECT packet flags. - * @ingroup packers - * - * @see - * MQTT v3.1.1: CONNECT Variable Header. - * - */ -enum MQTTConnectFlags { - MQTT_CONNECT_RESERVED = 1u, - MQTT_CONNECT_CLEAN_SESSION = 2u, - MQTT_CONNECT_WILL_FLAG = 4u, - MQTT_CONNECT_WILL_QOS_0 = (0u & 0x03) << 3, - MQTT_CONNECT_WILL_QOS_1 = (1u & 0x03) << 3, - MQTT_CONNECT_WILL_QOS_2 = (2u & 0x03) << 3, - MQTT_CONNECT_WILL_RETAIN = 32u, - MQTT_CONNECT_PASSWORD = 64u, - MQTT_CONNECT_USER_NAME = 128u -}; - -/** - * @brief Serialize a connection request into a buffer. - * @ingroup packers - * - * @param[out] buf the buffer to pack the connection request packet into. - * @param[in] bufsz the number of bytes left in \p buf. - * @param[in] client_id the ID that identifies the local client. \p client_id can be NULL or an empty - * string for Anonymous clients. - * @param[in] will_topic the topic under which the local client's will message will be published. - * Set to \c NULL for no will message. If \p will_topic is not \c NULL a - * \p will_message must also be provided. - * @param[in] will_message the will message to be published upon a unsuccessful disconnection of - * the local client. Set to \c NULL if \p will_topic is \c NULL. - * \p will_message must \em not be \c NULL if \p will_topic is not - * \c NULL. - * @param[in] will_message_size The size of \p will_message in bytes. - * @param[in] user_name the username to be used to connect to the broker with. Set to \c NULL if - * no username is required. - * @param[in] password the password to be used to connect to the broker with. Set to \c NULL if - * no password is required. - * @param[in] connect_flags additional MQTTConnectFlags to be set. The only flags that need to be - * set manually are \c MQTT_CONNECT_CLEAN_SESSION, - * \c MQTT_CONNECT_WILL_QOS_X (for \c X ∈ {0, 1, 2}), and - * \c MQTT_CONNECT_WILL_RETAIN. Set to 0 if no additional flags are - * required. - * @param[in] keep_alive the keep alive time in seconds. It is the responsibility of the clinet - * to ensure packets are sent to the server \em {at least} this frequently. - * - * @note If there is a \p will_topic and no additional \p connect_flags are given, then by - * default \p will_message will be published at QoS level 0. - * - * @see - * MQTT v3.1.1: CONNECT - Client Requests a Connection to a Server. - * - * - * @returns The number of bytes put into \p buf, 0 if \p buf is too small to fit the CONNECT - * packet, a negative value if there was a protocol violation. - */ -ssize_t mqtt_pack_connection_request(uint8_t *buf, size_t bufsz, - const char *client_id, - const char *will_topic, - const void *will_message, - size_t will_message_size, - const char *user_name, - const char *password, - uint8_t connect_flags, - uint16_t keep_alive); - -/** - * @brief An enumeration of the PUBLISH flags. - * @ingroup packers - * - * @see - * MQTT v3.1.1: PUBLISH - Publish Message. - * - */ -enum MQTTPublishFlags { - MQTT_PUBLISH_DUP = 8u, - MQTT_PUBLISH_QOS_0 = ((0u << 1) & 0x06), - MQTT_PUBLISH_QOS_1 = ((1u << 1) & 0x06), - MQTT_PUBLISH_QOS_2 = ((2u << 1) & 0x06), - MQTT_PUBLISH_QOS_MASK = ((3u << 1) & 0x06), - MQTT_PUBLISH_RETAIN = 0x01 -}; - -/** - * @brief Serialize a PUBLISH request and put it in \p buf. - * @ingroup packers - * - * @param[out] buf the buffer to put the PUBLISH packet in. - * @param[in] bufsz the maximum number of bytes that can be put into \p buf. - * @param[in] topic_name the topic to publish \p application_message under. - * @param[in] packet_id this packets packet ID. - * @param[in] application_message the application message to be published. - * @param[in] application_message_size the size of \p application_message in bytes. - * @param[in] publish_flags The flags to publish \p application_message with. These include - * the \c MQTT_PUBLISH_DUP flag, \c MQTT_PUBLISH_QOS_X (\c X ∈ - * {0, 1, 2}), and \c MQTT_PUBLISH_RETAIN flag. - * - * @note The default QoS is level 0. - * - * @see - * MQTT v3.1.1: PUBLISH - Publish Message. - * - * - * @returns The number of bytes put into \p buf, 0 if \p buf is too small to fit the PUBLISH - * packet, a negative value if there was a protocol violation. - */ -ssize_t mqtt_pack_publish_request(uint8_t *buf, size_t bufsz, - const char *topic_name, - uint16_t packet_id, - const void *application_message, - size_t application_message_size, - uint8_t publish_flags); - -/** - * @brief Serialize a PUBACK, PUBREC, PUBREL, or PUBCOMP packet and put it in \p buf. - * @ingroup packers - * - * @param[out] buf the buffer to put the PUBXXX packet in. - * @param[in] bufsz the maximum number of bytes that can be put into \p buf. - * @param[in] control_type the type of packet. Must be one of: \c MQTT_CONTROL_PUBACK, - * \c MQTT_CONTROL_PUBREC, \c MQTT_CONTROL_PUBREL, - * or \c MQTT_CONTROL_PUBCOMP. - * @param[in] packet_id the packet ID of the packet being acknowledged. - * - * - * @see - * MQTT v3.1.1: PUBACK - Publish Acknowledgement. - * - * @see - * MQTT v3.1.1: PUBREC - Publish Received. - * - * @see - * MQTT v3.1.1: PUBREL - Publish Released. - * - * @see - * MQTT v3.1.1: PUBCOMP - Publish Complete. - * - * - * @returns The number of bytes put into \p buf, 0 if \p buf is too small to fit the PUBXXX - * packet, a negative value if there was a protocol violation. - */ -ssize_t mqtt_pack_pubxxx_request(uint8_t *buf, size_t bufsz, - enum MQTTControlPacketType control_type, - uint16_t packet_id); - -/** - * @brief The maximum number topics that can be subscribed to in a single call to - * mqtt_pack_subscribe_request. - * @ingroup packers - * - * @see mqtt_pack_subscribe_request - */ -#define MQTT_SUBSCRIBE_REQUEST_MAX_NUM_TOPICS 8 - -/** - * @brief Serialize a SUBSCRIBE packet and put it in \p buf. - * @ingroup packers - * - * @param[out] buf the buffer to put the SUBSCRIBE packet in. - * @param[in] bufsz the maximum number of bytes that can be put into \p buf. - * @param[in] packet_id the packet ID to be used. - * @param[in] ... \c NULL terminated list of (\c {const char *topic_name}, \c {int max_qos_level}) - * pairs. - * - * @note The variadic arguments, \p ..., \em must be followed by a \c NULL. For example: - * @code - * ssize_t n = mqtt_pack_subscribe_request(buf, bufsz, 1234, "topic_1", 0, "topic_2", 2, NULL); - * @endcode - * - * @see - * MQTT v3.1.1: SUBSCRIBE - Subscribe to Topics. - * - * - * @returns The number of bytes put into \p buf, 0 if \p buf is too small to fit the SUBSCRIBE - * packet, a negative value if there was a protocol violation. - */ -ssize_t mqtt_pack_subscribe_request(uint8_t *buf, size_t bufsz, - unsigned int packet_id, - ...); /* null terminated */ - -/** - * @brief The maximum number topics that can be subscribed to in a single call to - * mqtt_pack_unsubscribe_request. - * @ingroup packers - * - * @see mqtt_pack_unsubscribe_request - */ -#define MQTT_UNSUBSCRIBE_REQUEST_MAX_NUM_TOPICS 8 - -/** - * @brief Serialize a UNSUBSCRIBE packet and put it in \p buf. - * @ingroup packers - * - * @param[out] buf the buffer to put the UNSUBSCRIBE packet in. - * @param[in] bufsz the maximum number of bytes that can be put into \p buf. - * @param[in] packet_id the packet ID to be used. - * @param[in] ... \c NULL terminated list of \c {const char *topic_name}'s to unsubscribe from. - * - * @note The variadic arguments, \p ..., \em must be followed by a \c NULL. For example: - * @code - * ssize_t n = mqtt_pack_unsubscribe_request(buf, bufsz, 4321, "topic_1", "topic_2", NULL); - * @endcode - * - * @see - * MQTT v3.1.1: UNSUBSCRIBE - Unsubscribe from Topics. - * - * - * @returns The number of bytes put into \p buf, 0 if \p buf is too small to fit the UNSUBSCRIBE - * packet, a negative value if there was a protocol violation. - */ -ssize_t mqtt_pack_unsubscribe_request(uint8_t *buf, size_t bufsz, - unsigned int packet_id, - ...); /* null terminated */ - -/** - * @brief Serialize a PINGREQ and put it into \p buf. - * @ingroup packers - * - * @param[out] buf the buffer to put the PINGREQ packet in. - * @param[in] bufsz the maximum number of bytes that can be put into \p buf. - * - * @see - * MQTT v3.1.1: PINGREQ - Ping Request. - * - * - * @returns The number of bytes put into \p buf, 0 if \p buf is too small to fit the PINGREQ - * packet, a negative value if there was a protocol violation. - */ -ssize_t mqtt_pack_ping_request(uint8_t *buf, size_t bufsz); - -/** - * @brief Serialize a DISCONNECT and put it into \p buf. - * @ingroup packers - * - * @param[out] buf the buffer to put the DISCONNECT packet in. - * @param[in] bufsz the maximum number of bytes that can be put into \p buf. - * - * @see - * MQTT v3.1.1: DISCONNECT - Disconnect Notification. - * - * - * @returns The number of bytes put into \p buf, 0 if \p buf is too small to fit the DISCONNECT - * packet, a negative value if there was a protocol violation. - */ -ssize_t mqtt_pack_disconnect(uint8_t *buf, size_t bufsz); - - -/** - * @brief An enumeration of queued message states. - * @ingroup details - */ -enum MQTTQueuedMessageState { - MQTT_QUEUED_UNSENT, - MQTT_QUEUED_AWAITING_ACK, - MQTT_QUEUED_COMPLETE -}; - -/** - * @brief A message in a mqtt_message_queue. - * @ingroup details - */ -struct mqtt_queued_message { - /** @brief A pointer to the start of the message. */ - uint8_t *start; - - /** @brief The number of bytes in the message. */ - size_t size; - - - /** @brief The state of the message. */ - enum MQTTQueuedMessageState state; - - /** - * @brief The time at which the message was sent.. - * - * @note A timeout will only occur if the message is in - * the MQTT_QUEUED_AWAITING_ACK \c state. - */ - mqtt_pal_time_t time_sent; - - /** - * @brief The control type of the message. - */ - enum MQTTControlPacketType control_type; - - /** - * @brief The packet id of the message. - * - * @note This field is only used if the associate \c control_type has a - * \c packet_id field. - */ - uint16_t packet_id; -}; - -/** - * @brief A message queue. - * @ingroup details - * - * @note This struct is used internally to manage sending messages. - * @note The only members the user should use are \c curr and \c curr_sz. - */ -struct mqtt_message_queue { - /** - * @brief The start of the message queue's memory block. - * - * @warning This member should \em not be manually changed. - */ - void *mem_start; - - /** @brief The end of the message queue's memory block. */ - void *mem_end; - - /** - * @brief A pointer to the position in the buffer you can pack bytes at. - * - * @note Immediately after packing bytes at \c curr you \em must call - * mqtt_mq_register. - */ - uint8_t *curr; - - /** - * @brief The number of bytes that can be written to \c curr. - * - * @note curr_sz will decrease by more than the number of bytes you write to - * \c curr. This is because the mqtt_queued_message structs share the - * same memory (and thus, a mqtt_queued_message must be allocated in - * the message queue's memory whenever a new message is registered). - */ - size_t curr_sz; - - /** - * @brief The tail of the array of mqtt_queued_messages's. - * - * @note This member should not be used manually. - */ - struct mqtt_queued_message *queue_tail; -}; - -/** - * @brief Initialize a message queue. - * @ingroup details - * - * @param[out] mq The message queue to initialize. - * @param[in] buf The buffer for this message queue. - * @param[in] bufsz The number of bytes in the buffer. - * - * @relates mqtt_message_queue - */ -void mqtt_mq_init(struct mqtt_message_queue *mq, void *buf, size_t bufsz); - -/** - * @brief Clear as many messages from the front of the queue as possible. - * @ingroup details - * - * @note Calls to this function are the \em only way to remove messages from the queue. - * - * @param mq The message queue. - * - * @relates mqtt_message_queue - */ -void mqtt_mq_clean(struct mqtt_message_queue *mq); - -/** - * @brief Register a message that was just added to the buffer. - * @ingroup details - * - * @note This function should be called immediately following a call to a packer function - * that returned a positive value. The positive value (number of bytes packed) should - * be passed to this function. - * - * @param mq The message queue. - * @param[in] nbytes The number of bytes that were just packed. - * - * @note This function will step mqtt_message_queue::curr and update mqtt_message_queue::curr_sz. - * @relates mqtt_message_queue - * - * @returns The newly added struct mqtt_queued_message. - */ -struct mqtt_queued_message *mqtt_mq_register(struct mqtt_message_queue *mq, size_t nbytes); - -/** - * @brief Find a message in the message queue. - * @ingroup details - * - * @param mq The message queue. - * @param[in] control_type The control type of the message you want to find. - * @param[in] packet_id The packet ID of the message you want to find. Set to \c NULL if you - * don't want to specify a packet ID. - * - * @relates mqtt_message_queue - * @returns The found message. \c NULL if the message was not found. - */ -struct mqtt_queued_message *mqtt_mq_find(const struct mqtt_message_queue *mq, enum MQTTControlPacketType control_type, const uint16_t *packet_id); - -/** - * @brief Returns the mqtt_queued_message at \p index. - * @ingroup details - * - * @param mq_ptr A pointer to the message queue. - * @param index The index of the message. - * - * @returns The mqtt_queued_message at \p index. - */ -#define mqtt_mq_get(mq_ptr, index) (((struct mqtt_queued_message*) ((mq_ptr)->mem_end)) - 1 - index) - -/** - * @brief Returns the number of messages in the message queue, \p mq_ptr. - * @ingroup details - */ -#define mqtt_mq_length(mq_ptr) (((struct mqtt_queued_message*) ((mq_ptr)->mem_end)) - (mq_ptr)->queue_tail) - -/** - * @brief Used internally to recalculate the \c curr_sz. - * @ingroup details - */ -#define mqtt_mq_currsz(mq_ptr) (((mq_ptr)->curr >= (uint8_t*) ((mq_ptr)->queue_tail - 1)) ? 0 : ((uint8_t*) ((mq_ptr)->queue_tail - 1)) - (mq_ptr)->curr) - -/* CLIENT */ - -/** - * @brief An MQTT client. - * @ingroup details - * - * @note All members can be manipulated via the related functions. - */ -struct mqtt_client { - /** @brief The socket connecting to the MQTT broker. */ - mqtt_pal_socket_handle socketfd; - - /** @brief The LFSR state used to generate packet ID's. */ - uint16_t pid_lfsr; - - /** @brief The keep-alive time in seconds. */ - uint16_t keep_alive; - - /** - * @brief A counter counting pings that have been sent to keep the connection alive. - * @see keep_alive - */ - int number_of_keep_alives; - - /** - * @brief The current sent offset. - * - * This is used to allow partial send commands. - */ - size_t send_offset; - - /** - * @brief The timestamp of the last message sent to the buffer. - * - * This is used to detect the need for keep-alive pings. - * - * @see keep_alive - */ - mqtt_pal_time_t time_of_last_send; - - /** - * @brief The error state of the client. - * - * error should be MQTT_OK for the entirety of the connection. - * - * @note The error state will be MQTT_ERROR_CONNECT_NOT_CALLED until - * you call mqtt_connect. - */ - enum MQTTErrors error; - - /** - * @brief The timeout period in seconds. - * - * If the broker doesn't return an ACK within response_timeout seconds a timeout - * will occur and the message will be retransmitted. - * - * @note The default value is 30 [seconds] but you can change it at any time. - */ - int response_timeout; - - /** @brief A counter counting the number of timeouts that have occurred. */ - int number_of_timeouts; - - /** - * @brief Approximately much time it has typically taken to receive responses from the - * broker. - * - * @note This is tracked using a exponential-averaging. - */ - float typical_response_time; - - /** - * @brief The callback that is called whenever a publish is received from the broker. - * - * Any topics that you have subscribed to will be returned from the broker as - * mqtt_response_publish messages. All the publishes received from the broker will - * be passed to this function. - * - * @note A pointer to publish_response_callback_state is always passed to the callback. - * Use publish_response_callback_state to keep track of any state information you - * need. - */ - void (*publish_response_callback)(void **state, struct mqtt_response_publish *publish); - - /** - * @brief A pointer to any publish_response_callback state information you need. - * - * @note A pointer to this pointer will always be publish_response_callback upon - * receiving a publish message from the broker. - */ - void *publish_response_callback_state; - - /** - * @brief A user-specified callback, triggered on each \ref mqtt_sync, allowing - * the user to perform state inspections (and custom socket error detection) - * on the client. - * - * This callback is triggered on each call to \ref mqtt_sync. If it returns MQTT_OK - * then \ref mqtt_sync will continue normally (performing reads and writes). If it - * returns an error then \ref mqtt_sync will not call reads and writes. - * - * This callback can be used to perform custom error detection, namely platform - * specific socket error detection, and force the client into an error state. - * - * This member is always initialized to NULL but it can be manually set at any - * time. - */ - enum MQTTErrors(*inspector_callback)(struct mqtt_client *); - - /** - * @brief A callback that is called whenever the client is in an error state. - * - * This callback is responsible for: application level error handling, closing - * previous sockets, and reestabilishing the connection to the broker and - * session configurations (i.e. subscriptions). - */ - void (*reconnect_callback)(struct mqtt_client *, void **); - - /** - * @brief A pointer to some state. A pointer to this member is passed to - * \ref mqtt_client.reconnect_callback. - */ - void *reconnect_state; - - /** - * @brief The buffer where ingress data is temporarily stored. - */ - struct { - /** @brief The start of the receive buffer's memory. */ - uint8_t *mem_start; - - /** @brief The size of the receive buffer's memory. */ - size_t mem_size; - - /** @brief A pointer to the next writable location in the receive buffer. */ - uint8_t *curr; - - /** @brief The number of bytes that are still writable at curr. */ - size_t curr_sz; - } recv_buffer; - - /** - * @brief A variable passed to support thread-safety. - * - * A pointer to this variable is passed to \c MQTT_PAL_MUTEX_LOCK, and - * \c MQTT_PAL_MUTEX_UNLOCK. - */ - mqtt_pal_mutex_t mutex; - - /** @brief The sending message queue. */ - struct mqtt_message_queue mq; -}; - -/** - * @brief Generate a new next packet ID. - * @ingroup details - * - * Packet ID's are generated using a max-length LFSR. - * - * @param client The MQTT client. - * - * @returns The new packet ID that should be used. - */ -uint16_t __mqtt_next_pid(struct mqtt_client *client); - -/** - * @brief Handles egress client traffic. - * @ingroup details - * - * @param client The MQTT client. - * - * @returns MQTT_OK upon success, an \ref MQTTErrors otherwise. - */ -ssize_t __mqtt_send(struct mqtt_client *client); - -/** - * @brief Handles ingress client traffic. - * @ingroup details - * - * @param client The MQTT client. - * - * @returns MQTT_OK upon success, an \ref MQTTErrors otherwise. - */ -ssize_t __mqtt_recv(struct mqtt_client *client); - -/** - * @brief Function that does the actual sending and receiving of - * traffic from the network. - * @ingroup api - * - * All the other functions in the @ref api simply stage messages for - * being sent to the broker. This function does the actual sending of - * those messages. Additionally this function receives traffic (responses and - * acknowledgements) from the broker and responds to that traffic accordingly. - * Lastly this function also calls the \c publish_response_callback when - * any \c MQTT_CONTROL_PUBLISH messages are received. - * - * @pre mqtt_init must have been called. - * - * @param[in,out] client The MQTT client. - * - * @attention It is the responsibility of the application programmer to - * call this function periodically. All functions in the @ref api are - * thread-safe so it is perfectly reasonable to have a thread dedicated - * to calling this function every 200 ms or so. MQTT-C can be used in single - * threaded application though by simply calling this functino periodically - * inside your main thread. See @ref simple_publisher.c and @ref simple_subscriber.c - * for examples (specifically the \c client_refresher functions). - * - * @returns MQTT_OK upon success, an \ref MQTTErrors otherwise. - */ -enum MQTTErrors mqtt_sync(struct mqtt_client *client); - -/** - * @brief Initializes an MQTT client. - * @ingroup api - * - * This function \em must be called before any other API function calls. - * - * @pre None. - * - * @param[out] client The MQTT client. - * @param[in] sockfd The socket file descriptor (or equivalent socket handle, e.g. BIO pointer - * for OpenSSL sockets) connected to the MQTT broker. - * @param[in] sendbuf A buffer that will be used for sending messages to the broker. - * @param[in] sendbufsz The size of \p sendbuf in bytes. - * @param[in] recvbuf A buffer that will be used for receiving messages from the broker. - * @param[in] recvbufsz The size of \p recvbuf in bytes. - * @param[in] publish_response_callback The callback to call whenever application messages - * are received from the broker. - * - * @post mqtt_connect must be called. - * - * @note \p sockfd is a non-blocking TCP connection. - * @note If \p sendbuf fills up completely during runtime a \c MQTT_ERROR_SEND_BUFFER_IS_FULL - * error will be set. Similarly if \p recvbuf is ever to small to receive a message from - * the broker an MQTT_ERROR_RECV_BUFFER_TOO_SMALL error will be set. - * @note A pointer to \ref mqtt_client.publish_response_callback_state is always passed as the - * \c state argument to \p publish_response_callback. Note that the second argument is - * the mqtt_response_publish that was received from the broker. - * - * @attention Only initialize an MQTT client once (i.e. don't call \ref mqtt_init or - * \ref mqtt_init_reconnect more than once per client). - * @attention \p sendbuf internally mapped to client's message-to-send queue that actively uses - * pointer access. In the case of unaligned \p sendbuf, that may lead to - * Segmentation/Hard/Memory Faults on systems that do not support unaligned pointer - * access (e.g. ARMv6, ARMv7-M). To avoid that, you may use the following technique: - * \code{.c} - * // example for ARMv7-M that requires pointers to be word aligned (4 byte boundary) - * static unsigned char mqtt_tx_buffer[MAX_TX_BUFFER_SIZE] __attribute__((aligned(4))); - * static unsigned char mqtt_rx_buffer[MAX_RX_BUFFER_SIZE]; - * // ... - * int main(void) { - * // ... - * mqtt_init(p_client, p_client->socketfd, mqtt_tx_buffer, sizeof mqtt_tx_buffer, mqtt_rx_buffer, - * sizeof mqtt_rx_buffer, message_callback); - * // ... - * } - * \endcode - * - * @returns \c MQTT_OK upon success, an \ref MQTTErrors otherwise. - */ -enum MQTTErrors mqtt_init(struct mqtt_client *client, - mqtt_pal_socket_handle sockfd, - uint8_t *sendbuf, size_t sendbufsz, - uint8_t *recvbuf, size_t recvbufsz, - void (*publish_response_callback)(void **state, struct mqtt_response_publish *publish)); - -/** - * @brief Initializes an MQTT client and enables automatic reconnections. - * @ingroup api - * - * An alternative to \ref mqtt_init that allows the client to automatically reconnect to the - * broker after an error occurs (e.g. socket error or internal buffer overflows). - * - * This is accomplished by calling the \p reconnect_callback whenever the client enters an error - * state. The job of the \p reconnect_callback is to: (1) perform error handling/logging, - * (2) clean up the old connection (i.e. close client->socketfd), (3) \ref mqtt_reinit the - * client, and (4) reconfigure the MQTT session by calling \ref mqtt_connect followed by other - * API calls such as \ref mqtt_subscribe. - * - * The first argument to the \p reconnect_callback is the client (which will be in an error - * state) and the second argument is a pointer to a void pointer where you can store some state - * information. Internally, MQTT-C calls the reconnect callback like so: - * - * \code - * client->reconnect_callback(client, &client->reconnect_state) - * \endcode - * - * Note that the \p reconnect_callback is also called to setup the initial session. After - * calling \ref mqtt_init_reconnect the client will be in the error state - * \c MQTT_ERROR_INITIAL_RECONNECT. - * - * @pre None. - * - * @param[in,out] client The MQTT client that will be initialized. - * @param[in] reconnect_callback The callback that will be called to connect/reconnect the - * client to the broker and perform application level error handling. - * @param[in] reconnect_state A pointer to some state data for your \p reconnect_callback. - * If your \p reconnect_callback does not require any state information set this - * to NULL. A pointer to the memory address where the client stores a copy of this - * pointer is passed as the second argumnet to \p reconnect_callback. - * @param[in] publish_response_callback The callback to call whenever application messages - * are received from the broker. - * - * @post Call \p reconnect_callback yourself, or call \ref mqtt_sync - * (which will trigger the call to \p reconnect_callback). - * - * @attention Only initialize an MQTT client once (i.e. don't call \ref mqtt_init or - * \ref mqtt_init_reconnect more than once per client). - * - */ -void mqtt_init_reconnect(struct mqtt_client *client, - void (*reconnect_callback)(struct mqtt_client *client, void **state), - void *reconnect_state, - void (*publish_response_callback)(void **state, struct mqtt_response_publish *publish)); - -/** - * @brief Safely assign/reassign a socket and buffers to an new/existing client. - * @ingroup api - * - * This function also clears the \p client error state. Upon exiting this function - * \c client->error will be \c MQTT_ERROR_CONNECT_NOT_CALLED (which will be cleared) - * as soon as \ref mqtt_connect is called. - * - * @pre This function must be called BEFORE \ref mqtt_connect. - * - * @param[in,out] client The MQTT client. - * @param[in] socketfd The new socket connected to the broker. - * @param[in] sendbuf The buffer that will be used to buffer egress traffic to the broker. - * @param[in] sendbufsz The size of \p sendbuf in bytes. - * @param[in] recvbuf The buffer that will be used to buffer ingress traffic from the broker. - * @param[in] recvbufsz The size of \p recvbuf in bytes. - * - * @post Call \ref mqtt_connect. - * - * @attention This function should be used in conjunction with clients that have been - * initialzed with \ref mqtt_init_reconnect. - */ -void mqtt_reinit(struct mqtt_client *client, - mqtt_pal_socket_handle socketfd, - uint8_t *sendbuf, size_t sendbufsz, - uint8_t *recvbuf, size_t recvbufsz); - -/** - * @brief Establishes a session with the MQTT broker. - * @ingroup api - * - * @pre mqtt_init must have been called. - * - * @param[in,out] client The MQTT client. - * @param[in] client_id The unique name identifying the client. (or NULL) - * @param[in] will_topic The topic name of client's \p will_message. If no will message is - * desired set to \c NULL. - * @param[in] will_message The application message (data) to be published in the event the - * client ungracefully disconnects. Set to \c NULL if \p will_topic is \c NULL. - * @param[in] will_message_size The size of \p will_message in bytes. - * @param[in] user_name The username to use when establishing the session with the MQTT broker. - * Set to \c NULL if a username is not required. - * @param[in] password The password to use when establishing the session with the MQTT broker. - * Set to \c NULL if a password is not required. - * @param[in] connect_flags Additional \ref MQTTConnectFlags to use when establishing the connection. - * These flags are for forcing the session to start clean, - * \c MQTT_CONNECT_CLEAN_SESSION, the QOS level to publish the \p will_message with - * (provided \c will_message != \c NULL), MQTT_CONNECT_WILL_QOS_[0,1,2], and whether - * or not the broker should retain the \c will_message, MQTT_CONNECT_WILL_RETAIN. - * @param[in] keep_alive The keep-alive time in seconds. A reasonable value for this is 400 [seconds]. - * - * @returns \c MQTT_OK upon success, an \ref MQTTErrors otherwise. - */ -enum MQTTErrors mqtt_connect(struct mqtt_client *client, - const char *client_id, - const char *will_topic, - const void *will_message, - size_t will_message_size, - const char *user_name, - const char *password, - uint8_t connect_flags, - uint16_t keep_alive); - -/* - todo: will_message should be a void* -*/ - -/** - * @brief Publish an application message. - * @ingroup api - * - * Publishes an application message to the MQTT broker. - * - * @pre mqtt_connect must have been called. - * - * @param[in,out] client The MQTT client. - * @param[in] topic_name The name of the topic. - * @param[in] application_message The data to be published. - * @param[in] application_message_size The size of \p application_message in bytes. - * @param[in] publish_flags \ref MQTTPublishFlags to be used, namely the QOS level to - * publish at (MQTT_PUBLISH_QOS_[0,1,2]) or whether or not the broker should - * retain the publish (MQTT_PUBLISH_RETAIN). - * - * @returns \c MQTT_OK upon success, an \ref MQTTErrors otherwise. - */ -enum MQTTErrors mqtt_publish(struct mqtt_client *client, - const char *topic_name, - const void *application_message, - size_t application_message_size, - uint8_t publish_flags); - -/** - * @brief Acknowledge an ingree publish with QOS==1. - * @ingroup details - * - * @param[in,out] client The MQTT client. - * @param[in] packet_id The packet ID of the ingress publish being acknowledged. - * - * @returns \c MQTT_OK upon success, an \ref MQTTErrors otherwise. - */ -ssize_t __mqtt_puback(struct mqtt_client *client, uint16_t packet_id); - -/** - * @brief Acknowledge an ingree publish with QOS==2. - * @ingroup details - * - * @param[in,out] client The MQTT client. - * @param[in] packet_id The packet ID of the ingress publish being acknowledged. - * - * @returns \c MQTT_OK upon success, an \ref MQTTErrors otherwise. - */ -ssize_t __mqtt_pubrec(struct mqtt_client *client, uint16_t packet_id); - -/** - * @brief Acknowledge an ingree PUBREC packet. - * @ingroup details - * - * @param[in,out] client The MQTT client. - * @param[in] packet_id The packet ID of the ingress PUBREC being acknowledged. - * - * @returns \c MQTT_OK upon success, an \ref MQTTErrors otherwise. - */ -ssize_t __mqtt_pubrel(struct mqtt_client *client, uint16_t packet_id); - -/** - * @brief Acknowledge an ingree PUBREL packet. - * @ingroup details - * - * @param[in,out] client The MQTT client. - * @param[in] packet_id The packet ID of the ingress PUBREL being acknowledged. - * - * @returns \c MQTT_OK upon success, an \ref MQTTErrors otherwise. - */ -ssize_t __mqtt_pubcomp(struct mqtt_client *client, uint16_t packet_id); - - -/** - * @brief Subscribe to a topic. - * @ingroup api - * - * @pre mqtt_connect must have been called. - * - * @param[in,out] client The MQTT client. - * @param[in] topic_name The name of the topic to subscribe to. - * @param[in] max_qos_level The maximum QOS level with which the broker can send application - * messages for this topic. - * - * @returns \c MQTT_OK upon success, an \ref MQTTErrors otherwise. - */ -enum MQTTErrors mqtt_subscribe(struct mqtt_client *client, - const char *topic_name, - int max_qos_level); - -/** - * @brief Unsubscribe from a topic. - * @ingroup api - * - * @pre mqtt_connect must have been called. - * - * @param[in,out] client The MQTT client. - * @param[in] topic_name The name of the topic to unsubscribe from. - * - * @returns \c MQTT_OK upon success, an \ref MQTTErrors otherwise. - */ -enum MQTTErrors mqtt_unsubscribe(struct mqtt_client *client, - const char *topic_name); - -/** - * @brief Ping the broker. - * @ingroup api - * - * @pre mqtt_connect must have been called. - * - * @param[in,out] client The MQTT client. - * - * @returns \c MQTT_OK upon success, an \ref MQTTErrors otherwise. - */ -enum MQTTErrors mqtt_ping(struct mqtt_client *client); - -/** - * @brief Ping the broker without locking/unlocking the mutex. - * @see mqtt_ping - */ -enum MQTTErrors __mqtt_ping(struct mqtt_client *client); - -/** - * @brief Terminate the session with the MQTT broker. - * @ingroup api - * - * @pre mqtt_connect must have been called. - * - * @param[in,out] client The MQTT client. - * - * @note To re-establish the session, mqtt_connect must be called. - * - * @returns \c MQTT_OK upon success, an \ref MQTTErrors otherwise. - */ -enum MQTTErrors mqtt_disconnect(struct mqtt_client *client); - -/** - * @brief Terminate the session with the MQTT broker and prepare to - * reconnect. Client code should call \ref mqtt_sync immediately - * after this call to prevent message loss. - * @ingroup api - * - * @note The user must provide a reconnect callback function for this to - * work as expected. See \r mqtt_client_reconnect. - * - * @pre mqtt_connect must have been called -* - * @param[in,out] client The MQTT client. - * - * @returns \c MQTT_OK upon success, an \ref MQTTErrors otherwise. - */ -enum MQTTErrors mqtt_reconnect(struct mqtt_client *client); - -#if defined(__cplusplus) -} -#endif - -#endif diff --git a/client/deps/mqtt/mqtt_pal.c b/client/deps/mqtt/mqtt_pal.c deleted file mode 100644 index 9ebab98b6..000000000 --- a/client/deps/mqtt/mqtt_pal.c +++ /dev/null @@ -1,235 +0,0 @@ -/* -MIT License - -Copyright(c) 2018 Liam Bindle - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include "mqtt.h" - -/** - * @file - * @brief Implements @ref mqtt_pal_sendall and @ref mqtt_pal_recvall and - * any platform-specific helpers you'd like. - * @cond Doxygen_Suppress - */ - -#if defined(MQTT_USE_CUSTOM_SOCKET_HANDLE) - -/* - * In case of MQTT_USE_CUSTOM_SOCKET_HANDLE, a pal implemantation is - * provided by the user. - */ - -/* Note: Some toolchains complain on an object without symbols */ - -int _mqtt_pal_dummy; - -#else /* defined(MQTT_USE_CUSTOM_SOCKET_HANDLE) */ - -#if defined(MQTT_USE_MBEDTLS) -#include - -ssize_t mqtt_pal_sendall(mqtt_pal_socket_handle fd, const void *buf, size_t len, int flags) { - enum MQTTErrors error = 0; - size_t sent = 0; - while (sent < len) { - int rv = mbedtls_ssl_write(fd, (const unsigned char *)buf + sent, len - sent); - if (rv < 0) { - if (rv == MBEDTLS_ERR_SSL_WANT_READ || - rv == MBEDTLS_ERR_SSL_WANT_WRITE -#if defined(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) - || rv == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -#endif -#if defined(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) - || rv == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -#endif - ) { - /* should call mbedtls_ssl_write later again */ - break; - } - error = MQTT_ERROR_SOCKET_ERROR; - break; - } - /* - * Note: rv can be 0 here eg. when mbedtls just flushed - * the previous incomplete record. - * - * Note: we never send an empty TLS record. - */ - sent += (size_t) rv; - } - if (sent == 0) { - return error; - } - return (ssize_t)sent; -} - -ssize_t mqtt_pal_recvall(mqtt_pal_socket_handle fd, void *buf, size_t bufsz, int flags) { - const void *const start = buf; - enum MQTTErrors error = 0; - int rv; - do { - rv = mbedtls_ssl_read(fd, (unsigned char *)buf, bufsz); - if (rv == 0) { - /* - * Note: mbedtls_ssl_read returns 0 when the underlying - * transport was closed without CloseNotify. - * - * Raise an error to trigger a reconnect. - */ - error = MQTT_ERROR_SOCKET_ERROR; - break; - } - if (rv < 0) { - if (rv == MBEDTLS_ERR_SSL_WANT_READ || - rv == MBEDTLS_ERR_SSL_WANT_WRITE -#if defined(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) - || rv == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -#endif -#if defined(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) - || rv == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -#endif - ) { - /* should call mbedtls_ssl_read later again */ - break; - } - /* Note: MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY is handled here. */ - error = MQTT_ERROR_SOCKET_ERROR; - break; - } - buf = (char *)buf + rv; - bufsz -= (unsigned long)rv; - } while (bufsz > 0); - if (buf == start) { - return error; - } - return (const char *)buf - (const char *)start; -} - -#elif defined(__unix__) || defined(__APPLE__) || defined(__NuttX__) - -#include - -ssize_t mqtt_pal_sendall(mqtt_pal_socket_handle fd, const void *buf, size_t len, int flags) { - enum MQTTErrors error = 0; - size_t sent = 0; - while (sent < len) { - ssize_t rv = send(fd, (const char *)buf + sent, len - sent, flags); - if (rv < 0) { - if (errno == EAGAIN) { - /* should call send later again */ - break; - } - error = MQTT_ERROR_SOCKET_ERROR; - break; - } - if (rv == 0) { - /* is this possible? maybe OS bug. */ - error = MQTT_ERROR_SOCKET_ERROR; - break; - } - sent += (size_t) rv; - } - if (sent == 0) { - return error; - } - return (ssize_t)sent; -} - -ssize_t mqtt_pal_recvall(mqtt_pal_socket_handle fd, void *buf, size_t bufsz, int flags) { - const void *const start = buf; - enum MQTTErrors error = 0; - ssize_t rv; - do { - rv = recv(fd, buf, bufsz, flags); - if (rv == 0) { - /* - * recv returns 0 when the socket is (half) closed by the peer. - * - * Raise an error to trigger a reconnect. - */ - error = MQTT_ERROR_SOCKET_ERROR; - break; - } - if (rv < 0) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - /* should call recv later again */ - break; - } - /* an error occurred that wasn't "nothing to read". */ - error = MQTT_ERROR_SOCKET_ERROR; - break; - } - buf = (char *)buf + rv; - bufsz -= (unsigned long)rv; - } while (bufsz > 0); - if (buf == start) { - return error; - } - return (char *)buf - (const char *)start; -} - -#elif defined(_MSC_VER) || defined(WIN32) - -#include - -ssize_t mqtt_pal_sendall(mqtt_pal_socket_handle fd, const void *buf, size_t len, int flags) { - size_t sent = 0; - while (sent < len) { - ssize_t tmp = send(fd, (char *)buf + sent, len - sent, flags); - if (tmp < 1) { - return MQTT_ERROR_SOCKET_ERROR; - } - sent += (size_t) tmp; - } - return sent; -} - -ssize_t mqtt_pal_recvall(mqtt_pal_socket_handle fd, void *buf, size_t bufsz, int flags) { - const char *const start = buf; - ssize_t rv; - do { - rv = recv(fd, buf, bufsz, flags); - if (rv > 0) { - /* successfully read bytes from the socket */ - buf = (char *)buf + rv; - bufsz -= rv; - } else if (rv < 0) { - int err = WSAGetLastError(); - if (err != WSAEWOULDBLOCK) { - /* an error occurred that wasn't "nothing to read". */ - return MQTT_ERROR_SOCKET_ERROR; - } - } - } while (rv > 0 && bufsz > 0); - - return (ssize_t)((char *)buf - start); -} - -#else - -#error No PAL! - -#endif - -#endif /* defined(MQTT_USE_CUSTOM_SOCKET_HANDLE) */ - -/** @endcond */ diff --git a/client/deps/mqtt/mqtt_pal.h b/client/deps/mqtt/mqtt_pal.h deleted file mode 100644 index 87b84500b..000000000 --- a/client/deps/mqtt/mqtt_pal.h +++ /dev/null @@ -1,173 +0,0 @@ -#if !defined(__MQTT_PAL_H__) -#define __MQTT_PAL_H__ - -/* -MIT License - -Copyright(c) 2018 Liam Bindle - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#if defined(__cplusplus) -extern "C" { -#endif - -/** - * @file - * @brief Includes/supports the types/calls required by the MQTT-C client. - * - * @note This is the \em only file included in mqtt.h, and mqtt.c. It is therefore - * responsible for including/supporting all the required types and calls. - * - * @defgroup pal Platform abstraction layer - * @brief Documentation of the types and calls required to port MQTT-C to a new platform. - * - * mqtt_pal.h is the \em only header file included in mqtt.c. Therefore, to port MQTT-C to a - * new platform the following types, functions, constants, and macros must be defined in - * mqtt_pal.h: - * - Types: - * - \c size_t, \c ssize_t - * - \c uint8_t, \c uint16_t, \c uint32_t - * - \c va_list - * - \c mqtt_pal_time_t : return type of \c MQTT_PAL_TIME() - * - \c mqtt_pal_mutex_t : type of the argument that is passed to \c MQTT_PAL_MUTEX_LOCK and - * \c MQTT_PAL_MUTEX_RELEASE - * - Functions: - * - \c memcpy, \c strlen - * - \c va_start, \c va_arg, \c va_end - * - Constants: - * - \c INT_MIN - * - * Additionally, three macro's are required: - * - \c MQTT_PAL_HTONS(s) : host-to-network endian conversion for uint16_t. - * - \c MQTT_PAL_NTOHS(s) : network-to-host endian conversion for uint16_t. - * - \c MQTT_PAL_TIME() : returns [type: \c mqtt_pal_time_t] current time in seconds. - * - \c MQTT_PAL_MUTEX_LOCK(mtx_pointer) : macro that locks the mutex pointed to by \c mtx_pointer. - * - \c MQTT_PAL_MUTEX_RELEASE(mtx_pointer) : macro that unlocks the mutex pointed to by - * \c mtx_pointer. - * - * Lastly, \ref mqtt_pal_sendall and \ref mqtt_pal_recvall, must be implemented in mqtt_pal.c - * for sending and receiving data using the platforms socket calls. - */ - - -/* UNIX-like platform support */ -#if defined(__unix__) || defined(__APPLE__) || defined(__NuttX__) -#include -#include -#include -#include -#include -#include - -#define MQTT_PAL_HTONS(s) htons(s) -#define MQTT_PAL_NTOHS(s) ntohs(s) - -#define MQTT_PAL_TIME() time(NULL) - -typedef time_t mqtt_pal_time_t; -typedef pthread_mutex_t mqtt_pal_mutex_t; - -#define MQTT_PAL_MUTEX_INIT(mtx_ptr) pthread_mutex_init(mtx_ptr, NULL) -#define MQTT_PAL_MUTEX_LOCK(mtx_ptr) pthread_mutex_lock(mtx_ptr) -#define MQTT_PAL_MUTEX_UNLOCK(mtx_ptr) pthread_mutex_unlock(mtx_ptr) - -#if !defined(MQTT_USE_CUSTOM_SOCKET_HANDLE) -#if defined(MQTT_USE_MBEDTLS) -struct mbedtls_ssl_context; -typedef struct mbedtls_ssl_context *mqtt_pal_socket_handle; -#else -typedef int mqtt_pal_socket_handle; -#endif -#endif - -#elif defined(_MSC_VER) || defined(WIN32) -#include -#include -#include -#include -#include - -typedef SSIZE_T ssize_t; -#define MQTT_PAL_HTONS(s) htons(s) -#define MQTT_PAL_NTOHS(s) ntohs(s) - -#define MQTT_PAL_TIME() time(NULL) - -typedef time_t mqtt_pal_time_t; -typedef CRITICAL_SECTION mqtt_pal_mutex_t; - -#define MQTT_PAL_MUTEX_INIT(mtx_ptr) InitializeCriticalSection(mtx_ptr) -#define MQTT_PAL_MUTEX_LOCK(mtx_ptr) EnterCriticalSection(mtx_ptr) -#define MQTT_PAL_MUTEX_UNLOCK(mtx_ptr) LeaveCriticalSection(mtx_ptr) - - -#if !defined(MQTT_USE_CUSTOM_SOCKET_HANDLE) -typedef SOCKET mqtt_pal_socket_handle; -#endif - -#endif - -/** - * @brief Sends all the bytes in a buffer. - * @ingroup pal - * - * @param[in] fd The file-descriptor (or handle) of the socket. - * @param[in] buf A pointer to the first byte in the buffer to send. - * @param[in] len The number of bytes to send (starting at \p buf). - * @param[in] flags Flags which are passed to the underlying socket. - * - * @returns The number of bytes sent if successful, an \ref MQTTErrors otherwise. - * - * Note about the error handling: - * - On an error, if some bytes have been processed already, - * this function should return the number of bytes successfully - * processed. (partial success) - * - Otherwise, if the error is an equivalent of EAGAIN, return 0. - * - Otherwise, return MQTT_ERROR_SOCKET_ERROR. - */ -ssize_t mqtt_pal_sendall(mqtt_pal_socket_handle fd, const void *buf, size_t len, int flags); - -/** - * @brief Non-blocking receive all the byte available. - * @ingroup pal - * - * @param[in] fd The file-descriptor (or handle) of the socket. - * @param[in] buf A pointer to the receive buffer. - * @param[in] bufsz The max number of bytes that can be put into \p buf. - * @param[in] flags Flags which are passed to the underlying socket. - * - * @returns The number of bytes received if successful, an \ref MQTTErrors otherwise. - * - * Note about the error handling: - * - On an error, if some bytes have been processed already, - * this function should return the number of bytes successfully - * processed. (partial success) - * - Otherwise, if the error is an equivalent of EAGAIN, return 0. - * - Otherwise, return MQTT_ERROR_SOCKET_ERROR. - */ -ssize_t mqtt_pal_recvall(mqtt_pal_socket_handle fd, void *buf, size_t bufsz, int flags); - -#if defined(__cplusplus) -} -#endif - - -#endif diff --git a/client/deps/mqtt/posix_sockets.h b/client/deps/mqtt/posix_sockets.h deleted file mode 100644 index 42954f640..000000000 --- a/client/deps/mqtt/posix_sockets.h +++ /dev/null @@ -1,73 +0,0 @@ -#if !defined(__POSIX_SOCKET_TEMPLATE_H__) -#define __POSIX_SOCKET_TEMPLATE_H__ - -#ifndef _WIN32 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// A template for opening a non-blocking POSIX socket. - -void close_nb_socket(int sockfd); -int open_nb_socket(const char *addr, const char *port); - -int open_nb_socket(const char *addr, const char *port) { - - struct addrinfo hints; - memset(&hints, 0, sizeof(hints)); - - hints.ai_family = AF_UNSPEC; /* IPv4 or IPv6 */ - hints.ai_socktype = SOCK_STREAM; /* Must be TCP */ - - struct addrinfo *p, *servinfo; - - /* get address information */ - int rv = getaddrinfo(addr, port, &hints, &servinfo); - if (rv != 0) { - fprintf(stderr, "Failed to open socket (getaddrinfo): %s\n", gai_strerror(rv)); - return -1; - } - - /* open the first possible socket */ - int sockfd = -1; - for (p = servinfo; p != NULL; p = p->ai_next) { - sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); - if (sockfd == -1) { - continue; - } - - /* connect to server */ - rv = connect(sockfd, p->ai_addr, p->ai_addrlen); - if (rv == -1) { - close(sockfd); - sockfd = -1; - continue; - } - break; - } - - // free servinfo - freeaddrinfo(servinfo); - - // make non-blocking - if (sockfd != -1) { - fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); - } - - return sockfd; -} - -void close_nb_socket(int sockfd) { - if (sockfd != -1) { - close(sockfd); - } -} -#endif -#endif diff --git a/client/deps/mqtt/readme.md b/client/deps/mqtt/readme.md deleted file mode 100644 index c7e437b7e..000000000 --- a/client/deps/mqtt/readme.md +++ /dev/null @@ -1,15 +0,0 @@ - -# Information -Source: https://github.com/LiamBindle/MQTT-C -License: MIT -Authors: - -MQTT-C was initially developed as a CMPT 434 (Winter Term, 2018) final project at the University of Saskatchewan by: - - - Liam Bindle - - Demilade Adeoye - - -# about -MQTT-C is an MQTT v3.1.1 client written in C. MQTT is a lightweight publisher-subscriber-based messaging protocol that is commonly used in IoT and networking applications where high-latency and low data-rate links are expected. The purpose of MQTT-C is to provide a portable MQTT client, written in C, for embedded systems and PC's alike. MQTT-C does this by providing a transparent Platform Abstraction Layer (PAL) which makes porting to new platforms easy. MQTT-C is completely thread-safe but can also run perfectly fine on single-threaded systems making MQTT-C well-suited for embedded systems and microcontrollers. Finally, MQTT-C is small; there are only two source files totalling less than 2000 lines. - diff --git a/client/deps/mqtt/win32_sockets.h b/client/deps/mqtt/win32_sockets.h deleted file mode 100644 index 4775bb851..000000000 --- a/client/deps/mqtt/win32_sockets.h +++ /dev/null @@ -1,92 +0,0 @@ -#if !defined(__WIN32_SOCKET_TEMPLATE_H__) -#define __WIN32_SOCKET_TEMPLATE_H__ - -#include -#include - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#include -#include - -void close_nb_socket(mqtt_pal_socket_handle sockfd); -mqtt_pal_socket_handle open_nb_socket(const char *addr, const char *port); - -mqtt_pal_socket_handle open_nb_socket(const char *addr, const char *port) { - - WSADATA wsaData; - int res = WSAStartup(MAKEWORD(2, 2), &wsaData); - if (res != 0) { - fprintf(stderr, "error: WSAStartup failed with error: %i", res); - return INVALID_SOCKET; - } - - struct addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; // IPv4 or IPv6 - hints.ai_socktype = SOCK_STREAM; // Must be TCP - hints.ai_protocol = IPPROTO_TCP; // - - struct addrinfo *p, *servinfo; - // get address information - int rv = getaddrinfo(addr, port, &hints, &servinfo); - if (rv != 0) { - fprintf(stderr, "error: getaddrinfo: %s", gai_strerror(rv)); - WSACleanup(); - return INVALID_SOCKET; - } - - /* open the first possible socket */ - SOCKET hSocket = INVALID_SOCKET; - for (p = servinfo; p != NULL; p = p->ai_next) { - hSocket = socket(p->ai_family, p->ai_socktype, p->ai_protocol); - - if (hSocket == INVALID_SOCKET) { - continue; - } - - // connect to server - if (connect(hSocket, p->ai_addr, (int)p->ai_addrlen) != INVALID_SOCKET) { - break; - } - - closesocket(hSocket); - hSocket = INVALID_SOCKET; - - } - - // free servinfo - freeaddrinfo(servinfo); - - if (p == NULL) { // No address succeeded - fprintf(stderr, "error: Could not connect"); - WSACleanup(); - return INVALID_SOCKET; - } - - // make non-blocking - if (hSocket != INVALID_SOCKET) { - u_long mode = 1; // FIONBIO returns size on 32b - ioctlsocket(hSocket, FIONBIO, &mode); - } - - int flag = 1; - res = setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag)); - if (res != 0) { - closesocket(hSocket); - WSACleanup(); - return INVALID_SOCKET; - } - - return hSocket; -} - -void close_nb_socket(mqtt_pal_socket_handle sockfd) { - if (sockfd != INVALID_SOCKET) { - closesocket(sockfd); - } -} -#endif - -#endif 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/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index d6db9392b..465431dd8 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -2542,7 +2542,7 @@ FAB943906E9C # R.A.T.T transport card key A/B AA034F342A55 456776908C48 -# + # BusFacil - Brazilian public transport card for some cities fae9b14365a9 c567dd4a6004 @@ -3108,32 +3108,6 @@ AB921CF0752C 567D734C403C 2426217B3B3B # -# German Aral Gas Station Car-Wash cards -080507020706 -0100815D8D00 -2459514AED5B -5D493F6B0352 -1CEC0F0ACC0E -922B5D1BF2BC -2D7E76C7B8EC -5E59896806FF -097EEA4FE51B -688FC86BAB79 -C01D1DBEEE79 -2529BF8544C2 -C6052FBAA150 -A1D7B3A95605 -00D0BF748E77 -C082C0F35CE6 -3C86C78541A7 -5632DCC517E1 -9310191C338F -2761858C02D7 -8C64B49C7638 -B1BA3E778930 -2037627D9260 -28C4D7170FCD -# # Card keys from Andalusian public transport system (Consorcio de Transportes) 1848A8D1E4C5 16EE1FE134E4 diff --git a/client/dictionaries/mfdes_default_keys.dic b/client/dictionaries/mfdes_default_keys.dic index 3b4e1dc28..782fc65bb 100644 --- a/client/dictionaries/mfdes_default_keys.dic +++ b/client/dictionaries/mfdes_default_keys.dic @@ -9,7 +9,6 @@ d3f7d3f7d3f7d3f7 000000000000000000000000000000000000000000000000 #NXP Default 3K3DES 00112233445566778899AABBCCDDEEFF0102030405060708 ffffffffffffffffffffffffffffffffffffffffffffffff -d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 425245414B4D454946594F5543414E21 # default UL-C key 00112233445566778899AABBCCDDEEFF #TI TRF7970A sloa213 79702553797025537970255379702553 #TI TRF7970A sloa213 diff --git a/client/experimental_lib/CMakeLists.txt b/client/experimental_lib/CMakeLists.txt index 7d0c952b1..6d4a9d9c8 100644 --- a/client/experimental_lib/CMakeLists.txt +++ b/client/experimental_lib/CMakeLists.txt @@ -434,7 +434,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 || ${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 ) diff --git a/client/luascripts/hf_mf_keycheck.lua b/client/luascripts/hf_mf_keycheck.lua index 53a003ebc..29eb46072 100644 --- a/client/luascripts/hf_mf_keycheck.lua +++ b/client/luascripts/hf_mf_keycheck.lua @@ -216,7 +216,7 @@ local function perform_check(uid, numsectors) for sector = 0, #keys do -- Check if user aborted if core.kbd_enter_pressed() then - print('Aborted via keyboard!') + print('Aborted by user') break end diff --git a/client/luascripts/kybercrystals.lua b/client/luascripts/kybercrystals.lua index 1b707768b..70306842b 100644 --- a/client/luascripts/kybercrystals.lua +++ b/client/luascripts/kybercrystals.lua @@ -2,7 +2,7 @@ Simple script to program DIY kyber crystals works on real kyber crystals and EM4305 2.12x12mm chips simply run the program and select a profile via a number - + issues if you are getting errors when trying to read or write a chip run the cmd "lf tune" with no chip on the device, then move the chip over the coils till you see the lowest voltage. try different angles and in the center and or the edge of the antenna ring. @@ -10,7 +10,7 @@ if thats still not working run "lf tune" again and put the chip in the best position like before the total voltage may be too high to reduce it slowly lower tin foil over the antenna and watch the voltage. the foil should be a bit bigger than the coil exact size does not matter. - + data pulled from here https://docs.google.com/spreadsheets/d/13P_GE6tNYpGvoVUTEQvA3SQzMqpZ-SoiWaTNoJoTV9Q/edit?usp=sharing --]] @@ -663,12 +663,12 @@ function get_profile_data(profile_name) [9] = "010D0000" } } - + -- When called without arguments, return the whole table if not profile_name then return profiles end - + -- Otherwise return the specific profile or wipe chip return profiles[profile_name] or profiles["wipe chip"] end @@ -676,7 +676,7 @@ end function get_profile_names() -- Get the complete profiles table from get_profile_data local all_profiles = get_profile_data() - + local names = {} for name, _ in pairs(all_profiles) do table.insert(names, name) @@ -687,16 +687,16 @@ end function select_profile() local profile_names = get_profile_names() - + print("\nAvailable profiles:") for i, name in ipairs(profile_names) do print(string.format("%d. %s", i, name)) end - + while true do io.write("\nSelect profile (1-" .. #profile_names .. "): ") local choice = tonumber(io.read()) - + if choice and choice >= 1 and choice <= #profile_names then return profile_names[choice] else @@ -707,40 +707,40 @@ end function main() print("\n[=== kyber crystal programmer ===]") - + -- Get profile from command line argument or prompt user local profile_name = args and args[1] if not profile_name then --print("\nNo profile specified as argument.") profile_name = select_profile() end - + local data_to_write = get_profile_data(profile_name) print("\n[+] Using profile: " .. profile_name) - + -- Display what will be written print("\n[+] Data to be written:") for addr, data in pairs(data_to_write) do print(string.format("Address %d: %s", addr, data)) end - + -- Step 1: Wipe the tag print("\n[+] Wiping tag...") send_command("lf em 4x05 wipe --4305") - + -- Step 2: Write data print("\n[+] Writing data...") for addr, data in pairs(data_to_write) do send_command("lf em 4x05 write -a " .. addr .. " -d " .. data) utils.Sleep(0.5) end - + -- Step 3: Read back and display data for verification print("\n[+] Verifying writes by reading back data...") for addr, expected_data in pairs(data_to_write) do local output = send_command("lf em 4x05 read -a " .. addr) end - + print("\n[+] Read complete. Review output above.") end diff --git a/client/luascripts/lf_awid_bulkclone.lua b/client/luascripts/lf_awid_bulkclone.lua index 3fa145ec2..63394aa99 100644 --- a/client/luascripts/lf_awid_bulkclone.lua +++ b/client/luascripts/lf_awid_bulkclone.lua @@ -10,7 +10,7 @@ For more info, check the comments in the code ]] example = [[ -- - script run lf_awid_bulkclone.lua -f 1 -b 1000 + script run lf_awid_bulkclone.lua -f 1 -b 1000 ]] usage = [[ script run lf_awid_bulkclone.lua -f facility -b base_id_num @@ -91,7 +91,7 @@ local function main(args) end end if o == 'b' then - if isempty(a) then + if isempty(a) then print('You did not supply a starting card number, using 59615') cn = 59615 else @@ -105,18 +105,18 @@ local function main(args) print("Session Start: " .. sessionStart) print("Facility Code,Card Number") - + while true do print(string.format("Preparing to Write: Facility Code %d, Card Number %d", fc, cn)) - + local command = string.format("lf awid clone --fmt 26 --fc %d --cn %d", fc, cn) core.console(command) - + print(string.format("%d,%d", fc, cn)) - + print("Press Enter to continue with the next card number or type 'q' and press Enter to quit.") local user_input = io.read() - + if user_input:lower() == 'q' then break else diff --git a/client/luascripts/lf_electra.lua b/client/luascripts/lf_electra.lua index 2c130ba7a..5b0886aa4 100644 --- a/client/luascripts/lf_electra.lua +++ b/client/luascripts/lf_electra.lua @@ -145,7 +145,7 @@ local function readfile() local f = io.open(ID_STATUS, "r") for line in f:lines() do id = line:match"^(%x+)" - if id then break end + if id then break end end f:close() if not id then @@ -299,7 +299,7 @@ local function main(args) if answer == 'n' then core.console('clear') print( string.rep('--',39) ) - print(ac.red..' Aborted via keyboard!'..ac.reset) + print(ac.red..' USER ABORTED'..ac.reset) print( string.rep('--',39) ) break end diff --git a/client/luascripts/lf_em4100_bulk.lua b/client/luascripts/lf_em4100_bulk.lua index 8a2ff399e..87d8bc91b 100644 --- a/client/luascripts/lf_em4100_bulk.lua +++ b/client/luascripts/lf_em4100_bulk.lua @@ -198,7 +198,7 @@ local function main(args) core.console('lf em 410x reader') end else - print(ac.red..'aborted via keyboard!'..ac.reset) + print(ac.red..'User aborted'..ac.reset) low = i break end diff --git a/client/luascripts/lf_hid_bulkclone_v2.lua b/client/luascripts/lf_hid_bulkclone_v2.lua index 50762e8f1..31615d19d 100644 --- a/client/luascripts/lf_hid_bulkclone_v2.lua +++ b/client/luascripts/lf_hid_bulkclone_v2.lua @@ -14,7 +14,7 @@ example = [[ script run lf_hid_bulkclone_v2.lua -f 1 -b 1000 ]] usage = [[ -script run lf_hid_bulkclone_v2.lua -f facility -b base_id_num +script run lf_hid_bulkclone_v2.lua -f facility -b base_id_num ]] arguments = [[ -h : this help @@ -67,7 +67,7 @@ local function exitMsg(msg) end local function main(args) - + print( string.rep('--',20) ) print( string.rep('--',20) ) print() @@ -107,7 +107,7 @@ local function main(args) print("Press Enter to write the next card, type 'r' and press Enter to retry, or type 'q' and press Enter to quit.") local user_input = io.read() - + if user_input:lower() == 'q' then print("Timestamp: ", timestamp) print("Successful Writes:") diff --git a/client/luascripts/lf_ioprox_bulkclone.lua b/client/luascripts/lf_ioprox_bulkclone.lua index 31fb91e76..37e9c4ce9 100644 --- a/client/luascripts/lf_ioprox_bulkclone.lua +++ b/client/luascripts/lf_ioprox_bulkclone.lua @@ -69,7 +69,7 @@ local function exitMsg(msg) end local function main(args) - + print( string.rep('--',20) ) print( string.rep('--',20) ) print() diff --git a/client/luascripts/lf_t55xx_fix.lua b/client/luascripts/lf_t55xx_fix.lua index b793cf629..cfdffc8f0 100644 --- a/client/luascripts/lf_t55xx_fix.lua +++ b/client/luascripts/lf_t55xx_fix.lua @@ -18,7 +18,7 @@ desc = [[ is found, it uses the wipe command to erase the T5577. Then the reanimation procedure is applied. If the password is not found or doesn't exist the script only performs the reanimation procedure. The script revives 99% of blocked tags. - ]] +]] usage = [[ script run lf_t55xx_fix ]] @@ -87,7 +87,7 @@ local function reanimate_t5577(password) p:console('lf t55 wipe -p ' .. password) print("T5577 wiped using a password: " ..ac.green.. password ..ac.reset) else - print(ac.yellow.." No valid password found, proceeding with reanimation."..ac.reset) + print(ac.yellow.."No valid password found, proceeding with reanimation."..ac.reset) end p:console('lf t55 write -b 0 -d 000880E8 -p 00000000') diff --git a/client/luascripts/paxton_clone.lua b/client/luascripts/paxton_clone.lua index 5e9076c9f..b8aaf2a9d 100644 --- a/client/luascripts/paxton_clone.lua +++ b/client/luascripts/paxton_clone.lua @@ -4,16 +4,7 @@ local ac = require('ansicolors') local os = require('os') local dash = string.rep('--', 32) local dir = os.getenv('HOME') .. '/.proxmark3/logs/' -local logfilecmd - ---Determine platform for logfile handling (Windows vs Unix/Linux) -if package.config:sub(1,1) == "\\" then - logfilecmd = 'dir /a-d /o-d /tw /b/s "' .. dir .. '" 2>nul:' -else - logfilecmd = 'find "' .. dir .. '" -type f -printf "%T@ %p\\n" | sort -nr | cut -d" " -f2-' -end - -local logfile = (io.popen(logfilecmd):read("*a"):match("%C+")) +local logfile = (io.popen('dir /a-d /o-d /tw /b/s "' .. dir .. '" 2>nul:'):read("*a"):match("%C+")) local log_file_path = dir .. "Paxton_log.txt" local nam = "" local pm3 = require('pm3') diff --git a/client/pyscripts/fm11rf08s_recovery.py b/client/pyscripts/fm11rf08s_recovery.py index 8b7eaffd8..cbb7246d5 100755 --- a/client/pyscripts/fm11rf08s_recovery.py +++ b/client/pyscripts/fm11rf08s_recovery.py @@ -216,7 +216,7 @@ def recovery(init_check=False, final_check=False, keep=False, no_oob=False, with open(dict_path, 'r', encoding='utf-8') as file: for line in file: if line[0] != '#' and len(line) >= 12: - DEFAULT_KEYS.add(line[:12].lower()) + DEFAULT_KEYS.add(line[:12]) show(f"Loaded {dict_def}") except FileNotFoundError: show(f"Warning, {dict_def} not found.") @@ -226,7 +226,6 @@ def recovery(init_check=False, final_check=False, keep=False, no_oob=False, dict_dnwd = None def_nt = ["" for _ in range(NUM_SECTORS)] if supply_chain: - default_nonces = '' try: default_nonces = f'{save_path}hf-mf-{uid:04X}-default_nonces.json' with open(default_nonces, 'r') as file: @@ -585,6 +584,8 @@ def recovery(init_check=False, final_check=False, keep=False, no_oob=False, if "Found keys have been dumped to" in line: keyfile = line[line.index("`"):].strip("`") else: + show() + show(color("found keys:", fg="green"), prompt=plus) show(prompt=plus) show("-----+-----+--------------+---+--------------+----", prompt=plus) show(" Sec | Blk | key A |res| key B |res", prompt=plus) diff --git a/client/pyscripts/intertic.py b/client/pyscripts/intertic.py index 6ccfaee2b..34a02800c 100644 --- a/client/pyscripts/intertic.py +++ b/client/pyscripts/intertic.py @@ -305,9 +305,6 @@ FRA_OrganizationalAuthority_Contract_Provider = { 0x021: { 1: InterticHelper('Bordeaux', 'TBM / Keolis', Describe_Usage_1_1), }, - 0x040: { - 28: InterticHelper('Colmar', 'Trace / Keolis', Describe_Usage_1_1), - }, 0x057: { 1: InterticHelper('Lyon', 'TCL / Keolis', Describe_Usage_1), # Strange usage ?, kept on generic 1 }, @@ -338,7 +335,6 @@ FRA_OrganizationalAuthority_Contract_Provider = { }, 0x912: { 3: InterticHelper('Le Havre', 'Lia / Transdev', Describe_Usage_1_1), - 29: InterticHelper('Caen', 'Twisto / RATP', Describe_Usage_2), 35: InterticHelper('Cherbourg-en-Cotentin', 'Cap Cotentin / Transdev'), }, 0x913: { diff --git a/client/resources/aid_desfire.json b/client/resources/aid_desfire.json index df68b254e..cd0b4fbc5 100644 --- a/client/resources/aid_desfire.json +++ b/client/resources/aid_desfire.json @@ -36,7 +36,7 @@ "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", "Country": "NZ", "Name": "Gallagher Security Credential", - "Description": "Cardax Card Data Application", + "Description": "Cardax Card Data Application (Alternative Endian)", "Type": "pacs" }, { @@ -44,7 +44,7 @@ "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", "Country": "NZ", "Name": "Gallagher Security Credential", - "Description": "Cardax Card Data Application", + "Description": "Cardax Card Data Application (Alternative Endian)", "Type": "pacs" }, { @@ -52,7 +52,7 @@ "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", "Country": "NZ", "Name": "Gallagher Security Credential", - "Description": "Cardax Card Data Application", + "Description": "Cardax Card Data Application (Alternative Endian)", "Type": "pacs" }, { @@ -60,7 +60,7 @@ "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", "Country": "NZ", "Name": "Gallagher Security Credential", - "Description": "Cardax Card Data Application", + "Description": "Cardax Card Data Application (Alternative Endian)", "Type": "pacs" }, { @@ -68,7 +68,7 @@ "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", "Country": "NZ", "Name": "Gallagher Security Credential", - "Description": "Cardax Card Data Application", + "Description": "Cardax Card Data Application (Alternative Endian)", "Type": "pacs" }, { @@ -76,7 +76,7 @@ "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", "Country": "NZ", "Name": "Gallagher Security Credential", - "Description": "Cardax Card Data Application", + "Description": "Cardax Card Data Application (Alternative Endian)", "Type": "pacs" }, { @@ -84,7 +84,7 @@ "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", "Country": "NZ", "Name": "Gallagher Security Credential", - "Description": "Cardax Card Data Application", + "Description": "Cardax Card Data Application (Alternative Endian)", "Type": "pacs" }, { @@ -92,7 +92,7 @@ "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", "Country": "NZ", "Name": "Gallagher Security Credential", - "Description": "Cardax Card Data Application", + "Description": "Cardax Card Data Application (Alternative Endian)", "Type": "pacs" }, { @@ -100,7 +100,7 @@ "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", "Country": "NZ", "Name": "Gallagher Security Credential", - "Description": "Cardax Card Data Application", + "Description": "Cardax Card Data Application (Alternative Endian)", "Type": "pacs" }, { @@ -108,7 +108,7 @@ "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", "Country": "NZ", "Name": "Gallagher Security Credential", - "Description": "Cardax Card Data Application", + "Description": "Cardax Card Data Application (Alternative Endian)", "Type": "pacs" }, { @@ -116,7 +116,7 @@ "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", "Country": "NZ", "Name": "Gallagher Security Credential", - "Description": "Cardax Card Data Application", + "Description": "Cardax Card Data Application (Alternative Endian)", "Type": "pacs" }, { @@ -124,7 +124,7 @@ "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", "Country": "NZ", "Name": "Gallagher Security Credential", - "Description": "Cardax Card Data Application", + "Description": "Cardax Card Data Application (Alternative Endian)", "Type": "pacs" }, { @@ -132,7 +132,7 @@ "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", "Country": "NZ", "Name": "Gallagher Security Credential", - "Description": "Unused Cardax Card Data Application", + "Description": "Unused Cardax Card Data Application (Alternative Endian)", "Type": "pacs" }, { @@ -140,7 +140,7 @@ "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", "Country": "NZ", "Name": "Gallagher Security Credential", - "Description": "Unused Cardax Card Data Application", + "Description": "Unused Cardax Card Data Application (Alternative Endian)", "Type": "pacs" }, { @@ -148,7 +148,7 @@ "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", "Country": "NZ", "Name": "Gallagher Security Credential", - "Description": "Unused Cardax Card Data Application", + "Description": "Unused Cardax Card Data Application (Alternative Endian)", "Type": "pacs" }, { @@ -156,7 +156,7 @@ "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", "Country": "NZ", "Name": "Gallagher Security Credential", - "Description": "Card Application Directory (CAD)", + "Description": "Card Application Directory (CAD) (Alternative Endian)", "Type": "pacs" }, { @@ -223,6 +223,134 @@ "Description": "Securitron DESFire EV2 Credential", "Type": "pacs" }, + { + "AID": "F48120", + "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", + "Country": "NZ", + "Name": "Gallagher Security Credential", + "Description": "Cardax Card Data Application", + "Type": "pacs" + }, + { + "AID": "F48121", + "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", + "Country": "NZ", + "Name": "Gallagher Security Credential", + "Description": "Cardax Card Data Application", + "Type": "pacs" + }, + { + "AID": "F48122", + "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", + "Country": "NZ", + "Name": "Gallagher Security Credential", + "Description": "Cardax Card Data Application", + "Type": "pacs" + }, + { + "AID": "F48123", + "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", + "Country": "NZ", + "Name": "Gallagher Security Credential", + "Description": "Cardax Card Data Application", + "Type": "pacs" + }, + { + "AID": "F48124", + "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", + "Country": "NZ", + "Name": "Gallagher Security Credential", + "Description": "Cardax Card Data Application", + "Type": "pacs" + }, + { + "AID": "F48125", + "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", + "Country": "NZ", + "Name": "Gallagher Security Credential", + "Description": "Cardax Card Data Application", + "Type": "pacs" + }, + { + "AID": "F48126", + "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", + "Country": "NZ", + "Name": "Gallagher Security Credential", + "Description": "Cardax Card Data Application", + "Type": "pacs" + }, + { + "AID": "F48127", + "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", + "Country": "NZ", + "Name": "Gallagher Security Credential", + "Description": "Cardax Card Data Application", + "Type": "pacs" + }, + { + "AID": "F48128", + "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", + "Country": "NZ", + "Name": "Gallagher Security Credential", + "Description": "Cardax Card Data Application", + "Type": "pacs" + }, + { + "AID": "F48129", + "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", + "Country": "NZ", + "Name": "Gallagher Security Credential", + "Description": "Cardax Card Data Application", + "Type": "pacs" + }, + { + "AID": "F4812A", + "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", + "Country": "NZ", + "Name": "Gallagher Security Credential", + "Description": "Cardax Card Data Application", + "Type": "pacs" + }, + { + "AID": "F4812B", + "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", + "Country": "NZ", + "Name": "Gallagher Security Credential", + "Description": "Cardax Card Data Application", + "Type": "pacs" + }, + { + "AID": "F4812C", + "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", + "Country": "NZ", + "Name": "Gallagher Security Credential", + "Description": "Unused Cardax Card Data Application", + "Type": "pacs" + }, + { + "AID": "F4812D", + "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", + "Country": "NZ", + "Name": "Gallagher Security Credential", + "Description": "Unused Cardax Card Data Application", + "Type": "pacs" + }, + { + "AID": "F4812E", + "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", + "Country": "NZ", + "Name": "Gallagher Security Credential", + "Description": "Unused Cardax Card Data Application", + "Type": "pacs" + }, + { + "AID": "F4812F", + "Vendor": "Gallagher Group Limited via PEC (New Zealand) Limited", + "Country": "NZ", + "Name": "Gallagher Security Credential", + "Description": "Card Application Directory (CAD)", + "Type": "pacs" + }, { "AID": "F484D1", "Vendor": "HID", @@ -767,14 +895,6 @@ "Description": "car2go - Member Card // Multi Functional Badge / Private Application #1", "Type": "carsharing" }, - { - "AID": "000001", - "Vendor": "Invalid / Reserved", - "Country": "", - "Name": "Invalid / Reserved", - "Description": "Used by ATL Breeze, PHL FREEDOM, and YVR Compass", - "Type": "transport" - }, { "AID": "000005", "Vendor": "Transports Metropolitans de Barcelona (TMB)", @@ -783,6 +903,14 @@ "Description": "BCN T-mobilitat", "Type": "transport" }, + { + "AID": "000001", + "Vendor": "Invalid / Reserved", + "Country": "", + "Name": "Invalid / Reserved", + "Description": "Used by ATL Breeze, PHL FREEDOM, and YVR Compass", + "Type": "transport" + }, { "AID": "0000F0", "Vendor": "Metropolitan Transportation Authority (MTA) / Bayerische Motoren Werke (BMW) AG", @@ -793,7 +921,7 @@ }, { "AID": "002000", - "Vendor": "Metrolinx via Accenture", + "Vendor": "Metrolinx", "Country": "CA", "Name": "PRESTO Card (YYZ/YHM/YOW)", "Description": "FIDs 00,0F: Backup Data; 08-0E,10-14: Standard Data", @@ -1081,7 +1209,7 @@ }, { "AID": "415431", - "Vendor": "Athens Urban Transport Organisation (OASA)", + "Vendor": "Athens Urban Transport Organization (OASA)", "Country": "GR", "Name": "ATH.ENA CARD (ATH)", "Description": "ATH ATH.ENA CARD", @@ -1153,7 +1281,7 @@ }, { "AID": "4F5931", - "Vendor": "Transport for London (TfL) via Cubic Transportation Systems", + "Vendor": "Transport for London (TfL)", "Country": "UK", "Name": "Oyster Card (LHR)", "Description": "FIDs: 00-07: Standard Data", @@ -1169,7 +1297,7 @@ }, { "AID": "534531", - "Vendor": "Transport for New South Wales (TfNSW) via Pearl Consortium", + "Vendor": "Transport for New South Wales (TfNSW)", "Country": "AU", "Name": "Opal Card (SYD)", "Description": "FIDs 00-06: Standard Data; 07: Card Balance/Number and Trip History", @@ -1177,7 +1305,7 @@ }, { "AID": "554000", - "Vendor": "Auckland Transport via Thales Group", + "Vendor": "Auckland Transport", "Country": "NZ", "Name": "AT HOP Card (AKL)", "Description": "FIDs: 00: Backup Data; 08/09/0A", @@ -1263,14 +1391,6 @@ "Description": "Umo Mobility Card", "Type": "transport" }, - { - "AID": "C1B1A1", - "Vendor": "AHORROBUS via MOBILITY ADO", - "Country": "MX", - "Name": "AHORROBUS Card (MEX)", - "Description": "MEX AHORROBUS Card", - "Type": "transport" - }, { "AID": "C65B80", "Vendor": "Umo Mobility via Cubic Transportation Systems", @@ -1345,7 +1465,7 @@ }, { "AID": "F21050", - "Vendor": "Metro Christchurch via INIT / Arc via Vix Technologies", + "Vendor": "Metro Christchurch via INIT / Arc", "Country": "NZ / CA", "Name": "Metrocard (CHC) / Arc (YEG)", "Description": "CHC FIDs: 00: Backup Data; 01/02: Trip History; 03: Card Balance", @@ -1353,7 +1473,7 @@ }, { "AID": "F210E0", - "Vendor": "TriMet via INIT", + "Vendor": "TriMet", "Country": "US", "Name": "hop fastpass (PDX)", "Description": "PDX hop fastpass Card", @@ -1401,7 +1521,7 @@ }, { "AID": "F21201", - "Vendor": "Green Bay Metro Transit via Genfare / Winnipeg Transit via Genfare", + "Vendor": "Green Bay Metro Transit via Genfare / Winnipeg Transit", "Country": "US / CA", "Name": "Tap-N-Go Card (GRB) / peggo card (YWG)", "Description": "GRB Tap-N-Go Card / YWG peggo card", @@ -1417,7 +1537,7 @@ }, { "AID": "F212A0", - "Vendor": "CTtransit via Genfare", + "Vendor": "CTtransit", "Country": "US", "Name": "Go CT Card (BDL)", "Description": "BDL Go CT Card", @@ -1425,7 +1545,7 @@ }, { "AID": "F21360", - "Vendor": "The City and County of Honolulu via INIT", + "Vendor": "INIT", "Country": "US", "Name": "HOLO Card (HNL)", "Description": "HNL HOLO Card", @@ -1441,7 +1561,7 @@ }, { "AID": "F21390", - "Vendor": "Otago Regional Council via INIT", + "Vendor": "Multiple NZ Transit Agencies via Otago Regional Council", "Country": "NZ", "Name": "Bee Card (DUD)", "Description": "Multi-Modal Transit #0 // FIDs 00: Backup Data; 01-02: Trip History; 03: Card Balance", @@ -1463,14 +1583,6 @@ "Description": "One Regional Card for All // FIDs 00: Standard Data; 01: Backup Data", "Type": "transport" }, - { - "AID": "F21400", - "Vendor": "Spokane Transit Authority (STA) via INIT", - "Country": "US", - "Name": "Connect Card (GEG)", - "Description": "GEG Connect Card", - "Type": "transport" - }, { "AID": "F40110", "Vendor": "ITSO Ltd", @@ -1505,7 +1617,7 @@ }, { "AID": "FF30FF", - "Vendor": "Metrolinx via Accenture", + "Vendor": "Metrolinx", "Country": "CA", "Name": "PRESTO Card (YYZ/YHM/YOW)", "Description": "FID 08: Standard Data", diff --git a/client/resources/aidlist.json b/client/resources/aidlist.json index 53828dbc1..9b6d58317 100644 --- a/client/resources/aidlist.json +++ b/client/resources/aidlist.json @@ -1247,6 +1247,14 @@ "Description": "PIV End Point Applet. Last 2 bytes designate version", "Type": "" }, + { + "AID": "A000000308000010000100", + "Vendor": "National Institute of Standards and Technology", + "Country": "United States", + "Name": "Personal Identity Verification (PIV) / ID-ONE PIV BIO", + "Description": "PIV End Point Applet. Last 2 bytes designate version", + "Type": "" + }, { "AID": "A00000031510100528", "Vendor": "Currence Holding/PIN BV", @@ -2462,37 +2470,5 @@ "Name": "Navigo", "Description": "CALYPSO-based transit card", "Type": "transport" - }, - { - "AID": "A0000000791000", - "Vendor": "HID Global", - "Country": "", - "Name": "Crescendo ACA", - "Description": "HID Crescendo ACA", - "Type": "access" - }, - { - "AID": "A0000000792300", - "Vendor": "HID Global", - "Country": "", - "Name": "Crescendo OATH #0 (HOTP)", - "Description": "HID Crescendo Key OATH instance 0 (default HOTP slot)", - "Type": "access" - }, - { - "AID": "A0000000792301", - "Vendor": "HID Global", - "Country": "", - "Name": "Crescendo OATH #1", - "Description": "HID Crescendo Key OATH instance 1", - "Type": "access" - }, - { - "AID": "A0000000792302", - "Vendor": "HID Global", - "Country": "", - "Name": "Crescendo OATH #2", - "Description": "HID Crescendo Key OATH instance 2", - "Type": "access" } ] diff --git a/client/resources/iceman.txt b/client/resources/iceman.txt deleted file mode 100644 index ad58ac814..000000000 --- a/client/resources/iceman.txt +++ /dev/null @@ -1,8 +0,0 @@ -$$$$$$\ $$$$$$\ $$$$$$$$\ $$\ $$\ $$$$$$\ $$\ $$\  -\_$$ _|$$ __$$\ $$ _____|$$$\ $$$ |$$ __$$\ $$$\ $$ | - $$ | $$ / \__|$$ | $$$$\ $$$$ |$$ / $$ |$$$$\ $$ | - $$ | $$ | $$$$$\ $$\$$\$$ $$ |$$$$$$$$ |$$ $$\$$ | - $$ | $$ | $$ __| $$ \$$$ $$ |$$ __$$ |$$ \$$$$ | - $$ | $$ | $$\ $$ | $$ |\$ /$$ |$$ | $$ |$$ |\$$$ | -$$$$$$\ \$$$$$$ |$$$$$$$$\ $$ | \_/ $$ |$$ | $$ |$$ | \$$ | -\______| \______/ \________|\__| \__|\__| \__|\__| \__| \ No newline at end of file diff --git a/client/resources/mad.json b/client/resources/mad.json index 6b8465f55..66a592e44 100644 --- a/client/resources/mad.json +++ b/client/resources/mad.json @@ -4130,13 +4130,6 @@ "service_provider": "HID Corporation", "system_integrator": "HID Corporation" }, - { - "application": "Access Control (SIO Elite)", - "company": "HID Global", - "mad": "0x3D05", - "service_provider": "HID Corporation", - "system_integrator": "HID Corporation" - }, { "application": "City transport, prepaid ticket, cardholder, servicespass", "company": "Ridango AS", diff --git a/client/src/cmddata.c b/client/src/cmddata.c index df05e9084..a8e285b7f 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -3527,8 +3527,8 @@ static int CmdAtrLookup(const char *Cmd) { static int CmdCryptography(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data crypto", - "This command lets you encrypt or decrypt data using DES/3DES/AES.\n" - "Supply data, key, IV (needed for des MAC or aes), and cryptography action.\n", + "Encrypt data, right here, right now. Or decrypt.", + "Supply data, key, IV (needed for des MAC or aes), and cryptography action.\n" "To calculate a MAC for FMCOS, supply challenge as IV, data as data, and session/line protection key as key.\n" "To calculate a MAC for FeliCa, supply first RC as IV, BLE+data as data and session key as key.\n" "data crypto -d 04D6850E06AABB80 -k FFFFFFFFFFFFFFFF --iv 9EA0401A00000000 --des -> Calculate a MAC for FMCOS chip. The result should be ED3A0133\n" @@ -3544,97 +3544,76 @@ static int CmdCryptography(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); - uint8_t dati[250] = {0}; uint8_t dato[250] = {0}; int datilen = 0; CLIGetHexWithReturn(ctx, 1, dati, &datilen); - - uint8_t key[33] = {0}; + uint8_t key[25] = {0}; int keylen = 0; CLIGetHexWithReturn(ctx, 2, key, &keylen); - - uint8_t type = 0; - if (arg_get_lit(ctx, 3)) { - type ^= 0x08; - } - - if (arg_get_lit(ctx, 4)) { - type ^= 0x04; - } - - if (arg_get_lit(ctx, 5)) { - type ^= 0x02; - } - + int type = 0; + if (arg_get_lit(ctx, 3)) type ^= 8; + if (arg_get_lit(ctx, 4)) type ^= 4; + if (arg_get_lit(ctx, 5)) type ^= 2; uint8_t iv[250] = {0}; int ivlen = 0; CLIGetHexWithReturn(ctx, 6, iv, &ivlen); CLIParserFree(ctx); // Do data length check - if ((type & 0x04) == 0x04) { // Use AES(0) or DES(1)? + if ((type & 0x4) >> 2) { // Use AES(0) or DES(1)? if (datilen % 8 != 0) { PrintAndLogEx(ERR, " length must be a multiple of 8. Got %d", datilen); return PM3_EINVARG; } - if (keylen != 8 && keylen != 16 && keylen != 24 && keylen != 32) { - PrintAndLogEx(ERR, " must be 8, 16, 24, 32 bytes. Got %d", keylen); + if (keylen != 8 && keylen != 16 && keylen != 24) { + PrintAndLogEx(ERR, " must be 8, 16 or 24 bytes. Got %d", keylen); return PM3_EINVARG; } } else { - if (datilen % 16 != 0 && ((type & 0x02) == 0)) { + if (datilen % 16 != 0 && ((type & 0x2) >> 1 == 0)) { PrintAndLogEx(ERR, " length must be a multiple of 16. Got %d", datilen); return PM3_EINVARG; } - if (keylen != 16 && keylen != 32) { - PrintAndLogEx(ERR, " must be 16 or 32 bytes. Got %d", keylen); + if (keylen != 16) { + PrintAndLogEx(ERR, " must be 16 bytes. Got %d", keylen); return PM3_EINVARG; } } // Encrypt(0) or decrypt(1)? - if ((type & 0x08) == 0x08) { + if ((type & 0x8) >> 3) { - if ((type & 0x04) == 0x04) { // AES or DES? + if ((type & 0x4) >> 2) { // AES or DES? if (keylen > 8) { + PrintAndLogEx(INFO, "Called 3DES decrypt"); des3_decrypt(dato, dati, key, keylen / 8); - PrintAndLogEx(INFO, "3DES decrypt... " _YELLOW_("%s"), sprint_hex_inrow(dato, datilen)); } else { - + PrintAndLogEx(INFO, "Called DES decrypt"); if (ivlen == 0) { // If there's an IV, use CBC des_decrypt_ecb(dato, dati, datilen, key); - PrintAndLogEx(INFO, "DES ECB decrypt... " _YELLOW_("%s"), sprint_hex_inrow(dato, datilen)); } else { des_decrypt_cbc(dato, dati, datilen, key, iv); - PrintAndLogEx(INFO, "DES CBC decrypt... " _YELLOW_("%s"), sprint_hex_inrow(dato, datilen)); } } - } else { - if (keylen == 32) { - aes256_decode(iv, key, dati, dato, datilen); - PrintAndLogEx(INFO, "AES-256 decrypt... " _YELLOW_("%s"), sprint_hex_inrow(dato, datilen)); - } else { - aes_decode(iv, key, dati, dato, datilen); - PrintAndLogEx(INFO, "AES-128 decrypt... " _YELLOW_("%s"), sprint_hex_inrow(dato, datilen)); - } + PrintAndLogEx(INFO, "Called AES decrypt"); + aes_decode(iv, key, dati, dato, datilen); } } else { - - if ((type & 0x04) == 0x04) { // AES or DES? - if ((type & 0x02) == 0x02) { // If we will calculate a MAC + if (type & 0x4) { // AES or DES? + if (type & 0x02) { // If we will calculate a MAC /*PrintAndLogEx(INFO, "Called FeliCa MAC"); // For DES all I know useful is the felica and fudan MAC algorithm.This is just des-cbc, but felica needs it in its way. for (int i = 0; i < datilen; i+=8){ // For all 8 byte sequences @@ -3658,42 +3637,37 @@ static int CmdCryptography(const char *Cmd) { } else { if (keylen > 8) { + PrintAndLogEx(INFO, "Called 3DES encrypt keysize: %i", keylen / 8); des3_encrypt(dato, dati, key, keylen / 8); - PrintAndLogEx(INFO, "3DES encrypt keysize ( %d )... " _YELLOW_("%s"), (keylen / 8), sprint_hex_inrow(dato, datilen)); } else { + PrintAndLogEx(INFO, "Called DES encrypt"); + if (ivlen == 0) { // If there's an IV, use ECB des_encrypt_ecb(dato, dati, datilen, key); - PrintAndLogEx(INFO, "DES ECB encrypt... " _YELLOW_("%s"), sprint_hex_inrow(dato, datilen)); } else { des_encrypt_cbc(dato, dati, datilen, key, iv); char pad[250]; memset(pad, ' ', 4 + 8 + (datilen - 8) * 3); pad[8 + (datilen - 8) * 3] = 0; // Make a padding to insert FMCOS macing algorithm guide PrintAndLogEx(INFO, "%sVV VV VV VV FMCOS MAC", pad); - PrintAndLogEx(INFO, "DES CBC encrypt... " _YELLOW_("%s"), sprint_hex_inrow(dato, datilen)); } } } } else { - if ((type & 0x02) == 0x02) { + if (type & 0x02) { + PrintAndLogEx(INFO, "Called AES CMAC"); // If we will calculate a MAC aes_cmac8(iv, key, dati, dato, datilen); - PrintAndLogEx(INFO, "AES CMAC... " _YELLOW_("%s"), sprint_hex_inrow(dato, datilen)); } else { - if (keylen == 32) { - aes256_encode(iv, key, dati, dato, datilen); - PrintAndLogEx(INFO, "AES-256 encrypt... " _YELLOW_("%s"), sprint_hex_inrow(dato, datilen)); - } else { - aes_encode(iv, key, dati, dato, datilen); - PrintAndLogEx(INFO, "AES-128 encrypt... " _YELLOW_("%s"), sprint_hex_inrow(dato, datilen)); - } + PrintAndLogEx(INFO, "Called AES encrypt"); + aes_encode(iv, key, dati, dato, datilen); } } } - + PrintAndLogEx(SUCCESS, "Result: %s", sprint_hex(dato, datilen)); return PM3_SUCCESS; } diff --git a/client/src/cmddata.h b/client/src/cmddata.h index 5f70516ff..5b19b0f4e 100644 --- a/client/src/cmddata.h +++ b/client/src/cmddata.h @@ -67,6 +67,7 @@ int CmdLtrim(const char *Cmd); int CmdNorm(const char *Cmd); // used by cmd lf data (!) int CmdPlot(const char *Cmd); // used by cmd lf cotag int CmdSave(const char *Cmd); // used by cmd auto +int CmdTuneSamples(const char *Cmd); // used by cmd lf hw int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose); // used by cmd lf em4x, lf fdxb, lf guard, lf jablotron, lf nedap, lf t55xx int ASKDemod(int clk, int invert, int maxErr, size_t maxlen, bool amplify, bool verbose, bool emSearch, uint8_t askType); // used by cmd lf em4x, lf t55xx, lf viking diff --git a/client/src/cmdflashmem.c b/client/src/cmdflashmem.c index 607a36b31..fa88549f7 100644 --- a/client/src/cmdflashmem.c +++ b/client/src/cmdflashmem.c @@ -192,24 +192,21 @@ static int CmdFlashMemLoad(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "mem load", "Loads binary file into flash memory on device\n" - "Warning! - mem area to be written must have been wiped first\n\n" - "OBS! - dictionaries are serviced as files in spiffs so no wipe is needed", - "mem load -f myfile -> upload file myfile values at default offset 0\n" - "mem load -f myfile -o 1024 -> upload file myfile values at offset 1024\n" - "mem load -f mfc_default_keys -m -> upload MIFARE Classic keys\n" - "mem load -f t55xx_default_pwds -t -> upload T55XX passwords\n" - "mem load -f iclass_default_keys -i -> upload iCLASS keys\n" - "mem load -f mfulc_default_keys --ulc -> upload MIFARE UL-C keys\n" + "Warning: mem area to be written must have been wiped first\n" + "( dictionaries are serviced as files in spiffs so no wipe is needed )", + "mem load -f myfile -> upload file myfile values at default offset 0\n" + "mem load -f myfile -o 1024 -> upload file myfile values at offset 1024\n" + "mem load -f mfc_default_keys -m -> upload MFC keys\n" + "mem load -f t55xx_default_pwds -t -> upload T55XX passwords\n" + "mem load -f iclass_default_keys -i -> upload iCLASS keys\n" ); void *argtable[] = { arg_param_begin, arg_int0("o", "offset", "", "offset in memory"), - arg_lit0("m", "mfc", "upload 6 bytes keys (MIFARE Classic dictionary)"), - arg_lit0("i", "iclass", "upload 8 bytes keys (iClass dictionary)"), - arg_lit0("t", "t55xx", "upload 4 bytes keys (T55xx dictionary)"), - arg_lit0(NULL, "ulc", "upload 16 bytes keys (MIFARE UL-C dictionary)"), - arg_lit0(NULL, "aes", "upload 16 bytes keys (MIFARE UL-AES dictionary)"), + arg_lit0("m", "mifare,mfc", "upload 6 bytes keys (mifare key dictionary)"), + arg_lit0("i", "iclass", "upload 8 bytes keys (iClass key dictionary)"), + arg_lit0("t", "t55xx", "upload 4 bytes keys (password dictionary)"), arg_str1("f", "file", "", "file name"), arg_param_end }; @@ -219,35 +216,28 @@ static int CmdFlashMemLoad(const char *Cmd) { bool is_mfc = arg_get_lit(ctx, 2); bool is_iclass = arg_get_lit(ctx, 3); bool is_t55xx = arg_get_lit(ctx, 4); - bool is_ulc = arg_get_lit(ctx, 5); - bool is_ulaes = arg_get_lit(ctx, 6); int fnlen = 0; char filename[FILE_PATH_SIZE] = {0}; - CLIParamStrToBuf(arg_get_str(ctx, 7), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + char spiffsDest[32] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); CLIParserFree(ctx); Dictionary_t d = DICTIONARY_NONE; if (is_mfc) { d = DICTIONARY_MIFARE; - PrintAndLogEx(INFO, "Treating file as MIFARE Classic keys"); + PrintAndLogEx(INFO, "treating file as MIFARE Classic keys"); } else if (is_iclass) { d = DICTIONARY_ICLASS; - PrintAndLogEx(INFO, "Treating file as iCLASS keys"); + PrintAndLogEx(INFO, "treating file as iCLASS keys"); } else if (is_t55xx) { d = DICTIONARY_T55XX; - PrintAndLogEx(INFO, "Treating file as T55xx passwords"); - } else if (is_ulc) { - d = DICTIONARY_MIFARE_ULC; - PrintAndLogEx(INFO, "Treating file as MIFARE Ultralight-C keys"); - } else if (is_ulaes) { - d = DICTIONARY_MIFARE_ULAES; - PrintAndLogEx(INFO, "Treating file as MIFARE Ultralight AES keys"); + PrintAndLogEx(INFO, "treating file as T55xx passwords"); } uint8_t spi_flash_pages = 0; int res = rdv4_get_flash_pages64k(&spi_flash_pages); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Failed to get flash pages count (%x)", res); + PrintAndLogEx(ERR, "failed to get flash pages count (%x)", res); return res; } @@ -256,8 +246,6 @@ static int CmdFlashMemLoad(const char *Cmd) { uint8_t keylen = 0; uint8_t *data = calloc(FLASH_MEM_MAX_SIZE_P(spi_flash_pages), sizeof(uint8_t)); - char spiffsDest[32] = {0}; - switch (d) { case DICTIONARY_MIFARE: { keylen = MF_KEY_LENGTH; @@ -304,36 +292,6 @@ static int CmdFlashMemLoad(const char *Cmd) { strcpy(spiffsDest, ICLASS_KEYS_FILE); break; } - case DICTIONARY_MIFARE_ULC: { - keylen = MFULC_KEY_LENGTH; - res = loadFileDICTIONARY(filename, data, &datalen, keylen, &keycount); - if (res || !keycount) { - free(data); - return PM3_EFILE; - } - if (datalen > FLASH_MEM_MAX_SIZE_P(spi_flash_pages)) { - PrintAndLogEx(ERR, "error, filesize is larger than available memory"); - free(data); - return PM3_EOVFLOW; - } - strcpy(spiffsDest, MFULC_KEYS_FILE); - break; - } - case DICTIONARY_MIFARE_ULAES: { - keylen = MFULAES_KEY_LENGTH; - res = loadFileDICTIONARY(filename, data, &datalen, keylen, &keycount); - if (res || !keycount) { - free(data); - return PM3_EFILE; - } - if (datalen > FLASH_MEM_MAX_SIZE_P(spi_flash_pages)) { - PrintAndLogEx(ERR, "error, filesize is larger than available memory"); - free(data); - return PM3_EOVFLOW; - } - strcpy(spiffsDest, MFULAES_KEYS_FILE); - break; - } case DICTIONARY_NONE: { res = loadFile_safe(filename, ".bin", (void **)&data, &datalen); if (res != PM3_SUCCESS) { @@ -372,12 +330,7 @@ static int CmdFlashMemLoad(const char *Cmd) { free(data); return res; } - - if (d == DICTIONARY_T55XX) { - PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%u")" passwords to file "_GREEN_("%s"), keycount, spiffsDest); - } else { - PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%u")" keys to file "_GREEN_("%s"), keycount, spiffsDest); - } + PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%u")" passwords to file "_GREEN_("%s"), keycount, spiffsDest); SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0); SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0); } else { @@ -776,7 +729,6 @@ static int CmdFlashMemInfo(const char *Cmd) { static command_t CommandTable[] = { {"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "{ SPI File system }"}, {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"-----------", CmdHelp, IfPm3Flash, "------------------- " _CYAN_("Operations") " -------------------"}, {"baudrate", CmdFlashmemSpiBaud, IfPm3Flash, "Set Flash memory Spi baudrate"}, {"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory"}, {"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information"}, diff --git a/client/src/cmdflashmem.h b/client/src/cmdflashmem.h index f47547166..ad8727204 100644 --- a/client/src/cmdflashmem.h +++ b/client/src/cmdflashmem.h @@ -26,9 +26,7 @@ typedef enum { DICTIONARY_NONE = 0, DICTIONARY_MIFARE, DICTIONARY_T55XX, - DICTIONARY_ICLASS, - DICTIONARY_MIFARE_ULC, - DICTIONARY_MIFARE_ULAES, + DICTIONARY_ICLASS } Dictionary_t; int CmdFlashMem(const char *Cmd); diff --git a/client/src/cmdhf.c b/client/src/cmdhf.c index 13c10d863..0cdf49b81 100644 --- a/client/src/cmdhf.c +++ b/client/src/cmdhf.c @@ -231,60 +231,60 @@ int CmdHFSearch(const char *Cmd) { } */ - DropField(); - PROMPT_CLEARLINE; if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_("No known/supported 13.56 MHz tags found")); - return res; - } - - // no need to print 14A hints, since it will print itself - - if (success[THINFILM]) { - PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf thinfilm") "` commands\n"); - } - - if (success[LTO]) { - PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf lto") "` commands\n"); - } - - if (success[LEGIC]) { - PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf legic") "` commands\n"); - } - - if (success[TOPAZ]) { - PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf topaz") "` commands\n"); - } - - if (success[PROTO_TEXKOM]) { - PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf texkom") "` commands\n"); - } - - if (success[PROTO_XEROX]) { - PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf xerox") "` commands\n"); - } - - if (success[ISO_14443B]) { - PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf 14b") "` commands\n"); - } - - if (success[ISO_15693]) { - PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf 15") "` commands\n"); - } - - if (success[ICLASS]) { - PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf iclass") "` commands\n"); - } - - if (success[FELICA]) { - PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf felica") "` commands\n"); - } - - if (success[PROTO_CRYPTORF]) { - PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf cryptorf") "` commands\n"); + res = PM3_ESOFT; + } else { + + // no need to print 14A hints, since it will print itself + + if (success[THINFILM]) { + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf thinfilm") "` commands\n"); + } + + if (success[LTO]) { + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf lto") "` commands\n"); + } + + if (success[LEGIC]) { + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf legic") "` commands\n"); + } + + if (success[TOPAZ]) { + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf topaz") "` commands\n"); + } + + if (success[PROTO_TEXKOM]) { + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf texkom") "` commands\n"); + } + + if (success[PROTO_XEROX]) { + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf xerox") "` commands\n"); + } + + if (success[ISO_14443B]) { + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf 14b") "` commands\n"); + } + + if (success[ISO_15693]) { + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf 15") "` commands\n"); + } + + if (success[ICLASS]) { + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf iclass") "` commands\n"); + } + + if (success[FELICA]) { + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf felica") "` commands\n"); + } + + if (success[PROTO_CRYPTORF]) { + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf cryptorf") "` commands\n"); + } } + DropField(); return res; } @@ -477,7 +477,7 @@ int CmdHFSniff(const char *Cmd) { if (kbd_enter_pressed()) { SendCommandNG(CMD_BREAK_LOOP, NULL, 0); - PrintAndLogEx(WARNING, "\naborted via keyboard!"); + PrintAndLogEx(INFO, "User aborted"); break; } diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 42bee9388..e9319ec21 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -880,7 +880,6 @@ int CmdHF14ASim(const char *Cmd) { "hf 14a sim -t 10 -> ST25TA IKEA Rothult\n" "hf 14a sim -t 11 -> Javacard (JCOP)\n" "hf 14a sim -t 12 -> 4K Seos card\n" - "hf 14a sim -t 13 -> MIFARE Ultralight C" ); void *argtable[] = { @@ -891,8 +890,6 @@ int CmdHF14ASim(const char *Cmd) { arg_lit0("x", NULL, "Performs the 'reader attack', nr/ar attack against a reader"), arg_lit0(NULL, "sk", "Fill simulator keys from found keys"), arg_lit0("v", "verbose", "verbose output"), - arg_lit0(NULL, "c1", "UL-C Auth - all zero handshake part 1"), - arg_lit0(NULL, "c2", "UL-C Auth - all zero handshake part 2"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -926,12 +923,9 @@ int CmdHF14ASim(const char *Cmd) { bool setEmulatorMem = arg_get_lit(ctx, 5); bool verbose = arg_get_lit(ctx, 6); - bool ulc_p1 = arg_get_lit(ctx, 7); - bool ulc_p2 = arg_get_lit(ctx, 8); - CLIParserFree(ctx); - if (tagtype > 13) { + if (tagtype > 12) { PrintAndLogEx(ERR, "Undefined tag %d", tagtype); return PM3_EINVARG; } @@ -945,16 +939,11 @@ int CmdHF14ASim(const char *Cmd) { uint16_t flags; uint8_t uid[10]; uint8_t exitAfter; - uint8_t rats[20]; - bool ulc_p1; - bool ulc_p2; } PACKED payload; payload.tagtype = tagtype; payload.flags = flags; payload.exitAfter = exitAfterNReads; - payload.ulc_p1 = ulc_p1; - payload.ulc_p2 = ulc_p2; memcpy(payload.uid, uid, uid_len); clearCommandBuffer(); @@ -968,17 +957,14 @@ int CmdHF14ASim(const char *Cmd) { bool keypress = kbd_enter_pressed(); while (keypress == false) { - if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == false) { + if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == false) continue; - } - if (resp.status != PM3_SUCCESS) { + if (resp.status != PM3_SUCCESS) break; - } - if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK) { + if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK) break; - } const nonces_t *data = (nonces_t *)resp.data.asBytes; readerAttack(k_sector, k_sectors_cnt, data[0], setEmulatorMem, verbose); @@ -1330,7 +1316,7 @@ static int CmdExchangeAPDU(bool chainingin, const uint8_t *datain, int datainlen // Button pressed / user cancelled if (iLen == -3) { - PrintAndLogEx(DEBUG, "\naborted via keyboard!"); + PrintAndLogEx(DEBUG, "ERR: APDU: User aborted"); return PM3_EAPDU_FAIL; } return PM3_SUCCESS; @@ -3147,18 +3133,18 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if (isMifareClassic || isMifareMini) { res = detect_classic_static_nonce(); if (res == NONCE_STATIC) { - PrintAndLogEx(SUCCESS, "Static nonce....... " _YELLOW_("yes")); + PrintAndLogEx(SUCCESS, "Static nonce......... " _YELLOW_("yes")); } if (res == NONCE_NORMAL) { // not static res = detect_classic_prng(); if (res == 1) { - PrintAndLogEx(SUCCESS, "Prng detection..... " _GREEN_("weak")); + PrintAndLogEx(SUCCESS, "Prng detection....... " _GREEN_("weak")); } else if (res == 0) { - PrintAndLogEx(SUCCESS, "Prng detection..... " _YELLOW_("hard")); + PrintAndLogEx(SUCCESS, "Prng detection....... " _YELLOW_("hard")); } else { - PrintAndLogEx(FAILED, "Prng detection...... " _RED_("fail")); + PrintAndLogEx(FAILED, "Prng detection........ " _RED_("fail")); } if (do_nack_test) { diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index d64d200a7..f61d7d1fb 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -2708,32 +2708,25 @@ static int CmdHF14BCalypsoRead(const char *Cmd) { CLIParserFree(ctx); transport_14b_apdu_t cmds[] = { - {"01.Select ICC ", "\x94\xa4\x08\x00\x04\x3f\x00\x00\x02", 9}, - {"02.ICC ", "\x94\xb2\x01\x04\x1d", 5}, - {"03.Select EnvHol ", "\x94\xa4\x08\x00\x04\x20\x00\x20\x01", 9}, - {"04.EnvHol1 ", "\x94\xb2\x01\x04\x1d", 5}, - {"05.Select EvLog ", "\x94\xa4\x08\x00\x04\x20\x00\x20\x10", 9}, - {"06.EvLog1 ", "\x94\xb2\x01\x04\x1d", 5}, - {"07.EvLog2 ", "\x94\xb2\x02\x04\x1d", 5}, - {"08.EvLog3 ", "\x94\xb2\x03\x04\x1d", 5}, - {"09.Select ConList ", "\x94\xa4\x08\x00\x04\x20\x00\x20\x50", 9}, - {"10.ConList ", "\x94\xb2\x01\x04\x1d", 5}, - {"11.Select Contra ", "\x94\xa4\x08\x00\x04\x20\x00\x20\x20", 9}, - {"12.Contra1 ", "\x94\xb2\x01\x04\x1d", 5}, - {"13.Contra2 ", "\x94\xb2\x02\x04\x1d", 5}, - {"14.Contra3 ", "\x94\xb2\x03\x04\x1d", 5}, - {"15.Contra4 ", "\x94\xb2\x04\x04\x1d", 5}, - {"16.Select Counter ", "\x94\xa4\x08\x00\x04\x20\x00\x20\x69", 9}, - {"17.Counter ", "\x94\xb2\x01\x04\x1d", 5}, - {"18.Select SpecEv ", "\x94\xa4\x08\x00\x04\x20\x00\x20\x40", 9}, - {"19.SpecEv1 ", "\x94\xb2\x01\x04\x1d", 5}, - {"20.Select Purse ", "\x00\xa4\x00\x00\x02\x10\x15", 7}, - {"21.Purse1 ", "\x00\xb2\x01\x04\x1d", 5}, - {"22.Purse2 ", "\x00\xb2\x02\x04\x1d", 5}, - {"23.Purse3 ", "\x00\xb2\x03\x04\x1d", 5}, - {"24.Select Top Up ", "\x00\xa4\x00\x00\x02\x10\x14", 7}, - {"25.Topup1 ", "\x00\xb2\x01\x04\x1d", 5}, - {"26.Select 1TIC.ICA", "\x00\xa4\x04\x00\x08\x31\x54\x49\x43\x2e\x49\x43\x41", 13}, + {"01.Select ICC file", "\x94\xa4\x08\x00\x04\x3f\x00\x00\x02", 9}, + {"02.ICC", "\x94\xb2\x01\x04\x1d", 5}, + {"03.Select EnvHol file", "\x94\xa4\x08\x00\x04\x20\x00\x20\x01", 9}, + {"04.EnvHol1", "\x94\xb2\x01\x04\x1d", 5}, + {"05.Select EvLog file", "\x94\xa4\x08\x00\x04\x20\x00\x20\x10", 9}, + {"06.EvLog1", "\x94\xb2\x01\x04\x1d", 5}, + {"07.EvLog2", "\x94\xb2\x02\x04\x1d", 5}, + {"08.EvLog3", "\x94\xb2\x03\x04\x1d", 5}, + {"09.Select ConList file", "\x94\xa4\x08\x00\x04\x20\x00\x20\x50", 9}, + {"10.ConList", "\x94\xb2\x01\x04\x1d", 5}, + {"11.Select Contra file", "\x94\xa4\x08\x00\x04\x20\x00\x20\x20", 9}, + {"12.Contra1", "\x94\xb2\x01\x04\x1d", 5}, + {"13.Contra2", "\x94\xb2\x02\x04\x1d", 5}, + {"14.Contra3", "\x94\xb2\x03\x04\x1d", 5}, + {"15.Contra4", "\x94\xb2\x04\x04\x1d", 5}, + {"16.Select Counter file", "\x94\xa4\x08\x00\x04\x20\x00\x20\x69", 9}, + {"17.Counter", "\x94\xb2\x01\x04\x1d", 5}, + {"18.Select SpecEv file", "\x94\xa4\x08\x00\x04\x20\x00\x20\x40", 9}, + {"19.SpecEv1", "\x94\xb2\x01\x04\x1d", 5}, }; /* @@ -2787,8 +2780,9 @@ static int CmdHF14BCalypsoRead(const char *Cmd) { uint16_t sw = get_sw(response, resplen); if (sw != ISO7816_OK) { - PrintAndLogEx(INFO, "%s - command failed (%04x - %s).", cmds[i].desc, sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - continue; + PrintAndLogEx(ERR, "Sending command failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + switch_off_field_14b(); + return PM3_ESOFT; } PrintAndLogEx(INFO, "%s - %s", cmds[i].desc, sprint_hex(response, resplen)); @@ -3079,7 +3073,7 @@ plot: } } - } while (loop && (kbd_enter_pressed() == false)); + } while (loop && kbd_enter_pressed() == false); if (verbose && found == false) { PrintAndLogEx(FAILED, "no ISO 14443-B tag found"); diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index d27c8d049..c2727fa38 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -50,6 +50,22 @@ #define Logic1 Iso15693Logic1 #define FrameEOF Iso15693FrameEOF #define CARD_MEMORY_SIZE 4096 +#define HF15_UID_LENGTH 8 + +#ifndef Crc15 +# define Crc15(data, len) Crc16ex(CRC_15693, (data), (len)) +#endif +#ifndef CheckCrc15 +# define CheckCrc15(data, len) check_crc(CRC_15693, (data), (len)) +#endif +#ifndef AddCrc15 +#define AddCrc15(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1) +#endif + +#ifndef ISO15_RAW_LEN +#define ISO15_RAW_LEN(x) (sizeof(iso15_raw_cmd_t) + (x)) +#endif + #ifndef ISO15_ERROR_HANDLING_RESPONSE #define ISO15_ERROR_HANDLING_RESPONSE { \ @@ -82,11 +98,6 @@ } #endif -typedef struct { - uint8_t lock; - uint8_t block[8]; -} t15memory_t; - // structure and database for uid -> tagtype lookups typedef struct { uint64_t uid; @@ -463,7 +474,7 @@ static int getUID(bool verbose, bool loop, uint8_t *buf) { // used with 'hf search' bool readHF15Uid(bool loop, bool verbose) { - uint8_t uid[ISO15693_UID_LENGTH] = {0}; + uint8_t uid[HF15_UID_LENGTH] = {0}; if (getUID(verbose, loop, uid) != PM3_SUCCESS) { return false; } @@ -654,7 +665,7 @@ static int NxpTestEAS(const uint8_t *uid) { return PM3_EINVARG; } - uint8_t approxlen = 3 + ISO15693_UID_LENGTH + 2; + uint8_t approxlen = 3 + HF15_UID_LENGTH + 2; iso15_raw_cmd_t *packet = (iso15_raw_cmd_t *)calloc(1, sizeof(iso15_raw_cmd_t) + approxlen); if (packet == NULL) { PrintAndLogEx(WARNING, "Failed to allocate memory"); @@ -666,8 +677,8 @@ static int NxpTestEAS(const uint8_t *uid) { packet->raw[packet->rawlen++] = ISO15693_EAS_ALARM; packet->raw[packet->rawlen++] = 0x04; // IC manufacturer code - memcpy(packet->raw + packet->rawlen, uid, ISO15693_UID_LENGTH); // add UID - packet->rawlen += ISO15693_UID_LENGTH; + memcpy(packet->raw + packet->rawlen, uid, HF15_UID_LENGTH); // add UID + packet->rawlen += HF15_UID_LENGTH; AddCrc15(packet->raw, packet->rawlen); packet->rawlen += 2; @@ -709,7 +720,7 @@ static int NxpCheckSig(uint8_t *uid) { return PM3_EINVARG; } - uint8_t approxlen = 3 + ISO15693_UID_LENGTH + 2; + uint8_t approxlen = 3 + HF15_UID_LENGTH + 2; iso15_raw_cmd_t *packet = (iso15_raw_cmd_t *)calloc(1, sizeof(iso15_raw_cmd_t) + approxlen); if (packet == NULL) { PrintAndLogEx(WARNING, "Failed to allocate memory"); @@ -722,8 +733,8 @@ static int NxpCheckSig(uint8_t *uid) { packet->raw[packet->rawlen++] = ISO15693_READ_SIGNATURE; packet->raw[packet->rawlen++] = 0x04; // IC manufacturer code - memcpy(packet->raw + packet->rawlen, uid, ISO15693_UID_LENGTH); // add UID - packet->rawlen += ISO15693_UID_LENGTH; + memcpy(packet->raw + packet->rawlen, uid, HF15_UID_LENGTH); // add UID + packet->rawlen += HF15_UID_LENGTH; AddCrc15(packet->raw, packet->rawlen); packet->rawlen += 2; @@ -776,7 +787,7 @@ static int NxpSysInfo(uint8_t *uid) { packet->raw[packet->rawlen++] = 0x04; // IC manufacturer code memcpy(packet->raw + 3, uid, 8); // add UID - packet->rawlen += ISO15693_UID_LENGTH; + packet->rawlen += HF15_UID_LENGTH; AddCrc15(packet->raw, packet->rawlen); packet->rawlen += 2; @@ -889,11 +900,11 @@ static int StCheckSig(uint8_t *uid) { } // ISO15693 Protocol params - packet->raw[packet->rawlen++] = arg_get_raw_flag(ISO15693_UID_LENGTH, false, false, false); + packet->raw[packet->rawlen++] = arg_get_raw_flag(HF15_UID_LENGTH, false, false, false); packet->raw[packet->rawlen++] = ISO15693_READBLOCK; // add UID (scan, uid) - memcpy(packet->raw + packet->rawlen, uid, ISO15693_UID_LENGTH); - packet->rawlen += ISO15693_UID_LENGTH; + memcpy(packet->raw + packet->rawlen, uid, HF15_UID_LENGTH); + packet->rawlen += HF15_UID_LENGTH; packet->flags = (ISO15_CONNECT | ISO15_READ_RESPONSE | ISO15_NO_DISCONNECT); uint16_t blkoff = packet->rawlen; char signature_hex[65] = {0}; @@ -932,9 +943,9 @@ static int StCheckSig(uint8_t *uid) { uint8_t signature[16]; size_t signature_len; hexstr_to_byte_array(signature_hex, signature, &signature_len); - uint8_t uid_swap[ISO15693_UID_LENGTH]; - reverse_array_copy(uid, ISO15693_UID_LENGTH, uid_swap); - int index = originality_check_verify_ex(uid_swap, ISO15693_UID_LENGTH, signature, signature_len, PK_ST25TV, false, true); + uint8_t uid_swap[HF15_UID_LENGTH]; + reverse_array_copy(uid, HF15_UID_LENGTH, uid_swap); + int index = originality_check_verify_ex(uid_swap, HF15_UID_LENGTH, signature, signature_len, PK_ST25TV, false, true); PrintAndLogEx(NORMAL, ""); return originality_check_print(signature, signature_len, index); } @@ -959,7 +970,7 @@ static int CmdHF15Info(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, true); - uint8_t uid[ISO15693_UID_LENGTH]; + uint8_t uid[HF15_UID_LENGTH]; int uidlen = 0; CLIGetHexWithReturn(ctx, 1, uid, &uidlen); bool unaddressed = arg_get_lit(ctx, 2); @@ -976,7 +987,7 @@ static int CmdHF15Info(const char *Cmd) { } // default fallback to scan for tag. - if (unaddressed == false && uidlen != ISO15693_UID_LENGTH) { + if (unaddressed == false && uidlen != HF15_UID_LENGTH) { scan = true; } @@ -1003,10 +1014,10 @@ static int CmdHF15Info(const char *Cmd) { free(packet); return PM3_EINVARG; } - uidlen = ISO15693_UID_LENGTH; + uidlen = HF15_UID_LENGTH; } - if (uidlen == ISO15693_UID_LENGTH) { + if (uidlen == HF15_UID_LENGTH) { // add UID (scan, uid) memcpy(packet->raw + packet->rawlen, uid, uidlen); packet->rawlen += uidlen; @@ -1240,11 +1251,8 @@ static int CmdHF15ELoad(const char *Cmd) { ((tag->pagesCount * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE) || (tag->pagesCount == 0) || (tag->bytesPerPage == 0)) { - PrintAndLogEx(FAILED, "Tag size error: pagesCount=%d, bytesPerPage=%d", - tag->pagesCount, - tag->bytesPerPage - ); + tag->pagesCount, tag->bytesPerPage); free(tag); return PM3_EINVARG; } @@ -1478,7 +1486,7 @@ static int CmdHF15Sim(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, true); struct { - uint8_t uid[ISO15693_UID_LENGTH]; + uint8_t uid[HF15_UID_LENGTH]; uint8_t block_size; } PACKED payload; memset(&payload, 0, sizeof(payload)); @@ -1489,7 +1497,7 @@ static int CmdHF15Sim(const char *Cmd) { CLIParserFree(ctx); // sanity checks - if (uidlen != 0 && uidlen != ISO15693_UID_LENGTH) { + if (uidlen != 0 && uidlen != HF15_UID_LENGTH) { PrintAndLogEx(WARNING, "UID must include 8 hex bytes, got ( " _RED_("%i") " )", uidlen); return PM3_EINVARG; } @@ -1616,7 +1624,7 @@ static int CmdHF15WriteAfi(const char *Cmd) { struct { uint8_t pwd[4]; bool use_pwd; - uint8_t uid[ISO15693_UID_LENGTH]; + uint8_t uid[HF15_UID_LENGTH]; bool use_uid; uint8_t afi; } PACKED payload; @@ -1637,7 +1645,7 @@ static int CmdHF15WriteAfi(const char *Cmd) { } payload.use_uid = false; - if (uidlen == ISO15693_UID_LENGTH) { + if (uidlen == HF15_UID_LENGTH) { payload.use_uid = true; } @@ -1695,7 +1703,7 @@ static int CmdHF15WriteDsfid(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, false); - uint8_t uid[ISO15693_UID_LENGTH] = {0}; + uint8_t uid[HF15_UID_LENGTH] = {0}; int uidlen = 0; CLIGetHexWithReturn(ctx, 1, uid, &uidlen); @@ -1734,10 +1742,10 @@ static int CmdHF15WriteDsfid(const char *Cmd) { free(packet); return PM3_EINVARG; } - uidlen = ISO15693_UID_LENGTH; + uidlen = HF15_UID_LENGTH; } - if (uidlen == ISO15693_UID_LENGTH) { + if (uidlen == HF15_UID_LENGTH) { // add UID (scan, uid) memcpy(packet->raw + packet->rawlen, uid, uidlen); packet->rawlen += uidlen; @@ -1799,7 +1807,7 @@ static int CmdHF15Dump(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, true); - uint8_t uid[ISO15693_UID_LENGTH] = {0}; + uint8_t uid[HF15_UID_LENGTH] = {0}; int uidlen = 0; CLIGetHexWithReturn(ctx, 1, uid, &uidlen); @@ -1830,7 +1838,7 @@ static int CmdHF15Dump(const char *Cmd) { } // default fallback to scan for tag. - if (uidlen != ISO15693_UID_LENGTH && !unaddressed) { + if (uidlen != HF15_UID_LENGTH && !unaddressed) { scan = true; } @@ -1866,11 +1874,11 @@ static int CmdHF15Dump(const char *Cmd) { return PM3_EINVARG; } } else { - reverse_array(uid, ISO15693_UID_LENGTH); + reverse_array(uid, HF15_UID_LENGTH); } // add UID (scan, uid) - memcpy(packet->raw + packet->rawlen, uid, ISO15693_UID_LENGTH); - packet->rawlen += ISO15693_UID_LENGTH; + memcpy(packet->raw + packet->rawlen, uid, HF15_UID_LENGTH); + packet->rawlen += HF15_UID_LENGTH; used_uid = true; } else { PrintAndLogEx(INFO, "Using unaddressed mode"); @@ -1907,49 +1915,35 @@ static int CmdHF15Dump(const char *Cmd) { uint8_t dCpt = 10; int res = iso15_error_handling_card_response(d, resp.length); - if (res == PM3_ECRC) { + if (res != PM3_SUCCESS) { free(tag); free(packet); return res; } - if (res == PM3_SUCCESS) { - memcpy(tag->uid, d + 2, 8); + memcpy(tag->uid, &d[2], 8); - if (d[1] & 0x01) { - tag->dsfid = d[dCpt]; - } - dCpt++; + if (d[1] & 0x01) { + tag->dsfid = d[dCpt++]; + } - if (d[1] & 0x02) { - tag->afi = d[dCpt]; - } - dCpt++; - - if (d[1] & 0x04) { - tag->pagesCount = d[dCpt] + 1; - tag->bytesPerPage = d[dCpt + 1] + 1; - } else { - // Set tag memory layout values (if can't be read in SYSINFO) - tag->bytesPerPage = blocksize; - tag->pagesCount = 128; - } - dCpt += 2; - - if (d[1] & 0x08) { - tag->ic = d[dCpt]; - } - dCpt++; + if (d[1] & 0x02) { + tag->afi = d[dCpt++]; + } + if (d[1] & 0x04) { + tag->pagesCount = d[dCpt++] + 1; + tag->bytesPerPage = d[dCpt++] + 1; } else { - tag->uid[0] = 0xE0; - tag->dsfid = 0; - tag->afi = 0; // Set tag memory layout values (if can't be read in SYSINFO) tag->bytesPerPage = blocksize; tag->pagesCount = 128; } + if (d[1] & 0x08) { + tag->ic = d[dCpt++]; + } + // add length for blockno (1) packet->rawlen++; packet->raw[0] |= ISO15_REQ_OPTION; // Add option to dump lock status @@ -2184,10 +2178,10 @@ static int CmdHF15Readmulti(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, false); - uint8_t uid[ISO15693_UID_LENGTH] = {0x00}; + uint8_t uid[HF15_UID_LENGTH] = {0x00}; int uidlen = 0; CLIGetHexWithReturn(ctx, 1, uid, &uidlen); - bool uid_set = (uidlen == ISO15693_UID_LENGTH) ? true : false; + bool uid_set = (uidlen == HF15_UID_LENGTH) ? true : false; bool unaddressed = arg_get_lit(ctx, 2); bool scan = (arg_get_lit(ctx, 3) || (!uid_set && !unaddressed)) ? true : false; //Default fallback to scan for tag. Overriding unaddressed parameter. @@ -2245,11 +2239,11 @@ static int CmdHF15Readmulti(const char *Cmd) { return PM3_EINVARG; } } else { - reverse_array(uid, ISO15693_UID_LENGTH); + reverse_array(uid, HF15_UID_LENGTH); } // add UID (scan, uid) - memcpy(packet->raw + packet->rawlen, uid, ISO15693_UID_LENGTH); - packet->rawlen += ISO15693_UID_LENGTH; + memcpy(packet->raw + packet->rawlen, uid, HF15_UID_LENGTH); + packet->rawlen += HF15_UID_LENGTH; } else { PrintAndLogEx(INFO, "Using unaddressed mode"); @@ -2261,9 +2255,7 @@ static int CmdHF15Readmulti(const char *Cmd) { // 0 means 1 page, // 1 means 2 pages, ... - if (blockcnt > 0) { - blockcnt--; - } + if (blockcnt > 0) blockcnt--; packet->raw[packet->rawlen++] = blockno; packet->raw[packet->rawlen++] = blockcnt; @@ -2293,7 +2285,7 @@ static int CmdHF15Readmulti(const char *Cmd) { ISO15_ERROR_HANDLING_CARD_RESPONSE(d, resp.length) // 1 byte cmd, 1 lock byte, 4 / 8 bytes block size, 2 crc - if (resp.length > (1 + ((blockcnt + 1) * (blocksize + 1)) + 2)) { + if (resp.length > (1 + (blockcnt * (blocksize + 1)) + 2)) { PrintAndLogEx(WARNING, "got longer response. Check block size!"); } @@ -2344,10 +2336,10 @@ static int CmdHF15Readblock(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, false); - uint8_t uid[ISO15693_UID_LENGTH]; + uint8_t uid[HF15_UID_LENGTH]; int uidlen = 0; CLIGetHexWithReturn(ctx, 1, uid, &uidlen); - bool uid_set = (uidlen == ISO15693_UID_LENGTH) ? true : false; + bool uid_set = (uidlen == HF15_UID_LENGTH) ? true : false; bool unaddressed = arg_get_lit(ctx, 2); bool scan = (arg_get_lit(ctx, 3) || (!uid_set && !unaddressed)) ? true : false; // Default fallback to scan for tag. Overriding unaddressed parameter. @@ -2401,11 +2393,11 @@ static int CmdHF15Readblock(const char *Cmd) { return PM3_EINVARG; } } else { - reverse_array(uid, ISO15693_UID_LENGTH); + reverse_array(uid, HF15_UID_LENGTH); } // add UID (scan, uid) - memcpy(packet->raw + packet->rawlen, uid, ISO15693_UID_LENGTH); - packet->rawlen += ISO15693_UID_LENGTH; + memcpy(packet->raw + packet->rawlen, uid, HF15_UID_LENGTH); + packet->rawlen += HF15_UID_LENGTH; } else { PrintAndLogEx(INFO, "Using unaddressed mode"); @@ -2498,8 +2490,8 @@ static int hf_15_write_blk(const uint8_t *pm3flags, uint16_t flags, const uint8_ // add UID if (uid) { - memcpy(packet->raw + packet->rawlen, uid, ISO15693_UID_LENGTH); - packet->rawlen += ISO15693_UID_LENGTH; + memcpy(packet->raw + packet->rawlen, uid, HF15_UID_LENGTH); + packet->rawlen += HF15_UID_LENGTH; } packet->raw[packet->rawlen++] = blockno; @@ -2558,10 +2550,10 @@ static int CmdHF15Write(const char *Cmd) { argtable[arglen++] = arg_param_end; CLIExecWithReturn(ctx, Cmd, argtable, false); - uint8_t uid[ISO15693_UID_LENGTH]; + uint8_t uid[HF15_UID_LENGTH]; int uidlen = 0; CLIGetHexWithReturn(ctx, 1, uid, &uidlen); - bool uid_set = (uidlen == ISO15693_UID_LENGTH) ? true : false; + bool uid_set = (uidlen == HF15_UID_LENGTH) ? true : false; bool unaddressed = arg_get_lit(ctx, 2); bool scan = (arg_get_lit(ctx, 3) || (!uid_set && !unaddressed)) ? true : false; // Default fallback to scan for tag. Overriding unaddressed parameter. @@ -2597,7 +2589,7 @@ static int CmdHF15Write(const char *Cmd) { return PM3_EINVARG; } } else { - reverse_array(uid, ISO15693_UID_LENGTH); + reverse_array(uid, HF15_UID_LENGTH); } } else { PrintAndLogEx(INFO, "Using unaddressed mode"); @@ -2632,7 +2624,7 @@ static int CmdHF15Restore(const char *Cmd) { "hf 15 restore -u E011223344556677 -f hf-15-my-dump.bin" ); - void *argtable[6 + 4] = {0}; + void *argtable[6 + 5] = {0}; uint8_t arglen = arg_add_default(argtable); argtable[arglen++] = arg_str0("f", "file", "", "Specify a filename for dump file"); argtable[arglen++] = arg_int0("r", "retry", "", "number of retries (def 3)"); @@ -2640,7 +2632,7 @@ static int CmdHF15Restore(const char *Cmd) { argtable[arglen++] = arg_param_end; CLIExecWithReturn(ctx, Cmd, argtable, true); - uint8_t uid[ISO15693_UID_LENGTH]; + uint8_t uid[HF15_UID_LENGTH]; int uidlen = 0; CLIGetHexWithReturn(ctx, 1, uid, &uidlen); @@ -2670,7 +2662,7 @@ static int CmdHF15Restore(const char *Cmd) { // default fallback to scan for tag. // overriding unaddress parameter :) - if (uidlen != ISO15693_UID_LENGTH) { + if (uidlen != HF15_UID_LENGTH) { scan = true; } @@ -2682,7 +2674,7 @@ static int CmdHF15Restore(const char *Cmd) { return PM3_EINVARG; } } else { - reverse_array(uid, ISO15693_UID_LENGTH); + reverse_array(uid, HF15_UID_LENGTH); } } else { PrintAndLogEx(INFO, "Using unaddressed mode"); @@ -2721,11 +2713,8 @@ static int CmdHF15Restore(const char *Cmd) { ((tag->pagesCount * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE) || (tag->pagesCount == 0) || (tag->bytesPerPage == 0)) { - PrintAndLogEx(FAILED, "Tag size error: pagesCount=%d, bytesPerPage=%d", - tag->pagesCount, - tag->bytesPerPage - ); + tag->pagesCount, tag->bytesPerPage); free(tag); return PM3_EINVARG; } @@ -2756,8 +2745,8 @@ static int CmdHF15Restore(const char *Cmd) { for (tried = 0; tried < retries; tried++) { - retval = hf_15_write_blk(&pm3flags, flags, uid, fast, i, data, tag->bytesPerPage); - + retval = hf_15_write_blk(&pm3flags, flags, uid, fast + , i, data, tag->bytesPerPage); if (retval == PM3_SUCCESS) { PrintAndLogEx(INPLACE, "blk %3d", i); @@ -2820,7 +2809,7 @@ static int CmdHF15CSetUID(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, false); struct { - uint8_t uid[ISO15693_UID_LENGTH]; + uint8_t uid[HF15_UID_LENGTH]; } PACKED payload; int uidlen = 0; @@ -2828,7 +2817,7 @@ static int CmdHF15CSetUID(const char *Cmd) { bool use_v2 = arg_get_lit(ctx, 2); CLIParserFree(ctx); - if (uidlen != ISO15693_UID_LENGTH) { + if (uidlen != HF15_UID_LENGTH) { PrintAndLogEx(WARNING, "UID must include 8 hex bytes, got " _RED_("%i"), uidlen); return PM3_EINVARG; } @@ -2842,7 +2831,7 @@ static int CmdHF15CSetUID(const char *Cmd) { PrintAndLogEx(INFO, "Get current tag"); - uint8_t carduid[ISO15693_UID_LENGTH] = {0x00}; + uint8_t carduid[HF15_UID_LENGTH] = {0x00}; if (getUID(true, false, carduid) != PM3_SUCCESS) { PrintAndLogEx(FAILED, "no tag found"); return PM3_ESOFT; @@ -2872,10 +2861,10 @@ static int CmdHF15CSetUID(const char *Cmd) { } // reverse cardUID to compare - uint8_t revuid[ISO15693_UID_LENGTH] = {0}; + uint8_t revuid[HF15_UID_LENGTH] = {0}; reverse_array_copy(carduid, sizeof(carduid), revuid); - if (memcmp(revuid, payload.uid, ISO15693_UID_LENGTH) == 0) { + if (memcmp(revuid, payload.uid, HF15_UID_LENGTH) == 0) { PrintAndLogEx(SUCCESS, "Setting new UID ( " _GREEN_("ok") " )"); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS;; @@ -3489,11 +3478,8 @@ static int CmdHF15View(const char *Cmd) { ((tag->pagesCount * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE) || (tag->pagesCount == 0) || (tag->bytesPerPage == 0)) { - PrintAndLogEx(FAILED, "Tag size error: pagesCount=%d, bytesPerPage=%d", - tag->pagesCount, - tag->bytesPerPage - ); + tag->pagesCount, tag->bytesPerPage); free(tag); return PM3_EINVARG; } @@ -3512,15 +3498,15 @@ static int CmdHF15Wipe(const char *Cmd) { ); void *argtable[6 + 3] = {0}; uint8_t arglen = arg_add_default(argtable); - argtable[arglen++] = arg_int0(NULL, "bs", "", "block size (def 4)"); - argtable[arglen++] = arg_lit0("v", "verbose", "verbose output"); + argtable[arglen++] = arg_int0(NULL, "bs", "", "block size (def 4)"), + argtable[arglen++] = arg_lit0("v", "verbose", "verbose output"); argtable[arglen++] = arg_param_end; CLIExecWithReturn(ctx, Cmd, argtable, true); - uint8_t uid[ISO15693_UID_LENGTH]; + uint8_t uid[HF15_UID_LENGTH]; int uidlen = 0; CLIGetHexWithReturn(ctx, 1, uid, &uidlen); - bool uid_set = (uidlen == ISO15693_UID_LENGTH) ? true : false; + bool uid_set = (uidlen == HF15_UID_LENGTH) ? true : false; bool unaddressed = arg_get_lit(ctx, 2); bool scan = (arg_get_lit(ctx, 3) || (!uid_set && !unaddressed)) ? true : false; // Default fallback to scan for tag. Overriding unaddressed parameter. @@ -3552,7 +3538,7 @@ static int CmdHF15Wipe(const char *Cmd) { return PM3_EINVARG; } } else { - reverse_array(uid, ISO15693_UID_LENGTH); + reverse_array(uid, HF15_UID_LENGTH); } } else { PrintAndLogEx(INFO, "Using unaddressed mode"); diff --git a/client/src/cmdhf15.h b/client/src/cmdhf15.h index b6f7d250b..8803a58b4 100644 --- a/client/src/cmdhf15.h +++ b/client/src/cmdhf15.h @@ -20,24 +20,9 @@ #define CMDHF15_H__ #include "common.h" -#include "crc16.h" -#include "iso15.h" // typedef structs / enum - -#ifndef Crc15 -# define Crc15(data, len) Crc16ex(CRC_15693, (data), (len)) -#endif -#ifndef CheckCrc15 -# define CheckCrc15(data, len) check_crc(CRC_15693, (data), (len)) -#endif -#ifndef AddCrc15 -#define AddCrc15(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1) -#endif - -#ifndef ISO15_RAW_LEN -#define ISO15_RAW_LEN(x) (sizeof(iso15_raw_cmd_t) + (x)) -#endif int CmdHF15(const char *Cmd); + bool readHF15Uid(bool loop, bool verbose); #endif diff --git a/client/src/cmdhfcryptorf.c b/client/src/cmdhfcryptorf.c index 1a00881e1..af703e511 100644 --- a/client/src/cmdhfcryptorf.c +++ b/client/src/cmdhfcryptorf.c @@ -232,7 +232,8 @@ int readHFCryptoRF(bool loop, bool verbose) { PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex_inrow(card.uid, card.uidlen)); set_last_known_card(card); } - } while (loop && (kbd_enter_pressed() == false)); + } while (loop && kbd_enter_pressed() == false); + DropField(); return res; } diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 5c48bbefe..d52cb52da 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -29,28 +29,9 @@ #include "ui.h" #include "iso18.h" // felica_card_select_t struct #include "des.h" -#include "platform_util.h" #include "cliparser.h" // cliparser #include "util_posix.h" // msleep - -#define FELICA_BLK_SIZE 16 -#define FELICA_BLK_HALF (FELICA_BLK_SIZE/2) - -#define FELICA_BLK_NUMBER_RC 0x80 -#define FELICA_BLK_NUMBER_ID 0x82 -#define FELICA_BLK_NUMBER_WCNT 0x90 -#define FELICA_BLK_NUMBER_MACA 0x91 -#define FELICA_BLK_NUMBER_STATE 0x92 - -#define FELICA_SERVICE_ATTRIBUTE_UNAUTH_READ (0b000001) -#define FELICA_SERVICE_ATTRIBUTE_READ_ONLY (0b000010) -#define FELICA_SERVICE_ATTRIBUTE_RANDOM_ACCESS (0b001000) -#define FELICA_SERVICE_ATTRIBUTE_CYCLIC (0b001100) -#define FELICA_SERVICE_ATTRIBUTE_PURSE (0b010000) -#define FELICA_SERVICE_ATTRIBUTE_PURSE_SUBFIELD (0b000110) - - #define AddCrc(data, len) compute_crc(CRC_FELICA, (data), (len), (data)+(len)+1, (data)+(len)) static int CmdHelp(const char *Cmd); @@ -269,7 +250,6 @@ static const char *felica_model_name(uint8_t rom_type, uint8_t ic_type) { return "FeliCa Standard RC-S919"; case 0x0B: case 0x31: - case 0x36: return "Suica card (FeliCa Standard RC-S ?)"; default: break; @@ -368,7 +348,7 @@ int read_felica_uid(bool loop, bool verbose) { res = PM3_SUCCESS; } - } while (loop && (kbd_enter_pressed() == false)); + } while (loop && kbd_enter_pressed() == false); DropField(); return res; @@ -493,7 +473,7 @@ static void print_rd_plain_response(felica_read_without_encryption_response_t *r temp = sprint_hex(rd_noCry_resp->block_element_number, sizeof(rd_noCry_resp->block_element_number)); strncpy(bl_element_number, temp, sizeof(bl_element_number) - 1); - PrintAndLogEx(INFO, " %s | %s ", bl_element_number, bl_data); + PrintAndLogEx(INFO, " %s | %s ", bl_element_number, bl_data); } else { PrintAndLogEx(SUCCESS, "IDm... %s", sprint_hex_inrow(rd_noCry_resp->frame_response.IDm, sizeof(rd_noCry_resp->frame_response.IDm))); PrintAndLogEx(SUCCESS, " Status flag 1... %s", sprint_hex(rd_noCry_resp->status_flags.status_flag1, sizeof(rd_noCry_resp->status_flags.status_flag1))); @@ -551,28 +531,6 @@ int send_rd_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, } } -/** - * Sends a dump_service frame to the pm3 and prints response. - * @param flags to use for pm3 communication. - * @param datalen frame length. - * @param data frame to be send. - * @param verbose display additional output. - * @param dump_sv_resp frame in which the response will be saved. - * @param is_area true if the service is an area, false if it is a service. - * @return success if response was received. - */ -int send_dump_sv_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_service_dump_response_t *dump_sv_resp, bool is_area) { - clear_and_send_command(flags, datalen, data, verbose); - PacketResponseNG resp; - if (waitCmdFelica(false, &resp, verbose) == false) { - PrintAndLogEx(ERR, "No response from card"); - return PM3_ERFTRANS; - } else { - memcpy(dump_sv_resp, (felica_service_dump_response_t *)resp.data.asBytes, sizeof(felica_service_dump_response_t)); - return PM3_SUCCESS; - } -} - /** * Checks if last known card can be added to data and adds it if possible. * @param custom_IDm @@ -1676,152 +1634,6 @@ static int CmdHFFelicaRequestSystemCode(const char *Cmd) { return PM3_SUCCESS; } -/** - * Command parser for rqservice. - * @param Cmd input data of the user. - * @return client result code. - */ -static int CmdHFFelicaDump(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf felica dump", - "Dump all existing Area Code and Service Code.\n" - "Only works on services that do not require authentication yet.\n", - "hf felica dump"); - void *argtable[] = { - arg_param_begin, - arg_lit0(NULL, "no-auth", "read public services"), - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, true); - CLIParserFree(ctx); - - // bool no_auth = arg_get_lit(ctx, 1); - - uint8_t data_service_dump[PM3_CMD_DATA_SIZE] = {0}; - data_service_dump[0] = 0x0C; - data_service_dump[1] = 0x0A; - uint16_t service_datalen = 12; - if (!check_last_idm(data_service_dump, service_datalen)) - return PM3_EINVARG; - - uint8_t data_block_dump[PM3_CMD_DATA_SIZE] = {0}; - data_block_dump[0] = 0x10; // Static length - data_block_dump[1] = 0x06; // unauth read block command - data_block_dump[10] = 0x01; // read one service at a time - data_block_dump[13] = 0x01; // read one block at a time - data_block_dump[14] = 0x80; // block list element first byte - uint16_t block_datalen = 16; // Length (1), Command ID (1), IDm (8), Number of Service (1), Service Code List(2), Number of Block(1), Block List(3) - if (!check_last_idm(data_block_dump, block_datalen)) { - return PM3_EINVARG; - } - - uint8_t flags = FELICA_APPEND_CRC | FELICA_RAW; - - uint16_t cursor = 0x0000; - - felica_service_dump_response_t resp; - - while (true) { - - data_service_dump[10] = cursor & 0xFF; - data_service_dump[11] = cursor >> 8; - AddCrc(data_service_dump, service_datalen); - - if (send_dump_sv_plain(flags, service_datalen + 2, data_service_dump, 0, - &resp, false) != PM3_SUCCESS) { - PrintAndLogEx(FAILED, "No response at cursor 0x%04X", cursor); - return PM3_ERFTRANS; - } - if (resp.frame_response.cmd_code[0] != 0x0B) { - PrintAndLogEx(FAILED, "Bad response cmd 0x%02X @ 0x%04X.", - resp.frame_response.cmd_code[0], cursor); - PrintAndLogEx(INFO, "This is a normal signal issue. Please try again."); - PrintAndLogEx(INFO, "If the issue persists, move the card around and check signal strength. FeliCa can be hard to keep in field."); - return PM3_ERFTRANS; - } - uint8_t len = resp.frame_response.length[0]; - uint16_t node_code = resp.payload[0] | (resp.payload[1] << 8); - if (node_code == 0xFFFF) break; - char attrib_str[64] = ""; - switch (len) { - case 0x0E: - break; - case 0x0C: { - uint8_t attribute = node_code & 0x3F; - bool is_public = (attribute & FELICA_SERVICE_ATTRIBUTE_UNAUTH_READ) != 0; - strcat(attrib_str, is_public ? "| Public " : "| Private "); - - bool is_purse = (attribute & FELICA_SERVICE_ATTRIBUTE_PURSE) != 0; - // Subfield bitwise attributes are applicable depending on is PURSE or not - - if (is_purse) { - strcat(attrib_str, "| Purse |"); - switch ((attribute & FELICA_SERVICE_ATTRIBUTE_PURSE_SUBFIELD) >> 1) { - case 0: - strcat(attrib_str, " Direct |"); - break; - case 1: - strcat(attrib_str, " Cashback |"); - break; - case 2: - strcat(attrib_str, " Decrement |"); - break; - case 3: - strcat(attrib_str, " Read Only |"); - break; - default: - strcat(attrib_str, " Unknown |"); - break; - } - } else { - bool is_random = (attribute & FELICA_SERVICE_ATTRIBUTE_RANDOM_ACCESS) != 0; - strcat(attrib_str, is_random ? "| Random |" : "| Cyclic |"); - bool is_readonly = (attribute & FELICA_SERVICE_ATTRIBUTE_READ_ONLY) != 0; - strcat(attrib_str, is_readonly ? " Read Only |" : " Read/Write |"); - } - - PrintAndLogEx(INFO, "Service %04X %s", node_code, attrib_str); - - if (is_public) { - // dump blocks here - PrintAndLogEx(INFO, " block | data "); - PrintAndLogEx(INFO, "-------+----------------------------------------"); - - data_block_dump[11] = resp.payload[0]; // convert service code to little endian - data_block_dump[12] = resp.payload[1]; - - uint16_t last_blockno = 0xFF; - for (uint16_t i = 0x00; i < last_blockno; i++) { - data_block_dump[15] = i; - AddCrc(data_block_dump, block_datalen); - felica_read_without_encryption_response_t rd_noCry_resp; - if ((send_rd_plain(flags, block_datalen + 2, data_block_dump, 0, &rd_noCry_resp) == PM3_SUCCESS)) { - if (rd_noCry_resp.status_flags.status_flag1[0] == 0 && rd_noCry_resp.status_flags.status_flag2[0] == 0) { - print_rd_plain_response(&rd_noCry_resp); - } else { - break; // no more blocks to read - } - } else { - break; - } - } - } - break; - } - default: - PrintAndLogEx(FAILED, "Unexpected length 0x%02X @ 0x%04X", - len, cursor); - return PM3_ERFTRANS; - } - cursor++; - if (cursor == 0) break; - } - - PrintAndLogEx(SUCCESS, "Unauth service dump complete."); - return PM3_SUCCESS; -} - - /** * Command parser for rqservice. * @param Cmd input data of the user. @@ -1931,119 +1743,18 @@ static int CmdHFFelicaRequestService(const char *Cmd) { return PM3_SUCCESS; } -/** - * Command parser for rqservice. - * @param Cmd input data of the user. - * @return client result code. - */ -static int CmdHFFelicaDumpServiceArea(const char *Cmd) { - /* -- CLI boilerplate (unchanged) ------------------------------- */ +static int CmdHFFelicaNotImplementedYet(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf felica scsvcode", - "Dump all existing Area Code and Service Code.\n", - "hf felica scsvcode"); - void *argtable[] = { arg_param_begin, arg_param_end }; - CLIExecWithReturn(ctx, Cmd, argtable, true); + "Feature not implemented yet. Feel free to contribute!", + "hf felica scsvcode" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); CLIParserFree(ctx); - - /* -- build static part of Search-Service frame ---------------- */ - uint8_t data[PM3_CMD_DATA_SIZE] = {0}; - data[0] = 0x0C; /* LEN */ - data[1] = 0x0A; /* CMD = 0x0A */ - uint16_t datalen = 12; /* LEN + CMD + IDm + cursor */ - - if (!check_last_idm(data, datalen)) - return PM3_EINVARG; - - PrintAndLogEx(HINT, "Area and service code are printed in big endian."); - PrintAndLogEx(HINT, "Don't forget to convert to little endian when using hf felica rdbl."); - PrintAndLogEx(INFO, "┌───────────────────────────────────────────────"); - - uint8_t flags = FELICA_APPEND_CRC | FELICA_RAW; - - /* -- traversal state ------------------------------------------ */ - uint16_t cursor = 0x0000; - uint16_t area_end_stack[8] = {0xFFFF}; /* root “end” = 0xFFFF */ - int depth = 0; /* current stack depth */ - - felica_service_dump_response_t resp; - - while (true) { - - /* insert cursor LE */ - data[10] = cursor & 0xFF; - data[11] = cursor >> 8; - AddCrc(data, datalen); - - if (send_dump_sv_plain(flags, datalen + 2, data, 0, - &resp, false) != PM3_SUCCESS) { - PrintAndLogEx(FAILED, "No response at cursor 0x%04X", cursor); - return PM3_ERFTRANS; - } - if (resp.frame_response.cmd_code[0] != 0x0B) { - PrintAndLogEx(FAILED, "Bad response cmd 0x%02X @ 0x%04X.", - resp.frame_response.cmd_code[0], cursor); - PrintAndLogEx(INFO, "This is a normal signal issue. Please try again."); - PrintAndLogEx(INFO, "If the issue persists, move the card around and check signal strength. FeliCa can be hard to keep in field."); - return PM3_ERFTRANS; - } - - uint8_t len = resp.frame_response.length[0]; - uint16_t node_code = resp.payload[0] | (resp.payload[1] << 8); - - if (node_code == 0xFFFF) break; /* end-marker */ - - /* pop finished areas */ - while (depth && node_code > area_end_stack[depth]) depth--; - - - /* ----- compose nice prefix ------------------------------------ */ - char prefix[64] = ""; - for (int i = 1; i < depth; i++) { - bool more_siblings = (cursor < area_end_stack[i]); - strcat(prefix, more_siblings ? "│ " : " "); - } - /* decide glyph for this line (areas always use └──) */ - const char *line_glyph = "├── "; - strcat(prefix, line_glyph); - - /* ----- print --------------------------------------------------- */ - if (len == 0x0E) { /* AREA node */ - uint16_t end_code = resp.payload[2] | (resp.payload[3] << 8); - PrintAndLogEx(INFO, "%sAREA_%04X", prefix, node_code >> 6); - - if (depth < 7) { - area_end_stack[++depth] = end_code; - } - } else if (len == 0x0C) { /* SERVICE */ - PrintAndLogEx(INFO, "%ssvc_%04X", prefix, node_code); - } else { - PrintAndLogEx(FAILED, "Unexpected length 0x%02X @ 0x%04X", - len, cursor); - return PM3_ERFTRANS; - } - cursor++; - if (cursor == 0) break; /* overflow safety */ - } - - /* draw closing bar └─┴─... based on final depth */ - char bar[128]; /* large enough for depth ≤ 7 */ - size_t pos = 0; - - /* leading corner */ - pos += snprintf(bar + pos, sizeof(bar) - pos, "└"); - - /* one segment per level-1 */ - for (int i = 0; i < depth - 1 && pos < sizeof(bar); i++) - pos += snprintf(bar + pos, sizeof(bar) - pos, "───┴"); - - /* tail */ - snprintf(bar + pos, sizeof(bar) - pos, "───────────────────────"); - - PrintAndLogEx(INFO, "%s", bar); - - - PrintAndLogEx(SUCCESS, "Service code and area dump complete."); return PM3_SUCCESS; } @@ -2092,7 +1803,7 @@ static int CmdHFFelicaSniff(const char *Cmd) { for (;;) { if (kbd_enter_pressed()) { SendCommandNG(CMD_BREAK_LOOP, NULL, 0); - PrintAndLogEx(DEBUG, "\naborted via keyboard!"); + PrintAndLogEx(DEBUG, "User aborted"); msleep(300); break; } @@ -2140,7 +1851,7 @@ static int CmdHFFelicaSimLite(const char *Cmd) { for (;;) { if (kbd_enter_pressed()) { SendCommandNG(CMD_BREAK_LOOP, NULL, 0); - PrintAndLogEx(DEBUG, "\naborted via keyboard!"); + PrintAndLogEx(DEBUG, "User aborted"); msleep(300); break; } @@ -2157,613 +1868,6 @@ static int CmdHFFelicaSimLite(const char *Cmd) { return PM3_SUCCESS; } -static int felica_make_block_list(uint16_t *out, const uint8_t *blk_numbers, const size_t length) { - if (length > 4) { - PrintAndLogEx(ERR, "felica_make_block_list: exceeds max size"); - return PM3_EINVARG; - } - - uint16_t tmp[4]; - memset(tmp, 0, sizeof(tmp)); - - for (size_t i = 0; i < length; i++) { - tmp[i] = (uint16_t)(blk_numbers[i] << 8) | 0x80; - } - memcpy(out, tmp, length * sizeof(uint16_t)); - - return PM3_SUCCESS; -} - -static int read_without_encryption( - const uint8_t *idm, - const uint8_t num, - const uint8_t *blk_numbers, - uint8_t *out, - uint16_t *n) { - - felica_read_request_haeder_t request = { - .command_code = { 0x06 }, - .number_of_service = { 1 }, - .service_code_list = { 0x00B }, - .number_of_block = { num }, - }; - memcpy(request.IDm, idm, sizeof(request.IDm)); - - uint16_t svc[num]; - int ret = felica_make_block_list(svc, blk_numbers, num); - if (ret) { - return PM3_EINVARG; - } - - size_t hdr_size = sizeof(request); - uint16_t size = hdr_size + sizeof(svc) + 1; - *n = size; - - memcpy(out, &(uint8_t) { size }, sizeof(uint8_t)); - memcpy(out + 1, &request, hdr_size); - memcpy(out + hdr_size + 1, &svc, sizeof(svc)); - - return PM3_SUCCESS; -} - -static bool check_write_req_data(const felica_write_request_haeder_t *hdr, const uint8_t datalen) { - if (!hdr || !datalen) - return false; - - uint8_t num = *(hdr->number_of_block); - if (num != 1 && num != 2) - return false; - - // Check Block data size - if (num * 16 != datalen) - return false; - - return true; -} - -static int write_without_encryption( - const uint8_t *idm, - uint8_t num, - uint8_t *blk_numbers, - const uint8_t *data, - size_t datalen, - uint8_t *out, - uint16_t *n) { - - felica_write_request_haeder_t hdr = { - .command_code = { 0x08 }, - .number_of_service = { 1 }, - .service_code_list = { 0x009 }, - .number_of_block = { num }, - }; - memcpy(hdr.IDm, idm, sizeof(hdr.IDm)); - - uint8_t dl = (uint8_t)(datalen); - - if (check_write_req_data(&hdr, dl) == false) { - PrintAndLogEx(FAILED, "invalid request"); - return PM3_EINVARG; - } - - uint16_t blk[num]; - int ret = felica_make_block_list(blk, blk_numbers, num); - if (ret) { - return PM3_EINVARG; - } - - - size_t hdr_size = sizeof(hdr); - size_t offset = hdr_size + (num * 2) + 1; - - uint8_t size = hdr_size + sizeof(blk) + dl + 1; - *n = size; - - memcpy(out, &(uint8_t) { size }, sizeof(uint8_t)); - memcpy(out + 1, &hdr, hdr_size); - memcpy(out + hdr_size + 1, &blk, sizeof(blk)); - memcpy(out + offset, data, dl); - - return PM3_SUCCESS; -} - -static int parse_multiple_block_data(const uint8_t *data, const size_t datalen, uint8_t *out, uint8_t *outlen) { - if (datalen < 3) { - PrintAndLogEx(ERR, "\ndata size must be at least 3 bytes"); - return PM3_EINVARG; - } - - felica_status_response_t res; - memcpy(&res, data, sizeof(res)); - - uint8_t empty[8] = {0}; - - if (!memcmp(res.frame_response.IDm, empty, sizeof(empty))) { - PrintAndLogEx(ERR, "internal error"); - return PM3_ERFTRANS; - } - - - if (res.status_flags.status_flag1[0] != 0x00 || res.status_flags.status_flag2[0] != 0x00) { - PrintAndLogEx(ERR, "error status"); - return PM3_ERFTRANS; - } - - size_t res_size = sizeof(res); - - uint8_t num = 0; - memcpy(&num, data + res_size, sizeof(uint8_t)); - res_size++; - - memcpy(out, data + res_size, num * FELICA_BLK_SIZE); - - if (outlen) { - *outlen = num * FELICA_BLK_SIZE; - } - - return PM3_SUCCESS; -} - -static int send_rd_multiple_plain(uint8_t flags, uint16_t datalen, uint8_t *data, uint8_t *out) { - clear_and_send_command(flags, datalen, data, false); - PacketResponseNG res; - if (waitCmdFelica(false, &res, false) == false) { - PrintAndLogEx(ERR, "\nGot no response from card"); - return PM3_ERFTRANS; - } - - uint8_t block_data[FELICA_BLK_SIZE * 4]; - memset(block_data, 0, sizeof(block_data)); - - uint8_t outlen = 0; - - int ret = parse_multiple_block_data(res.data.asBytes, sizeof(res.data.asBytes), block_data, &outlen); - if (ret) { - return PM3_ERFTRANS; - } - - memcpy(out, block_data, outlen); - - return PM3_SUCCESS; -} - -static int felica_auth_context_init( - mbedtls_des3_context *ctx, - const uint8_t *rc, - const size_t rclen, - const uint8_t *key, - const size_t keylen, - felica_auth_context_t *auth_ctx) { - - int ret = PM3_SUCCESS; - - uint8_t rev_rc[16], rev_key[16]; - uint8_t encrypted_sk[16], rev_sk[16]; - uint8_t iv[8] = {0}; - - if (!ctx || !auth_ctx || rclen != 16 || keylen != 16) { - PrintAndLogEx(ERR, "\nfelica_auth_context_init: invalid parameters"); - return PM3_EINVARG; - } - - SwapEndian64ex(rc, sizeof(rev_rc), 8, rev_rc); - memcpy(auth_ctx->random_challenge, rev_rc, sizeof(auth_ctx->random_challenge)); - - SwapEndian64ex(key, sizeof(rev_key), 8, rev_key); - - if (mbedtls_des3_set2key_enc(ctx, rev_key) != 0) { - ret = PM3_ECRYPTO; - goto cleanup; - } - - if (mbedtls_des3_crypt_cbc(ctx, MBEDTLS_DES_ENCRYPT, 16, iv, rev_rc, encrypted_sk) != 0) { - ret = PM3_ECRYPTO; - goto cleanup; - } - - SwapEndian64ex(encrypted_sk, sizeof(encrypted_sk), 8, rev_sk); - - memcpy(auth_ctx->session_key, rev_sk, sizeof(auth_ctx->session_key)); - -cleanup: - mbedtls_platform_zeroize(rev_rc, sizeof(rev_rc)); - mbedtls_platform_zeroize(rev_key, sizeof(rev_key)); - mbedtls_platform_zeroize(iv, sizeof(iv)); - mbedtls_platform_zeroize(encrypted_sk, sizeof(encrypted_sk)); - mbedtls_platform_zeroize(rev_sk, sizeof(rev_sk)); - - return ret; -} - -static void felica_auth_context_free(felica_auth_context_t *auth_ctx) { - if (!auth_ctx) { - return; - } - - mbedtls_platform_zeroize(auth_ctx->session_key, sizeof(auth_ctx->session_key)); - mbedtls_platform_zeroize(auth_ctx->random_challenge, sizeof(auth_ctx->random_challenge)); -} - -static int felica_generate_mac( - mbedtls_des3_context *ctx, - const felica_auth_context_t *auth_ctx, - const uint8_t *initialize_block, - const uint8_t *block_data, - const size_t length, - bool use_read_key, - uint8_t *mac) { - - int ret = PM3_SUCCESS; - - uint8_t rev_sk[FELICA_BLK_SIZE]; - uint8_t iv[8], rev_block[8], out[8]; - - if (!ctx || !auth_ctx || !initialize_block || !block_data || !mac) { - return PM3_EINVARG; - } - - if (length % FELICA_BLK_HALF != 0) { - return PM3_EINVARG; - } - - uint8_t sk[FELICA_BLK_SIZE]; - - if (use_read_key == false) { - memcpy(sk, auth_ctx->session_key + 8, 8); - memcpy(sk + 8, auth_ctx->session_key, 8); - } else { - memcpy(sk, auth_ctx->session_key, sizeof(auth_ctx->session_key)); - } - - SwapEndian64ex(sk, sizeof(sk), 8, rev_sk); - - memcpy(iv, auth_ctx->random_challenge, sizeof(iv)); - - SwapEndian64ex(initialize_block, sizeof(rev_block), 8, rev_block); - - if (mbedtls_des3_set2key_enc(ctx, rev_sk) != 0) { - ret = PM3_ECRYPTO; - goto cleanup; - } - - for (int i = 0; i <= length; i += 8) { - if (mbedtls_des3_crypt_cbc(ctx, MBEDTLS_DES_ENCRYPT, sizeof(rev_block), iv, rev_block, out) != 0) { - ret = PM3_ECRYPTO; - goto cleanup; - } - memcpy(iv, out, sizeof(iv)); - SwapEndian64ex(block_data + i, 8, 8, rev_block); - } - - SwapEndian64ex(out, FELICA_BLK_HALF, 8, mac); - -cleanup: - mbedtls_platform_zeroize(sk, sizeof(sk)); - mbedtls_platform_zeroize(rev_sk, sizeof(rev_sk)); - mbedtls_platform_zeroize(iv, sizeof(iv)); - mbedtls_platform_zeroize(out, sizeof(out)); - mbedtls_platform_zeroize(rev_block, sizeof(rev_block)); - - return ret; -} - -static int write_with_mac( - mbedtls_des3_context *ctx, - const felica_auth_context_t *auth_ctx, - const uint8_t *counter, - const uint8_t blk_number, - const uint8_t *block_data, - uint8_t *out) { - - uint8_t initialize_blk[FELICA_BLK_HALF]; - memset(initialize_blk, 0, sizeof(initialize_blk)); - - uint8_t wcnt[3]; - memcpy(wcnt, counter, 3); - - memcpy(initialize_blk, wcnt, sizeof(wcnt)); - initialize_blk[4] = blk_number; - initialize_blk[6] = 0x91; - - uint8_t mac[FELICA_BLK_HALF]; - - int ret = felica_generate_mac(ctx, auth_ctx, initialize_blk, block_data, FELICA_BLK_SIZE, false, mac); - if (ret != PM3_SUCCESS) { - return ret; - } - - uint8_t payload[FELICA_BLK_SIZE * 2]; - memset(payload, 0, sizeof(payload)); - - memcpy(payload, block_data, FELICA_BLK_SIZE); - memcpy(payload + FELICA_BLK_SIZE, mac, sizeof(mac)); - memcpy(payload + FELICA_BLK_SIZE + sizeof(mac), wcnt, sizeof(wcnt)); - - memcpy(out, payload, sizeof(payload)); - - return PM3_SUCCESS; -} - -static int felica_internal_authentication( - const uint8_t *idm, - const uint8_t *rc, - const size_t rclen, - mbedtls_des3_context *ctx, - const felica_auth_context_t *auth_ctx, - bool verbose) { - - uint8_t data[PM3_CMD_DATA_SIZE]; - memset(data, 0, sizeof(data)); - - uint8_t blk_numbers[1] = {FELICA_BLK_NUMBER_RC}; - - uint16_t datalen = 0; - - int ret = write_without_encryption(idm, (uint8_t)sizeof(blk_numbers), blk_numbers, rc, rclen, data, &datalen); - if (ret) { - return PM3_ERFTRANS; - } - - AddCrc(data, datalen); - datalen += 2; - - uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW | FELICA_NO_DISCONNECT); - - felica_status_response_t res; - if (send_wr_plain(flags, datalen, data, false, &res) != PM3_SUCCESS) { - return PM3_ERFTRANS; - } - - if (res.status_flags.status_flag1[0] != 0x00 && res.status_flags.status_flag2[0] != 0x00) { - PrintAndLogEx(ERR, "\nError RC Write"); - return PM3_ERFTRANS; - } - - memset(data, 0, sizeof(data)); - - uint8_t blk_numbers2[2] = {FELICA_BLK_NUMBER_ID, FELICA_BLK_NUMBER_MACA}; - - ret = read_without_encryption(idm, (uint8_t)sizeof(blk_numbers2), blk_numbers2, data, &datalen); - if (ret) { - return PM3_ERFTRANS; - } - - AddCrc(data, datalen); - datalen += 2; - - uint8_t pd[FELICA_BLK_SIZE * sizeof(blk_numbers2)]; - memset(pd, 0, sizeof(pd)); - - ret = send_rd_multiple_plain(flags, datalen, data, pd); - if (ret) { - return PM3_ERFTRANS; - } - - uint8_t id_blk[FELICA_BLK_SIZE]; - memcpy(id_blk, pd, FELICA_BLK_SIZE); - - uint8_t mac_blk[FELICA_BLK_SIZE]; - memcpy(mac_blk, pd + FELICA_BLK_SIZE, FELICA_BLK_SIZE); - - uint8_t initialize_blk[8]; - memset(initialize_blk, 0xFF, sizeof(initialize_blk)); - - initialize_blk[0] = FELICA_BLK_NUMBER_ID; - initialize_blk[1] = 0x00; - initialize_blk[2] = FELICA_BLK_NUMBER_MACA; - initialize_blk[3] = 0x00; - - uint8_t mac[FELICA_BLK_HALF]; - - ret = felica_generate_mac(ctx, auth_ctx, initialize_blk, id_blk, sizeof(id_blk), true, mac); - if (ret) { - return PM3_ERFTRANS; - } - - if (verbose) { - PrintAndLogEx(SUCCESS, "MAC_A: %s", sprint_hex(mac, sizeof(mac))); - } - - if (memcmp(mac_blk, mac, FELICA_BLK_HALF) != 0) { - PrintAndLogEx(ERR, "\nInternal Authenticate: " _RED_("Failed")); - return PM3_ERFTRANS; - } - - PrintAndLogEx(SUCCESS, "Internal Authenticate: " _GREEN_("OK")); - - return PM3_SUCCESS; -} - -static int felica_external_authentication( - const uint8_t *idm, - mbedtls_des3_context *ctx, - const felica_auth_context_t *auth_ctx, - bool keep) { - - uint8_t data[PM3_CMD_DATA_SIZE_MIX]; - memset(data, 0, sizeof(data)); - - uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW | FELICA_NO_DISCONNECT); - - uint16_t datalen = 0; - - uint8_t blk_numbers[1] = {FELICA_BLK_NUMBER_WCNT}; - - int ret = read_without_encryption(idm, (uint8_t)sizeof(blk_numbers), blk_numbers, data, &datalen); - if (ret) { - return PM3_ERFTRANS; - } - - AddCrc(data, datalen); - datalen += 2; - - uint8_t wcnt_blk[FELICA_BLK_SIZE]; - ret = send_rd_multiple_plain(flags, datalen, data, wcnt_blk); - if (ret) { - return PM3_ERFTRANS; - } - - uint8_t ext_auth[FELICA_BLK_SIZE]; - memset(ext_auth, 0, sizeof(ext_auth)); - - ext_auth[0] = 1; // After Authenticate - - uint8_t mac_w[FELICA_BLK_SIZE * 2]; - - ret = write_with_mac(ctx, auth_ctx, wcnt_blk, FELICA_BLK_NUMBER_STATE, ext_auth, mac_w); - if (ret) { - return PM3_ERFTRANS; - } - - uint8_t blk_numbers2[2] = {FELICA_BLK_NUMBER_STATE, FELICA_BLK_NUMBER_MACA}; - - ret = write_without_encryption(idm, (uint8_t)sizeof(blk_numbers2), blk_numbers2, mac_w, sizeof(mac_w), data, &datalen); - if (ret) { - return PM3_ERFTRANS; - } - - AddCrc(data, datalen); - datalen += 2; - - if (keep == false) { - flags &= ~FELICA_NO_DISCONNECT; - } - - felica_status_response_t res; - if (send_wr_plain(flags, datalen, data, false, &res) != PM3_SUCCESS) { - return PM3_ERFTRANS; - } - - if (res.status_flags.status_flag1[0] != 0x00 && res.status_flags.status_flag2[0] != 0x00) { - PrintAndLogEx(ERR, "\nExternal Authenticate: " _RED_("Failed")); - return PM3_ERFTRANS; - } - - PrintAndLogEx(SUCCESS, "External Authenticate: " _GREEN_("OK")); - - return PM3_SUCCESS; -} - -static int felica_mutual_authentication( - const uint8_t *idm, - const uint8_t *rc, - const size_t rclen, - const uint8_t *key, - const size_t keylen, - bool keep, - bool verbose) { - - int ret = PM3_SUCCESS; - - mbedtls_des3_context des3_ctx; - mbedtls_des3_init(&des3_ctx); - - felica_auth_context_t auth_ctx; - - ret = felica_auth_context_init(&des3_ctx, rc, rclen, key, keylen, &auth_ctx); - if (ret) { - goto cleanup; - } - - if (verbose) { - PrintAndLogEx(INFO, "Session Key(SK): %s", sprint_hex(auth_ctx.session_key, sizeof(auth_ctx.session_key))); - } - - ret = felica_internal_authentication(idm, rc, rclen, &des3_ctx, &auth_ctx, verbose); - if (ret) { - goto cleanup; - } - - ret = felica_external_authentication(idm, &des3_ctx, &auth_ctx, keep); - if (ret) { - goto cleanup; - } - -cleanup: - mbedtls_des3_free(&des3_ctx); - felica_auth_context_free(&auth_ctx); - - return ret; -} - -/** - * Command parser for liteauth. - * @param Cmd input data of the user. - * @return client result code. - */ -static int CmdHFFelicaAuthenticationLite(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf felica liteauth", - "Authenticate", - "hf felica liteauth -i 11100910C11BC407\n" - "hf felica liteauth --key 46656c69436130313233343536616263\n" - "hf felica liteauth --key 46656c69436130313233343536616263 -k\n" - "hf felica liteauth -c 701185c59f8d30afeab8e4b3a61f5cc4 --key 46656c69436130313233343536616263" - ); - void *argtable[] = { - arg_param_begin, - arg_str0(NULL, "key", "", "set card key, 16 bytes"), - arg_str0("c", "", "", "set random challenge, 16 bytes"), - arg_str0("i", "", "", "set custom IDm"), - arg_lit0("k", "", "keep signal field ON after receive"), - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, true); - - uint8_t key[FELICA_BLK_SIZE]; - memset(key, 0, sizeof(key)); - int keylen = 0; - int res = CLIParamHexToBuf(arg_get_str(ctx, 1), key, sizeof(key), &keylen); - if (res) { - CLIParserFree(ctx); - return PM3_EINVARG; - } - - uint8_t rc[FELICA_BLK_SIZE]; - memset(rc, 0, sizeof(rc)); - int rclen = 0; - res = CLIParamHexToBuf(arg_get_str(ctx, 2), rc, sizeof(rc), &rclen); - if (res) { - CLIParserFree(ctx); - return PM3_EINVARG; - } - - uint8_t idm[8]; - memset(idm, 0, sizeof(idm)); - int ilen = 0; - res = CLIParamHexToBuf(arg_get_str(ctx, 3), idm, sizeof(idm), &ilen); - if (res) { - CLIParserFree(ctx); - return PM3_EINVARG; - } - - bool keep_field_on = arg_get_lit(ctx, 4); - - CLIParserFree(ctx); - - if (!ilen) { - if (last_known_card.IDm[0] != 0 && last_known_card.IDm[1] != 0) { - memcpy(idm, last_known_card.IDm, sizeof(idm)); - } else { - PrintAndLogEx(WARNING, "No last known card! Use `" _YELLOW_("hf felica reader") "` first or set a custom IDm"); - return PM3_EINVARG; - } - } - - int ret = PM3_SUCCESS; - - PrintAndLogEx(INFO, "Card Key: %s", sprint_hex(key, sizeof(key))); - PrintAndLogEx(INFO, "Random Challenge(RC): %s", sprint_hex(rc, sizeof(rc))); - - PrintAndLogEx(SUCCESS, "FeliCa lite - auth started"); - - ret = felica_mutual_authentication(idm, rc, sizeof(rc), key, sizeof(key), keep_field_on, true); - if (ret) { - return PM3_EINVARG; - } - - return PM3_SUCCESS; -} - static void printSep(void) { PrintAndLogEx(INFO, "------------------------------------------------------------------------------------"); } @@ -2777,15 +1881,9 @@ static uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t trac uint8_t status1 = trace[1]; uint8_t status2 = trace[2]; - bool error = (status1 != 0x00 && (status2 == 0xB1 || status2 == 0xB2)); - char line[110] = {0}; for (int j = 0; j < 16; j++) { - if (error) { - snprintf(line + (j * 4), sizeof(line) - 1 - (j * 4), "?? "); - } else { - snprintf(line + (j * 4), sizeof(line) - 1 - (j * 4), "%02x ", trace[j + 3]); - } + snprintf(line + (j * 4), sizeof(line) - 1 - (j * 4), "%02x ", trace[j + 3]); } PrintAndLogEx(NORMAL, "block number %02x, status: %02x %02x", blocknum, status1, status2); @@ -2833,17 +1931,13 @@ static uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t trac PrintAndLogEx(NORMAL, "S_PAD13: %s", line); break; case 0x0E: { - uint32_t regA = trace[3] | trace[4] << 8 | trace[5] << 16 | trace[6] << 24; + uint32_t regA = trace[3] | trace[4] << 8 | trace[5] << 16 | trace[ 6] << 24; uint32_t regB = trace[7] | trace[8] << 8 | trace[9] << 16 | trace[10] << 24; line[0] = 0; for (int j = 0; j < 8; j++) snprintf(line + (j * 2), sizeof(line) - 1 - (j * 2), "%02x", trace[j + 11]); - if (error) { - PrintAndLogEx(NORMAL, "REG: regA: ???????? regB: ???????? regC: ???????????????? "); - } else { - PrintAndLogEx(NORMAL, "REG: regA: %d regB: %d regC: %s ", regA, regB, line); - } + PrintAndLogEx(NORMAL, "REG: regA: %d regB: %d regC: %s ", regA, regB, line); } break; case 0x80: @@ -2903,7 +1997,7 @@ static uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t trac } break; case 0x90: { - PrintAndLogEx(NORMAL, "Write counter, RO: %02x %02x %02x ", trace[3], trace[4], trace[5]); + PrintAndLogEx(NORMAL, "Write count, RO: %02x %02x %02x ", trace[3], trace[4], trace[5]); } break; case 0x91: { @@ -2942,52 +2036,11 @@ static int CmdHFFelicaDumpLite(const char *Cmd) { ); void *argtable[] = { arg_param_begin, - arg_str0("i", "", "", "set custom IDm"), - arg_str0(NULL, "key", "", "set card key, 16 bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - - uint8_t idm[8]; - memset(idm, 0, sizeof(idm)); - int ilen = 0; - int res = CLIParamHexToBuf(arg_get_str(ctx, 1), idm, sizeof(idm), &ilen); - if (res) { - CLIParserFree(ctx); - return PM3_EINVARG; - } - - uint8_t key[FELICA_BLK_SIZE]; - memset(key, 0, sizeof(key)); - int keylen = 0; - res = CLIParamHexToBuf(arg_get_str(ctx, 2), key, sizeof(key), &keylen); - if (res) { - CLIParserFree(ctx); - return PM3_EINVARG; - } - CLIParserFree(ctx); - if (keylen != 0) { - if (!ilen) { - if (last_known_card.IDm[0] != 0 && last_known_card.IDm[1] != 0) { - memcpy(idm, last_known_card.IDm, sizeof(idm)); - } else { - PrintAndLogEx(WARNING, "No last known card! Use `" _YELLOW_("hf felica reader") "` first or set a custom IDm"); - return PM3_EINVARG; - } - } - - uint8_t rc[FELICA_BLK_SIZE] = {0}; - - int ret = felica_mutual_authentication(idm, rc, sizeof(rc), key, sizeof(key), true, false); - if (ret) { - PrintAndLogEx(WARNING, "Authenticate Failed"); - } - } - - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "FeliCa lite - dump started"); clearCommandBuffer(); @@ -3001,7 +2054,7 @@ static int CmdHFFelicaDumpLite(const char *Cmd) { if (kbd_enter_pressed()) { SendCommandNG(CMD_BREAK_LOOP, NULL, 0); - PrintAndLogEx(DEBUG, "\naborted via keyboard!"); + PrintAndLogEx(DEBUG, "User aborted"); return PM3_EOPABORTED; } @@ -3158,10 +2211,10 @@ static command_t CommandTable[] = { {"sniff", CmdHFFelicaSniff, IfPm3Felica, "Sniff ISO 18092/FeliCa traffic"}, {"wrbl", CmdHFFelicaWritePlain, IfPm3Felica, "write block data to an authentication-not-required Service."}, {"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("FeliCa Standard") " -----------------------"}, - {"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"}, + //{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"}, {"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."}, {"rqresponse", CmdHFFelicaRequestResponse, IfPm3Felica, "verify the existence of a card and its Mode."}, - {"scsvcode", CmdHFFelicaDumpServiceArea, IfPm3Felica, "acquire Area Code and Service Code."}, + {"scsvcode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire Area Code and Service Code."}, {"rqsyscode", CmdHFFelicaRequestSystemCode, IfPm3Felica, "acquire System Code registered to the card."}, {"auth1", CmdHFFelicaAuthentication1, IfPm3Felica, "authenticate a card. Start mutual authentication with Auth1"}, {"auth2", CmdHFFelicaAuthentication2, IfPm3Felica, "allow a card to authenticate a Reader/Writer. Complete mutual authentication"}, @@ -3178,7 +2231,6 @@ static command_t CommandTable[] = { //{"uprandomid", CmdHFFelicaNotImplementedYet, IfPm3Felica, "update Random ID (IDr)."}, {"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("FeliCa Light") " -----------------------"}, {"litesim", CmdHFFelicaSimLite, IfPm3Felica, "Emulating ISO/18092 FeliCa Lite tag"}, - {"liteauth", CmdHFFelicaAuthenticationLite, IfPm3Felica, "authenticate a card."}, {"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"}, // {"sim", CmdHFFelicaSim, IfPm3Felica, " -- Simulate ISO 18092/FeliCa tag"} {NULL, NULL, NULL, NULL} diff --git a/client/src/cmdhffelica.h b/client/src/cmdhffelica.h index 6ab42aa36..9cb524814 100644 --- a/client/src/cmdhffelica.h +++ b/client/src/cmdhffelica.h @@ -26,6 +26,5 @@ int CmdHFFelica(const char *Cmd); int read_felica_uid(bool loop, bool verbose); int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose); int send_rd_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp); -int send_dump_sv_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_service_dump_response_t *dump_sv_resp, bool is_area); #endif diff --git a/client/src/cmdhffudan.c b/client/src/cmdhffudan.c index 817749353..52ed3bc5f 100644 --- a/client/src/cmdhffudan.c +++ b/client/src/cmdhffudan.c @@ -199,7 +199,7 @@ int read_fudan_uid(bool loop, bool verbose) { PrintAndLogEx(NORMAL, ""); } - } while (loop && (kbd_enter_pressed() == false)); + } while (loop && kbd_enter_pressed() == false); return PM3_SUCCESS; diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index d4bc1da45..4c945153e 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -1135,7 +1135,7 @@ int read_iclass_csn(bool loop, bool verbose, bool shallow_mod) { res = PM3_EMALLOC; } } - } while (loop && (kbd_enter_pressed() == false)); + } while (loop && kbd_enter_pressed() == false); DropField(); return res; @@ -2130,9 +2130,8 @@ static int CmdHFiClassDump(const char *Cmd) { return PM3_EOPABORTED; } - if (WaitForResponseTimeout(CMD_HF_ICLASS_DUMP, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_HF_ICLASS_DUMP, &resp, 2000)) break; - } } PrintAndLogEx(NORMAL, ""); @@ -2329,7 +2328,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { arg_lit0(NULL, "credit", "key is assumed to be the credit key"), arg_lit0(NULL, "elite", "elite computations applied to key"), arg_lit0(NULL, "raw", "no computations applied to key"), - arg_lit0(NULL, "nr", "replay of NR/MAC block write or use privilege escalation if mac is empty"), + arg_lit0(NULL, "nr", "replay of NR/MAC"), arg_lit0("v", "verbose", "verbose output"), arg_lit0(NULL, "shallow", "use shallow (ASK) reader modulation instead of OOK"), arg_param_end @@ -2569,7 +2568,6 @@ static int CmdHFiClassRestore(const char *Cmd) { arg_lit0(NULL, "raw", "no computations applied to key"), arg_lit0("v", "verbose", "verbose output"), arg_lit0(NULL, "shallow", "use shallow (ASK) reader modulation instead of OOK"), - arg_lit0(NULL, "nr", "replay of nr mac with privilege escalation"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -2620,7 +2618,6 @@ static int CmdHFiClassRestore(const char *Cmd) { bool rawkey = arg_get_lit(ctx, 8); bool verbose = arg_get_lit(ctx, 9); bool shallow_mod = arg_get_lit(ctx, 10); - bool use_replay = arg_get_lit(ctx, 11); CLIParserFree(ctx); @@ -2667,7 +2664,7 @@ static int CmdHFiClassRestore(const char *Cmd) { payload->req.use_raw = rawkey; payload->req.use_elite = elite; payload->req.use_credit_key = use_credit_key; - payload->req.use_replay = use_replay; + payload->req.use_replay = false; payload->req.blockno = startblock; payload->req.send_reply = true; payload->req.do_auth = true; @@ -4611,7 +4608,7 @@ static int iclass_recover(uint8_t key[8], uint32_t index_start, uint32_t loop, u repeat = false; } else if (resp.status == PM3_EOPABORTED) { PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(WARNING, "iCLASS Key Bits Recovery: " _YELLOW_("aborted via keyboard!")); + PrintAndLogEx(WARNING, "iCLASS Key Bits Recovery: " _YELLOW_("user aborted")); repeat = false; } else if (resp.status == PM3_ESOFT) { PrintAndLogEx(NORMAL, ""); @@ -5060,24 +5057,6 @@ static int CmdHFiClassUnhash(const char *Cmd) { return PM3_EINVARG; } - //check if divkey respects hash0 rules (legacy format) or if it could be AES Based - - int count_lsb0 = 0; - int count_lsb1 = 0; - - for (int i = 0; i < PICOPASS_BLOCK_SIZE; i++) { - if ((div_key[i] & 0x01) == 0) { - count_lsb0++; - } else { - count_lsb1++; - } - } - - if (count_lsb0 != 4 || count_lsb1 != 4) { - PrintAndLogEx(INFO, _RED_("Incorrect LSB Distribution, unable to unhash - the key might be AES based.")); - return PM3_SUCCESS; - } - PrintAndLogEx(INFO, "Diversified key... %s", sprint_hex_inrow(div_key, sizeof(div_key))); PrintAndLogEx(INFO, "-----------------------------------"); invert_hash0(div_key); @@ -5230,7 +5209,7 @@ static int CmdHFiClassLookUp(const char *Cmd) { item = (iclass_prekey_t *) bsearch(&lookup, prekey, keycount, sizeof(iclass_prekey_t), cmp_uint32); if (item != NULL) { - PrintAndLogEx(SUCCESS, "Found valid key " _GREEN_("%s"), sprint_hex_inrow(item->key, 8)); + PrintAndLogEx(SUCCESS, "Found valid key " _GREEN_("%s"), sprint_hex(item->key, 8)); add_key(item->key); } @@ -5906,15 +5885,6 @@ static int CmdHFiClassConfigCard(const char *Cmd) { return PM3_SUCCESS; } -static bool match_with_wildcard(const uint8_t *data, const uint8_t *pattern, const bool *mask, size_t length) { - for (size_t i = 0; i < length; ++i) { - if (mask[i] && data[i] != pattern[i]) { - return false; - } - } - return true; -} - static int CmdHFiClassSAM(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf iclass sam", @@ -5934,7 +5904,6 @@ static int CmdHFiClassSAM(const char *Cmd) { arg_lit0("p", "prevent", "fake epurse update"), arg_lit0(NULL, "shallow", "shallow mod"), arg_strx0("d", "data", "", "DER encoded command to send to SAM"), - arg_lit0("s", "snmp", "data is in snmp format without headers"), arg_lit0(NULL, "info", "get SAM infos (version, serial number)"), arg_param_end }; @@ -5947,8 +5916,7 @@ static int CmdHFiClassSAM(const char *Cmd) { bool break_nrmac = arg_get_lit(ctx, 5); bool prevent = arg_get_lit(ctx, 6); bool shallow_mod = arg_get_lit(ctx, 7); - bool snmp_data = arg_get_lit(ctx, 9); - bool info = arg_get_lit(ctx, 10); + bool info = arg_get_lit(ctx, 9); uint8_t flags = 0; if (disconnect_after) { @@ -5990,25 +5958,11 @@ static int CmdHFiClassSAM(const char *Cmd) { return PM3_ESOFT; } - if (snmp_data) { - uint8_t header[4] = {0xa0, cmdlen + 2, 0x94, cmdlen }; - memmove(data + 4, data, cmdlen + 1); - data[0] = flags; - memcpy(data + 1, header, 4); - cmdlen += 4; - } - clearCommandBuffer(); SendCommandNG(CMD_HF_SAM_PICOPASS, data, cmdlen + 1); PacketResponseNG resp; WaitForResponse(CMD_HF_SAM_PICOPASS, &resp); - bool is_snmp = false; - uint8_t snmp_pattern[] = {0xBD, 0x81, 0xFF, 0x8A, 0x81, 0xFF}; // SNMP Response header pattern, 0xFF is a wildcard value for message length - bool snmp_mask[] = {true, true, false, true, true, false}; // false means wildcard value in that position - uint8_t ok_pattern[] = {0xBD, 0xFF, 0x8A}; // Ok response header pattern, 0xFF is a wildcard value for message length - bool ok_mask[] = {true, false, true}; // false means wildcard value in that position - switch (resp.status) { case PM3_SUCCESS: break; @@ -6067,24 +6021,11 @@ static int CmdHFiClassSAM(const char *Cmd) { PrintAndLogEx(SUCCESS, " hf iclass dump --nr -k %s", sprint_hex_inrow(d + 1, 8)); } } else { - //if it is an error decode it - if (memcmp(d, "\xBE\x07\x80\x01", 4) == 0) { //if it the string is 0xbe 0x07 0x80 0x01 the next byte will indicate the error code - PrintAndLogEx(ERR, _RED_("Sam Error Code: %02x"), d[4]); - print_hex(d, resp.length); - } else if (match_with_wildcard(d, snmp_pattern, snmp_mask, 6)) { - is_snmp = true; - PrintAndLogEx(SUCCESS, _YELLOW_("[samSNMPMessageResponse] ")"%s", sprint_hex(d + 6, resp.length - 6)); - } else if (match_with_wildcard(d, ok_pattern, ok_mask, 3)) { - PrintAndLogEx(SUCCESS, _YELLOW_("[samResponseAcknowledge] ")"%s", sprint_hex(d + 4, resp.length - 4)); - } else { - print_hex(d, resp.length); - } + print_hex(d, resp.length); } - if (decodeTLV && is_snmp == false) { + if (decodeTLV) { asn1_print(d, d[1] + 2, " "); - } else if (decodeTLV && is_snmp) { - asn1_print(d + 6, resp.length - 6, " "); } return PM3_SUCCESS; diff --git a/client/src/cmdhfjooki.c b/client/src/cmdhfjooki.c index 81e7b3546..51f61e619 100644 --- a/client/src/cmdhfjooki.c +++ b/client/src/cmdhfjooki.c @@ -584,7 +584,7 @@ static int CmdHF14AJookiSim(const char *Cmd) { for (;;) { if (kbd_enter_pressed()) { SendCommandNG(CMD_BREAK_LOOP, NULL, 0); - PrintAndLogEx(DEBUG, "\naborted via keyboard!"); + PrintAndLogEx(DEBUG, "User aborted"); break; } diff --git a/client/src/cmdhflegic.c b/client/src/cmdhflegic.c index f47466761..0ff062532 100644 --- a/client/src/cmdhflegic.c +++ b/client/src/cmdhflegic.c @@ -560,7 +560,7 @@ static int CmdLegicSim(const char *Cmd) { for (;;) { if (kbd_enter_pressed()) { SendCommandNG(CMD_BREAK_LOOP, NULL, 0); - PrintAndLogEx(DEBUG, "Aborted via keyboard!"); + PrintAndLogEx(DEBUG, "User aborted"); break; } @@ -781,20 +781,17 @@ int legic_print_type(uint32_t tagtype, uint8_t spaces) { } int legic_get_type(legic_card_select_t *card) { - if (card == NULL) { + if (card == NULL) return PM3_EINVARG; - } clearCommandBuffer(); SendCommandNG(CMD_HF_LEGIC_INFO, NULL, 0); PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_HF_LEGIC_INFO, &resp, 1500) == false) { + if (WaitForResponseTimeout(CMD_HF_LEGIC_INFO, &resp, 1500) == false) return PM3_ETIMEOUT; - } - if (resp.status != PM3_SUCCESS) { + if (resp.status != PM3_SUCCESS) return PM3_ESOFT; - } memcpy(card, resp.data.asBytes, sizeof(legic_card_select_t)); return PM3_SUCCESS; @@ -1530,7 +1527,7 @@ int readLegicUid(bool loop, bool verbose) { PrintAndLogEx(SUCCESS, " MSN: " _GREEN_("%s"), sprint_hex(card.uid + 1, sizeof(card.uid) - 1)); legic_print_type(card.cardsize, 0); - } while (loop && (kbd_enter_pressed() == false)); + } while (loop && kbd_enter_pressed() == false); return PM3_SUCCESS; } diff --git a/client/src/cmdhflto.c b/client/src/cmdhflto.c index 1eadb3d67..51ede17ca 100644 --- a/client/src/cmdhflto.c +++ b/client/src/cmdhflto.c @@ -438,7 +438,7 @@ int reader_lto(bool loop, bool verbose) { PrintAndLogEx(INFO, "UID......... " _GREEN_("%s"), sprint_hex_inrow(serial, sizeof(serial))); } - } while (loop && (kbd_enter_pressed() == false)); + } while (loop && kbd_enter_pressed() == false); lto_switch_off_field(); return ret; diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index e35b6e18f..68a9eb044 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -63,8 +63,6 @@ typedef struct { const char *level_name; } SaflokKeyLevel; -static int CmdHelp(const char *Cmd); - // Static array for Saflok key levels static const SaflokKeyLevel saflok_key_levels[] = { {1, "Guest Key"}, @@ -220,8 +218,9 @@ static void ParseAndPrintSaflokData(const sector_t *sector0_info, const sector_t uint8_t key_id = decodedBA[1]; // Byte 2 & 3: KeyRecord, including OpeningKey flag + uint8_t key_record_high = decodedBA[2] & 0x7F; uint8_t opening_key = (decodedBA[2] & 0x80) >> 7; - uint16_t key_record = ((decodedBA[2] & 0x3F) << 8) | decodedBA[3]; + uint16_t key_record = (key_record_high << 8) | decodedBA[3]; // Byte 5 & 6: EncryptSequence + Combination uint16_t sequence_combination_number = ((decodedBA[5] & 0x0F) << 8) | decodedBA[6]; @@ -267,7 +266,7 @@ static void ParseAndPrintSaflokData(const sector_t *sector0_info, const sector_t uint16_t property_id = ((decodedBA[14] & 0x0F) << 8) | decodedBA[15]; // Bytes 11-13: Creation date since SAFLOK_YEAR_OFFSET Jan 1st - uint16_t creation_year = (creation_year_high_bits | (decodedBA[11] >> 4)) + SAFLOK_YEAR_OFFSET; + uint16_t creation_year = (((decodedBA[11] & 0xF0) >> 4) + SAFLOK_YEAR_OFFSET) | creation_year_high_bits; uint8_t creation_month = decodedBA[11] & 0x0F; uint8_t creation_day = (decodedBA[12] >> 3) & 0x1F; uint8_t creation_hour = ((decodedBA[12] & 0x07) << 2) | ((decodedBA[13] & 0xC0) >> 6); @@ -329,7 +328,7 @@ static void ParseAndPrintSaflokData(const sector_t *sector0_info, const sector_t bool checksum_valid = (checksum_calculated == checksum); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("Saflok details")); + PrintAndLogEx(INFO, "--- " _CYAN_("SAFLOK details")); PrintAndLogEx(SUCCESS, "Key Level............. %u (%s)", saflok_key_levels[key_level].level_num, saflok_key_levels[key_level].level_name); PrintAndLogEx(SUCCESS, "LED Warning........... %s", led_warning ? "Yes" : "No"); PrintAndLogEx(SUCCESS, "Key ID................ %u (0x%02X)", key_id, key_id); @@ -344,6 +343,10 @@ static void ParseAndPrintSaflokData(const sector_t *sector0_info, const sector_t PrintAndLogEx(SUCCESS, "Checksum Valid........ ( %s )", checksum_valid ? _GREEN_("ok") : _RED_("fail")); } + + +static int CmdHelp(const char *Cmd); + /* static int usage_hf14_keybrute(void) { PrintAndLogEx(NORMAL, "J_Run's 2nd phase of multiple sector nested authentication key recovery"); @@ -433,10 +436,9 @@ static int mf_read_uid(uint8_t *uid, int *uidlen, int *nxptype) { } static char *GenerateFilename(const char *prefix, const char *suffix) { - if (IfPm3Iso14443a() == false) { + if (! IfPm3Iso14443a()) { return NULL; } - uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int uidlen = 0; char *fptr = calloc(sizeof(char) * (strlen(prefix) + strlen(suffix)) + sizeof(uid) * 2 + 1, sizeof(uint8_t)); @@ -925,7 +927,7 @@ static int mfc_read_tag(iso14a_card_select_t *card, uint8_t *carddata, uint8_t n size_t alen = 0, blen = 0; uint8_t *keyA = NULL, *keyB = NULL; - if (loadFileBinaryKey(keyfn, "", (void **)&keyA, (void **)&keyB, &alen, &blen, true) != PM3_SUCCESS) { + if (loadFileBinaryKey(keyfn, "", (void **)&keyA, (void **)&keyB, &alen, &blen) != PM3_SUCCESS) { free(fptr); return PM3_ESOFT; } @@ -1128,9 +1130,9 @@ static int mf_load_keys(uint8_t **pkeyBlock, uint32_t *pkeycnt, uint8_t *userkey } *pkeyBlock = p; // Copy default keys to list - for (uint32_t i = 0; i < ARRAYLEN(g_mifare_default_keys); i++) { + for (int i = 0; i < ARRAYLEN(g_mifare_default_keys); i++) { num_to_bytes(g_mifare_default_keys[i], MIFARE_KEY_SIZE, (uint8_t *)(*pkeyBlock + (*pkeycnt + i) * MIFARE_KEY_SIZE)); - PrintAndLogEx(DEBUG, _YELLOW_("%2u") " - %s", *pkeycnt + i, sprint_hex(*pkeyBlock + (*pkeycnt + i) * MIFARE_KEY_SIZE, MIFARE_KEY_SIZE)); + PrintAndLogEx(DEBUG, _YELLOW_("%2d") " - %s", *pkeycnt + i, sprint_hex(*pkeyBlock + (*pkeycnt + i) * MIFARE_KEY_SIZE, MIFARE_KEY_SIZE)); } *pkeycnt += ARRAYLEN(g_mifare_default_keys); PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%zu") " hardcoded keys", ARRAYLEN(g_mifare_default_keys)); @@ -1246,15 +1248,13 @@ static int CmdHF14AMfDarkside(const char *Cmd) { uint64_t key = 0; uint64_t t1 = msclock(); - int res = mf_dark_side(blockno, key_type, &key); + int ret = mf_dark_side(blockno, key_type, &key); t1 = msclock() - t1; - if (res != PM3_SUCCESS) { - return res; - } + if (ret != PM3_SUCCESS) return ret; - PrintAndLogEx(SUCCESS, "Found valid key [ "_GREEN_("%012" PRIX64) " ]", key); - PrintAndLogEx(SUCCESS, "Time in darkside " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0); + PrintAndLogEx(SUCCESS, "found valid key: " _GREEN_("%012" PRIx64), key); + PrintAndLogEx(SUCCESS, "time in darkside " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0); return PM3_SUCCESS; } @@ -1566,7 +1566,7 @@ static int FastDumpWithEcFill(uint8_t numsectors) { } if (resp.status != PM3_SUCCESS) { - PrintAndLogEx(FAILED, "fast dump reported back failure w KEY A. Swapping to KEY B"); + PrintAndLogEx(FAILED, "fast dump reported back failure w KEY A, swapping to KEY B"); // ecfill key B payload.keytype = MF_KEY_B; @@ -1824,10 +1824,12 @@ static int CmdHF14AMfRestore(const char *Cmd) { // size_t alen = 0, blen = 0; uint8_t *keyA, *keyB; - if (loadFileBinaryKey(keyfilename, "", (void **)&keyA, (void **)&keyB, &alen, &blen, true) != PM3_SUCCESS) { + if (loadFileBinaryKey(keyfilename, "", (void **)&keyA, (void **)&keyB, &alen, &blen) != PM3_SUCCESS) { return PM3_ESOFT; } + PrintAndLogEx(INFO, "Using key file `" _YELLOW_("%s") "`", keyfilename); + // try reading card uid and create filename if (datafnlen == 0) { char *fptr = GenerateFilename("hf-mf-", "-dump.bin"); @@ -2006,7 +2008,7 @@ static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't CLIExecWithReturn(ctx, Cmd, argtable, false); int keylen = 0; - uint8_t key[MIFARE_KEY_SIZE] = {0}; + uint8_t key[6] = {0}; CLIGetHexWithReturn(ctx, 1, key, &keylen); bool m0 = arg_get_lit(ctx, 2); @@ -2025,7 +2027,6 @@ static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't } else if (arg_get_lit(ctx, 8)) { keyType = MF_KEY_B; } - uint8_t prev_keytype = keyType; keyType = arg_get_int_def(ctx, 9, keyType); if ((arg_get_lit(ctx, 7) || arg_get_lit(ctx, 8)) && (keyType != prev_keytype)) { @@ -2045,16 +2046,13 @@ static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't } else if (arg_get_lit(ctx, 12)) { trgKeyType = MF_KEY_B; } - uint8_t prev_trgkeytype = trgKeyType; trgKeyType = arg_get_int_def(ctx, 13, trgKeyType); - if ((arg_get_lit(ctx, 11) || arg_get_lit(ctx, 12)) && (trgKeyType != prev_trgkeytype)) { CLIParserFree(ctx); PrintAndLogEx(WARNING, "Choose one single target key type"); return PM3_EINVARG; } - bool transferToEml = arg_get_lit(ctx, 14); bool createDumpFile = arg_get_lit(ctx, 15); bool singleSector = trgBlockNo > -1; @@ -2103,16 +2101,16 @@ static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't return PM3_EINVARG; } } - if (SectorsCnt == 1) { SectorsCnt = MIFARE_1K_MAXSECTOR; } - if (keylen != MIFARE_KEY_SIZE) { - PrintAndLogEx(WARNING, "Input key must include 6 HEX bytes, got %u", keylen); + if (keylen != 6) { + PrintAndLogEx(WARNING, "Input key must include 12 HEX symbols"); return PM3_EINVARG; } + sector_t *e_sector = NULL; uint8_t keyBlock[(ARRAYLEN(g_mifare_default_keys) + 1) * 6]; uint64_t key64 = 0; @@ -2126,17 +2124,15 @@ static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't // check if we can authenticate to sector if (mf_check_keys(blockNo, keyType, true, 1, key, &key64) != PM3_SUCCESS) { if (keyType < 2) { - PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block %3d key type %c", blockNo, keyType ? 'B' : 'A'); + PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A'); } else { - PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block %3d key type %02x", blockNo, MIFARE_AUTH_KEYA + keyType); + PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%02x", blockNo, MIFARE_AUTH_KEYA + keyType); } return PM3_EOPABORTED; } if (singleSector) { - - uint8_t foundkey[MIFARE_KEY_SIZE] = {0}; - int16_t isOK = mf_nested(blockNo, keyType, key, trgBlockNo, trgKeyType, foundkey, !ignore_static_encrypted); + int16_t isOK = mf_nested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, !ignore_static_encrypted); switch (isOK) { case PM3_ETIMEOUT: PrintAndLogEx(ERR, "command execution time out\n"); @@ -2154,7 +2150,8 @@ static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't PrintAndLogEx(ERR, "Static encrypted nonce detected. Aborted\n"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("script run fm11rf08s_recovery.py") "`"); break; - case PM3_SUCCESS: { + case PM3_SUCCESS: + key64 = bytes_to_num(keyBlock, 6); // transfer key to the emulator if (transferToEml) { @@ -2165,43 +2162,32 @@ static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't } else { // 16 block sector sectortrailer = trgBlockNo | 0x0f; } + mf_eml_get_mem(keyBlock, sectortrailer, 1); - uint8_t block[MFBLOCK_SIZE] = {0}; - mf_eml_get_mem(block, sectortrailer, 1); + if (trgKeyType == MF_KEY_A) + num_to_bytes(key64, 6, keyBlock); + else + num_to_bytes(key64, 6, &keyBlock[10]); - if (trgKeyType == MF_KEY_A) { - memcpy(block, foundkey, MIFARE_KEY_SIZE); - } else { - memcpy(block + 10, foundkey, MIFARE_KEY_SIZE); - } - - mf_elm_set_mem(block, sectortrailer, 1); - PrintAndLogEx(SUCCESS, "Key transferred to emulator memory"); + mf_elm_set_mem(keyBlock, sectortrailer, 1); + PrintAndLogEx(SUCCESS, "Key transferred to emulator memory."); } return PM3_SUCCESS; - } - default : { + default : PrintAndLogEx(ERR, "Unknown error\n"); - } } return PM3_SUCCESS; } else { // ------------------------------------ multiple sectors working + uint64_t t1 = msclock(); - uint64_t t2; - - sector_t *e_sector = NULL; - if (initSectorTable(&e_sector, SectorsCnt) != PM3_SUCCESS) { - return PM3_EMALLOC; - } + e_sector = calloc(SectorsCnt, sizeof(sector_t)); + if (e_sector == NULL) return PM3_EMALLOC; // add our known key e_sector[mfSectorNum(blockNo)].foundKey[keyType] = 1; e_sector[mfSectorNum(blockNo)].Key[keyType] = key64; - PrintAndLogEx(SUCCESS, "--- " _CYAN_("Enter dictionary recovery mode") " ---------------"); - PrintAndLogEx(SUCCESS, "Sector count "_YELLOW_("%d"), SectorsCnt); - //test current key and additional standard keys first // add parameter key memcpy(keyBlock + (ARRAYLEN(g_mifare_default_keys) * 6), key, 6); @@ -2210,8 +2196,6 @@ static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t *)(keyBlock + cnt * 6)); } - uint64_t t1 = msclock(); - PrintAndLogEx(SUCCESS, "Testing known keys. Sector count "_YELLOW_("%d"), SectorsCnt); int res = mf_check_keys_fast(SectorsCnt, true, true, 1, ARRAYLEN(g_mifare_default_keys) + 1, keyBlock, e_sector, use_flashmemory, false); if (res == PM3_SUCCESS) { @@ -2219,9 +2203,9 @@ static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't goto jumptoend; } - t2 = msclock() - t1; - PrintAndLogEx(SUCCESS, "Time in check keys " _YELLOW_("%.0f") " seconds\n", (float)t2 / 1000.0); - PrintAndLogEx(SUCCESS, "--- " _CYAN_("Enter nested key recovery mode") " ---------------"); + uint64_t t2 = msclock() - t1; + PrintAndLogEx(SUCCESS, "Time to check " _YELLOW_("%zu") " known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0); + PrintAndLogEx(SUCCESS, "enter nested key recovery"); // nested sectors bool calibrate = !ignore_static_encrypted; @@ -2230,14 +2214,7 @@ static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; ++sectorNo) { for (int i = 0; i < MIFARE_SECTOR_RETRY; i++) { - while (kbd_enter_pressed()) { - PrintAndLogEx(WARNING, "\naborted via keyboard!"); - return PM3_EOPABORTED; - } - - if (e_sector[sectorNo].foundKey[trgKeyType]) { - continue; - } + if (e_sector[sectorNo].foundKey[trgKeyType]) continue; int16_t isOK = mf_nested(blockNo, keyType, key, mfFirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate); switch (isOK) { @@ -2261,7 +2238,7 @@ static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't case PM3_SUCCESS: calibrate = false; e_sector[sectorNo].foundKey[trgKeyType] = 1; - e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, MIFARE_KEY_SIZE); + e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6); mf_check_keys_fast(SectorsCnt, true, true, 2, 1, keyBlock, e_sector, false, false); continue; @@ -2275,24 +2252,24 @@ static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't } t1 = msclock() - t1; - PrintAndLogEx(SUCCESS, "Time in nested " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0); + PrintAndLogEx(SUCCESS, "time in nested " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0); // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? - PrintAndLogEx(INFO, "Trying to read key B..."); + PrintAndLogEx(INFO, "trying to read key B..."); for (int i = 0; i < SectorsCnt; i++) { // KEY A but not KEY B if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) { uint8_t sectrail = (mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1); - PrintAndLogEx(SUCCESS, "Reading block " _YELLOW_("%d"), sectrail); + PrintAndLogEx(SUCCESS, "reading block %d", sectrail); mf_readblock_t payload; payload.blockno = sectrail; payload.keytype = MF_KEY_A; - num_to_bytes(e_sector[i].Key[0], MIFARE_KEY_SIZE, payload.key); // KEY A + num_to_bytes(e_sector[i].Key[0], 6, payload.key); // KEY A clearCommandBuffer(); SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); @@ -2307,9 +2284,9 @@ static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't } uint8_t *data = resp.data.asBytes; - key64 = bytes_to_num(data + 10, MIFARE_KEY_SIZE); + key64 = bytes_to_num(data + 10, 6); if (key64) { - PrintAndLogEx(SUCCESS, "data: %s", sprint_hex(data + 10, MIFARE_KEY_SIZE)); + PrintAndLogEx(SUCCESS, "data: %s", sprint_hex(data + 10, 6)); e_sector[i].foundKey[1] = true; e_sector[i].Key[1] = key64; } @@ -2318,6 +2295,10 @@ static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't jumptoend: + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, _GREEN_("found keys:")); + + //print them printKeyTable(SectorsCnt, e_sector); // transfer them to the emulator @@ -2328,10 +2309,10 @@ jumptoend: mf_eml_get_mem(keyBlock, mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1, 1); if (e_sector[i].foundKey[0]) - num_to_bytes(e_sector[i].Key[0], MIFARE_KEY_SIZE, keyBlock); + num_to_bytes(e_sector[i].Key[0], 6, keyBlock); if (e_sector[i].foundKey[1]) - num_to_bytes(e_sector[i].Key[1], MIFARE_KEY_SIZE, &keyBlock[10]); + num_to_bytes(e_sector[i].Key[1], 6, &keyBlock[10]); if (i == SectorsCnt - 1) { // Disable fast mode on last packet @@ -2355,9 +2336,6 @@ jumptoend: } free(e_sector); } - - PrintAndLogEx(INFO, "Done!"); - PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -2492,8 +2470,8 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { } uint64_t t2 = msclock() - t1; - PrintAndLogEx(SUCCESS, "Time in check keys " _YELLOW_("%.0f") " seconds\n", (float)t2 / 1000.0); - PrintAndLogEx(SUCCESS, "--- " _CYAN_("Enter static nested key recovery") " --------------"); + PrintAndLogEx(SUCCESS, "Time to check "_YELLOW_("%zu") " known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0); + PrintAndLogEx(SUCCESS, "enter static nested key recovery"); // nested sectors for (trgKeyType = MF_KEY_A; trgKeyType <= MF_KEY_B; ++trgKeyType) { @@ -2533,7 +2511,7 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? - PrintAndLogEx(INFO, "Trying to read key B..."); + PrintAndLogEx(INFO, "trying to read key B..."); for (int i = 0; i < SectorsCnt; i++) { // KEY A but not KEY B if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) { @@ -2570,6 +2548,9 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { jumptoend: + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, _GREEN_("found keys:")); + //print them printKeyTable(SectorsCnt, e_sector); @@ -2750,15 +2731,9 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { SetSIMDInstr(SIMD_NEON); #endif - if (in) { + if (in) SetSIMDInstr(SIMD_NONE); - } - // santiy checks - if ((g_session.pm3_present == false) && (tests == false)) { - PrintAndLogEx(INFO, "No device connected"); - return PM3_EFAILED; - } bool known_target_key = (trg_keylen); @@ -2814,13 +2789,13 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { } } - PrintAndLogEx(INFO, "Target block no " _YELLOW_("%3d") " target key type: " _YELLOW_("%c") " known target key: " _YELLOW_("%02x%02x%02x%02x%02x%02x%s"), + PrintAndLogEx(INFO, "Target block no " _YELLOW_("%3d") ", target key type: " _YELLOW_("%c") ", known target key: " _YELLOW_("%02x%02x%02x%02x%02x%02x%s"), trg_blockno, (trg_keytype == MF_KEY_B) ? 'B' : 'A', trg_key[0], trg_key[1], trg_key[2], trg_key[3], trg_key[4], trg_key[5], known_target_key ? "" : " (not set)" ); - PrintAndLogEx(INFO, "File action: " _YELLOW_("%s") " Slow: " _YELLOW_("%s") " Tests: " _YELLOW_("%d"), + PrintAndLogEx(INFO, "File action: " _YELLOW_("%s") ", Slow: " _YELLOW_("%s") ", Tests: " _YELLOW_("%d"), nonce_file_write ? "write" : nonce_file_read ? "read" : "none", slow ? "Yes" : "No", tests); @@ -3035,6 +3010,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { int prng_type = PM3_EUNDEF; int isOK = 0; + // ------------------------------ PrintAndLogEx(NORMAL, ""); uint64_t tagT = GetHF14AMfU_Type(); @@ -3163,19 +3139,6 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { block_cnt += 8; } - // check if we can authenticate to sector - uint8_t loopupblk = mfFirstBlockOfSector(sectorno); - if (mf_check_keys(loopupblk, keytype, true, (in_keys_len / MIFARE_KEY_SIZE), in_keys, &key64) != PM3_SUCCESS) { - if (keytype < 2) { - PrintAndLogEx(WARNING, "Known key failed. Can't authenticate to block %3d key type %c", loopupblk, keytype ? 'B' : 'A'); - } else { - PrintAndLogEx(WARNING, "Known key failed. Can't authenticate to block %3d key type %02x", loopupblk, MIFARE_AUTH_KEYA + keytype); - } - known_key = false; - } else { - num_to_bytes(key64, MIFARE_KEY_SIZE, key); - } - // create/initialize key storage structure sector_t *e_sector = NULL; size_t e_sector_cnt = (sector_cnt > sectorno) ? sector_cnt : sectorno + 1; @@ -3209,9 +3172,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { // card prng type (weak=1 / hard=0 / select/card comm error = negative value) if (has_staticnonce == NONCE_NORMAL) { - prng_type = detect_classic_prng(); - if (prng_type < 0) { PrintAndLogEx(FAILED, "\nNo tag detected or other tag communication error (%i)", prng_type); free(e_sector); @@ -3219,50 +3180,47 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { return PM3_ESOFT; } - if (known_key) { - has_staticnonce = detect_classic_static_encrypted_nonce(loopupblk, keytype, key); - } else { - has_staticnonce = detect_classic_static_encrypted_nonce(0, MF_KEY_A, g_mifare_default_key); - } + // + has_staticnonce = detect_classic_static_encrypted_nonce(0, MF_KEY_A, g_mifare_default_key); } // print parameters if (verbose) { - PrintAndLogEx(INFO, "---- " _CYAN_("Command settings") " ------------------------------------------"); - PrintAndLogEx(INFO, "Card sectors... " _YELLOW_("%d"), sector_cnt); - PrintAndLogEx(INFO, "Key supplied... " _YELLOW_("%s"), known_key ? "yes" : "no"); - PrintAndLogEx(INFO, "Known sector... " _YELLOW_("%d"), sectorno); - PrintAndLogEx(INFO, "Key type....... " _YELLOW_("%c"), (keytype == MF_KEY_B) ? 'B' : 'A'); - PrintAndLogEx(INFO, "Known key...... " _YELLOW_("%s"), sprint_hex_inrow(key, sizeof(key))); + PrintAndLogEx(INFO, "======================= " _YELLOW_("SETTINGS") " ======================="); + PrintAndLogEx(INFO, " card sectors .. " _YELLOW_("%d"), sector_cnt); + PrintAndLogEx(INFO, " key supplied .. " _YELLOW_("%s"), known_key ? "True" : "False"); + PrintAndLogEx(INFO, " known sector .. " _YELLOW_("%d"), sectorno); + PrintAndLogEx(INFO, " keytype ....... " _YELLOW_("%c"), (keytype == MF_KEY_B) ? 'B' : 'A'); + PrintAndLogEx(INFO, " known key ..... " _YELLOW_("%s"), sprint_hex_inrow(key, sizeof(key))); switch (has_staticnonce) { case NONCE_STATIC: { - PrintAndLogEx(INFO, "Card PRNG ..... " _YELLOW_("STATIC")); + PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("STATIC")); break; } case NONCE_STATIC_ENC: { - PrintAndLogEx(INFO, "Card PRNG ..... " _RED_("STATIC ENCRYPTED")); + PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("STATIC ENCRYPTED")); break; } case NONCE_NORMAL: { - PrintAndLogEx(INFO, "Card PRNG ..... %s", (prng_type) ? "weak" : "hard"); + PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("%s"), prng_type ? "WEAK" : "HARD"); break; } default: { - PrintAndLogEx(INFO, "Card PRNG ..... " _YELLOW_("Could not determine PRNG") " ( " _RED_("read failed") " ) %i", has_staticnonce); + PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("Could not determine PRNG,") " " _RED_("read failed.")); break; } } - PrintAndLogEx(INFO, "Dictionary .... " _YELLOW_("%s"), strlen(filename) ? filename : "n/a"); - PrintAndLogEx(INFO, "Legacy mode ... %s", (legacy_mfchk) ? _YELLOW_("yes") : "no"); + PrintAndLogEx(INFO, " dictionary .... " _YELLOW_("%s"), strlen(filename) ? filename : "NONE"); + PrintAndLogEx(INFO, " legacy mode ... " _YELLOW_("%s"), legacy_mfchk ? "True" : "False"); - PrintAndLogEx(INFO, "----------------------------------------------------------------"); + PrintAndLogEx(INFO, "========================================================================"); } // check the user supplied key if (known_key == false) { - PrintAndLogEx(WARNING, "No known key was supplied, key recovery might fail"); + PrintAndLogEx(WARNING, "no known key was supplied, key recovery might fail"); } // Start the timer @@ -3273,7 +3231,6 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { if (use_flashmemory) { fnlen = 0; } - int ret = mf_load_keys(&keyBlock, &key_cnt, in_keys, in_keys_len, filename, fnlen, true); if (ret != PM3_SUCCESS) { free(e_sector); @@ -3284,7 +3241,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { // Use the dictionary to find sector keys on the card if (verbose) { - PrintAndLogEx(INFO, "--- " _CYAN_("Enter dictionary recovery mode") " -----------------------------"); + PrintAndLogEx(INFO, "======================= " _YELLOW_("START DICTIONARY ATTACK") " ======================="); } if (legacy_mfchk) { @@ -3357,7 +3314,6 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { uint8_t num_found_keys = 0; for (int i = 0; i < sector_cnt; i++) { for (int j = MF_KEY_A; j <= MF_KEY_B; j++) { - if (e_sector[i].foundKey[j] != 1) { continue; } @@ -3373,13 +3329,13 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { known_key = true; sectorno = i; keytype = j; - PrintAndLogEx(SUCCESS, "Target sector " _GREEN_("%3u") " key type " _GREEN_("%c") " -- found valid key [ " _GREEN_("%s") " ] (used for nested / hardnested attack)", + PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ] (used for nested / hardnested attack)", i, (j == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(tmp_key, sizeof(tmp_key)) ); } else { - PrintAndLogEx(SUCCESS, "Target sector " _GREEN_("%3u") " key type " _GREEN_("%c") " -- found valid key [ " _GREEN_("%s") " ]", + PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]", i, (j == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(tmp_key, sizeof(tmp_key)) @@ -3398,7 +3354,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { // Check if the darkside attack can be used if (prng_type && has_staticnonce != NONCE_STATIC) { if (verbose) { - PrintAndLogEx(INFO, "--- " _CYAN_("Enter darkside key recovery mode") " ---------------------------------"); + PrintAndLogEx(INFO, "======================= " _YELLOW_("START DARKSIDE ATTACK") " ======================="); } PrintAndLogEx(NORMAL, ""); @@ -3409,13 +3365,13 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { goto noValidKeyFound; } - PrintAndLogEx(SUCCESS, "Found valid key [ " _GREEN_("%012" PRIX64) " ]\n", key64); + PrintAndLogEx(SUCCESS, "Found valid key [ " _GREEN_("%012" PRIx64) " ]\n", key64); // Store the keys num_to_bytes(key64, MIFARE_KEY_SIZE, key); e_sector[sectorno].Key[keytype] = key64; e_sector[sectorno].foundKey[keytype] = 'S'; - PrintAndLogEx(SUCCESS, "Target sector " _GREEN_("%3u") " key type "_GREEN_("%c") " -- found valid key [ " _GREEN_("%012" PRIX64) " ] (used for nested / hardnested attack)", + PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%012" PRIx64) " ] (used for nested / hardnested attack)", sectorno, (keytype == MF_KEY_B) ? 'B' : 'A', key64 @@ -3454,9 +3410,8 @@ noValidKeyFound: // If the key is already known, just skip it if (e_sector[current_sector_i].foundKey[current_key_type_i] == 0) { - if (has_staticnonce == NONCE_STATIC) { + if (has_staticnonce == NONCE_STATIC) goto tryStaticnested; - } // Try the found keys are reused if (bytes_to_num(tmp_key, MIFARE_KEY_SIZE) != 0) { @@ -3465,15 +3420,14 @@ noValidKeyFound: for (int i = 0; i < sector_cnt; i++) { for (int j = MF_KEY_A; j <= MF_KEY_B; j++) { // Check if the sector key is already broken - if (e_sector[i].foundKey[j]) { + if (e_sector[i].foundKey[j]) continue; - } // Check if the key works if (mf_check_keys(mfFirstBlockOfSector(i), j, true, 1, tmp_key, &key64) == PM3_SUCCESS) { e_sector[i].Key[j] = bytes_to_num(tmp_key, MIFARE_KEY_SIZE); e_sector[i].foundKey[j] = 'R'; - PrintAndLogEx(SUCCESS, "Target sector " _GREEN_("%3u") " key type " _GREEN_("%c") " -- found valid key [ " _GREEN_("%s") " ]", + PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]", i, (j == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(tmp_key, sizeof(tmp_key)) @@ -3488,7 +3442,7 @@ noValidKeyFound: if (current_key_type_i == MF_KEY_B) { if (e_sector[current_sector_i].foundKey[0] && !e_sector[current_sector_i].foundKey[1]) { if (verbose) { - PrintAndLogEx(INFO, "--- " _CYAN_("Enter read B key recovery mode") " -----------------------"); + PrintAndLogEx(INFO, "======================= " _YELLOW_("START READ B KEY ATTACK") " ======================="); PrintAndLogEx(INFO, "reading B key of sector %3d with key type %c", current_sector_i, (current_key_type_i == MF_KEY_B) ? 'B' : 'A'); @@ -3504,29 +3458,24 @@ noValidKeyFound: clearCommandBuffer(); SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); - if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500) == false) { - goto skipReadBKey; - } + if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500) == false) goto skipReadBKey; - if (resp.status != PM3_SUCCESS) { - goto skipReadBKey; - } + if (resp.status != PM3_SUCCESS) goto skipReadBKey; uint8_t *data = resp.data.asBytes; key64 = bytes_to_num(data + 10, MIFARE_KEY_SIZE); - if (key64) { e_sector[current_sector_i].foundKey[current_key_type_i] = 'A'; e_sector[current_sector_i].Key[current_key_type_i] = key64; num_to_bytes(key64, MIFARE_KEY_SIZE, tmp_key); - PrintAndLogEx(SUCCESS, "Target sector " _GREEN_("%3u") " key type " _GREEN_("%c") " -- found valid key [ " _GREEN_("%s") " ]", + PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]", current_sector_i, (current_key_type_i == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(tmp_key, sizeof(tmp_key)) ); } else { if (verbose) { - PrintAndLogEx(WARNING, "Unknown B key: sector %3d key type %c", + PrintAndLogEx(WARNING, "unknown B key: sector: %3d key type: %c", current_sector_i, (current_key_type_i == MF_KEY_B) ? 'B' : 'A' ); @@ -3542,17 +3491,14 @@ noValidKeyFound: skipReadBKey: if (e_sector[current_sector_i].foundKey[current_key_type_i] == 0) { - if (has_staticnonce == NONCE_STATIC) { + if (has_staticnonce == NONCE_STATIC) goto tryStaticnested; - } if (prng_type && (nested_failed == false)) { uint8_t retries = 0; - - PrintAndLogEx(NORMAL, ""); if (verbose) { - PrintAndLogEx(INFO, "--- " _CYAN_("Enter nested key recovery mode") " -----------------------------"); - PrintAndLogEx(INFO, "Sector " _YELLOW_("%3d") " key type " _YELLOW_("%c"), + PrintAndLogEx(INFO, "======================= " _YELLOW_("START NESTED ATTACK") " ======================="); + PrintAndLogEx(INFO, "sector no %3d, target key type %c", current_sector_i, (current_key_type_i == MF_KEY_B) ? 'B' : 'A'); } @@ -3598,6 +3544,8 @@ tryNested: e_sector[current_sector_i].Key[current_key_type_i] = 0xffffffffffff; e_sector[current_sector_i].foundKey[current_key_type_i] = false; // Show the results to the user + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, _GREEN_("found keys:")); printKeyTable(sector_cnt, e_sector); PrintAndLogEx(NORMAL, ""); free(e_sector); @@ -3611,7 +3559,7 @@ tryNested: break; } default: { - PrintAndLogEx(ERR, "Unknown error\n"); + PrintAndLogEx(ERR, "unknown Error.\n"); free(e_sector); free(fptr); return isOK; @@ -3625,6 +3573,8 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack if (isMifarePlus) { // Show the results to the user + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, _GREEN_("found keys:")); printKeyTable(sector_cnt, e_sector); PrintAndLogEx(NORMAL, ""); free(e_sector); @@ -3632,10 +3582,9 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack return PM3_ESOFT; } - PrintAndLogEx(NORMAL, ""); if (verbose) { - PrintAndLogEx(INFO, "--- " _CYAN_("Enter hardnested key recovery mode") " -------------------------"); - PrintAndLogEx(INFO, "Sector " _YELLOW_("%3d") " key type " _YELLOW_("%c") ", slow " _YELLOW_("%s"), + PrintAndLogEx(INFO, "======================= " _YELLOW_("START HARDNESTED ATTACK") " ======================="); + PrintAndLogEx(INFO, "sector no %3d, target key type %c, Slow %s", current_sector_i, (current_key_type_i == MF_KEY_B) ? 'B' : 'A', slow ? "Yes" : "No"); @@ -3661,6 +3610,8 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack e_sector[current_sector_i].foundKey[current_key_type_i] = false; // Show the results to the user + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, _GREEN_("found keys:")); printKeyTable(sector_cnt, e_sector); PrintAndLogEx(NORMAL, ""); break; @@ -3686,10 +3637,9 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack if (has_staticnonce == NONCE_STATIC) { tryStaticnested: - PrintAndLogEx(NORMAL, ""); if (verbose) { - PrintAndLogEx(INFO, "--- " _CYAN_("Enter static nested key recovery mode") " -----------------------"); - PrintAndLogEx(INFO, "Sector " _YELLOW_("%3d") ", key type " _YELLOW_("%c"), + PrintAndLogEx(INFO, "======================= " _YELLOW_("START STATIC NESTED ATTACK") " ======================="); + PrintAndLogEx(INFO, "sector no %3d, target key type %c", current_sector_i, (current_key_type_i == MF_KEY_B) ? 'B' : 'A'); } @@ -3722,7 +3672,7 @@ tryStaticnested: // Check if the key was found if (e_sector[current_sector_i].foundKey[current_key_type_i]) { - PrintAndLogEx(SUCCESS, "Target sector " _GREEN_("%3u") " key type " _GREEN_("%c") " -- found valid key [ " _GREEN_("%s") " ]", + PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]", current_sector_i, (current_key_type_i == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(tmp_key, sizeof(tmp_key)) @@ -3736,6 +3686,9 @@ tryStaticnested: all_found: // Show the results to the user + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, _GREEN_("found keys:")); + printKeyTable(sector_cnt, e_sector); if (no_save == false) { @@ -3751,26 +3704,21 @@ all_found: clearCommandBuffer(); SendCommandNG(CMD_HF_MIFARE_EML_MEMCLR, NULL, 0); - PrintAndLogEx(INFO, "Transferring keys to simulator memory " NOLF); + PrintAndLogEx(INFO, "transferring keys to simulator memory " NOLF); bool transfer_status = true; for (current_sector_i = 0; current_sector_i < sector_cnt; current_sector_i++) { - mf_eml_get_mem(block, current_sector_i, 1); - - if (e_sector[current_sector_i].foundKey[0]) { + if (e_sector[current_sector_i].foundKey[0]) num_to_bytes(e_sector[current_sector_i].Key[0], MIFARE_KEY_SIZE, block); - } - - if (e_sector[current_sector_i].foundKey[1]) { + if (e_sector[current_sector_i].foundKey[1]) num_to_bytes(e_sector[current_sector_i].Key[1], MIFARE_KEY_SIZE, block + 10); - } transfer_status |= mf_elm_set_mem(block, mfFirstBlockOfSector(current_sector_i) + mfNumBlocksPerSector(current_sector_i) - 1, 1); } PrintAndLogEx(NORMAL, "( %s )", (transfer_status) ? _GREEN_("ok") : _RED_("fail")); - PrintAndLogEx(INFO, "Dumping card content to emulator memory (Cmd Error: 04 can occur)"); + PrintAndLogEx(INFO, "dumping card content to emulator memory (Cmd Error: 04 can occur)"); // use ecfill trick FastDumpWithEcFill(sector_cnt); @@ -3806,7 +3754,6 @@ all_found: } else { snprintf(suffix, sizeof(suffix), "-dump"); } - fptr = GenerateFilename("hf-mf-", suffix); if (fptr == NULL) { free(dump); @@ -3824,7 +3771,7 @@ all_found: out: // Generate and show statistics t1 = msclock() - t1; - PrintAndLogEx(INFO, "Autopwn execution time: " _YELLOW_("%.0f") " seconds", (float)t1 / 1000.0); + PrintAndLogEx(INFO, "autopwn execution time: " _YELLOW_("%.0f") " seconds", (float)t1 / 1000.0); DropField(); free(e_sector); @@ -3935,7 +3882,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { return PM3_EMALLOC; } - uint32_t chunksize = (keycnt > (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE)) ? (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) : keycnt; + uint32_t chunksize = keycnt > (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) ? (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) : keycnt; bool firstChunk = true, lastChunk = false; int i = 0; @@ -3954,26 +3901,30 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { // strategies. 1= deep first on sector 0 AB, 2= width first on all sectors for (uint8_t strategy = 1; strategy < 3; strategy++) { - PrintAndLogEx(INFO, "Running strategy " _YELLOW_("%u"), strategy); + PrintAndLogEx(INFO, "Running strategy %u", strategy); // main keychunk loop for (i = 0; i < keycnt; i += chunksize) { if (kbd_enter_pressed()) { - clearCommandBuffer(); - SendCommandNG(CMD_BREAK_LOOP, NULL, 0); - SendCommandNG(CMD_FPGA_MAJOR_MODE_OFF, NULL, 0); // field is still ON if not on last chunk PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(WARNING, "\naborted via keyboard!"); + PrintAndLogEx(WARNING, "\naborted via keyboard!\n"); + // field is still ON if not on last chunk + clearCommandBuffer(); + SendCommandNG(CMD_FPGA_MAJOR_MODE_OFF, NULL, 0); + // TODO: we're missing these cleanups on arm side, not sure if it's important... + // set_tracing(false); + // BigBuf_free(); + // BigBuf_Clear_ext(false); goto out; } - + PrintAndLogEx(INPLACE, "Testing %5i/%5i ( " _YELLOW_("%02.1f%%") " )", i, keycnt, (float)i * 100 / keycnt); uint32_t size = ((keycnt - i) > chunksize) ? chunksize : keycnt - i; // last chunk? - if (size == keycnt - i) { + if (size == keycnt - i) lastChunk = true; - } + int res = mf_check_keys_fast_ex(sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * MIFARE_KEY_SIZE), e_sector, false, false, true, singleSectorParams); if (firstChunk) firstChunk = false; @@ -3983,19 +3934,12 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { PrintAndLogEx(NORMAL, ""); goto out; } - PrintAndLogEx(INPLACE, "Testing %5i/%5i ( " _YELLOW_("%02.1f %%") " )", i, keycnt, (float)i * 100 / keycnt); } // end chunks of keys - - PrintAndLogEx(INPLACE, "Testing %5i/%5i ( " _YELLOW_("100 %%") " ) ", keycnt, keycnt); + PrintAndLogEx(INPLACE, "Testing %5i/%5i ( " _YELLOW_("100.00%%") " )", keycnt, keycnt); PrintAndLogEx(NORMAL, ""); - - // reset chunks when swapping strategies firstChunk = true; lastChunk = false; - - if (blockn != -1) { - break; - } + if (blockn != -1) break; } // end strategy } out: @@ -4021,6 +3965,9 @@ out: PrintAndLogEx(WARNING, "No keys found"); } else { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, _GREEN_("found keys:")); + printKeyTable(sectorsCnt, e_sector); if (use_flashmemory && found_keys == (sectorsCnt << 1)) { @@ -4239,6 +4186,9 @@ out: PrintAndLogEx(WARNING, "No keys found"); } else { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, _GREEN_("found keys:")); + printKeyTable(sectorsCnt, e_sector); if (transferToEml) { @@ -4403,9 +4353,9 @@ static int CmdHF14AMfChk(const char *Cmd) { uint8_t *keyBlock = NULL; uint32_t keycnt = 0; - int res = mf_load_keys(&keyBlock, &keycnt, key, keylen, filename, fnlen, load_default); - if (res != PM3_SUCCESS) { - return res; + int ret = mf_load_keys(&keyBlock, &keycnt, key, keylen, filename, fnlen, load_default); + if (ret != PM3_SUCCESS) { + return ret; } uint64_t key64 = 0; @@ -4454,8 +4404,7 @@ static int CmdHF14AMfChk(const char *Cmd) { uint32_t size = keycnt - c > max_keys ? max_keys : keycnt - c; - res = mf_check_keys(b, trgKeyType, clearLog, size, &keyBlock[MIFARE_KEY_SIZE * c], &key64); - if (res == PM3_SUCCESS) { + if (mf_check_keys(b, trgKeyType, clearLog, size, &keyBlock[MIFARE_KEY_SIZE * c], &key64) == PM3_SUCCESS) { e_sector[i].Key[trgKeyType] = key64; e_sector[i].foundKey[trgKeyType] = true; clearLog = false; @@ -4463,21 +4412,18 @@ static int CmdHF14AMfChk(const char *Cmd) { } clearLog = false; } - - if (singleSector) { + if (singleSector) break; - } b < 127 ? (b += 4) : (b += 16); } } - t1 = msclock() - t1; - PrintAndLogEx(INFO, "\nTime in checkkeys " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0); + PrintAndLogEx(INFO, "\ntime in checkkeys " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0); // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? if (keyType != MF_KEY_B) { - PrintAndLogEx(INFO, "Testing to read key B..."); + PrintAndLogEx(INFO, "testing to read key B..."); // loop sectors but block is used as to keep track of from which blocks to test int b = blockNo; @@ -4524,6 +4470,9 @@ static int CmdHF14AMfChk(const char *Cmd) { } out: + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, _GREEN_("found keys:")); + //print keys // if (singleSector) // printKeyTableEx(1, e_sector, mfSectorNum(blockNo)); @@ -4534,18 +4483,15 @@ out: // fast push mode g_conn.block_after_ACK = true; uint8_t block[MFBLOCK_SIZE] = {0x00}; - for (int i = 0; i < sectors_cnt; ++i) { uint8_t blockno = mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1; mf_eml_get_mem(block, blockno, 1); - if (e_sector[i].foundKey[0]) { + if (e_sector[i].foundKey[0]) num_to_bytes(e_sector[i].Key[0], MIFARE_KEY_SIZE, block); - } - if (e_sector[i].foundKey[1]) { + if (e_sector[i].foundKey[1]) num_to_bytes(e_sector[i].Key[1], MIFARE_KEY_SIZE, block + 10); - } if (i == sectors_cnt - 1) { // Disable fast mode on last packet @@ -4651,7 +4597,7 @@ static int CmdHF14AMfSim(const char *Cmd) { "hf mf sim --1k -u 11223344556677 --> MIFARE Classic 1k with 7b UID\n" "hf mf sim --1k -u 11223344 -i -x --> Perform reader attack in interactive mode\n" "hf mf sim --2k --> MIFARE 2k\n" - "hf mf sim --4k --> MIFARE 4k\n" + "hf mf sim --4k --> MIFARE 4k" "hf mf sim --1k -x -e --> Keep simulation running and populate with found reader keys\n" ); @@ -4671,7 +4617,6 @@ static int CmdHF14AMfSim(const char *Cmd) { arg_lit0("e", "emukeys", "Fill simulator keys from found keys. Requires -x or -y. Implies -i. Simulation will restart automatically."), // If access bits show that key B is Readable, any subsequent memory access should be refused. arg_lit0(NULL, "allowkeyb", "Allow key B even if readable"), - arg_lit0(NULL, "allowover", "Allow auth attempts out of range for selected MIFARE Classic type"), arg_lit0("v", "verbose", "Verbose output"), arg_lit0(NULL, "cve", "Trigger CVE 2021_0430"), arg_param_end @@ -4726,13 +4671,9 @@ static int CmdHF14AMfSim(const char *Cmd) { flags |= FLAG_MF_USE_READ_KEYB; } - if (arg_get_lit(ctx, 14)) { - flags |= FLAG_MF_ALLOW_OOB_AUTH; - } + bool verbose = arg_get_lit(ctx, 14); - bool verbose = arg_get_lit(ctx, 15); - - if (arg_get_lit(ctx, 16)) { + if (arg_get_lit(ctx, 15)) { flags |= FLAG_CVE21_0430; } CLIParserFree(ctx); @@ -4912,7 +4853,7 @@ static int CmdHF14AMfKeyBrute(const char *Cmd) { uint64_t t1 = msclock(); if (mfKeyBrute(blockNo, keytype, key, &foundkey)) - PrintAndLogEx(SUCCESS, "Found valid key [ %012" PRIX64 " ]\n", foundkey); + PrintAndLogEx(SUCCESS, "found valid key: %012" PRIx64 " \n", foundkey); else PrintAndLogEx(FAILED, "key not found"); @@ -5306,7 +5247,7 @@ int CmdHF14AMfELoad(const char *Cmd) { // update expected blocks to match converted data. block_cnt = bytes_read / MFU_BLOCK_SIZE; - PrintAndLogEx(INFO, "MIFARE Ultralight override, will use " _YELLOW_("%d") " blocks ( " _YELLOW_("%u") " bytes )", block_cnt, block_cnt * block_width); + PrintAndLogEx(INFO, "MIFARE Ultralight override, will use %d blocks ( %u bytes )", block_cnt, block_cnt * block_width); } PrintAndLogEx(INFO, "Uploading to emulator memory"); @@ -6603,9 +6544,8 @@ static int CmdHf14AMfNack(const char *Cmd) { bool verbose = arg_get_lit(ctx, 1); CLIParserFree(ctx); - if (verbose) { + if (verbose) PrintAndLogEx(INFO, "Started testing card for NACK bug. Press Enter to abort"); - } detect_classic_nackbug(verbose); return PM3_SUCCESS; @@ -7315,10 +7255,12 @@ int CmdHFMFNDEFFormat(const char *Cmd) { // size_t alen = 0, blen = 0; uint8_t *tmpA, *tmpB; - if (loadFileBinaryKey(keyFilename, "", (void **)&tmpA, (void **)&tmpB, &alen, &blen, true) != PM3_SUCCESS) { + if (loadFileBinaryKey(keyFilename, "", (void **)&tmpA, (void **)&tmpB, &alen, &blen) != PM3_SUCCESS) { goto skipfile; } + PrintAndLogEx(INFO, "Using `" _YELLOW_("%s") "`", keyFilename); + for (int i = 0; i < numSectors; i++) { memcpy(keyA[i], tmpA + (i * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE); memcpy(keyB[i], tmpB + (i * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE); @@ -10186,7 +10128,7 @@ static int CmdHF14AMfInfo(const char *Cmd) { } if (keylen != 0 && keylen != MIFARE_KEY_SIZE) { - PrintAndLogEx(ERR, "Key length must be %u bytes, got %d", MIFARE_KEY_SIZE, keylen); + PrintAndLogEx(ERR, "Key length must be %u bytes", MIFARE_KEY_SIZE); return PM3_EINVARG; } @@ -10242,7 +10184,7 @@ static int CmdHF14AMfInfo(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("ISO14443-a Information") " -----------------------------"); + PrintAndLogEx(INFO, "--- " _CYAN_("ISO14443-a Information") " ---------------------"); PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen)); PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]); PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]); @@ -10297,13 +10239,6 @@ static int CmdHF14AMfInfo(const char *Cmd) { PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("emv info") "`"); } - if ((card_type & MTFUDAN) == MTFUDAN) { - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "FUDAN FM11RF005 detected"); - PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf fudan dump") "`"); - goto out; - } - if (setDeviceDebugLevel(verbose ? MAX(dbg_curr, DBG_INFO) : DBG_NONE, false) != PM3_SUCCESS) { return PM3_EFAILED; } @@ -10341,14 +10276,13 @@ static int CmdHF14AMfInfo(const char *Cmd) { uint8_t blockdata[MFBLOCK_SIZE] = {0}; res = mf_check_keys_fast(sectorsCnt, true, true, 1, keycnt, keyBlock, e_sector, false, verbose); - // Identify Backdoor keyed cards if (res == PM3_SUCCESS || res == PM3_EPARTIAL) { if (e_sector[0].foundKey[MF_KEY_A]) { PrintAndLogEx(SUCCESS, "Sector 0 key A... " _GREEN_("%012" PRIX64), e_sector[0].Key[MF_KEY_A]); num_to_bytes(e_sector[0].Key[MF_KEY_A], MIFARE_KEY_SIZE, fkey); - if (mf_read_block(0, MF_KEY_A, fkey, blockdata) == PM3_SUCCESS) { + if (mf_read_block(0, MF_KEY_A, key, blockdata) == PM3_SUCCESS) { fKeyType = MF_KEY_A; } } @@ -10358,7 +10292,7 @@ static int CmdHF14AMfInfo(const char *Cmd) { if (fKeyType == 0xFF) { num_to_bytes(e_sector[0].Key[MF_KEY_B], MIFARE_KEY_SIZE, fkey); - if (mf_read_block(0, MF_KEY_B, fkey, blockdata) == PM3_SUCCESS) { + if (mf_read_block(0, MF_KEY_B, key, blockdata) == PM3_SUCCESS) { fKeyType = MF_KEY_B; } } @@ -10367,59 +10301,33 @@ static int CmdHF14AMfInfo(const char *Cmd) { if (e_sector[1].foundKey[MF_KEY_A]) { PrintAndLogEx(SUCCESS, "Sector 1 key A... " _GREEN_("%012" PRIX64), e_sector[1].Key[MF_KEY_A]); } - - if (e_sector[1].foundKey[MF_KEY_B]) { - PrintAndLogEx(SUCCESS, "Sector 1 key B... " _GREEN_("%012" PRIX64), e_sector[1].Key[MF_KEY_B]); - } } uint8_t k08s[MIFARE_KEY_SIZE] = {0xA3, 0x96, 0xEF, 0xA4, 0xE2, 0x4F}; uint8_t k08[MIFARE_KEY_SIZE] = {0xA3, 0x16, 0x67, 0xA8, 0xCE, 0xC1}; - uint8_t k32n[MIFARE_KEY_SIZE] = {0x51, 0x8B, 0x33, 0x54, 0xE7, 0x60}; - uint8_t k32n2[MIFARE_KEY_SIZE] = {0x73, 0xB9, 0x83, 0x6C, 0xF1, 0x68}; + uint8_t k32[MIFARE_KEY_SIZE] = {0x51, 0x8B, 0x33, 0x54, 0xE7, 0x60}; if (mf_read_block(0, 4, k08s, blockdata) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "Backdoor key..... " _YELLOW_("%s"), sprint_hex_inrow(k08s, sizeof(k08s))); fKeyType = MF_KEY_BD; memcpy(fkey, k08s, sizeof(fkey)); + } else if (mf_read_block(0, 4, k08, blockdata) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "Backdoor key..... " _YELLOW_("%s"), sprint_hex_inrow(k08, sizeof(k08))); fKeyType = MF_KEY_BD; memcpy(fkey, k08, sizeof(fkey)); - } else if (mf_read_block(0, 4, k32n, blockdata) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Backdoor key..... " _YELLOW_("%s"), sprint_hex_inrow(k32n, sizeof(k32n))); + } else if (mf_read_block(0, 4, k32, blockdata) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "Backdoor key..... " _YELLOW_("%s"), sprint_hex_inrow(k32, sizeof(k32))); fKeyType = MF_KEY_BD; - memcpy(fkey, k32n, sizeof(fkey)); - } else if (mf_read_block(0, 4, k32n2, blockdata) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Backdoor key..... " _YELLOW_("%s"), sprint_hex_inrow(k32n2, sizeof(k32n2))); - fKeyType = MF_KEY_BD; - memcpy(fkey, k32n2, sizeof(fkey)); + memcpy(fkey, k32, sizeof(fkey)); } - if ((fKeyType == MF_KEY_A) || (fKeyType == MF_KEY_B)) { - // we've a key but not a backdoor key - uint8_t blockdata2[MFBLOCK_SIZE] = {0}; - if (mf_read_block(0, fKeyType + 4, fkey, blockdata2) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Backdoor key..... " _GREEN_("same as key A/B")); - } else if (detect_classic_auth(MF_KEY_BD)) { - PrintAndLogEx(SUCCESS, "Backdoor key..... " _RED_("detected but unknown!")); - PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf mf nested --blk 0 -%s -k %s --tblk 0 --tc %i") "`" - , (fKeyType == MF_KEY_A) ? "a" : "b" - , sprint_hex_inrow(fkey, MIFARE_KEY_SIZE) - , fKeyType + 4 - ); - fKeyType = MF_KEY_BD; - } - } - - if (fKeyType != 0xFF) { - PrintAndLogEx(SUCCESS, "Block 0.......... %s | " NOLF, sprint_hex_inrow(blockdata, MFBLOCK_SIZE)); + PrintAndLogEx(SUCCESS, "Block 0.... %s | " NOLF, sprint_hex_inrow(blockdata, MFBLOCK_SIZE)); PrintAndLogEx(NORMAL, "%s", sprint_ascii(blockdata + 8, 8)); } PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("Fingerprint")); - bool expect_static_enc_nonce = false; if (fKeyType != 0xFF) { // cards with known backdoor @@ -10428,24 +10336,16 @@ static int CmdHF14AMfInfo(const char *Cmd) { PrintAndLogEx(SUCCESS, "Fudan based card"); } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08s, sizeof(fkey)) == 0 && card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0 - && (blockdata[8] == 0x03 || blockdata[8] == 0x04 || blockdata[8] == 0x05) && blockdata[15] == 0x90) { - PrintAndLogEx(SUCCESS, "Fudan FM11RF08S %02X%02X", blockdata[8], blockdata[15]); - expect_static_enc_nonce = true; - } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08s, sizeof(fkey)) == 0 - && card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0 - && (blockdata[8] == 0x03 || blockdata[8] == 0x04) && blockdata[15] == 0x91) { - PrintAndLogEx(SUCCESS, "Fudan FM11RF08 %02X%02X with advanced verification method", blockdata[8], blockdata[15]); - expect_static_enc_nonce = false; + && (blockdata[8] == 0x03 || blockdata[8] == 0x04) && blockdata[15] == 0x90) { + PrintAndLogEx(SUCCESS, "Fudan FM11RF08S"); } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08s, sizeof(fkey)) == 0 && card.sak == 0x08 && memcmp(blockdata + 5, "\x00\x03\x00\x10", 4) == 0 && blockdata[15] == 0x90) { - PrintAndLogEx(SUCCESS, "Fudan FM11RF08S-7B %02X%02X", blockdata[8], blockdata[15]); - expect_static_enc_nonce = true; + PrintAndLogEx(SUCCESS, "Fudan FM11RF08S-7B"); } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0 && card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0 && blockdata[15] == 0x98) { - PrintAndLogEx(SUCCESS, "Fudan FM11RF08S %02X%02X", blockdata[8], blockdata[15]); - expect_static_enc_nonce = true; + PrintAndLogEx(SUCCESS, "Fudan FM11RF08S **98"); } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0 && card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0 && (blockdata[8] >= 0x01 && blockdata[8] <= 0x03) && blockdata[15] == 0x1D) { @@ -10454,12 +10354,9 @@ static int CmdHF14AMfInfo(const char *Cmd) { && card.sak == 0x08 && memcmp(blockdata + 5, "\x00\x01\x00\x10", 4) == 0 && blockdata[15] == 0x1D) { PrintAndLogEx(SUCCESS, "Fudan FM11RF08-7B"); - } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k32n, sizeof(fkey)) == 0 + } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k32, sizeof(fkey)) == 0 && card.sak == 0x18 && memcmp(blockdata + 5, "\x18\x02\x00\x46\x44\x53\x37\x30\x56\x30\x31", 11) == 0) { - PrintAndLogEx(SUCCESS, "Fudan FM11RF32N"); - } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k32n2, sizeof(fkey)) == 0 - && card.sak == 0x18 && memcmp(blockdata + 5, "\x18\x02\x00\x46\x44\x53\x37\x30\x56\x30\x31", 11) == 0) { - PrintAndLogEx(SUCCESS, "Fudan FM11RF32N (variant)"); + PrintAndLogEx(SUCCESS, "Fudan FM11RF32"); } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0 && card.sak == 0x20 && memcmp(blockdata + 8, "\x62\x63\x64\x65\x66\x67\x68\x69", 8) == 0) { PrintAndLogEx(SUCCESS, "Fudan FM11RF32 (SAK=20)"); @@ -10542,9 +10439,6 @@ static int CmdHF14AMfInfo(const char *Cmd) { PrintAndLogEx(FAILED, "Prng........ " _RED_("fail")); } - bool tested_static_nonce = false; - int result_static_nonce = 0; - // detect static encrypted nonce if (keylen == MIFARE_KEY_SIZE) { res = detect_classic_static_encrypted_nonce(blockn, keytype, key); @@ -10558,8 +10452,6 @@ static int CmdHF14AMfInfo(const char *Cmd) { PrintAndLogEx(SUCCESS, "Static enc nonce... " _RED_("yes")); fKeyType = 0xFF; // dont detect twice } - result_static_nonce = res; - tested_static_nonce = true; } if (fKeyType != 0xFF) { @@ -10571,16 +10463,6 @@ static int CmdHF14AMfInfo(const char *Cmd) { } else if (res == NONCE_STATIC_ENC) { PrintAndLogEx(SUCCESS, "Static enc nonce... " _RED_("yes")); } - result_static_nonce = res; - tested_static_nonce = true; - } - if (tested_static_nonce) { - if ((result_static_nonce == NONCE_STATIC_ENC) && (!expect_static_enc_nonce)) { - PrintAndLogEx(WARNING, "Static enc nonce detected on a card not supposed to support it, please report... "); - } - if ((result_static_nonce != NONCE_STATIC_ENC) && (expect_static_enc_nonce)) { - PrintAndLogEx(WARNING, "Static enc nonce not detected on a card supposed to support it, please report... "); - } } if (do_nack_test) { @@ -10829,7 +10711,7 @@ static int CmdHF14AMfISEN(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("ISO14443-a Information") " -----------------------------"); + PrintAndLogEx(INFO, "--- " _CYAN_("ISO14443-a Information") " ---------------------"); PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen)); PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]); PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]); @@ -10841,11 +10723,11 @@ static int CmdHF14AMfISEN(const char *Cmd) { int res = detect_classic_static_encrypted_nonce_ex(blockn, keytype, key, blockn_nested, keytype_nested, key_nested, nr_nested, reset, hardreset, addread, addauth, incblk2, corruptnrar, corruptnrarparity, true); if (res == NONCE_STATIC) { - PrintAndLogEx(SUCCESS, "Static nonce....... " _YELLOW_("yes")); + PrintAndLogEx(SUCCESS, "Static nonce......... " _YELLOW_("yes")); } else if (res == NONCE_SUPERSTATIC) { - PrintAndLogEx(SUCCESS, "Static nonce....... " _YELLOW_("yes, even when nested")); + PrintAndLogEx(SUCCESS, "Static nonce......... " _YELLOW_("yes, even when nested")); } else if (res == NONCE_STATIC_ENC) { - PrintAndLogEx(SUCCESS, "Static enc nonce... " _RED_("yes")); + PrintAndLogEx(SUCCESS, "Static enc nonce..... " _RED_("yes")); } if (res == NONCE_STATIC_ENC) { diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index b13989119..a6f4f934c 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -238,7 +238,7 @@ static char *getProtocolStr(uint8_t id, bool hw) { static char *getVersionStr(uint8_t type, uint8_t major, uint8_t minor) { - static char buf[60] = {0x00}; + static char buf[40] = {0x00}; char *retStr = buf; if (type == 0x01 && major == 0x00) @@ -255,8 +255,6 @@ static char *getVersionStr(uint8_t type, uint8_t major, uint8_t minor) { snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire EV2") " )", major, minor); else if (type == 0x01 && major == 0x33 && minor == 0x00) snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire EV3") " )", major, minor); - else if (type == 0x81 && major == 0x43 && minor == 0x01) - snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire EV3C implementation on P71D600") " )", major, minor); // Swisskey iShield Key else if (type == 0x01 && major == 0x30 && minor == 0x00) snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire Light") " )", major, minor); else if (type == 0x02 && major == 0x11 && minor == 0x00) @@ -331,9 +329,6 @@ nxp_cardtype_t getCardType(uint8_t type, uint8_t major, uint8_t minor) { if (type == 0x01 && major == 0x33 && minor == 0x00) return DESFIRE_EV3; - if (type == 0x81 && major == 0x43 && minor == 0x01) - return DESFIRE_EV3; - // Duox if (type == 0x01 && major == 0xA0 && minor == 0x00) return DUOX; @@ -463,7 +458,7 @@ static void swap24(uint8_t *data) { // default parameters static uint8_t defaultKeyNum = 0; -static DesfireCryptoAlgorithm defaultAlgoId = T_3DES; // Real DESFire cards seem to use 2TDEA by default +static DesfireCryptoAlgorithm defaultAlgoId = T_DES; static uint8_t defaultKey[DESFIRE_MAX_KEY_SIZE] = {0}; static int defaultKdfAlgo = MFDES_KDF_ALGO_NONE; static int defaultKdfInputLen = 0; @@ -479,7 +474,6 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext_t *d uint8_t cmodeid, uint8_t ccsetid, uint8_t schannid, uint8_t appid, uint8_t appisoid, - uint8_t dfnameid, int *securechannel, DesfireCommunicationMode defcommmode, uint32_t *id, @@ -565,22 +559,6 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext_t *d return PM3_ESOFT; } - // Handle dfname parameter - if (dfnameid && id) { - uint8_t dfname_data[16] = {0}; - int dfname_len = 0; - if (CLIParamHexToBuf(arg_get_str(ctx, dfnameid), dfname_data, sizeof(dfname_data), &dfname_len) == 0 && dfname_len > 0) { - if (dfname_len <= 16) { - DesfireSetDFName(dctx, dfname_data, dfname_len); - if (selectway) - *selectway = ISWDFName; - } else { - PrintAndLogEx(ERR, "DF name length must be between 1-16 bytes, got %d", dfname_len); - return PM3_EINVARG; - } - } - } - if (appid && id) { *id = 0x000000; if (CLIGetUint32Hex(ctx, appid, 0x000000, id, NULL, 3, "AID must have 3 bytes length")) @@ -634,7 +612,7 @@ static int CmdHF14ADesDefault(const char *Cmd) { DesfireContext_t dctx; int securechann = defaultSecureChannel; - int res = CmdDesGetSessionParameters(ctx, &dctx, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, &securechann, DCMNone, NULL, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, &securechann, DCMNone, NULL, NULL); if (res) { CLIParserFree(ctx); return res; @@ -1049,7 +1027,7 @@ static int AuthCheckDesfire(DesfireContext_t *dctx, DesfireSetKeyNoClear(dctx, keyno, T_DES, deskeyList[curkey]); res = DesfireAuthenticate(dctx, secureChannel, false); if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "AID 0x%06X, Found DES Key %02u... " _GREEN_("%s"), curaid, keyno, sprint_hex(deskeyList[curkey], 8)); + PrintAndLogEx(SUCCESS, "AID 0x%06X, Found DES Key %02u : " _GREEN_("%s"), curaid, keyno, sprint_hex(deskeyList[curkey], 8)); foundKeys[0][keyno][0] = 0x01; *result = true; memcpy(&foundKeys[0][keyno][1], deskeyList[curkey], 8); @@ -1081,7 +1059,7 @@ static int AuthCheckDesfire(DesfireContext_t *dctx, DesfireSetKeyNoClear(dctx, keyno, T_3DES, aeskeyList[curkey]); res = DesfireAuthenticate(dctx, secureChannel, false); if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "AID 0x%06X, Found 2TDEA Key %02u... " _GREEN_("%s"), curaid, keyno, sprint_hex_inrow(aeskeyList[curkey], 16)); + PrintAndLogEx(SUCCESS, "AID 0x%06X, Found 2TDEA Key %02u : " _GREEN_("%s"), curaid, keyno, sprint_hex(aeskeyList[curkey], 16)); foundKeys[1][keyno][0] = 0x01; *result = true; memcpy(&foundKeys[1][keyno][1], aeskeyList[curkey], 16); @@ -1113,7 +1091,7 @@ static int AuthCheckDesfire(DesfireContext_t *dctx, DesfireSetKeyNoClear(dctx, keyno, T_AES, aeskeyList[curkey]); res = DesfireAuthenticate(dctx, secureChannel, false); if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "AID 0x%06X, Found AES Key %02u... " _GREEN_("%s"), curaid, keyno, sprint_hex_inrow(aeskeyList[curkey], 16)); + PrintAndLogEx(SUCCESS, "AID 0x%06X, Found AES Key %02u : " _GREEN_("%s"), curaid, keyno, sprint_hex(aeskeyList[curkey], 16)); foundKeys[2][keyno][0] = 0x01; *result = true; memcpy(&foundKeys[2][keyno][1], aeskeyList[curkey], 16); @@ -1145,7 +1123,7 @@ static int AuthCheckDesfire(DesfireContext_t *dctx, DesfireSetKeyNoClear(dctx, keyno, T_3K3DES, k3kkeyList[curkey]); res = DesfireAuthenticate(dctx, secureChannel, false); if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "AID 0x%06X, Found 3TDEA Key %02u... " _GREEN_("%s"), curaid, keyno, sprint_hex_inrow(k3kkeyList[curkey], 24)); + PrintAndLogEx(SUCCESS, "AID 0x%06X, Found 3TDEA Key %02u : " _GREEN_("%s"), curaid, keyno, sprint_hex(k3kkeyList[curkey], 24)); foundKeys[3][keyno][0] = 0x01; *result = true; memcpy(&foundKeys[3][keyno][1], k3kkeyList[curkey], 16); @@ -1537,7 +1515,6 @@ static int CmdHF14aDesDetect(const char *Cmd) { arg_str0(NULL, "schann", "", "Secure channel"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "isoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."), - arg_str0(NULL, "dfname", "", "Application ISO DF Name (5-16 hex bytes, big endian)"), arg_str0("f", "file", "", "Filename of dictionary"), arg_lit0(NULL, "save", "Save found key and parameters to defaults"), arg_param_end @@ -1551,7 +1528,7 @@ static int CmdHF14aDesDetect(const char *Cmd) { int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, &securechann, DCMMACed, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -1559,13 +1536,13 @@ static int CmdHF14aDesDetect(const char *Cmd) { uint8_t dict_filename[FILE_PATH_SIZE + 2] = {0}; int dict_filenamelen = 0; - if (CLIParamStrToBuf(arg_get_str(ctx, 14), dict_filename, FILE_PATH_SIZE, &dict_filenamelen)) { + if (CLIParamStrToBuf(arg_get_str(ctx, 13), dict_filename, FILE_PATH_SIZE, &dict_filenamelen)) { PrintAndLogEx(FAILED, "File name too long or invalid."); CLIParserFree(ctx); return PM3_EINVARG; } - bool save = arg_get_lit(ctx, 15); + bool save = arg_get_lit(ctx, 14); SetAPDULogging(APDULogging); CLIParserFree(ctx); @@ -1866,7 +1843,7 @@ static int CmdHF14aDesMAD(const char *Cmd) { DesfireContext_t dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, &securechann, DCMPlain, &appid, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMPlain, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -2042,7 +2019,7 @@ static int CmdHF14ADesSelectApp(const char *Cmd) { DesfireContext_t dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, &securechann, DCMPlain, &appid, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMPlain, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -2164,7 +2141,7 @@ static int CmdHF14ADesBruteApps(const char *Cmd) { DesfireContext_t dctx; int securechann = defaultSecureChannel; - int res = CmdDesGetSessionParameters(ctx, &dctx, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &securechann, DCMNone, NULL, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &securechann, DCMNone, NULL, NULL); if (res) { CLIParserFree(ctx); return res; @@ -2199,32 +2176,25 @@ static int CmdHF14ADesBruteApps(const char *Cmd) { reverse_array(startAid, 3); reverse_array(endAid, 3); - uint32_t idStart = DesfireAIDByteToUint(startAid); uint32_t idEnd = DesfireAIDByteToUint(endAid); - if (idStart > idEnd) { PrintAndLogEx(ERR, "Start should be lower than end. start: %06x end: %06x", idStart, idEnd); return PM3_EINVARG; } - - PrintAndLogEx(INFO, "Bruteforce from " _YELLOW_("%06x") " to " _YELLOW_("%06x"), idStart, idEnd); + PrintAndLogEx(INFO, "Bruteforce from %06x to %06x", idStart, idEnd); PrintAndLogEx(INFO, "Enumerating through all AIDs manually, this will take a while!"); - for (uint32_t id = idStart; id <= idEnd && id >= idStart; id += idIncrement) { + if (kbd_enter_pressed()) break; - if (kbd_enter_pressed()) { - break; - } - - float progress = ((id - idStart) / (idEnd - idStart)); - PrintAndLogEx(INPLACE, "Progress " _YELLOW_("%0.1f") " %% current AID: %06X", progress, id); + int progress = ((id - idStart) * 100) / ((idEnd - idStart)); + PrintAndLogEx(INPLACE, "Progress: %d %%, current AID: %06X", progress, id); res = DesfireSelectAIDHexNoFieldOn(&dctx, id); if (res == PM3_SUCCESS) { printf("\33[2K\r"); // clear current line before printing - PrintAndLogEx(SUCCESS, "Got new APPID " _GREEN_("%06X"), id); + PrintAndLogEx(SUCCESS, "Got new APPID %06X", id); } } @@ -2249,8 +2219,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { "hf mfdes auth -n 0 -t des -k 0000000000000000 --kdf none -> select PICC level and authenticate with key num=0, key type=des, key=00..00 and key derivation = none\n" "hf mfdes auth -n 0 -t aes -k 00000000000000000000000000000000 -> select PICC level and authenticate with key num=0, key type=aes, key=00..00 and key derivation = none\n" "hf mfdes auth -n 0 -t des -k 0000000000000000 --save -> select PICC level and authenticate and in case of successful authentication - save channel parameters to defaults\n" - "hf mfdes auth --aid 123456 -> select application 123456 and authenticate via parameters from `default` command\n" - "hf mfdes auth --dfname D2760000850100 -n 0 -t aes -k 00000000000000000000000000000000 -> select DF by name and authenticate"); + "hf mfdes auth --aid 123456 -> select application 123456 and authenticate via parameters from `default` command"); void *argtable[] = { arg_param_begin, @@ -2266,7 +2235,6 @@ static int CmdHF14ADesAuth(const char *Cmd) { arg_str0(NULL, "schann", "", "Secure channel"), arg_str0(NULL, "aid", "", "Application ID of application for some parameters (3 hex bytes, big endian)"), arg_str0(NULL, "isoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"), - arg_str0(NULL, "dfname", "", "Application ISO DF Name (5-16 hex bytes, big endian)"), arg_lit0(NULL, "save", "saves channels parameters to defaults if authentication succeeds"), arg_param_end }; @@ -2279,13 +2247,13 @@ static int CmdHF14ADesAuth(const char *Cmd) { int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, &securechann, DCMPlain, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMPlain, &id, &selectway); if (res) { CLIParserFree(ctx); return res; } - bool save = arg_get_lit(ctx, 14); + bool save = arg_get_lit(ctx, 13); SetAPDULogging(APDULogging); CLIParserFree(ctx); @@ -2297,9 +2265,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { return res; } - if (dctx.selectedDFNameLen > 0) { - PrintAndLogEx(SUCCESS, "DF selected and authenticated " _GREEN_("successfully")); - } else if (DesfireMFSelected(selectway, id)) + if (DesfireMFSelected(selectway, id)) PrintAndLogEx(SUCCESS, "PICC selected and authenticated " _GREEN_("succesfully")); else PrintAndLogEx(SUCCESS, "Application " _CYAN_("%s") " selected and authenticated " _GREEN_("succesfully"), DesfireWayIDStr(selectway, id)); @@ -2377,7 +2343,7 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) { int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, &securechann, DCMEncrypted, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMEncrypted, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -2492,7 +2458,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, &securechann, DCMEncrypted, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMEncrypted, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -2655,7 +2621,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { DesfireContext_t dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 12, 0, 0, &securechann, DCMMACed, &appid, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 12, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -2818,7 +2784,7 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) { DesfireContext_t dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, &securechann, DCMMACed, &appid, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -2856,8 +2822,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. Any card's key needs to be provided. ", "hf mfdes getuid -> execute with default factory setup\n" - "hf mfdes getuid --isoid df01 -t aes --schan lrp -> for desfire lights default settings\n" - "hf mfdes getuid --dfname D2760000850100 -> select DF by name and get UID"); + "hf mfdes getuid --isoid df01 -t aes --schan lrp -> for desfire lights default settings"); void *argtable[] = { arg_param_begin, @@ -2873,7 +2838,6 @@ static int CmdHF14ADesGetUID(const char *Cmd) { arg_str0(NULL, "schann", "", "Secure channel"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "isoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"), - arg_str0(NULL, "dfname", "", "Application ISO DF Name (5-16 hex bytes, big endian)"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -2885,7 +2849,7 @@ static int CmdHF14ADesGetUID(const char *Cmd) { int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, &securechann, DCMEncrypted, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMEncrypted, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -2963,7 +2927,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { DesfireContext_t dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, &securechann, DCMMACed, &appid, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -3010,7 +2974,6 @@ static int CmdHF14ADesGetFreeMem(const char *Cmd) { arg_str0("c", "ccset", "", "Communicaton command set"), arg_str0(NULL, "schann", "", "Secure channel"), arg_lit0(NULL, "no-auth", "Execute without authentication"), - arg_str0(NULL, "dfname", "", "Application ISO DF Name (5-16 hex bytes, big endian)"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -3022,9 +2985,7 @@ static int CmdHF14ADesGetFreeMem(const char *Cmd) { DesfireContext_t dctx; int securechann = defaultSecureChannel; - uint32_t id = 0x000000; - DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 12, &securechann, (noauth) ? DCMPlain : DCMMACed, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, &securechann, (noauth) ? DCMPlain : DCMMACed, NULL, NULL); if (res) { CLIParserFree(ctx); return res; @@ -3033,7 +2994,7 @@ static int CmdHF14ADesGetFreeMem(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose); + res = DesfireSelectAndAuthenticateEx(&dctx, securechann, 0x000000, noauth, verbose); if (res != PM3_SUCCESS) { DropField(); return res; @@ -3086,7 +3047,7 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { DesfireContext_t dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, &securechann, DCMEncrypted, &appid, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMEncrypted, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -3133,8 +3094,7 @@ static int CmdHF14ADesGetKeyVersions(const char *Cmd) { "--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\n" - "hf mfdes getkeyversions --aid 123456 --keynum 0d --no-auth -> get key version without authentication\n"\ - "hf mfdes getkeyversions --dfname D2760000850100 --keynum 00 -> select DF by name and get key versions"); + "hf mfdes getkeyversions --aid 123456 --keynum 0d --no-auth -> get key version without authentication"); void *argtable[] = { arg_param_begin, @@ -3150,38 +3110,36 @@ static int CmdHF14ADesGetKeyVersions(const char *Cmd) { arg_str0(NULL, "schann", "", "Secure channel"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "isoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."), - arg_str0(NULL, "dfname", "", "Application ISO DF Name (5-16 hex bytes, big endian)"), arg_str0(NULL, "keynum", "", "Key number/count (1 hex byte). (def: 0x00)"), arg_str0(NULL, "keyset", "", "Keyset number (1 hex byte)"), 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, 16); + bool noauth = arg_get_lit(ctx, 15); DesfireContext_t dctx; int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, &securechann, DCMMACed, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway); if (res) { CLIParserFree(ctx); return res; } uint32_t keynum32 = 0x00; - if (CLIGetUint32Hex(ctx, 14, 0x00, &keynum32, NULL, 1, "Key number must have 1 byte length")) { + if (CLIGetUint32Hex(ctx, 13, 0x00, &keynum32, NULL, 1, "Key number must have 1 byte length")) { CLIParserFree(ctx); return PM3_EINVARG; } uint32_t keysetnum32 = 0x00; bool keysetpresent = false; - if (CLIGetUint32Hex(ctx, 15, 0x00, &keysetnum32, &keysetpresent, 1, "Keyset number must have 1 byte length")) { + if (CLIGetUint32Hex(ctx, 14, 0x00, &keysetnum32, &keysetpresent, 1, "Keyset number must have 1 byte length")) { CLIParserFree(ctx); return PM3_EINVARG; } @@ -3238,8 +3196,7 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { CLIParserInit(&ctx, "hf mfdes getkeysettings", "Get key settings for card level or application level.", "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\n"\ - "hf mfdes getkeysettings --dfname D2760000850100 -> select DF by name and get key settings"); + "hf mfdes getkeysettings --aid 123456 -> get app 123456 key settings with default key/channel setup"); void *argtable[] = { arg_param_begin, @@ -3254,7 +3211,6 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { arg_str0("c", "ccset", "", "Communicaton command set"), arg_str0(NULL, "schann", "", "Secure channel"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), - arg_str0(NULL, "dfname", "", "Application ISO DF Name (5-16 hex bytes, big endian)"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -3265,8 +3221,7 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { DesfireContext_t dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 12, &securechann, DCMMACed, &appid, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -3344,7 +3299,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { DesfireContext_t dctx; int securechann = defaultSecureChannel; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, &securechann, DCMMACed, NULL, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, &securechann, DCMMACed, NULL, NULL); if (res) { CLIParserFree(ctx); return res; @@ -3416,7 +3371,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { DesfireContext_t dctx; int securechann = defaultSecureChannel; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, &securechann, DCMMACed, NULL, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, &securechann, DCMMACed, NULL, NULL); if (res) { CLIParserFree(ctx); return res; @@ -3463,8 +3418,7 @@ static int CmdHF14ADesGetFileIDs(const char *Cmd) { CLIParserInit(&ctx, "hf mfdes getfileids", "Get File IDs list from card. Master key needs to be provided or flag --no-auth set.", "hf mfdes getfileids --aid 123456 -> execute with defaults from `default` command\n" - "hf mfdes getfileids -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 -> execute with default factory setup\n" - "hf mfdes getfileids --dfname D2760000850100 -> select DF by name and get file IDs"); + "hf mfdes getfileids -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 -> execute with default factory setup"); void *argtable[] = { arg_param_begin, @@ -3480,7 +3434,6 @@ static int CmdHF14ADesGetFileIDs(const char *Cmd) { arg_str0(NULL, "schann", "", "Secure channel"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "isoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."), - arg_str0(NULL, "dfname", "", "Application ISO DF Name (5-16 hex bytes, big endian)"), arg_lit0(NULL, "no-auth", "Execute without authentication"), arg_param_end }; @@ -3488,13 +3441,13 @@ static int CmdHF14ADesGetFileIDs(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - bool noauth = arg_get_lit(ctx, 14); + bool noauth = arg_get_lit(ctx, 13); DesfireContext_t dctx; int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, &securechann, DCMMACed, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -3510,7 +3463,6 @@ static int CmdHF14ADesGetFileIDs(const char *Cmd) { return res; } - uint8_t buf[APDU_RES_LEN] = {0}; size_t buflen = 0; @@ -3526,7 +3478,7 @@ static int CmdHF14ADesGetFileIDs(const char *Cmd) { for (int i = 0; i < buflen; i++) PrintAndLogEx(INFO, "File ID: %02x", buf[i]); } else { - PrintAndLogEx(INFO, "There are no files in the application %06x", id); + PrintAndLogEx(INFO, "There is no files in the application %06x", id); } DropField(); @@ -3540,8 +3492,7 @@ static int CmdHF14ADesGetFileISOIDs(const char *Cmd) { "hf mfdes getfileisoids --aid 123456 -> execute with defaults from `default` command\n" "hf mfdes getfileisoids -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 -> execute with default factory setup\n" "hf mfdes getfileisoids --isoid df01 -> get iso file ids from Desfire Light with factory card settings\n" - "hf mfdes getfileisoids --isoid df01 --schann lrp -t aes -> get iso file ids from Desfire Light via lrp channel with default key authentication\n" - "hf mfdes getfileisoids --dfname D2760000850100 -> select DF by name and get file ISO IDs"); + "hf mfdes getfileisoids --isoid df01 --schann lrp -t aes -> get iso file ids from Desfire Light via lrp channel with default key authentication"); void *argtable[] = { arg_param_begin, @@ -3557,7 +3508,6 @@ static int CmdHF14ADesGetFileISOIDs(const char *Cmd) { arg_str0(NULL, "schann", "", "Secure channel"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "isoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."), - arg_str0(NULL, "dfname", "", "Application ISO DF Name (5-16 hex bytes, big endian)"), arg_lit0(NULL, "no-auth", "Execute without authentication"), arg_param_end }; @@ -3565,13 +3515,13 @@ static int CmdHF14ADesGetFileISOIDs(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - bool noauth = arg_get_lit(ctx, 14); + bool noauth = arg_get_lit(ctx, 13); DesfireContext_t dctx; int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, &securechann, DCMMACed, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -3602,7 +3552,7 @@ static int CmdHF14ADesGetFileISOIDs(const char *Cmd) { for (int i = 0; i < buflen; i += 2) PrintAndLogEx(INFO, "File ID: %04x", MemLeToUint2byte(&buf[i])); } else { - PrintAndLogEx(INFO, "There are no files in the application %06x", id); + PrintAndLogEx(INFO, "There is no files in the application %06x", id); } DropField(); @@ -3615,8 +3565,7 @@ static int CmdHF14ADesGetFileSettings(const char *Cmd) { "Get File Settings from file from application. Master key needs to be provided or flag --no-auth set (depend on cards settings).", "hf mfdes getfilesettings --aid 123456 --fid 01 -> execute with defaults from `default` command\n" "hf mfdes getfilesettings --isoid df01 --fid 00 --no-auth -> get file settings with select by iso id\n" - "hf mfdes getfilesettings -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 --fid 01 -> execute with default factory setup\n" - "hf mfdes getfilesettings --dfname D2760000850100 --fid 01 -> select DF by name and get file settings"); + "hf mfdes getfilesettings -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 --fid 01 -> execute with default factory setup"); void *argtable[] = { arg_param_begin, @@ -3632,7 +3581,6 @@ static int CmdHF14ADesGetFileSettings(const char *Cmd) { arg_str0(NULL, "schann", "", "Secure channel"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "isoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"), - arg_str0(NULL, "dfname", "", "Application ISO DF Name (5-16 hex bytes, big endian)"), arg_str0(NULL, "fid", "", "File ID (1 hex byte). (def: 1)"), arg_lit0(NULL, "no-auth", "Execute without authentication"), arg_param_end @@ -3641,20 +3589,20 @@ static int CmdHF14ADesGetFileSettings(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - bool noauth = arg_get_lit(ctx, 15); + bool noauth = arg_get_lit(ctx, 14); DesfireContext_t dctx; int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, &securechann, DCMMACed, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway); if (res) { CLIParserFree(ctx); return res; } uint32_t fileid = 1; - if (CLIGetUint32Hex(ctx, 14, 1, &fileid, NULL, 1, "File ID must have 1 byte length")) { + if (CLIGetUint32Hex(ctx, 13, 1, &fileid, NULL, 1, "File ID must have 1 byte length")) { CLIParserFree(ctx); return PM3_EINVARG; } @@ -3679,9 +3627,8 @@ static int CmdHF14ADesGetFileSettings(const char *Cmd) { return PM3_ESOFT; } - if (verbose) { + if (verbose) PrintAndLogEx(INFO, "%s file %02x settings[%zu]: %s", DesfireWayIDStr(selectway, id), fileid, buflen, sprint_hex(buf, buflen)); - } DesfirePrintFileSettings(buf, buflen); @@ -3824,7 +3771,7 @@ static int CmdHF14ADesChFileSettings(const char *Cmd) { int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, &securechann, DCMEncrypted, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMEncrypted, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -3971,7 +3918,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { DesfireContext_t dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, &securechann, DCMMACed, &appid, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -4075,7 +4022,7 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { arg_lit0("a", "apdu", "Show APDU requests and responses"), arg_lit0("v", "verbose", "Verbose output"), arg_int0("n", "keyno", "", "Key number"), - arg_str0("t", "algo", "", "Crypt algo (deft: 2TDEA)"), + arg_str0("t", "algo", "", "Crypt algo"), arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), arg_str0(NULL, "kdf", "", "Key Derivation Function (KDF)"), arg_str0("i", "kdfi", "", "KDF input (1-31 hex bytes)"), @@ -4108,7 +4055,7 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { DesfireContext_t dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, &securechann, DCMMACed, &appid, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -4235,7 +4182,7 @@ static int CmdHF14ADesCreateRecordFile(const char *Cmd) { DesfireContext_t dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, &securechann, DCMMACed, &appid, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); if (res) { CLIParserFree(ctx); return res; @@ -4353,7 +4300,7 @@ static int CmdHF14ADesCreateTrMACFile(const char *Cmd) { int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, &securechann, DCMEncrypted, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMEncrypted, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -4460,7 +4407,7 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) { int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, &securechann, DCMMACed, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -4515,7 +4462,7 @@ static int CmdHF14ADesValueOperations(const char *Cmd) { arg_lit0("a", "apdu", "Show APDU requests and responses"), arg_lit0("v", "verbose", "Verbose output"), arg_int0("n", "keyno", "", "Key number"), - arg_str0("t", "algo", "", "Crypt algo (deft: 2TDEA)"), + arg_str0("t", "algo", "", "Crypt algo"), arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), arg_str0(NULL, "kdf", "", "Key Derivation Function (KDF)"), arg_str0("i", "kdfi", "", "KDF input (1-31 hex bytes)"), @@ -4540,7 +4487,7 @@ static int CmdHF14ADesValueOperations(const char *Cmd) { int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, &securechann, DCMMACed, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -4710,7 +4657,7 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) { int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, &securechann, DCMMACed, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -5120,7 +5067,7 @@ static int CmdHF14ADesReadData(const char *Cmd) { int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 17, 0, &securechann, DCMMACed, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 17, &securechann, DCMMACed, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -5295,7 +5242,7 @@ static int CmdHF14ADesWriteData(const char *Cmd) { int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 20, 0, &securechann, DCMMACed, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 20, &securechann, DCMMACed, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -5595,8 +5542,7 @@ static int CmdHF14ADesLsFiles(const char *Cmd) { "This commands List files inside application AID / ISOID.\n" "Master key needs to be provided or flag --no-auth set (depend on cards settings).", "hf mfdes lsfiles --aid 123456 -> AID 123456, list files using `default` command creds\n" - "hf mfdes lsfiles --isoid df01 --no-auth -> list files for DESFire light\n" - "hf mfdes lsfiles --dfname D2760000850100 -> select DF by name and list files"); + "hf mfdes lsfiles --isoid df01 --no-auth -> list files for DESFire light"); void *argtable[] = { arg_param_begin, @@ -5612,7 +5558,6 @@ static int CmdHF14ADesLsFiles(const char *Cmd) { arg_str0(NULL, "schann", "", "Secure channel"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "isoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"), - arg_str0(NULL, "dfname", "", "Application ISO DF Name (5-16 hex bytes, big endian)"), arg_lit0(NULL, "no-auth", "Execute without authentication"), arg_param_end }; @@ -5620,13 +5565,13 @@ static int CmdHF14ADesLsFiles(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - bool noauth = arg_get_lit(ctx, 14); + bool noauth = arg_get_lit(ctx, 13); DesfireContext_t dctx; int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, &securechann, DCMMACed, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -5652,9 +5597,9 @@ static int CmdHF14ADesLsFiles(const char *Cmd) { } if (filescount == 0) { - PrintAndLogEx(INFO, "There are no files in the %s", DesfireWayIDStr(selectway, id)); + PrintAndLogEx(INFO, "There is no files in the %s", DesfireWayIDStr(selectway, id)); DropField(); - return PM3_SUCCESS; + return res; } PrintAndLogEx(INFO, "------------------------------------------ " _CYAN_("File list") " -----------------------------------------------------"); @@ -5670,8 +5615,7 @@ static int CmdHF14ADesLsApp(const char *Cmd) { CLIParserInit(&ctx, "hf mfdes lsapp", "Show application list. Master key needs to be provided or flag --no-auth set (depend on cards settings).", "hf mfdes lsapp -> show application list with defaults from `default` command\n" - "hf mfdes lsapp --files -> show application list and show each file type/settings/etc\n" - "hf mfdes lsapp --dfname D2760000850100 -> list apps after selecting DF by name"); + "hf mfdes lsapp --files -> show application list and show each file type/settings/etc"); void *argtable[] = { arg_param_begin, @@ -5688,7 +5632,6 @@ static int CmdHF14ADesLsApp(const char *Cmd) { arg_lit0(NULL, "no-auth", "Execute without authentication"), arg_lit0(NULL, "no-deep", "not to check authentication commands that avail for any application"), arg_lit0(NULL, "files", "scan files and print file settings"), - arg_str0(NULL, "dfname", "", "Application ISO DF Name (5-16 hex bytes, big endian)"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -5701,7 +5644,7 @@ static int CmdHF14ADesLsApp(const char *Cmd) { DesfireContext_t dctx; int securechann = defaultSecureChannel; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 14, &securechann, (noauth) ? DCMPlain : DCMMACed, NULL, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, &securechann, (noauth) ? DCMPlain : DCMMACed, NULL, NULL); if (res) { CLIParserFree(ctx); return res; @@ -5753,7 +5696,6 @@ static int CmdHF14ADesDump(const char *Cmd) { arg_str0(NULL, "schann", "", "Secure channel"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "isoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"), - arg_str0(NULL, "dfname", "", "Application ISO DF Name (5-16 hex bytes, big endian)"), arg_str0("l", "length", "", "Maximum length for read data files (3 hex bytes, big endian)"), arg_lit0(NULL, "no-auth", "Execute without authentication"), arg_param_end @@ -5762,20 +5704,20 @@ static int CmdHF14ADesDump(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - bool noauth = arg_get_lit(ctx, 15); + bool noauth = arg_get_lit(ctx, 14); DesfireContext_t dctx; int securechann = defaultSecureChannel; uint32_t id = 0x000000; DesfireISOSelectWay selectway = ISW6bAID; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, &securechann, (noauth) ? DCMPlain : DCMMACed, &id, &selectway); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, (noauth) ? DCMPlain : DCMMACed, &id, &selectway); if (res) { CLIParserFree(ctx); return res; } uint32_t maxlength = 0; - if (CLIGetUint32Hex(ctx, 14, 0, &maxlength, NULL, 3, "Length parameter must have 3 byte length")) { + if (CLIGetUint32Hex(ctx, 13, 0, &maxlength, NULL, 3, "Length parameter must have 3 byte length")) { CLIParserFree(ctx); return PM3_EINVARG; } @@ -5886,7 +5828,6 @@ static command_t CommandTable[] = { {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("Files") " -----------------------"}, {"getfileids", CmdHF14ADesGetFileIDs, IfPm3Iso14443a, "Get File IDs list"}, {"getfileisoids", CmdHF14ADesGetFileISOIDs, IfPm3Iso14443a, "Get File ISO IDs list"}, - {"lsfile", CmdHF14ADesLsFiles, IfPm3Iso14443a, "Show all files list"}, {"lsfiles", CmdHF14ADesLsFiles, IfPm3Iso14443a, "Show all files list"}, {"dump", CmdHF14ADesDump, IfPm3Iso14443a, "Dump all files"}, {"createfile", CmdHF14ADesCreateFile, IfPm3Iso14443a, "Create Standard/Backup File"}, diff --git a/client/src/cmdhfmfhard.c b/client/src/cmdhfmfhard.c index 885162437..8381a4c8d 100644 --- a/client/src/cmdhfmfhard.c +++ b/client/src/cmdhfmfhard.c @@ -127,6 +127,7 @@ static void print_progress_header(void) { get_SIMD_instruction_set(instr_set); snprintf(progress_text, sizeof(progress_text), "Start using " _YELLOW_("%d") " threads and " _YELLOW_("%s") " SIMD core", num_CPUs(), instr_set); + PrintAndLogEx(INFO, "Hardnested attack starting..."); PrintAndLogEx(INFO, "---------+---------+---------------------------------------------------------+-----------------+-------"); PrintAndLogEx(INFO, " | | | Expected to brute force"); PrintAndLogEx(INFO, " Time | #nonces | Activity | #states | time "); @@ -135,16 +136,12 @@ static void print_progress_header(void) { } void hardnested_print_progress(uint32_t nonces, const char *activity, float brute_force, uint64_t min_diff_print_time) { - static uint64_t last_print_time = 0; - if (msclock() - last_print_time >= min_diff_print_time) { - last_print_time = msclock(); uint64_t total_time = msclock() - start_time; float brute_force_time = brute_force / brute_force_per_second; char brute_force_time_string[20]; - if (brute_force_time < 90) { snprintf(brute_force_time_string, sizeof(brute_force_time_string), "%2.0fs", brute_force_time); } else if (brute_force_time < 60 * 90) { @@ -154,24 +151,7 @@ void hardnested_print_progress(uint32_t nonces, const char *activity, float brut } else { snprintf(brute_force_time_string, sizeof(brute_force_time_string), "%2.0fd", brute_force_time / (60 * 60 * 24)); } - - if (strlen(activity) > 67) { - PrintAndLogEx(INFO, " %7.0f | %7u | %-82s | %15.0f | %5s" - , (float)total_time / 1000.0 - , nonces - , activity - , brute_force - , brute_force_time_string - ); - } else { - PrintAndLogEx(INFO, " %7.0f | %7u | %-55s | %15.0f | %5s" - , (float)total_time / 1000.0 - , nonces - , activity - , brute_force - , brute_force_time_string - ); - } + PrintAndLogEx(INFO, " %7.0f | %7u | %-55s | %15.0f | %5s", (float)total_time / 1000.0, nonces, activity, brute_force, brute_force_time_string); } } @@ -506,14 +486,8 @@ static void init_bitflip_bitarrays(void) { effective_bitflip[odd_even][num_effective_bitflips[odd_even]] = 0x400; // EndOfList marker } { - char progress_text[100]; - memset(progress_text, 0, sizeof(progress_text)); - snprintf(progress_text, sizeof(progress_text), "Loaded " _YELLOW_("%u") " RAW / " _YELLOW_("%u") " LZ4 / " _YELLOW_("%u") " BZ2 in %4"PRIu64" ms" - , nraw - , nlz4 - , nbz2 - , msclock() - init_bitflip_bitarrays_starttime - ); + char progress_text[80]; + snprintf(progress_text, sizeof(progress_text), "Loaded %u RAW / %u LZ4 / %u BZ2 in %"PRIu64" ms", nraw, nlz4, nbz2, msclock() - init_bitflip_bitarrays_starttime); hardnested_print_progress(0, progress_text, (float)(1LL << 47), 0); } uint16_t i = 0; @@ -2507,10 +2481,8 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc free_candidates_memory(candidates); candidates = NULL; } else { - pre_XOR_nonces(); prepare_bf_test_nonces(nonces, best_first_bytes[0]); - for (uint8_t j = 0; j < NUM_SUMS && !key_found; j++) { float expected_brute_force = nonces[best_first_bytes[0]].expected_num_brute_force; snprintf(progress_text, sizeof(progress_text), "(%d. guess: Sum(a8) = %" PRIu16 ")", j + 1, sums[nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx]); @@ -2572,9 +2544,7 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc int res; if (nonce_file_read) { // use pre-acquired data from file nonces.bin - res = read_nonce_file(filename); - if (res != PM3_SUCCESS) { free_bitflip_bitarrays(); free_nonces_memory(); @@ -2584,16 +2554,12 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc free_part_sum_bitarrays(); return res; } - hardnested_stage = CHECK_1ST_BYTES | CHECK_2ND_BYTES; update_nonce_data(false); float brute_force_depth; shrink_key_space(&brute_force_depth); - } else { // acquire nonces. - res = acquire_nonces(blockNo, keyType, key, trgBlockNo, trgKeyType, nonce_file_write, slow, filename); - if (res != PM3_SUCCESS) { free_bitflip_bitarrays(); free_nonces_memory(); diff --git a/client/src/cmdhfmfp.c b/client/src/cmdhfmfp.c index 6433bcf2e..6007acf53 100644 --- a/client/src/cmdhfmfp.c +++ b/client/src/cmdhfmfp.c @@ -315,7 +315,7 @@ static int mfp_load_keys(uint8_t **pkeyBlock, uint32_t *pkeycnt, uint8_t *userke int len = hex_to_bytes(g_mifare_plus_default_keys[cnt], (uint8_t *)(*pkeyBlock + (*pkeycnt + cnt) * AES_KEY_LEN), AES_KEY_LEN); - PrintAndLogEx(DEBUG, _YELLOW_("%2u") " - %s", *pkeycnt + cnt, sprint_hex_inrow(*pkeyBlock + (*pkeycnt + cnt) * AES_KEY_LEN, AES_KEY_LEN)); + PrintAndLogEx(DEBUG, _YELLOW_("%2d") " - %s", *pkeycnt + cnt, sprint_hex_inrow(*pkeyBlock + (*pkeycnt + cnt) * AES_KEY_LEN, AES_KEY_LEN)); if (len != AES_KEY_LEN) { break; } @@ -1802,6 +1802,9 @@ static int CmdHFMFPChk(const char *Cmd) { t1 = msclock() - t1; PrintAndLogEx(INFO, "\ntime in checkkeys " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, _GREEN_("found keys:")); + // print result char strA[46 + 1] = {0}; char strB[46 + 1] = {0}; diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 1815705de..6ee8e2fd2 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -59,13 +59,11 @@ static int CmdHelp(const char *Cmd); -static const char *key_type[] = { "DataProtKey", "UIDRetrKey", "OriginalityKey" }; - static uint8_t default_aes_keys[][16] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // all zeroes { 0x42, 0x52, 0x45, 0x41, 0x4b, 0x4d, 0x45, 0x49, 0x46, 0x59, 0x4f, 0x55, 0x43, 0x41, 0x4e, 0x21 }, // 3des std key - { 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42, 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46 }, // NFC-key { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, // 0x00-0x0F + { 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42, 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46 }, // NFC-key { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, // all ones { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, // all FF { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }, // 11 22 33 @@ -76,8 +74,8 @@ static uint8_t default_aes_keys[][16] = { static uint8_t default_3des_keys[][16] = { { 0x42, 0x52, 0x45, 0x41, 0x4b, 0x4d, 0x45, 0x49, 0x46, 0x59, 0x4f, 0x55, 0x43, 0x41, 0x4e, 0x21 }, // 3des std key { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // all zeroes - { 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42, 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46 }, // NFC-key { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, // 0x00-0x0F + { 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42, 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46 }, // NFC-key { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, // all ones { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, // all FF { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }, // 11 22 33 @@ -3838,21 +3836,18 @@ static int CmdHF14AMfUSim(const char *Cmd) { "ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n" "from emulator memory. See `hf mfu eload` first. \n" "The UID from emulator memory will be used if not specified.\n" - "See `hf 14a sim -h` to see available types. You want 2, 7 or 13 usually.", + "See `hf 14a sim -h` to see available types. You want 2 or 7 usually.", "hf mfu sim -t 2 --uid 11223344556677 -> MIFARE Ultralight\n" "hf mfu sim -t 7 --uid 11223344556677 -n 5 -> MFU EV1 / NTAG 215 Amiibo\n" - "hf mfu sim -t 7 -> MFU EV1 / NTAG 215 Amiibo\n" - "hf mfu sim -t 13 -> MIFARE Ultralight-C\n" + "hf mfu sim -t 7 -> MFU EV1 / NTAG 215 Amiibo" ); void *argtable[] = { arg_param_begin, - arg_int1("t", "type", "<1..13> ", "Simulation type to use"), + arg_int1("t", "type", "<1..12> ", "Simulation type to use"), arg_str0("u", "uid", "", "<4|7|10> hex bytes UID"), arg_int0("n", "num", "", "Exit simulation after blocks. 0 = infinite"), arg_lit0("v", "verbose", "Verbose output"), - arg_lit0(NULL, "c1", "UL-C Auth - all zero handshake part 1"), - arg_lit0(NULL, "c2", "UL-C Auth - all zero handshake part 2"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -3935,13 +3930,13 @@ static int CmdHF14AMfUAESAuth(const char *Cmd) { " Key index 1... UIDRetrKey\n" " Key index 2... OriginalityKey\n", "hf mfu aesauth\n" - "hf mfu aesauth --key <16 hex bytes> --idx <0..2>" + "hf mfu aesauth --key <16 hex bytes> --index <0..2>" ); void *argtable[] = { arg_param_begin, arg_str0(NULL, "key", "", "AES key (16 hex bytes)"), - arg_int0("i", "idx", "<0..2>", "Key index (def: 0)"), + arg_int0("i", "index", "<0..2>", "Key index, default: 0"), arg_lit0("k", NULL, "Keep field on (only if a key is provided)"), arg_param_end }; @@ -3971,13 +3966,14 @@ static int CmdHF14AMfUAESAuth(const char *Cmd) { } int result = ulaes_requestAuthentication(authKeyPtr, key_index, !keep_field_on); + + const char *key_type[] = { "DataProtKey", "UIDRetrKey", "OriginalityKey" }; if (result == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Authentication with " _YELLOW_("%s") " " _GREEN_("%s") " ( " _GREEN_("ok")" )" - , key_type[key_index] - , sprint_hex_inrow(authKeyPtr, ak_len) - ); + PrintAndLogEx(SUCCESS, "Authentication with " _YELLOW_("%s") " " _GREEN_("%s") " ( " _GREEN_("ok")" )", + key_type[key_index], sprint_hex_inrow(authKeyPtr, ak_len)); } else { - PrintAndLogEx(WARNING, "Authentication with " _YELLOW_("%s") " ( " _RED_("fail") " )", key_type[key_index]); + PrintAndLogEx(WARNING, "Authentication with " _YELLOW_("%s") " ( " _RED_("fail") " )", + key_type[key_index]); } return result; } @@ -5923,6 +5919,12 @@ static int CmdHF14AMfUIncr(const char *Cmd) { increment_cmd[i + 2] = (value >> (8 * i)) & 0xff; } + iso14a_card_select_t card; + if (ul_select(&card) == false) { + PrintAndLogEx(FAILED, "failed to select card, exiting..."); + return PM3_ESOFT; + } + uint64_t tagtype = GetHF14AMfU_Type(); uint64_t tags_with_counter_ul = MFU_TT_UL_EV1_48 | MFU_TT_UL_EV1_128 | MFU_TT_UL_EV1; uint64_t tags_with_counter_ntag = MFU_TT_NTAG_213 | MFU_TT_NTAG_213_F | MFU_TT_NTAG_213_C | MFU_TT_NTAG_213_TT | MFU_TT_NTAG_215 | MFU_TT_NTAG_216; @@ -5948,12 +5950,6 @@ static int CmdHF14AMfUIncr(const char *Cmd) { } } - iso14a_card_select_t card; - if (ul_select(&card) == false) { - PrintAndLogEx(FAILED, "failed to select card, exiting..."); - return PM3_ESOFT; - } - uint8_t current_counter[3] = { 0, 0, 0 }; int len = ulev1_readCounter(counter, current_counter, sizeof(current_counter)); if (len != sizeof(current_counter)) { diff --git a/client/src/cmdhftexkom.c b/client/src/cmdhftexkom.c index 8a6cee6f2..6993d70cf 100644 --- a/client/src/cmdhftexkom.c +++ b/client/src/cmdhftexkom.c @@ -623,7 +623,7 @@ int read_texkom_uid(bool loop, bool verbose) { } } - } while (loop && (kbd_enter_pressed() == false)); + } while (loop && kbd_enter_pressed() == false); return PM3_SUCCESS; } diff --git a/client/src/cmdhftopaz.c b/client/src/cmdhftopaz.c index ca3efdaa3..05069a35b 100644 --- a/client/src/cmdhftopaz.c +++ b/client/src/cmdhftopaz.c @@ -109,7 +109,7 @@ static int topaz_select(uint8_t *atqa, uint8_t atqa_len, uint8_t *rid_response, } // read all of the static memory of a selected Topaz tag. -static int topaz_rall(const uint8_t *uid, uint8_t *response) { +static int topaz_rall(uint8_t *uid, uint8_t *response) { uint16_t resp_len = 124; uint8_t rall_cmd[] = {TOPAZ_RALL, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -1180,7 +1180,7 @@ int readTopazUid(bool loop, bool verbose) { topaz_tag.HR01[0] = rid_response[0]; topaz_tag.HR01[1] = rid_response[1]; - } while (loop && (kbd_enter_pressed() == false)); + } while (loop && kbd_enter_pressed() == false); topaz_switch_off_field(); return res; diff --git a/client/src/cmdhfxerox.c b/client/src/cmdhfxerox.c index 713b7f616..0bec9a1d9 100644 --- a/client/src/cmdhfxerox.c +++ b/client/src/cmdhfxerox.c @@ -593,7 +593,7 @@ int read_xerox_uid(bool loop, bool verbose) { return PM3_ESOFT; } - } while (loop && (kbd_enter_pressed() == false)); + } while (loop && kbd_enter_pressed() == false); return PM3_SUCCESS; } diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index b36c1c97b..0282f6c72 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -83,7 +83,7 @@ int lfsim_wait_check(uint32_t cmd) { for (;;) { if (kbd_enter_pressed()) { SendCommandNG(CMD_BREAK_LOOP, NULL, 0); - PrintAndLogEx(DEBUG, "\naborted via keyboard!"); + PrintAndLogEx(DEBUG, "User aborted"); break; } @@ -462,7 +462,7 @@ int CmdLFCommandRead(const char *Cmd) { return PM3_ETIMEOUT; } - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && kbd_enter_pressed() == false); return ret; } @@ -859,7 +859,7 @@ int CmdLFRead(const char *Cmd) { int ret = PM3_SUCCESS; do { ret = lf_read_internal(realtime, verbose, samples); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && kbd_enter_pressed() == false); if (ret == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "Got " _YELLOW_("%zu") " samples", g_GraphTraceLen); @@ -985,7 +985,7 @@ int CmdLFSniff(const char *Cmd) { int ret = PM3_SUCCESS; do { ret = lf_sniff(realtime, verbose, samples); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && kbd_enter_pressed() == false); return ret; } diff --git a/client/src/cmdlfawid.c b/client/src/cmdlfawid.c index 0f28d823d..9e330844a 100644 --- a/client/src/cmdlfawid.c +++ b/client/src/cmdlfawid.c @@ -349,7 +349,7 @@ static int CmdAWIDReader(const char *Cmd) { do { lf_read(false, 12000); demodAWID(!cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfdestron.c b/client/src/cmdlfdestron.c index a9c6b1bd2..c8cd6c596 100644 --- a/client/src/cmdlfdestron.c +++ b/client/src/cmdlfdestron.c @@ -129,7 +129,7 @@ static int CmdDestronReader(const char *Cmd) { do { lf_read(false, 16000); demodDestron(!cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfem410x.c b/client/src/cmdlfem410x.c index c178eb440..1b4f31d95 100644 --- a/client/src/cmdlfem410x.c +++ b/client/src/cmdlfem410x.c @@ -445,7 +445,7 @@ static int CmdEM410xReader(const char *Cmd) { if (break_first && gs_em410xid != 0) { break; } - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfem4x70.c b/client/src/cmdlfem4x70.c index 8fd80e3d7..75b5da1e7 100644 --- a/client/src/cmdlfem4x70.c +++ b/client/src/cmdlfem4x70.c @@ -587,7 +587,7 @@ static int CmdEM4x70Brute(const char *Cmd) { em4x70_cmd_output_brute_t data; int result = brute_em4x70(&opts, &data); if (result == PM3_EOPABORTED) { - PrintAndLogEx(DEBUG, "\naborted via keyboard!"); + PrintAndLogEx(DEBUG, "User aborted"); } else if (result == PM3_ETIMEOUT) { PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting..."); } else if (result == PM3_SUCCESS) { diff --git a/client/src/cmdlffdxb.c b/client/src/cmdlffdxb.c index 853c10dde..c3034f98f 100644 --- a/client/src/cmdlffdxb.c +++ b/client/src/cmdlffdxb.c @@ -692,7 +692,7 @@ static int CmdFdxBReader(const char *Cmd) { lf_read(false, 10000); ret = demodFDXB(!cm); // be verbose only if not in continuous mode - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); if (old_div != curr_div) { diff --git a/client/src/cmdlfgallagher.c b/client/src/cmdlfgallagher.c index 98e6bf524..b4955290d 100644 --- a/client/src/cmdlfgallagher.c +++ b/client/src/cmdlfgallagher.c @@ -132,7 +132,7 @@ static int CmdGallagherReader(const char *Cmd) { do { lf_read(false, 4096 * 2 + 20); demodGallagher(!cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfguard.c b/client/src/cmdlfguard.c index 8ff8c13d1..9275a5e32 100644 --- a/client/src/cmdlfguard.c +++ b/client/src/cmdlfguard.c @@ -243,7 +243,7 @@ static int CmdGuardReader(const char *Cmd) { do { lf_read(false, 10000); demodGuard(!cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfhid.c b/client/src/cmdlfhid.c index 0e932fccb..1db507df4 100644 --- a/client/src/cmdlfhid.c +++ b/client/src/cmdlfhid.c @@ -215,7 +215,7 @@ static int CmdHIDReader(const char *Cmd) { do { lf_read(false, 16000); demodHID(!cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index dddad1bab..425b0412c 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -498,7 +498,7 @@ static int ht2_check_dictionary(uint32_t key_count, uint8_t *keys, uint8_t keyl if (kbd_enter_pressed()) { SendCommandNG(CMD_BREAK_LOOP, NULL, 0); - PrintAndLogEx(WARNING, "\naborted via keyboard!"); + PrintAndLogEx(INFO, "User aborted"); break; } @@ -912,7 +912,7 @@ static int CmdLFHitagReader(const char *Cmd) { if (ht2_get_uid(&uid)) { PrintAndLogEx(SUCCESS, "UID.... " _GREEN_("%08X"), uid); } - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && kbd_enter_pressed() == false); return PM3_SUCCESS; } @@ -2428,8 +2428,8 @@ int ht2_read_uid(void) { return PM3_ESOFT; } - PrintAndLogEx(SUCCESS, "UID....... " _GREEN_("%08X"), uid); - PrintAndLogEx(SUCCESS, "TYPE...... " _GREEN_("%s"), getHitagTypeStr(uid)); + PrintAndLogEx(SUCCESS, "UID.... " _GREEN_("%08X"), uid); + PrintAndLogEx(SUCCESS, "TYPE... " _GREEN_("%s"), getHitagTypeStr(uid)); return PM3_SUCCESS; } diff --git a/client/src/cmdlfhitaghts.c b/client/src/cmdlfhitaghts.c index de6efcae3..f474e1bd1 100644 --- a/client/src/cmdlfhitaghts.c +++ b/client/src/cmdlfhitaghts.c @@ -182,8 +182,8 @@ int read_hts_uid(void) { return PM3_ESOFT; } - PrintAndLogEx(SUCCESS, "UID....... " _GREEN_("%08X"), uid); - PrintAndLogEx(SUCCESS, "TYPE...... " _GREEN_("%s"), hts_get_type_str(uid)); + PrintAndLogEx(SUCCESS, "UID.... " _GREEN_("%08X"), uid); + PrintAndLogEx(SUCCESS, "TYPE... " _GREEN_("%s"), hts_get_type_str(uid)); return PM3_SUCCESS; } @@ -968,7 +968,7 @@ static int CmdLFHitagSReader(const char *Cmd) { if (hts_get_uid(&uid)) { PrintAndLogEx(SUCCESS, "UID.... " _GREEN_("%08X"), uid); } - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && kbd_enter_pressed() == false); return PM3_SUCCESS; } diff --git a/client/src/cmdlfhitagu.c b/client/src/cmdlfhitagu.c index 59e72aebe..9a561651c 100644 --- a/client/src/cmdlfhitagu.c +++ b/client/src/cmdlfhitagu.c @@ -197,8 +197,8 @@ int read_htu_uid(void) { return PM3_ESOFT; } - PrintAndLogEx(SUCCESS, "UID....... " _GREEN_("%012llX"), uid); - // PrintAndLogEx(SUCCESS, "TYPE...... " _GREEN_("%s"), htu_get_type_str(uid)); + PrintAndLogEx(SUCCESS, "UID.... " _GREEN_("%012llX"), uid); + // PrintAndLogEx(SUCCESS, "TYPE... " _GREEN_("%s"), htu_get_type_str(uid)); return PM3_SUCCESS; } diff --git a/client/src/cmdlfidteck.c b/client/src/cmdlfidteck.c index b6976fe4d..fa498ea74 100644 --- a/client/src/cmdlfidteck.c +++ b/client/src/cmdlfidteck.c @@ -315,7 +315,7 @@ static int CmdIdteckReader(const char *Cmd) { do { lf_read(false, 5000); demodIdteck(NULL, !cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfindala.c b/client/src/cmdlfindala.c index 4efdd3531..87ad4d833 100644 --- a/client/src/cmdlfindala.c +++ b/client/src/cmdlfindala.c @@ -632,7 +632,7 @@ static int CmdIndalaReader(const char *Cmd) { do { lf_read(false, 30000); demodIndalaEx(clk, invert, max_err, !cm); - } while (cm & (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } @@ -1163,12 +1163,12 @@ int getIndalaBits(uint8_t fc, uint16_t cn, uint8_t *bits) { chk += ((cn >> 2) & 1); //y14 == 89 - 30 = 59 chk += (cn & 1); //y16 == 71 - 30 = 41 - if ((chk & 1) == 0) { // If the sum is even, checksum is '10' (binary) = 2. - bits[62] = 1; - bits[63] = 0; - } else { // If the sum is odd, checksum is '01' (binary) = 1. + if ((chk & 1) == 0) { bits[62] = 0; bits[63] = 1; + } else { + bits[62] = 1; + bits[63] = 0; } // add parity diff --git a/client/src/cmdlfio.c b/client/src/cmdlfio.c index a56b6b3a0..865b2b74a 100644 --- a/client/src/cmdlfio.c +++ b/client/src/cmdlfio.c @@ -202,7 +202,7 @@ static int CmdIOProxReader(const char *Cmd) { do { lf_read(false, 12000); demodIOProx(!cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfjablotron.c b/client/src/cmdlfjablotron.c index d0f9305d8..290181ae7 100644 --- a/client/src/cmdlfjablotron.c +++ b/client/src/cmdlfjablotron.c @@ -152,7 +152,7 @@ static int CmdJablotronReader(const char *Cmd) { do { lf_read(false, 16000); demodJablotron(!cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfkeri.c b/client/src/cmdlfkeri.c index 4fc5cac72..fc599a646 100644 --- a/client/src/cmdlfkeri.c +++ b/client/src/cmdlfkeri.c @@ -221,7 +221,7 @@ static int CmdKeriReader(const char *Cmd) { do { lf_read(false, 10000); demodKeri(!cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfmotorola.c b/client/src/cmdlfmotorola.c index 04cf7fe20..99caaa7a3 100644 --- a/client/src/cmdlfmotorola.c +++ b/client/src/cmdlfmotorola.c @@ -179,7 +179,7 @@ static int CmdMotorolaReader(const char *Cmd) { // 64 * 32 * 2 * n-ish lf_read(false, 5000); res = demodMotorola(!cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); // reset back to 125 kHz sc.divisor = LF_DIVISOR_125; diff --git a/client/src/cmdlfnedap.c b/client/src/cmdlfnedap.c index ac50d4851..ac6bea204 100644 --- a/client/src/cmdlfnedap.c +++ b/client/src/cmdlfnedap.c @@ -296,7 +296,7 @@ static int CmdLFNedapReader(const char *Cmd) { do { lf_read(false, 16000); demodNedap(!cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfnexwatch.c b/client/src/cmdlfnexwatch.c index 505ca6d7e..b1a162817 100644 --- a/client/src/cmdlfnexwatch.c +++ b/client/src/cmdlfnexwatch.c @@ -287,7 +287,7 @@ static int CmdNexWatchReader(const char *Cmd) { do { lf_read(false, 20000); demodNexWatch(!cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfnoralsy.c b/client/src/cmdlfnoralsy.c index b10ee7f97..2a0fbd2b2 100644 --- a/client/src/cmdlfnoralsy.c +++ b/client/src/cmdlfnoralsy.c @@ -150,7 +150,7 @@ static int CmdNoralsyReader(const char *Cmd) { do { lf_read(false, 8000); demodNoralsy(!cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfpac.c b/client/src/cmdlfpac.c index 8d00c40df..8d9dbebf4 100644 --- a/client/src/cmdlfpac.c +++ b/client/src/cmdlfpac.c @@ -214,7 +214,7 @@ static int CmdPacReader(const char *Cmd) { do { lf_read(false, 4096 * 2 + 20); demodPac(!cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfparadox.c b/client/src/cmdlfparadox.c index 71aa19ebe..dae518311 100644 --- a/client/src/cmdlfparadox.c +++ b/client/src/cmdlfparadox.c @@ -285,7 +285,7 @@ static int CmdParadoxReader(const char *Cmd) { do { lf_read(false, 10000); demodParadox(!cm, old); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfpcf7931.c b/client/src/cmdlfpcf7931.c index df18617dc..ae19b174f 100644 --- a/client/src/cmdlfpcf7931.c +++ b/client/src/cmdlfpcf7931.c @@ -84,7 +84,7 @@ static int CmdLFPCF7931Reader(const char *Cmd) { PrintAndLogEx(WARNING, "command execution time out"); return PM3_ETIMEOUT; } - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfpresco.c b/client/src/cmdlfpresco.c index 969a054ce..a3f1c89e2 100644 --- a/client/src/cmdlfpresco.c +++ b/client/src/cmdlfpresco.c @@ -160,7 +160,7 @@ static int CmdPrescoReader(const char *Cmd) { do { lf_read(false, 12000); demodPresco(!cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfpyramid.c b/client/src/cmdlfpyramid.c index e29453263..9e24c319b 100644 --- a/client/src/cmdlfpyramid.c +++ b/client/src/cmdlfpyramid.c @@ -231,7 +231,7 @@ static int CmdPyramidReader(const char *Cmd) { do { lf_read(false, 15000); demodPyramid(true); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } @@ -498,28 +498,25 @@ int getPyramidBits(uint32_t fc, uint32_t cn, uint8_t *pyramidBits) { // FSK Demod then try to locate a Farpointe Data (pyramid) ID int detectPyramid(uint8_t *dest, size_t *size, int *waveStartIdx) { - // make sure buffer has data + //make sure buffer has data if (*size < 128 * 50) return -1; - // test samples are not just noise + //test samples are not just noise if (getSignalProperties()->isnoise) return -2; // FSK demodulator RF/50 FSK 10,8 *size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); // pyramid fsk2 - // did we get a good demod? + //did we get a good demod? if (*size < 128) return -3; size_t startIdx = 0; uint8_t preamble[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) { - return -4; // preamble not found - } + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) + return -4; //preamble not found // wrong size? (between to preambles) - if (*size < 128) { - return -5; - } + if (*size < 128) return -5; return (int)startIdx; } diff --git a/client/src/cmdlfsecurakey.c b/client/src/cmdlfsecurakey.c index 30e997421..f4e381e42 100644 --- a/client/src/cmdlfsecurakey.c +++ b/client/src/cmdlfsecurakey.c @@ -161,7 +161,7 @@ static int CmdSecurakeyReader(const char *Cmd) { do { lf_read(false, 8000); demodSecurakey(!cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 49e50902f..96184c87f 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -4694,74 +4694,6 @@ static int CmdT55xxSniff(const char *Cmd) { return PM3_SUCCESS; } -static int CmdT55xxView(const char *Cmd) { - - CLIParserContext *ctx; - CLIParserInit(&ctx, "lf t55xx view", - "Print a T55xx dump file (bin/eml/json)\n", - "lf t55xx view -f lf-t55xx-00000000-11111111-22222222-33333333-dump.bin" - ); - void *argtable[] = { - arg_param_begin, - arg_str1("f", "file", "", "Specify a filename for dump file"), - arg_lit0("v", "verbose", "verbose output"), - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, false); - int fnlen = 0; - char filename[FILE_PATH_SIZE]; - CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); - // bool verbose = arg_get_lit(ctx, 2); - CLIParserFree(ctx); - - if (fnlen == 0) { - PrintAndLogEx(ERR, "Must specify a filename"); - return PM3_EINVARG; - } - - // read dump file - uint32_t *dump = NULL; - size_t bytes_read = 0; - int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, (T55x7_BLOCK_COUNT * 4)); - if (res != PM3_SUCCESS) { - return res; - } - - if (bytes_read != (T55x7_BLOCK_COUNT * 4)) { - free(dump); - PrintAndLogEx(FAILED, "wrong length of dump file. Expected 48 bytes, got %zu", bytes_read); - return PM3_EFILE; - } - - - PrintAndLogEx(INFO, ""); - PrintAndLogEx(SUCCESS, " " _CYAN_("Page 0")); - PrintAndLogEx(SUCCESS, "----+----------+-------"); - PrintAndLogEx(SUCCESS, "blk | hex data | ascii"); - PrintAndLogEx(SUCCESS, "----+----------+-------"); - - uint32_t *pd = dump; - uint8_t tmp[4] = {0}; - for (uint8_t i = 0; i < 8; ++i) { - Uint4byteToMemLe(tmp, *pd); - PrintAndLogEx(SUCCESS, " %02d | %s | %s", i, sprint_hex_inrow(tmp, sizeof(tmp)), sprint_ascii(tmp, 4)); - pd++; - } - PrintAndLogEx(INFO, ""); - PrintAndLogEx(SUCCESS, " " _CYAN_("Page 1")); - PrintAndLogEx(SUCCESS, "----+----------+-------"); - PrintAndLogEx(SUCCESS, "blk | hex data | ascii"); - PrintAndLogEx(SUCCESS, "----+----------+-------"); - for (uint8_t i = 0; i < 4; i++) { - Uint4byteToMemLe(tmp, *pd); - PrintAndLogEx(SUCCESS, " %02d | %s | %s", i, sprint_hex_inrow(tmp, sizeof(tmp)), sprint_ascii(tmp, 4)); - pd++; - } - PrintAndLogEx(NORMAL, ""); - free(dump); - return PM3_SUCCESS; -} - static command_t CommandTable[] = { {"-----------", CmdHelp, AlwaysAvailable, "---------------------------- " _CYAN_("notice") " -----------------------------"}, {"", CmdHelp, AlwaysAvailable, "Remember to run `" _YELLOW_("lf t55xx detect") "` first whenever a new card"}, @@ -4782,7 +4714,6 @@ static command_t CommandTable[] = { {"restore", CmdT55xxRestore, IfPm3Lf, "Restore T55xx card Page 0 / Page 1 blocks"}, {"trace", CmdT55xxReadTrace, AlwaysAvailable, "Show T55x7 traceability data (page 1/ blk 0-1)"}, {"wakeup", CmdT55xxWakeUp, IfPm3Lf, "Send AOR wakeup command"}, - {"view", CmdT55xxView, AlwaysAvailable, "Display content from tag dump file"}, {"write", CmdT55xxWriteBlock, IfPm3Lf, "Write T55xx block data"}, {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("recovery") " ---------------------"}, {"bruteforce", CmdT55xxBruteForce, IfPm3Lf, "Simple bruteforce attack to find password"}, diff --git a/client/src/cmdlfti.c b/client/src/cmdlfti.c index 17d843a7c..4664a344d 100644 --- a/client/src/cmdlfti.c +++ b/client/src/cmdlfti.c @@ -325,7 +325,7 @@ static int CmdTIReader(const char *Cmd) { do { clearCommandBuffer(); SendCommandNG(CMD_LF_TI_READ, NULL, 0); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfviking.c b/client/src/cmdlfviking.c index 7c206af4b..6807e828c 100644 --- a/client/src/cmdlfviking.c +++ b/client/src/cmdlfviking.c @@ -102,7 +102,7 @@ static int CmdVikingReader(const char *Cmd) { do { lf_read(false, 10000); demodViking(true); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfvisa2000.c b/client/src/cmdlfvisa2000.c index 092f38e30..7de1e9334 100644 --- a/client/src/cmdlfvisa2000.c +++ b/client/src/cmdlfvisa2000.c @@ -185,7 +185,7 @@ static int CmdVisa2kReader(const char *Cmd) { do { lf_read(false, 20000); demodVisa2k(!cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdlfzx8211.c b/client/src/cmdlfzx8211.c index 793cc3d54..03fcd6053 100644 --- a/client/src/cmdlfzx8211.c +++ b/client/src/cmdlfzx8211.c @@ -138,7 +138,7 @@ static int CmdzxReader(const char *Cmd) { do { lf_Zx_read(); demodzx(!cm); - } while (cm && (kbd_enter_pressed() == false)); + } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } diff --git a/client/src/cmdmain.c b/client/src/cmdmain.c index 9ab88324b..25bf6cce8 100644 --- a/client/src/cmdmain.c +++ b/client/src/cmdmain.c @@ -48,7 +48,6 @@ #include "commonutil.h" // ARRAYLEN #include "preferences.h" #include "cliparser.h" -#include "cmdmqtt.h" static int CmdHelp(const char *Cmd); @@ -339,7 +338,6 @@ static command_t CommandTable[] = { {"hw", CmdHW, AlwaysAvailable, "{ Hardware commands... }"}, {"lf", CmdLF, AlwaysAvailable, "{ Low frequency commands... }"}, {"mem", CmdFlashMem, IfPm3Flash, "{ Flash memory manipulation... }"}, - {"mqtt", CmdMqtt, AlwaysAvailable, "{ MQTT commmands... }"}, {"nfc", CmdNFC, AlwaysAvailable, "{ NFC commands... }"}, {"piv", CmdPIV, AlwaysAvailable, "{ PIV commands... }"}, {"reveng", CmdRev, AlwaysAvailable, "{ CRC calculations from RevEng software... }"}, diff --git a/client/src/cmdmqtt.c b/client/src/cmdmqtt.c deleted file mode 100644 index 1a0ea15ae..000000000 --- a/client/src/cmdmqtt.c +++ /dev/null @@ -1,422 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. -// -// This program 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 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. -// -// See LICENSE.txt for the text of the license. -//----------------------------------------------------------------------------- -// MQTT commands -//----------------------------------------------------------------------------- -#include "cmdmqtt.h" - -#include "cmdparser.h" -#include "cliparser.h" -#include "mqtt.h" // MQTT support -//#include "mbedtls_sockets.h" // MQTT networkings examples - -#ifndef _WIN32 -#include "posix_sockets.h" // MQTT networkings examples -#else -#include "win32_sockets.h" // MQTT networkings examples -#endif -#include "util_posix.h" // time -#include "fileutils.h" - -#define MQTT_BUFFER_SIZE ( 1 << 16 ) - -static int CmdHelp(const char *Cmd); - -static void mqtt_publish_callback(void **unused, struct mqtt_response_publish *published) { - - if (published == NULL) { - return; - } - - - // note that published->topic_name is NOT null-terminated (here we'll change it to a c-string) - char *topic_name = (char *) calloc(published->topic_name_size + 1, 1); - memcpy(topic_name, published->topic_name, published->topic_name_size); - - const char *msg = published->application_message; - - char *ps = strstr(msg, "Created\": \"proxmark3"); - if (ps) { - int res = saveFileTXT("ice_mqtt", ".json", msg, published->application_message_size, spDefault); - if (res == PM3_SUCCESS) { - PrintAndLogEx(INFO, "Got a json file ( %s )", _GREEN_("ok")); - } - } else { - PrintAndLogEx(SUCCESS, _GREEN_("%s") " - ( %zu ) " _YELLOW_("%s"), topic_name, published->application_message_size, msg); - } - free(topic_name); -} - -static volatile int mqtt_client_should_exit = 0; - -static void *mqtt_client_refresher(void *client) { - while (!mqtt_client_should_exit) { - mqtt_sync((struct mqtt_client *) client); - msleep(100); - } - return NULL; -} -static int mqtt_exit(int status, mqtt_pal_socket_handle sockfd, pthread_t *client_daemon) { - close_nb_socket(sockfd); - if (client_daemon != NULL) { - mqtt_client_should_exit = 1; - pthread_join(*client_daemon, NULL); // Wait for the thread to finish - mqtt_client_should_exit = 0; - } - return status; -} - -/* -static void mqtt_reconnect_client(struct mqtt_client* client, void **reconnect_state_vptr) { - - struct reconnect_state_t *rs = *((struct reconnect_state_t**) reconnect_state_vptr); - - // Close the clients socket if this isn't the initial reconnect call - if (client->error != MQTT_ERROR_INITIAL_RECONNECT) { - close_nb_socket(client->socketfd); - } - - if (client->error != MQTT_ERROR_INITIAL_RECONNECT) { - PrintAndLogEx(INFO, "reconnect_client: called while client was in error state `%s`", mqtt_error_str(client->error)); - } - - int sockfd = open_nb_socket(rs->hostname, rs->port); - if (sockfd == -1) { - PrintAndLogEx(FAILED, "Failed to open socket"); - mqtt_exit(PM3_EFAILED, sockfd, NULL); - } - - // Reinitialize the client. - mqtt_reinit(client, sockfd, rs->sendbuf, rs->sendbufsz, rs->recvbuf, rs->recvbufsz); - - const char* client_id = NULL; - - uint8_t connect_flags = MQTT_CONNECT_CLEAN_SESSION; - - mqtt_connect(client, client_id, NULL, NULL, 0, NULL, NULL, connect_flags, 400); - - mqtt_subscribe(client, rs->topic, 0); -} -*/ - -static int mqtt_receive(const char *addr, const char *port, const char *topic, const char *fn) { - // open the non-blocking TCP socket (connecting to the broker) - mqtt_pal_socket_handle sockfd = open_nb_socket(addr, port); - if (sockfd == -1) { - PrintAndLogEx(FAILED, "Failed to open socket"); - return mqtt_exit(PM3_EFAILED, sockfd, NULL); - } - - uint8_t sendbuf[MQTT_BUFFER_SIZE]; // 64kb sendbuf should be large enough to hold multiple whole mqtt messages - uint8_t recvbuf[MQTT_BUFFER_SIZE]; // 64kb recvbuf should be large enough any whole mqtt message expected to be received - - struct mqtt_client client; - - /* - struct reconnect_state_t rs; - rs.hostname = addr; - rs.port = port; - rs.topic = topic; - rs.sendbuf = sendbuf; - rs.sendbufsz = sizeof(sendbuf); - rs.recvbuf = recvbuf; - rs.recvbufsz = sizeof(recvbuf); - mqtt_init_reconnect(&client, mqtt_reconnect_client, &rs, mqtt_publish_callback); - */ - - mqtt_init(&client, sockfd, sendbuf, sizeof(sendbuf), recvbuf, sizeof(recvbuf), mqtt_publish_callback); - - char cid[20] = "pm3_"; - sprintf(cid + strlen(cid), "%02x%02x%02x%02x" - , rand() % 0xFF - , rand() % 0xFF - , rand() % 0xFF - , rand() % 0xFF - ); - - // Ensure we have a clean session - uint8_t connect_flags = MQTT_CONNECT_CLEAN_SESSION; - // Send connection request to the broker - mqtt_connect(&client, cid, NULL, NULL, 0, NULL, NULL, connect_flags, 400); - - // check that we don't have any errors - if (client.error != MQTT_OK) { - PrintAndLogEx(FAILED, "error: %s", mqtt_error_str(client.error)); - return mqtt_exit(PM3_ESOFT, sockfd, NULL); - } - - // start a thread to refresh the client (handle egress and ingree client traffic) - pthread_t client_daemon; - if (pthread_create(&client_daemon, NULL, mqtt_client_refresher, &client)) { - PrintAndLogEx(FAILED, "Failed to start client daemon"); - return mqtt_exit(PM3_ESOFT, sockfd, NULL); - } - - // subscribe to a topic with a max QoS level of 0 - mqtt_subscribe(&client, topic, 0); - - PrintAndLogEx(INFO, _CYAN_("%s") " listening at " _CYAN_("%s:%s/%s"), cid, addr, port, topic); - PrintAndLogEx(INFO, "Press " _GREEN_("") " to exit"); - - while (kbd_enter_pressed() == false) { - msleep(2000); - }; - - PrintAndLogEx(INFO, _CYAN_("%s") " disconnecting from " _CYAN_("%s"), cid, addr); - return mqtt_exit(PM3_SUCCESS, sockfd, &client_daemon); -} - -static int mqtt_send(const char *addr, const char *port, const char *topic, char *msg, const char *fn) { - - uint8_t *data; - size_t bytes_read = 0; - if (fn != NULL) { - int res = loadFile_TXTsafe(fn, "", (void **)&data, &bytes_read, true); - if (res != PM3_SUCCESS) { - return res; - } - } - - // open the non-blocking TCP socket (connecting to the broker) - int sockfd = open_nb_socket(addr, port); - - if (sockfd == -1) { - PrintAndLogEx(FAILED, "Failed to open socket"); - return mqtt_exit(PM3_EFAILED, sockfd, NULL); - } - - struct mqtt_client client; - uint8_t sendbuf[MQTT_BUFFER_SIZE]; - uint8_t recvbuf[MQTT_BUFFER_SIZE]; - mqtt_init(&client, sockfd, sendbuf, sizeof(sendbuf), recvbuf, sizeof(recvbuf), mqtt_publish_callback); - - char cid[20] = "pm3_"; - sprintf(cid + strlen(cid), "%02x%02x%02x%02x" - , rand() % 0xFF - , rand() % 0xFF - , rand() % 0xFF - , rand() % 0xFF - ); - - // Ensure we have a clean session - uint8_t connect_flags = MQTT_CONNECT_CLEAN_SESSION; - // Send connection request to the broker - mqtt_connect(&client, cid, NULL, NULL, 0, NULL, NULL, connect_flags, 400); - - // check that we don't have any errors - if (client.error != MQTT_OK) { - PrintAndLogEx(FAILED, "error: %s", mqtt_error_str(client.error)); - mqtt_exit(PM3_EFAILED, sockfd, NULL); - } - - // start a thread to refresh the client (handle egress and ingree client traffic) - pthread_t client_daemon; - if (pthread_create(&client_daemon, NULL, mqtt_client_refresher, &client)) { - PrintAndLogEx(FAILED, "Failed to start client daemon"); - mqtt_exit(PM3_EFAILED, sockfd, NULL); - - } - - PrintAndLogEx(INFO, _CYAN_("%s") " is ready", cid); - - if (fn != NULL) { - PrintAndLogEx(INFO, "Publishing file..."); - mqtt_publish(&client, topic, data, bytes_read, MQTT_PUBLISH_QOS_0); - } else { - PrintAndLogEx(INFO, "Publishing message..."); - mqtt_publish(&client, topic, msg, strlen(msg) + 1, MQTT_PUBLISH_QOS_0); - } - - if (client.error != MQTT_OK) { - PrintAndLogEx(INFO, "error: %s", mqtt_error_str(client.error)); - mqtt_exit(PM3_ESOFT, sockfd, &client_daemon); - } - - msleep(4000); - - PrintAndLogEx(INFO, _CYAN_("%s") " disconnecting from " _CYAN_("%s"), cid, addr); - return mqtt_exit(PM3_SUCCESS, sockfd, &client_daemon); -} - -static int CmdMqttSend(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "mqtt send", - "This command send MQTT messages. You can send JSON file\n" - "Default server: proxdump.com:1883 topic: proxdump\n", - "mqtt send --msg \"Hello from Pm3\" --> sending msg to default server/port/topic\n" - "mqtt send -f myfile.json --> sending file to default server/port/topic\n" - "mqtt send --addr test.mosquitto.org -p 1883 --topic pm3 --msg \"custom mqtt server \"\n" - ); - - void *argtable[] = { - arg_param_begin, - arg_str0(NULL, "addr", "", "MQTT server address"), - arg_str0("p", "port", "", "MQTT server port"), - arg_str0(NULL, "topic", "", "MQTT topic"), - arg_str0(NULL, "msg", "", "Message to send over MQTT"), - arg_str0("f", "file", "", "file to send"), - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, false); - - int alen = 0; - char addr[256] = {0x00}; - int res = CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)addr, sizeof(addr), &alen); - - int plen = 0; - char port[10 + 1] = {0x00}; - res = CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)port, sizeof(port), &plen); - - int tlen = 0; - char topic[128] = {0x00}; - res = CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)topic, sizeof(topic), &tlen); - - int mlen = 0; - char msg[128] = {0x00}; - res = CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t *)msg, sizeof(msg), &mlen); - - int fnlen = 0; - char filename[FILE_PATH_SIZE] = {0}; - CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); - - CLIParserFree(ctx); - - // Error message if... an error occured. - if (res) { - PrintAndLogEx(FAILED, "Error parsing input strings"); - return PM3_EINVARG; - } - - if (alen == 0) { - if (strlen(g_session.mqtt_server)) { - strcpy(addr, g_session.mqtt_server); - } else { - strcpy(addr, "proxdump.com"); - } - } - - if (plen == 0) { - if (strlen(g_session.mqtt_port)) { - strcpy(port, g_session.mqtt_port); - } else { - strcpy(port, "1883"); - } - } - - if (tlen == 0) { - if (strlen(g_session.mqtt_topic)) { - strcpy(topic, g_session.mqtt_topic); - } else { - strcpy(topic, "proxdump"); - } - } - - if (fnlen) { - return mqtt_send(addr, port, topic, NULL, filename); - } - - if (mlen) { - return mqtt_send(addr, port, topic, msg, NULL); - } - return PM3_SUCCESS; -} - -static int CmdMqttReceive(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "mqtt receive", - "This command receives MQTT messages. JSON text will be saved to file if detected\n" - "Default server: proxdump.com:1883 topic: proxdump\n", - "mqtt receive --> listening to default server/port/topic\n" - "mqtt receive --addr test.mosquitto.org -p 1883 --topic pm3\n" - ); - - void *argtable[] = { - arg_param_begin, - arg_str0(NULL, "addr", "", "MQTT server address"), - arg_str0("p", "port", "", "MQTT server port"), - arg_str0(NULL, "topic", "", "MQTT topic"), - arg_str0("f", "file", "", "file name to use for received files"), - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, true); - - int alen = 0; - char addr[256] = {0x00}; - int res = CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)addr, sizeof(addr), &alen); - - int plen = 0; - char port[10 + 1] = {0x00}; - res = CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)port, sizeof(port), &plen); - - int tlen = 0; - char topic[128] = {0x00}; - res = CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)topic, sizeof(topic), &tlen); - - int fnlen = 0; - char filename[FILE_PATH_SIZE] = {0}; - CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); - - CLIParserFree(ctx); - - // Error message if... an error occured. - if (res) { - PrintAndLogEx(FAILED, "Error parsing input strings"); - return PM3_EINVARG; - } - - if (alen == 0) { - if (strlen(g_session.mqtt_server)) { - strcpy(addr, g_session.mqtt_server); - } else { - strcpy(addr, "proxdump.com"); - } - } - - if (plen == 0) { - if (strlen(g_session.mqtt_port)) { - strcpy(port, g_session.mqtt_port); - } else { - strcpy(port, "1883"); - } - } - - if (tlen == 0) { - if (strlen(g_session.mqtt_topic)) { - strcpy(topic, g_session.mqtt_topic); - } else { - strcpy(topic, "proxdump"); - } - } - - return mqtt_receive(addr, port, topic, filename); -} - -static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"send", CmdMqttSend, AlwaysAvailable, "Send messages or json file over MQTT"}, - {"receive", CmdMqttReceive, AlwaysAvailable, "Receive message or json file over MQTT"}, - {NULL, NULL, NULL, NULL} -}; - -static int CmdHelp(const char *Cmd) { - (void)Cmd; // Cmd is not used so far - CmdsHelp(CommandTable); - return 0; -} - -int CmdMqtt(const char *Cmd) { - clearCommandBuffer(); - return CmdsParse(CommandTable, Cmd); -} diff --git a/client/src/cmdmqtt.h b/client/src/cmdmqtt.h deleted file mode 100644 index fad58ff8f..000000000 --- a/client/src/cmdmqtt.h +++ /dev/null @@ -1,26 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. -// -// This program 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 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. -// -// See LICENSE.txt for the text of the license. -//----------------------------------------------------------------------------- -// MQTT commands -//----------------------------------------------------------------------------- - -#ifndef CMDMQTT_H__ -#define CMDMQTT_H__ - -#include "common.h" - -int CmdMqtt(const char *Cmd); - -#endif diff --git a/client/src/cmdparser.c b/client/src/cmdparser.c index fc628b947..7421b3f58 100644 --- a/client/src/cmdparser.c +++ b/client/src/cmdparser.c @@ -20,15 +20,11 @@ #include #include -#include // spinlock -#include // system + #include "ui.h" #include "comms.h" #include "util_posix.h" // msleep -#if defined(__MACH__) && defined(__APPLE__) -# include "pthread_spin_lock_shim.h" // spinlock shim for OSX .. -#endif #define MAX_PM3_INPUT_ARGS_LENGTH 4096 @@ -223,30 +219,6 @@ void CmdsHelp(const command_t Commands[]) { PrintAndLogEx(NORMAL, ""); } -static int execute_system_command(const char *command) { - - pthread_spinlock_t sycmd_spinlock; - pthread_spin_init(&sycmd_spinlock, 0); - pthread_spin_lock(&sycmd_spinlock); - - int ret; - -#if defined(_WIN32) - char wrapped_command[255]; - strncat(wrapped_command, "cmd /C \"", 9); - strncat(wrapped_command, command, strlen(command)); - strncat(wrapped_command, "\"", 2); - - ret = system(wrapped_command); -#else - ret = system(command); -#endif - pthread_spin_unlock(&sycmd_spinlock); - pthread_spin_destroy(&sycmd_spinlock); - return ret; -} - - int CmdsParse(const command_t Commands[], const char *Cmd) { if (g_session.client_exe_delay != 0) { @@ -295,9 +267,6 @@ int CmdsParse(const command_t Commands[], const char *Cmd) { return PM3_SUCCESS; } - if (Cmd[0] == '!') { - return execute_system_command(Cmd + 1); - } char cmd_name[128] = {0}; memset(cmd_name, 0, sizeof(cmd_name)); @@ -318,9 +287,8 @@ int CmdsParse(const command_t Commands[], const char *Cmd) { } // Comment - if (cmd_name[0] == '#') { + if (cmd_name[0] == '#') return PM3_SUCCESS; - } // find args, check for -h / --help int tmplen = len; diff --git a/client/src/cmdsmartcard.c b/client/src/cmdsmartcard.c index 6e1c67ba5..46b467f94 100644 --- a/client/src/cmdsmartcard.c +++ b/client/src/cmdsmartcard.c @@ -1469,7 +1469,7 @@ static int CmdPCSC(const char *Cmd) { msleep(300); } - } while (kbd_enter_pressed() == false); + } while (!kbd_enter_pressed()); mbedtls_net_close(&netCtx); mbedtls_net_free(&netCtx); diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index 0f3242345..0e83bf128 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -181,7 +181,7 @@ static uint16_t extractChallenges(uint16_t tracepos, uint16_t traceLen, uint8_t } */ - // extract UL-C KEY when written. + // extract MFU-C KEY when written. switch (frame[0]) { case MIFARE_ULC_AUTH_1: { diff --git a/client/src/cmdwiegand.c b/client/src/cmdwiegand.c index c2d6bb3b1..d29521d53 100644 --- a/client/src/cmdwiegand.c +++ b/client/src/cmdwiegand.c @@ -201,7 +201,7 @@ int CmdWiegandDecode(const char *Cmd) { PrintAndLogEx(ERR, "Binary string contains none <0|1> chars"); return PM3_EINVARG; } - PrintAndLogEx(INFO, "#bits... %d", blen); + PrintAndLogEx(INFO, "Input bin len... %d", blen); } else if (plen) { diff --git a/client/src/crypto/libpcrypto.c b/client/src/crypto/libpcrypto.c index 9d506d8a8..031005ce0 100644 --- a/client/src/crypto/libpcrypto.c +++ b/client/src/crypto/libpcrypto.c @@ -55,15 +55,13 @@ 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) { - for (int i = 0; i < length; i += 8) { + 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) { + 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) { @@ -163,45 +161,6 @@ int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int l return PM3_SUCCESS; } -// NIST Special Publication 800-38A — Recommendation for block cipher modes of operation: methods and techniques, 2001. -int aes256_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length) { - uint8_t iiv[16] = {0}; - if (iv) { - memcpy(iiv, iv, sizeof(iiv)); - } - - mbedtls_aes_context aes; - mbedtls_aes_init(&aes); - if (mbedtls_aes_setkey_enc(&aes, key, 256)) { - return 1; - } - if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, length, iiv, input, output)) { - return 2; - } - mbedtls_aes_free(&aes); - return PM3_SUCCESS; -} - - -int aes256_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length) { - uint8_t iiv[16] = {0}; - if (iv) { - memcpy(iiv, iv, 16); - } - - mbedtls_aes_context aes; - mbedtls_aes_init(&aes); - if (mbedtls_aes_setkey_dec(&aes, key, 256)) { - return 1; - } - if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, length, iiv, input, output)) { - return 2; - } - mbedtls_aes_free(&aes); - return PM3_SUCCESS; -} - - // NIST Special Publication 800-38B — Recommendation for block cipher modes of operation: The CMAC mode for authentication. // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length) { diff --git a/client/src/crypto/libpcrypto.h b/client/src/crypto/libpcrypto.h index 7b086bf33..5d10b10ee 100644 --- a/client/src/crypto/libpcrypto.h +++ b/client/src/crypto/libpcrypto.h @@ -38,10 +38,6 @@ void des3_decrypt(void *out, const void *in, const void *key, uint8_t keycount); 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 aes256_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); -int aes256_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); int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length); diff --git a/client/src/crypto/originality.c b/client/src/crypto/originality.c index e0dfe1f9c..6b6e687a0 100644 --- a/client/src/crypto/originality.c +++ b/client/src/crypto/originality.c @@ -59,12 +59,6 @@ const ecdsa_publickey_ng_t manufacturer_public_keys[] = { "04DC34DAA903F2726A6225B11C692AF6AB4396575CA12810CBBCE3F781A097B3833B50AB364A70D9C2B641A728A599AE74" }, - // ref: AN12998 NTAG 22x DNA (StatusDetect) - Features and hints - { - PK_MFUL, MBEDTLS_ECP_DP_SECP192R1, 49, "NXP NTAG 22x DNA", - "0485D5B9353B4FAA77581BA2AE96630C5876D6E8603308ABE9A81A0B506F52D02D04FEE6F2D365B3DEE7B9FAD9133E2976" - }, - { PK_MFP, MBEDTLS_ECP_DP_SECP224R1, 57, "MIFARE Plus EV1", "044409ADC42F91A8394066BA83D872FB1D16803734E911170412DDF8BAD1A4DADFD0416291AFE1C748253925DA39A5F39A1C557FFACD34C62E" diff --git a/client/src/emv/emvcore.c b/client/src/emv/emvcore.c index b663af706..b2aa524ac 100644 --- a/client/src/emv/emvcore.c +++ b/client/src/emv/emvcore.c @@ -484,7 +484,7 @@ int EMVSearch(Iso7816CommandChannel channel, bool ActivateField, bool LeaveField for (int i = 0; i < ARRAYLEN(AIDlist); i ++) { if (kbd_enter_pressed()) { - PrintAndLogEx(WARNING, "\naborted via keyboard!"); + PrintAndLogEx(INFO, "user aborted..."); break; } diff --git a/client/src/fileutils.c b/client/src/fileutils.c index 1cbe50fba..a9d7cd3af 100644 --- a/client/src/fileutils.c +++ b/client/src/fileutils.c @@ -72,7 +72,9 @@ DumpFileType_t get_filetype(const char *filename) { size_t len = strlen(filename); if (len > 4) { // check if valid file extension and attempt to load data - char *s = str_dup(filename); + char s[FILE_PATH_SIZE]; + memset(s, 0, sizeof(s)); + memcpy(s, filename, len); str_lower(s); if (str_endswith(s, "bin")) { @@ -89,16 +91,12 @@ DumpFileType_t get_filetype(const char *filename) { o = FLIPPER; } else if (str_endswith(s, "picopass")) { o = FLIPPER; - } else if (str_endswith(s, "xml")) { - o = TAGINFO; } else { // mfd, trc, trace is binary o = BIN; // log is text // .pm3 is text values of signal data } - - free(s); } return o; } @@ -280,7 +278,7 @@ int saveFileEx(const char *preferredName, const char *suffix, const void *data, // Opening file for writing in binary mode FILE *f = fopen(fileName, "wb"); - if (f == NULL) { + if (!f) { PrintAndLogEx(WARNING, "file not found or locked `" _YELLOW_("%s") "`", fileName); free(fileName); return PM3_EFILE; @@ -293,33 +291,6 @@ int saveFileEx(const char *preferredName, const char *suffix, const void *data, return PM3_SUCCESS; } -int saveFileTXT(const char *preferredName, const char *suffix, const void *data, size_t datalen, savePaths_t e_save_path) { - if (data == NULL || datalen == 0) { - return PM3_EINVARG; - } - - char *fileName = newfilenamemcopyEx(preferredName, suffix, e_save_path); - if (fileName == NULL) { - return PM3_EMALLOC; - } - - // We should have a valid filename now, e.g. dumpdata-3.txt - - // Opening file for writing in text mode - FILE *f = fopen(fileName, "w"); - if (f == NULL) { - PrintAndLogEx(WARNING, "file not found or locked `" _YELLOW_("%s") "`", fileName); - free(fileName); - return PM3_EFILE; - } - fwrite(data, 1, datalen, f); - fflush(f); - fclose(f); - PrintAndLogEx(SUCCESS, "Saved " _YELLOW_("%zu") " bytes to text file `" _YELLOW_("%s") "`", datalen, fileName); - free(fileName); - return PM3_SUCCESS; -} - int prepareJSON(json_t *root, JSONFileType ftype, uint8_t *data, size_t datalen, bool verbose, void (*callback)(json_t *)) { if (ftype != jsfCustom) { if (data == NULL || datalen == 0) { @@ -823,9 +794,8 @@ int saveFileJSONroot(const char *preferredName, void *root, size_t flags, bool v } int saveFileJSONrootEx(const char *preferredName, const void *root, size_t flags, bool verbose, bool overwrite, savePaths_t e_save_path) { - if (root == NULL) { + if (root == NULL) return PM3_EINVARG; - } char *filename = NULL; if (overwrite) @@ -977,7 +947,7 @@ int createMfcKeyDump(const char *preferredName, uint8_t sectorsCnt, const sector } for (int i = 0; i < sectorsCnt; i++) { - if (e_sector[i].foundKey[1]) + if (e_sector[i].foundKey[0]) num_to_bytes(e_sector[i].Key[1], sizeof(tmp), tmp); else memcpy(tmp, empty, sizeof(tmp)); @@ -1005,7 +975,7 @@ int loadFile_safeEx(const char *preferredName, const char *suffix, void **pdata, } FILE *f = fopen(path, "rb"); - if (f == NULL) { + if (!f) { PrintAndLogEx(WARNING, "file not found or locked `" _YELLOW_("%s") "`", path); free(path); return PM3_EFILE; @@ -1048,58 +1018,6 @@ int loadFile_safeEx(const char *preferredName, const char *suffix, void **pdata, return PM3_SUCCESS; } -int loadFile_TXTsafe(const char *preferredName, const char *suffix, void **pdata, size_t *datalen, bool verbose) { - - char *path; - int res = searchFile(&path, RESOURCES_SUBDIR, preferredName, suffix, false); - if (res != PM3_SUCCESS) { - return PM3_EFILE; - } - - FILE *f = fopen(path, "r"); - if (f == NULL) { - PrintAndLogEx(WARNING, "file not found or locked `" _YELLOW_("%s") "`", path); - free(path); - return PM3_EFILE; - } - free(path); - - // get filesize in order to malloc memory - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - fseek(f, 0, SEEK_SET); - - if (fsize <= 0) { - PrintAndLogEx(FAILED, "error, when getting filesize"); - fclose(f); - return PM3_EFILE; - } - - *pdata = calloc(fsize, sizeof(uint8_t)); - if (*pdata == NULL) { - PrintAndLogEx(WARNING, "Failed to allocate memory"); - fclose(f); - return PM3_EMALLOC; - } - - size_t bytes_read = fread(*pdata, 1, fsize, f); - - fclose(f); - - if (bytes_read != fsize) { - PrintAndLogEx(FAILED, "error, bytes read mismatch file size"); - free(*pdata); - return PM3_EFILE; - } - - *datalen = bytes_read; - - if (verbose) { - PrintAndLogEx(SUCCESS, "Loaded " _YELLOW_("%zu") " bytes from text file `" _YELLOW_("%s") "`", bytes_read, preferredName); - } - return PM3_SUCCESS; -} - int loadFileEML_safe(const char *preferredName, void **pdata, size_t *datalen) { char *path; int res = searchFile(&path, RESOURCES_SUBDIR, preferredName, "", false); @@ -1203,7 +1121,7 @@ int loadFileNFC_safe(const char *preferredName, void *data, size_t maxdatalen, s } FILE *f = fopen(path, "r"); - if (f == NULL) { + if (!f) { PrintAndLogEx(WARNING, "file not found or locked `" _YELLOW_("%s") "`", path); free(path); return PM3_EFILE; @@ -1528,9 +1446,7 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_ } int loadFileJSONex(const char *preferredName, void *data, size_t maxdatalen, size_t *datalen, bool verbose, void (*callback)(json_t *)) { - if (data == NULL) { - return PM3_EINVARG; - } + if (data == NULL) return PM3_EINVARG; *datalen = 0; int retval = PM3_SUCCESS; @@ -2437,7 +2353,7 @@ int loadFileDICTIONARY_safe_ex(const char *preferredName, const char *suffix, vo keylen = 6; } - size_t block_size = 1000 * keylen; + size_t block_size = 10 * keylen; // double up since its chars keylen <<= 1; @@ -2512,9 +2428,10 @@ int loadFileDICTIONARY_safe_ex(const char *preferredName, const char *suffix, vo continue; } - int ret = hex_to_bytes(line, (uint8_t *)*pdata + (*keycnt * (keylen >> 1)), keylen >> 1); - if (ret != (keylen >> 1)) { - PrintAndLogEx(INFO, "hex to bytes wrong %i", ret); + if (hex_to_bytes( + line, + (uint8_t *)*pdata + (*keycnt * (keylen >> 1)), + keylen >> 1) != (keylen >> 1)) { continue; } @@ -2533,16 +2450,16 @@ out: return retval; } -int loadFileBinaryKey(const char *preferredName, const char *suffix, void **keya, void **keyb, size_t *alen, size_t *blen, bool verbose) { +int loadFileBinaryKey(const char *preferredName, const char *suffix, void **keya, void **keyb, size_t *alen, size_t *blen) { char *path; int res = searchFile(&path, RESOURCES_SUBDIR, preferredName, suffix, false); if (res != PM3_SUCCESS) { - return PM3_ENOFILE; + return PM3_EFILE; } FILE *f = fopen(path, "rb"); - if (f == NULL) { + if (!f) { PrintAndLogEx(WARNING, "file not found or locked `" _YELLOW_("%s") "`", path); free(path); return PM3_EFILE; @@ -2585,9 +2502,7 @@ int loadFileBinaryKey(const char *preferredName, const char *suffix, void **keya *blen = fread(*keyb, 1, fsize, f); fclose(f); - if (verbose) { - PrintAndLogEx(SUCCESS, "Loaded binary key file `" _YELLOW_("%s") "`", path); - } + PrintAndLogEx(SUCCESS, "Loaded binary key file `" _YELLOW_("%s") "`", path); free(path); return PM3_SUCCESS; } @@ -2662,7 +2577,7 @@ int detect_nfc_dump_format(const char *preferredName, nfc_df_e *dump_type, bool } FILE *f = fopen(path, "r"); - if (f == NULL) { + if (!f) { PrintAndLogEx(WARNING, "file not found or locked `" _YELLOW_("%s") "`", path); free(path); return PM3_EFILE; @@ -2713,10 +2628,6 @@ int detect_nfc_dump_format(const char *preferredName, nfc_df_e *dump_type, bool *dump_type = NFC_DF_14_4A; break; } - if (str_startswith(line, "device type: iso15693")) { - *dump_type = NFC_DF_15; - break; - } if (str_startswith(line, "filetype: flipper picopass device")) { *dump_type = NFC_DF_PICOPASS; break; @@ -2749,8 +2660,6 @@ int detect_nfc_dump_format(const char *preferredName, nfc_df_e *dump_type, bool case NFC_DF_PICOPASS: PrintAndLogEx(INFO, "Detected PICOPASS based dump format"); break; - case NFC_DF_15: - PrintAndLogEx(INFO, "Detected ISO15693 based dump format"); case NFC_DF_UNKNOWN: PrintAndLogEx(WARNING, "Failed to detected dump format"); break; @@ -3166,82 +3075,6 @@ int searchFile(char **foundpath, const char *pm3dir, const char *searchname, con return res; } -/** - * Inserts a line into a text file only if it does not already exist. - * Returns PM3_SUCCES or, PM3_EFILE; - * - * @param filepath Path to the file. - * @param line Line to insert (should not contain a trailing newline). - */ -int insert_line_if_not_exists(const char *preferredName, const char *keystr) { - - char *path; - int res = searchFile(&path, DICTIONARIES_SUBDIR, preferredName, ".dic", false); - if (res != PM3_SUCCESS) { - return PM3_EFILE; - } - - FILE *f = fopen(path, "r"); - if (f == NULL) { - PrintAndLogEx(WARNING, "file not found or locked `" _YELLOW_("%s") "`", path); - free(path); - return PM3_EFILE; - } - - // Maximum line length we assume (adjust as necessary for your use case) - char line[255]; - bool key_exists = false; - - char *keystrdup = str_dup(keystr); - str_upper(keystrdup); - - // First pass: check if the line exists - while (fgets(line, sizeof(line), f)) { - - // The line start with # is comment, skip - if (line[0] == '#') { - continue; - } - - // Remove trailing newline for comparison - line[strcspn(line, "\n")] = '\0'; - - // UPPER CASE - str_upper(line); - - key_exists = str_startswith(line, keystrdup); - if (key_exists) { - fclose(f); - free(path); - PrintAndLogEx(INFO, "already in there..."); - return PM3_SUCCESS; - } - } - - fclose(f); - - - // Reopen for appending if line doesn't exist - f = fopen(path, "a"); - if (f == NULL) { - PrintAndLogEx(WARNING, "file not found or locked `" _YELLOW_("%s") "`", path); - free(path); - return PM3_EFILE; - } - - free(path); - - // Append the line with a newline - if (fprintf(f, "%s\n", keystrdup) < 0) { - PrintAndLogEx(WARNING, "error writing to file"); - fclose(f); - return PM3_EFILE; - } - - fclose(f); - return PM3_SUCCESS; -} - int pm3_load_dump(const char *fn, void **pdump, size_t *dumplen, size_t maxdumplen) { int res = PM3_SUCCESS; @@ -3300,7 +3133,7 @@ int pm3_load_dump(const char *fn, void **pdump, size_t *dumplen, size_t maxdumpl break; } - if (dumptype == NFC_DF_MFC || dumptype == NFC_DF_MFU || dumptype == NFC_DF_PICOPASS || dumptype == NFC_DF_15) { + if (dumptype == NFC_DF_MFC || dumptype == NFC_DF_MFU || dumptype == NFC_DF_PICOPASS) { *pdump = calloc(maxdumplen, sizeof(uint8_t)); if (*pdump == NULL) { @@ -3325,10 +3158,6 @@ int pm3_load_dump(const char *fn, void **pdump, size_t *dumplen, size_t maxdumpl } break; } - case TAGINFO: { - //res = loadFileXML_safe(fn, ".xml", pdump, dumplen); - break; - } } return res; } @@ -3341,7 +3170,6 @@ int pm3_save_dump(const char *fn, uint8_t *d, size_t n, JSONFileType jsft) { PrintAndLogEx(INFO, "No data to save, skipping..."); return PM3_EINVARG; } - saveFile(fn, ".bin", d, n); saveFileJSON(fn, jsft, d, n, NULL); return PM3_SUCCESS; diff --git a/client/src/fileutils.h b/client/src/fileutils.h index a2d31c196..6fc450dd1 100644 --- a/client/src/fileutils.h +++ b/client/src/fileutils.h @@ -83,7 +83,6 @@ typedef enum { DICTIONARY, MCT, FLIPPER, - TAGINFO, } DumpFileType_t; typedef enum { @@ -101,16 +100,9 @@ typedef enum { NFC_DF_14_3A, NFC_DF_14_3B, NFC_DF_14_4A, - NFC_DF_15, NFC_DF_PICOPASS, } nfc_df_e; -typedef enum { - ISO15_DF_UNKNOWN, - ISO15_DF_V4_BIN, - ISO15_DF_V5_BIN -} iso15_df_e; - int fileExists(const char *filename); // set a path in the path list g_session.defaultPaths @@ -124,7 +116,7 @@ void truncate_filename(char *fn, uint16_t maxlen); /** * @brief Utility function to save data to a binary file. This method takes a preferred name, but if that * file already exists, it tries with another name until it finds something suitable. - * E.g. dumpdata-15.bin + * E.g. dumpdata-15.txt * * @param preferredName * @param suffix the file suffix. Including the ".". @@ -135,19 +127,6 @@ void truncate_filename(char *fn, uint16_t maxlen); int saveFile(const char *preferredName, const char *suffix, const void *data, size_t datalen); int saveFileEx(const char *preferredName, const char *suffix, const void *data, size_t datalen, savePaths_t e_save_path); -/** - * @brief Utility function to save data to a text file. This method takes a preferred name, but if that - * file already exists, it tries with another name until it finds something suitable. - * E.g. dumpdata-15.txt - * - * @param preferredName - * @param suffix the file suffix. Including the ".". - * @param data The binary data to write to the file - * @param datalen the length of the data - * @return 0 for ok, 1 for failz - */ -int saveFileTXT(const char *preferredName, const char *suffix, const void *data, size_t datalen, savePaths_t e_save_path); - /** STUB * @brief Utility function to save JSON data to a file. This method takes a preferred name, but if that * file already exists, it tries with another name until it finds something suitable. @@ -211,19 +190,6 @@ int createMfcKeyDump(const char *preferredName, uint8_t sectorsCnt, const sector */ int loadFile_safe(const char *preferredName, const char *suffix, void **pdata, size_t *datalen); int loadFile_safeEx(const char *preferredName, const char *suffix, void **pdata, size_t *datalen, bool verbose); - -/** - * @brief Utility function to load a text file. This method takes a preferred name. - * E.g. dumpdata-15.json, tries to search for it, and allocated memory. - * - * @param preferredName - * @param suffix the file suffix. Including the ".". - * @param data The data array to store the loaded bytes from file - * @param datalen the number of bytes loaded from file - * @return PM3_SUCCESS for ok, PM3_E* for failz -*/ -int loadFile_TXTsafe(const char *preferredName, const char *suffix, void **pdata, size_t *datalen, bool verbose); - /** * @brief Utility function to load data from a textfile (EML). This method takes a preferred name. * E.g. dumpdata-15.txt @@ -341,7 +307,7 @@ int loadFileDICTIONARY_safe_ex(const char *preferredName, const char *suffix, vo */ int loadFileXML_safe(const char *preferredName, const char *suffix, void **pdata, size_t *datalen); -int loadFileBinaryKey(const char *preferredName, const char *suffix, void **keya, void **keyb, size_t *alen, size_t *blen, bool verbose); +int loadFileBinaryKey(const char *preferredName, const char *suffix, void **keya, void **keyb, size_t *alen, size_t *blen); /** * @brief Utility function to check and convert plain mfu dump format to new mfu binary format. @@ -419,15 +385,4 @@ int pm3_save_mf_dump(const char *fn, uint8_t *d, size_t n, JSONFileType jsft); * @return PM3_SUCCESS if OK */ int pm3_save_fm11rf08s_nonces(const char *fn, iso14a_fm11rf08s_nonces_with_data_t *d, bool with_data); - - -/** - * Inserts a line into a text file only if it does not already exist. - * Returns PM3_SUCCES or, PM3_EFILE; - * - * @param filepath Path to the file. - * @param line Line to insert (should not contain a trailing newline). - */ -int insert_line_if_not_exists(const char *preferredName, const char *line); - #endif // FILEUTILS_H diff --git a/client/src/flash.c b/client/src/flash.c index 25edb7c0f..ff14309a0 100644 --- a/client/src/flash.c +++ b/client/src/flash.c @@ -30,7 +30,6 @@ #include "util_posix.h" #include "comms.h" #include "commonutil.h" -#include "fileutils.h" #define FLASH_START 0x100000 @@ -267,7 +266,7 @@ int flash_load(flash_file_t *ctx, bool force) { int res = PM3_EUNDEF; fd = fopen(ctx->filename, "rb"); - if (fd == NULL) { + if (!fd) { PrintAndLogEx(ERR, _RED_("Could not open file") " %s >>> ", ctx->filename); res = PM3_EFILE; goto fail; @@ -653,41 +652,17 @@ static const char ice[] = " !!: :!! !!: !!: !!: !!: !!! !!: !!!\n : :: :: : : :: ::: : : : : : :: : \n" _RED_(" . .. .. . . .. ... . . . . . .. . "); - -#define ICEMAN_LOGO_FN "iceman.txt" -#define ICEMAN_LOGO_SIZE (5000) // Write a file's segments to Flash int flash_write(flash_file_t *ctx) { - - char ice2[ICEMAN_LOGO_SIZE] = {0}; - char ice3[ICEMAN_LOGO_SIZE] = {0}; - - bool is_loaded = false; - if (g_session.supports_colors) { - - uint8_t *iraw = NULL; - size_t irawlen = 0; - int res = loadFile_safeEx(ICEMAN_LOGO_FN, "", (void **)&iraw, &irawlen, false); - if (res == PM3_SUCCESS && irawlen > ICEMAN_LOGO_SIZE) { - irawlen = ICEMAN_LOGO_SIZE; - } - if (res == PM3_SUCCESS) { - memcpy(ice3, iraw, irawlen); - free(iraw); - is_loaded = true; - } - } - - if (is_loaded == false) { - memcpy_filter_ansi(ice2, ice, sizeof(ice), !g_session.supports_colors); - memcpy_filter_emoji(ice3, ice2, sizeof(ice2), g_session.emoji_mode); - } - - size_t ice3len = strlen(ice3); + int len = 0; PrintAndLogEx(SUCCESS, "Writing segments for file: %s", ctx->filename); - int len = 0; + char ice2[sizeof(ice)] = {0}; + char ice3[sizeof(ice)] = {0}; + memcpy_filter_ansi(ice2, ice, sizeof(ice), !g_session.supports_colors); + memcpy_filter_emoji(ice3, ice2, sizeof(ice2), g_session.emoji_mode); + size_t ice3len = strlen(ice3); for (int i = 0; i < ctx->num_segs; i++) { flash_seg_t *seg = &ctx->segments[i]; @@ -697,14 +672,6 @@ int flash_write(flash_file_t *ctx) { uint32_t end = seg->start + length; PrintAndLogEx(SUCCESS, " 0x%08x..0x%08x [0x%x / %u blocks]", seg->start, end - 1, length, blocks); - if (is_loaded) { - if (blocks < 50) { - PrintAndLogEx(SUCCESS, "" NOLF); - } else { - fprintf(stdout, "\n\n"); - } - } - fflush(stdout); int block = 0; uint8_t *data = seg->data; @@ -726,45 +693,15 @@ int flash_write(flash_file_t *ctx) { length -= block_size; block++; - // small files, like bootrom - if (blocks < 50) { + if (len < ice3len) { + fprintf(stdout, "%c", ice3[len++]); + } else { + + if ((len - ice3len) % 67 == 0) { + fprintf(stdout, "\n"); + } fprintf(stdout, "."); len++; - fflush(stdout); - continue; - } - - // large fullimage write - if (is_loaded) { - if (len < ice3len) { - fprintf(stdout, "%c", ice3[len++]); - fprintf(stdout, "%c", ice3[len++]); - fprintf(stdout, "%c", ice3[len++]); - fprintf(stdout, "%c", ice3[len++]); - fprintf(stdout, "%c", ice3[len++]); - fprintf(stdout, "%c", ice3[len++]); - fprintf(stdout, "%c", ice3[len++]); - fprintf(stdout, "%c", ice3[len++]); - } else { - - if ((len - ice3len - 1) % 61 == 0) { - fprintf(stdout, "\n"); - } - fprintf(stdout, "."); - len++; - } - - } else { - if (len < ice3len) { - fprintf(stdout, "%c", ice3[len++]); - } else { - - if ((len - ice3len) % 67 == 0) { - fprintf(stdout, "\n"); - } - fprintf(stdout, "."); - len++; - } } fflush(stdout); } diff --git a/client/src/loclass/cipherutils.c b/client/src/loclass/cipherutils.c index 2ff42274d..83b23c698 100644 --- a/client/src/loclass/cipherutils.c +++ b/client/src/loclass/cipherutils.c @@ -126,67 +126,47 @@ uint64_t x_bytes_to_num(uint8_t *src, size_t len) { } void printarr(const char *name, uint8_t *arr, int len) { - - if (name == NULL || arr == NULL) { - return; - } + if (name == NULL || arr == NULL) return; int cx, i; size_t outsize = 40 + strlen(name) + len * 5; - char *output = calloc(outsize, sizeof(char)); if (output == NULL) { PrintAndLogEx(WARNING, "Failed to allocate memory"); return; } - cx = snprintf(output, outsize, "uint8_t %s[] = {", name); for (i = 0; i < len; i++) { - if (cx < outsize) { + if (cx < outsize) cx += snprintf(output + cx, outsize - cx, "0x%02x,", *(arr + i)); //5 bytes per byte - } } - - if (cx < outsize) { + if (cx < outsize) snprintf(output + cx, outsize - cx, "};"); - } - PrintAndLogEx(INFO, output); free(output); } void printarr_human_readable(const char *title, uint8_t *arr, int len) { - if (arr == NULL) { - return; - } + if (arr == NULL) return; int cx = 0, i; size_t outsize = 100 + strlen(title) + (len * 4); char *output = calloc(outsize, sizeof(char)); PrintAndLogEx(INFO, "%s", title); - for (i = 0; i < len; i++) { - if (i % 16 == 0) { if (i == 0) { - - if (cx < outsize) { + if (cx < outsize) cx += snprintf(output + cx, outsize - cx, "%02x| ", i); - } - } else { - - if (cx < outsize) { + if (cx < outsize) cx += snprintf(output + cx, outsize - cx, "\n%02x| ", i); - } } } - - if (cx < outsize) { + if (cx < outsize) cx += snprintf(output + cx, outsize - cx, "%02x ", *(arr + i)); - } } PrintAndLogEx(INFO, output); free(output); @@ -253,14 +233,11 @@ static int testReversedBitstream(void) { } int testCipherUtils(void) { + PrintAndLogEx(INFO, "Testing some internals..."); + int retval = testBitStream(); + if (retval == PM3_SUCCESS) + retval = testReversedBitstream(); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "---------------- " _CYAN_("Loclass selftests") " ----------------"); - - int res = testBitStream(); - if (res == PM3_SUCCESS) { - res = testReversedBitstream(); - } - return res; + return retval; } #endif diff --git a/client/src/loclass/elite_crack.c b/client/src/loclass/elite_crack.c index ad7beb249..01ffe7b29 100644 --- a/client/src/loclass/elite_crack.c +++ b/client/src/loclass/elite_crack.c @@ -248,12 +248,10 @@ void hash2(uint8_t *key64, uint8_t *outp_keytable) { } if (outp_keytable != NULL) { - for (uint8_t i = 0 ; i < 8 ; i++) { memcpy(outp_keytable + i * 16, y[i], 8); memcpy(outp_keytable + 8 + i * 16, z[i], 8); } - } else { printarr_human_readable("hash2", outp_keytable, 128); } @@ -331,9 +329,7 @@ static void *bf_thread(void *thread_arg) { int found = __atomic_load_n(&loclass_found, __ATOMIC_SEQ_CST); - if (found != 0xFF) { - return NULL; - } + if (found != 0xFF) return NULL; //Update the keytable with the brute-values for (uint8_t i = 0; i < numbytes_to_recover; i++) { @@ -387,22 +383,15 @@ static void *bf_thread(void *thread_arg) { #define _CLR_ "\x1b[0K" if (numbytes_to_recover == 3) { - if ((brute > 0) && ((brute & 0xFFFF) == 0)) { PrintAndLogEx(INPLACE, "[ %02x %02x %02x ] %8u / %u", bytes_to_recover[0], bytes_to_recover[1], bytes_to_recover[2], brute, 0xFFFFFF); } - } else if (numbytes_to_recover == 2) { - - if ((brute > 0) && ((brute & 0x3F) == 0)) { + if ((brute > 0) && ((brute & 0x3F) == 0)) PrintAndLogEx(INPLACE, "[ %02x %02x ] %5u / %u" _CLR_, bytes_to_recover[0], bytes_to_recover[1], brute, 0xFFFF); - } - } else { - - if ((brute > 0) && ((brute & 0x1F) == 0)) { + if ((brute > 0) && ((brute & 0x1F) == 0)) PrintAndLogEx(INPLACE, "[ %02x ] %3u / %u" _CLR_, bytes_to_recover[0], brute, 0xFF); - } } } pthread_exit(NULL); @@ -435,19 +424,15 @@ int bruteforceItem(loclass_dumpdata_t item, uint16_t keytable[]) { uint8_t bytes_to_recover[3] = {0}; uint8_t numbytes_to_recover = 0; for (uint8_t i = 0; i < 8; i++) { - - if (keytable[key_index[i]] & (LOCLASS_CRACKED | LOCLASS_BEING_CRACKED)) { - continue; - } + if (keytable[key_index[i]] & (LOCLASS_CRACKED | LOCLASS_BEING_CRACKED)) continue; bytes_to_recover[numbytes_to_recover++] = key_index[i]; - keytable[key_index[i]] |= LOCLASS_BEING_CRACKED; if (numbytes_to_recover > 3) { PrintAndLogEx(FAILED, "The CSN requires > 3 byte bruteforce, not supported"); - PrintAndLogEx(INFO, "CSN..... %s", sprint_hex_inrow(item.csn, 8)); - PrintAndLogEx(INFO, "HASH1... %s", sprint_hex_inrow(key_index, 8)); + PrintAndLogEx(INFO, "CSN %s", sprint_hex(item.csn, 8)); + PrintAndLogEx(INFO, "HASH1 %s", sprint_hex(key_index, 8)); PrintAndLogEx(NORMAL, ""); //Before we exit, reset the 'BEING_CRACKED' to zero keytable[bytes_to_recover[0]] &= ~LOCLASS_BEING_CRACKED; @@ -458,7 +443,6 @@ int bruteforceItem(loclass_dumpdata_t item, uint16_t keytable[]) { } if (numbytes_to_recover == 0) { - PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "No bytes to recover, exiting"); return PM3_ESOFT; } @@ -488,9 +472,8 @@ int bruteforceItem(loclass_dumpdata_t item, uint16_t keytable[]) { } // wait for threads to terminate: void *ptrs[loclass_tc]; - for (size_t i = 0; i < loclass_tc; i++) { + for (size_t i = 0; i < loclass_tc; i++) pthread_join(threads[i], &ptrs[i]); - } // was it a success? int res = PM3_SUCCESS; @@ -678,6 +661,7 @@ int bruteforceItem(loclass_dumpdata_t item, uint16_t keytable[]) { * @return 0 for ok, 1 for failz */ int calculateMasterKey(uint8_t first16bytes[], uint8_t kcus[]) { + mbedtls_des_context ctx_e; uint8_t z_0[8] = {0}; uint8_t y_0[8] = {0}; @@ -696,9 +680,8 @@ int calculateMasterKey(uint8_t first16bytes[], uint8_t kcus[]) { permutekey_rev(z_0, z_0_rev); // ~K_cus = DESenc(z[0], y[0]) - mbedtls_des_context ctx; - mbedtls_des_setkey_enc(&ctx, z_0_rev); - mbedtls_des_crypt_ecb(&ctx, y_0, key64_negated); + mbedtls_des_setkey_enc(&ctx_e, z_0_rev); + mbedtls_des_crypt_ecb(&ctx_e, y_0, key64_negated); key64[0] = ~key64_negated[0]; key64[1] = ~key64_negated[1]; @@ -714,24 +697,20 @@ int calculateMasterKey(uint8_t first16bytes[], uint8_t kcus[]) { uint8_t key64_stdformat[8] = {0}; permutekey_rev(key64, key64_stdformat); - mbedtls_des_setkey_enc(&ctx, key64_stdformat); - mbedtls_des_crypt_ecb(&ctx, key64_negated, result); - mbedtls_des_free(&ctx); + mbedtls_des_setkey_enc(&ctx_e, key64_stdformat); + mbedtls_des_crypt_ecb(&ctx_e, key64_negated, result); - // copy key to out array - if (kcus != NULL) { + if (kcus != NULL) memcpy(kcus, key64, 8); - } if (memcmp(z_0, result, 4) != 0) { - PrintAndLogEx(WARNING, "Calculated master key, k_cus ( %s )", _RED_("fail")); - PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(WARNING, _RED_("Failed to verify") " calculated master key (k_cus)! Something is wrong."); return PM3_ESOFT; } - PrintAndLogEx(SUCCESS, "--- " _CYAN_("High security custom key (Kcus)") " ---"); - PrintAndLogEx(SUCCESS, "Standard format... %s", sprint_hex_inrow(key64_stdformat, sizeof(key64_stdformat))); - PrintAndLogEx(SUCCESS, "iCLASS format..... " _GREEN_("%s"), sprint_hex_inrow(key64, sizeof(key64))); + PrintAndLogEx(SUCCESS, "----- " _CYAN_("High security custom key (Kcus)") " -----"); + PrintAndLogEx(SUCCESS, "Standard format %s", sprint_hex(key64_stdformat, 8)); + PrintAndLogEx(SUCCESS, "iCLASS format " _GREEN_("%s"), sprint_hex(key64, 8)); PrintAndLogEx(SUCCESS, "Key verified ( " _GREEN_("ok") " )"); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; @@ -744,7 +723,7 @@ int calculateMasterKey(uint8_t first16bytes[], uint8_t kcus[]) { * @return */ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) { - + uint8_t i; size_t itemsize = sizeof(loclass_dumpdata_t); loclass_dumpdata_t *attack = (loclass_dumpdata_t *) calloc(itemsize, sizeof(uint8_t)); if (attack == NULL) { @@ -758,28 +737,19 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) { int res = 0; uint64_t t1 = msclock(); - for (uint16_t i = 0 ; i * itemsize < dumpsize ; i++) { - + for (i = 0 ; i * itemsize < dumpsize ; i++) { memcpy(attack, dump + i * itemsize, itemsize); - res = bruteforceItem(*attack, keytable); - if (res != PM3_SUCCESS) { + if (res != PM3_SUCCESS) break; - } } - free(attack); - t1 = msclock() - t1; - if (res == PM3_SUCCESS) { - PrintAndLogEx(NORMAL, ""); - } + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, "time " _YELLOW_("%" PRIu64) " seconds", t1 / 1000); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "loclass key recovery( %s )", _RED_("fail")); - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass sim -t 2") "` again and collect new data"); - PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(ERR, "loclass exiting. Try run " _YELLOW_("`hf iclass sim -t 2`") " again and collect new data"); return PM3_ESOFT; } @@ -788,12 +758,11 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) { // indicate crack-status. Those must be discarded for the // master key calculation uint8_t first16bytes[16] = {0}; - for (uint8_t i = 0 ; i < 16 ; i++) { + for (i = 0 ; i < 16 ; i++) { first16bytes[i] = keytable[i] & 0xFF; if ((keytable[i] & LOCLASS_CRACKED) != LOCLASS_CRACKED) { PrintAndLogEx(WARNING, "Warning: we are missing byte " _RED_("%d") " , custom key calculation will fail...", i); - PrintAndLogEx(NORMAL, ""); return PM3_ESOFT; } } @@ -904,7 +873,7 @@ static int _testHash1(void) { } int testElite(bool slowtests) { - PrintAndLogEx(INFO, "Testing iClass Elite functionality..."); + PrintAndLogEx(INFO, "Testing iClass Elite functionality"); PrintAndLogEx(INFO, "Testing hash2..."); uint8_t k_cus[8] = {0x5B, 0x7C, 0x62, 0xC4, 0x91, 0xC1, 0x1B, 0x39}; @@ -925,23 +894,22 @@ int testElite(bool slowtests) { */ uint8_t keytable[128] = {0}; hash2(k_cus, keytable); - printarr_human_readable("--------------------- " _CYAN_("Hash2") " -----------------------", keytable, sizeof(keytable)); + printarr_human_readable("---------------------- Hash2 ----------------------", keytable, sizeof(keytable)); if (keytable[3] == 0xA1 && keytable[0x30] == 0xA3 && keytable[0x6F] == 0x95) { - PrintAndLogEx(SUCCESS, " Hash2 ( %s )", _GREEN_("ok")); + PrintAndLogEx(SUCCESS, " hash2 ( %s )", _GREEN_("ok")); } int res = PM3_SUCCESS; PrintAndLogEx(INFO, "Testing hash1..."); res += _testHash1(); - PrintAndLogEx((res == PM3_SUCCESS) ? SUCCESS : WARNING, " Hash1 ( %s )", (res == PM3_SUCCESS) ? _GREEN_("ok") : _RED_("fail")); + PrintAndLogEx((res == PM3_SUCCESS) ? SUCCESS : WARNING, " hash1 ( %s )", (res == PM3_SUCCESS) ? _GREEN_("ok") : _RED_("fail")); PrintAndLogEx(INFO, "Testing key diversification..."); res += _test_iclass_key_permutation(); - PrintAndLogEx((res == PM3_SUCCESS) ? SUCCESS : WARNING, " Key diversification ( %s )", (res == PM3_SUCCESS) ? _GREEN_("ok") : _RED_("fail")); + PrintAndLogEx((res == PM3_SUCCESS) ? SUCCESS : WARNING, " key diversification ( %s )", (res == PM3_SUCCESS) ? _GREEN_("ok") : _RED_("fail")); - if (slowtests) { + if (slowtests) res += _testBruteforce(); - } return res; } diff --git a/client/src/loclass/ikeys.c b/client/src/loclass/ikeys.c index b50699e9e..9382074fb 100644 --- a/client/src/loclass/ikeys.c +++ b/client/src/loclass/ikeys.c @@ -803,17 +803,17 @@ static bool des_getParityBitFromKey(uint8_t key) { } static void des_checkParity(uint8_t *key) { + int i; int fails = 0; - for (uint8_t i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) { bool parity = des_getParityBitFromKey(key[i]); if (parity != (key[i] & 0x1)) { fails++; PrintAndLogEx(FAILED, "parity1 fail, byte %d [%02x] was %d, should be %d", i, key[i], (key[i] & 0x1), parity); } } - if (fails) { - PrintAndLogEx(FAILED, "parity fails... " _RED_("%d"), fails); + PrintAndLogEx(FAILED, "parity fails: %d", fails); } else { PrintAndLogEx(SUCCESS, " Key syntax is with parity bits inside each byte (%s)", _GREEN_("ok")); } @@ -894,17 +894,15 @@ static int testKeyDiversificationWithMasterkeyTestcases(uint8_t *key) { int i, error = 0; uint8_t empty[8] = {0}; - PrintAndLogEx(INFO, "Testing encryption/decryption..."); + PrintAndLogEx(INFO, "Testing encryption/decryption"); - for (i = 0; memcmp(testcases + i, empty, 8); i++) { + for (i = 0; memcmp(testcases + i, empty, 8); i++) error += testDES(key, testcases[i]); - } - if (error) { - PrintAndLogEx(FAILED, "%d errors occurred, %d testcases ( %s )", error, i, _RED_("fail")); - } else { - PrintAndLogEx(SUCCESS, " Hashing seems to work, " _YELLOW_("%d") " testcases ( %s )", i, _GREEN_("ok")); - } + if (error) + PrintAndLogEx(FAILED, "%d errors occurred (%d testcases)", error, i); + else + PrintAndLogEx(SUCCESS, "Hashing seems to work (%d testcases)", i); return error; } @@ -944,9 +942,8 @@ static int testDES2(uint8_t *key, uint64_t csn, uint64_t expected) { PrintAndLogEx(DEBUG, " {csn} %"PRIx64, crypt_csn); PrintAndLogEx(DEBUG, " expected %"PRIx64 " (%s)", expected, (expected == crypt_csn) ? _GREEN_("ok") : _RED_("fail")); - if (expected != crypt_csn) { + if (expected != crypt_csn) return PM3_ESOFT; - } return PM3_SUCCESS; } @@ -957,12 +954,12 @@ static int testDES2(uint8_t *key, uint64_t csn, uint64_t expected) { */ static int doTestsWithKnownInputs(void) { // KSel from http://www.proxmark.org/forum/viewtopic.php?pid=10977#p10977 - PrintAndLogEx(INFO, "Testing DES encryption... "); + PrintAndLogEx(INFO, "Testing DES encryption"); uint8_t key[8] = {0x6c, 0x8d, 0x44, 0xf9, 0x2a, 0x2d, 0x01, 0xbf}; testDES2(key, 0xbbbbaaaabbbbeeee, 0xd6ad3ca619659e6b); - PrintAndLogEx(INFO, "Testing hashing algorithm... "); + PrintAndLogEx(INFO, "Testing hashing algorithm"); int res = PM3_SUCCESS; res += testCryptedCSN(0x0102030405060708, 0x0bdd6512073c460a); @@ -976,10 +973,10 @@ static int doTestsWithKnownInputs(void) { res += testCryptedCSN(0x14e2adfc5bb7e134, 0x6ac90c6508bd9ea3); if (res != PM3_SUCCESS) { - PrintAndLogEx(FAILED, "%d res occurred " _YELLOW_("9") " testcases ( %s )", res, _RED_("fail")); + PrintAndLogEx(FAILED, "%d res occurred (9 testcases)", res); res = PM3_ESOFT; } else { - PrintAndLogEx(SUCCESS, " Hashing seems to work " _YELLOW_("9") " testcases ( %s )", _GREEN_("ok")); + PrintAndLogEx(SUCCESS, "Hashing seems to work (9 testcases)"); res = PM3_SUCCESS; } return res; @@ -989,7 +986,6 @@ int doKeyTests(void) { uint8_t key[8] = { 0xAE, 0xA6, 0x84, 0xA6, 0xDA, 0xB2, 0x32, 0x78 }; uint8_t parity[8] = {0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01}; - for (int i = 0; i < 8; i++) { key[i] += parity[i]; } @@ -998,6 +994,7 @@ int doKeyTests(void) { des_checkParity(key); // Test hashing functions + PrintAndLogEx(SUCCESS, "The following tests require the correct 8-byte master key"); testKeyDiversificationWithMasterkeyTestcases(key); PrintAndLogEx(INFO, "Testing key diversification with non-sensitive keys..."); return doTestsWithKnownInputs(); diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 9d6fc5084..985aad1f4 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -575,11 +575,10 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext_t *ctx, uin size_t sentdatalen = 0; while (cdatalen >= sentdatalen) { - if ((cdatalen - sentdatalen) > DESFIRE_TX_FRAME_MAX_LEN) { + if ((cdatalen - sentdatalen) > DESFIRE_TX_FRAME_MAX_LEN) len = DESFIRE_TX_FRAME_MAX_LEN; - } else { + else len = cdatalen - sentdatalen; - } size_t sendindx = sentdatalen; size_t sendlen = len; @@ -658,9 +657,8 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext_t *ctx, uin } pos += buflen; - if (rcode != MFDES_ADDITIONAL_FRAME) { + if (rcode != MFDES_ADDITIONAL_FRAME) break; - } } if (resplen) { @@ -971,14 +969,12 @@ int DesfireSelectAIDHexNoFieldOn(DesfireContext_t *ctx, uint32_t aid) { ctx->secureChannel = DACNone; int res = DesfireExchangeEx(false, ctx, MFDES_SELECT_APPLICATION, data, 3, &respcode, resp, &resplen, true, 0); if (res == PM3_SUCCESS) { - if (resplen != 0) { + if (resplen != 0) return PM3_ECARDEXCHANGE; - } // select operation fail - if (respcode != MFDES_S_OPERATION_OK) { + if (respcode != MFDES_S_OPERATION_OK) return PM3_EAPDU_FAIL; - } DesfireClearSession(ctx); ctx->appSelected = (aid != 0x000000); @@ -1100,57 +1096,7 @@ int DesfireSelectAndAuthenticateW(DesfireContext_t *dctx, DesfireSecureChannel s DesfirePrintContext(dctx); int res = 0; - - // Handle DF Name selection if it's present in the context - if (dctx->selectedDFNameLen > 0) { - // Select DF by name using ISO7816 SELECT - uint8_t resp[250] = {0}; - size_t resplen = 0; - res = DesfireISOSelect(dctx, ISSDFName, dctx->selectedDFName, dctx->selectedDFNameLen, resp, &resplen); - if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire DF name select " _RED_("error")); - return 200; - } - if (verbose) { - PrintAndLogEx(INFO, "DF %s is " _GREEN_("selected"), sprint_hex(dctx->selectedDFName, dctx->selectedDFNameLen)); - } - - // If both dfname and aid are specified, now also select by AID - if (way == ISW6bAID && id != 0x000000) { - if (dctx->cmdSet == DCCISO) { - dctx->cmdSet = DCCNativeISO; - if (verbose) - PrintAndLogEx(INFO, "Select via " _CYAN_("native iso wrapping") " interface"); - - res = DesfireSelectAIDHex(dctx, id, false, 0); - if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire select " _RED_("error")); - return 200; - } - if (verbose) - PrintAndLogEx(INFO, "App %06x via native iso channel is " _GREEN_("selected"), id); - - dctx->cmdSet = DCCISO; - } else { - res = DesfireSelectEx(dctx, false, way, id, NULL); - if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire %s select " _RED_("error"), DesfireSelectWayToStr(way)); - return 202; - } - if (verbose) - PrintAndLogEx(INFO, "%s is " _GREEN_("selected"), DesfireWayIDStr(way, id)); - } - } else if (way == ISWIsoID && id != 0x0000) { - // Also select by ISO ID if specified - res = DesfireSelectEx(dctx, false, way, id, NULL); - if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire %s select " _RED_("error"), DesfireSelectWayToStr(way)); - return 202; - } - if (verbose) - PrintAndLogEx(INFO, "%s is " _GREEN_("selected"), DesfireWayIDStr(way, id)); - } - } else if (way == ISW6bAID && dctx->cmdSet == DCCISO) { + if (way == ISW6bAID && dctx->cmdSet == DCCISO) { dctx->cmdSet = DCCNativeISO; if (verbose) PrintAndLogEx(INFO, "Select via " _CYAN_("native iso wrapping") " interface"); @@ -2290,20 +2236,6 @@ int DesfireValueFileOperations(DesfireContext_t *dctx, uint8_t fid, uint8_t oper int res = DesfireCommand(dctx, operation, data, datalen, resp, &resplen, -1); - // Auto-detection fallback: if MAC mode fails with length error, retry with plain mode - if ((res == 0x7E || res == -20) && dctx->commMode == DCMMACed) { - PrintAndLogEx(INFO, "MAC mode failed with length error, retrying with plain mode"); - DesfireCommunicationMode original_mode = dctx->commMode; - dctx->commMode = DCMPlain; - - memset(resp, 0, sizeof(resp)); - resplen = 0; - res = DesfireCommand(dctx, operation, data, datalen, resp, &resplen, -1); - - // Restore original mode for future commands - dctx->commMode = original_mode; - } - if (resplen == 4 && value) { *value = MemLeToUint4byte(resp); } diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index b0097aab7..335a87f4d 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -101,17 +101,8 @@ void DesfireSetCommMode(DesfireContext_t *ctx, DesfireCommunicationMode commMode void DesfireSetKdf(DesfireContext_t *ctx, uint8_t kdfAlgo, uint8_t *kdfInput, uint8_t kdfInputLen) { ctx->kdfAlgo = kdfAlgo; ctx->kdfInputLen = kdfInputLen; - if (kdfInputLen) + if (kdfInputLen) { memcpy(ctx->kdfInput, kdfInput, kdfInputLen); -} - -void DesfireSetDFName(DesfireContext_t *ctx, uint8_t *dfname, uint8_t dfnameLen) { - ctx->selectedDFNameLen = 0; - memset(ctx->selectedDFName, 0, sizeof(ctx->selectedDFName)); - - if (dfname && dfnameLen > 0 && dfnameLen <= 16) { - ctx->selectedDFNameLen = dfnameLen; - memcpy(ctx->selectedDFName, dfname, dfnameLen); } } diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index 363cef461..464fb98ee 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -75,9 +75,6 @@ typedef struct { bool appSelected; // for iso auth uint32_t selectedAID; - uint8_t selectedDFName[16]; - uint8_t selectedDFNameLen; - uint8_t uid[10]; uint8_t uidlen; @@ -100,7 +97,6 @@ void DesfireSetCommandSet(DesfireContext_t *ctx, DesfireCommandSet cmdSet); void DesfireSetCommMode(DesfireContext_t *ctx, DesfireCommunicationMode commMode); void DesfireSetSecureChannel(DesfireContext_t *ctx, DesfireSecureChannel schann); void DesfireSetKdf(DesfireContext_t *ctx, uint8_t kdfAlgo, uint8_t *kdfInput, uint8_t kdfInputLen); -void DesfireSetDFName(DesfireContext_t *ctx, uint8_t *dfname, uint8_t dfnameLen); bool DesfireIsAuthenticated(DesfireContext_t *dctx); size_t DesfireGetMACLength(DesfireContext_t *ctx); diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index d9506d48b..2b439b1b4 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -219,6 +219,9 @@ static uint8_t DesfireGetCmdHeaderLen(uint8_t cmd) { static const uint8_t EV1D40TransmitMAC[] = { MFDES_WRITE_DATA, + MFDES_CREDIT, + MFDES_LIMITED_CREDIT, + MFDES_DEBIT, MFDES_WRITE_RECORD, MFDES_UPDATE_RECORD, MFDES_COMMIT_READER_ID, diff --git a/client/src/mifare/mad.c b/client/src/mifare/mad.c index eae149a4c..d15b4f4b6 100644 --- a/client/src/mifare/mad.c +++ b/client/src/mifare/mad.c @@ -317,6 +317,7 @@ static int MADInfoByteDecode(const uint8_t *sector, bool swapmad, int mad_ver, b void MADPrintHeader(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("MIFARE App Directory Information") " ----------------"); + PrintAndLogEx(INFO, "-----------------------------------------------------"); } int MAD1DecodeAndPrint(uint8_t *sector, bool swapmad, bool verbose, bool *haveMAD2) { @@ -449,9 +450,8 @@ int MADDFDecodeAndPrint(uint32_t short_aid, bool verbose) { } bool HasMADKey(uint8_t *d) { - if (d == NULL) { + if (d == NULL) return false; - } return (memcmp(d + (3 * MFBLOCK_SIZE), g_mifare_mad_key, sizeof(g_mifare_mad_key)) == 0); } diff --git a/client/src/mifare/mifaredefault.h b/client/src/mifare/mifaredefault.h index e43c42a4b..bcdc4a84b 100644 --- a/client/src/mifare/mifaredefault.h +++ b/client/src/mifare/mifaredefault.h @@ -121,24 +121,20 @@ static const uint64_t g_mifare_default_keys[] = { 0x96a301bce267, }; -static const uint8_t g_mifare_default_key[MIFARE_KEY_SIZE] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -static const uint8_t g_mifare_mad_key[MIFARE_KEY_SIZE] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5}; -static const uint8_t g_mifare_mad_key_b[MIFARE_KEY_SIZE] = {0x89, 0xEC, 0xA9, 0x7F, 0x8C, 0x2A}; +static const uint8_t g_mifare_default_key[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +static const uint8_t g_mifare_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5}; +static const uint8_t g_mifare_mad_key_b[] = {0x89, 0xEC, 0xA9, 0x7F, 0x8C, 0x2A}; // 16 key B D01AFEEB890A -static const uint8_t g_mifare_signature_key_a[MIFARE_KEY_SIZE] = {0x5C, 0x8F, 0xF9, 0x99, 0x0D, 0xA2}; -static const uint8_t g_mifare_signature_key_b[MIFARE_KEY_SIZE] = {0x4b, 0x79, 0x1b, 0xea, 0x7b, 0xcc}; +static const uint8_t g_mifare_signature_key_a[] = {0x5C, 0x8F, 0xF9, 0x99, 0x0D, 0xA2}; +static const uint8_t g_mifare_signature_key_b[] = {0x4b, 0x79, 0x1b, 0xea, 0x7b, 0xcc}; // Manufacture MFC / QL88 (S17 / B) -static const uint8_t g_mifare_ql88_signature_key_b[MIFARE_KEY_SIZE] = {0x70, 0x7B, 0x11, 0xFC, 0x14, 0x81}; +static const uint8_t g_mifare_ql88_signature_key_b[] = {0x70, 0x7B, 0x11, 0xFC, 0x14, 0x81}; -static const uint8_t g_mifare_ndef_key[MIFARE_KEY_SIZE] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}; +static const uint8_t g_mifare_ndef_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}; static const uint8_t g_mifarep_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7}; static const uint8_t g_mifarep_ndef_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}; -static const uint8_t g_mifare_k08s[MIFARE_KEY_SIZE] = {0xA3, 0x96, 0xEF, 0xA4, 0xE2, 0x4F}; -static const uint8_t g_mifare_k08[MIFARE_KEY_SIZE] = {0xA3, 0x16, 0x67, 0xA8, 0xCE, 0xC1}; -static const uint8_t g_mifare_k32n[MIFARE_KEY_SIZE] = {0x51, 0x8B, 0x33, 0x54, 0xE7, 0x60}; -static const uint8_t g_mifare_k32n2[MIFARE_KEY_SIZE] = {0x73, 0xB9, 0x83, 0x6C, 0xF1, 0x68}; extern const char *g_mifare_plus_default_keys[]; extern size_t g_mifare_plus_default_keys_len; diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index d8f3a04ed..6688a7842 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -43,8 +43,6 @@ #include "cmdhf14a.h" #include "gen4.h" #include "parity.h" -#include "pmflash.h" -#include "preferences.h" // setDeviceDebugLevel int mf_dark_side(uint8_t blockno, uint8_t key_type, uint64_t *key) { uint32_t uid = 0; @@ -64,7 +62,7 @@ int mf_dark_side(uint8_t blockno, uint8_t key_type, uint64_t *key) { //flush queue while (kbd_enter_pressed()) { SendCommandNG(CMD_BREAK_LOOP, NULL, 0); - PrintAndLogEx(WARNING, "aborted via keyboard"); + PrintAndLogEx(WARNING, "Aborted via keyboard"); return PM3_EOPABORTED; } @@ -90,7 +88,7 @@ int mf_dark_side(uint8_t blockno, uint8_t key_type, uint64_t *key) { //TODO: Not really stopping the command in time. if (kbd_enter_pressed()) { SendCommandNG(CMD_BREAK_LOOP, NULL, 0); - PrintAndLogEx(WARNING, "\naborted via keyboard"); + PrintAndLogEx(WARNING, "\nAborted via keyboard"); return PM3_EOPABORTED; } @@ -277,7 +275,7 @@ int mf_check_keys_fast_ex(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastCh while (kbd_enter_pressed()) { SendCommandNG(CMD_BREAK_LOOP, NULL, 0); - PrintAndLogEx(INFO, "aborted via keyboard!"); + PrintAndLogEx(NORMAL, ""); return PM3_EOPABORTED; } @@ -307,11 +305,12 @@ int mf_check_keys_fast_ex(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastCh uint8_t curr_keys = resp.oldarg[0]; if ((singleSectorParams >> 15) & 1) { - if (curr_keys) { - + // uint64_t foo = bytes_to_num(resp.data.asBytes, 6); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "\nTarget block " _GREEN_("%4u") " key type " _GREEN_("%c") " -- found valid key [ " _GREEN_("%s") " ]", +// PrintAndLogEx(SUCCESS, "found Key %s for block %2i found: " _GREEN_("%012" PRIx64), (singleSectorParams >> 8) & 1 ? "B" : "A", singleSectorParams & 0xFF, foo); + + PrintAndLogEx(SUCCESS, "\nTarget block %4u key type %c -- found valid key [ " _GREEN_("%s") " ]", singleSectorParams & 0xFF, ((singleSectorParams >> 8) & 1) ? 'B' : 'A', sprint_hex_inrow(resp.data.asBytes, MIFARE_KEY_SIZE) @@ -562,9 +561,8 @@ int mf_nested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo struct p *package = (struct p *)resp.data.asBytes; // error during nested on device side - if (package->isOK != PM3_SUCCESS) { + if (package->isOK != PM3_SUCCESS) return package->isOK; - } memcpy(&uid, package->cuid, sizeof(package->cuid)); @@ -584,14 +582,12 @@ int mf_nested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo pthread_t thread_id[2]; // create and run worker threads - for (uint8_t i = 0; i < 2; i++) { + for (uint8_t i = 0; i < 2; i++) pthread_create(thread_id + i, NULL, nested_worker_thread, &statelists[i]); - } // wait for threads to terminate: - for (uint8_t i = 0; i < 2; i++) { + for (uint8_t i = 0; i < 2; i++) pthread_join(thread_id[i], (void *)&statelists[i].head.slhead); - } // the first 16 Bits of the cryptostate already contain part of our key. // Create the intersection of the two lists based on these 16 Bits and @@ -600,11 +596,9 @@ int mf_nested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo p2 = p4 = statelists[1].head.slhead; while (p1 <= statelists[0].tail.sltail && p2 <= statelists[1].tail.sltail) { - if (Compare16Bits(p1, p2) == 0) { struct Crypto1State savestate; - savestate = *p1; while (Compare16Bits(p1, &savestate) == 0 && p1 <= statelists[0].tail.sltail) { *p3 = *p1; @@ -612,7 +606,6 @@ int mf_nested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo p3++; p1++; } - savestate = *p2; while (Compare16Bits(p2, &savestate) == 0 && p2 <= statelists[1].tail.sltail) { *p4 = *p2; @@ -620,7 +613,6 @@ int mf_nested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo p4++; p2++; } - } else { while (Compare16Bits(p1, p2) == -1) p1++; while (Compare16Bits(p1, p2) == 1) p2++; @@ -643,15 +635,13 @@ int mf_nested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo // Create the intersection statelists[0].len = intersection(statelists[0].head.keyhead, statelists[1].head.keyhead); - bool looped = false; - //statelists[0].tail.keytail = --p7; uint32_t keycnt = statelists[0].len; if (keycnt == 0) { goto out; } - PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") " key candidate%c", keycnt, (keycnt > 1) ? 's' : ' '); + PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") " key candidates", keycnt); memset(resultKey, 0, MIFARE_KEY_SIZE); uint64_t key64 = -1; @@ -669,53 +659,44 @@ int mf_nested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo register uint8_t j; for (j = 0; j < size; j++) { crypto1_get_lfsr(statelists[0].head.slhead + i, &key64); - num_to_bytes(key64, MIFARE_KEY_SIZE, keyBlock + j * MIFARE_KEY_SIZE); + num_to_bytes(key64, 6, keyBlock + j * MIFARE_KEY_SIZE); } if (mf_check_keys(statelists[0].blockNo, statelists[0].keyType, false, size, keyBlock, &key64) == PM3_SUCCESS) { - - if (looped) { - PrintAndLogEx(NORMAL, ""); - } - free(statelists[0].head.slhead); free(statelists[1].head.slhead); - num_to_bytes(key64, MIFARE_KEY_SIZE, resultKey); + num_to_bytes(key64, 6, resultKey); if (package->keytype < 2) { - PrintAndLogEx(SUCCESS, "Target block " _GREEN_("%4u") " key type " _GREEN_("%c") " -- found valid key [ " _GREEN_("%s") " ]", + PrintAndLogEx(SUCCESS, "\nTarget block %4u key type %c -- found valid key [ " _GREEN_("%s") " ]", package->block, package->keytype ? 'B' : 'A', sprint_hex_inrow(resultKey, MIFARE_KEY_SIZE) ); } else { - PrintAndLogEx(SUCCESS, "Target block " _GREEN_("%4u") " key type " _GREEN_("%02x") " -- found valid key [ " _GREEN_("%s") " ]", + PrintAndLogEx(SUCCESS, "\nTarget block %4u key type %02x -- found valid key [ " _GREEN_("%s") " ]", package->block, MIFARE_AUTH_KEYA + package->keytype, sprint_hex_inrow(resultKey, MIFARE_KEY_SIZE) ); } + + return PM3_SUCCESS; } float bruteforce_per_second = (float)(i + max_keys) / ((msclock() - start_time) / 1000.0); PrintAndLogEx(INPLACE, "%6d/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt - i) / bruteforce_per_second); - looped = true; } out: - - if (looped) { - PrintAndLogEx(NORMAL, ""); - } - if (package->keytype < 2) { - PrintAndLogEx(SUCCESS, "Target block " _YELLOW_("%4u") " key type " _YELLOW_("%c"), + PrintAndLogEx(SUCCESS, "\nTarget block %4u key type %c", package->block, package->keytype ? 'B' : 'A' ); } else { - PrintAndLogEx(SUCCESS, "Target block " _YELLOW_("%4u") " key type " _YELLOW_("%02x"), + PrintAndLogEx(SUCCESS, "\nTarget block %4u key type %02x", package->block, MIFARE_AUTH_KEYA + package->keytype ); @@ -930,11 +911,10 @@ int mf_static_nested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trg num_to_bytes(key64, MIFARE_KEY_SIZE, resultKey); - if (IfPm3Flash() && keycnt > 70) { + if (IfPm3Flash() && keycnt > 70) PrintAndLogEx(NORMAL, ""); - } - PrintAndLogEx(SUCCESS, "target block " _GREEN_("%4u") " key type " _GREEN_("%c") " -- found valid key [ " _GREEN_("%s") " ]", + PrintAndLogEx(SUCCESS, "target block %4u key type %c -- found valid key [ " _GREEN_("%s") " ]", package->block, package->keytype ? 'B' : 'A', sprint_hex_inrow(resultKey, MIFARE_KEY_SIZE) @@ -1418,41 +1398,6 @@ int detect_classic_prng(void) { uint32_t nonce = bytes_to_num(respA.data.asBytes, respA.oldarg[0]); return validate_prng_nonce(nonce); } - - -/* Detect supported Auth, -* function performs a partial AUTH, where it tries to authenticate against block0, but only collects tag nonce. -* @returns -* TRUE if tag replies with a nonce -* FALSE is tag does not reply with a nonce -*/ -int detect_classic_auth(uint8_t key_type) { - - PacketResponseNG resp, respA; - uint8_t cmd[] = {MIFARE_AUTH_KEYA + key_type, 0x00}; - uint32_t flags = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_RATS; - - clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO14443A_READER, flags, sizeof(cmd), 0, cmd, sizeof(cmd)); - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { - PrintAndLogEx(WARNING, "timeout while waiting for reply"); - return PM3_ETIMEOUT; - } - - // if select tag failed. - if (resp.oldarg[0] == 0) { - PrintAndLogEx(ERR, "error: selecting tag failed, can't detect nonce\n"); - return PM3_ERFTRANS; - } - if (WaitForResponseTimeout(CMD_ACK, &respA, 2500) == false) { - PrintAndLogEx(WARNING, "timeout while waiting for reply"); - return PM3_ETIMEOUT; - } - - // check respA for a nonce - return respA.oldarg[0] == 4; -} - /* Detect Mifare Classic NACK bug returns: @@ -1516,19 +1461,19 @@ int detect_classic_nackbug(bool verbose) { return PM3_SUCCESS; } case 2: { - PrintAndLogEx(SUCCESS, "NACK test... " _GREEN_("always leak NACK")); + PrintAndLogEx(SUCCESS, "NACK test: " _GREEN_("always leak NACK")); return PM3_SUCCESS; } case 1: { - PrintAndLogEx(SUCCESS, "NACK test... " _GREEN_("detected")); + PrintAndLogEx(SUCCESS, "NACK test: " _GREEN_("detected")); return PM3_SUCCESS; } case 0: { - PrintAndLogEx(SUCCESS, "NACK test... " _GREEN_("no bug")); + PrintAndLogEx(SUCCESS, "NACK test: " _GREEN_("no bug")); return PM3_SUCCESS; } default: { - PrintAndLogEx(ERR, "errorcode from device (" _RED_("%u") " )", ok); + PrintAndLogEx(ERR, "errorcode from device " _RED_("[%i]"), ok); return PM3_EUNDEF; } } @@ -1590,21 +1535,10 @@ int detect_classic_static_encrypted_nonce_ex(uint8_t block_no, uint8_t key_type, cdata[21] = corruptnrar; cdata[22] = corruptnrarparity; - uint8_t dbg_curr = DBG_NONE; - if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) { - return PM3_EFAILED; - } - - if (setDeviceDebugLevel(verbose ? MAX(dbg_curr, DBG_INFO) : DBG_NONE, false) != PM3_SUCCESS) { - return PM3_EFAILED; - } - clearCommandBuffer(); SendCommandNG(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE, cdata, sizeof(cdata)); PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE, &resp, 1500)) { - - setDeviceDebugLevel(dbg_curr, false); + if (WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE, &resp, 1000)) { if (resp.status == PM3_ESOFT) { return NONCE_FAIL; @@ -1670,8 +1604,6 @@ int detect_classic_static_encrypted_nonce_ex(uint8_t block_no, uint8_t key_type, } return resp.data.asBytes[0]; } - - setDeviceDebugLevel(dbg_curr, false); return NONCE_FAIL; } diff --git a/client/src/mifare/mifarehost.h b/client/src/mifare/mifarehost.h index 02c0422f0..9e6ba67c3 100644 --- a/client/src/mifare/mifarehost.h +++ b/client/src/mifare/mifarehost.h @@ -110,7 +110,6 @@ int mf_chinese_gen_4_set_block(uint8_t blockNo, uint8_t *block, uint8_t *key); int try_decrypt_word(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len); int detect_classic_prng(void); -int detect_classic_auth(uint8_t key_type); int detect_classic_nackbug(bool verbose); uint16_t detect_mf_magic(bool is_mfc, uint8_t key_type, uint64_t key); int detect_classic_static_nonce(void); diff --git a/client/src/pm3line_vocabulary.h b/client/src/pm3line_vocabulary.h index 8c106751f..a7cb8a8a2 100644 --- a/client/src/pm3line_vocabulary.h +++ b/client/src/pm3line_vocabulary.h @@ -51,7 +51,6 @@ const static vocabulary_t vocabulary[] = { { 1, "prefs get hints" }, { 1, "prefs get output" }, { 1, "prefs get plotsliders" }, - { 1, "prefs get mqtt" }, { 1, "prefs set help" }, { 1, "prefs set barmode" }, { 1, "prefs set client.debug" }, @@ -63,7 +62,6 @@ const static vocabulary_t vocabulary[] = { { 1, "prefs set savepaths" }, { 1, "prefs set output" }, { 1, "prefs set plotsliders" }, - { 1, "prefs set mqtt" }, { 1, "analyse help" }, { 1, "analyse lrc" }, { 1, "analyse crc" }, @@ -242,7 +240,6 @@ const static vocabulary_t vocabulary[] = { { 0, "hf felica reader" }, { 0, "hf felica sniff" }, { 0, "hf felica wrbl" }, - { 0, "hf felica dump" }, { 0, "hf felica rqservice" }, { 0, "hf felica rqresponse" }, { 0, "hf felica scsvcode" }, @@ -252,7 +249,6 @@ const static vocabulary_t vocabulary[] = { { 0, "hf felica rqspecver" }, { 0, "hf felica resetmode" }, { 0, "hf felica litesim" }, - { 0, "hf felica liteauth" }, { 0, "hf felica litedump" }, { 1, "hf fido help" }, { 1, "hf fido list" }, @@ -477,7 +473,6 @@ const static vocabulary_t vocabulary[] = { { 0, "hf mfdes getkeyversions" }, { 0, "hf mfdes getfileids" }, { 0, "hf mfdes getfileisoids" }, - { 0, "hf mfdes lsfile" }, { 0, "hf mfdes lsfiles" }, { 0, "hf mfdes dump" }, { 0, "hf mfdes createfile" }, @@ -799,7 +794,6 @@ const static vocabulary_t vocabulary[] = { { 0, "lf t55xx restore" }, { 1, "lf t55xx trace" }, { 0, "lf t55xx wakeup" }, - { 1, "lf t55xx view" }, { 0, "lf t55xx write" }, { 0, "lf t55xx bruteforce" }, { 0, "lf t55xx chk" }, @@ -838,9 +832,6 @@ const static vocabulary_t vocabulary[] = { { 0, "mem spiffs upload" }, { 0, "mem spiffs view" }, { 0, "mem spiffs wipe" }, - { 1, "mqtt help" }, - { 1, "mqtt send" }, - { 1, "mqtt receive" }, { 1, "nfc help" }, { 1, "nfc decode" }, { 0, "nfc type1 read" }, diff --git a/client/src/preferences.c b/client/src/preferences.c index f654a8533..37941ed65 100644 --- a/client/src/preferences.c +++ b/client/src/preferences.c @@ -48,54 +48,6 @@ static char *prefGetFilename(void) { return str_dup(preferencesFilename); } -static bool setDefaultMqttServer(const char *srv) { - - if ((srv == NULL) && (g_session.mqtt_server != NULL)) { - free(g_session.mqtt_server); - g_session.mqtt_server = NULL; - } - - if (srv == NULL) { - return false; - } - - g_session.mqtt_server = (char *)realloc(g_session.mqtt_server, strlen(srv) + 1); - strcpy(g_session.mqtt_server, srv); - return true; -} - -static bool setDefaultMqttPort(const char *port) { - - if ((port == NULL) && (g_session.mqtt_port != NULL)) { - free(g_session.mqtt_port); - g_session.mqtt_port = NULL; - } - - if (port == NULL) { - return false; - } - - g_session.mqtt_port = (char *)realloc(g_session.mqtt_port, strlen(port) + 1); - strcpy(g_session.mqtt_port, port); - return true; -} - -static bool setDefaultMqttTopic(const char *topic) { - - if ((topic == NULL) && (g_session.mqtt_topic != NULL)) { - free(g_session.mqtt_topic); - g_session.mqtt_topic = NULL; - } - - if (topic == NULL) { - return false; - } - - g_session.mqtt_topic = (char *)realloc(g_session.mqtt_topic, strlen(topic) + 1); - strcpy(g_session.mqtt_topic, topic); - return true; -} - int preferences_load(void) { // Set all defaults @@ -121,10 +73,6 @@ int preferences_load(void) { setDefaultPath(spDump, ""); setDefaultPath(spTrace, ""); - setDefaultMqttServer(""); - setDefaultMqttPort(""); - setDefaultMqttTopic(""); - // default save path if (get_my_user_directory() != NULL) { // should return path to .proxmark3 folder setDefaultPath(spDefault, get_my_user_directory()); @@ -329,13 +277,7 @@ void preferences_save_callback(json_t *root) { */ JsonSaveInt(root, "client.exe.delay", g_session.client_exe_delay); JsonSaveInt(root, "client.timeout", g_session.timeout); - - // MQTT - JsonSaveStr(root, "mqtt.server", g_session.mqtt_server); - JsonSaveStr(root, "mqtt.port", g_session.mqtt_port); - JsonSaveStr(root, "mqtt.topic", g_session.mqtt_topic); } - void preferences_load_callback(json_t *root) { json_error_t up_error = {0}; int b1; @@ -439,17 +381,6 @@ void preferences_load_callback(json_t *root) { // client command timeout if (json_unpack_ex(root, &up_error, 0, "{s:i}", "client.timeout", &i1) == 0) g_session.timeout = i1; - - // MQTT server - if (json_unpack_ex(root, &up_error, 0, "{s:s}", "mqtt.server", &s1) == 0) - setDefaultMqttServer(s1); - - if (json_unpack_ex(root, &up_error, 0, "{s:s}", "mqtt.port", &s1) == 0) - setDefaultMqttPort(s1); - - if (json_unpack_ex(root, &up_error, 0, "{s:s}", "mqtt.topic", &s1) == 0) - setDefaultMqttTopic(s1); - } // Help Functions @@ -469,6 +400,7 @@ static const char *pref_show_status_msg(prefShowOpt_t opt) { case prefShowUnknown: default: return ""; + } } @@ -588,7 +520,6 @@ static void showSavePathState(savePaths_t path_index, prefShowOpt_t opt) { case spItemCount: default: strcpy(s, _RED_("unknown")" save path......."); - break; } if (path_index < spItemCount) { @@ -671,30 +602,6 @@ static void showClientTimeoutState(void) { PrintAndLogEx(INFO, " communication timeout... " _GREEN_("%u") " ms", g_session.timeout); } -static void showMqttServer(prefShowOpt_t opt) { - if ((g_session.mqtt_server == NULL) || (strcmp(g_session.mqtt_server, "") == 0)) { - PrintAndLogEx(INFO, " MQTT server.............%s "_WHITE_("not set"), pref_show_status_msg(opt)); - } else { - PrintAndLogEx(INFO, " MQTT server.............%s "_GREEN_("%s"), pref_show_status_msg(opt), g_session.mqtt_server); - } -} - -static void showMqttPort(prefShowOpt_t opt) { - if ((g_session.mqtt_port == NULL) || (strcmp(g_session.mqtt_port, "") == 0)) { - PrintAndLogEx(INFO, " MQTT port...............%s "_WHITE_("not set"), pref_show_status_msg(opt)); - } else { - PrintAndLogEx(INFO, " MQTT port...............%s "_GREEN_("%s"), pref_show_status_msg(opt), g_session.mqtt_port); - } -} - -static void showMqttTopic(prefShowOpt_t opt) { - if ((g_session.mqtt_topic == NULL) || (strcmp(g_session.mqtt_topic, "") == 0)) { - PrintAndLogEx(INFO, " MQTT topic..............%s "_WHITE_("not set"), pref_show_status_msg(opt)); - } else { - PrintAndLogEx(INFO, " MQTT topic..............%s "_GREEN_("%s"), pref_show_status_msg(opt), g_session.mqtt_topic); - } -} - static int setCmdEmoji(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "prefs set emoji ", @@ -1030,7 +937,7 @@ static int setCmdExeDelay(const char *Cmd) { return PM3_SUCCESS; } -static int setCmdClientTimeout(const char *Cmd) { +static int setClientTimeout(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "prefs set client.timeout", "Set persistent preference of client communication timeout", @@ -1281,80 +1188,6 @@ static int setCmdBarMode(const char *Cmd) { return PM3_SUCCESS; } -static int setCmdMqtt(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "prefs set mqtt", - "Set persistent preference MQTT Server in the client", - "prefs set mqtt -s test.mosquito.com\n" - "prefs set mqtt -s test.mosquito.com -p 1883 -t proxdump\n" - ); - - void *argtable[] = { - arg_param_begin, - arg_str0("s", "srv", "", "default MQTT Server"), - arg_str0("p", "port", "", "default MQTT Port"), - arg_str0("t", "topic", "", "default MQTT Topic"), - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, true); - int deflen = 0; - char def_server[128] = {0}; - memset(def_server, 0, sizeof(def_server)); - int res = CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)def_server, sizeof(def_server), &deflen); - - int plen = 0; - char def_port[10] = {0}; - memset(def_port, 0, sizeof(def_port)); - res |= CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)def_port, sizeof(def_port), &plen); - - int tlen = 0; - char def_topic[10] = {0}; - memset(def_topic, 0, sizeof(def_topic)); - res |= CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)def_topic, sizeof(def_topic), &tlen); - CLIParserFree(ctx); - - // sanity checks - if (res) { - PrintAndLogEx(FAILED, "Error parsing input strings"); - return PM3_EINVARG; - } - - if (deflen) { - if (strcmp(def_server, g_session.mqtt_server) != 0) { - showMqttServer(prefShowOLD); - setDefaultMqttServer(def_server); - showMqttServer(prefShowNEW); - preferences_save(); - } else { - showMqttServer(prefShowNone); - } - } - - if (plen) { - if (strcmp(def_port, g_session.mqtt_port) != 0) { - showMqttPort(prefShowOLD); - setDefaultMqttPort(def_port); - showMqttPort(prefShowNEW); - preferences_save(); - } else { - showMqttPort(prefShowNone); - } - } - - if (tlen) { - if (strcmp(def_topic, g_session.mqtt_topic) != 0) { - showMqttTopic(prefShowOLD); - setDefaultMqttTopic(def_topic); - showMqttTopic(prefShowNEW); - preferences_save(); - } else { - showMqttTopic(prefShowNone); - } - } - - return PM3_SUCCESS; -} - static int getCmdEmoji(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "prefs get emoji", @@ -1501,7 +1334,7 @@ static int getCmdExeDelay(const char *Cmd) { return PM3_SUCCESS; } -static int getCmdClientTimeout(const char *Cmd) { +static int getClientTimeout(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "prefs get client.timeout", "Get preference of delay time before execution of a command in the client", @@ -1517,29 +1350,11 @@ static int getCmdClientTimeout(const char *Cmd) { return PM3_SUCCESS; } -static int getCmdMqtt(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "prefs get mqtt", - "Get preference of MQTT settings in the client", - "prefs get mqtt" - ); - void *argtable[] = { - arg_param_begin, - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, true); - CLIParserFree(ctx); - showMqttServer(prefShowNone); - showMqttPort(prefShowNone); - showMqttTopic(prefShowNone); - return PM3_SUCCESS; -} - static command_t CommandTableGet[] = { {"barmode", getCmdBarMode, AlwaysAvailable, "Get bar mode preference"}, {"client.debug", getCmdDebug, AlwaysAvailable, "Get client debug level preference"}, {"client.delay", getCmdExeDelay, AlwaysAvailable, "Get client execution delay preference"}, - {"client.timeout", getCmdClientTimeout, AlwaysAvailable, "Get client execution delay preference"}, + {"client.timeout", getClientTimeout, 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"}, @@ -1547,7 +1362,6 @@ static command_t CommandTableGet[] = { {"hints", getCmdHint, AlwaysAvailable, "Get hint display preference"}, {"output", getCmdOutput, AlwaysAvailable, "Get dump output style preference"}, {"plotsliders", getCmdPlotSlider, AlwaysAvailable, "Get plot slider display preference"}, - {"mqtt", getCmdMqtt, AlwaysAvailable, "Get MQTT preference"}, {NULL, NULL, NULL, NULL} }; @@ -1556,7 +1370,7 @@ static command_t CommandTableSet[] = { {"barmode", setCmdBarMode, AlwaysAvailable, "Set bar mode"}, {"client.debug", setCmdDebug, AlwaysAvailable, "Set client debug level"}, {"client.delay", setCmdExeDelay, AlwaysAvailable, "Set client execution delay"}, - {"client.timeout", setCmdClientTimeout, AlwaysAvailable, "Set client communication timeout"}, + {"client.timeout", setClientTimeout, AlwaysAvailable, "Set client communication timeout"}, {"color", setCmdColor, AlwaysAvailable, "Set color support"}, {"emoji", setCmdEmoji, AlwaysAvailable, "Set emoji display"}, @@ -1565,7 +1379,6 @@ static command_t CommandTableSet[] = { // {"devicedebug", setCmdDeviceDebug, AlwaysAvailable, "Set device debug level"}, {"output", setCmdOutput, AlwaysAvailable, "Set dump output style"}, {"plotsliders", setCmdPlotSliders, AlwaysAvailable, "Set plot slider display"}, - {"mqtt", setCmdMqtt, AlwaysAvailable, "Set MQTT default values"}, {NULL, NULL, NULL, NULL} }; @@ -1630,9 +1443,6 @@ static int CmdPrefShow(const char *Cmd) { showClientExeDelayState(); showOutputState(prefShowNone); showClientTimeoutState(); - showMqttServer(prefShowNone); - showMqttPort(prefShowNone); - showMqttTopic(prefShowNone); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; diff --git a/client/src/proxmark3.c b/client/src/proxmark3.c index 2904aaab8..f19adb71b 100644 --- a/client/src/proxmark3.c +++ b/client/src/proxmark3.c @@ -17,12 +17,14 @@ //----------------------------------------------------------------------------- #include "proxmark3.h" + #include #include #include #include #include // basename #include + #include "pm3line.h" #include "usart_defs.h" #include "util_posix.h" @@ -41,12 +43,13 @@ #include #endif + static int mainret = PM3_SUCCESS; #ifndef LIBPM3 #define BANNERMSG1 "" #define BANNERMSG2 "" -#define BANNERMSG3 "" +#define BANNERMSG3 "Release v4.20469 - Daddy Iceman" typedef enum LogoMode { UTF8, ANSI, ASCII } LogoMode; @@ -72,9 +75,8 @@ static void showBanner_logo(LogoMode mode) { sq, sq, tl, hl, hl, hl, br, __, sq, sq, vl, bl, sq, sq, tl, br, sq, sq, vl, __, bl, hl, hl, sq, sq, tr); PrintAndLogEx(NORMAL, " " _BLUE_("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s")" " BANNERMSG1, sq, sq, vl, __, __, __, __, __, sq, sq, vl, __, bl, hl, br, __, sq, sq, vl, sq, sq, sq, sq, sq, tl, br); - PrintAndLogEx(NORMAL, " " _BLUE_("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"), + PrintAndLogEx(NORMAL, " " _BLUE_("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s")" " BANNERMSG2, bl, hl, br, __, __, __, __, __, bl, hl, br, __, __, __, __, __, bl, hl, br, bl, hl, hl, hl, hl, br, __); - PrintAndLogEx(NORMAL, " " BANNERMSG2); break; } case ANSI: { @@ -85,8 +87,7 @@ static void showBanner_logo(LogoMode mode) { PrintAndLogEx(NORMAL, " " _CYAN_("8888888P\" 888 Y888P 888 \"Y8b. ")); PrintAndLogEx(NORMAL, " " _CYAN_("888 888 Y8P 888 888 888 ")); PrintAndLogEx(NORMAL, " " _CYAN_("888 888 \" 888 Y88b d88P") " " BANNERMSG1); - PrintAndLogEx(NORMAL, " " _CYAN_("888 888 888 \"Y8888P\"")); - PrintAndLogEx(NORMAL, " " BANNERMSG2); + PrintAndLogEx(NORMAL, " " _CYAN_("888 888 888 \"Y8888P\"") " " BANNERMSG2); break; } case ASCII: { @@ -97,11 +98,11 @@ static void showBanner_logo(LogoMode mode) { PrintAndLogEx(NORMAL, " 8888888P\" 888 Y888P 888 \"Y8b. "); PrintAndLogEx(NORMAL, " 888 888 Y8P 888 888 888 "); PrintAndLogEx(NORMAL, " 888 888 \" 888 Y88b d88P " BANNERMSG1); - PrintAndLogEx(NORMAL, " 888 888 888 \"Y8888P\""); - PrintAndLogEx(NORMAL, " " BANNERMSG2); + PrintAndLogEx(NORMAL, " 888 888 888 \"Y8888P\" " BANNERMSG2); break; } } + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, BANNERMSG3); } @@ -206,6 +207,7 @@ static void showBanner(void) { PrintAndLogEx(NORMAL, " [ " _YELLOW_("%s!")" :coffee: ]", get_quote()); // PrintAndLogEx(NORMAL, " [ https://patreon.com/iceman1001/ ]"); +// PrintAndLogEx(NORMAL, ""); // PrintAndLogEx(NORMAL, " Monero"); // PrintAndLogEx(NORMAL, " 43mNJLpgBVaTvyZmX9ajcohpvVkaRy1kbZPm8tqAb7itZgfuYecgkRF36rXrKFUkwEGeZedPsASRxgv4HPBHvJwyJdyvQuP"); PrintAndLogEx(NORMAL, ""); @@ -304,18 +306,16 @@ static bool DetectWindowsAnsiSupport(void) { #endif // disable colors if stdin or stdout are redirected - if ((! g_session.stdinOnTTY) || (! g_session.stdoutOnTTY)) { + if ((! g_session.stdinOnTTY) || (! g_session.stdoutOnTTY)) return false; - } HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); DWORD dwMode = 0; GetConsoleMode(hOut, &dwMode); //ENABLE_VIRTUAL_TERMINAL_PROCESSING is already set - if ((dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)) { + if ((dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)) return true; - } dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; @@ -335,13 +335,11 @@ int push_cmdscriptfile(char *path, bool stayafter) { } FILE *f = fopen(path, "r"); - if (f == NULL) { + if (f == NULL) return PM3_EFILE; - } - if (cmdscriptfile_idx == 0) { + if (cmdscriptfile_idx == 0) cmdscriptfile_stayafter = stayafter; - } cmdscriptfile[++cmdscriptfile_idx] = f; return PM3_SUCCESS; @@ -373,32 +371,28 @@ main_loop(const char *script_cmds_file, char *script_cmd, bool stayInCommandLoop bool execCommand = (script_cmd != NULL); bool fromInteractive = false; uint16_t script_cmd_len = 0; - if (execCommand) { script_cmd_len = strlen(script_cmd); str_creplace(script_cmd, script_cmd_len, ';', '\0'); } - bool stdinOnPipe = !isatty(STDIN_FILENO); char script_cmd_buf[256] = {0x00}; // iceman, needs lua script the same file_path_buffer as the rest // cache Version information now: - if (execCommand || script_cmds_file || stdinOnPipe) { + if (execCommand || script_cmds_file || stdinOnPipe) pm3_version(false, false); - } else { + else pm3_version_short(); - } if (script_cmds_file) { char *path; int res = searchFile(&path, CMD_SCRIPTS_SUBDIR, script_cmds_file, ".cmd", false); if (res == PM3_SUCCESS) { - if (push_cmdscriptfile(path, stayInCommandLoop) == PM3_SUCCESS) { + if (push_cmdscriptfile(path, stayInCommandLoop) == PM3_SUCCESS) PrintAndLogEx(SUCCESS, "executing commands from file: %s\n", path); - } else { + else PrintAndLogEx(ERR, "could not open " _YELLOW_("%s") "...", path); - } free(path); } } @@ -455,23 +449,20 @@ check_script: prompt_ctx = stdinOnPipe ? PROXPROMPT_CTX_STDIN : PROXPROMPT_CTX_SCRIPTCMD; cmd = str_dup(script_cmd); - if ((cmd != NULL) && (! fromInteractive)) { + if ((cmd != NULL) && (! fromInteractive)) printprompt = true; - } uint16_t len = strlen(script_cmd) + 1; script_cmd += len; - if (script_cmd_len == len - 1) { + if (script_cmd_len == len - 1) execCommand = false; - } script_cmd_len -= len; } else { // exit after exec command - if (script_cmd && !stayInCommandLoop) { + if (script_cmd && !stayInCommandLoop) break; - } // if there is a pipe from stdin if (stdinOnPipe) { @@ -561,27 +552,22 @@ check_script: mainret = CommandReceived(cmd); // exit or quit - if (mainret == PM3_EFATAL) { + if (mainret == PM3_EFATAL) break; - } - if (mainret == PM3_SQUIT) { // Normal quit, map to 0 mainret = PM3_SUCCESS; break; } } - free(cmd); cmd = NULL; - } else { PrintAndLogEx(NORMAL, "\n"); - if (script_cmds_file && stayInCommandLoop) { + if (script_cmds_file && stayInCommandLoop) stayInCommandLoop = false; - } else { + else break; - } } } // end while @@ -630,9 +616,8 @@ const char *get_my_executable_directory(void) { static void set_my_executable_path(void) { int path_length = wai_getExecutablePath(NULL, 0, NULL); - if (path_length == -1) { + if (path_length == -1) return; - } my_executable_path = (char *)calloc(path_length + 1, sizeof(uint8_t)); int dirname_length = 0; @@ -857,13 +842,12 @@ finish2: CloseProxmark(g_session.current_device); finish: - if (ret == PM3_SUCCESS) { + if (ret == PM3_SUCCESS) PrintAndLogEx(SUCCESS, _CYAN_("All done")); - } else if (ret == PM3_EOPABORTED) { + else if (ret == PM3_EOPABORTED) PrintAndLogEx(FAILED, "Aborted by user"); - } else { + else PrintAndLogEx(ERR, "Aborted on error %u", ret); - } return ret; } @@ -922,9 +906,8 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, const char *file goto finish; } - if (num_files == 0) { + if (num_files == 0) goto finish; - } for (int i = 0 ; i < num_files; ++i) { ret = flash_prepare(&files[i], can_write_bl, max_allowed * ONE_KB); @@ -945,26 +928,20 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, const char *file } finish: - if (ret != PM3_SUCCESS) { + if (ret != PM3_SUCCESS) PrintAndLogEx(WARNING, "The flashing procedure failed, follow the suggested steps!"); - } - ret = flash_stop_flashing(); CloseProxmark(g_session.current_device); - finish2: for (int i = 0 ; i < num_files; ++i) { flash_free(&files[i]); } - - if (ret == PM3_SUCCESS) { + if (ret == PM3_SUCCESS) PrintAndLogEx(SUCCESS, _CYAN_("All done")); - } else if (ret == PM3_EOPABORTED) { + else if (ret == PM3_EOPABORTED) PrintAndLogEx(FAILED, "Aborted by user"); - } else { + else PrintAndLogEx(ERR, "Aborted on error"); - } - PrintAndLogEx(INFO, "\nHave a nice day!"); return ret; } @@ -1000,6 +977,7 @@ void pm3_init(void) { // set global variables soon enough to get the log path set_my_executable_path(); set_my_user_directory(); + } #ifndef LIBPM3 @@ -1074,7 +1052,6 @@ int main(int argc, char *argv[]) { show_help(false, exec_name); return 1; } - if (port != NULL) { // We got already one PrintAndLogEx(ERR, _RED_("ERROR:") " cannot parse command line. We got " _YELLOW_("%s") " as port and now we got also: " _YELLOW_("%s") "\n", port, argv[i + 1]); @@ -1336,22 +1313,21 @@ int main(int argc, char *argv[]) { // This will allow the command line to override the settings.json values preferences_load(); // quick patch for debug level - if (debug_mode_forced == false) { + if (! debug_mode_forced) { g_debugMode = g_session.client_debug_level; } // settings_save (); // End Settings // even if prefs, we disable colors if stdin or stdout is not a TTY - if ((g_session.stdinOnTTY == false) || (g_session.stdoutOnTTY == false)) { + if ((! g_session.stdinOnTTY) || (! g_session.stdoutOnTTY)) { g_session.supports_colors = false; g_session.emoji_mode = EMO_ALTTEXT; } // Let's take a baudrate ok for real UART, USB-CDC & BT don't use that info anyway - if (speed == 0) { + if (speed == 0) speed = USART_BAUD_RATE; - } if (dumpmem_mode) { dumpmem_pm3(port, dumpmem_filename, dumpmem_addr, dumpmem_len, dumpmem_raw); @@ -1369,9 +1345,8 @@ int main(int argc, char *argv[]) { } if (script_cmd) { - while (script_cmd[strlen(script_cmd) - 1] == ' ') { + while (script_cmd[strlen(script_cmd) - 1] == ' ') script_cmd[strlen(script_cmd) - 1] = 0x00; - } if (strlen(script_cmd) == 0) { script_cmd = NULL; @@ -1404,23 +1379,23 @@ int main(int argc, char *argv[]) { CloseProxmark(g_session.current_device); } - if ((port != NULL) && (g_session.pm3_present == false)) { + if ((port != NULL) && (!g_session.pm3_present)) { exit(EXIT_FAILURE); } - if (g_session.pm3_present == false) { + if (!g_session.pm3_present) { PrintAndLogEx(INFO, _YELLOW_("OFFLINE") " mode. Check " _YELLOW_("\"%s -h\"") " if it's not what you want.\n", exec_name); } // ascii art only in interactive client - if (!script_cmds_file && !script_cmd && g_session.stdinOnTTY && g_session.stdoutOnTTY && (dumpmem_mode == false) && (flash_mode == false) && (reboot_bootloader_mode == false)) { + if (!script_cmds_file && !script_cmd && g_session.stdinOnTTY && g_session.stdoutOnTTY && !dumpmem_mode && !flash_mode && !reboot_bootloader_mode) { showBanner(); } // Save settings if not loaded from settings json file. // Doing this here will ensure other checks and updates are saved to over rule default // e.g. Linux color use check - if ((g_session.preferences_loaded == false) && (g_session.incognito == false)) { + if ((!g_session.preferences_loaded) && (!g_session.incognito)) { PrintAndLogEx(INFO, "Creating initial preferences file"); // json save reports file name, so just info msg here preferences_save(); // Save defaults g_session.preferences_loaded = true; @@ -1440,7 +1415,7 @@ int main(int argc, char *argv[]) { #ifdef HAVE_GUI -# if defined(_WIN32) || (defined(__MACH__) && defined(__APPLE__)) +# if defined(_WIN32) InitGraphics(argc, argv, script_cmds_file, script_cmd, stayInCommandLoop); MainGraphics(); # else diff --git a/client/src/pthread_spin_lock_shim.h b/client/src/pthread_spin_lock_shim.h deleted file mode 100644 index 243771a6c..000000000 --- a/client/src/pthread_spin_lock_shim.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - -Required imports: -#include - -*/ - -#ifndef PTHREAD_SPIN_LOCK_SHIM -#define PTHREAD_SPIN_LOCK_SHIM - -typedef int pthread_spinlock_t; - -#ifndef PTHREAD_PROCESS_SHARED -# define PTHREAD_PROCESS_SHARED 1 -#endif -#ifndef PTHREAD_PROCESS_PRIVATE -# define PTHREAD_PROCESS_PRIVATE 2 -#endif - -static inline int pthread_spin_init(pthread_spinlock_t *lock, int pshared) { - __asm__ __volatile__("" ::: "memory"); - *lock = 0; - return 0; -} - -static inline int pthread_spin_destroy(pthread_spinlock_t *lock) { - return 0; -} - -static inline int pthread_spin_lock(pthread_spinlock_t *lock) { - while (1) { - int i; - for (i = 0; i < 10000; i++) { - if (__sync_bool_compare_and_swap(lock, 0, 1)) { - return 0; - } - } - sched_yield(); - } -} - -static inline int pthread_spin_trylock(pthread_spinlock_t *lock) { - if (__sync_bool_compare_and_swap(lock, 0, 1)) { - return 0; - } - return 16; // EBUSY; -} - -static inline int pthread_spin_unlock(pthread_spinlock_t *lock) { - __asm__ __volatile__("" ::: "memory"); - *lock = 0; - return 0; -} - -#endif diff --git a/client/src/uart/uart_common.c b/client/src/uart/uart_common.c index f797d763c..e10897326 100644 --- a/client/src/uart/uart_common.c +++ b/client/src/uart/uart_common.c @@ -39,36 +39,31 @@ #endif bool uart_bind(void *socket, const char *bindAddrStr, const char *bindPortStr, bool isBindingIPv6) { - if (bindAddrStr == NULL && bindPortStr == NULL) { + if (bindAddrStr == NULL && bindPortStr == NULL) return true; // no need to bind - } struct sockaddr_storage bindSockaddr; memset(&bindSockaddr, 0, sizeof(bindSockaddr)); int bindPort = 0; // 0: port unspecified - if (bindPortStr != NULL) { + if (bindPortStr != NULL) bindPort = atoi(bindPortStr); - } - if (isBindingIPv6 == false) { + if (!isBindingIPv6) { struct sockaddr_in *bindSockaddr4 = (struct sockaddr_in *)&bindSockaddr; bindSockaddr4->sin_family = AF_INET; bindSockaddr4->sin_port = htons(bindPort); - if (bindAddrStr == NULL) { + if (bindAddrStr == NULL) bindSockaddr4->sin_addr.s_addr = INADDR_ANY; - } else { + else bindSockaddr4->sin_addr.s_addr = inet_addr(bindAddrStr); - } - } else { struct sockaddr_in6 *bindSockaddr6 = (struct sockaddr_in6 *)&bindSockaddr; bindSockaddr6->sin6_family = AF_INET6; bindSockaddr6->sin6_port = htons(bindPort); - if (bindAddrStr == NULL) { + if (bindAddrStr == NULL) bindSockaddr6->sin6_addr = in6addr_any; - } else { + else inet_pton(AF_INET6, bindAddrStr, &(bindSockaddr6->sin6_addr)); - } } #ifdef _WIN32 int res = bind(*(SOCKET *)socket, (struct sockaddr *)&bindSockaddr, sizeof(bindSockaddr)); diff --git a/client/src/ui.c b/client/src/ui.c index 1901ac9ef..4aed59a45 100644 --- a/client/src/ui.c +++ b/client/src/ui.c @@ -424,13 +424,18 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) { #ifdef RL_STATE_READCMD // We are using GNU readline. libedit (OSX) doesn't support this flag. int need_hack = (rl_readline_state & RL_STATE_READCMD) > 0; - char *saved_line = NULL; + char *saved_line; + int saved_point; if (need_hack) { + saved_point = rl_point; saved_line = rl_copy_text(0, rl_end); - rl_clear_visible_line(); + rl_save_prompt(); + rl_replace_line("", 0); + rl_redisplay(); } #endif + va_start(argptr, fmt); vsnprintf(buffer, sizeof(buffer), fmt, argptr); va_end(argptr); @@ -448,13 +453,14 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) { if (linefeed) { fprintf(stream, "\n"); } - fflush(stream); } #ifdef RL_STATE_READCMD + // We are using GNU readline. libedit (OSX) doesn't support this flag. if (need_hack) { - rl_on_new_line(); + rl_restore_prompt(); rl_replace_line(saved_line, 0); + rl_point = saved_point; rl_redisplay(); free(saved_line); } diff --git a/client/src/ui.h b/client/src/ui.h index b79798862..95ed70390 100644 --- a/client/src/ui.h +++ b/client/src/ui.h @@ -63,9 +63,6 @@ typedef struct { char *history_path; pm3_device_t *current_device; uint32_t timeout; - char *mqtt_server; - char *mqtt_port; - char *mqtt_topic; } session_arg_t; extern session_arg_t g_session; diff --git a/client/src/util.c b/client/src/util.c index 133f639ee..f5c3735d9 100644 --- a/client/src/util.c +++ b/client/src/util.c @@ -73,7 +73,6 @@ int kbd_enter_pressed(void) { c = getchar(); ret |= c == '\n'; } while (c != EOF); - //blocking flags &= ~O_NONBLOCK; if (fcntl(STDIN_FILENO, F_SETFL, flags) < 0) { @@ -1213,29 +1212,6 @@ void binstr_2_bytes(uint8_t *target, size_t *targetlen, const char *src) { } } -void binstr_2_u8(char *src, uint8_t n, uint8_t *dest) { - - uint8_t b = 0; - // Process binary string - for (uint8_t i = 0; i < n; ++i) { - b = (b << 1) | (src[i] == '1'); - } - if (dest) { - *dest = b; - } -} - -void binstr_2_u16(char *src, uint8_t n, uint16_t *dest) { - uint16_t b = 0; - // Process binary string - for (uint8_t i = 0; i < n; ++i) { - b = (b << 1) | (src[i] == '1'); - } - if (dest) { - *dest = b; - } -} - void hex_xor(uint8_t *d, const uint8_t *x, int n) { while (n--) { d[n] ^= x[n]; @@ -1630,40 +1606,3 @@ uint8_t get_highest_frequency(const uint8_t *d, uint8_t n) { PrintAndLogEx(DEBUG, "highest occurance... %u xor byte... 0x%02X", highest, v); return v; } - -size_t unduplicate(uint8_t *d, size_t n, const uint8_t item_n) { - if (n == 0) { - return 0; - } - if (n == 1) { - return 1; - } - - int write_index = 0; - - for (int read_index = 0; read_index < n; ++read_index) { - uint8_t *current = d + read_index * item_n; - - bool is_duplicate = false; - - // Check against all previous unique elements - for (int i = 0; i < write_index; ++i) { - uint8_t *unique = d + i * item_n; - if (memcmp(current, unique, item_n) == 0) { - is_duplicate = 1; - break; - } - } - - // If not duplicate, move to the write_index position - if (is_duplicate == false) { - uint8_t *dest = d + write_index * item_n; - if (dest != current) { - memcpy(dest, current, item_n); - } - write_index++; - } - } - - return write_index; -} diff --git a/client/src/util.h b/client/src/util.h index 186f2e2a7..0ca53591e 100644 --- a/client/src/util.h +++ b/client/src/util.h @@ -141,9 +141,6 @@ int binstr_2_binarray(uint8_t *target, char *source, int length); void bytes_2_binstr(char *target, const uint8_t *source, size_t sourcelen); void binstr_2_bytes(uint8_t *target, size_t *targetlen, const char *src); -void binstr_2_u8(char *src, uint8_t n, uint8_t *dest); -void binstr_2_u16(char *src, uint8_t n, uint16_t *dest); - void hex_xor(uint8_t *d, const uint8_t *x, int n); void hex_xor_token(uint8_t *d, const uint8_t *x, int dn, int xn); @@ -197,7 +194,4 @@ struct smartbuf { void sb_append_char(smartbuf *sb, unsigned char c); uint8_t get_highest_frequency(const uint8_t *d, uint8_t n); - -size_t unduplicate(uint8_t *d, size_t n, const uint8_t item_n); - #endif diff --git a/client/src/wiegand_formats.c b/client/src/wiegand_formats.c index fa1d68eb1..03b0f5501 100644 --- a/client/src/wiegand_formats.c +++ b/client/src/wiegand_formats.c @@ -733,7 +733,7 @@ static bool Unpack_Sie36(wiegand_message_t *packed, wiegand_card_t *card) { card->CardNumber = get_linear_field(packed, 19, 16); card->ParityValid = (get_bit_by_position(packed, 0) == oddparity32(get_nonlinear_field(packed, 23, (uint8_t[]) {1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21, 22, 24, 25, 27, 28, 30, 31, 33, 34}))) && - (get_bit_by_position(packed, 35) == evenparity32(get_nonlinear_field(packed, 23, (uint8_t[]) {1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34}))); + (get_bit_by_position(packed, 35) == oddparity32(get_nonlinear_field(packed, 23, (uint8_t[]) {1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34}))); return true; } @@ -1477,7 +1477,7 @@ static const cardformat_t FormatTable[] = { {"BQT34", Pack_bqt34, Unpack_bqt34, "BQT 34-bit", 34, {1, 1, 0, 0, 1, 0xFF, 0xFFFFFF, 0, 0}}, // from cardinfo.barkweb.com.au {"C1k35s", Pack_C1k35s, Unpack_C1k35s, "HID Corporate 1000 35-bit std", 35, {1, 1, 0, 0, 1, 0xFFF, 0xFFFFF, 0, 0}}, // imported from old pack/unpack {"C15001", Pack_C15001, Unpack_C15001, "HID KeyScan 36-bit", 36, {1, 1, 0, 1, 1, 0xFF, 0xFFFF, 0, 0x3FF}}, // from Proxmark forums - {"S12906", Pack_S12906, Unpack_S12906, "HID Simplex 36-bit", 36, {1, 1, 1, 0, 1, 0xFF, 0xFFFFFF, 0x3, 0}}, // from cardinfo.barkweb.com.au + {"S12906", Pack_S12906, Unpack_S12906, "HID Simplex 36-bit", 36, {1, 1, 1, 0, 1, 0xFF, 0x3, 0xFFFFFF, 0}}, // from cardinfo.barkweb.com.au {"Sie36", Pack_Sie36, Unpack_Sie36, "HID 36-bit Siemens", 36, {1, 1, 0, 0, 1, 0x3FFFF, 0xFFFF, 0, 0}}, // from cardinfo.barkweb.com.au {"H10320", Pack_H10320, Unpack_H10320, "HID H10320 37-bit BCD", 37, {1, 0, 0, 0, 1, 0, 99999999, 0, 0}}, // from Proxmark forums {"H10302", Pack_H10302, Unpack_H10302, "HID H10302 37-bit huge ID", 37, {1, 0, 0, 0, 1, 0, 0x7FFFFFFFF, 0, 0}}, // from Proxmark forums diff --git a/common/commonutil.c b/common/commonutil.c index ff0782514..48ce64bfa 100644 --- a/common/commonutil.c +++ b/common/commonutil.c @@ -450,43 +450,6 @@ void lslx(uint8_t *d, size_t n, uint8_t shifts) { } } -// right shift an array of length one bit -void rsl(uint8_t *d, size_t n) { - - uint8_t carry = 0; - - for (size_t i = 0; i < n; i++) { - - // Save the LSB before shifting - uint8_t new_carry = d[i] & 0x1; - - // Shift current byte right and incorporate previous carry - d[i] = (d[i] >> 1) | (carry ? 0x80 : 0); - - // Update carry for next byte - carry = new_carry; - } -} - -void rslx(uint8_t *d, size_t n, uint8_t shifts) { - - uint8_t carry = 0; - for (uint8_t j = 0; j < shifts; j++) { - - for (size_t i = 0; i < n; i++) { - - // Save the LSB before shifting - uint8_t new_carry = d[i] & 0x1; - - // Shift current byte right and incorporate previous carry - d[i] = (d[i] >> 1) | (carry ? 0x80 : 0); - - // Update carry for next byte - carry = new_carry; - } - } -} - // BSWAP24 of array[3] uint32_t le24toh(const uint8_t data[3]) { diff --git a/common/commonutil.h b/common/commonutil.h index bb4697ffa..f963805bb 100644 --- a/common/commonutil.h +++ b/common/commonutil.h @@ -75,7 +75,6 @@ typedef struct { int calculate_hours_between_dates(const Date_t s, Date_t *e); -void add_minutes(Date_t *d, int minutes_to_add); void add_hours(Date_t *d, int hours_to_add); void add_days(Date_t *d, int days_to_add); uint8_t days_in_month(int year, int month); @@ -136,9 +135,6 @@ void xor(uint8_t *dest, const uint8_t *src, size_t n); void lsl(uint8_t *d, size_t n); void lslx(uint8_t *d, size_t n, uint8_t shifts); -void rsl(uint8_t *d, size_t n); -void rslx(uint8_t *d, size_t n, uint8_t shifts); - uint32_t le24toh(const uint8_t data[3]); void htole24(uint32_t val, uint8_t data[3]); diff --git a/common/crapto1/crypto1.c b/common/crapto1/crypto1.c index 8ffe04fdb..78d42cec4 100644 --- a/common/crapto1/crypto1.c +++ b/common/crapto1/crypto1.c @@ -35,9 +35,8 @@ int filter(uint32_t const x) { (x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16) void crypto1_init(struct Crypto1State *state, uint64_t key) { - if (state == NULL) { + if (state == NULL) return; - } state->odd = 0; state->even = 0; for (int i = 47; i > 0; i -= 2) { @@ -54,9 +53,7 @@ void crypto1_deinit(struct Crypto1State *state) { #if !defined(__arm__) || defined(__linux__) || defined(_WIN32) || defined(__APPLE__) // bare metal ARM Proxmark lacks calloc()/free() struct Crypto1State *crypto1_create(uint64_t key) { struct Crypto1State *state = calloc(sizeof(*state), sizeof(uint8_t)); - if (state == NULL) { - return NULL; - } + if (!state) return NULL; crypto1_init(state, key); return state; } @@ -148,8 +145,8 @@ uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) { */ uint32_t prng_successor(uint32_t x, uint32_t n) { SWAPENDIAN(x); - while (n--) { + while (n--) x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; - } + return SWAPENDIAN(x); } diff --git a/common/crc16.c b/common/crc16.c index ecf8c1ed7..e55b20bdc 100644 --- a/common/crc16.c +++ b/common/crc16.c @@ -27,14 +27,12 @@ static CrcType_t current_crc_type = CRC_NONE; void init_table(CrcType_t crctype) { // same crc algo, and initialised already - if (crctype == current_crc_type && crc_table_init) { + if (crctype == current_crc_type && crc_table_init) return; - } // not the same crc algo. reset table. - if (crctype != current_crc_type) { + if (crctype != current_crc_type) reset_table(); - } current_crc_type = crctype; @@ -70,29 +68,23 @@ void init_table(CrcType_t crctype) { void generate_table(uint16_t polynomial, bool refin) { for (uint16_t i = 0; i < 256; i++) { - uint16_t c, crc = 0; - - if (refin) { + if (refin) c = reflect8(i) << 8; - } else { + else c = i << 8; - } for (uint16_t j = 0; j < 8; j++) { - if ((crc ^ c) & 0x8000) { + if ((crc ^ c) & 0x8000) crc = (crc << 1) ^ polynomial; - } else { + else crc = crc << 1; - } c = c << 1; } - - if (refin) { + if (refin) crc = reflect16(crc); - } crc_table[i] = crc; } @@ -110,25 +102,21 @@ uint16_t crc16_fast(uint8_t const *d, size_t n, uint16_t initval, bool refin, bo // fast lookup table algorithm without augmented zero bytes, e.g. used in pkzip. // only usable with polynom orders of 8, 16, 24 or 32. - if (n == 0) { + if (n == 0) return (~initval); - } uint16_t crc = initval; - if (refin) { + if (refin) crc = reflect16(crc); - } - if (refin == false) { + if (!refin) while (n--) crc = (crc << 8) ^ crc_table[((crc >> 8) ^ *d++) & 0xFF ]; - } else { + else while (n--) crc = (crc >> 8) ^ crc_table[(crc & 0xFF) ^ *d++]; - } - if (refout ^ refin) { + if (refout ^ refin) crc = reflect16(crc); - } return crc; } @@ -155,9 +143,8 @@ uint16_t update_crc16(uint16_t crc, uint8_t c) { // two ways. msb or lsb loop. uint16_t Crc16(uint8_t const *d, size_t bitlength, uint16_t remainder, uint16_t polynomial, bool refin, bool refout) { - if (bitlength == 0) { + if (bitlength == 0) return (~remainder); - } uint8_t offset = 8 - (bitlength % 8); // front padding with 0s won't change the CRC result @@ -166,9 +153,7 @@ uint16_t Crc16(uint8_t const *d, size_t bitlength, uint16_t remainder, uint16_t uint8_t c = prebits | d[i] >> offset; prebits = d[i] << (8 - offset); - if (refin) { - c = reflect8(c); - } + if (refin) c = reflect8(c); // xor in at msb remainder ^= (c << 8); @@ -182,10 +167,8 @@ uint16_t Crc16(uint8_t const *d, size_t bitlength, uint16_t remainder, uint16_t } } } - - if (refout) { + if (refout) remainder = reflect16(remainder); - } return remainder; } diff --git a/common/default_version_pm3.c b/common/default_version_pm3.c index d93a7ef15..419ee95ff 100644 --- a/common/default_version_pm3.c +++ b/common/default_version_pm3.c @@ -1,20 +1,5 @@ -//----------------------------------------------------------------------------- -// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. -// -// This program 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 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. -// -// See LICENSE.txt for the text of the license. -//----------------------------------------------------------------------------- #include "common.h" -/* This is the default version_pm3.c file that Makefile.common falls back to if sh is not available */ +/* Generated file, do not edit */ #ifndef ON_DEVICE #define SECTVERSINFO #else @@ -23,10 +8,10 @@ const struct version_information_t SECTVERSINFO g_version_information = { VERSION_INFORMATION_MAGIC, - 1, /* version 1 */ - 0, /* version information not present */ - 2, /* cleanliness couldn't be determined */ - "Iceman/master/unknown", - "1970-01-01 00:00:00", - "no sha256" + 1, + 1, + 2, + "Iceman/master/v4.20469", + "2025-06-16 16:18:01", + "72b1b17a3" }; diff --git a/common/hitag2/hitag2_crypto.h b/common/hitag2/hitag2_crypto.h index f5d4e7102..1dae77353 100644 --- a/common/hitag2/hitag2_crypto.h +++ b/common/hitag2/hitag2_crypto.h @@ -29,7 +29,7 @@ typedef struct { enum { TAG_STATE_RESET = 0x01, // Just powered up, awaiting GetSnr TAG_STATE_ACTIVATING = 0x02, // In activation phase (password mode), sent UID, awaiting reader password -// TAG_STATE_ACTIVATED = 0x03, // Activation complete, awaiting read/write commands + TAG_STATE_ACTIVATED = 0x03, // Activation complete, awaiting read/write commands TAG_STATE_WRITING = 0x04, // In write command, awaiting sector contents to be written } state; uint16_t active_sector; diff --git a/common_arm/Makefile.common b/common_arm/Makefile.common index e8e574112..a845963b2 100644 --- a/common_arm/Makefile.common +++ b/common_arm/Makefile.common @@ -49,7 +49,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 diff --git a/common_arm/ticks.c b/common_arm/ticks.c index 73182a11c..4abda2689 100644 --- a/common_arm/ticks.c +++ b/common_arm/ticks.c @@ -116,9 +116,8 @@ uint32_t RAMFUNC GetTickCount(void) { uint32_t RAMFUNC GetTickCountDelta(uint32_t start_ticks) { uint32_t stop_ticks = AT91C_BASE_RTTC->RTTC_RTVR; - if (stop_ticks >= start_ticks) { + if (stop_ticks >= start_ticks) return stop_ticks - start_ticks; - } return (UINT32_MAX - start_ticks) + stop_ticks; } diff --git a/doc/commands.json b/doc/commands.json index 564f068d7..b92990219 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -278,8 +278,9 @@ }, "data crypto": { "command": "data crypto", - "description": "This command lets you encrypt or decrypt data using DES/3DES/AES. Supply data, key, IV (needed for des MAC or aes), and cryptography action.", + "description": "Encrypt data, right here, right now. Or decrypt.", "notes": [ + "Supply data, key, IV (needed for des MAC or aes), and cryptography action.", "To calculate a MAC for FMCOS, supply challenge as IV, data as data, and session/line protection key as key.", "To calculate a MAC for FeliCa, supply first RC as IV, BLE+data as data and session key as key.", "data crypto -d 04D6850E06AABB80 -k FFFFFFFFFFFFFFFF --iv 9EA0401A00000000 --des -> Calculate a MAC for FMCOS chip. The result should be ED3A0133" @@ -1135,7 +1136,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... } mqtt { MQTT commmands... } nfc { NFC commands... } piv { PIV 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 --------------------------------------------------------------------------------------- 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... } piv { PIV 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 --------------------------------------------------------------------------------------- auto available offline: no Run LF SEARCH / HF SEARCH / DATA PLOT / DATA SAVE", "notes": [ "auto" ], @@ -1381,8 +1382,7 @@ "hf 14a sim -t 9 -> FM11RF005SH Shanghai Metro", "hf 14a sim -t 10 -> ST25TA IKEA Rothult", "hf 14a sim -t 11 -> Javacard (JCOP)", - "hf 14a sim -t 12 -> 4K Seos card", - "hf 14a sim -t 13 -> MIFARE Ultralight C" + "hf 14a sim -t 12 -> 4K Seos card" ], "offline": false, "options": [ @@ -1392,11 +1392,9 @@ "-n, --num Exit simulation after blocks have been read by reader. 0 = infinite", "-x Performs the 'reader attack', nr/ar attack against a reader", "--sk Fill simulator keys from found keys", - "-v, --verbose verbose output", - "--c1 UL-C Auth - all zero handshake part 1", - "--c2 UL-C Auth - all zero handshake part 2" + "-v, --verbose verbose output" ], - "usage": "hf 14a sim [-hxv] -t <1-12> [-u ] [-n ] [--sk] [--c1] [--c2]" + "usage": "hf 14a sim [-hxv] -t <1-12> [-u ] [-n ] [--sk]" }, "hf 14a simaid": { "command": "hf 14a simaid", @@ -2659,19 +2657,6 @@ ], "usage": "hf felica auth2 [-hv] [-i ] [-c ] [-k ]" }, - "hf felica dump": { - "command": "hf felica dump", - "description": "Dump all existing Area Code and Service Code. Only works on services that do not require authentication yet.", - "notes": [ - "hf felica dump" - ], - "offline": false, - "options": [ - "-h, --help This help", - "--no-auth read public services" - ], - "usage": "hf felica dump [-h] [--no-auth]" - }, "hf felica help": { "command": "hf felica help", "description": "----------- ----------------------- General ----------------------- help This help list List ISO 18092/FeliCa history ----------- ----------------------- Operations ----------------------- ----------- ----------------------- FeliCa Standard ----------------------- ----------- ----------------------- FeliCa Light ----------------------- --------------------------------------------------------------------------------------- hf felica list available offline: yes Alias of `trace list -t felica` 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", @@ -2705,25 +2690,6 @@ ], "usage": "hf felica info [-h]" }, - "hf felica liteauth": { - "command": "hf felica liteauth", - "description": "Authenticate", - "notes": [ - "hf felica liteauth -i 11100910C11BC407", - "hf felica liteauth --key 46656c69436130313233343536616263", - "hf felica liteauth --key 46656c69436130313233343536616263 -k", - "hf felica liteauth -c 701185c59f8d30afeab8e4b3a61f5cc4 --key 46656c69436130313233343536616263" - ], - "offline": false, - "options": [ - "-h, --help This help", - "--key set card key, 16 bytes", - "-c, set random challenge, 16 bytes", - "-i, set custom IDm", - "-k, keep signal field ON after receive" - ], - "usage": "hf felica liteauth [-hk] [--key ] [-c ] [-i ]" - }, "hf felica litedump": { "command": "hf felica litedump", "description": "Dump ISO/18092 FeliCa Lite tag. It will timeout after 200sec", @@ -2732,11 +2698,9 @@ ], "offline": false, "options": [ - "-h, --help This help", - "-i, set custom IDm", - "--key set card key, 16 bytes" + "-h, --help This help" ], - "usage": "hf felica litedump [-h] [-i ] [--key ]" + "usage": "hf felica litedump [-h]" }, "hf felica litesim": { "command": "hf felica litesim", @@ -2888,7 +2852,7 @@ }, "hf felica scsvcode": { "command": "hf felica scsvcode", - "description": "Dump all existing Area Code and Service Code.", + "description": "Feature not implemented yet. Feel free to contribute!", "notes": [ "hf felica scsvcode" ], @@ -3696,10 +3660,9 @@ "--elite elite computations applied to key", "--raw no computations applied to key", "-v, --verbose verbose output", - "--shallow use shallow (ASK) reader modulation instead of OOK", - "--nr replay of nr mac with privilege escalation" + "--shallow use shallow (ASK) reader modulation instead of OOK" ], - "usage": "hf iclass restore [-hv] -f [-k ] [--ki ] --first --last [--credit] [--elite] [--raw] [--shallow] [--nr]" + "usage": "hf iclass restore [-hv] -f [-k ] [--ki ] --first --last [--credit] [--elite] [--raw] [--shallow]" }, "hf iclass sam": { "command": "hf iclass sam", @@ -3720,10 +3683,9 @@ "-p, --prevent fake epurse update", "--shallow shallow mod", "-d, --data DER encoded command to send to SAM", - "-s, --snmp data is in snmp format without headers", "--info get SAM infos (version, serial number)" ], - "usage": "hf iclass sam [-hvkntps] [--break] [--shallow] [-d ]... [--info]" + "usage": "hf iclass sam [-hvkntp] [--break] [--shallow] [-d ]... [--info]" }, "hf iclass sim": { "command": "hf iclass sim", @@ -3843,7 +3805,7 @@ "--credit key is assumed to be the credit key", "--elite elite computations applied to key", "--raw no computations applied to key", - "--nr replay of NR/MAC block write or use privilege escalation if mac is empty", + "--nr replay of NR/MAC", "-v, --verbose verbose output", "--shallow use shallow (ASK) reader modulation instead of OOK" ], @@ -5524,8 +5486,7 @@ "hf mf sim --1k -u 11223344556677 -> MIFARE Classic 1k with 7b UID", "hf mf sim --1k -u 11223344 -i -x -> Perform reader attack in interactive mode", "hf mf sim --2k -> MIFARE 2k", - "hf mf sim --4k -> MIFARE 4k", - "hf mf sim --1k -x -e -> Keep simulation running and populate with found reader keys" + "hf mf sim --4k -> MIFARE 4khf mf sim --1k -x -e --> Keep simulation running and populate with found reader keys" ], "offline": false, "options": [ @@ -5543,11 +5504,10 @@ "-y Performs the nested 'reader attack'. This requires preloading nt & nt_enc in emulator memory. Implies -x.", "-e, --emukeys Fill simulator keys from found keys. Requires -x or -y. Implies -i. Simulation will restart automatically.", "--allowkeyb Allow key B even if readable", - "--allowover Allow auth attempts out of range for selected MIFARE Classic type", "-v, --verbose Verbose output", "--cve Trigger CVE 2021_0430" ], - "usage": "hf mf sim [-hixyev] [-u ] [--mini] [--1k] [--2k] [--4k] [--atqa ] [--sak ] [-n ] [--allowkeyb] [--allowover] [--cve]" + "usage": "hf mf sim [-hixyev] [-u ] [--mini] [--1k] [--2k] [--4k] [--atqa ] [--sak ] [-n ] [--allowkeyb] [--cve]" }, "hf mf staticnested": { "command": "hf mf staticnested", @@ -5680,8 +5640,7 @@ "hf mfdes auth -n 0 -t des -k 0000000000000000 --kdf none -> select PICC level and authenticate with key num=0, key type=des, key=00..00 and key derivation = none", "hf mfdes auth -n 0 -t aes -k 00000000000000000000000000000000 -> select PICC level and authenticate with key num=0, key type=aes, key=00..00 and key derivation = none", "hf mfdes auth -n 0 -t des -k 0000000000000000 --save -> select PICC level and authenticate and in case of successful authentication - save channel parameters to defaults", - "hf mfdes auth --aid 123456 -> select application 123456 and authenticate via parameters from `default` command", - "hf mfdes auth --dfname D2760000850100 -n 0 -t aes -k 00000000000000000000000000000000 -> select DF by name and authenticate" + "hf mfdes auth --aid 123456 -> select application 123456 and authenticate via parameters from `default` command" ], "offline": false, "options": [ @@ -5698,10 +5657,9 @@ "--schann Secure channel", "--aid Application ID of application for some parameters (3 hex bytes, big endian)", "--isoid Application ISO ID (ISO DF ID) (2 hex bytes, big endian)", - "--dfname Application ISO DF Name (5-16 hex bytes, big endian)", "--save saves channels parameters to defaults if authentication succeeds" ], - "usage": "hf mfdes auth [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [--dfname ] [--save]" + "usage": "hf mfdes auth [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [--save]" }, "hf mfdes bruteaid": { "command": "hf mfdes bruteaid", @@ -6074,7 +6032,7 @@ "-a, --apdu Show APDU requests and responses", "-v, --verbose Verbose output", "-n, --keyno Key number", - "-t, --algo Crypt algo (deft: 2TDEA)", + "-t, --algo Crypt algo", "-k, --key Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)", "--kdf Key Derivation Function (KDF)", "-i, --kdfi KDF input (1-31 hex bytes)", @@ -6192,11 +6150,10 @@ "--schann Secure channel", "--aid Application ID (3 hex bytes, big endian)", "--isoid Application ISO ID (ISO DF ID) (2 hex bytes, big endian).", - "--dfname Application ISO DF Name (5-16 hex bytes, big endian)", "-f, --file Filename of dictionary", "--save Save found key and parameters to defaults" ], - "usage": "hf mfdes detect [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [--dfname ] [-f ] [--save]" + "usage": "hf mfdes detect [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [-f ] [--save]" }, "hf mfdes dump": { "command": "hf mfdes dump", @@ -6219,11 +6176,10 @@ "--schann Secure channel", "--aid Application ID (3 hex bytes, big endian)", "--isoid Application ISO ID (ISO DF ID) (2 hex bytes, big endian)", - "--dfname Application ISO DF Name (5-16 hex bytes, big endian)", "-l, --length Maximum length for read data files (3 hex bytes, big endian)", "--no-auth Execute without authentication" ], - "usage": "hf mfdes dump [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [--dfname ] [-l ] [--no-auth]" + "usage": "hf mfdes dump [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [-l ] [--no-auth]" }, "hf mfdes formatpicc": { "command": "hf mfdes formatpicc", @@ -6267,10 +6223,9 @@ "-m, --cmode Communicaton mode", "-c, --ccset Communicaton command set", "--schann Secure channel", - "--no-auth Execute without authentication", - "--dfname Application ISO DF Name (5-16 hex bytes, big endian)" + "--no-auth Execute without authentication" ], - "usage": "hf mfdes getfreemem [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--no-auth] [--dfname ]" + "usage": "hf mfdes getfreemem [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--no-auth]" }, "hf mfdes getaids": { "command": "hf mfdes getaids", @@ -6323,8 +6278,7 @@ "description": "Get File IDs list from card. Master key needs to be provided or flag --no-auth set.", "notes": [ "hf mfdes getfileids --aid 123456 -> execute with defaults from `default` command", - "hf mfdes getfileids -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 -> execute with default factory setup", - "hf mfdes getfileids --dfname D2760000850100 -> select DF by name and get file IDs" + "hf mfdes getfileids -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 -> execute with default factory setup" ], "offline": false, "options": [ @@ -6341,10 +6295,9 @@ "--schann Secure channel", "--aid Application ID (3 hex bytes, big endian)", "--isoid Application ISO ID (ISO DF ID) (2 hex bytes, big endian).", - "--dfname Application ISO DF Name (5-16 hex bytes, big endian)", "--no-auth Execute without authentication" ], - "usage": "hf mfdes getfileids [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [--dfname ] [--no-auth]" + "usage": "hf mfdes getfileids [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [--no-auth]" }, "hf mfdes getfileisoids": { "command": "hf mfdes getfileisoids", @@ -6353,8 +6306,7 @@ "hf mfdes getfileisoids --aid 123456 -> execute with defaults from `default` command", "hf mfdes getfileisoids -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 -> execute with default factory setup", "hf mfdes getfileisoids --isoid df01 -> get iso file ids from Desfire Light with factory card settings", - "hf mfdes getfileisoids --isoid df01 --schann lrp -t aes -> get iso file ids from Desfire Light via lrp channel with default key authentication", - "hf mfdes getfileisoids --dfname D2760000850100 -> select DF by name and get file ISO IDs" + "hf mfdes getfileisoids --isoid df01 --schann lrp -t aes -> get iso file ids from Desfire Light via lrp channel with default key authentication" ], "offline": false, "options": [ @@ -6371,10 +6323,9 @@ "--schann Secure channel", "--aid Application ID (3 hex bytes, big endian)", "--isoid Application ISO ID (ISO DF ID) (2 hex bytes, big endian).", - "--dfname Application ISO DF Name (5-16 hex bytes, big endian)", "--no-auth Execute without authentication" ], - "usage": "hf mfdes getfileisoids [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [--dfname ] [--no-auth]" + "usage": "hf mfdes getfileisoids [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [--no-auth]" }, "hf mfdes getfilesettings": { "command": "hf mfdes getfilesettings", @@ -6382,8 +6333,7 @@ "notes": [ "hf mfdes getfilesettings --aid 123456 --fid 01 -> execute with defaults from `default` command", "hf mfdes getfilesettings --isoid df01 --fid 00 --no-auth -> get file settings with select by iso id", - "hf mfdes getfilesettings -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 --fid 01 -> execute with default factory setup", - "hf mfdes getfilesettings --dfname D2760000850100 --fid 01 -> select DF by name and get file settings" + "hf mfdes getfilesettings -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 --fid 01 -> execute with default factory setup" ], "offline": false, "options": [ @@ -6400,19 +6350,17 @@ "--schann Secure channel", "--aid Application ID (3 hex bytes, big endian)", "--isoid Application ISO ID (ISO DF ID) (2 hex bytes, big endian)", - "--dfname Application ISO DF Name (5-16 hex bytes, big endian)", "--fid File ID (1 hex byte). (def: 1)", "--no-auth Execute without authentication" ], - "usage": "hf mfdes getfilesettings [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [--dfname ] [--fid ] [--no-auth]" + "usage": "hf mfdes getfilesettings [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [--fid ] [--no-auth]" }, "hf mfdes getkeysettings": { "command": "hf mfdes getkeysettings", "description": "Get key settings for card level or application level.", "notes": [ "hf mfdes getkeysettings -> get picc key settings with default key/channel setup", - "hf mfdes getkeysettings --aid 123456 -> get app 123456 key settings with default key/channel setup", - "hf mfdes getkeysettings --dfname D2760000850100 -> select DF by name and get key settings" + "hf mfdes getkeysettings --aid 123456 -> get app 123456 key settings with default key/channel setup" ], "offline": false, "options": [ @@ -6427,10 +6375,9 @@ "-m, --cmode Communicaton mode", "-c, --ccset Communicaton command set", "--schann Secure channel", - "--aid Application ID (3 hex bytes, big endian)", - "--dfname Application ISO DF Name (5-16 hex bytes, big endian)" + "--aid Application ID (3 hex bytes, big endian)" ], - "usage": "hf mfdes getkeysettings [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--dfname ]" + "usage": "hf mfdes getkeysettings [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ]" }, "hf mfdes getkeyversions": { "command": "hf mfdes getkeyversions", @@ -6439,8 +6386,7 @@ "--keynum parameter: App level: key number. PICC level: 00..0d - keys count, 21..23 vc keys, default 0x00.", "hf mfdes getkeyversions --keynum 00 -> get picc master key version with default key/channel setup", "hf mfdes getkeyversions --aid 123456 --keynum 0d -> get app 123456 all key versions with default key/channel setup", - "hf mfdes getkeyversions --aid 123456 --keynum 0d --no-auth -> get key version without authentication", - "hf mfdes getkeyversions --dfname D2760000850100 --keynum 00 -> select DF by name and get key versions" + "hf mfdes getkeyversions --aid 123456 --keynum 0d --no-auth -> get key version without authentication" ], "offline": false, "options": [ @@ -6457,20 +6403,18 @@ "--schann Secure channel", "--aid Application ID (3 hex bytes, big endian)", "--isoid Application ISO ID (ISO DF ID) (2 hex bytes, big endian).", - "--dfname Application ISO DF Name (5-16 hex bytes, big endian)", "--keynum Key number/count (1 hex byte). (def: 0x00)", "--keyset Keyset number (1 hex byte)", "--no-auth Execute without authentication" ], - "usage": "hf mfdes getkeyversions [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [--dfname ] [--keynum ] [--keyset ] [--no-auth]" + "usage": "hf mfdes getkeyversions [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [--keynum ] [--keyset ] [--no-auth]" }, "hf mfdes getuid": { "command": "hf mfdes getuid", "description": "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. Any card's key needs to be provided.", "notes": [ "hf mfdes getuid -> execute with default factory setup", - "hf mfdes getuid --isoid df01 -t aes --schan lrp -> for desfire lights default settings", - "hf mfdes getuid --dfname D2760000850100 -> select DF by name and get UID" + "hf mfdes getuid --isoid df01 -t aes --schan lrp -> for desfire lights default settings" ], "offline": false, "options": [ @@ -6486,10 +6430,9 @@ "-c, --ccset Communicaton command set", "--schann Secure channel", "--aid Application ID (3 hex bytes, big endian)", - "--isoid Application ISO ID (ISO DF ID) (2 hex bytes, big endian)", - "--dfname Application ISO DF Name (5-16 hex bytes, big endian)" + "--isoid Application ISO ID (ISO DF ID) (2 hex bytes, big endian)" ], - "usage": "hf mfdes getuid [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [--dfname ]" + "usage": "hf mfdes getuid [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ]" }, "hf mfdes help": { "command": "hf mfdes help", @@ -6529,8 +6472,7 @@ "description": "Show application list. Master key needs to be provided or flag --no-auth set (depend on cards settings).", "notes": [ "hf mfdes lsapp -> show application list with defaults from `default` command", - "hf mfdes lsapp --files -> show application list and show each file type/settings/etc", - "hf mfdes lsapp --dfname D2760000850100 -> list apps after selecting DF by name" + "hf mfdes lsapp --files -> show application list and show each file type/settings/etc" ], "offline": false, "options": [ @@ -6547,46 +6489,16 @@ "--schann Secure channel", "--no-auth Execute without authentication", "--no-deep not to check authentication commands that avail for any application", - "--files scan files and print file settings", - "--dfname Application ISO DF Name (5-16 hex bytes, big endian)" + "--files scan files and print file settings" ], - "usage": "hf mfdes lsapp [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--no-auth] [--no-deep] [--files] [--dfname ]" - }, - "hf mfdes lsfile": { - "command": "hf mfdes lsfile", - "description": "This commands List files inside application AID / ISOID. Master key needs to be provided or flag --no-auth set (depend on cards settings).", - "notes": [ - "hf mfdes lsfiles --aid 123456 -> AID 123456, list files using `default` command creds", - "hf mfdes lsfiles --isoid df01 --no-auth -> list files for DESFire light", - "hf mfdes lsfiles --dfname D2760000850100 -> select DF by name and list files" - ], - "offline": false, - "options": [ - "-h, --help This help", - "-a, --apdu Show APDU requests and responses", - "-v, --verbose Verbose output", - "-n, --keyno Key number", - "-t, --algo Crypt algo", - "-k, --key Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)", - "--kdf Key Derivation Function (KDF)", - "-i, --kdfi KDF input (1-31 hex bytes)", - "-m, --cmode Communicaton mode", - "-c, --ccset Communicaton command set", - "--schann Secure channel", - "--aid Application ID (3 hex bytes, big endian)", - "--isoid Application ISO ID (ISO DF ID) (2 hex bytes, big endian)", - "--dfname Application ISO DF Name (5-16 hex bytes, big endian)", - "--no-auth Execute without authentication" - ], - "usage": "hf mfdes lsfiles [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [--dfname ] [--no-auth]" + "usage": "hf mfdes lsapp [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--no-auth] [--no-deep] [--files]" }, "hf mfdes lsfiles": { "command": "hf mfdes lsfiles", "description": "This commands List files inside application AID / ISOID. Master key needs to be provided or flag --no-auth set (depend on cards settings).", "notes": [ "hf mfdes lsfiles --aid 123456 -> AID 123456, list files using `default` command creds", - "hf mfdes lsfiles --isoid df01 --no-auth -> list files for DESFire light", - "hf mfdes lsfiles --dfname D2760000850100 -> select DF by name and list files" + "hf mfdes lsfiles --isoid df01 --no-auth -> list files for DESFire light" ], "offline": false, "options": [ @@ -6603,10 +6515,9 @@ "--schann Secure channel", "--aid Application ID (3 hex bytes, big endian)", "--isoid Application ISO ID (ISO DF ID) (2 hex bytes, big endian)", - "--dfname Application ISO DF Name (5-16 hex bytes, big endian)", "--no-auth Execute without authentication" ], - "usage": "hf mfdes lsfiles [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [--dfname ] [--no-auth]" + "usage": "hf mfdes lsfiles [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [--no-auth]" }, "hf mfdes mad": { "command": "hf mfdes mad", @@ -6783,7 +6694,7 @@ "-a, --apdu Show APDU requests and responses", "-v, --verbose Verbose output", "-n, --keyno Key number", - "-t, --algo Crypt algo (deft: 2TDEA)", + "-t, --algo Crypt algo", "-k, --key Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)", "--kdf Key Derivation Function (KDF)", "-i, --kdfi KDF input (1-31 hex bytes)", @@ -7177,13 +7088,13 @@ "description": "Tests AES key on Mifare Ultralight AES tags. If no key is specified, null key will be tried. Key index 0... DataProtKey (default) Key index 1... UIDRetrKey Key index 2... OriginalityKey", "notes": [ "hf mfu aesauth", - "hf mfu aesauth --key <16 hex bytes> --idx <0..2>" + "hf mfu aesauth --key <16 hex bytes> --index <0..2>" ], "offline": false, "options": [ "-h, --help This help", "--key AES key (16 hex bytes)", - "-i, --idx <0..2> Key index (def: 0)", + "-i, --index <0..2> Key index, default: 0", "-k Keep field on (only if a key is provided)" ], "usage": "hf mfu aesauth [-hk] [--key ] [-i <0..2>]" @@ -7487,24 +7398,21 @@ }, "hf mfu sim": { "command": "hf mfu sim", - "description": "Simulate MIFARE Ultralight family type based upon ISO/IEC 14443 type A tag with 4,7 or 10 byte UID from emulator memory. See `hf mfu eload` first. The UID from emulator memory will be used if not specified. See `hf 14a sim -h` to see available types. You want 2, 7 or 13 usually.", + "description": "Simulate MIFARE Ultralight family type based upon ISO/IEC 14443 type A tag with 4,7 or 10 byte UID from emulator memory. See `hf mfu eload` first. The UID from emulator memory will be used if not specified. See `hf 14a sim -h` to see available types. You want 2 or 7 usually.", "notes": [ "hf mfu sim -t 2 --uid 11223344556677 -> MIFARE Ultralight", "hf mfu sim -t 7 --uid 11223344556677 -n 5 -> MFU EV1 / NTAG 215 Amiibo", - "hf mfu sim -t 7 -> MFU EV1 / NTAG 215 Amiibo", - "hf mfu sim -t 13 -> MIFARE Ultralight-C" + "hf mfu sim -t 7 -> MFU EV1 / NTAG 215 Amiibo" ], "offline": false, "options": [ "-h, --help This help", - "-t, --type <1..13> Simulation type to use", + "-t, --type <1..12> Simulation type to use", "-u, --uid <4|7|10> hex bytes UID", "-n, --num Exit simulation after blocks. 0 = infinite", - "-v, --verbose Verbose output", - "--c1 UL-C Auth - all zero handshake part 1", - "--c2 UL-C Auth - all zero handshake part 2" + "-v, --verbose Verbose output" ], - "usage": "hf mfu sim [-hv] -t <1..13> [-u ] [-n ] [--c1] [--c2]" + "usage": "hf mfu sim [-hv] -t <1..12> [-u ] [-n ]" }, "hf mfu tamper": { "command": "hf mfu tamper", @@ -11731,7 +11639,7 @@ }, "lf t55xx help": { "command": "lf t55xx help", - "description": "----------- ---------------------------- notice ----------------------------- Remember to run `lf t55xx detect` first whenever a new card is placed on the Proxmark3 or the config block changed. help This help ----------- --------------------- operations --------------------- config Set/Get T55XX configuration (modulation, inverted, offset, rate) detect Try detecting the tag modulation from reading the configuration block info Show T55x7 configuration data (page 0/ blk 0) trace Show T55x7 traceability data (page 1/ blk 0-1) view Display content from tag dump file ----------- --------------------- recovery --------------------- sniff Attempt to recover T55xx commands from sample buffer --------------------------------------------------------------------------------------- lf t55xx clonehelp available offline: no Display a list of available commands for cloning specific techs on T5xx tags", + "description": "----------- ---------------------------- notice ----------------------------- Remember to run `lf t55xx detect` first whenever a new card is placed on the Proxmark3 or the config block changed. help This help ----------- --------------------- operations --------------------- config Set/Get T55XX configuration (modulation, inverted, offset, rate) detect Try detecting the tag modulation from reading the configuration block info Show T55x7 configuration data (page 0/ blk 0) trace Show T55x7 traceability data (page 1/ blk 0-1) ----------- --------------------- recovery --------------------- sniff Attempt to recover T55xx commands from sample buffer --------------------------------------------------------------------------------------- lf t55xx clonehelp available offline: no Display a list of available commands for cloning specific techs on T5xx tags", "notes": [ "lf t55xx clonehelp" ], @@ -11926,20 +11834,6 @@ ], "usage": "lf t55xx trace [-h1] [--r0] [--r1] [--r2] [--r3]" }, - "lf t55xx view": { - "command": "lf t55xx view", - "description": "Print a T55xx dump file (bin/eml/json)", - "notes": [ - "lf t55xx view -f lf-t55xx-00000000-11111111-22222222-33333333-dump.bin" - ], - "offline": true, - "options": [ - "-h, --help This help", - "-f, --file Specify a filename for dump file", - "-v, --verbose verbose output" - ], - "usage": "lf t55xx view [-hv] -f " - }, "lf t55xx wakeup": { "command": "lf t55xx wakeup", "description": "This commands sends the Answer-On-Request command and leaves the readerfield ON afterwards", @@ -12223,27 +12117,24 @@ }, "mem load": { "command": "mem load", - "description": "Loads binary file into flash memory on device Warning! - mem area to be written must have been wiped first OBS! - dictionaries are serviced as files in spiffs so no wipe is needed", + "description": "Loads binary file into flash memory on device Warning: mem area to be written must have been wiped first ( dictionaries are serviced as files in spiffs so no wipe is needed )", "notes": [ "mem load -f myfile -> upload file myfile values at default offset 0", "mem load -f myfile -o 1024 -> upload file myfile values at offset 1024", - "mem load -f mfc_default_keys -m -> upload MIFARE Classic keys", + "mem load -f mfc_default_keys -m -> upload MFC keys", "mem load -f t55xx_default_pwds -t -> upload T55XX passwords", - "mem load -f iclass_default_keys -i -> upload iCLASS keys", - "mem load -f mfulc_default_keys --ulc -> upload MIFARE UL-C keys" + "mem load -f iclass_default_keys -i -> upload iCLASS keys" ], "offline": false, "options": [ "-h, --help This help", "-o, --offset offset in memory", - "-m, --mfc upload 6 bytes keys (MIFARE Classic dictionary)", - "-i, --iclass upload 8 bytes keys (iClass dictionary)", - "-t, --t55xx upload 4 bytes keys (T55xx dictionary)", - "--ulc upload 16 bytes keys (MIFARE UL-C dictionary)", - "--aes upload 16 bytes keys (MIFARE UL-AES dictionary)", + "-m, --mifare, --mfc upload 6 bytes keys (mifare key dictionary)", + "-i, --iclass upload 8 bytes keys (iClass key dictionary)", + "-t, --t55xx upload 4 bytes keys (password dictionary)", "-f, --file file name" ], - "usage": "mem load [-hmit] [-o ] [--ulc] [--aes] -f " + "usage": "mem load [-hmit] [-o ] -f " }, "mem spiffs check": { "command": "mem spiffs check", @@ -12428,42 +12319,6 @@ ], "usage": "mem wipe [-h] [-p ]" }, - "mqtt help": { - "command": "mqtt help", - "description": "help This help send Send messages or json file over MQTT receive Receive message or json file over MQTT --------------------------------------------------------------------------------------- mqtt send available offline: yes This command send MQTT messages. You can send JSON file Default server: proxdump.com:1883 topic: proxdump", - "notes": [ - "mqtt send --msg \"Hello from Pm3\" -> sending msg to default server/port/topic", - "mqtt send -f myfile.json -> sending file to default server/port/topic", - "mqtt send --addr test.mosquitto.org -p 1883 --topic pm3 --msg \"custom mqtt server \"" - ], - "offline": true, - "options": [ - "-h, --help This help", - "--addr MQTT server address", - "-p, --port MQTT server port", - "--topic MQTT topic", - "--msg Message to send over MQTT", - "-f, --file file to send" - ], - "usage": "mqtt send [-h] [--addr ] [-p ] [--topic ] [--msg ] [-f ]" - }, - "mqtt receive": { - "command": "mqtt receive", - "description": "This command receives MQTT messages. JSON text will be saved to file if detected Default server: proxdump.com:1883 topic: proxdump", - "notes": [ - "mqtt receive -> listening to default server/port/topic", - "mqtt receive --addr test.mosquitto.org -p 1883 --topic pm3" - ], - "offline": true, - "options": [ - "-h, --help This help", - "--addr MQTT server address", - "-p, --port MQTT server port", - "--topic MQTT topic", - "-f, --file file name to use for received files" - ], - "usage": "mqtt receive [-h] [--addr ] [-p ] [--topic ] [-f ]" - }, "msleep": { "command": "msleep", "description": "Sleep for given amount of milliseconds", @@ -12894,18 +12749,6 @@ ], "usage": "prefs get hints [-h]" }, - "prefs get mqtt": { - "command": "prefs get mqtt", - "description": "Get preference of MQTT settings in the client", - "notes": [ - "prefs get mqtt" - ], - "offline": true, - "options": [ - "-h, --help This help" - ], - "usage": "prefs get mqtt [-h]" - }, "prefs get output": { "command": "prefs get output", "description": "Get preference of dump output style", @@ -13031,7 +12874,7 @@ }, "prefs set help": { "command": "prefs set help", - "description": "help This help barmode Set bar mode client.debug Set client debug level client.delay Set client execution delay client.timeout Set client communication timeout color Set color support emoji Set emoji display hints Set hint display savepaths ... to be adjusted next ... output Set dump output style plotsliders Set plot slider display mqtt Set MQTT default values --------------------------------------------------------------------------------------- prefs set barmode available offline: yes Set persistent preference of HF/LF tune command styled output in the client", + "description": "help This help barmode Set bar mode client.debug Set client debug level client.delay Set client execution delay client.timeout Set client communication timeout color Set color support emoji Set emoji display hints Set hint display savepaths ... to be adjusted next ... output Set dump output style plotsliders Set plot slider display --------------------------------------------------------------------------------------- prefs set barmode available offline: yes Set persistent preference of HF/LF tune command styled output in the client", "notes": [ "prefs set barmode --mix" ], @@ -13058,22 +12901,6 @@ ], "usage": "prefs set hints [-h] [--off] [--on]" }, - "prefs set mqtt": { - "command": "prefs set mqtt", - "description": "Set persistent preference MQTT Server in the client", - "notes": [ - "prefs set mqtt -s test.mosquito.com", - "prefs set mqtt -s test.mosquito.com -p 1883 -t proxdump" - ], - "offline": true, - "options": [ - "-h, --help This help", - "-s, --srv default MQTT Server", - "-p, --port default MQTT Port", - "-t, --topic default MQTT Topic" - ], - "usage": "prefs set mqtt [-h] [-s ] [-p ] [-t ]" - }, "prefs set output": { "command": "prefs set output", "description": "Set dump output style to condense consecutive repeated data", @@ -13536,8 +13363,8 @@ } }, "metadata": { - "commands_extracted": 780, + "commands_extracted": 768, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2025-08-20T08:39:30" + "extracted_on": "2025-06-15T10:52:29" } } diff --git a/doc/commands.md b/doc/commands.md index fbae0a050..9cdcf7a47 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -46,7 +46,6 @@ Check column "offline" for their availability. |`prefs get hints `|Y |`Get hint display preference` |`prefs get output `|Y |`Get dump output style preference` |`prefs get plotsliders `|Y |`Get plot slider display preference` -|`prefs get mqtt `|Y |`Get MQTT preference` ### prefs set @@ -66,7 +65,6 @@ Check column "offline" for their availability. |`prefs set savepaths `|Y |`... to be adjusted next ... ` |`prefs set output `|Y |`Set dump output style` |`prefs set plotsliders `|Y |`Set plot slider display` -|`prefs set mqtt `|Y |`Set MQTT default values` ### analyse @@ -333,7 +331,6 @@ Check column "offline" for their availability. |`hf felica reader `|N |`Act like an ISO18092/FeliCa reader` |`hf felica sniff `|N |`Sniff ISO 18092/FeliCa traffic` |`hf felica wrbl `|N |`write block data to an authentication-not-required Service.` -|`hf felica dump `|N |`Wait for and try dumping FeliCa` |`hf felica rqservice `|N |`verify the existence of Area and Service, and to acquire Key Version.` |`hf felica rqresponse `|N |`verify the existence of a card and its Mode.` |`hf felica scsvcode `|N |`acquire Area Code and Service Code.` @@ -343,7 +340,6 @@ Check column "offline" for their availability. |`hf felica rqspecver `|N |`acquire the version of card OS.` |`hf felica resetmode `|N |`reset Mode to Mode 0.` |`hf felica litesim `|N |`Emulating ISO/18092 FeliCa Lite tag` -|`hf felica liteauth `|N |`authenticate a card.` |`hf felica litedump `|N |`Wait for and try dumping FelicaLite` @@ -672,7 +668,6 @@ Check column "offline" for their availability. |`hf mfdes getkeyversions`|N |`Get Key Versions` |`hf mfdes getfileids `|N |`Get File IDs list` |`hf mfdes getfileisoids `|N |`Get File ISO IDs list` -|`hf mfdes lsfile `|N |`Show all files list` |`hf mfdes lsfiles `|N |`Show all files list` |`hf mfdes dump `|N |`Dump all files` |`hf mfdes createfile `|N |`Create Standard/Backup File` @@ -1347,7 +1342,6 @@ Check column "offline" for their availability. |`lf t55xx restore `|N |`Restore T55xx card Page 0 / Page 1 blocks` |`lf t55xx trace `|Y |`Show T55x7 traceability data (page 1/ blk 0-1)` |`lf t55xx wakeup `|N |`Send AOR wakeup command` -|`lf t55xx view `|Y |`Display content from tag dump file` |`lf t55xx write `|N |`Write T55xx block data` |`lf t55xx bruteforce `|N |`Simple bruteforce attack to find password` |`lf t55xx chk `|N |`Check passwords` @@ -1420,17 +1414,6 @@ Check column "offline" for their availability. |`mem spiffs wipe `|N |`Wipe all files from SPIFFS file system * dangerous *` -### mqtt - - { MQTT commmands... } - -|command |offline |description -|------- |------- |----------- -|`mqtt help `|Y |`This help` -|`mqtt send `|Y |`Send messages or json file over MQTT` -|`mqtt receive `|Y |`Receive message or json file over MQTT` - - ### nfc { NFC commands... } diff --git a/doc/desfire.md b/doc/desfire.md index 65f1af748..50bddc9d5 100644 --- a/doc/desfire.md +++ b/doc/desfire.md @@ -23,7 +23,6 @@ - [How to create files](#how-to-create-files) - [How to delete files](#how-to-delete-files) - [How to read/write files](#how-to-readwrite-files) - - [How to work with value files](#how-to-work-with-value-files) - [How to work with transaction mac](#how-to-work-with-transaction-mac) - [How to switch DESFire Light to LRP mode](#how-to-switch-desfire-light-to-lrp-mode) @@ -255,7 +254,7 @@ Create standard file with mac access mode and specified access settings. access `hf mfdes createfile --aid 123456 --fid 01 --isofid 0001 --size 000010 --amode mac --rrights free --wrights free --rwrights free --chrights key0` -`hf mfdes createvaluefile --aid 123456 --fid 01 --isofid 0001 --lower 00000010 --upper 00010000 --value 00000100` - create value file (see [How to work with value files](#how-to-work-with-value-files) for detailed examples) +`hf mfdes createvaluefile --aid 123456 --fid 01 --isofid 0001 --lower 00000010 --upper 00010000 --value 00000100` - create value file `hf mfdes createrecordfile --aid 123456 --fid 01 --isofid 0001 --size 000010 --maxrecord 000010` - create linear record file @@ -295,11 +294,9 @@ Here it is needed to specify the type of the file because there is no `hf mfdes `hf mfdes write --aid 123456 --fid 01 --type data -d 01020304 --commit` - write backup data file and commit -`hf mfdes write --aid 123456 --fid 01 --type value -d 00000001` increment value file (deprecated, use `hf mfdes value` command) +`hf mfdes write --aid 123456 --fid 01 --type value -d 00000001` increment value file -`hf mfdes write --aid 123456 --fid 01 --type value -d 00000001 --debit` decrement value file (deprecated, use `hf mfdes value` command) - -For modern value file operations, see [How to work with value files](#how-to-work-with-value-files) +`hf mfdes write --aid 123456 --fid 01 --type value -d 00000001 --debit` decrement value file `hf mfdes write --aid 123456 --fid 01 --type record -d 01020304` write data to a record file @@ -317,188 +314,6 @@ For more detailed samples look at the next howto. `hf mfdes write --aid 123456 --fid 01 -d 01020304 --readerid 010203` write data to the file with CommitReaderID command before and CommitTransaction after write -### How to work with value files -^[Top](#top) - -Value files are specialized files designed for storing and manipulating monetary values or counters. They provide atomic operations for incrementing (credit) and decrementing (debit) values with built-in limits and security features. - -**Key Features:** -- 32-bit value storage (represented internally as unsigned) -- Lower and upper limits to prevent underflow/overflow -- Atomic operations with automatic transaction commit -- Transaction logging support -- Secure communication modes (plain, MAC, encrypted) - -**Value File Structure:** -- Current value: 32-bit value -- Lower limit: minimum allowed value (prevents underflow) -- Upper limit: maximum allowed value (prevents overflow) - -**Access Rights:** -Value files use four access right categories: -- **Read**: Required to get the current value (`hf mfdes value --op get`) -- **Write**: Required for debit operations (`hf mfdes value --op debit`) -- **Read/Write**: Required for credit operations (`hf mfdes value --op credit`) -- **Change**: Required to modify file settings or delete the file - -Access rights can be set to: -- `key0` through `keyE`: Requires authentication with the specified key -- `free`: No authentication required -- `deny`: Operation is forbidden - -*Create value file:* - -Creating a Bitcoin wallet on your DESFire card: -``` -pm3 --> hf mfdes createapp --aid 425443 --ks1 0B --ks2 0E -[+] Desfire application 425443 successfully created - -pm3 --> hf mfdes createvaluefile --aid 425443 --fid 01 --lower 00000000 --upper 01406F40 --value 00000032 -[=] ---- Create file settings ---- -[+] File type : Value -[+] File number : 0x01 (1) -[+] File comm mode : Plain -[+] Additional access: No -[+] Access rights : EEEE -[+] read......... free -[+] write........ free -[+] read/write... free -[+] change....... free -[=] Lower limit... 0 / 0x00000000 -[=] Upper limit... 21000000 / 0x01406F40 -[=] Value............ 50 / 0x00000032 -[=] Limited credit... 0 - disabled -[=] GetValue access... Not Free -[+] Value file 01 in the app 425443 created successfully -``` -This creates a DESFire Bitcoin wallet with: -- Application ID 0x425443 (ASCII "BTC") -- File ID 0x01 for the wallet -- Lower limit: 0 BTC (no overdrafts in crypto) -- Upper limit: 21,000,000 BTC (respecting Satoshi's vision) -- Initial value: 50 BTC (the original block reward) - -Creating the infamous Pizza Day wallet: -``` -pm3 --> hf mfdes createvaluefile --aid 425443 --fid 02 --lower 00000000 --upper 01406F40 --value 00002710 -[=] ---- Create file settings ---- -[+] File type : Value -[+] File number : 0x02 (2) -[+] File comm mode : Plain -[+] Additional access: No -[+] Access rights : EEEE -[+] read......... free -[+] write........ free -[+] read/write... free -[+] change....... free -[=] Lower limit... 0 / 0x00000000 -[=] Upper limit... 21000000 / 0x01406F40 -[=] Value............ 10000 / 0x00002710 -[=] Limited credit... 0 - disabled -[=] GetValue access... Not Free -[+] Value file 02 in the app 425443 created successfully -``` -This creates a wallet pre-loaded with 10,000 BTC (historical exchange rate: 2 pizzas) - -*Value file operations:* - -Check your Bitcoin balance: -``` -pm3 --> hf mfdes value --aid 425443 --fid 01 --op get -[+] Value: 50 (0x00000032) - -pm3 --> hf mfdes value --aid 425443 --fid 01 --op get -m mac -[+] Value: 50 (0x00000032) -``` - -Loading Bitcoin IOUs onto your card: -``` -pm3 --> hf mfdes value --aid 425443 --fid 01 --op credit -d 00000019 -[+] Value changed successfully - -pm3 --> hf mfdes value --aid 425443 --fid 01 --op get -[+] Value: 75 (0x0000004b) -``` -Card now holds 75 BTC in IOUs ($9,000,000 in debt obligations) - -Buying coffee with Bitcoin IOUs: -``` -pm3 --> hf mfdes value --aid 425443 --fid 01 --op debit -d 00000001 -[+] Value changed successfully # You now owe the coffee shop $120,000 - -pm3 --> hf mfdes value --aid 425443 --fid 01 --op get -[+] Value: 74 (0x0000004a) # Remaining debt capacity -``` - -The legendary Pizza Day recreation: -``` -pm3 --> hf mfdes value --aid 425443 --fid 02 --op debit -d 00002710 -[+] Value changed successfully # You now owe Papa John's $1.2 billion - -pm3 --> hf mfdes value --aid 425443 --fid 02 --op get -[+] Value: 0 (0x00000000) # Card empty, bankruptcy imminent -``` - -*Communication modes:* - -Value files support different communication modes for security: - -Plain mode (no encryption): -``` -pm3 --> hf mfdes value --aid 123456 --fid 02 --op get -m plain -[+] Value: 125 (0x0000007d) -``` - -MAC mode (message authentication): -``` -pm3 --> hf mfdes value --aid 123456 --fid 02 --op credit -d 00000032 -m mac -[+] Value changed successfully -``` - -Encrypted mode (full encryption): -``` -pm3 --> hf mfdes value --aid 123456 --fid 02 --op debit -d 00000014 -m encrypted -[+] Value changed successfully -``` - -*Error handling and compatibility:* - -The Proxmark3 implementation includes automatic fallback for compatibility: -- If MAC mode fails with a length error (-20), it automatically retries in plain mode -- This ensures compatibility across different DESFire card generations -- Original communication mode is restored after fallback - -*Transaction behavior:* - -Value operations are atomic with automatic commit: -- The `hf mfdes value` command automatically issues CommitTransaction after credit/debit operations -- Get operations do not require a commit -- Operations either complete fully (including commit) or fail completely -- No manual transaction management required when using the `hf mfdes value` command -- Transaction MAC files can log all value operations for audit trails - -*Practical examples:* - -Daily Bitcoin IOU catastrophes: -``` -# Check morning IOU balance -pm3 --> hf mfdes value --aid 425443 --fid 01 --op get -[+] Value: 50 (0x00000032) # $6 million in IOUs - -# Friend sends you more IOUs via NFC bump -pm3 --> hf mfdes value --aid 425443 --fid 01 --op credit -d 000000C8 -[+] Value changed successfully # +200 BTC IOUs ($24M more debt) - -# Buy a Tesla (tap payment) -pm3 --> hf mfdes value --aid 425443 --fid 01 --op debit -d 00000001 -[+] Value changed successfully - -# Check remaining IOU capacity -pm3 --> hf mfdes value --aid 425443 --fid 01 --op get -[+] Value: 273 (0x00000111) # $32.76M in transferable debt -``` - - ### How to work with transaction mac ^[Top](#top) diff --git a/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md b/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md index 2a6611659..5c9149826 100644 --- a/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md +++ b/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md @@ -47,21 +47,12 @@ On Archlinux: sudo pacman -R modemmanager ``` -# Solution 2: mask ModemManager +# Solution 2: disable ModemManager ^[Top](#top) ```sh sudo systemctl stop ModemManager sudo systemctl disable ModemManager -sudo systemctl mask ModemManager -``` -After doing this check if it has been masked with: -`systemctl status ModemManager` -If you'll get something like this, you've masked ModemManager and you will be ready to install and setup your pm3. -``` -○ ModemManager.service - Loaded: masked (Reason: Unit ModemManager.service is masked.) - Active: inactive (dead) ``` # Solution 3: use filtering udev rules 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 55ca51687..cb1fc583e 100644 --- a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md +++ b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md @@ -66,7 +66,7 @@ Here are the supported values you can assign to `PLATFORM` in `Makefile.platform | PM3RDV4 (def) | Proxmark3 RDV4 | | PM3GENERIC | Proxmark3 generic target | | PM3ICOPYX | iCopy-X with XC3S100E | -| PM3ULTIMATE | Proxmark3 Ultimate with XC2S50 | +| PM3ULTIMATE | Proxmar3 Ultimate with XC2S50 | By default `PLATFORM=PM3RDV4`. diff --git a/doc/unofficial_desfire_bible.md b/doc/unofficial_desfire_bible.md deleted file mode 100644 index 104f64fcc..000000000 --- a/doc/unofficial_desfire_bible.md +++ /dev/null @@ -1,1008 +0,0 @@ -# The Unofficial DESFire Bible -## A Comprehensive Technical Reference with Citations - -### Table of Contents -1. [Introduction](#introduction) -2. [DESFire Evolution Timeline](#desfire-evolution-timeline) -3. [Version Comparison Table](#version-comparison-table) -4. [Memory Architecture](#memory-architecture) -5. [Security Features by Version](#security-features-by-version) -6. [Complete Command Reference](#complete-command-reference) -7. [Authentication Deep Dive](#authentication-deep-dive) -8. [File Types and Operations](#file-types-and-operations) -9. [Cryptographic Implementation](#cryptographic-implementation) -10. [Communication Modes](#communication-modes) -11. [Error Codes Reference](#error-codes-reference) -12. [Implementation Examples](#implementation-examples) -13. [Bibliography](#bibliography) - ---- - -## Introduction - -MIFARE DESFire is a family of contactless smart card ICs (Integrated Circuits) compliant with ISO/IEC 14443-4 Type A. This comprehensive reference documents all DESFire versions from Classic (D40) through EV3, including the cost-optimized Light variant. Every technical detail includes inline citations to ensure accuracy and traceability. - -### Document Scope -This bible covers: -- All DESFire versions: Classic/EV0, EV1, EV2, EV3, and Light -- Complete command sets with hex codes and parameters -- Authentication protocols and cryptographic implementations -- Memory organization and file structures -- Security features and attack mitigations -- Real-world implementation examples - ---- - -## DESFire Evolution Timeline - -### DESFire Classic/EV0 (D40) - Original Release -- **Release**: Early 2000s -- **Memory**: Fixed 4KB EEPROM [Source: MF3D_H_X3_SDS.pdf] -- **Applications**: Maximum 28 applications [Source: MF3D_H_X3_SDS.pdf] -- **Files per App**: Up to 16 files [Source: AN11004.pdf] -- **Encryption**: DES and 3DES only [Source: MF3D_H_X3_SDS.pdf] -- **Communication Speed**: 106 kbps [Source: AN11004.pdf] -- **Key Features**: - - Basic file types: Standard, Backup, Value, Cyclic Record - - Simple authentication protocol - - No advanced security features - -### DESFire EV1 - First Evolution (2006) -- **Memory Options**: 2KB, 4KB, 8KB EEPROM [Source: AN11004.pdf] -- **Applications**: Still limited to 28 [Source: MF3D_H_X3_SDS.pdf] -- **Files per App**: Increased to 32 [Source: AN11004.pdf] -- **New Cryptography**: Added AES-128 support [Source: AN11004.pdf] -- **Communication Speed**: Up to 848 kbps [Source: AN11004.pdf] -- **New Features** [Source: AN11004.pdf]: - - ISO/IEC 7816-4 APDU wrapping support - - Random UID option for privacy - - GetCardUID command - - ISO file identifiers (2 bytes) - - Transaction backup mechanism - - Improved key management - -### DESFire EV2 - Second Generation (2016) -- **Memory Options**: 2KB, 4KB, 8KB EEPROM [Source: AN12696.pdf] -- **Applications**: Unlimited (removed 28 app limit) [Source: MF3D_H_X3_SDS.pdf] -- **Communication Improvements**: 128-byte frame size (2x EV1) [Source: AN12696.pdf] -- **Major New Features**: - - **Virtual Card Architecture (VCA)** [Source: AN12696.pdf]: Privacy-preserving multiple card emulation - - **Transaction MAC (TMAC)** [Source: AN12696.pdf]: Offline transaction verification - - **Proximity Check** [Source: AN12696.pdf]: Protection against relay attacks - - **Delegated Application Management (DAM)** [Source: AN12696.pdf]: Secure cloud provisioning - - **Multiple Key Sets** [Source: AN12696.pdf]: Key rolling mechanism - - **Originality Check** [Source: AN12696.pdf]: Verify genuine NXP silicon - -### DESFire EV3 - Latest Generation (2020) -- **Memory Options**: 2KB, 4KB, 8KB, 16KB EEPROM [Source: MF3D_H_X3_SDS.pdf] -- **Performance**: 1.6x faster than EV1 [Source: AN12753.pdf] -- **Communication**: 256-byte frame size (2x EV2) [Source: AN12753.pdf] -- **Security Certification**: Common Criteria EAL5+ [Source: plt-05618-a.0-mifare-desfire-ev3-application-note.pdf] -- **New Features**: - - **Transaction Timer** [Source: AN12753.pdf]: Prevents delayed attack scenarios - - **Secure Dynamic Messaging (SDM)** [Source: AN12753.pdf]: Dynamic URL generation - - **Secure Unique NFC (SUN)** [Source: AN12753.pdf]: Unique tap verification - - **Pre-configured DAM Keys** [Source: AN12753.pdf]: Simplified cloud setup - - **Improved MACing** [Source: AN12753.pdf]: Enhanced integrity protection - -### DESFire Light - Cost-Optimized Variant -- **Memory Options**: 0.5KB (640B) or 2KB [Source: [0011955][v1.0] st_pegasus_desfire_lite_v10.pdf] -- **Applications**: Single application only [Source: [0011955][v1.0] st_pegasus_desfire_lite_v10.pdf] -- **Files**: Up to 32 files [Source: [0011955][v1.0] st_pegasus_desfire_lite_v10.pdf] -- **Cryptography**: AES-128 only (no DES/3DES) [Source: [0011955][v1.0] st_pegasus_desfire_lite_v10.pdf] -- **Limitations**: - - No backup files support - - Simplified command set - - No multi-application features - - Reduced security options - ---- - -## Version Comparison Table - -| Feature | Classic/EV0 | EV1 | EV2 | EV3 | Light | -|---------|-------------|-----|-----|-----|-------| -| **Memory Options** | 4KB | 2/4/8KB | 2/4/8KB | 2/4/8/16KB | 0.5/2KB | -| **Max Applications** | 28 [^1] | 28 [^1] | Unlimited [^2] | Unlimited [^2] | 1 [^3] | -| **Files per App** | 16 [^4] | 32 [^4] | 32 [^5] | 32 [^5] | 32 [^3] | -| **Frame Size** | 64B | 64B | 128B [^5] | 256B [^6] | 64B | -| **DES/3DES** | ✓ | ✓ | ✓ | ✓ | ✗ | -| **AES-128** | ✗ | ✓ [^4] | ✓ | ✓ | ✓ [^3] | -| **Random UID** | ✗ | ✓ [^4] | ✓ | ✓ | ✗ | -| **VCA** | ✗ | ✗ | ✓ [^5] | ✓ | ✗ | -| **Proximity Check** | ✗ | ✗ | ✓ [^5] | ✓ | ✗ | -| **Transaction MAC** | ✗ | ✗ | ✓ [^5] | ✓ | Limited | -| **Transaction Timer** | ✗ | ✗ | ✗ | ✓ [^6] | ✗ | -| **SDM/SUN** | ✗ | ✗ | ✗ | ✓ [^6] | ✗ | -| **Speed** | 106 kbps | 848 kbps [^4] | 848 kbps | 1.6x EV1 [^6] | 106 kbps | -| **CC Certification** | ✗ | EAL4+ | EAL5+ | EAL5+ [^7] | EAL4+ | - -[^1]: [Source: MF3D_H_X3_SDS.pdf] -[^2]: [Source: MF3D_H_X3_SDS.pdf] -[^3]: [Source: [0011955][v1.0] st_pegasus_desfire_lite_v10.pdf] -[^4]: [Source: AN11004.pdf] -[^5]: [Source: AN12696.pdf] -[^6]: [Source: AN12753.pdf] -[^7]: [Source: plt-05618-a.0-mifare-desfire-ev3-application-note.pdf] - ---- - -## Memory Architecture - -### Memory Layout Structure - -All DESFire cards follow a hierarchical structure: - -``` -PICC (Card) Level -├── Master Application (AID 0x000000) -│ ├── PICC Master Key -│ └── Card Configuration -└── Applications (AID 0x000001 - 0xFFFFFF) - ├── Application Master Key - ├── Application Keys (0-13) - └── Files (0-31) - ├── Standard Data Files - ├── Backup Files - ├── Value Files - ├── Linear Record Files - └── Cyclic Record Files -``` - -### Application Identifier (AID) -- **Size**: 3 bytes (24 bits) [Source: AN11004.pdf] -- **Range**: 0x000000 to 0xFFFFFF -- **Reserved**: 0x000000 (Master Application) -- **User Range**: 0x000001 to 0xFFFFFF - -### File Types and Structures - -#### 1. Standard Data File -- **Purpose**: Store raw data [Source: AN11004.pdf] -- **Size**: 1 to 8191 bytes (EV1), 1 to 32 bytes (Light) [Source: various] -- **Operations**: Read, Write -- **Structure**: Simple byte array - -#### 2. Backup File -- **Purpose**: Transactional data with commit/abort [Source: AN11004.pdf] -- **Size**: Same as Standard File -- **Operations**: Read, Write, Commit, Abort -- **Note**: Not supported on DESFire Light [Source: [0011955][v1.0] st_pegasus_desfire_lite_v10.pdf] - -#### 3. Value File -- **Purpose**: Store 32-bit signed integer [Source: AN11004.pdf] -- **Operations**: Read, Credit, Debit, Limited Credit -- **Limits**: Configurable lower and upper bounds -- **Structure**: - ``` - Value: 4 bytes (signed int32) - ``` - -#### 4. Linear Record File -- **Purpose**: Append-only records [Source: AN11004.pdf] -- **Record Size**: 1 to 8191 bytes -- **Max Records**: Configurable -- **Operations**: Read, Write (append), Clear - -#### 5. Cyclic Record File -- **Purpose**: Circular buffer of records [Source: AN11004.pdf] -- **Behavior**: Oldest record overwritten when full -- **Operations**: Read, Write (newest), Clear - -### Memory Access Rights - -Each file has configurable access rights [Source: AN11004.pdf]: -- **Read Access**: Key 0-13, 0xE (free), 0xF (deny) -- **Write Access**: Key 0-13, 0xE (free), 0xF (deny) -- **Read&Write Access**: Key 0-13, 0xE (free), 0xF (deny) -- **Change Access Rights**: Key 0-13, 0xF (deny) - -Communication settings per file: -- **0x00**: Plain communication -- **0x01**: MACed communication -- **0x03**: Fully enciphered communication - ---- - -## Security Features by Version - -### DESFire Classic/EV0 Security -- **Encryption**: DES/3DES only [Source: MF3D_H_X3_SDS.pdf] -- **Authentication**: Simple challenge-response -- **Protection**: Basic anti-collision, no advanced features - -### DESFire EV1 Security Enhancements -- **AES-128 Support**: Added alongside DES/3DES [Source: AN11004.pdf] -- **Random UID**: Configurable for privacy [Source: AN11004.pdf] -- **Diversified Keys**: Support for key derivation -- **Anti-tearing**: Transaction backup mechanism - -### DESFire EV2 Security Additions -- **Proximity Check** [Source: AN12696.pdf]: - - Prevents relay attacks - - Time-based distance bounding - - Configurable timing parameters - -- **Virtual Card Architecture (VCA)** [Source: AN12696.pdf]: - - Multiple virtual cards in one - - Install/Select/Delete virtual cards - - Privacy through UID randomization - -- **Transaction MAC (TMAC)** [Source: AN12696.pdf, MF2DLHX0.pdf]: - - Offline transaction verification - - Reader-specific MACs with CommitReaderID command (0xC8) - - Counter-based freshness (TMC - Transaction MAC Counter) - - Special file type 0x05 with unique access rights: - - Read: Normal access control - - Write: Always 0xF (disabled) - - ReadWrite: CommitReaderID key (0x0-0xE enabled, 0xF disabled) - - Change: Normal access control - - TMV (Transaction MAC Value) calculated on CommitTransaction - -- **Secure Messaging v2** [Source: AN12696.pdf]: - - Improved IV generation - - Command counter protection - - Enhanced session key derivation - -### DESFire EV3 Security Features -- **Transaction Timer** [Source: AN12753.pdf]: - - Maximum time window for operations - - Prevents delayed attack scenarios - - Configurable per application - -- **Secure Dynamic Messaging (SDM)** [Source: AN12753.pdf]: - - Dynamic NDEF message generation - - Encrypted file data in URLs - - PICCData and MACed responses - -- **Common Criteria EAL5+** [Source: plt-05618-a.0-mifare-desfire-ev3-application-note.pdf]: - - Highest security certification - - Formally verified implementation - - Hardware security evaluation - ---- - -## Complete Command Reference - -### Authentication Commands - -#### 0x0A - Authenticate (Legacy DES/3DES) -- **Parameters**: KeyNo (1 byte) [Source: protocols.h, line 334] -- **Response**: Encrypted RndB (8 bytes) + status -- **Versions**: All except Light -- **Flow**: See Authentication Deep Dive section - -#### 0x1A - Authenticate ISO (3DES) -- **Parameters**: KeyNo (1 byte) [Source: protocols.h, line 335] -- **Response**: Encrypted RndB (8 bytes) + status -- **Versions**: EV1, EV2, EV3 -- **Note**: ISO/IEC 7816-4 compliant - -#### 0xAA - Authenticate AES -- **Parameters**: KeyNo (1 byte) [Source: protocols.h, line 336] -- **Response**: Encrypted RndB (16 bytes) + status -- **Versions**: EV1, EV2, EV3, Light -- **Note**: Uses AES-128 in CBC mode - -#### 0x71 - AuthenticateEV2First -- **Parameters**: KeyNo (1 byte) + Capabilities [Source: protocols.h, line 337] -- **Response**: Transaction identifier + encrypted data -- **Versions**: EV2, EV3 -- **Purpose**: Initial EV2 authentication with capability exchange - -#### 0x77 - AuthenticateEV2NonFirst -- **Parameters**: KeyNo (1 byte) [Source: protocols.h, line 338] -- **Response**: Encrypted authentication data -- **Versions**: EV2, EV3 -- **Purpose**: Subsequent EV2 authentication - -#### 0x70 - FreeMem -- **Parameters**: None [Source: protocols.h, line 339] -- **Response**: Free memory (3 bytes) -- **Versions**: All -- **Authentication**: Not required - -### Application Management Commands - -#### 0xCA - CreateApplication -- **Parameters**: [Source: protocols.h, line 344] - - AID (3 bytes) - - KeySettings (1 byte) - - NumOfKeys (1 byte): Lower nibble = key count, Upper nibble = crypto method -- **Versions**: All -- **Example**: `CA 01 00 00 0F 81` creates AID 0x000001 with 1 AES key - -#### 0xDA - DeleteApplication -- **Parameters**: AID (3 bytes) [Source: protocols.h, line 345] -- **Versions**: All -- **Authentication**: PICC Master Key required - -#### 0x5A - SelectApplication -- **Parameters**: AID (3 bytes) [Source: protocols.h, line 347] -- **Versions**: All -- **Note**: AID 0x000000 selects master application - -#### 0x6A - GetApplicationIDs -- **Parameters**: None [Source: protocols.h, line 346] -- **Response**: List of AIDs (3 bytes each) -- **Versions**: All - -#### 0x45 - GetKeySettings -- **Parameters**: None [Source: protocols.h, line 350] -- **Response**: KeySettings (1 byte) + NumOfKeys (1 byte) -- **Versions**: All - -#### 0x64 - GetKeyVersion -- **Parameters**: KeyNo (1 byte) [Source: protocols.h, line 355] -- **Response**: Key version (1 byte) -- **Versions**: All - -### File Management Commands - -#### 0xCD - CreateStdDataFile -- **Parameters**: [Source: protocols.h, line 357] - - FileNo (1 byte) - - FileOption/CommSettings (1 byte) - - AccessRights (2 bytes) - - FileSize (3 bytes, LSB first) -- **Versions**: All - -#### 0xCB - CreateBackupFile -- **Parameters**: Same as CreateStdDataFile [Source: protocols.h, line 358] -- **Versions**: All except Light -- **Note**: Supports transaction mechanism - -#### 0xCC - CreateValueFile -- **Parameters**: [Source: protocols.h, line 359] - - FileNo (1 byte) - - CommSettings (1 byte) - - AccessRights (2 bytes) - - LowerLimit (4 bytes) - - UpperLimit (4 bytes) - - Value (4 bytes) - - LimitedCreditEnable (1 byte) -- **Versions**: All - -#### 0xC1 - CreateLinearRecordFile -- **Parameters**: [Source: protocols.h, line 360] - - FileNo (1 byte) - - CommSettings (1 byte) - - AccessRights (2 bytes) - - RecordSize (3 bytes) - - MaxNumberOfRecords (3 bytes) -- **Versions**: All - -#### 0xC0 - CreateCyclicRecordFile -- **Parameters**: Same as CreateLinearRecordFile [Source: protocols.h, line 361] -- **Versions**: All - -#### 0xDF - DeleteFile -- **Parameters**: FileNo (1 byte) [Source: protocols.h, line 362] -- **Versions**: All - -#### 0x6F - GetFileIDs -- **Parameters**: None [Source: protocols.h, line 363] -- **Response**: List of FileIDs (1 byte each) -- **Versions**: All - -#### 0xF5 - GetFileSettings -- **Parameters**: FileNo (1 byte) [Source: protocols.h, line 364] -- **Response**: File type + settings structure -- **Versions**: All - -### Data Manipulation Commands - -#### 0xBD - ReadData -- **Parameters**: [Source: protocols.h, line 367] - - FileNo (1 byte) - - Offset (3 bytes, LSB first) - - Length (3 bytes, LSB first) -- **Response**: Data + status -- **Versions**: All - -#### 0x3D - WriteData -- **Parameters**: [Source: protocols.h, line 368] - - FileNo (1 byte) - - Offset (3 bytes) - - Length (3 bytes) - - Data (variable) -- **Versions**: All - -#### 0x6C - GetValue -- **Parameters**: FileNo (1 byte) [Source: protocols.h, line 369] -- **Response**: Value (4 bytes) -- **Versions**: All - -#### 0x0C - Credit -- **Parameters**: [Source: protocols.h, line 370] - - FileNo (1 byte) - - Amount (4 bytes) -- **Versions**: All - -#### 0xDC - Debit -- **Parameters**: Same as Credit [Source: protocols.h, line 371] -- **Versions**: All - -#### 0x1C - LimitedCredit -- **Parameters**: Same as Credit [Source: protocols.h, line 372] -- **Versions**: All -- **Note**: Only if LimitedCreditEnabled - -#### 0x3B - WriteRecord -- **Parameters**: [Source: protocols.h, line 373] - - FileNo (1 byte) - - Offset (3 bytes) - - Length (3 bytes) - - Data (variable) -- **Versions**: All - -#### 0xBB - ReadRecords -- **Parameters**: [Source: protocols.h, line 374] - - FileNo (1 byte) - - Offset (3 bytes): Record number - - Length (3 bytes): Number of records -- **Versions**: All - -#### 0xEB - ClearRecordFile -- **Parameters**: FileNo (1 byte) [Source: protocols.h, line 375] -- **Versions**: All - -#### 0xC7 - CommitTransaction -- **Parameters**: Option byte (optional, 1 byte) [Source: MF2DLHX0.pdf, AN12343.pdf] -- **Versions**: All -- **Purpose**: Commit all pending changes -- **Note**: With option 0x01, returns TMC and TMV for TMAC verification - -#### 0xC8 - CommitReaderID -- **Parameters**: ReaderID (16 bytes) [Source: MF2DLHX0.pdf, Section 10.3] -- **Versions**: EV2, EV3, Light -- **Purpose**: Set reader-specific identifier for Transaction MAC generation -- **Authentication**: Depends on TMAC file ReadWrite access rights: - - 0x0-0x4: Authentication with specified key required - - 0xE: Free access allowed - - 0xF: CommitReaderID disabled -- **Communication**: Requires MACed or Encrypted mode -- **Response**: - - When authenticated: EncTMRI (16 bytes) = E_TM(SesTMENCKey, TMRIPrev) - - When not authenticated: No data, only status code -- **Notes**: - - EncTMRI uses AES CBC with zero IV for encryption - - TMRIPrev tracks previous transaction's ReaderID for chain verification - - TMRIPrev only updated on CommitTransaction if authenticated - - Used with TMAC file type (0x05) for offline transaction verification - -#### 0xA7 - AbortTransaction -- **Parameters**: None [Source: protocols.h, line 377] -- **Versions**: All -- **Purpose**: Rollback pending changes - -### Configuration Commands - -#### 0x5F - ChangeFileSettings -- **Parameters**: [Source: protocols.h, line 365] - - FileNo (1 byte) - - CommSettings (1 byte) - - AccessRights (2 bytes) -- **Versions**: All - -#### 0x54 - ChangeKeySettings -- **Parameters**: KeySettings (1 byte) [Source: protocols.h, line 351] -- **Versions**: All - -#### 0xC4 - ChangeKey -- **Parameters**: [Source: protocols.h, line 352] - - KeyNo (1 byte) - - New key data (encrypted) -- **Versions**: All - -### Information Commands - -#### 0x60 - GetVersion -- **Parameters**: None [Source: protocols.h, line 349] -- **Response**: Version info structure (28 bytes) -- **Versions**: All - -#### 0x51 - GetCardUID -- **Parameters**: None [Source: protocols.h, line 389] -- **Response**: UID (7 bytes) -- **Versions**: EV1+ -- **Authentication**: Required - -#### 0x61 - GetFileCounters -- **Parameters**: FileNo (1 byte) [Source: protocols.h, line 390] -- **Response**: Counters for SDM -- **Versions**: EV2+ - -#### 0x6E - GetFreeMemory -- **Parameters**: None [Source: AN11004.pdf] -- **Response**: Free memory (3 bytes) -- **Versions**: All - -### ISO Wrapped Commands - -#### 0xAD - ISOReadBinary -- **Parameters**: ISO 7816-4 wrapped ReadData [Source: protocols.h, line 378] -- **Versions**: EV1+ - -#### 0xAB - ISOAppendRecord -- **Parameters**: ISO 7816-4 wrapped WriteRecord [Source: protocols.h, line 380] -- **Versions**: EV1+ - -#### 0xA2 - ISOReadRecords -- **Parameters**: ISO 7816-4 wrapped ReadRecords [Source: protocols.h, line 379] -- **Versions**: EV1+ - -#### 0xA0 - ISOSelectFile -- **Parameters**: ISO 7816-4 file selection [Source: protocols.h, line 382] -- **Versions**: EV1+ - -#### 0x3A - ISOUpdateBinary -- **Parameters**: ISO 7816-4 wrapped WriteData [Source: protocols.h, line 383] -- **Versions**: EV1+ - -### Special Commands - -#### 0xAF - Additional Frame -- **Purpose**: Continue previous command [Source: protocols.h, line 342] -- **Parameters**: Additional data -- **Versions**: All - -#### 0x00 - ISO Wrapping -- **Purpose**: ISO 7816-4 command wrapping [Source: protocols.h, line 341] -- **Versions**: EV1+ - -### Transaction/Security Commands (EV2/EV3) - -#### 0xC9 - InitializeKeySet -- **Parameters**: KeySetNo + KeySetSettings [Source: protocols.h, line 385] -- **Versions**: EV2+ - -#### 0xCE - FinalizeKeySet -- **Parameters**: KeySetNo + KeyVersion [Source: protocols.h, line 386] -- **Versions**: EV2+ - -#### 0xCF - RollKeySet -- **Parameters**: KeySetNo [Source: protocols.h, line 387] -- **Versions**: EV2+ - -#### 0xF6 - GetDelegatedInfo -- **Parameters**: DAMSlotNo [Source: protocols.h, line 391] -- **Versions**: EV2+ - -#### 0xFA - TransactionMAC -- **Parameters**: Transaction data [Source: various sources] -- **Versions**: EV2+ -- **Purpose**: Generate offline verification MAC - -### Status Codes - -#### Success Codes -- **0x00**: OPERATION_OK [Source: protocols.h, line 393] -- **0x0C**: NO_CHANGES [Source: protocols.h, line 394] - -#### Error Codes -- **0x0E**: OUT_OF_MEMORY [Source: protocols.h, line 395] -- **0x1C**: ILLEGAL_COMMAND_CODE [Source: protocols.h, line 396] -- **0x1E**: INTEGRITY_ERROR [Source: protocols.h, line 397] -- **0x40**: NO_SUCH_KEY [Source: protocols.h, line 398] -- **0x7E**: LENGTH_ERROR [Source: protocols.h, line 399] -- **0x9D**: PERMISSION_DENIED [Source: protocols.h, line 400] -- **0x9E**: PARAMETER_ERROR [Source: protocols.h, line 401] -- **0xA0**: APPLICATION_NOT_FOUND [Source: protocols.h, line 402] -- **0xA1**: APPL_INTEGRITY_ERROR [Source: protocols.h, line 403] -- **0xAE**: AUTHENTICATION_ERROR [Source: protocols.h, line 404] -- **0xAF**: ADDITIONAL_FRAME [Source: protocols.h, line 405] -- **0xBE**: BOUNDARY_ERROR [Source: protocols.h, line 406] -- **0xC1**: COMMAND_ABORTED [Source: protocols.h, line 408] -- **0xCA**: PICC_INTEGRITY_ERROR [Source: protocols.h, line 407] -- **0xCD**: PICC_DISABLED_ERROR [Source: protocols.h, line 409] -- **0xCE**: COUNT_ERROR [Source: protocols.h, line 410] -- **0xDE**: DUPLICATE_ERROR [Source: protocols.h, line 411] -- **0xEE**: EEPROM_ERROR [Source: protocols.h, line 412] -- **0xF0**: FILE_NOT_FOUND [Source: protocols.h, line 413] -- **0xF1**: FILE_INTEGRITY_ERROR [Source: protocols.h, line 414] - ---- - -## Authentication Deep Dive - -### DES/3DES Authentication Protocol - -#### Phase 1: Initial Authentication Request -``` -PCD → PICC: 90 0A 00 00 01 [KeyNo] 00 - └─ Authenticate command (0x0A) -``` -[Source: DESFire DES authentication D40-DES authentification.pdf, line 7] - -#### Phase 2: PICC Responds with Encrypted RndB -``` -PICC → PCD: [Ek(RndB)] 91 AF - └─ 8 bytes encrypted RndB -``` -[Source: DESFire DES authentication D40-DES authentification.pdf, line 9] - -#### Phase 3: PCD Prepares Response -1. Decrypt RndB using key -2. Generate RndA (8 bytes) -3. Rotate RndB left by 1 byte -4. Concatenate: RndA || RndB_rotated -5. Encrypt with CBC mode, IV from previous response - -[Source: DESFire DES authentication D40-DES authentification.pdf, lines 23-39] - -#### Phase 4: Send Encrypted Challenge -``` -PCD → PICC: 90 AF 00 00 10 [Ek(RndA || RndB_rot)] 00 -``` -[Source: DESFire DES authentication D40-DES authentification.pdf, line 41] - -#### Phase 5: Verify PICC Response -``` -PICC → PCD: [Ek(RndA_rot)] 91 00 -``` -PCD decrypts and verifies rotated RndA matches -[Source: DESFire DES authentication D40-DES authentification.pdf, lines 43-56] - -### AES Authentication Protocol - -Similar flow but with 16-byte blocks: -1. Uses command 0xAA instead of 0x0A -2. RndA and RndB are 16 bytes each -3. AES-128 in CBC mode -4. Session key derivation differs - -[Source: DESFire.py, lines 79-144] - -### EV2 Authentication Protocol - -#### EV2First Authentication -1. **Capability Exchange**: - ``` - PCD → PICC: 71 [KeyNo] [Len] [PCDcap2] - PICC → PCD: [TI] [PDcap2] [PCDcap2] AF - ``` - [Source: desfire_ev3_authentication.pdf, lines 18-25] - -2. **Complete Authentication**: - - Similar challenge-response - - Generates Transaction Identifier (TI) - - Establishes secure channel - -#### EV2NonFirst Authentication -``` -PCD → PICC: 77 [KeyNo] -``` -Requires previous EV2First in same session -[Source: desfire_ev3_authentication.pdf, lines 27-30] - -### Session Key Generation - -#### DES Session Key (8 bytes) -``` -SessionKey = RndA[0:4] || RndB[0:4] -``` -[Source: DESFire DES authentication D40-DES authentification.pdf, lines 66-71] - -#### 2K3DES Session Key (16 bytes) -``` -SessionKey = RndA[0:4] || RndB[0:4] || RndA[4:8] || RndB[4:8] -``` -[Source: DESFire.py, lines 135-136] - -#### 3K3DES Session Key (24 bytes) -``` -SessionKey = RndA[0:4] || RndB[0:4] || - RndA[6:10] || RndB[6:10] || - RndA[12:16] || RndB[12:16] -``` -[Source: DESFire.py, lines 138-141] - -#### AES Session Key (16 bytes) -``` -SessionKey = RndA[0:4] || RndB[0:4] || RndA[12:16] || RndB[12:16] -``` -[Source: DESFire.py, lines 143-144] - -### CMAC Calculation - -#### Subkey Generation -```python -# Generate L by encrypting zero block -L = AES_Encrypt(Key, 0x00000000000000000000000000000000) - -# Generate K1 -K1 = L << 1 -if MSB(L) == 1: - K1 = K1 XOR Rb # Rb = 0x87 for AES - -# Generate K2 -K2 = K1 << 1 -if MSB(K1) == 1: - K2 = K2 XOR Rb -``` -[Source: mifare_desfire_crypto.c, lines 95-123] - -#### CMAC Calculation -1. Pad message if needed (0x80 0x00...) -2. XOR last block with K1 (complete) or K2 (incomplete) -3. CBC encrypt all blocks -4. Final block is CMAC - -[Source: mifare_desfire_crypto.c, lines 126-151] - ---- - -## File Types and Operations - -### Standard Data File Operations - -#### CreateStdDataFile -``` -Command: CD [FileNo] [CommSettings] [AccessRights] [FileSize] -Example: CD 01 00 00 00 00 10 00 00 // File 01, plain, free access, 16 bytes -``` -[Source: protocols.h, line 357] - -#### ReadData -``` -Command: BD [FileNo] [Offset-3B] [Length-3B] -Example: BD 01 00 00 00 10 00 00 // Read 16 bytes from offset 0 -``` -[Source: protocols.h, line 367] - -#### WriteData -``` -Command: 3D [FileNo] [Offset-3B] [Length-3B] [Data] -Example: 3D 01 00 00 00 04 00 00 DE AD BE EF // Write 4 bytes -``` -[Source: protocols.h, line 368] - -### Value File Operations - -#### CreateValueFile -``` -Command: CC [FileNo] [CommSettings] [AccessRights] [LowerLimit-4B] [UpperLimit-4B] [Value-4B] [LimitedCreditEnable] -Example: CC 02 00 00 00 00 00 00 00 E8 03 00 00 00 00 00 00 01 - // Value file 02, limits 0-1000, initial 0, limited credit enabled -``` -[Source: protocols.h, line 359] - -#### Credit Operation -``` -Command: 0C [FileNo] [Amount-4B] -Example: 0C 02 64 00 00 00 // Credit 100 to file 02 -``` -[Source: protocols.h, line 370] - -#### Debit Operation -``` -Command: DC [FileNo] [Amount-4B] -Example: DC 02 0A 00 00 00 // Debit 10 from file 02 -``` -[Source: protocols.h, line 371] - -### Record File Operations - -#### CreateLinearRecordFile -``` -Command: C1 [FileNo] [CommSettings] [AccessRights] [RecordSize-3B] [MaxRecords-3B] -Example: C1 03 00 00 00 20 00 00 0A 00 00 - // Linear record file 03, 32-byte records, max 10 records -``` -[Source: protocols.h, line 360] - -#### WriteRecord -``` -Command: 3B [FileNo] [Offset-3B] [Length-3B] [Data] -Example: 3B 03 00 00 00 20 00 00 [32 bytes of data] -``` -[Source: protocols.h, line 373] - -#### ReadRecords -``` -Command: BB [FileNo] [RecordNo-3B] [NumRecords-3B] -Example: BB 03 00 00 00 05 00 00 // Read 5 records starting from record 0 -``` -[Source: protocols.h, line 374] - -### Transaction Mechanism - -For Backup and Value files: -1. Perform operations (Write, Credit, Debit) -2. Changes are pending until: - - **CommitTransaction (0xC7)**: Apply changes - - **AbortTransaction (0xA7)**: Discard changes - -[Source: protocols.h, lines 376-377] - ---- - -## Cryptographic Implementation - -### Key Diversification (AN10922) - -#### Algorithm Steps -1. **Prepare Diversification Input**: - ``` - M = [Constant] || [UID] || [AID] || [SystemIdentifier] - ``` - Constants: - - 0x01: AES-128 - - 0x21: 2K3DES - - 0x31: 3K3DES - [Source: mifare_key_deriver.c, lines 10-17] - -2. **Calculate Diversified Key**: - ``` - DiversifiedKey = CMAC(MasterKey, M) - ``` - [Source: mifare_key_deriver.c, lines 101-177] - -### Secure Messaging - -#### MACed Communication Mode (0x01) -- Commands sent in plain -- Response includes 8-byte CMAC -- CMAC covers: Response Data + Status Code -[Source: various implementation files] - -#### Full Enciphered Mode (0x03) -- Command data encrypted after authentication -- Response data encrypted -- Both include CMAC for integrity -- Uses session keys and IVs - -### IV Generation - -#### EV1 IV Handling -- Initial IV: All zeros -- Subsequent: Last block of previous crypto operation - -#### EV2/EV3 IV Generation -``` -IV = EncryptedFlag || TI || .pdfCtr || ZeroPadding -``` -- TI: Transaction Identifier (4 bytes) -- .pdfCtr: Command Counter (2 bytes) -[Source: hf_desfire.c and crypto implementations] - ---- - -## Communication Modes - -### Plain Communication (0x00) -- No encryption or MACing -- Suitable for public data -- Fastest performance -- No authentication required for read - -### MACed Communication (0x01) -- Data transmitted in plain -- 8-byte CMAC appended to responses -- Integrity protection -- Requires authentication - -### Fully Enciphered Communication (0x03) -- All data encrypted -- CMAC for integrity -- Maximum security -- Requires authentication -- Performance impact - ---- - -## Error Codes Reference - -### Common Error Scenarios - -#### 0x9D - PERMISSION_DENIED -- Attempting operation without required authentication -- Wrong key authenticated for operation -- Access rights don't permit operation - -#### 0xAE - AUTHENTICATION_ERROR -- Authentication protocol failure -- Wrong key or key version -- Corrupted authentication data - -#### 0x7E - LENGTH_ERROR -- Command parameters wrong length -- Data exceeds file size -- Frame size exceeded - -#### 0xA0 - APPLICATION_NOT_FOUND -- Invalid AID selected -- Application was deleted -- Card not properly initialized - ---- - -## Implementation Examples - -### Example 1: Creating an Application with AES Keys -```python -# Create application 0x000001 with 5 AES keys -aid = [0x01, 0x00, 0x00] -key_settings = 0x0F # All keys changeable, free directory -num_keys = 0x85 # 5 keys, AES encryption (bit 7 set) - -command = [0xCA] + aid + [key_settings, num_keys] -response = send_command(command) -``` - -### Example 2: Secure File Write with MACing -```python -# Authenticate first -authenticate_aes(key_no=0x01, key=master_key) - -# Create MACed file -create_std_file(file_no=0x01, - comm_settings=0x01, # MACed - access_rights=0x0000, # Free access - file_size=32) - -# Write data (will be MACed automatically) -write_data(file_no=0x01, offset=0, data=b"Secure data here") -``` - -### Example 3: Value File Transaction -```python -# Create value file with limits -create_value_file(file_no=0x02, - lower_limit=0, - upper_limit=10000, - initial_value=1000, - limited_credit=True) - -# Perform operations -credit(file_no=0x02, amount=500) # Balance: 1500 -debit(file_no=0x02, amount=200) # Balance: 1300 - -# Commit all changes -commit_transaction() -``` - ---- - -## Bibliography - -### Primary Sources (Datasheets) -1. **AN11004**: MIFARE DESFire EV1 Features and Hints -2. **AN12696**: MIFARE DESFire EV2 Features and Hints -3. **AN12753**: MIFARE DESFire EV3 Features and Hints -4. **MF3D_H_X3_SDS**: MIFARE DESFire EV3 Secure Data Sheet -5. **PLT-05618**: MIFARE DESFire EV3 Application Note -6. **[0011955][v1.0]**: ST Pegasus DESFire Light v1.0 Specification -7. **AN-315**: Understanding Protege MIFARE DESFire Credentials - -### Implementation Sources -1. **protocols.h**: Proxmark3 DESFire protocol definitions -2. **hf_desfire.c**: Proxmark3 DESFire implementation -3. **DESFire.py**: Python DESFire implementation -4. **DESFire_DEF.py**: Python DESFire constants -5. **mifare_desfire.c**: libfreefare C implementation -6. **mifare_desfire_crypto.c**: libfreefare crypto implementation -7. **DesfireEv3.java**: Android DESFire EV3 implementation - -### Documentation Sources -1. **desfire_ev3_authentication.pdf**: EV3 authentication details -2. **desfire_ev3_file_operations.pdf**: EV3 file operation examples -3. **DESFire DES authentication D40-DES authentification.pdf**: Legacy auth flow -4. **DESFire TDES decryption SEND mode.pdf**: TDES implementation details -5. **auth1d_d40.pdf**: D40 authentication documentation - -### Additional References -1. ISO/IEC 14443-4: Proximity cards protocol -2. ISO/IEC 7816-4: Smart card APDU specification -3. Common Criteria EAL5+ certification documents -4. NIST SP 800-38B: CMAC specification -5. AN10922: NXP Key Diversification - ---- - -*End of The Unofficial DESFire Bible* - -*Compiled from official documentation and implementation sources* -*All information includes inline citations for verification* -*Last updated: Based on DESFire EV3 specifications* \ No newline at end of file diff --git a/include/ansi.h b/include/ansi.h index b791741f5..20815bc03 100644 --- a/include/ansi.h +++ b/include/ansi.h @@ -21,12 +21,6 @@ #define AEND "\x1b[0m" -#define _CLEAR_ "\x1b[2J" -#define _CLEAR_SCROLLBACK_ "\x1b[3J" -#define _TOP_ "\x1b[1;1f" - -#define _CLR_ "\x1b[0K" - #define _BLACK_(s) "\x1b[30m" s AEND #define _RED_(s) "\x1b[31m" s AEND #define _GREEN_(s) "\x1b[32m" s AEND @@ -63,6 +57,10 @@ #define _BACK_BRIGHT_CYAN_(s) "\x1b[46;1m" s AEND #define _BACK_BRIGHT_WHITE_(s) "\x1b[47;1m" s AEND +#define _CLEAR_ "\x1b[2J" +#define _CLEAR_SCROLLBACK_ "\x1b[3J" +#define _TOP_ "\x1b[1;1f" + #if defined(HAVE_READLINE) // https://wiki.hackzine.org/development/misc/readline-color-prompt.html // Applications may indicate that the prompt contains diff --git a/include/iclass_cmd.h b/include/iclass_cmd.h index 259c8cc2f..8210490a8 100644 --- a/include/iclass_cmd.h +++ b/include/iclass_cmd.h @@ -24,8 +24,7 @@ //----------------------------------------------------------------------------- // iCLASS / PICOPASS //----------------------------------------------------------------------------- -#define PICOPASS_BLOCK_SIZE ( 8 ) -#define PICOPASS_MAX_BYTES ( 4096 ) // # 32k bits = 4096 bytes +#define PICOPASS_BLOCK_SIZE 8 // iCLASS reader flags #define FLAG_ICLASS_READER_INIT 0x01 @@ -198,12 +197,5 @@ typedef struct { } header; } PACKED iclass_card_select_resp_t; -typedef struct { - union { - picopass_hdr_t hdr; - picopass_ns_hdr_t ns_hdr; - } header; - uint8_t data[PICOPASS_MAX_BYTES]; -} PACKED iclass_tag_t; #endif // _ICLASS_H_ diff --git a/include/iso15.h b/include/iso15.h index 9c39db3a3..0d19c1756 100644 --- a/include/iso15.h +++ b/include/iso15.h @@ -20,14 +20,10 @@ #define _ISO15_H_ #include "common.h" - -#define ISO15693_UID_LENGTH 8 -#define ISO15693_ATQB_LENGTH 7 - typedef struct { - uint8_t uid[ISO15693_UID_LENGTH]; + uint8_t uid[8]; uint8_t uidlen; - uint8_t atqb[ISO15693_ATQB_LENGTH]; + uint8_t atqb[7]; uint8_t chipid; uint8_t cid; } PACKED iso15_card_select_t; diff --git a/include/iso18.h b/include/iso18.h index da37819da..377f864d0 100644 --- a/include/iso18.h +++ b/include/iso18.h @@ -124,31 +124,4 @@ typedef struct { uint8_t PMi[8]; } PACKED felica_auth2_response_t; -typedef struct { - felica_frame_response_t frame_response; - uint8_t payload[4]; -} PACKED felica_service_dump_response_t; - -typedef struct { - uint8_t command_code[1]; - uint8_t IDm[8]; - uint8_t number_of_service[1]; - uint8_t service_code_list[2]; - uint8_t number_of_block[1]; -} PACKED felica_write_request_haeder_t; - -typedef struct { - uint8_t command_code[1]; - uint8_t IDm[8]; - uint8_t number_of_service[1]; - uint8_t service_code_list[2]; - uint8_t number_of_block[1]; -} PACKED felica_read_request_haeder_t; - - -typedef struct { - uint8_t random_challenge[16]; - uint8_t session_key[16]; -} PACKED felica_auth_context_t; - #endif // _ISO18_H_ diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index e5d8d2474..82623f2dd 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -349,12 +349,6 @@ typedef struct { uint8_t key[6]; } PACKED mfc_eload_t; -typedef struct { - bool use_flashmem; - uint16_t keycount; - uint8_t keys[]; -} PACKED mfulc_keys_t; - typedef struct { uint8_t status; uint8_t CSN[8]; @@ -872,7 +866,7 @@ typedef struct { #define FLAG_NR_AR_ATTACK 0x0400 // support nested authentication attack #define FLAG_NESTED_AUTH_ATTACK 0x0800 -#define FLAG_MF_ALLOW_OOB_AUTH 0x1000 + #define MODE_SIM_CSN 0 #define MODE_EXIT_AFTER_MAC 1 @@ -964,8 +958,6 @@ typedef struct { // Cryptographic error client/pm3: cryptographic operation failed #define PM3_ECRYPTO -29 -// File error client: error related to file does not exist in search paths -#define PM3_ENOFILE -30 // No data client/pm3: no data available, no host frame available (not really an error) #define PM3_ENODATA -98 // Quit program client: reserved, order to quit the program diff --git a/include/pmflash.h b/include/pmflash.h index 7e601c2bc..7820ad4e2 100644 --- a/include/pmflash.h +++ b/include/pmflash.h @@ -79,13 +79,6 @@ #define MF_KEYS_FILE "dict_mf.bin" #define MF_KEY_LENGTH 6 -// MIFARE Ultralight-C keys stored in spiffs -#define MFULC_KEYS_FILE "dict_mfulc.bin" -#define MFULC_KEY_LENGTH (16) - -// MIFARE Ultralight-AES keys stored in spiffs -#define MFULAES_KEYS_FILE "dict_mfulaes.bin" -#define MFULAES_KEY_LENGTH (16) // RDV40, validation structure to help identifying that client/firmware is talking with RDV40 typedef struct { uint8_t magic[4]; diff --git a/tools/fpga_compress/Makefile b/tools/fpga_compress/Makefile index 3e34619e8..92af2739e 100644 --- a/tools/fpga_compress/Makefile +++ b/tools/fpga_compress/Makefile @@ -1,8 +1,6 @@ ifeq ($(PLTNAME),) -include ../../Makefile.platform -include ../../.Makefile.options.cache -# Default platform if no platform specified - PLATFORM?=PM3RDV4 ifneq ($(PLATFORM), $(CACHED_PLATFORM)) $(error platform definitions have been changed, please "make clean" at the root of the project) endif diff --git a/tools/mfc/card_only/staticnested_2nt.c b/tools/mfc/card_only/staticnested_2nt.c index a013a0d97..4409d94e2 100644 --- a/tools/mfc/card_only/staticnested_2nt.c +++ b/tools/mfc/card_only/staticnested_2nt.c @@ -175,19 +175,19 @@ static void pm3_staticnested(uint32_t uid, uint32_t nt1, uint32_t ks1, uint32_t } } -static int usage(const char *prog) { +static int usage(void) { printf("\n"); printf("\nProgram tries to recover keys from static encrypted nested MFC cards\n"); printf("using two different implementations, Chameleon Ultra (CU) and Proxmark3.\n"); printf("It uses the nonce, keystream sent from pm3 device to client.\n"); printf("ie: NOT the CU data which is data in the trace.\n"); printf("\n"); - printf("syntax: %s \n\n", prog); + printf("syntax: staticnested \n\n"); printf("samples:\n"); printf("\n"); - printf(" %s 461dce03 7eef3586 ffb02eda 322bc14d ffc875ca\n", prog); - printf(" %s 461dce03 7eef3586 1fb6b496 322bc14d 1f4eebdd\n", prog); - printf(" %s 461dce03 7eef3586 7fa28c7e 322bc14d 7f62b3d6\n", prog); + printf(" ./staticnested 461dce03 7eef3586 ffb02eda 322bc14d ffc875ca\n"); + printf(" ./staticnested 461dce03 7eef3586 1fb6b496 322bc14d 1f4eebdd\n"); + printf(" ./staticnested 461dce03 7eef3586 7fa28c7e 322bc14d 7f62b3d6\n"); printf("\n"); return 1; } @@ -196,7 +196,7 @@ int main(int argc, char *const argv[]) { printf("\nMIFARE Classic static nested key recovery\n\n"); - if (argc < 5) return usage(argv[0]); + if (argc < 5) return usage(); printf("Init...\n"); NtpKs1 *pNK = calloc(2, sizeof(NtpKs1)); diff --git a/tools/mfc/card_only/staticnested_2x1nt_rf08s_1key.c b/tools/mfc/card_only/staticnested_2x1nt_rf08s_1key.c index 87b2f330d..f7b74ce0e 100644 --- a/tools/mfc/card_only/staticnested_2x1nt_rf08s_1key.c +++ b/tools/mfc/card_only/staticnested_2x1nt_rf08s_1key.c @@ -5,7 +5,7 @@ // * keyA and keyB are different for the targeted sector // // Strategy: -// * Use staticnested_2x1nt_rf08s to crack keyA +// * Use f08s_nested_known_collision to crack keyA // * If keyB not readable, find keyB in its dictionary based on the obscure relationship between keyA, keyB and their nT // // Doegox, 2024, cf https://eprint.iacr.org/2024/1275 for more info @@ -89,7 +89,7 @@ int main(int argc, char *const argv[]) { if (argc != 4) { printf("Usage:\n %s keys___.dic\n" - " where dict file is produced by staticnested_1nt *for the same UID and same sector* as provided nt and key\n", + " where dict file is produced by rf08s_nested_known *for the same UID and same sector* as provided nt and key\n", argv[0]); return 1; } diff --git a/tools/pm3_online_tests.sh b/tools/pm3_online_tests.sh deleted file mode 100755 index 998122f62..000000000 --- a/tools/pm3_online_tests.sh +++ /dev/null @@ -1,148 +0,0 @@ -#!/usr/bin/env bash - -# Online tests that require actual PM3 device connection -# This is used to make sure that the language for the functions is english instead of the system default language. -LANG=C - -PM3PATH="$(dirname "$0")/.." -cd "$PM3PATH" || exit 1 - -TESTALL=false -TESTDESFIREVALUE=false - -# https://medium.com/@Drew_Stokes/bash-argument-parsing-54f3b81a6a8f -PARAMS="" -while (( "$#" )); do - case "$1" in - -h|--help) - echo """ -Usage: $0 [--pm3bin /path/to/pm3] [desfire_value] - --pm3bin ...: Specify path to pm3 binary to test - desfire_value: Test DESFire value operations with card - You must specify a test target - no default 'all' for online tests -""" - exit 0 - ;; - --pm3bin) - if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then - PM3BIN=$2 - shift 2 - else - echo "Error: Argument for $1 is missing" >&2 - exit 1 - fi - ;; - desfire_value) - TESTALL=false - TESTDESFIREVALUE=true - shift - ;; - -*|--*=) # unsupported flags - echo "Error: Unsupported flag $1" >&2 - exit 1 - ;; - *) # preserve positional arguments - PARAMS="$PARAMS $1" - shift - ;; - esac -done -# set positional arguments in their proper place -eval set -- "$PARAMS" - -C_RED='\033[0;31m' -C_GREEN='\033[0;32m' -C_YELLOW='\033[0;33m' -C_BLUE='\033[0;34m' -C_NC='\033[0m' # No Color -C_OK='\xe2\x9c\x94\xef\xb8\x8f' -C_FAIL='\xe2\x9d\x8c' - -# Check if file exists -function CheckFileExist() { - printf "%-40s" "$1 " - if [ -f "$2" ]; then - echo -e "[ ${C_GREEN}OK${C_NC} ] ${C_OK}" - return 0 - fi - if ls "$2" 1> /dev/null 2>&1; then - echo -e "[ ${C_GREEN}OK${C_NC} ] ${C_OK}" - return 0 - fi - echo -e "[ ${C_RED}FAIL${C_NC} ] ${C_FAIL}" - return 1 -} - -# Execute command and check result -function CheckExecute() { - printf "%-40s" "$1 " - - start=$(date +%s) - TIMEINFO="" - RES=$(eval "$2") - end=$(date +%s) - delta=$(expr $end - $start) - if [ $delta -gt 2 ]; then - TIMEINFO=" ($delta s)" - fi - if echo "$RES" | grep -E -q "$3"; then - echo -e "[ ${C_GREEN}OK${C_NC} ] ${C_OK} $TIMEINFO" - return 0 - fi - echo -e "[ ${C_RED}FAIL${C_NC} ] ${C_FAIL} $TIMEINFO" - echo "Execution trace:" - echo "$RES" - return 1 -} - -echo -e "${C_BLUE}Iceman Proxmark3 online test tool${C_NC}" -echo "" -echo "work directory: $(pwd)" - -if command -v git >/dev/null && git rev-parse --is-inside-work-tree >/dev/null 2>&1; then - echo -n "git branch: " - git describe --all - echo -n "git sha: " - git rev-parse HEAD - echo "" -fi - -# Check that user specified a test -if [ "$TESTDESFIREVALUE" = false ]; then - echo "Error: You must specify a test target. Use -h for help." - exit 1 -fi - -while true; do - # DESFire value tests - if $TESTDESFIREVALUE; then - echo -e "\n${C_BLUE}Testing DESFire card value operations${C_NC} ${PM3BIN:=./pm3}" - echo " PLACE A FACTORY DESFIRE CARD ON THE READER NOW" - if ! CheckFileExist "pm3 exists" "$PM3BIN"; then break; fi - - echo " Formatting card to clean state..." - if ! CheckExecute "format card" "$PM3BIN -c 'hf mfdes formatpicc'" "done"; then break; fi - - echo " Running value operation tests..." - if ! CheckExecute "card auth test" "$PM3BIN -c 'hf mfdes auth -n 0 -t 2tdea -k 00000000000000000000000000000000 --kdf none'" "authenticated.*succes"; then break; fi - if ! CheckExecute "card app creation" "$PM3BIN -c 'hf mfdes createapp --aid 123456 --ks1 0F --ks2 0E --numkeys 1'" "successfully created"; then break; fi - if ! CheckExecute "card value file creation" "$PM3BIN -c 'hf mfdes createvaluefile --aid 123456 --fid 02 --lower 00000000 --upper 000003E8 --value 00000064'" "created successfully"; then break; fi - if ! CheckExecute "card value get plain" "$PM3BIN -c 'hf mfdes value --aid 123456 --fid 02 --op get -m plain'" "Value.*100"; then break; fi - if ! CheckExecute "card value get mac" "$PM3BIN -c 'hf mfdes value --aid 123456 --fid 02 --op get -m mac'" "Value.*100"; then break; fi - if ! CheckExecute "card value credit plain" "$PM3BIN -c 'hf mfdes value --aid 123456 --fid 02 --op credit -d 00000032 -m plain'" "Value.*changed"; then break; fi - if ! CheckExecute "card value get after credit" "$PM3BIN -c 'hf mfdes value --aid 123456 --fid 02 --op get -m plain'" "Value.*150"; then break; fi - if ! CheckExecute "card value credit mac" "$PM3BIN -c 'hf mfdes value --aid 123456 --fid 02 --op credit -d 0000000A -m mac'" "Value.*changed"; then break; fi - if ! CheckExecute "card value debit plain" "$PM3BIN -c 'hf mfdes value --aid 123456 --fid 02 --op debit -d 00000014 -m plain'" "Value.*changed"; then break; fi - if ! CheckExecute "card value debit mac" "$PM3BIN -c 'hf mfdes value --aid 123456 --fid 02 --op debit -d 00000014 -m mac'" "Value.*changed"; then break; fi - if ! CheckExecute "card value final check" "$PM3BIN -c 'hf mfdes value --aid 123456 --fid 02 --op get -m mac'" "Value.*120"; then break; fi - if ! CheckExecute "card cleanup" "$PM3BIN -c 'hf mfdes selectapp --aid 000000; hf mfdes auth -n 0 -t 2tdea -k 00000000000000000000000000000000 --kdf none; hf mfdes deleteapp --aid 123456'" "application.*deleted"; then break; fi - echo " card value operation tests completed successfully!" - fi - - echo -e "\n------------------------------------------------------------" - echo -e "Tests [ ${C_GREEN}OK${C_NC} ] ${C_OK}\n" - exit 0 -done -echo -e "\n------------------------------------------------------------" -echo -e "\nTests [ ${C_RED}FAIL${C_NC} ] ${C_FAIL}\n" -exit 1 \ No newline at end of file diff --git a/tools/pm3_tests.sh b/tools/pm3_tests.sh index f8e2dba2b..65a2f9985 100755 --- a/tools/pm3_tests.sh +++ b/tools/pm3_tests.sh @@ -573,8 +573,8 @@ while true; do if ! CheckExecute slow "hf iclass loclass long test" "$CLIENTBIN -c 'hf iclass loclass --long'" "verified \( ok \)"; then break; fi if ! CheckExecute slow "emv long test" "$CLIENTBIN -c 'emv test -l'" "Tests \( 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 AEA684A6DAB23278"; then break; fi - if ! CheckExecute "hf iclass loclass test" "$CLIENTBIN -c 'hf iclass loclass --test'" "Key diversification \( ok \)"; then break; fi + "valid key AE A6 84 A6 DA B2 32 78"; then break; 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'" "Tests \( 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 diff --git a/tools/recover_pk.py b/tools/recover_pk.py index 7795604d8..1e6bc33f7 100755 --- a/tools/recover_pk.py +++ b/tools/recover_pk.py @@ -173,22 +173,16 @@ def selftests(): 'samples': ["045E4CC2451390", "C9BBDA1B99EB6634CDFD8E3251AC5C4742EA5FA507B8A8A8B39B19AB7340D173331589C54C56C49F0CCA6DDBAC1E492A", # noqa: E501 "043F88C2451390", "5C2055A7373F119C3FDD9843020B06AA0E6DE18C16496C425C4AD971A50F05FA1A67B9E39CA60C355EEEEBF8214A84A5"], # noqa: E501 'pk': "0453BF8C49B7BD9FE3207A91513B9C1D238ECAB07186B772104AB535F7D3AE63CF7C7F3DD0D169DA3E99E43C6399621A86"}, # noqa: E501 - {'name': "MIFARE Ultralight AES (Vingcard alt key)", + {'name': "MIFARE Ultralight AES (alt key)", # uses prime192v1, None, - 'samples': ["04A31232241C90", "057595DCC601CA7E21341F1F978FA134F0204D87A33749C56DDB4ABD6F1F26194341DB10093B34C42F524A30DCC5CE54", # noqa: E501 - "041BC1D2F31B90", "FB5CF8F1B3CC39984BCA54A50FCF47ACFDC8C969010C1F4599554AF9A8E4F2B8371524855E45AD7EE71179A660D27667"], # noqa: E501 + # TODO more samples + 'samples': ["04A31232241C90", "057595DCC601CA7E21341F1F978FA134F0204D87A33749C56DDB4ABD6F1F26194341DB10093B34C42F524A30DCC5CE54"], # noqa: E501 'pk': "04DC34DAA903F2726A6225B11C692AF6AB4396575CA12810CBBCE3F781A097B3833B50AB364A70D9C2B641A728A599AE74"}, # noqa: E501 {'name': "MIFARE Classic / QL88", 'samples': ["30933C61", "AEA4DD0B800FAC63D4DE08EE91F4650ED825FD6B4D7DEEE98DBC9BAE10BE003E", "20593261", "F762CDD59EEDC075F4DDBA7ECD529FEEE5135C65A84D12EF0A250A321B2012F5"], 'pk': "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"}, - {'name': "NTAG223DNA, NTAG224DNA", - # uses prime192v1, None, - # TODO more samples - 'samples': ["043302218D3D00", "6A5D5E034F4FC823CACAB56C1A77A409B8DB345F89BD3FD59ED1F9C0093518609BE62D0A20764D2011E47EFA187F29AA"], # noqa: E501 - 'pk': "0485D5B9353B4FAA77581BA2AE96630C5876D6E8603308ABE9A81A0B506F52D02D04FEE6F2D365B3DEE7B9FAD9133E2976"}, # noqa: E501 - # TruST25 (ST25TA) - KeyID 0x01? # curve=secp128r1, hash=sha256 - from block 224 in ST25TA NDEF file {'name': "ST25TA02KB TruST25 (ST) / KeyID 0x01?", @@ -215,7 +209,7 @@ def selftests(): succeeded = True for t in tests: - print("Testing %-41s" % (t['name']+":"), end="") + print("Testing %-40s" % (t['name']+":"), end="") curvenames = guess_curvename(t['samples'][1]) recovered = set() @@ -229,16 +223,16 @@ def selftests(): c, h, pk = recovered.pop() pk = binascii.hexlify(pk).decode('utf8') if pk.lower() == t['pk'].lower(): - print("%14s/%-8s ( %s )" % (c, h, color('ok', fg='green'))) + print("%15s/%-8s ( %s )" % (c, h, color('ok', fg='green'))) else: succeeded = False - print("%14s/%-8s ( %s ) got %s" % (c, h, color('fail', fg='red'), pk.lower())) + print("%15s/%-8s ( %s ) got %s" % (c, h, color('fail', fg='red'), pk.lower())) elif len(t['samples'])//2 == 1: recovereds = [(c, h) for c, h, pk in list(recovered) if t['pk'].lower() == binascii.hexlify(pk).decode('utf8').lower()] if len(recovereds) == 1: c, h = recovereds[0] - print("%14s/%-8s ( %s ) partial" % (c, h, color('ok', fg='green'))) + print("%15s/%-8s ( %s ) partial" % (c, h, color('ok', fg='green'))) else: succeeded = False print(" ( %s ), got" % color('fail', fg='red'))