mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
Merge branch 'master' into smartcard-relay
This commit is contained in:
commit
7f91da8a9a
1001 changed files with 51581 additions and 4531 deletions
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
|
@ -41,7 +41,7 @@ jobs:
|
|||
run: sudo apt-get update
|
||||
|
||||
- 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
|
||||
run: |
|
||||
|
|
6
.github/workflows/ubuntu.yml
vendored
6
.github/workflows/ubuntu.yml
vendored
|
@ -26,7 +26,7 @@ jobs:
|
|||
run: sudo apt-get update
|
||||
|
||||
- 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
|
||||
run: |
|
||||
|
@ -58,7 +58,7 @@ jobs:
|
|||
run: sudo apt-get update
|
||||
|
||||
- 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
|
||||
run: |
|
||||
|
@ -91,7 +91,7 @@ jobs:
|
|||
run: sudo apt-get update
|
||||
|
||||
- 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
|
||||
run: |
|
||||
|
|
5
.github/workflows/uniq.yaml
vendored
5
.github/workflows/uniq.yaml
vendored
|
@ -18,6 +18,5 @@ jobs:
|
|||
- name: check unique keys in dic files
|
||||
shell: bash
|
||||
run: |
|
||||
find . -type f -name "*.dic" | xargs -I {} sh -c "echo {} && cat {} | grep -v '#' | 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
|
||||
|
||||
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 {} | sed 's/ *#.*//;/^$/d' | sort | uniq -i -d -c | sort -n -r " | grep -v '^\./' | wc -l) -gt 0 ]]; then exit 1; fi
|
||||
|
|
1
.github/workflows/windows.yml
vendored
1
.github/workflows/windows.yml
vendored
|
@ -110,6 +110,7 @@ jobs:
|
|||
gcc-arm-none-eabi
|
||||
libnewlib-dev
|
||||
libbz2-dev
|
||||
liblz4-dev
|
||||
qtbase5-dev
|
||||
cmake
|
||||
libpython3-dev
|
||||
|
|
10
.vscode/setup.sh
vendored
10
.vscode/setup.sh
vendored
|
@ -129,17 +129,17 @@ fi
|
|||
|
||||
HOSTOS=$(uname | awk '{print toupper($0)}')
|
||||
if [ "$HOSTOS" = "LINUX" ]; then
|
||||
if uname -a|grep -q Microsoft; then
|
||||
if uname -a|grep -q Microsoft; then
|
||||
setup_wsl
|
||||
else
|
||||
else
|
||||
setup_linux
|
||||
fi
|
||||
fi
|
||||
elif [ "$HOSTOS" = "DARWIN" ]; then
|
||||
echo >&2 "[!!] MacOS not supported, sorry!"
|
||||
exit 1
|
||||
elif [[ "$HOSTOS" =~ MINGW(32|64)_NT* ]]; then
|
||||
setup_ps
|
||||
else
|
||||
echo >&2 "[!!] Host OS not recognized, abort: $HOSTOS"
|
||||
exit 1
|
||||
echo >&2 "[!!] Host OS not recognized, abort: $HOSTOS"
|
||||
exit 1
|
||||
fi
|
65
CHANGELOG.md
65
CHANGELOG.md
|
@ -4,13 +4,62 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
|||
|
||||
## [unreleased][unreleased]
|
||||
- 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)
|
||||
- Added `emv reader` - act as a EMV reader (@iceman1001)
|
||||
- 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)
|
||||
- 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]
|
||||
- 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!
|
||||
- Fixed `pm3-flash-all` shell script now correctly identify the if running on outdated bootloader (@iceman1001)
|
||||
- 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)
|
||||
- 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)
|
||||
|
@ -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 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)
|
||||
- Add 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)
|
||||
- Add 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)
|
||||
- Improved NXP SLI/SLIX series tag identification (@nvx)
|
||||
- Added command `piv authsign` to get a buffer signed by the selected key (@jmichelp)
|
||||
- Added command `piv scan` which tries to read all known containers on PIV (@jmichelp)
|
||||
- Added support for PIV commands, over wired and contactless interfaces (@jmichelp)
|
||||
- Added `--shallow` option to `hf iclass` reader commands to do shallow (ASK) reader modulation instead of OOK (@nvx)
|
||||
- Change and improved NXP SLI/SLIX series tag identification (@nvx)
|
||||
- Fixed buffer overflow in "lf em 4x05 sniff" (@HeinrichsH)
|
||||
- Fixed potential NULL array printing (@jmichelp)
|
||||
- Added PIV aid to resource file (@jmichelp)
|
||||
|
|
23
Makefile
23
Makefile
|
@ -29,7 +29,7 @@ ifneq (,$(DESTDIR))
|
|||
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"
|
||||
#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
|
||||
INSTALLDOCS=doc/*.md doc/md
|
||||
|
||||
install: all common/install
|
||||
install: common/install
|
||||
|
||||
common/install:
|
||||
$(info [@] Installing common resources to $(MYDESTDIR)$(PREFIX)...)
|
||||
|
@ -109,6 +109,9 @@ endif
|
|||
$(Q)-$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
|
||||
|
||||
# tests
|
||||
cryptorf/check: FORCE
|
||||
$(info [*] CHECK $(patsubst %/check,%,$@))
|
||||
$(Q)$(BASH) tools/pm3_tests.sh $(CHECKARGS) $(patsubst %/check,%,$@)
|
||||
mfkey/check: FORCE
|
||||
$(info [*] CHECK $(patsubst %/check,%,$@))
|
||||
$(Q)$(BASH) tools/pm3_tests.sh $(CHECKARGS) $(patsubst %/check,%,$@)
|
||||
|
@ -145,6 +148,9 @@ common/check: FORCE
|
|||
check: common/check
|
||||
$(info [*] ALL CHECKS DONE)
|
||||
|
||||
cryptorf/%: FORCE
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C tools/cryptorf $(patsubst cryptorf/%,%,$@) DESTDIR=$(MYDESTDIR)
|
||||
mfkey/%: FORCE
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C tools/mfkey $(patsubst mfkey/%,%,$@) DESTDIR=$(MYDESTDIR)
|
||||
|
@ -170,7 +176,7 @@ client/%: FORCE cleanifplatformchanged
|
|||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C client $(patsubst client/%,%,$@) DESTDIR=$(MYDESTDIR)
|
||||
recovery/all: bootrom/all armsrc/all
|
||||
recovery/install: bootrom/all armsrc/all
|
||||
recovery/install: bootrom/install armsrc/install
|
||||
recovery/%: FORCE cleanifplatformchanged
|
||||
$(info [*] MAKE $@)
|
||||
$(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
|
||||
@echo "+ client - Make only the OS-specific host client"
|
||||
@echo "+ cryptorf - Make tools/cryptorf"
|
||||
@echo "+ mfkey - Make tools/mfkey"
|
||||
@echo "+ nonce2key - Make tools/nonce2key"
|
||||
@echo "+ mf_nonce_brute - Make tools/mf_nonce_brute"
|
||||
|
@ -232,6 +239,8 @@ fullimage/uninstall: armsrc/uninstall
|
|||
|
||||
recovery: recovery/all
|
||||
|
||||
cryptorf: cryptorf/all
|
||||
|
||||
mfkey: mfkey/all
|
||||
|
||||
nonce2key: nonce2key/all
|
||||
|
@ -318,10 +327,10 @@ style:
|
|||
# Make sure python3 is installed
|
||||
@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
|
||||
[ -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
|
||||
[ -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.
|
||||
|
@ -370,10 +379,10 @@ release:
|
|||
# - Tagging temporarily...
|
||||
@git tag -a -m "Release $(VERSION) - $(RELEASE_NAME)" $(VERSION)
|
||||
# - 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
|
||||
@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...
|
||||
@git tag -d $(VERSION)
|
||||
# - Amending commit...
|
||||
|
|
|
@ -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 - 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)|
|
||||
| [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)|
|
||||
| [Mac OS X - Setup and Build](/doc/md/Installation_Instructions/Mac-OS-X-Compile-From-Source-Instructions.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)|
|
||||
| [macOS - MacPorts](/doc/md/Installation_Instructions/macOS-MacPorts-Installation-Instructions.md) | [Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.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) ||
|
||||
| [Termux / Android - Setup and Build](/doc/termux_notes.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
|
||||
- Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, NetHunter, Arch Linux, Fedora, Debian, Raspbian
|
||||
- Android / Termux
|
||||
- Mac OS X / Homebrew (or MacPorts, experimental) / Apple Silicon M1
|
||||
- macOS / Homebrew (or MacPorts, experimental) / Apple Silicon M1
|
||||
- Docker container
|
||||
- [ 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/)
|
||||
|
|
|
@ -233,7 +233,7 @@ uint32_t BigBuf_get_traceLen(void) {
|
|||
by 'hf list -t raw', alternatively 'hf list -t <proto>' for protocol-specific
|
||||
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) {
|
||||
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
|
||||
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;
|
||||
duration /= 32;
|
||||
ts_end = ts_start + duration;
|
||||
|
@ -306,17 +306,24 @@ bool RAMFUNC LogTraceBits(const uint8_t *btBytes, uint16_t bitLen, uint32_t time
|
|||
}
|
||||
|
||||
// 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();
|
||||
if (offset + length < CARD_MEMORY_SIZE) {
|
||||
if (offset + length <= CARD_MEMORY_SIZE) {
|
||||
memcpy(mem + offset, data, length);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// get the address of the ToSend buffer. Allocate part of Bigbuf for it, if not yet done
|
||||
tosend_t *get_tosend(void) {
|
||||
|
|
|
@ -51,11 +51,12 @@ void set_tracing(bool enable);
|
|||
void set_tracelen(uint32_t value);
|
||||
bool get_tracing(void);
|
||||
|
||||
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool 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 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 {
|
||||
int max;
|
||||
|
|
|
@ -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 char mask = 0, px, py, xme, yme, offset;
|
||||
const char *data;
|
||||
|
|
|
@ -130,7 +130,7 @@ void LCDInit(void);
|
|||
void LCDReset(void);
|
||||
void LCDSetXY(unsigned char x, unsigned char y);
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -127,7 +127,7 @@ THUMBSRC = start.c \
|
|||
$(SRC_SMARTCARD) \
|
||||
$(SRC_FPC) \
|
||||
$(SRC_HITAG) \
|
||||
$(SRC_EM4x50) \
|
||||
$(SRC_EM4x50) \
|
||||
$(SRC_EM4x70) \
|
||||
$(SRC_SPIFFS) \
|
||||
$(SRC_HF) \
|
||||
|
@ -181,10 +181,10 @@ showinfo:
|
|||
|
||||
.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
|
||||
$(info [-] GEN $@)
|
||||
$(Q)$(SH) ../tools/mkversion.sh > $@ || $(CP) $< $@
|
||||
$(info [-] CHECK $@)
|
||||
$(Q)$(SH) ../tools/mkversion.sh $@ || $(CP) $< $@
|
||||
|
||||
fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR)
|
||||
$(info [-] GEN $@)
|
||||
|
|
|
@ -86,6 +86,9 @@ define KNOWN_STANDALONE_DEFINITIONS
|
|||
| HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth |
|
||||
| (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 |
|
||||
| (RDV4 only) | - Colin Brigato |
|
||||
+----------------------------------------------------------+
|
||||
|
@ -130,9 +133,9 @@ endef
|
|||
|
||||
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 += 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_REQ_BT := HF_REBLAY
|
||||
STANDALONE_MODES_REQ_BT := HF_CARDHOPPER HF_REBLAY
|
||||
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
|
||||
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),)
|
||||
|
|
|
@ -97,6 +97,10 @@ endif
|
|||
ifneq (,$(findstring WITH_STANDALONE_HF_BOG,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_bog.c
|
||||
endif
|
||||
# WITH_STANDALONE_HF_CARDHOPPER
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_CARDHOPPER,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_cardhopper.c
|
||||
endif
|
||||
# WITH_STANDALONE_HF_COLIN
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_COLIN,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = vtsend.c hf_colin.c frozen.c nprintf.c
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
* 1. mem spiffs dump -s hf_14asniff.trace -d hf_14asniff.trace
|
||||
* 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.
|
||||
*
|
||||
* 3. For ISO14a: trace list -t 14a -1
|
||||
|
@ -55,6 +55,7 @@
|
|||
* the lab connected to PM3 client before taking it into the field.
|
||||
*
|
||||
* To delete the trace data from flash:
|
||||
* mem spiffs remove -f hf_14asniff.trace
|
||||
*
|
||||
* Caveats / notes:
|
||||
* - Trace buffer will be cleared on starting stand-alone mode. Data in flash
|
||||
|
|
15
armsrc/Standalone/hf_14bsniff.c
Executable file → Normal file
15
armsrc/Standalone/hf_14bsniff.c
Executable file → Normal file
|
@ -14,9 +14,24 @@
|
|||
* - LED3: sniffed reader command, turns off when finished sniffing tag command
|
||||
* - 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
|
||||
* 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:
|
||||
* - Trace buffer will be cleared on starting stand-alone mode.
|
||||
* - This module will terminate if the trace buffer is full.
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
* 1. mem spiffs dump -s hf_15693sniff.trace -d hf_15693sniff.trace
|
||||
* 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.
|
||||
*
|
||||
* 3. For ISO15693: trace list -t 15 -1
|
||||
|
@ -54,6 +54,7 @@
|
|||
* the lab connected to PM3 client before taking it into the field.
|
||||
*
|
||||
* To delete the trace data from flash:
|
||||
* mem spiffs remove -f hf_15693sniff.trace
|
||||
*
|
||||
* Caveats / notes:
|
||||
* - Trace buffer will be cleared on starting stand-alone mode. Data in flash
|
||||
|
|
417
armsrc/Standalone/hf_cardhopper.c
Normal file
417
armsrc/Standalone/hf_cardhopper.c
Normal 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;
|
||||
}
|
|
@ -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);
|
||||
|
||||
// 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");
|
||||
cjSetCursLeft();
|
||||
|
@ -650,7 +650,7 @@ failtag:
|
|||
for (uint8_t t = 0; t < 2; t++) {
|
||||
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();
|
||||
|
||||
|
@ -827,12 +827,12 @@ int e_MifareECardLoad(uint32_t numofsectors, uint8_t keytype) {
|
|||
};
|
||||
if (isOK) {
|
||||
if (blockNo < NumBlocksPerSector(s) - 1) {
|
||||
emlSetMem(dataoutbuf, FirstBlockOfSector(s) + blockNo, 1);
|
||||
emlSetMem_xt(dataoutbuf, FirstBlockOfSector(s) + blockNo, 1, 16);
|
||||
} else {
|
||||
// sector trailer, keep the keys, set only the AC
|
||||
emlGetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1);
|
||||
memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);
|
||||
emlSetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1);
|
||||
emlSetMem_xt(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,8 +68,10 @@ static bool fill_eml_from_file(char *dumpfile) {
|
|||
}
|
||||
//read and load dump file
|
||||
BigBuf_Clear();
|
||||
if (g_dbglevel >= DBG_INFO)
|
||||
Dbprintf(_YELLOW_("Found dump file %s. Uploading to emulator memory..."), dumpfile);
|
||||
if (g_dbglevel >= DBG_INFO) {
|
||||
Dbprintf("Found dump file... `" _YELLOW_("%s") "`", dumpfile);
|
||||
Dbprintf("Uploading to emulator memory...");
|
||||
}
|
||||
uint8_t *emCARD = BigBuf_get_EM_addr();
|
||||
rdv40_spiffs_read_as_filetype(dumpfile, emCARD, size, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
return true;
|
||||
|
|
|
@ -273,12 +273,12 @@ static int saMifareECardLoad(uint32_t numofsectors, uint8_t keytype) {
|
|||
};
|
||||
|
||||
if (blockNo < NumBlocksPerSector(s) - 1) {
|
||||
emlSetMem(dataoutbuf, FirstBlockOfSector(s) + blockNo, 1);
|
||||
emlSetMem_xt(dataoutbuf, FirstBlockOfSector(s) + blockNo, 1, 16);
|
||||
} else {
|
||||
// sector trailer, keep the keys, set only the AC
|
||||
emlGetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1);
|
||||
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);
|
||||
}
|
||||
}
|
||||
emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
|
||||
emlSetMem_xt(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1, 16);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,8 @@ static bool fill_eml_from_file(char *dumpfile) {
|
|||
|
||||
//read and load dump file
|
||||
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();
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include "commonutil.h"
|
||||
#include "crc16.h"
|
||||
#include "protocols.h"
|
||||
#include "mifareutil.h"
|
||||
|
||||
|
||||
#ifdef WITH_LCD
|
||||
|
@ -783,6 +784,15 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
g_reply_via_usb = false;
|
||||
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
|
||||
case CMD_SET_DBGMODE: {
|
||||
g_dbglevel = packet->data.asBytes[0];
|
||||
|
@ -1144,27 +1154,27 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
|
||||
#ifdef WITH_EM4x50
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
case CMD_LF_EM4X50_LOGIN: {
|
||||
em4x50_login((uint32_t *)packet->data.asBytes, true);
|
||||
em4x50_login((const uint32_t *)packet->data.asBytes, true);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_EM4X50_SIM: {
|
||||
|
@ -1174,7 +1184,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
// destroy the Emulator Memory.
|
||||
//-----------------------------------------------------------------------------
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
em4x50_sim((uint32_t *)packet->data.asBytes, true);
|
||||
em4x50_sim((const uint32_t *)packet->data.asBytes, true);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_EM4X50_READER: {
|
||||
|
@ -1198,7 +1208,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
// destroy the Emulator Memory.
|
||||
//-----------------------------------------------------------------------------
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
em4x50_chk((uint8_t *)packet->data.asBytes, true);
|
||||
em4x50_chk((const char *)packet->data.asBytes, true);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
@ -1278,7 +1288,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
uint8_t data[];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
EmlSetMemIso15693(payload->count, payload->data, payload->offset);
|
||||
emlSet(payload->data, payload->offset, payload->count);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO15693_SIMULATE: {
|
||||
|
@ -1684,7 +1694,14 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
uint8_t data[];
|
||||
} PACKED;
|
||||
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;
|
||||
}
|
||||
case CMD_HF_MIFARE_EML_MEMGET: {
|
||||
|
@ -1923,6 +1940,10 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
iClass_Restore((iclass_restore_req_t *)packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_CREDIT_EPURSE: {
|
||||
iclass_credit_epurse((iclass_credit_epurse_t *)packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_HFSNIFF
|
||||
|
@ -2499,6 +2520,9 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
Flash_WriteEnable();
|
||||
Flash_Erase4k(3, 0xC);
|
||||
} else if (payload->startidx == DEFAULT_MF_KEYS_OFFSET) {
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
Flash_WriteEnable();
|
||||
Flash_Erase4k(3, 0x8);
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
Flash_WriteEnable();
|
||||
Flash_Erase4k(3, 0x9);
|
||||
|
@ -2703,6 +2727,7 @@ void __attribute__((noreturn)) AppMain(void) {
|
|||
SpinDelay(100);
|
||||
BigBuf_initialize();
|
||||
|
||||
// Add stack canary
|
||||
for (uint32_t *p = _stack_start; p + 0x200 < _stack_end ; ++p) {
|
||||
*p = 0xdeadbeef;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ bool g_reply_with_crc_on_fpc = true;
|
|||
bool g_reply_via_fpc = 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}}};
|
||||
|
||||
// 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) {
|
||||
len = MIN(len, PM3_CMD_DATA_SIZE);
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
uint64_t arg[3] = {arg0, arg1, arg2};
|
||||
if (len > PM3_CMD_DATA_SIZE - sizeof(arg)) {
|
||||
|
|
|
@ -27,9 +27,9 @@ extern bool g_reply_with_crc_on_fpc;
|
|||
extern bool g_reply_via_fpc;
|
||||
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_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);
|
||||
|
||||
#endif // _PROXMARK_CMD_H_
|
||||
|
|
|
@ -74,7 +74,7 @@ void Dbprintf(const char *fmt, ...) {
|
|||
}
|
||||
|
||||
// prints HEX & ASCII
|
||||
void Dbhexdump(int len, uint8_t *d, bool bAsci) {
|
||||
void Dbhexdump(int len, const uint8_t *d, bool bAsci) {
|
||||
#if DEBUG
|
||||
char ascii[9];
|
||||
|
||||
|
@ -103,9 +103,9 @@ void Dbhexdump(int len, uint8_t *d, bool bAsci) {
|
|||
#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;
|
||||
|
||||
for (; p - buf < tmp; p += 16) {
|
||||
|
|
|
@ -22,40 +22,12 @@
|
|||
#include "common.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 DbpStringEx(uint32_t flags, const char *src, size_t srclen);
|
||||
void Dbprintf(const char *fmt, ...);
|
||||
void DbprintfEx(uint32_t flags, const char *fmt, ...);
|
||||
void Dbhexdump(int len, uint8_t *d, bool bAsci);
|
||||
void print_result(const char *name, uint8_t *buf, size_t len);
|
||||
void Dbhexdump(int len, const uint8_t *d, bool bAsci);
|
||||
void print_result(const char *name, const uint8_t *buf, size_t len);
|
||||
//void PrintToSendBuffer(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -634,7 +634,7 @@ static int login(uint32_t password) {
|
|||
}
|
||||
|
||||
// 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;
|
||||
bool pwd_found = false;
|
||||
|
@ -694,7 +694,7 @@ static bool brute(em4x50_data_t *etd, uint32_t *pwd) {
|
|||
}
|
||||
|
||||
// login into EM4x50
|
||||
void em4x50_login(uint32_t *password, bool ledcontrol) {
|
||||
void em4x50_login(const uint32_t *password, bool ledcontrol) {
|
||||
em4x50_setup_read();
|
||||
|
||||
int status = PM3_EFAILED;
|
||||
|
@ -713,7 +713,7 @@ void em4x50_login(uint32_t *password, bool ledcontrol) {
|
|||
}
|
||||
|
||||
// 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();
|
||||
|
||||
bool bsuccess = false;
|
||||
|
@ -733,7 +733,7 @@ void em4x50_brute(em4x50_data_t *etd, bool ledcontrol) {
|
|||
}
|
||||
|
||||
// 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;
|
||||
uint32_t pwd = 0x0;
|
||||
|
||||
|
@ -743,11 +743,11 @@ void em4x50_chk(uint8_t *filename, bool ledcontrol) {
|
|||
|
||||
int changed = rdv40_spiffs_lazy_mount();
|
||||
uint16_t pwd_count = 0;
|
||||
uint32_t size = size_in_spiffs((char *)filename);
|
||||
uint32_t size = size_in_spiffs(filename);
|
||||
pwd_count = size / 4;
|
||||
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)
|
||||
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
|
||||
void em4x50_read(em4x50_data_t *etd, bool ledcontrol) {
|
||||
void em4x50_read(const em4x50_data_t *etd, bool ledcontrol) {
|
||||
int status = PM3_EFAILED;
|
||||
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
|
||||
void em4x50_info(em4x50_data_t *etd, bool ledcontrol) {
|
||||
void em4x50_info(const em4x50_data_t *etd, bool ledcontrol) {
|
||||
int status = PM3_EFAILED;
|
||||
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,
|
||||
// single word is written to given address, verified by selective read operation
|
||||
// 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;
|
||||
uint32_t words[EM4X50_NO_WORDS] = {0x0};
|
||||
|
||||
|
@ -1113,7 +1113,7 @@ void em4x50_write(em4x50_data_t *etd, bool ledcontrol) {
|
|||
}
|
||||
|
||||
// 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;
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
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();
|
||||
wait_cycles(EM4X50_T_TAG_HALF_PERIOD);
|
||||
|
@ -1460,7 +1460,7 @@ static void em4x50_sim_send_nak(void) {
|
|||
}
|
||||
|
||||
// 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
|
||||
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)
|
||||
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
|
||||
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)
|
||||
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
|
||||
uint32_t password = 0;
|
||||
|
@ -1581,7 +1581,7 @@ static int em4x50_sim_handle_login_command(uint32_t *tag, bool ledcontrol) {
|
|||
}
|
||||
|
||||
// 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)
|
||||
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
|
||||
// LED C -> reader command has been detected
|
||||
// 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;
|
||||
|
||||
|
|
|
@ -21,20 +21,21 @@
|
|||
|
||||
#include "../include/em4x50.h"
|
||||
|
||||
// used by standalone mode
|
||||
void em4x50_setup_read(void);
|
||||
int standard_read(int *now, uint32_t *words);
|
||||
|
||||
void em4x50_setup_sim(void);
|
||||
void em4x50_handle_commands(int *command, uint32_t *tag, bool ledcontrol);
|
||||
|
||||
void em4x50_info(em4x50_data_t *etd, bool ledcontrol);
|
||||
void em4x50_write(em4x50_data_t *etd, bool ledcontrol);
|
||||
void em4x50_writepwd(em4x50_data_t *etd, bool ledcontrol);
|
||||
void em4x50_read(em4x50_data_t *etd, bool ledcontrol);
|
||||
void em4x50_brute(em4x50_data_t *etd, bool ledcontrol);
|
||||
void em4x50_login(uint32_t *password, bool ledcontrol);
|
||||
void em4x50_sim(uint32_t *password, bool ledcontrol);
|
||||
// dispatch functions (appmain.c)
|
||||
void em4x50_info(const em4x50_data_t *etd, bool ledcontrol);
|
||||
void em4x50_write(const em4x50_data_t *etd, bool ledcontrol);
|
||||
void em4x50_writepwd(const em4x50_data_t *etd, bool ledcontrol);
|
||||
void em4x50_read(const em4x50_data_t *etd, bool ledcontrol);
|
||||
void em4x50_brute(const em4x50_data_t *etd, 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_chk(uint8_t *filename, bool ledcontrol);
|
||||
void em4x50_chk(const char *filename, bool ledcontrol);
|
||||
|
||||
#endif /* EM4X50_H */
|
||||
|
|
|
@ -310,6 +310,7 @@ static bool check_ack(void) {
|
|||
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) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int set_byte(uint8_t *target, int value) {
|
||||
int c = value > 0xFF;
|
||||
// Sets one (reflected) byte and returns carry bit
|
||||
// (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);
|
||||
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);
|
||||
switch (address) {
|
||||
case 9:
|
||||
c = set_byte(&temp_rnd[0], rev_rnd[0] + (rev_k & 0xFF));
|
||||
c = set_byte(&temp_rnd[1], rev_rnd[1] + c + ((rev_k >> 8) & 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) & 0xFFu));
|
||||
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[4], rev_rnd[4] + c);
|
||||
|
@ -383,16 +386,16 @@ static int bruteforce(const uint8_t address, const uint8_t *rnd, const uint8_t *
|
|||
break;
|
||||
|
||||
case 8:
|
||||
c = set_byte(&temp_rnd[2], rev_rnd[2] + (rev_k & 0xFF));
|
||||
c = set_byte(&temp_rnd[3], rev_rnd[3] + c + ((rev_k >> 8) & 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) & 0xFFu));
|
||||
c = set_byte(&temp_rnd[4], rev_rnd[4] + c);
|
||||
c = set_byte(&temp_rnd[5], rev_rnd[5] + c);
|
||||
set_byte(&temp_rnd[6], rev_rnd[6] + c);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
c = set_byte(&temp_rnd[4], rev_rnd[4] + (rev_k & 0xFF));
|
||||
c = set_byte(&temp_rnd[5], rev_rnd[5] + c + ((rev_k >> 8) & 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) & 0xFFu));
|
||||
set_byte(&temp_rnd[6], rev_rnd[6] + c);
|
||||
break;
|
||||
|
||||
|
@ -707,7 +710,7 @@ static int em4x70_receive(uint8_t *bits, size_t length) {
|
|||
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;
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
void em4x70_write(em4x70_data_t *etd, bool ledcontrol) {
|
||||
void em4x70_write(const em4x70_data_t *etd, bool ledcontrol) {
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void em4x70_unlock(em4x70_data_t *etd, bool ledcontrol) {
|
||||
void em4x70_unlock(const em4x70_data_t *etd, bool ledcontrol) {
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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 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));
|
||||
}
|
||||
|
||||
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 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));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -850,7 +853,7 @@ void em4x70_write_pin(em4x70_data_t *etd, bool ledcontrol) {
|
|||
if (em4x70_read_id()) {
|
||||
|
||||
// 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)) {
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -30,12 +30,12 @@ typedef enum {
|
|||
FALLING_EDGE
|
||||
} edge_detection_t;
|
||||
|
||||
void em4x70_info(em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_write(em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_brute(em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_unlock(em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_auth(em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_write_pin(em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_write_key(em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_info(const em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_write(const em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_brute(const em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_unlock(const em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_auth(const em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_write_pin(const em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_write_key(const em4x70_data_t *etd, bool ledcontrol);
|
||||
|
||||
#endif /* EM4x70_H */
|
||||
|
|
38
armsrc/epa.c
38
armsrc/epa.c
|
@ -37,6 +37,24 @@
|
|||
static const uint8_t pps[] = {0xD0, 0x11, 0x00, 0x52, 0xA6};
|
||||
#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
|
||||
|
||||
// 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
|
||||
//-----------------------------------------------------------------------------
|
||||
void EPA_Finish(void) {
|
||||
static void EPA_Finish(void) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
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 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;
|
||||
|
||||
|
@ -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
|
||||
// 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
|
||||
// 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)
|
||||
|
@ -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
|
||||
//-----------------------------------------------------------------------------
|
||||
void EPA_PACE_Collect_Nonce(PacketCommandNG *c) {
|
||||
void EPA_PACE_Collect_Nonce(const PacketCommandNG *c) {
|
||||
/*
|
||||
* ack layout:
|
||||
* arg:
|
||||
|
@ -354,7 +372,7 @@ void EPA_PACE_Collect_Nonce(PacketCommandNG *c) {
|
|||
struct p {
|
||||
uint32_t m;
|
||||
} 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);
|
||||
// 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
|
||||
// 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
|
||||
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
|
||||
// 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
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
void EPA_PACE_Replay(PacketCommandNG *c) {
|
||||
void EPA_PACE_Replay(const PacketCommandNG *c) {
|
||||
|
||||
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)
|
||||
// Returns 0 on success or a non-zero error code on failure
|
||||
//-----------------------------------------------------------------------------
|
||||
int EPA_Setup(void) {
|
||||
static int EPA_Setup(void) {
|
||||
|
||||
#ifdef WITH_ISO14443a
|
||||
{
|
||||
|
@ -593,7 +611,7 @@ int EPA_Setup(void) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
void EPA_PACE_Simulate(PacketCommandNG *c) {
|
||||
void EPA_PACE_Simulate(const PacketCommandNG *c) {
|
||||
|
||||
//---------Initializing---------
|
||||
|
||||
|
|
24
armsrc/epa.h
24
armsrc/epa.h
|
@ -22,26 +22,8 @@
|
|||
#include "common.h"
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
// this struct is used by EPA_Parse_CardAccess and contains info about the
|
||||
// PACE protocol supported by the chip
|
||||
typedef struct {
|
||||
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);
|
||||
void EPA_PACE_Collect_Nonce(const PacketCommandNG *c);
|
||||
void EPA_PACE_Replay(const PacketCommandNG *c);
|
||||
void EPA_PACE_Simulate(const PacketCommandNG *c);
|
||||
|
||||
#endif /* __EPA_H */
|
||||
|
|
|
@ -49,7 +49,7 @@ static uint32_t felica_lasttime_prox2air_start;
|
|||
|
||||
static void iso18092_setup(uint8_t fpga_minor_mode);
|
||||
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 void iso18092_set_timeout(uint32_t timeout) {
|
||||
|
@ -269,13 +269,13 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
|
|||
// copy UID
|
||||
// idm 8
|
||||
if (card) {
|
||||
memcpy(card->IDm, FelicaFrame.framebytes + 4, 8);
|
||||
memcpy(card->IDm, FelicaFrame.framebytes + 4, 8);
|
||||
memcpy(card->PMm, FelicaFrame.framebytes + 4 + 8, 8);
|
||||
//memcpy(card->servicecode, FelicaFrame.framebytes + 4 + 8 + 8, 2);
|
||||
memcpy(card->code, card->IDm, 2);
|
||||
memcpy(card->uid, card->IDm + 2, 6);
|
||||
memcpy(card->iccode, card->PMm, 2);
|
||||
memcpy(card->mrt, card->PMm + 2, 6);
|
||||
memcpy(card->code, card->IDm, 2);
|
||||
memcpy(card->uid, card->IDm + 2, 6);
|
||||
memcpy(card->iccode, card->PMm, 2);
|
||||
memcpy(card->mrt, card->PMm + 2, 6);
|
||||
if (g_dbglevel >= DBG_DEBUG) {
|
||||
Dbprintf("Received Frame: ");
|
||||
Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes, 0);
|
||||
|
@ -350,7 +350,12 @@ static void BuildFliteRdblk(const uint8_t *idm, uint8_t blocknum, const uint16_t
|
|||
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;
|
||||
if (power)
|
||||
flags |= FPGA_HF_ISO18092_FLAG_READER;
|
||||
|
@ -512,12 +517,12 @@ static void felica_reset_frame_mode(void) {
|
|||
// arg0 FeliCa flags
|
||||
// arg1 len of commandbytes
|
||||
// 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");
|
||||
|
||||
felica_command_t param = c->oldarg[0];
|
||||
size_t len = c->oldarg[1] & 0xffff;
|
||||
uint8_t *cmd = c->data.asBytes;
|
||||
const uint8_t *cmd = c->data.asBytes;
|
||||
uint32_t arg0;
|
||||
|
||||
felica_card_select_t card;
|
||||
|
@ -675,7 +680,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
|
|||
#define R_READBLK_LEN 0x21
|
||||
//simulate NFC Tag3 card - for now only poll response works
|
||||
// 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...
|
||||
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};
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
#include "common.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_sim_lite(uint8_t *uid);
|
||||
void felica_sim_lite(const uint8_t *uid);
|
||||
void felica_dump_lite_s(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -95,40 +95,40 @@ void SetupSpi(int mode) {
|
|||
case SPI_FPGA_MODE:
|
||||
AT91C_BASE_SPI->SPI_MR =
|
||||
(0 << 24) | // Delay between chip selects (take default: 6 MCK periods)
|
||||
(0xE << 16) | // Peripheral Chip Select (selects FPGA SPI_NCS0 or PA11)
|
||||
(0xE << 16) | // Peripheral Chip Select (selects FPGA SPI_NCS0 or PA11)
|
||||
(0 << 7) | // Local Loopback Disabled
|
||||
AT91C_SPI_MODFDIS | // Mode Fault Detection disabled
|
||||
AT91C_SPI_MODFDIS | // Mode Fault Detection disabled
|
||||
(0 << 2) | // Chip selects connected directly to peripheral
|
||||
AT91C_SPI_PS_FIXED | // Fixed Peripheral Select
|
||||
AT91C_SPI_PS_FIXED | // Fixed Peripheral Select
|
||||
AT91C_SPI_MSTR; // Master Mode
|
||||
|
||||
AT91C_BASE_SPI->SPI_CSR[0] =
|
||||
(1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
|
||||
(1 << 16) | // Delay Before SPCK (1 MCK period)
|
||||
(6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24MHz/6 = 4M baud
|
||||
AT91C_SPI_BITS_16 | // Bits per Transfer (16 bits)
|
||||
AT91C_SPI_BITS_16 | // Bits per Transfer (16 bits)
|
||||
(0 << 3) | // Chip Select inactive after transfer
|
||||
AT91C_SPI_NCPHA | // Clock Phase data captured on leading edge, changes on following edge
|
||||
AT91C_SPI_NCPHA | // Clock Phase data captured on leading edge, changes on following edge
|
||||
(0 << 0); // Clock Polarity inactive state is logic 0
|
||||
break;
|
||||
/*
|
||||
case SPI_LCD_MODE:
|
||||
AT91C_BASE_SPI->SPI_MR =
|
||||
( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods)
|
||||
(0xB << 16) | // Peripheral Chip Select (selects LCD SPI_NCS2 or PA10)
|
||||
( 0 << 7) | // Local Loopback Disabled
|
||||
( 1 << 4) | // Mode Fault Detection disabled
|
||||
( 0 << 2) | // Chip selects connected directly to peripheral
|
||||
( 0 << 1) | // Fixed Peripheral Select
|
||||
( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods)
|
||||
(0xB << 16) | // Peripheral Chip Select (selects LCD SPI_NCS2 or PA10)
|
||||
( 0 << 7) | // Local Loopback Disabled
|
||||
( 1 << 4) | // Mode Fault Detection disabled
|
||||
( 0 << 2) | // Chip selects connected directly to peripheral
|
||||
( 0 << 1) | // Fixed Peripheral Select
|
||||
( 1 << 0); // Master Mode
|
||||
|
||||
AT91C_BASE_SPI->SPI_CSR[2] =
|
||||
( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
|
||||
( 1 << 16) | // Delay Before SPCK (1 MCK period)
|
||||
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24MHz/6 = 4M baud
|
||||
AT91C_SPI_BITS_9 | // Bits per Transfer (9 bits)
|
||||
( 0 << 3) | // Chip Select inactive after transfer
|
||||
( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge
|
||||
( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
|
||||
( 1 << 16) | // Delay Before SPCK (1 MCK period)
|
||||
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24MHz/6 = 4M baud
|
||||
AT91C_SPI_BITS_9 | // Bits per Transfer (9 bits)
|
||||
( 0 << 3) | // Chip Select inactive after transfer
|
||||
( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge
|
||||
( 0 << 0); // Clock Polarity inactive state is logic 0
|
||||
break;
|
||||
*/
|
||||
|
@ -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
|
||||
// pulse, no output sync
|
||||
if (((fpga_mode & FPGA_MAJOR_MODE_MASK) == FPGA_MAJOR_MODE_HF_READER ||
|
||||
(fpga_mode & FPGA_MAJOR_MODE_MASK) == FPGA_MAJOR_MODE_HF_FSK_READER) &&
|
||||
if (((fpga_mode & FPGA_MAJOR_MODE_MASK) == FPGA_MAJOR_MODE_HF_READER) &&
|
||||
(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);
|
||||
} else {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) Jonathan Westhues, April 2006
|
||||
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
|
@ -32,76 +31,116 @@
|
|||
#define FPGA_BITSTREAM_HF_15 4
|
||||
|
||||
/*
|
||||
Communication between ARM / FPGA is done inside armsrc/fpgaloader.c (function FpgaSendCommand)
|
||||
Send 16 bit command / data pair to FPGA
|
||||
The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
|
||||
where
|
||||
C is 4bit command
|
||||
D is 12bit data
|
||||
Communication between ARM / FPGA is done inside armsrc/fpgaloader.c see: function FpgaSendCommand()
|
||||
Send 16 bit command / data pair to FPGA with the bit format:
|
||||
|
||||
+------ frame layout circa 2020 ------------------+
|
||||
| 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 |
|
||||
+-------------------------------------------------+
|
||||
| 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
|
||||
-----+-------------------------------------------
|
||||
*/
|
||||
|
||||
// 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.
|
||||
// Defining commands, modes and options. This must be aligned to the definitions in fpga/define.v
|
||||
#define FPGA_MAJOR_MODE_MASK 0x01C0
|
||||
#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_EDGE_DETECT (1<<6)
|
||||
#define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<6)
|
||||
#define FPGA_MAJOR_MODE_LF_ADC (3<<6)
|
||||
|
||||
// HF
|
||||
#define FPGA_MAJOR_MODE_HF_READER (0<<6) // D
|
||||
#define FPGA_MAJOR_MODE_HF_SIMULATOR (1<<6) // D
|
||||
#define FPGA_MAJOR_MODE_HF_ISO14443A (2<<6) // D
|
||||
#define FPGA_MAJOR_MODE_HF_SNIFF (3<<6) // D
|
||||
#define FPGA_MAJOR_MODE_HF_ISO18092 (4<<6) // D
|
||||
#define FPGA_MAJOR_MODE_HF_GET_TRACE (5<<6) // D
|
||||
#define FPGA_MAJOR_MODE_HF_FSK_READER (6<<6) // D
|
||||
|
||||
// BOTH HF / LF
|
||||
#define FPGA_MAJOR_MODE_OFF (7<<6) // D
|
||||
|
||||
#define FPGA_MAJOR_MODE_HF_READER (0<<6)
|
||||
#define FPGA_MAJOR_MODE_HF_SIMULATOR (1<<6)
|
||||
#define FPGA_MAJOR_MODE_HF_ISO14443A (2<<6)
|
||||
#define FPGA_MAJOR_MODE_HF_SNIFF (3<<6)
|
||||
#define FPGA_MAJOR_MODE_HF_ISO18092 (4<<6)
|
||||
#define FPGA_MAJOR_MODE_HF_GET_TRACE (5<<6)
|
||||
#define FPGA_MAJOR_MODE_OFF (7<<6)
|
||||
|
||||
// Options for LF_READER
|
||||
#define FPGA_LF_ADC_READER_FIELD 0x1
|
||||
#define FPGA_LF_ADC_READER_FIELD ( 1 )
|
||||
|
||||
// Options for LF_EDGE_DETECT
|
||||
#define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1
|
||||
#define FPGA_LF_EDGE_DETECT_READER_FIELD 0x1
|
||||
#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE 0x2
|
||||
#define FPGA_LF_EDGE_DETECT_READER_FIELD ( 1 )
|
||||
#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE ( 2 )
|
||||
|
||||
// Options for the HF reader
|
||||
#define FPGA_HF_READER_MODE_RECEIVE_IQ (0<<0)
|
||||
#define FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE (1<<0)
|
||||
#define FPGA_HF_READER_MODE_RECEIVE_PHASE (2<<0)
|
||||
#define FPGA_HF_READER_MODE_SEND_FULL_MOD (3<<0)
|
||||
#define FPGA_HF_READER_MODE_SEND_SHALLOW_MOD (4<<0)
|
||||
#define FPGA_HF_READER_MODE_SNIFF_IQ (5<<0)
|
||||
#define FPGA_HF_READER_MODE_SNIFF_AMPLITUDE (6<<0)
|
||||
#define FPGA_HF_READER_MODE_SNIFF_PHASE (7<<0)
|
||||
#define FPGA_HF_READER_MODE_SEND_JAM (8<<0)
|
||||
// Options for the generic HF reader
|
||||
#define FPGA_HF_READER_MODE_RECEIVE_IQ ( 0 )
|
||||
#define FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE ( 1 )
|
||||
#define FPGA_HF_READER_MODE_RECEIVE_PHASE ( 2 )
|
||||
#define FPGA_HF_READER_MODE_SEND_FULL_MOD ( 3 )
|
||||
#define FPGA_HF_READER_MODE_SEND_SHALLOW_MOD ( 4 )
|
||||
#define FPGA_HF_READER_MODE_SNIFF_IQ ( 5 )
|
||||
#define FPGA_HF_READER_MODE_SNIFF_AMPLITUDE ( 6 )
|
||||
#define FPGA_HF_READER_MODE_SNIFF_PHASE ( 7 )
|
||||
#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_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)
|
||||
|
||||
// Options for the HF simulated tag, how to modulate
|
||||
#define FPGA_HF_SIMULATOR_NO_MODULATION 0x0 // 0000
|
||||
#define FPGA_HF_SIMULATOR_MODULATE_BPSK 0x1 // 0001
|
||||
#define FPGA_HF_SIMULATOR_MODULATE_212K 0x2 // 0010
|
||||
#define FPGA_HF_SIMULATOR_MODULATE_424K 0x4 // 0100
|
||||
#define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5 // 0101
|
||||
// no 848K
|
||||
#define FPGA_HF_SIMULATOR_NO_MODULATION ( 0 )
|
||||
#define FPGA_HF_SIMULATOR_MODULATE_BPSK ( 1 )
|
||||
#define FPGA_HF_SIMULATOR_MODULATE_212K ( 2 )
|
||||
#define FPGA_HF_SIMULATOR_MODULATE_424K ( 4 )
|
||||
#define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT ( 5 )
|
||||
|
||||
// Options for ISO14443A
|
||||
#define FPGA_HF_ISO14443A_SNIFFER 0x0
|
||||
#define FPGA_HF_ISO14443A_TAGSIM_LISTEN 0x1
|
||||
#define FPGA_HF_ISO14443A_TAGSIM_MOD 0x2
|
||||
#define FPGA_HF_ISO14443A_READER_LISTEN 0x3
|
||||
#define FPGA_HF_ISO14443A_READER_MOD 0x4
|
||||
#define FPGA_HF_ISO14443A_SNIFFER ( 0 )
|
||||
#define FPGA_HF_ISO14443A_TAGSIM_LISTEN ( 1 )
|
||||
#define FPGA_HF_ISO14443A_TAGSIM_MOD ( 2 )
|
||||
#define FPGA_HF_ISO14443A_READER_LISTEN ( 3 )
|
||||
#define FPGA_HF_ISO14443A_READER_MOD ( 4 )
|
||||
|
||||
//options for Felica.
|
||||
#define FPGA_HF_ISO18092_FLAG_NOMOD 0x1 // 0001 disable modulation module
|
||||
#define FPGA_HF_ISO18092_FLAG_424K 0x2 // 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
|
||||
// Options for ISO18092 / Felica
|
||||
#define FPGA_HF_ISO18092_FLAG_NOMOD ( 1 ) // 0001 disable modulation module
|
||||
#define FPGA_HF_ISO18092_FLAG_424K ( 2 ) // 0010 should enable 414k mode (untested). No autodetect
|
||||
#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 FpgaWriteConfWord(uint16_t v);
|
||||
|
|
|
@ -200,7 +200,7 @@ static uint32_t HfEncodeTkm(const uint8_t *uid, uint8_t modulation, uint8_t *dat
|
|||
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
|
||||
BigBuf_free_keep_EM();
|
||||
|
||||
|
|
|
@ -22,6 +22,6 @@
|
|||
#include "common.h"
|
||||
|
||||
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
|
||||
|
|
|
@ -281,7 +281,7 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_
|
|||
}
|
||||
break;
|
||||
|
||||
// Received RWD authentication challenge and respnse
|
||||
// Received RWD authentication challenge and response
|
||||
case 64: {
|
||||
// Store the authentication attempt
|
||||
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) {
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
void EloadHitag(uint8_t *data, uint16_t len) {
|
||||
void EloadHitag(const uint8_t *data, uint16_t len) {
|
||||
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);
|
||||
}
|
||||
|
||||
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 response_start = 0, response_duration = 0;
|
||||
|
@ -1928,7 +1928,7 @@ out:
|
|||
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_duration = 0;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
void SniffHitag2(bool ledcontrol);
|
||||
void SimulateHitag2(bool ledcontrol);
|
||||
void ReaderHitag(hitag_function htf, hitag_data *htd, bool ledcontrol);
|
||||
void WriterHitag(hitag_function htf, hitag_data *htd, int page, bool ledcontrol);
|
||||
void EloadHitag(uint8_t *data, uint16_t len);
|
||||
void ReaderHitag(hitag_function htf, const hitag_data *htd, bool ledcontrol);
|
||||
void WriterHitag(hitag_function htf, const hitag_data *htd, int page, bool ledcontrol);
|
||||
void EloadHitag(const uint8_t *data, uint16_t len);
|
||||
#endif
|
||||
|
|
|
@ -91,17 +91,17 @@ uint32_t _hitag2_byte(uint64_t *x) {
|
|||
|
||||
void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv) {
|
||||
uint64_t key = ((uint64_t)tag->sectors[2][2]) |
|
||||
((uint64_t)tag->sectors[2][3] << 8) |
|
||||
((uint64_t)tag->sectors[2][3] << 8) |
|
||||
((uint64_t)tag->sectors[1][0] << 16) |
|
||||
((uint64_t)tag->sectors[1][1] << 24) |
|
||||
((uint64_t)tag->sectors[1][2] << 32) |
|
||||
((uint64_t)tag->sectors[1][3] << 40);
|
||||
uint32_t uid = ((uint32_t)tag->sectors[0][0]) |
|
||||
((uint32_t)tag->sectors[0][1] << 8) |
|
||||
((uint32_t)tag->sectors[0][1] << 8) |
|
||||
((uint32_t)tag->sectors[0][2] << 16) |
|
||||
((uint32_t)tag->sectors[0][3] << 24);
|
||||
uint32_t iv_ = (((uint32_t)(iv[0]))) |
|
||||
(((uint32_t)(iv[1])) << 8) |
|
||||
(((uint32_t)(iv[1])) << 8) |
|
||||
(((uint32_t)(iv[2])) << 16) |
|
||||
(((uint32_t)(iv[3])) << 24);
|
||||
tag->cs = _hitag2_init(REV64(key), REV32(uid), REV32(iv_));
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data, bool ledcontrol) {
|
||||
void SimulateHitagSTag(bool tag_mem_supplied, const uint8_t *data, bool ledcontrol) {
|
||||
|
||||
StopTicks();
|
||||
|
||||
|
@ -1052,7 +1052,7 @@ static size_t concatbits(uint8_t *dstbuf, size_t dstbufskip, const uint8_t *srcb
|
|||
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();
|
||||
|
||||
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.
|
||||
* 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];
|
||||
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.
|
||||
* 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;
|
||||
//check for valid input
|
||||
|
@ -1443,7 +1443,7 @@ write_end:
|
|||
* is not received correctly due to Antenna problems. This function
|
||||
* 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
|
||||
if (datalen < 8) {
|
||||
Dbprintf("Error, need chals");
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
#include "hitag.h"
|
||||
|
||||
void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data, bool ledcontrol);
|
||||
void ReadHitagS(hitag_function htf, hitag_data *htd, bool ledcontrol);
|
||||
void WritePageHitagS(hitag_function htf, hitag_data *htd, int page, bool ledcontrol);
|
||||
void Hitag_check_challenges(uint8_t *data, uint32_t datalen, bool ledcontrol);
|
||||
void SimulateHitagSTag(bool tag_mem_supplied, const uint8_t *data, bool ledcontrol);
|
||||
void ReadHitagS(hitag_function htf, const hitag_data *htd, bool ledcontrol);
|
||||
void WritePageHitagS(hitag_function htf, const hitag_data *htd, int page, bool ledcontrol);
|
||||
void Hitag_check_challenges(const uint8_t *data, uint32_t datalen, bool ledcontrol);
|
||||
#endif
|
||||
|
|
|
@ -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 ).
|
||||
// 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;
|
||||
do {
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
bool bBreak = true;
|
||||
|
||||
|
@ -772,7 +772,7 @@ void SmartCardAtr(void) {
|
|||
// StopTicks();
|
||||
}
|
||||
|
||||
void SmartCardRaw(smart_card_raw_t *p) {
|
||||
void SmartCardRaw(const smart_card_raw_t *p) {
|
||||
LED_D_ON();
|
||||
|
||||
uint16_t len = 0;
|
||||
|
|
|
@ -41,12 +41,12 @@ void I2C_Reset_EnterBootloader(void);
|
|||
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_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);
|
||||
|
||||
// for firmware
|
||||
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);
|
||||
//
|
||||
|
@ -54,7 +54,7 @@ bool GetATR(smart_card_atr_t *card_ptr, bool verbose);
|
|||
|
||||
// generice functions
|
||||
void SmartCardAtr(void);
|
||||
void SmartCardRaw(smart_card_raw_t *p);
|
||||
void SmartCardRaw(const smart_card_raw_t *p);
|
||||
void SmartCardUpgrade(uint64_t arg0);
|
||||
void SmartCardSetBaud(uint64_t arg0);
|
||||
void SmartCardSetClock(uint64_t arg0);
|
||||
|
|
157
armsrc/iclass.c
157
armsrc/iclass.c
|
@ -1902,13 +1902,13 @@ void iClass_WriteBlock(uint8_t *msg) {
|
|||
|
||||
// verify write
|
||||
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
|
||||
if (memcmp(payload->data + 4, resp, 4) || memcmp(payload->data, resp + 4, 4)) {
|
||||
res = false;
|
||||
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
|
||||
if (memcmp(all_ff, resp, 8)) {
|
||||
res = false;
|
||||
|
@ -1929,6 +1929,159 @@ out:
|
|||
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) {
|
||||
|
||||
// sanitation
|
||||
|
|
|
@ -25,6 +25,7 @@ void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string);
|
|||
void ReaderIClass(uint8_t flags);
|
||||
|
||||
void iClass_WriteBlock(uint8_t *msg);
|
||||
void iclass_credit_epurse(iclass_credit_epurse_t *payload);
|
||||
void iClass_Dump(uint8_t *msg);
|
||||
|
||||
void iClass_Restore(iclass_restore_req_t *msg);
|
||||
|
|
|
@ -142,6 +142,15 @@ Default HF 14a config is set to:
|
|||
*/
|
||||
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) {
|
||||
DbpString(_CYAN_("HF 14a config"));
|
||||
Dbprintf(" [a] Anticol override.... %s%s%s",
|
||||
|
@ -179,7 +188,7 @@ void printHf14aConfig(void) {
|
|||
* @brief setSamplingConfig
|
||||
* @param sc
|
||||
*/
|
||||
void setHf14aConfig(hf14a_config *hc) {
|
||||
void setHf14aConfig(const hf14a_config *hc) {
|
||||
|
||||
if ((hc->forceanticol >= 0) && (hc->forceanticol <= 2))
|
||||
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) {
|
||||
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
|
||||
rATQA[0] = 0x04;
|
||||
sak = 0x08;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2: { // MIFARE Ultralight
|
||||
rATQA[0] = 0x44;
|
||||
sak = 0x00;
|
||||
|
@ -1076,33 +1085,32 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
|
|||
// READ_SIG
|
||||
memcpy(rSIGN, mfu_header->signature, 32);
|
||||
AddCrc14A(rSIGN, sizeof(rSIGN) - 2);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3: { // MIFARE DESFire
|
||||
rATQA[0] = 0x44;
|
||||
rATQA[1] = 0x03;
|
||||
sak = 0x20;
|
||||
memcpy(rRATS, "\x06\x75\x77\x81\x02\x80\x00\x00", 8);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4: { // ISO/IEC 14443-4 - javacard (JCOP)
|
||||
rATQA[0] = 0x04;
|
||||
sak = 0x28;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 5: { // MIFARE TNP3XXX
|
||||
rATQA[0] = 0x01;
|
||||
rATQA[1] = 0x0f;
|
||||
sak = 0x01;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6: { // MIFARE Mini 320b
|
||||
rATQA[0] = 0x44;
|
||||
sak = 0x09;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 7: { // NTAG
|
||||
case 7: { // NTAG 215
|
||||
rATQA[0] = 0x44;
|
||||
sak = 0x00;
|
||||
// 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
|
||||
memcpy(rSIGN, mfu_header->signature, 32);
|
||||
AddCrc14A(rSIGN, sizeof(rSIGN) - 2);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 8: { // MIFARE Classic 4k
|
||||
rATQA[0] = 0x02;
|
||||
sak = 0x18;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 9: { // FM11RF005SH (Shanghai Metro)
|
||||
rATQA[0] = 0x03;
|
||||
rATQA[1] = 0x00;
|
||||
sak = 0x0A;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 10: { // ST25TA IKEA Rothult
|
||||
rATQA[0] = 0x42;
|
||||
rATQA[1] = 0x00;
|
||||
sak = 0x20;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 11: { // ISO/IEC 14443-4 - javacard (JCOP)
|
||||
rATQA[0] = 0x04;
|
||||
sak = 0x20;
|
||||
break;
|
||||
}
|
||||
case 12: { // HID Seos 4K card
|
||||
rATQA[0] = 0x01;
|
||||
sak = 0x20;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default: {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Error: unknown tagtype (%d)", tagType);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// EV1/NTAG, set PWD w AMIIBO algo if all zero.
|
||||
if (tagType == 7) {
|
||||
uint8_t pwd[4];
|
||||
uint8_t gen_pwd[4];
|
||||
uint16_t start = (*pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH;
|
||||
emlGetMemBt(pwd, start, sizeof(pwd));
|
||||
uint8_t pwd[4] = {0, 0, 0, 0};
|
||||
uint8_t gen_pwd[4] = {0, 0, 0, 0};
|
||||
emlGetMemBt(pwd, (*pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(pwd));
|
||||
emlGetMemBt(rPACK, (*pages) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(rPACK));
|
||||
|
||||
Uint4byteToMemBe(gen_pwd, ul_ev1_pwdgenB(data));
|
||||
if (memcmp(pwd, gen_pwd, sizeof(pwd)) == 0) {
|
||||
rPACK[0] = 0x80;
|
||||
rPACK[1] = 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
AddCrc14A(rPACK, sizeof(rPACK) - 2);
|
||||
|
||||
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.
|
||||
p_response = &responses[RESP_INDEX_UIDC1];
|
||||
} 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);
|
||||
AddCrc14A(emdata, 16);
|
||||
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
|
||||
EmSend4bit(CARD_NACK_IV);
|
||||
} else {
|
||||
uint8_t emdata[MAX_FRAME_SIZE];
|
||||
uint8_t emdata[MAX_FRAME_SIZE] = {0};
|
||||
// first blocks of emu are header
|
||||
int start = block1 * 4 + MFU_DUMP_PREFIX_LENGTH;
|
||||
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
|
||||
EmSend4bit(CARD_NACK_IV);
|
||||
} else {
|
||||
uint8_t cmd[3];
|
||||
uint8_t cmd[3] = {0, 0, 0};
|
||||
cmd[0] = tearings[index];
|
||||
AddCrc14A(cmd, sizeof(cmd) - 2);
|
||||
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
|
||||
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
p_response = NULL;
|
||||
} else if (receivedCmd[0] == MIFARE_ULEV1_AUTH && len == 7 && tagType == 7) { // NTAG / EV-1 authentication
|
||||
|
||||
/*
|
||||
// PWD stored in dump now
|
||||
uint8_t pwd[4];
|
||||
} else if (receivedCmd[0] == MIFARE_ULEV1_AUTH && len == 7 && tagType == 7) { // NTAG / EV-1
|
||||
uint8_t pwd[4] = {0, 0, 0, 0};
|
||||
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) {
|
||||
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) {
|
||||
|
||||
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));
|
||||
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Password match, responding with PACK.");
|
||||
p_response = &responses[RESP_INDEX_PACK];
|
||||
} else {
|
||||
EmSend4bit(CARD_NACK_NA);
|
||||
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Auth attempt: %08x", bytes_to_num(receivedCmd + 1, 4));
|
||||
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Password did not match, NACK_IV.");
|
||||
p_response = NULL;
|
||||
EmSend4bit(CARD_NACK_IV);
|
||||
}
|
||||
p_response = NULL;
|
||||
*/
|
||||
p_response = &responses[RESP_INDEX_PACK];
|
||||
|
||||
} 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);
|
||||
AddCrc14A(cmd, sizeof(cmd) - 2);
|
||||
EmSendCmd(cmd, sizeof(cmd));
|
||||
|
@ -2355,8 +2364,9 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive
|
|||
}
|
||||
|
||||
// timeout already in ms + 100ms guard time
|
||||
if (GetTickCountDelta(receive_timer) > timeout + 100)
|
||||
if (GetTickCountDelta(receive_timer) > timeout + 100) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
if (!GetIso14443aAnswerFromTag(receivedAnswer, par, offset))
|
||||
if (GetIso14443aAnswerFromTag(receivedAnswer, par, offset) == false) {
|
||||
return 0;
|
||||
}
|
||||
LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false);
|
||||
return Demod.len;
|
||||
}
|
||||
|
||||
uint16_t ReaderReceive(uint8_t *receivedAnswer, uint8_t *par) {
|
||||
if (!GetIso14443aAnswerFromTag(receivedAnswer, par, 0))
|
||||
if (GetIso14443aAnswerFromTag(receivedAnswer, par, 0) == false) {
|
||||
return 0;
|
||||
}
|
||||
LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false);
|
||||
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
|
||||
#define ECP_RETRY_TIMEOUT 100
|
||||
#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);
|
||||
}
|
||||
static int GetATQA(uint8_t *resp, uint8_t *resp_par, iso14a_polling_parameters_t *polling_parameters) {
|
||||
#define WUPA_RETRY_TIMEOUT 10
|
||||
|
||||
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.
|
||||
|
||||
bool first_try = true;
|
||||
uint32_t retry_timeout = use_ecp ? ECP_RETRY_TIMEOUT : WUPA_RETRY_TIMEOUT;
|
||||
uint32_t start_time;
|
||||
uint32_t retry_timeout = WUPA_RETRY_TIMEOUT * polling_parameters->frame_count + polling_parameters->extra_timeout;
|
||||
uint32_t start_time = 0;
|
||||
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 {
|
||||
if (use_ecp && !first_try) {
|
||||
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);
|
||||
iso14a_polling_frame_t *frame_parameters = &polling_parameters->frames[current_frame];
|
||||
|
||||
if (frame_parameters->last_byte_bits == 8) {
|
||||
ReaderTransmit(frame_parameters->frame, frame_parameters->frame_length, NULL);
|
||||
} else {
|
||||
ReaderTransmitBitsPar(frame_parameters->frame, frame_parameters->last_byte_bits, NULL, NULL);
|
||||
}
|
||||
|
||||
if (use_magsafe) {
|
||||
if (wupa[0] == MAGSAFE_CMD_WUPA_4) {
|
||||
wupa[0] = MAGSAFE_CMD_WUPA_1;
|
||||
} else {
|
||||
wupa[0]++;
|
||||
}
|
||||
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
|
||||
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;
|
||||
|
||||
// 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);
|
||||
|
||||
iso14a_set_timeout(save_iso14a_timeout);
|
||||
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) {
|
||||
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
|
||||
// fills the uid and cuid pointer unless NULL
|
||||
// fills the card info record unless NULL
|
||||
// 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)
|
||||
// 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_par[MAX_PARITY_SIZE] = {0};
|
||||
|
||||
uint8_t sak; // cascade uid
|
||||
uint8_t sak = 0; // cascade uid
|
||||
bool do_cascade = 1;
|
||||
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;
|
||||
}
|
||||
|
||||
if (GetATQA(resp, resp_par, use_ecp, use_magsafe) == false) {
|
||||
if (GetATQA(resp, resp_par, polling_parameters) == 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);
|
||||
|
||||
// select again?
|
||||
if (GetATQA(resp, resp_par, false, false) == false) {
|
||||
if (GetATQA(resp, resp_par, &WUPA_POLLING_PARAMETERS) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (GetATQA(resp, resp_par, false, false) == false) {
|
||||
if (GetATQA(resp, resp_par, &WUPA_POLLING_PARAMETERS) == 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
|
||||
int cascade_level = 0;
|
||||
|
||||
if (!GetATQA(resp, resp_par, false, false)) {
|
||||
if (GetATQA(resp, resp_par, &WUPA_POLLING_PARAMETERS) == 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);
|
||||
|
||||
// Receive the SAK
|
||||
if (!ReaderReceive(resp, resp_par)) return 0;
|
||||
if (!ReaderReceive(resp, resp_par)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
sak = resp[0];
|
||||
|
||||
|
@ -3035,7 +3032,12 @@ void ReaderIso14443a(PacketCommandNG *c) {
|
|||
// if failed selecting, turn off antenna and quite.
|
||||
if (!(param & ISO14A_NO_SELECT)) {
|
||||
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();
|
||||
|
||||
reply_mix(CMD_ACK, arg0, card->uidlen, 0, buf, sizeof(iso14a_card_select_t));
|
||||
|
|
|
@ -121,7 +121,7 @@ typedef enum {
|
|||
#endif
|
||||
|
||||
void printHf14aConfig(void);
|
||||
void setHf14aConfig(hf14a_config *hc);
|
||||
void setHf14aConfig(const hf14a_config *hc);
|
||||
hf14a_config *getHf14aConfig(void);
|
||||
void iso14a_set_timeout(uint32_t timeout);
|
||||
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);
|
||||
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_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);
|
||||
void iso14a_set_trigger(bool enable);
|
||||
|
||||
|
|
|
@ -39,9 +39,14 @@
|
|||
* Current timing issues with ISO14443-b implementation
|
||||
* Proxmark3
|
||||
* Carrier Frequency 13.56MHz
|
||||
* 1 / 13 560 000 = 73.74 nano seconds ( 0.07374 µs )
|
||||
|
||||
* 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.
|
||||
* ----------
|
||||
* 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
|
||||
// FWT(max) = 4949 ms or 4.95 seconds.
|
||||
// SSP_CLK = 4949000 * 3.39 = 16777120
|
||||
|
@ -122,8 +130,8 @@
|
|||
|
||||
// ETU 14 * 9.4395 µS = 132 µS == 0.132ms
|
||||
// TR2, counting from start of PICC EOF 14 ETU.
|
||||
#define DELAY_ISO14443B_PICC_TO_PCD_READER ETU_TO_SSP(14)
|
||||
#define DELAY_ISO14443B_PCD_TO_PICC_READER ETU_TO_SSP(15)
|
||||
#define DELAY_ISO14443B_PICC_TO_PCD_READER HF14_ETU_TO_SSP(14)
|
||||
#define DELAY_ISO14443B_PCD_TO_PICC_READER HF14_ETU_TO_SSP(15)
|
||||
|
||||
/* Guard Time (per 14443-2) in ETU
|
||||
*
|
||||
|
@ -138,41 +146,41 @@
|
|||
* TR0
|
||||
*/
|
||||
#ifndef ISO14B_TR0
|
||||
# define ISO14B_TR0 ETU_TO_SSP(32)
|
||||
# define ISO14B_TR0 HF14_ETU_TO_SSP(16)
|
||||
#endif
|
||||
|
||||
#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 - FWT for all other commands
|
||||
|
||||
// TR0 max is 151/fsc = 151/848kHz = 302us or 64 samples from FPGA
|
||||
// 32 ETU * 9.4395 µS == 302 µS
|
||||
// 32 * 8 = 256 sub carrier cycles,
|
||||
// 256 / 4 = 64 I/Q pairs.
|
||||
// TR0 max is 159 µS or 32 samples from FPGA
|
||||
// 16 ETU * 9.4395 µS == 151 µS
|
||||
// 16 * 8 = 128 sub carrier cycles,
|
||||
// 128 / 4 = 32 I/Q pairs.
|
||||
// since 1 I/Q pair after 4 subcarrier cycles at 848kHz subcarrier
|
||||
#endif
|
||||
|
||||
// 8 ETU = 75 µS == 256 SSP_CLK
|
||||
#ifndef ISO14B_TR0_MIN
|
||||
# define ISO14B_TR0_MIN ETU_TO_SSP(8)
|
||||
# define ISO14B_TR0_MIN HF14_ETU_TO_SSP(8)
|
||||
#endif
|
||||
|
||||
// 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
|
||||
# define ISO14B_TR1_MIN ETU_TO_SSP(10)
|
||||
# define ISO14B_TR1_MIN HF14_ETU_TO_SSP(16)
|
||||
#endif
|
||||
// Synchronization time (per 14443-2) in ETU
|
||||
// 25 ETU == 236 µS == 800 SSP_CLK
|
||||
#ifndef ISO14B_TR1_MAX
|
||||
# define ISO14B_TR1 ETU_TO_SSP(25)
|
||||
# define ISO14B_TR1 HF14_ETU_TO_SSP(25)
|
||||
#endif
|
||||
|
||||
// Frame Delay Time PICC to PCD (per 14443-3 Amendment 1) in ETU
|
||||
// 14 ETU == 132 µS == 448 SSP_CLK
|
||||
#ifndef ISO14B_TR2
|
||||
# define ISO14B_TR2 ETU_TO_SSP(14)
|
||||
# define ISO14B_TR2 HF14_ETU_TO_SSP(14)
|
||||
#endif
|
||||
|
||||
// 4sample
|
||||
|
@ -440,7 +448,7 @@ static void Uart14bInit(uint8_t *data) {
|
|||
// param timeout accepts 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)
|
||||
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
|
||||
// response to send, and send it.
|
||||
//-----------------------------------------------------------------------------
|
||||
void SimulateIso14443bTag(uint8_t *pupi) {
|
||||
void SimulateIso14443bTag(const uint8_t *pupi) {
|
||||
|
||||
LED_A_ON();
|
||||
// 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) {
|
||||
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
|
||||
// + (10) // time for TR1
|
||||
+ (10 + 2) // time for SOF transfer
|
||||
|
@ -1399,8 +1407,11 @@ static void TransmitFor14443b_AsReader(uint32_t *start_time) {
|
|||
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
||||
// TR2 minimum 14 ETUs
|
||||
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 = *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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
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);
|
||||
FpgaDisableTracing();
|
||||
|
||||
|
@ -1836,7 +1853,7 @@ int iso14443b_select_xrx_card(iso14b_card_select_t *card) {
|
|||
int 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);
|
||||
|
||||
|
@ -2076,7 +2093,6 @@ void iso14443b_setup(void) {
|
|||
|
||||
// allocate command receive buffer
|
||||
BigBuf_free();
|
||||
BigBuf_Clear_ext(false);
|
||||
|
||||
// Initialize Demod and Uart structs
|
||||
Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE), MAX_FRAME_SIZE);
|
||||
|
@ -2089,7 +2105,12 @@ void iso14443b_setup(void) {
|
|||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER);
|
||||
|
||||
// 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);
|
||||
#endif
|
||||
|
||||
SpinDelay(100);
|
||||
|
||||
// Start the timer
|
||||
|
@ -2395,6 +2416,7 @@ void SendRawCommand14443B_Ex(iso14b_raw_cmd_t *p) {
|
|||
|
||||
if ((p->flags & ISO14B_CLEARTRACE) == ISO14B_CLEARTRACE) {
|
||||
clear_trace();
|
||||
BigBuf_Clear_ext(false);
|
||||
}
|
||||
set_tracing(true);
|
||||
|
||||
|
|
|
@ -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_xrx_card(iso14b_card_select_t *card);
|
||||
|
||||
void SimulateIso14443bTag(uint8_t *pupi);
|
||||
void SimulateIso14443bTag(const uint8_t *pupi);
|
||||
void AcquireRawAdcSamplesIso14443b(uint32_t parameter);
|
||||
void ReadSTBlock(uint8_t blocknr);
|
||||
void SniffIso14443b(void);
|
||||
|
|
|
@ -294,7 +294,12 @@ void CodeIso15693AsTag(const uint8_t *cmd, size_t len) {
|
|||
// 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) {
|
||||
|
||||
#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));
|
||||
#endif
|
||||
|
||||
|
||||
if (*start_time < DELAY_ARM_TO_TAG) {
|
||||
*start_time = DELAY_ARM_TO_TAG;
|
||||
|
@ -2119,7 +2124,6 @@ void Iso15693InitTag(void) {
|
|||
StartCountSspClk();
|
||||
}
|
||||
|
||||
|
||||
void EmlClearIso15693(void) {
|
||||
// Resetting the bitstream also frees the BigBuf memory, so we do this here to prevent
|
||||
// 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);
|
||||
}
|
||||
|
||||
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
|
||||
// all demodulation performed in arm rather than host. - greg
|
||||
void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
|
||||
|
@ -2296,8 +2290,11 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
|
|||
}
|
||||
// Block data
|
||||
if (block_size * (block_idx + j + 1) <= CARD_MEMORY_SIZE) {
|
||||
EmlGetMemIso15693(block_size, resp_readblock + (work_offset + security_offset),
|
||||
block_size * (block_idx + j));
|
||||
emlGet(
|
||||
resp_readblock + (work_offset + security_offset),
|
||||
block_size * (block_idx + j),
|
||||
block_size
|
||||
);
|
||||
} else {
|
||||
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;
|
||||
|
||||
// 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
|
||||
int response_length = 3;
|
||||
|
@ -2664,7 +2661,7 @@ void SetTag15693Uid(const uint8_t *uid) {
|
|||
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);
|
||||
if (rnd) {
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
|
@ -2741,7 +2738,7 @@ static uint32_t set_pass_15693_Slix(uint32_t start_time, uint32_t *eof_time, uin
|
|||
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];
|
||||
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
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];
|
||||
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;
|
||||
}
|
||||
|
||||
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};
|
||||
|
||||
|
@ -2849,7 +2846,7 @@ static uint32_t write_password_15693_Slix(uint32_t start_time, uint32_t *eof_tim
|
|||
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;
|
||||
|
||||
|
@ -2888,7 +2885,7 @@ static uint32_t pass_protect_EASAFI_15693_Slix(uint32_t start_time, uint32_t *eo
|
|||
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) {
|
||||
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];
|
||||
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
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();
|
||||
Iso15693InitReader();
|
||||
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();
|
||||
Iso15693InitReader();
|
||||
StartCountSspClk();
|
||||
|
@ -3033,7 +3030,7 @@ void DisablePrivacySlixIso15693(uint8_t *password) {
|
|||
switch_off();
|
||||
}
|
||||
|
||||
void EnablePrivacySlixIso15693(uint8_t *password) {
|
||||
void EnablePrivacySlixIso15693(const uint8_t *password) {
|
||||
LED_D_ON();
|
||||
Iso15693InitReader();
|
||||
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();
|
||||
Iso15693InitReader();
|
||||
StartCountSspClk();
|
||||
|
@ -3067,7 +3064,7 @@ void DisableEAS_AFISlixIso15693(uint8_t *password, bool usepwd) {
|
|||
switch_off();
|
||||
}
|
||||
|
||||
void EnableEAS_AFISlixIso15693(uint8_t *password, bool usepwd) {
|
||||
void EnableEAS_AFISlixIso15693(const uint8_t *password, bool usepwd) {
|
||||
LED_D_ON();
|
||||
Iso15693InitReader();
|
||||
StartCountSspClk();
|
||||
|
@ -3082,7 +3079,7 @@ void EnableEAS_AFISlixIso15693(uint8_t *password, bool usepwd) {
|
|||
switch_off();
|
||||
}
|
||||
|
||||
void PassProtextEASSlixIso15693(uint8_t *password) {
|
||||
void PassProtextEASSlixIso15693(const uint8_t *password) {
|
||||
LED_D_ON();
|
||||
Iso15693InitReader();
|
||||
StartCountSspClk();
|
||||
|
@ -3091,7 +3088,7 @@ void PassProtextEASSlixIso15693(uint8_t *password) {
|
|||
reply_ng(CMD_HF_ISO15693_SLIX_PASS_PROTECT_EAS, res, NULL, 0);
|
||||
switch_off();
|
||||
}
|
||||
void PassProtectAFISlixIso15693(uint8_t *password) {
|
||||
void PassProtectAFISlixIso15693(const uint8_t *password) {
|
||||
LED_D_ON();
|
||||
Iso15693InitReader();
|
||||
StartCountSspClk();
|
||||
|
@ -3101,7 +3098,7 @@ void PassProtectAFISlixIso15693(uint8_t *password) {
|
|||
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();
|
||||
Iso15693InitReader();
|
||||
StartCountSspClk();
|
||||
|
|
|
@ -47,8 +47,6 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo
|
|||
void AcquireRawAdcSamplesIso15693(void);
|
||||
void ReaderIso15693(iso15_card_select_t *p_card); // ISO15693 reader
|
||||
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 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
|
||||
|
@ -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 WritePasswordSlixIso15693(uint8_t *old_password, uint8_t *new_password, uint8_t pwd_id);
|
||||
void DisablePrivacySlixIso15693(uint8_t *password);
|
||||
void EnablePrivacySlixIso15693(uint8_t *password);
|
||||
void DisableEAS_AFISlixIso15693(uint8_t *password, bool usepwd);
|
||||
void EnableEAS_AFISlixIso15693(uint8_t *password, bool usepwd);
|
||||
void PassProtextEASSlixIso15693(uint8_t *password);
|
||||
void PassProtectAFISlixIso15693(uint8_t *password);
|
||||
void WriteAFIIso15693(uint8_t *password, bool usepwd, uint8_t *uid, bool use_uid, uint8_t afi);
|
||||
void WritePasswordSlixIso15693(const uint8_t *old_password, const uint8_t *new_password, uint8_t pwd_id);
|
||||
void DisablePrivacySlixIso15693(const uint8_t *password);
|
||||
void EnablePrivacySlixIso15693(const uint8_t *password);
|
||||
void DisableEAS_AFISlixIso15693(const uint8_t *password, bool usepwd);
|
||||
void EnableEAS_AFISlixIso15693(const uint8_t *password, bool usepwd);
|
||||
void PassProtextEASSlixIso15693(const uint8_t *password);
|
||||
void PassProtectAFISlixIso15693(const uint8_t *password);
|
||||
void WriteAFIIso15693(const uint8_t *password, bool usepwd, uint8_t *uid, bool use_uid, uint8_t afi);
|
||||
#endif
|
||||
|
|
|
@ -528,7 +528,7 @@ OUT:
|
|||
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
|
||||
init_reader();
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
void LegicRfInfo(void);
|
||||
int LegicRfReaderEx(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);
|
||||
#endif /* __LEGICRF_H */
|
||||
|
|
|
@ -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 0
|
||||
// - 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
|
||||
uint32_t bit_start = last_frame_end;
|
||||
|
||||
// wait for pause to end
|
||||
if (!wait_for(RWD_PULSE, bit_start + RWD_TIME_1 * 3 / 2)) {
|
||||
return -1;
|
||||
if (wait_for(RWD_PULSE, bit_start + RWD_TIME_1 * 3 / 2) == false) {
|
||||
return PM3_ERFTRANS;
|
||||
}
|
||||
|
||||
// wait for next pause
|
||||
if (!wait_for(RWD_PAUSE, bit_start + RWD_TIME_1 * 3 / 2)) {
|
||||
return -1;
|
||||
if (wait_for(RWD_PAUSE, bit_start + RWD_TIME_1 * 3 / 2) == false) {
|
||||
return PM3_ERFTRANS;
|
||||
}
|
||||
|
||||
// update bit and frame end
|
||||
|
@ -110,7 +110,7 @@ static int8_t rx_bit(void) {
|
|||
|
||||
// check for code violation (bit to short)
|
||||
if (last_frame_end - bit_start < RWD_TIME_PAUSE) {
|
||||
return -1;
|
||||
return PM3_ERFTRANS;
|
||||
}
|
||||
|
||||
// apply threshold (average of RWD_TIME_0 and )
|
||||
|
@ -215,7 +215,6 @@ static void tx_ack(void) {
|
|||
// - receive the frame
|
||||
// - detect end of frame (last pause)
|
||||
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)
|
||||
// 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
|
||||
if (i > RWD_CMD_TIMEOUT) {
|
||||
return -1;
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
// backup ts for trace log
|
||||
uint32_t last_frame_start = last_frame_end;
|
||||
int32_t frame = 0;
|
||||
|
||||
// receive frame
|
||||
for (*len = 0; true; ++(*len)) {
|
||||
// receive next bit
|
||||
LED_B_ON();
|
||||
int8_t bit = rx_bit();
|
||||
int32_t bit = rx_bit();
|
||||
LED_B_OFF();
|
||||
|
||||
// check for code violation and to short / long frame
|
||||
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
|
||||
|
@ -353,7 +353,7 @@ static int32_t setup_phase(legic_card_select_t *p_card) {
|
|||
// wait for iv
|
||||
int32_t iv = rx_frame(&len);
|
||||
if ((len != 7) || (iv < 0)) {
|
||||
return -1;
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
// configure prng
|
||||
|
@ -375,19 +375,19 @@ static int32_t setup_phase(legic_card_select_t *p_card) {
|
|||
// wait for ack
|
||||
int32_t ack = rx_frame(&len);
|
||||
if ((len != 6) || (ack < 0)) {
|
||||
return -1;
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
// validate data
|
||||
switch (p_card->tagtype) {
|
||||
case 0:
|
||||
if (ack != 0x19) return -1;
|
||||
if (ack != 0x19) return PM3_ERFTRANS;
|
||||
break;
|
||||
case 1:
|
||||
if (ack != 0x39) return -1;
|
||||
if (ack != 0x39) return PM3_ERFTRANS;
|
||||
break;
|
||||
case 2:
|
||||
if (ack != 0x39) return -1;
|
||||
if (ack != 0x39) return PM3_ERFTRANS;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -399,7 +399,7 @@ static int32_t setup_phase(legic_card_select_t *p_card) {
|
|||
// the gap by one 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) {
|
||||
|
@ -414,7 +414,7 @@ static int32_t connected_phase(legic_card_select_t *p_card) {
|
|||
// wait for command
|
||||
int32_t cmd = rx_frame(&len);
|
||||
if (cmd < 0) {
|
||||
return -1;
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
// check if command is LEGIC_READ
|
||||
|
@ -425,8 +425,7 @@ static int32_t connected_phase(legic_card_select_t *p_card) {
|
|||
|
||||
// transmit data
|
||||
tx_frame((crc << 8) | byte, 12);
|
||||
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
// 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);
|
||||
if (calc_crc != crc) {
|
||||
Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc);
|
||||
return -1;
|
||||
return PM3_ECRC;
|
||||
}
|
||||
|
||||
// store data
|
||||
|
@ -449,11 +448,10 @@ static int32_t connected_phase(legic_card_select_t *p_card) {
|
|||
|
||||
// transmit ack
|
||||
tx_ack();
|
||||
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return PM3_ERFTRANS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -466,26 +464,26 @@ void LegicRfSimulate(uint8_t tagtype, bool send_reply) {
|
|||
// configure ARM and FPGA
|
||||
init_tag();
|
||||
|
||||
int res = PM3_SUCCESS;
|
||||
int res = init_card(tagtype, &card);
|
||||
// verify command line input
|
||||
if (init_card(tagtype, &card) != PM3_SUCCESS) {
|
||||
if (res != PM3_SUCCESS) {
|
||||
DbpString("Unknown tagtype to simulate");
|
||||
res = PM3_ESOFT;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
uint16_t counter = 0;
|
||||
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) {
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
if (counter >= 2000) {
|
||||
if (data_available()) {
|
||||
res = PM3_EOPABORTED;
|
||||
break;
|
||||
goto OUT;
|
||||
}
|
||||
counter = 0;
|
||||
}
|
||||
|
@ -497,12 +495,12 @@ void LegicRfSimulate(uint8_t tagtype, bool send_reply) {
|
|||
}
|
||||
|
||||
// wait for connection, restart on error
|
||||
if (setup_phase(&card)) {
|
||||
if (setup_phase(&card) != PM3_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// connection is established, process commands until one fails
|
||||
while (connected_phase(&card) == false) {
|
||||
while (connected_phase(&card) == PM3_SUCCESS) {
|
||||
WDT_HIT();
|
||||
}
|
||||
}
|
||||
|
@ -510,17 +508,19 @@ void LegicRfSimulate(uint8_t tagtype, bool send_reply) {
|
|||
OUT:
|
||||
|
||||
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)
|
||||
DbpString("aborted by user");
|
||||
if (res == PM3_EOPABORTED) {
|
||||
DbpString("Aborted by user");
|
||||
}
|
||||
|
||||
switch_off();
|
||||
StopTicks();
|
||||
|
||||
if (send_reply)
|
||||
if (send_reply) {
|
||||
reply_ng(CMD_HF_LEGIC_SIMULATE, res, NULL, 0);
|
||||
}
|
||||
|
||||
BigBuf_free_keep_EM();
|
||||
}
|
||||
|
|
|
@ -287,7 +287,7 @@ void printT55xxConfig(void) {
|
|||
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++) {
|
||||
if (c->m[i].start_gap != 0)
|
||||
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
|
||||
// simulate a FSK tag until the button is pressed
|
||||
// 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);
|
||||
|
||||
|
@ -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
|
||||
// simulate a FSK tag until the button is pressed
|
||||
// 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);
|
||||
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();
|
||||
}
|
||||
|
||||
void T55xxDangerousRawTest(uint8_t *data, bool ledcontrol) {
|
||||
void T55xxDangerousRawTest(const uint8_t *data, bool ledcontrol) {
|
||||
// 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 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
|
||||
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};
|
||||
if (q5) {
|
||||
|
|
|
@ -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 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,
|
||||
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,
|
||||
const uint8_t *bits, bool ledcontrol);
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
@ -66,7 +66,7 @@ void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block,
|
|||
uint8_t downlink_mode, bool ledcontrol);
|
||||
void T55xxWakeUp(uint32_t pwd, 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_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 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);
|
||||
void printT55xxConfig(void);
|
||||
void loadT55xxConfig(void);
|
||||
|
|
|
@ -94,7 +94,7 @@ void setDefaultSamplingConfig(void) {
|
|||
* @brief setSamplingConfig
|
||||
* @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
|
||||
if (sc->decimation > 0 && sc->decimation < 9)
|
||||
|
|
|
@ -110,7 +110,7 @@ void LFSetupFPGAForADC(int divisor, bool reader_field);
|
|||
* @brief setSamplingConfig
|
||||
* @param sc
|
||||
*/
|
||||
void setSamplingConfig(sample_config *sc);
|
||||
void setSamplingConfig(const sample_config *sc);
|
||||
void setDefaultSamplingConfig(void);
|
||||
sample_config *getSamplingConfig(void);
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ static void zx8211_setup_read(void) {
|
|||
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)
|
||||
return;
|
||||
|
|
|
@ -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;
|
||||
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
uint32_t timeout = iso14a_get_timeout();
|
||||
|
||||
LED_A_ON();
|
||||
LED_B_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;
|
||||
};
|
||||
|
||||
// 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++) {
|
||||
if (mifare_classic_readblock_ex(pcs, block_no + i, block_data + (i * 16), read_cmd)) {
|
||||
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:
|
||||
crypto1_deinit(pcs);
|
||||
|
||||
iso14a_set_timeout(timeout);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
set_tracing(false);
|
||||
BigBuf_free();
|
||||
|
||||
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_C_OFF();
|
||||
|
||||
uint8_t retval = PM3_SUCCESS;
|
||||
int retval = PM3_SUCCESS;
|
||||
|
||||
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
|
||||
|
@ -1805,8 +1810,8 @@ OUT:
|
|||
emlSetMem_xt(block, blockno, 1, sizeof(block));
|
||||
}
|
||||
|
||||
MifareECardLoad(sectorcnt, 0);
|
||||
MifareECardLoad(sectorcnt, 1);
|
||||
MifareECardLoad(sectorcnt, MF_KEY_A);
|
||||
MifareECardLoad(sectorcnt, MF_KEY_B);
|
||||
}
|
||||
} else {
|
||||
// partial/none keys found
|
||||
|
@ -2014,15 +2019,6 @@ void MifareEMemClr(void) {
|
|||
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) {
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
|
@ -2072,12 +2068,34 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
|
|||
|
||||
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++) {
|
||||
|
||||
uint64_t ui64Key = emlGetKey(s, keytype);
|
||||
|
||||
// MFC 1K EV1 sector 16,17 don't use key A.
|
||||
if ((sectorcnt == 18) && (keytype == 0) && s > 15) {
|
||||
continue;
|
||||
if (sectorcnt == 18) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -2110,43 +2128,56 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
|
|||
// Auth
|
||||
if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(s), keytype, ui64Key, AUTH_FIRST)) {
|
||||
retval = PM3_EPARTIAL;
|
||||
if (g_dbglevel > DBG_ERROR) {
|
||||
if (g_dbglevel >= DBG_ERROR) {
|
||||
Dbprintf("Sector %2d - Auth error", s);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
#define MAX_RETRIES 2
|
||||
|
||||
uint8_t data[16] = {0x00};
|
||||
for (uint8_t b = 0; b < NumBlocksPerSector(s); b++) {
|
||||
|
||||
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++) {
|
||||
|
||||
if (mifare_classic_readblock(pcs, FirstBlockOfSector(s) + b, data)) {
|
||||
int res = mifare_classic_readblock(pcs, tb, data);
|
||||
if (res == 1) {
|
||||
retval |= PM3_EPARTIAL;
|
||||
if (g_dbglevel > DBG_ERROR) {
|
||||
Dbprintf("Error reading sector %2d block %2d", s, b);
|
||||
if (g_dbglevel >= DBG_ERROR) {
|
||||
Dbprintf("Error No rights reading sector %2d block %2d", s, b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// retry if wrong len.
|
||||
if (res != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (b < NumBlocksPerSector(s) - 1) {
|
||||
emlSetMem(data, FirstBlockOfSector(s) + b, 1);
|
||||
} else {
|
||||
if (IsSectorTrailer(b)) {
|
||||
// sector trailer, keep the keys, set only the AC
|
||||
uint8_t st[16] = {0x00};
|
||||
emlGetMem(st, FirstBlockOfSector(s) + b, 1);
|
||||
emlGetMem(st, tb, 1);
|
||||
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);
|
||||
(void)res;
|
||||
|
||||
iso14a_set_timeout(timeout);
|
||||
crypto1_deinit(pcs);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
|
@ -2322,6 +2354,12 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
|
|||
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
|
||||
while (true) {
|
||||
if (workFlags & MAGIC_WUPC) {
|
||||
|
@ -2343,7 +2381,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
|
|||
}
|
||||
|
||||
// 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");
|
||||
errormsg = 0;
|
||||
break;
|
||||
|
@ -2371,6 +2409,8 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
|
|||
|
||||
if (workFlags & MAGIC_OFF)
|
||||
OnSuccessMagic();
|
||||
|
||||
iso14a_set_timeout(timeout);
|
||||
}
|
||||
|
||||
void MifareCIdent(bool is_mfc) {
|
||||
|
|
|
@ -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 MifareEMemClr(void);
|
||||
void MifareEMemSet(uint8_t blockno, uint8_t blockcnt, uint8_t blockwidth, uint8_t *datain);
|
||||
void MifareEMemGet(uint8_t blockno, uint8_t blockcnt);
|
||||
int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype);
|
||||
int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype);
|
||||
|
|
|
@ -523,7 +523,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
|
|||
uint8_t rAUTH_NT_keystream[4];
|
||||
uint32_t nonce = 0;
|
||||
|
||||
tUart14a *uart = GetUart14a();
|
||||
const tUart14a *uart = GetUart14a();
|
||||
|
||||
// free eventually allocated BigBuf memory but keep Emulator Memory
|
||||
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
|
||||
}
|
||||
}
|
||||
emlSetMem(receivedCmd_dec, cardWRBL, 1);
|
||||
emlSetMem_xt(receivedCmd_dec, cardWRBL, 1, 16);
|
||||
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); // always ACK?
|
||||
FpgaDisableTracing();
|
||||
|
||||
|
|
|
@ -116,7 +116,9 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t
|
|||
|
||||
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 (len == 1) {
|
||||
|
@ -127,8 +129,9 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t
|
|||
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 3)) << 3;
|
||||
answer[0] = res;
|
||||
} else {
|
||||
for (pos = 0; pos < len; pos++)
|
||||
for (pos = 0; pos < len; pos++) {
|
||||
answer[pos] = crypto1_byte(pcs, 0x00, 0) ^ answer[pos];
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
|
||||
// set timeout for authentication response
|
||||
if (save_timeout > 103)
|
||||
iso14a_set_timeout(103);
|
||||
if (save_timeout > 106)
|
||||
iso14a_set_timeout(106);
|
||||
|
||||
// Receive 4 byte tag answer
|
||||
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);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -610,32 +617,28 @@ uint8_t FirstBlockOfSector(uint8_t sectorNo) {
|
|||
return sectorNo * 4;
|
||||
else
|
||||
return 32 * 4 + (sectorNo - 32) * 16;
|
||||
|
||||
}
|
||||
|
||||
// work with emulator memory
|
||||
void emlSetMem(uint8_t *data, int blockNum, int blocksCount) {
|
||||
emlSetMem_xt(data, blockNum, blocksCount, 16);
|
||||
}
|
||||
|
||||
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 emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int block_width) {
|
||||
uint32_t offset = blockNum * block_width;
|
||||
uint32_t len = blocksCount * block_width;
|
||||
emlSet(data, offset, len);
|
||||
}
|
||||
|
||||
void emlGetMem(uint8_t *data, int blockNum, int blocksCount) {
|
||||
uint8_t *emCARD = BigBuf_get_EM_addr();
|
||||
memcpy(data, emCARD + blockNum * 16, blocksCount * 16);
|
||||
uint8_t *mem = BigBuf_get_EM_addr();
|
||||
memcpy(data, mem + blockNum * 16, blocksCount * 16);
|
||||
}
|
||||
|
||||
void emlGetMemBt(uint8_t *data, int offset, int byteCount) {
|
||||
uint8_t *emCARD = BigBuf_get_EM_addr();
|
||||
memcpy(data, emCARD + offset, byteCount);
|
||||
uint8_t *mem = BigBuf_get_EM_addr();
|
||||
memcpy(data, mem + offset, byteCount);
|
||||
}
|
||||
|
||||
int emlCheckValBl(int blockNum) {
|
||||
uint8_t *emCARD = BigBuf_get_EM_addr();
|
||||
uint8_t *data = emCARD + blockNum * 16;
|
||||
uint8_t *mem = BigBuf_get_EM_addr();
|
||||
uint8_t *data = mem + blockNum * 16;
|
||||
|
||||
if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) ||
|
||||
(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) {
|
||||
uint8_t *emCARD = BigBuf_get_EM_addr();
|
||||
uint8_t *data = emCARD + blockNum * 16;
|
||||
uint8_t *mem = BigBuf_get_EM_addr();
|
||||
uint8_t *data = mem + blockNum * 16;
|
||||
|
||||
if (emlCheckValBl(blockNum))
|
||||
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) {
|
||||
uint8_t *emCARD = BigBuf_get_EM_addr();
|
||||
uint8_t *data = emCARD + blockNum * 16;
|
||||
uint8_t *mem = BigBuf_get_EM_addr();
|
||||
uint8_t *data = mem + blockNum * 16;
|
||||
|
||||
memcpy(data + 0, &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[14] = blBlock;
|
||||
data[15] = blBlock ^ 0xff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t emlGetKey(int sectorNum, int keyType) {
|
||||
uint8_t key[6] = {0x00};
|
||||
uint8_t *em = BigBuf_get_EM_addr();
|
||||
memcpy(key, em + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6);
|
||||
uint8_t *mem = BigBuf_get_EM_addr();
|
||||
memcpy(key, mem + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6);
|
||||
return bytes_to_num(key, 6);
|
||||
}
|
||||
|
||||
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 uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04};
|
||||
uint8_t *emCARD = BigBuf_get_EM_addr();
|
||||
memset(emCARD, 0, CARD_MEMORY_SIZE);
|
||||
uint8_t *mem = BigBuf_get_EM_addr();
|
||||
memset(mem, 0, CARD_MEMORY_SIZE);
|
||||
|
||||
// fill sectors trailer data
|
||||
for (uint16_t b = 3; b < MIFARE_4K_MAXBLOCK; ((b < MIFARE_2K_MAXBLOCK - 4) ? (b += 4) : (b += 16)))
|
||||
emlSetMem((uint8_t *)trailer, b, 1);
|
||||
for (uint16_t b = 3; b < MIFARE_4K_MAXBLOCK; ((b < MIFARE_2K_MAXBLOCK - 4) ? (b += 4) : (b += 16))) {
|
||||
emlSetMem_xt((uint8_t *)trailer, b, 1, 16);
|
||||
}
|
||||
|
||||
// uid
|
||||
emlSetMem((uint8_t *)uid, 0, 1);
|
||||
emlSetMem_xt((uint8_t *)uid, 0, 1, 16);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t SectorTrailer(uint8_t blockNo) {
|
||||
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));
|
||||
}
|
||||
return (blockNo | 0x03);
|
||||
} else {
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x0f));
|
||||
return (blockNo | 0x0f);
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x0F));
|
||||
}
|
||||
return (blockNo | 0x0F);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -113,8 +113,7 @@ uint8_t SectorTrailer(uint8_t blockNo);
|
|||
|
||||
// emulator functions
|
||||
void emlClearMem(void);
|
||||
void emlSetMem(uint8_t *data, int blockNum, int blocksCount);
|
||||
void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth);
|
||||
void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int block_width);
|
||||
void emlGetMem(uint8_t *data, int blockNum, int blocksCount);
|
||||
void emlGetMemBt(uint8_t *data, int offset, int byteCount);
|
||||
uint64_t emlGetKey(int sectorNum, int keyType);
|
||||
|
|
|
@ -196,17 +196,19 @@ int rdv40_spiffs_check(void) {
|
|||
|
||||
///// 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);
|
||||
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));
|
||||
}
|
||||
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);
|
||||
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));
|
||||
}
|
||||
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) {
|
||||
uint32_t size = size_in_spiffs((char *)src);
|
||||
uint32_t size = size_in_spiffs(src);
|
||||
uint8_t *mem = BigBuf_malloc(size);
|
||||
read_from_spiffs((char *)src, (uint8_t *)mem, size);
|
||||
write_to_spiffs((char *)dst, (uint8_t *)mem, size);
|
||||
read_from_spiffs(src, (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.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)
|
||||
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(
|
||||
uint32_t idx;
|
||||
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(
|
||||
uint32_t idx;
|
||||
// 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.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( //
|
||||
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( //
|
||||
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( //
|
||||
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( //
|
||||
*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 ?")
|
||||
// ATTENTION : you must NOT provide the whole filename (so please do not include the .lnk extension)
|
||||
// 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(
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
@ -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 :
|
||||
// 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 !
|
||||
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(
|
||||
char linkfilename[SPIFFS_OBJ_NAME_LEN];
|
||||
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
|
||||
// preexistence, avoiding a link being created if filename exists, or avoiding a file being created if
|
||||
// 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(
|
||||
RDV40SpiFFSFileType filetype = filetype_in_spiffs((char *)filename);
|
||||
switch (filetype) {
|
||||
case RDV40_SPIFFS_FILETYPE_REAL:
|
||||
rdv40_spiffs_read((char *)filename, (uint8_t *)dst, size, level);
|
||||
rdv40_spiffs_read(filename, dst, size, level);
|
||||
break;
|
||||
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;
|
||||
case RDV40_SPIFFS_FILETYPE_BOTH:
|
||||
case RDV40_SPIFFS_FILETYPE_UNKNOWN:
|
||||
|
|
|
@ -46,18 +46,18 @@ typedef struct rdv40_spiffs_fsinfo {
|
|||
uint32_t usedPercent, freePercent;
|
||||
} 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_lazy_unmount(void);
|
||||
int rdv40_spiffs_lazy_mount(void);
|
||||
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_rename(char *old_filename, char *new_filename, RDV40SpiFFSSafetyLevel level);
|
||||
int rdv40_spiffs_remove(char *filename, RDV40SpiFFSSafetyLevel level);
|
||||
int rdv40_spiffs_read_as_symlink(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level);
|
||||
void write_to_spiffs(const char *filename, uint8_t *src, uint32_t size);
|
||||
int rdv40_spiffs_rename(const char *old_filename, const char *new_filename, RDV40SpiFFSSafetyLevel level);
|
||||
int rdv40_spiffs_remove(const char *filename, 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, const uint8_t *src, uint32_t size);
|
||||
void read_from_spiffs(const char *filename, uint8_t *dst, uint32_t size);
|
||||
void test_spiffs(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_is_symlink(const char *s);
|
||||
void rdv40_spiffs_safe_print_fsinfo(void);
|
||||
int rdv40_spiffs_make_symlink(char *linkdest, char *filename, RDV40SpiFFSSafetyLevel level);
|
||||
void append_to_spiffs(const char *filename, uint8_t *src, uint32_t size);
|
||||
int rdv40_spiffs_copy(char *src, char *dst, RDV40SpiFFSSafetyLevel level);
|
||||
int rdv40_spiffs_append(const char *filename, uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level);
|
||||
int rdv40_spiffs_stat(char *filename, uint32_t *buf, RDV40SpiFFSSafetyLevel level);
|
||||
int rdv40_spiffs_make_symlink(const char *linkdest, const char *filename, RDV40SpiFFSSafetyLevel level);
|
||||
void append_to_spiffs(const char *filename, const uint8_t *src, uint32_t size);
|
||||
int rdv40_spiffs_copy(const char *src_filename, const char *dst_filename, RDV40SpiFFSSafetyLevel level);
|
||||
int rdv40_spiffs_append(const char *filename, const uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level);
|
||||
int rdv40_spiffs_stat(const char *filename, uint32_t *size_in_bytes, RDV40SpiFFSSafetyLevel level);
|
||||
uint32_t size_in_spiffs(const char *filename);
|
||||
int exists_in_spiffs(const char *filename);
|
||||
|
||||
|
|
|
@ -18,6 +18,34 @@
|
|||
#include "usart.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_PIO pPIO = AT91C_BASE_PIOA;
|
||||
static volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_US1;
|
||||
|
|
|
@ -53,10 +53,10 @@ INSTALLFW = $(OBJDIR)/bootrom.elf
|
|||
|
||||
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
|
||||
$(info [=] GEN $@)
|
||||
$(Q)$(SH) ../tools/mkversion.sh > $@ || $(PERL) ../tools/mkversion.pl > $@ || $(CP) $< $@
|
||||
$(info [=] CHECK $@)
|
||||
$(Q)$(SH) ../tools/mkversion.sh $@ || $(CP) $< $@
|
||||
|
||||
all: showinfo $(OBJS)
|
||||
|
||||
|
|
|
@ -96,11 +96,12 @@ if (CMAKE_TOOLCHAIN_FILE)
|
|||
endif (ANDROID)
|
||||
set(EMBED_READLINE ON)
|
||||
set(EMBED_BZIP2 ON)
|
||||
set(EMBED_LZ4 ON)
|
||||
endif (CMAKE_TOOLCHAIN_FILE)
|
||||
|
||||
if (EMBED_READLINE OR EMBED_BZIP2)
|
||||
if (EMBED_READLINE OR EMBED_BZIP2 OR EMBED_LZ4)
|
||||
include(ExternalProject)
|
||||
endif (EMBED_READLINE OR EMBED_BZIP2)
|
||||
endif (EMBED_READLINE OR EMBED_BZIP2 OR EMBED_LZ4)
|
||||
|
||||
if (NOT SKIPREADLINE EQUAL 1)
|
||||
if (APPLE)
|
||||
|
@ -162,6 +163,7 @@ if (NOT SKIPJANSSONSYSTEM EQUAL 1)
|
|||
endif (NOT SKIPJANSSONSYSTEM EQUAL 1)
|
||||
|
||||
if(EMBED_BZIP2)
|
||||
cmake_policy(SET CMP0114 NEW)
|
||||
set(BZIP2_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/bzip2/src/bzip2)
|
||||
# Specify SOURCE_DIR will cause some errors
|
||||
ExternalProject_Add(bzip2
|
||||
|
@ -183,6 +185,34 @@ else(EMBED_BZIP2)
|
|||
find_package (BZip2 REQUIRED)
|
||||
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)
|
||||
find_path(WHEREAMI_INCLUDE_DIRS whereami.h)
|
||||
find_library(WHEREAMI_LIBRARIES whereami)
|
||||
|
@ -349,6 +379,7 @@ set (TARGET_SOURCES
|
|||
${PM3_ROOT}/client/src/fileutils.c
|
||||
${PM3_ROOT}/client/src/flash.c
|
||||
${PM3_ROOT}/client/src/graph.c
|
||||
${PM3_ROOT}/client/src/iso4217.c
|
||||
${PM3_ROOT}/client/src/jansson_path.c
|
||||
${PM3_ROOT}/client/src/preferences.c
|
||||
${PM3_ROOT}/client/src/pm3.c
|
||||
|
@ -366,7 +397,7 @@ set (TARGET_SOURCES
|
|||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c
|
||||
COMMAND sh ${PM3_ROOT}/tools/mkversion.sh > ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c
|
||||
COMMAND 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
|
||||
)
|
||||
|
||||
|
@ -456,6 +487,11 @@ if (BZIP2_FOUND)
|
|||
set(ADDITIONAL_LNK ${BZIP2_LIBRARIES} ${ADDITIONAL_LNK})
|
||||
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)
|
||||
set(ADDITIONAL_DIRS ${WHEREAMI_INCLUDE_DIRS} ${ADDITIONAL_DIRS})
|
||||
set(ADDITIONAL_LNK ${WHEREAMI_LIBRARIES} ${ADDITIONAL_LNK})
|
||||
|
@ -488,11 +524,25 @@ else (SKIPBT EQUAL 1)
|
|||
endif (BLUEZ_FOUND)
|
||||
endif(SKIPBT EQUAL 1)
|
||||
|
||||
if (EMBED_BZIP2)
|
||||
message(STATUS "Bzip2 library: embedded")
|
||||
else (EMBED_BZIP2)
|
||||
message(STATUS "Bzip2 library: system library found")
|
||||
endif (EMBED_BZIP2)
|
||||
if (BZIP2_FOUND)
|
||||
if (EMBED_BZIP2)
|
||||
message(STATUS "Bzip2 library: embedded")
|
||||
else (EMBED_BZIP2)
|
||||
message(STATUS "Bzip2 library: system library found")
|
||||
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)
|
||||
message(STATUS "Jansson library: local library forced")
|
||||
|
@ -592,6 +642,9 @@ endif (EMBED_READLINE)
|
|||
if (EMBED_BZIP2)
|
||||
add_dependencies(proxmark3 bzip2)
|
||||
endif (EMBED_BZIP2)
|
||||
if (EMBED_LZ4)
|
||||
add_dependencies(proxmark3 lz4)
|
||||
endif (EMBED_LZ4)
|
||||
|
||||
if (MINGW)
|
||||
# Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z)
|
||||
|
@ -603,21 +656,21 @@ if (MINGW)
|
|||
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}")
|
||||
|
||||
# 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)
|
||||
# beware these flags didn't exist for GCC < 7
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
|
||||
if (GCC_VERSION VERSION_GREATER 10.0 OR GCC_VERSION VERSION_EQUAL 10.0)
|
||||
set(CMAKE_C_FLAGS "-Wno-stringop-overflow -Wno-error=stringop-overflow ${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "-Wno-stringop-overflow -Wno-error=stringop-overflow ${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
|
||||
# link Winsock2
|
||||
set(ADDITIONAL_LNK ws2_32 ${ADDITIONAL_LNK})
|
||||
endif (MINGW)
|
||||
|
||||
# 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)
|
||||
# beware these flags didn't exist for GCC < 7
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
|
||||
if (GCC_VERSION VERSION_GREATER 10.0 OR GCC_VERSION VERSION_EQUAL 10.0)
|
||||
set(CMAKE_C_FLAGS "-Wno-stringop-overflow -Wno-error=stringop-overflow ${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "-Wno-stringop-overflow -Wno-error=stringop-overflow ${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
|
||||
target_include_directories(proxmark3 PRIVATE
|
||||
${PM3_ROOT}/common
|
||||
${PM3_ROOT}/common_fpga
|
||||
|
|
|
@ -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
|
||||
endif
|
||||
|
||||
ifdef ($(USE_MACPORTS),1)
|
||||
ifeq ($(USE_MACPORTS),1)
|
||||
INCLUDES += -I$(MACPORTS_PREFIX)/include
|
||||
LDLIBS += -L$(MACPORTS_PREFIX)/lib
|
||||
PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(MACPORTS_PREFIX)/lib/pkgconfig
|
||||
|
@ -242,6 +242,9 @@ endif
|
|||
## BZIP2
|
||||
LDLIBS += -lbz2
|
||||
|
||||
## LZ4
|
||||
LDLIBS += -llz4
|
||||
|
||||
## Bluez (optional)
|
||||
ifneq ($(SKIPBT),1)
|
||||
BTINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags bluez 2>/dev/null)
|
||||
|
@ -678,6 +681,7 @@ SRCS = mifare/aiddesfire.c \
|
|||
generator.c \
|
||||
graph.c \
|
||||
jansson_path.c \
|
||||
iso4217.c \
|
||||
iso7816/apduinfo.c \
|
||||
iso7816/iso7816core.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/proxguiqt.cpp: src/proxguiqt.h
|
||||
|
||||
src/proxguiqt.moc.cpp: src/proxguiqt.h
|
||||
$(info [-] MOC $@)
|
||||
$(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
|
||||
$(info [-] UIC $@)
|
||||
$(Q)$(UIC) $^ > $@
|
||||
|
@ -910,10 +918,10 @@ src/pm3_pywrap.c: pm3.i
|
|||
|
||||
.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
|
||||
$(info [=] GEN $@)
|
||||
$(Q)$(SH) ../tools/mkversion.sh > $@ || $(CP) $< $@
|
||||
$(info [=] CHECK $@)
|
||||
$(Q)$(SH) ../tools/mkversion.sh $@ || $(CP) $< $@
|
||||
|
||||
# easy printing of MAKE VARIABLES
|
||||
print-%: ; @echo $* = $($*)
|
||||
|
|
|
@ -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) {
|
||||
// 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;
|
||||
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
|
||||
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
|
||||
|
|
|
@ -96,7 +96,7 @@ static uint32_t keys_found = 0;
|
|||
static uint64_t num_keys_tested;
|
||||
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] = {
|
||||
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,
|
||||
|
@ -304,12 +304,13 @@ static bool ensure_buckets_alloc(size_t need_buckets) {
|
|||
while (need_buckets > alloc_sz) {
|
||||
alloc_sz *= 2;
|
||||
}
|
||||
|
||||
buckets = realloc(buckets, sizeof(statelist_t *) * alloc_sz);
|
||||
if (buckets == NULL) {
|
||||
statelist_t **new_buckets = realloc(buckets, sizeof(statelist_t *) * alloc_sz);
|
||||
if (new_buckets == NULL) {
|
||||
free(buckets);
|
||||
buckets_allocated = 0;
|
||||
return false;
|
||||
}
|
||||
buckets = new_buckets;
|
||||
memset(buckets + buckets_allocated, 0, (alloc_sz - buckets_allocated) * sizeof(statelist_t *));
|
||||
buckets_allocated = alloc_sz;
|
||||
}
|
||||
|
@ -412,11 +413,14 @@ static bool read_bench_data(statelist_t *test_candidates) {
|
|||
return false;
|
||||
}
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < nonces_to_bruteforce && i < 256; i++) {
|
||||
bytes_read = fread(&bf_test_nonce[i], 1, sizeof(uint32_t), benchfile);
|
||||
if (bytes_read != sizeof(uint32_t)) {
|
||||
|
@ -430,11 +434,13 @@ static bool read_bench_data(statelist_t *test_candidates) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bytes_read = fread(&num_states, 1, sizeof(uint32_t), benchfile);
|
||||
if (bytes_read != sizeof(uint32_t)) {
|
||||
fclose(benchfile);
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
if (bytes_read != sizeof(uint32_t)) {
|
||||
|
@ -442,9 +448,11 @@ static bool read_bench_data(statelist_t *test_candidates) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
for (uint32_t i = states_read; i < num_states; i++) {
|
||||
bytes_read = fread(&temp, 1, sizeof(uint32_t), benchfile);
|
||||
if (bytes_read != sizeof(uint32_t)) {
|
||||
|
@ -452,6 +460,7 @@ static bool read_bench_data(statelist_t *test_candidates) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
if (bytes_read != sizeof(uint32_t)) {
|
||||
|
@ -459,6 +468,7 @@ static bool read_bench_data(statelist_t *test_candidates) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ add_library(pm3rrg_rdv4_mbedtls STATIC
|
|||
../../common/mbedtls/error.c
|
||||
../../common/mbedtls/ecp.c
|
||||
../../common/mbedtls/ecdh.c
|
||||
../../common/mbedtls/ecc_point_compression.c
|
||||
../../common/mbedtls/gcm.c
|
||||
../../common/mbedtls/ecc_point_compression.c
|
||||
../../common/mbedtls/gcm.c
|
||||
../../common/mbedtls/ecp_curves.c
|
||||
../../common/mbedtls/certs.c
|
||||
../../common/mbedtls/camellia.c
|
||||
|
|
|
@ -232,21 +232,21 @@ static inline void put64(void *where, uint64_t 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;
|
||||
remaining -= remaining ? (ptrdiff_t)encoder->data.ptr : encoder->data.bytes_needed;
|
||||
remaining -= (ptrdiff_t)len;
|
||||
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)
|
||||
encoder->data.ptr += n;
|
||||
else
|
||||
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 (encoder->end != NULL) {
|
||||
len -= encoder->end - encoder->data.ptr;
|
||||
|
@ -263,11 +263,11 @@ static inline CborError append_to_buffer(CborEncoder *encoder, const void *data,
|
|||
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);
|
||||
}
|
||||
|
||||
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:
|
||||
* We could just write at the beginning of buf but append_to_buffer
|
||||
* only the necessary bytes.
|
||||
|
|
|
@ -142,19 +142,19 @@
|
|||
* \endif
|
||||
*/
|
||||
|
||||
static inline uint16_t get16(const uint8_t *ptr) {
|
||||
static uint16_t get16(const uint8_t *ptr) {
|
||||
uint16_t result;
|
||||
memcpy(&result, ptr, sizeof(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;
|
||||
memcpy(&result, ptr, sizeof(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;
|
||||
memcpy(&result, ptr, sizeof(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);
|
||||
}
|
||||
|
||||
static inline void prepare_string_iteration(CborValue *it) {
|
||||
static void prepare_string_iteration(CborValue *it) {
|
||||
if (!cbor_value_is_length_known(it)) {
|
||||
/* chunked string: we're before the first chunk;
|
||||
* advance to the first chunk */
|
||||
|
|
|
@ -36,6 +36,9 @@ D01AFEEB890A
|
|||
2612C6DE84CA
|
||||
707B11FC1481
|
||||
#
|
||||
# QL88 diversifed
|
||||
03F9067646AE
|
||||
2352C5B56D85
|
||||
#
|
||||
B0B1B2B3B4B5
|
||||
C0C1C2C3C4C5
|
||||
|
@ -133,6 +136,11 @@ F1D83F964314
|
|||
199404281970
|
||||
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
|
||||
000000000001
|
||||
000000000002
|
||||
|
@ -597,6 +605,7 @@ BFB6796A11DB
|
|||
# Data from Salto A/B
|
||||
6A1987C40A21
|
||||
7F33625BC129
|
||||
6BE9314930D8
|
||||
#
|
||||
# Data from forum
|
||||
2338B4913111
|
||||
|
@ -935,9 +944,9 @@ FBF225DC5D58
|
|||
# Data https://pastebin.com/BEm6bdAE
|
||||
# vingcard.txt
|
||||
# Note: most likely diversified
|
||||
96A301BCE267
|
||||
4708111C8604
|
||||
3D50D902EA48
|
||||
96A301BCE267
|
||||
6700F10FEC09
|
||||
7A09CC1DB70A
|
||||
560F7CFF2D81
|
||||
|
@ -1820,6 +1829,37 @@ E19504C39461
|
|||
FA1FBB3F0F1F
|
||||
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
|
||||
# Last update: Aug 13, 2022
|
||||
#
|
||||
|
@ -2050,9 +2090,15 @@ D144BD193063
|
|||
8627C10A7014
|
||||
453857395635
|
||||
#
|
||||
# Unknown hotel system Sec 0 / A
|
||||
353038383134
|
||||
#
|
||||
# Data from "the more the marriott" mifare project (colonelborkmundus)
|
||||
# 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
|
||||
43012BD9EB87
|
||||
# 20230125-02, Elite Member Marriott Rewards
|
||||
|
@ -2133,7 +2179,6 @@ D23C1CB1216E
|
|||
# 20230413-78, Caesars
|
||||
A1D92F808CAF
|
||||
# 20230413-79, The Cosmopolitan, Vegas
|
||||
# 96A301BCE267
|
||||
# 20230413-80, Aria
|
||||
1153C319B4F8
|
||||
# 20230413-81, Aria
|
||||
|
@ -2164,14 +2209,19 @@ D201DBB6AB6E
|
|||
09074A146605
|
||||
151F3E85EC46
|
||||
#
|
||||
#
|
||||
# Food GEM
|
||||
6686FADE5566
|
||||
#
|
||||
# Data from Discord, French pool
|
||||
9B7C25052FC3
|
||||
494446555455
|
||||
#
|
||||
# Data from Discord, seems to be related to ASSA
|
||||
427553754D47
|
||||
|
||||
# Travelodge by Wyndham Berkeley
|
||||
0000FFFFFFFF
|
||||
4663ACD2FFFF
|
||||
EDC317193709
|
||||
# Hotel Santa Cruz
|
||||
75FAB77E2E5B
|
||||
# saflok brand HOTEL key
|
||||
32F093536677
|
||||
# A WaterFront Hotel in Oakland
|
||||
3351916B5A77
|
||||
# Ballys (2018)
|
||||
336E34CC2177
|
||||
# Random Hawaiian Hotel
|
||||
A1670589B2AF
|
||||
# SF Hotel (SoMa area)
|
||||
2E0F00700000
|
||||
|
|
|
@ -97,11 +97,12 @@ if (CMAKE_TOOLCHAIN_FILE)
|
|||
endif (ANDROID)
|
||||
set(EMBED_READLINE ON)
|
||||
set(EMBED_BZIP2 ON)
|
||||
set(EMBED_LZ4 ON)
|
||||
endif (CMAKE_TOOLCHAIN_FILE)
|
||||
|
||||
if (EMBED_READLINE OR EMBED_BZIP2)
|
||||
if (EMBED_READLINE OR EMBED_BZIP2 OR EMBED_LZ4)
|
||||
include(ExternalProject)
|
||||
endif (EMBED_READLINE OR EMBED_BZIP2)
|
||||
endif (EMBED_READLINE OR EMBED_BZIP2 OR EMBED_LZ4)
|
||||
|
||||
if (NOT SKIPREADLINE EQUAL 1)
|
||||
if (APPLE)
|
||||
|
@ -163,6 +164,7 @@ if (NOT SKIPJANSSONSYSTEM EQUAL 1)
|
|||
endif (NOT SKIPJANSSONSYSTEM EQUAL 1)
|
||||
|
||||
if(EMBED_BZIP2)
|
||||
cmake_policy(SET CMP0114 NEW)
|
||||
set(BZIP2_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/bzip2/src/bzip2)
|
||||
ExternalProject_Add(bzip2
|
||||
GIT_REPOSITORY https://android.googlesource.com/platform/external/bzip2
|
||||
|
@ -183,6 +185,34 @@ else(EMBED_BZIP2)
|
|||
find_package (BZip2 REQUIRED)
|
||||
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)
|
||||
find_path(WHEREAMI_INCLUDE_DIRS whereami.h)
|
||||
find_library(WHEREAMI_LIBRARIES whereami)
|
||||
|
@ -349,6 +379,7 @@ set (TARGET_SOURCES
|
|||
${PM3_ROOT}/client/src/fileutils.c
|
||||
${PM3_ROOT}/client/src/flash.c
|
||||
${PM3_ROOT}/client/src/graph.c
|
||||
${PM3_ROOT}/client/src/iso4217.c
|
||||
${PM3_ROOT}/client/src/jansson_path.c
|
||||
${PM3_ROOT}/client/src/preferences.c
|
||||
${PM3_ROOT}/client/src/pm3.c
|
||||
|
@ -366,7 +397,7 @@ set (TARGET_SOURCES
|
|||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c
|
||||
COMMAND sh ${PM3_ROOT}/tools/mkversion.sh > ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c
|
||||
COMMAND 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
|
||||
)
|
||||
|
||||
|
@ -456,6 +487,11 @@ if (BZIP2_FOUND)
|
|||
set(ADDITIONAL_LNK ${BZIP2_LIBRARIES} ${ADDITIONAL_LNK})
|
||||
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)
|
||||
set(ADDITIONAL_DIRS ${WHEREAMI_INCLUDE_DIRS} ${ADDITIONAL_DIRS})
|
||||
set(ADDITIONAL_LNK ${WHEREAMI_LIBRARIES} ${ADDITIONAL_LNK})
|
||||
|
@ -488,11 +524,25 @@ else (SKIPBT EQUAL 1)
|
|||
endif (BLUEZ_FOUND)
|
||||
endif(SKIPBT EQUAL 1)
|
||||
|
||||
if (EMBED_BZIP2)
|
||||
message(STATUS "Bzip2 library: embedded")
|
||||
else (EMBED_BZIP2)
|
||||
message(STATUS "Bzip2 library: system library found")
|
||||
endif (EMBED_BZIP2)
|
||||
if (BZIP2_FOUND)
|
||||
if (EMBED_BZIP2)
|
||||
message(STATUS "Bzip2 library: embedded")
|
||||
else (EMBED_BZIP2)
|
||||
message(STATUS "Bzip2 library: system library found")
|
||||
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)
|
||||
message(STATUS "Jansson library: local library forced")
|
||||
|
@ -592,6 +642,9 @@ endif (EMBED_READLINE)
|
|||
if (EMBED_BZIP2)
|
||||
add_dependencies(pm3rrg_rdv4 bzip2)
|
||||
endif (EMBED_BZIP2)
|
||||
if (EMBED_LZ4)
|
||||
add_dependencies(pm3rrg_rdv4 lz4)
|
||||
endif (EMBED_LZ4)
|
||||
|
||||
if (MINGW)
|
||||
# Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z)
|
||||
|
@ -603,19 +656,19 @@ if (MINGW)
|
|||
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}")
|
||||
|
||||
# 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)
|
||||
# beware these flags didn't exist for GCC < 7
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
|
||||
if (GCC_VERSION VERSION_GREATER 10.0 OR GCC_VERSION VERSION_EQUAL 10.0)
|
||||
set(CMAKE_C_FLAGS "-Wno-stringop-overflow -Wno-error=stringop-overflow ${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "-Wno-stringop-overflow -Wno-error=stringop-overflow ${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
|
||||
endif (MINGW)
|
||||
|
||||
# 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)
|
||||
# beware these flags didn't exist for GCC < 7
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
|
||||
if (GCC_VERSION VERSION_GREATER 10.0 OR GCC_VERSION VERSION_EQUAL 10.0)
|
||||
set(CMAKE_C_FLAGS "-Wno-stringop-overflow -Wno-error=stringop-overflow ${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "-Wno-stringop-overflow -Wno-error=stringop-overflow ${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
|
||||
target_include_directories(pm3rrg_rdv4 PRIVATE
|
||||
${PM3_ROOT}/common
|
||||
${PM3_ROOT}/common_fpga
|
||||
|
|
|
@ -262,14 +262,19 @@ local Utils =
|
|||
|
||||
--
|
||||
-- Converts DECIMAL to HEX
|
||||
ConvertDecToHex = function(IN)
|
||||
local B,K,OUT,I,D = 16, "0123456789ABCDEF", "", 0
|
||||
while IN > 0 do
|
||||
I = I+1
|
||||
IN, D = math.floor(IN/B), math.modf(IN, B) + 1
|
||||
OUT = string.sub(K, D, D)..OUT
|
||||
ConvertDecToHex = function(decimal)
|
||||
if decimal == 0 then
|
||||
return "0"
|
||||
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,
|
||||
---
|
||||
-- Convert Byte array to string of hex
|
||||
|
|
|
@ -96,78 +96,6 @@ 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)
|
||||
--]]
|
||||
|
||||
example = "script run hf_legic"
|
||||
author = "Mosci, uhei"
|
||||
version = "1.0.4"
|
||||
|
||||
desc =
|
||||
[[
|
||||
|
||||
This script helps you to read, create and modify Legic Prime Tags (MIM22, MIM256, MIM1024)
|
||||
The virtual tag (and therefore the file to be saved) is always a MIM1024 tag.
|
||||
it's kinda interactive with following commands in three categories:
|
||||
|
||||
Data I/O Segment Manipulation Token-Data
|
||||
----------------- -------------------- -----------------
|
||||
rt => read Tag as => add Segment mt => make Token
|
||||
wt => write Tag es => edit Segment Header et => edit Token data
|
||||
ed => edit Segment Data tk => toggle KGH-Flag
|
||||
File I/O rs => remove Segment
|
||||
----------------- cc => check Segment-CRC
|
||||
lf => load bin File ck => check KGH
|
||||
sf => save eml/bin File ds => dump Segments
|
||||
xf => xor to File
|
||||
|
||||
|
||||
(partially) known Segments Virtual Tags Script Output
|
||||
--------------------------- ------------------------------- ------------------------
|
||||
dlc => dump Legic-Cash ct => copy mainTag to backupTag tac => toggle ansicolors
|
||||
elc => edit Legic-Cash tc => copy backupTag to mainTag
|
||||
d3p => dump 3rd-Party-Cash tt => switch mainTag & backupTag
|
||||
e3p => edit 3rd-Party-Cash di => dump mainTag
|
||||
do => dump backupTag
|
||||
|
||||
|
||||
|
||||
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
|
||||
without the need of changing anything - MCD,MSN,MCC will be read from the tag
|
||||
before and applied to the output.
|
||||
|
||||
lf: 'load file' - load a (xored) binary file (*.bin) from the local Filesystem into the 'virtual inTag'
|
||||
sf: 'save file' - saves the 'virtual inTag' to the local Filesystem as eml and bin (xored with Tag-MCC)
|
||||
xf: 'xor file' - saves the 'virtual inTag' to the local Filesystem (xored with chosen MCC - use '00' for plain values)
|
||||
|
||||
ct: 'copy tag' - copy the 'virtual Tag' to a second 'virtual TAG' - not useful yet, but inernally needed
|
||||
tc: 'copy tag' - copy the 'second virtual Tag' to 'virtual TAG' - not useful yet, but inernally needed
|
||||
tt: 'toggle tag' - copy mainTag to BackupTag and backupTag to mainTag
|
||||
|
||||
di: 'dump mainTag' - shows the current content of the 'virtual Tag'
|
||||
do: 'dump backupTag' - shows the current content of the 'virtual outTag'
|
||||
ds: 'dump Segments' - will show the content of a selected Segment
|
||||
as: 'add Segment' - will add a 'empty' Segment to the inTag
|
||||
es: 'edit Segment' - edit the Segment-Header of a selected Segment (len, WRP, WRC, RD, valid)
|
||||
all other Segment-Header-Values are either calculated or not needed to edit (yet)
|
||||
ed: 'edit data' - edit the Data of a Segment (ADF-Aera / Stamp & Payload specific Data)
|
||||
et: 'edit Token' - edit Data of a Token (CDF-Area / SAM, SAM64, SAM63, IAM, GAM specific Data)
|
||||
mt: 'make Token' - create a Token 'from scratch' (guided)
|
||||
rs: 'remove segment' - removes a Segment (except Segment 00, but this can be set to valid=0 for Master-Token)
|
||||
cc: 'check Segment-CRC'- checks & calculates (if check failed) the Segment-CRC of all Segments
|
||||
ck: 'check KGH-CRC' - checks the and calculates a 'Kaba Group Header' if one was detected
|
||||
'Kaba Group Header CRC calculation'
|
||||
tk: 'toggle KGH' - toggle the (script-internal) flag for kgh-calculation for a segment
|
||||
xc: 'etra c' - show string that was used to calculate the kgh-crc of a segment
|
||||
|
||||
dlc: 'dump Legic-Cash' - show balance and checksums of a Legic-Cash Segment
|
||||
elc: 'edit Legic-Cash' - edit values of a Legic-Cash Segment
|
||||
|
||||
d3p: 'dump 3rd Party' - show balance, history and checksums of a (yet) unknown 3rd-Party Cash Segment
|
||||
e3p: 'edit 3rd Party' - edit Data in 3rd-Party Cash Segment
|
||||
|
||||
tac: 'toggle ansicolors'- switch on and off the colored text-output of this script
|
||||
default can be changed by setting the variable 'colored_output' to false
|
||||
]]
|
||||
currentTag="inTAG"
|
||||
|
||||
---
|
||||
-- requirements
|
||||
|
@ -193,6 +121,10 @@ 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)
|
||||
|
@ -206,6 +138,10 @@ function load_colors(onoff)
|
|||
acblue = ansicolors.blue
|
||||
acmagenta= ansicolors.magenta
|
||||
acoff = ansicolors.reset
|
||||
|
||||
acy = ansicolors.yellow
|
||||
acc = ansicolors.cyan
|
||||
acr = ansicolors.reset
|
||||
else
|
||||
-- 'no color'
|
||||
acgreen = ""
|
||||
|
@ -215,9 +151,84 @@ function load_colors(onoff)
|
|||
acblue = ""
|
||||
acmagenta= ""
|
||||
acoff = ""
|
||||
|
||||
acy = ""
|
||||
acc = ""
|
||||
acr = ""
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
example = "script run hf_legic"
|
||||
author = "Mosci, uhei"
|
||||
version = "1.0.5"
|
||||
desc =
|
||||
[[
|
||||
|
||||
This script helps you to read, create and modify Legic Prime Tags ( MIM22, MIM256, MIM1024 )
|
||||
The virtual tag (and therefore the file to be saved) is always a MIM1024 tag.
|
||||
it's kinda interactive with following commands in three categories:
|
||||
|
||||
Data I/O Segment Manipulation Token-Data
|
||||
----------------- -------------------- -----------------
|
||||
]]..acy..[[rt]]..acr..[[ -> read Tag ]]..acy..[[as]]..acr..[[ -> add Segment ]]..acy..[[mt]]..acr..[[ -> make Token
|
||||
]]..acy..[[wt]]..acr..[[ -> write Tag ]]..acy..[[es]]..acr..[[ -> edit Segment Header ]]..acy..[[et]]..acr..[[ -> edit Token data
|
||||
]]..acy..[[ed]]..acr..[[ => edit Segment Data ]]..acy..[[tk]]..acr..[[ => toggle KGH-Flag
|
||||
File I/O ]]..acy..[[rs]]..acr..[[ => remove Segment
|
||||
----------------- ]]..acy..[[cc]]..acr..[[ -> check Segment-CRC
|
||||
]]..acy..[[lf]]..acr..[[ -> load bin File ]]..acy..[[ck]]..acr..[[ -> check KGH
|
||||
]]..acy..[[sf]]..acr..[[ -> save eml/bin File ]]..acy..[[ds]]..acr..[[ -> dump Segments
|
||||
]]..acy..[[xf]]..acr..[[ -> xor to File
|
||||
|
||||
|
||||
(partially) known Segments Virtual Tags Script Output
|
||||
--------------------------- ------------------------------- ------------------------
|
||||
]]..acy..[[dlc]]..acr..[[ -> dump Legic-Cash ]]..acy..[[ct]]..acr..[[ -> copy mainTag to backupTag ]]..acy..[[tac]]..acr..[[ -> toggle ansicolors
|
||||
]]..acy..[[elc]]..acr..[[ -> edit Legic-Cash ]]..acy..[[tc]]..acr..[[ -> copy backupTag to mainTag
|
||||
]]..acy..[[d3p]]..acr..[[ -> dump 3rd-Party-Cash ]]..acy..[[tt]]..acr..[[ -> switch mainTag & backupTag
|
||||
]]..acy..[[e3p]]..acr..[[ -> edit 3rd-Party-Cash ]]..acy..[[di]]..acr..[[ -> dump mainTag
|
||||
]]..acy..[[do]]..acr..[[ => dump backupTag
|
||||
|
||||
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
|
||||
without the need of changing anything - MCD,MSN,MCC will be read from the tag
|
||||
before and applied to the output.
|
||||
|
||||
lf: 'load file' - load a (xored) binary file (*.bin) from the local Filesystem into the 'virtual inTag'
|
||||
sf: 'save file' - saves the 'virtual inTag' to the local Filesystem as eml and bin (xored with Tag-MCC)
|
||||
xf: 'xor file' - saves the 'virtual inTag' to the local Filesystem (xored with chosen MCC - use '00' for plain values)
|
||||
|
||||
ct: 'copy tag' - copy the 'virtual Tag' to a second 'virtual TAG' - not useful yet, but inernally needed
|
||||
tc: 'copy tag' - copy the 'second virtual Tag' to 'virtual TAG' - not useful yet, but inernally needed
|
||||
tt: 'toggle tag' - copy mainTag to BackupTag and backupTag to mainTag
|
||||
|
||||
di: 'dump mainTag' - shows the current content of the 'virtual Tag'
|
||||
do: 'dump backupTag' - shows the current content of the 'virtual outTag'
|
||||
ds: 'dump Segments' - will show the content of a selected Segment
|
||||
as: 'add Segment' - will add a 'empty' Segment to the inTag
|
||||
es: 'edit Segment' - edit the Segment-Header of a selected Segment (len, WRP, WRC, RD, valid)
|
||||
all other Segment-Header-Values are either calculated or not needed to edit (yet)
|
||||
ed: 'edit data' - edit the Data of a Segment (ADF-Aera / Stamp & Payload specific Data)
|
||||
et: 'edit Token' - edit Data of a Token (CDF-Area / SAM, SAM64, SAM63, IAM, GAM specific Data)
|
||||
mt: 'make Token' - create a Token 'from scratch' (guided)
|
||||
rs: 'remove segment' - removes a Segment (except Segment 00, but this can be set to valid=0 for Master-Token)
|
||||
cc: 'check Segment-CRC' - checks & calculates (if check failed) the Segment-CRC of all Segments
|
||||
ck: 'check KGH-CRC' - checks the and calculates a 'Kaba Group Header' if one was detected
|
||||
'Kaba Group Header CRC calculation'
|
||||
tk: 'toggle KGH' - toggle the (script-internal) flag for kgh-calculation for a segment
|
||||
xc: 'etra c' - show string that was used to calculate the kgh-crc of a segment
|
||||
|
||||
dlc: 'dump Legic-Cash' - show balance and checksums of a Legic-Cash Segment
|
||||
elc: 'edit Legic-Cash' - edit values of a Legic-Cash Segment
|
||||
|
||||
d3p: 'dump 3rd Party' - show balance, history and checksums of a (yet) unknown 3rd-Party Cash Segment
|
||||
e3p: 'edit 3rd Party' - edit Data in 3rd-Party Cash Segment
|
||||
|
||||
tac: 'toggle ansicolors' - switch on and off the colored text-output of this script
|
||||
default can be changed by setting the variable 'colored_output' to false
|
||||
]]
|
||||
currentTag="inTAG"
|
||||
|
||||
---
|
||||
-- curency-codes for Legic-Cash-Segments (ISO 4217)
|
||||
local currency = {
|
||||
|
@ -237,7 +248,11 @@ end
|
|||
---
|
||||
-- Usage 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("Example usage: "..example)
|
||||
end
|
||||
|
@ -254,7 +269,6 @@ local function padString(str)
|
|||
if (#str == 1) then
|
||||
return '0'..str
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
|
||||
|
@ -305,18 +319,6 @@ function xorBytes(inBytes, crc)
|
|||
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
|
||||
local function split(str, sep)
|
||||
|
@ -330,6 +332,24 @@ local function split(str, sep)
|
|||
return fields
|
||||
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
|
||||
function str2bytes(s)
|
||||
|
@ -348,7 +368,7 @@ end
|
|||
function bytesToTable(bytes, bstart, bend)
|
||||
local t={}
|
||||
for i=0, (bend-bstart) do
|
||||
t[i]=bytes[bstart+i]
|
||||
t[i]=padString(bytes[bstart+i])
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
@ -358,8 +378,13 @@ end
|
|||
function getInputBytes(infile)
|
||||
local line
|
||||
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");
|
||||
for i = 1, #file_data do
|
||||
|
@ -367,7 +392,7 @@ function getInputBytes(infile)
|
|||
end
|
||||
fhi:close()
|
||||
if (bytes[7]=='00') then return false end
|
||||
print(#bytes .. " bytes from "..infile.." loaded")
|
||||
print(#bytes .. " bytes from "..path.." loaded")
|
||||
return bytes
|
||||
end
|
||||
|
||||
|
@ -613,12 +638,13 @@ local function readFile(filename)
|
|||
print(accyan)
|
||||
local bytes = {}
|
||||
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")
|
||||
end
|
||||
|
||||
bytes = getInputBytes(filename)
|
||||
|
||||
bytes = getInputBytes(path)
|
||||
if bytes == false then return oops('couldnt get input bytes') end
|
||||
|
||||
-- make plain bytes
|
||||
|
@ -640,12 +666,14 @@ local function save_BIN(data, filename)
|
|||
local fn = filename..ext
|
||||
|
||||
-- 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)
|
||||
counter = counter + 1
|
||||
res, path = file_check(fn)
|
||||
end
|
||||
|
||||
outfile = io.open(fn, 'wb')
|
||||
outfile = io.open(path, 'wb')
|
||||
|
||||
local i = 1
|
||||
while data[i] do
|
||||
|
@ -660,17 +688,19 @@ end
|
|||
-- write bytes to file
|
||||
function writeFile(bytes, filename)
|
||||
local emlext = ".eml"
|
||||
local res, path
|
||||
if (filename ~= 'MyLegicClone') then
|
||||
if (file_check(filename..emlext)) then
|
||||
local answer = confirm("\nthe output-file "..filename..emlext.." already exists!\nthis will delete the previous content!\ncontinue?")
|
||||
res, path = file_check(filename..emlext)
|
||||
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
|
||||
end
|
||||
end
|
||||
local line
|
||||
local bcnt = 0
|
||||
local fho, err = io.open(filename..emlext, "w")
|
||||
local fho, err = io.open(path, "w")
|
||||
if err then
|
||||
return oops("OOps ... failed to open output-file ".. filename..emlext)
|
||||
return oops("OOps ... failed to open output-file ".. path)
|
||||
end
|
||||
|
||||
bytes = xorBytes(bytes, bytes[5])
|
||||
|
@ -692,11 +722,10 @@ function writeFile(bytes, filename)
|
|||
end
|
||||
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)
|
||||
|
||||
-- save binary
|
||||
local fn_bin, fn_bin_num = save_BIN(bytes, filename)
|
||||
if fn_bin and fn_bin_num then
|
||||
print("\nwrote "..acyellow..fn_bin_num..acoff.." bytes to BINARY file "..acyellow..fn_bin..acoff)
|
||||
end
|
||||
|
@ -731,10 +760,16 @@ function readFromPM3()
|
|||
infile=getRandomTempName()
|
||||
core.console("hf legic dump -f "..infile)
|
||||
tag=readFile(infile..".bin")
|
||||
os.remove(infile)
|
||||
os.remove(infile..".bin")
|
||||
os.remove(infile..".eml")
|
||||
os.remove(infile..".json")
|
||||
|
||||
res, path = file_check(infile..".bin")
|
||||
if not res then return nil end
|
||||
os.remove(path)
|
||||
|
||||
res, path = file_check(infile..".eml")
|
||||
os.remove(path)
|
||||
|
||||
res, path = file_check(infile..".json")
|
||||
os.remove(path)
|
||||
return tag
|
||||
end
|
||||
|
||||
|
@ -758,16 +793,20 @@ end
|
|||
---
|
||||
-- save mapping to file
|
||||
local function saveTagMap(map, filename)
|
||||
|
||||
local res, path
|
||||
|
||||
if #filename > 0 then
|
||||
if file_check(filename) then
|
||||
local answer = confirm("\nthe output-file "..acyellow..filename..acoff.." alredy exists!\nthis will delete the previous content!\ncontinue?")
|
||||
res, path = file_check(filename)
|
||||
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
|
||||
end
|
||||
end
|
||||
|
||||
local line
|
||||
local fho,err = io.open(filename, "w")
|
||||
if err then oops("OOps ... failed to open output-file "..acyellow..filename..acoff) end
|
||||
local fho,err = io.open(path, "w")
|
||||
if err then oops("OOps ... failed to open output-file "..acyellow..path..acoff) end
|
||||
|
||||
-- write line to new file
|
||||
for k, v in pairs(map) do
|
||||
|
@ -842,10 +881,13 @@ function loadTagMap(filename)
|
|||
local line, fields
|
||||
local temp={}
|
||||
local offset=0
|
||||
if not file_check(filename) then
|
||||
return oops("input file: "..acyellow..filename..acoff.." not found")
|
||||
else
|
||||
local fhi,err = io.open(filename)
|
||||
|
||||
local res, path = file_check(filename)
|
||||
if not res then
|
||||
return oops("input file: "..acyellow..filename..acoff.." not found")
|
||||
else
|
||||
|
||||
local fhi,err = io.open(path)
|
||||
while true do
|
||||
line = fhi:read()
|
||||
if line == nil then
|
||||
|
@ -907,20 +949,21 @@ function dumpTagMap(tag, tagMap)
|
|||
end
|
||||
if (isPosCrc8(tagMap, v['start'])>0) 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
|
||||
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
|
||||
else
|
||||
io.write("("..("%04d"):format(v['start']).."-"..("%04d"):format(v['end'])..") "..((v['highlight']) and acmagenta or acyellow)..v['name']..acoff..":")
|
||||
end
|
||||
temp=""
|
||||
for i=((string.len(v['name']))/10), 2 do
|
||||
temp=temp.."\t"
|
||||
io.write("("..("%04d"):format(v['start']).."-"..("%04d"):format(v['end'])..") "..((v['highlight']) and acmagenta or acyellow)..v['name']..acoff)
|
||||
end
|
||||
|
||||
temp = ""
|
||||
while (#v['name'] + temp:len()) < 20 do temp = temp.." " end
|
||||
|
||||
for i=v['start'], v['end'] do
|
||||
temp=temp..bytes[i].." "
|
||||
end
|
||||
|
||||
print(temp)
|
||||
lastend=v['end']
|
||||
end
|
||||
|
@ -966,11 +1009,23 @@ end
|
|||
-- edit existing Map
|
||||
function editTagMap(tag, tagMap)
|
||||
local t = [[
|
||||
Data: dm = show dr = dump raw
|
||||
Mappings: im = insert am = add rm = remove
|
||||
CRC8: ac8 = add sc8 = show rc8 = remove
|
||||
: q = exit h = Help
|
||||
]]..acc..[[Data]]..acr..[[
|
||||
|
||||
]]..acy..[[dm]]..acr..[[ - show ]]..acy..[[dr]]..acr..[[ - dump raw
|
||||
|
||||
]]..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
|
||||
print("tagMap edit-mode submenu")
|
||||
repeat
|
||||
|
@ -2293,25 +2348,25 @@ function modifyHelp()
|
|||
|
||||
Data I/O Segment Manipulation Token-Data
|
||||
----------------- -------------------- ---------------------
|
||||
rt => read Tag as => add Segment mt => make Token
|
||||
wt => write Tag es => edit Segment Header et => edit Token data
|
||||
ed => edit Segment Data tk => toggle KGH-Flag
|
||||
File I/O rs => remove Segment
|
||||
----------------- cc => check Segment-CRC
|
||||
lf => load bin File ck => check KGH
|
||||
sf => save eml/bin File ds => dump Segments
|
||||
xf => xor to File
|
||||
]]..acy..[[rt]]..acr..[[ => read Tag ]]..acy..[[as]]..acr..[[ => add Segment ]]..acy..[[mt]]..acr..[[ => make Token
|
||||
]]..acy..[[wt]]..acr..[[ => write Tag ]]..acy..[[es]]..acr..[[ => edit Segment Header ]]..acy..[[et]]..acr..[[ => edit Token data
|
||||
]]..acy..[[ed]]..acr..[[ => edit Segment Data ]]..acy..[[tk]]..acr..[[ => toggle KGH-Flag
|
||||
File I/O ]]..acy..[[rs]]..acr..[[ => remove Segment
|
||||
----------------- ]]..acy..[[cc]]..acr..[[ => check Segment-CRC
|
||||
]]..acy..[[lf]]..acr..[[ => load bin File ]]..acy..[[ck]]..acr..[[ => check KGH
|
||||
]]..acy..[[sf]]..acr..[[ => save eml/bin File ]]..acy..[[ds]]..acr..[[ => dump Segments
|
||||
]]..acy..[[xf]]..acr..[[ => xor to File
|
||||
|
||||
|
||||
Virtual Tags tagMap (partial) known Segments
|
||||
-------------------------------- --------------------- ---------------------------
|
||||
ct => copy mainTag to backupTag mm => make (new) Map dlc => dump Legic-Cash
|
||||
tc => copy backupTag to mainTag em => edit Map submenu elc => edit Legic-Cash
|
||||
tt => switch mainTag & backupTag lm => load map from file d3p => dump 3rd-Party-Cash
|
||||
di => dump mainTag sm => save map to file e3p => edit 3rd-Party-Cash
|
||||
do => dump backupTag
|
||||
]]..acy..[[ct]]..acr..[[ => copy mainTag to backupTag ]]..acy..[[mm]]..acr..[[ => make (new) Map ]]..acy..[[dlc]]..acr..[[ => dump Legic-Cash
|
||||
]]..acy..[[tc]]..acr..[[ => copy backupTag to mainTag ]]..acy..[[em]]..acr..[[ => edit Map submenu ]]..acy..[[elc]]..acr..[[ => edit Legic-Cash
|
||||
]]..acy..[[tt]]..acr..[[ => switch mainTag & backupTag ]]..acy..[[lm]]..acr..[[ => load map from file ]]..acy..[[d3p]]..acr..[[ => dump 3rd-Party-Cash
|
||||
]]..acy..[[di]]..acr..[[ => dump mainTag ]]..acy..[[sm]]..acr..[[ => save map to file ]]..acy..[[e3p]]..acr..[[ => edit 3rd-Party-Cash
|
||||
]]..acy..[[do]]..acr..[[ => dump backupTag
|
||||
|
||||
h => this help q => quit
|
||||
]]..acy..[[h]]..acr..[[ => this help ]]..acy..[[q]]..acr..[[ => quit
|
||||
]]
|
||||
return t
|
||||
end
|
||||
|
@ -2325,8 +2380,10 @@ function modifyMode()
|
|||
---
|
||||
-- helptext
|
||||
["h"] = function(x)
|
||||
print(" Version: "..version);
|
||||
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(" Version: "..acgreen..version..acr);
|
||||
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,
|
||||
---
|
||||
-- read real Tag with PM3 into virtual 'mainTAG'
|
||||
|
@ -2367,16 +2424,16 @@ function modifyMode()
|
|||
---
|
||||
-- load file into mainTAG
|
||||
["lf"] = function(x)
|
||||
|
||||
if (type(x)=='string' and file_check(x)) then
|
||||
if (x and not x=="" and type(x)=='string' and file_check(x)) then
|
||||
filename = x
|
||||
else
|
||||
filename = input("enter filename: ", "legic.temp")
|
||||
end
|
||||
inTAG=readFile(filename)
|
||||
-- check for existing tagMap
|
||||
if (file_check(filename..".map")) then
|
||||
if(confirm(accyan.."Mapping-File for "..acoff..filename..accyan.." found - load it also?"..acoff)) then
|
||||
local res, path = file_check(filename..".map")
|
||||
if res then
|
||||
if(confirm(accyan.."Mapping-File for "..acoff..path..accyan.." found - load it also?"..acoff)) then
|
||||
tagMap=loadTagMap(filename..".map")
|
||||
end
|
||||
end
|
||||
|
@ -2724,7 +2781,7 @@ function modifyMode()
|
|||
}
|
||||
repeat
|
||||
-- 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)
|
||||
if (type(actions[string.lower(string.sub(ic,0,3))])=='function') then
|
||||
actions[string.lower(string.sub(ic,0,3))](string.sub(ic,5))
|
||||
|
@ -2743,10 +2800,13 @@ end
|
|||
function main(args)
|
||||
-- set init colors/switch (can be toggled with 'tac' => 'toggle ansicolors')
|
||||
load_colors(colored_output)
|
||||
if (#args == 0 ) then modifyMode() end
|
||||
if (#args == 0 ) then modifyMode() end
|
||||
--- variables
|
||||
local inTAG, backupTAG, outTAG, outfile, interactive, crc, ofs, cfs, dfs
|
||||
-- just a spacer for better readability
|
||||
local inTAG, backupTAG, outTAG, outfile, interactive, crc
|
||||
local ofs=false
|
||||
local cfs=false
|
||||
local dfs=false
|
||||
-- just a spacer for better readability
|
||||
print()
|
||||
--- parse arguments
|
||||
for o, a in getopt.getopt(args, 'hrmi:do:c:') do
|
||||
|
@ -2755,7 +2815,7 @@ function main(args)
|
|||
-- read tag from PM3
|
||||
if o == "r" then inTAG=readFromPM3() end
|
||||
-- input file
|
||||
if o == "i" then inTAG=readFile(a) end
|
||||
if o == "i" then inTAG=readFile(a) end
|
||||
-- dump virtual-Tag
|
||||
if o == "d" then dfs=true end
|
||||
-- interacive modifying
|
||||
|
@ -2793,7 +2853,10 @@ function main(args)
|
|||
|
||||
-- write to outfile
|
||||
if (bytes) then
|
||||
writeFile(bytes, outfile)
|
||||
|
||||
if (outfile) then
|
||||
writeFile(bytes, outfile)
|
||||
end
|
||||
--- read real tag into virtual tag
|
||||
-- inTAG=readFromPM3() end
|
||||
--- or simply use the bytes that where wriiten
|
||||
|
|
|
@ -168,7 +168,7 @@ local function help()
|
|||
print(example)
|
||||
end
|
||||
-- read LEGIC data
|
||||
local function readlegicdata(offset, length, iv)
|
||||
local function readlegicdata(offset, len, iv)
|
||||
-- Read data
|
||||
local d0 = ('%04X%04X%02X'):format(offset, len, iv)
|
||||
local c = Command:newNG{cmd = cmds.CMD_HF_LEGIC_READER, data = d0}
|
||||
|
|
|
@ -124,7 +124,7 @@ local function main(args)
|
|||
local c = string.format( command, n )
|
||||
print('Running: "'..c..'"')
|
||||
core.console(c)
|
||||
core.console('msleep '..timeout);
|
||||
core.console('msleep -t'..timeout);
|
||||
core.console('hw ping')
|
||||
end
|
||||
|
||||
|
|
|
@ -737,7 +737,7 @@ local function set_type(tagtype)
|
|||
write_uid('04112233445566')
|
||||
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
|
||||
elseif tagtype == 12 then
|
||||
elseif tagtype == 13 then
|
||||
print('Setting: Ultimate Magic card to UL-EV1 128')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000000")
|
||||
|
|
|
@ -12,7 +12,7 @@ This version
|
|||
- Iceman
|
||||
|
||||
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.
|
||||
|
||||
Ie: this script can't be used inside the normal build sequence.
|
||||
|
@ -65,8 +65,8 @@ def main():
|
|||
// readline auto complete utilities
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef PM3LINE_VOCABULORY_H__
|
||||
#define PM3LINE_VOCABULORY_H__
|
||||
#ifndef PM3LINE_VOCABULARY_H__
|
||||
#define PM3LINE_VOCABULARY_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -74,12 +74,12 @@ extern "C" {
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct vocabulory_s {
|
||||
typedef struct vocabulary_s {
|
||||
bool offline;
|
||||
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():
|
||||
offline = 0
|
||||
|
@ -88,7 +88,7 @@ const static vocabulory_t vocabulory[] = {\n""")
|
|||
|
||||
cmd = values['command']
|
||||
|
||||
args.output_file.write(' {{ {}, "{}" }}, \n'.format(offline, cmd))
|
||||
args.output_file.write(' {{ {}, "{}" }},\n'.format(offline, cmd))
|
||||
|
||||
args.output_file.write(""" {0, NULL}\n};
|
||||
|
||||
|
|
|
@ -2406,5 +2406,21 @@
|
|||
"Name": "AirDrop connection negotiation",
|
||||
"Description": "Used by NFC-based AirDrop negotiation added in IOS17",
|
||||
"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"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"value": "6a02c801000300000000000000",
|
||||
"name": "Transit: Ventra",
|
||||
|
@ -58,7 +57,7 @@
|
|||
},
|
||||
|
||||
{
|
||||
"value": "6a02c3020602ffff",
|
||||
"value": "6a02c3020002ffff",
|
||||
"name": "Access: Hotel: Hilton",
|
||||
"description": "TCI might be a wildcard before a reservation is made"
|
||||
},
|
||||
|
|
Binary file not shown.
BIN
client/resources/hardnested_tables/bitflip_0_001_states.bin.lz4
Normal file
BIN
client/resources/hardnested_tables/bitflip_0_001_states.bin.lz4
Normal file
Binary file not shown.
Binary file not shown.
BIN
client/resources/hardnested_tables/bitflip_0_003_states.bin.lz4
Normal file
BIN
client/resources/hardnested_tables/bitflip_0_003_states.bin.lz4
Normal file
Binary file not shown.
Binary file not shown.
BIN
client/resources/hardnested_tables/bitflip_0_005_states.bin.lz4
Normal file
BIN
client/resources/hardnested_tables/bitflip_0_005_states.bin.lz4
Normal file
Binary file not shown.
Binary file not shown.
BIN
client/resources/hardnested_tables/bitflip_0_007_states.bin.lz4
Normal file
BIN
client/resources/hardnested_tables/bitflip_0_007_states.bin.lz4
Normal file
Binary file not shown.
Binary file not shown.
BIN
client/resources/hardnested_tables/bitflip_0_009_states.bin.lz4
Normal file
BIN
client/resources/hardnested_tables/bitflip_0_009_states.bin.lz4
Normal file
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue