Merge branch 'master' into smartcard-relay

This commit is contained in:
Grayson Martin 2023-09-12 22:30:59 -05:00
commit 7f91da8a9a
No known key found for this signature in database
GPG key ID: 4914C62F2696A273
1001 changed files with 51581 additions and 4531 deletions

View file

@ -41,7 +41,7 @@ jobs:
run: sudo apt-get update run: sudo apt-get update
- name: Install dependencies - name: Install dependencies
run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0 lua5.2 sed libssl-dev run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0 lua5.2 sed libssl-dev
- name: Install Python dependencies - name: Install Python dependencies
run: | run: |

View file

@ -26,7 +26,7 @@ jobs:
run: sudo apt-get update run: sudo apt-get update
- name: Install dependencies - name: Install dependencies
run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0 lua5.2 sed libssl-dev run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0 lua5.2 sed libssl-dev
- name: Install Python dependencies - name: Install Python dependencies
run: | run: |
@ -58,7 +58,7 @@ jobs:
run: sudo apt-get update run: sudo apt-get update
- name: Install dependencies - name: Install dependencies
run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0 lua5.2 sed libssl-dev run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0 lua5.2 sed libssl-dev
- name: Install Python dependencies - name: Install Python dependencies
run: | run: |
@ -91,7 +91,7 @@ jobs:
run: sudo apt-get update run: sudo apt-get update
- name: Install dependencies - name: Install dependencies
run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0 lua5.2 sed libssl-dev run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0 lua5.2 sed libssl-dev
- name: Install Python dependencies - name: Install Python dependencies
run: | run: |

View file

@ -18,6 +18,5 @@ jobs:
- name: check unique keys in dic files - name: check unique keys in dic files
shell: bash shell: bash
run: | run: |
find . -type f -name "*.dic" | xargs -I {} sh -c "echo {} && cat {} | grep -v '#' | sort | uniq -i -d -c | sort -n -r " find . -type f -name "*.dic" | xargs -I {} sh -c "echo {} && cat {} | sed 's/ *#.*//;/^$/d' | sort | uniq -i -d -c | sort -n -r "
if [[ $(find . -type f -name "*.dic" | xargs -I {} sh -c "echo {} && cat {} | grep -v '#' | sort | uniq -i -d -c | sort -n -r " | grep -v "./" | wc -l) -gt 0 ]]; then exit 1; fi if [[ $(find . -type f -name "*.dic" | xargs -I {} sh -c "echo {} && cat {} | sed 's/ *#.*//;/^$/d' | sort | uniq -i -d -c | sort -n -r " | grep -v '^\./' | wc -l) -gt 0 ]]; then exit 1; fi

View file

@ -110,6 +110,7 @@ jobs:
gcc-arm-none-eabi gcc-arm-none-eabi
libnewlib-dev libnewlib-dev
libbz2-dev libbz2-dev
liblz4-dev
qtbase5-dev qtbase5-dev
cmake cmake
libpython3-dev libpython3-dev

View file

@ -4,13 +4,62 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
## [unreleased][unreleased] ## [unreleased][unreleased]
- Use proxmark3 as a generic smartcard reader with other software with `smart relay` (@gm3197) - Use proxmark3 as a generic smartcard reader with other software with `smart relay` (@gm3197)
- Fixed `utils.lua` library function "convertdectohex" wasn't working (@iceman1001)
- Added `hf iclass creditepurse` command to allow crediting the epurse debit value (@nvx)
## [Raccoon.4.17140][2023-09-09]
- Changed text and adjust pm3_test case for mf_aes_brute (@doegox)
- Fix CPPChecker warnings (@doegox)
- Fix TubmleWeed docker setup (@doegox)
- Added default keys (@ernestask) (@craftbyte)
- Fixed MFU authentication to send PACK correctly (@shallax)
- Fixed list output when line has 16 bytes (@piru)
- Changed AIDlist w new entries (@kormax)
- Swapped to OE1 for Shallow modulation on RDV4. Thanks to @gentilkiwi for testing (@d18c7db)
- Changed iClass SIO and Legacy credential detection to be more reliable (@nvx)
- Add hf_cardhopper standalone mode for long-distance relay attacks (@startrekdude)
- Added `hf iclass esetblk` - set iClass emulator memory block data (@nvx)
- Added cryptorf regressiontests (@iceman1001)
- Fixed `cryptorf/sma_multi` - local state used in multithread (@iceman1001)
- Changed `fpga_compress` - better deallocation of memory and closing of file handles (@iceman1001)
- Changed `hf search` - less swaps of fpga images on device side (@iceman1001)
- Changed `mkversion.sh` - now regenerates version_pm3.c (and consequently the binaries) only when needed (@doegox)
- Added `data atr` - a command to lookup ATR (@iceman1001)
- Fixed bug in ATR lookup fct, thanks @DidierA (@iceman1001)
- Updated ATR list (@iceman1001)
- Changed `mem load -m` - now correctly erase all allocated flash memory (@iceman1001)
- Fixed emulator quick dump to handle MFC Ev1 extra sectors (@iceman100)
- Removed some empty dump files (@iceman1001)
- Added a fct to choose fpga mode (@iceman1001)
- Changed `hf mf eload/gsave` - fast uploading to emulator memory (@iceman1001)
- Added empty dump files with keys for easy simulation (@iceman1001)
- Added `hf 15 view` - view ISO15693 dump files (@iceman1001)
- Fixed `hf iclass config` - now loops correct in keyroll generation (@iceman1001)
- Added `hf iclass sam` - skeleton command (@iceman1001)
- Changed `lf cotag demo` - a new decoder (@iceman1001)
- Changed `hf legic view/eview/info` - now in verbose mode will print raw hex dump (@iceman1001)
- Added new test for cotag demod using data commands in pm3_test.sh (@iceman1001)
- Added new sample trace file for cotag w fc/272. Thanks s1acky! (@iceman1001)
- Fixed `hf legic eload` - now it doesn't crash client (@doegox)
- Changed `lf hitag *` - rework client side (@doegox)
- Changed data commands to handle ask/nrz clocks above 256 (@iceman1001)
- Added `data envelope` - almost acts like data askedgedetect (@iceman1001)
- Added `data cthreshold` - acts like an inverted dirtythreshold command. Remove center values (@iceman1001)
- Added `hf mfp list` - interprets MIFARE Plus commands in traces (@DidierA)
- Changed `hf legic sim` - loop and return codes on deviceside updated to DEFINES (@iceman1001)
- Changed `hf legic einfo` - now accepts the three different cardsizes as params (@iceman1001)
- Fixed `lf cotag reader -1` - now doesn't fail (@iceman1001)
- Added support for LZ4 compressed hardnested tables (@doegox)
- Changed `emv reader -v` - now tries to print found transactions logs (@iceman1001)
- Added ISO4217 currency lookup (@iceman1001)
- Fixed bad free in loadfilebinarykey fct. Thanks to @gentilkiwi
- Changed `emv reader -v` - now can decode track1/2 data if found (@iceman1001) - Changed `emv reader -v` - now can decode track1/2 data if found (@iceman1001)
- Added `emv reader` - act as a EMV reader (@iceman1001) - Added `emv reader` - act as a EMV reader (@iceman1001)
- Added support for Apple Wallet NFC Passes with the Value Added Services protocol implementation (@gm3197) - Added support for Apple Wallet NFC Passes with the Value Added Services protocol implementation (@gm3197)
- Fix compiling liblua on iOS (@The-SamminAter) - Fixed compiling liblua on iOS (@The-SamminAter)
- Changed `hf_mf_luxeo_dump.lua` - now have list of keys to iterate (@iceman1001) - Changed `hf_mf_luxeo_dump.lua` - now have list of keys to iterate (@iceman1001)
- Fixed the timeout of TCP connections (@wh201906) - Fixed the timeout of TCP connections (@wh201906)
- Made the connection timeout configurable (@wh201906) - Changed the connection timeout configurable (@wh201906)
## [Seven.4.16717][2023-06-25] ## [Seven.4.16717][2023-06-25]
- Change `hf 14a info` - now identifes QL88 tags (@iceman1001) - Change `hf 14a info` - now identifes QL88 tags (@iceman1001)
@ -27,7 +76,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Added more default keys (@iceman1001) Thanks anon! - Added more default keys (@iceman1001) Thanks anon!
- Fixed `pm3-flash-all` shell script now correctly identify the if running on outdated bootloader (@iceman1001) - Fixed `pm3-flash-all` shell script now correctly identify the if running on outdated bootloader (@iceman1001)
- Fixed `hf 15693/iclass sniff` trace timings (@nvx) - Fixed `hf 15693/iclass sniff` trace timings (@nvx)
- Fix LegicCash segment handling in `hf_legic.lua` script (@jmichelp) - Fixed LegicCash segment handling in `hf_legic.lua` script (@jmichelp)
- Fixed `trace list` - now handles marking of crc bytes w color a bit better (@iceman1001) - Fixed `trace list` - now handles marking of crc bytes w color a bit better (@iceman1001)
- Changed `hf mfu pwdgen -r` - now generates pwd/pack for Philips Sonicare, thanks @ckuenzi, @atc1441 (@iceman1001) - Changed `hf mfu pwdgen -r` - now generates pwd/pack for Philips Sonicare, thanks @ckuenzi, @atc1441 (@iceman1001)
- Changed `hf mfu info` - now detects Philips Sonicare devices (@iceman1001) - Changed `hf mfu info` - now detects Philips Sonicare devices (@iceman1001)
@ -117,11 +166,11 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Changed `hf mfu info` - now also does a simple OTP fingerprinting (@iceman1001) - Changed `hf mfu info` - now also does a simple OTP fingerprinting (@iceman1001)
- Changed `hf mf wrbl` - now checks for strict readonly ACL's in the data to write (@iceman1001) - Changed `hf mf wrbl` - now checks for strict readonly ACL's in the data to write (@iceman1001)
- Changed `hf mf view` - verbose printing if strict readonly ACL's exists in dump file (@iceman1001) - Changed `hf mf view` - verbose printing if strict readonly ACL's exists in dump file (@iceman1001)
- Add command `piv authsign` to get a buffer signed by the selected key (@jmichelp) - Added command `piv authsign` to get a buffer signed by the selected key (@jmichelp)
- Add command `piv scan` which tries to read all known containers on PIV (@jmichelp) - Added command `piv scan` which tries to read all known containers on PIV (@jmichelp)
- Add support for PIV commands, over wired and contactless interfaces (@jmichelp) - Added support for PIV commands, over wired and contactless interfaces (@jmichelp)
- Add `--shallow` option to `hf iclass` reader commands to do shallow (ASK) reader modulation instead of OOK (@nvx) - Added `--shallow` option to `hf iclass` reader commands to do shallow (ASK) reader modulation instead of OOK (@nvx)
- Improved NXP SLI/SLIX series tag identification (@nvx) - Change and improved NXP SLI/SLIX series tag identification (@nvx)
- Fixed buffer overflow in "lf em 4x05 sniff" (@HeinrichsH) - Fixed buffer overflow in "lf em 4x05 sniff" (@HeinrichsH)
- Fixed potential NULL array printing (@jmichelp) - Fixed potential NULL array printing (@jmichelp)
- Added PIV aid to resource file (@jmichelp) - Added PIV aid to resource file (@jmichelp)

View file

@ -29,7 +29,7 @@ ifneq (,$(DESTDIR))
endif endif
endif endif
all clean install uninstall check: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/% mf_nonce_brute/% mfd_aes_brute/% fpga_compress/% all clean install uninstall check: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/% mf_nonce_brute/% mfd_aes_brute/% fpga_compress/% cryptorf/%
# hitag2crack toolsuite is not yet integrated in "all", it must be called explicitly: "make hitag2crack" # hitag2crack toolsuite is not yet integrated in "all", it must be called explicitly: "make hitag2crack"
#all clean install uninstall check: %: hitag2crack/% #all clean install uninstall check: %: hitag2crack/%
@ -39,7 +39,7 @@ INSTALLSCRIPTS=pm3 pm3-flash pm3-flash-all pm3-flash-bootrom pm3-flash-fullimage
INSTALLSHARES=tools/jtag_openocd traces INSTALLSHARES=tools/jtag_openocd traces
INSTALLDOCS=doc/*.md doc/md INSTALLDOCS=doc/*.md doc/md
install: all common/install install: common/install
common/install: common/install:
$(info [@] Installing common resources to $(MYDESTDIR)$(PREFIX)...) $(info [@] Installing common resources to $(MYDESTDIR)$(PREFIX)...)
@ -109,6 +109,9 @@ endif
$(Q)-$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH) $(Q)-$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
# tests # tests
cryptorf/check: FORCE
$(info [*] CHECK $(patsubst %/check,%,$@))
$(Q)$(BASH) tools/pm3_tests.sh $(CHECKARGS) $(patsubst %/check,%,$@)
mfkey/check: FORCE mfkey/check: FORCE
$(info [*] CHECK $(patsubst %/check,%,$@)) $(info [*] CHECK $(patsubst %/check,%,$@))
$(Q)$(BASH) tools/pm3_tests.sh $(CHECKARGS) $(patsubst %/check,%,$@) $(Q)$(BASH) tools/pm3_tests.sh $(CHECKARGS) $(patsubst %/check,%,$@)
@ -145,6 +148,9 @@ common/check: FORCE
check: common/check check: common/check
$(info [*] ALL CHECKS DONE) $(info [*] ALL CHECKS DONE)
cryptorf/%: FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C tools/cryptorf $(patsubst cryptorf/%,%,$@) DESTDIR=$(MYDESTDIR)
mfkey/%: FORCE mfkey/%: FORCE
$(info [*] MAKE $@) $(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C tools/mfkey $(patsubst mfkey/%,%,$@) DESTDIR=$(MYDESTDIR) $(Q)$(MAKE) --no-print-directory -C tools/mfkey $(patsubst mfkey/%,%,$@) DESTDIR=$(MYDESTDIR)
@ -170,7 +176,7 @@ client/%: FORCE cleanifplatformchanged
$(info [*] MAKE $@) $(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C client $(patsubst client/%,%,$@) DESTDIR=$(MYDESTDIR) $(Q)$(MAKE) --no-print-directory -C client $(patsubst client/%,%,$@) DESTDIR=$(MYDESTDIR)
recovery/all: bootrom/all armsrc/all recovery/all: bootrom/all armsrc/all
recovery/install: bootrom/all armsrc/all recovery/install: bootrom/install armsrc/install
recovery/%: FORCE cleanifplatformchanged recovery/%: FORCE cleanifplatformchanged
$(info [*] MAKE $@) $(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C recovery $(patsubst recovery/%,%,$@) DESTDIR=$(MYDESTDIR) $(Q)$(MAKE) --no-print-directory -C recovery $(patsubst recovery/%,%,$@) DESTDIR=$(MYDESTDIR)
@ -196,6 +202,7 @@ help:
@echo "+ recovery - Make bootrom and fullimage files for JTAG flashing" @echo "+ recovery - Make bootrom and fullimage files for JTAG flashing"
@echo @echo
@echo "+ client - Make only the OS-specific host client" @echo "+ client - Make only the OS-specific host client"
@echo "+ cryptorf - Make tools/cryptorf"
@echo "+ mfkey - Make tools/mfkey" @echo "+ mfkey - Make tools/mfkey"
@echo "+ nonce2key - Make tools/nonce2key" @echo "+ nonce2key - Make tools/nonce2key"
@echo "+ mf_nonce_brute - Make tools/mf_nonce_brute" @echo "+ mf_nonce_brute - Make tools/mf_nonce_brute"
@ -232,6 +239,8 @@ fullimage/uninstall: armsrc/uninstall
recovery: recovery/all recovery: recovery/all
cryptorf: cryptorf/all
mfkey: mfkey/all mfkey: mfkey/all
nonce2key: nonce2key/all nonce2key: nonce2key/all
@ -318,10 +327,10 @@ style:
# Make sure python3 is installed # Make sure python3 is installed
@command -v python3 >/dev/null || ( echo "Please install 'python3' package first" ; exit 1 ) @command -v python3 >/dev/null || ( echo "Please install 'python3' package first" ; exit 1 )
# Update commands.json, patch port in case it was run under Windows # Update commands.json, patch port in case it was run under Windows
[ -x client/proxmark3 ] && client/proxmark3 --fulltext | sed 's#com[0-9]#/dev/ttyacm0#'|python3 client/pyscripts/pm3_help2json.py - doc/commands.json [ -x client/proxmark3 ] && client/proxmark3 --fulltext | sed 's#com[0-9]#/dev/ttyACM0#'|python3 client/pyscripts/pm3_help2json.py - doc/commands.json
# Update the readline autocomplete autogenerated code # Update the readline autocomplete autogenerated code
[ -x client/proxmark3 ] && client/proxmark3 --fulltext | python3 client/pyscripts/pm3_help2list.py - client/src/pm3line_vocabulory.h [ -x client/proxmark3 ] && client/proxmark3 --fulltext | python3 client/pyscripts/pm3_help2list.py - client/src/pm3line_vocabulary.h
# Detecting weird codepages and tabs. # Detecting weird codepages and tabs.
@ -370,10 +379,10 @@ release:
# - Tagging temporarily... # - Tagging temporarily...
@git tag -a -m "Release $(VERSION) - $(RELEASE_NAME)" $(VERSION) @git tag -a -m "Release $(VERSION) - $(RELEASE_NAME)" $(VERSION)
# - Changing default version information based on new tag # - Changing default version information based on new tag
@$(SH) tools/mkversion.sh > common/default_version_pm3.c.tmp && $(MV) common/default_version_pm3.c.tmp common/default_version_pm3.c @$(SH) tools/mkversion.sh --force common/default_version_pm3.c
# - Removing mkversion calls # - Removing mkversion calls
@sed -i 's#^.*\.\./tools/mkversion.sh.*|| #\t$$(Q)#' client/Makefile bootrom/Makefile armsrc/Makefile @sed -i 's#^.*\.\./tools/mkversion.sh.*|| #\t$$(Q)#' client/Makefile bootrom/Makefile armsrc/Makefile
@sed -i '/COMMAND/s/sh .*|| //' client/CMakeLists.txt @sed -i '/COMMAND/s/sh .*|| //' client/CMakeLists.txt client/experimental_lib/CMakeLists.txt
# - Deleting tag... # - Deleting tag...
@git tag -d $(VERSION) @git tag -d $(VERSION)
# - Amending commit... # - Amending commit...

View file

@ -35,9 +35,9 @@ The Proxmark3 is the swiss-army tool of RFID, allowing for interactions with the
| :------------------: | :------------------: | | :------------------: | :------------------: |
| [Linux - Setup and Build](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) | [Compilation Instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md)| | [Linux - Setup and Build](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) | [Compilation Instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md)|
| [Linux - Important notes on ModemManager](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md) | [Validating Proxmark3 Client Functionality](/doc/md/Use_of_Proxmark/1_Validation.md)| | [Linux - Important notes on ModemManager](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md) | [Validating Proxmark3 Client Functionality](/doc/md/Use_of_Proxmark/1_Validation.md)|
| [Mac OS X - Homebrew & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md) | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)| | [macOS - Homebrew & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/macOS-Homebrew-Installation-Instructions.md) | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)|
| [Mac OS X - MacPorts](/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md) | [Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)| | [macOS - MacPorts](/doc/md/Installation_Instructions/macOS-MacPorts-Installation-Instructions.md) | [Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)|
| [Mac OS X - Setup and Build](/doc/md/Installation_Instructions/Mac-OS-X-Compile-From-Source-Instructions.md) || | [macOS - Setup and Build](/doc/md/Installation_Instructions/macOS-Compile-From-Source-Instructions.md) ||
| [Windows - Setup and Build](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md) || | [Windows - Setup and Build](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md) ||
| [Termux / Android - Setup and Build](/doc/termux_notes.md) || | [Termux / Android - Setup and Build](/doc/termux_notes.md) ||
| [Blue Shark Manual](/doc/bt_manual_v10.md) | [Command Cheat Sheet](/doc/cheatsheet.md)| | [Blue Shark Manual](/doc/bt_manual_v10.md) | [Command Cheat Sheet](/doc/cheatsheet.md)|
@ -184,7 +184,7 @@ This repo compiles nicely on
- Windows/MinGW environment - Windows/MinGW environment
- Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, NetHunter, Arch Linux, Fedora, Debian, Raspbian - Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, NetHunter, Arch Linux, Fedora, Debian, Raspbian
- Android / Termux - Android / Termux
- Mac OS X / Homebrew (or MacPorts, experimental) / Apple Silicon M1 - macOS / Homebrew (or MacPorts, experimental) / Apple Silicon M1
- Docker container - Docker container
- [ Iceman repo based ubuntu 18.04 container ](https://hub.docker.com/r/secopsconsult/proxmark3) - [ Iceman repo based ubuntu 18.04 container ](https://hub.docker.com/r/secopsconsult/proxmark3)
- [ Iceman fork based container v1.7 ](https://hub.docker.com/r/iceman1001/proxmark3/) - [ Iceman fork based container v1.7 ](https://hub.docker.com/r/iceman1001/proxmark3/)

View file

@ -233,7 +233,7 @@ uint32_t BigBuf_get_traceLen(void) {
by 'hf list -t raw', alternatively 'hf list -t <proto>' for protocol-specific by 'hf list -t raw', alternatively 'hf list -t <proto>' for protocol-specific
annotation of commands/responses. annotation of commands/responses.
**/ **/
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool reader2tag) { bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, const uint8_t *parity, bool reader2tag) {
if (tracing == false) { if (tracing == false) {
return false; return false;
} }
@ -290,7 +290,7 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
} }
// specific LogTrace function for ISO15693: the duration needs to be scaled because otherwise it won't fit into a uint16_t // specific LogTrace function for ISO15693: the duration needs to be scaled because otherwise it won't fit into a uint16_t
bool LogTrace_ISO15693(const uint8_t *bytes, uint16_t len, uint32_t ts_start, uint32_t ts_end, uint8_t *parity, bool reader2tag) { bool LogTrace_ISO15693(const uint8_t *bytes, uint16_t len, uint32_t ts_start, uint32_t ts_end, const uint8_t *parity, bool reader2tag) {
uint32_t duration = ts_end - ts_start; uint32_t duration = ts_end - ts_start;
duration /= 32; duration /= 32;
ts_end = ts_start + duration; ts_end = ts_start + duration;
@ -306,17 +306,24 @@ bool RAMFUNC LogTraceBits(const uint8_t *btBytes, uint16_t bitLen, uint32_t time
} }
// Emulator memory // Emulator memory
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length) { uint8_t emlSet(const uint8_t *data, uint32_t offset, uint32_t length) {
uint8_t *mem = BigBuf_get_EM_addr(); uint8_t *mem = BigBuf_get_EM_addr();
if (offset + length < CARD_MEMORY_SIZE) { if (offset + length <= CARD_MEMORY_SIZE) {
memcpy(mem + offset, data, length); memcpy(mem + offset, data, length);
return 0; return 0;
} }
Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset + length), CARD_MEMORY_SIZE); Dbprintf("Error, trying to set memory outside of bounds! " _RED_("%d") " > %d", (offset + length), CARD_MEMORY_SIZE);
return 1;
}
uint8_t emlGet(uint8_t *out, uint32_t offset, uint32_t length) {
uint8_t *mem = BigBuf_get_EM_addr();
if (offset + length <= CARD_MEMORY_SIZE) {
memcpy(out, mem + offset, length);
return 0;
}
Dbprintf("Error, trying to read memory outside of bounds! " _RED_("%d") " > %d", (offset + length), CARD_MEMORY_SIZE);
return 1; return 1;
} }
// get the address of the ToSend buffer. Allocate part of Bigbuf for it, if not yet done // get the address of the ToSend buffer. Allocate part of Bigbuf for it, if not yet done
tosend_t *get_tosend(void) { tosend_t *get_tosend(void) {

View file

@ -51,11 +51,12 @@ void set_tracing(bool enable);
void set_tracelen(uint32_t value); void set_tracelen(uint32_t value);
bool get_tracing(void); 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 reader2tag); bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, const uint8_t *parity, bool reader2tag);
bool RAMFUNC LogTraceBits(const uint8_t *btBytes, uint16_t bitLen, uint32_t timestamp_start, uint32_t timestamp_end, bool reader2tag); bool RAMFUNC LogTraceBits(const uint8_t *btBytes, uint16_t bitLen, uint32_t timestamp_start, uint32_t timestamp_end, bool reader2tag);
bool LogTrace_ISO15693(const uint8_t *bytes, uint16_t len, uint32_t ts_start, uint32_t ts_end, uint8_t *parity, bool reader2tag); bool LogTrace_ISO15693(const uint8_t *bytes, uint16_t len, uint32_t ts_start, uint32_t ts_end, const uint8_t *parity, bool reader2tag);
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length); uint8_t emlSet(const uint8_t *data, uint32_t offset, uint32_t length);
uint8_t emlGet(uint8_t *out, uint32_t offset, uint32_t length);
typedef struct { typedef struct {
int max; int max;

View file

@ -53,7 +53,7 @@ void LCDFill(unsigned char xs, unsigned char ys, unsigned char width, unsigned c
} }
} }
void LCDString(char *lcd_string, const char *font_style, unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor) { void LCDString(const char *lcd_string, const char *font_style, unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor) {
unsigned int i; unsigned int i;
unsigned char mask = 0, px, py, xme, yme, offset; unsigned char mask = 0, px, py, xme, yme, offset;
const char *data; const char *data;

View file

@ -130,7 +130,7 @@ void LCDInit(void);
void LCDReset(void); void LCDReset(void);
void LCDSetXY(unsigned char x, unsigned char y); void LCDSetXY(unsigned char x, unsigned char y);
void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color); void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color);
void LCDString(char *lcd_string, const char *font_style, unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor); void LCDString(const char *lcd_string, const char *font_style, unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor);
void LCDFill(unsigned char xs, unsigned char ys, unsigned char width, unsigned char height, unsigned char color); void LCDFill(unsigned char xs, unsigned char ys, unsigned char width, unsigned char height, unsigned char color);
#endif #endif

View file

@ -181,10 +181,10 @@ showinfo:
.DELETE_ON_ERROR: .DELETE_ON_ERROR:
# version_pm3.c should be remade on every time fullimage.stage1.elf should be remade # version_pm3.c should be checked on every time fullimage.stage1.elf should be remade
version_pm3.c: default_version_pm3.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) .FORCE version_pm3.c: default_version_pm3.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) .FORCE
$(info [-] GEN $@) $(info [-] CHECK $@)
$(Q)$(SH) ../tools/mkversion.sh > $@ || $(CP) $< $@ $(Q)$(SH) ../tools/mkversion.sh $@ || $(CP) $< $@
fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR)
$(info [-] GEN $@) $(info [-] GEN $@)

View file

@ -86,6 +86,9 @@ define KNOWN_STANDALONE_DEFINITIONS
| HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth | | HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth |
| (RDV4 only) | storing in flashmem - Bogito | | (RDV4 only) | storing in flashmem - Bogito |
+----------------------------------------------------------+ +----------------------------------------------------------+
| HF_CARDHOPPER | Relay 14a protocols over long distances|
| (RDV4 only) | (w/ IP backbone) - Sam Haskins |
+----------------------------------------------------------+
| HF_COLIN | Mifare ultra fast sniff/sim/clone | | HF_COLIN | Mifare ultra fast sniff/sim/clone |
| (RDV4 only) | - Colin Brigato | | (RDV4 only) | - Colin Brigato |
+----------------------------------------------------------+ +----------------------------------------------------------+
@ -130,9 +133,9 @@ endef
STANDALONE_MODES := LF_SKELETON STANDALONE_MODES := LF_SKELETON
STANDALONE_MODES += LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_MULTIHID LF_NEDAP_SIM LF_NEXID LF_PROXBRUTE LF_PROX2BRUTE LF_SAMYRUN LF_THAREXDE STANDALONE_MODES += LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_MULTIHID LF_NEDAP_SIM LF_NEXID LF_PROXBRUTE LF_PROX2BRUTE LF_SAMYRUN LF_THAREXDE
STANDALONE_MODES += HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_AVEFUL HF_BOG HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_REBLAY HF_TCPRST HF_TMUDFORD HF_YOUNG STANDALONE_MODES += HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_AVEFUL HF_BOG HF_CARDHOPPER HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_REBLAY HF_TCPRST HF_TMUDFORD HF_YOUNG
STANDALONE_MODES += DANKARMULTI STANDALONE_MODES += DANKARMULTI
STANDALONE_MODES_REQ_BT := HF_REBLAY STANDALONE_MODES_REQ_BT := HF_CARDHOPPER HF_REBLAY
STANDALONE_MODES_REQ_SMARTCARD := STANDALONE_MODES_REQ_SMARTCARD :=
STANDALONE_MODES_REQ_FLASH := LF_HIDFCBRUTE LF_ICEHID LF_NEXID LF_THAREXDE HF_BOG HF_COLIN HF_ICECLASS HF_LEGICSIM HF_MFCSIM STANDALONE_MODES_REQ_FLASH := LF_HIDFCBRUTE LF_ICEHID LF_NEXID LF_THAREXDE HF_BOG HF_COLIN HF_ICECLASS HF_LEGICSIM HF_MFCSIM
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),) ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),)

View file

@ -97,6 +97,10 @@ endif
ifneq (,$(findstring WITH_STANDALONE_HF_BOG,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_BOG,$(APP_CFLAGS)))
SRC_STANDALONE = hf_bog.c SRC_STANDALONE = hf_bog.c
endif endif
# WITH_STANDALONE_HF_CARDHOPPER
ifneq (,$(findstring WITH_STANDALONE_HF_CARDHOPPER,$(APP_CFLAGS)))
SRC_STANDALONE = hf_cardhopper.c
endif
# WITH_STANDALONE_HF_COLIN # WITH_STANDALONE_HF_COLIN
ifneq (,$(findstring WITH_STANDALONE_HF_COLIN,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_COLIN,$(APP_CFLAGS)))
SRC_STANDALONE = vtsend.c hf_colin.c frozen.c nprintf.c SRC_STANDALONE = vtsend.c hf_colin.c frozen.c nprintf.c

View file

@ -43,7 +43,7 @@
* 1. mem spiffs dump -s hf_14asniff.trace -d hf_14asniff.trace * 1. mem spiffs dump -s hf_14asniff.trace -d hf_14asniff.trace
* Copies trace data file from flash to your PC. * Copies trace data file from flash to your PC.
* *
* 2. trace load hf_14asniff.trace * 2. trace load -f hf_14asniff.trace
* Loads trace data from a file into PC-side buffers. * Loads trace data from a file into PC-side buffers.
* *
* 3. For ISO14a: trace list -t 14a -1 * 3. For ISO14a: trace list -t 14a -1
@ -55,6 +55,7 @@
* the lab connected to PM3 client before taking it into the field. * the lab connected to PM3 client before taking it into the field.
* *
* To delete the trace data from flash: * To delete the trace data from flash:
* mem spiffs remove -f hf_14asniff.trace
* *
* Caveats / notes: * Caveats / notes:
* - Trace buffer will be cleared on starting stand-alone mode. Data in flash * - Trace buffer will be cleared on starting stand-alone mode. Data in flash

15
armsrc/Standalone/hf_14bsniff.c Executable file → Normal file
View file

@ -14,9 +14,24 @@
* - LED3: sniffed reader command, turns off when finished sniffing tag command * - LED3: sniffed reader command, turns off when finished sniffing tag command
* - LED4: unmounting/sync'ing flash (normally < 100ms) * - LED4: unmounting/sync'ing flash (normally < 100ms)
* *
* To retrieve trace data from flash:
*
* 1. mem spiffs dump -s hf_14bsniff.trace -d hf_14bsniff.trace
* Copies trace data file from flash to your PC.
*
* 2. trace load -f hf_14bsniff.trace
* Loads trace data from a file into PC-side buffers.
*
* 3. For ISO14a: trace list -t 14b -1
*
* Lists trace data from buffer without requesting it from PM3.
*
* This module emits debug strings during normal operation -- so try it out in * This module emits debug strings during normal operation -- so try it out in
* the lab connected to PM3 client before taking it into the field. * the lab connected to PM3 client before taking it into the field.
* *
* To delete the trace data from flash:
* mem spiffs remove -f hf_14bsniff.trace
*
* Caveats / notes: * Caveats / notes:
* - Trace buffer will be cleared on starting stand-alone mode. * - Trace buffer will be cleared on starting stand-alone mode.
* - This module will terminate if the trace buffer is full. * - This module will terminate if the trace buffer is full.

View file

@ -43,7 +43,7 @@
* 1. mem spiffs dump -s hf_15693sniff.trace -d hf_15693sniff.trace * 1. mem spiffs dump -s hf_15693sniff.trace -d hf_15693sniff.trace
* Copies trace data file from flash to your PC. * Copies trace data file from flash to your PC.
* *
* 2. trace load hf_15693sniff.trace * 2. trace load -f hf_15693sniff.trace
* Loads trace data from a file into PC-side buffers. * Loads trace data from a file into PC-side buffers.
* *
* 3. For ISO15693: trace list -t 15 -1 * 3. For ISO15693: trace list -t 15 -1
@ -54,6 +54,7 @@
* the lab connected to PM3 client before taking it into the field. * the lab connected to PM3 client before taking it into the field.
* *
* To delete the trace data from flash: * To delete the trace data from flash:
* mem spiffs remove -f hf_15693sniff.trace
* *
* Caveats / notes: * Caveats / notes:
* - Trace buffer will be cleared on starting stand-alone mode. Data in flash * - Trace buffer will be cleared on starting stand-alone mode. Data in flash

View file

