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
|
||||
|
|
12
.vscode/setup.sh
vendored
12
.vscode/setup.sh
vendored
|
@ -39,7 +39,7 @@ function print_config {
|
|||
function setup_serial_port {
|
||||
if [ -z "$SerialPort" ]; then
|
||||
pm3list=$($VSCODEPATH/../pm3 --list 2>/dev/null)
|
||||
#Use first port listed
|
||||
#Use first port listed
|
||||
export SerialPort=$(echo $pm3list | head -n 1 | cut -c 4-)
|
||||
if [ -z "$SerialPort" ]; then
|
||||
echo >&2 "[!!] No serial port found, please set SerialPort manually"
|
||||
|
@ -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
|
||||
|
|
|
@ -53,7 +53,7 @@ SECTIONS
|
|||
.bss : {
|
||||
__bss_start__ = .;
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.bss.*)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} >ram AT>ram :bss
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -37,5 +37,5 @@ F41DAF58B20C8B91
|
|||
66584C91EE80D5E5
|
||||
C1B74D7478053AE2
|
||||
#
|
||||
# default iCLASS RFIDeas
|
||||
# default iCLASS RFIDeas
|
||||
6B65797374726B72
|
||||
|
|
|
@ -36,6 +36,9 @@ D01AFEEB890A
|
|||
2612C6DE84CA
|
||||
707B11FC1481
|
||||
#
|
||||
# QL88 diversifed
|
||||
03F9067646AE
|
||||
2352C5B56D85
|
||||
#
|
||||
B0B1B2B3B4B5
|
||||
C0C1C2C3C4C5
|
||||
|
@ -68,8 +71,8 @@ B27CCAB30DBD
|
|||
D2ECE8B9395E
|
||||
# NSCP default key
|
||||
1494E81663D7
|
||||
#
|
||||
# NFC tools
|
||||
#
|
||||
# NFC tools
|
||||
7c9fb8474242
|
||||
#
|
||||
# Kiev keys
|
||||
|
@ -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
|
||||
|
@ -296,7 +304,7 @@ AAFB06045877
|
|||
25094DF6F148
|
||||
#
|
||||
#
|
||||
# https://mattionline.de/fitnessstudio-armband-reverse-engineering/
|
||||
# https://mattionline.de/fitnessstudio-armband-reverse-engineering/
|
||||
# https://mattionline.de/milazycracker/
|
||||
# gym wistband A, same as Fysiken A
|
||||
# gym wistband B
|
||||
|
@ -307,7 +315,7 @@ AAFB06045877
|
|||
A05DBD98E0FC
|
||||
#
|
||||
# GoFit
|
||||
AA4DDA458EBB
|
||||
AA4DDA458EBB
|
||||
EAB8066C7479
|
||||
#
|
||||
# Nordic Wellness A, same as Fysiken A
|
||||
|
@ -597,6 +605,7 @@ BFB6796A11DB
|
|||
# Data from Salto A/B
|
||||
6A1987C40A21
|
||||
7F33625BC129
|
||||
6BE9314930D8
|
||||
#
|
||||
# Data from forum
|
||||
2338B4913111
|
||||
|
@ -868,7 +877,7 @@ AD4FB33388BF
|
|||
#
|
||||
# HID MIFARE Classic 1k Key
|
||||
484944204953
|
||||
204752454154
|
||||
204752454154
|
||||
# HID MIFARE SO
|
||||
3B7E4FD575AD
|
||||
11496F97752A
|
||||
|
@ -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
|
||||
|
|
|
@ -15,7 +15,7 @@ ffffffffffffffffffffffffffffffffffffffffffffffff
|
|||
6AC292FAA1315B4D858AB3A3D7D5933A
|
||||
404142434445464748494a4b4c4d4e4f
|
||||
3112B738D8862CCD34302EB299AAB456 # Gallagher AES (https://pastebin.com/GkbGLz8r)
|
||||
47454D5850524553534F53414D504C45 # Gemalto
|
||||
47454D5850524553534F53414D504C45 # Gemalto
|
||||
2b7e151628aed2a6abf7158809cf4f3c
|
||||
fbeed618357133667c85e08f7236a8de
|
||||
f7ddac306ae266ccf90bc11ee46d513b
|
||||
|
|
|
@ -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")
|
||||
|
@ -582,7 +632,7 @@ add_library(pm3rrg_rdv4 SHARED
|
|||
)
|
||||
|
||||
target_compile_definitions(pm3rrg_rdv4 PRIVATE LIBPM3)
|
||||
|
||||
|
||||
target_compile_options(pm3rrg_rdv4 PUBLIC -Wall -Werror -O3)
|
||||
if (EMBED_READLINE)
|
||||
if (NOT SKIPREADLINE EQUAL 1)
|
||||
|
@ -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.
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