diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..2f13a259a --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: iceman1001 +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.gitignore b/.gitignore index f5ee135e6..348195eba 100644 --- a/.gitignore +++ b/.gitignore @@ -35,10 +35,13 @@ Makefile.platform !client/hardnested/*.bin !client/hardnested/tables/*.z client/ui/ui_overlays.h +client/reveng/bmptst hardnested_stats.txt proxmark3 +proxmark3-flasher flasher +!flasher/ lua luac fpga_compress @@ -70,8 +73,9 @@ tools/jtag_openocd/openocd_configuration ppls patches/* *- Copy.* -client/lualibs/mf_default_keys.lua +client/lualibs/mfc_default_keys.lua client/lualibs/pm3_cmd.lua # recompiled fpga_version_info.c +.proxmark3/* diff --git a/.travis.yml b/.travis.yml index f42dd8f1c..c75bffe9b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,14 +4,29 @@ language: c #default linux build env is: xenial compiler: gcc +# move some env variables to homebrew env +env: + global: + - HOMEBREW_TRAVIS_BRANCH=$TRAVIS_BRANCH + - HOMEBREW_TRAVIS_COMMIT=$TRAVIS_COMMIT + # Test on Linux and MacOS matrix: include: - os: osx osx_image: xcode11 + env: MAKE_PARAMS='PLATFORM_EXTRAS=' + - os: osx + osx_image: xcode11 + env: MAKE_PARAMS='PLATFORM_EXTRAS=BTADDON' - os: linux dist: xenial sudo: required + env: MAKE_PARAMS='PLATFORM_EXTRAS=' + - os: linux + dist: xenial + sudo: required + env: MAKE_PARAMS='PLATFORM_EXTRAS=BTADDON' addons: apt: @@ -19,21 +34,25 @@ addons: - gcc-arm-none-eabi - libnewlib-dev homebrew: + packages: + - readline + - qt5 + - RfidResearchGroup/proxmark3/arm-none-eabi-gcc taps: RfidResearchGroup/proxmark3 install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then - brew info proxmark3; - brew options proxmark3; - brew install --HEAD proxmark3; - elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then - make all; + if ! arm-none-eabi-gcc -v; then + echo "arm-none-eabi-gcc [ERROR]"; + travis_terminate 1; fi + + make clean; + make all V=1 "$MAKE_PARAMS"; -script: +script: ## start and run a test script - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then - proxmark3 -h ; - elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then - ./client/proxmark3 -h ; - fi \ No newline at end of file + if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then + ./pm3test.sh; + elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then + ./pm3test.sh; + fi diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000..20b68be0e --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,27 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "type": "shell", + "command": "make clean && make all -j$(nproc --all)", + "problemMatcher": [ + "$gcc" + ] + }, + { + "label": "flash fullimage", + "type": "shell", + "command": "sudo ./pm3-flash-fullimage", + "problemMatcher": [] + }, + { + "label": "FLASH BOOTROM", + "type": "shell", + "command": "sudo ./pm3-flash-bootrom", + "problemMatcher": [] + } + ] +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index c9da6eba9..2099db5fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,52 @@ 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] + - Chg proxmark3-flasher is now merged into proxmark3 client. Add pm3-flash (@doegox) + - Chg `hf iclass clone\dump\rdbl\wrbl` - now uses NG (@iceman1001) + - Fix `hf iclass clone` - last block always fails (@iceman1001) + - Chg `hf iclass clone` - retries ten times, less output (honor verbose) (@iceman1001) + - Chg `hf iclass dump` - retries ten times, less output (honor verbose) (@iceman1001) + - Rename `hf iclass writeblk` -> `hf iclass wrbl` to match hf mf wrbl (@iceman1001) + - Rename `hf iclass readblk` -> `hf iclass rdbl` to match hf mf rdbl (@iceman1001) + - Add cmdscript example and show usage with shebang (@doegox) + - Add instructions for Fedora (@doegox) + - Chg reduce the list of requirements to the minimum and move to QT5 (@doegox) + - Add `make install` and reorganize/rename stuffs accordingly (@doegox) + - Add searchFile for several types of files (@doegox / @iceman1001) + - Chg posix sh version of mkversion (@doegox) + - Chg remove entirely ncurses, not needed nowadays (@doegox) + - Chg remove deprecated termcap, use ncurses instead (@ZeroChaos-) + - Chg `hf iclass encrypt` - now takes transport key as param. (@iceman1001) + - Chg `hf iclass decrypt` - now takes transport key as param. (@iceman1001) + - Chg `hf mf fchk m` - now secretly dumps card to emul, if all keys are found (@iceman1001) + - Chg history and logfile are now saved into $HOME/.proxmark3/ (@doegox) + - Chg optimization of iclass mac calculations on deviceside (@pwpiwi) + - Add `hf mf autopwn` - Autopwn function for Mifare Classic, extract all keys and dump card memory (@matthiaskonrath) + - Add Lua paths: look for scripts also in ~/.proxmark/lua{scripts,libs} and /usr/local/share/proxmark3/lua{scripts,libs} (@doegox) + - Change Lua directory scripts/ to luascript/ (@doegox) + - Change non-rdv4 PLATFORM must now use the generic PM3OTHER, simpler (@doegox) + - Fix reveng integration for all platforms else than WIN32 (@doegox) + - Add cheat sheet for easy operations of the Proxmark3 (scund00r) + - Chg commands are now in green in the helptext list (@iceman1001) + - Fix `script run ndefdump` - better exit messages when failing (@iceman1001) + - Fix `hf iclass dump` - now also saves in EML format (@iceman1001) + - Fix `hf iclass sim 3` - now works on legacy readers and legacy SE readers (@iceman1001) + - Rework hitag2 read/write help (@ViRb3) + - Add `lf nedap` - encoding / decoding (anon) + - Add client option `-i` to stay in interactive mode after a script or command (@DidierStevens/@doegox) + - Add VSCode tasks (@ViRb3) + - Better warn user of hardcoded hitag info (@ViRb3) + - Format and docs hitag (@ViRb3) + - Fix hitag password write offset by 1 (@ViRb3) + - Fix momentarily flash read/write of dicts (@doegox/@cjbrigato) + - Add some more default keys (@anon) + - Add `hf thinfilm sim` simulating Thinfilm NFC barcode tags (@doegox) + - Add `hf thinfilm list` specific trace decoding (Thinfilm NFC barcode tags) (@doegox) + - Fix `hf topaz reader` - don't crash when trying to read a Thinfilm tag (@iceman1001) + - Add `hf thinfilm info` - read / decode Kovio Thinfilm NFC barcode tags (@iceman1001) + - Add FPGA LF adc path (@anon) + - Add ECC support / check for NID_secp128r1 (@pwpiwi) + - Add some more default keys (ollibolli) - Fix T55x7 Downlink timings backward compatible (@mwalker33) - Add proper Makefile halting when using incompatible STANDALONE and PLATFORM vars (@doegox) - Add T55x7 Downlink mode support (@mwalker33) @@ -152,7 +198,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Change `lf indala demod` - refactoring (@iceman1001) - Change - handling fault bit markers (7) and partial nibbles in hex printing (@doegox) - Change - printing of fault bit markers (7) using a dot (@doegox) - - Change `sc upgrade` - firmware file integrity check (@piwi) + - Change `sc upgrade` - firmware file integrity check (@pwpiwi) - Fix `data rawdemod am` - last bit was missing (@doegox) - Fix `hf 15 dump f` - also selects tag first (@iceman1001) - Fix `hf iclass clone` - missing fileclose (@iceman1001) @@ -160,8 +206,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Change `lf hitag sim` - loads bin/eml/json (@iceman1001) - Change `lf hitag reader 21` - saves in bin/eml/json (@iceman1001) - Change `lf hitag` - refactoring (@iceman1001) - - Change `lf hitag` - refactoring (@piwi) - - Fix `lf hitag` - generic fix for missing clock init (@piwi) + - Change `lf hitag` - refactoring (@pwpiwi) + - Fix `lf hitag` - generic fix for missing clock init (@pwpiwi) - Fix fsk sim operations on deviceside - avoid division by zero (@doegox) - Fix `hf mf fchk` - condition always false (@doegox) - Fix `lf t55xx recoverpw` - shift as u32 (@doegox) @@ -290,7 +336,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added to proxmark command line parameters `c` and `l` - execute command and lua script from command line (@merlokk) - Added to proxmark ability to execute commands from stdin (pipe) (@merlokk) - Added new standalone mode "HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN" (@cjbrigato) - - Added to `hf 14a apdu` - exchange apdu via iso1443-4 (@merlokk) + - Added to `hf 14a apdu` - exchange apdu via iso14443-4 (@merlokk) - Added to `hf 14a apdu` - apdu and tlv results parser (@merlokk) - Added `hf emv` commands (@merlokk) - lots of bug fixes (many many) diff --git a/COMPILING.txt b/COMPILING.txt index 04ff1d8bf..58ee40c08 100644 --- a/COMPILING.txt +++ b/COMPILING.txt @@ -1,131 +1,2 @@ -The project compiles on Linux, Mac OS X and Windows (MinGW/MSYS). - -it requires: -- gcc >= 4.8 -- libpthread -- libreadline -- libusb -- perl -- an ARM cross-compiler to compile the firmware -- libncurses5-dev - -and optionally QT for the GUI - - -To compile, just run "make". - -=========== -= Windows = -=========== - -Rather than download and install every one of these packages, a new ProxSpace -environment archive file will be made available for download on the project -page at @Gator96100's repo - -Afterwards just clone the iceman repo or download someone elses. Read instructions on @Gator96100 repo page. (https://github.com/Gator96100/ProxSpace/) - -Download the ProxSpace environment archive and extract it to C:\ - -Links - https://github.com/Gator96100/ProxSpace/archive/master.zip - - -============ -= Mac OS X = -============ - -Installing from HomeBrew tap ---------------------------- -This method is recommended and tested on macOS Sierra 10.12.3 - -1. Install homebrew if you haven't yet already done so: http://brew.sh/ - -2. Tap proxmark repo: - brew tap iceman1001/proxmark3 - -3. Install Proxmark3: - -Stable release - brew install proxmark3 - -Latest non-stable from GitHub (use this if previous command fails) - brew install --HEAD proxmark3 - -For more information go to https://github.com/iceman1001/homebrew-proxmark3 - -Upgrading HomeBrew tap formula ------------------------------ -*This method is useful for those looking to run bleeding-edge versions of iceman's client. Keep this in mind when attempting to update your HomeBrew tap formula as this procedure could easily cause a build to break if an update is unstable on macOS.* - -Tested on macOS Sierra 10.12.6 - -*Note: This assumes you have already installed iceman's fork from HomeBrew as mentioned above* - -1. Force HomeBrew to pull the latest source from github -`brew upgrade --fetch-HEAD iceman1001/proxmark3/proxmark3` - -2. Flash the bootloader - * With your Proxmark3 unplugged from your machine, press and hold the button on your Proxmark 3 as you plug it into a USB port. After about 5 seconds let go of the button and run this command - `$ sudo proxmark3-flasher /dev/tty.usbmodem881 /usr/local/Cellar/proxmark3/HEAD-ccfdd60/share/firmware/fullimage.elf` - * After the bootloader finishes flashing, unplug your Proxmark3 from your machine - -3. Flash fullimage.elf - * Press and hold the button on your Proxmark 3 and keep it held as you plug the Proxmark 3 back into the USB port; continue to hold the button until after this step is complete and the `proxmark3-flasher` command outputs "Have a nice day!"* - -`$ sudo proxmark3-flasher /dev/tty.usbmodem881 /usr/local/Cellar/proxmark3/HEAD-ccfdd60/share/firmware/fullimage.elf` - -4. Enjoy the update - -Compilling from source manually (Legacy) ---------------------------- - -Tested on OSX 10.10 Yosemite - -1 - Install Xcode and Xcode Command Line Tools - -2 - Install Homebrew and dependencies - brew install readline libusb p7zip libusb-compat wget qt5 pkgconfig - -3 - Download DevKitARM for OSX - http://sourceforge.net/projects/devkitpro/files/devkitARM/devkitARM_r44/ - Unpack devkitARM_r44-osx.tar.bz2 to proxmark3 directory. - -4 - Edit proxmark3/client/Makefile adding path to readline and qt5 - - LDLIBS = -L/usr/local/opt/readline/lib -L/usr/local/opt/qt5/lib -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm - CFLAGS = -std=c99 -I/usr/local/opt/qt5/include -I/usr/local/opt/readline/include -I. -I../include -I../common -I../zlib -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4 - - If your old brew intallation use /usr/local/Cellar/ path replace /usr/local/opt/readline/lib with your actuall readline and qt5 path. See homebrew manuals. - -5 - Set Environment - - export DEVKITPRO=$HOME/proxmark3/ - export DEVKITARM=$DEVKITPRO/devkitARM - export PATH=${PATH}:${DEVKITARM}/bin - - -============ -= Linux = -============ - -1 - Download - -A precompiled DevKitARM cross compiler tool chain package can be found at -http://sourceforge.net/projects/devkitpro/files/devkitARM -Select the one you need (32bit or 64bit) and unpack to a convinient place, eg -$HOME/proxmark3/. It will create a devkitARM/ subdirectory. - -You will also need a general compiling environment on your computer for -the client and the libusb headers. In most distributions you will get all you -need with the lsb-package (Linux Standard Base). In debian/ubuntu you simply -call `aptitude install lsb libusb-dev libreadline-dev libreadline6`. - -For the graphical plot view, you might need the qtlibs (debian/ubuntu: -libqt4-dev), too. - -2 - Set Environment - -export DEVKITPRO=$HOME/proxmark3/ -export DEVKITARM=$DEVKITPRO/devkitARM -export PATH=${PATH}:${DEVKITARM}/bin +Refer to doc/md/Installation_Instructions/ for up-to-date intructions for various platforms. diff --git a/Makefile b/Makefile index 587fdf09d..ebb4dacb8 100644 --- a/Makefile +++ b/Makefile @@ -1,82 +1,131 @@ -# Hide full compilation line: -ifneq ($(V),1) - Q?=@ -endif -# To see full command lines, use make V=1 - -GZIP=gzip -# Windows' echo echos its input verbatim, on Posix there is some -# amount of shell command line parsing going on. echo "" on -# Windows yields literal "", on Linux yields an empty line -ifeq ($(shell echo ""),) - # This is probably a proper system, so we can use uname - DELETE=rm -rf - FLASH_TOOL=client/flasher - platform=$(shell uname) - ifneq (,$(findstring MINGW,$(platform))) - FLASH_PORT=com3 - PATHSEP=\\# - else - FLASH_PORT=/dev/ttyACM0 - PATHSEP=/ - endif -else - # Assume that we are running on native Windows - DELETE=del /q - FLASH_TOOL=client/flasher.exe - platform=Windows - FLASH_PORT=com3 - PATHSEP=\\# -endif +include Makefile.defs -include Makefile.platform -include .Makefile.options.cache -include common/Makefile.hal +include common_arm/Makefile.hal -all clean: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/% +# preserve relative DESTDIR path for subdir makes +ifneq (,$(DESTDIR)) + # realpath needs the directory to exist + $(shell $(MKDIR) $(DESTDIR)) + MYDESTDIR:=$(realpath $(DESTDIR)) + ifeq (,$(MYDESTDIR)) + $(error Can't create $(DESTDIR)) + endif +endif + +all clean install uninstall: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/% fpga_compress/% + +INSTALLTOOLS=pm3_eml2lower.sh pm3_eml2upper.sh pm3_mfdread.py pm3_mfd2eml.py pm3_eml2mfd.py findbits.py rfidtest.pl xorcheck.py +INSTALLSIMFW=sim011.bin sim011.sha512.txt +INSTALLSCRIPTS=pm3 pm3-flash pm3-flash-all pm3-flash-bootrom pm3-flash-fullimage +INSTALLSHARES=tools/jtag_openocd traces +INSTALLDOCS=doc/*.md doc/md + +install: all common/install + +common/install: + $(info [@] Installing common resources to $(MYDESTDIR)$(PREFIX)...) +ifneq (,$(INSTALLSCRIPTS)) + $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH) + $(Q)$(CP) $(INSTALLSCRIPTS) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH) +endif +ifneq (,$(INSTALLSHARES)) + $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH) + $(Q)$(CP) $(INSTALLSHARES) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH) +endif +ifneq (,$(INSTALLDOCS)) + $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH) + $(Q)$(CP) $(INSTALLDOCS) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH) +endif +ifneq (,$(INSTALLTOOLS)) + $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH) + $(Q)$(CP) $(foreach tool,$(INSTALLTOOLS),tools/$(tool)) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH) +endif +ifneq (,$(INSTALLSIMFW)) + $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH) + $(Q)$(CP) $(foreach fw,$(INSTALLSIMFW),tools/simmodule/$(fw)) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH) +endif +ifeq ($(platform),Linux) + $(Q)$(MKDIR) $(DESTDIR)$(UDEV_PREFIX) + $(Q)$(CP) driver/77-pm3-usb-device-blacklist.rules $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules +endif + +uninstall: common/uninstall + +common/uninstall: + $(info [@] Uninstalling common resources from $(MYDESTDIR)$(PREFIX)...) +ifneq (,$(INSTALLSCRIPTS)) + $(Q)$(RM) $(foreach script,$(INSTALLSCRIPTS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)$(PATHSEP)$(notdir $(script))) +endif +ifneq (,$(INSTALLSHARES)) + $(Q)$(RMDIR) $(foreach share,$(INSTALLSHARES),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)$(PATHSEP)$(notdir $(share))) +endif +ifneq (,$(INSTALLDOCS)) + $(Q)$(RMDIR) $(foreach doc,$(INSTALLDOCS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH)$(PATHSEP)$(notdir $(doc))) + $(Q)$(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH) +endif +ifneq (,$(INSTALLTOOLS)) + $(Q)$(RM) $(foreach tool,$(INSTALLTOOLS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)$(PATHSEP)$(notdir $(tool))) +endif + $(Q)$(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH) +ifneq (,$(INSTALLSIMFW)) + $(Q)$(RM) $(foreach fw,$(INSTALLSIMFW),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(notdir $(fw))) +endif + $(Q)$(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH) +ifeq ($(platform),Linux) + $(Q)$(RM) $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules +endif + $(Q)$(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH) mfkey/%: FORCE $(info [*] MAKE $@) - $(Q)$(MAKE) --no-print-directory -C tools/mfkey $(patsubst mfkey/%,%,$@) + $(Q)$(MAKE) --no-print-directory -C tools/mfkey $(patsubst mfkey/%,%,$@) DESTDIR=$(MYDESTDIR) nonce2key/%: FORCE $(info [*] MAKE $@) - $(Q)$(MAKE) --no-print-directory -C tools/nonce2key $(patsubst nonce2key/%,%,$@) + $(Q)$(MAKE) --no-print-directory -C tools/nonce2key $(patsubst nonce2key/%,%,$@) DESTDIR=$(MYDESTDIR) +fpga_compress/%: FORCE + $(info [*] MAKE $@) + $(Q)$(MAKE) --no-print-directory -C tools/fpga_compress $(patsubst fpga_compress/%,%,$@) DESTDIR=$(MYDESTDIR) bootrom/%: FORCE cleanifplatformchanged $(info [*] MAKE $@) - $(Q)$(MAKE) --no-print-directory -C bootrom $(patsubst bootrom/%,%,$@) -armsrc/%: FORCE cleanifplatformchanged + $(Q)$(MAKE) --no-print-directory -C bootrom $(patsubst bootrom/%,%,$@) DESTDIR=$(MYDESTDIR) +armsrc/%: FORCE cleanifplatformchanged fpga_compress/% $(info [*] MAKE $@) - $(Q)$(MAKE) --no-print-directory -C armsrc $(patsubst armsrc/%,%,$@) + $(Q)$(MAKE) --no-print-directory -C armsrc $(patsubst armsrc/%,%,$@) DESTDIR=$(MYDESTDIR) client/%: FORCE $(info [*] MAKE $@) - $(Q)$(MAKE) --no-print-directory -C client $(patsubst client/%,%,$@) -recovery/%: FORCE cleanifplatformchanged bootrom/% armsrc/% + $(Q)$(MAKE) --no-print-directory -C client $(patsubst client/%,%,$@) DESTDIR=$(MYDESTDIR) +recovery/all: bootrom/all armsrc/all +recovery/install: bootrom/all armsrc/all +recovery/%: FORCE cleanifplatformchanged $(info [*] MAKE $@) - $(Q)$(MAKE) --no-print-directory -C recovery $(patsubst recovery/%,%,$@) + $(Q)$(MAKE) --no-print-directory -C recovery $(patsubst recovery/%,%,$@) DESTDIR=$(MYDESTDIR) FORCE: # Dummy target to force remake in the subdirectories, even if files exist (this Makefile doesn't know about the prerequisites) -.PHONY: all clean help _test bootrom flash-bootrom os flash-os flash-all recovery client mfkey nounce2key style checks FORCE udev accessrights cleanifplatformchanged +.PHONY: all clean install uninstall help _test bootrom fullimage recovery client mfkey nonce2key style checks FORCE udev accessrights cleanifplatformchanged help: @echo "Multi-OS Makefile" @echo @echo "Possible targets:" - @echo "+ all - Make all targets: bootrom, armsrc and OS-specific host tools" - @echo "+ clean - Clean in all targets" + @echo "+ all - Make all targets: bootrom, fullimage and OS-specific host tools" + @echo "+ clean - Clean in all targets" + @echo "+ .../clean - Clean in specified target and its deps, e.g. bootrom/clean" + @echo "+ (un)install - Install/uninstall Proxmark files in the system, default to /usr/local/share, + @echo " else provide a PREFIX. See Maintainers.md for more options" @echo - @echo "+ bootrom - Make bootrom" - @echo "+ os - Make armsrc (includes fpga)" - @echo "+ flash-bootrom - Make bootrom and flash it" - @echo "+ flash-os - Make armsrc and flash os image (includes fpga)" - @echo "+ flash-all - Make bootrom and armsrc and flash bootrom and os image" - @echo "+ recovery - Make bootrom and armsrc images for JTAG flashing" + @echo "+ bootrom - Make bootrom" + @echo "+ fullimage - Make armsrc fullimage (includes fpga)" + @echo "+ recovery - Make bootrom and fullimage files for JTAG flashing" @echo - @echo "+ client - Make only the OS-specific host client" - @echo "+ mfkey - Make tools/mfkey" - @echo "+ nounce2key - Make tools/nounce2key" + @echo "+ client - Make only the OS-specific host client" + @echo "+ mfkey - Make tools/mfkey" + @echo "+ nonce2key - Make tools/nonce2key" + @echo "+ fpga_compress - Make tools/fpga_compress" @echo - @echo "+ style - Apply some automated source code formatting rules" - @echo "+ checks - Detect various encoding issues in source code" + @echo "+ style - Apply some automated source code formatting rules" + @echo "+ checks - Detect various encoding issues in source code" @echo @echo "Possible platforms: try \"make PLATFORM=\" for more info, default is PM3RDV4" @echo "To activate verbose mode, use make V=1" @@ -85,7 +134,17 @@ client: client/all bootrom: bootrom/all -os: armsrc/all +# aliases fullimage = armsrc + +fullimage: armsrc/all + +fullimage/all: armsrc/all + +fullimage/clean: armsrc/clean + +fullimage/install: armsrc/install + +fullimage/uninstall: armsrc/uninstall recovery: recovery/all @@ -93,17 +152,10 @@ mfkey: mfkey/all nonce2key: nonce2key/all -flash-bootrom: bootrom/obj/bootrom.elf $(FLASH_TOOL) - $(FLASH_TOOL) $(FLASH_PORT) -b $(subst /,$(PATHSEP),$<) - -flash-os: armsrc/obj/fullimage.elf $(FLASH_TOOL) - $(FLASH_TOOL) $(FLASH_PORT) $(subst /,$(PATHSEP),$<) - -flash-all: bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf $(FLASH_TOOL) - $(FLASH_TOOL) $(FLASH_PORT) -b $(subst /,$(PATHSEP),$(filter-out $(FLASH_TOOL),$^)) +fpga_compress: fpga_compress/all newtarbin: - $(DELETE) proxmark3-$(platform)-bin.tar proxmark3-$(platform)-bin.tar.gz + $(RM) proxmark3-$(platform)-bin.tar proxmark3-$(platform)-bin.tar.gz @touch proxmark3-$(platform)-bin.tar tarbin: newtarbin client/tarbin armsrc/tarbin bootrom/tarbin @@ -145,7 +197,7 @@ style: # Make sure astyle is installed @which astyle >/dev/null || ( echo "Please install 'astyle' package first" ; exit 1 ) # Remove spaces & tabs at EOL, add LF at EOF if needed on *.c, *.h, *.cpp. *.lua, *.py, *.pl, Makefile - find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" \) \ + find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" -or -name "*.v" \) \ -exec perl -pi -e 's/[ \t]+$$//' {} \; \ -exec sh -c "tail -c1 {} | xxd -p | tail -1 | grep -q -v 0a$$" \; \ -exec sh -c "echo >> {}" \; @@ -158,11 +210,16 @@ style: # Detecting weird codepages and tabs. checks: - find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" \) \ + @echo "Files with suspicious chars:" + @find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" -or -name "*.v" \) \ -exec sh -c "cat {} |recode utf8.. >/dev/null || echo {}" \; - find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "*.md" -or -name "*.txt" -or -name "*.awk" \) \ + @echo "Files with tabs:" +# to remove tabs within lines, one can try with: vi $file -c ':set tabstop=4' -c ':set et|retab' -c ':wq' + @find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "*.md" -or -name "*.txt" -or -name "*.awk" -or -name "*.v" \) \ -exec grep -lP '\t' {} \; -# to remove tabs within lines, one can try with vi: :set tabstop=4 :set et|retab +# @echo "Files with printf \\\\t:" +# @find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "*.md" -or -name "*.txt" -or -name "*.awk" -or -name "*.v" \) \ +# -exec grep -lP '\\t' {} \; # Dummy target to test for GNU make availability _test: diff --git a/Makefile.defs b/Makefile.defs new file mode 100644 index 000000000..4068d7516 --- /dev/null +++ b/Makefile.defs @@ -0,0 +1,46 @@ +# Hide full compilation line: +ifneq ($(V),1) + Q?=@ +endif +# To see full command lines, use make V=1 + +# been here +DEFSBEENHERE = true + +CP = cp -a +GZIP = gzip +MKDIR = mkdir -p +RM = rm -f +RMDIR = rm -rf +# rmdir only if dir is empty, tolerate failure +RMDIR_SOFT = -rmdir +MV = mv +TOUCH = touch +FALSE = false +TAR = tar +TARFLAGS ?= -v --ignore-failed-read -r +TARFLAGS += -C .. -f +CROSS ?= arm-none-eabi- +CC = gcc +CXX = g++ +LD = g++ + +PATHSEP=/ +PREFIX ?= /usr/local +UDEV_PREFIX ?= /etc/udev/rules.d +INSTALLBINRELPATH ?= bin +INSTALLSHARERELPATH ?= share/proxmark3 +INSTALLFWRELPATH ?= share/proxmark3/firmware +INSTALLTOOLSRELPATH ?= share/proxmark3/tools +INSTALLDOCSRELPATH ?= share/doc/proxmark3 + +platform = $(shell uname) +DETECTED_OS=$(platform) + +ifeq ($(platform),Darwin) + AR= /usr/bin/ar rcs + RANLIB= /usr/bin/ranlib +else + AR= ar rcs + RANLIB= ranlib +endif diff --git a/Makefile.host b/Makefile.host new file mode 100644 index 000000000..bfadd82b7 --- /dev/null +++ b/Makefile.host @@ -0,0 +1,76 @@ +# This Makefile might have been called from various subdirs, trying to find our Makefile.defs +ifeq ($(DEFSBEENHERE),) + -include Makefile.defs +endif +ifeq ($(DEFSBEENHERE),) + -include ../Makefile.defs +endif +ifeq ($(DEFSBEENHERE),) + -include ../../Makefile.defs +endif +ifeq ($(DEFSBEENHERE),) + $(error Can't find Makefile.defs) +endif + +CFLAGS ?= -Wall -Werror -O3 +CFLAGS += $(MYDEFS) $(MYCFLAGS) $(MYINCLUDES) + +vpath %.c $(MYSRCPATHS) + +# Flags to generate temporary dependency files +DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td +# make temporary to final dependency files after successful compilation +POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d && $(TOUCH) $@ + +BINDIR := . +OBJDIR := obj + +MYOBJS = $(MYSRCS:%.c=$(OBJDIR)/%.o) +CLEAN = $(foreach bin,$(MYLIBS) $(BINS) $(LIB_A),$(BINDIR)/$(bin)) + +all: $(foreach bin,$(MYLIBS) $(BINS) $(LIB_A),$(BINDIR)/$(bin)) + +clean: + $(Q)$(RM) $(CLEAN) + $(Q)$(RMDIR) $(OBJDIR) + +install: all +ifneq (,$(INSTALLTOOLS)) + $(info [@] Installing $(BINS) to $(DESTDIR)$(PREFIX)...) + $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH) + $(Q)$(CP) $(INSTALLTOOLS) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH) +endif + @true + +uninstall: +ifneq (,$(INSTALLTOOLS)) + $(info [@] Uninstalling $(BINS) from $(DESTDIR)$(PREFIX)...) + $(Q)$(RM) $(foreach tool,$(INSTALLTOOLS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)$(PATHSEP)$(notdir $(tool))) +endif + @true + +.PHONY: all clean install uninstall + +$(BINDIR)/$(LIB_A): $(MYOBJS) + $(info [=] AR $(notdir $@)) + $(Q)$(AR) $@ $(MYOBJS) + $(Q)$(RANLIB) $@ + +$(BINDIR)/% : $(OBJDIR)/%.o $(MYOBJS) $(MYLIBS) + $(info [=] LD $(notdir $@)) + $(Q)$(LD) $(LDFLAGS) $(MYOBJS) $< -o $@ $(MYLIBS) + +$(OBJDIR)/%.o : %.c | $(OBJDIR) + $(info [-] CC $<) + $(Q)$(CC) $(DEPFLAGS) $(CFLAGS) -c -o $@ $< + $(Q)$(POSTCOMPILE) + +$(OBJDIR): + $(Q)$(MKDIR) $(OBJDIR) + +DEPENDENCY_FILES = $(MYOBJS:%.o=%.d) $(BINS:%=$(OBJDIR)/%.d) + +$(DEPENDENCY_FILES): ; +.PRECIOUS: $(DEPENDENCY_FILES) + +-include $(DEPENDENCY_FILES) diff --git a/README.md b/README.md index 50813868e..6680f5333 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ -# Proxmark3 RDV4.0 Dedicated Github +# RRG / Iceman repo - Proxmark3 RDV4.0 and other Proxmark3 platforms. + +This repo is based on iceman fork for Proxmark3. It supports other Proxmark3 platforms as well. + +It is dedicated to bringing the most out of the new features for Proxmark3 RDV4.0 new hardware and design. -This repo is based on iceman fork for Proxmark3. It is dedicated to bringing the most out of the new features for Proxmark3 RDV4.0 new hardware and design. -Note that it also supports other Proxmark3 platforms as well! | Releases | Linux & OSX CI | Windows CI | | ------------------- |:-------------------:| -------------------:| @@ -15,16 +17,23 @@ Note that it also supports other Proxmark3 platforms as well! | ------------------- |:-------------------:| -------------------:| |[What has changed?](#what-has-changed) | [Setup and build for Linux](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) | [Compilation Instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md)| |[Development](#development) | [Important notes on ModemManager for Linux users](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md) | [Validating proxmark client functionality](/doc/md/Use_of_Proxmark/1_Validation.md) | -|[Why didn't you base it on official PM3 Master?](#why-didnt-you-base-it-on-official-pm3-master)| [Homebrew (Mac OS X) & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md) | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)| -|[PM3 GUI](#pm3-gui)|[Setup and build for Windows](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md)|[Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)| +|[Why didn't you base it on official Proxmark3 Master?](#why-didnt-you-base-it-on-official-proxmark3-master)| [Homebrew (Mac OS X) & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md) | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)| +|[Proxmark3 GUI](#proxmark3-gui)|[Setup and build for Windows](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md)|[Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)| |[Issues](#issues)|[Blue shark manual](/doc/bt_manual_v10.md) |[Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md)| -|[Notes on UART](/doc/uart_notes.md)||| -|[Notes on Frame format](/doc/new_frame_format.md)||| -|[Notes on external flash](/doc/ext_flash_notes.md)||| -|[Notes on Termux / Android](/doc/termux_notes.md)||| +|[Notes on UART](/doc/uart_notes.md)|[Maintainers](/doc/md/Development/Maintainers.md)|[Command Cheat sheet](/doc/cheatsheet.md)| +|[Notes on frame format](/doc/new_frame_format.md)||[More cheat sheets](https://github.com/RfidResearchGroup/proxmark3/wiki/More-cheat-sheets)| +|[Notes on external flash](/doc/ext_flash_notes.md)||[EMV](/doc/emv_notes.md)| +|[Notes on Termux / Android](/doc/termux_notes.md)||[Troubleshooting](/doc/md/Installation_Instructions/Troubleshooting.md)| +|[Notes on wireshark / tracedata](/doc/trace_wireshark_notes.md)||[JTAG](/doc/jtag_notes.md)| +|[Notes on loclass](/doc/loclass_notes.md)||| +|[Notes on paths](/doc/path_notes.md)||| |[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode) || |[Donations](#Donations)||| +## Support on other Proxmark3 platforms + +In order to build this repo for other Proxmark3 platforms we urge you to read [Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md) + ## What has changed? On the hardware side: @@ -36,28 +45,44 @@ On the hardware side: On the software side: quite a lot, see the [Changelog file](CHANGELOG.md). ## Development -This fork now compiles just fine on + +This repo now compiles just fine on + - Proxspace v3.2 - Windows/mingw environment with Qt5.6.1 & GCC 4.8 - Ubuntu 1404, 1510, 1604, 1804, 1904 - Mac OS X / Homebrew - - ParrotOS - - WSL (Windows subsystem linux) on Windows 10 + - ParrotOS, Gentoo, Pentoo, Kali, Nethunter, Archlinux, Fedora + - WSL, WSL2 (Windows subsystem linux) on Windows 10 - Docker container If you intend to contribute to the code, please read the [coding style notes](HACKING.md) first. - Internal notes on [Coverity Scan Config & Run](/doc/md/Development/Coverity-Scan-Config-%26-Run.md). -- Internal notes on UART -- Internal notes on Frame format -- Internal notes on standalone mode +- Internal notes on [UART](/doc/uart_notes.md) +- Internal notes on [Frame format](/doc/new_frame_format.md) +- Internal notes on [external flash](/doc/ext_flash_notes.md) +- Internal notes on [standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode) +- Internal notes on [Termux / Android](/doc/termux_notes.md) +- Internal notes on [Wireshark / tracedata](/doc/trace_wireshark_notes.md) +- Internal notes on [loclass](/doc/loclass_notes.md) +- Internal notes on [EMV](/doc/emv_notes.md) +- Internal notes on [Paths](/doc/path_notes.md) +## Cheat sheet +Thanks to Alex Dibs, you can enjoy a [command cheat sheet](/doc/cheatsheet.md) + +## Maintainers ( package, distro ) + +To all distro, package maintainers, we tried to make your life easier. `make install` is now available and if you want to know more. +- [Maintainers](/doc/md/Development/Maintainers.md) ## Why didn't you base it on official Proxmark3 Master? The separation from official Proxmark3 repo gives us a lot of freedom to create a firmware/client that suits the RDV40 features. We don't want to mess up the official Proxmark3 repo with RDV40 specific code. ## Proxmark3 GUI + The official PM3-GUI from Gaucho will not work. The new universal GUI will work. [Proxmark3 Universal GUI](https://github.com/burma69/PM3UniversalGUI) Almost, change needed in order to show helptext when client isn't connected to a device. @@ -73,6 +98,7 @@ It's needed to have a good USB cable to connect Proxmark3 to USB. If you have st - updated Feb 2019 [@5w0rdfish](https://mobile.twitter.com/5w0rdFish) # Donations + Nothing says thank you as much as a donation. So if you feel the love, do feel free to become a iceman patron. For some tiers it comes with rewards. https://www.patreon.com/iceman1001 diff --git a/appveyor.yml b/appveyor.yml index 3b937c197..af725ef93 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -73,14 +73,77 @@ clone_script: Write-Host "[ OK ]" -ForegroundColor Green - Write-Host "Update msys2 packages..." -NoNewLine + Write-Host "Update msys2 packages..." $env:Path = "C:\ProxSpace\msys2\usr\bin;C:\ProxSpace\msys2\mingw32\bin;C:\ProxSpace\gcc-arm-none-eabi\bin;$env:Path" + + Function ExecUpdate($Name, $Cmd, $ErrorLine) { - C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null 1> msys1.txt 2>&1 + Write-Host "Exec [$Name]... " -NoNewLine + #--- begin Job + + $Job = Start-Job -Name "$Name" -ScriptBlock { + $env:Path = "C:\ProxSpace\msys\bin;$env:Path" + Set-Location $using:PWD - C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null 1> msys1.txt 2>&1 + $sb=[scriptblock]::Create("$using:Cmd") + #execute scriptblock + $Cond=&$sb + return $Cond + } + + #--- end Job + + $JobTime=[System.Environment]::TickCount + while($true) { + Try { + $Res = Receive-Job -Job $Job -Keep 2>&1 6>&1 + } + Catch { + $Res = "" + Write-host "error in Receive-Job" + } + + if ($Res -is "String" -and $Res -like "*$ErrorLine*"){ + Write-host "Exit by stop phrase" -ForegroundColor Green + break + } + + if ($Res -is [Object]){ + [bool]$needexit = $false + ForEach($line in $Res){ + if ($line -like "*$ErrorLine*"){ + Write-host "Exit by stop phrase [obj]" -ForegroundColor Green + $needexit = $true + break + } + } + if ($needexit) { + break + } + } + + if(Wait-Job $Job -Timeout 5){ + Write-host "Exit by end job" -ForegroundColor Green + break + } + + if ([System.Environment]::TickCount-$JobTime -gt 1000000) { + Write-host "Exit by timeout" -ForegroundColor Yellow + break + } + } + + Remove-Job -Force $Job + } + + ExecUpdate "update1" "C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null" "terminate?MSYS2" + + ExecUpdate "update2" "C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null" "terminate?MSYS2" + + Write-Host "Update " -NoNewLine + Write-Host "[ OK ]" -ForegroundColor Green install: - ps: >- @@ -130,54 +193,38 @@ build_script: } - if(!(Test-Path C:\ProxSpace\pm3\client\hardnested\tables\*.bin.z)){ + if(!(Test-Path C:\ProxSpace\pm3\client\resources\hardnested_tables\*.bin.z)){ - throw "Files in hardnested\tables not exists." + throw "Files in client\resources\hardnested_tables is not exists." } - #copy + #install - Write-Host "Copy release files..." -NoNewLine -ForegroundColor Yellow + Write-Host "Installing..." -NoNewLine -ForegroundColor Yellow - New-Item -ItemType Directory -Force -Path C:\ProxSpace\Release + New-Item -ItemType Directory -Force -Path C:\ProxSpace\pm3\Release\bin - Copy-Item C:\ProxSpace\pm3\client\*.exe C:\ProxSpace\Release + bash -c -i 'make install DESTDIR=Release PREFIX=' - New-Item -ItemType Directory -Force -Path C:\ProxSpace\Release\arm - - Copy-Item C:\ProxSpace\pm3\armsrc\obj\*.elf C:\ProxSpace\Release\arm - - Copy-Item C:\ProxSpace\pm3\bootrom\obj\*.elf C:\ProxSpace\Release\arm - - New-Item -ItemType Directory -Force -Path C:\ProxSpace\Release\scripts - - Copy-Item C:\ProxSpace\pm3\client\scripts\*.lua C:\ProxSpace\Release\scripts - - New-Item -ItemType Directory -Force -Path C:\ProxSpace\Release\hardnested\tables - - Copy-Item C:\ProxSpace\pm3\client\hardnested\*.bin C:\ProxSpace\Release\hardnested - - Copy-Item C:\ProxSpace\pm3\client\hardnested\tables\*.bin.z C:\ProxSpace\Release\hardnested\tables - # dll files - Copy-Item C:\ProxSpace\msys2\mingw32\bin\libgcc_s_dw2-1.dll C:\ProxSpace\Release + Copy-Item C:\ProxSpace\msys2\mingw32\bin\libgcc_s_dw2-1.dll C:\ProxSpace\pm3\Release\bin - Copy-Item C:\ProxSpace\msys2\mingw32\bin\libstdc++-6.dll C:\ProxSpace\Release + Copy-Item C:\ProxSpace\msys2\mingw32\bin\libstdc++-6.dll C:\ProxSpace\pm3\Release\bin - Copy-Item C:\ProxSpace\msys2\mingw32\bin\libwinpthread-1.dll C:\ProxSpace\Release + Copy-Item C:\ProxSpace\msys2\mingw32\bin\libwinpthread-1.dll C:\ProxSpace\pm3\Release\bin - Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Core.dll C:\ProxSpace\Release + Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Core.dll C:\ProxSpace\pm3\Release\bin - Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Gui.dll C:\ProxSpace\Release + Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Gui.dll C:\ProxSpace\pm3\Release\bin - Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Widgets.dll C:\ProxSpace\Release + Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Widgets.dll C:\ProxSpace\pm3\Release\bin - Copy-Item C:\ProxSpace\msys2\mingw32\bin\libreadline*.dll C:\ProxSpace\Release + Copy-Item C:\ProxSpace\msys2\mingw32\bin\libreadline*.dll C:\ProxSpace\pm3\Release\bin - Copy-Item C:\ProxSpace\msys2\mingw32\bin\libtermcap-0.dll C:\ProxSpace\Release + Copy-Item C:\ProxSpace\msys2\mingw32\bin\libtermcap-0.dll C:\ProxSpace\pm3\Release\bin Write-Host "[ OK ]" -ForegroundColor Green @@ -199,7 +246,7 @@ build_script: cd C:\ProxSpace - 7z a release.zip C:\ProxSpace\Release + 7z a release.zip C:\ProxSpace\pm3\Release Push-AppveyorArtifact release.zip -DeploymentName "$releasename" @@ -218,7 +265,7 @@ test_script: Function ExecTest($Name, $File, $Cmd, $CheckResult) { - + #--- begin Job $Job = Start-Job -ScriptBlock { @@ -256,6 +303,13 @@ test_script: if ($Cond -is "String" -and $Cond -like "*true*"){ $res= $true } + ForEach($line in $Cond){ + if ($line -like "*passed*"){ + $res = $true + $Cond = $line + break + } + } } Else { $res=$Cond } @@ -287,6 +341,7 @@ test_script: Remove-Job -Force $Job if(!$res){ + Write-host "--------------------- tests fail" -ForegroundColor Red $global:TestsPassed=$false } } @@ -297,30 +352,34 @@ test_script: #file test - ExecTest "proxmark3 exists" "proxmark3.exe" {Test-Path C:\ProxSpace\Release\proxmark3.exe} + ExecTest "proxmark3 exists" "proxmark3.exe" {Test-Path C:\ProxSpace\pm3\Release\bin\proxmark3.exe} - ExecTest "arm image exists" "\arm\fullimage1.elf" {Test-Path C:\ProxSpace\Release\arm\fullimage.elf} + ExecTest "arm bootrom exists" "bootrom.elf" {Test-Path C:\ProxSpace\pm3\Release\share\proxmark3\firmware\bootrom.elf} - ExecTest "bootrom exists" "bootrom.elf" {Test-Path C:\ProxSpace\Release\arm\bootrom.elf} + ExecTest "arm image exists" "fullimage.elf" {Test-Path C:\ProxSpace\pm3\Release\share\proxmark3\firmware\fullimage.elf} - ExecTest "hardnested tables exists" "hardnested" {Test-Path C:\ProxSpace\Release\hardnested\tables\*.z} + ExecTest "arm recovery image exists" "proxmark3_recovery.bin" {Test-Path C:\ProxSpace\pm3\Release\share\proxmark3\firmware\proxmark3_recovery.bin} + + ExecTest "hardnested tables exists" "hardnested" {Test-Path C:\ProxSpace\pm3\Release\share\proxmark3\resources\hardnested_tables\*.z} ExecTest "release exists" "release.zip" {Test-Path C:\ProxSpace\release.zip} #proxmark logic tests - ExecTest "proxmark help" "proxmark3 -h" {bash -lc 'cd ~/client;./proxmark3 -h | grep -q wait && echo Passed || echo Failed'} + ExecTest "proxmark help" "proxmark3 -h" {bash -lc 'cd ~/client;./proxmark3 -h 2>&1 | grep -q wait && echo passed || echo failed'} - ExecTest "proxmark help text ISO7816" "proxmark3 -t" {bash -lc 'cd ~/client;./proxmark3 -t 2>&1 | grep -q ISO7816 && echo Passed || echo Failed'} + ExecTest "proxmark help text ISO7816" "proxmark3 -t" {bash -lc 'cd ~/client;./proxmark3 -t 2>&1 | grep -q ISO7816 && echo passed || echo failed'} - ExecTest "proxmark help text hardnested" "proxmark3 -t" {bash -lc 'cd ~/client;./proxmark3 -t 2>&1 | grep -q hardnested && echo Passed || echo Failed'} + ExecTest "proxmark help text hardnested" "proxmark3 -t" {bash -lc 'cd ~/client;./proxmark3 -t 2>&1 | grep -q hardnested && echo passed || echo failed'} ExecTest "hf mf offline text" "hf mf" {bash -lc "cd ~/client;./proxmark3 -c 'hf mf'"} "at_enc" ExecTest "hf mf hardnested" "hf mf hardnested" {bash -lc "cd ~/client;./proxmark3 -c 'hf mf hardnested t 1 000000000000'"} "found:" + ExecTest "hf mf iclass" "hf mf iclass" {bash -lc "cd ~/client;./proxmark3 -c 'hf iclass loclass t'"} "verified ok" + #proxmark crypto tests diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index 7b199930a..a0a25d1fe 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -10,6 +10,9 @@ //----------------------------------------------------------------------------- #include "BigBuf.h" +#include "string.h" +#include "dbprint.h" + // BigBuf is the large multi-purpose buffer, typically used to hold A/D samples or traces. // Also used to hold various smaller buffers and the Mifare Emulator Memory. // declare it as uint32_t to achieve alignment to 4 Byte boundary diff --git a/armsrc/BigBuf.h b/armsrc/BigBuf.h index 12f2521c6..ad967c4c7 100644 --- a/armsrc/BigBuf.h +++ b/armsrc/BigBuf.h @@ -12,10 +12,7 @@ #ifndef __BIGBUF_H #define __BIGBUF_H -#include // for bool -#include "proxmark3.h" -#include "string.h" -#include "ticks.h" +#include "common.h" #define BIGBUF_SIZE 40000 #define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame @@ -43,4 +40,5 @@ void set_tracelen(uint32_t value); bool get_tracing(void); bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length); + #endif /* __BIGBUF_H */ diff --git a/armsrc/LCD.c b/armsrc/LCD_disabled.c similarity index 100% rename from armsrc/LCD.c rename to armsrc/LCD_disabled.c diff --git a/armsrc/LCD.h b/armsrc/LCD_disabled.h similarity index 98% rename from armsrc/LCD.h rename to armsrc/LCD_disabled.h index 968c90246..ed765298f 100644 --- a/armsrc/LCD.h +++ b/armsrc/LCD_disabled.h @@ -9,10 +9,6 @@ #ifndef __LCD_H #define __LCD_H -#include "proxmark3.h" -#include "apps.h" -#include "fonts.h" - // The resolution of the LCD #define LCD_XRES 132 #define LCD_YRES 132 diff --git a/armsrc/Makefile b/armsrc/Makefile index 105a880a7..f94868b6e 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -2,16 +2,14 @@ # at your option, any later version. See the LICENSE.txt file for the text of # the license. #----------------------------------------------------------------------------- -# Makefile for armsrc, see ../common/Makefile.common for common settings +# Makefile for armsrc, see ../common_arm/Makefile.common for common settings #----------------------------------------------------------------------------- -APP_INCLUDES = apps.h - # This Makefile might have been called directly, not via the root Makefile, so: ifeq ($(PLTNAME),) -include ../Makefile.platform -include ../.Makefile.options.cache - include ../common/Makefile.hal + include ../common_arm/Makefile.hal # detect if there were changes in the platform definitions, requiring a clean ifeq ($(PLATFORM_CHANGED), true) $(error platform definitions have been changed, please "make clean" at the root of the project) @@ -28,20 +26,24 @@ APP_CFLAGS = $(PLATFORM_DEFS) \ SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c +#UNUSED: mifaresniff.c desfire_crypto.c SRC_ISO14443b = iso14443b.c SRC_FELICA = felica.c -SRC_CRAPTO1 = crypto1.c des.c desfire_key.c desfire_crypto.c mifaredesfire.c aes.c platform_util.c +SRC_CRAPTO1 = crypto1.c des.c desfire_key.c mifaredesfire.c aes.c platform_util.c SRC_CRC = crc.c crc16.c crc32.c SRC_ICLASS = iclass.c optimized_cipher.c SRC_LEGIC = legicrf.c legicrfsim.c legic_prng.c -SRC_SPIFFS = spiffs.c spiffs_cache.c spiffs_check.c spiffs_gc.c spiffs_nucleus.c spiffs_hydrogen.c +SRC_NFCBARCODE = thinfilm.c + # SRC_BEE = bee.c # RDV40 related hardware support ifneq (,$(findstring WITH_FLASH,$(APP_CFLAGS))) SRC_FLASH = flashmem.c + SRC_SPIFFS = spiffs.c spiffs_cache.c spiffs_check.c spiffs_gc.c spiffs_nucleus.c spiffs_hydrogen.c else SRC_FLASH = + SRC_SPIFFS = endif ifneq (,$(findstring WITH_SMARTCARD,$(APP_CFLAGS))) @@ -80,7 +82,7 @@ SRC_ZLIB = inflate.c inffast.c inftrees.c adler32.c zutil.c ZLIB_CFLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED APP_CFLAGS += $(ZLIB_CFLAGS) # zlib includes: -APP_CFLAGS += -I../zlib +APP_CFLAGS += -I../common/zlib # stdint.h provided locally until GCC 4.5 becomes C99 compliant, # stack-protect , no-pie reduces size on Gentoo Hardened 8.2 gcc @@ -88,9 +90,9 @@ APP_CFLAGS += -I. -fno-stack-protector -fno-pie # Compile these in thumb mode (small size) THUMBSRC = start.c \ - protocols.c \ $(SRC_LCD) \ $(SRC_ISO15693) \ + $(SRC_NFCBARCODE) \ $(SRC_LF) \ $(SRC_ZLIB) \ $(SRC_LEGIC) \ @@ -101,6 +103,7 @@ THUMBSRC = start.c \ $(SRC_SPIFFS) \ appmain.c \ printf.c \ + dbprint.c \ commonutil.c \ util.c \ string.c \ @@ -127,12 +130,19 @@ VERSIONSRC = version.c \ fpga_version_info.c # Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC -include ../common/Makefile.common +include ../common_arm/Makefile.common COMMON_FLAGS = -Os +INSTALLFW = $(OBJDIR)/fullimage.elf +ifneq (,$(FWTAG)) + INSTALLFWTAG = $(notdir $(INSTALLFW:%.elf=%-$(FWTAG).elf)) +else + INSTALLFWTAG = $(notdir $(INSTALLFW)) +endif + OBJS = $(OBJDIR)/fullimage.s19 -FPGA_COMPRESSOR = ../client/fpga_compress +FPGA_COMPRESSOR = ../tools/fpga_compress/fpga_compress all: $(OBJS) @@ -141,9 +151,9 @@ all: $(OBJS) # version.c should be remade on every time fullimage.stage1.elf should be remade version.c: default_version.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) $(info [-] GEN $@) - $(Q)perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@ + $(Q)sh ../tools/mkversion.sh > $@ || perl ../tools/mkversion.pl > $@ || $(CP) $^ $@ -fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) +fpga_version_info.c: $(FPGA_BITSTREAMS) | $(FPGA_COMPRESSOR) $(info [-] GEN $@) $(Q)$(FPGA_COMPRESSOR) -v $(filter %.bit,$^) $@ @@ -151,7 +161,7 @@ $(OBJDIR)/fpga_all.o: $(OBJDIR)/fpga_all.bit.z $(info [-] GEN $@) $(Q)$(OBJCOPY) -O elf32-littlearm -I binary -B arm --prefix-sections=fpga_all_bit $^ $@ -$(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) +$(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) | $(FPGA_COMPRESSOR) $(info [-] GEN $@) ifeq ($(Q),@) @$(FPGA_COMPRESSOR) $(filter %.bit,$^) $@ >/dev/null @@ -160,8 +170,8 @@ else endif $(FPGA_COMPRESSOR): - $(info [*] MAKE $@) - $(Q)$(MAKE) --no-print-directory -C ../client $(notdir $(FPGA_COMPRESSOR)) + $(error [!] MISSING $@ => To build it, go the root of the repo and do "make $(notdir $@)") + $(error [!] MISSING $@) $(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) $(info [=] LD $@) @@ -179,7 +189,7 @@ $(OBJDIR)/fullimage.data.bin: $(OBJDIR)/fullimage.stage1.elf $(info [-] GEN $@) $(Q)$(OBJCOPY) -O binary -I elf32-littlearm --only-section .data $^ $@ -$(OBJDIR)/fullimage.data.bin.z: $(OBJDIR)/fullimage.data.bin $(FPGA_COMPRESSOR) +$(OBJDIR)/fullimage.data.bin.z: $(OBJDIR)/fullimage.data.bin | $(FPGA_COMPRESSOR) $(info [-] GEN $@) ifeq ($(Q),@) @$(FPGA_COMPRESSOR) $(filter %.bin,$^) $@ >/dev/null @@ -200,18 +210,29 @@ tarbin: $(OBJS) $(Q)$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=armsrc/%) $(OBJS:%.s19=armsrc/%.elf) clean: - $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.o - $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.elf - $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.s19 - $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.map - $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.d - $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.z - $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.bin - $(Q)$(DELETE) version.c + $(Q)$(RM) $(DEPENDENCY_FILES) + $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.o + $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.elf + $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.s19 + $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.map + $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.d + $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.z + $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.bin + $(Q)$(RM) version.c -.PHONY: all clean help +install: all + $(info [@] Installing fullimage to $(DESTDIR)$(PREFIX)...) + $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH) + $(Q)$(CP) $(INSTALLFW) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(INSTALLFWTAG) + +uninstall: + $(info [@] Uninstalling fullimage from $(DESTDIR)$(PREFIX)...) + $(Q)$(RM) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(INSTALLFWTAG) + +.PHONY: all clean help install uninstall help: @echo Multi-OS Makefile, you are running on $(DETECTED_OS) @echo Possible targets: @echo + all - Build the full image $(OBJDIR)/fullimage.s19 @echo + clean - Clean $(OBJDIR) + diff --git a/armsrc/Standalone/Makefile.hal b/armsrc/Standalone/Makefile.hal index 5d3904794..f082dd117 100644 --- a/armsrc/Standalone/Makefile.hal +++ b/armsrc/Standalone/Makefile.hal @@ -1,6 +1,6 @@ # Default standalone if no standalone specified DEFAULT_STANDALONE=LF_SAMYRUN -HELP_EXAMPLE_STANDALONE=HF_COLIN +HELP_EXAMPLE_STANDALONE=HF_YOUNG # (you can set explicitly STANDALONE= to disable standalone modes) STANDALONE?=$(DEFAULT_STANDALONE) STANDALONE_REQ_DEFS= diff --git a/armsrc/Standalone/Makefile.inc b/armsrc/Standalone/Makefile.inc index cc7221a73..66dfc6da2 100644 --- a/armsrc/Standalone/Makefile.inc +++ b/armsrc/Standalone/Makefile.inc @@ -27,7 +27,7 @@ ifneq (,$(findstring WITH_STANDALONE_HF_MATTYRUN,$(APP_CFLAGS))) endif # WITH_STANDALONE_HF_COLIN ifneq (,$(findstring WITH_STANDALONE_HF_COLIN,$(APP_CFLAGS))) - SRC_STANDALONE = vtsend.c hf_colin.c + SRC_STANDALONE = vtsend.c hf_colin.c frozen.c nprintf.c endif # WITH_STANDALONE_HF_BOG ifneq (,$(findstring WITH_STANDALONE_HF_BOG,$(APP_CFLAGS))) diff --git a/armsrc/Standalone/hf_bog.c b/armsrc/Standalone/hf_bog.c index f8f832220..dc5c2e071 100644 --- a/armsrc/Standalone/hf_bog.c +++ b/armsrc/Standalone/hf_bog.c @@ -19,7 +19,18 @@ you can simply run 'script run read_pwd_mem' or just 'mem dump p l 256' from the client to view the stored quadlets. */ -#include "hf_bog.h" +#include "standalone.h" // standalone definitions +#include "proxmark3_arm.h" +#include "iso14443a.h" +#include "protocols.h" +#include "util.h" +#include "spiffs.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "dbprint.h" +#include "ticks.h" +#include "BigBuf.h" +#include "string.h" #define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8) #define DELAY_TAG_AIR2ARM_AS_SNIFFER (3 + 14 + 8) @@ -62,10 +73,10 @@ void RAMFUNC SniffAndStore(uint8_t param) { bool ReaderIsActive = false; // Set up the demodulator for tag -> reader responses. - DemodInit(receivedResp, receivedRespPar); + Demod14aInit(receivedResp, receivedRespPar); // Set up the demodulator for the reader -> tag commands - UartInit(receivedCmd, receivedCmdPar); + Uart14aInit(receivedCmd, receivedCmdPar); // Setup and start DMA. if (!FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE)) { @@ -74,8 +85,8 @@ void RAMFUNC SniffAndStore(uint8_t param) { return; } - tUart *uart = GetUart(); - tDemod *demod = GetDemod(); + tUart14a *uart = GetUart14a(); + tDemod14a *demod = GetDemod14a(); // We won't start recording the frames that we acquire until we trigger; // a good trigger condition to get started is probably when we see a @@ -153,13 +164,13 @@ void RAMFUNC SniffAndStore(uint8_t param) { break; } /* ready to receive another command. */ - UartReset(); + Uart14aReset(); /* reset the demod code, which might have been */ /* false-triggered by the commands from the reader. */ - DemodReset(); + Demod14aReset(); LED_B_OFF(); } - ReaderIsActive = (uart->state != STATE_UNSYNCD); + ReaderIsActive = (uart->state != STATE_14A_UNSYNCD); } // no need to try decoding tag data if the reader is sending - and we cannot afford the time @@ -176,13 +187,13 @@ void RAMFUNC SniffAndStore(uint8_t param) { triggered = true; // ready to receive another response. - DemodReset(); + Demod14aReset(); // reset the Miller decoder including its (now outdated) input buffer - UartReset(); + Uart14aReset(); // UartInit(receivedCmd, receivedCmdPar); LED_C_OFF(); } - TagIsActive = (demod->state != DEMOD_UNSYNCD); + TagIsActive = (demod->state != DEMOD_14A_UNSYNCD); } } @@ -218,7 +229,7 @@ void RAMFUNC SniffAndStore(uint8_t param) { if (DBGLEVEL > 1) Dbprintf("[!] Wrote %u Authentification attempts into logfile", auth_attempts); - SpinErr(0, 200, 5); // blink led A + SpinErr(LED_A, 200, 5); SpinDelay(100); } diff --git a/armsrc/Standalone/hf_bog.h b/armsrc/Standalone/hf_bog.h deleted file mode 100644 index 50bdf2df8..000000000 --- a/armsrc/Standalone/hf_bog.h +++ /dev/null @@ -1,27 +0,0 @@ -//----------------------------------------------------------------------------- -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// StandAlone Mod -//----------------------------------------------------------------------------- - -#ifndef __HF_BOG_H -#define __HF_BOG_H - -#include "proxmark3.h" -#include "mifareutil.h" -#include "iso14443a.h" -#include "protocols.h" -#include "util.h" -#include "standalone.h" // standalone definitions -#include // for bool -#include -#include -#include "apps.h" -#include "printf.h" -#include "parity.h" -#include "spiffs.h" - - -#endif /* __HF_BOG_H */ diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index 5eeb2a42a..4997f775e 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -8,12 +8,78 @@ //----------------------------------------------------------------------------- // main code for HF Mifare aka ColinRun by Colin Brigato //----------------------------------------------------------------------------- + +#include "standalone.h" // standalone definitions + #include "hf_colin.h" +#include "proxmark3_arm.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "dbprint.h" +#include "ticks.h" +#include "util.h" +#include "commonutil.h" +#include "BigBuf.h" +#include "iso14443a.h" +#include "mifareutil.h" +#include "mifaresim.h" +#include "vtsend.h" +#include "spiffs.h" +#include "frozen.h" #define MF1KSZ 1024 #define MF1KSZSIZE 64 #define AUTHENTICATION_TIMEOUT 848 #define HFCOLIN_LASTTAG_SYMLINK "hf_colin/lasttag.bin" +#define HFCOLIN_SCHEMAS_JSON "hf_colin/schemas.json" + +/* Example jsonconfig file schemas.json : (array !) +[{ + "name": "UrmetCaptive", + "trigger": "0x8829da9daf76", + "keysA": [ + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76" + ], + "keysB": [ + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76", + "0x8829da9daf76" + ] +},{ + "name": "Noralsy", +... + +] + +*/ uint8_t cjuid[10]; uint32_t cjcuid; @@ -27,6 +93,56 @@ int curlline; // Colin's VIGIKPWN sniff/simulate/clone repeat routine for HF Mifare +static const uint8_t is_hex[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, + 0, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static inline uint64_t hex2i(const char *s) { + uint64_t val = 0; + if (s == NULL || s[0] == 0) + return 0; + if (s[1] == 'x') + s += 2; + else if (*s == 'x') + s++; + while (is_hex[(uint8_t)*s]) + val = (val << 4) | (is_hex[(uint8_t) * (s++)] - 1); + return val; +} + +/*char *noralsy2test = + "{\"name\":\"noralsy2\",\"trigger\":\"0x414C41524F4E\",\"keysA\":[\"0x414C41524F4E\",\"0x414C41524F4E\"," + "\"0x414C41524F4E\"," + "\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\"," + "\"0x414C41524F4E\",\"0x414C41524F4E\"," + "\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\"," + "\"0x414C41524F4E\"],\"keysB\":[" + "\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\"," + "\"0x424C41524F4E\",\"0x424C41524F4E\"," + "\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\"," + "\"0x424C41524F4E\",\"0x424C41524F4E\"," + "\"0x424C41524F4E\",\"0x424C41524F4E\"]}";*/ + +/*char *urmetcaptive2test = + "{\"name\":\"urmetcaptive2\",\"trigger\":\"0x8829da9daf76\",\"keysA\":[\"0x8829da9daf76\",\"0x8829da9daf76\"," + "\"0x8829da9daf76\"," + "\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\"," + "\"0x8829da9daf76\",\"0x8829da9daf76\"," + "\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\"," + "\"0x8829da9daf76\"],\"keysB\":[" + "\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\"," + "\"0x8829da9daf76\",\"0x8829da9daf76\"," + "\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\"," + "\"0x8829da9daf76\",\"0x8829da9daf76\"," + "\"0x8829da9daf76\",\"0x8829da9daf76\"]}";*/ + typedef struct MFC1KSchema { uint8_t name[32]; uint64_t trigger; @@ -36,50 +152,49 @@ typedef struct MFC1KSchema { #define MAX_SCHEMAS 4 +static void scan_keys(const char *str, int len, uint64_t *user_data) { + struct json_token t; + int i; + char ks[32]; + for (i = 0; json_scanf_array_elem(str, len, "", i, &t) > 0; i++) { + sprintf(ks, "%.*s", t.len, t.ptr); + user_data[i] = hex2i(ks); + } +} + MFC1KSchema Schemas[MAX_SCHEMAS]; -MFC1KSchema Noralsy = { +/*MFC1KSchema Noralsy = { .name = "Noralsy", .trigger = 0x414c41524f4e, - .keysA = { - 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, - 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, - 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e - }, - .keysB = { - 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, - 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, - 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e - } -}; + .keysA = {0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, + 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, + 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e}, + .keysB = {0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, + 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, + 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e}}; MFC1KSchema InfiHexact = {.name = "Infineon/Hexact", .trigger = 0x484558414354, .keysA = {0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, - 0x484558414354 - }, + 0x484558414354}, .keysB = {0xa22ae129c013, 0x49fae4e3849f, 0x38fcf33072e0, 0x8ad5517b4b18, 0x509359f131b1, 0x6c78928e1317, 0xaa0720018738, 0xa6cac2886412, 0x62d0c424ed8e, 0xe64a986a5d94, - 0x8fa1d601d0a2, 0x89347350bd36, 0x66d2b7dc39ef, 0x6bc1e1ae547d, 0x22729a9bd40f - } - }; + 0x8fa1d601d0a2, 0x89347350bd36, 0x66d2b7dc39ef, 0x6bc1e1ae547d, 0x22729a9bd40f}}; +*/ -MFC1KSchema UrmetCaptive = { +/*MFC1KSchema UrmetCaptive = { .name = "Urmet Captive", .trigger = 0x8829da9daf76, - .keysA = { - 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, - 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, - 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76 - }, - .keysB = { - 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, - 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, - 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76 - } -}; + .keysA = {0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, + 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, + 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76}, + .keysB = {0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, + 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, + 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76}}; +*/ int total_schemas = 0; @@ -125,6 +240,41 @@ foundKey[5]); cjSetCursRight(); DbprintfEx(FLAG_NEWLINE, "SEC: %02x | KEY : %s | } */ +char *ReadSchemasFromSPIFFS(char *filename) { + SpinOff(0); + + int changed = rdv40_spiffs_lazy_mount(); + uint32_t size = size_in_spiffs((char *)filename); + uint8_t *mem = BigBuf_malloc(size); + rdv40_spiffs_read_as_filetype((char *)filename, (uint8_t *)mem, size, RDV40_SPIFFS_SAFETY_SAFE); + + if (changed) { + rdv40_spiffs_lazy_unmount(); + } + SpinOff(0); + return (char *)mem; +} + +void add_schemas_from_json_in_spiffs(char *filename) { + + char *jsonfile = ReadSchemasFromSPIFFS((char *)filename); + + int i, len = strlen(jsonfile); + struct json_token t; + for (i = 0; json_scanf_array_elem(jsonfile, len, "", i, &t) > 0; i++) { + char *tmpname; + char *tmptrigger; + MFC1KSchema tmpscheme; + json_scanf(t.ptr, t.len, "{ name:%Q, trigger:%Q, keysA:%M, keysB:%M}", &tmpname, &tmptrigger, scan_keys, + &tmpscheme.keysA, scan_keys, &tmpscheme.keysB); + memcpy(tmpscheme.name, tmpname, 32); + tmpscheme.trigger = hex2i(tmptrigger); + add_schema(Schemas, tmpscheme, &total_schemas); + DbprintfEx(FLAG_NEWLINE, "Schema loaded : %s", tmpname); + cjSetCursLeft(); + } +} + void ReadLastTagFromFlash() { SpinOff(0); LED_A_ON(); @@ -168,8 +318,8 @@ void WriteTagToFlash(uint32_t uid, size_t size) { sprintf(dest, "hf_colin/mf_%02x%02x%02x%02x.bin", buid[0], buid[1], buid[2], buid[3]); // TODO : by using safe function for multiple writes we are both breaking cache mecanisms and making useless and - // unoptimized mount operations we should manage at out level the mount status before and after the whole standalone - // mode + // unoptimized mount operations we should manage at out level the mount status before and after the whole + // standalone mode rdv40_spiffs_write((char *)dest, (uint8_t *)data, len, RDV40_SPIFFS_SAFETY_SAFE); // lastag will only contain filename/path to last written tag file so we don't loose time or space. rdv40_spiffs_make_symlink((char *)dest, (char *)HFCOLIN_LASTTAG_SYMLINK, RDV40_SPIFFS_SAFETY_SAFE); @@ -185,10 +335,10 @@ void ModInfo(void) { DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIG void RunMod() { StandAloneMode(); - add_schema(Schemas, Noralsy, &total_schemas); - add_schema(Schemas, InfiHexact, &total_schemas); - add_schema(Schemas, UrmetCaptive, &total_schemas); - + // add_schema(Schemas, Noralsy, &total_schemas); + // add_schema(Schemas, InfiHexact, &total_schemas); + // add_schema_from_json_in_spiffs((char *)HFCOLIN_URMETCAPTIVE_JSON); + // add_schema(Schemas, UrmetCaptive, &total_schemas); FpgaDownloadAndGo(FPGA_BITSTREAM_HF); currline = 20; @@ -242,9 +392,7 @@ void RunMod() { // French VIGIK system @2017 //---------------------------- -#define STKEYS 37 - - const uint64_t mfKeys[STKEYS] = { + const uint64_t mfKeys[] = { 0xffffffffffff, // TRANSPORTS 0x000000000000, // Blankkey 0x484558414354, // INFINEONON A / 0F SEC B / INTRATONE / HEXACT... @@ -285,8 +433,8 @@ void RunMod() { }; // Can remember something like that in case of Bigbuf - keyBlock = BigBuf_malloc(STKEYS * 6); - int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t); + keyBlock = BigBuf_malloc(ARRAYLEN(mfKeys) * 6); + int mfKeysCnt = ARRAYLEN(mfKeys); for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) { num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6)); @@ -325,6 +473,8 @@ void RunMod() { currfline = 24; cjSetCursLeft(); + add_schemas_from_json_in_spiffs((char *)HFCOLIN_SCHEMAS_JSON); + failtag: vtsend_cursor_position_save(NULL); @@ -368,7 +518,7 @@ failtag: if (cjcuid == 0) { cjSetCursLeft(); DbprintfEx(FLAG_NEWLINE, "%s>>%s BUG: 0000_CJCUID! Retrying...", _XRED_, _XWHITE_); - SpinErr(0, 100, 8); + SpinErr(LED_A, 100, 8); goto failtag; } @@ -419,8 +569,8 @@ failtag: if (key == -1) { err = 1; allKeysFound = false; - // used in portable imlementation on microcontroller: it reports back the fail and open the standalone - // lock reply_old(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); + // used in portable imlementation on microcontroller: it reports back the fail and open the + // standalone lock reply_old(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); break; } else if (key == -2) { err = 1; // Can't select card. @@ -486,7 +636,7 @@ failtag: cjTabulize(); DbprintfEx(FLAG_NEWLINE, "%s[ FAIL ]%s\r\n->did not found all the keys :'(", _XRED_, _XWHITE_); cjSetCursLeft(); - SpinErr(1, 100, 8); + SpinErr(LEB_B, 100, 8); SpinOff(100); return; } @@ -522,7 +672,7 @@ failtag: cjSetCursLeft(); DbprintfEx(FLAG_NEWLINE, "FATAL:EML_FALLBACKFILL_B"); - SpinErr(2, 100, 8); + SpinErr(LED_C, 100, 8); SpinOff(100); return; } @@ -567,8 +717,10 @@ readysim: SpinOff(100); LED_C_ON(); - uint16_t flags; - switch (p_card.uidlen) { + DBGLEVEL = DBG_NONE; + + //uint16_t flags=0; + /*switch (p_card.uidlen) { case 10: flags = FLAG_10B_UID_IN_DATA; break; @@ -581,13 +733,23 @@ readysim: default: flags = FLAG_UID_IN_EMUL; break; - } + }*/ // Use UID, SAK, ATQA from EMUL, if uid not defined // if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) { - flags |= FLAG_UID_IN_EMUL; + //flags |= FLAG_UID_IN_EMUL; //} - Mifare1ksim(flags | FLAG_MF_1K, 0, cjuid); + //flags |= FLAG_MF_1K; + //if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) { + // flags |= FLAG_UID_IN_EMUL; + //} + //flags = 0x10; + uint16_t flags = 0; + flags = 16; + DbprintfEx(FLAG_NEWLINE, "\n\n\n\n\n\n\n\nn\n\nn\n\n\nflags: %d (0x%02x)", flags, flags); + cjSetCursLeft(); + SpinOff(1000); + Mifare1ksim(flags, 0, cjuid, 0, 0); LED_C_OFF(); SpinOff(50); vtsend_cursor_position_restore(NULL); @@ -616,7 +778,7 @@ readysim: DbprintfEx(FLAG_NEWLINE, "- [ LA FIN ] -\r\n%s`-> You can take shell back :) ...", _XWHITE_); cjSetCursLeft(); vtsend_set_attribute(NULL, 0); - SpinErr(3, 100, 16); + SpinErr(LED_D, 100, 16); SpinDown(75); SpinOff(100); return; diff --git a/armsrc/Standalone/hf_colin.h b/armsrc/Standalone/hf_colin.h index e669f0417..a4b870abc 100644 --- a/armsrc/Standalone/hf_colin.h +++ b/armsrc/Standalone/hf_colin.h @@ -9,6 +9,10 @@ // StandAlone Mod //----------------------------------------------------------------------------- +#include +#include +#include + #ifndef FALSE #define FALSE 0 #endif @@ -16,22 +20,6 @@ #ifndef __HF_COLIN_H #define __HF_COLIN_H -#include "proxmark3.h" -#include "mifaresim.h" // mifare1ksim -#include "mifareutil.h" -#include "iso14443a.h" -#include "protocols.h" -#include "util.h" -#include "pmflash.h" -#include "standalone.h" // standalone definitions -#include // for bool -#include -#include -#include "vtsend.h" -#include "apps.h" -#include "printf.h" -#include "spiffs.h" - #define _XRED_ "\x1b[31m" #define _XGREEN_ "\x1b[32m" #define _XYELLOW_ "\x1b[33m" diff --git a/armsrc/Standalone/hf_mattyrun.c b/armsrc/Standalone/hf_mattyrun.c index 9ea0ba524..bf13a39c0 100644 --- a/armsrc/Standalone/hf_mattyrun.c +++ b/armsrc/Standalone/hf_mattyrun.c @@ -33,7 +33,21 @@ on a blank card. ## Spanish full description of the project [here](http://bit.ly/2c9nZXR). */ -#include "hf_mattyrun.h" +#include "standalone.h" // standalone definitions +#include "proxmark3_arm.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "util.h" +#include "dbprint.h" +#include "ticks.h" +#include "string.h" +#include "commonutil.h" +#include "iso14443a.h" +#include "mifarecmd.h" +#include "crc16.h" +#include "BigBuf.h" +#include "mifaresim.h" // mifare1ksim +#include "mifareutil.h" uint8_t uid[10]; uint32_t cuid; @@ -262,7 +276,7 @@ void RunMod() { keys in keyBlock's memory space . */ keyBlock = BigBuf_malloc(stKeyBlock * 6); - int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t); + int mfKeysCnt = ARRAYLEN(mfKeys); for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) { num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6)); @@ -400,7 +414,7 @@ void RunMod() { simflags = FLAG_4B_UID_IN_DATA; break; } - Mifare1ksim(simflags | FLAG_MF_1K, 0, uid); + Mifare1ksim(simflags | FLAG_MF_1K, 0, uid, 0, 0); LED_B_OFF(); /* diff --git a/armsrc/Standalone/hf_mattyrun.h b/armsrc/Standalone/hf_mattyrun.h deleted file mode 100644 index 5577e298a..000000000 --- a/armsrc/Standalone/hf_mattyrun.h +++ /dev/null @@ -1,23 +0,0 @@ -//----------------------------------------------------------------------------- -// Matías A. Ré Medina 2016 -// Christian Herrmann, 2018 -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// StandAlone Mod -//----------------------------------------------------------------------------- - -#ifndef __HF_MATTYRUN_H -#define __HF_MATTYRUN_H - -#include "standalone.h" // standalone definitions -#include "apps.h" // debugstatements, lfops? -#include "pm3_cmd.h" // mifare1ksim flags -#include "mifaresim.h" // mifare1ksim -#include "mifareutil.h" - -#define OPTS 2 - -#endif /* __HF_MATTYRUN_H */ diff --git a/armsrc/Standalone/hf_young.c b/armsrc/Standalone/hf_young.c index 906d0b36c..fcf964a5e 100644 --- a/armsrc/Standalone/hf_young.c +++ b/armsrc/Standalone/hf_young.c @@ -9,8 +9,21 @@ // main code for HF standalone mode Mifare /sniff/emulation by Craig Young //----------------------------------------------------------------------------- -#include "hf_young.h" -#include "common.h" +#include "standalone.h" // standalone definitions +#include +#include "proxmark3_arm.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "util.h" +#include "dbprint.h" +#include "ticks.h" +#include "string.h" +#include "commonutil.h" +#include "mifarecmd.h" +#include "iso14443a.h" +#include "protocols.h" + +#define OPTS 2 typedef struct { uint8_t uid[10]; @@ -138,18 +151,18 @@ void RunMod() { SpinDelay(500); // Begin clone function here: /* Example from client/mifarehost.c for commanding a block write for "magic Chinese" cards: - SendCommandOLD(CMD_MIFARE_CSETBLOCK, params & (0xFE | (uid == NULL ? 0:1)), blockNo, 0, data, 16); + SendCommandOLD(CMD_HF_MIFARE_CSETBL, params & (0xFE | (uid == NULL ? 0:1)), blockNo, 0, data, 16); Block read is similar: - SendCommandOLD(CMD_MIFARE_CGETBLOCK, params, blockNo, 0,...}; + SendCommandOLD(CMD_HF_MIFARE_CGETBL, params, blockNo, 0,...}; We need to imitate that call with blockNo 0 to set a uid. The get and set commands are handled in this file: // Work with "magic Chinese" card - case CMD_MIFARE_CSETBLOCK: + case CMD_HF_MIFARE_CSETBL: MifareCSetBlock(c->arg[0], c->arg[1], c->d.asBytes); break; - case CMD_MIFARE_CGETBLOCK: + case CMD_HF_MIFARE_CGETBL: MifareCGetBlock(c->arg[0], c->arg[1], c->d.asBytes); break; diff --git a/armsrc/Standalone/lf_hidbrute.c b/armsrc/Standalone/lf_hidbrute.c index 2c784c31a..b659bbdf1 100644 --- a/armsrc/Standalone/lf_hidbrute.c +++ b/armsrc/Standalone/lf_hidbrute.c @@ -24,8 +24,19 @@ //----------------------------------------------------------------------------------- // main code for LF aka HID corporate brutefore by Federico Dotta & Maurizio Agazzini //----------------------------------------------------------------------------------- +#include "standalone.h" // standalone definitions #include "lf_hidbrute.h" +#include "proxmark3_arm.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "util.h" +#include "dbprint.h" +#include "ticks.h" +#include "lfops.h" + +#define OPTS 3 + void ModInfo(void) { DbpString(" LF HID corporate 1000 bruteforce - aka Corporatebrute (Federico dotta & Maurizio Agazzini)"); } diff --git a/armsrc/Standalone/lf_hidbrute.h b/armsrc/Standalone/lf_hidbrute.h index 49b0af6c6..72e12d305 100644 --- a/armsrc/Standalone/lf_hidbrute.h +++ b/armsrc/Standalone/lf_hidbrute.h @@ -14,10 +14,7 @@ #ifndef __LF_HIDBRUTE_H #define __LF_HIDBRUTE_H -#include "standalone.h" // standalone definitions -#include "apps.h" // debugstatements, lfops? - -#define OPTS 3 +#include void hid_corporate_1000_calculate_checksum_and_set(uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc); diff --git a/armsrc/Standalone/lf_icerun.c b/armsrc/Standalone/lf_icerun.c index eafd4ca7d..dad74a75b 100644 --- a/armsrc/Standalone/lf_icerun.c +++ b/armsrc/Standalone/lf_icerun.c @@ -7,7 +7,12 @@ //----------------------------------------------------------------------------- // main code for skeleton aka IceRun by Iceman //----------------------------------------------------------------------------- -#include "lf_icerun.h" +#include "standalone.h" // standalone definitions +#include "proxmark3_arm.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "util.h" +#include "dbprint.h" void ModInfo(void) { DbpString(" LF skeleton mode - aka IceRun (iceman)"); diff --git a/armsrc/Standalone/lf_proxbrute.c b/armsrc/Standalone/lf_proxbrute.c index 09ddb1989..8044cbde9 100644 --- a/armsrc/Standalone/lf_proxbrute.c +++ b/armsrc/Standalone/lf_proxbrute.c @@ -9,7 +9,16 @@ //----------------------------------------------------------------------------- // main code for LF aka Proxbrute by Brad antoniewicz //----------------------------------------------------------------------------- -#include "lf_proxbrute.h" +#include "standalone.h" // standalone definitions +#include "proxmark3_arm.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "util.h" +#include "dbprint.h" +#include "ticks.h" +#include "lfops.h" + +#define OPTS 2 void ModInfo(void) { DbpString(" LF HID ProxII bruteforce - aka Proxbrute (Brad Antoniewicz)"); diff --git a/armsrc/Standalone/lf_samyrun.c b/armsrc/Standalone/lf_samyrun.c index 07fe8bae5..8228db512 100644 --- a/armsrc/Standalone/lf_samyrun.c +++ b/armsrc/Standalone/lf_samyrun.c @@ -8,7 +8,16 @@ //----------------------------------------------------------------------------- // main code for LF aka SamyRun by Samy Kamkar //----------------------------------------------------------------------------- -#include "lf_samyrun.h" +#include "standalone.h" // standalone definitions +#include "proxmark3_arm.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "lfops.h" +#include "util.h" +#include "dbprint.h" +#include "ticks.h" + +#define OPTS 2 void ModInfo(void) { DbpString(" LF HID26 standalone - aka SamyRun (Samy Kamkar)"); diff --git a/armsrc/Standalone/placeholder.c b/armsrc/Standalone/placeholder.c index b8a426e37..84f724920 100644 --- a/armsrc/Standalone/placeholder.c +++ b/armsrc/Standalone/placeholder.c @@ -1,5 +1,6 @@ #include "standalone.h" // standalone definitions -#include "apps.h" // debug statements + +#include "dbprint.h" void ModInfo(void) { DbpString(" No standalone mode present"); diff --git a/armsrc/Standalone/standalone.h b/armsrc/Standalone/standalone.h index 217c7b4cf..2dd35e94a 100644 --- a/armsrc/Standalone/standalone.h +++ b/armsrc/Standalone/standalone.h @@ -11,9 +11,6 @@ #ifndef __STANDALONE_H #define __STANDALONE_H -#include // for bool -#include // PRIu64 - void RunMod(); void ModInfo(); diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 02829c20c..a4b1c45bc 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -9,25 +9,37 @@ // The main application code. This is the first thing called after start.c // executes. //----------------------------------------------------------------------------- -#include -#include +#include "appmain.h" + #include "usb_cdc.h" -#include "proxmark3.h" +#include "proxmark3_arm.h" +#include "dbprint.h" #include "pmflash.h" -#include "apps.h" #include "fpga.h" -#include "util.h" -#include "printf.h" +#include "fpgaloader.h" #include "string.h" #include "legicrf.h" -#include "legicrfsim.h" -#include "lfsampling.h" #include "BigBuf.h" -#include "mifareutil.h" +#include "iso14443a.h" +#include "iso14443b.h" +#include "iso15693.h" +#include "thinfilm.h" +#include "felica.h" +#include "hitag2.h" +#include "hitagS.h" +#include "iclass.h" +#include "legicrfsim.h" +#include "epa.h" +#include "hfsnoop.h" +#include "lfops.h" +#include "lfsampling.h" +#include "mifarecmd.h" +#include "mifaredesfire.h" #include "mifaresim.h" -#include "hitag.h" - -#define DEBUG 1 +#include "pcf7931.h" +#include "Standalone/standalone.h" +#include "util.h" +#include "ticks.h" #ifdef WITH_LCD #include "LCD.h" @@ -58,6 +70,13 @@ int ToSendMax = -1; static int ToSendBit; struct common_area common_area __attribute__((section(".commonarea"))); int button_status = BUTTON_NO_CLICK; +bool allow_send_wtx = false; + +inline void send_wtx(uint16_t wtx) { + if (allow_send_wtx) { + reply_ng(CMD_WTX, PM3_SUCCESS, (uint8_t *)&wtx, sizeof(wtx)); + } +} void ToSendReset(void) { ToSendMax = -1; @@ -82,122 +101,6 @@ void ToSendStuffBit(int b) { } } -/* useful when debugging new protocol implementations like FeliCa -void PrintToSendBuffer(void) { - DbpString("Printing ToSendBuffer:"); - Dbhexdump(ToSendMax, ToSend, 0); -} -*/ - -void print_result(char *name, uint8_t *buf, size_t len) { - - uint8_t *p = buf; - uint16_t tmp = len & 0xFFF0; - - for (; p - buf < tmp; p += 16) { - Dbprintf("[%s: %02d/%02d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", - name, - p - buf, - len, - p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15] - ); - } - if (len % 16 != 0) { - char s[46] = {0}; - char *sp = s; - for (; p - buf < len; p++) { - sprintf(sp, "%02x ", p[0]); - sp += 3; - } - Dbprintf("[%s: %02d/%02d] %s", name, p - buf, len, s); - } -} - -//============================================================================= -// Debug print functions, to go out over USB, to the usual PC-side client. -//============================================================================= - -void DbpStringEx(uint32_t flags, char *str) { -#if DEBUG - struct { - uint16_t flag; - uint8_t buf[PM3_CMD_DATA_SIZE - sizeof(uint16_t)]; - } PACKED data; - data.flag = flags; - uint16_t len = MIN(strlen(str), sizeof(data.buf)); - memcpy(data.buf, str, len); - reply_ng(CMD_DEBUG_PRINT_STRING, PM3_SUCCESS, (uint8_t *)&data, sizeof(data.flag) + len); -#endif -} - -void DbpString(char *str) { -#if DEBUG - DbpStringEx(FLAG_LOG, str); -#endif -} - -#if 0 -void DbpIntegers(int x1, int x2, int x3) { - reply_old(CMD_DEBUG_PRINT_INTEGERS, x1, x2, x3, 0, 0); -} -#endif -void DbprintfEx(uint32_t flags, const char *fmt, ...) { -#if DEBUG - // should probably limit size here; oh well, let's just use a big buffer - char output_string[128] = {0x00}; - va_list ap; - va_start(ap, fmt); - kvsprintf(fmt, output_string, 10, ap); - va_end(ap); - - DbpStringEx(flags, output_string); -#endif -} - -void Dbprintf(const char *fmt, ...) { -#if DEBUG - // should probably limit size here; oh well, let's just use a big buffer - char output_string[128] = {0x00}; - va_list ap; - - va_start(ap, fmt); - kvsprintf(fmt, output_string, 10, ap); - va_end(ap); - - DbpString(output_string); -#endif -} - -// prints HEX & ASCII -void Dbhexdump(int len, uint8_t *d, bool bAsci) { -#if DEBUG - char ascii[9]; - - while (len > 0) { - - int l = (len > 8) ? 8 : len; - - memcpy(ascii, d, l); - ascii[l] = 0; - - // filter safe ascii - for (int i = 0; i < l; i++) { - if (ascii[i] < 32 || ascii[i] > 126) { - ascii[i] = '.'; - } - } - - if (bAsci) - Dbprintf("%-8s %*D", ascii, l, d, " "); - else - Dbprintf("%*D", l, d, " "); - - len -= 8; - d += 8; - } -#endif -} - //----------------------------------------------------------------------------- // Read an ADC channel and block till it completes, then return the result // in ADC units (0 to 1023). Also a routine to average 32 samples and @@ -266,9 +169,9 @@ void MeasureAntennaTuning(void) { SpinDelay(20); uint32_t adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10); if (i == 95) - v_lf125 = adcval; // voltage at 125Khz + v_lf125 = adcval; // voltage at 125kHz if (i == 89) - v_lf134 = adcval; // voltage at 134Khz + v_lf134 = adcval; // voltage at 134kHz LF_Results[i] = adcval >> 9; // scale int to fit in byte for graphing purposes if (LF_Results[i] > peak) { @@ -430,6 +333,9 @@ void SendStatus(void) { Dbprintf(" ToSendMax...............%d", ToSendMax); Dbprintf(" ToSendBit...............%d", ToSendBit); Dbprintf(" ToSend BUFFERSIZE.......%d", TOSEND_BUFFER_SIZE); + while ((AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINRDY) == 0); // Wait for MAINF value to become available... + uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINF; // Get # main clocks within 16 slow clocks + Dbprintf(" Slow clock..............%d Hz", (16 * MAINCK) / mainf); DbpString(_BLUE_("Installed StandAlone Mode")); ModInfo(); @@ -526,6 +432,11 @@ void SendCapabilities(void) { #else capabilities.compiled_with_iclass = false; #endif +#ifdef WITH_NFCBARCODE + capabilities.compiled_with_nfcbarcode = true; +#else + capabilities.compiled_with_nfcbarcode = false; +#endif #ifdef WITH_LCD capabilities.compiled_with_lcd = true; #else @@ -536,15 +447,12 @@ void SendCapabilities(void) { // Show some leds in a pattern to identify StandAlone mod is running void StandAloneMode(void) { - - DbpString("Stand-alone mode! No PC necessary."); - + DbpString("Stand-alone mode, no computer necessary"); SpinDown(50); - SpinOff(50); + SpinDelay(50); SpinUp(50); - SpinOff(50); + SpinDelay(50); SpinDown(50); - SpinDelay(500); } /* @@ -755,25 +663,25 @@ static void PacketReceived(PacketCommandNG *packet) { reply_via_usb = false; break; #ifdef WITH_LF - case CMD_SET_LF_T55XX_CONFIG: { - setT55xxConfig(packet->oldarg[0], (t55xx_config *) packet->data.asBytes); + case CMD_LF_T55XX_SET_CONFIG: { + setT55xxConfig(packet->oldarg[0], (t55xx_configurations_t *) packet->data.asBytes); break; } - case CMD_SET_LF_SAMPLING_CONFIG: { + case CMD_LF_SAMPLING_SET_CONFIG: { setSamplingConfig((sample_config *) packet->data.asBytes); break; } - case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K: { + case CMD_LF_ACQ_RAW_ADC: { struct p { uint8_t silent; uint32_t samples; } PACKED; struct p *payload = (struct p *)packet->data.asBytes; uint32_t bits = SampleLF(payload->silent, payload->samples); - reply_ng(CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, PM3_SUCCESS, (uint8_t *)&bits, sizeof(bits)); + reply_ng(CMD_LF_ACQ_RAW_ADC, PM3_SUCCESS, (uint8_t *)&bits, sizeof(bits)); break; } - case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K: { + case CMD_LF_MOD_THEN_ACQ_RAW_ADC: { struct p { uint32_t delay; uint16_t ones; @@ -783,67 +691,67 @@ static void PacketReceived(PacketCommandNG *packet) { ModThenAcquireRawAdcSamples125k(payload->delay, payload->zeros, payload->ones, packet->data.asBytes + 8); break; } - case CMD_LF_SNIFF_RAW_ADC_SAMPLES: { + case CMD_LF_SNIFF_RAW_ADC: { uint32_t bits = SniffLF(); reply_mix(CMD_ACK, bits, 0, 0, 0, 0); break; } - case CMD_HID_DEMOD_FSK: { + case CMD_LF_HID_DEMOD: { uint32_t high, low; CmdHIDdemodFSK(packet->oldarg[0], &high, &low, 1); break; } - case CMD_HID_SIM_TAG: { + case CMD_LF_HID_SIMULATE: { CmdHIDsimTAG(packet->oldarg[0], packet->oldarg[1], 1); break; } - case CMD_FSK_SIM_TAG: { + case CMD_LF_FSK_SIMULATE: { lf_fsksim_t *payload = (lf_fsksim_t *)packet->data.asBytes; CmdFSKsimTAG(payload->fchigh, payload->fclow, payload->separator, payload->clock, packet->length - sizeof(lf_fsksim_t), payload->data, true); break; } - case CMD_ASK_SIM_TAG: { + case CMD_LF_ASK_SIMULATE: { lf_asksim_t *payload = (lf_asksim_t *)packet->data.asBytes; CmdASKsimTAG(payload->encoding, payload->invert, payload->separator, payload->clock, packet->length - sizeof(lf_asksim_t), payload->data, true); break; } - case CMD_PSK_SIM_TAG: { + case CMD_LF_PSK_SIMULATE: { lf_psksim_t *payload = (lf_psksim_t *)packet->data.asBytes; CmdPSKsimTag(payload->carrier, payload->invert, payload->clock, packet->length - sizeof(lf_psksim_t), payload->data, true); break; } - case CMD_HID_CLONE_TAG: { + case CMD_LF_HID_CLONE: { CopyHIDtoT55x7(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes[0]); break; } - case CMD_IO_DEMOD_FSK: { + case CMD_LF_IO_DEMOD: { uint32_t high, low; CmdIOdemodFSK(packet->oldarg[0], &high, &low, 1); break; } - case CMD_IO_CLONE_TAG: { + case CMD_LF_IO_CLONE: { CopyIOtoT55x7(packet->oldarg[0], packet->oldarg[1]); break; } - case CMD_EM410X_DEMOD: { + case CMD_LF_EM410X_DEMOD: { uint32_t high; uint64_t low; CmdEM410xdemod(packet->oldarg[0], &high, &low, 1); break; } - case CMD_EM410X_WRITE_TAG: { + case CMD_LF_EM410X_WRITE: { WriteEM410x(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2]); break; } - case CMD_READ_TI_TYPE: { + case CMD_LF_TI_READ: { ReadTItag(); break; } - case CMD_WRITE_TI_TYPE: { + case CMD_LF_TI_WRITE: { WriteTItag(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2]); break; } - case CMD_SIMULATE_TAG_125K: { + case CMD_LF_SIMULATE: { LED_A_ON(); struct p { uint16_t len; @@ -852,7 +760,7 @@ static void PacketReceived(PacketCommandNG *packet) { struct p *payload = (struct p *)packet->data.asBytes; // length, start gap, led control SimulateTagLowFrequency(payload->len, payload->gap, 1); - reply_ng(CMD_SIMULATE_TAG_125K, PM3_EOPABORTED, NULL, 0); + reply_ng(CMD_LF_SIMULATE, PM3_EOPABORTED, NULL, 0); LED_A_OFF(); break; } @@ -860,18 +768,18 @@ static void PacketReceived(PacketCommandNG *packet) { SimulateTagLowFrequencyBidir(packet->oldarg[0], packet->oldarg[1]); break; } - case CMD_INDALA_CLONE_TAG: { + case CMD_LF_INDALA_CLONE: { CopyIndala64toT55x7(packet->data.asDwords[0], packet->data.asDwords[1]); break; } - case CMD_INDALA_CLONE_TAG_L: { + case CMD_LF_INDALA224_CLONE: { CopyIndala224toT55x7( packet->data.asDwords[0], packet->data.asDwords[1], packet->data.asDwords[2], packet->data.asDwords[3], packet->data.asDwords[4], packet->data.asDwords[5], packet->data.asDwords[6] ); break; } - case CMD_T55XX_READ_BLOCK: { + case CMD_LF_T55XX_READBL: { struct p { uint32_t password; uint8_t blockno; @@ -883,28 +791,28 @@ static void PacketReceived(PacketCommandNG *packet) { T55xxReadBlock(payload->page, payload->pwdmode, false, payload->blockno, payload->password, payload->downlink_mode); break; } - case CMD_T55XX_WRITE_BLOCK: { + case CMD_LF_T55XX_WRITEBL: { // uses NG format T55xxWriteBlock(packet->data.asBytes); break; } - case CMD_T55XX_WAKEUP: { + case CMD_LF_T55XX_WAKEUP: { T55xxWakeUp(packet->oldarg[0], packet->oldarg[1]); break; } - case CMD_T55XX_RESET_READ: { + case CMD_LF_T55XX_RESET_READ: { T55xxResetRead(packet->data.asBytes[0] & 0xff); break; } - case CMD_T55XX_CHKPWDS: { + case CMD_LF_T55XX_CHK_PWDS: { T55xx_ChkPwds(packet->data.asBytes[0] & 0xff); break; } - case CMD_PCF7931_READ: { + case CMD_LF_PCF7931_READ: { ReadPCF7931(); break; } - case CMD_PCF7931_WRITE: { + case CMD_LF_PCF7931_WRITE: { WritePCF7931( packet->data.asBytes[0], packet->data.asBytes[1], packet->data.asBytes[2], packet->data.asBytes[3], packet->data.asBytes[4], packet->data.asBytes[5], packet->data.asBytes[6], packet->data.asBytes[9], @@ -915,7 +823,7 @@ static void PacketReceived(PacketCommandNG *packet) { ); break; } - case CMD_EM4X_READ_WORD: { + case CMD_LF_EM4X_READWORD: { struct p { uint32_t password; uint8_t address; @@ -925,7 +833,7 @@ static void PacketReceived(PacketCommandNG *packet) { EM4xReadWord(payload->address, payload->password, payload->usepwd); break; } - case CMD_EM4X_WRITE_WORD: { + case CMD_LF_EM4X_WRITEWORD: { struct p { uint32_t password; uint32_t data; @@ -936,48 +844,48 @@ static void PacketReceived(PacketCommandNG *packet) { EM4xWriteWord(payload->address, payload->data, payload->password, payload->usepwd); break; } - case CMD_AWID_DEMOD_FSK: { + case CMD_LF_AWID_DEMOD: { uint32_t high, low; // Set realtime AWID demodulation CmdAWIDdemodFSK(packet->oldarg[0], &high, &low, 1); break; } - case CMD_VIKING_CLONE_TAG: { + case CMD_LF_VIKING_CLONE: { CopyVikingtoT55xx(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2]); break; } - case CMD_COTAG: { + case CMD_LF_COTAG_READ: { Cotag(packet->oldarg[0]); break; } #endif #ifdef WITH_HITAG - case CMD_SNIFF_HITAG: { // Eavesdrop Hitag tag, args = type + case CMD_LF_HITAG_SNIFF: { // Eavesdrop Hitag tag, args = type SniffHitag(); break; } - case CMD_SIMULATE_HITAG: { // Simulate Hitag tag, args = memory content + case CMD_LF_HITAG_SIMULATE: { // Simulate Hitag tag, args = memory content SimulateHitagTag((bool)packet->oldarg[0], packet->data.asBytes); break; } - case CMD_READER_HITAG: { // Reader for Hitag tags, args = type and function + case CMD_LF_HITAG_READER: { // Reader for Hitag tags, args = type and function ReaderHitag((hitag_function)packet->oldarg[0], (hitag_data *)packet->data.asBytes); break; } - case CMD_SIMULATE_HITAG_S: { // Simulate Hitag s tag, args = memory content + case CMD_LF_HITAGS_SIMULATE: { // Simulate Hitag s tag, args = memory content SimulateHitagSTag((bool)packet->oldarg[0], packet->data.asBytes); break; } - case CMD_TEST_HITAGS_TRACES: { // Tests every challenge within the given file + case CMD_LF_HITAGS_TEST_TRACES: { // Tests every challenge within the given file check_challenges((bool)packet->oldarg[0], packet->data.asBytes); break; } - case CMD_READ_HITAG_S: { //Reader for only Hitag S tags, args = key or challenge + case CMD_LF_HITAGS_READ: { //Reader for only Hitag S tags, args = key or challenge ReadHitagS((hitag_function)packet->oldarg[0], (hitag_data *)packet->data.asBytes); break; } - case CMD_WR_HITAG_S: { //writer for Hitag tags args=data to write,page and key or challenge + case CMD_LF_HITAGS_WRITE: { //writer for Hitag tags args=data to write,page and key or challenge if ((hitag_function)packet->oldarg[0] < 10) { WritePageHitagS((hitag_function)packet->oldarg[0], (hitag_data *)packet->data.asBytes, packet->oldarg[2]); } else { @@ -988,50 +896,50 @@ static void PacketReceived(PacketCommandNG *packet) { #endif #ifdef WITH_ISO15693 - case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693: { + case CMD_HF_ISO15693_ACQ_RAW_ADC: { AcquireRawAdcSamplesIso15693(); break; } - case CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693: { + case CMD_HF_ISO15693_RAWADC: { RecordRawAdcSamplesIso15693(); break; } - case CMD_ISO_15693_COMMAND: { + case CMD_HF_ISO15693_COMMAND: { DirectTag15693Command(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes); break; } - case CMD_ISO_15693_FIND_AFI: { + case CMD_HF_ISO15693_FINDAFI: { BruteforceIso15693Afi(packet->oldarg[0]); break; } - case CMD_READER_ISO_15693: { + case CMD_HF_ISO15693_READER: { ReaderIso15693(packet->oldarg[0]); break; } - case CMD_SIMTAG_ISO_15693: { + case CMD_HF_ISO15693_SIMULATE: { SimTagIso15693(packet->oldarg[0], packet->data.asBytes); break; } #endif #ifdef WITH_LEGICRF - case CMD_SIMULATE_TAG_LEGIC_RF: { + case CMD_HF_LEGIC_SIMULATE: { LegicRfSimulate(packet->oldarg[0]); break; } - case CMD_WRITER_LEGIC_RF: { + case CMD_HF_LEGIC_WRITER: { LegicRfWriter(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes); break; } - case CMD_READER_LEGIC_RF: { + case CMD_HF_LEGIC_READER: { LegicRfReader(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2]); break; } - case CMD_LEGIC_INFO: { + case CMD_HF_LEGIC_INFO: { LegicRfInfo(); break; } - case CMD_LEGIC_ESET: { + case CMD_HF_LEGIC_ESET: { //----------------------------------------------------------------------------- // Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not // involved in dealing with emulator memory. But if it is called later, it might @@ -1046,19 +954,19 @@ static void PacketReceived(PacketCommandNG *packet) { #endif #ifdef WITH_ISO14443b - case CMD_READ_SRI_TAG: { + case CMD_HF_SRI_READ: { ReadSTMemoryIso14443b(packet->oldarg[0]); break; } - case CMD_SNIFF_ISO_14443B: { + case CMD_HF_ISO14443B_SNIFF: { SniffIso14443b(); break; } - case CMD_SIMULATE_TAG_ISO_14443B: { + case CMD_HF_ISO14443B_SIMULATE: { SimulateIso14443bTag(packet->oldarg[0]); break; } - case CMD_ISO_14443B_COMMAND: { + case CMD_HF_ISO14443B_COMMAND: { //SendRawCommand14443B(packet->oldarg[0],packet->oldarg[1],packet->oldarg[2],packet->data.asBytes); SendRawCommand14443B_Ex(packet); break; @@ -1066,34 +974,40 @@ static void PacketReceived(PacketCommandNG *packet) { #endif #ifdef WITH_FELICA - case CMD_FELICA_COMMAND: { + case CMD_HF_FELICA_COMMAND: { felica_sendraw(packet); break; } - case CMD_FELICA_LITE_SIM: { + case CMD_HF_FELICALITE_SIMULATE: { felica_sim_lite(packet->oldarg[0]); break; } - case CMD_FELICA_SNIFF: { + case CMD_HF_FELICA_SNIFF: { felica_sniff(packet->oldarg[0], packet->oldarg[1]); break; } - case CMD_FELICA_LITE_DUMP: { + case CMD_HF_FELICALITE_DUMP: { felica_dump_lite_s(); break; } #endif +// always available + case CMD_HF_DROPFIELD: { + hf_field_off(); + break; + } + #ifdef WITH_ISO14443a - case CMD_SNIFF_ISO_14443a: { + case CMD_HF_ISO14443A_SNIFF: { SniffIso14443a(packet->data.asBytes[0]); break; } - case CMD_READER_ISO_14443a: { + case CMD_HF_ISO14443A_READER: { ReaderIso14443a(packet); break; } - case CMD_SIMULATE_TAG_ISO_14443a: { + case CMD_HF_ISO14443A_SIMULATE: { struct p { uint8_t tagtype; uint8_t flags; @@ -1103,87 +1017,85 @@ static void PacketReceived(PacketCommandNG *packet) { SimulateIso14443aTag(payload->tagtype, payload->flags, payload->uid); // ## Simulate iso14443a tag - pass tag type & UID break; } - case CMD_ANTIFUZZ_ISO_14443a: { + case CMD_HF_ISO14443A_ANTIFUZZ: { iso14443a_antifuzz(packet->oldarg[0]); break; } - case CMD_EPA_PACE_COLLECT_NONCE: { + case CMD_HF_EPA_COLLECT_NONCE: { EPA_PACE_Collect_Nonce(packet); break; } - case CMD_EPA_PACE_REPLAY: { + case CMD_HF_EPA_REPLAY: { EPA_PACE_Replay(packet); break; } - case CMD_READER_MIFARE: { + case CMD_HF_MIFARE_READER: { ReaderMifare(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2]); break; } - case CMD_MIFARE_READBL: { + case CMD_HF_MIFARE_READBL: { mf_readblock_t *payload = (mf_readblock_t *)packet->data.asBytes; MifareReadBlock(payload->blockno, payload->keytype, payload->key); break; } - case CMD_MIFAREU_READBL: { + case CMD_HF_MIFAREU_READBL: { MifareUReadBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); break; } - case CMD_MIFAREUC_AUTH: { + case CMD_HF_MIFAREUC_AUTH: { MifareUC_Auth(packet->oldarg[0], packet->data.asBytes); break; } - case CMD_MIFAREU_READCARD: { + case CMD_HF_MIFAREU_READCARD: { MifareUReadCard(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes); break; } - case CMD_MIFAREUC_SETPWD: { + case CMD_HF_MIFAREUC_SETPWD: { MifareUSetPwd(packet->oldarg[0], packet->data.asBytes); break; } - case CMD_MIFARE_READSC: { + case CMD_HF_MIFARE_READSC: { MifareReadSector(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); break; } - case CMD_MIFARE_WRITEBL: { + case CMD_HF_MIFARE_WRITEBL: { MifareWriteBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); break; } - //case CMD_MIFAREU_WRITEBL_COMPAT: { - //MifareUWriteBlockCompat(packet->oldarg[0], packet->data.asBytes); - //break; - //} - case CMD_MIFAREU_WRITEBL: { + case CMD_HF_MIFAREU_WRITEBL: { MifareUWriteBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); break; } - case CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES: { + case CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES: { MifareAcquireEncryptedNonces(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes); break; } - case CMD_MIFARE_ACQUIRE_NONCES: { + case CMD_HF_MIFARE_ACQ_NONCES: { MifareAcquireNonces(packet->oldarg[0], packet->oldarg[2]); break; } - case CMD_MIFARE_NESTED: { + case CMD_HF_MIFARE_NESTED: { MifareNested(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes); break; } - case CMD_MIFARE_CHKKEYS: { + case CMD_HF_MIFARE_CHKKEYS: { MifareChkKeys(packet->data.asBytes); break; } - case CMD_MIFARE_CHKKEYS_FAST: { + case CMD_HF_MIFARE_CHKKEYS_FAST: { MifareChkKeys_fast(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes); break; } - case CMD_SIMULATE_MIFARE_CARD: { + case CMD_HF_MIFARE_SIMULATE: { struct p { uint16_t flags; uint8_t exitAfter; uint8_t uid[10]; + uint16_t atqa; + uint8_t sak; } PACKED; struct p *payload = (struct p *) packet->data.asBytes; - Mifare1ksim(payload->flags, payload->exitAfter, payload->uid); + Mifare1ksim(payload->flags, payload->exitAfter, payload->uid, payload->atqa, payload->sak); break; } // emulator @@ -1193,12 +1105,12 @@ static void PacketReceived(PacketCommandNG *packet) { reply_ng(CMD_SET_DBGMODE, PM3_SUCCESS, NULL, 0); break; } - case CMD_MIFARE_EML_MEMCLR: { + case CMD_HF_MIFARE_EML_MEMCLR: { MifareEMemClr(); - reply_ng(CMD_MIFARE_EML_MEMCLR, PM3_SUCCESS, NULL, 0); + reply_ng(CMD_HF_MIFARE_EML_MEMCLR, PM3_SUCCESS, NULL, 0); break; } - case CMD_MIFARE_EML_MEMSET: { + case CMD_HF_MIFARE_EML_MEMSET: { struct p { uint8_t blockno; uint8_t blockcnt; @@ -1209,7 +1121,7 @@ static void PacketReceived(PacketCommandNG *packet) { MifareEMemSet(payload->blockno, payload->blockcnt, payload->blockwidth, payload->data); break; } - case CMD_MIFARE_EML_MEMGET: { + case CMD_HF_MIFARE_EML_MEMGET: { struct p { uint8_t blockno; uint8_t blockcnt; @@ -1218,124 +1130,161 @@ static void PacketReceived(PacketCommandNG *packet) { MifareEMemGet(payload->blockno, payload->blockcnt); break; } - case CMD_MIFARE_EML_CARDLOAD: { - MifareECardLoad(packet->oldarg[0], packet->oldarg[1]); + case CMD_HF_MIFARE_EML_LOAD: { + mfc_eload_t *payload = (mfc_eload_t *) packet->data.asBytes; + MifareECardLoadExt(payload->sectorcnt, payload->keytype); break; } // Work with "magic Chinese" card - case CMD_MIFARE_CSETBLOCK: { + case CMD_HF_MIFARE_CSETBL: { MifareCSetBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); break; } - case CMD_MIFARE_CGETBLOCK: { + case CMD_HF_MIFARE_CGETBL: { MifareCGetBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); break; } - case CMD_MIFARE_CIDENT: { + case CMD_HF_MIFARE_CIDENT: { MifareCIdent(); break; } // mifare sniffer -// case CMD_MIFARE_SNIFFER: { +// case CMD_HF_MIFARE_SNIFF: { // SniffMifare(packet->oldarg[0]); // break; // } - case CMD_MIFARE_SETMOD: { + case CMD_HF_MIFARE_SETMOD: { MifareSetMod(packet->data.asBytes); break; } //mifare desfire - case CMD_MIFARE_DESFIRE_READBL: { + case CMD_HF_DESFIRE_READBL: { break; } - case CMD_MIFARE_DESFIRE_WRITEBL: { + case CMD_HF_DESFIRE_WRITEBL: { break; } - case CMD_MIFARE_DESFIRE_AUTH1: { + case CMD_HF_DESFIRE_AUTH1: { MifareDES_Auth1(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes); break; } - case CMD_MIFARE_DESFIRE_AUTH2: { + case CMD_HF_DESFIRE_AUTH2: { //MifareDES_Auth2(packet->oldarg[0],packet->data.asBytes); break; } - case CMD_MIFARE_DES_READER: { + case CMD_HF_DESFIRE_READER: { //readermifaredes(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); break; } - case CMD_MIFARE_DESFIRE_INFO: { + case CMD_HF_DESFIRE_INFO: { MifareDesfireGetInformation(); break; } - case CMD_MIFARE_DESFIRE: { + case CMD_HF_DESFIRE_COMMAND: { MifareSendCommand(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); break; } - case CMD_MIFARE_COLLECT_NONCES: { + case CMD_HF_MIFARE_NACK_DETECT: { + DetectNACKbug(); break; } - case CMD_MIFARE_NACK_DETECT: { - DetectNACKbug(); +#endif + +#ifdef WITH_NFCBARCODE + case CMD_HF_THINFILM_READ: { + ReadThinFilm(); + break; + } + case CMD_HF_THINFILM_SIMULATE: { + SimulateThinFilm(packet->data.asBytes, packet->length); break; } #endif #ifdef WITH_ICLASS // Makes use of ISO14443a FPGA Firmware - case CMD_SNIFF_ICLASS: { + case CMD_HF_ICLASS_SNIFF: { SniffIClass(); break; } - case CMD_SIMULATE_TAG_ICLASS: { + case CMD_HF_ICLASS_SIMULATE: { SimulateIClass(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes); break; } - case CMD_READER_ICLASS: { - ReaderIClass(packet->oldarg[0]); + case CMD_HF_ICLASS_READER: { + struct p { + uint8_t flags; + } PACKED; + struct p *payload = (struct p *)packet->data.asBytes; + ReaderIClass(payload->flags); break; } - case CMD_READER_ICLASS_REPLAY: { + case CMD_HF_ICLASS_REPLAY: { ReaderIClass_Replay(packet->oldarg[0], packet->data.asBytes); break; } - case CMD_ICLASS_EML_MEMSET: { + case CMD_HF_ICLASS_EML_MEMSET: { //iceman, should call FPGADOWNLOAD before, since it corrupts BigBuf FpgaDownloadAndGo(FPGA_BITSTREAM_HF); emlSet(packet->data.asBytes, packet->oldarg[0], packet->oldarg[1]); break; } - case CMD_ICLASS_WRITEBLOCK: { - iClass_WriteBlock(packet->oldarg[0], packet->data.asBytes); + case CMD_HF_ICLASS_WRITEBL: { + struct p { + uint8_t blockno; + uint8_t data[12]; + } PACKED; + struct p *payload = (struct p *)packet->data.asBytes; + iClass_WriteBlock(payload->blockno, payload->data); break; } - case CMD_ICLASS_READCHECK: { // auth step 1 + // iceman2019, unused? + case CMD_HF_ICLASS_READCHECK: { // auth step 1 iClass_ReadCheck(packet->oldarg[0], packet->oldarg[1]); break; } - case CMD_ICLASS_READBLOCK: { - iClass_ReadBlk(packet->oldarg[0]); + case CMD_HF_ICLASS_READBL: { +/* + struct p { + uint8_t blockno; + } PACKED; + struct p *payload = (struct p *)packet->data.asBytes; + */ + iClass_ReadBlk( packet->data.asBytes[0] ); break; } - case CMD_ICLASS_AUTHENTICATION: { //check + case CMD_HF_ICLASS_AUTH: { //check +/* + struct p { + uint8_t mac[4]; + } PACKED; + struct p *payload = (struct p *)packet->data.asBytes; +*/ iClass_Authentication(packet->data.asBytes); break; } - case CMD_ICLASS_CHECK_KEYS: { + case CMD_HF_ICLASS_CHKKEYS: { iClass_Authentication_fast(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); break; } - case CMD_ICLASS_DUMP: { + case CMD_HF_ICLASS_DUMP: { iClass_Dump(packet->oldarg[0], packet->oldarg[1]); break; } - case CMD_ICLASS_CLONE: { - iClass_Clone(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); + case CMD_HF_ICLASS_CLONE: { + struct p { + uint8_t startblock; + uint8_t endblock; + uint8_t data[]; + } PACKED; + struct p *payload = (struct p *)packet->data.asBytes; + iClass_Clone(payload->startblock, payload->endblock, payload->data); break; } #endif #ifdef WITH_HFSNIFF - case CMD_HF_SNIFFER: { + case CMD_HF_SNIFF: { HfSniff(packet->oldarg[0], packet->oldarg[1]); break; } @@ -1537,7 +1486,7 @@ static void PacketReceived(PacketCommandNG *packet) { break; } #ifdef WITH_LF - case CMD_UPLOAD_SIM_SAMPLES_125K: { + case CMD_LF_UPLOAD_SIM_SAMPLES: { // iceman; since changing fpga_bitstreams clears bigbuff, Its better to call it before. // to be able to use this one for uploading data to device // flag = @@ -1559,7 +1508,7 @@ static void PacketReceived(PacketCommandNG *packet) { uint8_t *mem = BigBuf_get_addr(); memcpy(mem + payload->offset, &payload->data, PM3_CMD_DATA_SIZE - 3); - reply_ng(CMD_UPLOAD_SIM_SAMPLES_125K, PM3_SUCCESS, NULL, 0); + reply_ng(CMD_LF_UPLOAD_SIM_SAMPLES, PM3_SUCCESS, NULL, 0); break; } #endif @@ -1595,6 +1544,10 @@ static void PacketReceived(PacketCommandNG *packet) { test_spiffs(); break; } + case CMD_SPIFFS_CHECK: { + rdv40_spiffs_check(); + break; + } case CMD_SPIFFS_MOUNT: { rdv40_spiffs_lazy_mount(); break; @@ -1731,58 +1684,29 @@ static void PacketReceived(PacketCommandNG *packet) { uint16_t len = packet->oldarg[1]; uint8_t *data = packet->data.asBytes; - uint32_t tmp = startidx + len; - if (!FlashInit()) { break; } - Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); - if (startidx == DEFAULT_T55XX_KEYS_OFFSET) { + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); Flash_Erase4k(3, 0xC); } else if (startidx == DEFAULT_MF_KEYS_OFFSET) { + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); Flash_Erase4k(3, 0x9); + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); Flash_Erase4k(3, 0xA); } else if (startidx == DEFAULT_ICLASS_KEYS_OFFSET) { + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); Flash_Erase4k(3, 0xB); } - Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); - - // inside 256b page? - if ((tmp & 0xFF) != 0) { - - // is offset+len larger than a page - tmp = (startidx & 0xFF) + len; - if (tmp > 0xFF) { - - // data spread over two pages. - - // offset xxxx10, - uint8_t first_len = (~startidx & 0xFF) + 1; - - // first mem page - res = Flash_WriteDataCont(startidx, data, first_len); - - isok = (res == first_len) ? 1 : 0; - - // second mem page - res = Flash_WriteDataCont(startidx + first_len, data + first_len, len - first_len); - - isok &= (res == (len - first_len)) ? 1 : 0; - - } else { - res = Flash_WriteDataCont(startidx, data, len); - isok = (res == len) ? 1 : 0; - } - } else { - res = Flash_WriteDataCont(startidx, data, len); - isok = (res == len) ? 1 : 0; - } - FlashStop(); + res = Flash_Write(startidx, data, len); + isok = (res == len) ? 1 : 0; reply_old(CMD_ACK, isok, 0, 0, 0, 0); LED_B_OFF(); @@ -1822,7 +1746,7 @@ static void PacketReceived(PacketCommandNG *packet) { for (size_t i = 0; i < numofbytes; i += PM3_CMD_DATA_SIZE) { size_t len = MIN((numofbytes - i), PM3_CMD_DATA_SIZE); - + Flash_CheckBusy(BUSY_TIMEOUT); bool isok = Flash_ReadDataCont(startidx + i, mem, len); if (!isok) Dbprintf("reading flash memory failed :: | bytes between %d - %d", i, len); @@ -1856,7 +1780,7 @@ static void PacketReceived(PacketCommandNG *packet) { break; } #endif - case CMD_SET_LF_DIVISOR: { + case CMD_LF_SET_DIVISOR: { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, packet->data.asBytes[0]); break; @@ -1966,8 +1890,8 @@ void __attribute__((noreturn)) AppMain(void) { AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0; AT91C_BASE_PIOA->PIO_PDR = GPIO_PCK0; AT91C_BASE_PMC->PMC_SCER |= AT91C_PMC_PCK0; - // PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz - AT91C_BASE_PMC->PMC_PCKR[0] = AT91C_PMC_CSS_PLL_CLK | AT91C_PMC_PRES_CLK_4; // 4 for 24Mhz pck0, 2 for 48 MHZ pck0 + // PCK0 is PLL clock / 4 = 96MHz / 4 = 24MHz + AT91C_BASE_PMC->PMC_PCKR[0] = AT91C_PMC_CSS_PLL_CLK | AT91C_PMC_PRES_CLK_4; // 4 for 24MHz pck0, 2 for 48 MHZ pck0 AT91C_BASE_PIOA->PIO_OER = GPIO_PCK0; // Reset SPI @@ -2002,10 +1926,16 @@ void __attribute__((noreturn)) AppMain(void) { // against device such as http://www.hobbytronics.co.uk/usb-host-board-v2 usb_disable(); usb_enable(); + allow_send_wtx = true; #ifdef WITH_FLASH // If flash is not present, BUSY_TIMEOUT kicks in, let's do it after USB loadT55xxConfig(); + + // + // Enforce a spiffs check/garbage collection at boot so we are likely to never + // fall under the 2 contigous free blocks availables + rdv40_spiffs_check(); #endif for (;;) { @@ -2031,7 +1961,9 @@ void __attribute__((noreturn)) AppMain(void) { * So this is the trigger to execute a standalone mod. Generic entrypoint by following the standalone/standalone.h headerfile * All standalone mod "main loop" should be the RunMod() function. */ + allow_send_wtx = false; RunMod(); + allow_send_wtx = true; } } } diff --git a/armsrc/appmain.h b/armsrc/appmain.h new file mode 100644 index 000000000..141c943f9 --- /dev/null +++ b/armsrc/appmain.h @@ -0,0 +1,44 @@ +//----------------------------------------------------------------------------- +// Jonathan Westhues, Aug 2005 +// Gerhard de Koning Gans, April 2008, May 2011 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Definitions internal to the app source. +//----------------------------------------------------------------------------- +#ifndef __APPMAIN_H +#define __APPMAIN_H + +#include "common.h" + +extern const uint8_t OddByteParity[256]; +extern int rsamples; // = 0; +extern uint8_t trigger; +extern bool allow_send_wtx; + +// ADC Vref = 3300mV, and an (10M+1M):1M voltage divider on the HF input can measure voltages up to 36300 mV +#define MAX_ADC_HF_VOLTAGE 36300 +// ADC Vref = 3300mV, (240k-10M):240k voltage divider, 140800 mV +#define MAX_ADC_HF_VOLTAGE_RDV40 140800 +// ADC Vref = 3300mV, and an (10000k+240k):240k voltage divider on the LF input can measure voltages up to 140800 mV +#define MAX_ADC_LF_VOLTAGE 140800 + +extern int ToSendMax; +extern uint8_t ToSend[]; + +void send_wtx(uint16_t wtx); +void ReadMem(int addr); +void __attribute__((noreturn)) AppMain(void); + +uint16_t AvgAdc(int ch); + +//void PrintToSendBuffer(void); +void ToSendStuffBit(int b); +void ToSendReset(void); +void ListenReaderField(uint8_t limit); +void StandAloneMode(void); +void printStandAloneModes(void); + +#endif diff --git a/armsrc/apps.h b/armsrc/apps.h deleted file mode 100644 index e3ea8048c..000000000 --- a/armsrc/apps.h +++ /dev/null @@ -1,253 +0,0 @@ -//----------------------------------------------------------------------------- -// Jonathan Westhues, Aug 2005 -// Gerhard de Koning Gans, April 2008, May 2011 -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// Definitions internal to the app source. -//----------------------------------------------------------------------------- -#ifndef __APPS_H -#define __APPS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "common.h" -#include "usb_cdc.h" -#include "crc32.h" -#include "lfdemod.h" -#include "BigBuf.h" -#include "fpgaloader.h" -#include "hitag2.h" -#include "hitagS.h" -#include "mifare.h" -#include "pcf7931.h" -#include "desfire.h" -#include "iso14443b.h" -#include "Standalone/standalone.h" -#include "flashmem.h" - -extern const uint8_t OddByteParity[256]; -extern int rsamples; // = 0; -extern uint8_t trigger; - -// This may be used (sparingly) to declare a function to be copied to -// and executed from RAM -#define RAMFUNC __attribute((long_call, section(".ramfunc"))) - -/// appmain.h -void ReadMem(int addr); -void __attribute__((noreturn)) AppMain(void); -//void DbpIntegers(int a, int b, int c); -void DbpString(char *str); -void DbpStringEx(uint32_t flags, char *str); -void Dbprintf(const char *fmt, ...); -void DbprintfEx(uint32_t flags, const char *fmt, ...); -void Dbhexdump(int len, uint8_t *d, bool bAsci); - -// ADC Vref = 3300mV, and an (10M+1M):1M voltage divider on the HF input can measure voltages up to 36300 mV -#define MAX_ADC_HF_VOLTAGE 36300 -// ADC Vref = 3300mV, (240k-10M):240k voltage divider, 140800 mV -#define MAX_ADC_HF_VOLTAGE_RDV40 140800 -// ADC Vref = 3300mV, and an (10000k+240k):240k voltage divider on the LF input can measure voltages up to 140800 mV -#define MAX_ADC_LF_VOLTAGE 140800 -uint16_t AvgAdc(int ch); - -void print_result(char *name, uint8_t *buf, size_t len); -//void PrintToSendBuffer(void); -void ToSendStuffBit(int b); -void ToSendReset(void); -void ListenReaderField(uint8_t limit); -extern int ToSendMax; -extern uint8_t ToSend[]; - -void StandAloneMode(void); -void printStandAloneModes(void); - -/// lfops.h -extern uint8_t decimation; -extern uint8_t bits_per_sample ; -extern bool averaging; - -void AcquireRawAdcSamples125k(int divisor); -void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command); -void ReadTItag(void); -void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc); - -void AcquireTiType(void); -void AcquireRawBitsTI(void); -void SimulateTagLowFrequencyEx(int period, int gap, bool ledcontrol, int numcycles); -void SimulateTagLowFrequency(int period, int gap, bool ledcontrol); -void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen); - -void CmdHIDsimTAGEx(uint32_t hi, uint32_t lo, bool ledcontrol, int numcycles); -void CmdHIDsimTAG(uint32_t hi, uint32_t lo, bool ledcontrol); - -void CmdFSKsimTAG(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, uint8_t *bits, bool ledcontrol); -void CmdASKsimTAG(uint8_t encoding, uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol); -void CmdPSKsimTag(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol); - -void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); -void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); // Realtime demodulation mode for AWID26 -void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol); -void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); -void CopyIOtoT55x7(uint32_t hi, uint32_t lo); // Clone an ioProx card to T5557/T5567 -void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567 -void CopyVikingtoT55xx(uint32_t block1, uint32_t block2, uint8_t Q5); -void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo); -void CopyIndala64toT55x7(uint32_t hi, uint32_t lo); // Clone Indala 64-bit tag by UID to T55x7 -void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7); // Clone Indala 224-bit tag by UID to T55x7 -void T55xxResetRead(uint8_t flags); -//id T55xxWriteBlock(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags); -void T55xxWriteBlock(uint8_t *data); -// void T55xxWriteBlockExt(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags); -void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block, uint32_t pwd, uint8_t downlink_mode); -void T55xxWakeUp(uint32_t Pwd, uint8_t flags); -void T55xx_ChkPwds(uint8_t flags); - -void TurnReadLFOn(uint32_t delay); - -void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd); -void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd); - -void Cotag(uint32_t arg0); -void setT55xxConfig(uint8_t arg0, t55xx_config *c); -t55xx_config *getT55xxConfig(void); -void printT55xxConfig(void); -void loadT55xxConfig(void); - -/// iso14443b.h -void SimulateIso14443bTag(uint32_t pupi); -void AcquireRawAdcSamplesIso14443b(uint32_t parameter); -void ReadSTMemoryIso14443b(uint8_t numofblocks); -void RAMFUNC SniffIso14443b(void); -void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]); -void SendRawCommand14443B_Ex(PacketCommandNG *c); -void ClearFpgaShiftingRegisters(void); - -// iso14443a.h -void RAMFUNC SniffIso14443a(uint8_t param); -void ReaderIso14443a(PacketCommandNG *c); - -// Also used in iclass.c -//bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t len, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); -void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); -void iso14a_set_trigger(bool enable); -// also used in emv -//bool prepare_allocated_tag_modulation(tag_response_info_t *response_info); -//int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len); - -// epa.h -void EPA_PACE_Collect_Nonce(PacketCommandNG *c); -void EPA_PACE_Replay(PacketCommandNG *c); - -// mifarecmd.h -void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain); - -void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); -void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes); -void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain); -void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t *datain); -void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); -//void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain); -void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); -void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); -void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain); -void MifareAcquireNonces(uint32_t arg0, uint32_t flags); -void MifareChkKeys(uint8_t *datain); -void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); - -void MifareEMemClr(void); -void MifareEMemSet(uint8_t blockno, uint8_t blockcnt, uint8_t blockwidth, uint8_t *datain); -void MifareEMemGet(uint8_t blockno, uint8_t blockcnt); -int MifareECardLoad(uint32_t arg0, uint32_t arg1); - -void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card -void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); -void MifareCIdent(); // is "magic chinese" card? - -void MifareSetMod(uint8_t *datain); -void MifareUSetPwd(uint8_t arg0, uint8_t *datain); -void OnSuccessMagic(); -void OnErrorMagic(uint8_t reason); - -int32_t dist_nt(uint32_t nt1, uint32_t nt2); -void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype); -//void RAMFUNC SniffMifare(uint8_t param); - -//desfire -void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain); -void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain); - -// mifaredesfire.h -bool InitDesfireCard(); -void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain); -void MifareDesfireGetInformation(); -void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); -void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t *datain); -int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout); -size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout); -void OnSuccess(); -void OnError(uint8_t reason); - -// desfire_crypto.h -void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings); -void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings); -void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size); -void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation); -size_t key_block_size(const desfirekey_t key); -size_t padded_data_length(const size_t nbytes, const size_t block_size); -size_t maced_data_length(const desfirekey_t key, const size_t nbytes); -size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int communication_settings); -void cmac_generate_subkeys(desfirekey_t key); -void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac); - -// iso15693.h -void RecordRawAdcSamplesIso15693(void); -void AcquireRawAdcSamplesIso15693(void); -void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg -void SimTagIso15693(uint32_t parameter, uint8_t *uid); // simulate an ISO15693 tag - greg -void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox -void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI - atrox -void Iso15693InitReader(void); - -// iclass.h -void RAMFUNC SniffIClass(void); -void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); -void ReaderIClass(uint8_t arg0); -void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac); -void iClass_Authentication(uint8_t *mac); -void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain); -void iClass_WriteBlock(uint8_t blockno, uint8_t *data); -void iClass_ReadBlk(uint8_t blockno); -bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len); -void iClass_Dump(uint8_t blockno, uint8_t numblks); -void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data); -void iClass_ReadCheck(uint8_t blockno, uint8_t keytype); - -// cmd.h -int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len); -int reply_mix(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len); -int reply_ng(uint16_t cmd, int16_t status, uint8_t *data, size_t len); -int receive_ng(PacketCommandNG *rx); - -// util.h -void HfSniff(int, int); - -//felica.c -void felica_sendraw(PacketCommandNG *c); -void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip); -void felica_sim_lite(uint64_t uid); -void felica_dump_lite_s(); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/armsrc/buzzer.c b/armsrc/buzzer_disabled.c similarity index 100% rename from armsrc/buzzer.c rename to armsrc/buzzer_disabled.c diff --git a/armsrc/buzzer.h b/armsrc/buzzer_disabled.h similarity index 84% rename from armsrc/buzzer.h rename to armsrc/buzzer_disabled.h index 082450f04..c8b6e4472 100644 --- a/armsrc/buzzer.h +++ b/armsrc/buzzer_disabled.h @@ -5,10 +5,7 @@ #ifndef __BUZZER_H #define __BUZZER_H -#include -#include "proxmark3.h" -#include "apps.h" -#include "util.h" +#include "common.h" #define n_2_7khz 185 #define note_1 956 @@ -27,24 +24,3 @@ void Ring_ALL(uint16_t count); void Ring_Little_Star(uint16_t count); #endif - - - - - - - - - - - - - - - - - - - - - diff --git a/common/cmd.c b/armsrc/cmd.c similarity index 99% rename from common/cmd.c rename to armsrc/cmd.c index 6af0437d1..4b6dd3c1c 100644 --- a/common/cmd.c +++ b/armsrc/cmd.c @@ -30,7 +30,10 @@ * @brief */ #include "cmd.h" +#include "usb_cdc.h" +#include "usart.h" #include "crc16.h" +#include "string.h" // Flags to tell where to add CRC on sent replies bool reply_with_crc_on_usb = false; diff --git a/common/cmd.h b/armsrc/cmd.h similarity index 71% rename from common/cmd.h rename to armsrc/cmd.h index 261a1e1a0..e04f397a3 100644 --- a/common/cmd.h +++ b/armsrc/cmd.h @@ -35,14 +35,6 @@ #include "common.h" #include "pm3_cmd.h" -#include "usb_cdc.h" -#include "usart.h" -#include "proxmark3.h" - -int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len); -int reply_ng(uint16_t cmd, int16_t status, uint8_t *data, size_t len); -int reply_mix(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len); -int receive_ng(PacketCommandNG *rx); // Flags to tell where to add CRC on sent replies extern bool reply_with_crc_on_usb; @@ -51,33 +43,10 @@ extern bool reply_with_crc_on_fpc; extern bool reply_via_fpc; extern bool reply_via_usb; -extern void Dbprintf(const char *fmt, ...); -#define Dbprintf_usb(...) {\ - bool tmpfpc = reply_via_fpc;\ - bool tmpusb = reply_via_usb;\ - reply_via_fpc = false;\ - reply_via_usb = true;\ - Dbprintf(__VA_ARGS__);\ - reply_via_fpc = tmpfpc;\ - reply_via_usb = tmpusb;} - -#define Dbprintf_fpc(...) {\ - bool tmpfpc = reply_via_fpc;\ - bool tmpusb = reply_via_usb;\ - reply_via_fpc = true;\ - reply_via_usb = false;\ - Dbprintf(__VA_ARGS__);\ - reply_via_fpc = tmpfpc;\ - reply_via_usb = tmpusb;} - -#define Dbprintf_all(...) {\ - bool tmpfpc = reply_via_fpc;\ - bool tmpusb = reply_via_usb;\ - reply_via_fpc = true;\ - reply_via_usb = true;\ - Dbprintf(__VA_ARGS__);\ - reply_via_fpc = tmpfpc;\ - reply_via_usb = tmpusb;} +int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len); +int reply_ng(uint16_t cmd, int16_t status, uint8_t *data, size_t len); +int reply_mix(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len); +int receive_ng(PacketCommandNG *rx); #endif // _PROXMARK_CMD_H_ diff --git a/armsrc/dbprint.c b/armsrc/dbprint.c new file mode 100644 index 000000000..a26b7ba8b --- /dev/null +++ b/armsrc/dbprint.c @@ -0,0 +1,130 @@ +//----------------------------------------------------------------------------- +// Jonathan Westhues, Mar 2006 +// Edits by Gerhard de Koning Gans, Sep 2007 (##) +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// The main application code. This is the first thing called after start.c +// executes. +//----------------------------------------------------------------------------- + +#include "dbprint.h" + +#include "string.h" +#include "cmd.h" +#include "printf.h" + +#define DEBUG 1 + +//============================================================================= +// Debug print functions, to go out over USB, to the usual PC-side client. +//============================================================================= + +void DbpStringEx(uint32_t flags, char *str) { +#if DEBUG + struct { + uint16_t flag; + uint8_t buf[PM3_CMD_DATA_SIZE - sizeof(uint16_t)]; + } PACKED data; + data.flag = flags; + uint16_t len = MIN(strlen(str), sizeof(data.buf)); + memcpy(data.buf, str, len); + reply_ng(CMD_DEBUG_PRINT_STRING, PM3_SUCCESS, (uint8_t *)&data, sizeof(data.flag) + len); +#endif +} + +void DbpString(char *str) { +#if DEBUG + DbpStringEx(FLAG_LOG, str); +#endif +} + +void DbprintfEx(uint32_t flags, const char *fmt, ...) { +#if DEBUG + // should probably limit size here; oh well, let's just use a big buffer + char output_string[128] = {0x00}; + va_list ap; + va_start(ap, fmt); + kvsprintf(fmt, output_string, 10, ap); + va_end(ap); + + DbpStringEx(flags, output_string); +#endif +} + +void Dbprintf(const char *fmt, ...) { +#if DEBUG + // should probably limit size here; oh well, let's just use a big buffer + char output_string[128] = {0x00}; + va_list ap; + + va_start(ap, fmt); + kvsprintf(fmt, output_string, 10, ap); + va_end(ap); + + DbpString(output_string); +#endif +} + +// prints HEX & ASCII +void Dbhexdump(int len, uint8_t *d, bool bAsci) { +#if DEBUG + char ascii[9]; + + while (len > 0) { + + int l = (len > 8) ? 8 : len; + + memcpy(ascii, d, l); + ascii[l] = 0; + + // filter safe ascii + for (int i = 0; i < l; i++) { + if (ascii[i] < 32 || ascii[i] > 126) { + ascii[i] = '.'; + } + } + + if (bAsci) + Dbprintf("%-8s %*D", ascii, l, d, " "); + else + Dbprintf("%*D", l, d, " "); + + len -= 8; + d += 8; + } +#endif +} + +void print_result(char *name, uint8_t *buf, size_t len) { + + uint8_t *p = buf; + uint16_t tmp = len & 0xFFF0; + + for (; p - buf < tmp; p += 16) { + Dbprintf("[%s: %02d/%02d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + name, + p - buf, + len, + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15] + ); + } + if (len % 16 != 0) { + char s[46] = {0}; + char *sp = s; + for (; p - buf < len; p++) { + sprintf(sp, "%02x ", p[0]); + sp += 3; + } + Dbprintf("[%s: %02d/%02d] %s", name, p - buf, len, s); + } +} + +/* useful when debugging new protocol implementations like FeliCa +void PrintToSendBuffer(void) { + DbpString("Printing ToSendBuffer:"); + Dbhexdump(ToSendMax, ToSend, 0); +} +*/ diff --git a/armsrc/dbprint.h b/armsrc/dbprint.h new file mode 100644 index 000000000..54b813218 --- /dev/null +++ b/armsrc/dbprint.h @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------------- +// Jonathan Westhues, Aug 2005 +// Gerhard de Koning Gans, April 2008, May 2011 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Definitions internal to the app source. +//----------------------------------------------------------------------------- +#ifndef __DBPRINT_H +#define __DBPRINT_H + +#include "common.h" +#include "ansi.h" + +#define Dbprintf_usb(...) {\ + bool tmpfpc = reply_via_fpc;\ + bool tmpusb = reply_via_usb;\ + reply_via_fpc = false;\ + reply_via_usb = true;\ + Dbprintf(__VA_ARGS__);\ + reply_via_fpc = tmpfpc;\ + reply_via_usb = tmpusb;} + +#define Dbprintf_fpc(...) {\ + bool tmpfpc = reply_via_fpc;\ + bool tmpusb = reply_via_usb;\ + reply_via_fpc = true;\ + reply_via_usb = false;\ + Dbprintf(__VA_ARGS__);\ + reply_via_fpc = tmpfpc;\ + reply_via_usb = tmpusb;} + +#define Dbprintf_all(...) {\ + bool tmpfpc = reply_via_fpc;\ + bool tmpusb = reply_via_usb;\ + reply_via_fpc = true;\ + reply_via_usb = true;\ + Dbprintf(__VA_ARGS__);\ + reply_via_fpc = tmpfpc;\ + reply_via_usb = tmpusb;} + + +void DbpString(char *str); +void DbpStringEx(uint32_t flags, char *str); +void Dbprintf(const char *fmt, ...); +void DbprintfEx(uint32_t flags, const char *fmt, ...); +void Dbhexdump(int len, uint8_t *d, bool bAsci); +void print_result(char *name, uint8_t *buf, size_t len); +//void PrintToSendBuffer(void); + +#endif diff --git a/armsrc/des.c b/armsrc/des.c index 41b30734c..b84bc4c30 100644 --- a/armsrc/des.c +++ b/armsrc/des.c @@ -27,6 +27,7 @@ */ #include "des.h" +#include "string.h" const uint8_t sbox[256] = { /* S-box 1 */ diff --git a/armsrc/des.h b/armsrc/des.h index 0d2cceefb..8cf41b8ae 100644 --- a/armsrc/des.h +++ b/armsrc/des.h @@ -27,8 +27,7 @@ #ifndef __DES_H_ #define __DES_H_ -#include -#include +#include "common.h" /* the FIPS 46-3 (1999-10-25) name for triple DES is triple data encryption algorithm so TDEA. * Also we only implement the three key mode */ diff --git a/common/desfire.h b/armsrc/desfire.h similarity index 98% rename from common/desfire.h rename to armsrc/desfire.h index 41e5b6e12..5fa7e8d48 100644 --- a/common/desfire.h +++ b/armsrc/desfire.h @@ -1,9 +1,7 @@ #ifndef __DESFIRE_H #define __DESFIRE_H -#include -#include -#include "mbedtls/aes.h" +#include "common.h" #include "mifare.h" #define MAX_CRYPTO_BLOCK_SIZE 16 diff --git a/armsrc/desfire_crypto.h b/armsrc/desfire_crypto.h deleted file mode 100644 index 9964d094f..000000000 --- a/armsrc/desfire_crypto.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __DESFIRE_CRYPTO_H -#define __DESFIRE_CRYPTO_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "crc32.h" -#include "printf.h" -#include "desfire.h" -#include "iso14443a.h" - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/armsrc/desfire_crypto.c b/armsrc/desfire_crypto_disabled.c similarity index 99% rename from armsrc/desfire_crypto.c rename to armsrc/desfire_crypto_disabled.c index 2e9d5a8d3..d835a55d4 100644 --- a/armsrc/desfire_crypto.c +++ b/armsrc/desfire_crypto_disabled.c @@ -25,8 +25,16 @@ * Recommendation for Block Cipher Modes of Operation: The CMAC Mode for Authentication * May 2005 */ +#include + #include "desfire_crypto.h" +#include "crc32.h" +#include "printf.h" +#include "desfire.h" +#include "iso14443a.h" +#include "mbedtls/aes.h" + static void xor(const uint8_t *ivect, uint8_t *data, const size_t len); static size_t key_macing_length(desfirekey_t key); diff --git a/armsrc/desfire_crypto_disabled.h b/armsrc/desfire_crypto_disabled.h new file mode 100644 index 000000000..23043b30d --- /dev/null +++ b/armsrc/desfire_crypto_disabled.h @@ -0,0 +1,18 @@ +#ifndef __DESFIRE_CRYPTO_H +#define __DESFIRE_CRYPTO_H + +#include "common.h" +#include "desfire.h" + +void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings); +void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings); +void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size); +void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation); +size_t key_block_size(const desfirekey_t key); +size_t padded_data_length(const size_t nbytes, const size_t block_size); +size_t maced_data_length(const desfirekey_t key, const size_t nbytes); +size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int communication_settings); +void cmac_generate_subkeys(desfirekey_t key); +void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac); + +#endif diff --git a/armsrc/desfire_key.c b/armsrc/desfire_key.c index e1f880c8b..272f18562 100644 --- a/armsrc/desfire_key.c +++ b/armsrc/desfire_key.c @@ -18,6 +18,7 @@ */ #include "desfire_key.h" +#include "string.h" static inline void update_key_schedules(desfirekey_t key); diff --git a/armsrc/desfire_key.h b/armsrc/desfire_key.h index 4fc02854e..603fd5663 100644 --- a/armsrc/desfire_key.h +++ b/armsrc/desfire_key.h @@ -1,11 +1,8 @@ #ifndef __DESFIRE_KEY_INCLUDED #define __DESFIRE_KEY_INCLUDED -#include -#include -#include "iso14443a.h" +#include "common.h" #include "desfire.h" -//#include "mifare.h" // iso14a_card_select_t struct void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key); void Desfire_3des_key_new(const uint8_t value[16], desfirekey_t key); void Desfire_des_key_new_with_version(const uint8_t value[8], desfirekey_t key); @@ -17,4 +14,5 @@ void Desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version, uint8_t Desfire_key_get_version(desfirekey_t key); void Desfire_key_set_version(desfirekey_t key, uint8_t version); void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key); + #endif diff --git a/common/emvtags.h b/armsrc/emvtags.h similarity index 99% rename from common/emvtags.h rename to armsrc/emvtags.h index 9315258fc..c64b248a3 100644 --- a/common/emvtags.h +++ b/armsrc/emvtags.h @@ -12,8 +12,7 @@ #ifndef __EMVCARD_H #define __EMVCARD_H -#include -#include +#include "common.h" //structure to hold received/set tag values //variable data inputs have length specifiers diff --git a/armsrc/epa.c b/armsrc/epa.c index fabeec6d2..c43b35c98 100644 --- a/armsrc/epa.c +++ b/armsrc/epa.c @@ -12,6 +12,16 @@ //----------------------------------------------------------------------------- #include "epa.h" +#include "cmd.h" +#include "fpgaloader.h" +#include "iso14443a.h" +#include "iso14443b.h" +#include "string.h" +#include "util.h" +#include "dbprint.h" +#include "commonutil.h" +#include "ticks.h" + // Protocol and Parameter Selection Request for ISO 14443 type A cards // use regular (1x) speed in both directions // CRC is already included @@ -470,14 +480,14 @@ void EPA_PACE_Replay(PacketCommandNG *c) { uint8_t response_apdu[300] = {0}; // now replay the data and measure the timings - for (int i = 0; i < sizeof(apdu_lengths_replay); i++) { + for (int i = 0; i < ARRAYLEN(apdu_lengths_replay); i++) { StartCountUS(); func_return = EPA_APDU(apdus_replay[i].data, apdu_lengths_replay[i], response_apdu); timings[i] = GetCountUS(); // every step but the last one should succeed - if (i < sizeof(apdu_lengths_replay) - 1 + if (i < ARRAYLEN(apdu_lengths_replay) - 1 && (func_return < 6 || response_apdu[func_return - 4] != 0x90 || response_apdu[func_return - 3] != 0x00)) { diff --git a/armsrc/epa.h b/armsrc/epa.h index a0701ab57..66a95c059 100644 --- a/armsrc/epa.h +++ b/armsrc/epa.h @@ -11,9 +11,8 @@ #ifndef __EPA_H #define __EPA_H -#include "cmd.h" -#include "iso14443a.h" -#include "iso14443b.h" +#include "common.h" +#include "pm3_cmd.h" // this struct is used by EPA_Parse_CardAccess and contains info about the // PACE protocol supported by the chip @@ -23,8 +22,6 @@ typedef struct { uint8_t parameter_id; } pace_version_info_t; -// note: EPA_PACE_Collect_Nonce and EPA_PACE_Replay are declared in apps.h - // general functions void EPA_Finish(); size_t EPA_Parse_CardAccess(uint8_t *data, @@ -37,4 +34,7 @@ int EPA_Setup(); int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password); int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce); +void EPA_PACE_Collect_Nonce(PacketCommandNG *c); +void EPA_PACE_Replay(PacketCommandNG *c); + #endif /* __EPA_H */ diff --git a/armsrc/felica.c b/armsrc/felica.c index 48b6f4464..322d11327 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -1,13 +1,18 @@ -#include "proxmark3.h" -#include "apps.h" +#include "felica.h" +#include "proxmark3_arm.h" #include "BigBuf.h" #include "util.h" -#include "usb_cdc.h" // for usb_poll_validate_length #include "protocols.h" #include "crc16.h" // crc16 ccitt +#include "fpgaloader.h" +#include "string.h" +#include "commonutil.h" +#include "dbprint.h" +#include "ticks.h" +#include "mifare.h" // FeliCa timings -// minimum time between the start bits of consecutive transfers from reader to tag: 6800 carrier (13.56Mhz) cycles +// minimum time between the start bits of consecutive transfers from reader to tag: 6800 carrier (13.56MHz) cycles #ifndef FELICA_REQUEST_GUARD_TIME # define FELICA_REQUEST_GUARD_TIME (6800/16 + 1) #endif @@ -746,7 +751,7 @@ void felica_dump_lite_s() { // for (c=0; c < 8; c++) // ndef[c] = FelicaFrame.framebytes[c+4]; - for (blknum = 0; blknum < sizeof(liteblks);) { + for (blknum = 0; blknum < ARRAYLEN(liteblks);) { // block to read. BuildFliteRdblk(ndef, 1, &liteblks[blknum]); diff --git a/armsrc/Standalone/lf_proxbrute.h b/armsrc/felica.h similarity index 52% rename from armsrc/Standalone/lf_proxbrute.h rename to armsrc/felica.h index 3a9e1ce29..ef34dc108 100644 --- a/armsrc/Standalone/lf_proxbrute.h +++ b/armsrc/felica.h @@ -1,21 +1,22 @@ //----------------------------------------------------------------------------- -// Samy Kamkar, 2011, 2012 -// Brad antoniewicz 2011 -// Christian Herrmann, 2017 +// Jonathan Westhues, Aug 2005 +// Gerhard de Koning Gans, April 2008, May 2011 // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// StandAlone Mod +// Definitions internal to the app source. //----------------------------------------------------------------------------- +#ifndef __FELICA_H +#define __FELICA_H -#ifndef __LF_PROXBRUTE_H -#define __LF_PROXBRUTE_H +#include "common.h" +#include "cmd.h" -#include "standalone.h" // standalone definitions -#include "apps.h" // debugstatements, lfops? +void felica_sendraw(PacketCommandNG *c); +void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip); +void felica_sim_lite(uint64_t uid); +void felica_dump_lite_s(); -#define OPTS 2 - -#endif /* __LF_PROXBRUTE_H */ +#endif diff --git a/armsrc/flashmem.c b/armsrc/flashmem.c index 7bca9ddf9..fb69dee01 100644 --- a/armsrc/flashmem.c +++ b/armsrc/flashmem.c @@ -1,6 +1,11 @@ #include "flashmem.h" #include "pmflash.h" +#include "proxmark3_arm.h" +#include "ticks.h" +#include "dbprint.h" +#include "string.h" + /* here: use NCPS2 @ PA10: */ #define SPI_CSR_NUM 2 #define SPI_PCS(npcs) ((~(1 << (npcs)) & 0xF) << 16) @@ -16,7 +21,7 @@ uint32_t FLASHMEM_SPIBAUDRATE = FLASH_BAUD; void FlashmemSetSpiBaudrate(uint32_t baudrate) { FLASHMEM_SPIBAUDRATE = baudrate; - Dbprintf("Spi Baudrate : %dMhz", FLASHMEM_SPIBAUDRATE / 1000000); + Dbprintf("Spi Baudrate : %dMHz", FLASHMEM_SPIBAUDRATE / 1000000); } // initialize @@ -563,6 +568,7 @@ void Flashmem_print_info(void) { uint8_t keysum[2]; uint16_t num; + Flash_CheckBusy(BUSY_TIMEOUT); uint16_t isok = Flash_ReadDataCont(DEFAULT_MF_KEYS_OFFSET, keysum, 2); if (isok == 2) { num = ((keysum[1] << 8) | keysum[0]); @@ -570,6 +576,7 @@ void Flashmem_print_info(void) { Dbprintf(" Mifare.................."_YELLOW_("%d")"keys", num); } + Flash_CheckBusy(BUSY_TIMEOUT); isok = Flash_ReadDataCont(DEFAULT_T55XX_KEYS_OFFSET, keysum, 2); if (isok == 2) { num = ((keysum[1] << 8) | keysum[0]); @@ -577,6 +584,7 @@ void Flashmem_print_info(void) { Dbprintf(" T55x7..................."_YELLOW_("%d")"keys", num); } + Flash_CheckBusy(BUSY_TIMEOUT); isok = Flash_ReadDataCont(DEFAULT_ICLASS_KEYS_OFFSET, keysum, 2); if (isok == 2) { num = ((keysum[1] << 8) | keysum[0]); diff --git a/armsrc/flashmem.h b/armsrc/flashmem.h index 26d2d974d..42fc3d2f0 100644 --- a/armsrc/flashmem.h +++ b/armsrc/flashmem.h @@ -28,9 +28,7 @@ #ifndef __FLASHMEM_H #define __FLASHMEM_H -#include "proxmark3.h" -#include "apps.h" -#include "ticks.h" +#include "common.h" // Used Command #define ID 0x90 @@ -102,7 +100,6 @@ #define MAX_BLOCKS 4 #define MAX_SECTORS 16 -#define MCK 48000000 //#define FLASH_BAUD 24000000 #define FLASH_MINFAST 24000000 //33000000 #define FLASH_BAUD MCK/2 @@ -112,7 +109,6 @@ #define FASTFLASH (FLASHMEM_SPIBAUDRATE > FLASH_MINFAST) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -void Dbprintf(const char *fmt, ...); void FlashmemSetSpiBaudrate(uint32_t baudrate); bool FlashInit(); diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index 7e920a360..87213df96 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -11,6 +11,15 @@ //----------------------------------------------------------------------------- #include "fpgaloader.h" +#include "proxmark3_arm.h" +#include "appmain.h" +#include "BigBuf.h" +#include "ticks.h" +#include "dbprint.h" +#include "util.h" +#include "zlib.h" +#include "fpga.h" +#include "string.h" // remember which version of the bitstream we have already downloaded to the FPGA static int downloaded_bitstream = 0; @@ -81,7 +90,7 @@ void SetupSpi(int mode) { AT91C_BASE_SPI->SPI_CSR[0] = (1 << 24) | // Delay between Consecutive Transfers (32 MCK periods) (1 << 16) | // Delay Before SPCK (1 MCK period) - (6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud + (6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24MHz/6 = 4M baud AT91C_SPI_BITS_16 | // Bits per Transfer (16 bits) (0 << 3) | // Chip Select inactive after transfer AT91C_SPI_NCPHA | // Clock Phase data captured on leading edge, changes on following edge @@ -101,7 +110,7 @@ void SetupSpi(int mode) { AT91C_BASE_SPI->SPI_CSR[2] = ( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods) ( 1 << 16) | // Delay Before SPCK (1 MCK period) - ( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud + ( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24MHz/6 = 4M baud AT91C_SPI_BITS_9 | // Bits per Transfer (9 bits) ( 0 << 3) | // Chip Select inactive after transfer ( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge @@ -153,8 +162,7 @@ void FpgaSetupSsc(void) { //----------------------------------------------------------------------------- // Set up DMA to receive samples from the FPGA. We will use the PDC, with // a single buffer as a circular buffer (so that we just chain back to -// ourselves, not to another buffer). The stuff to manipulate those buffers -// is in apps.h, because it should be inlined, for speed. +// ourselves, not to another buffer). //----------------------------------------------------------------------------- bool FpgaSetupSscDma(uint8_t *buf, int len) { if (buf == NULL) return false; @@ -395,6 +403,8 @@ void FpgaDownloadAndGo(int bitstream_version) { if (downloaded_bitstream == bitstream_version) return; + // Send waiting time extension request as this will take a while + send_wtx(1500); z_stream compressed_fpga_stream; uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00}; diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index f9b0e44b0..83c5bb2e4 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -12,32 +12,10 @@ #ifndef __FPGALOADER_H #define __FPGALOADER_H -#include -#include -#include "apps.h" -#include "fpga.h" -#include "common.h" // standard definitions -#include "proxmark3.h" // common area -#include "string.h" -#include "BigBuf.h" // bigbuf mem -#include "zlib.h" // uncompress +#include "common.h" - -void FpgaSendCommand(uint16_t cmd, uint16_t v); -void FpgaWriteConfWord(uint8_t v); -void FpgaDownloadAndGo(int bitstream_version); -// void FpgaGatherVersion(int bitstream_version, char *dst, int len); -void FpgaSetupSsc(void); -void SetupSpi(int mode); -bool FpgaSetupSscDma(uint8_t *buf, int len); -void Fpga_print_status(void); -int FpgaGetCurrent(void); #define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; #define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; -void SetAdcMuxFor(uint32_t whichGpio); - -// extern and generel turn off the antenna method -void switch_off(void); // definitions for multiple FPGA config files support #define FPGA_BITSTREAM_LF 1 @@ -97,4 +75,18 @@ void switch_off(void); #define FPGA_HF_ISO18092_FLAG_424K (2<<0) // 0010 should enable 414k mode (untested). No autodetect #define FPGA_HF_ISO18092_FLAG_READER (4<<0) // 0100 enables antenna power, to act as a reader instead of tag +void FpgaSendCommand(uint16_t cmd, uint16_t v); +void FpgaWriteConfWord(uint8_t v); +void FpgaDownloadAndGo(int bitstream_version); +// void FpgaGatherVersion(int bitstream_version, char *dst, int len); +void FpgaSetupSsc(void); +void SetupSpi(int mode); +bool FpgaSetupSscDma(uint8_t *buf, int len); +void Fpga_print_status(void); +int FpgaGetCurrent(void); +void SetAdcMuxFor(uint32_t whichGpio); + +// extern and generel turn off the antenna method +void switch_off(void); + #endif diff --git a/armsrc/frozen.c b/armsrc/frozen.c new file mode 100644 index 000000000..a43300319 --- /dev/null +++ b/armsrc/frozen.c @@ -0,0 +1,1470 @@ +/* + * Copyright (c) 2004-2013 Sergey Lyubka + * Copyright (c) 2018 Cesanta Software Limited + * All rights reserved + * + * Licensed under the Apache License, Version 2.0 (the ""License""); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an ""AS IS"" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005+ */ + +#include "frozen.h" + +#include +#include +#include "nprintf.h" + +#include "BigBuf.h" +#define malloc(X) BigBuf_malloc(X) +#define free(X) + +#if !defined(WEAK) +#if (defined(__GNUC__) || defined(__TI_COMPILER_VERSION__)) && !defined(_WIN32) +#define WEAK __attribute__((weak)) +#else +#define WEAK +#endif +#endif + +#ifdef _WIN32 +#undef snprintf +#undef vsnprintf +#define snprintf cs_win_snprintf +#define vsnprintf cs_win_vsnprintf +int cs_win_snprintf(char *str, size_t size, const char *format, ...); +int cs_win_vsnprintf(char *str, size_t size, const char *format, va_list ap); +#if _MSC_VER >= 1700 +#include "stdint.h" +#else +typedef _int64 int64_t; +typedef unsigned _int64 uint64_t; +#endif +#define PRId64 "I64d" +#define PRIu64 "I64u" +#else /* _WIN32 */ +/* wants this for C++ */ +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif +#include +#endif /* _WIN32 */ + +#ifndef INT64_FMT +#define INT64_FMT PRId64 +#endif +#ifndef UINT64_FMT +#define UINT64_FMT PRIu64 +#endif + +#ifndef va_copy +#define va_copy(x, y) x = y +#endif + +#ifndef JSON_ENABLE_ARRAY +#define JSON_ENABLE_ARRAY 1 +#endif + +struct frozen { + const char *end; + const char *cur; + + const char *cur_name; + size_t cur_name_len; + + /* For callback API */ + char path[JSON_MAX_PATH_LEN]; + size_t path_len; + void *callback_data; + json_walk_callback_t callback; +}; + +struct fstate { + const char *ptr; + size_t path_len; +}; + +#define SET_STATE(fr, ptr, str, len) \ + struct fstate fstate = {(ptr), (fr)->path_len}; \ + json_append_to_path((fr), (str), (len)); + +#define CALL_BACK(fr, tok, value, len) \ + do { \ + if ((fr)->callback && \ + ((fr)->path_len == 0 || (fr)->path[(fr)->path_len - 1] != '.')) { \ + struct json_token t = {(value), (int) (len), (tok)}; \ + \ + /* Call the callback with the given value and current name */ \ + (fr)->callback((fr)->callback_data, (fr)->cur_name, (fr)->cur_name_len, \ + (fr)->path, &t); \ + \ + /* Reset the name */ \ + (fr)->cur_name = NULL; \ + (fr)->cur_name_len = 0; \ + } \ + } while (0) + +static int json_append_to_path(struct frozen *f, const char *str, int size) { + int n = f->path_len; + int left = sizeof(f->path) - n - 1; + if (size > left) size = left; + memcpy(f->path + n, str, size); + f->path[n + size] = '\0'; + f->path_len += size; + return n; +} + +static void json_truncate_path(struct frozen *f, size_t len) { + f->path_len = len; + f->path[len] = '\0'; +} + +static int json_parse_object(struct frozen *f); +static int json_parse_value(struct frozen *f); + +#define EXPECT(cond, err_code) \ + do { \ + if (!(cond)) return (err_code); \ + } while (0) + +#define TRY(expr) \ + do { \ + int _n = expr; \ + if (_n < 0) return _n; \ + } while (0) + +#define END_OF_STRING (-1) + +static int json_left(const struct frozen *f) { + return f->end - f->cur; +} + +static int json_isspace(int ch) { + return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'; +} + +static void json_skip_whitespaces(struct frozen *f) { + while (f->cur < f->end && json_isspace(*f->cur)) f->cur++; +} + +static int json_cur(struct frozen *f) { + json_skip_whitespaces(f); + return f->cur >= f->end ? END_OF_STRING : *(unsigned char *) f->cur; +} + +static int json_test_and_skip(struct frozen *f, int expected) { + int ch = json_cur(f); + if (ch == expected) { + f->cur++; + return 0; + } + return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID; +} + +static int json_isalpha(int ch) { + return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); +} + +static int json_isdigit(int ch) { + return ch >= '0' && ch <= '9'; +} + +static int json_isxdigit(int ch) { + return json_isdigit(ch) || (ch >= 'a' && ch <= 'f') || + (ch >= 'A' && ch <= 'F'); +} + +static int json_get_escape_len(const char *s, int len) { + switch (*s) { + case 'u': + return len < 6 ? JSON_STRING_INCOMPLETE + : json_isxdigit(s[1]) && json_isxdigit(s[2]) && + json_isxdigit(s[3]) && json_isxdigit(s[4]) + ? 5 + : JSON_STRING_INVALID; + case '"': + case '\\': + case '/': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + return len < 2 ? JSON_STRING_INCOMPLETE : 1; + default: + return JSON_STRING_INVALID; + } +} + +/* identifier = letter { letter | digit | '_' } */ +static int json_parse_identifier(struct frozen *f) { + EXPECT(json_isalpha(json_cur(f)), JSON_STRING_INVALID); + { + SET_STATE(f, f->cur, "", 0); + while (f->cur < f->end && + (*f->cur == '_' || json_isalpha(*f->cur) || json_isdigit(*f->cur))) { + f->cur++; + } + json_truncate_path(f, fstate.path_len); + CALL_BACK(f, JSON_TYPE_STRING, fstate.ptr, f->cur - fstate.ptr); + } + return 0; +} + +static int json_get_utf8_char_len(unsigned char ch) { + if ((ch & 0x80) == 0) return 1; + switch (ch & 0xf0) { + case 0xf0: + return 4; + case 0xe0: + return 3; + default: + return 2; + } +} + +/* string = '"' { quoted_printable_chars } '"' */ +static int json_parse_string(struct frozen *f) { + int n, ch = 0, len = 0; + TRY(json_test_and_skip(f, '"')); + { + SET_STATE(f, f->cur, "", 0); + for (; f->cur < f->end; f->cur += len) { + ch = *(unsigned char *) f->cur; + len = json_get_utf8_char_len((unsigned char) ch); + EXPECT(ch >= 32 && len > 0, JSON_STRING_INVALID); /* No control chars */ + EXPECT(len <= json_left(f), JSON_STRING_INCOMPLETE); + if (ch == '\\') { + EXPECT((n = json_get_escape_len(f->cur + 1, json_left(f))) > 0, n); + len += n; + } else if (ch == '"') { + json_truncate_path(f, fstate.path_len); + CALL_BACK(f, JSON_TYPE_STRING, fstate.ptr, f->cur - fstate.ptr); + f->cur++; + break; + }; + } + } + return ch == '"' ? 0 : JSON_STRING_INCOMPLETE; +} + +/* number = [ '-' ] digit+ [ '.' digit+ ] [ ['e'|'E'] ['+'|'-'] digit+ ] */ +static int json_parse_number(struct frozen *f) { + int ch = json_cur(f); + SET_STATE(f, f->cur, "", 0); + if (ch == '-') f->cur++; + EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE); + if (f->cur + 1 < f->end && f->cur[0] == '0' && f->cur[1] == 'x') { + f->cur += 2; + EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE); + EXPECT(json_isxdigit(f->cur[0]), JSON_STRING_INVALID); + while (f->cur < f->end && json_isxdigit(f->cur[0])) f->cur++; + } else { + EXPECT(json_isdigit(f->cur[0]), JSON_STRING_INVALID); + while (f->cur < f->end && json_isdigit(f->cur[0])) f->cur++; + if (f->cur < f->end && f->cur[0] == '.') { + f->cur++; + EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE); + EXPECT(json_isdigit(f->cur[0]), JSON_STRING_INVALID); + while (f->cur < f->end && json_isdigit(f->cur[0])) f->cur++; + } + if (f->cur < f->end && (f->cur[0] == 'e' || f->cur[0] == 'E')) { + f->cur++; + EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE); + if ((f->cur[0] == '+' || f->cur[0] == '-')) f->cur++; + EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE); + EXPECT(json_isdigit(f->cur[0]), JSON_STRING_INVALID); + while (f->cur < f->end && json_isdigit(f->cur[0])) f->cur++; + } + } + json_truncate_path(f, fstate.path_len); + CALL_BACK(f, JSON_TYPE_NUMBER, fstate.ptr, f->cur - fstate.ptr); + return 0; +} + +#if JSON_ENABLE_ARRAY +/* array = '[' [ value { ',' value } ] ']' */ +static int json_parse_array(struct frozen *f) { + int i = 0, current_path_len; + char buf[20]; + CALL_BACK(f, JSON_TYPE_ARRAY_START, NULL, 0); + TRY(json_test_and_skip(f, '[')); + { + { + SET_STATE(f, f->cur - 1, "", 0); + while (json_cur(f) != ']') { + snprintf(buf, sizeof(buf), "[%d]", i); + i++; + current_path_len = json_append_to_path(f, buf, strlen(buf)); + f->cur_name = + f->path + strlen(f->path) - strlen(buf) + 1 /*opening brace*/; + f->cur_name_len = strlen(buf) - 2 /*braces*/; + TRY(json_parse_value(f)); + json_truncate_path(f, current_path_len); + if (json_cur(f) == ',') f->cur++; + } + TRY(json_test_and_skip(f, ']')); + json_truncate_path(f, fstate.path_len); + CALL_BACK(f, JSON_TYPE_ARRAY_END, fstate.ptr, f->cur - fstate.ptr); + } + } + return 0; +} +#endif /* JSON_ENABLE_ARRAY */ + +static int json_expect(struct frozen *f, const char *s, int len, + enum json_token_type tok_type) { + int i, n = json_left(f); + SET_STATE(f, f->cur, "", 0); + for (i = 0; i < len; i++) { + if (i >= n) return JSON_STRING_INCOMPLETE; + if (f->cur[i] != s[i]) return JSON_STRING_INVALID; + } + f->cur += len; + json_truncate_path(f, fstate.path_len); + + CALL_BACK(f, tok_type, fstate.ptr, f->cur - fstate.ptr); + + return 0; +} + +/* value = 'null' | 'true' | 'false' | number | string | array | object */ +static int json_parse_value(struct frozen *f) { + int ch = json_cur(f); + + switch (ch) { + case '"': + TRY(json_parse_string(f)); + break; + case '{': + TRY(json_parse_object(f)); + break; +#if JSON_ENABLE_ARRAY + case '[': + TRY(json_parse_array(f)); + break; +#endif + case 'n': + TRY(json_expect(f, "null", 4, JSON_TYPE_NULL)); + break; + case 't': + TRY(json_expect(f, "true", 4, JSON_TYPE_TRUE)); + break; + case 'f': + TRY(json_expect(f, "false", 5, JSON_TYPE_FALSE)); + break; + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + TRY(json_parse_number(f)); + break; + default: + return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID; + } + + return 0; +} + +/* key = identifier | string */ +static int json_parse_key(struct frozen *f) { + int ch = json_cur(f); + if (json_isalpha(ch)) { + TRY(json_parse_identifier(f)); + } else if (ch == '"') { + TRY(json_parse_string(f)); + } else { + return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID; + } + return 0; +} + +/* pair = key ':' value */ +static int json_parse_pair(struct frozen *f) { + int current_path_len; + const char *tok; + json_skip_whitespaces(f); + tok = f->cur; + TRY(json_parse_key(f)); + { + f->cur_name = *tok == '"' ? tok + 1 : tok; + f->cur_name_len = *tok == '"' ? f->cur - tok - 2 : f->cur - tok; + current_path_len = json_append_to_path(f, f->cur_name, f->cur_name_len); + } + TRY(json_test_and_skip(f, ':')); + TRY(json_parse_value(f)); + json_truncate_path(f, current_path_len); + return 0; +} + +/* object = '{' pair { ',' pair } '}' */ +static int json_parse_object(struct frozen *f) { + CALL_BACK(f, JSON_TYPE_OBJECT_START, NULL, 0); + TRY(json_test_and_skip(f, '{')); + { + SET_STATE(f, f->cur - 1, ".", 1); + while (json_cur(f) != '}') { + TRY(json_parse_pair(f)); + if (json_cur(f) == ',') f->cur++; + } + TRY(json_test_and_skip(f, '}')); + json_truncate_path(f, fstate.path_len); + CALL_BACK(f, JSON_TYPE_OBJECT_END, fstate.ptr, f->cur - fstate.ptr); + } + return 0; +} + +static int json_doit(struct frozen *f) { + if (f->cur == 0 || f->end < f->cur) return JSON_STRING_INVALID; + if (f->end == f->cur) return JSON_STRING_INCOMPLETE; + return json_parse_value(f); +} + +int json_escape(struct json_out *out, const char *p, size_t len) WEAK; +int json_escape(struct json_out *out, const char *p, size_t len) { + size_t i, cl, n = 0; + const char *hex_digits = "0123456789abcdef"; + const char *specials = "btnvfr"; + + for (i = 0; i < len; i++) { + unsigned char ch = ((unsigned char *) p)[i]; + if (ch == '"' || ch == '\\') { + n += out->printer(out, "\\", 1); + n += out->printer(out, p + i, 1); + } else if (ch >= '\b' && ch <= '\r') { + n += out->printer(out, "\\", 1); + n += out->printer(out, &specials[ch - '\b'], 1); + } else if (c_isprint(ch)) { + n += out->printer(out, p + i, 1); + } else if ((cl = json_get_utf8_char_len(ch)) == 1) { + n += out->printer(out, "\\u00", 4); + n += out->printer(out, &hex_digits[(ch >> 4) % 0xf], 1); + n += out->printer(out, &hex_digits[ch % 0xf], 1); + } else { + n += out->printer(out, p + i, cl); + i += cl - 1; + } + } + + return n; +} + +int json_printer_buf(struct json_out *out, const char *buf, size_t len) WEAK; +int json_printer_buf(struct json_out *out, const char *buf, size_t len) { + size_t avail = out->u.buf.size - out->u.buf.len; + size_t n = len < avail ? len : avail; + memcpy(out->u.buf.buf + out->u.buf.len, buf, n); + out->u.buf.len += n; + if (out->u.buf.size > 0) { + size_t idx = out->u.buf.len; + if (idx >= out->u.buf.size) idx = out->u.buf.size - 1; + out->u.buf.buf[idx] = '\0'; + } + return len; +} + +int json_printer_file(struct json_out *out, const char *buf, size_t len) WEAK; +int json_printer_file(struct json_out *out, const char *buf, size_t len) { + return fwrite(buf, 1, len, out->u.fp); +} + +#if JSON_ENABLE_BASE64 +static int b64idx(int c) { + if (c < 26) { + return c + 'A'; + } else if (c < 52) { + return c - 26 + 'a'; + } else if (c < 62) { + return c - 52 + '0'; + } else { + return c == 62 ? '+' : '/'; + } +} + +static int b64rev(int c) { + if (c >= 'A' && c <= 'Z') { + return c - 'A'; + } else if (c >= 'a' && c <= 'z') { + return c + 26 - 'a'; + } else if (c >= '0' && c <= '9') { + return c + 52 - '0'; + } else if (c == '+') { + return 62; + } else if (c == '/') { + return 63; + } else { + return 64; + } +} + +static int b64enc(struct json_out *out, const unsigned char *p, int n) { + char buf[4]; + int i, len = 0; + for (i = 0; i < n; i += 3) { + int a = p[i], b = i + 1 < n ? p[i + 1] : 0, c = i + 2 < n ? p[i + 2] : 0; + buf[0] = b64idx(a >> 2); + buf[1] = b64idx((a & 3) << 4 | (b >> 4)); + buf[2] = b64idx((b & 15) << 2 | (c >> 6)); + buf[3] = b64idx(c & 63); + if (i + 1 >= n) buf[2] = '='; + if (i + 2 >= n) buf[3] = '='; + len += out->printer(out, buf, sizeof(buf)); + } + return len; +} + +static int b64dec(const char *src, int n, char *dst) { + const char *end = src + n; + int len = 0; + while (src + 3 < end) { + int a = b64rev(src[0]), b = b64rev(src[1]), c = b64rev(src[2]), + d = b64rev(src[3]); + dst[len++] = (a << 2) | (b >> 4); + if (src[2] != '=') { + dst[len++] = (b << 4) | (c >> 2); + if (src[3] != '=') { + dst[len++] = (c << 6) | d; + } + } + src += 4; + } + return len; +} +#endif /* JSON_ENABLE_BASE64 */ + +static unsigned char hexdec(const char *s) { +#define HEXTOI(x) (x >= '0' && x <= '9' ? x - '0' : x - 'W') + int a = c_tolower(*(const unsigned char *) s); + int b = c_tolower(*(const unsigned char *)(s + 1)); + return (HEXTOI(a) << 4) | HEXTOI(b); +} + +int json_vprintf(struct json_out *out, const char *fmt, va_list xap) WEAK; +int json_vprintf(struct json_out *out, const char *fmt, va_list xap) { + int len = 0; + const char *quote = "\"", *null = "null"; + va_list ap; + va_copy(ap, xap); + + while (*fmt != '\0') { + if (strchr(":, \r\n\t[]{}\"", *fmt) != NULL) { + len += out->printer(out, fmt, 1); + fmt++; + } else if (fmt[0] == '%') { + char buf[21]; + size_t skip = 2; + + if (fmt[1] == 'l' && fmt[2] == 'l' && (fmt[3] == 'd' || fmt[3] == 'u')) { + int64_t val = va_arg(ap, int64_t); + const char *fmt2 = fmt[3] == 'u' ? "%" UINT64_FMT : "%" INT64_FMT; + snprintf(buf, sizeof(buf), fmt2, val); + len += out->printer(out, buf, strlen(buf)); + skip += 2; + } else if (fmt[1] == 'z' && fmt[2] == 'u') { + size_t val = va_arg(ap, size_t); + snprintf(buf, sizeof(buf), "%lu", (unsigned long) val); + len += out->printer(out, buf, strlen(buf)); + skip += 1; + } else if (fmt[1] == 'M') { + json_printf_callback_t f = va_arg(ap, json_printf_callback_t); + len += f(out, &ap); + } else if (fmt[1] == 'B') { + int val = va_arg(ap, int); + const char *str = val ? "true" : "false"; + len += out->printer(out, str, strlen(str)); + } else if (fmt[1] == 'H') { +#if JSON_ENABLE_HEX + const char *hex = "0123456789abcdef"; + int i, n = va_arg(ap, int); + const unsigned char *p = va_arg(ap, const unsigned char *); + len += out->printer(out, quote, 1); + for (i = 0; i < n; i++) { + len += out->printer(out, &hex[(p[i] >> 4) & 0xf], 1); + len += out->printer(out, &hex[p[i] & 0xf], 1); + } + len += out->printer(out, quote, 1); +#endif /* JSON_ENABLE_HEX */ + } else if (fmt[1] == 'V') { +#if JSON_ENABLE_BASE64 + const unsigned char *p = va_arg(ap, const unsigned char *); + int n = va_arg(ap, int); + len += out->printer(out, quote, 1); + len += b64enc(out, p, n); + len += out->printer(out, quote, 1); +#endif /* JSON_ENABLE_BASE64 */ + } else if (fmt[1] == 'Q' || + (fmt[1] == '.' && fmt[2] == '*' && fmt[3] == 'Q')) { + size_t l = 0; + const char *p; + + if (fmt[1] == '.') { + l = (size_t) va_arg(ap, int); + skip += 2; + } + p = va_arg(ap, char *); + + if (p == NULL) { + len += out->printer(out, null, 4); + } else { + if (fmt[1] == 'Q') { + l = strlen(p); + } + len += out->printer(out, quote, 1); + len += json_escape(out, p, l); + len += out->printer(out, quote, 1); + } + } else { + /* + * we delegate printing to the system printf. + * The goal here is to delegate all modifiers parsing to the system + * printf, as you can see below we still have to parse the format + * types. + * + * Currently, %s with strings longer than 20 chars will require + * double-buffering (an auxiliary buffer will be allocated from heap). + * TODO(dfrank): reimplement %s and %.*s in order to avoid that. + */ + + const char *end_of_format_specifier = "sdfFeEgGlhuIcx.*-0123456789"; + int n = strspn(fmt + 1, end_of_format_specifier); + char *pbuf = buf; + int need_len, size = sizeof(buf); + char fmt2[20]; + va_list ap_copy; + strncpy(fmt2, fmt, + n + 1 > (int) sizeof(fmt2) ? sizeof(fmt2) : (size_t) n + 1); + fmt2[n + 1] = '\0'; + + va_copy(ap_copy, ap); + need_len = vsnprintf(pbuf, size, fmt2, ap_copy); + va_end(ap_copy); + + if (need_len < 0) { + /* + * Windows & eCos vsnprintf implementation return -1 on overflow + * instead of needed size. + */ + pbuf = NULL; + while (need_len < 0) { + free(pbuf); + size *= 2; + if ((pbuf = (char *) malloc(size)) == NULL) break; + va_copy(ap_copy, ap); + need_len = vsnprintf(pbuf, size, fmt2, ap_copy); + va_end(ap_copy); + } + } else if (need_len >= (int) sizeof(buf)) { + /* + * resulting string doesn't fit into a stack-allocated buffer `buf`, + * so we need to allocate a new buffer from heap and use it + */ + if ((pbuf = (char *) malloc(need_len + 1)) != NULL) { + va_copy(ap_copy, ap); + vsnprintf(pbuf, need_len + 1, fmt2, ap_copy); + va_end(ap_copy); + } + } + if (pbuf == NULL) { + buf[0] = '\0'; + pbuf = buf; + } + + /* + * however we need to parse the type ourselves in order to advance + * the va_list by the correct amount; there is no portable way to + * inherit the advancement made by vprintf. + * 32-bit (linux or windows) passes va_list by value. + */ + if ((n + 1 == strlen("%" PRId64) && strcmp(fmt2, "%" PRId64) == 0) || + (n + 1 == strlen("%" PRIu64) && strcmp(fmt2, "%" PRIu64) == 0)) { + (void) va_arg(ap, int64_t); + } else if (strcmp(fmt2, "%.*s") == 0) { + (void) va_arg(ap, int); + (void) va_arg(ap, char *); + } else { + switch (fmt2[n]) { + case 'u': + case 'd': + (void) va_arg(ap, int); + break; + case 'g': + case 'f': + (void) va_arg(ap, double); + break; + case 'p': + (void) va_arg(ap, void *); + break; + default: + /* many types are promoted to int */ + (void) va_arg(ap, int); + } + } + + len += out->printer(out, pbuf, strlen(pbuf)); + skip = n + 1; + + /* If buffer was allocated from heap, free it */ + if (pbuf != buf) { + free(pbuf); + pbuf = NULL; + } + } + fmt += skip; + } else if (*fmt == '_' || json_isalpha(*fmt)) { + len += out->printer(out, quote, 1); + while (*fmt == '_' || json_isalpha(*fmt) || json_isdigit(*fmt)) { + len += out->printer(out, fmt, 1); + fmt++; + } + len += out->printer(out, quote, 1); + } else { + len += out->printer(out, fmt, 1); + fmt++; + } + } + va_end(ap); + + return len; +} + +int json_printf(struct json_out *out, const char *fmt, ...) WEAK; +int json_printf(struct json_out *out, const char *fmt, ...) { + int n; + va_list ap; + va_start(ap, fmt); + n = json_vprintf(out, fmt, ap); + va_end(ap); + return n; +} + +int json_printf_array(struct json_out *out, va_list *ap) WEAK; +int json_printf_array(struct json_out *out, va_list *ap) { + int len = 0; + char *arr = va_arg(*ap, char *); + size_t i, arr_size = va_arg(*ap, size_t); + size_t elem_size = va_arg(*ap, size_t); + const char *fmt = va_arg(*ap, char *); + len += json_printf(out, "[", 1); + for (i = 0; arr != NULL && i < arr_size / elem_size; i++) { + union { + int64_t i; + double d; + } val; + memcpy(&val, arr + i * elem_size, + elem_size > sizeof(val) ? sizeof(val) : elem_size); + if (i > 0) len += json_printf(out, ", "); + if (strpbrk(fmt, "efg") != NULL) { + len += json_printf(out, fmt, val.d); + } else { + len += json_printf(out, fmt, val.i); + } + } + len += json_printf(out, "]", 1); + return len; +} + +#ifdef _WIN32 +int cs_win_vsnprintf(char *str, size_t size, const char *format, + va_list ap) WEAK; +int cs_win_vsnprintf(char *str, size_t size, const char *format, va_list ap) { + int res = _vsnprintf(str, size, format, ap); + va_end(ap); + if (res >= size) { + str[size - 1] = '\0'; + } + return res; +} + +int cs_win_snprintf(char *str, size_t size, const char *format, ...) WEAK; +int cs_win_snprintf(char *str, size_t size, const char *format, ...) { + int res; + va_list ap; + va_start(ap, format); + res = vsnprintf(str, size, format, ap); + va_end(ap); + return res; +} +#endif /* _WIN32 */ + +int json_walk(const char *json_string, int json_string_length, + json_walk_callback_t callback, void *callback_data) WEAK; +int json_walk(const char *json_string, int json_string_length, + json_walk_callback_t callback, void *callback_data) { + struct frozen frozen; + + memset(&frozen, 0, sizeof(frozen)); + frozen.end = json_string + json_string_length; + frozen.cur = json_string; + frozen.callback_data = callback_data; + frozen.callback = callback; + + TRY(json_doit(&frozen)); + + return frozen.cur - json_string; +} + +struct scan_array_info { + int found; + char path[JSON_MAX_PATH_LEN]; + struct json_token *token; +}; + +static void json_scanf_array_elem_cb(void *callback_data, const char *name, + size_t name_len, const char *path, + const struct json_token *token) { + struct scan_array_info *info = (struct scan_array_info *) callback_data; + + (void) name; + (void) name_len; + + if (strcmp(path, info->path) == 0) { + *info->token = *token; + info->found = 1; + } +} + +int json_scanf_array_elem(const char *s, int len, const char *path, int idx, + struct json_token *token) WEAK; +int json_scanf_array_elem(const char *s, int len, const char *path, int idx, + struct json_token *token) { + struct scan_array_info info; + info.token = token; + info.found = 0; + memset(token, 0, sizeof(*token)); + snprintf(info.path, sizeof(info.path), "%s[%d]", path, idx); + json_walk(s, len, json_scanf_array_elem_cb, &info); + return info.found ? token->len : -1; +} + +struct json_scanf_info { + int num_conversions; + char *path; + const char *fmt; + void *target; + void *user_data; + int type; +}; + +int json_unescape(const char *src, int slen, char *dst, int dlen) WEAK; +int json_unescape(const char *src, int slen, char *dst, int dlen) { + char *send = (char *) src + slen, *dend = dst + dlen, *orig_dst = dst, *p; + const char *esc1 = "\"\\/bfnrt", *esc2 = "\"\\/\b\f\n\r\t"; + + while (src < send) { + if (*src == '\\') { + if (++src >= send) return JSON_STRING_INCOMPLETE; + if (*src == 'u') { + if (send - src < 5) return JSON_STRING_INCOMPLETE; + /* Here we go: this is a \u.... escape. Process simple one-byte chars */ + if (src[1] == '0' && src[2] == '0') { + /* This is \u00xx character from the ASCII range */ + if (dst < dend) *dst = hexdec(src + 3); + src += 4; + } else { + /* Complex \uXXXX escapes drag utf8 lib... Do it at some stage */ + return JSON_STRING_INVALID; + } + } else if ((p = (char *) strchr(esc1, *src)) != NULL) { + if (dst < dend) *dst = esc2[p - esc1]; + } else { + return JSON_STRING_INVALID; + } + } else { + if (dst < dend) *dst = *src; + } + dst++; + src++; + } + + return dst - orig_dst; +} + +static void json_scanf_cb(void *callback_data, const char *name, + size_t name_len, const char *path, + const struct json_token *token) { + struct json_scanf_info *info = (struct json_scanf_info *) callback_data; + char buf[32]; /* Must be enough to hold numbers */ + + (void) name; + (void) name_len; + + if (token->ptr == NULL) { + /* + * We're not interested here in the events for which we have no value; + * namely, JSON_TYPE_OBJECT_START and JSON_TYPE_ARRAY_START + */ + return; + } + + if (strcmp(path, info->path) != 0) { + /* It's not the path we're looking for, so, just ignore this callback */ + return; + } + + switch (info->type) { + case 'B': + info->num_conversions++; + switch (sizeof(bool)) { + case sizeof(char): + *(char *) info->target = (token->type == JSON_TYPE_TRUE ? 1 : 0); + break; + case sizeof(int): + *(int *) info->target = (token->type == JSON_TYPE_TRUE ? 1 : 0); + break; + default: + /* should never be here */ + abort(); + } + break; + case 'M': { + union { + void *p; + json_scanner_t f; + } u = {info->target}; + info->num_conversions++; + u.f(token->ptr, token->len, info->user_data); + break; + } + case 'Q': { + char **dst = (char **) info->target; + if (token->type == JSON_TYPE_NULL) { + *dst = NULL; + } else { + int unescaped_len = json_unescape(token->ptr, token->len, NULL, 0); + if (unescaped_len >= 0 && + (*dst = (char *) malloc(unescaped_len + 1)) != NULL) { + info->num_conversions++; + if (json_unescape(token->ptr, token->len, *dst, unescaped_len) == + unescaped_len) { + (*dst)[unescaped_len] = '\0'; + } else { + free(*dst); + *dst = NULL; + } + } + } + break; + } + case 'H': { +#if JSON_ENABLE_HEX + char **dst = (char **) info->user_data; + int i, len = token->len / 2; + *(int *) info->target = len; + if ((*dst = (char *) malloc(len + 1)) != NULL) { + for (i = 0; i < len; i++) { + (*dst)[i] = hexdec(token->ptr + 2 * i); + } + (*dst)[len] = '\0'; + info->num_conversions++; + } +#endif /* JSON_ENABLE_HEX */ + break; + } + case 'V': { +#if JSON_ENABLE_BASE64 + char **dst = (char **) info->target; + int len = token->len * 4 / 3 + 2; + if ((*dst = (char *) malloc(len + 1)) != NULL) { + int n = b64dec(token->ptr, token->len, *dst); + (*dst)[n] = '\0'; + *(int *) info->user_data = n; + info->num_conversions++; + } +#endif /* JSON_ENABLE_BASE64 */ + break; + } + case 'T': + info->num_conversions++; + *(struct json_token *) info->target = *token; + break; + default: + if (token->len >= (int) sizeof(buf)) break; + /* Before converting, copy into tmp buffer in order to 0-terminate it */ + memcpy(buf, token->ptr, token->len); + buf[token->len] = '\0'; + /* NB: Use of base 0 for %d, %ld, %u and %lu is intentional. */ + if (info->fmt[1] == 'd' || (info->fmt[1] == 'l' && info->fmt[2] == 'd') || + info->fmt[1] == 'i') { + char *endptr = NULL; + long r = strtol(buf, &endptr, 0 /* base */); + if (*endptr == '\0') { + if (info->fmt[1] == 'l') { + *((long *) info->target) = r; + } else { + *((int *) info->target) = (int) r; + } + info->num_conversions++; + } + } else if (info->fmt[1] == 'u' || + (info->fmt[1] == 'l' && info->fmt[2] == 'u')) { + char *endptr = NULL; + unsigned long r = strtoul(buf, &endptr, 0 /* base */); + if (*endptr == '\0') { + if (info->fmt[1] == 'l') { + *((unsigned long *) info->target) = r; + } else { + *((unsigned int *) info->target) = (unsigned int) r; + } + info->num_conversions++; + } + } else { +#if !JSON_MINIMAL + info->num_conversions += sscanf(buf, info->fmt, info->target); +#endif + } + break; + } +} + +int json_vscanf(const char *s, int len, const char *fmt, va_list ap) WEAK; +int json_vscanf(const char *s, int len, const char *fmt, va_list ap) { + char path[JSON_MAX_PATH_LEN] = "", fmtbuf[20]; + int i = 0; + char *p = NULL; + struct json_scanf_info info = {0, path, fmtbuf, NULL, NULL, 0}; + + while (fmt[i] != '\0') { + if (fmt[i] == '{') { + strcat(path, "."); + i++; + } else if (fmt[i] == '}') { + if ((p = strrchr(path, '.')) != NULL) * p = '\0'; + i++; + } else if (fmt[i] == '%') { + info.target = va_arg(ap, void *); + info.type = fmt[i + 1]; + switch (fmt[i + 1]) { + case 'M': + case 'V': + case 'H': + info.user_data = va_arg(ap, void *); + /* FALLTHROUGH */ + case 'B': + case 'Q': + case 'T': + i += 2; + break; + default: { + const char *delims = ", \t\r\n]}"; + int conv_len = strcspn(fmt + i + 1, delims) + 1; + memcpy(fmtbuf, fmt + i, conv_len); + fmtbuf[conv_len] = '\0'; + i += conv_len; + i += strspn(fmt + i, delims); + break; + } + } + json_walk(s, len, json_scanf_cb, &info); + } else if (json_isalpha(fmt[i]) || json_get_utf8_char_len(fmt[i]) > 1) { + char *pe; + const char *delims = ": \r\n\t"; + int key_len = strcspn(&fmt[i], delims); + if ((p = strrchr(path, '.')) != NULL) p[1] = '\0'; + pe = path + strlen(path); + memcpy(pe, fmt + i, key_len); + pe[key_len] = '\0'; + i += key_len + strspn(fmt + i + key_len, delims); + } else { + i++; + } + } + return info.num_conversions; +} + +int json_scanf(const char *str, int len, const char *fmt, ...) WEAK; +int json_scanf(const char *str, int len, const char *fmt, ...) { + int result; + va_list ap; + va_start(ap, fmt); + result = json_vscanf(str, len, fmt, ap); + va_end(ap); + return result; +} + +int json_vfprintf(const char *file_name, const char *fmt, va_list ap) WEAK; +int json_vfprintf(const char *file_name, const char *fmt, va_list ap) { + int res = -1; + FILE *fp = fopen(file_name, "wb"); + if (fp != NULL) { + struct json_out out = JSON_OUT_FILE(fp); + res = json_vprintf(&out, fmt, ap); + fputc('\n', fp); + fclose(fp); + } + return res; +} + +int json_fprintf(const char *file_name, const char *fmt, ...) WEAK; +int json_fprintf(const char *file_name, const char *fmt, ...) { + int result; + va_list ap; + va_start(ap, fmt); + result = json_vfprintf(file_name, fmt, ap); + va_end(ap); + return result; +} + +char *json_fread(const char *path) WEAK; +char *json_fread(const char *path) { + FILE *fp; + char *data = NULL; + if ((fp = fopen(path, "rb")) == NULL) { + } else if (fseek(fp, 0, SEEK_END) != 0) { + fclose(fp); + } else { + long size = ftell(fp); + if (size > 0 && (data = (char *) malloc(size + 1)) != NULL) { + fseek(fp, 0, SEEK_SET); /* Some platforms might not have rewind(), Oo */ + if (fread(data, 1, size, fp) != (size_t) size) { + free(data); + data = NULL; + } else { + data[size] = '\0'; + } + } + fclose(fp); + } + return data; +} + +struct json_setf_data { + const char *json_path; + const char *base; /* Pointer to the source JSON string */ + int matched; /* Matched part of json_path */ + int pos; /* Offset of the mutated value begin */ + int end; /* Offset of the mutated value end */ + int prev; /* Offset of the previous token end */ +}; + +static int get_matched_prefix_len(const char *s1, const char *s2) { + int i = 0; + while (s1[i] && s2[i] && s1[i] == s2[i]) i++; + return i; +} + +static void json_vsetf_cb(void *userdata, const char *name, size_t name_len, + const char *path, const struct json_token *t) { + struct json_setf_data *data = (struct json_setf_data *) userdata; + int off, len = get_matched_prefix_len(path, data->json_path); + if (t->ptr == NULL) return; + off = t->ptr - data->base; + if (len > data->matched) data->matched = len; + + /* + * If there is no exact path match, set the mutation position to tbe end + * of the object or array + */ + if (len < data->matched && data->pos == 0 && + (t->type == JSON_TYPE_OBJECT_END || t->type == JSON_TYPE_ARRAY_END)) { + data->pos = data->end = data->prev; + } + + /* Exact path match. Set mutation position to the value of this token */ + if (strcmp(path, data->json_path) == 0 && t->type != JSON_TYPE_OBJECT_START && + t->type != JSON_TYPE_ARRAY_START) { + data->pos = off; + data->end = off + t->len; + } + + /* + * For deletion, we need to know where the previous value ends, because + * we don't know where matched value key starts. + * When the mutation position is not yet set, remember each value end. + * When the mutation position is already set, but it is at the beginning + * of the object/array, we catch the end of the object/array and see + * whether the object/array start is closer then previously stored prev. + */ + if (data->pos == 0) { + data->prev = off + t->len; /* pos is not yet set */ + } else if ((t->ptr[0] == '[' || t->ptr[0] == '{') && off + 1 < data->pos && + off + 1 > data->prev) { + data->prev = off + 1; + } + (void) name; + (void) name_len; +} + +int json_vsetf(const char *s, int len, struct json_out *out, + const char *json_path, const char *json_fmt, va_list ap) WEAK; +int json_vsetf(const char *s, int len, struct json_out *out, + const char *json_path, const char *json_fmt, va_list ap) { + struct json_setf_data data; + memset(&data, 0, sizeof(data)); + data.json_path = json_path; + data.base = s; + data.end = len; + json_walk(s, len, json_vsetf_cb, &data); + if (json_fmt == NULL) { + /* Deletion codepath */ + json_printf(out, "%.*s", data.prev, s); + /* Trim comma after the value that begins at object/array start */ + if (s[data.prev - 1] == '{' || s[data.prev - 1] == '[') { + int i = data.end; + while (i < len && json_isspace(s[i])) i++; + if (s[i] == ',') data.end = i + 1; /* Point after comma */ + } + json_printf(out, "%.*s", len - data.end, s + data.end); + } else { + /* Modification codepath */ + int n, off = data.matched, depth = 0; + + /* Print the unchanged beginning */ + json_printf(out, "%.*s", data.pos, s); + + /* Add missing keys */ + while ((n = strcspn(&json_path[off], ".[")) > 0) { + if (s[data.prev - 1] != '{' && s[data.prev - 1] != '[' && depth == 0) { + json_printf(out, ","); + } + if (off > 0 && json_path[off - 1] != '.') break; + json_printf(out, "%.*Q:", n, json_path + off); + off += n; + if (json_path[off] != '\0') { + json_printf(out, "%c", json_path[off] == '.' ? '{' : '['); + depth++; + off++; + } + } + /* Print the new value */ + json_vprintf(out, json_fmt, ap); + + /* Close brackets/braces of the added missing keys */ + for (; off > data.matched; off--) { + int ch = json_path[off]; + const char *p = ch == '.' ? "}" : ch == '[' ? "]" : ""; + json_printf(out, "%s", p); + } + + /* Print the rest of the unchanged string */ + json_printf(out, "%.*s", len - data.end, s + data.end); + } + return data.end > data.pos ? 1 : 0; +} + +int json_setf(const char *s, int len, struct json_out *out, + const char *json_path, const char *json_fmt, ...) WEAK; +int json_setf(const char *s, int len, struct json_out *out, + const char *json_path, const char *json_fmt, ...) { + int result; + va_list ap; + va_start(ap, json_fmt); + result = json_vsetf(s, len, out, json_path, json_fmt, ap); + va_end(ap); + return result; +} + +struct prettify_data { + struct json_out *out; + int level; + int last_token; +}; + +static void indent(struct json_out *out, int level) { + while (level-- > 0) out->printer(out, " ", 2); +} + +static void print_key(struct prettify_data *pd, const char *path, + const char *name, int name_len) { + if (pd->last_token != JSON_TYPE_INVALID && + pd->last_token != JSON_TYPE_ARRAY_START && + pd->last_token != JSON_TYPE_OBJECT_START) { + pd->out->printer(pd->out, ",", 1); + } + if (path[0] != '\0') pd->out->printer(pd->out, "\n", 1); + indent(pd->out, pd->level); + if (path[0] != '\0' && path[strlen(path) - 1] != ']') { + pd->out->printer(pd->out, "\"", 1); + pd->out->printer(pd->out, name, (int) name_len); + pd->out->printer(pd->out, "\"", 1); + pd->out->printer(pd->out, ": ", 2); + } +} + +static void prettify_cb(void *userdata, const char *name, size_t name_len, + const char *path, const struct json_token *t) { + struct prettify_data *pd = (struct prettify_data *) userdata; + switch (t->type) { + case JSON_TYPE_OBJECT_START: + case JSON_TYPE_ARRAY_START: + print_key(pd, path, name, name_len); + pd->out->printer(pd->out, t->type == JSON_TYPE_ARRAY_START ? "[" : "{", + 1); + pd->level++; + break; + case JSON_TYPE_OBJECT_END: + case JSON_TYPE_ARRAY_END: + pd->level--; + if (pd->last_token != JSON_TYPE_INVALID && + pd->last_token != JSON_TYPE_ARRAY_START && + pd->last_token != JSON_TYPE_OBJECT_START) { + pd->out->printer(pd->out, "\n", 1); + indent(pd->out, pd->level); + } + pd->out->printer(pd->out, t->type == JSON_TYPE_ARRAY_END ? "]" : "}", 1); + break; + case JSON_TYPE_NUMBER: + case JSON_TYPE_NULL: + case JSON_TYPE_TRUE: + case JSON_TYPE_FALSE: + case JSON_TYPE_STRING: + print_key(pd, path, name, name_len); + if (t->type == JSON_TYPE_STRING) pd->out->printer(pd->out, "\"", 1); + pd->out->printer(pd->out, t->ptr, t->len); + if (t->type == JSON_TYPE_STRING) pd->out->printer(pd->out, "\"", 1); + break; + default: + break; + } + pd->last_token = t->type; +} + +int json_prettify(const char *s, int len, struct json_out *out) WEAK; +int json_prettify(const char *s, int len, struct json_out *out) { + struct prettify_data pd = {out, 0, JSON_TYPE_INVALID}; + return json_walk(s, len, prettify_cb, &pd); +} + +int json_prettify_file(const char *file_name) WEAK; +int json_prettify_file(const char *file_name) { + int res = -1; + char *s = json_fread(file_name); + FILE *fp; + if (s != NULL && (fp = fopen(file_name, "wb")) != NULL) { + struct json_out out = JSON_OUT_FILE(fp); + res = json_prettify(s, strlen(s), &out); + if (res < 0) { + /* On error, restore the old content */ + fclose(fp); + fp = fopen(file_name, "wb"); + fseek(fp, 0, SEEK_SET); + fwrite(s, 1, strlen(s), fp); + } else { + fputc('\n', fp); + } + fclose(fp); + } + free(s); + return res; +} + +struct next_data { + void *handle; // Passed handle. Changed if a next entry is found + const char *path; // Path to the iterated object/array + int path_len; // Path length - optimisation + int found; // Non-0 if found the next entry + struct json_token *key; // Object's key + struct json_token *val; // Object's value + int *idx; // Array index +}; + +static void next_set_key(struct next_data *d, const char *name, int name_len, + int is_array) { + if (is_array) { + /* Array. Set index and reset key */ + if (d->key != NULL) { + d->key->len = 0; + d->key->ptr = NULL; + } + if (d->idx != NULL) *d->idx = atoi(name); + } else { + /* Object. Set key and make index -1 */ + if (d->key != NULL) { + d->key->ptr = name; + d->key->len = name_len; + } + if (d->idx != NULL) *d->idx = -1; + } +} + +static void json_next_cb(void *userdata, const char *name, size_t name_len, + const char *path, const struct json_token *t) { + struct next_data *d = (struct next_data *) userdata; + const char *p = path + d->path_len; + if (d->found) return; + if (d->path_len >= (int) strlen(path)) return; + if (strncmp(d->path, path, d->path_len) != 0) return; + if (strchr(p + 1, '.') != NULL) return; /* More nested objects - skip */ + if (strchr(p + 1, '[') != NULL) return; /* Ditto for arrays */ + // {OBJECT,ARRAY}_END types do not pass name, _START does. Save key. + if (t->type == JSON_TYPE_OBJECT_START || t->type == JSON_TYPE_ARRAY_START) { + next_set_key(d, name, name_len, p[0] == '['); + } else if (d->handle == NULL || d->handle < (void *) t->ptr) { + if (t->type != JSON_TYPE_OBJECT_END && t->type != JSON_TYPE_ARRAY_END) { + next_set_key(d, name, name_len, p[0] == '['); + } + if (d->val != NULL) *d->val = *t; + d->handle = (void *) t->ptr; + d->found = 1; + } +} + +static void *json_next(const char *s, int len, void *handle, const char *path, + struct json_token *key, struct json_token *val, int *i) { + struct json_token tmpval, *v = val == NULL ? &tmpval : val; + struct json_token tmpkey, *k = key == NULL ? &tmpkey : key; + int tmpidx, *pidx = i == NULL ? &tmpidx : i; + struct next_data data = {handle, path, (int) strlen(path), 0, k, v, pidx}; + json_walk(s, len, json_next_cb, &data); + return data.found ? data.handle : NULL; +} + +void *json_next_key(const char *s, int len, void *handle, const char *path, + struct json_token *key, struct json_token *val) WEAK; +void *json_next_key(const char *s, int len, void *handle, const char *path, + struct json_token *key, struct json_token *val) { + return json_next(s, len, handle, path, key, val, NULL); +} + +void *json_next_elem(const char *s, int len, void *handle, const char *path, + int *idx, struct json_token *val) WEAK; +void *json_next_elem(const char *s, int len, void *handle, const char *path, + int *idx, struct json_token *val) { + return json_next(s, len, handle, path, NULL, val, idx); +} + +static int json_sprinter(struct json_out *out, const char *str, size_t len) { + size_t old_len = out->u.buf.buf == NULL ? 0 : strlen(out->u.buf.buf); + size_t new_len = len + old_len; + char *p = (char *) realloc(out->u.buf.buf, new_len + 1); + if (p != NULL) { + memcpy(p + old_len, str, len); + p[new_len] = '\0'; + out->u.buf.buf = p; + } + return len; +} + +char *json_vasprintf(const char *fmt, va_list ap) WEAK; +char *json_vasprintf(const char *fmt, va_list ap) { + struct json_out out; + memset(&out, 0, sizeof(out)); + out.printer = json_sprinter; + json_vprintf(&out, fmt, ap); + return out.u.buf.buf; +} + +char *json_asprintf(const char *fmt, ...) WEAK; +char *json_asprintf(const char *fmt, ...) { + char *result = NULL; + va_list ap; + va_start(ap, fmt); + result = json_vasprintf(fmt, ap); + va_end(ap); + return result; +} diff --git a/armsrc/frozen.h b/armsrc/frozen.h new file mode 100644 index 000000000..beb6c5f44 --- /dev/null +++ b/armsrc/frozen.h @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2004-2013 Sergey Lyubka + * Copyright (c) 2018 Cesanta Software Limited + * All rights reserved + * + * Licensed under the Apache License, Version 2.0 (the ""License""); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an ""AS IS"" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CS_FROZEN_FROZEN_H_ +#define CS_FROZEN_FROZEN_H_ + +#include +#include + +/* JSON token type */ +enum json_token_type { + JSON_TYPE_INVALID = 0, /* memsetting to 0 should create INVALID value */ + JSON_TYPE_STRING, + JSON_TYPE_NUMBER, + JSON_TYPE_TRUE, + JSON_TYPE_FALSE, + JSON_TYPE_NULL, + JSON_TYPE_OBJECT_START, + JSON_TYPE_OBJECT_END, + JSON_TYPE_ARRAY_START, + JSON_TYPE_ARRAY_END, + + JSON_TYPES_CNT +}; + +/* + * Structure containing token type and value. Used in `json_walk()` and + * `json_scanf()` with the format specifier `%T`. + */ +struct json_token { + const char *ptr; /* Points to the beginning of the value */ + int len; /* Value length */ + enum json_token_type type; /* Type of the token, possible values are above */ +}; + +#define JSON_INVALID_TOKEN \ + { 0, 0, JSON_TYPE_INVALID } + +/* Error codes */ +#define JSON_STRING_INVALID -1 +#define JSON_STRING_INCOMPLETE -2 + +/* + * Callback-based SAX-like API. + * + * Property name and length is given only if it's available: i.e. if current + * event is an object's property. In other cases, `name` is `NULL`. For + * example, name is never given: + * - For the first value in the JSON string; + * - For events JSON_TYPE_OBJECT_END and JSON_TYPE_ARRAY_END + * + * E.g. for the input `{ "foo": 123, "bar": [ 1, 2, { "baz": true } ] }`, + * the sequence of callback invocations will be as follows: + * + * - type: JSON_TYPE_OBJECT_START, name: NULL, path: "", value: NULL + * - type: JSON_TYPE_NUMBER, name: "foo", path: ".foo", value: "123" + * - type: JSON_TYPE_ARRAY_START, name: "bar", path: ".bar", value: NULL + * - type: JSON_TYPE_NUMBER, name: "0", path: ".bar[0]", value: "1" + * - type: JSON_TYPE_NUMBER, name: "1", path: ".bar[1]", value: "2" + * - type: JSON_TYPE_OBJECT_START, name: "2", path: ".bar[2]", value: NULL + * - type: JSON_TYPE_TRUE, name: "baz", path: ".bar[2].baz", value: "true" + * - type: JSON_TYPE_OBJECT_END, name: NULL, path: ".bar[2]", value: "{ \"baz\": + *true }" + * - type: JSON_TYPE_ARRAY_END, name: NULL, path: ".bar", value: "[ 1, 2, { + *\"baz\": true } ]" + * - type: JSON_TYPE_OBJECT_END, name: NULL, path: "", value: "{ \"foo\": 123, + *\"bar\": [ 1, 2, { \"baz\": true } ] }" + */ +typedef void (*json_walk_callback_t)(void *callback_data, const char *name, + size_t name_len, const char *path, + const struct json_token *token); + +/* + * Parse `json_string`, invoking `callback` in a way similar to SAX parsers; + * see `json_walk_callback_t`. + * Return number of processed bytes, or a negative error code. + */ +int json_walk(const char *json_string, int json_string_length, + json_walk_callback_t callback, void *callback_data); + +/* + * JSON generation API. + * struct json_out abstracts output, allowing alternative printing plugins. + */ +struct json_out { + int (*printer)(struct json_out *, const char *str, size_t len); + union { + struct { + char *buf; + size_t size; + size_t len; + } buf; + void *data; + FILE *fp; + } u; +}; + +extern int json_printer_buf(struct json_out *, const char *, size_t); +extern int json_printer_file(struct json_out *, const char *, size_t); + +#define JSON_OUT_BUF(buf, len) \ + { \ + json_printer_buf, { \ + { buf, len, 0 } \ + } \ + } +#define JSON_OUT_FILE(fp) \ + { \ + json_printer_file, { \ + { (char *) fp, 0, 0 } \ + } \ + } + +typedef int (*json_printf_callback_t)(struct json_out *, va_list *ap); + +/* + * Generate formatted output into a given sting buffer. + * This is a superset of printf() function, with extra format specifiers: + * - `%B` print json boolean, `true` or `false`. Accepts an `int`. + * - `%Q` print quoted escaped string or `null`. Accepts a `const char *`. + * - `%.*Q` same as `%Q`, but with length. Accepts `int`, `const char *` + * - `%V` print quoted base64-encoded string. Accepts a `const char *`, `int`. + * - `%H` print quoted hex-encoded string. Accepts a `int`, `const char *`. + * - `%M` invokes a json_printf_callback_t function. That callback function + * can consume more parameters. + * + * Return number of bytes printed. If the return value is bigger than the + * supplied buffer, that is an indicator of overflow. In the overflow case, + * overflown bytes are not printed. + */ +int json_printf(struct json_out *, const char *fmt, ...); +int json_vprintf(struct json_out *, const char *fmt, va_list ap); + +/* + * Same as json_printf, but prints to a file. + * File is created if does not exist. File is truncated if already exists. + */ +int json_fprintf(const char *file_name, const char *fmt, ...); +int json_vfprintf(const char *file_name, const char *fmt, va_list ap); + +/* + * Print JSON into an allocated 0-terminated string. + * Return allocated string, or NULL on error. + * Example: + * + * ```c + * char *str = json_asprintf("{a:%H}", 3, "abc"); + * printf("%s\n", str); // Prints "616263" + * free(str); + * ``` + */ +char *json_asprintf(const char *fmt, ...); +char *json_vasprintf(const char *fmt, va_list ap); + +/* + * Helper %M callback that prints contiguous C arrays. + * Consumes void *array_ptr, size_t array_size, size_t elem_size, char *fmt + * Return number of bytes printed. + */ +int json_printf_array(struct json_out *, va_list *ap); + +/* + * Scan JSON string `str`, performing scanf-like conversions according to `fmt`. + * This is a `scanf()` - like function, with following differences: + * + * 1. Object keys in the format string may be not quoted, e.g. "{key: %d}" + * 2. Order of keys in an object is irrelevant. + * 3. Several extra format specifiers are supported: + * - %B: consumes `int *` (or `char *`, if `sizeof(bool) == sizeof(char)`), + * expects boolean `true` or `false`. + * - %Q: consumes `char **`, expects quoted, JSON-encoded string. Scanned + * string is malloc-ed, caller must free() the string. + * - %V: consumes `char **`, `int *`. Expects base64-encoded string. + * Result string is base64-decoded, malloced and NUL-terminated. + * The length of result string is stored in `int *` placeholder. + * Caller must free() the result. + * - %H: consumes `int *`, `char **`. + * Expects a hex-encoded string, e.g. "fa014f". + * Result string is hex-decoded, malloced and NUL-terminated. + * The length of the result string is stored in `int *` placeholder. + * Caller must free() the result. + * - %M: consumes custom scanning function pointer and + * `void *user_data` parameter - see json_scanner_t definition. + * - %T: consumes `struct json_token *`, fills it out with matched token. + * + * Return number of elements successfully scanned & converted. + * Negative number means scan error. + */ +int json_scanf(const char *str, int str_len, const char *fmt, ...); +int json_vscanf(const char *str, int str_len, const char *fmt, va_list ap); + +/* json_scanf's %M handler */ +typedef void (*json_scanner_t)(const char *str, int len, void *user_data); + +/* + * Helper function to scan array item with given path and index. + * Fills `token` with the matched JSON token. + * Return -1 if no array element found, otherwise non-negative token length. + */ +int json_scanf_array_elem(const char *s, int len, const char *path, int index, + struct json_token *token); + +/* + * Unescape JSON-encoded string src,slen into dst, dlen. + * src and dst may overlap. + * If destination buffer is too small (or zero-length), result string is not + * written but the length is counted nevertheless (similar to snprintf). + * Return the length of unescaped string in bytes. + */ +int json_unescape(const char *src, int slen, char *dst, int dlen); + +/* + * Escape a string `str`, `str_len` into the printer `out`. + * Return the number of bytes printed. + */ +int json_escape(struct json_out *out, const char *str, size_t str_len); + +/* + * Read the whole file in memory. + * Return malloc-ed file content, or NULL on error. The caller must free(). + */ +char *json_fread(const char *file_name); + +/* + * Update given JSON string `s,len` by changing the value at given `json_path`. + * The result is saved to `out`. If `json_fmt` == NULL, that deletes the key. + * If path is not present, missing keys are added. Array path without an + * index pushes a value to the end of an array. + * Return 1 if the string was changed, 0 otherwise. + * + * Example: s is a JSON string { "a": 1, "b": [ 2 ] } + * json_setf(s, len, out, ".a", "7"); // { "a": 7, "b": [ 2 ] } + * json_setf(s, len, out, ".b", "7"); // { "a": 1, "b": 7 } + * json_setf(s, len, out, ".b[]", "7"); // { "a": 1, "b": [ 2,7 ] } + * json_setf(s, len, out, ".b", NULL); // { "a": 1 } + */ +int json_setf(const char *s, int len, struct json_out *out, + const char *json_path, const char *json_fmt, ...); + +int json_vsetf(const char *s, int len, struct json_out *out, + const char *json_path, const char *json_fmt, va_list ap); + +/* + * Pretty-print JSON string `s,len` into `out`. + * Return number of processed bytes in `s`. + */ +int json_prettify(const char *s, int len, struct json_out *out); + +/* + * Prettify JSON file `file_name`. + * Return number of processed bytes, or negative number of error. + * On error, file content is not modified. + */ +int json_prettify_file(const char *file_name); + +/* + * Iterate over an object at given JSON `path`. + * On each iteration, fill the `key` and `val` tokens. It is OK to pass NULL + * for `key`, or `val`, in which case they won't be populated. + * Return an opaque value suitable for the next iteration, or NULL when done. + * + * Example: + * + * ```c + * void *h = NULL; + * struct json_token key, val; + * while ((h = json_next_key(s, len, h, ".foo", &key, &val)) != NULL) { + * printf("[%.*s] -> [%.*s]\n", key.len, key.ptr, val.len, val.ptr); + * } + * ``` + */ +void *json_next_key(const char *s, int len, void *handle, const char *path, + struct json_token *key, struct json_token *val); + +/* + * Iterate over an array at given JSON `path`. + * Similar to `json_next_key`, but fills array index `idx` instead of `key`. + */ +void *json_next_elem(const char *s, int len, void *handle, const char *path, + int *idx, struct json_token *val); + +#ifndef JSON_MAX_PATH_LEN +#define JSON_MAX_PATH_LEN 256 +#endif + +#ifndef JSON_MINIMAL +#define JSON_MINIMAL 1 +#endif + +#ifndef JSON_ENABLE_BASE64 +#define JSON_ENABLE_BASE64 !JSON_MINIMAL +#endif + +#ifndef JSON_ENABLE_HEX +#define JSON_ENABLE_HEX !JSON_MINIMAL +#endif + +#endif /* CS_FROZEN_FROZEN_H_ */ diff --git a/armsrc/hfsnoop.c b/armsrc/hfsnoop.c index bb5d8699c..994d76e51 100644 --- a/armsrc/hfsnoop.c +++ b/armsrc/hfsnoop.c @@ -1,8 +1,9 @@ -#include "proxmark3.h" -#include "apps.h" +#include "proxmark3_arm.h" #include "BigBuf.h" +#include "fpgaloader.h" +#include "ticks.h" +#include "dbprint.h" #include "util.h" -#include "usb_cdc.h" // for usb_poll_validate_length static void RAMFUNC optimizedSniff(void); diff --git a/armsrc/Standalone/lf_samyrun.h b/armsrc/hfsnoop.h similarity index 59% rename from armsrc/Standalone/lf_samyrun.h rename to armsrc/hfsnoop.h index 52c0bb942..b6fac7eb7 100644 --- a/armsrc/Standalone/lf_samyrun.h +++ b/armsrc/hfsnoop.h @@ -1,22 +1,16 @@ //----------------------------------------------------------------------------- -// Samy Kamkar 2012 -// Christian Herrmann, 2017 +// Jonathan Westhues, Aug 2005 +// Gerhard de Koning Gans, April 2008, May 2011 // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// StandAlone Mod +// Definitions internal to the app source. //----------------------------------------------------------------------------- +#ifndef __HFSNOOP_H +#define __HFSNOOP_H -#ifndef __LF_SAMYRUN_H -#define __LF_SAMYRUN_H +void HfSniff(int, int); -//#include // for bool -#include "standalone.h" // standalone definitions -#include "apps.h" // debugstatements, lfops? - - -#define OPTS 2 - -#endif /* __LF_SAMYRUN_H */ +#endif diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 682dd950a..c1fc7d8d4 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -20,15 +20,20 @@ #include "hitag2.h" #include "hitag2_crypto.h" -#include "hitag.h" -#include "proxmark3.h" -#include "apps.h" -#include "util.h" #include "string.h" +#include "proxmark3_arm.h" +#include "cmd.h" #include "BigBuf.h" +#include "fpgaloader.h" +#include "ticks.h" +#include "dbprint.h" +#include "util.h" +// Successful crypto auth static bool bCrypto; +// Is in auth stage static bool bAuthenticating; +// Successful password auth static bool bPwd; static bool bSuccessful; @@ -272,8 +277,8 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_ break; } -// LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false); -// LogTrace(tx, nbytes(txlen), 0, 0, NULL, true); + // LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false); + // LogTrace(tx, nbytes(txlen), 0, 0, NULL, true); if (tag.crypto_active) { hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen / 8, *txlen % 8); @@ -377,7 +382,7 @@ static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t // Reset the transmission frame length *txlen = 0; - if (bPwd && write) { + if (bPwd && !bAuthenticating && write) { if (!hitag2_write_page(rx, rxlen, tx, txlen)) { return false; } @@ -398,22 +403,29 @@ static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t // Received UID, tag password case 32: { + // stage 1, got UID if (!bPwd) { - *txlen = 32; - memcpy(tx, password, 4); bPwd = true; - memcpy(tag.sectors[blocknr], rx, 4); - blocknr++; + bAuthenticating = true; + memcpy(tx, password, 4); + *txlen = 32; } else { - - if (blocknr == 1) { - //store password in block1, the TAG answers with Block3, but we need the password in memory - memcpy(tag.sectors[blocknr], tx, 4); - } else { + // stage 2, got config byte+password TAG, discard as will read later + if (bAuthenticating) { + bAuthenticating = false; + if (write) { + if (!hitag2_write_page(rx, rxlen, tx, txlen)) { + return false; + } + break; + } + } + // stage 2+, got data block + else { memcpy(tag.sectors[blocknr], rx, 4); + blocknr++; } - blocknr++; if (blocknr > 7) { DbpString("Read succesful!"); bSuccessful = true; @@ -488,19 +500,22 @@ static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t * } // Received UID, crypto tag answer case 32: { + // stage 1, got UID if (!bCrypto) { uint64_t ui64key = key[0] | ((uint64_t)key[1]) << 8 | ((uint64_t)key[2]) << 16 | ((uint64_t)key[3]) << 24 | ((uint64_t)key[4]) << 32 | ((uint64_t)key[5]) << 40; uint32_t ui32uid = rx[0] | ((uint32_t)rx[1]) << 8 | ((uint32_t)rx[2]) << 16 | ((uint32_t)rx[3]) << 24; Dbprintf("hitag2_crypto: key=0x%x%x uid=0x%x", (uint32_t)((REV64(ui64key)) >> 32), (uint32_t)((REV64(ui64key)) & 0xffffffff), REV32(ui32uid)); cipher_state = _hitag2_init(REV64(ui64key), REV32(ui32uid), 0); + // PRN memset(tx, 0x00, 4); + // Secret data memset(tx + 4, 0xff, 4); hitag2_cipher_transcrypt(&cipher_state, tx + 4, 4, 0); *txlen = 64; bCrypto = true; bAuthenticating = true; } else { - // Check if we received answer tag (at) + // stage 2, got config byte+password TAG, discard as will read later if (bAuthenticating) { bAuthenticating = false; if (write) { @@ -509,7 +524,9 @@ static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t * } break; } - } else { + } + // stage 2+, got data block + else { // Store the received block memcpy(tag.sectors[blocknr], rx, 4); blocknr++; @@ -692,7 +709,7 @@ void SniffHitag(void) { StopTicks(); -// int frame_count; + // int frame_count; int response; int overflow; bool rising_edge; @@ -750,7 +767,7 @@ void SniffHitag(void) { // Reset the received frame, frame count and timing info memset(rx, 0x00, sizeof(rx)); -// frame_count = 0; + // frame_count = 0; response = 0; overflow = 0; reader_frame = false; @@ -857,7 +874,7 @@ void SniffHitag(void) { // Check if frame was captured if (rxlen > 0) { -// frame_count++; + // frame_count++; LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame); // Check if we recognize a valid authentication attempt @@ -907,7 +924,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { StopTicks(); -// int frame_count = 0; + // int frame_count = 0; int response = 0, overflow = 0; uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; @@ -950,7 +967,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { // Set up simulator mode, frequency divisor which will drive the FPGA // and analog mux selection. FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); // Configure output pin that is connected to the FPGA (for modulating) @@ -1025,7 +1042,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { // Check if frame was captured if (rxlen > 4) { -// frame_count++; + // frame_count++; LogTrace(rx, nbytes(rxlen), response, response, NULL, true); // Disable timer 1 with external trigger to avoid triggers during our own modulation @@ -1081,7 +1098,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { StopTicks(); -// int frame_count = 0; + // int frame_count = 0; int response = 0; uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; @@ -1104,6 +1121,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { memcpy(password, htd->pwd.password, 4); blocknr = 0; bPwd = false; + bAuthenticating = false; break; } case RHT2F_AUTHENTICATE: { @@ -1155,7 +1173,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); // Configure output and enable pin that is connected to the FPGA (for modulating) @@ -1216,7 +1234,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // Check if frame was captured and store it if (rxlen > 0) { -// frame_count++; + // frame_count++; LogTrace(rx, nbytes(rxlen), response, response, NULL, false); } @@ -1272,7 +1290,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // Add transmitted frame to total count if (txlen > 0) { -// frame_count++; + // frame_count++; LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true); } @@ -1366,7 +1384,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { StopTicks(); -// int frame_count = 0; + // int frame_count = 0; int response = 0; uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; @@ -1405,6 +1423,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { Dbhexdump(4, password, false); blocknr = page; bPwd = false; + bAuthenticating = false; writestate = WRITE_STATE_START; } break; @@ -1425,7 +1444,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); // Disable modulation at default, which means enable the field @@ -1486,7 +1505,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // Check if frame was captured and store it if (rxlen > 0) { -// frame_count++; + // frame_count++; LogTrace(rx, nbytes(rxlen), response, response, NULL, false); } @@ -1527,7 +1546,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // Add transmitted frame to total count if (txlen > 0) { -// frame_count++; + // frame_count++; LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true); } diff --git a/armsrc/hitag2.h b/armsrc/hitag2.h index c62a2a221..9e0fb84e6 100644 --- a/armsrc/hitag2.h +++ b/armsrc/hitag2.h @@ -11,8 +11,7 @@ #ifndef _HITAG2_H_ #define _HITAG2_H_ -#include -#include +#include "common.h" #include "hitag.h" void SniffHitag(void); diff --git a/armsrc/hitag2_crypto.c b/armsrc/hitag2_crypto.c index 7d1e10d87..91c04ef43 100644 --- a/armsrc/hitag2_crypto.c +++ b/armsrc/hitag2_crypto.c @@ -11,6 +11,9 @@ //----------------------------------------------------------------------------- #include "hitag2_crypto.h" +#include "util.h" +#include "string.h" + /* Following is a modified version of cryptolib.com/ciphers/hitag2/ */ // Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007. // For educational purposes only. diff --git a/armsrc/hitag2_crypto.h b/armsrc/hitag2_crypto.h index d874955e0..8544c7e1c 100644 --- a/armsrc/hitag2_crypto.h +++ b/armsrc/hitag2_crypto.h @@ -1,12 +1,7 @@ #ifndef __HITAG2_CRYPTO_H #define __HITAG2_CRYPTO_H -#ifdef __cplusplus -extern "C" { -#endif - -#include "string.h" -#include "util.h" +#include "common.h" struct hitag2_tag { uint32_t uid; @@ -29,8 +24,5 @@ uint32_t _hitag2_byte(uint64_t *x); void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv); int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is); int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) ; -#ifdef __cplusplus -} -#endif #endif diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index d52e18fd4..98c3844e2 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -13,6 +13,17 @@ #include "hitagS.h" +#include "proxmark3_arm.h" +#include "cmd.h" +#include "BigBuf.h" +#include "fpgaloader.h" +#include "ticks.h" +#include "dbprint.h" +#include "util.h" +#include "string.h" +#include "commonutil.h" +#include "hitag2_crypto.h" + #define CRC_PRESET 0xFF #define CRC_POLYNOM 0x1D @@ -983,7 +994,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { // and analog mux selection. FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); // Configure output pin that is connected to the FPGA (for modulating) @@ -1182,7 +1193,7 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { // Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); // Configure output and enable pin that is connected to the FPGA (for modulating) @@ -1517,7 +1528,7 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) { // Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); // Disable modulation at default, which means enable the field @@ -1778,7 +1789,7 @@ void check_challenges(bool file_given, uint8_t *data) { // Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); // Disable modulation at default, which means enable the field diff --git a/armsrc/hitagS.h b/armsrc/hitagS.h index 49a885c4c..f4efd70a6 100644 --- a/armsrc/hitagS.h +++ b/armsrc/hitagS.h @@ -12,16 +12,9 @@ #ifndef _HITAGS_H_ #define _HITAGS_H_ -#include -#include -#include -#include "hitag2_crypto.h" +#include "common.h" + #include "hitag.h" -#include "proxmark3.h" -#include "apps.h" -#include "util.h" -#include "string.h" -#include "BigBuf.h" void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data); void ReadHitagS(hitag_function htf, hitag_data *htd); diff --git a/common/i2c.c b/armsrc/i2c.c similarity index 98% rename from common/i2c.c rename to armsrc/i2c.c index d51cba4a3..2cd3c6f3e 100644 --- a/common/i2c.c +++ b/armsrc/i2c.c @@ -10,6 +10,14 @@ //----------------------------------------------------------------------------- #include "i2c.h" +#include "proxmark3_arm.h" +#include "cmd.h" +#include "BigBuf.h" +#include "ticks.h" +#include "dbprint.h" +#include "util.h" +#include "string.h" + #define GPIO_RST AT91C_PIO_PA1 #define GPIO_SCL AT91C_PIO_PA5 #define GPIO_SDA AT91C_PIO_PA7 @@ -26,7 +34,7 @@ volatile unsigned long c; -// Direct use the loop to delay. 6 instructions loop, Masterclock 48Mhz, +// Direct use the loop to delay. 6 instructions loop, Masterclock 48MHz, // delay=1 is about 200kbps // timer. // I2CSpinDelayClk(4) = 12.31us @@ -41,7 +49,7 @@ void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) { #define ISO7618_MAX_FRAME 255 -// try i2c bus recovery at 100kHz = 5uS high, 5uS low +// try i2c bus recovery at 100kHz = 5us high, 5us low void I2C_recovery(void) { DbpString("Performing i2c bus recovery"); diff --git a/common/i2c.h b/armsrc/i2c.h similarity index 95% rename from common/i2c.h rename to armsrc/i2c.h index 52be70ef0..7b1707502 100644 --- a/common/i2c.h +++ b/armsrc/i2c.h @@ -1,10 +1,7 @@ #ifndef __I2C_H #define __I2C_H -#include -#include "proxmark3.h" -#include "apps.h" -#include "BigBuf.h" +#include "common.h" #include "mifare.h" #define I2C_DEVICE_ADDRESS_BOOT 0xB0 @@ -18,7 +15,6 @@ #define I2C_DEVICE_CMD_GETVERSION 0x06 #define I2C_DEVICE_CMD_SEND_T0 0x07 - void I2C_recovery(void); void I2C_init(void); void I2C_Reset(void); @@ -48,4 +44,5 @@ void SmartCardSetBaud(uint64_t arg0); void SmartCardSetClock(uint64_t arg0); void I2C_print_status(void); int I2C_get_version(uint8_t *maj, uint8_t *min); + #endif diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 1662a963a..5bbcc1b4b 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -36,17 +36,30 @@ // //----------------------------------------------------------------------------- -#include "apps.h" +#include "iclass.h" + +#include "proxmark3_arm.h" #include "cmd.h" // Needed for CRC in emulation mode; // same construction as in ISO 14443; // different initial value (CRC_ICLASS) #include "crc16.h" -#include "protocols.h" #include "optimized_cipher.h" -#include "usb_cdc.h" // for usb_poll_validate_length -static int timeout = 4096; +#include "appmain.h" +#include "BigBuf.h" +#include "fpgaloader.h" +#include "string.h" +#include "util.h" +#include "dbprint.h" +#include "protocols.h" +#include "ticks.h" + +static int g_wait = 290; +static int timeout = 5000; +static uint32_t time_rdr = 0; +static uint32_t time_response = 0; + static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay); int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf); @@ -92,21 +105,21 @@ typedef struct { int bitBuffer; int dropPosition; uint8_t *output; -} tUart; +} tUartIc; */ typedef struct { enum { - DEMOD_UNSYNCD, - DEMOD_START_OF_COMMUNICATION, - DEMOD_START_OF_COMMUNICATION2, - DEMOD_START_OF_COMMUNICATION3, - DEMOD_SOF_COMPLETE, - DEMOD_MANCHESTER_D, - DEMOD_MANCHESTER_E, - DEMOD_END_OF_COMMUNICATION, - DEMOD_END_OF_COMMUNICATION2, - DEMOD_MANCHESTER_F, - DEMOD_ERROR_WAIT + DEMOD_IC_UNSYNCD, + DEMOD_IC_START_OF_COMMUNICATION, + DEMOD_IC_START_OF_COMMUNICATION2, + DEMOD_IC_START_OF_COMMUNICATION3, + DEMOD_IC_SOF_COMPLETE, + DEMOD_IC_MANCHESTER_D, + DEMOD_IC_MANCHESTER_E, + DEMOD_IC_END_OF_COMMUNICATION, + DEMOD_IC_END_OF_COMMUNICATION2, + DEMOD_IC_MANCHESTER_F, + DEMOD_IC_ERROR_WAIT } state; int bitCount; int posCount; @@ -125,7 +138,7 @@ typedef struct { SUB_BOTH } sub; uint8_t *output; -} tDemod; +} tDemodIc; /* * Abrasive's uart implementation @@ -138,18 +151,25 @@ typedef struct { bool frame_done; uint8_t *buf; int len; -} tUart; -static tUart Uart; +} tUartIc; +static tUartIc Uart; + +static void OnError(uint8_t reason) { + reply_mix(CMD_ACK, 0, reason, 0, 0, 0); + switch_off(); +} static void uart_reset(void) { Uart.frame_done = false; Uart.synced = false; Uart.frame = false; } + static void uart_init(uint8_t *data) { Uart.buf = data; uart_reset(); } + static void uart_bit(uint8_t bit) { static uint8_t buf = 0xff; static uint8_t n_buf; @@ -499,8 +519,8 @@ static RAMFUNC int OutOfNDecoding(int bit) { //============================================================================= // Manchester //============================================================================= -static tDemod Demod; -static void DemodReset() { +static tDemodIc Demod; +static void DemodIcReset() { Demod.bitCount = 0; Demod.posCount = 0; Demod.syncBit = 0; @@ -512,11 +532,11 @@ static void DemodReset() { Demod.samples = 0; Demod.len = 0; Demod.sub = SUB_NONE; - Demod.state = DEMOD_UNSYNCD; + Demod.state = DEMOD_IC_UNSYNCD; } -static void DemodInit(uint8_t *data) { +static void DemodIcInit(uint8_t *data) { Demod.output = data; - DemodReset(); + DemodIcReset(); } // UART debug @@ -592,7 +612,7 @@ static RAMFUNC int ManchesterDecoding_iclass(uint32_t v) { return false; } - if (Demod.state == DEMOD_UNSYNCD) { + if (Demod.state == DEMOD_IC_UNSYNCD) { Demod.output[Demod.len] = 0xfa; Demod.syncBit = 0; //Demod.samples = 0; @@ -620,7 +640,7 @@ static RAMFUNC int ManchesterDecoding_iclass(uint32_t v) { if (Demod.syncBit) { Demod.len = 0; - Demod.state = DEMOD_START_OF_COMMUNICATION; + Demod.state = DEMOD_IC_START_OF_COMMUNICATION; Demod.sub = SUB_FIRST_HALF; Demod.bitCount = 0; Demod.shiftReg = 0; @@ -644,12 +664,12 @@ static RAMFUNC int ManchesterDecoding_iclass(uint32_t v) { } // SOF must be long burst... otherwise stay unsynced!!! if (!(Demod.buffer & Demod.syncBit) || !(Demod.buffer2 & Demod.syncBit)) - Demod.state = DEMOD_UNSYNCD; + Demod.state = DEMOD_IC_UNSYNCD; } else { // SOF must be long burst... otherwise stay unsynced!!! if (!(Demod.buffer2 & Demod.syncBit) || !(Demod.buffer3 & Demod.syncBit)) { - Demod.state = DEMOD_UNSYNCD; + Demod.state = DEMOD_IC_UNSYNCD; error = 0x88; uart_debug(error, bit); return false; @@ -682,74 +702,74 @@ static RAMFUNC int ManchesterDecoding_iclass(uint32_t v) { } if (Demod.sub == SUB_NONE) { - if (Demod.state == DEMOD_SOF_COMPLETE) { + if (Demod.state == DEMOD_IC_SOF_COMPLETE) { Demod.output[Demod.len] = 0x0f; Demod.len++; - Demod.state = DEMOD_UNSYNCD; + Demod.state = DEMOD_IC_UNSYNCD; return true; } else { - Demod.state = DEMOD_ERROR_WAIT; + Demod.state = DEMOD_IC_ERROR_WAIT; error = 0x33; } } switch (Demod.state) { - case DEMOD_START_OF_COMMUNICATION: + case DEMOD_IC_START_OF_COMMUNICATION: if (Demod.sub == SUB_BOTH) { - Demod.state = DEMOD_START_OF_COMMUNICATION2; + Demod.state = DEMOD_IC_START_OF_COMMUNICATION2; Demod.posCount = 1; Demod.sub = SUB_NONE; } else { Demod.output[Demod.len] = 0xab; - Demod.state = DEMOD_ERROR_WAIT; + Demod.state = DEMOD_IC_ERROR_WAIT; error = 0xd2; } break; - case DEMOD_START_OF_COMMUNICATION2: + case DEMOD_IC_START_OF_COMMUNICATION2: if (Demod.sub == SUB_SECOND_HALF) { - Demod.state = DEMOD_START_OF_COMMUNICATION3; + Demod.state = DEMOD_IC_START_OF_COMMUNICATION3; } else { Demod.output[Demod.len] = 0xab; - Demod.state = DEMOD_ERROR_WAIT; + Demod.state = DEMOD_IC_ERROR_WAIT; error = 0xd3; } break; - case DEMOD_START_OF_COMMUNICATION3: + case DEMOD_IC_START_OF_COMMUNICATION3: if (Demod.sub == SUB_SECOND_HALF) { - Demod.state = DEMOD_SOF_COMPLETE; + Demod.state = DEMOD_IC_SOF_COMPLETE; } else { Demod.output[Demod.len] = 0xab; - Demod.state = DEMOD_ERROR_WAIT; + Demod.state = DEMOD_IC_ERROR_WAIT; error = 0xd4; } break; - case DEMOD_SOF_COMPLETE: - case DEMOD_MANCHESTER_D: - case DEMOD_MANCHESTER_E: + case DEMOD_IC_SOF_COMPLETE: + case DEMOD_IC_MANCHESTER_D: + case DEMOD_IC_MANCHESTER_E: // OPPOSITE FROM ISO14443 - 11110000 = 0 (1 in 14443) // 00001111 = 1 (0 in 14443) if (Demod.sub == SUB_SECOND_HALF) { // SUB_FIRST_HALF Demod.bitCount++; Demod.shiftReg = (Demod.shiftReg >> 1) ^ 0x100; - Demod.state = DEMOD_MANCHESTER_D; + Demod.state = DEMOD_IC_MANCHESTER_D; } else if (Demod.sub == SUB_FIRST_HALF) { // SUB_SECOND_HALF Demod.bitCount++; Demod.shiftReg >>= 1; - Demod.state = DEMOD_MANCHESTER_E; + Demod.state = DEMOD_IC_MANCHESTER_E; } else if (Demod.sub == SUB_BOTH) { - Demod.state = DEMOD_MANCHESTER_F; + Demod.state = DEMOD_IC_MANCHESTER_F; } else { - Demod.state = DEMOD_ERROR_WAIT; + Demod.state = DEMOD_IC_ERROR_WAIT; error = 0x55; } break; - case DEMOD_MANCHESTER_F: + case DEMOD_IC_MANCHESTER_F: // Tag response does not need to be a complete byte! if (Demod.len > 0 || Demod.bitCount > 0) { if (Demod.bitCount > 1) { // was > 0, do not interpret last closing bit, is part of EOF @@ -758,22 +778,22 @@ static RAMFUNC int ManchesterDecoding_iclass(uint32_t v) { Demod.len++; } - Demod.state = DEMOD_UNSYNCD; + Demod.state = DEMOD_IC_UNSYNCD; return true; } else { Demod.output[Demod.len] = 0xad; - Demod.state = DEMOD_ERROR_WAIT; + Demod.state = DEMOD_IC_ERROR_WAIT; error = 0x03; } break; - case DEMOD_ERROR_WAIT: - Demod.state = DEMOD_UNSYNCD; + case DEMOD_IC_ERROR_WAIT: + Demod.state = DEMOD_IC_UNSYNCD; break; default: Demod.output[Demod.len] = 0xdd; - Demod.state = DEMOD_UNSYNCD; + Demod.state = DEMOD_IC_UNSYNCD; break; } @@ -818,10 +838,10 @@ static void iclass_setup_sniff(void) { set_tracing(true); // Initialize Demod and Uart structs - DemodInit(BigBuf_malloc(ICLASS_BUFFER_SIZE)); + DemodIcInit(BigBuf_malloc(ICLASS_BUFFER_SIZE)); uart_init(BigBuf_malloc(ICLASS_BUFFER_SIZE)); - //UartInit(BigBuf_malloc(ICLASS_BUFFER_SIZE)); + //UartIcInit(BigBuf_malloc(ICLASS_BUFFER_SIZE)); if (DBGLEVEL > 1) { // Print debug information about the buffer sizes @@ -875,18 +895,23 @@ void RAMFUNC SniffIClass(void) { // time ZERO, the point from which it all is calculated. time_0 = GetCountSspClk(); - - int divi = 0; - uint8_t tag_byte = 0, foo = 0; + // loop and listen // every sample (1byte in data), // contains HIGH nibble = reader data // contains LOW nibble = tag data // so two bytes are needed in order to get 1byte of either reader or tag data. (ie 2 sample bytes) // since reader data is manchester encoded, we need 2bytes of data in order to get one demoded byte. (ie: 4 sample bytes) - while (!BUTTON_PRESS()) { + uint16_t checked = 0; + for (;;) { WDT_HIT(); + if (checked == 2000) { + if (BUTTON_PRESS() || data_available()) break; + checked = 0; + } + checked++; + previous_data <<= 8; previous_data |= *data; @@ -899,14 +924,6 @@ void RAMFUNC SniffIClass(void) { AT91C_BASE_PDC_SSC->PDC_RNCR = ICLASS_DMA_BUFFER_SIZE; } - if (*data & 0xF) { - //tag_byte <<= 1; - tag_byte ^= (1 << 4); - foo ^= (1 << (3 - divi)); - Dbprintf(" %d|%x == %d|%x", tag_byte, tag_byte, foo, foo); - } - divi++; - // every odd sample if (sniffCounter & 0x01) { // no need to try decoding reader data if the tag is sending @@ -919,7 +936,7 @@ void RAMFUNC SniffIClass(void) { if (Uart.frame_done) { time_stop = GetCountSspClk() - time_0; LogTrace(Uart.buf, Uart.len, time_start, time_stop, NULL, true); - DemodReset(); + DemodIcReset(); uart_reset(); } else { time_start = GetCountSspClk() - time_0; @@ -936,8 +953,6 @@ void RAMFUNC SniffIClass(void) { LED_C_INV(); // LOW nibble is always tag data. /* - - uint32_t tag_byte = ((previous_data & 0x0F000000) >> 8 ) | ((previous_data & 0x000F0000) >> 4 ) | @@ -947,28 +962,26 @@ void RAMFUNC SniffIClass(void) { */ - //uint8_t tag_byte = ((previous_data & 0xF) << 4 ) | (*data & 0xF); - if (ManchesterDecoding_iclass(foo)) { + uint8_t tag_byte = ((previous_data & 0xF) << 4 ) | (*data & 0xF); + if (ManchesterDecoding_iclass(tag_byte)) { time_stop = GetCountSspClk() - time_0; LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false); - DemodReset(); + DemodIcReset(); uart_reset(); } else { time_start = GetCountSspClk() - time_0; } - TagIsActive = (Demod.state != DEMOD_UNSYNCD); + TagIsActive = (Demod.state != DEMOD_IC_UNSYNCD); } - tag_byte = 0; - foo = 0; - divi = 0; } } // end main loop +/* if (DBGLEVEL >= 1) { DbpString("[+] Sniff statistics:"); Dbhexdump(ICLASS_DMA_BUFFER_SIZE, data, false); } - +*/ switch_off(); } @@ -996,9 +1009,17 @@ static bool GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen) uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; (void)b; - while (!BUTTON_PRESS()) { + uint16_t checked = 0; + for (;;) { + WDT_HIT(); + if (checked == 2000) { + if (BUTTON_PRESS() || data_available()) return false; + checked = 0; + } + checked++; + // keep tx buffer in a defined state anyway. if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) AT91C_BASE_SSC->SSC_THR = 0x00; @@ -1017,6 +1038,7 @@ static bool GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen) return false; } +/* static uint8_t encode4Bits(const uint8_t b) { // OTA, the least significant bits first // Manchester encoding added @@ -1063,6 +1085,9 @@ static uint8_t encode4Bits(const uint8_t b) { return 0xaa; // 0000 -> 0000 -> 10101010 -> 0xaa } } +*/ + +static uint8_t lut_enc[] = { 0xAA, 0x6A, 0x9A, 0x5A, 0xA6, 0x66, 0x96, 0x56, 0xA9, 0x69, 0x99, 0x59, 0xA5, 0x65, 0x95, 0x55 }; //----------------------------------------------------------------------------- // Prepare tag messages @@ -1109,8 +1134,8 @@ static void CodeIClassTagAnswer(const uint8_t *cmd, int len) { int i; for (i = 0; i < len; i++) { uint8_t b = cmd[i]; - ToSend[++ToSendMax] = encode4Bits(b & 0xF); // least significant half - ToSend[++ToSendMax] = encode4Bits((b >> 4) & 0xF); // most significant half + ToSend[++ToSendMax] = lut_enc[b & 0xF]; // least significant half + ToSend[++ToSendMax] = lut_enc[(b >> 4) & 0xF]; // most significant half } // Send EOF @@ -1195,11 +1220,11 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) { // Button pressed - reply_old(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i, 0, mac_responses, i * EPURSE_MAC_SIZE); + reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i, 0, mac_responses, i * EPURSE_MAC_SIZE); goto out; } } - reply_old(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i, 0, mac_responses, i * EPURSE_MAC_SIZE); + reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i, 0, mac_responses, i * EPURSE_MAC_SIZE); } else if (simType == 3) { //This is 'full sim' mode, where we use the emulator storage for data. @@ -1226,20 +1251,20 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain // keyroll 1 if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) { - reply_old(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2); + reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2); // Button pressed goto out; } // keyroll 2 if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + (i + numberOfCSNS) * EPURSE_MAC_SIZE)) { - reply_old(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2); + reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2); // Button pressed goto out; } } // double the amount of collected data. - reply_old(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2); + reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2); } else { // We may want a mode here where we hardcode the csns to use (from proxclone). @@ -1307,7 +1332,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { // Reader 81 anticoll. CSN // Tag CSN - uint8_t *modulated_response; + uint8_t *modulated_response = NULL; int modulated_response_size = 0; uint8_t *trace_data = NULL; int trace_data_size = 0; @@ -1382,11 +1407,11 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { //This is used for responding to READ-block commands or other data which is dynamically generated //First the 'trace'-data, not encoded for FPGA - uint8_t *data_generic_trace = BigBuf_malloc(8 + 2);//8 bytes data + 2byte CRC is max tag answer + uint8_t *data_generic_trace = BigBuf_malloc((8 * 4) + 2);//8 bytes data + 2byte CRC is max tag answer //Then storage for the modulated data //Each bit is doubled when modulated for FPGA, and we also have SOF and EOF (2 bytes) - uint8_t *data_response = BigBuf_malloc((8 + 2) * 2 + 2); + uint8_t *data_response = BigBuf_malloc(((8 * 4) + 2) * 2 + 2); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); SpinDelay(100); @@ -1396,9 +1421,9 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { uint32_t time_0 = GetCountSspClk(); uint32_t t2r_stime = 0, t2r_etime = 0; uint32_t r2t_stime, r2t_etime = 0; - LED_A_ON(); bool buttonPressed = false; + uint8_t cmd, options, block; while (!exitLoop) { WDT_HIT(); @@ -1419,7 +1444,11 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { LED_C_ON(); //Signal tracer - if (receivedCmd[0] == ICLASS_CMD_ACTALL) { // 0x0A + cmd = receivedCmd[0] & 0xF; + options = (receivedCmd[0] >> 4) & 0xFF; + block = receivedCmd[1]; + + if (cmd == ICLASS_CMD_ACTALL) { // 0x0A // Reader in anticollission phase modulated_response = resp_sof; modulated_response_size = resp_sof_Len; //order = 1; @@ -1427,7 +1456,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { trace_data_size = sizeof(sof_data); // adjusted for 330 + (160*num of slot) goto send; - } else if (receivedCmd[0] == ICLASS_CMD_READ_OR_IDENTIFY) { // 0x0C + } else if (cmd == ICLASS_CMD_READ_OR_IDENTIFY) { // 0x0C if (len == 1) { // Reader asks for anticollission CSN modulated_response = resp_anticoll; @@ -1436,21 +1465,22 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { trace_data_size = sizeof(anticoll_data); goto send; } + if (len == 4) { // block0,1,2,5 is always readable. - switch (receivedCmd[1]) { + switch (block) { case 0: // csn (0c 00) modulated_response = resp_csn; modulated_response_size = resp_csn_len; trace_data = csn_data; trace_data_size = sizeof(csn_data); - break; + goto send; case 1: // configuration (0c 01) modulated_response = resp_conf; modulated_response_size = resp_conf_len; trace_data = conf_data; trace_data_size = sizeof(conf_data); - break; + goto send; case 2: // e-purse (0c 02) modulated_response = resp_cc; modulated_response_size = resp_cc_len; @@ -1460,20 +1490,31 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { if (reader_mac_buf != NULL) { memcpy(reader_mac_buf, card_challenge_data, 8); } - break; + goto send; case 5:// Application Issuer Area (0c 05) modulated_response = resp_aia; modulated_response_size = resp_aia_len; trace_data = aia_data; trace_data_size = sizeof(aia_data); + goto send; + default : { + if (simulationMode == MODE_FULLSIM) { // 0x0C + //Read block + //Take the data... + memcpy(data_generic_trace, emulator + (block << 3), 8); + AddCrc(data_generic_trace, 8); + trace_data = data_generic_trace; + trace_data_size = 10; + CodeIClassTagAnswer(trace_data, trace_data_size); + memcpy(modulated_response, ToSend, ToSendMax); + modulated_response_size = ToSendMax; + goto send; + } break; - default: - break; - } - goto send; - } - - } else if (receivedCmd[0] == ICLASS_CMD_SELECT) { // 0x81 + } + }//swith + }// if 4 + } else if (cmd == ICLASS_CMD_SELECT) { // 0x81 // Reader selects anticollission CSN. // Tag sends the corresponding real CSN modulated_response = resp_csn; @@ -1481,23 +1522,15 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { trace_data = csn_data; trace_data_size = sizeof(csn_data); goto send; - } else if (receivedCmd[0] == ICLASS_CMD_READCHECK_KD) { // 0x88 - // Read e-purse (88 02) + } else if (cmd == ICLASS_CMD_READCHECK ) { // 0x88 + // Read e-purse KD (88 02) KC (18 02) modulated_response = resp_cc; modulated_response_size = resp_cc_len; //order = 4; trace_data = card_challenge_data; trace_data_size = sizeof(card_challenge_data); LED_B_ON(); goto send; - } else if (receivedCmd[0] == ICLASS_CMD_READCHECK_KC) { // 0x18 - // Read e-purse (18 02) - modulated_response = resp_cc; - modulated_response_size = resp_cc_len; //order = 4; - trace_data = card_challenge_data; - trace_data_size = sizeof(card_challenge_data); - LED_B_ON(); - goto send; - } else if (receivedCmd[0] == ICLASS_CMD_CHECK) { // 0x05 + } else if (cmd == ICLASS_CMD_CHECK) { // 0x05 // Reader random and reader MAC!!! if (simulationMode == MODE_FULLSIM) { // NR, from reader, is in receivedCmd +1 @@ -1535,27 +1568,25 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { } } goto send; - } else if (receivedCmd[0] == ICLASS_CMD_HALT && len == 1) { + } else if (cmd == ICLASS_CMD_HALT && options == 0 && len == 1) { // Reader ends the session modulated_response = resp_sof; modulated_response_size = 0; //order = 0; trace_data = NULL; trace_data_size = 0; goto send; - } else if (simulationMode == MODE_FULLSIM && receivedCmd[0] == ICLASS_CMD_READ_OR_IDENTIFY && len == 4) { // 0x0C + } else if (simulationMode == MODE_FULLSIM && cmd == ICLASS_CMD_READ4 && len == 4) { // 0x06 //Read block - uint16_t blk = receivedCmd[1]; //Take the data... - memcpy(data_generic_trace, emulator + (blk << 3), 8); - AddCrc(data_generic_trace, 8); + memcpy(data_generic_trace, emulator + (block << 3), 8 * 4); + AddCrc(data_generic_trace, 8 * 4); trace_data = data_generic_trace; - trace_data_size = 10; + trace_data_size = 34; CodeIClassTagAnswer(trace_data, trace_data_size); - memcpy(data_response, ToSend, ToSendMax); - modulated_response = data_response; + memcpy(modulated_response, ToSend, ToSendMax); modulated_response_size = ToSendMax; goto send; - } else if (simulationMode == MODE_FULLSIM && receivedCmd[0] == ICLASS_CMD_UPDATE) { + } else if (simulationMode == MODE_FULLSIM && cmd == ICLASS_CMD_UPDATE) { //Probably the reader wants to update the nonce. Let's just ignore that for now. // OBS! If this is implemented, don't forget to regenerate the cipher_state @@ -1599,7 +1630,7 @@ send: A legit tag has about 330us delay between reader EOT and tag SOF. **/ if (modulated_response_size > 0) { - t2r_stime = (GetCountSspClk() - time_0) << 4; + t2r_stime = GetCountSspClkDelta(time_0) << 4; SendIClassAnswer(modulated_response, modulated_response_size, 0); t2r_etime = ((GetCountSspClk() - time_0) << 4) - t2r_stime; } @@ -1632,7 +1663,14 @@ static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay) { AT91C_BASE_SSC->SSC_THR = 0x00; - while (!BUTTON_PRESS()) { + uint16_t checked = 0; + for (;;) { + + if (checked == 2000) { + if (BUTTON_PRESS() || data_available()) return 0; + checked = 0; + } + checked++; // Prevent rx holding register from overflowing if ((AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) { @@ -1662,14 +1700,16 @@ static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay) { //----------------------------------------------------------------------------- // Transmit the command (to the tag) that was placed in ToSend[]. //----------------------------------------------------------------------------- -static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int *wait) { +static void TransmitIClassCommand(const uint8_t *cmd, int len, int *wait) { int c = 0; - volatile uint32_t b; bool firstpart = true; uint8_t sendbyte; + time_rdr = 0; + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); + AT91C_BASE_SSC->SSC_THR = 0x00; // make sure we timeout previous comms. @@ -1699,20 +1739,9 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int if (c >= len) break; } - - // Prevent rx holding register from overflowing - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - b = AT91C_BASE_SSC->SSC_RHR; - (void)b; - } } - if (samples) { - if (wait) - *samples = (c + *wait) << 3; - else - *samples = c << 3; - } + time_rdr = GetCountSspClk(); } //----------------------------------------------------------------------------- @@ -1756,17 +1785,12 @@ void CodeIClassCommand(const uint8_t *cmd, int len) { void ReaderTransmitIClass_ext(uint8_t *frame, int len, int wait) { - int samples = 0; - // This is tied to other size changes CodeIClassCommand(frame, len); // Select the card - TransmitIClassCommand(ToSend, ToSendMax, &samples, &wait); - if (trigger) - LED_A_ON(); - - rsamples += samples; + TransmitIClassCommand(ToSend, ToSendMax, &wait); + LED_A_ON(); LogTrace(frame, len, rsamples, rsamples, NULL, true); } @@ -1779,52 +1803,49 @@ void ReaderTransmitIClass(uint8_t *frame, int len) { // If a response is captured return TRUE // If it takes too long return FALSE //----------------------------------------------------------------------------- -static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed) { +static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *wait) { // buffer needs to be 512 bytes // maxLen is not used... - - int c = 0; bool skip = false; - // Setup UART/DEMOD to receive - DemodInit(receivedResponse); - - if (elapsed) *elapsed = 0; - + LED_D_ON(); // Set FPGA mode to "reader listen mode", no modulation (listen // only, since we are receiving, not transmitting). FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN); - SpinDelayUs(320); //310 Tout= 330us (iso15603-2) (330/21.3) take consideration for clock increments. + + // Setup UART/DEMOD to receive + DemodIcInit(receivedResponse); + + SpinDelayUs(g_wait); //310 Tout= 330us (iso15603-2) (330/21.3) take consideration for clock increments. // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; (void)b; - while (!BUTTON_PRESS()) { + uint16_t checked = 0; + + uint32_t card_start = GetCountSspClk(); + for (;;) { WDT_HIT(); - // keep tx buffer in a defined state anyway. - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x00; - // To make use of exact timing of next command from reader!! - if (elapsed)(*elapsed)++; + if (checked == 2000) { + if (BUTTON_PRESS() || data_available()) return false; + checked = 0; } + checked++; // Wait for byte be become available in rx holding register if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - if (c >= timeout) return false; - - c++; b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - skip = !skip; if (skip) continue; if (ManchesterDecoding_iclass(b & 0x0f)) { - if (samples) - *samples = c << 3; + time_response = GetCountSspClk() - card_start; return true; + } else if (GetCountSspClkDelta(card_start) > timeout && Demod.state == DEMOD_IC_UNSYNCD) { + return false; } } } @@ -1832,18 +1853,11 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, } int ReaderReceiveIClass(uint8_t *receivedAnswer) { - int samples = 0; - if (!GetIClassAnswer(receivedAnswer, 0, &samples, NULL)) - return false; - - rsamples += samples; + if (GetIClassAnswer(receivedAnswer, 0, NULL) == false) + return 0; LogTrace(receivedAnswer, Demod.len, rsamples, rsamples, NULL, false); - - if (samples == 0) - return false; - return Demod.len; } @@ -1867,25 +1881,34 @@ void setupIclassReader() { // Now give it time to spin up. // Signal field is on with the appropriate LED FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); - SpinDelay(300); + SpinDelay(500); StartCountSspClk(); LED_A_ON(); } -bool sendCmdGetResponseWithRetries(uint8_t *command, size_t cmdsize, uint8_t *resp, uint8_t expected_size, uint8_t retries) { +bool sendCmdGetResponseWithRetries(uint8_t *command, size_t cmdsize, uint8_t *resp, uint8_t expected_size, int8_t retries) { while (retries-- > 0) { ReaderTransmitIClass(command, cmdsize); //iceman - if received size is bigger than expected, we smash the stack here // since its called with fixed sized arrays + + // update/write command takes 4ms to 15ms before responding + int old_wait = g_wait; + if ( (command[0] & 0xF) == ICLASS_CMD_UPDATE) + g_wait = 3900; + uint8_t got_n = ReaderReceiveIClass(resp); + g_wait = old_wait; + // 0xBB is the internal debug separator byte.. if (expected_size != got_n || (resp[0] == 0xBB || resp[7] == 0xBB || resp[2] == 0xBB)) { //try again +// SpinDelayUs(360); continue; } @@ -1907,26 +1930,30 @@ uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key) { // act_all... static uint8_t act_all[] = { ICLASS_CMD_ACTALL }; static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 }; - static uint8_t select[] = { ICLASS_CMD_SELECT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t readcheck_cc[] = { ICLASS_CMD_READCHECK_KD, 0x02 }; + static uint8_t select[] = { 0x80 | ICLASS_CMD_SELECT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t readcheck_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 }; + // Bit 4: K.If this bit equals to one, the READCHECK will use the Credit Key (Kc); if equals to zero, Debit Key (Kd) willbe used + // bit 7: parity. + if (use_credit_key) - readcheck_cc[0] = ICLASS_CMD_READCHECK_KC; + readcheck_cc[0] = 0x10 | ICLASS_CMD_READCHECK; uint8_t resp[ICLASS_BUFFER_SIZE] = {0}; - uint8_t read_status = 0; - // Send act_all - ReaderTransmitIClass_ext(act_all, 1, 330 + 160); + // Send act_all ( 330 timeout + 160 timeslot); + ReaderTransmitIClass_ext(act_all, 1, 330 + 180); + // Card present? - if (!ReaderReceiveIClass(resp)) return read_status;//Fail + if (ReaderReceiveIClass(resp) == 0) + return 0; //Send Identify ReaderTransmitIClass(identify, 1); //We expect a 10-byte response here, 8 byte anticollision-CSN and 2 byte CRC - uint8_t len = ReaderReceiveIClass(resp); - if (len != 10) return read_status;//Fail + if ( ReaderReceiveIClass(resp) != 10 ) + return 0; //Copy the Anti-collision CSN to our select-packet memcpy(&select[1], resp, 8); @@ -1935,31 +1962,33 @@ uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key) { ReaderTransmitIClass(select, sizeof(select)); //We expect a 10-byte response here, 8 byte CSN and 2 byte CRC - len = ReaderReceiveIClass(resp); - if (len != 10) return read_status;//Fail + if ( ReaderReceiveIClass(resp) != 10) + return 0; - //Success - level 1, we got CSN - //Save CSN in response data - memcpy(card_data, resp, 8); - - //Flag that we got to at least stage 1, read CSN - read_status = 1; - - // Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC) + // Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC) // ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc)); // if (ReaderReceiveIClass(resp) == 8) { // //Save CC (e-purse) in response data // memcpy(card_data+8, resp, 8); // read_status++; // } + + //Success - level 1, we got CSN + //Save CSN in response data + memcpy(card_data, resp, 8); + + bool isBlk_2 = sendCmdGetResponseWithRetries(readcheck_cc, sizeof(readcheck_cc), resp, 8, 3); - bool isOK = sendCmdGetResponseWithRetries(readcheck_cc, sizeof(readcheck_cc), resp, 8, 3); - if (!isOK) return read_status; - + //Flag that we got to at least stage 1, read CSN + if ( isBlk_2 == false) { + return 1; + } + //Save CC (e-purse) in response data memcpy(card_data + 8, resp, 8); - read_status++; - return read_status; + + // we got all data; + return 2; } uint8_t handshakeIclassTag(uint8_t *card_data) { return handshakeIclassTag_ext(card_data, false); @@ -1993,13 +2022,14 @@ void ReaderIClass(uint8_t arg0) { setupIclassReader(); + uint16_t checked = 0; bool userCancelled = BUTTON_PRESS() || data_available(); while (!userCancelled) { WDT_HIT(); // if only looking for one card try 2 times if we missed it the first time - if (try_once && tryCnt > 2) { + if (try_once && tryCnt > 10) { if (DBGLEVEL > 1) DbpString("Failed to find a tag"); break; } @@ -2082,7 +2112,7 @@ void ReaderIClass(uint8_t arg0) { if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("SEND %c", send ? 'y' : 'n'); if (send) { - reply_old(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data)); + reply_mix(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data)); if (abort_after_read) { LED_B_OFF(); return; @@ -2092,14 +2122,19 @@ void ReaderIClass(uint8_t arg0) { } } LED_B_OFF(); - userCancelled = BUTTON_PRESS() || data_available(); + + if (checked == 2000) { + userCancelled = BUTTON_PRESS() || data_available(); + checked = 0; + } + checked++; } if (userCancelled) { - reply_old(CMD_ACK, 0xFF, 0, 0, card_data, 0); + reply_mix(CMD_ACK, 0xFF, 0, 0, card_data, 0); switch_off(); } else { - reply_old(CMD_ACK, 0, 0, 0, card_data, 0); + reply_mix(CMD_ACK, 0, 0, 0, card_data, 0); } } @@ -2222,7 +2257,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac) { switch_off(); } -// not used. ?!? ( CMD_ICLASS_READCHECK) +// not used. ?!? ( CMD_HF_ICLASS_READCHECK) // turn off afterwards void iClass_ReadCheck(uint8_t blockno, uint8_t keytype) { uint8_t readcheck[] = { keytype, blockno }; @@ -2247,8 +2282,8 @@ void iClass_Authentication(uint8_t *mac) { //memcpy(check+5, mac, 4); // 6 retries - bool isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 6); - reply_mix(CMD_ACK, isOK, 0, 0, 0, 0); + uint8_t isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 6); + reply_ng(CMD_HF_ICLASS_AUTH, PM3_SUCCESS, (uint8_t*)&isOK ,sizeof(uint8_t)); } typedef struct iclass_premac { @@ -2269,10 +2304,10 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) { uint8_t keyCount = arg1 & 0xFF; uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t resp[ICLASS_BUFFER_SIZE]; - uint8_t readcheck_cc[] = { ICLASS_CMD_READCHECK_KD, 0x02 }; + uint8_t readcheck_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 }; if (use_credit_key) - readcheck_cc[0] = ICLASS_CMD_READCHECK_KC; + readcheck_cc[0] = 0x10 | ICLASS_CMD_READCHECK; // select card / e-purse uint8_t card_data[6 * 8] = {0}; @@ -2286,11 +2321,16 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) { setupIclassReader(); + uint16_t checked = 0; int read_status = 0; uint8_t startup_limit = 10; while (read_status != 2) { - if (BUTTON_PRESS() && !data_available()) goto out; + if (checked == 2000) { + if (BUTTON_PRESS() || !data_available()) goto out; + checked = 0; + } + checked++; read_status = handshakeIclassTag_ext(card_data, use_credit_key); if (startup_limit-- == 0) { @@ -2301,11 +2341,17 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) { }; // since handshakeIclassTag_ext call sends s readcheck, we start with sending first response. + checked = 0; + // Keychunk loop for (i = 0; i < keyCount; i++) { // Allow button press / usb cmd to interrupt device - if (BUTTON_PRESS() && !data_available()) break; + if (checked == 2000) { + if (BUTTON_PRESS() || !data_available()) goto out; + checked = 0; + } + checked++; WDT_HIT(); LED_B_ON(); @@ -2321,8 +2367,6 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) { if (isOK) goto out; - SpinDelayUs(400); //iClass (iso15693-2) should timeout after 330us. - // Auth Sequence MUST begin with reading e-purse. (block2) // Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC) ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc)); @@ -2358,10 +2402,14 @@ bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len) { // turn off afterwards // readblock 8 + 2. only want 8. void iClass_ReadBlk(uint8_t blockno) { - uint8_t data[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - bool isOK = iClass_ReadBlock(blockno, data, sizeof(data)); - reply_mix(CMD_ACK, isOK, 0, 0, data, sizeof(data)); + struct p { + bool isOK; + uint8_t blockdata[8]; + } PACKED result; + + result.isOK = iClass_ReadBlock(blockno, result.blockdata, sizeof(result.blockdata)); switch_off(); + reply_ng(CMD_HF_ICLASS_READBL, PM3_SUCCESS, (uint8_t *)&result, sizeof(result)); } // turn off afterwards @@ -2373,7 +2421,7 @@ void iClass_Dump(uint8_t blockno, uint8_t numblks) { BigBuf_free(); uint8_t *dataout = BigBuf_malloc(255 * 8); if (dataout == NULL) { - DbpString("[!] out of memory"); + DbpString("[!] fail to allocate memory"); OnError(1); return; } @@ -2393,39 +2441,26 @@ void iClass_Dump(uint8_t blockno, uint8_t numblks) { } memcpy(dataout + (blkCnt * 8), blockdata, 8); } + + switch_off(); //return pointer to dump memory in arg3 reply_mix(CMD_ACK, isOK, blkCnt, BigBuf_max_traceLen(), 0, 0); - switch_off(); BigBuf_free(); } bool iClass_WriteBlock_ext(uint8_t blockno, uint8_t *data) { - uint8_t resp[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - uint8_t write[] = { ICLASS_CMD_UPDATE, blockno, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t write[] = { 0x80 | ICLASS_CMD_UPDATE, blockno, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; memcpy(write + 2, data, 12); // data + mac AddCrc(write + 1, 13); - - bool isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 5); - if (isOK) { //if reader responded correctly - - //if response is not equal to write values - if (memcmp(write + 2, resp, 8)) { - - //if not programming key areas (note key blocks don't get programmed with actual key data it is xor data) - if (blockno != 3 && blockno != 4) { - isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 5); - } - } - } - return isOK; + return sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 5); } // turn off afterwards void iClass_WriteBlock(uint8_t blockno, uint8_t *data) { - bool isOK = iClass_WriteBlock_ext(blockno, data); - reply_mix(CMD_ACK, isOK, 0, 0, 0, 0); + uint8_t isOK = iClass_WriteBlock_ext(blockno, data); switch_off(); + reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_SUCCESS, (uint8_t*)&isOK, sizeof(uint8_t)); } // turn off afterwards @@ -2434,23 +2469,19 @@ void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) { int total_block = (endblock - startblock) + 1; for (i = 0; i < total_block; i++) { // block number - if (iClass_WriteBlock_ext(i + startblock, data + (i * 12))) { - Dbprintf("Write block [%02x] successful", i + startblock); + if (iClass_WriteBlock_ext(startblock + i, data + (i * 12))) { + Dbprintf("Write block [%02x] successful", startblock + i); written++; } else { - if (iClass_WriteBlock_ext(i + startblock, data + (i * 12))) { - Dbprintf("Write block [%02x] successful", i + startblock); - written++; - } else { - Dbprintf("Write block [%02x] failed", i + startblock); - } + Dbprintf("Write block [%02x] failed", startblock + i); } } - if (written == total_block) - DbpString("Clone complete"); - else - DbpString("Clone incomplete"); - reply_mix(CMD_ACK, 1, 0, 0, 0, 0); switch_off(); + + uint8_t isOK = 0; + if (written == total_block) + isOK = 1; + + reply_ng(CMD_HF_ICLASS_CLONE, PM3_SUCCESS, (uint8_t *)&isOK, sizeof(uint8_t)); } diff --git a/armsrc/iclass.h b/armsrc/iclass.h new file mode 100644 index 000000000..a9edbdfed --- /dev/null +++ b/armsrc/iclass.h @@ -0,0 +1,29 @@ +//----------------------------------------------------------------------------- +// Jonathan Westhues, Aug 2005 +// Gerhard de Koning Gans, April 2008, May 2011 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Definitions internal to the app source. +//----------------------------------------------------------------------------- +#ifndef __ICLASS_H +#define __ICLASS_H + +#include "common.h" + +void RAMFUNC SniffIClass(void); +void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); +void ReaderIClass(uint8_t arg0); +void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac); +void iClass_Authentication(uint8_t *mac); +void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain); +void iClass_WriteBlock(uint8_t blockno, uint8_t *data); +void iClass_ReadBlk(uint8_t blockno); +bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len); +void iClass_Dump(uint8_t blockno, uint8_t numblks); +void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data); +void iClass_ReadCheck(uint8_t blockno, uint8_t keytype); + +#endif diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index a09978d7a..794ead3c5 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -11,10 +11,25 @@ //----------------------------------------------------------------------------- #include "iso14443a.h" +#include "string.h" +#include "proxmark3_arm.h" +#include "cmd.h" +#include "appmain.h" +#include "BigBuf.h" +#include "fpgaloader.h" +#include "ticks.h" +#include "dbprint.h" +#include "util.h" +#include "parity.h" +#include "mifareutil.h" +#include "commonutil.h" +#include "crc16.h" +#include "protocols.h" + #define MAX_ISO14A_TIMEOUT 524288 static uint32_t iso14a_timeout; // if iso14443a not active - transmit/receive dont try to execute -static bool iso14443a_active = false; +static bool hf_field_active = false; uint8_t colpos = 0; int rsamples = 0; @@ -25,7 +40,7 @@ static uint8_t iso14_pcb_blocknum = 0; // // ISO14443 timing: // -// minimum time between the start bits of consecutive transfers from reader to tag: 7000 carrier (13.56Mhz) cycles +// minimum time between the start bits of consecutive transfers from reader to tag: 7000 carrier (13.56MHz) cycles #define REQUEST_GUARD_TIME (7000/16 + 1) // minimum time between last modulation of tag and next start bit from reader to tag: 1172 carrier cycles #define FRAME_DELAY_TIME_PICC_TO_PCD (1172/16 + 1) @@ -161,7 +176,7 @@ void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par) { // Note 1: the bitstream may start at any time. We therefore need to sync. // Note 2: the interpretation of Sequence Y and Z depends on the preceding sequence. //----------------------------------------------------------------------------- -static tUart Uart; +static tUart14a Uart; // Lookup-Table to decide if 4 raw bits are a modulation. // We accept the following: @@ -176,12 +191,12 @@ const bool Mod_Miller_LUT[] = { #define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x000000F0) >> 4]) #define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x0000000F)]) -tUart *GetUart() { +tUart14a *GetUart14a() { return &Uart; } -void UartReset(void) { - Uart.state = STATE_UNSYNCD; +void Uart14aReset(void) { + Uart.state = STATE_14A_UNSYNCD; Uart.bitCount = 0; Uart.len = 0; // number of decoded data bytes Uart.parityLen = 0; // number of decoded parity bytes @@ -194,17 +209,17 @@ void UartReset(void) { Uart.syncBit = 9999; } -void UartInit(uint8_t *data, uint8_t *par) { +void Uart14aInit(uint8_t *data, uint8_t *par) { Uart.output = data; Uart.parity = par; - UartReset(); + Uart14aReset(); } // use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) { Uart.fourBits = (Uart.fourBits << 8) | bit; - if (Uart.state == STATE_UNSYNCD) { // not yet synced + if (Uart.state == STATE_14A_UNSYNCD) { // not yet synced Uart.syncBit = 9999; // not set // 00x11111 2|3 ticks pause followed by 6|5 ticks unmodulated Sequence Z (a "0" or "start of communication") @@ -230,20 +245,20 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) { Uart.startTime = non_real_time ? non_real_time : (GetCountSspClk() & 0xfffffff8); Uart.startTime -= Uart.syncBit; Uart.endTime = Uart.startTime; - Uart.state = STATE_START_OF_COMMUNICATION; + Uart.state = STATE_14A_START_OF_COMMUNICATION; } } else { if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) { if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation in both halves - error - UartReset(); + Uart14aReset(); } else { // Modulation in first half = Sequence Z = logic "0" - if (Uart.state == STATE_MILLER_X) { // error - must not follow after X - UartReset(); + if (Uart.state == STATE_14A_MILLER_X) { // error - must not follow after X + Uart14aReset(); } else { Uart.bitCount++; Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg - Uart.state = STATE_MILLER_Z; + Uart.state = STATE_14A_MILLER_Z; Uart.endTime = Uart.startTime + 8 * (9 * Uart.len + Uart.bitCount + 1) - 6; if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity) Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); @@ -262,7 +277,7 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) { if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation second half = Sequence X = logic "1" Uart.bitCount++; Uart.shiftReg = (Uart.shiftReg >> 1) | 0x100; // add a 1 to the shiftreg - Uart.state = STATE_MILLER_X; + Uart.state = STATE_14A_MILLER_X; Uart.endTime = Uart.startTime + 8 * (9 * Uart.len + Uart.bitCount + 1) - 2; if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity) Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); @@ -276,8 +291,8 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) { } } } else { // no modulation in both halves - Sequence Y - if (Uart.state == STATE_MILLER_Z || Uart.state == STATE_MILLER_Y) { // Y after logic "0" - End of Communication - Uart.state = STATE_UNSYNCD; + if (Uart.state == STATE_14A_MILLER_Z || Uart.state == STATE_14A_MILLER_Y) { // Y after logic "0" - End of Communication + Uart.state = STATE_14A_UNSYNCD; Uart.bitCount--; // last "0" was part of EOC sequence Uart.shiftReg <<= 1; // drop it if (Uart.bitCount > 0) { // if we decoded some bits @@ -294,15 +309,15 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) { if (Uart.len) { return true; // we are finished with decoding the raw data sequence } else { - UartReset(); // Nothing received - start over + Uart14aReset(); // Nothing received - start over } } - if (Uart.state == STATE_START_OF_COMMUNICATION) { // error - must not follow directly after SOC - UartReset(); + if (Uart.state == STATE_14A_START_OF_COMMUNICATION) { // error - must not follow directly after SOC + Uart14aReset(); } else { // a logic "0" Uart.bitCount++; Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg - Uart.state = STATE_MILLER_Y; + Uart.state = STATE_14A_MILLER_Y; if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity) Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); Uart.parityBits <<= 1; // make room for the parity bit @@ -336,7 +351,7 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) { // 8 ticks modulated: A collision. Save the collision position and treat as Sequence D // Note 1: the bitstream may start at any time. We therefore need to sync. // Note 2: parameter offset is used to determine the position of the parity bits (required for the anticollision command only) -tDemod Demod; +tDemod14a Demod; // Lookup-Table to decide if 4 raw bits are a modulation. // We accept three or four "1" in any position @@ -348,11 +363,11 @@ const bool Mod_Manchester_LUT[] = { #define IsManchesterModulationNibble1(b) (Mod_Manchester_LUT[(b & 0x00F0) >> 4]) #define IsManchesterModulationNibble2(b) (Mod_Manchester_LUT[(b & 0x000F)]) -tDemod *GetDemod() { +tDemod14a *GetDemod14a() { return &Demod; } -void DemodReset(void) { - Demod.state = DEMOD_UNSYNCD; +void Demod14aReset(void) { + Demod.state = DEMOD_14A_UNSYNCD; Demod.len = 0; // number of decoded data bytes Demod.parityLen = 0; Demod.shiftReg = 0; // shiftreg to hold decoded data bits @@ -367,17 +382,17 @@ void DemodReset(void) { Demod.samples = 0; } -void DemodInit(uint8_t *data, uint8_t *par) { +void Demod14aInit(uint8_t *data, uint8_t *par) { Demod.output = data; Demod.parity = par; - DemodReset(); + Demod14aReset(); } // use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time) { Demod.twoBits = (Demod.twoBits << 8) | bit; - if (Demod.state == DEMOD_UNSYNCD) { + if (Demod.state == DEMOD_14A_UNSYNCD) { if (Demod.highCnt < 2) { // wait for a stable unmodulated signal if (Demod.twoBits == 0x0000) { @@ -399,7 +414,7 @@ RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_t Demod.startTime = non_real_time ? non_real_time : (GetCountSspClk() & 0xfffffff8); Demod.startTime -= Demod.syncBit; Demod.bitCount = offset; // number of decoded data bits - Demod.state = DEMOD_MANCHESTER_DATA; + Demod.state = DEMOD_14A_MANCHESTER_DATA; } } } else { @@ -455,7 +470,7 @@ RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_t if (Demod.len) { return true; // we are finished with decoding the raw data sequence } else { // nothing received. Start over - DemodReset(); + Demod14aReset(); } } } @@ -463,6 +478,82 @@ RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_t return false; // not finished yet, need more data } + +// Thinfilm, Kovio mangels ISO14443A in the way that they don't use start bit nor parity bits. +RAMFUNC int ManchesterDecoding_Thinfilm(uint8_t bit) { + Demod.twoBits = (Demod.twoBits << 8) | bit; + + if (Demod.state == DEMOD_14A_UNSYNCD) { + + if (Demod.highCnt < 2) { // wait for a stable unmodulated signal + if (Demod.twoBits == 0x0000) { + Demod.highCnt++; + } else { + Demod.highCnt = 0; + } + } else { + Demod.syncBit = 0xFFFF; // not set + if ((Demod.twoBits & 0x7700) == 0x7000) Demod.syncBit = 7; + else if ((Demod.twoBits & 0x3B80) == 0x3800) Demod.syncBit = 6; + else if ((Demod.twoBits & 0x1DC0) == 0x1C00) Demod.syncBit = 5; + else if ((Demod.twoBits & 0x0EE0) == 0x0E00) Demod.syncBit = 4; + else if ((Demod.twoBits & 0x0770) == 0x0700) Demod.syncBit = 3; + else if ((Demod.twoBits & 0x03B8) == 0x0380) Demod.syncBit = 2; + else if ((Demod.twoBits & 0x01DC) == 0x01C0) Demod.syncBit = 1; + else if ((Demod.twoBits & 0x00EE) == 0x00E0) Demod.syncBit = 0; + if (Demod.syncBit != 0xFFFF) { + Demod.startTime = (GetCountSspClk() & 0xfffffff8); + Demod.startTime -= Demod.syncBit; + Demod.bitCount = 1; // number of decoded data bits + Demod.shiftReg = 1; + Demod.state = DEMOD_14A_MANCHESTER_DATA; + } + } + } else { + + if (IsManchesterModulationNibble1(Demod.twoBits >> Demod.syncBit)) { // modulation in first half + if (IsManchesterModulationNibble2(Demod.twoBits >> Demod.syncBit)) { // ... and in second half = collision + if (!Demod.collisionPos) { + Demod.collisionPos = (Demod.len << 3) + Demod.bitCount; + } + } // modulation in first half only - Sequence D = 1 + Demod.bitCount++; + Demod.shiftReg = (Demod.shiftReg << 1) | 0x1; // in both cases, add a 1 to the shiftreg + if (Demod.bitCount == 8) { // if we decoded a full byte + Demod.output[Demod.len++] = (Demod.shiftReg & 0xff); + Demod.bitCount = 0; + Demod.shiftReg = 0; + } + Demod.endTime = Demod.startTime + 8 * (8 * Demod.len + Demod.bitCount + 1) - 4; + } else { // no modulation in first half + if (IsManchesterModulationNibble2(Demod.twoBits >> Demod.syncBit)) { // and modulation in second half = Sequence E = 0 + Demod.bitCount++; + Demod.shiftReg = (Demod.shiftReg << 1); // add a 0 to the shiftreg + if (Demod.bitCount >= 8) { // if we decoded a full byte + Demod.output[Demod.len++] = (Demod.shiftReg & 0xff); + Demod.bitCount = 0; + Demod.shiftReg = 0; + } + Demod.endTime = Demod.startTime + 8 * (8 * Demod.len + Demod.bitCount + 1); + } else { // no modulation in both halves - End of communication + if (Demod.bitCount > 0) { // there are some remaining data bits + Demod.shiftReg <<= (8 - Demod.bitCount); // left align the decoded bits + Demod.output[Demod.len++] = Demod.shiftReg & 0xff; // and add them to the output + return true; + } + if (Demod.len) { + return true; // we are finished with decoding the raw data sequence + } else { // nothing received. Start over + Demod14aReset(); + } + } + } + } + return false; // not finished yet, need more data +} + + + //============================================================================= // Finally, a `sniffer' for ISO 14443 Type A // Both sides of communication! @@ -506,10 +597,10 @@ void RAMFUNC SniffIso14443a(uint8_t param) { bool ReaderIsActive = false; // Set up the demodulator for tag -> reader responses. - DemodInit(receivedResp, receivedRespPar); + Demod14aInit(receivedResp, receivedRespPar); // Set up the demodulator for the reader -> tag commands - UartInit(receivedCmd, receivedCmdPar); + Uart14aInit(receivedCmd, receivedCmdPar); DbpString("Starting to sniff"); @@ -583,13 +674,13 @@ void RAMFUNC SniffIso14443a(uint8_t param) { true)) break; } /* ready to receive another command. */ - UartReset(); + Uart14aReset(); /* reset the demod code, which might have been */ /* false-triggered by the commands from the reader. */ - DemodReset(); + Demod14aReset(); LED_B_OFF(); } - ReaderIsActive = (Uart.state != STATE_UNSYNCD); + ReaderIsActive = (Uart.state != STATE_14A_UNSYNCD); } // no need to try decoding tag data if the reader is sending - and we cannot afford the time @@ -608,13 +699,13 @@ void RAMFUNC SniffIso14443a(uint8_t param) { if ((!triggered) && (param & 0x01)) triggered = true; // ready to receive another response. - DemodReset(); + Demod14aReset(); // reset the Miller decoder including its (now outdated) input buffer - UartReset(); - //UartInit(receivedCmd, receivedCmdPar); + Uart14aReset(); + //Uart14aInit(receivedCmd, receivedCmdPar); LED_C_OFF(); } - TagIsActive = (Demod.state != DEMOD_UNSYNCD); + TagIsActive = (Demod.state != DEMOD_14A_UNSYNCD); } } @@ -754,7 +845,7 @@ static bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int * FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); // Now run a `software UART` on the stream of incoming samples. - UartInit(received, par); + Uart14aInit(received, par); // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; @@ -1073,7 +1164,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) { if (SimulateIso14443aInit(tagType, flags, data, &responses, &cuid, counters, tearings, &pages) == false) { BigBuf_free_keep_EM(); - reply_ng(CMD_SIMULATE_MIFARE_CARD, PM3_EINIT, NULL, 0); + reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0); return; } @@ -1193,7 +1284,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) { ar_nr_nonces[index].state = SECOND; // send to client (one struct nonces_t) - reply_ng(CMD_SIMULATE_MIFARE_CARD, PM3_SUCCESS, (uint8_t *)&ar_nr_nonces[index], sizeof(nonces_t)); + reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_SUCCESS, (uint8_t *)&ar_nr_nonces[index], sizeof(nonces_t)); ar_nr_nonces[index].state = EMPTY; ar_nr_nonces[index].sector = 0; @@ -1517,7 +1608,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) { Dbprintf("-[ Num of moebius tries [%d]", moebius_count); } - reply_ng(CMD_SIMULATE_MIFARE_CARD, retval, NULL, 0); + reply_ng(CMD_HF_MIFARE_SIMULATE, retval, NULL, 0); } // prepare a delayed transfer. This simply shifts ToSend[] by a number @@ -1553,7 +1644,7 @@ void PrepareDelayedTransfer(uint16_t delay) { //------------------------------------------------------------------------------------- static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing) { - if (!iso14443a_active) + if (!hf_field_active) return; FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); @@ -1581,26 +1672,11 @@ static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing // clear TXRDY AT91C_BASE_SSC->SSC_THR = SEC_Y; - volatile uint8_t b; uint16_t c = 0; - uint32_t sendtimer = GetTickCount(); - uint32_t cntr = 0; while (c < len) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = cmd[c++]; - cntr = 0; - } else { - if (cntr++ > 1000) { - cntr = 0; - if (GetTickCount() - sendtimer > 100) - break; - } - } - - //iceman test - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); - (void)b; + AT91C_BASE_SSC->SSC_THR = cmd[c]; + c++; } } @@ -1719,7 +1795,7 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) { AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; // Now run a 'software UART' on the stream of incoming samples. - UartInit(received, par); + Uart14aInit(received, par); // Clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; @@ -1931,14 +2007,14 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start } //----------------------------------------------------------------------------- +// Kovio - Thinfilm barcode. TAG-TALK-FIRST - // Wait a certain time for tag response // If a response is captured return TRUE // If it takes too long return FALSE //----------------------------------------------------------------------------- -static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset) { - uint32_t c = 0; +bool GetIso14443aAnswerFromTag_Thinfilm(uint8_t *receivedResponse, uint8_t *received_len) { - if (!iso14443a_active) + if (!hf_field_active) return false; // Set FPGA mode to "reader listen mode", no modulation (listen @@ -1948,7 +2024,56 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN); // Now get the answer from the card - DemodInit(receivedResponse, receivedResponsePar); + Demod14aInit(receivedResponse, NULL); + + // clear RXRDY: + uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + (void)b; + + uint32_t receive_timer = GetTickCount(); + for (;;) { + WDT_HIT(); + + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + if (ManchesterDecoding_Thinfilm(b)) { + *received_len = Demod.len; + // log + LogTrace(receivedResponse, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, NULL, false); + return true; + } + } + + // timeout already in ms + 10ms guard time + if (GetTickCount() - receive_timer > 1160) + break; + } + *received_len = Demod.len; + // log + LogTrace(receivedResponse, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, NULL, false); + return false; +} + + +//----------------------------------------------------------------------------- +// Wait a certain time for tag response +// If a response is captured return TRUE +// If it takes too long return FALSE +//----------------------------------------------------------------------------- +static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset) { + uint32_t c = 0; + + if (!hf_field_active) + return false; + + // Set FPGA mode to "reader listen mode", no modulation (listen + // only, since we are receiving, not transmitting). + // Signal field is on with the appropriate LED + LED_D_ON(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN); + + // Now get the answer from the card + Demod14aInit(receivedResponse, receivedResponsePar); // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; @@ -1964,7 +2089,7 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive if (ManchesterDecoding(b, offset, 0)) { NextTransferTime = MAX(NextTransferTime, Demod.endTime - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FRAME_DELAY_TIME_PICC_TO_PCD); return true; - } else if (c++ > timeout && Demod.state == DEMOD_UNSYNCD) { + } else if (c++ > timeout && Demod.state == DEMOD_14A_UNSYNCD) { return false; } } @@ -2018,6 +2143,7 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par) { return Demod.len; } + // This function misstreats the ISO 14443a anticollision procedure. // by fooling the reader there is a collision and forceing the reader to // increase the uid bytes. The might be an overflow, DoS will occure. @@ -2363,8 +2489,7 @@ void iso14443a_setup(uint8_t fpga_minor_mode) { LED_D_OFF(); // Signal field is on with the appropriate LED - if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD || - fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN) + if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD || fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN) LED_D_ON(); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | fpga_minor_mode); @@ -2374,18 +2499,19 @@ void iso14443a_setup(uint8_t fpga_minor_mode) { StartCountSspClk(); // Prepare the demodulation functions - DemodReset(); - UartReset(); + Demod14aReset(); + Uart14aReset(); NextTransferTime = 2 * DELAY_ARM2AIR_AS_READER; iso14a_set_timeout(1060); // 106 * 10ms default - iso14443a_active = true; + hf_field_active = true; } -void iso14443a_off() { + +void hf_field_off(void) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); - iso14443a_active = false; + hf_field_active = false; } /* Peter Fillmore 2015 @@ -2590,7 +2716,7 @@ void ReaderIso14443a(PacketCommandNG *c) { return; OUT: - iso14443a_off(); + hf_field_off(); set_tracing(false); } @@ -2885,7 +3011,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { reply_mix(CMD_ACK, isOK, 0, 0, buf, sizeof(buf)); - iso14443a_off(); + hf_field_off(); set_tracing(false); } @@ -2893,7 +3019,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { * Mifare Classic NACK-bug detection * Thanks to @doegox for the feedback and new approaches. */ -void DetectNACKbug() { +void DetectNACKbug(void) { uint8_t mf_auth[] = {0x60, 0x00, 0xF5, 0x7B}; uint8_t mf_nr_ar[] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -3120,10 +3246,10 @@ void DetectNACKbug() { data[0] = isOK; data[1] = num_nacks; num_to_bytes(i, 2, data + 2); - reply_ng(CMD_MIFARE_NACK_DETECT, status, data, 4); + reply_ng(CMD_HF_MIFARE_NACK_DETECT, status, data, 4); //reply_mix(CMD_ACK, isOK, num_nacks, i, 0, 0); BigBuf_free(); - iso14443a_off(); + hf_field_off(); set_tracing(false); } diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index e5523c598..1bea3a1b9 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -13,21 +13,10 @@ #ifndef __ISO14443A_H #define __ISO14443A_H -#ifdef __cplusplus -extern "C" { -#endif - +#include "common.h" +#include "mifare.h" // struct #include "pm3_cmd.h" -#include "cmd.h" -#include "apps.h" -#include "util.h" -#include "string.h" -#include "crc16.h" -#include "mifaresniff.h" -#include "crapto1/crapto1.h" -#include "mifareutil.h" -#include "parity.h" -#include "mifare.h" // structs +#include "crc16.h" // compute_crc // When the PM acts as tag and is receiving it takes // 2 ticks delay in the RF part (for the first falling edge), @@ -42,11 +31,11 @@ extern "C" { typedef struct { enum { - DEMOD_UNSYNCD, - // DEMOD_HALF_SYNCD, - // DEMOD_MOD_FIRST_HALF, - // DEMOD_NOMOD_FIRST_HALF, - DEMOD_MANCHESTER_DATA + DEMOD_14A_UNSYNCD, + // DEMOD_14A_HALF_SYNCD, + // DEMOD_14A_MOD_FIRST_HALF, + // DEMOD_14A_NOMOD_FIRST_HALF, + DEMOD_14A_MANCHESTER_DATA } state; uint16_t twoBits; uint16_t highCnt; @@ -61,7 +50,7 @@ typedef struct { uint32_t startTime, endTime; uint8_t *output; uint8_t *parity; -} tDemod; +} tDemod14a; /* typedef enum { MOD_NOMOD = 0, @@ -73,11 +62,11 @@ typedef enum { typedef struct { enum { - STATE_UNSYNCD, - STATE_START_OF_COMMUNICATION, - STATE_MILLER_X, - STATE_MILLER_Y, - STATE_MILLER_Z, + STATE_14A_UNSYNCD, + STATE_14A_START_OF_COMMUNICATION, + STATE_14A_MILLER_X, + STATE_14A_MILLER_Y, + STATE_14A_MILLER_Z, // DROP_NONE, // DROP_FIRST_HALF, } state; @@ -93,7 +82,7 @@ typedef struct { uint32_t startTime, endTime; uint8_t *output; uint8_t *parity; -} tUart; +} tUart14a; #ifndef AddCrc14A # define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1) @@ -109,12 +98,12 @@ typedef struct { void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); -tDemod *GetDemod(void); -void DemodReset(void); -void DemodInit(uint8_t *data, uint8_t *par); -tUart *GetUart(void); -void UartReset(void); -void UartInit(uint8_t *data, uint8_t *par); +tDemod14a *GetDemod14a(void); +void Demod14aReset(void); +void Demod14aInit(uint8_t *data, uint8_t *par); +tUart14a *GetUart14a(void); +void Uart14aReset(void); +void Uart14aInit(uint8_t *data, uint8_t *par); RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time); RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time); @@ -132,6 +121,7 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, u 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_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades); void iso14a_set_trigger(bool enable); +void hf_field_off(void); int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen); int EmSend4bit(uint8_t resp); @@ -148,10 +138,8 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start 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 DetectNACKbug(void); -#ifdef __cplusplus -} -#endif +bool GetIso14443aAnswerFromTag_Thinfilm(uint8_t *receivedResponse, uint8_t *received_len); #endif /* __ISO14443A_H */ diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index 241484d01..6f19def06 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -10,6 +10,20 @@ //----------------------------------------------------------------------------- #include "iso14443b.h" +#include "proxmark3_arm.h" +#include "common.h" // access to global variable: DBGLEVEL +#include "util.h" +#include "string.h" +#include "crc16.h" +#include "protocols.h" +#include "appmain.h" +#include "BigBuf.h" +#include "cmd.h" +#include "fpgaloader.h" +#include "commonutil.h" +#include "dbprint.h" +#include "ticks.h" + #ifndef FWT_TIMEOUT_14B // defaults to 2000ms # define FWT_TIMEOUT_14B 35312 @@ -52,7 +66,7 @@ static uint32_t iso14b_timeout = FWT_TIMEOUT_14B; //============================================================================= // An ISO 14443 Type B tag. We listen for commands from the reader, using -// a UART kind of thing that's implemented in software. When we get a +// a kind of thing that's implemented in software. When we get a // frame (i.e., a group of bytes between SOF and EOF), we check the CRC. // If it's good, then we can do something appropriate with it, and send // a response. @@ -60,14 +74,14 @@ static uint32_t iso14b_timeout = FWT_TIMEOUT_14B; //----------------------------------------------------------------------------- -// The software UART that receives commands from the reader, and its state variables. +// The software that receives commands from the reader, and its state variables. //----------------------------------------------------------------------------- static struct { enum { - STATE_UNSYNCD, - STATE_GOT_FALLING_EDGE_OF_SOF, - STATE_AWAITING_START_BIT, - STATE_RECEIVING_DATA + STATE_14B_UNSYNCD, + STATE_14B_GOT_FALLING_EDGE_OF_SOF, + STATE_14B_AWAITING_START_BIT, + STATE_14B_RECEIVING_DATA } state; uint16_t shiftReg; int bitCnt; @@ -77,8 +91,8 @@ static struct { uint8_t *output; } Uart; -static void UartReset() { - Uart.state = STATE_UNSYNCD; +static void Uart14bReset() { + Uart.state = STATE_14B_UNSYNCD; Uart.shiftReg = 0; Uart.bitCnt = 0; Uart.byteCnt = 0; @@ -86,9 +100,9 @@ static void UartReset() { Uart.posCnt = 0; } -static void UartInit(uint8_t *data) { +static void Uart14bInit(uint8_t *data) { Uart.output = data; - UartReset(); + Uart14bReset(); // memset(Uart.output, 0x00, MAX_FRAME_SIZE); } @@ -120,7 +134,7 @@ static struct { } Demod; // Clear out the state of the "UART" that receives from the tag. -static void DemodReset() { +static void Demod14bReset() { Demod.state = DEMOD_UNSYNCD; Demod.bitCount = 0; Demod.posCount = 0; @@ -133,9 +147,9 @@ static void DemodReset() { Demod.endTime = 0; } -static void DemodInit(uint8_t *data) { +static void Demod14bInit(uint8_t *data) { Demod.output = data; - DemodReset(); + Demod14bReset(); // memset(Demod.output, 0x00, MAX_FRAME_SIZE); } @@ -315,16 +329,16 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { */ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) { switch (Uart.state) { - case STATE_UNSYNCD: + case STATE_14B_UNSYNCD: if (!bit) { // we went low, so this could be the beginning of an SOF - Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF; + Uart.state = STATE_14B_GOT_FALLING_EDGE_OF_SOF; Uart.posCnt = 0; Uart.bitCnt = 0; } break; - case STATE_GOT_FALLING_EDGE_OF_SOF: + case STATE_14B_GOT_FALLING_EDGE_OF_SOF: Uart.posCnt++; if (Uart.posCnt == 2) { // sample every 4 1/fs in the middle of a bit if (bit) { @@ -333,11 +347,11 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) { // zeros that it's a valid SOF Uart.posCnt = 0; Uart.byteCnt = 0; - Uart.state = STATE_AWAITING_START_BIT; + Uart.state = STATE_14B_AWAITING_START_BIT; LED_A_ON(); // Indicate we got a valid SOF } else { // didn't stay down long enough before going high, error - Uart.state = STATE_UNSYNCD; + Uart.state = STATE_14B_UNSYNCD; } } else { // do nothing, keep waiting @@ -348,27 +362,27 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) { if (Uart.bitCnt > 12) { // Give up if we see too many zeros without a one, too. LED_A_OFF(); - Uart.state = STATE_UNSYNCD; + Uart.state = STATE_14B_UNSYNCD; } break; - case STATE_AWAITING_START_BIT: + case STATE_14B_AWAITING_START_BIT: Uart.posCnt++; if (bit) { if (Uart.posCnt > 50 / 2) { // max 57us between characters = 49 1/fs, max 3 etus after low phase of SOF = 24 1/fs // stayed high for too long between characters, error - Uart.state = STATE_UNSYNCD; + Uart.state = STATE_14B_UNSYNCD; } } else { // falling edge, this starts the data byte Uart.posCnt = 0; Uart.bitCnt = 0; Uart.shiftReg = 0; - Uart.state = STATE_RECEIVING_DATA; + Uart.state = STATE_14B_RECEIVING_DATA; } break; - case STATE_RECEIVING_DATA: + case STATE_14B_RECEIVING_DATA: Uart.posCnt++; if (Uart.posCnt == 2) { // time to sample a bit @@ -391,30 +405,30 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) { if (Uart.byteCnt >= Uart.byteCntMax) { // Buffer overflowed, give up LED_A_OFF(); - Uart.state = STATE_UNSYNCD; + Uart.state = STATE_14B_UNSYNCD; } else { // so get the next byte now Uart.posCnt = 0; - Uart.state = STATE_AWAITING_START_BIT; + Uart.state = STATE_14B_AWAITING_START_BIT; } } else if (Uart.shiftReg == 0x000) { // this is an EOF byte LED_A_OFF(); // Finished receiving - Uart.state = STATE_UNSYNCD; + Uart.state = STATE_14B_UNSYNCD; if (Uart.byteCnt != 0) return true; } else { // this is an error LED_A_OFF(); - Uart.state = STATE_UNSYNCD; + Uart.state = STATE_14B_UNSYNCD; } } break; default: LED_A_OFF(); - Uart.state = STATE_UNSYNCD; + Uart.state = STATE_14B_UNSYNCD; break; } return false; @@ -454,7 +468,7 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) { } */ // Now run a `software UART' on the stream of incoming samples. - UartInit(received); + Uart14bInit(received); uint8_t mask; while (!BUTTON_PRESS()) { @@ -949,7 +963,7 @@ static void GetTagSamplesFor14443bDemod() { BigBuf_free(); // Set up the demodulator for tag -> reader responses. - DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); + Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE)); // The DMA buffer, used to stream samples from the FPGA int8_t *dmaBuf = (int8_t *) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); @@ -1306,8 +1320,8 @@ void iso14443b_setup() { FpgaDownloadAndGo(FPGA_BITSTREAM_HF); // Initialize Demod and Uart structs - DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); - UartInit(BigBuf_malloc(MAX_FRAME_SIZE)); + Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE)); + Uart14bInit(BigBuf_malloc(MAX_FRAME_SIZE)); // connect Demodulated Signal to ADC: SetAdcMuxFor(GPIO_MUXSEL_HIPKD); @@ -1411,8 +1425,8 @@ static void iso1444b_setup_sniff(void) { set_tracing(true); // Initialize Demod and Uart structs - DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); - UartInit(BigBuf_malloc(MAX_FRAME_SIZE)); + Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE)); + Uart14bInit(BigBuf_malloc(MAX_FRAME_SIZE)); if (DBGLEVEL > 1) { // Print debug information about the buffer sizes @@ -1502,8 +1516,8 @@ void RAMFUNC SniffIso14443b(void) { if (Handle14443bReaderUartBit(ci & 0x01)) { time_stop = GetCountSspClk() - time_0; LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true); - UartReset(); - DemodReset(); + Uart14bReset(); + Demod14bReset(); } else { time_start = GetCountSspClk() - time_0; } @@ -1511,12 +1525,12 @@ void RAMFUNC SniffIso14443b(void) { if (Handle14443bReaderUartBit(cq & 0x01)) { time_stop = GetCountSspClk() - time_0; LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true); - UartReset(); - DemodReset(); + Uart14bReset(); + Demod14bReset(); } else { time_start = GetCountSspClk() - time_0; } - ReaderIsActive = (Uart.state > STATE_GOT_FALLING_EDGE_OF_SOF); + ReaderIsActive = (Uart.state > STATE_14B_GOT_FALLING_EDGE_OF_SOF); } // no need to try decoding tag data if the reader is sending - and we cannot afford the time @@ -1527,8 +1541,8 @@ void RAMFUNC SniffIso14443b(void) { if (Handle14443bTagSamplesDemod(ci, cq)) { time_stop = GetCountSspClk() - time_0; LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false); - UartReset(); - DemodReset(); + Uart14bReset(); + Demod14bReset(); } else { time_start = GetCountSspClk() - time_0; } diff --git a/armsrc/iso14443b.h b/armsrc/iso14443b.h index 5ea3d530b..12ee316e9 100644 --- a/armsrc/iso14443b.h +++ b/armsrc/iso14443b.h @@ -13,18 +13,10 @@ #ifndef __ISO14443B_H #define __ISO14443B_H -#ifdef __cplusplus -extern "C" { -#endif +#include "common.h" -#include "proxmark3.h" -#include "common.h" // access to global variable: DBGLEVEL -#include "apps.h" -#include "util.h" -#include "string.h" -#include "crc16.h" #include "mifare.h" -#include "protocols.h" +#include "pm3_cmd.h" #ifndef AddCrc14A # define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1) @@ -34,12 +26,18 @@ extern "C" { # define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1) #endif -void SendRawCommand14443B_Ex(PacketCommandNG *c); void iso14443b_setup(); uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response); uint8_t iso14443b_select_card(iso14b_card_select_t *card); uint8_t iso14443b_select_card_srx(iso14b_card_select_t *card); +void SimulateIso14443bTag(uint32_t pupi); +void AcquireRawAdcSamplesIso14443b(uint32_t parameter); +void ReadSTMemoryIso14443b(uint8_t numofblocks); +void RAMFUNC SniffIso14443b(void); +void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]); +void SendRawCommand14443B_Ex(PacketCommandNG *c); + // testfunctions void WaitForFpgaDelayQueueIsEmpty(uint16_t delay); void ClearFpgaShiftingRegisters(void); @@ -53,8 +51,4 @@ void ClearFpgaShiftingRegisters(void); #define SIM_ACKNOWLEDGE 5 #define SIM_WORK 6 -#ifdef __cplusplus -} -#endif - #endif /* __ISO14443B_H */ diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index e74ca972d..84de71021 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -32,8 +32,8 @@ // // VICC (tag) -> VCD (reader) // Modulation: -// ASK / one subcarrier (423,75 khz) -// FSK / two subcarriers (423,75 khz && 484,28 khz) +// ASK / one subcarrier (423,75 kHz) +// FSK / two subcarriers (423,75 kHz && 484,28 kHz) // Data Rates / Modes: // low ASK: 6,62 kbit/s // low FSK: 6.67 kbit/s @@ -58,12 +58,20 @@ // *) remove or refactor code under "depricated" // *) document all the functions -#include "proxmark3.h" +#include "iso15693.h" + +#include "proxmark3_arm.h" #include "util.h" -#include "apps.h" #include "string.h" #include "iso15693tools.h" #include "cmd.h" +#include "appmain.h" +#include "dbprint.h" +#include "fpgaloader.h" +#include "commonutil.h" +#include "ticks.h" +#include "BigBuf.h" +#include "crc16.h" /////////////////////////////////////////////////////////////////////// // ISO 15693 Part 2 - Air Interface diff --git a/armsrc/iso15693.h b/armsrc/iso15693.h new file mode 100644 index 000000000..2233ba9fd --- /dev/null +++ b/armsrc/iso15693.h @@ -0,0 +1,26 @@ +//----------------------------------------------------------------------------- +// Jonathan Westhues, Aug 2005 +// Gerhard de Koning Gans, April 2008, May 2011 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Definitions internal to the app source. +//----------------------------------------------------------------------------- +#ifndef __ISO15693_H +#define __ISO15693_H + +#include "common.h" + +#include "pm3_cmd.h" // struct + +void RecordRawAdcSamplesIso15693(void); +void AcquireRawAdcSamplesIso15693(void); +void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg +void SimTagIso15693(uint32_t parameter, uint8_t *uid); // simulate an ISO15693 tag - greg +void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox +void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI - atrox +void Iso15693InitReader(void); + +#endif diff --git a/armsrc/ldscript b/armsrc/ldscript index 80c2a4aed..4d48d9948 100644 --- a/armsrc/ldscript +++ b/armsrc/ldscript @@ -7,7 +7,7 @@ Linker script for the ARM binary ----------------------------------------------------------------------------- */ -INCLUDE ../common/ldscript.common +INCLUDE ../common_arm/ldscript.common PHDRS { diff --git a/armsrc/legicrf.c b/armsrc/legicrf.c index 1b689550d..0665705b6 100644 --- a/armsrc/legicrf.c +++ b/armsrc/legicrf.c @@ -11,11 +11,20 @@ //----------------------------------------------------------------------------- #include "legicrf.h" -#include "ticks.h" /* timers */ #include "crc.h" /* legic crc-4 */ #include "legic_prng.h" /* legic PRNG impl */ #include "legic.h" /* legic_card_select_t struct */ +#include "proxmark3_arm.h" +#include "cmd.h" +#include "BigBuf.h" +#include "fpgaloader.h" +#include "ticks.h" +#include "dbprint.h" +#include "util.h" +#include "string.h" +#include "protocols.h" + static uint8_t *legic_mem; /* card memory, used for read, write */ static legic_card_select_t card;/* metadata of currently selected card */ static crc_t legic_crc; diff --git a/armsrc/legicrf.h b/armsrc/legicrf.h index 76c392257..47a7f89d6 100644 --- a/armsrc/legicrf.h +++ b/armsrc/legicrf.h @@ -12,7 +12,7 @@ #ifndef __LEGICRF_H #define __LEGICRF_H -#include "proxmark3.h" +#include "common.h" void LegicRfInfo(void); void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv); diff --git a/armsrc/legicrfsim.c b/armsrc/legicrfsim.c index 0500e3e32..111c4940b 100644 --- a/armsrc/legicrfsim.c +++ b/armsrc/legicrfsim.c @@ -11,11 +11,17 @@ //----------------------------------------------------------------------------- #include "legicrf.h" -#include "ticks.h" /* timers */ #include "crc.h" /* legic crc-4 */ #include "legic_prng.h" /* legic PRNG impl */ #include "legic.h" /* legic_card_select_t struct */ +#include "proxmark3_arm.h" +#include "BigBuf.h" +#include "fpgaloader.h" +#include "ticks.h" +#include "dbprint.h" +#include "util.h" + static uint8_t *legic_mem; /* card memory, used for sim */ static legic_card_select_t card;/* metadata of currently selected card */ static crc_t legic_crc; diff --git a/armsrc/legicrfsim.h b/armsrc/legicrfsim.h index 27fce129b..3d25fae0c 100644 --- a/armsrc/legicrfsim.h +++ b/armsrc/legicrfsim.h @@ -12,7 +12,7 @@ #ifndef __LEGICRFSIM_H #define __LEGICRFSIM_H -#include "proxmark3.h" +#include "common.h" void LegicRfSimulate(uint8_t tagtype); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index af80e2f6c..bee1413fc 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -8,54 +8,71 @@ // Also routines for raw mode reading/simulating of LF waveform //----------------------------------------------------------------------------- -#include "proxmark3.h" -#include "apps.h" +#include "lfops.h" + +#include "proxmark3_arm.h" +#include "cmd.h" +#include "BigBuf.h" +#include "fpgaloader.h" +#include "ticks.h" +#include "dbprint.h" #include "util.h" -#include "hitag2.h" +#include "commonutil.h" + #include "crc16.h" #include "string.h" +#include "printf.h" #include "lfdemod.h" #include "lfsampling.h" #include "protocols.h" -#include "usb_cdc.h" // for usb_poll_validate_length -#include "common.h" #include "pmflash.h" -#include "flashmem.h" // persistence on mem +#include "flashmem.h" // persistence on flash +/* +Notes about EM4xxx timings. +The timing values differs between cards, we got EM410x, EM43x5, EM445x etc. +We are trying to unify and enable the Proxmark to easily detect and select correct timings automatic. +The measures from datasheets doesn't always match correct the hardware features of RDV4 antenans and we still wanted to let other devices with other custom antennas +still benefit from this repo. This is why its configurable and we use to set these dynamic settings in device external flash memory. -//#define START_GAP 31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc) -//#define WRITE_GAP 8*8 // 17*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc) -//#define WRITE_0 15*8 // 18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc) -//#define WRITE_1 47*8 // 50*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (56fc) 432 for T55x7; 448 for E5550 -//#define READ_GAP 15*8 // VALUES TAKEN FROM EM4x function: SendForward -// START_GAP = 440; (55*8) cycles at 125Khz (8us = 1cycle) +// START_GAP = 440; (55*8) cycles at 125kHz (8us = 1cycle) // WRITE_GAP = 128; (16*8) // WRITE_1 = 256 32*8; (32*8) // These timings work for 4469/4269/4305 (with the 55*8 above) // WRITE_0 = 23*8 , 9*8 -// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) -// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz -// Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier) -// T0 = TIMER_CLOCK1 / 125000 = 192 -// 1 Cycle = 8 microseconds(us) == 1 field clock +Not about ARM TIMERS +Short note about timers on Proxmark device ARM. They are a bit differently implemented and gives decent correctness. + +SAM7S has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) + TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz + +New timer implemenation in ticks.c, which is used in LFOPS.c + 1us = 1.5ticks + 1fc = 8us = 12ticks + +Terms you find in different datasheets and how they match. +1 Cycle = 8 microseconds(us) == 1 field clock (fc) + +Note about HITAG timing +Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier) + T0 = TIMER_CLOCK1 / 125000 = 192 + -// new timer: -// = 1us = 1.5ticks -// 1fc = 8us = 12ticks -/* ========================================================================================================== T55x7 Timing ========================================================================================================== - // t55xx_config t_config = { 29 * 8, 17 * 8, 15 * 8, 47 * 8, 15 * 8 } ; - ATA5577 Downlink Protocol Timings. Note: All absolute times assume TC = 1 / fC = 8 μs (fC = 125 kHz) + + Note: These timings are from the datasheet and doesn't map the best to the features of the RVD4 LF antenna. + RDV4 LF antenna has high voltage and the drop of power when turning off the rf field takes about 1-2 TC longer. + ----------------------------------------------------------------------- Fixed-bit-length Protocol | Normal Downlink | Fast Downlink | ------------------------------+-----------------------------------+-----------------------------------+------ @@ -110,21 +127,23 @@ | |10 data | d10 | dref + 25 | dref + 32 | dref + 40 | dref + 13 | dref + 16 | dref + 20 | Tc | | |11 data | d11 | dref + 41 | dref + 48 | dref + 56 | dref + 21 | dref + 24 | dref + 28 | Tc | ------------------------------------------------------------------------------------------------------------- -*/ -// Initial values if not in flash -/* -// Note: Moved * 8 to apply when used. Saving 28 bytes here (- the *8) and 28 bytes flash. -// StartGap WriteGap Bit 0/00 Bit 1/01 Bit 10 Bit 11 ReadGap -t55xx_config T55xx_Timing = {{ + +Initial values if not in flash + + SG = Start gap + WG = Write gap + RG = Read gap + + Explainations for array T55xx_Timing below + SG WG Bit 0/00 Bit 1/01 Bit 10 Bit 11 RG + -------------------------------------------------------------------- { 29 , 17 , 15 , 47 , 0 , 0 , 15 }, // Default Fixed { 31 , 20 , 18 , 50 , 0 , 0 , 15 }, // Long Leading Ref. { 31 , 20 , 18 , 40 , 0 , 0 , 15 }, // Leading 0 { 29 , 17 , 15 , 31 , 47 , 63 , 15 } // 1 of 4 - } -}; */ -// StartGap WriteGap Bit 0/00 Bit 1/01 ReadGap Bit 10 Bit 11 -t55xx_config T55xx_Timing = {{ +t55xx_configurations_t T55xx_Timing = { + { { 29 * 8, 17 * 8, 15 * 8, 47 * 8, 15 * 8, 0, 0 }, // Default Fixed { 31 * 8, 20 * 8, 18 * 8, 50 * 8, 15 * 8, 0, 0 }, // Long Leading Ref. { 31 * 8, 20 * 8, 18 * 8, 40 * 8, 15 * 8, 0, 0 }, // Leading 0 @@ -134,61 +153,136 @@ t55xx_config T55xx_Timing = {{ // Some defines for readability -#define T55xx_DLMode_Fixed 0 // Default Mode -#define T55xx_DLMode_LLR 1 // Long Leading Reference -#define T55xx_DLMode_Leading0 2 // Leading Zero -#define T55xx_DLMode_1of4 3 // 1 of 4 -#define T55xx_LongLeadingReference 4 // Value to tell Write Bit to send long reference +#define T55XX_DLMODE_FIXED 0 // Default Mode +#define T55XX_DLMODE_LLR 1 // Long Leading Reference +#define T55XX_DLMODE_LEADING_ZERO 2 // Leading Zero +#define T55XX_DLMODE_1OF4 3 // 1 of 4 +#define T55XX_LONGLEADINGREFERENCE 4 // Value to tell Write Bit to send long reference -void printT55xxConfig(void) { - int DLMode; - - DbpString(_BLUE_("LF T55XX config")); - for (DLMode = 0; DLMode < 4; DLMode++) { - switch (DLMode) { - case T55xx_DLMode_Fixed : - Dbprintf("r 0 fixed bit length (default)"); - break; - case T55xx_DLMode_LLR : - Dbprintf("r 1 long leading reference"); - break; - case T55xx_DLMode_Leading0 : - Dbprintf("r 2 leading zero"); - break; - case T55xx_DLMode_1of4 : - Dbprintf("r 3 1 of 4 coding reference"); - break; - } - Dbprintf(" [a] startgap............%d*8 (%d)", T55xx_Timing.m[DLMode].start_gap / 8, T55xx_Timing.m[DLMode].start_gap); - Dbprintf(" [b] writegap............%d*8 (%d)", T55xx_Timing.m[DLMode].write_gap / 8, T55xx_Timing.m[DLMode].write_gap); - Dbprintf(" [c] write_0.............%d*8 (%d)", T55xx_Timing.m[DLMode].write_0 / 8, T55xx_Timing.m[DLMode].write_0); - Dbprintf(" [d] write_1.............%d*8 (%d)", T55xx_Timing.m[DLMode].write_1 / 8, T55xx_Timing.m[DLMode].write_1); - Dbprintf(" [e] readgap.............%d*8 (%d)", T55xx_Timing.m[DLMode].read_gap / 8, T55xx_Timing.m[DLMode].read_gap); - if (DLMode == T55xx_DLMode_1of4) { - Dbprintf(" [f] write_2.............%d*8 (%d)", T55xx_Timing.m[DLMode].write_2 / 8, T55xx_Timing.m[DLMode].write_2); - Dbprintf(" [g] write_3.............%d*8 (%d)", T55xx_Timing.m[DLMode].write_3 / 8, T55xx_Timing.m[DLMode].write_3); - } +// ATA55xx shared presets & routines +static uint32_t GetT55xxClockBit(uint32_t clock) { + switch (clock) { + case 128: + return T55x7_BITRATE_RF_128; + case 100: + return T55x7_BITRATE_RF_100; + case 64: + return T55x7_BITRATE_RF_64; + case 50: + return T55x7_BITRATE_RF_50; + case 40: + return T55x7_BITRATE_RF_40; + case 32: + return T55x7_BITRATE_RF_32; + case 16: + return T55x7_BITRATE_RF_16; + case 8: + return T55x7_BITRATE_RF_8; + default : + return 0; } } -void setT55xxConfig(uint8_t arg0, t55xx_config *c) { - uint8_t DLMode; -// uint8_t ClearT55Settings = c->m[0].start_gap & 0xffff; // all values will be ffff if clear requested +void printT55xxConfig(void) { +#define PRN_NA sprintf(s + strlen(s), _RED_("N/A") "| "); - for (DLMode = 0; DLMode < 4; DLMode++) { - if (c->m[DLMode].start_gap != 0) T55xx_Timing.m[DLMode].start_gap = c->m[DLMode].start_gap;// * 8; - if (c->m[DLMode].write_gap != 0) T55xx_Timing.m[DLMode].write_gap = c->m[DLMode].write_gap;// * 8; - if (c->m[DLMode].write_0 != 0) T55xx_Timing.m[DLMode].write_0 = c->m[DLMode].write_0 ;// * 8; - if (c->m[DLMode].write_1 != 0) T55xx_Timing.m[DLMode].write_1 = c->m[DLMode].write_1 ;// * 8; - if (DLMode == T55xx_DLMode_1of4) { - if (c->m[DLMode].write_2 != 0) T55xx_Timing.m[DLMode].write_2 = c->m[DLMode].write_2;// * 8; - if (c->m[DLMode].write_3 != 0) T55xx_Timing.m[DLMode].write_3 = c->m[DLMode].write_3;// * 8 ; - } else { - T55xx_Timing.m[DLMode].write_2 = 0x00; - T55xx_Timing.m[DLMode].write_3 = 0x00; + DbpString(_BLUE_("LF T55XX config")); + Dbprintf(" [r] [a] [b] [c] [d] [e] [f] [g]"); + Dbprintf(" mode |start|write|write|write| read|write|write"); + Dbprintf(" | gap | gap | 0 | 1 | gap | 2 | 3"); + Dbprintf("---------------------------+-----+-----+-----+-----+-----+-----+------"); + + for (uint8_t i = 0; i < 4; i++) { + + char s[160]; + memset(s, 0, sizeof(s)); + + switch (i) { + case T55XX_DLMODE_FIXED : + sprintf(s, _YELLOW_("fixed bit length") _GREEN_("(default)") "|"); + break; + case T55XX_DLMODE_LLR : + sprintf(s, _YELLOW_(" long leading reference") "|"); + break; + case T55XX_DLMODE_LEADING_ZERO : + sprintf(s, _YELLOW_(" leading zero") "|"); + break; + case T55XX_DLMODE_1OF4 : + sprintf(s, _YELLOW_(" 1 of 4 coding reference") "|"); + break; + default: + break; } - if (c->m[DLMode].read_gap != 0) T55xx_Timing.m[DLMode].read_gap = c->m[DLMode].read_gap;//* 8; + + if (T55xx_Timing.m[i].start_gap != 0xFFFF) + sprintf(s + strlen(s), " %3d | ", T55xx_Timing.m[i].start_gap / 8); + else + PRN_NA; + + if (T55xx_Timing.m[i].write_gap != 0xFFFF) + sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].write_gap / 8); + else + PRN_NA; + + if (T55xx_Timing.m[i].write_0 != 0xFFFF) + sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].write_0 / 8); + else + PRN_NA; + + if (T55xx_Timing.m[i].write_1 != 0xFFFF) + sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].write_1 / 8); + else + PRN_NA; + + if (T55xx_Timing.m[i].read_gap != 0xFFFF) + sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].read_gap / 8); + else + PRN_NA; + + if (T55xx_Timing.m[i].write_2 != 0xFFFF && i == T55XX_DLMODE_1OF4) + sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].write_2 / 8); + else + PRN_NA + + if (T55xx_Timing.m[i].write_3 != 0xFFFF && i == T55XX_DLMODE_1OF4) + sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].write_3 / 8); + else + PRN_NA; + + s[strlen(s)] = 0; + DbpString(s); + } + DbpString(""); +} + +void setT55xxConfig(uint8_t arg0, t55xx_configurations_t *c) { + for (uint8_t i = 0; i < 4; i++) { + if (c->m[i].start_gap != 0) + T55xx_Timing.m[i].start_gap = c->m[i].start_gap; + + if (c->m[i].write_gap != 0) + T55xx_Timing.m[i].write_gap = c->m[i].write_gap; + + if (c->m[i].write_0 != 0) + T55xx_Timing.m[i].write_0 = c->m[i].write_0; + + if (c->m[i].write_1 != 0) + T55xx_Timing.m[i].write_1 = c->m[i].write_1; + + if (i == T55XX_DLMODE_1OF4) { + if (c->m[i].write_2 != 0) + T55xx_Timing.m[i].write_2 = c->m[i].write_2; + + if (c->m[i].write_3 != 0) + T55xx_Timing.m[i].write_3 = c->m[i].write_3; + + } else { + T55xx_Timing.m[i].write_2 = 0x00; + T55xx_Timing.m[i].write_3 = 0x00; + } + if (c->m[i].read_gap != 0) + T55xx_Timing.m[i].read_gap = c->m[i].read_gap; } printT55xxConfig(); @@ -203,7 +297,6 @@ void setT55xxConfig(uint8_t arg0, t55xx_config *c) { return; } - uint8_t *buf = BigBuf_malloc(T55XX_CONFIG_LEN); Flash_CheckBusy(BUSY_TIMEOUT); uint16_t res = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN); @@ -215,21 +308,23 @@ void setT55xxConfig(uint8_t arg0, t55xx_config *c) { memcpy(buf, &T55xx_Timing, T55XX_CONFIG_LEN); + // delete old configuration Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); Flash_Erase4k(3, 0xD); + // write new res = Flash_Write(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN); if (res == T55XX_CONFIG_LEN && DBGLEVEL > 1) { - DbpString("T55XX Config save success"); + DbpString("T55XX Config save " _GREEN_("success")); } BigBuf_free(); #endif } -t55xx_config *getT55xxConfig(void) { +t55xx_configurations_t *getT55xxConfig(void) { return &T55xx_Timing;//_FixedBit; } @@ -308,7 +403,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint } // hack2 needed--- it appears to take about 8-16us to turn the antenna back on - // leading to ~ 1 to 2 125khz samples extra in every off period + // leading to ~ 1 to 2 125kHz samples extra in every off period // so we should test for last 0 before next 1 and reduce period_0 by this extra amount... // but is this time different for every antenna or other hw builds??? more testing needed @@ -366,7 +461,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint // Turn off antenna FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // tell client we are done - reply_ng(CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K, PM3_SUCCESS, NULL, 0); + reply_ng(CMD_LF_MOD_THEN_ACQ_RAW_ADC, PM3_SUCCESS, NULL, 0); } /* blank r/w tag data stream @@ -381,9 +476,9 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint void ReadTItag(void) { StartTicks(); // some hardcoded initial params - // when we read a TI tag we sample the zerocross line at 2Mhz - // TI tags modulate a 1 as 16 cycles of 123.2Khz - // TI tags modulate a 0 as 16 cycles of 134.2Khz + // when we read a TI tag we sample the zerocross line at 2MHz + // TI tags modulate a 1 as 16 cycles of 123.2kHz + // TI tags modulate a 0 as 16 cycles of 134.2kHz #define FSAMPLE 2000000 #define FREQLO 123200 #define FREQHI 134200 @@ -399,9 +494,9 @@ void ReadTItag(void) { // when to tell if we're close enough to one freq or another uint32_t threshold = (sampleslo - sampleshi + 1) >> 1; - // TI tags charge at 134.2Khz + // TI tags charge at 134.2kHz FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8kHz // Place FPGA in passthrough mode, in this mode the CROSS_LO line // connects to SSP_DIN and the SSP_DOUT logic level controls @@ -627,8 +722,8 @@ void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc) { } Dbprintf("Writing to tag: %x%08x, crc=%x", idhi, idlo, crc); - // TI tags charge at 134.2Khz - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz + // TI tags charge at 134.2kHz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8kHz // Place FPGA in passthrough mode, in this mode the CROSS_LO line // connects to SSP_DIN and the SSP_DOUT logic level controls // whether we're modulating the antenna (high) @@ -701,9 +796,9 @@ void SimulateTagLowFrequencyEx(int period, int gap, bool ledcontrol, int numcycl sample_config *sc = getSamplingConfig(); if ((sc->divisor == 1) || (sc->divisor < 0) || (sc->divisor > 255)) - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8kHz else if (sc->divisor == 0) - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz else FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor); @@ -946,7 +1041,7 @@ void CmdHIDsimTAGEx(uint32_t hi, uint32_t lo, bool ledcontrol, int numcycles) { void CmdHIDsimTAG(uint32_t hi, uint32_t lo, bool ledcontrol) { CmdHIDsimTAGEx(hi, lo, ledcontrol, -1); - reply_ng(CMD_HID_SIM_TAG, PM3_EOPABORTED, NULL, 0); + reply_ng(CMD_LF_HID_SIMULATE, PM3_EOPABORTED, NULL, 0); } // prepare a waveform pattern in the buffer based on the ID given then @@ -984,7 +1079,7 @@ void CmdFSKsimTAG(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, if (ledcontrol) LED_A_ON(); SimulateTagLowFrequency(n, 0, ledcontrol); if (ledcontrol) LED_A_OFF(); - reply_ng(CMD_FSK_SIM_TAG, PM3_EOPABORTED, NULL, 0); + reply_ng(CMD_LF_FSK_SIMULATE, PM3_EOPABORTED, NULL, 0); } // compose ask waveform for one bit(ASK) @@ -1073,7 +1168,7 @@ void CmdASKsimTAG(uint8_t encoding, uint8_t invert, uint8_t separator, uint8_t c if (ledcontrol) LED_A_ON(); SimulateTagLowFrequency(n, 0, ledcontrol); if (ledcontrol) LED_A_OFF(); - reply_ng(CMD_ASK_SIM_TAG, PM3_EOPABORTED, NULL, 0); + reply_ng(CMD_LF_ASK_SIMULATE, PM3_EOPABORTED, NULL, 0); } //carrier can be 2,4 or 8 @@ -1120,7 +1215,7 @@ void CmdPSKsimTag(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, u if (ledcontrol) LED_A_ON(); SimulateTagLowFrequency(n, 0, ledcontrol); if (ledcontrol) LED_A_OFF(); - reply_ng(CMD_PSK_SIM_TAG, PM3_EOPABORTED, NULL, 0); + reply_ng(CMD_LF_PSK_SIMULATE, PM3_EOPABORTED, NULL, 0); } // loop to get raw HID waveform then FSK demodulate the TAG ID from it @@ -1129,7 +1224,7 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) size_t size; uint32_t hi2 = 0, hi = 0, lo = 0; int dummyIdx = 0; - // Configure to go in 125Khz listen mode + // Configure to go in 125kHz listen mode LFSetupFPGAForADC(95, true); //clear read buffer @@ -1380,7 +1475,7 @@ void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { BigBuf_Clear_keep_EM(); - // Configure to go in 125Khz listen mode + // Configure to go in 125kHz listen mode LFSetupFPGAForADC(95, true); while (!BUTTON_PRESS() && !data_available()) { @@ -1478,37 +1573,35 @@ void TurnReadLF_off(uint32_t delay) { } // Macro for code readability -#define BitStream_Byte(X) ((X) >> 3) -#define BitStream_Bit(X) ((X) & 7) -#define t55_llr_ref (136 * 8) -#define t55_send_PwdMode (arg & 0x01) -#define t55_send_Page ((arg & 0x02) >> 1) -#define t55_send_TestMode ((arg & 0x04) >> 2) -#define t55_send_RegReadMode ((arg & 0x20) >> 5) -#define t55_send_ReadCmd ((arg & 0x40) >> 6) -#define t55_send_Reset ((arg & 0x80) >> 7) +#define BITSTREAM_BYTE(x) ((x) >> 3) // iceman note: isn't this NIBBLE??? +#define BITSTREAM_BIT(x) ((x) & 7) + +#define T55_LLR_REF (136 * 8) // Write one bit to chip void T55xxWriteBit(uint8_t bit, uint8_t downlink_idx) { - // Dbprintf ("%d",bit); - // If bit = 4 Send Long Leading Reference which is (138*8) + WRITE_0 switch (bit) { case 0 : + // send bit 0/00 TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_0); - break; // Send bit 0/00 + break; case 1 : + // send bit 1/01 TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_1); - break; // Send bit 1/01 + break; case 2 : + // send bits 10 (1 of 4) TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_2); - break; // Send bits 10 (1 of 4) + break; case 3 : + // send bits 11 (1 of 4) TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_3); - break; // Send bits 11 (1 of 4) + break; case 4 : - TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_0 + t55_llr_ref); - break; // Send Long Leading Reference + // send Long Leading Reference + TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_0 + T55_LLR_REF); + break; } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); @@ -1522,94 +1615,110 @@ void T55xxWriteBit(uint8_t bit, uint8_t downlink_idx) { // num_bits - how many bits (low x bits of data) Max 32 bits at a time // max_len - how many bytes can the bit_array hold (ensure no buffer overflow) // returns "Next" bit offset / bits stored (for next store) -uint8_t T55xx_SetBits(uint8_t *BitStream, uint8_t start_offset, uint32_t data, uint8_t num_bits, uint8_t max_len) { +uint8_t T55xx_SetBits(uint8_t *bs, uint8_t start_offset, uint32_t data, uint8_t num_bits, uint8_t max_len) { int8_t offset; - int8_t NextOffset = start_offset; + int8_t next_offset = start_offset; // Check if data will fit. if ((start_offset + num_bits) <= (max_len * 8)) { // Loop through the data and store for (offset = (num_bits - 1); offset >= 0; offset--) { - if ((data >> offset) & 1) BitStream[BitStream_Byte(NextOffset)] |= (1 << BitStream_Bit(NextOffset)); // Set the bit to 1 - else BitStream[BitStream_Byte(NextOffset)] &= (0xff ^ (1 << BitStream_Bit(NextOffset))); // Set the bit to 0 + if ((data >> offset) & 1) + bs[BITSTREAM_BYTE(next_offset)] |= (1 << BITSTREAM_BIT(next_offset)); // Set 1 + else + bs[BITSTREAM_BYTE(next_offset)] &= (0xff ^ (1 << BITSTREAM_BIT(next_offset))); // Set 0 - NextOffset++; + next_offset++; } } else { // Note: This should never happen unless some code changes cause it. // So short message for coders when testing. - Dbprintf("T55 too many bits"); + Dbprintf(_RED_("T55 too many bits")); } - return NextOffset; + return next_offset; } // Send one downlink command to the card -// void T55xx_SendCMD (uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) { -void T55xx_SendCMD(uint32_t Data, uint32_t Pwd, uint16_t arg) { +void T55xx_SendCMD(uint32_t data, uint32_t pwd, uint16_t arg) { /* arg bits - xxxx xxxxxxx1 0x001 PwdMode - xxxx xxxxxx1x 0x002 Page - xxxx xxxxx1xx 0x004 testMode - xxxx xxx11xxx 0x018 downlink mode - xxxx xx1xxxxx 0x020 !reg_readmode - xxxx x1xxxxxx 0x040 called for a read, so no data packet - xxxx 1xxxxxxx 0x080 reset - xxx1 xxxxxxxx 0x100 brute force - 111x xxxxxxxx 0xE00 Block + xxxx xxxxxxx1 0x001 password mode (Y/N) + xxxx xxxxxx1x 0x002 page (0|1) + xxxx xxxxx1xx 0x004 test mode (Y/N) + xxxx xxx11xxx 0x018 selected downlink mode (0|1|2|3|) + xxxx xx1xxxxx 0x020 !reg_readmode (ICEMAN ?? Why use negative in the bool ??) + xxxx x1xxxxxx 0x040 called for a read, so no data packet (Y/N) + xxxx 1xxxxxxx 0x080 reset (Y/N) + xxx1 xxxxxxxx 0x100 brute force (Y/N) + 111x xxxxxxxx 0xE00 block to write (0-7) */ + bool t55_send_pwdmode = (arg & 0x1); + bool t55_send_page = ((arg >> 1) & 0x1); + bool t55_send_testmode = ((arg >> 2) & 0x1); + bool t55_send_regreadmode = ((arg >> 5) & 0x1); + bool t55_send_readcmd = ((arg >> 6) & 0x1); + bool t55_send_reset = ((arg >> 7) & 0x1); + bool t55_brute_mem = ((arg >> 8) & 0x1); - uint8_t downlink_mode = (arg >> 3) & 0x03; - uint8_t i = 0; - uint8_t BitStream[10]; // Max Downlink Command size ~74 bits, so 10 bytes (80 bits) - uint8_t BitStreamLen = 0; - uint8_t SendBits; - uint8_t start_wait = 4; - bool brute_mem = (arg & 0x100); - uint8_t Block = (arg >> 9) & 0x07; + uint8_t downlink_mode = (arg >> 3) & 0x03; + uint8_t block_no = (arg >> 9) & 0x07; - if (brute_mem) start_wait = 0; + // no startup delay when in bruteforce command + uint8_t start_wait = (t55_brute_mem) ? 0 : 4; - // Build Bit Stream to send. - memset(BitStream, 0x00, sizeof(BitStream)); + // Max Downlink Command size ~74 bits, so 10 bytes (80 bits) + uint8_t bs[10]; + memset(bs, 0x00, sizeof(bs)); - BitStreamLen = 0; // Ensure 0 bit index to start. + uint8_t len = 0; - // Add Leading 0 and 1 of 4 reference bit - if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) - BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, 0, 1, sizeof(BitStream)); + // build bit stream to send. - // Add extra reference 0 for 1 of 4 - if (downlink_mode == T55xx_DLMode_1of4) - BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, 0, 1, sizeof(BitStream)); + // add Leading 0 + if (downlink_mode == T55XX_DLMODE_LEADING_ZERO) + len = T55xx_SetBits(bs, len, 0, 1, sizeof(bs)); - // Add Opcode - if (t55_send_Reset) { - // Reset : r*) 00 - BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, 0, 2, sizeof(BitStream)); + // add 1 of 4 reference bit + if (downlink_mode == T55XX_DLMODE_1OF4) { + len = T55xx_SetBits(bs, len, 0, 1, sizeof(bs)); + // add extra zero + len = T55xx_SetBits(bs, len, 0, 1, sizeof(bs)); + } + + // add Opcode + if (t55_send_reset) { + // reset : r*) 00 + len = T55xx_SetBits(bs, len, 0, 2, sizeof(bs)); } else { - if (t55_send_TestMode) Dbprintf("TestMODE"); - BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, t55_send_TestMode ? 0 : 1, 1, sizeof(BitStream)); - BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, t55_send_TestMode ? 1 : t55_send_Page, 1, sizeof(BitStream)); - //if (PwdMode) { - if (t55_send_PwdMode) { + + if (t55_send_testmode) + Dbprintf(_YELLOW_("Using Test Mode")); + + len = T55xx_SetBits(bs, len, t55_send_testmode ? 0 : 1, 1, sizeof(bs)); + + len = T55xx_SetBits(bs, len, t55_send_testmode ? 1 : t55_send_page, 1, sizeof(bs)); + + if (t55_send_pwdmode) { // Leading 0 and 1 of 4 00 fixed bits if passsword used - if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) { - BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, 0, 2, sizeof(BitStream)); + if ((downlink_mode == T55XX_DLMODE_LEADING_ZERO) || (downlink_mode == T55XX_DLMODE_1OF4)) { + len = T55xx_SetBits(bs, len, 0, 2, sizeof(bs)); } - BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, Pwd, 32, sizeof(BitStream)); + len = T55xx_SetBits(bs, len, pwd, 32, sizeof(bs)); } // Add Lock bit 0 - if (!t55_send_RegReadMode) BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, 0, 1, sizeof(BitStream)); + if (t55_send_regreadmode == false) + len = T55xx_SetBits(bs, len, 0, 1, sizeof(bs)); // Add Data if a write command - if (!t55_send_ReadCmd) BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, Data, 32, sizeof(BitStream)); + if (t55_send_readcmd == false) + len = T55xx_SetBits(bs, len, data, 32, sizeof(bs)); // Add Address - if (!t55_send_RegReadMode) BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, Block, 3, sizeof(BitStream)); + if (t55_send_regreadmode == false) + len = T55xx_SetBits(bs, len, block_no, 3, sizeof(bs)); } // Send Bits to T55xx @@ -1621,22 +1730,23 @@ void T55xx_SendCMD(uint32_t Data, uint32_t Pwd, uint16_t arg) { // Trigger T55x7 in mode. FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(T55xx_Timing.m[downlink_mode].start_gap * 8); + WaitUS(T55xx_Timing.m[downlink_mode].start_gap); // If long leading 0 send long reference pulse - if (downlink_mode == T55xx_DLMode_LLR) - T55xxWriteBit(T55xx_LongLeadingReference, downlink_mode);//Timing); // Send Long Leading Start Reference + if (downlink_mode == T55XX_DLMODE_LLR) + T55xxWriteBit(T55XX_LONGLEADINGREFERENCE, downlink_mode);//Timing); // Send Long Leading Start Reference - if ((downlink_mode == T55xx_DLMode_1of4) && (BitStreamLen > 0)) { // 1 of 4 need to send 2 bits at a time - for (i = 0; i < BitStreamLen - 1; i += 2) { - SendBits = (BitStream[BitStream_Byte(i)] >> (BitStream_Bit(i)) & 1) << 1; // Bit i - SendBits += (BitStream[BitStream_Byte(i + 1)] >> (BitStream_Bit(i + 1)) & 1); // Bit i+1; - T55xxWriteBit(SendBits & 3, downlink_mode);//Timing); + uint8_t sendbits; + if ((downlink_mode == T55XX_DLMODE_1OF4) && (len > 0)) { // 1 of 4 need to send 2 bits at a time + for (uint8_t i = 0; i < len - 1; i += 2) { + sendbits = (bs[BITSTREAM_BYTE(i)] >> (BITSTREAM_BIT(i)) & 1) << 1; // Bit i + sendbits += (bs[BITSTREAM_BYTE(i + 1)] >> (BITSTREAM_BIT(i + 1)) & 1); // Bit i+1; + T55xxWriteBit(sendbits & 3, downlink_mode); } } else { - for (i = 0; i < BitStreamLen; i++) { - SendBits = (BitStream[BitStream_Byte(i)] >> BitStream_Bit(i)); - T55xxWriteBit(SendBits & 1, downlink_mode);//Timing); + for (uint8_t i = 0; i < len; i++) { + sendbits = (bs[BITSTREAM_BYTE(i)] >> BITSTREAM_BIT(i)); + T55xxWriteBit(sendbits & 1, downlink_mode); } } } @@ -1722,7 +1832,7 @@ void T55xxWriteBlock(uint8_t *data) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // cmd_send(CMD_ACK,0,0,0,0,0); - reply_ng(CMD_T55XX_WRITE_BLOCK, PM3_SUCCESS, NULL, 0); + reply_ng(CMD_LF_T55XX_WRITEBL, PM3_SUCCESS, NULL, 0); LED_A_OFF(); } @@ -1731,7 +1841,7 @@ void T55xxWriteBlock(uint8_t *data) { void T55xxWriteBlock(uint8_t *data) { t55xx_write_block_t *c = (t55xx_write_block_t *)data; T55xxWriteBlockExt(c->data, c->blockno, c->pwd, c->flags); - // reply_ng(CMD_T55XX_WRITE_BLOCK, PM3_SUCCESS, NULL, 0); + // reply_ng(CMD_LF_T55XX_WRITEBL, PM3_SUCCESS, NULL, 0); } */ /* @@ -1783,7 +1893,7 @@ bool brute_mem = (flags & 0x0100) >> 8; // Turn the field off if (!brute_mem) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - reply_ng(CMD_T55XX_READ_BLOCK, PM3_SUCCESS, NULL, 0); + reply_ng(CMD_LF_T55XX_READBL, PM3_SUCCESS, NULL, 0); LED_A_OFF(); } } @@ -1843,7 +1953,7 @@ void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block, // Turn the field off if (!brute_mem) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - reply_ng(CMD_T55XX_READ_BLOCK, PM3_SUCCESS, NULL, 0); + reply_ng(CMD_LF_T55XX_READBL, PM3_SUCCESS, NULL, 0); LED_A_OFF(); } @@ -1941,12 +2051,12 @@ OUT: LEDsoff(); } -void T55xxWakeUp(uint32_t Pwd, uint8_t flags) { +void T55xxWakeUp(uint32_t pwd, uint8_t flags) { flags |= 0x01 | 0x40 | 0x20; //Password | Read Call (no data) | reg_read no block LED_B_ON(); - T55xx_SendCMD(0, Pwd, flags); + T55xx_SendCMD(0, pwd, flags); //-- Turn and leave field on to let the begin repeating transmission TurnReadLFOn(20 * 1000); @@ -2173,7 +2283,7 @@ uint8_t *fwd_write_ptr; //forwardlink bit pointer //==================================================================== //-------------------------------------------------------------------- // VALUES TAKEN FROM EM4x function: SendForward -// START_GAP = 440; (55*8) cycles at 125Khz (8us = 1cycle) +// START_GAP = 440; (55*8) cycles at 125kHz (8us = 1cycle) // WRITE_GAP = 128; (16*8) // WRITE_1 = 256 32*8; (32*8) @@ -2331,7 +2441,7 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) { DoPartialAcquisition(20, true, 6000, 1000); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - reply_ng(CMD_EM4X_READ_WORD, PM3_SUCCESS, NULL, 0); + reply_ng(CMD_LF_EM4X_READWORD, PM3_SUCCESS, NULL, 0); LED_A_OFF(); } @@ -2364,7 +2474,7 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) { DoPartialAcquisition(20, true, 6000, 1000); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - reply_ng(CMD_EM4X_WRITE_WORD, PM3_SUCCESS, NULL, 0); + reply_ng(CMD_LF_EM4X_WRITEWORD, PM3_SUCCESS, NULL, 0); LED_A_OFF(); } diff --git a/armsrc/lfops.h b/armsrc/lfops.h new file mode 100644 index 000000000..186b41f90 --- /dev/null +++ b/armsrc/lfops.h @@ -0,0 +1,69 @@ +//----------------------------------------------------------------------------- +// Jonathan Westhues, Aug 2005 +// Gerhard de Koning Gans, April 2008, May 2011 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Definitions internal to the app source. +//----------------------------------------------------------------------------- +#ifndef __LFOPS_H +#define __LFOPS_H + +#include "common.h" + +#include "pm3_cmd.h" // struct + +extern uint8_t decimation; +extern uint8_t bits_per_sample ; +extern bool averaging; + +void AcquireRawAdcSamples125k(int divisor); +void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command); +void ReadTItag(void); +void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc); + +void AcquireTiType(void); +void AcquireRawBitsTI(void); +void SimulateTagLowFrequencyEx(int period, int gap, bool ledcontrol, int numcycles); +void SimulateTagLowFrequency(int period, int gap, bool ledcontrol); +void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen); + +void CmdHIDsimTAGEx(uint32_t hi, uint32_t lo, bool ledcontrol, int numcycles); +void CmdHIDsimTAG(uint32_t hi, uint32_t lo, bool ledcontrol); + +void CmdFSKsimTAG(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, uint8_t *bits, bool ledcontrol); +void CmdASKsimTAG(uint8_t encoding, uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol); +void CmdPSKsimTag(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol); + +void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); +void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); // Realtime demodulation mode for AWID26 +void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol); +void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); +void CopyIOtoT55x7(uint32_t hi, uint32_t lo); // Clone an ioProx card to T5557/T5567 +void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567 +void CopyVikingtoT55xx(uint32_t block1, uint32_t block2, uint8_t Q5); +void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo); +void CopyIndala64toT55x7(uint32_t hi, uint32_t lo); // Clone Indala 64-bit tag by UID to T55x7 +void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7); // Clone Indala 224-bit tag by UID to T55x7 +void T55xxResetRead(uint8_t flags); +//id T55xxWriteBlock(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags); +void T55xxWriteBlock(uint8_t *data); +// void T55xxWriteBlockExt(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags); +void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block, uint32_t pwd, uint8_t downlink_mode); +void T55xxWakeUp(uint32_t pwd, uint8_t flags); +void T55xx_ChkPwds(uint8_t flags); + +void TurnReadLFOn(uint32_t delay); + +void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd); +void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd); + +void Cotag(uint32_t arg0); +void setT55xxConfig(uint8_t arg0, t55xx_configurations_t *c); +t55xx_configurations_t *getT55xxConfig(void); +void printT55xxConfig(void); +void loadT55xxConfig(void); + +#endif diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index c88401229..498d8f747 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -8,12 +8,20 @@ #include "lfsampling.h" +#include "proxmark3_arm.h" +#include "BigBuf.h" +#include "fpgaloader.h" +#include "ticks.h" +#include "dbprint.h" +#include "util.h" +#include "lfdemod.h" + /* Default LF config is set to: decimation = 1 (we keep 1 out of 1 samples) bits_per_sample = 8 averaging = YES - divisor = 95 (125khz) + divisor = 95 (125kHz) trigger_threshold = 0 */ sample_config config = { 1, 8, 1, 95, 0 } ; @@ -83,9 +91,9 @@ void pushBit(BitstreamOut *stream, uint8_t bit) { void LFSetupFPGAForADC(int divisor, bool lf_field) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); if ((divisor == 1) || (divisor < 0) || (divisor > 255)) - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8kHz else if (divisor == 0) - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz else FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor); diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index e3c7a0b4d..b17a871ba 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -1,12 +1,8 @@ #ifndef __LFSAMPLING_H #define __LFSAMPLING_H -#include "proxmark3.h" -#include "apps.h" -#include "util.h" -#include "string.h" -#include "usb_cdc.h" // for usb_poll_validate_length -#include "ticks.h" // for StartTicks +#include "common.h" +#include "pm3_cmd.h" typedef struct BitstreamOut BitstreamOut; @@ -82,5 +78,4 @@ sample_config *getSamplingConfig(); void printConfig(); - #endif // __LFSAMPLING_H diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 2d56a8a37..e8263d52a 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -15,9 +15,23 @@ #include "mifarecmd.h" -#include - #include "pmflash.h" +#include "proxmark3_arm.h" +#include "string.h" +#include "mifareutil.h" +#include "protocols.h" +#include "parity.h" +#include "BigBuf.h" +#include "cmd.h" +#include "flashmem.h" +#include "fpgaloader.h" +#include "iso14443a.h" +#include "mifaredesfire.h" +#include "util.h" +#include "commonutil.h" +#include "crc16.h" +#include "dbprint.h" +#include "ticks.h" #ifndef HARDNESTED_AUTHENTICATION_TIMEOUT # define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) @@ -94,7 +108,7 @@ void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain) { if (DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED"); LED_B_ON(); - reply_ng(CMD_MIFARE_READBL, status, dataoutbuf, 16); + reply_ng(CMD_HF_MIFARE_READBL, status, dataoutbuf, 16); LED_B_OFF(); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); @@ -1328,8 +1342,6 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da for (uint16_t i = s_point; i < keyCount; ++i) { - //if ( i % 100 == 0) Dbprintf("ChkKeys_fast: sector %d | checking %d | %d found | s_point %d", s, i, foundkeys, s_point); - // Allow button press / usb cmd to interrupt device if (BUTTON_PRESS() && !data_available()) { goto OUT; @@ -1495,7 +1507,7 @@ OUT: uint16_t bar = 0; uint8_t j = 0; - for (uint8_t m = 64; m < sizeof(found); m++) { + for (uint8_t m = 64; m < ARRAYLEN(found); m++) { bar |= ((uint16_t)(found[m] & 1) << j++); } @@ -1511,6 +1523,33 @@ OUT: FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); BigBuf_free(); BigBuf_Clear_ext(false); + + // special trick ecfill + if (use_flashmem && foundkeys == allkeys) { + + uint8_t block[16] = {0}; + for (int i = 0; i < sectorcnt; i++) { + + uint8_t blockno; + if (i < 32) { + blockno = (i * 4) ^ 0x3; + } else { + blockno = (32 * 4 + (i - 32) * 16) ^ 0xF; + } + // get ST + emlGetMem(block, blockno, 1); + + memcpy(block, k_sector[i].keyA, 6); + memcpy(block + 10, k_sector[i].keyB, 6); + + emlSetMem_xt(block, blockno, 1, sizeof(block)); + } + int oldbg = DBGLEVEL; + DBGLEVEL = DBG_NONE; + MifareECardLoad(sectorcnt, 0); + MifareECardLoad(sectorcnt, 1); + DBGLEVEL = oldbg; + } } else { // partial/none keys found reply_mix(CMD_ACK, foundkeys, 0, 0, 0, 0); @@ -1601,7 +1640,7 @@ void MifareChkKeys(uint8_t *datain) { LED_B_ON(); - reply_ng(CMD_MIFARE_CHKKEYS, PM3_SUCCESS, (uint8_t *)&keyresult, sizeof(keyresult)); + reply_ng(CMD_HF_MIFARE_CHKKEYS, PM3_SUCCESS, (uint8_t *)&keyresult, sizeof(keyresult)); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); @@ -1637,7 +1676,7 @@ void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) { // size_t size = blockcnt * 16; if (size > PM3_CMD_DATA_SIZE) { - reply_ng(CMD_MIFARE_EML_MEMGET, PM3_EMALLOC, NULL, 0); + reply_ng(CMD_HF_MIFARE_EML_MEMGET, PM3_EMALLOC, NULL, 0); return; } @@ -1646,7 +1685,7 @@ void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) { emlGetMem(buf, blockno, blockcnt); // data, block num, blocks count (max 4) LED_B_ON(); - reply_ng(CMD_MIFARE_EML_MEMGET, PM3_SUCCESS, buf, size); + reply_ng(CMD_HF_MIFARE_EML_MEMGET, PM3_SUCCESS, buf, size); LED_B_OFF(); BigBuf_free_keep_EM(); } @@ -1655,10 +1694,15 @@ void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) { // Load a card into the emulator memory // //----------------------------------------------------------------------------- -int MifareECardLoad(uint32_t arg0, uint32_t arg1) { +int MifareECardLoadExt(uint8_t numSectors, uint8_t keyType) { + int retval = MifareECardLoad(numSectors, keyType); + reply_ng(CMD_HF_MIFARE_EML_LOAD, retval, NULL, 0); + return retval; +} + +int MifareECardLoad(uint8_t numSectors, uint8_t keyType) { + uint32_t cuid = 0; - uint8_t numSectors = arg0; - uint8_t keyType = arg1; struct Crypto1State mpcs = {0, 0}; struct Crypto1State *pcs; pcs = &mpcs; @@ -1669,68 +1713,63 @@ int MifareECardLoad(uint32_t arg0, uint32_t arg1) { uint8_t uid[10] = {0x00}; LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); clear_trace(); set_tracing(true); - bool isOK = true; + int retval; if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - isOK = false; - if (DBGLEVEL >= 1) Dbprintf("Can't select card"); + retval = PM3_ESOFT; + if (DBGLEVEL > DBG_ERROR) Dbprintf("Can't select card"); + goto out; } - for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) { + for (uint8_t sectorNo = 0; sectorNo < numSectors; sectorNo++) { uint64_t ui64Key = emlGetKey(sectorNo, keyType); if (sectorNo == 0) { - if (isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { - if (DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo); + if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { + if (DBGLEVEL > DBG_ERROR) Dbprintf("Sector[%2d]. Auth error", sectorNo); break; } } else { - if (isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) { - isOK = false; - if (DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth nested error", sectorNo); - break; + if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) { + retval = PM3_ESOFT; + if (DBGLEVEL > DBG_ERROR) Dbprintf("Sector[%2d]. Auth nested error", sectorNo); + goto out; } } - for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { - if (isOK && mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) { - isOK = false; - if (DBGLEVEL >= 1) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo); + for (uint8_t blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) { + if (mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) { + retval = PM3_ESOFT; + if (DBGLEVEL > DBG_ERROR) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo); break; } - if (isOK) { - if (blockNo < NumBlocksPerSector(sectorNo) - 1) { - emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1); - } else { // sector trailer, keep the keys, set only the AC - emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); - memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4); - emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); - } + if (blockNo < NumBlocksPerSector(sectorNo) - 1) { + emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1); + } else { // sector trailer, keep the keys, set only the AC + emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); + memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4); + emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); } } - } - if (mifare_classic_halt(pcs, cuid)) - if (DBGLEVEL >= 1) + if (mifare_classic_halt(pcs, cuid)) { + if (DBGLEVEL > DBG_ERROR) Dbprintf("Halt error"); + } - // ----------------------------- crypto1 destroy + if (DBGLEVEL >= DBG_INFO) DbpString("Emulator fill sectors finished"); + +out: crypto1_destroy(pcs); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); - - if (DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED"); - set_tracing(false); - return (isOK) ? PM3_SUCCESS : PM3_EUNDEF; + return retval; } @@ -1941,6 +1980,8 @@ void MifareCIdent() { #define GEN_1A 1 #define GEN_1B 2 #define GEN_2 4 +#define GEN_UNFUSED 5 + // variables uint8_t isGen = 0; uint8_t rec[1] = {0x00}; @@ -1976,6 +2017,11 @@ TEST2: int res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true); if (res == 2) { + if (cuid == 0xAA55C396) { + isGen = GEN_UNFUSED; + goto OUT; + } + ReaderTransmit(rats, sizeof(rats), NULL); res = ReaderReceive(buf, par); if (memcmp(buf, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10\xF0\x05", 11) == 0) { @@ -1990,7 +2036,7 @@ TEST2: OUT: data[0] = isGen; - reply_ng(CMD_MIFARE_CIDENT, PM3_SUCCESS, data, sizeof(data)); + reply_ng(CMD_HF_MIFARE_CIDENT, PM3_SUCCESS, data, sizeof(data)); // turns off OnSuccessMagic(); BigBuf_free(); @@ -2059,7 +2105,7 @@ void MifareSetMod(uint8_t *datain) { crypto1_destroy(pcs); LED_B_ON(); - reply_ng(CMD_MIFARE_SETMOD, isOK, NULL, 0); + reply_ng(CMD_HF_MIFARE_SETMOD, isOK, NULL, 0); LED_B_OFF(); diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index 5e4a5cf97..d563e37a8 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -1,27 +1,53 @@ //----------------------------------------------------------------------------- -// Merlok - June 2011 -// Gerhard de Koning Gans - May 2008 -// Hagen Fritsch - June 2010 +// Jonathan Westhues, Aug 2005 +// Gerhard de Koning Gans, April 2008, May 2011 // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Routines to support ISO 14443 type A. +// Definitions internal to the app source. //----------------------------------------------------------------------------- - #ifndef __MIFARECMD_H #define __MIFARECMD_H -#include "proxmark3.h" -#include "apps.h" -#include "util.h" -#include "string.h" -#include "iso14443a.h" -#include "crapto1/crapto1.h" -#include "mifareutil.h" #include "common.h" -#include "crc.h" -#include "protocols.h" -#include "parity.h" + +void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain); + +void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); +void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes); +void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain); +void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t *datain); +void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); +//void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain); +void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); +void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); +void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain); +void MifareAcquireNonces(uint32_t arg0, uint32_t flags); +void MifareChkKeys(uint8_t *datain); +void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); + +void MifareEMemClr(void); +void MifareEMemSet(uint8_t blockno, uint8_t blockcnt, uint8_t blockwidth, uint8_t *datain); +void MifareEMemGet(uint8_t blockno, uint8_t blockcnt); +int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype); +int MifareECardLoadExt(uint8_t numSectors, uint8_t keyType); + +void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card +void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); +void MifareCIdent(); // is "magic chinese" card? + +void MifareSetMod(uint8_t *datain); +void MifareUSetPwd(uint8_t arg0, uint8_t *datain); +void OnSuccessMagic(); +void OnErrorMagic(uint8_t reason); + +int32_t dist_nt(uint32_t nt1, uint32_t nt2); +void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype); +//void RAMFUNC SniffMifare(uint8_t param); + +void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain); +void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain); + #endif diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index c57fed866..e16c00ed1 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -1,5 +1,20 @@ #include "mifaredesfire.h" +#include "common.h" +#include "proxmark3_arm.h" +#include "string.h" +#include "BigBuf.h" +#include "desfire_key.h" +#include "mifareutil.h" +#include "des.h" +#include "cmd.h" +#include "dbprint.h" +#include "fpgaloader.h" +#include "iso14443a.h" +#include "crc16.h" +#include "mbedtls/aes.h" +#include "commonutil.h" + #define MAX_APPLICATION_COUNT 28 #define MAX_FILE_COUNT 16 #define MAX_DESFIRE_FRAME_SIZE 60 diff --git a/armsrc/mifaredesfire.h b/armsrc/mifaredesfire.h index 7547dfcb2..8daed69aa 100644 --- a/armsrc/mifaredesfire.h +++ b/armsrc/mifaredesfire.h @@ -1,13 +1,26 @@ +//----------------------------------------------------------------------------- +// Jonathan Westhues, Aug 2005 +// Gerhard de Koning Gans, April 2008, May 2011 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Definitions internal to the app source. +//----------------------------------------------------------------------------- #ifndef __MIFAREDESFIRE_H #define __MIFAREDESFIRE_H #include "common.h" -#include "proxmark3.h" -#include "apps.h" -#include "string.h" -#include "BigBuf.h" -#include "iso14443a.h" -#include "desfire_key.h" -#include "mifareutil.h" -#include "des.h" + +bool InitDesfireCard(); +void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain); +void MifareDesfireGetInformation(); +void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); +void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t *datain); +int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout); +size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout); +void OnSuccess(); +void OnError(uint8_t reason); + #endif diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 0e64f00d1..7edcec398 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -20,19 +20,24 @@ // /!\ Printing Debug message is disrupting emulation, // Only use with caution during debugging +#include "mifaresim.h" + +#include #include "iso14443a.h" -#include "mifaresim.h" -#include "crapto1/crapto1.h" #include "BigBuf.h" #include "string.h" #include "mifareutil.h" #include "fpgaloader.h" -#include "proxmark3.h" -#include "usb_cdc.h" +#include "proxmark3_arm.h" #include "cmd.h" #include "protocols.h" -#include "apps.h" +#include "appmain.h" +#include "util.h" +#include "commonutil.h" +#include "crc16.h" +#include "dbprint.h" +#include "ticks.h" static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) { uint8_t sector_trailer[16]; @@ -163,7 +168,7 @@ static bool IsAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) { } } -static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len, uint8_t **rats, uint8_t *rats_len) { +static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_t sak, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len, uint8_t **rats, uint8_t *rats_len) { // SPEC: https://www.nxp.com/docs/en/application-note/AN10833.pdf // ATQA @@ -250,21 +255,21 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * if ((flags & FLAG_MF_MINI) == FLAG_MF_MINI) { memcpy(rATQA, rATQA_Mini, sizeof(rATQA)); rSAK[0] = rSAK_Mini; - Dbprintf("Mifare Mini"); + if (DBGLEVEL > DBG_NONE) Dbprintf("Enforcing Mifare Mini ATQA/SAK"); } else if ((flags & FLAG_MF_1K) == FLAG_MF_1K) { memcpy(rATQA, rATQA_1k, sizeof(rATQA)); rSAK[0] = rSAK_1k; - Dbprintf("Mifare 1K"); + if (DBGLEVEL > DBG_NONE) Dbprintf("Enforcing Mifare 1K ATQA/SAK"); } else if ((flags & FLAG_MF_2K) == FLAG_MF_2K) { memcpy(rATQA, rATQA_2k, sizeof(rATQA)); rSAK[0] = rSAK_2k; *rats = rRATS; *rats_len = sizeof(rRATS); - Dbprintf("Mifare 2K with RATS support"); + if (DBGLEVEL > DBG_NONE) Dbprintf("Enforcing Mifare 2K ATQA/SAK with RATS support"); } else if ((flags & FLAG_MF_4K) == FLAG_MF_4K) { memcpy(rATQA, rATQA_4k, sizeof(rATQA)); rSAK[0] = rSAK_4k; - Dbprintf("Mifare 4K"); + if (DBGLEVEL > DBG_NONE) Dbprintf("Enforcing Mifare 4K ATQA/SAK"); } // Prepare UID arrays @@ -279,7 +284,7 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * *cuid = bytes_to_num(rUIDBCC1, 4); // BCC rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; - if (DBGLEVEL >= DBG_NONE) { + if (DBGLEVEL > DBG_NONE) { Dbprintf("4B UID: %02x%02x%02x%02x", rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3]); } @@ -300,7 +305,7 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * // BCC rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; - if (DBGLEVEL >= DBG_NONE) { + if (DBGLEVEL > DBG_NONE) { Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x", rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], rUIDBCC2[0], rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3]); } @@ -326,7 +331,7 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; rUIDBCC3[4] = rUIDBCC3[0] ^ rUIDBCC3[1] ^ rUIDBCC3[2] ^ rUIDBCC3[3]; - if (DBGLEVEL >= DBG_NONE) { + if (DBGLEVEL > DBG_NONE) { Dbprintf("10B UID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3], @@ -340,6 +345,17 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * Dbprintf("[-] ERROR: UID size not defined"); return false; } + if (flags & FLAG_FORCED_ATQA) { + rATQA[0] = atqa >> 8; + rATQA[1] = atqa & 0xff; + } + if (flags & FLAG_FORCED_SAK) { + rSAK[0] = sak; + } + if (DBGLEVEL > DBG_NONE) { + Dbprintf("ATQA : %02X %02X", rATQA[1], rATQA[0]); + Dbprintf("SAK : %02X", rSAK[0]); + } // clone UIDs for byte-frame anti-collision multiple tag selection procedure memcpy(rUIDBCC1b4, &rUIDBCC1[1], 4); @@ -432,7 +448,7 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * *@param exitAfterNReads, exit simulation after n blocks have been read, 0 is infinite ... * (unless reader attack mode enabled then it runs util it gets enough nonces to recover all keys attmpted) */ -void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) { +void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak) { tag_response_info_t *responses; uint8_t cardSTATE = MFEMUL_NOFIELD; uint8_t uid_len = 0; // 4,7, 10 @@ -495,12 +511,12 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) { uint8_t rAUTH_NT_keystream[4]; uint32_t nonce = 0; - tUart *uart = GetUart(); + tUart14a *uart = GetUart14a(); // free eventually allocated BigBuf memory but keep Emulator Memory BigBuf_free_keep_EM(); - if (MifareSimInit(flags, datain, &responses, &cuid, &uid_len, &rats, &rats_len) == false) { + if (MifareSimInit(flags, datain, atqa, sak, &responses, &cuid, &uid_len, &rats, &rats_len) == false) { BigBuf_free_keep_EM(); return; } @@ -1221,7 +1237,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) { if ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK //Send the collected ar_nr in the response - reply_old(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, button_pushed, 0, &ar_nr_resp, sizeof(ar_nr_resp)); + reply_old(CMD_ACK, CMD_HF_MIFARE_SIMULATE, button_pushed, 0, &ar_nr_resp, sizeof(ar_nr_resp)); } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); diff --git a/armsrc/mifaresim.h b/armsrc/mifaresim.h index d05b730c9..d8c15aee2 100644 --- a/armsrc/mifaresim.h +++ b/armsrc/mifaresim.h @@ -13,14 +13,12 @@ #ifndef __MIFARESIM_H #define __MIFARESIM_H -#include +#include "common.h" #ifndef CheckCrc14A # define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len)) #endif -void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain); - #define AC_DATA_READ 0 #define AC_DATA_WRITE 1 #define AC_DATA_INC 2 @@ -36,4 +34,6 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain); #define AUTHKEYB 1 #define AUTHKEYNONE 0xff +void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak); + #endif diff --git a/armsrc/mifaresniff.c b/armsrc/mifaresniff_disabled.c similarity index 96% rename from armsrc/mifaresniff.c rename to armsrc/mifaresniff_disabled.c index 4171ab572..799fd62be 100644 --- a/armsrc/mifaresniff.c +++ b/armsrc/mifaresniff_disabled.c @@ -68,10 +68,10 @@ void RAMFUNC SniffMifare(uint8_t param) { // Set up the demodulator for tag -> reader responses. - DemodInit(receivedResp, receivedRespPar); + Demod14aInit(receivedResp, receivedRespPar); // Set up the demodulator for the reader -> tag commands - UartInit(receivedCmd, receivedCmdPar); + Uart14aInit(receivedCmd, receivedCmdPar); // Setup and start DMA. // set transfer address and number of bytes. Start transfer. @@ -80,8 +80,8 @@ void RAMFUNC SniffMifare(uint8_t param) { return; } - tUart *uart = GetUart(); - tDemod *demod = GetDemod(); + tUart14a *uart = GetUart14a(); + tDemod14a *demod = GetDemod14a(); MfSniffInit(); @@ -149,10 +149,10 @@ void RAMFUNC SniffMifare(uint8_t param) { uint8_t readerbyte = (previous_data & 0xF0) | (*data >> 4); if (MillerDecoding(readerbyte, (sniffCounter - 1) * 4)) { LogTrace(receivedCmd, uart->len, 0, 0, NULL, true); - DemodReset(); - UartReset(); + Demod14aReset(); + Uart14aReset(); } - ReaderIsActive = (uart->state != STATE_UNSYNCD); + ReaderIsActive = (uart->state != STATE_14A_UNSYNCD); } // no need to try decoding tag data if the reader is sending @@ -160,10 +160,10 @@ void RAMFUNC SniffMifare(uint8_t param) { uint8_t tagbyte = (previous_data << 4) | (*data & 0x0F); if (ManchesterDecoding(tagbyte, 0, (sniffCounter - 1) * 4)) { LogTrace(receivedResp, demod->len, 0, 0, NULL, false); - DemodReset(); - UartReset(); + Demod14aReset(); + Uart14aReset(); } - TagIsActive = (demod->state != DEMOD_UNSYNCD); + TagIsActive = (demod->state != DEMOD_14A_UNSYNCD); } } previous_data = *data; diff --git a/armsrc/mifaresniff.h b/armsrc/mifaresniff_disabled.h similarity index 87% rename from armsrc/mifaresniff.h rename to armsrc/mifaresniff_disabled.h index 198d14daf..426e5ccfa 100644 --- a/armsrc/mifaresniff.h +++ b/armsrc/mifaresniff_disabled.h @@ -11,13 +11,6 @@ #ifndef __MIFARESNIFF_H #define __MIFARESNIFF_H -#include "proxmark3.h" -#include "apps.h" -#include "util.h" -#include "string.h" -#include "iso14443a.h" -#include "crapto1/crapto1.h" -#include "mifareutil.h" #include "common.h" #define SNF_INIT 0 diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index b5f7567f9..ca112f1f8 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -9,6 +9,17 @@ //----------------------------------------------------------------------------- #include "mifareutil.h" +#include "string.h" +#include "BigBuf.h" +#include "iso14443a.h" +#include "ticks.h" +#include "dbprint.h" +#include "parity.h" +#include "commonutil.h" +#include "crc16.h" +#include "protocols.h" +#include "des.h" + int DBGLEVEL = DBG_ERROR; // crypto1 helpers diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index a2086c5e7..64eb04545 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -12,14 +12,8 @@ #ifndef __MIFAREUTIL_H #define __MIFAREUTIL_H -#include "proxmark3.h" -#include "apps.h" -#include "parity.h" -#include "util.h" -#include "string.h" -#include "iso14443a.h" +#include "common.h" #include "crapto1/crapto1.h" -#include "des.h" // mifare authentication #define CRYPT_NONE 0 diff --git a/armsrc/nprintf.c b/armsrc/nprintf.c new file mode 100644 index 000000000..b61ad794d --- /dev/null +++ b/armsrc/nprintf.c @@ -0,0 +1,894 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// 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. +// +// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. These routines are thread +// safe and reentrant! +// Use this instead of the bloated standard/newlib printf cause these use +// malloc for printf (and may not be thread safe). +// +/////////////////////////////////////////////////////////////////////////////// + +#include "nprintf.h" + + +// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the +// printf_config.h header file +// default: undefined +#ifdef PRINTF_INCLUDE_CONFIG_H +#include "printf_config.h" +#endif + + +// 'ntoa' conversion buffer size, this must be big enough to hold one converted +// numeric number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_NTOA_BUFFER_SIZE +#define PRINTF_NTOA_BUFFER_SIZE 32U +#endif + +// 'ftoa' conversion buffer size, this must be big enough to hold one converted +// float number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_FTOA_BUFFER_SIZE +#define PRINTF_FTOA_BUFFER_SIZE 32U +#endif + +// support for the floating point type (%f) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_FLOAT +#define PRINTF_SUPPORT_FLOAT +#endif + +// support for exponential floating point notation (%e/%g) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL +#define PRINTF_SUPPORT_EXPONENTIAL +#endif + +// define the default floating point precision +// default: 6 digits +#ifndef PRINTF_DEFAULT_FLOAT_PRECISION +#define PRINTF_DEFAULT_FLOAT_PRECISION 6U +#endif + +// define the largest float suitable to print with %f +// default: 1e9 +#ifndef PRINTF_MAX_FLOAT +#define PRINTF_MAX_FLOAT 1e9 +#endif + +// support for the long long types (%llu or %p) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG +#define PRINTF_SUPPORT_LONG_LONG +#endif + +// support for the ptrdiff_t type (%t) +// ptrdiff_t is normally defined in as long or long long type +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T +#define PRINTF_SUPPORT_PTRDIFF_T +#endif + +/////////////////////////////////////////////////////////////////////////////// + +// internal flag definitions +#define FLAGS_ZEROPAD (1U << 0U) +#define FLAGS_LEFT (1U << 1U) +#define FLAGS_PLUS (1U << 2U) +#define FLAGS_SPACE (1U << 3U) +#define FLAGS_HASH (1U << 4U) +#define FLAGS_UPPERCASE (1U << 5U) +#define FLAGS_CHAR (1U << 6U) +#define FLAGS_SHORT (1U << 7U) +#define FLAGS_LONG (1U << 8U) +#define FLAGS_LONG_LONG (1U << 9U) +#define FLAGS_PRECISION (1U << 10U) +#define FLAGS_ADAPT_EXP (1U << 11U) + + +// import float.h for DBL_MAX +#if defined(PRINTF_SUPPORT_FLOAT) +#include +#endif + + +// output function type +typedef void (*out_fct_type)(char character, void *buffer, size_t idx, size_t maxlen); + + +// wrapper (used as buffer) for output function type +typedef struct { + void (*fct)(char character, void *arg); + void *arg; +} out_fct_wrap_type; + + +// internal buffer output +static inline void _out_buffer(char character, void *buffer, size_t idx, size_t maxlen) { + if (idx < maxlen) { + ((char *)buffer)[idx] = character; + } +} + + +// internal null output +static inline void _out_null(char character, void *buffer, size_t idx, size_t maxlen) { + (void)character; + (void)buffer; + (void)idx; + (void)maxlen; +} + + +// internal _putchar wrapper +static inline void _out_char(char character, void *buffer, size_t idx, size_t maxlen) { + (void)buffer; + (void)idx; + (void)maxlen; + if (character) { + _putchar(character); + } +} + + +// internal output function wrapper +static inline void _out_fct(char character, void *buffer, size_t idx, size_t maxlen) { + (void)idx; + (void)maxlen; + if (character) { + // buffer is the output fct pointer + ((out_fct_wrap_type *)buffer)->fct(character, ((out_fct_wrap_type *)buffer)->arg); + } +} + + +// internal secure strlen +// \return The length of the string (excluding the terminating 0) limited by 'maxsize' +static inline unsigned int _strnlen_s(const char *str, size_t maxsize) { + const char *s; + for (s = str; *s && maxsize--; ++s); + return (unsigned int)(s - str); +} + + +// internal test if char is a digit (0-9) +// \return true if char is a digit +static inline bool _is_digit(char ch) { + return (ch >= '0') && (ch <= '9'); +} + + +// internal ASCII string to unsigned int conversion +static unsigned int _atoi(const char **str) { + unsigned int i = 0U; + while (_is_digit(**str)) { + i = i * 10U + (unsigned int)(*((*str)++) - '0'); + } + return i; +} + + +// output the specified string in reverse, taking care of any zero-padding +static size_t _out_rev(out_fct_type out, char *buffer, size_t idx, size_t maxlen, const char *buf, size_t len, unsigned int width, unsigned int flags) { + const size_t start_idx = idx; + + // pad spaces up to given width + if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { + for (size_t i = len; i < width; i++) { + out(' ', buffer, idx++, maxlen); + } + } + + // reverse string + while (len) { + out(buf[--len], buffer, idx++, maxlen); + } + + // append pad spaces up to given width + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) { + out(' ', buffer, idx++, maxlen); + } + } + + return idx; +} + + +// internal itoa format +static size_t _ntoa_format(out_fct_type out, char *buffer, size_t idx, size_t maxlen, char *buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags) { + // pad leading zeros + if (!(flags & FLAGS_LEFT)) { + if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + // handle hash + if (flags & FLAGS_HASH) { + if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) { + len--; + if (len && (base == 16U)) { + len--; + } + } + if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'x'; + } else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'X'; + } else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'b'; + } + if (len < PRINTF_NTOA_BUFFER_SIZE) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_NTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +// internal itoa for 'long' type +static size_t _ntoa_long(out_fct_type out, char *buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags) { + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} + + +// internal itoa for 'long long' type +#if defined(PRINTF_SUPPORT_LONG_LONG) +static size_t _ntoa_long_long(out_fct_type out, char *buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags) { + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} +#endif // PRINTF_SUPPORT_LONG_LONG + + +#if defined(PRINTF_SUPPORT_FLOAT) + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT +static size_t _etoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags); +#endif + + +// internal ftoa for fixed decimal floating point +static size_t _ftoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) { + char buf[PRINTF_FTOA_BUFFER_SIZE]; + size_t len = 0U; + double diff = 0.0; + + // powers of 10 + static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + + // test for special values + if (value != value) + return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags); + if (value < -DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags); + if (value > DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags); + + // test for very large values + // standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad + if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) { +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + return _etoa(out, buffer, idx, maxlen, value, prec, width, flags); +#else + return 0U; +#endif + } + + // test for negative + bool negative = false; + if (value < 0) { + negative = true; + value = 0 - value; + } + + // set default precision, if not set explicitly + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + // limit precision to 9, cause a prec >= 10 can lead to overflow errors + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) { + buf[len++] = '0'; + prec--; + } + + int whole = (int)value; + double tmp = (value - whole) * pow10[prec]; + unsigned long frac = (unsigned long)tmp; + diff = tmp - frac; + + if (diff > 0.5) { + ++frac; + // handle rollover, e.g. case 0.99 with prec 1 is 1.0 + if (frac >= pow10[prec]) { + frac = 0; + ++whole; + } + } else if (diff < 0.5) { + } else if ((frac == 0U) || (frac & 1U)) { + // if halfway, round up if odd OR if last digit is 0 + ++frac; + } + + if (prec == 0U) { + diff = value - (double)whole; + if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) { + // exactly 0.5 and ODD, then round up + // 1.5 -> 2, but 2.5 -> 2 + ++whole; + } + } else { + unsigned int count = prec; + // now do fractional part, as an unsigned number + while (len < PRINTF_FTOA_BUFFER_SIZE) { + --count; + buf[len++] = (char)(48U + (frac % 10U)); + if (!(frac /= 10U)) { + break; + } + } + // add extra 0s + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { + buf[len++] = '0'; + } + if (len < PRINTF_FTOA_BUFFER_SIZE) { + // add decimal + buf[len++] = '.'; + } + } + + // do whole part, number is reversed + while (len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = (char)(48 + (whole % 10)); + if (!(whole /= 10)) { + break; + } + } + + // pad leading zeros + if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) { + if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_FTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse +static size_t _etoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) { + // check for NaN and special values + if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) { + return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags); + } + + // determine the sign + const bool negative = value < 0; + if (negative) { + value = -value; + } + + // default precision + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + + // determine the decimal exponent + // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c) + union { + uint64_t U; + double F; + } conv; + + conv.F = value; + int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2 + conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2) + // now approximate log10 from the log2 integer part and an expansion of ln around 1.5 + int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168); + // now we want to compute 10^expval but we want to be sure it won't overflow + exp2 = (int)(expval * 3.321928094887362 + 0.5); + const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453; + const double z2 = z * z; + conv.U = (uint64_t)(exp2 + 1023) << 52U; + // compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex + conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14))))); + // correct for rounding errors + if (value < conv.F) { + expval--; + conv.F /= 10; + } + + // the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters + unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U; + + // in "%g" mode, "prec" is the number of *significant figures* not decimals + if (flags & FLAGS_ADAPT_EXP) { + // do we want to fall-back to "%f" mode? + if ((value >= 1e-4) && (value < 1e6)) { + if ((int)prec > expval) { + prec = (unsigned)((int)prec - expval - 1); + } else { + prec = 0; + } + flags |= FLAGS_PRECISION; // make sure _ftoa respects precision + // no characters in exponent + minwidth = 0U; + expval = 0; + } else { + // we use one sigfig for the whole part + if ((prec > 0) && (flags & FLAGS_PRECISION)) { + --prec; + } + } + } + + // will everything fit? + unsigned int fwidth = width; + if (width > minwidth) { + // we didn't fall-back so subtract the characters required for the exponent + fwidth -= minwidth; + } else { + // not enough characters, so go back to default sizing + fwidth = 0U; + } + if ((flags & FLAGS_LEFT) && minwidth) { + // if we're padding on the right, DON'T pad the floating part + fwidth = 0U; + } + + // rescale the float value + if (expval) { + value /= conv.F; + } + + // output the floating part + const size_t start_idx = idx; + idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP); + + // output the exponent part + if (minwidth) { + // output the exponential symbol + out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen); + // output the exponent value + idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth - 1, FLAGS_ZEROPAD | FLAGS_PLUS); + // might need to right-pad spaces + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) out(' ', buffer, idx++, maxlen); + } + } + return idx; +} +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + + +// internal vsnprintf +static int _vsnprintf(out_fct_type out, char *buffer, const size_t maxlen, const char *format, va_list va) { + unsigned int flags, width, precision, n; + size_t idx = 0U; + + if (!buffer) { + // use null output function + out = _out_null; + } + + while (*format) { + // format specifier? %[flags][width][.precision][length] + if (*format != '%') { + // no + out(*format, buffer, idx++, maxlen); + format++; + continue; + } else { + // yes, evaluate it + format++; + } + + // evaluate flags + flags = 0U; + do { + switch (*format) { + case '0': + flags |= FLAGS_ZEROPAD; + format++; + n = 1U; + break; + case '-': + flags |= FLAGS_LEFT; + format++; + n = 1U; + break; + case '+': + flags |= FLAGS_PLUS; + format++; + n = 1U; + break; + case ' ': + flags |= FLAGS_SPACE; + format++; + n = 1U; + break; + case '#': + flags |= FLAGS_HASH; + format++; + n = 1U; + break; + default : + n = 0U; + break; + } + } while (n); + + // evaluate width field + width = 0U; + if (_is_digit(*format)) { + width = _atoi(&format); + } else if (*format == '*') { + const int w = va_arg(va, int); + if (w < 0) { + flags |= FLAGS_LEFT; // reverse padding + width = (unsigned int) - w; + } else { + width = (unsigned int)w; + } + format++; + } + + // evaluate precision field + precision = 0U; + if (*format == '.') { + flags |= FLAGS_PRECISION; + format++; + if (_is_digit(*format)) { + precision = _atoi(&format); + } else if (*format == '*') { + const int prec = (int)va_arg(va, int); + precision = prec > 0 ? (unsigned int)prec : 0U; + format++; + } + } + + // evaluate length field + switch (*format) { + case 'l' : + flags |= FLAGS_LONG; + format++; + if (*format == 'l') { + flags |= FLAGS_LONG_LONG; + format++; + } + break; + case 'h' : + flags |= FLAGS_SHORT; + format++; + if (*format == 'h') { + flags |= FLAGS_CHAR; + format++; + } + break; +#if defined(PRINTF_SUPPORT_PTRDIFF_T) + case 't' : + flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; +#endif + case 'j' : + flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + case 'z' : + flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + default : + break; + } + + // evaluate specifier + switch (*format) { + case 'd' : + case 'i' : + case 'u' : + case 'x' : + case 'X' : + case 'o' : + case 'b' : { + // set the base + unsigned int base; + if (*format == 'x' || *format == 'X') { + base = 16U; + } else if (*format == 'o') { + base = 8U; + } else if (*format == 'b') { + base = 2U; + } else { + base = 10U; + flags &= ~FLAGS_HASH; // no hash for dec format + } + // uppercase + if (*format == 'X') { + flags |= FLAGS_UPPERCASE; + } + + // no plus or space flag for u, x, X, o, b + if ((*format != 'i') && (*format != 'd')) { + flags &= ~(FLAGS_PLUS | FLAGS_SPACE); + } + + // ignore '0' flag when precision is given + if (flags & FLAGS_PRECISION) { + flags &= ~FLAGS_ZEROPAD; + } + + // convert the integer + if ((*format == 'i') || (*format == 'd')) { + // signed + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + const long long value = va_arg(va, long long); + idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); +#endif + } else if (flags & FLAGS_LONG) { + const long value = va_arg(va, long); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } else { + const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } + } else { + // unsigned + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags); +#endif + } else if (flags & FLAGS_LONG) { + idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags); + } else { + const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int); + idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags); + } + } + format++; + break; + } +#if defined(PRINTF_SUPPORT_FLOAT) + case 'f' : + case 'F' : + if (*format == 'F') flags |= FLAGS_UPPERCASE; + idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + case 'e': + case 'E': + case 'g': + case 'G': + if ((*format == 'g') || (*format == 'G')) flags |= FLAGS_ADAPT_EXP; + if ((*format == 'E') || (*format == 'G')) flags |= FLAGS_UPPERCASE; + idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + case 'c' : { + unsigned int l = 1U; + // pre padding + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // char output + out((char)va_arg(va, int), buffer, idx++, maxlen); + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 's' : { + const char *p = va_arg(va, char *); + unsigned int l = _strnlen_s(p, precision ? precision : (size_t) -1); + // pre padding + if (flags & FLAGS_PRECISION) { + l = (l < precision ? l : precision); + } + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // string output + while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { + out(*(p++), buffer, idx++, maxlen); + } + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 'p' : { + width = sizeof(void *) * 2U; + flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE; +#if defined(PRINTF_SUPPORT_LONG_LONG) + const bool is_ll = sizeof(uintptr_t) == sizeof(long long); + if (is_ll) { + idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void *), false, 16U, precision, width, flags); + } else { +#endif + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void *)), false, 16U, precision, width, flags); +#if defined(PRINTF_SUPPORT_LONG_LONG) + } +#endif + format++; + break; + } + + case '%' : + out('%', buffer, idx++, maxlen); + format++; + break; + + default : + out(*format, buffer, idx++, maxlen); + format++; + break; + } + } + + // termination + out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); + + // return written chars without terminating \0 + return (int)idx; +} + + +/////////////////////////////////////////////////////////////////////////////// + +int printf_(const char *format, ...) { + va_list va; + va_start(va, format); + char buffer[1]; + const int ret = _vsnprintf(_out_char, buffer, (size_t) -1, format, va); + va_end(va); + return ret; +} + + +int sprintf_(char *buffer, const char *format, ...) { + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, (size_t) -1, format, va); + va_end(va); + return ret; +} + + +int snprintf_(char *buffer, size_t count, const char *format, ...) { + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, count, format, va); + va_end(va); + return ret; +} + + +int vprintf_(const char *format, va_list va) { + char buffer[1]; + return _vsnprintf(_out_char, buffer, (size_t) -1, format, va); +} + + +int vsnprintf_(char *buffer, size_t count, const char *format, va_list va) { + return _vsnprintf(_out_buffer, buffer, count, format, va); +} + + +int fctprintf(void (*out)(char character, void *arg), void *arg, const char *format, ...) { + va_list va; + va_start(va, format); + const out_fct_wrap_type out_fct_wrap = { out, arg }; + const int ret = _vsnprintf(_out_fct, (char *)(uintptr_t)&out_fct_wrap, (size_t) -1, format, va); + va_end(va); + return ret; +} diff --git a/armsrc/nprintf.h b/armsrc/nprintf.h new file mode 100644 index 000000000..5c83384b7 --- /dev/null +++ b/armsrc/nprintf.h @@ -0,0 +1,107 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// 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. +// +// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. +// Use this instead of bloated standard/newlib printf. +// These routines are thread safe and reentrant. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _PRINTF_H_ +#define _PRINTF_H_ + +#include +#include +#include +#include + +/** + * Output a character to a custom device like UART, used by the printf() function + * This function is declared here only. You have to write your custom implementation somewhere + * \param character Character to output + */ +void _putchar(char character); + + +/** + * Tiny printf implementation + * You have to implement _putchar if you use printf() + * To avoid conflicts with the regular printf() API it is overridden by macro defines + * and internal underscore-appended functions like printf_() are used + * \param format A string that specifies the format of the output + * \return The number of characters that are written into the array, not counting the terminating null character + */ +#define printf printf_ +int printf_(const char *format, ...); + + +/** + * Tiny sprintf implementation + * Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD! + * \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output! + * \param format A string that specifies the format of the output + * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character + */ +#define sprintf sprintf_ +int sprintf_(char *buffer, const char *format, ...); + + +/** + * Tiny snprintf/vsnprintf implementation + * \param buffer A pointer to the buffer where to store the formatted string + * \param count The maximum number of characters to store in the buffer, including a terminating null character + * \param format A string that specifies the format of the output + * \param va A value identifying a variable arguments list + * \return The number of characters that COULD have been written into the buffer, not counting the terminating + * null character. A value equal or larger than count indicates truncation. Only when the returned value + * is non-negative and less than count, the string has been completely written. + */ +#define snprintf snprintf_ +#define vsnprintf vsnprintf_ +int snprintf_(char *buffer, size_t count, const char *format, ...); +int vsnprintf_(char *buffer, size_t count, const char *format, va_list va); + + +/** + * Tiny vprintf implementation + * \param format A string that specifies the format of the output + * \param va A value identifying a variable arguments list + * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character + */ +#define vprintf vprintf_ +int vprintf_(const char *format, va_list va); + + +/** + * printf with output function + * You may use this as dynamic alternative to printf() with its fixed _putchar() output + * \param out An output function which takes one character and an argument pointer + * \param arg An argument pointer for user data passed to output function + * \param format A string that specifies the format of the output + * \return The number of characters that are sent to the output function, not counting the terminating null character + */ +int fctprintf(void (*out)(char character, void *arg), void *arg, const char *format, ...); + +#endif // _PRINTF_H_ diff --git a/armsrc/optimized_cipher.c b/armsrc/optimized_cipher.c index 4894bf6bc..0f762a8d6 100644 --- a/armsrc/optimized_cipher.c +++ b/armsrc/optimized_cipher.c @@ -60,11 +60,59 @@ -- MHS 2015 **/ +/** + + The runtime of opt_doTagMAC_2() with the MHS optimized version was 403 microseconds on Proxmark3. + This was still to slow for some newer readers which didn't want to wait that long. + + Further optimizations to speedup the MAC calculations: + * Optimized opt_Tt logic + * Look up table for opt_select + * Removing many unnecessary bit maskings (& 0x1) + * updating state in place instead of alternating use of a second state structure + * remove the necessity to reverse bits of input and output bytes + + opt_doTagMAC_2() now completes in 270 microseconds. + + -- piwi 2019 +**/ + #include "optimized_cipher.h" -#define opt_T(s) (0x1 & ((s->t >> 15) ^ (s->t >> 14)^ (s->t >> 10)^ (s->t >> 8)^ (s->t >> 5)^ (s->t >> 4)^ (s->t >> 1)^ s->t)) +static const uint8_t opt_select_LUT[256] = { + 00, 03, 02, 01, 02, 03, 00, 01, 04, 07, 07, 04, 06, 07, 05, 04, + 01, 02, 03, 00, 02, 03, 00, 01, 05, 06, 06, 05, 06, 07, 05, 04, + 06, 05, 04, 07, 04, 05, 06, 07, 06, 05, 05, 06, 04, 05, 07, 06, + 07, 04, 05, 06, 04, 05, 06, 07, 07, 04, 04, 07, 04, 05, 07, 06, + 06, 05, 04, 07, 04, 05, 06, 07, 02, 01, 01, 02, 00, 01, 03, 02, + 03, 00, 01, 02, 00, 01, 02, 03, 07, 04, 04, 07, 04, 05, 07, 06, + 00, 03, 02, 01, 02, 03, 00, 01, 00, 03, 03, 00, 02, 03, 01, 00, + 05, 06, 07, 04, 06, 07, 04, 05, 05, 06, 06, 05, 06, 07, 05, 04, + 02, 01, 00, 03, 00, 01, 02, 03, 06, 05, 05, 06, 04, 05, 07, 06, + 03, 00, 01, 02, 00, 01, 02, 03, 07, 04, 04, 07, 04, 05, 07, 06, + 02, 01, 00, 03, 00, 01, 02, 03, 02, 01, 01, 02, 00, 01, 03, 02, + 03, 00, 01, 02, 00, 01, 02, 03, 03, 00, 00, 03, 00, 01, 03, 02, + 04, 07, 06, 05, 06, 07, 04, 05, 00, 03, 03, 00, 02, 03, 01, 00, + 01, 02, 03, 00, 02, 03, 00, 01, 05, 06, 06, 05, 06, 07, 05, 04, + 04, 07, 06, 05, 06, 07, 04, 05, 04, 07, 07, 04, 06, 07, 05, 04, + 01, 02, 03, 00, 02, 03, 00, 01, 01, 02, 02, 01, 02, 03, 01, 00 +}; -#define opt_B(s) (((s->b >> 6) ^ (s->b >> 5) ^ (s->b >> 4) ^ (s->b)) & 0x1) +/********************** the table above has been generated with this code: ******** +#include "util.h" +static void init_opt_select_LUT(void) { + for (int r = 0; r < 256; r++) { + uint8_t r_ls2 = r << 2; + uint8_t r_and_ls2 = r & r_ls2; + uint8_t r_or_ls2 = r | r_ls2; + uint8_t z0 = (r_and_ls2 >> 5) ^ ((r & ~r_ls2) >> 4) ^ ( r_or_ls2 >> 3); + uint8_t z1 = (r_or_ls2 >> 6) ^ ( r_or_ls2 >> 1) ^ (r >> 5) ^ r; + uint8_t z2 = ((r & ~r_ls2) >> 4) ^ (r_and_ls2 >> 3) ^ r; + opt_select_LUT[r] = (z0 & 4) | (z1 & 2) | (z2 & 1); + } + print_result("", opt_select_LUT, 256); +} +***********************************************************************************/ #define opt__select(x,y,r) (4 & (((r & (r << 2)) >> 5) ^ ((r & ~(r << 2)) >> 4) ^ ( (r | r << 2) >> 3)))\ |(2 & (((r | r << 2) >> 6) ^ ( (r | r << 2) >> 1) ^ (r >> 5) ^ r ^ ((x^y) << 1)))\ @@ -74,9 +122,6 @@ * Some background on the expression above can be found here... uint8_t xopt__select(bool x, bool y, uint8_t r) { - uint8_t r_ls2 = r << 2; - uint8_t r_and_ls2 = r & r_ls2; - uint8_t r_or_ls2 = r | r_ls2; //r: r0 r1 r2 r3 r4 r5 r6 r7 //r_ls2: r2 r3 r4 r5 r6 r7 0 0 @@ -96,82 +141,95 @@ uint8_t xopt__select(bool x, bool y, uint8_t r) } */ -void opt_successor(const uint8_t *k, State *s, bool y, State *successor) { - uint8_t Tt = 1 & opt_T(s); +static void opt_successor(const uint8_t *k, State *s, uint8_t y) { +// #define opt_T(s) (0x1 & ((s->t >> 15) ^ (s->t >> 14) ^ (s->t >> 10) ^ (s->t >> 8) ^ (s->t >> 5) ^ (s->t >> 4)^ (s->t >> 1) ^ s->t)) + // uint8_t Tt = opt_T(s); + uint16_t Tt = s->t & 0xc533; + Tt = Tt ^ (Tt >> 1); + Tt = Tt ^ (Tt >> 4); + Tt = Tt ^ (Tt >> 10); + Tt = Tt ^ (Tt >> 8); - successor->t = (s->t >> 1); - successor->t |= (Tt ^ (s->r >> 7 & 0x1) ^ (s->r >> 3 & 0x1)) << 15; + s->t = (s->t >> 1); + s->t |= (Tt ^ (s->r >> 7) ^ (s->r >> 3)) << 15; - successor->b = s->b >> 1; - successor->b |= (opt_B(s) ^ (s->r & 0x1)) << 7; + uint8_t opt_B = s->b; + opt_B ^= s->b >> 6; + opt_B ^= s->b >> 5; + opt_B ^= s->b >> 4; - successor->r = (k[opt__select(Tt, y, s->r)] ^ successor->b) + s->l ; - successor->l = successor->r + s->r; + s->b = s->b >> 1; + s->b |= (opt_B ^ s->r) << 7; + + uint8_t opt_select = opt_select_LUT[s->r] & 0x04; + opt_select |= (opt_select_LUT[s->r] ^ ((Tt ^ y) << 1)) & 0x02; + opt_select |= (opt_select_LUT[s->r] ^ Tt) & 0x01; + + uint8_t r = s->r; + s->r = (k[opt_select] ^ s->b) + s->l ; + s->l = s->r + r; } -void opt_suc(const uint8_t *k, State *s, uint8_t *in, uint8_t length, bool add32Zeroes) { - State x2; +static void opt_suc(const uint8_t *k, State *s, uint8_t *in, uint8_t length, bool add32Zeroes) { for (int i = 0; i < length; i++) { uint8_t head; - head = 1 & (in[i] >> 7); - opt_successor(k, s, head, &x2); + head = in[i]; + opt_successor(k, s, head); - head = 1 & (in[i] >> 6); - opt_successor(k, &x2, head, s); + head >>= 1; + opt_successor(k, s, head); - head = 1 & (in[i] >> 5); - opt_successor(k, s, head, &x2); + head >>= 1; + opt_successor(k, s, head); - head = 1 & (in[i] >> 4); - opt_successor(k, &x2, head, s); + head >>= 1; + opt_successor(k, s, head); - head = 1 & (in[i] >> 3); - opt_successor(k, s, head, &x2); + head >>= 1; + opt_successor(k, s, head); - head = 1 & (in[i] >> 2); - opt_successor(k, &x2, head, s); + head >>= 1; + opt_successor(k, s, head); - head = 1 & (in[i] >> 1); - opt_successor(k, s, head, &x2); + head >>= 1; + opt_successor(k, s, head); - head = 1 & in[i]; - opt_successor(k, &x2, head, s); + head >>= 1; + opt_successor(k, s, head); } - //For tag MAC, an additional 32 zeroes if (add32Zeroes) { for (int i = 0; i < 16; i++) { - opt_successor(k, s, 0, &x2); - opt_successor(k, &x2, 0, s); + opt_successor(k, s, 0); + opt_successor(k, s, 0); } } } -void opt_output(const uint8_t *k, State *s, uint8_t *buffer) { - State temp = {0, 0, 0, 0}; +static void opt_output(const uint8_t *k, State *s, uint8_t *buffer) { for (uint8_t times = 0; times < 4; times++) { uint8_t bout = 0; - bout |= (s->r & 0x4) << 5; - opt_successor(k, s, 0, &temp); - bout |= (temp.r & 0x4) << 4; - opt_successor(k, &temp, 0, s); - bout |= (s->r & 0x4) << 3; - opt_successor(k, s, 0, &temp); - bout |= (temp.r & 0x4) << 2; - opt_successor(k, &temp, 0, s); - bout |= (s->r & 0x4) << 1; - opt_successor(k, s, 0, &temp); - bout |= (temp.r & 0x4) ; - opt_successor(k, &temp, 0, s); + bout |= (s->r & 0x4) >> 2; + opt_successor(k, s, 0); bout |= (s->r & 0x4) >> 1; - opt_successor(k, s, 0, &temp); - bout |= (temp.r & 0x4) >> 2; - opt_successor(k, &temp, 0, s); + opt_successor(k, s, 0); + bout |= (s->r & 0x4); + opt_successor(k, s, 0); + bout |= (s->r & 0x4) << 1; + opt_successor(k, s, 0); + bout |= (s->r & 0x4) << 2; + opt_successor(k, s, 0); + bout |= (s->r & 0x4) << 3; + opt_successor(k, s, 0); + bout |= (s->r & 0x4) << 4; + opt_successor(k, s, 0); + bout |= (s->r & 0x4) << 5; + opt_successor(k, s, 0); buffer[times] = bout; } } -void opt_MAC(uint8_t *k, uint8_t *input, uint8_t *out) { +static void opt_MAC(uint8_t *k, uint8_t *input, uint8_t *out) { State _init = { ((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l ((k[0] ^ 0x4c) + 0x21) & 0xFF,// r @@ -183,45 +241,25 @@ void opt_MAC(uint8_t *k, uint8_t *input, uint8_t *out) { opt_output(k, &_init, out); } -uint8_t rev_byte(uint8_t b) { - b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; - b = (b & 0xCC) >> 2 | (b & 0x33) << 2; - b = (b & 0xAA) >> 1 | (b & 0x55) << 1; - return b; -} - -void opt_reverse_arraybytecpy(uint8_t *dest, uint8_t *src, size_t len) { - uint8_t i; - for (i = 0; i < len ; i++) - dest[i] = rev_byte(src[i]); -} - void opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) { - static uint8_t cc_nr[12]; - opt_reverse_arraybytecpy(cc_nr, cc_nr_p, 12); uint8_t dest [] = {0, 0, 0, 0, 0, 0, 0, 0}; - opt_MAC(div_key_p, cc_nr, dest); - //The output MAC must also be reversed - opt_reverse_arraybytecpy(mac, dest, 4); + opt_MAC(div_key_p, cc_nr_p, dest); + memcpy(mac, dest, 4); return; } + void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) { - static uint8_t cc_nr[8 + 4 + 4]; - opt_reverse_arraybytecpy(cc_nr, cc_p, 12); State _init = { ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r 0x4c, // b 0xE012 // t }; - opt_suc(div_key_p, &_init, cc_nr, 12, true); - uint8_t dest [] = {0, 0, 0, 0}; - opt_output(div_key_p, &_init, dest); - //The output MAC must also be reversed - opt_reverse_arraybytecpy(mac, dest, 4); + opt_suc(div_key_p, &_init, cc_p, 12, true); + opt_output(div_key_p, &_init, mac); return; - } + /** * The tag MAC can be divided (both can, but no point in dividing the reader mac) into * two functions, since the first 8 bytes are known, we can pre-calculate the state @@ -231,17 +269,16 @@ void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) { * @return the cipher state */ State opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p) { - static uint8_t cc_nr[8]; - opt_reverse_arraybytecpy(cc_nr, cc_p, 8); State _init = { ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r 0x4c, // b 0xE012 // t }; - opt_suc(div_key_p, &_init, cc_nr, 8, false); + opt_suc(div_key_p, &_init, cc_p, 8, false); return _init; } + /** * The second part of the tag MAC calculation, since the CC is already calculated into the state, * this function is fed only the NR, and internally feeds the remaining 32 0-bits to generate the tag @@ -252,13 +289,7 @@ State opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p) { * @param div_key_p - the key to use */ void opt_doTagMAC_2(State _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p) { - static uint8_t _nr[4]; - opt_reverse_arraybytecpy(_nr, nr, 4); - opt_suc(div_key_p, &_init, _nr, 4, true); - - uint8_t dest [] = {0, 0, 0, 0}; - opt_output(div_key_p, &_init, dest); - //The output MAC must also be reversed - opt_reverse_arraybytecpy(mac, dest, 4); + opt_suc(div_key_p, &_init, nr, 4, true); + opt_output(div_key_p, &_init, mac); return; } diff --git a/armsrc/optimized_cipher.h b/armsrc/optimized_cipher.h index 9bf0516de..c6df25ab8 100644 --- a/armsrc/optimized_cipher.h +++ b/armsrc/optimized_cipher.h @@ -1,10 +1,8 @@ #ifndef OPTIMIZED_CIPHER_H #define OPTIMIZED_CIPHER_H -#include -#include -#include - +#include "common.h" +#include "string.h" /** * Definition 1 (Cipher state). A cipher state of iClass s is an element of F 40/2 * consisting of the following four components: diff --git a/armsrc/pcf7931.c b/armsrc/pcf7931.c index 942569a9c..1690c6ad3 100644 --- a/armsrc/pcf7931.c +++ b/armsrc/pcf7931.c @@ -1,5 +1,15 @@ #include "pcf7931.h" +#include "proxmark3_arm.h" +#include "cmd.h" +#include "BigBuf.h" +#include "fpgaloader.h" +#include "ticks.h" +#include "dbprint.h" +#include "util.h" +#include "lfsampling.h" +#include "string.h" + #define T0_PCF 8 //period for the pcf7931 in us #define ALLOC 16 @@ -84,7 +94,10 @@ size_t DemodPCF7931(uint8_t **outBlocks) { } else { // Error if (++warnings > 10) { - Dbprintf("Error: too many detection errors, aborting."); + + if ( DBGLEVEL >= DBG_EXTENDED ) + Dbprintf("Error: too many detection errors, aborting."); + return 0; } } @@ -125,27 +138,38 @@ bool IsBlock0PCF7931(uint8_t *block) { // assuming all RFU bits are set to 0 // if PAC is enabled password is set to 0 if (block[7] == 0x01) { - if (!memcmp(block, "\x00\x00\x00\x00\x00\x00\x00", 7) && !memcmp(block + 9, "\x00\x00\x00\x00\x00\x00\x00", 7)) + if (!memcmp(block, "\x00\x00\x00\x00\x00\x00\x00", 7) + && !memcmp(block + 9, "\x00\x00\x00\x00\x00\x00\x00", 7)) { return true; + } } else if (block[7] == 0x00) { - if (!memcmp(block + 9, "\x00\x00\x00\x00\x00\x00\x00", 7)) + if (!memcmp(block + 9, "\x00\x00\x00\x00\x00\x00\x00", 7)) { return true; + } } return false; } bool IsBlock1PCF7931(uint8_t *block) { // assuming all RFU bits are set to 0 - if (block[10] == 0 - && block[11] == 0 - && block[12] == 0 - && block[13] == 0) { - if ((block[14] & 0x7f) <= 9 - && block[15] <= 9) { + uint8_t rb1 = block[14] & 0x80; + uint8_t rfb = block[14] & 0x7f; + uint8_t rlb = block[15]; + + if (block[10] == 0 + && block[11] == 0 + && block[12] == 0 + && block[13] == 0) { + // block 1 is sent only if (RLB >= 1 && RFB <= 1) or RB1 enabled + if (rfb <= rlb + && rfb <= 9 + && rlb <= 9 + && ((rfb <= 1 && rlb >= 1) || rb1)) { return true; } } + return false; } @@ -178,21 +202,28 @@ void ReadPCF7931() { // exit if no block is received if (errors >= 10 && found_blocks == 0 && single_blocks_cnt == 0) { - Dbprintf("Error, no tag or bad tag"); + + if ( DBGLEVEL >= DBG_INFO ) + Dbprintf("[!!] Error, no tag or bad tag"); + return; } // exit if too many errors during reading if (tries > 50 && (2 * errors > tries)) { - Dbprintf("Error reading the tag"); - Dbprintf("Here is the partial content"); + + if ( DBGLEVEL >= DBG_INFO ) + Dbprintf("[!!] Error reading the tag, only partial content"); + goto end; } // our logic breaks if we don't get at least two blocks if (n < 2) { + // skip if all 0s block or no blocks if (n == 0 || !memcmp(tmp_blocks[0], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) continue; + // add block to single blocks list if (single_blocks_cnt < max_blocks) { for (i = 0; i < single_blocks_cnt; ++i) { if (!memcmp(single_blocks[i], tmp_blocks[0], 16)) { @@ -202,6 +233,7 @@ void ReadPCF7931() { } if (j != 1) { memcpy(single_blocks[single_blocks_cnt], tmp_blocks[0], 16); + print_result("got single block", single_blocks[single_blocks_cnt], 16); single_blocks_cnt++; } j = 0; @@ -210,7 +242,12 @@ void ReadPCF7931() { continue; } - Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n, found_blocks, (max_blocks == 0 ? found_blocks : max_blocks), tries, errors); + if ( DBGLEVEL >= DBG_EXTENDED ) + Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n, found_blocks, (max_blocks == 0 ? found_blocks : max_blocks), tries, errors); + + for (i = 0; i < n; ++i) { + print_result("got consecutive blocks", tmp_blocks[i], 16); + } i = 0; if (!found_0_1) { @@ -269,10 +306,12 @@ void ReadPCF7931() { } ++tries; if (BUTTON_PRESS()) { - Dbprintf("Button pressed, stopping."); + if ( DBGLEVEL >= DBG_EXTENDED) + Dbprintf("Button pressed, stopping."); + goto end; } - } while (found_blocks != max_blocks); + } while (found_blocks < max_blocks); end: Dbprintf("-----------------------------------------"); @@ -295,7 +334,7 @@ end: Dbprintf("-----------------------------------------"); } - reply_old(CMD_ACK, 0, 0, 0, 0, 0); + reply_mix(CMD_ACK, 0, 0, 0, 0, 0); } static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) { @@ -381,8 +420,12 @@ static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int3 @param data : data to write */ void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) { - Dbprintf("Initialization delay : %d us", init_delay); - Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p); + + if ( DBGLEVEL >= DBG_INFO ) { + Dbprintf("Initialization delay : %d us", init_delay); + Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p); + } + Dbprintf("Password (LSB first on each byte): %02x %02x %02x %02x %02x %02x %02x", pass1, pass2, pass3, pass4, pass5, pass6, pass7); Dbprintf("Block address : %02x", address); Dbprintf("Byte address : %02x", byte); @@ -401,10 +444,12 @@ void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, ui void SendCmdPCF7931(uint32_t *tab) { uint16_t u = 0, tempo = 0; - Dbprintf("Sending data frame..."); - + if ( DBGLEVEL >= DBG_INFO ) { + Dbprintf("Sending data frame..."); + } + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU); LED_A_ON(); @@ -444,7 +489,6 @@ void SendCmdPCF7931(uint32_t *tab) { SpinDelay(200); AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable - LED(0xFFFF, 1000); } @@ -458,13 +502,13 @@ bool AddBytePCF7931(uint8_t byte, uint32_t *tab, int32_t l, int32_t p) { uint32_t u; for (u = 0; u < 8; ++u) { if (byte & (1 << u)) { //bit is 1 - if (AddBitPCF7931(1, tab, l, p) == 1) return 1; + if (AddBitPCF7931(1, tab, l, p) == 1) return true; } else { //bit is 0 - if (AddBitPCF7931(0, tab, l, p) == 1) return 1; + if (AddBitPCF7931(0, tab, l, p) == 1) return true; } } - return 0; + return false; } /* Add a bits for building the data frame of PCF7931 tags @@ -477,7 +521,7 @@ bool AddBitPCF7931(bool b, uint32_t *tab, int32_t l, int32_t p) { uint8_t u = 0; //we put the cursor at the last value of the array - for (u = 0; tab[u] != 0; u += 3) { } + for (u = 0; tab[u] != 0; u += 3) { }; if (b == 1) { //add a bit 1 if (u == 0) @@ -487,7 +531,7 @@ bool AddBitPCF7931(bool b, uint32_t *tab, int32_t l, int32_t p) { tab[u + 1] = 6 * T0_PCF + tab[u] + l; tab[u + 2] = 88 * T0_PCF + tab[u + 1] - l - p; - return 0; + return false; } else { //add a bit 0 if (u == 0) @@ -497,9 +541,9 @@ bool AddBitPCF7931(bool b, uint32_t *tab, int32_t l, int32_t p) { tab[u + 1] = 6 * T0_PCF + tab[u] + l; tab[u + 2] = 24 * T0_PCF + tab[u + 1] - l - p; - return 0; + return false; } - return 1; + return true; } /* Add a custom pattern in the data frame @@ -516,5 +560,5 @@ bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t *tab) { tab[u + 1] = b + tab[u]; tab[u + 2] = c + tab[u + 1]; - return 0; + return true; } diff --git a/armsrc/pcf7931.h b/armsrc/pcf7931.h index 5e3c5a8e4..67a11f5f8 100644 --- a/armsrc/pcf7931.h +++ b/armsrc/pcf7931.h @@ -1,11 +1,7 @@ #ifndef __PCF7931_H #define __PCF7931_H -#include "proxmark3.h" -#include "apps.h" -#include "lfsampling.h" -#include "pcf7931.h" -#include "string.h" +#include "common.h" size_t DemodPCF7931(uint8_t **outBlocks); bool IsBlock0PCF7931(uint8_t *block); diff --git a/armsrc/printf.c b/armsrc/printf.c index d0d873e7d..0dffbb037 100644 --- a/armsrc/printf.c +++ b/armsrc/printf.c @@ -35,6 +35,8 @@ */ #include "printf.h" +#include "string.h" + typedef unsigned char u_char; typedef unsigned int u_int; typedef unsigned long long u_quad_t; diff --git a/armsrc/printf.h b/armsrc/printf.h index ff0143790..bd0a6e2c9 100644 --- a/armsrc/printf.h +++ b/armsrc/printf.h @@ -11,9 +11,8 @@ #ifndef __PRINTF_H #define __PRINTF_H -#include -#include -#include "string.h" +#include "common.h" +#include // va_list int kvsprintf(const char *fmt, void *arg, int radix, va_list ap) __attribute__((format(printf, 1, 0))); int vsprintf(char *dest, const char *fmt, va_list ap) __attribute__((format(printf, 2, 0))); diff --git a/common/radixsort.c b/armsrc/radixsort.c similarity index 100% rename from common/radixsort.c rename to armsrc/radixsort.c diff --git a/common/radixsort.h b/armsrc/radixsort.h similarity index 87% rename from common/radixsort.h rename to armsrc/radixsort.h index 41a036461..fb2bcc044 100644 --- a/common/radixsort.h +++ b/armsrc/radixsort.h @@ -1,9 +1,7 @@ #ifndef RADIXSORT_H__ #define RADIXSORT_H__ -#include -#include -#include +#include "common.h" typedef union { struct { @@ -20,4 +18,5 @@ typedef union { } rscounts_t; uint64_t *radixSort(uint64_t *array, uint32_t size); + #endif // RADIXSORT_H__ diff --git a/armsrc/spiffs.c b/armsrc/spiffs.c index 7fd712e7f..0296b7620 100644 --- a/armsrc/spiffs.c +++ b/armsrc/spiffs.c @@ -22,9 +22,11 @@ // case, will ensure a flush by rollbacking to previous Unmounted state #define RDV40_SPIFFS_CACHE_SZ ((LOG_PAGE_SIZE + 32) * 4) #define SPIFFS_FD_SIZE (32) -#define RDV40_SPIFFS_MAX_FD (2) +#define RDV40_SPIFFS_MAX_FD (3) #define RDV40_SPIFFS_FDBUF_SZ (SPIFFS_FD_SIZE * RDV40_SPIFFS_MAX_FD) +#define RDV40_LLERASE_BLOCKSIZE (64*1024) + #define RDV40_SPIFFS_LAZY_HEADER \ int changed = 0; \ if ((level == RDV40_SPIFFS_SAFETY_LAZY) || (level == RDV40_SPIFFS_SAFETY_SAFE)) { \ @@ -43,6 +45,8 @@ RDV40_SPIFFS_SAFE_FOOTER #include "spiffs.h" +#include "BigBuf.h" +#include "dbprint.h" ///// FLASH LEVEL R/W/E operations for feeding SPIFFS Driver///////////////// static s32_t rdv40_spiffs_llread(u32_t addr, u32_t size, u8_t *dst) { @@ -64,36 +68,37 @@ static s32_t rdv40_spiffs_llwrite(u32_t addr, u32_t size, u8_t *src) { static s32_t rdv40_spiffs_llerase(u32_t addr, u32_t size) { + + uint8_t erased = 0; + if (!FlashInit()) { return 130; } - - uint32_t bytes_erased = 0, bytes_remaining = size; - while (bytes_remaining > 0) { - - addr += bytes_erased; - Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); - FlashSendByte(SECTORERASE); - Flash_TransferAdresse(addr); - FlashSendLastByte(0); - - bytes_remaining -= 4096; - bytes_erased += 4096; + if (DBGLEVEL > 2) Dbprintf("LLERASEDBG : Orig addr : %d\n", addr); + uint8_t block, sector = 0; + block = addr / RDV40_LLERASE_BLOCKSIZE; + if (block) { + addr = addr - (block * RDV40_LLERASE_BLOCKSIZE); } + if (DBGLEVEL > 2) Dbprintf("LLERASEDBG : Result addr : %d\n", addr); + sector = addr / SPIFFS_CFG_LOG_BLOCK_SZ; + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); + if (DBGLEVEL > 2) Dbprintf("LLERASEDBG : block : %d, sector : %d \n", block, sector); + erased = Flash_Erase4k(block, sector); Flash_CheckBusy(BUSY_TIMEOUT); FlashStop(); - return SPIFFS_OK; + return SPIFFS_OK == erased ; } //////////////////////////////////////////////////////////////////////////////// ////// SPIFFS LOW LEVEL OPERATIONS ///////////////////////////////////////////// -static u8_t spiffs_work_buf[RDV40_SPIFFS_WORKBUF_SZ]; -static u8_t spiffs_fds[RDV40_SPIFFS_FDBUF_SZ]; -static u8_t spiffs_cache_buf[RDV40_SPIFFS_CACHE_SZ]; +static u8_t spiffs_work_buf[RDV40_SPIFFS_WORKBUF_SZ] __attribute__((aligned)); +static u8_t spiffs_fds[RDV40_SPIFFS_FDBUF_SZ] __attribute__((aligned)); +static u8_t spiffs_cache_buf[RDV40_SPIFFS_CACHE_SZ] __attribute__((aligned)); static spiffs fs; @@ -156,6 +161,15 @@ int rdv40_spiffs_unmount() { } return ret; } + +int rdv40_spiffs_check() { + rdv40_spiffs_lazy_mount(); + SPIFFS_check(&fs); + SPIFFS_gc_quick(&fs, 0); + rdv40_spiffs_lazy_unmount(); + rdv40_spiffs_lazy_mount(); + return SPIFFS_gc(&fs, 8192) == SPIFFS_OK; +} //////////////////////////////////////////////////////////////////////////////// ///// Base RDV40_SPIFFS_SAFETY_NORMAL operations//////////////////////////////// diff --git a/armsrc/spiffs.h b/armsrc/spiffs.h index f36bde4b0..d75335e40 100644 --- a/armsrc/spiffs.h +++ b/armsrc/spiffs.h @@ -33,7 +33,7 @@ typedef struct rdv40_spiffs_fsinfo { int rdv40_spiffs_read_as_filetype(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level); - +int rdv40_spiffs_check(); int rdv40_spiffs_lazy_unmount(); int rdv40_spiffs_lazy_mount(); int rdv40_spiffs_lazy_mount_rollback(int changed); diff --git a/armsrc/spiffs_cache.c b/armsrc/spiffs_cache.c index f86133be4..98acc4c2f 100644 --- a/armsrc/spiffs_cache.c +++ b/armsrc/spiffs_cache.c @@ -39,17 +39,17 @@ static s32_t spiffs_cache_page_free(spiffs *fs, int ix, u8_t write_back) { (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 && (cp->flags & SPIFFS_CACHE_FLAG_DIRTY)) { u8_t *mem = spiffs_get_cache_page(fs, cache, ix); - SPIFFS_CACHE_DBG("CACHE_FREE: write cache page "_SPIPRIi" pix "_SPIPRIpg"\n", ix, cp->pix); + SPIFFS_CACHE_DBG("CACHE_FREE: write cache page "_SPIPRIi" pix "_SPIPRIpg"\n", ix, cp->ucache.spix.pix); res = SPIFFS_HAL_WRITE(fs, SPIFFS_PAGE_TO_PADDR(fs, cp->ucache.spix.pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), mem); } #if SPIFFS_CACHE_WR if (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) { - SPIFFS_CACHE_DBG("CACHE_FREE: free cache page "_SPIPRIi" objid "_SPIPRIid"\n", ix, cp->obj_id); + SPIFFS_CACHE_DBG("CACHE_FREE: free cache page "_SPIPRIi" objid "_SPIPRIid"\n", ix, cp->ucache.swrc.obj_id); } else #endif { - SPIFFS_CACHE_DBG("CACHE_FREE: free cache page "_SPIPRIi" pix "_SPIPRIpg"\n", ix, cp->pix); + SPIFFS_CACHE_DBG("CACHE_FREE: free cache page "_SPIPRIi" pix "_SPIPRIpg"\n", ix, cp->ucache.spix.pix); } cache->cpage_use_map &= ~(1 << ix); cp->flags = 0; @@ -156,7 +156,7 @@ s32_t spiffs_phys_rd( if (cp) { cp->flags = SPIFFS_CACHE_FLAG_WRTHRU; cp->ucache.spix.pix = SPIFFS_PADDR_TO_PAGE(fs, addr); - SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page "_SPIPRIi" for pix "_SPIPRIpg "\n", cp->ix, cp->pix); + SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page "_SPIPRIi" for pix "_SPIPRIpg "\n", cp->ix, cp->ucache.spix.pix); s32_t res2 = SPIFFS_HAL_READ(fs, addr - SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr), diff --git a/armsrc/spiffs_config.h b/armsrc/spiffs_config.h index 99557f41f..7710a65a8 100644 --- a/armsrc/spiffs_config.h +++ b/armsrc/spiffs_config.h @@ -41,7 +41,7 @@ typedef uint8_t u8_t; #endif // Set spiffs debug output call for garbage collecting. #ifndef SPIFFS_GC_DBG -#define SPIFFS_GC_DBG(_f, ...) +#define SPIFFS_GC_DBG(_f, ...) //Dbprintf(_f, ## __VA_ARGS__) #define SPIFFS_GC_DBGF(str) SPIFFS_GC_DBG(str,NULL) #endif // Set spiffs debug output call for caching. @@ -51,7 +51,7 @@ typedef uint8_t u8_t; #endif // Set spiffs debug output call for system consistency checks. #ifndef SPIFFS_CHECK_DBG -#define SPIFFS_CHECK_DBG(_f, ...) //SPIFFS_CHECK_DBG(_f, ## __VA_ARGS__) +#define SPIFFS_CHECK_DBG(_f, ...) //Dbprintf(_f, ## __VA_ARGS__) #define SPIFFS_CHECK_DBGF(str) SPIFFS_CHECK_DBG(str,NULL) #endif // Set spiffs debug output call for all api invocations. diff --git a/armsrc/spiffs_nucleus.c b/armsrc/spiffs_nucleus.c index 7951a7952..8dd4b5629 100644 --- a/armsrc/spiffs_nucleus.c +++ b/armsrc/spiffs_nucleus.c @@ -2033,7 +2033,7 @@ s32_t spiffs_object_read( len_to_read = MIN(len_to_read, fd->size - cur_offset); SPIFFS_DBG("read: offset:"_SPIPRIi" rd:"_SPIPRIi" data spix:"_SPIPRIsp" is data_pix:"_SPIPRIpg" addr:"_SPIPRIad"\n", cur_offset, len_to_read, data_spix, data_pix, (u32_t)(SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header) + (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs)))); - if (len_to_read <= 0) { + if (len_to_read == 0) { res = SPIFFS_ERR_END_OF_OBJECT; break; } diff --git a/armsrc/spiffs_nucleus.h b/armsrc/spiffs_nucleus.h index c4a360384..c437faf30 100644 --- a/armsrc/spiffs_nucleus.h +++ b/armsrc/spiffs_nucleus.h @@ -110,6 +110,11 @@ #ifndef SPIFFS_NUCLEUS_H_ #define SPIFFS_NUCLEUS_H_ +#include "common.h" + +#include "string.h" +#include "spiffs.h" + #define _SPIFFS_ERR_CHECK_FIRST (SPIFFS_ERR_INTERNAL - 1) #define SPIFFS_ERR_CHECK_OBJ_ID_MISM (SPIFFS_ERR_INTERNAL - 1) #define SPIFFS_ERR_CHECK_SPIX_MISM (SPIFFS_ERR_INTERNAL - 2) diff --git a/armsrc/start.c b/armsrc/start.c index 94eb429ac..3e6f34702 100644 --- a/armsrc/start.c +++ b/armsrc/start.c @@ -12,8 +12,8 @@ #ifndef __START_H #define __START_H -#include "proxmark3.h" -#include "apps.h" +#include "proxmark3_arm.h" +#include "appmain.h" #include "zlib.h" #include "BigBuf.h" diff --git a/armsrc/string.c b/armsrc/string.c index ea113680e..4caa027a2 100644 --- a/armsrc/string.c +++ b/armsrc/string.c @@ -195,3 +195,141 @@ char *strtok(char *s, const char *delim) { return (__strtok_r(s, delim, &last)); } + + +char *strchr(const char *s, int c) { + while (*s != (char)c) + if (!*s++) + return 0; + return (char *)s; +} + +size_t strspn(const char *s1, const char *s2) { + size_t ret = 0; + while (*s1 && strchr(s2, *s1++)) + ret++; + return ret; +} + +char *strrchr(const char *s, int c) { + const char *ret = 0; + do { + if (*s == (char)c) + ret = s; + } while (*s++); + return (char *)ret; +} + +size_t strcspn(const char *s1, const char *s2) { + size_t ret = 0; + while (*s1) + if (strchr(s2, *s1)) + return ret; + else + s1++, ret++; + return ret; +} + +char *strpbrk(const char *s1, const char *s2) { + while (*s1) + if (strchr(s2, *s1++)) + return (char *)--s1; + return 0; +} + +int strncmp(const char *s1, const char *s2, size_t n) { + while (n--) + if (*s1++ != *s2++) + return *(unsigned char *)(s1 - 1) - *(unsigned char *)(s2 - 1); + return 0; +} + + + + +#define isspace(a) __extension__ ({ unsigned char bb__isspace = (a) - 9; bb__isspace == (' ' - 9) || bb__isspace <= (13 - 9); }) + +unsigned long strtoul(const char *p, char **out_p, int base) { + unsigned long v = 0; + + while (isspace(*p)) + p++; + if (((base == 16) || (base == 0)) && + ((*p == '0') && ((p[1] == 'x') || (p[1] == 'X')))) { + p += 2; + base = 16; + } + if (base == 0) { + if (*p == '0') + base = 8; + else + base = 10; + } + while (1) { + char c = *p; + if ((c >= '0') && (c <= '9') && (c - '0' < base)) + v = (v * base) + (c - '0'); + else if ((c >= 'a') && (c <= 'z') && (c - 'a' + 10 < base)) + v = (v * base) + (c - 'a' + 10); + else if ((c >= 'A') && (c <= 'Z') && (c - 'A' + 10 < base)) + v = (v * base) + (c - 'A' + 10); + else + break; + p++; + } + + if (out_p) *out_p = (char *)p; + return v; +} + +long strtol(const char *p, char **out_p, int base) { + long v = 0; + int is_neg = 0; + + while (isspace(*p)) + p++; + if (*p == '-') + is_neg = 1, p++; + else if (*p == '+') + is_neg = 0; + if (((base == 16) || (base == 0)) && + ((*p == '0') && ((p[1] == 'x') || (p[1] == 'X')))) { + p += 2; + base = 16; + } + if (base == 0) { + if (*p == '0') + base = 8; + else + base = 10; + } + while (1) { + char c = *p; + if ((c >= '0') && (c <= '9') && (c - '0' < base)) + v = (v * base) + (c - '0'); + else if ((c >= 'a') && (c <= 'z') && (c - 'a' + 10 < base)) + v = (v * base) + (c - 'a' + 10); + else if ((c >= 'A') && (c <= 'Z') && (c - 'A' + 10 < base)) + v = (v * base) + (c - 'A' + 10); + else + break; + p++; + } + if (is_neg) + v = -v; + if (out_p) *out_p = (char *)p; + return v; +} + +char c_tolower(int c) { + // (int)a = 97, (int)A = 65 + // (a)97 - (A)65 = 32 + // therefore 32 + 65 = a + return c > 64 && c < 91 ? c + 32 : c; +} + +char c_isprint(unsigned char c) { + if (c >= 0x20 && c <= 0x7e) + return 1; + return 0; +} diff --git a/armsrc/string.h b/armsrc/string.h index c30293a2a..781641fb9 100644 --- a/armsrc/string.h +++ b/armsrc/string.h @@ -12,7 +12,7 @@ #ifndef __STRING_H #define __STRING_H -#include +#include "common.h" int strlen(const char *str); void *memcpy(void *dest, const void *src, int len); @@ -27,5 +27,13 @@ char *strcpy(char *dst, const char *src); char *strncpy(char *destination, const char *source, size_t num); int strcmp(const char *s1, const char *s2); char *strtok(char *s, const char *delim); +char *strchr(const char *s, int c); +size_t strspn(const char *s1, const char *s2); +char *strrchr(const char *s, int c); +size_t strcspn(const char *s1, const char *s2); +char *strpbrk(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, size_t n); +char c_tolower(int c); +char c_isprint(unsigned char c); #endif /* __STRING_H */ diff --git a/armsrc/thinfilm.c b/armsrc/thinfilm.c new file mode 100644 index 000000000..bd8e696fb --- /dev/null +++ b/armsrc/thinfilm.c @@ -0,0 +1,162 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2019 iceman +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Routines to support a mangeled ISO 14443 type A for Thinfilm tags by Kovio +//----------------------------------------------------------------------------- + +#include "thinfilm.h" + +#include "proxmark3_arm.h" +#include "cmd.h" +#include "appmain.h" +#include "BigBuf.h" +#include "iso14443a.h" +#include "fpgaloader.h" +#include "ticks.h" +#include "dbprint.h" +#include "util.h" + +/** + * ref + * https://www.thinfilmnfc.com/wp-content/uploads/2017/09/Thinfilm-Kovio-NFC-Barcode-Protocol-Tag-Functional-Specification-v3.4-2017-05-26.pdf + * https://developer.android.com/reference/android/nfc/tech/NfcBarcode + * + */ + +void ReadThinFilm(void) { + + clear_trace(); + + set_tracing(true); + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + uint8_t len = 0; + uint8_t buf[36] = {0x00}; + + // power on and listen for answer. + bool status = GetIso14443aAnswerFromTag_Thinfilm(buf, &len); + reply_ng(CMD_HF_THINFILM_READ, status ? PM3_SUCCESS : PM3_ENODATA, buf, len); + + hf_field_off(); + set_tracing(false); +} + +#define SEC_D 0xf0 +#define SEC_E 0x0f +#define SEC_F 0x00 +uint16_t FpgaSendQueueDelay; + +uint16_t ReadReaderField(void) { + uint16_t hf_av = AvgAdc(ADC_CHAN_HF); + if (((MAX_ADC_HF_VOLTAGE * hf_av) >> 10) > MAX_ADC_HF_VOLTAGE - 300) + hf_av = AvgAdc(ADC_CHAN_HF_RDV40); + return hf_av; +} + +static void CodeThinfilmAsTag(const uint8_t *cmd, uint16_t len) { + ToSendReset(); + for (uint16_t i = 0; i < len; i++) { + uint8_t b = cmd[i]; + for (uint8_t j = 0; j < 8; j++) { + ToSend[++ToSendMax] = b & 0x80 ? SEC_D : SEC_E; + b <<= 1; + } + } + ToSendMax++; +} + +int EmSendCmdThinfilmRaw(uint8_t *resp, uint16_t respLen) { + volatile uint8_t b; + uint16_t i = 0; + uint32_t ThisTransferTime; + // wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line) + for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never + while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)); + if (AT91C_BASE_SSC->SSC_RHR) break; + } + while ((ThisTransferTime = GetCountSspClk()) & 0x00000007); + + + // Clear TXRDY: + AT91C_BASE_SSC->SSC_THR = SEC_F; + + // send cycle + for (; i < respLen;) { + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = resp[i++]; + FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + } + + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); + (void)b; + } + if (BUTTON_PRESS()) break; + } + + // Ensure that the FPGA Delay Queue is empty + uint8_t fpga_queued_bits = FpgaSendQueueDelay >> 3; + for (i = 0; i <= fpga_queued_bits / 8 + 1;) { + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = SEC_F; + FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + i++; + } + } + + return 0; +} + +void SimulateThinFilm(uint8_t *data, size_t len) { + Dbprintf("Simulate %i-bit Thinfilm tag", len * 8); + Dbhexdump(len, data, true); + int16_t status = PM3_SUCCESS; + CodeThinfilmAsTag(data, len); + + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + // Set up the synchronous serial port + FpgaSetupSsc(); + // connect Demodulated Signal to ADC: + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD); + SpinDelay(100); + uint16_t hf_baseline = ReadReaderField(); + + // Start the timer + StartCountSspClk(); + + bool reader_detected = false; + LED_A_ON(); + for (;;) { + WDT_HIT(); + if (BUTTON_PRESS() || data_available()) { + status = PM3_EOPABORTED; + break; + } + uint16_t hf_av = ReadReaderField(); + if (hf_av < hf_baseline) + hf_baseline = hf_av; + if (hf_av > hf_baseline + 10) { + EmSendCmdThinfilmRaw(ToSend, ToSendMax); + if (!reader_detected) { + LED_B_ON(); + //Dbprintf("Reader detected, start beaming data"); + reader_detected = true; + } + } else { + if (reader_detected) { + LED_B_OFF(); + //Dbprintf("Reader gone, stop beaming data"); + reader_detected = false; + } + } + } + LED_A_OFF(); + reply_ng(CMD_HF_THINFILM_SIMULATE, status, NULL, 0); +} diff --git a/armsrc/Standalone/hf_young.h b/armsrc/thinfilm.h similarity index 60% rename from armsrc/Standalone/hf_young.h rename to armsrc/thinfilm.h index dcd8b13e7..af1564482 100644 --- a/armsrc/Standalone/hf_young.h +++ b/armsrc/thinfilm.h @@ -1,22 +1,19 @@ //----------------------------------------------------------------------------- -// Craig Young 2014 -// Christian Herrmann, 2017 +// Iceman - August 2019 // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// StandAlone Mod +// Routines to support a mangeled ISO 14443 type A for Thinfilm tags by Kovio //----------------------------------------------------------------------------- -#ifndef __HF_YOUNG_H -#define __HF_YOUNG_H +#ifndef __THINFILM_H +#define __THINFILM_H -#include // for bool -#include "standalone.h" // standalone definitions -#include "iso14443a.h" -#include "protocols.h" +#include "common.h" -#define OPTS 2 +void ReadThinFilm(void); +void SimulateThinFilm(uint8_t *data, size_t len); -#endif /* __HF_YOUNG_H */ +#endif /* __ISO14443A_H */ diff --git a/armsrc/ticks.c b/armsrc/ticks.c index 7ece25b93..1510de490 100644 --- a/armsrc/ticks.c +++ b/armsrc/ticks.c @@ -9,10 +9,14 @@ // Timers, Clocks functions used in LF or Legic where you would need detailed time. //----------------------------------------------------------------------------- #include "ticks.h" -// attempt at high resolution microsecond timer -// beware: timer counts in 21.3uS increments (1024/48Mhz) + +#include "proxmark3_arm.h" +#include "dbprint.h" + +// timer counts in 21.3us increments (1024/48MHz), rounding applies +// WARNING: timer can't measure more than 1.39s (21.3us * 0xffff) void SpinDelayUs(int us) { - int ticks = (48 * us) >> 10; + int ticks = ((MCK / 1000000) * us + 512) >> 10; // Borrow a PWM unit for my real-time clock AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0); @@ -33,8 +37,13 @@ void SpinDelayUs(int us) { } } +// WARNING: timer can't measure more than 1.39s (21.3us * 0xffff) void SpinDelay(int ms) { - // convert to uS and call microsecond delay function + if (ms > 1390) { + if (DBGLEVEL >= DBG_ERROR) Dbprintf(_RED_("Error, SpinDelay called with %i > 1390"), ms); + ms = 1390; + } + // convert to us and call microsecond delay function SpinDelayUs(ms * 1000); } // ------------------------------------------------------------------------- @@ -49,9 +58,10 @@ void SpinDelay(int ms) { void StartTickCount(void) { // This timer is based on the slow clock. The slow clock frequency is between 22kHz and 40kHz. // We can determine the actual slow clock frequency by looking at the Main Clock Frequency Register. - uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & 0xffff; // = 16 * main clock frequency (16MHz) / slow clock frequency - // set RealTimeCounter divider to count at 1kHz: - AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST | ((256000 + (mainf / 2)) / mainf); + while ((AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINRDY) == 0); // Wait for MAINF value to become available... + uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINF; // Get # main clocks within 16 slow clocks + // set RealTimeCounter divider to count at 1kHz, should be 32 if RC is exactly at 32kHz: + AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST | ((((MAINCK / 1000 * 16) + (mainf / 2)) / mainf) & AT91C_RTTC_RTPRES); // note: worst case precision is approx 2.5% } @@ -59,12 +69,12 @@ void StartTickCount(void) { * Get the current count. */ uint32_t RAMFUNC GetTickCount(void) { - return AT91C_BASE_RTTC->RTTC_RTVR;// was * 2; + return AT91C_BASE_RTTC->RTTC_RTVR; } 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; } @@ -175,6 +185,13 @@ uint32_t RAMFUNC GetCountSspClk(void) { return tmp_count; } +uint32_t RAMFUNC GetCountSspClkDelta(uint32_t start) { + uint32_t stop = GetCountSspClk(); + if ( stop >= start ) + return stop - start; + return (UINT32_MAX - start) + stop; +} + // ------------------------------------------------------------------------- // Timer for bitbanging, or LF stuff when you need a very precis timer // 1us = 1.5ticks diff --git a/armsrc/ticks.h b/armsrc/ticks.h index 9ff0d6000..e036e018c 100644 --- a/armsrc/ticks.h +++ b/armsrc/ticks.h @@ -12,11 +12,7 @@ #ifndef __TICKS_H #define __TICKS_H -#include -#include #include "common.h" -#include "apps.h" -#include "proxmark3.h" #ifndef GET_TICKS #define GET_TICKS GetTicks() @@ -37,6 +33,7 @@ void SpinDelayCountUs(uint32_t us); void StartCountSspClk(); void ResetSspClk(void); uint32_t RAMFUNC GetCountSspClk(); +uint32_t RAMFUNC GetCountSspClkDelta(); void StartTicks(void); uint32_t GetTicks(void); @@ -45,4 +42,5 @@ void WaitUS(uint16_t us); void WaitMS(uint16_t ms); void StopTicks(void); + #endif diff --git a/common/usart.c b/armsrc/usart.c similarity index 97% rename from common/usart.c rename to armsrc/usart.c index ced1e5e6b..f3abb40a1 100644 --- a/common/usart.c +++ b/armsrc/usart.c @@ -8,10 +8,8 @@ //----------------------------------------------------------------------------- // The main USART code, for serial communications over FPC connector //----------------------------------------------------------------------------- -#include "cmd.h" #include "usart.h" -#include "string.h" -#include "../armsrc/ticks.h" // startcountus +#include "proxmark3_arm.h" volatile AT91PS_USART pUS1 = AT91C_BASE_US1; volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; @@ -229,9 +227,9 @@ void usart_init(uint32_t baudrate, uint8_t parity) { // OVER = 1, -yes we are oversampling // baudrate == selected clock/8/CD --> this is ours // - uint32_t brgr = 48000000 / (usart_baudrate << 3); + uint32_t brgr = MCK / (usart_baudrate << 3); // doing fp = round((mck / (usart_baudrate << 3) - brgr) * 8) with integers: - uint32_t fp = ((16 * 48000000 / (usart_baudrate << 3) - 16 * brgr) + 1) / 2; + uint32_t fp = ((16 * MCK / (usart_baudrate << 3) - 16 * brgr) + 1) / 2; pUS1->US_BRGR = (fp << 16) | brgr; diff --git a/common/usart.h b/armsrc/usart.h similarity index 58% rename from common/usart.h rename to armsrc/usart.h index ef0691df5..01ca0d809 100644 --- a/common/usart.h +++ b/armsrc/usart.h @@ -1,28 +1,20 @@ #ifndef __USART_H #define __USART_H -#include -#include "proxmark3.h" +#include "common.h" +#include "usart_defs.h" -//#define USART_BAUD_RATE 9600 -#define USART_BAUD_RATE 115200 - -// BT HC-06 physical layer runs at 128kbps -// so it's possible to gain a little bit by using 230400 -// with some risk to overflow its internal buffers: -//#define USART_BAUD_RATE 230400 +#define USART_BUFFLEN 512 +#define USART_FIFOLEN (2*USART_BUFFLEN) // Higher baudrates are pointless, only increasing overflow risk extern uint32_t usart_baudrate; -#define USART_PARITY 'N' extern uint8_t usart_parity; void usart_init(uint32_t baudrate, uint8_t parity); int usart_writebuffer_sync(uint8_t *data, size_t len); uint32_t usart_read_ng(uint8_t *data, size_t len); uint16_t usart_rxdata_available(void); -#define USART_BUFFLEN 512 -#define USART_FIFOLEN (2*USART_BUFFLEN) #endif diff --git a/armsrc/util.c b/armsrc/util.c index cad2d2ac5..888c64b9d 100644 --- a/armsrc/util.c +++ b/armsrc/util.c @@ -9,6 +9,14 @@ //----------------------------------------------------------------------------- #include "util.h" +#include "proxmark3_arm.h" +#include "ticks.h" +#include "commonutil.h" +#include "dbprint.h" +#include "string.h" +#include "usb_cdc.h" +#include "usart.h" + size_t nbytes(size_t nbits) { return (nbits >> 3) + ((nbits % 8) > 0); } @@ -82,6 +90,7 @@ void LEDsoff() { LED_D_OFF(); } +//ICEMAN: LED went from 1,2,3,4 -> 1,2,4,8 void LED(int led, int ms) { if (led & LED_A) // Proxmark3 historical mapping: LED_ORANGE LED_A_ON(); @@ -115,26 +124,27 @@ void SpinOff(uint32_t pause) { SpinDelay(pause); } -// 0=A, 1=B, 2=C, 3=D +// Blinks.. +// A = 1, B = 2, C = 4, D = 8 void SpinErr(uint8_t led, uint32_t speed, uint8_t times) { SpinOff(speed); NTIME(times) { - switch (led) { - case 0: - LED_A_INV(); - break; - case 1: - LED_B_INV(); - break; - case 2: - LED_C_INV(); - break; - case 3: - LED_D_INV(); - break; - } + + if (led & LED_A) // Proxmark3 historical mapping: LED_ORANGE + LED_A_INV(); + if (led & LED_B) // Proxmark3 historical mapping: LED_GREEN + LED_B_INV(); + if (led & LED_C) // Proxmark3 historical mapping: LED_RED + LED_C_INV(); + if (led & LED_D) // Proxmark3 historical mapping: LED_RED2 + LED_D_INV(); + SpinDelay(speed); } + LED_A_OFF(); + LED_B_OFF(); + LED_C_OFF(); + LED_D_OFF(); } void SpinDown(uint32_t speed) { @@ -176,7 +186,13 @@ void SpinUp(uint32_t speed) { // double click, otherwise it will waste 500ms -- use BUTTON_HELD instead int BUTTON_CLICKED(int ms) { // Up to 500ms in between clicks to mean a double click - int ticks = (48000 * (ms ? ms : 1000)) >> 10; + // timer counts in 21.3us increments (1024/48MHz) + // WARNING: timer can't measure more than 1.39s (21.3us * 0xffff) + if (ms > 1390) { + if (DBGLEVEL >= DBG_ERROR) Dbprintf(_RED_("Error, BUTTON_CLICKED called with %i > 1390"), ms); + ms = 1390; + } + int ticks = ((MCK / 1000) * (ms ? ms : 1000)) >> 10; // If we're not even pressed, forget about it! if (!BUTTON_PRESS()) @@ -203,7 +219,7 @@ int BUTTON_CLICKED(int ms) { // reset our timer for 500ms start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; - ticks = (48000 * (500)) >> 10; + ticks = ((MCK / 1000) * (500)) >> 10; } // Still haven't let it off @@ -233,6 +249,12 @@ int BUTTON_CLICKED(int ms) { // Determine if a button is held down int BUTTON_HELD(int ms) { + // timer counts in 21.3us increments (1024/48MHz) + // WARNING: timer can't measure more than 1.39s (21.3us * 0xffff) + if (ms > 1390) { + if (DBGLEVEL >= DBG_ERROR) Dbprintf(_RED_("Error, BUTTON_HELD called with %i > 1390"), ms); + ms = 1390; + } // If button is held for one second int ticks = (48000 * (ms ? ms : 1000)) >> 10; diff --git a/armsrc/util.h b/armsrc/util.h index 8649f0431..9748152ef 100644 --- a/armsrc/util.h +++ b/armsrc/util.h @@ -12,11 +12,6 @@ #define __UTIL_H #include "common.h" -#include "commonutil.h" -#include "proxmark3.h" -#include "string.h" -#include "BigBuf.h" -#include "ticks.h" // Basic macros diff --git a/armsrc/vtsend.c b/armsrc/vtsend.c index e851d4334..f07793cce 100644 --- a/armsrc/vtsend.c +++ b/armsrc/vtsend.c @@ -31,7 +31,8 @@ */ #include "vtsend.h" -#include "apps.h" +#include "pm3_cmd.h" +#include "dbprint.h" #define ESC (0x1B) //#define UART_WRITE(P, BUF, SIZ) (P)->uart_write(BUF, SIZ, (P)->extobj) diff --git a/armsrc/vtsend.h b/armsrc/vtsend.h index 4dcb0c62b..63d3d2461 100644 --- a/armsrc/vtsend.h +++ b/armsrc/vtsend.h @@ -33,6 +33,8 @@ #ifndef VTSEND_H #define VTSEND_H +#include "common.h" + #define VTSEND_COLOR_BLACK (0) #define VTSEND_COLOR_RED (1) #define VTSEND_COLOR_GREEN (2) @@ -56,10 +58,6 @@ typedef struct { void *extobj; } vtsend_t; -#ifdef __cplusplus -extern "C" { -#endif - int vtsend_init(vtsend_t *p, VTSEND_SERIAL_WRITE uart_write, void *extobj); int vtsend_cursor_position(vtsend_t *p, const int column, const int line); int vtsend_cursor_up(vtsend_t *p, const int n); @@ -84,10 +82,4 @@ int vtsend_fill_box( vtsend_t *p, const int x1, const int y1, const int x2, const int y2); -#ifdef __cplusplus -} #endif - -#endif - - diff --git a/common/wiegand.c b/armsrc/wiegand.c similarity index 100% rename from common/wiegand.c rename to armsrc/wiegand.c diff --git a/common/wiegand.h b/armsrc/wiegand.h similarity index 100% rename from common/wiegand.h rename to armsrc/wiegand.h diff --git a/bootrom/Makefile b/bootrom/Makefile index afc4162a7..d666f3acd 100644 --- a/bootrom/Makefile +++ b/bootrom/Makefile @@ -3,13 +3,13 @@ # at your option, any later version. See the LICENSE.txt file for the text of # the license. #----------------------------------------------------------------------------- -# Makefile for bootrom, see ../common/Makefile.common for common settings +# Makefile for bootrom, see ../common_arm/Makefile.common for common settings #----------------------------------------------------------------------------- # DO NOT use thumb mode in the phase 1 bootloader since that generates a section with glue code ARMSRC = THUMBSRC = usb_cdc.c \ - bootrom.c + bootrom.c ASMSRC = ram-reset.s flash-reset.s VERSIONSRC = version.c @@ -29,14 +29,16 @@ APP_CFLAGS += -fno-stack-protector -fno-pie # Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC -include ../common/Makefile.common +include ../common_arm/Makefile.common + +INSTALLFW = $(OBJDIR)/bootrom.elf OBJS = $(OBJDIR)/bootrom.s19 # version.c should be remade on every compilation version.c: default_version.c $(info [=] GEN $@) - $(Q)perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@ + $(Q)sh ../tools/mkversion.sh > $@ || perl ../tools/mkversion.pl > $@ || $(CP) $^ $@ all: $(OBJS) @@ -49,14 +51,23 @@ $(OBJDIR)/bootrom.elf: $(VERSIONOBJ) $(ASMOBJ) $(ARMOBJ) $(THUMBOBJ) $(Q)$(CC) $(LDFLAGS) -Wl,-T,ldscript-flash,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS) clean: - $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.o - $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.elf - $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.s19 - $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.map - $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.d - $(Q)$(DELETE) version.c + $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.o + $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.elf + $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.s19 + $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.map + $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.d + $(Q)$(RM) version.c -.PHONY: all clean help +install: all + $(info [@] Installing bootrom to $(DESTDIR)$(PREFIX)...) + $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH) + $(Q)$(CP) $(INSTALLFW) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH) + +uninstall: + $(info [@] Uninstalling bootrom from $(DESTDIR)$(PREFIX)...) + $(Q)$(RM) $(foreach fw,$(INSTALLFW),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(notdir $(fw))) + +.PHONY: all clean help install help: @echo Multi-OS Makefile, you are running on $(DETECTED_OS) @echo Possible targets: diff --git a/bootrom/bootrom.c b/bootrom/bootrom.c index 1a3dafc12..2c1a6f23a 100644 --- a/bootrom/bootrom.c +++ b/bootrom/bootrom.c @@ -6,9 +6,10 @@ // Main code for the bootloader //----------------------------------------------------------------------------- -#include #include "usb_cdc.h" +#include "proxmark3_arm.h" + struct common_area common_area __attribute__((section(".commonarea"))); unsigned int start_addr, end_addr, bootrom_unlocked; extern char _bootrom_start, _bootrom_end, _flash_start, _flash_end; @@ -52,7 +53,7 @@ void DbpString(char *str) { static void ConfigClocks(void) { // we are using a 16 MHz crystal as the basis for everything - // slow clock runs at 32Khz typical regardless of crystal + // slow clock runs at 32kHz typical regardless of crystal // enable system clock and USB clock AT91C_BASE_PMC->PMC_SCER |= AT91C_PMC_PCK | AT91C_PMC_UDP; @@ -66,8 +67,8 @@ static void ConfigClocks(void) { (1 << AT91C_ID_PWMC) | (1 << AT91C_ID_UDP); - // worst case scenario, with MAINCK = 16Mhz xtal, startup delay is 1.4ms - // if SLCK slow clock runs at its worst case (max) frequency of 42khz + // worst case scenario, with MAINCK = 16MHz xtal, startup delay is 1.4ms + // if SLCK slow clock runs at its worst case (max) frequency of 42kHz // max startup delay = (1.4ms*42k)/8 = 7.356 so round up to 8 // enable main oscillator and set startup delay @@ -80,7 +81,7 @@ static void ConfigClocks(void) { // PLL output clock frequency in range 80 - 160 MHz needs CKGR_PLL = 00 // PLL output clock frequency in range 150 - 180 MHz needs CKGR_PLL = 10 - // PLL output is MAINCK * multiplier / divisor = 16Mhz * 12 / 2 = 96Mhz + // PLL output is MAINCK * multiplier / divisor = 16MHz * 12 / 2 = 96MHz AT91C_BASE_PMC->PMC_PLLR = PMC_PLL_DIVISOR(2) | //PMC_PLL_COUNT_BEFORE_LOCK(0x10) | @@ -92,7 +93,7 @@ static void ConfigClocks(void) { // wait for PLL to lock while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK)) {}; - // we want a master clock (MCK) to be PLL clock / 2 = 96Mhz / 2 = 48Mhz + // we want a master clock (MCK) to be PLL clock / 2 = 96MHz / 2 = 48MHz // datasheet recommends that this register is programmed in two operations // when changing to PLL, program the prescaler first then the source AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2; diff --git a/bootrom/ldscript-flash b/bootrom/ldscript-flash index 26acf8242..c9174ffcd 100644 --- a/bootrom/ldscript-flash +++ b/bootrom/ldscript-flash @@ -8,7 +8,7 @@ ----------------------------------------------------------------------------- */ -INCLUDE ../common/ldscript.common +INCLUDE ../common_arm/ldscript.common PHDRS { diff --git a/client/Makefile b/client/Makefile index 440f2b888..6fee6eae8 100644 --- a/client/Makefile +++ b/client/Makefile @@ -9,33 +9,20 @@ # Add -DNOFORCE to disable the -F switch # Add -DPRESETS to compile with preset models (edit config.h) -# Hide full compilation line: -ifneq ($(V),1) - Q?=@ -endif -# To see full command lines, use make V=1 +# Must be called before any Makefile include +ROOT_DIR:=$(dir $(realpath $(lastword $(MAKEFILE_LIST)))) -CC = gcc -CXX = g++ -LD = g++ -TAR = tar -TARFLAGS = -C .. --ignore-failed-read -rvf -RM = rm -f -MV = mv +include ../Makefile.defs -ENV_LDFLAGS := $(LDFLAGS) -ENV_CFLAGS := $(CFLAGS) +INSTALLBIN = proxmark3 +INSTALLSHARE = cmdscripts lualibs luascripts resources dictionaries -platform = $(shell uname) - -VPATH = ../common ../zlib ../uart +VPATH = ../common uart +vpath %.dic dictionaries OBJDIR = obj -LDLIBS = -ifneq ($(platform),Darwin) - LDLIBS += -L/opt/local/lib -endif -LDLIBS += -L/usr/local/lib -lreadline -lpthread -lm +LDLIBS ?= -L/usr/local/lib +LDLIBS += -lreadline -lpthread -lm # RPi Zero gcc requires -latomic # but MacOSX /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld @@ -44,22 +31,35 @@ ifneq ($(platform),Darwin) LDLIBS += -Wl,--as-needed -latomic -Wl,--no-as-needed endif -LUALIB = ../liblua/liblua.a +# local libraries +LUALIBPATH = ./liblua +LUALIB = $(LUALIBPATH)/liblua.a JANSSONLIBPATH = ./jansson JANSSONLIB = $(JANSSONLIBPATH)/libjansson.a -MBEDTLSLIBPATH = ../common/mbedtls -MBEDTLSLIB = $(MBEDTLSLIBPATH)/libmbedtls.a CBORLIBPATH = ./tinycbor CBORLIB = $(CBORLIBPATH)/tinycbor.a -LIBS = -I../zlib -I../uart -I../liblua -I$(MBEDTLSLIBPATH) -I$(JANSSONLIBPATH) -I$(CBORLIBPATH) -INCLUDES_CLIENT = -I. -I../include -I../common -I/opt/local/include $(LIBS) -LDFLAGS = $(ENV_LDFLAGS) +REVENGPATH = ./reveng +REVENGLIB = $(REVENGPATH)/libreveng.a +AMIIBOLIBPATH = ./amiitool +AMIIBOLIB = $(AMIIBOLIBPATH)/libamiibo.a -CFLAGS = $(ENV_CFLAGS) -std=c99 -D_ISOC99_SOURCE -DPRESETS $(INCLUDES_CLIENT) -Wall -g -O3 +# common libraries +MBEDTLSLIBPATH = ../common/mbedtls +MBEDTLSLIB = $(OBJDIR)/libmbedtls.a +ZLIBPATH = ../common/zlib +ZLIB = $(OBJDIR)/libz.a + +LIBS = -I$(LUALIBPATH) -I$(MBEDTLSLIBPATH) -I$(JANSSONLIBPATH) -I$(CBORLIBPATH) -I$(ZLIBPATH) -I$(REVENGPATH) -I$(AMIIBOLIBPATH) +INCLUDES_CLIENT = -I. -I../include -I../common -Iuart $(LIBS) +CFLAGS ?= -Wall -Werror -g -O3 +# We cannot just use CFLAGS+=... because it has impact on sub-makes if CFLAGS is defined in env: +PM3CFLAGS = $(CFLAGS) -std=c99 -D_ISOC99_SOURCE $(INCLUDES_CLIENT) +PREFIX ?= /usr/local ifneq (,$(findstring MINGW,$(platform))) - CFLAGS += -mno-ms-bitfields + PM3CFLAGS += -mno-ms-bitfields -fexec-charset=cp850 endif -CXXFLAGS = -I../include -Wall -O3 +CXXFLAGS ?= -Wall -Werror -O3 +PM3CXXFLAGS = $(CXXFLAGS) -I../include LUAPLATFORM = generic ifneq (,$(findstring MINGW,$(platform))) @@ -73,7 +73,6 @@ else LIBS := -I/usr/local/opt/readline/include $(LIBS) else LUALIB += -ldl - LDLIBS += -ltermcap -lncurses LUAPLATFORM = linux endif endif @@ -90,7 +89,7 @@ ifeq ($(QTINCLUDES), ) MOC = $(shell pkg-config --variable=moc_location QtCore) UIC = $(shell pkg-config --variable=uic_location QtCore) else - CXXFLAGS += -std=c++11 -fPIC + PM3CXXFLAGS += -std=c++11 -fPIC endif ifeq ($(QTINCLUDES), ) # if both pkg-config commands failed, search in common places @@ -100,7 +99,7 @@ ifeq ($(QTINCLUDES), ) ifneq ($(wildcard $(QTDIR)/include/QtWidgets),) QTINCLUDES += -I$(QTDIR)/include/QtWidgets QTLDLIBS = -L$(QTDIR)/lib -lQt5Widgets -lQt5Gui -lQt5Core - CXXFLAGS += -std=c++11 -fPIC + PM3CXXFLAGS += -std=c++11 -fPIC endif MOC = $(QTDIR)/bin/moc UIC = $(QTDIR)/bin/uic @@ -110,15 +109,15 @@ endif ifneq ($(QTLDLIBS),) QTGUIOBJS = $(OBJDIR)/proxgui.o $(OBJDIR)/proxguiqt.o $(OBJDIR)/proxguiqt.moc.o - CFLAGS += -DHAVE_GUI + PM3CFLAGS += -DHAVE_GUI else QTGUIOBJS = $(OBJDIR)/guidummy.o endif # Flags to generate temporary dependency files DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td -# make temporary to final dependeny files after successful compilation -POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d +# make temporary to final dependency files after successful compilation +POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d && $(TOUCH) $@ CORESRCS = uart_posix.c \ uart_win32.c \ @@ -130,7 +129,7 @@ CORESRCS = uart_posix.c \ crc16.c \ comms.c -CMDSRCS = crapto1/crapto1.c \ +CMDSRCS = crapto1/crapto1.c \ crapto1/crypto1.c \ mifare/mfkey.c \ tea.c \ @@ -147,7 +146,7 @@ CMDSRCS = crapto1/crapto1.c \ loclass/cipherutils.c \ loclass/ikeys.c \ loclass/elite_crack.c \ - loclass/fileutils.c \ + fileutils.c \ whereami.c \ mifare/mifarehost.c \ parity.c \ @@ -199,6 +198,7 @@ CMDSRCS = crapto1/crapto1.c \ cmdhftopaz.c \ cmdhffido.c \ cmdhffelica.c \ + cmdhfthinfilm.c \ cmdhw.c \ cmdlf.c \ cmdlfawid.c \ @@ -236,15 +236,9 @@ CMDSRCS = crapto1/crapto1.c \ scripting.c \ cmdscript.c \ pm3_bitlib.c \ - protocols.c \ cmdcrc.c \ - reveng/preset.c \ - reveng/reveng.c \ - reveng/cli.c \ - reveng/bmpbit.c \ - reveng/model.c \ - reveng/poly.c \ - bucketsort.c + bucketsort.c \ + flash.c cpu_arch = $(shell uname -m) ifneq ($(findstring 86, $(cpu_arch)), ) @@ -257,16 +251,11 @@ ifeq ($(MULTIARCHSRCS), ) CMDSRCS += hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c endif -ZLIBSRCS = deflate.c adler32.c trees.c zutil.c inflate.c inffast.c inftrees.c -ZLIBFLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED -#-DDEBUG -Dverbose=1 - QTGUISRCS = proxgui.cpp proxguiqt.cpp proxguiqt.moc.cpp guidummy.cpp COREOBJS = $(CORESRCS:%.c=$(OBJDIR)/%.o) CMDOBJS = $(CMDSRCS:%.c=$(OBJDIR)/%.o) OBJCOBJS = $(OBJCSRCS:%.m=$(OBJDIR)/%.o) -ZLIBOBJS = $(ZLIBSRCS:%.c=$(OBJDIR)/%.o) MULTIARCHOBJS = $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_NOSIMD.o) \ $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_MMX.o) \ $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_SSE2.o) \ @@ -290,27 +279,21 @@ ifeq "$(SUPPORTS_AVX512)" "True" MULTIARCHOBJS += $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX512.o) endif -BINS = proxmark3 flasher fpga_compress -CLEAN = $(BINS) $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(ZLIBOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(OBJDIR)/*.o *.moc.cpp ui/ui_overlays.h lualibs/pm3_cmd.lua lualibs/mf_default_keys.lua +BINS = proxmark3 +CLEAN = $(BINS) *.moc.cpp ui/ui_overlays.h lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua +# transition: make sure old flasher is gone too +CLEAN += flasher # need to assign dependancies to build these first... -all: lua_build jansson_build mbedtls_build cbor_build $(BINS) +all: $(BINS) all-static: LDLIBS:=-static $(LDLIBS) -all-static: proxmark3 flasher fpga_compress +all-static: $(BINS) -proxmark3: LDLIBS+=$(LUALIB) $(JANSSONLIB) $(MBEDTLSLIB) $(CBORLIB) $(QTLDLIBS) -proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) lualibs/pm3_cmd.lua lualibs/mf_default_keys.lua +proxmark3: LDLIBS+=$(LUALIB) $(JANSSONLIB) $(MBEDTLSLIB) $(CBORLIB) $(ZLIB) $(REVENGLIB) $(AMIIBOLIB) $(QTLDLIBS) +proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(LUALIB) $(JANSSONLIB) $(CBORLIB) $(REVENGLIB) $(MBEDTLSLIB) $(ZLIB) $(AMIIBOLIB) lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua $(info [=] LD $@) - $(Q)$(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) $(LDLIBS) -o $@ - -flasher: $(OBJDIR)/flash.o $(OBJDIR)/flasher.o $(COREOBJS) $(OBJCOBJS) - $(info [=] LD $@) - $(Q)$(LD) $(LDFLAGS) $^ $(LDLIBS) -o $@ - -fpga_compress: $(OBJDIR)/fpga_compress.o $(ZLIBOBJS) - $(info [=] LD $@) - $(Q)$(LD) $(LDFLAGS) $(ZLIBFLAGS) $^ $(LDLIBS) -o $@ + $(Q)$(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(LDLIBS) -o $@ proxgui.cpp: ui/ui_overlays.h @@ -326,110 +309,144 @@ lualibs/pm3_cmd.lua: ../include/pm3_cmd.h $(info [=] GEN $@) $(Q)awk -f pm3_cmd_h2lua.awk $^ > $@ -lualibs/mf_default_keys.lua : default_keys.dic +lualibs/mfc_default_keys.lua : mfc_default_keys.dic $(info [=] GEN $@) $(Q)awk -f default_keys_dic2lua.awk $^ > $@ clean: $(Q)$(RM) $(CLEAN) - $(Q)$(MAKE) --no-print-directory -C ../liblua clean + $(Q)$(RMDIR) $(OBJDIR) + $(Q)$(MAKE) --no-print-directory -C $(LUALIBPATH) clean $(Q)$(MAKE) --no-print-directory -C $(JANSSONLIBPATH) clean - $(Q)$(MAKE) --no-print-directory -C $(MBEDTLSLIBPATH) clean $(Q)$(MAKE) --no-print-directory -C $(CBORLIBPATH) clean + $(Q)$(MAKE) --no-print-directory -C $(REVENGPATH) clean + $(Q)$(MAKE) --no-print-directory -C $(AMIIBOLIBPATH) clean + +install: all + $(info [@] Installing client to $(DESTDIR)$(PREFIX)...) +ifneq (,$(INSTALLBIN)) + $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH) + $(Q)$(CP) $(INSTALLBIN) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH) +endif +ifneq (,$(INSTALLSHARE)) + $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH) + $(Q)$(CP) $(INSTALLSHARE) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH) +endif + @true + +uninstall: + $(info [@] Uninstalling client from $(DESTDIR)$(PREFIX)...) +ifneq (,$(INSTALLBIN)) + $(Q)$(RM) $(foreach tool,$(INSTALLBIN),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)$(PATHSEP)$(notdir $(tool))) +endif +ifneq (,$(INSTALLSHARE)) + $(Q)$(RMDIR) $(foreach tool,$(INSTALLSHARE),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)$(PATHSEP)$(notdir $(tool))) +endif + @true tarbin: $(BINS) $(info [=] TAR ../proxmark3-$(platform)-bin.tar) $(Q)$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%) $(WINBINS:%=client/%) -lua_build: +# local libraries: +$(LUALIB): $(info [*] MAKE liblua for $(LUAPLATFORM)) - $(Q)$(MAKE) --no-print-directory -C ../liblua $(LUAPLATFORM) + $(Q)$(MAKE) --no-print-directory -C $(LUALIBPATH) $(LUAPLATFORM) -jansson_build: +$(JANSSONLIB): $(info [*] MAKE jansson) $(Q)$(MAKE) --no-print-directory -C $(JANSSONLIBPATH) all -mbedtls_build: - $(info [*] MAKE mbedtls) - $(Q)$(MAKE) --no-print-directory -C $(MBEDTLSLIBPATH) all - -cbor_build: +$(CBORLIB): $(info [*] MAKE tinycbor) $(Q)$(MAKE) --no-print-directory -C $(CBORLIBPATH) all -.PHONY: all clean +$(REVENGLIB): + $(info [*] MAKE reveng) + $(Q)$(MAKE) --no-print-directory -C $(REVENGPATH) all + +$(AMIIBOLIB): + $(info [*] MAKE amiibo) + $(Q)$(MAKE) --no-print-directory -C $(AMIIBOLIBPATH) all + +# common libraries: +$(MBEDTLSLIB): + $(info [*] MAKE mbedtls) + $(Q)$(MAKE) --no-print-directory -C $(MBEDTLSLIBPATH) OBJDIR=$(ROOT_DIR)$(OBJDIR) BINDIR=$(ROOT_DIR)$(OBJDIR) all + +$(ZLIB): + $(info [*] MAKE zlib) + $(Q)$(MAKE) --no-print-directory -C $(ZLIBPATH) OBJDIR=$(ROOT_DIR)$(OBJDIR) BINDIR=$(ROOT_DIR)$(OBJDIR) all + +.PHONY: all clean install uninstall # easy printing of MAKE VARIABLES print-%: ; @echo $* = $($*) $(OBJDIR)/%_NOSIMD.o : %.c $(OBJDIR)/%_NOSIMD.d $(info [-] CC(NOSIMD) $<) - $(Q)$(CC) $(DEPFLAGS:%.Td=%_NOSIMD.Td) $(CFLAGS) $(HARD_SWITCH_NOSIMD) -c -o $@ $< - $(Q)$(MV) -f $(OBJDIR)/$*_NOSIMD.Td $(OBJDIR)/$*_NOSIMD.d + $(Q)$(MKDIR) $(dir $@) + $(Q)$(CC) $(DEPFLAGS:%.Td=%_NOSIMD.Td) $(PM3CFLAGS) $(HARD_SWITCH_NOSIMD) -c -o $@ $< + $(Q)$(MV) -f $(OBJDIR)/$*_NOSIMD.Td $(OBJDIR)/$*_NOSIMD.d && $(TOUCH) $@ $(OBJDIR)/%_MMX.o : %.c $(OBJDIR)/%_MMX.d $(info [-] CC(MMX) $<) - $(Q)$(CC) $(DEPFLAGS:%.Td=%_MMX.Td) $(CFLAGS) $(HARD_SWITCH_MMX) -c -o $@ $< - $(Q)$(MV) -f $(OBJDIR)/$*_MMX.Td $(OBJDIR)/$*_MMX.d + $(Q)$(MKDIR) $(dir $@) + $(Q)$(CC) $(DEPFLAGS:%.Td=%_MMX.Td) $(PM3CFLAGS) $(HARD_SWITCH_MMX) -c -o $@ $< + $(Q)$(MV) -f $(OBJDIR)/$*_MMX.Td $(OBJDIR)/$*_MMX.d && $(TOUCH) $@ $(OBJDIR)/%_SSE2.o : %.c $(OBJDIR)/%_SSE2.d $(info [-] CC(SSE2) $<) - $(Q)$(CC) $(DEPFLAGS:%.Td=%_SSE2.Td) $(CFLAGS) $(HARD_SWITCH_SSE2) -c -o $@ $< - $(Q)$(MV) -f $(OBJDIR)/$*_SSE2.Td $(OBJDIR)/$*_SSE2.d + $(Q)$(MKDIR) $(dir $@) + $(Q)$(CC) $(DEPFLAGS:%.Td=%_SSE2.Td) $(PM3CFLAGS) $(HARD_SWITCH_SSE2) -c -o $@ $< + $(Q)$(MV) -f $(OBJDIR)/$*_SSE2.Td $(OBJDIR)/$*_SSE2.d && $(TOUCH) $@ $(OBJDIR)/%_AVX.o : %.c $(OBJDIR)/%_AVX.d $(info [-] CC(AVX) $<) - $(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX.Td) $(CFLAGS) $(HARD_SWITCH_AVX) -c -o $@ $< - $(Q)$(MV) -f $(OBJDIR)/$*_AVX.Td $(OBJDIR)/$*_AVX.d + $(Q)$(MKDIR) $(dir $@) + $(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX.Td) $(PM3CFLAGS) $(HARD_SWITCH_AVX) -c -o $@ $< + $(Q)$(MV) -f $(OBJDIR)/$*_AVX.Td $(OBJDIR)/$*_AVX.d && $(TOUCH) $@ $(OBJDIR)/%_AVX2.o : %.c $(OBJDIR)/%_AVX2.d $(info [-] CC(AVX2) $<) - $(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX2.Td) $(CFLAGS) $(HARD_SWITCH_AVX2) -c -o $@ $< - $(Q)$(MV) -f $(OBJDIR)/$*_AVX2.Td $(OBJDIR)/$*_AVX2.d + $(Q)$(MKDIR) $(dir $@) + $(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX2.Td) $(PM3CFLAGS) $(HARD_SWITCH_AVX2) -c -o $@ $< + $(Q)$(MV) -f $(OBJDIR)/$*_AVX2.Td $(OBJDIR)/$*_AVX2.d && $(TOUCH) $@ $(OBJDIR)/%_AVX512.o : %.c $(OBJDIR)/%_AVX512.d $(info [-] CC(AVX512) $<) - $(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX512.Td) $(CFLAGS) $(HARD_SWITCH_AVX512) -c -o $@ $< - $(Q)$(MV) -f $(OBJDIR)/$*_AVX512.Td $(OBJDIR)/$*_AVX512.d + $(Q)$(MKDIR) $(dir $@) + $(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX512.Td) $(PM3CFLAGS) $(HARD_SWITCH_AVX512) -c -o $@ $< + $(Q)$(MV) -f $(OBJDIR)/$*_AVX512.Td $(OBJDIR)/$*_AVX512.d && $(TOUCH) $@ %.o: %.c $(OBJDIR)/%.o : %.c $(OBJDIR)/%.d $(info [-] CC $<) - $(Q)$(CC) $(DEPFLAGS) $(CFLAGS) $(ZLIBFLAGS) -c -o $@ $< + $(Q)$(MKDIR) $(dir $@) + $(Q)$(CC) $(DEPFLAGS) $(PM3CFLAGS) -c -o $@ $< $(Q)$(POSTCOMPILE) %.o: %.cpp $(OBJDIR)/%.o : %.cpp $(OBJDIR)/%.d $(info [-] CXX $<) - $(Q)$(CXX) $(DEPFLAGS) $(CXXFLAGS) $(QTINCLUDES) -c -o $@ $< + $(Q)$(MKDIR) $(dir $@) + $(Q)$(CXX) $(DEPFLAGS) $(PM3CXXFLAGS) $(QTINCLUDES) -c -o $@ $< $(Q)$(POSTCOMPILE) %.o: %.m $(OBJDIR)/%.o : %.m $(OBJDIR)/%.d $(info [-] CC $<) - $(Q)$(CC) $(DEPFLAGS) $(CFLAGS) -c -o $@ $< + $(Q)$(MKDIR) $(dir $@) + $(Q)$(CC) $(DEPFLAGS) $(PM3CFLAGS) -c -o $@ $< $(Q)$(POSTCOMPILE) -#$(CMDOBJS) $(COREOBJS): $(notdir $(%.c)) %.d -# $(CC) $(DEPFLAGS) $(CFLAGS) -c -o $@ $< -# $(POSTCOMPILE) - -#$(ZLIBOBJS): $(notdir $(%.c)) %.d -# $(CC) $(DEPFLAGS) $(CFLAGS) $(ZLIBFLAGS) -c -o $@ $< -# $(POSTCOMPILE) - -#$(QTGUIOBJS): $(notdir $(%.cpp)) %.d -# $(CXX) $(DEPFLAGS) $(CXXFLAGS) -c -o $@ $< -# $(POSTCOMPILE) - -DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(CORESRCS) $(CMDSRCS) $(ZLIBSRCS)) \ +DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(CORESRCS) $(CMDSRCS) $(REVENGSRCS)) \ $(patsubst %.o, %.d, $(MULTIARCHOBJS)) \ $(patsubst %.cpp, $(OBJDIR)/%.d, $(QTGUISRCS)) \ $(patsubst %.m, $(OBJDIR)/%.d, $(OBJCSRCS)) \ - $(OBJDIR)/proxmark3.d $(OBJDIR)/flash.d $(OBJDIR)/flasher.d $(OBJDIR)/fpga_compress.d + $(OBJDIR)/proxmark3.d $(DEPENDENCY_FILES): ; .PRECIOUS: $(DEPENDENCY_FILES) -include $(DEPENDENCY_FILES) - diff --git a/client/amiitool/Makefile b/client/amiitool/Makefile new file mode 100644 index 000000000..c473f58ee --- /dev/null +++ b/client/amiitool/Makefile @@ -0,0 +1,19 @@ +MYSRCPATHS = +MYINCLUDES = -I. -I.. -I../jansson -I../../common/ -I../../include/ +MYCFLAGS = -std=c99 -D_ISOC99_SOURCE +MYDEFS = +MYSRCS = \ + amiibo.c \ + drbg.c \ + keygen.c + +LIB_A = libamiibo.a + +include ../../Makefile.host + +# just for testing amiitool before complete migration into a lib: + +amiitool: + gcc $(CFLAGS) \ + amiitool.c $(MYSRCS) ../../common/commonutil.c ../ui.c -lreadline -lm ../../common/mbedtls/libmbedtls.a \ + -o amiitool diff --git a/client/amiitool/amiibo.c b/client/amiitool/amiibo.c index a8596e30a..d8fe837b1 100644 --- a/client/amiitool/amiibo.c +++ b/client/amiitool/amiibo.c @@ -8,6 +8,7 @@ #include "amiibo.h" #include "mbedtls/md.h" #include "mbedtls/aes.h" +#include "commonutil.h" #define HMAC_POS_DATA 0x008 #define HMAC_POS_TAG 0x1B4 diff --git a/client/amiitool/amiibo.h b/client/amiitool/amiibo.h index 7b56a2c0a..47d544875 100644 --- a/client/amiitool/amiibo.h +++ b/client/amiitool/amiibo.h @@ -13,7 +13,6 @@ #include #include #include "keygen.h" -#include "util.h" #define NFC3D_AMIIBO_SIZE 520 diff --git a/client/amiitool/amiitool.c b/client/amiitool/amiitool.c index 78c8f4d1e..ca34a5c6a 100644 --- a/client/amiitool/amiitool.c +++ b/client/amiitool/amiitool.c @@ -5,10 +5,11 @@ * SPDX-License-Identifier: MIT */ -#include #include #include -#include "../loclass/fileutils.h" +#include "fileutils.h" +#include "amiibo.h" +#include "getopt.h" #define NTAG215_SIZE 540 @@ -16,7 +17,7 @@ static char *self; void amiitool_usage() { fprintf(stderr, - "amiitool build %i (commit %s-%08x)\n" + /*"amiitool build %i (commit %s-%08x)\n"*/ "by Marcos Del Sol Vives \n" "\n" "Usage: %s (-e|-d|-c) -k keyfile [-i input] [-s input2] [-o output]\n" @@ -28,7 +29,7 @@ void amiitool_usage() { " -s input save file, save from this file will replace input file ones.\n" " -o output file. If not specified, stdout will be used.\n" " -l decrypt files with invalid signatures.\n", - , self + self ); } @@ -62,6 +63,9 @@ int main(int argc, char **argv) { case 'i': infile = optarg; break; + case 'k': + keyfile = optarg; + break; case 's': savefile = optarg; break; @@ -83,7 +87,8 @@ int main(int argc, char **argv) { } nfc3d_amiibo_keys amiiboKeys; - + if (! LoadAmiikey(amiiboKeys, keyfile)) + return 5; uint8_t original[NTAG215_SIZE]; uint8_t modified[NFC3D_AMIIBO_SIZE]; diff --git a/client/amiitool/drbg.c b/client/amiitool/drbg.c index 623a29776..c1297920f 100644 --- a/client/amiitool/drbg.c +++ b/client/amiitool/drbg.c @@ -8,7 +8,7 @@ #include "drbg.h" #include #include -#include +#include "mbedtls/md.h" void nfc3d_drbg_init(nfc3d_drbg_ctx *ctx, const uint8_t *hmacKey, size_t hmacKeySize, const uint8_t *seed, size_t seedSize) { assert(ctx != NULL); diff --git a/client/amiitool/keygen.c b/client/amiitool/keygen.c index 4b74a0232..f148c0dc8 100644 --- a/client/amiitool/keygen.c +++ b/client/amiitool/keygen.c @@ -19,7 +19,7 @@ void nfc3d_keygen_prepare_seed(const nfc3d_keygen_masterkeys *baseKeys, const ui uint8_t *start = output; // 1: Copy whole type string - output = memccpy(output, baseKeys->typeString, '\0', sizeof(baseKeys->typeString)); + output = (uint8_t *)strcpy((char *)output, baseKeys->typeString); // 2: Append (16 - magicBytesSize) from the input seed size_t leadingSeedBytes = 16 - baseKeys->magicBytesSize; diff --git a/client/cliparser/cliparser.c b/client/cliparser/cliparser.c index ae2124085..02746c0f4 100644 --- a/client/cliparser/cliparser.c +++ b/client/cliparser/cliparser.c @@ -9,7 +9,6 @@ //----------------------------------------------------------------------------- #include "cliparser.h" -#include #include void **argtable = NULL; diff --git a/client/cliparser/cliparser.h b/client/cliparser/cliparser.h index 7da509757..c67488d59 100644 --- a/client/cliparser/cliparser.h +++ b/client/cliparser/cliparser.h @@ -12,7 +12,6 @@ #define __CLIPARSER_H #include "argtable3.h" #include "util.h" -#include #define arg_param_begin arg_lit0("hH", "help", "print this help and exit") #define arg_param_end arg_end(20) diff --git a/client/cmdanalyse.c b/client/cmdanalyse.c index 0821cc4d1..2e88f6e5b 100644 --- a/client/cmdanalyse.c +++ b/client/cmdanalyse.c @@ -9,6 +9,19 @@ //----------------------------------------------------------------------------- #include "cmdanalyse.h" +#include // size_t +#include +#include // tolower + +#include "commonutil.h" // reflect... +#include "comms.h" // clearCommandBuffer +#include "cmdparser.h" // command_t +#include "ui.h" // PrintAndLog +#include "crc.h" +#include "crc16.h" // crc16 ccitt +#include "tea.h" +#include "legic_prng.h" + static int CmdHelp(const char *Cmd); static int usage_analyse_lcr(void) { diff --git a/client/cmdanalyse.h b/client/cmdanalyse.h index 20dc58a7e..4d223be1b 100644 --- a/client/cmdanalyse.h +++ b/client/cmdanalyse.h @@ -11,20 +11,7 @@ #ifndef CMDANALYSE_H__ #define CMDANALYSE_H__ -#include // size_t -#include -#include -#include "cmdmain.h" -#include "proxmark3.h" -#include "ui.h" // PrintAndLog -#include "util.h" -#include "crc.h" -#include "crc16.h" // crc16 ccitt -#include "tea.h" -#include "legic_prng.h" -#include "loclass/elite_crack.h" -#include "mifare/mfkey.h" // nonce2key -#include "util_posix.h" // msclock +#include "common.h" int CmdAnalyse(const char *Cmd); #endif diff --git a/client/cmdcrc.c b/client/cmdcrc.c index af4baae45..7f41b90e3 100644 --- a/client/cmdcrc.c +++ b/client/cmdcrc.c @@ -9,6 +9,23 @@ //----------------------------------------------------------------------------- #include "cmdcrc.h" +#include +#include +#include +#include + +#ifdef _WIN32 +# include +# include +# ifndef STDIN_FILENO +# define STDIN_FILENO 0 +# endif /* STDIN_FILENO */ +#endif /* _WIN32 */ + +#include "reveng/reveng.h" +#include "ui.h" +#include "util.h" + #define MAX_ARGS 20 static int split(char *str, char *arr[MAX_ARGS]) { diff --git a/client/cmdcrc.h b/client/cmdcrc.h index e45c004f5..957cd1eec 100644 --- a/client/cmdcrc.h +++ b/client/cmdcrc.h @@ -11,22 +11,7 @@ #ifndef CMDCRC_H__ #define CMDCRC_H__ -#ifdef _WIN32 -# include -# include -# ifndef STDIN_FILENO -# define STDIN_FILENO 0 -# endif /* STDIN_FILENO */ -#endif /* _WIN32 */ - -#include -#include -#include -#include -#include "cmdmain.h" -#include "reveng/reveng.h" -#include "ui.h" -#include "util.h" +#include "common.h" int CmdCrc(const char *Cmd); diff --git a/client/cmddata.c b/client/cmddata.c index 7ade24586..9465c63ac 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -9,6 +9,22 @@ //----------------------------------------------------------------------------- #include "cmddata.h" +#include +#include +#include // for CmdNorm INT_MIN && INT_MAX +#include // pow +#include // tolower + +#include "commonutil.h" // ARRAYLEN +#include "cmdparser.h" // for command_t +#include "ui.h" // for show graph controls +#include "graph.h" // for graph data +#include "comms.h" +#include "lfdemod.h" // for demod code +#include "loclass/cipherutils.h" // for decimating samples in getsamples +#include "cmdlfem4x.h" // askem410xdecode +#include "fileutils.h" // searchFile + uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; size_t DemodBufferLen = 0; size_t g_DemodStartIdx = 0; @@ -23,6 +39,7 @@ static int usage_data_printdemodbuf(void) { PrintAndLogEx(NORMAL, " x output in hex (omit for binary output)"); PrintAndLogEx(NORMAL, " o enter offset in # of bits"); PrintAndLogEx(NORMAL, " l enter length to print in # of bits or hex characters respectively"); + PrintAndLogEx(NORMAL, " s strip leading zeroes, i.e. set offset to first bit equal to one"); return PM3_SUCCESS; } static int usage_data_manrawdecode(void) { @@ -386,6 +403,7 @@ void printDemodBuff(void) { int CmdPrintDemodBuff(const char *Cmd) { bool hexMode = false; bool errors = false; + bool lstrip = false; uint32_t offset = 0; uint32_t length = 512; char cmdp = 0; @@ -407,6 +425,10 @@ int CmdPrintDemodBuff(const char *Cmd) { if (!length) errors = true; cmdp += 2; break; + case 's': + lstrip = true; + cmdp ++; + break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -420,6 +442,15 @@ int CmdPrintDemodBuff(const char *Cmd) { PrintAndLogEx(NORMAL, "Demodbuffer is empty"); return PM3_ESOFT; } + if (lstrip) { + char *buf = (char *)(DemodBuffer + offset); + length = (length > (DemodBufferLen - offset)) ? DemodBufferLen - offset : length; + uint32_t i; + for (i = 0; i < length; i++) { + if (buf[i] == 1) break; + } + offset += i; + } length = (length > (DemodBufferLen - offset)) ? DemodBufferLen - offset : length; if (hexMode) { @@ -870,7 +901,7 @@ static int CmdBitsamples(const char *Cmd) { return PM3_ETIMEOUT; } - for (size_t j = 0; j < sizeof(got); j++) { + for (size_t j = 0; j < ARRAYLEN(got); j++) { for (uint8_t k = 0; k < 8; k++) { if (got[j] & (1 << (7 - k))) GraphBuffer[cnt++] = 1; @@ -1611,7 +1642,7 @@ int CmdTuneSamples(const char *Cmd) { } if (test1 > 0) { - PrintAndLogEx(SUCCESS, "\nDisplaying LF tuning graph. Divisor 89 is 134khz, 95 is 125khz.\n\n"); + PrintAndLogEx(SUCCESS, "\nDisplaying LF tuning graph. Divisor 89 is 134kHz, 95 is 125kHz.\n\n"); GraphTraceLen = 256; ShowGraphWindow(); RepaintGraphWindow(); @@ -1631,11 +1662,20 @@ static int CmdLoad(const char *Cmd) { if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; memcpy(filename, Cmd, len); - FILE *f = fopen(filename, "r"); + char *path; + if (searchFile(&path, TRACES_SUBDIR, filename, ".pm3", true) != PM3_SUCCESS) { + if (searchFile(&path, TRACES_SUBDIR, filename, "", false) != PM3_SUCCESS) { + return PM3_EFILE; + } + } + + FILE *f = fopen(path, "r"); if (!f) { - PrintAndLogEx(WARNING, "couldn't open '%s'", filename); + PrintAndLogEx(WARNING, "couldn't open '%s'", path); + free(path); return PM3_EFILE; } + free(path); GraphTraceLen = 0; char line[80]; diff --git a/client/cmddata.h b/client/cmddata.h index 583af4dd1..a453fafb1 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -11,26 +11,9 @@ #ifndef CMDDATA_H__ #define CMDDATA_H__ -#include //size_t -#include //uint_32+ -#include //bool -#include "cmdparser.h" // for command_t +#include "common.h" -#include // also included in util.h -#include // also included in util.h -#include -#include // for CmdNorm INT_MIN && INT_MAX -#include "util.h" -#include "cmdmain.h" -#include "proxmark3.h"// sendcommand -#include "ui.h" // for show graph controls -#include "graph.h" // for graph data -#include "comms.h" -#include "lfdemod.h" // for demod code -#include "crc.h" // for pyramid checksum maxim -#include "crc16.h" // for FDXB demod checksum -#include "loclass/cipherutils.h" // for decimating samples in getsamples -#include "cmdlfem4x.h" // askem410xdecode +//#include //size_t int CmdData(const char *Cmd); diff --git a/client/cmdflashmem.c b/client/cmdflashmem.c index cfe122c50..ce5b37f44 100644 --- a/client/cmdflashmem.c +++ b/client/cmdflashmem.c @@ -9,9 +9,17 @@ //----------------------------------------------------------------------------- #include "cmdflashmem.h" +#include + +#include "cmdparser.h" // command_t + +#include "pmflash.h" +#include "fileutils.h" //saveFile +#include "comms.h" //getfromdevice +#include "cmdflashmemspiffs.h" // spiffs commands + #include "mbedtls/rsa.h" #include "mbedtls/sha1.h" -#include "mbedtls/base64.h" #define MCK 48000000 #define FLASH_MINFAST 24000000 //33000000 @@ -29,9 +37,9 @@ static int usage_flashmem_spibaud(void) { PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " SPI baudrate in MHz [24|48]"); PrintAndLogEx(NORMAL, " "); - PrintAndLogEx(NORMAL, " If >= 24Mhz, FASTREADS instead of READS instruction will be used."); - PrintAndLogEx(NORMAL, " Reading Flash ID will virtually always fail under 48Mhz setting"); - PrintAndLogEx(NORMAL, " Unless you know what you are doing, please stay at 24Mhz"); + PrintAndLogEx(NORMAL, " If >= 24MHz, FASTREADS instead of READS instruction will be used."); + PrintAndLogEx(NORMAL, " Reading Flash ID will virtually always fail under 48MHz setting"); + PrintAndLogEx(NORMAL, " Unless you know what you are doing, please stay at 24MHz"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " mem spibaud 48"); return PM3_SUCCESS; @@ -51,9 +59,9 @@ static int usage_flashmem_load(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " mem load f myfile"); // upload file myfile at default offset 0 PrintAndLogEx(NORMAL, " mem load f myfile o 1024"); // upload file myfile at offset 1024 - PrintAndLogEx(NORMAL, " mem load f default_keys m"); - PrintAndLogEx(NORMAL, " mem load f default_pwd t"); - PrintAndLogEx(NORMAL, " mem load f default_iclass_keys i"); + PrintAndLogEx(NORMAL, " mem load f mfc_default_keys m"); + PrintAndLogEx(NORMAL, " mem load f t55xx_default_pwds t"); + PrintAndLogEx(NORMAL, " mem load f iclass_default_keys i"); return PM3_SUCCESS; } static int usage_flashmem_dump(void) { @@ -201,21 +209,20 @@ static int CmdFlashMemLoad(const char *Cmd) { datalen += 2; break; case DICTIONARY_NONE: - res = loadFile(filename, ".bin", data, FLASH_MEM_MAX_SIZE, &datalen); - //int res = loadFileEML( filename, data, &datalen); - if (res) { + res = loadFile_safe(filename, ".bin", (void **)&data, &datalen); + if (res != PM3_SUCCESS) { free(data); return PM3_EFILE; } if (datalen > FLASH_MEM_MAX_SIZE) { - PrintAndLogDevice(ERR, "error, filesize is larger than available memory"); + PrintAndLogEx(ERR, "error, filesize is larger than available memory"); free(data); return PM3_EOVFLOW; } break; } - +// not needed when we transite to loadxxxx_safe methods.(iceman) uint8_t *newdata = realloc(data, datalen); if (newdata == NULL) { free(data); @@ -310,7 +317,7 @@ static int CmdFlashMemDump(const char *Cmd) { uint8_t *dump = calloc(len, sizeof(uint8_t)); if (!dump) { - PrintAndLogDevice(ERR, "error, cannot allocate memory "); + PrintAndLogEx(ERR, "error, cannot allocate memory "); return PM3_EMALLOC; } diff --git a/client/cmdflashmem.h b/client/cmdflashmem.h index b08164837..011b57a14 100644 --- a/client/cmdflashmem.h +++ b/client/cmdflashmem.h @@ -11,20 +11,7 @@ #ifndef CMDFLASHMEM_H__ #define CMDFLASHMEM_H__ -#include -#include -#include -#include -#include "pmflash.h" #include "common.h" -#include "proxmark3.h" -#include "ui.h" -#include "cmdparser.h" -#include "util.h" -#include "util_posix.h" // msclock -#include "loclass/fileutils.h" //saveFile -#include "comms.h" //getfromdevice -#include "cmdflashmemspiffs.h" // spiffs commands typedef enum { DICTIONARY_NONE = 0, diff --git a/client/cmdflashmemspiffs.c b/client/cmdflashmemspiffs.c index bc7a408bd..109f51ae1 100644 --- a/client/cmdflashmemspiffs.c +++ b/client/cmdflashmemspiffs.c @@ -9,9 +9,12 @@ //----------------------------------------------------------------------------- #include "cmdflashmemspiffs.h" -#include "mbedtls/base64.h" -#include "mbedtls/rsa.h" -#include "mbedtls/sha1.h" +#include + +#include "cmdparser.h" // command_t +#include "pmflash.h" +#include "fileutils.h" //saveFile +#include "comms.h" //getfromdevice static int CmdHelp(const char *Cmd); @@ -36,6 +39,13 @@ static int CmdFlashMemSpiFFSTest(const char *Cmd) { return PM3_SUCCESS; } +static int CmdFlashMemSpiFFSCheck(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + clearCommandBuffer(); + SendCommandNG(CMD_SPIFFS_CHECK, NULL, 0); + return PM3_SUCCESS; +} + static int CmdFlashMemSpiFFSTree(const char *Cmd) { (void)Cmd; // Cmd is not used so far clearCommandBuffer(); @@ -278,7 +288,7 @@ static int CmdFlashMemSpiFFSDump(const char *Cmd) { uint8_t *dump = calloc(len, sizeof(uint8_t)); if (!dump) { - PrintAndLogDevice(ERR, "error, cannot allocate memory "); + PrintAndLogEx(ERR, "error, cannot allocate memory "); return PM3_EMALLOC; } @@ -320,12 +330,15 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) { if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { PrintAndLogEx(FAILED, "Filename too long"); errors = true; - break; } cmdp += 2; break; case 'o': param_getstr(Cmd, cmdp + 1, destfilename, 32); + if (strlen(destfilename) == 0) { + PrintAndLogEx(FAILED, "Destination Filename missing or invalid"); + errors = true; + } cmdp += 2; break; default: @@ -335,42 +348,20 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) { } } - if (destfilename[0] == '\0') { - PrintAndLogEx(FAILED, "Destination Filename missing or invalid"); - errors = true; - } - // Validations - if (errors || cmdp == 0) { - usage_flashmemspiffs_load(); - return PM3_EINVARG; - } + if (errors || cmdp == 0) + return usage_flashmemspiffs_load(); size_t datalen = 0; - int res = 0; - uint8_t *data = calloc(FLASH_MEM_MAX_SIZE, sizeof(uint8_t)); + uint8_t *data = NULL; - res = loadFile(filename, "", data, FLASH_MEM_MAX_SIZE, &datalen); + int res = loadFile_safe(filename, "", (void **)&data, &datalen); // int res = loadFileEML( filename, data, &datalen); - if (res) { + if (res != PM3_SUCCESS) { free(data); return PM3_EFILE; } - if (datalen > FLASH_MEM_MAX_SIZE) { - PrintAndLogDevice(ERR, "error, filesize is larger than available memory"); - free(data); - return PM3_EOVFLOW; - } - - uint8_t *newdata = realloc(data, datalen); - if (newdata == NULL) { - free(data); - return PM3_EMALLOC; - } else { - data = newdata; - } - // We want to mount before multiple operation so the lazy writes/append will not // trigger a mount + umount each loop iteration (lazy ops device side) SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0); @@ -415,6 +406,7 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) { if (!isok) { conn.block_after_ACK = false; PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent); + free(data); return PM3_EFLASH; } } @@ -436,6 +428,7 @@ static command_t CommandTable[] = { "copy", CmdFlashMemSpiFFSCopy, IfPm3Flash, "Copy a file to another (destructively) in SPIFFS FileSystem in FlashMEM (spiffs)" }, + {"check", CmdFlashMemSpiFFSCheck, IfPm3Flash, "Check/try to defrag faulty/fragmented Filesystem"}, {"dump", CmdFlashMemSpiFFSDump, IfPm3Flash, "Dump a file from SPIFFS FileSystem in FlashMEM (spiffs)"}, {"info", CmdFlashMemSpiFFSInfo, IfPm3Flash, "Print filesystem info and usage statistics (spiffs)"}, {"load", CmdFlashMemSpiFFSLoad, IfPm3Flash, "Upload file into SPIFFS Filesystem (spiffs)"}, diff --git a/client/cmdflashmemspiffs.h b/client/cmdflashmemspiffs.h index b3589ce86..d2dee17ab 100644 --- a/client/cmdflashmemspiffs.h +++ b/client/cmdflashmemspiffs.h @@ -11,19 +11,7 @@ #ifndef CMDFLASHMEMSPIFFS_H__ #define CMDFLASHMEMSPIFFS_H__ -#include -#include -#include -#include -#include "pmflash.h" #include "common.h" -#include "proxmark3.h" -#include "ui.h" -#include "cmdparser.h" -#include "util.h" -#include "util_posix.h" // msclock -#include "loclass/fileutils.h" //saveFile -#include "comms.h" //getfromdevice int CmdFlashMemSpiFFS(const char *Cmd); diff --git a/client/cmdhf.c b/client/cmdhf.c index 03a5c1681..8326d988f 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -8,7 +8,29 @@ //----------------------------------------------------------------------------- // High frequency commands //----------------------------------------------------------------------------- -#include "cmdhf.h" +//#include "cmdhf.h" + +#include // tolower + +#include "cmdparser.h" // command_t +#include "comms.h" // clearCommandBuffer + +#include "cmdhf14a.h" // ISO14443-A +#include "cmdhf14b.h" // ISO14443-B +#include "cmdhf15.h" // ISO15693 +#include "cmdhfepa.h" +#include "cmdhflegic.h" // LEGIC +#include "cmdhficlass.h" // ICLASS +#include "cmdhfmf.h" // CLASSIC +#include "cmdhfmfu.h" // ULTRALIGHT/NTAG etc +#include "cmdhfmfp.h" // Mifare Plus +#include "cmdhfmfdes.h" // DESFIRE +#include "cmdhftopaz.h" // TOPAZ +#include "cmdhffelica.h" // ISO18092 / FeliCa +#include "cmdhffido.h" // FIDO authenticators +#include "cmdhfthinfilm.h" // Thinfilm +#include "cmdtrace.h" // trace list +#include "ui.h" static int CmdHelp(const char *Cmd); @@ -18,7 +40,7 @@ static int usage_hf_search() { PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - This help"); PrintAndLogEx(NORMAL, ""); - return 0; + return PM3_SUCCESS; } static int usage_hf_sniff() { @@ -34,7 +56,7 @@ static int usage_hf_sniff() { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf sniff"); PrintAndLogEx(NORMAL, " hf sniff 1000 0"); - return 0; + return PM3_SUCCESS; } static int usage_hf_tune() { @@ -44,7 +66,7 @@ static int usage_hf_tune() { PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " - number of iterations (default: infinite)"); PrintAndLogEx(NORMAL, ""); - return 0; + return PM3_SUCCESS; } int CmdHFSearch(const char *Cmd) { @@ -54,42 +76,78 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INFO, "Checking for known tags...\n"); - if (infoHF14A(false, false) > 0) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-A tag") " found\n"); - return 1; + PrintAndLogEx(INPLACE, "Searching for ThinFilm tag..."); + if (IfPm3NfcBarcode()) { + if (infoThinFilm(false) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Thinfilm tag") " found\n"); + return PM3_SUCCESS; + } } - if (readHF15Uid(false) == 1) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO15693 tag") " found\n"); - return 1; + + PrintAndLogEx(INPLACE, "Searching for ISO14443-A tag..."); + if (IfPm3Iso14443a()) { + if (infoHF14A(false, false) > 0) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-A tag") " found\n"); + return PM3_SUCCESS; + } } - if (readLegicUid(false) == 0) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LEGIC tag") " found\n"); - return 1; + + PrintAndLogEx(INPLACE, "Searching for ISO15693 tag..."); + if (IfPm3Iso15693()) { + if (readHF15Uid(false) == 1) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO15693 tag") " found\n"); + DropField(); + return PM3_SUCCESS; + } + // until refactoring of ISO15693 cmds, this is needed. + DropField(); } - if (readTopazUid() == 0) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Topaz tag") " found\n"); - return 1; + + PrintAndLogEx(INPLACE, "Searching for LEGIC tag..."); + if (IfPm3Legicrf()) { + if (readLegicUid(false) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LEGIC tag") " found\n"); + return PM3_SUCCESS; + } } + + PrintAndLogEx(INPLACE, "Searching for Topaz tag..."); + if (IfPm3Iso14443a()) { + if (readTopazUid() == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Topaz tag") " found\n"); + return PM3_SUCCESS; + } + } + // 14b and iclass is the longest test (put last) - if (readHF14B(false) == 1) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-B tag") " found\n"); - return 1; - } - if (readIclass(false, false) == 1) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("iClass tag / PicoPass tag") " found\n"); - return 1; + PrintAndLogEx(INPLACE, "Searching for ISO14443-B tag..."); + if (IfPm3Iso14443a()) { + if (readHF14B(false) == 1) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-B tag") " found\n"); + return PM3_SUCCESS; + } } - /* - ans = CmdHFFelicaReader("s"); - if (ans) { - PrintAndLogEx(NORMAL, "\nValid " _GREEN_("ISO18092 / FeliCa tag") " found\n"); - return ans; + PrintAndLogEx(INPLACE, "Searching for iClass / PicoPass tag..."); + if (IfPm3Iclass()) { + if (readIclass(false, false) == 1) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("iClass tag / PicoPass tag") " found\n"); + return PM3_SUCCESS; + } } - */ - PrintAndLogEx(FAILED, "\nno known/supported 13.56 MHz tags found\n"); - return 0; + + //if (IfPm3Felica()) { + // ans = CmdHFFelicaReader("s"); + // if (ans) { + // PrintAndLogEx(NORMAL, "\nValid " _GREEN_("ISO18092 / FeliCa tag") " found\n"); + // return ans; + // } + //} + + + PrintAndLogEx(FAILED, "\nNo known/supported 13.56 MHz tags found\n"); + return PM3_ESOFT; } int CmdHFTune(const char *Cmd) { @@ -119,7 +177,7 @@ int CmdHFTune(const char *Cmd) { } if ((resp.status == PM3_EOPABORTED) || (resp.length != sizeof(uint16_t))) break; - uint16_t volt = resp.data.asDwords[0]; + uint16_t volt = resp.data.asDwords[0] & 0xFFFF; PrintAndLogEx(INPLACE, "%u mV / %5u V", volt, (uint16_t)(volt / 1000)); } mode[0] = 3; @@ -141,8 +199,8 @@ int CmdHFSniff(const char *Cmd) { int skiptriggers = param_get32ex(Cmd, 1, 0, 10); clearCommandBuffer(); - SendCommandMIX(CMD_HF_SNIFFER, skippairs, skiptriggers, 0, NULL, 0); - return 0; + SendCommandMIX(CMD_HF_SNIFF, skippairs, skiptriggers, 0, NULL, 0); + return PM3_SUCCESS; } static command_t CommandTable[] = { @@ -160,9 +218,10 @@ static command_t CommandTable[] = { {"mfdes", CmdHFMFDes, AlwaysAvailable, "{ MIFARE Desfire RFIDs... }"}, {"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"}, {"fido", CmdHFFido, AlwaysAvailable, "{ FIDO and FIDO2 authenticators... }"}, + {"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"}, {"list", CmdTraceList, AlwaysAvailable, "List protocol data in trace buffer"}, {"tune", CmdHFTune, IfPm3Present, "Continuously measure HF antenna tuning"}, - {"search", CmdHFSearch, AlwaysAvailable, "Search for known HF tags [preliminary]"}, + {"search", CmdHFSearch, AlwaysAvailable, "Search for known HF tags"}, {"sniff", CmdHFSniff, IfPm3Hfsniff, " Generic HF Sniff"}, {NULL, NULL, NULL, NULL} }; @@ -175,5 +234,5 @@ int CmdHF(const char *Cmd) { int CmdHelp(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdsHelp(CommandTable); - return 0; + return PM3_SUCCESS; } diff --git a/client/cmdhf.h b/client/cmdhf.h index 4540caf3d..14ded8e0e 100644 --- a/client/cmdhf.h +++ b/client/cmdhf.h @@ -11,27 +11,7 @@ #ifndef CMDHF_H__ #define CMDHF_H__ -#include -#include -#include -#include "proxmark3.h" -#include "graph.h" -#include "ui.h" -#include "cmdparser.h" -#include "cmdhf14a.h" // ISO14443-A -#include "cmdhf14b.h" // ISO14443-B -#include "cmdhf15.h" // ISO15693 -#include "cmdhfepa.h" -#include "cmdhflegic.h" // LEGIC -#include "cmdhficlass.h" // ICLASS -#include "cmdhfmf.h" // CLASSIC -#include "cmdhfmfu.h" // ULTRALIGHT/NTAG etc -#include "cmdhfmfp.h" // Mifare Plus -#include "cmdhfmfdes.h" // DESFIRE -#include "cmdhftopaz.h" // TOPAZ -#include "cmdhffelica.h" // ISO18092 / FeliCa -#include "cmdhffido.h" // FIDO authenticators -#include "cmdtrace.h" // trace list +#include "common.h" int CmdHF(const char *Cmd); int CmdHFTune(const char *Cmd); diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index f92a35370..b21e8dbd7 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -12,6 +12,21 @@ //----------------------------------------------------------------------------- #include "cmdhf14a.h" +#include +#include + +#include "cmdparser.h" // command_t +#include "commonutil.h" // ARRAYLEN +#include "comms.h" // clearCommandBuffer +#include "cmdtrace.h" +#include "cliparser/cliparser.h" +#include "cmdhfmf.h" +#include "cmdhfmfu.h" +#include "emv/emvcore.h" +#include "ui.h" +#include "crc16.h" +#include "util_posix.h" // msclock + bool APDUInFramingEnable = true; static int CmdHelp(const char *Cmd); @@ -73,7 +88,7 @@ static const manufactureName manufactureMapping[] = { { 0x34, "Mikron JSC Russia" }, { 0x35, "Fraunhofer Institute for Photonic Microsystems Germany" }, { 0x36, "IDS Microchip AG Switzerland" }, - { 0x37, "Kovio USA" }, + { 0x37, "Thinfilm - Kovio USA" }, { 0x38, "HMT Microelectronic Ltd Switzerland" }, { 0x39, "Silicon Craft Technology Thailand" }, { 0x3A, "Advanced Film Device Inc. Japan" }, @@ -118,7 +133,7 @@ static const manufactureName manufactureMapping[] = { { 0x61, "Wearlinks Technology Inc. China" }, { 0x62, "Userstar Information Systems Co., Ltd Taiwan" }, { 0x63, "Pragmatic Printing Ltd. UK" }, - { 0x64, "Associacao do Laboratorio de Sistemas Integraveis Tecnologico – LSI-TEC Brazil" }, + { 0x64, "Associacao do Laboratorio de Sistemas Integraveis Tecnologico - LSI-TEC Brazil" }, { 0x65, "Tendyron Corporation China" }, { 0x66, "MUTO Smart Co., Ltd. Korea" }, { 0x67, "ON Semiconductor USA" }, @@ -139,14 +154,13 @@ static const manufactureName manufactureMapping[] = { const char *getTagInfo(uint8_t uid) { int i; - int len = sizeof(manufactureMapping) / sizeof(manufactureName); - for (i = 0; i < len; ++i) + for (i = 0; i < ARRAYLEN(manufactureMapping); ++i) if (uid == manufactureMapping[i].uid) return manufactureMapping[i].desc; //No match, return default - return manufactureMapping[len - 1].desc; + return manufactureMapping[ARRAYLEN(manufactureMapping) - 1].desc; } // iso14a apdu input frame length @@ -228,7 +242,7 @@ static int CmdHF14AList(const char *Cmd) { } int Hf14443_4aGetCardData(iso14a_card_select_t *card) { - SendCommandMIX(CMD_READER_ISO_14443a, ISO14A_CONNECT, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); PacketResponseNG resp; WaitForResponse(CMD_ACK, &resp); @@ -298,7 +312,7 @@ static int CmdHF14AReader(const char *Cmd) { cm |= ISO14A_NO_DISCONNECT; clearCommandBuffer(); - SendCommandMIX(CMD_READER_ISO_14443a, cm, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443A_READER, cm, 0, 0, NULL, 0); if (ISO14A_CONNECT & cm) { PacketResponseNG resp; @@ -381,7 +395,7 @@ static int CmdHF14ACUIDs(const char *Cmd) { } // execute anticollision procedure - SendCommandMIX(CMD_READER_ISO_14443a, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0); PacketResponseNG resp; WaitForResponse(CMD_ACK, &resp); @@ -482,13 +496,13 @@ int CmdHF14ASim(const char *Cmd) { memcpy(payload.uid, uid, uidlen); clearCommandBuffer(); - SendCommandNG(CMD_SIMULATE_TAG_ISO_14443a, (uint8_t *)&payload, sizeof(payload)); + SendCommandNG(CMD_HF_ISO14443A_SIMULATE, (uint8_t *)&payload, sizeof(payload)); PacketResponseNG resp; PrintAndLogEx(SUCCESS, "press pm3-button to abort simulation"); while (!kbd_enter_pressed()) { - if (WaitForResponseTimeout(CMD_SIMULATE_MIFARE_CARD, &resp, 1500) == 0) continue; + if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0) continue; if (resp.status != PM3_SUCCESS) break; if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK) break; @@ -512,7 +526,7 @@ int CmdHF14ASniff(const char *Cmd) { if (ctmp == 'r') param |= 0x02; } clearCommandBuffer(); - SendCommandNG(CMD_SNIFF_ISO_14443a, (uint8_t *)¶m, sizeof(uint8_t)); + SendCommandNG(CMD_HF_ISO14443A_SNIFF, (uint8_t *)¶m, sizeof(uint8_t)); return PM3_SUCCESS; } @@ -526,7 +540,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav PacketResponseNG resp; // Anticollision + SELECT card - SendCommandMIX(CMD_READER_ISO_14443a, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(ERR, "Proxmark3 connection timeout."); return 1; @@ -546,7 +560,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav if (resp.oldarg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision // get ATS uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 - SendCommandOLD(CMD_READER_ISO_14443a, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0, rats, 2); + SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0, rats, 2); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(ERR, "Proxmark3 connection timeout."); return 1; @@ -565,7 +579,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav uint8_t data[PM3_CMD_DATA_SIZE] = { 0x0a | responseNum, 0x00}; responseNum ^= 1; memcpy(&data[2], datain, datainlen & 0xFFFF); - SendCommandOLD(CMD_READER_ISO_14443a, ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF) + 2, 0, data, (datainlen & 0xFFFF) + 2); + SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF) + 2, 0, data, (datainlen & 0xFFFF) + 2); uint8_t *recv; PacketResponseNG resp; @@ -620,7 +634,7 @@ static int SelectCard14443_4(bool disconnect, iso14a_card_select_t *card) { DropField(); // Anticollision + SELECT card - SendCommandMIX(CMD_READER_ISO_14443a, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(ERR, "Proxmark3 connection timeout."); return 1; @@ -640,7 +654,7 @@ static int SelectCard14443_4(bool disconnect, iso14a_card_select_t *card) { if (resp.oldarg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision // get ATS uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 - SendCommandOLD(CMD_READER_ISO_14443a, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, sizeof(rats), 0, rats, sizeof(rats)); + SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, sizeof(rats), 0, rats, sizeof(rats)); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(ERR, "Proxmark3 connection timeout."); return 1; @@ -695,9 +709,9 @@ static int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool // here length PM3_CMD_DATA_SIZE=512 // timeout must be authomatically set by "get ATS" if (datain) - SendCommandOLD(CMD_READER_ISO_14443a, ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, (datainlen & 0xFFFF), 0, datain, datainlen & 0xFFFF); + SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, (datainlen & 0xFFFF), 0, datain, datainlen & 0xFFFF); else - SendCommandMIX(CMD_READER_ISO_14443a, ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, 0, 0, NULL, 0); PacketResponseNG resp; @@ -1087,7 +1101,7 @@ static int CmdHF14ACmdRaw(const char *Cmd) { datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen; clearCommandBuffer(); - SendCommandOLD(CMD_READER_ISO_14443a, flags, (datalen & 0xFFFF) | ((uint32_t)(numbits << 16)), argtimeout, data, datalen & 0xFFFF); + SendCommandOLD(CMD_HF_ISO14443A_READER, flags, (datalen & 0xFFFF) | ((uint32_t)(numbits << 16)), argtimeout, data, datalen & 0xFFFF); if (reply) { int res = 0; @@ -1150,7 +1164,7 @@ static int CmdHF14AAntiFuzz(const char *Cmd) { CLIParserFree(); clearCommandBuffer(); - SendCommandMIX(CMD_ANTIFUZZ_ISO_14443a, arg0, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443A_ANTIFUZZ, arg0, 0, 0, NULL, 0); return 0; } @@ -1213,7 +1227,7 @@ int CmdHF14A(const char *Cmd) { int infoHF14A(bool verbose, bool do_nack_test) { clearCommandBuffer(); - SendCommandMIX(CMD_READER_ISO_14443a, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { if (verbose) PrintAndLogEx(WARNING, "iso14443a card select failed"); @@ -1265,7 +1279,7 @@ int infoHF14A(bool verbose, bool do_nack_test) { // reconnect for further tests clearCommandBuffer(); - SendCommandMIX(CMD_READER_ISO_14443a, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); WaitForResponse(CMD_ACK, &resp); memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); @@ -1335,7 +1349,7 @@ int infoHF14A(bool verbose, bool do_nack_test) { if (select_status == 2) { uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 clearCommandBuffer(); - SendCommandOLD(CMD_READER_ISO_14443a, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0, rats, sizeof(rats)); + SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0, rats, sizeof(rats)); WaitForResponse(CMD_ACK, &resp); memcpy(card.ats, resp.data.asBytes, resp.oldarg[0]); diff --git a/client/cmdhf14a.h b/client/cmdhf14a.h index d5626d995..9c42b9afd 100644 --- a/client/cmdhf14a.h +++ b/client/cmdhf14a.h @@ -12,25 +12,9 @@ #ifndef CMDHF14A_H__ #define CMDHF14A_H__ -#include -#include -#include -#include -#include -#include -#include "proxmark3.h" #include "common.h" -#include "ui.h" -#include "util.h" -#include "cmdparser.h" -#include "cmdmain.h" -#include "mifare.h" -#include "cmdhfmf.h" -#include "cmdhfmfu.h" -#include "cmdhf.h" // list cmd -#include "mifare/mifarehost.h" -#include "emv/apduinfo.h" -#include "emv/emvcore.h" + +#include "mifare.h" // structs // structure and database for uid -> tagtype lookups typedef struct { diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index c95494b7a..57f275a31 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -11,6 +11,17 @@ #include "cmdhf14b.h" +#include +#include "fileutils.h" + +#include "cmdparser.h" // command_t +#include "comms.h" // clearCommandBuffer +#include "cmdtrace.h" + +#include "crc16.h" +#include "cmdhf14a.h" +#include "protocols.h" // definitions of ISO14B protocol + #define TIMEOUT 2000 static int CmdHelp(const char *Cmd); @@ -109,13 +120,13 @@ static int usage_hf_14b_dump(void) { /* static void switch_on_field_14b(void) { clearCommandBuffer(); - SendCommandMIX(CMD_ISO_14443B_COMMAND, ISO14B_CONNECT, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT, 0, 0, NULL, 0); } */ static int switch_off_field_14b(void) { clearCommandBuffer(); - SendCommandMIX(CMD_ISO_14443B_COMMAND, ISO14B_DISCONNECT, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_DISCONNECT, 0, 0, NULL, 0); return 0; } @@ -170,7 +181,7 @@ static int CmdHF14BSim(const char *Cmd) { } clearCommandBuffer(); - SendCommandMIX(CMD_SIMULATE_TAG_ISO_14443B, pupi, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443B_SIMULATE, pupi, 0, 0, NULL, 0); return 0; } @@ -180,7 +191,7 @@ static int CmdHF14BSniff(const char *Cmd) { if (cmdp == 'h') return usage_hf_14b_sniff(); clearCommandBuffer(); - SendCommandNG(CMD_SNIFF_ISO_14443B, NULL, 0); + SendCommandNG(CMD_HF_ISO14443B_SNIFF, NULL, 0); return 0; } @@ -274,7 +285,7 @@ static int CmdHF14BCmdRaw(const char *Cmd) { datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen; clearCommandBuffer(); - SendCommandOLD(CMD_ISO_14443B_COMMAND, flags, datalen, time_wait, data, datalen); + SendCommandOLD(CMD_HF_ISO14443B_COMMAND, flags, datalen, time_wait, data, datalen); if (!reply) return 1; @@ -301,7 +312,7 @@ static bool get_14b_UID(iso14b_card_select_t *card) { while (retry--) { clearCommandBuffer(); - SendCommandMIX(CMD_ISO_14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0); if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { uint8_t status = resp.oldarg[0]; @@ -317,7 +328,7 @@ static bool get_14b_UID(iso14b_card_select_t *card) { while (retry--) { clearCommandBuffer(); - SendCommandMIX(CMD_ISO_14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { uint8_t status = resp.oldarg[0]; @@ -501,7 +512,7 @@ static bool HF14B_Std_Info(bool verbose) { // 14b get and print UID only (general info) clearCommandBuffer(); - SendCommandMIX(CMD_ISO_14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { @@ -541,7 +552,7 @@ static bool HF14B_Std_Info(bool verbose) { static bool HF14B_ST_Info(bool verbose) { clearCommandBuffer(); - SendCommandMIX(CMD_ISO_14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { @@ -597,7 +608,7 @@ static bool HF14B_ST_Reader(bool verbose) { // SRx get and print general info about SRx chip from UID clearCommandBuffer(); - SendCommandMIX(CMD_ISO_14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); @@ -636,7 +647,7 @@ static bool HF14B_Std_Reader(bool verbose) { // 14b get and print UID only (general info) clearCommandBuffer(); - SendCommandMIX(CMD_ISO_14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { @@ -680,7 +691,7 @@ static bool HF14B_Other_Reader() { // uint32_t flags = ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_RAW | ISO14B_APPEND_CRC; // clearCommandBuffer(); - // SendCommandOLD(CMD_ISO_14443B_COMMAND, flags, datalen, 0, data, datalen); + // SendCommandOLD(CMD_HF_ISO14443B_COMMAND, flags, datalen, 0, data, datalen); // PacketResponseNG resp; // WaitForResponse(CMD_ACK,&resp); @@ -694,7 +705,7 @@ static bool HF14B_Other_Reader() { // data[0] = ISO14443B_AUTHENTICATE; // clearCommandBuffer(); - // SendCommandOLD(CMD_ISO_14443B_COMMAND, flags, 1, 0, data, 1); + // SendCommandOLD(CMD_HF_ISO14443B_COMMAND, flags, 1, 0, data, 1); // PacketResponseNG resp; // WaitForResponse(CMD_ACK, &resp); @@ -708,7 +719,7 @@ static bool HF14B_Other_Reader() { // data[0] = ISO14443B_RESET; // clearCommandBuffer(); - // SendCommandOLD(CMD_ISO_14443B_COMMAND, flags, 1, 0, data, 1); + // SendCommandOLD(CMD_HF_ISO14443B_COMMAND, flags, 1, 0, data, 1); // PacketResponseNG resp; // WaitForResponse(CMD_ACK, &resp); @@ -745,7 +756,7 @@ static int CmdHF14BReadSri(const char *Cmd) { uint8_t blocks = (tagtype == 1) ? 0x7F : 0x0F; clearCommandBuffer(); - SendCommandMIX(CMD_READ_SRI_TAG, blocks, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_SRI_READ, blocks, 0, 0, NULL, 0); return 0; } // New command to write a SRI512/SRIX4K tag. @@ -884,7 +895,7 @@ static int CmdHF14BDump(const char *Cmd) { PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_ISO_14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0, NULL, 0); //select if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { @@ -901,7 +912,7 @@ static int CmdHF14BDump(const char *Cmd) { req[1] = blocknum; clearCommandBuffer(); - SendCommandOLD(CMD_ISO_14443B_COMMAND, ISO14B_APPEND_CRC | ISO14B_RAW, 2, 0, req, sizeof(req)); + SendCommandOLD(CMD_HF_ISO14443B_COMMAND, ISO14B_APPEND_CRC | ISO14B_RAW, 2, 0, req, sizeof(req)); if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { diff --git a/client/cmdhf14b.h b/client/cmdhf14b.h index 2180e2088..2058ea8ba 100644 --- a/client/cmdhf14b.h +++ b/client/cmdhf14b.h @@ -11,23 +11,7 @@ #ifndef CMDHF14B_H__ #define CMDHF14B_H__ -#include -#include -#include -#include -#include "crc16.h" -#include "proxmark3.h" -#include "graph.h" -#include "util.h" -#include "ui.h" -#include "cmdparser.h" -#include "cmdmain.h" -#include "cmdhf14a.h" -#include "cmdhf.h" -#include "prng.h" -#include "mbedtls/sha1.h" -#include "mifare.h" // structs/enum for ISO14B -#include "protocols.h" // definitions of ISO14B protocol +#include "common.h" int CmdHF14B(const char *Cmd); diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 33c3957fe..eb8cb6f87 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -24,6 +24,19 @@ // variant, but offers the possibility to analyze the waveforms directly. #include "cmdhf15.h" +#include + +#include "cmdparser.h" // command_t +#include "commonutil.h" // ARRAYLEN +#include "comms.h" // clearCommandBuffer +#include "cmdtrace.h" +#include "iso15693tools.h" + +#include "graph.h" +#include "crc16.h" // iso15 crc +#include "cmddata.h" // getsamples +#include "fileutils.h" // savefileEML + #define FrameSOF Iso15693FrameSOF #define Logic0 Iso15693Logic0 #define Logic1 Iso15693Logic1 @@ -212,7 +225,7 @@ static int getUID(uint8_t *buf) { for (retry = 0; retry < 3; retry++) { clearCommandBuffer(); - SendCommandOLD(CMD_ISO_15693_COMMAND, sizeof(data), 1, 1, data, sizeof(data)); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, sizeof(data), 1, 1, data, sizeof(data)); if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { @@ -583,7 +596,7 @@ static int CmdHF15Samples(const char *Cmd) { if (cmdp == 'h') return usage_15_samples(); clearCommandBuffer(); - SendCommandNG(CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693, NULL, 0); + SendCommandNG(CMD_HF_ISO15693_ACQ_RAW_ADC, NULL, 0); getSamples(0, false); return 0; @@ -617,7 +630,7 @@ static int CmdHF15Info(const char *Cmd) { //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(req, reqlen) ); clearCommandBuffer(); - SendCommandOLD(CMD_ISO_15693_COMMAND, reqlen, arg1, 1, req, reqlen); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(WARNING, "iso15693 card select failed"); @@ -680,7 +693,7 @@ static int CmdHF15Record(const char *Cmd) { if (cmdp == 'h') return usage_15_record(); clearCommandBuffer(); - SendCommandNG(CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693, NULL, 0); + SendCommandNG(CMD_HF_ISO15693_RAWADC, NULL, 0); return 0; } @@ -707,7 +720,7 @@ static int CmdHF15Sim(const char *Cmd) { PrintAndLogEx(SUCCESS, "Starting simulating UID %s", sprint_hex(uid, sizeof(uid))); clearCommandBuffer(); - SendCommandOLD(CMD_SIMTAG_ISO_15693, 0, 0, 0, uid, 8); + SendCommandOLD(CMD_HF_ISO15693_SIMULATE, 0, 0, 0, uid, 8); return 0; } @@ -721,7 +734,7 @@ static int CmdHF15Afi(const char *Cmd) { PrintAndLogEx(SUCCESS, "press pm3-button to cancel"); clearCommandBuffer(); - SendCommandMIX(CMD_ISO_15693_FIND_AFI, strtol(Cmd, NULL, 0), 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO15693_FINDAFI, strtol(Cmd, NULL, 0), 0, 0, NULL, 0); return 0; } @@ -798,7 +811,7 @@ static int CmdHF15Dump(const char *Cmd) { AddCrc15(req, 11); clearCommandBuffer(); - SendCommandOLD(CMD_ISO_15693_COMMAND, sizeof(req), 1, 1, req, sizeof(req)); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, sizeof(req), 1, 1, req, sizeof(req)); if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { @@ -915,7 +928,7 @@ static int CmdHF15Raw(const char *Cmd) { } clearCommandBuffer(); - SendCommandOLD(CMD_ISO_15693_COMMAND, datalen, fast, reply, data, datalen); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, datalen, fast, reply, data, datalen); if (reply) { if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { @@ -970,7 +983,7 @@ static int CmdHF15Readmulti(const char *Cmd) { reqlen += 2; clearCommandBuffer(); - SendCommandOLD(CMD_ISO_15693_COMMAND, reqlen, arg1, 1, req, reqlen); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(FAILED, "iso15693 card select failed"); @@ -1048,7 +1061,7 @@ static int CmdHF15Read(const char *Cmd) { reqlen += 2; clearCommandBuffer(); - SendCommandOLD(CMD_ISO_15693_COMMAND, reqlen, arg1, 1, req, reqlen); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(NORMAL, "iso15693 card select failed"); @@ -1131,7 +1144,7 @@ static int CmdHF15Write(const char *Cmd) { PrintAndLogEx(NORMAL, "iso15693 writing to page %02d (0x%02X) | data ", pagenum, pagenum); clearCommandBuffer(); - SendCommandOLD(CMD_ISO_15693_COMMAND, reqlen, arg1, 1, req, reqlen); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(FAILED, "iso15693 card timeout, data may be written anyway"); @@ -1352,7 +1365,7 @@ static int CmdHF15CSetUID(const char *Cmd) { AddCrc15(data[i], 7); clearCommandBuffer(); - SendCommandOLD(CMD_ISO_15693_COMMAND, sizeof(data[i]), fast, reply, data[i], sizeof(data[i])); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, sizeof(data[i]), fast, reply, data[i], sizeof(data[i])); if (reply) { if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { diff --git a/client/cmdhf15.h b/client/cmdhf15.h index 049e9f68f..b3f64ac70 100644 --- a/client/cmdhf15.h +++ b/client/cmdhf15.h @@ -11,20 +11,7 @@ #ifndef CMDHF15_H__ #define CMDHF15_H__ -#include -#include -#include -#include - -#include "proxmark3.h" -#include "graph.h" -#include "ui.h" -#include "util.h" -#include "cmdparser.h" -#include "crc16.h" // iso15 crc -#include "cmdmain.h" -#include "cmddata.h" // getsamples -#include "loclass/fileutils.h" // savefileEML +#include "common.h" int CmdHF15(const char *Cmd); diff --git a/client/cmdhfepa.c b/client/cmdhfepa.c index 9aeaabefd..b6329bef9 100644 --- a/client/cmdhfepa.c +++ b/client/cmdhfepa.c @@ -9,6 +9,18 @@ //----------------------------------------------------------------------------- #include "cmdhfepa.h" +#include +#include +#include +#include +#include + +#include "cmdparser.h" // command_t +#include "commonutil.h" // ARRAYLEN +#include "comms.h" // clearCommandBuffer +#include "ui.h" +#include "util_posix.h" + static int CmdHelp(const char *Cmd); // Perform (part of) the PACE protocol @@ -32,7 +44,7 @@ static int CmdHFEPACollectPACENonces(const char *Cmd) { for (uint32_t i = 0; i < n; i++) { // execute PACE clearCommandBuffer(); - SendCommandMIX(CMD_EPA_PACE_COLLECT_NONCE, (int)m, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_EPA_COLLECT_NONCE, (int)m, 0, 0, NULL, 0); PacketResponseNG resp; WaitForResponse(CMD_ACK, &resp); @@ -75,7 +87,7 @@ static int CmdHFEPAPACEReplay(const char *Cmd) { int skip = 0, skip_add = 0, scan_return; // for each APDU - for (int i = 0; i < sizeof(apdu_lengths); i++) { + for (int i = 0; i < ARRAYLEN(apdu_lengths); i++) { // scan to next space or end of string while (Cmd[skip] != ' ' && Cmd[skip] != '\0') { // convert @@ -96,7 +108,7 @@ static int CmdHFEPAPACEReplay(const char *Cmd) { // break on EOF if (Cmd[skip] == '\0') { - if (i < sizeof(apdu_lengths) - 1) { + if (i < ARRAYLEN(apdu_lengths) - 1) { PrintAndLogEx(NORMAL, (char *)usage_msg); return 0; @@ -111,7 +123,7 @@ static int CmdHFEPAPACEReplay(const char *Cmd) { uint8_t data[PM3_CMD_DATA_SIZE]; // fast push mode conn.block_after_ACK = true; - for (int i = 0; i < sizeof(apdu_lengths); i++) { + for (int i = 0; i < ARRAYLEN(apdu_lengths); i++) { // transfer the APDU in several parts if necessary for (int j = 0; j * sizeof(data) < apdu_lengths[i]; j++) { // amount of data in this packet @@ -119,7 +131,7 @@ static int CmdHFEPAPACEReplay(const char *Cmd) { if (packet_length > sizeof(data)) { packet_length = sizeof(data); } - if ((i == sizeof(apdu_lengths) - 1) && (j * sizeof(data) >= apdu_lengths[i] - 1)) { + if ((i == ARRAYLEN(apdu_lengths) - 1) && (j * sizeof(data) >= apdu_lengths[i] - 1)) { // Disable fast mode on last packet conn.block_after_ACK = false; } @@ -130,7 +142,7 @@ static int CmdHFEPAPACEReplay(const char *Cmd) { clearCommandBuffer(); // arg0: APDU number // arg1: offset into the APDU - SendCommandOLD(CMD_EPA_PACE_REPLAY, i + 1, j * sizeof(data), packet_length, data, packet_length); + SendCommandOLD(CMD_HF_EPA_REPLAY, i + 1, j * sizeof(data), packet_length, data, packet_length); WaitForResponse(CMD_ACK, &resp); if (resp.oldarg[0] != 0) { PrintAndLogEx(WARNING, "Transfer of APDU #%d Part %d failed!", i, j); @@ -141,7 +153,7 @@ static int CmdHFEPAPACEReplay(const char *Cmd) { // now perform the replay clearCommandBuffer(); - SendCommandMIX(CMD_EPA_PACE_REPLAY, 0, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_EPA_REPLAY, 0, 0, 0, NULL, 0); WaitForResponse(CMD_ACK, &resp); if (resp.oldarg[0] != 0) { PrintAndLogEx(NORMAL, "\nPACE replay failed in step %u!", (uint32_t)resp.oldarg[0]); diff --git a/client/cmdhfepa.h b/client/cmdhfepa.h index c08fa8ea0..da21630cd 100644 --- a/client/cmdhfepa.h +++ b/client/cmdhfepa.h @@ -11,19 +11,7 @@ #ifndef CMDHFEPA_H__ #define CMDHFEPA_H__ -#include -#include -#include -#include -#include -#include "util.h" -#include "proxmark3.h" #include "common.h" -#include "ui.h" -#include "cmdparser.h" -#include "cmdmain.h" -#include "util_posix.h" - int CmdHFEPA(const char *Cmd); diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 5a6f1d33a..c3681bf60 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -9,8 +9,22 @@ //----------------------------------------------------------------------------- #include "cmdhffelica.h" +#include +#include +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "cmdtrace.h" +#include "crc16.h" + +#include "ui.h" +#include "mifare.h" // felica_card_select_t struct + static int CmdHelp(const char *Cmd); +/* static int usage_hf_felica_sim(void) { PrintAndLogEx(NORMAL, "\n Emulating ISO/18092 FeliCa tag \n"); PrintAndLogEx(NORMAL, "Usage: hf felica sim [h] t [v]"); @@ -23,6 +37,7 @@ static int usage_hf_felica_sim(void) { PrintAndLogEx(NORMAL, " hf felica sim t 1 "); return 0; } +*/ static int usage_hf_felica_sniff(void) { PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer."); PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list felica'"); @@ -78,6 +93,8 @@ static int CmdHFFelicaReader(const char *Cmd) { } // simulate iso18092 / FeliCa tag +// Commented, there is no counterpart in ARM at the moment +/* static int CmdHFFelicaSim(const char *Cmd) { bool errors = false; uint8_t flags = 0; @@ -129,7 +146,7 @@ static int CmdHFFelicaSim(const char *Cmd) { if (errors || cmdp == 0) return usage_hf_felica_sim(); clearCommandBuffer(); - SendCommandOLD(CMD_FELICA_SIMULATE_TAG, tagtype, flags, 0, uid, uidlen >> 1); + SendCommandOLD(CMD_HF_FELICA_SIMULATE, tagtype, flags, 0, uid, uidlen >> 1); PacketResponseNG resp; if (verbose) @@ -140,6 +157,7 @@ static int CmdHFFelicaSim(const char *Cmd) { } return 0; } +*/ static int CmdHFFelicaSniff(const char *Cmd) { @@ -173,7 +191,7 @@ static int CmdHFFelicaSniff(const char *Cmd) { if (errors || cmdp == 0) return usage_hf_felica_sniff(); clearCommandBuffer(); - SendCommandMIX(CMD_FELICA_SNIFF, samples2skip, triggers2skip, 0, NULL, 0); + SendCommandMIX(CMD_HF_FELICA_SNIFF, samples2skip, triggers2skip, 0, NULL, 0); return 0; } @@ -186,7 +204,7 @@ static int CmdHFFelicaSimLite(const char *Cmd) { return usage_hf_felica_simlite(); clearCommandBuffer(); - SendCommandMIX(CMD_FELICA_LITE_SIM, uid, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_FELICALITE_SIMULATE, uid, 0, 0, NULL, 0); return 0; } @@ -349,7 +367,7 @@ static int CmdHFFelicaDumpLite(const char *Cmd) { PrintAndLogEx(SUCCESS, "FeliCa lite - dump started"); PrintAndLogEx(SUCCESS, "press pm3-button to cancel"); clearCommandBuffer(); - SendCommandNG(CMD_FELICA_LITE_DUMP, NULL, 0); + SendCommandNG(CMD_HF_FELICALITE_DUMP, NULL, 0); PacketResponseNG resp; uint8_t timeout = 0; @@ -520,7 +538,7 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen; clearCommandBuffer(); - SendCommandOLD(CMD_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen); + SendCommandOLD(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen); if (reply) { if (active_select) @@ -535,7 +553,7 @@ static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"list", CmdHFFelicaList, AlwaysAvailable, "List ISO 18092/FeliCa history"}, {"reader", CmdHFFelicaReader, IfPm3Felica, "Act like an ISO18092/FeliCa reader"}, - {"sim", CmdHFFelicaSim, IfPm3Felica, " -- Simulate ISO 18092/FeliCa tag"}, +// {"sim", CmdHFFelicaSim, IfPm3Felica, " -- Simulate ISO 18092/FeliCa tag"}, {"sniff", CmdHFFelicaSniff, IfPm3Felica, "sniff ISO 18092/Felica traffic"}, {"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"}, @@ -558,11 +576,11 @@ int CmdHFFelica(const char *Cmd) { int readFelicaUid(bool verbose) { clearCommandBuffer(); - SendCommandMIX(CMD_FELICA_COMMAND, FELICA_CONNECT, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_FELICA_COMMAND, FELICA_CONNECT, 0, 0, NULL, 0); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { if (verbose) PrintAndLogEx(WARNING, "FeliCa card select failed"); - //SendCommandMIX(CMD_FELICA_COMMAND, 0, 0, 0, NULL, 0); + //SendCommandMIX(CMD_HF_FELICA_COMMAND, 0, 0, 0, NULL, 0); return 0; } diff --git a/client/cmdhffelica.h b/client/cmdhffelica.h index b495b80ec..4193235f5 100644 --- a/client/cmdhffelica.h +++ b/client/cmdhffelica.h @@ -11,19 +11,7 @@ #ifndef CMDHFFELICA_H__ #define CMDHFFELICA_H__ -#include -#include -#include -#include -#include -#include "proxmark3.h" #include "common.h" -#include "ui.h" -#include "util.h" -#include "cmdparser.h" -#include "comms.h" // getfromdevice -#include "cmdhf.h" // list cmd -#include "mifare.h" // felica_card_select_t struct int CmdHFFelica(const char *Cmd); diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 39b080dca..fbc91e814 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -21,38 +21,30 @@ #include "cmdhffido.h" -#include -#include -#include -#include -#include #include -#include -#include -#include -#include + +#include "cmdparser.h" // command_t +#include "commonutil.h" + #include "comms.h" -#include "cmdmain.h" -#include "util.h" -#include "ui.h" #include "proxmark3.h" -#include "mifare.h" #include "emv/emvcore.h" #include "emv/emvjson.h" -#include "emv/dump.h" #include "cliparser/cliparser.h" #include "crypto/asn1utils.h" #include "crypto/libpcrypto.h" #include "fido/cbortools.h" #include "fido/fidocore.h" -#include "fido/cose.h" +#include "emv/dump.h" +#include "ui.h" +#include "cmdhf14a.h" static int CmdHelp(const char *Cmd); static int CmdHFFidoInfo(const char *cmd) { if (cmd && strlen(cmd) > 0) - PrintAndLogEx(WARNING, "WARNING: command don't have any parameters.\n"); + PrintAndLogEx(WARNING, "WARNING: command doesn't have any parameters.\n"); // info about 14a part infoHF14A(false, false); @@ -83,14 +75,14 @@ static int CmdHFFidoInfo(const char *cmd) { if (!strncmp((char *)buf, "U2F_V2", 7)) { if (!strncmp((char *)buf, "FIDO_2_0", 8)) { - PrintAndLogEx(INFO, "FIDO2 authenricator detected. Version: %.*s", len, buf); + PrintAndLogEx(INFO, "FIDO2 authenticator detected. Version: %.*s", len, buf); } else { - PrintAndLogEx(INFO, "FIDO authenricator detected (not standard U2F)."); + PrintAndLogEx(INFO, "FIDO authenticator detected (not standard U2F)."); PrintAndLogEx(INFO, "Non U2F authenticator version:"); dump_buffer((const unsigned char *)buf, len, NULL, 0); } } else { - PrintAndLogEx(INFO, "FIDO U2F authenricator detected. Version: %.*s", len, buf); + PrintAndLogEx(INFO, "FIDO U2F authenticator detected. Version: %.*s", len, buf); } res = FIDO2GetInfo(buf, sizeof(buf), &len, &sw); @@ -99,13 +91,13 @@ static int CmdHFFidoInfo(const char *cmd) { return res; } if (sw != 0x9000) { - PrintAndLogEx(ERR, "FIDO2 version not exists (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLogEx(ERR, "FIDO2 version doesn't exist (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); return 0; } if (buf[0]) { - PrintAndLogEx(ERR, "FIDO2 ger version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); + PrintAndLogEx(ERR, "FIDO2 get version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); return 0; } @@ -171,14 +163,14 @@ static int CmdHFFidoRegister(const char *cmd) { json_t *root = NULL; CLIParserInit("hf fido reg", - "Initiate a U2F token registration. Needs two 32-byte hash number. \nchallenge parameter (32b) and application parameter (32b).", + "Initiate a U2F token registration. Needs two 32-byte hash numbers. \nchallenge parameter (32b) and application parameter (32b).", "Usage:\n\thf fido reg -> execute command with 2 parameters, filled 0x00\n" "\thf fido reg 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters" "\thf fido reg -p s0 s1 -> execute command with plain parameters"); void *argtable[] = { arg_param_begin, - arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_lit0("aA", "apdu", "show APDU requests and responses"), arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"), arg_lit0("tT", "tlv", "Show DER certificate contents in TLV representation"), @@ -346,15 +338,15 @@ static int CmdHFFidoRegister(const char *cmd) { &buf[1], 65, // user public key NULL, 0); //PrintAndLogEx(NORMAL, "--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); - res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[hashp], len - hashp); + res = ecdsa_signature_verify(MBEDTLS_ECP_DP_SECP256R1, public_key, xbuf, xbuflen, &buf[hashp], len - hashp, true); if (res) { - if (res == -0x4e00) { - PrintAndLogEx(WARNING, "Signature is NOT VALID."); + if (res == MBEDTLS_ERR_ECP_VERIFY_FAILED) { + PrintAndLogEx(WARNING, "Signature is" _RED_("NOT VALID")); } else { PrintAndLogEx(WARNING, "Other signature check error: %x %s", (res < 0) ? -res : res, ecdsa_get_error(res)); } } else { - PrintAndLogEx(SUCCESS, "Signature is OK."); + PrintAndLogEx(SUCCESS, "Signature is" _GREEN_("OK")); } } else { @@ -401,7 +393,7 @@ static int CmdHFFidoAuthenticate(const char *cmd) { json_t *root = NULL; CLIParserInit("hf fido auth", - "Initiate a U2F token authentication. Needs key handle and two 32-byte hash number. \nkey handle(var 0..255), challenge parameter (32b) and application parameter (32b).", + "Initiate a U2F token authentication. Needs key handle and two 32-byte hash numbers. \nkey handle(var 0..255), challenge parameter (32b) and application parameter (32b).", "Usage:\n\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with 2 parameters, filled 0x00 and key handle\n" "\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f " "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters"); @@ -572,15 +564,15 @@ static int CmdHFFidoAuthenticate(const char *cmd) { data, 32, // challenge parameter NULL, 0); //PrintAndLogEx(NORMAL, "--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); - res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[5], len - 5); + res = ecdsa_signature_verify(MBEDTLS_ECP_DP_SECP256R1, public_key, xbuf, xbuflen, &buf[5], len - 5, true); if (res) { - if (res == -0x4e00) { - PrintAndLogEx(WARNING, "Signature is NOT VALID."); + if (res == MBEDTLS_ERR_ECP_VERIFY_FAILED) { + PrintAndLogEx(WARNING, "Signature is" _RED_("NOT VALID.")); } else { PrintAndLogEx(WARNING, "Other signature check error: %x %s", (res < 0) ? -res : res, ecdsa_get_error(res)); } } else { - PrintAndLogEx(SUCCESS, "Signature is OK."); + PrintAndLogEx(SUCCESS, "Signature is" _GREEN_("OK")); } } else { PrintAndLogEx(WARNING, "No public key provided. can't check signature."); @@ -648,8 +640,8 @@ static int CmdHFFido2MakeCredential(const char *cmd) { char fname[300] = {0}; CLIParserInit("hf fido make", - "Execute a FIDO2 Make Credentional command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", - "Usage:\n\thf fido make -> execute command default parameters file `fido2.json`\n" + "Execute a FIDO2 Make Credential command. Needs json file with parameters. Sample file " _YELLOW_("`fido2.json`") " in `resources/`.", + "Usage:\n\thf fido make -> execute command with default parameters file `fido2.json`\n" "\thf fido make test.json -> execute command with parameters file `text.json`"); void *argtable[] = { @@ -721,7 +713,7 @@ static int CmdHFFido2MakeCredential(const char *cmd) { return res; if (showCBOR) { - PrintAndLogEx(INFO, "CBOR make credentional request:"); + PrintAndLogEx(INFO, "CBOR make credential request:"); PrintAndLogEx(NORMAL, "---------------- CBOR ------------------"); TinyCborPrintFIDOPackage(fido2CmdMakeCredential, false, data, datalen); PrintAndLogEx(NORMAL, "---------------- CBOR ------------------"); @@ -746,7 +738,7 @@ static int CmdHFFido2MakeCredential(const char *cmd) { PrintAndLogEx(SUCCESS, "MakeCredential result (%d b) OK.", len); if (showCBOR) { - PrintAndLogEx(SUCCESS, "CBOR make credentional response:"); + PrintAndLogEx(SUCCESS, "CBOR make credential response:"); PrintAndLogEx(NORMAL, "---------------- CBOR ------------------"); TinyCborPrintFIDOPackage(fido2CmdMakeCredential, true, &buf[1], len - 1); PrintAndLogEx(NORMAL, "---------------- CBOR ------------------"); @@ -774,8 +766,8 @@ static int CmdHFFido2GetAssertion(const char *cmd) { char fname[300] = {0}; CLIParserInit("hf fido assert", - "Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file " _YELLOW_("`fido2.json`") ". File can be placed in proxmark directory or in `proxmark/fido` directory.", - "Usage:\n\thf fido assert -> execute command default parameters file `fido2.json`\n" + "Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file " _YELLOW_("`fido2.json`") " in `resources/`.", + "Usage:\n\thf fido assert -> execute command with default parameters file `fido2.json`\n" "\thf fido assert test.json -l -> execute command with parameters file `text.json` and add to request CredentialId"); void *argtable[] = { @@ -783,7 +775,7 @@ static int CmdHFFido2GetAssertion(const char *cmd) { arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), arg_lit0("cC", "cbor", "show CBOR decoded data"), - arg_lit0("lL", "list", "add CredentialId from json to allowList. Needs if `rk` option is `false` (authenticator don't store credential to its memory)"), + arg_lit0("lL", "list", "add CredentialId from json to allowList. Needs if `rk` option is `false` (authenticator doesn't store credential to its memory)"), arg_str0(NULL, NULL, "", "JSON input / output file name for parameters. Default `fido2.json`"), arg_param_end }; @@ -809,7 +801,7 @@ static int CmdHFFido2GetAssertion(const char *cmd) { SetAPDULogging(APDULogging); - int res = GetExistsFileNameJson("fido", "fido2", fname); + int res = GetExistsFileNameJson("fido", cjsonname, fname); if (res) { PrintAndLogEx(ERR, "ERROR: Can't found the json file."); return res; diff --git a/client/cmdhffido.h b/client/cmdhffido.h index b54f53118..9aca8ecc8 100644 --- a/client/cmdhffido.h +++ b/client/cmdhffido.h @@ -21,7 +21,8 @@ #ifndef CMDHFFIDO_H__ #define CMDHFFIDO_H__ +#include "common.h" + int CmdHFFido(const char *Cmd); - #endif diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 91757bbd4..f45151a7b 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -13,16 +13,34 @@ #include "cmdhficlass.h" +#include + +#include "cmdparser.h" // command_t +#include "commonutil.h" // ARRAYLEN +#include "cmdtrace.h" +#include "util_posix.h" + +#include "comms.h" +#include "mbedtls/des.h" +#include "loclass/cipherutils.h" +#include "loclass/cipher.h" +#include "loclass/ikeys.h" +#include "loclass/elite_crack.h" +#include "fileutils.h" +#include "protocols.h" + + #define NUM_CSNS 9 #define ICLASS_KEYS_MAX 8 +#define ICLASS_AUTH_RETRY 10 static int CmdHelp(const char *Cmd); static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = { - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xAE, 0xA6, 0x84, 0xA6, 0xDA, 0xB2, 0x32, 0x78 }, + { 0x76, 0x65, 0x54, 0x43, 0x32, 0x21, 0x10, 0x00 }, + { 0x5B, 0x7C, 0x62, 0xC4, 0x91, 0xc1, 0x1b, 0x39 }, + { 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -43,38 +61,46 @@ static int usage_hf_iclass_sim(void) { PrintAndLogEx(NORMAL, " hf iclass eload 'tagdump.bin'"); PrintAndLogEx(NORMAL, " hf iclass sim 3"); PrintAndLogEx(NORMAL, " hf iclass sim 4"); - return 0; + return PM3_SUCCESS; } static int usage_hf_iclass_eload(void) { PrintAndLogEx(NORMAL, "Loads iclass tag-dump into emulator memory on device"); PrintAndLogEx(NORMAL, "Usage: hf iclass eload f "); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin"); - return 0; + return PM3_SUCCESS; } static int usage_hf_iclass_decrypt(void) { PrintAndLogEx(NORMAL, "This is simple implementation, it tries to decrypt every block after block 6."); PrintAndLogEx(NORMAL, "Correct behaviour would be to decrypt only the application areas where the key is valid,"); PrintAndLogEx(NORMAL, "which is defined by the configuration block."); PrintAndLogEx(NORMAL, "OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside"); - PrintAndLogEx(NORMAL, "in the working directory. The file should be 16 bytes binary data"); + PrintAndLogEx(NORMAL, "in the resources directory. The file should be 16 bytes binary data"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf iclass decrypt f "); + PrintAndLogEx(NORMAL, "Usage: hf iclass decrypt d f k "); + PrintAndLogEx(NORMAL, " options"); + PrintAndLogEx(NORMAL, " d 16 bytes hex"); + PrintAndLogEx(NORMAL, " f filename of dump"); + PrintAndLogEx(NORMAL, " k 16 bytes hex"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, "S hf iclass decrypt f tagdump_12312342343.bin"); - return 0; + PrintAndLogEx(NORMAL, "S hf iclass decrypt f tagdump_1.bin"); + PrintAndLogEx(NORMAL, "S hf iclass decrypt f tagdump_1.bin k 000102030405060708090a0b0c0d0e0f"); + PrintAndLogEx(NORMAL, "S hf iclass decrypt d 1122334455667788 k 000102030405060708090a0b0c0d0e0f"); + + return PM3_SUCCESS; } static int usage_hf_iclass_encrypt(void) { PrintAndLogEx(NORMAL, "OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside"); - PrintAndLogEx(NORMAL, "in the working directory. The file should be 16 bytes binary data"); + PrintAndLogEx(NORMAL, "in the resources directory. The file should be 16 bytes binary data"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf iclass encrypt "); + PrintAndLogEx(NORMAL, "Usage: hf iclass encrypt d k "); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf iclass encrypt 0102030405060708"); + PrintAndLogEx(NORMAL, " hf iclass encrypt d 0102030405060708"); + PrintAndLogEx(NORMAL, " hf iclass encrypt d 0102030405060708 k 00112233445566778899AABBCCDDEEFF"); PrintAndLogEx(NORMAL, ""); - return 0; + return PM3_SUCCESS; } static int usage_hf_iclass_dump(void) { PrintAndLogEx(NORMAL, "Usage: hf iclass dump f k c [e|r|v]\n"); @@ -90,23 +116,23 @@ static int usage_hf_iclass_dump(void) { PrintAndLogEx(NORMAL, " hf iclass dump k 001122334455667B"); PrintAndLogEx(NORMAL, " hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B"); PrintAndLogEx(NORMAL, " hf iclass dump k AAAAAAAAAAAAAAAA e"); - return 0; + return PM3_SUCCESS; } static int usage_hf_iclass_clone(void) { PrintAndLogEx(NORMAL, "Usage: hf iclass clone f b l k c e|r"); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " f : specify a filename to clone from"); - PrintAndLogEx(NORMAL, " b : The first block to clone as 2 hex symbols"); - PrintAndLogEx(NORMAL, " l : Set the Data to write as 16 hex symbols"); - PrintAndLogEx(NORMAL, " k : Access Key as 16 hex symbols or 1 hex to select key from memory"); - PrintAndLogEx(NORMAL, " c : If 'c' is specified, the key set is assumed to be the credit key\n"); - PrintAndLogEx(NORMAL, " e : If 'e' is specified, elite computations applied to key"); - PrintAndLogEx(NORMAL, " r : If 'r' is specified, no computations applied to key"); + PrintAndLogEx(NORMAL, " f : specify a filename to clone from"); + PrintAndLogEx(NORMAL, " b : The first block to clone as 2 hex symbols"); + PrintAndLogEx(NORMAL, " l : Set the Data to write as 16 hex symbols"); + PrintAndLogEx(NORMAL, " k : Access Key as 16 hex symbols or 1 hex to select key from memory"); + PrintAndLogEx(NORMAL, " c : If 'c' is specified, the key set is assumed to be the credit key\n"); + PrintAndLogEx(NORMAL, " e : If 'e' is specified, elite computations applied to key"); + PrintAndLogEx(NORMAL, " r : If 'r' is specified, no computations applied to key"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e"); PrintAndLogEx(NORMAL, " hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0"); PrintAndLogEx(NORMAL, " hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e"); - return 0; + return PM3_SUCCESS; } static int usage_hf_iclass_writeblock(void) { PrintAndLogEx(NORMAL, "Usage: hf iclass writeblk b d k [c|e|r|v]\n"); @@ -121,7 +147,7 @@ static int usage_hf_iclass_writeblock(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B"); PrintAndLogEx(NORMAL, " hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c"); - return 0; + return PM3_SUCCESS; } static int usage_hf_iclass_readblock(void) { PrintAndLogEx(NORMAL, "Usage: hf iclass readblk b k [c|e|r|v]\n"); @@ -136,11 +162,11 @@ static int usage_hf_iclass_readblock(void) { PrintAndLogEx(NORMAL, " hf iclass readblk b 06 k 0011223344556677"); PrintAndLogEx(NORMAL, " hf iclass readblk b 1B k 0011223344556677 c"); PrintAndLogEx(NORMAL, " hf iclass readblk b 0A k 0"); - return 0; + return PM3_SUCCESS; } static int usage_hf_iclass_readtagfile() { PrintAndLogEx(NORMAL, "Usage: hf iclass readtagfile [startblock] [endblock]"); - return 0; + return PM3_SUCCESS; } static int usage_hf_iclass_calc_newkey(void) { PrintAndLogEx(NORMAL, "Calculate new key for updating\n"); @@ -156,24 +182,24 @@ static int usage_hf_iclass_calc_newkey(void) { PrintAndLogEx(NORMAL, " std key to e key read csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e"); PrintAndLogEx(NORMAL, " std to std read csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899"); PrintAndLogEx(NORMAL, "\nNOTE: * = required\n"); - return 0; + return PM3_SUCCESS;; } static int usage_hf_iclass_managekeys(void) { PrintAndLogEx(NORMAL, "HELP : Manage iClass Keys in client memory:\n"); PrintAndLogEx(NORMAL, "Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n"); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " n : specify the keyNbr to set in memory"); - PrintAndLogEx(NORMAL, " k : set a key in memory"); - PrintAndLogEx(NORMAL, " f : specify a filename to use with load or save operations"); - PrintAndLogEx(NORMAL, " s : save keys in memory to file specified by filename"); - PrintAndLogEx(NORMAL, " l : load keys to memory from file specified by filename"); - PrintAndLogEx(NORMAL, " p : print keys loaded into memory\n"); + PrintAndLogEx(NORMAL, " n : specify the keyNbr to set in memory"); + PrintAndLogEx(NORMAL, " k : set a key in memory"); + PrintAndLogEx(NORMAL, " f : specify a filename to use with load or save operations"); + PrintAndLogEx(NORMAL, " s : save keys in memory to file specified by filename"); + PrintAndLogEx(NORMAL, " l : load keys to memory from file specified by filename"); + PrintAndLogEx(NORMAL, " p : print keys loaded into memory\n"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " set key : hf iclass managekeys n 0 k 1122334455667788"); - PrintAndLogEx(NORMAL, " save key file: hf iclass managekeys f mykeys.bin s"); - PrintAndLogEx(NORMAL, " load key file: hf iclass managekeys f mykeys.bin l"); - PrintAndLogEx(NORMAL, " print keys : hf iclass managekeys p\n"); - return 0; + PrintAndLogEx(NORMAL, " set key : hf iclass managekeys n 0 k 1122334455667788"); + PrintAndLogEx(NORMAL, " save key file : hf iclass managekeys f mykeys.bin s"); + PrintAndLogEx(NORMAL, " load key file : hf iclass managekeys f mykeys.bin l"); + PrintAndLogEx(NORMAL, " print keys : hf iclass managekeys p\n"); + return PM3_SUCCESS; } static int usage_hf_iclass_reader(void) { PrintAndLogEx(NORMAL, "Act as a Iclass reader. Look for iClass tags until Enter or the pm3 button is pressed\n"); @@ -183,7 +209,7 @@ static int usage_hf_iclass_reader(void) { PrintAndLogEx(NORMAL, " 1 read only 1 tag"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf iclass reader 1"); - return 0; + return PM3_SUCCESS; } static int usage_hf_iclass_replay(void) { PrintAndLogEx(NORMAL, "Replay a collected mac message"); @@ -193,29 +219,29 @@ static int usage_hf_iclass_replay(void) { PrintAndLogEx(NORMAL, " Mac bytes to replay (8 hexsymbols)"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf iclass replay 00112233"); - return 0; + return PM3_SUCCESS; } static int usage_hf_iclass_sniff(void) { PrintAndLogEx(NORMAL, "Sniff the communication between reader and tag"); PrintAndLogEx(NORMAL, "Usage: hf iclass sniff [h]"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf iclass sniff"); - return 0; + return PM3_SUCCESS; } static int usage_hf_iclass_loclass(void) { PrintAndLogEx(NORMAL, "Usage: hf iclass loclass [options]"); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, "h Show this help"); - PrintAndLogEx(NORMAL, "t Perform self-test"); - PrintAndLogEx(NORMAL, "f Bruteforce iclass dumpfile"); - PrintAndLogEx(NORMAL, " An iclass dumpfile is assumed to consist of an arbitrary number of"); - PrintAndLogEx(NORMAL, " malicious CSNs, and their protocol responses"); - PrintAndLogEx(NORMAL, " The binary format of the file is expected to be as follows: "); - PrintAndLogEx(NORMAL, " <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); - PrintAndLogEx(NORMAL, " <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); - PrintAndLogEx(NORMAL, " <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); - PrintAndLogEx(NORMAL, " ... totalling N*24 bytes"); - return 0; + PrintAndLogEx(NORMAL, " h Show this help"); + PrintAndLogEx(NORMAL, " t Perform self-test"); + PrintAndLogEx(NORMAL, " f Bruteforce iclass dumpfile"); + PrintAndLogEx(NORMAL, " An iclass dumpfile is assumed to consist of an arbitrary number of"); + PrintAndLogEx(NORMAL, " malicious CSNs, and their protocol responses"); + PrintAndLogEx(NORMAL, " The binary format of the file is expected to be as follows: "); + PrintAndLogEx(NORMAL, " <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); + PrintAndLogEx(NORMAL, " <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); + PrintAndLogEx(NORMAL, " <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); + PrintAndLogEx(NORMAL, " ... totalling N*24 bytes"); + return PM3_SUCCESS; } static int usage_hf_iclass_chk(void) { PrintAndLogEx(NORMAL, "Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag"); @@ -227,9 +253,9 @@ static int usage_hf_iclass_chk(void) { PrintAndLogEx(NORMAL, " e elite"); PrintAndLogEx(NORMAL, " c credit key (if not use, default is debit)"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf iclass chk f default_iclass_keys.dic"); - PrintAndLogEx(NORMAL, " hf iclass chk f default_iclass_keys.dic e"); - return 0; + PrintAndLogEx(NORMAL, " hf iclass chk f dictionaries/iclass_default_keys.dic"); + PrintAndLogEx(NORMAL, " hf iclass chk f dictionaries/iclass_default_keys.dic e"); + return PM3_SUCCESS;; } static int usage_hf_iclass_lookup(void) { PrintAndLogEx(NORMAL, "Lookup keys takes some sniffed trace data and tries to verify what key was used against a dictionary file"); @@ -243,9 +269,9 @@ static int usage_hf_iclass_lookup(void) { PrintAndLogEx(NORMAL, " r raw"); PrintAndLogEx(NORMAL, " e elite"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf iclass lookup u 9655a400f8ff12e0 p f0ffffffffffffff m 0000000089cb984b f default_iclass_keys.dic"); - PrintAndLogEx(NORMAL, " hf iclass lookup u 9655a400f8ff12e0 p f0ffffffffffffff m 0000000089cb984b f default_iclass_keys.dic e"); - return 0; + PrintAndLogEx(NORMAL, " hf iclass lookup u 9655a400f8ff12e0 p f0ffffffffffffff m 0000000089cb984b f dictionaries/iclass_default_keys.dic"); + PrintAndLogEx(NORMAL, " hf iclass lookup u 9655a400f8ff12e0 p f0ffffffffffffff m 0000000089cb984b f dictionaries/iclass_default_keys.dic e"); + return PM3_SUCCESS; } static int usage_hf_iclass_permutekey(void) { PrintAndLogEx(NORMAL, "Permute function from 'heart of darkness' paper."); @@ -259,7 +285,7 @@ static int usage_hf_iclass_permutekey(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf iclass permute r 0123456789abcdef"); - return 0; + return PM3_SUCCESS; } /* @@ -271,6 +297,145 @@ static int xorbits_8(uint8_t val) { return res & 1; } */ + +// iclass / picopass chip config structures and shared routines +typedef struct { + uint8_t app_limit; //[8] + uint8_t otp[2]; //[9-10] + uint8_t block_writelock;//[11] + uint8_t chip_config; //[12] + uint8_t mem_config; //[13] + uint8_t eas; //[14] + uint8_t fuses; //[15] +} picopass_conf_block; + + +typedef struct { + uint8_t csn[8]; + picopass_conf_block conf; + uint8_t epurse[8]; + uint8_t key_d[8]; + uint8_t key_c[8]; + uint8_t app_issuer_area[8]; +} picopass_hdr; + +static uint8_t isset(uint8_t val, uint8_t mask) { + return (val & mask); +} + +static uint8_t notset(uint8_t val, uint8_t mask) { + return !(val & mask); +} + +static void fuse_config(const picopass_hdr *hdr) { + uint8_t fuses = hdr->conf.fuses; + + if (isset(fuses, FUSE_FPERS)) + PrintAndLogEx(SUCCESS, " Mode: Personalization [Programmable]"); + else + PrintAndLogEx(NORMAL, " Mode: Application [Locked]"); + + if (isset(fuses, FUSE_CODING1)) { + PrintAndLogEx(NORMAL, " Coding: RFU"); + } else { + if (isset(fuses, FUSE_CODING0)) + PrintAndLogEx(NORMAL, " Coding: ISO 14443-2 B/ISO 15693"); + else + PrintAndLogEx(NORMAL, " Coding: ISO 14443B only"); + } + // 1 1 + if (isset(fuses, FUSE_CRYPT1) && isset(fuses, FUSE_CRYPT0)) PrintAndLogEx(SUCCESS, " Crypt: Secured page, keys not locked"); + // 1 0 + if (isset(fuses, FUSE_CRYPT1) && notset(fuses, FUSE_CRYPT0)) PrintAndLogEx(NORMAL, " Crypt: Secured page, keys locked"); + // 0 1 + if (notset(fuses, FUSE_CRYPT1) && isset(fuses, FUSE_CRYPT0)) PrintAndLogEx(SUCCESS, " Crypt: Non secured page"); + // 0 0 + if (notset(fuses, FUSE_CRYPT1) && notset(fuses, FUSE_CRYPT0)) PrintAndLogEx(NORMAL, " Crypt: No auth possible. Read only if RA is enabled"); + + if (isset(fuses, FUSE_RA)) + PrintAndLogEx(NORMAL, " RA: Read access enabled"); + else + PrintAndLogEx(WARNING, " RA: Read access not enabled"); +} + +static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb) { + // mem-bit 5, mem-bit 7, chip-bit 4: defines chip type + uint8_t k16 = isset(mem_cfg, 0x80); + //uint8_t k2 = isset(mem_cfg, 0x08); + uint8_t book = isset(mem_cfg, 0x20); + + if (isset(chip_cfg, 0x10) && !k16 && !book) { + *kb = 2; + *app_areas = 2; + *max_blk = 31; + } else if (isset(chip_cfg, 0x10) && k16 && !book) { + *kb = 16; + *app_areas = 2; + *max_blk = 255; //16kb + } else if (notset(chip_cfg, 0x10) && !k16 && !book) { + *kb = 16; + *app_areas = 16; + *max_blk = 255; //16kb + } else if (isset(chip_cfg, 0x10) && k16 && book) { + *kb = 32; + *app_areas = 3; + *max_blk = 255; //16kb + } else if (notset(chip_cfg, 0x10) && !k16 && book) { + *kb = 32; + *app_areas = 17; + *max_blk = 255; //16kb + } else { + *kb = 32; + *app_areas = 2; + *max_blk = 255; + } +} + +static void mem_app_config(const picopass_hdr *hdr) { + uint8_t mem = hdr->conf.mem_config; + uint8_t chip = hdr->conf.chip_config; + uint8_t applimit = hdr->conf.app_limit; + uint8_t kb = 2; + uint8_t app_areas = 2; + uint8_t max_blk = 31; + + getMemConfig(mem, chip, &max_blk, &app_areas, &kb); + + if (applimit < 6) applimit = 26; + if (kb == 2 && (applimit > 0x1f)) applimit = 26; + + PrintAndLogEx(NORMAL, " Mem: %u KBits/%u App Areas (%u * 8 bytes) [%02X]", kb, app_areas, max_blk, mem); + PrintAndLogEx(NORMAL, " AA1: blocks 06-%02X", applimit); + PrintAndLogEx(NORMAL, " AA2: blocks %02X-%02X", applimit + 1, max_blk); + PrintAndLogEx(NORMAL, " OTP: 0x%02X%02X", hdr->conf.otp[1], hdr->conf.otp[0]); + PrintAndLogEx(NORMAL, " KeyAccess:"); + + uint8_t book = isset(mem, 0x20); + if (book) { + PrintAndLogEx(NORMAL, " Read A - Kd"); + PrintAndLogEx(NORMAL, " Read B - Kc"); + PrintAndLogEx(NORMAL, " Write A - Kd"); + PrintAndLogEx(NORMAL, " Write B - Kc"); + PrintAndLogEx(NORMAL, " Debit - Kd or Kc"); + PrintAndLogEx(NORMAL, " Credit - Kc"); + } else { + PrintAndLogEx(NORMAL, " Read A - Kd or Kc"); + PrintAndLogEx(NORMAL, " Read B - Kd or Kc"); + PrintAndLogEx(NORMAL, " Write A - Kc"); + PrintAndLogEx(NORMAL, " Write B - Kc"); + PrintAndLogEx(NORMAL, " Debit - Kd or Kc"); + PrintAndLogEx(NORMAL, " Credit - Kc"); + } +} +static void print_picopass_info(const picopass_hdr *hdr) { + fuse_config(hdr); + mem_app_config(hdr); +} +static void printIclassDumpInfo(uint8_t *iclass_dump) { + print_picopass_info((picopass_hdr *) iclass_dump); +} + + static int CmdHFiClassList(const char *Cmd) { (void)Cmd; // Cmd is not used so far //PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list iclass' instead"); @@ -281,7 +446,7 @@ static int CmdHFiClassList(const char *Cmd) { static int CmdHFiClassSniff(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_hf_iclass_sniff(); - SendCommandNG(CMD_SNIFF_ICLASS, NULL, 0); + SendCommandNG(CMD_HF_ICLASS_SNIFF, NULL, 0); return PM3_SUCCESS; } @@ -297,14 +462,14 @@ static int CmdHFiClassSim(const char *Cmd) { if (simType == 0) { if (param_gethex(Cmd, 1, CSN, 16)) { - PrintAndLogEx(WARNING, "A CSN should consist of 16 HEX symbols"); + PrintAndLogEx(ERR, "A CSN should consist of 16 HEX symbols"); return usage_hf_iclass_sim(); } - PrintAndLogEx(NORMAL, "--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8)); + PrintAndLogEx(NORMAL, " simtype: %02x csn: %s", simType, sprint_hex(CSN, 8)); } if (simType > 4) { - PrintAndLogEx(WARNING, "Undefined simptype %d", simType); + PrintAndLogEx(ERR, "Undefined simptype %d", simType); return usage_hf_iclass_sim(); } @@ -379,17 +544,17 @@ static int CmdHFiClassSim(const char *Cmd) { PrintAndLogEx(INFO, "press Enter to cancel"); PacketResponseNG resp; clearCommandBuffer(); - SendCommandOLD(CMD_SIMULATE_TAG_ICLASS, simType, NUM_CSNS, 0, csns, 8 * NUM_CSNS); + SendCommandOLD(CMD_HF_ICLASS_SIMULATE, simType, NUM_CSNS, 0, csns, 8 * NUM_CSNS); while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { tries++; if (kbd_enter_pressed()) { PrintAndLogEx(WARNING, "\naborted via keyboard."); - return 0; + return PM3_EOPABORTED; } if (tries > 20) { PrintAndLogEx(WARNING, "\ntimeout while waiting for reply."); - return 0; + return PM3_ETIMEOUT; } } uint8_t num_mac = resp.oldarg[1]; @@ -403,7 +568,7 @@ static int CmdHFiClassSim(const char *Cmd) { uint8_t *dump = calloc(datalen, sizeof(uint8_t)); if (!dump) { PrintAndLogEx(WARNING, "Failed to allocate memory"); - return 2; + return PM3_EMALLOC; } memset(dump, 0, datalen);//<-- Need zeroes for the EPURSE - field (offical) @@ -428,17 +593,17 @@ static int CmdHFiClassSim(const char *Cmd) { PrintAndLogEx(INFO, "press Enter to cancel"); PacketResponseNG resp; clearCommandBuffer(); - SendCommandOLD(CMD_SIMULATE_TAG_ICLASS, simType, NUM_CSNS, 0, csns, 8 * NUM_CSNS); + SendCommandOLD(CMD_HF_ICLASS_SIMULATE, simType, NUM_CSNS, 0, csns, 8 * NUM_CSNS); while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { tries++; if (kbd_enter_pressed()) { PrintAndLogEx(WARNING, "\naborted via keyboard."); - return 0; + return PM3_EOPABORTED; } if (tries > 20) { PrintAndLogEx(WARNING, "\ntimeout while waiting for reply."); - return 0; + return PM3_ETIMEOUT; } } uint8_t num_mac = resp.oldarg[1]; @@ -452,7 +617,7 @@ static int CmdHFiClassSim(const char *Cmd) { uint8_t *dump = calloc(datalen, sizeof(uint8_t)); if (!dump) { PrintAndLogEx(WARNING, "Failed to allocate memory"); - return 2; + return PM3_EMALLOC; } #define MAC_ITEM_SIZE 24 @@ -491,13 +656,17 @@ static int CmdHFiClassSim(const char *Cmd) { default: { uint8_t numberOfCSNs = 0; clearCommandBuffer(); - SendCommandOLD(CMD_SIMULATE_TAG_ICLASS, simType, numberOfCSNs, 0, CSN, 8); + SendCommandOLD(CMD_HF_ICLASS_SIMULATE, simType, numberOfCSNs, 0, CSN, 8); break; } } return PM3_SUCCESS; } +static int CmdHFiClassInfo(const char *Cmd) { + return PM3_SUCCESS; +} + static int CmdHFiClassReader(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_hf_iclass_reader(); @@ -519,60 +688,91 @@ static int CmdHFiClassReader_Replay(const char *Cmd) { } clearCommandBuffer(); - SendCommandMIX(CMD_READER_ICLASS_REPLAY, readerType, 0, 0, MAC, 4); + SendCommandMIX(CMD_HF_ICLASS_REPLAY, readerType, 0, 0, MAC, 4); return PM3_SUCCESS; } static int CmdHFiClassELoad(const char *Cmd) { - char ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf_iclass_eload(); - - if (ctmp != 'f') return usage_hf_iclass_eload(); - - //File handling and reading - char filename[FILE_PATH_SIZE]; - - if (param_getstr(Cmd, 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { - PrintAndLogEx(FAILED, "Filename too long"); - return 1; + DumpFileType_t dftype = BIN; + char filename[FILE_PATH_SIZE] = {0}; + bool errors = false; + uint8_t cmdp = 0; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_hf_iclass_eload(); + case 'f': + if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { + PrintAndLogEx(FAILED, "Filename too long"); + errors = true; + break; + } + cmdp += 2; + break; + case 'j': + dftype = JSON; + cmdp++; + break; + case 'e': + dftype = EML; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } } - FILE *f = fopen(filename, "rb"); - if (!f) { - PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename); + //Validations + if (errors || cmdp == 0) { + usage_hf_iclass_eload(); + return PM3_EINVARG; + } + + + uint8_t *dump = calloc(2048, sizeof(uint8_t)); + if (!dump) { + PrintAndLogEx(ERR, "error, cannot allocate memory "); + return PM3_EMALLOC; + } + + size_t bytes_read = 2048; + int res = 0; + + switch (dftype) { + case BIN: { + res = loadFile_safe(filename, ".bin", (void **)&dump, &bytes_read); + break; + } + case EML: { + res = loadFileEML(filename, dump, &bytes_read); + break; + } + case JSON: { + res = loadFileJSON(filename, dump, 2048, &bytes_read); + break; + } + default: + PrintAndLogEx(ERR, "No dictionary loaded"); + return PM3_ESOFT; + } + + if (res != PM3_SUCCESS) { + free(dump); return PM3_EFILE; } - // get filesize in order to malloc memory - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - fseek(f, 0, SEEK_SET); - - if (fsize <= 0) { - PrintAndLogDevice(ERR, "error, when getting filesize"); - fclose(f); - return 1; + uint8_t *newdump = realloc(dump, bytes_read); + if (newdump == NULL) { + free(dump); + return PM3_EMALLOC; + } else { + dump = newdump; } - uint8_t *dump = calloc(fsize, sizeof(uint8_t)); - if (!dump) { - PrintAndLogDevice(ERR, "error, cannot allocate memory "); - fclose(f); - return 1; - } - - size_t bytes_read = fread(dump, 1, fsize, f); - fclose(f); - printIclassDumpInfo(dump); - //Validate - - if (bytes_read < fsize) { - PrintAndLogDevice(ERR, "error, could only read %d bytes (should be %d)", bytes_read, fsize); - free(dump); - return 1; - } // fast push mode conn.block_after_ACK = true; @@ -588,7 +788,7 @@ static int CmdHFiClassELoad(const char *Cmd) { conn.block_after_ACK = false; } clearCommandBuffer(); - SendCommandOLD(CMD_ICLASS_EML_MEMSET, bytes_sent, bytes_in_packet, 0, dump + bytes_sent, bytes_in_packet); + SendCommandOLD(CMD_HF_ICLASS_EML_MEMSET, bytes_sent, bytes_in_packet, 0, dump + bytes_sent, bytes_in_packet); bytes_remaining -= bytes_in_packet; bytes_sent += bytes_in_packet; } @@ -598,147 +798,189 @@ static int CmdHFiClassELoad(const char *Cmd) { return PM3_SUCCESS; } -static int readKeyfile(const char *filename, size_t len, uint8_t *buffer) { - FILE *f = fopen(filename, "rb"); - if (!f) { - PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename); - return PM3_EFILE; - } - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - fseek(f, 0, SEEK_SET); - size_t bytes_read = fread(buffer, 1, len, f); - fclose(f); - - if (fsize != len) { - PrintAndLogEx(WARNING, "Warning, file size is %d, expected %d", fsize, len); - return 1; - } - - if (bytes_read != len) { - PrintAndLogEx(WARNING, "Warning, could only read %d bytes, expected %d", bytes_read, len); - return 1; - } - return PM3_SUCCESS; -} +#define ICLASS_DECRYPTION_BIN "iclass_decryptionkey.bin" static int CmdHFiClassDecrypt(const char *Cmd) { - char opt = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || opt == 'h') return usage_hf_iclass_decrypt(); + bool errors = false; + bool have_key = false; + bool have_data = false; + bool have_file = false; + uint8_t cmdp = 0; - uint8_t key[16] = { 0 }; - if (readKeyfile("iclass_decryptionkey.bin", 16, key)) return usage_hf_iclass_decrypt(); + uint8_t enc_data[8] = {0}; + + size_t keylen = 0; + uint8_t key[32] = {0}; + uint8_t *keyptr = NULL; - PrintAndLogEx(SUCCESS, "decryption key loaded from file"); - - //Open the tagdump-file - FILE *f; + size_t decryptedlen = 0; + uint8_t *decrypted = NULL; char filename[FILE_PATH_SIZE]; - if (opt == 'f' && param_getstr(Cmd, 1, filename, sizeof(filename)) > 0) { - f = fopen(filename, "rb"); - if (!f) { - PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename); - return PM3_EFILE; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_hf_iclass_decrypt(); + case 'd': + if (param_gethex(Cmd, cmdp + 1, enc_data, 16)) { + PrintAndLogEx(ERR, "data must be 16 HEX symbols"); + errors = true; + break; + } + have_data = true; + cmdp += 2; + break; + case 'f': + if (param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)) == 0) { + PrintAndLogEx(WARNING, "no filename found after f"); + errors = true; + break; + } + + if (loadFile_safe(filename, "", (void **)&decrypted, &decryptedlen) != PM3_SUCCESS) { + errors = true; + break; + } + have_file = true; + cmdp += 2; + break; + case 'k': + if (param_gethex(Cmd, cmdp + 1, key, 32)) { + PrintAndLogEx(ERR, "Transport key must include 32 HEX symbols"); + errors = true; + } + have_key = true; + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + errors = true; + break; } - } else { - return usage_hf_iclass_decrypt(); } - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - fseek(f, 0, SEEK_SET); + if (errors || cmdp < 1) return usage_hf_iclass_decrypt(); - if (fsize <= 0) { - PrintAndLogEx(ERR, "error, when getting filesize"); - fclose(f); - return 2; + if (have_key == false) { + int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&keyptr, &keylen); + if (res != PM3_SUCCESS) + return PM3_EINVARG; + + memcpy(key, keyptr, sizeof(key)); } - uint8_t *decrypted = calloc(fsize, sizeof(uint8_t)); - if (!decrypted) { - PrintAndLogEx(WARNING, "Failed to allocate memory"); - fclose(f); - return 1; - } - - size_t bytes_read = fread(decrypted, 1, fsize, f); - fclose(f); - if (bytes_read == 0) { - PrintAndLogEx(ERR, "file reading error"); - free(decrypted); - return 3; - } - - picopass_hdr *hdr = (picopass_hdr *)decrypted; - - uint8_t mem = hdr->conf.mem_config; - uint8_t chip = hdr->conf.chip_config; - uint8_t applimit = hdr->conf.app_limit; - uint8_t kb = 2; - uint8_t app_areas = 2; - uint8_t max_blk = 31; - getMemConfig(mem, chip, &max_blk, &app_areas, &kb); - - //Use the first block (CSN) for filename - char outfilename[FILE_PATH_SIZE] = {0}; - snprintf(outfilename, FILE_PATH_SIZE, "iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted", - hdr->csn[0], hdr->csn[1], hdr->csn[2], hdr->csn[3], - hdr->csn[4], hdr->csn[5], hdr->csn[6], hdr->csn[7]); - // tripledes mbedtls_des3_context ctx; mbedtls_des3_set2key_dec(&ctx, key); - uint8_t enc_dump[8] = {0}; - uint8_t empty[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - for (uint16_t blocknum = 0; blocknum < applimit; ++blocknum) { + uint8_t dec_data[8] = {0}; - uint8_t idx = blocknum * 8; - memcpy(enc_dump, decrypted + idx, 8); - - // block 7 or higher, and not empty 0xFF - if (blocknum > 6 && memcmp(enc_dump, empty, 8) != 0) { - mbedtls_des3_crypt_ecb(&ctx, enc_dump, decrypted + idx); - } + if ( have_data ) { + mbedtls_des3_crypt_ecb(&ctx, enc_data, dec_data); + PrintAndLogEx(SUCCESS, "Data: %s", sprint_hex(dec_data, sizeof(dec_data))); } - saveFile(outfilename, ".bin", decrypted, fsize); - printIclassDumpContents(decrypted, 1, (fsize / 8), fsize); - free(decrypted); + if ( have_file ) { + picopass_hdr *hdr = (picopass_hdr *)decrypted; + + uint8_t mem = hdr->conf.mem_config; + uint8_t chip = hdr->conf.chip_config; + uint8_t applimit = hdr->conf.app_limit; + uint8_t kb = 2; + uint8_t app_areas = 2; + uint8_t max_blk = 31; + getMemConfig(mem, chip, &max_blk, &app_areas, &kb); + + uint8_t empty[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + for (uint16_t blocknum = 0; blocknum < applimit; ++blocknum) { + + uint8_t idx = blocknum * 8; + memcpy(enc_data, decrypted + idx, 8); + + // block 7 or higher, and not empty 0xFF + if (blocknum > 6 && memcmp(enc_data, empty, 8) != 0) { + mbedtls_des3_crypt_ecb(&ctx, enc_data, decrypted + idx); + } + } + + //Use the first block (CSN) for filename + char *fptr = calloc(42, sizeof(uint8_t)); + strcat(fptr, "hf-iclass-"); + FillFileNameByUID(fptr, hdr->csn, "-data-decrypted", sizeof(hdr->csn)); + + saveFile(fptr, ".bin", decrypted, decryptedlen); + saveFileEML(fptr, decrypted, decryptedlen, 8); + saveFileJSON(fptr, jsfIclass, decrypted, decryptedlen); + + printIclassDumpContents(decrypted, 1, (decryptedlen / 8), decryptedlen); + free(decrypted); + free(fptr); + } + + mbedtls_des3_free(&ctx); return PM3_SUCCESS; } -static int iClassEncryptBlkData(uint8_t *blkData) { - uint8_t key[16] = { 0 }; - if (readKeyfile("iclass_decryptionkey.bin", 16, key)) { - usage_hf_iclass_encrypt(); - return 1; - } - PrintAndLogEx(SUCCESS, "decryption file found"); - uint8_t encryptedData[16]; - uint8_t *encrypted = encryptedData; +static void iClassEncryptBlkData(uint8_t *blk_data, uint8_t *key) { + uint8_t encrypted_data[16]; + uint8_t *encrypted = encrypted_data; mbedtls_des3_context ctx; mbedtls_des3_set2key_enc(&ctx, key); - - mbedtls_des3_crypt_ecb(&ctx, blkData, encrypted); - memcpy(blkData, encrypted, 8); - return 1; + mbedtls_des3_crypt_ecb(&ctx, blk_data, encrypted); + memcpy(blk_data, encrypted, 8); + mbedtls_des3_free(&ctx); } static int CmdHFiClassEncryptBlk(const char *Cmd) { - uint8_t blkData[8] = {0}; - char opt = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || opt == 'h') return usage_hf_iclass_encrypt(); + bool errors = false; + bool have_key = false; + uint8_t blk_data[8] = {0}; + uint8_t key[16] = {0}; + uint8_t *keyptr = NULL; + uint8_t cmdp = 0; - //get the bytes to encrypt - if (param_gethex(Cmd, 0, blkData, 16)) { - PrintAndLogEx(NORMAL, "BlockData must include 16 HEX symbols"); - return 0; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_hf_iclass_encrypt(); + case 'd': + if (param_gethex(Cmd, cmdp + 1, blk_data, 16)) { + PrintAndLogEx(ERR, "Block data must include 16 HEX symbols"); + errors = true; + } + cmdp += 2; + break; + case 'k': + if (param_gethex(Cmd, cmdp + 1, key, 32)) { + PrintAndLogEx(ERR, "Transport key must include 32 HEX symbols"); + errors = true; + } + have_key = true; + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + errors = true; + break; + } } - if (!iClassEncryptBlkData(blkData)) return 0; - printvar("encrypted block", blkData, 8); + if (errors || cmdp < 1) return usage_hf_iclass_encrypt(); + + if (have_key == false) { + size_t keylen = 0; + int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&keyptr, &keylen); + if (res != PM3_SUCCESS) + return PM3_EINVARG; + + memcpy(key, keyptr, sizeof(key)); + } + + iClassEncryptBlkData(blk_data, key); + + printvar("encrypted block", blk_data, 8); return PM3_SUCCESS; } @@ -757,8 +999,8 @@ static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool v flags |= FLAG_ICLASS_READER_CEDITKEY; clearCommandBuffer(); - SendCommandMIX(CMD_READER_ICLASS, flags, 0, 0, NULL, 0); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { + SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(WARNING, "command execute timeout"); return false; } @@ -777,7 +1019,9 @@ static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool v } if (isOK <= 1) { - PrintAndLogEx(FAILED, "failed to obtain CC! Tag-select is aborting... (%d)", isOK); + if ( verbose ) + PrintAndLogEx(FAILED, "failed to obtain CC! Tag-select is aborting... (%d)", isOK); + return false; } return true; @@ -789,6 +1033,8 @@ static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool u if (!select_only(CSN, CCNR, use_credit_key, verbose)) { if (verbose) PrintAndLogEx(FAILED, "selecting tag failed"); + +// DropField(); return false; } //get div_key @@ -800,18 +1046,27 @@ static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool u if (verbose) PrintAndLogEx(SUCCESS, "authing with %s: %s", rawkey ? "raw key" : "diversified key", sprint_hex(div_key, 8)); doMAC(CCNR, div_key, MAC); + PacketResponseNG resp; clearCommandBuffer(); - SendCommandOLD(CMD_ICLASS_AUTHENTICATION, 0, 0, 0, MAC, 4); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { - if (verbose) PrintAndLogEx(FAILED, "auth command execute timeout"); + + SendCommandNG(CMD_HF_ICLASS_AUTH, MAC, 4); + if (WaitForResponseTimeout(CMD_HF_ICLASS_AUTH, &resp, 2000) == 0) { + if (verbose) PrintAndLogEx(WARNING, "Command execute timeout"); return false; } - uint8_t isOK = resp.oldarg[0] & 0xFF; - if (!isOK) { + + if ( resp.status != PM3_SUCCESS ) { + if (verbose) PrintAndLogEx(ERR, "failed to communicate with card"); + return false; + } + + uint8_t isOK = resp.data.asBytes[0]; + if (isOK == 0) { if (verbose) PrintAndLogEx(FAILED, "authentication error"); return false; } + return true; } @@ -865,6 +1120,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { cmdp += 2; break; case 'e': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo")); elite = true; cmdp++; break; @@ -896,6 +1152,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { cmdp += 2; break; case 'r': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("raw mode")); rawkey = true; cmdp++; break; @@ -923,11 +1180,11 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { uint8_t tag_data[255 * 8]; clearCommandBuffer(); - SendCommandMIX(CMD_READER_ICLASS, flags, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0); if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) { PrintAndLogEx(WARNING, "command execute timeout"); DropField(); - return 0; + return PM3_ESOFT; } DropField(); @@ -936,7 +1193,8 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { if (readStatus == 0) { PrintAndLogEx(FAILED, "no tag found"); - return 0; + DropField(); + return PM3_ESOFT; } if (readStatus & (FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_CC)) { @@ -949,19 +1207,21 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { } // authenticate debit key and get div_key - later store in dump block 3 - if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) { - //try twice - for some reason it sometimes fails the first time... - PrintAndLogEx(SUCCESS, "retry to select card"); - if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) { - PrintAndLogEx(WARNING, "failed authenticating with debit key"); - DropField(); - return 0; - } + int numberAuthRetries = ICLASS_AUTH_RETRY; + do { + if (select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) + break; + } while (numberAuthRetries--); + + if ( numberAuthRetries <= 0) { + PrintAndLogEx(WARNING, "failed authenticating with debit key"); + DropField(); + return PM3_ESOFT; } // begin dump clearCommandBuffer(); - SendCommandMIX(CMD_ICLASS_DUMP, blockno, numblks - blockno + 1, 0, NULL, 0); + SendCommandMIX(CMD_HF_ICLASS_DUMP, blockno, numblks - blockno + 1, 0, NULL, 0); while (true) { printf("."); fflush(stdout); @@ -980,7 +1240,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { uint8_t isOK = resp.oldarg[0] & 0xff; if (!isOK && !blocksRead) { PrintAndLogEx(WARNING, "read block failed"); - return 0; + return PM3_ESOFT; } uint32_t startindex = resp.oldarg[2]; @@ -992,7 +1252,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { // response ok - now get bigbuf content of the dump if (!GetFromDevice(BIG_BUF, tag_data + (blockno * 8), blocksRead * 8, startindex, NULL, 0, NULL, 2500, false)) { PrintAndLogEx(WARNING, "command execution time out"); - return 0; + return PM3_ETIMEOUT; } size_t gotBytes = blocksRead * 8 + blockno * 8; @@ -1001,30 +1261,36 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { if (have_credit_key) { //turn off hf field before authenticating with different key DropField(); + memset(MAC, 0, 4); + // AA2 authenticate credit key and git c_div_key - later store in dump block 4 - if (!select_and_auth(CreditKEY, MAC, c_div_key, true, elite, rawkey, verbose)) { - //try twice - for some reason it sometimes fails the first time... - if (!select_and_auth(CreditKEY, MAC, c_div_key, true, elite, rawkey, verbose)) { - PrintAndLogEx(WARNING, "failed authenticating with credit key"); - DropField(); - return 0; - } + numberAuthRetries = ICLASS_AUTH_RETRY; + do { + if (select_and_auth(CreditKEY, MAC, c_div_key, true, elite, rawkey, verbose)) + break; + } while (numberAuthRetries--); + + if ( numberAuthRetries <= 0) { + PrintAndLogEx(WARNING, "failed authenticating with credit key"); + DropField(); + return PM3_ESOFT; } + // do we still need to read more block? (aa2 enabled?) if (maxBlk > blockno + numblks + 1) { // setup dump and start clearCommandBuffer(); - SendCommandMIX(CMD_ICLASS_DUMP, blockno + blocksRead, maxBlk - (blockno + blocksRead), 0, NULL, 0); + SendCommandMIX(CMD_HF_ICLASS_DUMP, blockno + blocksRead, maxBlk - (blockno + blocksRead), 0, NULL, 0); if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) { PrintAndLogEx(WARNING, "command execute timeout 2"); - return 0; + return PM3_ETIMEOUT; } isOK = resp.oldarg[0] & 0xff; blocksRead = resp.oldarg[1]; if (!isOK && !blocksRead) { PrintAndLogEx(WARNING, "read block failed 2"); - return 0; + return PM3_ESOFT; } startindex = resp.oldarg[2]; @@ -1035,7 +1301,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { // get dumped data from bigbuf if (!GetFromDevice(BIG_BUF, tag_data + gotBytes, blocksRead * 8, startindex, NULL, 0, NULL, 2500, false)) { PrintAndLogEx(WARNING, "command execution time out"); - return 0; + return PM3_ETIMEOUT; } gotBytes += blocksRead * 8; @@ -1045,51 +1311,88 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { DropField(); // add diversified keys to dump - if (have_debit_key) memcpy(tag_data + (3 * 8), div_key, 8); - if (have_credit_key) memcpy(tag_data + (4 * 8), c_div_key, 8); + if (have_debit_key) + memcpy(tag_data + (3 * 8), div_key, 8); + + if (have_credit_key) + memcpy(tag_data + (4 * 8), c_div_key, 8); + // print the dump - PrintAndLogEx(NORMAL, "------+--+-------------------------+\n"); - PrintAndLogEx(NORMAL, "CSN |00| %s|\n", sprint_hex(tag_data, 8)); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "------+--+-------------------------+"); + PrintAndLogEx(NORMAL, "CSN |00| %s|", sprint_hex(tag_data, 8)); printIclassDumpContents(tag_data, 1, (gotBytes / 8), gotBytes); if (filename[0] == 0) { - snprintf(filename, FILE_PATH_SIZE, "iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x", - tag_data[0], tag_data[1], tag_data[2], tag_data[3], - tag_data[4], tag_data[5], tag_data[6], tag_data[7]); + //Use the first block (CSN) for filename + strcat(filename, "hf-iclass-"); + FillFileNameByUID(filename, tag_data, "-data", 8); } // save the dump to .bin file PrintAndLogEx(SUCCESS, "saving dump file - %d blocks read", gotBytes / 8); saveFile(filename, ".bin", tag_data, gotBytes); - return 1; + saveFileEML(filename, tag_data, gotBytes, 8); + saveFileJSON(filename, jsfIclass, tag_data, gotBytes); + return PM3_SUCCESS; } static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool verbose) { - uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00}; - uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) - return 0; - PacketResponseNG resp; + int numberAuthRetries = ICLASS_AUTH_RETRY; + do { + + uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00}; + uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) { + numberAuthRetries--; + DropField(); + continue; + } - Calc_wb_mac(blockno, bldata, div_key, MAC); - uint8_t data[12]; - memcpy(data, bldata, 8); - memcpy(data + 8, MAC, 4); + Calc_wb_mac(blockno, bldata, div_key, MAC); - clearCommandBuffer(); - SendCommandOLD(CMD_ICLASS_WRITEBLOCK, blockno, 0, 0, data, sizeof(data)); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) { - if (verbose) PrintAndLogEx(WARNING, "Write Command execute timeout"); - return 0; + struct p { + uint8_t blockno; + uint8_t data[12]; + } PACKED payload; + payload.blockno = blockno; + + memcpy(payload.data, bldata, 8); + memcpy(payload.data + 8, MAC, 4); + + clearCommandBuffer(); + SendCommandNG(CMD_HF_ICLASS_WRITEBL, (uint8_t*)&payload, sizeof(payload)); + PacketResponseNG resp; + + if (WaitForResponseTimeout(CMD_HF_ICLASS_WRITEBL, &resp, 4000) == 0) { + if (verbose) PrintAndLogEx(WARNING, "Command execute timeout"); + DropField(); + return PM3_ETIMEOUT; + } + + if ( resp.status != PM3_SUCCESS ) { + if (verbose) PrintAndLogEx(ERR, "failed to communicate with card"); + DropField(); + return PM3_EWRONGANSVER; + } + + if (resp.data.asBytes[0] == 1) + break; + + } while (numberAuthRetries); + + DropField(); + + if ( numberAuthRetries > 0 ) { + PrintAndLogEx(SUCCESS, "Write block %02X successful\n", blockno); + } else { + PrintAndLogEx(ERR,"failed to authenticate and write block"); + return PM3_ESOFT; } - uint8_t isOK = resp.oldarg[0] & 0xff; - if (isOK) - PrintAndLogEx(SUCCESS, "Write block successful"); - else - PrintAndLogEx(WARNING, "Write block failed"); - return isOK; + + return PM3_SUCCESS; } static int CmdHFiClass_WriteBlock(const char *Cmd) { @@ -1099,6 +1402,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { uint8_t keyNbr = 0; uint8_t dataLen = 0; char tempStr[50] = {0}; + bool got_blockno = false; bool use_credit_key = false; bool elite = false; bool rawkey = false; @@ -1110,13 +1414,12 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { case 'h': return usage_hf_iclass_writeblock(); case 'b': - if (param_gethex(Cmd, cmdp + 1, &blockno, 2)) { - PrintAndLogEx(WARNING, "Block No must include 2 HEX symbols\n"); - errors = true; - } + blockno = param_get8ex(Cmd, cmdp + 1, 07, 16); + got_blockno = true; cmdp += 2; break; case 'c': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("CREDIT")); use_credit_key = true; cmdp++; break; @@ -1128,6 +1431,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { cmdp += 2; break; case 'e': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo")); elite = true; cmdp++; break; @@ -1138,6 +1442,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { } else if (dataLen == 1) { keyNbr = param_get8(Cmd, cmdp + 1); if (keyNbr < ICLASS_KEYS_MAX) { + PrintAndLogEx(SUCCESS, "Using key[%d] %s", keyNbr, sprint_hex(iClass_Key_Table[keyNbr], 8 )); memcpy(KEY, iClass_Key_Table[keyNbr], 8); } else { PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n"); @@ -1150,6 +1455,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { cmdp += 2; break; case 'r': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("raw mode")); rawkey = true; cmdp++; break; @@ -1163,11 +1469,12 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { break; } } + if ( got_blockno == false) + errors = true; + if (errors || cmdp < 6) return usage_hf_iclass_writeblock(); - int ans = WriteBlock(blockno, bldata, KEY, use_credit_key, elite, rawkey, verbose); - DropField(); - return ans; + return WriteBlock(blockno, bldata, KEY, use_credit_key, elite, rawkey, verbose); } static int CmdHFiClassCloneTag(const char *Cmd) { @@ -1179,6 +1486,7 @@ static int CmdHFiClassCloneTag(const char *Cmd) { uint8_t startblock = 0; uint8_t endblock = 0; uint8_t dataLen = 0; + bool got_startblk = false, got_endblk = false; bool use_credit_key = false; bool elite = false; bool rawkey = false; @@ -1190,17 +1498,17 @@ static int CmdHFiClassCloneTag(const char *Cmd) { case 'h': return usage_hf_iclass_clone(); case 'b': - if (param_gethex(Cmd, cmdp + 1, &startblock, 2)) { - PrintAndLogEx(WARNING, "start block No must include 2 HEX symbols\n"); - errors = true; - } + startblock = param_get8ex(Cmd, cmdp + 1, 07, 16); + got_startblk = true; cmdp += 2; break; case 'c': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("CREDIT")); use_credit_key = true; cmdp++; break; case 'e': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo")); elite = true; cmdp++; break; @@ -1219,6 +1527,7 @@ static int CmdHFiClassCloneTag(const char *Cmd) { } else if (dataLen == 1) { keyNbr = param_get8(Cmd, cmdp + 1); if (keyNbr < ICLASS_KEYS_MAX) { + PrintAndLogEx(SUCCESS, "Using key[%d] %s", keyNbr, sprint_hex(iClass_Key_Table[keyNbr], 8 )); memcpy(KEY, iClass_Key_Table[keyNbr], 8); } else { PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n"); @@ -1231,13 +1540,12 @@ static int CmdHFiClassCloneTag(const char *Cmd) { cmdp += 2; break; case 'l': - if (param_gethex(Cmd, cmdp + 1, &endblock, 2)) { - PrintAndLogEx(WARNING, "start Block No must include 2 HEX symbols\n"); - errors = true; - } + endblock = param_get8ex(Cmd, cmdp + 1, 07, 16); + got_endblk = true; cmdp += 2; break; case 'r': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("raw mode")); rawkey = true; cmdp++; break; @@ -1251,53 +1559,66 @@ static int CmdHFiClassCloneTag(const char *Cmd) { break; } } + if ( got_endblk == false || got_startblk == false) + errors = true; if (errors || cmdp < 8) return usage_hf_iclass_clone(); - FILE *f; - - iclass_block_t tag_data[PM3_CMD_DATA_SIZE / 12]; - - if ((endblock - startblock + 1) * 12 > PM3_CMD_DATA_SIZE) { - PrintAndLogEx(NORMAL, "Trying to write too many blocks at once. Max: %d", PM3_CMD_DATA_SIZE / 8); + if (startblock < 5) { + PrintAndLogEx(WARNING, "you cannot write key blocks this way. yet... make your start block > 4"); + return PM3_EINVARG; } + + int total_bytes = (((endblock - startblock) + 1) * 12); + + if (total_bytes > PM3_CMD_DATA_SIZE - 2) { + PrintAndLogEx(NORMAL, "Trying to write too many blocks at once. Max: %d", PM3_CMD_DATA_SIZE / 8); + return PM3_EINVARG; + } + // file handling and reading - f = fopen(filename, "rb"); + FILE *f = fopen(filename, "rb"); if (!f) { PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename); return PM3_EFILE; } - if (startblock < 5) { - PrintAndLogEx(WARNING, "you cannot write key blocks this way. yet... make your start block > 4"); - fclose(f); - return 0; - } - // now read data from the file from block 6 --- 19 - // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data - // then copy to usbcommand->asbytes; the max is 32 - 6 = 24 block 12 bytes each block 288 bytes then we can only accept to clone 21 blocks at the time, - // else we have to create a share memory + iclass_block_t tag_data[PM3_CMD_DATA_SIZE / 12]; + + // read data from file from block 6 --- 19 + // we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data + // then copy to usbcommand->asbytes; + // max is 32 - 6 = 28 block. 28 x 12 bytes gives 336 bytes int i; fseek(f, startblock * 8, SEEK_SET); size_t bytes_read = fread(tag_data, sizeof(iclass_block_t), endblock - startblock + 1, f); + fclose(f); + if (bytes_read == 0) { PrintAndLogEx(ERR, "file reading error."); - fclose(f); - return 2; + return PM3_EFILE; } - fclose(f); - uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) { - return 0; + + int numberAuthRetries = ICLASS_AUTH_RETRY; + do { + if (select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) + break; + } while (numberAuthRetries--); + + if ( numberAuthRetries <= 0 ) { + PrintAndLogEx(ERR, "failed to authenticate"); + DropField(); + return PM3_ESOFT; } - uint8_t data[(endblock - startblock) * 12]; + uint8_t data[total_bytes]; + // calculate all mac for every the block we will write for (i = startblock; i <= endblock; i++) { + Calc_wb_mac(i, tag_data[i - startblock].d, div_key, MAC); // usb command d start pointer = d + (i - 6) * 12 // memcpy(pointer,tag_data[i - 6],8) 8 bytes @@ -1307,54 +1628,113 @@ static int CmdHFiClassCloneTag(const char *Cmd) { memcpy(ptr, &(tag_data[i - startblock].d[0]), 8); memcpy(ptr + 8, MAC, 4); } - uint8_t p[12]; - for (i = 0; i <= endblock - startblock; i++) { - memcpy(p, data + (i * 12), 12); - PrintAndLogEx(NORMAL, "Block |%02x|", i + startblock); - PrintAndLogEx(NORMAL, " %02x%02x%02x%02x%02x%02x%02x%02x |", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); - PrintAndLogEx(NORMAL, " MAC |%02x%02x%02x%02x|\n", p[8], p[9], p[10], p[11]); + + if ( verbose ) { + PrintAndLogEx(NORMAL,"------+--------------------------+-------------"); + PrintAndLogEx(NORMAL,"block | data | mac"); + PrintAndLogEx(NORMAL,"------+--------------------------+-------------"); + uint8_t p[12]; + for (i = 0; i <= endblock - startblock; i++) { + memcpy(p, data + (i * 12), 12); + char *s = calloc(70, sizeof(uint8_t)); + sprintf(s, "| %s ", sprint_hex(p, 8)); + sprintf(s + strlen(s), "| %s", sprint_hex(p + 8, 4)); + PrintAndLogEx(NORMAL, " %02X %s", i + startblock, s ); + free(s); + } } + struct p { + uint8_t startblock; + uint8_t endblock; + uint8_t data[PM3_CMD_DATA_SIZE - 2]; + } PACKED payload; + + payload.startblock = startblock; + payload.endblock = endblock; + memcpy(payload.data, data, total_bytes); + PacketResponseNG resp; clearCommandBuffer(); - SendCommandOLD(CMD_ICLASS_CLONE, startblock, endblock, 0, data, (endblock - startblock) * 12); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) { + SendCommandNG(CMD_HF_ICLASS_CLONE, (uint8_t*)&payload, total_bytes + 2 ); + + if (WaitForResponseTimeout(CMD_HF_ICLASS_CLONE, &resp, 4500) == 0) { PrintAndLogEx(WARNING, "command execute timeout"); - return 0; + DropField(); + return PM3_ETIMEOUT; } - return PM3_SUCCESS; + + if (resp.status == PM3_SUCCESS) { + if ( resp.data.asBytes[0] == 1 ) + PrintAndLogEx(SUCCESS, "Clone successful"); + else + PrintAndLogEx(WARNING, "Clone failed"); + } + return resp.status; } static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool verbose, bool auth) { - // block 0,1 should always be able to read, and block 5 on some cards. - if (auth || blockno >= 2) { - uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00}; - uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - if (!select_and_auth(KEY, MAC, div_key, (keyType == 0x18), elite, rawkey, verbose)) - return 0; - } else { - uint8_t CSN[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - if (!select_only(CSN, CCNR, (keyType == 0x18), verbose)) - return 0; + + int numberAuthRetries = ICLASS_AUTH_RETRY; + // return data. + struct p { + bool isOK; + uint8_t blockdata[8]; + } PACKED; + + struct p *result = NULL; + + do { + // block 0,1 should always be able to read, and block 5 on some cards. + if (auth || blockno >= 2) { + uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00}; + uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + if (!select_and_auth(KEY, MAC, div_key, (keyType == 0x18), elite, rawkey, verbose)) { + numberAuthRetries--; + DropField(); + continue; + } + } else { + uint8_t CSN[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + if (!select_only(CSN, CCNR, (keyType == 0x18), verbose)) { + numberAuthRetries--; + DropField(); + continue; + } + } + + PacketResponseNG resp; + clearCommandBuffer(); + SendCommandNG(CMD_HF_ICLASS_READBL, (uint8_t*)&blockno, sizeof(uint8_t)); + + if (WaitForResponseTimeout(CMD_HF_ICLASS_READBL, &resp, 2000) == 0) { + if (verbose) PrintAndLogEx(WARNING, "Command execute timeout"); + DropField(); + return PM3_ETIMEOUT; + } + + if ( resp.status != PM3_SUCCESS ) { + if (verbose) PrintAndLogEx(ERR, "failed to communicate with card"); + DropField(); + return PM3_EWRONGANSVER; + } + + result = (struct p*)resp.data.asBytes; + if (result->isOK) + break; + + } while (numberAuthRetries); + + DropField(); + + if ( numberAuthRetries == 0 ) { + PrintAndLogEx(ERR,"failed to authenticate and read block"); + return PM3_ESOFT; } - PacketResponseNG resp; - clearCommandBuffer(); - SendCommandMIX(CMD_ICLASS_READBLOCK, blockno, 0, 0, NULL, 0); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) { - PrintAndLogEx(WARNING, "Command execute timeout"); - return 0; - } - - uint8_t isOK = resp.oldarg[0] & 0xff; - if (!isOK) { - PrintAndLogEx(WARNING, "read block failed"); - return 0; - } - //data read is stored in: resp.data.asBytes[0-15] - PrintAndLogEx(NORMAL, "block %02X: %s\n", blockno, sprint_hex(resp.data.asBytes, 8)); - return 1; + PrintAndLogEx(SUCCESS, "block %02X: %s\n", blockno, sprint_hex(result->blockdata, sizeof(result->blockdata))); + return PM3_SUCCESS; } static int CmdHFiClass_ReadBlock(const char *Cmd) { @@ -1364,6 +1744,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { uint8_t keyNbr = 0; uint8_t dataLen = 0; char tempStr[50] = {0}; + bool got_blockno = false; bool elite = false; bool rawkey = false; bool errors = false; @@ -1375,17 +1756,17 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { case 'h': return usage_hf_iclass_readblock(); case 'b': - if (param_gethex(Cmd, cmdp + 1, &blockno, 2)) { - PrintAndLogEx(WARNING, "Block No must include 2 HEX symbols\n"); - errors = true; - } + blockno = param_get8ex(Cmd, cmdp + 1, 7, 16); + got_blockno = true; cmdp += 2; break; case 'c': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("CREDIT")); keyType = 0x18; cmdp++; break; case 'e': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo")); elite = true; cmdp++; break; @@ -1397,6 +1778,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { } else if (dataLen == 1) { keyNbr = param_get8(Cmd, cmdp + 1); if (keyNbr < ICLASS_KEYS_MAX) { + PrintAndLogEx(SUCCESS, "Using key[%d] %s", keyNbr, sprint_hex(iClass_Key_Table[keyNbr], 8 )); memcpy(KEY, iClass_Key_Table[keyNbr], 8); } else { PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n"); @@ -1409,6 +1791,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { cmdp += 2; break; case 'r': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("raw mode")); rawkey = true; cmdp++; break; @@ -1422,10 +1805,14 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { break; } } + if ( got_blockno == false) + errors = true; + if (errors || cmdp < 4) return usage_hf_iclass_readblock(); if (!auth) PrintAndLogEx(FAILED, "warning: no authentication used with read, only a few specific blocks can be read accurately without authentication."); + return ReadBlock(KEY, blockno, keyType, elite, rawkey, verbose, auth); } @@ -1433,7 +1820,7 @@ static int CmdHFiClass_loclass(const char *Cmd) { char opt = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) < 1 || opt == 'h') - usage_hf_iclass_loclass(); + return usage_hf_iclass_loclass(); if (opt == 'f') { char fileName[FILE_PATH_SIZE] = {0}; @@ -1441,15 +1828,15 @@ static int CmdHFiClass_loclass(const char *Cmd) { return bruteforceFileNoKeys(fileName); } else { PrintAndLogEx(WARNING, "You must specify a filename"); - return 0; + return PM3_EFILE; } } else if (opt == 't') { int errors = testCipherUtils(); errors += testMAC(); errors += doKeyTests(0); errors += testElite(); - if (errors) PrintAndLogDevice(ERR, "There were errors!!!"); - return errors; + if (errors) PrintAndLogEx(ERR, "There were errors!!!"); + return PM3_ESOFT; } return PM3_SUCCESS; } @@ -1479,13 +1866,13 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e //PrintAndLog ("startblock: %d, endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d",startblock, endblock,filesize, maxmemcount, filemaxblock); int i = startblock; - PrintAndLogEx(NORMAL, "------+--+-------------------------+\n"); + PrintAndLogEx(NORMAL, "------+--+-------------------------+"); while (i <= endblock) { uint8_t *blk = iclass_dump + (i * 8); - PrintAndLogEx(NORMAL, " |%02X| %s\n", i, sprint_hex_ascii(blk, 8)); + PrintAndLogEx(NORMAL, " |%02X| %s", i, sprint_hex_ascii(blk, 8)); i++; } - PrintAndLogEx(NORMAL, "------+--+-------------------------+\n"); + PrintAndLogEx(NORMAL, "------+--+-------------------------+"); } static int CmdHFiClassReadTagFile(const char *Cmd) { @@ -1570,7 +1957,7 @@ static void HFiClassCalcNewKey(uint8_t *CSN, uint8_t *OLDKEY, uint8_t *NEWKEY, u //get new div key HFiClassCalcDivKey(CSN, NEWKEY, new_div_key, elite); - for (uint8_t i = 0; i < sizeof(old_div_key); i++) { + for (uint8_t i = 0; i < ARRAYLEN(old_div_key); i++) { xor_div_key[i] = old_div_key[i] ^ new_div_key[i]; } if (verbose) { @@ -1656,8 +2043,10 @@ static int CmdHFiClassCalcNewKey(const char *Cmd) { if (!givenCSN) { uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - if (!select_only(CSN, CCNR, false, true)) + if (!select_only(CSN, CCNR, false, true)) { + DropField(); return 0; + } } HFiClassCalcNewKey(CSN, OLDKEY, NEWKEY, xor_div_key, elite, oldElite, true); @@ -1699,7 +2088,7 @@ static int loadKeys(char *filename) { memcpy(iClass_Key_Table[i], dump + (i * 8), 8); free(dump); - PrintAndLogEx(SUCCESS, "%u keys loaded", i); + PrintAndLogEx(SUCCESS, "Loaded " _GREEN_("%2d") "keys from %s", i, filename); return PM3_SUCCESS; } @@ -1722,8 +2111,12 @@ static int saveKeys(char *filename) { static int printKeys(void) { PrintAndLogEx(NORMAL, ""); - for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++) - PrintAndLogEx(NORMAL, "%u: %s", i, sprint_hex(iClass_Key_Table[i], 8)); + for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++) { + if (memcmp(iClass_Key_Table[i], "\x00\x00\x00\x00\x00\x00\x00\x00", 8) == 0) + PrintAndLogEx(NORMAL, "%u: %s", i, sprint_hex(iClass_Key_Table[i], 8)); + else + PrintAndLogEx(NORMAL, "%u: "_YELLOW_("%s"), i, sprint_hex(iClass_Key_Table[i], 8)); + } PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -1746,7 +2139,7 @@ static int CmdHFiClassManageKeys(const char *Cmd) { case 'f': fileNameLen = param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); if (fileNameLen < 1) { - PrintAndLogEx(WARNING, "No filename found after f"); + PrintAndLogEx(ERR, "No filename found"); errors = true; } cmdp += 2; @@ -1754,7 +2147,7 @@ static int CmdHFiClassManageKeys(const char *Cmd) { case 'n': keyNbr = param_get8(Cmd, cmdp + 1); if (keyNbr >= ICLASS_KEYS_MAX) { - PrintAndLogEx(WARNING, "Invalid block number"); + PrintAndLogEx(ERR, "Invalid block number, MAX is " _YELLOW_("%d"), ICLASS_KEYS_MAX); errors = true; } cmdp += 2; @@ -1806,14 +2199,13 @@ static int CmdHFiClassManageKeys(const char *Cmd) { switch (operation) { case 3: memcpy(iClass_Key_Table[keyNbr], KEY, 8); - return 1; + return PM3_SUCCESS; case 4: return printKeys(); case 5: return loadKeys(filename); case 6: return saveKeys(filename); - break; } return PM3_SUCCESS; } @@ -1838,10 +2230,7 @@ static int CmdHFiClassCheckKeys(const char *Cmd) { char filename[FILE_PATH_SIZE] = {0}; uint8_t fileNameLen = 0; - - uint8_t *keyBlock = NULL; iclass_premac_t *pre = NULL; - int keycnt = 0; // time uint64_t t1 = msclock(); @@ -1853,7 +2242,7 @@ static int CmdHFiClassCheckKeys(const char *Cmd) { case 'f': fileNameLen = param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); if (fileNameLen < 1) { - PrintAndLogEx(WARNING, "no filename found after f"); + PrintAndLogEx(WARNING, _RED_("no filename found after f")); errors = true; } cmdp += 2; @@ -1879,62 +2268,64 @@ static int CmdHFiClassCheckKeys(const char *Cmd) { if (errors) return usage_hf_iclass_chk(); + uint8_t *keyBlock = NULL; + uint16_t keycount = 0; + + // load keys + int res = loadFileDICTIONARY_safe(filename, (void **)&keyBlock, 8, &keycount); + if (res != PM3_SUCCESS || keycount == 0) { + free(keyBlock); + return res; + } + // Get CSN / UID and CCNR PrintAndLogEx(SUCCESS, "Reading tag CSN"); - for (uint8_t i = 0; i < 10 && !got_csn; i++) { - if (select_only(CSN, CCNR, false, false)) { - got_csn = true; - } else { - PrintAndLogEx(WARNING, "one more try\n"); - } + for (uint8_t i = 0; i < ICLASS_AUTH_RETRY && !got_csn; i++) { + got_csn = select_only(CSN, CCNR, false, false); + if (got_csn == false) + PrintAndLogEx(WARNING, "one more try"); } - if (!got_csn) { - PrintAndLogEx(WARNING, "can't select card, aborting..."); - return 1; + if (got_csn == false) { + PrintAndLogEx(WARNING, "Tried 10 times. Can't select card, aborting..."); + DropField(); + return PM3_ESOFT; } - // load keys into keyblock - int res = LoadDictionaryKeyFile(filename, &keyBlock, &keycnt); - if (res > 0) { - free(keyBlock); - return 1; - } - - pre = calloc(keycnt, sizeof(iclass_premac_t)); + pre = calloc(keycount, sizeof(iclass_premac_t)); if (!pre) { + DropField(); free(keyBlock); - return 1; + return PM3_EMALLOC; } - PrintAndLogEx(SUCCESS, "Generating diversified keys, MAC"); + PrintAndLogEx(SUCCESS, "Generating diversified keys"); if (use_elite) - PrintAndLogEx(SUCCESS, "Using elite algo"); + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo")); if (use_raw) - PrintAndLogEx(SUCCESS, "Using raw mode"); + PrintAndLogEx(SUCCESS, "Using " _YELLOW_(" raw mode")); - PrintAndLogEx(SUCCESS, "Searching for %s key", (use_credit_key) ? "CREDIT" : "DEBIT"); + PrintAndLogEx(SUCCESS, "Searching for " _YELLOW_("%s") "key", (use_credit_key) ? "CREDIT" : "DEBIT"); PrintAndLogEx(SUCCESS, "Tag info"); PrintAndLogEx(SUCCESS, "CSN | %s", sprint_hex(CSN, sizeof(CSN))); PrintAndLogEx(SUCCESS, "CCNR | %s", sprint_hex(CCNR, sizeof(CCNR))); - res = GenerateMacFromKeyFile(CSN, CCNR, use_raw, use_elite, keyBlock, keycnt, pre); - if (res > 0) { - free(keyBlock); - free(pre); - return 1; - } + + GenerateMacFrom(CSN, CCNR, use_raw, use_elite, keyBlock, keycount, pre); //PrintPreCalcMac(keyBlock, keycnt, pre); // max 42 keys inside USB_COMMAND. 512/4 = 103 mac - uint32_t chunksize = keycnt > (PM3_CMD_DATA_SIZE / 4) ? (PM3_CMD_DATA_SIZE / 4) : keycnt; + uint32_t chunksize = keycount > (PM3_CMD_DATA_SIZE / 4) ? (PM3_CMD_DATA_SIZE / 4) : keycount; bool lastChunk = false; // fast push mode conn.block_after_ACK = true; + // keep track of position of found key + uint8_t found_offset = 0; + uint32_t key_offset = 0; // main keychunk loop - for (uint32_t i = 0; i < keycnt; i += chunksize) { + for (uint32_t key_offset = 0; key_offset < keycount; key_offset += chunksize) { uint64_t t2 = msclock(); uint8_t timeout = 0; @@ -1944,10 +2335,10 @@ static int CmdHFiClassCheckKeys(const char *Cmd) { goto out; } - uint32_t keys = ((keycnt - i) > chunksize) ? chunksize : keycnt - i; + uint32_t keys = ((keycount - key_offset) > chunksize) ? chunksize : keycount - key_offset; // last chunk? - if (keys == keycnt - i) { + if (keys == keycount - key_offset) { lastChunk = true; // Disable fast mode on last command conn.block_after_ACK = false; @@ -1959,7 +2350,7 @@ static int CmdHFiClassCheckKeys(const char *Cmd) { flags |= (use_credit_key << 16); clearCommandBuffer(); - SendCommandOLD(CMD_ICLASS_CHECK_KEYS, flags, keys, 0, pre + i, 4 * keys); + SendCommandOLD(CMD_HF_ICLASS_CHKKEYS, flags, keys, 0, pre + key_offset, 4 * keys); PacketResponseNG resp; while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { @@ -1972,7 +2363,7 @@ static int CmdHFiClassCheckKeys(const char *Cmd) { } } - uint8_t found = resp.oldarg[1] & 0xFF; + found_offset = resp.oldarg[1] & 0xFF; uint8_t isOK = resp.oldarg[0] & 0xFF; t2 = msclock() - t2; @@ -1980,20 +2371,20 @@ static int CmdHFiClassCheckKeys(const char *Cmd) { case 1: { found_debit = true; - PrintAndLogEx(NORMAL, "\n[-] Chunk [%d/%d]: %.1fs [%s] found key %s (index %u)" - , i - , keycnt + PrintAndLogEx(NORMAL, "\n[-] Chunk [%d/%d]: %.1fs [%s] idx [%u] - found key "_YELLOW_("%s") + , key_offset + , keycount , (float)(t2 / 1000.0) , (use_credit_key) ? "credit" : "debit" - , sprint_hex(keyBlock + (i + found) * 8, 8) - , found + , found_offset + , sprint_hex(keyBlock + (key_offset + found_offset) * 8, 8) ); break; } case 0: { PrintAndLogEx(NORMAL, "\n[-] Chunk [%d/%d] : %.1fs [%s]" - , i - , keycnt + , key_offset + , keycount , (float)(t2 / 1000.0) , (use_credit_key) ? "credit" : "debit" ); @@ -2017,8 +2408,22 @@ out: t1 = msclock() - t1; PrintAndLogEx(SUCCESS, "\nTime in iclass checkkeys: %.0f seconds\n", (float)t1 / 1000.0); - DropField(); + + // add to managekeys + if (found_debit) { + for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++) { + // simple check for preexistences + if (memcmp(iClass_Key_Table[i], keyBlock + (key_offset + found_offset) * 8, 8) == 0) break; + + if (memcmp(iClass_Key_Table[i], "\x00\x00\x00\x00\x00\x00\x00\x00", 8) == 0) { + memcpy(iClass_Key_Table[i], keyBlock + (key_offset + found_offset) * 8, 8); + PrintAndLogEx(SUCCESS, "Added key to keyslot [%d] - "_YELLOW_("`hf iclass managekeys p`")" to view", i); + break; + } + } + } + free(pre); free(keyBlock); return PM3_SUCCESS; @@ -2055,12 +2460,9 @@ static int CmdHFiClassLookUp(const char *Cmd) { uint8_t cmdp = 0x00; char filename[FILE_PATH_SIZE] = {0}; - uint8_t fileNameLen = 0; - uint8_t *keyBlock = NULL; iclass_prekey_t *prekey = NULL; - int keycnt = 0, len = 0; - + int len = 0; // if empty string if (strlen(Cmd) == 0) errors = true; // time @@ -2071,8 +2473,7 @@ static int CmdHFiClassLookUp(const char *Cmd) { case 'h': return usage_hf_iclass_lookup(); case 'f': - fileNameLen = param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); - if (fileNameLen < 1) { + if (param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)) < 1) { PrintAndLogEx(WARNING, "No filename found after f"); errors = true; } @@ -2131,103 +2532,67 @@ static int CmdHFiClassLookUp(const char *Cmd) { PrintAndLogEx(SUCCESS, "CCNR | %s", sprint_hex(CCNR, sizeof(CCNR))); PrintAndLogEx(SUCCESS, "MAC_TAG | %s", sprint_hex(MAC_TAG, sizeof(MAC_TAG))); - int res = LoadDictionaryKeyFile(filename, &keyBlock, &keycnt); - if (res > 0) { + uint8_t *keyBlock = NULL; + uint16_t keycount = 0; + + // load keys + int res = loadFileDICTIONARY_safe(filename, (void **)&keyBlock, 8, &keycount); + if (res != PM3_SUCCESS || keycount == 0) { free(keyBlock); - return 1; + return res; } + //iclass_prekey_t - prekey = calloc(keycnt, sizeof(iclass_prekey_t)); + prekey = calloc(keycount, sizeof(iclass_prekey_t)); if (!prekey) { free(keyBlock); - return 1; + return PM3_EMALLOC; } - PrintAndLogEx(FAILED, "Generating diversified keys and MAC"); - res = GenerateFromKeyFile(CSN, CCNR, use_raw, use_elite, keyBlock, keycnt, prekey); - if (res > 0) { - free(keyBlock); - free(prekey); - return 1; - } + PrintAndLogEx(INFO, "Generating diversified keys"); + GenerateMacKeyFrom(CSN, CCNR, use_raw, use_elite, keyBlock, keycount, prekey); - PrintAndLogEx(FAILED, "Sorting"); + PrintAndLogEx(INFO, "Sorting"); // sort mac list. - qsort(prekey, keycnt, sizeof(iclass_prekey_t), cmp_uint32); + qsort(prekey, keycount, sizeof(iclass_prekey_t), cmp_uint32); //PrintPreCalc(prekey, keycnt); - PrintAndLogEx(FAILED, "Searching"); + PrintAndLogEx(INFO, "Searching"); iclass_prekey_t *item; iclass_prekey_t lookup; memcpy(lookup.mac, MAC_TAG, 4); // binsearch - item = (iclass_prekey_t *) bsearch(&lookup, prekey, keycnt, sizeof(iclass_prekey_t), cmp_uint32); - if (item != NULL) - PrintAndLogEx(SUCCESS, "\n[debit] found key %s", sprint_hex(item->key, 8)); + item = (iclass_prekey_t *) bsearch(&lookup, prekey, keycount, sizeof(iclass_prekey_t), cmp_uint32); t1 = msclock() - t1; PrintAndLogEx(NORMAL, "\nTime in iclass : %.0f seconds\n", (float)t1 / 1000.0); + + // foudn + if (item != NULL) { + PrintAndLogEx(SUCCESS, "[debit] found key " _YELLOW_("%s"), sprint_hex(item->key, 8)); + for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++) { + // simple check for preexistences + if (memcmp(item->key, iClass_Key_Table[i], 8) == 0) break; + + if (memcmp(iClass_Key_Table[i], "\x00\x00\x00\x00\x00\x00\x00\x00", 8) == 0) { + memcpy(iClass_Key_Table[i], item->key, 8); + PrintAndLogEx(SUCCESS, "Added key to keyslot [%d] - "_YELLOW_("`hf iclass managekeys p`")"to view", i); + break; + } + } + } + free(prekey); free(keyBlock); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } -int LoadDictionaryKeyFile(char *filename, uint8_t **keys, int *keycnt) { - - char buf[17]; - FILE *f; - uint8_t *p; - int keyitems = 0; - - if (!(f = fopen(filename, "r"))) { - PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename); - return 1; - } - - while (fgets(buf, sizeof(buf), f)) { - if (strlen(buf) < 16 || buf[15] == '\n') - continue; - - //goto next line - while (fgetc(f) != '\n' && !feof(f)) {}; - - //The line start with # is comment, skip - if (buf[0] == '#') - continue; - - // doesn't this only test first char only? - if (!isxdigit(buf[0])) { - PrintAndLogEx(ERR, "file content error. '%s' must include 16 HEX symbols", buf); - continue; - } - - // null terminator (skip the rest of the line) - buf[16] = 0; - - p = realloc(*keys, 8 * (keyitems += 64)); - if (!p) { - PrintAndLogEx(ERR, "cannot allocate memory for default keys"); - fclose(f); - return 2; - } - *keys = p; - - memset(*keys + 8 * (*keycnt), 0, 8); - num_to_bytes(strtoull(buf, NULL, 16), 8, *keys + 8 * (*keycnt)); - (*keycnt)++; - memset(buf, 0, sizeof(buf)); - } - fclose(f); - PrintAndLogEx(SUCCESS, "Loaded " _GREEN_("%2d") " keys from %s", *keycnt, filename); - return PM3_SUCCESS; -} - // precalc diversified keys and their MAC -int GenerateMacFromKeyFile(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elite, uint8_t *keys, int keycnt, iclass_premac_t *list) { +void GenerateMacFrom(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elite, uint8_t *keys, int keycnt, iclass_premac_t *list) { uint8_t key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; @@ -2242,10 +2607,9 @@ int GenerateMacFromKeyFile(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_e doMAC(CCNR, div_key, list[i].mac); } - return PM3_SUCCESS; } -int GenerateFromKeyFile(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elite, uint8_t *keys, int keycnt, iclass_prekey_t *list) { +void GenerateMacKeyFrom(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elite, uint8_t *keys, int keycnt, iclass_prekey_t *list) { uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; @@ -2262,7 +2626,6 @@ int GenerateFromKeyFile(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elit // generate MAC doMAC(CCNR, div_key, list[i].mac); } - return PM3_SUCCESS; } // print diversified keys @@ -2396,25 +2759,26 @@ static int CmdHFiClassPermuteKey(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"calcnewkey", CmdHFiClassCalcNewKey, AlwaysAvailable, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"}, - {"chk", CmdHFiClassCheckKeys, AlwaysAvailable, " Check keys"}, - {"clone", CmdHFiClassCloneTag, IfPm3Iclass, "[options..] Authenticate and Clone from iClass bin file"}, - {"decrypt", CmdHFiClassDecrypt, AlwaysAvailable, "[f ] Decrypt tagdump" }, - {"dump", CmdHFiClassReader_Dump, IfPm3Iclass, "[options..] Authenticate and Dump iClass tag's AA1"}, - {"eload", CmdHFiClassELoad, IfPm3Iclass, "[f ] (experimental) Load data into iClass emulator memory"}, - {"encryptblk", CmdHFiClassEncryptBlk, AlwaysAvailable, " Encrypt given block data"}, - {"list", CmdHFiClassList, AlwaysAvailable, " List iClass history"}, - {"loclass", CmdHFiClass_loclass, AlwaysAvailable, "[options..] Use loclass to perform bruteforce of reader attack dump"}, + {"calcnewkey", CmdHFiClassCalcNewKey, AlwaysAvailable, "[options..] Calc diversified keys (blocks 3 & 4) to write new keys"}, + {"chk", CmdHFiClassCheckKeys, AlwaysAvailable, "[options..] Check keys"}, + {"clone", CmdHFiClassCloneTag, IfPm3Iclass, "[options..] Restore a dump file onto a iClass tag"}, + {"decrypt", CmdHFiClassDecrypt, AlwaysAvailable, "[options..] Decrypt given block data or tag dump file" }, + {"dump", CmdHFiClassReader_Dump, IfPm3Iclass, "[options..] Dump iClass tag to file"}, + {"eload", CmdHFiClassELoad, IfPm3Iclass, "[f ] Load iClass dump file into emulator memory"}, + {"encrypt", CmdHFiClassEncryptBlk, AlwaysAvailable, "[options..] Encrypt given block data"}, + {"info", CmdHFiClassInfo, AlwaysAvailable, " Tag information"}, + {"list", CmdHFiClassList, AlwaysAvailable, " List iClass history"}, + {"loclass", CmdHFiClass_loclass, AlwaysAvailable, "[options..] Use loclass to perform bruteforce reader attack"}, {"lookup", CmdHFiClassLookUp, AlwaysAvailable, "[options..] Uses authentication trace to check for key in dictionary file"}, - {"managekeys", CmdHFiClassManageKeys, AlwaysAvailable, "[options..] Manage the keys to use with iClass"}, + {"managekeys", CmdHFiClassManageKeys, AlwaysAvailable, "[options..] Manage keys to use with iClass"}, {"permutekey", CmdHFiClassPermuteKey, IfPm3Iclass, " Permute function from 'heart of darkness' paper"}, - {"readblk", CmdHFiClass_ReadBlock, IfPm3Iclass, "[options..] Authenticate and Read iClass block"}, + {"rdbl", CmdHFiClass_ReadBlock, IfPm3Iclass, "[options..] Read iClass block"}, {"reader", CmdHFiClassReader, IfPm3Iclass, " Act like an iClass reader"}, - {"readtagfile", CmdHFiClassReadTagFile, AlwaysAvailable, "[options..] Display Content from tagfile"}, - {"replay", CmdHFiClassReader_Replay, IfPm3Iclass, " Read an iClass tag via Replay Attack"}, + {"readtagfile", CmdHFiClassReadTagFile, AlwaysAvailable, "[options..] Display content from tag dump file"}, + {"replay", CmdHFiClassReader_Replay, IfPm3Iclass, " Read iClass tag via replay attack"}, {"sim", CmdHFiClassSim, IfPm3Iclass, "[options..] Simulate iClass tag"}, {"sniff", CmdHFiClassSniff, IfPm3Iclass, " Eavesdrop iClass communication"}, - {"writeblk", CmdHFiClass_WriteBlock, IfPm3Iclass, "[options..] Authenticate and Write iClass block"}, + {"wrbl", CmdHFiClass_WriteBlock, IfPm3Iclass, "[options..] Write iClass block"}, {NULL, NULL, NULL, NULL} }; @@ -2441,31 +2805,33 @@ int readIclass(bool loop, bool verbose) { while (!kbd_enter_pressed()) { clearCommandBuffer(); - SendCommandMIX(CMD_READER_ICLASS, flags, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0); if (WaitForResponseTimeout(CMD_ACK, &resp, 4500)) { uint8_t readStatus = resp.oldarg[0] & 0xff; uint8_t *data = resp.data.asBytes; - if (verbose) PrintAndLogEx(NORMAL, "Readstatus:%02x", readStatus); + if (verbose) PrintAndLogEx(INFO, "Readstatus:%02x", readStatus); + // no tag found or button pressed if ((readStatus == 0 && !loop) || readStatus == 0xFF) { // abort - if (verbose) { - PrintAndLogEx(FAILED, "Quitting..."); - DropField(); - return 0; - } + DropField(); + return PM3_EOPABORTED; } + if (readStatus & FLAG_ICLASS_READER_CSN) { PrintAndLogEx(NORMAL, " CSN: %s", sprint_hex(data, 8)); tagFound = true; } + if (readStatus & FLAG_ICLASS_READER_CC) { PrintAndLogEx(NORMAL, " CC: %s", sprint_hex(data + 16, 8)); } + if (readStatus & FLAG_ICLASS_READER_CONF) { printIclassDumpInfo(data); } + if (readStatus & FLAG_ICLASS_READER_AIA) { bool legacy = (memcmp((uint8_t *)(data + 8 * 5), "\xff\xff\xff\xff\xff\xff\xff\xff", 8) == 0); @@ -2482,7 +2848,7 @@ int readIclass(bool loop, bool verbose) { if (tagFound && !loop) { DropField(); - return 1; + return PM3_SUCCESS; } } else { if (verbose) diff --git a/client/cmdhficlass.h b/client/cmdhficlass.h index aa29fae1e..73304d4d0 100644 --- a/client/cmdhficlass.h +++ b/client/cmdhficlass.h @@ -11,31 +11,8 @@ #ifndef CMDHFICLASS_H__ #define CMDHFICLASS_H__ -#include -#include -#include -#include -//#include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type -#include "proxmark3.h" -#include "ui.h" -#include "cmdparser.h" #include "common.h" -#include "util.h" -#include "comms.h" -#include "mbedtls/des.h" -#include "loclass/cipherutils.h" -#include "loclass/cipher.h" -#include "loclass/ikeys.h" -#include "loclass/elite_crack.h" -#include "loclass/fileutils.h" -#include "protocols.h" -#include "pm3_cmd.h" -#include "cmdhfmfu.h" -#include "cmdhf.h" -#include "protocols.h" // picopass structs, -#include "usb_cdc.h" // for usb_poll_validate_length - - +#include "fileutils.h" typedef struct iclass_block { uint8_t d[8]; @@ -56,9 +33,8 @@ int readIclass(bool loop, bool verbose); void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize); void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite); -int LoadDictionaryKeyFile(char *filename, uint8_t **keys, int *keycnt); -int GenerateMacFromKeyFile(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elite, uint8_t *keys, int keycnt, iclass_premac_t *list); -int GenerateFromKeyFile(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elite, uint8_t *keys, int keycnt, iclass_prekey_t *list); +void GenerateMacFrom(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elite, uint8_t *keys, int keycnt, iclass_premac_t *list); +void GenerateMacKeyFrom(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elite, uint8_t *keys, int keycnt, iclass_prekey_t *list); void PrintPreCalcMac(uint8_t *keys, int keycnt, iclass_premac_t *pre_list); void PrintPreCalc(iclass_prekey_t *list, int itemcnt); #endif diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index e8089c3d8..fe1f53785 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -9,6 +9,16 @@ //----------------------------------------------------------------------------- #include "cmdhflegic.h" +#include // for Mingw readline +#include + +#include "cmdparser.h" // command_t +#include "comms.h" // clearCommandBuffer +#include "cmdtrace.h" +#include "crc.h" +#include "crc16.h" +#include "fileutils.h" //saveFile + static int CmdHelp(const char *Cmd); #define MAX_LENGTH 1024 @@ -26,7 +36,7 @@ static int usage_legic_calccrc(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf legic crc d deadbeef1122"); PrintAndLogEx(NORMAL, " hf legic crc d deadbeef1122 u 9A c 16"); - return 0; + return PM3_SUCCESS; } static int usage_legic_rdmem(void) { PrintAndLogEx(NORMAL, "Read data from a legic tag."); @@ -41,7 +51,7 @@ static int usage_legic_rdmem(void) { PrintAndLogEx(NORMAL, " hf legic rdmem 0 16 - reads from byte[0] 0x16 bytes(system header)"); PrintAndLogEx(NORMAL, " hf legic rdmem 0 4 55 - reads from byte[0] 0x4 bytes with IV 0x55"); PrintAndLogEx(NORMAL, " hf legic rdmem 0 100 55 - reads 0x100 bytes with IV 0x55"); - return 0; + return PM3_SUCCESS; } static int usage_legic_sim(void) { PrintAndLogEx(NORMAL, "Simulates a LEGIC Prime tag. MIM22, MIM256, MIM1024 types can be emulated"); @@ -55,7 +65,7 @@ static int usage_legic_sim(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf legic sim 2"); - return 0; + return PM3_SUCCESS; } static int usage_legic_write(void) { PrintAndLogEx(NORMAL, "Write data to a LEGIC Prime tag. It autodetects tagsize to make sure size"); @@ -68,7 +78,7 @@ static int usage_legic_write(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf legic write o 10 d 11223344 - Write 0x11223344 starting from offset 0x10"); - return 0; + return PM3_SUCCESS; } static int usage_legic_reader(void) { PrintAndLogEx(NORMAL, "Read UID and type information from a legic tag."); @@ -78,7 +88,7 @@ static int usage_legic_reader(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf legic reader"); - return 0; + return PM3_SUCCESS; } static int usage_legic_info(void) { PrintAndLogEx(NORMAL, "Reads information from a legic prime tag."); @@ -89,7 +99,7 @@ static int usage_legic_info(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf legic info"); - return 0; + return PM3_SUCCESS; } static int usage_legic_dump(void) { PrintAndLogEx(NORMAL, "Reads all pages from LEGIC Prime MIM22, MIM256, MIM1024"); @@ -103,7 +113,7 @@ static int usage_legic_dump(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf legic dump"); PrintAndLogEx(NORMAL, " hf legic dump o myfile"); - return 0; + return PM3_SUCCESS; } static int usage_legic_restore(void) { PrintAndLogEx(NORMAL, "Reads binary file and it autodetects card type and verifies that the file has the same size"); @@ -115,7 +125,7 @@ static int usage_legic_restore(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf legic restore i myfile"); - return 0; + return PM3_SUCCESS; } static int usage_legic_eload(void) { PrintAndLogEx(NORMAL, "It loads binary dump from the file `filename.bin`"); @@ -129,7 +139,7 @@ static int usage_legic_eload(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf legic eload 2 myfile"); - return 0; + return PM3_SUCCESS; } static int usage_legic_esave(void) { PrintAndLogEx(NORMAL, "It saves binary dump into the file `filename.bin` or `cardID.bin`"); @@ -143,7 +153,7 @@ static int usage_legic_esave(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf legic esave 2 myfile"); - return 0; + return PM3_SUCCESS; } static int usage_legic_wipe(void) { PrintAndLogEx(NORMAL, "Fills a legic tag memory with zeros. From byte7 and to the end."); @@ -153,7 +163,7 @@ static int usage_legic_wipe(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf legic wipe"); - return 0; + return PM3_SUCCESS; } /* * Output BigBuf and deobfuscate LEGIC RF tag data. @@ -175,9 +185,9 @@ static int CmdLegicInfo(const char *Cmd) { // tagtype legic_card_select_t card; - if (legic_get_type(&card)) { + if (legic_get_type(&card) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Failed to identify tagtype"); - return 1; + return PM3_ESOFT; } PrintAndLogEx(SUCCESS, "Reading full tag memory of %d bytes...", card.cardsize); @@ -186,14 +196,14 @@ static int CmdLegicInfo(const char *Cmd) { uint8_t *data = calloc(card.cardsize, sizeof(uint8_t)); if (!data) { PrintAndLogEx(WARNING, "Cannot allocate memory"); - return 2; + return PM3_EMALLOC; } int status = legic_read_mem(0, card.cardsize, 0x55, data, &datalen); - if (status > 0) { + if (status != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Failed reading memory"); free(data); - return 3; + return status; } // Output CDF System area (9 bytes) plus remaining header area (12 bytes) @@ -479,7 +489,7 @@ static int CmdLegicInfo(const char *Cmd) { out: free(data); - return 0; + return PM3_SUCCESS; } // params: @@ -497,7 +507,7 @@ static int CmdLegicRdmem(const char *Cmd) { // sanity checks if (len + offset >= MAX_LENGTH) { PrintAndLogEx(WARNING, "Out-of-bounds, Cardsize = %d, [offset+len = %d ]", MAX_LENGTH, len + offset); - return -1; + return PM3_EOUTOFBOUND; } PrintAndLogEx(SUCCESS, "Reading %d bytes, from offset %d", len, offset); @@ -506,11 +516,11 @@ static int CmdLegicRdmem(const char *Cmd) { uint8_t *data = calloc(len, sizeof(uint8_t)); if (!data) { PrintAndLogEx(WARNING, "Cannot allocate memory"); - return -2; + return PM3_EMALLOC; } int status = legic_read_mem(offset, len, iv, data, &datalen); - if (status == 0) { + if (status == PM3_SUCCESS) { PrintAndLogEx(NORMAL, "\n ## | 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"); PrintAndLogEx(NORMAL, "-----+------------------------------------------------------------------------------------------------"); print_hex_break(data, datalen, 32); @@ -527,8 +537,8 @@ static int CmdLegicRfSim(const char *Cmd) { uint64_t id = 1; sscanf(Cmd, " %" SCNi64, &id); clearCommandBuffer(); - SendCommandMIX(CMD_SIMULATE_TAG_LEGIC_RF, id, 0, 0, NULL, 0); - return 0; + SendCommandMIX(CMD_HF_LEGIC_SIMULATE, id, 0, 0, NULL, 0); + return PM3_SUCCESS; } static int CmdLegicRfWrite(const char *Cmd) { @@ -607,9 +617,9 @@ static int CmdLegicRfWrite(const char *Cmd) { // tagtype legic_card_select_t card; - if (legic_get_type(&card)) { + if (legic_get_type(&card) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Failed to identify tagtype"); - return -1; + return PM3_ESOFT; } legic_print_type(card.cardsize, 0); @@ -618,12 +628,12 @@ static int CmdLegicRfWrite(const char *Cmd) { // UID 4+1 bytes can't be written to. if (offset < 5) { PrintAndLogEx(WARNING, "Out-of-bounds, bytes 0-1-2-3-4 can't be written to. Offset = %d", offset); - return -2; + return PM3_EOUTOFBOUND; } if (len + offset >= card.cardsize) { PrintAndLogEx(WARNING, "Out-of-bounds, Cardsize = %d, [offset+len = %d ]", card.cardsize, len + offset); - return -2; + return PM3_EOUTOFBOUND; } if (offset == 5 || offset == 6) { @@ -634,7 +644,7 @@ static int CmdLegicRfWrite(const char *Cmd) { bool overwrite = (answer[0] == 'y' || answer[0] == 'Y'); if (!overwrite) { PrintAndLogEx(NORMAL, "command cancelled"); - return 0; + return PM3_EOPABORTED; } } @@ -644,7 +654,7 @@ static int CmdLegicRfWrite(const char *Cmd) { PacketResponseNG resp; clearCommandBuffer(); - SendCommandOLD(CMD_WRITER_LEGIC_RF, offset, len, IV, data, len); + SendCommandOLD(CMD_HF_LEGIC_WRITER, offset, len, IV, data, len); uint8_t timeout = 0; @@ -654,7 +664,7 @@ static int CmdLegicRfWrite(const char *Cmd) { fflush(stdout); if (timeout > 7) { PrintAndLogEx(WARNING, "\ncommand execution time out"); - return 1; + return PM3_ETIMEOUT; } } PrintAndLogEx(NORMAL, "\n"); @@ -662,10 +672,10 @@ static int CmdLegicRfWrite(const char *Cmd) { uint8_t isOK = resp.oldarg[0] & 0xFF; if (!isOK) { PrintAndLogEx(WARNING, "Failed writing tag"); - return 1; + return PM3_ERFTRANS; } - return 0; + return PM3_SUCCESS; } static int CmdLegicCalcCrc(const char *Cmd) { @@ -747,7 +757,7 @@ static int CmdLegicCalcCrc(const char *Cmd) { } if (data) free(data); - return 0; + return PM3_SUCCESS; } int legic_read_mem(uint32_t offset, uint32_t len, uint32_t iv, uint8_t *out, uint16_t *outlen) { @@ -755,7 +765,7 @@ int legic_read_mem(uint32_t offset, uint32_t len, uint32_t iv, uint8_t *out, uin legic_chk_iv(&iv); clearCommandBuffer(); - SendCommandMIX(CMD_READER_LEGIC_RF, offset, len, iv, NULL, 0); + SendCommandMIX(CMD_HF_LEGIC_READER, offset, len, iv, NULL, 0); PacketResponseNG resp; uint8_t timeout = 0; @@ -765,7 +775,7 @@ int legic_read_mem(uint32_t offset, uint32_t len, uint32_t iv, uint8_t *out, uin fflush(stdout); if (timeout > 7) { PrintAndLogEx(WARNING, "\ncommand execution time out"); - return 1; + return PM3_ETIMEOUT; } } PrintAndLogEx(NORMAL, "\n"); @@ -774,7 +784,7 @@ int legic_read_mem(uint32_t offset, uint32_t len, uint32_t iv, uint8_t *out, uin *outlen = resp.oldarg[1]; if (!isOK) { PrintAndLogEx(WARNING, "Failed reading tag"); - return 2; + return PM3_ESOFT; } if (*outlen != len) @@ -783,9 +793,9 @@ int legic_read_mem(uint32_t offset, uint32_t len, uint32_t iv, uint8_t *out, uin // copy data from device if (!GetFromDevice(BIG_BUF_EML, out, *outlen, 0, NULL, 0, NULL, 2500, false)) { PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); - return 4; + return PM3_ETIMEOUT; } - return 0; + return PM3_SUCCESS; } int legic_print_type(uint32_t tagtype, uint8_t spaces) { @@ -801,24 +811,24 @@ int legic_print_type(uint32_t tagtype, uint8_t spaces) { PrintAndLogEx(SUCCESS, "%sTYPE : MIM%d card (1002 bytes)", spacer, tagtype); else PrintAndLogEx(INFO, "%sTYPE : Unknown %06x", spacer, tagtype); - return 0; + return PM3_SUCCESS; } int legic_get_type(legic_card_select_t *card) { - if (card == NULL) return 1; + if (card == NULL) return PM3_EINVARG; clearCommandBuffer(); - SendCommandNG(CMD_LEGIC_INFO, NULL, 0); + SendCommandNG(CMD_HF_LEGIC_INFO, NULL, 0); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) - return 2; + return PM3_ETIMEOUT; uint8_t isOK = resp.oldarg[0] & 0xFF; if (!isOK) - return 3; + return PM3_ESOFT; memcpy(card, (legic_card_select_t *)resp.data.asBytes, sizeof(legic_card_select_t)); - return 0; + return PM3_SUCCESS; } void legic_chk_iv(uint32_t *iv) { if ((*iv & 0x7F) != *iv) { @@ -842,7 +852,7 @@ void legic_seteml(uint8_t *src, uint32_t offset, uint32_t numofbytes) { conn.block_after_ACK = false; } clearCommandBuffer(); - SendCommandOLD(CMD_LEGIC_ESET, i, len, 0, src + i, len); + SendCommandOLD(CMD_HF_LEGIC_ESET, i, len, 0, src + i, len); } } @@ -888,9 +898,9 @@ static int CmdLegicDump(const char *Cmd) { // tagtype legic_card_select_t card; - if (legic_get_type(&card)) { + if (legic_get_type(&card) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Failed to identify tagtype"); - return -1; + return PM3_ESOFT; } dumplen = card.cardsize; @@ -898,7 +908,7 @@ static int CmdLegicDump(const char *Cmd) { PrintAndLogEx(SUCCESS, "Reading tag memory %d b...", dumplen); clearCommandBuffer(); - SendCommandMIX(CMD_READER_LEGIC_RF, 0x00, dumplen, 0x55, NULL, 0); + SendCommandMIX(CMD_HF_LEGIC_READER, 0x00, dumplen, 0x55, NULL, 0); PacketResponseNG resp; uint8_t timeout = 0; @@ -908,7 +918,7 @@ static int CmdLegicDump(const char *Cmd) { fflush(stdout); if (timeout > 7) { PrintAndLogEx(WARNING, "\ncommand execution time out"); - return 1; + return PM3_ETIMEOUT; } } PrintAndLogEx(NORMAL, "\n"); @@ -916,14 +926,14 @@ static int CmdLegicDump(const char *Cmd) { uint8_t isOK = resp.oldarg[0] & 0xFF; if (!isOK) { PrintAndLogEx(WARNING, "Failed dumping tag data"); - return 2; + return PM3_ERFTRANS; } uint16_t readlen = resp.oldarg[1]; uint8_t *data = calloc(readlen, sizeof(uint8_t)); if (!data) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); - return 3; + return PM3_EMALLOC; } if (readlen != dumplen) @@ -933,7 +943,7 @@ static int CmdLegicDump(const char *Cmd) { if (!GetFromDevice(BIG_BUF_EML, data, readlen, 0, NULL, 0, NULL, 2500, false)) { PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); free(data); - return 4; + return PM3_ETIMEOUT; } // user supplied filename? @@ -994,9 +1004,9 @@ static int CmdLegicRestore(const char *Cmd) { // tagtype legic_card_select_t card; - if (legic_get_type(&card)) { + if (legic_get_type(&card) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Failed to identify tagtype"); - return 1; + return PM3_ESOFT; } numofbytes = card.cardsize; @@ -1004,7 +1014,7 @@ static int CmdLegicRestore(const char *Cmd) { uint8_t *data = calloc(numofbytes, sizeof(uint8_t)); if (!data) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); - return 2; + return PM3_EMALLOC; } legic_print_type(numofbytes, 0); @@ -1029,7 +1039,7 @@ static int CmdLegicRestore(const char *Cmd) { PrintAndLogEx(WARNING, "Fail, filesize and cardsize is not equal. [%u != %u]", filesize, numofbytes); free(data); fclose(f); - return 4; + return PM3_EFILE; } // load file @@ -1039,7 +1049,7 @@ static int CmdLegicRestore(const char *Cmd) { if (bytes_read == 0) { PrintAndLogEx(ERR, "File reading error"); free(data); - return 2; + return PM3_EFILE; } PrintAndLogEx(SUCCESS, "Restoring to card"); @@ -1057,7 +1067,7 @@ static int CmdLegicRestore(const char *Cmd) { conn.block_after_ACK = false; } clearCommandBuffer(); - SendCommandOLD(CMD_WRITER_LEGIC_RF, i, len, 0x55, data + i, len); + SendCommandOLD(CMD_HF_LEGIC_WRITER, i, len, 0x55, data + i, len); uint8_t timeout = 0; while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { @@ -1067,7 +1077,7 @@ static int CmdLegicRestore(const char *Cmd) { if (timeout > 7) { PrintAndLogEx(WARNING, "\ncommand execution time out"); free(data); - return 1; + return PM3_ETIMEOUT; } } PrintAndLogEx(NORMAL, "\n"); @@ -1076,7 +1086,7 @@ static int CmdLegicRestore(const char *Cmd) { if (!isOK) { PrintAndLogEx(WARNING, "Failed writing tag [msg = %u]", resp.oldarg[1] & 0xFF); free(data); - return 1; + return PM3_ERFTRANS; } PrintAndLogEx(SUCCESS, "Wrote chunk [offset %d | len %d | total %d", i, len, i + len); } @@ -1118,7 +1128,7 @@ static int CmdLegicELoad(const char *Cmd) { uint8_t *data = calloc(numofbytes, sizeof(uint8_t)); if (!data) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); - return 3; + return PM3_EMALLOC; } // set up file @@ -1143,7 +1153,7 @@ static int CmdLegicELoad(const char *Cmd) { free(data); fclose(f); f = NULL; - return 2; + return PM3_EFILE; } fclose(f); f = NULL; @@ -1195,7 +1205,7 @@ static int CmdLegicESave(const char *Cmd) { uint8_t *data = calloc(numofbytes, sizeof(uint8_t)); if (!data) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); - return 3; + return PM3_EMALLOC; } // download emulator memory @@ -1203,7 +1213,7 @@ static int CmdLegicESave(const char *Cmd) { if (!GetFromDevice(BIG_BUF_EML, data, numofbytes, 0, NULL, 0, NULL, 2500, false)) { PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); free(data); - return 4; + return PM3_ETIMEOUT; } // user supplied filename? if (fileNlen < 1) @@ -1213,7 +1223,7 @@ static int CmdLegicESave(const char *Cmd) { saveFileEML(filename, data, numofbytes, 8); saveFile(filename, ".bin", data, numofbytes); - return 0; + return PM3_SUCCESS; } static int CmdLegicWipe(const char *Cmd) { @@ -1224,16 +1234,16 @@ static int CmdLegicWipe(const char *Cmd) { // tagtype legic_card_select_t card; - if (legic_get_type(&card)) { + if (legic_get_type(&card) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Failed to identify tagtype"); - return 1; + return PM3_ESOFT; } // set up buffer uint8_t *data = calloc(card.cardsize, sizeof(uint8_t)); if (!data) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); - return 2; + return PM3_EMALLOC; } legic_print_type(card.cardsize, 0); @@ -1254,7 +1264,7 @@ static int CmdLegicWipe(const char *Cmd) { conn.block_after_ACK = false; } clearCommandBuffer(); - SendCommandOLD(CMD_WRITER_LEGIC_RF, i, len, 0x55, data + i, len); + SendCommandOLD(CMD_HF_LEGIC_WRITER, i, len, 0x55, data + i, len); uint8_t timeout = 0; while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { @@ -1264,7 +1274,7 @@ static int CmdLegicWipe(const char *Cmd) { if (timeout > 7) { PrintAndLogEx(WARNING, "\ncommand execution time out"); free(data); - return 3; + return PM3_ETIMEOUT; } } PrintAndLogEx(NORMAL, "\n"); @@ -1273,18 +1283,18 @@ static int CmdLegicWipe(const char *Cmd) { if (!isOK) { PrintAndLogEx(WARNING, "Failed writing tag [msg = %u]", resp.oldarg[1] & 0xFF); free(data); - return 4; + return PM3_ERFTRANS; } } PrintAndLogEx(SUCCESS, "ok\n"); free(data); - return 0; + return PM3_SUCCESS; } static int CmdLegicList(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdTraceList("legic"); - return 0; + return PM3_SUCCESS; } static command_t CommandTable[] = { @@ -1307,7 +1317,7 @@ static command_t CommandTable[] = { static int CmdHelp(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdsHelp(CommandTable); - return 0; + return PM3_SUCCESS; } int CmdHFLegic(const char *Cmd) { @@ -1319,18 +1329,18 @@ int readLegicUid(bool verbose) { legic_card_select_t card; switch (legic_get_type(&card)) { - case 1: - return 2; - case 2: + case PM3_EINVARG: + return PM3_EINVARG; + case PM3_ETIMEOUT: if (verbose) PrintAndLogEx(WARNING, "command execution time out"); - return 1; - case 3: + return PM3_ETIMEOUT; + case PM3_ESOFT: if (verbose) PrintAndLogEx(WARNING, "legic card select failed"); - return 2; + return PM3_ESOFT; default: break; } PrintAndLogEx(SUCCESS, " UID : %s", sprint_hex(card.uid, sizeof(card.uid))); legic_print_type(card.cardsize, 0); - return 0; + return PM3_SUCCESS; } diff --git a/client/cmdhflegic.h b/client/cmdhflegic.h index b922420ec..9e9411a33 100644 --- a/client/cmdhflegic.h +++ b/client/cmdhflegic.h @@ -11,18 +11,9 @@ #ifndef CMDHFLEGIC_H__ #define CMDHFLEGIC_H__ -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "cmdparser.h" -#include "comms.h" -#include "util.h" -#include "crc.h" -#include "legic_prng.h" -#include "legic.h" // legic_card_select_t struct -#include "cmdhf.h" // "hf list" -#include "loclass/fileutils.h" //saveFile +#include "common.h" + +#include "legic.h" // struct int CmdHFLegic(const char *Cmd); diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 13766e299..d44ac635c 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -11,6 +11,19 @@ #include "cmdhflist.h" +#include +#include +#include + +#include "commonutil.h" // ARRAYLEN +#include "mifare/mifarehost.h" +#include "mifare/mifaredefault.h" +#include "parity.h" // oddparity +#include "ui.h" +#include "crc16.h" +#include "crapto1/crapto1.h" +#include "protocols.h" + enum MifareAuthSeq { masNone, masNt, @@ -279,14 +292,26 @@ int applyIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { break; } case MIFARE_ULEV1_READSIG: - snprintf(exp, size, "READ_SIG"); + snprintf(exp, size, "READ SIG"); break; case MIFARE_ULEV1_CHECKTEAR: - snprintf(exp, size, "CHK_TEARING(%d)", cmd[1]); + snprintf(exp, size, "CHK TEARING(%d)", cmd[1]); break; case MIFARE_ULEV1_VCSL: snprintf(exp, size, "VCSL"); break; + case MIFARE_ULNANO_WRITESIG: + snprintf(exp, size, "WRITE SIG"); + break; + case MIFARE_ULNANO_LOCKSIF: { + if (cmd[1] == 0) + snprintf(exp, size, "UNLOCK SIG"); + else if (cmd[1] == 2) + snprintf(exp, size, "LOCK SIG"); + else + snprintf(exp, size, "?"); + break; + } default: return 0; } @@ -298,10 +323,31 @@ void annotateIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { } void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { - switch (cmd[0]) { + uint8_t c = cmd[0] & 0x0F; + uint8_t parity = 0; + for ( uint8_t i=0; i<7; i++) { + parity ^= (cmd[0] >> i) & 1; + } + + switch (c) { + case ICLASS_CMD_HALT: + snprintf(exp, size, "HALT"); + break; + case ICLASS_CMD_SELECT: + snprintf(exp, size, "SELECT"); + break; case ICLASS_CMD_ACTALL: snprintf(exp, size, "ACTALL"); break; + case ICLASS_CMD_DETECT: + snprintf(exp, size, "DETECT"); + break; + case ICLASS_CMD_CHECK: + snprintf(exp, size, "CHECK"); + break; + case ICLASS_CMD_READ4: + snprintf(exp, size, "READ4(%d)", cmd[1]); + break; case ICLASS_CMD_READ_OR_IDENTIFY: { if (cmdsize > 1) { snprintf(exp, size, "READ(%d)", cmd[1]); @@ -310,36 +356,22 @@ void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { } break; } - case ICLASS_CMD_SELECT: - snprintf(exp, size, "SELECT"); - break; case ICLASS_CMD_PAGESEL: snprintf(exp, size, "PAGESEL(%d)", cmd[1]); break; - case ICLASS_CMD_READCHECK_KC: - snprintf(exp, size, "READCHECK[Kc](%d)", cmd[1]); - break; - case ICLASS_CMD_READCHECK_KD: - snprintf(exp, size, "READCHECK[Kd](%d)", cmd[1]); - break; - case ICLASS_CMD_CHECK: - snprintf(exp, size, "CHECK"); - break; - case ICLASS_CMD_DETECT: - snprintf(exp, size, "DETECT"); - break; - case ICLASS_CMD_HALT: - snprintf(exp, size, "HALT"); - break; case ICLASS_CMD_UPDATE: snprintf(exp, size, "UPDATE(%d)", cmd[1]); break; + case ICLASS_CMD_READCHECK: + if ( ICLASS_CREDIT(c) ) { + snprintf(exp, size, "READCHECK[Kc](%d)", cmd[1]); + } else { + snprintf(exp, size, "READCHECK[Kd](%d)", cmd[1]); + } + break; case ICLASS_CMD_ACT: snprintf(exp, size, "ACT"); break; - case ICLASS_CMD_READ4: - snprintf(exp, size, "READ4(%d)", cmd[1]); - break; default: snprintf(exp, size, "?"); break; @@ -1114,7 +1146,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes // check default keys if (!traceCrypto1) { - for (int i = 0; i < MIFARE_DEFAULTKEYS_SIZE; i++) { + for (int i = 0; i < ARRAYLEN(g_mifare_default_keys); i++) { if (NestedCheckKey(g_mifare_default_keys[i], &AuthData, cmd, cmdsize, parity)) { PrintAndLogEx(NORMAL, " | | * |%61s %012"PRIx64"| |", "key", g_mifare_default_keys[i]); diff --git a/client/cmdhflist.h b/client/cmdhflist.h index ddc0ab00c..0dda4ea17 100644 --- a/client/cmdhflist.h +++ b/client/cmdhflist.h @@ -10,32 +10,7 @@ #ifndef CMDHFLIST_H #define CMDHFLIST_H -#include -#include -#include -#include -#include -#include "util.h" -#include "ui.h" -#include "cmdhf14a.h" // ISO14443-A -#include "cmdhf14b.h" // ISO14443-B -#include "cmdhf15.h" // ISO15693 -#include "cmdhfepa.h" -#include "cmdhflegic.h" // LEGIC -#include "cmdhficlass.h" // ICLASS -#include "cmdhfmf.h" // CLASSIC -#include "cmdhfmfu.h" // ULTRALIGHT/NTAG etc -#include "cmdhfmfdes.h" // DESFIRE -#include "cmdhftopaz.h" // TOPAZ -#include "cmdhffelica.h" // ISO18092 / FeliCa -#include "emv/cmdemv.h" // EMV -#include "protocols.h" -#include "crapto1/crapto1.h" -#include "mifare/mifarehost.h" -#include "mifare/mifaredefault.h" -#include "parity.h" // oddparity -#include "iso15693tools.h" // ISO15693 crc - +#include "common.h" typedef struct { uint32_t uid; // UID diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 6e2ca62f5..baa999128 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -9,10 +9,22 @@ //----------------------------------------------------------------------------- #include "cmdhfmf.h" -#include "mifare/mifare4.h" + +#include + +#include "cmdparser.h" // command_t +#include "commonutil.h" // ARRAYLEN +#include "comms.h" // clearCommandBuffer +#include "fileutils.h" +#include "cmdtrace.h" +#include "emv/dump.h" +#include "mifare/mifaredefault.h" // mifare default key array +#include "cliparser/cliparser.h" // argtable +#include "hardnested/hardnested_bf_core.h" // SetSIMDInstr #include "mifare/mad.h" #include "mifare/ndef.h" - +#include "protocols.h" +#include "util_posix.h" // msclock #define MFBLOCK_SIZE 16 @@ -29,7 +41,7 @@ static int CmdHelp(const char *Cmd); static int usage_hf14_ice(void) { - PrintAndLogEx(NORMAL, "Usage: hf mf ice [l] [f] "); + PrintAndLogEx(NORMAL, "Usage: hf mf ice [l ] [f ]"); PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " l nonces to be collected"); PrintAndLogEx(NORMAL, " f save nonces to instead of hf-mf--nonces.bin"); @@ -41,7 +53,7 @@ static int usage_hf14_ice(void) { } static int usage_hf14_dump(void) { - PrintAndLogEx(NORMAL, "Usage: hf mf dump [card memory] k f "); + PrintAndLogEx(NORMAL, "Usage: hf mf dump [card memory] [k ] [f ]"); PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); PrintAndLogEx(NORMAL, " k : key filename, if no given, UID will be used as filename"); PrintAndLogEx(NORMAL, " f : data filename, if no given, UID will be used as filename"); @@ -53,7 +65,7 @@ static int usage_hf14_dump(void) { } static int usage_hf14_mifare(void) { - PrintAndLogEx(NORMAL, "Usage: hf mf darkside [h] "); + PrintAndLogEx(NORMAL, "Usage: hf mf darkside "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " (Optional) target other block"); @@ -65,14 +77,17 @@ static int usage_hf14_mifare(void) { return 0; } static int usage_hf14_mfsim(void) { - PrintAndLogEx(NORMAL, "Usage: hf mf sim [h] u n [i] [x] [e] [v]"); + PrintAndLogEx(NORMAL, "Usage: hf mf sim [u ] [n ] [t] [a ] [s ] [i] [x] [e] [v]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " u (Optional) UID 4,7 or 10bytes. If not specified, the UID 4b from emulator memory will be used"); - PrintAndLogEx(NORMAL, " t (Optional) 0 = MIFARE Mini"); + PrintAndLogEx(NORMAL, " u (Optional) UID 4,7 or 10bytes. If not specified, the UID 4b/7b from emulator memory will be used"); + PrintAndLogEx(NORMAL, " t (Optional) Enforce ATQA/SAK:"); + PrintAndLogEx(NORMAL, " 0 = MIFARE Mini"); PrintAndLogEx(NORMAL, " 1 = MIFARE Classic 1k (Default)"); PrintAndLogEx(NORMAL, " 2 = MIFARE Classic 2k plus in SL0 mode"); PrintAndLogEx(NORMAL, " 4 = MIFARE Classic 4k"); + PrintAndLogEx(NORMAL, " a (Optional) Provide explicitly ATQA (2 bytes, override option t)"); + PrintAndLogEx(NORMAL, " s (Optional) Provide explicitly SAK (1 byte, override option t)"); PrintAndLogEx(NORMAL, " n (Optional) Automatically exit simulation after blocks have been read by reader. 0 = infinite"); PrintAndLogEx(NORMAL, " i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted"); PrintAndLogEx(NORMAL, " x (Optional) Crack, performs the 'reader attack', nr/ar attack against a reader"); @@ -151,6 +166,42 @@ static int usage_hf14_hardnested(void) { PrintAndLogEx(NORMAL, " hf mf hardnested 0 A A0A1A2A3A4A5 4 A FFFFFFFFFFFF"); return 0; } +static int usage_hf14_autopwn(void) { + PrintAndLogEx(NORMAL, "Usage:"); + PrintAndLogEx(NORMAL, " hf mf autopwn [k] "); + PrintAndLogEx(NORMAL, " [* ] [f [.dic]] [s] [i ] [l] [v]"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Description:"); + PrintAndLogEx(NORMAL, " This command automates the key recovery process on Mifare classic cards."); + PrintAndLogEx(NORMAL, " It uses the darkside, nested and hardnested attack to extract the keys and card content."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " k known key is supplied"); + PrintAndLogEx(NORMAL, " f [.dic] key dictionary file"); + PrintAndLogEx(NORMAL, " s slower acquisition for hardnested (required by some non standard cards)"); + PrintAndLogEx(NORMAL, " v verbose output (statistics)"); + PrintAndLogEx(NORMAL, " l legacy mode (use the slow 'mf chk' for the key enumeration)"); + PrintAndLogEx(NORMAL, " * all sectors based on card memory"); + PrintAndLogEx(NORMAL, " * 0 = MINI(320 bytes)"); + PrintAndLogEx(NORMAL, " * 1 = 1k (default)"); + PrintAndLogEx(NORMAL, " * 2 = 2k"); + PrintAndLogEx(NORMAL, " * 4 = 4k"); + PrintAndLogEx(NORMAL, " i set type of SIMD instructions for hardnested. Default: autodetection."); + PrintAndLogEx(NORMAL, " i 5 = AVX512"); + PrintAndLogEx(NORMAL, " i 2 = AVX2"); + PrintAndLogEx(NORMAL, " i a = AVX"); + PrintAndLogEx(NORMAL, " i s = SSE2"); + PrintAndLogEx(NORMAL, " i m = MMX"); + PrintAndLogEx(NORMAL, " i n = none (use CPU regular instruction set)"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf autopwn -- target Mifare classic card with default keys"); + PrintAndLogEx(NORMAL, " hf mf autopwn * 1 f mfc_default_keys -- target Mifare classic card (size 1k) with default dictionary"); + PrintAndLogEx(NORMAL, " hf mf autopwn k 0 A FFFFFFFFFFFF -- target Mifare classic card with Sector0 typeA with known key 'FFFFFFFFFFFF'"); + PrintAndLogEx(NORMAL, " hf mf autopwn k 0 A FFFFFFFFFFFF * 1 f mfc_default_keys -- this command combines the two above (reduce the need for nested / hardnested attacks, by using a dictionary)"); + return 0; +} static int usage_hf14_chk(void) { PrintAndLogEx(NORMAL, "Usage: hf mf chk [h] |<*card memory> [t|d] [] []"); PrintAndLogEx(NORMAL, "Options:"); @@ -164,10 +215,10 @@ static int usage_hf14_chk(void) { PrintAndLogEx(NORMAL, " t write keys to emulator memory\n"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf chk 0 A 1234567890ab -- target block 0, Key A using key 1234567890ab"); - PrintAndLogEx(NORMAL, " hf mf chk 0 A default_keys.dic -- target block 0, Key A using default dictionary file"); - PrintAndLogEx(NORMAL, " hf mf chk *1 ? t -- target all blocks, all keys, 1K, write to emulator memory"); - PrintAndLogEx(NORMAL, " hf mf chk *1 ? d -- target all blocks, all keys, 1K, write to file"); + PrintAndLogEx(NORMAL, " hf mf chk 0 A 1234567890ab -- target block 0, Key A using key 1234567890ab"); + PrintAndLogEx(NORMAL, " hf mf chk 0 A mfc_default_keys.dic -- target block 0, Key A using default dictionary file"); + PrintAndLogEx(NORMAL, " hf mf chk *1 ? t -- target all blocks, all keys, 1K, write to emulator memory"); + PrintAndLogEx(NORMAL, " hf mf chk *1 ? d -- target all blocks, all keys, 1K, write to file"); return 0; } static int usage_hf14_chk_fast(void) { @@ -185,14 +236,15 @@ static int usage_hf14_chk_fast(void) { PrintAndLogEx(NORMAL, " m use dictionary from flashmemory\n"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf fchk 1 1234567890ab -- target 1K using key 1234567890ab"); - PrintAndLogEx(NORMAL, " hf mf fchk 1 default_keys.dic -- target 1K using default dictionary file"); - PrintAndLogEx(NORMAL, " hf mf fchk 1 t -- target 1K, write to emulator memory"); - PrintAndLogEx(NORMAL, " hf mf fchk 1 d -- target 1K, write to file"); + PrintAndLogEx(NORMAL, " hf mf fchk 1 1234567890ab -- target 1K using key 1234567890ab"); + PrintAndLogEx(NORMAL, " hf mf fchk 1 mfc_default_keys.dic -- target 1K using default dictionary file"); + PrintAndLogEx(NORMAL, " hf mf fchk 1 t -- target 1K, write to emulator memory"); + PrintAndLogEx(NORMAL, " hf mf fchk 1 d -- target 1K, write to file"); if (IfPm3Flash()) - PrintAndLogEx(NORMAL, " hf mf fchk 1 m -- target 1K, use dictionary from flashmemory"); + PrintAndLogEx(NORMAL, " hf mf fchk 1 m -- target 1K, use dictionary from flashmemory"); return 0; } +/* static int usage_hf14_keybrute(void) { PrintAndLogEx(NORMAL, "J_Run's 2nd phase of multiple sector nested authentication key recovery"); PrintAndLogEx(NORMAL, "You have a known 4 last bytes of a key recovered with mf_nonce_brute tool."); @@ -210,6 +262,7 @@ static int usage_hf14_keybrute(void) { PrintAndLogEx(NORMAL, " hf mf keybrute 1 A 000011223344"); return 0; } +*/ static int usage_hf14_restore(void) { PrintAndLogEx(NORMAL, "Usage: hf mf restore [card memory] u k f "); PrintAndLogEx(NORMAL, "Options:"); @@ -398,7 +451,7 @@ static int usage_hf14_nack(void) { static int GetHFMF14AUID(uint8_t *uid, int *uidlen) { clearCommandBuffer(); - SendCommandMIX(CMD_READER_ISO_14443a, ISO14A_CONNECT, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { PrintAndLogEx(WARNING, "iso14443a card select failed"); @@ -511,7 +564,7 @@ static int CmdHF14AMfWrBl(const char *Cmd) { memcpy(data, key, 6); memcpy(data + 10, bldata, 16); clearCommandBuffer(); - SendCommandOLD(CMD_MIFARE_WRITEBL, blockNo, keyType, 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_MIFARE_WRITEBL, blockNo, keyType, 0, data, sizeof(data)); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { @@ -559,10 +612,10 @@ static int CmdHF14AMfRdBl(const char *Cmd) { memcpy(payload.key, key, sizeof(payload.key)); clearCommandBuffer(); - SendCommandNG(CMD_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); + SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_MIFARE_READBL, &resp, 1500)) { + if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) { uint8_t *data = resp.data.asBytes; if (resp.status == PM3_SUCCESS) { @@ -624,7 +677,7 @@ static int CmdHF14AMfRdSc(const char *Cmd) { PrintAndLogEx(NORMAL, "--sector no:%d key type:%c key:%s ", sectorNo, keyType ? 'B' : 'A', sprint_hex(key, 6)); clearCommandBuffer(); - SendCommandOLD(CMD_MIFARE_READSC, sectorNo, keyType, 0, key, 6); + SendCommandOLD(CMD_HF_MIFARE_READSC, sectorNo, keyType, 0, key, 6); PrintAndLogEx(NORMAL, ""); PacketResponseNG resp; @@ -701,6 +754,55 @@ static uint8_t NumBlocksPerSector(uint8_t sectorNo) { } } +static uint8_t GetSectorFromBlockNo(uint8_t blockNo) { + if (blockNo < 128) + return blockNo / 4; + else + return 32 + ((128 - blockNo) / 16); +} + +static char GetFormatFromSector(uint8_t sectorNo) { + switch (sectorNo) { + case MIFARE_MINI_MAXSECTOR: + return '0'; + case MIFARE_1K_MAXSECTOR: + return '1'; + case MIFARE_2K_MAXSECTOR: + return '2'; + case MIFARE_4K_MAXSECTOR: + return '4'; + default : + return ' '; + } +} + +static int FastDumpWithEcFill(uint8_t numsectors) { + PacketResponseNG resp; + + mfc_eload_t payload; + payload.sectorcnt = numsectors; + payload.keytype = 0; + + // ecfill key A + clearCommandBuffer(); + SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload)); + + int res = WaitForResponseTimeout(CMD_HF_MIFARE_EML_LOAD, &resp, 2000); + if (res != PM3_SUCCESS) { + } + + // ecfill key B + payload.keytype = 1; + + clearCommandBuffer(); + SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload)); + res = WaitForResponseTimeout(CMD_HF_MIFARE_EML_LOAD, &resp, 2000); + if (res != PM3_SUCCESS) { + + } + return PM3_SUCCESS; +} + static int CmdHF14AMfDump(const char *Cmd) { uint64_t t1 = msclock(); @@ -797,9 +899,9 @@ static int CmdHF14AMfDump(const char *Cmd) { memcpy(payload.key, keyA[sectorNo], sizeof(payload.key)); clearCommandBuffer(); - SendCommandNG(CMD_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); + SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); - if (WaitForResponseTimeout(CMD_MIFARE_READBL, &resp, 1500)) { + if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) { uint8_t *data = resp.data.asBytes; if (resp.status == PM3_SUCCESS) { @@ -836,8 +938,8 @@ static int CmdHF14AMfDump(const char *Cmd) { memcpy(payload.key, keyA[sectorNo], sizeof(payload.key)); clearCommandBuffer(); - SendCommandNG(CMD_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); - received = WaitForResponseTimeout(CMD_MIFARE_READBL, &resp, 1500); + SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); + received = WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500); } else { // data block. Check if it can be read with key A or key B uint8_t data_area = (sectorNo < 32) ? blockNo : blockNo / 5; if ((rights[sectorNo][data_area] == 0x03) || (rights[sectorNo][data_area] == 0x05)) { // only key B would work @@ -847,8 +949,8 @@ static int CmdHF14AMfDump(const char *Cmd) { memcpy(payload.key, keyB[sectorNo], sizeof(payload.key)); clearCommandBuffer(); - SendCommandNG(CMD_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); - received = WaitForResponseTimeout(CMD_MIFARE_READBL, &resp, 1500); + SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); + received = WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500); } else if (rights[sectorNo][data_area] == 0x07) { // no key would work PrintAndLogEx(WARNING, "access rights do not allow reading of sector %2d block %3d", sectorNo, blockNo); // where do you want to go?? Next sector or block? @@ -860,8 +962,8 @@ static int CmdHF14AMfDump(const char *Cmd) { memcpy(payload.key, keyA[sectorNo], sizeof(payload.key)); clearCommandBuffer(); - SendCommandNG(CMD_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); - received = WaitForResponseTimeout(CMD_MIFARE_READBL, &resp, 1500); + SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); + received = WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500); } } if (received) { @@ -907,9 +1009,11 @@ static int CmdHF14AMfDump(const char *Cmd) { PrintAndLogEx(SUCCESS, "\nSucceded in dumping all blocks"); if (strlen(dataFilename) < 1) { - fptr = dataFilename; - fptr += sprintf(fptr, "hf-mf-"); - FillFileNameByUID(fptr, (uint8_t *)carddata, "-data", 4); + fptr = GenerateFilename("hf-mf-", "-data"); + if (fptr == NULL) + return PM3_ESOFT; + + strcpy(dataFilename, fptr); } uint16_t bytes = 16 * (FirstBlockOfSector(numSectors - 1) + NumBlocksPerSector(numSectors - 1)); @@ -1046,7 +1150,7 @@ static int CmdHF14AMfRestore(const char *Cmd) { memcpy(data + 10, bldata, 16); clearCommandBuffer(); - SendCommandOLD(CMD_MIFARE_WRITEBL, FirstBlockOfSector(sectorNo) + blockNo, keyType, 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_MIFARE_WRITEBL, FirstBlockOfSector(sectorNo) + blockNo, keyType, 0, data, sizeof(data)); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { @@ -1069,7 +1173,7 @@ static int CmdHF14AMfNested(const char *Cmd) { uint8_t trgKeyType = 0; uint8_t SectorsCnt = 0; uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - uint8_t keyBlock[(MIFARE_DEFAULTKEYS_SIZE + 1) * 6]; + uint8_t keyBlock[(ARRAYLEN(g_mifare_default_keys) + 1) * 6]; uint64_t key64 = 0; bool transferToEml = false; bool createDumpFile = false; @@ -1171,28 +1275,37 @@ static int CmdHF14AMfNested(const char *Cmd) { e_sector = calloc(SectorsCnt, sizeof(sector_t)); if (e_sector == NULL) return PM3_EMALLOC; + // add our known key + e_sector[GetSectorFromBlockNo(blockNo)].foundKey[keyType] = 1; + e_sector[GetSectorFromBlockNo(blockNo)].Key[keyType] = key64; + //test current key and additional standard keys first // add parameter key - memcpy(keyBlock + (MIFARE_DEFAULTKEYS_SIZE * 6), key, 6); + memcpy(keyBlock + (ARRAYLEN(g_mifare_default_keys) * 6), key, 6); - for (int cnt = 0; cnt < MIFARE_DEFAULTKEYS_SIZE; cnt++) { + for (int cnt = 0; cnt < ARRAYLEN(g_mifare_default_keys); cnt++) { num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t *)(keyBlock + cnt * 6)); } PrintAndLogEx(SUCCESS, "Testing known keys. Sector count=%d", SectorsCnt); - mfCheckKeys_fast(SectorsCnt, true, true, 1, MIFARE_DEFAULTKEYS_SIZE + 1, keyBlock, e_sector, false); + int res = mfCheckKeys_fast(SectorsCnt, true, true, 1, ARRAYLEN(g_mifare_default_keys) + 1, keyBlock, e_sector, false); + if (res == PM3_SUCCESS) { + // all keys found + PrintAndLogEx(SUCCESS, "Fast check found all keys"); + goto jumptoend; + } uint64_t t2 = msclock() - t1; - PrintAndLogEx(SUCCESS, "Time to check %d known keys: %.0f seconds\n", MIFARE_DEFAULTKEYS_SIZE, (float)t2 / 1000.0); + PrintAndLogEx(SUCCESS, "Time to check %d known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0); PrintAndLogEx(SUCCESS, "enter nested attack"); // nested sectors // int iterations = 0; bool calibrate = true; - for (int i = 0; i < MIFARE_SECTOR_RETRY; i++) { + for (trgKeyType = 0; trgKeyType < 2; ++trgKeyType) { for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; ++sectorNo) { - for (trgKeyType = 0; trgKeyType < 2; ++trgKeyType) { + for (int i = 0; i < MIFARE_SECTOR_RETRY; i++) { if (e_sector[sectorNo].foundKey[trgKeyType]) continue; @@ -1250,10 +1363,10 @@ static int CmdHF14AMfNested(const char *Cmd) { num_to_bytes(e_sector[i].Key[0], 6, payload.key); // KEY A clearCommandBuffer(); - SendCommandNG(CMD_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); + SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_MIFARE_READBL, &resp, 1500)) continue; + if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) continue; if (resp.status != PM3_SUCCESS) continue; @@ -1267,6 +1380,7 @@ static int CmdHF14AMfNested(const char *Cmd) { } } +jumptoend: //print them printKeyTable(SectorsCnt, e_sector); @@ -1515,6 +1629,679 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { return 0; } +static int CmdHF14AMfAutoPWN(const char *Cmd) { + // Nested and Hardnested parameter + uint8_t blockNo = 0; + uint8_t keyType = 0; + uint8_t key[6] = {0}; + uint64_t key64 = 0; + bool calibrate = true; + // Attack key storage variables + uint8_t *keyBlock = NULL; + uint16_t key_cnt = 0; + sector_t *e_sector; + uint8_t sectors_cnt = MIFARE_1K_MAXSECTOR; + int block_cnt = MIFARE_1K_MAXBLOCK; + uint8_t tmp_key[6] = {0}; + bool know_target_key = false; + // For the timier + uint64_t t1; + // Parameters and dictionary file + char filename[FILE_PATH_SIZE] = {0}; + uint8_t cmdp = 0; + char ctmp; + // Nested and Hardnested returned status + uint64_t foundkey = 0; + int16_t isOK = 0; + int current_sector_i = 0, current_key_type_i = 0; + // Dumping and transfere to simulater memory + uint8_t block[16] = {0x00}; + uint8_t *dump; + int bytes; + char *fnameptr = filename; + // Settings + bool slow = false; + bool legacy_mfchk = false; + int prng_type = PM3_EUNDEF; + bool verbose = false; + bool has_filename = false; + bool errors = false; + + // Parse the options given by the user + while ((ctmp = param_getchar(Cmd, cmdp)) && !errors) { + switch (tolower(ctmp)) { + case 'h': + return usage_hf14_autopwn(); + case 'f': + if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { + PrintAndLogEx(FAILED, "Filename too long"); + errors = true; + } else { + has_filename = true; + } + cmdp += 2; + break; + case 'l': + legacy_mfchk = true; + cmdp++; + break; + case 'v': + verbose = true; + cmdp++; + break; + case '*': + // Get the number of sectors + sectors_cnt = NumOfSectors(param_getchar(Cmd, cmdp + 1)); + block_cnt = NumOfBlocks(param_getchar(Cmd, cmdp + 1)); + cmdp += 2; + break; + case 'k': + // Get the known block number + if (param_getchar(Cmd, cmdp + 1) == 0x00) { + errors = true; + break; + } + + blockNo = param_get8(Cmd, cmdp + 1); + + // Get the knonwn block type + ctmp = tolower(param_getchar(Cmd, cmdp + 2)); + if (ctmp != 'a' && ctmp != 'b') { + PrintAndLogEx(WARNING, "Key type must be A or B"); + errors = true; + break; + } + + if (ctmp != 'a') { + keyType = 1; + } + + // Get the known block key + if (param_gethex(Cmd, cmdp + 3, key, 12)) { + PrintAndLogEx(WARNING, "Key must include 12 HEX symbols"); + errors = true; + return PM3_EINVARG; + } + know_target_key = true; + cmdp += 3; + case 's': + slow = true; + cmdp++; + break; + case 'i': + SetSIMDInstr(SIMD_AUTO); + ctmp = tolower(param_getchar(Cmd, cmdp + 1)); + switch (ctmp) { + case '5': + SetSIMDInstr(SIMD_AVX512); + break; + case '2': + SetSIMDInstr(SIMD_AVX2); + break; + case 'a': + SetSIMDInstr(SIMD_AVX); + break; + case 's': + SetSIMDInstr(SIMD_SSE2); + break; + case 'm': + SetSIMDInstr(SIMD_MMX); + break; + case 'n': + SetSIMDInstr(SIMD_NONE); + break; + default: + PrintAndLogEx(WARNING, "Unknown SIMD type. %c", ctmp); + return PM3_EINVARG; + } + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", ctmp); + return usage_hf14_autopwn(); + } + } + + if (errors) { + return usage_hf14_autopwn(); + } + + // Create the key storage stucture + e_sector = calloc(sectors_cnt, sizeof(sector_t)); + if (e_sector == NULL) return PM3_EMALLOC; + + // clear the key storage + for (int i = 0; i < sectors_cnt; i++) { + for (int j = 0; j < 2; j++) { + e_sector[i].Key[j] = 0; + e_sector[i].foundKey[j] = 0; + } + } + + // card prng type (weak=1 / hard=0 / select/card comm error = negative value) + prng_type = detect_classic_prng(); + if (prng_type < 0){ + PrintAndLogEx(FAILED, "\nNo tag detected or other tag communication error"); + free(e_sector); + return prng_type; + } + + // print parameters + if (verbose) { + PrintAndLogEx(INFO, _YELLOW_("======================= SETTINGS =======================")); + PrintAndLogEx(INFO, " card sectors .. " _YELLOW_("%d"), sectors_cnt); + PrintAndLogEx(INFO, " key supplied .. " _YELLOW_("%s"), know_target_key ? "True" : "False"); + PrintAndLogEx(INFO, " known sector .. " _YELLOW_("%d"), blockNo); + PrintAndLogEx(INFO, " keytype ....... " _YELLOW_("%c"), keyType ? 'B' : 'A'); + PrintAndLogEx(INFO, " known key ..... " _YELLOW_("%s"), sprint_hex(key, sizeof(key))); + PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("%s"), prng_type ? "WEAK" : "HARD"); + PrintAndLogEx(INFO, " dictionary .... " _YELLOW_("%s"), strlen(filename) ? filename : "NONE"); + PrintAndLogEx(INFO, " legacy mode ... " _YELLOW_("%s"), legacy_mfchk ? "True" : "False"); + PrintAndLogEx(INFO, _YELLOW_("======================= SETTINGS =======================")); + } + + // Start the timer + t1 = msclock(); + + // check the user supplied key + if (know_target_key == false) + PrintAndLogEx(WARNING, "no known key was supplied, key recovery might fail"); + else { + if (verbose) { + PrintAndLogEx(INFO, _YELLOW_("======================= START KNOWN KEY ATTACK =======================")); + } + if (mfCheckKeys(FirstBlockOfSector(blockNo), keyType, true, 1, key, &key64) == PM3_SUCCESS) { + PrintAndLogEx(INFO, "target sector:%3u key type: %c -- using valid key [ " _YELLOW_("%s") "] (used for nested / hardnested attack)", + blockNo, + keyType ? 'B' : 'A', + sprint_hex(key, sizeof(key)) + ); + + // Store the key for the nested / hardnested attack (if supplied by the user) + e_sector[blockNo].Key[keyType] = key64; + } else { + know_target_key = false; + PrintAndLogEx(FAILED, "Key is wrong. Can't authenticate to sector:"_RED_("%3d") " key type: "_RED_("%c") " key: " _RED_("%s"), + blockNo, + keyType ? 'B' : 'A', + sprint_hex(key, sizeof(key)) + ); + PrintAndLogEx(WARNING, "falling back to dictionary"); + } + + // Check if the user supplied key is used by other sectors + for (int i = 0; i < sectors_cnt; i++) { + for (int j = 0; j < 2; j++) { + if (e_sector[i].foundKey[j] == 0) { + if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, key, &key64) == PM3_SUCCESS) { + e_sector[i].Key[j] = bytes_to_num(key, 6); + e_sector[i].foundKey[j] = 'U'; + + // If the user supplied secctor / keytype was wrong --> just be nice and correct it ;) + if (know_target_key == false) { + num_to_bytes(e_sector[i].Key[j], 6, key); + know_target_key = true; + blockNo = i; + keyType = j; + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "] (used for nested / hardnested attack)", + i, + j ? 'B' : 'A', + sprint_hex(key, sizeof(key)) + ); + } else { + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", + i, + j ? 'B' : 'A', + sprint_hex(key, sizeof(key)) + ); + } + } + } + } + } + if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= STOP KNOWN KEY ATTACK =======================")); + } + + bool load_success = true; + // Load the dictionary + if (has_filename) { + int res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock, 6, &key_cnt); + if (res != PM3_SUCCESS || key_cnt == 0 || keyBlock == NULL) { + PrintAndLogEx(FAILED, "An error occurred while loading the dictionary! (we will use the default keys now)"); + if (keyBlock != NULL) + free(keyBlock); + + load_success = false; + } + + } + + if (has_filename == false || load_success == false) { + keyBlock = calloc(ARRAYLEN(g_mifare_default_keys), 6); + if (keyBlock == NULL) { + free(e_sector); + return PM3_EMALLOC; + } + + for (int cnt = 0; cnt < ARRAYLEN(g_mifare_default_keys); cnt++) { + num_to_bytes(g_mifare_default_keys[cnt], 6, keyBlock + cnt * 6); + } + key_cnt = ARRAYLEN(g_mifare_default_keys); + PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") "keys from hardcoded default array", key_cnt); + } + + // Use the dictionary to find sector keys on the card + if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= START DICTIONARY ATTACK =======================")); + + if (legacy_mfchk) { + // Check all the sectors + for (int i = 0; i < sectors_cnt; i++) { + for (int j = 0; j < 2; j++) { + // Check if the key is known + if (e_sector[i].foundKey[j] == 0) { + for (int k = 0; k < key_cnt; k++) { + printf("."); + fflush(stdout); + if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, (keyBlock + (6 * k)), &key64) == PM3_SUCCESS) { + e_sector[i].Key[j] = bytes_to_num((keyBlock + (6 * k)), 6); + e_sector[i].foundKey[j] = 'D'; + break; + } + } + } + } + } + printf("\n"); + fflush(stdout); + } else { + + int chunksize = key_cnt > (PM3_CMD_DATA_SIZE / 6) ? (PM3_CMD_DATA_SIZE / 6) : key_cnt; + bool firstChunk = true, lastChunk = false; + + for (uint8_t strategy = 1; strategy < 3; strategy++) { + PrintAndLogEx(INFO, "running strategy %u", strategy); + // main keychunk loop + for (int i = 0; i < key_cnt; i += chunksize) { + + if (kbd_enter_pressed()) { + PrintAndLogEx(WARNING, "\naborted via keyboard!\n"); + i = key_cnt; + strategy = 3; + break; // Exit the loop + } + uint32_t size = ((key_cnt - i) > chunksize) ? chunksize : key_cnt - i; + // last chunk? + if (size == key_cnt - i) + lastChunk = true; + + int res = mfCheckKeys_fast(sectors_cnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), e_sector, false); + if (firstChunk) + firstChunk = false; + // all keys, aborted + if (res == PM3_SUCCESS) { + i = key_cnt; + strategy = 3; + break; // Exit the loop + } + } // end chunks of keys + firstChunk = true; + lastChunk = false; + } // end strategy + } + if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= STOP DICTIONARY ATTACK =======================")); + + + // Analyse the dictionary attack + for (int i = 0; i < sectors_cnt; i++) { + for (int j = 0; j < 2; j++) { + if (e_sector[i].foundKey[j] == 1) { + e_sector[i].foundKey[j] = 'D'; + num_to_bytes(e_sector[i].Key[j], 6, tmp_key); + + // Store valid credentials for the nested / hardnested attack if none exist + if (know_target_key == false) { + num_to_bytes(e_sector[i].Key[j], 6, key); + know_target_key = true; + blockNo = i; + keyType = j; + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "] (used for nested / hardnested attack)", + i, + j ? 'B' : 'A', + sprint_hex(tmp_key, sizeof(tmp_key)) + ); + } else { + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", + i, + j ? 'B' : 'A', + sprint_hex(tmp_key, sizeof(tmp_key)) + ); + } + } + } + } + + // Check if at least one sector key was found + if (know_target_key == false) { + // Check if the darkside attack can be used + if (prng_type) { + if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= START DARKSIDE ATTACK =======================")); + int isOK = mfDarkside(FirstBlockOfSector(blockNo), keyType, &key64); + if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= STOP DARKSIDE ATTACK =======================")); + switch (isOK) { + case -1 : + PrintAndLogEx(WARNING, "\nButton pressed. Aborted."); + goto noValidKeyFound; + case -2 : + PrintAndLogEx(FAILED, "\nCard is not vulnerable to Darkside attack (doesn't send NACK on authentication requests)."); + goto noValidKeyFound; + case -3 : + PrintAndLogEx(FAILED, "\nCard is not vulnerable to Darkside attack (its random number generator is not predictable)."); + goto noValidKeyFound; + case -4 : + PrintAndLogEx(FAILED, "\nCard is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown"); + PrintAndLogEx(FAILED, "generating polynomial with 16 effective bits only, but shows unexpected behaviour."); + goto noValidKeyFound; + case -5 : + PrintAndLogEx(WARNING, "\nAborted via keyboard."); + goto noValidKeyFound; + default : + PrintAndLogEx(SUCCESS, "\nFound valid key: %012" PRIx64 "\n", key64); + break; + } + + // Store the keys + e_sector[blockNo].Key[keyType] = key64; + e_sector[blockNo].foundKey[keyType] = 'S'; + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "] (used for nested / hardnested attack)", + blockNo, + keyType ? 'B' : 'A', + sprint_hex(key, sizeof(key)) + ); + } else { +noValidKeyFound: + PrintAndLogEx(FAILED, "No usable key was found!"); + free(keyBlock); + free(e_sector); + return PM3_ESOFT; + } + } + + free(keyBlock); + // Clear the needed variables + num_to_bytes(0, 6, tmp_key); + bool nested_failed = false; + + // Iterate over each sector and key(A/B) + for (current_sector_i = 0; current_sector_i < sectors_cnt; current_sector_i++) { + for (current_key_type_i = 0; current_key_type_i < 2; current_key_type_i++) { + + // If the key is already known, just skip it + if (e_sector[current_sector_i].foundKey[current_key_type_i] == 0) { + + // Try the found keys are reused + if (bytes_to_num(tmp_key, 6) != 0) { + // The fast check --> mfCheckKeys_fast(sectors_cnt, true, true, 2, 1, tmp_key, e_sector, false); + // Returns false keys, so we just stick to the slower mfchk. + for (int i = 0; i < sectors_cnt; i++) { + for (int j = 0; j < 2; j++) { + // Check if the sector key is already broken + if (e_sector[i].foundKey[j]) + continue; + + // Check if the key works + if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, tmp_key, &key64) == PM3_SUCCESS) { + e_sector[i].Key[j] = bytes_to_num(tmp_key, 6); + e_sector[i].foundKey[j] = 'R'; + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", + i, + j ? 'B' : 'A', + sprint_hex(tmp_key, sizeof(tmp_key)) + ); + } + } + } + } + // Clear the last found key + num_to_bytes(0, 6, tmp_key); + + if (current_key_type_i == 1) { + if (e_sector[current_sector_i].foundKey[0] && !e_sector[current_sector_i].foundKey[1]) { + if (verbose) { + PrintAndLogEx(INFO, _YELLOW_("======================= START READ B KEY ATTACK =======================")); + PrintAndLogEx(INFO, "reading B key: sector: %3d key type: %c", + current_sector_i, + current_key_type_i ? 'B' : 'A'); + } + uint8_t sectrail = (FirstBlockOfSector(current_sector_i) + NumBlocksPerSector(current_sector_i) - 1); + + mf_readblock_t payload; + payload.blockno = sectrail; + payload.keytype = 0; + + num_to_bytes(e_sector[current_sector_i].Key[0], 6, payload.key); // KEY A + + clearCommandBuffer(); + SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); + + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) goto skipReadBKey; + + if (resp.status != PM3_SUCCESS) goto skipReadBKey; + + uint8_t *data = resp.data.asBytes; + key64 = bytes_to_num(data + 10, 6); + 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, 6, tmp_key); + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", + current_sector_i, + current_key_type_i ? 'B' : 'A', + sprint_hex(tmp_key, sizeof(tmp_key)) + ); + } else { + if (verbose) PrintAndLogEx(WARNING, "unknown B key: sector: %3d key type: %c (reading the B key was not possible, maybe due to insufficient access rights) ", + current_sector_i, + current_key_type_i ? 'B' : 'A' + ); + } + if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= STOP READ B KEY ATTACK =======================")); + } + } + + // Use the nested / hardnested attack +skipReadBKey: + if (e_sector[current_sector_i].foundKey[current_key_type_i] == 0) { + if (prng_type && (! nested_failed)) { + uint8_t retries = 0; + if (verbose) { + PrintAndLogEx(INFO, _YELLOW_("======================= START NESTED ATTACK =======================")); + PrintAndLogEx(INFO, "sector no: %3d, target key type: %c", + current_sector_i, + current_key_type_i ? 'B' : 'A'); + } +tryNested: + isOK = mfnested(FirstBlockOfSector(blockNo), keyType, key, FirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key, calibrate); + switch (isOK) { + case -1 : + PrintAndLogEx(ERR, "\nError: No response from Proxmark3."); + free(e_sector); + return PM3_ESOFT; + case -2 : + PrintAndLogEx(WARNING, "\nButton pressed. Aborted."); + free(e_sector); + return PM3_ESOFT; + case -3 : + PrintAndLogEx(FAILED, "Tag isn't vulnerable to Nested Attack (PRNG is probably not predictable)."); + PrintAndLogEx(FAILED, "Nested attack failed --> try hardnested"); + goto tryHardnested; + case -4 : //key not found + calibrate = false; + // this can happen on some old cards, it's worth trying some more before switching to slower hardnested + if (retries++ < MIFARE_SECTOR_RETRY) { + PrintAndLogEx(FAILED, "Nested attack failed, trying again (%i/%i)", retries, MIFARE_SECTOR_RETRY); + goto tryNested; + } else { + PrintAndLogEx(FAILED, "Nested attack failed, moving to hardnested"); + nested_failed = true; + goto tryHardnested; + } + break; + case -5 : + calibrate = false; + e_sector[current_sector_i].Key[current_key_type_i] = bytes_to_num(tmp_key, 6); + e_sector[current_sector_i].foundKey[current_key_type_i] = 'N'; + break; + default : + PrintAndLogEx(ERR, "unknown Error.\n"); + free(e_sector); + return PM3_ESOFT; + } + if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= STOP NESTED ATTACK =======================")); + } else { +tryHardnested: // If the nested attack fails then we try the hardnested attack + if (verbose) { + PrintAndLogEx(INFO, _YELLOW_("======================= START HARDNESTED ATTACK =======================")); + PrintAndLogEx(INFO, "sector no: %3d, target key type: %c, Slow: %s", + current_sector_i, + current_key_type_i ? 'B' : 'A', + slow ? "Yes" : "No"); + } + + isOK = mfnestedhard(FirstBlockOfSector(blockNo), keyType, key, FirstBlockOfSector(current_sector_i), current_key_type_i, NULL, false, false, slow, 0, &foundkey, NULL); + DropField(); + if (isOK) { + switch (isOK) { + case 1 : + PrintAndLogEx(ERR, "\nError: No response from Proxmark3."); + break; + case 2 : + PrintAndLogEx(NORMAL, "\nButton pressed. Aborted."); + break; + default : + break; + } + free(e_sector); + return PM3_ESOFT; + } + + // Copy the found key to the tmp_key variale (for the following print statement, and the mfCheckKeys above) + num_to_bytes(foundkey, 6, tmp_key); + e_sector[current_sector_i].Key[current_key_type_i] = foundkey; + e_sector[current_sector_i].foundKey[current_key_type_i] = 'H'; + + if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= STOP HARDNESTED ATTACK =======================")); + } + // Check if the key was found + if (e_sector[current_sector_i].foundKey[current_key_type_i]) { + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", + current_sector_i, + current_key_type_i ? 'B' : 'A', + sprint_hex(tmp_key, sizeof(tmp_key)) + ); + } + } + } + } + } + + // Show the results to the user + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "found Keys:"); + + char strA[12 + 1] = {0}; + char strB[12 + 1] = {0}; + PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); + PrintAndLogEx(NORMAL, "|sec|key A |res|key B |res|"); + PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); + for (uint8_t i = 0; i < sectors_cnt; ++i) { + + snprintf(strA, sizeof(strA), "------------"); + snprintf(strB, sizeof(strB), "------------"); + + if (e_sector[i].foundKey[0]) + snprintf(strA, sizeof(strA), "%012" PRIx64, e_sector[i].Key[0]); + + if (e_sector[i].foundKey[1]) + snprintf(strB, sizeof(strB), "%012" PRIx64, e_sector[i].Key[1]); + + + PrintAndLogEx(NORMAL, "|%03d| %s | " _YELLOW_("%c")"| %s | " _YELLOW_("%c")"|" + , i + , strA, e_sector[i].foundKey[0] + , strB, e_sector[i].foundKey[1] + ); + } + PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); + PrintAndLogEx(NORMAL, "( " + _YELLOW_("D") ":Dictionary / " + _YELLOW_("S") ":darkSide / " + _YELLOW_("U") ":User / " + _YELLOW_("R") ":Reused / " + _YELLOW_("N") ":Nested / " + _YELLOW_("H") ":Hardnested / " + _YELLOW_("A") ":keyA " + ")" + ); + + // Dump the keys + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "saving keys"); + createMfcKeyDump(sectors_cnt, e_sector, GenerateFilename("hf-mf-", "-key.bin")); + + PrintAndLogEx(SUCCESS, "transferring keys to simulator memory (Cmd Error: 04 can occur)"); + + for (current_sector_i = 0; current_sector_i < sectors_cnt; current_sector_i++) { + mfEmlGetMem(block, current_sector_i, 1); + if (e_sector[current_sector_i].foundKey[0]) + num_to_bytes(e_sector[current_sector_i].Key[0], 6, block); + if (e_sector[current_sector_i].foundKey[1]) + num_to_bytes(e_sector[current_sector_i].Key[1], 6, block + 10); + + mfEmlSetMem(block, FirstBlockOfSector(current_sector_i) + NumBlocksPerSector(current_sector_i) - 1, 1); + } + + // use ecfill trick + FastDumpWithEcFill(sectors_cnt); + + bytes = block_cnt * MFBLOCK_SIZE; + dump = calloc(bytes, sizeof(uint8_t)); + if (!dump) { + PrintAndLogEx(ERR, "Fail, cannot allocate memory"); + free(e_sector); + return PM3_EMALLOC; + } + memset(dump, 0, bytes); + + PrintAndLogEx(INFO, "downloading the card content from emulator memory"); + if (!GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false)) { + PrintAndLogEx(ERR, "Fail, transfer from device time-out"); + free(e_sector); + free(dump); + return PM3_ETIMEOUT; + } + + fnameptr = GenerateFilename("hf-mf-", "-data"); + if (fnameptr == NULL) { + free(dump); + free(e_sector); + return PM3_ESOFT; + } + strcpy(filename, fnameptr); + + saveFile(filename, ".bin", dump, bytes); + saveFileEML(filename, dump, bytes, MFBLOCK_SIZE); + saveFileJSON(filename, jsfCardMemory, dump, bytes); + + // Generate and show statistics + t1 = msclock() - t1; + PrintAndLogEx(INFO, "autopwn execution time: " _YELLOW_("%.0f") " seconds", (float)t1 / 1000.0); + + free(dump); + free(e_sector); + return PM3_SUCCESS; +} + /* static int randInRange(int min, int max) { return min + (int)(rand() / (double)(RAND_MAX) * (max - min + 1)); @@ -1548,21 +2335,20 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { char filename[FILE_PATH_SIZE] = {0}; char buf[13]; char *fptr; - uint8_t tempkey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; uint8_t *keyBlock, *p; uint8_t sectorsCnt = 1; int i, keycnt = 0; int clen = 0; int transferToEml = 0, createDumpFile = 0; - uint32_t keyitems = MIFARE_DEFAULTKEYS_SIZE; + uint32_t keyitems = ARRAYLEN(g_mifare_default_keys); bool use_flashmemory = false; sector_t *e_sector = NULL; - keyBlock = calloc(MIFARE_DEFAULTKEYS_SIZE, 6); - if (keyBlock == NULL) return 1; + keyBlock = calloc(ARRAYLEN(g_mifare_default_keys), 6); + if (keyBlock == NULL) return PM3_EMALLOC; - for (int cnt = 0; cnt < MIFARE_DEFAULTKEYS_SIZE; cnt++) + for (int cnt = 0; cnt < ARRAYLEN(g_mifare_default_keys); cnt++) num_to_bytes(g_mifare_default_keys[cnt], 6, keyBlock + cnt * 6); // sectors @@ -1600,7 +2386,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { if (!p) { PrintAndLogEx(FAILED, "Cannot allocate memory for Keys"); free(keyBlock); - return 2; + return PM3_EMALLOC; } keyBlock = p; } @@ -1614,14 +2400,24 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { // May be a dic file if (param_getstr(Cmd, i, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { PrintAndLogEx(FAILED, "Filename too long"); - continue; + free(keyBlock); + return PM3_EINVARG; } - f = fopen(filename, "r"); - if (!f) { - PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename); - continue; + char *dict_path; + int res = searchFile(&dict_path, DICTIONARIES_SUBDIR, filename, ".dic", false); + if (res != PM3_SUCCESS) { + free(keyBlock); + return res; } + f = fopen(dict_path, "r"); + if (!f) { + PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", dict_path); + free(dict_path); + free(keyBlock); + return PM3_EFILE; + } + free(dict_path); // read file while (fgets(buf, sizeof(buf), f)) { @@ -1644,7 +2440,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { PrintAndLogEx(FAILED, "Cannot allocate memory for default keys"); free(keyBlock); fclose(f); - return 2; + return PM3_EMALLOC; } keyBlock = p; } @@ -1661,7 +2457,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { if (keycnt == 0 && !use_flashmemory) { PrintAndLogEx(SUCCESS, "No key specified, trying default keys"); - for (; keycnt < MIFARE_DEFAULTKEYS_SIZE; keycnt++) + for (; keycnt < ARRAYLEN(g_mifare_default_keys); keycnt++) PrintAndLogEx(NORMAL, "[%2d] %02x%02x%02x%02x%02x%02x", keycnt, (keyBlock + 6 * keycnt)[0], (keyBlock + 6 * keycnt)[1], (keyBlock + 6 * keycnt)[2], (keyBlock + 6 * keycnt)[3], (keyBlock + 6 * keycnt)[4], (keyBlock + 6 * keycnt)[5]); @@ -1671,7 +2467,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { e_sector = calloc(sectorsCnt, sizeof(sector_t)); if (e_sector == NULL) { free(keyBlock); - return 1; + return PM3_EMALLOC; } uint32_t chunksize = keycnt > (PM3_CMD_DATA_SIZE / 6) ? (PM3_CMD_DATA_SIZE / 6) : keycnt; @@ -1709,7 +2505,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { firstChunk = false; // all keys, aborted - if (res == 0 || res == 2) + if (res == PM3_SUCCESS || res == 2) goto out; } // end chunks of keys firstChunk = true; @@ -1737,6 +2533,13 @@ out: printKeyTable(sectorsCnt, e_sector); + if (use_flashmemory && found_keys == (sectorsCnt << 1)) { + PrintAndLogEx(SUCCESS, "Card dumped aswell. run " _YELLOW_("`%s %c`"), + "hf mf esave", + GetFormatFromSector(sectorsCnt) + ); + } + if (transferToEml) { // fast push mode conn.block_after_ACK = true; @@ -1755,34 +2558,15 @@ out: mfEmlSetMem(block, blockno, 1); } PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory"); + + if (found_keys == (sectorsCnt << 1)) { + FastDumpWithEcFill(sectorsCnt); + } } if (createDumpFile) { fptr = GenerateFilename("hf-mf-", "-key.bin"); - if (fptr == NULL) - return 1; - - FILE *fkeys = fopen(fptr, "wb"); - if (fkeys == NULL) { - PrintAndLogEx(WARNING, "Could not create file " _YELLOW_("%s"), fptr); - free(keyBlock); - free(e_sector); - return 1; - } - PrintAndLogEx(SUCCESS, "Printing keys to binary file " _YELLOW_("%s")"...", fptr); - - for (i = 0; i < sectorsCnt; i++) { - num_to_bytes(e_sector[i].Key[0], 6, tempkey); - fwrite(tempkey, 1, 6, fkeys); - } - - for (i = 0; i < sectorsCnt; i++) { - num_to_bytes(e_sector[i].Key[1], 6, tempkey); - fwrite(tempkey, 1, 6, fkeys); - } - - fclose(fkeys); - PrintAndLogEx(SUCCESS, "Found keys have been dumped to " _YELLOW_("%s")" --> 0xffffffffffff has been inserted for unknown keys.", fptr); + createMfcKeyDump(sectorsCnt, e_sector, fptr); } } @@ -1806,19 +2590,18 @@ static int CmdHF14AMfChk(const char *Cmd) { uint8_t blockNo = 0; uint8_t SectorsCnt = 1; uint8_t keyType = 0; - uint32_t keyitems = MIFARE_DEFAULTKEYS_SIZE; + uint32_t keyitems = ARRAYLEN(g_mifare_default_keys); uint64_t key64 = 0; - uint8_t tempkey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; char *fptr; int clen = 0; int transferToEml = 0; int createDumpFile = 0; int i, keycnt = 0; - keyBlock = calloc(MIFARE_DEFAULTKEYS_SIZE, 6); + keyBlock = calloc(ARRAYLEN(g_mifare_default_keys), 6); if (keyBlock == NULL) return PM3_EMALLOC; - for (int cnt = 0; cnt < MIFARE_DEFAULTKEYS_SIZE; cnt++) + for (int cnt = 0; cnt < ARRAYLEN(g_mifare_default_keys); cnt++) num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t *)(keyBlock + cnt * 6)); if (param_getchar(Cmd, 0) == '*') { @@ -1879,14 +2662,24 @@ static int CmdHF14AMfChk(const char *Cmd) { // May be a dic file if (param_getstr(Cmd, i, filename, sizeof(filename)) >= FILE_PATH_SIZE) { PrintAndLogEx(FAILED, "File name too long"); - continue; + free(keyBlock); + return PM3_EINVARG; } - f = fopen(filename, "r"); - if (!f) { - PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename); - continue; + char *dict_path; + int res = searchFile(&dict_path, DICTIONARIES_SUBDIR, filename, ".dic", false); + if (res != PM3_SUCCESS) { + free(keyBlock); + return PM3_EFILE; } + f = fopen(dict_path, "r"); + if (!f) { + PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", dict_path); + free(dict_path); + free(keyBlock); + return PM3_EFILE; + } + free(dict_path); // load keys from dictionary file while (fgets(buf, sizeof(buf), f)) { @@ -1928,7 +2721,7 @@ static int CmdHF14AMfChk(const char *Cmd) { if (keycnt == 0) { PrintAndLogEx(INFO, "No key specified, trying default keys"); - for (; keycnt < MIFARE_DEFAULTKEYS_SIZE; keycnt++) + for (; keycnt < ARRAYLEN(g_mifare_default_keys); keycnt++) PrintAndLogEx(NORMAL, "[%2d] %02x%02x%02x%02x%02x%02x", keycnt, (keyBlock + 6 * keycnt)[0], (keyBlock + 6 * keycnt)[1], (keyBlock + 6 * keycnt)[2], (keyBlock + 6 * keycnt)[3], (keyBlock + 6 * keycnt)[4], (keyBlock + 6 * keycnt)[5], 6); @@ -2014,10 +2807,10 @@ static int CmdHF14AMfChk(const char *Cmd) { num_to_bytes(e_sector[i].Key[0], 6, payload.key); // KEY A clearCommandBuffer(); - SendCommandNG(CMD_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); + SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_MIFARE_READBL, &resp, 1500)) continue; + if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) continue; if (resp.status != PM3_SUCCESS) continue; @@ -2063,31 +2856,7 @@ out: if (createDumpFile) { fptr = GenerateFilename("hf-mf-", "-key.bin"); - if (fptr == NULL) { - free(keyBlock); - free(e_sector); - return PM3_EFILE; - } - - FILE *fkeys = fopen(fptr, "wb"); - if (fkeys == NULL) { - PrintAndLogEx(WARNING, "Could not create file " _YELLOW_("%s"), fptr); - free(keyBlock); - free(e_sector); - return PM3_EFILE; - } - PrintAndLogEx(INFO, "Printing keys to binary file " _YELLOW_("%s")"...", fptr); - - for (i = 0; i < SectorsCnt; i++) { - num_to_bytes(e_sector[i].Key[0], 6, tempkey); - fwrite(tempkey, 1, 6, fkeys); - } - for (i = 0; i < SectorsCnt; i++) { - num_to_bytes(e_sector[i].Key[1], 6, tempkey); - fwrite(tempkey, 1, 6, fkeys); - } - fclose(fkeys); - PrintAndLogEx(SUCCESS, "Found keys have been dumped to file " _YELLOW_("%s")". 0xffffffffffff has been inserted for unknown keys.", fptr); + createMfcKeyDump(SectorsCnt, e_sector, fptr); } free(keyBlock); @@ -2163,6 +2932,10 @@ void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose) { static int CmdHF14AMfSim(const char *Cmd) { uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint8_t atqa[2] = {0, 0}; + int atqalen = 0; + uint8_t sak[1] = {0}; + int saklen = 0; uint8_t exitAfterNReads = 0; uint16_t flags = 0; int uidlen = 0; @@ -2194,6 +2967,10 @@ static int CmdHF14AMfSim(const char *Cmd) { flags |= FLAG_MF_MINI; sprintf(csize, "MINI"); break; + case 1: + flags |= FLAG_MF_1K; + sprintf(csize, "1K"); + break; case 2: flags |= FLAG_MF_2K; sprintf(csize, "2K with RATS"); @@ -2202,14 +2979,33 @@ static int CmdHF14AMfSim(const char *Cmd) { flags |= FLAG_MF_4K; sprintf(csize, "4K"); break; - case 1: default: - flags |= FLAG_MF_1K; - sprintf(csize, "1K"); + PrintAndLogEx(WARNING, "Unknown parameter for option t"); + errors = true; break; } cmdp += 2; break; + case 'a': + param_gethex_ex(Cmd, cmdp + 1, atqa, &atqalen); + if (atqalen >> 1 != 2) { + PrintAndLogEx(WARNING, "Wrong ATQA length"); + errors = true; + break; + } + flags |= FLAG_FORCED_ATQA; + cmdp += 2; + break; + case 's': + param_gethex_ex(Cmd, cmdp + 1, sak, &saklen); + if (saklen >> 1 != 1) { + PrintAndLogEx(WARNING, "Wrong SAK length"); + errors = true; + break; + } + flags |= FLAG_FORCED_SAK; + cmdp += 2; + break; case 'u': param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen); uidlen >>= 1; @@ -2268,14 +3064,18 @@ static int CmdHF14AMfSim(const char *Cmd) { uint16_t flags; uint8_t exitAfter; uint8_t uid[10]; + uint16_t atqa; + uint8_t sak; } PACKED payload; payload.flags = flags; payload.exitAfter = exitAfterNReads; memcpy(payload.uid, uid, uidlen); + payload.atqa = (atqa[1] << 8) | atqa[0]; + payload.sak = sak[0]; clearCommandBuffer(); - SendCommandNG(CMD_SIMULATE_MIFARE_CARD, (uint8_t *)&payload, sizeof(payload)); + SendCommandNG(CMD_HF_MIFARE_SIMULATE, (uint8_t *)&payload, sizeof(payload)); PacketResponseNG resp; if (flags & FLAG_INTERACTIVE) { @@ -2284,7 +3084,7 @@ static int CmdHF14AMfSim(const char *Cmd) { while (!kbd_enter_pressed()) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) continue; if (!(flags & FLAG_NR_AR_ATTACK)) break; - if ((resp.oldarg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD) break; + if ((resp.oldarg[0] & 0xffff) != CMD_HF_MIFARE_SIMULATE) break; memcpy(data, resp.data.asBytes, sizeof(data)); readerAttack(data[0], setEmulatorMem, verbose); @@ -2333,7 +3133,7 @@ static int CmdHF14AMfSniff(const char *Cmd) { PrintAndLogEx(NORMAL, "-------------------------------------------------------------------------\n"); clearCommandBuffer(); - SendCommandNG(CMD_MIFARE_SNIFFER, NULL, 0); + SendCommandNG(CMD_HF_MIFARE_SNIFF, NULL, 0); PacketResponseNG resp; @@ -2452,6 +3252,8 @@ static int CmdHF14AMfSniff(const char *Cmd) { return PM3_SUCCESS; } */ + +/* static int CmdHF14AMfKeyBrute(const char *Cmd) { uint8_t blockNo = 0, keytype = 0; @@ -2482,6 +3284,7 @@ static int CmdHF14AMfKeyBrute(const char *Cmd) { PrintAndLogEx(SUCCESS, "\ntime in keybrute: %.0f seconds\n", (float)t1 / 1000.0); return PM3_SUCCESS; } +*/ void printKeyTable(uint8_t sectorscnt, sector_t *e_sector) { char strA[12 + 1] = {0}; @@ -2510,6 +3313,7 @@ void printKeyTable(uint8_t sectorscnt, sector_t *e_sector) { PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); } + // EMULATOR COMMANDS static int CmdHF14AMfEGet(const char *Cmd) { char c = tolower(param_getchar(Cmd, 0)); @@ -2530,7 +3334,7 @@ static int CmdHF14AMfEClear(const char *Cmd) { if (c == 'h') return usage_hf14_eclr(); clearCommandBuffer(); - SendCommandNG(CMD_MIFARE_EML_MEMCLR, NULL, 0); + SendCommandNG(CMD_HF_MIFARE_EML_MEMCLR, NULL, 0); return PM3_SUCCESS; } @@ -2739,8 +3543,12 @@ static int CmdHF14AMfECFill(const char *Cmd) { } PrintAndLogEx(NORMAL, "--params: numSectors: %d, keyType: %c\n", numSectors, (keyType == 0) ? 'A' : 'B'); + + mfc_eload_t payload; + payload.sectorcnt = numSectors; + payload.keytype = keyType; clearCommandBuffer(); - SendCommandMIX(CMD_MIFARE_EML_CARDLOAD, numSectors, keyType, 0, NULL, 0); + SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload)); return PM3_SUCCESS; } @@ -3216,10 +4024,10 @@ static int CmdHf14AMfSetMod(const char *Cmd) { memcpy(data + 1, key, 6); clearCommandBuffer(); - SendCommandNG(CMD_MIFARE_SETMOD, data, sizeof(data)); + SendCommandNG(CMD_HF_MIFARE_SETMOD, data, sizeof(data)); PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_MIFARE_SETMOD, &resp, 1500)) { + if (WaitForResponseTimeout(CMD_HF_MIFARE_SETMOD, &resp, 1500)) { if (resp.status == PM3_SUCCESS) PrintAndLogEx(SUCCESS, "Success"); @@ -3314,7 +4122,7 @@ static int CmdHF14AMfice(const char *Cmd) { flags |= initialize ? 0x0001 : 0; flags |= slow ? 0x0002 : 0; clearCommandBuffer(); - SendCommandMIX(CMD_MIFARE_ACQUIRE_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, flags, NULL, 0); + SendCommandMIX(CMD_HF_MIFARE_ACQ_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, flags, NULL, 0); if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) goto out; if (resp.oldarg[0]) goto out; @@ -3346,7 +4154,7 @@ out: } clearCommandBuffer(); - SendCommandMIX(CMD_MIFARE_ACQUIRE_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, 4, NULL, 0); + SendCommandMIX(CMD_HF_MIFARE_ACQ_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, 4, NULL, 0); return PM3_SUCCESS; } @@ -3588,12 +4396,13 @@ static int CmdHF14AMfList(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"list", CmdHF14AMfList, AlwaysAvailable, "List Mifare history"}, - {"darkside", CmdHF14AMfDarkside, IfPm3Iso14443a, "Darkside attack. read parity error messages."}, - {"nested", CmdHF14AMfNested, IfPm3Iso14443a, "Nested attack. Test nested authentication"}, - {"hardnested", CmdHF14AMfNestedHard, AlwaysAvailable, "Nested attack for hardened Mifare cards"}, - {"keybrute", CmdHF14AMfKeyBrute, IfPm3Iso14443a, "J_Run's 2nd phase of multiple sector nested authentication key recovery"}, - {"nack", CmdHf14AMfNack, IfPm3Iso14443a, "Test for Mifare NACK bug"}, + {"list", CmdHF14AMfList, AlwaysAvailable, "List MIFARE history"}, + {"darkside", CmdHF14AMfDarkside, IfPm3Iso14443a, "Darkside attack"}, + {"nested", CmdHF14AMfNested, IfPm3Iso14443a, "Nested attack"}, + {"hardnested", CmdHF14AMfNestedHard, AlwaysAvailable, "Nested attack for hardened MIFARE Classic cards"}, + {"autopwn", CmdHF14AMfAutoPWN, IfPm3Iso14443a, "Automatic key recovery tool for MIFARE Classic"}, +// {"keybrute", CmdHF14AMfKeyBrute, IfPm3Iso14443a, "J_Run's 2nd phase of multiple sector nested authentication key recovery"}, + {"nack", CmdHf14AMfNack, IfPm3Iso14443a, "Test for MIFARE NACK bug"}, {"chk", CmdHF14AMfChk, IfPm3Iso14443a, "Check keys"}, {"fchk", CmdHF14AMfChk_fast, IfPm3Iso14443a, "Check keys fast, targets all keys on card"}, {"decrypt", CmdHf14AMfDecryptBytes, AlwaysAvailable, "[nt] [ar_enc] [at_enc] [data] - to decrypt sniff or trace"}, @@ -3607,7 +4416,7 @@ static command_t CommandTable[] = { {"auth4", CmdHF14AMfAuth4, IfPm3Iso14443a, "ISO14443-4 AES authentication"}, // {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"}, {"-----------", CmdHelp, IfPm3Iso14443a, ""}, - {"sim", CmdHF14AMfSim, IfPm3Iso14443a, "Simulate MIFARE card"}, + {"sim", CmdHF14AMfSim, IfPm3Iso14443a, "Simulate MIFARE card"}, {"eclr", CmdHF14AMfEClear, IfPm3Iso14443a, "Clear simulator memory"}, {"eget", CmdHF14AMfEGet, IfPm3Iso14443a, "Get simulator memory block"}, {"eset", CmdHF14AMfESet, IfPm3Iso14443a, "Set simulator memory block"}, @@ -3626,7 +4435,7 @@ static command_t CommandTable[] = { {"mad", CmdHF14AMfMAD, IfPm3Iso14443a, "Checks and prints MAD"}, {"ndef", CmdHFMFNDEF, IfPm3Iso14443a, "Prints NDEF records from card"}, - {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect Mifare Classic nonces to file"}, + {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"}, {NULL, NULL, NULL, NULL} }; diff --git a/client/cmdhfmf.h b/client/cmdhfmf.h index 8b7e68a40..55997bd87 100644 --- a/client/cmdhfmf.h +++ b/client/cmdhfmf.h @@ -11,26 +11,9 @@ #ifndef CMDHFMF_H__ #define CMDHFMF_H__ -#include -#include -#include -#include -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "cmdparser.h" #include "common.h" -#include "util.h" -#include "mifare.h" // nonces_t struct -#include "mifare/mfkey.h" // mfkey32_moebious -#include "cmdhfmfhard.h" -#include "mifare/mifarehost.h" // icesector_t, sector_t -#include "util_posix.h" // msclock -#include "mifare/mifaredefault.h" // mifare default key array -#include "cmdhf14a.h" // dropfield -#include "cliparser/cliparser.h" // argtable -#include "hardnested/hardnested_bf_core.h" // SetSIMDInstr +#include "mifare/mfkey.h" +#include "mifare/mifarehost.h" // struct int CmdHFMF(const char *Cmd); int CmdHF14AMfELoad(const char *Cmd); // used by cmd hf mfu eload diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index d9023da47..f46384d12 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -9,6 +9,15 @@ //----------------------------------------------------------------------------- #include "cmdhfmfdes.h" +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "cmdhf14a.h" +#include "mbedtls/des.h" + uint8_t key_zero_data[16] = { 0x00 }; uint8_t key_ones_data[16] = { 0x01 }; uint8_t key_defa_data[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; @@ -51,7 +60,7 @@ static int CmdHF14ADesWb(const char *Cmd) { uint8_t data[26]; memcpy(data, key, 6); memcpy(data + 10, bldata, 16); - SendCommandOLD(CMD_MIFARE_WRITEBL, blockNo, keyType, 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_MIFARE_WRITEBL, blockNo, keyType, 0, data, sizeof(data)); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { @@ -92,10 +101,10 @@ static int CmdHF14ADesRb(const char *Cmd) { mf_readblock_t payload = { blockNo, keyType, key }; - SendCommandNG(CMD_MIFARE_READBL, (uint8_t *)payload, sizeof(mf_readblock_t) ); + SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)payload, sizeof(mf_readblock_t) ); PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_MIFARE_READBL, &resp, 1500)) { + if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) { uint8_t * data = resp.data.asBytes; if (resp.status == PM3_SUCCESS) @@ -112,7 +121,7 @@ static int CmdHF14ADesRb(const char *Cmd) { static int CmdHF14ADesInfo(const char *Cmd) { (void)Cmd; // Cmd is not used so far - SendCommandNG(CMD_MIFARE_DESFIRE_INFO, NULL, 0); + SendCommandNG(CMD_HF_DESFIRE_INFO, NULL, 0); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { @@ -164,7 +173,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { // Free memory on card uint8_t data[1] = {GET_FREE_MEMORY}; - SendCommandOLD(CMD_MIFARE_DESFIRE, (INIT | DISCONNECT), 0x01, 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_DESFIRE_COMMAND, (INIT | DISCONNECT), 0x01, 0, data, sizeof(data)); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return 0; @@ -256,7 +265,7 @@ void getKeySettings(uint8_t *aid) { PrintAndLogEx(NORMAL, ""); { uint8_t data[1] = {GET_KEY_SETTINGS}; // 0x45 - SendCommandOLD(CMD_MIFARE_DESFIRE, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} isOK = resp.oldarg[0] & 0xff; @@ -275,7 +284,7 @@ void getKeySettings(uint8_t *aid) { PrintAndLogEx(NORMAL, " [0x01] CMK is changeable : %s", str); { uint8_t data[2] = {GET_KEY_VERSION, 0}; // 0x64 - SendCommandOLD(CMD_MIFARE_DESFIRE, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) { return; } isOK = resp.oldarg[0] & 0xff; @@ -290,7 +299,7 @@ void getKeySettings(uint8_t *aid) { { uint8_t data[2] = {AUTHENTICATE, 0}; // 0x0A, KEY 0 - SendCommandOLD(CMD_MIFARE_DESFIRE, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} isOK = resp.data.asBytes[2] & 0xff; @@ -298,7 +307,7 @@ void getKeySettings(uint8_t *aid) { { uint8_t data[2] = {AUTHENTICATE_ISO, 0}; // 0x1A, KEY 0 - SendCommandOLD(CMD_MIFARE_DESFIRE, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} isOK = resp.data.asBytes[2] & 0xff; @@ -306,7 +315,7 @@ void getKeySettings(uint8_t *aid) { { uint8_t data[2] = {AUTHENTICATE_AES, 0}; // 0xAA, KEY 0 - SendCommandOLD(CMD_MIFARE_DESFIRE, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} isOK = resp.data.asBytes[2] & 0xff; @@ -321,7 +330,7 @@ void getKeySettings(uint8_t *aid) { { uint8_t data[4] = {SELECT_APPLICATION}; // 0x5a memcpy(data + 1, aid, 3); - SendCommandOLD(CMD_MIFARE_DESFIRE, INIT | CLEARTRACE, sizeof(data), 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT | CLEARTRACE, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(WARNING, " Timed-out"); @@ -336,7 +345,7 @@ void getKeySettings(uint8_t *aid) { // KEY SETTINGS { uint8_t data[1] = {GET_KEY_SETTINGS}; // 0x45 - SendCommandOLD(CMD_MIFARE_DESFIRE, NONE, sizeof(data), 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { return; @@ -358,7 +367,7 @@ void getKeySettings(uint8_t *aid) { str = "All keys (except AMK,see Bit0) within this application are frozen"; break; default: - str = "Authentication with the specified key is necessary to change any ley. A change key and a PICC master key (CMK) can only be changed after authentication with the master key. For keys other then the master or change key, an authentication with the same key is needed."; + str = "Authentication with the specified key is necessary to change any key. A change key and a PICC master key (CMK) can only be changed after authentication with the master key. For keys other then the master or change key, an authentication with the same key is needed."; break; } PrintAndLogEx(NORMAL, "Changekey Access rights"); @@ -378,7 +387,7 @@ void getKeySettings(uint8_t *aid) { // KEY VERSION - AMK { uint8_t data[2] = {GET_KEY_VERSION, 0}; // 0x64 - SendCommandOLD(CMD_MIFARE_DESFIRE, NONE, sizeof(data), 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(WARNING, " Timed-out"); @@ -417,7 +426,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { uint8_t aid[3]; { uint8_t data[1] = {GET_APPLICATION_IDS}; //0x6a - SendCommandOLD(CMD_MIFARE_DESFIRE, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } PacketResponseNG resp; @@ -452,7 +461,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { { uint8_t data[4] = {SELECT_APPLICATION}; // 0x5a memcpy(data + 1, &resp.data.asBytes[i], 3); - SendCommandOLD(CMD_MIFARE_DESFIRE, INIT, sizeof(data), 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &respAid, 1500)) { @@ -468,7 +477,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { // Get File IDs { uint8_t data[1] = {GET_FILE_IDS}; // 0x6f - SendCommandOLD(CMD_MIFARE_DESFIRE, NONE, sizeof(data), 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &respFiles, 1500)) { @@ -489,7 +498,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { // Get ISO File IDs { uint8_t data[1] = {GET_ISOFILE_IDS}; // 0x61 - SendCommandOLD(CMD_MIFARE_DESFIRE, DISCONNECT, sizeof(data), 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_DESFIRE_COMMAND, DISCONNECT, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &respFiles, 1500)) { @@ -600,7 +609,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { uint8_t data[25] = {keylength}; // max length: 1 + 24 (3k3DES) memcpy(data + 1, key, keylength); clearCommandBuffer(); - SendCommandOLD(CMD_MIFARE_DESFIRE_AUTH1, cmdAuthMode, cmdAuthAlgo, cmdKeyNo, data, keylength + 1); + SendCommandOLD(CMD_HF_DESFIRE_AUTH1, cmdAuthMode, cmdAuthAlgo, cmdKeyNo, data, keylength + 1); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { diff --git a/client/cmdhfmfdes.h b/client/cmdhfmfdes.h index 70e61e757..3a19f6d83 100644 --- a/client/cmdhfmfdes.h +++ b/client/cmdhfmfdes.h @@ -10,19 +10,7 @@ #ifndef __MFDESFIRE_H #define __MFDESFIRE_H -#include -#include -#include -#include -#include "cmdmain.h" -#include "proxmark3.h" -#include "../include/common.h" -#include "../include/mifare.h" -#include "ui.h" -#include "cmdparser.h" -#include "util.h" -#include "cmdhf14a.h" -#include "mbedtls/des.h" +#include "common.h" int CmdHFMFDes(const char *Cmd); diff --git a/client/cmdhfmfdesfire.c b/client/cmdhfmfdesfire_disabled.c similarity index 98% rename from client/cmdhfmfdesfire.c rename to client/cmdhfmfdesfire_disabled.c index d09a56eea..fc123667b 100644 --- a/client/cmdhfmfdesfire.c +++ b/client/cmdhfmfdesfire_disabled.c @@ -10,6 +10,13 @@ #include "cmdhfmfdesfire.h" +#include "cmdparser.h" // command_t + +#include "cmdhfmf.h" +#include "util.h" +#include "mbedtls/des.h" +#include "mbedtls/aes.h" + static int CmdHelp(const char *Cmd); //DESFIRE diff --git a/client/cmdhfmfdesfire.h b/client/cmdhfmfdesfire_disabled.h similarity index 52% rename from client/cmdhfmfdesfire.h rename to client/cmdhfmfdesfire_disabled.h index bfa653dc3..1583bc395 100644 --- a/client/cmdhfmfdesfire.h +++ b/client/cmdhfmfdesfire_disabled.h @@ -1,10 +1,7 @@ #ifndef __MFDESFIRE_AD_H #define __MFDESFIRE_AD_H -#include "cmdhfmf.h" -#include "util.h" -#include "mbedtls/des.h" -#include "mbedtls/aes.h" +#include "common.h" int CmdHFMFDesfire(const char *Cmd); diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 4de46d36a..c38c4022e 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -21,28 +21,29 @@ #include #include #include -#include -#include #include #include +#include // MingW + +#include "commonutil.h" // ARRAYLEN +#include "comms.h" + #include "proxmark3.h" -#include "cmdmain.h" #include "ui.h" -#include "util.h" #include "util_posix.h" #include "crapto1/crapto1.h" #include "parity.h" -#include "hardnested/hardnested_bruteforce.h" #include "hardnested/hardnested_bf_core.h" #include "hardnested/hardnested_bitarray_core.h" #include "zlib.h" +#include "fileutils.h" #define NUM_CHECK_BITFLIPS_THREADS (num_CPUs()) #define NUM_REDUCTION_WORKING_THREADS (num_CPUs()) #define IGNORE_BITFLIP_THRESHOLD 0.99 // ignore bitflip arrays which have nearly only valid states -#define STATE_FILES_DIRECTORY "hardnested/tables/" +#define STATE_FILES_DIRECTORY "hardnested_tables/" #define STATE_FILE_TEMPLATE "bitflip_%d_%03" PRIx16 "_states.bin.z" #define DEBUG_KEY_ELIMINATION @@ -248,10 +249,15 @@ static void init_bitflip_bitarrays(void) { bitflip_bitarrays[odd_even][bitflip] = NULL; count_bitflip_bitarrays[odd_even][bitflip] = 1 << 24; sprintf(state_file_name, STATE_FILE_TEMPLATE, odd_even, bitflip); - strcpy(state_files_path, get_my_executable_directory()); - strcat(state_files_path, STATE_FILES_DIRECTORY); + strcpy(state_files_path, STATE_FILES_DIRECTORY); strcat(state_files_path, state_file_name); - FILE *statesfile = fopen(state_files_path, "rb"); + char *path; + if (searchFile(&path, RESOURCES_SUBDIR, state_files_path, "", true) != PM3_SUCCESS) { + continue; + } + + FILE *statesfile = fopen(path, "rb"); + free(path); if (statesfile == NULL) { continue; } else { @@ -1379,7 +1385,7 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ flags |= field_off ? 0x0004 : 0; clearCommandBuffer(); - SendCommandMIX(CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, flags, key, 6); + SendCommandMIX(CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, flags, key, 6); if (field_off) break; @@ -1388,7 +1394,7 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ uint8_t nullkey[6] = {0}; //strange second call (iceman) clearCommandBuffer(); - SendCommandMIX(CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, 4, nullkey, sizeof(nullkey)); + SendCommandMIX(CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, 4, nullkey, sizeof(nullkey)); return 1; } if (resp.oldarg[0]) return resp.oldarg[0]; // error during nested_hard diff --git a/client/cmdhfmfhard.h b/client/cmdhfmfhard.h index 2f20986e2..d86a2005a 100644 --- a/client/cmdhfmfhard.h +++ b/client/cmdhfmfhard.h @@ -11,8 +11,7 @@ #ifndef CMDHFMFHARD_H__ #define CMDHFMFHARD_H__ -#include -#include +#include "common.h" #define NUM_SUMS 19 // number of possible sum property values diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index fb1118b81..58eb5db1a 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -11,23 +11,20 @@ #include "cmdhfmfp.h" -#include #include -#include -#include -#include + +#include "cmdparser.h" // command_t +#include "commonutil.h" // ARRAYLEN + #include "comms.h" -#include "cmdmain.h" -#include "util.h" #include "ui.h" #include "cmdhf14a.h" -#include "mifare.h" #include "mifare/mifare4.h" #include "mifare/mad.h" #include "mifare/ndef.h" #include "cliparser/cliparser.h" -#include "crypto/libpcrypto.h" #include "emv/dump.h" +#include "mifare/mifaredefault.h" static const uint8_t DefaultKey[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; @@ -42,7 +39,7 @@ static int CmdHFMFPInfo(const char *cmd) { infoHF14A(false, false); // Mifare Plus info - SendCommandMIX(CMD_READER_ISO_14443a, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); PacketResponseNG resp; WaitForResponse(CMD_ACK, &resp); @@ -89,7 +86,7 @@ static int CmdHFMFPInfo(const char *cmd) { // check SL0 uint8_t data[250] = {0}; int datalen = 0; - // https://github.com/Proxmark/proxmark3/blob/master/client/scripts/mifarePlus.lua#L161 + // https://github.com/Proxmark/proxmark3/blob/master/client/luascripts/mifarePlus.lua#L161 uint8_t cmd[3 + 16] = {0xa8, 0x90, 0x90, 0x00}; int res = ExchangeRAW14a(cmd, sizeof(cmd), false, false, data, sizeof(data), &datalen); if (!res && datalen > 1 && data[0] == 0x09) { @@ -227,7 +224,7 @@ static int CmdHFMFPInitPerso(const char *cmd) { } mfpSetVerboseMode(verbose); - for (int i = 0; i < sizeof(CardAddresses) / 2; i++) { + for (int i = 0; i < ARRAYLEN(CardAddresses); i++) { keyNum[0] = CardAddresses[i] >> 8; keyNum[1] = CardAddresses[i] & 0xff; res = MFPWritePerso(keyNum, key, false, true, data, sizeof(data), &datalen); diff --git a/client/cmdhfmfp.h b/client/cmdhfmfp.h index 76917315b..6ba2af504 100644 --- a/client/cmdhfmfp.h +++ b/client/cmdhfmfp.h @@ -10,7 +10,7 @@ #ifndef CMDHFMFP_H__ #define CMDHFMFP_H__ -#include "mifare/mifaredefault.h" +#include "common.h" int CmdHFMFP(const char *Cmd); diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index df760f187..7c81ebfd6 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -9,6 +9,18 @@ //----------------------------------------------------------------------------- #include "cmdhfmfu.h" +#include + +#include "cmdparser.h" +#include "commonutil.h" +#include "crypto/libpcrypto.h" +#include "mbedtls/des.h" +#include "cmdhfmf.h" +#include "cmdhf14a.h" +#include "comms.h" +#include "fileutils.h" +#include "protocols.h" + #define MAX_UL_BLOCKS 0x0F #define MAX_ULC_BLOCKS 0x2B #define MAX_ULEV1a_BLOCKS 0x13 @@ -19,6 +31,7 @@ #define MAX_NTAG_213 0x2C #define MAX_NTAG_215 0x86 #define MAX_NTAG_216 0xE6 +#define MAX_NTAG_I2C_1K 0xE9 #define MAX_MY_D_NFC 0xFF #define MAX_MY_D_MOVE 0x25 #define MAX_MY_D_MOVE_LEAN 0x0F @@ -42,7 +55,7 @@ static int usage_hf_mfu_info(void) { PrintAndLogEx(NORMAL, " hf mfu info"); PrintAndLogEx(NORMAL, " hf mfu info k 00112233445566778899AABBCCDDEEFF"); PrintAndLogEx(NORMAL, " hf mfu info k AABBCCDD"); - return 0; + return PM3_SUCCESS; } static int usage_hf_mfu_dump(void) { @@ -63,7 +76,7 @@ static int usage_hf_mfu_dump(void) { PrintAndLogEx(NORMAL, " hf mfu dump n myfile"); PrintAndLogEx(NORMAL, " hf mfu dump k 00112233445566778899AABBCCDDEEFF"); PrintAndLogEx(NORMAL, " hf mfu dump k AABBCCDD\n"); - return 0; + return PM3_SUCCESS; } static int usage_hf_mfu_restore(void) { @@ -81,7 +94,7 @@ static int usage_hf_mfu_restore(void) { PrintAndLogEx(NORMAL, " hf mfu restore s f myfile"); PrintAndLogEx(NORMAL, " hf mfu restore k AABBCCDD s f myfile\n"); PrintAndLogEx(NORMAL, " hf mfu restore k AABBCCDD s e r f myfile\n"); - return 0; + return PM3_SUCCESS; } static int usage_hf_mfu_rdbl(void) { @@ -96,7 +109,7 @@ static int usage_hf_mfu_rdbl(void) { PrintAndLogEx(NORMAL, " hf mfu rdbl b 0"); PrintAndLogEx(NORMAL, " hf mfu rdbl b 0 k 00112233445566778899AABBCCDDEEFF"); PrintAndLogEx(NORMAL, " hf mfu rdbl b 0 k AABBCCDD\n"); - return 0; + return PM3_SUCCESS; } static int usage_hf_mfu_wrbl(void) { @@ -111,7 +124,7 @@ static int usage_hf_mfu_wrbl(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mfu wrbl b 0 d 01234567"); PrintAndLogEx(NORMAL, " hf mfu wrbl b 0 d 01234567 k AABBCCDD\n"); - return 0; + return PM3_SUCCESS; } static int usage_hf_mfu_eload(void) { @@ -126,7 +139,7 @@ static int usage_hf_mfu_eload(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " sample: hf mfu eload u filename"); PrintAndLogEx(NORMAL, " hf mfu eload u filename 57"); - return 0; + return PM3_SUCCESS; } static int usage_hf_mfu_sim(void) { @@ -141,8 +154,7 @@ static int usage_hf_mfu_sim(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mfu sim t 7"); PrintAndLogEx(NORMAL, " hf mfu sim t 7 u 1122344556677\n"); - - return 0; + return PM3_SUCCESS; } static int usage_hf_mfu_ucauth(void) { @@ -157,7 +169,7 @@ static int usage_hf_mfu_ucauth(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mfu cauth k"); PrintAndLogEx(NORMAL, " hf mfu cauth k 3"); - return 0; + return PM3_SUCCESS; } static int usage_hf_mfu_ucsetpwd(void) { @@ -167,7 +179,7 @@ static int usage_hf_mfu_ucsetpwd(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mfu setpwd 000102030405060708090a0b0c0d0e0f"); PrintAndLogEx(NORMAL, ""); - return 0; + return PM3_SUCCESS; } static int usage_hf_mfu_ucsetuid(void) { @@ -178,7 +190,7 @@ static int usage_hf_mfu_ucsetuid(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mfu setuid 11223344556677"); PrintAndLogEx(NORMAL, ""); - return 0; + return PM3_SUCCESS; } static int usage_hf_mfu_gendiverse(void) { @@ -191,7 +203,7 @@ static int usage_hf_mfu_gendiverse(void) { PrintAndLogEx(NORMAL, " hf mfu gen r"); PrintAndLogEx(NORMAL, " hf mfu gen 11223344"); PrintAndLogEx(NORMAL, ""); - return 0; + return PM3_SUCCESS; } static int usage_hf_mfu_pwdgen(void) { @@ -206,20 +218,11 @@ static int usage_hf_mfu_pwdgen(void) { PrintAndLogEx(NORMAL, " hf mfu pwdgen 11223344556677"); PrintAndLogEx(NORMAL, " hf mfu pwdgen t"); PrintAndLogEx(NORMAL, ""); - return 0; + return PM3_SUCCESS; } -#define PUBLIC_ECDA_KEYLEN 33 -uint8_t public_ecda_key[PUBLIC_ECDA_KEYLEN] = { - 0x04, 0x49, 0x4e, 0x1a, 0x38, 0x6d, 0x3d, 0x3c, - 0xfe, 0x3d, 0xc1, 0x0e, 0x5d, 0xe6, 0x8a, 0x49, - 0x9b, 0x1c, 0x20, 0x2d, 0xb5, 0xb1, 0x32, 0x39, - 0x3e, 0x89, 0xed, 0x19, 0xfe, 0x5b, 0xe8, 0xbc, - 0x61 -}; -#define KEYS_3DES_COUNT 7 -uint8_t default_3des_keys[KEYS_3DES_COUNT][16] = { +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 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, // 0x00-0x0F @@ -229,24 +232,45 @@ uint8_t default_3des_keys[KEYS_3DES_COUNT][16] = { { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF } // 11 22 33 }; -#define KEYS_PWD_COUNT 1 -uint8_t default_pwd_pack[KEYS_PWD_COUNT][4] = { +uint8_t default_pwd_pack[][4] = { {0xFF, 0xFF, 0xFF, 0xFF}, // PACK 0x00,0x00 -- factory default }; -#define MAX_UL_TYPES 22 -uint32_t UL_TYPES_ARRAY[MAX_UL_TYPES] = { +#define PUBLIC_ECDA_KEYLEN 33 + +// known public keys for the originality check (source: https://github.com/alexbatalov/node-nxp-originality-verifier) +// ref: AN11350 NTAG 21x Originality Signature Validation +// ref: AN11341 MIFARE Ultralight EV1 Originality Signature Validation +uint8_t public_keys[2][PUBLIC_ECDA_KEYLEN] = { + // UL, NTAG21x and NDEF + { + 0x04, 0x49, 0x4e, 0x1a, 0x38, 0x6d, 0x3d, 0x3c, + 0xfe, 0x3d, 0xc1, 0x0e, 0x5d, 0xe6, 0x8a, 0x49, + 0x9b, 0x1c, 0x20, 0x2d, 0xb5, 0xb1, 0x32, 0x39, + 0x3e, 0x89, 0xed, 0x19, 0xfe, 0x5b, 0xe8, 0xbc, 0x61 + }, + // UL EV1 + { + 0x04, 0x90, 0x93, 0x3b, 0xdc, 0xd6, 0xe9, 0x9b, + 0x4e, 0x25, 0x5e, 0x3d, 0xa5, 0x53, 0x89, 0xa8, + 0x27, 0x56, 0x4e, 0x11, 0x71, 0x8e, 0x01, 0x72, + 0x92, 0xfa, 0xf2, 0x32, 0x26, 0xa9, 0x66, 0x14, 0xb8 + } +}; + + +uint32_t UL_TYPES_ARRAY[] = { UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128, NTAG, NTAG_203, NTAG_210, NTAG_212, NTAG_213, NTAG_215, NTAG_216, MY_D, MY_D_NFC, MY_D_MOVE, MY_D_MOVE_NFC, MY_D_MOVE_LEAN, FUDAN_UL, - UL_EV1, NTAG_213_F, NTAG_216_F, UL_NANO_40 + UL_EV1, NTAG_213_F, NTAG_216_F, UL_NANO_40, NTAG_I2C_1K }; -uint8_t UL_MEMORY_ARRAY[MAX_UL_TYPES] = { +uint8_t UL_MEMORY_ARRAY[ARRAYLEN(UL_TYPES_ARRAY)] = { MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_ULC_BLOCKS, MAX_ULEV1a_BLOCKS, MAX_ULEV1b_BLOCKS, MAX_NTAG_203, MAX_NTAG_203, MAX_NTAG_210, MAX_NTAG_212, MAX_NTAG_213, MAX_NTAG_215, MAX_NTAG_216, MAX_UL_BLOCKS, MAX_MY_D_NFC, MAX_MY_D_MOVE, MAX_MY_D_MOVE, MAX_MY_D_MOVE_LEAN, MAX_UL_BLOCKS, - MAX_ULEV1a_BLOCKS, MAX_NTAG_213, MAX_NTAG_216, MAX_UL_NANO_40 + MAX_ULEV1a_BLOCKS, MAX_NTAG_213, MAX_NTAG_216, MAX_UL_NANO_40, MAX_NTAG_I2C_1K }; //------------------------------------ @@ -459,12 +483,12 @@ static char *getUlev1CardSizeStr(uint8_t fsize) { static void ul_switch_on_field(void) { clearCommandBuffer(); - SendCommandMIX(CMD_READER_ISO_14443a, ISO14A_CONNECT | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0); } static int ul_send_cmd_raw(uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uint16_t responseLength) { clearCommandBuffer(); - SendCommandOLD(CMD_READER_ISO_14443a, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_APPEND_CRC | ISO14A_NO_RATS, cmdlen, 0, cmd, cmdlen); + SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_APPEND_CRC | ISO14A_NO_RATS, cmdlen, 0, cmd, cmdlen); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1; if (!resp.oldarg[0] && responseLength) return -1; @@ -531,7 +555,7 @@ static int ulc_requestAuthentication(uint8_t *nonce, uint16_t nonceLength) { static int ulc_authentication(uint8_t *key, bool switch_off_field) { clearCommandBuffer(); - SendCommandOLD(CMD_MIFAREUC_AUTH, switch_off_field, 0, 0, key, 16); + SendCommandOLD(CMD_HF_MIFAREUC_AUTH, switch_off_field, 0, 0, key, 16); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return 0; if (resp.oldarg[0] == 1) return 1; @@ -555,20 +579,20 @@ static int ul_auth_select(iso14a_card_select_t *card, TagTypeUL_t tagtype, bool //will select card automatically and close connection on error if (!ulc_authentication(authkey, false)) { PrintAndLogEx(WARNING, "Authentication Failed UL-C"); - return 0; + return PM3_ESOFT; } } else { - if (!ul_select(card)) return 0; + if (!ul_select(card)) return PM3_ESOFT; if (hasAuthKey) { if (ulev1_requestAuthentication(authkey, pack, packSize) == -1) { DropField(); PrintAndLogEx(WARNING, "Authentication Failed UL-EV1/NTAG"); - return 0; + return PM3_ESOFT; } } } - return 1; + return PM3_SUCCESS; } static int ulev1_getVersion(uint8_t *response, uint16_t responseLength) { @@ -618,7 +642,7 @@ static int ul_fudan_check(void) { uint8_t cmd[4] = {0x30, 0x00, 0x02, 0xa7}; //wrong crc on purpose should be 0xa8 clearCommandBuffer(); - SendCommandOLD(CMD_READER_ISO_14443a, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, 4, 0, cmd, sizeof(cmd)); + SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, 4, 0, cmd, sizeof(cmd)); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return UL_ERROR; if (resp.oldarg[0] != 1) return UL_ERROR; @@ -642,25 +666,25 @@ static int ul_print_default(uint8_t *data) { if (uid[0] == 0x05 && ((uid[1] & 0xf0) >> 4) == 2) { // is infineon and 66RxxP uint8_t chip = (data[8] & 0xC7); // 11000111 mask, bit 3,4,5 RFU switch (chip) { - case 0xc2: + case 0xC2: PrintAndLogEx(NORMAL, " IC type : SLE 66R04P 770 Bytes"); break; //77 pages - case 0xc4: + case 0xC4: PrintAndLogEx(NORMAL, " IC type : SLE 66R16P 2560 Bytes"); break; //256 pages - case 0xc6: + case 0xC6: PrintAndLogEx(NORMAL, " IC type : SLE 66R32P 5120 Bytes"); break; //512 pages /2 sectors } } // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 - int crc0 = 0x88 ^ data[0] ^ data[1] ^ data[2]; + int crc0 = 0x88 ^ uid[0] ^ uid[1] ^ uid[2]; if (data[3] == crc0) PrintAndLogEx(NORMAL, " BCC0 : %02X, Ok", data[3]); else PrintAndLogEx(NORMAL, " BCC0 : %02X, crc should be %02X", data[3], crc0); - int crc1 = data[4] ^ data[5] ^ data[6] ^ data[7]; + int crc1 = uid[3] ^ uid[4] ^ uid[5] ^ uid[6]; if (data[8] == crc1) PrintAndLogEx(NORMAL, " BCC1 : %02X, Ok", data[8]); else @@ -678,13 +702,13 @@ static int ul_print_default(uint8_t *data) { sprint_bin(data + 12, 4) ); - return 0; + return PM3_SUCCESS; } static int ndef_print_CC(uint8_t *data) { // no NDEF message if (data[0] != 0xE1) - return -1; + return PM3_ESOFT; //NFC Forum Type 1,2,3,4 // @@ -763,7 +787,7 @@ static int ndef_print_CC(uint8_t *data) { PrintAndLogEx(NORMAL, " x - %02X : %s lock block", lb, (lb) ? "support" : "don\'t support"); PrintAndLogEx(NORMAL, " xx - %02X : RFU (%s)", mlrule, (mlrule == 0) ? _GREEN_("OK") : _RED_("Fail")); PrintAndLogEx(NORMAL, " x - %02X : IC %s multiple block reads", mbread, (mbread) ? "support" : "don\'t support"); - return 0; + return PM3_SUCCESS; } int ul_print_type(uint32_t tagtype, uint8_t spaces) { @@ -802,13 +826,13 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces) { else if (tagtype & NTAG_216_F) PrintAndLogEx(NORMAL, "%sTYPE : NTAG 216F 888bytes (NT2H1611F0DTL)", spacer); else if (tagtype & NTAG_I2C_1K) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG I%sC 888bytes (NT3H1101FHK)", spacer, "\xFD"); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG I2C 888bytes (NT3H1101FHK)", spacer); else if (tagtype & NTAG_I2C_2K) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG I%sC 1904bytes (NT3H1201FHK)", spacer, "\xFD"); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG I2C 1904bytes (NT3H1201FHK)", spacer); else if (tagtype & NTAG_I2C_1K_PLUS) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG I%sC plus 888bytes (NT3H2111FHK)", spacer, "\xFD"); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG I2C plus 888bytes (NT3H2111FHK)", spacer); else if (tagtype & NTAG_I2C_2K_PLUS) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG I%sC plus 1912bytes (NT3H2211FHK)", spacer, "\xFD"); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG I2C plus 1912bytes (NT3H2211FHK)", spacer); else if (tagtype & MY_D) PrintAndLogEx(NORMAL, "%sTYPE : INFINEON my-d\x99 (SLE 66RxxS)", spacer); else if (tagtype & MY_D_NFC) @@ -823,7 +847,7 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces) { PrintAndLogEx(NORMAL, "%sTYPE : FUDAN Ultralight Compatible (or other compatible) %s", spacer, (tagtype & MAGIC) ? "" : ""); else PrintAndLogEx(NORMAL, "%sTYPE : Unknown %06x", spacer, tagtype); - return 0; + return PM3_SUCCESS; } static int ulc_print_3deskey(uint8_t *data) { @@ -832,7 +856,7 @@ static int ulc_print_3deskey(uint8_t *data) { PrintAndLogEx(NORMAL, " deskey2 [46/0x2E] : %s [s]", sprint_hex(data + 8, 4), sprint_ascii(data + 8, 4)); PrintAndLogEx(NORMAL, " deskey2 [47/0x2F] : %s [s]", sprint_hex(data + 12, 4), sprint_ascii(data + 12, 4)); PrintAndLogEx(NORMAL, "\n 3des key : %s", sprint_hex(SwapEndian64(data, 16, 8), 16)); - return 0; + return PM3_SUCCESS; } static int ulc_print_configuration(uint8_t *data) { @@ -855,7 +879,7 @@ static int ulc_print_configuration(uint8_t *data) { sprint_hex(data + 12, 4), (data[12] & 1) ? "write access restricted" : "read and write access restricted" ); - return 0; + return PM3_SUCCESS; } static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t startPage) { @@ -961,7 +985,7 @@ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t st PrintAndLogEx(NORMAL, " PWD [%u/0x%02X] : %s- (cannot be read)", startPage + 2, startPage + 2, sprint_hex(data + 8, 4)); PrintAndLogEx(NORMAL, " PACK [%u/0x%02X] : %s - (cannot be read)", startPage + 3, startPage + 3, sprint_hex(data + 12, 2)); PrintAndLogEx(NORMAL, " RFU [%u/0x%02X] : %s- (cannot be read)", startPage + 3, startPage + 3, sprint_hex(data + 14, 2)); - return 0; + return PM3_SUCCESS; } static int ulev1_print_counters() { @@ -980,16 +1004,21 @@ static int ulev1_print_counters() { return len; } -static int ulev1_print_signature(uint8_t *data, uint8_t len) { +static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *signature, size_t signature_len) { + uint8_t public_key = 0; + if (tagtype == UL_EV1_48 || tagtype == UL_EV1_128) { + public_key = 1; + } + int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, public_keys[public_key], uid, 7, signature, signature_len, false); + bool is_valid = (res == 0); + PrintAndLogEx(NORMAL, "\n--- Tag Signature"); PrintAndLogEx(NORMAL, "IC signature public key name : NXP NTAG21x (2013)"); - PrintAndLogEx(NORMAL, "IC signature public key value : %s", sprint_hex(public_ecda_key, PUBLIC_ECDA_KEYLEN)); - PrintAndLogEx(NORMAL, " Elliptic curve parameters : secp128r1"); - PrintAndLogEx(NORMAL, " Tag ECC Signature : %s", sprint_hex(data, len)); - //to do: verify if signature is valid - // only UID is signed. - //PrintAndLogEx(NORMAL, "IC signature status: %s valid", (iseccvalid() )?"":"not"); - return 0; + PrintAndLogEx(NORMAL, "IC signature public key value : %s", sprint_hex(public_keys[public_key], PUBLIC_ECDA_KEYLEN)); + PrintAndLogEx(NORMAL, " Elliptic curve parameters : NID_secp128r1"); + PrintAndLogEx(NORMAL, " TAG IC Signature : %s", sprint_hex(signature, signature_len)); + PrintAndLogEx(NORMAL, "Signature verified %s", (is_valid) ? _GREEN_("successful") : _RED_("failed")); + return PM3_SUCCESS; } static int ulev1_print_version(uint8_t *data) { @@ -1002,7 +1031,7 @@ static int ulev1_print_version(uint8_t *data) { PrintAndLogEx(NORMAL, " Minor version : %02X", data[5]); PrintAndLogEx(NORMAL, " Size : %s", getUlev1CardSizeStr(data[6])); PrintAndLogEx(NORMAL, " Protocol type : %02X %s", data[7], (data[7] == 0x3) ? "(ISO14443-3 Compliant)" : ""); - return 0; + return PM3_SUCCESS; } /* @@ -1185,6 +1214,8 @@ static int CmdHF14AMfUInfo(const char *Cmd) { uint8_t *key = pwd; uint8_t pack[4] = {0, 0, 0, 0}; int len; + uint8_t uid[7]; + char tempStr[50]; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { @@ -1217,7 +1248,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { if (errors) return usage_hf_mfu_info(); TagTypeUL_t tagtype = GetHF14AMfU_Type(); - if (tagtype == UL_ERROR) return -1; + if (tagtype == UL_ERROR) return PM3_ESOFT; PrintAndLogEx(NORMAL, "\n--- Tag Information ---------"); PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); @@ -1226,15 +1257,17 @@ static int CmdHF14AMfUInfo(const char *Cmd) { // Swap endianness if (swapEndian && hasAuthKey) authkeyptr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4); - if (!ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; + if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; // read pages 0,1,2,3 (should read 4pages) status = ul_read(0, data, sizeof(data)); if (status == -1) { DropField(); PrintAndLogEx(ERR, "Error: tag didn't answer to READ"); - return status; + return PM3_ESOFT; } else if (status == 16) { + memcpy(uid, data, 3); + memcpy(uid + 3, data + 4, 4); ul_print_default(data); ndef_print_CC(data + 12); } else { @@ -1250,7 +1283,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { if (status == -1) { PrintAndLogEx(ERR, "Error: tag didn't answer to READ UL-C"); DropField(); - return status; + return PM3_ESOFT; } if (status == 16) ulc_print_configuration(ulc_conf); @@ -1264,28 +1297,28 @@ static int CmdHF14AMfUInfo(const char *Cmd) { if (status == -1) { DropField(); PrintAndLogEx(ERR, "Error: tag didn't answer to READ magic"); - return status; + return PM3_ESOFT; } if (status == 16) ulc_print_3deskey(ulc_deskey); } else { DropField(); // if we called info with key, just return - if (hasAuthKey) return 1; + if (hasAuthKey) return PM3_SUCCESS; // also try to diversify default keys.. look into CmdHF14AMfGenDiverseKeys PrintAndLogEx(INFO, "Trying some default 3des keys"); - for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i) { + for (uint8_t i = 0; i < ARRAYLEN(default_3des_keys); ++i) { key = default_3des_keys[i]; if (ulc_authentication(key, true)) { PrintAndLogEx(SUCCESS, "Found default 3des key: "); uint8_t keySwap[16]; memcpy(keySwap, SwapEndian64(key, 16, 8), 16); ulc_print_3deskey(keySwap); - return 1; + return PM3_SUCCESS; } } - return 1; + return PM3_SUCCESS; } } @@ -1295,7 +1328,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { if ((tagtype & (UL_EV1_48 | UL_EV1_128 | UL_EV1))) { if (ulev1_print_counters() != 3) { // failed - re-select - if (!ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; + if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; } } @@ -1308,12 +1341,13 @@ static int CmdHF14AMfUInfo(const char *Cmd) { if (status == -1) { PrintAndLogEx(ERR, "Error: tag didn't answer to READ SIGNATURE"); DropField(); - return status; + return PM3_ESOFT; } - if (status == 32) ulev1_print_signature(ulev1_signature, sizeof(ulev1_signature)); - else { + if (status == 32) { + ulev1_print_signature(tagtype, uid, ulev1_signature, sizeof(ulev1_signature)); + } else { // re-select - if (!ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; + if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; } } @@ -1324,19 +1358,19 @@ static int CmdHF14AMfUInfo(const char *Cmd) { if (status == -1) { PrintAndLogEx(ERR, "Error: tag didn't answer to GETVERSION"); DropField(); - return status; + return PM3_ESOFT; } else if (status == 10) { ulev1_print_version(version); } else { locked = true; - if (!ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; + if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; } uint8_t startconfigblock = 0; uint8_t ulev1_conf[16] = {0x00}; // config blocks always are last 4 pages - for (uint8_t i = 0; i < MAX_UL_TYPES; i++) { + for (uint8_t i = 0; i < ARRAYLEN(UL_TYPES_ARRAY); i++) { if (tagtype & UL_TYPES_ARRAY[i]) { startconfigblock = UL_MEMORY_ARRAY[i] - 3; break; @@ -1348,7 +1382,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { if (status == -1) { PrintAndLogEx(ERR, "Error: tag didn't answer to READ EV1"); DropField(); - return status; + return PM3_ESOFT; } else if (status == 16) { // save AUTHENTICATION LIMITS for later: authlim = (ulev1_conf[4] & 0x07); @@ -1375,7 +1409,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { goto out; } - if (!ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; + if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; // test pwd gen B num_to_bytes(ul_ev1_pwdgenB(card.uid), 4, key); @@ -1385,7 +1419,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { goto out; } - if (!ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; + if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; // test pwd gen C num_to_bytes(ul_ev1_pwdgenC(card.uid), 4, key); @@ -1395,7 +1429,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { goto out; } - if (!ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; + if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; // test pwd gen D num_to_bytes(ul_ev1_pwdgenD(card.uid), 4, key); @@ -1405,16 +1439,16 @@ static int CmdHF14AMfUInfo(const char *Cmd) { goto out; } - if (!ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; + if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; - for (uint8_t i = 0; i < KEYS_PWD_COUNT; ++i) { + for (uint8_t i = 0; i < ARRAYLEN(default_pwd_pack); ++i) { key = default_pwd_pack[i]; len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { PrintAndLogEx(SUCCESS, "Found a default password: %s || Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); break; } else { - if (!ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; + if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; } } if (len < 1) PrintAndLogEx(WARNING, "password not known"); @@ -1424,7 +1458,7 @@ out: DropField(); if (locked) PrintAndLogEx(FAILED, "\nTag appears to be locked, try using the key to get more info"); PrintAndLogEx(NORMAL, ""); - return 1; + return PM3_SUCCESS; } // @@ -1504,7 +1538,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { if (tagtype == UL_ERROR) return -1; uint8_t maxblockno = 0; - for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++) { + for (uint8_t idx = 0; idx < ARRAYLEN(UL_TYPES_ARRAY); idx++) { if (tagtype & UL_TYPES_ARRAY[idx]) { maxblockno = UL_MEMORY_ARRAY[idx]; break; @@ -1540,7 +1574,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { } clearCommandBuffer(); - SendCommandOLD(CMD_MIFAREU_WRITEBL, blockNo, keytype, 0, cmddata, datalen); + SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, blockNo, keytype, 0, cmddata, datalen); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { uint8_t isOK = resp.oldarg[0] & 0xff; @@ -1618,7 +1652,7 @@ static int CmdHF14AMfURdBl(const char *Cmd) { if (tagtype == UL_ERROR) return -1; uint8_t maxblockno = 0; - for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++) { + for (uint8_t idx = 0; idx < ARRAYLEN(UL_TYPES_ARRAY); idx++) { if (tagtype & UL_TYPES_ARRAY[idx]) { maxblockno = UL_MEMORY_ARRAY[idx]; break; @@ -1645,7 +1679,7 @@ static int CmdHF14AMfURdBl(const char *Cmd) { } clearCommandBuffer(); - SendCommandOLD(CMD_MIFAREU_READBL, blockNo, keytype, 0, authKeyPtr, datalen); + SendCommandOLD(CMD_HF_MIFAREU_READBL, blockNo, keytype, 0, authKeyPtr, datalen); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { uint8_t isOK = resp.oldarg[0] & 0xff; @@ -1892,7 +1926,7 @@ static int CmdHF14AMfUDump(const char *Cmd) { //get number of pages to read if (!manualPages) { - for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++) { + for (uint8_t idx = 0; idx < ARRAYLEN(UL_TYPES_ARRAY); idx++) { if (tagtype & UL_TYPES_ARRAY[idx]) { //add one as maxblks starts at 0 card_mem_size = pages = UL_MEMORY_ARRAY[idx] + 1; @@ -1911,7 +1945,7 @@ static int CmdHF14AMfUDump(const char *Cmd) { } clearCommandBuffer(); - SendCommandOLD(CMD_MIFAREU_READCARD, startPage, pages, keytype, authKeyPtr, dataLen); + SendCommandOLD(CMD_HF_MIFAREU_READCARD, startPage, pages, keytype, authKeyPtr, dataLen); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { @@ -2157,7 +2191,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { // convert old format to new format, if need int res = convertOldMfuDump(&dump, &bytes_read); - if (res) { + if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Failed convert on load to new Ultralight/NTAG format"); free(dump); return res; @@ -2213,7 +2247,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { PrintAndLogEx(NORMAL, "special PWD block written 0x%X - %s\n", MFU_NTAG_SPECIAL_PWD, sprint_hex(data, 4)); clearCommandBuffer(); - SendCommandOLD(CMD_MIFAREU_WRITEBL, MFU_NTAG_SPECIAL_PWD, keytype, 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, MFU_NTAG_SPECIAL_PWD, keytype, 0, data, sizeof(data)); wait4response(MFU_NTAG_SPECIAL_PWD); @@ -2229,7 +2263,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { data[3] = 0; PrintAndLogEx(NORMAL, "special PACK block written 0x%X - %s\n", MFU_NTAG_SPECIAL_PACK, sprint_hex(data, 4)); clearCommandBuffer(); - SendCommandOLD(CMD_MIFAREU_WRITEBL, MFU_NTAG_SPECIAL_PACK, keytype, 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, MFU_NTAG_SPECIAL_PACK, keytype, 0, data, sizeof(data)); wait4response(MFU_NTAG_SPECIAL_PACK); // Signature @@ -2237,7 +2271,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { memcpy(data, mem->signature + i, 4); PrintAndLogEx(NORMAL, "special SIG block written 0x%X - %s\n", s, sprint_hex(data, 4)); clearCommandBuffer(); - SendCommandOLD(CMD_MIFAREU_WRITEBL, s, keytype, 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, s, keytype, 0, data, sizeof(data)); wait4response(s); } @@ -2246,7 +2280,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { memcpy(data, mem->version + i, 4); PrintAndLogEx(NORMAL, "special VERSION block written 0x%X - %s\n", s, sprint_hex(data, 4)); clearCommandBuffer(); - SendCommandOLD(CMD_MIFAREU_WRITEBL, s, keytype, 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, s, keytype, 0, data, sizeof(data)); wait4response(s); } } @@ -2260,7 +2294,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { //Send write Block memcpy(data, mem->data + (b * 4), 4); clearCommandBuffer(); - SendCommandOLD(CMD_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data)); wait4response(b); printf("."); fflush(stdout); @@ -2276,11 +2310,11 @@ static int CmdHF14AMfURestore(const char *Cmd) { // otp, uid, lock, cfg1, cfg0, dynlockbits uint8_t blocks[] = {3, 0, 1, 2, pages - 5, pages - 4, pages - 3}; - for (uint8_t i = 0; i < sizeof(blocks); i++) { + for (uint8_t i = 0; i < ARRAYLEN(blocks); i++) { uint8_t b = blocks[i]; memcpy(data, mem->data + (b * 4), 4); clearCommandBuffer(); - SendCommandOLD(CMD_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data)); wait4response(b); PrintAndLogEx(NORMAL, "special block written %u - %s\n", b, sprint_hex(data, 4)); } @@ -2325,7 +2359,7 @@ static int CmdHF14AMfUCAuth(const char *Cmd) { //Change key to user defined one if (cmdp == 'k') { keyNo = param_get8(Cmd, 1); - if (keyNo >= KEYS_3DES_COUNT) + if (keyNo >= ARRAYLEN(default_3des_keys)) errors = true; } @@ -2455,7 +2489,7 @@ static int CmdHF14AMfUCSetPwd(const char *Cmd) { } clearCommandBuffer(); - SendCommandOLD(CMD_MIFAREUC_SETPWD, 0, 0, 0, pwd, 16); + SendCommandOLD(CMD_HF_MIFAREUC_SETPWD, 0, 0, 0, pwd, 16); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { @@ -2485,15 +2519,15 @@ static int CmdHF14AMfUCSetUid(const char *Cmd) { if (param_gethex(Cmd, 0, uid, 14)) { PrintAndLogEx(WARNING, "UID must include 14 HEX symbols"); - return 1; + return PM3_EINVARG; } // read block2. clearCommandBuffer(); - SendCommandMIX(CMD_MIFAREU_READBL, 2, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_MIFAREU_READBL, 2, 0, 0, NULL, 0); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(WARNING, "Command execute timeout"); - return 2; + return PM3_ETIMEOUT; } // save old block2. @@ -2507,10 +2541,10 @@ static int CmdHF14AMfUCSetUid(const char *Cmd) { data[2] = uid[2]; data[3] = 0x88 ^ uid[0] ^ uid[1] ^ uid[2]; clearCommandBuffer(); - SendCommandOLD(CMD_MIFAREU_WRITEBL, 0, 0, 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, 0, 0, 0, data, sizeof(data)); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(WARNING, "Command execute timeout"); - return 3; + return PM3_ETIMEOUT; } // block 1. @@ -2519,10 +2553,10 @@ static int CmdHF14AMfUCSetUid(const char *Cmd) { data[2] = uid[5]; data[3] = uid[6]; clearCommandBuffer(); - SendCommandOLD(CMD_MIFAREU_WRITEBL, 1, 0, 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, 1, 0, 0, data, sizeof(data)); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(WARNING, "Command execute timeout"); - return 4; + return PM3_ETIMEOUT; } // block 2. @@ -2531,12 +2565,12 @@ static int CmdHF14AMfUCSetUid(const char *Cmd) { data[2] = oldblock2[2]; data[3] = oldblock2[3]; clearCommandBuffer(); - SendCommandOLD(CMD_MIFAREU_WRITEBL, 2, 0, 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, 2, 0, 0, data, sizeof(data)); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(WARNING, "Command execute timeout"); - return 5; + return PM3_ETIMEOUT; } - return 0; + return PM3_SUCCESS; } static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { @@ -2548,7 +2582,7 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { if (cmdp == 'r') { // read uid from tag clearCommandBuffer(); - SendCommandMIX(CMD_READER_ISO_14443a, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0); PacketResponseNG resp; WaitForResponse(CMD_ACK, &resp); iso14a_card_select_t card; @@ -2613,12 +2647,12 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { PrintAndLogEx(NORMAL, "Message :\t %s", sprint_hex(mix, sizeof(mix))); PrintAndLogEx(NORMAL, "Diversified key: %s", sprint_hex(divkey + 1, 6)); - for (int i = 0; i < sizeof(mifarekeyA); ++i) { + for (int i = 0; i < ARRAYLEN(mifarekeyA); ++i) { dkeyA[i] = (mifarekeyA[i] << 1) & 0xff; dkeyA[6] |= ((mifarekeyA[i] >> 7) & 1) << (i + 1); } - for (int i = 0; i < sizeof(mifarekeyB); ++i) { + for (int i = 0; i < ARRAYLEN(mifarekeyB); ++i) { dkeyB[1] |= ((mifarekeyB[i] >> 7) & 1) << (i + 1); dkeyB[2 + i] = (mifarekeyB[i] << 1) & 0xff; } @@ -2647,8 +2681,9 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { PrintAndLogEx(NORMAL, "Mifare ABA :\t %s", sprint_hex(dmkey, sizeof(dmkey))); PrintAndLogEx(NORMAL, "Mifare Pwd :\t %s", sprint_hex(newpwd, sizeof(newpwd))); + mbedtls_des3_free(&ctx); // next. from the diversify_key method. - return 0; + return PM3_SUCCESS; } static int CmdHF14AMfUPwdGen(const char *Cmd) { @@ -2662,7 +2697,7 @@ static int CmdHF14AMfUPwdGen(const char *Cmd) { if (cmdp == 'r') { // read uid from tag clearCommandBuffer(); - SendCommandMIX(CMD_READER_ISO_14443a, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0); PacketResponseNG resp; WaitForResponse(CMD_ACK, &resp); iso14a_card_select_t card; @@ -2675,11 +2710,11 @@ static int CmdHF14AMfUPwdGen(const char *Cmd) { // 3: proprietary Anticollision if (select_status == 0) { PrintAndLogEx(WARNING, "iso14443a card select failed"); - return 1; + return PM3_ESOFT; } if (card.uidlen != 7) { PrintAndLogEx(WARNING, "Wrong sized UID, expected 7bytes got %d", card.uidlen); - return 1; + return PM3_ESOFT; } memcpy(uid, card.uid, sizeof(uid)); } else { @@ -2698,7 +2733,7 @@ static int CmdHF14AMfUPwdGen(const char *Cmd) { PrintAndLogEx(NORMAL, "------+----------+-----"); PrintAndLogEx(NORMAL, " Vingcard algo"); PrintAndLogEx(NORMAL, "--------------------"); - return 0; + return PM3_SUCCESS; } //------------------------------------ // Menu Stuff @@ -2723,7 +2758,7 @@ static command_t CommandTable[] = { static int CmdHelp(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdsHelp(CommandTable); - return 0; + return PM3_SUCCESS; } int CmdHFMFUltra(const char *Cmd) { diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h index 6587cd538..85f6a8475 100644 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@ -1,17 +1,9 @@ #ifndef CMDHFMFU_H__ #define CMDHFMFU_H__ -#include -#include -#include "mbedtls/des.h" -#include "cmdhfmf.h" -#include "cmdhf14a.h" -#include "mifare.h" -#include "util.h" -#include "protocols.h" -#include "comms.h" -#include "loclass/fileutils.h" +#include "common.h" +#include "mifare.h" // structs // Old Ultralight/NTAG dump file format // It is used only for converting diff --git a/client/cmdhfthinfilm.c b/client/cmdhfthinfilm.c new file mode 100644 index 000000000..a32aa8f59 --- /dev/null +++ b/client/cmdhfthinfilm.c @@ -0,0 +1,248 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2019 iceman +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Thinfilm commands +//----------------------------------------------------------------------------- +#include "cmdhfthinfilm.h" + +#include +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "cmdtrace.h" +#include "crc16.h" +#include "ui.h" +#include "cmdhf14a.h" // manufacture + +static int CmdHelp(const char *Cmd); + +static int usage_thinfilm_info(void) { + PrintAndLogEx(NORMAL, "Usage: hf thinfilm info [h]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf thinfilm info"); + return PM3_SUCCESS; +} + +static int usage_thinfilm_sim(void) { + PrintAndLogEx(NORMAL, "Usage: hf thinfilm sim [h] [d ]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " d bytes to send, in hex"); + PrintAndLogEx(NORMAL, " r raw, provided bytes should include CRC"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf thinfilm sim d B70470726f786d61726b2e636f6d"); + return PM3_SUCCESS; +} + +// Printing function based upon the code in libnfc +// ref +// https://github.com/nfc-tools/libnfc/blob/master/utils/nfc-barcode.c +static int print_barcode(uint8_t *barcode, const size_t barcode_len, bool verbose) { + + // remove start bit + uint8_t mb = barcode[0] & ~0x80; + PrintAndLogEx(SUCCESS, " Manufacturer : "_YELLOW_("%s") "[0x%02X]", getTagInfo(mb), mb); + + if (verbose) { + PrintAndLogEx(SUCCESS, " Data format : "_YELLOW_("%02X"), barcode[1]); + if (barcode_len > 2) { + uint8_t b1, b2; + compute_crc(CRC_14443_A, barcode, barcode_len - 2, &b1, &b2); + bool isok = (barcode[barcode_len - 1] == b1 && barcode[barcode_len - 2] == b2); + + PrintAndLogEx(SUCCESS, " Checksum : "_YELLOW_("%02X %02X")"- %s", b2, b1, (isok) ? _GREEN_("OK") : _RED_("fail")); + } else { + PrintAndLogEx(SUCCESS, " Checksum : "_YELLOW_("too few data for checksum")"- " _RED_("fail")); + } + PrintAndLogEx(SUCCESS, " Data len (bits) : "_YELLOW_("%i")"- %s", barcode_len*8, (barcode_len==16||barcode_len==32) ? _GREEN_("OK") : _YELLOW_("warning")); + PrintAndLogEx(SUCCESS, " Raw data : "_YELLOW_("%s"), sprint_hex(barcode, barcode_len)); + if (barcode_len < 4) // too few to go to next decoding stages + return PM3_ESOFT; + } + + char s[45]; + memset(s, 0x00, sizeof(s)); + + switch (barcode[1]) { + case 0: + PrintAndLogEx(SUCCESS, " Data format : Reserved for allocation by tag manufacturer"); + return PM3_SUCCESS; + case 1: + snprintf(s, sizeof(s), "http://www."); + break; + case 2: + snprintf(s, sizeof(s), "https://www."); + break; + case 3: + snprintf(s, sizeof(s), "http://"); + break; + case 4: + snprintf(s, sizeof(s), "https://"); + break; + case 5: + if (barcode_len < 16) { + PrintAndLogEx(WARNING, "EPC: (partial data) %s", sprint_hex(barcode + 2, barcode_len - 2)); + return PM3_ESOFT; + } + PrintAndLogEx(SUCCESS, "EPC: %s", sprint_hex(barcode + 2, 12)); + return PM3_SUCCESS; + default: + PrintAndLogEx(SUCCESS, " Data format : RFU Reserved for future use (%02X)", barcode[1]); + if (!verbose) + PrintAndLogEx(SUCCESS, "Raw data with CRC: "_YELLOW_("%s"), sprint_hex(barcode, barcode_len)); + return PM3_SUCCESS; + } + + snprintf(s + strlen(s), barcode_len - 3, (const char *)&barcode[2], barcode_len - 4); + + for (uint8_t i = 0; i < strlen(s); i++) { + + // terminate string + if ((uint8_t) s[i] == 0xFE) { + s[i] = 0; + break; + } + } + PrintAndLogEx(SUCCESS, " Decoded NFC URL : "_YELLOW_("%s"), s); + return PM3_SUCCESS; +} + + +static int CmdHfThinFilmInfo(const char *Cmd) { + + uint8_t cmdp = 0; + bool errors = false; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_thinfilm_info(); + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + + //Validations + if (errors) { + usage_thinfilm_info(); + return PM3_EINVARG; + } + + return infoThinFilm(true); +} + +int infoThinFilm(bool verbose) { + + clearCommandBuffer(); + SendCommandNG(CMD_HF_THINFILM_READ, NULL, 0); + + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_HF_THINFILM_READ, &resp, 1500)) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + return PM3_ETIMEOUT; + } + + if (resp.status == PM3_SUCCESS) { + if (resp.length == 16 || resp.length == 32 || verbose) { + print_barcode(resp.data.asBytes, resp.length, verbose); + } else { + PrintAndLogEx(WARNING, "Response is wrong length. (%d)", resp.length); + return PM3_ESOFT; + } + } + + return resp.status; +} + +static int CmdHfThinFilmSim(const char *Cmd) { + uint8_t cmdp = 0; + uint8_t data[512]; + int datalen = 0; + + bool addcrc = true; + bool errors = false; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_thinfilm_sim(); + case 'd': + // Retrieve the data + param_gethex_ex(Cmd, cmdp + 1, data, &datalen); + datalen >>= 1; + cmdp += 2; + break; + case 'r': + addcrc = false; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + + //Validations + if (errors || cmdp == 0 || datalen == 0 || datalen > 512) return usage_thinfilm_sim(); + if (addcrc && datalen <= 510) { + uint8_t b1, b2; + compute_crc(CRC_14443_A, data, datalen, &b1, &b2); + data[datalen++] = b2; + data[datalen++] = b1; + } + + clearCommandBuffer(); + SendCommandNG(CMD_HF_THINFILM_SIMULATE, (uint8_t *)&data, datalen); + PacketResponseNG resp; + PrintAndLogEx(SUCCESS, "press pm3-button to abort simulation"); + + int ret; + while (!(ret = kbd_enter_pressed())) { + if (WaitForResponseTimeout(CMD_HF_THINFILM_SIMULATE, &resp, 500) == 0) continue; + if (resp.status != PM3_SUCCESS) break; + } + if (ret) { + PrintAndLogEx(INFO, "Client side interrupted"); + PrintAndLogEx(WARNING, "Simulation still running on Proxmark3 till next command or button press"); + } else { + PrintAndLogEx(INFO, "Done"); + } + return PM3_SUCCESS; +} + +static int CmdHfThinFilmList(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + CmdTraceList("thinfilm"); + return PM3_SUCCESS; +} + +static command_t CommandTable[] = { + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"info", CmdHfThinFilmInfo, IfPm3NfcBarcode, "Tag information"}, + {"list", CmdHfThinFilmList, AlwaysAvailable, "List NFC Barcode / Thinfilm history - not correct"}, + {"sim", CmdHfThinFilmSim, IfPm3NfcBarcode, "Fake Thinfilm tag"}, + {NULL, NULL, NULL, NULL} +}; + +static int CmdHelp(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + CmdsHelp(CommandTable); + return PM3_SUCCESS; +} + +int CmdHFThinfilm(const char *Cmd) { + clearCommandBuffer(); + return CmdsParse(CommandTable, Cmd); +} diff --git a/armsrc/Standalone/lf_icerun.h b/client/cmdhfthinfilm.h similarity index 65% rename from armsrc/Standalone/lf_icerun.h rename to client/cmdhfthinfilm.h index 50427320a..ce7534759 100644 --- a/armsrc/Standalone/lf_icerun.h +++ b/client/cmdhfthinfilm.h @@ -1,17 +1,20 @@ //----------------------------------------------------------------------------- -// Iceman, Christian Herrmann, 2019 +// Copyright (C) 2019 iceman // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// StandAlone Mod +// Thinfilm commands //----------------------------------------------------------------------------- -#ifndef __LF_ICERUN_H -#define __LF_ICERUN_H +#ifndef CMDHFTHINFILM_H__ +#define CMDHFTHINFILM_H__ -#include "standalone.h" // standalone definitions -#include "apps.h" // debugstatements, lfops? +#include "common.h" -#endif /* __LF_ICERUN_H */ +int infoThinFilm(bool verbose); + +int CmdHFThinfilm(const char *Cmd); + +#endif diff --git a/client/cmdhftopaz.c b/client/cmdhftopaz.c index d604d4baf..35b31d8ce 100644 --- a/client/cmdhftopaz.c +++ b/client/cmdhftopaz.c @@ -9,6 +9,20 @@ //----------------------------------------------------------------------------- #include "cmdhftopaz.h" +#include +#include +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "cmdtrace.h" + +#include "cmdhf14a.h" +#include "ui.h" +#include "crc16.h" +#include "protocols.h" + #define TOPAZ_STATIC_MEMORY (0x0f * 8) // 15 blocks with 8 Bytes each // a struct to describe a memory area which contains lock bits and the corresponding lockable memory area @@ -31,30 +45,41 @@ static struct { } topaz_tag; static void topaz_switch_on_field(void) { - SendCommandMIX(CMD_READER_ISO_14443a, ISO14A_CONNECT | ISO14A_NO_SELECT | ISO14A_NO_DISCONNECT | ISO14A_TOPAZMODE | ISO14A_NO_RATS, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_SELECT | ISO14A_NO_DISCONNECT | ISO14A_TOPAZMODE | ISO14A_NO_RATS, 0, 0, NULL, 0); } static void topaz_switch_off_field(void) { - SendCommandMIX(CMD_READER_ISO_14443a, 0, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443A_READER, 0, 0, 0, NULL, 0); } // send a raw topaz command, returns the length of the response (0 in case of error) -static int topaz_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response) { - SendCommandOLD(CMD_READER_ISO_14443a, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_TOPAZMODE | ISO14A_NO_RATS, len, 0, cmd, len); +static int topaz_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16_t *response_len, bool verbose) { + SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_TOPAZMODE | ISO14A_NO_RATS, len, 0, cmd, len); PacketResponseNG resp; - WaitForResponse(CMD_ACK, &resp); - if (resp.oldarg[0] > 0) { - memcpy(response, resp.data.asBytes, resp.oldarg[0]); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply."); + return PM3_ETIMEOUT; } - return resp.oldarg[0]; + if (resp.oldarg[0] == *response_len) { + *response_len = resp.oldarg[0]; + + PrintAndLogEx(INFO, "%s", sprint_hex(resp.data.asBytes, *response_len)); + if (*response_len > 0) { + memcpy(response, resp.data.asBytes, *response_len); + } + } else { + if (verbose) PrintAndLogEx(WARNING, "Wrong response length (%d != %d)", *response_len, resp.oldarg[0]); + return PM3_ESOFT; + } + return PM3_SUCCESS; } // calculate CRC bytes and send topaz command, returns the length of the response (0 in case of error) -static int topaz_send_cmd(uint8_t *cmd, uint8_t len, uint8_t *response) { +static int topaz_send_cmd(uint8_t *cmd, uint8_t len, uint8_t *response, uint16_t *response_len, bool verbose) { if (len > 1) { uint8_t b1, b2; compute_crc(CRC_14443_B, cmd, len - 2, &b1, &b2); @@ -62,75 +87,85 @@ static int topaz_send_cmd(uint8_t *cmd, uint8_t len, uint8_t *response) { cmd[len - 1] = b2; } - return topaz_send_cmd_raw(cmd, len, response); + return topaz_send_cmd_raw(cmd, len, response, response_len, verbose); } // select a topaz tag. Send WUPA and RID. -static int topaz_select(uint8_t *atqa, uint8_t *rid_response) { +static int topaz_select(uint8_t *atqa, uint8_t atqa_len, uint8_t *rid_response, uint8_t rid_len, bool verbose) { // ToDo: implement anticollision + uint16_t resp_len; uint8_t wupa_cmd[] = {TOPAZ_WUPA}; uint8_t rid_cmd[] = {TOPAZ_RID, 0, 0, 0, 0, 0, 0, 0, 0}; topaz_switch_on_field(); - if (!topaz_send_cmd(wupa_cmd, sizeof(wupa_cmd), atqa)) { + resp_len = atqa_len; + int status = topaz_send_cmd(wupa_cmd, sizeof(wupa_cmd), atqa, &resp_len, verbose); + if (status == PM3_ETIMEOUT || status == PM3_ESOFT) { topaz_switch_off_field(); - return -1; // WUPA failed + return PM3_ESOFT; // WUPA failed } - if (!topaz_send_cmd(rid_cmd, sizeof(rid_cmd), rid_response)) { + resp_len = rid_len; + status = topaz_send_cmd(rid_cmd, sizeof(rid_cmd), rid_response, &resp_len, verbose); + if (status == PM3_ETIMEOUT || status == PM3_ESOFT) { topaz_switch_off_field(); - return -2; // RID failed + return PM3_EWRONGANSVER; // RID failed } - return 0; // OK + return PM3_SUCCESS; } // read all of the static memory of a selected Topaz tag. static int topaz_rall(uint8_t *uid, uint8_t *response) { + uint16_t resp_len = 0; uint8_t rall_cmd[] = {TOPAZ_RALL, 0, 0, 0, 0, 0, 0, 0, 0}; - memcpy(&rall_cmd[3], uid, 4); - if (!topaz_send_cmd(rall_cmd, sizeof(rall_cmd), response)) { + + if (topaz_send_cmd(rall_cmd, sizeof(rall_cmd), response, &resp_len, true) == PM3_ETIMEOUT) { topaz_switch_off_field(); - return -1; // RALL failed + return PM3_ESOFT; // RALL failed } - return 0; + return PM3_SUCCESS; } // read a block (8 Bytes) of a selected Topaz tag. static int topaz_read_block(uint8_t *uid, uint8_t blockno, uint8_t *block_data) { + uint16_t resp_len = 0; uint8_t read8_cmd[] = {TOPAZ_READ8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t read8_response[11]; read8_cmd[1] = blockno; memcpy(&read8_cmd[10], uid, 4); - if (!topaz_send_cmd(read8_cmd, sizeof(read8_cmd), read8_response)) { + + if (topaz_send_cmd(read8_cmd, sizeof(read8_cmd), read8_response, &resp_len, true) == PM3_ETIMEOUT) { topaz_switch_off_field(); - return -1; // READ8 failed + return PM3_ESOFT; // READ8 failed } memcpy(block_data, &read8_response[1], 8); - return 0; + return PM3_SUCCESS; } // read a segment (16 blocks = 128 Bytes) of a selected Topaz tag. Works only for tags with dynamic memory. static int topaz_read_segment(uint8_t *uid, uint8_t segno, uint8_t *segment_data) { + uint16_t resp_len = 0; uint8_t rseg_cmd[] = {TOPAZ_RSEG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t rseg_response[131]; rseg_cmd[1] = segno << 4; memcpy(&rseg_cmd[10], uid, 4); - if (!topaz_send_cmd(rseg_cmd, sizeof(rseg_cmd), rseg_response)) { + + if (topaz_send_cmd(rseg_cmd, sizeof(rseg_cmd), rseg_response, &resp_len, true) == PM3_ETIMEOUT) { topaz_switch_off_field(); - return -1; // RSEG failed + return PM3_ESOFT; // RSEG failed } memcpy(segment_data, &rseg_response[1], 128); - return 0; + return PM3_SUCCESS; } // search for the lock area descriptor for the lockable area including byteno @@ -181,7 +216,7 @@ static bool topaz_byte_is_locked(uint16_t byteno) { static int topaz_print_CC(uint8_t *data) { if (data[0] != 0xe1) { topaz_tag.size = TOPAZ_STATIC_MEMORY; - return -1; // no NDEF message + return PM3_ESOFT; // no NDEF message } PrintAndLogEx(NORMAL, "Capability Container: %02x %02x %02x %02x", data[0], data[1], data[2], data[3]); @@ -194,7 +229,7 @@ static int topaz_print_CC(uint8_t *data) { PrintAndLogEx(NORMAL, " %02x: %s / %s", data[3], (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security", (data[3] & 0x0F) == 0 ? "Write access granted without any security" : (data[3] & 0x0F) == 0x0F ? "No write access granted at all" : "(RFU)"); - return 0; + return PM3_SUCCESS; } @@ -320,20 +355,20 @@ static void topaz_print_control_TLVs(uint8_t *memory) { // read all of the dynamic memory static int topaz_read_dynamic_data(void) { // first read the remaining block of segment 0 - if (topaz_read_block(topaz_tag.uid, 0x0f, &topaz_tag.dynamic_memory[0]) == -1) { - PrintAndLogEx(ERR, "Error while reading dynamic memory block %02x. Aborting...", 0x0f); - return -1; + if (topaz_read_block(topaz_tag.uid, 0x0F, &topaz_tag.dynamic_memory[0]) == PM3_ESOFT) { + PrintAndLogEx(ERR, "Error while reading dynamic memory block " _YELLOW_("%02x") ". Aborting...", 0x0F); + return PM3_ESOFT; } // read the remaining segments uint8_t max_segment = topaz_tag.size / 128 - 1; for (uint8_t segment = 1; segment <= max_segment; segment++) { - if (topaz_read_segment(topaz_tag.uid, segment, &topaz_tag.dynamic_memory[(segment - 1) * 128 + 8]) == -1) { - PrintAndLogEx(ERR, "Error while reading dynamic memory block %02x. Aborting...", 0x0f); - return -1; + if (topaz_read_segment(topaz_tag.uid, segment, &topaz_tag.dynamic_memory[(segment - 1) * 128 + 8]) == PM3_ESOFT) { + PrintAndLogEx(ERR, "Error while reading dynamic memory block " _YELLOW_("%02x") ". Aborting...", segment); + return PM3_ESOFT; } } - return 0; + return PM3_SUCCESS; } @@ -343,16 +378,17 @@ static void topaz_print_dynamic_data(void) { PrintAndLogEx(NORMAL, "Dynamic Data blocks:"); if (topaz_read_dynamic_data() == 0) { PrintAndLogEx(NORMAL, "block# | offset | Data | Locked(y/n)"); + PrintAndLogEx(NORMAL, "-------+--------+-------------------------+------------"); char line[80]; - for (uint16_t blockno = 0x0f; blockno < topaz_tag.size / 8; blockno++) { - uint8_t *block_data = &topaz_tag.dynamic_memory[(blockno - 0x0f) * 8]; + for (uint16_t blockno = 0x0F; blockno < topaz_tag.size / 8; blockno++) { + uint8_t *block_data = &topaz_tag.dynamic_memory[(blockno - 0x0F) * 8]; char lockbits[9]; for (uint16_t j = 0; j < 8; j++) { sprintf(&line[3 * j], "%02x ", block_data[j]); lockbits[j] = topaz_byte_is_locked(blockno * 8 + j) ? 'y' : 'n'; } lockbits[8] = '\0'; - PrintAndLogEx(NORMAL, " 0x%02x | 0x%04x | %s| %-3s", blockno, blockno * 8, line, lockbits); + PrintAndLogEx(NORMAL, " 0x%02x | 0x%04x | %s| %-3s", blockno, blockno * 8, line, lockbits); } } } @@ -375,45 +411,48 @@ static int CmdHFTopazReader(const char *Cmd) { uint8_t rall_response[124]; bool verbose = true; - char ctmp = param_getchar(Cmd, 0); - if (ctmp == 'S' || ctmp == 's') verbose = false; + char ctmp = tolower(param_getchar(Cmd, 0)); + if (ctmp == 's') verbose = false; - status = topaz_select(atqa, rid_response); + status = topaz_select(atqa, sizeof(atqa), rid_response, sizeof(rid_response), verbose); - if (status == -1) { + if (status == PM3_ESOFT) { if (verbose) PrintAndLogEx(ERR, "Error: couldn't receive ATQA"); - return -1; + return PM3_ESOFT; + } + + if (atqa[1] != 0x0c && atqa[0] != 0x00) { + if (verbose) PrintAndLogEx(ERR, "Tag doesn't support the Topaz protocol."); + topaz_switch_off_field(); + return PM3_ESOFT; + } + + if (status == PM3_EWRONGANSVER) { + if (verbose) PrintAndLogEx(ERR, "Error: tag didn't answer to RID"); + topaz_switch_off_field(); + return PM3_ESOFT; } PrintAndLogEx(NORMAL, "ATQA : %02x %02x", atqa[1], atqa[0]); - if (atqa[1] != 0x0c && atqa[0] != 0x00) { - PrintAndLogEx(NORMAL, "Tag doesn't support the Topaz protocol."); - topaz_switch_off_field(); - return -1; - } - - if (status == -2) { - PrintAndLogEx(ERR, "Error: tag didn't answer to RID"); - topaz_switch_off_field(); - return -1; - } topaz_tag.HR01[0] = rid_response[0]; topaz_tag.HR01[1] = rid_response[1]; // ToDo: CRC check - PrintAndLogEx(NORMAL, "HR0 : %02x (%sa Topaz tag (%scapable of carrying a NDEF message), %s memory map)", rid_response[0], + PrintAndLogEx(NORMAL, "HR0 : %02x (%sa Topaz tag (%scapable of carrying a NDEF message), %s memory map)", + rid_response[0], (rid_response[0] & 0xF0) == 0x10 ? "" : "not ", (rid_response[0] & 0xF0) == 0x10 ? "" : "not ", (rid_response[0] & 0x0F) == 0x01 ? "static" : "dynamic"); + PrintAndLogEx(NORMAL, "HR1 : %02x", rid_response[1]); status = topaz_rall(uid_echo, rall_response); - if (status == -1) { + if (status == PM3_ESOFT) { PrintAndLogEx(ERR, "Error: tag didn't answer to RALL"); topaz_switch_off_field(); - return -1; + return PM3_ESOFT; } memcpy(topaz_tag.uid, rall_response + 2, 7); @@ -426,14 +465,15 @@ static int CmdHFTopazReader(const char *Cmd) { topaz_tag.uid[1], topaz_tag.uid[0]); - PrintAndLogEx(NORMAL, " UID[6] (Manufacturer Byte) = %02x, Manufacturer: %s", + PrintAndLogEx(NORMAL, " UID[6] (Manufacturer Byte) = " _YELLOW_("%02x")", Manufacturer: " _YELLOW_("%s"), topaz_tag.uid[6], getTagInfo(topaz_tag.uid[6])); memcpy(topaz_tag.data_blocks, rall_response + 2, 0x0f * 8); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Static Data blocks 00 to 0c:"); + PrintAndLogEx(NORMAL, "Static Data blocks " _YELLOW_("0x00") "to " _YELLOW_("0x0C")":"); PrintAndLogEx(NORMAL, "block# | offset | Data | Locked"); + PrintAndLogEx(NORMAL, "-------+--------+-------------------------+------------"); char line[80]; for (uint16_t i = 0; i <= 0x0c; i++) { char lockbits[9]; @@ -442,31 +482,32 @@ static int CmdHFTopazReader(const char *Cmd) { lockbits[j] = topaz_byte_is_locked(i * 8 + j) ? 'y' : 'n'; } lockbits[8] = '\0'; - PrintAndLogEx(NORMAL, " 0x%02x | 0x%02x | %s| %-3s", i, i * 8, line, lockbits); + PrintAndLogEx(NORMAL, " 0x%02x | 0x%02x | %s| %-3s", i, i * 8, line, lockbits); } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Static Reserved block 0d:"); + PrintAndLogEx(NORMAL, "Static Reserved block " _YELLOW_("0x0D")":"); for (uint16_t j = 0; j < 8; j++) { sprintf(&line[3 * j], "%02x ", topaz_tag.data_blocks[0x0d][j]); } - PrintAndLogEx(NORMAL, " 0x%02x | 0x%02x | %s| %-3s", 0x0d, 0x0d * 8, line, "n/a"); - + PrintAndLogEx(NORMAL, "-------+--------+-------------------------+------------"); + PrintAndLogEx(NORMAL, " 0x%02x | 0x%02x | %s| %-3s", 0x0d, 0x0d * 8, line, "n/a"); PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Static Lockbits and OTP Bytes:"); for (uint16_t j = 0; j < 8; j++) { sprintf(&line[3 * j], "%02x ", topaz_tag.data_blocks[0x0e][j]); } - PrintAndLogEx(NORMAL, " 0x%02x | 0x%02x | %s| %-3s", 0x0e, 0x0e * 8, line, "n/a"); - + PrintAndLogEx(NORMAL, "-------+--------+-------------------------+------------"); + PrintAndLogEx(NORMAL, " 0x%02x | 0x%02x | %s| %-3s", 0x0e, 0x0e * 8, line, "n/a"); PrintAndLogEx(NORMAL, ""); status = topaz_print_CC(&topaz_tag.data_blocks[1][0]); - if (status == -1) { + if (status == PM3_ESOFT) { PrintAndLogEx(NORMAL, "No NDEF message data present"); topaz_switch_off_field(); - return 0; + return PM3_SUCCESS; } PrintAndLogEx(NORMAL, ""); @@ -480,35 +521,35 @@ static int CmdHFTopazReader(const char *Cmd) { topaz_print_NDEF(&topaz_tag.data_blocks[1][0]); topaz_switch_off_field(); - return 0; + return PM3_SUCCESS; } static int CmdHFTopazSim(const char *Cmd) { (void)Cmd; // Cmd is not used so far PrintAndLogEx(NORMAL, "not yet implemented"); - return 0; + return PM3_SUCCESS; } static int CmdHFTopazCmdRaw(const char *Cmd) { (void)Cmd; // Cmd is not used so far PrintAndLogEx(NORMAL, "not yet implemented. Use hf 14 raw with option -T."); - return 0; + return PM3_SUCCESS; } static int CmdHFTopazList(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdTraceList("topaz"); - return 0; + return PM3_SUCCESS; } static int CmdHelp(const char *Cmd); static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"reader", CmdHFTopazReader, IfPm3Iso14443a, "Act like a Topaz reader"}, - {"sim", CmdHFTopazSim, IfPm3Iso14443a, " -- Simulate Topaz tag"}, - {"sniff", CmdHF14ASniff, IfPm3Iso14443a, "Sniff Topaz reader-tag communication"}, - {"raw", CmdHFTopazCmdRaw, IfPm3Iso14443a, "Send raw hex data to tag"}, + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"reader", CmdHFTopazReader, IfPm3Iso14443a, "Act like a Topaz reader"}, + {"sim", CmdHFTopazSim, IfPm3Iso14443a, " -- Simulate Topaz tag"}, + {"sniff", CmdHF14ASniff, IfPm3Iso14443a, "Sniff Topaz reader-tag communication"}, + {"raw", CmdHFTopazCmdRaw, IfPm3Iso14443a, "Send raw hex data to tag"}, {"list", CmdHFTopazList, AlwaysAvailable, "List Topaz history"}, {NULL, NULL, 0, NULL} }; @@ -516,7 +557,7 @@ static command_t CommandTable[] = { static int CmdHelp(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdsHelp(CommandTable); - return 0; + return PM3_SUCCESS; } int CmdHFTopaz(const char *Cmd) { diff --git a/client/cmdhftopaz.h b/client/cmdhftopaz.h index ed0b37a08..2cd2379b0 100644 --- a/client/cmdhftopaz.h +++ b/client/cmdhftopaz.h @@ -11,19 +11,7 @@ #ifndef CMDHFTOPAZ_H__ #define CMDHFTOPAZ_H__ -#include -#include -#include -#include -#include "cmdmain.h" -#include "cmdparser.h" -#include "cmdhf14a.h" -#include "ui.h" -#include "mifare.h" -#include "proxmark3.h" -#include "crc16.h" -#include "protocols.h" -#include "cmdhf.h" +#include "common.h" int CmdHFTopaz(const char *Cmd); diff --git a/client/cmdhw.c b/client/cmdhw.c index 1348f16b4..c81efda9e 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -12,12 +12,13 @@ #include #include #include -#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "usart_defs.h" #include "ui.h" -#include "proxmark3.h" -#include "cmdparser.h" #include "cmdhw.h" -#include "cmdmain.h" #include "cmddata.h" static int CmdHelp(const char *Cmd); @@ -449,9 +450,9 @@ static int CmdSetDivisor(const char *Cmd) { PrintAndLogEx(ERR, "divisor must be between 19 and 255"); return PM3_EINVARG; } - // 12 000 000 (12Mhz) + // 12 000 000 (12MHz) clearCommandBuffer(); - SendCommandNG(CMD_SET_LF_DIVISOR, (uint8_t *)&arg, sizeof(arg)); + SendCommandNG(CMD_LF_SET_DIVISOR, (uint8_t *)&arg, sizeof(arg)); PrintAndLogEx(SUCCESS, "Divisor set, expected %.1f kHz", ((double)12000 / (arg + 1))); return PM3_SUCCESS; } @@ -492,7 +493,7 @@ static int CmdTune(const char *Cmd) { static int CmdVersion(const char *Cmd) { (void)Cmd; // Cmd is not used so far - pm3_version(true); + pm3_version(true, false); return PM3_SUCCESS; } @@ -596,7 +597,7 @@ static command_t CommandTable[] = { {"ping", CmdPing, IfPm3Present, "Test if the Proxmark3 is responsive"}, {"readmem", CmdReadmem, IfPm3Present, "[address] -- Read memory at decimal address from flash"}, {"reset", CmdReset, IfPm3Present, "Reset the Proxmark3"}, - {"setlfdivisor", CmdSetDivisor, IfPm3Present, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"}, + {"setlfdivisor", CmdSetDivisor, IfPm3Present, "<19 - 255> -- Drive LF antenna at 12MHz/(divisor+1)"}, {"setmux", CmdSetMux, IfPm3Present, "Set the ADC mux to a specific value"}, {"standalone", CmdStandalone, IfPm3Present, "Jump to the standalone mode"}, {"status", CmdStatus, IfPm3Present, "Show runtime status information about the connected Proxmark3"}, @@ -616,7 +617,66 @@ int CmdHW(const char *Cmd) { return CmdsParse(CommandTable, Cmd); } -void pm3_version(bool verbose) { +void pm3_version(bool verbose, bool oneliner) { + +#if defined(__MINGW64__) +# define PM3CLIENTCOMPILER "MinGW-w64 " +#elif defined(__MINGW32__) +# define PM3CLIENTCOMPILER "MinGW " +#elif defined(__clang__) +# define PM3CLIENTCOMPILER "Clang/LLVM " +#elif defined(__GNUC__) || defined(__GNUG__) +# define PM3CLIENTCOMPILER "GCC " +#else +# define PM3CLIENTCOMPILER "unknown compiler " +#endif + +#if defined(__APPLE__) || defined(__MACH__) +# define PM3HOSTOS " OS:OSX" +#elif defined(__ANDROID__) || defined(ANDROID) +// must be tested before __linux__ +# define PM3HOSTOS " OS:Android" +#elif defined(__linux__) +# define PM3HOSTOS " OS:Linux" +#elif defined(__FreeBSD__) +# define PM3HOSTOS " OS:FreeBSD" +#elif defined(__NetBSD__) +# define PM3HOSTOS " OS:NetBSD" +#elif defined(__OpenBSD__) +# define PM3HOSTOS " OS:OpenBSD" +#elif defined(__CYGWIN__) +# define PM3HOSTOS " OS:Cygwin" +#elif defined(_WIN64) | defined(__WIN64__) +// must be tested before _WIN32 +# define PM3HOSTOS " OS:Windows (64b)" +#elif defined(_WIN32) | defined(__WIN32__) +# define PM3HOSTOS " OS:Windows (32b)" +#else +# define PM3HOSTOS " OS:unknown" +#endif + +#if defined(__x86_64__) +# define PM3HOSTARCH " ARCH:x86_64" +#elif defined(__i386__) +# define PM3HOSTARCH " ARCH:x86" +#elif defined(__aarch64__) +# define PM3HOSTARCH " ARCH:aarch64" +#elif defined(__arm__) +# define PM3HOSTARCH " ARCH:arm" +#elif defined(__powerpc64__) +# define PM3HOSTARCH " ARCH:powerpc64" +#elif defined(__mips__) +# define PM3HOSTARCH " ARCH:mips" +#else +# define PM3HOSTARCH " ARCH:unknown" +#endif + + if (oneliner) { + // For "proxmark3 -v", simple printf, avoid logging + printf("Client: RRG/Iceman compiled with " PM3CLIENTCOMPILER __VERSION__ PM3HOSTOS PM3HOSTARCH "\n"); + return; + } + if (!verbose) return; @@ -629,11 +689,7 @@ void pm3_version(bool verbose) { PrintAndLogEx(NORMAL, "\n" _BLUE_(" [ Proxmark3 RFID instrument ]") "\n"); PrintAndLogEx(NORMAL, "\n [ CLIENT ]"); PrintAndLogEx(NORMAL, " client: RRG/Iceman"); // TODO version info? -#if defined(__clang__) - PrintAndLogEx(NORMAL, " compiled with Clang/LLVM "__VERSION__); -#elif defined(__GNUC__) || defined(__GNUG__) - PrintAndLogEx(NORMAL, " compiled with GCC "__VERSION__); -#endif + PrintAndLogEx(NORMAL, " compiled with " PM3CLIENTCOMPILER __VERSION__ PM3HOSTOS PM3HOSTARCH); PrintAndLogEx(NORMAL, "\n [ PROXMARK RDV4 ]"); PrintAndLogEx(NORMAL, " external flash: %s", IfPm3Flash() ? _GREEN_("present") : _YELLOW_("absent")); PrintAndLogEx(NORMAL, " smartcard reader: %s", IfPm3Smartcard() ? _GREEN_("present") : _YELLOW_("absent")); diff --git a/client/cmdhw.h b/client/cmdhw.h index a1a3a4b8f..bf40b70a8 100644 --- a/client/cmdhw.h +++ b/client/cmdhw.h @@ -11,8 +11,10 @@ #ifndef CMDHW_H__ #define CMDHW_H__ +#include "common.h" + int CmdHW(const char *Cmd); -void pm3_version(bool verbose); +void pm3_version(bool verbose, bool oneliner); #endif diff --git a/client/cmdlf.c b/client/cmdlf.c index 42b26be0d..366f2ed0e 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -9,6 +9,45 @@ //----------------------------------------------------------------------------- #include "cmdlf.h" +#include +#include +#include +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "commonutil.h" // ARRAYLEN + +#include "lfdemod.h" // device/client demods of LF signals +#include "ui.h" // for show graph controls +#include "graph.h" // for graph data +#include "cmddata.h" // for `lf search` +#include "cmdlfawid.h" // for awid menu +#include "cmdlfem4x.h" // for em4x menu +#include "cmdlfhid.h" // for hid menu +#include "cmdlfhitag.h" // for hitag menu +#include "cmdlfio.h" // for ioprox menu +#include "cmdlft55xx.h" // for t55xx menu +#include "cmdlfti.h" // for ti menu +#include "cmdlfpresco.h" // for presco menu +#include "cmdlfpcf7931.h" // for pcf7931 menu +#include "cmdlfpyramid.h" // for pyramid menu +#include "cmdlfviking.h" // for viking menu +#include "cmdlfnedap.h" // for NEDAP menu +#include "cmdlfjablotron.h" // for JABLOTRON menu +#include "cmdlfvisa2000.h" // for VISA2000 menu +#include "cmdlfnoralsy.h" // for NORALSY meny +#include "cmdlfcotag.h" // for COTAG meny +#include "cmdlfindala.h" // for indala menu +#include "cmdlfguard.h" // for gproxii menu +#include "cmdlffdx.h" // for fdx-b menu +#include "cmdlfparadox.h" // for paradox menu +#include "cmdlfnexwatch.h" // for nexwatch menu +#include "cmdlfsecurakey.h" // for securakey menu +#include "cmdlfpac.h" // for pac menu +#include "cmdlfkeri.h" // for keri menu + bool g_lf_threshold_set = false; static int CmdHelp(const char *Cmd); @@ -201,11 +240,11 @@ int CmdLFCommandRead(const char *Cmd) { PrintAndLogEx(SUCCESS, "Sending"); clearCommandBuffer(); - SendCommandNG(CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K, (uint8_t *)&payload, 8 + datalen); + SendCommandNG(CMD_LF_MOD_THEN_ACQ_RAW_ADC, (uint8_t *)&payload, 8 + datalen); printf("\n"); uint8_t i = 10; - while (!WaitForResponseTimeout(CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K, NULL, 2000) && i != 0) { + while (!WaitForResponseTimeout(CMD_LF_MOD_THEN_ACQ_RAW_ADC, NULL, 2000) && i != 0) { printf("."); fflush(stdout); i--; @@ -361,7 +400,7 @@ int CmdLFSetConfig(const char *Cmd) { sample_config config = { decimation, bps, averaging, divisor, trigger_threshold }; clearCommandBuffer(); - SendCommandNG(CMD_SET_LF_SAMPLING_CONFIG, (uint8_t *)&config, sizeof(sample_config)); + SendCommandNG(CMD_LF_SAMPLING_SET_CONFIG, (uint8_t *)&config, sizeof(sample_config)); return PM3_SUCCESS; } @@ -378,13 +417,13 @@ int lf_read(bool silent, uint32_t samples) { payload.samples = samples; clearCommandBuffer(); - SendCommandNG(CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, (uint8_t *)&payload, sizeof(payload)); + SendCommandNG(CMD_LF_ACQ_RAW_ADC, (uint8_t *)&payload, sizeof(payload)); PacketResponseNG resp; if (g_lf_threshold_set) { - WaitForResponse(CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, &resp); + WaitForResponse(CMD_LF_ACQ_RAW_ADC, &resp); } else { - if (!WaitForResponseTimeout(CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, &resp, 2500)) { + if (!WaitForResponseTimeout(CMD_LF_ACQ_RAW_ADC, &resp, 2500)) { PrintAndLogEx(WARNING, "command execution time out"); return PM3_ETIMEOUT; } @@ -414,7 +453,7 @@ int CmdLFRead(const char *Cmd) { cmdp++; break; case 'd': - samples = param_get32ex(Cmd, cmdp, 0, 10); + samples = param_get32ex(Cmd, cmdp + 1, 0, 10); cmdp += 2; break; default: @@ -438,7 +477,7 @@ int CmdLFSniff(const char *Cmd) { if (cmdp == 'h') return usage_lf_sniff(); clearCommandBuffer(); - SendCommandNG(CMD_LF_SNIFF_RAW_ADC_SAMPLES, NULL, 0); + SendCommandNG(CMD_LF_SNIFF_RAW_ADC, NULL, 0); WaitForResponse(CMD_ACK, NULL); getSamples(0, false); return PM3_SUCCESS; @@ -501,8 +540,8 @@ int CmdLFSim(const char *Cmd) { payload_up.data[j] = GraphBuffer[i + j]; - SendCommandNG(CMD_UPLOAD_SIM_SAMPLES_125K, (uint8_t *)&payload_up, sizeof(struct pupload)); - WaitForResponse(CMD_UPLOAD_SIM_SAMPLES_125K, NULL); + SendCommandNG(CMD_LF_UPLOAD_SIM_SAMPLES, (uint8_t *)&payload_up, sizeof(struct pupload)); + WaitForResponse(CMD_LF_UPLOAD_SIM_SAMPLES, NULL); printf("."); fflush(stdout); payload_up.flag = 0; @@ -522,10 +561,10 @@ int CmdLFSim(const char *Cmd) { payload.gap = gap; clearCommandBuffer(); - SendCommandNG(CMD_SIMULATE_TAG_125K, (uint8_t *)&payload, sizeof(payload)); + SendCommandNG(CMD_LF_SIMULATE, (uint8_t *)&payload, sizeof(payload)); PacketResponseNG resp; - WaitForResponse(CMD_SIMULATE_TAG_125K, &resp); + WaitForResponse(CMD_LF_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) @@ -624,12 +663,12 @@ int CmdLFfskSim(const char *Cmd) { PrintAndLogEx(INFO, "Simulating"); clearCommandBuffer(); - SendCommandNG(CMD_FSK_SIM_TAG, (uint8_t *)payload, sizeof(lf_fsksim_t) + size); + SendCommandNG(CMD_LF_FSK_SIMULATE, (uint8_t *)payload, sizeof(lf_fsksim_t) + size); free(payload); setClockGrid(clk, 0); PacketResponseNG resp; - WaitForResponse(CMD_FSK_SIM_TAG, &resp); + WaitForResponse(CMD_LF_FSK_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) @@ -726,11 +765,11 @@ int CmdLFaskSim(const char *Cmd) { PrintAndLogEx(INFO, "Simulating"); clearCommandBuffer(); - SendCommandNG(CMD_ASK_SIM_TAG, (uint8_t *)payload, sizeof(lf_asksim_t) + size); + SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + size); free(payload); PacketResponseNG resp; - WaitForResponse(CMD_ASK_SIM_TAG, &resp); + WaitForResponse(CMD_LF_ASK_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) @@ -845,11 +884,11 @@ int CmdLFpskSim(const char *Cmd) { PrintAndLogEx(INFO, "Simulating"); clearCommandBuffer(); - SendCommandNG(CMD_PSK_SIM_TAG, (uint8_t *)payload, sizeof(lf_psksim_t) + size); + SendCommandNG(CMD_LF_PSK_SIMULATE, (uint8_t *)payload, sizeof(lf_psksim_t) + size); free(payload); PacketResponseNG resp; - WaitForResponse(CMD_PSK_SIM_TAG, &resp); + WaitForResponse(CMD_LF_PSK_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) diff --git a/client/cmdlf.h b/client/cmdlf.h index 89299beaf..8c90d2d42 100644 --- a/client/cmdlf.h +++ b/client/cmdlf.h @@ -10,46 +10,8 @@ #ifndef CMDLF_H__ #define CMDLF_H__ -#include -#include -#include -#include -#include -#include -#include "proxmark3.h" -#include "lfdemod.h" // device/client demods of LF signals -#include "util.h" // for parsing cli command utils -#include "ui.h" // for show graph controls -#include "graph.h" // for graph data -#include "cmdparser.h" // for getting cli commands included in cmdmain.h -#include "cmdmain.h" // for sending cmds to device. GetFromBigBuf -#include "cmddata.h" // for `lf search` -#include "cmdlfawid.h" // for awid menu -#include "cmdlfem4x.h" // for em4x menu -#include "cmdlfhid.h" // for hid menu -#include "cmdlfhitag.h" // for hitag menu -#include "cmdlfio.h" // for ioprox menu -#include "cmdlft55xx.h" // for t55xx menu -#include "cmdlfti.h" // for ti menu -#include "cmdlfpresco.h" // for presco menu -#include "cmdlfpcf7931.h" // for pcf7931 menu -#include "cmdlfpyramid.h" // for pyramid menu -#include "cmdlfviking.h" // for viking menu -#include "cmdlfguard.h" // for GuardAll menu -#include "cmdlfnedap.h" // for NEDAP menu -#include "cmdlfjablotron.h" // for JABLOTRON menu -#include "cmdlfvisa2000.h" // for VISA2000 menu -#include "cmdlfnoralsy.h" // for NORALSY meny -#include "cmdlffdx.h" // for FDX-B meny -#include "cmdlfcotag.h" // for COTAG meny -#include "cmdlfindala.h" // for indala menu -#include "cmdlfguard.h" // for gproxii menu -#include "cmdlffdx.h" // for fdx-b menu -#include "cmdlfparadox.h" // for paradox menu -#include "cmdlfnexwatch.h" // for nexwatch menu -#include "cmdlfsecurakey.h" // for securakey menu -#include "cmdlfpac.h" // for pac menu -#include "cmdlfkeri.h" // for keri menu + +#include "common.h" #define T55XX_WRITE_TIMEOUT 1500 diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index 386d14e5e..b574af772 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -12,6 +12,21 @@ //----------------------------------------------------------------------------- #include "cmdlfawid.h" // AWID function declarations +#include +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "graph.h" +#include "cmddata.h" + +#include "ui.h" // PrintAndLog +#include "lfdemod.h" // parityTest +#include "cmdlf.h" // lf read +#include "protocols.h" // for T55xx config register definitions +#include "util_posix.h" + static int CmdHelp(const char *Cmd); /* static int usage_lf_awid_read(void) { @@ -115,7 +130,7 @@ static int sendTry(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint32_t delay, uin memcpy(payload->data, bits, bs_len); clearCommandBuffer(); - SendCommandNG(CMD_FSK_SIM_TAG, (uint8_t *)payload, sizeof(lf_fsksim_t) + bs_len); + SendCommandNG(CMD_LF_FSK_SIMULATE, (uint8_t *)payload, sizeof(lf_fsksim_t) + bs_len); free(payload); msleep(delay); @@ -172,7 +187,7 @@ static int CmdAWIDRead_device(const char *Cmd) { if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_awid_read(); uint8_t findone = (Cmd[0] == '1') ? 1 : 0; clearCommandBuffer(); - SendCommandMIX(CMD_AWID_DEMOD_FSK, findone, 0, 0, NULL, 0); + SendCommandMIX(CMD_LF_AWID_DEMOD, findone, 0, 0, NULL, 0); return PM3_SUCCESS; } */ @@ -352,11 +367,11 @@ static int CmdAWIDSim(const char *Cmd) { memcpy(payload->data, bs, sizeof(bs)); clearCommandBuffer(); - SendCommandNG(CMD_FSK_SIM_TAG, (uint8_t *)payload, sizeof(lf_fsksim_t) + sizeof(bs)); + SendCommandNG(CMD_LF_FSK_SIMULATE, (uint8_t *)payload, sizeof(lf_fsksim_t) + sizeof(bs)); free(payload); PacketResponseNG resp; - WaitForResponse(CMD_FSK_SIM_TAG, &resp); + WaitForResponse(CMD_LF_FSK_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) @@ -417,8 +432,8 @@ static int CmdAWIDClone(const char *Cmd) { ng.blockno = i; ng.flags = 0; - SendCommandNG(CMD_T55XX_WRITE_BLOCK, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_T55XX_WRITE_BLOCK, &resp, T55XX_WRITE_TIMEOUT)) { + SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); + if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); return PM3_ETIMEOUT; } diff --git a/client/cmdlfawid.h b/client/cmdlfawid.h index e51e986a6..80645e9b9 100644 --- a/client/cmdlfawid.h +++ b/client/cmdlfawid.h @@ -11,18 +11,7 @@ #ifndef CMDLFAWID_H__ #define CMDLFAWID_H__ -#include // sscanf -#include // bool -#include "proxmark3.h" // Definitions, USB controls, etc -#include "ui.h" // PrintAndLog -#include "cmdparser.h" // CmdsParse, CmdsHelp -#include "lfdemod.h" // parityTest -#include "util.h" // weigandparity -#include "cmdlf.h" // lf read -#include "protocols.h" // for T55xx config register definitions -#include "cmdmain.h" -#include "util_posix.h" - +#include "common.h" int CmdLFAWID(const char *Cmd); diff --git a/client/cmdlfcotag.c b/client/cmdlfcotag.c index 134d55c68..96548fca9 100644 --- a/client/cmdlfcotag.c +++ b/client/cmdlfcotag.c @@ -9,6 +9,15 @@ //----------------------------------------------------------------------------- #include "cmdlfcotag.h" // COTAG function declarations +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "lfdemod.h" +#include "cmddata.h" // getSamples +#include "ui.h" // PrintAndLog + static int CmdHelp(const char *Cmd); static int usage_lf_cotag_read(void) { @@ -75,7 +84,7 @@ static int CmdCOTAGRead(const char *Cmd) { sscanf(Cmd, "%u", &rawsignal); clearCommandBuffer(); - SendCommandMIX(CMD_COTAG, rawsignal, 0, 0, NULL, 0); + SendCommandMIX(CMD_LF_COTAG_READ, rawsignal, 0, 0, NULL, 0); if (!WaitForResponseTimeout(CMD_ACK, NULL, 7000)) { PrintAndLogEx(WARNING, "command execution time out"); return PM3_ETIMEOUT; diff --git a/client/cmdlfcotag.h b/client/cmdlfcotag.h index e4b12235d..01c4daa03 100644 --- a/client/cmdlfcotag.h +++ b/client/cmdlfcotag.h @@ -11,13 +11,7 @@ #ifndef CMDLFCOTAG_H__ #define CMDLFCOTAG_H__ -#include "proxmark3.h" // Definitions, USB controls, COTAG_BITS -#include "util.h" // FALSE / TRUE -#include "cmddata.h" // getSamples -#include "cmdparser.h" // CmdsParse, CmdsHelp -#include "comms.h" -#include "ui.h" // PrintAndLog -#include "cmdlf.h" // Setconfig +#include "common.h" #ifndef COTAG_BITS #define COTAG_BITS 264 diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 165f22001..c04e64c00 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -10,6 +10,23 @@ #include "cmdlfem4x.h" +#include +#include +#include +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "commonutil.h" +#include "util_posix.h" +#include "protocols.h" +#include "ui.h" +#include "graph.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "lfdemod.h" + uint64_t g_em410xid = 0; static int CmdHelp(const char *Cmd); @@ -401,7 +418,7 @@ int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose) { static int CmdEM410xRead_device(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); uint8_t findone = (cmdp == '1') ? 1 : 0; - SendCommandMIX(CMD_EM410X_DEMOD, findone, 0, 0, NULL, 0); + SendCommandMIX(CMD_LF_EM410X_DEMOD, findone, 0, 0, NULL, 0); return PM3_SUCCESS; } */ @@ -425,7 +442,7 @@ static int CmdEM410xDemod(const char *Cmd) { // this read is the "normal" read, which download lf signal and tries to demod here. static int CmdEM410xRead(const char *Cmd) { - lf_read(true, 8192); + lf_read(true, 12288); return CmdEM410xDemod(Cmd); } @@ -582,7 +599,7 @@ static int CmdEM410xWatch(const char *Cmd) { PrintAndLogEx(WARNING, "\naborted via keyboard!\n"); break; } - lf_read(true, 8201); + lf_read(true, 12288); } while (CmdEM410xRead("") != PM3_SUCCESS); return PM3_SUCCESS; @@ -645,7 +662,7 @@ static int CmdEM410xWrite(const char *Cmd) { PrintAndLogEx(SUCCESS, "Writing %s tag with UID 0x%010" PRIx64 " (clock rate: %d)", "T55x7", id, clock1); // NOTE: We really should pass the clock in as a separate argument, but to // provide for backwards-compatibility for older firmware, and to avoid - // having to add another argument to CMD_EM410X_WRITE_TAG, we just store + // having to add another argument to CMD_LF_EM410X_WRITE, we just store // the clock rate in bits 8-15 of the card value card = (card & 0xFF) | ((clock1 << 8) & 0xFF00); } else if (card == 0) { @@ -656,7 +673,7 @@ static int CmdEM410xWrite(const char *Cmd) { return PM3_ESOFT; } - SendCommandMIX(CMD_EM410X_WRITE_TAG, card, (uint32_t)(id >> 32), (uint32_t)id, NULL, 0); + SendCommandMIX(CMD_LF_EM410X_WRITE, card, (uint32_t)(id >> 32), (uint32_t)id, NULL, 0); return PM3_SUCCESS; } @@ -1147,9 +1164,9 @@ static int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t payload.usepwd = usePwd; clearCommandBuffer(); - SendCommandNG(CMD_EM4X_READ_WORD, (uint8_t *)&payload, sizeof(payload)); + SendCommandNG(CMD_LF_EM4X_READWORD, (uint8_t *)&payload, sizeof(payload)); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_EM4X_READ_WORD, &resp, 2500)) { + if (!WaitForResponseTimeout(CMD_LF_EM4X_READWORD, &resp, 2500)) { PrintAndLogEx(DEBUG, "timeout while waiting for reply."); return PM3_ETIMEOUT; } @@ -1259,9 +1276,9 @@ static int CmdEM4x05Write(const char *Cmd) { payload.usepwd = usePwd; clearCommandBuffer(); - SendCommandNG(CMD_EM4X_WRITE_WORD, (uint8_t *)&payload, sizeof(payload)); + SendCommandNG(CMD_LF_EM4X_WRITEWORD, (uint8_t *)&payload, sizeof(payload)); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_EM4X_WRITE_WORD, &resp, 2000)) { + if (!WaitForResponseTimeout(CMD_LF_EM4X_WRITEWORD, &resp, 2000)) { PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); return PM3_ETIMEOUT; } diff --git a/client/cmdlfem4x.h b/client/cmdlfem4x.h index 12f27c2c7..d727cb551 100644 --- a/client/cmdlfem4x.h +++ b/client/cmdlfem4x.h @@ -11,19 +11,7 @@ #ifndef CMDLFEM4X_H__ #define CMDLFEM4X_H__ -#include -#include // for bool -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "comms.h" -#include "cmdlf.h" -#include "lfdemod.h" +#include "common.h" int CmdLFEM4X(const char *Cmd); diff --git a/client/cmdlffdx.c b/client/cmdlffdx.c index 35f3216ad..2e48918fb 100644 --- a/client/cmdlffdx.c +++ b/client/cmdlffdx.c @@ -10,6 +10,21 @@ #include "cmdlffdx.h" +#include +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "commonutil.h" + +#include "ui.h" // PrintAndLog +#include "cmddata.h" +#include "cmdlf.h" // lf read +#include "crc16.h" // for checksum crc-16_ccitt +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // parityTest + /* FDX-B ISO11784/85 demod (aka animal tag) BIPHASE, inverted, rf/32, with preamble of 00000000001 (128bits) 8 databits + 1 parity (1) @@ -298,8 +313,8 @@ static int CmdFdxClone(const char *Cmd) { ng.blockno = i; ng.flags = 0; - SendCommandNG(CMD_T55XX_WRITE_BLOCK, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_T55XX_WRITE_BLOCK, &resp, T55XX_WRITE_TIMEOUT)) { + SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); + if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); return PM3_ETIMEOUT; } @@ -334,11 +349,11 @@ static int CmdFdxSim(const char *Cmd) { memcpy(payload->data, bs, sizeof(bs)); clearCommandBuffer(); - SendCommandNG(CMD_ASK_SIM_TAG, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs)); + SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs)); free(payload); PacketResponseNG resp; - WaitForResponse(CMD_ASK_SIM_TAG, &resp); + WaitForResponse(CMD_LF_ASK_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) diff --git a/client/cmdlffdx.h b/client/cmdlffdx.h index 5e6c5ab48..d8b666ccb 100644 --- a/client/cmdlffdx.h +++ b/client/cmdlffdx.h @@ -8,16 +8,8 @@ //----------------------------------------------------------------------------- #ifndef CMDLFFDX_H__ #define CMDLFFDX_H__ -#include "proxmark3.h" // Definitions, USB controls, etc -#include "ui.h" // PrintAndLog -#include "util.h" // weigandparity -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdmain.h" -#include "cmdlf.h" // lf read -#include "crc16.h" // for checksum crc-16_ccitt -#include "protocols.h" // for T55xx config register definitions -#include "lfdemod.h" // parityTest + +#include "common.h" int CmdLFFdx(const char *Cmd); int detectFDXB(uint8_t *dest, size_t *size); diff --git a/client/cmdlfguard.c b/client/cmdlfguard.c index 1b09eb18d..22f7141fc 100644 --- a/client/cmdlfguard.c +++ b/client/cmdlfguard.c @@ -9,6 +9,19 @@ //----------------------------------------------------------------------------- #include "cmdlfguard.h" +#include +#include +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // parityTest + static int CmdHelp(const char *Cmd); static int usage_lf_guard_clone(void) { @@ -187,8 +200,8 @@ static int CmdGuardClone(const char *Cmd) { ng.blockno = i; ng.flags = 0; - SendCommandNG(CMD_T55XX_WRITE_BLOCK, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_T55XX_WRITE_BLOCK, &resp, T55XX_WRITE_TIMEOUT)) { + SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); + if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); return PM3_ETIMEOUT; } @@ -228,11 +241,11 @@ static int CmdGuardSim(const char *Cmd) { memcpy(payload->data, bs, sizeof(bs)); clearCommandBuffer(); - SendCommandNG(CMD_ASK_SIM_TAG, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs)); + SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs)); free(payload); PacketResponseNG resp; - WaitForResponse(CMD_ASK_SIM_TAG, &resp); + WaitForResponse(CMD_LF_ASK_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) diff --git a/client/cmdlfguard.h b/client/cmdlfguard.h index c6725ed07..3d923a7fe 100644 --- a/client/cmdlfguard.h +++ b/client/cmdlfguard.h @@ -8,19 +8,8 @@ //----------------------------------------------------------------------------- #ifndef CMDLFGUARD_H__ #define CMDLFGUARD_H__ -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdmain.h" -#include "cmdlf.h" -#include "protocols.h" // for T55xx config register definitions -#include "lfdemod.h" // parityTest -#include "crc.h" + +#include "common.h" int CmdLFGuard(const char *Cmd); int detectGProxII(uint8_t *bits, size_t *size); diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index cc395c8c5..8e22654f4 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -10,6 +10,22 @@ #include "cmdlfhid.h" +#include +#include + +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "commonutil.h" // ARRAYLEN +#include "ui.h" +#include "graph.h" +#include "cmddata.h" //for g_debugMode, demodbuff cmds +#include "cmdlf.h" // lf_read +#include "util_posix.h" +#include "lfdemod.h" + #ifndef BITS # define BITS 96 #endif @@ -111,7 +127,7 @@ static int sendTry(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint32_t delay, uin calcWiegand(fmtlen, fc, cn, bits, 0); clearCommandBuffer(); - SendCommandMIX(CMD_HID_SIM_TAG, bytebits_to_byte(bits, 32), bytebits_to_byte(bits + 32, 32), 0, NULL, 0); + SendCommandMIX(CMD_LF_HID_SIMULATE, bytebits_to_byte(bits, 32), bytebits_to_byte(bits + 32, 32), 0, NULL, 0); msleep(delay); return sendPing(); @@ -240,7 +256,7 @@ static int CmdHIDRead_device(const char *Cmd) { if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_hid_read(); uint8_t findone = (Cmd[0] == '1') ? 1 : 0; clearCommandBuffer(); - SendCommandMIX(CMD_HID_DEMOD_FSK, findone, 0, 0, NULL, 0); + SendCommandMIX(CMD_LF_HID_DEMOD, findone, 0, 0, NULL, 0); return PM3_SUCCESS; } */ @@ -260,9 +276,9 @@ static int CmdHIDSim(const char *Cmd) { PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation"); clearCommandBuffer(); - SendCommandMIX(CMD_HID_SIM_TAG, hi, lo, 0, NULL, 0); + SendCommandMIX(CMD_LF_HID_SIMULATE, hi, lo, 0, NULL, 0); PacketResponseNG resp; - WaitForResponse(CMD_HID_SIM_TAG, &resp); + WaitForResponse(CMD_LF_HID_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) return resp.status; @@ -297,7 +313,7 @@ static int CmdHIDClone(const char *Cmd) { } clearCommandBuffer(); - SendCommandOLD(CMD_HID_CLONE_TAG, hi2, hi, lo, longid, sizeof(longid)); + SendCommandOLD(CMD_LF_HID_CLONE, hi2, hi, lo, longid, sizeof(longid)); return PM3_SUCCESS; } @@ -485,7 +501,7 @@ static int CmdHIDWiegand(const char *Cmd) { PrintAndLogEx(NORMAL, "HID | OEM | FC | CN | Wiegand | HID Formatted"); PrintAndLogEx(NORMAL, "----+-----+------+---------+-----------+--------------------"); - for (uint8_t i = 0; i < sizeof(fmtlen); i++) { + for (uint8_t i = 0; i < ARRAYLEN(fmtlen); i++) { memset(bits, 0x00, sizeof(bits)); calcWiegand(fmtlen[i], fc, cardnum, bs, oem); PrintAndLogEx(NORMAL, "ice:: %s \n", sprint_bin(bs, fmtlen[i])); @@ -545,7 +561,7 @@ static int CmdHIDBrute(const char *Cmd) { cmdp += 2; bool is_ftm_ok = false; uint8_t ftms[] = {26, 33, 34, 35, 37}; - for (uint8_t i = 0; i < sizeof(ftms); i++) { + for (uint8_t i = 0; i < ARRAYLEN(ftms); i++) { if (ftms[i] == fmtlen) { is_ftm_ok = true; } diff --git a/client/cmdlfhid.h b/client/cmdlfhid.h index 8270b6469..2b61861ff 100644 --- a/client/cmdlfhid.h +++ b/client/cmdlfhid.h @@ -11,18 +11,7 @@ #ifndef CMDLFHID_H__ #define CMDLFHID_H__ -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "graph.h" -#include "cmdparser.h" -#include "util.h" // wiegand_add_parity etc -#include "cmddata.h" //for g_debugMode, demodbuff cmds -#include "cmdlf.h" // lf_read -#include "cmdmain.h" -#include "util_posix.h" -#include "lfdemod.h" +#include "common.h" int CmdLFHID(const char *Cmd); diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 0fc4b053c..2bcd476ea 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -8,20 +8,14 @@ // Low frequency Hitag support //----------------------------------------------------------------------------- -#include -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "cmdparser.h" -#include "common.h" -#include "util.h" -#include "parity.h" -#include "hitag.h" -#include "util_posix.h" +#include + +#include "cmdparser.h" // command_t #include "comms.h" -#include "cmddata.h" -#include "loclass/fileutils.h" // savefile +#include "cmdtrace.h" +#include "commonutil.h" +#include "hitag.h" +#include "fileutils.h" // savefile static int CmdHelp(const char *Cmd); @@ -84,13 +78,14 @@ static int usage_hitag_reader(void) { PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h This help"); PrintAndLogEx(NORMAL, " HitagS (0*)"); - PrintAndLogEx(NORMAL, " 01 Challenge, read all pages from a Hitag S tag"); - PrintAndLogEx(NORMAL, " 02 Set to 0 if no authentication is needed. Read all pages from a Hitag S tag"); + PrintAndLogEx(NORMAL, " 01 Read all pages, challenge mode"); + PrintAndLogEx(NORMAL, " 02 Read all pages, crypto mode. Set key=0 for no auth"); PrintAndLogEx(NORMAL, " Hitag1 (1*)"); + PrintAndLogEx(NORMAL, " Not implemented"); PrintAndLogEx(NORMAL, " Hitag2 (2*)"); - PrintAndLogEx(NORMAL, " 21 Password mode"); - PrintAndLogEx(NORMAL, " 22 Authentication"); - PrintAndLogEx(NORMAL, " 23 Authentication, key is in format: ISK high + ISK low"); + PrintAndLogEx(NORMAL, " 21 Read all pages, password mode. Default: 4D494B52 (\"MIKR\")"); + PrintAndLogEx(NORMAL, " 22 Read all pages, challenge mode"); + PrintAndLogEx(NORMAL, " 23 Read all pages, crypto mode. Key format: ISK high + ISK low. Default: 4F4E4D494B52 (\"ONMIKR\")"); PrintAndLogEx(NORMAL, " 25 Test recorded authentications"); PrintAndLogEx(NORMAL, " 26 Just read UID"); return 0; @@ -99,14 +94,16 @@ static int usage_hitag_writer(void) { PrintAndLogEx(NORMAL, "Hitag writer functions"); PrintAndLogEx(NORMAL, "Usage: lf hitag write [h] "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " h This help"); PrintAndLogEx(NORMAL, " HitagS (0*)"); - PrintAndLogEx(NORMAL, " 03 (Challenge) write page on a Hitag S tag"); - PrintAndLogEx(NORMAL, " 04 (set to 0 if no authentication is needed) write page on a Hitag S tag"); + PrintAndLogEx(NORMAL, " 03 Write page, challenge mode"); + PrintAndLogEx(NORMAL, " 04 Write page, crypto mode. Set key=0 for no auth"); PrintAndLogEx(NORMAL, " Hitag1 (1*)"); + PrintAndLogEx(NORMAL, " Not implemented"); PrintAndLogEx(NORMAL, " Hitag2 (2*)"); - PrintAndLogEx(NORMAL, " 24 (set to 0 if no authentication is needed) write page on a Hitag2 tag"); - PrintAndLogEx(NORMAL, " 27 write page on a Hitag2 tag"); + PrintAndLogEx(NORMAL, " 24 Write page, crypto mode. Key format: ISK high + ISK low."); + PrintAndLogEx(NORMAL, " Default: 4F4E4D494B52 (\"ONMIKR\"). Set key=0 for no auth"); + PrintAndLogEx(NORMAL, " 27 Write page, password mode. Default: 4D494B52 (\"MIKR\")"); return 0; } static int usage_hitag_checkchallenges(void) { @@ -262,7 +259,7 @@ static int CmdLFHitagSniff(const char *Cmd) { if (ctmp == 'h') return usage_hitag_sniff(); clearCommandBuffer(); - SendCommandNG(CMD_SNIFF_HITAG, NULL, 0); + SendCommandNG(CMD_LF_HITAG_SNIFF, NULL, 0); return 0; } @@ -277,7 +274,7 @@ static int CmdLFHitagSim(const char *Cmd) { int res = 0; char filename[FILE_PATH_SIZE] = { 0x00 }; - uint16_t cmd = CMD_SIMULATE_HITAG; + uint16_t cmd = CMD_LF_HITAG_SIMULATE; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': @@ -288,7 +285,7 @@ static int CmdLFHitagSim(const char *Cmd) { cmdp++; break; case 's': - cmd = CMD_SIMULATE_HITAG_S; + cmd = CMD_LF_HITAGS_SIMULATE; maxdatalen = 4 * 64; cmdp++; break; @@ -296,7 +293,7 @@ static int CmdLFHitagSim(const char *Cmd) { param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); res = loadFileEML(filename, data, &datalen); if (res > 0 || datalen != maxdatalen) { - PrintAndLogDevice(FAILED, "error, bytes read mismatch file size"); + PrintAndLogEx(FAILED, "error, bytes read mismatch file size"); errors = true; break; } @@ -459,7 +456,7 @@ static bool getHitagUid(uint32_t *uid) { hitag_data htd; memset(&htd, 0, sizeof(htd)); clearCommandBuffer(); - SendCommandMIX(CMD_READER_HITAG, RHT2F_UID_ONLY, 0, 0, &htd, sizeof(htd)); + SendCommandMIX(CMD_LF_HITAG_READER, RHT2F_UID_ONLY, 0, 0, &htd, sizeof(htd)); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); @@ -478,15 +475,9 @@ static bool getHitagUid(uint32_t *uid) { } static int CmdLFHitagInfo(const char *Cmd) { - PrintAndLogEx(INFO, "Hitag2 tag information "); - PrintAndLogEx(INFO, "To be done!"); - PrintAndLogEx(INFO, "------------------------------------"); - char ctmp = tolower(param_getchar(Cmd, 0)); if (ctmp == 'h') return usage_hitag_info(); - // pwd or key - // read UID uint32_t uid = 0; if (getHitagUid(&uid) == false) @@ -495,8 +486,8 @@ static int CmdLFHitagInfo(const char *Cmd) { PrintAndLogEx(SUCCESS, "UID: %08X", uid); // how to detemine Hitag types? - // read block3, get configuration byte. + PrintAndLogEx(FAILED, _RED_("TODO: This is a hardcoded example!")); // common configurations. printHitagConfiguration(0x06); @@ -512,19 +503,19 @@ static int CmdLFHitagInfo(const char *Cmd) { // static int CmdLFHitagReader(const char *Cmd) { - uint16_t cmd = CMD_READER_HITAG; + uint16_t cmd = CMD_LF_HITAG_READER; hitag_data htd; hitag_function htf = param_get32ex(Cmd, 0, 0, 10); switch (htf) { case RHTSF_CHALLENGE: { - cmd = CMD_READ_HITAG_S; + cmd = CMD_LF_HITAGS_READ; num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd.auth.NrAr); num_to_bytes(param_get32ex(Cmd, 2, 0, 16), 4, htd.auth.NrAr + 4); break; } case RHTSF_KEY: { - cmd = CMD_READ_HITAG_S; + cmd = CMD_LF_HITAGS_READ; num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd.crypto.key); break; } @@ -633,9 +624,9 @@ static int CmdLFHitagCheckChallenges(const char *Cmd) { clearCommandBuffer(); if (file_given) - SendCommandOLD(CMD_TEST_HITAGS_TRACES, 1, 0, 0, data, datalen); + SendCommandOLD(CMD_LF_HITAGS_TEST_TRACES, 1, 0, 0, data, datalen); else - SendCommandMIX(CMD_TEST_HITAGS_TRACES, 0, 0, 0, NULL, 0); + SendCommandMIX(CMD_LF_HITAGS_TEST_TRACES, 0, 0, 0, NULL, 0); free(data); return 0; @@ -678,7 +669,7 @@ static int CmdLFHitagWriter(const char *Cmd) { } clearCommandBuffer(); - SendCommandOLD(CMD_WR_HITAG_S, htf, 0, arg2, &htd, sizeof(htd)); + SendCommandOLD(CMD_LF_HITAGS_WRITE, htf, 0, arg2, &htd, sizeof(htd)); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); diff --git a/client/cmdlfhitag.h b/client/cmdlfhitag.h index 264a245a1..c95c0e334 100644 --- a/client/cmdlfhitag.h +++ b/client/cmdlfhitag.h @@ -11,6 +11,8 @@ #ifndef CMDLFHITAG_H__ #define CMDLFHITAG_H__ +#include "common.h" + int CmdLFHitag(const char *Cmd); int readHitagUid(void); diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 41c292a5b..3fd3be59e 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -10,6 +10,22 @@ #include "cmdlfindala.h" +#include +#include + +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "graph.h" +#include "cliparser/cliparser.h" +#include "commonutil.h" +#include "ui.h" // PrintAndLog +#include "lfdemod.h" // parityTest, bitbytes_to_byte +#include "cmddata.h" +#include "cmdlf.h" // lf_read + static int CmdHelp(const char *Cmd); //large 224 bit indala formats (different preamble too...) @@ -411,11 +427,11 @@ static int CmdIndalaSim(const char *Cmd) { PrintAndLogEx(INFO, "Simulating"); clearCommandBuffer(); - SendCommandNG(CMD_PSK_SIM_TAG, (uint8_t *)payload, sizeof(lf_psksim_t) + sizeof(bs)); + SendCommandNG(CMD_LF_PSK_SIMULATE, (uint8_t *)payload, sizeof(lf_psksim_t) + sizeof(bs)); free(payload); PacketResponseNG resp; - WaitForResponse(CMD_PSK_SIM_TAG, &resp); + WaitForResponse(CMD_LF_PSK_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) @@ -461,14 +477,14 @@ static int CmdIndalaClone(const char *Cmd) { datawords[5] = bytes_to_num(data + 20, 4); datawords[6] = bytes_to_num(data + 24, 4); clearCommandBuffer(); - SendCommandOLD(CMD_INDALA_CLONE_TAG_L, 0, 0, 0, datawords, sizeof(datawords)); + SendCommandOLD(CMD_LF_INDALA224_CLONE, 0, 0, 0, datawords, sizeof(datawords)); } else { PrintAndLogEx(INFO, "Preparing to clone Indala 64bit tag with RawID %s", sprint_hex(data, datalen)); uint32_t datawords[2] = {0}; datawords[0] = bytes_to_num(data, 4); datawords[1] = bytes_to_num(data + 4, 4); clearCommandBuffer(); - SendCommandOLD(CMD_INDALA_CLONE_TAG, 0, 0, 0, datawords, sizeof(datawords)); + SendCommandOLD(CMD_LF_INDALA_CLONE, 0, 0, 0, datawords, sizeof(datawords)); } return PM3_SUCCESS; diff --git a/client/cmdlfindala.h b/client/cmdlfindala.h index 1de894bf7..830017117 100644 --- a/client/cmdlfindala.h +++ b/client/cmdlfindala.h @@ -10,18 +10,7 @@ #ifndef CMDLFINDALA_H__ #define CMDLFINDALA_H__ -#include // sscanf -#include -#include -#include "proxmark3.h" // Definitions, USB controls, etc -#include "ui.h" // PrintAndLog -#include "cmdparser.h" // CmdsParse, CmdsHelp -#include "lfdemod.h" // parityTest, bitbytes_to_byte -#include "util.h" // weigandparity -#include "protocols.h" // for T55xx config register definitions -#include "cmdmain.h" -#include "cmddata.h" -#include "cmdlf.h" // lf_read +#include "common.h" int CmdLFINDALA(const char *Cmd); diff --git a/client/cmdlfio.c b/client/cmdlfio.c index d187daaab..87fa17b02 100644 --- a/client/cmdlfio.c +++ b/client/cmdlfio.c @@ -10,6 +10,21 @@ #include "cmdlfio.h" +#include // sscanf +#include +#include + +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "graph.h" +#include "cmdlf.h" +#include "ui.h" // PrintAndLog +#include "lfdemod.h" // parityTest, bitbytes_to_byte +#include "protocols.h" // for T55xx config register definitions +#include "cmddata.h" + static int CmdHelp(const char *Cmd); /* static int usage_lf_io_read(void) { @@ -67,7 +82,7 @@ static int CmdIOProxRead_device(const char *Cmd) { if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_io_read(); int findone = (Cmd[0] == '1') ? 1 : 0; clearCommandBuffer(); - SendCommandMIX(CMD_IO_DEMOD_FSK, findone, 0, 0, NULL, 0); + SendCommandMIX(CMD_LF_IO_DEMOD, findone, 0, 0, NULL, 0); return PM3_SUCCESS; } */ @@ -214,11 +229,11 @@ static int CmdIOProxSim(const char *Cmd) { memcpy(payload->data, bs, sizeof(bs)); clearCommandBuffer(); - SendCommandNG(CMD_FSK_SIM_TAG, (uint8_t *)payload, sizeof(lf_fsksim_t) + sizeof(bs)); + SendCommandNG(CMD_LF_FSK_SIMULATE, (uint8_t *)payload, sizeof(lf_fsksim_t) + sizeof(bs)); free(payload); PacketResponseNG resp; - WaitForResponse(CMD_FSK_SIM_TAG, &resp); + WaitForResponse(CMD_LF_FSK_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) @@ -263,7 +278,7 @@ static int CmdIOProxClone(const char *Cmd) { print_blocks(blocks, 3); clearCommandBuffer(); - SendCommandMIX(CMD_IO_CLONE_TAG, blocks[1], blocks[2], 0, NULL, 0); + SendCommandMIX(CMD_LF_IO_CLONE, blocks[1], blocks[2], 0, NULL, 0); return PM3_SUCCESS; } diff --git a/client/cmdlfio.h b/client/cmdlfio.h index 39abbc767..cb3a514be 100644 --- a/client/cmdlfio.h +++ b/client/cmdlfio.h @@ -4,17 +4,7 @@ #ifndef CMDLFIO_H__ #define CMDLFIO_H__ -#include // sscanf -#include -#include -#include "proxmark3.h" // Definitions, USB controls, etc -#include "ui.h" // PrintAndLog -#include "cmdparser.h" // CmdsParse, CmdsHelp -#include "lfdemod.h" // parityTest, bitbytes_to_byte -#include "util.h" // weigandparity -#include "protocols.h" // for T55xx config register definitions -#include "cmdmain.h" -#include "cmddata.h" +#include "common.h" int CmdLFIO(const char *Cmd); diff --git a/client/cmdlfjablotron.c b/client/cmdlfjablotron.c index c2478705c..9cc663895 100644 --- a/client/cmdlfjablotron.c +++ b/client/cmdlfjablotron.c @@ -10,6 +10,21 @@ #include "cmdlfjablotron.h" +#include +#include +#include +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "commonutil.h" +#include "ui.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // parityTest + static int CmdHelp(const char *Cmd); static int usage_lf_jablotron_clone(void) { @@ -172,8 +187,8 @@ static int CmdJablotronClone(const char *Cmd) { ng.blockno = i; ng.flags = 0; - SendCommandNG(CMD_T55XX_WRITE_BLOCK, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_T55XX_WRITE_BLOCK, &resp, T55XX_WRITE_TIMEOUT)) { + SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); + if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); return PM3_ETIMEOUT; } @@ -208,11 +223,11 @@ static int CmdJablotronSim(const char *Cmd) { memcpy(payload->data, bs, sizeof(bs)); clearCommandBuffer(); - SendCommandNG(CMD_ASK_SIM_TAG, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs)); + SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs)); free(payload); PacketResponseNG resp; - WaitForResponse(CMD_ASK_SIM_TAG, &resp); + WaitForResponse(CMD_LF_ASK_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) diff --git a/client/cmdlfjablotron.h b/client/cmdlfjablotron.h index ae6186496..da4de291f 100644 --- a/client/cmdlfjablotron.h +++ b/client/cmdlfjablotron.h @@ -8,19 +8,8 @@ //----------------------------------------------------------------------------- #ifndef CMDLFJABLOTRON_H__ #define CMDLFJABLOTRON_H__ -#include -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdmain.h" -#include "cmdlf.h" -#include "protocols.h" // for T55xx config register definitions -#include "lfdemod.h" // parityTest + +#include "common.h" int CmdLFJablotron(const char *Cmd); diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index b3761055f..384aad0b6 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -9,6 +9,20 @@ //----------------------------------------------------------------------------- #include "cmdlfkeri.h" +#include +#include + +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // preamble test + static int CmdHelp(const char *Cmd); static int usage_lf_keri_clone(void) { @@ -162,8 +176,8 @@ static int CmdKeriClone(const char *Cmd) { ng.blockno = i; ng.flags = 0; - SendCommandNG(CMD_T55XX_WRITE_BLOCK, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_T55XX_WRITE_BLOCK, &resp, T55XX_WRITE_TIMEOUT)) { + SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); + if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); return PM3_ETIMEOUT; } @@ -201,11 +215,11 @@ static int CmdKeriSim(const char *Cmd) { PrintAndLogEx(INFO, "Simulating"); clearCommandBuffer(); - SendCommandNG(CMD_PSK_SIM_TAG, (uint8_t *)payload, sizeof(lf_psksim_t) + sizeof(bs)); + SendCommandNG(CMD_LF_PSK_SIMULATE, (uint8_t *)payload, sizeof(lf_psksim_t) + sizeof(bs)); free(payload); PacketResponseNG resp; - WaitForResponse(CMD_PSK_SIM_TAG, &resp); + WaitForResponse(CMD_LF_PSK_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) diff --git a/client/cmdlfkeri.h b/client/cmdlfkeri.h index 78b087834..2e1ada11f 100644 --- a/client/cmdlfkeri.h +++ b/client/cmdlfkeri.h @@ -9,18 +9,7 @@ #ifndef CMDLFKERI_H__ #define CMDLFKERI_H__ -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdmain.h" -#include "cmdlf.h" -#include "protocols.h" // for T55xx config register definitions -#include "lfdemod.h" // preamble test +#include "common.h" int CmdLFKeri(const char *Cmd); diff --git a/client/cmdlfnedap.c b/client/cmdlfnedap.c index 0b998d716..3a4ebd131 100644 --- a/client/cmdlfnedap.c +++ b/client/cmdlfnedap.c @@ -8,137 +8,274 @@ //----------------------------------------------------------------------------- #include "cmdlfnedap.h" + +#include + +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "crc16.h" +#include "cmdlft55xx.h" +#include "ui.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "lfdemod.h" + +#define FIXED_71 0x71 +#define FIXED_40 0x40 +#define UNKNOWN_A 0x00 +#define UNKNOWN_B 0x00 + static int CmdHelp(const char *Cmd); -/* -static int usage_lf_nedap_clone(void) { - PrintAndLogEx(NORMAL, "clone a NEDAP tag to a T55x7 tag."); +static int usage_lf_nedap_gen(void) { + PrintAndLogEx(NORMAL, "generate Nedap bitstream in DemodBuffer"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf nedap clone [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " : 24-bit value card number"); -// PrintAndLogEx(NORMAL, " Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf nedap clone 112233"); - return PM3_SUCCESS; -} -*/ - -static int usage_lf_nedap_sim(void) { - PrintAndLogEx(NORMAL, "Enables simulation of NEDAP card with specified card number."); - PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf nedap sim [h] "); + PrintAndLogEx(NORMAL, "Usage: lf nedap generate [h] [s ] c i [l]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " : 24-bit value card number"); + PrintAndLogEx(NORMAL, " s : optional, default=5"); + PrintAndLogEx(NORMAL, " c : customerCode"); + PrintAndLogEx(NORMAL, " i : ID (max 99999)"); + PrintAndLogEx(NORMAL, " l : optional - long (128), default to short (64)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf nedap sim 112233"); + PrintAndLogEx(NORMAL, " lf nedap generate s 1 c 123 i 112233"); return PM3_SUCCESS; } +static int usage_lf_nedap_clone(void) { + PrintAndLogEx(NORMAL, "clone a Nedap tag to a T55x7 tag."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: lf nedap clone [h] [s ] c i [l]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " s : optional, default=5"); + PrintAndLogEx(NORMAL, " c : customerCode"); + PrintAndLogEx(NORMAL, " i : ID (max 99999)"); + PrintAndLogEx(NORMAL, " l : optional - long (128), default to short (64)"); +// PrintAndLogEx(NORMAL, " Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf nedap clone s 1 c 123 i 112233"); + return PM3_SUCCESS; +} + +static int usage_lf_nedap_sim(void) { + PrintAndLogEx(NORMAL, "simulate Nedap card."); + PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: lf nedap sim [h] [s ] c i [l]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " s : subtype, default=5"); + PrintAndLogEx(NORMAL, " c : customerCode"); + PrintAndLogEx(NORMAL, " i : ID (max 99999)"); + PrintAndLogEx(NORMAL, " l : long (128), default to short (64)"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); +// TODO proper example? + PrintAndLogEx(NORMAL, " lf nedap sim s 1 c 7 i 1337"); + return PM3_SUCCESS; +} + +const uint8_t translateTable[10] = {8, 2, 1, 12, 4, 5, 10, 13, 0, 9}; +const uint8_t invTranslateTable[16] = {8, 2, 1, 0xff, 4, 5, 0xff, 0xff, 0, 9, 6, 0xff, 3, 7, 0xff, 0xff}; +const uint8_t preamble[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}; // zero inside + +static inline uint32_t bitcount(uint32_t a) { +#if defined __GNUC__ + return __builtin_popcountl(a); +#else + a = a - ((a >> 1) & 0x55555555); + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); + return (((a + (a >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24; +#endif +} + +static uint8_t isEven_64_63(const uint8_t *data) { // 8 + return (bitcount(*(uint32_t *) data) + (bitcount((*(uint32_t *)(data + 4)) & 0xfeffffff))) & 1; +} + //NEDAP demod - ASK/Biphase (or Diphase), RF/64 with preamble of 1111111110 (always a 128 bit data stream) -//print NEDAP Prox ID, encoding, encrypted ID, static int CmdLFNedapDemod(const char *Cmd) { (void)Cmd; // Cmd is not used so far - //raw ask demod no start bit finding just get binary from wave + + uint8_t data[16], buffer[7], r0, r1, r2, r3, r4, r5, idxC1, idxC2, idxC3, idxC4, idxC5, fixed0, fixed1, unk1, unk2, subtype; // 4 bits + size_t size, offset = 0; + uint16_t checksum, customerCode; // 12 bits + uint32_t badgeId; // max 99999 + if (ASKbiphaseDemod("0 64 1 0", false) != PM3_SUCCESS) { - if (g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: Error - Nedap ASKbiphaseDemod failed"); + if (g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: Error - NEDAP: ASK/Biphase Demod failed"); return PM3_ESOFT; } - size_t size = DemodBufferLen; - int idx = detectNedap(DemodBuffer, &size); - if (idx < 0) { - if (g_debugMode) { - // if (idx == -5) - // PrintAndLogEx(DEBUG, "DEBUG: Error - not enough samples"); - // else if (idx == -1) - // PrintAndLogEx(DEBUG, "DEBUG: Error - only noise found"); - // else if (idx == -2) - // PrintAndLogEx(DEBUG, "DEBUG: Error - problem during ASK/Biphase demod"); - if (idx == -3) - PrintAndLogEx(DEBUG, "DEBUG: Error - Nedap Size not correct: %d", size); - else if (idx == -4) - PrintAndLogEx(DEBUG, "DEBUG: Error - Nedap preamble not found"); - else - PrintAndLogEx(DEBUG, "DEBUG: Error - Nedap idx: %d", idx); + + size = DemodBufferLen; + if (!preambleSearch(DemodBuffer, (uint8_t *) preamble, sizeof(preamble), &size, &offset)) { + PrintAndLogEx(DEBUG, "DEBUG: Error - NEDAP: preamble not found"); + return PM3_ESOFT; + } + + // set plot + setDemodBuff(DemodBuffer, size, offset); + setClockGrid(g_DemodClock, g_DemodStartIdx + (g_DemodClock * offset)); + + // sanity checks + if ((size != 128) && (size != 64)) { + PrintAndLogEx(DEBUG, "DEBUG: Error - NEDAP: Size not correct: %d", size); + return PM3_ESOFT; + } + + if (bits_to_array(DemodBuffer, size, data) != PM3_SUCCESS) { + PrintAndLogEx(DEBUG, "DEBUG: Error - NEDAP: bits_to_array error\n"); + return PM3_ESOFT; + } + + + int ret = PM3_SUCCESS; + + // first part + + // parity 1 check + if (isEven_64_63(data) != (data[7] & 0x01)) { + PrintAndLogEx(ERR, "Bad parity (%1u)", data[7] & 0x01); + ret = PM3_ESOFT; + } + + // header 1 check + // (1111111110 0 -- zero inside) + if ((data[0] != 0xFF) && ((data[1] & 0xE0) != 0x80)) { + PrintAndLogEx(ERR, "Bad header"); + ret = PM3_ESOFT; + } + + buffer[0] = (data[0] << 7) | (data[1] >> 1); + buffer[1] = (data[1] << 7) | (data[2] >> 1); + buffer[2] = (data[2] << 7) | (data[3] >> 1); + buffer[3] = ((data[4] & 0x1e) << 3) | ((data[5] & 0x1e) >> 1); + buffer[4] = ((data[6] & 0x1e) << 3) | ((data[7] & 0x1e) >> 1); + + // CHECKSUM + init_table(CRC_XMODEM); + checksum = crc16_xmodem(buffer, 5); + + buffer[6] = (data[3] << 7) | ((data[4] & 0xe0) >> 1) | ((data[4] & 0x01) << 3) | ((data[5] & 0xe0) >> 5); + buffer[5] = (data[5] << 7) | ((data[6] & 0xe0) >> 1) | ((data[6] & 0x01) << 3) | ((data[7] & 0xe0) >> 5); + + bool isValid = (checksum == *(uint16_t *)(buffer + 5)); + + subtype = (data[1] & 0x1e) >> 1; + customerCode = ((data[1] & 0x01) << 11) | (data[2] << 3) | ((data[3] & 0xe0) >> 5); + + if (isValid == false) { + PrintAndLogEx(ERR, "Checksum : %s (calc 0x%04X != 0x%04X)", _RED_("failed"), checksum, *(uint16_t *)(buffer + 5)); + ret = PM3_ESOFT; + } + + idxC1 = invTranslateTable[(data[3] & 0x1e) >> 1]; + idxC2 = invTranslateTable[(data[4] & 0x1e) >> 1]; + idxC3 = invTranslateTable[(data[5] & 0x1e) >> 1]; + idxC4 = invTranslateTable[(data[6] & 0x1e) >> 1]; + idxC5 = invTranslateTable[(data[7] & 0x1e) >> 1]; + + // validation + if ((idxC1 != 0xFF) && (idxC2 != 0xFF) && (idxC3 != 0xFF) && (idxC4 != 0xFF) && (idxC5 != 0xFF)) { + r1 = idxC1; + r2 = ((10 + idxC2) - (idxC1 + 1)) % 10; + r3 = ((10 + idxC3) - (idxC2 + 1)) % 10; + r4 = ((10 + idxC4) - (idxC3 + 1)) % 10; + r5 = ((10 + idxC5) - (idxC4 + 1)) % 10; + + badgeId = r1 * 10000 + r2 * 1000 + r3 * 100 + r4 * 10 + r5; + + PrintAndLogEx(SUCCESS, "NEDAP Tag Found: Card ID "_YELLOW_("%05u")" subtype: "_YELLOW_("%1u")" customer code: "_YELLOW_("%03x"), badgeId, subtype, customerCode); + PrintAndLogEx(SUCCESS, "Checksum is %s (0x%04X)", _GREEN_("OK"), checksum); + PrintAndLogEx(SUCCESS, "Raw: %s", sprint_hex(data, size / 8)); + } else { + PrintAndLogEx(ERR, "Invalid idx (1:%02x - 2:%02x - 3:%02x - 4:%02x - 5:%02x)", idxC1, idxC2, idxC3, idxC4, idxC5); + ret = PM3_ESOFT; + } + + if (size > 64) { + // second part + PrintAndLogEx(DEBUG, "NEDAP Tag, second part found"); + + if (isEven_64_63(data + 8) != (data[15] & 0x01)) { + PrintAndLogEx(ERR, "Bad parity (%1u)", data[15] & 0x01); + return ret; } - return PM3_ESOFT; - } - /* Index map E E - preamble enc tag type encrypted uid P d 33 d 90 d 04 d 71 d 40 d 45 d E7 P - 1111111110 00101101000001011010001100100100001011010100110101100 1 0 00110011 0 10010000 0 00000100 0 01110001 0 01000000 0 01000101 0 11100111 1 - uid2 uid1 uid0 I I R R - 1111111110 00101101000001011010001100100100001011010100110101100 1 + // validation + if ((data[8] & 0x80) + && (data[9] & 0x40) + && (data[10] & 0x20) + && (data[11] & 0x10) + && (data[12] & 0x08) + && (data[13] & 0x04) + && (data[14] & 0x02)) { + PrintAndLogEx(ERR, "Bad zeros"); + return ret; + } - 0 00110011 - 0 10010000 - 0 00000100 - 0 01110001 - 0 01000000 - 0 01000101 - 0 11100111 - 1 + // + r4 = (data[8] >> 3) & 0x0F; + r5 = ((data[8] << 1) & 0x0F) | (data[9] >> 7); + r2 = (data[9] >> 2) & 0x0F; + r3 = ((data[9] << 2) & 0x0F) | (data[10] >> 6); + r0 = ((data[10] >> 1) & 0x0F); + r1 = ((data[10] << 3) & 0x0F) | (data[11] >> 5); - Tag ID is 049033 - I = Identical on all tags - R = Random ? - UID2, UID1, UID0 == card number + fixed0 = ((data[11] << 4) & 0xF0) | (data[12] >> 4); + fixed1 = ((data[12] << 5) & 0xE0) | (data[13] >> 3); - */ - //get raw ID before removing parities - uint32_t raw[4] = {0, 0, 0, 0}; - raw[0] = bytebits_to_byte(DemodBuffer + idx + 96, 32); - raw[1] = bytebits_to_byte(DemodBuffer + idx + 64, 32); - raw[2] = bytebits_to_byte(DemodBuffer + idx + 32, 32); - raw[3] = bytebits_to_byte(DemodBuffer + idx, 32); - setDemodBuff(DemodBuffer, 128, idx); - setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock)); + unk1 = ((data[13] << 6) & 0xC0) | (data[14] >> 2); + unk2 = ((data[14] << 7) & 0xC0) | (data[15] >> 1); - uint8_t firstParity = GetParity(DemodBuffer, EVEN, 63); - if (firstParity != DemodBuffer[63]) { - PrintAndLogEx(DEBUG, "DEBUG: Error - Nedap 1st 64bit parity check failed: %d|%d ", DemodBuffer[63], firstParity); - return PM3_ESOFT; - } + // validation 2 + if (!r0 && (r1 < 10) && (r2 < 10) && (r3 < 10) && (r4 < 10) && (r5 < 10)) { - uint8_t secondParity = GetParity(DemodBuffer + 64, EVEN, 63); - if (secondParity != DemodBuffer[127]) { - PrintAndLogEx(DEBUG, "DEBUG: Error - Nedap 2st 64bit parity check failed: %d|%d ", DemodBuffer[127], secondParity); - return PM3_ESOFT; - } + badgeId = r1 * 10000 + r2 * 1000 + r3 * 100 + r4 * 10 + r5; + PrintAndLogEx(SUCCESS, "Second Card Id " _YELLOW_("%05u"), badgeId); - // ok valid card found! - uint32_t uid = 0; - uid = bytebits_to_byte(DemodBuffer + 65, 8); - uid |= bytebits_to_byte(DemodBuffer + 74, 8) << 8; - uid |= bytebits_to_byte(DemodBuffer + 83, 8) << 16; + if ((fixed0 == FIXED_71) && (fixed1 == FIXED_40)) + PrintAndLogEx(DEBUG, "Fixed part {0 = 0x%02x, 1 = 0x%02x}", fixed0, fixed1); + else + PrintAndLogEx(DEBUG, "Bad fixed: {0 = 0x%02x (%0x02x), 1 = 0x%02x (%0x02x)}", fixed0, FIXED_71, fixed1, FIXED_40); - uint16_t two = 0; - two = bytebits_to_byte(DemodBuffer + 92, 8); - two |= bytebits_to_byte(DemodBuffer + 101, 8) << 8; - - uint16_t chksum2 = 0; - chksum2 = bytebits_to_byte(DemodBuffer + 110, 8); - chksum2 |= bytebits_to_byte(DemodBuffer + 119, 8) << 8; - - PrintAndLogEx(SUCCESS, "NEDAP ID Found - Raw: %08x%08x%08x%08x", raw[3], raw[2], raw[1], raw[0]); - PrintAndLogEx(SUCCESS, " - UID: %06X", uid); - PrintAndLogEx(SUCCESS, " - i: %04X", two); - PrintAndLogEx(SUCCESS, " - Checksum2 %04X", chksum2); - - if (g_debugMode) { - PrintAndLogEx(DEBUG, "DEBUG: idx: %d, Len: %d, Printing Demod Buffer:", idx, 128); - printDemodBuff(); - PrintAndLogEx(DEBUG, "BIN:\n%s", sprint_bin_break(DemodBuffer, 128, 64)); + PrintAndLogEx(DEBUG, "Unknown part {1 = 0x%02x, 2 = 0x%02x}", unk1, unk2); + } else { + PrintAndLogEx(ERR, "Bad digits (0:%1x - 1:%1x - 2:%1x - 3:%1x - 4:%1x - 5:%1x)", r0, r1, r2, r3, r4, r5); + return ret; + } } return PM3_SUCCESS; } -/* + +/* Index map E E + preamble enc tag type encrypted uid P d 33 d 90 d 04 d 71 d 40 d 45 d E7 P + 1111111110 00101101000001011010001100100100001011010100110101100 1 0 00110011 0 10010000 0 00000100 0 01110001 0 01000000 0 01000101 0 11100111 1 + uid2 uid1 uid0 I I R R + 1111111110 00101101000001011010001100100100001011010100110101100 1 + + 0 00110011 + 0 10010000 + 0 00000100 + 0 01110001 + 0 01000000 + 0 01000101 + 0 11100111 + 1 + + Tag ID is 049033 + I = Identical on all tags + R = Random ? + UID2, UID1, UID0 == card number + + configuration lf t55xx wr b 0 d 00170082 @@ -163,51 +300,181 @@ lf t55xx wr b 4 d 4c0003ff */ static int CmdLFNedapRead(const char *Cmd) { - lf_read(true, 12000); + lf_read(true, 16000); return CmdLFNedapDemod(Cmd); } -/* -static int CmdLFNedapClone(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_nedap_clone(); +static void NedapGen(uint8_t subType, uint16_t customerCode, uint32_t id, bool isLong, uint8_t *data) { // 8 or 16 + uint8_t buffer[7], r1, r2, r3, r4, r5, idxC1, idxC2, idxC3, idxC4, idxC5, i, tmp, carry, id2, id1, id0; + uint16_t checksum; - uint32_t cardnumber=0, cn = 0; - uint32_t blocks[5]; - uint8_t bits[128]; - memset(bits, 0x00, sizeof(bits)); + r1 = (uint8_t)(id / 10000); + r2 = (uint8_t)((id % 10000) / 1000); + r3 = (uint8_t)((id % 1000) / 100); + r4 = (uint8_t)((id % 100) / 10); + r5 = (uint8_t)(id % 10); - if (sscanf(Cmd, "%u", &cn ) != 1) return usage_lf_nedap_clone(); + // first part + idxC1 = r1; + idxC2 = (idxC1 + 1 + r2) % 10; + idxC3 = (idxC2 + 1 + r3) % 10; + idxC4 = (idxC3 + 1 + r4) % 10; + idxC5 = (idxC4 + 1 + r5) % 10; - cardnumber = (cn & 0x00FFFFFF); + buffer[0] = 0xc0 | (subType & 0x0F); + buffer[1] = (customerCode & 0x0FF0) >> 4; + buffer[2] = ((customerCode & 0x000F) << 4) | translateTable[idxC1]; + buffer[3] = (translateTable[idxC2] << 4) | translateTable[idxC3]; + buffer[4] = (translateTable[idxC4] << 4) | translateTable[idxC5]; - if ( getNedapBits(cardnumber, bits) == PM3_SUCCESS ) { + // checksum + init_table(CRC_XMODEM); + checksum = crc16_xmodem(buffer, 5); + + buffer[6] = ((checksum & 0x000F) << 4) | (buffer[4] & 0x0F); + buffer[5] = (checksum & 0x00F0) | ((buffer[4] & 0xF0) >> 4); + buffer[4] = ((checksum & 0x0F00) >> 4) | (buffer[3] & 0x0F); + buffer[3] = ((checksum & 0xF000) >> 8) | ((buffer[3] & 0xF0) >> 4); + + // carry calc + for (i = 0, carry = 0; i < sizeof(buffer); i++) { + tmp = buffer[sizeof(buffer) - 1 - i]; + data[7 - i] = ((tmp & 0x7F) << 1) | carry; + carry = (tmp & 0x80) >> 7; + } + data[0] = 0xFE | carry; + data[7] |= isEven_64_63(data); + + // second part + if (isLong) { + id0 = r1; + id1 = (r2 << 4) | r3; + id2 = (r4 << 4) | r5; + + data[8] = (id2 >> 1); + data[9] = ((id2 & 0x01) << 7) | (id1 >> 2); + data[10] = ((id1 & 0x03) << 6) | (id0 >> 3); + data[11] = ((id0 & 0x07) << 5) | (FIXED_71 >> 4); + data[12] = ((FIXED_71 & 0x0F) << 4) | (FIXED_40 >> 5); + data[13] = ((FIXED_40 & 0x1F) << 3) | (UNKNOWN_A >> 6); + data[14] = ((UNKNOWN_A & 0x3F) << 2) | (UNKNOWN_B >> 7); + data[15] = ((UNKNOWN_B & 0x7F) << 1); + data[15] |= isEven_64_63(data + 8); + } +} + +static int (*usage_to_be_displayed)(void) = NULL; + +static int CmdLfNedapGen(const char *Cmd) { + uint8_t cmdp = 0, subType = 5, data[16], i, bin[128]; + uint16_t customerCode = 0; + uint32_t id = 0; + bool isLong = false, errors = false; + + int (*usage)(void) = usage_lf_nedap_gen; + if (usage_to_be_displayed != NULL) { + usage = usage_to_be_displayed; + usage_to_be_displayed = NULL; + } + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 's': + subType = param_get8ex(Cmd, cmdp + 1, 5, 10); + cmdp += 2; + break; + case 'c': + customerCode = param_get32ex(Cmd, cmdp + 1, 0, 16); + cmdp += 2; + break; + case 'i': + id = param_get32ex(Cmd, cmdp + 1, 0, 10); + cmdp += 2; + break; + case 'l': + isLong = true; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + //Validations + if ((!customerCode) || (!id) || (subType > 0xF) || (customerCode > 0xFFF) || (id > 99999)) + errors = true; + + if (errors || cmdp == 0) { + usage(); + return PM3_EINVARG; + } + + PrintAndLogEx(SUCCESS, + "Tag - subtype: %1u , customer code: %03x , ID: %05u | %s" + , subType + , customerCode + , id + , isLong ? "(128b)" : "(64b)" + ); + + NedapGen(subType, customerCode, id, isLong, data); + + for (i = 0; i < (isLong ? 16 : 8); i++) + num_to_bytebits(data[i], 8, bin + i * 8); + + setDemodBuff(bin, (isLong ? 128 : 64), 0); + return PM3_SUCCESS; +} + +int CmdLFNedapClone(const char *Cmd) { + uint8_t max; + uint32_t blocks[5] = {0}; + + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_nedap_clone(); + + usage_to_be_displayed = usage_lf_nedap_clone; + + int ret = CmdLfNedapGen(Cmd); + if (ret != PM3_SUCCESS) + return ret; + + if ((DemodBufferLen != 128) && (DemodBufferLen != 64)) { PrintAndLogEx(ERR, "Error with tag bitstream generation."); return PM3_ESOFT; } - ((ASK/DIphase data rawdemod ab 0 64 1 0 + CmdPrintDemodBuff("x"); + +// What we had before in commented code: //NEDAP - compat mode, ASK/DIphase, data rate 64, 4 data blocks - // DI-pahse (CDP) T55x7_MODULATION_DIPHASE - blocks[0] = T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_64 | 7 << T55x7_MAXBLOCK_SHIFT; + // DI-phase (CDP) T55x7_MODULATION_DIPHASE +// blocks[0] = T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_64 | 7 << T55x7_MAXBLOCK_SHIFT; +// if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q') +// blocks[0] = T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 7 <encoding = 2; payload->invert = 1; payload->separator = 0; payload->clock = 64; - memcpy(payload->data, bs, sizeof(bs)); + memcpy(payload->data, DemodBuffer, DemodBufferLen); clearCommandBuffer(); - SendCommandNG(CMD_ASK_SIM_TAG, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs)); + SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + DemodBufferLen); free(payload); PacketResponseNG resp; - WaitForResponse(CMD_ASK_SIM_TAG, &resp); + WaitForResponse(CMD_LF_ASK_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) return resp.status; - return PM3_SUCCESS; -} -static int CmdLFNedapChk(const char *Cmd) { - //301600714021BE - uint8_t data[256] = { 0x30, 0x16, 0x00, 0x71, 0x40, 0x21, 0xBE}; - int len = 0; - param_gethex_ex(Cmd, 0, data, &len); - - len = (len == 0) ? 5 : len >> 1; - - PrintAndLogEx(SUCCESS, "Input: [%d] %s", len, sprint_hex(data, len)); - - //uint8_t last = GetParity(data, EVEN, 62); - //PrintAndLogEx(NORMAL, "TEST PARITY:: %d | %d ", DemodBuffer[62], last); - - uint8_t cl = 0x1D, ch = 0x1D; - - for (int i = len; i >= 0; --i) { - uint8_t al = data[i]; - for (int j = 8; j > 0; --j) { - - uint8_t bl = al ^ ch; - //PrintAndLogEx(NORMAL, "BL %02x | CH %02x \n", al, ch); - - uint8_t carry = (cl & 0x80) ? 1 : 0; - cl <<= 1; - - uint8_t temp = (ch & 0x80) ? 1 : 0; - ch = (ch << 1) | carry; - carry = temp; - - carry = (al & 0x80) ? 1 : 0; - al <<= 1; - - carry = (bl & 0x80) ? 1 : 0; -// bl <<= 1; - - if (carry) { - cl ^= 0x21; - ch ^= 0x10; - } - } - } - - PrintAndLogEx(SUCCESS, "Nedap checksum: 0x%X", ((ch << 8) | cl)); return PM3_SUCCESS; } static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "this help"}, - {"demod", CmdLFNedapDemod, AlwaysAvailable, "demodulate an Nedap tag from the GraphBuffer"}, - {"read", CmdLFNedapRead, IfPm3Lf, "attempt to read and extract tag data"}, -// {"clone", CmdLFNedapClone, IfPm3Lf, " clone nedap tag"}, - {"sim", CmdLFNedapSim, IfPm3Lf, "simulate nedap tag"}, - {"chk", CmdLFNedapChk, AlwaysAvailable, "calculate Nedap Checksum "}, + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"demod", CmdLFNedapDemod, AlwaysAvailable, "Demodulate Nedap tag from the GraphBuffer"}, + {"generate", CmdLfNedapGen, AlwaysAvailable, "Generate Nedap bitstream in DemodBuffer"}, + {"read", CmdLFNedapRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"}, + {"clone", CmdLFNedapClone, IfPm3Lf, "Clone Nedap tag to T55x7"}, + {"sim", CmdLFNedapSim, IfPm3Lf, "Simulate Nedap tag"}, {NULL, NULL, NULL, NULL} }; @@ -338,72 +559,6 @@ int CmdLFNedap(const char *Cmd) { return CmdsParse(CommandTable, Cmd); } -// find nedap preamble in already demoded data -int detectNedap(uint8_t *dest, size_t *size) { - //make sure buffer has data - if (*size < 128) return -3; - - size_t startIdx = 0; - //uint8_t preamble[] = {1,1,1,1,1,1,1,1,1,0,0,0,1}; - uint8_t preamble[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 0}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) - return -4; //preamble not found - return (int) startIdx; -} - -int getNedapBits(uint32_t cn, uint8_t *nedapBits) { - - uint8_t pre[128]; - memset(pre, 0x00, sizeof(pre)); - - // preamble 1111 1111 10 = 0xFF8 - num_to_bytebits(0xFF8, 12, pre); - - // fixed tagtype code? 0010 1101 = 0x2D - num_to_bytebits(0x2D, 8, pre + 10); - - // 46 encrypted bits - UNKNOWN ALGO - // -- 16 bits checksum. Should be 4x4 checksum, based on UID and 2 constant values. - // -- 30 bits undocumented? - //num_to_bytebits(cn, 46, pre+18); - - //----from this part, the UID in clear text, with a 1bit ZERO as separator between bytes. - pre[64] = 0; - pre[73] = 0; - pre[82] = 0; - pre[91] = 0; - pre[100] = 0; - pre[109] = 0; - pre[118] = 0; - - // cardnumber (uid) - num_to_bytebits((cn >> 0) & 0xFF, 8, pre + 65); - num_to_bytebits((cn >> 8) & 0xFF, 8, pre + 74); - num_to_bytebits((cn >> 16) & 0xFF, 8, pre + 83); - - // two ? - num_to_bytebits(0, 8, pre + 92); - num_to_bytebits(0, 8, pre + 101); - - // chksum - num_to_bytebits((0 >> 0) & 0xFF, 8, pre + 110); - num_to_bytebits((0 >> 8) & 0xFF, 8, pre + 119); - - pre[63] = GetParity(pre, EVEN, 63); - pre[127] = GetParity(pre + 64, EVEN, 63); - - memcpy(nedapBits, pre, 128); - - // 1111111110001011010000010110100011001001000010110101001101011001000110011010010000000000100001110001001000000001000101011100111 - return PM3_SUCCESS; -} -/* - - UID: 001630 - - i: 4071 - - Checksum2 BE21 -*/ -//GetParity( uint8_t *bits, uint8_t type, int length) - int demodNedap(void) { return CmdLFNedapDemod(""); } diff --git a/client/cmdlfnedap.h b/client/cmdlfnedap.h index 8ba7c9908..fda0e130e 100644 --- a/client/cmdlfnedap.h +++ b/client/cmdlfnedap.h @@ -8,19 +8,8 @@ //----------------------------------------------------------------------------- #ifndef CMDLFNEDAP_H__ #define CMDLFNEDAP_H__ -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdmain.h" -#include "cmdlf.h" -#include "protocols.h" // for T55xx config register definitions -#include "lfdemod.h" // parityTest -#include "crc.h" + +#include "common.h" int CmdLFNedap(const char *Cmd); diff --git a/client/cmdlfnexwatch.c b/client/cmdlfnexwatch.c index e543dd635..bad9dea4f 100644 --- a/client/cmdlfnexwatch.c +++ b/client/cmdlfnexwatch.c @@ -10,6 +10,13 @@ #include "cmdlfnexwatch.h" +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "cmddata.h" // preamblesearch +#include "cmdlf.h" +#include "lfdemod.h" + static int CmdHelp(const char *Cmd); static int CmdNexWatchDemod(const char *Cmd) { diff --git a/client/cmdlfnexwatch.h b/client/cmdlfnexwatch.h index 4a70761a4..a282a320e 100644 --- a/client/cmdlfnexwatch.h +++ b/client/cmdlfnexwatch.h @@ -9,18 +9,7 @@ #ifndef CMDLFNEXWATCH_H__ #define CMDLFNEXWATCH_H__ -#include -#include -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" // preamblesearch -#include "cmdlf.h" -#include "lfdemod.h" +#include "common.h" int CmdLFNEXWATCH(const char *Cmd); diff --git a/client/cmdlfnoralsy.c b/client/cmdlfnoralsy.c index 34ad1023f..cc1db82ca 100644 --- a/client/cmdlfnoralsy.c +++ b/client/cmdlfnoralsy.c @@ -9,6 +9,18 @@ //----------------------------------------------------------------------------- #include "cmdlfnoralsy.h" +#include +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // parityTest + static int CmdHelp(const char *Cmd); static int usage_lf_noralsy_clone(void) { @@ -131,8 +143,8 @@ static int CmdNoralsyClone(const char *Cmd) { uint8_t bits[96]; memset(bits, 0, sizeof(bits)); - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_noralsy_clone(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_noralsy_clone(); id = param_get32ex(Cmd, 0, 0, 10); year = param_get32ex(Cmd, 1, 2000, 10); @@ -170,8 +182,8 @@ static int CmdNoralsyClone(const char *Cmd) { ng.blockno = i; ng.flags = 0; - SendCommandNG(CMD_T55XX_WRITE_BLOCK, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_T55XX_WRITE_BLOCK, &resp, T55XX_WRITE_TIMEOUT)) { + SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); + if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); return PM3_ETIMEOUT; } @@ -187,8 +199,8 @@ static int CmdNoralsySim(const char *Cmd) { uint16_t year = 0; uint32_t id = 0; - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_noralsy_sim(); id = param_get32ex(Cmd, 0, 0, 10); @@ -209,15 +221,16 @@ static int CmdNoralsySim(const char *Cmd) { memcpy(payload->data, bs, sizeof(bs)); clearCommandBuffer(); - SendCommandNG(CMD_ASK_SIM_TAG, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs)); + SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs)); free(payload); PacketResponseNG resp; - WaitForResponse(CMD_ASK_SIM_TAG, &resp); + WaitForResponse(CMD_LF_ASK_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) return resp.status; + return PM3_SUCCESS; } diff --git a/client/cmdlfnoralsy.h b/client/cmdlfnoralsy.h index b5a5cd914..f76accab7 100644 --- a/client/cmdlfnoralsy.h +++ b/client/cmdlfnoralsy.h @@ -8,19 +8,8 @@ //----------------------------------------------------------------------------- #ifndef CMDLFNORALSY_H__ #define CMDLFNORALSY_H__ -#include -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdmain.h" -#include "cmdlf.h" -#include "protocols.h" // for T55xx config register definitions -#include "lfdemod.h" // parityTest + +#include "common.h" int CmdLFNoralsy(const char *Cmd); diff --git a/client/cmdlfpac.c b/client/cmdlfpac.c index b9d6f1449..864506089 100644 --- a/client/cmdlfpac.c +++ b/client/cmdlfpac.c @@ -9,6 +9,13 @@ //----------------------------------------------------------------------------- #include "cmdlfpac.h" +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "lfdemod.h" // preamble test + static int CmdHelp(const char *Cmd); //see NRZDemod for what args are accepted diff --git a/client/cmdlfpac.h b/client/cmdlfpac.h index f076121cd..3c9c4fbda 100644 --- a/client/cmdlfpac.h +++ b/client/cmdlfpac.h @@ -9,17 +9,7 @@ #ifndef CMDLFPAC_H__ #define CMDLFPAC_H__ -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdmain.h" -#include "cmdlf.h" -#include "lfdemod.h" // preamble test +#include "common.h" int CmdLFPac(const char *Cmd); diff --git a/client/cmdlfparadox.c b/client/cmdlfparadox.c index c5c022d9b..8a1a940c5 100644 --- a/client/cmdlfparadox.c +++ b/client/cmdlfparadox.c @@ -7,15 +7,17 @@ // Low frequency Paradox tag commands // FSK2a, rf/50, 96 bits (completely known) //----------------------------------------------------------------------------- +#include "cmdlfparadox.h" + #include #include -#include -#include "cmdlfparadox.h" -#include "proxmark3.h" +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" #include "ui.h" -#include "util.h" #include "graph.h" -#include "cmdparser.h" #include "cmddata.h" #include "cmdlf.h" #include "lfdemod.h" @@ -142,11 +144,11 @@ static int CmdParadoxSim(const char *Cmd) { memcpy(payload->data, bs, sizeof(bs)); clearCommandBuffer(); - SendCommandNG(CMD_FSK_SIM_TAG, (uint8_t *)payload, sizeof(lf_fsksim_t) + sizeof(bs)); + SendCommandNG(CMD_LF_FSK_SIMULATE, (uint8_t *)payload, sizeof(lf_fsksim_t) + sizeof(bs)); free(payload); PacketResponseNG resp; - WaitForResponse(CMD_FSK_SIM_TAG, &resp); + WaitForResponse(CMD_LF_FSK_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) diff --git a/client/cmdlfparadox.h b/client/cmdlfparadox.h index f7f4a4ffe..34c3cb6cd 100644 --- a/client/cmdlfparadox.h +++ b/client/cmdlfparadox.h @@ -8,6 +8,9 @@ //----------------------------------------------------------------------------- #ifndef CMDLFPARADOX_H__ #define CMDLFPARADOX_H__ + +#include "common.h" + int CmdLFParadox(const char *Cmd); int demodParadox(void); diff --git a/client/cmdlfpcf7931.c b/client/cmdlfpcf7931.c index c9f5711ef..e4a14a47e 100644 --- a/client/cmdlfpcf7931.c +++ b/client/cmdlfpcf7931.c @@ -8,18 +8,14 @@ //----------------------------------------------------------------------------- // Low frequency PCF7931 commands //----------------------------------------------------------------------------- -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdmain.h" -#include "cmdlf.h" #include "cmdlfpcf7931.h" +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" + static int CmdHelp(const char *Cmd); #define PCF7931_DEFAULT_INITDELAY 17500 @@ -101,7 +97,7 @@ static int CmdLFPCF7931Read(const char *Cmd) { PacketResponseNG resp; clearCommandBuffer(); - SendCommandNG(CMD_PCF7931_READ, NULL, 0); + SendCommandNG(CMD_LF_PCF7931_READ, NULL, 0); if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { PrintAndLogEx(WARNING, "command execution time out"); return 1; @@ -151,7 +147,7 @@ static int CmdLFPCF7931Write(const char *Cmd) { buf[9] = configPcf.InitDelay; clearCommandBuffer(); - SendCommandOLD(CMD_PCF7931_WRITE, block, bytepos, data, buf, sizeof(buf)); + SendCommandOLD(CMD_LF_PCF7931_WRITE, block, bytepos, data, buf, sizeof(buf)); //no ack? return 0; } diff --git a/client/cmdlfpcf7931.h b/client/cmdlfpcf7931.h index 419386956..4f84085b2 100644 --- a/client/cmdlfpcf7931.h +++ b/client/cmdlfpcf7931.h @@ -12,6 +12,8 @@ #ifndef CMDLFPCF7931_H__ #define CMDLFPCF7931_H__ +#include "common.h" + struct pcf7931_config { uint8_t Pwd[7]; uint16_t InitDelay; diff --git a/client/cmdlfpresco.c b/client/cmdlfpresco.c index 3f1ce71f3..14d87648e 100644 --- a/client/cmdlfpresco.c +++ b/client/cmdlfpresco.c @@ -8,6 +8,20 @@ //----------------------------------------------------------------------------- #include "cmdlfpresco.h" + +#include +#include +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // parityTest + static int CmdHelp(const char *Cmd); static int usage_lf_presco_clone(void) { @@ -136,8 +150,8 @@ static int CmdPrescoClone(const char *Cmd) { ng.blockno = i; ng.flags = 0; - SendCommandNG(CMD_T55XX_WRITE_BLOCK, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_T55XX_WRITE_BLOCK, &resp, T55XX_WRITE_TIMEOUT)) { + SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); + if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); return PM3_ETIMEOUT; } @@ -167,11 +181,11 @@ static int CmdPrescoSim(const char *Cmd) { memcpy(payload->data, bs, sizeof(bs)); clearCommandBuffer(); - SendCommandNG(CMD_ASK_SIM_TAG, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs)); + SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs)); free(payload); PacketResponseNG resp; - WaitForResponse(CMD_ASK_SIM_TAG, &resp); + WaitForResponse(CMD_LF_ASK_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) diff --git a/client/cmdlfpresco.h b/client/cmdlfpresco.h index 1f101a13c..098a98342 100644 --- a/client/cmdlfpresco.h +++ b/client/cmdlfpresco.h @@ -8,18 +8,8 @@ //----------------------------------------------------------------------------- #ifndef CMDLFPRESCO_H__ #define CMDLFPRESCO_H__ -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdmain.h" -#include "cmdlf.h" -#include "protocols.h" // for T55xx config register definitions -#include "lfdemod.h" // parityTest + +#include "common.h" int CmdLFPresco(const char *Cmd); diff --git a/client/cmdlfpyramid.c b/client/cmdlfpyramid.c index 4e5588ec6..d5c3076a9 100644 --- a/client/cmdlfpyramid.c +++ b/client/cmdlfpyramid.c @@ -9,6 +9,21 @@ //----------------------------------------------------------------------------- #include "cmdlfpyramid.h" +#include +#include +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "graph.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // parityTest +#include "crc.h" + static int CmdHelp(const char *Cmd); static int usage_lf_pyramid_clone(void) { @@ -247,8 +262,8 @@ static int CmdPyramidClone(const char *Cmd) { ng.blockno = i; ng.flags = 0; - SendCommandNG(CMD_T55XX_WRITE_BLOCK, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_T55XX_WRITE_BLOCK, &resp, T55XX_WRITE_TIMEOUT)) { + SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); + if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); return PM3_ETIMEOUT; } @@ -287,11 +302,11 @@ static int CmdPyramidSim(const char *Cmd) { memcpy(payload->data, bs, sizeof(bs)); clearCommandBuffer(); - SendCommandNG(CMD_FSK_SIM_TAG, (uint8_t *)payload, sizeof(lf_fsksim_t) + sizeof(bs)); + SendCommandNG(CMD_LF_FSK_SIMULATE, (uint8_t *)payload, sizeof(lf_fsksim_t) + sizeof(bs)); free(payload); PacketResponseNG resp; - WaitForResponse(CMD_FSK_SIM_TAG, &resp); + WaitForResponse(CMD_LF_FSK_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) diff --git a/client/cmdlfpyramid.h b/client/cmdlfpyramid.h index 009bec3ce..2d717fbb3 100644 --- a/client/cmdlfpyramid.h +++ b/client/cmdlfpyramid.h @@ -8,19 +8,8 @@ //----------------------------------------------------------------------------- #ifndef CMDLFPYRAMID_H__ #define CMDLFPYRAMID_H__ -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdmain.h" -#include "cmdlf.h" -#include "protocols.h" // for T55xx config register definitions -#include "lfdemod.h" // parityTest -#include "crc.h" + +#include "common.h" int CmdLFPyramid(const char *Cmd); diff --git a/client/cmdlfsecurakey.c b/client/cmdlfsecurakey.c index 82df3b659..0ee22524f 100644 --- a/client/cmdlfsecurakey.c +++ b/client/cmdlfsecurakey.c @@ -9,6 +9,16 @@ //----------------------------------------------------------------------------- #include "cmdlfsecurakey.h" +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "lfdemod.h" // preamble test +#include "parity.h" // for wiegand parity test + static int CmdHelp(const char *Cmd); //see ASKDemod for what args are accepted diff --git a/client/cmdlfsecurakey.h b/client/cmdlfsecurakey.h index 6a84d2046..229fd0047 100644 --- a/client/cmdlfsecurakey.h +++ b/client/cmdlfsecurakey.h @@ -9,20 +9,7 @@ #ifndef CMDLFSECURAKEY_H__ #define CMDLFSECURAKEY_H__ -#include -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdmain.h" -#include "cmdlf.h" -#include "protocols.h" // for T55xx config register definitions -#include "lfdemod.h" // preamble test -#include "parity.h" // for wiegand parity test +#include "common.h" int CmdLFSecurakey(const char *Cmd); diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 3d0871893..55b711482 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -14,12 +14,27 @@ #include "cmdlft55xx.h" +#include +#include // MingW + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "commonutil.h" +#include "protocols.h" +#include "graph.h" +#include "cmddata.h" +#include "lfdemod.h" +#include "cmdhf14a.h" // for getTagInfo +#include "fileutils.h" // loadDictionary +#include "util_posix.h" + + // Some defines for readability -#define T55xx_DLMode_Fixed 0 // Default Mode -#define T55xx_DLMode_LLR 1 // Long Leading Reference -#define T55xx_DLMode_Leading0 2 // Leading Zero -#define T55xx_DLMode_1of4 3 // 1 of 4 -#define T55xx_LongLeadingReference 4 // Value to tell Write Bit to send long reference +#define T55XX_DLMODE_FIXED 0 // Default Mode +#define T55XX_DLMODE_LLR 1 // Long Leading Reference +#define T55XX_DLMODE_LEADING_ZERO 2 // Leading Zero +#define T55XX_DLMODE_1OF4 3 // 1 of 4 +#define T55XX_LONGLEADINGREFERENCE 4 // Value to tell Write Bit to send long reference // Default configuration t55xx_conf_block_t config = { .modulation = DEMOD_ASK, .inverted = false, .offset = 0x00, .block0 = 0x00, .Q5 = false }; @@ -31,6 +46,14 @@ void Set_t55xx_Config(t55xx_conf_block_t conf) { config = conf; } +static void print_usage_t55xx_downloadlink(void) { + PrintAndLogEx(NORMAL, " r - downlink encoding 0|1|2|3"); + PrintAndLogEx(NORMAL, " 0 - fixed bit length (default)"); + PrintAndLogEx(NORMAL, " 1 - long leading reference"); + PrintAndLogEx(NORMAL, " 2 - leading zero"); + PrintAndLogEx(NORMAL, " 3 - 1 of 4 coding reference"); +} + static int usage_t55xx_config() { PrintAndLogEx(NORMAL, "Usage: lf t55xx config [d ] [i [0/1]] [o ] [Q5 [0/1]] [ST [0/1]]"); PrintAndLogEx(NORMAL, "Options:"); @@ -55,9 +78,8 @@ static int usage_t55xx_read() { PrintAndLogEx(NORMAL, " b - block number to read. Between 0-7"); PrintAndLogEx(NORMAL, " p - OPTIONAL password (8 hex characters)"); PrintAndLogEx(NORMAL, " o - OPTIONAL override safety check"); - PrintAndLogEx(NORMAL, " 1 - OPTIONAL read Page 1 instead of Page 0"); - PrintAndLogEx(NORMAL, " r - downlink encoding '0' fixed bit length (default), '1' long leading ref."); - PrintAndLogEx(NORMAL, " '2' leading zero, '3' 1 of 4 coding ref."); + PrintAndLogEx(NORMAL, " 1 - OPTIONAL 0|1 read Page 1 instead of Page 0"); + print_usage_t55xx_downloadlink(); PrintAndLogEx(NORMAL, " ****WARNING****"); PrintAndLogEx(NORMAL, " Use of read with password on a tag not configured for a pwd"); PrintAndLogEx(NORMAL, " can damage the tag"); @@ -77,8 +99,7 @@ static int usage_t55xx_write() { PrintAndLogEx(NORMAL, " p - OPTIONAL password 4bytes (8 hex characters)"); PrintAndLogEx(NORMAL, " 1 - OPTIONAL write Page 1 instead of Page 0"); PrintAndLogEx(NORMAL, " t - OPTIONAL test mode write - ****DANGER****"); - PrintAndLogEx(NORMAL, " r - downlink encoding '0' fixed bit length (default), '1' long leading ref."); - PrintAndLogEx(NORMAL, " '2' leading zero, '3' 1 of 4 coding ref."); + print_usage_t55xx_downloadlink(); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf t55xx write b 3 d 11223344 - write 11223344 to block 3"); @@ -89,8 +110,7 @@ static int usage_t55xx_write() { static int usage_t55xx_trace() { PrintAndLogEx(NORMAL, "Usage: lf t55xx trace [r mode]"); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " r - downlink encoding '0' fixed bit length (default), '1' long leading ref."); - PrintAndLogEx(NORMAL, " '2' leading zero, '3' 1 of 4 coding ref."); + print_usage_t55xx_downloadlink(); // Command did not seem to support the 1 option (yet) so have removed the help lines // PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag."); PrintAndLogEx(NORMAL, ""); @@ -108,8 +128,7 @@ static int usage_t55xx_info() { PrintAndLogEx(NORMAL, " d - 4 bytes of data (8 hex characters)"); PrintAndLogEx(NORMAL, " if set, use these data instead of reading tag."); PrintAndLogEx(NORMAL, " q - if set, provided data are interpreted as Q5 config."); - PrintAndLogEx(NORMAL, " r - downlink encoding '0' fixed bit length (default), '1' long leading ref."); - PrintAndLogEx(NORMAL, " '2' leading zero, '3' 1 of 4 coding ref."); + print_usage_t55xx_downloadlink(); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf t55xx info"); @@ -124,8 +143,7 @@ static int usage_t55xx_dump() { PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " - OPTIONAL password 4bytes (8 hex symbols)"); PrintAndLogEx(NORMAL, " o - OPTIONAL override, force pwd read despite danger to card"); - PrintAndLogEx(NORMAL, " r - downlink encoding '0' fixed bit length (default), '1' long leading ref."); - PrintAndLogEx(NORMAL, " '2' leading zero, '3' 1 of 4 coding ref."); + print_usage_t55xx_downloadlink(); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf t55xx dump"); @@ -138,9 +156,7 @@ static int usage_t55xx_detect() { PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag."); PrintAndLogEx(NORMAL, " p - downlink encoding '0' fixed bit length (default)"); - PrintAndLogEx(NORMAL, " '1' long leading ref., '2' leading zero "); - PrintAndLogEx(NORMAL, " '3' 1 of 4 coding ref., '4' try all modes"); + print_usage_t55xx_downloadlink(); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf t55xx detect"); @@ -155,9 +171,7 @@ static int usage_t55xx_detectP1() { PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag."); PrintAndLogEx(NORMAL, " p - OPTIONAL password (8 hex characters)"); - PrintAndLogEx(NORMAL, " r - downlink encoding '0' fixed bit length (default)"); - PrintAndLogEx(NORMAL, " '1' long leading ref., '2' leading zero "); - PrintAndLogEx(NORMAL, " '3' 1 of 4 coding ref., '4' try all modes"); + print_usage_t55xx_downloadlink(); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf t55xx p1detect"); @@ -172,8 +186,7 @@ static int usage_t55xx_wakup() { PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - this help"); PrintAndLogEx(NORMAL, " p - password 4bytes (8 hex symbols)"); - PrintAndLogEx(NORMAL, " r - downlink encoding '0' fixed bit length (default), '1' long leading ref."); - PrintAndLogEx(NORMAL, " '2' leading zero, '3' 1 of 4 coding ref."); + print_usage_t55xx_downloadlink(); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf t55xx wakeup p 11223344 - send wakeup password"); @@ -188,14 +201,12 @@ static int usage_t55xx_chk() { PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - this help"); PrintAndLogEx(NORMAL, " m - use dictionary from flashmemory\n"); - PrintAndLogEx(NORMAL, " r - downlink encoding '0' fixed bit length (default)"); - PrintAndLogEx(NORMAL, " '1' long leading ref., '2' leading zero "); - PrintAndLogEx(NORMAL, " '3' 1 of 4 coding ref., '4' try all modes"); + print_usage_t55xx_downloadlink(); PrintAndLogEx(NORMAL, " i <*.dic> - loads a default keys dictionary file <*.dic>"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf t55xx chk m"); - PrintAndLogEx(NORMAL, " lf t55xx chk i default_pwd.dic"); + PrintAndLogEx(NORMAL, " lf t55xx chk i t55xx_default_pwds"); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -208,9 +219,7 @@ static int usage_t55xx_bruteforce() { PrintAndLogEx(NORMAL, " password must be 4 bytes (8 hex symbols)"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " r - downlink encoding '0' fixed bit length (default)"); - PrintAndLogEx(NORMAL, " '1' long leading ref., '2' leading zero "); - PrintAndLogEx(NORMAL, " '3' 1 of 4 coding ref., '4' try all modes"); + print_usage_t55xx_downloadlink(); PrintAndLogEx(NORMAL, " - 4 byte hex value to start pwd search at"); PrintAndLogEx(NORMAL, " - 4 byte hex value to end pwd search at"); PrintAndLogEx(NORMAL, ""); @@ -229,9 +238,7 @@ static int usage_t55xx_recoverpw() { PrintAndLogEx(NORMAL, " default password is 51243648, used by many cloners"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " r - downlink encoding '0' fixed bit length (default)"); - PrintAndLogEx(NORMAL, " '1' long leading ref., '2' leading zero "); - PrintAndLogEx(NORMAL, " '3' 1 of 4 coding ref., '4' try all modes"); + print_usage_t55xx_downloadlink(); PrintAndLogEx(NORMAL, " [password] - 4 byte hex value of password written by cloner"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); @@ -265,8 +272,7 @@ static int usage_lf_deviceconfig() { PrintAndLogEx(NORMAL, " f <8..255> - Set write TWO gap (1 of 4 only)"); PrintAndLogEx(NORMAL, " g <8..255> - Set write THREE gap (1 of 4 only)"); PrintAndLogEx(NORMAL, " p - persist to flashmemory"); - PrintAndLogEx(NORMAL, " r - downlink encoding '0' fixed bit length (default), '1' long leading ref."); - PrintAndLogEx(NORMAL, " '2' leading zero, '3' 1 of 4 coding ref."); + print_usage_t55xx_downloadlink(); PrintAndLogEx(NORMAL, " z - Set default t55x7 timings (use p to save if required)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); @@ -403,12 +409,12 @@ int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, uint8_t override, uin //Password mode if (usepwd) { // try reading the config block and verify that PWD bit is set before doing this! - if (!override) { + if (override == 0) { if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, false, 0, downlink_mode)) return PM3_ESOFT; if (!tryDetectModulation()) { PrintAndLogEx(NORMAL, "Safety Check: Could not detect if PWD bit is set in config block. Exits."); - return 0; + return PM3_ESOFT; } else { PrintAndLogEx(NORMAL, "Safety Check: PWD bit is NOT set in config block. Reading without password..."); usepwd = false; @@ -416,28 +422,31 @@ int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, uint8_t override, uin } } else { // Show only if first for command i.e. override = 1 (override and display) override = 2 (override and dont display) - if ((override & 2) != 2) + if (override == 1) PrintAndLogEx(NORMAL, "Safety Check Overriden - proceeding despite risk"); } } - if (!AquireData(page1, block, usepwd, password, downlink_mode)) return PM3_ESOFT; - if (!DecodeT55xxBlock()) return PM3_ESOFT; + if (!AquireData(page1, block, usepwd, password, downlink_mode)) + return PM3_ESOFT; + + if (!DecodeT55xxBlock()) + return PM3_ESOFT; printT55xxBlock(block); return PM3_SUCCESS; } static int CmdT55xxReadBlock(const char *Cmd) { - uint8_t block = REGULAR_READ_MODE_BLOCK; - uint32_t password = 0; //default to blank Block 7 - bool usepwd = false; - bool override = false; - bool page1 = false; - bool errors = false; - uint8_t cmdp = 0; - uint8_t downlink_mode = 0; + uint8_t block = REGULAR_READ_MODE_BLOCK; + uint8_t override = 0; + uint8_t cmdp = 0; + uint8_t downlink_mode = 0; + uint32_t password = 0; //default to blank Block 7 + bool usepwd = false; + bool page1 = false; + bool errors = false; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { @@ -448,7 +457,7 @@ static int CmdT55xxReadBlock(const char *Cmd) { cmdp += 2; break; case 'o': - override = true; + override = 1; cmdp++; break; case 'p': @@ -461,7 +470,6 @@ static int CmdT55xxReadBlock(const char *Cmd) { cmdp++; break; case 'r': - case 'R': downlink_mode = param_getchar(Cmd, cmdp + 1) - '0'; if (downlink_mode > 3) downlink_mode = 0; cmdp += 2; @@ -564,28 +572,25 @@ static int SanityOfflineCheck(bool useGraphBuffer) { } void T55xx_Print_DownlinkMode(uint8_t downlink_mode) { - char Msg[80]; - sprintf(Msg, "Downlink Mode used : "); + char msg[80]; + sprintf(msg, "Downlink Mode used : "); switch (downlink_mode) { - case 0 : - strcat(Msg, "default/fixed bit length"); - break; case 1 : - strcat(Msg, "long leading reference (r 1)"); + strcat(msg, _YELLOW_("long leading reference")); break; case 2 : - strcat(Msg, "leading zero reference (r 2)"); + strcat(msg, _YELLOW_("leading zero reference")); break; case 3 : - strcat(Msg, "1 of 4 coding reference (r 3)"); + strcat(msg, _YELLOW_("1 of 4 coding reference")); break; default : - strcat(Msg, "default/fixed bit length"); + strcat(msg, _YELLOW_("default/fixed bit length")); break; } - PrintAndLogEx(NORMAL, Msg); + PrintAndLogEx(NORMAL, msg); } // static int CmdT55xxDetect(const char *Cmd) { @@ -1148,7 +1153,7 @@ static int CmdT55xxWakeUp(const char *Cmd) { flags = (downlink_mode & 3) << 3; clearCommandBuffer(); - SendCommandMIX(CMD_T55XX_WAKEUP, password, flags, 0, NULL, 0); + SendCommandMIX(CMD_LF_T55XX_WAKEUP, password, flags, 0, NULL, 0); PrintAndLogEx(SUCCESS, "Wake up command sent. Try read now"); return PM3_SUCCESS; @@ -1240,8 +1245,8 @@ static int CmdT55xxWriteBlock(const char *Cmd) { ng.blockno = block; ng.flags = flags; - SendCommandNG(CMD_T55XX_WRITE_BLOCK, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_T55XX_WRITE_BLOCK, &resp, 2000)) { + SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); + if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, 2000)) { PrintAndLogEx(ERR, "Error occurred, device did not ACK write operation. (May be due to old firmware)"); return PM3_ETIMEOUT; } @@ -1650,26 +1655,27 @@ static int CmdT55xxInfo(const char *Cmd) { static int CmdT55xxDump(const char *Cmd) { - uint32_t password = 0; - uint8_t override = false; - uint8_t cmd_opt_idx = 0; - uint8_t downlink_mode = 0; - uint8_t pwd_offset = 0; - char cmdp = tolower(param_getchar(Cmd, 0)); - + uint32_t password = 0; + uint8_t override = 0; + uint8_t cmd_opt_idx = 0; + uint8_t downlink_mode = 0; + uint8_t pwd_offset = 0; + char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_t55xx_dump(); if (cmdp == 'r') { cmd_opt_idx++; downlink_mode = param_getchar(Cmd, cmd_opt_idx++) - '0'; - if (downlink_mode > 3) downlink_mode = 0; + if (downlink_mode > 3) + downlink_mode = 0; + pwd_offset = 3; } bool usepwd = (strlen(Cmd) > pwd_offset); if (usepwd) { password = param_get32ex(Cmd, cmd_opt_idx++, 0, 16); if (param_getchar(Cmd, cmd_opt_idx++) == 'o') - override = true; + override = 1; } printT5xxHeader(0); @@ -1677,7 +1683,7 @@ static int CmdT55xxDump(const char *Cmd) { T55xxReadBlock(i, 0, usepwd, override, password, downlink_mode); // idea for better user experience and display. // only show override warning on the first block read - if (override) override |= 2; // flag not to show safty for 2nd and on. + if (override == 1) override++; // flag not to show safty for 2nd and on. } printT5xxHeader(1); for (uint8_t i = 0; i < 4; i++) @@ -1708,8 +1714,8 @@ bool AquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password, ui payload.downlink_mode = downlink_mode; clearCommandBuffer(); - SendCommandNG(CMD_T55XX_READ_BLOCK, (uint8_t *)&payload, sizeof(payload)); - if (!WaitForResponseTimeout(CMD_T55XX_READ_BLOCK, NULL, 2500)) { + SendCommandNG(CMD_LF_T55XX_READBL, (uint8_t *)&payload, sizeof(payload)); + if (!WaitForResponseTimeout(CMD_LF_T55XX_READBL, NULL, 2500)) { PrintAndLogEx(WARNING, "command execution time out"); return false; } @@ -1978,7 +1984,7 @@ static int CmdResetRead(const char *Cmd) { printf("DL : %d\n", downlink_mode); flags = downlink_mode << 3; clearCommandBuffer(); - SendCommandNG(CMD_T55XX_RESET_READ, &flags, sizeof(flags)); + SendCommandNG(CMD_LF_T55XX_RESET_READ, &flags, sizeof(flags)); if (!WaitForResponseTimeout(CMD_ACK, NULL, 2500)) { PrintAndLogEx(WARNING, "command execution time out"); return PM3_ETIMEOUT; @@ -2088,7 +2094,7 @@ static int CmdT55xxChkPwds(const char *Cmd) { if (from_flash) { clearCommandBuffer(); - SendCommandNG(CMD_T55XX_CHKPWDS, &flags, sizeof(flags)); + SendCommandNG(CMD_LF_T55XX_CHK_PWDS, &flags, sizeof(flags)); PacketResponseNG resp; while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { @@ -2124,19 +2130,13 @@ static int CmdT55xxChkPwds(const char *Cmd) { if (use_pwd_file) { uint16_t keycount = 0; - size_t datalen = 0; - // TODO, a way of reallocating memory if file was larger - keyBlock = calloc(4 * 200, sizeof(uint8_t)); - if (keyBlock == NULL) { - PrintAndLogDevice(ERR, "error, cannot allocate memory "); - return PM3_ESOFT; - } - - int res = loadFileDICTIONARY(filename, keyBlock, &datalen, 4, &keycount); - if (res || keycount == 0) { + int res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock, 4, &keycount); + if (res != PM3_SUCCESS || keycount == 0 || keyBlock == NULL) { PrintAndLogEx(WARNING, "No keys found in file"); - free(keyBlock); + if (keyBlock != NULL) + free(keyBlock); + return PM3_ESOFT; } @@ -2551,12 +2551,10 @@ static int CmdT55xxDetectPage1(const char *Cmd) { } static int CmdT55xxSetDeviceConfig(const char *Cmd) { - uint8_t startgap = 0, writegap = 0, readgap = 0; - uint8_t write0 = 0, write1 = 0, write2 = 0, write3 = 0; - bool errors = false, shall_persist = false; - uint8_t cmdp = 0; - uint8_t downlink_mode = 0; - bool set_defaults = false; + uint8_t startgap = 0, writegap = 0, readgap = 0; + uint8_t write0 = 0, write1 = 0, write2 = 0, write3 = 0; + uint8_t cmdp = 0, downlink_mode = 0; + bool errors = false, shall_persist = false, set_defaults = false; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { @@ -2613,63 +2611,57 @@ static int CmdT55xxSetDeviceConfig(const char *Cmd) { //Validations if (errors || cmdp == 0) return usage_lf_deviceconfig(); - t55xx_config conf = {0}; -/* if (erase) { - memset (&conf,0xff, sizeof(conf)); - printf ("Conf.m[0] %x\n",conf.m[0].start_gap); - */ - // - if (set_defaults){ - // fixed bit length - conf.m[T55xx_DLMode_Fixed].start_gap = 29 * 8; - conf.m[T55xx_DLMode_Fixed].write_gap = 17 * 8; - conf.m[T55xx_DLMode_Fixed].write_0 = 15 * 8; - conf.m[T55xx_DLMode_Fixed].write_1 = 47 * 8; - conf.m[T55xx_DLMode_Fixed].read_gap = 15 * 8; - conf.m[T55xx_DLMode_Fixed].write_2 = 0; - conf.m[T55xx_DLMode_Fixed].write_3 = 0; - - // long leading reference - conf.m[T55xx_DLMode_LLR].start_gap = 31 * 8; - conf.m[T55xx_DLMode_LLR].write_gap = 20 * 8; - conf.m[T55xx_DLMode_LLR].write_0 = 18 * 8; - conf.m[T55xx_DLMode_LLR].write_1 = 50 * 8; - conf.m[T55xx_DLMode_LLR].read_gap = 15 * 8; - conf.m[T55xx_DLMode_LLR].write_2 = 0; - conf.m[T55xx_DLMode_LLR].write_3 = 0; - - // leading zero - conf.m[T55xx_DLMode_Leading0].start_gap = 31 * 8; - conf.m[T55xx_DLMode_Leading0].write_gap = 20 * 8; - conf.m[T55xx_DLMode_Leading0].write_0 = 18 * 8; - conf.m[T55xx_DLMode_Leading0].write_1 = 40 * 8; - conf.m[T55xx_DLMode_Leading0].read_gap = 15 * 8; - conf.m[T55xx_DLMode_Leading0].write_2 = 0; - conf.m[T55xx_DLMode_Leading0].write_3 = 0; + t55xx_configurations_t configurations = {{{0}, {0}, {0}, {0}}}; - // 1 of 4 coding reference - conf.m[T55xx_DLMode_1of4].start_gap = 29 * 8; - conf.m[T55xx_DLMode_1of4].write_gap = 17 * 8; - conf.m[T55xx_DLMode_1of4].write_0 = 15 * 8; - conf.m[T55xx_DLMode_1of4].write_1 = 31 * 8; - conf.m[T55xx_DLMode_1of4].read_gap = 15 * 8; - conf.m[T55xx_DLMode_1of4].write_2 = 47 * 8; - conf.m[T55xx_DLMode_1of4].write_3 = 63 * 8; + if (set_defaults) { + // fixed bit length + configurations.m[T55XX_DLMODE_FIXED].start_gap = 29 * 8; + configurations.m[T55XX_DLMODE_FIXED].write_gap = 17 * 8; + configurations.m[T55XX_DLMODE_FIXED].write_0 = 15 * 8; + configurations.m[T55XX_DLMODE_FIXED].write_1 = 47 * 8; + configurations.m[T55XX_DLMODE_FIXED].read_gap = 15 * 8; + configurations.m[T55XX_DLMODE_FIXED].write_2 = 0; + configurations.m[T55XX_DLMODE_FIXED].write_3 = 0; + + // long leading reference + configurations.m[T55XX_DLMODE_LLR].start_gap = 31 * 8; + configurations.m[T55XX_DLMODE_LLR].write_gap = 20 * 8; + configurations.m[T55XX_DLMODE_LLR].write_0 = 18 * 8; + configurations.m[T55XX_DLMODE_LLR].write_1 = 50 * 8; + configurations.m[T55XX_DLMODE_LLR].read_gap = 15 * 8; + configurations.m[T55XX_DLMODE_LLR].write_2 = 0; + configurations.m[T55XX_DLMODE_LLR].write_3 = 0; + + // leading zero + configurations.m[T55XX_DLMODE_LEADING_ZERO].start_gap = 31 * 8; + configurations.m[T55XX_DLMODE_LEADING_ZERO].write_gap = 20 * 8; + configurations.m[T55XX_DLMODE_LEADING_ZERO].write_0 = 18 * 8; + configurations.m[T55XX_DLMODE_LEADING_ZERO].write_1 = 40 * 8; + configurations.m[T55XX_DLMODE_LEADING_ZERO].read_gap = 15 * 8; + configurations.m[T55XX_DLMODE_LEADING_ZERO].write_2 = 0; + configurations.m[T55XX_DLMODE_LEADING_ZERO].write_3 = 0; + + // 1 of 4 coding reference + configurations.m[T55XX_DLMODE_1OF4].start_gap = 29 * 8; + configurations.m[T55XX_DLMODE_1OF4].write_gap = 17 * 8; + configurations.m[T55XX_DLMODE_1OF4].write_0 = 15 * 8; + configurations.m[T55XX_DLMODE_1OF4].write_1 = 31 * 8; + configurations.m[T55XX_DLMODE_1OF4].read_gap = 15 * 8; + configurations.m[T55XX_DLMODE_1OF4].write_2 = 47 * 8; + configurations.m[T55XX_DLMODE_1OF4].write_3 = 63 * 8; + + } else { + configurations.m[downlink_mode].start_gap = startgap * 8; + configurations.m[downlink_mode].write_gap = writegap * 8; + configurations.m[downlink_mode].write_0 = write0 * 8; + configurations.m[downlink_mode].write_1 = write1 * 8; + configurations.m[downlink_mode].read_gap = readgap * 8; + configurations.m[downlink_mode].write_2 = write2 * 8; + configurations.m[downlink_mode].write_3 = write3 * 8; + } - } - else { - - conf.m[downlink_mode].start_gap = startgap * 8; - conf.m[downlink_mode].write_gap = writegap * 8; - conf.m[downlink_mode].write_0 = write0 * 8; - conf.m[downlink_mode].write_1 = write1 * 8; - conf.m[downlink_mode].read_gap = readgap * 8; - conf.m[downlink_mode].write_2 = write2 * 8; - conf.m[downlink_mode].write_3 = write3 * 8; - } - clearCommandBuffer(); - SendCommandOLD(CMD_SET_LF_T55XX_CONFIG, shall_persist, 0, 0, &conf, sizeof(t55xx_config)); + SendCommandOLD(CMD_LF_T55XX_SET_CONFIG, shall_persist, 0, 0, &configurations, sizeof(t55xx_configurations_t)); return PM3_SUCCESS; } diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index c61ef137d..668b23be3 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -10,23 +10,7 @@ #ifndef CMDLFT55XX_H__ #define CMDLFT55XX_H__ -#include -#include -#include -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "graph.h" -#include "comms.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdlf.h" -#include "util.h" -#include "lfdemod.h" -#include "cmdhf14a.h" // for getTagInfo -#include "loclass/fileutils.h" // loadDictionary - +#include "common.h" #define T55x7_CONFIGURATION_BLOCK 0x00 #define T55x7_TRACE_BLOCK1 0x01 diff --git a/client/cmdlfti.c b/client/cmdlfti.c index 5236550b2..cf01abb73 100644 --- a/client/cmdlfti.c +++ b/client/cmdlfti.c @@ -11,13 +11,14 @@ #include #include #include + +#include "cmdparser.h" // command_t +#include "commonutil.h" +#include "comms.h" #include "crc16.h" -#include "proxmark3.h" #include "ui.h" #include "graph.h" -#include "cmdparser.h" #include "cmdlfti.h" -#include "cmdmain.h" static int CmdHelp(const char *Cmd); @@ -80,8 +81,8 @@ static int CmdTIDemod(const char *Cmd) { save_restoreGB(GRAPH_SAVE); - int lowLen = sizeof(LowTone) / sizeof(int); - int highLen = sizeof(HighTone) / sizeof(int); + int lowLen = ARRAYLEN(LowTone); + int highLen = ARRAYLEN(HighTone); int convLen = (highLen > lowLen) ? highLen : lowLen; uint16_t crc; int i, j, TagType; @@ -276,7 +277,7 @@ out: static int CmdTIRead(const char *Cmd) { (void)Cmd; // Cmd is not used so far clearCommandBuffer(); - SendCommandNG(CMD_READ_TI_TYPE, NULL, 0); + SendCommandNG(CMD_LF_TI_READ, NULL, 0); return PM3_SUCCESS; } @@ -294,7 +295,7 @@ static int CmdTIWrite(const char *Cmd) { return PM3_EINVARG; } clearCommandBuffer(); - SendCommandMIX(CMD_WRITE_TI_TYPE, arg0, arg1, arg2, NULL, 0); + SendCommandMIX(CMD_LF_TI_WRITE, arg0, arg1, arg2, NULL, 0); return PM3_SUCCESS; } diff --git a/client/cmdlfti.h b/client/cmdlfti.h index bb4922f78..e185a1403 100644 --- a/client/cmdlfti.h +++ b/client/cmdlfti.h @@ -11,6 +11,8 @@ #ifndef CMDLFTI_H__ #define CMDLFTI_H__ +#include "common.h" + int CmdLFTI(const char *Cmd); int demodTI(void); diff --git a/client/cmdlfviking.c b/client/cmdlfviking.c index 41193ea12..ef88cc169 100644 --- a/client/cmdlfviking.c +++ b/client/cmdlfviking.c @@ -9,6 +9,17 @@ //----------------------------------------------------------------------------- #include "cmdlfviking.h" +#include +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "lfdemod.h" + static int CmdHelp(const char *Cmd); static int usage_lf_viking_clone(void) { @@ -88,7 +99,7 @@ static int CmdVikingClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone Viking tag - ID " _YELLOW_("%08X")" raw " _YELLOW_("%08X%08X"), id, (uint32_t)(rawID >> 32), (uint32_t)(rawID & 0xFFFFFFFF)); clearCommandBuffer(); - SendCommandMIX(CMD_VIKING_CLONE_TAG, rawID >> 32, rawID & 0xFFFFFFFF, Q5, NULL, 0); + SendCommandMIX(CMD_LF_VIKING_CLONE, rawID >> 32, rawID & 0xFFFFFFFF, Q5, NULL, 0); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, T55XX_WRITE_TIMEOUT)) { PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); @@ -121,11 +132,11 @@ static int CmdVikingSim(const char *Cmd) { memcpy(payload->data, bs, sizeof(bs)); clearCommandBuffer(); - SendCommandNG(CMD_ASK_SIM_TAG, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs)); + SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs)); free(payload); PacketResponseNG resp; - WaitForResponse(CMD_ASK_SIM_TAG, &resp); + WaitForResponse(CMD_LF_ASK_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) diff --git a/client/cmdlfviking.h b/client/cmdlfviking.h index 8789515d6..156d57c7d 100644 --- a/client/cmdlfviking.h +++ b/client/cmdlfviking.h @@ -8,18 +8,8 @@ //----------------------------------------------------------------------------- #ifndef CMDLFVIKING_H__ #define CMDLFVIKING_H__ -#include -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdmain.h" -#include "cmdlf.h" -#include "lfdemod.h" + +#include "common.h" int CmdLFViking(const char *Cmd); diff --git a/client/cmdlfvisa2000.c b/client/cmdlfvisa2000.c index 12d4ba1c6..ed181d991 100644 --- a/client/cmdlfvisa2000.c +++ b/client/cmdlfvisa2000.c @@ -11,6 +11,19 @@ #include "cmdlfvisa2000.h" +#include +#include +#include + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "graph.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // parityTest + #define BL0CK1 0x56495332 static int CmdHelp(const char *Cmd); @@ -183,8 +196,8 @@ static int CmdVisa2kClone(const char *Cmd) { ng.blockno = i; ng.flags = 0; - SendCommandNG(CMD_T55XX_WRITE_BLOCK, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_T55XX_WRITE_BLOCK, &resp, T55XX_WRITE_TIMEOUT)) { + SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); + if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); return PM3_ETIMEOUT; @@ -218,11 +231,11 @@ static int CmdVisa2kSim(const char *Cmd) { memcpy(payload->data, bs, sizeof(bs)); clearCommandBuffer(); - SendCommandNG(CMD_ASK_SIM_TAG, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs)); + SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs)); free(payload); PacketResponseNG resp; - WaitForResponse(CMD_ASK_SIM_TAG, &resp); + WaitForResponse(CMD_LF_ASK_SIMULATE, &resp); PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) diff --git a/client/cmdlfvisa2000.h b/client/cmdlfvisa2000.h index 15d626f6c..63e7fdc67 100644 --- a/client/cmdlfvisa2000.h +++ b/client/cmdlfvisa2000.h @@ -8,19 +8,9 @@ //----------------------------------------------------------------------------- #ifndef CMDLFVISA2000_H__ #define CMDLFVISA2000_H__ -#include -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdmain.h" -#include "cmdlf.h" -#include "protocols.h" // for T55xx config register definitions -#include "lfdemod.h" // parityTest + +#include "common.h" + int CmdLFVisa2k(const char *Cmd); int getvisa2kBits(uint64_t fullcode, uint8_t *bits); diff --git a/client/cmdmain.c b/client/cmdmain.c index 6748f81f0..eba34b2ca 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -15,6 +15,26 @@ #endif #include "cmdmain.h" +#include +#include +#include // MingW + +#include "comms.h" +#include "cmdhf.h" +#include "cmddata.h" +#include "cmdhw.h" +#include "cmdlf.h" +#include "cmdtrace.h" +#include "cmdscript.h" +#include "cmdcrc.h" +#include "cmdanalyse.h" +#include "emv/cmdemv.h" // EMV +#include "cmdflashmem.h" // rdv40 flashmem commands +#include "cmdsmartcard.h" // rdv40 smart card ISO7816 commands +#include "cmdusart.h" // rdv40 FPC USART commands +#include "ui.h" +#include "util_posix.h" + static int CmdHelp(const char *Cmd); static int CmdRem(const char *Cmd) { @@ -82,7 +102,7 @@ static command_t CommandTable[] = { {"sc", CmdSmartcard, IfPm3Smartcard, "{ Smart card ISO7816 commands... }"}, {"script", CmdScript, AlwaysAvailable, "{ Scripting commands }"}, {"trace", CmdTrace, AlwaysAvailable, "{ Trace manipulation... }"}, - {"usart", CmdUsart, IfPm3FpcUsartDevFromUsb, "{ USART commands... }"}, + {"usart", CmdUsart, IfPm3FpcUsartFromUsb, "{ USART commands... }"}, {"quit", CmdQuit, AlwaysAvailable, ""}, {"exit", CmdQuit, AlwaysAvailable, "Exit program"}, {NULL, NULL, NULL, NULL} diff --git a/client/cmdmain.h b/client/cmdmain.h index e3c513550..8b440143e 100644 --- a/client/cmdmain.h +++ b/client/cmdmain.h @@ -11,30 +11,8 @@ #ifndef CMDMAIN_H__ #define CMDMAIN_H__ -#include -#include -#include -#include -#include -#include -#include "util_posix.h" -#include "proxmark3.h" -#include "pm3_cmd.h" -#include "util.h" -#include "ui.h" -#include "cmdparser.h" -#include "cmdhf.h" -#include "cmddata.h" -#include "cmdhw.h" -#include "cmdlf.h" -#include "cmdtrace.h" -#include "cmdscript.h" -#include "cmdcrc.h" -#include "cmdanalyse.h" -#include "emv/cmdemv.h" // EMV -#include "cmdflashmem.h" // rdv40 flashmem commands -#include "cmdsmartcard.h" // rdv40 smart card ISO7816 commands -#include "cmdusart.h" // rdv40 FPC USART commands +#include "common.h" +#include "cmdparser.h" // command_t int CommandReceived(char *Cmd); command_t *getTopLevelCommandTable(void); diff --git a/client/cmdparser.c b/client/cmdparser.c index 077ba8ac5..9e7b83afa 100644 --- a/client/cmdparser.c +++ b/client/cmdparser.c @@ -8,13 +8,12 @@ // Command parser //----------------------------------------------------------------------------- -#include -#include -#include -#include "util.h" -#include "ui.h" #include "cmdparser.h" -#include "proxmark3.h" + +#include +#include + +#include "ui.h" #include "comms.h" bool AlwaysAvailable(void) { @@ -73,6 +72,11 @@ bool IfPm3FpcUsartDevFromUsb(void) { return !conn.send_via_fpc_usart; } +bool IfPm3FpcUsartFromUsb(void) { + // true if FPC USART Host or developer support and if talking from USB-CDC interface + return IfPm3FpcUsartHostFromUsb() || IfPm3FpcUsartDevFromUsb(); +} + bool IfPm3Lf(void) { if (!IfPm3Present()) return false; @@ -133,6 +137,12 @@ bool IfPm3Iclass(void) { return pm3_capabilities.compiled_with_iclass; } +bool IfPm3NfcBarcode(void) { + if (!IfPm3Present()) + return false; + return pm3_capabilities.compiled_with_nfcbarcode; +} + bool IfPm3Lcd(void) { if (!IfPm3Present()) return false; @@ -145,7 +155,7 @@ void CmdsHelp(const command_t Commands[]) { int i = 0; while (Commands[i].Name) { if (Commands[i].IsAvailable()) - PrintAndLogEx(NORMAL, "%-16s %s", Commands[i].Name, Commands[i].Help); + PrintAndLogEx(NORMAL, _GREEN_("%-16s")" %s", Commands[i].Name, Commands[i].Help); ++i; } } @@ -166,6 +176,9 @@ int CmdsParse(const command_t Commands[], const char *Cmd) { memset(cmd_name, 0, sizeof(cmd_name)); sscanf(Cmd, "%127s%n", cmd_name, &len); str_lower(cmd_name); + // Comment + if (cmd_name[0] == '#') + return PM3_SUCCESS; int i = 0; while (Commands[i].Name) { if (0 == strcmp(Commands[i].Name, cmd_name)) { diff --git a/client/cmdparser.h b/client/cmdparser.h index c5aa5460e..b98aef9d4 100644 --- a/client/cmdparser.h +++ b/client/cmdparser.h @@ -11,6 +11,8 @@ #ifndef CMDPARSER_H__ #define CMDPARSER_H__ +#include "common.h" + typedef struct command_s { const char *Name; int (*Parse)(const char *Cmd); @@ -28,6 +30,7 @@ bool IfPm3FpcUsart(void); bool IfPm3FpcUsartHost(void); bool IfPm3FpcUsartHostFromUsb(void); bool IfPm3FpcUsartDevFromUsb(void); +bool IfPm3FpcUsartFromUsb(void); bool IfPm3Lf(void); bool IfPm3Hitag(void); bool IfPm3Hfsniff(void); @@ -38,6 +41,7 @@ bool IfPm3Iso15693(void); bool IfPm3Felica(void); bool IfPm3Legicrf(void); bool IfPm3Iclass(void); +bool IfPm3NfcBarcode(void); bool IfPm3Lcd(void); // Print help for each command in the command array diff --git a/client/cmdscript.c b/client/cmdscript.c index 8880e18fd..6d7858d54 100644 --- a/client/cmdscript.c +++ b/client/cmdscript.c @@ -8,60 +8,24 @@ // Some lua scripting glue to proxmark core. //----------------------------------------------------------------------------- -// this define is needed for scandir/alphasort to work -#define _GNU_SOURCE - -#include #include #include -#include -#include -#include -#include "proxmark3.h" +#include "cmdparser.h" // command_t #include "scripting.h" -#include "ui.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmdmain.h" #include "comms.h" #include "cmdscript.h" #include "cmdhfmf.h" #include "pm3_binlib.h" #include "pm3_bitlib.h" -#include -#include -#include - -#ifdef _WIN32 -#include "scandir.h" -#endif +#include "lualib.h" +#include "lauxlib.h" +#include "proxmark3.h" +#include "ui.h" +#include "fileutils.h" static int CmdHelp(const char *Cmd); -static int str_ends_with(const char *str, const char *suffix) { - - if (str == NULL || suffix == NULL) - return 0; - - size_t str_len = strlen(str); - size_t suffix_len = strlen(suffix); - - if (suffix_len > str_len) - return 0; - - return 0 == strncmp(str + str_len - suffix_len, suffix, suffix_len); -} - -/** - * Utility to check the ending of a string (used to check file suffix) - */ -static bool endsWith(const char *base, const char *str) { - int blen = strlen(base); - int slen = strlen(str); - return (blen >= slen) && (0 == strcmp(base + blen - slen, str)); -} - /** * Generate a sorted list of available commands, what it does is * generate a file listing of the script-directory for files @@ -69,31 +33,10 @@ static bool endsWith(const char *base, const char *str) { */ static int CmdScriptList(const char *Cmd) { (void)Cmd; // Cmd is not used so far - - char const *exedir = get_my_executable_directory(); - if (exedir == NULL) - return 0; - char script_directory_path[strlen(exedir) + strlen(LUA_SCRIPTS_DIRECTORY) + 1]; - strcpy(script_directory_path, exedir); - strcpy(script_directory_path, get_my_executable_directory()); - strcat(script_directory_path, LUA_SCRIPTS_DIRECTORY); - - struct dirent **namelist; - int n; - - n = scandir(script_directory_path, &namelist, NULL, alphasort); - if (n == -1) { - PrintAndLogEx(FAILED, "Couldn't open the scripts-directory"); - return 1; - } - - for (uint16_t i = 0; i < n; i++) { - if (str_ends_with(namelist[i]->d_name, ".lua")) - PrintAndLogEx(NORMAL, "%-21s", namelist[i]->d_name); - free(namelist[i]); - } - free(namelist); - return 0; + int ret = searchAndList(LUA_SCRIPTS_SUBDIR, ".lua"); + if (ret != PM3_SUCCESS) + return ret; + return searchAndList(CMD_SCRIPTS_SUBDIR, ".cmd"); } /** @@ -103,67 +46,81 @@ static int CmdScriptList(const char *Cmd) { * @return */ static int CmdScriptRun(const char *Cmd) { - // create new Lua state - lua_State *lua_state; - lua_state = luaL_newstate(); - // load Lua libraries - luaL_openlibs(lua_state); - - //Sets the pm3 core libraries, that go a bit 'under the hood' - set_pm3_libraries(lua_state); - - //Add the 'bin' library - set_bin_library(lua_state); - - //Add the 'bit' library - set_bit_library(lua_state); - - char script_name[128] = {0}; + char preferredName[128] = {0}; char arguments[256] = {0}; int name_len = 0; int arg_len = 0; - sscanf(Cmd, "%127s%n %255[^\n\r]%n", script_name, &name_len, arguments, &arg_len); + static uint8_t luascriptfile_idx = 0; + sscanf(Cmd, "%127s%n %255[^\n\r]%n", preferredName, &name_len, arguments, &arg_len); - const char *suffix = ""; - if (!endsWith(script_name, ".lua")) { - suffix = ".lua"; + char *script_path; + if ((!str_endswith(preferredName, ".cmd")) && (searchFile(&script_path, LUA_SCRIPTS_SUBDIR, preferredName, ".lua", true) == PM3_SUCCESS)) { + int error; + if (luascriptfile_idx == MAX_NESTED_LUASCRIPT) { + PrintAndLogEx(ERR, "Too many nested scripts, skipping %s\n", script_path); + return PM3_EMALLOC; + } + PrintAndLogEx(SUCCESS, "Executing Lua script: %s, args '%s'\n", script_path, arguments); + luascriptfile_idx++; + + // create new Lua state + lua_State *lua_state; + lua_state = luaL_newstate(); + + // load Lua libraries + luaL_openlibs(lua_state); + + //Sets the pm3 core libraries, that go a bit 'under the hood' + set_pm3_libraries(lua_state); + + //Add the 'bin' library + set_bin_library(lua_state); + + //Add the 'bit' library + set_bit_library(lua_state); + + error = luaL_loadfile(lua_state, script_path); + free(script_path); + if (!error) { + lua_pushstring(lua_state, arguments); + lua_setglobal(lua_state, "args"); + + //Call it with 0 arguments + error = lua_pcall(lua_state, 0, LUA_MULTRET, 0); // once again, returns non-0 on error, + } + if (error) { // if non-0, then an error + // the top of the stack should be the error string + if (!lua_isstring(lua_state, lua_gettop(lua_state))) + PrintAndLogEx(FAILED, "Error - but no error (?!)"); + + // get the top of the stack as the error and pop it off + const char *str = lua_tostring(lua_state, lua_gettop(lua_state)); + lua_pop(lua_state, 1); + puts(str); + } + + //luaL_dofile(lua_state, buf); + // close the Lua state + lua_close(lua_state); + luascriptfile_idx--; + PrintAndLogEx(SUCCESS, "\nFinished %s\n", preferredName); + return PM3_SUCCESS; } - - char script_path[strlen(get_my_executable_directory()) + strlen(LUA_SCRIPTS_DIRECTORY) + strlen(script_name) + strlen(suffix) + 1]; - strcpy(script_path, get_my_executable_directory()); - strcat(script_path, LUA_SCRIPTS_DIRECTORY); - strcat(script_path, script_name); - strcat(script_path, suffix); - - PrintAndLogEx(SUCCESS, "Executing: %s%s, args '%s'\n", script_name, suffix, arguments); - - // run the Lua script - int error = luaL_loadfile(lua_state, script_path); - if (!error) { - lua_pushstring(lua_state, arguments); - lua_setglobal(lua_state, "args"); - - //Call it with 0 arguments - error = lua_pcall(lua_state, 0, LUA_MULTRET, 0); // once again, returns non-0 on error, + if ((!str_endswith(preferredName, ".lua")) && (searchFile(&script_path, CMD_SCRIPTS_SUBDIR, preferredName, ".cmd", true) == PM3_SUCCESS)) { + PrintAndLogEx(SUCCESS, "Executing Cmd script: %s, args '%s'\n", script_path, arguments); + int ret = push_cmdscriptfile(script_path, true); + if (ret != PM3_SUCCESS) + PrintAndLogEx(ERR, "could not open " _YELLOW_("%s") "...", script_path); + free(script_path); + return ret; } - if (error) { // if non-0, then an error - // the top of the stack should be the error string - if (!lua_isstring(lua_state, lua_gettop(lua_state))) - PrintAndLogEx(FAILED, "Error - but no error (?!)"); - - // get the top of the stack as the error and pop it off - const char *str = lua_tostring(lua_state, lua_gettop(lua_state)); - lua_pop(lua_state, 1); - puts(str); - } - - //luaL_dofile(lua_state, buf); - // close the Lua state - lua_close(lua_state); - PrintAndLogEx(SUCCESS, "\nFinished\n"); - return 0; + // file not found, let's search again to display the error messages + int ret = PM3_EUNDEF; + if (!str_endswith(preferredName, ".cmd")) ret = searchFile(&script_path, LUA_SCRIPTS_SUBDIR, preferredName, ".lua", false); + if (!str_endswith(preferredName, ".lua")) ret = searchFile(&script_path, CMD_SCRIPTS_SUBDIR, preferredName, ".cmd", false); + return ret; } static command_t CommandTable[] = { @@ -181,7 +138,7 @@ static command_t CommandTable[] = { */ static int CmdHelp(const char *Cmd) { (void)Cmd; // Cmd is not used so far - PrintAndLogEx(NORMAL, "This is a feature to run Lua-scripts. You can place lua-scripts within the scripts/-folder. "); + PrintAndLogEx(NORMAL, "This is a feature to run Lua-scripts. You can place Lua-scripts within the luascripts/-folder. "); return 0; } diff --git a/client/cmdscript.h b/client/cmdscript.h index 866b09e99..37384db20 100644 --- a/client/cmdscript.h +++ b/client/cmdscript.h @@ -11,6 +11,8 @@ #ifndef CMDSCRIPT_H__ #define CMDSCRIPT_H__ +#include "common.h" + int CmdScript(const char *Cmd); #endif diff --git a/client/cmdscripts/rdv4_init_extflash.cmd b/client/cmdscripts/rdv4_init_extflash.cmd new file mode 100755 index 000000000..2cae05294 --- /dev/null +++ b/client/cmdscripts/rdv4_init_extflash.cmd @@ -0,0 +1,6 @@ +#!/usr/bin/env -S pm3 -s + +mem load f mfc_default_keys m +mem load f t55xx_default_pwds t +mem load f iclass_default_keys i +lf t55xx deviceconfig z p diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index c49f0d0e7..c9dde7063 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -8,7 +8,21 @@ // Proxmark3 RDV40 Smartcard module commands //----------------------------------------------------------------------------- #include "cmdsmartcard.h" -#include "../emv/emvjson.h" + +#include +#include + +#include "cmdparser.h" // command_t +#include "commonutil.h" // ARRAYLEN +#include "protocols.h" +#include "cmdtrace.h" +#include "proxmark3.h" +#include "comms.h" // getfromdevice +#include "emv/emvcore.h" // decodeTVL +#include "crypto/libpcrypto.h" // sha512hash +#include "emv/dump.h" +#include "ui.h" +#include "fileutils.h" static int CmdHelp(const char *Cmd); @@ -55,13 +69,13 @@ static int usage_sm_upgrade(void) { PrintAndLogEx(NORMAL, " f : firmware file name"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " sc upgrade f ../tools/simmodule/SIM011.BIN"); + PrintAndLogEx(NORMAL, " sc upgrade f ../tools/simmodule/sim011.bin"); return 0; } static int usage_sm_setclock(void) { PrintAndLogEx(NORMAL, "Usage: sc setclock [h] c "); PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, " c <> : clockspeed (0 = 16mhz, 1=8mhz, 2=4mhz) "); + PrintAndLogEx(NORMAL, " c <> : clockspeed (0 = 16MHz, 1=8MHz, 2=4MHz) "); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " sc setclock c 2"); @@ -79,33 +93,35 @@ static int usage_sm_brute(void) { return 0; } -static int smart_loadjson(const char *preferredName, const char *suffix, json_t **root) { +static int smart_loadjson(const char *preferredName, json_t **root) { json_error_t error; if (preferredName == NULL) return 1; - if (suffix == NULL) return 1; - int retval = 0; - int size = sizeof(char) * (strlen(get_my_executable_directory()) + strlen(preferredName) + strlen(suffix) + 10); - char *fileName = calloc(size, sizeof(char)); - sprintf(fileName, "%s%s.%s", get_my_executable_directory(), preferredName, suffix); - *root = json_load_file(fileName, 0, &error); + char *path; + int res = searchFile(&path, RESOURCES_SUBDIR, preferredName, ".json", false); + if (res != PM3_SUCCESS) { + return PM3_EFILE; + } + + int retval = PM3_SUCCESS; + *root = json_load_file(path, 0, &error); if (!*root) { - PrintAndLogEx(ERR, "json (%s) error on line %d: %s", fileName, error.line, error.text); - retval = 2; + PrintAndLogEx(ERR, "json (%s) error on line %d: %s", path, error.line, error.text); + retval = PM3_ESOFT; goto out; } if (!json_is_array(*root)) { - PrintAndLogEx(ERR, "Invalid json (%s) format. root must be an array.", fileName); - retval = 3; + PrintAndLogEx(ERR, "Invalid json (%s) format. root must be an array.", path); + retval = PM3_ESOFT; goto out; } - PrintAndLogEx(SUCCESS, "Loaded file (%s) OK.", fileName); + PrintAndLogEx(SUCCESS, "Loaded file (%s) OK.", path); out: - free(fileName); + free(path); return retval; } @@ -843,13 +859,13 @@ static int CmdSmartSetClock(const char *Cmd) { switch (clock1) { case 0: - PrintAndLogEx(SUCCESS, "Clock changed to 16mhz giving 10800 baudrate"); + PrintAndLogEx(SUCCESS, "Clock changed to 16MHz giving 10800 baudrate"); break; case 1: - PrintAndLogEx(SUCCESS, "Clock changed to 8mhz giving 21600 baudrate"); + PrintAndLogEx(SUCCESS, "Clock changed to 8MHz giving 21600 baudrate"); break; case 2: - PrintAndLogEx(SUCCESS, "Clock changed to 4mhz giving 86400 baudrate"); + PrintAndLogEx(SUCCESS, "Clock changed to 4MHz giving 86400 baudrate"); break; default: break; @@ -878,7 +894,7 @@ static void smart_brute_prim() { PrintAndLogEx(INFO, "Reading primitives"); - for (int i = 0; i < sizeof(get_card_data); i += 5) { + for (int i = 0; i < ARRAYLEN(get_card_data); i += 5) { clearCommandBuffer(); SendCommandOLD(CMD_SMART_RAW, SC_RAW_T0, 5, 0, get_card_data + i, 5); @@ -1022,7 +1038,7 @@ static int CmdSmartBruteforceSFI(const char *Cmd) { PrintAndLogEx(INFO, "Importing AID list"); json_t *root = NULL; - smart_loadjson("aidlist", "json", &root); + smart_loadjson("aidlist", &root); uint8_t *buf = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t)); if (!buf) diff --git a/client/cmdsmartcard.h b/client/cmdsmartcard.h index 6b960f311..74c305a0d 100644 --- a/client/cmdsmartcard.h +++ b/client/cmdsmartcard.h @@ -11,21 +11,8 @@ #ifndef CMDSMARTCARD_H__ #define CMDSMARTCARD_H__ -#include -#include -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "cmdparser.h" #include "common.h" -#include "util.h" -#include "loclass/fileutils.h" // saveFile -#include "comms.h" // getfromdevice -#include "emv/emvcore.h" // decodeTVL -#include "emv/apduinfo.h" // APDUcode description -#include "emv/dump.h" // dump_buffer -#include "crypto/libpcrypto.h" // sha512hash +#include "mifare.h" // structs int CmdSmartcard(const char *Cmd); diff --git a/client/cmdtrace.c b/client/cmdtrace.c index 3a2ea9aef..010621498 100644 --- a/client/cmdtrace.c +++ b/client/cmdtrace.c @@ -9,6 +9,15 @@ //----------------------------------------------------------------------------- #include "cmdtrace.h" +#include + +#include "cmdparser.h" // command_t +#include "protocols.h" +#include "parity.h" // oddparity +#include "cmdhflist.h" // annotations +#include "comms.h" // for sending cmds to device. GetFromBigBuf +#include "fileutils.h" // for saveFile + static int CmdHelp(const char *Cmd); // trace pointer @@ -24,18 +33,19 @@ static int usage_trace_list() { PrintAndLogEx(NORMAL, " syntax to use: `text2pcap -t \"%%S.\" -l 264 -n `"); PrintAndLogEx(NORMAL, " <0|1> - use data from Tracebuffer, if not set, try reading data from tag."); PrintAndLogEx(NORMAL, "Supported values:"); - PrintAndLogEx(NORMAL, " raw - just show raw data without annotations"); - PrintAndLogEx(NORMAL, " 14a - interpret data as iso14443a communications"); - PrintAndLogEx(NORMAL, " mf - interpret data as iso14443a communications and decrypt crypto1 stream"); - PrintAndLogEx(NORMAL, " 14b - interpret data as iso14443b communications"); - PrintAndLogEx(NORMAL, " 15 - interpret data as iso15693 communications"); - PrintAndLogEx(NORMAL, " des - interpret data as DESFire communications"); - PrintAndLogEx(NORMAL, " iclass - interpret data as iclass communications"); - PrintAndLogEx(NORMAL, " topaz - interpret data as topaz communications"); - PrintAndLogEx(NORMAL, " 7816 - interpret data as iso7816-4 communications"); - PrintAndLogEx(NORMAL, " legic - interpret data as LEGIC communications"); - PrintAndLogEx(NORMAL, " felica - interpret data as ISO18092 / FeliCa communications"); - PrintAndLogEx(NORMAL, " hitag - interpret data as Hitag2 / HitagS communications"); + PrintAndLogEx(NORMAL, " raw - just show raw data without annotations"); + PrintAndLogEx(NORMAL, " 14a - interpret data as iso14443a communications"); + PrintAndLogEx(NORMAL, " thinfilm - interpret data as Thinfilm communications"); + PrintAndLogEx(NORMAL, " topaz - interpret data as Topaz communications"); + PrintAndLogEx(NORMAL, " mf - interpret data as iso14443a communications and decrypt crypto1 stream"); + PrintAndLogEx(NORMAL, " des - interpret data as DESFire communications"); + PrintAndLogEx(NORMAL, " 14b - interpret data as iso14443b communications"); + PrintAndLogEx(NORMAL, " 7816 - interpret data as iso7816-4 communications"); + PrintAndLogEx(NORMAL, " 15 - interpret data as iso15693 communications"); + PrintAndLogEx(NORMAL, " iclass - interpret data as iclass communications"); + PrintAndLogEx(NORMAL, " legic - interpret data as LEGIC communications"); + PrintAndLogEx(NORMAL, " felica - interpret data as ISO18092 / FeliCa communications"); + PrintAndLogEx(NORMAL, " hitag - interpret data as Hitag2 / HitagS communications"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " trace list 14a f"); @@ -254,6 +264,15 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr case MFDES: crcStatus = iso14443A_CRC_check(isResponse, frame, data_len); break; + case THINFILM: + frame[data_len - 1] ^= frame[data_len - 2]; + frame[data_len - 2] ^= frame[data_len - 1]; + frame[data_len - 1] ^= frame[data_len - 2]; + crcStatus = iso14443A_CRC_check(true, frame, data_len); + frame[data_len - 1] ^= frame[data_len - 2]; + frame[data_len - 2] ^= frame[data_len - 1]; + frame[data_len - 1] ^= frame[data_len - 2]; + break; case ISO_15693: crcStatus = iso15693_CRC_check(frame, data_len); break; @@ -275,13 +294,27 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr uint8_t parityBits = parityBytes[j >> 3]; if (protocol != LEGIC && protocol != ISO_14443B + && protocol != ISO_15693 + && protocol != ICLASS && protocol != ISO_7816_4 && protocol != PROTO_HITAG + && protocol != THINFILM && (isResponse || protocol == ISO_14443A) && (oddparity8(frame[j]) != ((parityBits >> (7 - (j & 0x0007))) & 0x01))) { snprintf(line[j / 18] + ((j % 18) * 4), 110, "%02x! ", frame[j]); - } else { + } else if ( protocol == ICLASS && isResponse == false) { + uint8_t parity = 0; + for (int i=0; i<6; i++) { + parity ^= ((frame[0] >> i) & 1); + } + if ( parity == ((frame[0] >> 7) & 1)) { + snprintf(line[j / 18] + ((j % 18) * 4), 110, "%02x ", frame[j]); + } else { + snprintf(line[j / 18] + ((j % 18) * 4), 110, "%02x! ", frame[j]); + } + + } else { snprintf(line[j / 18] + ((j % 18) * 4), 110, "%02x ", frame[j]); } @@ -727,7 +760,7 @@ int CmdTraceList(const char *Cmd) { str_lower(type); // validate type of output - if (strcmp(type, "iclass") == 0) protocol = ICLASS; + if (strcmp(type, "iclass") == 0) protocol = ICLASS; else if (strcmp(type, "14a") == 0) protocol = ISO_14443A; else if (strcmp(type, "14b") == 0) protocol = ISO_14443B; else if (strcmp(type, "topaz") == 0) protocol = TOPAZ; @@ -738,6 +771,7 @@ int CmdTraceList(const char *Cmd) { else if (strcmp(type, "felica") == 0) protocol = FELICA; else if (strcmp(type, "mf") == 0) protocol = PROTO_MIFARE; else if (strcmp(type, "hitag") == 0) protocol = PROTO_HITAG; + else if (strcmp(type, "thinfilm") == 0) protocol = THINFILM; else if (strcmp(type, "raw") == 0) protocol = -1; //No crc, no annotations else errors = true; @@ -791,17 +825,23 @@ int CmdTraceList(const char *Cmd) { } } else { PrintAndLogEx(NORMAL, "Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); - if (protocol == ISO_14443A || protocol == PROTO_MIFARE) - PrintAndLogEx(NORMAL, "iso14443a - All times are in carrier periods (1/13.56Mhz)"); + if (protocol == ISO_14443A || protocol == PROTO_MIFARE || protocol == MFDES || protocol == TOPAZ) + PrintAndLogEx(NORMAL, "ISO14443A - All times are in carrier periods (1/13.56MHz)"); + if (protocol == THINFILM) + PrintAndLogEx(NORMAL, "Thinfilm - All times are in carrier periods (1/13.56MHz)"); if (protocol == ICLASS) PrintAndLogEx(NORMAL, "iClass - Timings are not as accurate"); if (protocol == LEGIC) PrintAndLogEx(NORMAL, "LEGIC - Reader Mode: Timings are in ticks (1us == 1.5ticks)\n" " Tag Mode: Timings are in sub carrier periods (1/212 kHz == 4.7us)"); + if (protocol == ISO_14443B) + PrintAndLogEx(NORMAL, "ISO14443B"); // Timings ? if (protocol == ISO_15693) PrintAndLogEx(NORMAL, "ISO15693 - Timings are not as accurate"); if (protocol == ISO_7816_4) PrintAndLogEx(NORMAL, "ISO7816-4 / Smartcard - Timings N/A yet"); + if (protocol == FELICA) + PrintAndLogEx(NORMAL, "Felica"); // Timings ? if (protocol == PROTO_HITAG) PrintAndLogEx(NORMAL, "Hitag2 / HitagS - Timings in ETU (8us)"); @@ -812,6 +852,9 @@ int CmdTraceList(const char *Cmd) { ClearAuthData(); while (tracepos < traceLen) { tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles, markCRCBytes); + + if (kbd_enter_pressed()) + break; } } return 0; diff --git a/client/cmdtrace.h b/client/cmdtrace.h index 2f0125664..acef66884 100644 --- a/client/cmdtrace.h +++ b/client/cmdtrace.h @@ -10,22 +10,8 @@ #ifndef CMDTRACE_H__ #define CMDTRACE_H__ -#include -#include -#include -#include -#include -#include -#include "proxmark3.h" -#include "protocols.h" -#include "parity.h" // oddparity -#include "cmdhflist.h" // annotations -#include "iso15693tools.h" // ISO15693 crc -#include "util.h" // for parsing cli command utils -#include "ui.h" // for show graph controls -#include "cmdparser.h" // for getting cli commands included in cmdmain.h -#include "comms.h" // for sending cmds to device. GetFromBigBuf -#include "loclass/fileutils.h" // for saveFile + +#include "common.h" int CmdTrace(const char *Cmd); int CmdTraceList(const char *Cmd); diff --git a/client/cmdusart.c b/client/cmdusart.c index 60b977430..26b972f82 100644 --- a/client/cmdusart.c +++ b/client/cmdusart.c @@ -9,6 +9,18 @@ //----------------------------------------------------------------------------- #include "cmdusart.h" +#include // size_t +#include +#include +#include + +#include "cmdparser.h" // command_t +#include "commonutil.h" // ARRAYLEN +#include "comms.h" +#include "util_posix.h" +#include "usart_defs.h" +#include "ui.h" // PrintAndLog + static int CmdHelp(const char *Cmd); static int usage_usart_bt_pin(void) { @@ -47,7 +59,7 @@ static int usage_usart_tx(void) { PrintAndLogEx(NORMAL, "Send string over USART"); PrintAndLogEx(NORMAL, _RED_("WARNING: it will have side-effects if used in USART HOST mode!")); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: usart tx [h] \"string\""); + PrintAndLogEx(NORMAL, "Usage: usart tx [h] d \"string\""); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h This help"); PrintAndLogEx(NORMAL, " d string string to send"); @@ -106,7 +118,7 @@ static int usage_usart_txrx(void) { PrintAndLogEx(NORMAL, _YELLOW_("to add-on when BT connection is not established (LED needs to be blinking)")); PrintAndLogEx(NORMAL, _RED_("Any other usage in USART HOST mode will have side-effects!")); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: usart txrx [h] [t ] \"string\""); + PrintAndLogEx(NORMAL, "Usage: usart txrx [h] [t ] d \"string\""); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h This help"); PrintAndLogEx(NORMAL, " t timeout in ms, default is 1000ms"); @@ -751,8 +763,8 @@ static int CmdUsartRXhex(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"btpin", CmdUsartBtPin, IfPm3FpcUsartHostFromUsb, "Change BT add-on PIN"}, - {"btfactory", CmdUsartBtFactory, IfPm3FpcUsartHostFromUsb, "Reset BT add-on to factory settings"}, + {"btpin", CmdUsartBtPin, IfPm3FpcUsartFromUsb, "Change BT add-on PIN"}, + {"btfactory", CmdUsartBtFactory, IfPm3FpcUsartFromUsb, "Reset BT add-on to factory settings"}, {"tx", CmdUsartTX, IfPm3FpcUsartDevFromUsb, "Send string over USART"}, {"rx", CmdUsartRX, IfPm3FpcUsartDevFromUsb, "Receive string over USART"}, {"txrx", CmdUsartTXRX, IfPm3FpcUsartDevFromUsb, "Send string over USART and wait for response"}, diff --git a/client/cmdusart.h b/client/cmdusart.h index f2e4d02dd..1ee21e060 100644 --- a/client/cmdusart.h +++ b/client/cmdusart.h @@ -11,14 +11,7 @@ #ifndef CMDUSART_H__ #define CMDUSART_H__ -#include // size_t -#include -#include -#include "cmdmain.h" -#include "proxmark3.h" -#include "ui.h" // PrintAndLog -#include "util.h" -//#include "util_posix.h" // msclock +#include "common.h" int CmdUsart(const char *Cmd); #endif diff --git a/client/comms.c b/client/comms.c index ef00ebc44..8d2c8f733 100644 --- a/client/comms.c +++ b/client/comms.c @@ -10,11 +10,16 @@ //----------------------------------------------------------------------------- #include "comms.h" + +#include +#include +#include + +#include "uart.h" +#include "ui.h" #include "crc16.h" -#if defined(__linux__) || (__APPLE__) -#include -#include -#endif +#include "util_posix.h" // msclock +#include "util_darwin.h" // en/dis-ableNapp(); //#define COMMS_DEBUG //#define COMMS_DEBUG_RAW @@ -53,6 +58,8 @@ static pthread_mutex_t rxBufferMutex = PTHREAD_MUTEX_INITIALIZER; // as sending lot of these packets can slow down things wuite a lot on slow links (e.g. hw status or lf read at 9600) static uint64_t timeout_start_time; +static uint64_t last_packet_time; + static bool dl_it(uint8_t *dest, uint32_t bytes, uint32_t start_index, PacketResponseNG *response, size_t ms_timeout, bool show_warning, uint32_t rec_cmd); // Simple alias to track usages linked to the Bootloader, these commands must not be migrated. @@ -248,11 +255,14 @@ static int getReply(PacketResponseNG *packet) { //----------------------------------------------------------------------------- static void PacketResponseReceived(PacketResponseNG *packet) { -// PrintAndLogEx(NORMAL, "RECV %s magic %08x length %04x status %04x crc %04x cmd %04x", -// packet->ng ? "NG" : "OLD", packet->magic, packet->length, packet->status, packet->crc, packet->cmd); - // we got a packet, reset WaitForResponseTimeout timeout - __atomic_store_n(&timeout_start_time, msclock(), __ATOMIC_SEQ_CST); + uint64_t prev_clk = __atomic_load_n(&last_packet_time, __ATOMIC_SEQ_CST); + uint64_t clk = msclock(); + __atomic_store_n(&timeout_start_time, clk, __ATOMIC_SEQ_CST); + __atomic_store_n(&last_packet_time, clk, __ATOMIC_SEQ_CST); + (void) prev_clk; +// PrintAndLogEx(NORMAL, "[%07"PRIu64"] RECV %s magic %08x length %04x status %04x crc %04x cmd %04x", +// clk - prev_clk, packet->ng ? "NG" : "OLD", packet->magic, packet->length, packet->status, packet->crc, packet->cmd); switch (packet->cmd) { // First check if we are handling a debug message @@ -585,6 +595,7 @@ int TestProxmark(void) { for (uint16_t i = 0; i < len; i++) data[i] = i & 0xFF; + __atomic_store_n(&last_packet_time, msclock(), __ATOMIC_SEQ_CST); clearCommandBuffer(); SendCommandNG(CMD_PING, data, len); @@ -622,7 +633,9 @@ int TestProxmark(void) { conn.send_via_fpc_usart = pm3_capabilities.via_fpc; conn.uart_speed = pm3_capabilities.baudrate; - PrintAndLogEx(INFO, "Communicating with PM3 over %s", conn.send_via_fpc_usart ? _YELLOW_("FPC UART") : _YELLOW_("USB-CDC")); + PrintAndLogEx(INFO, "Communicating with PM3 over %s%s", + conn.send_via_fpc_usart ? _YELLOW_("FPC UART") : _YELLOW_("USB-CDC"), + memcmp(conn.serial_port_name, "tcp:", 4) == 0 ? "over " _YELLOW_("TCP") : ""); if (conn.send_via_fpc_usart) { PrintAndLogEx(INFO, "PM3 UART serial baudrate: " _YELLOW_("%u") "\n", conn.uart_speed); @@ -702,6 +715,12 @@ bool WaitForResponseTimeoutW(uint32_t cmd, PacketResponseNG *response, size_t ms if (cmd == CMD_UNKNOWN || response->cmd == cmd) { return true; } + if (response->cmd == CMD_WTX && response->length == sizeof(uint16_t)) { + uint16_t wtx = response->data.asDwords[0] & 0xFFFF; + PrintAndLogEx(DEBUG, "Got Waiting Time eXtension request %i ms", wtx); + if (ms_timeout != (size_t) - 1) + ms_timeout += wtx; + } } uint64_t tmp_clk = __atomic_load_n(&timeout_start_time, __ATOMIC_SEQ_CST); @@ -816,6 +835,11 @@ static bool dl_it(uint8_t *dest, uint32_t bytes, uint32_t start_index, PacketRes bytes_completed += copy_bytes; } else if (response->cmd == CMD_ACK) { return true; + } else if (response->cmd == CMD_WTX && response->length == sizeof(uint16_t)) { + uint16_t wtx = response->data.asDwords[0] & 0xFFFF; + PrintAndLogEx(DEBUG, "Got Waiting Time eXtension request %i ms", wtx); + if (ms_timeout != (size_t) - 1) + ms_timeout += wtx; } } diff --git a/client/comms.h b/client/comms.h index bc036f008..b49ff6d11 100644 --- a/client/comms.h +++ b/client/comms.h @@ -12,19 +12,22 @@ #ifndef COMMS_H_ #define COMMS_H_ -#include -#include - -#include "pm3_cmd.h" -#include "uart.h" -#include "ui.h" #include "common.h" -#include "util_posix.h" -#include "util.h" -#include "util_darwin.h" +#include "pm3_cmd.h" // Packet structs +#include "util.h" // FILE_PATH_SIZE -#if defined(__linux__) && !defined(NO_UNLINK) -#include // for unlink() +#ifndef DropField +#define DropField() { \ + clearCommandBuffer(); SendCommandNG(CMD_HF_DROPFIELD, NULL, 0); \ + } +#endif + +#ifndef DropFieldEx +#define DropFieldEx(x) { \ + if ( (x) == ECC_CONTACTLESS) { \ + DropField(); \ + } \ + } #endif //For storing command that are received from the device diff --git a/client/crypto/asn1dump.c b/client/crypto/asn1dump.c index 2c720ad04..91b04216a 100644 --- a/client/crypto/asn1dump.c +++ b/client/crypto/asn1dump.c @@ -8,8 +8,10 @@ // asn.1 dumping //----------------------------------------------------------------------------- #define _POSIX_C_SOURCE 200809L // need for strnlen() - #include "asn1dump.h" + +#include "commonutil.h" // ARRAYLEN + #include #include #include @@ -23,6 +25,8 @@ #include "emv/emvjson.h" #include "util.h" #include "proxmark3.h" +#include "fileutils.h" +#include "pm3_cmd.h" #ifndef PRINT_INDENT # define PRINT_INDENT(level) {for (int myi = 0; myi < (level); myi++) fprintf(f, " ");} @@ -233,25 +237,17 @@ static void asn1_tag_dump_integer(const struct tlv *tlv, const struct asn1_tag * static char *asn1_oid_description(const char *oid, bool with_group_desc) { json_error_t error; json_t *root = NULL; - char fname[300] = {0}; static char res[300]; memset(res, 0x00, sizeof(res)); - size_t len = strlen(get_my_executable_directory()); - if (len >= 300) len = 299; - - strncpy(fname, get_my_executable_directory(), len); - strcat(fname, "crypto/oids.json"); - if (access(fname, F_OK) < 0) { - strncpy(fname, get_my_executable_directory(), len); - strcat(fname, "oids.json"); - if (access(fname, F_OK) < 0) { - goto error; // file not found - } + char *path; + if (searchFile(&path, RESOURCES_SUBDIR, "oids", ".json", false) != PM3_SUCCESS) { + return NULL; } // load `oids.json` - root = json_load_file(fname, 0, &error); + root = json_load_file(path, 0, &error); + free(path); if (!root || !json_is_object(root)) { goto error; diff --git a/client/crypto/asn1utils.c b/client/crypto/asn1utils.c index c82f4aac8..1b2c78212 100644 --- a/client/crypto/asn1utils.c +++ b/client/crypto/asn1utils.c @@ -12,6 +12,9 @@ #include #include #include + +#include "ui.h" // Print... + #include "emv/tlv.h" #include "emv/dump.h" #include "asn1dump.h" diff --git a/client/crypto/libpcrypto.c b/client/crypto/libpcrypto.c index 775080c42..31c698dc7 100644 --- a/client/crypto/libpcrypto.c +++ b/client/crypto/libpcrypto.c @@ -121,14 +121,14 @@ int sha512hash(uint8_t *input, int length, uint8_t *hash) { return 0; } -static int ecdsa_init_str(mbedtls_ecdsa_context *ctx, const char *key_d, const char *key_x, const char *key_y) { +static int ecdsa_init_str(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id curveid, const char *key_d, const char *key_x, const char *key_y) { if (!ctx) return 1; int res; mbedtls_ecdsa_init(ctx); - res = mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1); // secp256r1 + res = mbedtls_ecp_group_load(&ctx->grp, curveid); if (res) return res; @@ -147,25 +147,26 @@ static int ecdsa_init_str(mbedtls_ecdsa_context *ctx, const char *key_d, const c return 0; } -static int ecdsa_init(mbedtls_ecdsa_context *ctx, uint8_t *key_d, uint8_t *key_xy) { +static int ecdsa_init(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id curveid, uint8_t *key_d, uint8_t *key_xy) { if (!ctx) return 1; int res; mbedtls_ecdsa_init(ctx); - res = mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1); // secp256r1 + res = mbedtls_ecp_group_load(&ctx->grp, curveid); if (res) return res; + size_t keylen = (ctx->grp.nbits + 7) / 8; if (key_d) { - res = mbedtls_mpi_read_binary(&ctx->d, key_d, 32); + res = mbedtls_mpi_read_binary(&ctx->d, key_d, keylen); if (res) return res; } if (key_xy) { - res = mbedtls_ecp_point_read_binary(&ctx->grp, &ctx->Q, key_xy, 32 * 2 + 1); + res = mbedtls_ecp_point_read_binary(&ctx->grp, &ctx->Q, key_xy, keylen * 2 + 1); if (res) return res; } @@ -173,10 +174,10 @@ static int ecdsa_init(mbedtls_ecdsa_context *ctx, uint8_t *key_d, uint8_t *key_x return 0; } -int ecdsa_key_create(uint8_t *key_d, uint8_t *key_xy) { +int ecdsa_key_create(mbedtls_ecp_group_id curveid, uint8_t *key_d, uint8_t *key_xy) { int res; mbedtls_ecdsa_context ctx; - ecdsa_init(&ctx, NULL, NULL); + ecdsa_init(&ctx, curveid, NULL, NULL); mbedtls_entropy_context entropy; @@ -190,25 +191,26 @@ int ecdsa_key_create(uint8_t *key_d, uint8_t *key_xy) { if (res) goto exit; - res = mbedtls_ecdsa_genkey(&ctx, MBEDTLS_ECP_DP_SECP256R1, mbedtls_ctr_drbg_random, &ctr_drbg); + res = mbedtls_ecdsa_genkey(&ctx, curveid, mbedtls_ctr_drbg_random, &ctr_drbg); if (res) goto exit; - res = mbedtls_mpi_write_binary(&ctx.d, key_d, 32); + size_t keylen = (ctx.grp.nbits + 7) / 8; + res = mbedtls_mpi_write_binary(&ctx.d, key_d, keylen); if (res) goto exit; - size_t keylen = 0; + size_t public_keylen = 0; uint8_t public_key[200] = {0}; - res = mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &keylen, public_key, sizeof(public_key)); + res = mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &public_keylen, public_key, sizeof(public_key)); if (res) goto exit; - if (keylen != 65) { // 0x04 + if (public_keylen != 1 + 2 * keylen) { // 0x04 res = 1; goto exit; } - memcpy(key_xy, public_key, 65); + memcpy(key_xy, public_key, public_keylen); exit: mbedtls_entropy_free(&entropy); @@ -224,32 +226,36 @@ char *ecdsa_get_error(int ret) { return retstr; } -int ecdsa_public_key_from_pk(mbedtls_pk_context *pk, uint8_t *key, size_t keylen) { +int ecdsa_public_key_from_pk(mbedtls_pk_context *pk, mbedtls_ecp_group_id curveid, uint8_t *key, size_t keylen) { int res = 0; size_t realkeylen = 0; - if (keylen < 65) - return 1; mbedtls_ecdsa_context ctx; mbedtls_ecdsa_init(&ctx); - res = mbedtls_ecp_group_load(&ctx.grp, MBEDTLS_ECP_DP_SECP256R1); // secp256r1 + res = mbedtls_ecp_group_load(&ctx.grp, curveid); if (res) goto exit; + size_t private_keylen = (ctx.grp.nbits + 7) / 8; + if (keylen < 1 + 2 * private_keylen) { + res = 1; + goto exit; + } + res = mbedtls_ecdsa_from_keypair(&ctx, mbedtls_pk_ec(*pk)); if (res) goto exit; res = mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &realkeylen, key, keylen); - if (realkeylen != 65) + if (realkeylen != 1 + 2 * private_keylen) res = 2; exit: mbedtls_ecdsa_free(&ctx); return res; } -int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen) { +int ecdsa_signature_create(mbedtls_ecp_group_id curveid, uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen, bool hash) { int res; *signaturelen = 0; @@ -270,8 +276,18 @@ int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int goto exit; mbedtls_ecdsa_context ctx; - ecdsa_init(&ctx, key_d, key_xy); - res = mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256, shahash, sizeof(shahash), signature, signaturelen, mbedtls_ctr_drbg_random, &ctr_drbg); + ecdsa_init(&ctx, curveid, key_d, key_xy); + res = mbedtls_ecdsa_write_signature( + &ctx, + MBEDTLS_MD_SHA256, + hash ? shahash : input, + hash ? sizeof(shahash) : length, + signature, + signaturelen, + mbedtls_ctr_drbg_random, + &ctr_drbg + ); + exit: mbedtls_ctr_drbg_free(&ctr_drbg); @@ -279,7 +295,7 @@ exit: return res; } -static int ecdsa_signature_create_test(const char *key_d, const char *key_x, const char *key_y, const char *random, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen) { +static int ecdsa_signature_create_test(mbedtls_ecp_group_id curveid, const char *key_d, const char *key_x, const char *key_y, const char *random, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen) { int res; *signaturelen = 0; @@ -292,14 +308,14 @@ static int ecdsa_signature_create_test(const char *key_d, const char *key_x, con param_gethex_to_eol(random, 0, fixed_rand_value, sizeof(fixed_rand_value), &rndlen); mbedtls_ecdsa_context ctx; - ecdsa_init_str(&ctx, key_d, key_x, key_y); + ecdsa_init_str(&ctx, curveid, key_d, key_x, key_y); res = mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256, shahash, sizeof(shahash), signature, signaturelen, fixed_rand, NULL); mbedtls_ecdsa_free(&ctx); return res; } -static int ecdsa_signature_verify_keystr(const char *key_x, const char *key_y, uint8_t *input, int length, uint8_t *signature, size_t signaturelen) { +static int ecdsa_signature_verify_keystr(mbedtls_ecp_group_id curveid, const char *key_x, const char *key_y, uint8_t *input, int length, uint8_t *signature, size_t signaturelen, bool hash) { int res; uint8_t shahash[32] = {0}; res = sha256hash(input, length, shahash); @@ -307,28 +323,69 @@ static int ecdsa_signature_verify_keystr(const char *key_x, const char *key_y, u return res; mbedtls_ecdsa_context ctx; - ecdsa_init_str(&ctx, NULL, key_x, key_y); - res = mbedtls_ecdsa_read_signature(&ctx, shahash, sizeof(shahash), signature, signaturelen); + ecdsa_init_str(&ctx, curveid, NULL, key_x, key_y); + res = mbedtls_ecdsa_read_signature( + &ctx, + hash ? shahash : input, + hash ? sizeof(shahash) : length, + signature, + signaturelen + ); mbedtls_ecdsa_free(&ctx); return res; } -int ecdsa_signature_verify(uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t signaturelen) { +int ecdsa_signature_verify(mbedtls_ecp_group_id curveid, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t signaturelen, bool hash) { int res; uint8_t shahash[32] = {0}; - res = sha256hash(input, length, shahash); - if (res) - return res; + if (hash) { + res = sha256hash(input, length, shahash); + if (res) + return res; + } mbedtls_ecdsa_context ctx; - ecdsa_init(&ctx, NULL, key_xy); - res = mbedtls_ecdsa_read_signature(&ctx, shahash, sizeof(shahash), signature, signaturelen); + res = ecdsa_init(&ctx, curveid, NULL, key_xy); + res = mbedtls_ecdsa_read_signature( + &ctx, + hash ? shahash : input, + hash ? sizeof(shahash) : length, + signature, + signaturelen + ); mbedtls_ecdsa_free(&ctx); return res; } + +int ecdsa_signature_r_s_verify(mbedtls_ecp_group_id curveid, uint8_t *key_xy, uint8_t *input, int length, uint8_t *r_s, size_t r_s_len, bool hash) { + int res; + uint8_t signature[MBEDTLS_ECDSA_MAX_LEN]; + size_t signature_len; + + // convert r & s to ASN.1 signature + mbedtls_mpi r, s; + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + mbedtls_mpi_read_binary(&r, r_s, r_s_len / 2); + mbedtls_mpi_read_binary(&s, r_s + r_s_len / 2, r_s_len / 2); + + res = ecdsa_signature_to_asn1(&r, &s, signature, &signature_len); + if (res < 0) { + return res; + } + + res = ecdsa_signature_verify(curveid, key_xy, input, length, signature, signature_len, hash); + + mbedtls_mpi_free(&r); + mbedtls_mpi_free(&s); + + return res; +} + + #define T_PRIVATE_KEY "C477F9F65C22CCE20657FAA5B2D1D8122336F851A508A1ED04E479C34985BF96" #define T_Q_X "B7E08AFDFE94BAD3F1DC8C734798BA1C62B3A0AD1E9EA2A38201CD0889BC7A19" #define T_Q_Y "3603F747959DBF7A4BB226E41928729063ADC7AE43529E61B563BBC606CC5E09" @@ -339,6 +396,7 @@ int ecdsa_signature_verify(uint8_t *key_xy, uint8_t *input, int length, uint8_t int ecdsa_nist_test(bool verbose) { int res; uint8_t input[] = "Example of ECDSA with P-256"; + mbedtls_ecp_group_id curveid = MBEDTLS_ECP_DP_SECP256R1; int length = strlen((char *)input); uint8_t signature[300] = {0}; size_t siglen = 0; @@ -347,7 +405,7 @@ int ecdsa_nist_test(bool verbose) { if (verbose) printf(" ECDSA NIST test: "); // make signature - res = ecdsa_signature_create_test(T_PRIVATE_KEY, T_Q_X, T_Q_Y, T_K, input, length, signature, &siglen); + res = ecdsa_signature_create_test(curveid, T_PRIVATE_KEY, T_Q_X, T_Q_Y, T_K, input, length, signature, &siglen); // printf("res: %x signature[%x]: %s\n", (res<0)?-res:res, siglen, sprint_hex(signature, siglen)); if (res) goto exit; @@ -371,13 +429,13 @@ int ecdsa_nist_test(bool verbose) { } // verify signature - res = ecdsa_signature_verify_keystr(T_Q_X, T_Q_Y, input, length, signature, siglen); + res = ecdsa_signature_verify_keystr(curveid, T_Q_X, T_Q_Y, input, length, signature, siglen, true); if (res) goto exit; // verify wrong signature input[0] ^= 0xFF; - res = ecdsa_signature_verify_keystr(T_Q_X, T_Q_Y, input, length, signature, siglen); + res = ecdsa_signature_verify_keystr(curveid, T_Q_X, T_Q_Y, input, length, signature, siglen, true); if (!res) { res = 1; goto exit; @@ -394,20 +452,20 @@ int ecdsa_nist_test(bool verbose) { memset(signature, 0x00, sizeof(signature)); siglen = 0; - res = ecdsa_key_create(key_d, key_xy); + res = ecdsa_key_create(curveid, key_d, key_xy); if (res) goto exit; - res = ecdsa_signature_create(key_d, key_xy, input, length, signature, &siglen); + res = ecdsa_signature_create(curveid, key_d, key_xy, input, length, signature, &siglen, true); if (res) goto exit; - res = ecdsa_signature_verify(key_xy, input, length, signature, siglen); + res = ecdsa_signature_verify(curveid, key_xy, input, length, signature, siglen, true); if (res) goto exit; input[0] ^= 0xFF; - res = ecdsa_signature_verify(key_xy, input, length, signature, siglen); + res = ecdsa_signature_verify(curveid, key_xy, input, length, signature, siglen, true); if (!res) goto exit; diff --git a/client/crypto/libpcrypto.h b/client/crypto/libpcrypto.h index 38d37b66a..b4307f454 100644 --- a/client/crypto/libpcrypto.h +++ b/client/crypto/libpcrypto.h @@ -24,10 +24,12 @@ int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int lengt int sha256hash(uint8_t *input, int length, uint8_t *hash); int sha512hash(uint8_t *input, int length, uint8_t *hash); -int ecdsa_key_create(uint8_t *key_d, uint8_t *key_xy); -int ecdsa_public_key_from_pk(mbedtls_pk_context *pk, uint8_t *key, size_t keylen); -int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen); -int ecdsa_signature_verify(uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t signaturelen); +int ecdsa_key_create(mbedtls_ecp_group_id curveid, uint8_t *key_d, uint8_t *key_xy); +int ecdsa_public_key_from_pk(mbedtls_pk_context *pk, mbedtls_ecp_group_id curveid, uint8_t *key, size_t keylen); +int ecdsa_signature_create(mbedtls_ecp_group_id curveid, uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen, bool hash); +int ecdsa_signature_verify(mbedtls_ecp_group_id curveid, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t signaturelen, bool hash); +int ecdsa_signature_r_s_verify(mbedtls_ecp_group_id curveid, uint8_t *key_xy, uint8_t *input, int length, uint8_t *r_s, size_t r_s_len, bool hash); + char *ecdsa_get_error(int ret); int ecdsa_nist_test(bool verbose); diff --git a/client/default_iclass_keys.dic b/client/default_iclass_keys.dic deleted file mode 100644 index 829ba521e..000000000 --- a/client/default_iclass_keys.dic +++ /dev/null @@ -1,11 +0,0 @@ -# -# iClass Default Keys -# -- iceman fork version -- -# -- contribute to this list, sharing is caring -- -AEA684A6DAB23278 -- AA1 -7665544332211000 -- key1/Kc from PicoPass 2k documentation -0123456789ABCDEF -- SAGEM -5b7c62c491c11b39 -- from loclass demo file. -F0E1D2C3B4A59687 -- Kd from PicoPass 2k documentation -5CBCF1DA45D5FB4F -- PicoPass Default Exchange Key -31ad7ebd2f282168 -- From HID multiclassSE reader diff --git a/client/default_keys.dic b/client/default_keys.dic deleted file mode 100644 index 81b03fe2c..000000000 --- a/client/default_keys.dic +++ /dev/null @@ -1,953 +0,0 @@ -# -# Mifare Default Keys -# -- iceman fork version -- -# -- contribute to this list, sharing is caring -- -# -ffffffffffff,//Defaultkey(firstkeyusedbyprogramifnouserdefinedkey) -000000000000,//Blankkey -a0a1a2a3a4a5,//NFCForumMADkey -b0b1b2b3b4b5, -c0c1c2c3c4c5, -d0d1d2d3d4d5, -aabbccddeeff, -4d3a99c351dd, -1a982c7e459a, -d3f7d3f7d3f7,// key A Wien -5a1b85fce20a,// key B Wien -714c5c886e97, -587ee5f9350f, -a0478cc39091, -533cb6c723f6, -8fd0a4f256e9, -# -d2ece8b9395e, //lib -# -# more Keys from mf_default_keys.lua -000000000001, -000000000002, -00000000000a, -00000000000b, -00000ffe2488,--VästtrafikenKeyB -010203040506, -0123456789ab, -0297927c0f77,--VästtrafikenKeyA -100000000000, -111111111111, -123456789abc, -12f2ee3478c1, -14d446e33363, -1999a3554a55, -200000000000, -222222222222, -26940b21ff5d,--RKFSLKeyA -27dd91f1fcf1, -2BA9621E0A36,--DirectoryandeventlogKeyB -333333333333, -33f974b42769, -34d1df9934c5, -434f4d4d4f41,--RKFJOJOGROUPKeyA -434f4d4d4f42,--RKFJOJOGROUPKeyB -43ab19ef5c31, -444444444444, -47524f555041,--RKFJOJOGROUPKeyA -47524f555042,--RKFJOJOGROUPKeyB -4AF9D7ADEBE4,--DirectoryandeventlogKeyA -4b0b20107ccb,--TNP3xxx -505249564141,--RKFJOJOPRIVAKeyA -505249564142,--RKFJOJOPRIVAKeyB -505249565441, -505249565442, -54726176656c,--VästtrafikenKeyA -555555555555, -55f5a5dd38c9, -569369c5a0e5,--kiev -5c598c9c58b5,--RKFSLKeyB -632193be1c3c,--kiev -644672bd4afe,--kiev -666666666666, -722bfcc5375f,--RKFRejskortDanmarkKeyA -776974687573,--VästtrafikenKeyB -777777777777, -888888888888, -8fe644038790,--kiev -999999999999, -99c636334433, -9de89e070277,--kiev -a00000000000, -a053a292a4af, -a64598a77478,--RKFSLKeyA -a94133013401, -aaaaaaaaaaaa, -abcdef123456,--Keyfromladyada.net -b00000000000, -b127c6f41436, -b5ff67cba951,--kiev -bbbbbbbbbbbb, -bd493a3962b6, -c934fe34d934, -cccccccccccc, -dddddddddddd, -e4d2770a89be,--RKFSLKeyB -ee0042f88840,--VästtrafikenKeyB -eeeeeeeeeeee, -eff603e1efe9,--kiev -f14ee7cae863,--kiev -f1a97341a9fc, -f1d83f964314,--RKFRejskortDanmarkKeyB -fc00018778f7,--VästtrafikenKeyA, RKFÖstgötaTrafikenKeyA -44ab09010845,-- hotel system -85fed980ea5a,-- hotel system -314B49474956 --VIGIK1 A -564c505f4d41 --VIGIK1 B -ba5b895da162 --VIGIK1 B -# Vigik mystery Keys Mifare 1k EV1 (S50) -5c8ff9990da2, 16 A -75ccb59c9bed, 17 A -d01afeeb890a, 16 B -4b791bea7bcc, 17 B -# -4143414F5250, -a9b43414F585,--Tehran Railway -1FB235AC1388,--Tehran Railway -# -# Data from: http://irq5.io/2013/04/13/decoding-bcard-conference-badges/ -f4a9ef2afc6d,--BCARD KeyB -# -# -a9f953def0a3,-- -# -# Here be BIP keys... -3A42F33AF429, -1FC235AC1309, -6338A371C0ED, -243F160918D1, -F124C2578AD0, -9AFC42372AF1, -32AC3B90AC13, -682D401ABB09, -4AD1E273EAF1, -067DB45454A9, -E2C42591368A, -15FC4C7613FE, -2A3C347A1200, -68D30288910A, -16F3D5AB1139, -F59A36A2546D, -937A4FFF3011, -64E3C10394C2, -35C3D2CAEE88, -B736412614AF, -693143F10368, -324F5DF65310, -A3F97428DD01, -643FB6DE2217, -63F17A449AF0, -82F435DEDF01, -C4652C54261C, -0263DE1278F3, -D49E2826664F, -51284C3686A6, -3DF14C8000A1, -6A470D54127C, -# -# Data from: http://pastebin.com/AK9Bftpw -48ffe71294a0, -- Länstrafiken i Västerbotten -e3429281efc1, -- Länstrafiken i Västerbotten -16f21a82ec84, -- Länstrafiken i Västerbotten -460722122510, -- Länstrafiken i Västerbotten -# -# 3dprinter -AAFB06045877, --EPI Envisionte# 3dprinter -# -# gym -3e65e4fb65b3, --Fysiken A -25094df6f148, --Fysiken B -# -# 24-7 -D21762B2DE3B, -0E83A374B513, -1F1FFE000000, -A10F303FC879, -1322285230b8, -0C71BCFB7E72, -C3C88C6340B8, -F101622750B7, -1F107328DC8D, -710732200D34, -7C335FB121B5, -B39AE17435DC, -# -# -454841585443, -- key A -# -# Data from: http://pastebin.com/gQ6nk38G -D39BB83F5297, -85675B200017, -528C9DFFE28C, -C82EC29E3235, -3E3554AF0E12, -491CDCFB7752, -22C1BAE1AACD, -5F146716E373, -740E9A4F9AAF, -AC0E24C75527, -97184D136233, -E444D53D359F, -17758856B182, -A8966C7CC54B, -C6AD00254562, -AE3FF4EEA0DB, -5EB8F884C8D1, -FEE470A4CB58, -75D8690F21B6, -871B8C085997, -97D1101F18B0, -75EDE6A84460, -DF27A8F1CB8E, -B0C9DD55DD4D, -# -# Data from: http://bit.ly/1bdSbJl -A0B0C0D0E0F0, -A1B1C1D1E1F1, -# -# Data from: msk social -2735fc181807, -2aba9519f574, -84fd7f7a12b6, -186d8c4b93f9, -3a4bba8adaf0, -8765b17968a2, -40ead80721ce, -0db5e6523f7c, -51119dae5216, -83e3549ce42d, -136bdb246cac, -7de02a7f6025, -bf23a53c1f63, -cb9a1f2d7368, -c7c0adb3284f, -9f131d8c2057, -67362d90f973, -6202a38f69e2, -100533b89331, -653a87594079, -d8a274b2e026, -b20b83cb145c, -9afa6cb4fc3d, -# -# Data from http://pastebin.com/RRJUEDCM -0d258fe90296, -e55a3ca71826, -a4f204203f56, -eeb420209d0c, -911e52fd7ce4, -752fbb5b7b45, -66b03aca6ee9, -48734389edc3, -17193709adf4, -1acc3189578c, -c2b7ec7d4eb1, -369a4663acd2, -# -# Data from https://github.com/zhangjingye03/zxcardumper -# zxcard Key A/B -668770666644, -003003003003, -# -# Data from: http://phreakerclub.com/forum/showthread.php?p=41266 -26973ea74321, -71f3a315ad26, -51044efb5aab, -ac70ca327a04, -eb0a8ff88ade, -# -# Data from: https://github.com/RadioWar/NFCGUI -44dd5a385aaf, -21a600056cb0, -b1aca33180a5, -dd61eb6bce22, -1565a172770f, -3e84d2612e2a, -f23442436765, -79674f96c771, -87df99d496cb, -c5132c8980bc, -a21680c27773, -f26e21edcee2, -675557ecc92e, -f4396e468114, -6db17c16b35b, -4186562a5bb2, -2feae851c199, -db1a3338b2eb, -157b10d84c6b, -a643f952ea57, -df37dcb6afb3, -4c32baf326e0, -91ce16c07ac5, -3c5d1c2bcd18, -c3f19ec592a2, -f72a29005459, -185fa3438949, -321a695bd266, -d327083a60a7, -45635ef66ef3, -5481986d2d62, -cba6ae869ad5, -645a166b1eeb, -a7abbc77cc9e, -f792c4c76a5c, -bfb6796a11db, -# -# Data from Salto A/B -6A1987C40A21, -7F33625BC129, -# -# Data from forum -2338b4913111, -# -# Data from stoye -cb779c50e1bd, -a27d3804c259, -003cc420001a, -f9861526130f, -381ece050fbd, -a57186bdd2b9, -48c739e21a04, -36abf5874ed7, -649d2abbbd20, -bbe8fffcf363, -ab4e7045e97d, -340e40f81cd8, -e4f65c0ef32c, -d2a597d76936, -a920f32fe93a, -86afd95200f7, -9b832a9881ff, -26643965b16e, -0c669993c776, -b468d1991af9, -d9a37831dce5, -2fc1f32f51b1, -0ffbf65b5a14, -c5cfe06d9ea3, -c0dece673829, -# -a56c2df9a26d, -# -# Data from: https://pastebin.com/vbwast74 -# -68d3f7307c89, -568c9083f71c,--Smart Rider. Western Australian Public Transport Cards -# Vigik Keys -# Various sources : -# * https://github.com/DumpDos/Vigik -# * http://newffr.com/viewtopic.php?&forum=235&topic=11559 -# * Own dumps -021209197591, // BTCINO UNDETERMINED SPREAKD 0x01->0x13 key -2ef720f2af76, -414c41524f4e, -424c41524f4e, -4a6352684677, -bf1f4424af76, -536653644c65, -# -# Intratone Cogelec -# Data from http://bouzdeck.com/rfid/32-cloning-a-mifare-classic-1k-tag.html -484558414354, -a22ae129c013, -49fae4e3849f, -38fcf33072e0, -8ad5517b4b18, -509359f131b1, -6c78928e1317, -aa0720018738, -a6cac2886412, -62d0c424ed8e, -e64a986a5d94, -8fa1d601d0a2, -89347350bd36, -66d2b7dc39ef, -6bc1e1ae547d, -22729a9bd40f, -# -# Data from https://dfir.lu/blog/cloning-a-mifare-classic-1k-tag.html -925b158f796f, -fad63ecb5891, -bba840ba1c57, -cc6b3b3cd263, -6245e47352e6, -8ed41e8b8056, -2dd39a54e1f3, -6d4c5b3658d2, -1877ed29435a, -52264716efde, -961c0db4a7ed, -703140fd6d86, -157c9a513fa5, -e2a5dc8e066f, -# -# Data from a oyster card -374bf468607f, -bfc8e353af63, -15cafd6159f6, -62efd80ab715, -987a7f7f1a35, -c4104fa3c526, -4c961f23e6be, -67546972bc69, -f4cd5d4c13ff, -94414c1a07dc, -16551d52fd20, -9cb290282f7d, -77a84170b574, -ed646c83a4f3, -e703589db50b, -513c85d06cde, -95093f0b2e22, -543b01b27a95, -c6d375b99972, -ee4cc572b40e, -5106ca7e4a69, -c96bd1ce607f, -167a1be102e0, -a8d0d850a606, -a2abb693ce34, -7b296c40c486, -91f93a5564c9, -e10623e7a016, -b725f9cbf183, -# -# Data from FDi tag -8829da9daf76, -# -# Data from GitHub issue -0A7932DC7E65, -11428B5BCE06, -11428B5BCE07, -11428B5BCE08, -11428B5BCE09, -11428B5BCE0A, -11428B5BCE0F, -18971D893494, -25D60050BF6E, -3FA7217EC575, -44F0B5FBE344, -7B296F353C6B, -8553263F4FF0, -8E5D33A6ED51, -9F42971E8322, -C620318EF179, -D4FE03CE5B06, -D4FE03CE5B07, -D4FE03CE5B08, -D4FE03CE5B09, -D4FE03CE5B0A, -D4FE03CE5B0F, -E241E8AFCBAF, -# -# Data from forum post -123F8888F322, -050908080008, -# -# Data from hoist -4f9f59c9c875, -# -# Data from pastebin -66f3ed00fed7, -f7a39753d018, -# -# Data from https://pastebin.com/Z7pEeZif -386B4D634A65, -666E564F4A44, -564777315276, -476242304C53, -6A696B646631, -4D3248735131, -425A73484166, -57784A533069, -345547514B4D, -4C6B69723461, -4E4175623670, -4D5076656D58, -686A736A356E, -484A57696F4A, -6F4B6D644178, -744E326B3441, -70564650584F, -584F66326877, -6D4E334B6C48, -6A676C315142, -77494C526339, -623055724556, -356D46474348, -4E32336C6E38, -57734F6F6974, -436A46587552, -5544564E6E67, -6F506F493353, -31646241686C, -77646B633657, -# -# Data from TransPert -2031d1e57a3b, -53c11f90822a, -9189449ea24e, -# -# data from Github -410b9b40b872, -2cb1a90071c8, -# -# data from -8697389ACA26, -1AB23CD45EF6, -013889343891, -# -# -0000000018de, -16ddcb6b3f24, -# -# Data from https://pastebin.com/vwDRZW7d -EC0A9B1A9E06,--Vingcard Mifare 4k Staff card -6C94E1CED026,--Vingcard Mifare 4k Staff card -0F230695923F,--Vingcard Mifare 4k Staff card -0000014B5C31,--Vingcard Mifare 4k Staff card -# -BEDB604CC9D1, -B8A1F613CF3D, -B578F38A5C61, -AD4FB33388BF, -69FB7B7CD8EE, -2A6D9205E7CA, -2a2c13cc242a, -27FBC86A00D0, -01FA3FC68349, -# -6D44B5AAF464,--Smart Rider. Western Australian Public Transport Cards -1717E34A7A8A,--Smart Rider. Western Australian Public Transport Cards -# -6B6579737472,--RFIDeas -# -484944204953,--HID MIFARE Classic 1k Key -204752454154,--HID MIFARE Classic 1k Key -3B7E4FD575AD,--HID MIFARE SO -11496F97752A,--HID MIFARE SO -# -415A54454B4D,--Luxeo/Aztek cashless vending -# -321958042333,--BQT -# -160A91D29A9C,--Aperio KEY_A Sector 1, 12, 13, 14, 15 Data Start 0 Length 48 -# -b7bf0c13066e,--Gallagher -# -# Boston, MA, USA Transit - MBTA Charlie Card -3060206f5b0a,-- charlie -5ec39b022f2b,-- charlie -3a09594c8587,-- charlie -f1b9f5669cc8,-- charlie -f662248e7e89,-- charlie -62387b8d250d,-- charlie -f238d78ff48f,-- charlie -9dc282d46217,-- charlie -afd0ba94d624,-- charlie -92ee4dc87191,-- charlie -b35a0e4acc09,-- charlie -756ef55e2507,-- charlie -447ab7fd5a6b,-- charlie -932b9cb730ef,-- charlie -1f1a0a111b5b,-- charlie -ad9e0a1ca2f7,-- charlie -d58023ba2bdc,-- charlie -62ced42a6d87,-- charlie -2548a443df28,-- charlie -2ed3b15e7c0f,-- charlie -# -60012e9ba3fa, -# -de1fcbec764b, -81bfbe8cacba, -bff123126c9b, -2f47741062a0, -b4166b0a27ea, -a170d9b59f95, -400bc9be8976, -d80511fc2ab4, -1fcef3005bcf, -bb467463acd6, -e67c8010502d, -ff58ba1b4478, -# Data from https://pastebin.com/Kz8xp4ev -fbf225dc5d58, -# -# Data https://pastebin.com/BEm6bdAE -# vingcard.txt -4708111c8604, -3d50d902ea48, -96a301bce267, -6700f10fec09, -7a09cc1db70a, -560f7cff2d81, -66b31e64ca4b, -9e53491f685b, -3a09911d860c, -8a036920ac0c, -361f69d2c462, -d9bcde7fc489, -0c03a720f208, -6018522fac02, -# -# Data from https://pastebin.com/4t2yFMgt -# Mifare technische Universität Graz TUG -D58660D1ACDE, -50A11381502C, -C01FC822C6E5, -0854BF31111E, -# More keys: -8a19d40cf2b5, -ae8587108640, -135b88a94b8b, SafLock standalone door locks. -# -# Russian Troika card -08B386463229, -0E8F64340BA4, -0F1C63013DBA, -2AA05ED1856F, -2B7F3253FAC5, -69A32F1C2F19, -73068F118C13, -9BECDF3D9273, -A73F5DC1D333, -A82607B01C0D, -AE3D65A3DAD4, -CD4C61C26E3D, -D3EAFB5DF46D, -E35173494A81, -FBC2793D540B, -5125974CD391, -ECF751084A80, -7545DF809202, -AB16584C972A, -7A38E3511A38, -C8454C154CB5, -04C297B91308, -EFCB0E689DB3, -07894FFEC1D6, -FBA88F109B32, -2FE3CB83EA43, -B90DE525CEB6, -1CC219E9FEC1, -A74332F74994, -764CD061F1E6, -8F79C4FD8A01, -CD64E567ABCD, -CE26ECB95252, -ABA208516740, -9868925175BA, -16A27AF45407, -372CC880F216, -3EBCE0925B2F, -73E5B9D9D3A4, -0DB520C78C1C, -70D901648CB9, -C11F4597EFB5, -B39D19A280DF, -403D706BA880, -7038CD25C408, -6B02733BB6EC, -EAAC88E5DC99, -4ACEC1205D75, -2910989B6880, -31C7610DE3B0, -5EFBAECEF46B, -F8493407799D, -6B8BD9860763, -D3A297DC2698, -# -# Keys from MifareClassicTool project -044CE1872BC3, -045CECA15535, -0BE5FAC8B06A, -0CE7CD2CC72B, -0EB23CC8110B, -0F01CEFF2742, -0F318130ED18, -114D6BE9440C, -18E3A02B5EFF, -19FC84A3784B, -1B61B2E78C75, -22052B480D11, -3367BFAA91DB, -3A8A139C20B4, -42E9B54E51AB, -46D78E850A7E, -4B609876BBA3, -518DC6EEA089, -6B07877E2C5C, -7259FA0197C6, -72F96BDD3714, -7413B599C4EA, -77DABC9825E1, -7A396F0D633D, -7A86AA203788, -8791B2CCB5C4, -8A8D88151A00, -8C97CD7A0E56, -8E26E45E7D65, -9D993C5D4EF4, -9EA3387A63C1, -A3FAA6DAFF67, -A7141147D430, -AAFB06045877, -ACFFFFFFFFFF, -AFCEF64C9913, -B27ADDFB64B0, -B81F2B0C2F66, -B9F8A7D83978, -BAFF3053B496, -BB52F8CCE07F, -BC2D1791DEC1, -BC4580B7F20B, -C65D4EAA645B, -C76BF71A2509, -D5524F591EED, -E328A1C7156D, -E4821A377B75, -E56AC127DD45, -EA0FD73CB149, -FC0001877BF7, -FD8705E721B0, -00ada2cd516d, -# -# -D3F7D3F7D3F7 -## -237a4d0d9119, -0ed7846c2bc9, -FFFFD06F83E3, -FFFFAE82366C, -F89C86B2A961, -F83466888612, -ED3A7EFBFF56, -E96246531342, -E1DD284379D4, -DFED39FFBB76, -DB5181C92CBE, -CFC738403AB0, -BCFE01BCFE01, -BA28CFD15EE8, -B0699AD03D17, -AABBCC660429, -A4EF6C3BB692, -A2B2C9D187FB, -9B1DD7C030A1, -9AEDF9931EC1, -8F9B229047AC, -872B71F9D15A, -833FBD3CFE51, -5D293AFC8D7E, -5554AAA96321, -474249437569, -435330666666, -1A2B3C4D5E6F, -123456ABCDEF, -83BAB5ACAD62, -64E2283FCF5E, -64A2EE93B12B, -46868F6D5677, -40E5EA1EFC00, -37D4DCA92451, -2012053082AD, -2011092119F1, -200306202033, -1795902DBAF9, -17505586EF02, -022FE48B3072, -013940233313, -# -# Hotel Adina -9EBC3EB37130, -# -# mostlikely diverised individual keys. -# data from: https://github.com/korsehindi/proxmark3/commit/24fdbfa9a1d5c996aaa5c192bc07e4ab28db4c5c -491CDC863104, -A2F63A485632, -98631ED2B229, -19F1FFE02563, -563A22C01FC8, -- Argentina -43CA22C13091, -- Argentina -25094DF2C1BD, -- Argentina -# -# OMNITEC.ES HOTEL TIMECARD / MAINTENANCECARD -AFBECD120454, -# -# OMNITEC.ES HOTEL EMERGENCYCARD -842146108088, -# -# TAPCARD PUBLIC TRANSPORT LA -# -EA1B88DF0A76, -D1991E71E2C5, -05F89678CFCF, -D31463A7AB6D, -C38197C36420, -772219470B38, -1C1532A6F1BC, -FA38F70215AD, -E907470D31CC, -160F4B7AB806, -1D28C58BBE8A, -B3830B95CA34, -6A0E215D1EEB, -E41E6199318F, -C4F271F5F0B3, -1E352F9E19E5, -0E0E8C6D8EB6, -C342F825B01B, -CB911A1A1929, -E65B66089AFC, -B81846F06EDF, -37FC71221B46, -880C09CFA23C, -6476FA0746E7, -419A13811554, -2C60E904539C, -4ECCA6236400, -10F2BBAA4D1C, -4857DD68ECD9, -C6A76CB2F3B5, -E3AD9E9BA5D4, -6C9EC046C1A4, -# -# ROC HIGHSCHOOL ACCESSCARD -# -B021669B44BB, -B18CDCDE52B7, -A22647F422AE, -B268F7C9CA63, -A37A30004AC9, -B3630C9F11C8, -A4CDFF3B1848, -B42C4DFD7A90, -A541538F1416, -B5F454568271, -A6C028A12FBB, -B6323F550F54, -A7D71AC06DC2, -B7C344A36D88, -A844F4F52385, -B8457ACC5F5D, -A9A4045DCE77, -B9B8B7B6B5B3, -AA4D051954AC, -BA729428E808, -AB28A44AD5F5, -BB320A757099, -AC45AD2D620D, -BCF5A6B5E13F, -AD5645062534, -BDF837787A71, -AE43F36C1A9A, -BE7C4F6C7A9A, -5EC7938F140A, -82D58AA49CCB, -# -# MELONCARD -# -323334353637, -# -# -CEE3632EEFF5, -827ED62B31A7, -03EA4053C6ED, -C0BEEFEC850B, -F57F410E18FF, -0AF7DB99AEE4, -A7FB4824ACBF, -207FFED492FD, -1CFA22DBDFC3, -30FFB6B056F5, -39CF885474DD, -00F0BD116D70, -4CFF128FA3EF, -10F3BEBC01DF, -# -# Transportes Insular La Palma -# -0172066b2f03, -0000085f0000, -1a80b93f7107, -70172066b2f0, -b1a80c94f710, -0b0172066b2f, -0f1a81c95071, -f0f0172066b2, -1131a81d9507, -2f130172066b, -71171a82d951, -b2f170172066, -1711b1a82e96, -6b2f1b017206, -62711f1a83e9, -66b2f1f01720, -97271231a83f, -066b2f230172, -f97371271a84, -2066b2f27017, -50983712b1a8, -72066b2f2b01, -850984712f1a, -172066b2f2f0, -a85198481331, -0172066b2f33, -1a8619858137, -70172066b2f3, -b1a862985913, -3b0172066b2f, -3f1a87298691, -f3f0172066b2, -# -# Tehran ezpay -# -38A88AEC1C43 -CBD2568BC7C6 -7BCB4774EC8F -22ECE9316461 -AE4B497A2527 -EEC0626B01A1 -2C71E22A32FE -91142568B22F -7D56759A974A -D3B1C7EA5C53 -41C82D231497 -0B8B21C692C2 -604Ac8D87C7E -8E7B29460F12 -BB3D7B11D224 -# -# Chaco -# -b210cfa436d2 -b8b1cfa646a8 -a9f95891f0a4 -# -# Keys from APK application "Scan Badge" -4A4C474F524D -444156494442 -434143445649 -434456495243 -A00002000021 -EF61A3D48E2A -A23456789123 -010000000000 -363119000001 -A00003000084 -675A32413770 -395244733978 -A0004A000036 -2C9F3D45BA13 -4243414F5250 -DFE73BE48AC6 -# -B069D0D03D17 -000131B93F28 diff --git a/client/default_pwd.dic b/client/default_pwd.dic deleted file mode 100644 index aa2b23719..000000000 --- a/client/default_pwd.dic +++ /dev/null @@ -1,123 +0,0 @@ -# known cloners -# ref. http://www.proxmark.org/forum/viewtopic.php?id=2022 -51243648, -000D8787, -19920427, -65857569, //chinese "handheld RFID writer" blue cloner from circa 2013 (also sold by xfpga.com) -# ref. http://kazus.ru/forums/showpost.php?p=1045937&postcount=77 -05D73B9F, -# ref. http://www.proxmark.org/forum/viewtopic.php?= -89A69E60, -# ref lock -314159E0, -# ref. http://www.proxmark.org/forum/viewtopic.php?pid=28115#p28115 -AA55BBBB, -# ref. http://www.proxmark.org/forum/viewtopic.php?pid=33376#p33376 -A5B4C3D2, -# ref. http://www.proxmark.org/forum/viewtopic.php?pid=30379#p30379 -1C0B5848, -# http://www.proxmark.org/forum/viewtopic.php?pid=35075#p35075 -00434343, -44B44CAE, -88661858, -# paxton bullit? -575F4F4B, -# -50520901, -# Default pwd, simple: -00000000, -11111111, -22222222, -33333333, -44444444, -55555555, -66666666, -77777777, -88888888, -99999999, -AAAAAAAA, -BBBBBBBB, -CCCCCCCC, -DDDDDDDD, -EEEEEEEE, -FFFFFFFF, -a0a1a2a3, -b0b1b2b3, -aabbccdd, -bbccddee, -ccddeeff, -50415353, -00000001, -00000002, -0000000a, -0000000b, -01020304, -02030405, -03040506, -04050607, -05060708, -06070809, -0708090A, -08090A0B, -090A0B0C, -0A0B0C0D, -0B0C0D0E, -0C0D0E0F, -01234567, -12345678, -10000000, -20000000, -30000000, -40000000, -50000000, -60000000, -70000000, -80000000, -90000000, -A0000000, -B0000000, -C0000000, -D0000000, -E0000000, -F0000000, -10101010, -01010101, -11223344, -22334455, -33445566, -44556677, -55667788, -66778899, -778899AA, -8899AABB, -99AABBCC, -AABBCCDD, -BBCCDDEE, -CCDDEEFF, -0CB7E7FC, //rfidler? -FABADA11, //china? -# 20 most common len==8 -87654321, -12341234, -69696969, -12121212, -12344321, -1234ABCD, -11112222, -13131313, -10041004, -# -31415926, //pii -abcd1234, -20002000, -19721972, -aa55aa55, // amiboo -55aa55aa, // rev amiboo -4f271149, // seeds ul-ev1 -07d7bb0b, // seeds ul-ev1 -9636ef8f, // seeds ul-ev1 -b5f44686, // seeds ul-ev1 -9E3779B9, // TEA -C6EF3720, // TEA -7854794A, // xbox tea constant :) -F1EA5EED, // burtle diff --git a/client/dictionaries/bmp_sort_keys.dic b/client/dictionaries/bmp_sort_keys.dic deleted file mode 100644 index 0f8acdcf3..000000000 --- a/client/dictionaries/bmp_sort_keys.dic +++ /dev/null @@ -1,1000 +0,0 @@ -002DE0301481, -004173272D18, -0058A4884CA5, -00BAC32761D8, -00BB79731B00, -00E8C85DB172, -02096124DA70, -024988BC4D5E, -0271B7C4B015, -028137A705DB, -02827C286AB4, -02C10DA600D0, -0340643D5E27, -037A5DA4682B, -037AC43CBD9D, -037B9B8AA219, -037EE3DE21B7, -0380A9A3CBDE, -03D10A75B56A, -03E8CD22E691, -04109ED8EA79, -04361330B35C, -043D8B66D569, -045E5588845C, -048DE5148DE7, -0490921D0194, -04B717BD92EB, -04D49C76623B, -051518B3301E, -0529E8827A52, -052B16064085, -05DC4016B500, -06124317A9A6, -06147D199266, -0670AEB833CE, -0686A9E6D6E0, -06A34E5E6639, -06B78AD0C4BB, -0710E7818AB8, -07121B8C633A, -07176713C0ED, -0793533A5087, -081D1B1C3110, -0849495E1CCA, -09429512046E, -0966C3B28E04, -098A92C3660A, -098B48278122, -099672009EEA, -0A7632943926, -0AEE126549DA, -0B3B8C2833BC, -0B733C13E2C9, -0B764247D00E, -0BE811559D69, -0C208AD4E4B3, -0C270BC0BDDC, -0C5D782CB183, -0C82C94EB11B, -0CCDE948878A, -0CCE39820AAE, -0CDE3E716B32, -0CE06C96DB4C, -0CE87813E389, -0D3385CEA152, -0D5C5B8BCC5B, -0DB0A87AB882, -0DE247593B93, -0E0AD1796003, -0E62E6CAC3D3, -106E2D6E55E6, -1096A7830C82, -11549C141AD9, -116A92C793D6, -116C31526819, -11C68052AAE9, -1234B5BE8E78, -1268C7D104E1, -12A21B5671A8, -13359D5AE9A5, -1426EC62BB6C, -144489B1056E, -14A22C112090, -14C9BBB5361B, -14EB6286AC57, -14EE72B27223, -153BB53ACE71, -157B03405B38, -15A45083D24E, -15DACCE8D5EC, -16124677BBC5, -16373A44D5D7, -1663659384DC, -167828B6105C, -16B25A453093, -1706B1BE25C7, -171B15888483, -17BC8EED9A0C, -17C6299D5A37, -17E9C4C416EB, -1804087C7166, -1841CC4E3E79, -18AB05761CC5, -18ADAAC2B08B, -18E566417E5C, -191390328752, -1A47959E7DB4, -1A9A970CC370, -1B095E78BB33, -1B1717043D2B, -1B1A054566D9, -1B4654AE9454, -1B9CD1ED3420, -1B9E00780953, -1BB6A9CE71E2, -1C1250A36A13, -1C2316079532, -1C2855ED7A10, -1CD1AE73CA8C, -1CD3D4E690B7, -1D0322005969, -1D09B23EB116, -1D67A32045ED, -1D89D900968A, -1DAE8D2CEA5C, -1E1873799CD7, -1E60CE7C5179, -1E6A67909B8D, -1E8516585792, -1EB0864E9134, -1ECE3D04A020, -2009828E4A21, -200A6A3AA65D, -20188A599582, -20267CB20256, -20628CA7D92D, -2077C980EB2E, -2089B5D68B27, -209481EC6256, -20B6691C64B1, -20CC5A00C677, -211473555436, -2170E9D0D448, -219529A90EDD, -21A5B6481B7D, -224A308017D1, -227D16EA455A, -22A1245CA266, -22A95CB798DC, -230E26964171, -231173B68E46, -2332BB9A2452, -234323BC2992, -234E50256146, -235C9338D5B6, -23789D9ADD0D, -23997DD240AB, -23A5BA53AD4D, -23BB58853461, -24CAD4153036, -24CE79506842, -25228ED714BC, -257377227B34, -2584287A0174, -2616192EEB22, -265C03B50877, -26D641E834DC, -27073B57132B, -279060E3DEE9, -284BA0A0A29C, -285C6604C5B4, -28B20331245A, -28D042242A83, -28DDD4C3E9C4, -292C2CCD157E, -299ABB519354, -2A41BE015C1D, -2A4A55052A51, -2A94CBCD7A6E, -2AB6536187C7, -2B2D2DC3D319, -2BD607CA70B2, -2C6C7957EB3E, -2C9E9E4D0895, -2D2A97DD45E3, -2D41850A8AA6, -2DAC030D1AB9, -2E12426D8847, -2E25AD1D6D8D, -2E2E85E0E6C9, -2E4340CC1C63, -2E6803BE2E11, -2EB24B573DCD, -2EC6450A47C7, -2ECDA9A5EA96, -2EDE1C155023, -302D5D37342B, -303645E47667, -303B30A460E8, -3048EBB8A18E, -30BD652BED24, -30CCE5ECB397, -310241E1CB36, -312670228372, -319E8895EAB5, -31E3A933BC4A, -3250D2E661DA, -32560224418D, -32589E221D10, -326657A8E9C0, -329AC7C59311, -32A091B89995, -3312C094BD20, -336C8CBA5AE2, -34240649314A, -3493D84E6317, -349A347186D7, -349BEAC5210E, -34A939B49EDC, -34CC7E36C8C4, -34D71347877E, -34DC25B4D0CE, -35895EB472C4, -358A6A398211, -360A08C66042, -36306A9CA571, -37284428A250, -377EC8A78B8D, -37BD90A68613, -37E602347133, -382DE6AB2D1A, -385D498B5390, -38B67589E47D, -393CCCCCDA4A, -39682B3E10B5, -397619525709, -39A83A32909B, -3A5834C46513, -3A70C7A4BCE4, -3A818D01E093, -3AA5AC1CDC21, -3AAE07339954, -3B4497052B42, -3B784087DB2D, -3B86A20C16EA, -3B8E321AB1B4, -3BC4A3099B0D, -3BC741376E71, -3C4C95D0A0C7, -3C84B55A5E54, -3C888A88C59D, -3D5C8240B2D2, -3DB004172BE7, -3E23271C1C15, -3E3188294ED1, -3E84144A770E, -3EA227893101, -3EB914E70076, -3EE6D4A85643, -40DABA780B41, -4119340759A2, -415210E0C6BB, -416D21717779, -41B1839829A9, -4201A36DE766, -4261A795D5A7, -42AA0B29626E, -430265958BEB, -4317C5C16EAD, -431D799E0C89, -4342794AD7BB, -4387ADE263DB, -43982124C310, -4436CB060568, -44449507B736, -44E858C82975, -459BC12982B1, -45AE5DDA9830, -45C414CDC347, -45CE4E504C06, -461744C8EABD, -46D012CA3BEC, -47170BD112B6, -47C43D5DD234, -47CD4AC26271, -47D410D1C7C4, -4808C5AD0115, -485BEEDBC293, -486001404A80, -488CCC60B70A, -49204E3CA169, -495657C78147, -4970714D53D9, -4AA715A0BBB4, -4B9901AEC16E, -4BE0B912A5A3, -4CBC34D10D83, -4CD3ACABC6A3, -4CE00134DE1E, -4CEB27151C49, -4D02A3D7CE48, -4D13683C7960, -4D1A263BA48B, -4D23919463A3, -4D9763C083D9, -4DAC8EE52C68, -4DCB89C7B2E6, -4DD9D9B637C4, -4DE6CB63A920, -4DEBA10CC85D, -4E232A8C2E30, -4E2879A411E7, -4EA7B0BED74B, -4EB8761372EA, -4EC2B23135AB, -4EC71DB088DE, -4EC9AB4B5519, -50179E461EE6, -50265ED9D468, -5047DC2975BE, -508357498162, -508BE54D326E, -510A8C52AAC4, -511335CC92CD, -518229589A81, -5184D04315D7, -51B4AE31B246, -526EDB918BEE, -529CE44BEBCC, -52A843082BB3, -52AE9A909674, -5313E9079489, -532DE5E7E0E9, -535508AA6C91, -53691569B669, -540A5B789761, -547B86E57596, -54C649075B57, -552249203848, -55430B5318E9, -5570D22DC66B, -55710879E113, -55D2E4AC0446, -56207539825A, -564664475726, -566441C5C28C, -56A7930913C3, -56C944B04618, -56D455A8BBEA, -5726991C8C28, -5726AA3BE37B, -573314090BA5, -577C31903867, -577C528E786C, -57AD9604ED24, -580C377283C7, -587329CE3EBE, -587C34557B36, -58B11E803B58, -5902E4DCC95D, -5A060A64C535, -5A36898CA7C5, -5A4740D952EC, -5A6ED7966868, -5A99578CAA13, -5AAD6814E68B, -5B065568048A, -5B6CE0B3AD0A, -5B70E0B11758, -5B926E3751EB, -5B9CA63C4267, -5BDC1391B289, -5C1D3898D537, -5C34B8E4A456, -5C36456EA1E5, -5C43A75C65A0, -5C5752328A47, -5C9D20250D74, -5CBA3CEE351A, -5CD5E98A2864, -5CE0EB9C01B6, -5D384E6A4145, -5D9DB8445155, -5DE8717BB640, -5E1A4EE98748, -5E45A227B391, -5E8E50B3048B, -5EB0EA0A9412, -6032C47B7676, -60E0C84ADDEE, -612A447A2149, -612D81821854, -616B820EAD01, -616D75A4A022, -61DE2B085AC9, -62312EC272A0, -6232C5262CC6, -62B7C7C9B0D0, -62C531C6E29C, -63E6AAAB4433, -644ABCC3DD12, -64AE7BEA1784, -6515B38077D6, -65972038CC25, -65E120DE5E55, -66141DDE8320, -66718BD91332, -668082242328, -668920AEE063, -6696C4332D46, -66C9880D1DC2, -67150CB11E95, -671737BA0054, -673551D0A99E, -676D682C4336, -678B98AA2E86, -6847808E63EE, -6887A122AA62, -6888C514DEAD, -688BD5B7B4E9, -68A99E258692, -68C312391560, -68C9D33E3735, -6900A069E3D7, -690155BE8D8E, -69174742042D, -69B9CE233517, -6A0B123D7595, -6AB8E2B49E25, -6ABD4C4A72D9, -6B1CC539A1B2, -6B30B6B0925D, -6B638C1C950D, -6BAAAB1D4589, -6BAD01EBE736, -6BB4ED5E1682, -6CA178E036DA, -6CE210B529C4, -6D23D505D2B1, -6D3CBD12BC6D, -6D83563EB521, -6D98AB9CCC71, -6E3D7366E78C, -6E5582237608, -6E6602904925, -6E77B8EB6444, -6E978A7B16C6, -6EEC05EB651C, -70284824B26C, -702CDACE0C14, -704E1B85BED8, -70BB123776D6, -70CCC3A2D7C0, -716A747CB931, -7173E199A420, -71BC9C9E31E4, -71CAEEA3B771, -71D8BA423D55, -72253C7DD951, -7260377CD286, -7280858E8B20, -72913BDAB647, -72B5B87BBC6E, -72C83B1D098A, -72DA8050A38E, -735C2AB60A97, -736B602A93D9, -738D7833E7DE, -73E7B22D6E54, -74133B1E2DED, -74A929877793, -74E3670C045A, -7531E3E2A41C, -7542A9B65EB4, -7564993C91C7, -760ED0AB626E, -762E0E021E38, -763D7E6BB40E, -764B38E2903D, -768016001C8D, -76A616C3D42C, -76AE99D9A294, -76BAAA710D25, -76E3B23696BC, -77322DD2E184, -77B40902B6D9, -77C0AC14972D, -77C1CE0E7674, -77D7B7E2C8BA, -78279397A68E, -7836593AB838, -783859EB51A6, -78CCDB50C193, -7932684154AE, -79604362370E, -796630ED27B3, -799E4E270953, -79A00573947A, -79B798D66B01, -7A0455D0A7EC, -7A33D19B7248, -7B0A8AE18817, -7B0BA045AB35, -7B0DE8504D57, -7B21781EC649, -7B7224C1AB79, -7B90C2BA9B23, -7BB90D382672, -7BBC9DC92836, -7C09DC408C47, -7C418B493454, -7C491D518242, -7C7A86CC727C, -7CE836EBD228, -7D49042C530D, -7E5744EC286C, -7E680A48C383, -7EC45CCEC35A, -7EDADA19EB57, -8005BD088847, -8022E705B640, -8031E3565825, -80499BAA5959, -807466CCBAB5, -810518578380, -810D24CB13CC, -812B02C34A64, -8163A5DDE1CD, -8186CE2B363E, -81DE6062B9D7, -822017D8929A, -8247C78188C5, -8270D538D5E8, -82D8E8DDE296, -831207CA6E8A, -83378A077357, -83A05B477535, -840160379EEE, -84044BAB78A7, -84366C6D7781, -8442CC9AA777, -8470AAD30447, -8498740493BB, -84A35A698E93, -84ABDE484425, -84B24DBB9A67, -84B723B2A237, -852BEB133D74, -854501E98239, -854A0ED2E77D, -85A066D39785, -8619557091AA, -86228C3742A4, -8637BB3BA795, -8642D9310B46, -86538085966D, -86EE9C410811, -870A042C1B34, -873B47C457E6, -873CE44DDC6B, -874D123262E7, -87513C960770, -877641436923, -878A091B74B7, -87927467808B, -88C2E39B5990, -88D252AC1A8A, -891EDA20BDEA, -89267DEE07ED, -892CB89ACCC6, -8A2423E9D100, -8A6BC2E3811B, -8A8EB5771EE9, -8A906B4B3211, -8AB21B524C5C, -8AB823BDC2AE, -8AC3B2ADE77B, -8AC4317D049B, -8ACD6B86EC44, -8AD966CA3B4D, -8B0A3B3DCDD4, -8B1B6C705C1A, -8B1C75E27153, -8B2A5E0332A1, -8B6216E412DB, -8B7CCA9DB004, -8B9999AE9703, -8BABAD9A65C6, -8C32D0AE3DB7, -8C99807368A5, -8CC1133D7D5B, -8CD2C872187A, -8D0563B86DD4, -8D43D81E37B4, -8D96A800B21A, -8D97B475C957, -8DA62EC0C524, -8DACA1BC0636, -8DE3B131D728, -8E55316D3B3D, -8EE497C9A869, -90210DDAB57D, -9026977EB8A6, -903AA4305025, -9083158A49A1, -9092D12E7967, -90D8713352D1, -911E097A27A9, -9140EC087241, -918A67D05479, -919B1D357E91, -9210BBA2AB26, -9224B6555E30, -9226D4D1236A, -922E7955CC67, -929CC86B1B26, -929E1556110E, -9302DEB79C5A, -9384841B4702, -93B4BD1CB47C, -93D985D55712, -940B37939AC6, -94673AE73823, -947A8147E0AE, -94CD6A4B6391, -94CEEAC5A8D7, -95ABD3A7C631, -95E1C233EDE2, -9607AE17AD09, -960C98566E52, -96435BD1D29B, -965D66E19245, -965D72659982, -9695167B4149, -96D0C3996714, -97274C21BD6C, -973186B345BB, -973A28C983A3, -979686C51AB6, -97992CE2DD31, -97E9D0C89DA8, -97EB8A44C49D, -98314DC363C5, -9860DC044565, -988D023C15A5, -9917BDA7B4D7, -9996A233442A, -9A2132B5B625, -9A694755A978, -9A7911ECC275, -9AA1E6CE588C, -9ABCCD2AE7C7, -9B39A60D3841, -9C0630361CC5, -9C4E19AB64B1, -9CE96BADE4D8, -9D442B28BD11, -9D4C35AE1A08, -9E02910C691A, -9E46407C9024, -9E74D104ACEA, -9EDD416A7912, -A026642D13AD, -A12908B38536, -A16EE9666D5A, -A199132A4043, -A1AEC2B58BBA, -A1BE42A15EDE, -A1D0844C2C63, -A1E0103A1879, -A253602B9445, -A2B019B46CB9, -A2BBCC3B546C, -A2C325A73A9C, -A2CB60E815A0, -A314B97C1A6A, -A3647146C335, -A3A580799BB4, -A3D30CC8EB97, -A402B5137D86, -A42158CC74B5, -A435DD64AD17, -A4693D21013B, -A479A91EED49, -A4B30D146A01, -A5142D626200, -A54056E87CBB, -A57DBD287491, -A588C918E327, -A593071D4758, -A5CC0EE7B9E3, -A6375E98A5B5, -A666347B3B4B, -A6A203994202, -A6BAE1A1520D, -A6E9885AA49D, -A705087E89A8, -A7072D4324C7, -A745AD7D6789, -A750456E7C5E, -A783A8774651, -A787C822020C, -A78BB575EAC5, -A7905680A254, -A805534D84E9, -A86C2595A1C3, -A89903B6ADDB, -A9182707A219, -A9391782A846, -A96B08E3A50B, -A98DEB0733C9, -A9C37CE71D23, -AA2D69C757D9, -AA4E4558A9EE, -AA6C835C9124, -AAC0C35C43EB, -AB30CB2CB354, -AB6191DB240A, -AB8953D3560C, -ABBB521319E6, -AC47461358D7, -AC58C25A1559, -AC7D4B201D92, -AD061A23287D, -AD105D52DB36, -AD4EA84D7185, -AD5038D15490, -AD97523144B2, -ADB24E78784B, -ADCBD453B232, -AE516A187825, -AE52116C234C, -AE817239CAB5, -AEA5A5A0E46B, -AECC93678543, -B0452769A83C, -B04D71906C60, -B0805C191424, -B09172DDBE43, -B13AE369390C, -B14080E570D1, -B1419B62772C, -B14775DEA2E2, -B188BA649EA1, -B1BB0DB95C67, -B1BB19BDD424, -B1E8B5054DAD, -B1EBB537CC0D, -B2174092CDC5, -B2554CC8AD6E, -B2C5A2E88304, -B312E56ED250, -B37B48D8C1C5, -B39C699CD208, -B3B121208E34, -B3C3C6E4395B, -B410B958C3B8, -B4204546A74E, -B45171C5A67D, -B4B103E693ED, -B4DACABCAB07, -B506567A2B84, -B51083D5C2BD, -B54D7674CB90, -B570E5EA1DA3, -B598984AD584, -B5D7E1135821, -B60D053A36D9, -B63957593E23, -B64558CAC0C9, -B68175BCA864, -B6CD1A3EC5BC, -B72468A7710D, -B75176C82A8B, -B7AA0CA5D94A, -B7B9D7E523B8, -B808D87AB75C, -B93A6432E51A, -B941A9D99B6C, -B9DA40920237, -BA6C2E10086A, -BA7384AB949E, -BA8DEEE045E8, -BADC2149EC42, -BB1924266B36, -BB41640E6340, -BBB475DB2B03, -BBD4C4699719, -BC0B2C897267, -BC7BEE6B71C4, -BC8B21AD8802, -BCA2D8118631, -BCB7A7006400, -BCBC6637499B, -BCBD2B8BE4B3, -BD213E28C568, -BD32E4EC7080, -BD401D63C3E9, -BD463C3693A4, -BD749E85586A, -BD7CA11B9551, -BD96355CBE36, -BD9E6EB7B524, -BDADE6111218, -BDB576D1E88C, -BDB5DC09C522, -BE19C75D6B7E, -BE5B3ED935AC, -BEA20C972E70, -BEEB4A159B37, -C01E8740DE38, -C0411C28857D, -C045544AD1E4, -C04660B76831, -C0C4CA21B876, -C0E0E092C8B4, -C0EE394D3D95, -C14601C6B411, -C16EBAE928B2, -C189A791A85B, -C1ACDB8C1890, -C1C55A7A99EA, -C1D72A47755A, -C1D8B91D65AA, -C1E6149B386D, -C22D8E2B1E37, -C23E999B6298, -C314E31A670D, -C3D275A9B8C7, -C3EE19B61C89, -C427B93DC2ED, -C443EEC4330D, -C477B966D328, -C4C6CAE4784C, -C55875BCB82C, -C581CA998910, -C5ABC0A455C5, -C5BE33E6B1E2, -C629E0D34581, -C65194543D6B, -C67B8E869D90, -C6BC3B9CCB41, -C7034BC581A6, -C748500B6947, -C757C15E9E0D, -C798A8465ACB, -C7B6702AC17B, -C849133B7CCC, -C870C98A4E91, -C90B7AD266D3, -C90D996C3A2D, -C953797CCE61, -C9639352EEC8, -C983685AA86B, -C9CCA6D095A3, -C9CE81D47EDB, -C9D449AD9970, -CA0D9CCC4C38, -CA277AC09859, -CA56EB045188, -CAB92B865BAD, -CAE8572C2657, -CB1CE185575C, -CB2ECC3D9C22, -CB642A081A89, -CBBAD2DA0EC5, -CC1B5BD45315, -CC2C02300D34, -CC559969D0CC, -CC5646BD7AEB, -CC6A93BD93D1, -CC726DD08765, -CCBBAB6504A4, -CCC1EA3E27B8, -CD16EAB946E9, -CDB4EEE02E14, -CDC21E1E1EC7, -CE09B3870EA2, -CE5AA0C8B5A8, -CE63DE29E069, -D0368B24CA49, -D0489010A72C, -D075379A21A6, -D09893B4EE04, -D0A7A2787570, -D0B8C06C02E4, -D106E94A4C3B, -D11E7D1BBEEA, -D12B25B8DDE2, -D1972D6CE2C3, -D1B91D224946, -D2752E53679D, -D35B2B75CC52, -D40E935117A2, -D4C37528DC05, -D4C818A5455E, -D4CD56DB8AEB, -D5190BD5CED6, -D55E5AA3406D, -D576E9D856D9, -D5E444E9D82D, -D61A3231790D, -D669B3AE1E11, -D6C075899D06, -D6C3503456C4, -D7AC70A05A0C, -D80A37B6D7ED, -D82E6938C58C, -D85E51344EB6, -D8809EB9BA7D, -D8913C2D48E9, -D9109460D912, -D94E36427E20, -D97E55B1816A, -D99425130C1A, -D99C3222A190, -D9A207103ED7, -D9C70CC5818A, -DA3379D12773, -DA705702248C, -DA818C56CE43, -DAE1888DCC0B, -DBA0A2DCA8E0, -DBD9799E15B1, -DC242193D7E3, -DCB5AC62946C, -DCB75AEC61A0, -DD6E0587A821, -DD7B1A7C6A82, -DDA22A189095, -DDDAE53AA711, -DDE7304E78B6, -DE1B4DA681B9, -DEAC67E2D7C1, -DEB7D7E4C62B, -E127434AB3B7, -E1ACC6742AB7, -E1E59574ADBC, -E1EA6BAA03D9, -E222553A59A2, -E2230B8E84C9, -E33E807EC3BA, -E341574B2E32, -E42868808B70, -E43562C624B0, -E43D54DC3511, -E466090D2123, -E47069DA0C44, -E49DD6062901, -E4ACA0ADBA0D, -E4B976AD6687, -E526BB7888DB, -E53354B71B10, -E57581CE8617, -E61A1DA5A60E, -E6293BDA5EDC, -E64C2A07CA9B, -E6600C4D6A44, -E6655B6425DC, -E6BADC631036, -E70143BE0091, -E75E07A010D1, -E76962E3B8B4, -E8028A6DCC90, -E80C5E3E8227, -E8779E40450E, -E8A9E2D87D36, -E8B5A0BDD993, -E933DA9735C4, -E93A2E63189D, -E9447637E40D, -E94836269887, -E94D82A564BA, -E98DC3B561B5, -E9EB2DE57AE9, -EA490920877D, -EA4C494C9353, -EA9B1695DD91, -EAD0E31A6834, -EB16B6462B66, -EB276C9AB68D, -EB3C9732C3BA, -EB44DDC408CE, -EB8536C958B2, -EBC825C186B3, -EC1A55BB58EB, -EC2B12107313, -EC8CB5758097, -ECD4C42EA3D1, -ED22B7115435, -ED2CE17A590C, -ED65A9B6469C, -ED6748113E0D, -ED8CEB8B7102, -EDCE0890472D, -EDD4A2EA7493, -EE17C426D25E, -EE487A4C806E, -EE5931913A8D, -EED56840AEBA, diff --git a/client/dictionaries/icbpm_sort_keys.dic b/client/dictionaries/icbpm_sort_keys.dic deleted file mode 100644 index b4a635d44..000000000 --- a/client/dictionaries/icbpm_sort_keys.dic +++ /dev/null @@ -1,1001 +0,0 @@ - -00383D96411D, -005307DB7853, -009A4C4C6C49, -00C447B8A2D2, -01124119AB54, -0117BAE4D8D9, -018861488381, -0267B4922681, -02974B9786C9, -02A46AC9233A, -02BED876BD48, -02D8A7729ED3, -02EB32B92D30, -03C34821DE9A, -03D87397E9A8, -042CDEE5D0BA, -044ED79417E1, -04524659496E, -04602A40C037, -048451A79DA1, -0490AD0C9283, -04E16965C142, -05138E278443, -052B99EC186E, -056D4B5D2915, -0578E317C419, -05865124E5CA, -0599E014139E, -05DB68DB9364, -066C127C208D, -06966B31A285, -06B577E0E480, -071B57D258CE, -072B300309C9, -0759955331EE, -0769855EEC13, -079B8DA54DB1, -082B68A67491, -0832E4783600, -08506533E741, -0853A982D793, -08629D1DD0D6, -087C0CDA3B46, -08AE4ECD7CE3, -0965220D2ECE, -09A14A80754E, -09ACEA48DD0D, -09DB8EE5458C, -09E6CB76C080, -0A44A754B592, -0A7328887DC2, -0A906663EE1C, -0AB08938E3DA, -0AD8AD0739A6, -0B00220EAE75, -0B1960681E79, -0B31815E6A7C, -0B3690D4B122, -0BB8414CB6EA, -0BEC525E3463, -0C296648344D, -0CB6CC83AC45, -0CCAD03DDBC6, -0D6C26AB25CD, -0DC9143735D1, -0DE8A36CBBCC, -0E175033BD77, -0E6478123917, -0E7D4AC83133, -0E8420B04083, -0EA607E1C4E3, -105743704432, -107A6AB6B305, -110BB6D5539D, -1114A47CC39A, -116AA873ACC8, -120616C6208E, -120C83C06317, -12343D71106C, -123A082E2AEA, -12E50BE60524, -133DC845505E, -138153A4351A, -1395C108B6B6, -1428C04BAAD1, -147D93848C70, -14A353C60820, -1504C1846399, -1523A1E39D03, -1532A2511A8B, -157308368E8E, -16065CC411E0, -1637D8ACA71E, -1639134699C7, -167358BB268E, -168DE72B3B5A, -16A05D5C31C3, -16B4442EAE97, -17197B247A4A, -1774DB1A8CA1, -17820DAA47B2, -1782BEDBD347, -17B561AA82B4, -17C548CBC3A6, -17DA5C873BC5, -18025130661E, -184B95B4E3C6, -18A3196D364B, -18A97BD26818, -18BE810A83DD, -18C3AC2A7E90, -194D4E1DE89D, -196E279BE9A9, -1A2C8D855336, -1A3A76ED470A, -1A55D4849951, -1A9872D00EC9, -1ACD5433BBDD, -1ADC527D5BDA, -1AE29C8CD672, -1B14CAC3D0C2, -1B20A6E1D06B, -1B30A7825B23, -1B3E45AEE657, -1B75E7B007DB, -1B9DABDEBAE0, -1BAB19D01495, -1BD3119E0363, -1BDA0D87A575, -1CD38D77090B, -1D12BBB575B1, -1E1A0DB8729C, -1E2DE60A477A, -1E3C71643766, -1E6ED46CE258, -1EE60A4A8D22, -200D45263629, -2013899194BB, -206CE78E0C6C, -20B51C977E54, -2142B57D369D, -2172D827D3E2, -2178ED80D581, -21B4BE97AE07, -21B91A26133A, -21C7650673CD, -220D815D366A, -22C2176E1CD6, -22C3AB41B123, -233D7B324CEE, -2340CBD61A71, -2348251AD23E, -2381B8214025, -23BAE8DA1AC5, -23C317B8D6DA, -243A41574A39, -248EA5E91987, -2491457885A7, -255A9E590BCC, -257192699E32, -25892216C620, -2595E5B1DE76, -25AE69DED1B4, -25BA8775B3C4, -25D967D4DD35, -25DB996D56ED, -25EE21CDE4B9, -2625E408276B, -26B744C673DB, -26C6D38B8257, -26D787613684, -27689527E201, -27743B5A5736, -27D1635ED1B3, -27D5B8D2642E, -28035CA5B300, -2812EB6A427C, -28133B46730A, -281499DD16A0, -281DD9E6C98E, -2870E08CEDBA, -28B8685B1B22, -28C3D17E4DEC, -2953C63E9E58, -295D3C9A8B28, -297B74853CAA, -29ACACC2828E, -29EA97BC4A6B, -29EB3CA1C0DE, -2A079CC2AD37, -2A27E0602400, -2A45A0D8D6EE, -2A47CDD3A322, -2A4C4DB1D71D, -2AA82B4B6711, -2ABD68BDC5A3, -2AE7BDB10CB4, -2B051C90BE82, -2B490231E063, -2BAB94372644, -2C03252C10E7, -2C3EE5E98804, -2CB671E6365D, -2CC55B46705B, -2CD09D3C0A1B, -2CECBC323E31, -2D302827C9B4, -2D716C9C467B, -2D8856109732, -2E15681A4355, -2E79209B9519, -2EEE063290C1, -301C9AA3DECA, -30C520D6A2B9, -30D6324910AB, -3113AADC9D6B, -3124ACA5491C, -315AD0D6E6D2, -31A16DAC864D, -31EC44581294, -32DE3CD81C24, -32E532232C29, -33256E443128, -33293485AD61, -33305B0365AA, -3343B72BAA71, -3372C9C5D4AE, -33754E0D1687, -33A444334869, -33B54345C32E, -34002AAEE45D, -343C556CEE59, -3444DDE6D7E5, -345B62452538, -3495A04A9270, -34EB673C863B, -35123500C1EA, -353A7167576B, -3599856810B2, -35E7DE9899EE, -35EDABB506D8, -36C54912D10E, -36CA0101B6DC, -36D268442846, -373E5827E0B8, -376D6C446746, -37E2EAE635B5, -381B0A70E135, -3862B259DC71, -386676C44A13, -3905679DEEC4, -39070618BB17, -394181105544, -395D38815892, -39A00E856381, -39C0E2ED99B5, -3A1E82E2CDB7, -3A5D13E05B6A, -3A6DE2081CDD, -3A8498924010, -3A9D49E8BEB2, -3AD0EE1031A9, -3B052E65D40A, -3B4986981212, -3B4C51ACC53D, -3B99486097C6, -3BB36BC22CE4, -3BB4B3025B79, -3BBB7BD8D7B7, -3C09C971D835, -3C4A12E7A107, -3C633B3474DD, -3CB9E31D6022, -3CD344A7EB21, -3CD8C6705954, -3CE887B9D091, -3D5EA1C71953, -3D89120EB993, -3D9C3245AE76, -3DED9D496478, -3E0913A96E74, -3E34909990B5, -3E7DD7953DDD, -3EEB33434C1A, -4015D16B5C1C, -401C81A72C56, -40E7B8D60242, -41016C0CB8DE, -4124864B0D40, -415BAA0CAB15, -418184DBB4A0, -419513740558, -4195EE7238CC, -41B727883B27, -41BC44A8C3C6, -41DDC3A48EEA, -420445087613, -42068108DE36, -4245921D73CA, -42A959953C45, -430E67734C18, -4314D9D03B95, -43166BCA83EB, -43400A093A7E, -434CE764DE91, -43595AC786EE, -438099331C1E, -43814087A7B5, -438C3CD95B58, -43B3E895B281, -44074C461042, -444D37149B20, -44A04DAA30CB, -4537282554C5, -4584EACB6087, -45DB3799C150, -45E599AE38EA, -462305611C4A, -4636195CDA2D, -46752993E2E9, -4684316440D6, -46C7246C1958, -4751A5274848, -4761E34CB054, -476388408D8E, -478947735B45, -47AD81972D5B, -47C23398EA52, -47E9D4D4BE35, -4812AEC4B01A, -48276645A4EA, -48644467A214, -489C783B3514, -48C860AA4B74, -495C6639575B, -49681C20A00D, -49E8249DD677, -49E93C110AA1, -4A24470C19C5, -4A4755BC4A2A, -4A4D5E3A9011, -4A65D627625C, -4A6B36C5BCCC, -4AB725ED89B5, -4B39E3923D0D, -4B59316C10E0, -4C275C8BB2DA, -4C2E9455D296, -4C44DB1D0C3A, -4C67059B0006, -4CA30E1A298A, -4CA74DAC7C01, -4CB212D72D57, -4CD3B228EBB4, -4CE1972E090C, -4CEE1794E0EA, -4D06DBCA167E, -4D2CC85EB338, -4D40BC7A44DB, -4D769DA515D3, -4D79C95DAD2D, -4DBAC8ECE167, -4E3CB839E87D, -4E3D548E1267, -4E8250E29617, -4E94C7962769, -5038884E4178, -505B5A8EB20A, -50642C36DA00, -5083664D8C09, -50B77DA96DE2, -511E269A9BAE, -51798AEAAE9E, -51ED5833AB6D, -525335E4CD34, -5261CDDA279E, -526E55542A54, -529C16A720AB, -52A230B1C50E, -52AADA374811, -52D20D6E3E35, -534BB4A6984E, -5352CCC3DCD2, -540B15E8019D, -54AA2915E815, -558DB8891A90, -55A691710B48, -55D1E91B1D35, -55D95774E9A0, -563C6B96D59D, -567032E13B54, -56741B108D22, -57029D991123, -5714E9D33034, -5734CD8A65DA, -5785EE00049E, -57B8B111491D, -57CC9D0AA32B, -57D7D4D746DA, -583C936DCB4B, -586B470A43B3, -5876E1D34183, -58B6AE62DB88, -58C35C8BC9AB, -597E98000ED4, -59DB4DBB5D7A, -5A150653E624, -5A211CE57C4B, -5A6272CDBE9C, -5ACB8043C10C, -5B41CEBC2213, -5B59BCC4321E, -5BA03479BB8C, -5BC64C42281C, -5C9B1A8E31CD, -5C9BD0AC1DB1, -5D223E990AD8, -5D8C3A5C5761, -5DA57EACA38C, -5E41DD5D1154, -5E6ABB51EC75, -5E7CC04C3A58, -5E810C48C8D8, -5E8943D9A836, -5ED616273468, -60100DD0E023, -6033A1C0E431, -6088A566CC60, -60B20ADA0471, -60B8411D876E, -60C742D8D9C0, -6135433CC5EA, -6153ADD80A15, -61718ED2C94D, -6175241B035A, -61780BCB0C57, -61B701698050, -61C4E56629A3, -61D59C284952, -61E57B490A55, -622E5E0812D7, -6251CE7E547A, -62953A89B137, -62D6EAA06CD6, -630228659A47, -632931BE8EC7, -63539BB89DEE, -636CB69BB10C, -63783393E20D, -639DB16995B7, -63AA2A5B076C, -63B636458E94, -6443E64DCC4B, -64695084C575, -6493D06D5710, -649B302A97C5, -64B8632B54D4, -654BACB21C3B, -65A3D5823819, -65DEDABD1B34, -6608944EE186, -665B8B24C20D, -6685D0BE19E0, -66933A9E7982, -674C7BB59A16, -675E35EE359E, -67AA98E362C9, -67D47C1B6425, -67DE22850162, -67E8B986B2A7, -681EA28BA6CD, -6828B52B6507, -6874E54471E8, -6879B1CA44A3, -68C00A810D41, -68C9E8AA5C3E, -697A8ED07418, -69B5357A617A, -6A7B3A7B6735, -6AA40421D23C, -6AB676B4DB9D, -6B00420BE41C, -6B0B7B967871, -6B9D041136B4, -6BB1A14768A8, -6BCAE24D9700, -6C0458728774, -6C57CBD51995, -6C5E10B86CDE, -6CA491A8C7B8, -6CBC25C1DA2E, -6CD430D99958, -6CEC27647CC0, -6D4D29CEB9B5, -6D6E9A6B725D, -6D801AC74572, -6D97408C6D60, -6DDE6E871C64, -6DEA848B6195, -6E05B5C44A54, -6E751666AE9A, -6E7DBCDA05B3, -7004BA1763ED, -7016ECD01559, -7076D48D5E49, -7091621EA016, -709311997549, -70984C14D3DB, -70D73BE22CDD, -70D9461C5E90, -712BC18422CB, -712E6CAA74A4, -7164042BA89E, -7175E14A4D62, -718B39561350, -718BDA352E28, -719B1418323E, -71A8D54D82B3, -71DC30168C27, -7221E016597B, -7234CC6BD65D, -727A80DD5296, -72B393D6E8A9, -732C9BE4DDBA, -736B4A835B2B, -73EA81968900, -740AB5126199, -741A31054E6B, -74498C1D4B3D, -745276053CB6, -74684B0B4B1D, -74772915E24C, -74A24BE33BE2, -74A778236D5A, -74AA58008A31, -74C27A96CB3A, -754AD5773746, -756C15E54212, -759403A563D8, -759D2130312B, -75A0E10D8C84, -75A807E46B96, -75E454785C6C, -76078A25C088, -76140285B768, -763D835BD5ED, -767C33468C72, -76962C07EC9E, -76984E62CCE4, -769AE4646931, -76E5DA67A1EC, -7708D5CAD58B, -77383BAA4D90, -7789E646A556, -779A248E098C, -77DB71037644, -77E0A57DD456, -7853D464E2A4, -78EA6EB04463, -7909427EC8B9, -7910A31ECD19, -79271963B6E8, -793D98517D33, -79B7A4C58DE0, -79B9148761B3, -7A2893B75AD1, -7A4C61A1B48D, -7A7469B69C6A, -7AA84B1A527D, -7B00211CA416, -7B118EABC7BB, -7B1D9A2E22AA, -7B583D350740, -7B9D3A6BD061, -7C2DAC2CC775, -7C4CBBD2DDE1, -7CD52B5B8E77, -7D412100532B, -7D46C149DAD9, -7D4CA630E229, -7DAC0E83D335, -7DC935E220A0, -7DCA66BACA13, -7E30778792D2, -7E43C3BAB3CB, -7E475BA186E6, -7EE2A624851A, -80CED5362B2C, -80D2CC78E10B, -80D62251E20C, -816875D55ED1, -81950D0517AC, -81B519418C3E, -8211571B9D16, -823C7CC6E06A, -826DD63B9032, -827303C574B5, -82C5ADED4B81, -82E344329D34, -83588E140165, -835D33B48113, -8384148AE52D, -8394B57153D6, -83A0184757C0, -83D86835B48B, -8502EE9A7E85, -852C2B72659D, -8534A6CE0911, -85ABD94CD7A9, -85DA8099CD7E, -85E0B6B26945, -864CA2A6BE93, -868A33A44447, -86EDEABCC357, -87DDD5A188EE, -8830379B50B7, -883803A3360C, -883DA78EC87D, -88482A12C2C6, -888EBD3DB945, -88D026793359, -88DD4B7C5991, -8931DC3733D4, -894D8E2DCDEE, -897B845C2680, -89B638BD909E, -89D2C28BE578, -8A1869848D1A, -8A39D09508C9, -8ACCC7290C8C, -8AD8B41EC218, -8B028B7E6D60, -8B6A95C7D2E2, -8BA1226EBA21, -8BD586B21ABC, -8C0EA504B635, -8CA939DC6DE4, -8CAE5D688443, -8CEC639E64DC, -8DECE0DD29DE, -8E0EC762E883, -8E958D8B8C52, -8EB64D710C88, -8ED4A17717D9, -8EE9D9C03A0D, -9014E1430AEB, -90965DEBC8B9, -90E56E616DDD, -912CD8E04437, -912E33563E1B, -918048032247, -919402EC39CB, -91D28E2B126D, -9216EEE5B677, -9232215296B2, -925A070E9096, -925A5521D48D, -92CC200886A2, -932035869655, -937144459949, -93B260DBC70A, -94552B863E37, -95327A0A3600, -954275CDD7E0, -957E6EE3EB55, -95B920CACC84, -96382E1C8E12, -964E8E5338BD, -96706C8D6ECC, -96759A0D5566, -96D5213C5DDB, -97300764797A, -973BDDBE7434, -974838AE17A0, -9752A6B316D5, -97926543783B, -97EB373096CA, -982D6054B83D, -989D127BD496, -98A54AD58A43, -98A92128364C, -98CD5AA2A4DB, -98E8C543688E, -99207A00AA4A, -99243E754CB8, -9925893ABAC7, -9937553A965E, -9976E6ADE0C9, -9982E3E6A4A0, -9984C1A3229E, -99C487AB85EC, -99E2A19C9673, -9A05EBE41D7D, -9A138D1A5CB7, -9A179148B824, -9A6EC0A9ECB8, -9A720CBD7BB1, -9AB22BBDDD87, -9AC43B5A06D8, -9AD8150BE648, -9AD97423190D, -9B4ADDDEB749, -9B7603341727, -9C45237377BE, -9D090AE1A15E, -9D59641E40A5, -9DA4528CEB8C, -9DA728164176, -9DAC62A346B7, -9E0E9D983B9A, -9E5271763D3D, -9EE95586D024, -9EEE39E00CBB, -A04671256EE2, -A091485B4B5D, -A1B5577ED36E, -A1EB280E3901, -A2789E1DD888, -A293A90AE72C, -A309E3AEBDB9, -A3196E77B072, -A31E72DCC826, -A34DEA01690E, -A36031D6ECB2, -A38044A3E18E, -A421D7A04C4B, -A424C686CA39, -A44590A779A5, -A47AD3895C63, -A5041E8B8E22, -A50DC0830AA5, -A52B8929D665, -A5BCBA6BE592, -A61D5137E6B3, -A6344C0418DC, -A690A817B9D9, -A7E3B3459240, -A81E6D3C8E11, -A8C0BE436685, -A8DE205120A8, -A91E2BE6C308, -A9258D6B06B5, -A992B5E070C1, -AAC6E3205D48, -AB101546634E, -AB6EE0761ACA, -AB9BCA200547, -AC4BC5B2D3C0, -AC7A0B47B03E, -AC88B26AC1D0, -ACAEB3456AD9, -ACB906631D8A, -ACE07B45C0C5, -AD1992AE37CA, -AD5586744A60, -AD674E4ADB79, -ADA093B06831, -AE7C3AE5334A, -AE9EB8CAB2C3, -AEAE9E5CE65D, -B002D1BDC29B, -B0463E703098, -B063B209BB20, -B0788BE3BAA4, -B0C3B3299090, -B128298D9073, -B160677E7035, -B19D3D57176A, -B1CCDB7999B9, -B231AA398B90, -B250E9590215, -B28BE0D819ED, -B292C9554CBA, -B2D8485C2460, -B31763D9D0DE, -B328014DDD6A, -B378C424C9E2, -B3D8C03C78E0, -B41D18E3B980, -B46824B972E9, -B50383A32302, -B509D631967C, -B56CA847A7C3, -B56EC9A20D28, -B5B763215C82, -B6550EAC573A, -B66060201705, -B6614EBEAAA2, -B6A18CBD4DA6, -B6ABB62E437E, -B6C6558E58CA, -B7009204D512, -B71D5B22B1C2, -B7392DD1E497, -B7709ED7CE60, -B7A26320A491, -B7A9DA22E9C6, -B7DEC863369D, -B7E9A91174CB, -B8178A34E2DC, -B83092098A7D, -B84C50E56DEC, -B89BD135E935, -B8E87380D361, -B9485A9648C6, -B9ED829C22AE, -BA227EE91818, -BA7BBD9683B1, -BA8224EA7A80, -BA84C974B356, -BAD293A45C8A, -BB850C7E4934, -BBC1256810A4, -BC1CD369549E, -BC5C76E5909C, -BC66E9270049, -BC6AB08B03CC, -BC74CA2C2B06, -BC7C64828C1D, -BCCC3A719013, -BD06E96EB7D7, -BD196D0A74E0, -BE02790E84AC, -BE1266314B9D, -BE518C742B74, -BE5695316117, -BE5D8EBA120D, -BE8286DA7D12, -BE9CE00EE4DD, -C003962B3462, -C0067E095049, -C015A21E0146, -C03BC03AD437, -C06CE7D57A0D, -C07EE1E10B56, -C0885A29251E, -C198163ABECE, -C1EB7337A035, -C225479C7064, -C2740E1665A8, -C27924128A00, -C2A701656B8B, -C2C30D21C53E, -C2CBB2ACD38D, -C38D19A9C8D1, -C3B1BB7E7492, -C3BA2438A981, -C3CD74758DE2, -C4033B3BB1D7, -C404D280640E, -C4467DE80B2D, -C46A048C88DD, -C52877867C05, -C56D005E258E, -C56D052D5533, -C5BB2CCCB9C3, -C5C272694A1E, -C6121BC4A29C, -C65EEAE02433, -C661C4AE1DD1, -C76C94B495CA, -C7BD49777A79, -C7CD131E9B60, -C7E35D6294BA, -C8E173DB04CC, -C95855AE08E8, -C98147E69033, -C99A004E6133, -C9E893C4090B, -CA119C79A197, -CA309D2CBC41, -CA4BAA390BC4, -CA92DD257E21, -CA968EBEB9C7, -CADED0C50AC4, -CB18774EA550, -CB1999D19E10, -CB75C1BAE669, -CC2517AB2346, -CC2AC1AD29CA, -CD11359C7A90, -CD14C8553CB9, -CD333295BBE2, -CD3DB8C27E5C, -CDA811AD5055, -CDABDCA23986, -CDCA8BD7B002, -CE0456AB0DCE, -CE58AE1C51E9, -CE76E8A600DC, -CE95875316C8, -CEB105E65289, -CEB651752D4C, -CEE02D97E5BD, -D023DB35ED05, -D0BE546CC06B, -D0CE7EB0D379, -D10329D366C8, -D15C004DBC8D, -D16E6B668254, -D1CEEC977644, -D1DC0E1CC09E, -D2550925679B, -D28B2D42DE1A, -D2926519AC09, -D313116A45B4, -D3DC10453857, -D431C8C73BDC, -D4C67846791C, -D5629384CE7D, -D5ABE7180600, -D62A4A0E57C2, -D660CE9E3080, -D66AE9282140, -D6A91C14AC47, -D6E23B4E75C6, -D726C4979654, -D76DE12943B4, -D7A405AD9E4E, -D7BD3AE48E93, -D7D49700BBCC, -D7E8A5089E7A, -D84C81EE910D, -D8545199A949, -D86243C1380E, -D88A12EB3622, -D89B5EA419C1, -D8A3690B0115, -D94646A4C65B, -D982B4846A96, -DA303BADB013, -DAD9A48A8C33, -DAEB5D63920B, -DB01A99DD94C, -DB22BB7D6818, -DB37160CBB4B, -DB7E3687E450, -DC7697E37A9B, -DCC44C4E9269, -DCCE477E785E, -DD68DE9CDA5A, -DE1B08C6D94B, -DE41BBD7E68D, -DE6E04AE4475, -DE8CD4277A9E, -DEA8098D6E51, -DEB2BEE8858A, -DEB550958AD9, -E045E6309471, -E0E21213C611, -E0E457054B62, -E1097C69DA4A, -E1EA831EA514, -E20716902884, -E2C9CB14C06C, -E33B66EA2705, -E34C5B12BABA, -E38A1C654E82, -E3905BA54194, -E3E3919444CA, -E4450EC1010C, -E49A03306224, -E5100AC4C6C3, -E5124DB665A6, -E5491B5E3DD6, -E5BE9C989A29, -E5C3A9A27D3E, -E65111EB1E40, -E65792427D4C, -E7004C5EA94A, -E705087DECBB, -E7CB93E68155, -E81512343BAD, -E8428C8B0740, -E859EBC22318, -E87267A508DB, -E886AE7D1BE0, -E8B008239600, -E8C4B4A4E482, -E8D53410B736, -E902964DA28D, -E9203D5BD2DA, -E9526CACA8B2, -E9C11D763BEC, -EA3BDAA4E498, -EA61AC8B4969, -EA8E8ADC26B9, -EB5588EAE5E8, -EBA964C07075, -EC71B679D3AA, -ECB4019ADD97, -ED14D0A14B0C, -ED296C79266C, -EDBA3C943EA8, -EDC7CEBD4000, -EDE2747DA6C3, -EE3029556CEB, -EE49610E6121, -EEB704D69BCA, -EED69A391464, diff --git a/client/dictionaries/iclass_default_keys.dic b/client/dictionaries/iclass_default_keys.dic new file mode 100644 index 000000000..22e1ee653 --- /dev/null +++ b/client/dictionaries/iclass_default_keys.dic @@ -0,0 +1,12 @@ +# +# iClass Default Keys +# -- iceman fork version -- +# -- contribute to this list, sharing is caring -- +# +AEA684A6DAB23278 # AA1 +7665544332211000 # key1/Kc from PicoPass 2k documentation +0123456789ABCDEF # SAGEM +5b7c62c491c11b39 # from loclass demo file. +F0E1D2C3B4A59687 # Kd from PicoPass 2k documentation +5CBCF1DA45D5FB4F # PicoPass Default Exchange Key +31ad7ebd2f282168 # From HID multiclassSE reader diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic new file mode 100644 index 000000000..280604b3a --- /dev/null +++ b/client/dictionaries/mfc_default_keys.dic @@ -0,0 +1,1020 @@ +# +# Mifare Default Keys +# -- iceman fork version -- +# -- contribute to this list, sharing is caring -- +# +ffffffffffff # Defaultkey(firstkeyusedbyprogramifnouserdefinedkey) +000000000000 # Blankkey +a0a1a2a3a4a5 # NFCForumMADkey +b0b1b2b3b4b5 +c0c1c2c3c4c5 +d0d1d2d3d4d5 +aabbccddeeff +4d3a99c351dd +1a982c7e459a +d3f7d3f7d3f7 # key A Wien +5a1b85fce20a # key B Wien +714c5c886e97 +587ee5f9350f +a0478cc39091 +533cb6c723f6 +8fd0a4f256e9 +# +d2ece8b9395e # lib +# +# more Keys from mfc_default_keys.lua +000000000001 +000000000002 +00000000000a +00000000000b +00000ffe2488 # VästtrafikenKeyB +010203040506 +0123456789ab +0297927c0f77 # VästtrafikenKeyA +100000000000 +111111111111 +123456789abc +12f2ee3478c1 +14d446e33363 +1999a3554a55 +200000000000 +222222222222 +26940b21ff5d # RKFSLKeyA +27dd91f1fcf1 +2BA9621E0A36 # DirectoryandeventlogKeyB +333333333333 +33f974b42769 +34d1df9934c5 +434f4d4d4f41 # RKFJOJOGROUPKeyA +434f4d4d4f42 # RKFJOJOGROUPKeyB +43ab19ef5c31 +444444444444 +47524f555041 # RKFJOJOGROUPKeyA +47524f555042 # RKFJOJOGROUPKeyB +4AF9D7ADEBE4 # DirectoryandeventlogKeyA +4b0b20107ccb # TNP3xxx +505249564141 # RKFJOJOPRIVAKeyA +505249564142 # RKFJOJOPRIVAKeyB +505249565441 +505249565442 +54726176656c # VästtrafikenKeyA +555555555555 +55f5a5dd38c9 +569369c5a0e5 # kiev +5c598c9c58b5 # RKFSLKeyB +632193be1c3c # kiev +644672bd4afe # kiev +666666666666 +722bfcc5375f # RKFRejskortDanmarkKeyA +776974687573 # VästtrafikenKeyB +777777777777 +888888888888 +8fe644038790 # kiev +999999999999 +99c636334433 +9de89e070277 # kiev +a00000000000 +a053a292a4af +a64598a77478 # RKFSLKeyA +a94133013401 +aaaaaaaaaaaa +abcdef123456 # Keyfromladyada.net +b00000000000 +b127c6f41436 +b5ff67cba951 # kiev +bbbbbbbbbbbb +bd493a3962b6 +c934fe34d934 +cccccccccccc +dddddddddddd +e4d2770a89be # RKFSLKeyB +ee0042f88840 # VästtrafikenKeyB +eeeeeeeeeeee +eff603e1efe9 # kiev +f14ee7cae863 # kiev +f1a97341a9fc +f1d83f964314 # RKFRejskortDanmarkKeyB +fc00018778f7 # VästtrafikenKeyA, RKFÖstgötaTrafikenKeyA +44ab09010845 # hotel system +85fed980ea5a # hotel system +314B49474956 # VIGIK1 A +564c505f4d41 # VIGIK1 B +ba5b895da162 # VIGIK1 B +# Vigik mystery Keys Mifare 1k EV1 (S50) +5c8ff9990da2 # 16 A +75ccb59c9bed # 17 A +d01afeeb890a # 16 B +4b791bea7bcc # 17 B +# +43454952534E # ARD (fr) key A +4A2B29111213 # ARD (fr) key B +# +4143414F5250 +a9b43414F585 # Tehran Railway +1FB235AC1388 # Tehran Railway +# +# Data from http://irq5.io/2013/04/13/decoding-bcard-conference-badges/ +f4a9ef2afc6d # BCARD KeyB +# +# Data from ... +89eac97f8c2a # S0 B +43c7600dee6b # S4 A +0120bf672a64 # S6 A +fb0b20df1f34 # S6 B +# +a9f953def0a3 +# +# Here be BIP keys... +3A42F33AF429 +1FC235AC1309 +6338A371C0ED +243F160918D1 +F124C2578AD0 +9AFC42372AF1 +32AC3B90AC13 +682D401ABB09 +4AD1E273EAF1 +067DB45454A9 +E2C42591368A +15FC4C7613FE +2A3C347A1200 +68D30288910A +16F3D5AB1139 +F59A36A2546D +937A4FFF3011 +64E3C10394C2 +35C3D2CAEE88 +B736412614AF +693143F10368 +324F5DF65310 +A3F97428DD01 +643FB6DE2217 +63F17A449AF0 +82F435DEDF01 +C4652C54261C +0263DE1278F3 +D49E2826664F +51284C3686A6 +3DF14C8000A1 +6A470D54127C +# +# Data from http://pastebin.com/AK9Bftpw +48ffe71294a0 # Länstrafiken i Västerbotten +e3429281efc1 # Länstrafiken i Västerbotten +16f21a82ec84 # Länstrafiken i Västerbotten +460722122510 # Länstrafiken i Västerbotten +# +# 3dprinter +AAFB06045877 # EPI Envisionte# 3dprinter +# +# gym +3e65e4fb65b3 # Fysiken A +25094df6f148 # Fysiken B +a05dbd98e0fc # CleverFit +# +d3b595e9dd63 # Hotel KeyCard +afbecd121004 # Hotel KeyCard +6471a5ef2d1a # SimonsVoss +# +# 24-7 +D21762B2DE3B +0E83A374B513 +1F1FFE000000 +A10F303FC879 +1322285230b8 +0C71BCFB7E72 +C3C88C6340B8 +F101622750B7 +1F107328DC8D +710732200D34 +7C335FB121B5 +B39AE17435DC +# +# +454841585443 # key A +# +# Data from http://pastebin.com/gQ6nk38G +D39BB83F5297 +85675B200017 +528C9DFFE28C +C82EC29E3235 +3E3554AF0E12 +491CDCFB7752 +22C1BAE1AACD +5F146716E373 +740E9A4F9AAF +AC0E24C75527 +97184D136233 +E444D53D359F +17758856B182 +A8966C7CC54B +C6AD00254562 +AE3FF4EEA0DB +5EB8F884C8D1 +FEE470A4CB58 +75D8690F21B6 +871B8C085997 +97D1101F18B0 +75EDE6A84460 +DF27A8F1CB8E +B0C9DD55DD4D +# +# Data from http://bit.ly/1bdSbJl +A0B0C0D0E0F0 +A1B1C1D1E1F1 +# +# Data from msk social +2735fc181807 +2aba9519f574 +84fd7f7a12b6 +186d8c4b93f9 +3a4bba8adaf0 +8765b17968a2 +40ead80721ce +0db5e6523f7c +51119dae5216 +83e3549ce42d +136bdb246cac +7de02a7f6025 +bf23a53c1f63 +cb9a1f2d7368 +c7c0adb3284f +9f131d8c2057 +67362d90f973 +6202a38f69e2 +100533b89331 +653a87594079 +d8a274b2e026 +b20b83cb145c +9afa6cb4fc3d +# +# Data from http://pastebin.com/RRJUEDCM +0d258fe90296 +e55a3ca71826 +a4f204203f56 +eeb420209d0c +911e52fd7ce4 +752fbb5b7b45 +66b03aca6ee9 +48734389edc3 +17193709adf4 +1acc3189578c +c2b7ec7d4eb1 +369a4663acd2 +# +# Data from https://github.com/zhangjingye03/zxcardumper +# zxcard Key A/B +668770666644 +003003003003 +# +# Data from http://phreakerclub.com/forum/showthread.php?p=41266 +26973ea74321 +71f3a315ad26 +51044efb5aab +ac70ca327a04 +eb0a8ff88ade +# +# Data from https://github.com/RadioWar/NFCGUI +44dd5a385aaf +21a600056cb0 +b1aca33180a5 +dd61eb6bce22 +1565a172770f +3e84d2612e2a +f23442436765 +79674f96c771 +87df99d496cb +c5132c8980bc +a21680c27773 +f26e21edcee2 +675557ecc92e +f4396e468114 +6db17c16b35b +4186562a5bb2 +2feae851c199 +db1a3338b2eb +157b10d84c6b +a643f952ea57 +df37dcb6afb3 +4c32baf326e0 +91ce16c07ac5 +3c5d1c2bcd18 +c3f19ec592a2 +f72a29005459 +185fa3438949 +321a695bd266 +d327083a60a7 +45635ef66ef3 +5481986d2d62 +cba6ae869ad5 +645a166b1eeb +a7abbc77cc9e +f792c4c76a5c +bfb6796a11db +# +# Data from Salto A/B +6A1987C40A21 +7F33625BC129 +# +# Data from forum +2338b4913111 +# +# Data from stoye +cb779c50e1bd +a27d3804c259 +003cc420001a +f9861526130f +381ece050fbd +a57186bdd2b9 +48c739e21a04 +36abf5874ed7 +649d2abbbd20 +bbe8fffcf363 +ab4e7045e97d +340e40f81cd8 +e4f65c0ef32c +d2a597d76936 +a920f32fe93a +86afd95200f7 +9b832a9881ff +26643965b16e +0c669993c776 +b468d1991af9 +d9a37831dce5 +2fc1f32f51b1 +0ffbf65b5a14 +c5cfe06d9ea3 +c0dece673829 +# +a56c2df9a26d +# +# Data from https://pastebin.com/vbwast74 +# +68d3f7307c89 +568c9083f71c # Smart Rider. Western Australian Public Transport Cards +# Vigik Keys +# Various sources : +# * https://github.com/DumpDos/Vigik +# * http://newffr.com/viewtopic.php?&forum=235&topic=11559 +# * Own dumps +021209197591 # BTCINO UNDETERMINED SPREAKD 0x01->0x13 key +2ef720f2af76 +414c41524f4e +424c41524f4e +4a6352684677 +bf1f4424af76 +536653644c65 +# +# Intratone Cogelec +# Data from http://bouzdeck.com/rfid/32-cloning-a-mifare-classic-1k-tag.html +484558414354 +a22ae129c013 +49fae4e3849f +38fcf33072e0 +8ad5517b4b18 +509359f131b1 +6c78928e1317 +aa0720018738 +a6cac2886412 +62d0c424ed8e +e64a986a5d94 +8fa1d601d0a2 +89347350bd36 +66d2b7dc39ef +6bc1e1ae547d +22729a9bd40f +# +# Data from https://dfir.lu/blog/cloning-a-mifare-classic-1k-tag.html +925b158f796f +fad63ecb5891 +bba840ba1c57 +cc6b3b3cd263 +6245e47352e6 +8ed41e8b8056 +2dd39a54e1f3 +6d4c5b3658d2 +1877ed29435a +52264716efde +961c0db4a7ed +703140fd6d86 +157c9a513fa5 +e2a5dc8e066f +# +# Data from a oyster card +374bf468607f +bfc8e353af63 +15cafd6159f6 +62efd80ab715 +987a7f7f1a35 +c4104fa3c526 +4c961f23e6be +67546972bc69 +f4cd5d4c13ff +94414c1a07dc +16551d52fd20 +9cb290282f7d +77a84170b574 +ed646c83a4f3 +e703589db50b +513c85d06cde +95093f0b2e22 +543b01b27a95 +c6d375b99972 +ee4cc572b40e +5106ca7e4a69 +c96bd1ce607f +167a1be102e0 +a8d0d850a606 +a2abb693ce34 +7b296c40c486 +91f93a5564c9 +e10623e7a016 +b725f9cbf183 +# +# Data from FDi tag +8829da9daf76 +# +# Data from GitHub issue +0A7932DC7E65 +11428B5BCE06 +11428B5BCE07 +11428B5BCE08 +11428B5BCE09 +11428B5BCE0A +11428B5BCE0F +18971D893494 +25D60050BF6E +3FA7217EC575 +44F0B5FBE344 +7B296F353C6B +8553263F4FF0 +8E5D33A6ED51 +9F42971E8322 +C620318EF179 +D4FE03CE5B06 +D4FE03CE5B07 +D4FE03CE5B08 +D4FE03CE5B09 +D4FE03CE5B0A +D4FE03CE5B0F +E241E8AFCBAF +# +# Data from forum post +123F8888F322 +050908080008 +# +# Data from hoist +4f9f59c9c875 +# +# Data from pastebin +66f3ed00fed7 +f7a39753d018 +# +# Data from https://pastebin.com/Z7pEeZif +386B4D634A65 +666E564F4A44 +564777315276 +476242304C53 +6A696B646631 +4D3248735131 +425A73484166 +57784A533069 +345547514B4D +4C6B69723461 +4E4175623670 +4D5076656D58 +686A736A356E +484A57696F4A +6F4B6D644178 +744E326B3441 +70564650584F +584F66326877 +6D4E334B6C48 +6A676C315142 +77494C526339 +623055724556 +356D46474348 +4E32336C6E38 +57734F6F6974 +436A46587552 +5544564E6E67 +6F506F493353 +31646241686C +77646B633657 +# +# Data from TransPert +2031d1e57a3b +53c11f90822a +9189449ea24e +# +# data from Github +410b9b40b872 +2cb1a90071c8 +# +# data from +8697389ACA26 +1AB23CD45EF6 +013889343891 +# +# +0000000018de +16ddcb6b3f24 +# +# Data from https://pastebin.com/vwDRZW7d +EC0A9B1A9E06 # Vingcard Mifare 4k Staff card +6C94E1CED026 # Vingcard Mifare 4k Staff card +0F230695923F # Vingcard Mifare 4k Staff card +0000014B5C31 # Vingcard Mifare 4k Staff card +# +BEDB604CC9D1 +B8A1F613CF3D +B578F38A5C61 +B66AC040203A +6D0B6A2A0003 +2E641D99AD5B +AD4FB33388BF +69FB7B7CD8EE +2A6D9205E7CA +2a2c13cc242a +27FBC86A00D0 +01FA3FC68349 +# +6D44B5AAF464 # Smart Rider. Western Australian Public Transport Cards +1717E34A7A8A # Smart Rider. Western Australian Public Transport Cards +# +6B6579737472 # RFIDeas +# +484944204953 # HID MIFARE Classic 1k Key +204752454154 # HID MIFARE Classic 1k Key +3B7E4FD575AD # HID MIFARE SO +11496F97752A # HID MIFARE SO +# +415A54454B4D # Luxeo/Aztek cashless vending +# +321958042333 # BQT +# +160A91D29A9C # Aperio KEY_A Sector 1, 12, 13, 14, 15 Data Start 0 Length 48 +# +b7bf0c13066e # Gallagher +# +# Boston, MA, USA Transit - MBTA Charlie Card +3060206f5b0a # charlie +5ec39b022f2b # charlie +3a09594c8587 # charlie +f1b9f5669cc8 # charlie +f662248e7e89 # charlie +62387b8d250d # charlie +f238d78ff48f # charlie +9dc282d46217 # charlie +afd0ba94d624 # charlie +92ee4dc87191 # charlie +b35a0e4acc09 # charlie +756ef55e2507 # charlie +447ab7fd5a6b # charlie +932b9cb730ef # charlie +1f1a0a111b5b # charlie +ad9e0a1ca2f7 # charlie +d58023ba2bdc # charlie +62ced42a6d87 # charlie +2548a443df28 # charlie +2ed3b15e7c0f # charlie +# +60012e9ba3fa +# +de1fcbec764b +81bfbe8cacba +bff123126c9b +2f47741062a0 +b4166b0a27ea +a170d9b59f95 +400bc9be8976 +d80511fc2ab4 +1fcef3005bcf +bb467463acd6 +e67c8010502d +ff58ba1b4478 +# Data from https://pastebin.com/Kz8xp4ev +fbf225dc5d58 +# +# Data https://pastebin.com/BEm6bdAE +# vingcard.txt +4708111c8604 +3d50d902ea48 +96a301bce267 +6700f10fec09 +7a09cc1db70a +560f7cff2d81 +66b31e64ca4b +9e53491f685b +3a09911d860c +8a036920ac0c +361f69d2c462 +d9bcde7fc489 +0c03a720f208 +6018522fac02 +# +# Data from https://pastebin.com/4t2yFMgt +# Mifare technische Universität Graz TUG +D58660D1ACDE +50A11381502C +C01FC822C6E5 +0854BF31111E +# More keys: +8a19d40cf2b5 +ae8587108640 +135b88a94b8b, SafLock standalone door locks. +# +# Russian Troika card +08B386463229 +0E8F64340BA4 +0F1C63013DBA +2AA05ED1856F +2B7F3253FAC5 +69A32F1C2F19 +73068F118C13 +9BECDF3D9273 +A73F5DC1D333 +A82607B01C0D +AE3D65A3DAD4 +CD4C61C26E3D +D3EAFB5DF46D +E35173494A81 +FBC2793D540B +5125974CD391 +ECF751084A80 +7545DF809202 +AB16584C972A +7A38E3511A38 +C8454C154CB5 +04C297B91308 +EFCB0E689DB3 +07894FFEC1D6 +FBA88F109B32 +2FE3CB83EA43 +B90DE525CEB6 +1CC219E9FEC1 +A74332F74994 +764CD061F1E6 +8F79C4FD8A01 +CD64E567ABCD +CE26ECB95252 +ABA208516740 +9868925175BA +16A27AF45407 +372CC880F216 +3EBCE0925B2F +73E5B9D9D3A4 +0DB520C78C1C +70D901648CB9 +C11F4597EFB5 +B39D19A280DF +403D706BA880 +7038CD25C408 +6B02733BB6EC +EAAC88E5DC99 +4ACEC1205D75 +2910989B6880 +31C7610DE3B0 +5EFBAECEF46B +F8493407799D +6B8BD9860763 +D3A297DC2698 +# +# Keys from MifareClassicTool project +044CE1872BC3 +045CECA15535 +0BE5FAC8B06A +0CE7CD2CC72B +0EB23CC8110B +0F01CEFF2742 +0F318130ED18 +114D6BE9440C +18E3A02B5EFF +19FC84A3784B +1B61B2E78C75 +22052B480D11 +3367BFAA91DB +3A8A139C20B4 +42E9B54E51AB +46D78E850A7E +4B609876BBA3 +518DC6EEA089 +6B07877E2C5C +7259FA0197C6 +72F96BDD3714 +7413B599C4EA +77DABC9825E1 +7A396F0D633D +7A86AA203788 +8791B2CCB5C4 +8A8D88151A00 +8C97CD7A0E56 +8E26E45E7D65 +9D993C5D4EF4 +9EA3387A63C1 +A3FAA6DAFF67 +A7141147D430 +AAFB06045877 +ACFFFFFFFFFF +AFCEF64C9913 +B27ADDFB64B0 +B81F2B0C2F66 +B9F8A7D83978 +BAFF3053B496 +BB52F8CCE07F +BC2D1791DEC1 +BC4580B7F20B +C65D4EAA645B +C76BF71A2509 +D5524F591EED +E328A1C7156D +E4821A377B75 +E56AC127DD45 +EA0FD73CB149 +FC0001877BF7 +FD8705E721B0 +00ada2cd516d +# +# +D3F7D3F7D3F7 +## +237a4d0d9119 +0ed7846c2bc9 +FFFFD06F83E3 +FFFFAE82366C +F89C86B2A961 +F83466888612 +ED3A7EFBFF56 +E96246531342 +E1DD284379D4 +DFED39FFBB76 +DB5181C92CBE +CFC738403AB0 +BCFE01BCFE01 +BA28CFD15EE8 +B0699AD03D17 +AABBCC660429 +A4EF6C3BB692 +A2B2C9D187FB +9B1DD7C030A1 +9AEDF9931EC1 +8F9B229047AC +872B71F9D15A +833FBD3CFE51 +5D293AFC8D7E +5554AAA96321 +474249437569 +435330666666 +1A2B3C4D5E6F +123456ABCDEF +83BAB5ACAD62 +64E2283FCF5E +64A2EE93B12B +46868F6D5677 +40E5EA1EFC00 +37D4DCA92451 +2012053082AD +2011092119F1 +200306202033 +1795902DBAF9 +17505586EF02 +022FE48B3072 +013940233313 +# +# Hotel Adina +9EBC3EB37130 +# +# most likely diversed individual keys. +# data from https://github.com/korsehindi/proxmark3/commit/24fdbfa9a1d5c996aaa5c192bc07e4ab28db4c5c +491CDC863104 +A2F63A485632 +98631ED2B229 +19F1FFE02563 +563A22C01FC8 # Argentina +43CA22C13091 # Argentina +25094DF2C1BD # Argentina +# +# OMNITEC.ES HOTEL TIMECARD / MAINTENANCECARD +AFBECD120454 +# +# OMNITEC.ES HOTEL EMERGENCYCARD +842146108088 +# +# TAPCARD PUBLIC TRANSPORT LA +# +EA1B88DF0A76 +D1991E71E2C5 +05F89678CFCF +D31463A7AB6D +C38197C36420 +772219470B38 +1C1532A6F1BC +FA38F70215AD +E907470D31CC +160F4B7AB806 +1D28C58BBE8A +B3830B95CA34 +6A0E215D1EEB +E41E6199318F +C4F271F5F0B3 +1E352F9E19E5 +0E0E8C6D8EB6 +C342F825B01B +CB911A1A1929 +E65B66089AFC +B81846F06EDF +37FC71221B46 +880C09CFA23C +6476FA0746E7 +419A13811554 +2C60E904539C +4ECCA6236400 +10F2BBAA4D1C +4857DD68ECD9 +C6A76CB2F3B5 +E3AD9E9BA5D4 +6C9EC046C1A4 +# +# ROC HIGHSCHOOL ACCESSCARD +# +B021669B44BB +B18CDCDE52B7 +A22647F422AE +B268F7C9CA63 +A37A30004AC9 +B3630C9F11C8 +A4CDFF3B1848 +B42C4DFD7A90 +A541538F1416 +B5F454568271 +A6C028A12FBB +B6323F550F54 +A7D71AC06DC2 +B7C344A36D88 +A844F4F52385 +B8457ACC5F5D +A9A4045DCE77 +B9B8B7B6B5B3 +AA4D051954AC +BA729428E808 +AB28A44AD5F5 +BB320A757099 +AC45AD2D620D +BCF5A6B5E13F +AD5645062534 +BDF837787A71 +AE43F36C1A9A +BE7C4F6C7A9A +5EC7938F140A +82D58AA49CCB +# +# MELONCARD +# +323334353637 +# +# +CEE3632EEFF5 +827ED62B31A7 +03EA4053C6ED +C0BEEFEC850B +F57F410E18FF +0AF7DB99AEE4 +A7FB4824ACBF +207FFED492FD +1CFA22DBDFC3 +30FFB6B056F5 +39CF885474DD +00F0BD116D70 +4CFF128FA3EF +10F3BEBC01DF +# +# Transportes Insular La Palma +# +0172066b2f03 +0000085f0000 +1a80b93f7107 +70172066b2f0 +b1a80c94f710 +0b0172066b2f +0f1a81c95071 +f0f0172066b2 +1131a81d9507 +2f130172066b +71171a82d951 +b2f170172066 +1711b1a82e96 +6b2f1b017206 +62711f1a83e9 +66b2f1f01720 +97271231a83f +066b2f230172 +f97371271a84 +2066b2f27017 +50983712b1a8 +72066b2f2b01 +850984712f1a +172066b2f2f0 +a85198481331 +0172066b2f33 +1a8619858137 +70172066b2f3 +b1a862985913 +3b0172066b2f +3f1a87298691 +f3f0172066b2 +# +# Tehran ezpay +# +38A88AEC1C43 +CBD2568BC7C6 +7BCB4774EC8F +22ECE9316461 +AE4B497A2527 +EEC0626B01A1 +2C71E22A32FE +91142568B22F +7D56759A974A +D3B1C7EA5C53 +41C82D231497 +0B8B21C692C2 +604Ac8D87C7E +8E7B29460F12 +BB3D7B11D224 +# +# Chaco +# +b210cfa436d2 +b8b1cfa646a8 +a9f95891f0a4 +# +# Keys from APK application "Scan Badge" +4A4C474F524D +444156494442 +434143445649 +434456495243 +A00002000021 +EF61A3D48E2A +A23456789123 +010000000000 +363119000001 +A00003000084 +675A32413770 +395244733978 +A0004A000036 +2C9F3D45BA13 +4243414F5250 +DFE73BE48AC6 +# +B069D0D03D17 +000131B93F28 +# +# From the DFW Area, TX, USA +# +a506370e7c0f +26396f2042e7 +70758fdd31e0 +9f9d8eeddcce +06ff5f03aa1a +4098653289d3 +904735f00f9e +b4c36c79da8d +68f9a1f0b424 +5a85536395b3 +7dd399d4e897 +ef4c5a7ac6fc +b47058139187 +8268046cd154 +67cc03b7d577 +# +# From the HTL Mödling, NÖ, AT +# +a5524645cd91 +d964406e67b4 +99858a49c119 +7b7e752b6a2d +c27d999912ea +66a163ba82b4 +4c60f4b15ba8 +# +# CAFE + CO, AT +# +35d850d10a24 +4b511f4d28dd +e45230e7a9e8 +535f47d35e39 +fb6c88b7e279 +# +# Metro Card, AT +# +223C3427108A +# +# Unknown, AT +# +23d4cdff8da3 +e6849fcc324b +12fd3a94df0e +# +# Unknown, AT +# +0b83797a9c64 +39ad2963d3d1 diff --git a/client/dictionaries/mfc_keys_bmp_sorted.dic b/client/dictionaries/mfc_keys_bmp_sorted.dic new file mode 100644 index 000000000..85ab141e0 --- /dev/null +++ b/client/dictionaries/mfc_keys_bmp_sorted.dic @@ -0,0 +1,1000 @@ +002DE0301481 +004173272D18 +0058A4884CA5 +00BAC32761D8 +00BB79731B00 +00E8C85DB172 +02096124DA70 +024988BC4D5E +0271B7C4B015 +028137A705DB +02827C286AB4 +02C10DA600D0 +0340643D5E27 +037A5DA4682B +037AC43CBD9D +037B9B8AA219 +037EE3DE21B7 +0380A9A3CBDE +03D10A75B56A +03E8CD22E691 +04109ED8EA79 +04361330B35C +043D8B66D569 +045E5588845C +048DE5148DE7 +0490921D0194 +04B717BD92EB +04D49C76623B +051518B3301E +0529E8827A52 +052B16064085 +05DC4016B500 +06124317A9A6 +06147D199266 +0670AEB833CE +0686A9E6D6E0 +06A34E5E6639 +06B78AD0C4BB +0710E7818AB8 +07121B8C633A +07176713C0ED +0793533A5087 +081D1B1C3110 +0849495E1CCA +09429512046E +0966C3B28E04 +098A92C3660A +098B48278122 +099672009EEA +0A7632943926 +0AEE126549DA +0B3B8C2833BC +0B733C13E2C9 +0B764247D00E +0BE811559D69 +0C208AD4E4B3 +0C270BC0BDDC +0C5D782CB183 +0C82C94EB11B +0CCDE948878A +0CCE39820AAE +0CDE3E716B32 +0CE06C96DB4C +0CE87813E389 +0D3385CEA152 +0D5C5B8BCC5B +0DB0A87AB882 +0DE247593B93 +0E0AD1796003 +0E62E6CAC3D3 +106E2D6E55E6 +1096A7830C82 +11549C141AD9 +116A92C793D6 +116C31526819 +11C68052AAE9 +1234B5BE8E78 +1268C7D104E1 +12A21B5671A8 +13359D5AE9A5 +1426EC62BB6C +144489B1056E +14A22C112090 +14C9BBB5361B +14EB6286AC57 +14EE72B27223 +153BB53ACE71 +157B03405B38 +15A45083D24E +15DACCE8D5EC +16124677BBC5 +16373A44D5D7 +1663659384DC +167828B6105C +16B25A453093 +1706B1BE25C7 +171B15888483 +17BC8EED9A0C +17C6299D5A37 +17E9C4C416EB +1804087C7166 +1841CC4E3E79 +18AB05761CC5 +18ADAAC2B08B +18E566417E5C +191390328752 +1A47959E7DB4 +1A9A970CC370 +1B095E78BB33 +1B1717043D2B +1B1A054566D9 +1B4654AE9454 +1B9CD1ED3420 +1B9E00780953 +1BB6A9CE71E2 +1C1250A36A13 +1C2316079532 +1C2855ED7A10 +1CD1AE73CA8C +1CD3D4E690B7 +1D0322005969 +1D09B23EB116 +1D67A32045ED +1D89D900968A +1DAE8D2CEA5C +1E1873799CD7 +1E60CE7C5179 +1E6A67909B8D +1E8516585792 +1EB0864E9134 +1ECE3D04A020 +2009828E4A21 +200A6A3AA65D +20188A599582 +20267CB20256 +20628CA7D92D +2077C980EB2E +2089B5D68B27 +209481EC6256 +20B6691C64B1 +20CC5A00C677 +211473555436 +2170E9D0D448 +219529A90EDD +21A5B6481B7D +224A308017D1 +227D16EA455A +22A1245CA266 +22A95CB798DC +230E26964171 +231173B68E46 +2332BB9A2452 +234323BC2992 +234E50256146 +235C9338D5B6 +23789D9ADD0D +23997DD240AB +23A5BA53AD4D +23BB58853461 +24CAD4153036 +24CE79506842 +25228ED714BC +257377227B34 +2584287A0174 +2616192EEB22 +265C03B50877 +26D641E834DC +27073B57132B +279060E3DEE9 +284BA0A0A29C +285C6604C5B4 +28B20331245A +28D042242A83 +28DDD4C3E9C4 +292C2CCD157E +299ABB519354 +2A41BE015C1D +2A4A55052A51 +2A94CBCD7A6E +2AB6536187C7 +2B2D2DC3D319 +2BD607CA70B2 +2C6C7957EB3E +2C9E9E4D0895 +2D2A97DD45E3 +2D41850A8AA6 +2DAC030D1AB9 +2E12426D8847 +2E25AD1D6D8D +2E2E85E0E6C9 +2E4340CC1C63 +2E6803BE2E11 +2EB24B573DCD +2EC6450A47C7 +2ECDA9A5EA96 +2EDE1C155023 +302D5D37342B +303645E47667 +303B30A460E8 +3048EBB8A18E +30BD652BED24 +30CCE5ECB397 +310241E1CB36 +312670228372 +319E8895EAB5 +31E3A933BC4A +3250D2E661DA +32560224418D +32589E221D10 +326657A8E9C0 +329AC7C59311 +32A091B89995 +3312C094BD20 +336C8CBA5AE2 +34240649314A +3493D84E6317 +349A347186D7 +349BEAC5210E +34A939B49EDC +34CC7E36C8C4 +34D71347877E +34DC25B4D0CE +35895EB472C4 +358A6A398211 +360A08C66042 +36306A9CA571 +37284428A250 +377EC8A78B8D +37BD90A68613 +37E602347133 +382DE6AB2D1A +385D498B5390 +38B67589E47D +393CCCCCDA4A +39682B3E10B5 +397619525709 +39A83A32909B +3A5834C46513 +3A70C7A4BCE4 +3A818D01E093 +3AA5AC1CDC21 +3AAE07339954 +3B4497052B42 +3B784087DB2D +3B86A20C16EA +3B8E321AB1B4 +3BC4A3099B0D +3BC741376E71 +3C4C95D0A0C7 +3C84B55A5E54 +3C888A88C59D +3D5C8240B2D2 +3DB004172BE7 +3E23271C1C15 +3E3188294ED1 +3E84144A770E +3EA227893101 +3EB914E70076 +3EE6D4A85643 +40DABA780B41 +4119340759A2 +415210E0C6BB +416D21717779 +41B1839829A9 +4201A36DE766 +4261A795D5A7 +42AA0B29626E +430265958BEB +4317C5C16EAD +431D799E0C89 +4342794AD7BB +4387ADE263DB +43982124C310 +4436CB060568 +44449507B736 +44E858C82975 +459BC12982B1 +45AE5DDA9830 +45C414CDC347 +45CE4E504C06 +461744C8EABD +46D012CA3BEC +47170BD112B6 +47C43D5DD234 +47CD4AC26271 +47D410D1C7C4 +4808C5AD0115 +485BEEDBC293 +486001404A80 +488CCC60B70A +49204E3CA169 +495657C78147 +4970714D53D9 +4AA715A0BBB4 +4B9901AEC16E +4BE0B912A5A3 +4CBC34D10D83 +4CD3ACABC6A3 +4CE00134DE1E +4CEB27151C49 +4D02A3D7CE48 +4D13683C7960 +4D1A263BA48B +4D23919463A3 +4D9763C083D9 +4DAC8EE52C68 +4DCB89C7B2E6 +4DD9D9B637C4 +4DE6CB63A920 +4DEBA10CC85D +4E232A8C2E30 +4E2879A411E7 +4EA7B0BED74B +4EB8761372EA +4EC2B23135AB +4EC71DB088DE +4EC9AB4B5519 +50179E461EE6 +50265ED9D468 +5047DC2975BE +508357498162 +508BE54D326E +510A8C52AAC4 +511335CC92CD +518229589A81 +5184D04315D7 +51B4AE31B246 +526EDB918BEE +529CE44BEBCC +52A843082BB3 +52AE9A909674 +5313E9079489 +532DE5E7E0E9 +535508AA6C91 +53691569B669 +540A5B789761 +547B86E57596 +54C649075B57 +552249203848 +55430B5318E9 +5570D22DC66B +55710879E113 +55D2E4AC0446 +56207539825A +564664475726 +566441C5C28C +56A7930913C3 +56C944B04618 +56D455A8BBEA +5726991C8C28 +5726AA3BE37B +573314090BA5 +577C31903867 +577C528E786C +57AD9604ED24 +580C377283C7 +587329CE3EBE +587C34557B36 +58B11E803B58 +5902E4DCC95D +5A060A64C535 +5A36898CA7C5 +5A4740D952EC +5A6ED7966868 +5A99578CAA13 +5AAD6814E68B +5B065568048A +5B6CE0B3AD0A +5B70E0B11758 +5B926E3751EB +5B9CA63C4267 +5BDC1391B289 +5C1D3898D537 +5C34B8E4A456 +5C36456EA1E5 +5C43A75C65A0 +5C5752328A47 +5C9D20250D74 +5CBA3CEE351A +5CD5E98A2864 +5CE0EB9C01B6 +5D384E6A4145 +5D9DB8445155 +5DE8717BB640 +5E1A4EE98748 +5E45A227B391 +5E8E50B3048B +5EB0EA0A9412 +6032C47B7676 +60E0C84ADDEE +612A447A2149 +612D81821854 +616B820EAD01 +616D75A4A022 +61DE2B085AC9 +62312EC272A0 +6232C5262CC6 +62B7C7C9B0D0 +62C531C6E29C +63E6AAAB4433 +644ABCC3DD12 +64AE7BEA1784 +6515B38077D6 +65972038CC25 +65E120DE5E55 +66141DDE8320 +66718BD91332 +668082242328 +668920AEE063 +6696C4332D46 +66C9880D1DC2 +67150CB11E95 +671737BA0054 +673551D0A99E +676D682C4336 +678B98AA2E86 +6847808E63EE +6887A122AA62 +6888C514DEAD +688BD5B7B4E9 +68A99E258692 +68C312391560 +68C9D33E3735 +6900A069E3D7 +690155BE8D8E +69174742042D +69B9CE233517 +6A0B123D7595 +6AB8E2B49E25 +6ABD4C4A72D9 +6B1CC539A1B2 +6B30B6B0925D +6B638C1C950D +6BAAAB1D4589 +6BAD01EBE736 +6BB4ED5E1682 +6CA178E036DA +6CE210B529C4 +6D23D505D2B1 +6D3CBD12BC6D +6D83563EB521 +6D98AB9CCC71 +6E3D7366E78C +6E5582237608 +6E6602904925 +6E77B8EB6444 +6E978A7B16C6 +6EEC05EB651C +70284824B26C +702CDACE0C14 +704E1B85BED8 +70BB123776D6 +70CCC3A2D7C0 +716A747CB931 +7173E199A420 +71BC9C9E31E4 +71CAEEA3B771 +71D8BA423D55 +72253C7DD951 +7260377CD286 +7280858E8B20 +72913BDAB647 +72B5B87BBC6E +72C83B1D098A +72DA8050A38E +735C2AB60A97 +736B602A93D9 +738D7833E7DE +73E7B22D6E54 +74133B1E2DED +74A929877793 +74E3670C045A +7531E3E2A41C +7542A9B65EB4 +7564993C91C7 +760ED0AB626E +762E0E021E38 +763D7E6BB40E +764B38E2903D +768016001C8D +76A616C3D42C +76AE99D9A294 +76BAAA710D25 +76E3B23696BC +77322DD2E184 +77B40902B6D9 +77C0AC14972D +77C1CE0E7674 +77D7B7E2C8BA +78279397A68E +7836593AB838 +783859EB51A6 +78CCDB50C193 +7932684154AE +79604362370E +796630ED27B3 +799E4E270953 +79A00573947A +79B798D66B01 +7A0455D0A7EC +7A33D19B7248 +7B0A8AE18817 +7B0BA045AB35 +7B0DE8504D57 +7B21781EC649 +7B7224C1AB79 +7B90C2BA9B23 +7BB90D382672 +7BBC9DC92836 +7C09DC408C47 +7C418B493454 +7C491D518242 +7C7A86CC727C +7CE836EBD228 +7D49042C530D +7E5744EC286C +7E680A48C383 +7EC45CCEC35A +7EDADA19EB57 +8005BD088847 +8022E705B640 +8031E3565825 +80499BAA5959 +807466CCBAB5 +810518578380 +810D24CB13CC +812B02C34A64 +8163A5DDE1CD +8186CE2B363E +81DE6062B9D7 +822017D8929A +8247C78188C5 +8270D538D5E8 +82D8E8DDE296 +831207CA6E8A +83378A077357 +83A05B477535 +840160379EEE +84044BAB78A7 +84366C6D7781 +8442CC9AA777 +8470AAD30447 +8498740493BB +84A35A698E93 +84ABDE484425 +84B24DBB9A67 +84B723B2A237 +852BEB133D74 +854501E98239 +854A0ED2E77D +85A066D39785 +8619557091AA +86228C3742A4 +8637BB3BA795 +8642D9310B46 +86538085966D +86EE9C410811 +870A042C1B34 +873B47C457E6 +873CE44DDC6B +874D123262E7 +87513C960770 +877641436923 +878A091B74B7 +87927467808B +88C2E39B5990 +88D252AC1A8A +891EDA20BDEA +89267DEE07ED +892CB89ACCC6 +8A2423E9D100 +8A6BC2E3811B +8A8EB5771EE9 +8A906B4B3211 +8AB21B524C5C +8AB823BDC2AE +8AC3B2ADE77B +8AC4317D049B +8ACD6B86EC44 +8AD966CA3B4D +8B0A3B3DCDD4 +8B1B6C705C1A +8B1C75E27153 +8B2A5E0332A1 +8B6216E412DB +8B7CCA9DB004 +8B9999AE9703 +8BABAD9A65C6 +8C32D0AE3DB7 +8C99807368A5 +8CC1133D7D5B +8CD2C872187A +8D0563B86DD4 +8D43D81E37B4 +8D96A800B21A +8D97B475C957 +8DA62EC0C524 +8DACA1BC0636 +8DE3B131D728 +8E55316D3B3D +8EE497C9A869 +90210DDAB57D +9026977EB8A6 +903AA4305025 +9083158A49A1 +9092D12E7967 +90D8713352D1 +911E097A27A9 +9140EC087241 +918A67D05479 +919B1D357E91 +9210BBA2AB26 +9224B6555E30 +9226D4D1236A +922E7955CC67 +929CC86B1B26 +929E1556110E +9302DEB79C5A +9384841B4702 +93B4BD1CB47C +93D985D55712 +940B37939AC6 +94673AE73823 +947A8147E0AE +94CD6A4B6391 +94CEEAC5A8D7 +95ABD3A7C631 +95E1C233EDE2 +9607AE17AD09 +960C98566E52 +96435BD1D29B +965D66E19245 +965D72659982 +9695167B4149 +96D0C3996714 +97274C21BD6C +973186B345BB +973A28C983A3 +979686C51AB6 +97992CE2DD31 +97E9D0C89DA8 +97EB8A44C49D +98314DC363C5 +9860DC044565 +988D023C15A5 +9917BDA7B4D7 +9996A233442A +9A2132B5B625 +9A694755A978 +9A7911ECC275 +9AA1E6CE588C +9ABCCD2AE7C7 +9B39A60D3841 +9C0630361CC5 +9C4E19AB64B1 +9CE96BADE4D8 +9D442B28BD11 +9D4C35AE1A08 +9E02910C691A +9E46407C9024 +9E74D104ACEA +9EDD416A7912 +A026642D13AD +A12908B38536 +A16EE9666D5A +A199132A4043 +A1AEC2B58BBA +A1BE42A15EDE +A1D0844C2C63 +A1E0103A1879 +A253602B9445 +A2B019B46CB9 +A2BBCC3B546C +A2C325A73A9C +A2CB60E815A0 +A314B97C1A6A +A3647146C335 +A3A580799BB4 +A3D30CC8EB97 +A402B5137D86 +A42158CC74B5 +A435DD64AD17 +A4693D21013B +A479A91EED49 +A4B30D146A01 +A5142D626200 +A54056E87CBB +A57DBD287491 +A588C918E327 +A593071D4758 +A5CC0EE7B9E3 +A6375E98A5B5 +A666347B3B4B +A6A203994202 +A6BAE1A1520D +A6E9885AA49D +A705087E89A8 +A7072D4324C7 +A745AD7D6789 +A750456E7C5E +A783A8774651 +A787C822020C +A78BB575EAC5 +A7905680A254 +A805534D84E9 +A86C2595A1C3 +A89903B6ADDB +A9182707A219 +A9391782A846 +A96B08E3A50B +A98DEB0733C9 +A9C37CE71D23 +AA2D69C757D9 +AA4E4558A9EE +AA6C835C9124 +AAC0C35C43EB +AB30CB2CB354 +AB6191DB240A +AB8953D3560C +ABBB521319E6 +AC47461358D7 +AC58C25A1559 +AC7D4B201D92 +AD061A23287D +AD105D52DB36 +AD4EA84D7185 +AD5038D15490 +AD97523144B2 +ADB24E78784B +ADCBD453B232 +AE516A187825 +AE52116C234C +AE817239CAB5 +AEA5A5A0E46B +AECC93678543 +B0452769A83C +B04D71906C60 +B0805C191424 +B09172DDBE43 +B13AE369390C +B14080E570D1 +B1419B62772C +B14775DEA2E2 +B188BA649EA1 +B1BB0DB95C67 +B1BB19BDD424 +B1E8B5054DAD +B1EBB537CC0D +B2174092CDC5 +B2554CC8AD6E +B2C5A2E88304 +B312E56ED250 +B37B48D8C1C5 +B39C699CD208 +B3B121208E34 +B3C3C6E4395B +B410B958C3B8 +B4204546A74E +B45171C5A67D +B4B103E693ED +B4DACABCAB07 +B506567A2B84 +B51083D5C2BD +B54D7674CB90 +B570E5EA1DA3 +B598984AD584 +B5D7E1135821 +B60D053A36D9 +B63957593E23 +B64558CAC0C9 +B68175BCA864 +B6CD1A3EC5BC +B72468A7710D +B75176C82A8B +B7AA0CA5D94A +B7B9D7E523B8 +B808D87AB75C +B93A6432E51A +B941A9D99B6C +B9DA40920237 +BA6C2E10086A +BA7384AB949E +BA8DEEE045E8 +BADC2149EC42 +BB1924266B36 +BB41640E6340 +BBB475DB2B03 +BBD4C4699719 +BC0B2C897267 +BC7BEE6B71C4 +BC8B21AD8802 +BCA2D8118631 +BCB7A7006400 +BCBC6637499B +BCBD2B8BE4B3 +BD213E28C568 +BD32E4EC7080 +BD401D63C3E9 +BD463C3693A4 +BD749E85586A +BD7CA11B9551 +BD96355CBE36 +BD9E6EB7B524 +BDADE6111218 +BDB576D1E88C +BDB5DC09C522 +BE19C75D6B7E +BE5B3ED935AC +BEA20C972E70 +BEEB4A159B37 +C01E8740DE38 +C0411C28857D +C045544AD1E4 +C04660B76831 +C0C4CA21B876 +C0E0E092C8B4 +C0EE394D3D95 +C14601C6B411 +C16EBAE928B2 +C189A791A85B +C1ACDB8C1890 +C1C55A7A99EA +C1D72A47755A +C1D8B91D65AA +C1E6149B386D +C22D8E2B1E37 +C23E999B6298 +C314E31A670D +C3D275A9B8C7 +C3EE19B61C89 +C427B93DC2ED +C443EEC4330D +C477B966D328 +C4C6CAE4784C +C55875BCB82C +C581CA998910 +C5ABC0A455C5 +C5BE33E6B1E2 +C629E0D34581 +C65194543D6B +C67B8E869D90 +C6BC3B9CCB41 +C7034BC581A6 +C748500B6947 +C757C15E9E0D +C798A8465ACB +C7B6702AC17B +C849133B7CCC +C870C98A4E91 +C90B7AD266D3 +C90D996C3A2D +C953797CCE61 +C9639352EEC8 +C983685AA86B +C9CCA6D095A3 +C9CE81D47EDB +C9D449AD9970 +CA0D9CCC4C38 +CA277AC09859 +CA56EB045188 +CAB92B865BAD +CAE8572C2657 +CB1CE185575C +CB2ECC3D9C22 +CB642A081A89 +CBBAD2DA0EC5 +CC1B5BD45315 +CC2C02300D34 +CC559969D0CC +CC5646BD7AEB +CC6A93BD93D1 +CC726DD08765 +CCBBAB6504A4 +CCC1EA3E27B8 +CD16EAB946E9 +CDB4EEE02E14 +CDC21E1E1EC7 +CE09B3870EA2 +CE5AA0C8B5A8 +CE63DE29E069 +D0368B24CA49 +D0489010A72C +D075379A21A6 +D09893B4EE04 +D0A7A2787570 +D0B8C06C02E4 +D106E94A4C3B +D11E7D1BBEEA +D12B25B8DDE2 +D1972D6CE2C3 +D1B91D224946 +D2752E53679D +D35B2B75CC52 +D40E935117A2 +D4C37528DC05 +D4C818A5455E +D4CD56DB8AEB +D5190BD5CED6 +D55E5AA3406D +D576E9D856D9 +D5E444E9D82D +D61A3231790D +D669B3AE1E11 +D6C075899D06 +D6C3503456C4 +D7AC70A05A0C +D80A37B6D7ED +D82E6938C58C +D85E51344EB6 +D8809EB9BA7D +D8913C2D48E9 +D9109460D912 +D94E36427E20 +D97E55B1816A +D99425130C1A +D99C3222A190 +D9A207103ED7 +D9C70CC5818A +DA3379D12773 +DA705702248C +DA818C56CE43 +DAE1888DCC0B +DBA0A2DCA8E0 +DBD9799E15B1 +DC242193D7E3 +DCB5AC62946C +DCB75AEC61A0 +DD6E0587A821 +DD7B1A7C6A82 +DDA22A189095 +DDDAE53AA711 +DDE7304E78B6 +DE1B4DA681B9 +DEAC67E2D7C1 +DEB7D7E4C62B +E127434AB3B7 +E1ACC6742AB7 +E1E59574ADBC +E1EA6BAA03D9 +E222553A59A2 +E2230B8E84C9 +E33E807EC3BA +E341574B2E32 +E42868808B70 +E43562C624B0 +E43D54DC3511 +E466090D2123 +E47069DA0C44 +E49DD6062901 +E4ACA0ADBA0D +E4B976AD6687 +E526BB7888DB +E53354B71B10 +E57581CE8617 +E61A1DA5A60E +E6293BDA5EDC +E64C2A07CA9B +E6600C4D6A44 +E6655B6425DC +E6BADC631036 +E70143BE0091 +E75E07A010D1 +E76962E3B8B4 +E8028A6DCC90 +E80C5E3E8227 +E8779E40450E +E8A9E2D87D36 +E8B5A0BDD993 +E933DA9735C4 +E93A2E63189D +E9447637E40D +E94836269887 +E94D82A564BA +E98DC3B561B5 +E9EB2DE57AE9 +EA490920877D +EA4C494C9353 +EA9B1695DD91 +EAD0E31A6834 +EB16B6462B66 +EB276C9AB68D +EB3C9732C3BA +EB44DDC408CE +EB8536C958B2 +EBC825C186B3 +EC1A55BB58EB +EC2B12107313 +EC8CB5758097 +ECD4C42EA3D1 +ED22B7115435 +ED2CE17A590C +ED65A9B6469C +ED6748113E0D +ED8CEB8B7102 +EDCE0890472D +EDD4A2EA7493 +EE17C426D25E +EE487A4C806E +EE5931913A8D +EED56840AEBA diff --git a/client/dictionaries/mfc_keys_icbmp_sorted.dic b/client/dictionaries/mfc_keys_icbmp_sorted.dic new file mode 100644 index 000000000..2fe3c0235 --- /dev/null +++ b/client/dictionaries/mfc_keys_icbmp_sorted.dic @@ -0,0 +1,1000 @@ +00383D96411D +005307DB7853 +009A4C4C6C49 +00C447B8A2D2 +01124119AB54 +0117BAE4D8D9 +018861488381 +0267B4922681 +02974B9786C9 +02A46AC9233A +02BED876BD48 +02D8A7729ED3 +02EB32B92D30 +03C34821DE9A +03D87397E9A8 +042CDEE5D0BA +044ED79417E1 +04524659496E +04602A40C037 +048451A79DA1 +0490AD0C9283 +04E16965C142 +05138E278443 +052B99EC186E +056D4B5D2915 +0578E317C419 +05865124E5CA +0599E014139E +05DB68DB9364 +066C127C208D +06966B31A285 +06B577E0E480 +071B57D258CE +072B300309C9 +0759955331EE +0769855EEC13 +079B8DA54DB1 +082B68A67491 +0832E4783600 +08506533E741 +0853A982D793 +08629D1DD0D6 +087C0CDA3B46 +08AE4ECD7CE3 +0965220D2ECE +09A14A80754E +09ACEA48DD0D +09DB8EE5458C +09E6CB76C080 +0A44A754B592 +0A7328887DC2 +0A906663EE1C +0AB08938E3DA +0AD8AD0739A6 +0B00220EAE75 +0B1960681E79 +0B31815E6A7C +0B3690D4B122 +0BB8414CB6EA +0BEC525E3463 +0C296648344D +0CB6CC83AC45 +0CCAD03DDBC6 +0D6C26AB25CD +0DC9143735D1 +0DE8A36CBBCC +0E175033BD77 +0E6478123917 +0E7D4AC83133 +0E8420B04083 +0EA607E1C4E3 +105743704432 +107A6AB6B305 +110BB6D5539D +1114A47CC39A +116AA873ACC8 +120616C6208E +120C83C06317 +12343D71106C +123A082E2AEA +12E50BE60524 +133DC845505E +138153A4351A +1395C108B6B6 +1428C04BAAD1 +147D93848C70 +14A353C60820 +1504C1846399 +1523A1E39D03 +1532A2511A8B +157308368E8E +16065CC411E0 +1637D8ACA71E +1639134699C7 +167358BB268E +168DE72B3B5A +16A05D5C31C3 +16B4442EAE97 +17197B247A4A +1774DB1A8CA1 +17820DAA47B2 +1782BEDBD347 +17B561AA82B4 +17C548CBC3A6 +17DA5C873BC5 +18025130661E +184B95B4E3C6 +18A3196D364B +18A97BD26818 +18BE810A83DD +18C3AC2A7E90 +194D4E1DE89D +196E279BE9A9 +1A2C8D855336 +1A3A76ED470A +1A55D4849951 +1A9872D00EC9 +1ACD5433BBDD +1ADC527D5BDA +1AE29C8CD672 +1B14CAC3D0C2 +1B20A6E1D06B +1B30A7825B23 +1B3E45AEE657 +1B75E7B007DB +1B9DABDEBAE0 +1BAB19D01495 +1BD3119E0363 +1BDA0D87A575 +1CD38D77090B +1D12BBB575B1 +1E1A0DB8729C +1E2DE60A477A +1E3C71643766 +1E6ED46CE258 +1EE60A4A8D22 +200D45263629 +2013899194BB +206CE78E0C6C +20B51C977E54 +2142B57D369D +2172D827D3E2 +2178ED80D581 +21B4BE97AE07 +21B91A26133A +21C7650673CD +220D815D366A +22C2176E1CD6 +22C3AB41B123 +233D7B324CEE +2340CBD61A71 +2348251AD23E +2381B8214025 +23BAE8DA1AC5 +23C317B8D6DA +243A41574A39 +248EA5E91987 +2491457885A7 +255A9E590BCC +257192699E32 +25892216C620 +2595E5B1DE76 +25AE69DED1B4 +25BA8775B3C4 +25D967D4DD35 +25DB996D56ED +25EE21CDE4B9 +2625E408276B +26B744C673DB +26C6D38B8257 +26D787613684 +27689527E201 +27743B5A5736 +27D1635ED1B3 +27D5B8D2642E +28035CA5B300 +2812EB6A427C +28133B46730A +281499DD16A0 +281DD9E6C98E +2870E08CEDBA +28B8685B1B22 +28C3D17E4DEC +2953C63E9E58 +295D3C9A8B28 +297B74853CAA +29ACACC2828E +29EA97BC4A6B +29EB3CA1C0DE +2A079CC2AD37 +2A27E0602400 +2A45A0D8D6EE +2A47CDD3A322 +2A4C4DB1D71D +2AA82B4B6711 +2ABD68BDC5A3 +2AE7BDB10CB4 +2B051C90BE82 +2B490231E063 +2BAB94372644 +2C03252C10E7 +2C3EE5E98804 +2CB671E6365D +2CC55B46705B +2CD09D3C0A1B +2CECBC323E31 +2D302827C9B4 +2D716C9C467B +2D8856109732 +2E15681A4355 +2E79209B9519 +2EEE063290C1 +301C9AA3DECA +30C520D6A2B9 +30D6324910AB +3113AADC9D6B +3124ACA5491C +315AD0D6E6D2 +31A16DAC864D +31EC44581294 +32DE3CD81C24 +32E532232C29 +33256E443128 +33293485AD61 +33305B0365AA +3343B72BAA71 +3372C9C5D4AE +33754E0D1687 +33A444334869 +33B54345C32E +34002AAEE45D +343C556CEE59 +3444DDE6D7E5 +345B62452538 +3495A04A9270 +34EB673C863B +35123500C1EA +353A7167576B +3599856810B2 +35E7DE9899EE +35EDABB506D8 +36C54912D10E +36CA0101B6DC +36D268442846 +373E5827E0B8 +376D6C446746 +37E2EAE635B5 +381B0A70E135 +3862B259DC71 +386676C44A13 +3905679DEEC4 +39070618BB17 +394181105544 +395D38815892 +39A00E856381 +39C0E2ED99B5 +3A1E82E2CDB7 +3A5D13E05B6A +3A6DE2081CDD +3A8498924010 +3A9D49E8BEB2 +3AD0EE1031A9 +3B052E65D40A +3B4986981212 +3B4C51ACC53D +3B99486097C6 +3BB36BC22CE4 +3BB4B3025B79 +3BBB7BD8D7B7 +3C09C971D835 +3C4A12E7A107 +3C633B3474DD +3CB9E31D6022 +3CD344A7EB21 +3CD8C6705954 +3CE887B9D091 +3D5EA1C71953 +3D89120EB993 +3D9C3245AE76 +3DED9D496478 +3E0913A96E74 +3E34909990B5 +3E7DD7953DDD +3EEB33434C1A +4015D16B5C1C +401C81A72C56 +40E7B8D60242 +41016C0CB8DE +4124864B0D40 +415BAA0CAB15 +418184DBB4A0 +419513740558 +4195EE7238CC +41B727883B27 +41BC44A8C3C6 +41DDC3A48EEA +420445087613 +42068108DE36 +4245921D73CA +42A959953C45 +430E67734C18 +4314D9D03B95 +43166BCA83EB +43400A093A7E +434CE764DE91 +43595AC786EE +438099331C1E +43814087A7B5 +438C3CD95B58 +43B3E895B281 +44074C461042 +444D37149B20 +44A04DAA30CB +4537282554C5 +4584EACB6087 +45DB3799C150 +45E599AE38EA +462305611C4A +4636195CDA2D +46752993E2E9 +4684316440D6 +46C7246C1958 +4751A5274848 +4761E34CB054 +476388408D8E +478947735B45 +47AD81972D5B +47C23398EA52 +47E9D4D4BE35 +4812AEC4B01A +48276645A4EA +48644467A214 +489C783B3514 +48C860AA4B74 +495C6639575B +49681C20A00D +49E8249DD677 +49E93C110AA1 +4A24470C19C5 +4A4755BC4A2A +4A4D5E3A9011 +4A65D627625C +4A6B36C5BCCC +4AB725ED89B5 +4B39E3923D0D +4B59316C10E0 +4C275C8BB2DA +4C2E9455D296 +4C44DB1D0C3A +4C67059B0006 +4CA30E1A298A +4CA74DAC7C01 +4CB212D72D57 +4CD3B228EBB4 +4CE1972E090C +4CEE1794E0EA +4D06DBCA167E +4D2CC85EB338 +4D40BC7A44DB +4D769DA515D3 +4D79C95DAD2D +4DBAC8ECE167 +4E3CB839E87D +4E3D548E1267 +4E8250E29617 +4E94C7962769 +5038884E4178 +505B5A8EB20A +50642C36DA00 +5083664D8C09 +50B77DA96DE2 +511E269A9BAE +51798AEAAE9E +51ED5833AB6D +525335E4CD34 +5261CDDA279E +526E55542A54 +529C16A720AB +52A230B1C50E +52AADA374811 +52D20D6E3E35 +534BB4A6984E +5352CCC3DCD2 +540B15E8019D +54AA2915E815 +558DB8891A90 +55A691710B48 +55D1E91B1D35 +55D95774E9A0 +563C6B96D59D +567032E13B54 +56741B108D22 +57029D991123 +5714E9D33034 +5734CD8A65DA +5785EE00049E +57B8B111491D +57CC9D0AA32B +57D7D4D746DA +583C936DCB4B +586B470A43B3 +5876E1D34183 +58B6AE62DB88 +58C35C8BC9AB +597E98000ED4 +59DB4DBB5D7A +5A150653E624 +5A211CE57C4B +5A6272CDBE9C +5ACB8043C10C +5B41CEBC2213 +5B59BCC4321E +5BA03479BB8C +5BC64C42281C +5C9B1A8E31CD +5C9BD0AC1DB1 +5D223E990AD8 +5D8C3A5C5761 +5DA57EACA38C +5E41DD5D1154 +5E6ABB51EC75 +5E7CC04C3A58 +5E810C48C8D8 +5E8943D9A836 +5ED616273468 +60100DD0E023 +6033A1C0E431 +6088A566CC60 +60B20ADA0471 +60B8411D876E +60C742D8D9C0 +6135433CC5EA +6153ADD80A15 +61718ED2C94D +6175241B035A +61780BCB0C57 +61B701698050 +61C4E56629A3 +61D59C284952 +61E57B490A55 +622E5E0812D7 +6251CE7E547A +62953A89B137 +62D6EAA06CD6 +630228659A47 +632931BE8EC7 +63539BB89DEE +636CB69BB10C +63783393E20D +639DB16995B7 +63AA2A5B076C +63B636458E94 +6443E64DCC4B +64695084C575 +6493D06D5710 +649B302A97C5 +64B8632B54D4 +654BACB21C3B +65A3D5823819 +65DEDABD1B34 +6608944EE186 +665B8B24C20D +6685D0BE19E0 +66933A9E7982 +674C7BB59A16 +675E35EE359E +67AA98E362C9 +67D47C1B6425 +67DE22850162 +67E8B986B2A7 +681EA28BA6CD +6828B52B6507 +6874E54471E8 +6879B1CA44A3 +68C00A810D41 +68C9E8AA5C3E +697A8ED07418 +69B5357A617A +6A7B3A7B6735 +6AA40421D23C +6AB676B4DB9D +6B00420BE41C +6B0B7B967871 +6B9D041136B4 +6BB1A14768A8 +6BCAE24D9700 +6C0458728774 +6C57CBD51995 +6C5E10B86CDE +6CA491A8C7B8 +6CBC25C1DA2E +6CD430D99958 +6CEC27647CC0 +6D4D29CEB9B5 +6D6E9A6B725D +6D801AC74572 +6D97408C6D60 +6DDE6E871C64 +6DEA848B6195 +6E05B5C44A54 +6E751666AE9A +6E7DBCDA05B3 +7004BA1763ED +7016ECD01559 +7076D48D5E49 +7091621EA016 +709311997549 +70984C14D3DB +70D73BE22CDD +70D9461C5E90 +712BC18422CB +712E6CAA74A4 +7164042BA89E +7175E14A4D62 +718B39561350 +718BDA352E28 +719B1418323E +71A8D54D82B3 +71DC30168C27 +7221E016597B +7234CC6BD65D +727A80DD5296 +72B393D6E8A9 +732C9BE4DDBA +736B4A835B2B +73EA81968900 +740AB5126199 +741A31054E6B +74498C1D4B3D +745276053CB6 +74684B0B4B1D +74772915E24C +74A24BE33BE2 +74A778236D5A +74AA58008A31 +74C27A96CB3A +754AD5773746 +756C15E54212 +759403A563D8 +759D2130312B +75A0E10D8C84 +75A807E46B96 +75E454785C6C +76078A25C088 +76140285B768 +763D835BD5ED +767C33468C72 +76962C07EC9E +76984E62CCE4 +769AE4646931 +76E5DA67A1EC +7708D5CAD58B +77383BAA4D90 +7789E646A556 +779A248E098C +77DB71037644 +77E0A57DD456 +7853D464E2A4 +78EA6EB04463 +7909427EC8B9 +7910A31ECD19 +79271963B6E8 +793D98517D33 +79B7A4C58DE0 +79B9148761B3 +7A2893B75AD1 +7A4C61A1B48D +7A7469B69C6A +7AA84B1A527D +7B00211CA416 +7B118EABC7BB +7B1D9A2E22AA +7B583D350740 +7B9D3A6BD061 +7C2DAC2CC775 +7C4CBBD2DDE1 +7CD52B5B8E77 +7D412100532B +7D46C149DAD9 +7D4CA630E229 +7DAC0E83D335 +7DC935E220A0 +7DCA66BACA13 +7E30778792D2 +7E43C3BAB3CB +7E475BA186E6 +7EE2A624851A +80CED5362B2C +80D2CC78E10B +80D62251E20C +816875D55ED1 +81950D0517AC +81B519418C3E +8211571B9D16 +823C7CC6E06A +826DD63B9032 +827303C574B5 +82C5ADED4B81 +82E344329D34 +83588E140165 +835D33B48113 +8384148AE52D +8394B57153D6 +83A0184757C0 +83D86835B48B +8502EE9A7E85 +852C2B72659D +8534A6CE0911 +85ABD94CD7A9 +85DA8099CD7E +85E0B6B26945 +864CA2A6BE93 +868A33A44447 +86EDEABCC357 +87DDD5A188EE +8830379B50B7 +883803A3360C +883DA78EC87D +88482A12C2C6 +888EBD3DB945 +88D026793359 +88DD4B7C5991 +8931DC3733D4 +894D8E2DCDEE +897B845C2680 +89B638BD909E +89D2C28BE578 +8A1869848D1A +8A39D09508C9 +8ACCC7290C8C +8AD8B41EC218 +8B028B7E6D60 +8B6A95C7D2E2 +8BA1226EBA21 +8BD586B21ABC +8C0EA504B635 +8CA939DC6DE4 +8CAE5D688443 +8CEC639E64DC +8DECE0DD29DE +8E0EC762E883 +8E958D8B8C52 +8EB64D710C88 +8ED4A17717D9 +8EE9D9C03A0D +9014E1430AEB +90965DEBC8B9 +90E56E616DDD +912CD8E04437 +912E33563E1B +918048032247 +919402EC39CB +91D28E2B126D +9216EEE5B677 +9232215296B2 +925A070E9096 +925A5521D48D +92CC200886A2 +932035869655 +937144459949 +93B260DBC70A +94552B863E37 +95327A0A3600 +954275CDD7E0 +957E6EE3EB55 +95B920CACC84 +96382E1C8E12 +964E8E5338BD +96706C8D6ECC +96759A0D5566 +96D5213C5DDB +97300764797A +973BDDBE7434 +974838AE17A0 +9752A6B316D5 +97926543783B +97EB373096CA +982D6054B83D +989D127BD496 +98A54AD58A43 +98A92128364C +98CD5AA2A4DB +98E8C543688E +99207A00AA4A +99243E754CB8 +9925893ABAC7 +9937553A965E +9976E6ADE0C9 +9982E3E6A4A0 +9984C1A3229E +99C487AB85EC +99E2A19C9673 +9A05EBE41D7D +9A138D1A5CB7 +9A179148B824 +9A6EC0A9ECB8 +9A720CBD7BB1 +9AB22BBDDD87 +9AC43B5A06D8 +9AD8150BE648 +9AD97423190D +9B4ADDDEB749 +9B7603341727 +9C45237377BE +9D090AE1A15E +9D59641E40A5 +9DA4528CEB8C +9DA728164176 +9DAC62A346B7 +9E0E9D983B9A +9E5271763D3D +9EE95586D024 +9EEE39E00CBB +A04671256EE2 +A091485B4B5D +A1B5577ED36E +A1EB280E3901 +A2789E1DD888 +A293A90AE72C +A309E3AEBDB9 +A3196E77B072 +A31E72DCC826 +A34DEA01690E +A36031D6ECB2 +A38044A3E18E +A421D7A04C4B +A424C686CA39 +A44590A779A5 +A47AD3895C63 +A5041E8B8E22 +A50DC0830AA5 +A52B8929D665 +A5BCBA6BE592 +A61D5137E6B3 +A6344C0418DC +A690A817B9D9 +A7E3B3459240 +A81E6D3C8E11 +A8C0BE436685 +A8DE205120A8 +A91E2BE6C308 +A9258D6B06B5 +A992B5E070C1 +AAC6E3205D48 +AB101546634E +AB6EE0761ACA +AB9BCA200547 +AC4BC5B2D3C0 +AC7A0B47B03E +AC88B26AC1D0 +ACAEB3456AD9 +ACB906631D8A +ACE07B45C0C5 +AD1992AE37CA +AD5586744A60 +AD674E4ADB79 +ADA093B06831 +AE7C3AE5334A +AE9EB8CAB2C3 +AEAE9E5CE65D +B002D1BDC29B +B0463E703098 +B063B209BB20 +B0788BE3BAA4 +B0C3B3299090 +B128298D9073 +B160677E7035 +B19D3D57176A +B1CCDB7999B9 +B231AA398B90 +B250E9590215 +B28BE0D819ED +B292C9554CBA +B2D8485C2460 +B31763D9D0DE +B328014DDD6A +B378C424C9E2 +B3D8C03C78E0 +B41D18E3B980 +B46824B972E9 +B50383A32302 +B509D631967C +B56CA847A7C3 +B56EC9A20D28 +B5B763215C82 +B6550EAC573A +B66060201705 +B6614EBEAAA2 +B6A18CBD4DA6 +B6ABB62E437E +B6C6558E58CA +B7009204D512 +B71D5B22B1C2 +B7392DD1E497 +B7709ED7CE60 +B7A26320A491 +B7A9DA22E9C6 +B7DEC863369D +B7E9A91174CB +B8178A34E2DC +B83092098A7D +B84C50E56DEC +B89BD135E935 +B8E87380D361 +B9485A9648C6 +B9ED829C22AE +BA227EE91818 +BA7BBD9683B1 +BA8224EA7A80 +BA84C974B356 +BAD293A45C8A +BB850C7E4934 +BBC1256810A4 +BC1CD369549E +BC5C76E5909C +BC66E9270049 +BC6AB08B03CC +BC74CA2C2B06 +BC7C64828C1D +BCCC3A719013 +BD06E96EB7D7 +BD196D0A74E0 +BE02790E84AC +BE1266314B9D +BE518C742B74 +BE5695316117 +BE5D8EBA120D +BE8286DA7D12 +BE9CE00EE4DD +C003962B3462 +C0067E095049 +C015A21E0146 +C03BC03AD437 +C06CE7D57A0D +C07EE1E10B56 +C0885A29251E +C198163ABECE +C1EB7337A035 +C225479C7064 +C2740E1665A8 +C27924128A00 +C2A701656B8B +C2C30D21C53E +C2CBB2ACD38D +C38D19A9C8D1 +C3B1BB7E7492 +C3BA2438A981 +C3CD74758DE2 +C4033B3BB1D7 +C404D280640E +C4467DE80B2D +C46A048C88DD +C52877867C05 +C56D005E258E +C56D052D5533 +C5BB2CCCB9C3 +C5C272694A1E +C6121BC4A29C +C65EEAE02433 +C661C4AE1DD1 +C76C94B495CA +C7BD49777A79 +C7CD131E9B60 +C7E35D6294BA +C8E173DB04CC +C95855AE08E8 +C98147E69033 +C99A004E6133 +C9E893C4090B +CA119C79A197 +CA309D2CBC41 +CA4BAA390BC4 +CA92DD257E21 +CA968EBEB9C7 +CADED0C50AC4 +CB18774EA550 +CB1999D19E10 +CB75C1BAE669 +CC2517AB2346 +CC2AC1AD29CA +CD11359C7A90 +CD14C8553CB9 +CD333295BBE2 +CD3DB8C27E5C +CDA811AD5055 +CDABDCA23986 +CDCA8BD7B002 +CE0456AB0DCE +CE58AE1C51E9 +CE76E8A600DC +CE95875316C8 +CEB105E65289 +CEB651752D4C +CEE02D97E5BD +D023DB35ED05 +D0BE546CC06B +D0CE7EB0D379 +D10329D366C8 +D15C004DBC8D +D16E6B668254 +D1CEEC977644 +D1DC0E1CC09E +D2550925679B +D28B2D42DE1A +D2926519AC09 +D313116A45B4 +D3DC10453857 +D431C8C73BDC +D4C67846791C +D5629384CE7D +D5ABE7180600 +D62A4A0E57C2 +D660CE9E3080 +D66AE9282140 +D6A91C14AC47 +D6E23B4E75C6 +D726C4979654 +D76DE12943B4 +D7A405AD9E4E +D7BD3AE48E93 +D7D49700BBCC +D7E8A5089E7A +D84C81EE910D +D8545199A949 +D86243C1380E +D88A12EB3622 +D89B5EA419C1 +D8A3690B0115 +D94646A4C65B +D982B4846A96 +DA303BADB013 +DAD9A48A8C33 +DAEB5D63920B +DB01A99DD94C +DB22BB7D6818 +DB37160CBB4B +DB7E3687E450 +DC7697E37A9B +DCC44C4E9269 +DCCE477E785E +DD68DE9CDA5A +DE1B08C6D94B +DE41BBD7E68D +DE6E04AE4475 +DE8CD4277A9E +DEA8098D6E51 +DEB2BEE8858A +DEB550958AD9 +E045E6309471 +E0E21213C611 +E0E457054B62 +E1097C69DA4A +E1EA831EA514 +E20716902884 +E2C9CB14C06C +E33B66EA2705 +E34C5B12BABA +E38A1C654E82 +E3905BA54194 +E3E3919444CA +E4450EC1010C +E49A03306224 +E5100AC4C6C3 +E5124DB665A6 +E5491B5E3DD6 +E5BE9C989A29 +E5C3A9A27D3E +E65111EB1E40 +E65792427D4C +E7004C5EA94A +E705087DECBB +E7CB93E68155 +E81512343BAD +E8428C8B0740 +E859EBC22318 +E87267A508DB +E886AE7D1BE0 +E8B008239600 +E8C4B4A4E482 +E8D53410B736 +E902964DA28D +E9203D5BD2DA +E9526CACA8B2 +E9C11D763BEC +EA3BDAA4E498 +EA61AC8B4969 +EA8E8ADC26B9 +EB5588EAE5E8 +EBA964C07075 +EC71B679D3AA +ECB4019ADD97 +ED14D0A14B0C +ED296C79266C +EDBA3C943EA8 +EDC7CEBD4000 +EDE2747DA6C3 +EE3029556CEB +EE49610E6121 +EEB704D69BCA +EED69A391464 diff --git a/client/dictionaries/mfc_keys_mrzd_sorted.dic b/client/dictionaries/mfc_keys_mrzd_sorted.dic new file mode 100644 index 000000000..f2ebafc10 --- /dev/null +++ b/client/dictionaries/mfc_keys_mrzd_sorted.dic @@ -0,0 +1,57 @@ +010203040506 +013940233313 +022FE48B3072 +123456789ABC +123456ABCDEF +17505586EF02 +1795902DBAF9 +1A2B3C4D5E6F +1A982C7E459A +200306202033 +2011092119F1 +2012053082AD +37D4DCA92451 +40E5EA1EFC00 +435330666666 +46868F6D5677 +474249437569 +4D3A99C351DD +533CB6C723F6 +5554AAA96321 +587EE5F9350F +5A1B85FCE20A +5D293AFC8D7E +64A2EE93B12B +64E2283FCF5E +714C5C886E97 +833FBD3CFE51 +83BAB5ACAD62 +872B71F9D15A +8F9B229047AC +8FD0A4F256E9 +9AEDF9931EC1 +9B1DD7C030A1 +A0478CC39091 +A0A1A2A3A4A5 +A2B2C9D187FB +A4EF6C3BB692 +AABBCC660429 +AABBCCDDEEFF +ABCDEF123456 +B0699AD03D17 +B0B1B2B3B4B5 +BA28CFD15EE8 +BCFE01BCFE01 +C0C1C2C3C4C5 +CFC738403AB0 +D0D1D2D3D4D5 +D3F7D3F7D3F7 +DB5181C92CBE +DFED39FFBB76 +E1DD284379D4 +E96246531342 +ED3A7EFBFF56 +F83466888612 +F89C86B2A961 +FFFFAE82366C +FFFFD06F83E3 diff --git a/client/default_ultralight_keys.dic b/client/dictionaries/mfulc_default_keys.dic similarity index 63% rename from client/default_ultralight_keys.dic rename to client/dictionaries/mfulc_default_keys.dic index 3c0c01acd..51b4b9365 100644 --- a/client/default_ultralight_keys.dic +++ b/client/dictionaries/mfulc_default_keys.dic @@ -2,4 +2,5 @@ # Mifare Ultralight Default Keys # -- iceman fork version -- # -- contribute to this list, sharing is caring -- -425245414B4D454946594F5543414E21 -- Sample Key (BREAKMEIFYOUCAN!) +# +425245414B4D454946594F5543414E21 # Sample Key (BREAKMEIFYOUCAN!) diff --git a/client/dictionaries/mrzd_sort_keys.dic b/client/dictionaries/mrzd_sort_keys.dic deleted file mode 100644 index 025f1b995..000000000 --- a/client/dictionaries/mrzd_sort_keys.dic +++ /dev/null @@ -1,57 +0,0 @@ -010203040506, -013940233313, -022FE48B3072, -123456789ABC, -123456ABCDEF, -17505586EF02, -1795902DBAF9, -1A2B3C4D5E6F, -1A982C7E459A, -200306202033, -2011092119F1, -2012053082AD, -37D4DCA92451, -40E5EA1EFC00, -435330666666, -46868F6D5677, -474249437569, -4D3A99C351DD, -533CB6C723F6, -5554AAA96321, -587EE5F9350F, -5A1B85FCE20A, -5D293AFC8D7E, -64A2EE93B12B, -64E2283FCF5E, -714C5C886E97, -833FBD3CFE51, -83BAB5ACAD62, -872B71F9D15A, -8F9B229047AC, -8FD0A4F256E9, -9AEDF9931EC1, -9B1DD7C030A1, -A0478CC39091, -A0A1A2A3A4A5, -A2B2C9D187FB, -A4EF6C3BB692, -AABBCC660429, -AABBCCDDEEFF, -ABCDEF123456, -B0699AD03D17, -B0B1B2B3B4B5, -BA28CFD15EE8, -BCFE01BCFE01, -C0C1C2C3C4C5, -CFC738403AB0, -D0D1D2D3D4D5, -D3F7D3F7D3F7, -DB5181C92CBE, -DFED39FFBB76, -E1DD284379D4, -E96246531342, -ED3A7EFBFF56, -F83466888612, -F89C86B2A961, -FFFFAE82366C, -FFFFD06F83E3, diff --git a/client/dictionaries/t55xx_default_pwds.dic b/client/dictionaries/t55xx_default_pwds.dic new file mode 100644 index 000000000..511be26d1 --- /dev/null +++ b/client/dictionaries/t55xx_default_pwds.dic @@ -0,0 +1,123 @@ +# known cloners +# ref. http://www.proxmark.org/forum/viewtopic.php?id=2022 +51243648 +000D8787 +19920427 +65857569 //chinese "handheld RFID writer" blue cloner from circa 2013 (also sold by xfpga.com) +# ref. http://kazus.ru/forums/showpost.php?p=1045937&postcount=77 +05D73B9F +# ref. http://www.proxmark.org/forum/viewtopic.php?= +89A69E60 +# ref lock +314159E0 +# ref. http://www.proxmark.org/forum/viewtopic.php?pid=28115#p28115 +AA55BBBB +# ref. http://www.proxmark.org/forum/viewtopic.php?pid=33376#p33376 +A5B4C3D2 +# ref. http://www.proxmark.org/forum/viewtopic.php?pid=30379#p30379 +1C0B5848 +# ref. http://www.proxmark.org/forum/viewtopic.php?pid=35075#p35075 +00434343 +44B44CAE +88661858 +# paxton bullit? +575F4F4B +# +50520901 +# Default pwd, simple: +00000000 +11111111 +22222222 +33333333 +44444444 +55555555 +66666666 +77777777 +88888888 +99999999 +AAAAAAAA +BBBBBBBB +CCCCCCCC +DDDDDDDD +EEEEEEEE +FFFFFFFF +a0a1a2a3 +b0b1b2b3 +aabbccdd +bbccddee +ccddeeff +50415353 +00000001 +00000002 +0000000a +0000000b +01020304 +02030405 +03040506 +04050607 +05060708 +06070809 +0708090A +08090A0B +090A0B0C +0A0B0C0D +0B0C0D0E +0C0D0E0F +01234567 +12345678 +10000000 +20000000 +30000000 +40000000 +50000000 +60000000 +70000000 +80000000 +90000000 +A0000000 +B0000000 +C0000000 +D0000000 +E0000000 +F0000000 +10101010 +01010101 +11223344 +22334455 +33445566 +44556677 +55667788 +66778899 +778899AA +8899AABB +99AABBCC +AABBCCDD +BBCCDDEE +CCDDEEFF +0CB7E7FC # rfidler? +FABADA11 # china? +# 20 most common len==8 +87654321 +12341234 +69696969 +12121212 +12344321 +1234ABCD +11112222 +13131313 +10041004 +# +31415926 # pii +abcd1234 +20002000 +19721972 +aa55aa55 # amiboo +55aa55aa # rev amiboo +4f271149 # seeds ul-ev1 +07d7bb0b # seeds ul-ev1 +9636ef8f # seeds ul-ev1 +b5f44686 # seeds ul-ev1 +9E3779B9 # TEA +C6EF3720 # TEA +7854794A # xbox tea constant :) +F1EA5EED # burtle diff --git a/client/emv/apduinfo.c b/client/emv/apduinfo.c index 48e97622b..cf43615cb 100644 --- a/client/emv/apduinfo.c +++ b/client/emv/apduinfo.c @@ -10,6 +10,13 @@ #include "apduinfo.h" +#include // memmove +#include + +#include "ui.h" // Print... +#include "util.h" +#include "commonutil.h" // ARRAYLEN + const APDUCode APDUCodeTable[] = { // ID Type Description {"XXXX", APDUCODE_TYPE_NONE, ""}, // blank string @@ -257,7 +264,6 @@ const APDUCode APDUCodeTable[] = { {"9FXX", APDUCODE_TYPE_NONE, "Command successfully executed; 'xx' bytes of data are available and can be requested using GET RESPONSE."}, {"9XXX", APDUCODE_TYPE_NONE, "Application related status, (ISO 7816-3)"} }; -const size_t APDUCodeTableLen = sizeof(APDUCodeTable) / sizeof(APDUCode); static int CodeCmp(const char *code1, const char *code2) { int xsymb = 0; @@ -279,12 +285,12 @@ static int CodeCmp(const char *code1, const char *code2) { const APDUCode *GetAPDUCode(uint8_t sw1, uint8_t sw2) { char buf[6] = {0}; - int mineq = APDUCodeTableLen; + int mineq = ARRAYLEN(APDUCodeTable); int mineqindx = 0; sprintf(buf, "%02X%02X", sw1, sw2); - for (int i = 0; i < APDUCodeTableLen; i++) { + for (int i = 0; i < ARRAYLEN(APDUCodeTable); i++) { int res = CodeCmp(APDUCodeTable[i].ID, buf); // equal @@ -300,7 +306,7 @@ const APDUCode *GetAPDUCode(uint8_t sw1, uint8_t sw2) { } // if we have not equal, but with some 'X' - if (mineqindx < APDUCodeTableLen) { + if (mineqindx < ARRAYLEN(APDUCodeTable)) { return &APDUCodeTable[mineqindx]; } diff --git a/client/emv/apduinfo.h b/client/emv/apduinfo.h index 25d062dcf..590c72885 100644 --- a/client/emv/apduinfo.h +++ b/client/emv/apduinfo.h @@ -11,13 +11,7 @@ #ifndef APDUINFO_H__ #define APDUINFO_H__ -#include -#include -#include -#include -#include - -#include "util.h" +#include "common.h" #define APDUCODE_TYPE_NONE 0 #define APDUCODE_TYPE_INFO 1 diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 0cf177620..348840cb3 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -8,14 +8,24 @@ // EMV commands //----------------------------------------------------------------------------- -#include -#include "mifare.h" #include "cmdemv.h" + +#include + +#include "comms.h" // DropField +#include "cmdsmartcard.h" // smart_select +#include "cmdtrace.h" #include "emvjson.h" -#include "emv_pki.h" #include "test/cryptotest.h" #include "cliparser/cliparser.h" -#include +#include "cmdparser.h" +#include "proxmark3.h" +#include "emv_roca.h" +#include "emvcore.h" +#include "cmdhf14a.h" +#include "dol.h" +#include "ui.h" +#include "emv_tags.h" static int CmdHelp(const char *Cmd); @@ -222,7 +232,7 @@ static int CmdEMVGPO(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_lit0("kK", "keep", "keep field ON for next command"), - arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for PDOLdata making from PDOL and parameters"), + arg_lit0("pP", "params", "load parameters from `emv_defparams.json` file for PDOLdata making from PDOL and parameters"), arg_lit0("mM", "make", "make PDOLdata from PDOL (tag 9F38) and parameters (by default uses default parameters)"), arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"), @@ -388,7 +398,7 @@ static int CmdEMVAC(const char *Cmd) { arg_lit0("kK", "keep", "keep field ON for next command"), arg_lit0("cC", "cda", "executes CDA transaction. Needs to get SDAD in results."), arg_str0("dD", "decision", "", "Terminal decision. aac - declined, tc - approved, arqc - online authorisation requested"), - arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for CDOLdata making from CDOL and parameters"), + arg_lit0("pP", "params", "load parameters from `emv_defparams.json` file for CDOLdata making from CDOL and parameters"), arg_lit0("mM", "make", "make CDOLdata from CDOL (tag 8C and 8D) and parameters (by default uses default parameters)"), arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"), @@ -554,7 +564,7 @@ static int CmdEMVInternalAuthenticate(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_lit0("kK", "keep", "keep field ON for next command"), - arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for DDOLdata making from DDOL and parameters"), + arg_lit0("pP", "params", "load parameters from `emv_defparams.json` file for DDOLdata making from DDOL and parameters"), arg_lit0("mM", "make", "make DDOLdata from DDOL (tag 9F49) and parameters (by default uses default parameters)"), arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"), @@ -775,7 +785,7 @@ static int CmdEMVExec(const char *Cmd) { arg_lit0("sS", "select", "activate field and select card."), arg_lit0("aA", "apdu", "show APDU reqests and responses."), arg_lit0("tT", "tlv", "TLV decode results."), - arg_lit0("jJ", "jload", "Load transaction parameters from `emv/defparams.json` file."), + arg_lit0("jJ", "jload", "Load transaction parameters from `emv_defparams.json` file."), arg_lit0("fF", "forceaid", "Force search AID. Search AID instead of execute PPSE."), arg_rem("By default:", "Transaction type - MSD"), arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip."), @@ -1366,7 +1376,7 @@ static int CmdEMVScan(const char *Cmd) { arg_lit0("aA", "apdu", "show APDU reqests and responses."), arg_lit0("tT", "tlv", "TLV decode results."), arg_lit0("eE", "extract", "Extract TLV elements and fill Application Data"), - arg_lit0("jJ", "jload", "Load transaction parameters from `emv/defparams.json` file."), + arg_lit0("jJ", "jload", "Load transaction parameters from `emv_defparams.json` file."), arg_rem("By default:", "Transaction type - MSD"), arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip."), arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."), diff --git a/client/emv/cmdemv.h b/client/emv/cmdemv.h index 8cdcdf990..ca1f9fc5a 100644 --- a/client/emv/cmdemv.h +++ b/client/emv/cmdemv.h @@ -11,21 +11,7 @@ #ifndef CMDEMV_H__ #define CMDEMV_H__ -#include -#include -#include -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "cmdparser.h" #include "common.h" -#include "util.h" -#include "util_posix.h" -#include "cmdmain.h" -#include "emvcore.h" -#include "apduinfo.h" -#include "emv_roca.h" int CmdEMV(const char *Cmd); diff --git a/client/emv/crypto.c b/client/emv/crypto.c index ccf668477..f7fc60c80 100644 --- a/client/emv/crypto.c +++ b/client/emv/crypto.c @@ -20,8 +20,6 @@ #include "crypto.h" #include "crypto_backend.h" -#include - static struct crypto_backend *crypto_backend; static bool crypto_init(void) { diff --git a/client/emv/crypto.h b/client/emv/crypto.h index 4eacca0b8..32252b4cc 100644 --- a/client/emv/crypto.h +++ b/client/emv/crypto.h @@ -16,8 +16,7 @@ #ifndef CRYPTO_H #define CRYPTO_H -#include -#include +#include "common.h" enum crypto_algo_hash { HASH_INVALID, diff --git a/client/emv/crypto_backend.h b/client/emv/crypto_backend.h index 1113cf341..3a38cc772 100644 --- a/client/emv/crypto_backend.h +++ b/client/emv/crypto_backend.h @@ -18,8 +18,7 @@ #include "crypto.h" -#include -#include +#include // va_list struct crypto_hash { enum crypto_algo_hash algo; diff --git a/client/emv/crypto_polarssl.c b/client/emv/crypto_polarssl.c index 13f093aa4..b87dd9ee0 100644 --- a/client/emv/crypto_polarssl.c +++ b/client/emv/crypto_polarssl.c @@ -18,11 +18,8 @@ #include #endif -#include "crypto.h" #include "crypto_backend.h" -#include -#include #include #include diff --git a/client/emv/dol.h b/client/emv/dol.h index 496ae66f5..8e65f679d 100644 --- a/client/emv/dol.h +++ b/client/emv/dol.h @@ -17,7 +17,6 @@ #define DOL_H #include "emv/tlv.h" -#include struct tlv *dol_process(const struct tlv *tlv, const struct tlvdb *tlvdb, tlv_tag_t tag); struct tlvdb *dol_parse(const struct tlv *tlv, const unsigned char *data, size_t data_len); diff --git a/client/emv/dump.h b/client/emv/dump.h index fd6e16018..5a71b9519 100644 --- a/client/emv/dump.h +++ b/client/emv/dump.h @@ -16,9 +16,9 @@ #ifndef DUMP_H #define DUMP_H -#include -#include -#include +#include "common.h" + +#include // FILE void dump_buffer_simple(const unsigned char *ptr, size_t len, FILE *f); void dump_buffer(const unsigned char *ptr, size_t len, FILE *f, int level); diff --git a/client/emv/emv_pk.c b/client/emv/emv_pk.c index b03567440..8465a6e95 100644 --- a/client/emv/emv_pk.c +++ b/client/emv/emv_pk.c @@ -19,16 +19,18 @@ /* For asprintf */ #define _GNU_SOURCE -#include #include "emv_pk.h" -#include "crypto.h" -#include "proxmark3.h" -#include "util.h" -#include + +#include #include #include -#include + +#include "ui.h" +#include "crypto.h" +#include "proxmark3.h" +#include "fileutils.h" +#include "pm3_cmd.h" #define BCD(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \ -1) @@ -483,13 +485,12 @@ struct emv_pk *emv_pk_get_ca_pk(const unsigned char *rid, unsigned char idx) { } } */ - const char *relfname = "emv/capk.txt"; - - char fname[strlen(get_my_executable_directory()) + strlen(relfname) + 1]; - strcpy(fname, get_my_executable_directory()); - strcat(fname, relfname); - - pk = emv_pk_get_ca_pk_from_file(fname, rid, idx); + char *path; + if (searchFile(&path, RESOURCES_SUBDIR, "capk", ".txt", false) != PM3_SUCCESS) { + return NULL; + } + pk = emv_pk_get_ca_pk_from_file(path, rid, idx); + free(path); if (!pk) return NULL; diff --git a/client/emv/emv_pk.h b/client/emv/emv_pk.h index ed8000dc0..dfc249710 100644 --- a/client/emv/emv_pk.h +++ b/client/emv/emv_pk.h @@ -16,8 +16,7 @@ #ifndef EMV_PK_H #define EMV_PK_H -#include -#include +#include "common.h" struct emv_pk { unsigned char rid[5]; diff --git a/client/emv/emv_pki.c b/client/emv/emv_pki.c index cb2486bb4..bbdb321b3 100644 --- a/client/emv/emv_pki.c +++ b/client/emv/emv_pki.c @@ -18,15 +18,15 @@ #endif #include "emv_pki.h" -#include "crypto.h" -#include "dump.h" -#include "util.h" -#include #include #include #include +#include "crypto.h" +#include "dump.h" +#include "util.h" + static bool strictExecution = true; void PKISetStrictExecution(bool se) { strictExecution = se; diff --git a/client/emv/emv_pki.h b/client/emv/emv_pki.h index 91ff60166..05506f02c 100644 --- a/client/emv/emv_pki.h +++ b/client/emv/emv_pki.h @@ -19,8 +19,6 @@ #include "emv_pk.h" #include "tlv.h" -#include - void PKISetStrictExecution(bool se); unsigned char *emv_pki_sdatl_fill(const struct tlvdb *db, size_t *sdatl_len); diff --git a/client/emv/emv_pki_priv.c b/client/emv/emv_pki_priv.c index 5256b4e37..f10c5352b 100644 --- a/client/emv/emv_pki_priv.c +++ b/client/emv/emv_pki_priv.c @@ -18,7 +18,6 @@ #endif #include "emv_pki_priv.h" -#include "crypto.h" #include #include diff --git a/client/emv/emv_pki_priv.h b/client/emv/emv_pki_priv.h index 8c8d1a813..b85b1176b 100644 --- a/client/emv/emv_pki_priv.h +++ b/client/emv/emv_pki_priv.h @@ -16,12 +16,12 @@ #ifndef EMV_PKI_PRIV_H #define EMV_PKI_PRIV_H +#include "common.h" + #include "crypto.h" #include "emv_pk.h" #include "tlv.h" -#include - struct emv_pk *emv_pki_make_ca(const struct crypto_pk *cp, const unsigned char *rid, unsigned char index, unsigned int expire, enum crypto_algo_hash hash_algo); diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index a3a8cb7fe..521120b05 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -23,6 +23,9 @@ #include "emv_roca.h" +#include "ui.h" // Print... +#include "mbedtls/bignum.h" + static uint8_t g_primes[ROCA_PRINTS_LENGTH] = { 11, 13, 17, 19, 37, 53, 61, 71, 73, 79, 97, 103, 107, 109, 127, 151, 157 }; diff --git a/client/emv/emv_roca.h b/client/emv/emv_roca.h index 6663ce710..8c8ea86e4 100644 --- a/client/emv/emv_roca.h +++ b/client/emv/emv_roca.h @@ -24,10 +24,7 @@ #ifndef EMV_ROCA_H__ #define EMV_ROCA_H__ -#include -#include -#include "mbedtls/bignum.h" -#include "util.h" +#include "common.h" #define ROCA_PRINTS_LENGTH 17 diff --git a/client/emv/emv_tags.c b/client/emv/emv_tags.c index 9ef049221..296dcdf82 100644 --- a/client/emv/emv_tags.c +++ b/client/emv/emv_tags.c @@ -17,12 +17,13 @@ #include #endif -#include "tlv.h" #include "emv_tags.h" #include #include +#include "commonutil.h" + #ifndef PRINT_INDENT # define PRINT_INDENT(level) {for (int myi = 0; myi < (level); myi++) fprintf(f, " ");} #endif @@ -400,11 +401,11 @@ static const struct emv_tag emv_tags[] = { { 0xdf811b, "Kernel Configuration", EMV_TAG_GENERIC, NULL }, { 0xdf811c, "Max Lifetime of Torn Transaction Log Record", EMV_TAG_GENERIC, NULL }, { 0xdf811d, "Max Number of Torn Transaction Log Records", EMV_TAG_GENERIC, NULL }, - { 0xdf811e, "Mag-stripe CVM Capability – CVM Required", EMV_TAG_GENERIC, NULL }, + { 0xdf811e, "Mag-stripe CVM Capability - CVM Required", EMV_TAG_GENERIC, NULL }, { 0xdf811f, "Security Capability", EMV_TAG_GENERIC, NULL }, - { 0xdf8120, "Terminal Action Code – Default", EMV_TAG_GENERIC, NULL }, - { 0xdf8121, "Terminal Action Code – Denial", EMV_TAG_GENERIC, NULL }, - { 0xdf8122, "Terminal Action Code – Online", EMV_TAG_GENERIC, NULL }, + { 0xdf8120, "Terminal Action Code - Default", EMV_TAG_GENERIC, NULL }, + { 0xdf8121, "Terminal Action Code - Denial", EMV_TAG_GENERIC, NULL }, + { 0xdf8122, "Terminal Action Code - Online", EMV_TAG_GENERIC, NULL }, { 0xdf8123, "Reader Contactless Floor Limit", EMV_TAG_GENERIC, NULL }, { 0xdf8124, "Reader Contactless Transaction Limit (No On-device CVM)", EMV_TAG_GENERIC, NULL }, { 0xdf8125, "Reader Contactless Transaction Limit (On-device CVM)", EMV_TAG_GENERIC, NULL }, @@ -414,7 +415,7 @@ static const struct emv_tag emv_tags[] = { { 0xdf8129, "Outcome Parameter Set", EMV_TAG_GENERIC, NULL }, { 0xdf812a, "DD Card (Track1)", EMV_TAG_GENERIC, NULL }, { 0xdf812b, "DD Card (Track2)", EMV_TAG_GENERIC, NULL }, - { 0xdf812c, "Mag-stripe CVM Capability – No CVM Required", EMV_TAG_GENERIC, NULL }, + { 0xdf812c, "Mag-stripe CVM Capability - No CVM Required", EMV_TAG_GENERIC, NULL }, { 0xdf812d, "Message Hold Time", EMV_TAG_GENERIC, NULL }, { 0xff8101, "Torn Record", EMV_TAG_GENERIC, NULL }, @@ -437,7 +438,7 @@ static int emv_tlv_compare(const void *a, const void *b) { } static const struct emv_tag *emv_get_tag(const struct tlv *tlv) { - struct emv_tag *tag = bsearch(tlv, emv_tags, sizeof(emv_tags) / sizeof(emv_tags[0]), + struct emv_tag *tag = bsearch(tlv, emv_tags, ARRAYLEN(emv_tags), sizeof(emv_tags[0]), emv_tlv_compare); return tag ? tag : &emv_tags[0]; diff --git a/client/emv/emv_tags.h b/client/emv/emv_tags.h index 51905e75e..235048b20 100644 --- a/client/emv/emv_tags.h +++ b/client/emv/emv_tags.h @@ -17,7 +17,7 @@ #define TAGS_H #include "tlv.h" -#include +#include // FILE // AC # define EMVAC_AC_MASK 0xC0 diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index c814eb11e..09dc7883e 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -9,6 +9,18 @@ //----------------------------------------------------------------------------- #include "emvcore.h" + +#include + +#include "commonutil.h" // ARRAYLEN +#include "comms.h" // DropField +#include "cmdparser.h" +#include "cmdsmartcard.h" // ExchangeAPDUSC +#include "ui.h" +#include "cmdhf14a.h" +#include "dol.h" +#include "dump.h" +#include "emv_tags.h" #include "emvjson.h" #include "util_posix.h" @@ -18,7 +30,6 @@ static const char *PSElist [] = { "325041592E5359532E4444463031", // 2PAY.SYS.DDF01 - Visa Proximity Payment System Environment - PPSE "315041592E5359532E4444463031" // 1PAY.SYS.DDF01 - Visa Payment System Environment - PSE }; -//static const size_t PSElistLen = sizeof(PSElist)/sizeof(char*); const char *TransactionTypeStr[] = { "MSD", @@ -119,7 +130,6 @@ static const TAIDList AIDlist [] = { { CV_OTHER, "D5780000021010" }, // Bankaxept Norway Bankaxept Norwegian domestic debit card { CV_OTHER, "F0000000030001" }, // BRADESCO - Brazilian Bank Banco Bradesco }; -static const size_t AIDlistLen = sizeof(AIDlist) / sizeof(TAIDList); static bool APDULogging = false; void SetAPDULogging(bool logging) { @@ -133,7 +143,7 @@ enum CardPSVendor GetCardPSVendor(uint8_t *AID, size_t AIDlen) { hex_to_buffer((uint8_t *)buf, AID, AIDlen, sizeof(buf) - 1, 0, 0, true); - for (int i = 0; i < AIDlistLen; i ++) { + for (int i = 0; i < ARRAYLEN(AIDlist); i ++) { if (strncmp(AIDlist[i].aid, buf, strlen(AIDlist[i].aid)) == 0) { return AIDlist[i].vendor; } @@ -530,7 +540,7 @@ int EMVSearch(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, int res = 0; int retrycnt = 0; - for (int i = 0; i < AIDlistLen; i ++) { + for (int i = 0; i < ARRAYLEN(AIDlist); i ++) { param_gethex_to_eol(AIDlist[i].aid, 0, aidbuf, sizeof(aidbuf), &aidlen); res = EMVSelect(channel, (i == 0) ? ActivateField : false, true, aidbuf, aidlen, data, sizeof(data), &datalen, &sw, tlv); // retry if error and not returned sw error diff --git a/client/emv/emvcore.h b/client/emv/emvcore.h index 3faae283d..a520a2d5f 100644 --- a/client/emv/emvcore.h +++ b/client/emv/emvcore.h @@ -11,22 +11,12 @@ #ifndef EMVCORE_H__ #define EMVCORE_H__ -#include -#include -#include -#include -#include -#include -#include "util.h" #include "common.h" -#include "ui.h" -#include "cmdhf14a.h" + +#include +#include + #include "apduinfo.h" -#include "tlv.h" -#include "dol.h" -#include "dump.h" -#include "emv_tags.h" -#include "emv_pk.h" #include "emv_pki.h" #define APDU_RES_LEN 260 diff --git a/client/emv/emvjson.c b/client/emv/emvjson.c index 54bd8846c..785b6b8e7 100644 --- a/client/emv/emvjson.c +++ b/client/emv/emvjson.c @@ -9,14 +9,16 @@ //----------------------------------------------------------------------------- #include "emvjson.h" -#include -#include -#include -#include + #include + +#include "commonutil.h" // ARRAYLEN #include "ui.h" +#include "util.h" #include "proxmark3.h" #include "emv_tags.h" +#include "fileutils.h" +#include "pm3_cmd.h" static const ApplicationDataElm ApplicationData[] = { {0x82, "AIP"}, @@ -57,10 +59,9 @@ static const ApplicationDataElm ApplicationData[] = { {0x00, "end..."} }; -int ApplicationDataLen = sizeof(ApplicationData) / sizeof(ApplicationDataElm); const char *GetApplicationDataName(tlv_tag_t tag) { - for (int i = 0; i < ApplicationDataLen; i++) + for (int i = 0; i < ARRAYLEN(ApplicationData); i++) if (ApplicationData[i].Tag == tag) return ApplicationData[i].Name; @@ -304,13 +305,12 @@ bool ParamLoadFromJson(struct tlvdb *tlv) { return false; } - // current path + file name - const char *relfname = "emv/defparams.json"; - char fname[strlen(get_my_executable_directory()) + strlen(relfname) + 1]; - strcpy(fname, get_my_executable_directory()); - strcat(fname, relfname); - - root = json_load_file(fname, 0, &error); + char *path; + if (searchFile(&path, RESOURCES_SUBDIR, "emv_defparams", ".json", false) != PM3_SUCCESS) { + return false; + } + root = json_load_file(path, 0, &error); + free(path); if (!root) { PrintAndLogEx(ERR, "Load params: json error on line " _YELLOW_("%d") ": %s", error.line, error.text); return false; diff --git a/client/emv/emvjson.h b/client/emv/emvjson.h index 6bcf8243d..54d97ada8 100644 --- a/client/emv/emvjson.h +++ b/client/emv/emvjson.h @@ -10,6 +10,8 @@ #ifndef EMVJSON_H__ #define EMVJSON_H__ +#include "common.h" + #include #include "tlv.h" diff --git a/client/emv/test/crypto_test.c b/client/emv/test/crypto_test.c index 4220515df..cdf22a995 100644 --- a/client/emv/test/crypto_test.c +++ b/client/emv/test/crypto_test.c @@ -17,6 +17,8 @@ #include #endif +#include "commonutil.h" // ARRAYLEN + #include "../crypto.h" #include "../dump.h" #include "util_posix.h" @@ -312,7 +314,7 @@ int exec_crypto_test(bool verbose) { } fprintf(stdout, "Crypto raw test: passed\n\n"); - for (i = 0; i < sizeof(keylengths) / sizeof(keylengths[0]); i++) { + for (i = 0; i < ARRAYLEN(keylengths); i++) { unsigned int kl = keylengths[i]; ret = test_genkey(kl, message, kl / 8, verbose); if (ret) { diff --git a/client/emv/test/cryptotest.c b/client/emv/test/cryptotest.c index 29c4fdaa3..937ff7e8e 100644 --- a/client/emv/test/cryptotest.c +++ b/client/emv/test/cryptotest.c @@ -58,7 +58,13 @@ int ExecuteCryptoTests(bool verbose) { res = mbedtls_entropy_self_test(verbose); if (res) TestFail = true; - res = mbedtls_timing_self_test(verbose); + // retry for CI (when resources too low) + for (int i = 0; i < 3; i++) { + res = mbedtls_timing_self_test(verbose); + if (!res) + break; + PrintAndLogEx(WARNING, "Repeat timing test %d", i + 1); + } if (res) TestFail = true; res = mbedtls_ctr_drbg_self_test(verbose); diff --git a/client/emv/tlv.c b/client/emv/tlv.c index f3961c7a6..6e840f928 100644 --- a/client/emv/tlv.c +++ b/client/emv/tlv.c @@ -22,8 +22,6 @@ #include "tlv.h" #include -#include -#include #include #define TLV_TAG_CLASS_MASK 0xc0 diff --git a/client/emv/tlv.h b/client/emv/tlv.h index 053b31362..06a836876 100644 --- a/client/emv/tlv.h +++ b/client/emv/tlv.h @@ -18,9 +18,7 @@ #ifndef TLV_H #define TLV_H -#include -#include -#include +#include "common.h" typedef uint32_t tlv_tag_t; diff --git a/client/fido/additional_ca.c b/client/fido/additional_ca.c index 550847e10..7ea103004 100644 --- a/client/fido/additional_ca.c +++ b/client/fido/additional_ca.c @@ -10,7 +10,6 @@ // #include "additional_ca.h" -#include "mbedtls/certs.h" #define GLOBALSIGN_CA \ "-----BEGIN CERTIFICATE-----\r\n" \ @@ -37,6 +36,7 @@ // Name: Yubico U2F Root CA Serial 457200631 // Issued: 2014-08-01 +// https://github.com/Yubico/developers.yubico.com/tree/master/static/U2F #define YUBICO_CA \ "-----BEGIN CERTIFICATE-----\r\n" \ "MIIDHjCCAgagAwIBAgIEG0BT9zANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZ\r\n" \ diff --git a/client/fido/additional_ca.h b/client/fido/additional_ca.h index d0f642e46..689e5f059 100644 --- a/client/fido/additional_ca.h +++ b/client/fido/additional_ca.h @@ -12,7 +12,7 @@ #ifndef __ADDITIONAL_CA_H__ #define __ADDITIONAL_CA_H__ -#include +#include "common.h" // Concatenation of all CA certificates in PEM format if available extern const char additional_ca_pem[]; diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index 7cb7fc456..72cccf429 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -11,7 +11,9 @@ // #include "cbortools.h" -#include + +#include + #include "emv/emvjson.h" #include "util.h" #include "fidocore.h" diff --git a/client/fido/cbortools.h b/client/fido/cbortools.h index 99b3536c1..96c39ca3b 100644 --- a/client/fido/cbortools.h +++ b/client/fido/cbortools.h @@ -13,8 +13,7 @@ #ifndef __CBORTOOLS_H__ #define __CBORTOOLS_H__ -#include -#include +#include "common.h" #include #include diff --git a/client/fido/cose.c b/client/fido/cose.c index c62d6cfb3..f6f20852b 100644 --- a/client/fido/cose.c +++ b/client/fido/cose.c @@ -11,8 +11,11 @@ // #include "cose.h" -#include + #include "cbortools.h" +#include "commonutil.h" // ARRAYLEN +#include "ui.h" // Print... +#include "util.h" static const char COSEEmptyStr[] = ""; diff --git a/client/fido/cose.h b/client/fido/cose.h index e62054646..b78f27421 100644 --- a/client/fido/cose.h +++ b/client/fido/cose.h @@ -13,10 +13,7 @@ #ifndef __COSE_H__ #define __COSE_H__ -#include -#include -#include -#include "util.h" +#include "common.h" const char *GetCOSEAlgName(int id); const char *GetCOSEAlgDescription(int id); diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index c356c3456..8093f45c8 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -11,17 +11,20 @@ // #include "fidocore.h" + +#include "commonutil.h" // ARRAYLEN + #include "emv/emvcore.h" #include "emv/emvjson.h" -#include #include "cbortools.h" -#include -#include -#include +#include "mbedtls/x509_crt.h" #include "crypto/asn1utils.h" #include "crypto/libpcrypto.h" -#include "fido/additional_ca.h" -#include "fido/cose.h" +#include "additional_ca.h" +#include "cose.h" +#include "emv/dump.h" +#include "ui.h" +#include "util.h" typedef struct { uint8_t ErrorCode; @@ -150,7 +153,7 @@ fido2Desc_t fido2CmdGetInfoRespDesc[] = { }; const char *fido2GetCmdErrorDescription(uint8_t errorCode) { - for (size_t i = 0; i < sizeof(fido2Errors) / sizeof(fido2Error_t); i++) + for (size_t i = 0; i < ARRAYLEN(fido2Errors); i++) if (fido2Errors[i].ErrorCode == errorCode) return fido2Errors[i].Description; @@ -158,7 +161,7 @@ const char *fido2GetCmdErrorDescription(uint8_t errorCode) { } const char *fido2GetCmdMemberDescription(uint8_t cmdCode, bool isResponse, int memberNum) { - for (size_t i = 0; i < sizeof(fido2CmdGetInfoRespDesc) / sizeof(fido2Desc_t); i++) + for (size_t i = 0; i < ARRAYLEN(fido2CmdGetInfoRespDesc); i++) if (fido2CmdGetInfoRespDesc[i].Command == cmdCode && fido2CmdGetInfoRespDesc[i].PckType == (isResponse ? ptResponse : ptQuery) && fido2CmdGetInfoRespDesc[i].MemberNumber == memberNum) @@ -262,7 +265,7 @@ int FIDOCheckDERAndGetKey(uint8_t *der, size_t derLen, bool verbose, uint8_t *pu } // get public key - res = ecdsa_public_key_from_pk(&cert.pk, publicKey, publicKeyMaxLen); + res = ecdsa_public_key_from_pk(&cert.pk, MBEDTLS_ECP_DP_SECP256R1, publicKey, publicKeyMaxLen); if (res) { PrintAndLogEx(ERR, "ERROR: getting public key from certificate 0x%x - %s", (res < 0) ? -res : res, ecdsa_get_error(res)); } else { @@ -381,10 +384,10 @@ static int FIDO2CheckSignature(json_t *root, uint8_t *publickey, uint8_t *sign, clientDataHash, 32, // Hash of the serialized client data. "$.ClientDataHash" from json NULL, 0); //PrintAndLogEx(NORMAL, "--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); - res = ecdsa_signature_verify(publickey, xbuf, xbuflen, sign, signLen); + res = ecdsa_signature_verify(MBEDTLS_ECP_DP_SECP256R1, publickey, xbuf, xbuflen, sign, signLen, true); if (res) { - if (res == -0x4e00) { - PrintAndLogEx(WARNING, "Signature is NOT VALID."); + if (res == MBEDTLS_ERR_ECP_VERIFY_FAILED) { + PrintAndLogEx(WARNING, "Signature is " _RED_("NOT VALID")); } else { PrintAndLogEx(WARNING, "Other signature check error: %x %s", (res < 0) ? -res : res, ecdsa_get_error(res)); } diff --git a/client/fido/fidocore.h b/client/fido/fidocore.h index d54dc5b88..56c563120 100644 --- a/client/fido/fidocore.h +++ b/client/fido/fidocore.h @@ -12,10 +12,10 @@ #ifndef __FIDOCORE_H__ #define __FIDOCORE_H__ -#include -#include +#include "common.h" + #include -#include "cmdhf14a.h" +#include "emv/apduinfo.h" // sAPDU typedef enum { fido2CmdMakeCredential = 0x01, diff --git a/client/loclass/fileutils.c b/client/fileutils.c similarity index 51% rename from client/loclass/fileutils.c rename to client/fileutils.c index cb16a7fa3..8e0e3bb72 100644 --- a/client/loclass/fileutils.c +++ b/client/fileutils.c @@ -34,11 +34,23 @@ * * ****************************************************************************/ + +// this define is needed for scandir/alphasort to work +#define _GNU_SOURCE #include "fileutils.h" -#ifndef ON_DEVICE +#include +#include -#define PATH_MAX_LENGTH 100 +#include "pm3_cmd.h" +#include "commonutil.h" +#include "proxmark3.h" +#include "util.h" +#ifdef _WIN32 +#include "scandir.h" +#endif + +#define PATH_MAX_LENGTH 200 /** * @brief checks if a file exists @@ -91,32 +103,32 @@ static char *newfilenamemcopy(const char *preferredName, const char *suffix) { int saveFile(const char *preferredName, const char *suffix, const void *data, size_t datalen) { - if (data == NULL) return 1; + if (data == NULL) return PM3_EINVARG; char *fileName = newfilenamemcopy(preferredName, suffix); - if (fileName == NULL) return 1; + if (fileName == NULL) return PM3_EMALLOC; /* We should have a valid filename now, e.g. dumpdata-3.bin */ /*Opening file for writing in binary mode*/ FILE *f = fopen(fileName, "wb"); if (!f) { - PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_("%s")"'", fileName); + PrintAndLogEx(WARNING, "file not found or locked. '" _YELLOW_("%s")"'", fileName); free(fileName); return PM3_EFILE; } fwrite(data, 1, datalen, f); fflush(f); fclose(f); - PrintAndLogDevice(SUCCESS, "saved %u bytes to binary file " _YELLOW_("%s"), datalen, fileName); + PrintAndLogEx(SUCCESS, "saved %u bytes to binary file " _YELLOW_("%s"), datalen, fileName); free(fileName); return PM3_SUCCESS; } int saveFileEML(const char *preferredName, uint8_t *data, size_t datalen, size_t blocksize) { - if (data == NULL) return 1; + if (data == NULL) return PM3_EINVARG; char *fileName = newfilenamemcopy(preferredName, ".eml"); - if (fileName == NULL) return 1; + if (fileName == NULL) return PM3_EMALLOC; int retval = PM3_SUCCESS; int blocks = datalen / blocksize; @@ -127,7 +139,7 @@ int saveFileEML(const char *preferredName, uint8_t *data, size_t datalen, size_t /*Opening file for writing in text mode*/ FILE *f = fopen(fileName, "w+"); if (!f) { - PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_("%s")"'", fileName); + PrintAndLogEx(WARNING, "file not found or locked. '" _YELLOW_("%s")"'", fileName); retval = PM3_EFILE; goto out; } @@ -150,7 +162,7 @@ int saveFileEML(const char *preferredName, uint8_t *data, size_t datalen, size_t } fflush(f); fclose(f); - PrintAndLogDevice(SUCCESS, "saved %d blocks to text file " _YELLOW_("%s"), blocks, fileName); + PrintAndLogEx(SUCCESS, "saved %d blocks to text file " _YELLOW_("%s"), blocks, fileName); out: free(fileName); @@ -159,9 +171,9 @@ out: int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, size_t datalen) { - if (data == NULL) return 1; + if (data == NULL) return PM3_EINVARG; char *fileName = newfilenamemcopy(preferredName, ".json"); - if (fileName == NULL) return 1; + if (fileName == NULL) return PM3_EMALLOC; int retval = PM3_SUCCESS; @@ -269,16 +281,29 @@ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, s } break; } + case jsfIclass: { + JsonSaveStr(root, "FileType", "iclass"); + uint8_t csn[8] = {0}; + memcpy(csn, data, 8); + JsonSaveBufAsHexCompact(root, "$.Card.CSN", csn, sizeof(csn)); + + for (size_t i = 0; i < (datalen / 8); i++) { + char path[PATH_MAX_LENGTH] = {0}; + sprintf(path, "$.blocks.%zu", i); + JsonSaveBufAsHexCompact(root, path, data + (i * 8), 8); + } + break; + } } int res = json_dump_file(root, fileName, JSON_INDENT(2)); if (res) { - PrintAndLogDevice(FAILED, "error: can't save the file: " _YELLOW_("%s"), fileName); + PrintAndLogEx(FAILED, "error: can't save the file: " _YELLOW_("%s"), fileName); json_decref(root); retval = 200; goto out; } - PrintAndLogDevice(SUCCESS, "saved to json file " _YELLOW_("%s"), fileName); + PrintAndLogEx(SUCCESS, "saved to json file " _YELLOW_("%s"), fileName); json_decref(root); out: @@ -286,17 +311,48 @@ out: return retval; } +int createMfcKeyDump(uint8_t sectorsCnt, sector_t *e_sector, char *fptr) { + uint8_t tmpKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + int i; + + if (fptr == NULL) { + return PM3_EINVARG; + } + + FILE *fkeys = fopen(fptr, "wb"); + if (fkeys == NULL) { + PrintAndLogEx(WARNING, "Could not create file " _YELLOW_("%s"), fptr); + return PM3_EFILE; + } + PrintAndLogEx(SUCCESS, "Printing keys to binary file " _YELLOW_("%s")"...", fptr); + + for (i = 0; i < sectorsCnt; i++) { + num_to_bytes(e_sector[i].Key[0], 6, tmpKey); + fwrite(tmpKey, 1, 6, fkeys); + } + + for (i = 0; i < sectorsCnt; i++) { + num_to_bytes(e_sector[i].Key[1], 6, tmpKey); + fwrite(tmpKey, 1, 6, fkeys); + } + + fclose(fkeys); + PrintAndLogEx(SUCCESS, "Found keys have been dumped to " _YELLOW_("%s")" --> 0xffffffffffff has been inserted for unknown keys.", fptr); + return PM3_SUCCESS; +} + + int loadFile(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen) { if (data == NULL) return 1; char *fileName = filenamemcopy(preferredName, suffix); - if (fileName == NULL) return 1; + if (fileName == NULL) return PM3_EINVARG; int retval = PM3_SUCCESS; FILE *f = fopen(fileName, "rb"); if (!f) { - PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_("%s")"'", fileName); + PrintAndLogEx(WARNING, "file not found or locked. '" _YELLOW_("%s")"'", fileName); free(fileName); return PM3_EFILE; } @@ -307,58 +363,108 @@ int loadFile(const char *preferredName, const char *suffix, void *data, size_t m fseek(f, 0, SEEK_SET); if (fsize <= 0) { - PrintAndLogDevice(FAILED, "error, when getting filesize"); - retval = 1; + PrintAndLogEx(FAILED, "error, when getting filesize"); + retval = PM3_EFILE; goto out; } uint8_t *dump = calloc(fsize, sizeof(uint8_t)); if (!dump) { - PrintAndLogDevice(FAILED, "error, cannot allocate memory"); - retval = 2; + PrintAndLogEx(FAILED, "error, cannot allocate memory"); + retval = PM3_EMALLOC; goto out; } size_t bytes_read = fread(dump, 1, fsize, f); + fclose(f); if (bytes_read != fsize) { - PrintAndLogDevice(FAILED, "error, bytes read mismatch file size"); + PrintAndLogEx(FAILED, "error, bytes read mismatch file size"); free(dump); - retval = 3; + retval = PM3_EFILE; goto out; } if (bytes_read > maxdatalen) { - PrintAndLogDevice(WARNING, "Warning, bytes read exceed calling array limit. Max bytes is %d bytes", maxdatalen); + PrintAndLogEx(WARNING, "Warning, bytes read exceed calling array limit. Max bytes is %d bytes", maxdatalen); bytes_read = maxdatalen; } memcpy((data), dump, bytes_read); free(dump); - PrintAndLogDevice(SUCCESS, "loaded %d bytes from binary file " _YELLOW_("%s"), bytes_read, fileName); + PrintAndLogEx(SUCCESS, "loaded %d bytes from binary file " _YELLOW_("%s"), bytes_read, fileName); *datalen = bytes_read; out: - fclose(f); free(fileName); + return retval; +} +int loadFile_safe(const char *preferredName, const char *suffix, void **pdata, size_t *datalen) { + + char *path; + int res = searchFile(&path, RESOURCES_SUBDIR, preferredName, suffix, false); + if (res != PM3_SUCCESS) { + return PM3_EFILE; + } + + int retval = PM3_SUCCESS; + + FILE *f = fopen(path, "rb"); + if (!f) { + 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) { + PrintAndLogEx(FAILED, "error, cannot 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"); + return PM3_EFILE; + } + + *datalen = bytes_read; + + PrintAndLogEx(SUCCESS, "loaded %d bytes from binary file " _YELLOW_("%s"), bytes_read, preferredName); return retval; } int loadFileEML(const char *preferredName, void *data, size_t *datalen) { - if (data == NULL) return 1; + if (data == NULL) return PM3_EINVARG; char *fileName = filenamemcopy(preferredName, ".eml"); - if (fileName == NULL) return 1; + if (fileName == NULL) return PM3_EMALLOC; size_t counter = 0; int retval = PM3_SUCCESS, hexlen = 0; FILE *f = fopen(fileName, "r"); if (!f) { - PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_("%s")"'", fileName); + PrintAndLogEx(WARNING, "file not found or locked. '" _YELLOW_("%s")"'", fileName); retval = PM3_EFILE; goto out; } @@ -377,7 +483,7 @@ int loadFileEML(const char *preferredName, void *data, size_t *datalen) { break; fclose(f); PrintAndLogEx(FAILED, "File reading error."); - retval = 2; + retval = PM3_EFILE; goto out; } @@ -391,7 +497,7 @@ int loadFileEML(const char *preferredName, void *data, size_t *datalen) { } } fclose(f); - PrintAndLogDevice(SUCCESS, "loaded %d bytes from text file " _YELLOW_("%s"), counter, fileName); + PrintAndLogEx(SUCCESS, "loaded %d bytes from text file " _YELLOW_("%s"), counter, fileName); if (datalen) *datalen = counter; @@ -403,9 +509,9 @@ out: int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_t *datalen) { - if (data == NULL) return 1; + if (data == NULL) return PM3_EINVARG; char *fileName = filenamemcopy(preferredName, ".json"); - if (fileName == NULL) return 1; + if (fileName == NULL) return PM3_EMALLOC; *datalen = 0; json_t *root; @@ -416,13 +522,13 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_ root = json_load_file(fileName, 0, &error); if (!root) { PrintAndLogEx(ERR, "ERROR: json " _YELLOW_("%s") " error on line %d: %s", fileName, error.line, error.text); - retval = 2; + retval = PM3_ESOFT; goto out; } if (!json_is_object(root)) { PrintAndLogEx(ERR, "ERROR: Invalid json " _YELLOW_("%s") " format. root must be an object.", fileName); - retval = 3; + retval = PM3_ESOFT; goto out; } @@ -438,7 +544,7 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_ size_t sptr = 0; for (int i = 0; i < 256; i++) { if (sptr + 16 > maxdatalen) { - retval = 5; + retval = PM3_EMALLOC; goto out; } @@ -460,7 +566,7 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_ size_t sptr = 0; for (int i = 0; i < 256; i++) { if (sptr + 4 > maxdatalen) { - retval = 5; + retval = PM3_EMALLOC; goto out; } @@ -482,7 +588,7 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_ size_t sptr = 0; for (size_t i = 0; i < (maxdatalen / 4); i++) { if (sptr + 4 > maxdatalen) { - retval = 5; + retval = PM3_EMALLOC; goto out; } @@ -500,6 +606,27 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_ *datalen = sptr; } + if (!strcmp(ctype, "iclass")) { + size_t sptr = 0; + for (size_t i = 0; i < (maxdatalen / 8); i++) { + if (sptr + 8 > maxdatalen) { + retval = PM3_EMALLOC; + goto out; + } + + char path[30] = {0}; + sprintf(path, "$.blocks.%zu", i); + + size_t len = 0; + JsonLoadBufAsHex(root, path, &udata[sptr], 8, &len); + if (!len) + break; + + sptr += len; + } + *datalen = sptr; + } + PrintAndLogEx(SUCCESS, "loaded from JSON file " _YELLOW_("%s"), fileName); out: json_decref(root); @@ -509,10 +636,10 @@ out: int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, uint8_t keylen, uint16_t *keycnt) { - - if (data == NULL) return 1; - char *fileName = filenamemcopy(preferredName, ".dic"); - if (fileName == NULL) return 1; + if (data == NULL) return PM3_EINVARG; + char *path; + if (searchFile(&path, DICTIONARIES_SUBDIR, preferredName, ".dic", false) != PM3_SUCCESS) + return PM3_EFILE; // t5577 == 4bytes // mifare == 6 bytes @@ -530,9 +657,9 @@ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, u size_t counter = 0; int retval = PM3_SUCCESS; - FILE *f = fopen(fileName, "r"); + FILE *f = fopen(path, "r"); if (!f) { - PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_("%s")"'", fileName); + PrintAndLogEx(WARNING, "file not found or locked. '" _YELLOW_("%s")"'", path); retval = PM3_EFILE; goto out; } @@ -564,12 +691,98 @@ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, u counter += (keylen >> 1); } fclose(f); - PrintAndLogDevice(SUCCESS, "loaded " _GREEN_("%2d") "keys from dictionary file " _YELLOW_("%s"), *keycnt, fileName); + PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") "keys from dictionary file " _YELLOW_("%s"), *keycnt, path); if (datalen) *datalen = counter; out: - free(fileName); + free(path); + return retval; +} + +int loadFileDICTIONARY_safe(const char *preferredName, void **pdata, uint8_t keylen, uint16_t *keycnt) { + + int retval = PM3_SUCCESS; + + char *path; + if (searchFile(&path, DICTIONARIES_SUBDIR, preferredName, ".dic", false) != PM3_SUCCESS) + return PM3_EFILE; + + // t5577 == 4bytes + // mifare == 6 bytes + // iclass == 8 bytes + // default to 6 bytes. + if (keylen != 4 && keylen != 6 && keylen != 8) { + keylen = 6; + } + + size_t mem_size; + size_t block_size = 10 * keylen; + + // double up since its chars + keylen <<= 1; + + char line[255]; + + // allocate some space for the dictionary + *pdata = calloc(block_size, sizeof(uint8_t)); + if (*pdata == NULL) + return PM3_EFILE; + + mem_size = block_size; + + FILE *f = fopen(path, "r"); + if (!f) { + PrintAndLogEx(WARNING, "file not found or locked. '" _YELLOW_("%s")"'", path); + retval = PM3_EFILE; + goto out; + } + + // read file + while (fgets(line, sizeof(line), f)) { + + // check if we have enough space (if not allocate more) + if ((*keycnt * (keylen >> 1)) >= mem_size) { + + mem_size += block_size; + *pdata = realloc(*pdata, mem_size); + + if (*pdata == NULL) { + return PM3_EFILE; + } else { + memset(*pdata + (mem_size - block_size), 0, block_size); + } + } + + // add null terminator + line[keylen] = 0; + + // smaller keys than expected is skipped + if (strlen(line) < keylen) + continue; + + // The line start with # is comment, skip + if (line[0] == '#') + continue; + + if (!isxdigit(line[0])) { + PrintAndLogEx(FAILED, "file content error. '%s' must include " _BLUE_("%2d") "HEX symbols", line, keylen); + continue; + } + + uint64_t key = strtoull(line, NULL, 16); + + num_to_bytes(key, keylen >> 1, *pdata + (*keycnt * (keylen >> 1))); + + (*keycnt)++; + + memset(line, 0, sizeof(line)); + } + fclose(f); + PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") "keys from dictionary file " _YELLOW_("%s"), *keycnt, path); + +out: + free(path); return retval; } @@ -601,11 +814,215 @@ int convertOldMfuDump(uint8_t **dump, size_t *dumplen) { *dumplen = new_dump_len; free(*dump); *dump = (uint8_t *) mfu_dump; - PrintAndLogDevice(SUCCESS, "old mfu dump format, was converted on load to " _GREEN_("%d") " pages", mfu_dump->pages + 1); + PrintAndLogEx(SUCCESS, "old mfu dump format, was converted on load to " _GREEN_("%d") " pages", mfu_dump->pages + 1); return PM3_SUCCESS; } +static int filelist(const char *path, const char *ext, bool last, bool tentative) { + struct dirent **namelist; + int n; -#else //if we're on ARM + n = scandir(path, &namelist, NULL, alphasort); + if (n == -1) { + if (!tentative) + PrintAndLogEx(NORMAL, "%s── %s", last ? "└" : "├", path); + return PM3_EFILE; + } -#endif + PrintAndLogEx(NORMAL, "%s── %s", last ? "└" : "├", path); + for (uint16_t i = 0; i < n; i++) { + if (((ext == NULL) && (namelist[i]->d_name[0] != '.')) || (str_endswith(namelist[i]->d_name, ext))) { + PrintAndLogEx(NORMAL, "%s   %s── %-21s", last ? " " : "│", i == n - 1 ? "└" : "├", namelist[i]->d_name); + } + free(namelist[i]); + } + free(namelist); + return PM3_SUCCESS; +} + +int searchAndList(const char *pm3dir, const char *ext) { + // display in same order as searched by searchFile + // try pm3 dirs in current workdir (dev mode) + if (get_my_executable_directory() != NULL) { + char script_directory_path[strlen(get_my_executable_directory()) + strlen(pm3dir) + 1]; + strcpy(script_directory_path, get_my_executable_directory()); + strcat(script_directory_path, pm3dir); + filelist(script_directory_path, ext, false, true); + } + // try pm3 dirs in user .proxmark3 (user mode) + char *userpath = getenv("HOME"); + if (userpath != NULL) { + char script_directory_path[strlen(userpath) + strlen(PM3_USER_DIRECTORY) + strlen(pm3dir) + 1]; + strcpy(script_directory_path, userpath); + strcat(script_directory_path, PM3_USER_DIRECTORY); + strcat(script_directory_path, pm3dir); + filelist(script_directory_path, ext, false, false); + } + // try pm3 dirs in pm3 installation dir (install mode) + const char *exec_path = get_my_executable_directory(); + if (exec_path != NULL) { + char script_directory_path[strlen(exec_path) + strlen(PM3_SHARE_RELPATH) + strlen(pm3dir) + 1]; + strcpy(script_directory_path, exec_path); + strcat(script_directory_path, PM3_SHARE_RELPATH); + strcat(script_directory_path, pm3dir); + filelist(script_directory_path, ext, true, false); + } + return PM3_SUCCESS; +} + +static int searchFinalFile(char **foundpath, const char *pm3dir, const char *searchname, bool silent) { + if ((foundpath == NULL) || (pm3dir == NULL) || (searchname == NULL)) return PM3_ESOFT; + // explicit absolute (/) or relative path (./) => try only to match it directly + char *filename = calloc(strlen(searchname) + 1, sizeof(char)); + if (filename == NULL) return PM3_EMALLOC; + strcpy(filename, searchname); + if ((g_debugMode == 2) && (!silent)) { + PrintAndLogEx(INFO, "Searching %s", filename); + } + if (((strlen(filename) > 1) && (filename[0] == '/')) || + ((strlen(filename) > 2) && (filename[0] == '.') && (filename[1] == '/'))) { + if (fileExists(filename)) { + *foundpath = filename; + if ((g_debugMode == 2) && (!silent)) { + PrintAndLogEx(INFO, "Found %s", *foundpath); + } + return PM3_SUCCESS; + } else { + goto out; + } + } + // else + + // try implicit relative path + { + if (fileExists(filename)) { + *foundpath = filename; + if ((g_debugMode == 2) && (!silent)) { + PrintAndLogEx(INFO, "Found %s", *foundpath); + } + return PM3_SUCCESS; + } + } + // try pm3 dirs in user .proxmark3 (user mode) + char *user_path = getenv("HOME"); + if (user_path != NULL) { + char *path = calloc(strlen(user_path) + strlen(PM3_USER_DIRECTORY) + strlen(pm3dir) + strlen(filename) + 1, sizeof(char)); + if (path == NULL) + goto out; + strcpy(path, user_path); + strcat(path, PM3_USER_DIRECTORY); + strcat(path, pm3dir); + strcat(path, filename); + if ((g_debugMode == 2) && (!silent)) { + PrintAndLogEx(INFO, "Searching %s", path); + } + if (fileExists(path)) { + free(filename); + *foundpath = path; + if ((g_debugMode == 2) && (!silent)) { + PrintAndLogEx(INFO, "Found %s", *foundpath); + } + return PM3_SUCCESS; + } else { + free(path); + } + } + // try pm3 dirs in current client workdir (dev mode) + const char *exec_path = get_my_executable_directory(); + if ((exec_path != NULL) && + ((strcmp(DICTIONARIES_SUBDIR, pm3dir) == 0) || + (strcmp(LUA_LIBRARIES_SUBDIR, pm3dir) == 0) || + (strcmp(LUA_SCRIPTS_SUBDIR, pm3dir) == 0) || + (strcmp(CMD_SCRIPTS_SUBDIR, pm3dir) == 0) || + (strcmp(RESOURCES_SUBDIR, pm3dir) == 0))) { + char *path = calloc(strlen(exec_path) + strlen(pm3dir) + strlen(filename) + 1, sizeof(char)); + if (path == NULL) + goto out; + strcpy(path, exec_path); + strcat(path, pm3dir); + strcat(path, filename); + if ((g_debugMode == 2) && (!silent)) { + PrintAndLogEx(INFO, "Searching %s", path); + } + if (fileExists(path)) { + free(filename); + *foundpath = path; + if ((g_debugMode == 2) && (!silent)) { + PrintAndLogEx(INFO, "Found %s", *foundpath); + } + return PM3_SUCCESS; + } else { + free(path); + } + } + // try pm3 dirs in current repo workdir (dev mode) + if ((exec_path != NULL) && + ((strcmp(TRACES_SUBDIR, pm3dir) == 0) || + (strcmp(FIRMWARES_SUBDIR, pm3dir) == 0) || + (strcmp(BOOTROM_SUBDIR, pm3dir) == 0) || + (strcmp(FULLIMAGE_SUBDIR, pm3dir) == 0))) { + char *above = "../"; + char *path = calloc(strlen(exec_path) + strlen(above) + strlen(pm3dir) + strlen(filename) + 1, sizeof(char)); + if (path == NULL) + goto out; + strcpy(path, exec_path); + strcat(path, above); + strcat(path, pm3dir); + strcat(path, filename); + if ((g_debugMode == 2) && (!silent)) { + PrintAndLogEx(INFO, "Searching %s", path); + } + if (fileExists(path)) { + free(filename); + *foundpath = path; + if ((g_debugMode == 2) && (!silent)) { + PrintAndLogEx(INFO, "Found %s", *foundpath); + } + return PM3_SUCCESS; + } else { + free(path); + } + } + // try pm3 dirs in pm3 installation dir (install mode) + { + char *path = calloc(strlen(exec_path) + strlen(PM3_SHARE_RELPATH) + strlen(pm3dir) + strlen(filename) + 1, sizeof(char)); + if (path == NULL) + goto out; + strcpy(path, exec_path); + strcat(path, PM3_SHARE_RELPATH); + strcat(path, pm3dir); + strcat(path, filename); + if ((g_debugMode == 2) && (!silent)) { + PrintAndLogEx(INFO, "Searching %s", path); + } + if (fileExists(path)) { + free(filename); + *foundpath = path; + if ((g_debugMode == 2) && (!silent)) { + PrintAndLogEx(INFO, "Found %s", *foundpath); + } + return PM3_SUCCESS; + } else { + free(path); + } + } +out: + free(filename); + return PM3_EFILE; +} + +int searchFile(char **foundpath, const char *pm3dir, const char *searchname, const char *suffix, bool silent) { + if (foundpath == NULL) + return PM3_EINVARG; + char *filename = filenamemcopy(searchname, suffix); + if (filename == NULL) return PM3_EMALLOC; + int res = searchFinalFile(foundpath, pm3dir, filename, silent); + if (res != PM3_SUCCESS) { + if ((res == PM3_EFILE) && (!silent)) + PrintAndLogEx(FAILED, "Error - can't find %s", filename); + free(filename); + return res; + } + free(filename); + return PM3_SUCCESS; +} diff --git a/client/loclass/fileutils.h b/client/fileutils.h similarity index 77% rename from client/loclass/fileutils.h rename to client/fileutils.h index dae23a1b1..5432aa816 100644 --- a/client/loclass/fileutils.h +++ b/client/fileutils.h @@ -38,17 +38,16 @@ #ifndef FILEUTILS_H #define FILEUTILS_H -#ifndef ON_DEVICE - #include #include #include #include #include #include -#include "../ui.h" -#include "../emv/emvjson.h" +#include "ui.h" +#include "emv/emvjson.h" #include "mifare/mifare4.h" +#include "mifare/mifarehost.h" #include "cmdhfmfu.h" typedef enum { @@ -56,12 +55,20 @@ typedef enum { jsfCardMemory, jsfMfuMemory, jsfHitag, + jsfIclass, // jsf14b, // jsf15, // jsfLegic, // jsfT55xx, } JSONFileType; +typedef enum { + BIN = 0, + EML, + JSON, + DICTIONARY, +} DumpFileType_t; + int fileExists(const char *filename); /** @@ -103,7 +110,17 @@ int saveFileEML(const char *preferredName, uint8_t *data, size_t datalen, size_t */ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, size_t datalen); -/** STUB +/** + * @brief Utility function to save a keydump. + * + * @param sectorsCnt the used sectors + * @param e_sector the keys in question + * @param fptr string pointer to the filename + * @return 0 for ok, 1 for failz + */ +int createMfcKeyDump(uint8_t sectorsCnt, sector_t *e_sector, char *fptr); + +/** * @brief Utility function to load data from a binary file. This method takes a preferred name. * E.g. dumpdata-15.bin * @@ -112,10 +129,22 @@ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, s * @param data The data array to store the loaded bytes from file * @param maxdatalen the number of bytes that your data array has * @param datalen the number of bytes loaded from file - * @return 0 for ok, 1 for failz + * @return PM3_SUCCESS for ok, PM3_E* for failz */ int loadFile(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen); + +/** + * @brief Utility function to load data from a binary file. This method takes a preferred name. + * E.g. dumpdata-15.bin, 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_safe(const char *preferredName, const char *suffix, void **pdata, size_t *datalen); /** * @brief Utility function to load data from a textfile (EML). This method takes a preferred name. * E.g. dumpdata-15.txt @@ -139,10 +168,9 @@ int loadFileEML(const char *preferredName, void *data, size_t *datalen); */ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_t *datalen); - /** * @brief Utility function to load data from a DICTIONARY textfile. This method takes a preferred name. - * E.g. default_keys.dic + * E.g. mfc_default_keys.dic * * @param preferredName * @param data The data array to store the loaded bytes from file @@ -153,6 +181,17 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_ */ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, uint8_t keylen, uint16_t *keycnt); +/** + * @brief Utility function to load data safely from a DICTIONARY textfile. This method takes a preferred name. + * E.g. mfc_default_keys.dic + * + * @param preferredName + * @param pdata A pointer to a pointer (for reverencing the loaded dictionary) + * @param keylen the number of bytes a key per row is + * @return 0 for ok, 1 for failz +*/ +int loadFileDICTIONARY_safe(const char *preferredName, void **pdata, uint8_t keylen, uint16_t *keycnt); + /** * @brief Utility function to check and convert old mfu dump format to new * @@ -162,20 +201,7 @@ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, u */ int convertOldMfuDump(uint8_t **dump, size_t *dumplen); -#define PrintAndLogDevice(level, format, args...) PrintAndLogEx(level, format , ## args) -#else - -/** -* Utility function to print to console. This is used consistently within the library instead -* of printf, but it actually only calls printf. The reason to have this method is to -*make it simple to plug this library into proxmark, which has this function already to -* write also to a logfile. When doing so, just point this function to use PrintAndLog -* @param fmt -*/ -#define PrintAndLogDevice(level, format, args...) { } - - - -#endif //ON_DEVICE +int searchAndList(const char *pm3dir, const char *ext); +int searchFile(char **foundpath, const char *pm3dir, const char *searchname, const char *suffix, bool silent); #endif // FILEUTILS_H diff --git a/client/flash.c b/client/flash.c index f2f0b526a..5bbb669c0 100644 --- a/client/flash.c +++ b/client/flash.c @@ -10,6 +10,17 @@ #include "flash.h" +#include +#include +#include + +#include "ui.h" +#include "elf.h" +#include "proxendian.h" +#include "at91sam7s512.h" +#include "util_posix.h" +#include "comms.h" + #define FLASH_START 0x100000 #define BOOTLOADER_SIZE 0x2000 @@ -72,7 +83,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, ctx->segments = calloc(sizeof(flash_seg_t) * num_phdrs, sizeof(uint8_t)); if (!ctx->segments) { PrintAndLogEx(ERR, "Out of memory"); - return -1; + return PM3_EMALLOC; } ctx->num_segs = 0; seg = ctx->segments; @@ -102,19 +113,19 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, if (filesz != memsz) { PrintAndLogEx(ERR, "Error: PHDR file size does not equal memory size\n" "(DATA+BSS PHDRs do not make sense on ROM platforms!)"); - return -1; + return PM3_EFILE; } if (paddr < last_end) { PrintAndLogEx(ERR, "Error: PHDRs not sorted or overlap"); - return -1; + return PM3_EFILE; } if (paddr < FLASH_START || (paddr + filesz) > flash_end) { PrintAndLogEx(ERR, "Error: PHDR is not contained in Flash"); - return -1; + return PM3_EFILE; } if (vaddr >= FLASH_START && vaddr < flash_end && (flags & PF_W)) { PrintAndLogEx(ERR, "Error: Flash VMA segment is writable"); - return -1; + return PM3_EFILE; } uint8_t *data; @@ -122,12 +133,12 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, data = calloc(filesz + BLOCK_SIZE, sizeof(uint8_t)); if (!data) { PrintAndLogEx(ERR, "Error: Out of memory"); - return -1; + return PM3_EMALLOC; } if (fseek(fd, offset, SEEK_SET) < 0 || fread(data, 1, filesz, fd) != filesz) { PrintAndLogEx(ERR, "Error while reading PHDR payload"); free(data); - return -1; + return PM3_EFILE; } uint32_t block_offset = paddr & (BLOCK_SIZE - 1); @@ -146,7 +157,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, if (!new_data) { PrintAndLogEx(ERR, "Error: Out of memory"); free(data); - return -1; + return PM3_EMALLOC; } memset(new_data, 0xff, new_length); memcpy(new_data, prev_seg->data, prev_seg->length); @@ -180,7 +191,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, last_end = paddr + filesz; phdr++; } - return 0; + return PM3_SUCCESS; } // Sanity check segments and check for bootloader writes @@ -190,26 +201,26 @@ static int check_segs(flash_file_t *ctx, int can_write_bl, uint32_t flash_end) { if (seg->start & (BLOCK_SIZE - 1)) { PrintAndLogEx(ERR, "Error: Segment is not aligned"); - return -1; + return PM3_EFILE; } if (seg->start < FLASH_START) { PrintAndLogEx(ERR, "Error: Segment is outside of flash bounds"); - return -1; + return PM3_EFILE; } if (seg->start + seg->length > flash_end) { PrintAndLogEx(ERR, "Error: Segment is outside of flash bounds"); - return -1; + return PM3_EFILE; } if (!can_write_bl && seg->start < BOOTLOADER_END) { PrintAndLogEx(ERR, "Attempted to write bootloader but bootloader writes are not enabled"); - return -1; + return PM3_EINVARG; } if (can_write_bl && seg->start < BOOTLOADER_END && (seg->start + seg->length > BOOTLOADER_END)) { PrintAndLogEx(ERR, "Error: Segment is outside of bootloader bounds"); - return -1; + return PM3_EFILE; } } - return 0; + return PM3_SUCCESS; } // Load an ELF file and prepare it for flashing @@ -219,11 +230,12 @@ int flash_load(flash_file_t *ctx, const char *name, int can_write_bl, int flash_ Elf32_Phdr *phdrs = NULL; uint16_t num_phdrs; uint32_t flash_end = FLASH_START + flash_size; - int res; + int res = PM3_EUNDEF; fd = fopen(name, "rb"); if (!fd) { PrintAndLogEx(ERR, _RED_("Could not open file") "%s >>> ", name); + res = PM3_EFILE; goto fail; } @@ -231,28 +243,34 @@ int flash_load(flash_file_t *ctx, const char *name, int can_write_bl, int flash_ if (fread(&ehdr, sizeof(ehdr), 1, fd) != 1) { PrintAndLogEx(ERR, "Error while reading ELF file header"); + res = PM3_EFILE; goto fail; } if (memcmp(ehdr.e_ident, elf_ident, sizeof(elf_ident)) || le32(ehdr.e_version) != 1) { PrintAndLogEx(ERR, "Not an ELF file or wrong ELF type"); + res = PM3_EFILE; goto fail; } if (le16(ehdr.e_type) != ET_EXEC) { PrintAndLogEx(ERR, "ELF is not executable"); + res = PM3_EFILE; goto fail; } if (le16(ehdr.e_machine) != EM_ARM) { PrintAndLogEx(ERR, "Wrong ELF architecture"); + res = PM3_EFILE; goto fail; } if (!ehdr.e_phnum || !ehdr.e_phoff) { PrintAndLogEx(ERR, "ELF has no PHDRs"); + res = PM3_EFILE; goto fail; } if (le16(ehdr.e_phentsize) != sizeof(Elf32_Phdr)) { // could be a structure padding issue... PrintAndLogEx(ERR, "Either the ELF file or this code is made of fail"); + res = PM3_EFILE; goto fail; } num_phdrs = le16(ehdr.e_phnum); @@ -260,28 +278,31 @@ int flash_load(flash_file_t *ctx, const char *name, int can_write_bl, int flash_ phdrs = calloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr), sizeof(uint8_t)); if (!phdrs) { PrintAndLogEx(ERR, "Out of memory"); + res = PM3_EMALLOC; goto fail; } if (fseek(fd, le32(ehdr.e_phoff), SEEK_SET) < 0) { PrintAndLogEx(ERR, "Error while reading ELF PHDRs"); + res = PM3_EFILE; goto fail; } if (fread(phdrs, sizeof(Elf32_Phdr), num_phdrs, fd) != num_phdrs) { + res = PM3_EFILE; PrintAndLogEx(ERR, "Error while reading ELF PHDRs"); goto fail; } res = build_segs_from_phdrs(ctx, fd, phdrs, num_phdrs, flash_end); - if (res < 0) + if (res != PM3_SUCCESS) goto fail; res = check_segs(ctx, can_write_bl, flash_end); - if (res < 0) + if (res != PM3_SUCCESS) goto fail; free(phdrs); fclose(fd); ctx->filename = name; - return 0; + return PM3_SUCCESS; fail: if (phdrs) @@ -289,7 +310,7 @@ fail: if (fd) fclose(fd); flash_free(ctx); - return -1; + return res; } // Get the state of the proxmark, backwards compatible @@ -315,22 +336,23 @@ static int get_proxmark_state(uint32_t *state) { break; default: PrintAndLogEx(ERR, _RED_("Error:") "Couldn't get Proxmark3 state, bad response type: 0x%04x", resp.cmd); - return -1; + return PM3_EFATAL; break; } - return 0; + return PM3_SUCCESS; } // Enter the bootloader to be able to start flashing static int enter_bootloader(char *serial_port_name) { uint32_t state; + int ret; - if (get_proxmark_state(&state) < 0) - return -1; + if ((ret = get_proxmark_state(&state)) != PM3_SUCCESS) + return ret; /* Already in flash state, we're done. */ if (state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) - return 0; + return PM3_SUCCESS; if (state & DEVICE_INFO_FLAG_CURRENT_MODE_OS) { PrintAndLogEx(SUCCESS, _BLUE_("Entering bootloader...")); @@ -353,15 +375,15 @@ static int enter_bootloader(char *serial_port_name) { if (OpenProxmark(serial_port_name, true, 60, true, FLASHMODE_SPEED)) { PrintAndLogEx(NORMAL, " " _GREEN_("Found")); - return 0; + return PM3_SUCCESS; } else { PrintAndLogEx(ERR, _RED_("Error:") "Proxmark3 not found."); - return -1; + return PM3_ETIMEOUT; } } PrintAndLogEx(ERR, _RED_("Error:") "Unknown Proxmark3 mode"); - return -1; + return PM3_EFATAL; } static int wait_for_ack(PacketResponseNG *ack) { @@ -372,30 +394,33 @@ static int wait_for_ack(PacketResponseNG *ack) { ack->cmd, (ack->cmd == CMD_NACK) ? "NACK" : "" ); - return -1; + return PM3_ESOFT; } - return 0; + return PM3_SUCCESS; } static void flash_suggest_update_bootloader(void) { - PrintAndLogEx(ERR, _RED_("It is recommended that you first update your bootloader alone,")); + PrintAndLogEx(ERR, _RED_("It is recommended that you first " _YELLOW_("update your bootloader") _RED_("alone,"))); PrintAndLogEx(ERR, _RED_("reboot the Proxmark3 then only update the main firmware") "\n"); } static void flash_suggest_update_flasher(void) { - PrintAndLogEx(ERR, _RED_("It is recommended that you first update your flasher")); + PrintAndLogEx(ERR, _RED_("It is recommended that you first " _YELLOW_("update your flasher"))); } // Go into flashing mode int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t *max_allowed) { uint32_t state; uint32_t chipinfo = 0; + int ret; - if (enter_bootloader(serial_port_name) < 0) - return -1; + ret = enter_bootloader(serial_port_name); + if (ret != PM3_SUCCESS) + return ret; - if (get_proxmark_state(&state) < 0) - return -1; + ret = get_proxmark_state(&state); + if (ret != PM3_SUCCESS) + return ret; if (state & DEVICE_INFO_FLAG_UNDERSTANDS_CHIP_INFO) { SendCommandBL(CMD_CHIP_INFO, 0, 0, 0, NULL, 0); @@ -413,18 +438,22 @@ int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t if ((BL_VERSION_MAJOR(version) < BL_VERSION_FIRST_MAJOR) || (BL_VERSION_MAJOR(version) > BL_VERSION_LAST_MAJOR)) { // version info seems fishy version = BL_VERSION_INVALID; + PrintAndLogEx(ERR, _RED_("====================== OBS ! ===========================")); PrintAndLogEx(ERR, _RED_("Note: Your bootloader reported an invalid version number")); flash_suggest_update_bootloader(); // } else if (BL_VERSION_MAJOR(version) < BL_VERSION_MAJOR(FLASHER_VERSION)) { + PrintAndLogEx(ERR, _RED_("====================== OBS ! ===================================")); PrintAndLogEx(ERR, _RED_("Note: Your bootloader reported a version older than this flasher")); flash_suggest_update_bootloader(); } else if (BL_VERSION_MAJOR(version) > BL_VERSION_MAJOR(FLASHER_VERSION)) { + PrintAndLogEx(ERR, _RED_("====================== OBS ! =========================")); PrintAndLogEx(ERR, _RED_("Note: Your bootloader is more recent than this flasher")); flash_suggest_update_flasher(); } } else { - PrintAndLogEx(ERR, _RED_("Note: Your bootloader does not understand the new CMD_BL_VERSION command")); + PrintAndLogEx(ERR, _RED_("====================== OBS ! ===========================================")); + PrintAndLogEx(ERR, _RED_("Note: Your bootloader does not understand the new " _YELLOW_("CMD_BL_VERSION") _RED_("command"))); flash_suggest_update_bootloader(); } @@ -433,9 +462,10 @@ int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t int mem_avail = chipid_to_mem_avail(chipinfo); if (mem_avail != 0) { - PrintAndLogEx(NORMAL, "Available memory on this board: %uK bytes\n", mem_avail); + PrintAndLogEx(INFO, "Available memory on this board: "_YELLOW_("%uK") "bytes\n", mem_avail); if (mem_avail > 256) { if (BL_VERSION_MAJOR(version) < BL_VERSION_MAJOR(BL_VERSION_1_0_0)) { + PrintAndLogEx(ERR, _RED_("====================== OBS ! ======================")); PrintAndLogEx(ERR, _RED_("Your bootloader does not support writing above 256k")); flash_suggest_update_bootloader(); } else { @@ -444,8 +474,9 @@ int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t } } } else { - PrintAndLogEx(NORMAL, "Available memory on this board: "_RED_("UNKNOWN")"\n"); - PrintAndLogEx(ERR, _RED_("Note: Your bootloader does not understand the new CHIP_INFO command")); + PrintAndLogEx(INFO, "Available memory on this board: "_RED_("UNKNOWN")"\n"); + PrintAndLogEx(ERR, _RED_("====================== OBS ! ======================================")); + PrintAndLogEx(ERR, _RED_("Note: Your bootloader does not understand the new " _YELLOW_("CHIP_INFO") _RED_("command"))); flash_suggest_update_bootloader(); } @@ -464,10 +495,11 @@ int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t } return wait_for_ack(&resp); } else { - PrintAndLogEx(ERR, _RED_("Note: Your bootloader does not understand the new START_FLASH command")); + PrintAndLogEx(ERR, _RED_("====================== OBS ! ========================================")); + PrintAndLogEx(ERR, _RED_("Note: Your bootloader does not understand the new " _YELLOW_("START_FLASH") _RED_("command"))); flash_suggest_update_bootloader(); } - return 0; + return PM3_SUCCESS; } static int write_block(uint32_t address, uint8_t *data, uint32_t length) { @@ -513,7 +545,7 @@ int flash_write(flash_file_t *ctx) { if (write_block(baddr, data, block_size) < 0) { PrintAndLogEx(ERR, "Error writing block %d of %u", block, blocks); - return -1; + return PM3_EFATAL; } data += block_size; @@ -526,7 +558,7 @@ int flash_write(flash_file_t *ctx) { PrintAndLogEx(NORMAL, " " _GREEN_("OK")); fflush(stdout); } - return 0; + return PM3_SUCCESS; } // free a file context @@ -546,5 +578,5 @@ void flash_free(flash_file_t *ctx) { int flash_stop_flashing(void) { SendCommandBL(CMD_HARDWARE_RESET, 0, 0, 0, NULL, 0); msleep(100); - return 0; + return PM3_SUCCESS; } diff --git a/client/flash.h b/client/flash.h index 4f05029dc..23dd28079 100644 --- a/client/flash.h +++ b/client/flash.h @@ -9,20 +9,10 @@ #ifndef __FLASH_H__ #define __FLASH_H__ -#include -#include -#include -#include -#include +#include "common.h" -#include "proxmark3.h" -#include "elf.h" -#include "proxendian.h" -#include "pm3_cmd.h" -#include "at91sam7s512.h" -#include "util_posix.h" -#include "util.h" -#include "comms.h" +#define FLASH_MAX_FILES 4 +#define ONE_KB 1024 typedef struct { void *data; diff --git a/client/flasher.c b/client/flasher.c deleted file mode 100644 index 97e3d7a1c..000000000 --- a/client/flasher.c +++ /dev/null @@ -1,137 +0,0 @@ -//----------------------------------------------------------------------------- -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// Flasher frontend tool -//----------------------------------------------------------------------------- - -#include -#include -#include -#include -#include -#include -#include "util_posix.h" -#include "proxmark3.h" -#include "util.h" -#include "flash.h" -#include "comms.h" -#include "pm3_cmd.h" -#include "ui.h" - -#define MAX_FILES 4 -#define ONE_KB 1024 - -static void usage(char *argv0) { - PrintAndLogEx(NORMAL, "Usage: %s [-b] image.elf [image.elf...]", argv0); - PrintAndLogEx(NORMAL, " %s -i\n", argv0); - PrintAndLogEx(NORMAL, "\t-b\tEnable flashing of bootloader area (DANGEROUS)"); - PrintAndLogEx(NORMAL, "\t-i\tProbe the connected Proxmark3 to retrieve its memory size"); - PrintAndLogEx(NORMAL, "\nExamples:\n\t %s "SERIAL_PORT_EXAMPLE_H" -i", argv0); - PrintAndLogEx(NORMAL, "\t %s "SERIAL_PORT_EXAMPLE_H" armsrc/obj/fullimage.elf", argv0); -#ifdef __linux__ - PrintAndLogEx(NORMAL, "\nNote (Linux):\nif the flasher gets stuck in 'Waiting for Proxmark3 to reappear on ',"); - PrintAndLogEx(NORMAL, "you need to blacklist Proxmark3 for modem-manager - see documentation for more details:"); - PrintAndLogEx(NORMAL, "* https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md"); - PrintAndLogEx(NORMAL, "\nMore info on flashing procedure from the official Proxmark3 wiki:"); - PrintAndLogEx(NORMAL, "* https://github.com/Proxmark/proxmark3/wiki/Gentoo%%20Linux"); - PrintAndLogEx(NORMAL, "* https://github.com/Proxmark/proxmark3/wiki/Ubuntu%%20Linux"); - PrintAndLogEx(NORMAL, "* https://github.com/Proxmark/proxmark3/wiki/OSX\n"); -#endif -} - -int main(int argc, char **argv) { - int can_write_bl = 0; - int num_files = 0; - int res; - int ret = 0; - flash_file_t files[MAX_FILES]; - char *filenames[MAX_FILES]; - bool info = false; - memset(files, 0, sizeof(files)); - - session.supports_colors = false; - session.stdinOnTTY = isatty(STDIN_FILENO); - session.stdoutOnTTY = isatty(STDOUT_FILENO); -#if defined(__linux__) || (__APPLE__) - if (session.stdinOnTTY && session.stdoutOnTTY) - session.supports_colors = true; -#endif - session.help_dump_mode = false; - - if (argc < 3) { - usage(argv[0]); - return -1; - } - - for (int i = 2; i < argc; i++) { - if (argv[i][0] == '-') { - if (!strcmp(argv[i], "-b")) { - can_write_bl = 1; - } else if (!strcmp(argv[i], "-i")) { - info = true; - } else { - usage(argv[0]); - return -1; - } - } else { - filenames[num_files] = argv[i]; - num_files++; - } - } - - char *serial_port_name = argv[1]; - - if (OpenProxmark(serial_port_name, true, 60, true, FLASHMODE_SPEED)) { - PrintAndLogEx(NORMAL, _GREEN_("Found")); - } else { - PrintAndLogEx(ERR, "Could not find Proxmark3 on " _RED_("%s") ".\n", serial_port_name); - return -1; - } - - uint32_t max_allowed = 0; - res = flash_start_flashing(can_write_bl, serial_port_name, &max_allowed); - if (res < 0) { - ret = -1; - goto finish; - } - - if (info) - goto finish; - - for (int i = 0 ; i < num_files; ++i) { - res = flash_load(&files[i], filenames[i], can_write_bl, max_allowed * ONE_KB); - if (res < 0) { - ret = -1; - goto finish; - } - PrintAndLogEx(NORMAL, ""); - } - - PrintAndLogEx(SUCCESS, "\n" _BLUE_("Flashing...")); - - for (int i = 0; i < num_files; i++) { - res = flash_write(&files[i]); - if (res < 0) { - ret = -1; - goto finish; - } - flash_free(&files[i]); - PrintAndLogEx(NORMAL, "\n"); - } - -finish: - res = flash_stop_flashing(); - if (res < 0) - ret = -1; - - CloseProxmark(); - - if (ret == 0) - PrintAndLogEx(SUCCESS, _BLUE_("All done.")); - else - PrintAndLogEx(ERR, "Aborted on error."); - PrintAndLogEx(NORMAL, "\nHave a nice day!"); - return ret; -} diff --git a/client/graph.c b/client/graph.c index 4af3261d2..fc0ceab2d 100644 --- a/client/graph.c +++ b/client/graph.c @@ -9,6 +9,12 @@ //----------------------------------------------------------------------------- #include "graph.h" +#include +#include "ui.h" +#include "util.h" //param_get32ex +#include "lfdemod.h" +#include "cmddata.h" //for g_debugmode + int GraphBuffer[MAX_GRAPH_TRACE_LEN]; size_t GraphTraceLen; int s_Buff[MAX_GRAPH_TRACE_LEN]; diff --git a/client/graph.h b/client/graph.h index fca93a889..01b20c7e2 100644 --- a/client/graph.h +++ b/client/graph.h @@ -10,13 +10,8 @@ #ifndef GRAPH_H__ #define GRAPH_H__ -#include -#include -#include -#include -#include "ui.h" -#include "lfdemod.h" -#include "cmddata.h" //for g_debugmode + +#include "common.h" void AppendGraph(bool redraw, uint16_t clock, int bit); size_t ClearGraph(bool redraw); diff --git a/client/hardnested/hardnested_bf_core.c b/client/hardnested/hardnested_bf_core.c index da9e19db4..adc203f61 100644 --- a/client/hardnested/hardnested_bf_core.c +++ b/client/hardnested/hardnested_bf_core.c @@ -60,6 +60,7 @@ THE SOFTWARE. #include "crapto1/crapto1.h" #include "parity.h" #include "util.h" +#include "common.h" // bitslice type // while AVX supports 256 bit vector floating point operations, we need integer operations for boolean logic diff --git a/client/hardnested/hardnested_bruteforce.c b/client/hardnested/hardnested_bruteforce.c index 9ecec900a..3aea34a96 100644 --- a/client/hardnested/hardnested_bruteforce.c +++ b/client/hardnested/hardnested_bruteforce.c @@ -55,6 +55,8 @@ THE SOFTWARE. #include #include #include + +#include "common.h" #include "proxmark3.h" #include "cmdhfmfhard.h" #include "hardnested_bf_core.h" @@ -63,11 +65,13 @@ THE SOFTWARE. #include "util_posix.h" #include "crapto1/crapto1.h" #include "parity.h" +#include "fileutils.h" +#include "pm3_cmd.h" #define NUM_BRUTE_FORCE_THREADS (num_CPUs()) #define DEFAULT_BRUTE_FORCE_RATE (120000000.0) // if benchmark doesn't succeed #define TEST_BENCH_SIZE (6000) // number of odd and even states for brute force benchmark -#define TEST_BENCH_FILENAME "hardnested/bf_bench_data.bin" +#define TEST_BENCH_FILENAME "hardnested_bf_bench_data.bin" //#define WRITE_BENCH_FILE // debugging options @@ -263,8 +267,12 @@ void prepare_bf_test_nonces(noncelist_t *nonces, uint8_t best_first_byte) { #if defined (WRITE_BENCH_FILE) static void write_benchfile(statelist_t *candidates) { - printf("Writing brute force benchmark data..."); - FILE *benchfile = fopen(TEST_BENCH_FILENAME, "wb"); + PrintAndLogEx(NORMAL, "Writing brute force benchmark data in " RESOURCES_SUBDIR " subdirectory..."); + FILE *benchfile = fopen(RESOURCES_SUBDIR TEST_BENCH_FILENAME, "wb"); + if (benchfile == NULL) { + PrintAndLogEx(ERR, "Can't write " RESOURCES_SUBDIR TEST_BENCH_FILENAME", abort!"); + return; + } fwrite(&nonces_to_bruteforce, 1, sizeof(nonces_to_bruteforce), benchfile); for (uint32_t i = 0; i < nonces_to_bruteforce; i++) { fwrite(&(bf_test_nonce[i]), 1, sizeof(bf_test_nonce[i]), benchfile); @@ -281,7 +289,7 @@ static void write_benchfile(statelist_t *candidates) { fwrite(&(candidates->states[ODD_STATE][i]), 1, sizeof(uint32_t), benchfile); } fclose(benchfile); - printf("done.\n"); + PrintAndLogEx(NORMAL, "Done"); } #endif @@ -358,14 +366,17 @@ static bool read_bench_data(statelist_t *test_candidates) { uint32_t num_states = 0; uint32_t states_read = 0; - char bench_file_path[strlen(get_my_executable_directory()) + strlen(TEST_BENCH_FILENAME) + 1]; - strcpy(bench_file_path, get_my_executable_directory()); - strcat(bench_file_path, TEST_BENCH_FILENAME); - - FILE *benchfile = fopen(bench_file_path, "rb"); - if (benchfile == NULL) { + char *path; + if (searchFile(&path, RESOURCES_SUBDIR, TEST_BENCH_FILENAME, "", false) != PM3_SUCCESS) { return false; } + + FILE *benchfile = fopen(path, "rb"); + if (benchfile == NULL) { + free(path); + return false; + } + free(path); bytes_read = fread(&nonces_to_bruteforce, 1, sizeof(nonces_to_bruteforce), benchfile); if (bytes_read != sizeof(nonces_to_bruteforce)) { fclose(benchfile); diff --git a/client/jansson/Makefile b/client/jansson/Makefile index e06ffbc76..dc4ae230b 100644 --- a/client/jansson/Makefile +++ b/client/jansson/Makefile @@ -1,81 +1,21 @@ -# Hide full compilation line: -ifneq ($(V),1) - Q?=@ -endif -# To see full command lines, use make V=1 - -include_HEADERS = jansson.h -nodist_include_HEADERS = jansson_config.h - -LIB_A = libjansson.a -libjansson_la_SOURCES = \ +MYSRCPATHS = +MYINCLUDES = -I. +MYCFLAGS = -std=c99 -D_ISOC99_SOURCE -Wno-unused-function +MYDEFS = -DHAVE_STDINT_H +MYSRCS = \ dump.c \ error.c \ hashtable.c \ - hashtable.h \ hashtable_seed.c \ - jansson_private.h \ load.c \ - lookup3.h \ memory.c \ pack_unpack.c \ strbuffer.c \ - strbuffer.h \ strconv.c \ utf.c \ - utf.h \ path.c \ value.c -libjansson_la_LDFLAGS = \ - -no-undefined \ - -export-symbols-regex '^json_' \ - -version-info 15:0:11 +LIB_A = libjansson.a -CFILES = $(filter %.c, $(libjansson_la_SOURCES)) -CMDOBJS = $(CFILES:%.c=%.o) -CLEAN = $(CMDOBJS) - -platform = $(shell uname) - -CC= gcc -CFLAGS= -O2 -Wall -Wno-unused-variable -Wno-unused-function - -LDFLAGS= $(SYSLDFLAGS) $(libjansson_la_LDFLAGS) -LIBS= $(SYSLIBS) $(MYLIBS) -DEFAULT_INCLUDES = -I. -DEFS = -DHAVE_STDINT_H - -ifeq ($(platform),Darwin) -AR= /usr/bin/ar rcs -RANLIB= /usr/bin/ranlib -else -AR= ar rcs -RANLIB= ranlib -endif -RM= rm -f -TST= echo - -SYSLDFLAGS= -SYSLIBS= - -MYLIBS= -MYOBJS= - -$(LIB_A): $(CMDOBJS) - $(info [=] AR $@) - $(Q)$(AR) $(LIB_A) $(CMDOBJS) - $(Q)$(RANLIB) $(LIB_A) - -all: $(LIB_A) - -clean: - $(Q)$(RM) $(CLEAN) - $(Q)$(RM) $(LIB_A) - -%.o: %.c - $(info [-] CC $<) - $(Q)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(CFLAGS) -c -o $@ $< $(LIBS) - -.PHONY: all clean - +include ../../Makefile.host diff --git a/client/liblua/Makefile b/client/liblua/Makefile new file mode 100644 index 000000000..250f4b7ee --- /dev/null +++ b/client/liblua/Makefile @@ -0,0 +1,62 @@ +MYSRCPATHS = +MYINCLUDES = -I. +# Lua lib is not ready for C99 style... +#MYCFLAGS = -std=c99 -D_ISOC99_SOURCE +MYCFLAGS = +MYDEFS = -DLUA_COMPAT_ALL $(SYSCFLAGS) +MYSRCS = lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c \ + lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c \ + ltm.c lundump.c lvm.c lzio.c \ + lauxlib.c lbaselib.c lbitlib.c lcorolib.c ldblib.c liolib.c \ + lmathlib.c loslib.c lstrlib.c ltablib.c loadlib.c linit.c + +SYSCFLAGS= + +LIB_A= liblua.a + +# Your platform. See PLATS for possible values. +PLAT= none + +PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris + +default: $(PLAT) + +include ../../Makefile.host + +# Convenience targets for popular platforms +ALL= all + +none: + @echo "Please do 'make PLATFORM' where PLATFORM is one of these:" + @echo " $(PLATS)" + +aix: + $(Q)$(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" + +ansi: + $(Q)$(MAKE) $(ALL) SYSCFLAGS="-DLUA_ANSI" + +bsd: + $(Q)$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" + +freebsd: + $(Q)$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" + +generic: $(ALL) + +linux: + $(Q)$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" + +macosx: + $(Q)$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" + +mingw: + $(Q)$(MAKE) $(ALL) + +posix: + $(Q)$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX" + +solaris: + $(Q)$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" + +.PHONY: all $(PLATS) default clean depend none diff --git a/liblua/lapi.c b/client/liblua/lapi.c similarity index 100% rename from liblua/lapi.c rename to client/liblua/lapi.c diff --git a/liblua/lapi.h b/client/liblua/lapi.h similarity index 100% rename from liblua/lapi.h rename to client/liblua/lapi.h diff --git a/liblua/lauxlib.c b/client/liblua/lauxlib.c similarity index 100% rename from liblua/lauxlib.c rename to client/liblua/lauxlib.c diff --git a/liblua/lauxlib.h b/client/liblua/lauxlib.h similarity index 100% rename from liblua/lauxlib.h rename to client/liblua/lauxlib.h diff --git a/liblua/lbaselib.c b/client/liblua/lbaselib.c similarity index 100% rename from liblua/lbaselib.c rename to client/liblua/lbaselib.c diff --git a/liblua/lbitlib.c b/client/liblua/lbitlib.c similarity index 100% rename from liblua/lbitlib.c rename to client/liblua/lbitlib.c diff --git a/liblua/lcode.c b/client/liblua/lcode.c similarity index 100% rename from liblua/lcode.c rename to client/liblua/lcode.c diff --git a/liblua/lcode.h b/client/liblua/lcode.h similarity index 100% rename from liblua/lcode.h rename to client/liblua/lcode.h diff --git a/liblua/lcorolib.c b/client/liblua/lcorolib.c similarity index 100% rename from liblua/lcorolib.c rename to client/liblua/lcorolib.c diff --git a/liblua/lctype.c b/client/liblua/lctype.c similarity index 100% rename from liblua/lctype.c rename to client/liblua/lctype.c diff --git a/liblua/lctype.h b/client/liblua/lctype.h similarity index 100% rename from liblua/lctype.h rename to client/liblua/lctype.h diff --git a/liblua/ldblib.c b/client/liblua/ldblib.c similarity index 100% rename from liblua/ldblib.c rename to client/liblua/ldblib.c diff --git a/liblua/ldebug.c b/client/liblua/ldebug.c similarity index 100% rename from liblua/ldebug.c rename to client/liblua/ldebug.c diff --git a/liblua/ldebug.h b/client/liblua/ldebug.h similarity index 100% rename from liblua/ldebug.h rename to client/liblua/ldebug.h diff --git a/liblua/ldo.c b/client/liblua/ldo.c similarity index 100% rename from liblua/ldo.c rename to client/liblua/ldo.c diff --git a/liblua/ldo.h b/client/liblua/ldo.h similarity index 100% rename from liblua/ldo.h rename to client/liblua/ldo.h diff --git a/liblua/ldump.c b/client/liblua/ldump.c similarity index 100% rename from liblua/ldump.c rename to client/liblua/ldump.c diff --git a/liblua/lfunc.c b/client/liblua/lfunc.c similarity index 100% rename from liblua/lfunc.c rename to client/liblua/lfunc.c diff --git a/liblua/lfunc.h b/client/liblua/lfunc.h similarity index 100% rename from liblua/lfunc.h rename to client/liblua/lfunc.h diff --git a/liblua/lgc.c b/client/liblua/lgc.c similarity index 100% rename from liblua/lgc.c rename to client/liblua/lgc.c diff --git a/liblua/lgc.h b/client/liblua/lgc.h similarity index 100% rename from liblua/lgc.h rename to client/liblua/lgc.h diff --git a/liblua/linit.c b/client/liblua/linit.c similarity index 100% rename from liblua/linit.c rename to client/liblua/linit.c diff --git a/liblua/liolib.c b/client/liblua/liolib.c similarity index 100% rename from liblua/liolib.c rename to client/liblua/liolib.c diff --git a/liblua/llex.c b/client/liblua/llex.c similarity index 100% rename from liblua/llex.c rename to client/liblua/llex.c diff --git a/liblua/llex.h b/client/liblua/llex.h similarity index 100% rename from liblua/llex.h rename to client/liblua/llex.h diff --git a/liblua/llimits.h b/client/liblua/llimits.h similarity index 100% rename from liblua/llimits.h rename to client/liblua/llimits.h diff --git a/liblua/lmathlib.c b/client/liblua/lmathlib.c similarity index 100% rename from liblua/lmathlib.c rename to client/liblua/lmathlib.c diff --git a/liblua/lmem.c b/client/liblua/lmem.c similarity index 100% rename from liblua/lmem.c rename to client/liblua/lmem.c diff --git a/liblua/lmem.h b/client/liblua/lmem.h similarity index 100% rename from liblua/lmem.h rename to client/liblua/lmem.h diff --git a/liblua/loadlib.c b/client/liblua/loadlib.c similarity index 100% rename from liblua/loadlib.c rename to client/liblua/loadlib.c diff --git a/liblua/lobject.c b/client/liblua/lobject.c similarity index 100% rename from liblua/lobject.c rename to client/liblua/lobject.c diff --git a/liblua/lobject.h b/client/liblua/lobject.h similarity index 100% rename from liblua/lobject.h rename to client/liblua/lobject.h diff --git a/liblua/lopcodes.c b/client/liblua/lopcodes.c similarity index 100% rename from liblua/lopcodes.c rename to client/liblua/lopcodes.c diff --git a/liblua/lopcodes.h b/client/liblua/lopcodes.h similarity index 100% rename from liblua/lopcodes.h rename to client/liblua/lopcodes.h diff --git a/liblua/loslib.c b/client/liblua/loslib.c similarity index 100% rename from liblua/loslib.c rename to client/liblua/loslib.c diff --git a/liblua/lparser.c b/client/liblua/lparser.c similarity index 100% rename from liblua/lparser.c rename to client/liblua/lparser.c diff --git a/liblua/lparser.h b/client/liblua/lparser.h similarity index 100% rename from liblua/lparser.h rename to client/liblua/lparser.h diff --git a/liblua/lstate.c b/client/liblua/lstate.c similarity index 100% rename from liblua/lstate.c rename to client/liblua/lstate.c diff --git a/liblua/lstate.h b/client/liblua/lstate.h similarity index 100% rename from liblua/lstate.h rename to client/liblua/lstate.h diff --git a/liblua/lstring.c b/client/liblua/lstring.c similarity index 100% rename from liblua/lstring.c rename to client/liblua/lstring.c diff --git a/liblua/lstring.h b/client/liblua/lstring.h similarity index 100% rename from liblua/lstring.h rename to client/liblua/lstring.h diff --git a/liblua/lstrlib.c b/client/liblua/lstrlib.c similarity index 100% rename from liblua/lstrlib.c rename to client/liblua/lstrlib.c diff --git a/liblua/ltable.c b/client/liblua/ltable.c similarity index 100% rename from liblua/ltable.c rename to client/liblua/ltable.c diff --git a/liblua/ltable.h b/client/liblua/ltable.h similarity index 100% rename from liblua/ltable.h rename to client/liblua/ltable.h diff --git a/liblua/ltablib.c b/client/liblua/ltablib.c similarity index 100% rename from liblua/ltablib.c rename to client/liblua/ltablib.c diff --git a/liblua/ltm.c b/client/liblua/ltm.c similarity index 100% rename from liblua/ltm.c rename to client/liblua/ltm.c diff --git a/liblua/ltm.h b/client/liblua/ltm.h similarity index 100% rename from liblua/ltm.h rename to client/liblua/ltm.h diff --git a/liblua/lua.c b/client/liblua/lua.c similarity index 100% rename from liblua/lua.c rename to client/liblua/lua.c diff --git a/liblua/lua.h b/client/liblua/lua.h similarity index 100% rename from liblua/lua.h rename to client/liblua/lua.h diff --git a/liblua/lua.hpp b/client/liblua/lua.hpp similarity index 100% rename from liblua/lua.hpp rename to client/liblua/lua.hpp diff --git a/liblua/luac.c b/client/liblua/luac.c similarity index 100% rename from liblua/luac.c rename to client/liblua/luac.c diff --git a/liblua/luaconf.h b/client/liblua/luaconf.h similarity index 100% rename from liblua/luaconf.h rename to client/liblua/luaconf.h diff --git a/liblua/lualib.h b/client/liblua/lualib.h similarity index 100% rename from liblua/lualib.h rename to client/liblua/lualib.h diff --git a/liblua/lundump.c b/client/liblua/lundump.c similarity index 100% rename from liblua/lundump.c rename to client/liblua/lundump.c diff --git a/liblua/lundump.h b/client/liblua/lundump.h similarity index 100% rename from liblua/lundump.h rename to client/liblua/lundump.h diff --git a/liblua/lvm.c b/client/liblua/lvm.c similarity index 100% rename from liblua/lvm.c rename to client/liblua/lvm.c diff --git a/liblua/lvm.h b/client/liblua/lvm.h similarity index 100% rename from liblua/lvm.h rename to client/liblua/lvm.h diff --git a/liblua/lzio.c b/client/liblua/lzio.c similarity index 100% rename from liblua/lzio.c rename to client/liblua/lzio.c diff --git a/liblua/lzio.h b/client/liblua/lzio.h similarity index 100% rename from liblua/lzio.h rename to client/liblua/lzio.h diff --git a/client/loclass/cipher.c b/client/loclass/cipher.c index fe676e83d..13f686b51 100644 --- a/client/loclass/cipher.c +++ b/client/loclass/cipher.c @@ -226,8 +226,8 @@ void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) { reverse_arraybytes(dest, sizeof(dest)); memcpy(mac, dest, 4); //free(cc_nr); - return; } + void doMAC_N(uint8_t *address_data_p, uint8_t address_data_size, uint8_t *div_key_p, uint8_t mac[4]) { uint8_t *address_data; uint8_t div_key[8]; @@ -245,12 +245,11 @@ void doMAC_N(uint8_t *address_data_p, uint8_t address_data_size, uint8_t *div_ke reverse_arraybytes(dest, sizeof(dest)); memcpy(mac, dest, 4); free(address_data); - return; } #ifndef ON_DEVICE int testMAC() { - PrintAndLogDevice(SUCCESS, "Testing MAC calculation..."); + PrintAndLogEx(SUCCESS, "Testing MAC calculation..."); //From the "dismantling.IClass" paper: uint8_t cc_nr[] = {0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0}; @@ -262,13 +261,13 @@ int testMAC() { doMAC(cc_nr, div_key, calculated_mac); if (memcmp(calculated_mac, correct_MAC, 4) == 0) { - PrintAndLogDevice(SUCCESS, "MAC calculation OK!"); + PrintAndLogEx(SUCCESS, "MAC calculation OK!"); } else { - PrintAndLogDevice(FAILED, "FAILED: MAC calculation failed:"); + PrintAndLogEx(FAILED, "FAILED: MAC calculation failed:"); printarr(" Calculated_MAC", calculated_mac, 4); printarr(" Correct_MAC ", correct_MAC, 4); - return 1; + return PM3_ESOFT; } - return 0; + return PM3_SUCCESS; } #endif diff --git a/client/loclass/cipher.h b/client/loclass/cipher.h index b79dc47cd..7b1257aa5 100644 --- a/client/loclass/cipher.h +++ b/client/loclass/cipher.h @@ -39,6 +39,7 @@ #ifndef CIPHER_H #define CIPHER_H #include +#include "pm3_cmd.h" void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]); void doMAC_N(uint8_t *address_data_p, uint8_t address_data_size, uint8_t *div_key_p, uint8_t mac[4]); diff --git a/client/loclass/cipherutils.c b/client/loclass/cipherutils.c index c829574e9..b50268697 100644 --- a/client/loclass/cipherutils.c +++ b/client/loclass/cipherutils.c @@ -34,12 +34,15 @@ * * ****************************************************************************/ +#include "cipherutils.h" #include #include #include +#include "util.h" // sprint_hex +#include "commonutil.h" // ARRAYLEN + #include "fileutils.h" -#include "cipherutils.h" /** * * @brief Return and remove the first bit (x0) in the stream : @@ -124,18 +127,21 @@ uint64_t x_bytes_to_num(uint8_t *src, size_t len) { } return num; } + uint8_t reversebytes(uint8_t b) { b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; b = (b & 0xCC) >> 2 | (b & 0x33) << 2; b = (b & 0xAA) >> 1 | (b & 0x55) << 1; return b; } + void reverse_arraybytes(uint8_t *arr, size_t len) { uint8_t i; for (i = 0; i < len ; i++) { arr[i] = reversebytes(arr[i]); } } + void reverse_arraycopy(uint8_t *arr, uint8_t *dest, size_t len) { uint8_t i; for (i = 0; i < len ; i++) { @@ -152,34 +158,25 @@ void printarr(const char *name, uint8_t *arr, int len) { cx += snprintf(output + cx, outsize - cx, "0x%02x,", *(arr + i)); //5 bytes per byte } snprintf(output + cx, outsize - cx, "};"); - PrintAndLogDevice(NORMAL, output); + PrintAndLogEx(NORMAL, output); free(output); } void printvar(const char *name, uint8_t *arr, int len) { - int cx, i; - size_t outsize = 40 + strlen(name) + len * 2; - char *output = calloc(outsize, sizeof(char)); - cx = snprintf(output, outsize, "%s = ", name); - for (i = 0; i < len; i++) { - cx += snprintf(output + cx, outsize - cx, "%02x", *(arr + i)); //2 bytes per byte - } - - PrintAndLogDevice(NORMAL, output); - free(output); + PrintAndLogEx(NORMAL, "%s = " _YELLOW_("%s"), name, sprint_hex(arr, len)); } void printarr_human_readable(const char *title, uint8_t *arr, int len) { - int cx, i; + int cx = 0, i; size_t outsize = 100 + strlen(title) + len * 4; char *output = calloc(outsize, sizeof(char)); - cx = snprintf(output, outsize, "\n\t%s\n", title); + PrintAndLogEx(NORMAL, "\n %s", title); for (i = 0; i < len; i++) { if (i % 16 == 0) cx += snprintf(output + cx, outsize - cx, "\n%02x| ", i); cx += snprintf(output + cx, outsize - cx, "%02x ", *(arr + i)); } - PrintAndLogDevice(NORMAL, output); + PrintAndLogEx(NORMAL, output); free(output); } @@ -201,16 +198,16 @@ static int testBitStream() { } if (memcmp(input, output, sizeof(input)) == 0) { - PrintAndLogDevice(SUCCESS, " Bitstream test 1 ok"); + PrintAndLogEx(SUCCESS, " Bitstream test 1 ok"); } else { - PrintAndLogDevice(FAILED, " Bitstream test 1 failed"); + PrintAndLogEx(FAILED, " Bitstream test 1 failed"); uint8_t i; - for (i = 0 ; i < sizeof(input) ; i++) { - PrintAndLogDevice(NORMAL, " IN %02x, OUT %02x", input[i], output[i]); + for (i = 0 ; i < ARRAYLEN(input) ; i++) { + PrintAndLogEx(NORMAL, " IN %02x, OUT %02x", input[i], output[i]); } - return 1; + return PM3_ESOFT; } - return 0; + return PM3_SUCCESS; } static int testReversedBitstream() { @@ -231,21 +228,21 @@ static int testReversedBitstream() { } if (memcmp(input, output, sizeof(input)) == 0) { - PrintAndLogDevice(SUCCESS, " Bitstream test 2 ok"); + PrintAndLogEx(SUCCESS, " Bitstream test 2 ok"); } else { - PrintAndLogDevice(FAILED, " Bitstream test 2 failed"); + PrintAndLogEx(FAILED, " Bitstream test 2 failed"); uint8_t i; - for (i = 0 ; i < sizeof(input) ; i++) { - PrintAndLogDevice(NORMAL, " IN %02x, MIDDLE: %02x, OUT %02x", input[i], reverse[i], output[i]); + for (i = 0 ; i < ARRAYLEN(input) ; i++) { + PrintAndLogEx(NORMAL, " IN %02x, MIDDLE: %02x, OUT %02x", input[i], reverse[i], output[i]); } - return 1; + return PM3_ESOFT; } - return 0; + return PM3_SUCCESS; } int testCipherUtils(void) { - PrintAndLogDevice(INFO, "Testing some internals..."); + PrintAndLogEx(INFO, "Testing some internals..."); int retval = 0; retval |= testBitStream(); retval |= testReversedBitstream(); diff --git a/client/loclass/cipherutils.h b/client/loclass/cipherutils.h index 70438d33b..6c90326a6 100644 --- a/client/loclass/cipherutils.h +++ b/client/loclass/cipherutils.h @@ -41,6 +41,7 @@ #include #include #include +#include "pm3_cmd.h" typedef struct { uint8_t *buffer; diff --git a/client/loclass/elite_crack.c b/client/loclass/elite_crack.c index 5b019d8e0..bf9aee5b3 100644 --- a/client/loclass/elite_crack.c +++ b/client/loclass/elite_crack.c @@ -221,7 +221,7 @@ void hash2(uint8_t *key64, uint8_t *outp_keytable) { // Once again, key is on iclass-format desencrypt_iclass(key64, key64_negated, z[0]); -// PrintAndLogDevice(NORMAL, "\n"); PrintAndLogDevice(NORMAL, "High security custom key (Kcus):"); +// PrintAndLogEx(NORMAL, "\n"); PrintAndLogEx(NORMAL, "High security custom key (Kcus):"); // printvar("z0 ", z[0],8); uint8_t y[8][8] = {{0}, {0}}; @@ -325,10 +325,10 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) { keytable[key_index[i]] |= BEING_CRACKED; if (numbytes_to_recover > 3) { - PrintAndLogDevice(FAILED, "The CSN requires > 3 byte bruteforce, not supported"); + PrintAndLogEx(FAILED, "The CSN requires > 3 byte bruteforce, not supported"); printvar("[-] CSN", item.csn, 8); printvar("[-] HASH1", key_index, 8); - PrintAndLogDevice(NORMAL, ""); + PrintAndLogEx(NORMAL, ""); //Before we exit, reset the 'BEING_CRACKED' to zero keytable[bytes_to_recover[0]] &= ~BEING_CRACKED; keytable[bytes_to_recover[1]] &= ~BEING_CRACKED; @@ -351,9 +351,9 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) { */ uint32_t endmask = 1 << 8 * numbytes_to_recover; - PrintAndLogDevice(NORMAL, "----------------------------"); + PrintAndLogEx(NORMAL, "----------------------------"); for (i = 0 ; i < numbytes_to_recover && numbytes_to_recover > 1; i++) - PrintAndLogDevice(INFO, "Bruteforcing byte %d", bytes_to_recover[i]); + PrintAndLogEx(INFO, "Bruteforcing byte %d", bytes_to_recover[i]); while (!found && !(brute & endmask)) { @@ -384,7 +384,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) { if (memcmp(calculated_MAC, item.mac, 4) == 0) { printf("\r\n"); for (i = 0 ; i < numbytes_to_recover; i++) { - PrintAndLogDevice(INFO, "%d: 0x%02x", bytes_to_recover[i], 0xFF & keytable[bytes_to_recover[i]]); + PrintAndLogEx(INFO, "%d: 0x%02x", bytes_to_recover[i], 0xFF & keytable[bytes_to_recover[i]]); } found = true; break; @@ -400,8 +400,8 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) { } if (!found) { - PrintAndLogDevice(NORMAL, "\n"); - PrintAndLogDevice(WARNING, "Failed to recover %d bytes using the following CSN", numbytes_to_recover); + PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(WARNING, "Failed to recover %d bytes using the following CSN", numbytes_to_recover); printvar("[!] CSN", item.csn, 8); errors++; @@ -411,7 +411,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) { keytable[bytes_to_recover[i]] |= CRACK_FAILED; } } else { - //PrintAndLogDevice(SUCCESS, "DES calcs: %u", brute); + //PrintAndLogEx(SUCCESS, "DES calcs: %u", brute); for (i = 0; i < numbytes_to_recover; i++) { keytable[bytes_to_recover[i]] &= 0xFF; keytable[bytes_to_recover[i]] |= CRACKED; @@ -466,8 +466,8 @@ int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[]) { mbedtls_des_setkey_enc(&ctx_e, key64_stdformat); mbedtls_des_crypt_ecb(&ctx_e, key64_negated, result); - PrintAndLogDevice(NORMAL, "\n"); - PrintAndLogDevice(SUCCESS, "-- High security custom key (Kcus) --"); + PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(SUCCESS, "-- High security custom key (Kcus) --"); printvar("[+] Standard format ", key64_stdformat, 8); printvar("[+] iClass format ", key64, 8); @@ -475,11 +475,11 @@ int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[]) { memcpy(master_key, key64, 8); if (memcmp(z_0, result, 4) != 0) { - PrintAndLogDevice(WARNING, "Failed to verify calculated master key (k_cus)! Something is wrong."); + PrintAndLogEx(WARNING, _RED_("Failed to verify") "calculated master key (k_cus)! Something is wrong."); return 1; } else { - PrintAndLogDevice(NORMAL, "\n"); - PrintAndLogDevice(SUCCESS, "Key verified ok!\n"); + PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(SUCCESS, _GREEN_("Key verified ok!")); } return 0; } @@ -502,10 +502,18 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) { for (i = 0 ; i * itemsize < dumpsize ; i++) { memcpy(attack, dump + i * itemsize, itemsize); errors += bruteforceItem(*attack, keytable); + if (errors) + break; } free(attack); t1 = msclock() - t1; - PrintAndLogDevice(SUCCESS, "time: %" PRIu64 " seconds", t1 / 1000); + PrintAndLogEx(SUCCESS, "time: %" PRIu64 " seconds", t1 / 1000); + + + if (errors) { + PrintAndLogEx(ERR, "loclass exiting. Try run " _YELLOW_("`hf iclass sim 2`") "again and collect new data"); + return 1; + } // Pick out the first 16 bytes of the keytable. // The keytable is now in 16-bit ints, where the upper 8 bits @@ -516,8 +524,10 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) { for (i = 0 ; i < 16 ; i++) { first16bytes[i] = keytable[i] & 0xFF; - if (!(keytable[i] & CRACKED)) - PrintAndLogDevice(WARNING, "Warning: we are missing byte %d, custom key calculation will fail...", i); + if (!(keytable[i] & CRACKED)) { + PrintAndLogEx(WARNING, "Warning: we are missing byte %d, custom key calculation will fail...", i); + return 1; + } } errors += calculateMasterKey(first16bytes, NULL); return errors; @@ -530,37 +540,14 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) { * @return */ int bruteforceFile(const char *filename, uint16_t keytable[]) { - FILE *f = fopen(filename, "rb"); - if (!f) { - PrintAndLogDevice(WARNING, "Failed to read from file '%s'", filename); - return 1; + + size_t dumplen = 0; + uint8_t *dump = NULL; + if (loadFile_safe(filename, "", (void **)&dump, &dumplen) != PM3_SUCCESS) { + return PM3_EFILE; } - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - fseek(f, 0, SEEK_SET); - - if (fsize <= 0) { - PrintAndLogDevice(ERR, "Error, when getting filesize"); - fclose(f); - return 1; - } - - uint8_t *dump = calloc(fsize, sizeof(uint8_t)); - if (!dump) { - PrintAndLogDevice(WARNING, "Failed to allocate memory"); - fclose(f); - return 2; - } - size_t bytes_read = fread(dump, 1, fsize, f); - - fclose(f); - - if (bytes_read < fsize) { - PrintAndLogDevice(WARNING, "Warning: could only read %d bytes (should be %d)", bytes_read, fsize); - } - - uint8_t res = bruteforceDump(dump, fsize, keytable); + uint8_t res = bruteforceDump(dump, dumplen, keytable); free(dump); return res; } @@ -582,39 +569,30 @@ int bruteforceFileNoKeys(const char *filename) { // TEST CODE BELOW // ---------------------------------------------------------------------------- static int _testBruteforce() { - int errors = 0; - if (true) { - // First test - PrintAndLogDevice(INFO, "Testing crack from dumpfile..."); - /** - Expected values for the dumpfile: - High Security Key Table + PrintAndLogEx(INFO, "Testing crack from dumpfile..."); - 00 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1 - 10 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21 - 20 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2 - 30 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C - 40 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6 - 50 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42 - 60 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95 - 70 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB + /** + Expected values for the dumpfile: + High Security Key Table - **** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 **** - **/ - uint16_t keytable[128] = {0}; + 00 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1 + 10 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21 + 20 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2 + 30 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C + 40 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6 + 50 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42 + 60 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95 + 70 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB - //Test a few variants - if (fileExists("iclass_dump.bin")) { - errors |= bruteforceFile("iclass_dump.bin", keytable); - } else if (fileExists("loclass/iclass_dump.bin")) { - errors |= bruteforceFile("loclass/iclass_dump.bin", keytable); - } else if (fileExists("client/loclass/iclass_dump.bin")) { - errors |= bruteforceFile("client/loclass/iclass_dump.bin", keytable); - } else { - PrintAndLogDevice(ERR, "Error: The file iclass_dump.bin was not found!"); - } + **** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 **** + **/ + uint16_t keytable[128] = {0}; + int errors = bruteforceFile("iclass_dump.bin", keytable); + if (errors) { + PrintAndLogEx(ERR, "Error: The file " _YELLOW_("iclass_dump.bin") "was not found!"); } + return errors; } @@ -627,20 +605,20 @@ static int _test_iclass_key_permutation() { permutekey_rev(testcase_output, testcase_output_rev); if (memcmp(testcase_output, testcase_output_correct, 8) != 0) { - PrintAndLogDevice(ERR, "Error with iclass key permute!"); + PrintAndLogEx(ERR, "Error with iclass key permute!"); printarr("testcase_output", testcase_output, 8); printarr("testcase_output_correct", testcase_output_correct, 8); return 1; } if (memcmp(testcase, testcase_output_rev, 8) != 0) { - PrintAndLogDevice(ERR, "Error with reverse iclass key permute"); + PrintAndLogEx(ERR, "Error with reverse iclass key permute"); printarr("testcase", testcase, 8); printarr("testcase_output_rev", testcase_output_rev, 8); return 1; } - PrintAndLogDevice(SUCCESS, "Iclass key permutation OK!"); + PrintAndLogEx(SUCCESS, "Iclass key permutation OK!"); return 0; } @@ -651,7 +629,7 @@ static int _testHash1() { hash1(csn, k); if (memcmp(k, expected, 8) != 0) { - PrintAndLogDevice(ERR, "Error with hash1!"); + PrintAndLogEx(ERR, "Error with hash1!"); printarr("calculated", k, 8); printarr("expected", expected, 8); return 1; @@ -660,8 +638,8 @@ static int _testHash1() { } int testElite() { - PrintAndLogDevice(INFO, "Testing iClass Elite functinality..."); - PrintAndLogDevice(INFO, "Testing hash2"); + PrintAndLogEx(INFO, "Testing iClass Elite functinality..."); + PrintAndLogEx(INFO, "Testing hash2"); uint8_t k_cus[8] = {0x5B, 0x7C, 0x62, 0xC4, 0x91, 0xC1, 0x1B, 0x39}; /** @@ -683,13 +661,13 @@ int testElite() { hash2(k_cus, keytable); printarr_human_readable("Hash2", keytable, 128); if (keytable[3] == 0xA1 && keytable[0x30] == 0xA3 && keytable[0x6F] == 0x95) { - PrintAndLogDevice(SUCCESS, "Hash2 looks fine..."); + PrintAndLogEx(SUCCESS, "Hash2 looks fine..."); } int errors = 0 ; - PrintAndLogDevice(INFO, "Testing hash1..."); + PrintAndLogEx(INFO, "Testing hash1..."); errors += _testHash1(); - PrintAndLogDevice(INFO, "Testing key diversification ..."); + PrintAndLogEx(INFO, "Testing key diversification ..."); errors += _test_iclass_key_permutation(); errors += _testBruteforce(); return errors; diff --git a/client/loclass/ikeys.c b/client/loclass/ikeys.c index 70605942f..f14e43eaf 100644 --- a/client/loclass/ikeys.c +++ b/client/loclass/ikeys.c @@ -63,6 +63,9 @@ From "Dismantling iclass": #include #include #include + +#include "commonutil.h" // ARRAYLEN + #include "fileutils.h" #include "cipherutils.h" #include "mbedtls/des.h" @@ -218,7 +221,7 @@ static void printbegin() { if (debug_print < 2) return; - PrintAndLogDevice(NORMAL, " | x| y|z0|z1|z2|z3|z4|z5|z6|z7|"); + PrintAndLogEx(NORMAL, " | x| y|z0|z1|z2|z3|z4|z5|z6|z7|"); } static void printState(const char *desc, uint64_t c) { @@ -281,7 +284,7 @@ void hash0(uint64_t c, uint8_t k[8]) { if (x & 1) //Check if x7 is 1 p = ~p; - if (debug_print >= 2) PrintAndLogDevice(DEBUG, "p:%02x", p); + if (debug_print >= 2) PrintAndLogEx(DEBUG, "p:%02x", p); BitstreamIn p_in = { &p, 8, 0 }; uint8_t outbuffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; @@ -426,7 +429,7 @@ static int testDES(Testcase testcase, mbedtls_des_context ctx_enc, mbedtls_des_c if (memcmp(testcase.uid, decrypted, 8) != 0) { //Decryption fail - PrintAndLogDevice(FAILED, "Encryption <-> Decryption FAIL"); + PrintAndLogEx(FAILED, "Encryption <-> Decryption FAIL"); printarr("Input", testcase.uid, 8); printarr("Decrypted", decrypted, 8); retval = 1; @@ -434,7 +437,7 @@ static int testDES(Testcase testcase, mbedtls_des_context ctx_enc, mbedtls_des_c if (memcmp(des_encrypted_csn, testcase.t_key, 8) != 0) { //Encryption fail - PrintAndLogDevice(FAILED, "Encryption != Expected result"); + PrintAndLogEx(FAILED, "Encryption != Expected result"); printarr("Output", des_encrypted_csn, 8); printarr("Expected", testcase.t_key, 8); retval = 1; @@ -444,7 +447,7 @@ static int testDES(Testcase testcase, mbedtls_des_context ctx_enc, mbedtls_des_c if (memcmp(div_key, testcase.div_key, 8) != 0) { //Key diversification fail - PrintAndLogDevice(FAILED, "Div key != expected result"); + PrintAndLogEx(FAILED, "Div key != expected result"); printarr(" csn ", testcase.uid, 8); printarr("{csn} ", des_encrypted_csn, 8); printarr("hash0 ", div_key, 8); @@ -469,13 +472,13 @@ static void des_checkParity(uint8_t *key) { bool parity = des_getParityBitFromKey(key[i]); if (parity != (key[i] & 0x1)) { fails++; - PrintAndLogDevice(FAILED, "parity1 fail, byte %d [%02x] was %d, should be %d", i, key[i], (key[i] & 0x1), parity); + PrintAndLogEx(FAILED, "parity1 fail, byte %d [%02x] was %d, should be %d", i, key[i], (key[i] & 0x1), parity); } } if (fails) { - PrintAndLogDevice(FAILED, "parity fails: %d", fails); + PrintAndLogEx(FAILED, "parity fails: %d", fails); } else { - PrintAndLogDevice(SUCCESS, "Key syntax is with parity bits inside each byte"); + PrintAndLogEx(SUCCESS, "Key syntax is with parity bits inside each byte"); } } @@ -554,15 +557,15 @@ static int testKeyDiversificationWithMasterkeyTestcases() { int i, error = 0; uint8_t empty[8] = {0}; - PrintAndLogDevice(INFO, "Testing encryption/decryption"); + PrintAndLogEx(INFO, "Testing encryption/decryption"); for (i = 0; memcmp(testcases + i, empty, 8); i++) error += testDES(testcases[i], ctx_enc, ctx_dec); if (error) - PrintAndLogDevice(FAILED, "%d errors occurred (%d testcases)", error, i); + PrintAndLogEx(FAILED, "%d errors occurred (%d testcases)", error, i); else - PrintAndLogDevice(SUCCESS, "Hashing seems to work (%d testcases)", i); + PrintAndLogEx(SUCCESS, "Hashing seems to work (%d testcases)", i); return error; } @@ -573,7 +576,7 @@ static void print64bits(const char *name, uint64_t val) { static uint64_t testCryptedCSN(uint64_t crypted_csn, uint64_t expected) { int retval = 0; uint8_t result[8] = {0}; - if (debug_print) PrintAndLogDevice(DEBUG, "debug_print %d", debug_print); + if (debug_print) PrintAndLogEx(DEBUG, "debug_print %d", debug_print); if (debug_print) print64bits(" {csn} ", crypted_csn); uint64_t crypted_csn_swapped = swapZvalues(crypted_csn); @@ -586,13 +589,13 @@ static uint64_t testCryptedCSN(uint64_t crypted_csn, uint64_t expected) { if (resultbyte != expected) { if (debug_print) { - PrintAndLogDevice(NORMAL, "\n"); - PrintAndLogDevice(FAILED, "FAIL!"); + PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(FAILED, "FAIL!"); print64bits(" expected ", expected); } retval = 1; } else { - if (debug_print) PrintAndLogDevice(SUCCESS, "[OK]"); + if (debug_print) PrintAndLogEx(SUCCESS, "[OK]"); } return retval; } @@ -611,7 +614,7 @@ static int testDES2(uint64_t csn, uint64_t expected) { print64bits(" expected ", expected); if (expected == crypt_csn) { - PrintAndLogDevice(SUCCESS, "OK"); + PrintAndLogEx(SUCCESS, "OK"); return 0; } else { return 1; @@ -626,13 +629,13 @@ static int testDES2(uint64_t csn, uint64_t expected) { static int doTestsWithKnownInputs() { // KSel from http://www.proxmark.org/forum/viewtopic.php?pid=10977#p10977 int errors = 0; - PrintAndLogDevice(SUCCESS, "Testing DES encryption"); + PrintAndLogEx(SUCCESS, "Testing DES encryption"); uint8_t key[8] = {0x6c, 0x8d, 0x44, 0xf9, 0x2a, 0x2d, 0x01, 0xbf}; mbedtls_des_setkey_enc(&ctx_enc, key); testDES2(0xbbbbaaaabbbbeeee, 0xd6ad3ca619659e6b); - PrintAndLogDevice(SUCCESS, "Testing hashing algorithm"); + PrintAndLogEx(SUCCESS, "Testing hashing algorithm"); errors += testCryptedCSN(0x0102030405060708, 0x0bdd6512073c460a); errors += testCryptedCSN(0x1020304050607080, 0x0208211405f3381f); @@ -645,70 +648,58 @@ static int doTestsWithKnownInputs() { errors += testCryptedCSN(0x14e2adfc5bb7e134, 0x6ac90c6508bd9ea3); if (errors) - PrintAndLogDevice(FAILED, "%d errors occurred (9 testcases)", errors); + PrintAndLogEx(FAILED, "%d errors occurred (9 testcases)", errors); else - PrintAndLogDevice(SUCCESS, "Hashing seems to work (9 testcases)"); + PrintAndLogEx(SUCCESS, "Hashing seems to work (9 testcases)"); return errors; } -static bool readKeyFile(uint8_t key[8]) { - bool retval = false; - //Test a few variants - char filename[30] = {0}; +static bool readKeyFile(uint8_t *key, size_t keylen) { - if (fileExists("iclass_key.bin")) { - sprintf(filename, "%s.bin", "iclass_key"); - } else if (fileExists("loclass/iclass_key.bin")) { - sprintf(filename, "%s.bin", "loclass/iclass_key"); - } else if (fileExists("client/loclass/iclass_key.bin")) { - sprintf(filename, "%s.bin", "client/loclass/iclass_key"); + size_t len = 0; + uint8_t *keyptr = NULL; + if (loadFile_safe("iclass_key.bin", "", (void **)&keyptr, &len) != PM3_SUCCESS) { + return false; } - if (strlen(filename) == 0) - return retval; + if (keylen != len) { + return false; + } - FILE *f = fopen(filename, "rb"); - if (!f) - return retval; - - size_t bytes_read = fread(key, sizeof(uint8_t), 8, f); - if (bytes_read == 8) - retval = true; - - fclose(f); - return retval; + memcpy(key, keyptr, keylen); + return true; } int doKeyTests(uint8_t debuglevel) { debug_print = debuglevel; - PrintAndLogDevice(INFO, "Checking if the master key is present (iclass_key.bin)..."); + PrintAndLogEx(INFO, "Checking if the master key is present (iclass_key.bin)..."); uint8_t key[8] = {0}; - if (!readKeyFile(key)) { - PrintAndLogDevice(FAILED, "Master key not present, will not be able to do all testcases"); + if (readKeyFile(key, sizeof(key)) == false) { + PrintAndLogEx(FAILED, "Master key not present, will not be able to do all testcases"); } else { //Test if it's the right key... uint8_t i; uint8_t j = 0; - for (i = 0; i < sizeof(key); i++) + for (i = 0; i < ARRAYLEN(key); i++) j += key[i]; if (j != 185) { - PrintAndLogDevice(INFO, "A key was loaded, but it does not seem to be the correct one. Aborting these tests"); + PrintAndLogEx(INFO, "A key was loaded, but it does not seem to be the correct one. Aborting these tests"); } else { - PrintAndLogDevice(SUCCESS, "Key present"); - PrintAndLogDevice(SUCCESS, "Checking key parity..."); + PrintAndLogEx(SUCCESS, "Key present"); + PrintAndLogEx(SUCCESS, "Checking key parity..."); des_checkParity(key); mbedtls_des_setkey_enc(&ctx_enc, key); mbedtls_des_setkey_dec(&ctx_dec, key); // Test hashing functions - PrintAndLogDevice(SUCCESS, "The following tests require the correct 8-byte master key"); + PrintAndLogEx(SUCCESS, "The following tests require the correct 8-byte master key"); testKeyDiversificationWithMasterkeyTestcases(); } } - PrintAndLogDevice(SUCCESS, "Testing key diversification with non-sensitive keys..."); + PrintAndLogEx(SUCCESS, "Testing key diversification with non-sensitive keys..."); doTestsWithKnownInputs(); return 0; } diff --git a/client/loclass/loclass_information.txt b/client/loclass/loclass_information.txt deleted file mode 100644 index 307d28203..000000000 --- a/client/loclass/loclass_information.txt +++ /dev/null @@ -1,12 +0,0 @@ -2017-08-19 iceman, - -iclass_dump.bin -=============== -The file iclass_dump.bin contains CSN's mac results from 128 CSNs. -Hence when running the test mode, - 'hf iclass loclass t' -it shows a long output from the bruteforce test. - -iclass_key.bin -============== -The file iclass_key.bin is where you add the AA1 master key in order for the proxmark3 client to use it with the loclass commands diff --git a/client/lualibs/emulator.lua b/client/lualibs/emulator.lua index af92d5cf8..d43f5da92 100644 --- a/client/lualibs/emulator.lua +++ b/client/lualibs/emulator.lua @@ -12,7 +12,7 @@ local Emulator = { function Emulator:set_mem (data, clear_first) if clear_first then -- Clear out the emulator memory first - local memclrCmd = Command:newMIX{cmd = cmds.CMD_MIFARE_EML_MEMCLR} + local memclrCmd = Command:newMIX{cmd = cmds.CMD_HF_MIFARE_EML_MEMCLR} local _, err = memclrCmd:sendMIX() if err then @@ -30,7 +30,7 @@ function Emulator:set_mem (data, clear_first) -- arg1: start block number -- arg2: block count - local memsetCmd = Command:newMIX{cmd = cmds.CMD_MIFARE_EML_MEMSET, + local memsetCmd = Command:newMIX{cmd = cmds.CMD_HF_MIFARE_EML_MEMSET, data = utils.hexlify(cur_out_block), arg1 = i * self.BLOCK_COUNT, arg2 = self.BLOCK_COUNT} @@ -57,7 +57,7 @@ function Emulator:get_mem (size) for i = 0, (size / (MAX_BLOCKS * 16)) do -- arg1: start block number -- arg2: block count (max 4) - local getmemCmd = Command:newMIX{cmd = cmds.CMD_MIFARE_EML_MEMGET, + local getmemCmd = Command:newMIX{cmd = cmds.CMD_HF_MIFARE_EML_MEMGET, arg1 = i * MAX_BLOCKS, arg2 = MAX_BLOCKS, arg3 = 0} diff --git a/client/lualibs/read14a.lua b/client/lualibs/read14a.lua index 3bf243235..3f0d71dde 100644 --- a/client/lualibs/read14a.lua +++ b/client/lualibs/read14a.lua @@ -86,7 +86,7 @@ local function read14443a(dont_disconnect, no_rats) local command, result, info, err, data command = Command:newMIX{ - cmd = cmds.CMD_READER_ISO_14443a, + cmd = cmds.CMD_HF_ISO14443A_READER, arg1 = ISO14A_COMMAND.ISO14A_CONNECT } @@ -132,7 +132,7 @@ end -- Sends an instruction to do nothing, only disconnect local function disconnect14443a() - local c = Command:newMIX{cmd = cmds.CMD_READER_ISO_14443a} + local c = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER} -- We can ignore the response here, no ACK is returned for this command -- Check /armsrc/iso14443a.c, ReaderIso14443a() for details return c:sendMIX(true) diff --git a/client/lualibs/read14b.lua b/client/lualibs/read14b.lua index 67d2bd469..aace09827 100644 --- a/client/lualibs/read14b.lua +++ b/client/lualibs/read14b.lua @@ -28,7 +28,7 @@ local ISO14B_COMMAND = { ISO14B_SELECT_SR = 0x80, } -local function parse1443b(data) +local function parse14443b(data) --[[ Based on this struct : @@ -70,7 +70,7 @@ local function read14443b(disconnect) end command = Command:newMIX{ - cmd = cmds.CMD_ISO_14443B_COMMAND, + cmd = cmds.CMD_HF_ISO14443B_COMMAND, arg1 = flags } @@ -79,7 +79,7 @@ local function read14443b(disconnect) local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result) if arg0 == 0 then data = string.sub(result, count) - info, err = parse1443b(data) + info, err = parse14443b(data) else err = 'iso14443b card select failed' end @@ -111,13 +111,13 @@ end --- -- turns on the HF field. local function connect14443b() - local c = Command:newMIX{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = ISO14B_COMMAND.ISO14B_CONNECT} + local c = Command:newMIX{cmd = cmds.CMD_HF_ISO14443B_COMMAND, arg1 = ISO14B_COMMAND.ISO14B_CONNECT} return c:sendMIX(true) end --- -- Sends an instruction to do nothing, only disconnect local function disconnect14443b() - local c = Command:newMIX{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = ISO14B_COMMAND.ISO14B_DISCONNECT} + local c = Command:newMIX{cmd = cmds.CMD_HF_ISO14443B_COMMAND, arg1 = ISO14B_COMMAND.ISO14B_DISCONNECT} -- We can ignore the response here, no ACK is returned for this command -- Check /armsrc/iso14443b.c, ReaderIso14443b() for details return c:sendMIX(true) @@ -126,7 +126,7 @@ end local library = { read = read14443b, waitFor14443b = waitFor14443b, - parse1443b = parse1443b, + parse14443b = parse14443b, connect = connect14443b, disconnect = disconnect14443b, ISO14B_COMMAND = ISO14B_COMMAND, diff --git a/client/lualibs/read15.lua b/client/lualibs/read15.lua index a70641186..112c12d94 100644 --- a/client/lualibs/read15.lua +++ b/client/lualibs/read15.lua @@ -95,7 +95,7 @@ local function read15693(slow, dont_readresponse) data = utils.Crc15("260100") command = Command:newMIX{ - cmd = cmds.CMD_ISO_15693_COMMAND, + cmd = cmds.CMD_HF_ISO15693_COMMAND, arg1 = #data / 2, arg2 = 1, arg3 = 1, @@ -144,7 +144,7 @@ end -- Sends an instruction to do nothing, only disconnect local function disconnect15693() - local c = Command:newMIX{cmd = cmds.CMD_ISO_15693_COMMAND} + local c = Command:newMIX{cmd = cmds.CMD_HF_ISO15693_COMMAND} -- We can ignore the response here, no ACK is returned for this command -- Check /armsrc/iso14443a.c, ReaderIso14443a() for details return c:sendMIX(true) diff --git a/client/scripts/14araw.lua b/client/luascripts/14araw.lua similarity index 98% rename from client/scripts/14araw.lua rename to client/luascripts/14araw.lua index 3bc5c060e..30ab5e497 100644 --- a/client/scripts/14araw.lua +++ b/client/luascripts/14araw.lua @@ -166,7 +166,7 @@ function sendRaw(rawdata, options) flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC end - local command = Command:newMIX{cmd = cmds.CMD_READER_ISO_14443a, + local command = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER, arg1 = flags, -- Send raw -- arg2 contains the length, which is half the length -- of the ASCII-string rawdata diff --git a/client/scripts/Legic_clone.lua b/client/luascripts/Legic_clone.lua similarity index 100% rename from client/scripts/Legic_clone.lua rename to client/luascripts/Legic_clone.lua diff --git a/client/scripts/amiibo.lua b/client/luascripts/amiibo.lua similarity index 97% rename from client/scripts/amiibo.lua rename to client/luascripts/amiibo.lua index 73366de02..10ede4008 100644 --- a/client/scripts/amiibo.lua +++ b/client/luascripts/amiibo.lua @@ -16,7 +16,7 @@ local luamiibo = luamiibo_open() local function nfc_read_amiibo () local command = Command:newMIX{ - cmd = cmds.CMD_MIFAREU_READCARD, + cmd = cmds.CMD_HF_MIFAREU_READCARD, arg1 = 0, arg2 = 135 } @@ -90,7 +90,7 @@ local function emulate_amiibo (amiibo_data) -- Begin simulating NTAG215 local simCmd = Command:newMIX{ - cmd = cmds.CMD_SIMULATE_TAG_ISO_14443a, + cmd = cmds.CMD_HF_ISO14443A_SIMULATE, arg1 = 7, arg2 = uid_first, arg3 = uid_second @@ -205,7 +205,7 @@ local function main(args) return end - parsed_tag = reader.parse1443a(tag) + parsed_tag = reader.parse14443a(tag) print('Tag type:', parsed_tag.name) print('Tag UID:', parsed_tag.uid) print('Tag len:', tag:len()) diff --git a/client/scripts/brutesim.lua b/client/luascripts/brutesim.lua similarity index 100% rename from client/scripts/brutesim.lua rename to client/luascripts/brutesim.lua diff --git a/client/scripts/calc_di.lua b/client/luascripts/calc_di.lua similarity index 100% rename from client/scripts/calc_di.lua rename to client/luascripts/calc_di.lua diff --git a/client/scripts/calc_ev1_it.lua b/client/luascripts/calc_ev1_it.lua similarity index 100% rename from client/scripts/calc_ev1_it.lua rename to client/luascripts/calc_ev1_it.lua diff --git a/client/scripts/calc_mizip.lua b/client/luascripts/calc_mizip.lua similarity index 100% rename from client/scripts/calc_mizip.lua rename to client/luascripts/calc_mizip.lua diff --git a/client/scripts/calypso.lua b/client/luascripts/calypso.lua similarity index 99% rename from client/scripts/calypso.lua rename to client/luascripts/calypso.lua index de512c5c8..afb466109 100644 --- a/client/scripts/calypso.lua +++ b/client/luascripts/calypso.lua @@ -114,7 +114,7 @@ local function calypso_send_cmd_raw(data, ignoreresponse ) data = data or "00" command = Command:newMIX{ - cmd = cmds.CMD_ISO_14443B_COMMAND, + cmd = cmds.CMD_HF_ISO14443B_COMMAND, arg1 = flags, arg2 = #data/2, -- LEN of data, half the length of the ASCII-string hex string data = data} -- data bytes (commands etc) diff --git a/client/scripts/cmdline.lua b/client/luascripts/cmdline.lua old mode 100644 new mode 100755 similarity index 82% rename from client/scripts/cmdline.lua rename to client/luascripts/cmdline.lua index dc1e752c1..baa76eed6 --- a/client/scripts/cmdline.lua +++ b/client/luascripts/cmdline.lua @@ -1,5 +1,8 @@ +#!/usr/bin/env -S pm3 -l + --[[ A sampe script file on how to implement at cmd line inteface. +It also demonstrates how the script can be used with a shebang. --]] print("This is how a cmd-line interface could be implemented\nPrint 'exit' to exit.\n") diff --git a/client/scripts/didump.lua b/client/luascripts/didump.lua similarity index 99% rename from client/scripts/didump.lua rename to client/luascripts/didump.lua index d5ac6f873..a9228c7b5 100644 --- a/client/scripts/didump.lua +++ b/client/luascripts/didump.lua @@ -475,7 +475,7 @@ local function readblock( blockno, key ) -- Read block N local keytype = '00' local data = ('%02x%s%s'):format(blockno, keytype, key) - local c = Command:newNG{cmd = cmds.CMD_MIFARE_READBL, data = data} + local c = Command:newNG{cmd = cmds.CMD_HF_MIFARE_READBL, data = data} local b, err = getblockdata(c:sendNG(false)) if not b then return oops(err) end return b diff --git a/client/scripts/dumptoemul-mfu.lua b/client/luascripts/dumptoemul-mfu.lua similarity index 100% rename from client/scripts/dumptoemul-mfu.lua rename to client/luascripts/dumptoemul-mfu.lua diff --git a/client/scripts/dumptoemul.lua b/client/luascripts/dumptoemul.lua similarity index 93% rename from client/scripts/dumptoemul.lua rename to client/luascripts/dumptoemul.lua index e364ccc8b..80653a14a 100644 --- a/client/scripts/dumptoemul.lua +++ b/client/luascripts/dumptoemul.lua @@ -14,7 +14,7 @@ example = [[ script run dumptoemul -i dumpdata-foobar.bin ]] usage = [[ -script run dumptoemul [-i ] [-o ] +_script run dumptoemul [-i ] [-o ] Arguments: -h This help @@ -108,8 +108,11 @@ local function main(args) if infile == nil then return oops('Could not read file ', input) end - local dumpdata = readdump(infile) + + local dumpdata = readdump(infile) -- The hex-data is now in ascii-format, + if dumpdata == NIL then return oops('Dumpfle not loaded') end + -- But first, check the uid local uid = string.sub(dumpdata, 1, 8) @@ -117,6 +120,8 @@ local function main(args) -- Format some linebreaks dumpdata = convert_to_emulform(dumpdata) + if dumpdata == NIL then return oops('Dumpfle not loaded') end + local outfile = io.open(output, 'w') if outfile == nil then diff --git a/client/scripts/e.lua b/client/luascripts/e.lua similarity index 100% rename from client/scripts/e.lua rename to client/luascripts/e.lua diff --git a/client/scripts/emul2dump.lua b/client/luascripts/emul2dump.lua similarity index 100% rename from client/scripts/emul2dump.lua rename to client/luascripts/emul2dump.lua diff --git a/client/scripts/emul2html.lua b/client/luascripts/emul2html.lua similarity index 100% rename from client/scripts/emul2html.lua rename to client/luascripts/emul2html.lua diff --git a/client/scripts/formatMifare.lua b/client/luascripts/formatMifare.lua similarity index 100% rename from client/scripts/formatMifare.lua rename to client/luascripts/formatMifare.lua diff --git a/client/scripts/hf_read.lua b/client/luascripts/hf_read.lua similarity index 100% rename from client/scripts/hf_read.lua rename to client/luascripts/hf_read.lua diff --git a/client/scripts/htmldump.lua b/client/luascripts/htmldump.lua similarity index 100% rename from client/scripts/htmldump.lua rename to client/luascripts/htmldump.lua diff --git a/client/scripts/iso15_magic.lua b/client/luascripts/iso15_magic.lua similarity index 100% rename from client/scripts/iso15_magic.lua rename to client/luascripts/iso15_magic.lua diff --git a/client/scripts/legic.lua b/client/luascripts/legic.lua similarity index 100% rename from client/scripts/legic.lua rename to client/luascripts/legic.lua diff --git a/client/scripts/legic_buffer2card.lua b/client/luascripts/legic_buffer2card.lua similarity index 100% rename from client/scripts/legic_buffer2card.lua rename to client/luascripts/legic_buffer2card.lua diff --git a/client/scripts/lf_bulk.lua b/client/luascripts/lf_bulk.lua similarity index 100% rename from client/scripts/lf_bulk.lua rename to client/luascripts/lf_bulk.lua diff --git a/client/scripts/mfkeys.lua b/client/luascripts/mfckeys.lua similarity index 95% rename from client/scripts/mfkeys.lua rename to client/luascripts/mfckeys.lua index 65f50eb9c..128967c37 100644 --- a/client/scripts/mfkeys.lua +++ b/client/luascripts/mfckeys.lua @@ -9,7 +9,7 @@ Copyright (C) 2013 m h swende --]] local cmds = require('commands') -local keylist = require('mf_default_keys') +local keylist = require('mfc_default_keys') local lib14a = require('read14a') local getopt = require('getopt') local utils = require('utils') @@ -19,9 +19,9 @@ author = "Holiman" version = 'v1.0.1' desc = ("This script implements Mifare check keys.\ It utilises a large list of default keys (currently %d keys).\ -If you want to add more, just put them inside /lualibs/mf_default_keys.lua\n"):format(#keylist) +If you want to add more, just put them inside /lualibs/mfc_default_keys.lua\n"):format(#keylist) example = [[ - 1. script run mfkeys + 1. script run mfckeys ]] usage = [[ Arguments: @@ -54,7 +54,7 @@ end -- waits for answer from pm3 device local function checkCommand(response) if not response then - print("Timeout while waiting for response. Increase TIMEOUT in mfkeys.lua to wait longer") + print("Timeout while waiting for response. Increase TIMEOUT in mfckeys.lua to wait longer") return nil, "Timeout while waiting for device to respond" end @@ -90,7 +90,7 @@ local function checkBlock(blockno, testkeys, keytype) print(("Testing block %d, keytype %d, with %d keys"):format(blockno, keytype, chunksize)) - local c = Command:newNG{cmd = cmds.CMD_MIFARE_CHKKEYS, data = d0..d1} + local c = Command:newNG{cmd = cmds.CMD_HF_MIFARE_CHKKEYS, data = d0..d1} key, err = checkCommand(c:sendNG(false)) if key then return key, blockno end @@ -230,7 +230,7 @@ local function perform_check(numsectors) local end_time = os.time() print('') - print('[+] mfkeys - Checkkey execution time: '..os.difftime(end_time, start_time)..' sec') + print('[+] mfckeys - Checkkey execution time: '..os.difftime(end_time, start_time)..' sec') core.fast_push_mode(false) diff --git a/client/scripts/mifare_access.lua b/client/luascripts/mifare_access.lua similarity index 100% rename from client/scripts/mifare_access.lua rename to client/luascripts/mifare_access.lua diff --git a/client/scripts/mifare_autopwn.lua b/client/luascripts/mifare_autopwn.lua similarity index 100% rename from client/scripts/mifare_autopwn.lua rename to client/luascripts/mifare_autopwn.lua diff --git a/client/scripts/mifareplus.lua b/client/luascripts/mifareplus.lua similarity index 99% rename from client/scripts/mifareplus.lua rename to client/luascripts/mifareplus.lua index a81be26d8..f49ad95e5 100644 --- a/client/scripts/mifareplus.lua +++ b/client/luascripts/mifareplus.lua @@ -74,7 +74,7 @@ local function sendRaw(rawdata, crc, power) flags = flags + lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT end - local command = Command:newMIX{cmd = cmds.CMD_READER_ISO_14443a, + local command = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER, arg1 = flags, -- Send raw arg2 = string.len(rawdata) / 2, -- arg2 contains the length, which is half the length of the ASCII-string rawdata data = rawdata diff --git a/client/scripts/ndef_dump.lua b/client/luascripts/ndef_dump.lua similarity index 97% rename from client/scripts/ndef_dump.lua rename to client/luascripts/ndef_dump.lua index 856053207..cb4be467b 100644 --- a/client/scripts/ndef_dump.lua +++ b/client/luascripts/ndef_dump.lua @@ -2,7 +2,8 @@ local getopt = require('getopt') local cmds = require('commands') local lib14a = require('read14a') local utils = require('utils') - +-- +-- Refactored iceman, 2019 copyright = '' author = 'Martin Holst Swende & Asper' version = 'v1.0.1' @@ -69,7 +70,7 @@ end -- -- Sends an instruction to do nothing, only disconnect function disconnect() - local command = Command:newMIX{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0,} + local command = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER, arg1 = 0,} -- We can ignore the response here, no ACK is returned for this command -- Check /armsrc/iso14443a.c, ReaderIso14443a() for details return command:sendMIX(true) @@ -93,7 +94,7 @@ end -- @return nil, errormessage if unsuccessfull local function getBlock(blockno) local block, err - local c = Command:newMIX{cmd = cmds.CMD_MIFAREU_READBL, arg1 = blockno, data = 0} + local c = Command:newMIX{cmd = cmds.CMD_HF_MIFAREU_READBL, arg1 = blockno, data = 0} block, err = getblockdata(c:sendMIX(false)) if not block then return oops(err) end diff --git a/client/scripts/ntag_3d.lua b/client/luascripts/ntag_3d.lua similarity index 99% rename from client/scripts/ntag_3d.lua rename to client/luascripts/ntag_3d.lua index ff2c68d0f..869590cf2 100644 --- a/client/scripts/ntag_3d.lua +++ b/client/luascripts/ntag_3d.lua @@ -223,7 +223,7 @@ local function configure_magic_ntag(uid) -- -p == set pwd -- -a == set pack args =('-t 12 -u %s -p %08X -a %04X'):format(uid, pwd, pack) - require('../scripts/mfu_magic') + require('mfu_magic') -- Set back args. Not that it's used, just for the karma... args = myargs diff --git a/client/scripts/parameters.lua b/client/luascripts/parameters.lua similarity index 100% rename from client/scripts/parameters.lua rename to client/luascripts/parameters.lua diff --git a/client/scripts/read_pwd_mem.lua b/client/luascripts/read_pwd_mem.lua similarity index 100% rename from client/scripts/read_pwd_mem.lua rename to client/luascripts/read_pwd_mem.lua diff --git a/client/scripts/remagic.lua b/client/luascripts/remagic.lua similarity index 100% rename from client/scripts/remagic.lua rename to client/luascripts/remagic.lua diff --git a/client/scripts/test_t55x7.lua b/client/luascripts/test_t55x7.lua similarity index 99% rename from client/scripts/test_t55x7.lua rename to client/luascripts/test_t55x7.lua index c06d2848a..0fc112ea7 100644 --- a/client/scripts/test_t55x7.lua +++ b/client/luascripts/test_t55x7.lua @@ -260,7 +260,7 @@ local function test(modulation) local data = ('%s%s%s%s'):format(utils.SwapEndiannessStr(p_config_cmd, 32), password, block, flags) - local wc = Command:newNG{cmd = cmds.CMD_T55XX_WRITE_BLOCK, data = data} + local wc = Command:newNG{cmd = cmds.CMD_LF_T55XX_WRITEBL, data = data} local response, err = wc:sendNG(false, TIMEOUT) if not response then return oops(err) end diff --git a/client/scripts/test_t55x7_ask.lua b/client/luascripts/test_t55x7_ask.lua similarity index 97% rename from client/scripts/test_t55x7_ask.lua rename to client/luascripts/test_t55x7_ask.lua index ecf02346b..bb232a6fd 100644 --- a/client/scripts/test_t55x7_ask.lua +++ b/client/luascripts/test_t55x7_ask.lua @@ -117,7 +117,7 @@ local function test() dbg(('lf t55xx write b 0 d %s'):format(config)) local data = ('%s%s%s%s'):format(utils.SwapEndiannessStr(config, 32), password, block, flags) - local wc = Command:newNG{cmd = cmds.CMD_T55XX_WRITE_BLOCK, data = data} + local wc = Command:newNG{cmd = cmds.CMD_LF_T55XX_WRITEBL, data = data} local response, err = wc:sendNG(false, TIMEOUT) if not response then return oops(err) end diff --git a/client/scripts/test_t55x7_bi.lua b/client/luascripts/test_t55x7_bi.lua similarity index 97% rename from client/scripts/test_t55x7_bi.lua rename to client/luascripts/test_t55x7_bi.lua index 0b0239717..49ee4882a 100644 --- a/client/scripts/test_t55x7_bi.lua +++ b/client/luascripts/test_t55x7_bi.lua @@ -112,7 +112,7 @@ local function test() local data = ('%s%s%s%s'):format(utils.SwapEndiannessStr(config, 32), password, block, flags) - local wc = Command:newNG{cmd = cmds.CMD_T55XX_WRITE_BLOCK, data = data} + local wc = Command:newNG{cmd = cmds.CMD_LF_T55XX_WRITEBL, data = data} local response, err = wc:sendNG(false, TIMEOUT) if not response then return oops(err) end diff --git a/client/scripts/test_t55x7_fsk.lua b/client/luascripts/test_t55x7_fsk.lua similarity index 97% rename from client/scripts/test_t55x7_fsk.lua rename to client/luascripts/test_t55x7_fsk.lua index abf4692d7..c755042b1 100644 --- a/client/scripts/test_t55x7_fsk.lua +++ b/client/luascripts/test_t55x7_fsk.lua @@ -113,7 +113,7 @@ local function test(modulation) dbg(('lf t55xx write b 0 d %s'):format(config)) local data = ('%s%s%s%s'):format(utils.SwapEndiannessStr(config, 32), password, block, flags) - local wc = Command:newNG{cmd = cmds.CMD_T55XX_WRITE_BLOCK, data = data} + local wc = Command:newNG{cmd = cmds.CMD_LF_T55XX_WRITEBL, data = data} local response, err = wc:sendNG(false, TIMEOUT) if not response then return oops(err) end else diff --git a/client/scripts/test_t55x7_psk.lua b/client/luascripts/test_t55x7_psk.lua similarity index 97% rename from client/scripts/test_t55x7_psk.lua rename to client/luascripts/test_t55x7_psk.lua index 2c0efa163..10fecd549 100644 --- a/client/scripts/test_t55x7_psk.lua +++ b/client/luascripts/test_t55x7_psk.lua @@ -119,7 +119,7 @@ local function test(modulation) local data = ('%s%s%s%s'):format(utils.SwapEndiannessStr(config, 32), password, block, flags) - local wc = Command:newNG{cmd = cmds.CMD_T55XX_WRITE_BLOCK, data = data} + local wc = Command:newNG{cmd = cmds.CMD_LF_T55XX_WRITEBL, data = data} local response, err = wc:sendNG(false, TIMEOUT) if not response then return oops(err) end else diff --git a/client/scripts/tnp3clone.lua b/client/luascripts/tnp3clone.lua similarity index 97% rename from client/scripts/tnp3clone.lua rename to client/luascripts/tnp3clone.lua index 18dd6edfb..58bb5d338 100644 --- a/client/scripts/tnp3clone.lua +++ b/client/luascripts/tnp3clone.lua @@ -77,7 +77,7 @@ local function readblock( blocknum, keyA ) -- Read block N local keytype = '00' local data = ('%02x%s%s'):format(blocknum, keytype, keyA) - local c = Command:newNG{cmd = cmds.CMD_MIFARE_READBL, data = data} + local c = Command:newNG{cmd = cmds.CMD_HF_MIFARE_READBL, data = data} local b, err = getblockdata(c:sendNG(false)) if not b then return oops(err) end return b @@ -88,7 +88,7 @@ local function readmagicblock( blocknum ) -- Read block N local CSETBLOCK_SINGLE_OPERATION = 0x1F local c = Command:newMIX{ - cmd = cmds.CMD_MIFARE_CGETBLOCK + cmd = cmds.CMD_HF_MIFARE_CGETBL , arg1 = CSETBLOCK_SINGLE_OPERATION , arg3 = blocknum } diff --git a/client/scripts/tnp3dump.lua b/client/luascripts/tnp3dump.lua similarity index 97% rename from client/scripts/tnp3dump.lua rename to client/luascripts/tnp3dump.lua index 0faadecaf..488d2f5f9 100644 --- a/client/scripts/tnp3dump.lua +++ b/client/luascripts/tnp3dump.lua @@ -169,7 +169,7 @@ local function main(args) local blockno = '00' local keytype = '00' local data = ('%s%s%s'):format(blockno, keytype, keyA) - cmd = Command:newNG{cmd = cmds.CMD_MIFARE_READBL, data = data} + cmd = Command:newNG{cmd = cmds.CMD_HF_MIFARE_READBL, data = data} block0, err = getblockdata(cmd:sendNG(false)) if not block0 then return oops(err) end @@ -179,7 +179,7 @@ local function main(args) dbg('Reading block 1') local blockno = '01' data = ('%s%s%s'):format(blockno, keytype, keyA) - cmd = Command:newNG{cmd = cmds.CMD_MIFARE_READBL, data = data} + cmd = Command:newNG{cmd = cmds.CMD_HF_MIFARE_READBL, data = data} block1, err = getblockdata(cmd:sendNG(false)) if not block1 then return oops(err) end @@ -208,7 +208,7 @@ local function main(args) pos = (math.floor( blockNo / 4 ) * 12)+1 key = akeys:sub(pos, pos + 11 ) data = ('%02x%s%s'):format(blockNo, keytype, key) - cmd = Command:newNG{cmd = cmds.CMD_MIFARE_READBL, data = data} + cmd = Command:newNG{cmd = cmds.CMD_HF_MIFARE_READBL, data = data} local blockdata, err = getblockdata(cmd:sendNG(false)) if not blockdata then return oops(err) end diff --git a/client/scripts/tnp3sim.lua b/client/luascripts/tnp3sim.lua similarity index 99% rename from client/scripts/tnp3sim.lua rename to client/luascripts/tnp3sim.lua index f1b58f95e..014474416 100644 --- a/client/scripts/tnp3sim.lua +++ b/client/luascripts/tnp3sim.lua @@ -246,7 +246,7 @@ local function LoadEmulator(uid, blocks) io.write( _..',') io.flush() core.clearCommandBuffer() - cmd = Command:newMIX{cmd = cmds.CMD_MIFARE_EML_MEMSET, arg1 = _ ,arg2 = 1,arg3 = 16, data = blockdata} + cmd = Command:newMIX{cmd = cmds.CMD_HF_MIFARE_EML_MEMSET, arg1 = _ ,arg2 = 1,arg3 = 16, data = blockdata} local err, msg = cmd:sendMIX(true) if err == nil then return err, msg end end diff --git a/client/scripts/tracetest.lua b/client/luascripts/tracetest.lua similarity index 100% rename from client/scripts/tracetest.lua rename to client/luascripts/tracetest.lua diff --git a/client/scripts/ufodump.lua b/client/luascripts/ufodump.lua similarity index 98% rename from client/scripts/ufodump.lua rename to client/luascripts/ufodump.lua index 0f6a51a76..140652492 100644 --- a/client/scripts/ufodump.lua +++ b/client/luascripts/ufodump.lua @@ -96,7 +96,7 @@ function sendRaw(rawdata, options) + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC + lib14a.ISO14A_COMMAND.ISO14A_NO_RATS - local command = Command:newMIX{cmd = cmds.CMD_READER_ISO_14443a, + local command = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER, arg1 = flags, -- Send raw -- arg2 contains the length, which is half the length -- of the ASCII-string rawdata diff --git a/client/scripts/ul_uid.lua b/client/luascripts/ul_uid.lua similarity index 100% rename from client/scripts/ul_uid.lua rename to client/luascripts/ul_uid.lua diff --git a/client/mifare/mad.c b/client/mifare/mad.c index 47b7cb70a..5cf3e1852 100644 --- a/client/mifare/mad.c +++ b/client/mifare/mad.c @@ -10,6 +10,8 @@ #include "mad.h" #include "ui.h" +#include "commonutil.h" // ARRAYLEN + #include "crc.h" #include "util.h" diff --git a/client/mifare/mad.h b/client/mifare/mad.h index d1028e06a..ce5ed4131 100644 --- a/client/mifare/mad.h +++ b/client/mifare/mad.h @@ -11,9 +11,7 @@ #ifndef _MAD_H_ #define _MAD_H_ -#include -#include -#include +#include "common.h" typedef struct { uint16_t AID; diff --git a/client/mifare/mfkey.c b/client/mifare/mfkey.c index 178da7fe4..bdccd302e 100644 --- a/client/mifare/mfkey.c +++ b/client/mifare/mfkey.c @@ -11,6 +11,8 @@ //----------------------------------------------------------------------------- #include "mfkey.h" +#include "crapto1/crapto1.h" + // MIFARE int compare_uint64(const void *a, const void *b) { if (*(uint64_t *)b == *(uint64_t *)a) return 0; diff --git a/client/mifare/mfkey.h b/client/mifare/mfkey.h index 4af5175a1..36ca8ed11 100644 --- a/client/mifare/mfkey.h +++ b/client/mifare/mfkey.h @@ -13,11 +13,8 @@ #ifndef MFKEY_H #define MFKEY_H -#include -#include -#include +#include "common.h" #include "mifare.h" -#include "crapto1/crapto1.h" uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint32_t ar, uint64_t par_info, uint64_t ks_info, uint64_t **keys); bool mfkey32(nonces_t data, uint64_t *outputkey); diff --git a/client/mifare/mifare4.c b/client/mifare/mifare4.c index b172e5131..5cdca2e14 100644 --- a/client/mifare/mifare4.c +++ b/client/mifare/mifare4.c @@ -10,10 +10,10 @@ //----------------------------------------------------------------------------- #include "mifare4.h" -#include #include +#include "commonutil.h" // ARRAYLEN +#include "comms.h" // DropField #include "cmdhf14a.h" -#include "util.h" #include "ui.h" #include "crypto/libpcrypto.h" @@ -40,10 +40,9 @@ static const PlusErrorsElm PlusErrors[] = { {0x0f, "General Manipulation Error. Failure in the operation of the PICC (cannot write to the data block), etc."}, {0x90, "OK"}, }; -int PlusErrorsLen = sizeof(PlusErrors) / sizeof(PlusErrorsElm); const char *mfpGetErrorDescription(uint8_t errorCode) { - for (int i = 0; i < PlusErrorsLen; i++) + for (int i = 0; i < ARRAYLEN(PlusErrors); i++) if (errorCode == PlusErrors[i].Code) return PlusErrors[i].Description; diff --git a/client/mifare/mifare4.h b/client/mifare/mifare4.h index 330c6d9f9..31eac1fdb 100644 --- a/client/mifare/mifare4.h +++ b/client/mifare/mifare4.h @@ -12,9 +12,7 @@ #ifndef MIFARE4_H #define MIFARE4_H -#include -#include -#include +#include "common.h" typedef struct { bool Authenticated; diff --git a/client/mifare/mifaredefault.h b/client/mifare/mifaredefault.h index 8debf3f65..7232510a0 100644 --- a/client/mifare/mifaredefault.h +++ b/client/mifare/mifaredefault.h @@ -11,9 +11,7 @@ #ifndef MIFAREDEFAULT_H__ #define MIFAREDEFAULT_H__ -#include - -#define MIFARE_DEFAULTKEYS_SIZE sizeof(g_mifare_default_keys) / sizeof(uint64_t) +#include "common.h" static const uint64_t g_mifare_default_keys[] = { 0xffffffffffff, // Default key (first key used by program if no user defined key) diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 100b595ce..429605a4e 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -8,7 +8,22 @@ // mifare commands //----------------------------------------------------------------------------- #include "mifarehost.h" -#include "cmdmain.h" + +#include +#include +#include +#include + +#include "comms.h" +#include "commonutil.h" +#include "mifare4.h" +#include "ui.h" // PrintAndLog... +#include "crapto1/crapto1.h" +#include "crc16.h" +#include "protocols.h" +#include "mfkey.h" +#include "util_posix.h" // msclock + int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { uint32_t uid = 0; @@ -25,7 +40,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { while (true) { clearCommandBuffer(); - SendCommandMIX(CMD_READER_MIFARE, arg0, blockno, key_type, NULL, 0); + SendCommandMIX(CMD_HF_MIFARE_READER, arg0, blockno, key_type, NULL, 0); //flush queue while (kbd_enter_pressed()) { @@ -125,10 +140,10 @@ int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keyc data[2] = clear_trace; data[3] = keycnt; memcpy(data + 4, keyBlock, 6 * keycnt); - SendCommandNG(CMD_MIFARE_CHKKEYS, data, (4 + 6 * keycnt)); + SendCommandNG(CMD_HF_MIFARE_CHKKEYS, data, (4 + 6 * keycnt)); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_MIFARE_CHKKEYS, &resp, 2500)) return PM3_ETIMEOUT; + if (!WaitForResponseTimeout(CMD_HF_MIFARE_CHKKEYS, &resp, 2500)) return PM3_ETIMEOUT; if (resp.status != PM3_SUCCESS) return resp.status; struct kr { @@ -153,7 +168,7 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, // send keychunk clearCommandBuffer(); - SendCommandOLD(CMD_MIFARE_CHKKEYS_FAST, (sectorsCnt | (firstChunk << 8) | (lastChunk << 12)), ((use_flashmemory << 8) | strategy), size, keyBlock, 6 * size); + SendCommandOLD(CMD_HF_MIFARE_CHKKEYS_FAST, (sectorsCnt | (firstChunk << 8) | (lastChunk << 12)), ((use_flashmemory << 8) | strategy), size, keyBlock, 6 * size); PacketResponseNG resp; while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { @@ -194,7 +209,8 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, // initialize storage for found keys icesector_t *tmp = calloc(sectorsCnt, sizeof(icesector_t)); if (tmp == NULL) - return 1; + return PM3_EMALLOC; + memcpy(tmp, resp.data.asBytes, sectorsCnt * sizeof(icesector_t)); for (int i = 0; i < sectorsCnt; i++) { @@ -212,11 +228,11 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, free(tmp); if (curr_keys == sectorsCnt * 2) - return 0; + return PM3_SUCCESS; if (lastChunk) - return 1; + return PM3_ESOFT; } - return 1; + return PM3_ESOFT; } // PM3 imp of J-Run mf_key_brute (part 2) @@ -299,7 +315,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, struct Crypto1State *p1, *p2, *p3, *p4; clearCommandBuffer(); - SendCommandOLD(CMD_MIFARE_NESTED, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, calibrate, key, 6); + SendCommandOLD(CMD_HF_MIFARE_NESTED, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, calibrate, key, 6); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return PM3_ETIMEOUT; // error during nested @@ -419,7 +435,7 @@ out: int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data) { clearCommandBuffer(); - SendCommandOLD(CMD_MIFARE_READSC, sectorNo, keyType, 0, key, 6); + SendCommandOLD(CMD_HF_MIFARE_READSC, sectorNo, keyType, 0, key, 6); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { @@ -456,10 +472,10 @@ int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) { payload.blockcnt = blocksCount; clearCommandBuffer(); - SendCommandNG(CMD_MIFARE_EML_MEMGET, (uint8_t *)&payload, sizeof(payload)); + SendCommandNG(CMD_HF_MIFARE_EML_MEMGET, (uint8_t *)&payload, sizeof(payload)); PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_MIFARE_EML_MEMGET, &resp, 1500) == 0) { + if (WaitForResponseTimeout(CMD_HF_MIFARE_EML_MEMGET, &resp, 1500) == 0) { PrintAndLogEx(WARNING, "Command execute timeout"); return PM3_ETIMEOUT; } @@ -495,7 +511,7 @@ int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidt memcpy(payload->data, data, size); clearCommandBuffer(); - SendCommandNG(CMD_MIFARE_EML_MEMSET, (uint8_t *)payload, sizeof(payload) + size); + SendCommandNG(CMD_HF_MIFARE_EML_MEMSET, (uint8_t *)payload, sizeof(payload) + size); return PM3_SUCCESS; } @@ -536,7 +552,7 @@ int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params) { clearCommandBuffer(); - SendCommandOLD(CMD_MIFARE_CSETBLOCK, params, blockNo, 0, data, 16); + SendCommandOLD(CMD_HF_MIFARE_CSETBL, params, blockNo, 0, data, 16); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { uint8_t isOK = resp.oldarg[0] & 0xff; @@ -553,7 +569,7 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params) { int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) { clearCommandBuffer(); - SendCommandMIX(CMD_MIFARE_CGETBLOCK, params, blockNo, 0, NULL, 0); + SendCommandMIX(CMD_HF_MIFARE_CGETBL, params, blockNo, 0, NULL, 0); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { uint8_t isOK = resp.oldarg[0] & 0xff; @@ -905,7 +921,7 @@ int detect_classic_prng(void) { uint32_t flags = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_RATS; clearCommandBuffer(); - SendCommandMIX(CMD_READER_ISO_14443a, flags, sizeof(cmd), 0, cmd, sizeof(cmd)); + SendCommandMIX(CMD_HF_ISO14443A_READER, flags, sizeof(cmd), 0, cmd, sizeof(cmd)); if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(WARNING, "PRNG UID: Reply timeout."); @@ -942,7 +958,7 @@ returns: int detect_classic_nackbug(bool verbose) { clearCommandBuffer(); - SendCommandNG(CMD_MIFARE_NACK_DETECT, NULL, 0); + SendCommandNG(CMD_HF_MIFARE_NACK_DETECT, NULL, 0); PacketResponseNG resp; if (verbose) @@ -955,7 +971,7 @@ int detect_classic_nackbug(bool verbose) { return PM3_EOPABORTED; } - if (WaitForResponseTimeout(CMD_MIFARE_NACK_DETECT, &resp, 500)) { + if (WaitForResponseTimeout(CMD_HF_MIFARE_NACK_DETECT, &resp, 500)) { if (resp.status == PM3_EOPABORTED) { PrintAndLogEx(WARNING, "button pressed. Aborted."); @@ -1010,8 +1026,8 @@ void detect_classic_magic(void) { uint8_t isGeneration = 0; PacketResponseNG resp; clearCommandBuffer(); - SendCommandNG(CMD_MIFARE_CIDENT, NULL, 0); - if (WaitForResponseTimeout(CMD_MIFARE_CIDENT, &resp, 1500)) { + SendCommandNG(CMD_HF_MIFARE_CIDENT, NULL, 0); + if (WaitForResponseTimeout(CMD_HF_MIFARE_CIDENT, &resp, 1500)) { if (resp.status == PM3_SUCCESS) isGeneration = resp.data.asBytes[0]; } @@ -1026,6 +1042,9 @@ void detect_classic_magic(void) { case 4: PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 2 / CUID): " _GREEN_("YES")); break; + case 5: + PrintAndLogEx(SUCCESS, "Answers to magic commands (Write Once / FUID): " _GREEN_("YES")); + break; default: PrintAndLogEx(INFO, "Answers to magic commands: " _YELLOW_("NO")); break; diff --git a/client/mifare/mifarehost.h b/client/mifare/mifarehost.h index 90837bcf7..11bd3f29c 100644 --- a/client/mifare/mifarehost.h +++ b/client/mifare/mifarehost.h @@ -10,22 +10,9 @@ #ifndef __MIFARE_HOST_H #define __MIFARE_HOST_H -#include -#include -#include -#include -#include - -#include "proxmark3.h" // time_t #include "common.h" + #include "util.h" // FILE_PATH_SIZE -#include "ui.h" // PrintAndLog... -#include "crapto1/crapto1.h" -#include "crc16.h" -#include "protocols.h" -#include "mifare.h" -#include "mfkey.h" -#include "util_posix.h" // msclock #define MIFARE_SECTOR_RETRY 10 diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index 7d0100d70..95c66bd72 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -9,7 +9,11 @@ //----------------------------------------------------------------------------- #include "ndef.h" + +#include + #include "ui.h" +#include "util.h" // sprint_hex... #include "emv/dump.h" #include "crypto/asn1utils.h" diff --git a/client/mifare/ndef.h b/client/mifare/ndef.h index 1737a6082..7d9ca2fbf 100644 --- a/client/mifare/ndef.h +++ b/client/mifare/ndef.h @@ -11,9 +11,7 @@ #ifndef _NDEF_H_ #define _NDEF_H_ -#include -#include -#include +#include "common.h" typedef enum { tnfEmptyRecord = 0x00, diff --git a/client/obj/.dummy b/client/obj/.dummy deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/obj/amiitool/.dummy b/client/obj/amiitool/.dummy deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/obj/cliparser/.dummy b/client/obj/cliparser/.dummy deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/obj/crapto1/.dummy b/client/obj/crapto1/.dummy deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/obj/crypto/.dummy b/client/obj/crypto/.dummy deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/obj/emv/.dummy b/client/obj/emv/.dummy deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/obj/emv/test/.dummy b/client/obj/emv/test/.dummy deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/obj/fido/.dummy b/client/obj/fido/.dummy deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/obj/hardnested/.dummy b/client/obj/hardnested/.dummy deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/obj/jansson/.dummy b/client/obj/jansson/.dummy deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/obj/loclass/.dummy b/client/obj/loclass/.dummy deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/obj/mifare/.dummy b/client/obj/mifare/.dummy deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/obj/nonce2key/.dummy b/client/obj/nonce2key/.dummy deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/obj/reveng/.gitignore b/client/obj/reveng/.gitignore deleted file mode 100644 index 07669e14a..000000000 --- a/client/obj/reveng/.gitignore +++ /dev/null @@ -1,35 +0,0 @@ -# .gitignore -# don't push these files to the repository - -*.log -*.eml -*.o -*.a -*.d -*.elf -*.s19 -*.map -*.bin -*.dll -*.moc.cpp -*.exe -proxmark -proxmark3 -flasher -version.c -lua -luac - -fpga/* -!fpga/tests -!fpga/fpga_lf.bit -!fpga/fpga_hf.bit -!fpga/*.v -!fpga/Makefile -!fpga/fpga.ucf -!fpga/xst_lf.scr -!fpga/xst_hf.scr -!fpga/go.bat -!fpga/sim.tcl - - diff --git a/client/platforms/.gitignore b/client/platforms/.gitignore deleted file mode 100644 index 07669e14a..000000000 --- a/client/platforms/.gitignore +++ /dev/null @@ -1,35 +0,0 @@ -# .gitignore -# don't push these files to the repository - -*.log -*.eml -*.o -*.a -*.d -*.elf -*.s19 -*.map -*.bin -*.dll -*.moc.cpp -*.exe -proxmark -proxmark3 -flasher -version.c -lua -luac - -fpga/* -!fpga/tests -!fpga/fpga_lf.bit -!fpga/fpga_hf.bit -!fpga/*.v -!fpga/Makefile -!fpga/fpga.ucf -!fpga/xst_lf.scr -!fpga/xst_hf.scr -!fpga/go.bat -!fpga/sim.tcl - - diff --git a/client/pm3_bit_limits.h b/client/pm3_bit_limits.h index 9bf06e16e..a2deda4c8 100644 --- a/client/pm3_bit_limits.h +++ b/client/pm3_bit_limits.h @@ -1,7 +1,9 @@ #ifndef __BITLIB_LIMITS_H #define __BITLIB_LIMITS_H + #define BITLIB_FLOAT_BITS 53 #define BITLIB_FLOAT_MAX 0xfffffffffffffL #define BITLIB_FLOAT_MIN (-0x10000000000000L) #define BITLIB_FLOAT_UMAX 0x1fffffffffffffUL + #endif diff --git a/common/prng.c b/client/prng.c similarity index 100% rename from common/prng.c rename to client/prng.c diff --git a/common/prng.h b/client/prng.h similarity index 94% rename from common/prng.h rename to client/prng.h index b9f49c6b6..3762f9f72 100644 --- a/common/prng.h +++ b/client/prng.h @@ -6,8 +6,9 @@ #ifndef __PRNG_H #define __PRNG_H -#include -#include + +#include "common.h" + typedef struct prng_ctx { uint32_t a; uint32_t b; @@ -21,4 +22,5 @@ void burtle_init_mod(prng_ctx *x, uint32_t seed); void burtle_init(prng_ctx *x, uint32_t seed); uint32_t GetSimplePrng(uint32_t seed); + #endif /* __PRNG_H */ diff --git a/client/proxendian.h b/client/proxendian.h index 44e099547..fde5126b1 100644 --- a/client/proxendian.h +++ b/client/proxendian.h @@ -11,7 +11,7 @@ #ifndef PROXENDIAN_H__ #define PROXENDIAN_H__ -#include +#include "common.h" #ifdef _WIN32 # define HOST_LITTLE_ENDIAN diff --git a/client/proxgui.cpp b/client/proxgui.cpp index 120f2b26d..d5f82ffe9 100644 --- a/client/proxgui.cpp +++ b/client/proxgui.cpp @@ -9,20 +9,22 @@ //----------------------------------------------------------------------------- #include "proxgui.h" + +#include #include "proxguiqt.h" #include "proxmark3.h" static ProxGuiQT *gui = NULL; static WorkerThread *main_loop_thread = NULL; -WorkerThread::WorkerThread(char *script_cmds_file, char *script_cmd) : script_cmds_file(script_cmds_file), script_cmd(script_cmd) { +WorkerThread::WorkerThread(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) : script_cmds_file(script_cmds_file), script_cmd(script_cmd), stayInCommandLoop(stayInCommandLoop) { } WorkerThread::~WorkerThread() { } void WorkerThread::run() { - main_loop(script_cmds_file, script_cmd); + main_loop(script_cmds_file, script_cmd, stayInCommandLoop); } extern "C" void ShowGraphWindow(void) { @@ -53,12 +55,12 @@ extern "C" void MainGraphics(void) { gui->MainLoop(); } -extern "C" void InitGraphics(int argc, char **argv, char *script_cmds_file, char *script_cmd) { +extern "C" void InitGraphics(int argc, char **argv, char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) { #ifdef Q_WS_X11 if (getenv("DISPLAY") == NULL) return; #endif - main_loop_thread = new WorkerThread(script_cmds_file, script_cmd); + main_loop_thread = new WorkerThread(script_cmds_file, script_cmd, stayInCommandLoop); gui = new ProxGuiQT(argc, argv, main_loop_thread); } diff --git a/client/proxgui.h b/client/proxgui.h index dfbddbc0c..c4adbeb01 100644 --- a/client/proxgui.h +++ b/client/proxgui.h @@ -16,13 +16,14 @@ extern "C" { #endif #include -#include +#include +#include void ShowGraphWindow(void); void HideGraphWindow(void); void RepaintGraphWindow(void); void MainGraphics(void); -void InitGraphics(int argc, char **argv, char *script_cmds_file, char *script_cmd); +void InitGraphics(int argc, char **argv, char *script_cmds_file, char *script_cmd, bool stayInCommandLoop); void ExitGraphics(void); #ifndef MAX_GRAPH_TRACE_LEN #define MAX_GRAPH_TRACE_LEN (40000 * 8) diff --git a/client/proxguiqt.cpp b/client/proxguiqt.cpp index 344f48b03..6bf99f5a1 100644 --- a/client/proxguiqt.cpp +++ b/client/proxguiqt.cpp @@ -535,7 +535,7 @@ void Plot::paintEvent(QPaintEvent *event) { sprintf(str, "@%d dt=%d [%2.2f] zoom=%2.2f CursorAPos=%d CursorBPos=%d GridX=%d GridY=%d (%s) GridXoffset=%d", GraphStart, CursorBPos - CursorAPos, - (CursorBPos - CursorAPos) / CursorScaleFactor, + ((int32_t)(CursorBPos - CursorAPos)) / CursorScaleFactor, GraphPixelsPerPoint, CursorAPos, CursorBPos, diff --git a/client/proxguiqt.h b/client/proxguiqt.h index e50bfe073..80d9e1ef4 100644 --- a/client/proxguiqt.h +++ b/client/proxguiqt.h @@ -93,12 +93,13 @@ class ProxWidget : public QWidget { class WorkerThread : public QThread { Q_OBJECT; public: - WorkerThread(char *, char *); + WorkerThread(char *, char *, bool); ~WorkerThread(); void run(); private: char *script_cmds_file; char *script_cmd; + bool stayInCommandLoop; }; class ProxGuiQT : public QObject { diff --git a/client/proxmark3.c b/client/proxmark3.c index 1d3a0e8b5..aa37cda9a 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -8,30 +8,29 @@ //----------------------------------------------------------------------------- // Main binary //----------------------------------------------------------------------------- -#include "proxmark3.h" -#include +#include "proxmark3.h" +#include +#include // for Mingw readline #include -#include -#include #include #include #include - +#include "usart_defs.h" #include "util_posix.h" #include "proxgui.h" #include "cmdmain.h" #include "ui.h" -#include "util.h" -#include "cmdparser.h" #include "cmdhw.h" #include "whereami.h" #include "comms.h" -#include "usart.h" +#include "fileutils.h" +#include "flash.h" + static void showBanner(void) { PrintAndLogEx(NORMAL, "\n"); -#if defined(__linux__) || (__APPLE__) +#if defined(__linux__) || (__APPLE__) || (_WIN32) PrintAndLogEx(NORMAL, _BLUE_("██████╗ ███╗ ███╗ ████╗ ") " ...iceman fork"); PrintAndLogEx(NORMAL, _BLUE_("██╔══██╗████╗ ████║ ══█║") " ...dedicated to " _BLUE_("RDV40")); PrintAndLogEx(NORMAL, _BLUE_("██████╔╝██╔████╔██║ ████╔╝")); @@ -46,7 +45,8 @@ static void showBanner(void) { PrintAndLogEx(NORMAL, "==. ==. ... ==. ====.. https://github.com/rfidresearchgroup/proxmark3/"); PrintAndLogEx(NORMAL, "... ... ... ..... pre-release v4.0"); #endif - PrintAndLogEx(NORMAL, "\nSupport iceman on patreon, https://www.patreon.com/iceman1001/"); + PrintAndLogEx(NORMAL, "\nSupport iceman on patreon - https://www.patreon.com/iceman1001/"); + PrintAndLogEx(NORMAL, " on paypal - https://www.paypal.me/iceman1001"); // printf("\nMonero: 43mNJLpgBVaTvyZmX9ajcohpvVkaRy1kbZPm8tqAb7itZgfuYecgkRF36rXrKFUkwEGeZedPsASRxgv4HPBHvJwyJdyvQuP"); PrintAndLogEx(NORMAL, "\n"); fflush(stdout); @@ -63,6 +63,38 @@ int check_comm(void) { return 0; } +// first slot is always NULL, indicating absence of script when idx=0 +FILE *cmdscriptfile[MAX_NESTED_CMDSCRIPT + 1] = {0}; +uint8_t cmdscriptfile_idx = 0; +bool cmdscriptfile_stayafter = false; + +int push_cmdscriptfile(char *path, bool stayafter) { + if (cmdscriptfile_idx == MAX_NESTED_CMDSCRIPT) { + PrintAndLogEx(ERR, "Too many nested scripts, skipping %s\n", path); + return PM3_EMALLOC; + } + FILE *tmp = fopen(path, "r"); + if (tmp == NULL) + return PM3_EFILE; + if (cmdscriptfile_idx == 0) + cmdscriptfile_stayafter = stayafter; + cmdscriptfile[++cmdscriptfile_idx] = tmp; + return PM3_SUCCESS; +} + +FILE *current_cmdscriptfile() { + return cmdscriptfile[cmdscriptfile_idx]; +} + +bool pop_cmdscriptfile() { + fclose(cmdscriptfile[cmdscriptfile_idx]); + cmdscriptfile[cmdscriptfile_idx--] = NULL; + if (cmdscriptfile_idx == 0) + return cmdscriptfile_stayafter; + else + return true; +} + // Main thread of PM3 Client void #ifdef __has_attribute @@ -70,7 +102,7 @@ void __attribute__((force_align_arg_pointer)) #endif #endif -main_loop(char *script_cmds_file, char *script_cmd) { +main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) { char *cmd = NULL; bool execCommand = (script_cmd != NULL); @@ -80,7 +112,6 @@ main_loop(char *script_cmds_file, char *script_cmd) { strcreplace(script_cmd, script_cmd_len, ';', '\0'); } bool stdinOnPipe = !isatty(STDIN_FILENO); - FILE *sf = NULL; char script_cmd_buf[256] = {0x00}; // iceman, needs lua script the same file_path_buffer as the rest PrintAndLogEx(DEBUG, "ISATTY/STDIN_FILENO == %s\n", (stdinOnPipe) ? "true" : "false"); @@ -88,36 +119,48 @@ main_loop(char *script_cmds_file, char *script_cmd) { if (session.pm3_present) { // cache Version information now: if (execCommand || script_cmds_file || stdinOnPipe) - pm3_version(false); + pm3_version(false, false); else - pm3_version(true); + pm3_version(true, false); } if (script_cmds_file) { - sf = fopen(script_cmds_file, "r"); - if (sf) - PrintAndLogEx(SUCCESS, "executing commands from file: %s\n", script_cmds_file); - else - PrintAndLogEx(ERR, "could not open " _YELLOW_("%s") "...", 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) + PrintAndLogEx(SUCCESS, "executing commands from file: %s\n", path); + else + PrintAndLogEx(ERR, "could not open " _YELLOW_("%s") "...", path); + free(path); + } } - read_history(".history"); - + char *my_history_path = NULL; + if (searchHomeFilePath(&my_history_path, PROXHISTORY, true) != PM3_SUCCESS) { + PrintAndLogEx(ERR, "No history will be recorded"); + my_history_path = NULL; + } else { + read_history(my_history_path); + } // loops every time enter is pressed... while (1) { bool printprompt = false; + char *prompt = PROXPROMPT; +check_script: // If there is a script file - if (sf) { + if (current_cmdscriptfile()) { // clear array memset(script_cmd_buf, 0, sizeof(script_cmd_buf)); // read script file - if (!fgets(script_cmd_buf, sizeof(script_cmd_buf), sf)) { - fclose(sf); - sf = NULL; + if (!fgets(script_cmd_buf, sizeof(script_cmd_buf), current_cmdscriptfile())) { + if (!pop_cmdscriptfile()) + break; + goto check_script; } else { // remove linebreaks @@ -138,7 +181,7 @@ main_loop(char *script_cmds_file, char *script_cmd) { script_cmd_len -= len; } else { // exit after exec command - if (script_cmd) + if (script_cmd && !stayInCommandLoop) break; // if there is a pipe from stdin @@ -161,12 +204,12 @@ main_loop(char *script_cmds_file, char *script_cmd) { rl_event_hook = check_comm; if (session.pm3_present) { if (conn.send_via_fpc_usart == false) - cmd = readline(PROXPROMPT_USB); + prompt = PROXPROMPT_USB; else - cmd = readline(PROXPROMPT_FPC); + prompt = PROXPROMPT_FPC; } else - cmd = readline(PROXPROMPT_OFFLINE); - + prompt = PROXPROMPT_OFFLINE; + cmd = readline(prompt); fflush(NULL); } } @@ -189,15 +232,20 @@ main_loop(char *script_cmds_file, char *script_cmd) { cmd[strlen(cmd) - off] = '\0'; if (cmd[0] != '\0') { - if (printprompt) - PrintAndLogEx(NORMAL, PROXPROMPT"%s", cmd); + if (!printprompt) + g_printAndLog = PRINTANDLOG_LOG; + PrintAndLogEx(NORMAL, "%s%s", prompt, cmd); + g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG; + // add to history if not from a script + if (!current_cmdscriptfile()) { + HIST_ENTRY *entry = history_get(history_length); + // add if not identical to latest recorded cmd + if ((!entry) || (strcmp(entry->line, cmd) != 0)) + add_history(cmd); + } + // process cmd int ret = CommandReceived(cmd); - - HIST_ENTRY *entry = history_get(history_length); - if ((!entry) || (strcmp(entry->line, cmd) != 0)) - add_history(cmd); - // exit or quit if (ret == PM3_EFATAL) break; @@ -206,7 +254,10 @@ main_loop(char *script_cmds_file, char *script_cmd) { cmd = NULL; } else { PrintAndLogEx(NORMAL, "\n"); - break; + if (script_cmds_file && stayInCommandLoop) + stayInCommandLoop = false; + else + break; } } // end while @@ -214,11 +265,13 @@ main_loop(char *script_cmds_file, char *script_cmd) { SendCommandNG(CMD_QUIT_SESSION, NULL, 0); msleep(100); // Make sure command is sent before killing client - if (sf) - fclose(sf); - - write_history(".history"); + while (current_cmdscriptfile()) + pop_cmdscriptfile(); + if (my_history_path) { + write_history(my_history_path); + free(my_history_path); + } if (cmd) { free(cmd); cmd = NULL; @@ -264,37 +317,140 @@ static void set_my_executable_path(void) { static void show_help(bool showFullHelp, char *exec_name) { - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "syntax: %s [-h|-t|-m]\n", exec_name); - PrintAndLogEx(NORMAL, " %s [[-p] ] [-b] [-w] [-f] [-c ]|[-l ]|[-s ]\n", exec_name); + PrintAndLogEx(NORMAL, "\nsyntax: %s [-h|-t|-m]", exec_name); + PrintAndLogEx(NORMAL, " %s [[-p] ] [-b] [-w] [-f] [-c ]|[-l ]|[-s ] [-i] [-d <0|1|2>]", exec_name); + PrintAndLogEx(NORMAL, " %s [-p] --flash [--unlock-bootloader] [--image ]+ [-w] [-f] [-d <0|1|2>]", exec_name); if (showFullHelp) { - PrintAndLogEx(NORMAL, "options:"); + + PrintAndLogEx(NORMAL, "\nCommon options:"); PrintAndLogEx(NORMAL, " -h/--help this help"); - PrintAndLogEx(NORMAL, " -t/--text dump all interactive command's help at once"); - PrintAndLogEx(NORMAL, " -m/--markdown dump all interactive help at once in markdown syntax"); + PrintAndLogEx(NORMAL, " -v/--version print client version"); PrintAndLogEx(NORMAL, " -p/--port serial port to connect to"); - PrintAndLogEx(NORMAL, " -b/--baud serial port speed (only needed for physical UART, not for USB-CDC or BT)"); PrintAndLogEx(NORMAL, " -w/--wait 20sec waiting the serial port to appear in the OS"); PrintAndLogEx(NORMAL, " -f/--flush output will be flushed after every print"); + PrintAndLogEx(NORMAL, " -d/--debug <0|1|2> set debugmode"); + PrintAndLogEx(NORMAL, "\nOptions in client mode:"); + PrintAndLogEx(NORMAL, " -t/--text dump all interactive command's help at once"); + PrintAndLogEx(NORMAL, " -m/--markdown dump all interactive help at once in markdown syntax"); + PrintAndLogEx(NORMAL, " -b/--baud serial port speed (only needed for physical UART, not for USB-CDC or BT)"); PrintAndLogEx(NORMAL, " -c/--command execute one Proxmark3 command (or several separated by ';')."); PrintAndLogEx(NORMAL, " -l/--lua execute lua script."); PrintAndLogEx(NORMAL, " -s/--script-file script file with one Proxmark3 command per line"); - PrintAndLogEx(NORMAL, "\nsamples:"); - PrintAndLogEx(NORMAL, " %s -h\n", exec_name); - PrintAndLogEx(NORMAL, " %s -m\n", exec_name); - PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -f -- flush output everytime\n", exec_name); - PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -w -- wait for serial port\n", exec_name); - PrintAndLogEx(NORMAL, "\n how to run Proxmark3 client\n"); - PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -- runs the pm3 client\n", exec_name); - PrintAndLogEx(NORMAL, " %s -- runs the pm3 client in OFFLINE mode\n", exec_name); - PrintAndLogEx(NORMAL, "\n how to execute different commands from terminal\n"); - PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -c \"hf mf chk 1* ?\" -- execute cmd and quit client\n", exec_name); - PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -l hf_read -- execute lua script " _YELLOW_("`hf_read`")"and quit client\n", exec_name); - PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -s mycmds.txt -- execute each pm3 cmd in file and quit client\n", exec_name); + PrintAndLogEx(NORMAL, " -i/--interactive enter interactive mode after executing the script or the command"); + PrintAndLogEx(NORMAL, "\nOptions in flasher mode:"); + PrintAndLogEx(NORMAL, " --flash flash Proxmark3, requires at least one --image"); + PrintAndLogEx(NORMAL, " --unlock-bootloader Enable flashing of bootloader area *DANGEROUS* (need --flash or --flash-info)"); + PrintAndLogEx(NORMAL, " --image image to flash. Can be specified several times."); + PrintAndLogEx(NORMAL, "\nExamples:"); + PrintAndLogEx(NORMAL, "\n to run Proxmark3 client:\n"); + PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -- runs the pm3 client", exec_name); + PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -f -- flush output everytime", exec_name); + PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -w -- wait for serial port", exec_name); + PrintAndLogEx(NORMAL, " %s -- runs the pm3 client in OFFLINE mode", exec_name); + PrintAndLogEx(NORMAL, "\n to execute different commands from terminal:\n"); + PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -c \"hf mf chk 1* ?\" -- execute cmd and quit client", exec_name); + PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -l hf_read -- execute lua script " _YELLOW_("`hf_read`")"and quit client", exec_name); + PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -s mycmds.txt -- execute each pm3 cmd in file and quit client", exec_name); + PrintAndLogEx(NORMAL, "\n to flash fullimage and bootloader:\n"); + PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" --flash --unlock-bootloader --image bootrom.elf --image fullimage.elf", exec_name); +#ifdef __linux__ + PrintAndLogEx(NORMAL, "\nNote (Linux):\nif the flasher gets stuck in 'Waiting for Proxmark3 to reappear on ',"); + PrintAndLogEx(NORMAL, "you need to blacklist Proxmark3 for modem-manager - see documentation for more details:"); + PrintAndLogEx(NORMAL, "* https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md"); + PrintAndLogEx(NORMAL, "\nMore info on flashing procedure from the official Proxmark3 wiki:"); + PrintAndLogEx(NORMAL, "* https://github.com/Proxmark/proxmark3/wiki/Gentoo%%20Linux"); + PrintAndLogEx(NORMAL, "* https://github.com/Proxmark/proxmark3/wiki/Ubuntu%%20Linux"); + PrintAndLogEx(NORMAL, "* https://github.com/Proxmark/proxmark3/wiki/OSX\n"); +#endif } } +static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[FLASH_MAX_FILES], bool can_write_bl) { + + int ret = PM3_EUNDEF; + flash_file_t files[FLASH_MAX_FILES]; + memset(files, 0, sizeof(files)); + char *filepaths[FLASH_MAX_FILES]; + + if (serial_port_name == NULL) { + PrintAndLogEx(ERR, "You must specify a port.\n"); + return PM3_EINVARG; + } + + for (int i = 0 ; i < num_files; ++i) { + char *path; + ret = searchFile(&path, FIRMWARES_SUBDIR, filenames[i], ".elf", true); + if (ret != PM3_SUCCESS) { + ret = searchFile(&path, BOOTROM_SUBDIR, filenames[i], ".elf", true); + } + if (ret != PM3_SUCCESS) { + // Last try, let the error msg be displayed if not found + ret = searchFile(&path, FULLIMAGE_SUBDIR, filenames[i], ".elf", false); + } + if (ret != PM3_SUCCESS) { + goto finish2; + } + filepaths[i] = path; + } + + PrintAndLogEx(SUCCESS, "About to use the following file%s:", num_files > 1 ? "s" : ""); + for (int i = 0 ; i < num_files; ++i) { + PrintAndLogEx(SUCCESS, " %s", filepaths[i]); + } + + if (OpenProxmark(serial_port_name, true, 60, true, FLASHMODE_SPEED)) { + PrintAndLogEx(NORMAL, _GREEN_("Found")); + } else { + PrintAndLogEx(ERR, "Could not find Proxmark3 on " _RED_("%s") ".\n", serial_port_name); + ret = PM3_ETIMEOUT; + goto finish2; + } + + uint32_t max_allowed = 0; + ret = flash_start_flashing(can_write_bl, serial_port_name, &max_allowed); + if (ret != PM3_SUCCESS) { + goto finish; + } + + if (num_files == 0) + goto finish; + + for (int i = 0 ; i < num_files; ++i) { + ret = flash_load(&files[i], filepaths[i], can_write_bl, max_allowed * ONE_KB); + if (ret != PM3_SUCCESS) { + goto finish; + } + PrintAndLogEx(NORMAL, ""); + } + + PrintAndLogEx(SUCCESS, "\n" _BLUE_("Flashing...")); + + for (int i = 0; i < num_files; i++) { + ret = flash_write(&files[i]); + if (ret != PM3_SUCCESS) { + goto finish; + } + flash_free(&files[i]); + PrintAndLogEx(NORMAL, "\n"); + } + +finish: + ret = flash_stop_flashing(); + CloseProxmark(); +finish2: + for (int i = 0 ; i < num_files; ++i) { + if (filepaths[i] != NULL) + free(filepaths[i]); + } + if (ret == PM3_SUCCESS) + PrintAndLogEx(SUCCESS, _BLUE_("All done.")); + else + PrintAndLogEx(ERR, "Aborted on error."); + PrintAndLogEx(NORMAL, "\nHave a nice day!"); + return ret; +} + int main(int argc, char *argv[]) { srand(time(0)); @@ -302,6 +458,7 @@ int main(int argc, char *argv[]) { session.help_dump_mode = false; bool waitCOMPort = false; bool addLuaExec = false; + bool stayInCommandLoop = false; char *script_cmds_file = NULL; char *script_cmd = NULL; char *port = NULL; @@ -324,6 +481,11 @@ int main(int argc, char *argv[]) { } #endif + bool flash_mode = false; + bool flash_can_write_bl = false; + int flash_num_files = 0; + char *flash_filenames[FLASH_MAX_FILES]; + for (int i = 1; i < argc; i++) { if (argv[i][0] != '-') { @@ -357,12 +519,14 @@ int main(int argc, char *argv[]) { // short help if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { + g_printAndLog = PRINTANDLOG_PRINT; show_help(true, exec_name); return 0; } // dump help if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--text") == 0) { + g_printAndLog = PRINTANDLOG_PRINT; show_help(false, exec_name); dumpAllHelp(0); return 0; @@ -370,9 +534,32 @@ int main(int argc, char *argv[]) { // dump markup if (strcmp(argv[i], "-m") == 0 || strcmp(argv[i], "--markdown") == 0) { + g_printAndLog = PRINTANDLOG_PRINT; dumpAllHelp(1); return 0; } + // print client version + if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) { + pm3_version(true, true); + return 0; + } + + // set debugmode + if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--debug") == 0) { + if (i + 1 == argc) { + PrintAndLogEx(ERR, _RED_("ERROR:") "missing debugmode specification after -d\n"); + show_help(false, exec_name); + return 1; + } + int demod = atoi(argv[i + 1]); + if (demod < 0 || demod > 2) { + PrintAndLogEx(ERR, _RED_("ERROR:") "invalid debugmode: -d " _YELLOW_("%s") "\n", argv[i + 1]); + return 1; + } + g_debugMode = demod; + i++; + continue; + } // flush output if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--flush") == 0) { @@ -438,6 +625,39 @@ int main(int argc, char *argv[]) { continue; } + // go to interactive instead of quitting after a script/command + if (strcmp(argv[i], "-i") == 0 || strcmp(argv[i], "--interactive") == 0) { + stayInCommandLoop = true; + continue; + } + + // go to flash mode + if (strcmp(argv[i], "--flash") == 0) { + flash_mode = true; + continue; + } + + // unlock bootloader area + if (strcmp(argv[i], "--unlock-bootloader") == 0) { + flash_can_write_bl = true; + continue; + } + + // flash file + if (strcmp(argv[i], "--image") == 0) { + if (flash_num_files == FLASH_MAX_FILES) { + PrintAndLogEx(ERR, _RED_("ERROR:") "too many --image, please use it max %i times\n", FLASH_MAX_FILES); + return 1; + } + if (i + 1 == argc) { + PrintAndLogEx(ERR, _RED_("ERROR:") "missing image specification after --image\n"); + show_help(false, exec_name); + return 1; + } + flash_filenames[flash_num_files++] = argv[++i]; + continue; + } + // We got an unknown parameter PrintAndLogEx(ERR, _RED_("ERROR:") "invalid parameter: " _YELLOW_("%s") "\n", argv[i]); show_help(false, exec_name); @@ -458,13 +678,21 @@ int main(int argc, char *argv[]) { session.supports_colors = true; #endif // ascii art only in interactive client - if (!script_cmds_file && !script_cmd && session.stdinOnTTY && session.stdoutOnTTY) + if (!script_cmds_file && !script_cmd && session.stdinOnTTY && session.stdoutOnTTY && !flash_mode) showBanner(); // Let's take a baudrate ok for real UART, USB-CDC & BT don't use that info anyway if (speed == 0) speed = USART_BAUD_RATE; + // set global variables + set_my_executable_path(); + + if (flash_mode) { + flash_pm3(port, flash_num_files, flash_filenames, flash_can_write_bl); + exit(EXIT_SUCCESS); + } + if (script_cmd) { while (script_cmd[strlen(script_cmd) - 1] == ' ') script_cmd[strlen(script_cmd) - 1] = 0x00; @@ -490,9 +718,6 @@ int main(int argc, char *argv[]) { } } - // set global variables - set_my_executable_path(); - // try to open USB connection to Proxmark if (port != NULL) { OpenProxmark(port, waitCOMPort, 20, false, speed); @@ -512,21 +737,21 @@ int main(int argc, char *argv[]) { #ifdef HAVE_GUI # ifdef _WIN32 - InitGraphics(argc, argv, script_cmds_file, script_cmd); + InitGraphics(argc, argv, script_cmds_file, script_cmd, stayInCommandLoop); MainGraphics(); # else // for *nix distro's, check enviroment variable to verify a display char *display = getenv("DISPLAY"); if (display && strlen(display) > 1) { - InitGraphics(argc, argv, script_cmds_file, script_cmd); + InitGraphics(argc, argv, script_cmds_file, script_cmd, stayInCommandLoop); MainGraphics(); } else { - main_loop(script_cmds_file, script_cmd); + main_loop(script_cmds_file, script_cmd, stayInCommandLoop); } # endif #else - main_loop(script_cmds_file, script_cmd); + main_loop(script_cmds_file, script_cmd, stayInCommandLoop); #endif // Clean up the port diff --git a/client/proxmark3.h b/client/proxmark3.h index 7fea9a092..c370efdff 100644 --- a/client/proxmark3.h +++ b/client/proxmark3.h @@ -12,21 +12,25 @@ #ifndef PROXMARK3_H__ #define PROXMARK3_H__ -#include "pm3_cmd.h" -#include "cmdscript.h" // CmdScriptRun +#include "common.h" #define PROXPROMPT "pm3 --> " #define PROXPROMPT_USB "[usb] pm3 --> " #define PROXPROMPT_FPC "[fpc] pm3 --> " #define PROXPROMPT_OFFLINE "[offline] pm3 --> " +#define PROXHISTORY "history.txt" +#define PROXLOG "log_%Y%m%d.txt" +#define MAX_NESTED_CMDSCRIPT 10 +#define MAX_NESTED_LUASCRIPT 10 #ifdef __cplusplus extern "C" { #endif +int push_cmdscriptfile(char *path, bool stayafter); const char *get_my_executable_path(void); const char *get_my_executable_directory(void); -void main_loop(char *script_cmds_file, char *script_cmd); +void main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop); #ifdef __cplusplus } diff --git a/client/aidlist.json b/client/resources/aidlist.json similarity index 100% rename from client/aidlist.json rename to client/resources/aidlist.json diff --git a/client/emv/capk.txt b/client/resources/capk.txt similarity index 100% rename from client/emv/capk.txt rename to client/resources/capk.txt diff --git a/client/emv/defparams.json b/client/resources/emv_defparams.json similarity index 100% rename from client/emv/defparams.json rename to client/resources/emv_defparams.json diff --git a/client/hardnested/bf_bench_data.bin b/client/resources/hardnested_bf_bench_data.bin similarity index 100% rename from client/hardnested/bf_bench_data.bin rename to client/resources/hardnested_bf_bench_data.bin diff --git a/client/hardnested/tables/bitflip_0_001_states.bin.z b/client/resources/hardnested_tables/bitflip_0_001_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_001_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_001_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_003_states.bin.z b/client/resources/hardnested_tables/bitflip_0_003_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_003_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_003_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_005_states.bin.z b/client/resources/hardnested_tables/bitflip_0_005_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_005_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_005_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_007_states.bin.z b/client/resources/hardnested_tables/bitflip_0_007_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_007_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_007_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_009_states.bin.z b/client/resources/hardnested_tables/bitflip_0_009_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_009_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_009_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_00b_states.bin.z b/client/resources/hardnested_tables/bitflip_0_00b_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_00b_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_00b_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_00d_states.bin.z b/client/resources/hardnested_tables/bitflip_0_00d_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_00d_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_00d_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_00f_states.bin.z b/client/resources/hardnested_tables/bitflip_0_00f_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_00f_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_00f_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_010_states.bin.z b/client/resources/hardnested_tables/bitflip_0_010_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_010_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_010_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_014_states.bin.z b/client/resources/hardnested_tables/bitflip_0_014_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_014_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_014_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_01c_states.bin.z b/client/resources/hardnested_tables/bitflip_0_01c_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_01c_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_01c_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_021_states.bin.z b/client/resources/hardnested_tables/bitflip_0_021_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_021_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_021_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_023_states.bin.z b/client/resources/hardnested_tables/bitflip_0_023_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_023_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_023_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_025_states.bin.z b/client/resources/hardnested_tables/bitflip_0_025_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_025_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_025_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_027_states.bin.z b/client/resources/hardnested_tables/bitflip_0_027_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_027_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_027_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_029_states.bin.z b/client/resources/hardnested_tables/bitflip_0_029_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_029_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_029_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_02b_states.bin.z b/client/resources/hardnested_tables/bitflip_0_02b_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_02b_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_02b_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_02d_states.bin.z b/client/resources/hardnested_tables/bitflip_0_02d_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_02d_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_02d_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_02f_states.bin.z b/client/resources/hardnested_tables/bitflip_0_02f_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_02f_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_02f_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_030_states.bin.z b/client/resources/hardnested_tables/bitflip_0_030_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_030_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_030_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_034_states.bin.z b/client/resources/hardnested_tables/bitflip_0_034_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_034_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_034_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_03c_states.bin.z b/client/resources/hardnested_tables/bitflip_0_03c_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_03c_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_03c_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_040_states.bin.z b/client/resources/hardnested_tables/bitflip_0_040_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_040_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_040_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_044_states.bin.z b/client/resources/hardnested_tables/bitflip_0_044_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_044_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_044_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_04c_states.bin.z b/client/resources/hardnested_tables/bitflip_0_04c_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_04c_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_04c_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_051_states.bin.z b/client/resources/hardnested_tables/bitflip_0_051_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_051_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_051_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_053_states.bin.z b/client/resources/hardnested_tables/bitflip_0_053_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_053_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_053_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_055_states.bin.z b/client/resources/hardnested_tables/bitflip_0_055_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_055_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_055_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_057_states.bin.z b/client/resources/hardnested_tables/bitflip_0_057_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_057_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_057_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_059_states.bin.z b/client/resources/hardnested_tables/bitflip_0_059_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_059_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_059_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_05b_states.bin.z b/client/resources/hardnested_tables/bitflip_0_05b_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_05b_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_05b_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_05d_states.bin.z b/client/resources/hardnested_tables/bitflip_0_05d_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_05d_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_05d_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_05f_states.bin.z b/client/resources/hardnested_tables/bitflip_0_05f_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_05f_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_05f_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_064_states.bin.z b/client/resources/hardnested_tables/bitflip_0_064_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_064_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_064_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_06c_states.bin.z b/client/resources/hardnested_tables/bitflip_0_06c_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_06c_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_06c_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_071_states.bin.z b/client/resources/hardnested_tables/bitflip_0_071_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_071_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_071_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_073_states.bin.z b/client/resources/hardnested_tables/bitflip_0_073_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_073_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_073_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_075_states.bin.z b/client/resources/hardnested_tables/bitflip_0_075_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_075_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_075_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_077_states.bin.z b/client/resources/hardnested_tables/bitflip_0_077_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_077_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_077_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_079_states.bin.z b/client/resources/hardnested_tables/bitflip_0_079_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_079_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_079_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_07b_states.bin.z b/client/resources/hardnested_tables/bitflip_0_07b_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_07b_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_07b_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_07f_states.bin.z b/client/resources/hardnested_tables/bitflip_0_07f_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_07f_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_07f_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_081_states.bin.z b/client/resources/hardnested_tables/bitflip_0_081_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_081_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_081_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_083_states.bin.z b/client/resources/hardnested_tables/bitflip_0_083_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_083_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_083_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_085_states.bin.z b/client/resources/hardnested_tables/bitflip_0_085_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_085_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_085_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_087_states.bin.z b/client/resources/hardnested_tables/bitflip_0_087_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_087_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_087_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_089_states.bin.z b/client/resources/hardnested_tables/bitflip_0_089_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_089_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_089_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_08b_states.bin.z b/client/resources/hardnested_tables/bitflip_0_08b_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_08b_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_08b_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_08d_states.bin.z b/client/resources/hardnested_tables/bitflip_0_08d_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_08d_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_08d_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_08f_states.bin.z b/client/resources/hardnested_tables/bitflip_0_08f_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_08f_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_08f_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_090_states.bin.z b/client/resources/hardnested_tables/bitflip_0_090_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_090_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_090_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_094_states.bin.z b/client/resources/hardnested_tables/bitflip_0_094_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_094_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_094_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_09c_states.bin.z b/client/resources/hardnested_tables/bitflip_0_09c_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_09c_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_09c_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0a1_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0a1_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0a1_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0a1_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0a3_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0a3_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0a3_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0a3_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0a5_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0a5_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0a5_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0a5_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0a7_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0a7_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0a7_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0a7_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0a9_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0a9_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0a9_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0a9_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0ab_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0ab_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0ab_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0ab_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0ad_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0ad_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0ad_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0ad_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0af_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0af_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0af_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0af_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0b0_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0b0_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0b0_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0b0_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0b4_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0b4_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0b4_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0b4_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0bc_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0bc_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0bc_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0bc_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0c0_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0c0_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0c0_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0c0_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0c4_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0c4_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0c4_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0c4_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0cc_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0cc_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0cc_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0cc_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0d1_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0d1_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0d1_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0d1_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0d3_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0d3_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0d3_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0d3_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0d5_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0d5_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0d5_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0d5_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0d7_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0d7_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0d7_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0d7_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0d9_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0d9_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0d9_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0d9_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0db_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0db_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0db_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0db_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0dd_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0dd_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0dd_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0dd_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0df_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0df_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0df_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0df_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0e4_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0e4_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0e4_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0e4_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0ec_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0ec_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0ec_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0ec_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0f1_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0f1_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0f1_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0f1_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0f3_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0f3_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0f3_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0f3_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0f5_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0f5_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0f5_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0f5_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0f7_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0f7_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0f7_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0f7_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0f9_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0f9_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0f9_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0f9_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0fb_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0fb_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0fb_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0fb_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0fd_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0fd_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0fd_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0fd_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_0ff_states.bin.z b/client/resources/hardnested_tables/bitflip_0_0ff_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_0ff_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_0ff_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_104_states.bin.z b/client/resources/hardnested_tables/bitflip_0_104_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_104_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_104_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_10c_states.bin.z b/client/resources/hardnested_tables/bitflip_0_10c_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_10c_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_10c_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_111_states.bin.z b/client/resources/hardnested_tables/bitflip_0_111_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_111_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_111_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_113_states.bin.z b/client/resources/hardnested_tables/bitflip_0_113_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_113_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_113_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_115_states.bin.z b/client/resources/hardnested_tables/bitflip_0_115_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_115_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_115_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_117_states.bin.z b/client/resources/hardnested_tables/bitflip_0_117_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_117_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_117_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_119_states.bin.z b/client/resources/hardnested_tables/bitflip_0_119_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_119_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_119_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_11b_states.bin.z b/client/resources/hardnested_tables/bitflip_0_11b_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_11b_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_11b_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_11d_states.bin.z b/client/resources/hardnested_tables/bitflip_0_11d_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_11d_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_11d_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_11f_states.bin.z b/client/resources/hardnested_tables/bitflip_0_11f_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_11f_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_11f_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_124_states.bin.z b/client/resources/hardnested_tables/bitflip_0_124_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_124_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_124_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_12c_states.bin.z b/client/resources/hardnested_tables/bitflip_0_12c_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_12c_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_12c_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_131_states.bin.z b/client/resources/hardnested_tables/bitflip_0_131_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_131_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_131_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_133_states.bin.z b/client/resources/hardnested_tables/bitflip_0_133_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_133_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_133_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_135_states.bin.z b/client/resources/hardnested_tables/bitflip_0_135_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_135_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_135_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_137_states.bin.z b/client/resources/hardnested_tables/bitflip_0_137_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_137_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_137_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_139_states.bin.z b/client/resources/hardnested_tables/bitflip_0_139_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_139_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_139_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_13b_states.bin.z b/client/resources/hardnested_tables/bitflip_0_13b_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_13b_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_13b_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_13d_states.bin.z b/client/resources/hardnested_tables/bitflip_0_13d_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_13d_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_13d_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_13f_states.bin.z b/client/resources/hardnested_tables/bitflip_0_13f_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_13f_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_13f_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_141_states.bin.z b/client/resources/hardnested_tables/bitflip_0_141_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_141_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_141_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_143_states.bin.z b/client/resources/hardnested_tables/bitflip_0_143_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_143_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_143_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_145_states.bin.z b/client/resources/hardnested_tables/bitflip_0_145_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_145_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_145_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_147_states.bin.z b/client/resources/hardnested_tables/bitflip_0_147_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_147_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_147_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_149_states.bin.z b/client/resources/hardnested_tables/bitflip_0_149_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_149_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_149_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_14b_states.bin.z b/client/resources/hardnested_tables/bitflip_0_14b_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_14b_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_14b_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_14d_states.bin.z b/client/resources/hardnested_tables/bitflip_0_14d_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_14d_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_14d_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_14f_states.bin.z b/client/resources/hardnested_tables/bitflip_0_14f_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_14f_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_14f_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_150_states.bin.z b/client/resources/hardnested_tables/bitflip_0_150_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_150_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_150_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_154_states.bin.z b/client/resources/hardnested_tables/bitflip_0_154_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_154_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_154_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_15c_states.bin.z b/client/resources/hardnested_tables/bitflip_0_15c_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_15c_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_15c_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_161_states.bin.z b/client/resources/hardnested_tables/bitflip_0_161_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_161_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_161_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_163_states.bin.z b/client/resources/hardnested_tables/bitflip_0_163_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_163_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_163_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_165_states.bin.z b/client/resources/hardnested_tables/bitflip_0_165_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_165_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_165_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_167_states.bin.z b/client/resources/hardnested_tables/bitflip_0_167_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_167_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_167_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_169_states.bin.z b/client/resources/hardnested_tables/bitflip_0_169_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_169_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_169_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_16b_states.bin.z b/client/resources/hardnested_tables/bitflip_0_16b_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_16b_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_16b_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_16d_states.bin.z b/client/resources/hardnested_tables/bitflip_0_16d_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_16d_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_16d_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_16f_states.bin.z b/client/resources/hardnested_tables/bitflip_0_16f_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_16f_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_16f_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_170_states.bin.z b/client/resources/hardnested_tables/bitflip_0_170_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_170_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_170_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_174_states.bin.z b/client/resources/hardnested_tables/bitflip_0_174_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_174_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_174_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_17c_states.bin.z b/client/resources/hardnested_tables/bitflip_0_17c_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_17c_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_17c_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_184_states.bin.z b/client/resources/hardnested_tables/bitflip_0_184_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_184_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_184_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_18c_states.bin.z b/client/resources/hardnested_tables/bitflip_0_18c_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_18c_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_18c_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_191_states.bin.z b/client/resources/hardnested_tables/bitflip_0_191_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_191_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_191_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_193_states.bin.z b/client/resources/hardnested_tables/bitflip_0_193_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_193_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_193_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_195_states.bin.z b/client/resources/hardnested_tables/bitflip_0_195_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_195_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_195_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_197_states.bin.z b/client/resources/hardnested_tables/bitflip_0_197_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_197_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_197_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_199_states.bin.z b/client/resources/hardnested_tables/bitflip_0_199_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_199_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_199_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_19b_states.bin.z b/client/resources/hardnested_tables/bitflip_0_19b_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_19b_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_19b_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_19d_states.bin.z b/client/resources/hardnested_tables/bitflip_0_19d_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_19d_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_19d_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_19f_states.bin.z b/client/resources/hardnested_tables/bitflip_0_19f_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_19f_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_19f_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1a4_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1a4_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1a4_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1a4_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1ac_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1ac_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1ac_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1ac_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1b1_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1b1_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1b1_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1b1_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1b3_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1b3_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1b3_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1b3_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1b5_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1b5_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1b5_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1b5_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1b7_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1b7_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1b7_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1b7_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1b9_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1b9_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1b9_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1b9_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1bb_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1bb_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1bb_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1bb_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1bd_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1bd_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1bd_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1bd_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1bf_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1bf_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1bf_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1bf_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1c1_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1c1_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1c1_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1c1_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1c3_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1c3_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1c3_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1c3_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1c5_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1c5_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1c5_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1c5_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1c9_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1c9_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1c9_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1c9_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1cb_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1cb_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1cb_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1cb_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1d0_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1d0_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1d0_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1d0_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1d4_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1d4_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1d4_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1d4_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1dc_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1dc_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1dc_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1dc_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1e1_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1e1_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1e1_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1e1_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1e3_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1e3_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1e3_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1e3_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1e5_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1e5_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1e5_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1e5_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1e7_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1e7_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1e7_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1e7_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1e9_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1e9_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1e9_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1e9_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1eb_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1eb_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1eb_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1eb_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1ed_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1ed_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1ed_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1ed_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1ef_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1ef_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1ef_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1ef_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1f0_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1f0_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1f0_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1f0_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1f4_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1f4_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1f4_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1f4_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_1fc_states.bin.z b/client/resources/hardnested_tables/bitflip_0_1fc_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_1fc_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_1fc_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_210_states.bin.z b/client/resources/hardnested_tables/bitflip_0_210_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_210_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_210_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_225_states.bin.z b/client/resources/hardnested_tables/bitflip_0_225_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_225_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_225_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_227_states.bin.z b/client/resources/hardnested_tables/bitflip_0_227_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_227_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_227_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_22d_states.bin.z b/client/resources/hardnested_tables/bitflip_0_22d_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_22d_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_22d_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_22f_states.bin.z b/client/resources/hardnested_tables/bitflip_0_22f_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_22f_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_22f_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_240_states.bin.z b/client/resources/hardnested_tables/bitflip_0_240_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_240_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_240_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_275_states.bin.z b/client/resources/hardnested_tables/bitflip_0_275_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_275_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_275_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_277_states.bin.z b/client/resources/hardnested_tables/bitflip_0_277_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_277_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_277_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_27f_states.bin.z b/client/resources/hardnested_tables/bitflip_0_27f_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_27f_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_27f_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_294_states.bin.z b/client/resources/hardnested_tables/bitflip_0_294_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_294_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_294_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_2a1_states.bin.z b/client/resources/hardnested_tables/bitflip_0_2a1_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_2a1_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_2a1_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_2a3_states.bin.z b/client/resources/hardnested_tables/bitflip_0_2a3_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_2a3_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_2a3_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_2a9_states.bin.z b/client/resources/hardnested_tables/bitflip_0_2a9_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_2a9_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_2a9_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_2ab_states.bin.z b/client/resources/hardnested_tables/bitflip_0_2ab_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_2ab_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_2ab_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_2c4_states.bin.z b/client/resources/hardnested_tables/bitflip_0_2c4_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_2c4_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_2c4_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_2f1_states.bin.z b/client/resources/hardnested_tables/bitflip_0_2f1_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_2f1_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_2f1_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_2f3_states.bin.z b/client/resources/hardnested_tables/bitflip_0_2f3_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_2f3_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_2f3_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_2f9_states.bin.z b/client/resources/hardnested_tables/bitflip_0_2f9_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_2f9_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_2f9_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_2fb_states.bin.z b/client/resources/hardnested_tables/bitflip_0_2fb_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_2fb_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_2fb_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_335_states.bin.z b/client/resources/hardnested_tables/bitflip_0_335_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_335_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_335_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_337_states.bin.z b/client/resources/hardnested_tables/bitflip_0_337_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_337_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_337_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_33d_states.bin.z b/client/resources/hardnested_tables/bitflip_0_33d_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_33d_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_33d_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_33f_states.bin.z b/client/resources/hardnested_tables/bitflip_0_33f_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_33f_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_33f_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_350_states.bin.z b/client/resources/hardnested_tables/bitflip_0_350_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_350_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_350_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_365_states.bin.z b/client/resources/hardnested_tables/bitflip_0_365_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_365_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_365_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_367_states.bin.z b/client/resources/hardnested_tables/bitflip_0_367_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_367_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_367_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_36d_states.bin.z b/client/resources/hardnested_tables/bitflip_0_36d_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_36d_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_36d_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_36f_states.bin.z b/client/resources/hardnested_tables/bitflip_0_36f_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_36f_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_36f_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_384_states.bin.z b/client/resources/hardnested_tables/bitflip_0_384_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_384_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_384_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_3b1_states.bin.z b/client/resources/hardnested_tables/bitflip_0_3b1_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_3b1_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_3b1_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_3b3_states.bin.z b/client/resources/hardnested_tables/bitflip_0_3b3_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_3b3_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_3b3_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_3b9_states.bin.z b/client/resources/hardnested_tables/bitflip_0_3b9_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_3b9_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_3b9_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_3bb_states.bin.z b/client/resources/hardnested_tables/bitflip_0_3bb_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_3bb_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_3bb_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_3d4_states.bin.z b/client/resources/hardnested_tables/bitflip_0_3d4_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_3d4_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_3d4_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_3e1_states.bin.z b/client/resources/hardnested_tables/bitflip_0_3e1_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_3e1_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_3e1_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_3e3_states.bin.z b/client/resources/hardnested_tables/bitflip_0_3e3_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_3e3_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_3e3_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_3e9_states.bin.z b/client/resources/hardnested_tables/bitflip_0_3e9_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_3e9_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_3e9_states.bin.z diff --git a/client/hardnested/tables/bitflip_0_3eb_states.bin.z b/client/resources/hardnested_tables/bitflip_0_3eb_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_0_3eb_states.bin.z rename to client/resources/hardnested_tables/bitflip_0_3eb_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_002_states.bin.z b/client/resources/hardnested_tables/bitflip_1_002_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_002_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_002_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_008_states.bin.z b/client/resources/hardnested_tables/bitflip_1_008_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_008_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_008_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_00a_states.bin.z b/client/resources/hardnested_tables/bitflip_1_00a_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_00a_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_00a_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_012_states.bin.z b/client/resources/hardnested_tables/bitflip_1_012_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_012_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_012_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_018_states.bin.z b/client/resources/hardnested_tables/bitflip_1_018_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_018_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_018_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_01a_states.bin.z b/client/resources/hardnested_tables/bitflip_1_01a_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_01a_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_01a_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_020_states.bin.z b/client/resources/hardnested_tables/bitflip_1_020_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_020_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_020_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_028_states.bin.z b/client/resources/hardnested_tables/bitflip_1_028_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_028_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_028_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_02a_states.bin.z b/client/resources/hardnested_tables/bitflip_1_02a_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_02a_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_02a_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_02e_states.bin.z b/client/resources/hardnested_tables/bitflip_1_02e_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_02e_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_02e_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_032_states.bin.z b/client/resources/hardnested_tables/bitflip_1_032_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_032_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_032_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_036_states.bin.z b/client/resources/hardnested_tables/bitflip_1_036_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_036_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_036_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_038_states.bin.z b/client/resources/hardnested_tables/bitflip_1_038_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_038_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_038_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_03a_states.bin.z b/client/resources/hardnested_tables/bitflip_1_03a_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_03a_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_03a_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_03e_states.bin.z b/client/resources/hardnested_tables/bitflip_1_03e_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_03e_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_03e_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_040_states.bin.z b/client/resources/hardnested_tables/bitflip_1_040_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_040_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_040_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_042_states.bin.z b/client/resources/hardnested_tables/bitflip_1_042_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_042_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_042_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_046_states.bin.z b/client/resources/hardnested_tables/bitflip_1_046_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_046_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_046_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_048_states.bin.z b/client/resources/hardnested_tables/bitflip_1_048_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_048_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_048_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_04a_states.bin.z b/client/resources/hardnested_tables/bitflip_1_04a_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_04a_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_04a_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_04e_states.bin.z b/client/resources/hardnested_tables/bitflip_1_04e_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_04e_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_04e_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_052_states.bin.z b/client/resources/hardnested_tables/bitflip_1_052_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_052_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_052_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_056_states.bin.z b/client/resources/hardnested_tables/bitflip_1_056_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_056_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_056_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_058_states.bin.z b/client/resources/hardnested_tables/bitflip_1_058_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_058_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_058_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_05a_states.bin.z b/client/resources/hardnested_tables/bitflip_1_05a_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_05a_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_05a_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_05e_states.bin.z b/client/resources/hardnested_tables/bitflip_1_05e_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_05e_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_05e_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_060_states.bin.z b/client/resources/hardnested_tables/bitflip_1_060_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_060_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_060_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_062_states.bin.z b/client/resources/hardnested_tables/bitflip_1_062_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_062_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_062_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_066_states.bin.z b/client/resources/hardnested_tables/bitflip_1_066_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_066_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_066_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_068_states.bin.z b/client/resources/hardnested_tables/bitflip_1_068_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_068_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_068_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_06a_states.bin.z b/client/resources/hardnested_tables/bitflip_1_06a_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_06a_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_06a_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_06e_states.bin.z b/client/resources/hardnested_tables/bitflip_1_06e_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_06e_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_06e_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_072_states.bin.z b/client/resources/hardnested_tables/bitflip_1_072_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_072_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_072_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_076_states.bin.z b/client/resources/hardnested_tables/bitflip_1_076_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_076_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_076_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_078_states.bin.z b/client/resources/hardnested_tables/bitflip_1_078_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_078_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_078_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_07a_states.bin.z b/client/resources/hardnested_tables/bitflip_1_07a_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_07a_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_07a_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_07e_states.bin.z b/client/resources/hardnested_tables/bitflip_1_07e_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_07e_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_07e_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_080_states.bin.z b/client/resources/hardnested_tables/bitflip_1_080_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_080_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_080_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_082_states.bin.z b/client/resources/hardnested_tables/bitflip_1_082_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_082_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_082_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_086_states.bin.z b/client/resources/hardnested_tables/bitflip_1_086_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_086_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_086_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_088_states.bin.z b/client/resources/hardnested_tables/bitflip_1_088_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_088_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_088_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_08a_states.bin.z b/client/resources/hardnested_tables/bitflip_1_08a_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_08a_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_08a_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_08e_states.bin.z b/client/resources/hardnested_tables/bitflip_1_08e_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_08e_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_08e_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_092_states.bin.z b/client/resources/hardnested_tables/bitflip_1_092_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_092_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_092_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_096_states.bin.z b/client/resources/hardnested_tables/bitflip_1_096_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_096_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_096_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_098_states.bin.z b/client/resources/hardnested_tables/bitflip_1_098_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_098_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_098_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_09a_states.bin.z b/client/resources/hardnested_tables/bitflip_1_09a_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_09a_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_09a_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_09e_states.bin.z b/client/resources/hardnested_tables/bitflip_1_09e_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_09e_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_09e_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0a0_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0a0_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0a0_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0a0_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0a2_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0a2_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0a2_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0a2_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0a6_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0a6_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0a6_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0a6_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0a8_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0a8_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0a8_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0a8_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0aa_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0aa_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0aa_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0aa_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0ae_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0ae_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0ae_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0ae_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0b2_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0b2_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0b2_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0b2_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0b6_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0b6_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0b6_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0b6_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0b8_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0b8_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0b8_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0b8_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0ba_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0ba_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0ba_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0ba_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0be_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0be_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0be_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0be_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0c0_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0c0_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0c0_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0c0_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0c2_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0c2_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0c2_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0c2_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0c6_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0c6_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0c6_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0c6_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0c8_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0c8_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0c8_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0c8_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0ca_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0ca_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0ca_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0ca_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0ce_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0ce_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0ce_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0ce_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0d2_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0d2_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0d2_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0d2_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0d6_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0d6_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0d6_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0d6_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0d8_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0d8_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0d8_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0d8_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0da_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0da_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0da_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0da_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0de_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0de_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0de_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0de_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0e0_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0e0_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0e0_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0e0_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0e8_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0e8_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0e8_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0e8_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_0f8_states.bin.z b/client/resources/hardnested_tables/bitflip_1_0f8_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_0f8_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_0f8_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_108_states.bin.z b/client/resources/hardnested_tables/bitflip_1_108_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_108_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_108_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_111_states.bin.z b/client/resources/hardnested_tables/bitflip_1_111_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_111_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_111_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_113_states.bin.z b/client/resources/hardnested_tables/bitflip_1_113_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_113_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_113_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_115_states.bin.z b/client/resources/hardnested_tables/bitflip_1_115_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_115_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_115_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_117_states.bin.z b/client/resources/hardnested_tables/bitflip_1_117_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_117_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_117_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_118_states.bin.z b/client/resources/hardnested_tables/bitflip_1_118_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_118_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_118_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_11a_states.bin.z b/client/resources/hardnested_tables/bitflip_1_11a_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_11a_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_11a_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_11b_states.bin.z b/client/resources/hardnested_tables/bitflip_1_11b_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_11b_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_11b_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_120_states.bin.z b/client/resources/hardnested_tables/bitflip_1_120_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_120_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_120_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_122_states.bin.z b/client/resources/hardnested_tables/bitflip_1_122_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_122_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_122_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_128_states.bin.z b/client/resources/hardnested_tables/bitflip_1_128_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_128_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_128_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_131_states.bin.z b/client/resources/hardnested_tables/bitflip_1_131_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_131_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_131_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_135_states.bin.z b/client/resources/hardnested_tables/bitflip_1_135_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_135_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_135_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_138_states.bin.z b/client/resources/hardnested_tables/bitflip_1_138_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_138_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_138_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_145_states.bin.z b/client/resources/hardnested_tables/bitflip_1_145_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_145_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_145_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_147_states.bin.z b/client/resources/hardnested_tables/bitflip_1_147_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_147_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_147_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_148_states.bin.z b/client/resources/hardnested_tables/bitflip_1_148_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_148_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_148_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_158_states.bin.z b/client/resources/hardnested_tables/bitflip_1_158_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_158_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_158_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_160_states.bin.z b/client/resources/hardnested_tables/bitflip_1_160_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_160_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_160_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_161_states.bin.z b/client/resources/hardnested_tables/bitflip_1_161_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_161_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_161_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_163_states.bin.z b/client/resources/hardnested_tables/bitflip_1_163_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_163_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_163_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_165_states.bin.z b/client/resources/hardnested_tables/bitflip_1_165_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_165_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_165_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_168_states.bin.z b/client/resources/hardnested_tables/bitflip_1_168_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_168_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_168_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_178_states.bin.z b/client/resources/hardnested_tables/bitflip_1_178_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_178_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_178_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_180_states.bin.z b/client/resources/hardnested_tables/bitflip_1_180_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_180_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_180_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_188_states.bin.z b/client/resources/hardnested_tables/bitflip_1_188_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_188_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_188_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_191_states.bin.z b/client/resources/hardnested_tables/bitflip_1_191_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_191_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_191_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_198_states.bin.z b/client/resources/hardnested_tables/bitflip_1_198_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_198_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_198_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_199_states.bin.z b/client/resources/hardnested_tables/bitflip_1_199_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_199_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_199_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_19d_states.bin.z b/client/resources/hardnested_tables/bitflip_1_19d_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_19d_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_19d_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_19f_states.bin.z b/client/resources/hardnested_tables/bitflip_1_19f_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_19f_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_19f_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1a0_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1a0_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1a0_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1a0_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1a8_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1a8_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1a8_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1a8_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1b3_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1b3_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1b3_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1b3_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1b5_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1b5_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1b5_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1b5_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1b7_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1b7_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1b7_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1b7_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1b8_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1b8_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1b8_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1b8_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1b9_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1b9_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1b9_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1b9_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1bd_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1bd_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1bd_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1bd_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1c1_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1c1_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1c1_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1c1_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1c3_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1c3_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1c3_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1c3_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1c8_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1c8_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1c8_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1c8_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1c9_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1c9_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1c9_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1c9_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1cd_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1cd_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1cd_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1cd_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1cf_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1cf_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1cf_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1cf_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1d8_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1d8_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1d8_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1d8_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1e0_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1e0_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1e0_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1e0_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1e1_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1e1_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1e1_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1e1_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1e5_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1e5_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1e5_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1e5_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1e7_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1e7_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1e7_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1e7_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1e8_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1e8_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1e8_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1e8_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1e9_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1e9_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1e9_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1e9_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1eb_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1eb_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1eb_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1eb_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1ed_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1ed_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1ed_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1ed_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_1f8_states.bin.z b/client/resources/hardnested_tables/bitflip_1_1f8_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_1f8_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_1f8_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_208_states.bin.z b/client/resources/hardnested_tables/bitflip_1_208_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_208_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_208_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_220_states.bin.z b/client/resources/hardnested_tables/bitflip_1_220_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_220_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_220_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_24a_states.bin.z b/client/resources/hardnested_tables/bitflip_1_24a_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_24a_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_24a_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_24e_states.bin.z b/client/resources/hardnested_tables/bitflip_1_24e_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_24e_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_24e_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_25a_states.bin.z b/client/resources/hardnested_tables/bitflip_1_25a_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_25a_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_25a_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_25e_states.bin.z b/client/resources/hardnested_tables/bitflip_1_25e_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_25e_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_25e_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_262_states.bin.z b/client/resources/hardnested_tables/bitflip_1_262_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_262_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_262_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_266_states.bin.z b/client/resources/hardnested_tables/bitflip_1_266_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_266_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_266_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_272_states.bin.z b/client/resources/hardnested_tables/bitflip_1_272_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_272_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_272_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_276_states.bin.z b/client/resources/hardnested_tables/bitflip_1_276_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_276_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_276_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_280_states.bin.z b/client/resources/hardnested_tables/bitflip_1_280_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_280_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_280_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_2a8_states.bin.z b/client/resources/hardnested_tables/bitflip_1_2a8_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_2a8_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_2a8_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_2c2_states.bin.z b/client/resources/hardnested_tables/bitflip_1_2c2_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_2c2_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_2c2_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_2c6_states.bin.z b/client/resources/hardnested_tables/bitflip_1_2c6_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_2c6_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_2c6_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_2d2_states.bin.z b/client/resources/hardnested_tables/bitflip_1_2d2_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_2d2_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_2d2_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_2d6_states.bin.z b/client/resources/hardnested_tables/bitflip_1_2d6_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_2d6_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_2d6_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_328_states.bin.z b/client/resources/hardnested_tables/bitflip_1_328_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_328_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_328_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_388_states.bin.z b/client/resources/hardnested_tables/bitflip_1_388_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_388_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_388_states.bin.z diff --git a/client/hardnested/tables/bitflip_1_3a0_states.bin.z b/client/resources/hardnested_tables/bitflip_1_3a0_states.bin.z similarity index 100% rename from client/hardnested/tables/bitflip_1_3a0_states.bin.z rename to client/resources/hardnested_tables/bitflip_1_3a0_states.bin.z diff --git a/client/loclass/iclass_dump.bin b/client/resources/iclass_dump.bin similarity index 100% rename from client/loclass/iclass_dump.bin rename to client/resources/iclass_dump.bin diff --git a/client/crypto/oids.json b/client/resources/oids.json similarity index 100% rename from client/crypto/oids.json rename to client/resources/oids.json diff --git a/client/reveng/Makefile b/client/reveng/Makefile new file mode 100644 index 000000000..c29538fa5 --- /dev/null +++ b/client/reveng/Makefile @@ -0,0 +1,33 @@ +# reveng will compile without macros, but these may be useful: +# Add -DBMPMACRO to use bitmap size constant macros (edit config.h) +# Add -DNOFORCE to disable the -F switch +# Add -DPRESETS to compile with preset models (edit config.h) + +MYSRCPATHS = +MYINCLUDES = -I. -I.. +MYCFLAGS = -std=c99 -D_ISOC99_SOURCE +MYDEFS = -DPRESETS +MYSRCS = \ + bmpbit.c \ + cli.c \ + getopt.c \ + model.c \ + poly.c \ + preset.c \ + reveng.c + +LIB_A = libreveng.a + +include ../../Makefile.host + +CLEAN += bmptst + +$(BINDIR)/$(LIB_A): $(BINDIR)/bmptst + +$(BINDIR)/bmptst: bmpbit.c config.h reveng.h + $(info [-] CC $<) + $(Q)$(CC) $(CFLAGS) -DBMPTST -o $@ $< + $(info [=] TEST $@) + $(Q)( ./$@ && $(TOUCH) $@ ) || ( $(RM) $@ && $(FALSE) ) + +.PHONY: all clean diff --git a/client/reveng/bmpbit.c b/client/reveng/bmpbit.c index d529b0e96..e44ddb250 100644 --- a/client/reveng/bmpbit.c +++ b/client/reveng/bmpbit.c @@ -67,7 +67,7 @@ main(int argc, char *argv[]) { setbmp(); if (BMP_BIT != bmpbit || BMP_SUB != bmpsub) { fprintf(stderr, "reveng: configuration fault. Update " - "config.h with these definitions and " + "reveng/config.h with these definitions and " "recompile:\n" "\t#define BMP_BIT %d\n" "\t#define BMP_SUB %d\n", diff --git a/client/reveng/config.h b/client/reveng/config.h index a4d46e9f2..94d3c4da5 100644 --- a/client/reveng/config.h +++ b/client/reveng/config.h @@ -57,33 +57,44 @@ /* #define ALWPCK 1 */ -/* Define PRESETS to compile CRC RevEng with the preset models from the +/* #define PRESETS 1 + * Define PRESETS to compile CRC RevEng with the preset models from the * CRC Catalogue. This implies BMPMACRO and so makes the code platform- * specific. */ -#ifdef _WIN32 -#define PRESETS 1 // -#endif - - -/* Macros defining the size of a bmp_t. +/* #define BMP_BIT 32 + * Macros defining the size of a bmp_t. * Their values only matter if PRESETS and/or BMPMACRO are defined, in * which case edit the macros below to suit your architecture. * Otherwise, BMP_BIT and BMP_SUB will be redefined as aliases of bmpbit * and bmpsub, global objects initialised at run time. */ -/* Size in bits of a bmp_t. Not necessarily a power of two. */ - -#define BMP_BIT 32 - -/* The highest power of two that is strictly less than BMP_BIT. +/* #define BMP_SUB 16 + * The highest power of two that is strictly less than BMP_BIT. * Initialises the index of a binary search for set bits in a bmp_t. */ + +#include +#include +#if ULONG_MAX == UINT64_MAX +// most 64-bit platforms +#define PRESETS 1 +#define BMP_BIT 64 +#define BMP_SUB 32 + +#elif ULONG_MAX == UINT32_MAX +// 32-bit platforms and Mingw64 +#define PRESETS 1 +#define BMP_BIT 32 #define BMP_SUB 16 +#else +#error Cannot determine automatically REVENG PRESETS Macros for your platform, you need to set them manually +#endif + /***************************************** * * * End of user configuration options * diff --git a/client/reveng/poly.c b/client/reveng/poly.c index 0fc6555d9..44f5709f4 100644 --- a/client/reveng/poly.c +++ b/client/reveng/poly.c @@ -600,9 +600,6 @@ plast(const poly_t poly) { idx = size - 1UL; while (idx && !(accu = poly.bitmap[idx])) --idx; - if (poly.length == 24) - printf("ICE plast B - poly.length %lu vs size %lu idx %lu bitmap %ld\n", poly.length, size, idx, poly.bitmap[idx]); - if (!idx && !(accu = poly.bitmap[idx])) return (0UL); /* now accu == poly.bitmap[idx] and contains last significant term */ @@ -1080,10 +1077,6 @@ praloc(poly_t *poly, unsigned long length) { if (poly->bitmap) { - if (poly->length == 24) - printf("ICE praloc - poly->length %lu\n", poly->length); - - if (poly->length < length) { /* poly->length >= 0, length > 0, size > 0. * poly expanded. clear old last word and all new words @@ -1094,15 +1087,11 @@ praloc(poly_t *poly, unsigned long length) { while (oldsize < size) poly->bitmap[oldsize++] = BMP_C(0); - if (poly->length == 24) printf("ICE praloc MISS A\n"); - } else if (LOFS(length)) { /* poly->length >= length > 0. * poly shrunk. clear new last word */ poly->bitmap[size - 1UL] &= ~(~BMP_C(0) >> LOFS(length)); - - if (poly->length == 24) printf("ICE praloc B size %lu, bm %lu \n", size, poly->bitmap[size - 1UL]); } poly->length = length; diff --git a/client/scripting.c b/client/scripting.c index 4a2ff28d6..724f72235 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -10,6 +10,29 @@ //----------------------------------------------------------------------------- #include "scripting.h" +#include +#include + +#include "lauxlib.h" +#include "cmdmain.h" +#include "comms.h" +#include "mifare/mifarehost.h" +#include "crc.h" +#include "crc64.h" +#include "mbedtls/sha1.h" +#include "mbedtls/aes.h" +#include "cmdcrc.h" +#include "cmdhfmfhard.h" +#include "cmdhfmfu.h" +#include "cmdlft55xx.h" // read t55xx etc +#include "mifare/ndef.h" // ndef parsing +#include "commonutil.h" +#include "ui.h" +#include "proxmark3.h" +#include "crc16.h" +#include "protocols.h" +#include "fileutils.h" // searchfile + static int returnToLuaWithError(lua_State *L, const char *fmt, ...) { char buffer[200]; va_list args; @@ -28,7 +51,7 @@ static int l_clearCommandBuffer(lua_State *L) { } /** - * Enable / Disable fast push mode for lua scripts like mfkeys + * Enable / Disable fast push mode for lua scripts like mfckeys * The following params expected: * *@brief l_fast_push_mode @@ -66,7 +89,7 @@ static int l_fast_push_mode(lua_State *L) { * @return */ static int l_SendCommandOLD(lua_State *L) { -// SendCommandMIX(CMD_HF_SNIFFER, skippairs, skiptriggers, 0, NULL, 0); +// SendCommandMIX(CMD_HF_SNIFF, skippairs, skiptriggers, 0, NULL, 0); // (uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len) uint64_t cmd, arg0, arg1, arg2; @@ -395,7 +418,7 @@ static int l_foobar(lua_State *L) { printf("Arguments discarded, stack now contains %d elements", lua_gettop(L)); // todo: this is not used, where was it intended for? - // PacketCommandOLD response = {CMD_MIFARE_READBL, {1337, 1338, 1339}, {{0}}}; + // PacketCommandOLD response = {CMD_HF_MIFARE_READBL, {1337, 1338, 1339}, {{0}}}; printf("Now returning a uint64_t as a string"); uint64_t x = 0xDEADC0DE; @@ -1030,6 +1053,29 @@ static int l_ndefparse(lua_State *L) { return 1; } +static int l_searchfile(lua_State *L) { + //Check number of arguments + int n = lua_gettop(L); + if (n != 2) { + return returnToLuaWithError(L, "Only filename and extension"); + } + + size_t size; + // data + const char *filename = luaL_checklstring(L, 1, &size); + if (size == 0) + return returnToLuaWithError(L, "Must specify filename"); + + const char *suffix = luaL_checklstring(L, 2, &size); + char *path; + int res = searchFile(&path, "", filename, suffix, false); + if (res != PM3_SUCCESS) { + return returnToLuaWithError(L, "Failed to find file"); + } + + lua_pushstring(L, path); + return 1; +} /** * @brief Sets the lua path to include "./lualibs/?.lua", in order for a script to be @@ -1090,6 +1136,7 @@ int set_pm3_libraries(lua_State *L) { {"t55xx_detect", l_T55xx_detect}, {"ndefparse", l_ndefparse}, {"fast_push_mode", l_fast_push_mode}, + {"search_file", l_searchfile}, {NULL, NULL} }; @@ -1109,21 +1156,57 @@ int set_pm3_libraries(lua_State *L) { //-- remove the global environment table from the stack lua_pop(L, 1); - //--add to the LUA_PATH (package.path in lua) - // so we can load scripts from the ./scripts/ - directory - char scripts_path[strlen(get_my_executable_directory()) + strlen(LUA_SCRIPTS_DIRECTORY) + strlen(LUA_LIBRARIES_WILDCARD) + 1]; - strcpy(scripts_path, get_my_executable_directory()); - strcat(scripts_path, LUA_SCRIPTS_DIRECTORY); - strcat(scripts_path, LUA_LIBRARIES_WILDCARD); - setLuaPath(L, scripts_path); + // so we can load scripts from various places: + const char *exec_path = get_my_executable_directory(); + if (exec_path != NULL) { + // from the ./luascripts/ directory + char scripts_path[strlen(exec_path) + strlen(LUA_SCRIPTS_SUBDIR) + strlen(LUA_LIBRARIES_WILDCARD) + 1]; + strcpy(scripts_path, exec_path); + strcat(scripts_path, LUA_SCRIPTS_SUBDIR); + strcat(scripts_path, LUA_LIBRARIES_WILDCARD); + setLuaPath(L, scripts_path); + // from the ./lualib/ directory + char libraries_path[strlen(exec_path) + strlen(LUA_LIBRARIES_SUBDIR) + strlen(LUA_LIBRARIES_WILDCARD) + 1]; + strcpy(libraries_path, exec_path); + strcat(libraries_path, LUA_LIBRARIES_SUBDIR); + strcat(libraries_path, LUA_LIBRARIES_WILDCARD); + setLuaPath(L, libraries_path); + } + char *user_path = getenv("HOME"); + if (user_path != NULL) { + // from the $HOME/.proxmark3/luascripts/ directory + char scripts_path[strlen(user_path) + strlen(PM3_USER_DIRECTORY) + strlen(LUA_SCRIPTS_SUBDIR) + strlen(LUA_LIBRARIES_WILDCARD) + 1]; + strcpy(scripts_path, user_path); + strcat(scripts_path, PM3_USER_DIRECTORY); + strcat(scripts_path, LUA_SCRIPTS_SUBDIR); + strcat(scripts_path, LUA_LIBRARIES_WILDCARD); + setLuaPath(L, scripts_path); - //-- Last but not least, add to the LUA_PATH (package.path in lua) - // so we can load libraries from the ./lualib/ - directory - char libraries_path[strlen(get_my_executable_directory()) + strlen(LUA_LIBRARIES_DIRECTORY) + strlen(LUA_LIBRARIES_WILDCARD) + 1]; - strcpy(libraries_path, get_my_executable_directory()); - strcat(libraries_path, LUA_LIBRARIES_DIRECTORY); - strcat(libraries_path, LUA_LIBRARIES_WILDCARD); - setLuaPath(L, libraries_path); + // from the $HOME/.proxmark3/lualib/ directory + char libraries_path[strlen(user_path) + strlen(PM3_USER_DIRECTORY) + strlen(LUA_LIBRARIES_SUBDIR) + strlen(LUA_LIBRARIES_WILDCARD) + 1]; + strcpy(libraries_path, user_path); + strcat(libraries_path, PM3_USER_DIRECTORY); + strcat(libraries_path, LUA_LIBRARIES_SUBDIR); + strcat(libraries_path, LUA_LIBRARIES_WILDCARD); + setLuaPath(L, libraries_path); + } + + if (exec_path != NULL) { + // from the $PREFIX/share/proxmark3/luascripts/ directory + char scripts_path[strlen(exec_path) + strlen(PM3_SHARE_RELPATH) + strlen(LUA_SCRIPTS_SUBDIR) + strlen(LUA_LIBRARIES_WILDCARD) + 1]; + strcpy(scripts_path, exec_path); + strcat(scripts_path, PM3_SHARE_RELPATH); + strcat(scripts_path, LUA_SCRIPTS_SUBDIR); + strcat(scripts_path, LUA_LIBRARIES_WILDCARD); + setLuaPath(L, scripts_path); + // from the $PREFIX/share/proxmark3/lualib/ directory + char libraries_path[strlen(exec_path) + strlen(PM3_SHARE_RELPATH) + strlen(LUA_LIBRARIES_SUBDIR) + strlen(LUA_LIBRARIES_WILDCARD) + 1]; + strcpy(libraries_path, exec_path); + strcat(libraries_path, PM3_SHARE_RELPATH); + strcat(libraries_path, LUA_LIBRARIES_SUBDIR); + strcat(libraries_path, LUA_LIBRARIES_WILDCARD); + setLuaPath(L, libraries_path); + } return 1; } diff --git a/client/scripting.h b/client/scripting.h index 5b8c15ddd..b23ce3a9a 100644 --- a/client/scripting.h +++ b/client/scripting.h @@ -10,30 +10,10 @@ #ifndef SCRIPTING_H__ #define SCRIPTING_H__ -#include #include -#include -#include -#include "proxmark3.h" -#include "pm3_cmd.h" -#include "cmdmain.h" -#include "comms.h" -#include "util.h" -#include "mifare/mifarehost.h" -#include "crc.h" -#include "crc16.h" -#include "crc64.h" -#include "mbedtls/sha1.h" -#include "mbedtls/aes.h" -#include "cmdcrc.h" -#include "cmdhfmfhard.h" -#include "cmdhfmfu.h" -#include "protocols.h" -#include "cmdlft55xx.h" // read t55xx etc -#include "mifare/ndef.h" // ndef parsing +//#include +//#include -#define LUA_LIBRARIES_DIRECTORY "lualibs/" -#define LUA_SCRIPTS_DIRECTORY "scripts/" #define LUA_LIBRARIES_WILDCARD "?.lua" /** diff --git a/common/tea.c b/client/tea.c similarity index 97% rename from common/tea.c rename to client/tea.c index 187f8a3bc..b2a425e11 100644 --- a/common/tea.c +++ b/client/tea.c @@ -7,6 +7,9 @@ // ref: http://143.53.36.235:8080/source.htm#ansi //----------------------------------------------------------------------------- #include "tea.h" + +#include "commonutil.h" // bytes_to_num etc + #define ROUNDS 32 #define DELTA 0x9E3779B9 #define SUM 0xC6EF3720 diff --git a/common/tea.h b/client/tea.h similarity index 90% rename from common/tea.h rename to client/tea.h index 57be7e834..3390b9d92 100644 --- a/common/tea.h +++ b/client/tea.h @@ -10,9 +10,9 @@ #ifndef __TEA_H #define __TEA_H -#include "commonutil.h" -#include -#include +#include "common.h" + void tea_encrypt(uint8_t *v, uint8_t *key); void tea_decrypt(uint8_t *v, uint8_t *key); + #endif /* __TEA_H */ diff --git a/client/tinycbor/Makefile b/client/tinycbor/Makefile index af22846e9..6470246d4 100644 --- a/client/tinycbor/Makefile +++ b/client/tinycbor/Makefile @@ -1,11 +1,10 @@ -# Hide full compilation line: -ifneq ($(V),1) - Q?=@ -endif -# To see full command lines, use make V=1 - -LIB_A = tinycbor.a -tinycbor_SOURCES = \ +MYSRCPATHS = +MYINCLUDES = +# Strange errors on Mingw when compiling with C99 +#MYCFLAGS = -std=c99 -D_ISOC99_SOURCE +MYCFLAGS = +MYDEFS = +MYSRCS = \ cborencoder.c \ cborencoder_close_container_checked.c \ cborerrorstrings.c \ @@ -15,48 +14,9 @@ tinycbor_SOURCES = \ cbortojson.c \ cborvalidation.c \ -CFILES = $(filter %.c, $(tinycbor_SOURCES)) -CMDOBJS = $(CFILES:%.c=%.o) -CLEAN = $(CMDOBJS) +LIB_A = tinycbor.a -platform = $(shell uname) - -CC= gcc -CFLAGS= -O2 -Wall -Wno-unused-variable -Wno-unused-function -LIBS= $(SYSLIBS) $(MYLIBS) -DEFAULT_INCLUDES = -I. -I.. -DEFS = -DHAVE_STDINT_H - -ifeq ($(platform),Darwin) -AR= /usr/bin/ar rcs -RANLIB= /usr/bin/ranlib -else -AR= ar rcs -RANLIB= ranlib -endif -RM= rm -f -TST= echo - -SYSLDFLAGS= -SYSLIBS= - -MYLIBS= -MYOBJS= - -$(LIB_A): $(CMDOBJS) - $(info [=] AR $@) - $(Q)$(AR) $(LIB_A) $(CMDOBJS) - $(Q)$(RANLIB) $(LIB_A) - -all: $(LIB_A) - -clean: - $(Q)$(RM) $(CLEAN) - $(Q)$(RM) $(LIB_A) - -%.o: %.c - $(info [-] CC $<) - $(Q)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(CFLAGS) -c -o $@ $< $(LIBS) - -.PHONY: all clean +# Strange errors on Mingw when compiling with -O3 +CFLAGS ?= -Wall -Werror -O2 +include ../../Makefile.host diff --git a/uart/README.md b/client/uart/README.md similarity index 100% rename from uart/README.md rename to client/uart/README.md diff --git a/uart/uart.h b/client/uart/uart.h similarity index 91% rename from uart/uart.h rename to client/uart/uart.h index a4f2f1f85..172e7db0d 100644 --- a/uart/uart.h +++ b/client/uart/uart.h @@ -32,25 +32,7 @@ #ifndef _UART_H_ #define _UART_H_ -#include -#include -#include - -#include -#include #include "common.h" -#include "comms.h" -#include "util_posix.h" // msclock - - - -#if defined (_WIN32) -#define SERIAL_PORT_EXAMPLE_H "com3" -#elif defined(__APPLE__) -#define SERIAL_PORT_EXAMPLE_H "/dev/cu.usbmodem" -#else -#define SERIAL_PORT_EXAMPLE_H "/dev/ttyACM0" -#endif /* serial_port is declared as a void*, which you should cast to whatever type * makes sense to your connection method. Both the posix and win32 diff --git a/uart/uart_posix.c b/client/uart/uart_posix.c similarity index 98% rename from uart/uart_posix.c rename to client/uart/uart_posix.c index ea535fd73..0077924cf 100644 --- a/uart/uart_posix.c +++ b/client/uart/uart_posix.c @@ -39,22 +39,18 @@ #include "uart.h" +#include +#include +#include #include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include #include +#include "comms.h" + // Taken from https://github.com/unbit/uwsgi/commit/b608eb1772641d525bfde268fe9d6d8d0d5efde7 #ifndef SOL_TCP # define SOL_TCP IPPROTO_TCP diff --git a/uart/uart_win32.c b/client/uart/uart_win32.c similarity index 98% rename from uart/uart_win32.c rename to client/uart/uart_win32.c index 5a5f8b9d3..bbb5bfcfa 100644 --- a/uart/uart_win32.c +++ b/client/uart/uart_win32.c @@ -38,6 +38,12 @@ #include "uart.h" +#include +#include +#include + +#include "comms.h" + // The windows serial port implementation #ifdef _WIN32 #include diff --git a/client/ui.c b/client/ui.c index 0dcaca9e6..883ea963a 100644 --- a/client/ui.c +++ b/client/ui.c @@ -16,6 +16,21 @@ #endif #include "ui.h" +#include "commonutil.h" // ARRAYLEN + +#include // for Mingw readline +#include +#include +#include +#include +#include "util.h" +#include "proxmark3.h" // PROXLOG +#include "fileutils.h" +#include "pm3_cmd.h" +#ifdef _WIN32 +# include // _mkdir +#endif +#include session_arg_t session; double CursorScaleFactor = 1; @@ -27,9 +42,61 @@ bool GridLocked = false; bool showDemod = true; pthread_mutex_t print_lock = PTHREAD_MUTEX_INITIALIZER; -static const char *logfilename = "proxmark3.log"; + static void fPrintAndLog(FILE *stream, const char *fmt, ...); +// needed by flasher, so let's put it here instead of fileutils.c +int searchHomeFilePath(char **foundpath, const char *filename, bool create_home) { + if (foundpath == NULL) + return PM3_EINVARG; + char *user_path = getenv("HOME"); + if (user_path == NULL) { + fprintf(stderr, "Could not retrieve $HOME from the environment\n"); + return PM3_EFILE; + } + char *path = calloc(strlen(user_path) + strlen(PM3_USER_DIRECTORY) + 1, sizeof(char)); + if (path == NULL) + return PM3_EMALLOC; + strcpy(path, user_path); + strcat(path, PM3_USER_DIRECTORY); + + int result; +#ifdef _WIN32 + struct _stat st; + // Mingw _stat fails if path ends with /, so let's use a stripped path + if (path[strlen(path) - 1] == '/') { + path[strlen(path) - 1] = '\0'; + result = _stat(path, &st); + path[strlen(path)] = '/'; + } else { + result = _stat(path, &st); + } +#else + struct stat st; + result = stat(path, &st); +#endif + if ((result != 0) && create_home) { + +#ifdef _WIN32 + if (_mkdir(path)) { +#else + if (mkdir(path, 0700)) { +#endif + fprintf(stderr, "Could not create user directory %s\n", path); + free(path); + return PM3_EFILE; + } + } + if (filename == NULL) { + *foundpath = path; + return PM3_SUCCESS; + } + path = realloc(path, (strlen(user_path) + strlen(PM3_USER_DIRECTORY) + strlen(filename) + 1) * sizeof(char)); + strcat(path, filename); + *foundpath = path; + return PM3_SUCCESS; +} + void PrintAndLogOptions(const char *str[][2], size_t size, size_t space) { char buff[2000] = "Options:\n"; char format[2000] = ""; @@ -156,11 +223,26 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) { // lock this section to avoid interlacing prints from different threads pthread_mutex_lock(&print_lock); - if (logging && !logfile) { - logfile = fopen(logfilename, "a"); - if (!logfile) { - fprintf(stderr, "Can't open logfile, logging disabled!\n"); + if ((g_printAndLog & PRINTANDLOG_LOG) && logging && !logfile) { + char *my_logfile_path = NULL; + char filename[40]; + struct tm *timenow; + time_t now = time(NULL); + timenow = gmtime(&now); + strftime(filename, sizeof(filename), PROXLOG, timenow); + if (searchHomeFilePath(&my_logfile_path, filename, true) != PM3_SUCCESS) { + fprintf(stderr, "[-] Logging disabled!\n\n"); + my_logfile_path = NULL; logging = 0; + } else { + logfile = fopen(my_logfile_path, "a"); + if (logfile == NULL) { + fprintf(stderr, "[-] Can't open logfile %s, logging disabled!\n", my_logfile_path); + logging = 0; + } else { + printf("[=] Session log %s\n", my_logfile_path); + } + free(my_logfile_path); } } @@ -187,9 +269,11 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) { bool filter_ansi = !session.supports_colors; memcpy_filter_ansi(buffer2, buffer, sizeof(buffer), filter_ansi); - fprintf(stream, "%s", buffer2); - fprintf(stream, " "); // cleaning prompt - fprintf(stream, "\n"); + if (g_printAndLog & PRINTANDLOG_PRINT) { + fprintf(stream, "%s", buffer2); + fprintf(stream, " "); // cleaning prompt + fprintf(stream, "\n"); + } #ifdef RL_STATE_READCMD // We are using GNU readline. libedit (OSX) doesn't support this flag. @@ -202,7 +286,7 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) { } #endif - if (logging && logfile) { + if ((g_printAndLog & PRINTANDLOG_LOG) && logging && logfile) { if (filter_ansi) { // already done fprintf(logfile, "%s\n", buffer2); } else { @@ -219,10 +303,6 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) { pthread_mutex_unlock(&print_lock); } -void SetLogFilename(char *fn) { - logfilename = fn; -} - void SetFlushAfterWrite(bool value) { flushAfterWrite = value; } diff --git a/client/ui.h b/client/ui.h index 6e70b053d..7e00ab52b 100644 --- a/client/ui.h +++ b/client/ui.h @@ -11,18 +11,11 @@ #ifndef UI_H__ #define UI_H__ -#define _USE_MATH_DEFINES -#include -#include -#include -#include -#include -#include -#include +#include "common.h" #include -#include -#include -#include "util.h" +#include "ansi.h" + +#define _USE_MATH_DEFINES typedef struct { bool stdinOnTTY; @@ -46,7 +39,6 @@ void ShowGraphWindow(void); void RepaintGraphWindow(void); void PrintAndLogOptions(const char *str[][2], size_t size, size_t space); void PrintAndLogEx(logLevel_t level, const char *fmt, ...); -void SetLogFilename(char *fn); void SetFlushAfterWrite(bool value); void memcpy_filter_ansi(void *dest, const void *src, size_t n, bool filter); @@ -56,6 +48,8 @@ extern uint32_t CursorCPos, CursorDPos; extern bool GridLocked; extern bool showDemod; +int searchHomeFilePath(char **foundpath, const char *filename, bool create_home); + extern pthread_mutex_t print_lock; void iceIIR_Butterworth(int *data, const size_t len); diff --git a/client/util.c b/client/util.c index f6f89e0ff..1f5a29781 100644 --- a/client/util.c +++ b/client/util.c @@ -9,15 +9,27 @@ //----------------------------------------------------------------------------- // ensure gmtime_r is available even with -std=c99; must be included before -#if !defined(_WIN32) +#if !defined(_WIN32) && !defined(__APPLE__) #define _POSIX_C_SOURCE 200112L #endif #include "util.h" +#include +#include +#include +#include +#include +#include +#include // Mingw + +#include "ui.h" // PrintAndLog + #define UTIL_BUFFER_SIZE_SPRINT 4097 // global client debug variable uint8_t g_debugMode = 0; +// global client disable logging variable +uint8_t g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG; #ifdef _WIN32 #include @@ -807,24 +819,12 @@ int num_CPUs(void) { SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); return sysinfo.dwNumberOfProcessors; -#elif defined(__linux__) && defined(_SC_NPROCESSORS_ONLN) +#else #include int count = sysconf(_SC_NPROCESSORS_ONLN); if (count <= 0) count = 1; return count; -#elif defined(__APPLE__) - /* - TODO ICEMAN 2019, its commented out until someone finds a better solution -#include "sys/sysctl.h" - uint32_t logicalcores = 0; - size_t size = sizeof( logicalcores ); - sysctlbyname( "hw.logicalcpu", &logicalcores, &size, NULL, 0 ); - return logicalcores; - */ - return 1; -#else - return 1; #endif } diff --git a/client/util.h b/client/util.h index 3f677df7a..7cfea0f8b 100644 --- a/client/util.h +++ b/client/util.h @@ -10,16 +10,6 @@ #ifndef __UTIL_H_ #define __UTIL_H_ -#include //included in data.h -#include -#include -#include -#include -#include -#include -#include -#include "ui.h" // PrintAndLog -#include "commonutil.h" #include "common.h" #ifdef ANDROID @@ -31,21 +21,10 @@ # define FILE_PATH_SIZE 1000 #endif -#ifndef DropField -#define DropField() { \ - clearCommandBuffer(); SendCommandMIX(CMD_READER_ISO_14443a, 0, 0, 0, NULL, 0); \ - } -#endif - -#ifndef DropFieldEx -#define DropFieldEx(x) { \ - if ( (x) == ECC_CONTACTLESS) { \ - DropField(); \ - } \ - } -#endif - uint8_t g_debugMode; +uint8_t g_printAndLog; +#define PRINTANDLOG_PRINT 1 +#define PRINTANDLOG_LOG 2 int kbd_enter_pressed(void); void AddLogLine(const char *fn, const char *data, const char *c); diff --git a/client/whereami.c b/client/whereami.c index a18d2d2f7..9b154c628 100644 --- a/client/whereami.c +++ b/client/whereami.c @@ -213,6 +213,7 @@ int WAI_PREFIX(getExecutablePath)(char *out, int capacity, int *dirname_length) #if defined(__ANDROID__) || defined(ANDROID) #include #include +#include #endif WAI_NOINLINE diff --git a/common/bucketsort.h b/common/bucketsort.h index 0a56509c1..9e5123e1a 100644 --- a/common/bucketsort.h +++ b/common/bucketsort.h @@ -1,8 +1,7 @@ #ifndef BUCKETSORT_H__ #define BUCKETSORT_H__ -#include -#include +#include "common.h" typedef struct bucket { uint32_t *head; @@ -21,4 +20,5 @@ typedef struct bucket_info { void bucket_sort_intersect(uint32_t *const estart, uint32_t *const estop, uint32_t *const ostart, uint32_t *const ostop, bucket_info_t *bucket_info, bucket_array_t bucket); + #endif diff --git a/common/commonutil.h b/common/commonutil.h index 9504abd5b..a22486fff 100644 --- a/common/commonutil.h +++ b/common/commonutil.h @@ -11,8 +11,8 @@ #ifndef __COMMONUTIL_H #define __COMMONUTIL_H -#include -#include +#include "common.h" + // endian change for 16bit #ifdef __GNUC__ #ifndef BSWAP_16 @@ -53,11 +53,4 @@ void lsl(uint8_t *data, size_t len); int32_t le24toh(uint8_t data[3]); void htole24(uint32_t val, uint8_t data[3]); -# define _BLUE_(s) "\x1b[34m" s "\x1b[0m " -# define _RED_(s) "\x1b[31m" s "\x1b[0m " -# define _GREEN_(s) "\x1b[32m" s "\x1b[0m " -# define _YELLOW_(s) "\x1b[33m" s "\x1b[0m " -# define _MAGENTA_(s) "\x1b[35m" s "\x1b[0m " -# define _CYAN_(s) "\x1b[36m" s "\x1b[0m " - #endif diff --git a/common/crapto1/crapto1.c b/common/crapto1/crapto1.c index ba55227b5..66af2f41c 100644 --- a/common/crapto1/crapto1.c +++ b/common/crapto1/crapto1.c @@ -19,6 +19,8 @@ */ #include "crapto1.h" +#include "bucketsort.h" + #include #include "parity.h" diff --git a/common/crapto1/crapto1.h b/common/crapto1/crapto1.h index 49a784cf9..ab061e2e7 100644 --- a/common/crapto1/crapto1.h +++ b/common/crapto1/crapto1.h @@ -19,13 +19,10 @@ */ #ifndef CRAPTO1_INCLUDED #define CRAPTO1_INCLUDED -#include -#include -#include "bucketsort.h" -#ifdef __cplusplus -extern "C" { -#endif +#include +#include +#include struct Crypto1State {uint32_t odd, even;}; #if defined(__arm__) && !defined(__linux__) && !defined(_WIN32) && !defined(__APPLE__) // bare metal ARM Proxmark lacks malloc()/free() @@ -77,7 +74,4 @@ static inline int filter(uint32_t const x) { f |= 0x0d938 >> (x >> 16 & 0xf) & 1; return BIT(0xEC57E80A, f); } -#ifdef __cplusplus -} -#endif #endif diff --git a/common/crapto1/crypto1.c b/common/crapto1/crypto1.c index 7d6bb6e7d..9df30b356 100644 --- a/common/crapto1/crypto1.c +++ b/common/crapto1/crypto1.c @@ -17,9 +17,9 @@ Copyright (C) 2008-2008 bla */ -#include "crapto1.h" - #include + +#include "crapto1.h" #include "parity.h" #define SWAPENDIAN(x)\ diff --git a/common/crc.c b/common/crc.c index e197c0eee..0237fb36a 100644 --- a/common/crc.c +++ b/common/crc.c @@ -9,6 +9,8 @@ // #include "crc.h" +#include "commonutil.h" + void crc_init_ref(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor, bool refin, bool refout) { crc_init(crc, order, polynom, initial_value, final_xor); crc->refin = refin; diff --git a/common/crc.h b/common/crc.h index f0fa91194..6dcfe918f 100644 --- a/common/crc.h +++ b/common/crc.h @@ -9,8 +9,7 @@ #ifndef __CRC_H #define __CRC_H -#include "common.h" //stdint, stddef, stdbool -#include "commonutil.h" // reflect, bswap_16 +#include "common.h" typedef struct crc_ctx { uint32_t state; @@ -24,6 +23,18 @@ typedef struct crc_ctx { bool refout; /* Parameter: Reflect output CRC? */ } crc_t; +/* Static initialization of a crc structure */ +#define CRC_INITIALIZER(_order, _polynom, _initial_value, _final_xor) { \ + .state = ((_initial_value) & ((1L<<(_order))-1)), \ + .order = (_order), \ + .polynom = (_polynom), \ + .initial_value = (_initial_value), \ + .final_xor = (_final_xor), \ + .mask = ((1L<<(_order))-1) \ + .refin = false, \ + .refout = false \ +} + /* Initialize a crc structure. order is the order of the polynom, e.g. 32 for a CRC-32 * polynom is the CRC polynom. initial_value is the initial value of a clean state. * final_xor is XORed onto the state before returning it from crc_result(). @@ -62,16 +73,4 @@ uint32_t CRC4Legic(uint8_t *buff, size_t size); // Calculate CRC-8/Legic checksum uint32_t CRC8Legic(uint8_t *buff, size_t size); -/* Static initialization of a crc structure */ -#define CRC_INITIALIZER(_order, _polynom, _initial_value, _final_xor) { \ - .state = ((_initial_value) & ((1L<<(_order))-1)), \ - .order = (_order), \ - .polynom = (_polynom), \ - .initial_value = (_initial_value), \ - .final_xor = (_final_xor), \ - .mask = ((1L<<(_order))-1) \ - .refin = false, \ - .refout = false \ -} - #endif /* __CRC_H */ diff --git a/common/crc16.c b/common/crc16.c index 47d408660..729c15cf4 100644 --- a/common/crc16.c +++ b/common/crc16.c @@ -7,6 +7,9 @@ //----------------------------------------------------------------------------- #include "crc16.h" +#include +#include "commonutil.h" + static uint16_t crc_table[256]; static bool crc_table_init = false; static CrcType_t current_crc_type = CRC_NONE; @@ -31,6 +34,7 @@ void init_table(CrcType_t crctype) { generate_table(CRC16_POLY_CCITT, true); break; case CRC_FELICA: + case CRC_XMODEM: generate_table(CRC16_POLY_CCITT, false); break; case CRC_LEGIC: @@ -172,6 +176,7 @@ void compute_crc(CrcType_t ct, const uint8_t *d, size_t n, uint8_t *first, uint8 crc = crc16_iclass(d, n); break; case CRC_FELICA: + case CRC_XMODEM: crc = crc16_xmodem(d, n); break; case CRC_CCITT: @@ -204,6 +209,7 @@ uint16_t Crc16ex(CrcType_t ct, const uint8_t *d, size_t n) { case CRC_ICLASS: return crc16_iclass(d, n); case CRC_FELICA: + case CRC_XMODEM: return crc16_xmodem(d, n); case CRC_CCITT: return crc16_ccitt(d, n); @@ -244,6 +250,7 @@ bool check_crc(CrcType_t ct, const uint8_t *d, size_t n) { case CRC_ICLASS: return (crc16_iclass(d, n) == 0); case CRC_FELICA: + case CRC_XMODEM: return (crc16_xmodem(d, n) == 0); case CRC_CCITT: return (crc16_ccitt(d, n) == 0); diff --git a/common/crc16.h b/common/crc16.h index cc29d3ee0..6989af22e 100644 --- a/common/crc16.h +++ b/common/crc16.h @@ -8,11 +8,7 @@ #ifndef __CRC16_H #define __CRC16_H -#include -#include -#include -#include -#include "commonutil.h" +#include "common.h" #define CRC16_POLY_CCITT 0x1021 #define CRC16_POLY_LEGIC 0xc6c6 //0x6363 @@ -30,6 +26,7 @@ typedef enum { CRC_LEGIC, CRC_CCITT, CRC_KERMIT, + CRC_XMODEM, } CrcType_t; uint16_t update_crc16_ex(uint16_t crc, uint8_t c, uint16_t polynomial); diff --git a/common/crc32.h b/common/crc32.h index 308b3a077..a6bbee16a 100644 --- a/common/crc32.h +++ b/common/crc32.h @@ -9,18 +9,9 @@ #ifndef __CRC32_H #define __CRC32_H -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif +#include "common.h" void crc32_ex(const uint8_t *data, const size_t len, uint8_t *crc); void crc32_append(uint8_t *data, const size_t len); -#ifdef __cplusplus -} -#endif - #endif diff --git a/common/crc64.c b/common/crc64.c index 23360f6bd..3bdc596ac 100644 --- a/common/crc64.c +++ b/common/crc64.c @@ -1,5 +1,3 @@ -#include -#include #include "crc64.h" #define CRC64_ISO_PRESET 0xFFFFFFFFFFFFFFFF diff --git a/common/crc64.h b/common/crc64.h index 3782bdbae..af6417cb3 100644 --- a/common/crc64.h +++ b/common/crc64.h @@ -9,6 +9,8 @@ #ifndef __CRC64_H #define __CRC64_H +#include "common.h" + void crc64(const uint8_t *data, const size_t len, uint64_t *crc) ; #endif diff --git a/common/iso15693tools.c b/common/iso15693tools.c index 795d1be60..66a0f81da 100644 --- a/common/iso15693tools.c +++ b/common/iso15693tools.c @@ -7,6 +7,8 @@ //----------------------------------------------------------------------------- #include "iso15693tools.h" +#include + // returns a string representation of the UID // UID is transmitted and stored LSB first, displayed MSB first // target char* buffer, where to put the UID, if NULL a static buffer is returned diff --git a/common/iso15693tools.h b/common/iso15693tools.h index 26a7a87a7..42b2152cc 100644 --- a/common/iso15693tools.h +++ b/common/iso15693tools.h @@ -11,10 +11,7 @@ #ifndef ISO15693_H__ #define ISO15693_H__ -#include "proxmark3.h" -#include -#include -#include "crc16.h" +#include "common.h" // REQUEST FLAGS #define ISO15_REQ_SUBCARRIER_SINGLE 0x00 // Tag should respond using one subcarrier (ASK) @@ -70,8 +67,6 @@ #define ISO15_CMD_SYSINFO 0x2B #define ISO15_CMD_SECSTATUS 0x2C -char *Iso15693sprintUID(char *target, uint8_t *uid); - //----------------------------------------------------------------------------- // Map a sequence of octets (~layer 2 command) into the set of bits to feed // to the FPGA, to transmit that command to the tag. @@ -82,8 +77,8 @@ char *Iso15693sprintUID(char *target, uint8_t *uid); // SOF defined as // 1) Unmodulated time of 56.64us -// 2) 24 pulses of 423.75khz -// 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz) +// 2) 24 pulses of 423.75kHz +// 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75kHz) static const int Iso15693FrameSOF[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -109,8 +104,8 @@ static const int Iso15693Logic1[] = { }; // EOF defined as -// 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us) -// 2) 24 pulses of 423.75khz +// 1) logic '0' (8 pulses of 423.75kHz followed by unmodulated for 18.88us) +// 2) 24 pulses of 423.75kHz // 3) Unmodulated time of 56.64us static const int Iso15693FrameEOF[] = { 1, 1, 1, 1, @@ -123,4 +118,6 @@ static const int Iso15693FrameEOF[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; +char *Iso15693sprintUID(char *target, uint8_t *uid); + #endif diff --git a/include/legic_prng.h b/common/legic_prng.h similarity index 96% rename from include/legic_prng.h rename to common/legic_prng.h index c34455c4c..b72c6d8ed 100644 --- a/include/legic_prng.h +++ b/common/legic_prng.h @@ -9,10 +9,12 @@ #ifndef __LEGIC_PRNG_H #define __LEGIC_PRNG_H -#include +#include "common.h" + void legic_prng_init(uint8_t iv); void legic_prng_forward(int count); uint8_t legic_prng_get_bit(void); uint32_t legic_prng_get_bits(uint8_t len); + #endif diff --git a/common/lfdemod.c b/common/lfdemod.c index f8daec079..b0b30a1c8 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -36,12 +36,10 @@ // marshmellow //----------------------------------------------------------------------------- -#include // for memset, memcmp and size_t #include "lfdemod.h" -#include // for uint_32+ -#include // for bool +#include // for memset, memcmp and size_t #include "parity.h" // for parity test -#include "commonutil.h" // colors +#include "pm3_cmd.h" // error codes //********************************************************************************************** //---------------------------------Utilities Section-------------------------------------------- //********************************************************************************************** @@ -50,15 +48,12 @@ //to allow debug print calls when used not on dev -//void dummy(char *fmt, ...){} -void Dbprintf(const char *fmt, ...); - #ifndef ON_DEVICE #include "ui.h" -# include "cmdparser.h" # include "cmddata.h" # define prnt(args...) PrintAndLogEx(DEBUG, ## args ); #else +# include "dbprint.h" uint8_t g_debugMode = 0; # define prnt Dbprintf #endif @@ -223,13 +218,13 @@ size_t addParity(uint8_t *src, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, u } // array must be size dividable with 8 -uint8_t bits_to_array(const uint8_t *bits, size_t size, uint8_t *dest) { - if ((size == 0) || (size % 8) != 0) return 0; +int bits_to_array(const uint8_t *bits, size_t size, uint8_t *dest) { + if ((size == 0) || (size % 8) != 0) return PM3_EINVARG; for (uint32_t i = 0; i < (size / 8); i++) dest[i] = bytebits_to_byte((uint8_t *) bits + (i * 8), 8); - return 0; + return PM3_SUCCESS; } uint32_t bytebits_to_byte(uint8_t *src, size_t numbits) { diff --git a/common/lfdemod.h b/common/lfdemod.h index 4c9671ed4..50d769c6b 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -13,12 +13,8 @@ #ifndef LFDEMOD_H__ #define LFDEMOD_H__ -#include // for uint_32+ -#include // for bool -#include // for strcmp, memset, memcmp and size_t -#include // for -#include // for bool -#include "parity.h" // for parity test + +#include "common.h" //might not be high enough for noisy environments #define NOISE_AMPLITUDE_THRESHOLD 8 @@ -49,7 +45,7 @@ int askdemod(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType, int *startIdx); void askAmp(uint8_t *bits, size_t size); int BiphaseRawDecode(uint8_t *bits, size_t *size, int *offset, int invert); -uint8_t bits_to_array(const uint8_t *bits, size_t size, uint8_t *dest); +int bits_to_array(const uint8_t *bits, size_t size, uint8_t *dest); uint32_t bytebits_to_byte(uint8_t *src, size_t numbits); uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits); uint16_t countFC(uint8_t *bits, size_t size, bool fskAdj); @@ -83,4 +79,5 @@ int Em410xDecode(uint8_t *bits, size_t *size, size_t *start_idx, uint32_t *hi, u int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx); int detectIdteck(uint8_t *dest, size_t *size); int detectIOProx(uint8_t *dest, size_t *size, int *waveStartIdx); + #endif diff --git a/common/mbedtls/Makefile b/common/mbedtls/Makefile index a16b2cfd9..52663d67e 100644 --- a/common/mbedtls/Makefile +++ b/common/mbedtls/Makefile @@ -1,11 +1,8 @@ -# Hide full compilation line: -ifneq ($(V),1) - Q?=@ -endif -# To see full command lines, use make V=1 - -LIB_A = libmbedtls.a -mbedtls_SOURCES = \ +MYSRCPATHS = +MYINCLUDES = -I. -I.. +MYCFLAGS = -std=c99 -D_ISOC99_SOURCE +MYDEFS = +MYSRCS = \ aes.c \ asn1parse.c \ asn1write.c \ @@ -49,55 +46,7 @@ mbedtls_SOURCES = \ x509.c \ x509_crl.c \ x509_crt.c -mbedtls_LDFLAGS = \ - -no-undefined \ - -export-symbols-regex '^mbedtls_' \ - -version-info 15:0:11 +LIB_A = libmbedtls.a -CFILES = $(filter %.c, $(mbedtls_SOURCES)) -CMDOBJS = $(CFILES:%.c=%.o) -CLEAN = $(CMDOBJS) - -platform = $(shell uname) - -CC= gcc -CFLAGS= -O2 -Wall -Wno-unused-variable -Wno-unused-function -LDFLAGS= $(SYSLDFLAGS) $(mbedtls_LDFLAGS) -LIBS= $(SYSLIBS) $(MYLIBS) -DEFAULT_INCLUDES = -I. -I.. -DEFS = -DHAVE_STDINT_H - -ifeq ($(platform),Darwin) -AR= /usr/bin/ar rcs -RANLIB= /usr/bin/ranlib -else -AR= ar rcs -RANLIB= ranlib -endif -RM= rm -f -TST= echo - -SYSLDFLAGS= -SYSLIBS= - -MYLIBS= -MYOBJS= - -$(LIB_A): $(CMDOBJS) - $(info [=] AR $@) - $(Q)$(AR) $(LIB_A) $(CMDOBJS) - $(Q)$(RANLIB) $(LIB_A) - -all: $(LIB_A) - -clean: - $(Q)$(RM) $(CLEAN) - $(Q)$(RM) $(LIB_A) - -%.o: %.c - $(info [-] CC $<) - $(Q)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(CFLAGS) -c -o $@ $< $(LIBS) - -.PHONY: all clean - +include ../../Makefile.host diff --git a/common/mbedtls/check_config.h b/common/mbedtls/check_config.h index a4fa7bdde..b395844d5 100644 --- a/common/mbedtls/check_config.h +++ b/common/mbedtls/check_config.h @@ -115,6 +115,7 @@ #endif #if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ + !defined(MBEDTLS_ECP_DP_SECP128R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ diff --git a/common/mbedtls/config.h b/common/mbedtls/config.h index 9f4b19c5e..707c493d7 100644 --- a/common/mbedtls/config.h +++ b/common/mbedtls/config.h @@ -645,6 +645,7 @@ * * Comment macros to disable the curve and functions for it */ +#define MBEDTLS_ECP_DP_SECP128R1_ENABLED #define MBEDTLS_ECP_DP_SECP192R1_ENABLED #define MBEDTLS_ECP_DP_SECP224R1_ENABLED #define MBEDTLS_ECP_DP_SECP256R1_ENABLED diff --git a/common/mbedtls/ecdsa.c b/common/mbedtls/ecdsa.c index 2fac6d875..1d087f386 100644 --- a/common/mbedtls/ecdsa.c +++ b/common/mbedtls/ecdsa.c @@ -286,8 +286,8 @@ cleanup: /* * Convert a signature (given by context) to ASN.1 */ -static int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s, - unsigned char *sig, size_t *slen) { +int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s, + unsigned char *sig, size_t *slen) { int ret; unsigned char buf[MBEDTLS_ECDSA_MAX_LEN]; unsigned char *p = buf + sizeof(buf); diff --git a/common/mbedtls/ecdsa.h b/common/mbedtls/ecdsa.h index 0371e8c36..5293c2376 100644 --- a/common/mbedtls/ecdsa.h +++ b/common/mbedtls/ecdsa.h @@ -334,6 +334,8 @@ void mbedtls_ecdsa_init(mbedtls_ecdsa_context *ctx); */ void mbedtls_ecdsa_free(mbedtls_ecdsa_context *ctx); +int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s, unsigned char *sig, size_t *slen); + #ifdef __cplusplus } #endif diff --git a/common/mbedtls/ecp.c b/common/mbedtls/ecp.c index 896801dd7..3a2b48804 100644 --- a/common/mbedtls/ecp.c +++ b/common/mbedtls/ecp.c @@ -84,7 +84,8 @@ static unsigned long add_count, dbl_count, mul_count; #endif -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ +#if defined(MBEDTLS_ECP_DP_SECP128R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ @@ -157,6 +158,9 @@ static const mbedtls_ecp_curve_info ecp_supported_curves[] = { #endif #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP128R1_ENABLED) + { MBEDTLS_ECP_DP_SECP128R1, 0xFE00, 128, "secp128r1" }, #endif { MBEDTLS_ECP_DP_NONE, 0, 0, NULL }, }; diff --git a/common/mbedtls/ecp.h b/common/mbedtls/ecp.h index f7ca89493..4c2592a9e 100644 --- a/common/mbedtls/ecp.h +++ b/common/mbedtls/ecp.h @@ -81,6 +81,7 @@ typedef enum { MBEDTLS_ECP_DP_SECP224K1, /*!< Domain parameters for 224-bit "Koblitz" curve. */ MBEDTLS_ECP_DP_SECP256K1, /*!< Domain parameters for 256-bit "Koblitz" curve. */ MBEDTLS_ECP_DP_CURVE448, /*!< Domain parameters for Curve448. */ + MBEDTLS_ECP_DP_SECP128R1, /*!< Domain parameters for the 128-bit curve used for NXP originality check. */ } mbedtls_ecp_group_id; /** diff --git a/common/mbedtls/ecp_curves.c b/common/mbedtls/ecp_curves.c index 2fd9a2daf..8242c9076 100644 --- a/common/mbedtls/ecp_curves.c +++ b/common/mbedtls/ecp_curves.c @@ -84,6 +84,42 @@ * to be directly usable in MPIs */ +/* + * Domain parameters for secp128r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP128R1_ENABLED) +static const mbedtls_mpi_uint secp128r1_p[] = { + // 2^128 - 2^97 - 1 // TODO + BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF), +}; +static const mbedtls_mpi_uint secp128r1_a[] = { + // FFFFFFFDFFFFFFFF FFFFFFFFFFFFFFFC + BYTES_TO_T_UINT_8(0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF), +}; +static const mbedtls_mpi_uint secp128r1_b[] = { + // E87579C11079F43D D824993C2CEE5ED3 + BYTES_TO_T_UINT_8(0xD3, 0x5E, 0xEE, 0x2C, 0x3C, 0x99, 0x24, 0xD8), + BYTES_TO_T_UINT_8(0x3D, 0xF4, 0x79, 0x10, 0xC1, 0x79, 0x75, 0xE8), +}; +static const mbedtls_mpi_uint secp128r1_gx[] = { + // 161FF7528B899B2D 0C28607CA52C5B86 + BYTES_TO_T_UINT_8(0x86, 0x5B, 0x2C, 0xA5, 0x7C, 0x60, 0x28, 0x0C), + BYTES_TO_T_UINT_8(0x2D, 0x9B, 0x89, 0x8B, 0x52, 0xF7, 0x1F, 0x16), +}; +static const mbedtls_mpi_uint secp128r1_gy[] = { + // CF5AC8395BAFEB13 C02DA292DDED7A83 + BYTES_TO_T_UINT_8(0x83, 0x7A, 0xED, 0xDD, 0x92, 0xA2, 0x2D, 0xC0), + BYTES_TO_T_UINT_8(0x13, 0xEB, 0xAF, 0x5B, 0x39, 0xC8, 0x5A, 0xCF), +}; +static const mbedtls_mpi_uint secp128r1_n[] = { + // FFFFFFFE00000000 75A30D1B9038A115 + BYTES_TO_T_UINT_8(0x15, 0xA1, 0x38, 0x90, 0x1B, 0x0D, 0xA3, 0x75), + BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF), +}; +#endif /* MBEDTLS_ECP_DP_SECP128R1_ENABLED */ + /* * Domain parameters for secp192r1 */ @@ -747,6 +783,11 @@ int mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id) { grp->id = id; switch (id) { +#if defined(MBEDTLS_ECP_DP_SECP128R1_ENABLED) + case MBEDTLS_ECP_DP_SECP128R1: + grp->modp = NULL; + return (LOAD_GROUP_A(secp128r1)); +#endif /* MBEDTLS_ECP_DP_SECP128R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) case MBEDTLS_ECP_DP_SECP192R1: NIST_MODP(p192); diff --git a/common/parity.c b/common/parity.c index 2a1d6281c..1db224f37 100644 --- a/common/parity.c +++ b/common/parity.c @@ -6,7 +6,6 @@ // parity functions (all defined in parity.h) //----------------------------------------------------------------------------- #include -#include const uint8_t OddByteParity[256] = { 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, diff --git a/common/parity.h b/common/parity.h index e42616917..a768f51fb 100644 --- a/common/parity.h +++ b/common/parity.h @@ -11,12 +11,7 @@ #ifndef __PARITY_H #define __PARITY_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include +#include "common.h" extern const uint8_t OddByteParity[256]; @@ -52,8 +47,4 @@ static inline bool oddparity32(uint32_t x) { #endif } -#ifdef __cplusplus -} -#endif - #endif /* __PARITY_H */ diff --git a/common/protocols.c b/common/protocols.c deleted file mode 100644 index 809c31704..000000000 --- a/common/protocols.c +++ /dev/null @@ -1,150 +0,0 @@ -#include "protocols.h" - -// ATA55xx shared presets & routines -uint32_t GetT55xxClockBit(uint32_t clock) { - switch (clock) { - case 128: - return T55x7_BITRATE_RF_128; - case 100: - return T55x7_BITRATE_RF_100; - case 64: - return T55x7_BITRATE_RF_64; - case 50: - return T55x7_BITRATE_RF_50; - case 40: - return T55x7_BITRATE_RF_40; - case 32: - return T55x7_BITRATE_RF_32; - case 16: - return T55x7_BITRATE_RF_16; - case 8: - return T55x7_BITRATE_RF_8; - default : - return 0; - } -} - -#ifndef ON_DEVICE -#include "ui.h" -#define PrintAndLogDevice(level, format, args...) PrintAndLogEx(level, format , ## args) - -static uint8_t isset(uint8_t val, uint8_t mask) { - return (val & mask); -} - -static uint8_t notset(uint8_t val, uint8_t mask) { - return !(val & mask); -} - -static void fuse_config(const picopass_hdr *hdr) { - uint8_t fuses = hdr->conf.fuses; - - if (isset(fuses, FUSE_FPERS)) - PrintAndLogDevice(SUCCESS, "\tMode: Personalization [Programmable]"); - else - PrintAndLogDevice(NORMAL, "\tMode: Application [Locked]"); - - if (isset(fuses, FUSE_CODING1)) { - PrintAndLogDevice(NORMAL, "\tCoding: RFU"); - } else { - if (isset(fuses, FUSE_CODING0)) - PrintAndLogDevice(NORMAL, "\tCoding: ISO 14443-2 B/ISO 15693"); - else - PrintAndLogDevice(NORMAL, "\tCoding: ISO 14443B only"); - } - // 1 1 - if (isset(fuses, FUSE_CRYPT1) && isset(fuses, FUSE_CRYPT0)) PrintAndLogDevice(SUCCESS, "\tCrypt: Secured page, keys not locked"); - // 1 0 - if (isset(fuses, FUSE_CRYPT1) && notset(fuses, FUSE_CRYPT0)) PrintAndLogDevice(NORMAL, "\tCrypt: Secured page, keys locked"); - // 0 1 - if (notset(fuses, FUSE_CRYPT1) && isset(fuses, FUSE_CRYPT0)) PrintAndLogDevice(SUCCESS, "\tCrypt: Non secured page"); - // 0 0 - if (notset(fuses, FUSE_CRYPT1) && notset(fuses, FUSE_CRYPT0)) PrintAndLogDevice(NORMAL, "\tCrypt: No auth possible. Read only if RA is enabled"); - - if (isset(fuses, FUSE_RA)) - PrintAndLogDevice(NORMAL, "\tRA: Read access enabled"); - else - PrintAndLogDevice(WARNING, "\tRA: Read access not enabled"); -} - -void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb) { - // mem-bit 5, mem-bit 7, chip-bit 4: defines chip type - uint8_t k16 = isset(mem_cfg, 0x80); - //uint8_t k2 = isset(mem_cfg, 0x08); - uint8_t book = isset(mem_cfg, 0x20); - - if (isset(chip_cfg, 0x10) && !k16 && !book) { - *kb = 2; - *app_areas = 2; - *max_blk = 31; - } else if (isset(chip_cfg, 0x10) && k16 && !book) { - *kb = 16; - *app_areas = 2; - *max_blk = 255; //16kb - } else if (notset(chip_cfg, 0x10) && !k16 && !book) { - *kb = 16; - *app_areas = 16; - *max_blk = 255; //16kb - } else if (isset(chip_cfg, 0x10) && k16 && book) { - *kb = 32; - *app_areas = 3; - *max_blk = 255; //16kb - } else if (notset(chip_cfg, 0x10) && !k16 && book) { - *kb = 32; - *app_areas = 17; - *max_blk = 255; //16kb - } else { - *kb = 32; - *app_areas = 2; - *max_blk = 255; - } -} - -static void mem_app_config(const picopass_hdr *hdr) { - uint8_t mem = hdr->conf.mem_config; - uint8_t chip = hdr->conf.chip_config; - uint8_t applimit = hdr->conf.app_limit; - uint8_t kb = 2; - uint8_t app_areas = 2; - uint8_t max_blk = 31; - - getMemConfig(mem, chip, &max_blk, &app_areas, &kb); - - if (applimit < 6) applimit = 26; - if (kb == 2 && (applimit > 0x1f)) applimit = 26; - - PrintAndLogDevice(NORMAL, " Mem: %u KBits/%u App Areas (%u * 8 bytes) [%02X]", kb, app_areas, max_blk, mem); - PrintAndLogDevice(NORMAL, "\tAA1: blocks 06-%02X", applimit); - PrintAndLogDevice(NORMAL, "\tAA2: blocks %02X-%02X", applimit + 1, max_blk); - PrintAndLogDevice(NORMAL, "\tOTP: 0x%02X%02X", hdr->conf.otp[1], hdr->conf.otp[0]); - PrintAndLogDevice(NORMAL, "\nKeyAccess:"); - - uint8_t book = isset(mem, 0x20); - if (book) { - PrintAndLogDevice(NORMAL, "\tRead A - Kd"); - PrintAndLogDevice(NORMAL, "\tRead B - Kc"); - PrintAndLogDevice(NORMAL, "\tWrite A - Kd"); - PrintAndLogDevice(NORMAL, "\tWrite B - Kc"); - PrintAndLogDevice(NORMAL, "\tDebit - Kd or Kc"); - PrintAndLogDevice(NORMAL, "\tCredit - Kc"); - } else { - PrintAndLogDevice(NORMAL, "\tRead A - Kd or Kc"); - PrintAndLogDevice(NORMAL, "\tRead B - Kd or Kc"); - PrintAndLogDevice(NORMAL, "\tWrite A - Kc"); - PrintAndLogDevice(NORMAL, "\tWrite B - Kc"); - PrintAndLogDevice(NORMAL, "\tDebit - Kd or Kc"); - PrintAndLogDevice(NORMAL, "\tCredit - Kc"); - } -} -static void print_picopass_info(const picopass_hdr *hdr) { - fuse_config(hdr); - mem_app_config(hdr); -} -void printIclassDumpInfo(uint8_t *iclass_dump) { - print_picopass_info((picopass_hdr *) iclass_dump); -} - -#else -#define PrintAndLogDevice(level, format, ...) { } -#endif -//ON_DEVICE diff --git a/client/util_posix.c b/common/util_posix.c similarity index 95% rename from client/util_posix.c rename to common/util_posix.c index ca54d2ae4..050040a32 100644 --- a/client/util_posix.c +++ b/common/util_posix.c @@ -8,8 +8,10 @@ // utilities requiring Posix library functions //----------------------------------------------------------------------------- +// ensure availability even with -std=c99; must be included before #if !defined(_WIN32) -#define _POSIX_C_SOURCE 199309L // need nanosleep() +//#define _POSIX_C_SOURCE 199309L // need nanosleep() +#define _POSIX_C_SOURCE 200112L // need localtime_r() #else #include #endif diff --git a/client/util_posix.h b/common/util_posix.h similarity index 83% rename from client/util_posix.h rename to common/util_posix.h index a0a8c8638..546b4ea35 100644 --- a/client/util_posix.h +++ b/common/util_posix.h @@ -11,16 +11,16 @@ #ifndef UTIL_POSIX_H__ #define UTIL_POSIX_H__ -#include +#include "common.h" #ifdef _WIN32 # include # define sleep(n) Sleep(1000 *(n)) # define msleep(n) Sleep((n)) #else -extern void msleep(uint32_t n); // sleep n milliseconds +void msleep(uint32_t n); // sleep n milliseconds #endif // _WIN32 -extern uint64_t msclock(void); // a milliseconds clock +uint64_t msclock(void); // a milliseconds clock #endif diff --git a/zlib/ChangeLog b/common/zlib/ChangeLog similarity index 100% rename from zlib/ChangeLog rename to common/zlib/ChangeLog diff --git a/zlib/FAQ b/common/zlib/FAQ similarity index 100% rename from zlib/FAQ rename to common/zlib/FAQ diff --git a/common/zlib/Makefile b/common/zlib/Makefile new file mode 100644 index 000000000..b62071d5d --- /dev/null +++ b/common/zlib/Makefile @@ -0,0 +1,10 @@ +MYSRCPATHS = ../../common/zlib +MYSRCS = deflate.c adler32.c trees.c zutil.c inflate.c inffast.c inftrees.c +MYINCLUDES = -I../../common/zlib +MYCFLAGS = -std=c99 -D_ISOC99_SOURCE +MYDEFS = -DZ_SOLO -DNO_GZIP -DZLIB_PM3_TUNED +#-DDEBUG -Dverbose=1 + +LIB_A = libz.a + +include ../../Makefile.host diff --git a/zlib/README b/common/zlib/README similarity index 100% rename from zlib/README rename to common/zlib/README diff --git a/zlib/adler32.c b/common/zlib/adler32.c similarity index 100% rename from zlib/adler32.c rename to common/zlib/adler32.c diff --git a/zlib/deflate.c b/common/zlib/deflate.c similarity index 100% rename from zlib/deflate.c rename to common/zlib/deflate.c diff --git a/zlib/deflate.h b/common/zlib/deflate.h similarity index 100% rename from zlib/deflate.h rename to common/zlib/deflate.h diff --git a/zlib/inffast.c b/common/zlib/inffast.c similarity index 100% rename from zlib/inffast.c rename to common/zlib/inffast.c diff --git a/zlib/inffast.h b/common/zlib/inffast.h similarity index 100% rename from zlib/inffast.h rename to common/zlib/inffast.h diff --git a/zlib/inffixed.h b/common/zlib/inffixed.h similarity index 100% rename from zlib/inffixed.h rename to common/zlib/inffixed.h diff --git a/zlib/inflate.c b/common/zlib/inflate.c similarity index 100% rename from zlib/inflate.c rename to common/zlib/inflate.c diff --git a/zlib/inflate.h b/common/zlib/inflate.h similarity index 100% rename from zlib/inflate.h rename to common/zlib/inflate.h diff --git a/zlib/inftrees.c b/common/zlib/inftrees.c similarity index 100% rename from zlib/inftrees.c rename to common/zlib/inftrees.c diff --git a/zlib/inftrees.h b/common/zlib/inftrees.h similarity index 100% rename from zlib/inftrees.h rename to common/zlib/inftrees.h diff --git a/zlib/trees.c b/common/zlib/trees.c similarity index 100% rename from zlib/trees.c rename to common/zlib/trees.c diff --git a/zlib/trees.h b/common/zlib/trees.h similarity index 100% rename from zlib/trees.h rename to common/zlib/trees.h diff --git a/zlib/zconf.h b/common/zlib/zconf.h similarity index 100% rename from zlib/zconf.h rename to common/zlib/zconf.h diff --git a/zlib/zlib.h b/common/zlib/zlib.h similarity index 100% rename from zlib/zlib.h rename to common/zlib/zlib.h diff --git a/zlib/zutil.c b/common/zlib/zutil.c similarity index 100% rename from zlib/zutil.c rename to common/zlib/zutil.c diff --git a/zlib/zutil.h b/common/zlib/zutil.h similarity index 100% rename from zlib/zutil.h rename to common/zlib/zutil.h diff --git a/common/Makefile.common b/common_arm/Makefile.common similarity index 60% rename from common/Makefile.common rename to common_arm/Makefile.common index 282f242d9..52ec2ebd2 100644 --- a/common/Makefile.common +++ b/common_arm/Makefile.common @@ -6,71 +6,48 @@ # Common makefile functions for all platforms #----------------------------------------------------------------------------- -# This new makefile replaces the previous Makefile/Makefile.linux -# with as much common code for both environments as possible. -# Following is a short OS detection to set up variables, all the -# remaining Makefile should be portable and only depend on these -# variables -# - -ifneq ($(V),1) - Q?=@ -endif -# To see full command lines, use make V=1 - # Make sure that all is the default target # (The including Makefile still needs to define what 'all' is) -platform = $(shell uname) - all: -CROSS ?= arm-none-eabi- +# This Makefile might have been called from various subdirs, trying to find our Makefile.defs +ifeq ($(DEFSBEENHERE),) + -include Makefile.defs +endif +ifeq ($(DEFSBEENHERE),) + -include ../Makefile.defs +endif +ifeq ($(DEFSBEENHERE),) + -include ../../Makefile.defs +endif +ifeq ($(DEFSBEENHERE),) + $(error Can't find Makefile.defs) +endif + CC = $(CROSS)gcc AS = $(CROSS)as LD = $(CROSS)ld OBJCOPY = $(CROSS)objcopy -GZIP=gzip OBJDIR = obj -INCLUDE = -I../include -I../common -I. - -TAR=tar -TARFLAGS = -C .. -rvf - -# Windows' echo echos its input verbatim, on Posix there is some -# amount of shell command line parsing going on. echo "" on -# Windows yields literal "", on Linux yields an empty line -ifeq ($(shell echo ""),) -DELETE=rm -rf -MOVE=mv -COPY=cp -PATHSEP=/ -FLASH_TOOL=client/flasher -# This is probably a proper system, so we can use uname -DETECTED_OS=$(platform) -else - -# Assume that we are running on Windows. -DELETE=del /q -MOVE=ren -COPY=copy -PATHSEP=\\# -FLASH_TOOL=client\\flasher.exe -DETECTED_OS=Windows - -endif +INCLUDE = -I../include -I../common_arm -I../common_fpga -I../common -I. # Also search prerequisites in the common directory (for usb.c), the fpga directory (for fpga.bit), and the zlib directory -VPATH = . ../common ../common/crapto1 ../common/mbedtls ../fpga ../zlib ../armsrc/Standalone ../uart +VPATH = . ../common_arm ../common ../common/crapto1 ../common/mbedtls ../common/zlib ../fpga ../armsrc/Standalone -INCLUDES = ../include/proxmark3.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/pm3_cmd.h $(APP_INCLUDES) +INCLUDES = ../include/proxmark3_arm.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/pm3_cmd.h CFLAGS = -c $(INCLUDE) -Wall -Werror -pedantic -Wunused -std=c99 $(APP_CFLAGS) -Os LDFLAGS = -nostartfiles -nodefaultlibs -Wl,-gc-sections -n LIBS = -lgcc +# Flags to generate temporary dependency files +DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td +# make temporary to final dependency files after successful compilation +POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d + THUMBOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(THUMBSRC))) ARMOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(ARMSRC))) ASMOBJ = $(patsubst %.s,$(OBJDIR)/%.o,$(notdir $(ASMSRC))) @@ -78,11 +55,13 @@ VERSIONOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(VERSIONSRC))) $(THUMBOBJ): $(OBJDIR)/%.o: %.c $(INCLUDES) $(info [-] CC $<) - $(Q)$(CC) $(CFLAGS) -mthumb -mthumb-interwork -o $@ $< + $(Q)$(CC) $(CFLAGS) $(DEPFLAGS) -mthumb -mthumb-interwork -o $@ $< + $(Q)$(POSTCOMPILE) $(ARMOBJ): $(OBJDIR)/%.o: %.c $(INCLUDES) $(info [-] CC $<) - $(Q)$(CC) $(CFLAGS) -mthumb-interwork -o $@ $< + $(Q)$(CC) $(CFLAGS) $(DEPFLAGS) -mthumb-interwork -o $@ $< + $(Q)$(POSTCOMPILE) $(ASMOBJ): $(OBJDIR)/%.o: %.s $(info [-] CC $<) @@ -111,11 +90,7 @@ DEPENDENCY_FILES = $(patsubst %.c,$(OBJDIR)/%.d,$(notdir $(THUMBSRC))) \ $(patsubst %.c,$(OBJDIR)/%.d,$(notdir $(ARMSRC))) \ $(patsubst %.s,$(OBJDIR)/%.d,$(notdir $(ASMSRC))) -$(DEPENDENCY_FILES): Makefile ../common/Makefile.common - -$(patsubst %.o,%.d,$(THUMBOBJ) $(ARMOBJ)): $(OBJDIR)/%.d: %.c - @$(CC) -MM -MT "$(@) $(@:.d=.o)" $(CFLAGS) $< > $@ -$(patsubst %.o,%.d,$(ASMOBJ)):$(OBJDIR)/%.d: %.s - @$(CC) -MM -MT "$(@) $(@:.d=.o)" $(CFLAGS) $< > $@ +$(DEPENDENCY_FILES): Makefile ../common_arm/Makefile.common +.PRECIOUS: $(DEPENDENCY_FILES) -include $(DEPENDENCY_FILES) diff --git a/common/Makefile.hal b/common_arm/Makefile.hal similarity index 67% rename from common/Makefile.hal rename to common_arm/Makefile.hal index 46154d244..22ae385c3 100644 --- a/common/Makefile.hal +++ b/common_arm/Makefile.hal @@ -2,6 +2,8 @@ PLATFORM?=PM3RDV4 # Standalone Mode info (path depends if make is called at top or from armsrc) +# Guard Makefile.hal against implicit rules: (with % to avoid being first goal) +%/Makefile.hal: ; -include armsrc/Standalone/Makefile.hal -include Standalone/Makefile.hal ifndef DEFAULT_STANDALONE @@ -12,37 +14,29 @@ define KNOWN_PLATFORM_DEFINITIONS Known definitions: -+==========================================================+ -| PLATFORM | DESCRIPTION | -+==========================================================+ -| PM3RDV4 (def) | Proxmark3 rdv4 with AT91SAM7S512 | -+----------------------------------------------------------+ -| PM3EVO | Proxmark3 EVO with AT91SAM7S512 | -+----------------------------------------------------------+ -| PM3EASY | Proxmark3 rdv3 Easy with AT91SAM7S256 | -+----------------------------------------------------------+ -| PM3RDV2 | Proxmark3 rdv2 with AT91SAM7S512 | -+----------------------------------------------------------+ -| PM3OLD256 | Proxmark3 V1 with AT91SAM7S256 | -+----------------------------------------------------------+ -| PM3OLD512 | Proxmark3 V1 with AT91SAM7S512 | -+----------------------------------------------------------+ ++============================================+ +| PLATFORM | DESCRIPTION | ++============================================+ +| PM3RDV4 (def) | Proxmark3 rdv4 | ++--------------------------------------------+ +| PM3OTHER | Proxmark3 Generic target | ++--------------------------------------------+ -+==========================================================+ -| PLATFORM_EXTRAS | DESCRIPTION | -+==========================================================+ -| BTADDON | Proxmark3 rdv4 BT add-on | -+----------------------------------------------------------+ ++============================================+ +| PLATFORM_EXTRAS | DESCRIPTION | ++============================================+ +| BTADDON | Proxmark3 rdv4 BT add-on | ++--------------------------------------------+ endef define HELP_DEFINITIONS Options to define platform, platform extras and/or standalone mode: -(1) Run make with PLATFORM, PLATFORM_EXTRAS and/or STANDALONE as follows: -make PLATFORM=PM3EASY STANDALONE=$(HELP_EXAMPLE_STANDALONE) +(1) Run make with your PLATFORM, PLATFORM_EXTRAS and/or STANDALONE choices as follows: +make PLATFORM=PM3OTHER STANDALONE=$(HELP_EXAMPLE_STANDALONE) -(2) Save a file called Makefile.platform with contents: -PLATFORM=PM3EASY +(2) Save a file called Makefile.platform with contents, e.g.: +PLATFORM=PM3OTHER or if you have a Proxmark 3 RDV4 with the BT add-on: PLATFORM=PM3RDV4 @@ -62,24 +56,10 @@ endef PLTNAME = Unknown Platform ifeq ($(PLATFORM),PM3RDV4) - MCU = AT91SAM7S512 PLATFORM_DEFS = -DWITH_SMARTCARD -DWITH_FLASH PLTNAME = Proxmark3 rdv4 -else ifeq ($(PLATFORM),PM3EVO) - MCU = AT91SAM7S512 - PLTNAME = Proxmark3 EVO -else ifeq ($(PLATFORM),PM3EASY) - MCU = AT91SAM7S256 - PLTNAME = Proxmark3 rdv3 Easy -else ifeq ($(PLATFORM),PM3RDV2) - MCU = AT91SAM7S512 - PLTNAME = Proxmark3 rdv2 -else ifeq ($(PLATFORM),PM3OLD256) - MCU = AT91SAM7S256 - PLTNAME = Proxmark3 V1 with AT91SAM7S256 -else ifeq ($(PLATFORM),PM3OLD512) - MCU = AT91SAM7S512 - PLTNAME = Proxmark3 V1 with AT91SAM7S512 +else ifeq ($(PLATFORM),PM3OTHER) + PLTNAME = Proxmark3 Generic target else $(error Invalid or empty PLATFORM: $(PLATFORM). $(KNOWN_DEFINITIONS)) endif @@ -111,8 +91,10 @@ PLATFORM_DEFS += \ -DWITH_ISO14443a \ -DWITH_ICLASS \ -DWITH_FELICA \ + -DWITH_NFCBARCODE \ -DWITH_HFSNIFF + # Standalone mode ifneq ($(strip $(filter $(PLATFORM_DEFS),$(STANDALONE_REQ_DEFS))),$(strip $(STANDALONE_REQ_DEFS))) $(error Chosen Standalone mode $(STANDALONE) requires $(strip $(STANDALONE_REQ_DEFS)), unsupported by $(PLTNAME)) @@ -164,7 +146,6 @@ export PLATFORM export PLATFORM_EXTRAS export PLATFORM_EXTRAS_INFO export PLTNAME -export MCU export PLATFORM_DEFS export PLATFORM_DEFS_INFO export PLATFORM_DEFS_INFO_STANDALONE diff --git a/common/default_version.c b/common_arm/default_version.c similarity index 82% rename from common/default_version.c rename to common_arm/default_version.c index b586e4ad1..b4b8ae17d 100644 --- a/common/default_version.c +++ b/common_arm/default_version.c @@ -1,5 +1,5 @@ -#include "proxmark3.h" -/* This is the default version.c file that Makefile.common falls back to if perl is not available */ +#include "proxmark3_arm.h" +/* This is the default version.c file that Makefile.common falls back to if neither sh nor perl are available */ const struct version_information __attribute__((section(".version_information"))) version_information = { VERSION_INFORMATION_MAGIC, 1, /* version 1 */ diff --git a/common/ldscript.common b/common_arm/ldscript.common similarity index 100% rename from common/ldscript.common rename to common_arm/ldscript.common diff --git a/common/usb_cdc.c b/common_arm/usb_cdc.c similarity index 98% rename from common/usb_cdc.c rename to common_arm/usb_cdc.c index 25a5d80d9..dd8d2f7c4 100644 --- a/common/usb_cdc.c +++ b/common_arm/usb_cdc.c @@ -33,6 +33,9 @@ */ #include "usb_cdc.h" +#include "proxmark3_arm.h" +#include "usart_defs.h" + /* AT91SAM7S256 USB Device Port • Embedded 328-byte dual-port RAM for endpoints @@ -446,17 +449,18 @@ AT91S_CDC_LINE_CODING line = { // purely informative, actual values don't matter 8 // 8 Data bits }; -static void SpinDelay(int ms) { - int us = ms * 1000; - int ticks = (48 * us) >> 10; +// timer counts in 21.3us increments (1024/48MHz), rounding applies +// WARNING: timer can't measure more than 1.39s (21.3us * 0xffff) +static void SpinDelayUs(int us) { + int ticks = ((MCK / 1000000) * us + 512) >> 10; // Borrow a PWM unit for my real-time clock AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0); // 48 MHz / 1024 gives 46.875 kHz - AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); - AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; - AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; + AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); // Channel Mode Register + AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; // Channel Duty Cycle Register + AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; // Channel Period Register uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; @@ -510,7 +514,7 @@ void usb_enable() { // Disconnect and reconnect USB controller for 100ms usb_disable(); - SpinDelay(100); + SpinDelayUs(100 * 1000); // Wait for a short while //for (volatile size_t i=0; i<0x100000; i++) {}; diff --git a/common/usb_cdc.h b/common_arm/usb_cdc.h similarity index 95% rename from common/usb_cdc.h rename to common_arm/usb_cdc.h index 64dfbcd4d..b5ec2e8d7 100644 --- a/common/usb_cdc.h +++ b/common_arm/usb_cdc.h @@ -35,12 +35,8 @@ #ifndef _USB_CDC_H_ #define _USB_CDC_H_ -#include -#include "at91sam7s512.h" -#include "usart.h" -#include "config_gpio.h" -#include "proxmark3.h" // USB_CONNECT() #include "common.h" +#include "at91sam7s512.h" void usb_disable(void); void usb_enable(void); @@ -62,4 +58,3 @@ void AT91F_USB_SendStall(AT91PS_UDP pUdp); void AT91F_CDC_Enumerate(void); #endif // _USB_CDC_H_ - diff --git a/common/fpga.h b/common_fpga/fpga.h similarity index 95% rename from common/fpga.h rename to common_fpga/fpga.h index eb26d0ccb..5ab015f57 100644 --- a/common/fpga.h +++ b/common_fpga/fpga.h @@ -7,6 +7,9 @@ #ifndef __FPGA_H #define __FPGA_H +#include +#include + #define FPGA_BITSTREAM_FIXED_HEADER_SIZE sizeof(bitparse_fixed_header) #define FPGA_INTERLEAVE_SIZE 288 #define FPGA_CONFIG_SIZE 42336L // our current fpga_[lh]f.bit files are 42175 bytes. Rounded up to next multiple of FPGA_INTERLEAVE_SIZE diff --git a/doc/bt_manual_v10.md b/doc/bt_manual_v10.md index 1cc8d3690..38f5f0d3b 100644 --- a/doc/bt_manual_v10.md +++ b/doc/bt_manual_v10.md @@ -128,7 +128,7 @@ connection is successful. 4. Use Proxmark client on BT-serial port ```sh -./proxmark /dev/rfcomm0 +./proxmark3 /dev/rfcomm0 ``` The first time, your OS will ask you for pairing. The default PIN is 1234. If PIN is not typed in quickly, the client might timeout. Simply @@ -169,7 +169,7 @@ turn on solid. 4. a serial port `/dev/ttyUSB0` will be created, use Proxmark3 client on it ```sh -./proxmark /dev/ttyUSB0 +./proxmark3 /dev/ttyUSB0 ``` #### MacOS @@ -191,9 +191,19 @@ After reboot you can go ahead to pairing your Proxmark3 RDV4 Blue Shark: 8. A serial port like `/dev/tty.PM3_RDV40-DevB` will be created, use Proxmark3 client on it ```sh -./proxmark /dev/tty.PM3_RDV40-DevB +./proxmark3 /dev/tty.PM3_RDV40-DevB ``` +#### Android +#### (2) Fast connection using dedicated Bluetooth (HC-06 Master + CP2102) adapter under Android with Termux + + 1. Make sure you already followed this tutorial https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/termux_notes.md#setup and have Termux with an running Proxmark3 client ready. You need additional the `cp210x` serial usb driver enabled and working, like the `USB_ACM` driver to communicate wireless. + 2. Insert the Bluetooth adapter with an fitting USB-C/Micro-USB converter into your Android USB port and a serial port `/dev/ttyUSB0` will be created. To see if it's working, run `tsudo ls /dev/ttyU*` and it should list `/dev/ttyUSB0`. + 3. The adapter will search automatically and establish the connection to BlueShark. The adapter will remember the device that was first connected and after that the same device will be connected. After the connection is established, the blue state LED on add-on will turn on solid. + 4. If you see this, congratulations, you can run your Proxmark3 client in Termux with `tsudo proxmark3/client/proxmark3 /dev/ttyUSB0` + +##### Notes +If you bought your Bluetooth adapter somewhere else, make sure to set the baud rate to 115200 `AT+BAUD8` and PIN `AT+PIN1234` correctly ### 6. OTHER NOTES diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md new file mode 100644 index 000000000..4a61ae7d2 --- /dev/null +++ b/doc/cheatsheet.md @@ -0,0 +1,575 @@ +# Command Cheat Sheet + + +|Generic|Low Frequence 125 kHz|High Frequence 13.56 MHz| +|---|---|---| +|[Generic](#Generic)|[T55XX](#T55XX)|[Mifare](#Mifare)| +|[Data](#Data)|[HID Prox](#HID-Prox)|[iClass](#iClass)| +|[Memory](#Memory)|[Indala](#Indala)|| +|[Sim Module](#Sim-Module)|[Hitag](#Hitag)|| +|[Lua Scripts](#Lua-Scripts)||| +|[Smart Card](#Smart-Card)||| + + +## Generic +^[Top](#top) + +Identify High Frequency cards +``` +pm3 --> hf search +``` + +Identify Low Frequency cards +``` +pm3 --> lf search +``` + +Measure antenna characteristics, LF/HF voltage should be around 20-45+ V +``` +pm3 --> hw tune +``` + +Check versioning +``` +pm3 --> hw version +``` + +Check overall status +``` +pm3 --> hw status +``` + +## iClass +^[Top](#top) + +Reverse permute iClass master key +``` +Options +--- +r reverse permuted key + +pm3 --> hf iclass permute r 3F90EBF0910F7B6F +``` + +iClass Reader +``` +pm3 --> hf iclass reader +``` + +Dump iClass card contents +``` +Options +--- +k : *Access Key as 16 hex symbols or 1 hex to select key from memory + +pm3 --> hf iclass dump k AFA785A7DAB33378 +``` + +Read iClass Block +``` +Options +--- +b : The block number as 2 hex symbols +k : Access Key as 16 hex symbols or 1 hex to select key from memory + +pm3 --> hf iclass readblk b 7 k AFA785A7DAB33378 +``` + +Write to iClass Block +``` +Options +--- +b : The block number as 2 hex symbols +d : Set the Data to write as 16 hex symbols +k : Access Key as 16 hex symbols or 1 hex to select key from memory + +pm3 --> hf iclass writeblk b 07 d 6ce099fe7e614fd0 k AFA785A7DAB33378 +``` + +Print keystore +``` +Options +--- +p : print keys loaded into memory + +pm3 --> hf iclass managekeys p +``` + +Add key to keystore [0-7] +``` +Options +--- +n : specify the keyNbr to set in memory +k : set a key in memory + +pm3 --> hf iclass managekeys n 0 k AFA785A7DAB33378 +``` + +Encrypt iClass Block +``` +pm3 --> hf iclass encryptblk 0000000f2aa3dba8 +``` + +Load iClass dump into memory for simulation +``` +Options +--- +f : load iclass tag-dump filename + +pm3 --> hf iclass eload f iclass_tagdump-db883702f8ff12e0.bin +``` + +Simulate iClass +``` +Options +--- +0 simulate the given CSN +1 simulate default CSN +3 Full simulation using emulator memory (see 'hf iclass eload') + +pm3 --> hf iclass sim 3 +``` + +Clone iClass Legacy Sequence +``` +pm3 --> hf iclass readblk b 7 k AFA785A7DAB33378 +pm3 --> hf iclass writeblk b 07 d 6ce099fe7e614fd0 k AFA785A7DAB33378 +``` + +Simulate iClass Sequence +``` +pm3 --> hf iclass dump k AFA785A7DAB33378 +pm3 --> hf iclass eload f iclass_tagdump-db883702f8ff12e0.bin +pm3 --> hf iclass sim 3 +``` + +Extract custom iClass key (loclass attack) +``` +Options +--- +f : specify a filename to clone from +k : Access Key as 16 hex symbols or 1 hex to select key from memory +e : If 'e' is specified, elite computations applied to key + +pm3 --> hf iclass sim 2 +pm3 --> hf iclass loclass f iclass_mac_attack.bin +pm3 --> hf iclass dump k e +``` + +Verify custom iClass key +``` +Options +--- +f : Dictionary file with default iclass keys +u : CSN +p : EPURSE +m : macs +e : elite + +pm3 --> hf iclass lookup u 010a0ffff7ff12e0 p feffffffffffffff m 66348979153c41b9 f iclass_default_keys e +``` + +## Mifare +^[Top](#top) + +Check for default keys +``` +Options +--- +<*card memory> [t|d|s|ss] +* : all sectors +card memory : 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K +d : write keys to binary file + +pm3 --> hf mf chk *1 ? d mfc_default_keys +``` + +Check for default keys from local memory +``` +Options +--- +card memory : 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K +m : use dictionary from flashmemory + +pm3 --> hf mf fchk 1 m +``` + +Dump Mifare card contents +``` +Options +--- + : 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K +k : key filename, if no given, UID will be used as filename" +f : data filename, if no given, UID will be used as filename + +pm3 --> hf mf dump 1 +pm3 --> hf mf dump 1 k hf-mf-A29558E4-key.bin f hf-mf-A29558E4-data.bin +``` + +Convert .bin to .eml +``` +Options +--- +i : Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used + +pm3 --> script run dumptoemul -i dumpdata.bin +``` + +Write to Mifare block +``` +Options +--- + + +pm3 --> hf mf wrbl 0 A FFFFFFFFFFFF d3a2859f6b880400c801002000000016 +``` + +Run Hardnested attack +``` +Options +--- + [known target key (12 hex symbols)] [w] [s] +w : Acquire nonces and write them to binary file nonces.bin + +pm3 --> hf mf hardnested 0 A 8829da9daf76 0 A w +``` + +Load Mifare emul dump file into memory for simulation +``` +Options +--- + +[card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K, u = UL + +pm3 --> hf mf eload 353C2AA6 +pm3 --> hf mf eload 1 353C2AA6 +``` + +Simulate Mifare +``` +u : (Optional) UID 4,7 or 10 bytes. If not specified, the UID 4B from emulator memory will be used + +pm3 --> hf mf sim u 353c2aa6 +``` + +Simulate Mifare Sequence +``` +pm3 --> hf mf chk *1 ? d mfc_default_keys +pm3 --> hf mf dump 1 +pm3 --> script run dumptoemul -i dumpdata.bin +pm3 --> hf mf eload 353C2AA6 +pm3 --> hf mf sim u 353c2aa6 +``` + +Clone Mifare 1K Sequence +``` +pm3 --> hf mf chk *1 ? d mfc_default_keys +pm3 --> hf mf dump +pm3 --> hf mf restore 1 u 4A6CE843 k hf-mf-A29558E4-key.bin f hf-mf-A29558E4-data.bin +``` + +## HID Prox +^[Top](#top) + +Read HID Prox card +``` +pm3 --> lf hid read +``` + +Demodulate HID Prox card +``` +pm3 --> lf hid demod +``` + +Convert Site & Facility code to Wiegand +``` +Options +--- + +OEM : OEM number / site code +FC : facility code +CN : card number + +pm3 --> lf hid wiegand 0 56 150 +``` + +Simulate Prox card +``` + +pm3 --> lf hid sim 200670012d +``` + +Clone Prox to T5577 card +``` +pm3 --> lf hid clone 200670012d +``` + +Brute force HID reader +``` +Options +--- +a : 26|33|34|35|37|40|44|84 +f : 8-bit value HID facility code +c : (optional) cardnumber to start with, max 65535 +d : delay betweens attempts in ms. Default 1000ms +v : verbose logging, show all tries + +pm3 --> lf hid brute a 26 f 224 +pm3 --> lf hid brute v a 26 f 21 c 200 d 2000 +``` + +## Indala +^[Top](#top) + +Read Indala card +``` +pm3 --> lf indala read +``` + +Demodulate Indala card +``` +pm3 --> lf indala demod +``` + +Simulate Indala card +``` +Options +--- + : 64/224 UID + +pm3 --> lf indala sim a0000000c2c436c1 +``` + +Clone to T55x7 card +``` +Options +--- + : 64/224 UID + +pm3 --> lf indala clone a0000000c2c436c1 +``` + +## Hitag +^[Top](#top) + +Read Hitag information +``` +pm3 --> lf hitag info +``` + +Act as Hitag reader +``` +Options +--- +HitagS: +01 : Read all pages, challenge mode +02 : Read all pages, crypto mode. Set key=0 for no auth + +Hitag2: +21 : Read all pages, password mode. Default: 4D494B52 ("MIKR") +22 : Read all pages, challenge mode +23 : Read all pages, crypto mode. Key format: ISK high + ISK low. Default: 4F4E4D494B52 ("ONMIKR") +25 : Test recorded authentications +26 : Just read UID + +pm3 --> lf hitag 26 +pm3 --> lf hitag 21 4D494B52 +``` + +Sniff Hitag traffic +``` +pm3 --> lf hitag sniff +pm3 --> lf hitag list +``` + +Simulate Hitag +``` +pm3 --> lf hitag sim c378181c_a8f7.ht2 +``` + +Write to Hitag block +``` +Options +--- +HitagS: +03 : Write page, challenge mode +04 : Write page, crypto mode. Set key=0 for no auth + +Hitag2: +24 : Write page, crypto mode. Key format: ISK high + ISK low. +27 : Write page, password mode. Default: 4D494B52 ("MIKR") + +pm3 --> lf hitag writer 24 499602D2 1 00000000 +``` + +Simulate Hitag2 sequence +``` +pm3 --> lf hitag reader 21 56713368 +pm3 --> lf hitag sim c378181c_a8f7.ht2 +``` + +## T55XX +^[Top](#top) + +Detect T55XX card +``` +pm3 --> lf t55xx detect +``` + +Configure modulation +``` +Options +--- + : Set modulation +EM is ASK +HID Prox is FSK +Indala is PSK + +pm3 --> lf t55xx config FSK +``` + +Set timings to default +``` +Options +--- +p : persist to flashmemory +z : Set default t55x7 timings (use p to save if required) + +pm3 --> lf t55xx deviceconfig z p +``` + +Write to T55xx block +``` +b : block number to write. Between 0-7 +d : 4 bytes of data to write (8 hex characters) + +pm3 --> lf t55xx wr b 0 d 00081040 +``` + +Wipe a T55xx tag and set defaults +``` +pm3 --> lf t55xx wipe +``` + +## Data +^[Top](#top) + +Get raw samples [512-40000] +``` +pm3 --> data samples +``` + +Save samples to file +``` +pm3 --> data save +``` + +Load samples from file +``` +pm3 --> data load +``` + +## Lua Scripts +^[Top](#top) + +List Lua Scripts + +``` +pm3 --> script list +``` + +Convert .bin to .eml +``` +Options +--- +i : Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used + +pm3 --> script run dumptoemul -i xxxxxxxxxxxxxx.bin +``` + +Format Mifare card +``` +Options +--- +k : the current six byte key with write access +n : the new key that will be written to the card +a : the new access bytes that will be written to the card +x : execute the commands aswell. + +pm3 --> script run formatMifare -k FFFFFFFFFFFF -n FFFFFFFFFFFF -x +``` + +## Memory +^[Top](#top) + +Load default keys into memory +``` +Options +--- +o : offset in memory +f : file name +m : upload 6 bytes keys (mifare key dictionary) +i : upload 8 bytes keys (iClass key dictionary) +t : upload 4 bytes keys (pwd dictionary) + +pm3 --> mem load f mfc_default_keys m +pm3 --> mem load f t55xx_default_pwds t +pm3 --> mem load f iclass_default_keys i +``` + +## Sim Module +^[Top](#top) + +Upgrade Sim Module firmware +``` +pm3 --> sc upgrade f ../tools/simmodule/sim011.bin +``` + +## Smart Card +^[Top](#top) + +Get Smart Card Information +``` +pm3 --> sc info +``` + +Act like an IS07816 reader +``` +pm3 --> sc reader +``` + +Set clock speed +``` +Options +--- +c : clockspeed (0 = 16MHz, 1=8MHz, 2=4MHz) + +pm3 --> sc setclock c 2 +``` + +Send raw hex data +``` +Options +--- +r : do not read response +a : active smartcard without select (reset sc module) +s : active smartcard with select (get ATR) +t : executes TLV decoder if it possible +0 : use protocol T=0 +d : bytes to send + +pm3 --> sc raw s 0 d 00a404000e315041592e5359532e4444463031 : 1PAY.SYS.DDF01 PPSE directory with get ATR +pm3 --> sc raw 0 d 00a404000e325041592e5359532e4444463031 : 2PAY.SYS.DDF01 PPSE directory +pm3 --> sc raw 0 t d 00a4040007a0000000041010 : Mastercard +pm3 --> sc raw 0 t d 00a4040007a0000000031010 : Visa +```` + +Bruteforce SPI +``` +Options +--- +t : executes TLV decoder if it possible + +pm3 --> sc brute +pm3 --> sc brute t +``` diff --git a/doc/emv_notes.md b/doc/emv_notes.md new file mode 100644 index 000000000..a289d8ea5 --- /dev/null +++ b/doc/emv_notes.md @@ -0,0 +1,141 @@ +# EMV commands + + +### EMV Implemented parts: + +- Get ATR|ATS +- Get AID by PSE (`emv pse`) +- Get AID by appliation list (`emv search`) +- Select application (`emv select`) +- Format PDOL (look at next part) +- Execute GPO (`emv gpo` this step and format PDOL) +- Get records from AFL (`emv readrec`) +- Make SDA (check records from GPO) +- Make DDA (`emv challenge` `emv intauth`) +- Check PIN (`not implemented`) +- Fill CDOL1 and CDOL2 (look at next part) +- Execute AC1 (with CDA support) (`emv genac`) +- Check ARQC (bank part) (`not implemented`) +- Make ARPC (bank part) (`not implemented`) +- Execute external authenticate (`not implemented`) +- Execute AC2 (with CDA support) (`not implemented`) +- Check ARQC cryptogram (`not implemented`) +- Issuer scripts processing (`not implemented`) + +### Working parts of qVSDC: +^[Top](#top) + +- Get ATR|ATS +- Get AID by PSE (`emv pse`) +- Get AID by appliation list (`emv search`) +- Select application (`emv select`) +- Format PDOL (look at next part) +- Execute GPO (`emv gpo` this step and format PDOL) +- Get records from AFL (`emv readrec`) +- Make fDDA (`emv challenge` `emv intauth`) +- External authenticate command (`not implemented`) +- Issuer scripts processing (`not implemented`) + +### `not implemented` parts of EMV +^[Top](#top) + +They can be implemented, but it needs to know issuer's card keys (usually 3DES) and now this parts can be tested only on special test cards. + +### Commands +^[Top](#top) + +All this commands are parts of command `emv exec`. +command `emv exec` executes EMV transaction. it have parameters: +``` + -j, -J, --jload Load transaction parameters from `emv/defparams.json` file. + -f, -F, --forceaid Force search AID. Search AID instead of execute PPSE. + By default: Transaction type - MSD + -v, -V, --qvsdc Transaction type - qVSDC or M/Chip. + -c, -C, --qvsdccda Transaction type - qVSDC or M/Chip plus CDA (SDAD generation). + -x, -X, --vsdc Transaction type - VSDC. + -g, -G, --acgpo VISA. generate AC from GPO. + -w, -W, --wired Send data via contact (iso7816) interface. Contactless interface set by default. +``` +It works for VISA(r) and Mastercard(r) transactions. It may work with other EMV payment system's card (and it works in general cases that is described in EMV). + +### VISA(r) transactions: +^[Top](#top) + +MSD - Magnetic Stripe mode +VSDC - contact transacion +qVSDC - contactless transaction + +### Mastercard(r) transactions +^[Top](#top) + +MSD - Magnetic Stripe mode +M/Chip - contact and contactless transaction + +Different cards have different modes on/of and different behavior in them. So needs to check card in all this modes. +MSD - compatibility mode. Now it work always. But it less secure and in near future it will be slowly) disabled. + +### all commands: +^[Top](#top) + +``` +exec Executes EMV contactless transaction. +pse Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory. +search Try to select all applets from applets list and print installed applets. +select Select applet. +gpo Execute GetProcessingOptions. +readrec Read files from card. +genac Generate ApplicationCryptogram. +challenge Generate challenge. +intauth Internal authentication. +scan Scan EMV card and save it contents to json file for emulator. +test Crypto logic test. +list List ISO7816 history +roca Extract public keys and run ROCA test +``` + +All main commands are parts of EMV specification. Commands than not described there: + +`emv scan` - scans card and saves all records to json file. Can be executed with or without tags disassembly. + +`emv roca` - extract public keys from cards (part of `emv scan`) + +`emv test` - test all crypto code from emv part of proxmark. + +### Useful links: +^[Top](#top) + +EMV specifications +http://www.emvco.com/specifications.aspx?id=155 + +Excelent explanation of EMV +http://www.openscdp.org/scripts/emv/index.html + +Fully working terminal written in Ruby. +https://code.google.com/p/ruby-pboc2-lib/source/browse/trunk/lib/pboc.rb + +EMV kernel written in C++ +https://github.com/ntufar/EMV/tree/master/EMV_Library + +C EMV library (part of this library uses proxmark) +https://github.com/lumag/emv-tools + +Resources (keys, country codes, etc): +https://github.com/binaryfoo/emv-bertlv/tree/master/src/main/resources + +### EMV kernels +^[Top](#top) + +POS terminal checks card and selects one of EMV kernels and launches it for EMV transaction. Different kernels have different rules to make EMV transaction. + +This list from: + +EMVco Architecture and General Requirement V2.4 volume A. +EMVco Entry Point specification V2.4 volume B + +- EMVco C-1 Kernel 1 V2.4 for some cards with JCB AIDs and some cards with Visa AIDs +- EMVco C-2 Kernel 2 V2.4 for MasterCards AIDs +- EMVco C-3 Kernel 3 V2.4 for Visa AIDs +- EMVco C-4 Kernel 4 V2.4 for American Express AIDs +- EMVco C-5 Kernel 5 V2.4 for JCB AIDs +- EMVco C-6 Kernel 6 V2.4 for Discover AIDs +- EMVco C-7 Kernel 7 V2.4 for UnionPay AIDs diff --git a/doc/extensions_notes.md b/doc/extensions_notes.md new file mode 100644 index 000000000..f8d4c75c1 --- /dev/null +++ b/doc/extensions_notes.md @@ -0,0 +1,17 @@ +# Notes on file extensions + +The Proxmark3 client uses a wide range of files. Here is a brief recap to get you up to speed. + +| extension | description| +|---|---| +| .exe | windows executable | +| .bin | binary file, can be firmware or memory dump of a tag | +| .eml | text file, with memory dump of a tag | +| .mfd | binary file, usually created with Mifare Classic Tool app (MCT), contains memory dump of tag. Very similar to .bin file | +| .json | JSON file, usually settings file or it can also be a memory dump of a tag | +| .dic | dictionary file. textual, with keys/passwords one line / key | +| .elf | binary proxmark3 device firmware file. | +| .cmd | text file, contains proxmark3 client commands used to call client with -s | +| .lua | text file, contains lua script to be run inside client. or called with -l | +| .pm3 | text file, with numbers ranging 0-255 or -127 - 128. Contains trace signal data for low frequency tags (data load) | +| .trace | binary file, contains trace log data usually from high frequency tags. (hw trace load) | diff --git a/doc/jtag_notes.md b/doc/jtag_notes.md new file mode 100644 index 000000000..8e31f1112 --- /dev/null +++ b/doc/jtag_notes.md @@ -0,0 +1,79 @@ +Some notes on how to reflash a bricked Proxmark3 over JTAG. + +# Linux and OpenOCD + +## Using RDV4 scripts + +The RDV4 repository contains helper scripts for JTAG flashing. + +* Get OpenOCD, e.g.: `apt-get install openocd` +* Create `tools/jtag_openocd/openocd_configuration` by copying [`tools/jtag_openocd/openocd_configuration.sample`](/tools/jtag_openocd/openocd_configuration.sample) +* Tune it to fit your JTAG tool: adapt `CONFIG_IF` to refer to the `interface-*.cfg` file corresponding to your JTAG tool. By default `openocd_configuration.sample` is set up to work with the J-Link. +* Wire the Proxmark3 to the JTAG tool. How to do it depends on the tool. See below for examples. **Warning:** don't plug the Proxmark3 on USB if the tool delivers already the voltage to the Proxmark3, which is most probably the case. +* Then just run + +``` +cd tools/jtag_openocd/ +./openocd_flash_recovery.sh +``` + +In some rare situations, flashing the full image over JTAG may fail but the bootloader could be fixed. If it's the case, you can flash the image without JTAG by booting on your fresh bootloader (possibly forced by pressing the Proxmark3 button). + +For advanced usages there are also `openocd_flash_dump.sh` for dumping the content of the Proxmark3 and `openocd_interactive.sh` for an OpenOCD console. + +## RDV4 pinout + +The RDV4 JTAG header is quite smaller compared to other Proxmark3 platforms. +If you're using a J-Link, there is a [convenient adapter](https://github.com/RfidResearchGroup/proxmark3/wiki/Tools#jtag-adapter) made by Proxgrind. +You can also make yours with some 1.27mm headers (look for `1.27mm header` on Aliexpress) or Pogo pins. + +## JLink pinout + +J-Link [pinout](https://www.segger.com/interface-description.html): + +``` + --------- --------- + |1917151311 9 7 5 3 1| + |201816141210 8 6 4 2| + -------------------- +``` + +PM3 | JLink +--- | ----- +TMS | 7 +TDI | 5 +TDO |13 +TCK | 9 +GND | 6 +3.3 | 2 + +## Raspberry Pi pinout + +RPi [pinout](https://pinout.xyz/): + +PM3 | RPi +--- | ----- +TMS | 22 +TDI | 19 +TDO | 21 +TCK | 23 +GND | 6 +3.3 | 1 + +## Third party notes on using a BusPirate + +* https://github.com/Proxmark/proxmark3/wiki/Debricking-Proxmark3-with-buspirate + +## Third party notes on using a J-Link + +* http://wiki.yobi.be/wiki/Proxmark + +## Third party notes on using a RaspBerry Pi + +* http://www.lucasoldi.com/2017/01/17/unbrick-proxmark3-with-a-raspberry-pi-and-openocd/ + +# Windows + +## Third party notes on using a J-Link on Windows + +* https://github.com/Proxmark/proxmark3/wiki/De-Bricking-Segger diff --git a/doc/loclass_notes.md b/doc/loclass_notes.md new file mode 100644 index 000000000..2684ae433 --- /dev/null +++ b/doc/loclass_notes.md @@ -0,0 +1,26 @@ +# About LOCLASS attack + +This document is primarily intended for understanding `hf iclass loclass` and files used with it. + +LOCLASS aim is to recoved the used masterkey for that specific reader configued in Elite mode / High Security mode. + +LOCLASS, is a two part attack. First is the online part where you gather needed information from the reader by presenting a carefully selected CSN and save the responses to file. For the first part you run `hf iclass sim 2` and take notice of the saved filename. + +The second part is offline, where the information gathered from the first step is used in a series of DES operations to figure out the used +masterkey. + run `hf iclass loclass f abc.bin` + +If you don't have access to a iClass SE reader configured in Elite mode there is a test file which you can use. + `hf iclass loclass f iclass_dump.bin` + + +# Unit testing +In order to verify that loclass is actually working, there is a "unit" test mode. +run `hf iclass loclass t`. + +This test mode uses two files. + +- `iclass_dump.bin` + this is a sample file from `hf iclass sim 2`, with complete keytable recovery, using 128 carefully selected CSN and the file contains the MAC results from reader. +- `iclass_key.bin` + this is file shall contain the legacy masterkey, AA1 key. loclass uses it to verify that permution / reversing / generation of key is correct. \ No newline at end of file diff --git a/doc/md/Development/Maintainers.md b/doc/md/Development/Maintainers.md new file mode 100644 index 000000000..ff3525784 --- /dev/null +++ b/doc/md/Development/Maintainers.md @@ -0,0 +1,73 @@ +# Hi maintainers! + +Here are some tips how to integrate this repo in some nice package for your distro. +Feel free to contact us via Github issues for any question, suggestion or if you want to share useful tricks in this file for other maintainers. + +Makefile +======== + +`PREFIX` and `UDEV_PREFIX` can be provided by environment variable, else it defaults to `/usr/local/share` and `/etc/udev/rules.d`. + +`DESTDIR` can be provided by environment variable, it can be a relative path and it will be prepended to `PREFIX`, so you can use e.g.: + +``` +make -j +make install DESTDIR=build PREFIX=/usr UDEV_PREFIX=/lib/udev/rules.d +``` + +and it will be deployed as + +``` +./build/lib/udev/rules.d/77-pm3-usb-device-blacklist.rules +./build/usr/bin/proxmark3 ... +./build/usr/share/doc/proxmark3/... +./build/usr/share/proxmark3/firmware/fullimage.elf +etc. +``` + +That should be a good start for you to create your package :) + +If you need to tune some more paths, see their definition in `Makefile.defs`. +E.g. you might need to move the documentation elsewhere according to your distro policy: + +``` +make install PREFIX=/usr INSTALLDOCSRELPATH=share/doc/proxmark3-${version} +``` + +It's possible to add other firmwares as well with tagged names (`FWTAG=`), e.g. here we're compiling another image for non-RDV4 devices: + +``` +make -j fullimage PLATFORM=PM3OTHER PLATFORM_EXTRAS= +make fullimage/install PLATFORM=PM3OTHER PLATFORM_EXTRAS= DESTDIR=build PREFIX=/usr FWTAG=other +``` + +and it will be added along the other firmware as: + +``` +./build/usr/share/proxmark3/firmware/fullimage-other.elf +``` + +For verbose usage and see the actual commands being executed, add `V=1`. + +`CFLAGS` and `LDFLAGS` can be overriden by environment variables. + +Default compiler is gcc but you can use clang for the non-ARM parts with e.g. `make client CC=clang CXX=clang++ LD=clang++`. + +`make install` is actually triggering the following individual targets which can be accessed individually: + +* `make client/install` +* `make bootrom/install` +* `make fullimage/install` (alias of `make armsrc/install`) +* `make recovery/install` +* `make mfkey/install` +* `make nonce2key/install` +* `make fpga_compress/install` (dummy) +* `make common/install` (some shared content installation:) + * `pm3-*` scripts + * `tools/jtag_openocd`, `traces` + * `doc/md`, `doc/*.md` + * Tools scripts (`pm3_eml2lower.sh` etc) + * SIM firmware + * udev rule on Linux + +Same logic for `make all`, `make clean`, `make uninstall` diff --git a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md index fe23db001..70d102aa3 100644 --- a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md @@ -24,28 +24,32 @@ sudo apt-get update Install the requirements ```sh -sudo apt-get install p7zip git ca-certificates build-essential libreadline5 libreadline-dev \ -libusb-0.1-4 libusb-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libnewlib-dev libqt4-dev +sudo apt-get install --no-install-recommends git ca-certificates build-essential pkg-config \ +libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev ``` -If you don't need the graphical components of the Proxmark3 client, you can skip the installation of `libqt4-dev`. +If you don't need the graphical components of the Proxmark3 client, you can skip the installation of `qtbase5-dev`. If you get some (non blocking) error at runtime such as _Gtk-Message: Failed to load module "canberra-gtk-module"_ you may have to install `libcanberra-gtk-module`. ## On ArchLinux ```sh -sudo pacman -Sy base-devel p7zip libusb readline ncurses arm-none-eabi-gcc arm-none-eabi-newlib git --needed -``` -Additional AUR packages: -```sh -yaourt -S termcap +sudo pacman -Sy base-devel readline arm-none-eabi-gcc arm-none-eabi-newlib git --needed ``` If you want graphical output (such as in `hw tune`): ```sh sudo pacman -Su qt5-base ``` +## On Fedora + +```sh +sudo dnf install git make gcc gcc-c++ arm-none-eabi-gcc-cs arm-none-eabi-newlib readline-devel qt5-qtbase-devel libatomic +``` + +If you don't need the graphical components of the Proxmark3 client, you can skip the installation of `qt5-qtbase-devel`. + # Clone the RRG/Iceman repository ```sh diff --git a/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md b/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md index 34b9c3aa5..f78016df9 100644 --- a/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md @@ -1,4 +1,7 @@ -# Homebrew (Mac OS X) +# Homebrew (Mac OS X), automatic installation + +## Install Proxmark3 tools + These instructions comes from @Chrisfu, where we got the proxmark3.rb scriptfile from. For further questions about Mac & Homebrew, contact @Chrisfu (https://github.com/chrisfu/) @@ -8,7 +11,9 @@ For further questions about Mac & Homebrew, contact @Chrisfu (https://github.c 3. Install Proxmark3: `brew install proxmark3` for stable release or `brew install --HEAD proxmark3` for latest non-stable from GitHub. -## Upgrading HomeBrew tap formula +For more info, go to https://github.com/RfidResearchGroup/homebrew-proxmark3 + +## Upgrade HomeBrew tap formula *This method is useful for those looking to run bleeding-edge versions of RRG/iceman's client. Keep this in mind when attempting to update your HomeBrew tap formula as this procedure could easily cause a build to break if an update is unstable on macOS.* @@ -24,21 +29,33 @@ brew upgrade --fetch-HEAD proxmark3 ## Flash the BOOTROM & FULLIMAGE -With your Proxmark3 unplugged from your machine, press and hold the button on your Proxmark3 as you plug it into a USB port. Continue to hold the button until after this step is complete and the `proxmark3-flasher` command outputs "Have a nice day!" +With your Proxmark3 unplugged from your machine, press and hold the button on your Proxmark3 as you plug it into a USB port. You can release the button, two of the four LEDs should stay on. You're un bootloader mode, ready for the next step. In case the two LEDs don't stay on when you're releasing the button, you've an old bootloader, start over and keep the button pressed during the whole flashing procedure. + +In principle, the helper script `pm3-flash-all` should auto-detect your port, so you can just try: ```sh -sudo proxmark3-flasher /dev/tty.usbmodemiceman1 -b /usr/local/Cellar/proxmark3/HEAD-/share/firmware/bootrom.elf /usr/local/Cellar/proxmark3/HEAD-/share/firmware/fullimage.elf +pm3-flash-all ``` -> Replace \ with the HEAD-XXXX ID displayed by brew. -> Depending on the firmware version your Proxmark3 can also appear as `/dev/tty.usbmodem881` +If port detection failed, you'll have to call the flasher manually and specify the correct port: +```sh +proxmark3 /dev/tty.usbmodemiceman1 --flash --unlock-bootloader --image /usr/local/share/proxmark3/firmware/bootrom.elf --image /usr/local/share/proxmark3/firmware/fullimage.elf +``` + +> Depending on the firmware version your Proxmark3 can also appear as `/dev/tty.usbmodem881`. ## Run the client ```sh -sudo proxmark3 /dev/tty.usbmodemiceman1 +pm3 +``` + +or, if the port doesn't get properly detected: + +```sh +proxmark3 /dev/tty.usbmodemiceman1 ``` ## Next steps @@ -50,3 +67,31 @@ For the next steps, please read the following pages: * [Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)| + + +# Homebrew (Mac OS X), developer installation + +These instructions will show how to setup the environment on OSX to the point where you'll be able to clone and compile the repo by yourself, as on Linux, Windows, etc. + +1. Install homebrew if you haven't yet already done so: http://brew.sh/ + +2. Install dependencies: + +``` +brew install readline qt5 pkgconfig +brew install RfidResearchGroup/proxmark3/arm-none-eabi-gcc +``` + +## Compile and use the project + +To use the compiled client, the only difference is that the Proxmark3 port is `/dev/tty.usbmodemiceman1`, so commands become: + +```sh +proxmark3 /dev/ttyACM0 => proxmark3 /dev/tty.usbmodemiceman1 +``` + +Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md). + +To flash on OS X, better to enter the bootloader mode manually, else you may experience errors. +With your Proxmark3 unplugged from your machine, press and hold the button on your Proxmark3 as you plug it into a USB port. You can release the button, two of the four LEDs should stay on. You're in bootloader mode, ready for the next step. In case the two LEDs don't stay on when you're releasing the button, you've an old bootloader, start over and keep the button pressed during the whole flashing procedure. +From there, you can follow the original compilation instructions. diff --git a/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md b/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md index 68b69ea7b..23ae480cc 100644 --- a/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md +++ b/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md @@ -121,7 +121,7 @@ In short: * unplug device * press button and keep it pressed (IMPORTANT) * plug in device -* run flash command `sudo client/flasher /dev/ttyACM0 armsrc/obj/fullimage.elf` +* run flash command `pm3-flash-fullimage` * wait until flash is finished * release button * un/plug device diff --git a/doc/md/Installation_Instructions/Troubleshooting.md b/doc/md/Installation_Instructions/Troubleshooting.md new file mode 100644 index 000000000..e0cf7f7aa --- /dev/null +++ b/doc/md/Installation_Instructions/Troubleshooting.md @@ -0,0 +1,159 @@ +# Troubleshooting guide + +## First of all + +Always use the latest repository commits from *master* branch. There are always many fixes done almost daily. + +## Table of Contents + + * [pm3 or pm3-flash* doesn't see my Proxmark](#pm3-or-pm3-flash-doesnt-see-my-proxmark) + * [My Proxmark3 seems bricked](#my-proxmark3-seems-bricked) + * [Maybe just a false alarm?](#maybe-just-a-false-alarm) + * [Find out why it would be bricked](#find-out-why-it-would-be-bricked) + * [Determine if the bootloader was damaged or only the main OS image](#determine-if-the-bootloader-was-damaged-or-only-the-main-os-image) + * [Ok, my bootloader is definitively dead, now what?](#ok-my-bootloader-is-definitively-dead-now-what) + * [Slow to boot or difficulties to enumerate the device over USB](#slow-to-boot-or-difficulties-to-enumerate-the-device-over-usb) + * [Troubles with SIM card reader](#troubles-with-sim-card-reader) + * [Troubles with t5577 commands or MFC/iClass/T55x7 dictionaries](#troubles-with-t5577-commands-or-mfciclasst55x7-dictionaries) + * [File not found](#file-not-found) + * [pixmap / pixbuf warnings](#pixmap--pixbuf-warnings) + +## `pm3` or `pm3-flash*` doesn't see my Proxmark + +Try using directly the client: + +``` +client/proxmark3 ... +``` + +Refer to the installation guide specific to your OS for details about ports. + +* [Linux](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) +* [Mac OSX](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md) +* [Windows](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md) + +Note that with the Bluetooth adapter, you *have to* use directly the client, and flasher over Bluetooth is not possible. + +* [Bluetooth](/doc/bt_manual_v10.md) + +## My Proxmark3 seems bricked + +### Maybe just a false alarm? + +The flasher refused to flash your Proxmark3? Are there any messages in *red*? The most common reason is that the Proxmark3 RDV4 firmware recently got a new bootloader able to handle larger firmwares and... the image grew over 256k almost at the same time. So your old bootloader can't flash such new images. But it's easy, you just need to flash *first* the bootloader *only*, then the image. + +``` +pm3-flash-bootrom +pm3-flash-fullimage +``` +or +``` +proxmark3 --flash --unlock-bootloader --image bootrom/obj/bootrom.elf +proxmark3 --flash --image armsrc/obj/fullimage.elf +``` + +### Find out why it would be bricked + +The most common reason of a flashing failure is the interference of ModemManager, read carefully [how to avoid ModemManager-related issues](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md) and fix your setup! + +Another possibility is if, when using the button for entering bootloader mode, the button was released during flashing (for old bootloaders) or the button was pressed again during flashing (for newer bootloaders). + +### Determine if the bootloader was damaged or only the main OS image + +Unplug, press the Proxmark3 button and keep it pressed when you plug it on USB. If the red LEDs show a "off/on/off/on" pattern, you're goot, you manually entered into the bootloader mode. +On new bootloaders, you can release the button. If the pattern disappears, you're on an older bootloader and you've to do it again and keep the button pressed during all the flashing operation. + +Once in bootloader mode, flash the main image. + +``` +pm3-flash-fullimage +``` +or +``` +proxmark3 --flash --image armsrc/obj/fullimage.elf +``` + +You should be back on tracks now. In case the flasher complains about bootloader version, you can follow the button procedure and flash first your bootloader. + +``` +pm3-flash-bootrom +``` +or +``` +proxmark3 --flash --unlock-bootloader --image bootrom/obj/bootrom.elf +``` + +### Ok, my bootloader is definitively dead, now what? + +At this point, only reflashing via JTAG can revive your Proxmark3. + +See [details here](/doc/jtag_notes.md). + +## Slow to boot or difficulties to enumerate the device over USB + +You're using another Proxmark3 than a RDV4? +The RDV4 firmware can run on other Proxmark3 as such but the booting procedure is a bit slower because of the absence of SIM and external flash. +Make sure to configure properly your `Makefile.platform` to get a firmware better tuned for your Proxmark3 hardware. +See [details here](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md). + +## Troubles with SIM card reader + +(RDV4 only) Make sure you've the latest SIM firmware according to the [configuration documentation](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md#verify-sim-module-firmware-version). + +## Troubles with t5577 commands or MFC/iClass/T55x7 dictionaries + +(RDV4 only) Make sure you've set everything up according to the [configuration documentation](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md#first-things-on-your-rdv40). + +Instructions evolve over time so check if you're still up to date! + +## File not found + +If Proxmark3 has been installed with `make install` or packaged for your distro, the binaries should be in your path and you can call them directly: + +``` +pm3 +proxmark3 +``` + +and you must adapt accordingly the file path of some commands, e.g. + +``` +proxmark3 --flash --image /usr/local/share/proxmark3/firmware/fullimage.elf +<> +proxmark3 --flash --image /usr/share/proxmark3/firmware/fullimage.elf + +pm3 --> sc upgrade f /usr/local/share/proxmark3/firmware/sim011.bin +<> +pm3 --> sc upgrade f /usr/share/proxmark3/firmware/sim011.bin +``` + +If you didn't install the PRoxmark but you're working from the sources directory and depending how you launch the client, your working directory might be the root of the repository: + +``` +./pm3 ... +client/proxmark3 ... +``` + +or the `client/` subdirectory: + +``` +cd client; ./proxmark3 ... +``` + +Therefore client commands referring to files of the repo must be adapted, e.g. + +``` +client/proxmark3 --flash --image armsrc/obj/fullimage.elf +<> +./proxmark3 --flash --image ../armsrc/obj/fullimage.elf + +pm3 --> sc upgrade f tools/simmodule/sim011.bin +<> +pm3 --> sc upgrade f ../tools/simmodule/sim011.bin +``` + +etc. + +## pixmap / pixbuf warnings + +If you get warnings related to pixmap or pixbuf such as *Pixbuf theme: Cannot load pixmap file* or *Invalid borders specified for theme pixmap*, it's a problem of your Theme, try another one and the problem should vanish. See e.g. [#354](https://github.com/RfidResearchGroup/proxmark3/issues/354) (Yaru theme on Ubuntu) and [#386](https://github.com/RfidResearchGroup/proxmark3/issues/386) (Kali-X theme on Kali). diff --git a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md index db9a9084f..9cd150a22 100644 --- a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md @@ -19,7 +19,7 @@ Step by step guides are online such as [RiscCorps](https://store.ryscc.com/blogs ## Download / clone ProxSpace repo -Download the Gator96100 ProxSpace package from https://github.com/Gator96100/ProxSpace/ +Download the Gator96100 ProxSpace package from https://github.com/Gator96100/ProxSpace/releases If you prefer, you can clone it, provided that you installed Github for Windows https://desktop.github.com/. @@ -52,34 +52,14 @@ pacman -S mingw-w64-x86_64-astyle ## Compile and use the project +To use the compiled client, the only differences are that executables end with `.exe` (e.g. `proxmark3.exe`) and that the Proxmark3 port is one of your `comX` ports where "X" is the com port number assigned to proxmark3 under Windows, so commands become: + +```sh +proxmark3 /dev/ttyACM0 => proxmark3.exe comX +``` + Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md). -To use the compiled client and flasher, the only differences are that executables end with `.exe` (e.g. `client/flasher.exe`) and that the Proxmark3 port is one of your `comX` ports where "X" is the com port number assigned to proxmark3 under Windows. - -To flash: In principle, the helper script `flash-all.sh` should auto-detect your COM port, so you can just try: - -```sh -./flash-all.sh -``` - -If COM port detection failed, you'll have to call the flasher manually and specify the correct port: - -```sh -client/flasher.exe comX -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf -``` - -Similarly, to run the client, you may try: - -```sh -./proxmark3.sh -``` - -Or, by specifying the COM port manually: - -```sh -client/proxmark3.exe comX -``` - # Installing on Windows with WSL It requires to run a Windows 10 version 1709 or above. Previous versions didn't have support for COM ports. @@ -98,12 +78,11 @@ Enter WSL prompt (`wsl`) and from there, follow the [Linux Installation Instruct ```sh sudo apt-get update -sudo apt-get install p7zip git ca-certificates build-essential libreadline5 libreadline-dev libusb-0.1-4 \ -libusb-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libstdc++-arm-none-eabi-newlib \ -libqt4-dev +sudo apt-get install --no-install-recommends git ca-certificates build-essential pkg-config \ +libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev ``` -If you don't need the graphical components of the Proxmark3 client, you can skip the installation of `libqt4-dev`. +If you don't need the graphical components of the Proxmark3 client, you can skip the installation of `qtbase5-dev`. ## Clone the RRG/Iceman repository @@ -113,9 +92,11 @@ git clone https://github.com/RfidResearchGroup/proxmark3.git ## Compile and use the project -Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md). +To use the compiled client, the only difference is that the Proxmark3 port is translated from your `comX` port where "X" is the com port number assigned to proxmark3 under Windows, to a `/dev/ttySX`, so commands become: -To use the compiled client and flasher, the only difference is that the Proxmark3 port is translated from your `comX` port where "X" is the com port number assigned to proxmark3 under Windows, to a `/dev/ttySX`. +```sh +proxmark3 /dev/ttyACM0 => proxmark3 /dev/ttySX +``` Depending on the Windows version, you might need to give permission to the current user to access `/dev/ttySX`: (change X to your port number) @@ -142,28 +123,6 @@ and add it to your Bash profile for the next times: echo "export DISPLAY=:0" >> ~/.bashrc ``` -To flash: In principle, the helper script `flash-all.sh` should auto-detect your COMX==/dev/ttySX port, so you can just try: - -```sh -./flash-all.sh -``` - -If port detection failed, you'll have to call the flasher manually and specify the correct port: - -```sh -client/flasher /dev/ttySX -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf -``` - -Similarly, to run the client, you may try: - -```sh -./proxmark3.sh -``` - -Or, by specifying the COM port manually: - -```sh -client/proxmark3 /dev/ttySX -``` - Note that it may take a quite long time for a freshly plugged Proxmark3 to be visible on a WSL /dev/ttySX port. + +Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md). diff --git a/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md b/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md index 7493fba1a..e423752ab 100644 --- a/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md +++ b/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md @@ -24,27 +24,62 @@ git pull make clean && make all ``` -## Flash the BOOTROM & FULLIMAGE +## Install -In most cases, you can run the script `flash-all.sh` which try to auto-detect the port to use, on several OS. - -For the other cases, specify the port by yourself. For example, for a Proxmark3 connected via USB under Linux: +This is an optional step. If you do ```sh -client/flasher /dev/ttyACM0 -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf +sudo make install +``` + +Then the required files will be installed on your system, by default in `/usr/local/bin` and `/usr/local/share/proxmark3`. +Maintainers can read [this doc](../Development/Maintainers.md) to learn how to modify installation paths via `DESTDIR` and `PREFIX` Makefile variables. + +The commands given in the documentation assume you did the installation step. If you didn't, you've to adjust the commands paths and files paths accordingly, +e.g. calling `./pm3` or `client/proxmark3` instead of just `pm3` or `proxmark3`. + +## Flash the BOOTROM & FULLIMAGE + +In most cases, you can run the following script which try to auto-detect the port to use, on several OS: + +```sh +pm3-flash-all +``` + +For the other cases, specify the port by yourself. For example, for a Proxmark3 connected via USB under Linux (adjust the port for your OS): + +```sh +proxmark3 /dev/ttyACM0 --flash --unlock-bootloader --image bootrom.elf --image fullimage.elf +``` + +The firmware files will be searched in the expected locations (installed files, working repo files, user folder, etc.). You can also specify their location: + +```sh +pm3-flash -b /tmp/my-bootrom.elf /tmp/my-fullimage.elf +``` + +or + +```sh +proxmark3 /dev/ttyACM0 --flash --unlock-bootloader --image /tmp/my-bootrom.elf --image /tmp/my-fullimage.elf ``` ## Run the client -In most cases, you can run the script `proxmark3.sh` which try to auto-detect the port to use, on several OS. +In most cases, you can run the script `pm3` which try to auto-detect the port to use, on several OS. For the other cases, specify the port by yourself. For example, for a Proxmark3 connected via USB under Linux: -Here, for example, for a Proxmark3 connected via USB under Linux: +Here, for example, for a Proxmark3 connected via USB under Linux (adjust the port for your OS): ```sh -cd client -./proxmark3 /dev/ttyACM0 +proxmark3 /dev/ttyACM0 +``` + +or from the local repo + +```sh +client/proxmark3 /dev/ttyACM0 ``` ## Next steps diff --git a/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md b/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md index 0d3665f37..8b88115c6 100644 --- a/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md +++ b/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md @@ -1,9 +1,9 @@ ### First things on your RDV40 You will need to run these commands to make sure your rdv4 is prepared ``` -pm3 --> mem load f default_keys m -pm3 --> mem load f default_pwd t -pm3 --> mem load f default_iclass_keys i +pm3 --> mem load f mfc_default_keys m +pm3 --> mem load f t55xx_default_pwds t +pm3 --> mem load f iclass_default_keys i pm3 --> lf t55xx deviceconfig a 29 b 17 c 15 d 47 e 15 p pm3 --> lf t55xx deviceconfig r 1 a 31 b 20 c 18 d 50 e 15 p pm3 --> lf t55xx deviceconfig r 2 a 31 b 20 c 18 d 40 e 15 p @@ -30,11 +30,25 @@ Find version in the long output, look for these two lines #db# version.................v2.06 ``` -This version is obsolete. The following command upgrades your device sim module firmware. -Don't not turn off your device during the execution of this command!! +This version is obsolete. + +If you didn't download sim011.bin from the RRG Repo be aware that it might be corrupted or faulty. +You find a hash text file in this folder. It was generated with the following linux command. ``` -pm3 --> sc upgrade f ../tools/simmodule/SIM011.BIN +sha512sum -b sim011.bin > sim011.sha512.txt +``` + +You should validate the sim011.bin file against this hash file in order to be sure the file is not corrupted or faulty. + +The following command upgrades your device sim module firmware. +Don't not turn off your device during the execution of this command!! +Even its a quite fast command you should be warned. You may brick it if you interrupt it. + +``` +pm3 --> sc upgrade f /usr/local/share/proxmark3/firmware/sim011.bin +# or if from local repo +pm3 --> sc upgrade f tools/simmodule/sim011.bin ``` You get the following output if the execution was successful: @@ -54,6 +68,12 @@ You get the following output if the execution was successful: [+] Smartcard socket firmware upgraded successful ``` +Run hw status command to verify that the upgrade went well. + +``` +pm3 --> hw status +``` + ## Next steps For the next steps, please read the following page: 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 aea5b5e30..b4fb4384a 100644 --- a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md +++ b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md @@ -19,7 +19,7 @@ These features make it very different from all other devices, there is non other **Recommendation**: if you don't have a RDV4, we strongly recommend your device to have at least a 512kb arm chip, since this repo is on the very edge of 256kb limit. -A firmware built for the RDV4 can still run on the other platforms as it will auto-detect during boot that external SPI and Sim are not present, still it will boot faster if it's tuned to the platform. +A firmware built for the RDV4 can still run on the other platforms as it will auto-detect during boot that external SPI and Sim are not present, still it will boot faster if it's tuned to the platform, which solves USB enumeration issues on some OSes. If you need to tune things and save the configuration, create a file `Makefile.platform` in the root directory of the repository, see `Makefile.platform.sample`. For an up-to-date exhaustive list of options, you can run `make PLATFORM=`. @@ -28,17 +28,15 @@ For an up-to-date exhaustive list of options, you can run `make PLATFORM=`. Here are the supported values you can assign to `PLATFORM` in `Makefile.platform`: -| PLATFORM | DESCRIPTION | -|-----------------|----------------------------------------| -| PM3RDV4 (def) | Proxmark3 rdv4 with AT91SAM7S512 | -| PM3EVO | Proxmark3 EVO with AT91SAM7S512 | -| PM3EASY | Proxmark3 rdv3 Easy with AT91SAM7S256 | -| PM3RDV2 | Proxmark3 rdv2 with AT91SAM7S512 | -| PM3OLD256 | Proxmark3 V1 with AT91SAM7S256 | -| PM3OLD512 | Proxmark3 V1 with AT91SAM7S512 | +| PLATFORM | DESCRIPTION | +|-----------------|--------------------------| +| PM3RDV4 (def) | Proxmark3 rdv4 | +| PM3OTHER | Proxmark3 generic target | By default `PLATFORM=PM3RDV4`. +The MCU version (256 or 512) will be detected automatically during flashing. + Known issues: * 256kb Arm chip devices: The compiled firmware image from this repo may/will be too large for your device. diff --git a/doc/path_notes.md b/doc/path_notes.md new file mode 100644 index 000000000..556780f54 --- /dev/null +++ b/doc/path_notes.md @@ -0,0 +1,235 @@ +# Notes on paths. + + +With the recent (2019-09-01) changes and creation of `make install` command it is easy to get lost. + +If you install the Proxmark tools with `make install`, they will go under the prefix `/usr/local/` but if you install the tools from your distro, there are chances the path is `/usr` so you'll have to adapt the paths presented here. + +# Installed elements + +## Binaries + +The main Proxmark3 executables / shellscripts will be copied to + +``` +/usr/local/bin/ +``` + +* executables: `proxmark3` +* scripts: `pm3`, `pm3-flash`, `pm3-flash-all`, `pm3-flash-bootloader`, `pm3-flash-fullimage` + +Some more executable / scripts will be copied to + +``` +/usr/local/share/proxmark3/tools +``` + +* executables: `mfkey32`, `mfkey32v2`, `mfkey64`, `nonce2key` +* scripts: `pm3_eml2lower.sh`, `pm3_eml2upper.sh`, `pm3_mfdread.py`, `pm3_mfd2eml.py`, `pm3_eml2mfd.py`, `findbits.py`, `rfidtest.pl`, `xorcheck.py` + + +## Firmwares + +The recovery / firmware files will be copied to + +``` +/usr/local/share/proxmark3/firmware +``` + +* Proxmark3 firmware: `bootrom.elf`, `fullimage.elf`, `proxmark3_recovery.bin` (used for JTAG) +* SIM firmware: `sim011.bin`, `sim011.sha512.txt` + + +## Traces + +Proxmark3 client has a lot of sample trace files for many different low frequency tags. They will be copied to + +``` +/usr/local/share/proxmark3/traces +``` + + +## JTAG-related stuff + +JTAG configurations and helper scripts for OpenOCD will be copied to + +`/usr/local/share/proxmark3/jtag_openocd` + + +## Proxmark3 client files: dictionaries + +Dictionaries used by the client will be copied to + +``` +/usr/local/share/proxmark3/dictionaries +``` + +Here you find the default dictionaries used for commands like `hf mf chk`, `hf mf fchk`, `lf t55xx chk` +A dictionary file is a text based file with one key per line in hexdecimal form. +The length of the key is decided by the Proxmark3 client for the different commands. All chars afterwards on line is ignored. +if key isn't a hex number, the key is igonored. + +- t55xx, Mifare Ultralight/NTAG - uses 4 hexbytes (11223344) +- Mifare classic uses 6 hexbytes (112233445566) +- iClass uses 8 hexbytes (1122334455667788) + +See [here](#proxmark3-client-files-and-traces) how to add your own dictionaries. + +## Proxmark3 client files: cmd scripts + +Cmd scripts used by the client will be copied to + +``` +/usr/local/share/proxmark3/cmdscripts +``` + +See [here](#proxmark3-client-files-and-traces) how to add your own cmd scripts. + +## Proxmark3 client files: Lua libraries and scripts + +Lua libraries and scripts used by the client will be copied to + +``` +/usr/local/share/proxmark3/lualibs +/usr/local/share/proxmark3/luascripts +``` + +`lualibs` contains the supporting lua libraries used for lua scripts. Basically reused functions in a lua file like converting string to hex etc. + +See [here](#proxmark3-client-files-and-traces) how to add your own Lua scripts. + +## Proxmark3 client files: various resources + +Various resources used by the client will be copied to + +``` +/usr/local/share/proxmark3/resources +``` + +It comprises the needed files for commands like hardnested, fido, EMV, iClass. + +See [here](#proxmark3-client-files-and-traces) how to add your own resources. + +## Documentation + +Documentation will be copied to + +``` +/usr/local/share/doc/proxmark3 +``` + +# User files + +The client will make use of a personal directory `~/.proxmark3` (or more precisely `$HOME/.proxmark3`) + +## .history / log files + +We have now a rolling log file, created new per day. All these logfiles and the history file are now located at + +``` +~/.proxmark3/history.txt +~/.proxmark3/log_YYYYMMDD.txt +``` + +## Proxmark3 client files and traces + +If you wants to add scripts, dictionaries or other resources, you can use the same structure as the installed directory structure and add your own files there, e.g. + +``` +~/.proxmark3/cmdscripts/mycmdscript.cmd +~/.proxmark3/dictionaries/mydict.dic +~/.proxmark3/luascripts/myluascript.lua +~/.proxmark3/resources/oids.json +~/.proxmark3/traces/mylftrace.pm3 +``` + +If you add a file with the same name as the file provided with the Proxmark3 installation, it will take precedence. + +See also [Scripts](#scripts) on how to write your own scripts. + +# Searching files + +With the directory structure explained above, the client applies some heuristics to find its files or the files you specified in command line. + +## TL;DR + +It adds the expected suffix if you didn't provide it yet, then it looks (by order of precedence): + +1. in the current directory, or in the path if you provided also a path, so it works with autocompletion +2. in the `~/.proxmark3` directory structure as seen above, so it works with your stuffs +3. in the repo directory structure, so it works as usual if used from the Git repo +4. in the installed directory structure, so it works when installed + +## Gory details + +The client is using _searchFile_ (in _client/fileutils.c_) when calling a Proxmark3 command with a filename or when the client needs to find its files. +_searchFile_ takes as argument a relative path *pm3dir*, a file to search and possibly a *suffix*. + +So for example when using _searchFile_ over a filename supposed to be a dictionary file, it's called with *pm3dir=dictionaries/* and *suffix=.dic*. +When a user provides a filename (including possibly a path), _searchFile_ will search different locations and return as soon as a file is found: + +* Add the suffix if the suffix is not yet present, so: *foo* -> *foo.dic* and *foo.dic* -> *foo.dic* +* If the filename is an absolute path (*/tmp/foo.dic*), take it as it is, try to access the file and return. +* If the filename is an explicit relative path (*./foo.dic*), take it as it is, try to access the file from the current directory and return. +* Try to find the filename as relative path (*foo.dic* -> *./foo.dic*), so filenames provided by CLI autocompletion work as expected. +* Try to find the filename in the *pm3dir* relative to the user directory *$HOME/.proxmark3* (*foo.dic* -> *~/.proxmark3/dictionaries/foo.dic*) +* Try to find the filename in the *pm3dir* relative to where the client binary is when in the repo configuration (*foo.dic* -> *$(path_to_dir_of_proxmark3_bin)/dictionaries/foo.dic*), so when the client is executed from a repo workdir, filenames are searched in the expected location. +* Try to find the filename in the *pm3dir* relative to where the client binary is when in the installed configuration (*foo.dic* -> *$(path_to_dir_of_proxmark3_bin)/../share/proxmark3/dictionaries/foo.dic* which resolves to e.g. */usr/share/proxmark3/dictionaries/foo.dic* or */usr/local/share/proxmark3/dictionaries/foo.dic*), so when the client is executed from a repo workdir, filenames are searched in the expected location. + +# Scripts + +You can provide your own lua or cmd scripts. +Look at existing scripts for ideas how to create your own scripts. + +### Proxmark command script (.cmd) +For cmd scripts, the command line scripts, the client can run a text file containing Proxmark3 commands. + +A samplefile could be like this. +``` +$> cat myscript.cmd + +rem running some HF-based info commands +hf 14a info +hf mfu info +rem done +``` + +You call it with: + +`$> pm3 -s myscript.cmd` + +The client will execute each one of the commands in order and then exit. There is also a possibility to remain in the client afterwards with the -i parameter: + +`$> pm3 -s myscript.cmd -i` + +You can place it in `~/.proxmark3/cmdscripts/` and it will be found automatically. + +You can skip the script file extension, it works equally well with. + +`pm3 -s myscript` + + +### Shebangs (on *nix) + +You can also use the magic of shebangs to make an executable script, e.g. taking the example above, we can write: + +``` +$> cat myscript.cmd + +#!/usr/bin/env -S pm3 -s +hf 14a info +hf mfu info + +$> chmod +x myscript.cmd +$> ./myscript.cmd +``` + +And it will be executed invoking the `pm3` script. + +Use the following if your script is intended to work offline. + +``` +#!/usr/bin/env -S proxmark3 -s +``` + +Beware the shebang trick is not available on all the platforms, it requires your `env` to accept the `-S` switch. diff --git a/doc/termux_notes.md b/doc/termux_notes.md index f568c6f16..d86ec7f08 100644 --- a/doc/termux_notes.md +++ b/doc/termux_notes.md @@ -14,35 +14,30 @@ From official Proxmark3 wiki: > In any case, you would need a USB-C to A or USB-OTG cable to connect Proxmark3 to your Android device. Some Android devices may not supply enough power (USB-OTG = 100mA), and need a USB Y-cable and external battery, otherwise they will get strange failures. ref : https://github.com/Proxmark/proxmark3/wiki/android -## Tested setup +## Tested setups + - OnePlus 5 (arm64, USB-C) -- [OmniROM (Android 9)](https://www.omnirom.org/) -- [OmniROM kernel](https://www.omnirom.org/) -- [Magisk 19.3](https://github.com/topjohnwu/Magisk/) + + - [OmniROM (Android 9)](https://www.omnirom.org/) + - [OmniROM kernel](https://www.omnirom.org/) + - [Magisk 19.3](https://github.com/topjohnwu/Magisk/) + +- Nexus 5X (arm64, USB-C) + + - [LineageOS (Android 8.1)](https://download.lineageos.org/) + - [LineageOS kernel](https://download.lineageos.org/) + - [Magisk 19.3](https://github.com/topjohnwu/Magisk/) ## Setup -### Getting ncurses with termcap -You need `termcap` to build the Proxmark3 client. Unfortunately, the prebuilt `ncurses` package does not include it. Since [this PR](https://github.com/termux/termux-packages/pull/2131) hasn't been merged yet, you will have to build `ncurses` yourself - -1. Clone the [termux-packages](https://github.com/termux/termux-packages) repo -2. Apply [the PR](https://github.com/termux/termux-packages/pull/2131) -3. Build `ncurses`. Refer to the [build docs](https://github.com/termux/termux-packages/blob/master/docs/BUILD_ENVIRONMENT.md) for more information. The easiest way is to use Docker: - - `./scripts/run-docker.sh` - - `./build-package.sh ncurses` - - the built packages will be under the `debs` directory -4. Copy `ncurses_6.1.x-x_aarch64.deb` to your phone's `/sdcard` ### Setting up Termux 1. Install [Termux](https://play.google.com/store/apps/details?id=com.termux) and start it 2. Run the following commands: ``` -pkg install make, clang, clang++, readline-dev, libclang-dev, libc++, git, tsu -termux-setup-storage -dpkg -i /sdcard/ncurses_6.1.x-x_aarch64.deb +pkg install make clang clang++ readline libc++ git tsu git clone https://github.com/RfidResearchGroup/proxmark3.git ``` ### Building Proxmark3 client -1. Edit `proxmark3/client/Makefile` and append `-fPIC` to the `CFLAGS` variable (line 30) -2. `make clean && make client` +1. `make clean && make client` ### USB_ACM You need the `USB_ACM` driver enabled and working to communicate with the Proxmark3. To see if it's working, run `tsudo ls /dev/tty*` and it should list `/dev/ttyACM0` (or similar). If you see this, congratulations, skip this step! diff --git a/doc/trace_wireshark_notes.md b/doc/trace_wireshark_notes.md new file mode 100644 index 000000000..50dd9d082 --- /dev/null +++ b/doc/trace_wireshark_notes.md @@ -0,0 +1,60 @@ +# Trace command notes + +The `trace` command lists the data exchange by the proxmark3 and a tag or a reader in human readable form. + +With `trace list` a table is shown which gives timing information, the src of the data bytes, the transmitted/received bytes itself, a check if the CRC was correct and some decoding of the command. + +To get a more detailed explanation of the transmitted data for ISO14443A traces the output can be converted to a pcapng file to read it with [Wireshark](https://www.wireshark.org/). + +To do so + +* use `trace list 14a x` +* copy the output (starting with the timestamp) into a textfile +* run `text2pcap -t "%S." -l 264 -n ` +* now open your pcapng file in Wireshark or read it with the CLI version `tshark` + +An example frame + +with `trace list 14a`: + +``` +19072 | 29536 | Rdr |93 70 88 04 cf ff bc 7f bb | ok | SELECT_UID +``` + +the same data with `tshark -r foo.pcapng -V -x`: + +``` +Frame 5: 13 bytes on wire (104 bits), 13 bytes captured (104 bits) on interface 0 + Interface id: 0 (unknown) + Interface name: unknown + Encapsulation type: ISO 14443 contactless smartcard standards (177) + Arrival Time: Aug 17, 2019 23:17:00.000002606 CEST + [Time shift for this packet: 0.000000000 seconds] + Epoch Time: 1566076620.000002606 seconds + [Time delta from previous captured frame: 0.000000840 seconds] + [Time delta from previous displayed frame: 0.000000840 seconds] + [Time since reference or first frame: 0.000001907 seconds] + Frame Number: 5 + Frame Length: 13 bytes (104 bits) + Capture Length: 13 bytes (104 bits) + [Frame is marked: False] + [Frame is ignored: False] + [Protocols in frame: iso14443] +ISO 14443 + Pseudo header + Version: 0x00 + Event: Data transfer PCD -> PICC (0xfe) + Length field: 9 + Message: Select + SEL: 0x93 + NVB: 0x70 + CT: 0x88 + UID_CLn: 04cfff + BCC: 0xbc + CRC: 0xbb7f [correct] + [CRC Status: Good] + +0000 00 fe 00 09 93 70 88 04 cf ff bc 7f bb .....p....... +``` + +If the Wireshark ISO14443a dissector is missing some commands or needs some other rework please [file a bug](https://bugs.wireshark.org/bugzilla/). diff --git a/flash-all.sh b/flash-all.sh deleted file mode 100755 index d4fcdc975..000000000 --- a/flash-all.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -PM3PATH=$(dirname "$0") -cd "$PM3PATH" || exit 1 -. proxmark3.sh diff --git a/flash-bootrom.sh b/flash-bootrom.sh deleted file mode 100755 index d4fcdc975..000000000 --- a/flash-bootrom.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -PM3PATH=$(dirname "$0") -cd "$PM3PATH" || exit 1 -. proxmark3.sh diff --git a/flash-fullimage.sh b/flash-fullimage.sh deleted file mode 100755 index d4fcdc975..000000000 --- a/flash-fullimage.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -PM3PATH=$(dirname "$0") -cd "$PM3PATH" || exit 1 -. proxmark3.sh diff --git a/fpga/Makefile b/fpga/Makefile index ba9fec28b..06cdec2ee 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -1,44 +1,41 @@ -include ../common/Makefile.common # for $(DETECTED_OS) - all: fpga_lf.bit fpga_hf.bit clean: - $(Q)$(DELETE) *.bgn *.drc *.ncd *.ngd *_par.xrpt *-placed.* *-placed_pad.* *_usage.xml xst_hf.srp xst_lf.srp - $(Q)$(DELETE) *.map *.ngc *.xrpt *.pcf *.rbt *_auto_* *.bld *.mrp *.ngm *.unroutes *_summary.xml netlist.lst xst + $(Q)$(RM) *.bgn *.drc *.ncd *.ngd *_par.xrpt *-placed.* *-placed_pad.* *_usage.xml xst_hf.srp xst_lf.srp + $(Q)$(RM) *.map *.ngc *.xrpt *.pcf *.rbt *_auto_* *.bld *.mrp *.ngm *.unroutes *_summary.xml netlist.lst xst fpga_hf.ngc: fpga_hf.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_read_tx.v hi_read_rx_xcorr.v hi_iso14443a.v hi_sniffer.v hi_flite.v - $(Q)$(DELETE) $@ + $(Q)$(RM) $@ $(info [-] XST $@) $(Q)$(XILINX_TOOLS_PREFIX)xst -ifn xst_hf.scr fpga_lf.ngc: fpga_lf.v fpga.ucf xst_lf.scr util.v clk_divider.v lo_edge_detect.v lo_read.v lo_passthru.v lp20khz_1MSa_iir_filter.v min_max_tracker.v lf_edge_detect.v - $(Q)$(DELETE) $@ + $(Q)$(RM) $@ $(info [-] XST $@) $(Q)$(XILINX_TOOLS_PREFIX)xst -ifn xst_lf.scr %.ngd: %.ngc - $(Q)$(DELETE) $@ + $(Q)$(RM) $@ $(info [-] NGD $@) $(Q)$(XILINX_TOOLS_PREFIX)ngdbuild -aul -p xc2s30-5-vq100 -nt timestamp -uc fpga.ucf $< $@ %.ncd: %.ngd - $(Q)$(DELETE) $@ + $(Q)$(RM) $@ $(info [-] MAP $@) $(Q)$(XILINX_TOOLS_PREFIX)map -p xc2s30-5-vq100 $< %-placed.ncd: %.ncd - $(Q)$(DELETE) $@ + $(Q)$(RM) $@ $(info [-] PAR $@) $(Q)$(XILINX_TOOLS_PREFIX)par $< $@ %.bit: %-placed.ncd - $(Q)$(DELETE) $@ $*.drc $*.rbt + $(Q)$(RM) $@ $*.drc $*.rbt $(info [=] BITGEN $@) $(Q)$(XILINX_TOOLS_PREFIX)bitgen $< $@ .PHONY: all clean help help: - @echo Multi-OS Makefile, you are running on $(DETECTED_OS) @echo Possible targets: @echo + all - Make fpga.bit, the FPGA bitstream @echo + clean - Clean intermediate files, does not clean fpga.bit diff --git a/fpga/clk_divider.v b/fpga/clk_divider.v index 882af5cc8..9a57879b0 100644 --- a/fpga/clk_divider.v +++ b/fpga/clk_divider.v @@ -7,19 +7,19 @@ //----------------------------------------------------------------------------- module clk_divider(input clk, input [7:0] divisor, output [7:0] div_cnt, output div_clk); - reg [7:0] div_cnt_ = 0; - reg div_clk_; - assign div_cnt = div_cnt_; - assign div_clk = div_clk_; + reg [7:0] div_cnt_ = 0; + reg div_clk_; + assign div_cnt = div_cnt_; + assign div_clk = div_clk_; - always @(posedge clk) - begin - if(div_cnt == divisor) begin - div_cnt_ <= 8'd0; - div_clk_ = !div_clk_; - end else - div_cnt_ <= div_cnt_ + 1; - end + always @(posedge clk) + begin + if(div_cnt == divisor) begin + div_cnt_ <= 8'd0; + div_clk_ = !div_clk_; + end else + div_cnt_ <= div_cnt_ + 1; + end endmodule diff --git a/fpga/fpga_hf.v b/fpga/fpga_hf.v index 7593d8aeb..0dc26b6ec 100644 --- a/fpga/fpga_hf.v +++ b/fpga/fpga_hf.v @@ -22,14 +22,14 @@ `include "hi_flite.v" module fpga_hf( - input spck, output miso, input mosi, input ncs, - input pck0, input ck_1356meg, input ck_1356megb, - output pwr_lo, output pwr_hi, - output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, - input [7:0] adc_d, output adc_clk, output adc_noe, - output ssp_frame, output ssp_din, input ssp_dout, output ssp_clk, - input cross_hi, input cross_lo, - output dbg + input spck, output miso, input mosi, input ncs, + input pck0, input ck_1356meg, input ck_1356megb, + output pwr_lo, output pwr_hi, + output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, + input [7:0] adc_d, output adc_clk, output adc_noe, + output ssp_frame, output ssp_din, input ssp_dout, output ssp_clk, + input cross_hi, input cross_lo, + output dbg ); //----------------------------------------------------------------------------- @@ -47,18 +47,18 @@ reg [7:0] conf_word; // glitching, or else we will glitch the transmitted carrier. always @(posedge ncs) begin - case(shift_reg[15:12]) - 4'b0001: conf_word <= shift_reg[7:0]; // FPGA_CMD_SET_CONFREG - endcase + case(shift_reg[15:12]) + 4'b0001: conf_word <= shift_reg[7:0]; // FPGA_CMD_SET_CONFREG + endcase end always @(posedge spck) begin - if(~ncs) - begin - shift_reg[15:1] <= shift_reg[14:0]; - shift_reg[0] <= mosi; - end + if(~ncs) + begin + shift_reg[15:1] <= shift_reg[14:0]; + shift_reg[0] <= mosi; + end end wire [2:0] major_mode; @@ -87,43 +87,43 @@ wire [2:0] hi_simulate_mod_type = conf_word[2:0]; //----------------------------------------------------------------------------- hi_read_tx ht( - pck0, ck_1356meg, ck_1356megb, - ht_pwr_lo, ht_pwr_hi, ht_pwr_oe1, ht_pwr_oe2, ht_pwr_oe3, ht_pwr_oe4, - adc_d, ht_adc_clk, - ht_ssp_frame, ht_ssp_din, ssp_dout, ht_ssp_clk, - cross_hi, cross_lo, - ht_dbg, - hi_read_tx_shallow_modulation + pck0, ck_1356meg, ck_1356megb, + ht_pwr_lo, ht_pwr_hi, ht_pwr_oe1, ht_pwr_oe2, ht_pwr_oe3, ht_pwr_oe4, + adc_d, ht_adc_clk, + ht_ssp_frame, ht_ssp_din, ssp_dout, ht_ssp_clk, + cross_hi, cross_lo, + ht_dbg, + hi_read_tx_shallow_modulation ); hi_read_rx_xcorr hrxc( - pck0, ck_1356meg, ck_1356megb, - hrxc_pwr_lo, hrxc_pwr_hi, hrxc_pwr_oe1, hrxc_pwr_oe2, hrxc_pwr_oe3, hrxc_pwr_oe4, - adc_d, hrxc_adc_clk, - hrxc_ssp_frame, hrxc_ssp_din, ssp_dout, hrxc_ssp_clk, - cross_hi, cross_lo, - hrxc_dbg, - hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter + pck0, ck_1356meg, ck_1356megb, + hrxc_pwr_lo, hrxc_pwr_hi, hrxc_pwr_oe1, hrxc_pwr_oe2, hrxc_pwr_oe3, hrxc_pwr_oe4, + adc_d, hrxc_adc_clk, + hrxc_ssp_frame, hrxc_ssp_din, ssp_dout, hrxc_ssp_clk, + cross_hi, cross_lo, + hrxc_dbg, + hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter ); hi_simulate hs( - pck0, ck_1356meg, ck_1356megb, - hs_pwr_lo, hs_pwr_hi, hs_pwr_oe1, hs_pwr_oe2, hs_pwr_oe3, hs_pwr_oe4, - adc_d, hs_adc_clk, - hs_ssp_frame, hs_ssp_din, ssp_dout, hs_ssp_clk, - cross_hi, cross_lo, - hs_dbg, - hi_simulate_mod_type + pck0, ck_1356meg, ck_1356megb, + hs_pwr_lo, hs_pwr_hi, hs_pwr_oe1, hs_pwr_oe2, hs_pwr_oe3, hs_pwr_oe4, + adc_d, hs_adc_clk, + hs_ssp_frame, hs_ssp_din, ssp_dout, hs_ssp_clk, + cross_hi, cross_lo, + hs_dbg, + hi_simulate_mod_type ); hi_iso14443a hisn( - pck0, ck_1356meg, ck_1356megb, - hisn_pwr_lo, hisn_pwr_hi, hisn_pwr_oe1, hisn_pwr_oe2, hisn_pwr_oe3, hisn_pwr_oe4, - adc_d, hisn_adc_clk, - hisn_ssp_frame, hisn_ssp_din, ssp_dout, hisn_ssp_clk, - cross_hi, cross_lo, - hisn_dbg, - hi_simulate_mod_type + pck0, ck_1356meg, ck_1356megb, + hisn_pwr_lo, hisn_pwr_hi, hisn_pwr_oe1, hisn_pwr_oe2, hisn_pwr_oe3, hisn_pwr_oe4, + adc_d, hisn_adc_clk, + hisn_ssp_frame, hisn_ssp_din, ssp_dout, hisn_ssp_clk, + cross_hi, cross_lo, + hisn_dbg, + hi_simulate_mod_type ); hi_sniffer he( @@ -157,17 +157,17 @@ hi_flite hfl( // 110 -- none // 111 -- everything off -mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, hfl_ssp_clk, 1'b0, 1'b0); -mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, he_ssp_din, hfl_ssp_din, 1'b0, 1'b0); -mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, he_ssp_frame, hfl_ssp_frame, 1'b0, 1'b0); -mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, he_pwr_oe1, hfl_pwr_oe1, 1'b0, 1'b0); -mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, he_pwr_oe2, hfl_pwr_oe2, 1'b0, 1'b0); -mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, he_pwr_oe3, hfl_pwr_oe3, 1'b0, 1'b0); -mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, he_pwr_oe4, hfl_pwr_oe4, 1'b0, 1'b0); -mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, he_pwr_lo, hfl_pwr_lo, 1'b0, 1'b0); -mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, he_pwr_hi, hfl_pwr_hi, 1'b0, 1'b0); -mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, he_adc_clk, hfl_adc_clk, 1'b0, 1'b0); -mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, he_dbg, hfl_dbg, 1'b0, 1'b0); +mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, hfl_ssp_clk, 1'b0, 1'b0); +mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, he_ssp_din, hfl_ssp_din, 1'b0, 1'b0); +mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, he_ssp_frame, hfl_ssp_frame, 1'b0, 1'b0); +mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, he_pwr_oe1, hfl_pwr_oe1, 1'b0, 1'b0); +mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, he_pwr_oe2, hfl_pwr_oe2, 1'b0, 1'b0); +mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, he_pwr_oe3, hfl_pwr_oe3, 1'b0, 1'b0); +mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, he_pwr_oe4, hfl_pwr_oe4, 1'b0, 1'b0); +mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, he_pwr_lo, hfl_pwr_lo, 1'b0, 1'b0); +mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, he_pwr_hi, hfl_pwr_hi, 1'b0, 1'b0); +mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, he_adc_clk, hfl_adc_clk, 1'b0, 1'b0); +mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, he_dbg, hfl_dbg, 1'b0, 1'b0); // In all modes, let the ADC's outputs be enabled. assign adc_noe = 1'b0; diff --git a/fpga/fpga_lf.bit b/fpga/fpga_lf.bit index a668017bf..f694ad4cf 100644 Binary files a/fpga/fpga_lf.bit and b/fpga/fpga_lf.bit differ diff --git a/fpga/fpga_lf.v b/fpga/fpga_lf.v index 2c0a498d0..88b22b7ca 100644 --- a/fpga/fpga_lf.v +++ b/fpga/fpga_lf.v @@ -6,18 +6,19 @@ `include "lo_read.v" `include "lo_passthru.v" `include "lo_edge_detect.v" +`include "lo_adc.v" `include "util.v" `include "clk_divider.v" module fpga_lf( - input spck, output miso, input mosi, input ncs, - input pck0, input ck_1356meg, input ck_1356megb, - output pwr_lo, output pwr_hi, - output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, - input [7:0] adc_d, output adc_clk, output adc_noe, - output ssp_frame, output ssp_din, input ssp_dout, output ssp_clk, - input cross_hi, input cross_lo, - output dbg + input spck, output miso, input mosi, input ncs, + input pck0, input ck_1356meg, input ck_1356megb, + output pwr_lo, output pwr_hi, + output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, + input [7:0] adc_d, output adc_clk, output adc_noe, + output ssp_frame, output ssp_din, input ssp_dout, output ssp_clk, + input cross_hi, input cross_lo, + output dbg ); //----------------------------------------------------------------------------- @@ -34,26 +35,26 @@ reg [7:0] user_byte1; always @(posedge ncs) begin - case(shift_reg[15:12]) - 4'b0001: - begin - conf_word <= shift_reg[7:0]; - if (shift_reg[7:0] == 8'b00000001) begin // LF edge detect - user_byte1 <= 127; // default threshold - end - end - 4'b0010: divisor <= shift_reg[7:0]; // FPGA_CMD_SET_DIVISOR - 4'b0011: user_byte1 <= shift_reg[7:0]; // FPGA_CMD_SET_USER_BYTE1 - endcase + case(shift_reg[15:12]) + 4'b0001: + begin + conf_word <= shift_reg[7:0]; + if (shift_reg[7:0] == 8'b00000001) begin // LF edge detect + user_byte1 <= 127; // default threshold + end + end + 4'b0010: divisor <= shift_reg[7:0]; // FPGA_CMD_SET_DIVISOR + 4'b0011: user_byte1 <= shift_reg[7:0]; // FPGA_CMD_SET_USER_BYTE1 + endcase end always @(posedge spck) begin - if(~ncs) - begin - shift_reg[15:1] <= shift_reg[14:0]; - shift_reg[0] <= mosi; - end + if(~ncs) + begin + shift_reg[15:1] <= shift_reg[14:0]; + shift_reg[0] <= mosi; + end end wire [2:0] major_mode = conf_word[7:5]; @@ -73,51 +74,62 @@ wire pck_divclk; clk_divider div_clk(pck0, divisor, pck_cnt, pck_divclk); lo_read lr( - pck0, pck_cnt, pck_divclk, - lr_pwr_lo, lr_pwr_hi, lr_pwr_oe1, lr_pwr_oe2, lr_pwr_oe3, lr_pwr_oe4, - adc_d, lr_adc_clk, - lr_ssp_frame, lr_ssp_din, lr_ssp_clk, - lr_dbg, lf_field + pck0, pck_cnt, pck_divclk, + lr_pwr_lo, lr_pwr_hi, lr_pwr_oe1, lr_pwr_oe2, lr_pwr_oe3, lr_pwr_oe4, + adc_d, lr_adc_clk, + lr_ssp_frame, lr_ssp_din, lr_ssp_clk, + lr_dbg, lf_field ); lo_passthru lp( - pck_divclk, - lp_pwr_lo, lp_pwr_hi, lp_pwr_oe1, lp_pwr_oe2, lp_pwr_oe3, lp_pwr_oe4, - lp_adc_clk, - lp_ssp_din, ssp_dout, - cross_lo, - lp_dbg + pck_divclk, + lp_pwr_lo, lp_pwr_hi, lp_pwr_oe1, lp_pwr_oe2, lp_pwr_oe3, lp_pwr_oe4, + lp_adc_clk, + lp_ssp_din, ssp_dout, + cross_lo, + lp_dbg ); lo_edge_detect le( - pck0, pck_divclk, - le_pwr_lo, le_pwr_hi, le_pwr_oe1, le_pwr_oe2, le_pwr_oe3, le_pwr_oe4, - adc_d, le_adc_clk, - le_ssp_frame, ssp_dout, le_ssp_clk, - cross_lo, - le_dbg, - lf_field, - lf_ed_toggle_mode, lf_ed_threshold + pck0, pck_divclk, + le_pwr_lo, le_pwr_hi, le_pwr_oe1, le_pwr_oe2, le_pwr_oe3, le_pwr_oe4, + adc_d, le_adc_clk, + le_ssp_frame, ssp_dout, le_ssp_clk, + cross_lo, + le_dbg, + lf_field, + lf_ed_toggle_mode, lf_ed_threshold +); + +lo_adc la( + pck0, + la_pwr_lo, la_pwr_hi, la_pwr_oe1, la_pwr_oe2, la_pwr_oe3, la_pwr_oe4, + adc_d, la_adc_clk, + la_ssp_frame, la_ssp_din, ssp_dout, la_ssp_clk, + cross_hi, cross_lo, + la_dbg, divisor, + lo_is_125khz, lf_field ); // Major modes: // 000 -- LF reader (generic) // 001 -- LF edge detect (generic) // 010 -- LF passthrough -// 110 -- FPGA_MAJOR_MODE_OFF_LF (rdv40 specific) +// 011 -- LF ADC (read/write) +// 110 -- FPGA_MAJOR_MODE_OFF_LF (rdv40 specific) // 111 -- FPGA_MAJOR_MODE_OFF -// 000 001 010 011 100 101 110 111 -mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, le_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_ssp_din (major_mode, ssp_din, lr_ssp_din, 1'b0, lp_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_ssp_frame (major_mode, ssp_frame, lr_ssp_frame, le_ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe1 (major_mode, pwr_oe1, lr_pwr_oe1, le_pwr_oe1, lp_pwr_oe1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe2 (major_mode, pwr_oe2, lr_pwr_oe2, le_pwr_oe2, lp_pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe3 (major_mode, pwr_oe3, lr_pwr_oe3, le_pwr_oe3, lp_pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe4 (major_mode, pwr_oe4, lr_pwr_oe4, le_pwr_oe4, lp_pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_lo (major_mode, pwr_lo, lr_pwr_lo, le_pwr_lo, lp_pwr_lo, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0); -mux8 mux_pwr_hi (major_mode, pwr_hi, lr_pwr_hi, le_pwr_hi, lp_pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_adc_clk (major_mode, adc_clk, lr_adc_clk, le_adc_clk, lp_adc_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_dbg (major_mode, dbg, lr_dbg, le_dbg, lp_dbg, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); +// 000 001 010 011 100 101 110 111 +mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, le_ssp_clk, 1'b0, la_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_ssp_din (major_mode, ssp_din, lr_ssp_din, 1'b0, lp_ssp_din, la_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_ssp_frame (major_mode, ssp_frame, lr_ssp_frame, le_ssp_frame, 1'b0, la_ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe1 (major_mode, pwr_oe1, lr_pwr_oe1, le_pwr_oe1, lp_pwr_oe1, la_pwr_oe1, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe2 (major_mode, pwr_oe2, lr_pwr_oe2, le_pwr_oe2, lp_pwr_oe2, la_pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe3 (major_mode, pwr_oe3, lr_pwr_oe3, le_pwr_oe3, lp_pwr_oe3, la_pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe4 (major_mode, pwr_oe4, lr_pwr_oe4, le_pwr_oe4, lp_pwr_oe4, la_pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_lo (major_mode, pwr_lo, lr_pwr_lo, le_pwr_lo, lp_pwr_lo, la_pwr_lo, 1'b0, 1'b0, 1'b1, 1'b0); +mux8 mux_pwr_hi (major_mode, pwr_hi, lr_pwr_hi, le_pwr_hi, lp_pwr_hi, la_pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_adc_clk (major_mode, adc_clk, lr_adc_clk, le_adc_clk, lp_adc_clk, la_adc_clk, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_dbg (major_mode, dbg, lr_dbg, le_dbg, lp_dbg, la_dbg, 1'b0, 1'b0, 1'b0, 1'b0); // In all modes, let the ADC's outputs be enabled. assign adc_noe = 1'b0; diff --git a/fpga/hi_flite.v b/fpga/hi_flite.v index 86f03c3ab..18d3a46ac 100644 --- a/fpga/hi_flite.v +++ b/fpga/hi_flite.v @@ -1,9 +1,9 @@ //this code demodulates and modulates signal as described in ISO/IEC 18092. That includes packets used for Felica, NFC Tag 3, etc. (which do overlap) -//simple envelope following algorithm is used (modification of fail0verflow LF one) is used to combat some nasty aliasing effect with testing phone (envelope looked like sine wave) +//simple envelope following algorithm is used (modification of fail0verflow LF one) is used to combat some nasty aliasing effect with testing phone (envelope looked like sine wave) // only 212 kbps (fc/64) for now 414 is relatively straightforward... though for reader, the selection has to come from ARM -// modulation waits for -//market sprocket -doesn't really mean anything ;) +// modulation waits for +//market sprocket -doesn't really mean anything ;) //redefining mod_type: bits 210: bit 2 - reader drive/power on/off, bit 1 - speed bit, 0:212, 1 -424 bit 0: listen or modulate @@ -15,7 +15,7 @@ module hi_flite( cross_hi, cross_lo, dbg, mod_type // used - + ); input pck0, ck_1356meg, ck_1356megb; output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; @@ -33,7 +33,7 @@ wire speed= mod_type[1]; wire disabl= mod_type[0]; // Most off, oe4 for modulation; -// Trying reader emulation (would presumably just require switching power on, but I am not sure) +// Trying reader emulation (would presumably just require switching power on, but I am not sure) //;// 1'b0; assign pwr_lo = 1'b0; @@ -55,7 +55,7 @@ assign adc_clk = ck_1356meg; //minimum values and corresponding thresholds reg [8:0] curmin=`imin; -reg [8:0] curminthres=`ithrmin; +reg [8:0] curminthres=`ithrmin; reg [8:0] curmaxthres=`ithrmax; reg [8:0] curmax=`imax; @@ -103,37 +103,37 @@ always @(posedge adc_clk) ssp_cnt <= (ssp_cnt + 1); //maybe change it so that ARM sends preamble as well. -//then: ready bits sent to ARM, 8 bits sent from ARM (all ones), then preamble (all zeros, presumably) - which starts modulation - +//then: ready bits sent to ARM, 8 bits sent from ARM (all ones), then preamble (all zeros, presumably) - which starts modulation + always @(negedge adc_clk) begin //count fc/64 - transfer bits to ARM at the rate they are received if( ((~speed) && (ssp_cnt[5:0] == 6'b000000)) || (speed &&(ssp_cnt[4:0] == 5'b00000))) begin - ssp_clk <= 1'b1; + ssp_clk <= 1'b1; // if(mod_type[2]) // begin // ssp_din<=outp[0];//after_hysteresis; - - //outp<={1'b0,outp[7:1]}; + + //outp<={1'b0,outp[7:1]}; // end // else - ssp_din <= curbit; - + ssp_din <= curbit; + //sample ssp_dout - + end - if( ( (~speed) && (ssp_cnt[5:0] == 6'b100000)) ||(speed && ssp_cnt[4:0] == 5'b10000)) - ssp_clk <= 1'b0; + if( ( (~speed) && (ssp_cnt[5:0] == 6'b100000)) ||(speed && ssp_cnt[4:0] == 5'b10000)) + ssp_clk <= 1'b0; //create frame pulses. TBH, I still don't know what they do exactly, but they are crucial for ARM->FPGA transfer. If the frame is in the beginning of the byte, transfer slows to a crawl for some reason - // took me a day to figure THAT out. + // took me a day to figure THAT out. if(( (~speed) && (ssp_cnt[8:0] == 9'd31))||(speed && ssp_cnt[7:0] == 8'd15)) begin - ssp_frame <= 1'b1; + ssp_frame <= 1'b1; end if(( (~speed) && (ssp_cnt[8:0] == 9'b1011111))||(speed &&ssp_cnt[7:0] == 8'b101111) ) begin - ssp_frame <= 1'b0; + ssp_frame <= 1'b0; end end @@ -141,23 +141,23 @@ end //send current bit (detected in SNIFF mode or the one being modulated in MOD mode, 0 otherwise) -reg ssp_din;//= outp[0]; - - +reg ssp_din;//= outp[0]; + + //previous signal value, mostly to detect SYNC reg prv =1'b1; -reg[7:0] mid=8'd128; //for simple error correction in mod/demod detection, use maximum of modded/demodded in given interval. Maybe 1 bit is extra? but better safe than sorry. +reg[7:0] mid=8'd128; //for simple error correction in mod/demod detection, use maximum of modded/demodded in given interval. Maybe 1 bit is extra? but better safe than sorry. // set TAGSIM__MODULATE on ARM if we want to write... (frame would get lost if done mid-frame...) // start sending over 1s on ssp->arm when we start sending preamble -reg counting_desync=1'b0; // are we counting bits since last frame? -reg sending=1'b0; // are we actively modulating? -reg [11:0] bit_counts=12'd0;///for timeslots... only support ts=0 for now, at 212 speed -512 fullbits from end of frame. One hopes. might remove those? +reg counting_desync=1'b0; // are we counting bits since last frame? +reg sending=1'b0; // are we actively modulating? +reg [11:0] bit_counts=12'd0;///for timeslots... only support ts=0 for now, at 212 speed -512 fullbits from end of frame. One hopes. might remove those? //reg [2:0]old_mod; @@ -166,19 +166,19 @@ reg [11:0] bit_counts=12'd0;///for timeslots... only support ts=0 for now, at 21 //begin //if (mod_type[2]==1&&old_mod[2]==0) // bit_counts=0; -//old_mod=mod_type; +//old_mod=mod_type; //end //we need some way to flush bit_counts triggers on mod_type changes don't compile reg dlay; -always @(negedge adc_clk) //every data ping? +always @(negedge adc_clk) //every data ping? begin - //envelope follow code... - //////////// + //envelope follow code... + //////////// //move the counter to the outside... - // if (adc_d>=curminthres||try_sync) + // if (adc_d>=curminthres||try_sync) if(fccount==bitmlen) - begin + begin if((~try_sync)&&(adc_d768) // should be over ts0 now, without ARM interference... stop counting... - begin + begin bit_counts<=0; // counting_desync<=0; end @@ -199,11 +199,11 @@ begin if((power)) bit_counts<=0; else - bit_counts<=bit_counts+1; - // end + bit_counts<=bit_counts+1; + // end end else - begin + begin if((~try_sync)&&(adc_dcurmaxthres) //rising edge begin case (state) @@ -230,38 +230,38 @@ begin 2: begin if (adc_d>curmax) curmax <= adc_d; - end + end default: begin - end + end endcase after_hysteresis <=1'b1; if(try_sync) tsinceedge<=0; end else if (adc_d>1)+(curmin>>2)+(curmin>>4)+(curmax>>3)+(curmax>>4)); curmaxthres <= ( (curmax>>1)+(curmax>>2)+(curmax>>4)+(curmin>>3)+(curmin>>4)); curmin <=adc_d<`imin? adc_d :`imin; - state <=1; - end + state <=1; + end default: begin - end - endcase + end + endcase after_hysteresis <=0; - if (~try_sync ) //begin modulation, lower edge... + if (~try_sync ) //begin modulation, lower edge... begin try_sync <=1; //counting_desync<=1'b0; @@ -271,7 +271,7 @@ begin mid <=8'd127; tsinceedge<=0; prv <=1; - end + end else begin tsinceedge<=0; @@ -282,12 +282,12 @@ begin curminthres <= ( (curmin>>1)+(curmin>>2)+(curmin>>4)+(curmax>>3)+(curmax>>4)); curmaxthres <= ( (curmax>>1)+(curmax>>2)+(curmax>>4)+(curmin>>3)+(curmin>>4)); state <=0; - + if (try_sync ) begin if (tsinceedge>=(128)) begin - //we might need to start counting... assuming ARM wants to reply to the frame. + //we might need to start counting... assuming ARM wants to reply to the frame. // counting_desync<=1'b1; bit_counts<=1;// i think? 128 is about 2 bits passed... but 1 also works try_sync<=0; @@ -295,7 +295,7 @@ begin curmin <=`imin; //reset envelope curmax <=`imax; curminthres <=`ithrmin; - curmaxthres <=`ithrmax; + curmaxthres <=`ithrmax; prv <=1; tsinceedge <=0; after_hysteresis <=1'b1; @@ -305,33 +305,33 @@ begin else tsinceedge<=(tsinceedge+1); end - end - - - - + end + + + + if (try_sync && tsinceedge<128) begin //detect bits in their middle ssp sampling is in sync, so it would sample all bits in order if (fccount==bithalf) begin if ((~did_sync) && ((prv==1&&(mid>128))||(prv==0&&(mid<=128)))) - begin + begin //sync the Zero, and set curbit roperly did_sync <=1'b1; zero <= ~prv;// 1-prv curbit <=1; - end - else + end + else curbit <= (mid>128) ? (~zero):zero; - - prv <=(mid>128) ?1:0; - - if(adc_d>curmaxthres) + + prv <=(mid>128) ?1:0; + + if(adc_d>curmaxthres) mid <=8'd129; - else if (adc_d128)?1:0; + prv <=(mid>128)?1:0; mid <=128; end else begin // minimum-maximum calc - if(adc_d>curmaxthres) + if(adc_d>curmaxthres) mid <=mid+1; - else if (adc_d PM3: -// detecting and shaping the reader's signal. Reader will modulate the carrier by 100% (signal is either on or off). Use a +// detecting and shaping the reader's signal. Reader will modulate the carrier by 100% (signal is either on or off). Use a // hysteresis (Schmitt Trigger) to avoid false triggers during slowly increasing or decreasing carrier amplitudes reg after_hysteresis; reg [11:0] has_been_low_for; always @(negedge adc_clk) begin - if(adc_d >= 16) after_hysteresis <= 1'b1; // U >= 1,14V -> after_hysteresis = 1 - else if(adc_d < 8) after_hysteresis <= 1'b0; // U < 1,04V -> after_hysteresis = 0 - // Note: was >= 3,53V and <= 1,19V. The new trigger values allow more reliable detection of the first bit - // (it might not reach 3,53V due to the high time constant of the high pass filter in the analogue RF part). - // In addition, the new values are more in line with ISO14443-2: "The PICC shall detect the ”End of Pause” after the field exceeds - // 5% of H_INITIAL and before it exceeds 60% of H_INITIAL." Depending on the signal strength, 60% might well be less than 3,53V. - - - // detecting a loss of reader's field (adc_d < 192 for 4096 clock cycles). If this is the case, - // set the detected reader signal (after_hysteresis) to '1' (unmodulated) - if(adc_d >= 192) + if(adc_d >= 16) after_hysteresis <= 1'b1; // U >= 1,14V -> after_hysteresis = 1 + else if(adc_d < 8) after_hysteresis <= 1'b0; // U < 1,04V -> after_hysteresis = 0 + // Note: was >= 3,53V and <= 1,19V. The new trigger values allow more reliable detection of the first bit + // (it might not reach 3,53V due to the high time constant of the high pass filter in the analogue RF part). + // In addition, the new values are more in line with ISO14443-2: "The PICC shall detect the ”End of Pause” after the field exceeds + // 5% of H_INITIAL and before it exceeds 60% of H_INITIAL." Depending on the signal strength, 60% might well be less than 3,53V. + + + // detecting a loss of reader's field (adc_d < 192 for 4096 clock cycles). If this is the case, + // set the detected reader signal (after_hysteresis) to '1' (unmodulated) + if(adc_d >= 192) begin has_been_low_for <= 12'd0; end @@ -65,43 +65,43 @@ begin after_hysteresis <= 1'b1; end else - begin + begin has_been_low_for <= has_been_low_for + 1; - end + end end - + end //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Reader -> PM3 -// detect when a reader is active (modulating). We assume that the reader is active, if we see the carrier off for at least 8 -// carrier cycles. We assume that the reader is inactive, if the carrier stayed high for at least 256 carrier cycles. +// detect when a reader is active (modulating). We assume that the reader is active, if we see the carrier off for at least 8 +// carrier cycles. We assume that the reader is inactive, if the carrier stayed high for at least 256 carrier cycles. reg deep_modulation; reg [2:0] deep_counter; reg [8:0] saw_deep_modulation; always @(negedge adc_clk) begin - if(~(| adc_d[7:0])) // if adc_d == 0 (U <= 0,94V) - begin - if(deep_counter == 3'd7) // adc_d == 0 for 8 adc_clk ticks -> deep_modulation (by reader) - begin - deep_modulation <= 1'b1; - saw_deep_modulation <= 8'd0; - end - else - deep_counter <= deep_counter + 1; - end - else - begin - deep_counter <= 3'd0; - if(saw_deep_modulation == 8'd255) // adc_d != 0 for 256 adc_clk ticks -> deep_modulation is over, probably waiting for tag's response - deep_modulation <= 1'b0; - else - saw_deep_modulation <= saw_deep_modulation + 1; - end + if(~(| adc_d[7:0])) // if adc_d == 0 (U <= 0,94V) + begin + if(deep_counter == 3'd7) // adc_d == 0 for 8 adc_clk ticks -> deep_modulation (by reader) + begin + deep_modulation <= 1'b1; + saw_deep_modulation <= 8'd0; + end + else + deep_counter <= deep_counter + 1; + end + else + begin + deep_counter <= 3'd0; + if(saw_deep_modulation == 8'd255) // adc_d != 0 for 256 adc_clk ticks -> deep_modulation is over, probably waiting for tag's response + deep_modulation <= 1'b0; + else + saw_deep_modulation <= saw_deep_modulation + 1; + end end @@ -115,16 +115,16 @@ reg [7:0] input_prev_4, input_prev_3, input_prev_2, input_prev_1; always @(negedge adc_clk) begin - input_prev_4 <= input_prev_3; - input_prev_3 <= input_prev_2; - input_prev_2 <= input_prev_1; - input_prev_1 <= adc_d; -end + input_prev_4 <= input_prev_3; + input_prev_3 <= input_prev_2; + input_prev_2 <= input_prev_1; + input_prev_1 <= adc_d; +end // adc_d_filtered = 2*input_prev4 + 1*input_prev3 + 0*input_prev2 - 1*input_prev1 - 2*input -// = (2*input_prev4 + input_prev3) - (2*input + input_prev1) +// = (2*input_prev4 + input_prev3) - (2*input + input_prev1) wire [8:0] input_prev_4_times_2 = input_prev_4 << 1; -wire [8:0] adc_d_times_2 = adc_d << 1; +wire [8:0] adc_d_times_2 = adc_d << 1; wire [9:0] tmp1 = input_prev_4_times_2 + input_prev_3; wire [9:0] tmp2 = adc_d_times_2 + input_prev_1; @@ -133,49 +133,49 @@ wire [9:0] tmp2 = adc_d_times_2 + input_prev_1; wire signed [10:0] adc_d_filtered = {1'b0, tmp1} - {1'b0, tmp2}; - + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// internal FPGA timing. Maximum required period is 128 carrier clock cycles for a full 8 Bit transfer to ARM. (i.e. we need a +// internal FPGA timing. Maximum required period is 128 carrier clock cycles for a full 8 Bit transfer to ARM. (i.e. we need a // 7 bit counter). Adjust its frequency to external reader's clock when simulating a tag or sniffing. -reg pre_after_hysteresis; +reg pre_after_hysteresis; reg [3:0] reader_falling_edge_time; reg [6:0] negedge_cnt; always @(negedge adc_clk) begin - // detect a reader signal's falling edge and remember its timing: - pre_after_hysteresis <= after_hysteresis; - if (pre_after_hysteresis && ~after_hysteresis) - begin - reader_falling_edge_time[3:0] <= negedge_cnt[3:0]; - end + // detect a reader signal's falling edge and remember its timing: + pre_after_hysteresis <= after_hysteresis; + if (pre_after_hysteresis && ~after_hysteresis) + begin + reader_falling_edge_time[3:0] <= negedge_cnt[3:0]; + end - // adjust internal timer counter if necessary: - if (negedge_cnt[3:0] == 4'd13 && (mod_type == `SNIFFER || mod_type == `TAGSIM_LISTEN) && deep_modulation) - begin - if (reader_falling_edge_time == 4'd1) // reader signal changes right after sampling. Better sample earlier next time. - begin - negedge_cnt <= negedge_cnt + 2; // time warp - end - else if (reader_falling_edge_time == 4'd0) // reader signal changes right before sampling. Better sample later next time. - begin - negedge_cnt <= negedge_cnt; // freeze time - end - else - begin - negedge_cnt <= negedge_cnt + 1; // Continue as usual - end - reader_falling_edge_time[3:0] <= 4'd8; // adjust only once per detected edge - end - else if (negedge_cnt == 7'd127) // normal operation: count from 0 to 127 - begin - negedge_cnt <= 0; - end - else - begin - negedge_cnt <= negedge_cnt + 1; - end -end + // adjust internal timer counter if necessary: + if (negedge_cnt[3:0] == 4'd13 && (mod_type == `SNIFFER || mod_type == `TAGSIM_LISTEN) && deep_modulation) + begin + if (reader_falling_edge_time == 4'd1) // reader signal changes right after sampling. Better sample earlier next time. + begin + negedge_cnt <= negedge_cnt + 2; // time warp + end + else if (reader_falling_edge_time == 4'd0) // reader signal changes right before sampling. Better sample later next time. + begin + negedge_cnt <= negedge_cnt; // freeze time + end + else + begin + negedge_cnt <= negedge_cnt + 1; // Continue as usual + end + reader_falling_edge_time[3:0] <= 4'd8; // adjust only once per detected edge + end + else if (negedge_cnt == 7'd127) // normal operation: count from 0 to 127 + begin + negedge_cnt <= 0; + end + else + begin + negedge_cnt <= negedge_cnt + 1; + end +end //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -185,28 +185,28 @@ reg [3:0] mod_detect_reset_time; always @(negedge adc_clk) begin - if (mod_type == `READER_LISTEN) - // (our) reader signal changes at negedge_cnt[3:0]=9, tag response expected to start n*16+4 ticks later, further delayed by - // 3 ticks ADC conversion. The maximum filter output (edge detected) will be detected after subcarrier zero crossing (+7 ticks). - // To allow some timing variances, we want to have the maximum filter outputs well within the detection window, i.e. - // at mod_detect_reset_time+4 and mod_detect_reset_time+12 (-4 ticks). - // 9 + 4 + 3 + 7 - 4 = 19. 19 mod 16 = 3 - begin - mod_detect_reset_time <= 4'd4; - end - else - if (mod_type == `SNIFFER) - begin - // detect a rising edge of reader's signal and sync modulation detector to the tag's answer: - if (~pre_after_hysteresis && after_hysteresis && deep_modulation) - // reader signal rising edge detected at negedge_cnt[3:0]. This signal had been delayed - // 9 ticks by the RF part + 3 ticks by the A/D converter + 1 tick to assign to after_hysteresis. - // Then the same as above. - // - 9 - 3 - 1 + 4 + 3 + 7 - 4 = -3 - begin - mod_detect_reset_time <= negedge_cnt[3:0] - 4'd3; - end - end + if (mod_type == `READER_LISTEN) + // (our) reader signal changes at negedge_cnt[3:0]=9, tag response expected to start n*16+4 ticks later, further delayed by + // 3 ticks ADC conversion. The maximum filter output (edge detected) will be detected after subcarrier zero crossing (+7 ticks). + // To allow some timing variances, we want to have the maximum filter outputs well within the detection window, i.e. + // at mod_detect_reset_time+4 and mod_detect_reset_time+12 (-4 ticks). + // 9 + 4 + 3 + 7 - 4 = 19. 19 mod 16 = 3 + begin + mod_detect_reset_time <= 4'd4; + end + else + if (mod_type == `SNIFFER) + begin + // detect a rising edge of reader's signal and sync modulation detector to the tag's answer: + if (~pre_after_hysteresis && after_hysteresis && deep_modulation) + // reader signal rising edge detected at negedge_cnt[3:0]. This signal had been delayed + // 9 ticks by the RF part + 3 ticks by the A/D converter + 1 tick to assign to after_hysteresis. + // Then the same as above. + // - 9 - 3 - 1 + 4 + 3 + 7 - 4 = -3 + begin + mod_detect_reset_time <= negedge_cnt[3:0] - 4'd3; + end + end end @@ -218,34 +218,34 @@ reg signed [10:0] rx_mod_falling_edge_max; reg signed [10:0] rx_mod_rising_edge_max; reg curbit; -`define EDGE_DETECT_THRESHOLD 5 +`define EDGE_DETECT_THRESHOLD 5 always @(negedge adc_clk) begin - if(negedge_cnt[3:0] == mod_detect_reset_time) - begin - // detect modulation signal: if modulating, there must have been a falling AND a rising edge - if ((rx_mod_falling_edge_max > `EDGE_DETECT_THRESHOLD) && (rx_mod_rising_edge_max < -`EDGE_DETECT_THRESHOLD)) - curbit <= 1'b1; // modulation - else - curbit <= 1'b0; // no modulation - // reset modulation detector - rx_mod_rising_edge_max <= 0; - rx_mod_falling_edge_max <= 0; - end - else // look for steepest edges (slopes) - begin - if (adc_d_filtered > 0) - begin - if (adc_d_filtered > rx_mod_falling_edge_max) - rx_mod_falling_edge_max <= adc_d_filtered; - end - else - begin - if (adc_d_filtered < rx_mod_rising_edge_max) - rx_mod_rising_edge_max <= adc_d_filtered; - end - end + if(negedge_cnt[3:0] == mod_detect_reset_time) + begin + // detect modulation signal: if modulating, there must have been a falling AND a rising edge + if ((rx_mod_falling_edge_max > `EDGE_DETECT_THRESHOLD) && (rx_mod_rising_edge_max < -`EDGE_DETECT_THRESHOLD)) + curbit <= 1'b1; // modulation + else + curbit <= 1'b0; // no modulation + // reset modulation detector + rx_mod_rising_edge_max <= 0; + rx_mod_falling_edge_max <= 0; + end + else // look for steepest edges (slopes) + begin + if (adc_d_filtered > 0) + begin + if (adc_d_filtered > rx_mod_falling_edge_max) + rx_mod_falling_edge_max <= adc_d_filtered; + end + else + begin + if (adc_d_filtered < rx_mod_rising_edge_max) + rx_mod_rising_edge_max <= adc_d_filtered; + end + end end @@ -260,11 +260,11 @@ reg [3:0] tag_data; always @(negedge adc_clk) begin if(negedge_cnt[3:0] == 4'd0) - begin + begin reader_data[3:0] <= {reader_data[2:0], after_hysteresis}; - tag_data[3:0] <= {tag_data[2:0], curbit}; - end -end + tag_data[3:0] <= {tag_data[2:0], curbit}; + end +end @@ -277,17 +277,17 @@ reg mod_sig; always @(negedge adc_clk) begin - if(negedge_cnt[3:0] == 4'd0) // sample data at rising edge of ssp_clk - ssp_dout changes at the falling edge. - begin - mod_sig_buf[31:2] <= mod_sig_buf[30:1]; // shift - if (~ssp_dout && ~mod_sig_buf[1]) - mod_sig_buf[1] <= 1'b0; // delete the correction bit (a single 1 preceded and succeeded by 0) - else - mod_sig_buf[1] <= mod_sig_buf[0]; - mod_sig_buf[0] <= ssp_dout; // add new data to the delay line + if(negedge_cnt[3:0] == 4'd0) // sample data at rising edge of ssp_clk - ssp_dout changes at the falling edge. + begin + mod_sig_buf[31:2] <= mod_sig_buf[30:1]; // shift + if (~ssp_dout && ~mod_sig_buf[1]) + mod_sig_buf[1] <= 1'b0; // delete the correction bit (a single 1 preceded and succeeded by 0) + else + mod_sig_buf[1] <= mod_sig_buf[0]; + mod_sig_buf[0] <= ssp_dout; // add new data to the delay line - mod_sig = mod_sig_buf[mod_sig_ptr]; // the delayed signal. - end + mod_sig = mod_sig_buf[mod_sig_ptr]; // the delayed signal. + end end @@ -297,7 +297,7 @@ end // a timer for the 1172 cycles fdt (Frame Delay Time). Start the timer with a rising edge of the reader's signal. // set fdt_elapsed when we no longer need to delay data. Set fdt_indicator when we can start sending data. // Note: the FPGA only takes care for the 1172 delay. To achieve an additional 1236-1172=64 ticks delay, the ARM must send -// a correction bit (before the start bit). The correction bit will be coded as 00010000, i.e. it adds 4 bits to the +// a correction bit (before the start bit). The correction bit will be coded as 00010000, i.e. it adds 4 bits to the // transmission stream, causing the required additional delay. reg [10:0] fdt_counter; reg fdt_indicator, fdt_elapsed; @@ -317,41 +317,41 @@ reg [3:0] sub_carrier_cnt; `define FDT_INDICATOR_COUNT 11'd647 // Note: worst case, assignment to sendbit takes 15 ticks more, and transfer to ARM needs 7*16 = 112 ticks more. // When the ARM's response then appears, the fdt_count is already 647 + 15 + 112 = 774, which still allows the ARM a possible -// response window of 1128 - 774 = 354 ticks. +// response window of 1128 - 774 = 354 ticks. // reset on a pause in listen mode. I.e. the counter starts when the pause is over: assign fdt_reset = ~after_hysteresis && mod_type == `TAGSIM_LISTEN; always @(negedge adc_clk) begin - if (fdt_reset) - begin - fdt_counter <= 11'd0; - fdt_elapsed <= 1'b0; - fdt_indicator <= 1'b0; - end - else - begin - if(fdt_counter == `FDT_COUNT) - begin - if(~fdt_elapsed) // just reached fdt. - begin - mod_sig_flip <= negedge_cnt[3:0]; // start modulation at this time - sub_carrier_cnt <= 4'd0; // subcarrier phase in sync with start of modulation - fdt_elapsed <= 1'b1; - end - else - begin - sub_carrier_cnt <= sub_carrier_cnt + 1; - end - end - else - begin - fdt_counter <= fdt_counter + 1; - end - end - - if(fdt_counter == `FDT_INDICATOR_COUNT) fdt_indicator <= 1'b1; + if (fdt_reset) + begin + fdt_counter <= 11'd0; + fdt_elapsed <= 1'b0; + fdt_indicator <= 1'b0; + end + else + begin + if(fdt_counter == `FDT_COUNT) + begin + if(~fdt_elapsed) // just reached fdt. + begin + mod_sig_flip <= negedge_cnt[3:0]; // start modulation at this time + sub_carrier_cnt <= 4'd0; // subcarrier phase in sync with start of modulation + fdt_elapsed <= 1'b1; + end + else + begin + sub_carrier_cnt <= sub_carrier_cnt + 1; + end + end + else + begin + fdt_counter <= fdt_counter + 1; + end + end + + if(fdt_counter == `FDT_INDICATOR_COUNT) fdt_indicator <= 1'b1; end @@ -363,24 +363,24 @@ reg mod_sig_coil; always @(negedge adc_clk) begin - if (mod_type == `TAGSIM_MOD) // need to take care of proper fdt timing - begin - if(fdt_counter == `FDT_COUNT) - begin - if(fdt_elapsed) - begin - if(negedge_cnt[3:0] == mod_sig_flip) mod_sig_coil <= mod_sig; - end - else - begin - mod_sig_coil <= mod_sig; // just reached fdt. Immediately assign signal to coil - end - end - end - else // other modes: don't delay - begin - mod_sig_coil <= ssp_dout; - end + if (mod_type == `TAGSIM_MOD) // need to take care of proper fdt timing + begin + if(fdt_counter == `FDT_COUNT) + begin + if(fdt_elapsed) + begin + if(negedge_cnt[3:0] == mod_sig_flip) mod_sig_coil <= mod_sig; + end + else + begin + mod_sig_coil <= mod_sig; // just reached fdt. Immediately assign signal to coil + end + end + end + else // other modes: don't delay + begin + mod_sig_coil <= ssp_dout; + end end @@ -392,39 +392,39 @@ reg temp_buffer_reset; always @(negedge adc_clk) begin - if(fdt_reset) - begin - mod_sig_ptr <= 5'd0; - temp_buffer_reset = 1'b0; - end - else - begin - if(fdt_counter == `FDT_COUNT && ~fdt_elapsed) // if we just reached fdt - if(~(| mod_sig_ptr[4:0])) - mod_sig_ptr <= 5'd8; // ... but didn't buffer a 1 yet, delay next 1 by n*128 ticks. - else - temp_buffer_reset = 1'b1; // else no need for further delays. + if(fdt_reset) + begin + mod_sig_ptr <= 5'd0; + temp_buffer_reset = 1'b0; + end + else + begin + if(fdt_counter == `FDT_COUNT && ~fdt_elapsed) // if we just reached fdt + if(~(| mod_sig_ptr[4:0])) + mod_sig_ptr <= 5'd8; // ... but didn't buffer a 1 yet, delay next 1 by n*128 ticks. + else + temp_buffer_reset = 1'b1; // else no need for further delays. - if(negedge_cnt[3:0] == 4'd0) // at rising edge of ssp_clk - ssp_dout changes at the falling edge. - begin - if((ssp_dout || (| mod_sig_ptr[4:0])) && ~fdt_elapsed) // buffer a 1 (and all subsequent data) until fdt is reached. - if (mod_sig_ptr == 5'd31) - mod_sig_ptr <= 5'd0; // buffer overflow - data loss. - else - mod_sig_ptr <= mod_sig_ptr + 1; // increase buffer (= increase delay by 16 adc_clk ticks). mod_sig_ptr always points ahead of first 1. - else if(fdt_elapsed && ~temp_buffer_reset) - begin - // wait for the next 1 after fdt_elapsed before fixing the delay and starting modulation. This ensures that the response can only happen - // at intervals of 8 * 16 = 128 adc_clk ticks (as defined in ISO14443-3) - if(ssp_dout) - temp_buffer_reset = 1'b1; - if(mod_sig_ptr == 5'd1) - mod_sig_ptr <= 5'd8; // still nothing received, need to go for the next interval - else - mod_sig_ptr <= mod_sig_ptr - 1; // decrease buffer. - end - end - end + if(negedge_cnt[3:0] == 4'd0) // at rising edge of ssp_clk - ssp_dout changes at the falling edge. + begin + if((ssp_dout || (| mod_sig_ptr[4:0])) && ~fdt_elapsed) // buffer a 1 (and all subsequent data) until fdt is reached. + if (mod_sig_ptr == 5'd31) + mod_sig_ptr <= 5'd0; // buffer overflow - data loss. + else + mod_sig_ptr <= mod_sig_ptr + 1; // increase buffer (= increase delay by 16 adc_clk ticks). mod_sig_ptr always points ahead of first 1. + else if(fdt_elapsed && ~temp_buffer_reset) + begin + // wait for the next 1 after fdt_elapsed before fixing the delay and starting modulation. This ensures that the response can only happen + // at intervals of 8 * 16 = 128 adc_clk ticks (as defined in ISO14443-3) + if(ssp_dout) + temp_buffer_reset = 1'b1; + if(mod_sig_ptr == 5'd1) + mod_sig_ptr <= 5'd8; // still nothing received, need to go for the next interval + else + mod_sig_ptr <= mod_sig_ptr - 1; // decrease buffer. + end + end + end end @@ -436,43 +436,43 @@ reg [7:0] to_arm; always @(negedge adc_clk) begin - if (negedge_cnt[5:0] == 6'd63) // fill the buffer - begin - if (mod_type == `SNIFFER) - begin - if(deep_modulation) // a reader is sending (or there's no field at all) - begin - to_arm <= {reader_data[3:0], 4'b0000}; // don't send tag data - end - else - begin - to_arm <= {reader_data[3:0], tag_data[3:0]}; - end - end - else - begin - to_arm[7:0] <= {mod_sig_ptr[4:0], mod_sig_flip[3:1]}; // feedback timing information - end - end + if (negedge_cnt[5:0] == 6'd63) // fill the buffer + begin + if (mod_type == `SNIFFER) + begin + if(deep_modulation) // a reader is sending (or there's no field at all) + begin + to_arm <= {reader_data[3:0], 4'b0000}; // don't send tag data + end + else + begin + to_arm <= {reader_data[3:0], tag_data[3:0]}; + end + end + else + begin + to_arm[7:0] <= {mod_sig_ptr[4:0], mod_sig_flip[3:1]}; // feedback timing information + end + end - if(negedge_cnt[2:0] == 3'b000 && mod_type == `SNIFFER) // shift at double speed - begin - // Don't shift if we just loaded new data, obviously. - if(negedge_cnt[5:0] != 6'd0) - begin - to_arm[7:1] <= to_arm[6:0]; - end - end + if(negedge_cnt[2:0] == 3'b000 && mod_type == `SNIFFER) // shift at double speed + begin + // Don't shift if we just loaded new data, obviously. + if(negedge_cnt[5:0] != 6'd0) + begin + to_arm[7:1] <= to_arm[6:0]; + end + end + + if(negedge_cnt[3:0] == 4'b0000 && mod_type != `SNIFFER) + begin + // Don't shift if we just loaded new data, obviously. + if(negedge_cnt[6:0] != 7'd0) + begin + to_arm[7:1] <= to_arm[6:0]; + end + end - if(negedge_cnt[3:0] == 4'b0000 && mod_type != `SNIFFER) - begin - // Don't shift if we just loaded new data, obviously. - if(negedge_cnt[6:0] != 7'd0) - begin - to_arm[7:1] <= to_arm[6:0]; - end - end - end @@ -484,32 +484,32 @@ reg ssp_frame; always @(negedge adc_clk) begin - if(mod_type == `SNIFFER) - // SNIFFER mode (ssp_clk = adc_clk / 8, ssp_frame clock = adc_clk / 64)): - begin - if(negedge_cnt[2:0] == 3'd0) - ssp_clk <= 1'b1; - if(negedge_cnt[2:0] == 3'd4) - ssp_clk <= 1'b0; + if(mod_type == `SNIFFER) + // SNIFFER mode (ssp_clk = adc_clk / 8, ssp_frame clock = adc_clk / 64)): + begin + if(negedge_cnt[2:0] == 3'd0) + ssp_clk <= 1'b1; + if(negedge_cnt[2:0] == 3'd4) + ssp_clk <= 1'b0; - if(negedge_cnt[5:0] == 6'd0) // ssp_frame rising edge indicates start of frame - ssp_frame <= 1'b1; - if(negedge_cnt[5:0] == 6'd8) - ssp_frame <= 1'b0; - end - else - // all other modes (ssp_clk = adc_clk / 16, ssp_frame clock = adc_clk / 128): - begin - if(negedge_cnt[3:0] == 4'd0) - ssp_clk <= 1'b1; - if(negedge_cnt[3:0] == 4'd8) - ssp_clk <= 1'b0; + if(negedge_cnt[5:0] == 6'd0) // ssp_frame rising edge indicates start of frame + ssp_frame <= 1'b1; + if(negedge_cnt[5:0] == 6'd8) + ssp_frame <= 1'b0; + end + else + // all other modes (ssp_clk = adc_clk / 16, ssp_frame clock = adc_clk / 128): + begin + if(negedge_cnt[3:0] == 4'd0) + ssp_clk <= 1'b1; + if(negedge_cnt[3:0] == 4'd8) + ssp_clk <= 1'b0; - if(negedge_cnt[6:0] == 7'd7) // ssp_frame rising edge indicates start of frame - ssp_frame <= 1'b1; - if(negedge_cnt[6:0] == 7'd23) - ssp_frame <= 1'b0; - end + if(negedge_cnt[6:0] == 7'd7) // ssp_frame rising edge indicates start of frame + ssp_frame <= 1'b1; + if(negedge_cnt[6:0] == 7'd23) + ssp_frame <= 1'b0; + end end @@ -522,31 +522,31 @@ reg sendbit; always @(negedge adc_clk) begin - if(negedge_cnt[3:0] == 4'd0) - begin - // What do we communicate to the ARM - if(mod_type == `TAGSIM_LISTEN) - sendbit = after_hysteresis; - else if(mod_type == `TAGSIM_MOD) - /* if(fdt_counter > 11'd772) sendbit = mod_sig_coil; // huh? - else */ - sendbit = fdt_indicator; - else if (mod_type == `READER_LISTEN) - sendbit = curbit; - else - sendbit = 1'b0; - end + if(negedge_cnt[3:0] == 4'd0) + begin + // What do we communicate to the ARM + if(mod_type == `TAGSIM_LISTEN) + sendbit = after_hysteresis; + else if(mod_type == `TAGSIM_MOD) + /* if(fdt_counter > 11'd772) sendbit = mod_sig_coil; // huh? + else */ + sendbit = fdt_indicator; + else if (mod_type == `READER_LISTEN) + sendbit = curbit; + else + sendbit = 1'b0; + end - if(mod_type == `SNIFFER) - // send sampled reader and tag data: - bit_to_arm = to_arm[7]; - else if (mod_type == `TAGSIM_MOD && fdt_elapsed && temp_buffer_reset) - // send timing information: - bit_to_arm = to_arm[7]; - else - // send data or fdt_indicator - bit_to_arm = sendbit; + if(mod_type == `SNIFFER) + // send sampled reader and tag data: + bit_to_arm = to_arm[7]; + else if (mod_type == `TAGSIM_MOD && fdt_elapsed && temp_buffer_reset) + // send timing information: + bit_to_arm = to_arm[7]; + else + // send data or fdt_indicator + bit_to_arm = sendbit; end @@ -559,7 +559,7 @@ wire sub_carrier; assign sub_carrier = ~sub_carrier_cnt[3]; // in READER_MOD: drop carrier for mod_sig_coil==1 (pause); in READER_LISTEN: carrier always on; in other modes: carrier always off -assign pwr_hi = (ck_1356megb & (((mod_type == `READER_MOD) & ~mod_sig_coil) || (mod_type == `READER_LISTEN))); +assign pwr_hi = (ck_1356megb & (((mod_type == `READER_MOD) & ~mod_sig_coil) || (mod_type == `READER_LISTEN))); // Enable HF antenna drivers: @@ -567,8 +567,8 @@ assign pwr_oe1 = 1'b0; assign pwr_oe3 = 1'b0; // TAGSIM_MOD: short circuit antenna with different resistances (modulated by sub_carrier modulated by mod_sig_coil) -// for pwr_oe4 = 1 (tristate): antenna load = 10k || 33 = 32,9 Ohms -// for pwr_oe4 = 0 (active): antenna load = 10k || 33 || 33 = 16,5 Ohms +// for pwr_oe4 = 1 (tristate): antenna load = 10k || 33 = 32,9 Ohms +// for pwr_oe4 = 0 (active): antenna load = 10k || 33 || 33 = 16,5 Ohms assign pwr_oe4 = mod_sig_coil & sub_carrier & (mod_type == `TAGSIM_MOD); // This is all LF, so doesn't matter. diff --git a/fpga/hi_read_rx_xcorr.v b/fpga/hi_read_rx_xcorr.v index 94a798a86..be70b97b0 100644 --- a/fpga/hi_read_rx_xcorr.v +++ b/fpga/hi_read_rx_xcorr.v @@ -32,16 +32,16 @@ reg [2:0] fc_div; always @(negedge ck_1356megb) fc_div <= fc_div + 1; -(* clock_signal = "yes" *) reg adc_clk; // sample frequency, always 16 * fc +(* clock_signal = "yes" *) reg adc_clk; // sample frequency, always 16 * fc always @(ck_1356megb, xcorr_is_848, xcorr_quarter_freq, fc_div) - if (xcorr_is_848 & ~xcorr_quarter_freq) // fc = 847.5 kHz, standard ISO14443B - adc_clk <= ck_1356megb; - else if (~xcorr_is_848 & ~xcorr_quarter_freq) // fc = 423.75 kHz - adc_clk <= fc_div[0]; - else if (xcorr_is_848 & xcorr_quarter_freq) // fc = 211.875 kHz - adc_clk <= fc_div[1]; - else // fc = 105.9375 kHz - adc_clk <= fc_div[2]; + if (xcorr_is_848 & ~xcorr_quarter_freq) // fc = 847.5 kHz, standard ISO14443B + adc_clk <= ck_1356megb; + else if (~xcorr_is_848 & ~xcorr_quarter_freq) // fc = 423.75 kHz + adc_clk <= fc_div[0]; + else if (xcorr_is_848 & xcorr_quarter_freq) // fc = 211.875 kHz + adc_clk <= fc_div[1]; + else // fc = 105.9375 kHz + adc_clk <= fc_div[2]; // When we're a reader, we just need to do the BPSK demod; but when we're an // eavesdropper, we also need to pick out the commands sent by the reader, @@ -94,9 +94,9 @@ reg ssp_frame; always @(negedge adc_clk) begin - corr_i_cnt <= corr_i_cnt + 1; -end - + corr_i_cnt <= corr_i_cnt + 1; +end + // ADC data appears on the rising edge, so sample it on the falling edge always @(negedge adc_clk) @@ -147,7 +147,7 @@ begin else corr_i_accum <= corr_i_accum + adc_d; - if(corr_i_cnt[3] == corr_i_cnt[2]) // phase shifted by pi/2 + if(corr_i_cnt[3] == corr_i_cnt[2]) // phase shifted by pi/2 corr_q_accum <= corr_q_accum + adc_d; else corr_q_accum <= corr_q_accum - adc_d; @@ -177,8 +177,8 @@ begin end end - // set ssp_frame signal for corr_i_cnt = 0..3 and corr_i_cnt = 32..35 - // (send two frames with 8 Bits each) + // set ssp_frame signal for corr_i_cnt = 0..3 and corr_i_cnt = 32..35 + // (send two frames with 8 Bits each) if(corr_i_cnt[5:2] == 4'b0000 || corr_i_cnt[5:2] == 4'b1000) ssp_frame = 1'b1; else diff --git a/fpga/hi_read_tx.v b/fpga/hi_read_tx.v index 756683cdd..f9550ed24 100644 --- a/fpga/hi_read_tx.v +++ b/fpga/hi_read_tx.v @@ -27,7 +27,7 @@ module hi_read_tx( // low frequency outputs, not relevant assign pwr_lo = 1'b0; assign pwr_oe2 = 1'b0; - + // The high-frequency stuff. For now, for testing, just bring out the carrier, // and allow the ARM to modulate it over the SSP. reg pwr_hi; @@ -75,4 +75,4 @@ assign ssp_din = 1'b0; assign dbg = ssp_frame; -endmodule \ No newline at end of file +endmodule diff --git a/fpga/hi_simulate.v b/fpga/hi_simulate.v index aea6b743b..d336a5ddf 100644 --- a/fpga/hi_simulate.v +++ b/fpga/hi_simulate.v @@ -1,7 +1,7 @@ //----------------------------------------------------------------------------- // Pretend to be an ISO 14443 tag. We will do this by alternately short- // circuiting and open-circuiting the antenna coil, with the tri-state -// pins. +// pins. // // We communicate over the SSP, as a bitstream (i.e., might as well be // unframed, though we still generate the word sync signal). The output @@ -69,7 +69,7 @@ begin // Get next bit at 212kHz ssp_clk <= ssp_clk_divider[5]; else - // Get next bit at 424Khz + // Get next bit at 424kHz ssp_clk <= ssp_clk_divider[4]; end diff --git a/fpga/lf_edge_detect.v b/fpga/lf_edge_detect.v index 573adf7bd..d086f95fc 100644 --- a/fpga/lf_edge_detect.v +++ b/fpga/lf_edge_detect.v @@ -5,73 +5,73 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// input clk is 24Mhz +// input clk is 24MHz `include "min_max_tracker.v" module lf_edge_detect(input clk, input [7:0] adc_d, input [7:0] lf_ed_threshold, - output [7:0] max, output [7:0] min, - output [7:0] high_threshold, output [7:0] highz_threshold, - output [7:0] lowz_threshold, output [7:0] low_threshold, - output edge_state, output edge_toggle); + output [7:0] max, output [7:0] min, + output [7:0] high_threshold, output [7:0] highz_threshold, + output [7:0] lowz_threshold, output [7:0] low_threshold, + output edge_state, output edge_toggle); - min_max_tracker tracker(clk, adc_d, lf_ed_threshold, min, max); + min_max_tracker tracker(clk, adc_d, lf_ed_threshold, min, max); - // auto-tune - assign high_threshold = (max + min) / 2 + (max - min) / 4; - assign highz_threshold = (max + min) / 2 + (max - min) / 8; - assign lowz_threshold = (max + min) / 2 - (max - min) / 8; - assign low_threshold = (max + min) / 2 - (max - min) / 4; + // auto-tune + assign high_threshold = (max + min) / 2 + (max - min) / 4; + assign highz_threshold = (max + min) / 2 + (max - min) / 8; + assign lowz_threshold = (max + min) / 2 - (max - min) / 8; + assign low_threshold = (max + min) / 2 - (max - min) / 4; - // heuristic to see if it makes sense to try to detect an edge - wire enabled = - (high_threshold > highz_threshold) - & (highz_threshold > lowz_threshold) - & (lowz_threshold > low_threshold) - & ((high_threshold - highz_threshold) > 8) - & ((highz_threshold - lowz_threshold) > 16) - & ((lowz_threshold - low_threshold) > 8); + // heuristic to see if it makes sense to try to detect an edge + wire enabled = + (high_threshold > highz_threshold) + & (highz_threshold > lowz_threshold) + & (lowz_threshold > low_threshold) + & ((high_threshold - highz_threshold) > 8) + & ((highz_threshold - lowz_threshold) > 16) + & ((lowz_threshold - low_threshold) > 8); - // Toggle the output with hysteresis - // Set to high if the ADC value is above the threshold - // Set to low if the ADC value is below the threshold - reg is_high = 0; - reg is_low = 0; - reg is_zero = 0; - reg trigger_enabled = 1; - reg output_edge = 0; - reg output_state; + // Toggle the output with hysteresis + // Set to high if the ADC value is above the threshold + // Set to low if the ADC value is below the threshold + reg is_high = 0; + reg is_low = 0; + reg is_zero = 0; + reg trigger_enabled = 1; + reg output_edge = 0; + reg output_state; - always @(posedge clk) - begin - is_high <= (adc_d >= high_threshold); - is_low <= (adc_d <= low_threshold); - is_zero <= ((adc_d > lowz_threshold) & (adc_d < highz_threshold)); - end + always @(posedge clk) + begin + is_high <= (adc_d >= high_threshold); + is_low <= (adc_d <= low_threshold); + is_zero <= ((adc_d > lowz_threshold) & (adc_d < highz_threshold)); + end - // all edges detection - always @(posedge clk) - if (enabled) begin - // To enable detecting two consecutive peaks at the same level - // (low or high) we check whether or not we went back near 0 in-between. - // This extra check is necessary to prevent from noise artifacts - // around the threshold values. - if (trigger_enabled & (is_high | is_low)) begin - output_edge <= ~output_edge; - trigger_enabled <= 0; - end else - trigger_enabled <= trigger_enabled | is_zero; - end + // all edges detection + always @(posedge clk) + if (enabled) begin + // To enable detecting two consecutive peaks at the same level + // (low or high) we check whether or not we went back near 0 in-between. + // This extra check is necessary to prevent from noise artifacts + // around the threshold values. + if (trigger_enabled & (is_high | is_low)) begin + output_edge <= ~output_edge; + trigger_enabled <= 0; + end else + trigger_enabled <= trigger_enabled | is_zero; + end - // edge states - always @(posedge clk) - if (enabled) begin - if (is_high) - output_state <= 1'd1; - else if (is_low) - output_state <= 1'd0; - end + // edge states + always @(posedge clk) + if (enabled) begin + if (is_high) + output_state <= 1'd1; + else if (is_low) + output_state <= 1'd0; + end - assign edge_state = output_state; - assign edge_toggle = output_edge; + assign edge_state = output_state; + assign edge_toggle = output_edge; endmodule diff --git a/fpga/lo_adc.v b/fpga/lo_adc.v new file mode 100644 index 000000000..57e9eebc8 --- /dev/null +++ b/fpga/lo_adc.v @@ -0,0 +1,82 @@ +//----------------------------------------------------------------------------- +// The way that we connect things in low-frequency simulation mode. In this +// case just pass everything through to the ARM, which can bit-bang this +// (because it is so slow). +// +// Jonathan Westhues, April 2006 +//----------------------------------------------------------------------------- + +module lo_adc( + pck0, + pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, + adc_d, adc_clk, + ssp_frame, ssp_din, ssp_dout, ssp_clk, + cross_hi, cross_lo, + dbg, divisor, + lo_is_125khz, lf_field +); + input pck0; + output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; + input [7:0] adc_d; + output adc_clk; + input ssp_dout; + output ssp_frame, ssp_din, ssp_clk; + input cross_hi, cross_lo; + output dbg; + input [7:0] divisor; + input lo_is_125khz; // redundant signal, no longer used anywhere + input lf_field; + +reg [7:0] to_arm_shiftreg; +reg [7:0] pck_divider; +reg clk_state; + +// Antenna logic, depending on "lf_field" (in arm defined as FPGA_LF_READER_FIELD) +wire tag_modulation; +assign tag_modulation = ssp_dout & !lf_field; +wire reader_modulation; +assign reader_modulation = !ssp_dout & lf_field & clk_state; +assign pwr_oe1 = 1'b0; // not used in LF mode +assign pwr_oe2 = 1'b0; //tag_modulation; +assign pwr_oe3 = tag_modulation; +assign pwr_oe4 = 1'b0; //tag_modulation; +assign pwr_lo = reader_modulation; +assign pwr_hi = 1'b0; +assign dbg = adc_clk; + +// ADC clock out of phase with antenna driver +assign adc_clk = ~clk_state; +// serialized SSP data is gated by clk_state to suppress unwanted signal +assign ssp_din = to_arm_shiftreg[7] && !clk_state; +// SSP clock always runs at 24MHz +assign ssp_clk = pck0; +// SSP frame is gated by clk_state and goes high when pck_divider=8..15 +assign ssp_frame = (pck_divider[7:3] == 5'd1) && !clk_state; + +always @(posedge pck0) +begin + if(pck_divider == divisor[7:0]) + begin + pck_divider <= 8'd0; + clk_state = !clk_state; + end + else + begin + pck_divider <= pck_divider + 1; + end +end + +always @(posedge pck0) +begin + if((pck_divider == 8'd7) && !clk_state) + begin + to_arm_shiftreg <= adc_d; + end + else + begin + to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0]; + to_arm_shiftreg[0] <= 1'b0; + end +end + +endmodule diff --git a/fpga/lo_edge_detect.v b/fpga/lo_edge_detect.v index bb1301574..5c73af96f 100644 --- a/fpga/lo_edge_detect.v +++ b/fpga/lo_edge_detect.v @@ -35,11 +35,11 @@ wire tag_modulation = ssp_dout & !lf_field; wire reader_modulation = !ssp_dout & lf_field & pck_divclk; // No logic, straight through. -assign pwr_oe1 = 1'b0; // not used in LF mode -assign pwr_oe3 = 1'b0; // base antenna load = 33 Ohms +assign pwr_oe1 = 1'b0; // not used in LF mode +assign pwr_oe3 = 1'b0; // base antenna load = 33 Ohms // when modulating, add another 33 Ohms and 10k Ohms in parallel: assign pwr_oe2 = tag_modulation; -assign pwr_oe4 = tag_modulation; +assign pwr_oe4 = tag_modulation; assign ssp_clk = cross_lo; assign pwr_lo = reader_modulation; @@ -56,9 +56,9 @@ wire [7:0] high_threshold, highz_threshold, lowz_threshold, low_threshold; wire [7:0] max, min; wire edge_state, edge_toggle; lf_edge_detect lf_ed(pck0, adc_filtered, lf_ed_threshold, - max, min, - high_threshold, highz_threshold, lowz_threshold, low_threshold, - edge_state, edge_toggle); + max, min, + high_threshold, highz_threshold, lowz_threshold, low_threshold, + edge_state, edge_toggle); assign dbg = lf_ed_toggle_mode ? edge_toggle : edge_state; diff --git a/fpga/lo_passthru.v b/fpga/lo_passthru.v index 3507f660e..f0f2847a0 100644 --- a/fpga/lo_passthru.v +++ b/fpga/lo_passthru.v @@ -5,13 +5,13 @@ // iZsh , June 2014 module lo_passthru( - input pck_divclk, - output pwr_lo, output pwr_hi, - output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, - output adc_clk, - output ssp_din, input ssp_dout, - input cross_lo, - output dbg + input pck_divclk, + output pwr_lo, output pwr_hi, + output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, + output adc_clk, + output ssp_din, input ssp_dout, + input cross_lo, + output dbg ); // the antenna is modulated when ssp_dout = 1, when 0 the diff --git a/fpga/lo_read.v b/fpga/lo_read.v index a6d077b99..8f778309b 100644 --- a/fpga/lo_read.v +++ b/fpga/lo_read.v @@ -8,18 +8,18 @@ //----------------------------------------------------------------------------- module lo_read( - input pck0, input [7:0] pck_cnt, input pck_divclk, - output pwr_lo, output pwr_hi, - output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, - input [7:0] adc_d, output adc_clk, - output ssp_frame, output ssp_din, output ssp_clk, - output dbg, - input lf_field + input pck0, input [7:0] pck_cnt, input pck_divclk, + output pwr_lo, output pwr_hi, + output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, + input [7:0] adc_d, output adc_clk, + output ssp_frame, output ssp_din, output ssp_clk, + output dbg, + input lf_field ); reg [7:0] to_arm_shiftreg; -// this task also runs at pck0 frequency (24Mhz) and is used to serialize +// this task also runs at pck0 frequency (24MHz) and is used to serialize // the ADC output which is then clocked into the ARM SSP. // because pck_divclk always transitions when pck_cnt = 0 we use the @@ -27,17 +27,17 @@ reg [7:0] to_arm_shiftreg; // we read the ADC value when pck_cnt=7 and shift it out on counts 8..15 always @(posedge pck0) begin - if((pck_cnt == 8'd7) && !pck_divclk) - to_arm_shiftreg <= adc_d; - else begin - to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0]; - // simulation showed a glitch occuring due to the LSB of the shifter - // not being set as we shift bits out - // this ensures the ssp_din remains low after a transfer and suppresses - // the glitch that would occur when the last data shifted out ended in - // a 1 bit and the next data shifted out started with a 0 bit - to_arm_shiftreg[0] <= 1'b0; - end + if((pck_cnt == 8'd7) && !pck_divclk) + to_arm_shiftreg <= adc_d; + else begin + to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0]; + // simulation showed a glitch occuring due to the LSB of the shifter + // not being set as we shift bits out + // this ensures the ssp_din remains low after a transfer and suppresses + // the glitch that would occur when the last data shifted out ended in + // a 1 bit and the next data shifted out started with a 0 bit + to_arm_shiftreg[0] <= 1'b0; + end end // ADC samples on falling edge of adc_clk, data available on the rising edge @@ -55,7 +55,7 @@ end // serialized SSP data is gated by ant_lo to suppress unwanted signal assign ssp_din = to_arm_shiftreg[7] && !pck_divclk; -// SSP clock always runs at 24Mhz +// SSP clock always runs at 24MHz assign ssp_clk = pck0; // SSP frame is gated by ant_lo and goes high when pck_divider=8..15 assign ssp_frame = (pck_cnt[7:3] == 5'd1) && !pck_divclk; diff --git a/fpga/lo_simulate.v b/fpga/lo_simulate.v index 687bed27c..c4edc3eeb 100644 --- a/fpga/lo_simulate.v +++ b/fpga/lo_simulate.v @@ -13,7 +13,7 @@ module lo_simulate( ssp_frame, ssp_din, ssp_dout, ssp_clk, cross_hi, cross_lo, dbg, - divisor + divisor ); input pck0, ck_1356meg, ck_1356megb; output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; @@ -23,7 +23,7 @@ module lo_simulate( output ssp_frame, ssp_din, ssp_clk; input cross_hi, cross_lo; output dbg; - input [7:0] divisor; + input [7:0] divisor; // No logic, straight through. assign pwr_oe3 = 1'b0; @@ -41,15 +41,15 @@ reg clk_state; always @(posedge pck0) begin - if(pck_divider == divisor[7:0]) - begin - pck_divider <= 8'd0; - clk_state = !clk_state; - end - else - begin - pck_divider <= pck_divider + 1; - end + if(pck_divider == divisor[7:0]) + begin + pck_divider <= 8'd0; + clk_state = !clk_state; + end + else + begin + pck_divider <= pck_divider + 1; + end end assign adc_clk = ~clk_state; @@ -63,18 +63,18 @@ reg output_state; always @(posedge pck0) begin - if((pck_divider == 8'd7) && !clk_state) begin - is_high = (adc_d >= 8'd191); - is_low = (adc_d <= 8'd64); - end + if((pck_divider == 8'd7) && !clk_state) begin + is_high = (adc_d >= 8'd191); + is_low = (adc_d <= 8'd64); + end end always @(posedge is_high or posedge is_low) begin - if(is_high) - output_state <= 1'd1; - else if(is_low) - output_state <= 1'd0; + if(is_high) + output_state <= 1'd1; + else if(is_low) + output_state <= 1'd0; end assign ssp_frame = output_state; diff --git a/fpga/lp20khz_1MSa_iir_filter.v b/fpga/lp20khz_1MSa_iir_filter.v index a227a902c..2dbfd6945 100644 --- a/fpga/lp20khz_1MSa_iir_filter.v +++ b/fpga/lp20khz_1MSa_iir_filter.v @@ -28,54 +28,54 @@ // https://fail0verflow.com/blog/2014/proxmark3-fpga-iir-filter.html module lp20khz_1MSa_iir_filter(input clk, input [7:0] adc_d, output rdy, output [7:0] out); - // clk is 24Mhz, the IIR filter is designed for 1MS/s - // hence we need to divide it by 24 - // using a shift register takes less area than a counter - reg [23:0] cnt = 1; - assign rdy = cnt[0]; - always @(posedge clk) - cnt <= {cnt[22:0], cnt[23]}; + // clk is 24MHz, the IIR filter is designed for 1MS/s + // hence we need to divide it by 24 + // using a shift register takes less area than a counter + reg [23:0] cnt = 1; + assign rdy = cnt[0]; + always @(posedge clk) + cnt <= {cnt[22:0], cnt[23]}; - reg [7:0] x0 = 0; - reg [7:0] x1 = 0; - reg [16:0] y0 = 0; - reg [16:0] y1 = 0; + reg [7:0] x0 = 0; + reg [7:0] x1 = 0; + reg [16:0] y0 = 0; + reg [16:0] y1 = 0; - always @(posedge clk) - begin - if (rdy) - begin - x0 <= x1; - x1 <= adc_d; - y0 <= y1; - y1 <= - // center the signal: - // input range is [0; 255] - // We want "128" to be at the center of the 17bit register - // (128+z)*gain = 17bit center - // z = (1<<16)/gain - 128 = 109 - // We could use 9bit x registers for that, but that would be - // a waste, let's just add the constant during the computation - // (x0+109) + 2*(x1+109) + (x2+109) = x0 + 2*x1 + x2 + 436 - x0 + {x1, 1'b0} + adc_d + 436 - // we want "- y0 * 0xd6 / 0x100" using only shift and add - // 0xd6 == 0b11010110 - // so *0xd6/0x100 is equivalent to - // ((x << 1) + (x << 2) + (x << 4) + (x << 6) + (x << 7)) >> 8 - // which is also equivalent to - // (x >> 7) + (x >> 6) + (x >> 4) + (x >> 2) + (x >> 1) - - ((y0 >> 7) + (y0 >> 6) + (y0 >> 4) + (y0 >> 2) + (y0 >> 1)) // - y0 * 0xd6 / 0x100 - // we want "+ y1 * 0x1d3 / 0x100" - // 0x1d3 == 0b111010011 - // so this is equivalent to - // ((x << 0) + (x << 1) + (x << 4) + (x << 6) + (x << 7) + (x << 8)) >> 8 - // which is also equivalent to - // (x >> 8) + (x >> 7) + (x >> 4) + (x >> 2) + (x >> 1) + (x >> 0) - + ((y1 >> 8) + (y1 >> 7) + (y1 >> 4) + (y1 >> 2) + (y1 >> 1) + y1); - end - end + always @(posedge clk) + begin + if (rdy) + begin + x0 <= x1; + x1 <= adc_d; + y0 <= y1; + y1 <= + // center the signal: + // input range is [0; 255] + // We want "128" to be at the center of the 17bit register + // (128+z)*gain = 17bit center + // z = (1<<16)/gain - 128 = 109 + // We could use 9bit x registers for that, but that would be + // a waste, let's just add the constant during the computation + // (x0+109) + 2*(x1+109) + (x2+109) = x0 + 2*x1 + x2 + 436 + x0 + {x1, 1'b0} + adc_d + 436 + // we want "- y0 * 0xd6 / 0x100" using only shift and add + // 0xd6 == 0b11010110 + // so *0xd6/0x100 is equivalent to + // ((x << 1) + (x << 2) + (x << 4) + (x << 6) + (x << 7)) >> 8 + // which is also equivalent to + // (x >> 7) + (x >> 6) + (x >> 4) + (x >> 2) + (x >> 1) + - ((y0 >> 7) + (y0 >> 6) + (y0 >> 4) + (y0 >> 2) + (y0 >> 1)) // - y0 * 0xd6 / 0x100 + // we want "+ y1 * 0x1d3 / 0x100" + // 0x1d3 == 0b111010011 + // so this is equivalent to + // ((x << 0) + (x << 1) + (x << 4) + (x << 6) + (x << 7) + (x << 8)) >> 8 + // which is also equivalent to + // (x >> 8) + (x >> 7) + (x >> 4) + (x >> 2) + (x >> 1) + (x >> 0) + + ((y1 >> 8) + (y1 >> 7) + (y1 >> 4) + (y1 >> 2) + (y1 >> 1) + y1); + end + end - // output: reduce to 8bit - assign out = y1[16:9]; + // output: reduce to 8bit + assign out = y1[16:9]; endmodule diff --git a/fpga/min_max_tracker.v b/fpga/min_max_tracker.v index 8abd40fba..06a395a70 100644 --- a/fpga/min_max_tracker.v +++ b/fpga/min_max_tracker.v @@ -14,52 +14,52 @@ // This algorithm therefore can't be used directly for realtime peak detections, // but it can be used as a simple envelope follower. module min_max_tracker(input clk, input [7:0] adc_d, input [7:0] threshold, - output [7:0] min, output [7:0] max); + output [7:0] min, output [7:0] max); - reg [7:0] min_val = 255; - reg [7:0] max_val = 0; - reg [7:0] cur_min_val = 255; - reg [7:0] cur_max_val = 0; - reg [1:0] state = 0; + reg [7:0] min_val = 255; + reg [7:0] max_val = 0; + reg [7:0] cur_min_val = 255; + reg [7:0] cur_max_val = 0; + reg [1:0] state = 0; - always @(posedge clk) - begin - case (state) - 0: - begin - if (cur_max_val >= ({1'b0, adc_d} + threshold)) - state <= 2; - else if (adc_d >= ({1'b0, cur_min_val} + threshold)) - state <= 1; - if (cur_max_val <= adc_d) - cur_max_val <= adc_d; - else if (adc_d <= cur_min_val) - cur_min_val <= adc_d; - end - 1: - begin - if (cur_max_val <= adc_d) - cur_max_val <= adc_d; - else if (({1'b0, adc_d} + threshold) <= cur_max_val) begin - state <= 2; - cur_min_val <= adc_d; - max_val <= cur_max_val; - end - end - 2: - begin - if (adc_d <= cur_min_val) - cur_min_val <= adc_d; - else if (adc_d >= ({1'b0, cur_min_val} + threshold)) begin - state <= 1; - cur_max_val <= adc_d; - min_val <= cur_min_val; - end - end - endcase - end + always @(posedge clk) + begin + case (state) + 0: + begin + if (cur_max_val >= ({1'b0, adc_d} + threshold)) + state <= 2; + else if (adc_d >= ({1'b0, cur_min_val} + threshold)) + state <= 1; + if (cur_max_val <= adc_d) + cur_max_val <= adc_d; + else if (adc_d <= cur_min_val) + cur_min_val <= adc_d; + end + 1: + begin + if (cur_max_val <= adc_d) + cur_max_val <= adc_d; + else if (({1'b0, adc_d} + threshold) <= cur_max_val) begin + state <= 2; + cur_min_val <= adc_d; + max_val <= cur_max_val; + end + end + 2: + begin + if (adc_d <= cur_min_val) + cur_min_val <= adc_d; + else if (adc_d >= ({1'b0, cur_min_val} + threshold)) begin + state <= 1; + cur_max_val <= adc_d; + min_val <= cur_min_val; + end + end + endcase + end - assign min = min_val; - assign max = max_val; + assign min = min_val; + assign max = max_val; endmodule diff --git a/fpga/testbed_fpga.v b/fpga/testbed_fpga.v index f62255db3..e33df789c 100644 --- a/fpga/testbed_fpga.v +++ b/fpga/testbed_fpga.v @@ -18,33 +18,33 @@ module testbed_fpga; ssp_frame, ssp_din, ssp_dout, ssp_clk ); - integer i; + integer i; - initial begin + initial begin - // init inputs - #5 ncs=1; - #5 spck = 1; - #5 mosi = 1; + // init inputs + #5 ncs=1; + #5 spck = 1; + #5 mosi = 1; - #50 ncs=0; - for (i = 0 ; i < 8 ; i = i + 1) begin - #5 mosi = $random; - #5 spck = 0; - #5 spck = 1; - end - #5 ncs=1; + #50 ncs=0; + for (i = 0 ; i < 8 ; i = i + 1) begin + #5 mosi = $random; + #5 spck = 0; + #5 spck = 1; + end + #5 ncs=1; - #50 ncs=0; - for (i = 0 ; i < 8 ; i = i + 1) begin - #5 mosi = $random; - #5 spck = 0; - #5 spck = 1; - end - #5 ncs=1; + #50 ncs=0; + for (i = 0 ; i < 8 ; i = i + 1) begin + #5 mosi = $random; + #5 spck = 0; + #5 spck = 1; + end + #5 ncs=1; + + #50 mosi=1; + $finish; + end - #50 mosi=1; - $finish; - end - endmodule // main diff --git a/fpga/testbed_hi_read_tx.v b/fpga/testbed_hi_read_tx.v index bd4f5b40e..ee28a0a61 100644 --- a/fpga/testbed_hi_read_tx.v +++ b/fpga/testbed_hi_read_tx.v @@ -1,109 +1,109 @@ `include "hi_read_tx.v" /* - pck0 - input main 24Mhz clock (PLL / 4) - [7:0] adc_d - input data from A/D converter - shallow_modulation - modulation type + pck0 - input main 24MHz clock (PLL / 4) + [7:0] adc_d - input data from A/D converter + shallow_modulation - modulation type - pwr_lo - output to coil drivers (ssp_clk / 8) - adc_clk - output A/D clock signal - ssp_frame - output SSS frame indicator (goes high while the 8 bits are shifted) - ssp_din - output SSP data to ARM (shifts 8 bit A/D value serially to ARM MSB first) - ssp_clk - output SSP clock signal + pwr_lo - output to coil drivers (ssp_clk / 8) + adc_clk - output A/D clock signal + ssp_frame - output SSS frame indicator (goes high while the 8 bits are shifted) + ssp_din - output SSP data to ARM (shifts 8 bit A/D value serially to ARM MSB first) + ssp_clk - output SSP clock signal - ck_1356meg - input unused - ck_1356megb - input unused - ssp_dout - input unused - cross_hi - input unused - cross_lo - input unused + ck_1356meg - input unused + ck_1356megb - input unused + ssp_dout - input unused + cross_hi - input unused + cross_lo - input unused - pwr_hi - output unused, tied low - pwr_oe1 - output unused, undefined - pwr_oe2 - output unused, undefined - pwr_oe3 - output unused, undefined - pwr_oe4 - output unused, undefined - dbg - output alias for adc_clk + pwr_hi - output unused, tied low + pwr_oe1 - output unused, undefined + pwr_oe2 - output unused, undefined + pwr_oe3 - output unused, undefined + pwr_oe4 - output unused, undefined + dbg - output alias for adc_clk */ module testbed_hi_read_tx; - reg pck0; - reg [7:0] adc_d; - reg shallow_modulation; + reg pck0; + reg [7:0] adc_d; + reg shallow_modulation; - wire pwr_lo; - wire adc_clk; - reg ck_1356meg; - reg ck_1356megb; - wire ssp_frame; - wire ssp_din; - wire ssp_clk; - reg ssp_dout; - wire pwr_hi; - wire pwr_oe1; - wire pwr_oe2; - wire pwr_oe3; - wire pwr_oe4; - wire cross_lo; - wire cross_hi; - wire dbg; + wire pwr_lo; + wire adc_clk; + reg ck_1356meg; + reg ck_1356megb; + wire ssp_frame; + wire ssp_din; + wire ssp_clk; + reg ssp_dout; + wire pwr_hi; + wire pwr_oe1; + wire pwr_oe2; + wire pwr_oe3; + wire pwr_oe4; + wire cross_lo; + wire cross_hi; + wire dbg; - hi_read_tx #(5,200) dut( - .pck0(pck0), - .ck_1356meg(ck_1356meg), - .ck_1356megb(ck_1356megb), - .pwr_lo(pwr_lo), - .pwr_hi(pwr_hi), - .pwr_oe1(pwr_oe1), - .pwr_oe2(pwr_oe2), - .pwr_oe3(pwr_oe3), - .pwr_oe4(pwr_oe4), - .adc_d(adc_d), - .adc_clk(adc_clk), - .ssp_frame(ssp_frame), - .ssp_din(ssp_din), - .ssp_dout(ssp_dout), - .ssp_clk(ssp_clk), - .cross_hi(cross_hi), - .cross_lo(cross_lo), - .dbg(dbg), - .shallow_modulation(shallow_modulation) - ); + hi_read_tx #(5,200) dut( + .pck0(pck0), + .ck_1356meg(ck_1356meg), + .ck_1356megb(ck_1356megb), + .pwr_lo(pwr_lo), + .pwr_hi(pwr_hi), + .pwr_oe1(pwr_oe1), + .pwr_oe2(pwr_oe2), + .pwr_oe3(pwr_oe3), + .pwr_oe4(pwr_oe4), + .adc_d(adc_d), + .adc_clk(adc_clk), + .ssp_frame(ssp_frame), + .ssp_din(ssp_din), + .ssp_dout(ssp_dout), + .ssp_clk(ssp_clk), + .cross_hi(cross_hi), + .cross_lo(cross_lo), + .dbg(dbg), + .shallow_modulation(shallow_modulation) + ); - integer idx, i; + integer idx, i; - // main clock - always #5 begin - ck_1356megb = !ck_1356megb; - ck_1356meg = ck_1356megb; - end + // main clock + always #5 begin + ck_1356megb = !ck_1356megb; + ck_1356meg = ck_1356megb; + end - //crank DUT - task crank_dut; - begin - @(posedge ssp_clk) ; - ssp_dout = $random; - end - endtask + //crank DUT + task crank_dut; + begin + @(posedge ssp_clk) ; + ssp_dout = $random; + end + endtask - initial begin + initial begin - // init inputs - ck_1356megb = 0; - adc_d = 0; - ssp_dout=0; + // init inputs + ck_1356megb = 0; + adc_d = 0; + ssp_dout=0; - // shallow modulation off - shallow_modulation=0; - for (i = 0 ; i < 16 ; i = i + 1) begin - crank_dut; - end + // shallow modulation off + shallow_modulation=0; + for (i = 0 ; i < 16 ; i = i + 1) begin + crank_dut; + end + + // shallow modulation on + shallow_modulation=1; + for (i = 0 ; i < 16 ; i = i + 1) begin + crank_dut; + end + $finish; + end - // shallow modulation on - shallow_modulation=1; - for (i = 0 ; i < 16 ; i = i + 1) begin - crank_dut; - end - $finish; - end - endmodule // main diff --git a/fpga/testbed_hi_simulate.v b/fpga/testbed_hi_simulate.v index b06720165..2a2e2f799 100644 --- a/fpga/testbed_hi_simulate.v +++ b/fpga/testbed_hi_simulate.v @@ -1,116 +1,116 @@ `include "hi_simulate.v" /* - pck0 - input main 24Mhz clock (PLL / 4) - [7:0] adc_d - input data from A/D converter - mod_type - modulation type + pck0 - input main 24MHz clock (PLL / 4) + [7:0] adc_d - input data from A/D converter + mod_type - modulation type - pwr_lo - output to coil drivers (ssp_clk / 8) - adc_clk - output A/D clock signal - ssp_frame - output SSS frame indicator (goes high while the 8 bits are shifted) - ssp_din - output SSP data to ARM (shifts 8 bit A/D value serially to ARM MSB first) - ssp_clk - output SSP clock signal + pwr_lo - output to coil drivers (ssp_clk / 8) + adc_clk - output A/D clock signal + ssp_frame - output SSS frame indicator (goes high while the 8 bits are shifted) + ssp_din - output SSP data to ARM (shifts 8 bit A/D value serially to ARM MSB first) + ssp_clk - output SSP clock signal - ck_1356meg - input unused - ck_1356megb - input unused - ssp_dout - input unused - cross_hi - input unused - cross_lo - input unused + ck_1356meg - input unused + ck_1356megb - input unused + ssp_dout - input unused + cross_hi - input unused + cross_lo - input unused - pwr_hi - output unused, tied low - pwr_oe1 - output unused, undefined - pwr_oe2 - output unused, undefined - pwr_oe3 - output unused, undefined - pwr_oe4 - output unused, undefined - dbg - output alias for adc_clk + pwr_hi - output unused, tied low + pwr_oe1 - output unused, undefined + pwr_oe2 - output unused, undefined + pwr_oe3 - output unused, undefined + pwr_oe4 - output unused, undefined + dbg - output alias for adc_clk */ module testbed_hi_simulate; - reg pck0; - reg [7:0] adc_d; - reg mod_type; + reg pck0; + reg [7:0] adc_d; + reg mod_type; - wire pwr_lo; - wire adc_clk; - reg ck_1356meg; - reg ck_1356megb; - wire ssp_frame; - wire ssp_din; - wire ssp_clk; - reg ssp_dout; - wire pwr_hi; - wire pwr_oe1; - wire pwr_oe2; - wire pwr_oe3; - wire pwr_oe4; - wire cross_lo; - wire cross_hi; - wire dbg; + wire pwr_lo; + wire adc_clk; + reg ck_1356meg; + reg ck_1356megb; + wire ssp_frame; + wire ssp_din; + wire ssp_clk; + reg ssp_dout; + wire pwr_hi; + wire pwr_oe1; + wire pwr_oe2; + wire pwr_oe3; + wire pwr_oe4; + wire cross_lo; + wire cross_hi; + wire dbg; - hi_simulate #(5,200) dut( - .pck0(pck0), - .ck_1356meg(ck_1356meg), - .ck_1356megb(ck_1356megb), - .pwr_lo(pwr_lo), - .pwr_hi(pwr_hi), - .pwr_oe1(pwr_oe1), - .pwr_oe2(pwr_oe2), - .pwr_oe3(pwr_oe3), - .pwr_oe4(pwr_oe4), - .adc_d(adc_d), - .adc_clk(adc_clk), - .ssp_frame(ssp_frame), - .ssp_din(ssp_din), - .ssp_dout(ssp_dout), - .ssp_clk(ssp_clk), - .cross_hi(cross_hi), - .cross_lo(cross_lo), - .dbg(dbg), - .mod_type(mod_type) - ); + hi_simulate #(5,200) dut( + .pck0(pck0), + .ck_1356meg(ck_1356meg), + .ck_1356megb(ck_1356megb), + .pwr_lo(pwr_lo), + .pwr_hi(pwr_hi), + .pwr_oe1(pwr_oe1), + .pwr_oe2(pwr_oe2), + .pwr_oe3(pwr_oe3), + .pwr_oe4(pwr_oe4), + .adc_d(adc_d), + .adc_clk(adc_clk), + .ssp_frame(ssp_frame), + .ssp_din(ssp_din), + .ssp_dout(ssp_dout), + .ssp_clk(ssp_clk), + .cross_hi(cross_hi), + .cross_lo(cross_lo), + .dbg(dbg), + .mod_type(mod_type) + ); - integer idx, i; + integer idx, i; - // main clock - always #5 begin - ck_1356megb = !ck_1356megb; - ck_1356meg = ck_1356megb; - end + // main clock + always #5 begin + ck_1356megb = !ck_1356megb; + ck_1356meg = ck_1356megb; + end - always begin - @(negedge adc_clk) ; - adc_d = $random; - end + always begin + @(negedge adc_clk) ; + adc_d = $random; + end - //crank DUT - task crank_dut; - begin - @(negedge ssp_clk) ; - ssp_dout = $random; - end - endtask + //crank DUT + task crank_dut; + begin + @(negedge ssp_clk) ; + ssp_dout = $random; + end + endtask - initial begin + initial begin - // init inputs - ck_1356megb = 0; - // random values - adc_d = 0; - ssp_dout=1; + // init inputs + ck_1356megb = 0; + // random values + adc_d = 0; + ssp_dout=1; - // shallow modulation off - mod_type=0; - for (i = 0 ; i < 16 ; i = i + 1) begin - crank_dut; - end + // shallow modulation off + mod_type=0; + for (i = 0 ; i < 16 ; i = i + 1) begin + crank_dut; + end + + // shallow modulation on + mod_type=1; + for (i = 0 ; i < 16 ; i = i + 1) begin + crank_dut; + end + $finish; + end - // shallow modulation on - mod_type=1; - for (i = 0 ; i < 16 ; i = i + 1) begin - crank_dut; - end - $finish; - end - endmodule // main diff --git a/fpga/testbed_lo_read.v b/fpga/testbed_lo_read.v index 370ed389e..0536a403f 100644 --- a/fpga/testbed_lo_read.v +++ b/fpga/testbed_lo_read.v @@ -1,101 +1,101 @@ `include "lo_read.v" /* - pck0 - input main 24Mhz clock (PLL / 4) - [7:0] adc_d - input data from A/D converter - lo_is_125khz - input freq selector (1=125Khz, 0=136Khz) + pck0 - input main 24MHz clock (PLL / 4) + [7:0] adc_d - input data from A/D converter + lo_is_125khz - input freq selector (1=125kHz, 0=136kHz) - pwr_lo - output to coil drivers (ssp_clk / 8) - adc_clk - output A/D clock signal - ssp_frame - output SSS frame indicator (goes high while the 8 bits are shifted) - ssp_din - output SSP data to ARM (shifts 8 bit A/D value serially to ARM MSB first) - ssp_clk - output SSP clock signal 1Mhz/1.09Mhz (pck0 / 2*(11+lo_is_125khz) ) + pwr_lo - output to coil drivers (ssp_clk / 8) + adc_clk - output A/D clock signal + ssp_frame - output SSS frame indicator (goes high while the 8 bits are shifted) + ssp_din - output SSP data to ARM (shifts 8 bit A/D value serially to ARM MSB first) + ssp_clk - output SSP clock signal 1MHz/1.09MHz (pck0 / 2*(11+lo_is_125khz) ) - ck_1356meg - input unused - ck_1356megb - input unused - ssp_dout - input unused - cross_hi - input unused - cross_lo - input unused + ck_1356meg - input unused + ck_1356megb - input unused + ssp_dout - input unused + cross_hi - input unused + cross_lo - input unused - pwr_hi - output unused, tied low - pwr_oe1 - output unused, undefined - pwr_oe2 - output unused, undefined - pwr_oe3 - output unused, undefined - pwr_oe4 - output unused, undefined - dbg - output alias for adc_clk + pwr_hi - output unused, tied low + pwr_oe1 - output unused, undefined + pwr_oe2 - output unused, undefined + pwr_oe3 - output unused, undefined + pwr_oe4 - output unused, undefined + dbg - output alias for adc_clk */ module testbed_lo_read; - reg pck0; - reg [7:0] adc_d; - reg lo_is_125khz; - reg [15:0] divisor; + reg pck0; + reg [7:0] adc_d; + reg lo_is_125khz; + reg [15:0] divisor; - wire pwr_lo; - wire adc_clk; - wire ck_1356meg; - wire ck_1356megb; - wire ssp_frame; - wire ssp_din; - wire ssp_clk; - reg ssp_dout; - wire pwr_hi; - wire pwr_oe1; - wire pwr_oe2; - wire pwr_oe3; - wire pwr_oe4; - wire cross_lo; - wire cross_hi; - wire dbg; + wire pwr_lo; + wire adc_clk; + wire ck_1356meg; + wire ck_1356megb; + wire ssp_frame; + wire ssp_din; + wire ssp_clk; + reg ssp_dout; + wire pwr_hi; + wire pwr_oe1; + wire pwr_oe2; + wire pwr_oe3; + wire pwr_oe4; + wire cross_lo; + wire cross_hi; + wire dbg; - lo_read #(5,10) dut( - .pck0(pck0), - .ck_1356meg(ck_1356meg), - .ck_1356megb(ck_1356megb), - .pwr_lo(pwr_lo), - .pwr_hi(pwr_hi), - .pwr_oe1(pwr_oe1), - .pwr_oe2(pwr_oe2), - .pwr_oe3(pwr_oe3), - .pwr_oe4(pwr_oe4), - .adc_d(adc_d), - .adc_clk(adc_clk), - .ssp_frame(ssp_frame), - .ssp_din(ssp_din), - .ssp_dout(ssp_dout), - .ssp_clk(ssp_clk), - .cross_hi(cross_hi), - .cross_lo(cross_lo), - .dbg(dbg), - .lo_is_125khz(lo_is_125khz), - .divisor(divisor) - ); + lo_read #(5,10) dut( + .pck0(pck0), + .ck_1356meg(ck_1356meg), + .ck_1356megb(ck_1356megb), + .pwr_lo(pwr_lo), + .pwr_hi(pwr_hi), + .pwr_oe1(pwr_oe1), + .pwr_oe2(pwr_oe2), + .pwr_oe3(pwr_oe3), + .pwr_oe4(pwr_oe4), + .adc_d(adc_d), + .adc_clk(adc_clk), + .ssp_frame(ssp_frame), + .ssp_din(ssp_din), + .ssp_dout(ssp_dout), + .ssp_clk(ssp_clk), + .cross_hi(cross_hi), + .cross_lo(cross_lo), + .dbg(dbg), + .lo_is_125khz(lo_is_125khz), + .divisor(divisor) + ); - integer idx, i, adc_val=8; + integer idx, i, adc_val=8; - // main clock - always #5 pck0 = !pck0; + // main clock + always #5 pck0 = !pck0; - task crank_dut; - begin - @(posedge adc_clk) ; - adc_d = adc_val; - adc_val = (adc_val *2) + 53; - end - endtask + task crank_dut; + begin + @(posedge adc_clk) ; + adc_d = adc_val; + adc_val = (adc_val *2) + 53; + end + endtask - initial begin + initial begin - // init inputs - pck0 = 0; - adc_d = 0; - ssp_dout = 0; - lo_is_125khz = 1; - divisor = 255; //min 16, 95=125Khz, max 255 + // init inputs + pck0 = 0; + adc_d = 0; + ssp_dout = 0; + lo_is_125khz = 1; + divisor = 255; //min 16, 95=125kHz, max 255 - // simulate 4 A/D cycles at 125Khz - for (i = 0 ; i < 8 ; i = i + 1) begin - crank_dut; - end - $finish; - end + // simulate 4 A/D cycles at 125kHz + for (i = 0 ; i < 8 ; i = i + 1) begin + crank_dut; + end + $finish; + end endmodule // main diff --git a/fpga/testbed_lo_simulate.v b/fpga/testbed_lo_simulate.v index 70b6331f9..ec4bb73fe 100644 --- a/fpga/testbed_lo_simulate.v +++ b/fpga/testbed_lo_simulate.v @@ -1,101 +1,101 @@ `include "lo_simulate.v" /* - pck0 - input main 24Mhz clock (PLL / 4) - [7:0] adc_d - input data from A/D converter + pck0 - input main 24MHz clock (PLL / 4) + [7:0] adc_d - input data from A/D converter - pwr_lo - output to coil drivers (ssp_clk / 8) - adc_clk - output A/D clock signal - ssp_frame - output SSS frame indicator (goes high while the 8 bits are shifted) - ssp_din - output SSP data to ARM (shifts 8 bit A/D value serially to ARM MSB first) - ssp_clk - output SSP clock signal + pwr_lo - output to coil drivers (ssp_clk / 8) + adc_clk - output A/D clock signal + ssp_frame - output SSS frame indicator (goes high while the 8 bits are shifted) + ssp_din - output SSP data to ARM (shifts 8 bit A/D value serially to ARM MSB first) + ssp_clk - output SSP clock signal - ck_1356meg - input unused - ck_1356megb - input unused - ssp_dout - input unused - cross_hi - input unused - cross_lo - input unused + ck_1356meg - input unused + ck_1356megb - input unused + ssp_dout - input unused + cross_hi - input unused + cross_lo - input unused - pwr_hi - output unused, tied low - pwr_oe1 - output unused, undefined - pwr_oe2 - output unused, undefined - pwr_oe3 - output unused, undefined - pwr_oe4 - output unused, undefined - dbg - output alias for adc_clk + pwr_hi - output unused, tied low + pwr_oe1 - output unused, undefined + pwr_oe2 - output unused, undefined + pwr_oe3 - output unused, undefined + pwr_oe4 - output unused, undefined + dbg - output alias for adc_clk */ module testbed_lo_simulate; - reg pck0; - reg [7:0] adc_d; + reg pck0; + reg [7:0] adc_d; - wire pwr_lo; - wire adc_clk; - wire ck_1356meg; - wire ck_1356megb; - wire ssp_frame; - wire ssp_din; - wire ssp_clk; - reg ssp_dout; - wire pwr_hi; - wire pwr_oe1; - wire pwr_oe2; - wire pwr_oe3; - wire pwr_oe4; - reg cross_lo; - wire cross_hi; - wire dbg; + wire pwr_lo; + wire adc_clk; + wire ck_1356meg; + wire ck_1356megb; + wire ssp_frame; + wire ssp_din; + wire ssp_clk; + reg ssp_dout; + wire pwr_hi; + wire pwr_oe1; + wire pwr_oe2; + wire pwr_oe3; + wire pwr_oe4; + reg cross_lo; + wire cross_hi; + wire dbg; - lo_simulate #(5,200) dut( - .pck0(pck0), - .ck_1356meg(ck_1356meg), - .ck_1356megb(ck_1356megb), - .pwr_lo(pwr_lo), - .pwr_hi(pwr_hi), - .pwr_oe1(pwr_oe1), - .pwr_oe2(pwr_oe2), - .pwr_oe3(pwr_oe3), - .pwr_oe4(pwr_oe4), - .adc_d(adc_d), - .adc_clk(adc_clk), - .ssp_frame(ssp_frame), - .ssp_din(ssp_din), - .ssp_dout(ssp_dout), - .ssp_clk(ssp_clk), - .cross_hi(cross_hi), - .cross_lo(cross_lo), - .dbg(dbg) - ); + lo_simulate #(5,200) dut( + .pck0(pck0), + .ck_1356meg(ck_1356meg), + .ck_1356megb(ck_1356megb), + .pwr_lo(pwr_lo), + .pwr_hi(pwr_hi), + .pwr_oe1(pwr_oe1), + .pwr_oe2(pwr_oe2), + .pwr_oe3(pwr_oe3), + .pwr_oe4(pwr_oe4), + .adc_d(adc_d), + .adc_clk(adc_clk), + .ssp_frame(ssp_frame), + .ssp_din(ssp_din), + .ssp_dout(ssp_dout), + .ssp_clk(ssp_clk), + .cross_hi(cross_hi), + .cross_lo(cross_lo), + .dbg(dbg) + ); - integer i, counter=0; + integer i, counter=0; - // main clock - always #5 pck0 = !pck0; + // main clock + always #5 pck0 = !pck0; - //cross_lo is not really synced to pck0 but it's roughly pck0/192 (24Mhz/192=125Khz) - task crank_dut; - begin - @(posedge pck0) ; - counter = counter + 1; - if (counter == 192) begin - counter = 0; - ssp_dout = $random; - cross_lo = 1; - end else begin - cross_lo = 0; - end - - end - endtask + //cross_lo is not really synced to pck0 but it's roughly pck0/192 (24MHz/192=125kHz) + task crank_dut; + begin + @(posedge pck0) ; + counter = counter + 1; + if (counter == 192) begin + counter = 0; + ssp_dout = $random; + cross_lo = 1; + end else begin + cross_lo = 0; + end - initial begin - pck0 = 0; - for (i = 0 ; i < 4096 ; i = i + 1) begin - crank_dut; - end - $finish; - end + end + endtask + + initial begin + pck0 = 0; + for (i = 0 ; i < 4096 ; i = i + 1) begin + crank_dut; + end + $finish; + end endmodule // main diff --git a/fpga/tests/Makefile b/fpga/tests/Makefile index 79ed20816..f2ae6d729 100644 --- a/fpga/tests/Makefile +++ b/fpga/tests/Makefile @@ -5,7 +5,7 @@ # at your option, any later version. See the LICENSE.txt file for the text of # the license. #----------------------------------------------------------------------------- - +MKDIR = mkdir -p TEST_OUTDIR = tb_tmp TB_SOURCES = \ @@ -62,7 +62,7 @@ tb_lf_edge_detect: tb_lf_edge_detect.vvp | test_dir rm -f $(TEST_OUTDIR)/data.* test_dir: - @if [ ! -d $(TEST_OUTDIR) ] ; then mkdir $(TEST_OUTDIR) ; fi + @if [ ! -d $(TEST_OUTDIR) ] ; then $(MKDIR) $(TEST_OUTDIR) ; fi .PHONY: all clean diff --git a/fpga/tests/tb_lf_edge_detect.v b/fpga/tests/tb_lf_edge_detect.v index a9fccf8bd..f2a373be9 100644 --- a/fpga/tests/tb_lf_edge_detect.v +++ b/fpga/tests/tb_lf_edge_detect.v @@ -20,16 +20,16 @@ module lf_edge_detect_tb; - integer fin, fout_state, fout_toggle; - integer fout_high, fout_highz, fout_lowz, fout_low, fout_min, fout_max; - integer r; + integer fin, fout_state, fout_toggle; + integer fout_high, fout_highz, fout_lowz, fout_low, fout_min, fout_max; + integer r; - reg clk = 0; - reg [7:0] adc_d; - wire adc_clk; - wire data_rdy; - wire edge_state; - wire edge_toggle; + reg clk = 0; + reg [7:0] adc_d; + wire adc_clk; + wire data_rdy; + wire edge_state; + wire edge_toggle; wire [7:0] high_threshold; wire [7:0] highz_threshold; @@ -38,74 +38,74 @@ module lf_edge_detect_tb; wire [7:0] max; wire [7:0] min; - initial - begin - clk = 0; - fin = $fopen(`FIN, "r"); - if (!fin) begin - $display("ERROR: can't open the data file"); - $finish; - end - fout_min = $fopen(`FOUT_MIN, "w+"); - fout_max = $fopen(`FOUT_MAX, "w+"); - fout_state = $fopen(`FOUT_STATE, "w+"); - fout_toggle = $fopen(`FOUT_TOGGLE, "w+"); - fout_high = $fopen(`FOUT_HIGH, "w+"); - fout_highz = $fopen(`FOUT_HIGHZ, "w+"); - fout_lowz = $fopen(`FOUT_LOWZ, "w+"); - fout_low = $fopen(`FOUT_LOW, "w+"); - if (!$feof(fin)) - adc_d = $fgetc(fin); // read the first value - end + initial + begin + clk = 0; + fin = $fopen(`FIN, "r"); + if (!fin) begin + $display("ERROR: can't open the data file"); + $finish; + end + fout_min = $fopen(`FOUT_MIN, "w+"); + fout_max = $fopen(`FOUT_MAX, "w+"); + fout_state = $fopen(`FOUT_STATE, "w+"); + fout_toggle = $fopen(`FOUT_TOGGLE, "w+"); + fout_high = $fopen(`FOUT_HIGH, "w+"); + fout_highz = $fopen(`FOUT_HIGHZ, "w+"); + fout_lowz = $fopen(`FOUT_LOWZ, "w+"); + fout_low = $fopen(`FOUT_LOW, "w+"); + if (!$feof(fin)) + adc_d = $fgetc(fin); // read the first value + end - always - # 1 clk = !clk; + always + # 1 clk = !clk; - // input - initial - begin - while (!$feof(fin)) begin - @(negedge clk) adc_d <= $fgetc(fin); - end + // input + initial + begin + while (!$feof(fin)) begin + @(negedge clk) adc_d <= $fgetc(fin); + end - if ($feof(fin)) - begin - # 3 $fclose(fin); - $fclose(fout_state); - $fclose(fout_toggle); - $fclose(fout_high); - $fclose(fout_highz); - $fclose(fout_lowz); - $fclose(fout_low); - $fclose(fout_min); - $fclose(fout_max); - $finish; - end - end + if ($feof(fin)) + begin + # 3 $fclose(fin); + $fclose(fout_state); + $fclose(fout_toggle); + $fclose(fout_high); + $fclose(fout_highz); + $fclose(fout_lowz); + $fclose(fout_low); + $fclose(fout_min); + $fclose(fout_max); + $finish; + end + end - initial - begin - // $monitor("%d\t S: %b, E: %b", $time, edge_state, edge_toggle); - end + initial + begin + // $monitor("%d\t S: %b, E: %b", $time, edge_state, edge_toggle); + end - // output - always @(negedge clk) - if ($time > 2) begin - r = $fputc(min, fout_min); - r = $fputc(max, fout_max); - r = $fputc(edge_state, fout_state); - r = $fputc(edge_toggle, fout_toggle); - r = $fputc(high_threshold, fout_high); - r = $fputc(highz_threshold, fout_highz); - r = $fputc(lowz_threshold, fout_lowz); - r = $fputc(low_threshold, fout_low); - end + // output + always @(negedge clk) + if ($time > 2) begin + r = $fputc(min, fout_min); + r = $fputc(max, fout_max); + r = $fputc(edge_state, fout_state); + r = $fputc(edge_toggle, fout_toggle); + r = $fputc(high_threshold, fout_high); + r = $fputc(highz_threshold, fout_highz); + r = $fputc(lowz_threshold, fout_lowz); + r = $fputc(low_threshold, fout_low); + end - // module to test - lf_edge_detect detect(clk, adc_d, 8'd127, - max, min, - high_threshold, highz_threshold, - lowz_threshold, low_threshold, - edge_state, edge_toggle); + // module to test + lf_edge_detect detect(clk, adc_d, 8'd127, + max, min, + high_threshold, highz_threshold, + lowz_threshold, low_threshold, + edge_state, edge_toggle); -endmodule \ No newline at end of file +endmodule diff --git a/fpga/tests/tb_lp20khz_1MSa_iir_filter.v b/fpga/tests/tb_lp20khz_1MSa_iir_filter.v index ad0cfc6e6..e78c475e1 100644 --- a/fpga/tests/tb_lp20khz_1MSa_iir_filter.v +++ b/fpga/tests/tb_lp20khz_1MSa_iir_filter.v @@ -13,43 +13,43 @@ module lp20khz_1MSa_iir_filter_tb; - integer fin, fout, r; + integer fin, fout, r; - reg clk; - reg [7:0] adc_d; - wire data_rdy; - wire [7:0] adc_filtered; + reg clk; + reg [7:0] adc_d; + wire data_rdy; + wire [7:0] adc_filtered; - initial - begin - clk = 0; - fin = $fopen(`FIN, "r"); - if (!fin) begin - $display("ERROR: can't open the data file"); - $finish; - end - fout = $fopen(`FOUT, "w+"); - if (!$feof(fin)) - adc_d = $fgetc(fin); // read the first value - end + initial + begin + clk = 0; + fin = $fopen(`FIN, "r"); + if (!fin) begin + $display("ERROR: can't open the data file"); + $finish; + end + fout = $fopen(`FOUT, "w+"); + if (!$feof(fin)) + adc_d = $fgetc(fin); // read the first value + end - always - # 1 clk = !clk; + always + # 1 clk = !clk; - always @(posedge clk) - if (data_rdy) begin - if ($time > 1) - r = $fputc(adc_filtered, fout); - if (!$feof(fin)) - adc_d <= $fgetc(fin); - else begin - $fclose(fin); - $fclose(fout); - $finish; - end - end + always @(posedge clk) + if (data_rdy) begin + if ($time > 1) + r = $fputc(adc_filtered, fout); + if (!$feof(fin)) + adc_d <= $fgetc(fin); + else begin + $fclose(fin); + $fclose(fout); + $finish; + end + end - // module to test - lp20khz_1MSa_iir_filter filter(clk, adc_d, data_rdy, adc_filtered); + // module to test + lp20khz_1MSa_iir_filter filter(clk, adc_d, data_rdy, adc_filtered); endmodule diff --git a/fpga/tests/tb_min_max_tracker.v b/fpga/tests/tb_min_max_tracker.v index 4cccc3f1d..3bec6c7da 100644 --- a/fpga/tests/tb_min_max_tracker.v +++ b/fpga/tests/tb_min_max_tracker.v @@ -14,61 +14,61 @@ module min_max_tracker_tb; - integer fin; - integer fout_min, fout_max; - integer r; + integer fin; + integer fout_min, fout_max; + integer r; - reg clk; - reg [7:0] adc_d; - wire [7:0] min; - wire [7:0] max; + reg clk; + reg [7:0] adc_d; + wire [7:0] min; + wire [7:0] max; - initial - begin - clk = 0; - fin = $fopen(`FIN, "r"); - if (!fin) begin - $display("ERROR: can't open the data file"); - $finish; - end - fout_min = $fopen(`FOUT_MIN, "w+"); - fout_max = $fopen(`FOUT_MAX, "w+"); - if (!$feof(fin)) - adc_d = $fgetc(fin); // read the first value - end + initial + begin + clk = 0; + fin = $fopen(`FIN, "r"); + if (!fin) begin + $display("ERROR: can't open the data file"); + $finish; + end + fout_min = $fopen(`FOUT_MIN, "w+"); + fout_max = $fopen(`FOUT_MAX, "w+"); + if (!$feof(fin)) + adc_d = $fgetc(fin); // read the first value + end - always - # 1 clk = !clk; + always + # 1 clk = !clk; - // input - initial - begin - while (!$feof(fin)) begin - @(negedge clk) adc_d <= $fgetc(fin); - end + // input + initial + begin + while (!$feof(fin)) begin + @(negedge clk) adc_d <= $fgetc(fin); + end - if ($feof(fin)) - begin - # 3 $fclose(fin); - $fclose(fout_min); - $fclose(fout_max); - $finish; - end - end + if ($feof(fin)) + begin + # 3 $fclose(fin); + $fclose(fout_min); + $fclose(fout_max); + $finish; + end + end - initial - begin - // $monitor("%d\t min: %x, max: %x", $time, min, max); - end + initial + begin + // $monitor("%d\t min: %x, max: %x", $time, min, max); + end - // output - always @(negedge clk) - if ($time > 2) begin - r = $fputc(min, fout_min); - r = $fputc(max, fout_max); - end + // output + always @(negedge clk) + if ($time > 2) begin + r = $fputc(min, fout_min); + r = $fputc(max, fout_max); + end - // module to test - min_max_tracker tracker(clk, adc_d, 8'd127, min, max); + // module to test + min_max_tracker tracker(clk, adc_d, 8'd127, min, max); -endmodule \ No newline at end of file +endmodule diff --git a/include/ansi.h b/include/ansi.h new file mode 100644 index 000000000..49bd46039 --- /dev/null +++ b/include/ansi.h @@ -0,0 +1,14 @@ +#ifndef __ANSI_H +#define __ANSI_H + +#define AEND "\x1b[0m " + +#define _BLUE_(s) "\x1b[34m" s AEND +#define _RED_(s) "\x1b[31m" s AEND +#define _GREEN_(s) "\x1b[32m" s AEND +#define _YELLOW_(s) "\x1b[33m" s AEND +#define _MAGENTA_(s) "\x1b[35m" s AEND +#define _CYAN_(s) "\x1b[36m" s AEND +#define _WHITE_(s) "\x1b[37m" s AEND + +#endif diff --git a/include/common.h b/include/common.h index dec2261ec..627846ff2 100644 --- a/include/common.h +++ b/include/common.h @@ -12,26 +12,29 @@ #ifndef __COMMON_H #define __COMMON_H -#ifdef __cplusplus -extern "C" { -#endif - +#include #include -#include #include -typedef unsigned char byte_t; +#define PATHSEP "/" +// PM3 share path relative to executable when installed +#define PM3_SHARE_RELPATH ".." PATHSEP "share" PATHSEP "proxmark3" PATHSEP + +// PM3_USER_DIRECTORY will be expanded from $HOME, e.g. ~/.proxmark3/ +#define PM3_USER_DIRECTORY PATHSEP ".proxmark3" PATHSEP + +// PM3 subdirectories: +#define CMD_SCRIPTS_SUBDIR "cmdscripts" PATHSEP +#define DICTIONARIES_SUBDIR "dictionaries" PATHSEP +#define LUA_LIBRARIES_SUBDIR "lualibs" PATHSEP +#define LUA_SCRIPTS_SUBDIR "luascripts" PATHSEP +#define RESOURCES_SUBDIR "resources" PATHSEP +#define TRACES_SUBDIR "traces" PATHSEP +#define FIRMWARES_SUBDIR "firmware" PATHSEP +#define BOOTROM_SUBDIR "bootrom/obj" PATHSEP +#define FULLIMAGE_SUBDIR "armsrc/obj" PATHSEP -#ifdef _MSC_VER -typedef DWORD uint32_t; -typedef BYTE uint8_t; -#define PACKED -// stuff -#else -#include -#include #define PACKED __attribute__((packed)) -#endif // debug #define DBG_NONE 0 // no messages @@ -138,7 +141,4 @@ extern int DBGLEVEL; # define DEC2BCD(dec) HornerScheme(dec, 10, 0x10) #endif -#ifdef __cplusplus -} -#endif #endif diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index be5d75b21..e87e8bc33 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -118,7 +118,7 @@ typedef struct { bool averaging; int divisor; int trigger_threshold; -} sample_config; +} PACKED sample_config; /* typedef struct { uint16_t start_gap; @@ -131,20 +131,20 @@ typedef struct { // Extended to support 1 of 4 timing typedef struct { - uint16_t start_gap ; - uint16_t write_gap ; - uint16_t write_0 ; - uint16_t write_1 ; - uint16_t read_gap ; - uint16_t write_2 ; - uint16_t write_3 ; - + uint16_t start_gap; + uint16_t write_gap; + uint16_t write_0; + uint16_t write_1; + uint16_t read_gap; + uint16_t write_2; + uint16_t write_3; } t55xx_config_t; + // This setup will allow for the 4 downlink modes "m" as well as other items if needed. // Given the one struct we can then read/write to flash/client in one go. typedef struct { t55xx_config_t m[4]; // mode -} t55xx_config; +} t55xx_configurations_t; /*typedef struct { uint16_t start_gap [4]; @@ -178,6 +178,7 @@ typedef struct { bool compiled_with_felica : 1; bool compiled_with_legicrf : 1; bool compiled_with_iclass : 1; + bool compiled_with_nfcbarcode : 1; // misc bool compiled_with_lcd : 1; @@ -185,10 +186,10 @@ typedef struct { bool hw_available_flash : 1; bool hw_available_smartcard : 1; } PACKED capabilities_t; -#define CAPABILITIES_VERSION 2 +#define CAPABILITIES_VERSION 3 extern capabilities_t pm3_capabilities; -// For CMD_T55XX_WRITE_BLOCK +// For CMD_LF_T55XX_WRITEBL typedef struct { uint32_t data; uint32_t pwd; @@ -196,7 +197,7 @@ typedef struct { uint8_t flags; } PACKED t55xx_write_block_t; -// For CMD_FSK_SIM_TAG (FSK) +// For CMD_LF_FSK_SIMULATE (FSK) typedef struct { uint8_t fchigh; uint8_t fclow; @@ -205,7 +206,7 @@ typedef struct { uint8_t data[]; } PACKED lf_fsksim_t; -// For CMD_ASK_SIM_TAG (ASK) +// For CMD_LF_ASK_SIMULATE (ASK) typedef struct { uint8_t encoding; uint8_t invert; @@ -214,7 +215,7 @@ typedef struct { uint8_t data[]; } PACKED lf_asksim_t; -// For CMD_PSK_SIM_TAG (PSK) +// For CMD_LF_PSK_SIMULATE (PSK) typedef struct { uint8_t carrier; uint8_t invert; @@ -228,6 +229,10 @@ typedef struct { uint8_t key[6]; } PACKED mf_readblock_t; +typedef struct { + uint8_t sectorcnt; + uint8_t keytype; +} PACKED mfc_eload_t; // For the bootloader #define CMD_DEVICE_INFO 0x0000 @@ -257,6 +262,7 @@ typedef struct { #define CMD_QUIT_SESSION 0x0113 #define CMD_SET_DBGMODE 0x0114 #define CMD_STANDALONE 0x0115 +#define CMD_WTX 0x0116 // RDV40, Flash memory operations #define CMD_FLASHMEM_WRITE 0x0121 @@ -297,6 +303,7 @@ typedef struct { #define CMD_SPIFFS_PRINT_FSINFO 0x2133 #define CMD_SPIFFS_DOWNLOAD 0x2134 #define CMD_SPIFFS_DOWNLOADED 0x2135 +#define CMD_SPIFFS_CHECK 0x3000 // more ? @@ -315,184 +322,171 @@ typedef struct { #define CMD_USART_CONFIG 0x0163 // For low-frequency tags -#define CMD_READ_TI_TYPE 0x0202 -#define CMD_WRITE_TI_TYPE 0x0203 -#define CMD_DOWNLOADED_RAW_BITS_TI_TYPE 0x0204 -#define CMD_ACQUIRE_RAW_ADC_SAMPLES_125K 0x0205 -#define CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K 0x0206 +#define CMD_LF_TI_READ 0x0202 +#define CMD_LF_TI_WRITE 0x0203 +#define CMD_LF_ACQ_RAW_ADC 0x0205 +#define CMD_LF_MOD_THEN_ACQ_RAW_ADC 0x0206 #define CMD_DOWNLOAD_BIGBUF 0x0207 #define CMD_DOWNLOADED_BIGBUF 0x0208 -#define CMD_UPLOAD_SIM_SAMPLES_125K 0x0209 -#define CMD_SIMULATE_TAG_125K 0x020A -#define CMD_HID_DEMOD_FSK 0x020B -#define CMD_HID_SIM_TAG 0x020C -#define CMD_SET_LF_DIVISOR 0x020D +#define CMD_LF_UPLOAD_SIM_SAMPLES 0x0209 +#define CMD_LF_SIMULATE 0x020A +#define CMD_LF_HID_DEMOD 0x020B +#define CMD_LF_HID_SIMULATE 0x020C +#define CMD_LF_SET_DIVISOR 0x020D #define CMD_LF_SIMULATE_BIDIR 0x020E #define CMD_SET_ADC_MUX 0x020F -#define CMD_HID_CLONE_TAG 0x0210 -#define CMD_EM410X_WRITE_TAG 0x0211 -#define CMD_INDALA_CLONE_TAG 0x0212 +#define CMD_LF_HID_CLONE 0x0210 +#define CMD_LF_EM410X_WRITE 0x0211 +#define CMD_LF_INDALA_CLONE 0x0212 // for 224 bits UID -#define CMD_INDALA_CLONE_TAG_L 0x0213 -#define CMD_T55XX_READ_BLOCK 0x0214 -#define CMD_T55XX_WRITE_BLOCK 0x0215 -#define CMD_T55XX_RESET_READ 0x0216 -#define CMD_PCF7931_READ 0x0217 -#define CMD_PCF7931_WRITE 0x0223 -#define CMD_EM4X_READ_WORD 0x0218 -#define CMD_EM4X_WRITE_WORD 0x0219 -#define CMD_IO_DEMOD_FSK 0x021A -#define CMD_IO_CLONE_TAG 0x021B -#define CMD_EM410X_DEMOD 0x021c +#define CMD_LF_INDALA224_CLONE 0x0213 +#define CMD_LF_T55XX_READBL 0x0214 +#define CMD_LF_T55XX_WRITEBL 0x0215 +#define CMD_LF_T55XX_RESET_READ 0x0216 +#define CMD_LF_PCF7931_READ 0x0217 +#define CMD_LF_PCF7931_WRITE 0x0223 +#define CMD_LF_EM4X_READWORD 0x0218 +#define CMD_LF_EM4X_WRITEWORD 0x0219 +#define CMD_LF_IO_DEMOD 0x021A +#define CMD_LF_IO_CLONE 0x021B +#define CMD_LF_EM410X_DEMOD 0x021c // Sampling configuration for LF reader/sniffer -#define CMD_SET_LF_SAMPLING_CONFIG 0x021d -#define CMD_FSK_SIM_TAG 0x021E -#define CMD_ASK_SIM_TAG 0x021F -#define CMD_PSK_SIM_TAG 0x0220 -#define CMD_AWID_DEMOD_FSK 0x0221 -#define CMD_VIKING_CLONE_TAG 0x0222 -#define CMD_T55XX_WAKEUP 0x0224 -#define CMD_COTAG 0x0225 -#define CMD_SET_LF_T55XX_CONFIG 0x0226 +#define CMD_LF_SAMPLING_SET_CONFIG 0x021d +#define CMD_LF_FSK_SIMULATE 0x021E +#define CMD_LF_ASK_SIMULATE 0x021F +#define CMD_LF_PSK_SIMULATE 0x0220 +#define CMD_LF_AWID_DEMOD 0x0221 +#define CMD_LF_VIKING_CLONE 0x0222 +#define CMD_LF_T55XX_WAKEUP 0x0224 +#define CMD_LF_COTAG_READ 0x0225 +#define CMD_LF_T55XX_SET_CONFIG 0x0226 -#define CMD_T55XX_CHKPWDS 0x0230 +#define CMD_LF_T55XX_CHK_PWDS 0x0230 /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ // For the 13.56 MHz tags -#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300 -#define CMD_READ_SRI_TAG 0x0303 -#define CMD_ISO_14443B_COMMAND 0x0305 -#define CMD_READER_ISO_15693 0x0310 -#define CMD_SIMTAG_ISO_15693 0x0311 -#define CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693 0x0312 -#define CMD_ISO_15693_COMMAND 0x0313 -#define CMD_ISO_15693_COMMAND_DONE 0x0314 -#define CMD_ISO_15693_FIND_AFI 0x0315 -#define CMD_LF_SNIFF_RAW_ADC_SAMPLES 0x0317 +#define CMD_HF_ISO15693_ACQ_RAW_ADC 0x0300 +#define CMD_HF_SRI_READ 0x0303 +#define CMD_HF_ISO14443B_COMMAND 0x0305 +#define CMD_HF_ISO15693_READER 0x0310 +#define CMD_HF_ISO15693_SIMULATE 0x0311 +#define CMD_HF_ISO15693_RAWADC 0x0312 +#define CMD_HF_ISO15693_COMMAND 0x0313 +#define CMD_HF_ISO15693_FINDAFI 0x0315 +#define CMD_LF_SNIFF_RAW_ADC 0x0317 // For Hitag2 transponders -#define CMD_SNIFF_HITAG 0x0370 -#define CMD_SIMULATE_HITAG 0x0371 -#define CMD_READER_HITAG 0x0372 +#define CMD_LF_HITAG_SNIFF 0x0370 +#define CMD_LF_HITAG_SIMULATE 0x0371 +#define CMD_LF_HITAG_READER 0x0372 // For HitagS -#define CMD_TEST_HITAGS_TRACES 0x0367 -#define CMD_SIMULATE_HITAG_S 0x0368 -#define CMD_READ_HITAG_S 0x0373 -#define CMD_WR_HITAG_S 0x0375 -#define CMD_EMU_HITAG_S 0x0376 +#define CMD_LF_HITAGS_TEST_TRACES 0x0367 +#define CMD_LF_HITAGS_SIMULATE 0x0368 +#define CMD_LF_HITAGS_READ 0x0373 +#define CMD_LF_HITAGS_WRITE 0x0375 -#define CMD_ANTIFUZZ_ISO_14443a 0x0380 -#define CMD_SIMULATE_TAG_ISO_14443B 0x0381 -#define CMD_SNIFF_ISO_14443B 0x0382 +#define CMD_HF_ISO14443A_ANTIFUZZ 0x0380 +#define CMD_HF_ISO14443B_SIMULATE 0x0381 +#define CMD_HF_ISO14443B_SNIFF 0x0382 -#define CMD_SNIFF_ISO_14443a 0x0383 -#define CMD_SIMULATE_TAG_ISO_14443a 0x0384 +#define CMD_HF_ISO14443A_SNIFF 0x0383 +#define CMD_HF_ISO14443A_SIMULATE 0x0384 -#define CMD_READER_ISO_14443a 0x0385 +#define CMD_HF_ISO14443A_READER 0x0385 -#define CMD_RAW_WRITER_LEGIC_RF 0x0386 -#define CMD_SIMULATE_TAG_LEGIC_RF 0x0387 -#define CMD_READER_LEGIC_RF 0x0388 -#define CMD_WRITER_LEGIC_RF 0x0389 +#define CMD_HF_LEGIC_SIMULATE 0x0387 +#define CMD_HF_LEGIC_READER 0x0388 +#define CMD_HF_LEGIC_WRITER 0x0389 -#define CMD_EPA_PACE_COLLECT_NONCE 0x038A -#define CMD_EPA_PACE_REPLAY 0x038B +#define CMD_HF_EPA_COLLECT_NONCE 0x038A +#define CMD_HF_EPA_REPLAY 0x038B -#define CMD_LEGIC_INFO 0x03BC -#define CMD_LEGIC_ESET 0x03BD -#define CMD_LEGIC_EGET 0x03BE +#define CMD_HF_LEGIC_INFO 0x03BC +#define CMD_HF_LEGIC_ESET 0x03BD -#define CMD_ICLASS_READCHECK 0x038F -#define CMD_ICLASS_CLONE 0x0390 -#define CMD_ICLASS_DUMP 0x0391 -#define CMD_SNIFF_ICLASS 0x0392 -#define CMD_SIMULATE_TAG_ICLASS 0x0393 -#define CMD_READER_ICLASS 0x0394 -#define CMD_READER_ICLASS_REPLAY 0x0395 -#define CMD_ICLASS_READBLOCK 0x0396 -#define CMD_ICLASS_WRITEBLOCK 0x0397 -#define CMD_ICLASS_EML_MEMSET 0x0398 -#define CMD_ICLASS_AUTHENTICATION 0x0399 -#define CMD_ICLASS_CHECK_KEYS 0x039A +#define CMD_HF_ICLASS_READCHECK 0x038F +#define CMD_HF_ICLASS_CLONE 0x0390 +#define CMD_HF_ICLASS_DUMP 0x0391 +#define CMD_HF_ICLASS_SNIFF 0x0392 +#define CMD_HF_ICLASS_SIMULATE 0x0393 +#define CMD_HF_ICLASS_READER 0x0394 +#define CMD_HF_ICLASS_REPLAY 0x0395 +#define CMD_HF_ICLASS_READBL 0x0396 +#define CMD_HF_ICLASS_WRITEBL 0x0397 +#define CMD_HF_ICLASS_EML_MEMSET 0x0398 +#define CMD_HF_ICLASS_AUTH 0x0399 +#define CMD_HF_ICLASS_CHKKEYS 0x039A // For ISO1092 / FeliCa -#define CMD_FELICA_SIMULATE_TAG 0x03A0 -#define CMD_FELICA_SNIFF 0x03A1 -#define CMD_FELICA_COMMAND 0x03A2 +#define CMD_HF_FELICA_SIMULATE 0x03A0 +#define CMD_HF_FELICA_SNIFF 0x03A1 +#define CMD_HF_FELICA_COMMAND 0x03A2 //temp -#define CMD_FELICA_LITE_DUMP 0x03AA -#define CMD_FELICA_LITE_SIM 0x03AB +#define CMD_HF_FELICALITE_DUMP 0x03AA +#define CMD_HF_FELICALITE_SIMULATE 0x03AB // For measurements of the antenna tuning #define CMD_MEASURE_ANTENNA_TUNING 0x0400 #define CMD_MEASURE_ANTENNA_TUNING_HF 0x0401 #define CMD_LISTEN_READER_FIELD 0x0420 +#define CMD_HF_DROPFIELD 0x0430 // For direct FPGA control #define CMD_FPGA_MAJOR_MODE_OFF 0x0500 // For mifare commands -#define CMD_MIFARE_EML_MEMCLR 0x0601 -#define CMD_MIFARE_EML_MEMSET 0x0602 -#define CMD_MIFARE_EML_MEMGET 0x0603 -#define CMD_MIFARE_EML_CARDLOAD 0x0604 +#define CMD_HF_MIFARE_EML_MEMCLR 0x0601 +#define CMD_HF_MIFARE_EML_MEMSET 0x0602 +#define CMD_HF_MIFARE_EML_MEMGET 0x0603 +#define CMD_HF_MIFARE_EML_LOAD 0x0604 // magic chinese card commands -#define CMD_MIFARE_CSETBLOCK 0x0605 -#define CMD_MIFARE_CGETBLOCK 0x0606 -#define CMD_MIFARE_CIDENT 0x0607 +#define CMD_HF_MIFARE_CSETBL 0x0605 +#define CMD_HF_MIFARE_CGETBL 0x0606 +#define CMD_HF_MIFARE_CIDENT 0x0607 -#define CMD_SIMULATE_MIFARE_CARD 0x0610 +#define CMD_HF_MIFARE_SIMULATE 0x0610 -#define CMD_READER_MIFARE 0x0611 -#define CMD_MIFARE_NESTED 0x0612 -#define CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES 0x0613 -#define CMD_MIFARE_ACQUIRE_NONCES 0x0614 +#define CMD_HF_MIFARE_READER 0x0611 +#define CMD_HF_MIFARE_NESTED 0x0612 +#define CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES 0x0613 +#define CMD_HF_MIFARE_ACQ_NONCES 0x0614 -#define CMD_MIFARE_READBL 0x0620 -#define CMD_MIFAREU_READBL 0x0720 -#define CMD_MIFARE_READSC 0x0621 -#define CMD_MIFAREU_READCARD 0x0721 -#define CMD_MIFARE_WRITEBL 0x0622 -#define CMD_MIFAREU_WRITEBL 0x0722 -#define CMD_MIFAREU_WRITEBL_COMPAT 0x0723 +#define CMD_HF_MIFARE_READBL 0x0620 +#define CMD_HF_MIFAREU_READBL 0x0720 +#define CMD_HF_MIFARE_READSC 0x0621 +#define CMD_HF_MIFAREU_READCARD 0x0721 +#define CMD_HF_MIFARE_WRITEBL 0x0622 +#define CMD_HF_MIFAREU_WRITEBL 0x0722 -#define CMD_MIFARE_CHKKEYS 0x0623 -#define CMD_MIFARE_SETMOD 0x0624 -#define CMD_MIFARE_CHKKEYS_FAST 0x0625 +#define CMD_HF_MIFARE_CHKKEYS 0x0623 +#define CMD_HF_MIFARE_SETMOD 0x0624 +#define CMD_HF_MIFARE_CHKKEYS_FAST 0x0625 -#define CMD_MIFARE_SNIFFER 0x0630 +#define CMD_HF_MIFARE_SNIFF 0x0630 //ultralightC -#define CMD_MIFAREUC_AUTH 0x0724 +#define CMD_HF_MIFAREUC_AUTH 0x0724 //0x0725 and 0x0726 no longer used -#define CMD_MIFAREUC_SETPWD 0x0727 +#define CMD_HF_MIFAREUC_SETPWD 0x0727 // mifare desfire -#define CMD_MIFARE_DESFIRE_READBL 0x0728 -#define CMD_MIFARE_DESFIRE_WRITEBL 0x0729 -#define CMD_MIFARE_DESFIRE_AUTH1 0x072a -#define CMD_MIFARE_DESFIRE_AUTH2 0x072b -#define CMD_MIFARE_DES_READER 0x072c -#define CMD_MIFARE_DESFIRE_INFO 0x072d -#define CMD_MIFARE_DESFIRE 0x072e +#define CMD_HF_DESFIRE_READBL 0x0728 +#define CMD_HF_DESFIRE_WRITEBL 0x0729 +#define CMD_HF_DESFIRE_AUTH1 0x072a +#define CMD_HF_DESFIRE_AUTH2 0x072b +#define CMD_HF_DESFIRE_READER 0x072c +#define CMD_HF_DESFIRE_INFO 0x072d +#define CMD_HF_DESFIRE_COMMAND 0x072e -#define CMD_MIFARE_COLLECT_NONCES 0x072f -#define CMD_MIFARE_NACK_DETECT 0x0730 +#define CMD_HF_MIFARE_NACK_DETECT 0x0730 -#define CMD_HF_SNIFFER 0x0800 +#define CMD_HF_SNIFF 0x0800 -// For EMV Commands -#define CMD_EMV_READ_RECORD 0x0700 -#define CMD_EMV_TRANSACTION 0x0701 -#define CMD_EMV_CLONE 0x0702 -#define CMD_EMV_SIM 0x0703 -#define CMD_EMV_TEST 0x0704 -#define CMD_EMV_FUZZ_RATS 0x0705 -#define CMD_EMV_GET_RANDOM_NUM 0x0706 -#define CMD_EMV_LOAD_VALUE 0x0707 -#define CMD_EMV_DUMP_CARD 0x0708 +// For ThinFilm Kovio +#define CMD_HF_THINFILM_READ 0x0810 +#define CMD_HF_THINFILM_SIMULATE 0x0811 #define CMD_UNKNOWN 0xFFFF @@ -507,6 +501,8 @@ typedef struct { #define FLAG_MF_1K 0x100 #define FLAG_MF_2K 0x200 #define FLAG_MF_4K 0x400 +#define FLAG_FORCED_ATQA 0x800 +#define FLAG_FORCED_SAK 0x1000 //Iclass reader flags #define FLAG_ICLASS_READER_ONLY_ONCE 0x01 @@ -559,6 +555,10 @@ typedef struct { #define PM3_ENOTTY -14 // Initialization error pm3: error related to trying to initalize the pm3 / fpga for different operations #define PM3_EINIT -15 +// Expected a different answer error client/pm3: error when expecting one answer and got another one +#define PM3_EWRONGANSVER -16 +// Memory out-of-bounds error client/pm3: error when a read/write is outside the expected array +#define PM3_EOUTOFBOUND -17 // No data 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 @@ -577,7 +577,7 @@ typedef struct { // uart_windows.c & uart_posix.c # define UART_FPC_CLIENT_RX_TIMEOUT_MS 200 # define UART_USB_CLIENT_RX_TIMEOUT_MS 20 -# define UART_TCP_CLIENT_RX_TIMEOUT_MS 300 +# define UART_TCP_CLIENT_RX_TIMEOUT_MS 500 // CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions: diff --git a/include/pmflash.h b/include/pmflash.h index b7bf39ddc..d61b5647d 100644 --- a/include/pmflash.h +++ b/include/pmflash.h @@ -12,14 +12,6 @@ #ifndef __PMFLASH_H #define __PMFLASH_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - #include "common.h" // Flashmem spi baudrate @@ -61,7 +53,7 @@ extern uint32_t FLASHMEM_SPIBAUDRATE; #endif #ifndef T55XX_CONFIG_LEN -# define T55XX_CONFIG_LEN sizeof( t55xx_config ) +# define T55XX_CONFIG_LEN sizeof( t55xx_configurations_t ) #endif #ifndef T55XX_CONFIG_OFFSET @@ -90,8 +82,4 @@ typedef struct { uint8_t signature[FLASH_MEM_SIGNATURE_LEN]; } PACKED rdv40_validation_t; -#ifdef __cplusplus -} -#endif - #endif // __PMFLASH_H diff --git a/common/protocols.h b/include/protocols.h similarity index 89% rename from common/protocols.h rename to include/protocols.h index cef339dc4..9b47266c3 100644 --- a/common/protocols.h +++ b/include/protocols.h @@ -1,10 +1,7 @@ #ifndef PROTOCOLS_H #define PROTOCOLS_H -#include -#include -#include - +#include "common.h" //The following data is taken from http://www.proxmark.org/forum/viewtopic.php?pid=13501#p13501 /* @@ -123,22 +120,21 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. // for instance ICLASS_CMD_SELECT 0x81 tells if ISO14443b/BPSK coding/106 kbits/s // for instance ICLASS_CMD_SELECT 0x41 tells if ISO14443b/BPSK coding/423 kbits/s // -#define ICLASS_CMD_HALT 0x00 -#define ICLASS_CMD_SELECT_15 0x01 -#define ICLASS_CMD_ACTALL 0x0A -#define ICLASS_CMD_DETECT 0x0F +#define ICLASS_CMD_HALT 0x0 +#define ICLASS_CMD_SELECT 0x1 +#define ICLASS_CMD_ACTALL 0xA +#define ICLASS_CMD_DETECT 0xF -#define ICLASS_CMD_CHECK 0x05 -#define ICLASS_CMD_READ4 0x06 -#define ICLASS_CMD_READ_OR_IDENTIFY 0x0C - -#define ICLASS_CMD_SELECT 0x81 -#define ICLASS_CMD_PAGESEL 0x84 -#define ICLASS_CMD_UPDATE 0x87 -#define ICLASS_CMD_READCHECK_KC 0x18 -#define ICLASS_CMD_READCHECK_KD 0x88 -#define ICLASS_CMD_ACT 0x8E +#define ICLASS_CMD_PAGESEL 0x4 +#define ICLASS_CMD_CHECK 0x5 +#define ICLASS_CMD_READ4 0x6 +#define ICLASS_CMD_UPDATE 0x7 +#define ICLASS_CMD_READCHECK 0x8 +#define ICLASS_CMD_READ_OR_IDENTIFY 0xC +#define ICLASS_CMD_ACT 0xE +#define ICLASS_CREDIT(x) (((x) & 0x5) == 1) +#define ICLASS_DEBIT(x) (((x) & 0x5) == 0) #define ISO14443A_CMD_REQA 0x26 @@ -279,6 +275,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define FELICA 8 #define PROTO_MIFARE 9 #define PROTO_HITAG 10 +#define THINFILM 11 //-- Picopass fuses #define FUSE_FPERS 0x80 @@ -360,9 +357,6 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define LEGIC_READ 0x01 #define LEGIC_WRITE 0x00 -void printIclassDumpInfo(uint8_t *iclass_dump); -void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb); - /* T55x7 configuration register definitions */ #define T55x7_POR_DELAY 0x00000001 #define T55x7_ST_TERMINATOR 0x00000008 @@ -419,9 +413,6 @@ void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t * #define T55XX_WRITE_TIMEOUT 1500 -uint32_t GetT55xxClockBit(uint32_t clock); - - // em4x05 & em4x69 chip configuration register definitions #define EM4x05_GET_BITRATE(x) (((x & 0x3F)*2)+2) #define EM4x05_SET_BITRATE(x) ((x-2)/2) @@ -550,27 +541,26 @@ uint32_t GetT55xxClockBit(uint32_t clock); #define CALYPSO_SAM_SV_DEBIT 0x54 #define CALYPSO_SAM_SV_RELOAD 0x56 -// iclass / picopass chip config structures and shared routines -typedef struct { - uint8_t app_limit; //[8] - uint8_t otp[2]; //[9-10] - uint8_t block_writelock;//[11] - uint8_t chip_config; //[12] - uint8_t mem_config; //[13] - uint8_t eas; //[14] - uint8_t fuses; //[15] -} picopass_conf_block; - - -typedef struct { - uint8_t csn[8]; - picopass_conf_block conf; - uint8_t epurse[8]; - uint8_t key_d[8]; - uint8_t key_c[8]; - uint8_t app_issuer_area[8]; -} picopass_hdr; +// HITAG1 commands +#define HITAG1_SET_CCNEW 0xC2 // left 5 bits only +#define HITAG1_READ_ID 0x00 // not a real command, consists of 5 bits length, bits partial SN, 8 bits CRC +#define HITAG1_SELECT 0x00 // left 5 bits only, followed by 32 bits SN and 8 bits CRC +#define HITAG1_WRPPAGE 0x80 // left 4 bits only, followed by 8 bits page and 8 bits CRC +#define HITAG1_WRPBLK 0x90 // left 4 bits only, followed by 8 bits block and 8 bits CRC +#define HITAG1_WRCPAGE 0xA0 // left 4 bits only, followed by 8 bits page or key information and 8 bits CRC +#define HITAG1_WRCBLK 0xB0 // left 4 bits only, followed by 8 bits block and 8 bits CRC +#define HITAG1_RDPPAGE 0xC0 // left 4 bits only, followed by 8 bits page and 8 bits CRC +#define HITAG1_RDPBLK 0xD0 // left 4 bits only, followed by 8 bits block and 8 bits CRC +#define HITAG1_RDCPAGE 0xE0 // left 4 bits only, followed by 8 bits page and 8 bits CRC +#define HITAG1_RDCBLK 0xF0 // left 4 bits only, followed by 8 bits block and 8 bits CRC +#define HITAG1_HALT 0x70 // left 4 bits only, followed by 8 bits (dummy) page and 8 bits CRC +// HITAG2 commands +#define HITAG2_START_AUTH 0xC0 // left 5 bits only +#define HITAG2_READ_PAGE 0xC0 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits +#define HITAG2_READ_PAGE_INVERTED 0x44 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits +#define HITAG2_WRITE_PAGE 0x82 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits +#define HITAG2_HALT 0x00 // left 5 bits only #endif // PROTOCOLS_H diff --git a/include/proxmark3.h b/include/proxmark3_arm.h similarity index 97% rename from include/proxmark3.h rename to include/proxmark3_arm.h index 469713b5b..a2f76e93d 100644 --- a/include/proxmark3.h +++ b/include/proxmark3_arm.h @@ -11,11 +11,16 @@ #ifndef __PROXMARK3_H #define __PROXMARK3_H +#include "common.h" + // Might as well have the hardware-specific defines everywhere. #include "at91sam7s512.h" #include "config_gpio.h" #include "pm3_cmd.h" -#include "common.h" + +// Check bootrom.c for actual clock settings +#define MAINCK 16000000 +#define MCK (3 * MAINCK) #define WDT_HIT() AT91C_BASE_WDTC->WDTC_WDCR = 0xa5000001 diff --git a/include/usart_defs.h b/include/usart_defs.h new file mode 100644 index 000000000..cf6630e83 --- /dev/null +++ b/include/usart_defs.h @@ -0,0 +1,26 @@ +#ifndef __USART_DEFS_H +#define __USART_DEFS_H + +//#define USART_BAUD_RATE 9600 +#define USART_BAUD_RATE 115200 +// BT HC-06 physical layer runs at 128kbps +// so it's possible to gain a little bit by using 230400 +// with some risk to overflow its internal buffers: +//#define USART_BAUD_RATE 230400 + +#define USART_BUFFLEN 512 +#define USART_FIFOLEN (2*USART_BUFFLEN) + +// Higher baudrates are pointless, only increasing overflow risk + +#define USART_PARITY 'N' + +#if defined (_WIN32) +#define SERIAL_PORT_EXAMPLE_H "com3" +#elif defined(__APPLE__) +#define SERIAL_PORT_EXAMPLE_H "/dev/tty.usbmodemiceman1" +#else +#define SERIAL_PORT_EXAMPLE_H "/dev/ttyACM0" +#endif + +#endif diff --git a/install.sh b/install.sh deleted file mode 100755 index 8dc3e5317..000000000 --- a/install.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/bash -set -x -# This is for linux ppl and it works on Ubuntu distros. Don't know about Kali. -function installProxmark_Linux { - # install dependencies for Proxmark3 source code. - sudo apt-get install p7zip git build-essential libreadline5 libreadline-dev gcc-arm-none-eabi - sudo apt-get install libusb-0.1-4 libusb-dev libqt4-dev libncurses5-dev perl pkg-config wget - #cleaning up - sudo apt-get install -f -y - sudo apt-get autoremove -y - sudo apt-get autoclean -y - sudo apt-get clean -y - sudo apt-get update - - # Install libcanberragtk in Ubuntu 18.04 - if [[ $(cat /etc/issue | awk '{print $2}') = *"18.04"* ]]; then - apt-get install libcanberra-gtk-module - fi - -# install RDV40 - proxmark3 - git clone https://github.com/RfidResearchGroup/proxmark3.git . - ( - cd proxmark3 || exit 1 - git reset --hard - git clean -dfx - make clean - make -j$(nproc) all - # Copy blacklist rules into /etc/udev/rules.d - # check the Makefile for details - sudo make udev - ) -} -function installProxmark_macOS { - # Install dependencies for Proxmark3 source code. - brew tap nitsky/stm32 - brew install readline libusb p7zip libusb-compat wget qt5 pkgconfig arm-none-eabi-gcc - brew link --force readline - # add moc_location in Qt5Core.pc file. -local qtDir=$(ls /usr/local/Cellar/qt/ 2>/dev/null | head -1) -local qt5Core=$(find /usr -name Qt5Core.pc 2>/dev/null) - ( - export PKG_CONFIG_PATH=/usr/local/Cellar/qt/$qtDir/lib/pkgconfig/ - export QT_PKG_CONFIG_QT5CORE=$qt5Core - chmod 666 $QT_PKG_CONFIG_QT5CORE - echo "moc_location=\${prefix}/bin/moc" >> $QT_PKG_CONFIG_QT5CORE - chmod 444 $QT_PKG_CONFIG_QT5CORE - ) - # install RDV40 - proxmark3 - git clone https://github.com/RfidResearchGroup/proxmark3.git - ( - cd proxmark3 || exit 1 - git reset --hard - git clean -dfx - make clean - make -j$(sysctl -n hw.physicalcpu) - ) - } -# Where is my device? -#dmesg | tail -10 -# Detect OS and install libraries and proxmark3 client -if [[ $(uname | awk '{print toupper($0)}') == "LINUX" ]]; then - echo >&2 "Linux Detected - Updating your system..." - $(installProxmark_Linux) -elif [[ $(uname | awk '{print toupper($0)}') == "DARWIN" ]]; then - echo >&2 "MAC OS X Detected - Updating your system..." - $(installProxmark_macOS) 2>/dev/null -fi -echo >&2 "Done." diff --git a/liblua/Makefile b/liblua/Makefile deleted file mode 100644 index 2b3d7614f..000000000 --- a/liblua/Makefile +++ /dev/null @@ -1,208 +0,0 @@ -# Makefile for building Lua -# See ../doc/readme.html for installation and customization instructions. - -# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= - -# Hide full compilation line: -ifneq ($(V),1) - Q?=@ -endif -# To see full command lines, use make V=1 - -# Your platform. See PLATS for possible values. -PLAT= none - -platform= $(shell uname) - -CC= gcc -CFLAGS= -O3 -Wall -DLUA_COMPAT_ALL $(SYSCFLAGS) $(MYCFLAGS) -LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS) -LIBS= -lm $(SYSLIBS) $(MYLIBS) - -ifeq ($(platform),Darwin) -AR= /usr/bin/ar rc -RANLIB= /usr/bin/ranlib -else -AR= ar rc -RANLIB= ranlib -endif -RM= rm -f - -SYSCFLAGS= -SYSLDFLAGS= -SYSLIBS= - -MYCFLAGS= -MYLDFLAGS= -MYLIBS= -MYOBJS= - -# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE ======= - -%.o: %.c - $(info [-] CC $<) - $(Q)$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $< - -PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris - -LUA_A= liblua.a -CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \ - lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \ - ltm.o lundump.o lvm.o lzio.o -LIB_O= lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o \ - lmathlib.o loslib.o lstrlib.o ltablib.o loadlib.o linit.o -BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS) - -LUA_T= lua -LUA_O= lua.o - -LUAC_T= luac -LUAC_O= luac.o - -ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O) -ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T) -ALL_A= $(LUA_A) - -# Targets start here. -default: $(PLAT) - -all: $(ALL_T) - -o: $(ALL_O) - -a: $(ALL_A) - -$(LUA_A): $(BASE_O) - $(info [=] AR $@) - $(Q)$(AR) $@ $(BASE_O) - $(Q)$(RANLIB) $@ - -$(LUA_T): $(LUA_O) $(LUA_A) - $(info [=] LD $@) - $(Q)$(CC) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS) - -$(LUAC_T): $(LUAC_O) $(LUA_A) - $(info [=] LD $@) - $(Q)$(CC) -o $@ $(LDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS) - -clean: - $(Q)$(RM) $(ALL_T) $(ALL_O) - -depend: - $(info GEN DEPS) - $(Q)$(CC) $(CFLAGS) -MM l*.c - -echo: - @echo "PLAT= $(PLAT)" - @echo "CC= $(CC)" - @echo "CFLAGS= $(CFLAGS)" - @echo "LDFLAGS= $(SYSLDFLAGS)" - @echo "LIBS= $(LIBS)" - @echo "AR= $(AR)" - @echo "RANLIB= $(RANLIB)" - @echo "RM= $(RM)" - -# Convenience targets for popular platforms -ALL= all - -none: - @echo "Please do 'make PLATFORM' where PLATFORM is one of these:" - @echo " $(PLATS)" - -aix: - $(Q)$(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall" - -ansi: - $(Q)$(MAKE) $(ALL) SYSCFLAGS="-DLUA_ANSI" - -bsd: - $(Q)$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E" - -freebsd: - $(Q)$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -lreadline" - -generic: $(ALL) - -linux: - $(Q)$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline -ltermcap -lncurses" - -macosx: - $(Q)$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" - -mingw: - $(Q)$(MAKE) "LUA_A=lua52.dll" "LUA_T=lua.exe" \ - "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ - "SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe - $(Q)$(MAKE) "LUAC_T=luac.exe" luac.exe - -posix: - $(Q)$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX" - -solaris: - $(Q)$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" - -# list targets that do not create files (but not all makes understand .PHONY) -.PHONY: all $(PLATS) default o a clean depend echo none - -# DO NOT DELETE - -lapi.o: lapi.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h ltm.h \ - lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h ltable.h lundump.h \ - lvm.h -lauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h -lbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h -lbitlib.o: lbitlib.c lua.h luaconf.h lauxlib.h lualib.h -lcode.o: lcode.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ - lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lgc.h \ - lstring.h ltable.h lvm.h -lcorolib.o: lcorolib.c lua.h luaconf.h lauxlib.h lualib.h -lctype.o: lctype.c lctype.h lua.h luaconf.h llimits.h -ldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h -ldebug.o: ldebug.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h \ - ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h ldebug.h ldo.h \ - lfunc.h lstring.h lgc.h ltable.h lvm.h -ldo.o: ldo.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h ltm.h \ - lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h lparser.h \ - lstring.h ltable.h lundump.h lvm.h -ldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \ - lzio.h lmem.h lundump.h -lfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h \ - lstate.h ltm.h lzio.h lmem.h -lgc.o: lgc.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ - lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h -linit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h -liolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h -llex.o: llex.c lua.h luaconf.h lctype.h llimits.h ldo.h lobject.h \ - lstate.h ltm.h lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h -lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h -lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ - ltm.h lzio.h lmem.h ldo.h lgc.h -loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h -lobject.o: lobject.c lua.h luaconf.h lctype.h llimits.h ldebug.h lstate.h \ - lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h lvm.h -lopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h -loslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h -lparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ - lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lfunc.h \ - lstring.h lgc.h ltable.h -lstate.o: lstate.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h \ - ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h lstring.h \ - ltable.h -lstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \ - ltm.h lzio.h lstring.h lgc.h -lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h -ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ - ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h -ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h -ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \ - lmem.h lstring.h lgc.h ltable.h -lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h -luac.o: luac.c lua.h luaconf.h lauxlib.h lobject.h llimits.h lstate.h \ - ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h -lundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h lundump.h -lvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ - lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h -lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \ - lzio.h - diff --git a/pm3 b/pm3 new file mode 100755 index 000000000..a740beb12 --- /dev/null +++ b/pm3 @@ -0,0 +1,197 @@ +#!/bin/bash + +# Usage: run option -h to get help + +PM3PATH=$(dirname "$0") +FULLIMAGE="fullimage.elf" +BOOTIMAGE="bootrom.elf" +# try pm3 dirs in current repo workdir +if [ -d "$PM3PATH/client/" ]; then + CLIENT="$PM3PATH/client/proxmark3" +# try install dir +elif [ -x "$PM3PATH/proxmark3" ]; then + CLIENT="$PM3PATH/proxmark3" +else +# hope it's installed somehow, still not sure where fw images are... + CLIENT="proxmark3" +fi + +function wait4proxmark_Linux { + echo >&2 "[=] Waiting for Proxmark3 to appear..." + while true; do + PM3=$(find /dev/pm3-* /dev/ttyACM* 2>/dev/null | head -1) + if [[ $PM3 != "" ]]; then + break + fi + sleep .1 + done + echo "$PM3" +} + +function wait4proxmark_macOS { + echo >&2 "[=] Waiting for Proxmark3 to appear..." + while true; do + PM3=$(find /dev/pm3-* /dev/tty.usbmodem* 2>/dev/null | head -1) + if [[ $PM3 != "" ]]; then + break + fi + sleep .1 + done + echo "$PM3" +} + +function wait4proxmark_Windows { + echo >&2 "[=] Waiting for Proxmark3 to appear..." + while true; do + device=$(wmic path Win32_SerialPort where "PNPDeviceID like '%VID_9AC4&PID_4B8F%'" get DeviceID,PNPDeviceID 2>/dev/null | awk 'NR==2') + if [[ $device != "" ]]; then + PM3=${device/ */} + break + fi + sleep .1 + done + echo "$PM3" +} + +function wait4proxmark_WSL { + echo >&2 "[=] Waiting for Proxmark3 to appear..." + while true; do + device=$(wmic.exe path Win32_SerialPort where "PNPDeviceID like '%VID_9AC4&PID_4B8F%'" get DeviceID,PNPDeviceID 2>/dev/null | awk 'NR==2') + if [[ $device != "" ]]; then + PM3=${device/ */} + PM3="/dev/ttyS${PM3#COM}" + break + fi + sleep .1 + done + if [ -e "$PM3" ] && [ ! -w "$PM3" ]; then + echo "[!!] We need to give current user read/write access to $PM3" + sudo chmod 666 "$PM3" + fi + echo "$PM3" +} + +SCRIPT=$(basename -- "$0") + +if [ "$SCRIPT" = "pm3" ]; then + CMD() { $CLIENT "$@"; } + HELP() { + cat << EOF +Quick helper script for proxmark3 client when working with a Proxmark device connected via USB + +Description: + The usage is the same as for the proxmark3 client, with the following differences: + * the correct port name will be automatically guessed; + * the script will wait for a Proxmark to be connected (same as option -w of the client). + Don't use this script if you want to work offline or with the BT addon. + +Usage: + $SCRIPT [-f] [-c ]|[-l ]|[-s ] [-i] + +See "$CLIENT -h" for more details on options. +EOF + } +elif [ "$SCRIPT" = "pm3-flash" ]; then + CMD() { + ARGS=("$1" "--flash") + shift; + while [ "$1" != "" ]; do + if [ "$1" == "-b" ]; then + ARGS+=("--unlock-bootloader") + else + ARGS+=("--image" "$1") + fi + shift; + done + $CLIENT ${ARGS[@]}; + } + HELP() { + cat << EOF +Quick helper script for flashing a Proxmark device via USB + +Description: + The usage is similar to the old proxmark3-flasher binary, except that the correct port name will be automatically guessed. + If this doesn't work, you'll have to use manually the proxmark3 client, see "$CLIENT -h". + +Usage: + $SCRIPT [-b] image.elf [image.elf...] + +Options: + -b Enable flashing of bootloader area (DANGEROUS) + +Example: + $SCRIPT -b bootrom.elf fullimage.elf +EOF + } +elif [ "$SCRIPT" = "pm3-flash-all" ]; then + CMD() { $CLIENT "$1" "--flash" "--unlock-bootloader" "--image" "$BOOTIMAGE" "--image" "$FULLIMAGE"; } + HELP() { + cat << EOF +Quick helper script for flashing a Proxmark device via USB + +Description: + The correct port name will be automatically guessed and the stock bootloader and firmware image will be flashed. + If this doesn't work, you'll have to use manually the proxmark3 client, see "$CLIENT -h". + +Usage: + $SCRIPT +EOF + } +elif [ "$SCRIPT" = "pm3-flash-fullimage" ]; then + CMD() { $CLIENT "$1" "--flash" "--image" "$FULLIMAGE"; } + HELP() { + cat << EOF +Quick helper script for flashing a Proxmark device via USB + +Description: + The correct port name will be automatically guessed and the stock firmware image will be flashed. + If this doesn't work, you'll have to use manually the proxmark3 client, see "$CLIENT -h". + +Usage: + $SCRIPT +EOF + } +elif [ "$SCRIPT" = "pm3-flash-bootrom" ]; then + CMD() { $CLIENT "$1" "--flash" "--unlock-bootloader" "--image" "$BOOTIMAGE"; } + HELP() { + cat << EOF +Quick helper script for flashing a Proxmark device via USB + +Description: + The correct port name will be automatically guessed and the stock bootloader will be flashed. + If this doesn't work, you'll have to use manually the proxmark3 client, see "$CLIENT -h". + +Usage: + $SCRIPT +EOF + } +else + echo "[!!] Script ran under unknown name, abort: $SCRIPT" + exit 1 +fi +if [ "$1" == "-h" ] || [ "$1" == "--help" ]; then + HELP + exit 0 +fi +HOSTOS=$(uname | awk '{print toupper($0)}') +if [ "$HOSTOS" = "LINUX" ]; then + if uname -a|grep -q Microsoft; then + PORT=$(wait4proxmark_WSL) + else + PORT=$(wait4proxmark_Linux) + fi +elif [ "$HOSTOS" = "DARWIN" ]; then + PORT=$(wait4proxmark_macOS) +elif [[ "$HOSTOS" =~ MINGW(32|64)_NT* ]]; then + PORT=$(wait4proxmark_Windows) +else + echo "[!!] Host OS not recognized, abort: $HOSTOS" + exit 1 +fi +if [ "$PORT" = "" ]; then + echo "[!!] No port, abort" + exit 1 +fi + +CMD "$PORT" "$@" +exit $? diff --git a/pm3-flash b/pm3-flash new file mode 100755 index 000000000..e5cd5479d --- /dev/null +++ b/pm3-flash @@ -0,0 +1,4 @@ +#!/bin/bash + +PM3PATH=$(dirname "$0") +. "$PM3PATH/pm3" diff --git a/pm3-flash-all b/pm3-flash-all new file mode 100755 index 000000000..e5cd5479d --- /dev/null +++ b/pm3-flash-all @@ -0,0 +1,4 @@ +#!/bin/bash + +PM3PATH=$(dirname "$0") +. "$PM3PATH/pm3" diff --git a/pm3-flash-bootrom b/pm3-flash-bootrom new file mode 100755 index 000000000..e5cd5479d --- /dev/null +++ b/pm3-flash-bootrom @@ -0,0 +1,4 @@ +#!/bin/bash + +PM3PATH=$(dirname "$0") +. "$PM3PATH/pm3" diff --git a/pm3-flash-fullimage b/pm3-flash-fullimage new file mode 100755 index 000000000..e5cd5479d --- /dev/null +++ b/pm3-flash-fullimage @@ -0,0 +1,4 @@ +#!/bin/bash + +PM3PATH=$(dirname "$0") +. "$PM3PATH/pm3" diff --git a/pm3test.sh b/pm3test.sh new file mode 100755 index 000000000..8785bf8df --- /dev/null +++ b/pm3test.sh @@ -0,0 +1,113 @@ +#!/bin/bash + +PM3PATH=$(dirname "$0") +cd "$PM3PATH" || exit 1 + +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 + +# title, file name or file wildcard to check +function CheckFileExist() { + + if [ -f "$2" ]; then + echo -e "$1 ${C_GREEN}[OK]${C_NC}" + return 0 + fi + + if ls $2 1> /dev/null 2>&1; then + echo -e "$1 ${C_GREEN}[OK]${C_NC}" + return 0 + fi + + echo -e "$1 ${C_RED}[Fail]${C_NC}" + return 1 +} + +# title, command line, check result, repeat several times if failed, ignore if fail +function CheckExecute() { + + if [ $4 ]; then + local RETRY="1 2 3 e" + else + local RETRY="e" + fi + + for I in $RETRY + do + RES=$(eval "$2") + if echo "$RES" | grep -q "$3"; then + echo -e "$1 ${C_GREEN}[OK]${C_NC}" + return 0 + fi + if [ ! $I == "e" ]; then echo "retry $I"; fi + done + + + if [ $5 ]; then + echo -e "$1 ${C_YELLOW}[Ignored]${C_NC}" + return 0 + fi + + echo -e "$1 ${C_RED}[Fail]${C_NC}" + echo -e "Execution trace:\n$RES" + return 1 +} + +printf "\n${C_BLUE}RRG/Iceman Proxmark3 test tool ${C_NC}\n\n" + +printf "work directory: " +pwd + +if [ "$TRAVIS_COMMIT" ]; then + if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then + echo "Travis branch: $TRAVIS_BRANCH slug: $TRAVIS_REPO_SLUG commit: $TRAVIS_COMMIT" + else + echo "Travis pull request: $TRAVIS_PULL_REQUEST branch: $TRAVIS_BRANCH slug: $TRAVIS_PULL_REQUEST_SLUG commit: $TRAVIS_COMMIT" + fi +fi + +printf "git branch: " +git describe --all +printf "git sha: " +git rev-parse HEAD +echo "" + +while true; do + printf "\n${C_BLUE}Testing files:${C_NC}\n" + if ! CheckFileExist "proxmark3 exists" "./client/proxmark3"; then break; fi + if ! CheckFileExist "arm image exists" "./armsrc/obj/fullimage.elf"; then break; fi + if ! CheckFileExist "bootrom exists" "./bootrom/obj/bootrom.elf"; then break; fi + if ! CheckFileExist "hardnested tables exists" "./client/resources/hardnested_tables/*.z"; then break; fi + + printf "\n${C_BLUE}Testing basic help:${C_NC}\n" + if ! CheckExecute "proxmark help" "./client/proxmark3 -h" "wait"; then break; fi + if ! CheckExecute "proxmark help text ISO7816" "./client/proxmark3 -t 2>&1" "ISO7816"; then break; fi + if ! CheckExecute "proxmark help text hardnested" "./client/proxmark3 -t 2>&1" "hardnested"; then break; fi + + printf "\n${C_BLUE}Testing data manipulation:${C_NC}\n" + if ! CheckExecute "reveng test" "./client/proxmark3 -c 'reveng -w 8 -s 01020304e3 010204039d'" "CRC-8/SMBUS"; then break; fi + + printf "\n${C_BLUE}Testing LF:${C_NC}\n" + if ! CheckExecute "lf em4x05 test" "./client/proxmark3 -c 'data load traces/em4x05.pm3;lf search'" "FDX-B ID found"; then break; fi + + printf "\n${C_BLUE}Testing HF:${C_NC}\n" + if ! CheckExecute "hf mf offline text" "./client/proxmark3 -c 'hf mf'" "at_enc"; then break; fi + if ! CheckExecute "hf mf hardnested test" "./client/proxmark3 -c 'hf mf hardnested t 1 000000000000'" "found:" "repeat" "ignore"; then break; fi + if ! CheckExecute "hf iclass test" "./client/proxmark3 -c 'hf iclass loclass t'" "verified ok"; then break; fi + if ! CheckExecute "emv test" "./client/proxmark3 -c 'emv test'" "Test(s) \[ OK"; then break; fi + + printf "\n${C_BLUE}Testing tools:${C_NC}\n" + # Need a decent example for mfkey32... + if ! CheckExecute "mfkey32v2 test" "tools/mfkey/mfkey32v2 12345678 1AD8DF2B 1D316024 620EF048 30D6CB07 C52077E2 837AC61A" "Found Key: \[a0a1a2a3a4a5\]"; then break; fi + if ! CheckExecute "mfkey64 test" "tools/mfkey/mfkey64 9c599b32 82a4166c a1e458ce 6eea41e0 5cadf439" "Found Key: \[ffffffffffff\]"; then break; fi + if ! CheckExecute "mfkey64 long trace test" "tools/mfkey/./mfkey64 14579f69 ce844261 f8049ccb 0525c84f 9431cc40 7093df99 9972428ce2e8523f456b99c831e769dced09 8ca6827b ab797fd369e8b93a86776b40dae3ef686efd c3c381ba 49e2c9def4868d1777670e584c27230286f4 fbdcd7c1 4abd964b07d3563aa066ed0a2eac7f6312bf 9f9149ea" "Found Key: \[091e639cb715\]"; then break; fi + if ! CheckExecute "nonce2key test" "tools/nonce2key/nonce2key e9cadd9c a8bf4a12 a020a8285858b090 050f010607060e07 5693be6c00000000" "key recovered: fc00018778f7"; then break; fi + printf "\n${C_GREEN}Tests [OK]${C_NC}\n\n" + exit 0 +done + +printf "\n${C_RED}Tests [FAIL]${C_NC}\n\n" +exit 1 diff --git a/proxmark3.sh b/proxmark3.sh deleted file mode 100755 index 4cd6d76bc..000000000 --- a/proxmark3.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/bin/bash - -FULLIMAGE="armsrc/obj/fullimage.elf" -BOOTIMAGE="bootrom/obj/bootrom.elf" - -PM3PATH=$(dirname "$0") -cd "$PM3PATH" || exit 1 - -function wait4proxmark_Linux { - echo >&2 "Waiting for Proxmark to appear..." - while true; do - PM3=$(find /dev/pm3-* /dev/ttyACM* 2>/dev/null | head -1) - if [[ $PM3 != "" ]]; then - break - fi - sleep .1 - done - echo "$PM3" -} - -function wait4proxmark_macOS { - echo >&2 "Waiting for Proxmark to appear..." - while true; do - PM3=$(find /dev/pm3-* /dev/cu.usbmodem* 2>/dev/null | head -1) - if [[ $PM3 != "" ]]; then - break - fi - sleep .1 - done - echo "$PM3" -} - -function wait4proxmark_Windows { - echo >&2 "Waiting for Proxmark to appear..." - while true; do - device=$(wmic path Win32_SerialPort where "PNPDeviceID like '%VID_9AC4&PID_4B8F%'" get DeviceID,PNPDeviceID 2>/dev/null | awk 'NR==2') - if [[ $device != "" ]]; then - PM3=${device/ */} - break - fi - sleep .1 - done - echo "$PM3" -} - -function wait4proxmark_WSL { - echo >&2 "Waiting for Proxmark to appear..." - while true; do - device=$(wmic.exe path Win32_SerialPort where "PNPDeviceID like '%VID_9AC4&PID_4B8F%'" get DeviceID,PNPDeviceID 2>/dev/null | awk 'NR==2') - if [[ $device != "" ]]; then - PM3=${device/ */} - PM3="/dev/ttyS${PM3#COM}" - break - fi - sleep .1 - done - if [ -e "$PM3" ] && [ ! -w "$PM3" ]; then - echo "We need to give current user read/write access to $PM3" - sudo chmod 666 "$PM3" - fi - echo "$PM3" -} - -SCRIPT=$(basename -- "$0") - -if [ "$SCRIPT" = "proxmark3.sh" ]; then - CMD() { client/proxmark3 "$@"; } -elif [ "$SCRIPT" = "flash-all.sh" ]; then - CMD() { client/flasher "$1" -b "$BOOTIMAGE" "$FULLIMAGE"; } -elif [ "$SCRIPT" = "flash-fullimage.sh" ]; then - CMD() { client/flasher "$1" "$FULLIMAGE"; } -elif [ "$SCRIPT" = "flash-bootrom.sh" ]; then - CMD() { client/flasher "$1" -b "$BOOTIMAGE"; } -else - echo "Script ran under unknown name, abort: $SCRIPT" - exit 1 -fi -HOSTOS=$(uname | awk '{print toupper($0)}') -if [ "$HOSTOS" = "LINUX" ]; then - if uname -a|grep -q Microsoft; then - PORT=$(wait4proxmark_WSL) - else - PORT=$(wait4proxmark_Linux) - fi -elif [ "$HOSTOS" = "DARWIN" ]; then - PORT=$(wait4proxmark_macOS) -elif [[ "$HOSTOS" =~ MINGW(32|64)_NT* ]]; then - PORT=$(wait4proxmark_Windows) -else - echo "Host OS not recognized, abort: $HOSTOS" - exit 1 -fi -if [ "$PORT" = "" ]; then - echo "No port, abort" - exit 1 -fi - -CMD "$PORT" "$@" -exit $? diff --git a/recovery/Makefile b/recovery/Makefile index 601f93055..2bfd1475f 100644 --- a/recovery/Makefile +++ b/recovery/Makefile @@ -1,6 +1,13 @@ -include ../common/Makefile.common +include ../common_arm/Makefile.common -BINS = bootrom.bin fullimage.bin proxmark3_recovery.bin +INSTALLFW = proxmark3_recovery.bin +ifneq (,$(FWTAG)) + INSTALLFWTAG = $(notdir $(INSTALLFW:%.bin=%-$(FWTAG).bin)) +else + INSTALLFWTAG = $(notdir $(INSTALLFW)) +endif + +BINS = bootrom.bin fullimage.bin $(INSTALLFW) all: $(BINS) @@ -17,5 +24,15 @@ proxmark3_recovery.bin: bootrom.bin fullimage.bin $(Q)cat bootrom.bin fullimage.bin > $@ clean: - $(Q)rm -f $(BINS) + $(Q)$(RM) $(BINS) +install: all + $(info [@] Installing recovery to $(DESTDIR)$(PREFIX)...) + $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH) + $(Q)$(CP) $(INSTALLFW) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(INSTALLFWTAG) + +uninstall: + $(info [@] Uninstalling recovery from $(DESTDIR)$(PREFIX)...) + $(Q)$(RM) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(INSTALLFWTAG) + +.PHONY: all clean install uninstall diff --git a/tools/Makefile b/tools/Makefile index 3b1dc1b0f..5f2355f20 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,18 +1,23 @@ +MKDIR = mkdir -p +WGET = wget -N +TAR = tar Jxvf +GIT = git clone + get_craptev1: - wget -N http://crapto1.netgarage.org/craptev1-v1.1.tar.xz - tar Jxvf craptev1-v1.1.tar.xz -C craptev1-v1.1 + $(WGET) http://crapto1.netgarage.org/craptev1-v1.1.tar.xz + $(TAR) craptev1-v1.1.tar.xz -C craptev1-v1.1 get_crapto1: - wget -N http://crapto1.netgarage.org/crapto1-v3.3.tar.xz - tar Jxvf crapto1-v3.3.tar.xz -C crapto1-v3.3 + $(WGET) http://crapto1.netgarage.org/crapto1-v3.3.tar.xz + $(TAR) Jxvf crapto1-v3.3.tar.xz -C crapto1-v3.3 get_nonce_bf: -# git clone https://github.com/J-Run/mf_key_brute.git mf_key_brute - git clone https://github.com/iceman1001/mf_nonce_brute mf_nonce_brute +# $(GIT) https://github.com/J-Run/mf_key_brute.git mf_key_brute + $(GIT) https://github.com/iceman1001/mf_nonce_brute mf_nonce_brute get_xorsearch: - mkdir xorsearch - wget -N https://didierstevens.com/files/software/XORSearch_V1_11_2.zip + $(MKDIR) xorsearch + $(WGET) https://didierstevens.com/files/software/XORSearch_V1_11_2.zip # Mingw # unzzip-big XORSearch_V1_11_2.zip # linux diff --git a/tools/analyzesize.py b/tools/analyzesize.py index 4a5211c67..889222c01 100755 --- a/tools/analyzesize.py +++ b/tools/analyzesize.py @@ -16,7 +16,7 @@ except FileNotFoundError: db = dict() if len(sys.argv) < 3: - print("Usage: analazysize.py ") + print("Usage: analyzesize.py ") exit(-1) action, name = sys.argv[1:3] currentdata = subprocess.run(["arm-none-eabi-size","armsrc/obj/fullimage.stage1.elf"], stdout=subprocess.PIPE).stdout diff --git a/client/deprecated-hid-flasher/flasher/Info.plist b/tools/deprecated-hid-flasher/flasher/Info.plist similarity index 100% rename from client/deprecated-hid-flasher/flasher/Info.plist rename to tools/deprecated-hid-flasher/flasher/Info.plist diff --git a/client/deprecated-hid-flasher/flasher/Makefile b/tools/deprecated-hid-flasher/flasher/Makefile similarity index 76% rename from client/deprecated-hid-flasher/flasher/Makefile rename to tools/deprecated-hid-flasher/flasher/Makefile index bff511459..52b1229fe 100644 --- a/client/deprecated-hid-flasher/flasher/Makefile +++ b/tools/deprecated-hid-flasher/flasher/Makefile @@ -5,30 +5,27 @@ #----------------------------------------------------------------------------- CC=gcc -CXX=g++ -#COMMON_FLAGS = -m32 +LD=gcc OBJDIR = obj -LDLIBS = -lreadline -lpthread -CFLAGS = -std=gnu99 -Wall -Wno-unused-function $(COMMON_FLAGS) -g -O3 +LDLIBS = +CFLAGS ?= -Wall -Werror -g -O3 +CFLAGS += -std=gnu99 ifeq ($(platform),Darwin) LDLIBS += -lusb-1.0 else LDLIBS += -lusb endif -LDFLAGS = $(COMMON_FLAGS) -CXXFLAGS = - RM = rm -f -BINS = flasher -CLEAN = flasher flasher.exe $(OBJDIR)/*.o *.o +BINS = pm3-hid-flasher +CLEAN = pm3-hid-flasher pm3-hid-flasher.exe $(OBJDIR)/*.o all: $(BINS) -flasher: $(OBJDIR)/flash.o $(OBJDIR)/flasher.o $(OBJDIR)/proxusb.o - $(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@ +pm3-hid-flasher: $(OBJDIR)/flash.o $(OBJDIR)/flasher.o $(OBJDIR)/proxusb.o + $(LD) $(LDFLAGS) $^ $(LDLIBS) -o $@ $(OBJDIR)/%.o: %.c $(CC) $(CFLAGS) -c -o $@ $< diff --git a/tools/deprecated-hid-flasher/flasher/README.md b/tools/deprecated-hid-flasher/flasher/README.md new file mode 100644 index 000000000..c5ddfed62 --- /dev/null +++ b/tools/deprecated-hid-flasher/flasher/README.md @@ -0,0 +1,10 @@ +Compilation notes +================= + +Besides the global Proxmark3 requirements, this flasher compatible with very old firmwares requires the libusb 0.1 to work. +So you'll need to install the libusb 0.1 package first. + +* OSX: libusb-compat +* Debian-alike: libusb-0.1-4 libusb-dev +* Arch: libusb +* Fedora: libusb-devel diff --git a/client/deprecated-hid-flasher/flasher/elf.h b/tools/deprecated-hid-flasher/flasher/elf.h similarity index 100% rename from client/deprecated-hid-flasher/flasher/elf.h rename to tools/deprecated-hid-flasher/flasher/elf.h diff --git a/client/deprecated-hid-flasher/flasher/flash.c b/tools/deprecated-hid-flasher/flasher/flash.c similarity index 100% rename from client/deprecated-hid-flasher/flasher/flash.c rename to tools/deprecated-hid-flasher/flasher/flash.c diff --git a/client/deprecated-hid-flasher/flasher/flash.h b/tools/deprecated-hid-flasher/flasher/flash.h similarity index 100% rename from client/deprecated-hid-flasher/flasher/flash.h rename to tools/deprecated-hid-flasher/flasher/flash.h diff --git a/client/deprecated-hid-flasher/flasher/flasher.c b/tools/deprecated-hid-flasher/flasher/flasher.c similarity index 100% rename from client/deprecated-hid-flasher/flasher/flasher.c rename to tools/deprecated-hid-flasher/flasher/flasher.c diff --git a/client/deprecated-hid-flasher/flasher/obj/.dummy b/tools/deprecated-hid-flasher/flasher/obj/.dummy similarity index 100% rename from client/deprecated-hid-flasher/flasher/obj/.dummy rename to tools/deprecated-hid-flasher/flasher/obj/.dummy diff --git a/client/deprecated-hid-flasher/flasher/proxendian.h b/tools/deprecated-hid-flasher/flasher/proxendian.h similarity index 100% rename from client/deprecated-hid-flasher/flasher/proxendian.h rename to tools/deprecated-hid-flasher/flasher/proxendian.h diff --git a/client/deprecated-hid-flasher/flasher/proxmark3.h b/tools/deprecated-hid-flasher/flasher/proxmark3.h similarity index 100% rename from client/deprecated-hid-flasher/flasher/proxmark3.h rename to tools/deprecated-hid-flasher/flasher/proxmark3.h diff --git a/client/deprecated-hid-flasher/flasher/proxusb.c b/tools/deprecated-hid-flasher/flasher/proxusb.c similarity index 100% rename from client/deprecated-hid-flasher/flasher/proxusb.c rename to tools/deprecated-hid-flasher/flasher/proxusb.c diff --git a/client/deprecated-hid-flasher/flasher/proxusb.h b/tools/deprecated-hid-flasher/flasher/proxusb.h similarity index 100% rename from client/deprecated-hid-flasher/flasher/proxusb.h rename to tools/deprecated-hid-flasher/flasher/proxusb.h diff --git a/client/deprecated-hid-flasher/flasher/sleep.h b/tools/deprecated-hid-flasher/flasher/sleep.h similarity index 100% rename from client/deprecated-hid-flasher/flasher/sleep.h rename to tools/deprecated-hid-flasher/flasher/sleep.h diff --git a/client/deprecated-hid-flasher/flasher/usb_cmd.h b/tools/deprecated-hid-flasher/flasher/usb_cmd.h similarity index 53% rename from client/deprecated-hid-flasher/flasher/usb_cmd.h rename to tools/deprecated-hid-flasher/flasher/usb_cmd.h index 60c359e5a..75136c1f4 100644 --- a/client/deprecated-hid-flasher/flasher/usb_cmd.h +++ b/tools/deprecated-hid-flasher/flasher/usb_cmd.h @@ -66,98 +66,94 @@ typedef struct { #define CMD_FLASHMEM_INFO 0x0125 // For low-frequency tags -#define CMD_READ_TI_TYPE 0x0202 -#define CMD_WRITE_TI_TYPE 0x0203 -#define CMD_DOWNLOADED_RAW_BITS_TI_TYPE 0x0204 -#define CMD_ACQUIRE_RAW_ADC_SAMPLES_125K 0x0205 -#define CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K 0x0206 +#define CMD_LF_TI_READ 0x0202 +#define CMD_LF_TI_WRITE 0x0203 +#define CMD_LF_ACQ_RAW_ADC 0x0205 +#define CMD_LF_MOD_THEN_ACQ_RAW_ADC 0x0206 #define CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K 0x0207 #define CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K 0x0208 -#define CMD_UPLOAD_SIM_SAMPLES_125K 0x0209 -#define CMD_SIMULATE_TAG_125K 0x020A -#define CMD_HID_DEMOD_FSK 0x020B -#define CMD_HID_SIM_TAG 0x020C -#define CMD_SET_LF_DIVISOR 0x020D +#define CMD_LF_UPLOAD_SIM_SAMPLES 0x0209 +#define CMD_LF_SIMULATE 0x020A +#define CMD_LF_HID_DEMOD 0x020B +#define CMD_LF_HID_SIMULATE 0x020C +#define CMD_LF_SET_DIVISOR 0x020D #define CMD_LF_SIMULATE_BIDIR 0x020E #define CMD_SET_ADC_MUX 0x020F -#define CMD_HID_CLONE_TAG 0x0210 -#define CMD_EM410X_WRITE_TAG 0x0211 -#define CMD_INDALA_CLONE_TAG 0x0212 +#define CMD_LF_HID_CLONE 0x0210 +#define CMD_LF_EM410X_WRITE 0x0211 +#define CMD_LF_INDALA_CLONE 0x0212 // for 224 bits UID -#define CMD_INDALA_CLONE_TAG_L 0x0213 -#define CMD_T55XX_READ_BLOCK 0x0214 -#define CMD_T55XX_WRITE_BLOCK 0x0215 -#define CMD_T55XX_RESET_READ 0x0216 -#define CMD_T55XX_WAKEUP 0x0224 +#define CMD_LF_INDALA224_CLONE 0x0213 +#define CMD_LF_T55XX_READBL 0x0214 +#define CMD_LF_T55XX_WRITEBL 0x0215 +#define CMD_LF_T55XX_RESET_READ 0x0216 +#define CMD_LF_T55XX_WAKEUP 0x0224 -#define CMD_PCF7931_READ 0x0217 -#define CMD_PCF7931_WRITE 0x0223 -#define CMD_EM4X_READ_WORD 0x0218 -#define CMD_EM4X_WRITE_WORD 0x0219 -#define CMD_IO_DEMOD_FSK 0x021A -#define CMD_IO_CLONE_TAG 0x021B -#define CMD_EM410X_DEMOD 0x021c +#define CMD_LF_PCF7931_READ 0x0217 +#define CMD_LF_PCF7931_WRITE 0x0223 +#define CMD_LF_EM4X_READWORD 0x0218 +#define CMD_LF_EM4X_WRITEWORD 0x0219 +#define CMD_LF_IO_DEMOD 0x021A +#define CMD_LF_IO_CLONE 0x021B +#define CMD_LF_EM410X_DEMOD 0x021c // Sampling configuration for LF reader/sniffer -#define CMD_SET_LF_SAMPLING_CONFIG 0x021d -#define CMD_FSK_SIM_TAG 0x021E -#define CMD_ASK_SIM_TAG 0x021F -#define CMD_PSK_SIM_TAG 0x0220 -#define CMD_AWID_DEMOD_FSK 0x0221 -#define CMD_VIKING_CLONE_TAG 0x0222 -#define CMD_T55XX_WAKEUP 0x0224 -#define CMD_COTAG 0x0225 -#define CMD_SET_LF_T55XX_CONFIG 0x0226 +#define CMD_LF_SAMPLING_SET_CONFIG 0x021d +#define CMD_LF_FSK_SIMULATE 0x021E +#define CMD_LF_ASK_SIMULATE 0x021F +#define CMD_LF_PSK_SIMULATE 0x0220 +#define CMD_LF_AWID_DEMOD 0x0221 +#define CMD_LF_VIKING_CLONE 0x0222 +#define CMD_LF_T55XX_WAKEUP 0x0224 +#define CMD_LF_COTAG_READ 0x0225 +#define CMD_LF_T55XX_SET_CONFIG 0x0226 /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ // For the 13.56 MHz tags -#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300 -#define CMD_READ_SRI_TAG 0x0303 -#define CMD_ISO_14443B_COMMAND 0x0305 -#define CMD_READER_ISO_15693 0x0310 -#define CMD_SIMTAG_ISO_15693 0x0311 -#define CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693 0x0312 -#define CMD_ISO_15693_COMMAND 0x0313 -#define CMD_ISO_15693_COMMAND_DONE 0x0314 -#define CMD_ISO_15693_FIND_AFI 0x0315 -#define CMD_LF_SNIFF_RAW_ADC_SAMPLES 0x0317 +#define CMD_HF_ISO15693_ACQ_RAW_ADC 0x0300 +#define CMD_HF_SRI_READ 0x0303 +#define CMD_HF_ISO14443B_COMMAND 0x0305 +#define CMD_HF_ISO15693_READER 0x0310 +#define CMD_HF_ISO15693_SIMULATE 0x0311 +#define CMD_HF_ISO15693_RAWADC 0x0312 +#define CMD_HF_ISO15693_COMMAND 0x0313 +#define CMD_HF_ISO15693_FINDAFI 0x0315 +#define CMD_LF_SNIFF_RAW_ADC 0x0317 // For Hitag2 transponders -#define CMD_SNIFF_HITAG 0x0370 -#define CMD_SIMULATE_HITAG 0x0371 -#define CMD_READER_HITAG 0x0372 +#define CMD_LF_HITAG_SNIFF 0x0370 +#define CMD_LF_HITAG_SIMULATE 0x0371 +#define CMD_LF_HITAG_READER 0x0372 // For HitagS -#define CMD_SIMULATE_HITAG_S 0x0368 -#define CMD_TEST_HITAGS_TRACES 0x0367 -#define CMD_READ_HITAG_S 0x0373 -#define CMD_WR_HITAG_S 0x0375 -#define CMD_EMU_HITAG_S 0x0376 +#define CMD_LF_HITAGS_SIMULATE 0x0368 +#define CMD_LF_HITAGS_TEST_TRACES 0x0367 +#define CMD_LF_HITAGS_READ 0x0373 +#define CMD_LF_HITAGS_WRITE 0x0375 -#define CMD_ANTIFUZZ_ISO_14443a 0x0380 -#define CMD_SIMULATE_TAG_ISO_14443B 0x0381 -#define CMD_SNIFF_ISO_14443B 0x0382 -#define CMD_SNIFF_ISO_14443a 0x0383 -#define CMD_SIMULATE_TAG_ISO_14443a 0x0384 -#define CMD_READER_ISO_14443a 0x0385 +#define CMD_HF_ISO14443A_ANTIFUZZ 0x0380 +#define CMD_HF_ISO14443B_SIMULATE 0x0381 +#define CMD_HF_ISO14443B_SNIFF 0x0382 +#define CMD_HF_ISO14443A_SNIFF 0x0383 +#define CMD_HF_ISO14443A_SIMULATE 0x0384 +#define CMD_HF_ISO14443A_READER 0x0385 -#define CMD_SIMULATE_TAG_LEGIC_RF 0x0387 -#define CMD_READER_LEGIC_RF 0x0388 -#define CMD_WRITER_LEGIC_RF 0x0389 +#define CMD_HF_LEGIC_SIMULATE 0x0387 +#define CMD_HF_LEGIC_READER 0x0388 +#define CMD_HF_LEGIC_WRITER 0x0389 -#define CMD_EPA_PACE_COLLECT_NONCE 0x038A -#define CMD_EPA_PACE_REPLAY 0x038B +#define CMD_HF_EPA_COLLECT_NONCE 0x038A +#define CMD_HF_EPA_REPLAY 0x038B -#define CMD_LEGIC_INFO 0x03BC -#define CMD_LEGIC_ESET 0x03BD -#define CMD_LEGIC_EGET 0x03BE +#define CMD_HF_LEGIC_INFO 0x03BC +#define CMD_HF_LEGIC_ESET 0x03BD -#define CMD_SNIFF_ICLASS 0x0392 -#define CMD_SIMULATE_TAG_ICLASS 0x0393 -#define CMD_READER_ICLASS 0x0394 -#define CMD_READER_ICLASS_REPLAY 0x0395 +#define CMD_HF_ICLASS_SNIFF 0x0392 +#define CMD_HF_ICLASS_SIMULATE 0x0393 +#define CMD_HF_ICLASS_READER 0x0394 +#define CMD_HF_ICLASS_REPLAY 0x0395 #define CMD_ICLASS_ISO14443A_WRITE 0x0397 -#define CMD_ICLASS_EML_MEMSET 0x0398 +#define CMD_HF_ICLASS_EML_MEMSET 0x0398 // For measurements of the antenna tuning #define CMD_MEASURE_ANTENNA_TUNING 0x0400 @@ -170,53 +166,51 @@ typedef struct { // For mifare commands #define CMD_MIFARE_SET_DBGMODE 0x0600 -#define CMD_MIFARE_EML_MEMCLR 0x0601 -#define CMD_MIFARE_EML_MEMSET 0x0602 -#define CMD_MIFARE_EML_MEMGET 0x0603 -#define CMD_MIFARE_EML_CARDLOAD 0x0604 +#define CMD_HF_MIFARE_EML_MEMCLR 0x0601 +#define CMD_HF_MIFARE_EML_MEMSET 0x0602 +#define CMD_HF_MIFARE_EML_MEMGET 0x0603 +#define CMD_HF_MIFARE_EML_LOAD 0x0604 // magic chinese card commands -#define CMD_MIFARE_CSETBLOCK 0x0605 -#define CMD_MIFARE_CGETBLOCK 0x0606 -#define CMD_MIFARE_CIDENT 0x0607 +#define CMD_HF_MIFARE_CSETBL 0x0605 +#define CMD_HF_MIFARE_CGETBL 0x0606 +#define CMD_HF_MIFARE_CIDENT 0x0607 -#define CMD_SIMULATE_MIFARE_CARD 0x0610 +#define CMD_HF_MIFARE_SIMULATE 0x0610 -#define CMD_READER_MIFARE 0x0611 -#define CMD_MIFARE_NESTED 0x0612 -#define CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES 0x0613 +#define CMD_HF_MIFARE_READER 0x0611 +#define CMD_HF_MIFARE_NESTED 0x0612 +#define CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES 0x0613 -#define CMD_MIFARE_READBL 0x0620 -#define CMD_MIFAREU_READBL 0x0720 -#define CMD_MIFARE_READSC 0x0621 -#define CMD_MIFAREU_READCARD 0x0721 -#define CMD_MIFARE_WRITEBL 0x0622 -#define CMD_MIFAREU_WRITEBL 0x0722 -#define CMD_MIFAREU_WRITEBL_COMPAT 0x0723 +#define CMD_HF_MIFARE_READBL 0x0620 +#define CMD_HF_MIFAREU_READBL 0x0720 +#define CMD_HF_MIFARE_READSC 0x0621 +#define CMD_HF_MIFAREU_READCARD 0x0721 +#define CMD_HF_MIFARE_WRITEBL 0x0622 +#define CMD_HF_MIFAREU_WRITEBL 0x0722 -#define CMD_MIFARE_CHKKEYS 0x0623 -#define CMD_MIFARE_SETMOD 0x0624 +#define CMD_HF_MIFARE_CHKKEYS 0x0623 +#define CMD_HF_MIFARE_SETMOD 0x0624 -#define CMD_MIFARE_SNIFFER 0x0630 +#define CMD_HF_MIFARE_SNIFF 0x0630 //ultralightC -#define CMD_MIFAREUC_AUTH 0x0724 +#define CMD_HF_MIFAREUC_AUTH 0x0724 //0x0725 and 0x0726 no longer used -#define CMD_MIFAREUC_SETPWD 0x0727 +#define CMD_HF_MIFAREUC_SETPWD 0x0727 // mifare desfire -#define CMD_MIFARE_DESFIRE_READBL 0x0728 -#define CMD_MIFARE_DESFIRE_WRITEBL 0x0729 -#define CMD_MIFARE_DESFIRE_AUTH1 0x072a -#define CMD_MIFARE_DESFIRE_AUTH2 0x072b -#define CMD_MIFARE_DES_READER 0x072c -#define CMD_MIFARE_DESFIRE_INFO 0x072d -#define CMD_MIFARE_DESFIRE 0x072e +#define CMD_HF_DESFIRE_READBL 0x0728 +#define CMD_HF_DESFIRE_WRITEBL 0x0729 +#define CMD_HF_DESFIRE_AUTH1 0x072a +#define CMD_HF_DESFIRE_AUTH2 0x072b +#define CMD_HF_DESFIRE_READER 0x072c +#define CMD_HF_DESFIRE_INFO 0x072d +#define CMD_HF_DESFIRE_COMMAND 0x072e -#define CMD_MIFARE_COLLECT_NONCES 0x072f -#define CMD_HF_SNIFFER 0x0800 +#define CMD_HF_SNIFF 0x0800 #define CMD_UNKNOWN 0xFFFF diff --git a/client/deprecated-hid-flasher/unbind-proxmark b/tools/deprecated-hid-flasher/unbind-proxmark similarity index 100% rename from client/deprecated-hid-flasher/unbind-proxmark rename to tools/deprecated-hid-flasher/unbind-proxmark diff --git a/tools/fpga_compress/Makefile b/tools/fpga_compress/Makefile new file mode 100644 index 000000000..86c995924 --- /dev/null +++ b/tools/fpga_compress/Makefile @@ -0,0 +1,21 @@ +MYSRCPATHS = +MYINCLUDES = -I../../common_fpga +MYCFLAGS = -std=c99 -D_ISOC99_SOURCE +MYDEFS = +MYSRCS = +MYLIBS = + +ZLIBPATH = ../../common/zlib +MYINCLUDES += -I$(ZLIBPATH) +MYLIBS += $(OBJDIR)/libz.a + +BINS = fpga_compress + +ROOT_DIR:=$(dir $(realpath $(lastword $(MAKEFILE_LIST)))) + +include ../../Makefile.host + +fpga_compress: $(OBJDIR)/fpga_compress.o $(MYOBJS) +$(OBJDIR)/libz.a: + $(info [*] MAKE zlib) + $(Q)$(MAKE) --no-print-directory -C $(ZLIBPATH) OBJDIR=$(ROOT_DIR)$(OBJDIR) BINDIR=$(ROOT_DIR)$(OBJDIR) all diff --git a/client/fpga_compress.c b/tools/fpga_compress/fpga_compress.c similarity index 99% rename from client/fpga_compress.c rename to tools/fpga_compress/fpga_compress.c index a030afe81..54d2438d2 100644 --- a/client/fpga_compress.c +++ b/tools/fpga_compress/fpga_compress.c @@ -15,18 +15,14 @@ #include #include #include -#include -#include -#include #include "fpga.h" #include "zlib.h" -#define MAX(a,b) ((a)>(b)?(a):(b)) - // zlib configuration #define COMPRESS_LEVEL 9 // use best possible compression #define COMPRESS_WINDOW_BITS 15 // default = max = 15 for a window of 2^15 = 32KBytes #define COMPRESS_MEM_LEVEL 9 // determines the amount of memory allocated during compression. Default = 8. + /* COMPRESS_STRATEGY can be Z_DEFAULT_STRATEGY (the default), Z_FILTERED (more huffmann, less string matching), @@ -341,6 +337,8 @@ static int FpgaGatherVersion(FILE *infile, char *infile_name, char *dst, int len for (uint16_t i = 0; i < fpga_info_len; i++) { char c = (char)fgetc(infile); if (i < sizeof(tempstr)) { + if (c == '/') c = '-'; + if (c == ' ') c = '0'; tempstr[i] = c; } } diff --git a/tools/install-gnuarm4.sh b/tools/install-gnuarm4.sh deleted file mode 100755 index a5d92c5d5..000000000 --- a/tools/install-gnuarm4.sh +++ /dev/null @@ -1,277 +0,0 @@ -#!/bin/bash - -# Some things for you to configure -BINUTILS_VER="2.19.1a" -GCC_VER="4.3.3" -GDB_VER="6.8a" -NEWLIB_VER="1.17.0" -GMP_VER="4.2.4" -MPFR_VER="2.4.2" -INSIGHT_VER="6.8a" - -# Where you want to install the tools -if [ "${1}" = "" ]; then - echo "Syntax: ${0} [download & build directory (default ${PWD})]" - exit 1 -else - DESTDIR="${1}" -fi - -# Where do you want to build the tools. This is where the log files -# will be written (which you can monitor with 'tail' during compilation). -# You can delete this directory after everything is done. -if [ ! "${2}" = "" ]; then - SRCDIR="${2}" -else - SRCDIR="${PWD}" -fi -BUILDDIR=${SRCDIR}/build-gnuarm4 - -# Where to get each of the toolchain components -BINUTILS=http://ftp.gnu.org/gnu/binutils/binutils-${BINUTILS_VER}.tar.bz2 -BINUTILS_TAR=binutils-${BINUTILS_VER}.tar.bz2 -GCCCORE=http://ftp.gnu.org/gnu/gcc/gcc-${GCC_VER}/gcc-core-${GCC_VER}.tar.bz2 -GCCCORE_TAR=gcc-core-${GCC_VER}.tar.bz2 -GPP=http://ftp.gnu.org/gnu/gcc/gcc-${GCC_VER}/gcc-g++-${GCC_VER}.tar.bz2 -GPP_TAR=gcc-g++-${GCC_VER}.tar.bz2 -NEWLIB=ftp://sources.redhat.com/pub/newlib/newlib-${NEWLIB_VER}.tar.gz -NEWLIB_TAR=newlib-${NEWLIB_VER}.tar.gz -#INSIGHT=ftp://sourceware.org/pub/insight/releases/insight-${INSIGHT_VER}.tar.bz2 -INSIGHT=http://mirrors.kernel.org/sources.redhat.com/insight/releases/insight-${INSIGHT_VER}.tar.bz2 -INSIGHT_TAR=insight-${INSIGHT_VER}.tar.bz2 -#INSIGHT=http://www.mirrorservice.org/sites/sources.redhat.com/pub/insight/releases/insight-${INSIGHT_VER}.tar.bz2 -GDB=http://ftp.gnu.org/gnu/gdb/gdb-${GDB_VER}.tar.bz2 -GDB_TAR=gdb-${GDB_VER}.tar.bz2 -GMP=http://ftp.sunet.se/pub/gnu/gmp/gmp-${GMP_VER}.tar.bz2 -GMP_TAR=gmp-${GMP_VER}.tar.bz2 -MPFR=http://ftp.gnu.org/gnu/mpfr/mpfr-${MPFR_VER}.tar.bz2 -MPFR_TAR=mpfr-${MPFR_VER}.tar.bz2 -GNU_KEYRING_GPG=gnu-keyring.gpg -GNU_KEYRING=ftp://ftp.gnu.org/gnu/${GNU_KEYRING_GPG} - -# Common configuration options (i.e., things to pass to 'configure') -COMMON_CFG="--enable-interwork --target=arm-eabi --program-prefix=arm-none-eabi- --prefix=${DESTDIR} --disable-werror --enable-languages=c,c++ --enable-multilib --disable-shared" - -# Extra configuration options for each toolchain component -BINUTILS_CFG= -GCCCORE_CFG="--disable-nls --disable-threads --with-gcc --with-gnu-ld --with-gnu-as --with-dwarf2 --with-newlib --with-headers=${BUILDDIR}/newlib-${NEWLIB_VER}/newlib/libc/include --disable-libssp --disable-libstdcxx-pch --disable-libmudflap --disable-libgomp -v" -NEWLIB_CFG= -INSIGHT_CFG= -GDB_CFG= - -# Make flags -MAKEFLAGS="-j 4" - -# wget options -# -nv: non-verbose but not too quiet (still print errors/warnings) -# -nc: no-clobber, do not download a file that already exists -# -t 0: retry indefinitely -# -a wget.log: append errors/warnings to wget.log file -# -c continue -#WGET_OPTS="-nv -nc -t 0 -a wget.log" -WGET_OPTS="-c -t 0" - -# Compiler flags for compiling Newlib (-O2 is already hard-coded) -NEWLIB_FLAGS="-march=armv4t -mcpu=arm7tdmi -g" - -# GPG options to avoid polluting the user's keyring -GPG_OPTS="--keyring ${GNU_KEYRING_GPG} --no-default-keyring --homedir ." - -############################################################################ -# End of configuration section. You shouldn't have to modify anything below. -############################################################################ - -if [[ "$USER" != "root" ]]; then - echo "*** Warning! Not running as root!" - echo "Installation may fail if you do not have appropriate permissions!" -fi - -mkdir -p ${BUILDDIR} -cd ${SRCDIR} - -if [[ -f all.downloaded ]]; then - echo Looks like all downloads are complete, skipping downloads -else - wget ${WGET_OPTS} ${GNU_KEYRING} - - # TODO: guess it's better to have a function that "downloads, checks file-presence and signature, and returns true/false" whether the file is ok - # Function will check if file exists (otherwise try to download the file - if failed and file still doesn't exist, complain and exit the script) - # Check if signature file exists (otherwise download the signature file as well - if download fail, warn the user and return function) - # Check the signature. If failed, backup-by-renaming current files, redownload both file & signature, run the function body one more time - if still no success, warn and return from function - - function download_lib { - echo Now downloading $1 - wget ${WGET_OPTS} $2 - } - - function download_signed_lib { - download_lib $1 $2 - wget -N ${WGET_OPTS} $2.sig - gpg $GPG_OPTS --verify $3.sig 2> /dev/null - if [[ $? != 0 ]]; then - echo "Failed signature check for:" $3.sig - exit 1 - fi - } - - # NOTE: If new downloads are added here, please see the IMPORTANT note below - download_signed_lib BINUTILS ${BINUTILS} ${BINUTILS_TAR} || exit 1 - download_signed_lib GCC ${GCCCORE} ${GCCCORE_TAR} || exit 1 - download_signed_lib G++ ${GPP} ${GPP_TAR} || exit 1 - download_lib NEWLIB ${NEWLIB} - # TODO: signature/hash check - download_lib INSIGHT ${INSIGHT} - # TODO: signature/hash check - download_signed_lib GDB ${GDB} ${GDB_TAR} || exit 1 - download_signed_lib GMP ${GMP} ${GMP_TAR} || exit 1 - download_signed_lib MPFR ${MPFR} ${MPFR_TAR} || exit 1 - - # IMPORTANT: Here is the number of .tar. archives downloaded above. Please update if new .tar. are added to download list. - if [[ `ls -1 *.tar.bz2 *.tar.gz | wc -l` != 8 ]]; then - echo "Seems like not all prerequisite files downloaded... Exiting." - exit 1 - else - touch all.downloaded - fi -fi - -cd ${BUILDDIR} -if [[ -f binutils.built ]]; then - echo Looks like BINUTILS was already built. -else - echo Building BINUTILS... - tar -xjf ../`basename ${BINUTILS}` - echo ___________________ > make.log - echo Building binutils... >> make.log - cd `find . -maxdepth 1 -type d -name 'binutils*'` - mkdir gnuarm - cd gnuarm - ../configure ${COMMON_CFG} ${BINUTILS_CFG} >> ../../make.log 2>&1 - make ${MAKEFLAGS} MAKEINFO=`which makeinfo` >> ../../make.log 2>&1 - make install >> ../../make.log 2>&1 - cd ../.. - touch binutils.built -fi - - echo ___________________ >> make.log - echo Adding ${DESTDIR}/bin to PATH >> make.log -export PATH; PATH=${DESTDIR}/bin:$PATH - echo ___________________ >> make.log - -if [[ -f gcc.built ]]; then - echo Looks like GCC was already built. -else - echo Building GCC... - tar -xjf ../`basename ${GCCCORE}` - tar -xjf ../`basename ${GPP}` - tar -xjf ../`basename ${GMP}` - ln -s "${BUILDDIR}/gmp-${GMP_VER}" "${BUILDDIR}/gcc-${GCC_VER}/gmp" - tar -xjf ../`basename ${MPFR}` - ln -s "${BUILDDIR}/mpfr-${MPFR_VER}" "${BUILDDIR}/gcc-${GCC_VER}/mpfr" - tar -xzf ../`basename ${NEWLIB}` - - echo ___________________ >> make.log - -cat << EOF > gcc.patch ---- gcc-4.3.3.orig/gcc/config/arm/t-arm-elf -+++ gcc-4.3.3.mod/gcc/config/arm/t-arm-elf -@@ -33,8 +33,8 @@ - # MULTILIB_DIRNAMES += fpu soft - # MULTILIB_EXCEPTIONS += *mthumb/*mhard-float* - # --# MULTILIB_OPTIONS += mno-thumb-interwork/mthumb-interwork --# MULTILIB_DIRNAMES += normal interwork -+MULTILIB_OPTIONS += mno-thumb-interwork/mthumb-interwork -+MULTILIB_DIRNAMES += normal interwork - # - # MULTILIB_OPTIONS += fno-leading-underscore/fleading-underscore - # MULTILIB_DIRNAMES += elf under -EOF - - echo Patching GCC >> make.log - cd `find . -maxdepth 1 -type d -name 'gcc*'` - patch -p1 < ../gcc.patch - echo Building gcc... >> make.log - mkdir gnuarm - cd gnuarm - ../configure ${COMMON_CFG} ${GCCCORE_CFG} >> ../../make.log 2>&1 - make ${MAKEFLAGS} all-gcc >> ../../make.log 2>&1 - make install >> ../../make.log 2>&1 - cd ../.. - touch gcc.built -fi - -if [[ -f newlib.built ]]; then - echo Looks like NEWLIB was already built. -else - echo Building NEWLIB... - echo ___________________ >> make.log - echo Building newlib... >> make.log - cd `find . -maxdepth 1 -type d -name 'newlib*'` - mkdir gnuarm - cd gnuarm - ../configure ${COMMON_CFG} ${NEWLIB_CFG} >> ../../make.log 2>&1 - - # This line adds our NEWLIB_CFLAGS to the configure.host file in the - # newlib subdirectory. This is the only way I could find to tell Newlib to - # compile itself with the -mmarch=armv4t and -mcpu=arm7tdmi flags. -# sed -i "/^newlib_cflags=/s/=.*\$/=\"${NEWLIB_FLAGS}\"/" ../newlib/configure.host - make ${MAKEFLAGS} >> ../../make.log 2>&1 - make install >> ../../make.log 2>&1 - cd ../.. - touch newlib.built -fi - - echo ___________________ >> make.log - echo "Now that newlib is built, second pass for GCC..." >> make.log - cd `find . -maxdepth 1 -type d -name 'gcc*'` - cd gnuarm - make ${MAKEFLAGS} >> ../../make.log 2>&1 - make install >> ../../make.log 2>&1 - cd ../.. - - -if [[ -f insight.built ]]; then - echo Looks like INSIGHT was already built. -else - echo Building INSIGHT... - tar -xjf ../`basename ${INSIGHT}` - echo ___________________ >> make.log - echo Building insight... >> make.log - cd `find . -maxdepth 1 -type d -name 'insight*'` - mkdir gnuarm - cd gnuarm - ../configure ${COMMON_CFG} ${INSIGHT_CFG} >> ../../make.log 2>&1 - make ${MAKEFLAGS} >> ../../make.log 2>&1 - make install >> ../../make.log 2>&1 - cd ../.. - touch insight.built -fi - -if [[ -f gdb.built ]]; then - echo Looks like GDB was already built. -else - echo Building GDB... - tar -xjf ../`basename ${GDB}` - echo ___________________ >> make.log - echo Building insight... >> make.log - cd `find . -maxdepth 1 -type d -name 'gdb*'` - mkdir gnuarm - cd gnuarm - ../configure ${COMMON_CFG} ${GDB_CFG} >> ../../make.log 2>&1 - make ${MAKEFLAGS} >> ../../make.log 2>&1 - make install >> ../../make.log 2>&1 - cd ../.. - touch gdb.built -fi - -echo ___________________ >> make.log -echo Build complete. >> make.log - -cd ${DESTDIR} -chmod -R a+rX . - -echo Downloaded archives are in ${SRCDIR} -echo build driectory: ${BUILDDIR} -echo set environment variable ARMLIB to ${DESTDIR}/lib/gcc/arm-eabi/4.3.3/interwork for Makefile.linux -exit 0 diff --git a/tools/mfkey/Makefile b/tools/mfkey/Makefile index 24508265a..a7b006f6e 100644 --- a/tools/mfkey/Makefile +++ b/tools/mfkey/Makefile @@ -1,27 +1,14 @@ -# Hide full compilation line: -ifneq ($(V),1) - Q?=@ -endif -# To see full command lines, use make V=1 +MYSRCPATHS = ../../common ../../common/crapto1 +MYSRCS = crypto1.c crapto1.c bucketsort.c +MYINCLUDES = -I../../include -I../../common +MYCFLAGS = -std=c99 -D_ISOC99_SOURCE +MYDEFS = -VPATH = ../../common ../../common/crapto1 ../../client -CC = gcc -LD = gcc -CFLAGS += -std=c99 -D_ISOC99_SOURCE -I../../include -I../../common -I../../client -Wall -O3 -LDFLAGS += +BINS = mfkey32 mfkey32v2 mfkey64 +INSTALLTOOLS = $(BINS) -OBJS = crypto1.o crapto1.o parity.o util_posix.o bucketsort.o -EXES = mfkey32 mfkey32v2 mfkey64 +include ../../Makefile.host -all: $(OBJS) $(EXES) - -%.o : %.c - $(info [-] CC $<) - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -% : %.c $(OBJS) - $(info [=] LD $@) - $(Q)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $< - -clean: - $(Q)rm -f $(OBJS) $(EXES) +mfkey32 : $(OBJDIR)/mfkey32.o $(MYOBJS) +mfkey32v2 : $(OBJDIR)/mfkey32v2.o $(MYOBJS) +mfkey64 : $(OBJDIR)/mfkey64.o $(MYOBJS) diff --git a/tools/mkversion.pl b/tools/mkversion.pl index aaac146f8..997c2081b 100644 --- a/tools/mkversion.pl +++ b/tools/mkversion.pl @@ -64,7 +64,7 @@ $fullgitinfo =~ s/(\s)//g; $fullgitinfo = substr $fullgitinfo, 0, 49; print < $@ - -%.o: %.c - $(info [-] CC $<) - $(Q)$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $< +nonce2key : $(OBJDIR)/nonce2key.o $(MYOBJS) diff --git a/tools/nonce2key/crapto1.c b/tools/nonce2key/crapto1.c deleted file mode 100644 index 3be92c0f2..000000000 --- a/tools/nonce2key/crapto1.c +++ /dev/null @@ -1,549 +0,0 @@ -/* crapto1.c - - 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 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, US$ - - Copyright (C) 2008-2014 bla -*/ -#include "crapto1.h" -#include - -#if !defined LOWMEM && defined __GNUC__ -static uint8_t filterlut[1 << 20]; -static void __attribute__((constructor)) fill_lut() { - uint32_t i; - for (i = 0; i < 1 << 20; ++i) - filterlut[i] = filter(i); -} -#define filter(x) (filterlut[(x) & 0xfffff]) -#endif - - - -typedef struct bucket { - uint32_t *head; - uint32_t *bp; -} bucket_t; - -typedef bucket_t bucket_array_t[2][0x100]; - -typedef struct bucket_info { - struct { - uint32_t *head, *tail; - } bucket_info[2][0x100]; - uint32_t numbuckets; -} bucket_info_t; - - -static void bucket_sort_intersect(uint32_t *const estart, uint32_t *const estop, - uint32_t *const ostart, uint32_t *const ostop, - bucket_info_t *bucket_info, bucket_array_t bucket) { - uint32_t *p1, *p2; - uint32_t *start[2]; - uint32_t *stop[2]; - - start[0] = estart; - stop[0] = estop; - start[1] = ostart; - stop[1] = ostop; - - // init buckets to be empty - for (uint32_t i = 0; i < 2; i++) { - for (uint32_t j = 0x00; j <= 0xff; j++) { - bucket[i][j].bp = bucket[i][j].head; - } - } - - // sort the lists into the buckets based on the MSB (contribution bits) - for (uint32_t i = 0; i < 2; i++) { - for (p1 = start[i]; p1 <= stop[i]; p1++) { - uint32_t bucket_index = (*p1 & 0xff000000) >> 24; - *(bucket[i][bucket_index].bp++) = *p1; - } - } - - - // write back intersecting buckets as sorted list. - // fill in bucket_info with head and tail of the bucket contents in the list and number of non-empty buckets. - for (uint32_t i = 0; i < 2; i++) { - p1 = start[i]; - uint32_t nonempty_bucket = 0; - for (uint32_t j = 0x00; j <= 0xff; j++) { - if (bucket[0][j].bp != bucket[0][j].head && bucket[1][j].bp != bucket[1][j].head) { // non-empty intersecting buckets only - bucket_info->bucket_info[i][nonempty_bucket].head = p1; - for (p2 = bucket[i][j].head; p2 < bucket[i][j].bp; *p1++ = *p2++); - bucket_info->bucket_info[i][nonempty_bucket].tail = p1 - 1; - nonempty_bucket++; - } - } - bucket_info->numbuckets = nonempty_bucket; - } -} - -/** update_contribution - * helper, calculates the partial linear feedback contributions and puts in MSB - */ -static inline void update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2) { - uint32_t p = *item >> 25; - - p = p << 1 | parity(*item & mask1); - p = p << 1 | parity(*item & mask2); - *item = p << 24 | (*item & 0xffffff); -} - -/** extend_table - * using a bit of the keystream extend the table of possible lfsr states - */ -static inline void extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in) { - in <<= 24; - for (*tbl <<= 1; tbl <= *end; *++tbl <<= 1) - if (filter(*tbl) ^ filter(*tbl | 1)) { - *tbl |= filter(*tbl) ^ bit; - update_contribution(tbl, m1, m2); - *tbl ^= in; - } else if (filter(*tbl) == bit) { - *++*end = tbl[1]; - tbl[1] = tbl[0] | 1; - update_contribution(tbl, m1, m2); - *tbl++ ^= in; - update_contribution(tbl, m1, m2); - *tbl ^= in; - } else - *tbl-- = *(*end)--; -} -/** extend_table_simple - * using a bit of the keystream extend the table of possible lfsr states - */ -static inline void extend_table_simple(uint32_t *tbl, uint32_t **end, int bit) { - for (*tbl <<= 1; tbl <= *end; *++tbl <<= 1) { - if (filter(*tbl) ^ filter(*tbl | 1)) { // replace - *tbl |= filter(*tbl) ^ bit; - } else if (filter(*tbl) == bit) { // insert - *++*end = *++tbl; - *tbl = tbl[-1] | 1; - } else { // drop - *tbl-- = *(*end)--; - } - } -} -/** recover - * recursively narrow down the search space, 4 bits of keystream at a time - */ -static struct Crypto1State * -recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks, - uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem, - struct Crypto1State *sl, uint32_t in, bucket_array_t bucket) { - bucket_info_t bucket_info; - - if (rem == -1) { - for (uint32_t *e = e_head; e <= e_tail; ++e) { - *e = *e << 1 ^ parity(*e & LF_POLY_EVEN) ^ (!!(in & 4)); - for (uint32_t *o = o_head; o <= o_tail; ++o, ++sl) { - sl->even = *o; - sl->odd = *e ^ parity(*o & LF_POLY_ODD); - sl[1].odd = sl[1].even = 0; - } - } - return sl; - } - - for (uint32_t i = 0; i < 4 && rem--; i++) { - oks >>= 1; - eks >>= 1; - in >>= 2; - extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0); - if (o_head > o_tail) - return sl; - - extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, in & 3); - if (e_head > e_tail) - return sl; - } - - bucket_sort_intersect(e_head, e_tail, o_head, o_tail, &bucket_info, bucket); - - for (int i = bucket_info.numbuckets - 1; i >= 0; i--) { - sl = recover(bucket_info.bucket_info[1][i].head, bucket_info.bucket_info[1][i].tail, oks, - bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks, - rem, sl, in, bucket); - } - - return sl; -} -/** lfsr_recovery - * recover the state of the lfsr given 32 bits of the keystream - * additionally you can use the in parameter to specify the value - * that was fed into the lfsr at the time the keystream was generated - */ -struct Crypto1State *lfsr_recovery32(uint32_t ks2, uint32_t in) { - struct Crypto1State *statelist; - uint32_t *odd_head = 0, *odd_tail = 0, oks = 0; - uint32_t *even_head = 0, *even_tail = 0, eks = 0; - - // split the keystream into an odd and even part - for (int i = 31; i >= 0; i -= 2) - oks = oks << 1 | BEBIT(ks2, i); - for (int i = 30; i >= 0; i -= 2) - eks = eks << 1 | BEBIT(ks2, i); - - odd_head = odd_tail = malloc(sizeof(uint32_t) << 21); - even_head = even_tail = malloc(sizeof(uint32_t) << 21); - statelist = malloc(sizeof(struct Crypto1State) << 18); - if (!odd_tail-- || !even_tail-- || !statelist) { - free(statelist); - statelist = 0; - goto out; - } - - statelist->odd = statelist->even = 0; - - // allocate memory for out of place bucket_sort - bucket_array_t bucket; - - for (uint32_t i = 0; i < 2; i++) { - for (uint32_t j = 0; j <= 0xff; j++) { - bucket[i][j].head = malloc(sizeof(uint32_t) << 14); - if (!bucket[i][j].head) { - goto out; - } - } - } - - // initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream - for (int i = 1 << 20; i >= 0; --i) { - if (filter(i) == (oks & 1)) - *++odd_tail = i; - if (filter(i) == (eks & 1)) - *++even_tail = i; - } - - // extend the statelists. Look at the next 8 Bits of the keystream (4 Bit each odd and even): - for (uint8_t i = 0; i < 4; i++) { - extend_table_simple(odd_head, &odd_tail, (oks >>= 1) & 1); - extend_table_simple(even_head, &even_tail, (eks >>= 1) & 1); - } - - // the statelists now contain all states which could have generated the last 10 Bits of the keystream. - // 22 bits to go to recover 32 bits in total. From now on, we need to take the "in" - // parameter into account. - in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping - recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket); - -out: - for (uint32_t i = 0; i < 2; i++) - for (uint32_t j = 0; j <= 0xff; j++) - free(bucket[i][j].head); - free(odd_head); - free(even_head); - return statelist; -} - -static const uint32_t S1[] = { 0x62141, 0x310A0, 0x18850, 0x0C428, 0x06214, - 0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83, - 0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA - }; -static const uint32_t S2[] = { 0x3A557B00, 0x5D2ABD80, 0x2E955EC0, 0x174AAF60, - 0x0BA557B0, 0x05D2ABD8, 0x0449DE68, 0x048464B0, 0x42423258, 0x278192A8, - 0x156042D0, 0x0AB02168, 0x43F89B30, 0x61FC4D98, 0x765EAD48, 0x7D8FDD20, - 0x7EC7EE90, 0x7F63F748, 0x79117020 - }; -static const uint32_t T1[] = { - 0x4F37D, 0x279BE, 0x97A6A, 0x4BD35, 0x25E9A, 0x12F4D, 0x097A6, 0x80D66, - 0xC4006, 0x62003, 0xB56B4, 0x5AB5A, 0xA9318, 0xD0F39, 0x6879C, 0xB057B, - 0x582BD, 0x2C15E, 0x160AF, 0x8F6E2, 0xC3DC4, 0xE5857, 0x72C2B, 0x39615, - 0x98DBF, 0xC806A, 0xE0680, 0x70340, 0x381A0, 0x98665, 0x4C332, 0xA272C -}; -static const uint32_t T2[] = { 0x3C88B810, 0x5E445C08, 0x2982A580, 0x14C152C0, - 0x4A60A960, 0x253054B0, 0x52982A58, 0x2FEC9EA8, 0x1156C4D0, 0x08AB6268, - 0x42F53AB0, 0x217A9D58, 0x161DC528, 0x0DAE6910, 0x46D73488, 0x25CB11C0, - 0x52E588E0, 0x6972C470, 0x34B96238, 0x5CFC3A98, 0x28DE96C8, 0x12CFC0E0, - 0x4967E070, 0x64B3F038, 0x74F97398, 0x7CDC3248, 0x38CE92A0, 0x1C674950, - 0x0E33A4A8, 0x01B959D0, 0x40DCACE8, 0x26CEDDF0 - }; -static const uint32_t C1[] = { 0x846B5, 0x4235A, 0x211AD}; -static const uint32_t C2[] = { 0x1A822E0, 0x21A822E0, 0x21A822E0}; -/** Reverse 64 bits of keystream into possible cipher states - * Variation mentioned in the paper. Somewhat optimized version - */ -struct Crypto1State *lfsr_recovery64(uint32_t ks2, uint32_t ks3) { - struct Crypto1State *statelist, *sl; - uint8_t oks[32], eks[32], hi[32]; - uint32_t low = 0, win = 0; - uint32_t *tail, table[1 << 16]; - int i, j; - - sl = statelist = malloc(sizeof(struct Crypto1State) << 4); - if (!sl) - return 0; - sl->odd = sl->even = 0; - - for (i = 30; i >= 0; i -= 2) { - oks[i >> 1] = BEBIT(ks2, i); - oks[16 + (i >> 1)] = BEBIT(ks3, i); - } - for (i = 31; i >= 0; i -= 2) { - eks[i >> 1] = BEBIT(ks2, i); - eks[16 + (i >> 1)] = BEBIT(ks3, i); - } - - for (i = 0xfffff; i >= 0; --i) { - if (filter(i) != oks[0]) - continue; - - *(tail = table) = i; - for (j = 1; tail >= table && j < 29; ++j) - extend_table_simple(table, &tail, oks[j]); - - if (tail < table) - continue; - - for (j = 0; j < 19; ++j) - low = low << 1 | parity(i & S1[j]); - for (j = 0; j < 32; ++j) - hi[j] = parity(i & T1[j]); - - for (; tail >= table; --tail) { - for (j = 0; j < 3; ++j) { - *tail = *tail << 1; - *tail |= parity((i & C1[j]) ^ (*tail & C2[j])); - if (filter(*tail) != oks[29 + j]) - goto continue2; - } - - for (j = 0; j < 19; ++j) - win = win << 1 | parity(*tail & S2[j]); - - win ^= low; - for (j = 0; j < 32; ++j) { - win = win << 1 ^ hi[j] ^ parity(*tail & T2[j]); - if (filter(win) != eks[j]) - goto continue2; - } - - *tail = *tail << 1 | parity(LF_POLY_EVEN & *tail); - sl->odd = *tail ^ parity(LF_POLY_ODD & win); - sl->even = win; - ++sl; - sl->odd = sl->even = 0; -continue2: - ; - } - } - return statelist; -} - -/** lfsr_rollback_bit - * Rollback the shift register in order to get previous states - */ -uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb) { - int out; - uint8_t ret; - uint32_t t; - - s->odd &= 0xffffff; - t = s->odd, s->odd = s->even, s->even = t; - - out = s->even & 1; - out ^= LF_POLY_EVEN & (s->even >>= 1); - out ^= LF_POLY_ODD & s->odd; - out ^= !!in; - out ^= (ret = filter(s->odd)) & (!!fb); - - s->even |= parity(out) << 23; - return ret; -} -/** lfsr_rollback_byte - * Rollback the shift register in order to get previous states - */ -uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb) { - uint8_t ret = 0; - ret |= lfsr_rollback_bit(s, BIT(in, 7), fb) << 7; - ret |= lfsr_rollback_bit(s, BIT(in, 6), fb) << 6; - ret |= lfsr_rollback_bit(s, BIT(in, 5), fb) << 5; - ret |= lfsr_rollback_bit(s, BIT(in, 4), fb) << 4; - ret |= lfsr_rollback_bit(s, BIT(in, 3), fb) << 3; - ret |= lfsr_rollback_bit(s, BIT(in, 2), fb) << 2; - ret |= lfsr_rollback_bit(s, BIT(in, 1), fb) << 1; - ret |= lfsr_rollback_bit(s, BIT(in, 0), fb) << 0; - return ret; -} -/** lfsr_rollback_word - * Rollback the shift register in order to get previous states - */ -uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) { - - uint32_t ret = 0; - ret |= lfsr_rollback_bit(s, BEBIT(in, 31), fb) << (31 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 30), fb) << (30 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 29), fb) << (29 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 28), fb) << (28 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 27), fb) << (27 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 26), fb) << (26 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 25), fb) << (25 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 24), fb) << (24 ^ 24); - - ret |= lfsr_rollback_bit(s, BEBIT(in, 23), fb) << (23 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 22), fb) << (22 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 21), fb) << (21 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 20), fb) << (20 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 19), fb) << (19 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 18), fb) << (18 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 17), fb) << (17 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 16), fb) << (16 ^ 24); - - ret |= lfsr_rollback_bit(s, BEBIT(in, 15), fb) << (15 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 14), fb) << (14 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 13), fb) << (13 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 12), fb) << (12 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 11), fb) << (11 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 10), fb) << (10 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 9), fb) << (9 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 8), fb) << (8 ^ 24); - - ret |= lfsr_rollback_bit(s, BEBIT(in, 7), fb) << (7 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 6), fb) << (6 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 5), fb) << (5 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 4), fb) << (4 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 3), fb) << (3 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 2), fb) << (2 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 1), fb) << (1 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 0), fb) << (0 ^ 24); - return ret; -} - -/** nonce_distance - * x,y valid tag nonces, then prng_successor(x, nonce_distance(x, y)) = y - */ -static uint16_t *dist = 0; -int nonce_distance(uint32_t from, uint32_t to) { - if (!dist) { - dist = calloc(2 << 16, sizeof(uint8_t)); - if (!dist) - return -1; - uint16_t x = 1; - for (uint16_t i = 1; i; ++i) { - dist[(x & 0xff) << 8 | x >> 8] = i; - x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; - } - } - return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535; -} - - -static uint32_t fastfwd[2][8] = { - { 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB}, - { 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980} -}; - - -/** lfsr_prefix_ks - * - * Is an exported helper function from the common prefix attack - * Described in the "dark side" paper. It returns an -1 terminated array - * of possible partial(21 bit) secret state. - * The required keystream(ks) needs to contain the keystream that was used to - * encrypt the NACK which is observed when varying only the 3 last bits of Nr - * only correct iff [NR_3] ^ NR_3 does not depend on Nr_3 - */ -uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) { - uint32_t *candidates = calloc(4 << 10, sizeof(uint8_t)); - if (!candidates) return 0; - - uint32_t c, entry; - int size = 0, i, good; - - for (i = 0; i < 1 << 21; ++i) { - for (c = 0, good = 1; good && c < 8; ++c) { - entry = i ^ fastfwd[isodd][c]; - good &= (BIT(ks[c], isodd) == filter(entry >> 1)); - good &= (BIT(ks[c], isodd + 2) == filter(entry)); - } - if (good) - candidates[size++] = i; - } - - candidates[size] = -1; - - return candidates; -} - -/** check_pfx_parity - * helper function which eliminates possible secret states using parity bits - */ -static struct Crypto1State *check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8], uint32_t odd, uint32_t even, struct Crypto1State *sl) { - uint32_t good = 1; - - for (uint32_t c = 0; good && c < 8; ++c) { - sl->odd = odd ^ fastfwd[1][c]; - sl->even = even ^ fastfwd[0][c]; - - lfsr_rollback_bit(sl, 0, 0); - lfsr_rollback_bit(sl, 0, 0); - - uint32_t ks3 = lfsr_rollback_bit(sl, 0, 0); - uint32_t ks2 = lfsr_rollback_word(sl, 0, 0); - uint32_t ks1 = lfsr_rollback_word(sl, prefix | c << 5, 1); - - uint32_t nr = ks1 ^ (prefix | c << 5); - uint32_t rr = ks2 ^ rresp; - - good &= parity(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24); - good &= parity(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16); - good &= parity(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8); - good &= parity(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0); - good &= parity(rr & 0x000000ff) ^ parities[c][7] ^ ks3; - } - - return sl + good; -} - -/** lfsr_common_prefix - * Implentation of the common prefix attack. - * Requires the 28 bit constant prefix used as reader nonce (pfx) - * The reader response used (rr) - * The keystream used to encrypt the observed NACK's (ks) - * The parity bits (par) - * It returns a zero terminated list of possible cipher states after the - * tag nonce was fed in - */ - -struct Crypto1State *lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]) { - struct Crypto1State *statelist, *s; - uint32_t *odd, *even, *o, *e, top; - - odd = lfsr_prefix_ks(ks, 1); - even = lfsr_prefix_ks(ks, 0); - - s = statelist = malloc((sizeof * statelist) << 24); // was << 20. Need more for no_par special attack. Enough??? - if (!s || !odd || !even) { - free(statelist); - statelist = 0; - goto out; - } - - for (o = odd; *o + 1; ++o) - for (e = even; *e + 1; ++e) - for (top = 0; top < 64; ++top) { - *o += 1 << 21; - *e += (!(top & 7) + 1) << 21; - s = check_pfx_parity(pfx, rr, par, *o, *e, s); - } - - s->odd = s->even = 0; -out: - free(odd); - free(even); - return statelist; -} diff --git a/tools/nonce2key/crapto1.h b/tools/nonce2key/crapto1.h deleted file mode 100644 index db8b5cba2..000000000 --- a/tools/nonce2key/crapto1.h +++ /dev/null @@ -1,93 +0,0 @@ -/* crapto1.h - - 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 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301, US$ - - Copyright (C) 2008-2014 bla -*/ -#ifndef CRAPTO1_H__ -#define CRAPTO1_H__ -#include -#ifdef __cplusplus -extern "C" { -#endif - -struct Crypto1State {uint32_t odd, even;}; -struct Crypto1State *crypto1_create(uint64_t); -void crypto1_destroy(struct Crypto1State *); -void crypto1_get_lfsr(struct Crypto1State *, uint64_t *); -uint8_t crypto1_bit(struct Crypto1State *, uint8_t, int); -uint8_t crypto1_byte(struct Crypto1State *, uint8_t, int); -uint32_t crypto1_word(struct Crypto1State *, uint32_t, int); -uint32_t prng_successor(uint32_t x, uint32_t n); - -struct Crypto1State *lfsr_recovery32(uint32_t ks2, uint32_t in); -struct Crypto1State *lfsr_recovery64(uint32_t ks2, uint32_t ks3); -uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd); -struct Crypto1State *lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]); - -uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb); -uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb); -uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb); -int nonce_distance(uint32_t from, uint32_t to); -#define SWAPENDIAN(x)\ - (x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16) - -#define FOREACH_VALID_NONCE(N, FILTER, FSIZE)\ - uint32_t __n = 0,__M = 0, N = 0;\ - int __i;\ - for(; __n < 1 << 16; N = prng_successor(__M = ++__n, 16))\ - for(__i = FSIZE - 1; __i >= 0; __i--)\ - if(BIT(FILTER, __i) ^ parity(__M & 0xFF01))\ - break;\ - else if(__i)\ - __M = prng_successor(__M, (__i == 7) ? 48 : 8);\ - else - -#define LF_POLY_ODD (0x29CE5C) -#define LF_POLY_EVEN (0x870804) -#define BIT(x, n) ((x) >> (n) & 1) -#define BEBIT(x, n) BIT(x, (n) ^ 24) -static inline int parity(uint32_t x) { -#if !defined __i386__ || !defined __GNUC__ - x ^= x >> 16; - x ^= x >> 8; - x ^= x >> 4; - return BIT(0x6996, x & 0xf); -#else - __asm__("movl %1, %%eax\n" - "mov %%ax, %%cx\n" - "shrl $0x10, %%eax\n" - "xor %%ax, %%cx\n" - "xor %%ch, %%cl\n" - "setpo %%al\n" - "movzx %%al, %0\n": "=r"(x) : "r"(x): "eax", "ecx"); - return x; -#endif -} -static inline int filter(uint32_t const x) { - uint32_t f; - - f = 0xf22c0 >> (x & 0xf) & 16; - f |= 0x6c9c0 >> (x >> 4 & 0xf) & 8; - f |= 0x3c8b0 >> (x >> 8 & 0xf) & 4; - f |= 0x1e458 >> (x >> 12 & 0xf) & 2; - f |= 0x0d938 >> (x >> 16 & 0xf) & 1; - return BIT(0xEC57E80A, f); -} -#ifdef __cplusplus -} -#endif -#endif diff --git a/tools/nonce2key/crypto1.c b/tools/nonce2key/crypto1.c deleted file mode 100644 index f6f4642e2..000000000 --- a/tools/nonce2key/crypto1.c +++ /dev/null @@ -1,125 +0,0 @@ -/* crypto1.c - - 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 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301, US - - Copyright (C) 2008-2008 bla -*/ -#include "crapto1.h" -#include - -struct Crypto1State *crypto1_create(uint64_t key) { - struct Crypto1State *s = malloc(sizeof(*s)); - if (!s) return NULL; - - s->odd = s->even = 0; - - int i; - //for(i = 47;s && i > 0; i -= 2) { - for (i = 47; i > 0; i -= 2) { - s->odd = s->odd << 1 | BIT(key, (i - 1) ^ 7); - s->even = s->even << 1 | BIT(key, i ^ 7); - } - return s; -} -void crypto1_destroy(struct Crypto1State *state) { - free(state); -} -void crypto1_get_lfsr(struct Crypto1State *state, uint64_t *lfsr) { - int i; - for (*lfsr = 0, i = 23; i >= 0; --i) { - *lfsr = *lfsr << 1 | BIT(state->odd, i ^ 3); - *lfsr = *lfsr << 1 | BIT(state->even, i ^ 3); - } -} -uint8_t crypto1_bit(struct Crypto1State *s, uint8_t in, int is_encrypted) { - uint32_t feedin; - uint32_t tmp; - uint8_t ret = filter(s->odd); - - feedin = ret & (!!is_encrypted); - feedin ^= !!in; - feedin ^= LF_POLY_ODD & s->odd; - feedin ^= LF_POLY_EVEN & s->even; - s->even = s->even << 1 | parity(feedin); - - tmp = s->odd; - s->odd = s->even; - s->even = tmp; - - return ret; -} -uint8_t crypto1_byte(struct Crypto1State *s, uint8_t in, int is_encrypted) { - uint8_t ret = 0; - ret |= crypto1_bit(s, BIT(in, 0), is_encrypted) << 0; - ret |= crypto1_bit(s, BIT(in, 1), is_encrypted) << 1; - ret |= crypto1_bit(s, BIT(in, 2), is_encrypted) << 2; - ret |= crypto1_bit(s, BIT(in, 3), is_encrypted) << 3; - ret |= crypto1_bit(s, BIT(in, 4), is_encrypted) << 4; - ret |= crypto1_bit(s, BIT(in, 5), is_encrypted) << 5; - ret |= crypto1_bit(s, BIT(in, 6), is_encrypted) << 6; - ret |= crypto1_bit(s, BIT(in, 7), is_encrypted) << 7; - return ret; -} -uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) { - uint32_t ret = 0; - ret |= crypto1_bit(s, BEBIT(in, 0), is_encrypted) << (0 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 1), is_encrypted) << (1 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 2), is_encrypted) << (2 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 3), is_encrypted) << (3 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 4), is_encrypted) << (4 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 5), is_encrypted) << (5 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 6), is_encrypted) << (6 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 7), is_encrypted) << (7 ^ 24); - - ret |= crypto1_bit(s, BEBIT(in, 8), is_encrypted) << (8 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 9), is_encrypted) << (9 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 10), is_encrypted) << (10 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 11), is_encrypted) << (11 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 12), is_encrypted) << (12 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 13), is_encrypted) << (13 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 14), is_encrypted) << (14 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 15), is_encrypted) << (15 ^ 24); - - ret |= crypto1_bit(s, BEBIT(in, 16), is_encrypted) << (16 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 17), is_encrypted) << (17 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 18), is_encrypted) << (18 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 19), is_encrypted) << (19 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 20), is_encrypted) << (20 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 21), is_encrypted) << (21 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 22), is_encrypted) << (22 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 23), is_encrypted) << (23 ^ 24); - - ret |= crypto1_bit(s, BEBIT(in, 24), is_encrypted) << (24 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 25), is_encrypted) << (25 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 26), is_encrypted) << (26 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 27), is_encrypted) << (27 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 28), is_encrypted) << (28 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 29), is_encrypted) << (29 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 30), is_encrypted) << (30 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 31), is_encrypted) << (31 ^ 24); - return ret; -} - -/* prng_successor - * helper used to obscure the keystream during authentication - */ -uint32_t prng_successor(uint32_t x, uint32_t n) { - SWAPENDIAN(x); - while (n--) - x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; - - return SWAPENDIAN(x); -} diff --git a/tools/nonce2key/nonce2key.c b/tools/nonce2key/nonce2key.c index f4cb10e62..d7ccec0bb 100644 --- a/tools/nonce2key/nonce2key.c +++ b/tools/nonce2key/nonce2key.c @@ -1,4 +1,4 @@ -#include "crapto1.h" +#include "crapto1/crapto1.h" #define __STDC_FORMAT_MACROS #include #include @@ -48,7 +48,7 @@ int main(const int argc, const char *argv[]) { } printf("+----+--------+---+-----+---------------+\n"); - state = lfsr_common_prefix(nr, rr, ks3x, par); + state = lfsr_common_prefix(nr, rr, ks3x, par, false); lfsr_rollback_word(state, uid ^ nt, 0); crypto1_get_lfsr(state, &key_recovered); printf("\nkey recovered: %012" PRIx64 "\n\n", key_recovered); diff --git a/client/eml2lower.sh b/tools/pm3_eml2lower.sh old mode 100644 new mode 100755 similarity index 97% rename from client/eml2lower.sh rename to tools/pm3_eml2lower.sh index ddb3354db..086439c3c --- a/client/eml2lower.sh +++ b/tools/pm3_eml2lower.sh @@ -1,7 +1,7 @@ #!/bin/bash # Andrei Costin , 2011 -# eml2lower.sh +# pm3_eml2lower.sh # Converts PM3 Mifare Classic emulator EML file to lower case (for easier comparison in some text-comparison tools) # http://www.linuxquestions.org/questions/programming-9/bash-script-parsing-optional-parameters-621728/ diff --git a/client/pm3_eml2mfd.py b/tools/pm3_eml2mfd.py similarity index 100% rename from client/pm3_eml2mfd.py rename to tools/pm3_eml2mfd.py diff --git a/client/eml2UPPER.sh b/tools/pm3_eml2upper.sh old mode 100644 new mode 100755 similarity index 97% rename from client/eml2UPPER.sh rename to tools/pm3_eml2upper.sh index a28ae22a0..73b8646b7 --- a/client/eml2UPPER.sh +++ b/tools/pm3_eml2upper.sh @@ -1,7 +1,7 @@ #!/bin/bash # Andrei Costin , 2011 -# eml2UPPER.sh +# pm3_eml2upper.sh # Converts PM3 Mifare Classic emulator EML file to UPPER case (for easier comparison in some text-comparison tools) # http://www.linuxquestions.org/questions/programming-9/bash-script-parsing-optional-parameters-621728/ diff --git a/client/pm3_eml_mfd_test.py b/tools/pm3_eml_mfd_test.py similarity index 100% rename from client/pm3_eml_mfd_test.py rename to tools/pm3_eml_mfd_test.py diff --git a/client/pm3_mfd2eml.py b/tools/pm3_mfd2eml.py similarity index 100% rename from client/pm3_mfd2eml.py rename to tools/pm3_mfd2eml.py diff --git a/client/pm3_mfdread.py b/tools/pm3_mfdread.py old mode 100644 new mode 100755 similarity index 100% rename from client/pm3_mfdread.py rename to tools/pm3_mfdread.py diff --git a/tools/simmodule/SIM010.BIN b/tools/simmodule/SIM010.BIN deleted file mode 100644 index dea57a7d8..000000000 Binary files a/tools/simmodule/SIM010.BIN and /dev/null differ diff --git a/tools/simmodule/SIM010.md5.txt b/tools/simmodule/SIM010.md5.txt deleted file mode 100644 index c790101f7..000000000 --- a/tools/simmodule/SIM010.md5.txt +++ /dev/null @@ -1 +0,0 @@ -136e157364609e5c395540dc8dadbfd6 *SIM010.BIN diff --git a/tools/simmodule/SIM010.sha512.txt b/tools/simmodule/SIM010.sha512.txt deleted file mode 100644 index b7bab7246..000000000 --- a/tools/simmodule/SIM010.sha512.txt +++ /dev/null @@ -1 +0,0 @@ -e6ac5e6f1d7cc86d56f2128f2a495f1395fe044bf6ff3b6ca24ce90d1e361ae835fe273a206f2fc90e4344a13b37b180dd017a2c7f23312f1ed163f10c01ea5a *SIM010.BIN diff --git a/tools/simmodule/SIM011.md5.txt b/tools/simmodule/SIM011.md5.txt deleted file mode 100644 index 2a564eeb6..000000000 --- a/tools/simmodule/SIM011.md5.txt +++ /dev/null @@ -1 +0,0 @@ -e0be612fd3e68681ef0ee4706b4f28e2 *SIM011.BIN diff --git a/tools/simmodule/readme.txt b/tools/simmodule/readme.txt deleted file mode 100644 index 5dad9cd85..000000000 --- a/tools/simmodule/readme.txt +++ /dev/null @@ -1,32 +0,0 @@ - -2018-12-20 Iceman -2019-03-11 Iceman chg -======================================= - -The latest firmware for the SIM MODULE is : SIM011.bin - -You can use it to upgrade you sim module via the pm3 client. - -pm3 --> sc upgrade -h -pm3 --> sc upgrade f ../tools/simmodule/SIM011.bin - - -Even its a quite fast command you should be warned. You may brick it if you interrupt it. - - -Run hw status command to verify that the upgrade went well. - -pm3 --> hw status - - - -If you didn't download this file from the RRG Repo be aware that it might be corrupt or faulty. - -You find to hash text files in this folder. They were generated with the following linux commands. - - -md5sum -b SIM011.bin > SIM011.md5.txt -sha512sum -b SIM011.bin > SIM011.sha512.txt - - -You should validate the SIM011.bin file against these hash files in order to be sure the file is not corrupt or faulty. \ No newline at end of file diff --git a/tools/simmodule/sim011.asm b/tools/simmodule/sim011.asm new file mode 100644 index 000000000..178b1c484 --- /dev/null +++ b/tools/simmodule/sim011.asm @@ -0,0 +1,713 @@ +; --------------------------------------------------------------------------- +; Proxmark3 RDV4 SIM module firmware +; +; Copyright (C) 2019 Sentinel +; +; This program is free software: you can redistribute it and/or modify it +; under the terms of the GNU Lesser General Public License as published by the +; Free Software Foundation, either version 3 of the License, or (at your +; option) any later version. +; +; This program is distributed in the hope that it will be useful, but WITHOUT +; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +; more details. +; +; You should have received a copy of the GNU Lesser General Public License +; along with this program. If not, see +; --------------------------------------------------------------------------- + VERS_HI equ 3 + VERS_LO equ 11 +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- + SCON_0 equ 098h + FE_0 equ 098h.7 + + SCON_1 equ 0F8h + RI_1 equ 0F8h.0 + TI_1 equ 0F8h.1 + FE_1 equ 0F8h.7 + SBUF_1 equ 09Ah + T3CON equ 0C4h + RL3 equ 0C5h + RH3 equ 0C6h + + P0M1 equ 0B1h + P0M2 equ 0B2h + P1M1 equ 0B3h + P1M2 equ 0B4h + P3M1 equ 0ACh; + P3M2 equ 0ADh; + + EIE equ 09Bh + EIE1 equ 09Ch + + TA equ 0C7h + + RCTRIM0 equ 084h +; --------------------------------------------------------------------------- + CKCON equ 08Eh + CKDIV equ 095h +; --------------------------------------------------------------------------- + P1S equ 0B3h ;Page1 + SFRS equ 091h ;TA Protection +; --------------------------------------------------------------------------- + AUXR1 equ 0A2h +; --------------------------------------------------------------------------- + I2DAT equ 0BCh; + I2STAT equ 0BDh; + I2CLK equ 0BEh; + I2TOC equ 0BFh; + I2CON equ 0C0h; + ; equ I2CON.7;8 + I2CEN equ I2CON.6;4 + STA equ I2CON.5;2 + STO equ I2CON.4;1 + SI equ I2CON.3;8 + AA equ I2CON.2;4 + ; equ I2CON.1;2 + I2CPX equ I2CON.0;1 + + + I2ADDR equ 0C1h; + +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- + pin_TX1 equ P1.6 + + pin_TX0 equ P0.6 + pin_RX0 equ P0.7 + + pin_SCL equ P1.3 + pin_SDA equ P1.4 + + pin_RST equ P1.0 + pin_CLC equ P1.1 + pin_led equ P1.2 + +; --------------------------------------------------------------------------- +; =========================================================================== + + + CMD_GENERATE_ATR equ 01h + CMD_WRITE_DATA_SIM equ 02h + CMD_READ_DATA_SIM equ 03h + + CMD_SET_BAUD_RATE equ 04h + CMD_SET_SIM_CLC equ 05h + CMD_GET_VERS equ 06h + CMD_WRITE_CONFIRM equ 07h + + + +; --------------------------------------------------------------------------- +; =========================================================================== + + bit_RX0 equ 32.0 + bit_command_receive equ 32.1 + bit_generate_ATR equ 32.2 + i2c_write_mode equ 32.3 + i2c_write_done equ 32.4 + bit_data_sim_wr equ 32.5 + bit_length_answer equ 32.6 + bit_TX0 equ 32.7 + + bit_command_buff equ 33.0 + i2c_write_command equ 33.1 + i2c_command_done equ 33.2 + bit_wait_confirm equ 33.3 + bit_first_ATR equ 33.4 ;11/03/2019 +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + bit_32 equ 32 + bit_33 equ 33 + pointer_RX1 equ 34 ;save SBUF(SIM) to XRAM + pointer_RX2 equ 35 ;read XRAM to I2C + pointer_TX equ 36 + + length_send_to_sim equ 37 + length_answer_sim equ 38 + length_command equ 39 + time_data_read equ 40 + time_confirm equ 41 + + buff_command equ 42 + cmd_command equ 42 + data_command equ 43 + + STACKKKKK equ 200 +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- +; Beginning of the main program + cseg at 00 + Ljmp main_start + +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- + cseg at 11 ;1302Hz = 4MHZ(Fsys)/12/256 +; --------------------------------------------------------------------------- + jb time_confirm.7, $+3+2 ;3 + dec time_confirm ;2 +; --------------------------------------------------------------------------- + jb time_data_read.7,reti_timer0 + djnz time_data_read, reti_timer0 + setb pin_scl +reti_timer0: + reti + + +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- + cseg at 35 ;UART0 + ajmp jmp_UART0_interrupt + +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- + cseg at 51 ;I2C + ajmp jmp_i2c_interrupt + +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- + cseg at 123 ;UART1 + clr RI_1 + clr TI_1 + reti + +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- +jmp_UART0_interrupt: + jbc RI,jmp_byte_RI + jbc TI,jmp_byte_TI + reti +; --------------------------------------------------------------------------- +jmp_byte_RI: + jnb bit_first_ATR, jmp_not_collect ;11/03/2019 + + setb bit_RX0 + jb i2c_write_done,jmp_not_collect + PUSH ACC + inc AUXR1 ;DPTR2 + mov a,SBUF ;DPTR2 + ;mov SBUF_1,DPL ;DPTR2 + mov DPL,pointer_RX1 ;DPTR2 + mov DPH,#1 ;DPTR2 + movx @DPTR,a ;DPTR2 + inc pointer_RX1 ;DPTR2 + inc AUXR1 ;DPTR2 + POP ACC + ;09/08/2018 + clr pin_scl + mov time_data_read,#52 ;52/1302Hz = 40mS + + inc length_answer_sim +jmp_not_collect: + reti +; --------------------------------------------------------------------------- +jmp_byte_TI: + setb bit_TX0 + reti + + +; =========================================================================== +; --------------------------------------------------------------------------- +jmp_i2c_interrupt: + PUSH ACC + PUSH PSW + mov PSW,#24 + mov R7,I2STAT +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + cjne R7,#000h,nextttt00000 + setb STO + clr SI + jb STO,$ + ajmp pop_i2c_psw +nextttt00000: +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + cjne R7,#060h,nextttt00001 ;START+MY ADRESS + clr pin_led ;LED ON + + clr bit_command_receive + clr i2c_write_mode + clr bit_data_sim_wr + clr bit_length_answer + clr bit_command_buff + clr i2c_write_command + + ajmp end_i2c_interrupt +nextttt00001: +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + cjne R7,#080h,nextttt00002 ;RAM ADRESS + + jb bit_command_receive,jmp_data_receive + setb bit_command_receive + + mov a,I2DAT +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + cjne a,#CMD_WRITE_CONFIRM,next_comm001a + + setb bit_wait_confirm + + sjmp jmp_WRITEDATASIM +next_comm001a: +; --------------------------------------------------------------------------- + cjne a,#CMD_WRITE_DATA_SIM,next_comm001b + clr bit_wait_confirm +jmp_WRITEDATASIM: + mov length_send_to_sim,#0 + setb bit_data_sim_wr + mov pointer_TX,#0 + ajmp end_i2c_interrupt +next_comm001b: +; --------------------------------------------------------------------------- + cjne a,#CMD_GENERATE_ATR,next_comm002 + setb bit_generate_ATR + ;Prepare to answer + mov length_answer_sim,#0 + mov pointer_RX1,#0 + mov pointer_RX2,#0 + ajmp end_i2c_interrupt +next_comm002: +; --------------------------------------------------------------------------- + cjne a,#CMD_GET_VERS,next_comm003 + ajmp ANSWER_VERS +next_comm003: +; --------------------------------------------------------------------------- + cjne a,#CMD_SET_BAUD_RATE,next_comm004 + mov R0,#data_command + mov length_command,#0 + mov cmd_command,#CMD_SET_BAUD_RATE + setb i2c_write_command + ajmp end_i2c_interrupt +next_comm004: +; --------------------------------------------------------------------------- + cjne a,#CMD_SET_SIM_CLC,next_comm005 + mov R0,#data_command + mov length_command,#0 + mov cmd_command,#CMD_SET_SIM_CLC + setb i2c_write_command + ajmp end_i2c_interrupt +next_comm005: +; --------------------------------------------------------------------------- + ajmp end_i2c_interrupt +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +jmp_data_receive: + ;What receive ? Data to SIM/Command to bridge + jb bit_data_sim_wr, jmp_data_sim_receive + jb i2c_write_command,jmp_comm_bridge_receive + ajmp end_i2c_interrupt +; --------------------------------------------------------------------------- +jmp_comm_bridge_receive: + mov @R0,I2DAT + inc R0 + inc length_command + ajmp end_i2c_interrupt +; --------------------------------------------------------------------------- +jmp_data_sim_receive: + + setb i2c_write_mode + + inc AUXR1 ;DPTR2 + mov a,I2DAT ;DPTR2 + mov DPL,pointer_TX ;DPTR2 + mov DPH,#0 ;DPTR2 + movx @DPTR,a ;DPTR2 + inc pointer_TX ;DPTR2 + inc AUXR1 ;DPTR2 + + inc length_send_to_sim + ajmp end_i2c_interrupt +nextttt00002: +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + cjne R7,#0A0h,nextttt00003 ;STOP + setb pin_led ;LED OFF + + ;Command finish ? + jnb i2c_write_command,jmp_not_command + clr i2c_write_command + setb i2c_command_done +jmp_not_command: + + ;data to SIM finish ? + jnb i2c_write_mode,end_i2c_interrupt + clr i2c_write_mode + + setb i2c_write_done + ;Prepare to answer + mov length_answer_sim,#0 + mov pointer_RX1,#0 + mov pointer_RX2,#0 + + ajmp end_i2c_interrupt +nextttt00003: +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + cjne R7,#0A8h,nextttt00004 + sjmp read_byte_I2C +nextttt00004: +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + cjne R7,#0B8h,nextttt00005 +read_byte_I2C: + jnb bit_command_buff,jmp_not_comm_buff2 + mov I2DAT,@R0 + inc R0 + ajmp end_i2c_interrupt + +jmp_not_comm_buff2: + jb bit_length_answer,read_byte_APROM + setb bit_length_answer + + mov I2DAT,length_answer_sim + ajmp end_i2c_interrupt +read_byte_APROM: + inc AUXR1 ;DPTR2 + mov DPL,pointer_RX2 ;DPTR2 + mov DPH,#1 ;DPTR2 + movx a,@DPTR ;DPTR2 + mov I2DAT,a ;DPTR2 + inc pointer_RX2 ;DPTR2 + inc AUXR1 ;DPTR2 +nextttt00005: +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +end_i2c_interrupt: + clr STA + clr STO + setb AA +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +pop_i2c_psw: + POP PSW + POP ACC + clr SI + reti + + +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- +ANSWER_VERS: + mov R0,#data_command + mov cmd_command,#CMD_GET_VERS + mov (data_command+0),#2 + mov (data_command+1),#VERS_HI + mov (data_command+2),#VERS_LO + setb bit_command_buff + ajmp end_i2c_interrupt + + +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- +; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +main_start: + mov SP,#STACKKKKK +; --------------------------------------------------------------------------- + ;0-bidirect 1-push pull 0-input only 1-open drain + ;0 0 1 1 +; --------------------------------------------------------------------------- + mov P0M2,#01000000b ;Р0 + mov P0M1,#11111111b ;P1.6-Tx0 SIM; + ; + mov P1M2,#01011111b ;Р1 + mov P1M1,#10111000b ;P1.6-Tx1 DEBUG; P1.4,P1.3 - I2C; + + mov P3M2,#00000000b ;P3 + mov P3M1,#11111111b ; +; --------------------------------------------------------------------------- + mov TMOD, #22h + mov TH0, #0 ;14400hz + mov TH1, #0E9h ;UART0 10800 Bit/sec + mov TCON, #55h +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + mov TA,#0AAh + mov TA,#055h + orl SFRS,#00000001b + + mov P1S, #00010000b ;P1.4 trigger schmiddt + + mov TA,#0AAh + mov TA,#055h + anl SFRS,#11111110b +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + ;------- CONFIG I2C --------- + mov I2CON, #44h ;set AA, set I2C enable + setb pin_sda + setb pin_scl + mov I2ADDR,#0C0h +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + ;mov SCON, #050h ;UART0 8bit + mov SCON, #0D0h ;UART0 9bit + ;mov PCON, #11000000b;FE_0 enable + mov PCON, #10000000b;FE_0 disable +; --------------------------------------------------------------------------- + mov SCON_1,#050h ;UART1 + ;mov T3CON, #01101000b;FE_1 enable TIMER3 UART0 BAUD + ;mov T3CON, #00101000b;FE_1 disable TIMER3 UART0 BAUD + mov T3CON, #00001000b;FE_1 disable TIMER1 UART0 BAUD + ;mov RL3,#0E9h ;10800/21600 + ;mov RH3,#0FFh +; --------------------------------------------------------------------------- + ;UART1 + mov RL3,#0F7h ;27777/55556 + mov RH3,#0FFh +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + mov CKDIV,#2 ;Fsys=4.00MHZ + ;mov CKDIV,#1 ;Fsys=8.00MHZ +; --------------------------------------------------------------------------- + mov bit_32,#0 + mov bit_33,#0 + setb time_data_read.7 +; --------------------------------------------------------------------------- + ;orl CKCON,#00000010b ;ENABLE CLC TIMER1 Fsys/12 + orl CKCON,#00010010b ;ENABLE CLC TIMER1 Fsys +; --------------------------------------------------------------------------- + ;mov a,RCTRIM0 + ;add a,#31 + ;mov TA,#0AAh + ;mov TA,#055h + ;mov RCTRIM0,a +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + acall clr_buffer +; --------------------------------------------------------------------------- + mov EIE, #00000001b ;I2C Interrupt + ;mov IE, #10010000b ;EA, SERIAL0 + mov IE, #10010010b ;EA, SERIAL0, TIMER0 +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +main_loop: + acall control_ATR + acall control_send_to_sim + acall control_command + sjmp main_loop + +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- +control_command: + jbc i2c_command_done,$+3+1 ;3 + ret ;1 +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + ;Control Length command=1 + mov a,length_command + cjne a,#1,next_commandEND ;error length_command != 1 +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + mov a,cmd_command + cjne a,#CMD_SET_BAUD_RATE,next_command001 + mov TH1,data_command ;Timer1 HIGH byte + ret +next_command001: +; --------------------------------------------------------------------------- + cjne a,#CMD_SET_SIM_CLC, next_command002 + mov CKDIV,data_command ;Fsys DIV + ret +next_command002: +; --------------------------------------------------------------------------- +next_commandEND: + ret + +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- +control_send_to_sim: + jb i2c_write_done,$+3+1 ;3 + ret ;1 +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + jbc bit_wait_confirm,jmp_wait_confirm +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + mov DPTR,#0000 +looop_send: + movx a,@DPTR + inc DPTR + acall for_coooooom0 + djnz length_send_to_sim,looop_send +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + jnb bit_RX0,$ + clr i2c_write_done + ret + + +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- +jmp_wait_confirm: + mov DPTR,#0001 + movx a,@DPTR + mov R3,a + mov R4,#5 +; --------------------------------------------------------------------------- + mov DPTR,#0000 +looop_seend: + movx a,@DPTR + inc DPTR + acall for_coooooom0 + djnz R4,jmp_not_5byte + + jnb bit_RX0,$ + clr bit_RX0 + ;18/12/2018 + mov time_confirm,#65 ;New timeout 50mS +looop_waitconf: + jb time_confirm.7,jmp_no_answer + jnb bit_RX0,looop_waitconf + + ;clr pin_scl ;TEST PULSE! + mov a,SBUF + xrl a,R3 + ;setb pin_scl ;TEST PULSE! + + jnz jmp_no_correct_answer ;18/12/2018 + + ;pause for next byte 17/12/2018 + mov R7,#0 + djnz R7,$ ;~260mkSec + djnz R7,$ ;~260mkSec + djnz R7,$ ;~260mkSec + +jmp_not_5byte: + djnz length_send_to_sim,looop_seend +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- + jnb bit_RX0,$ + clr bit_RX0 +jmp_no_answer: + clr i2c_write_done + ret + +; --------------------------------------------------------------------------- +; --------------------------------------------------------------------------- +;18/12/2018 +jmp_no_correct_answer: + clr EA + clr i2c_write_done + mov a,SBUF + mov DPL,pointer_RX1 + mov DPH,#1 + movx @DPTR,a + inc pointer_RX1 + clr pin_scl + mov time_data_read,#52 ;52/1302Hz = 40mS + inc length_answer_sim + setb EA + ret + + + +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- +control_ATR: + jbc bit_generate_ATR,$+3+1 ;3 + ret ;1 +; --------------------------------------------------------------------------- + clr pin_RST + ;acall clr_buffer + ; Add rezet pause 17/12/2018 + + mov R6,#200 +looop_pause50mS: + djnz R7,$ ;~260mkSec + djnz R6,looop_pause50mS + + ;Prepare to answer 11/03/2019 + acall clr_buffer + mov length_answer_sim,#0 + mov pointer_RX1,#0 + mov pointer_RX2,#0 + setb bit_first_ATR + setb pin_RST + ret + +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- +for_coooooom0: + clr bit_RX0 + mov c,P + mov TB8,c ;9bit parity + mov SBUF,a + jnb bit_TX0,$ + clr bit_TX0 + mov R7,#100 + djnz R7,$ + ret + +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- +clr_buffer: + mov DPTR,#0256 ;Receive SIM buffer + mov R7,#255 + clr a +looop_clr_bufff: + movx @DPTR,a + inc DPTR + djnz R7,looop_clr_bufff + ret + +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- +;for_coooooom1: +; mov SBUF_1,a +; jnb TI_1,$ +; clr TI_1 +; ret +; +; --------------------------------------------------------------------------- +; =========================================================================== +; --------------------------------------------------------------------------- + +end. diff --git a/tools/simmodule/SIM011.BIN b/tools/simmodule/sim011.bin similarity index 100% rename from tools/simmodule/SIM011.BIN rename to tools/simmodule/sim011.bin diff --git a/tools/simmodule/SIM011.sha512.txt b/tools/simmodule/sim011.sha512.txt similarity index 90% rename from tools/simmodule/SIM011.sha512.txt rename to tools/simmodule/sim011.sha512.txt index 54a8bfd09..23ee6875f 100644 --- a/tools/simmodule/SIM011.sha512.txt +++ b/tools/simmodule/sim011.sha512.txt @@ -1 +1 @@ -752f9d8af3db214a797bacb7362a0b53eff4dd3793853e467047b7d36ddae9d1b4a050d9136225a48830d9c70bbad791f89d05553b0453f004b7bbcdc337e658 *SIM011.BIN +752f9d8af3db214a797bacb7362a0b53eff4dd3793853e467047b7d36ddae9d1b4a050d9136225a48830d9c70bbad791f89d05553b0453f004b7bbcdc337e658 *sim011.bin diff --git a/tools/srecswap.pl b/tools/srecswap.pl deleted file mode 100644 index 47db8e687..000000000 --- a/tools/srecswap.pl +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/perl - -# endian-swap S records; we need this because the JTAG tools we're using -# expect the memory image in byte-swapped format -# -# Jonathan Westhues, April 2004 - -if(@ARGV == 0) { - die "usage: $0 file-to-endian-swap.s19 > out.s19\n"; -} - -while(<>) { - chomp; - - if(/^S0/) { - next; - } - if(/^S7/) { - print "$_\n"; - next; - } - - if(not /^S3(..)(........)(.*)(..)$/) { - die "bad S record at line $.\n"; - } - - $data = $3; - $checksum = $4; - - print "S3$1$2"; - while($data =~ m#(..)(..)(..)(..)#g) { - print "$4$3$2$1"; - } - print "$checksum\n"; -}