@ -0,0 +1,417 @@
/*
* hf_cardhopper standalone mode by Sam Haskins
*
* A component of our (me + Trevor Stevado) research on long-range relay
* attacks against 14a-based protocols (as presented at DEF CON '31).
* Works with a CardHopper (recommended) or BlueShark add-on.
*
* If you're reading this, you're clearly a very interesting person---
* do reach out if you get any fun results? [ sam AT loudmouth DOT io ]
* Good luck, and may the odds be ever in your favour!
*
* The companion Android app is available on our gitlab: gitlab.com/loudmouth-security
*
* For more information, see: https://media.defcon.org/DEF%20CON%2031/DEF%20CON%2031%20presentations/Trevor%20Stevado%20Sam%20Haskins%20-%20Unlocking%20Doors%20from%20Half%20a%20Continent%20Away.pdf
*/
#include <string.h>
#include "appmain.h"
#include "BigBuf.h"
#include "dbprint.h"
#include "fpgaloader.h"
#include "iso14443a.h"
#include "protocols.h"
#include "proxmark3_arm.h"
#include "standalone.h"
#include "ticks.h"
#include "util.h"
#include "usart.h"
void ModInfo(void) {
DbpString(" HF - Long-range relay 14a over serial<->IP - a.k.a. CardHopper (Sam Haskins)");
}
typedef struct PACKED {
uint8_t len;
uint8_t dat[255];
} packet_t;
// Magic numbers
static const uint8_t magicREAD[4] = "READ";
static const uint8_t magicCARD[4] = "CARD";
static const uint8_t magicEND [4] = "\xff" "END";
static const uint8_t magicRSRT[7] = "RESTART";
static const uint8_t magicERR [4] = "\xff" "ERR";
static uint8_t magicACK [1] = "\xfe"; // is constant, but must be passed to API that doesn't like that
// Forward declarations
static void become_reader(void);
static void select_card(void);
static void become_card(void);
static void prepare_emulation(uint8_t *, uint16_t *, uint8_t *, packet_t *);
static void cook_ats(packet_t *, uint8_t, uint8_t);
static bool try_use_canned_response(const uint8_t *, int, tag_response_info_t *);
static void reply_with_packet(packet_t *);
static void read_packet(packet_t *);
static void write_packet(packet_t *);
static bool GetIso14443aCommandFromReaderInterruptible(uint8_t *, uint8_t *, int *);
void RunMod(void) {
StandAloneMode();
DbpString(_CYAN_("[@]") " CardHopper has started - waiting for mode");
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
clear_trace();
set_tracing(true);
// Indicate we are alive and in CardHopper
LEDsoff();
LED_A_ON();
LED_D_ON();
while (1) {
WDT_HIT();
packet_t modeRx = { 0 };
read_packet(&modeRx);
if (memcmp(magicREAD, modeRx.dat, sizeof(magicREAD)) == 0) {
DbpString(_CYAN_("[@]") " I am a READER. I talk to a CARD.");
become_reader();
} else if (memcmp(magicCARD, modeRx.dat, sizeof(magicCARD)) == 0) {
DbpString(_CYAN_("[@]") " I am a CARD. I talk to a READER.");
become_card();
} else if (memcmp(magicEND, modeRx.dat, sizeof(magicEND)) == 0) {
break;
} else {
DbpString(_YELLOW_("[!]") " unknown mode!");
Dbhexdump(modeRx.len, modeRx.dat, true);
}
}
DbpString(_CYAN_("[@]") " exiting ...");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
static void become_reader(void) {
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
select_card(); // also sends UID, ATS
DbpString(_CYAN_("[@]") " entering reader main loop ...");
packet_t packet = { 0 };
packet_t *rx = &packet;
packet_t *tx = &packet;
uint8_t toCard[256] = { 0 };
uint8_t parity[MAX_PARITY_SIZE] = { 0 };
while (1) {
WDT_HIT();
read_packet(rx);
if (memcmp(magicRSRT, rx->dat, sizeof(magicRSRT)) == 0) break;
memcpy(toCard, rx->dat, rx->len);
AddCrc14A(toCard, rx->len);
ReaderTransmit(toCard, rx->len + 2, NULL);
tx->len = ReaderReceive(tx->dat, parity);
if (tx->len == 0) {
tx->len = sizeof(magicERR);
memcpy(tx->dat, magicERR, sizeof(magicERR));
} else tx->len -= 2; // cut off the CRC
write_packet(tx);
}
}
static void select_card(void) {
iso14a_card_select_t card = { 0 };
while (1) {
WDT_HIT();
int ret = iso14443a_select_card(NULL, &card, NULL, true, 0, false);
if (ret && ret != 1)
Dbprintf(_RED_("[!]") " Error selecting card: %d", ret);
if (ret == 1) break;
SpinDelay(20);
}
DbpString(_CYAN_("[@]") " UID:");
Dbhexdump(card.uidlen, card.uid, false);
DbpString(_CYAN_("[@]") " ATS:");
Dbhexdump(card.ats_len - 2 /* no CRC */, card.ats, false);
packet_t tx = { 0 };
tx.len = card.uidlen;
memcpy(tx.dat, card.uid, tx.len);
write_packet(&tx);
tx.len = card.ats_len - 2;
memcpy(tx.dat, card.ats, tx.len);
write_packet(&tx);
}
static void become_card(void) {
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
uint8_t tagType;
uint16_t flags;
uint8_t data[PM3_CMD_DATA_SIZE] = { 0 };
packet_t ats = { 0 };
prepare_emulation(&tagType, &flags, data, &ats);
tag_response_info_t *canned;
uint32_t cuid;
uint32_t counters[3] = { 0 };
uint8_t tearings[3] = { 0xbd, 0xbd, 0xbd };
uint8_t pages;
SimulateIso14443aInit(tagType, flags, data, &canned, &cuid, counters, tearings, &pages);
DbpString(_CYAN_("[@]") " Setup done - entering emulation loop");
int fromReaderLen;
uint8_t fromReaderDat[256] = { 0 };
uint8_t parity[MAX_PARITY_SIZE] = { 0 };
packet_t packet = { 0 };
packet_t *tx = &packet;
packet_t *rx = &packet;
while (1) {
WDT_HIT();
if (!GetIso14443aCommandFromReaderInterruptible(fromReaderDat, parity, &fromReaderLen)) {
if (usart_rxdata_available()) {
read_packet(rx);
if (memcmp(magicRSRT, rx->dat, sizeof(magicRSRT)) == 0) {
DbpString(_CYAN_("[@]") " Breaking from reader loop");
break;
}
}
continue;
}
// Option 1: Use a canned response
if (try_use_canned_response(fromReaderDat, fromReaderLen, canned)) continue;
// Option 2: Reply with our cooked ATS
if (fromReaderDat[0] == ISO14443A_CMD_RATS && fromReaderLen == 4) {
reply_with_packet(&ats);
continue;
}
// Option 3: Relay the message
tx->len = fromReaderLen - 2; // cut off the crc
memcpy(tx->dat, fromReaderDat, tx->len);
write_packet(tx);
read_packet(rx);
reply_with_packet(rx);
}
}
static void prepare_emulation(uint8_t *tagType, uint16_t *flags, uint8_t *data, packet_t *ats) {
packet_t tagTypeRx = { 0 };
read_packet(&tagTypeRx);
packet_t timeModeRx = { 0 };
read_packet(&timeModeRx);
packet_t uidRx = { 0 };
read_packet(&uidRx);
read_packet(ats);
*tagType = tagTypeRx.dat[0];
Dbprintf(_CYAN_("[@]") " Using tag type: %hhu", *tagType);
DbpString(_CYAN_("[@]") " Time control parameters:");
Dbhexdump(timeModeRx.len, timeModeRx.dat, false);
uint8_t fwi = timeModeRx.dat[0] & 0x0f;
uint8_t sfgi = timeModeRx.dat[1] & 0x0f;
Dbprintf(_CYAN_("[@]") " Parsed as fwi = %hhu, sfgi = %hhu", fwi, sfgi);
if (fwi == 0xf) {
DbpString(_YELLOW_("[!]") " Refusing to use 15 as FWI - will use 14");
fwi = 0xe;
}
if (sfgi == 0xf) {
DbpString(_YELLOW_("[!]") " Refusing to use 15 as SFGI - will use 14");
sfgi = 0xe;
}
memcpy(data, uidRx.dat, uidRx.len);
*flags = (uidRx.len == 10 ? FLAG_10B_UID_IN_DATA : (uidRx.len == 7 ? FLAG_7B_UID_IN_DATA : FLAG_4B_UID_IN_DATA));
DbpString(_CYAN_("[@]") " UID:");
Dbhexdump(uidRx.len, data, false);
Dbprintf(_CYAN_("[@]") " Flags: %hu", *flags);
DbpString(_CYAN_("[@]") " Original ATS:");
Dbhexdump(ats->len, ats->dat, false);
cook_ats(ats, fwi, sfgi);
DbpString(_CYAN_("[@]") " Cooked ATS:");
Dbhexdump(ats->len, ats->dat, false);
}
static void cook_ats(packet_t *ats, uint8_t fwi, uint8_t sfgi) {
if (ats->len != ats->dat[0]) {
DbpString(_RED_("[!]") " Malformed ATS - unable to cook; things may go wrong!");
return;
}
// If the ATS is too short (unusual), pad it to length with hopefully-sensible data
// Might be better for the phone side to do this tbh
if (ats->len == 1) {
ats->len = 4;
ats->dat[0] = 0x04;
ats->dat[1] = 0x78;
ats->dat[2] = 0x77;
// ats->dat[3] = 0x80;
} else if (ats->len == 2) {
ats->len = 4;
ats->dat[0] = 0x04;
ats->dat[2] = 0x77;
// ats->dat[3] = 0x80;
} else if (ats->len == 3) {
ats->len = 4;
ats->dat[0] = 0x04;
// ats->dat[3] = 0x80;
}
// Set the SFGI as well as the FWI - needed for some older readers (firmware revs?)
uint8_t cookedTB0 = (fwi << 4) | sfgi;
ats->dat[3] = cookedTB0;
}
static bool try_use_canned_response(const uint8_t *dat, int len, tag_response_info_t *canned) {
if ((dat[0] == ISO14443A_CMD_REQA || dat[0] == ISO14443A_CMD_WUPA) && len == 1) {
EmSendPrecompiledCmd(canned + RESP_INDEX_ATQA);
return true;
}
if (dat[1] == 0x20 && len == 2) {
if (dat[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) {
EmSendPrecompiledCmd(canned + RESP_INDEX_UIDC1);
return true;
} else if (dat[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) {
EmSendPrecompiledCmd(canned + RESP_INDEX_UIDC2);
return true;
} else if (dat[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3) {
EmSendPrecompiledCmd(canned + RESP_INDEX_UIDC3);
return true;
}
}
if (dat[1] == 0x70 && len == 9) {
if (dat[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) {
EmSendPrecompiledCmd(canned + RESP_INDEX_SAKC1);
return true;
} else if (dat[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) {
EmSendPrecompiledCmd(canned + RESP_INDEX_SAKC2);
return true;
} else if (dat[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3) {
EmSendPrecompiledCmd(canned + RESP_INDEX_SAKC3);
return true;
}
}
if (dat[0] == ISO14443A_CMD_PPS) {
EmSendPrecompiledCmd(canned + RESP_INDEX_PPS);
return true;
}
// No response is expected to these 14a commands
if ((dat[0] == 0xf2 && len == 4) || dat[0] == 0xfa) return true;
if (dat[0] == ISO14443A_CMD_HALT && len == 4) return true;
// Ignore Apple ECP2 polling
if (dat[0] == 0x6a) return true;
return false;
}
static uint8_t g_responseBuffer [512 ] = { 0 };
static uint8_t g_modulationBuffer[1024] = { 0 };
static void reply_with_packet(packet_t *packet) {
tag_response_info_t response = { 0 };
response.response = g_responseBuffer;
response.modulation = g_modulationBuffer;
memcpy(response.response, packet->dat, packet->len);
AddCrc14A(response.response, packet->len);
response.response_n = packet->len + 2;
prepare_tag_modulation(&response, sizeof(g_modulationBuffer));
EmSendPrecompiledCmd(&response);
}
static void read_packet(packet_t *packet) {
while (!usart_rxdata_available()) {
WDT_HIT();
SpinDelayUs(100);
}
uint32_t dataReceived = usart_read_ng((uint8_t *) packet, sizeof(packet_t)) - 1;
while (dataReceived != packet->len) {
while (!usart_rxdata_available()) WDT_HIT();
dataReceived += usart_read_ng(packet->dat + dataReceived, 255 - dataReceived);
}
usart_writebuffer_sync(magicACK, sizeof(magicACK));
}
static void write_packet(packet_t *packet) {
usart_writebuffer_sync((uint8_t *) packet, packet->len + 1);
}
static bool GetIso14443aCommandFromReaderInterruptible(uint8_t *received, uint8_t *par, int *len) {
LED_D_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
Uart14aInit(received, par);
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
(void)b;
uint8_t flip = 0;
uint16_t checker = 4000;
for (;;) {
WDT_HIT();
if (flip == 3) {
if (usart_rxdata_available())
return false;
flip = 0;
}
if (checker-- == 0) {
flip++;
checker = 4000;
}
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
if (MillerDecoding(b, 0)) {
*len = GetUart14a()->len;
return true;
}
}
}
return false;
}

View file

@ -293,7 +293,7 @@ static void ReadLastTagFromFlash(void) {
rdv40_spiffs_read_as_filetype((char *)HFCOLIN_LASTTAG_SYMLINK, (uint8_t *)mem, len, RDV40_SPIFFS_SAFETY_SAFE); rdv40_spiffs_read_as_filetype((char *)HFCOLIN_LASTTAG_SYMLINK, (uint8_t *)mem, len, RDV40_SPIFFS_SAFETY_SAFE);
// copy 64blocks (16bytes) starting w block0, to emulator mem. // copy 64blocks (16bytes) starting w block0, to emulator mem.
emlSetMem(mem, 0, 64); emlSetMem_xt(mem, 0, 64, 16);
DbprintfEx(FLAG_NEWLINE, "[OK] Last tag recovered from FLASHMEM set to emulator"); DbprintfEx(FLAG_NEWLINE, "[OK] Last tag recovered from FLASHMEM set to emulator");
cjSetCursLeft(); cjSetCursLeft();
@ -650,7 +650,7 @@ failtag:
for (uint8_t t = 0; t < 2; t++) { for (uint8_t t = 0; t < 2; t++) {
memcpy(mblock + t * 10, foundKey[t][sectorNo], 6); memcpy(mblock + t * 10, foundKey[t][sectorNo], 6);
} }
emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); emlSetMem_xt(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1, 16);
} }
cjSetCursLeft(); cjSetCursLeft();
@ -827,12 +827,12 @@ int e_MifareECardLoad(uint32_t numofsectors, uint8_t keytype) {
}; };
if (isOK) { if (isOK) {
if (blockNo < NumBlocksPerSector(s) - 1) { if (blockNo < NumBlocksPerSector(s) - 1) {
emlSetMem(dataoutbuf, FirstBlockOfSector(s) + blockNo, 1); emlSetMem_xt(dataoutbuf, FirstBlockOfSector(s) + blockNo, 1, 16);
} else { } else {
// sector trailer, keep the keys, set only the AC // sector trailer, keep the keys, set only the AC
emlGetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1); emlGetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1);
memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4); memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);
emlSetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1); emlSetMem_xt(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1, 16);
} }
} }
} }

View file

@ -68,8 +68,10 @@ static bool fill_eml_from_file(char *dumpfile) {
} }
//read and load dump file //read and load dump file
BigBuf_Clear(); BigBuf_Clear();
if (g_dbglevel >= DBG_INFO) if (g_dbglevel >= DBG_INFO) {
Dbprintf(_YELLOW_("Found dump file %s. Uploading to emulator memory..."), dumpfile); Dbprintf("Found dump file... `" _YELLOW_("%s") "`", dumpfile);
Dbprintf("Uploading to emulator memory...");
}
uint8_t *emCARD = BigBuf_get_EM_addr(); uint8_t *emCARD = BigBuf_get_EM_addr();
rdv40_spiffs_read_as_filetype(dumpfile, emCARD, size, RDV40_SPIFFS_SAFETY_SAFE); rdv40_spiffs_read_as_filetype(dumpfile, emCARD, size, RDV40_SPIFFS_SAFETY_SAFE);
return true; return true;

View file

@ -273,12 +273,12 @@ static int saMifareECardLoad(uint32_t numofsectors, uint8_t keytype) {
}; };
if (blockNo < NumBlocksPerSector(s) - 1) { if (blockNo < NumBlocksPerSector(s) - 1) {
emlSetMem(dataoutbuf, FirstBlockOfSector(s) + blockNo, 1); emlSetMem_xt(dataoutbuf, FirstBlockOfSector(s) + blockNo, 1, 16);
} else { } else {
// sector trailer, keep the keys, set only the AC // sector trailer, keep the keys, set only the AC
emlGetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1); emlGetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1);
memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4); memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);
emlSetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1); emlSetMem_xt(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1, 16);
} }
} }
} }
@ -505,7 +505,7 @@ void RunMod(void) {
memcpy(mblock + t * 10, foundKey[t][sectorNo], 6); memcpy(mblock + t * 10, foundKey[t][sectorNo], 6);
} }
} }
emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); emlSetMem_xt(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1, 16);
} }
} }

View file

