diff --git a/.gitignore b/.gitignore index f5ee135e6..f61e85eb9 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ client/ui/ui_overlays.h hardnested_stats.txt proxmark3 flasher +!flasher/ lua luac fpga_compress diff --git a/.travis.yml b/.travis.yml index 723d1c1a2..f42dd8f1c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,22 +8,18 @@ compiler: gcc matrix: include: - os: osx - osx_image: xcode9.2 # OS X 10.13 + osx_image: xcode11 - os: linux dist: xenial sudo: required -before_install: -## Install ARM toolchain on Linux. -## add our homebrew tap for MacOS -## Note: all dependencies on MacOS should be resolved by the brew install command - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then - sudo apt-get update -qq; - sudo apt-get install -y gcc-arm-none-eabi libnewlib-dev; - elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then - brew update; - brew tap RfidResearchGroup/proxmark3; - fi +addons: + apt: + packages: + - gcc-arm-none-eabi + - libnewlib-dev + homebrew: + taps: RfidResearchGroup/proxmark3 install: if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then @@ -34,8 +30,6 @@ install: make all; fi -before_script: - script: ## start and run a test script if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000..ca3660980 --- /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": "./flash-fullimage.sh", + "problemMatcher": [] + }, + { + "label": "FLASH BOOTROM", + "type": "shell", + "command": "./flash-bootrom.sh", + "problemMatcher": [] + } + ] +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index c9da6eba9..90f193bd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,22 @@ 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] + - 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 +168,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 +176,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 +306,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/Makefile b/Makefile index 587fdf09d..58c61281f 100644 --- a/Makefile +++ b/Makefile @@ -31,9 +31,9 @@ endif -include Makefile.platform -include .Makefile.options.cache -include common/Makefile.hal +include common_arm/Makefile.hal -all clean: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/% +all clean: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/% fpga_compress/% mfkey/%: FORCE $(info [*] MAKE $@) @@ -41,10 +41,13 @@ mfkey/%: FORCE nonce2key/%: FORCE $(info [*] MAKE $@) $(Q)$(MAKE) --no-print-directory -C tools/nonce2key $(patsubst nonce2key/%,%,$@) +fpga_compress/%: FORCE + $(info [*] MAKE $@) + $(Q)$(MAKE) --no-print-directory -C tools/fpga_compress $(patsubst fpga_compress/%,%,$@) bootrom/%: FORCE cleanifplatformchanged $(info [*] MAKE $@) $(Q)$(MAKE) --no-print-directory -C bootrom $(patsubst bootrom/%,%,$@) -armsrc/%: FORCE cleanifplatformchanged +armsrc/%: FORCE cleanifplatformchanged fpga_compress/% $(info [*] MAKE $@) $(Q)$(MAKE) --no-print-directory -C armsrc $(patsubst armsrc/%,%,$@) client/%: FORCE @@ -55,7 +58,7 @@ recovery/%: FORCE cleanifplatformchanged bootrom/% armsrc/% $(Q)$(MAKE) --no-print-directory -C recovery $(patsubst recovery/%,%,$@) 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 help _test bootrom flash-bootrom os flash-os flash-all recovery client mfkey nonce2key style checks FORCE udev accessrights cleanifplatformchanged help: @echo "Multi-OS Makefile" @@ -73,7 +76,8 @@ help: @echo @echo "+ client - Make only the OS-specific host client" @echo "+ mfkey - Make tools/mfkey" - @echo "+ nounce2key - Make tools/nounce2key" + @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" @@ -93,6 +97,8 @@ mfkey: mfkey/all nonce2key: nonce2key/all +fpga_compress: fpga_compress/all + flash-bootrom: bootrom/obj/bootrom.elf $(FLASH_TOOL) $(FLASH_TOOL) $(FLASH_PORT) -b $(subst /,$(PATHSEP),$<) @@ -145,7 +151,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 +164,11 @@ 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" \) \ + 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" \) \ + 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 +# to remove tabs within lines, one can try with: vi $file -c ':set tabstop=4' -c ':set et|retab' -c ':wq' # Dummy target to test for GNU make availability _test: 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..665c91005 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,12 @@ 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 OBJS = $(OBJDIR)/fullimage.s19 -FPGA_COMPRESSOR = ../client/fpga_compress +FPGA_COMPRESSOR = ../tools/fpga_compress/fpga_compress all: $(OBJS) @@ -143,7 +146,7 @@ version.c: default_version.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o $(info [-] GEN $@) $(Q)perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@ -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 +154,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 +163,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 +182,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,6 +203,7 @@ tarbin: $(OBJS) $(Q)$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=armsrc/%) $(OBJS:%.s19=armsrc/%.elf) clean: + $(Q)$(DELETE) $(DEPENDENCY_FILES) $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.o $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.elf $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.s19 @@ -215,3 +219,4 @@ help: @echo Possible targets: @echo + all - Build the full image $(OBJDIR)/fullimage.s19 @echo + clean - Clean $(OBJDIR) + 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..6580af7fd 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); } } 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..a45dd71c3 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -8,12 +8,81 @@ //----------------------------------------------------------------------------- // main code for HF Mifare aka ColinRun by Colin Brigato //----------------------------------------------------------------------------- +#include "standalone.h" // standalone definitions +#include // for bool +#include +#include #include "hf_colin.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "dbprint.h" +#include "ticks.h" +#include "commonutil.h" +#include "crc16.h" +#include "BigBuf.h" +#include "frozen.h" +#include "proxmark3_arm.h" +#include "mifaresim.h" // mifare1ksim +#include "mifareutil.h" +#include "iso14443a.h" +#include "util.h" +#include "vtsend.h" +#include "spiffs.h" +#include "string.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 +96,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 +155,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 +243,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 +321,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 +338,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 +395,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 +436,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 +476,8 @@ void RunMod() { currfline = 24; cjSetCursLeft(); + add_schemas_from_json_in_spiffs((char *)HFCOLIN_SCHEMAS_JSON); + failtag: vtsend_cursor_position_save(NULL); @@ -419,8 +572,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. @@ -587,7 +740,7 @@ readysim: // if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) { flags |= FLAG_UID_IN_EMUL; //} - Mifare1ksim(flags | FLAG_MF_1K, 0, cjuid); + Mifare1ksim(flags | FLAG_MF_1K, 0, cjuid, 0, 0); LED_C_OFF(); SpinOff(50); vtsend_cursor_position_restore(NULL); diff --git a/armsrc/Standalone/hf_colin.h b/armsrc/Standalone/hf_colin.h index e669f0417..ca65a6df4 100644 --- a/armsrc/Standalone/hf_colin.h +++ b/armsrc/Standalone/hf_colin.h @@ -16,22 +16,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..f163e579b 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 @@ -755,25 +666,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 +694,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 +763,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 +771,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 +794,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 +826,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 +836,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 +847,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 +899,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 +957,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 +977,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 +1020,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 +1108,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 +1124,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 +1133,132 @@ static void PacketReceived(PacketCommandNG *packet) { MifareEMemGet(payload->blockno, payload->blockcnt); break; } - case CMD_MIFARE_EML_CARDLOAD: { + case CMD_HF_MIFARE_EML_LOAD: { MifareECardLoad(packet->oldarg[0], packet->oldarg[1]); 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: { + case CMD_HF_ICLASS_READER: { ReaderIClass(packet->oldarg[0]); 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: { + case CMD_HF_ICLASS_WRITEBL: { iClass_WriteBlock(packet->oldarg[0], packet->data.asBytes); break; } - case CMD_ICLASS_READCHECK: { // auth step 1 + case CMD_HF_ICLASS_READCHECK: { // auth step 1 iClass_ReadCheck(packet->oldarg[0], packet->oldarg[1]); break; } - case CMD_ICLASS_READBLOCK: { + case CMD_HF_ICLASS_READBL: { iClass_ReadBlk(packet->oldarg[0]); break; } - case CMD_ICLASS_AUTHENTICATION: { //check + case CMD_HF_ICLASS_AUTH: { //check 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: { + case CMD_HF_ICLASS_CLONE: { iClass_Clone(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); break; } #endif #ifdef WITH_HFSNIFF - case CMD_HF_SNIFFER: { + case CMD_HF_SNIFF: { HfSniff(packet->oldarg[0], packet->oldarg[1]); break; } @@ -1537,7 +1460,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 +1482,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 @@ -1731,58 +1654,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 +1716,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 +1750,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 +1860,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,6 +1896,7 @@ 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 @@ -2031,7 +1926,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..fa35714e3 --- /dev/null +++ b/armsrc/appmain.h @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// 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 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); +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 c53169255..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,25 +568,28 @@ 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]); if (num != 0xFFFF && num != 0x0) - Dbprintf(" Mifare................"_YELLOW_("%d")"keys", num); + 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]); if (num != 0xFFFF && num != 0x0) - Dbprintf(" T55x7................."_YELLOW_("%d")"keys", num); + 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]); if (num != 0xFFFF && num != 0x0) - Dbprintf(" iClass................"_YELLOW_("%d")"keys", num); + Dbprintf(" iClass.................."_YELLOW_("%d")"keys", num); } FlashStop(); 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..220f51d6c --- /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 +#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..c8504e5ed 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -36,15 +36,24 @@ // //----------------------------------------------------------------------------- -#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 + +#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 timeout = 4096; static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay); @@ -92,21 +101,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 +134,7 @@ typedef struct { SUB_BOTH } sub; uint8_t *output; -} tDemod; +} tDemodIc; /* * Abrasive's uart implementation @@ -138,8 +147,13 @@ 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_old(CMD_ACK, 0, reason, 0, 0, 0); + switch_off(); +} static void uart_reset(void) { Uart.frame_done = false; @@ -499,8 +513,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 +526,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 +606,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 +634,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 +658,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 +696,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 +772,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 +832,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 @@ -884,9 +898,17 @@ void RAMFUNC SniffIClass(void) { // 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 == 1000) { + if (BUTTON_PRESS() || data_available()) break; + checked = 0; + } else { + checked++; + } + previous_data <<= 8; previous_data |= *data; @@ -919,7 +941,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; @@ -951,12 +973,12 @@ void RAMFUNC SniffIClass(void) { if (ManchesterDecoding_iclass(foo)) { 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; @@ -996,9 +1018,18 @@ 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 == 1000) { + if (BUTTON_PRESS() || data_available()) return false; + checked = 0; + } else { + checked++; + } + // keep tx buffer in a defined state anyway. if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) AT91C_BASE_SSC->SSC_THR = 0x00; @@ -1195,11 +1226,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 +1257,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 +1338,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 +1413,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); @@ -1436,6 +1467,7 @@ 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]) { @@ -1444,13 +1476,13 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { 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,19 +1492,30 @@ 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 + (receivedCmd[1] << 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; - } - + } + }//swith + }// if 4 } else if (receivedCmd[0] == ICLASS_CMD_SELECT) { // 0x81 // Reader selects anticollission CSN. // Tag sends the corresponding real CSN @@ -1542,17 +1585,15 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { 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 && receivedCmd[0] == 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 + (receivedCmd[1] << 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) { @@ -1632,8 +1673,15 @@ 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 == 1000) { + if (BUTTON_PRESS() || data_available()) return 0; + checked = 0; + } else { + checked++; + } // Prevent rx holding register from overflowing if ((AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) { b = AT91C_BASE_SSC->SSC_RHR; @@ -1787,7 +1835,7 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, bool skip = false; // Setup UART/DEMOD to receive - DemodInit(receivedResponse); + DemodIcInit(receivedResponse); if (elapsed) *elapsed = 0; @@ -1800,9 +1848,18 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; (void)b; - while (!BUTTON_PRESS()) { + uint16_t checked = 0; + + for (;;) { WDT_HIT(); + if (checked == 1000) { + if (BUTTON_PRESS() || data_available()) return false; + checked = 0; + } else { + checked++; + } + // keep tx buffer in a defined state anyway. if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = 0x00; @@ -1993,6 +2050,7 @@ void ReaderIClass(uint8_t arg0) { setupIclassReader(); + uint16_t checked = 0; bool userCancelled = BUTTON_PRESS() || data_available(); while (!userCancelled) { @@ -2092,7 +2150,13 @@ void ReaderIClass(uint8_t arg0) { } } LED_B_OFF(); - userCancelled = BUTTON_PRESS() || data_available(); + + if (checked == 1000) { + userCancelled = BUTTON_PRESS() || data_available(); + checked = 0; + } else { + checked++; + } } if (userCancelled) { @@ -2222,7 +2286,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 }; @@ -2286,11 +2350,17 @@ 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 == 1000) { + if (BUTTON_PRESS() || !data_available()) goto out; + checked = 0; + } else { + checked++; + } read_status = handshakeIclassTag_ext(card_data, use_credit_key); if (startup_limit-- == 0) { @@ -2305,7 +2375,12 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) { for (i = 0; i < keyCount; i++) { // Allow button press / usb cmd to interrupt device - if (BUTTON_PRESS() && !data_available()) break; + if (checked == 1000) { + if (BUTTON_PRESS() || !data_available()) goto out; + checked = 0; + } else { + checked++; + } WDT_HIT(); LED_B_ON(); 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..786db50dc 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); @@ -1719,7 +1810,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 +2022,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 +2039,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 +2104,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 +2158,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 +2504,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 +2514,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 +2731,7 @@ void ReaderIso14443a(PacketCommandNG *c) { return; OUT: - iso14443a_off(); + hf_field_off(); set_tracing(false); } @@ -2885,7 +3026,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 +3034,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 +3261,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..e4ea7f0df 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -13,21 +13,9 @@ #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 // 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 +30,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 +49,7 @@ typedef struct { uint32_t startTime, endTime; uint8_t *output; uint8_t *parity; -} tDemod; +} tDemod14a; /* typedef enum { MOD_NOMOD = 0, @@ -73,11 +61,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 +81,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 +97,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 +120,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 +137,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..5e9de52dd 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); @@ -1495,7 +1509,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++); } @@ -1601,7 +1615,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 +1651,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 +1660,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(); } @@ -1990,7 +2004,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 +2073,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..445b04130 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -1,27 +1,52 @@ //----------------------------------------------------------------------------- -// 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(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); + +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.h b/armsrc/optimized_cipher.h index 9bf0516de..893297ddd 100644 --- a/armsrc/optimized_cipher.h +++ b/armsrc/optimized_cipher.h @@ -1,9 +1,7 @@ #ifndef OPTIMIZED_CIPHER_H #define OPTIMIZED_CIPHER_H -#include -#include -#include +#include "common.h" /** * Definition 1 (Cipher state). A cipher state of iClass s is an element of F 40/2 diff --git a/armsrc/pcf7931.c b/armsrc/pcf7931.c index 942569a9c..2c679b31f 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 @@ -404,7 +414,7 @@ void SendCmdPCF7931(uint32_t *tab) { 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(); 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..de6e9e226 100644 --- a/armsrc/spiffs.c +++ b/armsrc/spiffs.c @@ -43,6 +43,12 @@ RDV40_SPIFFS_SAFE_FOOTER #include "spiffs.h" +#include "flashmem.h" +#include "dbprint.h" +#include "printf.h" +#include "common.h" +#include "string.h" +#include "BigBuf.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) { diff --git a/armsrc/spiffs.h b/armsrc/spiffs.h index f36bde4b0..29e8215b0 100644 --- a/armsrc/spiffs.h +++ b/armsrc/spiffs.h @@ -7,9 +7,8 @@ #ifndef SPIFFS_H_ #define SPIFFS_H_ -#if defined(__cplusplus) -extern "C" { -#endif + +#include "common.h" #include "spiffs_config.h" @@ -854,8 +853,5 @@ u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages); #if SPIFFS_CACHE #endif -#if defined(__cplusplus) -} -#endif #endif /* SPIFFS_H_ */ diff --git a/armsrc/spiffs_config.h b/armsrc/spiffs_config.h index 99557f41f..6fe1f48c6 100644 --- a/armsrc/spiffs_config.h +++ b/armsrc/spiffs_config.h @@ -8,22 +8,7 @@ #ifndef SPIFFS_CONFIG_H_ #define SPIFFS_CONFIG_H_ -// ----------- 8< ------------ -// Following includes are for the linux test build of spiffs -// These may/should/must be removed/altered/replaced in your target -//#include -//#include -// -#include "printf.h" -#include "string.h" -#include "flashmem.h" - -void Dbprintf(const char *fmt, ...); - -//#include -//#include -// ----------- >8 ------------ - +#include "common.h" typedef int s32_t; typedef uint32_t u32_t; 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..43555b21b 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; } diff --git a/armsrc/ticks.h b/armsrc/ticks.h index 9ff0d6000..089501c87 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() @@ -45,4 +41,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..b855ab949 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); } @@ -176,7 +184,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 +217,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 +247,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..c4103b522 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,7 +29,7 @@ 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 OBJS = $(OBJDIR)/bootrom.s19 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..adf83cb18 100644 --- a/client/Makefile +++ b/client/Makefile @@ -28,7 +28,7 @@ ENV_CFLAGS := $(CFLAGS) platform = $(shell uname) -VPATH = ../common ../zlib ../uart +VPATH = ../common ../common/zlib uart OBJDIR = obj LDLIBS = @@ -44,18 +44,19 @@ ifneq ($(platform),Darwin) LDLIBS += -Wl,--as-needed -latomic -Wl,--no-as-needed endif -LUALIB = ../liblua/liblua.a +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) +LIBS = -I../common/zlib -Iuart -I$(LUALIBPATH) -I$(MBEDTLSLIBPATH) -I$(JANSSONLIBPATH) -I$(CBORLIBPATH) INCLUDES_CLIENT = -I. -I../include -I../common -I/opt/local/include $(LIBS) LDFLAGS = $(ENV_LDFLAGS) -CFLAGS = $(ENV_CFLAGS) -std=c99 -D_ISOC99_SOURCE -DPRESETS $(INCLUDES_CLIENT) -Wall -g -O3 +CFLAGS = $(ENV_CFLAGS) -std=c99 -D_ISOC99_SOURCE -DPRESETS $(INCLUDES_CLIENT) -Wall -Werror -g -O3 ifneq (,$(findstring MINGW,$(platform))) CFLAGS += -mno-ms-bitfields endif @@ -117,7 +118,7 @@ endif # Flags to generate temporary dependency files DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td -# make temporary to final dependeny files after successful compilation +# make temporary to final dependency files after successful compilation POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d CORESRCS = uart_posix.c \ @@ -130,7 +131,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 \ @@ -199,6 +200,7 @@ CMDSRCS = crapto1/crapto1.c \ cmdhftopaz.c \ cmdhffido.c \ cmdhffelica.c \ + cmdhfthinfilm.c \ cmdhw.c \ cmdlf.c \ cmdlfawid.c \ @@ -236,7 +238,6 @@ CMDSRCS = crapto1/crapto1.c \ scripting.c \ cmdscript.c \ pm3_bitlib.c \ - protocols.c \ cmdcrc.c \ reveng/preset.c \ reveng/reveng.c \ @@ -290,14 +291,14 @@ 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 flasher +CLEAN = $(BINS) $(DEPENDENCY_FILES) $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(ZLIBOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(OBJDIR)/*.o *.moc.cpp ui/ui_overlays.h lualibs/pm3_cmd.lua lualibs/mf_default_keys.lua # need to assign dependancies to build these first... all: lua_build jansson_build mbedtls_build cbor_build $(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 @@ -308,10 +309,6 @@ 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 $@ - proxgui.cpp: ui/ui_overlays.h proxguiqt.moc.cpp: proxguiqt.h @@ -332,7 +329,7 @@ lualibs/mf_default_keys.lua : default_keys.dic clean: $(Q)$(RM) $(CLEAN) - $(Q)$(MAKE) --no-print-directory -C ../liblua clean + $(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 @@ -343,7 +340,7 @@ tarbin: $(BINS) lua_build: $(info [*] MAKE liblua for $(LUAPLATFORM)) - $(Q)$(MAKE) --no-print-directory -C ../liblua $(LUAPLATFORM) + $(Q)$(MAKE) --no-print-directory -C $(LUALIBPATH) $(LUAPLATFORM) jansson_build: $(info [*] MAKE jansson) @@ -426,7 +423,7 @@ DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(CORESRCS) $(CMDSRCS) $(ZLIBS $(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 $(OBJDIR)/flash.d $(OBJDIR)/flasher.d $(DEPENDENCY_FILES): ; .PRECIOUS: $(DEPENDENCY_FILES) 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..81060cd59 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -9,6 +9,21 @@ //----------------------------------------------------------------------------- #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 + uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; size_t DemodBufferLen = 0; size_t g_DemodStartIdx = 0; @@ -870,7 +885,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 +1626,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(); 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..6bb6fbc3c 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 "loclass/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; @@ -209,7 +217,7 @@ static int CmdFlashMemLoad(const char *Cmd) { } 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; } @@ -310,7 +318,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..a3f9b950a 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 "loclass/fileutils.h" //saveFile +#include "comms.h" //getfromdevice static int CmdHelp(const char *Cmd); @@ -278,7 +281,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; } @@ -358,7 +361,7 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) { } 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; } 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..a6c5ea11e 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,65 @@ 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; + 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; + 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; + 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; + if (IfPm3Legicrf()) { + if (readLegicUid(false) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LEGIC tag") " found\n"); + return PM3_SUCCESS; + } + } + 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 (IfPm3Iso14443a()) { + if (readHF14B(false) == 1) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-B tag") " found\n"); + return PM3_SUCCESS; + } } - if (readIclass(false, false) == 1) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("iClass tag / PicoPass tag") " found\n"); - return 1; + if (IfPm3Iclass()) { + if (readIclass(false, false) == 1) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("iClass tag / PicoPass tag") " found\n"); + return PM3_SUCCESS; + } } - /* - ans = CmdHFFelicaReader("s"); - if (ans) { - PrintAndLogEx(NORMAL, "\nValid " _GREEN_("ISO18092 / FeliCa tag") " found\n"); - return ans; - } - */ + + //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 0; + return PM3_ESOFT; } int CmdHFTune(const char *Cmd) { @@ -119,7 +164,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 +186,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,6 +205,7 @@ 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]"}, @@ -175,5 +221,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..8aea8db6c 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" }, @@ -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..c5a628835 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -11,6 +11,17 @@ #include "cmdhf14b.h" +#include +#include "loclass/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..2c788087e 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 "loclass/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..e9b3376a9 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -21,31 +21,23 @@ #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); @@ -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 { @@ -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."); 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..f58d5377c 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -13,6 +13,23 @@ #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 "loclass/fileutils.h" +#include "protocols.h" + + #define NUM_CSNS 9 #define ICLASS_KEYS_MAX 8 @@ -271,6 +288,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, "\tMode: Personalization [Programmable]"); + else + PrintAndLogEx(NORMAL, "\tMode: Application [Locked]"); + + if (isset(fuses, FUSE_CODING1)) { + PrintAndLogEx(NORMAL, "\tCoding: RFU"); + } else { + if (isset(fuses, FUSE_CODING0)) + PrintAndLogEx(NORMAL, "\tCoding: ISO 14443-2 B/ISO 15693"); + else + PrintAndLogEx(NORMAL, "\tCoding: ISO 14443B only"); + } + // 1 1 + if (isset(fuses, FUSE_CRYPT1) && isset(fuses, FUSE_CRYPT0)) PrintAndLogEx(SUCCESS, "\tCrypt: Secured page, keys not locked"); + // 1 0 + if (isset(fuses, FUSE_CRYPT1) && notset(fuses, FUSE_CRYPT0)) PrintAndLogEx(NORMAL, "\tCrypt: Secured page, keys locked"); + // 0 1 + if (notset(fuses, FUSE_CRYPT1) && isset(fuses, FUSE_CRYPT0)) PrintAndLogEx(SUCCESS, "\tCrypt: Non secured page"); + // 0 0 + if (notset(fuses, FUSE_CRYPT1) && notset(fuses, FUSE_CRYPT0)) PrintAndLogEx(NORMAL, "\tCrypt: No auth possible. Read only if RA is enabled"); + + if (isset(fuses, FUSE_RA)) + PrintAndLogEx(NORMAL, "\tRA: Read access enabled"); + else + PrintAndLogEx(WARNING, "\tRA: 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, "\tAA1: blocks 06-%02X", applimit); + PrintAndLogEx(NORMAL, "\tAA2: blocks %02X-%02X", applimit + 1, max_blk); + PrintAndLogEx(NORMAL, "\tOTP: 0x%02X%02X", hdr->conf.otp[1], hdr->conf.otp[0]); + PrintAndLogEx(NORMAL, "\nKeyAccess:"); + + uint8_t book = isset(mem, 0x20); + if (book) { + PrintAndLogEx(NORMAL, "\tRead A - Kd"); + PrintAndLogEx(NORMAL, "\tRead B - Kc"); + PrintAndLogEx(NORMAL, "\tWrite A - Kd"); + PrintAndLogEx(NORMAL, "\tWrite B - Kc"); + PrintAndLogEx(NORMAL, "\tDebit - Kd or Kc"); + PrintAndLogEx(NORMAL, "\tCredit - Kc"); + } else { + PrintAndLogEx(NORMAL, "\tRead A - Kd or Kc"); + PrintAndLogEx(NORMAL, "\tRead B - Kd or Kc"); + PrintAndLogEx(NORMAL, "\tWrite A - Kc"); + PrintAndLogEx(NORMAL, "\tWrite B - Kc"); + PrintAndLogEx(NORMAL, "\tDebit - Kd or Kc"); + PrintAndLogEx(NORMAL, "\tCredit - 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 +437,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; } @@ -379,7 +535,7 @@ 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++; @@ -428,7 +584,7 @@ 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++; @@ -491,7 +647,7 @@ 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; } } @@ -519,7 +675,7 @@ 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; } @@ -550,14 +706,14 @@ static int CmdHFiClassELoad(const char *Cmd) { fseek(f, 0, SEEK_SET); if (fsize <= 0) { - PrintAndLogDevice(ERR, "error, when getting filesize"); + PrintAndLogEx(ERR, "error, when getting filesize"); fclose(f); return 1; } uint8_t *dump = calloc(fsize, sizeof(uint8_t)); if (!dump) { - PrintAndLogDevice(ERR, "error, cannot allocate memory "); + PrintAndLogEx(ERR, "error, cannot allocate memory "); fclose(f); return 1; } @@ -569,7 +725,7 @@ static int CmdHFiClassELoad(const char *Cmd) { //Validate if (bytes_read < fsize) { - PrintAndLogDevice(ERR, "error, could only read %d bytes (should be %d)", bytes_read, fsize); + PrintAndLogEx(ERR, "error, could only read %d bytes (should be %d)", bytes_read, fsize); free(dump); return 1; } @@ -588,7 +744,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; } @@ -757,7 +913,7 @@ 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); + SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0); if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { PrintAndLogEx(WARNING, "command execute timeout"); return false; @@ -802,7 +958,7 @@ static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool u doMAC(CCNR, div_key, MAC); PacketResponseNG resp; clearCommandBuffer(); - SendCommandOLD(CMD_ICLASS_AUTHENTICATION, 0, 0, 0, MAC, 4); + SendCommandOLD(CMD_HF_ICLASS_AUTH, 0, 0, 0, MAC, 4); if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { if (verbose) PrintAndLogEx(FAILED, "auth command execute timeout"); return false; @@ -923,7 +1079,7 @@ 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(); @@ -961,7 +1117,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { // 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); @@ -1015,7 +1171,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { 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; @@ -1062,6 +1218,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { // save the dump to .bin file PrintAndLogEx(SUCCESS, "saving dump file - %d blocks read", gotBytes / 8); saveFile(filename, ".bin", tag_data, gotBytes); + saveFileEML(filename, tag_data, gotBytes, 8); return 1; } @@ -1079,7 +1236,7 @@ static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_c memcpy(data + 8, MAC, 4); clearCommandBuffer(); - SendCommandOLD(CMD_ICLASS_WRITEBLOCK, blockno, 0, 0, data, sizeof(data)); + SendCommandOLD(CMD_HF_ICLASS_WRITEBL, blockno, 0, 0, data, sizeof(data)); if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) { if (verbose) PrintAndLogEx(WARNING, "Write Command execute timeout"); return 0; @@ -1317,7 +1474,7 @@ static int CmdHFiClassCloneTag(const char *Cmd) { PacketResponseNG resp; clearCommandBuffer(); - SendCommandOLD(CMD_ICLASS_CLONE, startblock, endblock, 0, data, (endblock - startblock) * 12); + SendCommandOLD(CMD_HF_ICLASS_CLONE, startblock, endblock, 0, data, (endblock - startblock) * 12); if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) { PrintAndLogEx(WARNING, "command execute timeout"); return 0; @@ -1341,7 +1498,7 @@ static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_ICLASS_READBLOCK, blockno, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ICLASS_READBL, blockno, 0, 0, NULL, 0); if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) { PrintAndLogEx(WARNING, "Command execute timeout"); return 0; @@ -1448,7 +1605,7 @@ static int CmdHFiClass_loclass(const char *Cmd) { errors += testMAC(); errors += doKeyTests(0); errors += testElite(); - if (errors) PrintAndLogDevice(ERR, "There were errors!!!"); + if (errors) PrintAndLogEx(ERR, "There were errors!!!"); return errors; } return PM3_SUCCESS; @@ -1570,7 +1727,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) { @@ -1959,7 +2116,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 + i, 4 * keys); PacketResponseNG resp; while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { @@ -2441,7 +2598,7 @@ 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; diff --git a/client/cmdhficlass.h b/client/cmdhficlass.h index aa29fae1e..9f2b5caac 100644 --- a/client/cmdhficlass.h +++ b/client/cmdhficlass.h @@ -11,31 +11,7 @@ #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 - - typedef struct iclass_block { uint8_t d[8]; diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index e8089c3d8..af56807b1 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 "loclass/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..5a2ff5248 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; } @@ -1114,7 +1139,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..affc53603 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 "loclass/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 @@ -68,11 +80,14 @@ static int usage_hf14_mfsim(void) { PrintAndLogEx(NORMAL, "Usage: hf mf sim [h] u n [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"); @@ -398,7 +413,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 +526,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 +574,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 +639,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; @@ -797,9 +812,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 +851,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 +862,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 +875,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) { @@ -1046,7 +1061,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 +1084,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; @@ -1173,17 +1188,17 @@ static int CmdHF14AMfNested(const char *Cmd) { //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); + mfCheckKeys_fast(SectorsCnt, true, true, 1, ARRAYLEN(g_mifare_default_keys) + 1, keyBlock, e_sector, false); 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 @@ -1250,10 +1265,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; @@ -1554,15 +1569,15 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { 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); + keyBlock = calloc(ARRAYLEN(g_mifare_default_keys), 6); if (keyBlock == NULL) return 1; - 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 @@ -1661,7 +1676,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]); @@ -1806,7 +1821,7 @@ 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; @@ -1815,10 +1830,10 @@ static int CmdHF14AMfChk(const char *Cmd) { 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) == '*') { @@ -1928,7 +1943,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 +2029,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; @@ -2163,6 +2178,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 +2213,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 +2225,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 +2310,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 +2330,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 +2379,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; @@ -2530,7 +2576,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; } @@ -2740,7 +2786,7 @@ static int CmdHF14AMfECFill(const char *Cmd) { PrintAndLogEx(NORMAL, "--params: numSectors: %d, keyType: %c\n", numSectors, (keyType == 0) ? 'A' : 'B'); clearCommandBuffer(); - SendCommandMIX(CMD_MIFARE_EML_CARDLOAD, numSectors, keyType, 0, NULL, 0); + SendCommandMIX(CMD_HF_MIFARE_EML_LOAD, numSectors, keyType, 0, NULL, 0); return PM3_SUCCESS; } @@ -3216,10 +3262,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 +3360,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 +3392,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; } 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..d66df7eae 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -21,18 +21,18 @@ #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" @@ -1379,7 +1379,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 +1388,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..8c7cfcc5c 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); @@ -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..e2c64a004 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 "loclass/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)) { @@ -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)) { @@ -2490,7 +2524,7 @@ static int CmdHF14AMfUCSetUid(const char *Cmd) { // 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; @@ -2507,7 +2541,7 @@ 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; @@ -2519,7 +2553,7 @@ 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; @@ -2531,7 +2565,7 @@ 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; @@ -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; } @@ -2662,7 +2696,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; 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..2e9ab7a85 --- /dev/null +++ b/client/cmdhfthinfilm.c @@ -0,0 +1,247 @@ +//----------------------------------------------------------------------------- +// 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, " 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..7fec7a40c 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; } @@ -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"}, diff --git a/client/cmdhw.h b/client/cmdhw.h index a1a3a4b8f..1a378e70f 100644 --- a/client/cmdhw.h +++ b/client/cmdhw.h @@ -11,6 +11,8 @@ #ifndef CMDHW_H__ #define CMDHW_H__ +#include "common.h" + int CmdHW(const char *Cmd); void pm3_version(bool verbose); diff --git a/client/cmdlf.c b/client/cmdlf.c index 42b26be0d..cf8e60f82 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; } @@ -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..a87fd46eb 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; } */ @@ -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..190b84283 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -8,19 +8,13 @@ // 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 "cmdtrace.h" +#include "commonutil.h" +#include "hitag.h" #include "loclass/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..b7f9891a5 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 (%s) ; subtype : %1u , customer : %03x , ID : %05u" + , isLong ? "long (128b)" : "short (64b)" + , subType + , customerCode + , id + ); + + 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..d5f66496d 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 "loclass/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,9 +201,7 @@ 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:"); @@ -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:"); @@ -564,28 +570,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 +1151,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 +1243,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; } @@ -1708,8 +1711,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 +1981,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 +2091,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)) { @@ -2129,7 +2132,7 @@ static int CmdT55xxChkPwds(const char *Cmd) { // 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 "); + PrintAndLogEx(ERR, "error, cannot allocate memory "); return PM3_ESOFT; } @@ -2551,12 +2554,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 +2614,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..618f04c73 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) { 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..d9ece2310 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) { @@ -133,6 +132,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 +150,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; } } diff --git a/client/cmdparser.h b/client/cmdparser.h index c5aa5460e..284142780 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); @@ -38,6 +40,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..28dd8608f 100644 --- a/client/cmdscript.c +++ b/client/cmdscript.c @@ -11,27 +11,21 @@ // this define is needed for scandir/alphasort to work #define _GNU_SOURCE -#include +#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 +#include "lualib.h" +#include "lauxlib.h" +#include "proxmark3.h" +#include "ui.h" #ifdef _WIN32 #include "scandir.h" 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/cmdsmartcard.c b/client/cmdsmartcard.c index c49f0d0e7..f1fd2b917 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -8,7 +8,20 @@ // 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" static int CmdHelp(const char *Cmd); @@ -61,7 +74,7 @@ static int usage_sm_upgrade(void) { 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"); @@ -843,13 +856,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 +891,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); 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..15416a8a6 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 "loclass/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; @@ -277,6 +296,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr && protocol != ISO_14443B && protocol != ISO_7816_4 && protocol != PROTO_HITAG + && protocol != THINFILM && (isResponse || protocol == ISO_14443A) && (oddparity8(frame[j]) != ((parityBits >> (7 - (j & 0x0007))) & 0x01))) { @@ -727,7 +747,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 +758,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 +812,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 +839,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..0b668bbe7 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"); 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..d42bd09fb 100644 --- a/client/comms.c +++ b/client/comms.c @@ -10,11 +10,15 @@ //----------------------------------------------------------------------------- #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 //#define COMMS_DEBUG //#define COMMS_DEBUG_RAW @@ -53,6 +57,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 +254,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 +594,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 +632,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 +714,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 +834,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..356dd3591 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 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_keys.dic b/client/default_keys.dic index 4df09cb1c..54c355de4 100644 --- a/client/default_keys.dic +++ b/client/default_keys.dic @@ -113,8 +113,13 @@ a9b43414F585,--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,-- +a9f953def0a3, # # Here be BIP keys... 3A42F33AF429, @@ -162,6 +167,11 @@ AAFB06045877, --EPI Envisionte# 3dprinter # gym 3e65e4fb65b3, --Fysiken A 25094df6f148, --Fysiken B +a05dbd98e0fc, -- CleverFit +# +d3b595e9dd63, -- Hotel KeyCard +afbecd121004, -- Hotel KeyCard +6471a5ef2d1a, -- SimonsVoss # # 24-7 D21762B2DE3B, @@ -516,6 +526,9 @@ EC0A9B1A9E06,--Vingcard Mifare 4k Staff card BEDB604CC9D1, B8A1F613CF3D, B578F38A5C61, +B66AC040203A +6D0B6A2A0003 +2E641D99AD5B AD4FB33388BF, 69FB7B7CD8EE, 2A6D9205E7CA, @@ -950,3 +963,4 @@ A0004A000036 DFE73BE48AC6 # B069D0D03D17 +000131B93F28 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..3891bdb48 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); 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..e273480c8 100644 --- a/client/emv/emv_pk.c +++ b/client/emv/emv_pk.c @@ -19,16 +19,16 @@ /* 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" #define BCD(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \ -1) 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..72c1fe78e 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 @@ -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..88d886c6e 100644 --- a/client/emv/emvjson.c +++ b/client/emv/emvjson.c @@ -9,12 +9,12 @@ //----------------------------------------------------------------------------- #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" @@ -57,10 +57,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; 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/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..21d9d80f6 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" \ 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/flash.c b/client/flash.c index f2f0b526a..ca2f012bb 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 @@ -378,12 +389,12 @@ static int wait_for_ack(PacketResponseNG *ack) { } 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 @@ -413,18 +424,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 +448,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(NORMAL, "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 { @@ -445,7 +461,8 @@ 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(ERR, _RED_("====================== OBS ! ======================================")); + PrintAndLogEx(ERR, _RED_("Note: Your bootloader does not understand the new " _YELLOW_("CHIP_INFO") _RED_("command"))); flash_suggest_update_bootloader(); } @@ -464,7 +481,8 @@ 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; diff --git a/client/flash.h b/client/flash.h index 4f05029dc..eca4d9ccc 100644 --- a/client/flash.h +++ b/client/flash.h @@ -9,20 +9,7 @@ #ifndef __FLASH_H__ #define __FLASH_H__ -#include -#include -#include -#include -#include - -#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" +#include "common.h" typedef struct { void *data; diff --git a/client/flasher.c b/client/flasher.c index 97e3d7a1c..931976997 100644 --- a/client/flasher.c +++ b/client/flasher.c @@ -6,18 +6,11 @@ // Flasher frontend tool //----------------------------------------------------------------------------- -#include -#include #include -#include -#include #include -#include "util_posix.h" -#include "proxmark3.h" -#include "util.h" +#include "usart_defs.h" #include "flash.h" #include "comms.h" -#include "pm3_cmd.h" #include "ui.h" #define MAX_FILES 4 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..5f93d4811 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" diff --git a/liblua/Makefile b/client/liblua/Makefile similarity index 100% rename from liblua/Makefile rename to client/liblua/Makefile 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..931f0c845 100644 --- a/client/loclass/cipher.c +++ b/client/loclass/cipher.c @@ -250,7 +250,7 @@ void doMAC_N(uint8_t *address_data_p, uint8_t address_data_size, uint8_t *div_ke #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,9 +262,9 @@ 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; diff --git a/client/loclass/cipherutils.c b/client/loclass/cipherutils.c index c829574e9..b11f6883a 100644 --- a/client/loclass/cipherutils.c +++ b/client/loclass/cipherutils.c @@ -34,12 +34,15 @@ * * ****************************************************************************/ +#include "cipherutils.h" #include #include #include + +#include "commonutil.h" // ARRAYLEN + #include "fileutils.h" -#include "cipherutils.h" /** * * @brief Return and remove the first bit (x0) in the stream : @@ -152,7 +155,7 @@ 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); } @@ -165,7 +168,7 @@ void printvar(const char *name, uint8_t *arr, int len) { cx += snprintf(output + cx, outsize - cx, "%02x", *(arr + i)); //2 bytes per byte } - PrintAndLogDevice(NORMAL, output); + PrintAndLogEx(NORMAL, output); free(output); } @@ -179,7 +182,7 @@ void printarr_human_readable(const char *title, uint8_t *arr, int len) { 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,12 +204,12 @@ 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; } @@ -231,12 +234,12 @@ 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; } @@ -245,7 +248,7 @@ static int testReversedBitstream() { 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/elite_crack.c b/client/loclass/elite_crack.c index 5b019d8e0..a4296f476 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, "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, "Key verified ok!\n"); } return 0; } @@ -505,7 +505,7 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) { } free(attack); t1 = msclock() - t1; - PrintAndLogDevice(SUCCESS, "time: %" PRIu64 " seconds", t1 / 1000); + PrintAndLogEx(SUCCESS, "time: %" PRIu64 " seconds", t1 / 1000); // Pick out the first 16 bytes of the keytable. // The keytable is now in 16-bit ints, where the upper 8 bits @@ -517,7 +517,7 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) { first16bytes[i] = keytable[i] & 0xFF; if (!(keytable[i] & CRACKED)) - PrintAndLogDevice(WARNING, "Warning: we are missing byte %d, custom key calculation will fail...", i); + PrintAndLogEx(WARNING, "Warning: we are missing byte %d, custom key calculation will fail...", i); } errors += calculateMasterKey(first16bytes, NULL); return errors; @@ -532,7 +532,7 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) { int bruteforceFile(const char *filename, uint16_t keytable[]) { FILE *f = fopen(filename, "rb"); if (!f) { - PrintAndLogDevice(WARNING, "Failed to read from file '%s'", filename); + PrintAndLogEx(WARNING, "Failed to read from file '%s'", filename); return 1; } @@ -541,14 +541,14 @@ int bruteforceFile(const char *filename, uint16_t keytable[]) { fseek(f, 0, SEEK_SET); if (fsize <= 0) { - PrintAndLogDevice(ERR, "Error, when getting filesize"); + PrintAndLogEx(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"); + PrintAndLogEx(WARNING, "Failed to allocate memory"); fclose(f); return 2; } @@ -557,7 +557,7 @@ int bruteforceFile(const char *filename, uint16_t keytable[]) { fclose(f); if (bytes_read < fsize) { - PrintAndLogDevice(WARNING, "Warning: could only read %d bytes (should be %d)", bytes_read, fsize); + PrintAndLogEx(WARNING, "Warning: could only read %d bytes (should be %d)", bytes_read, fsize); } uint8_t res = bruteforceDump(dump, fsize, keytable); @@ -585,7 +585,7 @@ static int _testBruteforce() { int errors = 0; if (true) { // First test - PrintAndLogDevice(INFO, "Testing crack from dumpfile..."); + PrintAndLogEx(INFO, "Testing crack from dumpfile..."); /** Expected values for the dumpfile: @@ -612,7 +612,7 @@ static int _testBruteforce() { } 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!"); + PrintAndLogEx(ERR, "Error: The file iclass_dump.bin was not found!"); } } return errors; @@ -627,20 +627,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 +651,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 +660,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 +683,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/fileutils.c b/client/loclass/fileutils.c index cb16a7fa3..b89925334 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -36,6 +36,13 @@ ****************************************************************************/ #include "fileutils.h" +#include + +#include "pm3_cmd.h" +#include "commonutil.h" +#include "util.h" + + #ifndef ON_DEVICE #define PATH_MAX_LENGTH 100 @@ -100,14 +107,14 @@ int saveFile(const char *preferredName, const char *suffix, const void *data, si /*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; } @@ -127,7 +134,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 +157,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); @@ -273,12 +280,12 @@ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, s 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: @@ -296,7 +303,7 @@ int loadFile(const char *preferredName, const char *suffix, void *data, size_t m 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,14 +314,14 @@ 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"); + PrintAndLogEx(FAILED, "error, when getting filesize"); retval = 1; goto out; } uint8_t *dump = calloc(fsize, sizeof(uint8_t)); if (!dump) { - PrintAndLogDevice(FAILED, "error, cannot allocate memory"); + PrintAndLogEx(FAILED, "error, cannot allocate memory"); retval = 2; goto out; } @@ -322,21 +329,21 @@ int loadFile(const char *preferredName, const char *suffix, void *data, size_t m size_t bytes_read = fread(dump, 1, fsize, 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; 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; @@ -358,7 +365,7 @@ int loadFileEML(const char *preferredName, void *data, size_t *datalen) { 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; } @@ -391,7 +398,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; @@ -532,7 +539,7 @@ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, u 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; } @@ -564,7 +571,7 @@ 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, fileName); if (datalen) *datalen = counter; @@ -601,7 +608,7 @@ 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; } diff --git a/client/loclass/fileutils.h b/client/loclass/fileutils.h index dae23a1b1..74d54000b 100644 --- a/client/loclass/fileutils.h +++ b/client/loclass/fileutils.h @@ -162,7 +162,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) +#define PrintAndLogEx(level, format, args...) PrintAndLogEx(level, format , ## args) #else /** @@ -172,7 +172,7 @@ int convertOldMfuDump(uint8_t **dump, size_t *dumplen); * write also to a logfile. When doing so, just point this function to use PrintAndLog * @param fmt */ -#define PrintAndLogDevice(level, format, args...) { } +#define PrintAndLogEx(level, format, args...) { } diff --git a/client/loclass/ikeys.c b/client/loclass/ikeys.c index 70605942f..53f7848de 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,9 +648,9 @@ 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; } @@ -683,32 +686,32 @@ static bool readKeyFile(uint8_t key[8]) { 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"); + 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/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/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..f7c7ce4f2 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)) { @@ -299,7 +314,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 +434,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 +471,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 +510,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 +551,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 +568,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 +920,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 +957,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 +970,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 +1025,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]; } 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/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.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..de6fe43af 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -10,24 +10,24 @@ //----------------------------------------------------------------------------- #include "proxmark3.h" -#include +#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 "usart.h" static void showBanner(void) { PrintAndLogEx(NORMAL, "\n"); @@ -70,7 +70,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); @@ -138,7 +138,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 @@ -206,7 +206,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 @@ -266,7 +269,7 @@ 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, " %s [[-p] ] [-b] [-w] [-f] [-c ]|[-l ]|[-s ] [-i]\n", exec_name); if (showFullHelp) { PrintAndLogEx(NORMAL, "options:"); @@ -280,6 +283,7 @@ static void show_help(bool showFullHelp, char *exec_name) { 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, " -i/--interactive enter interactive mode after executing the script or the command"); PrintAndLogEx(NORMAL, "\nsamples:"); PrintAndLogEx(NORMAL, " %s -h\n", exec_name); PrintAndLogEx(NORMAL, " %s -m\n", exec_name); @@ -302,6 +306,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; @@ -438,6 +443,12 @@ 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; + } + // We got an unknown parameter PrintAndLogEx(ERR, _RED_("ERROR:") "invalid parameter: " _YELLOW_("%s") "\n", argv[i]); show_help(false, exec_name); @@ -512,21 +523,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..6d245da10 100644 --- a/client/proxmark3.h +++ b/client/proxmark3.h @@ -12,8 +12,7 @@ #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 --> " @@ -26,7 +25,7 @@ extern "C" { 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/scripting.c b/client/scripting.c index 4a2ff28d6..429d96fac 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -10,6 +10,28 @@ //----------------------------------------------------------------------------- #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" + static int returnToLuaWithError(lua_State *L, const char *fmt, ...) { char buffer[200]; va_list args; @@ -66,7 +88,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 +417,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; diff --git a/client/scripting.h b/client/scripting.h index 5b8c15ddd..07b07aa67 100644 --- a/client/scripting.h +++ b/client/scripting.h @@ -10,27 +10,9 @@ #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/" diff --git a/client/scripts/14araw.lua b/client/scripts/14araw.lua index 3bc5c060e..30ab5e497 100644 --- a/client/scripts/14araw.lua +++ b/client/scripts/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/amiibo.lua b/client/scripts/amiibo.lua index 73366de02..10ede4008 100644 --- a/client/scripts/amiibo.lua +++ b/client/scripts/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/calypso.lua b/client/scripts/calypso.lua index de512c5c8..afb466109 100644 --- a/client/scripts/calypso.lua +++ b/client/scripts/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/didump.lua b/client/scripts/didump.lua index d5ac6f873..a9228c7b5 100644 --- a/client/scripts/didump.lua +++ b/client/scripts/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.lua b/client/scripts/dumptoemul.lua index e364ccc8b..80653a14a 100644 --- a/client/scripts/dumptoemul.lua +++ b/client/scripts/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/mfkeys.lua b/client/scripts/mfkeys.lua index 65f50eb9c..f15bb6d5e 100644 --- a/client/scripts/mfkeys.lua +++ b/client/scripts/mfkeys.lua @@ -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 diff --git a/client/scripts/mifareplus.lua b/client/scripts/mifareplus.lua index a81be26d8..f49ad95e5 100644 --- a/client/scripts/mifareplus.lua +++ b/client/scripts/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/scripts/ndef_dump.lua index 856053207..cb4be467b 100644 --- a/client/scripts/ndef_dump.lua +++ b/client/scripts/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/test_t55x7.lua b/client/scripts/test_t55x7.lua index c06d2848a..0fc112ea7 100644 --- a/client/scripts/test_t55x7.lua +++ b/client/scripts/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/scripts/test_t55x7_ask.lua index ecf02346b..bb232a6fd 100644 --- a/client/scripts/test_t55x7_ask.lua +++ b/client/scripts/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/scripts/test_t55x7_bi.lua index 0b0239717..49ee4882a 100644 --- a/client/scripts/test_t55x7_bi.lua +++ b/client/scripts/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/scripts/test_t55x7_fsk.lua index abf4692d7..c755042b1 100644 --- a/client/scripts/test_t55x7_fsk.lua +++ b/client/scripts/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/scripts/test_t55x7_psk.lua index 2c0efa163..10fecd549 100644 --- a/client/scripts/test_t55x7_psk.lua +++ b/client/scripts/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/scripts/tnp3clone.lua index 18dd6edfb..58bb5d338 100644 --- a/client/scripts/tnp3clone.lua +++ b/client/scripts/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/scripts/tnp3dump.lua index 0faadecaf..488d2f5f9 100644 --- a/client/scripts/tnp3dump.lua +++ b/client/scripts/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/scripts/tnp3sim.lua index f1b58f95e..014474416 100644 --- a/client/scripts/tnp3sim.lua +++ b/client/scripts/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/ufodump.lua b/client/scripts/ufodump.lua index 0f6a51a76..140652492 100644 --- a/client/scripts/ufodump.lua +++ b/client/scripts/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/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/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..9927fd6d6 100644 --- a/client/ui.c +++ b/client/ui.c @@ -16,6 +16,15 @@ #endif #include "ui.h" +#include "commonutil.h" // ARRAYLEN + +#include // for Mingw readline +#include +#include +#include +#include +#include "util.h" + session_arg_t session; double CursorScaleFactor = 1; diff --git a/client/ui.h b/client/ui.h index 6e70b053d..648dce4c4 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; diff --git a/client/util.c b/client/util.c index f6f89e0ff..52321689b 100644 --- a/client/util.c +++ b/client/util.c @@ -9,12 +9,22 @@ //----------------------------------------------------------------------------- // 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; @@ -807,24 +817,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..09aeeaecb 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,20 +21,6 @@ # 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; int kbd_enter_pressed(void); diff --git a/client/util_posix.c b/client/util_posix.c index ca54d2ae4..050040a32 100644 --- a/client/util_posix.c +++ b/client/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/client/util_posix.h index a0a8c8638..546b4ea35 100644 --- a/client/util_posix.h +++ b/client/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/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/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/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/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 81% rename from common/Makefile.common rename to common_arm/Makefile.common index 282f242d9..cf4405d6a 100644 --- a/common/Makefile.common +++ b/common_arm/Makefile.common @@ -31,10 +31,11 @@ AS = $(CROSS)as LD = $(CROSS)ld OBJCOPY = $(CROSS)objcopy GZIP=gzip +MV=mv OBJDIR = obj -INCLUDE = -I../include -I../common -I. +INCLUDE = -I../include -I../common_arm -I../common_fpga -I../common -I. TAR=tar TARFLAGS = -C .. -rvf @@ -63,14 +64,19 @@ DETECTED_OS=Windows endif # 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 +84,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 +119,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 97% rename from common/Makefile.hal rename to common_arm/Makefile.hal index 46154d244..af80bc6ac 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 @@ -111,8 +113,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)) diff --git a/common/default_version.c b/common_arm/default_version.c similarity index 93% rename from common/default_version.c rename to common_arm/default_version.c index b586e4ad1..e1e5dc64c 100644 --- a/common/default_version.c +++ b/common_arm/default_version.c @@ -1,4 +1,4 @@ -#include "proxmark3.h" +#include "proxmark3_arm.h" /* This is the default version.c file that Makefile.common falls back to if perl is not available */ const struct version_information __attribute__((section(".version_information"))) version_information = { VERSION_INFORMATION_MAGIC, 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/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/md/Installation_Instructions/Troubleshooting.md b/doc/md/Installation_Instructions/Troubleshooting.md new file mode 100644 index 000000000..b4ed877cb --- /dev/null +++ b/doc/md/Installation_Instructions/Troubleshooting.md @@ -0,0 +1,128 @@ +# Troubleshooting guide + +## First of all + +Always use the latest repository commits from *master* branch. There are always many fixes done almost daily. + +## `./proxmark.sh` or `./flash-*.sh` doesn't see my Proxmark + +Try using directly the client or flasher: + +``` +client/flasher ... +client/proxmark ... +``` + +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. + +``` +./flash-bootrom.sh +./flash-fullimage.sh +``` +or +``` +client/flasher -b bootrom/obj/bootrom.elf +client/flasher 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. + +``` +./flash-fullimage.sh +``` +or +``` +client/flasher 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. + +``` +./flash-bootrom.sh +``` +or +``` +client/flasher -b 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 + +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 + +Depending how you launch the client, your working directory might be the root of the repository: + +``` +./proxmark.sh ... +client/proxmark ... +``` + +or the `client/` subdirectory: + +``` +cd client; ./proxmark ... +``` + +Therefore client commands referring to files of the repo must be adapted, e.g. + +``` +pm3 --> sc upgrade f tools/simmodule/SIM011.BIN +<> +pm3 --> sc upgrade f ../tools/simmodule/SIM011.BIN +``` + +``` +pm3 --> mem load f default_keys m +<> +pm3 --> mem load f client/default_keys m +``` + +etc. + +This also affects where your history and logfile will be read from and written to. + 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/fpga/Makefile b/fpga/Makefile index ba9fec28b..b28c27db9 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -1,5 +1,3 @@ -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 @@ -38,7 +36,6 @@ fpga_lf.ngc: fpga_lf.v fpga.ucf xst_lf.scr util.v clk_divider.v lo_edge_detect.v .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..20d2ca440 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..dff9fda3f --- /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/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..29df618a1 --- /dev/null +++ b/include/ansi.h @@ -0,0 +1,11 @@ +#ifndef __ANSI_H +#define __ANSI_H + +#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/include/common.h b/include/common.h index dec2261ec..f427cb221 100644 --- a/include/common.h +++ b/include/common.h @@ -12,26 +12,11 @@ #ifndef __COMMON_H #define __COMMON_H -#ifdef __cplusplus -extern "C" { -#endif - +#include #include -#include #include -typedef unsigned char byte_t; - -#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 +123,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..3d7b156bd 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; @@ -257,6 +258,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 @@ -315,184 +317,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 +496,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 +550,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 +572,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 96% rename from common/protocols.h rename to include/protocols.h index cef339dc4..5a1e56f4e 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 /* @@ -279,6 +276,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 +358,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 +414,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 +542,5 @@ 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; - - #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..232e80276 --- /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/cu.usbmodem" +#else +#define SERIAL_PORT_EXAMPLE_H "/dev/ttyACM0" +#endif + +#endif diff --git a/recovery/Makefile b/recovery/Makefile index 601f93055..59f7f37c8 100644 --- a/recovery/Makefile +++ b/recovery/Makefile @@ -1,4 +1,4 @@ -include ../common/Makefile.common +include ../common_arm/Makefile.common BINS = bootrom.bin fullimage.bin proxmark3_recovery.bin 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 100% rename from client/deprecated-hid-flasher/flasher/Makefile rename to tools/deprecated-hid-flasher/flasher/Makefile 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..8798ace1e --- /dev/null +++ b/tools/fpga_compress/Makefile @@ -0,0 +1,80 @@ +# Hide full compilation line: +ifneq ($(V),1) + Q?=@ +endif +# To see full command lines, use make V=1 + +CC = gcc +CXX = g++ +LD = g++ +RM = rm -f +MV = mv +CP = cp -a + +platform = $(shell uname) + +VPATH = ../../common/zlib +OBJDIR = obj + +# RPi Zero gcc requires -latomic +# but MacOSX /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld +# doesn't recognize option --as-needed +ifneq ($(platform),Darwin) + LDLIBS += -Wl,--as-needed -latomic -Wl,--no-as-needed +endif + +LIBS = -I../../common/zlib +INCLUDES_CLIENT = -I../../common_fpga $(LIBS) + +CFLAGS += -std=c99 -D_ISOC99_SOURCE -DPRESETS $(INCLUDES_CLIENT) -Wall -Werror -g -O3 + +# 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 + +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 + +ZLIBOBJS = $(ZLIBSRCS:%.c=$(OBJDIR)/%.o) + +BINS = fpga_compress +CLEAN = $(BINS) $(DEPENDENCY_FILES) $(ZLIBOBJS) $(OBJDIR)/*.o +# OSX Brew is expecting fpga_compress in client folder, some workaround for now: +ifeq ($(platform),Darwin) +CLEAN += $(foreach bin,$(BINS),../../client/$(bin)) +endif + +# need to assign dependancies to build these first... +all: $(BINS) + +all-static: LDLIBS:=-static $(LDLIBS) +all-static: $(BINS) + +fpga_compress: $(OBJDIR)/fpga_compress.o $(ZLIBOBJS) + $(info [=] LD $@) + $(Q)$(LD) $(LDFLAGS) $(ZLIBFLAGS) $^ $(LDLIBS) -o $@ +# OSX Brew is expecting fpga_compress in client folder, some workaround for now: +ifeq ($(platform),Darwin) + $(Q)$(CP) $@ ../../client/ +endif + +clean: + $(Q)$(RM) $(CLEAN) + +.PHONY: all clean + +%.o: %.c +$(OBJDIR)/%.o : %.c $(OBJDIR)/%.d + $(info [-] CC $<) + $(Q)$(CC) $(DEPFLAGS) $(CFLAGS) $(ZLIBFLAGS) -c -o $@ $< + $(Q)$(POSTCOMPILE) + +DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(ZLIBSRCS)) $(OBJDIR)/fpga_compress.d + +$(DEPENDENCY_FILES): ; +.PRECIOUS: $(DEPENDENCY_FILES) + +-include $(DEPENDENCY_FILES) + 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..7777b6d51 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), diff --git a/tools/fpga_compress/obj/.dummy b/tools/fpga_compress/obj/.dummy new file mode 100644 index 000000000..e69de29bb 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 < -#ifdef __cplusplus -extern "C" { -#endif struct Crypto1State {uint32_t odd, even;}; struct Crypto1State *crypto1_create(uint64_t); @@ -87,7 +84,4 @@ static inline int filter(uint32_t const x) { f |= 0x0d938 >> (x >> 16 & 0xf) & 1; return BIT(0xEC57E80A, f); } -#ifdef __cplusplus -} -#endif #endif