Merge branch 'master' into smartcard-relay

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

View file

@ -41,7 +41,7 @@ jobs:
run: sudo apt-get update
- 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: |

View file

@ -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: |

View file

@ -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

View file

@ -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
View file

@ -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

View file

@ -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)

View file

@ -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...

View file

@ -35,9 +35,9 @@ The Proxmark3 is the swiss-army tool of RFID, allowing for interactions with the
| :------------------: | :------------------: |
| [Linux - Setup and Build](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) | [Compilation Instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md)|
| [Linux - 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/)

View file

@ -233,7 +233,7 @@ uint32_t BigBuf_get_traceLen(void) {
by 'hf list -t raw', alternatively 'hf list -t <proto>' for protocol-specific
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) {

View file

@ -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;

View file

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

View file

@ -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

View file

@ -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 $@)

View file

@ -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)),)

View file

@ -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

View file

@ -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
View 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.

View file

@ -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

View file

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

View file

@ -293,7 +293,7 @@ static void ReadLastTagFromFlash(void) {
rdv40_spiffs_read_as_filetype((char *)HFCOLIN_LASTTAG_SYMLINK, (uint8_t *)mem, len, RDV40_SPIFFS_SAFETY_SAFE);
// 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);
}
}
}

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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();

View file

@ -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;
}

View file

@ -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)) {

View file

@ -27,9 +27,9 @@ extern bool g_reply_with_crc_on_fpc;
extern bool g_reply_via_fpc;
extern bool g_reply_via_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_

View file

@ -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) {

View file

@ -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

View file

@ -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;

View file

@ -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 */

View file

@ -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;

View file

@ -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 */

View file

@ -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---------

View file

@ -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 */

View file

@ -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};

View file

@ -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

View file

@ -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 {

View file

@ -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);

View file

@ -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();

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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_));

View file

@ -635,7 +635,7 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
/*
* Emulates a Hitag S Tag with the given data from the .hts file
*/
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");

View file

@ -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

View file

@ -407,7 +407,7 @@ bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address) {
//Sends array of data (Array, length, command to be written , SlaveDevice address ).
// 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;

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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));

View file

@ -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);

View file

@ -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);

View file

@ -41,7 +41,7 @@ int iso14443b_select_card(iso14b_card_select_t *card);
int iso14443b_select_card_srx(iso14b_card_select_t *card);
int iso14443b_select_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);

View file

@ -294,7 +294,12 @@ void CodeIso15693AsTag(const uint8_t *cmd, size_t len) {
// Transmit the command (to the tag) that was placed in cmd[].
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();

View file

@ -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

View file

@ -53,7 +53,7 @@ SECTIONS
.bss : {
__bss_start__ = .;
*(.bss)
*(.bss.*)
*(.bss.*)
. = ALIGN(4);
__bss_end__ = .;
} >ram AT>ram :bss

View file

@ -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();

View file

@ -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 */

View file

@ -91,18 +91,18 @@ static bool wait_for(bool value, const uint32_t timeout) {
// - A bit length >80.2us is a 1
// - A bit length <80.2us is a 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();
}

View file

@ -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) {

View file

@ -38,9 +38,9 @@ void CmdHIDsimTAGEx(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, boo
void CmdHIDsimTAG(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, bool ledcontrol);
void 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);

View file

@ -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)

View file

@ -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);

View file

@ -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;

View file

@ -73,10 +73,11 @@ int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_c
struct Crypto1State *pcs = &mpcs;
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) {

View file

@ -40,7 +40,6 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
void MifareChkKeys_file(uint8_t *fn);
void 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);

View file

@ -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();

View file

@ -116,7 +116,9 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t
uint16_t len = ReaderReceive(answer, par);
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);
}
}

View file

@ -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);

View file

@ -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:

View file

@ -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);

View file

@ -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;

View file

@ -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)

View file

@ -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

View file

@ -40,7 +40,7 @@ ifeq ($(USE_BREW),1)
PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(BREW_PREFIX)/lib/pkgconfig:$(BREW_PREFIX)/opt/qt/lib/pkgconfig:$(BREW_PREFIX)/opt/qt5/lib/pkgconfig
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 $* = $($*)

View file

@ -371,7 +371,7 @@ uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, statel
for (uint32_t tests = 0; tests < nonces_to_bruteforce; ++tests) {
// 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

View file

@ -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];
}

View file

@ -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

View file

@ -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.

View file

@ -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 */

View file

@ -37,5 +37,5 @@ F41DAF58B20C8B91
66584C91EE80D5E5
C1B74D7478053AE2
#
# default iCLASS RFIDeas
# default iCLASS RFIDeas
6B65797374726B72

View file

@ -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

View file

@ -15,7 +15,7 @@ ffffffffffffffffffffffffffffffffffffffffffffffff
6AC292FAA1315B4D858AB3A3D7D5933A
404142434445464748494a4b4c4d4e4f
3112B738D8862CCD34302EB299AAB456 # Gallagher AES (https://pastebin.com/GkbGLz8r)
47454D5850524553534F53414D504C45 # Gemalto
47454D5850524553534F53414D504C45 # Gemalto
2b7e151628aed2a6abf7158809cf4f3c
fbeed618357133667c85e08f7236a8de
f7ddac306ae266ccf90bc11ee46d513b

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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}

View file

@ -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

View file

@ -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")

View file

@ -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};

View file

@ -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"
}
]

View file

@ -25,7 +25,6 @@
"description": "iPhones before IOS17 emit this frame so that other Apple devices don't react to the field during background reading. Also emitted during NFCReaderSession subtypes"
},
{
"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"
},

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