@ -71,7 +71,8 @@ static bool fill_eml_from_file(char *dumpfile) {
//read and load dump file //read and load dump file
if (g_dbglevel >= DBG_INFO) { if (g_dbglevel >= DBG_INFO) {
Dbprintf(_YELLOW_("Found dump file %s. Uploading to emulator memory..."), dumpfile); Dbprintf("Found dump file... `" _YELLOW_("%s") "`", dumpfile);
Dbprintf("Uploading to emulator memory...");
} }
emlClearMem(); emlClearMem();

View file

@ -61,6 +61,7 @@
#include "commonutil.h" #include "commonutil.h"
#include "crc16.h" #include "crc16.h"
#include "protocols.h" #include "protocols.h"
#include "mifareutil.h"
#ifdef WITH_LCD #ifdef WITH_LCD
@ -783,6 +784,15 @@ static void PacketReceived(PacketCommandNG *packet) {
g_reply_via_usb = false; g_reply_via_usb = false;
break; break;
} }
case CMD_SET_FPGAMODE: {
uint8_t mode = packet->data.asBytes[0];
if (mode >= FPGA_BITSTREAM_LF && mode <= FPGA_BITSTREAM_HF_15) {
FpgaDownloadAndGo(mode);
reply_ng(CMD_SET_FPGAMODE, PM3_SUCCESS, NULL, 0);
}
reply_ng(CMD_SET_FPGAMODE, PM3_EINVARG, NULL, 0);
break;
}
// emulator // emulator
case CMD_SET_DBGMODE: { case CMD_SET_DBGMODE: {
g_dbglevel = packet->data.asBytes[0]; g_dbglevel = packet->data.asBytes[0];
@ -1144,27 +1154,27 @@ static void PacketReceived(PacketCommandNG *packet) {
#ifdef WITH_EM4x50 #ifdef WITH_EM4x50
case CMD_LF_EM4X50_INFO: { case CMD_LF_EM4X50_INFO: {
em4x50_info((em4x50_data_t *)packet->data.asBytes, true); em4x50_info((const em4x50_data_t *)packet->data.asBytes, true);
break; break;
} }
case CMD_LF_EM4X50_WRITE: { case CMD_LF_EM4X50_WRITE: {
em4x50_write((em4x50_data_t *)packet->data.asBytes, true); em4x50_write((const em4x50_data_t *)packet->data.asBytes, true);
break; break;
} }
case CMD_LF_EM4X50_WRITEPWD: { case CMD_LF_EM4X50_WRITEPWD: {
em4x50_writepwd((em4x50_data_t *)packet->data.asBytes, true); em4x50_writepwd((const em4x50_data_t *)packet->data.asBytes, true);
break; break;
} }
case CMD_LF_EM4X50_READ: { case CMD_LF_EM4X50_READ: {
em4x50_read((em4x50_data_t *)packet->data.asBytes, true); em4x50_read((const em4x50_data_t *)packet->data.asBytes, true);
break; break;
} }
case CMD_LF_EM4X50_BRUTE: { case CMD_LF_EM4X50_BRUTE: {
em4x50_brute((em4x50_data_t *)packet->data.asBytes, true); em4x50_brute((const em4x50_data_t *)packet->data.asBytes, true);
break; break;
} }
case CMD_LF_EM4X50_LOGIN: { case CMD_LF_EM4X50_LOGIN: {
em4x50_login((uint32_t *)packet->data.asBytes, true); em4x50_login((const uint32_t *)packet->data.asBytes, true);
break; break;
} }
case CMD_LF_EM4X50_SIM: { case CMD_LF_EM4X50_SIM: {
@ -1174,7 +1184,7 @@ static void PacketReceived(PacketCommandNG *packet) {
// destroy the Emulator Memory. // destroy the Emulator Memory.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
em4x50_sim((uint32_t *)packet->data.asBytes, true); em4x50_sim((const uint32_t *)packet->data.asBytes, true);
break; break;
} }
case CMD_LF_EM4X50_READER: { case CMD_LF_EM4X50_READER: {
@ -1198,7 +1208,7 @@ static void PacketReceived(PacketCommandNG *packet) {
// destroy the Emulator Memory. // destroy the Emulator Memory.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
em4x50_chk((uint8_t *)packet->data.asBytes, true); em4x50_chk((const char *)packet->data.asBytes, true);
break; break;
} }
#endif #endif
@ -1278,7 +1288,7 @@ static void PacketReceived(PacketCommandNG *packet) {
uint8_t data[]; uint8_t data[];
} PACKED; } PACKED;
struct p *payload = (struct p *) packet->data.asBytes; struct p *payload = (struct p *) packet->data.asBytes;
EmlSetMemIso15693(payload->count, payload->data, payload->offset); emlSet(payload->data, payload->offset, payload->count);
break; break;
} }
case CMD_HF_ISO15693_SIMULATE: { case CMD_HF_ISO15693_SIMULATE: {
@ -1684,7 +1694,14 @@ static void PacketReceived(PacketCommandNG *packet) {
uint8_t data[]; uint8_t data[];
} PACKED; } PACKED;
struct p *payload = (struct p *) packet->data.asBytes; struct p *payload = (struct p *) packet->data.asBytes;
MifareEMemSet(payload->blockno, payload->blockcnt, payload->blockwidth, payload->data);
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// backwards compat... default bytewidth
if (payload->blockwidth == 0)
payload->blockwidth = 16;
emlSetMem_xt(payload->data, payload->blockno, payload->blockcnt, payload->blockwidth);
break; break;
} }
case CMD_HF_MIFARE_EML_MEMGET: { case CMD_HF_MIFARE_EML_MEMGET: {
@ -1923,6 +1940,10 @@ static void PacketReceived(PacketCommandNG *packet) {
iClass_Restore((iclass_restore_req_t *)packet->data.asBytes); iClass_Restore((iclass_restore_req_t *)packet->data.asBytes);
break; break;
} }
case CMD_HF_ICLASS_CREDIT_EPURSE: {
iclass_credit_epurse((iclass_credit_epurse_t *)packet->data.asBytes);
break;
}
#endif #endif
#ifdef WITH_HFSNIFF #ifdef WITH_HFSNIFF
@ -2499,6 +2520,9 @@ static void PacketReceived(PacketCommandNG *packet) {
Flash_WriteEnable(); Flash_WriteEnable();
Flash_Erase4k(3, 0xC); Flash_Erase4k(3, 0xC);
} else if (payload->startidx == DEFAULT_MF_KEYS_OFFSET) { } else if (payload->startidx == DEFAULT_MF_KEYS_OFFSET) {
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase4k(3, 0x8);
Flash_CheckBusy(BUSY_TIMEOUT); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_WriteEnable();
Flash_Erase4k(3, 0x9); Flash_Erase4k(3, 0x9);
@ -2703,6 +2727,7 @@ void __attribute__((noreturn)) AppMain(void) {
SpinDelay(100); SpinDelay(100);
BigBuf_initialize(); BigBuf_initialize();
// Add stack canary
for (uint32_t *p = _stack_start; p + 0x200 < _stack_end ; ++p) { for (uint32_t *p = _stack_start; p + 0x200 < _stack_end ; ++p) {
*p = 0xdeadbeef; *p = 0xdeadbeef;
} }

View file

@ -26,7 +26,7 @@ bool g_reply_with_crc_on_fpc = true;
bool g_reply_via_fpc = false; bool g_reply_via_fpc = false;
bool g_reply_via_usb = false; bool g_reply_via_usb = false;
int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len) { int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, const void *data, size_t len) {
PacketResponseOLD txcmd = {CMD_UNKNOWN, {0, 0, 0}, {{0}}}; PacketResponseOLD txcmd = {CMD_UNKNOWN, {0, 0, 0}, {{0}}};
// for (size_t i = 0; i < sizeof(PacketResponseOLD); i++) // for (size_t i = 0; i < sizeof(PacketResponseOLD); i++)
@ -42,7 +42,7 @@ int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *d
if (data && len) { if (data && len) {
len = MIN(len, PM3_CMD_DATA_SIZE); len = MIN(len, PM3_CMD_DATA_SIZE);
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
txcmd.d.asBytes[i] = ((uint8_t *)data)[i]; txcmd.d.asBytes[i] = ((const uint8_t *)data)[i];
} }
} }
@ -135,7 +135,7 @@ int reply_ng(uint16_t cmd, int16_t status, const uint8_t *data, size_t len) {
return reply_ng_internal(cmd, status, data, len, true); return reply_ng_internal(cmd, status, data, len, true);
} }
int reply_mix(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, const void *data, size_t len) {
int16_t status = PM3_SUCCESS; int16_t status = PM3_SUCCESS;
uint64_t arg[3] = {arg0, arg1, arg2}; uint64_t arg[3] = {arg0, arg1, arg2};
if (len > PM3_CMD_DATA_SIZE - sizeof(arg)) { if (len > PM3_CMD_DATA_SIZE - sizeof(arg)) {

View file

@ -27,9 +27,9 @@ extern bool g_reply_with_crc_on_fpc;
extern bool g_reply_via_fpc; extern bool g_reply_via_fpc;
extern bool g_reply_via_usb; extern bool g_reply_via_usb;
int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len); int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, const void *data, size_t len);
int reply_ng(uint16_t cmd, int16_t status, const uint8_t *data, size_t len); int reply_ng(uint16_t cmd, int16_t status, const 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 reply_mix(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, const void *data, size_t len);
int receive_ng(PacketCommandNG *rx); int receive_ng(PacketCommandNG *rx);
#endif // _PROXMARK_CMD_H_ #endif // _PROXMARK_CMD_H_

View file

@ -74,7 +74,7 @@ void Dbprintf(const char *fmt, ...) {
} }
// prints HEX & ASCII // prints HEX & ASCII
void Dbhexdump(int len, uint8_t *d, bool bAsci) { void Dbhexdump(int len, const uint8_t *d, bool bAsci) {
#if DEBUG #if DEBUG
char ascii[9]; char ascii[9];
@ -103,9 +103,9 @@ void Dbhexdump(int len, uint8_t *d, bool bAsci) {
#endif #endif
} }
void print_result(const char *name, uint8_t *buf, size_t len) { void print_result(const char *name, const uint8_t *buf, size_t len) {
uint8_t *p = buf; const uint8_t *p = buf;
uint16_t tmp = len & 0xFFF0; uint16_t tmp = len & 0xFFF0;
for (; p - buf < tmp; p += 16) { for (; p - buf < tmp; p += 16) {

View file

@ -22,40 +22,12 @@
#include "common.h" #include "common.h"
#include "ansi.h" #include "ansi.h"
#define Dbprintf_usb(...) {\
bool tmpfpc = g_reply_via_fpc;\
bool tmpusb = g_reply_via_usb;\
g_reply_via_fpc = false;\
g_reply_via_usb = true;\
Dbprintf(__VA_ARGS__);\
g_reply_via_fpc = tmpfpc;\
g_reply_via_usb = tmpusb;}
#define Dbprintf_fpc(...) {\
bool tmpfpc = g_reply_via_fpc;\
bool tmpusb = g_reply_via_usb;\
g_reply_via_fpc = true;\
g_reply_via_usb = false;\
Dbprintf(__VA_ARGS__);\
g_reply_via_fpc = tmpfpc;\
g_reply_via_usb = tmpusb;}
#define Dbprintf_all(...) {\
bool tmpfpc = g_reply_via_fpc;\
bool tmpusb = g_reply_via_usb;\
g_reply_via_fpc = true;\
g_reply_via_usb = true;\
Dbprintf(__VA_ARGS__);\
g_reply_via_fpc = tmpfpc;\
g_reply_via_usb = tmpusb;}
void DbpString(const char *str); void DbpString(const char *str);
void DbpStringEx(uint32_t flags, const char *src, size_t srclen); void DbpStringEx(uint32_t flags, const char *src, size_t srclen);
void Dbprintf(const char *fmt, ...); void Dbprintf(const char *fmt, ...);
void DbprintfEx(uint32_t flags, const char *fmt, ...); void DbprintfEx(uint32_t flags, const char *fmt, ...);
void Dbhexdump(int len, uint8_t *d, bool bAsci); void Dbhexdump(int len, const uint8_t *d, bool bAsci);
void print_result(const char *name, uint8_t *buf, size_t len); void print_result(const char *name, const uint8_t *buf, size_t len);
//void PrintToSendBuffer(void); //void PrintToSendBuffer(void);
#endif #endif

View file

@ -634,7 +634,7 @@ static int login(uint32_t password) {
} }
// searching for password using chosen bruteforce algorithm // searching for password using chosen bruteforce algorithm
static bool brute(em4x50_data_t *etd, uint32_t *pwd) { static bool brute(const em4x50_data_t *etd, uint32_t *pwd) {
generator_context_t ctx; generator_context_t ctx;
bool pwd_found = false; bool pwd_found = false;
@ -694,7 +694,7 @@ static bool brute(em4x50_data_t *etd, uint32_t *pwd) {
} }
// login into EM4x50 // login into EM4x50
void em4x50_login(uint32_t *password, bool ledcontrol) { void em4x50_login(const uint32_t *password, bool ledcontrol) {
em4x50_setup_read(); em4x50_setup_read();
int status = PM3_EFAILED; int status = PM3_EFAILED;
@ -713,7 +713,7 @@ void em4x50_login(uint32_t *password, bool ledcontrol) {
} }
// invoke password search // invoke password search
void em4x50_brute(em4x50_data_t *etd, bool ledcontrol) { void em4x50_brute(const em4x50_data_t *etd, bool ledcontrol) {
em4x50_setup_read(); em4x50_setup_read();
bool bsuccess = false; bool bsuccess = false;
@ -733,7 +733,7 @@ void em4x50_brute(em4x50_data_t *etd, bool ledcontrol) {
} }
// check passwords from dictionary content in flash memory // check passwords from dictionary content in flash memory
void em4x50_chk(uint8_t *filename, bool ledcontrol) { void em4x50_chk(const char *filename, bool ledcontrol) {
int status = PM3_EFAILED; int status = PM3_EFAILED;
uint32_t pwd = 0x0; uint32_t pwd = 0x0;
@ -743,11 +743,11 @@ void em4x50_chk(uint8_t *filename, bool ledcontrol) {
int changed = rdv40_spiffs_lazy_mount(); int changed = rdv40_spiffs_lazy_mount();
uint16_t pwd_count = 0; uint16_t pwd_count = 0;
uint32_t size = size_in_spiffs((char *)filename); uint32_t size = size_in_spiffs(filename);
pwd_count = size / 4; pwd_count = size / 4;
uint8_t *pwds = BigBuf_malloc(size); uint8_t *pwds = BigBuf_malloc(size);
rdv40_spiffs_read_as_filetype((char *)filename, pwds, size, RDV40_SPIFFS_SAFETY_SAFE); rdv40_spiffs_read_as_filetype(filename, pwds, size, RDV40_SPIFFS_SAFETY_SAFE);
if (changed) if (changed)
rdv40_spiffs_lazy_unmount(); rdv40_spiffs_lazy_unmount();
@ -873,7 +873,7 @@ static int selective_read(uint32_t addresses, uint32_t *words) {
} }
// reads by using "selective read mode" -> bidirectional communication // reads by using "selective read mode" -> bidirectional communication
void em4x50_read(em4x50_data_t *etd, bool ledcontrol) { void em4x50_read(const em4x50_data_t *etd, bool ledcontrol) {
int status = PM3_EFAILED; int status = PM3_EFAILED;
uint32_t words[EM4X50_NO_WORDS] = {0x0}; uint32_t words[EM4X50_NO_WORDS] = {0x0};
@ -906,7 +906,7 @@ void em4x50_read(em4x50_data_t *etd, bool ledcontrol) {
} }
// collects as much information as possible via selective read mode // collects as much information as possible via selective read mode
void em4x50_info(em4x50_data_t *etd, bool ledcontrol) { void em4x50_info(const em4x50_data_t *etd, bool ledcontrol) {
int status = PM3_EFAILED; int status = PM3_EFAILED;
uint32_t words[EM4X50_NO_WORDS] = {0x0}; uint32_t words[EM4X50_NO_WORDS] = {0x0};
@ -1053,7 +1053,7 @@ static int write_password(uint32_t password, uint32_t new_password) {
// write operation process for EM4x50 tag, // write operation process for EM4x50 tag,
// single word is written to given address, verified by selective read operation // single word is written to given address, verified by selective read operation
// wrong password -> return with PM3_EFAILED // wrong password -> return with PM3_EFAILED
void em4x50_write(em4x50_data_t *etd, bool ledcontrol) { void em4x50_write(const em4x50_data_t *etd, bool ledcontrol) {
int status = PM3_EFAILED; int status = PM3_EFAILED;
uint32_t words[EM4X50_NO_WORDS] = {0x0}; uint32_t words[EM4X50_NO_WORDS] = {0x0};
@ -1113,7 +1113,7 @@ void em4x50_write(em4x50_data_t *etd, bool ledcontrol) {
} }
// simple change of password // simple change of password
void em4x50_writepwd(em4x50_data_t *etd, bool ledcontrol) { void em4x50_writepwd(const em4x50_data_t *etd, bool ledcontrol) {
int status = PM3_EFAILED; int status = PM3_EFAILED;
em4x50_setup_read(); em4x50_setup_read();
@ -1358,7 +1358,7 @@ static bool em4x50_sim_read_word(uint32_t *word) {
} }
// check if reader requests receive mode (rm) by sending two zeros // check if reader requests receive mode (rm) by sending two zeros
static int check_rm_request(uint32_t *tag, bool ledcontrol) { static int check_rm_request(const uint32_t *tag, bool ledcontrol) {
// look for first zero // look for first zero
int bit = em4x50_sim_read_bit(); int bit = em4x50_sim_read_bit();
@ -1387,7 +1387,7 @@ static int check_rm_request(uint32_t *tag, bool ledcontrol) {
} }
// send single listen window in simulation mode // send single listen window in simulation mode
static int em4x50_sim_send_listen_window(uint32_t *tag, bool ledcontrol) { static int em4x50_sim_send_listen_window(const uint32_t *tag, bool ledcontrol) {
SHORT_COIL(); SHORT_COIL();
wait_cycles(EM4X50_T_TAG_HALF_PERIOD); wait_cycles(EM4X50_T_TAG_HALF_PERIOD);
@ -1460,7 +1460,7 @@ static void em4x50_sim_send_nak(void) {
} }
// standard read mode process (simulation mode) // standard read mode process (simulation mode)
static int em4x50_sim_handle_standard_read_command(uint32_t *tag, bool ledcontrol) { static int em4x50_sim_handle_standard_read_command(const uint32_t *tag, bool ledcontrol) {
// extract control data // extract control data
int fwr = reflect32(tag[EM4X50_CONTROL]) & 0xFF; // first word read int fwr = reflect32(tag[EM4X50_CONTROL]) & 0xFF; // first word read
@ -1500,7 +1500,7 @@ static int em4x50_sim_handle_standard_read_command(uint32_t *tag, bool ledcontro
} }
// selective read mode process (simulation mode) // selective read mode process (simulation mode)
static int em4x50_sim_handle_selective_read_command(uint32_t *tag, bool ledcontrol) { static int em4x50_sim_handle_selective_read_command(const uint32_t *tag, bool ledcontrol) {
// read password // read password
uint32_t address = 0; uint32_t address = 0;
@ -1555,7 +1555,7 @@ static int em4x50_sim_handle_selective_read_command(uint32_t *tag, bool ledcontr
} }
// login process (simulation mode) // login process (simulation mode)
static int em4x50_sim_handle_login_command(uint32_t *tag, bool ledcontrol) { static int em4x50_sim_handle_login_command(const uint32_t *tag, bool ledcontrol) {
// read password // read password
uint32_t password = 0; uint32_t password = 0;
@ -1581,7 +1581,7 @@ static int em4x50_sim_handle_login_command(uint32_t *tag, bool ledcontrol) {
} }
// reset process (simulation mode) // reset process (simulation mode)
static int em4x50_sim_handle_reset_command(uint32_t *tag, bool ledcontrol) { static int em4x50_sim_handle_reset_command(const uint32_t *tag, bool ledcontrol) {
// processing pause time (corresponds to a "1" bit) // processing pause time (corresponds to a "1" bit)
em4x50_sim_send_bit(1); em4x50_sim_send_bit(1);
@ -1806,7 +1806,7 @@ void em4x50_handle_commands(int *command, uint32_t *tag, bool ledcontrol) {
// simulate uploaded data in emulator memory // simulate uploaded data in emulator memory
// LED C -> reader command has been detected // LED C -> reader command has been detected
// LED D -> operations that require authentication are possible // LED D -> operations that require authentication are possible
void em4x50_sim(uint32_t *password, bool ledcontrol) { void em4x50_sim(const uint32_t *password, bool ledcontrol) {
int command = PM3_ENODATA; int command = PM3_ENODATA;

View file

@ -21,20 +21,21 @@
#include "../include/em4x50.h" #include "../include/em4x50.h"
// used by standalone mode
void em4x50_setup_read(void); void em4x50_setup_read(void);
int standard_read(int *now, uint32_t *words); int standard_read(int *now, uint32_t *words);
void em4x50_setup_sim(void); void em4x50_setup_sim(void);
void em4x50_handle_commands(int *command, uint32_t *tag, bool ledcontrol); void em4x50_handle_commands(int *command, uint32_t *tag, bool ledcontrol);
void em4x50_info(em4x50_data_t *etd, bool ledcontrol); // dispatch functions (appmain.c)
void em4x50_write(em4x50_data_t *etd, bool ledcontrol); void em4x50_info(const em4x50_data_t *etd, bool ledcontrol);
void em4x50_writepwd(em4x50_data_t *etd, bool ledcontrol); void em4x50_write(const em4x50_data_t *etd, bool ledcontrol);
void em4x50_read(em4x50_data_t *etd, bool ledcontrol); void em4x50_writepwd(const em4x50_data_t *etd, bool ledcontrol);
void em4x50_brute(em4x50_data_t *etd, bool ledcontrol); void em4x50_read(const em4x50_data_t *etd, bool ledcontrol);
void em4x50_login(uint32_t *password, bool ledcontrol); void em4x50_brute(const em4x50_data_t *etd, bool ledcontrol);
void em4x50_sim(uint32_t *password, bool ledcontrol); void em4x50_login(const uint32_t *password, bool ledcontrol);
void em4x50_sim(const uint32_t *password, bool ledcontrol);
void em4x50_reader(bool ledcontrol); void em4x50_reader(bool ledcontrol);
void em4x50_chk(uint8_t *filename, bool ledcontrol); void em4x50_chk(const char *filename, bool ledcontrol);
#endif /* EM4X50_H */ #endif /* EM4X50_H */

View file

@ -310,6 +310,7 @@ static bool check_ack(void) {
return false; return false;
} }
// TODO: define and use structs for rnd, frnd, response
static int authenticate(const uint8_t *rnd, const uint8_t *frnd, uint8_t *response) { static int authenticate(const uint8_t *rnd, const uint8_t *frnd, uint8_t *response) {
if (find_listen_window(true)) { if (find_listen_window(true)) {
@ -350,8 +351,10 @@ static int authenticate(const uint8_t *rnd, const uint8_t *frnd, uint8_t *respon
return PM3_ESOFT; return PM3_ESOFT;
} }
static int set_byte(uint8_t *target, int value) { // Sets one (reflected) byte and returns carry bit
int c = value > 0xFF; // (1 if `value` parameter was greater than 0xFF)
static int set_byte(uint8_t *target, uint16_t value) {
int c = value > 0xFF ? 1 : 0; // be explicit about carry bit values
*target = reflect8(value); *target = reflect8(value);
return c; return c;
} }
@ -373,8 +376,8 @@ static int bruteforce(const uint8_t address, const uint8_t *rnd, const uint8_t *
uint16_t rev_k = reflect16(k); uint16_t rev_k = reflect16(k);
switch (address) { switch (address) {
case 9: case 9:
c = set_byte(&temp_rnd[0], rev_rnd[0] + (rev_k & 0xFF)); c = set_byte(&temp_rnd[0], rev_rnd[0] + ((rev_k) & 0xFFu));
c = set_byte(&temp_rnd[1], rev_rnd[1] + c + ((rev_k >> 8) & 0xFF)); c = set_byte(&temp_rnd[1], rev_rnd[1] + c + ((rev_k >> 8) & 0xFFu));
c = set_byte(&temp_rnd[2], rev_rnd[2] + c); c = set_byte(&temp_rnd[2], rev_rnd[2] + c);
c = set_byte(&temp_rnd[3], rev_rnd[3] + c); c = set_byte(&temp_rnd[3], rev_rnd[3] + c);
c = set_byte(&temp_rnd[4], rev_rnd[4] + c); c = set_byte(&temp_rnd[4], rev_rnd[4] + c);
@ -383,16 +386,16 @@ static int bruteforce(const uint8_t address, const uint8_t *rnd, const uint8_t *
break; break;
case 8: case 8:
c = set_byte(&temp_rnd[2], rev_rnd[2] + (rev_k & 0xFF)); c = set_byte(&temp_rnd[2], rev_rnd[2] + ((rev_k) & 0xFFu));
c = set_byte(&temp_rnd[3], rev_rnd[3] + c + ((rev_k >> 8) & 0xFF)); c = set_byte(&temp_rnd[3], rev_rnd[3] + c + ((rev_k >> 8) & 0xFFu));
c = set_byte(&temp_rnd[4], rev_rnd[4] + c); c = set_byte(&temp_rnd[4], rev_rnd[4] + c);
c = set_byte(&temp_rnd[5], rev_rnd[5] + c); c = set_byte(&temp_rnd[5], rev_rnd[5] + c);
set_byte(&temp_rnd[6], rev_rnd[6] + c); set_byte(&temp_rnd[6], rev_rnd[6] + c);
break; break;
case 7: case 7:
c = set_byte(&temp_rnd[4], rev_rnd[4] + (rev_k & 0xFF)); c = set_byte(&temp_rnd[4], rev_rnd[4] + ((rev_k) & 0xFFu));
c = set_byte(&temp_rnd[5], rev_rnd[5] + c + ((rev_k >> 8) & 0xFF)); c = set_byte(&temp_rnd[5], rev_rnd[5] + c + ((rev_k >> 8) & 0xFFu));
set_byte(&temp_rnd[6], rev_rnd[6] + c); set_byte(&temp_rnd[6], rev_rnd[6] + c);
break; break;
@ -707,7 +710,7 @@ static int em4x70_receive(uint8_t *bits, size_t length) {
return bit_pos; return bit_pos;
} }
void em4x70_info(em4x70_data_t *etd, bool ledcontrol) { void em4x70_info(const em4x70_data_t *etd, bool ledcontrol) {
uint8_t status = 0; uint8_t status = 0;
@ -728,7 +731,7 @@ void em4x70_info(em4x70_data_t *etd, bool ledcontrol) {
reply_ng(CMD_LF_EM4X70_INFO, status, tag.data, sizeof(tag.data)); reply_ng(CMD_LF_EM4X70_INFO, status, tag.data, sizeof(tag.data));
} }
void em4x70_write(em4x70_data_t *etd, bool ledcontrol) { void em4x70_write(const em4x70_data_t *etd, bool ledcontrol) {
uint8_t status = 0; uint8_t status = 0;
@ -758,7 +761,7 @@ void em4x70_write(em4x70_data_t *etd, bool ledcontrol) {
reply_ng(CMD_LF_EM4X70_WRITE, status, tag.data, sizeof(tag.data)); reply_ng(CMD_LF_EM4X70_WRITE, status, tag.data, sizeof(tag.data));
} }
void em4x70_unlock(em4x70_data_t *etd, bool ledcontrol) { void em4x70_unlock(const em4x70_data_t *etd, bool ledcontrol) {
uint8_t status = 0; uint8_t status = 0;
@ -791,7 +794,7 @@ void em4x70_unlock(em4x70_data_t *etd, bool ledcontrol) {
reply_ng(CMD_LF_EM4X70_UNLOCK, status, tag.data, sizeof(tag.data)); reply_ng(CMD_LF_EM4X70_UNLOCK, status, tag.data, sizeof(tag.data));
} }
void em4x70_auth(em4x70_data_t *etd, bool ledcontrol) { void em4x70_auth(const em4x70_data_t *etd, bool ledcontrol) {
uint8_t status = 0; uint8_t status = 0;
uint8_t response[3] = {0}; uint8_t response[3] = {0};
@ -813,7 +816,7 @@ void em4x70_auth(em4x70_data_t *etd, bool ledcontrol) {
reply_ng(CMD_LF_EM4X70_AUTH, status, response, sizeof(response)); reply_ng(CMD_LF_EM4X70_AUTH, status, response, sizeof(response));
} }
void em4x70_brute(em4x70_data_t *etd, bool ledcontrol) { void em4x70_brute(const em4x70_data_t *etd, bool ledcontrol) {
uint8_t status = 0; uint8_t status = 0;
uint8_t response[2] = {0}; uint8_t response[2] = {0};
@ -834,7 +837,7 @@ void em4x70_brute(em4x70_data_t *etd, bool ledcontrol) {
reply_ng(CMD_LF_EM4X70_BRUTE, status, response, sizeof(response)); reply_ng(CMD_LF_EM4X70_BRUTE, status, response, sizeof(response));
} }
void em4x70_write_pin(em4x70_data_t *etd, bool ledcontrol) { void em4x70_write_pin(const em4x70_data_t *etd, bool ledcontrol) {
uint8_t status = 0; uint8_t status = 0;
@ -850,7 +853,7 @@ void em4x70_write_pin(em4x70_data_t *etd, bool ledcontrol) {
if (em4x70_read_id()) { if (em4x70_read_id()) {
// Write new PIN // Write new PIN
if ((write(etd->pin & 0xFFFF, EM4X70_PIN_WORD_UPPER) == PM3_SUCCESS) && if ((write((etd->pin) & 0xFFFF, EM4X70_PIN_WORD_UPPER) == PM3_SUCCESS) &&
(write((etd->pin >> 16) & 0xFFFF, EM4X70_PIN_WORD_LOWER) == PM3_SUCCESS)) { (write((etd->pin >> 16) & 0xFFFF, EM4X70_PIN_WORD_LOWER) == PM3_SUCCESS)) {
// Now Try to authenticate using the new PIN // Now Try to authenticate using the new PIN
@ -874,7 +877,7 @@ void em4x70_write_pin(em4x70_data_t *etd, bool ledcontrol) {
reply_ng(CMD_LF_EM4X70_WRITEPIN, status, tag.data, sizeof(tag.data)); reply_ng(CMD_LF_EM4X70_WRITEPIN, status, tag.data, sizeof(tag.data));
} }
void em4x70_write_key(em4x70_data_t *etd, bool ledcontrol) { void em4x70_write_key(const em4x70_data_t *etd, bool ledcontrol) {
uint8_t status = 0; uint8_t status = 0;

View file

@ -30,12 +30,12 @@ typedef enum {
FALLING_EDGE FALLING_EDGE
} edge_detection_t; } edge_detection_t;
void em4x70_info(em4x70_data_t *etd, bool ledcontrol); void em4x70_info(const em4x70_data_t *etd, bool ledcontrol);
void em4x70_write(em4x70_data_t *etd, bool ledcontrol); void em4x70_write(const em4x70_data_t *etd, bool ledcontrol);
void em4x70_brute(em4x70_data_t *etd, bool ledcontrol); void em4x70_brute(const em4x70_data_t *etd, bool ledcontrol);
void em4x70_unlock(em4x70_data_t *etd, bool ledcontrol); void em4x70_unlock(const em4x70_data_t *etd, bool ledcontrol);
void em4x70_auth(em4x70_data_t *etd, bool ledcontrol); void em4x70_auth(const em4x70_data_t *etd, bool ledcontrol);
void em4x70_write_pin(em4x70_data_t *etd, bool ledcontrol); void em4x70_write_pin(const em4x70_data_t *etd, bool ledcontrol);
void em4x70_write_key(em4x70_data_t *etd, bool ledcontrol); void em4x70_write_key(const em4x70_data_t *etd, bool ledcontrol);
#endif /* EM4x70_H */ #endif /* EM4x70_H */

View file

@ -37,6 +37,24 @@
static const uint8_t pps[] = {0xD0, 0x11, 0x00, 0x52, 0xA6}; static const uint8_t pps[] = {0xD0, 0x11, 0x00, 0x52, 0xA6};
#endif #endif
// this struct is used by EPA_Parse_CardAccess and contains info about the
// PACE protocol supported by the chip
typedef struct {
uint8_t oid[10];
uint8_t version;
uint8_t parameter_id;
} pace_version_info_t;
// general functions
static void EPA_Finish(void);
static size_t EPA_Parse_CardAccess(const uint8_t *data, size_t length, pace_version_info_t *pace_info);
static int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length);
static int EPA_Setup(void);
// PACE related functions
static int EPA_PACE_MSE_Set_AT(const pace_version_info_t pace_version_info, uint8_t password);
static int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce);
// APDUs for communication with German Identification Card // APDUs for communication with German Identification Card
// General Authenticate (request encrypted nonce) WITHOUT the Le at the end // General Authenticate (request encrypted nonce) WITHOUT the Le at the end
@ -153,7 +171,7 @@ static int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response, uint16_t re
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Closes the communication channel and turns off the field // Closes the communication channel and turns off the field
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void EPA_Finish(void) { static void EPA_Finish(void) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();
iso_type = 0; iso_type = 0;
@ -172,7 +190,7 @@ void EPA_Finish(void) {
// TODO: Support elements with long tags (tag is longer than 1 byte) // TODO: Support elements with long tags (tag is longer than 1 byte)
// TODO: Support proprietary PACE domain parameters // TODO: Support proprietary PACE domain parameters
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
size_t EPA_Parse_CardAccess(uint8_t *data, size_t length, pace_version_info_t *pace_info) { static size_t EPA_Parse_CardAccess(const uint8_t *data, size_t length, pace_version_info_t *pace_info) {
size_t index = 0; size_t index = 0;
@ -243,7 +261,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data, size_t length, pace_version_info_t *p
// Returns -1 on failure or the length of the data on success // Returns -1 on failure or the length of the data on success
// TODO: for the moment this sends only 1 APDU regardless of the requested length // TODO: for the moment this sends only 1 APDU regardless of the requested length
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length) { static int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length) {
// the response APDU of the card // the response APDU of the card
// since the card doesn't always care for the expected length we send it, // since the card doesn't always care for the expected length we send it,
// we reserve 262 bytes here just to be safe (256-byte APDU + SW + ISO frame) // we reserve 262 bytes here just to be safe (256-byte APDU + SW + ISO frame)
@ -300,7 +318,7 @@ static void EPA_PACE_Collect_Nonce_Abort(uint32_t cmd, uint8_t step, int func_re
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Acquire one encrypted PACE nonce // Acquire one encrypted PACE nonce
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void EPA_PACE_Collect_Nonce(PacketCommandNG *c) { void EPA_PACE_Collect_Nonce(const PacketCommandNG *c) {
/* /*
* ack layout: * ack layout:
* arg: * arg:
@ -354,7 +372,7 @@ void EPA_PACE_Collect_Nonce(PacketCommandNG *c) {
struct p { struct p {
uint32_t m; uint32_t m;
} PACKED; } PACKED;
struct p *packet = (struct p *)c->data.asBytes; const struct p *packet = (const struct p *)c->data.asBytes;
func_return = EPA_PACE_Get_Nonce(packet->m, nonce); func_return = EPA_PACE_Get_Nonce(packet->m, nonce);
// check if the command succeeded // check if the command succeeded
@ -377,7 +395,7 @@ void EPA_PACE_Collect_Nonce(PacketCommandNG *c) {
// Returns the actual size of the nonce on success or a less-than-zero error // Returns the actual size of the nonce on success or a less-than-zero error
// code on failure. // code on failure.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce) { static int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce) {
// build the APDU // build the APDU
uint8_t apdu[sizeof(apdu_general_authenticate_pace_get_nonce) + 1]; uint8_t apdu[sizeof(apdu_general_authenticate_pace_get_nonce) + 1];
@ -416,7 +434,7 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce) {
// Initializes the PACE protocol by performing the "MSE: Set AT" step // Initializes the PACE protocol by performing the "MSE: Set AT" step
// Returns 0 on success or a non-zero error code on failure // Returns 0 on success or a non-zero error code on failure
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password) { static int EPA_PACE_MSE_Set_AT(const pace_version_info_t pace_version_info, uint8_t password) {
// create the MSE: Set AT APDU // create the MSE: Set AT APDU
uint8_t apdu[23]; uint8_t apdu[23];
@ -479,7 +497,7 @@ int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Perform the PACE protocol by replaying given APDUs // Perform the PACE protocol by replaying given APDUs
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void EPA_PACE_Replay(PacketCommandNG *c) { void EPA_PACE_Replay(const PacketCommandNG *c) {
uint32_t timings[ARRAYLEN(apdu_lengths_replay)] = {0}; uint32_t timings[ARRAYLEN(apdu_lengths_replay)] = {0};
@ -547,7 +565,7 @@ void EPA_PACE_Replay(PacketCommandNG *c) {
// Set up a communication channel (Card Select, PPS) // Set up a communication channel (Card Select, PPS)
// Returns 0 on success or a non-zero error code on failure // Returns 0 on success or a non-zero error code on failure
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int EPA_Setup(void) { static int EPA_Setup(void) {
#ifdef WITH_ISO14443a #ifdef WITH_ISO14443a
{ {
@ -593,7 +611,7 @@ int EPA_Setup(void) {
return 1; return 1;
} }
void EPA_PACE_Simulate(PacketCommandNG *c) { void EPA_PACE_Simulate(const PacketCommandNG *c) {
//---------Initializing--------- //---------Initializing---------

View file

@ -22,26 +22,8 @@
#include "common.h" #include "common.h"
#include "pm3_cmd.h" #include "pm3_cmd.h"
// this struct is used by EPA_Parse_CardAccess and contains info about the void EPA_PACE_Collect_Nonce(const PacketCommandNG *c);
// PACE protocol supported by the chip void EPA_PACE_Replay(const PacketCommandNG *c);
typedef struct { void EPA_PACE_Simulate(const PacketCommandNG *c);
uint8_t oid[10];
uint8_t version;
uint8_t parameter_id;
} pace_version_info_t;
// general functions
void EPA_Finish(void);
size_t EPA_Parse_CardAccess(uint8_t *data, size_t length, pace_version_info_t *pace_info);
int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length);
int EPA_Setup(void);
// PACE related functions
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);
void EPA_PACE_Simulate(PacketCommandNG *c);
#endif /* __EPA_H */ #endif /* __EPA_H */

View file

@ -49,7 +49,7 @@ static uint32_t felica_lasttime_prox2air_start;
static void iso18092_setup(uint8_t fpga_minor_mode); static void iso18092_setup(uint8_t fpga_minor_mode);
static uint8_t felica_select_card(felica_card_select_t *card); static uint8_t felica_select_card(felica_card_select_t *card);
static void TransmitFor18092_AsReader(uint8_t *frame, uint16_t len, uint32_t *timing, uint8_t power, uint8_t highspeed); static void TransmitFor18092_AsReader(const uint8_t *frame, uint16_t len, const uint32_t *NYI_timing_NYI, uint8_t power, uint8_t highspeed);
static bool WaitForFelicaReply(uint16_t maxbytes); static bool WaitForFelicaReply(uint16_t maxbytes);
static void iso18092_set_timeout(uint32_t timeout) { static void iso18092_set_timeout(uint32_t timeout) {
@ -350,7 +350,12 @@ static void BuildFliteRdblk(const uint8_t *idm, uint8_t blocknum, const uint16_t
AddCrc(frameSpace + 2, c - 2); AddCrc(frameSpace + 2, c - 2);
} }
static void TransmitFor18092_AsReader(uint8_t *frame, uint16_t len, uint32_t *timing, uint8_t power, uint8_t highspeed) { static void TransmitFor18092_AsReader(const uint8_t *frame, uint16_t len, const uint32_t *NYI_timing_NYI, uint8_t power, uint8_t highspeed) {
if (NYI_timing_NYI != NULL) {
Dbprintf("Error: TransmitFor18092_AsReader does not check or set parameter NYI_timing_NYI");
return;
}
uint16_t flags = FPGA_MAJOR_MODE_HF_ISO18092; uint16_t flags = FPGA_MAJOR_MODE_HF_ISO18092;
if (power) if (power)
flags |= FPGA_HF_ISO18092_FLAG_READER; flags |= FPGA_HF_ISO18092_FLAG_READER;
@ -512,12 +517,12 @@ static void felica_reset_frame_mode(void) {
// arg0 FeliCa flags // arg0 FeliCa flags
// arg1 len of commandbytes // arg1 len of commandbytes
// d.asBytes command bytes to send // d.asBytes command bytes to send
void felica_sendraw(PacketCommandNG *c) { void felica_sendraw(const PacketCommandNG *c) {
if (g_dbglevel >= DBG_DEBUG) Dbprintf("FeliCa_sendraw Enter"); if (g_dbglevel >= DBG_DEBUG) Dbprintf("FeliCa_sendraw Enter");
felica_command_t param = c->oldarg[0]; felica_command_t param = c->oldarg[0];
size_t len = c->oldarg[1] & 0xffff; size_t len = c->oldarg[1] & 0xffff;
uint8_t *cmd = c->data.asBytes; const uint8_t *cmd = c->data.asBytes;
uint32_t arg0; uint32_t arg0;
felica_card_select_t card; felica_card_select_t card;
@ -675,7 +680,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
#define R_READBLK_LEN 0x21 #define R_READBLK_LEN 0x21
//simulate NFC Tag3 card - for now only poll response works //simulate NFC Tag3 card - for now only poll response works
// second half (4 bytes) of NDEF2 goes into nfcid2_0, first into nfcid2_1 // second half (4 bytes) of NDEF2 goes into nfcid2_0, first into nfcid2_1
void felica_sim_lite(uint8_t *uid) { void felica_sim_lite(const uint8_t *uid) {
// prepare our 3 responses... // prepare our 3 responses...
uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2, 0x4d, 0x12, FELICA_POLL_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7f}; uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2, 0x4d, 0x12, FELICA_POLL_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7f};

View file

@ -21,9 +21,9 @@
#include "common.h" #include "common.h"
#include "cmd.h" #include "cmd.h"
void felica_sendraw(PacketCommandNG *c); void felica_sendraw(const PacketCommandNG *c);
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip); void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip);
void felica_sim_lite(uint8_t *uid); void felica_sim_lite(const uint8_t *uid);
void felica_dump_lite_s(void); void felica_dump_lite_s(void);
#endif #endif

View file

@ -162,8 +162,7 @@ void FpgaSetupSsc(uint16_t fpga_mode) {
// 8, 16 or 32 bits per transfer, no loopback, MSB first, 1 transfer per sync // 8, 16 or 32 bits per transfer, no loopback, MSB first, 1 transfer per sync
// pulse, no output sync // pulse, no output sync
if (((fpga_mode & FPGA_MAJOR_MODE_MASK) == FPGA_MAJOR_MODE_HF_READER || if (((fpga_mode & FPGA_MAJOR_MODE_MASK) == FPGA_MAJOR_MODE_HF_READER) &&
(fpga_mode & FPGA_MAJOR_MODE_MASK) == FPGA_MAJOR_MODE_HF_FSK_READER) &&
(FpgaGetCurrent() == FPGA_BITSTREAM_HF || FpgaGetCurrent() == FPGA_BITSTREAM_HF_15)) { (FpgaGetCurrent() == FPGA_BITSTREAM_HF || FpgaGetCurrent() == FPGA_BITSTREAM_HF_15)) {
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
} else { } else {

View file

@ -1,5 +1,4 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) Jonathan Westhues, April 2006
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
@ -32,76 +31,116 @@
#define FPGA_BITSTREAM_HF_15 4 #define FPGA_BITSTREAM_HF_15 4
/* /*
Communication between ARM / FPGA is done inside armsrc/fpgaloader.c (function FpgaSendCommand) Communication between ARM / FPGA is done inside armsrc/fpgaloader.c see: function FpgaSendCommand()
Send 16 bit command / data pair to FPGA Send 16 bit command / data pair to FPGA with the bit format:
The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
where +------ frame layout circa 2020 ------------------+
C is 4bit command | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 |
D is 12bit data +-------------------------------------------------+
| C C C C M M M M P P P P P P P P | C = FPGA_CMD_SET_CONFREG, M = FPGA_MAJOR_MODE_*, P = FPGA_LF_* or FPGA_HF_* parameter
| C C C C D D D D D D D D | C = FPGA_CMD_SET_DIVISOR, D = divisor
| C C C C T T T T T T T T | C = FPGA_CMD_SET_EDGE_DETECT_THRESHOLD, T = threshold
| C C C C E | C = FPGA_CMD_TRACE_ENABLE, E=0 off, E=1 on
+-------------------------------------------------+
+------ frame layout current ---------------------+
| 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 |
+-------------------------------------------------+
| C C C C M M M P P P P P P | C = FPGA_CMD_SET_CONFREG, M = FPGA_MAJOR_MODE_*, P = FPGA_LF_* or FPGA_HF_* parameter
| C C C C D D D D D D D D | C = FPGA_CMD_SET_DIVISOR, D = divisor
| C C C C T T T T T T T T | C = FPGA_CMD_SET_EDGE_DETECT_THRESHOLD, T = threshold
| C C C C E | C = FPGA_CMD_TRACE_ENABLE, E=0 off, E=1 on
+-------------------------------------------------+
shift_reg receive this 16bit frame
LF command
----------
shift_reg[15:12] == 4bit command
LF has three commands (FPGA_CMD_SET_CONFREG, FPGA_CMD_SET_DIVISOR, FPGA_CMD_SET_EDGE_DETECT_THRESHOLD)
Current commands uses only 2bits. We have room for up to 4bits of commands total (7).
LF data
-------
shift_reg[11:0] == 12bit data
lf data is divided into MAJOR MODES and configuration values.
The major modes uses 3bits (0,1,2,3,7 | 000, 001, 010, 011, 111)
000 FPGA_MAJOR_MODE_LF_READER = Act as LF reader (modulate)
001 FPGA_MAJOR_MODE_LF_EDGE_DETECT = Simulate LF
010 FPGA_MAJOR_MODE_LF_PASSTHRU = Passthrough mode, CROSS_LO line connected to SSP_DIN. SSP_DOUT logic level controls if we modulate / listening
011 FPGA_MAJOR_MODE_LF_ADC = refactor hitag2, clear ADC sampling
111 FPGA_MAJOR_MODE_OFF = turn off sampling.
Each one of this major modes can have options. Currently these two major modes uses options.
- FPGA_MAJOR_MODE_LF_READER
- FPGA_MAJOR_MODE_LF_EDGE_DETECT
FPGA_MAJOR_MODE_LF_READER
-------------------------------------
lf_field = 1bit (FPGA_LF_ADC_READER_FIELD)
You can send FPGA_CMD_SET_DIVISOR to set with FREQUENCY the fpga should sample at
divisor = 8bits shift_reg[7:0]
FPGA_MAJOR_MODE_LF_EDGE_DETECT
------------------------------------------
lf_ed_toggle_mode = 1bits
lf_ed_threshold = 8bits threshold defaults to 127
You can send FPGA_CMD_SET_EDGE_DETECT_THRESHOLD to set a custom threshold
lf_ed_threshold = 8bits threshold value.
conf_word 12bits
conf_word[7:5] = 3bit major mode.
conf_word[0] = 1bit lf_field
conf_word[1] = 1bit lf_ed_toggle_mode
conf_word[7:0] = 8bit divisor
conf_word[7:0] = 8bit threshold
-----+--------- frame layout --------------------
bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
-----+-------------------------------------------
cmd | x x x x
major| x x x
opt | x x
divi | x x x x x x x x
thres| x x x x x x x x
-----+-------------------------------------------
*/ */
// Defining commands, modes and options. This must be aligned to the definitions in fpga/define.v
// Definitions for the FPGA commands.
// BOTH HF / LF
#define FPGA_CMD_SET_CONFREG (1<<12) // C
// LF
#define FPGA_CMD_SET_DIVISOR (2<<12) // C
#define FPGA_CMD_SET_USER_BYTE1 (3<<12) // C
// HF
#define FPGA_CMD_TRACE_ENABLE (2<<12) // C
// Definitions for the FPGA configuration word.
#define FPGA_MAJOR_MODE_MASK 0x01C0 #define FPGA_MAJOR_MODE_MASK 0x01C0
#define FPGA_MINOR_MODE_MASK 0x003F #define FPGA_MINOR_MODE_MASK 0x003F
// LF // Definitions for the FPGA commands.
#define FPGA_CMD_SET_CONFREG (1<<12)
#define FPGA_CMD_SET_DIVISOR (2<<12)
#define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD (3<<12)
#define FPGA_CMD_TRACE_ENABLE (2<<12)
// Major modes
#define FPGA_MAJOR_MODE_LF_READER (0<<6) #define FPGA_MAJOR_MODE_LF_READER (0<<6)
#define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<6) #define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<6)
#define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<6) #define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<6)
#define FPGA_MAJOR_MODE_LF_ADC (3<<6) #define FPGA_MAJOR_MODE_LF_ADC (3<<6)
// HF #define FPGA_MAJOR_MODE_HF_READER (0<<6)
#define FPGA_MAJOR_MODE_HF_READER (0<<6) // D #define FPGA_MAJOR_MODE_HF_SIMULATOR (1<<6)
#define FPGA_MAJOR_MODE_HF_SIMULATOR (1<<6) // D #define FPGA_MAJOR_MODE_HF_ISO14443A (2<<6)
#define FPGA_MAJOR_MODE_HF_ISO14443A (2<<6) // D #define FPGA_MAJOR_MODE_HF_SNIFF (3<<6)
#define FPGA_MAJOR_MODE_HF_SNIFF (3<<6) // D #define FPGA_MAJOR_MODE_HF_ISO18092 (4<<6)
#define FPGA_MAJOR_MODE_HF_ISO18092 (4<<6) // D #define FPGA_MAJOR_MODE_HF_GET_TRACE (5<<6)
#define FPGA_MAJOR_MODE_HF_GET_TRACE (5<<6) // D #define FPGA_MAJOR_MODE_OFF (7<<6)
#define FPGA_MAJOR_MODE_HF_FSK_READER (6<<6) // D
// BOTH HF / LF
#define FPGA_MAJOR_MODE_OFF (7<<6) // D
// Options for LF_READER // Options for LF_READER
#define FPGA_LF_ADC_READER_FIELD 0x1 #define FPGA_LF_ADC_READER_FIELD ( 1 )
// Options for LF_EDGE_DETECT // Options for LF_EDGE_DETECT
#define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1 #define FPGA_LF_EDGE_DETECT_READER_FIELD ( 1 )
#define FPGA_LF_EDGE_DETECT_READER_FIELD 0x1 #define FPGA_LF_EDGE_DETECT_TOGGLE_MODE ( 2 )
#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE 0x2
// Options for the HF reader // Options for the generic HF reader
#define FPGA_HF_READER_MODE_RECEIVE_IQ (0<<0) #define FPGA_HF_READER_MODE_RECEIVE_IQ ( 0 )
#define FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE (1<<0) #define FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE ( 1 )
#define FPGA_HF_READER_MODE_RECEIVE_PHASE (2<<0) #define FPGA_HF_READER_MODE_RECEIVE_PHASE ( 2 )
#define FPGA_HF_READER_MODE_SEND_FULL_MOD (3<<0) #define FPGA_HF_READER_MODE_SEND_FULL_MOD ( 3 )
#define FPGA_HF_READER_MODE_SEND_SHALLOW_MOD (4<<0) #define FPGA_HF_READER_MODE_SEND_SHALLOW_MOD ( 4 )
#define FPGA_HF_READER_MODE_SNIFF_IQ (5<<0) #define FPGA_HF_READER_MODE_SNIFF_IQ ( 5 )
#define FPGA_HF_READER_MODE_SNIFF_AMPLITUDE (6<<0) #define FPGA_HF_READER_MODE_SNIFF_AMPLITUDE ( 6 )
#define FPGA_HF_READER_MODE_SNIFF_PHASE (7<<0) #define FPGA_HF_READER_MODE_SNIFF_PHASE ( 7 )
#define FPGA_HF_READER_MODE_SEND_JAM (8<<0) #define FPGA_HF_READER_MODE_SEND_JAM ( 8 )
#define FPGA_HF_READER_MODE_SEND_SHALLOW_MOD_RDV4 ( 9 )
#define FPGA_HF_READER_SUBCARRIER_848_KHZ (0<<4) #define FPGA_HF_READER_SUBCARRIER_848_KHZ (0<<4)
#define FPGA_HF_READER_SUBCARRIER_424_KHZ (1<<4) #define FPGA_HF_READER_SUBCARRIER_424_KHZ (1<<4)
@ -109,24 +148,23 @@ thres| x x x x x x x x
#define FPGA_HF_READER_2SUBCARRIERS_424_484_KHZ (3<<4) #define FPGA_HF_READER_2SUBCARRIERS_424_484_KHZ (3<<4)
// Options for the HF simulated tag, how to modulate // Options for the HF simulated tag, how to modulate
#define FPGA_HF_SIMULATOR_NO_MODULATION 0x0 // 0000 #define FPGA_HF_SIMULATOR_NO_MODULATION ( 0 )
#define FPGA_HF_SIMULATOR_MODULATE_BPSK 0x1 // 0001 #define FPGA_HF_SIMULATOR_MODULATE_BPSK ( 1 )
#define FPGA_HF_SIMULATOR_MODULATE_212K 0x2 // 0010 #define FPGA_HF_SIMULATOR_MODULATE_212K ( 2 )
#define FPGA_HF_SIMULATOR_MODULATE_424K 0x4 // 0100 #define FPGA_HF_SIMULATOR_MODULATE_424K ( 4 )
#define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5 // 0101 #define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT ( 5 )
// no 848K
// Options for ISO14443A // Options for ISO14443A
#define FPGA_HF_ISO14443A_SNIFFER 0x0 #define FPGA_HF_ISO14443A_SNIFFER ( 0 )
#define FPGA_HF_ISO14443A_TAGSIM_LISTEN 0x1 #define FPGA_HF_ISO14443A_TAGSIM_LISTEN ( 1 )
#define FPGA_HF_ISO14443A_TAGSIM_MOD 0x2 #define FPGA_HF_ISO14443A_TAGSIM_MOD ( 2 )
#define FPGA_HF_ISO14443A_READER_LISTEN 0x3 #define FPGA_HF_ISO14443A_READER_LISTEN ( 3 )
#define FPGA_HF_ISO14443A_READER_MOD 0x4 #define FPGA_HF_ISO14443A_READER_MOD ( 4 )
//options for Felica. // Options for ISO18092 / Felica
#define FPGA_HF_ISO18092_FLAG_NOMOD 0x1 // 0001 disable modulation module #define FPGA_HF_ISO18092_FLAG_NOMOD ( 1 ) // 0001 disable modulation module
#define FPGA_HF_ISO18092_FLAG_424K 0x2 // 0010 should enable 414k mode (untested). No autodetect #define FPGA_HF_ISO18092_FLAG_424K ( 2 ) // 0010 should enable 414k mode (untested). No autodetect
#define FPGA_HF_ISO18092_FLAG_READER 0x4 // 0100 enables antenna power, to act as a reader instead of tag #define FPGA_HF_ISO18092_FLAG_READER ( 4 ) // 0100 enables antenna power, to act as a reader instead of tag
void FpgaSendCommand(uint16_t cmd, uint16_t v); void FpgaSendCommand(uint16_t cmd, uint16_t v);
void FpgaWriteConfWord(uint16_t v); void FpgaWriteConfWord(uint16_t v);

View file

@ -200,7 +200,7 @@ static uint32_t HfEncodeTkm(const uint8_t *uid, uint8_t modulation, uint8_t *dat
return len; return len;
} }
int HfSimulateTkm(uint8_t *uid, uint8_t modulation, uint32_t timeout) { int HfSimulateTkm(const uint8_t *uid, uint8_t modulation, uint32_t timeout) {
// free eventually allocated BigBuf memory // free eventually allocated BigBuf memory
BigBuf_free_keep_EM(); BigBuf_free_keep_EM();

View file

@ -22,6 +22,6 @@
#include "common.h" #include "common.h"
int HfReadADC(uint32_t samplesCount, bool ledcontrol); int HfReadADC(uint32_t samplesCount, bool ledcontrol);
int HfSimulateTkm(uint8_t *uid, uint8_t modulation, uint32_t timeout); int HfSimulateTkm(const uint8_t *uid, uint8_t modulation, uint32_t timeout);
#endif #endif

View file

@ -281,7 +281,7 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_
} }
break; break;
// Received RWD authentication challenge and respnse // Received RWD authentication challenge and response
case 64: { case 64: {
// Store the authentication attempt // Store the authentication attempt
if (auth_table_len < (AUTH_TABLE_LENGTH - 8)) { if (auth_table_len < (AUTH_TABLE_LENGTH - 8)) {
@ -891,7 +891,7 @@ static bool hitag2_test_auth_attempts(uint8_t *rx, const size_t rxlen, uint8_t *
if (bCrypto) { if (bCrypto) {
Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed, removed entry!", NrAr[0], NrAr[1], NrAr[2], NrAr[3], NrAr[4], NrAr[5], NrAr[6], NrAr[7]); Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed, removed entry!", NrAr[0], NrAr[1], NrAr[2], NrAr[3], NrAr[4], NrAr[5], NrAr[6], NrAr[7]);
// Removing failed entry from authentiations table // Removing failed entry from authentications table
memcpy(auth_table + auth_table_pos, auth_table + auth_table_pos + 8, 8); memcpy(auth_table + auth_table_pos, auth_table + auth_table_pos + 8, 8);
auth_table_len -= 8; auth_table_len -= 8;
@ -979,7 +979,7 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t
return true; return true;
} }
void EloadHitag(uint8_t *data, uint16_t len) { void EloadHitag(const uint8_t *data, uint16_t len) {
memcpy(tag.sectors, data, sizeof(tag.sectors)); memcpy(tag.sectors, data, sizeof(tag.sectors));
} }
@ -1532,7 +1532,7 @@ void SimulateHitag2(bool ledcontrol) {
// reply_ng(CMD_LF_HITAG_SIMULATE, (checked == -1) ? PM3_EOPABORTED : PM3_SUCCESS, (uint8_t *)tag.sectors, tag_size); // reply_ng(CMD_LF_HITAG_SIMULATE, (checked == -1) ? PM3_EOPABORTED : PM3_SUCCESS, (uint8_t *)tag.sectors, tag_size);
} }
void ReaderHitag(hitag_function htf, hitag_data *htd, bool ledcontrol) { void ReaderHitag(hitag_function htf, const hitag_data *htd, bool ledcontrol) {
uint32_t command_start = 0, command_duration = 0; uint32_t command_start = 0, command_duration = 0;
uint32_t response_start = 0, response_duration = 0; uint32_t response_start = 0, response_duration = 0;
@ -1928,7 +1928,7 @@ out:
reply_mix(CMD_ACK, bSuccessful, 0, 0, 0, 0); reply_mix(CMD_ACK, bSuccessful, 0, 0, 0, 0);
} }
void WriterHitag(hitag_function htf, hitag_data *htd, int page, bool ledcontrol) { void WriterHitag(hitag_function htf, const hitag_data *htd, int page, bool ledcontrol) {
uint32_t command_start = 0; uint32_t command_start = 0;
uint32_t command_duration = 0; uint32_t command_duration = 0;

View file

@ -24,7 +24,7 @@
void SniffHitag2(bool ledcontrol); void SniffHitag2(bool ledcontrol);
void SimulateHitag2(bool ledcontrol); void SimulateHitag2(bool ledcontrol);
void ReaderHitag(hitag_function htf, hitag_data *htd, bool ledcontrol); void ReaderHitag(hitag_function htf, const hitag_data *htd, bool ledcontrol);
void WriterHitag(hitag_function htf, hitag_data *htd, int page, bool ledcontrol); void WriterHitag(hitag_function htf, const hitag_data *htd, int page, bool ledcontrol);
void EloadHitag(uint8_t *data, uint16_t len); void EloadHitag(const uint8_t *data, uint16_t len);
#endif #endif

View file

@ -635,7 +635,7 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
/* /*
* Emulates a Hitag S Tag with the given data from the .hts file * Emulates a Hitag S Tag with the given data from the .hts file
*/ */
void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data, bool ledcontrol) { void SimulateHitagSTag(bool tag_mem_supplied, const uint8_t *data, bool ledcontrol) {
StopTicks(); StopTicks();
@ -1052,7 +1052,7 @@ static size_t concatbits(uint8_t *dstbuf, size_t dstbufskip, const uint8_t *srcb
return dstbufskip + srcbuflen; return dstbufskip + srcbuflen;
} }
static int selectHitagS(hitag_function htf, hitag_data *htd, uint8_t *tx, size_t sizeoftx, uint8_t *rx, size_t sizeofrx, int t_wait, bool ledcontrol) { static int selectHitagS(hitag_function htf, const hitag_data *htd, uint8_t *tx, size_t sizeoftx, uint8_t *rx, size_t sizeofrx, int t_wait, bool ledcontrol) {
StopTicks(); StopTicks();
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
@ -1263,7 +1263,7 @@ static int selectHitagS(hitag_function htf, hitag_data *htd, uint8_t *tx, size_t
* If the key was given the password will be decrypted. * If the key was given the password will be decrypted.
* Reads every page of a hitag S transpoder. * Reads every page of a hitag S transpoder.
*/ */
void ReadHitagS(hitag_function htf, hitag_data *htd, bool ledcontrol) { void ReadHitagS(hitag_function htf, const hitag_data *htd, bool ledcontrol) {
uint8_t rx[HITAG_FRAME_LEN]; uint8_t rx[HITAG_FRAME_LEN];
size_t rxlen = 0; size_t rxlen = 0;
@ -1356,7 +1356,7 @@ void ReadHitagS(hitag_function htf, hitag_data *htd, bool ledcontrol) {
* Authenticates to the Tag with the given Key or Challenge. * Authenticates to the Tag with the given Key or Challenge.
* Writes the given 32Bit data into page_ * Writes the given 32Bit data into page_
*/ */
void WritePageHitagS(hitag_function htf, hitag_data *htd, int page, bool ledcontrol) { void WritePageHitagS(hitag_function htf, const hitag_data *htd, int page, bool ledcontrol) {
bool bSuccessful = false; bool bSuccessful = false;
//check for valid input //check for valid input
@ -1443,7 +1443,7 @@ write_end:
* is not received correctly due to Antenna problems. This function * is not received correctly due to Antenna problems. This function
* detects these challenges. * detects these challenges.
*/ */
void Hitag_check_challenges(uint8_t *data, uint32_t datalen, bool ledcontrol) { void Hitag_check_challenges(const uint8_t *data, uint32_t datalen, bool ledcontrol) {
//check for valid input //check for valid input
if (datalen < 8) { if (datalen < 8) {
Dbprintf("Error, need chals"); Dbprintf("Error, need chals");

View file

@ -25,8 +25,8 @@
#include "hitag.h" #include "hitag.h"
void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data, bool ledcontrol); void SimulateHitagSTag(bool tag_mem_supplied, const uint8_t *data, bool ledcontrol);
void ReadHitagS(hitag_function htf, hitag_data *htd, bool ledcontrol); void ReadHitagS(hitag_function htf, const hitag_data *htd, bool ledcontrol);
void WritePageHitagS(hitag_function htf, hitag_data *htd, int page, bool ledcontrol); void WritePageHitagS(hitag_function htf, const hitag_data *htd, int page, bool ledcontrol);
void Hitag_check_challenges(uint8_t *data, uint32_t datalen, bool ledcontrol); void Hitag_check_challenges(const uint8_t *data, uint32_t datalen, bool ledcontrol);
#endif #endif

View file

@ -407,7 +407,7 @@ bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address) {
//Sends array of data (Array, length, command to be written , SlaveDevice address ). //Sends array of data (Array, length, command to be written , SlaveDevice address ).
// len = uint16 because we need to write up to 256 bytes // len = uint16 because we need to write up to 256 bytes
bool I2C_BufferWrite(uint8_t *data, uint16_t len, uint8_t device_cmd, uint8_t device_address) { bool I2C_BufferWrite(const uint8_t *data, uint16_t len, uint8_t device_cmd, uint8_t device_address) {
bool bBreak = true; bool bBreak = true;
do { do {
if (!I2C_Start()) if (!I2C_Start())
@ -602,7 +602,7 @@ int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t
return readcount; return readcount;
} }
bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) { bool I2C_WriteFW(const uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) {
//START, 0xB0, 0x00, 0x00, xx, yy, zz, ......, STOP //START, 0xB0, 0x00, 0x00, xx, yy, zz, ......, STOP
bool bBreak = true; bool bBreak = true;
@ -772,7 +772,7 @@ void SmartCardAtr(void) {
// StopTicks(); // StopTicks();
} }
void SmartCardRaw(smart_card_raw_t *p) { void SmartCardRaw(const smart_card_raw_t *p) {
LED_D_ON(); LED_D_ON();
uint16_t len = 0; uint16_t len = 0;

View file

@ -41,12 +41,12 @@ void I2C_Reset_EnterBootloader(void);
bool I2C_WriteCmd(uint8_t device_cmd, uint8_t device_address); bool I2C_WriteCmd(uint8_t device_cmd, uint8_t device_address);
bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address); bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address);
bool I2C_BufferWrite(uint8_t *data, uint16_t len, uint8_t device_cmd, uint8_t device_address); bool I2C_BufferWrite(const uint8_t *data, uint16_t len, uint8_t device_cmd, uint8_t device_address);
int16_t I2C_BufferRead(uint8_t *data, uint16_t len, uint8_t device_cmd, uint8_t device_address); int16_t I2C_BufferRead(uint8_t *data, uint16_t len, uint8_t device_cmd, uint8_t device_address);
// for firmware // for firmware
int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address); int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address);
bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address); bool I2C_WriteFW(const uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address);
bool sc_rx_bytes(uint8_t *dest, uint16_t *destlen); bool sc_rx_bytes(uint8_t *dest, uint16_t *destlen);
// //
@ -54,7 +54,7 @@ bool GetATR(smart_card_atr_t *card_ptr, bool verbose);
// generice functions // generice functions
void SmartCardAtr(void); void SmartCardAtr(void);
void SmartCardRaw(smart_card_raw_t *p); void SmartCardRaw(const smart_card_raw_t *p);
void SmartCardUpgrade(uint64_t arg0); void SmartCardUpgrade(uint64_t arg0);
void SmartCardSetBaud(uint64_t arg0); void SmartCardSetBaud(uint64_t arg0);
void SmartCardSetClock(uint64_t arg0); void SmartCardSetClock(uint64_t arg0);

View file

@ -1902,13 +1902,13 @@ void iClass_WriteBlock(uint8_t *msg) {
// verify write // verify write
uint8_t all_ff[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; uint8_t all_ff[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
if (payload->req.blockno == 2) { if (pagemap == PICOPASS_SECURE_PAGEMODE && payload->req.blockno == 2) {
// check response. e-purse update swaps first and second half // check response. e-purse update swaps first and second half
if (memcmp(payload->data + 4, resp, 4) || memcmp(payload->data, resp + 4, 4)) { if (memcmp(payload->data + 4, resp, 4) || memcmp(payload->data, resp + 4, 4)) {
res = false; res = false;
goto out; goto out;
} }
} else if (payload->req.blockno == 3 || payload->req.blockno == 4) { } else if (pagemap == PICOPASS_SECURE_PAGEMODE && (payload->req.blockno == 3 || payload->req.blockno == 4)) {
// check response. Key updates always return 0xffffffffffffffff // check response. Key updates always return 0xffffffffffffffff
if (memcmp(all_ff, resp, 8)) { if (memcmp(all_ff, resp, 8)) {
res = false; res = false;
@ -1929,6 +1929,159 @@ out:
reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_SUCCESS, (uint8_t *)&res, sizeof(uint8_t)); reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_SUCCESS, (uint8_t *)&res, sizeof(uint8_t));
} }
void iclass_credit_epurse(iclass_credit_epurse_t *payload) {
LED_A_ON();
bool shallow_mod = payload->req.shallow_mod;
Iso15693InitReader();
// select tag.
uint32_t eof_time = 0;
picopass_hdr_t hdr = {0};
uint8_t res = select_iclass_tag(&hdr, payload->req.use_credit_key, &eof_time, shallow_mod);
if (res == false) {
goto out;
}
uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
uint8_t mac[4] = {0};
// authenticate
if (payload->req.do_auth) {
res = authenticate_iclass_tag(&payload->req, &hdr, &start_time, &eof_time, mac);
if (res == false) {
goto out;
}
}
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
uint8_t cmd_read[] = {ICLASS_CMD_READ_OR_IDENTIFY, payload->req.blockno, 0x00, 0x00};
AddCrc(cmd_read + 1, 1);
uint8_t epurse[10];
res = iclass_send_cmd_with_retries(cmd_read, sizeof(cmd_read), epurse, sizeof(epurse), 10, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time, shallow_mod);
if (!res) {
switch_off();
if (payload->req.send_reply)
reply_ng(CMD_HF_ICLASS_CREDIT_EPURSE, PM3_ETIMEOUT, (uint8_t *)&res, sizeof(uint8_t));
return;
}
uint8_t write[14] = { 0x80 | ICLASS_CMD_UPDATE, payload->req.blockno };
uint8_t write_len = 14;
uint8_t epurse_offset = 0;
const uint8_t empty_epurse[] = {0xff, 0xff, 0xff, 0xff};
if (!memcmp(epurse, empty_epurse, 4)) {
// epurse data in stage 2
epurse_offset = 4;
}
memcpy(epurse + epurse_offset, payload->epurse, 4);
// blank out debiting value as per the first step of the crediting procedure
epurse[epurse_offset + 0] = 0xFF;
epurse[epurse_offset + 1] = 0xFF;
// initial epurse write for credit
memcpy(write + 2, epurse, 8);
doMAC_N(write + 1, 9, payload->req.use_credit_key ? hdr.key_c : hdr.key_d, mac);
memcpy(write + 10, mac, sizeof(mac));
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
uint8_t resp[10] = {0};
uint8_t tries = 3;
while (tries-- > 0) {
iclass_send_as_reader(write, write_len, &start_time, &eof_time, shallow_mod);
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred
res = false;
switch_off();
if (payload->req.send_reply)
reply_ng(CMD_HF_ICLASS_CREDIT_EPURSE, PM3_ETEAROFF, (uint8_t *)&res, sizeof(uint8_t));
return;
} else {
uint16_t resp_len = 0;
int res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_UPDATE, &eof_time, false, true, &resp_len);
if (res2 == PM3_SUCCESS && resp_len == 10) {
res = true;
break;
}
}
}
if (tries == 0) {
res = false;
goto out;
}
// check response. e-purse update swaps first and second half
if (memcmp(write + 2 + 4, resp, 4) || memcmp(write + 2, resp + 4, 4)) {
res = false;
goto out;
}
// new epurse write
// epurse offset is now flipped after the first write
epurse_offset ^= 4;
memcpy(resp + epurse_offset, payload->epurse, 4);
memcpy(write + 2, resp, 8);
doMAC_N(write + 1, 9, payload->req.use_credit_key ? hdr.key_c : hdr.key_d, mac);
memcpy(write + 10, mac, sizeof(mac));
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
tries = 3;
while (tries-- > 0) {
iclass_send_as_reader(write, write_len, &start_time, &eof_time, shallow_mod);
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred
res = false;
switch_off();
if (payload->req.send_reply)
reply_ng(CMD_HF_ICLASS_CREDIT_EPURSE, PM3_ETEAROFF, (uint8_t *)&res, sizeof(uint8_t));
return;
} else {
uint16_t resp_len = 0;
int res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_UPDATE, &eof_time, false, true, &resp_len);
if (res2 == PM3_SUCCESS && resp_len == 10) {
res = true;
break;
}
}
}
if (tries == 0) {
res = false;
goto out;
}
// check response. e-purse update swaps first and second half
if (memcmp(write + 2 + 4, resp, 4) || memcmp(write + 2, resp + 4, 4)) {
res = false;
goto out;
}
out:
switch_off();
if (payload->req.send_reply)
reply_ng(CMD_HF_ICLASS_CREDIT_EPURSE, PM3_SUCCESS, (uint8_t *)&res, sizeof(uint8_t));
}
void iClass_Restore(iclass_restore_req_t *msg) { void iClass_Restore(iclass_restore_req_t *msg) {
// sanitation // sanitation

View file

@ -25,6 +25,7 @@ void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string);
void ReaderIClass(uint8_t flags); void ReaderIClass(uint8_t flags);
void iClass_WriteBlock(uint8_t *msg); void iClass_WriteBlock(uint8_t *msg);
void iclass_credit_epurse(iclass_credit_epurse_t *payload);
void iClass_Dump(uint8_t *msg); void iClass_Dump(uint8_t *msg);
void iClass_Restore(iclass_restore_req_t *msg); void iClass_Restore(iclass_restore_req_t *msg);

View file

@ -142,6 +142,15 @@ Default HF 14a config is set to:
*/ */
static hf14a_config hf14aconfig = { 0, 0, 0, 0, 0 } ; static hf14a_config hf14aconfig = { 0, 0, 0, 0, 0 } ;
// Polling frames and configurations
static iso14a_polling_parameters_t WUPA_POLLING_PARAMETERS = {
.frames = { {{ 0x52 }, 1, 7, 0} },
.frame_count = 1,
.extra_timeout = 0,
};
void printHf14aConfig(void) { void printHf14aConfig(void) {
DbpString(_CYAN_("HF 14a config")); DbpString(_CYAN_("HF 14a config"));
Dbprintf(" [a] Anticol override.... %s%s%s", Dbprintf(" [a] Anticol override.... %s%s%s",
@ -179,7 +188,7 @@ void printHf14aConfig(void) {
* @brief setSamplingConfig * @brief setSamplingConfig
* @param sc * @param sc
*/ */
void setHf14aConfig(hf14a_config *hc) { void setHf14aConfig(const hf14a_config *hc) {
if ((hc->forceanticol >= 0) && (hc->forceanticol <= 2)) if ((hc->forceanticol >= 0) && (hc->forceanticol <= 2))
hf14aconfig.forceanticol = hc->forceanticol; hf14aconfig.forceanticol = hc->forceanticol;
@ -555,7 +564,7 @@ RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_t
} }
// Thinfilm, Kovio mangels ISO14443A in the way that they don't use start bit nor parity bits. // Thinfilm, Kovio mangles ISO14443A in the way that they don't use start bit nor parity bits.
static RAMFUNC int ManchesterDecoding_Thinfilm(uint8_t bit) { static RAMFUNC int ManchesterDecoding_Thinfilm(uint8_t bit) {
Demod.twoBits = (Demod.twoBits << 8) | bit; Demod.twoBits = (Demod.twoBits << 8) | bit;
@ -1045,8 +1054,8 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
case 1: { // MIFARE Classic 1k case 1: { // MIFARE Classic 1k
rATQA[0] = 0x04; rATQA[0] = 0x04;
sak = 0x08; sak = 0x08;
}
break; break;
}
case 2: { // MIFARE Ultralight case 2: { // MIFARE Ultralight
rATQA[0] = 0x44; rATQA[0] = 0x44;
sak = 0x00; sak = 0x00;
@ -1076,33 +1085,32 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
// READ_SIG // READ_SIG
memcpy(rSIGN, mfu_header->signature, 32); memcpy(rSIGN, mfu_header->signature, 32);
AddCrc14A(rSIGN, sizeof(rSIGN) - 2); AddCrc14A(rSIGN, sizeof(rSIGN) - 2);
}
break; break;
}
case 3: { // MIFARE DESFire case 3: { // MIFARE DESFire
rATQA[0] = 0x44; rATQA[0] = 0x44;
rATQA[1] = 0x03; rATQA[1] = 0x03;
sak = 0x20; sak = 0x20;
memcpy(rRATS, "\x06\x75\x77\x81\x02\x80\x00\x00", 8); memcpy(rRATS, "\x06\x75\x77\x81\x02\x80\x00\x00", 8);
}
break; break;
}
case 4: { // ISO/IEC 14443-4 - javacard (JCOP) case 4: { // ISO/IEC 14443-4 - javacard (JCOP)
rATQA[0] = 0x04; rATQA[0] = 0x04;
sak = 0x28; sak = 0x28;
}
break; break;
}
case 5: { // MIFARE TNP3XXX case 5: { // MIFARE TNP3XXX
rATQA[0] = 0x01; rATQA[0] = 0x01;
rATQA[1] = 0x0f; rATQA[1] = 0x0f;
sak = 0x01; sak = 0x01;
}
break; break;
}
case 6: { // MIFARE Mini 320b case 6: { // MIFARE Mini 320b
rATQA[0] = 0x44; rATQA[0] = 0x44;
sak = 0x09; sak = 0x09;
}
break; break;
case 7: { // NTAG }
case 7: { // NTAG 215
rATQA[0] = 0x44; rATQA[0] = 0x44;
sak = 0x00; sak = 0x00;
// some first pages of UL/NTAG dump is special data // some first pages of UL/NTAG dump is special data
@ -1131,37 +1139,39 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
// READ_SIG // READ_SIG
memcpy(rSIGN, mfu_header->signature, 32); memcpy(rSIGN, mfu_header->signature, 32);
AddCrc14A(rSIGN, sizeof(rSIGN) - 2); AddCrc14A(rSIGN, sizeof(rSIGN) - 2);
}
break; break;
}
case 8: { // MIFARE Classic 4k case 8: { // MIFARE Classic 4k
rATQA[0] = 0x02; rATQA[0] = 0x02;
sak = 0x18; sak = 0x18;
}
break; break;
}
case 9: { // FM11RF005SH (Shanghai Metro) case 9: { // FM11RF005SH (Shanghai Metro)
rATQA[0] = 0x03; rATQA[0] = 0x03;
rATQA[1] = 0x00; rATQA[1] = 0x00;
sak = 0x0A; sak = 0x0A;
}
break; break;
}
case 10: { // ST25TA IKEA Rothult case 10: { // ST25TA IKEA Rothult
rATQA[0] = 0x42; rATQA[0] = 0x42;
rATQA[1] = 0x00; rATQA[1] = 0x00;
sak = 0x20; sak = 0x20;
}
break; break;
}
case 11: { // ISO/IEC 14443-4 - javacard (JCOP) case 11: { // ISO/IEC 14443-4 - javacard (JCOP)
rATQA[0] = 0x04; rATQA[0] = 0x04;
sak = 0x20; sak = 0x20;
}
break; break;
}
case 12: { // HID Seos 4K card
rATQA[0] = 0x01;
sak = 0x20;
break;
}
default: { default: {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Error: unknown tagtype (%d)", tagType); if (g_dbglevel >= DBG_ERROR) Dbprintf("Error: unknown tagtype (%d)", tagType);
return false; return false;
} }
break;
} }
// if uid not supplied then get from emulator memory // if uid not supplied then get from emulator memory
@ -1264,17 +1274,20 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
AddCrc14A(rPPS, sizeof(rPPS) - 2); AddCrc14A(rPPS, sizeof(rPPS) - 2);
// EV1/NTAG, set PWD w AMIIBO algo if all zero.
if (tagType == 7) { if (tagType == 7) {
uint8_t pwd[4]; uint8_t pwd[4] = {0, 0, 0, 0};
uint8_t gen_pwd[4]; uint8_t gen_pwd[4] = {0, 0, 0, 0};
uint16_t start = (*pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH; emlGetMemBt(pwd, (*pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(pwd));
emlGetMemBt(pwd, start, sizeof(pwd)); emlGetMemBt(rPACK, (*pages) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(rPACK));
Uint4byteToMemBe(gen_pwd, ul_ev1_pwdgenB(data)); Uint4byteToMemBe(gen_pwd, ul_ev1_pwdgenB(data));
if (memcmp(pwd, gen_pwd, sizeof(pwd)) == 0) { if (memcmp(pwd, gen_pwd, sizeof(pwd)) == 0) {
rPACK[0] = 0x80; rPACK[0] = 0x80;
rPACK[1] = 0x80; rPACK[1] = 0x80;
} }
} }
AddCrc14A(rPACK, sizeof(rPACK) - 2); AddCrc14A(rPACK, sizeof(rPACK) - 2);
static tag_response_info_t responses_init[] = { static tag_response_info_t responses_init[] = {
@ -1558,7 +1571,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
// block1 = 4byte UID. // block1 = 4byte UID.
p_response = &responses[RESP_INDEX_UIDC1]; p_response = &responses[RESP_INDEX_UIDC1];
} else { // all other tags (16 byte block tags) } else { // all other tags (16 byte block tags)
uint8_t emdata[MAX_MIFARE_FRAME_SIZE]; uint8_t emdata[MAX_MIFARE_FRAME_SIZE] = {0};
emlGetMemBt(emdata, block, 16); emlGetMemBt(emdata, block, 16);
AddCrc14A(emdata, 16); AddCrc14A(emdata, 16);
EmSendCmd(emdata, sizeof(emdata)); EmSendCmd(emdata, sizeof(emdata));
@ -1572,7 +1585,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
// send NACK 0x0 == invalid argument // send NACK 0x0 == invalid argument
EmSend4bit(CARD_NACK_IV); EmSend4bit(CARD_NACK_IV);
} else { } else {
uint8_t emdata[MAX_FRAME_SIZE]; uint8_t emdata[MAX_FRAME_SIZE] = {0};
// first blocks of emu are header // first blocks of emu are header
int start = block1 * 4 + MFU_DUMP_PREFIX_LENGTH; int start = block1 * 4 + MFU_DUMP_PREFIX_LENGTH;
len = (block2 - block1 + 1) * 4; len = (block2 - block1 + 1) * 4;
@ -1656,7 +1669,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
// send NACK 0x0 == invalid argument // send NACK 0x0 == invalid argument
EmSend4bit(CARD_NACK_IV); EmSend4bit(CARD_NACK_IV);
} else { } else {
uint8_t cmd[3]; uint8_t cmd[3] = {0, 0, 0};
cmd[0] = tearings[index]; cmd[0] = tearings[index];
AddCrc14A(cmd, sizeof(cmd) - 2); AddCrc14A(cmd, sizeof(cmd) - 2);
EmSendCmd(cmd, sizeof(cmd)); EmSendCmd(cmd, sizeof(cmd));
@ -1692,36 +1705,32 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
} else if (receivedCmd[0] == MIFARE_ULC_AUTH_1) { // ULC authentication, or Desfire Authentication } else if (receivedCmd[0] == MIFARE_ULC_AUTH_1) { // ULC authentication, or Desfire Authentication
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
p_response = NULL; p_response = NULL;
} else if (receivedCmd[0] == MIFARE_ULEV1_AUTH && len == 7 && tagType == 7) { // NTAG / EV-1 authentication } else if (receivedCmd[0] == MIFARE_ULEV1_AUTH && len == 7 && tagType == 7) { // NTAG / EV-1
uint8_t pwd[4] = {0, 0, 0, 0};
/*
// PWD stored in dump now
uint8_t pwd[4];
emlGetMemBt(pwd, (pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(pwd)); emlGetMemBt(pwd, (pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(pwd));
if (g_dbglevel >= DBG_DEBUG) {
Dbprintf("Reader sent password: ");
Dbhexdump(4, receivedCmd + 1, 0);
Dbprintf("Loaded password from memory: ");
Dbhexdump(4, pwd, 0);
}
if (memcmp(pwd, "\x00\x00\x00\x00", 4) == 0) { if (memcmp(pwd, "\x00\x00\x00\x00", 4) == 0) {
Uint4byteToMemLe(pwd, ul_ev1_pwdgenB(data)); Uint4byteToMemLe(pwd, ul_ev1_pwdgenB(data));
Dbprintf("Calc pwd... %02X %02X %02X %02X", pwd[0], pwd[1], pwd[2], pwd[3]); if (g_dbglevel >= DBG_DEBUG) Dbprintf("Calc pwd... %02X %02X %02X %02X", pwd[0], pwd[1], pwd[2], pwd[3]);
} }
if (memcmp(receivedCmd + 1, pwd, 4) == 0) { if (memcmp(receivedCmd + 1, pwd, 4) == 0) {
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Password match, responding with PACK.");
uint8_t pack[4];
emlGetMemBt(pack, pages * 4 + MFU_DUMP_PREFIX_LENGTH, 2);
if (memcmp(pack, "\x00\x00\x00\x00", 4) == 0) {
pack[0] = 0x80;
pack[1] = 0x80;
}
AddCrc14A(pack, sizeof(pack) - 2);
EmSendCmd(pack, sizeof(pack));
} else {
EmSend4bit(CARD_NACK_NA);
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Auth attempt: %08x", bytes_to_num(receivedCmd + 1, 4));
}
p_response = NULL;
*/
p_response = &responses[RESP_INDEX_PACK]; p_response = &responses[RESP_INDEX_PACK];
} else {
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Password did not match, NACK_IV.");
p_response = NULL;
EmSend4bit(CARD_NACK_IV);
}
} else if (receivedCmd[0] == MIFARE_ULEV1_VCSL && len == 23 && tagType == 7) { } else if (receivedCmd[0] == MIFARE_ULEV1_VCSL && len == 23 && tagType == 7) {
uint8_t cmd[3]; uint8_t cmd[3] = {0, 0, 0};
emlGetMemBt(cmd, (pages - 2) * 4 + 1 + MFU_DUMP_PREFIX_LENGTH, 1); emlGetMemBt(cmd, (pages - 2) * 4 + 1 + MFU_DUMP_PREFIX_LENGTH, 1);
AddCrc14A(cmd, sizeof(cmd) - 2); AddCrc14A(cmd, sizeof(cmd) - 2);
EmSendCmd(cmd, sizeof(cmd)); EmSendCmd(cmd, sizeof(cmd));
@ -2355,9 +2364,10 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive
} }
// timeout already in ms + 100ms guard time // timeout already in ms + 100ms guard time
if (GetTickCountDelta(receive_timer) > timeout + 100) if (GetTickCountDelta(receive_timer) > timeout + 100) {
break; break;
} }
}
return false; return false;
} }
@ -2391,15 +2401,17 @@ void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing) {
} }
static uint16_t ReaderReceiveOffset(uint8_t *receivedAnswer, uint16_t offset, uint8_t *par) { static uint16_t ReaderReceiveOffset(uint8_t *receivedAnswer, uint16_t offset, uint8_t *par) {
if (!GetIso14443aAnswerFromTag(receivedAnswer, par, offset)) if (GetIso14443aAnswerFromTag(receivedAnswer, par, offset) == false) {
return 0; return 0;
}
LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false); LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false);
return Demod.len; return Demod.len;
} }
uint16_t ReaderReceive(uint8_t *receivedAnswer, uint8_t *par) { uint16_t ReaderReceive(uint8_t *receivedAnswer, uint8_t *par) {
if (!GetIso14443aAnswerFromTag(receivedAnswer, par, 0)) if (GetIso14443aAnswerFromTag(receivedAnswer, par, 0) == false) {
return 0; return 0;
}
LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false); LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false);
return Demod.len; return Demod.len;
} }
@ -2508,57 +2520,33 @@ static void iso14a_set_ATS_times(const uint8_t *ats) {
} }
} }
static int GetATQA(uint8_t *resp, uint8_t *resp_par, bool use_ecp, bool use_magsafe) {
#define ECP_DELAY 10 static int GetATQA(uint8_t *resp, uint8_t *resp_par, iso14a_polling_parameters_t *polling_parameters) {
#define ECP_RETRY_TIMEOUT 100 #define WUPA_RETRY_TIMEOUT 10
#define WUPA_RETRY_TIMEOUT 10 // 10ms
// 0x26 - REQA
// 0x52 - WAKE-UP
// 0x7A - MAGESAFE WAKE UP
uint8_t wupa[] = { ISO14443A_CMD_WUPA };
// if magsafe, set it outofbounds
if (use_magsafe) {
wupa[0] = MAGSAFE_CMD_WUPA_4;
}
if (use_ecp) {
// In case a device was already selected, we send a S-BLOCK deselect to bring it into an idle state so it can be selected again
uint8_t deselect_cmd[] = {0xc2, 0xe0, 0xb4};
ReaderTransmit(deselect_cmd, sizeof(deselect_cmd), NULL);
// Read response if present
(void) ReaderReceive(resp, resp_par);
}
uint32_t save_iso14a_timeout = iso14a_get_timeout(); uint32_t save_iso14a_timeout = iso14a_get_timeout();
iso14a_set_timeout(1236 / 128 + 1); // response to WUPA is expected at exactly 1236/fc. No need to wait longer. iso14a_set_timeout(1236 / 128 + 1); // response to WUPA is expected at exactly 1236/fc. No need to wait longer.
bool first_try = true; bool first_try = true;
uint32_t retry_timeout = use_ecp ? ECP_RETRY_TIMEOUT : WUPA_RETRY_TIMEOUT; uint32_t retry_timeout = WUPA_RETRY_TIMEOUT * polling_parameters->frame_count + polling_parameters->extra_timeout;
uint32_t start_time; uint32_t start_time = 0;
int len; int len;
// we may need several tries if we did send an unknown command or a wrong authentication before... uint8_t current_frame = 0;
do { do {
if (use_ecp && !first_try) { iso14a_polling_frame_t *frame_parameters = &polling_parameters->frames[current_frame];
uint8_t ecp[] = { 0x6a, 0x02, 0xC8, 0x01, 0x00, 0x03, 0x00, 0x02, 0x79, 0x00, 0x00, 0x00, 0x00, 0xC2, 0xD8};
ReaderTransmit(ecp, sizeof(ecp), NULL);
SpinDelay(ECP_DELAY);
}
if (use_magsafe) { if (frame_parameters->last_byte_bits == 8) {
if (wupa[0] == MAGSAFE_CMD_WUPA_4) { ReaderTransmit(frame_parameters->frame, frame_parameters->frame_length, NULL);
wupa[0] = MAGSAFE_CMD_WUPA_1;
} else { } else {
wupa[0]++; ReaderTransmitBitsPar(frame_parameters->frame, frame_parameters->last_byte_bits, NULL, NULL);
} }
if (frame_parameters->extra_delay) {
SpinDelay(frame_parameters->extra_delay);
} }
// Broadcast for a card, WUPA (0x52) will force response from all cards in the field
ReaderTransmitBitsPar(wupa, 7, NULL, NULL);
// Receive the ATQA // Receive the ATQA
len = ReaderReceive(resp, resp_par); len = ReaderReceive(resp, resp_par);
@ -2568,28 +2556,35 @@ static int GetATQA(uint8_t *resp, uint8_t *resp_par, bool use_ecp, bool use_mags
} }
first_try = false; first_try = false;
// Go over frame configurations, loop back when we reach the end
current_frame = current_frame < (polling_parameters->frame_count - 1) ? current_frame + 1 : 0;
} while (len == 0 && GetTickCountDelta(start_time) <= retry_timeout); } while (len == 0 && GetTickCountDelta(start_time) <= retry_timeout);
iso14a_set_timeout(save_iso14a_timeout); iso14a_set_timeout(save_iso14a_timeout);
return len; return len;
} }
int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) { int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) {
return iso14443a_select_cardEx(uid_ptr, p_card, cuid_ptr, anticollision, num_cascades, no_rats, false, false); return iso14443a_select_cardEx(uid_ptr, p_card, cuid_ptr, anticollision, num_cascades, no_rats, &WUPA_POLLING_PARAMETERS);
} }
// performs iso14443a anticollision (optional) and card select procedure // performs iso14443a anticollision (optional) and card select procedure
// fills the uid and cuid pointer unless NULL // fills the uid and cuid pointer unless NULL
// fills the card info record unless NULL // fills the card info record unless NULL
// if anticollision is false, then the UID must be provided in uid_ptr[] // if anticollision is false, then the UID must be provided in uid_ptr[]
// and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID) // and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID)
// requests ATS unless no_rats is true // requests ATS unless no_rats is true
int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats, bool use_ecp, bool use_magsafe) { int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr,
bool anticollision, uint8_t num_cascades, bool no_rats,
iso14a_polling_parameters_t *polling_parameters) {
uint8_t resp[MAX_FRAME_SIZE] = {0}; // theoretically. A usual RATS will be much smaller uint8_t resp[MAX_FRAME_SIZE] = {0}; // theoretically. A usual RATS will be much smaller
uint8_t resp_par[MAX_PARITY_SIZE] = {0}; uint8_t resp_par[MAX_PARITY_SIZE] = {0};
uint8_t sak; // cascade uid uint8_t sak = 0; // cascade uid
bool do_cascade = 1; bool do_cascade = 1;
int cascade_level = 0; int cascade_level = 0;
@ -2599,7 +2594,7 @@ int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint
p_card->ats_len = 0; p_card->ats_len = 0;
} }
if (GetATQA(resp, resp_par, use_ecp, use_magsafe) == false) { if (GetATQA(resp, resp_par, polling_parameters) == 0) {
return 0; return 0;
} }
@ -2624,11 +2619,11 @@ int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint
memcpy(p_card->uid, resp, 4); memcpy(p_card->uid, resp, 4);
// select again? // select again?
if (GetATQA(resp, resp_par, false, false) == false) { if (GetATQA(resp, resp_par, &WUPA_POLLING_PARAMETERS) == 0) {
return 0; return 0;
} }
if (GetATQA(resp, resp_par, false, false) == false) { if (GetATQA(resp, resp_par, &WUPA_POLLING_PARAMETERS) == 0) {
return 0; return 0;
} }
@ -2827,7 +2822,7 @@ int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades) {
uint8_t sak = 0x04; // cascade uid uint8_t sak = 0x04; // cascade uid
int cascade_level = 0; int cascade_level = 0;
if (!GetATQA(resp, resp_par, false, false)) { if (GetATQA(resp, resp_par, &WUPA_POLLING_PARAMETERS) == 0) {
return 0; return 0;
} }
@ -2854,7 +2849,9 @@ int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades) {
ReaderTransmit(sel_uid, sizeof(sel_uid), NULL); ReaderTransmit(sel_uid, sizeof(sel_uid), NULL);
// Receive the SAK // Receive the SAK
if (!ReaderReceive(resp, resp_par)) return 0; if (!ReaderReceive(resp, resp_par)) {
return 0;
}
sak = resp[0]; sak = resp[0];
@ -3035,7 +3032,12 @@ void ReaderIso14443a(PacketCommandNG *c) {
// if failed selecting, turn off antenna and quite. // if failed selecting, turn off antenna and quite.
if (!(param & ISO14A_NO_SELECT)) { if (!(param & ISO14A_NO_SELECT)) {
iso14a_card_select_t *card = (iso14a_card_select_t *)buf; iso14a_card_select_t *card = (iso14a_card_select_t *)buf;
arg0 = iso14443a_select_cardEx(NULL, card, NULL, true, 0, (param & ISO14A_NO_RATS), (param & ISO14A_USE_ECP), (param & ISO14A_USE_MAGSAFE));
arg0 = iso14443a_select_cardEx(
NULL, card, NULL, true, 0, (param & ISO14A_NO_RATS),
(param & ISO14A_USE_CUSTOM_POLLING) ? (iso14a_polling_parameters_t *)cmd : &WUPA_POLLING_PARAMETERS
);
// TODO: Improve by adding a cmd parser pointer and moving it by struct length to allow combining data with polling params
FpgaDisableTracing(); FpgaDisableTracing();
reply_mix(CMD_ACK, arg0, card->uidlen, 0, buf, sizeof(iso14a_card_select_t)); reply_mix(CMD_ACK, arg0, card->uidlen, 0, buf, sizeof(iso14a_card_select_t));

View file

@ -121,7 +121,7 @@ typedef enum {
#endif #endif
void printHf14aConfig(void); void printHf14aConfig(void);
void setHf14aConfig(hf14a_config *hc); void setHf14aConfig(const hf14a_config *hc);
hf14a_config *getHf14aConfig(void); hf14a_config *getHf14aConfig(void);
void iso14a_set_timeout(uint32_t timeout); void iso14a_set_timeout(uint32_t timeout);
uint32_t iso14a_get_timeout(void); uint32_t iso14a_get_timeout(void);
@ -151,7 +151,7 @@ uint16_t ReaderReceive(uint8_t *receivedAnswer, uint8_t *par);
void iso14443a_setup(uint8_t fpga_minor_mode); void iso14443a_setup(uint8_t fpga_minor_mode);
int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint8_t *res); int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint8_t *res);
int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats); int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats);
int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats, bool use_ecp, bool use_magsafe); int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats, iso14a_polling_parameters_t *polling_parameters);
int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades); int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades);
void iso14a_set_trigger(bool enable); void iso14a_set_trigger(bool enable);

View file

@ -39,9 +39,14 @@
* Current timing issues with ISO14443-b implementation * Current timing issues with ISO14443-b implementation
* Proxmark3 * Proxmark3
* Carrier Frequency 13.56MHz * Carrier Frequency 13.56MHz
* 1 / 13 560 000 = 73.74 nano seconds ( 0.07374 µs )
* SSP_CLK runs at 13.56MHz / 4 = 3,39MHz * SSP_CLK runs at 13.56MHz / 4 = 3,39MHz
* 1 / 3 390 000 = 294.98 nano seconds ( 0.2949 µs )
* *
* * 1 ETU = 9.4395 µs = 32 SSP_CLK = 128 FC
* 1 SSP_CLK = 4 FC
* 1 µs 3 SSP_CLK about 14 FC
* PROBLEM 1. * PROBLEM 1.
* ---------- * ----------
* one way of calculating time, that relates both to PM3 ssp_clk 3.39MHz, ISO freq of 13.56Mhz and ETUs * one way of calculating time, that relates both to PM3 ssp_clk 3.39MHz, ISO freq of 13.56Mhz and ETUs
@ -106,6 +111,9 @@
* *
*/ */
#ifndef MAX_14B_TIMEOUT #ifndef MAX_14B_TIMEOUT
// FWT(max) = 4949 ms or 4.95 seconds. // FWT(max) = 4949 ms or 4.95 seconds.
// SSP_CLK = 4949000 * 3.39 = 16777120 // SSP_CLK = 4949000 * 3.39 = 16777120
@ -122,8 +130,8 @@
// ETU 14 * 9.4395 µS = 132 µS == 0.132ms // ETU 14 * 9.4395 µS = 132 µS == 0.132ms
// TR2, counting from start of PICC EOF 14 ETU. // TR2, counting from start of PICC EOF 14 ETU.
#define DELAY_ISO14443B_PICC_TO_PCD_READER ETU_TO_SSP(14) #define DELAY_ISO14443B_PICC_TO_PCD_READER HF14_ETU_TO_SSP(14)
#define DELAY_ISO14443B_PCD_TO_PICC_READER ETU_TO_SSP(15) #define DELAY_ISO14443B_PCD_TO_PICC_READER HF14_ETU_TO_SSP(15)
/* Guard Time (per 14443-2) in ETU /* Guard Time (per 14443-2) in ETU
* *
@ -138,41 +146,41 @@
* TR0 * TR0
*/ */
#ifndef ISO14B_TR0 #ifndef ISO14B_TR0
# define ISO14B_TR0 ETU_TO_SSP(32) # define ISO14B_TR0 HF14_ETU_TO_SSP(16)
#endif #endif
#ifndef ISO14B_TR0_MAX #ifndef ISO14B_TR0_MAX
# define ISO14B_TR0_MAX ETU_TO_SSP(32) # define ISO14B_TR0_MAX HF14_ETU_TO_SSP(32)
// * TR0 - 32 ETU's maximum for ATQB only // * TR0 - 32 ETU's maximum for ATQB only
// * TR0 - FWT for all other commands // * TR0 - FWT for all other commands
// TR0 max is 151/fsc = 151/848kHz = 302us or 64 samples from FPGA // TR0 max is 159 µS or 32 samples from FPGA
// 32 ETU * 9.4395 µS == 302 µS // 16 ETU * 9.4395 µS == 151 µS
// 32 * 8 = 256 sub carrier cycles, // 16 * 8 = 128 sub carrier cycles,
// 256 / 4 = 64 I/Q pairs. // 128 / 4 = 32 I/Q pairs.
// since 1 I/Q pair after 4 subcarrier cycles at 848kHz subcarrier // since 1 I/Q pair after 4 subcarrier cycles at 848kHz subcarrier
#endif #endif
// 8 ETU = 75 µS == 256 SSP_CLK // 8 ETU = 75 µS == 256 SSP_CLK
#ifndef ISO14B_TR0_MIN #ifndef ISO14B_TR0_MIN
# define ISO14B_TR0_MIN ETU_TO_SSP(8) # define ISO14B_TR0_MIN HF14_ETU_TO_SSP(8)
#endif #endif
// Synchronization time (per 14443-2) in ETU // Synchronization time (per 14443-2) in ETU
// 10 ETU = 94,39 µS == 320 SSP_CLK // 16 ETU = 151 µS == 512 SSP_CLK
#ifndef ISO14B_TR1_MIN #ifndef ISO14B_TR1_MIN
# define ISO14B_TR1_MIN ETU_TO_SSP(10) # define ISO14B_TR1_MIN HF14_ETU_TO_SSP(16)
#endif #endif
// Synchronization time (per 14443-2) in ETU // Synchronization time (per 14443-2) in ETU
// 25 ETU == 236 µS == 800 SSP_CLK // 25 ETU == 236 µS == 800 SSP_CLK
#ifndef ISO14B_TR1_MAX #ifndef ISO14B_TR1_MAX
# define ISO14B_TR1 ETU_TO_SSP(25) # define ISO14B_TR1 HF14_ETU_TO_SSP(25)
#endif #endif
// Frame Delay Time PICC to PCD (per 14443-3 Amendment 1) in ETU // Frame Delay Time PICC to PCD (per 14443-3 Amendment 1) in ETU
// 14 ETU == 132 µS == 448 SSP_CLK // 14 ETU == 132 µS == 448 SSP_CLK
#ifndef ISO14B_TR2 #ifndef ISO14B_TR2
# define ISO14B_TR2 ETU_TO_SSP(14) # define ISO14B_TR2 HF14_ETU_TO_SSP(14)
#endif #endif
// 4sample // 4sample
@ -440,7 +448,7 @@ static void Uart14bInit(uint8_t *data) {
// param timeout accepts ETU // param timeout accepts ETU
static void iso14b_set_timeout(uint32_t timeout_etu) { static void iso14b_set_timeout(uint32_t timeout_etu) {
uint32_t ssp = ETU_TO_SSP(timeout_etu); uint32_t ssp = HF14_ETU_TO_SSP(timeout_etu);
if (ssp > MAX_14B_TIMEOUT) if (ssp > MAX_14B_TIMEOUT)
ssp = MAX_14B_TIMEOUT; ssp = MAX_14B_TIMEOUT;
@ -701,7 +709,7 @@ static void TransmitFor14443b_AsTag(const uint8_t *response, uint16_t len) {
// Main loop of simulated tag: receive commands from reader, decide what // Main loop of simulated tag: receive commands from reader, decide what
// response to send, and send it. // response to send, and send it.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void SimulateIso14443bTag(uint8_t *pupi) { void SimulateIso14443bTag(const uint8_t *pupi) {
LED_A_ON(); LED_A_ON();
// the only commands we understand is WUPB, AFI=0, Select All, N=1: // the only commands we understand is WUPB, AFI=0, Select All, N=1:
@ -1381,7 +1389,7 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, uint32_t
} }
if (Demod.len > 0) { if (Demod.len > 0) {
uint32_t sof_time = *eof_time - ETU_TO_SSP( uint32_t sof_time = *eof_time - HF14_ETU_TO_SSP(
(Demod.len * (8 + 2)) // time for byte transfers (Demod.len * (8 + 2)) // time for byte transfers
// + (10) // time for TR1 // + (10) // time for TR1
+ (10 + 2) // time for SOF transfer + (10 + 2) // time for SOF transfer
@ -1399,8 +1407,11 @@ static void TransmitFor14443b_AsReader(uint32_t *start_time) {
tosend_t *ts = get_tosend(); tosend_t *ts = get_tosend();
#ifdef RDV4
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_SHALLOW_MOD_RDV4);
#else
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_SHALLOW_MOD); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_SHALLOW_MOD);
#endif
// TR2 minimum 14 ETUs // TR2 minimum 14 ETUs
if (*start_time < ISO14B_TR0) { if (*start_time < ISO14B_TR0) {
@ -1544,7 +1555,7 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len, uint32_t
// eof_time in ssp clocks, but bits was added here! // eof_time in ssp clocks, but bits was added here!
// *eof_time = *start_time + (10 * ts->max) + 10 + 2 + 10; // *eof_time = *start_time + (10 * ts->max) + 10 + 2 + 10;
*eof_time = *start_time + ETU_TO_SSP(8 * ts->max); *eof_time = *start_time + HF14_ETU_TO_SSP(8 * ts->max);
LogTrace(cmd, len, *start_time, *eof_time, NULL, true); LogTrace(cmd, len, *start_time, *eof_time, NULL, true);
} }
@ -1579,6 +1590,12 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void
CodeAndTransmit14443bAsReader(real_cmd, msg_len + 3, &start_time, &eof_time, true); CodeAndTransmit14443bAsReader(real_cmd, msg_len + 3, &start_time, &eof_time, true);
eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER;
// Activation frame waiting time
// 65536/fc == 4833 µS
// SSP_CLK = 4833 µS * 3.39 = 16384
int len = Get14443bAnswerFromTag(rxdata, rxmaxlen, iso14b_timeout, &eof_time); int len = Get14443bAnswerFromTag(rxdata, rxmaxlen, iso14b_timeout, &eof_time);
FpgaDisableTracing(); FpgaDisableTracing();
@ -1836,7 +1853,7 @@ int iso14443b_select_xrx_card(iso14b_card_select_t *card) {
int slot; int slot;
for (slot = 0; slot < 4; slot++) { for (slot = 0; slot < 4; slot++) {
start_time = eof_time + ETU_TO_SSP(30); //(24); // next slot after 24 ETU start_time = eof_time + HF14_ETU_TO_SSP(30); //(24); // next slot after 24 ETU
retlen = Get14443bAnswerFromTag(x_atqb, sizeof(x_atqb), iso14b_timeout, &eof_time); retlen = Get14443bAnswerFromTag(x_atqb, sizeof(x_atqb), iso14b_timeout, &eof_time);
@ -2076,7 +2093,6 @@ void iso14443b_setup(void) {
// allocate command receive buffer // allocate command receive buffer
BigBuf_free(); BigBuf_free();
BigBuf_Clear_ext(false);
// Initialize Demod and Uart structs // Initialize Demod and Uart structs
Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE), MAX_FRAME_SIZE); Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE), MAX_FRAME_SIZE);
@ -2089,7 +2105,12 @@ void iso14443b_setup(void) {
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER); FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER);
// Signal field is on with the appropriate LED // Signal field is on with the appropriate LED
#ifdef RDV4
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_SHALLOW_MOD_RDV4);
#else
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_SHALLOW_MOD); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_SHALLOW_MOD);
#endif
SpinDelay(100); SpinDelay(100);
// Start the timer // Start the timer
@ -2395,6 +2416,7 @@ void SendRawCommand14443B_Ex(iso14b_raw_cmd_t *p) {
if ((p->flags & ISO14B_CLEARTRACE) == ISO14B_CLEARTRACE) { if ((p->flags & ISO14B_CLEARTRACE) == ISO14B_CLEARTRACE) {
clear_trace(); clear_trace();
BigBuf_Clear_ext(false);
} }
set_tracing(true); set_tracing(true);

View file

@ -41,7 +41,7 @@ int iso14443b_select_card(iso14b_card_select_t *card);
int iso14443b_select_card_srx(iso14b_card_select_t *card); int iso14443b_select_card_srx(iso14b_card_select_t *card);
int iso14443b_select_xrx_card(iso14b_card_select_t *card); int iso14443b_select_xrx_card(iso14b_card_select_t *card);
void SimulateIso14443bTag(uint8_t *pupi); void SimulateIso14443bTag(const uint8_t *pupi);
void AcquireRawAdcSamplesIso14443b(uint32_t parameter); void AcquireRawAdcSamplesIso14443b(uint32_t parameter);
void ReadSTBlock(uint8_t blocknr); void ReadSTBlock(uint8_t blocknr);
void SniffIso14443b(void); void SniffIso14443b(void);

View file

@ -294,7 +294,12 @@ void CodeIso15693AsTag(const uint8_t *cmd, size_t len) {
// Transmit the command (to the tag) that was placed in cmd[]. // Transmit the command (to the tag) that was placed in cmd[].
void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time, bool shallow_mod) { void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time, bool shallow_mod) {
#ifdef RDV4
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | (shallow_mod ? FPGA_HF_READER_MODE_SEND_SHALLOW_MOD_RDV4 : FPGA_HF_READER_MODE_SEND_FULL_MOD));
#else
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | (shallow_mod ? FPGA_HF_READER_MODE_SEND_SHALLOW_MOD : FPGA_HF_READER_MODE_SEND_FULL_MOD)); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | (shallow_mod ? FPGA_HF_READER_MODE_SEND_SHALLOW_MOD : FPGA_HF_READER_MODE_SEND_FULL_MOD));
#endif
if (*start_time < DELAY_ARM_TO_TAG) { if (*start_time < DELAY_ARM_TO_TAG) {
*start_time = DELAY_ARM_TO_TAG; *start_time = DELAY_ARM_TO_TAG;
@ -2119,7 +2124,6 @@ void Iso15693InitTag(void) {
StartCountSspClk(); StartCountSspClk();
} }
void EmlClearIso15693(void) { void EmlClearIso15693(void) {
// Resetting the bitstream also frees the BigBuf memory, so we do this here to prevent // Resetting the bitstream also frees the BigBuf memory, so we do this here to prevent
// an inconvenient reset in the future by Iso15693InitTag // an inconvenient reset in the future by Iso15693InitTag
@ -2128,16 +2132,6 @@ void EmlClearIso15693(void) {
reply_ng(CMD_HF_ISO15693_EML_CLEAR, PM3_SUCCESS, NULL, 0); reply_ng(CMD_HF_ISO15693_EML_CLEAR, PM3_SUCCESS, NULL, 0);
} }
void EmlSetMemIso15693(uint8_t count, uint8_t *data, uint32_t offset) {
uint8_t *emCARD = BigBuf_get_EM_addr();
memcpy(emCARD + offset, data, count);
}
void EmlGetMemIso15693(uint8_t count, uint8_t *output, uint32_t offset) {
uint8_t *emCARD = BigBuf_get_EM_addr();
memcpy(output, emCARD + offset, count);
}
// Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands // Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
// all demodulation performed in arm rather than host. - greg // all demodulation performed in arm rather than host. - greg
void SimTagIso15693(uint8_t *uid, uint8_t block_size) { void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
@ -2296,8 +2290,11 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
} }
// Block data // Block data
if (block_size * (block_idx + j + 1) <= CARD_MEMORY_SIZE) { if (block_size * (block_idx + j + 1) <= CARD_MEMORY_SIZE) {
EmlGetMemIso15693(block_size, resp_readblock + (work_offset + security_offset), emlGet(
block_size * (block_idx + j)); resp_readblock + (work_offset + security_offset),
block_size * (block_idx + j),
block_size
);
} else { } else {
memset(resp_readblock + work_offset + security_offset, 0, block_size); memset(resp_readblock + work_offset + security_offset, 0, block_size);
} }
@ -2334,7 +2331,7 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
uint8_t *data = cmd + 3 + address_offset + multi_offset; uint8_t *data = cmd + 3 + address_offset + multi_offset;
// write data // write data
EmlSetMemIso15693(block_count * block_size, data, block_idx * block_size); emlSet(data, (block_idx * block_size), (block_count * block_size));
// Build WRITE_(MULTI_)BLOCK response // Build WRITE_(MULTI_)BLOCK response
int response_length = 3; int response_length = 3;
@ -2664,7 +2661,7 @@ void SetTag15693Uid(const uint8_t *uid) {
switch_off(); switch_off();
} }
static void init_password_15693_Slix(uint8_t *buffer, uint8_t *pwd, const uint8_t *rnd) { static void init_password_15693_Slix(uint8_t *buffer, const uint8_t *pwd, const uint8_t *rnd) {
memcpy(buffer, pwd, 4); memcpy(buffer, pwd, 4);
if (rnd) { if (rnd) {
buffer[0] ^= rnd[0]; buffer[0] ^= rnd[0];
@ -2692,7 +2689,7 @@ static bool get_rnd_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t
return true; return true;
} }
static uint32_t disable_privacy_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t pass_id, uint8_t *password) { static uint32_t disable_privacy_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t pass_id, const uint8_t *password) {
uint8_t rnd[2]; uint8_t rnd[2];
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) { if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
@ -2714,7 +2711,7 @@ static uint32_t disable_privacy_15693_Slix(uint32_t start_time, uint32_t *eof_ti
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static uint32_t set_pass_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t pass_id, uint8_t *password, uint8_t *uid) { static uint32_t set_pass_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t pass_id, const uint8_t *password, uint8_t *uid) {
uint8_t rnd[2]; uint8_t rnd[2];
@ -2741,7 +2738,7 @@ static uint32_t set_pass_15693_Slix(uint32_t start_time, uint32_t *eof_time, uin
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static uint32_t set_privacy_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *password) { static uint32_t set_privacy_15693_Slix(uint32_t start_time, uint32_t *eof_time, const uint8_t *password) {
uint8_t rnd[2]; uint8_t rnd[2];
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) { if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
@ -2762,7 +2759,7 @@ static uint32_t set_privacy_15693_Slix(uint32_t start_time, uint32_t *eof_time,
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static uint32_t disable_eas_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *password, bool usepwd) { static uint32_t disable_eas_15693_Slix(uint32_t start_time, uint32_t *eof_time, const uint8_t *password, bool usepwd) {
uint8_t uid[8]; uint8_t uid[8];
get_uid_slix(start_time, eof_time, uid); get_uid_slix(start_time, eof_time, uid);
@ -2796,7 +2793,7 @@ static uint32_t disable_eas_15693_Slix(uint32_t start_time, uint32_t *eof_time,
} }
static uint32_t enable_eas_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *password, bool usepwd) { static uint32_t enable_eas_15693_Slix(uint32_t start_time, uint32_t *eof_time, const uint8_t *password, bool usepwd) {
uint8_t uid[8]; uint8_t uid[8];
get_uid_slix(start_time, eof_time, uid); get_uid_slix(start_time, eof_time, uid);
@ -2828,7 +2825,7 @@ static uint32_t enable_eas_15693_Slix(uint32_t start_time, uint32_t *eof_time, u
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static uint32_t write_password_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t pwd_id, uint8_t *password, uint8_t *uid) { static uint32_t write_password_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t pwd_id, const uint8_t *password, uint8_t *uid) {
uint8_t new_pwd_cmd[] = { (ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS), ISO15693_WRITE_PASSWORD, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, pwd_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t new_pwd_cmd[] = { (ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS), ISO15693_WRITE_PASSWORD, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, pwd_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
@ -2849,7 +2846,7 @@ static uint32_t write_password_15693_Slix(uint32_t start_time, uint32_t *eof_tim
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static uint32_t pass_protect_EASAFI_15693_Slix(uint32_t start_time, uint32_t *eof_time, bool set_option_flag, uint8_t *password) { static uint32_t pass_protect_EASAFI_15693_Slix(uint32_t start_time, uint32_t *eof_time, bool set_option_flag, const uint8_t *password) {
uint8_t flags; uint8_t flags;
@ -2888,7 +2885,7 @@ static uint32_t pass_protect_EASAFI_15693_Slix(uint32_t start_time, uint32_t *eo
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static uint32_t write_afi_15693(uint32_t start_time, uint32_t *eof_time, uint8_t *password, bool usepwd, uint8_t *uid, bool use_uid, uint8_t afi) { static uint32_t write_afi_15693(uint32_t start_time, uint32_t *eof_time, const uint8_t *password, bool usepwd, uint8_t *uid, bool use_uid, uint8_t afi) {
if (!use_uid) { if (!use_uid) {
int res_getuid = get_uid_slix(start_time, eof_time, uid); int res_getuid = get_uid_slix(start_time, eof_time, uid);
@ -2925,7 +2922,7 @@ static uint32_t write_afi_15693(uint32_t start_time, uint32_t *eof_time, uint8_t
} }
/* /*
static uint32_t enable_privacy_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t pass_id, uint8_t *password) { static uint32_t enable_privacy_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t pass_id, const uint8_t *password) {
uint8_t rnd[2]; uint8_t rnd[2];
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) { if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
@ -2946,7 +2943,7 @@ static uint32_t enable_privacy_15693_Slix(uint32_t start_time, uint32_t *eof_tim
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static uint32_t write_password_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t pass_id, uint8_t *password) { static uint32_t write_password_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t pass_id, const uint8_t *password) {
uint8_t rnd[2]; uint8_t rnd[2];
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) { if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
@ -2969,7 +2966,7 @@ static uint32_t write_password_15693_Slix(uint32_t start_time, uint32_t *eof_tim
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static uint32_t destroy_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t *password) { static uint32_t destroy_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, const uint8_t *password) {
uint8_t rnd[2]; uint8_t rnd[2];
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) { if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
@ -2993,7 +2990,7 @@ static uint32_t destroy_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint
*/ */
void WritePasswordSlixIso15693(uint8_t *old_password, uint8_t *new_password, uint8_t pwd_id) { void WritePasswordSlixIso15693(const uint8_t *old_password, const uint8_t *new_password, uint8_t pwd_id) {
LED_D_ON(); LED_D_ON();
Iso15693InitReader(); Iso15693InitReader();
StartCountSspClk(); StartCountSspClk();
@ -3018,7 +3015,7 @@ void WritePasswordSlixIso15693(uint8_t *old_password, uint8_t *new_password, uin
} }
void DisablePrivacySlixIso15693(uint8_t *password) { void DisablePrivacySlixIso15693(const uint8_t *password) {
LED_D_ON(); LED_D_ON();
Iso15693InitReader(); Iso15693InitReader();
StartCountSspClk(); StartCountSspClk();
@ -3033,7 +3030,7 @@ void DisablePrivacySlixIso15693(uint8_t *password) {
switch_off(); switch_off();
} }
void EnablePrivacySlixIso15693(uint8_t *password) { void EnablePrivacySlixIso15693(const uint8_t *password) {
LED_D_ON(); LED_D_ON();
Iso15693InitReader(); Iso15693InitReader();
StartCountSspClk(); StartCountSspClk();
@ -3049,7 +3046,7 @@ void EnablePrivacySlixIso15693(uint8_t *password) {
} }
void DisableEAS_AFISlixIso15693(uint8_t *password, bool usepwd) { void DisableEAS_AFISlixIso15693(const uint8_t *password, bool usepwd) {
LED_D_ON(); LED_D_ON();
Iso15693InitReader(); Iso15693InitReader();
StartCountSspClk(); StartCountSspClk();
@ -3067,7 +3064,7 @@ void DisableEAS_AFISlixIso15693(uint8_t *password, bool usepwd) {
switch_off(); switch_off();
} }
void EnableEAS_AFISlixIso15693(uint8_t *password, bool usepwd) { void EnableEAS_AFISlixIso15693(const uint8_t *password, bool usepwd) {
LED_D_ON(); LED_D_ON();
Iso15693InitReader(); Iso15693InitReader();
StartCountSspClk(); StartCountSspClk();
@ -3082,7 +3079,7 @@ void EnableEAS_AFISlixIso15693(uint8_t *password, bool usepwd) {
switch_off(); switch_off();
} }
void PassProtextEASSlixIso15693(uint8_t *password) { void PassProtextEASSlixIso15693(const uint8_t *password) {
LED_D_ON(); LED_D_ON();
Iso15693InitReader(); Iso15693InitReader();
StartCountSspClk(); StartCountSspClk();
@ -3091,7 +3088,7 @@ void PassProtextEASSlixIso15693(uint8_t *password) {
reply_ng(CMD_HF_ISO15693_SLIX_PASS_PROTECT_EAS, res, NULL, 0); reply_ng(CMD_HF_ISO15693_SLIX_PASS_PROTECT_EAS, res, NULL, 0);
switch_off(); switch_off();
} }
void PassProtectAFISlixIso15693(uint8_t *password) { void PassProtectAFISlixIso15693(const uint8_t *password) {
LED_D_ON(); LED_D_ON();
Iso15693InitReader(); Iso15693InitReader();
StartCountSspClk(); StartCountSspClk();
@ -3101,7 +3098,7 @@ void PassProtectAFISlixIso15693(uint8_t *password) {
switch_off(); switch_off();
} }
void WriteAFIIso15693(uint8_t *password, bool use_pwd, uint8_t *uid, bool use_uid, uint8_t afi) { void WriteAFIIso15693(const uint8_t *password, bool use_pwd, uint8_t *uid, bool use_uid, uint8_t afi) {
LED_D_ON(); LED_D_ON();
Iso15693InitReader(); Iso15693InitReader();
StartCountSspClk(); StartCountSspClk();

View file

@ -47,8 +47,6 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo
void AcquireRawAdcSamplesIso15693(void); void AcquireRawAdcSamplesIso15693(void);
void ReaderIso15693(iso15_card_select_t *p_card); // ISO15693 reader void ReaderIso15693(iso15_card_select_t *p_card); // ISO15693 reader
void EmlClearIso15693(void); void EmlClearIso15693(void);
void EmlSetMemIso15693(uint8_t count, uint8_t *data, uint32_t offset);
void EmlGetMemIso15693(uint8_t count, uint8_t *output, uint32_t offset);
void SimTagIso15693(uint8_t *uid, uint8_t block_size); // simulate an ISO15693 tag void SimTagIso15693(uint8_t *uid, uint8_t block_size); // simulate an ISO15693 tag
void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag
void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI
@ -62,12 +60,12 @@ int SendDataTagEOF(uint8_t *recv, uint16_t max_recv_len, uint32_t start_time, ui
void SetTag15693Uid(const uint8_t *uid); void SetTag15693Uid(const uint8_t *uid);
void WritePasswordSlixIso15693(uint8_t *old_password, uint8_t *new_password, uint8_t pwd_id); void WritePasswordSlixIso15693(const uint8_t *old_password, const uint8_t *new_password, uint8_t pwd_id);
void DisablePrivacySlixIso15693(uint8_t *password); void DisablePrivacySlixIso15693(const uint8_t *password);
void EnablePrivacySlixIso15693(uint8_t *password); void EnablePrivacySlixIso15693(const uint8_t *password);
void DisableEAS_AFISlixIso15693(uint8_t *password, bool usepwd); void DisableEAS_AFISlixIso15693(const uint8_t *password, bool usepwd);
void EnableEAS_AFISlixIso15693(uint8_t *password, bool usepwd); void EnableEAS_AFISlixIso15693(const uint8_t *password, bool usepwd);
void PassProtextEASSlixIso15693(uint8_t *password); void PassProtextEASSlixIso15693(const uint8_t *password);
void PassProtectAFISlixIso15693(uint8_t *password); void PassProtectAFISlixIso15693(const uint8_t *password);
void WriteAFIIso15693(uint8_t *password, bool usepwd, uint8_t *uid, bool use_uid, uint8_t afi); void WriteAFIIso15693(const uint8_t *password, bool usepwd, uint8_t *uid, bool use_uid, uint8_t afi);
#endif #endif

View file

@ -528,7 +528,7 @@ OUT:
StopTicks(); StopTicks();
} }
void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) { void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, const uint8_t *data) {
// configure ARM and FPGA // configure ARM and FPGA
init_reader(); init_reader();

View file

@ -25,7 +25,7 @@
void LegicRfInfo(void); void LegicRfInfo(void);
int LegicRfReaderEx(uint16_t offset, uint16_t len, uint8_t iv); int LegicRfReaderEx(uint16_t offset, uint16_t len, uint8_t iv);
void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv); void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv);
void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data); void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, const uint8_t *data);
legic_card_select_t *getLegicCardInfo(void); legic_card_select_t *getLegicCardInfo(void);
#endif /* __LEGICRF_H */ #endif /* __LEGICRF_H */

View file

@ -91,18 +91,18 @@ static bool wait_for(bool value, const uint32_t timeout) {
// - A bit length >80.2us is a 1 // - A bit length >80.2us is a 1
// - A bit length <80.2us is a 0 // - A bit length <80.2us is a 0
// - A bit length >148.6us is a code violation // - A bit length >148.6us is a code violation
static int8_t rx_bit(void) { static int32_t rx_bit(void) {
// backup ts for threshold calculation // backup ts for threshold calculation
uint32_t bit_start = last_frame_end; uint32_t bit_start = last_frame_end;
// wait for pause to end // wait for pause to end
if (!wait_for(RWD_PULSE, bit_start + RWD_TIME_1 * 3 / 2)) { if (wait_for(RWD_PULSE, bit_start + RWD_TIME_1 * 3 / 2) == false) {
return -1; return PM3_ERFTRANS;
} }
// wait for next pause // wait for next pause
if (!wait_for(RWD_PAUSE, bit_start + RWD_TIME_1 * 3 / 2)) { if (wait_for(RWD_PAUSE, bit_start + RWD_TIME_1 * 3 / 2) == false) {
return -1; return PM3_ERFTRANS;
} }
// update bit and frame end // update bit and frame end
@ -110,7 +110,7 @@ static int8_t rx_bit(void) {
// check for code violation (bit to short) // check for code violation (bit to short)
if (last_frame_end - bit_start < RWD_TIME_PAUSE) { if (last_frame_end - bit_start < RWD_TIME_PAUSE) {
return -1; return PM3_ERFTRANS;
} }
// apply threshold (average of RWD_TIME_0 and ) // apply threshold (average of RWD_TIME_0 and )
@ -215,7 +215,6 @@ static void tx_ack(void) {
// - receive the frame // - receive the frame
// - detect end of frame (last pause) // - detect end of frame (last pause)
static int32_t rx_frame(uint8_t *len) { static int32_t rx_frame(uint8_t *len) {
int32_t frame = 0;
// add 2 SSP clock cycles (1 for tx and 1 for rx pipeline delay) // add 2 SSP clock cycles (1 for tx and 1 for rx pipeline delay)
// those will be subtracted at the end of the rx phase // those will be subtracted at the end of the rx phase
@ -235,23 +234,24 @@ static int32_t rx_frame(uint8_t *len) {
// check for code violation // check for code violation
if (i > RWD_CMD_TIMEOUT) { if (i > RWD_CMD_TIMEOUT) {
return -1; return PM3_ETIMEOUT;
} }
} }
// backup ts for trace log // backup ts for trace log
uint32_t last_frame_start = last_frame_end; uint32_t last_frame_start = last_frame_end;
int32_t frame = 0;
// receive frame // receive frame
for (*len = 0; true; ++(*len)) { for (*len = 0; true; ++(*len)) {
// receive next bit // receive next bit
LED_B_ON(); LED_B_ON();
int8_t bit = rx_bit(); int32_t bit = rx_bit();
LED_B_OFF(); LED_B_OFF();
// check for code violation and to short / long frame // check for code violation and to short / long frame
if ((bit < 0) && ((*len < RWD_MIN_FRAME_LEN) || (*len > RWD_MAX_FRAME_LEN))) { if ((bit < 0) && ((*len < RWD_MIN_FRAME_LEN) || (*len > RWD_MAX_FRAME_LEN))) {
return -1; return PM3_ERFTRANS;
} }
// check for code violation caused by end of frame // check for code violation caused by end of frame
@ -353,7 +353,7 @@ static int32_t setup_phase(legic_card_select_t *p_card) {
// wait for iv // wait for iv
int32_t iv = rx_frame(&len); int32_t iv = rx_frame(&len);
if ((len != 7) || (iv < 0)) { if ((len != 7) || (iv < 0)) {
return -1; return PM3_ETIMEOUT;
} }
// configure prng // configure prng
@ -375,19 +375,19 @@ static int32_t setup_phase(legic_card_select_t *p_card) {
// wait for ack // wait for ack
int32_t ack = rx_frame(&len); int32_t ack = rx_frame(&len);
if ((len != 6) || (ack < 0)) { if ((len != 6) || (ack < 0)) {
return -1; return PM3_ETIMEOUT;
} }
// validate data // validate data
switch (p_card->tagtype) { switch (p_card->tagtype) {
case 0: case 0:
if (ack != 0x19) return -1; if (ack != 0x19) return PM3_ERFTRANS;
break; break;
case 1: case 1:
if (ack != 0x39) return -1; if (ack != 0x39) return PM3_ERFTRANS;
break; break;
case 2: case 2:
if (ack != 0x39) return -1; if (ack != 0x39) return PM3_ERFTRANS;
break; break;
} }
@ -399,7 +399,7 @@ static int32_t setup_phase(legic_card_select_t *p_card) {
// the gap by one period. // the gap by one period.
last_frame_end += TAG_BIT_PERIOD; last_frame_end += TAG_BIT_PERIOD;
return 0; return PM3_SUCCESS;
} }
static uint8_t calc_crc4(uint16_t cmd, uint8_t cmd_sz, uint8_t value) { static uint8_t calc_crc4(uint16_t cmd, uint8_t cmd_sz, uint8_t value) {
@ -414,7 +414,7 @@ static int32_t connected_phase(legic_card_select_t *p_card) {
// wait for command // wait for command
int32_t cmd = rx_frame(&len); int32_t cmd = rx_frame(&len);
if (cmd < 0) { if (cmd < 0) {
return -1; return PM3_ETIMEOUT;
} }
// check if command is LEGIC_READ // check if command is LEGIC_READ
@ -425,8 +425,7 @@ static int32_t connected_phase(legic_card_select_t *p_card) {
// transmit data // transmit data
tx_frame((crc << 8) | byte, 12); tx_frame((crc << 8) | byte, 12);
return PM3_SUCCESS;
return 0;
} }
// check if command is LEGIC_WRITE // check if command is LEGIC_WRITE
@ -441,7 +440,7 @@ static int32_t connected_phase(legic_card_select_t *p_card) {
uint8_t calc_crc = calc_crc4(addr << 1, p_card->cmdsize, byte); uint8_t calc_crc = calc_crc4(addr << 1, p_card->cmdsize, byte);
if (calc_crc != crc) { if (calc_crc != crc) {
Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc); Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc);
return -1; return PM3_ECRC;
} }
// store data // store data
@ -449,11 +448,10 @@ static int32_t connected_phase(legic_card_select_t *p_card) {
// transmit ack // transmit ack
tx_ack(); tx_ack();
return PM3_SUCCESS;
return 0;
} }
return -1; return PM3_ERFTRANS;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -466,26 +464,26 @@ void LegicRfSimulate(uint8_t tagtype, bool send_reply) {
// configure ARM and FPGA // configure ARM and FPGA
init_tag(); init_tag();
int res = PM3_SUCCESS; int res = init_card(tagtype, &card);
// verify command line input // verify command line input
if (init_card(tagtype, &card) != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
DbpString("Unknown tagtype to simulate"); DbpString("Unknown tagtype to simulate");
res = PM3_ESOFT;
goto OUT; goto OUT;
} }
uint16_t counter = 0;
LED_A_ON(); LED_A_ON();
Dbprintf("Legic Prime, simulating uid: %02X%02X%02X%02X", legic_mem[0], legic_mem[1], legic_mem[2], legic_mem[3]); Dbprintf("Legic Prime, simulating MCD... " _YELLOW_("%02X") " MSN... " _YELLOW_("%02X%02X%02X"), legic_mem[0], legic_mem[1], legic_mem[2], legic_mem[3]);
uint16_t counter = 0;
while (BUTTON_PRESS() == false) { while (BUTTON_PRESS() == false) {
WDT_HIT(); WDT_HIT();
if (counter >= 2000) { if (counter >= 2000) {
if (data_available()) { if (data_available()) {
res = PM3_EOPABORTED; res = PM3_EOPABORTED;
break; goto OUT;
} }
counter = 0; counter = 0;
} }
@ -497,12 +495,12 @@ void LegicRfSimulate(uint8_t tagtype, bool send_reply) {
} }
// wait for connection, restart on error // wait for connection, restart on error
if (setup_phase(&card)) { if (setup_phase(&card) != PM3_SUCCESS) {
continue; continue;
} }
// connection is established, process commands until one fails // connection is established, process commands until one fails
while (connected_phase(&card) == false) { while (connected_phase(&card) == PM3_SUCCESS) {
WDT_HIT(); WDT_HIT();
} }
} }
@ -510,17 +508,19 @@ void LegicRfSimulate(uint8_t tagtype, bool send_reply) {
OUT: OUT:
if (g_dbglevel >= DBG_ERROR) { if (g_dbglevel >= DBG_ERROR) {
Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", get_tracing(), BigBuf_get_traceLen()); Dbprintf("Emulator stopped. Trace length... " _YELLOW_("%d"), BigBuf_get_traceLen());
} }
if (res == PM3_EOPABORTED) if (res == PM3_EOPABORTED) {
DbpString("aborted by user"); DbpString("Aborted by user");
}
switch_off(); switch_off();
StopTicks(); StopTicks();
if (send_reply) if (send_reply) {
reply_ng(CMD_HF_LEGIC_SIMULATE, res, NULL, 0); reply_ng(CMD_HF_LEGIC_SIMULATE, res, NULL, 0);
}
BigBuf_free_keep_EM(); BigBuf_free_keep_EM();
} }

View file

@ -287,7 +287,7 @@ void printT55xxConfig(void) {
DbpString(""); DbpString("");
} }
void setT55xxConfig(uint8_t arg0, t55xx_configurations_t *c) { void setT55xxConfig(uint8_t arg0, const t55xx_configurations_t *c) {
for (uint8_t i = 0; i < 4; i++) { for (uint8_t i = 0; i < 4; i++) {
if (c->m[i].start_gap != 0) if (c->m[i].start_gap != 0)
T55xx_Timing.m[i].start_gap = c->m[i].start_gap; T55xx_Timing.m[i].start_gap = c->m[i].start_gap;
@ -1009,7 +1009,7 @@ void CmdHIDsimTAG(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, bool
// prepare a waveform pattern in the buffer based on the ID given then // prepare a waveform pattern in the buffer based on the ID given then
// simulate a FSK tag until the button is pressed // simulate a FSK tag until the button is pressed
// arg1 contains fcHigh and fcLow, arg2 contains STT marker and clock // arg1 contains fcHigh and fcLow, arg2 contains STT marker and clock
void CmdFSKsimTAGEx(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, uint8_t *bits, bool ledcontrol, int numcycles) { void CmdFSKsimTAGEx(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, const uint8_t *bits, bool ledcontrol, int numcycles) {
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
@ -1045,7 +1045,7 @@ void CmdFSKsimTAGEx(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t cl
// prepare a waveform pattern in the buffer based on the ID given then // prepare a waveform pattern in the buffer based on the ID given then
// simulate a FSK tag until the button is pressed // simulate a FSK tag until the button is pressed
// arg1 contains fcHigh and fcLow, arg2 contains STT marker and clock // arg1 contains fcHigh and fcLow, arg2 contains STT marker and clock
void CmdFSKsimTAG(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, uint8_t *bits, bool ledcontrol) { void CmdFSKsimTAG(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, const uint8_t *bits, bool ledcontrol) {
CmdFSKsimTAGEx(fchigh, fclow, separator, clk, bitslen, bits, ledcontrol, -1); CmdFSKsimTAGEx(fchigh, fclow, separator, clk, bitslen, bits, ledcontrol, -1);
reply_ng(CMD_LF_FSK_SIMULATE, PM3_EOPABORTED, NULL, 0); reply_ng(CMD_LF_FSK_SIMULATE, PM3_EOPABORTED, NULL, 0);
} }
@ -1866,9 +1866,9 @@ void T55xxResetRead(uint8_t flags, bool ledcontrol) {
if (ledcontrol) LED_A_OFF(); if (ledcontrol) LED_A_OFF();
} }
void T55xxDangerousRawTest(uint8_t *data, bool ledcontrol) { void T55xxDangerousRawTest(const uint8_t *data, bool ledcontrol) {
// supports only default downlink mode // supports only default downlink mode
t55xx_test_block_t *c = (t55xx_test_block_t *)data; const t55xx_test_block_t *c = (const t55xx_test_block_t *)data;
uint8_t start_wait = 4; uint8_t start_wait = 4;
uint8_t bs[128 / 8]; uint8_t bs[128 / 8];
@ -2320,7 +2320,7 @@ void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, boo
} }
// clone viking tag to T55xx // clone viking tag to T55xx
void CopyVikingtoT55xx(uint8_t *blocks, bool q5, bool em, bool ledcontrol) { void CopyVikingtoT55xx(const uint8_t *blocks, bool q5, bool em, bool ledcontrol) {
uint32_t data[] = {T55x7_BITRATE_RF_32 | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT), 0, 0}; uint32_t data[] = {T55x7_BITRATE_RF_32 | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT), 0, 0};
if (q5) { if (q5) {

View file

@ -38,9 +38,9 @@ void CmdHIDsimTAGEx(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, boo
void CmdHIDsimTAG(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, bool ledcontrol); void CmdHIDsimTAG(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, bool ledcontrol);
void CmdFSKsimTAGEx(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, void CmdFSKsimTAGEx(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen,
uint8_t *bits, bool ledcontrol, int numcycles); const uint8_t *bits, bool ledcontrol, int numcycles);
void CmdFSKsimTAG(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, void CmdFSKsimTAG(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen,
uint8_t *bits, bool ledcontrol); const uint8_t *bits, bool ledcontrol);
void CmdASKsimTAG(uint8_t encoding, uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size, void CmdASKsimTAG(uint8_t encoding, uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size,
const uint8_t *bits, bool ledcontrol); const uint8_t *bits, bool ledcontrol);
void CmdPSKsimTAG(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, void CmdPSKsimTAG(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size,
@ -54,7 +54,7 @@ int lf_em410x_watch(int findone, uint32_t *high, uint64_t *low, bool ledcontrol)
int lf_io_watch(int findone, uint32_t *high, uint32_t *low, bool ledcontrol); int lf_io_watch(int findone, uint32_t *high, uint32_t *low, bool ledcontrol);
void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, bool q5, bool em, bool ledcontrol); // Clone an HID card to T5557/T5567 void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, bool q5, bool em, bool ledcontrol); // Clone an HID card to T5557/T5567
void CopyVikingtoT55xx(uint8_t *blocks, bool q5, bool em, bool ledcontrol); void CopyVikingtoT55xx(const uint8_t *blocks, bool q5, bool em, bool ledcontrol);
int copy_em410x_to_t55xx(uint8_t card, uint8_t clock, uint32_t id_hi, uint32_t id_lo, bool ledcontrol); int copy_em410x_to_t55xx(uint8_t card, uint8_t clock, uint32_t id_hi, uint32_t id_lo, bool ledcontrol);
@ -66,7 +66,7 @@ void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block,
uint8_t downlink_mode, bool ledcontrol); uint8_t downlink_mode, bool ledcontrol);
void T55xxWakeUp(uint32_t pwd, uint8_t flags, bool ledcontrol); void T55xxWakeUp(uint32_t pwd, uint8_t flags, bool ledcontrol);
void T55xx_ChkPwds(uint8_t flags, bool ledcontrol); void T55xx_ChkPwds(uint8_t flags, bool ledcontrol);
void T55xxDangerousRawTest(uint8_t *data, bool ledcontrol); void T55xxDangerousRawTest(const uint8_t *data, bool ledcontrol);
void turn_read_lf_on(uint32_t delay); void turn_read_lf_on(uint32_t delay);
void turn_read_lf_off(uint32_t delay); void turn_read_lf_off(uint32_t delay);
@ -78,7 +78,7 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd, bo
void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd, bool ledcontrol); void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd, bool ledcontrol);
void Cotag(uint32_t arg0, bool ledcontrol); void Cotag(uint32_t arg0, bool ledcontrol);
void setT55xxConfig(uint8_t arg0, t55xx_configurations_t *c); void setT55xxConfig(uint8_t arg0, const t55xx_configurations_t *c);
t55xx_configurations_t *getT55xxConfig(void); t55xx_configurations_t *getT55xxConfig(void);
void printT55xxConfig(void); void printT55xxConfig(void);
void loadT55xxConfig(void); void loadT55xxConfig(void);

View file

@ -94,7 +94,7 @@ void setDefaultSamplingConfig(void) {
* @brief setSamplingConfig * @brief setSamplingConfig
* @param sc * @param sc
*/ */
void setSamplingConfig(sample_config *sc) { void setSamplingConfig(const sample_config *sc) {
// decimation (1-8) how many bits of adc sample value to save // decimation (1-8) how many bits of adc sample value to save
if (sc->decimation > 0 && sc->decimation < 9) if (sc->decimation > 0 && sc->decimation < 9)

View file

@ -110,7 +110,7 @@ void LFSetupFPGAForADC(int divisor, bool reader_field);
* @brief setSamplingConfig * @brief setSamplingConfig
* @param sc * @param sc
*/ */
void setSamplingConfig(sample_config *sc); void setSamplingConfig(const sample_config *sc);
void setDefaultSamplingConfig(void); void setDefaultSamplingConfig(void);
sample_config *getSamplingConfig(void); sample_config *getSamplingConfig(void);

View file

@ -115,7 +115,7 @@ static void zx8211_setup_read(void) {
WDT_HIT(); WDT_HIT();
} }
static void zx_send(uint8_t *cmd, uint8_t clen) { static void zx_send(const uint8_t *cmd, uint8_t clen) {
if (clen == 0) if (clen == 0)
return; return;

View file

@ -73,10 +73,11 @@ int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_c
struct Crypto1State *pcs = &mpcs; struct Crypto1State *pcs = &mpcs;
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
uint32_t timeout = iso14a_get_timeout();
LED_A_ON(); LED_A_ON();
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
@ -95,6 +96,10 @@ int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_c
goto OUT; goto OUT;
}; };
// frame waiting time (FWT) in 1/fc
uint32_t fwt = 256 * 16 * (1 << 7);
iso14a_set_timeout(fwt / (8 * 16));
for (uint8_t i = 0; i < count; i++) { for (uint8_t i = 0; i < count; i++) {
if (mifare_classic_readblock_ex(pcs, block_no + i, block_data + (i * 16), read_cmd)) { if (mifare_classic_readblock_ex(pcs, block_no + i, block_data + (i * 16), read_cmd)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Read block error"); if (g_dbglevel >= DBG_ERROR) Dbprintf("Read block error");
@ -112,11 +117,11 @@ int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_c
OUT: OUT:
crypto1_deinit(pcs); crypto1_deinit(pcs);
iso14a_set_timeout(timeout);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();
set_tracing(false); set_tracing(false);
BigBuf_free(); BigBuf_free();
return retval; return retval;
} }
@ -145,7 +150,7 @@ int16_t mifare_cmd_writeblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t write
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
uint8_t retval = PM3_SUCCESS; int retval = PM3_SUCCESS;
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
@ -1805,8 +1810,8 @@ OUT:
emlSetMem_xt(block, blockno, 1, sizeof(block)); emlSetMem_xt(block, blockno, 1, sizeof(block));
} }
MifareECardLoad(sectorcnt, 0); MifareECardLoad(sectorcnt, MF_KEY_A);
MifareECardLoad(sectorcnt, 1); MifareECardLoad(sectorcnt, MF_KEY_B);
} }
} else { } else {
// partial/none keys found // partial/none keys found
@ -2014,15 +2019,6 @@ void MifareEMemClr(void) {
emlClearMem(); emlClearMem();
} }
void MifareEMemSet(uint8_t blockno, uint8_t blockcnt, uint8_t blockwidth, uint8_t *datain) {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
if (blockwidth == 0)
blockwidth = 16; // backwards compat... default bytewidth
emlSetMem_xt(datain, blockno, blockcnt, blockwidth); // data, block num, blocks count, block byte width
}
void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) { void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
@ -2072,14 +2068,36 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
int retval = PM3_SUCCESS; int retval = PM3_SUCCESS;
// increase time-out. Magic card etc are slow
uint32_t timeout = iso14a_get_timeout();
// frame waiting time (FWT) in 1/fc
uint32_t fwt = 256 * 16 * (1 << 6);
iso14a_set_timeout(fwt / (8 * 16));
for (uint8_t s = 0; s < sectorcnt; s++) { for (uint8_t s = 0; s < sectorcnt; s++) {
uint64_t ui64Key = emlGetKey(s, keytype); uint64_t ui64Key = emlGetKey(s, keytype);
// MFC 1K EV1 sector 16,17 don't use key A. if (sectorcnt == 18) {
if ((sectorcnt == 18) && (keytype == 0) && s > 15) { // MFC 1K EV1, skip sector 16 since its lockdown
if (s == 16) {
// unknown sector trailer, keep the keys, set only the AC
uint8_t st[16] = {0x00};
emlGetMem(st, FirstBlockOfSector(s) + 3, 1);
memcpy(st + 6, "\x70\xF0\xF8\x69", 4);
emlSetMem_xt(st, FirstBlockOfSector(s) + 3, 1, 16);
continue; continue;
} }
// ICEMAN: ugly hack, we don't want to trigger the partial load message
// MFC 1K EV1 sector 17 don't use key A.
// not mention we don't save signatures in our MFC dump files.
if (s == 17 && keytype == 0) {
ui64Key = 0x4B791BEA7BCC;
keytype = 1;
}
}
// use fast select // use fast select
if (have_uid == false) { // need a full select cycle to get the uid first if (have_uid == false) { // need a full select cycle to get the uid first
iso14a_card_select_t card_info; iso14a_card_select_t card_info;
@ -2110,43 +2128,56 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
// Auth // Auth
if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(s), keytype, ui64Key, AUTH_FIRST)) { if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(s), keytype, ui64Key, AUTH_FIRST)) {
retval = PM3_EPARTIAL; retval = PM3_EPARTIAL;
if (g_dbglevel > DBG_ERROR) { if (g_dbglevel >= DBG_ERROR) {
Dbprintf("Sector %2d - Auth error", s); Dbprintf("Sector %2d - Auth error", s);
} }
continue; continue;
} }
#define MAX_RETRIES 2 #define MAX_RETRIES 2
uint8_t data[16] = {0x00}; uint8_t data[16] = {0x00};
for (uint8_t b = 0; b < NumBlocksPerSector(s); b++) { for (uint8_t b = 0; b < NumBlocksPerSector(s); b++) {
memset(data, 0x00, sizeof(data)); memset(data, 0x00, sizeof(data));
uint8_t tb = FirstBlockOfSector(s) + b;
uint8_t r = 0;
for (; r < MAX_RETRIES; r++) {
for (uint8_t r = 0; r < MAX_RETRIES; r++) { int res = mifare_classic_readblock(pcs, tb, data);
if (res == 1) {
if (mifare_classic_readblock(pcs, FirstBlockOfSector(s) + b, data)) {
retval |= PM3_EPARTIAL; retval |= PM3_EPARTIAL;
if (g_dbglevel > DBG_ERROR) { if (g_dbglevel >= DBG_ERROR) {
Dbprintf("Error reading sector %2d block %2d", s, b); Dbprintf("Error No rights reading sector %2d block %2d", s, b);
} }
break;
}
// retry if wrong len.
if (res != 0) {
continue; continue;
} }
// No need to copy empty // No need to copy empty
if (memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) == 0) { if (memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) == 0) {
continue; break;
} }
if (b < NumBlocksPerSector(s) - 1) { if (IsSectorTrailer(b)) {
emlSetMem(data, FirstBlockOfSector(s) + b, 1);
} else {
// sector trailer, keep the keys, set only the AC // sector trailer, keep the keys, set only the AC
uint8_t st[16] = {0x00}; uint8_t st[16] = {0x00};
emlGetMem(st, FirstBlockOfSector(s) + b, 1); emlGetMem(st, tb, 1);
memcpy(st + 6, data + 6, 4); memcpy(st + 6, data + 6, 4);
emlSetMem(st, FirstBlockOfSector(s) + b, 1); emlSetMem_xt(st, tb, 1, 16);
} else {
emlSetMem_xt(data, tb, 1, 16);
} }
break;
}
// if we failed all retries, notify client
if (r == MAX_RETRIES) {
retval |= PM3_EPARTIAL;
} }
} }
} }
@ -2154,6 +2185,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
int res = mifare_classic_halt(pcs); int res = mifare_classic_halt(pcs);
(void)res; (void)res;
iso14a_set_timeout(timeout);
crypto1_deinit(pcs); crypto1_deinit(pcs);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();
@ -2322,6 +2354,12 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
set_tracing(true); set_tracing(true);
} }
// increase time-out. Magic card etc are slow
uint32_t timeout = iso14a_get_timeout();
// frame waiting time (FWT) in 1/fc
uint32_t fwt = 256 * 16 * (1 << 7);
iso14a_set_timeout(fwt / (8 * 16));
//loop doesn't loop just breaks out if error or done //loop doesn't loop just breaks out if error or done
while (true) { while (true) {
if (workFlags & MAGIC_WUPC) { if (workFlags & MAGIC_WUPC) {
@ -2343,7 +2381,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
} }
// read block // read block
if ((mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) { if ((mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != MAX_MIFARE_FRAME_SIZE)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("read block send command error"); if (g_dbglevel >= DBG_ERROR) Dbprintf("read block send command error");
errormsg = 0; errormsg = 0;
break; break;
@ -2371,6 +2409,8 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
if (workFlags & MAGIC_OFF) if (workFlags & MAGIC_OFF)
OnSuccessMagic(); OnSuccessMagic();
iso14a_set_timeout(timeout);
} }
void MifareCIdent(bool is_mfc) { void MifareCIdent(bool is_mfc) {

View file

@ -40,7 +40,6 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
void MifareChkKeys_file(uint8_t *fn); void MifareChkKeys_file(uint8_t *fn);
void MifareEMemClr(void); 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); void MifareEMemGet(uint8_t blockno, uint8_t blockcnt);
int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype); int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype);
int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype); int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype);

View file

@ -523,7 +523,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
uint8_t rAUTH_NT_keystream[4]; uint8_t rAUTH_NT_keystream[4];
uint32_t nonce = 0; uint32_t nonce = 0;
tUart14a *uart = GetUart14a(); const tUart14a *uart = GetUart14a();
// free eventually allocated BigBuf memory but keep Emulator Memory // free eventually allocated BigBuf memory but keep Emulator Memory
BigBuf_free_keep_EM(); BigBuf_free_keep_EM();
@ -1272,7 +1272,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
memcpy(receivedCmd_dec, response, 16); // don't change anything memcpy(receivedCmd_dec, response, 16); // don't change anything
} }
} }
emlSetMem(receivedCmd_dec, cardWRBL, 1); emlSetMem_xt(receivedCmd_dec, cardWRBL, 1, 16);
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); // always ACK? EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); // always ACK?
FpgaDisableTracing(); FpgaDisableTracing();

View file

@ -116,7 +116,9 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t
uint16_t len = ReaderReceive(answer, par); uint16_t len = ReaderReceive(answer, par);
if (answer_parity) *answer_parity = par[0]; if (answer_parity) {
*answer_parity = par[0];
}
if (pcs && (crypted == CRYPT_ALL)) { if (pcs && (crypted == CRYPT_ALL)) {
if (len == 1) { if (len == 1) {
@ -127,10 +129,11 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 3)) << 3; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 3)) << 3;
answer[0] = res; answer[0] = res;
} else { } else {
for (pos = 0; pos < len; pos++) for (pos = 0; pos < len; pos++) {
answer[pos] = crypto1_byte(pcs, 0x00, 0) ^ answer[pos]; answer[pos] = crypto1_byte(pcs, 0x00, 0) ^ answer[pos];
} }
} }
}
return len; return len;
} }
@ -206,8 +209,8 @@ int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
uint32_t save_timeout = iso14a_get_timeout(); uint32_t save_timeout = iso14a_get_timeout();
// set timeout for authentication response // set timeout for authentication response
if (save_timeout > 103) if (save_timeout > 106)
iso14a_set_timeout(103); iso14a_set_timeout(106);
// Receive 4 byte tag answer // Receive 4 byte tag answer
len = ReaderReceive(receivedAnswer, receivedAnswerPar); len = ReaderReceive(receivedAnswer, receivedAnswerPar);
@ -238,11 +241,15 @@ int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8
uint16_t len = mifare_sendcmd_short(pcs, 1, iso_byte, blockNo, receivedAnswer, receivedAnswerPar, NULL); uint16_t len = mifare_sendcmd_short(pcs, 1, iso_byte, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if (len == 1) { if (len == 1) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error %02x", receivedAnswer[0]); if (g_dbglevel >= DBG_ERROR) {
Dbprintf("Block " _YELLOW_("%3d") " Cmd 0x%02x Cmd Error %02x", blockNo, iso_byte, receivedAnswer[0]);
}
return 1; return 1;
} }
if (len != 18) { if (len != 18) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("wrong response len %d (expected 18)", len); if (g_dbglevel >= DBG_ERROR) {
Dbprintf("Block " _YELLOW_("%3d") " Cmd 0x%02x Wrong response len, expected 18 got " _RED_("%d"), blockNo, iso_byte, len);
}
return 2; return 2;
} }
@ -610,32 +617,28 @@ uint8_t FirstBlockOfSector(uint8_t sectorNo) {
return sectorNo * 4; return sectorNo * 4;
else else
return 32 * 4 + (sectorNo - 32) * 16; return 32 * 4 + (sectorNo - 32) * 16;
} }
// work with emulator memory // work with emulator memory
void emlSetMem(uint8_t *data, int blockNum, int blocksCount) { void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int block_width) {
emlSetMem_xt(data, blockNum, blocksCount, 16); uint32_t offset = blockNum * block_width;
} uint32_t len = blocksCount * block_width;
emlSet(data, offset, len);
void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth) {
uint8_t *emCARD = BigBuf_get_EM_addr();
memcpy(emCARD + blockNum * blockBtWidth, data, blocksCount * blockBtWidth);
} }
void emlGetMem(uint8_t *data, int blockNum, int blocksCount) { void emlGetMem(uint8_t *data, int blockNum, int blocksCount) {
uint8_t *emCARD = BigBuf_get_EM_addr(); uint8_t *mem = BigBuf_get_EM_addr();
memcpy(data, emCARD + blockNum * 16, blocksCount * 16); memcpy(data, mem + blockNum * 16, blocksCount * 16);
} }
void emlGetMemBt(uint8_t *data, int offset, int byteCount) { void emlGetMemBt(uint8_t *data, int offset, int byteCount) {
uint8_t *emCARD = BigBuf_get_EM_addr(); uint8_t *mem = BigBuf_get_EM_addr();
memcpy(data, emCARD + offset, byteCount); memcpy(data, mem + offset, byteCount);
} }
int emlCheckValBl(int blockNum) { int emlCheckValBl(int blockNum) {
uint8_t *emCARD = BigBuf_get_EM_addr(); uint8_t *mem = BigBuf_get_EM_addr();
uint8_t *data = emCARD + blockNum * 16; uint8_t *data = mem + blockNum * 16;
if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) || if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) ||
(data[1] != (data[5] ^ 0xff)) || (data[1] != data[9]) || (data[1] != (data[5] ^ 0xff)) || (data[1] != data[9]) ||
@ -649,8 +652,8 @@ int emlCheckValBl(int blockNum) {
} }
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) { int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) {
uint8_t *emCARD = BigBuf_get_EM_addr(); uint8_t *mem = BigBuf_get_EM_addr();
uint8_t *data = emCARD + blockNum * 16; uint8_t *data = mem + blockNum * 16;
if (emlCheckValBl(blockNum)) if (emlCheckValBl(blockNum))
return 1; return 1;
@ -661,8 +664,8 @@ int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) {
} }
int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) { int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) {
uint8_t *emCARD = BigBuf_get_EM_addr(); uint8_t *mem = BigBuf_get_EM_addr();
uint8_t *data = emCARD + blockNum * 16; uint8_t *data = mem + blockNum * 16;
memcpy(data + 0, &blReg, 4); memcpy(data + 0, &blReg, 4);
memcpy(data + 8, &blReg, 4); memcpy(data + 8, &blReg, 4);
@ -673,41 +676,43 @@ int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) {
data[13] = blBlock ^ 0xff; data[13] = blBlock ^ 0xff;
data[14] = blBlock; data[14] = blBlock;
data[15] = blBlock ^ 0xff; data[15] = blBlock ^ 0xff;
return 0; return 0;
} }
uint64_t emlGetKey(int sectorNum, int keyType) { uint64_t emlGetKey(int sectorNum, int keyType) {
uint8_t key[6] = {0x00}; uint8_t key[6] = {0x00};
uint8_t *em = BigBuf_get_EM_addr(); uint8_t *mem = BigBuf_get_EM_addr();
memcpy(key, em + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6); memcpy(key, mem + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6);
return bytes_to_num(key, 6); return bytes_to_num(key, 6);
} }
void emlClearMem(void) { void emlClearMem(void) {
const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04}; const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04};
uint8_t *emCARD = BigBuf_get_EM_addr(); uint8_t *mem = BigBuf_get_EM_addr();
memset(emCARD, 0, CARD_MEMORY_SIZE); memset(mem, 0, CARD_MEMORY_SIZE);
// fill sectors trailer data // fill sectors trailer data
for (uint16_t b = 3; b < MIFARE_4K_MAXBLOCK; ((b < MIFARE_2K_MAXBLOCK - 4) ? (b += 4) : (b += 16))) for (uint16_t b = 3; b < MIFARE_4K_MAXBLOCK; ((b < MIFARE_2K_MAXBLOCK - 4) ? (b += 4) : (b += 16))) {
emlSetMem((uint8_t *)trailer, b, 1); emlSetMem_xt((uint8_t *)trailer, b, 1, 16);
}
// uid // uid
emlSetMem((uint8_t *)uid, 0, 1); emlSetMem_xt((uint8_t *)uid, 0, 1, 16);
return; return;
} }
uint8_t SectorTrailer(uint8_t blockNo) { uint8_t SectorTrailer(uint8_t blockNo) {
if (blockNo <= MIFARE_2K_MAXBLOCK) { if (blockNo <= MIFARE_2K_MAXBLOCK) {
if (g_dbglevel >= DBG_EXTENDED) if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x03)); Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x03));
}
return (blockNo | 0x03); return (blockNo | 0x03);
} else { } else {
if (g_dbglevel >= DBG_EXTENDED) if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x0f)); Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x0F));
return (blockNo | 0x0f); }
return (blockNo | 0x0F);
} }
} }

View file

@ -113,8 +113,7 @@ uint8_t SectorTrailer(uint8_t blockNo);
// emulator functions // emulator functions
void emlClearMem(void); void emlClearMem(void);
void emlSetMem(uint8_t *data, int blockNum, int blocksCount); void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int block_width);
void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth);
void emlGetMem(uint8_t *data, int blockNum, int blocksCount); void emlGetMem(uint8_t *data, int blockNum, int blocksCount);
void emlGetMemBt(uint8_t *data, int offset, int byteCount); void emlGetMemBt(uint8_t *data, int offset, int byteCount);
uint64_t emlGetKey(int sectorNum, int keyType); uint64_t emlGetKey(int sectorNum, int keyType);

View file

@ -196,17 +196,19 @@ int rdv40_spiffs_check(void) {
///// Base RDV40_SPIFFS_SAFETY_NORMAL operations//////////////////////////////// ///// Base RDV40_SPIFFS_SAFETY_NORMAL operations////////////////////////////////
void write_to_spiffs(const char *filename, uint8_t *src, uint32_t size) { void write_to_spiffs(const char *filename, const uint8_t *src, uint32_t size) {
spiffs_file fd = SPIFFS_open(&fs, filename, SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0); spiffs_file fd = SPIFFS_open(&fs, filename, SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0);
if (SPIFFS_write(&fs, fd, src, size) < 0) { // Note: SPIFFS_write() doesn't declare third parameter as const (but should)
if (SPIFFS_write(&fs, fd, (void *)src, size) < 0) {
Dbprintf("wr errno %i\n", SPIFFS_errno(&fs)); Dbprintf("wr errno %i\n", SPIFFS_errno(&fs));
} }
SPIFFS_close(&fs, fd); SPIFFS_close(&fs, fd);
} }
void append_to_spiffs(const char *filename, uint8_t *src, uint32_t size) { void append_to_spiffs(const char *filename, const uint8_t *src, uint32_t size) {
spiffs_file fd = SPIFFS_open(&fs, filename, SPIFFS_APPEND | SPIFFS_RDWR, 0); spiffs_file fd = SPIFFS_open(&fs, filename, SPIFFS_APPEND | SPIFFS_RDWR, 0);
if (SPIFFS_write(&fs, fd, src, size) < 0) { // Note: SPIFFS_write() doesn't declare third parameter as const (but should)
if (SPIFFS_write(&fs, fd, (void *)src, size) < 0) {
Dbprintf("errno %i\n", SPIFFS_errno(&fs)); Dbprintf("errno %i\n", SPIFFS_errno(&fs));
} }
SPIFFS_close(&fs, fd); SPIFFS_close(&fs, fd);
@ -310,10 +312,10 @@ static int is_valid_filename(const char *filename) {
} }
*/ */
static void copy_in_spiffs(const char *src, const char *dst) { static void copy_in_spiffs(const char *src, const char *dst) {
uint32_t size = size_in_spiffs((char *)src); uint32_t size = size_in_spiffs(src);
uint8_t *mem = BigBuf_malloc(size); uint8_t *mem = BigBuf_malloc(size);
read_from_spiffs((char *)src, (uint8_t *)mem, size); read_from_spiffs(src, (uint8_t *)mem, size);
write_to_spiffs((char *)dst, (uint8_t *)mem, size); write_to_spiffs(dst, (uint8_t *)mem, size);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -434,7 +436,7 @@ int rdv40_spiffs_lazy_mount_rollback(int changed) {
// TODO : forbid writing to a filename which already exists as lnk ! // TODO : forbid writing to a filename which already exists as lnk !
// TODO : forbid writing to a filename.lnk which already exists without lnk ! // TODO : forbid writing to a filename.lnk which already exists without lnk !
// Note: Writing in SPIFFS_WRITE_CHUNK_SIZE (8192) byte chucks helps to ensure "free space" has been erased by GC (Garbage collection) // Note: Writing in SPIFFS_WRITE_CHUNK_SIZE (8192) byte chucks helps to ensure "free space" has been erased by GC (Garbage collection)
int rdv40_spiffs_write(const char *filename, uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level) { int rdv40_spiffs_write(const char *filename, const uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level) {
RDV40_SPIFFS_SAFE_FUNCTION( RDV40_SPIFFS_SAFE_FUNCTION(
uint32_t idx; uint32_t idx;
if (size <= SPIFFS_WRITE_CHUNK_SIZE) { if (size <= SPIFFS_WRITE_CHUNK_SIZE) {
@ -457,7 +459,7 @@ int rdv40_spiffs_write(const char *filename, uint8_t *src, uint32_t size, RDV40S
) )
} }
int rdv40_spiffs_append(const char *filename, uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level) { int rdv40_spiffs_append(const char *filename, const uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level) {
RDV40_SPIFFS_SAFE_FUNCTION( RDV40_SPIFFS_SAFE_FUNCTION(
uint32_t idx; uint32_t idx;
// Append any SPIFFS_WRITE_CHUNK_SIZE byte chunks // Append any SPIFFS_WRITE_CHUNK_SIZE byte chunks
@ -480,26 +482,26 @@ int rdv40_spiffs_read(const char *filename, uint8_t *dst, uint32_t size, RDV40Sp
// TODO : forbid writing to a filename which already exists as lnk ! // TODO : forbid writing to a filename which already exists as lnk !
// TODO : forbid writing to a filename.lnk which already exists without lnk ! // TODO : forbid writing to a filename.lnk which already exists without lnk !
int rdv40_spiffs_rename(char *old_filename, char *new_filename, RDV40SpiFFSSafetyLevel level) { int rdv40_spiffs_rename(const char *old_filename, const char *new_filename, RDV40SpiFFSSafetyLevel level) {
RDV40_SPIFFS_SAFE_FUNCTION( // RDV40_SPIFFS_SAFE_FUNCTION( //
rename_in_spiffs(old_filename, new_filename); // rename_in_spiffs(old_filename, new_filename); //
) )
} }
int rdv40_spiffs_remove(char *filename, RDV40SpiFFSSafetyLevel level) { int rdv40_spiffs_remove(const char *filename, RDV40SpiFFSSafetyLevel level) {
RDV40_SPIFFS_SAFE_FUNCTION( // RDV40_SPIFFS_SAFE_FUNCTION( //
remove_from_spiffs(filename); // remove_from_spiffs(filename); //
) )
} }
int rdv40_spiffs_copy(char *src, char *dst, RDV40SpiFFSSafetyLevel level) { int rdv40_spiffs_copy(const char *src_filename, const char *dst_filename, RDV40SpiFFSSafetyLevel level) {
RDV40_SPIFFS_SAFE_FUNCTION( // RDV40_SPIFFS_SAFE_FUNCTION( //
copy_in_spiffs(src, dst); // copy_in_spiffs(src_filename, dst_filename); //
) )
} }
int rdv40_spiffs_stat(char *filename, uint32_t *buf, RDV40SpiFFSSafetyLevel level) { int rdv40_spiffs_stat(const char *filename, uint32_t *size_in_bytes, RDV40SpiFFSSafetyLevel level) {
RDV40_SPIFFS_SAFE_FUNCTION( // RDV40_SPIFFS_SAFE_FUNCTION( //
*buf = size_in_spiffs(filename); // *size_in_bytes = size_in_spiffs(filename); //
) )
} }
@ -530,7 +532,7 @@ int rdv40_spiffs_is_symlink(const char *s) {
// symlink ?") // symlink ?")
// ATTENTION : you must NOT provide the whole filename (so please do not include the .lnk extension) // ATTENTION : you must NOT provide the whole filename (so please do not include the .lnk extension)
// TODO : integrate in read_function // TODO : integrate in read_function
int rdv40_spiffs_read_as_symlink(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level) { int rdv40_spiffs_read_as_symlink(const char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level) {
RDV40_SPIFFS_SAFE_FUNCTION( RDV40_SPIFFS_SAFE_FUNCTION(
char linkdest[SPIFFS_OBJ_NAME_LEN]; char linkdest[SPIFFS_OBJ_NAME_LEN];
@ -538,7 +540,7 @@ int rdv40_spiffs_read_as_symlink(char *filename, uint8_t *dst, uint32_t size, RD
sprintf(linkfilename, "%s.lnk", filename); sprintf(linkfilename, "%s.lnk", filename);
if (g_dbglevel >= DBG_DEBUG) if (g_dbglevel >= DBG_DEBUG)
Dbprintf("Linkk real filename is " _YELLOW_("%s"), linkfilename); Dbprintf("Link real filename is " _YELLOW_("%s"), linkfilename);
read_from_spiffs((char *)linkfilename, (uint8_t *)linkdest, SPIFFS_OBJ_NAME_LEN); read_from_spiffs((char *)linkfilename, (uint8_t *)linkdest, SPIFFS_OBJ_NAME_LEN);
@ -561,11 +563,11 @@ int rdv40_spiffs_read_as_symlink(char *filename, uint8_t *dst, uint32_t size, RD
// which you can then read back with : // which you can then read back with :
// rdv40_spiffs_read_as_symlink((uint8_t *)"world",(uint8_t *) buffer, orig_file_size, RDV40_SPIFFS_SAFETY_SAFE); // rdv40_spiffs_read_as_symlink((uint8_t *)"world",(uint8_t *) buffer, orig_file_size, RDV40_SPIFFS_SAFETY_SAFE);
// TODO : FORBID creating a symlink with a basename (before.lnk) which already exists as a file ! // TODO : FORBID creating a symlink with a basename (before.lnk) which already exists as a file !
int rdv40_spiffs_make_symlink(char *linkdest, char *filename, RDV40SpiFFSSafetyLevel level) { int rdv40_spiffs_make_symlink(const char *linkdest, const char *filename, RDV40SpiFFSSafetyLevel level) {
RDV40_SPIFFS_SAFE_FUNCTION( RDV40_SPIFFS_SAFE_FUNCTION(
char linkfilename[SPIFFS_OBJ_NAME_LEN]; char linkfilename[SPIFFS_OBJ_NAME_LEN];
sprintf(linkfilename, "%s.lnk", filename); sprintf(linkfilename, "%s.lnk", filename);
write_to_spiffs((char *)linkfilename, (uint8_t *)linkdest, SPIFFS_OBJ_NAME_LEN); write_to_spiffs(linkfilename, (const uint8_t *)linkdest, SPIFFS_OBJ_NAME_LEN);
) )
} }
@ -575,15 +577,15 @@ int rdv40_spiffs_make_symlink(char *linkdest, char *filename, RDV40SpiFFSSafetyL
// Still, this case won't happen when the write(s) functions will check for both symlink and real file // Still, this case won't happen when the write(s) functions will check for both symlink and real file
// preexistence, avoiding a link being created if filename exists, or avoiding a file being created if // preexistence, avoiding a link being created if filename exists, or avoiding a file being created if
// symlink exists with same name // symlink exists with same name
int rdv40_spiffs_read_as_filetype(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level) { int rdv40_spiffs_read_as_filetype(const char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level) {
RDV40_SPIFFS_SAFE_FUNCTION( RDV40_SPIFFS_SAFE_FUNCTION(
RDV40SpiFFSFileType filetype = filetype_in_spiffs((char *)filename); RDV40SpiFFSFileType filetype = filetype_in_spiffs((char *)filename);
switch (filetype) { switch (filetype) {
case RDV40_SPIFFS_FILETYPE_REAL: case RDV40_SPIFFS_FILETYPE_REAL:
rdv40_spiffs_read((char *)filename, (uint8_t *)dst, size, level); rdv40_spiffs_read(filename, dst, size, level);
break; break;
case RDV40_SPIFFS_FILETYPE_SYMLINK: case RDV40_SPIFFS_FILETYPE_SYMLINK:
rdv40_spiffs_read_as_symlink(filename, (uint8_t *)dst, size, level); rdv40_spiffs_read_as_symlink(filename, dst, size, level);
break; break;
case RDV40_SPIFFS_FILETYPE_BOTH: case RDV40_SPIFFS_FILETYPE_BOTH:
case RDV40_SPIFFS_FILETYPE_UNKNOWN: case RDV40_SPIFFS_FILETYPE_UNKNOWN:

View file

@ -46,18 +46,18 @@ typedef struct rdv40_spiffs_fsinfo {
uint32_t usedPercent, freePercent; uint32_t usedPercent, freePercent;
} rdv40_spiffs_fsinfo; } rdv40_spiffs_fsinfo;
int rdv40_spiffs_read_as_filetype(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level); int rdv40_spiffs_read_as_filetype(const char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level);
int rdv40_spiffs_check(void); int rdv40_spiffs_check(void);
int rdv40_spiffs_lazy_unmount(void); int rdv40_spiffs_lazy_unmount(void);
int rdv40_spiffs_lazy_mount(void); int rdv40_spiffs_lazy_mount(void);
int rdv40_spiffs_lazy_mount_rollback(int changed); int rdv40_spiffs_lazy_mount_rollback(int changed);
int rdv40_spiffs_write(const char *filename, uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level); int rdv40_spiffs_write(const char *filename, const uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level);
int rdv40_spiffs_read(const char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level); int rdv40_spiffs_read(const char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level);
int rdv40_spiffs_rename(char *old_filename, char *new_filename, RDV40SpiFFSSafetyLevel level); int rdv40_spiffs_rename(const char *old_filename, const char *new_filename, RDV40SpiFFSSafetyLevel level);
int rdv40_spiffs_remove(char *filename, RDV40SpiFFSSafetyLevel level); int rdv40_spiffs_remove(const char *filename, RDV40SpiFFSSafetyLevel level);
int rdv40_spiffs_read_as_symlink(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level); int rdv40_spiffs_read_as_symlink(const char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level);
void write_to_spiffs(const char *filename, uint8_t *src, uint32_t size); void write_to_spiffs(const char *filename, const uint8_t *src, uint32_t size);
void read_from_spiffs(const char *filename, uint8_t *dst, uint32_t size); void read_from_spiffs(const char *filename, uint8_t *dst, uint32_t size);
void test_spiffs(void); void test_spiffs(void);
void rdv40_spiffs_safe_print_tree(void); void rdv40_spiffs_safe_print_tree(void);
@ -65,11 +65,11 @@ int rdv40_spiffs_unmount(void);
int rdv40_spiffs_mount(void); int rdv40_spiffs_mount(void);
int rdv40_spiffs_is_symlink(const char *s); int rdv40_spiffs_is_symlink(const char *s);
void rdv40_spiffs_safe_print_fsinfo(void); void rdv40_spiffs_safe_print_fsinfo(void);
int rdv40_spiffs_make_symlink(char *linkdest, char *filename, RDV40SpiFFSSafetyLevel level); int rdv40_spiffs_make_symlink(const char *linkdest, const char *filename, RDV40SpiFFSSafetyLevel level);
void append_to_spiffs(const char *filename, uint8_t *src, uint32_t size); void append_to_spiffs(const char *filename, const uint8_t *src, uint32_t size);
int rdv40_spiffs_copy(char *src, char *dst, RDV40SpiFFSSafetyLevel level); int rdv40_spiffs_copy(const char *src_filename, const char *dst_filename, RDV40SpiFFSSafetyLevel level);
int rdv40_spiffs_append(const char *filename, uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level); int rdv40_spiffs_append(const char *filename, const uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level);
int rdv40_spiffs_stat(char *filename, uint32_t *buf, RDV40SpiFFSSafetyLevel level); int rdv40_spiffs_stat(const char *filename, uint32_t *size_in_bytes, RDV40SpiFFSSafetyLevel level);
uint32_t size_in_spiffs(const char *filename); uint32_t size_in_spiffs(const char *filename);
int exists_in_spiffs(const char *filename); int exists_in_spiffs(const char *filename);

View file

@ -18,6 +18,34 @@
#include "usart.h" #include "usart.h"
#include "proxmark3_arm.h" #include "proxmark3_arm.h"
#define Dbprintf_usb(...) {\
bool tmpfpc = g_reply_via_fpc;\
bool tmpusb = g_reply_via_usb;\
g_reply_via_fpc = false;\
g_reply_via_usb = true;\
Dbprintf(__VA_ARGS__);\
g_reply_via_fpc = tmpfpc;\
g_reply_via_usb = tmpusb;}
#define Dbprintf_fpc(...) {\
bool tmpfpc = g_reply_via_fpc;\
bool tmpusb = g_reply_via_usb;\
g_reply_via_fpc = true;\
g_reply_via_usb = false;\
Dbprintf(__VA_ARGS__);\
g_reply_via_fpc = tmpfpc;\
g_reply_via_usb = tmpusb;}
#define Dbprintf_all(...) {\
bool tmpfpc = g_reply_via_fpc;\
bool tmpusb = g_reply_via_usb;\
g_reply_via_fpc = true;\
g_reply_via_usb = true;\
Dbprintf(__VA_ARGS__);\
g_reply_via_fpc = tmpfpc;\
g_reply_via_usb = tmpusb;}
static volatile AT91PS_USART pUS1 = AT91C_BASE_US1; static volatile AT91PS_USART pUS1 = AT91C_BASE_US1;
static volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; static volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA;
static volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_US1; static volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_US1;

View file

@ -53,10 +53,10 @@ INSTALLFW = $(OBJDIR)/bootrom.elf
OBJS = $(OBJDIR)/bootrom.s19 OBJS = $(OBJDIR)/bootrom.s19
# version_pm3.c should be remade on every compilation # version_pm3.c should be checked on every compilation
version_pm3.c: default_version_pm3.c .FORCE version_pm3.c: default_version_pm3.c .FORCE
$(info [=] GEN $@) $(info [=] CHECK $@)
$(Q)$(SH) ../tools/mkversion.sh > $@ || $(PERL) ../tools/mkversion.pl > $@ || $(CP) $< $@ $(Q)$(SH) ../tools/mkversion.sh $@ || $(CP) $< $@
all: showinfo $(OBJS) all: showinfo $(OBJS)

View file

@ -96,11 +96,12 @@ if (CMAKE_TOOLCHAIN_FILE)
endif (ANDROID) endif (ANDROID)
set(EMBED_READLINE ON) set(EMBED_READLINE ON)
set(EMBED_BZIP2 ON) set(EMBED_BZIP2 ON)
set(EMBED_LZ4 ON)
endif (CMAKE_TOOLCHAIN_FILE) endif (CMAKE_TOOLCHAIN_FILE)
if (EMBED_READLINE OR EMBED_BZIP2) if (EMBED_READLINE OR EMBED_BZIP2 OR EMBED_LZ4)
include(ExternalProject) include(ExternalProject)
endif (EMBED_READLINE OR EMBED_BZIP2) endif (EMBED_READLINE OR EMBED_BZIP2 OR EMBED_LZ4)
if (NOT SKIPREADLINE EQUAL 1) if (NOT SKIPREADLINE EQUAL 1)
if (APPLE) if (APPLE)
@ -162,6 +163,7 @@ if (NOT SKIPJANSSONSYSTEM EQUAL 1)
endif (NOT SKIPJANSSONSYSTEM EQUAL 1) endif (NOT SKIPJANSSONSYSTEM EQUAL 1)
if(EMBED_BZIP2) if(EMBED_BZIP2)
cmake_policy(SET CMP0114 NEW)
set(BZIP2_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/bzip2/src/bzip2) set(BZIP2_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/bzip2/src/bzip2)
# Specify SOURCE_DIR will cause some errors # Specify SOURCE_DIR will cause some errors
ExternalProject_Add(bzip2 ExternalProject_Add(bzip2
@ -183,6 +185,34 @@ else(EMBED_BZIP2)
find_package (BZip2 REQUIRED) find_package (BZip2 REQUIRED)
endif(EMBED_BZIP2) endif(EMBED_BZIP2)
if(EMBED_LZ4)
cmake_policy(SET CMP0114 NEW)
set(LZ4_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/lz4/src/lz4)
# Specify SOURCE_DIR will cause some errors
ExternalProject_Add(lz4
GIT_REPOSITORY https://android.googlesource.com/platform/external/lz4
GIT_TAG platform-tools-30.0.2
PREFIX deps/lz4
# SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/lz4
CONFIGURE_COMMAND mkdir -p ${LZ4_BUILD_DIR} && git archive --format tar HEAD | tar -C ${LZ4_BUILD_DIR} -x
BUILD_IN_SOURCE ON
BUILD_COMMAND make -C ${LZ4_BUILD_DIR}/lib -j4 CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} liblz4.a
INSTALL_COMMAND ""
LOG_DOWNLOAD ON
)
ExternalProject_Add_StepTargets(lz4 configure build install)
set(LZ4_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/deps/lz4/src/lz4/lib)
set(LZ4_LIBRARIES ${CMAKE_CURRENT_BINARY_DIR}/deps/lz4/src/lz4/lib/liblz4.a)
set(LZ4_FOUND ON)
else(EMBED_LZ4)
find_path(LZ4_INCLUDE_DIRS lz4frame.h)
find_library(LZ4_LIBRARIES lz4)
endif(EMBED_LZ4)
if (LZ4_INCLUDE_DIRS AND LZ4_LIBRARIES)
set(LZ4_FOUND ON)
endif (LZ4_INCLUDE_DIRS AND LZ4_LIBRARIES)
if (NOT SKIPWHEREAMISYSTEM EQUAL 1) if (NOT SKIPWHEREAMISYSTEM EQUAL 1)
find_path(WHEREAMI_INCLUDE_DIRS whereami.h) find_path(WHEREAMI_INCLUDE_DIRS whereami.h)
find_library(WHEREAMI_LIBRARIES whereami) find_library(WHEREAMI_LIBRARIES whereami)
@ -349,6 +379,7 @@ set (TARGET_SOURCES
${PM3_ROOT}/client/src/fileutils.c ${PM3_ROOT}/client/src/fileutils.c
${PM3_ROOT}/client/src/flash.c ${PM3_ROOT}/client/src/flash.c
${PM3_ROOT}/client/src/graph.c ${PM3_ROOT}/client/src/graph.c
${PM3_ROOT}/client/src/iso4217.c
${PM3_ROOT}/client/src/jansson_path.c ${PM3_ROOT}/client/src/jansson_path.c
${PM3_ROOT}/client/src/preferences.c ${PM3_ROOT}/client/src/preferences.c
${PM3_ROOT}/client/src/pm3.c ${PM3_ROOT}/client/src/pm3.c
@ -366,7 +397,7 @@ set (TARGET_SOURCES
add_custom_command( add_custom_command(
OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c
COMMAND sh ${PM3_ROOT}/tools/mkversion.sh > ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c COMMAND sh ${PM3_ROOT}/tools/mkversion.sh ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c
DEPENDS ${PM3_ROOT}/common/default_version_pm3.c DEPENDS ${PM3_ROOT}/common/default_version_pm3.c
) )
@ -456,6 +487,11 @@ if (BZIP2_FOUND)
set(ADDITIONAL_LNK ${BZIP2_LIBRARIES} ${ADDITIONAL_LNK}) set(ADDITIONAL_LNK ${BZIP2_LIBRARIES} ${ADDITIONAL_LNK})
endif (BZIP2_FOUND) endif (BZIP2_FOUND)
if (LZ4_FOUND)
set(ADDITIONAL_DIRS ${LZ4_INCLUDE_DIRS} ${ADDITIONAL_DIRS})
set(ADDITIONAL_LNK ${LZ4_LIBRARIES} ${ADDITIONAL_LNK})
endif (LZ4_FOUND)
if (WHEREAMI_FOUND) if (WHEREAMI_FOUND)
set(ADDITIONAL_DIRS ${WHEREAMI_INCLUDE_DIRS} ${ADDITIONAL_DIRS}) set(ADDITIONAL_DIRS ${WHEREAMI_INCLUDE_DIRS} ${ADDITIONAL_DIRS})
set(ADDITIONAL_LNK ${WHEREAMI_LIBRARIES} ${ADDITIONAL_LNK}) set(ADDITIONAL_LNK ${WHEREAMI_LIBRARIES} ${ADDITIONAL_LNK})
@ -488,11 +524,25 @@ else (SKIPBT EQUAL 1)
endif (BLUEZ_FOUND) endif (BLUEZ_FOUND)
endif(SKIPBT EQUAL 1) endif(SKIPBT EQUAL 1)
if (BZIP2_FOUND)
if (EMBED_BZIP2) if (EMBED_BZIP2)
message(STATUS "Bzip2 library: embedded") message(STATUS "Bzip2 library: embedded")
else (EMBED_BZIP2) else (EMBED_BZIP2)
message(STATUS "Bzip2 library: system library found") message(STATUS "Bzip2 library: system library found")
endif (EMBED_BZIP2) endif (EMBED_BZIP2)
else (BZIP2_FOUND)
message(SEND_ERROR "Bzip2 library: Bzip2 not found")
endif (BZIP2_FOUND)
if (LZ4_FOUND)
if (EMBED_LZ4)
message(STATUS "LZ4 library: embedded")
else (EMBED_LZ4)
message(STATUS "LZ4 library: system library found")
endif (EMBED_LZ4)
else (LZ4_FOUND)
message(SEND_ERROR "LZ4 library: LZ4 not found")
endif (LZ4_FOUND)
if (SKIPJANSSONSYSTEM EQUAL 1) if (SKIPJANSSONSYSTEM EQUAL 1)
message(STATUS "Jansson library: local library forced") message(STATUS "Jansson library: local library forced")
@ -592,6 +642,9 @@ endif (EMBED_READLINE)
if (EMBED_BZIP2) if (EMBED_BZIP2)
add_dependencies(proxmark3 bzip2) add_dependencies(proxmark3 bzip2)
endif (EMBED_BZIP2) endif (EMBED_BZIP2)
if (EMBED_LZ4)
add_dependencies(proxmark3 lz4)
endif (EMBED_LZ4)
if (MINGW) if (MINGW)
# Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z) # Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z)
@ -603,6 +656,10 @@ if (MINGW)
set(CMAKE_C_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_C_FLAGS}") set(CMAKE_C_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_CXX_FLAGS}")
# link Winsock2
set(ADDITIONAL_LNK ws2_32 ${ADDITIONAL_LNK})
endif (MINGW)
# GCC 10 has issues with false positives on stringop-overflow, # GCC 10 has issues with false positives on stringop-overflow,
# let's disable them for now (cf https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92955, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94335) # let's disable them for now (cf https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92955, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94335)
# beware these flags didn't exist for GCC < 7 # beware these flags didn't exist for GCC < 7
@ -614,10 +671,6 @@ if (MINGW)
endif() endif()
endif(CMAKE_COMPILER_IS_GNUCXX) endif(CMAKE_COMPILER_IS_GNUCXX)
# link Winsock2
set(ADDITIONAL_LNK ws2_32 ${ADDITIONAL_LNK})
endif (MINGW)
target_include_directories(proxmark3 PRIVATE target_include_directories(proxmark3 PRIVATE
${PM3_ROOT}/common ${PM3_ROOT}/common
${PM3_ROOT}/common_fpga ${PM3_ROOT}/common_fpga

View file

@ -40,7 +40,7 @@ ifeq ($(USE_BREW),1)
PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(BREW_PREFIX)/lib/pkgconfig:$(BREW_PREFIX)/opt/qt/lib/pkgconfig:$(BREW_PREFIX)/opt/qt5/lib/pkgconfig PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(BREW_PREFIX)/lib/pkgconfig:$(BREW_PREFIX)/opt/qt/lib/pkgconfig:$(BREW_PREFIX)/opt/qt5/lib/pkgconfig
endif endif
ifdef ($(USE_MACPORTS),1) ifeq ($(USE_MACPORTS),1)
INCLUDES += -I$(MACPORTS_PREFIX)/include INCLUDES += -I$(MACPORTS_PREFIX)/include
LDLIBS += -L$(MACPORTS_PREFIX)/lib LDLIBS += -L$(MACPORTS_PREFIX)/lib
PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(MACPORTS_PREFIX)/lib/pkgconfig PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(MACPORTS_PREFIX)/lib/pkgconfig
@ -242,6 +242,9 @@ endif
## BZIP2 ## BZIP2
LDLIBS += -lbz2 LDLIBS += -lbz2
## LZ4
LDLIBS += -llz4
## Bluez (optional) ## Bluez (optional)
ifneq ($(SKIPBT),1) ifneq ($(SKIPBT),1)
BTINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags bluez 2>/dev/null) BTINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags bluez 2>/dev/null)
@ -678,6 +681,7 @@ SRCS = mifare/aiddesfire.c \
generator.c \ generator.c \
graph.c \ graph.c \
jansson_path.c \ jansson_path.c \
iso4217.c \
iso7816/apduinfo.c \ iso7816/apduinfo.c \
iso7816/iso7816core.c \ iso7816/iso7816core.c \
loclass/cipher.c \ loclass/cipher.c \
@ -777,10 +781,14 @@ proxmark3: $(OBJS) $(STATICLIBS) lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lu
src/proxgui.cpp: src/ui/ui_overlays.h src/ui/ui_image.h src/proxgui.cpp: src/ui/ui_overlays.h src/ui/ui_image.h
src/proxguiqt.cpp: src/proxguiqt.h
src/proxguiqt.moc.cpp: src/proxguiqt.h src/proxguiqt.moc.cpp: src/proxguiqt.h
$(info [-] MOC $@) $(info [-] MOC $@)
$(Q)$(MOC) -o$@ $^ $(Q)$(MOC) -o$@ $^
src/proxguiqt.h: src/ui/ui_overlays.h src/ui/ui_image.h
src/ui/ui_overlays.h: src/ui/overlays.ui src/ui/ui_overlays.h: src/ui/overlays.ui
$(info [-] UIC $@) $(info [-] UIC $@)
$(Q)$(UIC) $^ > $@ $(Q)$(UIC) $^ > $@
@ -910,10 +918,10 @@ src/pm3_pywrap.c: pm3.i
.PHONY: all clean install uninstall tarbin .FORCE .PHONY: all clean install uninstall tarbin .FORCE
# version_pm3.c should be remade on every compilation # version_pm3.c should be checked on every compilation
src/version_pm3.c: default_version_pm3.c .FORCE src/version_pm3.c: default_version_pm3.c .FORCE
$(info [=] GEN $@) $(info [=] CHECK $@)
$(Q)$(SH) ../tools/mkversion.sh > $@ || $(CP) $< $@ $(Q)$(SH) ../tools/mkversion.sh $@ || $(CP) $< $@
# easy printing of MAKE VARIABLES # easy printing of MAKE VARIABLES
print-%: ; @echo $* = $($*) print-%: ; @echo $* = $($*)

View file

@ -371,7 +371,7 @@ uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, statel
for (uint32_t tests = 0; tests < nonces_to_bruteforce; ++tests) { for (uint32_t tests = 0; tests < nonces_to_bruteforce; ++tests) {
// common bits with preceding test nonce // common bits with preceding test nonce
uint32_t common_bits = next_common_bits; //tests ? trailing_zeros(bf_test_nonce_2nd_byte[tests] ^ bf_test_nonce_2nd_byte[tests-1]) : 0; uint32_t common_bits = next_common_bits; //tests ? trailing_zeros(bf_test_nonce_2nd_byte[tests] ^ bf_test_nonce_2nd_byte[tests-1]) : 0;
next_common_bits = tests < nonces_to_bruteforce - 1 ? trailing_zeros(bf_test_nonce_2nd_byte[tests] ^ bf_test_nonce_2nd_byte[tests + 1]) : 0; next_common_bits = (tests < nonces_to_bruteforce - 1) ? trailing_zeros(bf_test_nonce_2nd_byte[tests] ^ bf_test_nonce_2nd_byte[tests + 1]) : 0;
uint32_t parity_bit_idx = 1; // start checking with the parity of second nonce byte uint32_t parity_bit_idx = 1; // start checking with the parity of second nonce byte
bitslice_value_t fb_bits = fbb[common_bits]; // start with precomputed feedback bits from previous nonce bitslice_value_t fb_bits = fbb[common_bits]; // start with precomputed feedback bits from previous nonce
bitslice_value_t ks_bits = ksb[common_bits]; // dito for first keystream bits bitslice_value_t ks_bits = ksb[common_bits]; // dito for first keystream bits

View file

@ -96,7 +96,7 @@ static uint32_t keys_found = 0;
static uint64_t num_keys_tested; static uint64_t num_keys_tested;
static uint64_t found_bs_key = 0; static uint64_t found_bs_key = 0;
inline uint8_t trailing_zeros(uint8_t byte) { uint8_t trailing_zeros(uint8_t byte) {
static const uint8_t trailing_zeros_LUT[256] = { static const uint8_t trailing_zeros_LUT[256] = {
8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
@ -304,12 +304,13 @@ static bool ensure_buckets_alloc(size_t need_buckets) {
while (need_buckets > alloc_sz) { while (need_buckets > alloc_sz) {
alloc_sz *= 2; alloc_sz *= 2;
} }
statelist_t **new_buckets = realloc(buckets, sizeof(statelist_t *) * alloc_sz);
buckets = realloc(buckets, sizeof(statelist_t *) * alloc_sz); if (new_buckets == NULL) {
if (buckets == NULL) { free(buckets);
buckets_allocated = 0; buckets_allocated = 0;
return false; return false;
} }
buckets = new_buckets;
memset(buckets + buckets_allocated, 0, (alloc_sz - buckets_allocated) * sizeof(statelist_t *)); memset(buckets + buckets_allocated, 0, (alloc_sz - buckets_allocated) * sizeof(statelist_t *));
buckets_allocated = alloc_sz; buckets_allocated = alloc_sz;
} }
@ -412,11 +413,14 @@ static bool read_bench_data(statelist_t *test_candidates) {
return false; return false;
} }
free(path); free(path);
bytes_read = fread(&nonces_to_bruteforce, 1, sizeof(nonces_to_bruteforce), benchfile);
if (bytes_read != sizeof(nonces_to_bruteforce)) { // read 4 bytes of data ?
bytes_read = fread(&nonces_to_bruteforce, 1, sizeof(uint32_t), benchfile);
if (bytes_read != sizeof(uint32_t) || (nonces_to_bruteforce >= 256)) {
fclose(benchfile); fclose(benchfile);
return false; return false;
} }
for (uint32_t i = 0; i < nonces_to_bruteforce && i < 256; i++) { for (uint32_t i = 0; i < nonces_to_bruteforce && i < 256; i++) {
bytes_read = fread(&bf_test_nonce[i], 1, sizeof(uint32_t), benchfile); bytes_read = fread(&bf_test_nonce[i], 1, sizeof(uint32_t), benchfile);
if (bytes_read != sizeof(uint32_t)) { if (bytes_read != sizeof(uint32_t)) {
@ -430,11 +434,13 @@ static bool read_bench_data(statelist_t *test_candidates) {
return false; return false;
} }
} }
bytes_read = fread(&num_states, 1, sizeof(uint32_t), benchfile); bytes_read = fread(&num_states, 1, sizeof(uint32_t), benchfile);
if (bytes_read != sizeof(uint32_t)) { if (bytes_read != sizeof(uint32_t)) {
fclose(benchfile); fclose(benchfile);
return false; return false;
} }
for (states_read = 0; states_read < MIN(num_states, TEST_BENCH_SIZE); states_read++) { for (states_read = 0; states_read < MIN(num_states, TEST_BENCH_SIZE); states_read++) {
bytes_read = fread(test_candidates->states[EVEN_STATE] + states_read, 1, sizeof(uint32_t), benchfile); bytes_read = fread(test_candidates->states[EVEN_STATE] + states_read, 1, sizeof(uint32_t), benchfile);
if (bytes_read != sizeof(uint32_t)) { if (bytes_read != sizeof(uint32_t)) {
@ -442,9 +448,11 @@ static bool read_bench_data(statelist_t *test_candidates) {
return false; return false;
} }
} }
for (uint32_t i = states_read; i < TEST_BENCH_SIZE; i++) { for (uint32_t i = states_read; i < TEST_BENCH_SIZE; i++) {
test_candidates->states[EVEN_STATE][i] = test_candidates->states[EVEN_STATE][i - states_read]; test_candidates->states[EVEN_STATE][i] = test_candidates->states[EVEN_STATE][i - states_read];
} }
for (uint32_t i = states_read; i < num_states; i++) { for (uint32_t i = states_read; i < num_states; i++) {
bytes_read = fread(&temp, 1, sizeof(uint32_t), benchfile); bytes_read = fread(&temp, 1, sizeof(uint32_t), benchfile);
if (bytes_read != sizeof(uint32_t)) { if (bytes_read != sizeof(uint32_t)) {
@ -452,6 +460,7 @@ static bool read_bench_data(statelist_t *test_candidates) {
return false; return false;
} }
} }
for (states_read = 0; states_read < MIN(num_states, TEST_BENCH_SIZE); states_read++) { for (states_read = 0; states_read < MIN(num_states, TEST_BENCH_SIZE); states_read++) {
bytes_read = fread(test_candidates->states[ODD_STATE] + states_read, 1, sizeof(uint32_t), benchfile); bytes_read = fread(test_candidates->states[ODD_STATE] + states_read, 1, sizeof(uint32_t), benchfile);
if (bytes_read != sizeof(uint32_t)) { if (bytes_read != sizeof(uint32_t)) {
@ -459,6 +468,7 @@ static bool read_bench_data(statelist_t *test_candidates) {
return false; return false;
} }
} }
for (uint32_t i = states_read; i < TEST_BENCH_SIZE; i++) { for (uint32_t i = states_read; i < TEST_BENCH_SIZE; i++) {
test_candidates->states[ODD_STATE][i] = test_candidates->states[ODD_STATE][i - states_read]; test_candidates->states[ODD_STATE][i] = test_candidates->states[ODD_STATE][i - states_read];
} }

View file

@ -232,21 +232,21 @@ static inline void put64(void *where, uint64_t v) {
memcpy(where, &v, sizeof(v)); memcpy(where, &v, sizeof(v));
} }
static inline bool would_overflow(CborEncoder *encoder, size_t len) { static bool would_overflow(CborEncoder *encoder, size_t len) {
ptrdiff_t remaining = (ptrdiff_t)encoder->end; ptrdiff_t remaining = (ptrdiff_t)encoder->end;
remaining -= remaining ? (ptrdiff_t)encoder->data.ptr : encoder->data.bytes_needed; remaining -= remaining ? (ptrdiff_t)encoder->data.ptr : encoder->data.bytes_needed;
remaining -= (ptrdiff_t)len; remaining -= (ptrdiff_t)len;
return unlikely(remaining < 0); return unlikely(remaining < 0);
} }
static inline void advance_ptr(CborEncoder *encoder, size_t n) { static void advance_ptr(CborEncoder *encoder, size_t n) {
if (encoder->end) if (encoder->end)
encoder->data.ptr += n; encoder->data.ptr += n;
else else
encoder->data.bytes_needed += n; encoder->data.bytes_needed += n;
} }
static inline CborError append_to_buffer(CborEncoder *encoder, const void *data, size_t len) { static CborError append_to_buffer(CborEncoder *encoder, const void *data, size_t len) {
if (would_overflow(encoder, len)) { if (would_overflow(encoder, len)) {
if (encoder->end != NULL) { if (encoder->end != NULL) {
len -= encoder->end - encoder->data.ptr; len -= encoder->end - encoder->data.ptr;
@ -263,11 +263,11 @@ static inline CborError append_to_buffer(CborEncoder *encoder, const void *data,
return CborNoError; return CborNoError;
} }
static inline CborError append_byte_to_buffer(CborEncoder *encoder, uint8_t byte) { static CborError append_byte_to_buffer(CborEncoder *encoder, uint8_t byte) {
return append_to_buffer(encoder, &byte, 1); return append_to_buffer(encoder, &byte, 1);
} }
static inline CborError encode_number_no_update(CborEncoder *encoder, uint64_t ui, uint8_t shiftedMajorType) { static CborError encode_number_no_update(CborEncoder *encoder, uint64_t ui, uint8_t shiftedMajorType) {
/* Little-endian would have been so much more convenient here: /* Little-endian would have been so much more convenient here:
* We could just write at the beginning of buf but append_to_buffer * We could just write at the beginning of buf but append_to_buffer
* only the necessary bytes. * only the necessary bytes.

View file

@ -142,19 +142,19 @@
* \endif * \endif
*/ */
static inline uint16_t get16(const uint8_t *ptr) { static uint16_t get16(const uint8_t *ptr) {
uint16_t result; uint16_t result;
memcpy(&result, ptr, sizeof(result)); memcpy(&result, ptr, sizeof(result));
return cbor_ntohs(result); return cbor_ntohs(result);
} }
static inline uint32_t get32(const uint8_t *ptr) { static uint32_t get32(const uint8_t *ptr) {
uint32_t result; uint32_t result;
memcpy(&result, ptr, sizeof(result)); memcpy(&result, ptr, sizeof(result));
return cbor_ntohl(result); return cbor_ntohl(result);
} }
static inline uint64_t get64(const uint8_t *ptr) { static uint64_t get64(const uint8_t *ptr) {
uint64_t result; uint64_t result;
memcpy(&result, ptr, sizeof(result)); memcpy(&result, ptr, sizeof(result));
return cbor_ntohll(result); return cbor_ntohll(result);
@ -949,7 +949,7 @@ CborError cbor_value_calculate_string_length(const CborValue *value, size_t *len
return _cbor_value_copy_string(value, NULL, len, NULL); return _cbor_value_copy_string(value, NULL, len, NULL);
} }
static inline void prepare_string_iteration(CborValue *it) { static void prepare_string_iteration(CborValue *it) {
if (!cbor_value_is_length_known(it)) { if (!cbor_value_is_length_known(it)) {
/* chunked string: we're before the first chunk; /* chunked string: we're before the first chunk;
* advance to the first chunk */ * advance to the first chunk */

View file

@ -36,6 +36,9 @@ D01AFEEB890A
2612C6DE84CA 2612C6DE84CA
707B11FC1481 707B11FC1481
# #
# QL88 diversifed
03F9067646AE
2352C5B56D85
# #
B0B1B2B3B4B5 B0B1B2B3B4B5
C0C1C2C3C4C5 C0C1C2C3C4C5
@ -133,6 +136,11 @@ F1D83F964314
199404281970 199404281970
199404281998 199404281998
# #
# Data from http://www.proxmark.org/forum/viewtopic.php?pid=25925#p25925
# Tengo Cards Key A
FFF011223358
FF9F11223358
#
# more Keys from mfc_default_keys.lua # more Keys from mfc_default_keys.lua
000000000001 000000000001
000000000002 000000000002
@ -597,6 +605,7 @@ BFB6796A11DB
# Data from Salto A/B # Data from Salto A/B
6A1987C40A21 6A1987C40A21
7F33625BC129 7F33625BC129
6BE9314930D8
# #
# Data from forum # Data from forum
2338B4913111 2338B4913111
@ -935,9 +944,9 @@ FBF225DC5D58
# Data https://pastebin.com/BEm6bdAE # Data https://pastebin.com/BEm6bdAE
# vingcard.txt # vingcard.txt
# Note: most likely diversified # Note: most likely diversified
96A301BCE267
4708111C8604 4708111C8604
3D50D902EA48 3D50D902EA48
96A301BCE267
6700F10FEC09 6700F10FEC09
7A09CC1DB70A 7A09CC1DB70A
560F7CFF2D81 560F7CFF2D81
@ -1820,6 +1829,37 @@ E19504C39461
FA1FBB3F0F1F FA1FBB3F0F1F
FF16014FEFC7 FF16014FEFC7
# #
#
# Food GEM
6686FADE5566
#
# Data from Discord, French pool
9B7C25052FC3
494446555455
#
# Data from Discord, seems to be related to ASSA
427553754D47
# Keys found on Edith Cowan University Smart Riders
9A677289564D
186C59E6AFC9
DDDAA35A9749
9D0D0A829F49
# Mercator Pika Card, Slovenia
97D77FAE77D3
5AF445D2B87A
#
# Vilniečio/JUDU kortelė, Lithuania
# A
16901CB400BC
F0FE56621A42
8C187E78EE9C
FE2A42E85CA8
# B
6A6C80423226
F4CE4AF888AE
307448829EBC
C2A0105EB028
#
# Keys from Flipper Zero Community # Keys from Flipper Zero Community
# Last update: Aug 13, 2022 # Last update: Aug 13, 2022
# #
@ -2050,9 +2090,15 @@ D144BD193063
8627C10A7014 8627C10A7014
453857395635 453857395635
# #
# Unknown hotel system Sec 0 / A
353038383134
#
# Data from "the more the marriott" mifare project (colonelborkmundus) # Data from "the more the marriott" mifare project (colonelborkmundus)
# aka The Horde # aka The Horde
# #
# These keys seem to be from Vingcard / Saflok system which means they are diversified
# and not static default keys. To verify this, the UID from such a card is needed.
#
# 20230125-01, Elite Member Marriott Rewards # 20230125-01, Elite Member Marriott Rewards
43012BD9EB87 43012BD9EB87
# 20230125-02, Elite Member Marriott Rewards # 20230125-02, Elite Member Marriott Rewards
@ -2133,7 +2179,6 @@ D23C1CB1216E
# 20230413-78, Caesars # 20230413-78, Caesars
A1D92F808CAF A1D92F808CAF
# 20230413-79, The Cosmopolitan, Vegas # 20230413-79, The Cosmopolitan, Vegas
# 96A301BCE267
# 20230413-80, Aria # 20230413-80, Aria
1153C319B4F8 1153C319B4F8
# 20230413-81, Aria # 20230413-81, Aria
@ -2164,14 +2209,19 @@ D201DBB6AB6E
09074A146605 09074A146605
151F3E85EC46 151F3E85EC46
# #
# # Travelodge by Wyndham Berkeley
# Food GEM 0000FFFFFFFF
6686FADE5566 4663ACD2FFFF
# EDC317193709
# Data from Discord, French pool # Hotel Santa Cruz
9B7C25052FC3 75FAB77E2E5B
494446555455 # saflok brand HOTEL key
# 32F093536677
# Data from Discord, seems to be related to ASSA # A WaterFront Hotel in Oakland
427553754D47 3351916B5A77
# Ballys (2018)
336E34CC2177
# Random Hawaiian Hotel
A1670589B2AF
# SF Hotel (SoMa area)
2E0F00700000

View file

@ -97,11 +97,12 @@ if (CMAKE_TOOLCHAIN_FILE)
endif (ANDROID) endif (ANDROID)
set(EMBED_READLINE ON) set(EMBED_READLINE ON)
set(EMBED_BZIP2 ON) set(EMBED_BZIP2 ON)
set(EMBED_LZ4 ON)
endif (CMAKE_TOOLCHAIN_FILE) endif (CMAKE_TOOLCHAIN_FILE)
if (EMBED_READLINE OR EMBED_BZIP2) if (EMBED_READLINE OR EMBED_BZIP2 OR EMBED_LZ4)
include(ExternalProject) include(ExternalProject)
endif (EMBED_READLINE OR EMBED_BZIP2) endif (EMBED_READLINE OR EMBED_BZIP2 OR EMBED_LZ4)
if (NOT SKIPREADLINE EQUAL 1) if (NOT SKIPREADLINE EQUAL 1)
if (APPLE) if (APPLE)
@ -163,6 +164,7 @@ if (NOT SKIPJANSSONSYSTEM EQUAL 1)
endif (NOT SKIPJANSSONSYSTEM EQUAL 1) endif (NOT SKIPJANSSONSYSTEM EQUAL 1)
if(EMBED_BZIP2) if(EMBED_BZIP2)
cmake_policy(SET CMP0114 NEW)
set(BZIP2_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/bzip2/src/bzip2) set(BZIP2_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/bzip2/src/bzip2)
ExternalProject_Add(bzip2 ExternalProject_Add(bzip2
GIT_REPOSITORY https://android.googlesource.com/platform/external/bzip2 GIT_REPOSITORY https://android.googlesource.com/platform/external/bzip2
@ -183,6 +185,34 @@ else(EMBED_BZIP2)
find_package (BZip2 REQUIRED) find_package (BZip2 REQUIRED)
endif(EMBED_BZIP2) endif(EMBED_BZIP2)
if(EMBED_LZ4)
cmake_policy(SET CMP0114 NEW)
set(LZ4_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/lz4/src/lz4)
# Specify SOURCE_DIR will cause some errors
ExternalProject_Add(lz4
GIT_REPOSITORY https://android.googlesource.com/platform/external/lz4
GIT_TAG platform-tools-30.0.2
PREFIX deps/lz4
# SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/lz4
CONFIGURE_COMMAND mkdir -p ${LZ4_BUILD_DIR} && git archive --format tar HEAD | tar -C ${LZ4_BUILD_DIR} -x
BUILD_IN_SOURCE ON
BUILD_COMMAND make -C ${LZ4_BUILD_DIR}/lib -j4 CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} liblz4.a
INSTALL_COMMAND ""
LOG_DOWNLOAD ON
)
ExternalProject_Add_StepTargets(lz4 configure build install)
set(LZ4_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/deps/lz4/src/lz4/lib)
set(LZ4_LIBRARIES ${CMAKE_CURRENT_BINARY_DIR}/deps/lz4/src/lz4/lib/liblz4.a)
set(LZ4_FOUND ON)
else(EMBED_LZ4)
find_path(LZ4_INCLUDE_DIRS lz4frame.h)
find_library(LZ4_LIBRARIES lz4)
endif(EMBED_LZ4)
if (LZ4_INCLUDE_DIRS AND LZ4_LIBRARIES)
set(LZ4_FOUND ON)
endif (LZ4_INCLUDE_DIRS AND LZ4_LIBRARIES)
if (NOT SKIPWHEREAMISYSTEM EQUAL 1) if (NOT SKIPWHEREAMISYSTEM EQUAL 1)
find_path(WHEREAMI_INCLUDE_DIRS whereami.h) find_path(WHEREAMI_INCLUDE_DIRS whereami.h)
find_library(WHEREAMI_LIBRARIES whereami) find_library(WHEREAMI_LIBRARIES whereami)
@ -349,6 +379,7 @@ set (TARGET_SOURCES
${PM3_ROOT}/client/src/fileutils.c ${PM3_ROOT}/client/src/fileutils.c
${PM3_ROOT}/client/src/flash.c ${PM3_ROOT}/client/src/flash.c
${PM3_ROOT}/client/src/graph.c ${PM3_ROOT}/client/src/graph.c
${PM3_ROOT}/client/src/iso4217.c
${PM3_ROOT}/client/src/jansson_path.c ${PM3_ROOT}/client/src/jansson_path.c
${PM3_ROOT}/client/src/preferences.c ${PM3_ROOT}/client/src/preferences.c
${PM3_ROOT}/client/src/pm3.c ${PM3_ROOT}/client/src/pm3.c
@ -366,7 +397,7 @@ set (TARGET_SOURCES
add_custom_command( add_custom_command(
OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c
COMMAND sh ${PM3_ROOT}/tools/mkversion.sh > ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c COMMAND sh ${PM3_ROOT}/tools/mkversion.sh ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c
DEPENDS ${PM3_ROOT}/common/default_version_pm3.c DEPENDS ${PM3_ROOT}/common/default_version_pm3.c
) )
@ -456,6 +487,11 @@ if (BZIP2_FOUND)
set(ADDITIONAL_LNK ${BZIP2_LIBRARIES} ${ADDITIONAL_LNK}) set(ADDITIONAL_LNK ${BZIP2_LIBRARIES} ${ADDITIONAL_LNK})
endif (BZIP2_FOUND) endif (BZIP2_FOUND)
if (LZ4_FOUND)
set(ADDITIONAL_DIRS ${LZ4_INCLUDE_DIRS} ${ADDITIONAL_DIRS})
set(ADDITIONAL_LNK ${LZ4_LIBRARIES} ${ADDITIONAL_LNK})
endif (LZ4_FOUND)
if (WHEREAMI_FOUND) if (WHEREAMI_FOUND)
set(ADDITIONAL_DIRS ${WHEREAMI_INCLUDE_DIRS} ${ADDITIONAL_DIRS}) set(ADDITIONAL_DIRS ${WHEREAMI_INCLUDE_DIRS} ${ADDITIONAL_DIRS})
set(ADDITIONAL_LNK ${WHEREAMI_LIBRARIES} ${ADDITIONAL_LNK}) set(ADDITIONAL_LNK ${WHEREAMI_LIBRARIES} ${ADDITIONAL_LNK})
@ -488,11 +524,25 @@ else (SKIPBT EQUAL 1)
endif (BLUEZ_FOUND) endif (BLUEZ_FOUND)
endif(SKIPBT EQUAL 1) endif(SKIPBT EQUAL 1)
if (BZIP2_FOUND)
if (EMBED_BZIP2) if (EMBED_BZIP2)
message(STATUS "Bzip2 library: embedded") message(STATUS "Bzip2 library: embedded")
else (EMBED_BZIP2) else (EMBED_BZIP2)
message(STATUS "Bzip2 library: system library found") message(STATUS "Bzip2 library: system library found")
endif (EMBED_BZIP2) endif (EMBED_BZIP2)
else (BZIP2_FOUND)
message(SEND_ERROR "Bzip2 library: Bzip2 not found")
endif (BZIP2_FOUND)
if (LZ4_FOUND)
if (EMBED_LZ4)
message(STATUS "LZ4 library: embedded")
else (EMBED_LZ4)
message(STATUS "LZ4 library: system library found")
endif (EMBED_LZ4)
else (LZ4_FOUND)
message(SEND_ERROR "LZ4 library: LZ4 not found")
endif (LZ4_FOUND)
if (SKIPJANSSONSYSTEM EQUAL 1) if (SKIPJANSSONSYSTEM EQUAL 1)
message(STATUS "Jansson library: local library forced") message(STATUS "Jansson library: local library forced")
@ -592,6 +642,9 @@ endif (EMBED_READLINE)
if (EMBED_BZIP2) if (EMBED_BZIP2)
add_dependencies(pm3rrg_rdv4 bzip2) add_dependencies(pm3rrg_rdv4 bzip2)
endif (EMBED_BZIP2) endif (EMBED_BZIP2)
if (EMBED_LZ4)
add_dependencies(pm3rrg_rdv4 lz4)
endif (EMBED_LZ4)
if (MINGW) if (MINGW)
# Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z) # Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z)
@ -603,6 +656,8 @@ if (MINGW)
set(CMAKE_C_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_C_FLAGS}") set(CMAKE_C_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_CXX_FLAGS}")
endif (MINGW)
# GCC 10 has issues with false positives on stringop-overflow, # GCC 10 has issues with false positives on stringop-overflow,
# let's disable them for now (cf https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92955, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94335) # let's disable them for now (cf https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92955, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94335)
# beware these flags didn't exist for GCC < 7 # beware these flags didn't exist for GCC < 7
@ -614,8 +669,6 @@ if (MINGW)
endif() endif()
endif(CMAKE_COMPILER_IS_GNUCXX) endif(CMAKE_COMPILER_IS_GNUCXX)
endif (MINGW)
target_include_directories(pm3rrg_rdv4 PRIVATE target_include_directories(pm3rrg_rdv4 PRIVATE
${PM3_ROOT}/common ${PM3_ROOT}/common
${PM3_ROOT}/common_fpga ${PM3_ROOT}/common_fpga

View file

@ -262,14 +262,19 @@ local Utils =
-- --
-- Converts DECIMAL to HEX -- Converts DECIMAL to HEX
ConvertDecToHex = function(IN) ConvertDecToHex = function(decimal)
local B,K,OUT,I,D = 16, "0123456789ABCDEF", "", 0 if decimal == 0 then
while IN > 0 do return "0"
I = I+1
IN, D = math.floor(IN/B), math.modf(IN, B) + 1
OUT = string.sub(K, D, D)..OUT
end end
return OUT
local B,DIGITS,hex = 16, "0123456789ABCDEF", ""
while decimal > 0 do
local remainder = math.fmod(decimal, B)
hex = string.sub(DIGITS, remainder + 1, remainder + 1) .. hex
decimal = math.floor(decimal / B)
end
return hex
end, end,
--- ---
-- Convert Byte array to string of hex -- Convert Byte array to string of hex

View file

@ -96,10 +96,72 @@ Known issues; needs to be fixed:
* last byte in last segment is handled incorrectly when it is the last bytes on the card itself (MIM256: => byte 256) * last byte in last segment is handled incorrectly when it is the last bytes on the card itself (MIM256: => byte 256)
--]] --]]
---
-- requirements
local utils = require('utils')
local getopt = require('getopt')
local ansicolors = require('ansicolors')
---
-- global variables / defines
local bxor = bit32.bxor
local bbit = bit32.extract
local input = utils.input
local confirm = utils.confirm
---
-- init ansicolor-values & ansicolors switch
local colored_output = true
local acoff = ""
local acgreen= ""
local accyan = ""
local acred = ""
local acyellow = ""
local acblue = ""
local acmagenta = ""
local acy = ansicolors.yellow
local acc = ansicolors.cyan
local acr = ansicolors.reset
--- Helper ---
---
-- default colors (change to whatever you want)
function load_colors(onoff)
if (onoff) then
-- colors
acgreen = ansicolors.green
accyan = ansicolors.cyan
acred = ansicolors.red
acyellow= ansicolors.yellow
acblue = ansicolors.blue
acmagenta= ansicolors.magenta
acoff = ansicolors.reset
acy = ansicolors.yellow
acc = ansicolors.cyan
acr = ansicolors.reset
else
-- 'no color'
acgreen = ""
accyan = ""
acred = ""
acyellow= ""
acblue = ""
acmagenta= ""
acoff = ""
acy = ""
acc = ""
acr = ""
end
end
example = "script run hf_legic" example = "script run hf_legic"
author = "Mosci, uhei" author = "Mosci, uhei"
version = "1.0.4" version = "1.0.5"
desc = desc =
[[ [[
@ -109,25 +171,23 @@ it's kinda interactive with following commands in three categories:
Data I/O Segment Manipulation Token-Data Data I/O Segment Manipulation Token-Data
----------------- -------------------- ----------------- ----------------- -------------------- -----------------
rt => read Tag as => add Segment mt => make Token ]]..acy..[[rt]]..acr..[[ -> read Tag ]]..acy..[[as]]..acr..[[ -> add Segment ]]..acy..[[mt]]..acr..[[ -> make Token
wt => write Tag es => edit Segment Header et => edit Token data ]]..acy..[[wt]]..acr..[[ -> write Tag ]]..acy..[[es]]..acr..[[ -> edit Segment Header ]]..acy..[[et]]..acr..[[ -> edit Token data
ed => edit Segment Data tk => toggle KGH-Flag ]]..acy..[[ed]]..acr..[[ => edit Segment Data ]]..acy..[[tk]]..acr..[[ => toggle KGH-Flag
File I/O rs => remove Segment File I/O ]]..acy..[[rs]]..acr..[[ => remove Segment
----------------- cc => check Segment-CRC ----------------- ]]..acy..[[cc]]..acr..[[ -> check Segment-CRC
lf => load bin File ck => check KGH ]]..acy..[[lf]]..acr..[[ -> load bin File ]]..acy..[[ck]]..acr..[[ -> check KGH
sf => save eml/bin File ds => dump Segments ]]..acy..[[sf]]..acr..[[ -> save eml/bin File ]]..acy..[[ds]]..acr..[[ -> dump Segments
xf => xor to File ]]..acy..[[xf]]..acr..[[ -> xor to File
(partially) known Segments Virtual Tags Script Output (partially) known Segments Virtual Tags Script Output
--------------------------- ------------------------------- ------------------------ --------------------------- ------------------------------- ------------------------
dlc => dump Legic-Cash ct => copy mainTag to backupTag tac => toggle ansicolors ]]..acy..[[dlc]]..acr..[[ -> dump Legic-Cash ]]..acy..[[ct]]..acr..[[ -> copy mainTag to backupTag ]]..acy..[[tac]]..acr..[[ -> toggle ansicolors
elc => edit Legic-Cash tc => copy backupTag to mainTag ]]..acy..[[elc]]..acr..[[ -> edit Legic-Cash ]]..acy..[[tc]]..acr..[[ -> copy backupTag to mainTag
d3p => dump 3rd-Party-Cash tt => switch mainTag & backupTag ]]..acy..[[d3p]]..acr..[[ -> dump 3rd-Party-Cash ]]..acy..[[tt]]..acr..[[ -> switch mainTag & backupTag
e3p => edit 3rd-Party-Cash di => dump mainTag ]]..acy..[[e3p]]..acr..[[ -> edit 3rd-Party-Cash ]]..acy..[[di]]..acr..[[ -> dump mainTag
do => dump backupTag ]]..acy..[[do]]..acr..[[ => dump backupTag
rt: 'read tag' - reads a tag placed near to the PM3 rt: 'read tag' - reads a tag placed near to the PM3
wt: 'write tag' - writes the content of the 'virtual inTag' to a tag placed near to th PM3 wt: 'write tag' - writes the content of the 'virtual inTag' to a tag placed near to th PM3
@ -169,55 +229,6 @@ tac: 'toggle ansicolors'- switch on and off the colored text-output of this scri
]] ]]
currentTag="inTAG" currentTag="inTAG"
---
-- requirements
local utils = require('utils')
local getopt = require('getopt')
local ansicolors = require('ansicolors')
---
-- global variables / defines
local bxor = bit32.bxor
local bbit = bit32.extract
local input = utils.input
local confirm = utils.confirm
---
-- init ansicolor-values & ansicolors switch
local colored_output = true
local acoff = ""
local acgreen= ""
local accyan = ""
local acred = ""
local acyellow = ""
local acblue = ""
local acmagenta = ""
--- Helper ---
---
-- default colors (change to whatever you want)
function load_colors(onoff)
if (onoff) then
-- colors
acgreen = ansicolors.green
accyan = ansicolors.cyan
acred = ansicolors.red
acyellow= ansicolors.yellow
acblue = ansicolors.blue
acmagenta= ansicolors.magenta
acoff = ansicolors.reset
else
-- 'no color'
acgreen = ""
accyan = ""
acred = ""
acyellow= ""
acblue = ""
acmagenta= ""
acoff = ""
end
end
--- ---
-- curency-codes for Legic-Cash-Segments (ISO 4217) -- curency-codes for Legic-Cash-Segments (ISO 4217)
local currency = { local currency = {
@ -237,7 +248,11 @@ end
--- ---
-- Usage help -- Usage help
function help() function help()
print(desc) -- the proxmark3 client can't handle such long strings
-- by breaking up at specific points it still looks good.
print(string.sub(desc, 0, 1961))
print(string.sub(desc, 1962, 3925))
print(string.sub(desc, 3926, #desc))
print("Version: "..version) print("Version: "..version)
print("Example usage: "..example) print("Example usage: "..example)
end end
@ -254,7 +269,6 @@ local function padString(str)
if (#str == 1) then if (#str == 1) then
return '0'..str return '0'..str
end end
return str return str
end end
@ -305,18 +319,6 @@ function xorBytes(inBytes, crc)
end end
end end
---
-- check availability of file
function file_check(file_name)
local file_found = io.open(file_name, "r")
if file_found == nil then
return false
else
file_found:close()
return true
end
end
--- ---
-- split csv-string into table -- split csv-string into table
local function split(str, sep) local function split(str, sep)
@ -330,6 +332,24 @@ local function split(str, sep)
return fields return fields
end end
---
-- check availability of file
function file_check(file_name)
if not file_name then return false, "" end
local arr = split(file_name, ".")
local path = core.search_file(arr[1], "."..arr[2])
if (path == nil) then return false end
local file_found = io.open(path, "r")
if file_found == nil then
return false, ""
else
file_found:close()
return true, path
end
end
--- ---
-- put a string into a bytes-table -- put a string into a bytes-table
function str2bytes(s) function str2bytes(s)
@ -348,7 +368,7 @@ end
function bytesToTable(bytes, bstart, bend) function bytesToTable(bytes, bstart, bend)
local t={} local t={}
for i=0, (bend-bstart) do for i=0, (bend-bstart) do
t[i]=bytes[bstart+i] t[i]=padString(bytes[bstart+i])
end end
return t return t
end end
@ -358,8 +378,13 @@ end
function getInputBytes(infile) function getInputBytes(infile)
local line local line
local bytes = {} local bytes = {}
local fhi,err = io.open(infile,"rb")
if err then oops("failed to read from file ".. infile); return false; end local arr = split(infile, ".")
local path = core.search_file(arr[1], "."..arr[2])
if (path == nil) then oops("failed to read from file ".. infile); return false; end
local fhi,err = io.open(path,"rb")
if err then oops("failed to read from file ".. path); return false; end
file_data = fhi:read("*a"); file_data = fhi:read("*a");
for i = 1, #file_data do for i = 1, #file_data do
@ -367,7 +392,7 @@ function getInputBytes(infile)
end end
fhi:close() fhi:close()
if (bytes[7]=='00') then return false end if (bytes[7]=='00') then return false end
print(#bytes .. " bytes from "..infile.." loaded") print(#bytes .. " bytes from "..path.." loaded")
return bytes return bytes
end end
@ -613,12 +638,13 @@ local function readFile(filename)
print(accyan) print(accyan)
local bytes = {} local bytes = {}
local tag = {} local tag = {}
if file_check(filename) == false then
local res, path = file_check(filename)
if not res then
return oops("input file: "..acyellow..filename..acoff.." not found") return oops("input file: "..acyellow..filename..acoff.." not found")
end end
bytes = getInputBytes(filename) bytes = getInputBytes(path)
if bytes == false then return oops('couldnt get input bytes') end if bytes == false then return oops('couldnt get input bytes') end
-- make plain bytes -- make plain bytes
@ -640,12 +666,14 @@ local function save_BIN(data, filename)
local fn = filename..ext local fn = filename..ext
-- Make sure we don't overwrite a file -- Make sure we don't overwrite a file
while file_check(fn) do local res, path = file_check(fn)
while res == false do
fn = filename..ext:gsub(ext, "-"..tostring(counter)..ext) fn = filename..ext:gsub(ext, "-"..tostring(counter)..ext)
counter = counter + 1 counter = counter + 1
res, path = file_check(fn)
end end
outfile = io.open(fn, 'wb') outfile = io.open(path, 'wb')
local i = 1 local i = 1
while data[i] do while data[i] do
@ -660,17 +688,19 @@ end
-- write bytes to file -- write bytes to file
function writeFile(bytes, filename) function writeFile(bytes, filename)
local emlext = ".eml" local emlext = ".eml"
local res, path
if (filename ~= 'MyLegicClone') then if (filename ~= 'MyLegicClone') then
if (file_check(filename..emlext)) then res, path = file_check(filename..emlext)
local answer = confirm("\nthe output-file "..filename..emlext.." already exists!\nthis will delete the previous content!\ncontinue?") if res then
local answer = confirm("\nthe output-file "..path.." already exists!\nthis will delete the previous content!\ncontinue?")
if not answer then return print("user abort") end if not answer then return print("user abort") end
end end
end end
local line local line
local bcnt = 0 local bcnt = 0
local fho, err = io.open(filename..emlext, "w") local fho, err = io.open(path, "w")
if err then if err then
return oops("OOps ... failed to open output-file ".. filename..emlext) return oops("OOps ... failed to open output-file ".. path)
end end
bytes = xorBytes(bytes, bytes[5]) bytes = xorBytes(bytes, bytes[5])
@ -692,11 +722,10 @@ function writeFile(bytes, filename)
end end
fho:close() fho:close()
-- save binary
local fn_bin, fn_bin_num = save_BIN(bytes, filename)
print("\nwrote "..acyellow..(#bytes * 3)..acoff.." bytes to " ..acyellow..filename..emlext..acoff) print("\nwrote "..acyellow..(#bytes * 3)..acoff.." bytes to " ..acyellow..filename..emlext..acoff)
-- save binary
local fn_bin, fn_bin_num = save_BIN(bytes, filename)
if fn_bin and fn_bin_num then if fn_bin and fn_bin_num then
print("\nwrote "..acyellow..fn_bin_num..acoff.." bytes to BINARY file "..acyellow..fn_bin..acoff) print("\nwrote "..acyellow..fn_bin_num..acoff.." bytes to BINARY file "..acyellow..fn_bin..acoff)
end end
@ -731,10 +760,16 @@ function readFromPM3()
infile=getRandomTempName() infile=getRandomTempName()
core.console("hf legic dump -f "..infile) core.console("hf legic dump -f "..infile)
tag=readFile(infile..".bin") tag=readFile(infile..".bin")
os.remove(infile)
os.remove(infile..".bin") res, path = file_check(infile..".bin")
os.remove(infile..".eml") if not res then return nil end
os.remove(infile..".json") os.remove(path)
res, path = file_check(infile..".eml")
os.remove(path)
res, path = file_check(infile..".json")
os.remove(path)
return tag return tag
end end
@ -758,16 +793,20 @@ end
--- ---
-- save mapping to file -- save mapping to file
local function saveTagMap(map, filename) local function saveTagMap(map, filename)
local res, path
if #filename > 0 then if #filename > 0 then
if file_check(filename) then res, path = file_check(filename)
local answer = confirm("\nthe output-file "..acyellow..filename..acoff.." alredy exists!\nthis will delete the previous content!\ncontinue?") if res then
local answer = confirm("\nthe output-file "..acyellow..path..acoff.." alredy exists!\nthis will delete the previous content!\ncontinue?")
if not answer then return print("user abort") end if not answer then return print("user abort") end
end end
end end
local line local line
local fho,err = io.open(filename, "w") local fho,err = io.open(path, "w")
if err then oops("OOps ... failed to open output-file "..acyellow..filename..acoff) end if err then oops("OOps ... failed to open output-file "..acyellow..path..acoff) end
-- write line to new file -- write line to new file
for k, v in pairs(map) do for k, v in pairs(map) do
@ -842,10 +881,13 @@ function loadTagMap(filename)
local line, fields local line, fields
local temp={} local temp={}
local offset=0 local offset=0
if not file_check(filename) then
local res, path = file_check(filename)
if not res then
return oops("input file: "..acyellow..filename..acoff.." not found") return oops("input file: "..acyellow..filename..acoff.." not found")
else else
local fhi,err = io.open(filename)
local fhi,err = io.open(path)
while true do while true do
line = fhi:read() line = fhi:read()
if line == nil then if line == nil then
@ -907,20 +949,21 @@ function dumpTagMap(tag, tagMap)
end end
if (isPosCrc8(tagMap, v['start'])>0) then if (isPosCrc8(tagMap, v['start'])>0) then
if ( checkMapCrc8(tagMap, bytes, isPosCrc8(tagMap, v['start']) ) ) then if ( checkMapCrc8(tagMap, bytes, isPosCrc8(tagMap, v['start']) ) ) then
io.write("("..("%04d"):format(v['start']).."-"..("%04d"):format(v['end'])..") "..acgreen..v['name']..acoff..":") io.write("("..("%04d"):format(v['start']).."-"..("%04d"):format(v['end'])..") "..acgreen..v['name']..acoff)
else else
io.write("("..("%04d"):format(v['start']).."-"..("%04d"):format(v['end'])..") "..acred..v['name']..acoff..":") io.write("("..("%04d"):format(v['start']).."-"..("%04d"):format(v['end'])..") "..acred..v['name']..acoff)
end end
else else
io.write("("..("%04d"):format(v['start']).."-"..("%04d"):format(v['end'])..") "..((v['highlight']) and acmagenta or acyellow)..v['name']..acoff..":") io.write("("..("%04d"):format(v['start']).."-"..("%04d"):format(v['end'])..") "..((v['highlight']) and acmagenta or acyellow)..v['name']..acoff)
end end
temp = "" temp = ""
for i=((string.len(v['name']))/10), 2 do while (#v['name'] + temp:len()) < 20 do temp = temp.." " end
temp=temp.."\t"
end
for i=v['start'], v['end'] do for i=v['start'], v['end'] do
temp=temp..bytes[i].." " temp=temp..bytes[i].." "
end end
print(temp) print(temp)
lastend=v['end'] lastend=v['end']
end end
@ -966,11 +1009,23 @@ end
-- edit existing Map -- edit existing Map
function editTagMap(tag, tagMap) function editTagMap(tag, tagMap)
local t = [[ local t = [[
Data: dm = show dr = dump raw ]]..acc..[[Data]]..acr..[[
Mappings: im = insert am = add rm = remove
CRC8: ac8 = add sc8 = show rc8 = remove ]]..acy..[[dm]]..acr..[[ - show ]]..acy..[[dr]]..acr..[[ - dump raw
: q = exit h = Help
]]..acc..[[Mappings]]..acr..[[
]]..acy..[[im]]..acr..[[ - insert ]]..acy..[[am]]..acr..[[ - add
]]..acy..[[rm]]..acr..[[ - remove ]]..acy..[[mas]]..acr..[[ - map all segments
]]..acc..[[CRC8]]..acr..[[
]]..acy..[[ac8]]..acr..[[ - add ]]..acy..[[sc8]]..acr..[[ - show
]]..acy..[[rc8]]..acr..[[ - remove
]]..acy..[[q]]..acr..[[ - exit ]]..acy..[[h]]..acr..[[ - Help
]] ]]
--if(#tagMap.mappings==0) then oops("no mappings in tagMap"); return tagMap end --if(#tagMap.mappings==0) then oops("no mappings in tagMap"); return tagMap end
print("tagMap edit-mode submenu") print("tagMap edit-mode submenu")
repeat repeat
@ -2293,25 +2348,25 @@ function modifyHelp()
Data I/O Segment Manipulation Token-Data Data I/O Segment Manipulation Token-Data
----------------- -------------------- --------------------- ----------------- -------------------- ---------------------
rt => read Tag as => add Segment mt => make Token ]]..acy..[[rt]]..acr..[[ => read Tag ]]..acy..[[as]]..acr..[[ => add Segment ]]..acy..[[mt]]..acr..[[ => make Token
wt => write Tag es => edit Segment Header et => edit Token data ]]..acy..[[wt]]..acr..[[ => write Tag ]]..acy..[[es]]..acr..[[ => edit Segment Header ]]..acy..[[et]]..acr..[[ => edit Token data
ed => edit Segment Data tk => toggle KGH-Flag ]]..acy..[[ed]]..acr..[[ => edit Segment Data ]]..acy..[[tk]]..acr..[[ => toggle KGH-Flag
File I/O rs => remove Segment File I/O ]]..acy..[[rs]]..acr..[[ => remove Segment
----------------- cc => check Segment-CRC ----------------- ]]..acy..[[cc]]..acr..[[ => check Segment-CRC
lf => load bin File ck => check KGH ]]..acy..[[lf]]..acr..[[ => load bin File ]]..acy..[[ck]]..acr..[[ => check KGH
sf => save eml/bin File ds => dump Segments ]]..acy..[[sf]]..acr..[[ => save eml/bin File ]]..acy..[[ds]]..acr..[[ => dump Segments
xf => xor to File ]]..acy..[[xf]]..acr..[[ => xor to File
Virtual Tags tagMap (partial) known Segments Virtual Tags tagMap (partial) known Segments
-------------------------------- --------------------- --------------------------- -------------------------------- --------------------- ---------------------------
ct => copy mainTag to backupTag mm => make (new) Map dlc => dump Legic-Cash ]]..acy..[[ct]]..acr..[[ => copy mainTag to backupTag ]]..acy..[[mm]]..acr..[[ => make (new) Map ]]..acy..[[dlc]]..acr..[[ => dump Legic-Cash
tc => copy backupTag to mainTag em => edit Map submenu elc => edit Legic-Cash ]]..acy..[[tc]]..acr..[[ => copy backupTag to mainTag ]]..acy..[[em]]..acr..[[ => edit Map submenu ]]..acy..[[elc]]..acr..[[ => edit Legic-Cash
tt => switch mainTag & backupTag lm => load map from file d3p => dump 3rd-Party-Cash ]]..acy..[[tt]]..acr..[[ => switch mainTag & backupTag ]]..acy..[[lm]]..acr..[[ => load map from file ]]..acy..[[d3p]]..acr..[[ => dump 3rd-Party-Cash
di => dump mainTag sm => save map to file e3p => edit 3rd-Party-Cash ]]..acy..[[di]]..acr..[[ => dump mainTag ]]..acy..[[sm]]..acr..[[ => save map to file ]]..acy..[[e3p]]..acr..[[ => edit 3rd-Party-Cash
do => dump backupTag ]]..acy..[[do]]..acr..[[ => dump backupTag
h => this help q => quit ]]..acy..[[h]]..acr..[[ => this help ]]..acy..[[q]]..acr..[[ => quit
]] ]]
return t return t
end end
@ -2325,8 +2380,10 @@ function modifyMode()
--- ---
-- helptext -- helptext
["h"] = function(x) ["h"] = function(x)
print(" Version: "..version); print(" Version: "..acgreen..version..acr);
print(modifyHelp().."\n".."tags im Memory: "..(istable(inTAG) and ((currentTag=='inTAG') and acgreen.."*mainTAG"..acoff or "mainTAG") or "").." "..(istable(backupTAG) and ((currentTag=='backupTAG') and acgreen.."*backupTAG"..acoff or "backupTAG") or "")) print(modifyHelp())
print("\n".."tags im Memory: "..(istable(inTAG) and ((currentTag=='inTAG') and acgreen.."*mainTAG"..acoff or "mainTAG") or "").." "..(istable(backupTAG) and ((currentTag=='backupTAG') and acgreen.."*backupTAG"..acoff or "backupTAG") or ""))
print("")
end, end,
--- ---
-- read real Tag with PM3 into virtual 'mainTAG' -- read real Tag with PM3 into virtual 'mainTAG'
@ -2367,16 +2424,16 @@ function modifyMode()
--- ---
-- load file into mainTAG -- load file into mainTAG
["lf"] = function(x) ["lf"] = function(x)
if (x and not x=="" and type(x)=='string' and file_check(x)) then
if (type(x)=='string' and file_check(x)) then
filename = x filename = x
else else
filename = input("enter filename: ", "legic.temp") filename = input("enter filename: ", "legic.temp")
end end
inTAG=readFile(filename) inTAG=readFile(filename)
-- check for existing tagMap -- check for existing tagMap
if (file_check(filename..".map")) then local res, path = file_check(filename..".map")
if(confirm(accyan.."Mapping-File for "..acoff..filename..accyan.." found - load it also?"..acoff)) then if res then
if(confirm(accyan.."Mapping-File for "..acoff..path..accyan.." found - load it also?"..acoff)) then
tagMap=loadTagMap(filename..".map") tagMap=loadTagMap(filename..".map")
end end
end end
@ -2724,7 +2781,7 @@ function modifyMode()
} }
repeat repeat
-- default message / prompt -- default message / prompt
ic=input("Legic command? ('h' for help - 'q' for quit)", "h") ic=input("Legic command? ('"..acy.."h"..acr.."' for help - '"..acy.."q"..acr.."' for quit)", acy.."h"..acr)
-- command actions decisions (first match, longer commands before shorter) -- command actions decisions (first match, longer commands before shorter)
if (type(actions[string.lower(string.sub(ic,0,3))])=='function') then if (type(actions[string.lower(string.sub(ic,0,3))])=='function') then
actions[string.lower(string.sub(ic,0,3))](string.sub(ic,5)) actions[string.lower(string.sub(ic,0,3))](string.sub(ic,5))
@ -2745,7 +2802,10 @@ function main(args)
load_colors(colored_output) load_colors(colored_output)
if (#args == 0 ) then modifyMode() end if (#args == 0 ) then modifyMode() end
--- variables --- variables
local inTAG, backupTAG, outTAG, outfile, interactive, crc, ofs, cfs, dfs local inTAG, backupTAG, outTAG, outfile, interactive, crc
local ofs=false
local cfs=false
local dfs=false
-- just a spacer for better readability -- just a spacer for better readability
print() print()
--- parse arguments --- parse arguments
@ -2793,7 +2853,10 @@ function main(args)
-- write to outfile -- write to outfile
if (bytes) then if (bytes) then
if (outfile) then
writeFile(bytes, outfile) writeFile(bytes, outfile)
end
--- read real tag into virtual tag --- read real tag into virtual tag
-- inTAG=readFromPM3() end -- inTAG=readFromPM3() end
--- or simply use the bytes that where wriiten --- or simply use the bytes that where wriiten

View file

@ -168,7 +168,7 @@ local function help()
print(example) print(example)
end end
-- read LEGIC data -- read LEGIC data
local function readlegicdata(offset, length, iv) local function readlegicdata(offset, len, iv)
-- Read data -- Read data
local d0 = ('%04X%04X%02X'):format(offset, len, iv) local d0 = ('%04X%04X%02X'):format(offset, len, iv)
local c = Command:newNG{cmd = cmds.CMD_HF_LEGIC_READER, data = d0} local c = Command:newNG{cmd = cmds.CMD_HF_LEGIC_READER, data = d0}

View file

@ -124,7 +124,7 @@ local function main(args)
local c = string.format( command, n ) local c = string.format( command, n )
print('Running: "'..c..'"') print('Running: "'..c..'"')
core.console(c) core.console(c)
core.console('msleep '..timeout); core.console('msleep -t'..timeout);
core.console('hw ping') core.console('hw ping')
end end

View file

@ -737,7 +737,7 @@ local function set_type(tagtype)
write_uid('04112233445566') write_uid('04112233445566')
write_otp('00000000') -- Setting OTP to default 00 00 00 00 write_otp('00000000') -- Setting OTP to default 00 00 00 00
write_version('0004030101000b03') -- UL-EV1 (48) 00 04 03 01 01 00 0b 03 write_version('0004030101000b03') -- UL-EV1 (48) 00 04 03 01 01 00 0b 03
elseif tagtype == 12 then elseif tagtype == 13 then
print('Setting: Ultimate Magic card to UL-EV1 128') print('Setting: Ultimate Magic card to UL-EV1 128')
connect() connect()
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000000") send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000000")

View file

@ -12,7 +12,7 @@ This version
- Iceman - Iceman
Note: Note:
This script is used as a helper script to generate the pm3line_vocabulory.h file. This script is used as a helper script to generate the pm3line_vocabulary.h file.
It need a working proxmark3 client to extract the help text. It need a working proxmark3 client to extract the help text.
Ie: this script can't be used inside the normal build sequence. Ie: this script can't be used inside the normal build sequence.
@ -65,8 +65,8 @@ def main():
// readline auto complete utilities // readline auto complete utilities
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifndef PM3LINE_VOCABULORY_H__ #ifndef PM3LINE_VOCABULARY_H__
#define PM3LINE_VOCABULORY_H__ #define PM3LINE_VOCABULARY_H__
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -74,12 +74,12 @@ extern "C" {
#include <stdbool.h> #include <stdbool.h>
typedef struct vocabulory_s { typedef struct vocabulary_s {
bool offline; bool offline;
const char *name; const char *name;
} vocabulory_t; } vocabulary_t;
const static vocabulory_t vocabulory[] = {\n""") const static vocabulary_t vocabulary[] = {\n""")
for key, values in command_data.items(): for key, values in command_data.items():
offline = 0 offline = 0

View file

@ -2406,5 +2406,21 @@
"Name": "AirDrop connection negotiation", "Name": "AirDrop connection negotiation",
"Description": "Used by NFC-based AirDrop negotiation added in IOS17", "Description": "Used by NFC-based AirDrop negotiation added in IOS17",
"Type": "" "Type": ""
},
{
"AID": "a0000004400001010001",
"Vendor": "HID Global",
"Country": "",
"Name": "SEOS",
"Description": "Used by both by physical cards and mobile implementations",
"Type": "access"
},
{
"AID": "A00000054000060100010000FF",
"Vendor": "HID Global",
"Country": "",
"Name": "SEOS Mobile",
"Description": "Declared by some SEOS-compatible applications for HCE",
"Type": "access"
} }
] ]

View file

@ -25,7 +25,6 @@
"description": "iPhones before IOS17 emit this frame so that other Apple devices don't react to the field during background reading. Also emitted during NFCReaderSession subtypes" "description": "iPhones before IOS17 emit this frame so that other Apple devices don't react to the field during background reading. Also emitted during NFCReaderSession subtypes"
}, },
{ {
"value": "6a02c801000300000000000000", "value": "6a02c801000300000000000000",
"name": "Transit: Ventra", "name": "Transit: Ventra",
@ -58,7 +57,7 @@
}, },
{ {
"value": "6a02c3020602ffff", "value": "6a02c3020002ffff",
"name": "Access: Hotel: Hilton", "name": "Access: Hotel: Hilton",
"description": "TCI might be a wildcard before a reservation is made" "description": "TCI might be a wildcard before a reservation is made"
}, },

Some files were not shown because too many files have changed in this diff Show more