This commit is contained in:
Antiklesys 2023-09-10 19:07:38 +08:00
commit f29c409275
1268 changed files with 69254 additions and 28552 deletions

View file

@ -18,26 +18,11 @@ assignees: doegox, iceman1001
- [ ] `tools/build_all_firmwares.sh` check that the script contains all standalone modes then compile all standalone modes (linux only) - [ ] `tools/build_all_firmwares.sh` check that the script contains all standalone modes then compile all standalone modes (linux only)
- [ ] `experimental_lib` compilation & tests - [ ] `experimental_lib` compilation & tests
- [ ] `experimental_client_with_swig` compilation & tests - [ ] `experimental_client_with_swig` compilation & tests
- [ ] Check Android `CMakeLists.txt` list of source file
- [ ] GitHub Actions - green across the board ( MacOS, Ubuntu, Windows) - [ ] GitHub Actions - green across the board ( MacOS, Ubuntu, Windows)
# OS compilation and tests # OS compilation and tests
```bash Run `tools/release_tests.sh` on:
#!/usr/bin/env bash
make clean && make -j PLATFORM=PM3GENERIC PLATFORM_EXTRAS= && tools/pm3_tests.sh --long || exit 1
make clean && make -j PLATFORM=PM3RDV4 PLATFORM_EXTRAS= || exit 1
make clean && make -j PLATFORM=PM3RDV4 PLATFORM_EXTRAS=BTADDON || exit 1
make -j PLATFORM=PM3RDV4 PLATFORM_EXTRAS=BTADDON && sudo make install PLATFORM=PM3RDV4 PLATFORM_EXTRAS=BTADDON && ( cd /tmp; proxmark3 -c 'data load -f lf_EM4x05.pm3;lf search -1'|grep 'Valid FDX-B ID found' ) && sudo make uninstall || exit 1
( cd client; rm -rf build; mkdir build;cd build;cmake .. && make -j PLATFORM=PM3GENERIC PLATFORM_EXTRAS= && cp -a ../*scripts ../*libs . && ../../tools/pm3_tests.sh --clientbin $(pwd)/proxmark3 client ) || exit 1
( cd client; rm -rf build; mkdir build;cd build;cmake .. && make -j PLATFORM=PM3RDV4 PLATFORM_EXTRAS= ) || exit 1
( cd client; rm -rf build; mkdir build;cd build;cmake .. && make -j PLATFORM=PM3RDV4 PLATFORM_EXTRAS=BTADDON ) || exit 1
# Hitag2crack, optionally with --long and --opencl ...
make hitag2crack/clean && make hitag2crack && tools/pm3_tests.sh hitag2crack || exit 1
```
- [ ] RPI Zero - [ ] RPI Zero
- [ ] Jetson Nano - [ ] Jetson Nano
@ -47,9 +32,9 @@ make hitag2crack/clean && make hitag2crack && tools/pm3_tests.sh hitag2crack ||
- [ ] Kali - [ ] Kali
- [ ] Debian Stable - [ ] Debian Stable
- [ ] Debian Testing - [ ] Debian Testing
- [ ] Ubuntu21 - [ ] Ubuntu 22
- [ ] ParrotOS - [ ] ParrotOS
- [ ] Fedora - [ ] Fedora 37
- [ ] OpenSuse Leap - [ ] OpenSuse Leap
- [ ] OpenSuse Tumbleweed - [ ] OpenSuse Tumbleweed
- [ ] OSX (MacPorts) - [ ] OSX (MacPorts)

View file

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

View file

@ -36,6 +36,7 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: brew install readline coreutils qt5 RfidResearchGroup/proxmark3/arm-none-eabi-gcc openssl run: brew install readline coreutils qt5 RfidResearchGroup/proxmark3/arm-none-eabi-gcc openssl
continue-on-error: true
- name: Install Python dependencies - name: Install Python dependencies
run: | run: |
@ -77,6 +78,7 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: brew install readline coreutils qt5 RfidResearchGroup/proxmark3/arm-none-eabi-gcc openssl run: brew install readline coreutils qt5 RfidResearchGroup/proxmark3/arm-none-eabi-gcc openssl
continue-on-error: true
- name: Install Python dependencies - name: Install Python dependencies
run: | run: |
@ -119,6 +121,7 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: brew install readline coreutils qt5 RfidResearchGroup/proxmark3/arm-none-eabi-gcc openssl run: brew install readline coreutils qt5 RfidResearchGroup/proxmark3/arm-none-eabi-gcc openssl
continue-on-error: true
- name: Install Python dependencies - name: Install Python dependencies
run: | run: |

View file

@ -9,7 +9,7 @@ jobs:
- name: Changelog Reminder - name: Changelog Reminder
uses: peterjgrainger/action-changelog-reminder@v1.2.0 uses: peterjgrainger/action-changelog-reminder@v1.2.0
with: with:
changelog_regex: '/CHANGELOG.md' changelog_regex: 'CHANGELOG.md'
customPrMessage: 'You are welcome to add an entry to the CHANGELOG.md as well' customPrMessage: 'You are welcome to add an entry to the CHANGELOG.md as well'
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

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

22
.github/workflows/uniq.yaml vendored Normal file
View file

@ -0,0 +1,22 @@
name: Check uniq keys
on:
push:
paths:
- 'client/dictionaries/**'
pull_request:
paths:
- 'client/dictionaries/**'
workflow_dispatch:
jobs:
check-unique:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: check unique keys in dic files
shell: bash
run: |
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

@ -98,9 +98,9 @@ jobs:
steps: steps:
- name: WSL setup - name: WSL setup
uses: Vampire/setup-wsl@v1 uses: Vampire/setup-wsl@v2
with: with:
distribution: Ubuntu-20.04 distribution: Ubuntu-22.04
update: "true" update: "true"
additional-packages: git additional-packages: git
ca-certificates ca-certificates
@ -110,6 +110,7 @@ jobs:
gcc-arm-none-eabi gcc-arm-none-eabi
libnewlib-dev libnewlib-dev
libbz2-dev libbz2-dev
liblz4-dev
qtbase5-dev qtbase5-dev
cmake cmake
libpython3-dev libpython3-dev

12
.gitignore vendored
View file

@ -80,17 +80,7 @@ tools/mfd_aes_brute/mfd_aes_brute
tools/mfd_aes_brute/mfd_multi_brute tools/mfd_aes_brute/mfd_multi_brute
tools/mfd_aes_brute/brute_key tools/mfd_aes_brute/brute_key
fpga/* fpga/__build*
!fpga/tests
!fpga/fpga_lf.bit
!fpga/fpga_hf.bit
!fpga/*.v
!fpga/Makefile
!fpga/fpga.ucf
!fpga/xst_lf.scr
!fpga/xst_hf.scr
!fpga/go.bat
!fpga/sim.tcl
# offcial dumps folder # offcial dumps folder
dumps/* dumps/*

View file

@ -3,9 +3,180 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased] ## [unreleased][unreleased]
- Moved to non-deprecated API to initialize Python interpreter (jmichel@)
- Changed `sc upgrade` updated firmware v4.12 (RDV40) (@sentiprox) ## [Raccoon.4.17140][2023-09-09]
- Fixed contact interface / smartcard APDU chaining logic and allow 256 bytes ADPU payload. Need SIM firmware 4.12 to work (@jmichel) - 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)
- 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)
- Changed the connection timeout configurable (@wh201906)
## [Seven.4.16717][2023-06-25]
- Change `hf 14a info` - now identifes QL88 tags (@iceman1001)
- Added support for compiling on iOS (@The-SamminAter)
- Fixed viewing MFC dump - border char is now white (@iceman1001)
- Changed `data diff` - to print filenames in header if it fits (@iceman1001)
- Changed viewing MFC dump files - it now colors ACL + GPB bytes (@iceman1001)
- Added `hf mf supercard --furui` - now supports key recovery from Furui detection card. Thanks foxushka! (@iceman1001)
- Added `hf topaz dump --ns` - now supports nosave param (@iceman1001)
- Changed `hf topaz rdbl` - unified output (@iceman1001)
- Fixed `hf topaz wrbl` - now supports tear off and write_nonerase command (@iceman1001)
- Fixed `hf mf` commands (@iceman1001)
- Fixed `hf mfp` commands (@iceman1001)
- 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)
- 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)
- Fixed truncated FPGA upload due to incorrect integer size variable (@d18c7db)
- Changed `usart btfactory` - handles the new BT board with version "BT SPP V3.0" (@iceman1001)
- Changed `hf mf eview --sk` - now can extract keys and save to file (@iceman1001)
- Changed `hf mf view --sk` - now can extract keys and save to file (@iceman1001)
- Changed `hf mf sim` - reduce 6ms threshold to 4ms for reset to idle #1974 (@net147)
- Rebuilt the Spartan-2 `fpga_*.bit` files to include the `hi_iso14443a.v` update (@d18c7db)
- Added minor orphaned change from `hi_iso14443a.v` in `fpga-xc3s100e` to `hi_iso14443a.v` in `fpga-xc2s30` (@d18c7db)
- Added python3 script to convert amiibo nfc Flipper Zero files to eml files to be used with Proxmark3 (@OscarAkaElvis)
- Changed `hf mf restore` - Auth both key A and key B with default password (@wh201906)
- Changed `nfc decode -f` - now can detect and convert MFC dumpfiles to NDEF byte arrays (@iceman1001)
- Changed `nfc decode` - now handles EXTERNAL RECORDS better (@iceman1001)
- Fixed `nfc decode` - now handles NDEF Signature version1 records better (@iceman1001)
- Added new standalone mode `LF_MULTIHID` - HID26 (H1031) multi simulator (@flamebarke)
- Changed `hf 14b dump --ns` - now supports `no save` of card memory (@iceman1001)
- Changed `hf mfu dump --ns` - now supports `no save` of card memory (@iceman1001)
- Changed the PM3 client to honor the preferences dump/trace paths. experimental support (@iceman1001)
- Added the possibility to load `.MCT` dump files (@iceman1001)
- Changed `lf t55xx dump --ns` - now supports `no save` of memory (@iceman1001)
- Fixed the USB enumeration process (@wh201906)
- Fixed `hf mf rdsc` - now correctly gets size in bytes when sector is larger than 32 (@iceman1001)
- Changed `hf mf supercard` - Support editing UID and recovery of keys from second generation card (@AloneLiberty)
- Added iClass credit key to default iClass key table and reorganized key order (@GuruSteve)
- Changed `hf mf value` - ability to use transfer on different block (@AloneLiberty)
- Changed `hf mf dump --ns` - dump command now supports `no save` of MFC card memory (@iceman1001)
- Added `hf mf gdmsetcfg` - Supprt Gen4 GDM write configuration block (@iceman1001)
- Added `hf mf gdmcfg` - Support Gen4 GDM read configuration block (@iceman1001)
- Changed magic note to include a section about GDM tags (@iceman1001)
- Added `hf mf gdmsetblk` - Support Gen4 GDM write block (@iceman1001)
- Changed `hf 14a info` - detect Gen GDM magic tags (@iceman1001)
- Changed CLI max string argument length limit from 512 to 4096 (@iceman1001)
- Fixed `data asn1` - now handles bad input better (@iceman1001)
- Added new public key for signature MIFARE Plus Troika (@iceman100)
- Fixed the client build on Android (@wh201906)
- Added TCP connection support on Windows (@wh201906)
- Added `data num` - easy convert between dec/hex/bin (@iceman1001)
- Fixed `hf mfdes info` - now handles incorrect tag answers better (@didiera)
- Fixed `hf mfdes` generic help text is now correct (@didiera)
- Fixed `pm3` script to correctly identify WSL enabled distros (@henrygab)
- Changed device enumeration with "unique USB serial numbers when built with `FLASH` -- **_UPDATES BOOTROM ALSO_**" (@henrygab)
- Changed the readline package to v8.2 in the CMAKE files for the client (@iceman1001)
- Fixed `pm3` script for passing arguments (@doegox)
- Fixed python paths to include current directory (@jmichelp)
- Fixed infinite loops in spindelayus (@lnv42)
- Changed ICECLASS standalone to support a read/sim mode (@natesales)
- Changed `hf iclass encode` - added verbose flag (@natesales)
- Changed `hf waveshare` - now identify 1.54 nfc epaper correct (@ah01)
- Fixed `Makefile` regression that broke `make install` (@henrygab)
- Fixed `lf em 4x70 brute` - now works as expected (@adite)
- Fixed the lf sampling when bits_per_sample is less than 8 (@wh201906)
- Added `lf em 4x70 brute` command (@adite)
- Added documentation for usage of Proxmark3 under WSL2 (@henrygab)
- Fixed device permissions via updated `udev` rules (@henrygab)
- Added `--back` option to `clear` command to clear the scrollback buffer (@wh201906)
- Changed `hf iclass decrypt` - mark credentials as decrypted in the dump (@natesales)
- Changed `hf iclass view` - show credentials on a decrypted dump (@natesales)
- Changed `hf mfu info` - NTAG213TT tamper info (mjaksn)
- Added commands for configuring NTAG213TT tamper featue (@mjaksn)
- Added Mifare Classic EV1 signature write support to gen4 magic tag lua script (@augustozanellato)
- Added XOR key extraction and flag to Guardall G-Prox II (@GuruSteve)
- Changed verbiage on `hf iclass info` KeyAccess area to be congruent with AA1 and AA2 areas (@GuruSteve)
- Added `hf legic info` command for other sources (@0xdeb)
- Added `hf legic einfo` - views emulator menory (@0xdeb)
- Changed `hf legic view` - now also print the decoded info of the dump file (@0xdeb)
- Changed `script run hf_mf_ultimatecard.lua -u` to support 10bytes UID (@alejandro12120)
- Updated documentation for installation on macOS with MacPorts (@linuxgemini)
- Added possible Paxton id to hitag2 tag info output
- Changed `hf mf sim` - reduce 50ms threshold to 6ms for reset to idle #1974 (@net147)
- Update `amiibo_tools.lua` with new identifiers and create a python script `update_amiibo_tools_lua.py` to automate the process in the future. (@CorySolovewicz)
- Added `lf paradox sim --fc --cn` - Simulates Paradox fob from facility code and card number (jerji)
## [Nitride.4.16191][2023-01-29]
- Changed `build_all_firmwares.sh` to fit GENERIC 256kb firmware images (@doegox)
- Fixed some coverity fixes (@iceman1001)
- Fixed `make accessrights` on Fedora (@mooey5775)
- Fixed `hf mfu info` - can now identify the 50 pF version of NTAG 210u(micro) (@mjacksn)
- Added `hf 15` sub-commands for controlling EAS, AFI, privacy mode, and the setting of passwords on SLIX tags (@mjacksn)
- Added new magic gen4 cards command in docs (@McEloff)
- Added `hf tesla info` - intital information command to read TESLA cards (@iceman1001)
- Changed `hf emrtd info` - looking for lower case .bin extensions (@iceman1001)
- Changed `hf emrtd dump` - looking for lower case .bin extensions (@iceman1001)
- Changed `lf paradox clone` - it now accepts FC/CN (@mwalker33)
- Added standalone mode for simulatin Nedap ID (@anon)
- 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)
- 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)
- Fixed failing compilation on Proxspace environment due to how python is initialized (@jmichelp)
- Fixed length check in sim module communications (@jmichelp)
- Changed timings in i2c.c when communicating with sim module (@iceman1001)
- Moved to non-deprecated API to initialize Python interpreter (@jmichelp)
- Changed `sc upgrade` updated firmware v4.13 (RDV40) - frame buffer is now 384 bytes (@sentiprox)
- Fixed contact interface / smartcard APDU chaining logic and allow 256 bytes ADPU payload. Need SIM firmware 4.13 to work (@jmichelp)
- Fixed `lf hitag dump` - Should now work as described in the command help (@natmchugh) - Fixed `lf hitag dump` - Should now work as described in the command help (@natmchugh)
- Fixed SPI flash overflow when loading dictionnaries into flash. Breaking change: added 1 more sector for Mifare - dictionnaries should be loaded again (@jmichelp) - Fixed SPI flash overflow when loading dictionnaries into flash. Breaking change: added 1 more sector for Mifare - dictionnaries should be loaded again (@jmichelp)
- Added `hf mf gload, gsave, ggetblk, gsetblk` for Gen4 GTU in mifare classic mode (@DidierA) - Added `hf mf gload, gsave, ggetblk, gsetblk` for Gen4 GTU in mifare classic mode (@DidierA)
@ -126,7 +297,6 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Fixed `hf 15 slixdisable` wrong pass id (@r1ddl3rz) - Fixed `hf 15 slixdisable` wrong pass id (@r1ddl3rz)
- Added `script run hf_mf_hid_sim.lua` (@micsen) - Added `script run hf_mf_hid_sim.lua` (@micsen)
## [Frostbit.4.14831][2022-01-11] ## [Frostbit.4.14831][2022-01-11]
- Changed Wiegand format lookup - now case-insensitive (@iceman1001) - Changed Wiegand format lookup - now case-insensitive (@iceman1001)
- Added new standalone mode `hf_15SNIFF` - Same as `hf_14ASNIFF` standalone mode for RDV4 - flashmem (@startrk1995) - Added new standalone mode `hf_15SNIFF` - Same as `hf_14ASNIFF` standalone mode for RDV4 - flashmem (@startrk1995)
@ -1343,7 +1513,10 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Mifare simulation, `hf mf sim` (was broken a long time) (@pwpiwi) - Mifare simulation, `hf mf sim` (was broken a long time) (@pwpiwi)
- Major improvements in LF area and data operations. (@marshmellow42, @iceman1001) - Major improvements in LF area and data operations. (@marshmellow42, @iceman1001)
- Issues regarding LF simulation (@pwpiwi) - Issues regarding LF simulation (@pwpiwi)
- Issue interpreting NXP "get sys info" command return value for icode tags. (@mjacksn)
### Added ### Added
- iClass functionality: full simulation of iclass tags, so tags can be simulated with data (not only CSN). Not yet support for write/update, but readers do not seem to enforce update. (@holiman). - iClass functionality: full simulation of iclass tags, so tags can be simulated with data (not only CSN). Not yet support for write/update, but readers do not seem to enforce update. (@holiman).
- iClass decryption. Proxmark can now decrypt data on an iclass tag, but requires you to have the HID decryption key locally on your computer, as this is not bundled with the sourcecode. - iClass decryption. Proxmark can now decrypt data on an iclass tag, but requires you to have the HID decryption key locally on your computer, as this is not bundled with the sourcecode.
- `hf 15 info` can detect NTAG 5 tags
- `hf 15 info` include an EAS status check on more of the icode tags which support EAS (SLI, SLIX, SLIX-L, and SLIX-S)

View file

@ -29,17 +29,17 @@ ifneq (,$(DESTDIR))
endif endif
endif endif
all clean install uninstall check: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/% mf_nonce_brute/% mfd_aes_brute/% fpga_compress/% all clean install uninstall check: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/% mf_nonce_brute/% mfd_aes_brute/% fpga_compress/% cryptorf/%
# hitag2crack toolsuite is not yet integrated in "all", it must be called explicitly: "make hitag2crack" # hitag2crack toolsuite is not yet integrated in "all", it must be called explicitly: "make hitag2crack"
#all clean install uninstall check: %: hitag2crack/% #all clean install uninstall check: %: hitag2crack/%
INSTALLTOOLS=pm3_eml2lower.sh pm3_eml2upper.sh pm3_mfdread.py pm3_mfd2eml.py pm3_eml2mfd.py pm3_amii_bin2eml.pl pm3_reblay-emulating.py pm3_reblay-reading.py INSTALLTOOLS=pm3_eml2lower.sh pm3_eml2upper.sh pm3_mfdread.py pm3_mfd2eml.py pm3_eml2mfd.py pm3_amii_bin2eml.pl pm3_reblay-emulating.py pm3_reblay-reading.py
INSTALLSIMFW=sim011.bin sim011.sha512.txt INSTALLSIMFW=sim011.bin sim011.sha512.txt sim013.bin sim013.sha512.txt
INSTALLSCRIPTS=pm3 pm3-flash pm3-flash-all pm3-flash-bootrom pm3-flash-fullimage INSTALLSCRIPTS=pm3 pm3-flash pm3-flash-all pm3-flash-bootrom pm3-flash-fullimage
INSTALLSHARES=tools/jtag_openocd traces INSTALLSHARES=tools/jtag_openocd traces
INSTALLDOCS=doc/*.md doc/md INSTALLDOCS=doc/*.md doc/md
install: all common/install install: common/install
common/install: common/install:
$(info [@] Installing common resources to $(MYDESTDIR)$(PREFIX)...) $(info [@] Installing common resources to $(MYDESTDIR)$(PREFIX)...)
@ -65,7 +65,13 @@ ifneq (,$(INSTALLSIMFW))
endif endif
ifeq ($(platform),Linux) ifeq ($(platform),Linux)
$(Q)$(INSTALLSUDO) $(MKDIR) $(DESTDIR)$(UDEV_PREFIX) $(Q)$(INSTALLSUDO) $(MKDIR) $(DESTDIR)$(UDEV_PREFIX)
$(Q)$(INSTALLSUDO) $(CP) driver/77-pm3-usb-device-blacklist.rules $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules # If user is running ArchLinux, use group 'uucp'
# Else, use group 'dialout'
ifneq ($(wildcard /etc/arch-release),)
$(Q)$(INSTALLSUDO) $(CP) driver/77-pm3-usb-device-blacklist-uucp.rules $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
else
$(Q)$(INSTALLSUDO) $(CP) driver/77-pm3-usb-device-blacklist-dialout.rules $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
endif
endif endif
uninstall: common/uninstall uninstall: common/uninstall
@ -75,27 +81,37 @@ common/uninstall:
ifneq (,$(INSTALLSCRIPTS)) ifneq (,$(INSTALLSCRIPTS))
$(Q)$(INSTALLSUDO) $(RM) $(foreach script,$(INSTALLSCRIPTS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)$(PATHSEP)$(notdir $(script))) $(Q)$(INSTALLSUDO) $(RM) $(foreach script,$(INSTALLSCRIPTS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)$(PATHSEP)$(notdir $(script)))
endif endif
ifneq (,$(INSTALLSHARES)) ifneq (,$(INSTALLSHARES))
$(Q)$(INSTALLSUDO) $(RMDIR) $(foreach share,$(INSTALLSHARES),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)$(PATHSEP)$(notdir $(share))) $(Q)$(INSTALLSUDO) $(RMDIR) $(foreach share,$(INSTALLSHARES),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)$(PATHSEP)$(notdir $(share)))
endif endif
ifneq (,$(INSTALLDOCS)) ifneq (,$(INSTALLDOCS))
$(Q)$(INSTALLSUDO) $(RMDIR) $(foreach doc,$(INSTALLDOCS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH)$(PATHSEP)$(notdir $(doc))) $(Q)$(INSTALLSUDO) $(RMDIR) $(foreach doc,$(INSTALLDOCS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH)$(PATHSEP)$(notdir $(doc)))
$(Q)$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH) $(Q)-$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH)
endif endif
ifneq (,$(INSTALLTOOLS)) ifneq (,$(INSTALLTOOLS))
$(Q)$(INSTALLSUDO) $(RM) $(foreach tool,$(INSTALLTOOLS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)$(PATHSEP)$(notdir $(tool))) $(Q)$(INSTALLSUDO) $(RM) $(foreach tool,$(INSTALLTOOLS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)$(PATHSEP)$(notdir $(tool)))
endif endif
$(Q)$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)
$(Q)-$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)
ifneq (,$(INSTALLSIMFW)) ifneq (,$(INSTALLSIMFW))
$(Q)$(INSTALLSUDO) $(RM) $(foreach fw,$(INSTALLSIMFW),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(notdir $(fw))) $(Q)$(INSTALLSUDO) $(RM) $(foreach fw,$(INSTALLSIMFW),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(notdir $(fw)))
endif endif
$(Q)$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
$(Q)-$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
ifeq ($(platform),Linux) ifeq ($(platform),Linux)
$(Q)$(INSTALLSUDO) $(RM) $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules $(Q)$(INSTALLSUDO) $(RM) $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
endif endif
$(Q)$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH) $(Q)-$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
# tests # tests
cryptorf/check: FORCE
$(info [*] CHECK $(patsubst %/check,%,$@))
$(Q)$(BASH) tools/pm3_tests.sh $(CHECKARGS) $(patsubst %/check,%,$@)
mfkey/check: FORCE mfkey/check: FORCE
$(info [*] CHECK $(patsubst %/check,%,$@)) $(info [*] CHECK $(patsubst %/check,%,$@))
$(Q)$(BASH) tools/pm3_tests.sh $(CHECKARGS) $(patsubst %/check,%,$@) $(Q)$(BASH) tools/pm3_tests.sh $(CHECKARGS) $(patsubst %/check,%,$@)
@ -132,6 +148,9 @@ common/check: FORCE
check: common/check check: common/check
$(info [*] ALL CHECKS DONE) $(info [*] ALL CHECKS DONE)
cryptorf/%: FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C tools/cryptorf $(patsubst cryptorf/%,%,$@) DESTDIR=$(MYDESTDIR)
mfkey/%: FORCE mfkey/%: FORCE
$(info [*] MAKE $@) $(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C tools/mfkey $(patsubst mfkey/%,%,$@) DESTDIR=$(MYDESTDIR) $(Q)$(MAKE) --no-print-directory -C tools/mfkey $(patsubst mfkey/%,%,$@) DESTDIR=$(MYDESTDIR)
@ -157,7 +176,7 @@ client/%: FORCE cleanifplatformchanged
$(info [*] MAKE $@) $(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C client $(patsubst client/%,%,$@) DESTDIR=$(MYDESTDIR) $(Q)$(MAKE) --no-print-directory -C client $(patsubst client/%,%,$@) DESTDIR=$(MYDESTDIR)
recovery/all: bootrom/all armsrc/all recovery/all: bootrom/all armsrc/all
recovery/install: bootrom/all armsrc/all recovery/install: bootrom/install armsrc/install
recovery/%: FORCE cleanifplatformchanged recovery/%: FORCE cleanifplatformchanged
$(info [*] MAKE $@) $(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C recovery $(patsubst recovery/%,%,$@) DESTDIR=$(MYDESTDIR) $(Q)$(MAKE) --no-print-directory -C recovery $(patsubst recovery/%,%,$@) DESTDIR=$(MYDESTDIR)
@ -183,6 +202,7 @@ help:
@echo "+ recovery - Make bootrom and fullimage files for JTAG flashing" @echo "+ recovery - Make bootrom and fullimage files for JTAG flashing"
@echo @echo
@echo "+ client - Make only the OS-specific host client" @echo "+ client - Make only the OS-specific host client"
@echo "+ cryptorf - Make tools/cryptorf"
@echo "+ mfkey - Make tools/mfkey" @echo "+ mfkey - Make tools/mfkey"
@echo "+ nonce2key - Make tools/nonce2key" @echo "+ nonce2key - Make tools/nonce2key"
@echo "+ mf_nonce_brute - Make tools/mf_nonce_brute" @echo "+ mf_nonce_brute - Make tools/mf_nonce_brute"
@ -219,6 +239,8 @@ fullimage/uninstall: armsrc/uninstall
recovery: recovery/all recovery: recovery/all
cryptorf: cryptorf/all
mfkey: mfkey/all mfkey: mfkey/all
nonce2key: nonce2key/all nonce2key: nonce2key/all
@ -256,8 +278,15 @@ endif
# configure system to ignore PM3 device as a modem (ModemManager blacklist, effective *only* if ModemManager is not using _strict_ policy) # configure system to ignore PM3 device as a modem (ModemManager blacklist, effective *only* if ModemManager is not using _strict_ policy)
# Read doc/md/ModemManager-Must-Be-Discarded.md for more info # Read doc/md/ModemManager-Must-Be-Discarded.md for more info
udev: udev:
$(SUDO) cp -rf driver/77-pm3-usb-device-blacklist.rules $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules ifneq ($(wildcard /etc/arch-release),)
# If user is running ArchLinux, use group 'uucp'
$(SUDO) cp -rf driver/77-pm3-usb-device-blacklist-uucp.rules $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
else
# Else, use group 'dialout'
$(SUDO) cp -rf driver/77-pm3-usb-device-blacklist-dialout.rules $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
endif
$(SUDO) udevadm control --reload-rules $(SUDO) udevadm control --reload-rules
$(SUDO) udevadm trigger --action=change
# configure system to add user to the dialout group and if bluetooth group exists, add user to it # configure system to add user to the dialout group and if bluetooth group exists, add user to it
# you need to logout, relogin to get this access right correct. # you need to logout, relogin to get this access right correct.
@ -267,6 +296,10 @@ ifneq ($(wildcard /etc/arch-release),)
#If user is running ArchLinux, use specific command and group #If user is running ArchLinux, use specific command and group
$(Q)$(SUDO) $(USERMOD) uucp $(USER) $(Q)$(SUDO) $(USERMOD) uucp $(USER)
$(Q)$(GETENT_BL) >/dev/null && $(SUDO) $(USERMOD) bluetooth $(USER) || true $(Q)$(GETENT_BL) >/dev/null && $(SUDO) $(USERMOD) bluetooth $(USER) || true
else ifneq ($(wildcard /etc/fedora-release),)
# If the user is running Fedora, use `usermod` with the dialout group
$(Q)$(SUDO) $(USERMOD) dialout $(USER)
$(Q)$(GETENT_BL) >/dev/null && $(SUDO) $(USERMOD) bluetooth $(USER) || true
else else
$(Q)$(SUDO) $(ADDUSER) $(USER) dialout $(Q)$(SUDO) $(ADDUSER) $(USER) dialout
$(Q)$(GETENT_BL) >/dev/null && $(SUDO) $(ADDUSER) $(USER) bluetooth || true $(Q)$(GETENT_BL) >/dev/null && $(SUDO) $(ADDUSER) $(USER) bluetooth || true
@ -294,10 +327,10 @@ style:
# Make sure python3 is installed # Make sure python3 is installed
@command -v python3 >/dev/null || ( echo "Please install 'python3' package first" ; exit 1 ) @command -v python3 >/dev/null || ( echo "Please install 'python3' package first" ; exit 1 )
# Update commands.json, patch port in case it was run under Windows # Update commands.json, patch port in case it was run under Windows
[ -x client/proxmark3 ] && client/proxmark3 --fulltext | sed 's#com[0-9]#/dev/ttyacm0#'|python3 client/pyscripts/pm3_help2json.py - doc/commands.json [ -x client/proxmark3 ] && client/proxmark3 --fulltext | sed 's#com[0-9]#/dev/ttyACM0#'|python3 client/pyscripts/pm3_help2json.py - doc/commands.json
# Update the readline autocomplete autogenerated code # Update the readline autocomplete autogenerated code
[ -x client/proxmark3 ] && client/proxmark3 --fulltext | python3 client/pyscripts/pm3_help2list.py - client/src/pm3line_vocabulory.h [ -x client/proxmark3 ] && client/proxmark3 --fulltext | python3 client/pyscripts/pm3_help2list.py - client/src/pm3line_vocabulary.h
# Detecting weird codepages and tabs. # Detecting weird codepages and tabs.
@ -346,10 +379,10 @@ release:
# - Tagging temporarily... # - Tagging temporarily...
@git tag -a -m "Release $(VERSION) - $(RELEASE_NAME)" $(VERSION) @git tag -a -m "Release $(VERSION) - $(RELEASE_NAME)" $(VERSION)
# - Changing default version information based on new tag # - Changing default version information based on new tag
@$(SH) tools/mkversion.sh > common/default_version_pm3.c.tmp && $(MV) common/default_version_pm3.c.tmp common/default_version_pm3.c @$(SH) tools/mkversion.sh --force common/default_version_pm3.c
# - Removing mkversion calls # - Removing mkversion calls
@sed -i 's#^.*\.\./tools/mkversion.sh.*|| #\t$$(Q)#' client/Makefile bootrom/Makefile armsrc/Makefile @sed -i 's#^.*\.\./tools/mkversion.sh.*|| #\t$$(Q)#' client/Makefile bootrom/Makefile armsrc/Makefile
@sed -i '/COMMAND/s/sh .*|| //' client/CMakeLists.txt @sed -i '/COMMAND/s/sh .*|| //' client/CMakeLists.txt client/experimental_lib/CMakeLists.txt
# - Deleting tag... # - Deleting tag...
@git tag -d $(VERSION) @git tag -d $(VERSION)
# - Amending commit... # - Amending commit...

View file

@ -29,8 +29,8 @@ GZIP = gzip
MKDIR = mkdir -p MKDIR = mkdir -p
RM = rm -f RM = rm -f
RMDIR = rm -rf RMDIR = rm -rf
# rmdir only if dir is empty, tolerate failure # rmdir only if dir is empty, you must add "-" when using it to tolerate failure
RMDIR_SOFT = -rmdir RMDIR_SOFT = rmdir
MV = mv MV = mv
TOUCH = touch TOUCH = touch
FALSE = false FALSE = false
@ -75,7 +75,15 @@ else
endif endif
ifeq ($(platform),Darwin) ifeq ($(platform),Darwin)
ifeq ($(shell uname -p),arm64)
# The platform is iOS
USE_BREW ?= 0
# iOS refuses to compile unless this is set
export IPHONEOS_DEPLOYMENT_TARGET=11.0
else
# M* macOS devices return arm
USE_BREW ?= 1 USE_BREW ?= 1
endif
USE_MACPORTS ?= 0 USE_MACPORTS ?= 0
AR= /usr/bin/ar rcs AR= /usr/bin/ar rcs
RANLIB= /usr/bin/ranlib RANLIB= /usr/bin/ranlib
@ -132,6 +140,10 @@ ifeq ($(shell expr $(CC_VERSION) \>= 10), 1)
endif endif
endif endif
ifeq ($(platform),Darwin) ifeq ($(platform),Darwin)
ifeq ($(shell uname -p),arm64)
# iOS will refuse to compile without the minimum target of iOS 11.0
DEFCFLAGS += -mios-version-min=11.0
endif
# their readline has strict-prototype issues # their readline has strict-prototype issues
DEFCFLAGS += -Wno-strict-prototypes DEFCFLAGS += -Wno-strict-prototypes
# some warnings about braced initializers on structs we want to ignore # some warnings about braced initializers on structs we want to ignore

View file

@ -5,8 +5,23 @@ PLATFORM=PM3RDV4
#PLATFORM=PM3GENERIC #PLATFORM=PM3GENERIC
# If you want more than one PLATFORM_EXTRAS option, separate them by spaces: # If you want more than one PLATFORM_EXTRAS option, separate them by spaces:
#PLATFORM_EXTRAS=BTADDON #PLATFORM_EXTRAS=BTADDON
#PLATFORM_EXTRAS=FLASH
#PLATFORM_EXTRAS=BTADDON FLASH
#STANDALONE=LF_SAMYRUN #STANDALONE=LF_SAMYRUN
# Uncomment the lines below in order to make a 256KB image
# and comment out the lines above
#PLATFORM=PM3GENERIC
#PLATFORM_SIZE=256
#STANDALONE=
#SKIP_HITAG=1
#SKIP_FELICA=1
#SKIP_HFPLOT=1
#SKIP_NFCBARCODE=1
#SKIP_ZX8211=1
#SKIP_LF=1
# To accelerate repetitive compilations: # To accelerate repetitive compilations:
# Install package "ccache" -> Debian/Ubuntu: /usr/lib/ccache, Fedora/CentOS/RHEL: /usr/lib64/ccache # Install package "ccache" -> Debian/Ubuntu: /usr/lib/ccache, Fedora/CentOS/RHEL: /usr/lib64/ccache
# And uncomment the following line # And uncomment the following line

View file

@ -1,4 +1,4 @@
# Iceman Fork - Proxmark3 a RFID / NFC project. # Iceman Fork - Proxmark3
The Proxmark3 is the swiss-army tool of RFID, allowing for interactions with the vast majority of RFID tags on a global scale. Originally built by Jonathan Westhues, the device is now the goto tool for RFID Analysis for the enthusiast. Iceman repository is considered to be the pinnacle of features and functionality, enabling a huge range of extremely useful and convenient commands and LUA scripts to automate chip identification, penetration testing, and programming The Proxmark3 is the swiss-army tool of RFID, allowing for interactions with the vast majority of RFID tags on a global scale. Originally built by Jonathan Westhues, the device is now the goto tool for RFID Analysis for the enthusiast. Iceman repository is considered to be the pinnacle of features and functionality, enabling a huge range of extremely useful and convenient commands and LUA scripts to automate chip identification, penetration testing, and programming
@ -35,9 +35,9 @@ The Proxmark3 is the swiss-army tool of RFID, allowing for interactions with the
| :------------------: | :------------------: | | :------------------: | :------------------: |
| [Linux - Setup and Build](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) | [Compilation Instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md)| | [Linux - Setup and Build](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) | [Compilation Instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md)|
| [Linux - Important notes on ModemManager](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md) | [Validating Proxmark3 Client Functionality](/doc/md/Use_of_Proxmark/1_Validation.md)| | [Linux - Important notes on ModemManager](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md) | [Validating Proxmark3 Client Functionality](/doc/md/Use_of_Proxmark/1_Validation.md)|
| [Mac OS X - Homebrew & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md) | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)| | [macOS - Homebrew & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/macOS-Homebrew-Installation-Instructions.md) | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)|
| [Mac OS X - MacPorts](/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md) | [Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)| | [macOS - MacPorts](/doc/md/Installation_Instructions/macOS-MacPorts-Installation-Instructions.md) | [Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)|
| [Mac OS X - Setup and Build](/doc/md/Installation_Instructions/Mac-OS-X-Compile-From-Source-Instructions.md) || | [macOS - Setup and Build](/doc/md/Installation_Instructions/macOS-Compile-From-Source-Instructions.md) ||
| [Windows - Setup and Build](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md) || | [Windows - Setup and Build](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md) ||
| [Termux / Android - Setup and Build](/doc/termux_notes.md) || | [Termux / Android - Setup and Build](/doc/termux_notes.md) ||
| [Blue Shark Manual](/doc/bt_manual_v10.md) | [Command Cheat Sheet](/doc/cheatsheet.md)| | [Blue Shark Manual](/doc/bt_manual_v10.md) | [Command Cheat Sheet](/doc/cheatsheet.md)|
@ -83,7 +83,7 @@ We define generic Proxmark3 platforms as following devices.
- **Note**: unknown pin assignments. - **Note**: unknown pin assignments.
- ⚠ Ryscorp Proxmark3 Pro - ⚠ Ryscorp Proxmark3 Pro
- **Note**: device has different fpga and unknown pin assignments. - **Note**: device has different fpga and unknown pin assignments.
- **Note**: Company have dissappared, leaving their customers in the dark. - **Note**: Company have disappeared, leaving their customers in the dark.
- ⚠ iCopy-X - ⚠ iCopy-X
- **Note**: experimental support, currently incompatible with iCopy-X GUI as Proxmark client commands are now using cliparser. - **Note**: experimental support, currently incompatible with iCopy-X GUI as Proxmark client commands are now using cliparser.
- **Note**: see also [icopyx-community repos](https://github.com/iCopy-X-Community/) for upstream sources, reversed hw etc. - **Note**: see also [icopyx-community repos](https://github.com/iCopy-X-Community/) for upstream sources, reversed hw etc.
@ -93,24 +93,30 @@ We define generic Proxmark3 platforms as following devices.
- ⚠ VX - ⚠ VX
- **Note**: unknown device hw - **Note**: unknown device hw
- ⚠ Proxmark3 X - ⚠ Proxmark3 X
- **Note**: unknown device hw. - **Note**: unknown device hw
- ⚠ Proxmark3 Ultimate
- **Note**: unknown device hw
- ⚠ Proxmark3 SE
- **Note**: unknown device hw
When it comes to these new unknown models we are depending on the community to report in if this repo works and what they did to make it work.
**256kb flash memory size of generic Proxmark3 platforms** **256KB flash memory size of generic Proxmark3 platforms**
> ⚠ **Note**: > ⚠ **Note**:
> You need to keep a eye on how large your ARM chip built-in flash memory is. > You need to keep a eye on how large your ARM chip built-in flash memory is.
> With 512kb you are fine but if its 256kb you need to compile this repo with even less functionality. > With 512KB you are fine but if its 256KB you need to compile this repo with even less functionality.
> When running the `./pm3-flash-all` you can see which size your device have if you have the bootloader from this repo installed. > When running the `./pm3-flash-all` you can see which size your device have if you have the bootloader from this repo installed.
> Otherwise you will find the size reported in the start message when running the Proxmark3 client `./pm3`. > Otherwise you will find the size reported in the start message when running the Proxmark3 client `./pm3`.
> >
> [OBS! Read the 256kb flash memory advisory](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md#256kb-versions) > [OBS! Read the 256KB flash memory advisory](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md#256KB-versions)
# What has changed? # What has changed?
Proxmark3 RDV4 hardware modifications: Proxmark3 RDV4 hardware modifications:
* added flash memory 256kb * added flash memory 256KB
* added smart card module * added smart card module
* added FPC connector for peripherals such as Bluetooth+battery addon * added FPC connector for peripherals such as Bluetooth+battery addon
* improved antennas * improved antennas
@ -178,7 +184,7 @@ This repo compiles nicely on
- Windows/MinGW environment - Windows/MinGW environment
- Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, NetHunter, Arch Linux, Fedora, Debian, Raspbian - Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, NetHunter, Arch Linux, Fedora, Debian, Raspbian
- Android / Termux - Android / Termux
- Mac OS X / Homebrew (or MacPorts, experimental) / Apple Silicon M1 - macOS / Homebrew (or MacPorts, experimental) / Apple Silicon M1
- Docker container - Docker container
- [ Iceman repo based ubuntu 18.04 container ](https://hub.docker.com/r/secopsconsult/proxmark3) - [ Iceman repo based ubuntu 18.04 container ](https://hub.docker.com/r/secopsconsult/proxmark3)
- [ Iceman fork based container v1.7 ](https://hub.docker.com/r/iceman1001/proxmark3/) - [ Iceman fork based container v1.7 ](https://hub.docker.com/r/iceman1001/proxmark3/)

15
SECURITY.md Normal file
View file

@ -0,0 +1,15 @@
# Security Policy
This is an open source project driven by volunteering devs contributing their time for free.
This is a bleeding edge repository.
The maintainers actively is working out of this repository and will be periodically re-structuring the code to make it easier to comprehend, navigate, build, test, and contribute to, so DO expect significant changes to code layout on a regular basis.
## Reporting a Vulnerability
if you find a vulnerability feel free to make a pull request with your fix and we will deal with it.
👉 Remember!
If you intend to contribute to the code, please read the coding style notes first. We usually merge your contributions fast since we do like the idea of getting a functionality in the Proxmark3 and weed out the bugs afterwards.

View file

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

View file

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

View file

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

View file

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

View file

@ -77,7 +77,7 @@ else
endif endif
ifneq (,$(findstring WITH_EM4x50,$(APP_CFLAGS))) ifneq (,$(findstring WITH_EM4x50,$(APP_CFLAGS)))
SRC_EM4x50 = em4x50.c SRC_EM4x50 = em4x50.c bruteforce.c
else else
SRC_EM4x50 = SRC_EM4x50 =
endif endif
@ -103,9 +103,6 @@ endif
# Generic standalone Mode injection of source code # Generic standalone Mode injection of source code
include Standalone/Makefile.inc include Standalone/Makefile.inc
#the FPGA bitstream files. Note: order matters!
FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit fpga_felica.bit fpga_hf_15.bit
#the lz4 source files required for decompressing the fpga config at run time #the lz4 source files required for decompressing the fpga config at run time
SRC_LZ4 = lz4.c SRC_LZ4 = lz4.c
#additional defines required to compile lz4 #additional defines required to compile lz4
@ -184,10 +181,10 @@ showinfo:
.DELETE_ON_ERROR: .DELETE_ON_ERROR:
# version_pm3.c should be remade on every time fullimage.stage1.elf should be remade # version_pm3.c should be checked on every time fullimage.stage1.elf should be remade
version_pm3.c: default_version_pm3.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) version_pm3.c: default_version_pm3.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) .FORCE
$(info [-] GEN $@) $(info [-] CHECK $@)
$(Q)$(SH) ../tools/mkversion.sh > $@ || $(CP) $< $@ $(Q)$(SH) ../tools/mkversion.sh $@ || $(CP) $< $@
fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR)
$(info [-] GEN $@) $(info [-] GEN $@)
@ -257,7 +254,7 @@ uninstall:
$(info [@] Uninstalling fullimage from $(DESTDIR)$(PREFIX)...) $(info [@] Uninstalling fullimage from $(DESTDIR)$(PREFIX)...)
$(Q)$(INSTALLSUDO) $(RM) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(INSTALLFWTAG) $(Q)$(INSTALLSUDO) $(RM) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(INSTALLFWTAG)
.PHONY: all clean help install uninstall .PHONY: all clean help install uninstall .FORCE
help: help:
@echo Multi-OS Makefile, you are running on $(DETECTED_OS) @echo Multi-OS Makefile, you are running on $(DETECTED_OS)
@echo Possible targets: @echo Possible targets:

View file

@ -50,12 +50,21 @@ define KNOWN_STANDALONE_DEFINITIONS
| LF_ICEHID | LF HID collector to flashmem | | LF_ICEHID | LF HID collector to flashmem |
| (RDV4 only) | | | (RDV4 only) | |
+----------------------------------------------------------+ +----------------------------------------------------------+
| LF_MULTIHID | LF HID 26 Bit (H1031) multi simulator |
| | - Shain Lakin |
+----------------------------------------------------------+
| LF_NEDAP_SIM | LF Nedap ID simple simulator |
| | |
+----------------------------------------------------------+
| LF_NEXID | LF Nexwatch collector to flashmem | | LF_NEXID | LF Nexwatch collector to flashmem |
| (RDV4 only) | | | (RDV4 only) | |
+----------------------------------------------------------+ +----------------------------------------------------------+
| LF_PROXBRUTE | HID ProxII bruteforce | | LF_PROXBRUTE | HID ProxII bruteforce |
| | - Brad Antoniewicz | | | - Brad Antoniewicz |
+----------------------------------------------------------+ +----------------------------------------------------------+
| LF_PROX2BRUTE | HID ProxII bruteforce v2 |
| | |
+----------------------------------------------------------+
| LF_SAMYRUN | HID26 read/clone/sim | | LF_SAMYRUN | HID26 read/clone/sim |
| (default) | - Samy Kamkar | | (default) | - Samy Kamkar |
+----------------------------------------------------------+ +----------------------------------------------------------+
@ -77,6 +86,9 @@ define KNOWN_STANDALONE_DEFINITIONS
| HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth | | HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth |
| (RDV4 only) | storing in flashmem - Bogito | | (RDV4 only) | storing in flashmem - Bogito |
+----------------------------------------------------------+ +----------------------------------------------------------+
| HF_CARDHOPPER | Relay 14a protocols over long distances|
| (RDV4 only) | (w/ IP backbone) - Sam Haskins |
+----------------------------------------------------------+
| HF_COLIN | Mifare ultra fast sniff/sim/clone | | HF_COLIN | Mifare ultra fast sniff/sim/clone |
| (RDV4 only) | - Colin Brigato | | (RDV4 only) | - Colin Brigato |
+----------------------------------------------------------+ +----------------------------------------------------------+
@ -118,11 +130,14 @@ define KNOWN_STANDALONE_DEFINITIONS
+----------------------------------------------------------+ +----------------------------------------------------------+
endef endef
STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN LF_THAREXDE LF_NEXID
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_TCPRST HF_TMUDFORD HF_YOUNG HF_REBLAY DANKARMULTI STANDALONE_MODES := LF_SKELETON
STANDALONE_MODES_REQ_BT := HF_REBLAY 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_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_CARDHOPPER HF_REBLAY
STANDALONE_MODES_REQ_SMARTCARD := STANDALONE_MODES_REQ_SMARTCARD :=
STANDALONE_MODES_REQ_FLASH := LF_HIDFCBRUTE LF_ICEHID LF_NEXID LF_THAREXDE HF_BOG HF_COLIN HF_ICECLASS HF_MFCSIM HF_LEGICSIM STANDALONE_MODES_REQ_FLASH := LF_HIDFCBRUTE LF_ICEHID LF_NEXID LF_THAREXDE HF_BOG HF_COLIN HF_ICECLASS HF_LEGICSIM HF_MFCSIM
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),) ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),)
STANDALONE_PLATFORM_DEFS += -DWITH_STANDALONE_$(STANDALONE) STANDALONE_PLATFORM_DEFS += -DWITH_STANDALONE_$(STANDALONE)
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_SMARTCARD)),) ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_SMARTCARD)),)

View file

@ -21,13 +21,21 @@ SRC_STANDALONE = placeholder.c
ifneq (,$(findstring WITH_STANDALONE_LF_SKELETON,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_LF_SKELETON,$(APP_CFLAGS)))
SRC_STANDALONE = lf_skeleton.c SRC_STANDALONE = lf_skeleton.c
endif endif
# WITH_STANDALONE_LF_SAMYRUN # WITH_STANDALONE_LF_EM4100EMUL
ifneq (,$(findstring WITH_STANDALONE_LF_SAMYRUN,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_LF_EM4100EMUL,$(APP_CFLAGS)))
SRC_STANDALONE = lf_samyrun.c SRC_STANDALONE = lf_em4100emul.c
endif endif
# WITH_STANDALONE_LF_PROXBRUTE # WITH_STANDALONE_LF_EM4100RSWB
ifneq (,$(findstring WITH_STANDALONE_LF_PROXBRUTE,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RSWB,$(APP_CFLAGS)))
SRC_STANDALONE = lf_proxbrute.c SRC_STANDALONE = lf_em4100rswb.c
endif
# WITH_STANDALONE_LF_EM4100RSWW
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RSWW,$(APP_CFLAGS)))
SRC_STANDALONE = lf_em4100rsww.c
endif
# WITH_STANDALONE_LF_EM4100RWC
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RWC,$(APP_CFLAGS)))
SRC_STANDALONE = lf_em4100rwc.c
endif endif
# WITH_STANDALONE_LF_HIDBRUTE # WITH_STANDALONE_LF_HIDBRUTE
ifneq (,$(findstring WITH_STANDALONE_LF_HIDBRUTE,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_LF_HIDBRUTE,$(APP_CFLAGS)))
@ -37,21 +45,37 @@ endif
ifneq (,$(findstring WITH_STANDALONE_LF_HIDFCBRUTE,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_LF_HIDFCBRUTE,$(APP_CFLAGS)))
SRC_STANDALONE = lf_hidfcbrute.c SRC_STANDALONE = lf_hidfcbrute.c
endif endif
# WITH_STANDALONE_HF_YOUNG # WITH_STANDALONE_LF_ICEHID
ifneq (,$(findstring WITH_STANDALONE_HF_YOUNG,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS)))
SRC_STANDALONE = hf_young.c SRC_STANDALONE = lf_icehid.c
endif endif
# WITH_STANDALONE_HF_MATTYRUN # WITH_STANDALONE_LF_MULTIHID
ifneq (,$(findstring WITH_STANDALONE_HF_MATTYRUN,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_LF_MULTIHID,$(APP_CFLAGS)))
SRC_STANDALONE = hf_mattyrun.c SRC_STANDALONE = lf_multihid.c
endif endif
# WITH_STANDALONE_HF_COLIN # WITH_STANDALONE_LF_NEDAP_SIM
ifneq (,$(findstring WITH_STANDALONE_HF_COLIN,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_LF_NEDAP_SIM,$(APP_CFLAGS)))
SRC_STANDALONE = vtsend.c hf_colin.c frozen.c nprintf.c SRC_STANDALONE = lf_nedap_sim.c
endif endif
# WITH_STANDALONE_HF_BOG # WITH_STANDALONE_LF_NEXID
ifneq (,$(findstring WITH_STANDALONE_HF_BOG,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_LF_NEXID,$(APP_CFLAGS)))
SRC_STANDALONE = hf_bog.c SRC_STANDALONE = lf_nexid.c
endif
# WITH_STANDALONE_LF_SAMYRUN
ifneq (,$(findstring WITH_STANDALONE_LF_SAMYRUN,$(APP_CFLAGS)))
SRC_STANDALONE = lf_samyrun.c
endif
# WITH_STANDALONE_LF_PROXBRUTE
ifneq (,$(findstring WITH_STANDALONE_LF_PROXBRUTE,$(APP_CFLAGS)))
SRC_STANDALONE = lf_proxbrute.c
endif
# WITH_STANDALONE_LF_PROX2BRUTE
ifneq (,$(findstring WITH_STANDALONE_LF_PROX2BRUTE,$(APP_CFLAGS)))
SRC_STANDALONE = lf_prox2brute.c
endif
# WITH_STANDALONE_LF_THAREXDE
ifneq (,$(findstring WITH_STANDALONE_LF_THAREXDE,$(APP_CFLAGS)))
SRC_STANDALONE = lf_tharexde.c
endif endif
# WITH_STANDALONE_HF_14ASNIFF # WITH_STANDALONE_HF_14ASNIFF
ifneq (,$(findstring WITH_STANDALONE_HF_14ASNIFF,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_14ASNIFF,$(APP_CFLAGS)))
@ -69,33 +93,25 @@ endif
ifneq (,$(findstring WITH_STANDALONE_HF_AVEFUL,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_AVEFUL,$(APP_CFLAGS)))
SRC_STANDALONE = hf_aveful.c SRC_STANDALONE = hf_aveful.c
endif endif
# WITH_STANDALONE_HF_TCPRST # WITH_STANDALONE_HF_BOG
ifneq (,$(findstring WITH_STANDALONE_HF_TCPRST,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_BOG,$(APP_CFLAGS)))
SRC_STANDALONE = hf_tcprst.c SRC_STANDALONE = hf_bog.c
endif endif
# WITH_STANDALONE_LF_ICEHID # WITH_STANDALONE_HF_CARDHOPPER
ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_CARDHOPPER,$(APP_CFLAGS)))
SRC_STANDALONE = lf_icehid.c SRC_STANDALONE = hf_cardhopper.c
endif endif
# WITH_STANDALONE_LF_NEXID # WITH_STANDALONE_HF_COLIN
ifneq (,$(findstring WITH_STANDALONE_LF_NEXID,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_COLIN,$(APP_CFLAGS)))
SRC_STANDALONE = lf_nexid.c SRC_STANDALONE = vtsend.c hf_colin.c frozen.c nprintf.c
endif endif
# WITH_STANDALONE_LF_EM4100EMUL # WITH_STANDALONE_HF_CRAFTBYTE
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100EMUL,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_CRAFTBYTE,$(APP_CFLAGS)))
SRC_STANDALONE = lf_em4100emul.c SRC_STANDALONE = hf_craftbyte.c
endif endif
# WITH_STANDALONE_LF_EM4100RSWB # WITH_STANDALONE_HF_ICECLASS
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RSWB,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_ICECLASS,$(APP_CFLAGS)))
SRC_STANDALONE = lf_em4100rswb.c SRC_STANDALONE = hf_iceclass.c
endif
# WITH_STANDALONE_LF_EM4100RSWW
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RSWW,$(APP_CFLAGS)))
SRC_STANDALONE = lf_em4100rsww.c
endif
# WITH_STANDALONE_LF_EM4100RWC
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RWC,$(APP_CFLAGS)))
SRC_STANDALONE = lf_em4100rwc.c
endif endif
# WITH_STANDALONE_HF_LEGIC # WITH_STANDALONE_HF_LEGIC
ifneq (,$(findstring WITH_STANDALONE_HF_LEGIC,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_LEGIC,$(APP_CFLAGS)))
@ -105,33 +121,33 @@ endif
ifneq (,$(findstring WITH_STANDALONE_HF_LEGICSIM,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_LEGICSIM,$(APP_CFLAGS)))
SRC_STANDALONE = hf_legicsim.c SRC_STANDALONE = hf_legicsim.c
endif endif
# WITH_STANDALONE_HF_MATTYRUN
ifneq (,$(findstring WITH_STANDALONE_HF_MATTYRUN,$(APP_CFLAGS)))
SRC_STANDALONE = hf_mattyrun.c
endif
# WITH_STANDALONE_HF_MFCSIM
ifneq (,$(findstring WITH_STANDALONE_HF_MFCSIM,$(APP_CFLAGS)))
SRC_STANDALONE = hf_mfcsim.c
endif
# WITH_STANDALONE_HF_MSDSAL # WITH_STANDALONE_HF_MSDSAL
ifneq (,$(findstring WITH_STANDALONE_HF_MSDSAL,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_MSDSAL,$(APP_CFLAGS)))
SRC_STANDALONE = hf_msdsal.c SRC_STANDALONE = hf_msdsal.c
endif endif
# WITH_STANDALONE_HF_ICECLASS # WITH_STANDALONE_HF_REBLAY
ifneq (,$(findstring WITH_STANDALONE_HF_ICECLASS,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_REBLAY,$(APP_CFLAGS)))
SRC_STANDALONE = hf_iceclass.c SRC_STANDALONE = hf_reblay.c
endif endif
# WITH_STANDALONE_LF_THAREXDE # WITH_STANDALONE_HF_TCPRST
ifneq (,$(findstring WITH_STANDALONE_LF_THAREXDE,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_TCPRST,$(APP_CFLAGS)))
SRC_STANDALONE = lf_tharexde.c SRC_STANDALONE = hf_tcprst.c
endif
# WITH_STANDALONE_HF_CRAFTBYTE
ifneq (,$(findstring WITH_STANDALONE_HF_CRAFTBYTE,$(APP_CFLAGS)))
SRC_STANDALONE = hf_craftbyte.c
endif endif
# WITH_STANDALONE_HF_TMUDFORD # WITH_STANDALONE_HF_TMUDFORD
ifneq (,$(findstring WITH_STANDALONE_HF_TMUDFORD,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_TMUDFORD,$(APP_CFLAGS)))
SRC_STANDALONE = hf_tmudford.c SRC_STANDALONE = hf_tmudford.c
endif endif
# WITH_STANDALONE_HF_REBLAY # WITH_STANDALONE_HF_YOUNG
ifneq (,$(findstring WITH_STANDALONE_HF_REBLAY,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_YOUNG,$(APP_CFLAGS)))
SRC_STANDALONE = hf_reblay.c SRC_STANDALONE = hf_young.c
endif
# WITH_STANDALONE_HF_MFCSIM
ifneq (,$(findstring WITH_STANDALONE_HF_MFCSIM,$(APP_CFLAGS)))
SRC_STANDALONE = hf_mfcsim.c
endif endif
ifneq (,$(findstring WITH_STANDALONE_DANKARMULTI,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_DANKARMULTI,$(APP_CFLAGS)))

View file

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

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

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

View file

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

View file

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

View file

@ -293,7 +293,7 @@ static void ReadLastTagFromFlash(void) {
rdv40_spiffs_read_as_filetype((char *)HFCOLIN_LASTTAG_SYMLINK, (uint8_t *)mem, len, RDV40_SPIFFS_SAFETY_SAFE); rdv40_spiffs_read_as_filetype((char *)HFCOLIN_LASTTAG_SYMLINK, (uint8_t *)mem, len, RDV40_SPIFFS_SAFETY_SAFE);
// copy 64blocks (16bytes) starting w block0, to emulator mem. // copy 64blocks (16bytes) starting w block0, to emulator mem.
emlSetMem(mem, 0, 64); emlSetMem_xt(mem, 0, 64, 16);
DbprintfEx(FLAG_NEWLINE, "[OK] Last tag recovered from FLASHMEM set to emulator"); DbprintfEx(FLAG_NEWLINE, "[OK] Last tag recovered from FLASHMEM set to emulator");
cjSetCursLeft(); cjSetCursLeft();
@ -650,7 +650,7 @@ failtag:
for (uint8_t t = 0; t < 2; t++) { for (uint8_t t = 0; t < 2; t++) {
memcpy(mblock + t * 10, foundKey[t][sectorNo], 6); memcpy(mblock + t * 10, foundKey[t][sectorNo], 6);
} }
emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); emlSetMem_xt(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1, 16);
} }
cjSetCursLeft(); cjSetCursLeft();
@ -821,24 +821,24 @@ int e_MifareECardLoad(uint32_t numofsectors, uint8_t keytype) {
} }
for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(s); blockNo++) { for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(s); blockNo++) {
if (isOK && mifare_classic_readblock(pcs, colin_cjcuid, FirstBlockOfSector(s) + blockNo, dataoutbuf)) { if (isOK && mifare_classic_readblock(pcs, FirstBlockOfSector(s) + blockNo, dataoutbuf)) {
isOK = false; isOK = false;
break; break;
}; };
if (isOK) { if (isOK) {
if (blockNo < NumBlocksPerSector(s) - 1) { if (blockNo < NumBlocksPerSector(s) - 1) {
emlSetMem(dataoutbuf, FirstBlockOfSector(s) + blockNo, 1); emlSetMem_xt(dataoutbuf, FirstBlockOfSector(s) + blockNo, 1, 16);
} else { } else {
// sector trailer, keep the keys, set only the AC // sector trailer, keep the keys, set only the AC
emlGetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1); emlGetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1);
memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4); memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);
emlSetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1); emlSetMem_xt(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1, 16);
} }
} }
} }
} }
int res = mifare_classic_halt(pcs, colin_cjcuid); int res = mifare_classic_halt(pcs);
(void)res; (void)res;
crypto1_deinit(pcs); crypto1_deinit(pcs);
@ -986,7 +986,7 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
break; break;
}; };
if (mifare_classic_halt(NULL, colin_cjcuid)) { if (mifare_classic_halt(NULL)) {
DbprintfEx(FLAG_NEWLINE, "Halt error"); DbprintfEx(FLAG_NEWLINE, "Halt error");
break; break;
}; };
@ -1006,7 +1006,7 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
break; break;
}; };
if (mifare_classic_halt(NULL, colin_cjcuid)) { if (mifare_classic_halt(NULL)) {
DbprintfEx(FLAG_NEWLINE, "Halt error"); DbprintfEx(FLAG_NEWLINE, "Halt error");
break; break;
}; };
@ -1043,7 +1043,7 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
}; };
if (workFlags & 0x04) { if (workFlags & 0x04) {
if (mifare_classic_halt(NULL, colin_cjcuid)) { if (mifare_classic_halt(NULL)) {
cjSetCursFRight(); cjSetCursFRight();
DbprintfEx(FLAG_NEWLINE, "Halt error"); DbprintfEx(FLAG_NEWLINE, "Halt error");

View file

@ -44,8 +44,9 @@
#define ICE_STATE_READER 3 #define ICE_STATE_READER 3
#define ICE_STATE_CONFIGCARD 4 #define ICE_STATE_CONFIGCARD 4
#define ICE_STATE_DUMP_SIM 5 #define ICE_STATE_DUMP_SIM 5
#define ICE_STATE_READ_SIM 6
#define HF_ICLASS_NUM_MODES 6 #define HF_ICLASS_NUM_MODES 7
// ==================================================== // ====================================================
// Select which standalone function to be active. // Select which standalone function to be active.
@ -56,6 +57,7 @@
//#define ICE_USE ICE_STATE_READER //#define ICE_USE ICE_STATE_READER
//#define ICE_USE ICE_STATE_CONFIGCARD //#define ICE_USE ICE_STATE_CONFIGCARD
//#define ICE_USE ICE_STATE_DUMP_SIM //#define ICE_USE ICE_STATE_DUMP_SIM
//#define ICE_USE ICE_STATE_READ_SIM
// ==================================================== // ====================================================
@ -322,6 +324,7 @@ static int reader_dump_mode(void) {
.use_credit_key = false, .use_credit_key = false,
.do_auth = true, .do_auth = true,
.send_reply = false, .send_reply = false,
.shallow_mod = false,
}; };
memcpy(auth.key, legacy_aa1_key, sizeof(auth.key)); memcpy(auth.key, legacy_aa1_key, sizeof(auth.key));
@ -333,7 +336,7 @@ static int reader_dump_mode(void) {
// select tag. // select tag.
uint32_t eof_time = 0; uint32_t eof_time = 0;
bool res = select_iclass_tag(hdr, auth.use_credit_key, &eof_time); bool res = select_iclass_tag(hdr, auth.use_credit_key, &eof_time, false);
if (res == false) { if (res == false) {
switch_off(); switch_off();
continue; continue;
@ -382,7 +385,7 @@ static int reader_dump_mode(void) {
// main read loop // main read loop
for (uint16_t i = start_block; i <= app1_limit; i++) { for (uint16_t i = start_block; i <= app1_limit; i++) {
if (iclass_read_block(i, card_data + (8 * i), &start_time, &eof_time)) { if (iclass_read_block(i, card_data + (8 * i), &start_time, &eof_time, false)) {
dumped++; dumped++;
} }
} }
@ -394,7 +397,7 @@ static int reader_dump_mode(void) {
auth.use_credit_key = true; auth.use_credit_key = true;
memcpy(auth.key, aa2_key, sizeof(auth.key)); memcpy(auth.key, aa2_key, sizeof(auth.key));
res = select_iclass_tag(hdr, auth.use_credit_key, &eof_time); res = select_iclass_tag(hdr, auth.use_credit_key, &eof_time, false);
if (res) { if (res) {
// sanity check of CSN. // sanity check of CSN.
@ -408,7 +411,7 @@ static int reader_dump_mode(void) {
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
for (uint16_t i = app1_limit + 1; i <= app2_limit; i++) { for (uint16_t i = app1_limit + 1; i <= app2_limit; i++) {
if (iclass_read_block(i, card_data + (8 * i), &start_time, &eof_time)) { if (iclass_read_block(i, card_data + (8 * i), &start_time, &eof_time, false)) {
dumped++; dumped++;
} }
} }
@ -458,6 +461,7 @@ static int dump_sim_mode(void) {
.use_credit_key = false, .use_credit_key = false,
.do_auth = true, .do_auth = true,
.send_reply = false, .send_reply = false,
.shallow_mod = false,
}; };
memcpy(auth.key, legacy_aa1_key, sizeof(auth.key)); memcpy(auth.key, legacy_aa1_key, sizeof(auth.key));
@ -469,7 +473,7 @@ static int dump_sim_mode(void) {
// select tag. // select tag.
uint32_t eof_time = 0; uint32_t eof_time = 0;
bool res = select_iclass_tag(hdr, auth.use_credit_key, &eof_time); bool res = select_iclass_tag(hdr, auth.use_credit_key, &eof_time, false);
if (res == false) { if (res == false) {
switch_off(); switch_off();
continue; continue;
@ -518,7 +522,7 @@ static int dump_sim_mode(void) {
// main read loop // main read loop
for (uint16_t i = start_block; i <= app1_limit; i++) { for (uint16_t i = start_block; i <= app1_limit; i++) {
if (iclass_read_block(i, card_data + (8 * i), &start_time, &eof_time)) { if (iclass_read_block(i, card_data + (8 * i), &start_time, &eof_time, false)) {
dumped++; dumped++;
} }
} }
@ -530,7 +534,7 @@ static int dump_sim_mode(void) {
auth.use_credit_key = true; auth.use_credit_key = true;
memcpy(auth.key, aa2_key, sizeof(auth.key)); memcpy(auth.key, aa2_key, sizeof(auth.key));
res = select_iclass_tag(hdr, auth.use_credit_key, &eof_time); res = select_iclass_tag(hdr, auth.use_credit_key, &eof_time, false);
if (res) { if (res) {
// sanity check of CSN. // sanity check of CSN.
@ -544,7 +548,7 @@ static int dump_sim_mode(void) {
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
for (uint16_t i = app1_limit + 1; i <= app2_limit; i++) { for (uint16_t i = app1_limit + 1; i <= app2_limit; i++) {
if (iclass_read_block(i, card_data + (8 * i), &start_time, &eof_time)) { if (iclass_read_block(i, card_data + (8 * i), &start_time, &eof_time, false)) {
dumped++; dumped++;
} }
} }
@ -718,6 +722,16 @@ void RunMod(void) {
mode = ICE_STATE_NONE; mode = ICE_STATE_NONE;
break; break;
} }
case ICE_STATE_READ_SIM: {
DbpString("-=[ enter " _CYAN_("`read & sim`") " mode, read cards, then sim after button press ]=-");
DbpString("Entering reader dump mode");
reader_dump_mode();
SpinDelay(1200); // debounce button press
DbpString("Entering fullsim mode");
fullsim_mode();
DbpString("Exiting fullsim mode");
LEDsoff();
}
} }
} }

View file

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

View file

@ -109,7 +109,7 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_
break; break;
}; };
if (mifare_classic_halt(NULL, mattyrun_cuid)) { if (mifare_classic_halt(NULL)) {
DbprintfEx(FLAG_NEWLINE, "Halt error"); DbprintfEx(FLAG_NEWLINE, "Halt error");
break; break;
}; };
@ -129,7 +129,7 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_
break; break;
}; };
if (mifare_classic_halt(NULL, mattyrun_cuid)) { if (mifare_classic_halt(NULL)) {
DbprintfEx(FLAG_NEWLINE, "Halt error"); DbprintfEx(FLAG_NEWLINE, "Halt error");
break; break;
}; };
@ -165,7 +165,7 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_
}; };
if (workFlags & 0x04) { if (workFlags & 0x04) {
if (mifare_classic_halt(NULL, mattyrun_cuid)) { if (mifare_classic_halt(NULL)) {
DbprintfEx(FLAG_NEWLINE, "Halt error"); DbprintfEx(FLAG_NEWLINE, "Halt error");
break; break;
}; };
@ -267,23 +267,23 @@ static int saMifareECardLoad(uint32_t numofsectors, uint8_t keytype) {
// failure to read one block, skips to next sector. // failure to read one block, skips to next sector.
for (uint8_t blockNo = 0; blockNo < NumBlocksPerSector(s); blockNo++) { for (uint8_t blockNo = 0; blockNo < NumBlocksPerSector(s); blockNo++) {
if (mifare_classic_readblock(pcs, mattyrun_cuid, FirstBlockOfSector(s) + blockNo, dataoutbuf)) { if (mifare_classic_readblock(pcs, FirstBlockOfSector(s) + blockNo, dataoutbuf)) {
retval = PM3_ESOFT; retval = PM3_ESOFT;
break; break;
}; };
if (blockNo < NumBlocksPerSector(s) - 1) { if (blockNo < NumBlocksPerSector(s) - 1) {
emlSetMem(dataoutbuf, FirstBlockOfSector(s) + blockNo, 1); emlSetMem_xt(dataoutbuf, FirstBlockOfSector(s) + blockNo, 1, 16);
} else { } else {
// sector trailer, keep the keys, set only the AC // sector trailer, keep the keys, set only the AC
emlGetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1); emlGetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1);
memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4); memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);
emlSetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1); emlSetMem_xt(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1, 16);
} }
} }
} }
int res = mifare_classic_halt(pcs, mattyrun_cuid); int res = mifare_classic_halt(pcs);
(void)res; (void)res;
out: out:
@ -505,7 +505,7 @@ void RunMod(void) {
memcpy(mblock + t * 10, foundKey[t][sectorNo], 6); memcpy(mblock + t * 10, foundKey[t][sectorNo], 6);
} }
} }
emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); emlSetMem_xt(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1, 16);
} }
} }

View file

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

View file

@ -189,7 +189,7 @@ void RunMod(void) {
memcpy(data, visauid, 4); memcpy(data, visauid, 4);
// to initialize the emulation // to initialize the emulation
uint8_t tagType = 4; // 4 = ISO/IEC 14443-4 - javacard (JCOP) uint8_t tagType = 11; // 11 = ISO/IEC 14443-4 - javacard (JCOP)
tag_response_info_t *responses; tag_response_info_t *responses;
uint32_t cuid = 0; uint32_t cuid = 0;
uint32_t counters[3] = { 0x00, 0x00, 0x00 }; uint32_t counters[3] = { 0x00, 0x00, 0x00 };
@ -377,6 +377,7 @@ void RunMod(void) {
// dynamic_response_info will be in charge of responses // dynamic_response_info will be in charge of responses
dynamic_response_info.response_n = 0; dynamic_response_info.response_n = 0;
//Dbprintf("receivedCmd: %02x\n", receivedCmd);
// received a REQUEST // received a REQUEST
if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) { if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) {
odd_reply = !odd_reply; odd_reply = !odd_reply;
@ -386,30 +387,35 @@ void RunMod(void) {
// received a HALT // received a HALT
} else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) { } else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) {
// DbpString(_YELLOW_("+") "Received a HALT"); //DbpString(_YELLOW_("+") "Received a HALT");
p_response = NULL; p_response = NULL;
// received a WAKEUP // received a WAKEUP
} else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) { } else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) {
// DbpString(_YELLOW_("+") "WAKEUP Received"); //DbpString(_YELLOW_("+") "WAKEUP Received");
prevCmd = 0; prevCmd = 0;
p_response = &responses[RESP_INDEX_ATQA]; p_response = &responses[RESP_INDEX_ATQA];
// received request for UID (cascade 1) // received request for UID (cascade 1)
} else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 2) { } else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 2) {
// DbpString(_YELLOW_("+") "Request for UID C1"); //DbpString(_YELLOW_("+") "Request for UID C1");
p_response = &responses[RESP_INDEX_UIDC1]; p_response = &responses[RESP_INDEX_UIDC1];
// received a SELECT (cascade 1) // received a SELECT (cascade 1)
} else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) { } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) {
// DbpString(_YELLOW_("+") "Request for SELECT S1"); //DbpString(_YELLOW_("+") "Request for SELECT S1");
p_response = &responses[RESP_INDEX_SAKC1]; p_response = &responses[RESP_INDEX_SAKC1];
// received a RATS request // received a RATS request
} else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { } else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) {
// DbpString(_YELLOW_("+") "Request for RATS"); DbpString(_YELLOW_("+") "Request for RATS");
prevCmd = 0; prevCmd = 0;
p_response = &responses[RESP_INDEX_RATS]; //p_response = &responses[RESP_INDEX_RATS];
static uint8_t rRATS[] = { 0x13, 0x78, 0x80, 0x72, 0x02, 0x80, 0x31, 0x80, 0x66, 0xb1, 0x84, 0x0c, 0x01, 0x6e, 0x01, 0x83, 0x00, 0x90, 0x00 };
memcpy(&dynamic_response_info.response[0], rRATS, sizeof(rRATS));
dynamic_response_info.response_n = sizeof(rRATS);
} else { } else {
DbpString(_YELLOW_("[ ") "Card reader command" _YELLOW_(" ]")); DbpString(_YELLOW_("[ ") "Card reader command" _YELLOW_(" ]"));
@ -483,6 +489,7 @@ void RunMod(void) {
} }
} }
} }
if (dynamic_response_info.response_n > 0) { if (dynamic_response_info.response_n > 0) {
DbpString(_GREEN_("[ ") "Proxmark3 answer" _GREEN_(" ]")); DbpString(_GREEN_("[ ") "Proxmark3 answer" _GREEN_(" ]"));
Dbhexdump(dynamic_response_info.response_n, dynamic_response_info.response, false); Dbhexdump(dynamic_response_info.response_n, dynamic_response_info.response, false);

View file

@ -0,0 +1,76 @@
//-----------------------------------------------------------------------------
// Copyright (C) Shain Lakin, 2023
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
// LF HID 26 Bit (H10301) multi simulator:
// Simple LF HID26 (H10301) tag simulator
// Short click - select next slot and start simulation
// LEDS = LED ON for selected slot
// Add tags (raw) to the hid26_predefined_raw array
//-----------------------------------------------------------------------------
#include "standalone.h"
#include "proxmark3_arm.h"
#include "appmain.h"
#include "fpgaloader.h"
#include "util.h"
#include "dbprint.h"
#include "ticks.h"
#include "lfops.h"
#define ARRAYLEN(x) (sizeof(x) / sizeof((x)[0]))
#define MAX_IND 4
void LED_Slot(int i);
static uint64_t hid26_predefined_raw[] = {0x2004ec2e87, 0x2004421807, 0x20064312d6, 0x2006ec0c86};
static uint8_t hid26_slots_count;
void ModInfo(void) {
DbpString("LF HID 26 Bit (H10301) multi simulator - aka MultiHID (Shain Lakin)");
}
void LED_Slot(int i) {
LEDsoff();
if (hid26_slots_count > 4) {
LED(i % MAX_IND, 0);
} else {
LED(1 << i, 0);
}
}
void RunMod(void) {
StandAloneMode();
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
Dbprintf(">> LF HID26 multi simulator started - aka MultiHID (Shain Lakin) <<");
int selected = 0; //selected slot after start
hid26_slots_count = ARRAYLEN(hid26_predefined_raw);
for (;;) {
WDT_HIT();
if (data_available()) {
LEDsoff();
break;
}
SpinDelay(100);
SpinUp(100);
LED_Slot(selected);
uint64_t raw_data = hid26_predefined_raw[selected];
CmdHIDsimTAG(0, raw_data >> 32, raw_data & 0xFFFFFFFF, 0, false);
selected = (selected + 1) % hid26_slots_count;
}
}

View file

@ -0,0 +1,207 @@
//-----------------------------------------------------------------------------
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
// This simple mode encode, then emulate a Nedap identificator until button pressed
// lots of code from client side, cmdlfnedap, util, etc.
//-----------------------------------------------------------------------------
#include "standalone.h" // standalone definitions
#include "proxmark3_arm.h"
#include "appmain.h"
#include "fpgaloader.h"
#include "lfops.h"
#include "util.h"
#include "dbprint.h"
#include "string.h"
#include "BigBuf.h"
#include "crc16.h"
#define MODULE_LONG_NAME "LF Nedap simple simulator"
typedef struct _NEDAP_TAG {
uint8_t subType;
uint16_t customerCode;
uint32_t id;
uint8_t bIsLong;
} NEDAP_TAG, *PNEDAP_TAG;
const NEDAP_TAG Tag = {.subType = 0x5, .customerCode = 0x123, .id = 42424, .bIsLong = 1};
static int NedapPrepareBigBuffer(const NEDAP_TAG *pTag);
static void biphaseSimBitInverted(uint8_t c, int *n, uint8_t *phase);
static void NedapGen(uint8_t subType, uint16_t customerCode, uint32_t id, bool isLong, uint8_t *data);
static uint8_t isEven_64_63(const uint8_t *data);
static inline uint32_t bitcount32(uint32_t a);
static void bytes_to_bytebits(const void *src, const size_t srclen, void *dest);
void ModInfo(void) {
DbpString(" " MODULE_LONG_NAME);
}
void RunMod(void) {
int n;
StandAloneMode();
Dbprintf("[=] " MODULE_LONG_NAME " -- started");
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
Dbprintf("[=] NEDAP (%s) - ID: " _GREEN_("%05u") " subtype: " _GREEN_("%1u") " customer code: " _GREEN_("%u / 0x%03X"), Tag.bIsLong ? "128b" : "64b", Tag.id, Tag.subType, Tag.customerCode, Tag.customerCode);
n = NedapPrepareBigBuffer(&Tag);
do {
WDT_HIT();
if (data_available())
break;
SimulateTagLowFrequency(n, 0, true);
} while (BUTTON_HELD(1000) == BUTTON_NO_CLICK);
Dbprintf("[=] " MODULE_LONG_NAME " -- exiting");
LEDsoff();
}
static int NedapPrepareBigBuffer(const NEDAP_TAG *pTag) {
int ret = 0;
uint8_t data[16], bitStream[sizeof(data) * 8], phase = 0;
uint16_t i, size = pTag->bIsLong ? sizeof(data) : (sizeof(data) / 2);
NedapGen(pTag->subType, pTag->customerCode, pTag->id, pTag->bIsLong, data);
bytes_to_bytebits(data, size, bitStream);
size <<= 3;
for (i = 0; i < size; i++) {
biphaseSimBitInverted(!bitStream[i], &ret, &phase);
}
if (phase == 1) { //run a second set inverted to keep phase in check
for (i = 0; i < size; i++) {
biphaseSimBitInverted(!bitStream[i], &ret, &phase);
}
}
return ret;
}
static void biphaseSimBitInverted(uint8_t c, int *n, uint8_t *phase) {
uint8_t *dest = BigBuf_get_addr();
if (c) {
memset(dest + (*n), c ^ 1 ^ *phase, 32);
memset(dest + (*n) + 32, c ^ *phase, 32);
} else {
memset(dest + (*n), c ^ *phase, 64);
*phase ^= 1;
}
*n += 64;
}
#define FIXED_71 0x71
#define FIXED_40 0x40
#define UNKNOWN_A 0x00
#define UNKNOWN_B 0x00
static const uint8_t translateTable[10] = {8, 2, 1, 12, 4, 5, 10, 13, 0, 9};
static void NedapGen(uint8_t subType, uint16_t customerCode, uint32_t id, bool isLong, uint8_t *data) { // 8 or 16
uint8_t buffer[7];
uint8_t r1 = (uint8_t)(id / 10000);
uint8_t r2 = (uint8_t)((id % 10000) / 1000);
uint8_t r3 = (uint8_t)((id % 1000) / 100);
uint8_t r4 = (uint8_t)((id % 100) / 10);
uint8_t r5 = (uint8_t)(id % 10);
// first part
uint8_t idxC1 = r1;
uint8_t idxC2 = (idxC1 + 1 + r2) % 10;
uint8_t idxC3 = (idxC2 + 1 + r3) % 10;
uint8_t idxC4 = (idxC3 + 1 + r4) % 10;
uint8_t idxC5 = (idxC4 + 1 + r5) % 10;
buffer[0] = 0xc0 | (subType & 0x0F);
buffer[1] = (customerCode & 0x0FF0) >> 4;
buffer[2] = ((customerCode & 0x000F) << 4) | translateTable[idxC1];
buffer[3] = (translateTable[idxC2] << 4) | translateTable[idxC3];
buffer[4] = (translateTable[idxC4] << 4) | translateTable[idxC5];
// checksum
init_table(CRC_XMODEM);
uint16_t checksum = crc16_xmodem(buffer, 5);
buffer[6] = ((checksum & 0x000F) << 4) | (buffer[4] & 0x0F);
buffer[5] = (checksum & 0x00F0) | ((buffer[4] & 0xF0) >> 4);
buffer[4] = ((checksum & 0x0F00) >> 4) | (buffer[3] & 0x0F);
buffer[3] = ((checksum & 0xF000) >> 8) | ((buffer[3] & 0xF0) >> 4);
// carry calc
uint8_t carry = 0;
for (uint8_t i = 0; i < sizeof(buffer); i++) {
uint8_t tmp = buffer[sizeof(buffer) - 1 - i];
data[7 - i] = ((tmp & 0x7F) << 1) | carry;
carry = (tmp & 0x80) >> 7;
}
data[0] = 0xFE | carry;
data[7] |= isEven_64_63(data);
// second part
if (isLong) {
uint8_t id0 = r1;
uint8_t id1 = (r2 << 4) | r3;
uint8_t id2 = (r4 << 4) | r5;
data[8] = (id2 >> 1);
data[9] = ((id2 & 0x01) << 7) | (id1 >> 2);
data[10] = ((id1 & 0x03) << 6) | (id0 >> 3);
data[11] = ((id0 & 0x07) << 5) | (FIXED_71 >> 4);
data[12] = ((FIXED_71 & 0x0F) << 4) | (FIXED_40 >> 5);
data[13] = ((FIXED_40 & 0x1F) << 3) | (UNKNOWN_A >> 6);
data[14] = ((UNKNOWN_A & 0x3F) << 2) | (UNKNOWN_B >> 7);
data[15] = ((UNKNOWN_B & 0x7F) << 1);
data[15] |= isEven_64_63(data + 8);
}
}
static uint8_t isEven_64_63(const uint8_t *data) { // 8
uint32_t tmp[2];
memcpy(tmp, data, 8);
return (bitcount32(tmp[0]) + (bitcount32(tmp[1] & 0xfeffffff))) & 1;
}
static void bytes_to_bytebits(const void *src, const size_t srclen, void *dest) {
uint8_t *s = (uint8_t *)src, *d = (uint8_t *)dest;
size_t i = srclen * 8, j = srclen;
while (j--) {
uint8_t b = s[j];
d[--i] = (b >> 0) & 1;
d[--i] = (b >> 1) & 1;
d[--i] = (b >> 2) & 1;
d[--i] = (b >> 3) & 1;
d[--i] = (b >> 4) & 1;
d[--i] = (b >> 5) & 1;
d[--i] = (b >> 6) & 1;
d[--i] = (b >> 7) & 1;
}
}
static inline uint32_t bitcount32(uint32_t a) {
#if defined __GNUC__
return __builtin_popcountl(a);
#else
a = a - ((a >> 1) & 0x55555555);
a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
return (((a + (a >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24;
#endif
}

View file

@ -0,0 +1,108 @@
//-----------------------------------------------------------------------------
// Copyright (C) Yann Gascuel 2023
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
// LF HID ProxII Brutforce v2 by lnv42 - based on Proxbrute by Brad antoniewicz
//
// Following code is a trivial brute forcer for when you know the facility
// code and want to find valid(s) card number(s). It will try all card
// fnumbers rom CARDNUM_START to CARDNUM_END one by one (max. ~65k tries).
// This brute force will be a lot faster than Proxbrute that will try all
// possibles values for LF low, even those with bad checksum (~4g tries).
// LEDs will help you know which card number(s) worked.
//
//-----------------------------------------------------------------------------
#include "standalone.h" // standalone definitions
#include "proxmark3_arm.h"
#include "appmain.h"
#include "fpgaloader.h"
#include "util.h"
#include "dbprint.h"
#include "lfops.h"
#include "parity.h"
#define CARDNUM_START 0
#define CARDNUM_END 0xFFFF
#define FACILITY_CODE 2
void ModInfo(void) {
DbpString(" LF HID ProxII bruteforce v2");
}
// samy's sniff and repeat routine for LF
void RunMod(void) {
StandAloneMode();
Dbprintf(">> LF HID proxII bruteforce v2 a.k.a Prox2Brute Started <<");
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
const uint32_t high = 0x20; // LF high value is always 0x20 here
uint32_t low = 0;
uint32_t fac = FACILITY_CODE, cardnum = 0;
LED_D_ON();
while (BUTTON_HELD(200) != BUTTON_HOLD) { // Waiting for a 200ms button press
WDT_HIT();
// exit from SamyRun, send a usbcommand.
if (data_available()) { // early exit
DbpString("[=] You can take the shell back :) ...");
LEDsoff();
return;
}
}
LED_C_ON();
WAIT_BUTTON_RELEASED(); // We are now ready to start brutforcing card numbers
LEDsoff();
Dbprintf("[=] Starting HID ProxII Bruteforce from card %08x to %08x",
CARDNUM_START, MIN(CARDNUM_END, 0xFFFF));
for (cardnum = CARDNUM_START ; cardnum <= MIN(CARDNUM_END, 0xFFFF) ; cardnum++) {
WDT_HIT();
// exit from SamyRun, send a usbcommand.
if (data_available()) break;
// short button press may be used for fast-forward
if (BUTTON_HELD(1000) == BUTTON_HOLD) break; // long button press (>=1sec) exit
// calculate the new LF low value including Card number, Facility code and checksum
low = (cardnum << 1) | (fac << 17);
low |= oddparity32((low >> 1) & 0xFFF);
low |= evenparity32((low >> 13) & 0xFFF) << 25;
Dbprintf("[=] trying Facility = %08x, Card = %08x, raw = %08x%08x",
fac, cardnum, high, low);
// Start simulating an HID TAG, with high/low values, no led control and 20000 cycles timeout
CmdHIDsimTAGEx(0, high, low, 0, false, 20000);
// switch leds to be able to know (aproximatly) which card number worked (64 tries loop)
LED_A_INV(); // switch led A every try
if ((cardnum - CARDNUM_START) % 8 == 7) // switch led B every 8 tries
LED_B_INV();
if ((cardnum - CARDNUM_START) % 16 == 15) // switch led C every 16 tries
LED_C_INV();
if ((cardnum - CARDNUM_START) % 32 == 31) // switch led D every 32 tries
LED_D_INV();
}
SpinErr((LED_A | LED_B | LED_C | LED_D), 250, 5); // Xmax tree
Dbprintf("[=] Ending HID ProxII Bruteforce from card %08x to %08x",
CARDNUM_START, cardnum - 1);
DbpString("[=] You can take the shell back :) ...");
LEDsoff(); // This is the end
}

View file

@ -100,6 +100,8 @@ STANDALONE_MODES_REQ_FLASH :=
STANDALONE_MODES_REQ_BT := STANDALONE_MODES_REQ_BT :=
``` ```
Please respect alphabetic order!
## Update MAKEFILE.INC ## Update MAKEFILE.INC
^[Top](#top) ^[Top](#top)
@ -117,6 +119,8 @@ ifneq (,$(findstring WITH_STANDALONE_LF_FOO,$(APP_CFLAGS)))
endif endif
``` ```
Please respect alphabetic order!
## Adding identification string of your mode ## Adding identification string of your mode
^[Top](#top) ^[Top](#top)
@ -174,9 +178,11 @@ Once you're ready to share your mode, please
* add a line in CHANGELOG.md * add a line in CHANGELOG.md
* add your mode in the modes table in `doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md` * add your mode in the modes table in `doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md`
* add your mode in `tools/build_all_firmwares.sh` * add your mode in `tools/build_all_firmwares.sh` such that it reflects `armsrc/Standalone/Makefile.hal` list of firmwares to build.
and submit your PR. Please respect alphabetic order of standalone modes everywhere!
Then submit your PR.
Once approved, add also your mode in https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode Once approved, add also your mode in https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode

View file

@ -60,6 +60,8 @@
#include "ticks.h" #include "ticks.h"
#include "commonutil.h" #include "commonutil.h"
#include "crc16.h" #include "crc16.h"
#include "protocols.h"
#include "mifareutil.h"
#ifdef WITH_LCD #ifdef WITH_LCD
@ -345,7 +347,7 @@ static void print_debug_level(void) {
char dbglvlstr[20] = {0}; char dbglvlstr[20] = {0};
switch (g_dbglevel) { switch (g_dbglevel) {
case DBG_NONE: case DBG_NONE:
sprintf(dbglvlstr, "none"); sprintf(dbglvlstr, "off");
break; break;
case DBG_ERROR: case DBG_ERROR:
sprintf(dbglvlstr, "error"); sprintf(dbglvlstr, "error");
@ -453,6 +455,12 @@ static void SendCapabilities(void) {
capabilities.baudrate = g_usart_baudrate; capabilities.baudrate = g_usart_baudrate;
#endif #endif
#ifdef RDV4
capabilities.is_rdv4 = true;
#else
capabilities.is_rdv4 = false;
#endif
#ifdef WITH_FLASH #ifdef WITH_FLASH
capabilities.compiled_with_flash = true; capabilities.compiled_with_flash = true;
capabilities.hw_available_flash = FlashInit(); capabilities.hw_available_flash = FlashInit();
@ -776,6 +784,15 @@ static void PacketReceived(PacketCommandNG *packet) {
g_reply_via_usb = false; g_reply_via_usb = false;
break; break;
} }
case CMD_SET_FPGAMODE: {
uint8_t mode = packet->data.asBytes[0];
if (mode >= FPGA_BITSTREAM_LF && mode <= FPGA_BITSTREAM_HF_15) {
FpgaDownloadAndGo(mode);
reply_ng(CMD_SET_FPGAMODE, PM3_SUCCESS, NULL, 0);
}
reply_ng(CMD_SET_FPGAMODE, PM3_EINVARG, NULL, 0);
break;
}
// emulator // emulator
case CMD_SET_DBGMODE: { case CMD_SET_DBGMODE: {
g_dbglevel = packet->data.asBytes[0]; g_dbglevel = packet->data.asBytes[0];
@ -1137,27 +1154,27 @@ static void PacketReceived(PacketCommandNG *packet) {
#ifdef WITH_EM4x50 #ifdef WITH_EM4x50
case CMD_LF_EM4X50_INFO: { case CMD_LF_EM4X50_INFO: {
em4x50_info((em4x50_data_t *)packet->data.asBytes, true); em4x50_info((const em4x50_data_t *)packet->data.asBytes, true);
break; break;
} }
case CMD_LF_EM4X50_WRITE: { case CMD_LF_EM4X50_WRITE: {
em4x50_write((em4x50_data_t *)packet->data.asBytes, true); em4x50_write((const em4x50_data_t *)packet->data.asBytes, true);
break; break;
} }
case CMD_LF_EM4X50_WRITEPWD: { case CMD_LF_EM4X50_WRITEPWD: {
em4x50_writepwd((em4x50_data_t *)packet->data.asBytes, true); em4x50_writepwd((const em4x50_data_t *)packet->data.asBytes, true);
break; break;
} }
case CMD_LF_EM4X50_READ: { case CMD_LF_EM4X50_READ: {
em4x50_read((em4x50_data_t *)packet->data.asBytes, true); em4x50_read((const em4x50_data_t *)packet->data.asBytes, true);
break; break;
} }
case CMD_LF_EM4X50_BRUTE: { case CMD_LF_EM4X50_BRUTE: {
em4x50_brute((em4x50_data_t *)packet->data.asBytes, true); em4x50_brute((const em4x50_data_t *)packet->data.asBytes, true);
break; break;
} }
case CMD_LF_EM4X50_LOGIN: { case CMD_LF_EM4X50_LOGIN: {
em4x50_login((uint32_t *)packet->data.asBytes, true); em4x50_login((const uint32_t *)packet->data.asBytes, true);
break; break;
} }
case CMD_LF_EM4X50_SIM: { case CMD_LF_EM4X50_SIM: {
@ -1167,7 +1184,7 @@ static void PacketReceived(PacketCommandNG *packet) {
// destroy the Emulator Memory. // destroy the Emulator Memory.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
em4x50_sim((uint32_t *)packet->data.asBytes, true); em4x50_sim((const uint32_t *)packet->data.asBytes, true);
break; break;
} }
case CMD_LF_EM4X50_READER: { case CMD_LF_EM4X50_READER: {
@ -1191,7 +1208,7 @@ static void PacketReceived(PacketCommandNG *packet) {
// destroy the Emulator Memory. // destroy the Emulator Memory.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
em4x50_chk((uint8_t *)packet->data.asBytes, true); em4x50_chk((const char *)packet->data.asBytes, true);
break; break;
} }
#endif #endif
@ -1221,6 +1238,10 @@ static void PacketReceived(PacketCommandNG *packet) {
em4x70_write_key((em4x70_data_t *)packet->data.asBytes, true); em4x70_write_key((em4x70_data_t *)packet->data.asBytes, true);
break; break;
} }
case CMD_LF_EM4X70_BRUTE: {
em4x70_brute((em4x70_data_t *)packet->data.asBytes, true);
break;
}
#endif #endif
#ifdef WITH_ZX8211 #ifdef WITH_ZX8211
@ -1267,7 +1288,7 @@ static void PacketReceived(PacketCommandNG *packet) {
uint8_t data[]; uint8_t data[];
} PACKED; } PACKED;
struct p *payload = (struct p *) packet->data.asBytes; struct p *payload = (struct p *) packet->data.asBytes;
EmlSetMemIso15693(payload->count, payload->data, payload->offset); emlSet(payload->data, payload->offset, payload->count);
break; break;
} }
case CMD_HF_ISO15693_SIMULATE: { case CMD_HF_ISO15693_SIMULATE: {
@ -1287,20 +1308,76 @@ static void PacketReceived(PacketCommandNG *packet) {
SetTag15693Uid(payload->uid); SetTag15693Uid(payload->uid);
break; break;
} }
case CMD_HF_ISO15693_SLIX_L_DISABLE_PRIVACY: { case CMD_HF_ISO15693_SLIX_DISABLE_EAS: {
struct p { struct p {
uint8_t pwd[4]; uint8_t pwd[4];
bool usepwd;
} PACKED; } PACKED;
struct p *payload = (struct p *) packet->data.asBytes; struct p *payload = (struct p *) packet->data.asBytes;
DisablePrivacySlixLIso15693(payload->pwd); DisableEAS_AFISlixIso15693(payload->pwd, payload->usepwd);
break; break;
} }
case CMD_HF_ISO15693_SLIX_L_DISABLE_AESAFI: { case CMD_HF_ISO15693_SLIX_ENABLE_EAS: {
struct p {
uint8_t pwd[4];
bool usepwd;
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
EnableEAS_AFISlixIso15693(payload->pwd, payload->usepwd);
break;
}
case CMD_HF_ISO15693_SLIX_WRITE_PWD: {
struct p {
uint8_t old_pwd[4];
uint8_t new_pwd[4];
uint8_t pwd_id;
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
WritePasswordSlixIso15693(payload->old_pwd, payload->new_pwd, payload->pwd_id);
break;
}
case CMD_HF_ISO15693_SLIX_DISABLE_PRIVACY: {
struct p { struct p {
uint8_t pwd[4]; uint8_t pwd[4];
} PACKED; } PACKED;
struct p *payload = (struct p *) packet->data.asBytes; struct p *payload = (struct p *) packet->data.asBytes;
DisableEAS_AFISlixLIso15693(payload->pwd); DisablePrivacySlixIso15693(payload->pwd);
break;
}
case CMD_HF_ISO15693_SLIX_ENABLE_PRIVACY: {
struct p {
uint8_t pwd[4];
} PACKED;
struct p *payload = (struct p *)packet->data.asBytes;
EnablePrivacySlixIso15693(payload->pwd);
break;
}
case CMD_HF_ISO15693_SLIX_PASS_PROTECT_AFI: {
struct p {
uint8_t pwd[4];
} PACKED;
struct p *payload = (struct p *)packet->data.asBytes;
PassProtectAFISlixIso15693(payload->pwd);
break;
}
case CMD_HF_ISO15693_WRITE_AFI: {
struct p {
uint8_t pwd[4];
bool use_pwd;
uint8_t uid[8];
bool use_uid;
uint8_t afi;
} PACKED;
struct p *payload = (struct p *)packet->data.asBytes;
WriteAFIIso15693(payload->pwd, payload->use_pwd, payload->uid, payload->use_uid, payload->afi);
break;
}
case CMD_HF_ISO15693_SLIX_PASS_PROTECT_EAS: {
struct p {
uint8_t pwd[4];
} PACKED;
struct p *payload = (struct p *)packet->data.asBytes;
PassProtextEASSlixIso15693(payload->pwd);
break; break;
} }
@ -1490,7 +1567,9 @@ static void PacketReceived(PacketCommandNG *packet) {
} }
case CMD_HF_MIFARE_READBL: { case CMD_HF_MIFARE_READBL: {
mf_readblock_t *payload = (mf_readblock_t *)packet->data.asBytes; mf_readblock_t *payload = (mf_readblock_t *)packet->data.asBytes;
MifareReadBlock(payload->blockno, payload->keytype, payload->key); uint8_t outbuf[16];
int16_t retval = mifare_cmd_readblocks(MIFARE_AUTH_KEYA + (payload->keytype & 1), payload->key, ISO14443A_CMD_READBLOCK, payload->blockno, 1, outbuf);
reply_ng(CMD_HF_MIFARE_READBL, retval, outbuf, sizeof(outbuf));
break; break;
} }
case CMD_HF_MIFAREU_READBL: { case CMD_HF_MIFAREU_READBL: {
@ -1514,11 +1593,23 @@ static void PacketReceived(PacketCommandNG *packet) {
break; break;
} }
case CMD_HF_MIFARE_WRITEBL: { case CMD_HF_MIFARE_WRITEBL: {
MifareWriteBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); uint8_t block_no = packet->oldarg[0];
uint8_t key_type = packet->oldarg[1];
uint8_t *key = packet->data.asBytes;
uint8_t *block_data = packet->data.asBytes + 10;
int16_t retval = mifare_cmd_writeblocks(MIFARE_AUTH_KEYA + (key_type & 1), key, ISO14443A_CMD_WRITEBLOCK, block_no, 1, block_data);
// convert ng style retval to old status
if (retval >= 0) {
retval = 1;
}
reply_mix(CMD_ACK, retval, 0, 0, 0, 0);
break; break;
} }
case CMD_HF_MIFARE_VALUE: { case CMD_HF_MIFARE_VALUE: {
MifareValue(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); MifareValue(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
break; break;
} }
case CMD_HF_MIFAREU_WRITEBL: { case CMD_HF_MIFAREU_WRITEBL: {
@ -1603,7 +1694,14 @@ static void PacketReceived(PacketCommandNG *packet) {
uint8_t data[]; uint8_t data[];
} PACKED; } PACKED;
struct p *payload = (struct p *) packet->data.asBytes; struct p *payload = (struct p *) packet->data.asBytes;
MifareEMemSet(payload->blockno, payload->blockcnt, payload->blockwidth, payload->data);
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// backwards compat... default bytewidth
if (payload->blockwidth == 0)
payload->blockwidth = 16;
emlSetMem_xt(payload->data, payload->blockno, payload->blockcnt, payload->blockwidth);
break; break;
} }
case CMD_HF_MIFARE_EML_MEMGET: { case CMD_HF_MIFARE_EML_MEMGET: {
@ -1620,7 +1718,7 @@ static void PacketReceived(PacketCommandNG *packet) {
MifareECardLoadExt(payload->sectorcnt, payload->keytype); MifareECardLoadExt(payload->sectorcnt, payload->keytype);
break; break;
} }
// Work with "magic Chinese" card // Gen1a / 1b - "magic Chinese" card
case CMD_HF_MIFARE_CSETBL: { case CMD_HF_MIFARE_CSETBL: {
MifareCSetBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); MifareCSetBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
break; break;
@ -1647,6 +1745,7 @@ static void PacketReceived(PacketCommandNG *packet) {
MifareGen3Freez(); MifareGen3Freez();
break; break;
} }
// Gen 4 GTU magic cards
case CMD_HF_MIFARE_G4_RDBL: { case CMD_HF_MIFARE_G4_RDBL: {
struct p { struct p {
uint8_t blockno; uint8_t blockno;
@ -1657,7 +1756,6 @@ static void PacketReceived(PacketCommandNG *packet) {
MifareG4ReadBlk(payload->blockno, payload->pwd, payload->workFlags); MifareG4ReadBlk(payload->blockno, payload->pwd, payload->workFlags);
break; break;
} }
// Gen 4 GTU magic cards
case CMD_HF_MIFARE_G4_WRBL: { case CMD_HF_MIFARE_G4_WRBL: {
struct p { struct p {
uint8_t blockno; uint8_t blockno;
@ -1669,6 +1767,37 @@ static void PacketReceived(PacketCommandNG *packet) {
MifareG4WriteBlk(payload->blockno, payload->pwd, payload->data, payload->workFlags); MifareG4WriteBlk(payload->blockno, payload->pwd, payload->data, payload->workFlags);
break; break;
} }
case CMD_HF_MIFARE_G4_GDM_CONFIG: {
struct p {
uint8_t key[6];
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
uint8_t outbuf[16];
int16_t retval = mifare_cmd_readblocks(MIFARE_MAGIC_GDM_AUTH_KEY, payload->key, MIFARE_MAGIC_GDM_READ_CFG, 0, 1, outbuf);
reply_ng(CMD_HF_MIFARE_G4_GDM_CONFIG, retval, outbuf, sizeof(outbuf));
break;
}
case CMD_HF_MIFARE_G4_GDM_WRCFG: {
struct p {
uint8_t data[16];
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
int16_t retval = mifare_cmd_writeblocks(MIFARE_MAGIC_GDM_AUTH_KEY, key, MIFARE_MAGIC_GDM_WRITE_CFG, 0, 1, payload->data);
reply_ng(CMD_HF_MIFARE_G4_GDM_WRCFG, retval, NULL, 0);
break;
}
case CMD_HF_MIFARE_G4_GDM_WRBL: {
struct p {
uint8_t blockno;
uint8_t key[6];
uint8_t data[16]; // data to be written
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
int16_t retval = mifare_cmd_writeblocks(MIFARE_MAGIC_GDM_AUTH_KEY, payload->key, MIFARE_MAGIC_GDM_WRITEBLOCK, payload->blockno, 1, payload->data);
reply_ng(CMD_HF_MIFARE_G4_GDM_WRBL, retval, NULL, 0);
break;
}
case CMD_HF_MIFARE_PERSONALIZE_UID: { case CMD_HF_MIFARE_PERSONALIZE_UID: {
struct p { struct p {
uint8_t keytype; uint8_t keytype;
@ -1921,11 +2050,16 @@ static void PacketReceived(PacketCommandNG *packet) {
uint32_t waittime; uint32_t waittime;
} PACKED; } PACKED;
struct p *payload = (struct p *) &packet->data.asBytes; struct p *payload = (struct p *) &packet->data.asBytes;
uint16_t available; uint16_t available;
uint16_t pre_available = 0; uint16_t pre_available = 0;
uint8_t *dest = BigBuf_malloc(USART_FIFOLEN); uint8_t *dest = BigBuf_malloc(USART_FIFOLEN);
uint32_t wait = payload->waittime; uint32_t wait = payload->waittime;
StartTicks();
uint32_t ti = GetTickCount(); uint32_t ti = GetTickCount();
while (true) { while (true) {
WaitMS(50); WaitMS(50);
available = usart_rxdata_available(); available = usart_rxdata_available();
@ -1946,6 +2080,8 @@ static void PacketReceived(PacketCommandNG *packet) {
} else { } else {
reply_ng(CMD_USART_RX, PM3_ENODATA, NULL, 0); reply_ng(CMD_USART_RX, PM3_ENODATA, NULL, 0);
} }
StopTicks();
BigBuf_free(); BigBuf_free();
LED_B_OFF(); LED_B_OFF();
break; break;
@ -1958,11 +2094,16 @@ static void PacketReceived(PacketCommandNG *packet) {
} PACKED; } PACKED;
struct p *payload = (struct p *) &packet->data.asBytes; struct p *payload = (struct p *) &packet->data.asBytes;
usart_writebuffer_sync(payload->data, packet->length - sizeof(payload)); usart_writebuffer_sync(payload->data, packet->length - sizeof(payload));
uint16_t available; uint16_t available;
uint16_t pre_available = 0; uint16_t pre_available = 0;
uint8_t *dest = BigBuf_malloc(USART_FIFOLEN); uint8_t *dest = BigBuf_malloc(USART_FIFOLEN);
uint32_t wait = payload->waittime; uint32_t wait = payload->waittime;
StartTicks();
uint32_t ti = GetTickCount(); uint32_t ti = GetTickCount();
while (true) { while (true) {
WaitMS(50); WaitMS(50);
available = usart_rxdata_available(); available = usart_rxdata_available();
@ -1977,12 +2118,15 @@ static void PacketReceived(PacketCommandNG *packet) {
if (GetTickCountDelta(ti) > wait) if (GetTickCountDelta(ti) > wait)
break; break;
} }
if (available > 0) { if (available > 0) {
uint16_t len = usart_read_ng(dest, available); uint16_t len = usart_read_ng(dest, available);
reply_ng(CMD_USART_TXRX, PM3_SUCCESS, dest, len); reply_ng(CMD_USART_TXRX, PM3_SUCCESS, dest, len);
} else { } else {
reply_ng(CMD_USART_TXRX, PM3_ENODATA, NULL, 0); reply_ng(CMD_USART_TXRX, PM3_ENODATA, NULL, 0);
} }
StopTicks();
BigBuf_free(); BigBuf_free();
LED_B_OFF(); LED_B_OFF();
break; break;
@ -2372,6 +2516,9 @@ static void PacketReceived(PacketCommandNG *packet) {
Flash_WriteEnable(); Flash_WriteEnable();
Flash_Erase4k(3, 0xC); Flash_Erase4k(3, 0xC);
} else if (payload->startidx == DEFAULT_MF_KEYS_OFFSET) { } else if (payload->startidx == DEFAULT_MF_KEYS_OFFSET) {
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase4k(3, 0x8);
Flash_CheckBusy(BUSY_TIMEOUT); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_WriteEnable();
Flash_Erase4k(3, 0x9); Flash_Erase4k(3, 0x9);
@ -2405,8 +2552,11 @@ static void PacketReceived(PacketCommandNG *packet) {
LED_B_OFF(); LED_B_OFF();
break; break;
} }
if (page < 3) if (page < 3) {
isok = Flash_WipeMemoryPage(page); isok = Flash_WipeMemoryPage(page);
// let spiffs check and update its info post flash erase
rdv40_spiffs_check();
}
reply_mix(CMD_ACK, isok, 0, 0, 0, 0); reply_mix(CMD_ACK, isok, 0, 0, 0, 0);
LED_B_OFF(); LED_B_OFF();
@ -2573,6 +2723,7 @@ void __attribute__((noreturn)) AppMain(void) {
SpinDelay(100); SpinDelay(100);
BigBuf_initialize(); BigBuf_initialize();
// Add stack canary
for (uint32_t *p = _stack_start; p + 0x200 < _stack_end ; ++p) { for (uint32_t *p = _stack_start; p + 0x200 < _stack_end ; ++p) {
*p = 0xdeadbeef; *p = 0xdeadbeef;
} }
@ -2608,18 +2759,20 @@ void __attribute__((noreturn)) AppMain(void) {
#endif #endif
#ifdef WITH_SMARTCARD #ifdef WITH_SMARTCARD
I2C_init(); I2C_init(false);
#endif #endif
#ifdef WITH_FPC_USART #ifdef WITH_FLASH
usart_init(USART_BAUD_RATE, USART_PARITY); if (FlashInit()) {
uint64_t flash_uniqueID = 0;
if (!Flash_CheckBusy(BUSY_TIMEOUT)) { // OK because firmware was built for devices with flash
Flash_UniqueID((uint8_t *)(&flash_uniqueID));
}
FlashStop();
usb_update_serial(flash_uniqueID);
}
#endif #endif
// This is made as late as possible to ensure enumeration without timeout
// against device such as http://www.hobbytronics.co.uk/usb-host-board-v2
usb_disable();
usb_enable();
allow_send_wtx = true;
#ifdef WITH_FLASH #ifdef WITH_FLASH
// If flash is not present, BUSY_TIMEOUT kicks in, let's do it after USB // If flash is not present, BUSY_TIMEOUT kicks in, let's do it after USB
@ -2628,9 +2781,22 @@ void __attribute__((noreturn)) AppMain(void) {
// //
// Enforce a spiffs check/garbage collection at boot so we are likely to never // Enforce a spiffs check/garbage collection at boot so we are likely to never
// fall under the 2 contigous free blocks availables // fall under the 2 contigous free blocks availables
// This is a time-consuming process on large flash.
rdv40_spiffs_check(); rdv40_spiffs_check();
#endif #endif
#ifdef WITH_FPC_USART
usart_init(USART_BAUD_RATE, USART_PARITY);
#endif
// This is made as late as possible to ensure enumeration without timeout
// against device such as http://www.hobbytronics.co.uk/usb-host-board-v2
// In other words, keep the interval between usb_enable() and the main loop as short as possible.
// (AT91F_CDC_Enumerate() will be called in the main loop)
usb_disable();
usb_enable();
allow_send_wtx = true;
for (;;) { for (;;) {
WDT_HIT(); WDT_HIT();

View file

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

View file

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

View file

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

View file

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

View file

@ -755,7 +755,7 @@ void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect,
memcpy(ovect, data, block_size); memcpy(ovect, data, block_size);
} }
uint8_t edata[DESFIRE_MAX_CRYPTO_BLOCK_SIZE]; uint8_t edata[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0};
switch (key->type) { switch (key->type) {
case T_DES: case T_DES:

View file

@ -27,6 +27,7 @@
#include "BigBuf.h" #include "BigBuf.h"
#include "spiffs.h" #include "spiffs.h"
#include "appmain.h" // tear #include "appmain.h" // tear
#include "bruteforce.h"
// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) // Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz // TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
@ -632,12 +633,21 @@ static int login(uint32_t password) {
return PM3_EFAILED; return PM3_EFAILED;
} }
// searching for password in given range // searching for password using chosen bruteforce algorithm
static bool brute(uint32_t start, uint32_t stop, uint32_t *pwd) { static bool brute(const em4x50_data_t *etd, uint32_t *pwd) {
generator_context_t ctx;
bool pwd_found = false; bool pwd_found = false;
int generator_ret = 0;
int cnt = 0; int cnt = 0;
for (*pwd = start; *pwd <= stop; (*pwd)++) { bf_generator_init(&ctx, etd->bruteforce_mode);
if (etd->bruteforce_mode == BRUTEFORCE_MODE_CHARSET)
bf_generator_set_charset(&ctx, etd->bruteforce_charset);
while ((generator_ret = bf_generate32(&ctx)) == GENERATOR_NEXT) {
*pwd = ctx.current_key32;
WDT_HIT(); WDT_HIT();
@ -684,7 +694,7 @@ static bool brute(uint32_t start, uint32_t stop, uint32_t *pwd) {
} }
// login into EM4x50 // login into EM4x50
void em4x50_login(uint32_t *password, bool ledcontrol) { void em4x50_login(const uint32_t *password, bool ledcontrol) {
em4x50_setup_read(); em4x50_setup_read();
int status = PM3_EFAILED; int status = PM3_EFAILED;
@ -702,8 +712,8 @@ void em4x50_login(uint32_t *password, bool ledcontrol) {
reply_ng(CMD_LF_EM4X50_LOGIN, status, NULL, 0); reply_ng(CMD_LF_EM4X50_LOGIN, status, NULL, 0);
} }
// envoke password search // invoke password search
void em4x50_brute(em4x50_data_t *etd, bool ledcontrol) { void em4x50_brute(const em4x50_data_t *etd, bool ledcontrol) {
em4x50_setup_read(); em4x50_setup_read();
bool bsuccess = false; bool bsuccess = false;
@ -714,7 +724,7 @@ void em4x50_brute(em4x50_data_t *etd, bool ledcontrol) {
LED_C_OFF(); LED_C_OFF();
LED_D_ON(); LED_D_ON();
} }
bsuccess = brute(etd->password1, etd->password2, &pwd); bsuccess = brute(etd, &pwd);
} }
if (ledcontrol) LEDsoff(); if (ledcontrol) LEDsoff();
@ -723,7 +733,7 @@ void em4x50_brute(em4x50_data_t *etd, bool ledcontrol) {
} }
// check passwords from dictionary content in flash memory // check passwords from dictionary content in flash memory
void em4x50_chk(uint8_t *filename, bool ledcontrol) { void em4x50_chk(const char *filename, bool ledcontrol) {
int status = PM3_EFAILED; int status = PM3_EFAILED;
uint32_t pwd = 0x0; uint32_t pwd = 0x0;
@ -733,11 +743,11 @@ void em4x50_chk(uint8_t *filename, bool ledcontrol) {
int changed = rdv40_spiffs_lazy_mount(); int changed = rdv40_spiffs_lazy_mount();
uint16_t pwd_count = 0; uint16_t pwd_count = 0;
uint32_t size = size_in_spiffs((char *)filename); uint32_t size = size_in_spiffs(filename);
pwd_count = size / 4; pwd_count = size / 4;
uint8_t *pwds = BigBuf_malloc(size); uint8_t *pwds = BigBuf_malloc(size);
rdv40_spiffs_read_as_filetype((char *)filename, pwds, size, RDV40_SPIFFS_SAFETY_SAFE); rdv40_spiffs_read_as_filetype(filename, pwds, size, RDV40_SPIFFS_SAFETY_SAFE);
if (changed) if (changed)
rdv40_spiffs_lazy_unmount(); rdv40_spiffs_lazy_unmount();
@ -863,7 +873,7 @@ static int selective_read(uint32_t addresses, uint32_t *words) {
} }
// reads by using "selective read mode" -> bidirectional communication // reads by using "selective read mode" -> bidirectional communication
void em4x50_read(em4x50_data_t *etd, bool ledcontrol) { void em4x50_read(const em4x50_data_t *etd, bool ledcontrol) {
int status = PM3_EFAILED; int status = PM3_EFAILED;
uint32_t words[EM4X50_NO_WORDS] = {0x0}; uint32_t words[EM4X50_NO_WORDS] = {0x0};
@ -896,7 +906,7 @@ void em4x50_read(em4x50_data_t *etd, bool ledcontrol) {
} }
// collects as much information as possible via selective read mode // collects as much information as possible via selective read mode
void em4x50_info(em4x50_data_t *etd, bool ledcontrol) { void em4x50_info(const em4x50_data_t *etd, bool ledcontrol) {
int status = PM3_EFAILED; int status = PM3_EFAILED;
uint32_t words[EM4X50_NO_WORDS] = {0x0}; uint32_t words[EM4X50_NO_WORDS] = {0x0};
@ -1043,7 +1053,7 @@ static int write_password(uint32_t password, uint32_t new_password) {
// write operation process for EM4x50 tag, // write operation process for EM4x50 tag,
// single word is written to given address, verified by selective read operation // single word is written to given address, verified by selective read operation
// wrong password -> return with PM3_EFAILED // wrong password -> return with PM3_EFAILED
void em4x50_write(em4x50_data_t *etd, bool ledcontrol) { void em4x50_write(const em4x50_data_t *etd, bool ledcontrol) {
int status = PM3_EFAILED; int status = PM3_EFAILED;
uint32_t words[EM4X50_NO_WORDS] = {0x0}; uint32_t words[EM4X50_NO_WORDS] = {0x0};
@ -1103,7 +1113,7 @@ void em4x50_write(em4x50_data_t *etd, bool ledcontrol) {
} }
// simple change of password // simple change of password
void em4x50_writepwd(em4x50_data_t *etd, bool ledcontrol) { void em4x50_writepwd(const em4x50_data_t *etd, bool ledcontrol) {
int status = PM3_EFAILED; int status = PM3_EFAILED;
em4x50_setup_read(); em4x50_setup_read();
@ -1348,7 +1358,7 @@ static bool em4x50_sim_read_word(uint32_t *word) {
} }
// check if reader requests receive mode (rm) by sending two zeros // check if reader requests receive mode (rm) by sending two zeros
static int check_rm_request(uint32_t *tag, bool ledcontrol) { static int check_rm_request(const uint32_t *tag, bool ledcontrol) {
// look for first zero // look for first zero
int bit = em4x50_sim_read_bit(); int bit = em4x50_sim_read_bit();
@ -1377,7 +1387,7 @@ static int check_rm_request(uint32_t *tag, bool ledcontrol) {
} }
// send single listen window in simulation mode // send single listen window in simulation mode
static int em4x50_sim_send_listen_window(uint32_t *tag, bool ledcontrol) { static int em4x50_sim_send_listen_window(const uint32_t *tag, bool ledcontrol) {
SHORT_COIL(); SHORT_COIL();
wait_cycles(EM4X50_T_TAG_HALF_PERIOD); wait_cycles(EM4X50_T_TAG_HALF_PERIOD);
@ -1450,7 +1460,7 @@ static void em4x50_sim_send_nak(void) {
} }
// standard read mode process (simulation mode) // standard read mode process (simulation mode)
static int em4x50_sim_handle_standard_read_command(uint32_t *tag, bool ledcontrol) { static int em4x50_sim_handle_standard_read_command(const uint32_t *tag, bool ledcontrol) {
// extract control data // extract control data
int fwr = reflect32(tag[EM4X50_CONTROL]) & 0xFF; // first word read int fwr = reflect32(tag[EM4X50_CONTROL]) & 0xFF; // first word read
@ -1490,7 +1500,7 @@ static int em4x50_sim_handle_standard_read_command(uint32_t *tag, bool ledcontro
} }
// selective read mode process (simulation mode) // selective read mode process (simulation mode)
static int em4x50_sim_handle_selective_read_command(uint32_t *tag, bool ledcontrol) { static int em4x50_sim_handle_selective_read_command(const uint32_t *tag, bool ledcontrol) {
// read password // read password
uint32_t address = 0; uint32_t address = 0;
@ -1545,7 +1555,7 @@ static int em4x50_sim_handle_selective_read_command(uint32_t *tag, bool ledcontr
} }
// login process (simulation mode) // login process (simulation mode)
static int em4x50_sim_handle_login_command(uint32_t *tag, bool ledcontrol) { static int em4x50_sim_handle_login_command(const uint32_t *tag, bool ledcontrol) {
// read password // read password
uint32_t password = 0; uint32_t password = 0;
@ -1571,7 +1581,7 @@ static int em4x50_sim_handle_login_command(uint32_t *tag, bool ledcontrol) {
} }
// reset process (simulation mode) // reset process (simulation mode)
static int em4x50_sim_handle_reset_command(uint32_t *tag, bool ledcontrol) { static int em4x50_sim_handle_reset_command(const uint32_t *tag, bool ledcontrol) {
// processing pause time (corresponds to a "1" bit) // processing pause time (corresponds to a "1" bit)
em4x50_sim_send_bit(1); em4x50_sim_send_bit(1);
@ -1796,7 +1806,7 @@ void em4x50_handle_commands(int *command, uint32_t *tag, bool ledcontrol) {
// simulate uploaded data in emulator memory // simulate uploaded data in emulator memory
// LED C -> reader command has been detected // LED C -> reader command has been detected
// LED D -> operations that require authentication are possible // LED D -> operations that require authentication are possible
void em4x50_sim(uint32_t *password, bool ledcontrol) { void em4x50_sim(const uint32_t *password, bool ledcontrol) {
int command = PM3_ENODATA; int command = PM3_ENODATA;

View file

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

View file

@ -21,6 +21,7 @@
#include "dbprint.h" #include "dbprint.h"
#include "lfadc.h" #include "lfadc.h"
#include "commonutil.h" #include "commonutil.h"
#include "optimized_cipherutils.h"
#include "em4x70.h" #include "em4x70.h"
#include "appmain.h" // tear #include "appmain.h" // tear
@ -85,7 +86,7 @@ static int em4x70_receive(uint8_t *bits, size_t length);
static bool find_listen_window(bool command); static bool find_listen_window(bool command);
static void init_tag(void) { static void init_tag(void) {
memset(tag.data, 0x00, ARRAYLEN(tag.data)); memset(tag.data, 0x00, sizeof(tag.data));
} }
static void em4x70_setup_read(void) { static void em4x70_setup_read(void) {
@ -298,17 +299,18 @@ static bool check_ack(void) {
// returns true if signal structue corresponds to ACK, anything else is // returns true if signal structue corresponds to ACK, anything else is
// counted as NAK (-> false) // counted as NAK (-> false)
// ACK 64 + 64 // ACK 64 + 64
// NACK 64 + 48 // NAK 64 + 48
if (check_pulse_length(get_pulse_length(FALLING_EDGE), 2 * EM4X70_T_TAG_FULL_PERIOD) && if (check_pulse_length(get_pulse_length(FALLING_EDGE), 2 * EM4X70_T_TAG_FULL_PERIOD) &&
check_pulse_length(get_pulse_length(FALLING_EDGE), 2 * EM4X70_T_TAG_FULL_PERIOD)) { check_pulse_length(get_pulse_length(FALLING_EDGE), 2 * EM4X70_T_TAG_FULL_PERIOD)) {
// ACK // ACK
return true; return true;
} }
// Othewise it was a NACK or Listen Window // Otherwise it was a NAK or Listen Window
return false; return false;
} }
// TODO: define and use structs for rnd, frnd, response
static int authenticate(const uint8_t *rnd, const uint8_t *frnd, uint8_t *response) { static int authenticate(const uint8_t *rnd, const uint8_t *frnd, uint8_t *response) {
if (find_listen_window(true)) { if (find_listen_window(true)) {
@ -339,7 +341,7 @@ static int authenticate(const uint8_t *rnd, const uint8_t *frnd, uint8_t *respon
uint8_t grnd[EM4X70_MAX_RECEIVE_LENGTH] = {0}; uint8_t grnd[EM4X70_MAX_RECEIVE_LENGTH] = {0};
int num = em4x70_receive(grnd, 20); int num = em4x70_receive(grnd, 20);
if (num < 20) { if (num < 20) {
Dbprintf("Auth failed"); if (g_dbglevel >= DBG_EXTENDED) Dbprintf("Auth failed");
return PM3_ESOFT; return PM3_ESOFT;
} }
bits2bytes(grnd, 24, response); bits2bytes(grnd, 24, response);
@ -349,6 +351,82 @@ static int authenticate(const uint8_t *rnd, const uint8_t *frnd, uint8_t *respon
return PM3_ESOFT; return PM3_ESOFT;
} }
// 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;
}
static int bruteforce(const uint8_t address, const uint8_t *rnd, const uint8_t *frnd, uint16_t start_key, uint8_t *response) {
uint8_t auth_resp[3] = {0};
uint8_t rev_rnd[7];
uint8_t temp_rnd[7];
reverse_arraycopy((uint8_t *)rnd, rev_rnd, sizeof(rev_rnd));
memcpy(temp_rnd, rnd, sizeof(temp_rnd));
for (int k = start_key; k <= 0xFFFF; ++k) {
int c = 0;
WDT_HIT();
uint16_t rev_k = reflect16(k);
switch (address) {
case 9:
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);
c = set_byte(&temp_rnd[5], rev_rnd[5] + c);
set_byte(&temp_rnd[6], rev_rnd[6] + c);
break;
case 8:
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) & 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;
default:
Dbprintf("Bad block number given: %d", address);
return PM3_ESOFT;
}
// Report progress every 256 attempts
if ((k % 0x100) == 0) {
Dbprintf("Trying: %04X", k);
}
// Due to performance reason, we only try it once. Therefore you need a very stable RFID communcation.
if (authenticate(temp_rnd, frnd, auth_resp) == PM3_SUCCESS) {
if (g_dbglevel >= DBG_INFO)
Dbprintf("Authentication success with rnd: %02X%02X%02X%02X%02X%02X%02X", temp_rnd[0], temp_rnd[1], temp_rnd[2], temp_rnd[3], temp_rnd[4], temp_rnd[5], temp_rnd[6]);
response[0] = (k >> 8) & 0xFF;
response[1] = k & 0xFF;
return PM3_SUCCESS;
}
if (BUTTON_PRESS() || data_available()) {
Dbprintf("EM4x70 Bruteforce Interrupted");
return PM3_EOPABORTED;
}
}
return PM3_ESOFT;
}
static int send_pin(const uint32_t pin) { static int send_pin(const uint32_t pin) {
// sends pin code for unlocking // sends pin code for unlocking
@ -576,7 +654,7 @@ static int em4x70_receive(uint8_t *bits, size_t length) {
} }
if (!foundheader) { if (!foundheader) {
Dbprintf("Failed to find read header"); if (g_dbglevel >= DBG_EXTENDED) Dbprintf("Failed to find read header");
return 0; return 0;
} }
@ -632,7 +710,7 @@ static int em4x70_receive(uint8_t *bits, size_t length) {
return bit_pos; return bit_pos;
} }
void em4x70_info(em4x70_data_t *etd, bool ledcontrol) { void em4x70_info(const em4x70_data_t *etd, bool ledcontrol) {
uint8_t status = 0; uint8_t status = 0;
@ -653,7 +731,7 @@ void em4x70_info(em4x70_data_t *etd, bool ledcontrol) {
reply_ng(CMD_LF_EM4X70_INFO, status, tag.data, sizeof(tag.data)); reply_ng(CMD_LF_EM4X70_INFO, status, tag.data, sizeof(tag.data));
} }
void em4x70_write(em4x70_data_t *etd, bool ledcontrol) { void em4x70_write(const em4x70_data_t *etd, bool ledcontrol) {
uint8_t status = 0; uint8_t status = 0;
@ -683,7 +761,7 @@ void em4x70_write(em4x70_data_t *etd, bool ledcontrol) {
reply_ng(CMD_LF_EM4X70_WRITE, status, tag.data, sizeof(tag.data)); reply_ng(CMD_LF_EM4X70_WRITE, status, tag.data, sizeof(tag.data));
} }
void em4x70_unlock(em4x70_data_t *etd, bool ledcontrol) { void em4x70_unlock(const em4x70_data_t *etd, bool ledcontrol) {
uint8_t status = 0; uint8_t status = 0;
@ -716,7 +794,7 @@ void em4x70_unlock(em4x70_data_t *etd, bool ledcontrol) {
reply_ng(CMD_LF_EM4X70_UNLOCK, status, tag.data, sizeof(tag.data)); reply_ng(CMD_LF_EM4X70_UNLOCK, status, tag.data, sizeof(tag.data));
} }
void em4x70_auth(em4x70_data_t *etd, bool ledcontrol) { void em4x70_auth(const em4x70_data_t *etd, bool ledcontrol) {
uint8_t status = 0; uint8_t status = 0;
uint8_t response[3] = {0}; uint8_t response[3] = {0};
@ -738,7 +816,28 @@ void em4x70_auth(em4x70_data_t *etd, bool ledcontrol) {
reply_ng(CMD_LF_EM4X70_AUTH, status, response, sizeof(response)); reply_ng(CMD_LF_EM4X70_AUTH, status, response, sizeof(response));
} }
void em4x70_write_pin(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};
command_parity = etd->parity;
init_tag();
em4x70_setup_read();
// Find the Tag
if (get_signalproperties() && find_em4x70_tag()) {
// Bruteforce partial key
status = bruteforce(etd->address, etd->rnd, etd->frnd, etd->start_key, response) == PM3_SUCCESS;
}
StopTicks();
lf_finalize(ledcontrol);
reply_ng(CMD_LF_EM4X70_BRUTE, status, response, sizeof(response));
}
void em4x70_write_pin(const em4x70_data_t *etd, bool ledcontrol) {
uint8_t status = 0; uint8_t status = 0;
@ -754,7 +853,7 @@ void em4x70_write_pin(em4x70_data_t *etd, bool ledcontrol) {
if (em4x70_read_id()) { if (em4x70_read_id()) {
// Write new PIN // Write new PIN
if ((write(etd->pin & 0xFFFF, EM4X70_PIN_WORD_UPPER) == PM3_SUCCESS) && if ((write((etd->pin) & 0xFFFF, EM4X70_PIN_WORD_UPPER) == PM3_SUCCESS) &&
(write((etd->pin >> 16) & 0xFFFF, EM4X70_PIN_WORD_LOWER) == PM3_SUCCESS)) { (write((etd->pin >> 16) & 0xFFFF, EM4X70_PIN_WORD_LOWER) == PM3_SUCCESS)) {
// Now Try to authenticate using the new PIN // Now Try to authenticate using the new PIN
@ -778,7 +877,7 @@ void em4x70_write_pin(em4x70_data_t *etd, bool ledcontrol) {
reply_ng(CMD_LF_EM4X70_WRITEPIN, status, tag.data, sizeof(tag.data)); reply_ng(CMD_LF_EM4X70_WRITEPIN, status, tag.data, sizeof(tag.data));
} }
void em4x70_write_key(em4x70_data_t *etd, bool ledcontrol) { void em4x70_write_key(const em4x70_data_t *etd, bool ledcontrol) {
uint8_t status = 0; uint8_t status = 0;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -162,8 +162,7 @@ void FpgaSetupSsc(uint16_t fpga_mode) {
// 8, 16 or 32 bits per transfer, no loopback, MSB first, 1 transfer per sync // 8, 16 or 32 bits per transfer, no loopback, MSB first, 1 transfer per sync
// pulse, no output sync // pulse, no output sync
if (((fpga_mode & FPGA_MAJOR_MODE_MASK) == FPGA_MAJOR_MODE_HF_READER || if (((fpga_mode & FPGA_MAJOR_MODE_MASK) == FPGA_MAJOR_MODE_HF_READER) &&
(fpga_mode & FPGA_MAJOR_MODE_MASK) == FPGA_MAJOR_MODE_HF_FSK_READER) &&
(FpgaGetCurrent() == FPGA_BITSTREAM_HF || FpgaGetCurrent() == FPGA_BITSTREAM_HF_15)) { (FpgaGetCurrent() == FPGA_BITSTREAM_HF || FpgaGetCurrent() == FPGA_BITSTREAM_HF_15)) {
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
} else { } else {
@ -393,7 +392,7 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3
while (numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) { while (numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) {
char current_name = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); char current_name = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
numbytes++; numbytes++;
uint16_t current_length = 0; uint32_t current_length = 0;
if (current_name < 'a' || current_name > 'e') { if (current_name < 'a' || current_name > 'e') {
/* Strange section name, abort */ /* Strange section name, abort */
break; break;
@ -404,16 +403,22 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3
/* Four byte length field */ /* Four byte length field */
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 24; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 24;
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 16; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 16;
numbytes += 2; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8;
default: /* Fall through, two byte length field */ current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0;
numbytes += 4;
if (current_length > 300 * 1024) {
/* section e should never exceed about 300KB, if the length is too big limit it but still send the bitstream just in case */
current_length = 300 * 1024;
}
break;
default: /* Two byte length field */
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8;
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0;
numbytes += 2; numbytes += 2;
if (current_length > 64) {
/* if text field is too long, keep it but truncate it */
current_length = 64;
} }
if (current_name != 'e' && current_length > 255) {
/* Maybe a parse error */
break;
} }
if (current_name == section_name) { if (current_name == section_name) {
@ -423,7 +428,7 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3
break; break;
} }
for (uint16_t i = 0; i < current_length && numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH; i++) { for (uint32_t i = 0; i < current_length && numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH; i++) {
get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
numbytes++; numbytes++;
} }

View file

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

View file

@ -235,9 +235,10 @@ static int json_get_utf8_char_len(unsigned char ch) {
/* string = '"' { quoted_printable_chars } '"' */ /* string = '"' { quoted_printable_chars } '"' */
static int json_parse_string(struct frozen *f) { static int json_parse_string(struct frozen *f) {
int n, ch = 0, len = 0; int ch = 0;
TRY(json_test_and_skip(f, '"')); TRY(json_test_and_skip(f, '"'));
{ {
int len = 0;
SET_STATE(f, f->cur, "", 0); SET_STATE(f, f->cur, "", 0);
for (; f->cur < f->end; f->cur += len) { for (; f->cur < f->end; f->cur += len) {
ch = *(unsigned char *) f->cur; ch = *(unsigned char *) f->cur;
@ -245,6 +246,7 @@ static int json_parse_string(struct frozen *f) {
EXPECT(ch >= 32 && len > 0, JSON_STRING_INVALID); /* No control chars */ EXPECT(ch >= 32 && len > 0, JSON_STRING_INVALID); /* No control chars */
EXPECT(len <= json_left(f), JSON_STRING_INCOMPLETE); EXPECT(len <= json_left(f), JSON_STRING_INCOMPLETE);
if (ch == '\\') { if (ch == '\\') {
int n;
EXPECT((n = json_get_escape_len(f->cur + 1, json_left(f))) > 0, n); EXPECT((n = json_get_escape_len(f->cur + 1, json_left(f))) > 0, n);
len += n; len += n;
} else if (ch == '"') { } else if (ch == '"') {
@ -295,17 +297,17 @@ static int json_parse_number(struct frozen *f) {
#if JSON_ENABLE_ARRAY #if JSON_ENABLE_ARRAY
/* array = '[' [ value { ',' value } ] ']' */ /* array = '[' [ value { ',' value } ] ']' */
static int json_parse_array(struct frozen *f) { static int json_parse_array(struct frozen *f) {
int i = 0, current_path_len;
char buf[20];
CALL_BACK(f, JSON_TYPE_ARRAY_START, NULL, 0); CALL_BACK(f, JSON_TYPE_ARRAY_START, NULL, 0);
TRY(json_test_and_skip(f, '[')); TRY(json_test_and_skip(f, '['));
{ {
{ {
int i = 0;
SET_STATE(f, f->cur - 1, "", 0); SET_STATE(f, f->cur - 1, "", 0);
while (json_cur(f) != ']') { while (json_cur(f) != ']') {
char buf[20];
snprintf(buf, sizeof(buf), "[%d]", i); snprintf(buf, sizeof(buf), "[%d]", i);
i++; i++;
current_path_len = json_append_to_path(f, buf, strlen(buf)); int current_path_len = json_append_to_path(f, buf, strlen(buf));
f->cur_name = f->cur_name =
f->path + strlen(f->path) - strlen(buf) + 1 /*opening brace*/; f->path + strlen(f->path) - strlen(buf) + 1 /*opening brace*/;
f->cur_name_len = strlen(buf) - 2 /*braces*/; f->cur_name_len = strlen(buf) - 2 /*braces*/;
@ -1427,9 +1429,12 @@ static void json_next_cb(void *userdata, const char *name, size_t name_len,
static void *json_next(const char *s, int len, void *handle, const char *path, static void *json_next(const char *s, int len, void *handle, const char *path,
struct json_token *key, struct json_token *val, int *i) { struct json_token *key, struct json_token *val, int *i) {
struct json_token tmpval, *v = val == NULL ? &tmpval : val; struct json_token tmpval;
struct json_token tmpkey, *k = key == NULL ? &tmpkey : key; struct json_token *v = val == NULL ? &tmpval : val;
int tmpidx, *pidx = i == NULL ? &tmpidx : i; struct json_token tmpkey;
struct json_token *k = key == NULL ? &tmpkey : key;
int tmpidx;
int *pidx = i == NULL ? &tmpidx : i;
struct next_data data = {handle, path, (int) strlen(path), 0, k, v, pidx}; struct next_data data = {handle, path, (int) strlen(path), 0, k, v, pidx};
json_walk(s, len, json_next_cb, &data); json_walk(s, len, json_next_cb, &data);
return data.found ? data.handle : NULL; return data.found ? data.handle : NULL;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -91,7 +91,7 @@ void I2C_recovery(void) {
DbpString("I2C bus recovery complete"); DbpString("I2C bus recovery complete");
} }
void I2C_init(void) { void I2C_init(bool has_ticks) {
// Configure reset pin, close up pull up, push-pull output, default high // Configure reset pin, close up pull up, push-pull output, default high
AT91C_BASE_PIOA->PIO_PPUDR = GPIO_RST; AT91C_BASE_PIOA->PIO_PPUDR = GPIO_RST;
AT91C_BASE_PIOA->PIO_MDDR = GPIO_RST; AT91C_BASE_PIOA->PIO_MDDR = GPIO_RST;
@ -106,6 +106,10 @@ void I2C_init(void) {
AT91C_BASE_PIOA->PIO_OER |= (GPIO_SCL | GPIO_SDA | GPIO_RST); AT91C_BASE_PIOA->PIO_OER |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
AT91C_BASE_PIOA->PIO_PER |= (GPIO_SCL | GPIO_SDA | GPIO_RST); AT91C_BASE_PIOA->PIO_PER |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
if (has_ticks) {
WaitMS(2);
}
bool isok = (SCL_read && SDA_read); bool isok = (SCL_read && SDA_read);
if (isok == false) if (isok == false)
I2C_recovery(); I2C_recovery();
@ -133,7 +137,7 @@ void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA) {
// Note: the SIM_Adapter will not enter the main program after power up. Please run this function before use SIM_Adapter. // Note: the SIM_Adapter will not enter the main program after power up. Please run this function before use SIM_Adapter.
void I2C_Reset_EnterMainProgram(void) { void I2C_Reset_EnterMainProgram(void) {
StartTicks(); StartTicks();
I2C_init(); I2C_init(true);
I2C_SetResetStatus(0, 0, 0); I2C_SetResetStatus(0, 0, 0);
WaitMS(30); WaitMS(30);
I2C_SetResetStatus(1, 0, 0); I2C_SetResetStatus(1, 0, 0);
@ -146,7 +150,7 @@ void I2C_Reset_EnterMainProgram(void) {
// Reserve for firmware update. // Reserve for firmware update.
void I2C_Reset_EnterBootloader(void) { void I2C_Reset_EnterBootloader(void) {
StartTicks(); StartTicks();
I2C_init(); I2C_init(true);
I2C_SetResetStatus(0, 1, 1); I2C_SetResetStatus(0, 1, 1);
WaitMS(100); WaitMS(100);
I2C_SetResetStatus(1, 1, 1); I2C_SetResetStatus(1, 1, 1);
@ -167,7 +171,7 @@ static bool WaitSCL_H_delay(uint32_t delay) {
// 5000 * 3.07us = 15350us. 15.35ms // 5000 * 3.07us = 15350us. 15.35ms
// 15000 * 3.07us = 46050us. 46.05ms // 15000 * 3.07us = 46050us. 46.05ms
static bool WaitSCL_H(void) { static bool WaitSCL_H(void) {
return WaitSCL_H_delay(15000); return WaitSCL_H_delay(5000);
} }
static bool WaitSCL_L_delay(uint32_t delay) { static bool WaitSCL_L_delay(uint32_t delay) {
@ -179,19 +183,21 @@ static bool WaitSCL_L_delay(uint32_t delay) {
} }
return false; return false;
} }
// 5000 * 3.07us = 15350us. 15.35ms // 5000 * 3.07us = 15350us. 15.35ms
// 15000 * 3.07us = 46050us. 46.05ms
static bool WaitSCL_L(void) { static bool WaitSCL_L(void) {
return WaitSCL_L_delay(15000); return WaitSCL_L_delay(5000);
} }
// Wait max 1800ms or until SCL goes LOW. // Wait max 1800ms or until SCL goes LOW.
// It timeout reading response from card // It timeout reading response from card
// Which ever comes first // Which ever comes first
static bool WaitSCL_L_timeout(void) { static bool WaitSCL_L_timeout(void) {
volatile uint32_t delay = 1700; volatile uint32_t delay = 200;
while (delay--) { while (delay--) {
// exit on SCL LOW // exit on SCL LOW
if (!SCL_read) if (SCL_read == false)
return true; return true;
WaitMS(1); WaitMS(1);
@ -206,12 +212,15 @@ static bool I2C_Start(void) {
SDA_H; SDA_H;
I2C_DELAY_1CLK; I2C_DELAY_1CLK;
SCL_H; SCL_H;
if (!WaitSCL_H()) return false; if (!WaitSCL_H())
return false;
I2C_DELAY_2CLK; I2C_DELAY_2CLK;
if (!SCL_read) return false; if (!SCL_read)
if (!SDA_read) return false; return false;
if (!SDA_read)
return false;
SDA_L; SDA_L;
I2C_DELAY_2CLK; I2C_DELAY_2CLK;
@ -226,8 +235,9 @@ static bool I2C_WaitForSim(void) {
// 8051 speaks with smart card. // 8051 speaks with smart card.
// 1000*50*3.07 = 153.5ms // 1000*50*3.07 = 153.5ms
// 1000*110*3.07 = 337.7ms
// 1byte transfer == 1ms with max frame being 256bytes // 1byte transfer == 1ms with max frame being 256bytes
return WaitSCL_H_delay(1000 * 300); return WaitSCL_H_delay(1000 * 110);
} }
// send i2c STOP // send i2c STOP
@ -397,7 +407,7 @@ bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address) {
//Sends array of data (Array, length, command to be written , SlaveDevice address ). //Sends array of data (Array, length, command to be written , SlaveDevice address ).
// len = uint16 because we need to write up to 256 bytes // len = uint16 because we need to write up to 256 bytes
bool I2C_BufferWrite(uint8_t *data, uint16_t len, uint8_t device_cmd, uint8_t device_address) { bool I2C_BufferWrite(const uint8_t *data, uint16_t len, uint8_t device_cmd, uint8_t device_address) {
bool bBreak = true; bool bBreak = true;
do { do {
if (!I2C_Start()) if (!I2C_Start())
@ -592,7 +602,7 @@ int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t
return readcount; return readcount;
} }
bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) { bool I2C_WriteFW(const uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) {
//START, 0xB0, 0x00, 0x00, xx, yy, zz, ......, STOP //START, 0xB0, 0x00, 0x00, xx, yy, zz, ......, STOP
bool bBreak = true; bool bBreak = true;
@ -708,11 +718,12 @@ bool GetATR(smart_card_atr_t *card_ptr, bool verbose) {
// read bytes from module // read bytes from module
uint16_t len = sizeof(card_ptr->atr); uint16_t len = sizeof(card_ptr->atr);
if (sc_rx_bytes(card_ptr->atr, &len) == false)
return false;
if (len > sizeof(card_ptr->atr)) { if (len > sizeof(card_ptr->atr)) {
len = sizeof(card_ptr->atr); len = sizeof(card_ptr->atr);
} }
if (sc_rx_bytes(card_ptr->atr, &len) == false)
return false;
uint8_t pos_td = 1; uint8_t pos_td = 1;
if ((card_ptr->atr[1] & 0x10) == 0x10) pos_td++; if ((card_ptr->atr[1] & 0x10) == 0x10) pos_td++;
@ -738,7 +749,7 @@ bool GetATR(smart_card_atr_t *card_ptr, bool verbose) {
} }
} }
card_ptr->atr_len = (uint8_t) (len & 0xff); card_ptr->atr_len = (uint8_t)(len & 0xff);
if (verbose) { if (verbose) {
LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false); LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false);
} }
@ -761,7 +772,7 @@ void SmartCardAtr(void) {
// StopTicks(); // StopTicks();
} }
void SmartCardRaw(smart_card_raw_t *p) { void SmartCardRaw(const smart_card_raw_t *p) {
LED_D_ON(); LED_D_ON();
uint16_t len = 0; uint16_t len = 0;

View file

@ -31,7 +31,7 @@
#define I2C_DEVICE_CMD_SEND_T0 0x07 #define I2C_DEVICE_CMD_SEND_T0 0x07
void I2C_recovery(void); void I2C_recovery(void);
void I2C_init(void); void I2C_init(bool has_ticks);
void I2C_Reset(void); void I2C_Reset(void);
void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA); void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA);
@ -41,12 +41,12 @@ void I2C_Reset_EnterBootloader(void);
bool I2C_WriteCmd(uint8_t device_cmd, uint8_t device_address); bool I2C_WriteCmd(uint8_t device_cmd, uint8_t device_address);
bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address); bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address);
bool I2C_BufferWrite(uint8_t *data, uint16_t len, uint8_t device_cmd, uint8_t device_address); bool I2C_BufferWrite(const uint8_t *data, uint16_t len, uint8_t device_cmd, uint8_t device_address);
int16_t I2C_BufferRead(uint8_t *data, uint16_t len, uint8_t device_cmd, uint8_t device_address); int16_t I2C_BufferRead(uint8_t *data, uint16_t len, uint8_t device_cmd, uint8_t device_address);
// for firmware // for firmware
int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address); int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address);
bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address); bool I2C_WriteFW(const uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address);
bool sc_rx_bytes(uint8_t *dest, uint16_t *destlen); bool sc_rx_bytes(uint8_t *dest, uint16_t *destlen);
// //
@ -54,7 +54,7 @@ bool GetATR(smart_card_atr_t *card_ptr, bool verbose);
// generice functions // generice functions
void SmartCardAtr(void); void SmartCardAtr(void);
void SmartCardRaw(smart_card_raw_t *p); void SmartCardRaw(const smart_card_raw_t *p);
void SmartCardUpgrade(uint64_t arg0); void SmartCardUpgrade(uint64_t arg0);
void SmartCardSetBaud(uint64_t arg0); void SmartCardSetBaud(uint64_t arg0);
void SmartCardSetClock(uint64_t arg0); void SmartCardSetClock(uint64_t arg0);

View file

@ -1245,29 +1245,28 @@ send:
} }
// THE READER CODE // THE READER CODE
static void iclass_send_as_reader(uint8_t *frame, int len, uint32_t *start_time, uint32_t *end_time) { static void iclass_send_as_reader(uint8_t *frame, int len, uint32_t *start_time, uint32_t *end_time, bool shallow_mod) {
CodeIso15693AsReader(frame, len); CodeIso15693AsReader(frame, len);
tosend_t *ts = get_tosend(); tosend_t *ts = get_tosend();
TransmitTo15693Tag(ts->buf, ts->max, start_time); TransmitTo15693Tag(ts->buf, ts->max, start_time, shallow_mod);
*end_time = *start_time + (32 * ((8 * ts->max) - 4)); // subtract the 4 padding bits after EOF *end_time = *start_time + (32 * ((8 * ts->max) - 4)); // subtract the 4 padding bits after EOF
LogTrace_ISO15693(frame, len, (*start_time * 4), (*end_time * 4), NULL, true); LogTrace_ISO15693(frame, len, (*start_time * 4), (*end_time * 4), NULL, true);
} }
static bool iclass_send_cmd_with_retries(uint8_t *cmd, size_t cmdsize, uint8_t *resp, size_t max_resp_size, static bool iclass_send_cmd_with_retries(uint8_t *cmd, size_t cmdsize, uint8_t *resp, size_t max_resp_size,
uint8_t expected_size, uint8_t tries, uint32_t *start_time, uint8_t expected_size, uint8_t tries, uint32_t *start_time,
uint16_t timeout, uint32_t *eof_time) { uint16_t timeout, uint32_t *eof_time, bool shallow_mod) {
uint16_t resp_len = 0; uint16_t resp_len = 0;
int res;
while (tries-- > 0) { while (tries-- > 0) {
iclass_send_as_reader(cmd, cmdsize, start_time, eof_time); iclass_send_as_reader(cmd, cmdsize, start_time, eof_time, shallow_mod);
if (resp == NULL) { if (resp == NULL) {
return true; return true;
} }
res = GetIso15693AnswerFromTag(resp, max_resp_size, timeout, eof_time, false, true, &resp_len); int res = GetIso15693AnswerFromTag(resp, max_resp_size, timeout, eof_time, false, true, &resp_len);
if (res == PM3_SUCCESS && expected_size == resp_len) { if (res == PM3_SUCCESS && expected_size == resp_len) {
return true; return true;
} }
@ -1282,7 +1281,7 @@ static bool iclass_send_cmd_with_retries(uint8_t *cmd, size_t cmdsize, uint8_t *
* @return false = fail * @return false = fail
* true = Got all. * true = Got all.
*/ */
static bool select_iclass_tag_ex(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time, uint8_t *status) { static bool select_iclass_tag_ex(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time, uint8_t *status, bool shallow_mod) {
static uint8_t act_all[] = { ICLASS_CMD_ACTALL }; static uint8_t act_all[] = { ICLASS_CMD_ACTALL };
static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 }; static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 };
@ -1299,7 +1298,7 @@ static bool select_iclass_tag_ex(picopass_hdr_t *hdr, bool use_credit_key, uint3
// wakeup // wakeup
uint32_t start_time = GetCountSspClk(); uint32_t start_time = GetCountSspClk();
iclass_send_as_reader(act_all, 1, &start_time, eof_time); iclass_send_as_reader(act_all, 1, &start_time, eof_time, shallow_mod);
int res; int res;
uint16_t resp_len = 0; uint16_t resp_len = 0;
res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_ACTALL, eof_time, false, true, &resp_len); res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_ACTALL, eof_time, false, true, &resp_len);
@ -1308,7 +1307,7 @@ static bool select_iclass_tag_ex(picopass_hdr_t *hdr, bool use_credit_key, uint3
// send Identify // send Identify
start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
iclass_send_as_reader(identify, 1, &start_time, eof_time); iclass_send_as_reader(identify, 1, &start_time, eof_time, shallow_mod);
// expect a 10-byte response here, 8 byte anticollision-CSN and 2 byte CRC // expect a 10-byte response here, 8 byte anticollision-CSN and 2 byte CRC
res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len); res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len);
@ -1320,7 +1319,7 @@ static bool select_iclass_tag_ex(picopass_hdr_t *hdr, bool use_credit_key, uint3
// select the card // select the card
start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
iclass_send_as_reader(select, sizeof(select), &start_time, eof_time); iclass_send_as_reader(select, sizeof(select), &start_time, eof_time, shallow_mod);
// expect a 10-byte response here, 8 byte CSN and 2 byte CRC // expect a 10-byte response here, 8 byte CSN and 2 byte CRC
res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len); res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len);
@ -1332,7 +1331,7 @@ static bool select_iclass_tag_ex(picopass_hdr_t *hdr, bool use_credit_key, uint3
// card selected, now read config (block1) (only 8 bytes no CRC) // card selected, now read config (block1) (only 8 bytes no CRC)
start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
iclass_send_as_reader(read_conf, sizeof(read_conf), &start_time, eof_time); iclass_send_as_reader(read_conf, sizeof(read_conf), &start_time, eof_time, shallow_mod);
// expect a 8-byte response here // expect a 8-byte response here
res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len); res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len);
@ -1350,7 +1349,7 @@ static bool select_iclass_tag_ex(picopass_hdr_t *hdr, bool use_credit_key, uint3
// read App Issuer Area block 5 // read App Issuer Area block 5
start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
iclass_send_as_reader(read_aia, sizeof(read_aia), &start_time, eof_time); iclass_send_as_reader(read_aia, sizeof(read_aia), &start_time, eof_time, shallow_mod);
// expect a 10-byte response here // expect a 10-byte response here
res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len); res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len);
@ -1364,7 +1363,7 @@ static bool select_iclass_tag_ex(picopass_hdr_t *hdr, bool use_credit_key, uint3
// card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC) // card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC)
start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
iclass_send_as_reader(read_check_cc, sizeof(read_check_cc), &start_time, eof_time); iclass_send_as_reader(read_check_cc, sizeof(read_check_cc), &start_time, eof_time, shallow_mod);
// expect a 8-byte response here // expect a 8-byte response here
res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len); res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len);
@ -1386,7 +1385,7 @@ static bool select_iclass_tag_ex(picopass_hdr_t *hdr, bool use_credit_key, uint3
read_aia[3] = 0x10; read_aia[3] = 0x10;
start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
iclass_send_as_reader(read_aia, sizeof(read_aia), &start_time, eof_time); iclass_send_as_reader(read_aia, sizeof(read_aia), &start_time, eof_time, shallow_mod);
// expect a 10-byte response here // expect a 10-byte response here
res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len); res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len);
@ -1402,9 +1401,9 @@ static bool select_iclass_tag_ex(picopass_hdr_t *hdr, bool use_credit_key, uint3
return true; return true;
} }
bool select_iclass_tag(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time) { bool select_iclass_tag(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time, bool shallow_mod) {
uint8_t result = 0; uint8_t result = 0;
return select_iclass_tag_ex(hdr, use_credit_key, eof_time, &result); return select_iclass_tag_ex(hdr, use_credit_key, eof_time, &result, shallow_mod);
} }
// Reader iClass Anticollission // Reader iClass Anticollission
@ -1413,6 +1412,7 @@ void ReaderIClass(uint8_t flags) {
// flag to use credit key // flag to use credit key
bool use_credit_key = ((flags & FLAG_ICLASS_READER_CREDITKEY) == FLAG_ICLASS_READER_CREDITKEY); bool use_credit_key = ((flags & FLAG_ICLASS_READER_CREDITKEY) == FLAG_ICLASS_READER_CREDITKEY);
bool shallow_mod = (flags & FLAG_ICLASS_READER_SHALLOW_MOD);
if ((flags & FLAG_ICLASS_READER_INIT) == FLAG_ICLASS_READER_INIT) { if ((flags & FLAG_ICLASS_READER_INIT) == FLAG_ICLASS_READER_INIT) {
Iso15693InitReader(); Iso15693InitReader();
@ -1427,7 +1427,7 @@ void ReaderIClass(uint8_t flags) {
uint32_t eof_time = 0; uint32_t eof_time = 0;
picopass_hdr_t hdr = {0}; picopass_hdr_t hdr = {0};
if (select_iclass_tag_ex(&hdr, use_credit_key, &eof_time, &res) == false) { if (select_iclass_tag_ex(&hdr, use_credit_key, &eof_time, &res, shallow_mod) == false) {
reply_ng(CMD_HF_ICLASS_READER, PM3_ERFTRANS, NULL, 0); reply_ng(CMD_HF_ICLASS_READER, PM3_ERFTRANS, NULL, 0);
goto out; goto out;
} }
@ -1498,7 +1498,7 @@ bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr_t *hdr, ui
cmd_check[7] = pmac[2]; cmd_check[7] = pmac[2];
cmd_check[8] = pmac[3]; cmd_check[8] = pmac[3];
} }
return iclass_send_cmd_with_retries(cmd_check, sizeof(cmd_check), resp_auth, sizeof(resp_auth), 4, 2, start_time, ICLASS_READER_TIMEOUT_OTHERS, eof_time); return iclass_send_cmd_with_retries(cmd_check, sizeof(cmd_check), resp_auth, sizeof(resp_auth), 4, 2, start_time, ICLASS_READER_TIMEOUT_OTHERS, eof_time, payload->shallow_mod);
} }
@ -1516,6 +1516,8 @@ void iClass_Authentication_fast(iclass_chk_t *p) {
return; return;
} }
bool shallow_mod = p->shallow_mod;
uint8_t check[9] = { ICLASS_CMD_CHECK }; uint8_t check[9] = { ICLASS_CMD_CHECK };
uint8_t resp[ICLASS_BUFFER_SIZE] = {0}; uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
uint8_t readcheck_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 }; uint8_t readcheck_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 };
@ -1537,7 +1539,7 @@ void iClass_Authentication_fast(iclass_chk_t *p) {
bool isOK = false; bool isOK = false;
uint32_t start_time = 0, eof_time = 0; uint32_t start_time = 0, eof_time = 0;
if (select_iclass_tag(&hdr, p->use_credit_key, &eof_time) == false) if (select_iclass_tag(&hdr, p->use_credit_key, &eof_time, shallow_mod) == false)
goto out; goto out;
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
@ -1566,14 +1568,14 @@ void iClass_Authentication_fast(iclass_chk_t *p) {
check[8] = keys[i].mac[3]; check[8] = keys[i].mac[3];
// expect 4bytes, 3 retries times.. // expect 4bytes, 3 retries times..
isOK = iclass_send_cmd_with_retries(check, sizeof(check), resp, sizeof(resp), 4, 2, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time); isOK = iclass_send_cmd_with_retries(check, sizeof(check), resp, sizeof(resp), 4, 2, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time, shallow_mod);
if (isOK) if (isOK)
goto out; goto out;
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
// Auth Sequence MUST begin with reading e-purse. (block2) // Auth Sequence MUST begin with reading e-purse. (block2)
// Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC) // Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC)
iclass_send_as_reader(readcheck_cc, sizeof(readcheck_cc), &start_time, &eof_time); iclass_send_as_reader(readcheck_cc, sizeof(readcheck_cc), &start_time, &eof_time, shallow_mod);
LED_B_OFF(); LED_B_OFF();
} }
@ -1586,11 +1588,11 @@ out:
// Tries to read block. // Tries to read block.
// retries 3times. // retries 3times.
// reply 8 bytes block // reply 8 bytes block
bool iclass_read_block(uint16_t blockno, uint8_t *data, uint32_t *start_time, uint32_t *eof_time) { bool iclass_read_block(uint16_t blockno, uint8_t *data, uint32_t *start_time, uint32_t *eof_time, bool shallow_mod) {
uint8_t resp[10]; uint8_t resp[10];
uint8_t c[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockno, 0x00, 0x00}; uint8_t c[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockno, 0x00, 0x00};
AddCrc(c + 1, 1); AddCrc(c + 1, 1);
bool isOK = iclass_send_cmd_with_retries(c, sizeof(c), resp, sizeof(resp), 10, 2, start_time, ICLASS_READER_TIMEOUT_OTHERS, eof_time); bool isOK = iclass_send_cmd_with_retries(c, sizeof(c), resp, sizeof(resp), 10, 2, start_time, ICLASS_READER_TIMEOUT_OTHERS, eof_time, shallow_mod);
if (isOK) if (isOK)
memcpy(data, resp, 8); memcpy(data, resp, 8);
return isOK; return isOK;
@ -1602,6 +1604,7 @@ bool iclass_read_block(uint16_t blockno, uint8_t *data, uint32_t *start_time, ui
void iClass_ReadBlock(uint8_t *msg) { void iClass_ReadBlock(uint8_t *msg) {
iclass_auth_req_t *payload = (iclass_auth_req_t *)msg; iclass_auth_req_t *payload = (iclass_auth_req_t *)msg;
bool shallow_mod = payload->shallow_mod;
iclass_readblock_resp_t response = { .isOK = true }; iclass_readblock_resp_t response = { .isOK = true };
memset(response.data, 0, sizeof(response.data)); memset(response.data, 0, sizeof(response.data));
@ -1614,7 +1617,7 @@ void iClass_ReadBlock(uint8_t *msg) {
// select tag. // select tag.
uint32_t eof_time = 0; uint32_t eof_time = 0;
picopass_hdr_t hdr = {0}; picopass_hdr_t hdr = {0};
bool res = select_iclass_tag(&hdr, payload->use_credit_key, &eof_time); bool res = select_iclass_tag(&hdr, payload->use_credit_key, &eof_time, shallow_mod);
if (res == false) { if (res == false) {
if (payload->send_reply) { if (payload->send_reply) {
response.isOK = res; response.isOK = res;
@ -1642,7 +1645,7 @@ void iClass_ReadBlock(uint8_t *msg) {
// read data // read data
uint8_t resp[10]; uint8_t resp[10];
res = iclass_send_cmd_with_retries(cmd_read, sizeof(cmd_read), resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time); res = iclass_send_cmd_with_retries(cmd_read, sizeof(cmd_read), resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time, shallow_mod);
if (res) { if (res) {
memcpy(response.data, resp, sizeof(response.data)); memcpy(response.data, resp, sizeof(response.data));
if (payload->send_reply) { if (payload->send_reply) {
@ -1670,6 +1673,7 @@ void iClass_Dump(uint8_t *msg) {
iclass_dump_req_t *cmd = (iclass_dump_req_t *)msg; iclass_dump_req_t *cmd = (iclass_dump_req_t *)msg;
iclass_auth_req_t *req = &cmd->req; iclass_auth_req_t *req = &cmd->req;
bool shallow_mod = req->shallow_mod;
uint8_t *dataout = BigBuf_malloc(ICLASS_16KS_SIZE); uint8_t *dataout = BigBuf_malloc(ICLASS_16KS_SIZE);
if (dataout == NULL) { if (dataout == NULL) {
@ -1689,7 +1693,7 @@ void iClass_Dump(uint8_t *msg) {
picopass_hdr_t hdr = {0}; picopass_hdr_t hdr = {0};
memset(&hdr, 0xff, sizeof(picopass_hdr_t)); memset(&hdr, 0xff, sizeof(picopass_hdr_t));
bool res = select_iclass_tag(&hdr, req->use_credit_key, &eof_time); bool res = select_iclass_tag(&hdr, req->use_credit_key, &eof_time, shallow_mod);
if (res == false) { if (res == false) {
if (req->send_reply) { if (req->send_reply) {
reply_ng(CMD_HF_ICLASS_DUMP, PM3_ETIMEOUT, NULL, 0); reply_ng(CMD_HF_ICLASS_DUMP, PM3_ETIMEOUT, NULL, 0);
@ -1724,7 +1728,7 @@ void iClass_Dump(uint8_t *msg) {
uint8_t c[] = {ICLASS_CMD_READ_OR_IDENTIFY, i, 0x00, 0x00}; uint8_t c[] = {ICLASS_CMD_READ_OR_IDENTIFY, i, 0x00, 0x00};
AddCrc(c + 1, 1); AddCrc(c + 1, 1);
res = iclass_send_cmd_with_retries(c, sizeof(c), resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time); res = iclass_send_cmd_with_retries(c, sizeof(c), resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time, shallow_mod);
if (res) { if (res) {
memcpy(dataout + (8 * i), resp, 8); memcpy(dataout + (8 * i), resp, 8);
} else { } else {
@ -1759,7 +1763,7 @@ void iClass_Dump(uint8_t *msg) {
BigBuf_free(); BigBuf_free();
} }
static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data, uint8_t *mac, bool use_mac) { static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data, uint8_t *mac, bool use_mac, bool shallow_mod) {
// write command: cmd, 1 blockno, 8 data, 4 mac // write command: cmd, 1 blockno, 8 data, 4 mac
uint8_t write[14] = { 0x80 | ICLASS_CMD_UPDATE, blockno }; uint8_t write[14] = { 0x80 | ICLASS_CMD_UPDATE, blockno };
@ -1775,7 +1779,7 @@ static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data, uint8_t *mac,
uint8_t resp[10] = {0}; uint8_t resp[10] = {0};
uint32_t eof_time = 0, start_time = 0; uint32_t eof_time = 0, start_time = 0;
bool isOK = iclass_send_cmd_with_retries(write, write_len, resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_UPDATE, &eof_time); bool isOK = iclass_send_cmd_with_retries(write, write_len, resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_UPDATE, &eof_time, shallow_mod);
if (isOK == false) { if (isOK == false) {
return false; return false;
} }
@ -1807,6 +1811,7 @@ void iClass_WriteBlock(uint8_t *msg) {
LED_A_ON(); LED_A_ON();
iclass_writeblock_req_t *payload = (iclass_writeblock_req_t *)msg; iclass_writeblock_req_t *payload = (iclass_writeblock_req_t *)msg;
bool shallow_mod = payload->req.shallow_mod;
uint8_t write[14] = { 0x80 | ICLASS_CMD_UPDATE, payload->req.blockno }; uint8_t write[14] = { 0x80 | ICLASS_CMD_UPDATE, payload->req.blockno };
uint8_t write_len = 14; uint8_t write_len = 14;
@ -1816,7 +1821,7 @@ void iClass_WriteBlock(uint8_t *msg) {
// select tag. // select tag.
uint32_t eof_time = 0; uint32_t eof_time = 0;
picopass_hdr_t hdr = {0}; picopass_hdr_t hdr = {0};
uint8_t res = select_iclass_tag(&hdr, payload->req.use_credit_key, &eof_time); uint8_t res = select_iclass_tag(&hdr, payload->req.use_credit_key, &eof_time, shallow_mod);
if (res == false) { if (res == false) {
goto out; goto out;
} }
@ -1871,7 +1876,7 @@ void iClass_WriteBlock(uint8_t *msg) {
uint8_t tries = 3; uint8_t tries = 3;
while (tries-- > 0) { while (tries-- > 0) {
iclass_send_as_reader(write, write_len, &start_time, &eof_time); iclass_send_as_reader(write, write_len, &start_time, &eof_time, shallow_mod);
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred
res = false; res = false;
@ -1939,6 +1944,8 @@ void iClass_Restore(iclass_restore_req_t *msg) {
return; return;
} }
bool shallow_mod = msg->req.shallow_mod;
LED_A_ON(); LED_A_ON();
Iso15693InitReader(); Iso15693InitReader();
@ -1947,7 +1954,7 @@ void iClass_Restore(iclass_restore_req_t *msg) {
picopass_hdr_t hdr = {0}; picopass_hdr_t hdr = {0};
// select // select
bool res = select_iclass_tag(&hdr, msg->req.use_credit_key, &eof_time); bool res = select_iclass_tag(&hdr, msg->req.use_credit_key, &eof_time, shallow_mod);
if (res == false) { if (res == false) {
goto out; goto out;
} }
@ -1988,7 +1995,7 @@ void iClass_Restore(iclass_restore_req_t *msg) {
} }
// data + mac // data + mac
if (iclass_writeblock_ext(item.blockno, item.data, mac, use_mac)) { if (iclass_writeblock_ext(item.blockno, item.data, mac, use_mac, shallow_mod)) {
Dbprintf("Write block [%3d/0x%02X] " _GREEN_("successful"), item.blockno, item.blockno); Dbprintf("Write block [%3d/0x%02X] " _GREEN_("successful"), item.blockno, item.blockno);
written++; written++;
} else { } else {

View file

@ -38,8 +38,8 @@ void iClass_Authentication_fast(iclass_chk_t *p);
bool iclass_auth(iclass_auth_req_t *payload, uint8_t *out); bool iclass_auth(iclass_auth_req_t *payload, uint8_t *out);
void iClass_ReadBlock(uint8_t *msg); void iClass_ReadBlock(uint8_t *msg);
bool iclass_read_block(uint16_t blockno, uint8_t *data, uint32_t *start_time, uint32_t *eof_time); bool iclass_read_block(uint16_t blockno, uint8_t *data, uint32_t *start_time, uint32_t *eof_time, bool shallow_mod);
bool select_iclass_tag(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time); bool select_iclass_tag(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time, bool shallow_mod);
bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr_t *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out); bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr_t *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out);
#endif #endif

View file

@ -142,6 +142,15 @@ Default HF 14a config is set to:
*/ */
static hf14a_config hf14aconfig = { 0, 0, 0, 0, 0 } ; static hf14a_config hf14aconfig = { 0, 0, 0, 0, 0 } ;
// Polling frames and configurations
static iso14a_polling_parameters_t WUPA_POLLING_PARAMETERS = {
.frames = { {{ 0x52 }, 1, 7, 0} },
.frame_count = 1,
.extra_timeout = 0,
};
void printHf14aConfig(void) { void printHf14aConfig(void) {
DbpString(_CYAN_("HF 14a config")); DbpString(_CYAN_("HF 14a config"));
Dbprintf(" [a] Anticol override.... %s%s%s", Dbprintf(" [a] Anticol override.... %s%s%s",
@ -179,7 +188,7 @@ void printHf14aConfig(void) {
* @brief setSamplingConfig * @brief setSamplingConfig
* @param sc * @param sc
*/ */
void setHf14aConfig(hf14a_config *hc) { void setHf14aConfig(const hf14a_config *hc) {
if ((hc->forceanticol >= 0) && (hc->forceanticol <= 2)) if ((hc->forceanticol >= 0) && (hc->forceanticol <= 2))
hf14aconfig.forceanticol = hc->forceanticol; hf14aconfig.forceanticol = hc->forceanticol;
@ -555,7 +564,7 @@ RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_t
} }
// Thinfilm, Kovio mangels ISO14443A in the way that they don't use start bit nor parity bits. // Thinfilm, Kovio mangles ISO14443A in the way that they don't use start bit nor parity bits.
static RAMFUNC int ManchesterDecoding_Thinfilm(uint8_t bit) { static RAMFUNC int ManchesterDecoding_Thinfilm(uint8_t bit) {
Demod.twoBits = (Demod.twoBits << 8) | bit; Demod.twoBits = (Demod.twoBits << 8) | bit;
@ -1039,44 +1048,69 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
// PPS response // PPS response
static uint8_t rPPS[3] = { 0xD0 }; static uint8_t rPPS[3] = { 0xD0 };
static uint8_t rPACK[4] = { 0x00, 0x00, 0x00, 0x00 };
switch (tagType) { switch (tagType) {
case 1: { // MIFARE Classic 1k case 1: { // MIFARE Classic 1k
rATQA[0] = 0x04; rATQA[0] = 0x04;
sak = 0x08; sak = 0x08;
}
break; break;
}
case 2: { // MIFARE Ultralight case 2: { // MIFARE Ultralight
rATQA[0] = 0x44; rATQA[0] = 0x44;
sak = 0x00; sak = 0x00;
// some first pages of UL/NTAG dump is special data // some first pages of UL/NTAG dump is special data
mfu_dump_t *mfu_header = (mfu_dump_t *) BigBuf_get_EM_addr(); mfu_dump_t *mfu_header = (mfu_dump_t *) BigBuf_get_EM_addr();
*pages = MAX(mfu_header->pages, 15); *pages = MAX(mfu_header->pages, 15);
// counters and tearing flags
// for old dumps with all zero headers, we need to set default values.
for (uint8_t i = 0; i < 3; i++) {
counters[i] = le24toh(mfu_header->counter_tearing[i]);
if (mfu_header->counter_tearing[i][3] != 0x00) {
tearings[i] = mfu_header->counter_tearing[i][3];
} }
}
// GET_VERSION
if (memcmp(mfu_header->version, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) == 0) {
memcpy(rVERSION, "\x00\x04\x04\x02\x01\x00\x11\x03", 8);
} else {
memcpy(rVERSION, mfu_header->version, 8);
}
AddCrc14A(rVERSION, sizeof(rVERSION) - 2);
// READ_SIG
memcpy(rSIGN, mfu_header->signature, 32);
AddCrc14A(rSIGN, sizeof(rSIGN) - 2);
break; break;
}
case 3: { // MIFARE DESFire case 3: { // MIFARE DESFire
rATQA[0] = 0x44; rATQA[0] = 0x44;
rATQA[1] = 0x03; rATQA[1] = 0x03;
sak = 0x20; sak = 0x20;
memcpy(rRATS, "\x06\x75\x77\x81\x02\x80\x00\x00", 8); memcpy(rRATS, "\x06\x75\x77\x81\x02\x80\x00\x00", 8);
}
break; break;
}
case 4: { // ISO/IEC 14443-4 - javacard (JCOP) case 4: { // ISO/IEC 14443-4 - javacard (JCOP)
rATQA[0] = 0x04; rATQA[0] = 0x04;
sak = 0x28; sak = 0x28;
}
break; break;
}
case 5: { // MIFARE TNP3XXX case 5: { // MIFARE TNP3XXX
rATQA[0] = 0x01; rATQA[0] = 0x01;
rATQA[1] = 0x0f; rATQA[1] = 0x0f;
sak = 0x01; sak = 0x01;
}
break; break;
}
case 6: { // MIFARE Mini 320b case 6: { // MIFARE Mini 320b
rATQA[0] = 0x44; rATQA[0] = 0x44;
sak = 0x09; sak = 0x09;
}
break; break;
case 7: { // NTAG }
case 7: { // NTAG 215
rATQA[0] = 0x44; rATQA[0] = 0x44;
sak = 0x00; sak = 0x00;
// some first pages of UL/NTAG dump is special data // some first pages of UL/NTAG dump is special data
@ -1105,32 +1139,39 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
// READ_SIG // READ_SIG
memcpy(rSIGN, mfu_header->signature, 32); memcpy(rSIGN, mfu_header->signature, 32);
AddCrc14A(rSIGN, sizeof(rSIGN) - 2); AddCrc14A(rSIGN, sizeof(rSIGN) - 2);
}
break; break;
}
case 8: { // MIFARE Classic 4k case 8: { // MIFARE Classic 4k
rATQA[0] = 0x02; rATQA[0] = 0x02;
sak = 0x18; sak = 0x18;
}
break; break;
}
case 9: { // FM11RF005SH (Shanghai Metro) case 9: { // FM11RF005SH (Shanghai Metro)
rATQA[0] = 0x03; rATQA[0] = 0x03;
rATQA[1] = 0x00; rATQA[1] = 0x00;
sak = 0x0A; sak = 0x0A;
}
break; break;
}
case 10: { // ST25TA IKEA Rothult case 10: { // ST25TA IKEA Rothult
rATQA[0] = 0x42; rATQA[0] = 0x42;
rATQA[1] = 0x00; rATQA[1] = 0x00;
sak = 0x20; sak = 0x20;
}
break; break;
}
case 11: { // ISO/IEC 14443-4 - javacard (JCOP)
rATQA[0] = 0x04;
sak = 0x20;
break;
}
case 12: { // HID Seos 4K card
rATQA[0] = 0x01;
sak = 0x20;
break;
}
default: { default: {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Error: unknown tagtype (%d)", tagType); if (g_dbglevel >= DBG_ERROR) Dbprintf("Error: unknown tagtype (%d)", tagType);
return false; return false;
} }
break;
} }
// if uid not supplied then get from emulator memory // if uid not supplied then get from emulator memory
@ -1157,7 +1198,13 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
// Configure the ATQA and SAK accordingly // Configure the ATQA and SAK accordingly
rATQA[0] &= 0xBF; rATQA[0] &= 0xBF;
if (tagType == 11) {
rSAKc1[0] = sak & 0xFC & 0X70;
} else {
rSAKc1[0] = sak & 0xFB; rSAKc1[0] = sak & 0xFB;
}
AddCrc14A(rSAKc1, sizeof(rSAKc1) - 2); AddCrc14A(rSAKc1, sizeof(rSAKc1) - 2);
*cuid = bytes_to_num(data, 4); *cuid = bytes_to_num(data, 4);
@ -1227,6 +1274,22 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
AddCrc14A(rPPS, sizeof(rPPS) - 2); AddCrc14A(rPPS, sizeof(rPPS) - 2);
// EV1/NTAG, set PWD w AMIIBO algo if all zero.
if (tagType == 7) {
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[] = { static tag_response_info_t responses_init[] = {
{ .response = rATQA, .response_n = sizeof(rATQA) }, // Answer to request - respond with card type { .response = rATQA, .response_n = sizeof(rATQA) }, // Answer to request - respond with card type
{ .response = rUIDc1, .response_n = sizeof(rUIDc1) }, // Anticollision cascade1 - respond with uid { .response = rUIDc1, .response_n = sizeof(rUIDc1) }, // Anticollision cascade1 - respond with uid
@ -1238,14 +1301,16 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
{ .response = rRATS, .response_n = sizeof(rRATS) }, // dummy ATS (pseudo-ATR), answer to RATS { .response = rRATS, .response_n = sizeof(rRATS) }, // dummy ATS (pseudo-ATR), answer to RATS
{ .response = rVERSION, .response_n = sizeof(rVERSION) }, // EV1/NTAG GET_VERSION response { .response = rVERSION, .response_n = sizeof(rVERSION) }, // EV1/NTAG GET_VERSION response
{ .response = rSIGN, .response_n = sizeof(rSIGN) }, // EV1/NTAG READ_SIG response { .response = rSIGN, .response_n = sizeof(rSIGN) }, // EV1/NTAG READ_SIG response
{ .response = rPPS, .response_n = sizeof(rPPS) } // PPS response { .response = rPPS, .response_n = sizeof(rPPS) }, // PPS response
{ .response = rPACK, .response_n = sizeof(rPACK) } // PACK response
}; };
// "precompile" responses. There are 11 predefined responses with a total of 80 bytes data to transmit. // "precompile" responses. There are 12 predefined responses with a total of 84 bytes data to transmit.
// Coded responses need one byte per bit to transfer (data, parity, start, stop, correction) // Coded responses need one byte per bit to transfer (data, parity, start, stop, correction)
// 81 * 8 data bits, 81 * 1 parity bits, 11 start bits, 11 stop bits, 11 correction bits // 85 * 8 data bits, 85 * 1 parity bits, 12 start bits, 12 stop bits, 12 correction bits
// 81 * 8 + 81 + 11 + 11 + 11 == 762 // 85 * 8 + 85 + 12 + 12 + 12 == 801
#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 762 #define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 801
uint8_t *free_buffer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE); uint8_t *free_buffer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE);
// modulation buffer pointer and current buffer free space size // modulation buffer pointer and current buffer free space size
@ -1506,7 +1571,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
// block1 = 4byte UID. // block1 = 4byte UID.
p_response = &responses[RESP_INDEX_UIDC1]; p_response = &responses[RESP_INDEX_UIDC1];
} else { // all other tags (16 byte block tags) } else { // all other tags (16 byte block tags)
uint8_t emdata[MAX_MIFARE_FRAME_SIZE]; uint8_t emdata[MAX_MIFARE_FRAME_SIZE] = {0};
emlGetMemBt(emdata, block, 16); emlGetMemBt(emdata, block, 16);
AddCrc14A(emdata, 16); AddCrc14A(emdata, 16);
EmSendCmd(emdata, sizeof(emdata)); EmSendCmd(emdata, sizeof(emdata));
@ -1520,7 +1585,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
// send NACK 0x0 == invalid argument // send NACK 0x0 == invalid argument
EmSend4bit(CARD_NACK_IV); EmSend4bit(CARD_NACK_IV);
} else { } else {
uint8_t emdata[MAX_FRAME_SIZE]; uint8_t emdata[MAX_FRAME_SIZE] = {0};
// first blocks of emu are header // first blocks of emu are header
int start = block1 * 4 + MFU_DUMP_PREFIX_LENGTH; int start = block1 * 4 + MFU_DUMP_PREFIX_LENGTH;
len = (block2 - block1 + 1) * 4; len = (block2 - block1 + 1) * 4;
@ -1604,7 +1669,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
// send NACK 0x0 == invalid argument // send NACK 0x0 == invalid argument
EmSend4bit(CARD_NACK_IV); EmSend4bit(CARD_NACK_IV);
} else { } else {
uint8_t cmd[3]; uint8_t cmd[3] = {0, 0, 0};
cmd[0] = tearings[index]; cmd[0] = tearings[index];
AddCrc14A(cmd, sizeof(cmd) - 2); AddCrc14A(cmd, sizeof(cmd) - 2);
EmSendCmd(cmd, sizeof(cmd)); EmSendCmd(cmd, sizeof(cmd));
@ -1640,31 +1705,32 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
} else if (receivedCmd[0] == MIFARE_ULC_AUTH_1) { // ULC authentication, or Desfire Authentication } else if (receivedCmd[0] == MIFARE_ULC_AUTH_1) { // ULC authentication, or Desfire Authentication
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
p_response = NULL; p_response = NULL;
} else if (receivedCmd[0] == MIFARE_ULEV1_AUTH && len == 7 && tagType == 7) { // NTAG / EV-1 authentication } else if (receivedCmd[0] == MIFARE_ULEV1_AUTH && len == 7 && tagType == 7) { // NTAG / EV-1
// PWD stored in dump now uint8_t pwd[4] = {0, 0, 0, 0};
uint8_t pwd[4];
emlGetMemBt(pwd, (pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(pwd)); emlGetMemBt(pwd, (pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(pwd));
if (g_dbglevel >= DBG_DEBUG) {
Dbprintf("Reader sent password: ");
Dbhexdump(4, receivedCmd + 1, 0);
Dbprintf("Loaded password from memory: ");
Dbhexdump(4, pwd, 0);
}
if (memcmp(pwd, "\x00\x00\x00\x00", 4) == 0) { if (memcmp(pwd, "\x00\x00\x00\x00", 4) == 0) {
Uint4byteToMemLe(pwd, ul_ev1_pwdgenB(data)); Uint4byteToMemLe(pwd, ul_ev1_pwdgenB(data));
Dbprintf("Calc pwd... %02X %02X %02X %02X", pwd[0], pwd[1], pwd[2], pwd[3]); if (g_dbglevel >= DBG_DEBUG) Dbprintf("Calc pwd... %02X %02X %02X %02X", pwd[0], pwd[1], pwd[2], pwd[3]);
} }
if (memcmp(receivedCmd + 1, pwd, 4) == 0) { if (memcmp(receivedCmd + 1, pwd, 4) == 0) {
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Password match, responding with PACK.");
uint8_t pack[4]; p_response = &responses[RESP_INDEX_PACK];
emlGetMemBt(pack, pages * 4 + MFU_DUMP_PREFIX_LENGTH, 2);
if (memcmp(pack, "\x00\x00\x00\x00", 4) == 0) {
memcpy(pack, "\x80\x80\x00\x00", 4);
}
AddCrc14A(pack, sizeof(pack) - 2);
EmSendCmd(pack, sizeof(pack));
} else { } else {
EmSend4bit(CARD_NACK_NA); if (g_dbglevel >= DBG_DEBUG) Dbprintf("Password did not match, NACK_IV.");
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Auth attempt: %08x", bytes_to_num(receivedCmd + 1, 4));
}
p_response = NULL; p_response = NULL;
EmSend4bit(CARD_NACK_IV);
}
} else if (receivedCmd[0] == MIFARE_ULEV1_VCSL && len == 23 && tagType == 7) { } else if (receivedCmd[0] == MIFARE_ULEV1_VCSL && len == 23 && tagType == 7) {
uint8_t cmd[3]; uint8_t cmd[3] = {0, 0, 0};
emlGetMemBt(cmd, (pages - 2) * 4 + 1 + MFU_DUMP_PREFIX_LENGTH, 1); emlGetMemBt(cmd, (pages - 2) * 4 + 1 + MFU_DUMP_PREFIX_LENGTH, 1);
AddCrc14A(cmd, sizeof(cmd) - 2); AddCrc14A(cmd, sizeof(cmd) - 2);
EmSendCmd(cmd, sizeof(cmd)); EmSendCmd(cmd, sizeof(cmd));
@ -2038,8 +2104,8 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
if (timer == 0) { if (timer == 0) {
timer = GetTickCount(); timer = GetTickCount();
} else { } else {
// 50ms no field --> card to idle state // 4ms no field --> card to idle state
if (GetTickCountDelta(timer) > 50) { if (GetTickCountDelta(timer) > 4) {
return 2; return 2;
} }
} }
@ -2298,9 +2364,10 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive
} }
// timeout already in ms + 100ms guard time // timeout already in ms + 100ms guard time
if (GetTickCountDelta(receive_timer) > timeout + 100) if (GetTickCountDelta(receive_timer) > timeout + 100) {
break; break;
} }
}
return false; return false;
} }
@ -2334,15 +2401,17 @@ void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing) {
} }
static uint16_t ReaderReceiveOffset(uint8_t *receivedAnswer, uint16_t offset, uint8_t *par) { static uint16_t ReaderReceiveOffset(uint8_t *receivedAnswer, uint16_t offset, uint8_t *par) {
if (!GetIso14443aAnswerFromTag(receivedAnswer, par, offset)) if (GetIso14443aAnswerFromTag(receivedAnswer, par, offset) == false) {
return 0; return 0;
}
LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false); LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false);
return Demod.len; return Demod.len;
} }
uint16_t ReaderReceive(uint8_t *receivedAnswer, uint8_t *par) { uint16_t ReaderReceive(uint8_t *receivedAnswer, uint8_t *par) {
if (!GetIso14443aAnswerFromTag(receivedAnswer, par, 0)) if (GetIso14443aAnswerFromTag(receivedAnswer, par, 0) == false) {
return 0; return 0;
}
LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false); LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false);
return Demod.len; return Demod.len;
} }
@ -2451,83 +2520,71 @@ static void iso14a_set_ATS_times(const uint8_t *ats) {
} }
} }
static int GetATQA(uint8_t *resp, uint8_t *resp_par, bool use_ecp, bool use_magsafe) {
#define ECP_DELAY 10 static int GetATQA(uint8_t *resp, uint8_t *resp_par, iso14a_polling_parameters_t *polling_parameters) {
#define ECP_RETRY_TIMEOUT 100 #define WUPA_RETRY_TIMEOUT 10
#define WUPA_RETRY_TIMEOUT 10 // 10ms
// 0x26 - REQA
// 0x52 - WAKE-UP
// 0x7A - MAGESAFE WAKE UP
uint8_t wupa[] = { ISO14443A_CMD_WUPA };
// if magsafe, set it outofbounds
if (use_magsafe) {
wupa[0] = MAGSAFE_CMD_WUPA_4;
}
if (use_ecp) {
// In case a device was already selected, we send a S-BLOCK deselect to bring it into an idle state so it can be selected again
uint8_t deselect_cmd[] = {0xc2, 0xe0, 0xb4};
ReaderTransmit(deselect_cmd, sizeof(deselect_cmd), NULL);
// Read response if present
(void) ReaderReceive(resp, resp_par);
}
uint32_t save_iso14a_timeout = iso14a_get_timeout(); uint32_t save_iso14a_timeout = iso14a_get_timeout();
iso14a_set_timeout(1236 / 128 + 1); // response to WUPA is expected at exactly 1236/fc. No need to wait longer. iso14a_set_timeout(1236 / 128 + 1); // response to WUPA is expected at exactly 1236/fc. No need to wait longer.
bool first_try = true; bool first_try = true;
uint32_t retry_timeout = use_ecp ? ECP_RETRY_TIMEOUT : WUPA_RETRY_TIMEOUT; uint32_t retry_timeout = WUPA_RETRY_TIMEOUT * polling_parameters->frame_count + polling_parameters->extra_timeout;
uint32_t start_time = GetTickCount(); uint32_t start_time = 0;
int len; int len;
// we may need several tries if we did send an unknown command or a wrong authentication before... uint8_t current_frame = 0;
do { do {
if (use_ecp && !first_try) { iso14a_polling_frame_t *frame_parameters = &polling_parameters->frames[current_frame];
uint8_t ecp[] = { 0x6a, 0x02, 0xC8, 0x01, 0x00, 0x03, 0x00, 0x02, 0x79, 0x00, 0x00, 0x00, 0x00, 0xC2, 0xD8};
ReaderTransmit(ecp, sizeof(ecp), NULL);
SpinDelay(ECP_DELAY);
}
if (use_magsafe) { if (frame_parameters->last_byte_bits == 8) {
if (wupa[0] == MAGSAFE_CMD_WUPA_4) { ReaderTransmit(frame_parameters->frame, frame_parameters->frame_length, NULL);
wupa[0] = MAGSAFE_CMD_WUPA_1;
} else { } else {
wupa[0]++; ReaderTransmitBitsPar(frame_parameters->frame, frame_parameters->last_byte_bits, NULL, NULL);
} }
if (frame_parameters->extra_delay) {
SpinDelay(frame_parameters->extra_delay);
} }
// Broadcast for a card, WUPA (0x52) will force response from all cards in the field
ReaderTransmitBitsPar(wupa, 7, NULL, NULL);
// Receive the ATQA // Receive the ATQA
len = ReaderReceive(resp, resp_par); len = ReaderReceive(resp, resp_par);
// We set the start_time here otherwise in some cases we miss the window and only ever try once
if (first_try) {
start_time = GetTickCount();
}
first_try = false; first_try = false;
// Go over frame configurations, loop back when we reach the end
current_frame = current_frame < (polling_parameters->frame_count - 1) ? current_frame + 1 : 0;
} while (len == 0 && GetTickCountDelta(start_time) <= retry_timeout); } while (len == 0 && GetTickCountDelta(start_time) <= retry_timeout);
iso14a_set_timeout(save_iso14a_timeout); iso14a_set_timeout(save_iso14a_timeout);
return len; return len;
} }
int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) { int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) {
return iso14443a_select_cardEx(uid_ptr, p_card, cuid_ptr, anticollision, num_cascades, no_rats, false, false); return iso14443a_select_cardEx(uid_ptr, p_card, cuid_ptr, anticollision, num_cascades, no_rats, &WUPA_POLLING_PARAMETERS);
} }
// performs iso14443a anticollision (optional) and card select procedure // performs iso14443a anticollision (optional) and card select procedure
// fills the uid and cuid pointer unless NULL // fills the uid and cuid pointer unless NULL
// fills the card info record unless NULL // fills the card info record unless NULL
// if anticollision is false, then the UID must be provided in uid_ptr[] // if anticollision is false, then the UID must be provided in uid_ptr[]
// and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID) // and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID)
// requests ATS unless no_rats is true // requests ATS unless no_rats is true
int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats, bool use_ecp, bool use_magsafe) { int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr,
bool anticollision, uint8_t num_cascades, bool no_rats,
iso14a_polling_parameters_t *polling_parameters) {
uint8_t resp[MAX_FRAME_SIZE] = {0}; // theoretically. A usual RATS will be much smaller uint8_t resp[MAX_FRAME_SIZE] = {0}; // theoretically. A usual RATS will be much smaller
uint8_t resp_par[MAX_PARITY_SIZE] = {0}; uint8_t resp_par[MAX_PARITY_SIZE] = {0};
uint8_t sak; // cascade uid uint8_t sak = 0; // cascade uid
bool do_cascade = 1; bool do_cascade = 1;
int cascade_level = 0; int cascade_level = 0;
@ -2537,7 +2594,7 @@ int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint
p_card->ats_len = 0; p_card->ats_len = 0;
} }
if (GetATQA(resp, resp_par, use_ecp, use_magsafe) == false) { if (GetATQA(resp, resp_par, polling_parameters) == 0) {
return 0; return 0;
} }
@ -2555,18 +2612,18 @@ int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint
uint8_t fudan_read[] = { 0x30, 0x01, 0x8B, 0xB9}; uint8_t fudan_read[] = { 0x30, 0x01, 0x8B, 0xB9};
ReaderTransmit(fudan_read, sizeof(fudan_read), NULL); ReaderTransmit(fudan_read, sizeof(fudan_read), NULL);
if (!ReaderReceive(resp, resp_par)) { if (!ReaderReceive(resp, resp_par)) {
Dbprintf("Card didn't answer to select all"); if (g_dbglevel >= DBG_INFO) Dbprintf("Card didn't answer to select all");
return 0; return 0;
} }
memcpy(p_card->uid, resp, 4); memcpy(p_card->uid, resp, 4);
// select again? // select again?
if (GetATQA(resp, resp_par, false, false) == false) { if (GetATQA(resp, resp_par, &WUPA_POLLING_PARAMETERS) == 0) {
return 0; return 0;
} }
if (GetATQA(resp, resp_par, false, false) == false) { if (GetATQA(resp, resp_par, &WUPA_POLLING_PARAMETERS) == 0) {
return 0; return 0;
} }
@ -2604,7 +2661,7 @@ int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint
// SELECT_ALL // SELECT_ALL
ReaderTransmit(sel_all, sizeof(sel_all), NULL); ReaderTransmit(sel_all, sizeof(sel_all), NULL);
if (!ReaderReceive(resp, resp_par)) { if (!ReaderReceive(resp, resp_par)) {
Dbprintf("Card didn't answer to CL%i select all", cascade_level + 1); if (g_dbglevel >= DBG_INFO) Dbprintf("Card didn't answer to CL%i select all", cascade_level + 1);
return 0; return 0;
} }
@ -2682,7 +2739,7 @@ int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint
// Receive the SAK // Receive the SAK
if (!ReaderReceive(resp, resp_par)) { if (!ReaderReceive(resp, resp_par)) {
Dbprintf("Card didn't answer to select"); if (g_dbglevel >= DBG_INFO) Dbprintf("Card didn't answer to select");
return 0; return 0;
} }
sak = resp[0]; sak = resp[0];
@ -2765,7 +2822,7 @@ int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades) {
uint8_t sak = 0x04; // cascade uid uint8_t sak = 0x04; // cascade uid
int cascade_level = 0; int cascade_level = 0;
if (!GetATQA(resp, resp_par, false, false)) { if (GetATQA(resp, resp_par, &WUPA_POLLING_PARAMETERS) == 0) {
return 0; return 0;
} }
@ -2773,10 +2830,9 @@ int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades) {
// which case we need to make a cascade 2 request and select - this is a long UID // which case we need to make a cascade 2 request and select - this is a long UID
// While the UID is not complete, the 3nd bit (from the right) is set in the SAK. // While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
for (; sak & 0x04; cascade_level++) { for (; sak & 0x04; cascade_level++) {
uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x20 };
uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
// SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97) // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97)
sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2; sel_uid[0] = ISO14443A_CMD_ANTICOLL_OR_SELECT + cascade_level * 2;
if (cascade_level < num_cascades - 1) { if (cascade_level < num_cascades - 1) {
uid_resp[0] = 0x88; uid_resp[0] = 0x88;
@ -2793,7 +2849,9 @@ int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades) {
ReaderTransmit(sel_uid, sizeof(sel_uid), NULL); ReaderTransmit(sel_uid, sizeof(sel_uid), NULL);
// Receive the SAK // Receive the SAK
if (!ReaderReceive(resp, resp_par)) return 0; if (!ReaderReceive(resp, resp_par)) {
return 0;
}
sak = resp[0]; sak = resp[0];
@ -2974,7 +3032,12 @@ void ReaderIso14443a(PacketCommandNG *c) {
// if failed selecting, turn off antenna and quite. // if failed selecting, turn off antenna and quite.
if (!(param & ISO14A_NO_SELECT)) { if (!(param & ISO14A_NO_SELECT)) {
iso14a_card_select_t *card = (iso14a_card_select_t *)buf; iso14a_card_select_t *card = (iso14a_card_select_t *)buf;
arg0 = iso14443a_select_cardEx(NULL, card, NULL, true, 0, (param & ISO14A_NO_RATS), (param & ISO14A_USE_ECP), (param & ISO14A_USE_MAGSAFE));
arg0 = iso14443a_select_cardEx(
NULL, card, NULL, true, 0, (param & ISO14A_NO_RATS),
(param & ISO14A_USE_CUSTOM_POLLING) ? (iso14a_polling_parameters_t *)cmd : &WUPA_POLLING_PARAMETERS
);
// TODO: Improve by adding a cmd parser pointer and moving it by struct length to allow combining data with polling params
FpgaDisableTracing(); FpgaDisableTracing();
reply_mix(CMD_ACK, arg0, card->uidlen, 0, buf, sizeof(iso14a_card_select_t)); reply_mix(CMD_ACK, arg0, card->uidlen, 0, buf, sizeof(iso14a_card_select_t));
@ -3037,6 +3100,9 @@ void ReaderIso14443a(PacketCommandNG *c) {
} }
} }
if ((param & ISO14A_TOPAZMODE)) {
if (cmd[0] == TOPAZ_WRITE_E8 || cmd[0] == TOPAZ_WRITE_NE8) {
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred
FpgaDisableTracing(); FpgaDisableTracing();
reply_mix(CMD_ACK, 0, 0, 0, NULL, 0); reply_mix(CMD_ACK, 0, 0, 0, NULL, 0);
@ -3045,6 +3111,23 @@ void ReaderIso14443a(PacketCommandNG *c) {
FpgaDisableTracing(); FpgaDisableTracing();
reply_old(CMD_ACK, arg0, 0, 0, buf, sizeof(buf)); reply_old(CMD_ACK, arg0, 0, 0, buf, sizeof(buf));
} }
} else {
arg0 = ReaderReceive(buf, par);
FpgaDisableTracing();
reply_old(CMD_ACK, arg0, 0, 0, buf, sizeof(buf));
}
} else {
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred
FpgaDisableTracing();
reply_mix(CMD_ACK, 0, 0, 0, NULL, 0);
} else {
arg0 = ReaderReceive(buf, par);
FpgaDisableTracing();
reply_old(CMD_ACK, arg0, 0, 0, buf, sizeof(buf));
}
}
} }
if ((param & ISO14A_REQUEST_TRIGGER)) if ((param & ISO14A_REQUEST_TRIGGER))

View file

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

View file

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

View file

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

View file

@ -177,6 +177,36 @@ static void CodeIso15693AsReaderEOF(void) {
} }
static int get_uid_slix(uint32_t start_time, uint32_t *eof_time, uint8_t *uid) {
uint8_t *answer = BigBuf_malloc(ISO15693_MAX_RESPONSE_LENGTH);
memset(answer, 0x00, ISO15693_MAX_RESPONSE_LENGTH);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
uint8_t cmd[5] = {0};
BuildIdentifyRequest(cmd);
uint16_t recvlen = 0;
SendDataTag(cmd, sizeof(cmd), false, true, answer, ISO15693_MAX_RESPONSE_LENGTH, start_time, ISO15693_READER_TIMEOUT, eof_time, &recvlen);
if (recvlen != 12) {
return PM3_ETIMEOUT;
}
uid[0] = answer[2];
uid[1] = answer[3];
uid[2] = answer[4];
uid[3] = answer[5];
uid[4] = answer[6];
uid[5] = answer[7];
uid[6] = answer[8];
uid[7] = answer[9];
BigBuf_free();
return PM3_SUCCESS;
}
// encode data using "1 out of 256" scheme // encode data using "1 out of 256" scheme
// data rate is 1,66 kbit/s (fc/8192) // data rate is 1,66 kbit/s (fc/8192)
// is designed for more robust communication over longer distances // is designed for more robust communication over longer distances
@ -262,9 +292,14 @@ void CodeIso15693AsTag(const uint8_t *cmd, size_t len) {
} }
// Transmit the command (to the tag) that was placed in cmd[]. // Transmit the command (to the tag) that was placed in cmd[].
void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time) { 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
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_FULL_MOD);
if (*start_time < DELAY_ARM_TO_TAG) { if (*start_time < DELAY_ARM_TO_TAG) {
*start_time = DELAY_ARM_TO_TAG; *start_time = DELAY_ARM_TO_TAG;
@ -1585,7 +1620,7 @@ void AcquireRawAdcSamplesIso15693(void) {
tosend_t *ts = get_tosend(); tosend_t *ts = get_tosend();
uint32_t start_time = 0; uint32_t start_time = 0;
TransmitTo15693Tag(ts->buf, ts->max, &start_time); TransmitTo15693Tag(ts->buf, ts->max, &start_time, false);
// wait for last transfer to complete // wait for last transfer to complete
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY)) ; while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY)) ;
@ -1706,14 +1741,19 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string, bool icla
// no need to try decoding reader data if the tag is sending // no need to try decoding reader data if the tag is sending
if (!tag_is_active) { if (!tag_is_active) {
if (Handle15693SampleFromReader((sniffdata & 0x02) >> 1, &dreader)) { int extra_8s = 1;
if (Handle15693SampleFromReader((sniffdata & 0x02) >> 1, &dreader) ||
(++extra_8s && Handle15693SampleFromReader(sniffdata & 0x01, &dreader))) {
uint32_t eof_time = dma_start_time + (samples * 16) + 8 - DELAY_READER_TO_ARM_SNIFF; // end of EOF
if (dreader.byteCount > 0) { if (dreader.byteCount > 0) {
// sof/eof_times are in ssp_clk, which is 13.56MHz / 4
// not sure where the extra +8's on the EOF time comes from though, if someone knows update this comment
uint32_t eof_time = dma_start_time + (samples * 16) + (extra_8s * 8) - DELAY_READER_TO_ARM_SNIFF; // end of EOF
uint32_t sof_time = eof_time uint32_t sof_time = eof_time
- dreader.byteCount * (dreader.Coding == CODING_1_OUT_OF_4 ? 128 * 16 : 2048 * 16) // time for byte transfers - dreader.byteCount * (dreader.Coding == CODING_1_OUT_OF_4 ? 1024 : 16384) // time for byte transfers
- 32 * 16 // time for SOF transfer - 256 // time for SOF transfer (1024/fc / 4)
- 16 * 16; // time for EOF transfer - 128; // time for EOF transfer (512/fc / 4)
// sof/eof_times * 4 here to bring from ssp_clk freq to RF carrier freq
LogTrace_ISO15693(dreader.output, dreader.byteCount, (sof_time * 4), (eof_time * 4), NULL, true); LogTrace_ISO15693(dreader.output, dreader.byteCount, (sof_time * 4), (eof_time * 4), NULL, true);
if (!iclass) { // Those flags don't exist in iClass if (!iclass) { // Those flags don't exist in iClass
@ -1721,52 +1761,38 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string, bool icla
expect_fast_answer = dreader.output[0] & ISO15_REQ_DATARATE_HIGH; expect_fast_answer = dreader.output[0] & ISO15_REQ_DATARATE_HIGH;
} }
} }
// And ready to receive another command. // And ready to receive another command.
//DecodeReaderReset(&dreader); // already reseted //DecodeReaderReset(&dreader); // already reseted
DecodeTagReset(&dtag); DecodeTagReset(&dtag);
DecodeTagFSKReset(&dtagfsk); DecodeTagFSKReset(&dtagfsk);
reader_is_active = false; reader_is_active = false;
expect_tag_answer = true; expect_tag_answer = true;
} else if (Handle15693SampleFromReader(sniffdata & 0x01, &dreader)) {
uint32_t eof_time = dma_start_time + (samples * 16) + 16 - DELAY_READER_TO_ARM_SNIFF; // end of EOF
if (dreader.byteCount > 0) {
uint32_t sof_time = eof_time
- dreader.byteCount * (dreader.Coding == CODING_1_OUT_OF_4 ? 128 * 16 : 2048 * 16) // time for byte transfers
- 32 * 16 // time for SOF transfer
- 16 * 16; // time for EOF transfer
LogTrace_ISO15693(dreader.output, dreader.byteCount, (sof_time * 4), (eof_time * 4), NULL, true);
if (!iclass) { // Those flags don't exist in iClass
expect_fsk_answer = dreader.output[0] & ISO15_REQ_SUBCARRIER_TWO;
expect_fast_answer = dreader.output[0] & ISO15_REQ_DATARATE_HIGH;
}
}
// And ready to receive another command
//DecodeReaderReset(&dreader); // already reseted
DecodeTagReset(&dtag);
DecodeTagFSKReset(&dtagfsk);
reader_is_active = false;
expect_tag_answer = true;
} else { } else {
reader_is_active = (dreader.state >= STATE_READER_RECEIVE_DATA_1_OUT_OF_4); reader_is_active = (dreader.state >= STATE_READER_RECEIVE_DATA_1_OUT_OF_4);
} }
} }
if (!reader_is_active && expect_tag_answer) { // no need to try decoding tag data if the reader is currently sending or no answer expected yet // no need to try decoding tag data if the reader is currently sending or no answer expected yet
if (!reader_is_active && expect_tag_answer) {
if (!expect_fsk_answer) { if (!expect_fsk_answer) {
// single subcarrier tag response
if (Handle15693SamplesFromTag((sniffdata >> 4) << 2, &dtag, expect_fast_answer)) { if (Handle15693SamplesFromTag((sniffdata >> 4) << 2, &dtag, expect_fast_answer)) {
// sof/eof_times are in ssp_clk, which is 13.56MHz / 4
uint32_t eof_time = dma_start_time + (samples * 16) - DELAY_TAG_TO_ARM_SNIFF; // end of EOF uint32_t eof_time = dma_start_time + (samples * 16) - DELAY_TAG_TO_ARM_SNIFF; // end of EOF
if (dtag.lastBit == SOF_PART2) { if (dtag.lastBit == SOF_PART2) {
eof_time -= (8 * 16); // needed 8 additional samples to confirm single SOF (iCLASS) eof_time -= (8 * 16); // needed 8 additional samples to confirm single SOF (iCLASS)
} }
uint32_t sof_time = eof_time uint32_t sof_time = eof_time
- dtag.len * 8 * 8 * 16 // time for byte transfers - dtag.len * 1024 // time for byte transfers (4096/fc / 4)
- (32 * 16) // time for SOF transfer - 512 // time for SOF transfer (2048/fc / 4)
- (dtag.lastBit != SOF_PART2 ? (32 * 16) : 0); // time for EOF transfer - (dtag.lastBit != SOF_PART2 ? 512 : 0); // time for EOF transfer (2048/fc / 4)
// sof/eof_times * 4 here to bring from ssp_clk freq to RF carrier freq
LogTrace_ISO15693(dtag.output, dtag.len, (sof_time * 4), (eof_time * 4), NULL, false); LogTrace_ISO15693(dtag.output, dtag.len, (sof_time * 4), (eof_time * 4), NULL, false);
// And ready to receive another response. // And ready to receive another response.
DecodeTagReset(&dtag); DecodeTagReset(&dtag);
DecodeTagFSKReset(&dtagfsk); DecodeTagFSKReset(&dtagfsk);
@ -1777,26 +1803,23 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string, bool icla
tag_is_active = (dtag.state >= STATE_TAG_RECEIVING_DATA); tag_is_active = (dtag.state >= STATE_TAG_RECEIVING_DATA);
} }
} else { } else {
// dual subcarrier tag response
if (FREQ_IS_0((sniffdata >> 2) & 0x3)) // tolerate 1 00 if (FREQ_IS_0((sniffdata >> 2) & 0x3)) // tolerate 1 00
sniffdata = sniffdata_prev; sniffdata = sniffdata_prev;
if (Handle15693FSKSamplesFromTag((sniffdata >> 2) & 0x3, &dtagfsk, expect_fast_answer)) { if (Handle15693FSKSamplesFromTag((sniffdata >> 2) & 0x3, &dtagfsk, expect_fast_answer)) {
expect_fsk_answer = false;
} else {
tag_is_active = (dtagfsk.state >= STATE_FSK_RECEIVING_DATA_484);
}
if (!expect_fsk_answer) {
// FSK answer no more expected: switch back to ASK
if (dtagfsk.len > 0) { if (dtagfsk.len > 0) {
// sof/eof_times are in ssp_clk, which is 13.56MHz / 4
uint32_t eof_time = dma_start_time + (samples * 16) - DELAY_TAG_TO_ARM_SNIFF; // end of EOF uint32_t eof_time = dma_start_time + (samples * 16) - DELAY_TAG_TO_ARM_SNIFF; // end of EOF
if (dtagfsk.lastBit == SOF) { if (dtagfsk.lastBit == SOF) {
eof_time -= (8 * 16); // needed 8 additional samples to confirm single SOF (iCLASS) eof_time -= (8 * 16); // needed 8 additional samples to confirm single SOF (iCLASS)
} }
uint32_t sof_time = eof_time uint32_t sof_time = eof_time
- dtagfsk.len * 8 * 8 * 16 // time for byte transfers - dtagfsk.len * 1016 // time for byte transfers (4064/fc / 4) - FSK is slightly different
- (32 * 16) // time for SOF transfer - 512 // time for SOF transfer (2048/fc / 4)
- (dtagfsk.lastBit != SOF ? (32 * 16) : 0); // time for EOF transfer - (dtagfsk.lastBit != SOF ? 512 : 0); // time for EOF transfer (2048/fc / 4)
// sof/eof_times * 4 here to bring from ssp_clk freq to RF carrier freq
LogTrace_ISO15693(dtagfsk.output, dtagfsk.len, (sof_time * 4), (eof_time * 4), NULL, false); LogTrace_ISO15693(dtagfsk.output, dtagfsk.len, (sof_time * 4), (eof_time * 4), NULL, false);
} }
@ -1804,6 +1827,10 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string, bool icla
DecodeReaderReset(&dreader); DecodeReaderReset(&dreader);
expect_tag_answer = false; expect_tag_answer = false;
tag_is_active = false; tag_is_active = false;
// FSK answer no more expected: switch back to ASK
expect_fsk_answer = false;
} else {
tag_is_active = (dtagfsk.state >= STATE_FSK_RECEIVING_DATA_484);
} }
} }
} }
@ -1813,20 +1840,20 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string, bool icla
switch_off(); switch_off();
DbpString(""); DbpString("");
if (g_dbglevel > DBG_ERROR) {
DbpString(_CYAN_("Sniff statistics")); DbpString(_CYAN_("Sniff statistics"));
DbpString("================================="); DbpString("=================================");
Dbprintf(" DecodeTag State........%d", dtag.state); Dbprintf("DecodeTag State........ %d", dtag.state);
Dbprintf(" DecodeTag byteCnt......%d", dtag.len); Dbprintf("DecodeTag byteCnt...... %d", dtag.len);
Dbprintf(" DecodeTag posCount.....%d", dtag.posCount); Dbprintf("DecodeTag posCount..... %d", dtag.posCount);
Dbprintf(" DecodeTagFSK State.....%d", dtagfsk.state); Dbprintf("DecodeTagFSK State..... %d", dtagfsk.state);
Dbprintf(" DecodeTagFSK byteCnt...%d", dtagfsk.len); Dbprintf("DecodeTagFSK byteCnt... %d", dtagfsk.len);
Dbprintf(" DecodeTagFSK count.....%d", dtagfsk.count); Dbprintf("DecodeTagFSK count..... %d", dtagfsk.count);
Dbprintf(" DecodeReader State.....%d", dreader.state); Dbprintf("DecodeReader State..... %d", dreader.state);
Dbprintf(" DecodeReader byteCnt...%d", dreader.byteCount); Dbprintf("DecodeReader byteCnt... %d", dreader.byteCount);
Dbprintf(" DecodeReader posCount..%d", dreader.posCount); Dbprintf("DecodeReader posCount.. %d", dreader.posCount);
Dbprintf(" Trace length..........." _YELLOW_("%d"), BigBuf_get_traceLen()); }
DbpString(""); Dbprintf("Trace length........... " _YELLOW_("%d"), BigBuf_get_traceLen());
} }
// Initialize Proxmark3 as ISO15693 reader // Initialize Proxmark3 as ISO15693 reader
@ -1899,7 +1926,7 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, bool speed_fast, uint8_t
} }
tosend_t *ts = get_tosend(); tosend_t *ts = get_tosend();
TransmitTo15693Tag(ts->buf, ts->max, &start_time); TransmitTo15693Tag(ts->buf, ts->max, &start_time, false);
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred
*resp_len = 0; *resp_len = 0;
@ -1922,7 +1949,7 @@ int SendDataTagEOF(uint8_t *recv, uint16_t max_recv_len, uint32_t start_time, ui
CodeIso15693AsReaderEOF(); CodeIso15693AsReaderEOF();
tosend_t *ts = get_tosend(); tosend_t *ts = get_tosend();
TransmitTo15693Tag(ts->buf, ts->max, &start_time); TransmitTo15693Tag(ts->buf, ts->max, &start_time, false);
uint32_t end_time = start_time + 32 * (8 * ts->max - 4); // subtract the 4 padding bits after EOF uint32_t end_time = start_time + 32 * (8 * ts->max - 4); // subtract the 4 padding bits after EOF
LogTrace_ISO15693(NULL, 0, (start_time * 4), (end_time * 4), NULL, true); LogTrace_ISO15693(NULL, 0, (start_time * 4), (end_time * 4), NULL, true);
@ -2097,7 +2124,6 @@ void Iso15693InitTag(void) {
StartCountSspClk(); StartCountSspClk();
} }
void EmlClearIso15693(void) { void EmlClearIso15693(void) {
// Resetting the bitstream also frees the BigBuf memory, so we do this here to prevent // Resetting the bitstream also frees the BigBuf memory, so we do this here to prevent
// an inconvenient reset in the future by Iso15693InitTag // an inconvenient reset in the future by Iso15693InitTag
@ -2106,16 +2132,6 @@ void EmlClearIso15693(void) {
reply_ng(CMD_HF_ISO15693_EML_CLEAR, PM3_SUCCESS, NULL, 0); reply_ng(CMD_HF_ISO15693_EML_CLEAR, PM3_SUCCESS, NULL, 0);
} }
void EmlSetMemIso15693(uint8_t count, uint8_t *data, uint32_t offset) {
uint8_t *emCARD = BigBuf_get_EM_addr();
memcpy(emCARD + offset, data, count);
}
void EmlGetMemIso15693(uint8_t count, uint8_t *output, uint32_t offset) {
uint8_t *emCARD = BigBuf_get_EM_addr();
memcpy(output, emCARD + offset, count);
}
// Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands // Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
// all demodulation performed in arm rather than host. - greg // all demodulation performed in arm rather than host. - greg
void SimTagIso15693(uint8_t *uid, uint8_t block_size) { void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
@ -2274,8 +2290,11 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
} }
// Block data // Block data
if (block_size * (block_idx + j + 1) <= CARD_MEMORY_SIZE) { if (block_size * (block_idx + j + 1) <= CARD_MEMORY_SIZE) {
EmlGetMemIso15693(block_size, resp_readblock + (work_offset + security_offset), emlGet(
block_size * (block_idx + j)); resp_readblock + (work_offset + security_offset),
block_size * (block_idx + j),
block_size
);
} else { } else {
memset(resp_readblock + work_offset + security_offset, 0, block_size); memset(resp_readblock + work_offset + security_offset, 0, block_size);
} }
@ -2312,7 +2331,7 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
uint8_t *data = cmd + 3 + address_offset + multi_offset; uint8_t *data = cmd + 3 + address_offset + multi_offset;
// write data // write data
EmlSetMemIso15693(block_count * block_size, data, block_idx * block_size); emlSet(data, (block_idx * block_size), (block_count * block_size));
// Build WRITE_(MULTI_)BLOCK response // Build WRITE_(MULTI_)BLOCK response
int response_length = 3; int response_length = 3;
@ -2431,6 +2450,8 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint
case ISO15693_WRITE_AFI: case ISO15693_WRITE_AFI:
case ISO15693_LOCK_AFI: case ISO15693_LOCK_AFI:
case ISO15693_WRITE_DSFID: case ISO15693_WRITE_DSFID:
case ISO15693_WRITE_PASSWORD:
case ISO15693_PASSWORD_PROTECT_EAS:
case ISO15693_LOCK_DSFID: case ISO15693_LOCK_DSFID:
timeout = ISO15693_READER_TIMEOUT_WRITE; timeout = ISO15693_READER_TIMEOUT_WRITE;
request_answer = data[0] & ISO15_REQ_OPTION; request_answer = data[0] & ISO15_REQ_OPTION;
@ -2640,7 +2661,7 @@ void SetTag15693Uid(const uint8_t *uid) {
switch_off(); switch_off();
} }
static void init_password_15693_slixl(uint8_t *buffer, uint8_t *pwd, const uint8_t *rnd) { static void init_password_15693_Slix(uint8_t *buffer, const uint8_t *pwd, const uint8_t *rnd) {
memcpy(buffer, pwd, 4); memcpy(buffer, pwd, 4);
if (rnd) { if (rnd) {
buffer[0] ^= rnd[0]; buffer[0] ^= rnd[0];
@ -2650,14 +2671,14 @@ static void init_password_15693_slixl(uint8_t *buffer, uint8_t *pwd, const uint8
} }
} }
static bool get_rnd_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t *rnd) { static bool get_rnd_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *rnd) {
// 0x04, == NXP from manufacture id list. // 0x04, == NXP from manufacture id list.
uint8_t c[] = {ISO15_REQ_DATARATE_HIGH, ISO15693_GET_RANDOM_NUMBER, 0x04, 0x00, 0x00 }; uint8_t c[] = {ISO15_REQ_DATARATE_HIGH, ISO15693_GET_RANDOM_NUMBER, 0x04, 0x00, 0x00 };
AddCrc15(c, 3); AddCrc15(c, 3);
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint16_t recvlen = 0; uint16_t recvlen = 0;
int res = SendDataTag(c, sizeof(c), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen); int res = SendDataTag(c, sizeof(c), true, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen);
if (res != PM3_SUCCESS && recvlen != 5) { if (res != PM3_SUCCESS && recvlen != 5) {
return false; return false;
} }
@ -2668,15 +2689,16 @@ static bool get_rnd_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t
return true; return true;
} }
static uint32_t set_pass_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t pass_id, uint8_t *password) { static uint32_t disable_privacy_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t pass_id, const uint8_t *password) {
uint8_t rnd[2]; uint8_t rnd[2];
if (get_rnd_15693_slixl(start_time, eof_time, rnd) == false) { if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
// 0x04, == NXP from manufacture id list. // 0x04, == NXP from manufacture id list.
uint8_t c[] = {ISO15_REQ_DATARATE_HIGH, ISO15693_SET_PASSWORD, 0x04, pass_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t c[] = { ISO15_REQ_DATARATE_HIGH, ISO15693_SET_PASSWORD, 0x04, pass_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
init_password_15693_slixl(&c[4], password, rnd); init_password_15693_Slix(&c[4], password, rnd);
AddCrc15(c, 8); AddCrc15(c, 8);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
@ -2689,16 +2711,226 @@ static uint32_t set_pass_15693_slixl(uint32_t start_time, uint32_t *eof_time, ui
return PM3_SUCCESS; return PM3_SUCCESS;
} }
/* static uint32_t set_pass_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t pass_id, const uint8_t *password, uint8_t *uid) {
static uint32_t enable_privacy_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t pass_id, uint8_t *password) {
uint8_t rnd[2]; uint8_t rnd[2];
if (get_rnd_15693_slixl(start_time, eof_time, rnd) == false) { if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT;
}
// 0x04, == NXP from manufacture id list.
uint8_t c[] = { (ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS), ISO15693_SET_PASSWORD, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, pass_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
init_password_15693_Slix(&c[12], password, rnd);
memcpy(&c[3], uid, 8);
AddCrc15(c, 16);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint16_t recvlen = 0;
int res = SendDataTag(c, sizeof(c), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen);
if (res != PM3_SUCCESS && recvlen != 3) {
return PM3_EWRONGANSWER;
}
return PM3_SUCCESS;
}
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;
}
// 0x04, == NXP from manufacture id list.
uint8_t c[] = { ISO15_REQ_DATARATE_HIGH, 0xBA, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
init_password_15693_Slix(&c[3], password, rnd);
AddCrc15(c, 7);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint16_t recvlen = 0;
int res = SendDataTag(c, sizeof(c), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen);
if (res != PM3_SUCCESS && recvlen != 3) {
return PM3_EWRONGANSWER;
}
return PM3_SUCCESS;
}
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);
uint8_t rnd[2];
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT;
}
if (usepwd) {
int res_setpass = set_pass_15693_Slix(start_time, eof_time, 0x10, password, uid);
if (res_setpass != PM3_SUCCESS) {
return PM3_EWRONGANSWER;
}
}
// 0x04, == NXP from manufacture id list.
uint8_t c[] = { ISO15_REQ_DATARATE_HIGH, 0xA3, 0x04, 0x00, 0x00};
AddCrc15(c, 3);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint16_t recvlen = 0;
int res = SendDataTag(c, sizeof(c), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen);
if (res != PM3_SUCCESS && recvlen != 3) {
return PM3_EWRONGANSWER;
}
return PM3_SUCCESS;
}
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);
uint8_t rnd[2];
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT;
}
if (usepwd) {
int res_setpass = set_pass_15693_Slix(start_time, eof_time, 0x10, password, uid);
if (res_setpass != PM3_SUCCESS) {
return PM3_EWRONGANSWER;
}
}
// 0x04, == NXP from manufacture id list.
uint8_t c[] = { ISO15_REQ_DATARATE_HIGH, 0xA2, 0x04, 0x00, 0x00};
//init_password_15693_Slix(&c[3], password, rnd);
AddCrc15(c, 3);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint16_t recvlen = 0;
int res = SendDataTag(c, sizeof(c), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen);
if (res != PM3_SUCCESS && recvlen != 3) {
return PM3_EWRONGANSWER;
}
return PM3_SUCCESS;
}
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};
memcpy(&new_pwd_cmd[3], uid, 8);
memcpy(&new_pwd_cmd[12], password, 4);
AddCrc15(new_pwd_cmd, 16);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint16_t recvlen = 0;
int res_wrp = SendDataTag(new_pwd_cmd, sizeof(new_pwd_cmd), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen);
if (res_wrp != PM3_SUCCESS && recvlen != 3) {
return PM3_EWRONGANSWER;
}
return PM3_SUCCESS;
}
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;
if (set_option_flag)
flags = ISO15_REQ_DATARATE_HIGH | ISO15_REQ_OPTION;
else
flags = ISO15_REQ_DATARATE_HIGH;
uint8_t uid[8];
get_uid_slix(start_time, eof_time, uid);
uint8_t rnd[2];
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT;
}
int res_setpass = set_pass_15693_Slix(start_time, eof_time, 0x10, password, uid);
if (res_setpass != PM3_SUCCESS) {
return PM3_EWRONGANSWER;
}
uint8_t new_pass_protect_cmd[] = { flags, ISO15693_PASSWORD_PROTECT_EAS, 0x04, 0x00, 0x00};
AddCrc15(new_pass_protect_cmd, 3);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint16_t recvlen = 0;
int res = SendDataTag(new_pass_protect_cmd, sizeof(new_pass_protect_cmd), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen);
if (res != PM3_SUCCESS && recvlen != 3) {
return PM3_EWRONGANSWER;
}
return PM3_SUCCESS;
}
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);
if (res_getuid != PM3_SUCCESS) {
return res_getuid;
}
}
if (usepwd) {
int res_setpass = set_pass_15693_Slix(start_time, eof_time, 0x10, password, uid);
if (res_setpass != PM3_SUCCESS) {
return PM3_EWRONGANSWER;
}
}
uint8_t cmd[] = { ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS, ISO15693_WRITE_AFI, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
memcpy(&cmd[2], uid, 8);
cmd[10] = afi;
AddCrc15(cmd, 11);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint16_t recvlen = 0;
int res = SendDataTag(cmd, sizeof(cmd), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen);
if (res != PM3_SUCCESS || recvlen != 3) {
return PM3_EWRONGANSWER;
}
return PM3_SUCCESS;
}
/*
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; return PM3_ETIMEOUT;
} }
uint8_t c[] = {ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS, ISO15693_ENABLE_PRIVACY, pass_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t c[] = {ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS, ISO15693_ENABLE_PRIVACY, pass_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
memcpy(&c[3], uid, 8); memcpy(&c[3], uid, 8);
init_password_15693_slixl(&c[11], password, rnd); init_password_15693_Slix(&c[11], password, rnd);
AddCrc15(c, 15); AddCrc15(c, 15);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
@ -2711,16 +2943,16 @@ static uint32_t enable_privacy_15693_slixl(uint32_t start_time, uint32_t *eof_ti
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static uint32_t write_password_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t pass_id, uint8_t *password) { static uint32_t write_password_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t pass_id, const uint8_t *password) {
uint8_t rnd[2]; uint8_t rnd[2];
if (get_rnd_15693_slixl(start_time, eof_time, rnd) == false) { if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
uint8_t c[] = {ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS, ISO15693_WRITE_PASSWORD, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t c[] = {ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS, ISO15693_WRITE_PASSWORD, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
memcpy(&c[3], uid, 8); memcpy(&c[3], uid, 8);
c[11] = pass_id; c[11] = pass_id;
init_password_15693_slixl(&c[12], password, NULL); init_password_15693_Slix(&c[12], password, NULL);
AddCrc15(c, 16); AddCrc15(c, 16);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
@ -2734,16 +2966,16 @@ static uint32_t write_password_15693_slixl(uint32_t start_time, uint32_t *eof_ti
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static uint32_t destroy_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t *password) { static uint32_t destroy_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, const uint8_t *password) {
uint8_t rnd[2]; uint8_t rnd[2];
if (get_rnd_15693_slixl(start_time, eof_time, rnd) == false) { if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
uint8_t c[] = {ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS, ISO15693_DESTROY, ISO15693_ENABLE_PRIVACY, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t c[] = {ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS, ISO15693_DESTROY, ISO15693_ENABLE_PRIVACY, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
memcpy(&c[3], uid, 8); memcpy(&c[3], uid, 8);
init_password_15693_slixl(&c[11], password, rnd); init_password_15693_Slix(&c[11], password, rnd);
AddCrc15(c, 15); AddCrc15(c, 15);
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
@ -2758,8 +2990,32 @@ static uint32_t destroy_15693_slixl(uint32_t start_time, uint32_t *eof_time, uin
*/ */
// Sets a PRIVACY password to all ZEROS void WritePasswordSlixIso15693(const uint8_t *old_password, const uint8_t *new_password, uint8_t pwd_id) {
void DisablePrivacySlixLIso15693(uint8_t *password) { LED_D_ON();
Iso15693InitReader();
StartCountSspClk();
uint32_t start_time = 0, eof_time = 0;
int res = PM3_EFAILED;
uint8_t uid[8];
get_uid_slix(start_time, &eof_time, uid);
res = set_pass_15693_Slix(start_time, &eof_time, pwd_id, old_password, uid);
if (res != PM3_SUCCESS) {
reply_ng(CMD_HF_ISO15693_SLIX_WRITE_PWD, res, NULL, 0);
switch_off();
return;
}
res = write_password_15693_Slix(start_time, &eof_time, pwd_id, new_password, uid);
reply_ng(CMD_HF_ISO15693_SLIX_WRITE_PWD, res, NULL, 0);
switch_off();
}
void DisablePrivacySlixIso15693(const uint8_t *password) {
LED_D_ON(); LED_D_ON();
Iso15693InitReader(); Iso15693InitReader();
StartCountSspClk(); StartCountSspClk();
@ -2769,13 +3025,12 @@ void DisablePrivacySlixLIso15693(uint8_t *password) {
// 0x04 Privacy // 0x04 Privacy
// 0x08 Destroy SLIX-L // 0x08 Destroy SLIX-L
// 0x10 EAS/AFI // 0x10 EAS/AFI
int res = set_pass_15693_slixl(start_time, &eof_time, 0x04, password); int res = disable_privacy_15693_Slix(start_time, &eof_time, 0x04, password);
reply_ng(CMD_HF_ISO15693_SLIX_L_DISABLE_PRIVACY, res, NULL, 0); reply_ng(CMD_HF_ISO15693_SLIX_DISABLE_PRIVACY, res, NULL, 0);
switch_off(); switch_off();
} }
// Sets a EAS/AFI password to all ZEROS void EnablePrivacySlixIso15693(const uint8_t *password) {
void DisableEAS_AFISlixLIso15693(uint8_t *password) {
LED_D_ON(); LED_D_ON();
Iso15693InitReader(); Iso15693InitReader();
StartCountSspClk(); StartCountSspClk();
@ -2785,8 +3040,71 @@ void DisableEAS_AFISlixLIso15693(uint8_t *password) {
// 0x04 Privacy // 0x04 Privacy
// 0x08 Destroy SLIX-L // 0x08 Destroy SLIX-L
// 0x10 EAS/AFI // 0x10 EAS/AFI
int res = set_pass_15693_slixl(start_time, &eof_time, 0x10, password); int res = set_privacy_15693_Slix(start_time, &eof_time, password);
reply_ng(CMD_HF_ISO15693_SLIX_L_DISABLE_AESAFI, res, NULL, 0); reply_ng(CMD_HF_ISO15693_SLIX_ENABLE_PRIVACY, res, NULL, 0);
switch_off(); switch_off();
} }
void DisableEAS_AFISlixIso15693(const uint8_t *password, bool usepwd) {
LED_D_ON();
Iso15693InitReader();
StartCountSspClk();
uint32_t start_time = 0, eof_time = 0;
// Password identifier Password byte
// 0x04 Privacy
// 0x08 Destroy SLIX-L
// 0x10 EAS/AFI
int res = disable_eas_15693_Slix(start_time, &eof_time, password, usepwd);
reply_ng(CMD_HF_ISO15693_SLIX_DISABLE_EAS, res, NULL, 0);
switch_off();
}
void EnableEAS_AFISlixIso15693(const uint8_t *password, bool usepwd) {
LED_D_ON();
Iso15693InitReader();
StartCountSspClk();
uint32_t start_time = 0, eof_time = 0;
// Password identifier Password byte
// 0x04 Privacy
// 0x08 Destroy SLIX-L
// 0x10 EAS/AFI
int res = enable_eas_15693_Slix(start_time, &eof_time, password, usepwd);
reply_ng(CMD_HF_ISO15693_SLIX_ENABLE_EAS, res, NULL, 0);
switch_off();
}
void PassProtextEASSlixIso15693(const uint8_t *password) {
LED_D_ON();
Iso15693InitReader();
StartCountSspClk();
uint32_t start_time = 0, eof_time = 0;
int res = pass_protect_EASAFI_15693_Slix(start_time, &eof_time, false, password);
reply_ng(CMD_HF_ISO15693_SLIX_PASS_PROTECT_EAS, res, NULL, 0);
switch_off();
}
void PassProtectAFISlixIso15693(const uint8_t *password) {
LED_D_ON();
Iso15693InitReader();
StartCountSspClk();
uint32_t start_time = 0, eof_time = 0;
int res = pass_protect_EASAFI_15693_Slix(start_time, &eof_time, true, password);
reply_ng(CMD_HF_ISO15693_SLIX_PASS_PROTECT_AFI, res, NULL, 0);
switch_off();
}
void WriteAFIIso15693(const uint8_t *password, bool use_pwd, uint8_t *uid, bool use_uid, uint8_t afi) {
LED_D_ON();
Iso15693InitReader();
StartCountSspClk();
uint32_t start_time = 0, eof_time = 0;
int res = write_afi_15693(start_time, &eof_time, password, use_pwd, uid, use_uid, afi);
//int res = PM3_SUCCESS;
reply_ng(CMD_HF_ISO15693_WRITE_AFI, res, NULL, 0);
switch_off();
}

View file

@ -40,15 +40,13 @@ void CodeIso15693AsTag(const uint8_t *cmd, size_t len);
void TransmitTo15693Reader(const uint8_t *cmd, size_t len, uint32_t *start_time, uint32_t slot_time, bool slow); void TransmitTo15693Reader(const uint8_t *cmd, size_t len, uint32_t *start_time, uint32_t slot_time, bool slow);
int GetIso15693CommandFromReader(uint8_t *received, size_t max_len, uint32_t *eof_time); int GetIso15693CommandFromReader(uint8_t *received, size_t max_len, uint32_t *eof_time);
void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time); void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time, bool shallow_mod);
int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeout, uint32_t *eof_time, bool fsk, bool recv_speed, uint16_t *resp_len); int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeout, uint32_t *eof_time, bool fsk, bool recv_speed, uint16_t *resp_len);
//void RecordRawAdcSamplesIso15693(void); //void RecordRawAdcSamplesIso15693(void);
void AcquireRawAdcSamplesIso15693(void); void AcquireRawAdcSamplesIso15693(void);
void ReaderIso15693(iso15_card_select_t *p_card); // ISO15693 reader void ReaderIso15693(iso15_card_select_t *p_card); // ISO15693 reader
void EmlClearIso15693(void); void EmlClearIso15693(void);
void EmlSetMemIso15693(uint8_t count, uint8_t *data, uint32_t offset);
void EmlGetMemIso15693(uint8_t count, uint8_t *output, uint32_t offset);
void SimTagIso15693(uint8_t *uid, uint8_t block_size); // simulate an ISO15693 tag void SimTagIso15693(uint8_t *uid, uint8_t block_size); // simulate an ISO15693 tag
void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag
void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI
@ -62,6 +60,12 @@ int SendDataTagEOF(uint8_t *recv, uint16_t max_recv_len, uint32_t start_time, ui
void SetTag15693Uid(const uint8_t *uid); void SetTag15693Uid(const uint8_t *uid);
void DisablePrivacySlixLIso15693(uint8_t *password); void WritePasswordSlixIso15693(const uint8_t *old_password, const uint8_t *new_password, uint8_t pwd_id);
void DisableEAS_AFISlixLIso15693(uint8_t *password); 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 #endif

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -94,7 +94,7 @@ void setDefaultSamplingConfig(void) {
* @brief setSamplingConfig * @brief setSamplingConfig
* @param sc * @param sc
*/ */
void setSamplingConfig(sample_config *sc) { void setSamplingConfig(const sample_config *sc) {
// decimation (1-8) how many bits of adc sample value to save // decimation (1-8) how many bits of adc sample value to save
if (sc->decimation > 0 && sc->decimation < 9) if (sc->decimation > 0 && sc->decimation < 9)
@ -296,7 +296,9 @@ void LFSetupFPGAForADC(int divisor, bool reader_field) {
uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, int16_t trigger_threshold, uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, int16_t trigger_threshold,
bool verbose, uint32_t sample_size, uint32_t cancel_after, int32_t samples_to_skip, bool ledcontrol) { bool verbose, uint32_t sample_size, uint32_t cancel_after, int32_t samples_to_skip, bool ledcontrol) {
initSampleBuffer(&sample_size); initSampleBuffer(&sample_size); // sample size in bytes
sample_size <<= 3; // sample size in bits
sample_size /= bits_per_sample; // sample count
if (g_dbglevel >= DBG_DEBUG) { if (g_dbglevel >= DBG_DEBUG) {
printSamples(); printSamples();
@ -368,8 +370,11 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
} }
// Ensure that DC offset removal and noise check is performed for any device-side processing // Ensure that DC offset removal and noise check is performed for any device-side processing
if (bits_per_sample == 8) {
// these functions only consider bps==8
removeSignalOffset(data.buffer, samples.total_saved); removeSignalOffset(data.buffer, samples.total_saved);
computeSignalProperties(data.buffer, samples.total_saved); computeSignalProperties(data.buffer, samples.total_saved);
}
return data.numbits; return data.numbits;
} }
/** /**

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

@ -19,19 +19,18 @@
#include "common.h" #include "common.h"
void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain); int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_cmd, uint8_t block_no, uint8_t count, uint8_t *block_data);
int16_t mifare_cmd_writeblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t write_cmd, uint8_t block_no, uint8_t count, uint8_t *block_data);
void MifareReadSector(uint8_t sector_no, uint8_t key_type, uint8_t *key);
void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes); void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes);
void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain); void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareUWriteBlockCompat(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareUWriteBlockCompat(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, bool calibrate, uint8_t *key);
void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, bool calibrate, uint8_t *key);
void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, uint8_t *key); void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, uint8_t *key);
void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain); void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
@ -41,16 +40,17 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
void MifareChkKeys_file(uint8_t *fn); void MifareChkKeys_file(uint8_t *fn);
void MifareEMemClr(void); void MifareEMemClr(void);
void MifareEMemSet(uint8_t blockno, uint8_t blockcnt, uint8_t blockwidth, uint8_t *datain);
void MifareEMemGet(uint8_t blockno, uint8_t blockcnt); void MifareEMemGet(uint8_t blockno, uint8_t blockcnt);
int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype); int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype);
int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype); int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype);
// MFC GEN1a /1b
void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card
void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain);
void MifareCIdent(bool is_mfc); // is "magic chinese" card? void MifareCIdent(bool is_mfc); // is "magic chinese" card?
void MifareHasStaticNonce(void); // Has the tag a static nonce? void MifareHasStaticNonce(void); // Has the tag a static nonce?
// MFC GEN3
int DoGen3Cmd(uint8_t *cmd, uint8_t cmd_len); int DoGen3Cmd(uint8_t *cmd, uint8_t cmd_len);
void MifareGen3UID(uint8_t uidlen, uint8_t *uid); // Gen 3 magic card set UID without manufacturer block void MifareGen3UID(uint8_t uidlen, uint8_t *uid); // Gen 3 magic card set UID without manufacturer block
void MifareGen3Blk(uint8_t block_len, uint8_t *block); // Gen 3 magic card overwrite manufacturer block void MifareGen3Blk(uint8_t block_len, uint8_t *block); // Gen 3 magic card overwrite manufacturer block

View file

@ -139,6 +139,7 @@ void MifareDesfireGetInformation(void) {
uint8_t details[14]; uint8_t details[14];
} PACKED payload; } PACKED payload;
memset(&payload, 0x00, sizeof(payload));
/* /*
1 = PCB 1 1 = PCB 1
2 = cid 2 2 = cid 2
@ -181,6 +182,12 @@ void MifareDesfireGetInformation(void) {
return; return;
} }
if (len < sizeof(payload.versionHW) + 1) {
Dbprintf("Tag answer to MFDES_GET_VERSION was too short: data in Hardware Information is probably invalid.");
print_result("Answer", resp, len);
memset(resp + len, 0xFF, sizeof(payload.versionHW) + 1 - len); // clear remaining bytes
}
memcpy(payload.versionHW, resp + 1, sizeof(payload.versionHW)); memcpy(payload.versionHW, resp + 1, sizeof(payload.versionHW));
// ADDITION_FRAME 1 // ADDITION_FRAME 1
@ -193,6 +200,13 @@ void MifareDesfireGetInformation(void) {
switch_off(); switch_off();
return; return;
} }
if (len < sizeof(payload.versionSW) + 1) {
Dbprintf("Tag answer to MFDES_ADDITIONAL_FRAME 1 was too short: data in Software Information is probably invalid.");
print_result("Answer", resp, len);
memset(resp + len, 0xFF, sizeof(payload.versionSW) + 1 - len); // clear remaining bytes
}
memcpy(payload.versionSW, resp + 1, sizeof(payload.versionSW)); memcpy(payload.versionSW, resp + 1, sizeof(payload.versionSW));
// ADDITION_FRAME 2 // ADDITION_FRAME 2
@ -205,6 +219,12 @@ void MifareDesfireGetInformation(void) {
return; return;
} }
if (len < sizeof(payload.details) + 1) {
Dbprintf("Tag answer to MFDES_ADDITIONAL_FRAME 2 was too short: data in Batch number and Production date is probably invalid");
print_result("Answer", resp, len);
memset(resp + len, 0xFF, sizeof(payload.details) + 1 - len); // clear remaining bytes
}
memcpy(payload.details, resp + 1, sizeof(payload.details)); memcpy(payload.details, resp + 1, sizeof(payload.details));
LED_B_ON(); LED_B_ON();

View file

@ -46,6 +46,15 @@
#include "dbprint.h" #include "dbprint.h"
#include "ticks.h" #include "ticks.h"
static bool IsKeyBReadable(uint8_t blockNo) {
uint8_t sector_trailer[16];
emlGetMem(sector_trailer, SectorTrailer(blockNo), 1);
uint8_t AC = ((sector_trailer[7] >> 5) & 0x04)
| ((sector_trailer[8] >> 2) & 0x02)
| ((sector_trailer[8] >> 7) & 0x01);
return (AC == 0x00 || AC == 0x01 || AC == 0x02);
}
static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) { static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
uint8_t sector_trailer[16]; uint8_t sector_trailer[16];
emlGetMem(sector_trailer, blockNo, 1); emlGetMem(sector_trailer, blockNo, 1);
@ -514,7 +523,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
uint8_t rAUTH_NT_keystream[4]; uint8_t rAUTH_NT_keystream[4];
uint32_t nonce = 0; uint32_t nonce = 0;
tUart14a *uart = GetUart14a(); const tUart14a *uart = GetUart14a();
// free eventually allocated BigBuf memory but keep Emulator Memory // free eventually allocated BigBuf memory but keep Emulator Memory
BigBuf_free_keep_EM(); BigBuf_free_keep_EM();
@ -872,8 +881,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
break; break;
} }
*/ */
blockNo = receivedCmd_dec[1];
if (MifareBlockToSector(receivedCmd_dec[1]) != cardAUTHSC) { if (MifareBlockToSector(blockNo) != cardAUTHSC) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
FpgaDisableTracing(); FpgaDisableTracing();
@ -881,6 +890,18 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
Dbprintf("[MFEMUL_WORK] Reader tried to operate (0x%02x) on block (0x%02x) not authenticated for (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], cardAUTHSC); Dbprintf("[MFEMUL_WORK] Reader tried to operate (0x%02x) on block (0x%02x) not authenticated for (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], cardAUTHSC);
break; break;
} }
// Compliance of MIFARE Classic EV1 1K Datasheet footnote of Table 8
// If access bits show that key B is Readable, any subsequent memory access will be refused.
if (cardAUTHKEY == AUTHKEYB && IsKeyBReadable(blockNo)) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
FpgaDisableTracing();
if (g_dbglevel >= DBG_ERROR)
Dbprintf("[MFEMUL_WORK] Access denied: Reader tried to access memory on authentication with key B while key B is readable in sector (0x%02x)", cardAUTHSC);
break;
}
} }
// case MFEMUL_WORK => CMD READ block // case MFEMUL_WORK => CMD READ block
@ -1251,7 +1272,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
memcpy(receivedCmd_dec, response, 16); // don't change anything memcpy(receivedCmd_dec, response, 16); // don't change anything
} }
} }
emlSetMem(receivedCmd_dec, cardWRBL, 1); emlSetMem_xt(receivedCmd_dec, cardWRBL, 1, 16);
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); // always ACK? EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); // always ACK?
FpgaDisableTracing(); FpgaDisableTracing();

View file

@ -18,6 +18,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "mifareutil.h" #include "mifareutil.h"
#include "appmain.h" // tearoff hook
#include "string.h" #include "string.h"
#include "BigBuf.h" #include "BigBuf.h"
#include "iso14443a.h" #include "iso14443a.h"
@ -115,7 +116,9 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t
uint16_t len = ReaderReceive(answer, par); uint16_t len = ReaderReceive(answer, par);
if (answer_parity) *answer_parity = par[0]; if (answer_parity) {
*answer_parity = par[0];
}
if (pcs && (crypted == CRYPT_ALL)) { if (pcs && (crypted == CRYPT_ALL)) {
if (len == 1) { if (len == 1) {
@ -126,10 +129,11 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 3)) << 3; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 3)) << 3;
answer[0] = res; answer[0] = res;
} else { } else {
for (pos = 0; pos < len; pos++) for (pos = 0; pos < len; pos++) {
answer[pos] = crypto1_byte(pcs, 0x00, 0) ^ answer[pos]; answer[pos] = crypto1_byte(pcs, 0x00, 0) ^ answer[pos];
} }
} }
}
return len; return len;
} }
@ -137,25 +141,24 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested) { int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested) {
return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL); return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL);
} }
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) { int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) {
int len; return mifare_classic_authex_cmd(pcs, uid, blockNo, (keyType & 1) == 0 ? MIFARE_AUTH_KEYA : MIFARE_AUTH_KEYB, ui64Key, isNested, ntptr, timing);
uint32_t pos, nt, ntpp; // Supplied tag nonce }
uint8_t par[1] = {0x00}; int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) {
// "random" reader nonce:
uint8_t nr[4]; uint8_t nr[4];
uint8_t mf_nr_ar[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; num_to_bytes(prng_successor(GetTickCount(), 32), 4, nr);
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
// "random" reader nonce: // Transmit MIFARE_CLASSIC_AUTH, 0x60 for key A, 0x61 for key B, or 0x80 for GDM backdoor
num_to_bytes(prng_successor(GetTickCount(), 32), 4, nr); int len = mifare_sendcmd_short(pcs, isNested, cmd, blockNo, receivedAnswer, receivedAnswerPar, timing);
// Transmit MIFARE_CLASSIC_AUTH
len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing);
if (len != 4) return 1; if (len != 4) return 1;
// Save the tag nonce (nt) // Save the tag nonce (nt)
nt = bytes_to_num(receivedAnswer, 4); uint32_t nt = bytes_to_num(receivedAnswer, 4);
// ----------------------------- crypto1 create // ----------------------------- crypto1 create
if (isNested) if (isNested)
@ -181,7 +184,9 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
*ntptr = nt; *ntptr = nt;
// Generate (encrypted) nr+parity by loading it into the cipher (Nr) // Generate (encrypted) nr+parity by loading it into the cipher (Nr)
par[0] = 0; uint32_t pos;
uint8_t par[1] = {0x00};
uint8_t mf_nr_ar[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
for (pos = 0; pos < 4; pos++) { for (pos = 0; pos < 4; pos++) {
mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos]; mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos];
par[0] |= (((filter(pcs->odd) ^ oddparity8(nr[pos])) & 0x01) << (7 - pos)); par[0] |= (((filter(pcs->odd) ^ oddparity8(nr[pos])) & 0x01) << (7 - pos));
@ -204,8 +209,8 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
uint32_t save_timeout = iso14a_get_timeout(); uint32_t save_timeout = iso14a_get_timeout();
// set timeout for authentication response // set timeout for authentication response
if (save_timeout > 103) if (save_timeout > 106)
iso14a_set_timeout(103); iso14a_set_timeout(106);
// Receive 4 byte tag answer // Receive 4 byte tag answer
len = ReaderReceive(receivedAnswer, receivedAnswerPar); len = ReaderReceive(receivedAnswer, receivedAnswerPar);
@ -217,8 +222,8 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
return 2; return 2;
} }
ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0, 0); // Supplied tag nonce
uint32_t ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0, 0);
if (ntpp != bytes_to_num(receivedAnswer, 4)) { if (ntpp != bytes_to_num(receivedAnswer, 4)) {
if (g_dbglevel >= DBG_EXTENDED) Dbprintf("Authentication failed. Error card response"); if (g_dbglevel >= DBG_EXTENDED) Dbprintf("Authentication failed. Error card response");
return 3; return 3;
@ -226,23 +231,29 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
return 0; return 0;
} }
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) { int mifare_classic_readblock(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData) {
return mifare_classic_readblock_ex(pcs, blockNo, blockData, ISO14443A_CMD_READBLOCK);
}
int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t iso_byte) {
int len;
uint8_t bt[2] = {0x00, 0x00};
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); uint16_t len = mifare_sendcmd_short(pcs, 1, iso_byte, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if (len == 1) { if (len == 1) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error %02x", receivedAnswer[0]); if (g_dbglevel >= DBG_ERROR) {
Dbprintf("Block " _YELLOW_("%3d") " Cmd 0x%02x Cmd Error %02x", blockNo, iso_byte, receivedAnswer[0]);
}
return 1; return 1;
} }
if (len != 18) { if (len != 18) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("wrong response len %d (expected 18)", len); if (g_dbglevel >= DBG_ERROR) {
Dbprintf("Block " _YELLOW_("%3d") " Cmd 0x%02x Wrong response len, expected 18 got " _RED_("%d"), blockNo, iso_byte, len);
}
return 2; return 2;
} }
uint8_t bt[2] = {0x00, 0x00};
memcpy(bt, receivedAnswer + 16, 2); memcpy(bt, receivedAnswer + 16, 2);
AddCrc14A(receivedAnswer, 16); AddCrc14A(receivedAnswer, 16);
if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
@ -410,58 +421,72 @@ int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) {
return res; return res;
} }
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) { int mifare_classic_writeblock(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData) {
// variables return mifare_classic_writeblock_ex(pcs, blockNo, blockData, ISO14443A_CMD_WRITEBLOCK);
uint16_t len = 0; }
uint32_t pos = 0; int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t cmd) {
uint8_t par[3] = {0x00, 0x00, 0x00}; // enough for 18 Bytes to send
uint8_t res = 0;
uint8_t d_block[18], d_block_enc[18]; // variables
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
// command MIFARE_CLASSIC_WRITEBLOCK // cmd is ISO14443A_CMD_WRITEBLOCK for normal tags, but could also be
len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); // MIFARE_MAGIC_GDM_WRITEBLOCK or MIFARE_MAGIC_GDM_WRITE_CFG for certain magic tags
uint16_t len = mifare_sendcmd_short(pcs, 1, cmd, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); if (g_dbglevel >= DBG_INFO) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1; return PM3_EFAILED;
} }
uint8_t d_block[18], d_block_enc[18];
memcpy(d_block, blockData, 16); memcpy(d_block, blockData, 16);
AddCrc14A(d_block, 16); AddCrc14A(d_block, 16);
if (pcs) {
// enough for 18 Bytes to send
uint8_t par[3] = {0x00, 0x00, 0x00};
// crypto // crypto
for (pos = 0; pos < 18; pos++) { for (uint32_t pos = 0; pos < 18; pos++) {
d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos]; d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos];
par[pos >> 3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos & 0x0007))); par[pos >> 3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos & 0x0007)));
} }
ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL); ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL);
} else {
ReaderTransmit(d_block, sizeof(d_block), NULL);
}
// tearoff occurred
if (tearoff_hook() == PM3_ETEAROFF) {
return PM3_ETEAROFF;
} else {
// Receive the response // Receive the response
len = ReaderReceive(receivedAnswer, receivedAnswerPar); len = ReaderReceive(receivedAnswer, receivedAnswerPar);
res = 0; uint8_t res = 0;
if (pcs) {
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 0)) << 0; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 0)) << 0;
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 1)) << 1; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 1)) << 1;
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 2)) << 2; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 2)) << 2;
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3;
} else {
res = receivedAnswer[0];
}
if ((len != 1) || (res != 0x0A)) { if ((len != 1) || (res != 0x0A)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd send data2 Error: %02x", res); if (g_dbglevel >= DBG_INFO) Dbprintf("Cmd send data2 Error: %02x", res);
return 2; return PM3_EFAILED;
} }
return 0; }
return PM3_SUCCESS;
} }
int mifare_classic_value(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t action) { int mifare_classic_value(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t action) {
// variables // variables
uint16_t len = 0; uint16_t len = 0;
uint32_t pos = 0; uint32_t pos = 0;
uint8_t par[3] = {0x00, 0x00, 0x00}; // enough for 18 Bytes to send uint8_t par[3] = {0x00, 0x00, 0x00}; // enough for 18 Bytes to send
uint8_t res = 0;
uint8_t d_block[18], d_block_enc[18]; uint8_t d_block[18], d_block_enc[18];
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
@ -471,13 +496,15 @@ int mifare_classic_value(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo
if (action == 0x01) if (action == 0x01)
command = MIFARE_CMD_DEC; command = MIFARE_CMD_DEC;
if (action == 0x02)
command = MIFARE_CMD_RESTORE;
// Send increment or decrement command // Send increment or decrement command
len = mifare_sendcmd_short(pcs, 1, command, blockNo, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_short(pcs, 1, command, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); if (g_dbglevel >= DBG_INFO) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1; return PM3_EFAILED;
} }
memcpy(d_block, blockData, 4); memcpy(d_block, blockData, 4);
@ -495,26 +522,19 @@ int mifare_classic_value(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo
len = ReaderReceive(receivedAnswer, receivedAnswerPar); len = ReaderReceive(receivedAnswer, receivedAnswerPar);
if (len != 0) { // Something not right, len == 0 (no response is ok as its waiting for transfer if (len != 0) { // Something not right, len == 0 (no response is ok as its waiting for transfer
res = 0; uint8_t res = 0;
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 0)) << 0; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 0)) << 0;
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 1)) << 1; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 1)) << 1;
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 2)) << 2; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 2)) << 2;
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3;
if ((len != 1) || (res != 0x0A)) { if ((len != 1) || (res != 0x0A)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd send data2 Error: %02x", res); if (g_dbglevel >= DBG_INFO) Dbprintf("Cmd send data2 Error: %02x", res);
return 2; return PM3_EFAILED;
}
} else {
// send trnasfer (commit the change)
len = mifare_sendcmd_short(pcs, 1, MIFARE_CMD_TRANSFER, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1;
} }
} }
return 0; return PM3_SUCCESS;
} }
int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) { int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) {
@ -528,9 +548,10 @@ int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) {
len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
if (g_dbglevel >= DBG_ERROR) if (g_dbglevel >= DBG_INFO) {
Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0], len); Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0], len);
return 1; }
return PM3_EFAILED;
} }
memcpy(d_block, blockData, 16); memcpy(d_block, blockData, 16);
@ -542,11 +563,12 @@ int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) {
len = ReaderReceive(receivedAnswer, receivedAnswerPar); len = ReaderReceive(receivedAnswer, receivedAnswerPar);
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
if (g_dbglevel >= DBG_ERROR) if (g_dbglevel >= DBG_INFO) {
Dbprintf("Cmd Send Data Error: %02x %d", receivedAnswer[0], len); Dbprintf("Cmd Send Data Error: %02x %d", receivedAnswer[0], len);
return 2;
} }
return 0; return PM3_EFAILED;
}
return PM3_SUCCESS;
} }
int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) { int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) {
@ -561,13 +583,15 @@ int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) {
len = mifare_sendcmd(MIFARE_ULC_WRITE, block, sizeof(block), receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd(MIFARE_ULC_WRITE, block, sizeof(block), receivedAnswer, receivedAnswerPar, NULL);
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
if (g_dbglevel >= DBG_ERROR) if (g_dbglevel >= DBG_INFO) {
Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0], len); Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0], len);
return 1;
} }
return 0; return PM3_EFAILED;
}
return PM3_SUCCESS;
} }
int mifare_classic_halt_ex(struct Crypto1State *pcs) {
int mifare_classic_halt(struct Crypto1State *pcs) {
uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00};
uint16_t len = mifare_sendcmd_short(pcs, (pcs == NULL) ? CRYPT_NONE : CRYPT_ALL, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL); uint16_t len = mifare_sendcmd_short(pcs, (pcs == NULL) ? CRYPT_NONE : CRYPT_ALL, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL);
if (len != 0) { if (len != 0) {
@ -576,19 +600,9 @@ int mifare_classic_halt_ex(struct Crypto1State *pcs) {
} }
return 0; return 0;
} }
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) {
return mifare_classic_halt_ex(pcs);
}
int mifare_ultra_halt(void) { int mifare_ultra_halt(void) {
uint16_t len = 0; return mifare_classic_halt(NULL);
uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00};
len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL);
if (len != 0) {
if (g_dbglevel >= DBG_EXTENDED) Dbprintf("halt warning. response len: %x", len);
return 1;
}
return 0;
} }
@ -603,32 +617,28 @@ uint8_t FirstBlockOfSector(uint8_t sectorNo) {
return sectorNo * 4; return sectorNo * 4;
else else
return 32 * 4 + (sectorNo - 32) * 16; return 32 * 4 + (sectorNo - 32) * 16;
} }
// work with emulator memory // work with emulator memory
void emlSetMem(uint8_t *data, int blockNum, int blocksCount) { void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int block_width) {
emlSetMem_xt(data, blockNum, blocksCount, 16); uint32_t offset = blockNum * block_width;
} uint32_t len = blocksCount * block_width;
emlSet(data, offset, len);
void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth) {
uint8_t *emCARD = BigBuf_get_EM_addr();
memcpy(emCARD + blockNum * blockBtWidth, data, blocksCount * blockBtWidth);
} }
void emlGetMem(uint8_t *data, int blockNum, int blocksCount) { void emlGetMem(uint8_t *data, int blockNum, int blocksCount) {
uint8_t *emCARD = BigBuf_get_EM_addr(); uint8_t *mem = BigBuf_get_EM_addr();
memcpy(data, emCARD + blockNum * 16, blocksCount * 16); memcpy(data, mem + blockNum * 16, blocksCount * 16);
} }
void emlGetMemBt(uint8_t *data, int offset, int byteCount) { void emlGetMemBt(uint8_t *data, int offset, int byteCount) {
uint8_t *emCARD = BigBuf_get_EM_addr(); uint8_t *mem = BigBuf_get_EM_addr();
memcpy(data, emCARD + offset, byteCount); memcpy(data, mem + offset, byteCount);
} }
int emlCheckValBl(int blockNum) { int emlCheckValBl(int blockNum) {
uint8_t *emCARD = BigBuf_get_EM_addr(); uint8_t *mem = BigBuf_get_EM_addr();
uint8_t *data = emCARD + blockNum * 16; uint8_t *data = mem + blockNum * 16;
if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) || if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) ||
(data[1] != (data[5] ^ 0xff)) || (data[1] != data[9]) || (data[1] != (data[5] ^ 0xff)) || (data[1] != data[9]) ||
@ -642,8 +652,8 @@ int emlCheckValBl(int blockNum) {
} }
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) { int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) {
uint8_t *emCARD = BigBuf_get_EM_addr(); uint8_t *mem = BigBuf_get_EM_addr();
uint8_t *data = emCARD + blockNum * 16; uint8_t *data = mem + blockNum * 16;
if (emlCheckValBl(blockNum)) if (emlCheckValBl(blockNum))
return 1; return 1;
@ -654,8 +664,8 @@ int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) {
} }
int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) { int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) {
uint8_t *emCARD = BigBuf_get_EM_addr(); uint8_t *mem = BigBuf_get_EM_addr();
uint8_t *data = emCARD + blockNum * 16; uint8_t *data = mem + blockNum * 16;
memcpy(data + 0, &blReg, 4); memcpy(data + 0, &blReg, 4);
memcpy(data + 8, &blReg, 4); memcpy(data + 8, &blReg, 4);
@ -666,41 +676,43 @@ int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) {
data[13] = blBlock ^ 0xff; data[13] = blBlock ^ 0xff;
data[14] = blBlock; data[14] = blBlock;
data[15] = blBlock ^ 0xff; data[15] = blBlock ^ 0xff;
return 0; return 0;
} }
uint64_t emlGetKey(int sectorNum, int keyType) { uint64_t emlGetKey(int sectorNum, int keyType) {
uint8_t key[6] = {0x00}; uint8_t key[6] = {0x00};
uint8_t *emCARD = BigBuf_get_EM_addr(); uint8_t *mem = BigBuf_get_EM_addr();
memcpy(key, emCARD + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6); memcpy(key, mem + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6);
return bytes_to_num(key, 6); return bytes_to_num(key, 6);
} }
void emlClearMem(void) { void emlClearMem(void) {
const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04}; const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04};
uint8_t *emCARD = BigBuf_get_EM_addr(); uint8_t *mem = BigBuf_get_EM_addr();
memset(emCARD, 0, CARD_MEMORY_SIZE); memset(mem, 0, CARD_MEMORY_SIZE);
// fill sectors trailer data // fill sectors trailer data
for (uint16_t b = 3; b < MIFARE_4K_MAXBLOCK; ((b < MIFARE_2K_MAXBLOCK - 4) ? (b += 4) : (b += 16))) for (uint16_t b = 3; b < MIFARE_4K_MAXBLOCK; ((b < MIFARE_2K_MAXBLOCK - 4) ? (b += 4) : (b += 16))) {
emlSetMem((uint8_t *)trailer, b, 1); emlSetMem_xt((uint8_t *)trailer, b, 1, 16);
}
// uid // uid
emlSetMem((uint8_t *)uid, 0, 1); emlSetMem_xt((uint8_t *)uid, 0, 1, 16);
return; return;
} }
uint8_t SectorTrailer(uint8_t blockNo) { uint8_t SectorTrailer(uint8_t blockNo) {
if (blockNo <= MIFARE_2K_MAXBLOCK) { if (blockNo <= MIFARE_2K_MAXBLOCK) {
if (g_dbglevel >= DBG_EXTENDED) if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x03)); Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x03));
}
return (blockNo | 0x03); return (blockNo | 0x03);
} else { } else {
if (g_dbglevel >= DBG_EXTENDED) if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x0f)); Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x0F));
return (blockNo | 0x0f); }
return (blockNo | 0x0F);
} }
} }
@ -747,9 +759,10 @@ int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData) {
len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer, receivedAnswerPar, NULL);
if (len == 1) { if (len == 1) {
if (g_dbglevel >= DBG_ERROR) if (g_dbglevel >= DBG_INFO) {
Dbprintf("Cmd Error: %02x", receivedAnswer[0]); Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1; }
return PM3_EFAILED;
} }
if (len == 12) { if (len == 12) {
@ -760,9 +773,9 @@ int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData) {
receivedAnswer[10], receivedAnswer[11]); receivedAnswer[10], receivedAnswer[11]);
} }
memcpy(blockData, receivedAnswer, 12); memcpy(blockData, receivedAnswer, 12);
return 0; return PM3_SUCCESS;
} }
return 1; return PM3_EFAILED;
} }
int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData) { int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData) {
@ -777,9 +790,10 @@ int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData) {
len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar, NULL);
if ((receivedAnswer[0] == 0x03) && (receivedAnswer[1] == 0xae)) { if ((receivedAnswer[0] == 0x03) && (receivedAnswer[1] == 0xae)) {
if (g_dbglevel >= DBG_ERROR) if (g_dbglevel >= DBG_ERROR) {
Dbprintf("Auth Error: %02x %02x", receivedAnswer[0], receivedAnswer[1]); Dbprintf("Auth Error: %02x %02x", receivedAnswer[0], receivedAnswer[1]);
return 1; }
return PM3_EFAILED;
} }
if (len == 12) { if (len == 12) {
@ -790,7 +804,7 @@ int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData) {
receivedAnswer[10], receivedAnswer[11]); receivedAnswer[10], receivedAnswer[11]);
} }
memcpy(blockData, receivedAnswer, 12); memcpy(blockData, receivedAnswer, 12);
return 0; return PM3_SUCCESS;
} }
return 1; return PM3_EFAILED;
} }

View file

@ -72,11 +72,15 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t
// mifare classic // mifare classic
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested); int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested);
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing); int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing);
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing);
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid);
int mifare_classic_halt_ex(struct Crypto1State *pcs); int mifare_classic_readblock(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData);
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t iso_byte);
int mifare_classic_value(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t action);
int mifare_classic_halt(struct Crypto1State *pcs);
int mifare_classic_writeblock(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData);
int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t cmd);
int mifare_classic_value(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t action);
// Ultralight/NTAG... // Ultralight/NTAG...
int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack); int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack);
@ -109,8 +113,7 @@ uint8_t SectorTrailer(uint8_t blockNo);
// emulator functions // emulator functions
void emlClearMem(void); void emlClearMem(void);
void emlSetMem(uint8_t *data, int blockNum, int blocksCount); void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int block_width);
void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth);
void emlGetMem(uint8_t *data, int blockNum, int blocksCount); void emlGetMem(uint8_t *data, int blockNum, int blocksCount);
void emlGetMemBt(uint8_t *data, int offset, int byteCount); void emlGetMemBt(uint8_t *data, int offset, int byteCount);
uint64_t emlGetKey(int sectorNum, int keyType); uint64_t emlGetKey(int sectorNum, int keyType);

View file

@ -39,14 +39,14 @@
typedef struct { typedef struct {
uint8_t *buffer; uint8_t *buffer;
uint8_t numbits; uint32_t numbits;
uint8_t position; uint32_t position;
} BitstreamIn_t; } BitstreamIn_t;
typedef struct { typedef struct {
uint8_t *buffer; uint8_t *buffer;
uint8_t numbits; uint32_t numbits;
uint8_t position; uint32_t position;
} BitstreamOut_t; } BitstreamOut_t;
bool headBit(BitstreamIn_t *stream); bool headBit(BitstreamIn_t *stream);

View file

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

View file

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

View file

@ -18,6 +18,34 @@
#include "usart.h" #include "usart.h"
#include "proxmark3_arm.h" #include "proxmark3_arm.h"
#define Dbprintf_usb(...) {\
bool tmpfpc = g_reply_via_fpc;\
bool tmpusb = g_reply_via_usb;\
g_reply_via_fpc = false;\
g_reply_via_usb = true;\
Dbprintf(__VA_ARGS__);\
g_reply_via_fpc = tmpfpc;\
g_reply_via_usb = tmpusb;}
#define Dbprintf_fpc(...) {\
bool tmpfpc = g_reply_via_fpc;\
bool tmpusb = g_reply_via_usb;\
g_reply_via_fpc = true;\
g_reply_via_usb = false;\
Dbprintf(__VA_ARGS__);\
g_reply_via_fpc = tmpfpc;\
g_reply_via_usb = tmpusb;}
#define Dbprintf_all(...) {\
bool tmpfpc = g_reply_via_fpc;\
bool tmpusb = g_reply_via_usb;\
g_reply_via_fpc = true;\
g_reply_via_usb = true;\
Dbprintf(__VA_ARGS__);\
g_reply_via_fpc = tmpfpc;\
g_reply_via_usb = tmpusb;}
static volatile AT91PS_USART pUS1 = AT91C_BASE_US1; static volatile AT91PS_USART pUS1 = AT91C_BASE_US1;
static volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; static volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA;
static volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_US1; static volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_US1;
@ -46,8 +74,8 @@ void usart_close(void) {
} }
*/ */
static uint8_t us_inbuf1[USART_BUFFLEN]; static uint8_t us_in_a[USART_BUFFLEN];
static uint8_t us_inbuf2[USART_BUFFLEN]; static uint8_t us_in_b[USART_BUFFLEN];
static uint8_t *usart_cur_inbuf = NULL; static uint8_t *usart_cur_inbuf = NULL;
static uint16_t usart_cur_inbuf_off = 0; static uint16_t usart_cur_inbuf_off = 0;
static uint8_t us_rxfifo[USART_FIFOLEN]; static uint8_t us_rxfifo[USART_FIFOLEN];
@ -56,7 +84,9 @@ static size_t us_rxfifo_high = 0;
static void usart_fill_rxfifo(void) { static void usart_fill_rxfifo(void) {
uint16_t rxfifo_free ;
uint16_t rxfifo_free = 0;
if (pUS1->US_RNCR == 0) { // One buffer got filled, backup buffer being used if (pUS1->US_RNCR == 0) { // One buffer got filled, backup buffer being used
if (us_rxfifo_low > us_rxfifo_high) if (us_rxfifo_low > us_rxfifo_high)
@ -79,20 +109,23 @@ static void usart_fill_rxfifo(void) {
pUS1->US_RNCR = USART_BUFFLEN; pUS1->US_RNCR = USART_BUFFLEN;
// Swap current buff // Swap current buff
if (usart_cur_inbuf == us_inbuf1) if (usart_cur_inbuf == us_in_a)
usart_cur_inbuf = us_inbuf2; usart_cur_inbuf = us_in_b;
else else
usart_cur_inbuf = us_inbuf1; usart_cur_inbuf = us_in_a;
usart_cur_inbuf_off = 0; usart_cur_inbuf_off = 0;
} else { } else {
// Take only what we have room for // Take only what we have room for
available = rxfifo_free; available = rxfifo_free;
for (uint16_t i = 0; i < available; i++) { for (uint16_t i = 0; i < available; i++) {
us_rxfifo[us_rxfifo_high++] = usart_cur_inbuf[usart_cur_inbuf_off + i]; us_rxfifo[us_rxfifo_high++] = usart_cur_inbuf[usart_cur_inbuf_off + i];
if (us_rxfifo_high == sizeof(us_rxfifo))
if (us_rxfifo_high == sizeof(us_rxfifo)) {
us_rxfifo_high = 0; us_rxfifo_high = 0;
} }
}
usart_cur_inbuf_off += available; usart_cur_inbuf_off += available;
return; return;
} }
@ -101,19 +134,21 @@ static void usart_fill_rxfifo(void) {
if (pUS1->US_RCR < USART_BUFFLEN - usart_cur_inbuf_off) { // Current buffer partially filled if (pUS1->US_RCR < USART_BUFFLEN - usart_cur_inbuf_off) { // Current buffer partially filled
if (us_rxfifo_low > us_rxfifo_high) if (us_rxfifo_low > us_rxfifo_high)
rxfifo_free = us_rxfifo_low - us_rxfifo_high; rxfifo_free = (us_rxfifo_low - us_rxfifo_high);
else else
rxfifo_free = sizeof(us_rxfifo) - us_rxfifo_high + us_rxfifo_low; rxfifo_free = (sizeof(us_rxfifo) - us_rxfifo_high + us_rxfifo_low);
uint16_t available = USART_BUFFLEN - pUS1->US_RCR - usart_cur_inbuf_off; uint16_t available = (USART_BUFFLEN - pUS1->US_RCR - usart_cur_inbuf_off);
if (available > rxfifo_free) if (available > rxfifo_free)
available = rxfifo_free; available = rxfifo_free;
for (uint16_t i = 0; i < available; i++) { for (uint16_t i = 0; i < available; i++) {
us_rxfifo[us_rxfifo_high++] = usart_cur_inbuf[usart_cur_inbuf_off + i]; us_rxfifo[us_rxfifo_high++] = usart_cur_inbuf[usart_cur_inbuf_off + i];
if (us_rxfifo_high == sizeof(us_rxfifo)) if (us_rxfifo_high == sizeof(us_rxfifo)) {
us_rxfifo_high = 0; us_rxfifo_high = 0;
} }
}
usart_cur_inbuf_off += available; usart_cur_inbuf_off += available;
} }
} }
@ -121,9 +156,9 @@ static void usart_fill_rxfifo(void) {
uint16_t usart_rxdata_available(void) { uint16_t usart_rxdata_available(void) {
usart_fill_rxfifo(); usart_fill_rxfifo();
if (us_rxfifo_low <= us_rxfifo_high) if (us_rxfifo_low <= us_rxfifo_high)
return us_rxfifo_high - us_rxfifo_low; return (us_rxfifo_high - us_rxfifo_low);
else else
return sizeof(us_rxfifo) - us_rxfifo_low + us_rxfifo_high; return (sizeof(us_rxfifo) - us_rxfifo_low + us_rxfifo_high);
} }
uint32_t usart_read_ng(uint8_t *data, size_t len) { uint32_t usart_read_ng(uint8_t *data, size_t len) {
@ -143,9 +178,10 @@ uint32_t usart_read_ng(uint8_t *data, size_t len) {
uint32_t maxtry = 10 * (3000000 / USART_BAUD_RATE) + tryconstant; uint32_t maxtry = 10 * (3000000 / USART_BAUD_RATE) + tryconstant;
while (len) { while (len) {
uint32_t available = usart_rxdata_available();
uint32_t available = usart_rxdata_available();
uint32_t packetSize = MIN(available, len); uint32_t packetSize = MIN(available, len);
if (available > 0) { if (available > 0) {
// Dbprintf_usb("Dbg USART ask %d bytes, available %d bytes, packetsize %d bytes", len, available, packetSize); // Dbprintf_usb("Dbg USART ask %d bytes, available %d bytes, packetsize %d bytes", len, available, packetSize);
// highest_observed_try = MAX(highest_observed_try, try); // highest_observed_try = MAX(highest_observed_try, try);
@ -153,8 +189,9 @@ uint32_t usart_read_ng(uint8_t *data, size_t len) {
} }
len -= packetSize; len -= packetSize;
while (packetSize--) { while (packetSize--) {
if (us_rxfifo_low == sizeof(us_rxfifo)) if (us_rxfifo_low == sizeof(us_rxfifo)) {
us_rxfifo_low = 0; us_rxfifo_low = 0;
}
data[bytes_rcv++] = us_rxfifo[us_rxfifo_low++]; data[bytes_rcv++] = us_rxfifo[us_rxfifo_low++];
} }
if (try++ == maxtry) { if (try++ == maxtry) {
@ -183,10 +220,13 @@ int usart_writebuffer_sync(uint8_t *data, size_t len) {
void usart_init(uint32_t baudrate, uint8_t parity) { void usart_init(uint32_t baudrate, uint8_t parity) {
if (baudrate != 0) if (baudrate != 0) {
g_usart_baudrate = baudrate; g_usart_baudrate = baudrate;
if ((parity == 'N') || (parity == 'O') || (parity == 'E')) }
if ((parity == 'N') || (parity == 'O') || (parity == 'E')) {
g_usart_parity = parity; g_usart_parity = parity;
}
// For a nice detailed sample, interrupt driven but still relevant. // For a nice detailed sample, interrupt driven but still relevant.
// See https://www.sparkfun.com/datasheets/DevTools/SAM7/at91sam7%20serial%20communications.pdf // See https://www.sparkfun.com/datasheets/DevTools/SAM7/at91sam7%20serial%20communications.pdf
@ -262,11 +302,11 @@ void usart_init(uint32_t baudrate, uint8_t parity) {
pUS1->US_TCR = 0; pUS1->US_TCR = 0;
pUS1->US_TNPR = (uint32_t)0; pUS1->US_TNPR = (uint32_t)0;
pUS1->US_TNCR = 0; pUS1->US_TNCR = 0;
pUS1->US_RPR = (uint32_t)us_inbuf1; pUS1->US_RPR = (uint32_t)us_in_a;
pUS1->US_RCR = USART_BUFFLEN; pUS1->US_RCR = USART_BUFFLEN;
usart_cur_inbuf = us_inbuf1; usart_cur_inbuf = us_in_a;
usart_cur_inbuf_off = 0; usart_cur_inbuf_off = 0;
pUS1->US_RNPR = (uint32_t)us_inbuf2; pUS1->US_RNPR = (uint32_t)us_in_b;
pUS1->US_RNCR = USART_BUFFLEN; pUS1->US_RNCR = USART_BUFFLEN;
// Initialize our fifo // Initialize our fifo

View file

@ -34,11 +34,17 @@ VERSIONSRC = version_pm3.c
# THUMBSRC := # THUMBSRC :=
# stdint.h provided locally until GCC 4.5 becomes C99 compliant # stdint.h provided locally until GCC 4.5 becomes C99 compliant
APP_CFLAGS = -I. -ffunction-sections -fdata-sections APP_CFLAGS = -I. -ffunction-sections -fdata-sections -DAS_BOOTROM
# stack-protect , no-pie reduces size on Gentoo Hardened 8.2 gcc, no-common makes sure uninitialized vars don't end up in COMMON area # stack-protect , no-pie reduces size on Gentoo Hardened 8.2 gcc, no-common makes sure uninitialized vars don't end up in COMMON area
APP_CFLAGS += -fno-stack-protector -fno-pie -fno-common APP_CFLAGS += -fno-stack-protector -fno-pie -fno-common
ifneq (,$(findstring WITH_FLASH,$(PLATFORM_DEFS)))
APP_CFLAGS += -DWITH_FLASH
APP_CFLAGS += -I../common_arm
THUMBSRC += flashmem.c ticks.c
endif
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC # Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
include ../common_arm/Makefile.common include ../common_arm/Makefile.common
@ -47,10 +53,10 @@ INSTALLFW = $(OBJDIR)/bootrom.elf
OBJS = $(OBJDIR)/bootrom.s19 OBJS = $(OBJDIR)/bootrom.s19
# version_pm3.c should be remade on every compilation # version_pm3.c should be checked on every compilation
version_pm3.c: default_version_pm3.c version_pm3.c: default_version_pm3.c .FORCE
$(info [=] GEN $@) $(info [=] CHECK $@)
$(Q)$(SH) ../tools/mkversion.sh > $@ || $(PERL) ../tools/mkversion.pl > $@ || $(CP) $< $@ $(Q)$(SH) ../tools/mkversion.sh $@ || $(CP) $< $@
all: showinfo $(OBJS) all: showinfo $(OBJS)
@ -82,7 +88,7 @@ uninstall:
$(info [@] Uninstalling bootrom from $(DESTDIR)$(PREFIX)...) $(info [@] Uninstalling bootrom from $(DESTDIR)$(PREFIX)...)
$(Q)$(INSTALLSUDO) $(RM) $(foreach fw,$(INSTALLFW),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(notdir $(fw))) $(Q)$(INSTALLSUDO) $(RM) $(foreach fw,$(INSTALLFW),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(notdir $(fw)))
.PHONY: all clean help install showinfo .PHONY: all clean help install showinfo .FORCE
help: help:
@echo Multi-OS Makefile, you are running on $(DETECTED_OS) @echo Multi-OS Makefile, you are running on $(DETECTED_OS)
@echo Possible targets: @echo Possible targets:

View file

@ -20,6 +20,10 @@
#include "clocks.h" #include "clocks.h"
#include "usb_cdc.h" #include "usb_cdc.h"
#ifdef WITH_FLASH
#include "flashmem.h"
#endif
#include "proxmark3_arm.h" #include "proxmark3_arm.h"
#define DEBUG 0 #define DEBUG 0
@ -214,8 +218,18 @@ static void flash_mode(void) {
bootrom_unlocked = false; bootrom_unlocked = false;
uint8_t rx[sizeof(PacketCommandOLD)]; uint8_t rx[sizeof(PacketCommandOLD)];
g_common_area.command = COMMON_AREA_COMMAND_NONE; g_common_area.command = COMMON_AREA_COMMAND_NONE;
if (!g_common_area.flags.button_pressed && BUTTON_PRESS()) if (!g_common_area.flags.button_pressed && BUTTON_PRESS()) {
g_common_area.flags.button_pressed = 1; g_common_area.flags.button_pressed = 1;
}
#ifdef WITH_FLASH
if (FlashInit()) { // checks for existence of flash also ... OK because bootrom was built for devices with flash
uint64_t flash_uniqueID = 0;
Flash_UniqueID((uint8_t *)&flash_uniqueID);
FlashStop();
usb_update_serial(flash_uniqueID);
}
#endif
usb_enable(); usb_enable();
@ -296,10 +310,10 @@ void BootROM(void) {
LED_B_OFF(); LED_B_OFF();
LED_A_OFF(); LED_A_OFF();
// Set the first 256kb memory flashspeed // Set the first 256KB memory flashspeed
AT91C_BASE_EFC0->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48); AT91C_BASE_EFC0->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48);
// 9 = 256, 10+ is 512kb // 9 = 256, 10+ is 512KB
uint8_t id = (*(AT91C_DBGU_CIDR) & 0xF00) >> 8; uint8_t id = (*(AT91C_DBGU_CIDR) & 0xF00) >> 8;
if (id > 9) if (id > 9)
AT91C_BASE_EFC1->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48); AT91C_BASE_EFC1->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48);

View file

@ -53,6 +53,7 @@ SECTIONS
*(.rodata.*) *(.rodata.*)
*(.data) *(.data)
*(.data.*) *(.data.*)
*(.ramfunc)
. = ALIGN(4); . = ALIGN(4);
} >ram AT>bootphase2 :phase2 } >ram AT>bootphase2 :phase2

View file

@ -96,11 +96,12 @@ if (CMAKE_TOOLCHAIN_FILE)
endif (ANDROID) endif (ANDROID)
set(EMBED_READLINE ON) set(EMBED_READLINE ON)
set(EMBED_BZIP2 ON) set(EMBED_BZIP2 ON)
set(EMBED_LZ4 ON)
endif (CMAKE_TOOLCHAIN_FILE) endif (CMAKE_TOOLCHAIN_FILE)
if (EMBED_READLINE OR EMBED_BZIP2) if (EMBED_READLINE OR EMBED_BZIP2 OR EMBED_LZ4)
include(ExternalProject) include(ExternalProject)
endif (EMBED_READLINE OR EMBED_BZIP2) endif (EMBED_READLINE OR EMBED_BZIP2 OR EMBED_LZ4)
if (NOT SKIPREADLINE EQUAL 1) if (NOT SKIPREADLINE EQUAL 1)
if (APPLE) if (APPLE)
@ -121,7 +122,7 @@ if (NOT SKIPREADLINE EQUAL 1)
ExternalProject_Add_StepTargets(ncurses configure build install) ExternalProject_Add_StepTargets(ncurses configure build install)
ExternalProject_Add(readline ExternalProject_Add(readline
URL ftp://ftp.gnu.org/gnu/readline/readline-8.1.tar.gz URL ftp://ftp.gnu.org/gnu/readline/readline-8.2.tar.gz
PREFIX deps/readline PREFIX deps/readline
DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/readline DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/readline
CONFIGURE_COMMAND ./configure CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} --host=arm --enable-static CONFIGURE_COMMAND ./configure CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} --host=arm --enable-static
@ -162,12 +163,14 @@ if (NOT SKIPJANSSONSYSTEM EQUAL 1)
endif (NOT SKIPJANSSONSYSTEM EQUAL 1) endif (NOT SKIPJANSSONSYSTEM EQUAL 1)
if(EMBED_BZIP2) if(EMBED_BZIP2)
cmake_policy(SET CMP0114 NEW)
set(BZIP2_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/bzip2/src/bzip2) set(BZIP2_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/bzip2/src/bzip2)
# Specify SOURCE_DIR will cause some errors
ExternalProject_Add(bzip2 ExternalProject_Add(bzip2
GIT_REPOSITORY https://android.googlesource.com/platform/external/bzip2 GIT_REPOSITORY https://android.googlesource.com/platform/external/bzip2
GIT_TAG platform-tools-30.0.2 GIT_TAG platform-tools-30.0.2
PREFIX deps/bzip2 PREFIX deps/bzip2
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/bzip2 # SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/bzip2
CONFIGURE_COMMAND mkdir -p ${BZIP2_BUILD_DIR} && git archive --format tar HEAD | tar -C ${BZIP2_BUILD_DIR} -x CONFIGURE_COMMAND mkdir -p ${BZIP2_BUILD_DIR} && git archive --format tar HEAD | tar -C ${BZIP2_BUILD_DIR} -x
BUILD_IN_SOURCE ON BUILD_IN_SOURCE ON
BUILD_COMMAND make -C ${BZIP2_BUILD_DIR} -j4 CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} libbz2.a BUILD_COMMAND make -C ${BZIP2_BUILD_DIR} -j4 CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} libbz2.a
@ -182,6 +185,34 @@ else(EMBED_BZIP2)
find_package (BZip2 REQUIRED) find_package (BZip2 REQUIRED)
endif(EMBED_BZIP2) endif(EMBED_BZIP2)
if(EMBED_LZ4)
cmake_policy(SET CMP0114 NEW)
set(LZ4_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/lz4/src/lz4)
# Specify SOURCE_DIR will cause some errors
ExternalProject_Add(lz4
GIT_REPOSITORY https://android.googlesource.com/platform/external/lz4
GIT_TAG platform-tools-30.0.2
PREFIX deps/lz4
# SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/lz4
CONFIGURE_COMMAND mkdir -p ${LZ4_BUILD_DIR} && git archive --format tar HEAD | tar -C ${LZ4_BUILD_DIR} -x
BUILD_IN_SOURCE ON
BUILD_COMMAND make -C ${LZ4_BUILD_DIR}/lib -j4 CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} liblz4.a
INSTALL_COMMAND ""
LOG_DOWNLOAD ON
)
ExternalProject_Add_StepTargets(lz4 configure build install)
set(LZ4_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/deps/lz4/src/lz4/lib)
set(LZ4_LIBRARIES ${CMAKE_CURRENT_BINARY_DIR}/deps/lz4/src/lz4/lib/liblz4.a)
set(LZ4_FOUND ON)
else(EMBED_LZ4)
find_path(LZ4_INCLUDE_DIRS lz4frame.h)
find_library(LZ4_LIBRARIES lz4)
endif(EMBED_LZ4)
if (LZ4_INCLUDE_DIRS AND LZ4_LIBRARIES)
set(LZ4_FOUND ON)
endif (LZ4_INCLUDE_DIRS AND LZ4_LIBRARIES)
if (NOT SKIPWHEREAMISYSTEM EQUAL 1) if (NOT SKIPWHEREAMISYSTEM EQUAL 1)
find_path(WHEREAMI_INCLUDE_DIRS whereami.h) find_path(WHEREAMI_INCLUDE_DIRS whereami.h)
find_library(WHEREAMI_LIBRARIES whereami) find_library(WHEREAMI_LIBRARIES whereami)
@ -293,9 +324,11 @@ set (TARGET_SOURCES
${PM3_ROOT}/client/src/cmdhfseos.c ${PM3_ROOT}/client/src/cmdhfseos.c
${PM3_ROOT}/client/src/cmdhfst.c ${PM3_ROOT}/client/src/cmdhfst.c
${PM3_ROOT}/client/src/cmdhfst25ta.c ${PM3_ROOT}/client/src/cmdhfst25ta.c
${PM3_ROOT}/client/src/cmdhftesla.c
${PM3_ROOT}/client/src/cmdhftexkom.c
${PM3_ROOT}/client/src/cmdhfthinfilm.c ${PM3_ROOT}/client/src/cmdhfthinfilm.c
${PM3_ROOT}/client/src/cmdhftopaz.c ${PM3_ROOT}/client/src/cmdhftopaz.c
${PM3_ROOT}/client/src/cmdhftexkom.c ${PM3_ROOT}/client/src/cmdhfvas.c
${PM3_ROOT}/client/src/cmdhfwaveshare.c ${PM3_ROOT}/client/src/cmdhfwaveshare.c
${PM3_ROOT}/client/src/cmdhfxerox.c ${PM3_ROOT}/client/src/cmdhfxerox.c
${PM3_ROOT}/client/src/cmdhw.c ${PM3_ROOT}/client/src/cmdhw.c
@ -336,6 +369,7 @@ set (TARGET_SOURCES
${PM3_ROOT}/client/src/cmdmain.c ${PM3_ROOT}/client/src/cmdmain.c
${PM3_ROOT}/client/src/cmdnfc.c ${PM3_ROOT}/client/src/cmdnfc.c
${PM3_ROOT}/client/src/cmdparser.c ${PM3_ROOT}/client/src/cmdparser.c
${PM3_ROOT}/client/src/cmdpiv.c
${PM3_ROOT}/client/src/cmdscript.c ${PM3_ROOT}/client/src/cmdscript.c
${PM3_ROOT}/client/src/cmdsmartcard.c ${PM3_ROOT}/client/src/cmdsmartcard.c
${PM3_ROOT}/client/src/cmdtrace.c ${PM3_ROOT}/client/src/cmdtrace.c
@ -345,6 +379,7 @@ set (TARGET_SOURCES
${PM3_ROOT}/client/src/fileutils.c ${PM3_ROOT}/client/src/fileutils.c
${PM3_ROOT}/client/src/flash.c ${PM3_ROOT}/client/src/flash.c
${PM3_ROOT}/client/src/graph.c ${PM3_ROOT}/client/src/graph.c
${PM3_ROOT}/client/src/iso4217.c
${PM3_ROOT}/client/src/jansson_path.c ${PM3_ROOT}/client/src/jansson_path.c
${PM3_ROOT}/client/src/preferences.c ${PM3_ROOT}/client/src/preferences.c
${PM3_ROOT}/client/src/pm3.c ${PM3_ROOT}/client/src/pm3.c
@ -362,7 +397,7 @@ set (TARGET_SOURCES
add_custom_command( add_custom_command(
OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c
COMMAND sh ${PM3_ROOT}/tools/mkversion.sh > ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c COMMAND sh ${PM3_ROOT}/tools/mkversion.sh ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c
DEPENDS ${PM3_ROOT}/common/default_version_pm3.c DEPENDS ${PM3_ROOT}/common/default_version_pm3.c
) )
@ -377,7 +412,23 @@ message(STATUS "CMAKE_SYSTEM_PROCESSOR := ${CMAKE_SYSTEM_PROCESSOR}")
if (APPLE) if (APPLE)
message(STATUS "Apple device detected.") message(STATUS "Apple device detected.")
set(ADDITIONAL_SRC ${PM3_ROOT}/client/src/util_darwin.h ${PM3_ROOT}/client/src/util_darwin.m ${ADDITIONAL_SRC}) set(ADDITIONAL_SRC ${PM3_ROOT}/client/src/util_darwin.h ${PM3_ROOT}/client/src/util_darwin.m ${ADDITIONAL_SRC})
find_library(UIKIT_LIBRARY UIKit)
if (NOT UIKIT_LIBRARY)
message(STATUS "UIKit.framework NOT found!")
else()
message(STATUS "UIKit.framework found! ${UIKIT_LIBRARY}")
set(ADDITIONAL_LNK "-framework Foundation" "-framework UIKit")
endif()
find_library(APPKIT_LIBRARY AppKit)
if (NOT APPKIT_LIBRARY)
message(STATUS "AppKit.framework NOT found!")
else()
message(STATUS "AppKit.framework found! ${APPKIT_LIBRARY}")
set(ADDITIONAL_LNK "-framework Foundation" "-framework AppKit") set(ADDITIONAL_LNK "-framework Foundation" "-framework AppKit")
endif()
endif (APPLE) endif (APPLE)
if ((NOT SKIPQT EQUAL 1) AND (Qt5_FOUND)) if ((NOT SKIPQT EQUAL 1) AND (Qt5_FOUND))
@ -436,6 +487,11 @@ if (BZIP2_FOUND)
set(ADDITIONAL_LNK ${BZIP2_LIBRARIES} ${ADDITIONAL_LNK}) set(ADDITIONAL_LNK ${BZIP2_LIBRARIES} ${ADDITIONAL_LNK})
endif (BZIP2_FOUND) endif (BZIP2_FOUND)
if (LZ4_FOUND)
set(ADDITIONAL_DIRS ${LZ4_INCLUDE_DIRS} ${ADDITIONAL_DIRS})
set(ADDITIONAL_LNK ${LZ4_LIBRARIES} ${ADDITIONAL_LNK})
endif (LZ4_FOUND)
if (WHEREAMI_FOUND) if (WHEREAMI_FOUND)
set(ADDITIONAL_DIRS ${WHEREAMI_INCLUDE_DIRS} ${ADDITIONAL_DIRS}) set(ADDITIONAL_DIRS ${WHEREAMI_INCLUDE_DIRS} ${ADDITIONAL_DIRS})
set(ADDITIONAL_LNK ${WHEREAMI_LIBRARIES} ${ADDITIONAL_LNK}) set(ADDITIONAL_LNK ${WHEREAMI_LIBRARIES} ${ADDITIONAL_LNK})
@ -468,11 +524,25 @@ else (SKIPBT EQUAL 1)
endif (BLUEZ_FOUND) endif (BLUEZ_FOUND)
endif(SKIPBT EQUAL 1) endif(SKIPBT EQUAL 1)
if (EMBED_BZIP2) if (BZIP2_FOUND)
if (EMBED_BZIP2)
message(STATUS "Bzip2 library: embedded") message(STATUS "Bzip2 library: embedded")
else (EMBED_BZIP2) else (EMBED_BZIP2)
message(STATUS "Bzip2 library: system library found") message(STATUS "Bzip2 library: system library found")
endif (EMBED_BZIP2) endif (EMBED_BZIP2)
else (BZIP2_FOUND)
message(SEND_ERROR "Bzip2 library: Bzip2 not found")
endif (BZIP2_FOUND)
if (LZ4_FOUND)
if (EMBED_LZ4)
message(STATUS "LZ4 library: embedded")
else (EMBED_LZ4)
message(STATUS "LZ4 library: system library found")
endif (EMBED_LZ4)
else (LZ4_FOUND)
message(SEND_ERROR "LZ4 library: LZ4 not found")
endif (LZ4_FOUND)
if (SKIPJANSSONSYSTEM EQUAL 1) if (SKIPJANSSONSYSTEM EQUAL 1)
message(STATUS "Jansson library: local library forced") message(STATUS "Jansson library: local library forced")
@ -572,6 +642,9 @@ endif (EMBED_READLINE)
if (EMBED_BZIP2) if (EMBED_BZIP2)
add_dependencies(proxmark3 bzip2) add_dependencies(proxmark3 bzip2)
endif (EMBED_BZIP2) endif (EMBED_BZIP2)
if (EMBED_LZ4)
add_dependencies(proxmark3 lz4)
endif (EMBED_LZ4)
if (MINGW) if (MINGW)
# Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z) # Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z)
@ -582,8 +655,22 @@ if (MINGW)
set(CMAKE_C_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_C_FLAGS}") set(CMAKE_C_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_CXX_FLAGS}")
# link Winsock2
set(ADDITIONAL_LNK ws2_32 ${ADDITIONAL_LNK})
endif (MINGW) 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 target_include_directories(proxmark3 PRIVATE
${PM3_ROOT}/common ${PM3_ROOT}/common
${PM3_ROOT}/common_fpga ${PM3_ROOT}/common_fpga

View file

@ -40,7 +40,7 @@ ifeq ($(USE_BREW),1)
PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(BREW_PREFIX)/lib/pkgconfig:$(BREW_PREFIX)/opt/qt/lib/pkgconfig:$(BREW_PREFIX)/opt/qt5/lib/pkgconfig PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(BREW_PREFIX)/lib/pkgconfig:$(BREW_PREFIX)/opt/qt/lib/pkgconfig:$(BREW_PREFIX)/opt/qt5/lib/pkgconfig
endif endif
ifdef ($(USE_MACPORTS),1) ifeq ($(USE_MACPORTS),1)
INCLUDES += -I$(MACPORTS_PREFIX)/include INCLUDES += -I$(MACPORTS_PREFIX)/include
LDLIBS += -L$(MACPORTS_PREFIX)/lib LDLIBS += -L$(MACPORTS_PREFIX)/lib
PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(MACPORTS_PREFIX)/lib/pkgconfig PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(MACPORTS_PREFIX)/lib/pkgconfig
@ -93,7 +93,6 @@ LUALIBLD =
LUAPLATFORM = generic LUAPLATFORM = generic
ifneq (,$(findstring MINGW,$(platform))) ifneq (,$(findstring MINGW,$(platform)))
LUAPLATFORM = mingw LUAPLATFORM = mingw
LDLIBS += -lws2_32
else else
ifeq ($(platform),Darwin) ifeq ($(platform),Darwin)
LUAPLATFORM = macosx LUAPLATFORM = macosx
@ -103,6 +102,11 @@ else
endif endif
endif endif
## Winsock2
ifneq (,$(findstring MINGW,$(platform)))
LDLIBS += -lws2_32
endif
## Reveng ## Reveng
REVENGLIBPATH = ./deps/reveng REVENGLIBPATH = ./deps/reveng
REVENGLIBINC = -I$(REVENGLIBPATH) REVENGLIBINC = -I$(REVENGLIBPATH)
@ -238,6 +242,9 @@ endif
## BZIP2 ## BZIP2
LDLIBS += -lbz2 LDLIBS += -lbz2
## LZ4
LDLIBS += -llz4
## Bluez (optional) ## Bluez (optional)
ifneq ($(SKIPBT),1) ifneq ($(SKIPBT),1)
BTINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags bluez 2>/dev/null) BTINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags bluez 2>/dev/null)
@ -430,7 +437,13 @@ LDFLAGS += $(MYLDFLAGS)
PM3LDFLAGS = $(LDFLAGS) PM3LDFLAGS = $(LDFLAGS)
ifeq ($(platform),Darwin) ifeq ($(platform),Darwin)
ifeq ($(shell uname -p),arm64)
# The platform is iOS
PM3LDFLAGS += -framework Foundation -framework UIKit
else
# M* macOS devices return arm
PM3LDFLAGS += -framework Foundation -framework AppKit PM3LDFLAGS += -framework Foundation -framework AppKit
endif
endif endif
################### ###################
@ -583,9 +596,11 @@ SRCS = mifare/aiddesfire.c \
cmdhfseos.c \ cmdhfseos.c \
cmdhfst.c \ cmdhfst.c \
cmdhfst25ta.c \ cmdhfst25ta.c \
cmdhftesla.c \
cmdhfthinfilm.c \ cmdhfthinfilm.c \
cmdhftopaz.c \ cmdhftopaz.c \
cmdhftexkom.c \ cmdhftexkom.c \
cmdhfvas.c \
cmdhfwaveshare.c \ cmdhfwaveshare.c \
cmdhfxerox.c \ cmdhfxerox.c \
cmdhw.c \ cmdhw.c \
@ -626,6 +641,7 @@ SRCS = mifare/aiddesfire.c \
cmdmain.c \ cmdmain.c \
cmdnfc.c \ cmdnfc.c \
cmdparser.c \ cmdparser.c \
cmdpiv.c \
cmdscript.c \ cmdscript.c \
cmdsmartcard.c \ cmdsmartcard.c \
cmdtrace.c \ cmdtrace.c \
@ -665,6 +681,7 @@ SRCS = mifare/aiddesfire.c \
generator.c \ generator.c \
graph.c \ graph.c \
jansson_path.c \ jansson_path.c \
iso4217.c \
iso7816/apduinfo.c \ iso7816/apduinfo.c \
iso7816/iso7816core.c \ iso7816/iso7816core.c \
loclass/cipher.c \ loclass/cipher.c \
@ -764,10 +781,14 @@ proxmark3: $(OBJS) $(STATICLIBS) lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lu
src/proxgui.cpp: src/ui/ui_overlays.h src/ui/ui_image.h src/proxgui.cpp: src/ui/ui_overlays.h src/ui/ui_image.h
src/proxguiqt.cpp: src/proxguiqt.h
src/proxguiqt.moc.cpp: src/proxguiqt.h src/proxguiqt.moc.cpp: src/proxguiqt.h
$(info [-] MOC $@) $(info [-] MOC $@)
$(Q)$(MOC) -o$@ $^ $(Q)$(MOC) -o$@ $^
src/proxguiqt.h: src/ui/ui_overlays.h src/ui/ui_image.h
src/ui/ui_overlays.h: src/ui/overlays.ui src/ui/ui_overlays.h: src/ui/overlays.ui
$(info [-] UIC $@) $(info [-] UIC $@)
$(Q)$(UIC) $^ > $@ $(Q)$(UIC) $^ > $@
@ -897,10 +918,10 @@ src/pm3_pywrap.c: pm3.i
.PHONY: all clean install uninstall tarbin .FORCE .PHONY: all clean install uninstall tarbin .FORCE
# version_pm3.c should be remade on every compilation # version_pm3.c should be checked on every compilation
src/version_pm3.c: default_version_pm3.c .FORCE src/version_pm3.c: default_version_pm3.c .FORCE
$(info [=] GEN $@) $(info [=] CHECK $@)
$(Q)$(SH) ../tools/mkversion.sh > $@ || $(CP) $< $@ $(Q)$(SH) ../tools/mkversion.sh $@ || $(CP) $< $@
# easy printing of MAKE VARIABLES # easy printing of MAKE VARIABLES
print-%: ; @echo $* = $($*) print-%: ; @echo $* = $($*)

View file

@ -11,8 +11,8 @@
#include "cliparser.h" #include "cliparser.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <util.h> // Get color constants #include <util.h> // color constants
#include <ui.h> // get PrintAndLogEx #include <ui.h> // PrintAndLogEx
#include <ctype.h> // tolower #include <ctype.h> // tolower
#include <inttypes.h> // PRIu64 #include <inttypes.h> // PRIu64
@ -34,65 +34,78 @@
int CLIParserInit(CLIParserContext **ctx, const char *vprogramName, const char *vprogramHint, const char *vprogramHelp) { int CLIParserInit(CLIParserContext **ctx, const char *vprogramName, const char *vprogramHint, const char *vprogramHelp) {
*ctx = calloc(sizeof(CLIParserContext), sizeof(uint8_t)); *ctx = calloc(sizeof(CLIParserContext), sizeof(uint8_t));
if (!*ctx) { if (*ctx == NULL) {
PrintAndLogEx(ERR, "ERROR: Insufficient memory\n"); PrintAndLogEx(ERR, "ERROR: Insufficient memory\n");
return 2; return 2;
} }
(*ctx)->argtable = NULL; (*ctx)->argtable = NULL;
(*ctx)->argtableLen = 0; (*ctx)->argtableLen = 0;
(*ctx)->programName = vprogramName; (*ctx)->programName = vprogramName;
(*ctx)->programHint = vprogramHint; (*ctx)->programHint = vprogramHint;
(*ctx)->programHelp = vprogramHelp; (*ctx)->programHelp = vprogramHelp;
memset((*ctx)->buf, 0x00, sizeof((*ctx)->buf)); memset((*ctx)->buf, 0x00, sizeof((*ctx)->buf));
return 0;
return PM3_SUCCESS;
} }
void CLIParserPrintHelp(CLIParserContext *ctx) { void CLIParserPrintHelp(CLIParserContext *ctx) {
if (ctx->programHint) if (ctx->programHint) {
PrintAndLogEx(NORMAL, "\n"_DescriptionColor_("%s"), ctx->programHint); PrintAndLogEx(NORMAL, "\n"_DescriptionColor_("%s"), ctx->programHint);
}
PrintAndLogEx(NORMAL, "\n"_SectionTagColor_("usage:")); PrintAndLogEx(NORMAL, "\n"_SectionTagColor_("usage:"));
PrintAndLogEx(NORMAL, " "_CommandColor_("%s")NOLF, ctx->programName); PrintAndLogEx(NORMAL, " "_CommandColor_("%s")NOLF, ctx->programName);
arg_print_syntax(stdout, ctx->argtable, "\n\n"); arg_print_syntax(stdout, ctx->argtable, "\n\n");
PrintAndLogEx(NORMAL, _SectionTagColor_("options:")); PrintAndLogEx(NORMAL, _SectionTagColor_("options:"));
arg_print_glossary(stdout, ctx->argtable, " "_ArgColor_("%-30s")" "_ArgHelpColor_("%s")"\n"); arg_print_glossary(stdout, ctx->argtable, " "_ArgColor_("%-30s")" "_ArgHelpColor_("%s")"\n");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
if (ctx->programHelp) {
PrintAndLogEx(NORMAL, _SectionTagColor_("examples/notes:"));
char *buf = NULL;
int idx = 0;
buf = realloc(buf, strlen(ctx->programHelp) + 1); // more then enough as we are splitting
char *p2; // pointer to split example from comment. if (ctx->programHelp) {
// allocate more then enough memory as we are splitting
char *s = calloc(strlen(ctx->programHelp) + 1, sizeof(uint8_t));
if (s == NULL) {
PrintAndLogEx(FAILED, "cannot allocate memory");
return;
}
PrintAndLogEx(NORMAL, _SectionTagColor_("examples/notes:"));
// pointer to split example from comment.
char *p2;
int idx = 0;
int egWidth = 30; int egWidth = 30;
for (int i = 0; i <= strlen(ctx->programHelp); i++) { // <= so to get string terminator. for (int i = 0; i <= strlen(ctx->programHelp); i++) { // <= so to get string terminator.
buf[idx++] = ctx->programHelp[i];
s[idx++] = ctx->programHelp[i];
if ((ctx->programHelp[i] == '\n') || (ctx->programHelp[i] == 0x00)) { if ((ctx->programHelp[i] == '\n') || (ctx->programHelp[i] == 0x00)) {
buf[idx - 1] = 0x00;
p2 = strstr(buf, "->"); // See if the example has a comment. s[idx - 1] = 0x00;
p2 = strstr(s, "->"); // See if the example has a comment.
if (p2 != NULL) { if (p2 != NULL) {
*(p2 - 1) = 0x00; *(p2 - 1) = 0x00;
if (strlen(buf) > 28) if (strlen(s) > 28)
egWidth = strlen(buf) + 5; egWidth = strlen(s) + 5;
else else
egWidth = 30; egWidth = 30;
PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s")" %s", egWidth, buf, p2); PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s")" %s", egWidth, s, p2);
} else { } else {
PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s"), egWidth, buf); PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s"), egWidth, s);
} }
idx = 0; idx = 0;
} }
} }
free(s);
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
free(buf);
} }
fflush(stdout); fflush(stdout);
} }
@ -127,7 +140,7 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta
return 3; return 3;
} }
return 0; return PM3_SUCCESS;
} }
enum ParserState { enum ParserState {
@ -144,21 +157,25 @@ int CLIParserParseString(CLIParserContext *ctx, const char *str, void *vargtable
int CLIParserParseStringEx(CLIParserContext *ctx, const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData) { int CLIParserParseStringEx(CLIParserContext *ctx, const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData) {
int argc = 0; int argc = 0;
char *argv[200] = {NULL}; char *argv[MAX_INPUT_ARG_LENGTH] = {NULL};
int len = strlen(str); int len = strlen(str);
memset(ctx->buf, 0x00, ARRAYLEN(ctx->buf)); memset(ctx->buf, 0x00, ARRAYLEN(ctx->buf));
char *bufptr = ctx->buf; char *bufptr = ctx->buf;
char *bufptrend = ctx->buf + ARRAYLEN(ctx->buf) - 1; char *bufptrend = ctx->buf + ARRAYLEN(ctx->buf) - 1;
char *spaceptr = NULL; char *spaceptr = NULL;
enum ParserState state = PS_FIRST; enum ParserState state = PS_FIRST;
argv[argc++] = bufptr; argv[argc++] = bufptr;
// param0 = program name // param0 = program name + with 0x00
memcpy(ctx->buf, ctx->programName, strlen(ctx->programName) + 1); // with 0x00 memcpy(ctx->buf, ctx->programName, strlen(ctx->programName) + 1);
bufptr += strlen(ctx->programName) + 1; bufptr += strlen(ctx->programName) + 1;
if (len) if (len) {
argv[argc++] = bufptr; argv[argc++] = bufptr;
}
// parse params // parse params
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
@ -214,10 +231,9 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
*datalen = 0; *datalen = 0;
int tmplen = 0; int tmplen = 0;
uint8_t tmpstr[(256 * 2) + 1] = {0}; uint8_t tmpstr[MAX_INPUT_ARG_LENGTH + 1] = {0};
// concat all strings in argstr into tmpstr[] // concat all strings in argstr into tmpstr[]
//
int res = CLIParamStrToBuf(argstr, tmpstr, sizeof(tmpstr), &tmplen); int res = CLIParamStrToBuf(argstr, tmpstr, sizeof(tmpstr), &tmplen);
if (res || (tmplen == 0)) { if (res || (tmplen == 0)) {
return res; return res;
@ -242,7 +258,7 @@ int CLIParamBinToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
*datalen = 0; *datalen = 0;
int tmplen = 0; int tmplen = 0;
uint8_t tmpstr[(256 * 2) + 1] = {0}; uint8_t tmpstr[MAX_INPUT_ARG_LENGTH + 1] = {0};
// concat all strings in argstr into tmpstr[] // concat all strings in argstr into tmpstr[]
// //
@ -268,7 +284,7 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
if (!argstr->count) if (!argstr->count)
return 0; return 0;
uint8_t tmpstr[(512 * 2) + 1] = {0}; uint8_t tmpstr[MAX_INPUT_ARG_LENGTH + 1] = {0};
int ibuf = 0; int ibuf = 0;
for (int i = 0; i < argstr->count; i++) { for (int i = 0; i < argstr->count; i++) {
@ -303,7 +319,7 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array, int *value) { int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array, int *value) {
char data[200] = {0}; char data[200] = {0};
int datalen = 0; int datalen = 200;
int res = CLIParamStrToBuf(argstr, (uint8_t *)data, sizeof(data), &datalen); int res = CLIParamStrToBuf(argstr, (uint8_t *)data, sizeof(data), &datalen);
if (res) if (res)
return res; return res;
@ -316,7 +332,7 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array
int val = -1; int val = -1;
int cntr = 0; int cntr = 0;
for (int i = 0; i < CLI_MAX_OPTLIST_LEN && option_array[i].text != NULL; i++) { for (int i = 0; (i < CLI_MAX_OPTLIST_LEN) && (option_array[i].text != NULL); i++) {
// exact match // exact match
if (strcmp(option_array[i].text, data) == 0) { if (strcmp(option_array[i].text, data) == 0) {
*value = option_array[i].code; *value = option_array[i].code;
@ -346,10 +362,11 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array
const char *CLIGetOptionListStr(const CLIParserOption *option_array, int value) { const char *CLIGetOptionListStr(const CLIParserOption *option_array, int value) {
static const char *errmsg = "n/a"; static const char *errmsg = "n/a";
for (int i = 0; i < CLI_MAX_OPTLIST_LEN && option_array[i].text != NULL; i++) { for (int i = 0; (i < CLI_MAX_OPTLIST_LEN) && (option_array[i].text != NULL); i++) {
if (option_array[i].code == value) if (option_array[i].code == value) {
return option_array[i].text; return option_array[i].text;
} }
}
return errmsg; return errmsg;
} }

View file

@ -12,6 +12,7 @@
#define __CLIPARSER_H #define __CLIPARSER_H
#include "argtable3.h" #include "argtable3.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include "util.h" #include "util.h"
#define arg_param_begin arg_lit0("h", "help", "This help") #define arg_param_begin arg_lit0("h", "help", "This help")
@ -53,13 +54,16 @@
#define CLIGetOptionListWithReturn(ctx, paramnum, option_array, option_array_len, value) if (CLIGetOptionList(arg_get_str((ctx), (paramnum)), (option_array), (option_array_len), (value))) {CLIParserFree((ctx)); return PM3_ESOFT;} #define CLIGetOptionListWithReturn(ctx, paramnum, option_array, option_array_len, value) if (CLIGetOptionList(arg_get_str((ctx), (paramnum)), (option_array), (option_array_len), (value))) {CLIParserFree((ctx)); return PM3_ESOFT;}
#define MAX_INPUT_ARG_LENGTH 4096
typedef struct { typedef struct {
void **argtable; void **argtable;
size_t argtableLen; size_t argtableLen;
const char *programName; const char *programName;
const char *programHint; const char *programHint;
const char *programHelp; const char *programHelp;
char buf[1024 + 60]; char buf[MAX_INPUT_ARG_LENGTH + 60];
} CLIParserContext; } CLIParserContext;
#define CLI_MAX_OPTLIST_LEN 50 #define CLI_MAX_OPTLIST_LEN 50

View file

@ -17,7 +17,7 @@ target_compile_definitions(pm3rrg_rdv4_hardnested_nosimd PRIVATE NOSIMD_BUILD)
## Mingw platforms: AMD64 ## Mingw platforms: AMD64
set(X86_CPUS x86 x86_64 i686 AMD64) set(X86_CPUS x86 x86_64 i686 AMD64)
set(ARM64_CPUS arm64 aarch64) set(ARM64_CPUS arm64 aarch64)
set(ARM32_CPUS armel armhf) set(ARM32_CPUS armel armhf armv7-a)
message(STATUS "CMAKE_SYSTEM_PROCESSOR := ${CMAKE_SYSTEM_PROCESSOR}") message(STATUS "CMAKE_SYSTEM_PROCESSOR := ${CMAKE_SYSTEM_PROCESSOR}")

View file

@ -22,6 +22,9 @@ endif
ifneq ($(findstring aarch64, $(cpu_arch)), ) ifneq ($(findstring aarch64, $(cpu_arch)), )
IS_SIMD_ARCH=arm64 IS_SIMD_ARCH=arm64
endif endif
ifneq ($(findstring iP, $(cpu_arch)), )
IS_SIMD_ARCH=arm64
endif
ifneq ($(IS_SIMD_ARCH), ) ifneq ($(IS_SIMD_ARCH), )
MULTIARCHSRCS = hardnested_bf_core.c hardnested_bitarray_core.c MULTIARCHSRCS = hardnested_bf_core.c hardnested_bitarray_core.c

View file

@ -371,7 +371,7 @@ uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, statel
for (uint32_t tests = 0; tests < nonces_to_bruteforce; ++tests) { for (uint32_t tests = 0; tests < nonces_to_bruteforce; ++tests) {
// common bits with preceding test nonce // common bits with preceding test nonce
uint32_t common_bits = next_common_bits; //tests ? trailing_zeros(bf_test_nonce_2nd_byte[tests] ^ bf_test_nonce_2nd_byte[tests-1]) : 0; uint32_t common_bits = next_common_bits; //tests ? trailing_zeros(bf_test_nonce_2nd_byte[tests] ^ bf_test_nonce_2nd_byte[tests-1]) : 0;
next_common_bits = tests < nonces_to_bruteforce - 1 ? trailing_zeros(bf_test_nonce_2nd_byte[tests] ^ bf_test_nonce_2nd_byte[tests + 1]) : 0; next_common_bits = (tests < nonces_to_bruteforce - 1) ? trailing_zeros(bf_test_nonce_2nd_byte[tests] ^ bf_test_nonce_2nd_byte[tests + 1]) : 0;
uint32_t parity_bit_idx = 1; // start checking with the parity of second nonce byte uint32_t parity_bit_idx = 1; // start checking with the parity of second nonce byte
bitslice_value_t fb_bits = fbb[common_bits]; // start with precomputed feedback bits from previous nonce bitslice_value_t fb_bits = fbb[common_bits]; // start with precomputed feedback bits from previous nonce
bitslice_value_t ks_bits = ksb[common_bits]; // dito for first keystream bits bitslice_value_t ks_bits = ksb[common_bits]; // dito for first keystream bits
@ -530,7 +530,6 @@ stop_tests:
bucket_states_tested += bucket_size[block_idx]; bucket_states_tested += bucket_size[block_idx];
// prepare to set new states // prepare to set new states
state_p = &states[KEYSTREAM_SIZE]; state_p = &states[KEYSTREAM_SIZE];
continue;
} }
} }
out: out:

View file

@ -78,6 +78,8 @@ THE SOFTWARE.
#define DEBUG_KEY_ELIMINATION 1 #define DEBUG_KEY_ELIMINATION 1
// #define DEBUG_BRUTE_FORCE // #define DEBUG_BRUTE_FORCE
#define MIN_BUCKETS_SIZE 128
typedef enum { typedef enum {
EVEN_STATE = 0, EVEN_STATE = 0,
ODD_STATE = 1 ODD_STATE = 1
@ -88,12 +90,13 @@ static uint32_t bf_test_nonce[256];
static uint8_t bf_test_nonce_2nd_byte[256]; static uint8_t bf_test_nonce_2nd_byte[256];
static uint8_t bf_test_nonce_par[256]; static uint8_t bf_test_nonce_par[256];
static uint32_t bucket_count = 0; static uint32_t bucket_count = 0;
static statelist_t *buckets[128]; static size_t buckets_allocated = 0;
static statelist_t **buckets = NULL;
static uint32_t keys_found = 0; static uint32_t keys_found = 0;
static uint64_t num_keys_tested; static uint64_t num_keys_tested;
static uint64_t found_bs_key = 0; static uint64_t found_bs_key = 0;
inline uint8_t trailing_zeros(uint8_t byte) { uint8_t trailing_zeros(uint8_t byte) {
static const uint8_t trailing_zeros_LUT[256] = { static const uint8_t trailing_zeros_LUT[256] = {
8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
@ -157,6 +160,7 @@ crack_states_thread(void *x) {
uint8_t *best_first_bytes; uint8_t *best_first_bytes;
} *thread_arg; } *thread_arg;
const int num_brute_force_threads = NUM_BRUTE_FORCE_THREADS;
thread_arg = (struct arg *)x; thread_arg = (struct arg *)x;
const int thread_id = thread_arg->thread_ID; const int thread_id = thread_arg->thread_ID;
uint32_t current_bucket = thread_id; uint32_t current_bucket = thread_id;
@ -182,13 +186,13 @@ crack_states_thread(void *x) {
} else { } else {
if (!thread_arg->silent) { if (!thread_arg->silent) {
char progress_text[80]; char progress_text[80];
snprintf(progress_text, sizeof(progress_text), "Brute force phase: %6.02f%%\t", 100.0 * (float)num_keys_tested / (float)(thread_arg->maximum_states)); snprintf(progress_text, sizeof(progress_text), "Brute force phase: %6.02f%% ", 100.0 * (float)num_keys_tested / (float)(thread_arg->maximum_states));
float remaining_bruteforce = thread_arg->nonces[thread_arg->best_first_bytes[0]].expected_num_brute_force - (float)num_keys_tested / 2; float remaining_bruteforce = thread_arg->nonces[thread_arg->best_first_bytes[0]].expected_num_brute_force - (float)num_keys_tested / 2;
hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, remaining_bruteforce, 5000); hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, remaining_bruteforce, 5000);
} }
} }
} }
current_bucket += NUM_BRUTE_FORCE_THREADS; current_bucket += num_brute_force_threads;
} }
return NULL; return NULL;
} }
@ -294,12 +298,35 @@ static void write_benchfile(statelist_t *candidates) {
#endif #endif
static bool ensure_buckets_alloc(size_t need_buckets) {
if (need_buckets > buckets_allocated) {
size_t alloc_sz = ((buckets_allocated == 0) ? MIN_BUCKETS_SIZE : (buckets_allocated * 2));
while (need_buckets > alloc_sz) {
alloc_sz *= 2;
}
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;
}
return true;
}
bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint32_t num_acquired_nonces, uint64_t maximum_states, noncelist_t *nonces, uint8_t *best_first_bytes, uint64_t *found_key) { bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint32_t num_acquired_nonces, uint64_t maximum_states, noncelist_t *nonces, uint8_t *best_first_bytes, uint64_t *found_key) {
#if defined (WRITE_BENCH_FILE) #if defined (WRITE_BENCH_FILE)
write_benchfile(candidates); write_benchfile(candidates);
#endif #endif
bool silent = (bf_rate != NULL); bool silent = (bf_rate != NULL);
const int num_brute_force_threads = NUM_BRUTE_FORCE_THREADS;
keys_found = 0; keys_found = 0;
num_keys_tested = 0; num_keys_tested = 0;
found_bs_key = 0; found_bs_key = 0;
@ -310,6 +337,11 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint
bucket_count = 0; bucket_count = 0;
for (statelist_t *p = candidates; p != NULL; p = p->next) { for (statelist_t *p = candidates; p != NULL; p = p->next) {
if (p->states[ODD_STATE] != NULL && p->states[EVEN_STATE] != NULL) { if (p->states[ODD_STATE] != NULL && p->states[EVEN_STATE] != NULL) {
if (!ensure_buckets_alloc(bucket_count + 1)) {
PrintAndLogEx(ERR, "Can't allocate buckets, abort!");
return false;
}
buckets[bucket_count] = p; buckets[bucket_count] = p;
bucket_count++; bucket_count++;
} }
@ -322,7 +354,7 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint
return false; return false;
#endif #endif
pthread_t threads[NUM_BRUTE_FORCE_THREADS]; pthread_t threads[num_brute_force_threads];
struct args { struct args {
bool silent; bool silent;
int thread_ID; int thread_ID;
@ -331,9 +363,9 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint
uint64_t maximum_states; uint64_t maximum_states;
noncelist_t *nonces; noncelist_t *nonces;
uint8_t *best_first_bytes; uint8_t *best_first_bytes;
} thread_args[NUM_BRUTE_FORCE_THREADS]; } thread_args[num_brute_force_threads];
for (uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS; i++) { for (uint32_t i = 0; i < num_brute_force_threads; i++) {
thread_args[i].thread_ID = i; thread_args[i].thread_ID = i;
thread_args[i].silent = silent; thread_args[i].silent = silent;
thread_args[i].cuid = cuid; thread_args[i].cuid = cuid;
@ -343,10 +375,14 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint
thread_args[i].best_first_bytes = best_first_bytes; thread_args[i].best_first_bytes = best_first_bytes;
pthread_create(&threads[i], NULL, crack_states_thread, (void *)&thread_args[i]); pthread_create(&threads[i], NULL, crack_states_thread, (void *)&thread_args[i]);
} }
for (uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS; i++) { for (uint32_t i = 0; i < num_brute_force_threads; i++) {
pthread_join(threads[i], 0); pthread_join(threads[i], 0);
} }
free(buckets);
buckets = NULL;
buckets_allocated = 0;
uint64_t elapsed_time = msclock() - start_time; uint64_t elapsed_time = msclock() - start_time;
if (bf_rate != NULL) if (bf_rate != NULL)
@ -377,11 +413,14 @@ static bool read_bench_data(statelist_t *test_candidates) {
return false; return false;
} }
free(path); free(path);
bytes_read = fread(&nonces_to_bruteforce, 1, sizeof(nonces_to_bruteforce), benchfile);
if (bytes_read != sizeof(nonces_to_bruteforce)) { // read 4 bytes of data ?
bytes_read = fread(&nonces_to_bruteforce, 1, sizeof(uint32_t), benchfile);
if (bytes_read != sizeof(uint32_t) || (nonces_to_bruteforce >= 256)) {
fclose(benchfile); fclose(benchfile);
return false; return false;
} }
for (uint32_t i = 0; i < nonces_to_bruteforce && i < 256; i++) { for (uint32_t i = 0; i < nonces_to_bruteforce && i < 256; i++) {
bytes_read = fread(&bf_test_nonce[i], 1, sizeof(uint32_t), benchfile); bytes_read = fread(&bf_test_nonce[i], 1, sizeof(uint32_t), benchfile);
if (bytes_read != sizeof(uint32_t)) { if (bytes_read != sizeof(uint32_t)) {
@ -395,11 +434,13 @@ static bool read_bench_data(statelist_t *test_candidates) {
return false; return false;
} }
} }
bytes_read = fread(&num_states, 1, sizeof(uint32_t), benchfile); bytes_read = fread(&num_states, 1, sizeof(uint32_t), benchfile);
if (bytes_read != sizeof(uint32_t)) { if (bytes_read != sizeof(uint32_t)) {
fclose(benchfile); fclose(benchfile);
return false; return false;
} }
for (states_read = 0; states_read < MIN(num_states, TEST_BENCH_SIZE); states_read++) { for (states_read = 0; states_read < MIN(num_states, TEST_BENCH_SIZE); states_read++) {
bytes_read = fread(test_candidates->states[EVEN_STATE] + states_read, 1, sizeof(uint32_t), benchfile); bytes_read = fread(test_candidates->states[EVEN_STATE] + states_read, 1, sizeof(uint32_t), benchfile);
if (bytes_read != sizeof(uint32_t)) { if (bytes_read != sizeof(uint32_t)) {
@ -407,9 +448,11 @@ static bool read_bench_data(statelist_t *test_candidates) {
return false; return false;
} }
} }
for (uint32_t i = states_read; i < TEST_BENCH_SIZE; i++) { for (uint32_t i = states_read; i < TEST_BENCH_SIZE; i++) {
test_candidates->states[EVEN_STATE][i] = test_candidates->states[EVEN_STATE][i - states_read]; test_candidates->states[EVEN_STATE][i] = test_candidates->states[EVEN_STATE][i - states_read];
} }
for (uint32_t i = states_read; i < num_states; i++) { for (uint32_t i = states_read; i < num_states; i++) {
bytes_read = fread(&temp, 1, sizeof(uint32_t), benchfile); bytes_read = fread(&temp, 1, sizeof(uint32_t), benchfile);
if (bytes_read != sizeof(uint32_t)) { if (bytes_read != sizeof(uint32_t)) {
@ -417,6 +460,7 @@ static bool read_bench_data(statelist_t *test_candidates) {
return false; return false;
} }
} }
for (states_read = 0; states_read < MIN(num_states, TEST_BENCH_SIZE); states_read++) { for (states_read = 0; states_read < MIN(num_states, TEST_BENCH_SIZE); states_read++) {
bytes_read = fread(test_candidates->states[ODD_STATE] + states_read, 1, sizeof(uint32_t), benchfile); bytes_read = fread(test_candidates->states[ODD_STATE] + states_read, 1, sizeof(uint32_t), benchfile);
if (bytes_read != sizeof(uint32_t)) { if (bytes_read != sizeof(uint32_t)) {
@ -424,6 +468,7 @@ static bool read_bench_data(statelist_t *test_candidates) {
return false; return false;
} }
} }
for (uint32_t i = states_read; i < TEST_BENCH_SIZE; i++) { for (uint32_t i = states_read; i < TEST_BENCH_SIZE; i++) {
test_candidates->states[ODD_STATE][i] = test_candidates->states[ODD_STATE][i - states_read]; test_candidates->states[ODD_STATE][i] = test_candidates->states[ODD_STATE][i - states_read];
} }
@ -434,30 +479,31 @@ static bool read_bench_data(statelist_t *test_candidates) {
float brute_force_benchmark(void) { float brute_force_benchmark(void) {
statelist_t test_candidates[NUM_BRUTE_FORCE_THREADS]; const int num_brute_force_threads = NUM_BRUTE_FORCE_THREADS;
statelist_t test_candidates[num_brute_force_threads];
test_candidates[0].states[ODD_STATE] = calloc(1, (TEST_BENCH_SIZE + 1) * sizeof(uint32_t)); test_candidates[0].states[ODD_STATE] = calloc(1, (TEST_BENCH_SIZE + 1) * sizeof(uint32_t));
test_candidates[0].states[EVEN_STATE] = calloc(1, (TEST_BENCH_SIZE + 1) * sizeof(uint32_t)); test_candidates[0].states[EVEN_STATE] = calloc(1, (TEST_BENCH_SIZE + 1) * sizeof(uint32_t));
for (uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS - 1; i++) { for (uint32_t i = 0; i < num_brute_force_threads - 1; i++) {
test_candidates[i].next = test_candidates + i + 1; test_candidates[i].next = test_candidates + i + 1;
test_candidates[i + 1].states[ODD_STATE] = test_candidates[0].states[ODD_STATE]; test_candidates[i + 1].states[ODD_STATE] = test_candidates[0].states[ODD_STATE];
test_candidates[i + 1].states[EVEN_STATE] = test_candidates[0].states[EVEN_STATE]; test_candidates[i + 1].states[EVEN_STATE] = test_candidates[0].states[EVEN_STATE];
} }
test_candidates[NUM_BRUTE_FORCE_THREADS - 1].next = NULL; test_candidates[num_brute_force_threads - 1].next = NULL;
if (!read_bench_data(test_candidates)) { if (!read_bench_data(test_candidates)) {
PrintAndLogEx(NORMAL, "Couldn't read benchmark data. Assuming brute force rate of %1.0f states per second", DEFAULT_BRUTE_FORCE_RATE); PrintAndLogEx(NORMAL, "Couldn't read benchmark data. Assuming brute force rate of %1.0f states per second", DEFAULT_BRUTE_FORCE_RATE);
return DEFAULT_BRUTE_FORCE_RATE; return DEFAULT_BRUTE_FORCE_RATE;
} }
for (uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS; i++) { for (uint32_t i = 0; i < num_brute_force_threads; i++) {
test_candidates[i].len[ODD_STATE] = TEST_BENCH_SIZE; test_candidates[i].len[ODD_STATE] = TEST_BENCH_SIZE;
test_candidates[i].len[EVEN_STATE] = TEST_BENCH_SIZE; test_candidates[i].len[EVEN_STATE] = TEST_BENCH_SIZE;
test_candidates[i].states[ODD_STATE][TEST_BENCH_SIZE] = -1; test_candidates[i].states[ODD_STATE][TEST_BENCH_SIZE] = -1;
test_candidates[i].states[EVEN_STATE][TEST_BENCH_SIZE] = -1; test_candidates[i].states[EVEN_STATE][TEST_BENCH_SIZE] = -1;
} }
uint64_t maximum_states = TEST_BENCH_SIZE * TEST_BENCH_SIZE * (uint64_t)NUM_BRUTE_FORCE_THREADS; uint64_t maximum_states = TEST_BENCH_SIZE * TEST_BENCH_SIZE * (uint64_t)num_brute_force_threads;
float bf_rate; float bf_rate;
uint64_t found_key = 0; uint64_t found_key = 0;

View file

@ -10,9 +10,6 @@
#if defined(__APPLE__) #if defined(__APPLE__)
#include "TargetConditionals.h" #include "TargetConditionals.h"
#if TARGET_OS_IOS || TARGET_OS_WATCH || TARGET_OS_TV
#define system(s) ((s)==NULL ? 0 : -1)
#endif // end iOS
#endif #endif
#include <limits.h> #include <limits.h>

View file

@ -9,6 +9,9 @@ add_library(pm3rrg_rdv4_mbedtls STATIC
../../common/mbedtls/entropy.c ../../common/mbedtls/entropy.c
../../common/mbedtls/error.c ../../common/mbedtls/error.c
../../common/mbedtls/ecp.c ../../common/mbedtls/ecp.c
../../common/mbedtls/ecdh.c
../../common/mbedtls/ecc_point_compression.c
../../common/mbedtls/gcm.c
../../common/mbedtls/ecp_curves.c ../../common/mbedtls/ecp_curves.c
../../common/mbedtls/certs.c ../../common/mbedtls/certs.c
../../common/mbedtls/camellia.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)); memcpy(where, &v, sizeof(v));
} }
static inline bool would_overflow(CborEncoder *encoder, size_t len) { static bool would_overflow(CborEncoder *encoder, size_t len) {
ptrdiff_t remaining = (ptrdiff_t)encoder->end; ptrdiff_t remaining = (ptrdiff_t)encoder->end;
remaining -= remaining ? (ptrdiff_t)encoder->data.ptr : encoder->data.bytes_needed; remaining -= remaining ? (ptrdiff_t)encoder->data.ptr : encoder->data.bytes_needed;
remaining -= (ptrdiff_t)len; remaining -= (ptrdiff_t)len;
return unlikely(remaining < 0); return unlikely(remaining < 0);
} }
static inline void advance_ptr(CborEncoder *encoder, size_t n) { static void advance_ptr(CborEncoder *encoder, size_t n) {
if (encoder->end) if (encoder->end)
encoder->data.ptr += n; encoder->data.ptr += n;
else else
encoder->data.bytes_needed += n; encoder->data.bytes_needed += n;
} }
static inline CborError append_to_buffer(CborEncoder *encoder, const void *data, size_t len) { static CborError append_to_buffer(CborEncoder *encoder, const void *data, size_t len) {
if (would_overflow(encoder, len)) { if (would_overflow(encoder, len)) {
if (encoder->end != NULL) { if (encoder->end != NULL) {
len -= encoder->end - encoder->data.ptr; len -= encoder->end - encoder->data.ptr;
@ -263,11 +263,11 @@ static inline CborError append_to_buffer(CborEncoder *encoder, const void *data,
return CborNoError; return CborNoError;
} }
static inline CborError append_byte_to_buffer(CborEncoder *encoder, uint8_t byte) { static CborError append_byte_to_buffer(CborEncoder *encoder, uint8_t byte) {
return append_to_buffer(encoder, &byte, 1); return append_to_buffer(encoder, &byte, 1);
} }
static inline CborError encode_number_no_update(CborEncoder *encoder, uint64_t ui, uint8_t shiftedMajorType) { static CborError encode_number_no_update(CborEncoder *encoder, uint64_t ui, uint8_t shiftedMajorType) {
/* Little-endian would have been so much more convenient here: /* Little-endian would have been so much more convenient here:
* We could just write at the beginning of buf but append_to_buffer * We could just write at the beginning of buf but append_to_buffer
* only the necessary bytes. * only the necessary bytes.

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