mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 13:23:51 -07:00
Merge branch 'master' into patch-1
Signed-off-by: Esteban Martinena Guerrero <orensbruli@gmail.com>
This commit is contained in:
commit
1683fc53ee
339 changed files with 26675 additions and 5927 deletions
21
.github/ISSUE_TEMPLATE/checklist-for-release.md
vendored
21
.github/ISSUE_TEMPLATE/checklist-for-release.md
vendored
|
@ -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)
|
||||
- [ ] `experimental_lib` 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)
|
||||
|
||||
# OS compilation and tests
|
||||
|
||||
```bash
|
||||
#!/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
|
||||
```
|
||||
Run `tools/release_tests.sh` on:
|
||||
|
||||
- [ ] RPI Zero
|
||||
- [ ] Jetson Nano
|
||||
|
@ -47,9 +32,9 @@ make hitag2crack/clean && make hitag2crack && tools/pm3_tests.sh hitag2crack ||
|
|||
- [ ] Kali
|
||||
- [ ] Debian Stable
|
||||
- [ ] Debian Testing
|
||||
- [ ] Ubuntu21
|
||||
- [ ] Ubuntu 22
|
||||
- [ ] ParrotOS
|
||||
- [ ] Fedora
|
||||
- [ ] Fedora 37
|
||||
- [ ] OpenSuse Leap
|
||||
- [ ] OpenSuse Tumbleweed
|
||||
- [ ] OSX (MacPorts)
|
||||
|
|
4
.github/workflows/codeql-analysis.yml
vendored
4
.github/workflows/codeql-analysis.yml
vendored
|
@ -41,7 +41,7 @@ jobs:
|
|||
run: sudo apt-get update
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0-dbg 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 libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0 lua5.2 sed libssl-dev
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
|
@ -51,7 +51,7 @@ jobs:
|
|||
if [ -f requirements.txt ]; then python3 -m pip install -r requirements.txt; fi
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
|
9
.github/workflows/macos.yml
vendored
9
.github/workflows/macos.yml
vendored
|
@ -19,7 +19,7 @@ jobs:
|
|||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set Git http.postBuffer to something high
|
||||
run: git config --global http.postBuffer 524288000
|
||||
|
@ -36,6 +36,7 @@ jobs:
|
|||
|
||||
- name: Install dependencies
|
||||
run: brew install readline coreutils qt5 RfidResearchGroup/proxmark3/arm-none-eabi-gcc openssl
|
||||
continue-on-error: true
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
|
@ -60,7 +61,7 @@ jobs:
|
|||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set Git http.postBuffer to something high
|
||||
run: git config --global http.postBuffer 524288000
|
||||
|
@ -77,6 +78,7 @@ jobs:
|
|||
|
||||
- name: Install dependencies
|
||||
run: brew install readline coreutils qt5 RfidResearchGroup/proxmark3/arm-none-eabi-gcc openssl
|
||||
continue-on-error: true
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
|
@ -102,7 +104,7 @@ jobs:
|
|||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set Git http.postBuffer to something high
|
||||
run: git config --global http.postBuffer 524288000
|
||||
|
@ -119,6 +121,7 @@ jobs:
|
|||
|
||||
- name: Install dependencies
|
||||
run: brew install readline coreutils qt5 RfidResearchGroup/proxmark3/arm-none-eabi-gcc openssl
|
||||
continue-on-error: true
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
|
|
12
.github/workflows/ubuntu.yml
vendored
12
.github/workflows/ubuntu.yml
vendored
|
@ -20,13 +20,13 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Update apt repos
|
||||
run: sudo apt-get update
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0-dbg 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 libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0 lua5.2 sed libssl-dev
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
|
@ -52,13 +52,13 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Update apt repos
|
||||
run: sudo apt-get update
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0-dbg 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 libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0 lua5.2 sed libssl-dev
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
|
@ -85,13 +85,13 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Update apt repos
|
||||
run: sudo apt-get update
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0-dbg 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 libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0 lua5.2 sed libssl-dev
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
|
|
8
.github/workflows/windows.yml
vendored
8
.github/workflows/windows.yml
vendored
|
@ -48,7 +48,7 @@ jobs:
|
|||
working-directory: C:\ProxSpace
|
||||
run: ./runme64.bat -c "exit"
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: make clean
|
||||
run: make clean
|
||||
|
@ -98,9 +98,9 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: WSL setup
|
||||
uses: Vampire/setup-wsl@v1
|
||||
uses: Vampire/setup-wsl@v2
|
||||
with:
|
||||
distribution: Ubuntu-20.04
|
||||
distribution: Ubuntu-22.04
|
||||
update: "true"
|
||||
additional-packages: git
|
||||
ca-certificates
|
||||
|
@ -134,7 +134,7 @@ jobs:
|
|||
git config --global core.autocrlf false
|
||||
git config --global core.eol lf
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: make clean
|
||||
run: make clean
|
||||
|
|
134
CHANGELOG.md
134
CHANGELOG.md
|
@ -3,7 +3,137 @@ 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...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- 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)
|
||||
- Change `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)
|
||||
|
||||
## [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)
|
||||
- Add command `piv authsign` to get a buffer signed by the selected key (@jmichelp)
|
||||
- Add command `piv scan` which tries to read all known containers on PIV (@jmichelp)
|
||||
- Add support for PIV commands, over wired and contactless interfaces (@jmichelp)
|
||||
- Add `--shallow` option to `hf iclass` reader commands to do shallow (ASK) reader modulation instead of OOK (@nvx)
|
||||
- Improved NXP SLI/SLIX series tag identification (@nvx)
|
||||
- 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 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)
|
||||
- Fixed `trace list -r` (relative times) not working unless `-u` (microseconds) was specified, and made `--frame` respect `-u` and `-r` options (@nvx)
|
||||
- Added detection of magic Gen4 GTU (@DidierA)
|
||||
- Added luascript `hf_i2c_plus_2k_utils` - Script for dumping/modifying user memory of sectors 0 and 1 (@flamebarke)
|
||||
- Added `hf mfu esave` - saves emulator memory to mfu dump file (@DidierA)
|
||||
- Added luascript `hf_mfu_ntag` - Script for configuring NTAG216 configuration pages (@flamebarke)
|
||||
- Changed `hf mf hardnested` - a detection for static encrypted nonces (@iceman1001)
|
||||
- Added requirements.txt file to tools folder. Minimum to run pm3_tests.sh (@iceman1001)
|
||||
- Changed `hf mf hardnested` - now can detect and use MFC EV1 signature sector key (@iceman1001)
|
||||
- Changed `hf mf autopwn` - now can detect and use MFC EV1 signature sector key (@iceman1001)
|
||||
- Fixed `pm3` shell script now automatically detects WSL2 with USBIPD serial ports (@iceman1001)
|
||||
- Fixed `trace list -c` - annotation of CRC bytes now is colored or squared if no ansi colors is supported (@iceman1001)
|
||||
- Fixed `trace list -t mf` - now also finds UID if anticollision is partial captured, to be used for mfkey (@iceman1001)
|
||||
|
||||
## [Radium.4.15864][2022-10-29]
|
||||
- Changed `lf indala sim` - now accepts fc / cn (@iceman1001)
|
||||
- Added `lf indala brute`- brute forcing of 64b Indala ID (@iceman1001)
|
||||
- Added `hf 14a ndefwrite` - write raw NDEF records to TYPE4A tags (@iceman1001)
|
||||
- Changed ndef output to be more dense. Honors verbose now (@iceman1001)
|
||||
- Fixed `hf mf ndefwrite` - now skips not ndef formatted sectors (@iceman1001)
|
||||
- Fixed `hf mf ndefread` - now skips not ndef formatted sectors correctly (@iceman1001)
|
||||
- Fixed `lf hitag` - keep inside the arrays for key/password/nrar (@iceman1001)
|
||||
- Added `hf mf ndefwrite` - write raw NDEF records to MIFARE Classic tag (@iceman1001)
|
||||
- Changed `hf mf cwipe` - swapped the block0 data to genuine manufacture ones (@iceman1001)
|
||||
- Added `hf mf ndefformat` - format a MIFARE Classic tag as NFC tag with Data Exchange Format (NDEF) (@iceman1001)
|
||||
- Changed `hf 14b dump, view` to get correct chip type in case of SRT512 and friends (@DidierA)
|
||||
- Added `hf 15 eview` and `hf 15 esave` - Retrieve emulator image for ISO15693 simulation (@markus-oehme-pg40)
|
||||
- Changed `hf 15 sim` - now supports reader writes (@markus-oehme-pg40)
|
||||
- Added `hf 15 eload` - specify memory image for ISO15693 simulation (@markus-oehme-pg40)
|
||||
- Added `hf 15 sim --blocksize` - configure block size for simulation (@markus-oehme-pg40)
|
||||
- Fixed buffer overflow in mfu ndef decode (@mwalker)
|
||||
- Changed spiffs write/append to send in 8192 chunks to ensure its eraised (@mwalker)
|
||||
- Fixed spiffs dump to ensure to fails correctly if no big_buff was allocated (@mwalker)
|
||||
- Change Client Makefile to respect global flags (@blshkv)
|
||||
- Change Makefile, honors global CC values (@blshkv)
|
||||
- Fixed bad memory handling in MifareSim device side (@iceman1001)
|
||||
- Added json topaz file format (@iceman1001)
|
||||
- Added `hf topaz rdbl, wrbl, view` commands (@iceman1001)
|
||||
- Added more details to the annotations of `hf mfdes list` output (@nvx)
|
||||
- Changed `hf iclass view` and related to suppress consecutive blocks with repeated contents with a `-z` flag, or `prefs set output --dense` (@nvx)
|
||||
- Changed `hf iclass list` to display matched keys on the CHECK command rather than the card response, and made it check for elite keys too (@nvx)
|
||||
- Fixed `hf iclass info` and `hf iclass view` key access info looking at the wrong card config bit (@nvx)
|
||||
- Added `hf gallagher decode` command and fix Gallagher diversification for card master key (@nvx)
|
||||
- Changed `hf texkom reader` - now supports mmbit-002 (kibi-002, kb5004xk1) russian tag (@merlokk)
|
||||
- Added `hf sniff --smode` skip/group adc data to consume less memory. Now it can sniff very long signals (@merlokk)
|
||||
- Added `hf fudan` skeleton commands (@iceman1001)
|
||||
- Added `--reboot-to-bootloader` arg to pm3
|
||||
- Changed `hf 14b raw` - now supports selecting Fuji/Xerox tag (@horror)
|
||||
- Added `hf xerox dump` - dump a Fuji/Xerox tag (@horror)
|
||||
- Added `hf xerox info` - read Fuji/Xerox tag (@horror)
|
||||
- Fixed `hf 14a reader --ecp` to work consistently (@kormax)
|
||||
- Change `trace list -t 14a` to annotate ECP frames of all valid V1 and V2 formats (@kormax)
|
||||
- Added 122 new keys from Flipper Zero community to `mfc_default_keys.dic` (@UberGuidoZ)
|
||||
- Added showing password for the read command in the `lf t55xx sniff` command (@merlokk)
|
||||
- Added reading texcom tk13 and tk17 tags with `hf texkom read` command (@merlokk @iceman1001)
|
||||
- Added simulating texcom tk13 and tk17 tags with `hf texkom sim` command (@merlokk)
|
||||
- Changed `hf mf staticnested` - significant speedups by using two encrypted nonces (@xianglin1998)
|
||||
- Change use of `sprintf` in code to `snprintf` to fix compilation on macOS (@Doridian)
|
||||
- Change `hf mf mad` - it now takes a dump file for offline MAD decoding (@iceman1001)
|
||||
|
@ -64,6 +194,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
|||
- Changed - AID limitations when using Gallagher key diversification (@DarkMatterMatt)
|
||||
- Added new standalone mode `lf_em4100rsww` (@zabszk)
|
||||
- Fixed `hf 15 slixdisable` wrong pass id (@r1ddl3rz)
|
||||
- Added `script run hf_mf_hid_sim.lua` (@micsen)
|
||||
|
||||
## [Frostbit.4.14831][2022-01-11]
|
||||
- Changed Wiegand format lookup - now case-insensitive (@iceman1001)
|
||||
|
@ -1281,7 +1412,10 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
|||
- Mifare simulation, `hf mf sim` (was broken a long time) (@pwpiwi)
|
||||
- Major improvements in LF area and data operations. (@marshmellow42, @iceman1001)
|
||||
- Issues regarding LF simulation (@pwpiwi)
|
||||
- Issue interpreting NXP "get sys info" command return value for icode tags. (@mjacksn)
|
||||
|
||||
### 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 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)
|
||||
|
|
56
Makefile
56
Makefile
|
@ -34,7 +34,7 @@ all clean install uninstall check: %: client/% bootrom/% armsrc/% recovery/% mfk
|
|||
#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
|
||||
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
|
||||
INSTALLSHARES=tools/jtag_openocd traces
|
||||
INSTALLDOCS=doc/*.md doc/md
|
||||
|
@ -65,7 +65,13 @@ ifneq (,$(INSTALLSIMFW))
|
|||
endif
|
||||
ifeq ($(platform),Linux)
|
||||
$(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
|
||||
|
||||
uninstall: common/uninstall
|
||||
|
@ -75,25 +81,32 @@ common/uninstall:
|
|||
ifneq (,$(INSTALLSCRIPTS))
|
||||
$(Q)$(INSTALLSUDO) $(RM) $(foreach script,$(INSTALLSCRIPTS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)$(PATHSEP)$(notdir $(script)))
|
||||
endif
|
||||
|
||||
ifneq (,$(INSTALLSHARES))
|
||||
$(Q)$(INSTALLSUDO) $(RMDIR) $(foreach share,$(INSTALLSHARES),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)$(PATHSEP)$(notdir $(share)))
|
||||
endif
|
||||
|
||||
ifneq (,$(INSTALLDOCS))
|
||||
$(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
|
||||
|
||||
ifneq (,$(INSTALLTOOLS))
|
||||
$(Q)$(INSTALLSUDO) $(RM) $(foreach tool,$(INSTALLTOOLS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)$(PATHSEP)$(notdir $(tool)))
|
||||
endif
|
||||
$(Q)$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)
|
||||
|
||||
$(Q)-$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)
|
||||
|
||||
ifneq (,$(INSTALLSIMFW))
|
||||
$(Q)$(INSTALLSUDO) $(RM) $(foreach fw,$(INSTALLSIMFW),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(notdir $(fw)))
|
||||
endif
|
||||
$(Q)$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
|
||||
|
||||
$(Q)-$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
|
||||
|
||||
ifeq ($(platform),Linux)
|
||||
$(Q)$(INSTALLSUDO) $(RM) $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
|
||||
endif
|
||||
$(Q)$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
|
||||
$(Q)-$(INSTALLSUDO) $(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
|
||||
|
||||
# tests
|
||||
mfkey/check: FORCE
|
||||
|
@ -248,28 +261,39 @@ ifeq ($(PLATFORM_CHANGED),true)
|
|||
$(Q)$(MAKE) --no-print-directory -C recovery clean
|
||||
$(Q)$(MAKE) --no-print-directory -C client clean
|
||||
$(Q)$(MAKE) --no-print-directory -C tools/fpga_compress clean
|
||||
$(Q)echo CACHED_PLATFORM=$(PLATFORM) > .Makefile.options.cache
|
||||
$(Q)echo CACHED_PLATFORM_EXTRAS=$(PLATFORM_EXTRAS) >> .Makefile.options.cache
|
||||
$(Q)echo CACHED_PLATFORM_DEFS=$(PLATFORM_DEFS) >> .Makefile.options.cache
|
||||
$(Q)$(ECHO) CACHED_PLATFORM=$(PLATFORM) > .Makefile.options.cache
|
||||
$(Q)$(ECHO) CACHED_PLATFORM_EXTRAS=$(PLATFORM_EXTRAS) >> .Makefile.options.cache
|
||||
$(Q)$(ECHO) CACHED_PLATFORM_DEFS=$(PLATFORM_DEFS) >> .Makefile.options.cache
|
||||
endif
|
||||
|
||||
# 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
|
||||
udev:
|
||||
sudo cp -rf driver/77-pm3-usb-device-blacklist.rules $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
|
||||
sudo udevadm control --reload-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 trigger --action=change
|
||||
|
||||
# configure system to add user to the dialout group
|
||||
# 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.
|
||||
# Finally, you might need to run the proxmark3 client under SUDO on some systems
|
||||
accessrights:
|
||||
ifneq ($(wildcard /etc/arch-release),)
|
||||
#If user is running ArchLinux, use specific command and group
|
||||
$(Q)sudo usermod -aG uucp $(USER)
|
||||
$(Q)getent group bluetooth >/dev/null && sudo usermod -aG bluetooth $(USER) || true
|
||||
$(Q)$(SUDO) $(USERMOD) uucp $(USER)
|
||||
$(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
|
||||
$(Q)sudo adduser $(USER) dialout
|
||||
$(Q)getent group bluetooth >/dev/null && sudo adduser $(USER) bluetooth || true
|
||||
$(Q)$(SUDO) $(ADDUSER) $(USER) dialout
|
||||
$(Q)$(GETENT_BL) >/dev/null && $(SUDO) $(ADDUSER) $(USER) bluetooth || true
|
||||
endif
|
||||
|
||||
# easy printing of MAKE VARIABLES
|
||||
|
|
|
@ -29,18 +29,17 @@ GZIP = gzip
|
|||
MKDIR = mkdir -p
|
||||
RM = rm -f
|
||||
RMDIR = rm -rf
|
||||
# rmdir only if dir is empty, tolerate failure
|
||||
RMDIR_SOFT = -rmdir
|
||||
# rmdir only if dir is empty, you must add "-" when using it to tolerate failure
|
||||
RMDIR_SOFT = rmdir
|
||||
MV = mv
|
||||
TOUCH = touch
|
||||
FALSE = false
|
||||
TAR = tar
|
||||
TARFLAGS ?= -v --ignore-failed-read -r
|
||||
TARFLAGS += -C .. -f
|
||||
CROSS ?= arm-none-eabi-
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
LD = g++
|
||||
CROSS ?= arm-none-eabi-
|
||||
CC ?= gcc
|
||||
CXX ?= g++
|
||||
SH = sh
|
||||
BASH = bash
|
||||
PERL = perl
|
||||
|
@ -48,6 +47,14 @@ SWIG = swig
|
|||
CC_VERSION = $(shell $(CC) -dumpversion 2>/dev/null|sed 's/\..*//')
|
||||
CC_VERSION := $(or $(strip $(CC_VERSION)),0)
|
||||
|
||||
ECHO = echo
|
||||
SUDO = sudo
|
||||
USERMOD = usermod -aG
|
||||
ADDUSER = adduser
|
||||
GETENT_BL = getent group bluetooth
|
||||
|
||||
|
||||
|
||||
PATHSEP=/
|
||||
PREFIX ?= /usr/local
|
||||
UDEV_PREFIX ?= /etc/udev/rules.d
|
||||
|
@ -78,9 +85,13 @@ else
|
|||
endif
|
||||
|
||||
ifeq ($(USE_BREW),1)
|
||||
BREW_PREFIX = $(shell brew --prefix 2>/dev/null)
|
||||
ifeq ($(strip $(BREW_PREFIX)),)
|
||||
USE_BREW = 0
|
||||
ifneq ($(strip $(HOMEBREW_PREFIX)),)
|
||||
BREW_PREFIX = $(HOMEBREW_PREFIX)
|
||||
else
|
||||
BREW_PREFIX = $(shell brew --prefix 2>/dev/null)
|
||||
ifeq ($(strip $(BREW_PREFIX)),)
|
||||
USE_BREW = 0
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
|
|
@ -86,8 +86,8 @@ $(BINDIR)/$(LIB_A): $(MYOBJS) $(MYCXXOBJS)
|
|||
$(Q)$(RANLIB) $@
|
||||
|
||||
$(BINDIR)/% : $(OBJDIR)/%.o $(MYOBJS) $(MYCXXOBJS) $(MYLIBS)
|
||||
$(info [=] LD $(notdir $@))
|
||||
$(Q)$(LD) $(LDFLAGS) $(MYOBJS) $(MYCXXOBJS) $< -o $@ $(MYLIBS) $(MYLDLIBS)
|
||||
$(info [=] CXX $(notdir $@))
|
||||
$(Q)$(CXX) $(LDFLAGS) $(MYOBJS) $(MYCXXOBJS) $< -o $@ $(MYLIBS) $(MYLDLIBS)
|
||||
|
||||
%.o: %.c
|
||||
$(OBJDIR)/%.o : %.c $(OBJDIR)/%.d | $(OBJDIR)
|
||||
|
|
|
@ -5,8 +5,23 @@ PLATFORM=PM3RDV4
|
|||
#PLATFORM=PM3GENERIC
|
||||
# If you want more than one PLATFORM_EXTRAS option, separate them by spaces:
|
||||
#PLATFORM_EXTRAS=BTADDON
|
||||
#PLATFORM_EXTRAS=FLASH
|
||||
#PLATFORM_EXTRAS=BTADDON FLASH
|
||||
#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:
|
||||
# Install package "ccache" -> Debian/Ubuntu: /usr/lib/ccache, Fedora/CentOS/RHEL: /usr/lib64/ccache
|
||||
# And uncomment the following line
|
||||
|
|
20
README.md
20
README.md
|
@ -83,7 +83,7 @@ We define generic Proxmark3 platforms as following devices.
|
|||
- **Note**: unknown pin assignments.
|
||||
- ⚠ Ryscorp Proxmark3 Pro
|
||||
- **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
|
||||
- **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.
|
||||
|
@ -93,24 +93,30 @@ We define generic Proxmark3 platforms as following devices.
|
|||
- ⚠ VX
|
||||
- **Note**: unknown device hw
|
||||
- ⚠ 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**:
|
||||
> 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.
|
||||
> 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?
|
||||
|
||||
Proxmark3 RDV4 hardware modifications:
|
||||
* added flash memory 256kb
|
||||
* added flash memory 256KB
|
||||
* added smart card module
|
||||
* added FPC connector for peripherals such as Bluetooth+battery addon
|
||||
* improved antennas
|
||||
|
@ -200,7 +206,7 @@ The official PM3-GUI from Gaucho will not work. Not to mention is quite old and
|
|||
|
||||
## Official channels
|
||||
Where do you find the community?
|
||||
- [RFID Hacking community discord server](https://discord.gg/iceman)
|
||||
- [RFID Hacking community discord server](https://t.ly/d4_C)
|
||||
- [Proxmark3 IRC channel](https://web.libera.chat/?channels=#proxmark3)
|
||||
- [Proxmark3 sub reddit](https://www.reddit.com/r/proxmark3/)
|
||||
- [Proxmark3 forum](http://www.proxmark.org/forum/index.php)
|
||||
|
|
15
SECURITY.md
Normal file
15
SECURITY.md
Normal 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.
|
|
@ -35,6 +35,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \
|
|||
-ffunction-sections -fdata-sections
|
||||
|
||||
SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c lfadc.c
|
||||
SRC_HF = hfops.c
|
||||
SRC_ISO15693 = iso15693.c iso15693tools.c
|
||||
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c
|
||||
#UNUSED: mifaresniff.c
|
||||
|
@ -132,6 +133,7 @@ THUMBSRC = start.c \
|
|||
$(SRC_EM4x50) \
|
||||
$(SRC_EM4x70) \
|
||||
$(SRC_SPIFFS) \
|
||||
$(SRC_HF) \
|
||||
$(SRC_ISO14443a) \
|
||||
$(SRC_ISO14443b) \
|
||||
$(SRC_CRAPTO1) \
|
||||
|
@ -150,7 +152,8 @@ THUMBSRC = start.c \
|
|||
BigBuf.c \
|
||||
ticks.c \
|
||||
clocks.c \
|
||||
hfsnoop.c
|
||||
hfsnoop.c \
|
||||
generator.c
|
||||
|
||||
|
||||
# These are to be compiled in ARM mode
|
||||
|
@ -182,7 +185,7 @@ showinfo:
|
|||
.DELETE_ON_ERROR:
|
||||
|
||||
# version_pm3.c should be remade 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 $@)
|
||||
$(Q)$(SH) ../tools/mkversion.sh > $@ || $(CP) $< $@
|
||||
|
||||
|
@ -254,7 +257,7 @@ uninstall:
|
|||
$(info [@] Uninstalling fullimage from $(DESTDIR)$(PREFIX)...)
|
||||
$(Q)$(INSTALLSUDO) $(RM) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(INSTALLFWTAG)
|
||||
|
||||
.PHONY: all clean help install uninstall
|
||||
.PHONY: all clean help install uninstall .FORCE
|
||||
help:
|
||||
@echo Multi-OS Makefile, you are running on $(DETECTED_OS)
|
||||
@echo Possible targets:
|
||||
|
|
|
@ -50,12 +50,18 @@ define KNOWN_STANDALONE_DEFINITIONS
|
|||
| LF_ICEHID | LF HID collector to flashmem |
|
||||
| (RDV4 only) | |
|
||||
+----------------------------------------------------------+
|
||||
| LF_NEDAP_SIM | LF Nedap ID simple simulator |
|
||||
| | |
|
||||
+----------------------------------------------------------+
|
||||
| LF_NEXID | LF Nexwatch collector to flashmem |
|
||||
| (RDV4 only) | |
|
||||
+----------------------------------------------------------+
|
||||
| LF_PROXBRUTE | HID ProxII bruteforce |
|
||||
| | - Brad Antoniewicz |
|
||||
+----------------------------------------------------------+
|
||||
| LF_PROX2BRUTE | HID ProxII bruteforce v2 |
|
||||
| | |
|
||||
+----------------------------------------------------------+
|
||||
| LF_SAMYRUN | HID26 read/clone/sim |
|
||||
| (default) | - Samy Kamkar |
|
||||
+----------------------------------------------------------+
|
||||
|
@ -118,11 +124,14 @@ define KNOWN_STANDALONE_DEFINITIONS
|
|||
+----------------------------------------------------------+
|
||||
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 += LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_NEDAP_SIM LF_NEXID LF_PROXBRUTE LF_PROX2BRUTE LF_SAMYRUN LF_THAREXDE
|
||||
STANDALONE_MODES += HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_AVEFUL HF_BOG HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_REBLAY HF_TCPRST HF_TMUDFORD HF_YOUNG
|
||||
STANDALONE_MODES += DANKARMULTI
|
||||
STANDALONE_MODES_REQ_BT := HF_REBLAY
|
||||
STANDALONE_MODES_REQ_SMARTCARD :=
|
||||
STANDALONE_MODES_REQ_FLASH := LF_HIDFCBRUTE LF_ICEHID LF_NEXID LF_THAREXDE HF_BOG HF_COLIN HF_ICECLASS HF_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)),)
|
||||
STANDALONE_PLATFORM_DEFS += -DWITH_STANDALONE_$(STANDALONE)
|
||||
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_SMARTCARD)),)
|
||||
|
|
|
@ -21,13 +21,21 @@ SRC_STANDALONE = placeholder.c
|
|||
ifneq (,$(findstring WITH_STANDALONE_LF_SKELETON,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_skeleton.c
|
||||
endif
|
||||
# WITH_STANDALONE_LF_SAMYRUN
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_SAMYRUN,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_samyrun.c
|
||||
# WITH_STANDALONE_LF_EM4100EMUL
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100EMUL,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_em4100emul.c
|
||||
endif
|
||||
# WITH_STANDALONE_LF_PROXBRUTE
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_PROXBRUTE,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_proxbrute.c
|
||||
# WITH_STANDALONE_LF_EM4100RSWB
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RSWB,$(APP_CFLAGS)))
|
||||
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
|
||||
# WITH_STANDALONE_LF_HIDBRUTE
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_HIDBRUTE,$(APP_CFLAGS)))
|
||||
|
@ -37,21 +45,33 @@ endif
|
|||
ifneq (,$(findstring WITH_STANDALONE_LF_HIDFCBRUTE,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_hidfcbrute.c
|
||||
endif
|
||||
# WITH_STANDALONE_HF_YOUNG
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_YOUNG,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_young.c
|
||||
# WITH_STANDALONE_LF_ICEHID
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_icehid.c
|
||||
endif
|
||||
# WITH_STANDALONE_HF_MATTYRUN
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_MATTYRUN,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_mattyrun.c
|
||||
# WITH_STANDALONE_LF_NEDAP_SIM
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_NEDAP_SIM,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_nedap_sim.c
|
||||
endif
|
||||
# WITH_STANDALONE_HF_COLIN
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_COLIN,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = vtsend.c hf_colin.c frozen.c nprintf.c
|
||||
# WITH_STANDALONE_LF_NEXID
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_NEXID,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_nexid.c
|
||||
endif
|
||||
# WITH_STANDALONE_HF_BOG
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_BOG,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_bog.c
|
||||
# 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
|
||||
# WITH_STANDALONE_HF_14ASNIFF
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_14ASNIFF,$(APP_CFLAGS)))
|
||||
|
@ -69,33 +89,21 @@ endif
|
|||
ifneq (,$(findstring WITH_STANDALONE_HF_AVEFUL,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_aveful.c
|
||||
endif
|
||||
# WITH_STANDALONE_HF_TCPRST
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_TCPRST,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_tcprst.c
|
||||
# WITH_STANDALONE_HF_BOG
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_BOG,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_bog.c
|
||||
endif
|
||||
# WITH_STANDALONE_LF_ICEHID
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_icehid.c
|
||||
# WITH_STANDALONE_HF_COLIN
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_COLIN,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = vtsend.c hf_colin.c frozen.c nprintf.c
|
||||
endif
|
||||
# WITH_STANDALONE_LF_NEXID
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_NEXID,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_nexid.c
|
||||
# WITH_STANDALONE_HF_CRAFTBYTE
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_CRAFTBYTE,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_craftbyte.c
|
||||
endif
|
||||
# WITH_STANDALONE_LF_EM4100EMUL
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100EMUL,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_em4100emul.c
|
||||
endif
|
||||
# WITH_STANDALONE_LF_EM4100RSWB
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RSWB,$(APP_CFLAGS)))
|
||||
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
|
||||
# WITH_STANDALONE_HF_ICECLASS
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_ICECLASS,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_iceclass.c
|
||||
endif
|
||||
# WITH_STANDALONE_HF_LEGIC
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_LEGIC,$(APP_CFLAGS)))
|
||||
|
@ -105,33 +113,33 @@ endif
|
|||
ifneq (,$(findstring WITH_STANDALONE_HF_LEGICSIM,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_legicsim.c
|
||||
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
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_MSDSAL,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_msdsal.c
|
||||
endif
|
||||
# WITH_STANDALONE_HF_ICECLASS
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_ICECLASS,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_iceclass.c
|
||||
# WITH_STANDALONE_HF_REBLAY
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_REBLAY,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_reblay.c
|
||||
endif
|
||||
# WITH_STANDALONE_LF_THAREXDE
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_THAREXDE,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_tharexde.c
|
||||
endif
|
||||
# WITH_STANDALONE_HF_CRAFTBYTE
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_CRAFTBYTE,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_craftbyte.c
|
||||
# WITH_STANDALONE_HF_TCPRST
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_TCPRST,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_tcprst.c
|
||||
endif
|
||||
# WITH_STANDALONE_HF_TMUDFORD
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_TMUDFORD,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_tmudford.c
|
||||
endif
|
||||
# WITH_STANDALONE_HF_REBLAY
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_REBLAY,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_reblay.c
|
||||
endif
|
||||
# WITH_STANDALONE_HF_MFCSIM
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_MFCSIM,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_mfcsim.c
|
||||
# WITH_STANDALONE_HF_YOUNG
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_YOUNG,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_young.c
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring WITH_STANDALONE_DANKARMULTI,$(APP_CFLAGS)))
|
||||
|
|
|
@ -43,9 +43,10 @@
|
|||
#define ICE_STATE_ATTACK 2
|
||||
#define ICE_STATE_READER 3
|
||||
#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.
|
||||
|
@ -56,6 +57,7 @@
|
|||
//#define ICE_USE ICE_STATE_READER
|
||||
//#define ICE_USE ICE_STATE_CONFIGCARD
|
||||
//#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,
|
||||
.do_auth = true,
|
||||
.send_reply = false,
|
||||
.shallow_mod = false,
|
||||
};
|
||||
memcpy(auth.key, legacy_aa1_key, sizeof(auth.key));
|
||||
|
||||
|
@ -333,7 +336,7 @@ static int reader_dump_mode(void) {
|
|||
|
||||
// select tag.
|
||||
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) {
|
||||
switch_off();
|
||||
continue;
|
||||
|
@ -382,7 +385,7 @@ static int reader_dump_mode(void) {
|
|||
|
||||
// main read loop
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
@ -394,7 +397,7 @@ static int reader_dump_mode(void) {
|
|||
auth.use_credit_key = true;
|
||||
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) {
|
||||
|
||||
// sanity check of CSN.
|
||||
|
@ -408,7 +411,7 @@ static int reader_dump_mode(void) {
|
|||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
@ -458,6 +461,7 @@ static int dump_sim_mode(void) {
|
|||
.use_credit_key = false,
|
||||
.do_auth = true,
|
||||
.send_reply = false,
|
||||
.shallow_mod = false,
|
||||
};
|
||||
memcpy(auth.key, legacy_aa1_key, sizeof(auth.key));
|
||||
|
||||
|
@ -469,7 +473,7 @@ static int dump_sim_mode(void) {
|
|||
|
||||
// select tag.
|
||||
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) {
|
||||
switch_off();
|
||||
continue;
|
||||
|
@ -518,7 +522,7 @@ static int dump_sim_mode(void) {
|
|||
|
||||
// main read loop
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
@ -530,7 +534,7 @@ static int dump_sim_mode(void) {
|
|||
auth.use_credit_key = true;
|
||||
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) {
|
||||
|
||||
// sanity check of CSN.
|
||||
|
@ -544,7 +548,7 @@ static int dump_sim_mode(void) {
|
|||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
@ -718,6 +722,16 @@ void RunMod(void) {
|
|||
mode = ICE_STATE_NONE;
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ void RunMod(void) {
|
|||
//Indicate which card will be simulated
|
||||
LED(i, 0);
|
||||
|
||||
//Try to load dump form flash
|
||||
//Try to load dump from flash
|
||||
sprintf(cur_dump_file, HF_LEGICSIM_DUMPFILE_SIM, i);
|
||||
Dbprintf(_YELLOW_("[Slot: %d] Try to load dump file: %s"), i, cur_dump_file);
|
||||
if (!fill_eml_from_file(cur_dump_file)) {
|
||||
|
|
|
@ -56,10 +56,11 @@ static char cur_dump_file[22] = {0};
|
|||
|
||||
static bool fill_eml_from_file(char *dumpfile) {
|
||||
// check file exist
|
||||
if (!exists_in_spiffs(dumpfile)) {
|
||||
if (exists_in_spiffs(dumpfile) == false) {
|
||||
Dbprintf(_RED_("Dump file %s not found!"), dumpfile);
|
||||
return false;
|
||||
}
|
||||
|
||||
//check dumpfile size
|
||||
uint32_t size = size_in_spiffs(dumpfile);
|
||||
if (size != DUMP_SIZE) {
|
||||
|
@ -67,9 +68,12 @@ static bool fill_eml_from_file(char *dumpfile) {
|
|||
BigBuf_free();
|
||||
return false;
|
||||
}
|
||||
|
||||
//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);
|
||||
}
|
||||
|
||||
emlClearMem();
|
||||
uint8_t *emCARD = BigBuf_get_EM_addr();
|
||||
rdv40_spiffs_read_as_filetype(dumpfile, emCARD, size, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
|
@ -77,7 +81,7 @@ static bool fill_eml_from_file(char *dumpfile) {
|
|||
}
|
||||
|
||||
static bool write_file_from_eml(char *dumpfile) {
|
||||
if (!exists_in_spiffs(dumpfile)) {
|
||||
if (exists_in_spiffs(dumpfile) == false) {
|
||||
Dbprintf(_RED_("Dump file %s not found!"), dumpfile);
|
||||
return false;
|
||||
}
|
||||
|
@ -99,14 +103,18 @@ void RunMod(void) {
|
|||
|
||||
bool flag_has_dumpfile = false;
|
||||
for (int i = 1;; i++) {
|
||||
|
||||
//Exit! usbcommand break
|
||||
if (data_available()) break;
|
||||
|
||||
//Infinite loop
|
||||
// infinite loop
|
||||
if (i > 15) {
|
||||
if (!flag_has_dumpfile)
|
||||
break; //still no dump file found
|
||||
i = 1; //next loop
|
||||
// still no dump file found
|
||||
if (flag_has_dumpfile == false) {
|
||||
break;
|
||||
}
|
||||
// next loop
|
||||
i = 1;
|
||||
}
|
||||
|
||||
//Indicate which card will be simulated
|
||||
|
@ -115,7 +123,7 @@ void RunMod(void) {
|
|||
//Try to load dump form flash
|
||||
sprintf(cur_dump_file, HF_MFCSIM_DUMPFILE_SIM, i);
|
||||
Dbprintf(_YELLOW_("[Slot: %d] Try to load dump file: %s"), i, cur_dump_file);
|
||||
if (!fill_eml_from_file(cur_dump_file)) {
|
||||
if (fill_eml_from_file(cur_dump_file) == false) {
|
||||
Dbprintf(_YELLOW_("[Slot: %d] Dump load Failed, Next one!"), i);
|
||||
LEDsoff();
|
||||
continue;
|
||||
|
@ -145,8 +153,10 @@ void RunMod(void) {
|
|||
}
|
||||
Dbprintf(_YELLOW_("[Slot: %d] Write Success! Change to next one!"), i);
|
||||
}
|
||||
if (!flag_has_dumpfile)
|
||||
|
||||
if (flag_has_dumpfile == false) {
|
||||
Dbprintf("No dump file found!");
|
||||
}
|
||||
Dbprintf("Breaked! Exit standalone mode!");
|
||||
SpinErr(15, 200, 3);
|
||||
return;
|
||||
|
|
|
@ -386,28 +386,28 @@ void RunMod(void) {
|
|||
|
||||
// received a HALT
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) {
|
||||
DbpString(_YELLOW_("+") "Received a HALT");
|
||||
// DbpString(_YELLOW_("+") "Received a HALT");
|
||||
p_response = NULL;
|
||||
|
||||
// received a WAKEUP
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) {
|
||||
DbpString(_YELLOW_("+") "WAKEUP Received");
|
||||
// DbpString(_YELLOW_("+") "WAKEUP Received");
|
||||
prevCmd = 0;
|
||||
p_response = &responses[RESP_INDEX_ATQA];
|
||||
|
||||
// received request for UID (cascade 1)
|
||||
} 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];
|
||||
|
||||
// received a SELECT (cascade 1)
|
||||
} 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];
|
||||
|
||||
// received a RATS request
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) {
|
||||
DbpString(_YELLOW_("+") "Request for RATS");
|
||||
// DbpString(_YELLOW_("+") "Request for RATS");
|
||||
prevCmd = 0;
|
||||
p_response = &responses[RESP_INDEX_RATS];
|
||||
|
||||
|
|
|
@ -314,24 +314,24 @@ void RunMod() {
|
|||
}
|
||||
}
|
||||
if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) { // Received a REQUEST
|
||||
DbpString(_YELLOW_("+") "REQUEST Received");
|
||||
// DbpString(_YELLOW_("+") "REQUEST Received");
|
||||
p_response = &responses[RESP_INDEX_ATQA];
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) { // Received a HALT
|
||||
DbpString(_YELLOW_("+") "Received a HALT");
|
||||
// DbpString(_YELLOW_("+") "Received a HALT");
|
||||
p_response = NULL;
|
||||
resp = 0;
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) { // Received a WAKEUP
|
||||
DbpString(_YELLOW_("+") "WAKEUP Received");
|
||||
// DbpString(_YELLOW_("+") "WAKEUP Received");
|
||||
p_response = &responses[RESP_INDEX_ATQA];
|
||||
resp = 0;
|
||||
} else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 2) { // Received request for UID (cascade 1)
|
||||
DbpString(_YELLOW_("+") "Request for UID C1");
|
||||
// DbpString(_YELLOW_("+") "Request for UID C1");
|
||||
p_response = &responses[RESP_INDEX_UIDC1];
|
||||
} else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) { // Received a SELECT (cascade 1)
|
||||
DbpString(_YELLOW_("+") "Request for SELECT S1");
|
||||
// DbpString(_YELLOW_("+") "Request for SELECT S1");
|
||||
p_response = &responses[RESP_INDEX_SAKC1];
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request
|
||||
DbpString(_YELLOW_("+") "Request for RATS");
|
||||
// DbpString(_YELLOW_("+") "Request for RATS");
|
||||
p_response = &responses[RESP_INDEX_RATS];
|
||||
resp = 1;
|
||||
} else if (receivedCmd[0] == 0xf2 && len == 4) { // ACKed - Time extension
|
||||
|
|
|
@ -75,7 +75,8 @@ void RunMod(void) {
|
|||
} else if (state == STATE_EMUL) {
|
||||
Iso15693InitTag();
|
||||
Dbprintf("Starting simulation, press pm3-button to stop and go back to search state.");
|
||||
SimTagIso15693(card.uid);
|
||||
// default block size is 4
|
||||
SimTagIso15693(card.uid, 4);
|
||||
|
||||
state = STATE_READ;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
// then from shell:
|
||||
// hexdump lf.bin -e '5/1 "%02X" /0 "\n"'
|
||||
//
|
||||
// To recall only LAST stored ID from flash use lf-last instead of lf file.
|
||||
// To recall only LAST stored ID from flash use lf-last instead of lf file.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// Modes of operation:
|
||||
|
|
207
armsrc/Standalone/lf_nedap_sim.c
Normal file
207
armsrc/Standalone/lf_nedap_sim.c
Normal 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
|
||||
}
|
108
armsrc/Standalone/lf_prox2brute.c
Normal file
108
armsrc/Standalone/lf_prox2brute.c
Normal 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
|
||||
}
|
|
@ -100,6 +100,8 @@ STANDALONE_MODES_REQ_FLASH :=
|
|||
STANDALONE_MODES_REQ_BT :=
|
||||
```
|
||||
|
||||
Please respect alphabetic order!
|
||||
|
||||
## Update MAKEFILE.INC
|
||||
^[Top](#top)
|
||||
|
||||
|
@ -117,6 +119,8 @@ ifneq (,$(findstring WITH_STANDALONE_LF_FOO,$(APP_CFLAGS)))
|
|||
endif
|
||||
```
|
||||
|
||||
Please respect alphabetic order!
|
||||
|
||||
## Adding identification string of your mode
|
||||
^[Top](#top)
|
||||
|
||||
|
@ -174,9 +178,11 @@ Once you're ready to share your mode, please
|
|||
|
||||
* 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 `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
|
||||
|
||||
|
|
242
armsrc/appmain.c
242
armsrc/appmain.c
|
@ -33,6 +33,7 @@
|
|||
#include "legicrf.h"
|
||||
#include "BigBuf.h"
|
||||
#include "iclass_cmd.h"
|
||||
#include "hfops.h"
|
||||
#include "iso14443a.h"
|
||||
#include "iso14443b.h"
|
||||
#include "iso15693.h"
|
||||
|
@ -344,7 +345,7 @@ static void print_debug_level(void) {
|
|||
char dbglvlstr[20] = {0};
|
||||
switch (g_dbglevel) {
|
||||
case DBG_NONE:
|
||||
sprintf(dbglvlstr, "none");
|
||||
sprintf(dbglvlstr, "off");
|
||||
break;
|
||||
case DBG_ERROR:
|
||||
sprintf(dbglvlstr, "error");
|
||||
|
@ -452,6 +453,12 @@ static void SendCapabilities(void) {
|
|||
capabilities.baudrate = g_usart_baudrate;
|
||||
#endif
|
||||
|
||||
#ifdef RDV4
|
||||
capabilities.is_rdv4 = true;
|
||||
#else
|
||||
capabilities.is_rdv4 = false;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_FLASH
|
||||
capabilities.compiled_with_flash = true;
|
||||
capabilities.hw_available_flash = FlashInit();
|
||||
|
@ -1220,6 +1227,10 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
em4x70_write_key((em4x70_data_t *)packet->data.asBytes, true);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_EM4X70_BRUTE: {
|
||||
em4x70_brute((em4x70_data_t *)packet->data.asBytes, true);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_ZX8211
|
||||
|
@ -1255,12 +1266,27 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
ReaderIso15693(NULL);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO15693_EML_CLEAR: {
|
||||
EmlClearIso15693();
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO15693_EML_SETMEM: {
|
||||
struct p {
|
||||
uint32_t offset;
|
||||
uint8_t count;
|
||||
uint8_t data[];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
EmlSetMemIso15693(payload->count, payload->data, payload->offset);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO15693_SIMULATE: {
|
||||
struct p {
|
||||
uint8_t uid[8];
|
||||
uint8_t block_size;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
SimTagIso15693(payload->uid);
|
||||
SimTagIso15693(payload->uid, payload->block_size);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO15693_CSETUID: {
|
||||
|
@ -1271,20 +1297,76 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
SetTag15693Uid(payload->uid);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO15693_SLIX_L_DISABLE_PRIVACY: {
|
||||
case CMD_HF_ISO15693_SLIX_DISABLE_EAS: {
|
||||
struct p {
|
||||
uint8_t pwd[4];
|
||||
bool usepwd;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
DisablePrivacySlixLIso15693(payload->pwd);
|
||||
DisableEAS_AFISlixIso15693(payload->pwd, payload->usepwd);
|
||||
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 {
|
||||
uint8_t pwd[4];
|
||||
} PACKED;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1384,6 +1466,26 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_GENERAL_HF
|
||||
case CMD_HF_ACQ_RAW_ADC: {
|
||||
uint32_t samplesCount = 0;
|
||||
memcpy(&samplesCount, packet->data.asBytes, 4);
|
||||
HfReadADC(samplesCount, true);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_TEXKOM_SIMULATE: {
|
||||
struct p {
|
||||
uint8_t data[8];
|
||||
uint8_t modulation;
|
||||
uint32_t timeout;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
HfSimulateTkm(payload->data, payload->modulation, payload->timeout);
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef WITH_ISO14443a
|
||||
case CMD_HF_ISO14443A_PRINT_CONFIG: {
|
||||
printHf14aConfig();
|
||||
|
@ -1428,6 +1530,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
iso14443a_antifuzz(payload->flag);
|
||||
break;
|
||||
}
|
||||
// EPA related
|
||||
case CMD_HF_EPA_COLLECT_NONCE: {
|
||||
EPA_PACE_Collect_Nonce(packet);
|
||||
break;
|
||||
|
@ -1436,6 +1539,11 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
EPA_PACE_Replay(packet);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_EPA_PACE_SIMULATE: {
|
||||
EPA_PACE_Simulate(packet);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_HF_MIFARE_READER: {
|
||||
struct p {
|
||||
uint8_t first_run;
|
||||
|
@ -1476,7 +1584,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
case CMD_HF_MIFAREU_WRITEBL: {
|
||||
|
@ -1578,7 +1686,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
MifareECardLoadExt(payload->sectorcnt, payload->keytype);
|
||||
break;
|
||||
}
|
||||
// Work with "magic Chinese" card
|
||||
// Gen1a / 1b - "magic Chinese" card
|
||||
case CMD_HF_MIFARE_CSETBL: {
|
||||
MifareCSetBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
||||
break;
|
||||
|
@ -1605,13 +1713,53 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
MifareGen3Freez();
|
||||
break;
|
||||
}
|
||||
// Gen 4 GTU magic cards
|
||||
case CMD_HF_MIFARE_G4_RDBL: {
|
||||
struct p {
|
||||
uint8_t blockno;
|
||||
uint8_t pwd[4];
|
||||
uint8_t workFlags;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
MifareG4ReadBlk(payload->blockno, payload->pwd);
|
||||
MifareG4ReadBlk(payload->blockno, payload->pwd, payload->workFlags);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFARE_G4_WRBL: {
|
||||
struct p {
|
||||
uint8_t blockno;
|
||||
uint8_t pwd[4];
|
||||
uint8_t data[16]; // data to be written
|
||||
uint8_t workFlags;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
MifareG4WriteBlk(payload->blockno, payload->pwd, payload->data, payload->workFlags);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFARE_G4_GDM_CONFIG: {
|
||||
struct p {
|
||||
uint8_t key[6];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
MifareReadConfigBlockGDM(payload->key);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFARE_G4_GDM_WRCFG: {
|
||||
struct p {
|
||||
uint8_t data[16];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
MifareWriteConfigBlockGDM(payload->data);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFARE_G4_GDM_WRBL: {
|
||||
struct p {
|
||||
uint8_t blockno;
|
||||
uint8_t keytype;
|
||||
uint8_t key[6];
|
||||
uint8_t data[16]; // data to be written
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
MifareWriteBlockGDM(payload->blockno, payload->keytype, payload->key, payload->data);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFARE_PERSONALIZE_UID: {
|
||||
|
@ -1763,11 +1911,13 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
struct p {
|
||||
uint32_t samplesToSkip;
|
||||
uint32_t triggersToSkip;
|
||||
uint8_t skipMode;
|
||||
uint8_t skipRatio;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *)packet->data.asBytes;
|
||||
|
||||
uint16_t len = 0;
|
||||
int res = HfSniff(payload->samplesToSkip, payload->triggersToSkip, &len);
|
||||
int res = HfSniff(payload->samplesToSkip, payload->triggersToSkip, &len, payload->skipMode, payload->skipRatio);
|
||||
|
||||
struct {
|
||||
uint16_t len;
|
||||
|
@ -2143,20 +2293,26 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
uint32_t size = packet->oldarg[1];
|
||||
|
||||
uint8_t *buff = BigBuf_malloc(size);
|
||||
rdv40_spiffs_read_as_filetype((char *)filename, (uint8_t *)buff, size, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
if (buff == NULL) {
|
||||
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Could not allocate buffer");
|
||||
// Trigger a finish downloading signal with an PM3_EMALLOC
|
||||
reply_ng(CMD_SPIFFS_DOWNLOAD, PM3_EMALLOC, NULL, 0);
|
||||
} else {
|
||||
rdv40_spiffs_read_as_filetype((char *)filename, (uint8_t *)buff, size, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
// arg0 = filename
|
||||
// arg1 = size
|
||||
// arg2 = RFU
|
||||
|
||||
// arg0 = filename
|
||||
// arg1 = size
|
||||
// arg2 = RFU
|
||||
|
||||
for (size_t i = 0; i < size; i += PM3_CMD_DATA_SIZE) {
|
||||
size_t len = MIN((size - i), PM3_CMD_DATA_SIZE);
|
||||
int result = reply_old(CMD_SPIFFS_DOWNLOADED, i, len, 0, buff + i, len);
|
||||
if (result != PM3_SUCCESS)
|
||||
Dbprintf("transfer to client failed :: | bytes between %d - %d (%d) | result: %d", i, i + len, len, result);
|
||||
for (size_t i = 0; i < size; i += PM3_CMD_DATA_SIZE) {
|
||||
size_t len = MIN((size - i), PM3_CMD_DATA_SIZE);
|
||||
int result = reply_old(CMD_SPIFFS_DOWNLOADED, i, len, 0, buff + i, len);
|
||||
if (result != PM3_SUCCESS)
|
||||
Dbprintf("transfer to client failed :: | bytes between %d - %d (%d) | result: %d", i, i + len, len, result);
|
||||
}
|
||||
// Trigger a finish downloading signal with an ACK frame
|
||||
reply_ng(CMD_SPIFFS_DOWNLOAD, PM3_SUCCESS, NULL, 0);
|
||||
BigBuf_free();
|
||||
}
|
||||
// Trigger a finish downloading signal with an ACK frame
|
||||
reply_ng(CMD_SPIFFS_DOWNLOAD, PM3_SUCCESS, NULL, 0);
|
||||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
|
@ -2263,6 +2419,30 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
case CMD_SPIFFS_ELOAD: {
|
||||
LED_B_ON();
|
||||
|
||||
uint8_t *em = BigBuf_get_EM_addr();
|
||||
if (em == NULL) {
|
||||
reply_ng(CMD_SPIFFS_ELOAD, PM3_EMALLOC, NULL, 0);
|
||||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
|
||||
char *fn = (char *)packet->data.asBytes;
|
||||
|
||||
uint32_t size = size_in_spiffs(fn);
|
||||
if (size == 0) {
|
||||
reply_ng(CMD_SPIFFS_ELOAD, PM3_SUCCESS, NULL, 0);
|
||||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
|
||||
rdv40_spiffs_read_as_filetype(fn, em, size, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
reply_ng(CMD_SPIFFS_ELOAD, PM3_SUCCESS, NULL, 0);
|
||||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
case CMD_FLASHMEM_SET_SPIBAUDRATE: {
|
||||
if (packet->length != sizeof(uint32_t))
|
||||
break;
|
||||
|
@ -2318,8 +2498,11 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
if (page < 3)
|
||||
if (page < 3) {
|
||||
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);
|
||||
LED_B_OFF();
|
||||
|
@ -2521,7 +2704,18 @@ void __attribute__((noreturn)) AppMain(void) {
|
|||
#endif
|
||||
|
||||
#ifdef WITH_SMARTCARD
|
||||
I2C_init();
|
||||
I2C_init(false);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_FLASH
|
||||
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
|
||||
|
||||
#ifdef WITH_FPC_USART
|
||||
|
|
|
@ -131,7 +131,7 @@ static int reply_ng_internal(uint16_t cmd, int16_t status, const uint8_t *data,
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ extern bool g_reply_via_fpc;
|
|||
extern bool g_reply_via_usb;
|
||||
|
||||
int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
|
||||
int reply_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 receive_ng(PacketCommandNG *rx);
|
||||
|
||||
|
|
|
@ -755,7 +755,7 @@ void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect,
|
|||
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) {
|
||||
case T_DES:
|
||||
|
|
106
armsrc/em4x70.c
106
armsrc/em4x70.c
|
@ -21,6 +21,7 @@
|
|||
#include "dbprint.h"
|
||||
#include "lfadc.h"
|
||||
#include "commonutil.h"
|
||||
#include "optimized_cipherutils.h"
|
||||
#include "em4x70.h"
|
||||
#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 void init_tag(void) {
|
||||
memset(tag.data, 0x00, ARRAYLEN(tag.data));
|
||||
memset(tag.data, 0x00, sizeof(tag.data));
|
||||
}
|
||||
|
||||
static void em4x70_setup_read(void) {
|
||||
|
@ -298,14 +299,14 @@ static bool check_ack(void) {
|
|||
// returns true if signal structue corresponds to ACK, anything else is
|
||||
// counted as NAK (-> false)
|
||||
// ACK 64 + 64
|
||||
// NACK 64 + 48
|
||||
// NAK 64 + 48
|
||||
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)) {
|
||||
// ACK
|
||||
return true;
|
||||
}
|
||||
|
||||
// Othewise it was a NACK or Listen Window
|
||||
// Otherwise it was a NAK or Listen Window
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -339,7 +340,7 @@ static int authenticate(const uint8_t *rnd, const uint8_t *frnd, uint8_t *respon
|
|||
uint8_t grnd[EM4X70_MAX_RECEIVE_LENGTH] = {0};
|
||||
int num = em4x70_receive(grnd, 20);
|
||||
if (num < 20) {
|
||||
Dbprintf("Auth failed");
|
||||
if (g_dbglevel >= DBG_EXTENDED) Dbprintf("Auth failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
bits2bytes(grnd, 24, response);
|
||||
|
@ -349,6 +350,80 @@ static int authenticate(const uint8_t *rnd, const uint8_t *frnd, uint8_t *respon
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
static int set_byte(uint8_t *target, int value) {
|
||||
int c = value > 0xFF;
|
||||
*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 & 0xFF));
|
||||
c = set_byte(&temp_rnd[1], rev_rnd[1] + c + ((rev_k >> 8) & 0xFF));
|
||||
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 & 0xFF));
|
||||
c = set_byte(&temp_rnd[3], rev_rnd[3] + c + ((rev_k >> 8) & 0xFF));
|
||||
c = set_byte(&temp_rnd[4], rev_rnd[4] + c);
|
||||
c = set_byte(&temp_rnd[5], rev_rnd[5] + c);
|
||||
set_byte(&temp_rnd[6], rev_rnd[6] + c);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
c = set_byte(&temp_rnd[4], rev_rnd[4] + (rev_k & 0xFF));
|
||||
c = set_byte(&temp_rnd[5], rev_rnd[5] + c + ((rev_k >> 8) & 0xFF));
|
||||
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) {
|
||||
|
||||
// sends pin code for unlocking
|
||||
|
@ -576,7 +651,7 @@ static int em4x70_receive(uint8_t *bits, size_t length) {
|
|||
}
|
||||
|
||||
if (!foundheader) {
|
||||
Dbprintf("Failed to find read header");
|
||||
if (g_dbglevel >= DBG_EXTENDED) Dbprintf("Failed to find read header");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -738,6 +813,27 @@ void em4x70_auth(em4x70_data_t *etd, bool ledcontrol) {
|
|||
reply_ng(CMD_LF_EM4X70_AUTH, status, response, sizeof(response));
|
||||
}
|
||||
|
||||
void em4x70_brute(em4x70_data_t *etd, bool ledcontrol) {
|
||||
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(em4x70_data_t *etd, bool ledcontrol) {
|
||||
|
||||
uint8_t status = 0;
|
||||
|
|
|
@ -32,6 +32,7 @@ typedef enum {
|
|||
|
||||
void em4x70_info(em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_write(em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_brute(em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_unlock(em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_auth(em4x70_data_t *etd, bool ledcontrol);
|
||||
void em4x70_write_pin(em4x70_data_t *etd, bool ledcontrol);
|
||||
|
|
41
armsrc/epa.c
41
armsrc/epa.c
|
@ -592,3 +592,44 @@ int EPA_Setup(void) {
|
|||
Dbprintf("No card found");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void EPA_PACE_Simulate(PacketCommandNG *c) {
|
||||
|
||||
//---------Initializing---------
|
||||
|
||||
// Get password from arguments
|
||||
unsigned char pwd[6];
|
||||
memcpy(pwd, c->data.asBytes, 6);
|
||||
|
||||
// Set up communication with the card
|
||||
int res = EPA_Setup();
|
||||
if (res != 0) {
|
||||
EPA_PACE_Collect_Nonce_Abort(CMD_HF_EPA_PACE_SIMULATE, 1, res);
|
||||
return;
|
||||
}
|
||||
|
||||
// Read EF.CardAccess
|
||||
uint8_t card_access[210] = {0};
|
||||
int card_access_length = EPA_Read_CardAccess(card_access, 210);
|
||||
|
||||
// The response has to be at least this big to hold the OID
|
||||
if (card_access_length < 18) {
|
||||
EPA_PACE_Collect_Nonce_Abort(CMD_HF_EPA_PACE_SIMULATE, 2, card_access_length);
|
||||
return;
|
||||
}
|
||||
|
||||
// PACEInfo of the card
|
||||
pace_version_info_t pace_version_info;
|
||||
|
||||
// Search for the PACE OID
|
||||
res = EPA_Parse_CardAccess(card_access, card_access_length, &pace_version_info);
|
||||
|
||||
if (res != 0 || pace_version_info.version == 0) {
|
||||
EPA_PACE_Collect_Nonce_Abort(CMD_HF_EPA_PACE_SIMULATE, 3, res);
|
||||
return;
|
||||
}
|
||||
|
||||
Dbprintf("Standardized Domain Parameter: %i", pace_version_info.parameter_id);
|
||||
DbpString("");
|
||||
DbpString("finished");
|
||||
}
|
||||
|
|
|
@ -32,9 +32,7 @@ typedef struct {
|
|||
|
||||
// general functions
|
||||
void EPA_Finish(void);
|
||||
size_t EPA_Parse_CardAccess(uint8_t *data,
|
||||
size_t length,
|
||||
pace_version_info_t *pace_info);
|
||||
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);
|
||||
|
||||
|
@ -44,5 +42,6 @@ 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 */
|
||||
|
|
|
@ -298,7 +298,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
|
|||
// 8-byte IDm, number of blocks, blocks numbers
|
||||
// number of blocks limited to 4 for FelicaLite(S)
|
||||
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);
|
||||
|
||||
uint8_t c = 0, i = 0;
|
||||
|
|
|
@ -613,10 +613,12 @@ void switch_off(void) {
|
|||
if (g_dbglevel > 3) {
|
||||
Dbprintf("switch_off");
|
||||
}
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
if (downloaded_bitstream == FPGA_BITSTREAM_HF || downloaded_bitstream == FPGA_BITSTREAM_HF_15) {
|
||||
FpgaDisableSscDma();
|
||||
}
|
||||
|
||||
set_tracing(false);
|
||||
LEDsoff();
|
||||
}
|
||||
|
|
|
@ -235,9 +235,10 @@ static int json_get_utf8_char_len(unsigned char ch) {
|
|||
|
||||
/* string = '"' { quoted_printable_chars } '"' */
|
||||
static int json_parse_string(struct frozen *f) {
|
||||
int n, ch = 0, len = 0;
|
||||
int ch = 0;
|
||||
TRY(json_test_and_skip(f, '"'));
|
||||
{
|
||||
int len = 0;
|
||||
SET_STATE(f, f->cur, "", 0);
|
||||
for (; f->cur < f->end; f->cur += len) {
|
||||
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(len <= json_left(f), JSON_STRING_INCOMPLETE);
|
||||
if (ch == '\\') {
|
||||
int n;
|
||||
EXPECT((n = json_get_escape_len(f->cur + 1, json_left(f))) > 0, n);
|
||||
len += n;
|
||||
} else if (ch == '"') {
|
||||
|
@ -295,17 +297,17 @@ static int json_parse_number(struct frozen *f) {
|
|||
#if JSON_ENABLE_ARRAY
|
||||
/* array = '[' [ value { ',' value } ] ']' */
|
||||
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);
|
||||
TRY(json_test_and_skip(f, '['));
|
||||
{
|
||||
{
|
||||
int i = 0;
|
||||
SET_STATE(f, f->cur - 1, "", 0);
|
||||
while (json_cur(f) != ']') {
|
||||
char buf[20];
|
||||
snprintf(buf, sizeof(buf), "[%d]", 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->path + strlen(f->path) - strlen(buf) + 1 /*opening brace*/;
|
||||
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,
|
||||
struct json_token *key, struct json_token *val, int *i) {
|
||||
struct json_token tmpval, *v = val == NULL ? &tmpval : val;
|
||||
struct json_token tmpkey, *k = key == NULL ? &tmpkey : key;
|
||||
int tmpidx, *pidx = i == NULL ? &tmpidx : i;
|
||||
struct json_token tmpval;
|
||||
struct json_token *v = val == NULL ? &tmpval : val;
|
||||
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};
|
||||
json_walk(s, len, json_next_cb, &data);
|
||||
return data.found ? data.handle : NULL;
|
||||
|
|
273
armsrc/hfops.c
Normal file
273
armsrc/hfops.c
Normal file
|
@ -0,0 +1,273 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
// HF general operations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "hfops.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "appmain.h"
|
||||
#include "proxmark3_arm.h"
|
||||
#include "cmd.h"
|
||||
#include "BigBuf.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "ticks.h"
|
||||
#include "dbprint.h"
|
||||
#include "util.h"
|
||||
#include "commonutil.h"
|
||||
#include "lfsampling.h"
|
||||
|
||||
int HfReadADC(uint32_t samplesCount, bool ledcontrol) {
|
||||
if (ledcontrol) LEDsoff();
|
||||
|
||||
BigBuf_Clear_ext(false);
|
||||
// connect Demodulated Signal to ADC:
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
// And put the FPGA in the appropriate mode
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_212_KHZ | FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE);
|
||||
|
||||
// Setup
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER);
|
||||
|
||||
if (ledcontrol) LED_A_ON();
|
||||
|
||||
uint32_t sbs = samplesCount;
|
||||
initSampleBuffer(&sbs);
|
||||
|
||||
uint32_t wdtcntr = 0;
|
||||
for (;;) {
|
||||
if (BUTTON_PRESS()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
volatile uint16_t sample = AT91C_BASE_SSC->SSC_RHR;
|
||||
|
||||
// FPGA side:
|
||||
// corr_i_out <= {2'b00, corr_amplitude[13:8]};
|
||||
// corr_q_out <= corr_amplitude[7:0];
|
||||
if (sample > 0x1fff)
|
||||
sample = 0xff;
|
||||
else
|
||||
sample = sample >> 5;
|
||||
logSample(sample & 0xff, 1, 8, false);
|
||||
if (getSampleCounter() >= samplesCount)
|
||||
break;
|
||||
|
||||
if (wdtcntr++ > 512) {
|
||||
WDT_HIT();
|
||||
wdtcntr = 0;
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
FpgaDisableTracing();
|
||||
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_OFF);
|
||||
// Turn the field off
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
||||
uint32_t scnt = getSampleCounter();
|
||||
reply_ng(CMD_HF_ACQ_RAW_ADC, PM3_SUCCESS, (uint8_t *)&scnt, 4);
|
||||
if (ledcontrol) LEDsoff();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t encode_acc = 0;
|
||||
uint8_t encode_acc_bit_count = 0;
|
||||
uint32_t encode_indx = 0;
|
||||
|
||||
static void EncodeInit(void) {
|
||||
encode_acc = 0;
|
||||
encode_acc_bit_count = 0;
|
||||
encode_indx = 0;
|
||||
}
|
||||
|
||||
static void EncodeAddBit(uint8_t *data, uint8_t bit, uint8_t bit_count) {
|
||||
for (int i = 0; i < bit_count; i++) {
|
||||
encode_acc = (encode_acc << 1) | (bit & 0x01);
|
||||
encode_acc_bit_count++;
|
||||
if (encode_acc_bit_count > 7) {
|
||||
data[encode_indx++] = encode_acc;
|
||||
encode_acc = 0;
|
||||
encode_acc_bit_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t EncodeFinish(uint8_t *data) {
|
||||
if (encode_acc_bit_count > 0) {
|
||||
encode_acc = encode_acc << (8 - encode_acc_bit_count);
|
||||
data[encode_indx++] = encode_acc;
|
||||
}
|
||||
|
||||
return encode_indx;
|
||||
}
|
||||
|
||||
static uint32_t HfEncodeTkm(const uint8_t *uid, uint8_t modulation, uint8_t *data) {
|
||||
uint32_t len = 0;
|
||||
if (modulation == 0) {
|
||||
// TK-13
|
||||
// 74ns 1 field cycle,
|
||||
// carrier frequency is fc/64 (212kHz), 4.7 mks
|
||||
// 100 field cycle = impulse 1.6 ( 1 bit from real tag)
|
||||
// 1000 field cycle = `1` 15.6 (17 bit from real tag)
|
||||
// 500 field cycle = `0` 7.8 ( 7 bit from real tag)
|
||||
|
||||
EncodeInit();
|
||||
for (int i = 0; i < 8; i++) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if (((uid[i] << j) & 0x80) != 0) {
|
||||
// `1`
|
||||
EncodeAddBit(data, 1, 1);
|
||||
EncodeAddBit(data, 0, 17);
|
||||
EncodeAddBit(data, 1, 1);
|
||||
EncodeAddBit(data, 0, 7);
|
||||
} else {
|
||||
// `0`
|
||||
EncodeAddBit(data, 1, 1);
|
||||
EncodeAddBit(data, 0, 7);
|
||||
EncodeAddBit(data, 1, 1);
|
||||
EncodeAddBit(data, 0, 17);
|
||||
}
|
||||
}
|
||||
}
|
||||
len = EncodeFinish(data);
|
||||
} else {
|
||||
// TK-17
|
||||
// 74ns 1 field cycle,
|
||||
// carrier frequency is fc/64 (212kHz), 4.7 mks
|
||||
// 0 --- 8 --- 12-15 --- 18-19 --- 26-28 --- 32
|
||||
// DO NOT NORMALIZE!!!! it must be with some error like this!!!!
|
||||
// `00` -- 1-25-1-5
|
||||
// `01` -- 1-12-1-18
|
||||
// `10` -- 1-17-1-13
|
||||
// `11` -- 1-7-1-23
|
||||
|
||||
EncodeInit();
|
||||
for (int i = 0; i < 8; i++) {
|
||||
for (int j = 0; j < 8; j += 2) {
|
||||
uint8_t twobit = ((uid[i] >> j) & 0x03);
|
||||
if (twobit == 0x00) {
|
||||
// `00`
|
||||
EncodeAddBit(data, 1, 1);
|
||||
EncodeAddBit(data, 0, 25);
|
||||
EncodeAddBit(data, 1, 1);
|
||||
EncodeAddBit(data, 0, 5);
|
||||
} else if (twobit == 0x01) {
|
||||
// `01`
|
||||
EncodeAddBit(data, 1, 1);
|
||||
EncodeAddBit(data, 0, 12);
|
||||
EncodeAddBit(data, 1, 1);
|
||||
EncodeAddBit(data, 0, 18);
|
||||
} else if (twobit == 0x02) {
|
||||
// `10`
|
||||
EncodeAddBit(data, 1, 1);
|
||||
EncodeAddBit(data, 0, 17);
|
||||
EncodeAddBit(data, 1, 1);
|
||||
EncodeAddBit(data, 0, 13);
|
||||
} else { // twobit == 0x03
|
||||
// `11`
|
||||
EncodeAddBit(data, 1, 1);
|
||||
EncodeAddBit(data, 0, 7);
|
||||
EncodeAddBit(data, 1, 1);
|
||||
EncodeAddBit(data, 0, 23);
|
||||
}
|
||||
}
|
||||
}
|
||||
EncodeAddBit(data, 1, 1);
|
||||
len = EncodeFinish(data);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int HfSimulateTkm(uint8_t *uid, uint8_t modulation, uint32_t timeout) {
|
||||
// free eventually allocated BigBuf memory
|
||||
BigBuf_free_keep_EM();
|
||||
|
||||
LEDsoff();
|
||||
|
||||
uint8_t *data = BigBuf_calloc(256);
|
||||
uint32_t elen = HfEncodeTkm(uid, modulation, data);
|
||||
if (elen == 0) {
|
||||
DbpString("encode error");
|
||||
reply_ng(CMD_HF_TEXKOM_SIMULATE, PM3_EAPDU_ENCODEFAIL, NULL, 0);
|
||||
return PM3_EAPDU_ENCODEFAIL;
|
||||
}
|
||||
|
||||
LED_C_ON();
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_212K);
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR);
|
||||
|
||||
bool button_pressed = false;
|
||||
bool exit_loop = false;
|
||||
bool field_on = false;
|
||||
|
||||
uint32_t startTime = GetTickCount();
|
||||
while (exit_loop == false) {
|
||||
|
||||
button_pressed = BUTTON_PRESS();
|
||||
if (button_pressed || data_available()) {
|
||||
break;
|
||||
}
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
if (timeout > 0 && startTime + timeout < GetTickCount())
|
||||
break;
|
||||
|
||||
// in mV
|
||||
int vHf = (MAX_ADC_HF_VOLTAGE * SumAdc(ADC_CHAN_HF, 32)) >> 15;
|
||||
if (vHf > MF_MINFIELDV) {
|
||||
if (field_on == false) {
|
||||
LED_A_ON();
|
||||
SpinDelay(50);
|
||||
}
|
||||
field_on = true;
|
||||
} else {
|
||||
if (field_on) {
|
||||
LED_A_OFF();
|
||||
}
|
||||
field_on = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
SpinDelay(3);
|
||||
|
||||
for (int i = 0; i < elen;) {
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
||||
AT91C_BASE_SSC->SSC_THR = data[i++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch_off();
|
||||
|
||||
if (button_pressed)
|
||||
DbpString("Exit by press button");
|
||||
|
||||
reply_ng(CMD_HF_TEXKOM_SIMULATE, PM3_SUCCESS, NULL, 0);
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
27
armsrc/hfops.h
Normal file
27
armsrc/hfops.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
// HF general operations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef HFOPS_H
|
||||
#define HFOPS_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
int HfReadADC(uint32_t samplesCount, bool ledcontrol);
|
||||
int HfSimulateTkm(uint8_t *uid, uint8_t modulation, uint32_t timeout);
|
||||
|
||||
#endif
|
|
@ -36,7 +36,56 @@ static void RAMFUNC optimizedSniff(uint16_t *dest, uint16_t dsize) {
|
|||
}
|
||||
}
|
||||
|
||||
int HfSniff(uint32_t samplesToSkip, uint32_t triggersToSkip, uint16_t *len) {
|
||||
static void RAMFUNC skipSniff(uint8_t *dest, uint16_t dsize, uint8_t skipMode, uint8_t skipRatio) {
|
||||
uint32_t accum = (skipMode == HF_SNOOP_SKIP_MIN) ? 0xffffffff : 0;
|
||||
uint8_t ratioindx = 0;
|
||||
while (dsize > 0) {
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||
volatile uint16_t val = (uint16_t)(AT91C_BASE_SSC->SSC_RHR);
|
||||
switch (skipMode) {
|
||||
case HF_SNOOP_SKIP_MAX:
|
||||
if (accum < (val & 0xff))
|
||||
accum = val & 0xff;
|
||||
if (accum < (val >> 8))
|
||||
accum = val >> 8;
|
||||
break;
|
||||
case HF_SNOOP_SKIP_MIN:
|
||||
if (accum > (val & 0xff))
|
||||
accum = val & 0xff;
|
||||
if (accum > (val >> 8))
|
||||
accum = val >> 8;
|
||||
break;
|
||||
case HF_SNOOP_SKIP_AVG:
|
||||
accum += (val & 0xff) + (val & 0xff);
|
||||
break;
|
||||
default: { // HF_SNOOP_SKIP_DROP and the rest
|
||||
if (ratioindx == 0)
|
||||
accum = val & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
ratioindx++;
|
||||
if (ratioindx >= skipRatio) {
|
||||
if (skipMode == HF_SNOOP_SKIP_AVG && skipRatio > 0) {
|
||||
accum = accum / (skipRatio * 2);
|
||||
if (accum <= 0xff)
|
||||
*dest = accum;
|
||||
else
|
||||
*dest = 0xff;
|
||||
} else {
|
||||
*dest = accum;
|
||||
}
|
||||
|
||||
dest++;
|
||||
dsize --;
|
||||
accum = (skipMode == HF_SNOOP_SKIP_MIN) ? 0xffffffff : 0;
|
||||
ratioindx = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int HfSniff(uint32_t samplesToSkip, uint32_t triggersToSkip, uint16_t *len, uint8_t skipMode, uint8_t skipRatio) {
|
||||
BigBuf_free();
|
||||
BigBuf_Clear_ext(false);
|
||||
|
||||
|
@ -105,7 +154,10 @@ int HfSniff(uint32_t samplesToSkip, uint32_t triggersToSkip, uint16_t *len) {
|
|||
}
|
||||
}
|
||||
|
||||
optimizedSniff((uint16_t *)mem, *len);
|
||||
if (skipMode == 0)
|
||||
optimizedSniff((uint16_t *)mem, *len);
|
||||
else
|
||||
skipSniff(mem, *len, skipMode, skipRatio);
|
||||
|
||||
if (g_dbglevel >= DBG_INFO) {
|
||||
Dbprintf("Trigger kicked in (%d >= 180)", r);
|
||||
|
@ -157,6 +209,6 @@ void HfPlotDownload(void) {
|
|||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
||||
// Trigger a finish downloading signal with an ACK frame
|
||||
reply_mix(CMD_ACK, 1, 0, FPGA_TRACE_SIZE, 0, 0);
|
||||
reply_ng(CMD_FPGAMEM_DOWNLOAD, PM3_SUCCESS, NULL, 0);
|
||||
LED_B_OFF();
|
||||
}
|
||||
|
|
|
@ -18,6 +18,13 @@
|
|||
|
||||
#include "proxmark3_arm.h"
|
||||
|
||||
int HfSniff(uint32_t samplesToSkip, uint32_t triggersToSkip, uint16_t *len);
|
||||
// what to do with skipped data
|
||||
#define HF_SNOOP_SKIP_NONE (0)
|
||||
#define HF_SNOOP_SKIP_DROP (1)
|
||||
#define HF_SNOOP_SKIP_MAX (2)
|
||||
#define HF_SNOOP_SKIP_MIN (3)
|
||||
#define HF_SNOOP_SKIP_AVG (4)
|
||||
|
||||
int HfSniff(uint32_t samplesToSkip, uint32_t triggersToSkip, uint16_t *len, uint8_t skipMode, uint8_t skipRatio);
|
||||
void HfPlotDownload(void);
|
||||
#endif
|
||||
|
|
|
@ -1268,7 +1268,6 @@ void ReadHitagS(hitag_function htf, hitag_data *htd, bool ledcontrol) {
|
|||
uint8_t rx[HITAG_FRAME_LEN];
|
||||
size_t rxlen = 0;
|
||||
uint8_t tx[HITAG_FRAME_LEN];
|
||||
size_t txlen;
|
||||
int t_wait = HITAG_T_WAIT_MAX;
|
||||
|
||||
|
||||
|
@ -1284,7 +1283,7 @@ void ReadHitagS(hitag_function htf, hitag_data *htd, bool ledcontrol) {
|
|||
WDT_HIT();
|
||||
|
||||
//send read request
|
||||
txlen = 0;
|
||||
size_t txlen = 0;
|
||||
uint8_t cmd = 0x0c;
|
||||
txlen = concatbits(tx, txlen, &cmd, 8 - 4, 4);
|
||||
uint8_t addr = pageNum;
|
||||
|
|
109
armsrc/i2c.c
109
armsrc/i2c.c
|
@ -53,7 +53,8 @@ static void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {
|
|||
#define I2C_DELAY_2CLK I2CSpinDelayClk(2)
|
||||
#define I2C_DELAY_XCLK(x) I2CSpinDelayClk((x))
|
||||
|
||||
#define ISO7618_MAX_FRAME 255
|
||||
// The SIM module v4 supports up to 384 bytes for the length.
|
||||
#define ISO7816_MAX_FRAME 270
|
||||
|
||||
// try i2c bus recovery at 100kHz = 5us high, 5us low
|
||||
void I2C_recovery(void) {
|
||||
|
@ -90,7 +91,7 @@ void I2C_recovery(void) {
|
|||
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
|
||||
AT91C_BASE_PIOA->PIO_PPUDR = GPIO_RST;
|
||||
AT91C_BASE_PIOA->PIO_MDDR = GPIO_RST;
|
||||
|
@ -105,6 +106,10 @@ void I2C_init(void) {
|
|||
AT91C_BASE_PIOA->PIO_OER |= (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);
|
||||
if (isok == false)
|
||||
I2C_recovery();
|
||||
|
@ -132,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.
|
||||
void I2C_Reset_EnterMainProgram(void) {
|
||||
StartTicks();
|
||||
I2C_init();
|
||||
I2C_init(true);
|
||||
I2C_SetResetStatus(0, 0, 0);
|
||||
WaitMS(30);
|
||||
I2C_SetResetStatus(1, 0, 0);
|
||||
|
@ -145,7 +150,7 @@ void I2C_Reset_EnterMainProgram(void) {
|
|||
// Reserve for firmware update.
|
||||
void I2C_Reset_EnterBootloader(void) {
|
||||
StartTicks();
|
||||
I2C_init();
|
||||
I2C_init(true);
|
||||
I2C_SetResetStatus(0, 1, 1);
|
||||
WaitMS(100);
|
||||
I2C_SetResetStatus(1, 1, 1);
|
||||
|
@ -166,7 +171,7 @@ static bool WaitSCL_H_delay(uint32_t delay) {
|
|||
// 5000 * 3.07us = 15350us. 15.35ms
|
||||
// 15000 * 3.07us = 46050us. 46.05ms
|
||||
static bool WaitSCL_H(void) {
|
||||
return WaitSCL_H_delay(15000);
|
||||
return WaitSCL_H_delay(5000);
|
||||
}
|
||||
|
||||
static bool WaitSCL_L_delay(uint32_t delay) {
|
||||
|
@ -178,19 +183,21 @@ static bool WaitSCL_L_delay(uint32_t delay) {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 5000 * 3.07us = 15350us. 15.35ms
|
||||
// 15000 * 3.07us = 46050us. 46.05ms
|
||||
static bool WaitSCL_L(void) {
|
||||
return WaitSCL_L_delay(15000);
|
||||
return WaitSCL_L_delay(5000);
|
||||
}
|
||||
|
||||
// Wait max 1800ms or until SCL goes LOW.
|
||||
// It timeout reading response from card
|
||||
// Which ever comes first
|
||||
static bool WaitSCL_L_timeout(void) {
|
||||
volatile uint32_t delay = 1700;
|
||||
volatile uint32_t delay = 200;
|
||||
while (delay--) {
|
||||
// exit on SCL LOW
|
||||
if (!SCL_read)
|
||||
if (SCL_read == false)
|
||||
return true;
|
||||
|
||||
WaitMS(1);
|
||||
|
@ -205,12 +212,15 @@ static bool I2C_Start(void) {
|
|||
SDA_H;
|
||||
I2C_DELAY_1CLK;
|
||||
SCL_H;
|
||||
if (!WaitSCL_H()) return false;
|
||||
if (!WaitSCL_H())
|
||||
return false;
|
||||
|
||||
I2C_DELAY_2CLK;
|
||||
|
||||
if (!SCL_read) return false;
|
||||
if (!SDA_read) return false;
|
||||
if (!SCL_read)
|
||||
return false;
|
||||
if (!SDA_read)
|
||||
return false;
|
||||
|
||||
SDA_L;
|
||||
I2C_DELAY_2CLK;
|
||||
|
@ -225,8 +235,9 @@ static bool I2C_WaitForSim(void) {
|
|||
|
||||
// 8051 speaks with smart card.
|
||||
// 1000*50*3.07 = 153.5ms
|
||||
// 1byte transfer == 1ms with max frame being 256bytes
|
||||
return WaitSCL_H_delay(1000 * 300);
|
||||
// 1000*110*3.07 = 337.7ms
|
||||
// 1byte transfer == 1ms with max frame being 256bytes
|
||||
return WaitSCL_H_delay(1000 * 110);
|
||||
}
|
||||
|
||||
// send i2c STOP
|
||||
|
@ -395,8 +406,8 @@ bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address) {
|
|||
}
|
||||
|
||||
//Sends array of data (Array, length, command to be written , SlaveDevice address ).
|
||||
// len = uint8 (max buffer to write 256bytes)
|
||||
bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) {
|
||||
// len = uint16 because we need to write up to 256 bytes
|
||||
bool I2C_BufferWrite(uint8_t *data, uint16_t len, uint8_t device_cmd, uint8_t device_address) {
|
||||
bool bBreak = true;
|
||||
do {
|
||||
if (!I2C_Start())
|
||||
|
@ -433,8 +444,8 @@ bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t dev
|
|||
}
|
||||
|
||||
// read one array of data (Data array, Readout length, command to be written , SlaveDevice address ).
|
||||
// len = uint8 (max buffer to read 256bytes)
|
||||
int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) {
|
||||
// len = uint16 because we need to read up to 256bytes
|
||||
int16_t I2C_BufferRead(uint8_t *data, uint16_t len, uint8_t device_cmd, uint8_t device_address) {
|
||||
|
||||
if (!data || len == 0)
|
||||
return 0;
|
||||
|
@ -445,6 +456,7 @@ int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d
|
|||
|
||||
bool bBreak = true;
|
||||
uint16_t readcount = 0;
|
||||
uint16_t recv_len = 0;
|
||||
|
||||
do {
|
||||
if (!I2C_Start())
|
||||
|
@ -484,11 +496,34 @@ int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d
|
|||
|
||||
len--;
|
||||
|
||||
// The first byte in response is the message length
|
||||
if (!readcount && (len > *data)) {
|
||||
len = *data;
|
||||
// Starting firmware v4 the length is encoded on the first two bytes.
|
||||
// This only applies if command is I2C_DEVICE_CMD_READ.
|
||||
if (device_cmd == I2C_DEVICE_CMD_READ) {
|
||||
switch (readcount) {
|
||||
case 0:
|
||||
// Length (MSB)
|
||||
recv_len = (*data) << 8;
|
||||
break;
|
||||
case 1:
|
||||
// Length (LSB)
|
||||
recv_len += *data;
|
||||
// Adjust len if needed
|
||||
if (len > recv_len) {
|
||||
len = recv_len;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Data byte received
|
||||
data++;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
data++;
|
||||
// Length is encoded on 1 byte
|
||||
if ((readcount == 0) && (len > *data)) {
|
||||
len = *data;
|
||||
} else {
|
||||
data++;
|
||||
}
|
||||
}
|
||||
readcount++;
|
||||
|
||||
|
@ -501,8 +536,8 @@ int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d
|
|||
|
||||
I2C_Stop();
|
||||
|
||||
// return bytecount - first byte (which is length byte)
|
||||
return --readcount;
|
||||
// return bytecount - bytes encoding length
|
||||
return readcount - (device_cmd == I2C_DEVICE_CMD_READ ? 2 : 1);
|
||||
}
|
||||
|
||||
int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) {
|
||||
|
@ -612,10 +647,14 @@ bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t d
|
|||
void I2C_print_status(void) {
|
||||
DbpString(_CYAN_("Smart card module (ISO 7816)"));
|
||||
uint8_t maj, min;
|
||||
if (I2C_get_version(&maj, &min) == PM3_SUCCESS)
|
||||
if (I2C_get_version(&maj, &min) == PM3_SUCCESS) {
|
||||
Dbprintf(" version................. " _YELLOW_("v%x.%02d"), maj, min);
|
||||
else
|
||||
if (maj < 4) {
|
||||
DbpString(" " _RED_("Outdated firmware.") " Please upgrade to v4.x or above.");
|
||||
}
|
||||
} else {
|
||||
DbpString(" version................. " _RED_("FAILED"));
|
||||
}
|
||||
}
|
||||
|
||||
int I2C_get_version(uint8_t *maj, uint8_t *min) {
|
||||
|
@ -631,7 +670,7 @@ int I2C_get_version(uint8_t *maj, uint8_t *min) {
|
|||
}
|
||||
|
||||
// Will read response from smart card module, retries 3 times to get the data.
|
||||
bool sc_rx_bytes(uint8_t *dest, uint8_t *destlen) {
|
||||
bool sc_rx_bytes(uint8_t *dest, uint16_t *destlen) {
|
||||
|
||||
uint8_t i = 5;
|
||||
int16_t len = 0;
|
||||
|
@ -656,7 +695,7 @@ bool sc_rx_bytes(uint8_t *dest, uint8_t *destlen) {
|
|||
if (len <= 1)
|
||||
return false;
|
||||
|
||||
*destlen = (uint8_t)len & 0xFF;
|
||||
*destlen = len;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -678,10 +717,14 @@ bool GetATR(smart_card_atr_t *card_ptr, bool verbose) {
|
|||
return false;
|
||||
|
||||
// read bytes from module
|
||||
uint8_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)) {
|
||||
len = sizeof(card_ptr->atr);
|
||||
}
|
||||
|
||||
uint8_t pos_td = 1;
|
||||
if ((card_ptr->atr[1] & 0x10) == 0x10) pos_td++;
|
||||
if ((card_ptr->atr[1] & 0x20) == 0x20) pos_td++;
|
||||
|
@ -697,7 +740,7 @@ bool GetATR(smart_card_atr_t *card_ptr, bool verbose) {
|
|||
|
||||
uint8_t chksum = 0;
|
||||
// xor property. will be zero when xored with chksum.
|
||||
for (uint8_t i = 1; i < len; ++i)
|
||||
for (uint16_t i = 1; i < len; ++i)
|
||||
chksum ^= card_ptr->atr[i];
|
||||
|
||||
if (chksum) {
|
||||
|
@ -706,7 +749,7 @@ bool GetATR(smart_card_atr_t *card_ptr, bool verbose) {
|
|||
}
|
||||
}
|
||||
|
||||
card_ptr->atr_len = len;
|
||||
card_ptr->atr_len = (uint8_t)(len & 0xff);
|
||||
if (verbose) {
|
||||
LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false);
|
||||
}
|
||||
|
@ -732,8 +775,8 @@ void SmartCardAtr(void) {
|
|||
void SmartCardRaw(smart_card_raw_t *p) {
|
||||
LED_D_ON();
|
||||
|
||||
uint8_t len = 0;
|
||||
uint8_t *resp = BigBuf_malloc(ISO7618_MAX_FRAME);
|
||||
uint16_t len = 0;
|
||||
uint8_t *resp = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
// check if alloacted...
|
||||
smartcard_command_t flags = p->flags;
|
||||
|
||||
|
@ -777,7 +820,7 @@ void SmartCardRaw(smart_card_raw_t *p) {
|
|||
}
|
||||
|
||||
// read bytes from module
|
||||
len = ISO7618_MAX_FRAME;
|
||||
len = ISO7816_MAX_FRAME;
|
||||
res = sc_rx_bytes(resp, &len);
|
||||
if (res) {
|
||||
LogTrace(resp, len, 0, 0, NULL, false);
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#define I2C_DEVICE_CMD_SEND_T0 0x07
|
||||
|
||||
void I2C_recovery(void);
|
||||
void I2C_init(void);
|
||||
void I2C_init(bool has_ticks);
|
||||
void I2C_Reset(void);
|
||||
void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA);
|
||||
|
||||
|
@ -41,14 +41,14 @@ void I2C_Reset_EnterBootloader(void);
|
|||
bool I2C_WriteCmd(uint8_t device_cmd, uint8_t device_address);
|
||||
|
||||
bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address);
|
||||
bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address);
|
||||
int16_t I2C_BufferRead(uint8_t *data, uint8_t len, 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);
|
||||
int16_t I2C_BufferRead(uint8_t *data, uint16_t len, uint8_t device_cmd, uint8_t device_address);
|
||||
|
||||
// for firmware
|
||||
int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address);
|
||||
bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address);
|
||||
|
||||
bool sc_rx_bytes(uint8_t *dest, uint8_t *destlen);
|
||||
bool sc_rx_bytes(uint8_t *dest, uint16_t *destlen);
|
||||
//
|
||||
bool GetATR(smart_card_atr_t *card_ptr, bool verbose);
|
||||
|
||||
|
|
|
@ -1245,29 +1245,28 @@ send:
|
|||
}
|
||||
|
||||
// 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);
|
||||
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
|
||||
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,
|
||||
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;
|
||||
int res;
|
||||
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) {
|
||||
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) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1282,7 +1281,7 @@ static bool iclass_send_cmd_with_retries(uint8_t *cmd, size_t cmdsize, uint8_t *
|
|||
* @return false = fail
|
||||
* 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 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
|
||||
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;
|
||||
uint16_t resp_len = 0;
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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)
|
||||
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
|
||||
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
|
||||
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
|
||||
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)
|
||||
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
|
||||
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;
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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
|
||||
|
@ -1413,6 +1412,7 @@ void ReaderIClass(uint8_t flags) {
|
|||
|
||||
// flag to use credit key
|
||||
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) {
|
||||
Iso15693InitReader();
|
||||
|
@ -1427,7 +1427,7 @@ void ReaderIClass(uint8_t flags) {
|
|||
uint32_t eof_time = 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);
|
||||
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[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;
|
||||
}
|
||||
|
||||
bool shallow_mod = p->shallow_mod;
|
||||
|
||||
uint8_t check[9] = { ICLASS_CMD_CHECK };
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
|
||||
uint8_t readcheck_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 };
|
||||
|
@ -1537,7 +1539,7 @@ void iClass_Authentication_fast(iclass_chk_t *p) {
|
|||
bool isOK = false;
|
||||
|
||||
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;
|
||||
|
||||
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];
|
||||
|
||||
// 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)
|
||||
goto out;
|
||||
|
||||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
// Auth Sequence MUST begin with reading e-purse. (block2)
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
@ -1586,11 +1588,11 @@ out:
|
|||
// Tries to read block.
|
||||
// retries 3times.
|
||||
// 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 c[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockno, 0x00, 0x00};
|
||||
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)
|
||||
memcpy(data, resp, 8);
|
||||
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) {
|
||||
|
||||
iclass_auth_req_t *payload = (iclass_auth_req_t *)msg;
|
||||
bool shallow_mod = payload->shallow_mod;
|
||||
|
||||
iclass_readblock_resp_t response = { .isOK = true };
|
||||
memset(response.data, 0, sizeof(response.data));
|
||||
|
@ -1614,7 +1617,7 @@ void iClass_ReadBlock(uint8_t *msg) {
|
|||
// select tag.
|
||||
uint32_t eof_time = 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 (payload->send_reply) {
|
||||
response.isOK = res;
|
||||
|
@ -1642,7 +1645,7 @@ void iClass_ReadBlock(uint8_t *msg) {
|
|||
|
||||
// read data
|
||||
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) {
|
||||
memcpy(response.data, resp, sizeof(response.data));
|
||||
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_auth_req_t *req = &cmd->req;
|
||||
bool shallow_mod = req->shallow_mod;
|
||||
|
||||
uint8_t *dataout = BigBuf_malloc(ICLASS_16KS_SIZE);
|
||||
if (dataout == NULL) {
|
||||
|
@ -1689,7 +1693,7 @@ void iClass_Dump(uint8_t *msg) {
|
|||
picopass_hdr_t hdr = {0};
|
||||
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 (req->send_reply) {
|
||||
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};
|
||||
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) {
|
||||
memcpy(dataout + (8 * i), resp, 8);
|
||||
} else {
|
||||
|
@ -1759,7 +1763,7 @@ void iClass_Dump(uint8_t *msg) {
|
|||
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
|
||||
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};
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1807,6 +1811,7 @@ void iClass_WriteBlock(uint8_t *msg) {
|
|||
LED_A_ON();
|
||||
|
||||
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_len = 14;
|
||||
|
@ -1816,7 +1821,7 @@ void iClass_WriteBlock(uint8_t *msg) {
|
|||
// select tag.
|
||||
uint32_t eof_time = 0;
|
||||
picopass_hdr_t hdr = {0};
|
||||
uint8_t res = select_iclass_tag(&hdr, payload->req.use_credit_key, &eof_time);
|
||||
uint8_t res = select_iclass_tag(&hdr, payload->req.use_credit_key, &eof_time, shallow_mod);
|
||||
if (res == false) {
|
||||
goto out;
|
||||
}
|
||||
|
@ -1846,17 +1851,22 @@ void iClass_WriteBlock(uint8_t *msg) {
|
|||
AddCrc(write + 1, 9);
|
||||
write_len -= 2;
|
||||
} else {
|
||||
// Secure tags uses MAC
|
||||
uint8_t wb[9];
|
||||
wb[0] = payload->req.blockno;
|
||||
memcpy(wb + 1, payload->data, 8);
|
||||
|
||||
if (payload->req.use_credit_key)
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
|
||||
else
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
|
||||
if (payload->req.use_replay) {
|
||||
memcpy(write + 10, payload->mac, sizeof(payload->mac));
|
||||
} else {
|
||||
// Secure tags uses MAC
|
||||
uint8_t wb[9];
|
||||
wb[0] = payload->req.blockno;
|
||||
memcpy(wb + 1, payload->data, 8);
|
||||
|
||||
memcpy(write + 10, mac, sizeof(mac));
|
||||
if (payload->req.use_credit_key)
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
|
||||
else
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
|
||||
|
||||
memcpy(write + 10, mac, sizeof(mac));
|
||||
}
|
||||
}
|
||||
|
||||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
|
@ -1866,7 +1876,7 @@ void iClass_WriteBlock(uint8_t *msg) {
|
|||
uint8_t tries = 3;
|
||||
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
|
||||
res = false;
|
||||
|
@ -1934,6 +1944,8 @@ void iClass_Restore(iclass_restore_req_t *msg) {
|
|||
return;
|
||||
}
|
||||
|
||||
bool shallow_mod = msg->req.shallow_mod;
|
||||
|
||||
LED_A_ON();
|
||||
Iso15693InitReader();
|
||||
|
||||
|
@ -1942,7 +1954,7 @@ void iClass_Restore(iclass_restore_req_t *msg) {
|
|||
picopass_hdr_t hdr = {0};
|
||||
|
||||
// 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) {
|
||||
goto out;
|
||||
}
|
||||
|
@ -1983,7 +1995,7 @@ void iClass_Restore(iclass_restore_req_t *msg) {
|
|||
}
|
||||
|
||||
// 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);
|
||||
written++;
|
||||
} else {
|
||||
|
|
|
@ -38,8 +38,8 @@ void iClass_Authentication_fast(iclass_chk_t *p);
|
|||
bool iclass_auth(iclass_auth_req_t *payload, uint8_t *out);
|
||||
|
||||
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);
|
||||
#endif
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "commonutil.h"
|
||||
#include "crc16.h"
|
||||
#include "protocols.h"
|
||||
#include "generator.h"
|
||||
|
||||
#define MAX_ISO14A_TIMEOUT 524288
|
||||
|
||||
|
@ -927,9 +928,13 @@ bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int *len) {
|
|||
(void)b;
|
||||
|
||||
uint8_t flip = 0;
|
||||
uint16_t checker = 0;
|
||||
uint16_t checker = 4000;
|
||||
for (;;) {
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
// ever 3 * 4000, check if we got any data from client
|
||||
// takes long time, usually messes with simualtion
|
||||
if (flip == 3) {
|
||||
if (data_available())
|
||||
return false;
|
||||
|
@ -937,14 +942,14 @@ bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int *len) {
|
|||
flip = 0;
|
||||
}
|
||||
|
||||
if (checker >= 3000) {
|
||||
// button press, takes a bit time, might mess with simualtion
|
||||
if (checker-- == 0) {
|
||||
if (BUTTON_PRESS())
|
||||
return false;
|
||||
|
||||
flip++;
|
||||
checker = 0;
|
||||
checker = 4000;
|
||||
}
|
||||
++checker;
|
||||
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
@ -1034,6 +1039,8 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
|
|||
// PPS response
|
||||
static uint8_t rPPS[3] = { 0xD0 };
|
||||
|
||||
static uint8_t rPACK[4] = { 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
switch (tagType) {
|
||||
case 1: { // MIFARE Classic 1k
|
||||
rATQA[0] = 0x04;
|
||||
|
@ -1046,6 +1053,30 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
|
|||
// some first pages of UL/NTAG dump is special data
|
||||
mfu_dump_t *mfu_header = (mfu_dump_t *) BigBuf_get_EM_addr();
|
||||
*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;
|
||||
case 3: { // MIFARE DESFire
|
||||
|
@ -1100,6 +1131,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
|
|||
// READ_SIG
|
||||
memcpy(rSIGN, mfu_header->signature, 32);
|
||||
AddCrc14A(rSIGN, sizeof(rSIGN) - 2);
|
||||
|
||||
}
|
||||
break;
|
||||
case 8: { // MIFARE Classic 4k
|
||||
|
@ -1221,6 +1253,19 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
|
|||
|
||||
AddCrc14A(rPPS, sizeof(rPPS) - 2);
|
||||
|
||||
if (tagType == 7) {
|
||||
uint8_t pwd[4];
|
||||
uint8_t gen_pwd[4];
|
||||
uint16_t start = (*pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH;
|
||||
emlGetMemBt(pwd, start, sizeof(pwd));
|
||||
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[] = {
|
||||
{ .response = rATQA, .response_n = sizeof(rATQA) }, // Answer to request - respond with card type
|
||||
{ .response = rUIDc1, .response_n = sizeof(rUIDc1) }, // Anticollision cascade1 - respond with uid
|
||||
|
@ -1232,14 +1277,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 = rVERSION, .response_n = sizeof(rVERSION) }, // EV1/NTAG GET_VERSION 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)
|
||||
// 81 * 8 data bits, 81 * 1 parity bits, 11 start bits, 11 stop bits, 11 correction bits
|
||||
// 81 * 8 + 81 + 11 + 11 + 11 == 762
|
||||
#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 762
|
||||
// 85 * 8 data bits, 85 * 1 parity bits, 12 start bits, 12 stop bits, 12 correction bits
|
||||
// 85 * 8 + 85 + 12 + 12 + 12 == 801
|
||||
#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 801
|
||||
|
||||
uint8_t *free_buffer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE);
|
||||
// modulation buffer pointer and current buffer free space size
|
||||
|
@ -1635,14 +1682,23 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
|
|||
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
p_response = NULL;
|
||||
} else if (receivedCmd[0] == MIFARE_ULEV1_AUTH && len == 7 && tagType == 7) { // NTAG / EV-1 authentication
|
||||
|
||||
/*
|
||||
// PWD stored in dump now
|
||||
uint8_t pwd[4];
|
||||
emlGetMemBt(pwd, (pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(pwd));
|
||||
if (memcmp(pwd, "\x00\x00\x00\x00", 4) == 0) {
|
||||
Uint4byteToMemLe(pwd, ul_ev1_pwdgenB(data));
|
||||
Dbprintf("Calc pwd... %02X %02X %02X %02X", pwd[0], pwd[1], pwd[2], pwd[3]);
|
||||
}
|
||||
|
||||
if (memcmp(receivedCmd + 1, pwd, 4) == 0) {
|
||||
|
||||
uint8_t pack[4];
|
||||
emlGetMemBt(pack, pages * 4 + MFU_DUMP_PREFIX_LENGTH, 2);
|
||||
if (memcmp(pack, "\x00\x00\x00\x00", 4) == 0) {
|
||||
memcpy(pack, "\x80\x80\x00\x00", 4);
|
||||
pack[0] = 0x80;
|
||||
pack[1] = 0x80;
|
||||
}
|
||||
AddCrc14A(pack, sizeof(pack) - 2);
|
||||
EmSendCmd(pack, sizeof(pack));
|
||||
|
@ -1651,6 +1707,8 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
|
|||
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Auth attempt: %08x", bytes_to_num(receivedCmd + 1, 4));
|
||||
}
|
||||
p_response = NULL;
|
||||
*/
|
||||
p_response = &responses[RESP_INDEX_PACK];
|
||||
} else if (receivedCmd[0] == MIFARE_ULEV1_VCSL && len == 23 && tagType == 7) {
|
||||
uint8_t cmd[3];
|
||||
emlGetMemBt(cmd, (pages - 2) * 4 + 1 + MFU_DUMP_PREFIX_LENGTH, 1);
|
||||
|
@ -2441,9 +2499,11 @@ 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 15
|
||||
#define ECP_DELAY 10
|
||||
#define ECP_RETRY_TIMEOUT 100
|
||||
#define WUPA_RETRY_TIMEOUT 10 // 10ms
|
||||
|
||||
|
||||
// 0x26 - REQA
|
||||
// 0x52 - WAKE-UP
|
||||
// 0x7A - MAGESAFE WAKE UP
|
||||
|
@ -2454,15 +2514,25 @@ static int GetATQA(uint8_t *resp, uint8_t *resp_par, bool use_ecp, bool use_mags
|
|||
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();
|
||||
iso14a_set_timeout(1236 / 128 + 1); // response to WUPA is expected at exactly 1236/fc. No need to wait longer.
|
||||
|
||||
bool first_try = true;
|
||||
uint32_t retry_timeout = use_ecp ? ECP_RETRY_TIMEOUT : WUPA_RETRY_TIMEOUT;
|
||||
uint32_t start_time = GetTickCount();
|
||||
int len;
|
||||
|
||||
// we may need several tries if we did send an unknown command or a wrong authentication before...
|
||||
do {
|
||||
if (use_ecp) {
|
||||
if (use_ecp && !first_try) {
|
||||
uint8_t ecp[] = { 0x6a, 0x02, 0xC8, 0x01, 0x00, 0x03, 0x00, 0x02, 0x79, 0x00, 0x00, 0x00, 0x00, 0xC2, 0xD8};
|
||||
ReaderTransmit(ecp, sizeof(ecp), NULL);
|
||||
SpinDelay(ECP_DELAY);
|
||||
|
@ -2476,12 +2546,13 @@ static int GetATQA(uint8_t *resp, uint8_t *resp_par, bool use_ecp, bool use_mags
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Broadcast for a card, WUPA (0x52) will force response from all cards in the field
|
||||
ReaderTransmitBitsPar(wupa, 7, NULL, NULL);
|
||||
// Receive the ATQA
|
||||
len = ReaderReceive(resp, resp_par);
|
||||
} while (len == 0 && GetTickCountDelta(start_time) <= WUPA_RETRY_TIMEOUT);
|
||||
|
||||
first_try = false;
|
||||
} while (len == 0 && GetTickCountDelta(start_time) <= retry_timeout);
|
||||
|
||||
iso14a_set_timeout(save_iso14a_timeout);
|
||||
return len;
|
||||
|
@ -2530,7 +2601,7 @@ int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint
|
|||
uint8_t fudan_read[] = { 0x30, 0x01, 0x8B, 0xB9};
|
||||
ReaderTransmit(fudan_read, sizeof(fudan_read), NULL);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2579,7 +2650,7 @@ int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint
|
|||
// SELECT_ALL
|
||||
ReaderTransmit(sel_all, sizeof(sel_all), NULL);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2657,7 +2728,7 @@ int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint
|
|||
|
||||
// Receive the SAK
|
||||
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;
|
||||
}
|
||||
sak = resp[0];
|
||||
|
|
|
@ -104,7 +104,8 @@ typedef enum {
|
|||
RESP_INDEX_RATS,
|
||||
RESP_INDEX_VERSION,
|
||||
RESP_INDEX_SIGNATURE,
|
||||
RESP_INDEX_PPS
|
||||
RESP_INDEX_PPS,
|
||||
RESP_INDEX_PACK,
|
||||
} resp_index_t;
|
||||
|
||||
#ifndef AddCrc14A
|
||||
|
|
|
@ -1381,11 +1381,11 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, uint32_t
|
|||
}
|
||||
|
||||
if (Demod.len > 0) {
|
||||
uint32_t sof_time = *eof_time
|
||||
- (Demod.len * (8 + 2)) // time for byte transfers
|
||||
- (10) // time for TR1
|
||||
- (10 + 2) // time for SOF transfer
|
||||
- (10); // time for EOF transfer
|
||||
uint32_t sof_time = *eof_time - ETU_TO_SSP(
|
||||
(Demod.len * (8 + 2)) // time for byte transfers
|
||||
// + (10) // time for TR1
|
||||
+ (10 + 2) // time for SOF transfer
|
||||
+ (10)); // time for EOF transfer
|
||||
LogTrace(Demod.output, Demod.len, sof_time, *eof_time, NULL, false);
|
||||
}
|
||||
return Demod.len;
|
||||
|
@ -1435,9 +1435,28 @@ static void TransmitFor14443b_AsReader(uint32_t *start_time) {
|
|||
}
|
||||
WDT_HIT();
|
||||
}
|
||||
|
||||
// transmit remaining bits. we need one-sample granularity now
|
||||
|
||||
volatile uint8_t data = ts->buf[ts->max], last_bits = ts->bit;
|
||||
|
||||
for (uint8_t i = 0; i < last_bits; i++) {
|
||||
volatile uint16_t send_word = (data & 0x80) ? 0x0000 : 0xFFFF;
|
||||
|
||||
while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) ;
|
||||
AT91C_BASE_SSC->SSC_THR = send_word;
|
||||
|
||||
while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) ;
|
||||
AT91C_BASE_SSC->SSC_THR = send_word;
|
||||
|
||||
data <<= 1;
|
||||
}
|
||||
WDT_HIT();
|
||||
|
||||
|
||||
LED_B_OFF();
|
||||
|
||||
*start_time += DELAY_ARM_TO_TAG;
|
||||
// *start_time += DELAY_ARM_TO_TAG;
|
||||
|
||||
// wait for last transfer to complete
|
||||
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY)) {};
|
||||
|
@ -1447,7 +1466,7 @@ static void TransmitFor14443b_AsReader(uint32_t *start_time) {
|
|||
// Code a layer 2 command (string of octets, including CRC) into ToSend[],
|
||||
// so that it is ready to transmit to the tag using TransmitFor14443b().
|
||||
//-----------------------------------------------------------------------------
|
||||
static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
|
||||
static void CodeIso14443bAsReader(const uint8_t *cmd, int len, bool framing) {
|
||||
/*
|
||||
* QUESTION: how long is a 1 or 0 in pulses in the xcorr_848 mode?
|
||||
* 1 "stuffbit" = 1ETU (9us)
|
||||
|
@ -1460,14 +1479,18 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
|
|||
int i;
|
||||
tosend_reset();
|
||||
|
||||
// Send SOF
|
||||
// 10-11 ETUs of ZERO
|
||||
for (i = 0; i < 10; i++) {
|
||||
tosend_stuffbit(0);
|
||||
// add framing enable flag. xerox chips use unframed commands during anticollision
|
||||
|
||||
if (framing) {
|
||||
// Send SOF
|
||||
// 10-11 ETUs of ZERO
|
||||
for (i = 0; i < 10; i++) {
|
||||
tosend_stuffbit(0);
|
||||
}
|
||||
// 2-3 ETUs of ONE
|
||||
tosend_stuffbit(1);
|
||||
tosend_stuffbit(1);
|
||||
}
|
||||
// 2-3 ETUs of ONE
|
||||
tosend_stuffbit(1);
|
||||
tosend_stuffbit(1);
|
||||
|
||||
// Sending cmd, LSB
|
||||
// from here we add BITS
|
||||
|
@ -1493,28 +1516,36 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
|
|||
// FOR PICC it ranges 0-19us == 0 - 2 ETU
|
||||
}
|
||||
|
||||
// Send EOF
|
||||
// 10-11 ETUs of ZERO
|
||||
for (i = 0; i < 10; i++) {
|
||||
tosend_stuffbit(0);
|
||||
if (framing) {
|
||||
// Send EOF
|
||||
// 10-11 ETUs of ZERO
|
||||
for (i = 0; i < 10; i++) {
|
||||
tosend_stuffbit(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int pad = (10 + 2 + (len * 10) + 10) & 0x7;
|
||||
for (i = 0; i < 16 - pad; ++i)
|
||||
tosend_stuffbit(1);
|
||||
|
||||
// we can't use padding now
|
||||
/*
|
||||
int pad = (10 + 2 + (len * 10) + 10) & 0x7;
|
||||
for (i = 0; i < 16 - pad; ++i)
|
||||
tosend_stuffbit(1);
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Convenience function to encode, transmit and trace iso 14443b comms
|
||||
*/
|
||||
static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len, uint32_t *start_time, uint32_t *eof_time) {
|
||||
static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len, uint32_t *start_time, uint32_t *eof_time, bool framing) {
|
||||
tosend_t *ts = get_tosend();
|
||||
CodeIso14443bAsReader(cmd, len);
|
||||
CodeIso14443bAsReader(cmd, len, framing);
|
||||
TransmitFor14443b_AsReader(start_time);
|
||||
if (g_trigger) LED_A_ON();
|
||||
*eof_time = *start_time + (10 * ts->max) + 10 + 2 + 10;
|
||||
|
||||
// eof_time in ssp clocks, but bits was added here!
|
||||
// *eof_time = *start_time + (10 * ts->max) + 10 + 2 + 10;
|
||||
|
||||
*eof_time = *start_time + ETU_TO_SSP(8 * ts->max);
|
||||
|
||||
LogTrace(cmd, len, *start_time, *eof_time, NULL, true);
|
||||
}
|
||||
|
||||
|
@ -1545,7 +1576,7 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void
|
|||
// send
|
||||
uint32_t start_time = 0;
|
||||
uint32_t eof_time = 0;
|
||||
CodeAndTransmit14443bAsReader(real_cmd, msg_len + 3, &start_time, &eof_time);
|
||||
CodeAndTransmit14443bAsReader(real_cmd, msg_len + 3, &start_time, &eof_time, true);
|
||||
|
||||
eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER;
|
||||
int len = Get14443bAnswerFromTag(rxdata, rxmaxlen, iso14b_timeout, &eof_time);
|
||||
|
@ -1578,7 +1609,7 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void
|
|||
AddCrc14B(data_bytes, len - 2);
|
||||
|
||||
// transmit S-Block
|
||||
CodeAndTransmit14443bAsReader(data_bytes, len, &start_time, &eof_time);
|
||||
CodeAndTransmit14443bAsReader(data_bytes, len, &start_time, &eof_time, true);
|
||||
|
||||
// retrieve the result again (with increased timeout)
|
||||
eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER;
|
||||
|
@ -1637,7 +1668,7 @@ static int iso14443b_select_cts_card(iso14b_cts_card_select_t *card) {
|
|||
|
||||
uint32_t start_time = 0;
|
||||
uint32_t eof_time = 0;
|
||||
CodeAndTransmit14443bAsReader(cmdINIT, sizeof(cmdINIT), &start_time, &eof_time);
|
||||
CodeAndTransmit14443bAsReader(cmdINIT, sizeof(cmdINIT), &start_time, &eof_time, true);
|
||||
|
||||
eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER;
|
||||
int retlen = Get14443bAnswerFromTag(r, sizeof(r), iso14b_timeout, &eof_time);
|
||||
|
@ -1657,7 +1688,7 @@ static int iso14443b_select_cts_card(iso14b_cts_card_select_t *card) {
|
|||
}
|
||||
|
||||
start_time = eof_time + ISO14B_TR2;
|
||||
CodeAndTransmit14443bAsReader(cmdMSBUID, sizeof(cmdMSBUID), &start_time, &eof_time);
|
||||
CodeAndTransmit14443bAsReader(cmdMSBUID, sizeof(cmdMSBUID), &start_time, &eof_time, true);
|
||||
|
||||
eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER;
|
||||
retlen = Get14443bAnswerFromTag(r, sizeof(r), iso14b_timeout, &eof_time);
|
||||
|
@ -1675,7 +1706,7 @@ static int iso14443b_select_cts_card(iso14b_cts_card_select_t *card) {
|
|||
}
|
||||
|
||||
start_time = eof_time + ISO14B_TR2;
|
||||
CodeAndTransmit14443bAsReader(cmdLSBUID, sizeof(cmdLSBUID), &start_time, &eof_time);
|
||||
CodeAndTransmit14443bAsReader(cmdLSBUID, sizeof(cmdLSBUID), &start_time, &eof_time, true);
|
||||
|
||||
eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER;
|
||||
retlen = Get14443bAnswerFromTag(r, sizeof(r), iso14b_timeout, &eof_time);
|
||||
|
@ -1706,7 +1737,7 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
|||
|
||||
uint32_t start_time = 0;
|
||||
uint32_t eof_time = 0;
|
||||
CodeAndTransmit14443bAsReader(init_srx, sizeof(init_srx), &start_time, &eof_time);
|
||||
CodeAndTransmit14443bAsReader(init_srx, sizeof(init_srx), &start_time, &eof_time, true);
|
||||
|
||||
eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER;
|
||||
int retlen = Get14443bAnswerFromTag(r_init, sizeof(r_init), iso14b_timeout, &eof_time);
|
||||
|
@ -1728,7 +1759,7 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
|||
AddCrc14B(select_srx, 2);
|
||||
|
||||
start_time = eof_time + ISO14B_TR2;
|
||||
CodeAndTransmit14443bAsReader(select_srx, sizeof(select_srx), &start_time, &eof_time);
|
||||
CodeAndTransmit14443bAsReader(select_srx, sizeof(select_srx), &start_time, &eof_time, true);
|
||||
|
||||
eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER;
|
||||
retlen = Get14443bAnswerFromTag(r_select, sizeof(r_select), iso14b_timeout, &eof_time);
|
||||
|
@ -1752,7 +1783,7 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
|||
AddCrc14B(select_srx, 1);
|
||||
|
||||
start_time = eof_time + ISO14B_TR2;
|
||||
CodeAndTransmit14443bAsReader(select_srx, 3, &start_time, &eof_time); // Only first three bytes for this one
|
||||
CodeAndTransmit14443bAsReader(select_srx, 3, &start_time, &eof_time, true); // Only first three bytes for this one
|
||||
|
||||
eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER;
|
||||
retlen = Get14443bAnswerFromTag(r_papid, sizeof(r_papid), iso14b_timeout, &eof_time);
|
||||
|
@ -1772,6 +1803,178 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Xerox tag connect function: wup, anticoll, attrib, password
|
||||
// the original chips require all commands in this sequence
|
||||
|
||||
// 0: OK, 1: select fail, 2: attrib fail, 3: crc fail, 4: password fail
|
||||
int iso14443b_select_xrx_card(iso14b_card_select_t *card) {
|
||||
// AFI
|
||||
static const uint8_t x_wup1[] = { 0x0D, 0x37, 0x21, 0x92, 0xf2 };
|
||||
static const uint8_t x_wup2[] = { 0x5D, 0x37, 0x21, 0x71, 0x71 };
|
||||
uint8_t slot_mark[1];
|
||||
|
||||
uint8_t x_atqb[24] = {0x0}; // ATQB len = 18
|
||||
|
||||
uint32_t start_time = 0;
|
||||
uint32_t eof_time = 0;
|
||||
|
||||
iso14b_set_timeout(24); // wait for carrier
|
||||
|
||||
// wup1
|
||||
CodeAndTransmit14443bAsReader(x_wup1, sizeof(x_wup1), &start_time, &eof_time, true);
|
||||
|
||||
start_time = eof_time + US_TO_SSP(9000); // 9ms before next cmd
|
||||
|
||||
// wup2
|
||||
CodeAndTransmit14443bAsReader(x_wup2, sizeof(x_wup2), &start_time, &eof_time, true);
|
||||
|
||||
uint64_t uid = 0;
|
||||
int retlen;
|
||||
|
||||
for (int uid_pos = 0; uid_pos < 64; uid_pos += 2) {
|
||||
int slot;
|
||||
|
||||
for (slot = 0; slot < 4; slot++) {
|
||||
start_time = eof_time + ETU_TO_SSP(30); //(24); // next slot after 24 ETU
|
||||
|
||||
retlen = Get14443bAnswerFromTag(x_atqb, sizeof(x_atqb), iso14b_timeout, &eof_time);
|
||||
|
||||
if (retlen > 0) {
|
||||
FpgaDisableTracing();
|
||||
|
||||
Dbprintf("unexpected data %d", retlen);
|
||||
Dbprintf("crc %s", check_crc(CRC_14443_B, x_atqb, retlen) ? "OK" : "BAD");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// tx unframed slot-marker
|
||||
|
||||
if (Demod.posCount) { // no rx, but subcarrier burst detected
|
||||
uid |= (uint64_t)slot << uid_pos;
|
||||
|
||||
slot_mark[0] = 0xB1 + (slot << 1); // ack slot
|
||||
CodeAndTransmit14443bAsReader(slot_mark, sizeof(slot_mark), &start_time, &eof_time, false);
|
||||
break;
|
||||
} else { // no subcarrier burst
|
||||
slot_mark[0] = 0xA1 + (slot << 1); // nak slot
|
||||
CodeAndTransmit14443bAsReader(slot_mark, sizeof(slot_mark), &start_time, &eof_time, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (4 == slot) {
|
||||
FpgaDisableTracing();
|
||||
|
||||
if (g_dbglevel >= DBG_DEBUG) {
|
||||
DbpString("no answer to anticollision");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
retlen = Get14443bAnswerFromTag(x_atqb, sizeof(x_atqb), iso14b_timeout, &eof_time);
|
||||
|
||||
if (g_dbglevel >= DBG_DEBUG) {
|
||||
Dbprintf("anticollision uid %llx", uid);
|
||||
}
|
||||
|
||||
// ATQB too short?
|
||||
if (retlen < 18) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// VALIDATE CRC
|
||||
if (check_crc(CRC_14443_B, x_atqb, 18) == false) { // use fixed len because unstable EOF catch
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (x_atqb[0] != 0x50) {
|
||||
// DbpString("aqtb bad");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (card) {
|
||||
card->uidlen = 8;
|
||||
memcpy(card->uid, x_atqb + 1, 8);
|
||||
memcpy(card->atqb, x_atqb + 9, 7);
|
||||
}
|
||||
|
||||
// DbpString("aqtb ok");
|
||||
|
||||
// send ATTRIB command
|
||||
|
||||
uint8_t txbuf[18];
|
||||
|
||||
txbuf[1] = 0x1d;
|
||||
memcpy(txbuf + 2, &uid, 8);
|
||||
txbuf[10] = 0;
|
||||
txbuf[11] = 0xF;
|
||||
txbuf[12] = 1;
|
||||
txbuf[13] = 0xF;
|
||||
|
||||
AddCrc14B(txbuf + 1, 13);
|
||||
|
||||
start_time = eof_time + ISO14B_TR2;
|
||||
CodeAndTransmit14443bAsReader(txbuf + 1, 15, &start_time, &eof_time, true);
|
||||
|
||||
eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER;
|
||||
retlen = Get14443bAnswerFromTag(x_atqb, sizeof(x_atqb), iso14b_timeout, &eof_time);
|
||||
FpgaDisableTracing();
|
||||
|
||||
if (retlen < 3) {
|
||||
// DbpString("attrib failed");
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (check_crc(CRC_14443_B, x_atqb, 3) == false) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (x_atqb[0] != 0) {
|
||||
// DbpString("attrib failed");
|
||||
return 2;
|
||||
}
|
||||
|
||||
// DbpString("attrib ok");
|
||||
|
||||
// apply PASSWORD command
|
||||
|
||||
txbuf[0] = 2;
|
||||
txbuf[1] = 0x38;
|
||||
// uid from previous command used
|
||||
txbuf[10] = 3;
|
||||
txbuf[11] = 0x4e;
|
||||
txbuf[12] = 0x4b;
|
||||
txbuf[13] = 0x53;
|
||||
txbuf[14] = 0x4F;
|
||||
|
||||
AddCrc14B(txbuf, 15);
|
||||
|
||||
start_time = eof_time + ISO14B_TR2;
|
||||
CodeAndTransmit14443bAsReader(txbuf, 17, &start_time, &eof_time, true);
|
||||
|
||||
eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER;
|
||||
retlen = Get14443bAnswerFromTag(x_atqb, sizeof(x_atqb), iso14b_timeout, &eof_time);
|
||||
|
||||
if (retlen < 4) {
|
||||
// DbpString("passwd failed");
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (check_crc(CRC_14443_B, x_atqb, 4) == false) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (x_atqb[0] != 2 || x_atqb[1] != 0) {
|
||||
// DbpString("passwd failed");
|
||||
return 4;
|
||||
}
|
||||
|
||||
// DbpString("passwd ok");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perform the ISO 14443 B Card Selection procedure
|
||||
* Currently does NOT do any collision handling.
|
||||
* It expects 0-1 cards in the device's range.
|
||||
|
@ -1794,7 +1997,7 @@ int iso14443b_select_card(iso14b_card_select_t *card) {
|
|||
// first, wake up the tag
|
||||
uint32_t start_time = 0;
|
||||
uint32_t eof_time = 0;
|
||||
CodeAndTransmit14443bAsReader(wupb, sizeof(wupb), &start_time, &eof_time);
|
||||
CodeAndTransmit14443bAsReader(wupb, sizeof(wupb), &start_time, &eof_time, true);
|
||||
|
||||
eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER;
|
||||
int retlen = Get14443bAnswerFromTag(r_pupid, sizeof(r_pupid), iso14b_timeout, &eof_time);
|
||||
|
@ -1823,7 +2026,7 @@ int iso14443b_select_card(iso14b_card_select_t *card) {
|
|||
attrib[7] = r_pupid[10] & 0x0F;
|
||||
AddCrc14B(attrib, 9);
|
||||
start_time = eof_time + ISO14B_TR2;
|
||||
CodeAndTransmit14443bAsReader(attrib, sizeof(attrib), &start_time, &eof_time);
|
||||
CodeAndTransmit14443bAsReader(attrib, sizeof(attrib), &start_time, &eof_time, true);
|
||||
|
||||
eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER;
|
||||
retlen = Get14443bAnswerFromTag(r_attrib, sizeof(r_attrib), iso14b_timeout, &eof_time);
|
||||
|
@ -1916,7 +2119,7 @@ static int read_srx_block(uint8_t blocknr, uint8_t *block) {
|
|||
|
||||
uint32_t start_time = 0;
|
||||
uint32_t eof_time = 0;
|
||||
CodeAndTransmit14443bAsReader(cmd, sizeof(cmd), &start_time, &eof_time);
|
||||
CodeAndTransmit14443bAsReader(cmd, sizeof(cmd), &start_time, &eof_time, true);
|
||||
|
||||
eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER;
|
||||
int retlen = Get14443bAnswerFromTag(r_block, sizeof(r_block), iso14b_timeout, &eof_time);
|
||||
|
@ -2223,6 +2426,13 @@ void SendRawCommand14443B_Ex(iso14b_raw_cmd_t *p) {
|
|||
if (status > 0) goto out;
|
||||
}
|
||||
|
||||
if ((p->flags & ISO14B_SELECT_XRX) == ISO14B_SELECT_XRX) {
|
||||
status = iso14443b_select_xrx_card(&card);
|
||||
reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, (uint8_t *)&card, sendlen);
|
||||
// 0: OK, 1: select fail, 2: attrib fail, 3: crc fail, 4: password fail
|
||||
if (status != 0) goto out;
|
||||
}
|
||||
|
||||
if ((p->flags & ISO14B_APDU) == ISO14B_APDU) {
|
||||
uint8_t res;
|
||||
status = iso14443b_apdu(p->raw, p->rawlen, (p->flags & ISO14B_SEND_CHAINING), buf, sizeof(buf), &res);
|
||||
|
@ -2239,7 +2449,7 @@ void SendRawCommand14443B_Ex(iso14b_raw_cmd_t *p) {
|
|||
}
|
||||
uint32_t start_time = 0;
|
||||
uint32_t eof_time = 0;
|
||||
CodeAndTransmit14443bAsReader(p->raw, p->rawlen, &start_time, &eof_time);
|
||||
CodeAndTransmit14443bAsReader(p->raw, p->rawlen, &start_time, &eof_time, true);
|
||||
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred
|
||||
FpgaDisableTracing();
|
||||
|
|
|
@ -39,6 +39,7 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void
|
|||
|
||||
int iso14443b_select_card(iso14b_card_select_t *card);
|
||||
int iso14443b_select_card_srx(iso14b_card_select_t *card);
|
||||
int iso14443b_select_xrx_card(iso14b_card_select_t *card);
|
||||
|
||||
void SimulateIso14443bTag(uint8_t *pupi);
|
||||
void AcquireRawAdcSamplesIso14443b(uint32_t parameter);
|
||||
|
|
|
@ -116,7 +116,6 @@
|
|||
#define CMD_READ_RESP 13
|
||||
#define CMD_INV_RESP 12
|
||||
#define CMD_SYSINFO_RESP 17
|
||||
#define CMD_READBLOCK_RESP 7
|
||||
|
||||
//#define Crc(data, len) Crc(CRC_15693, (data), (len))
|
||||
#define CheckCrc15(data, len) check_crc(CRC_15693, (data), (len))
|
||||
|
@ -178,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
|
||||
// data rate is 1,66 kbit/s (fc/8192)
|
||||
// is designed for more robust communication over longer distances
|
||||
|
@ -263,9 +292,9 @@ void CodeIso15693AsTag(const uint8_t *cmd, size_t len) {
|
|||
}
|
||||
|
||||
// Transmit the command (to the tag) that was placed in cmd[].
|
||||
void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time) {
|
||||
void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time, bool shallow_mod) {
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_FULL_MOD);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | (shallow_mod ? FPGA_HF_READER_MODE_SEND_SHALLOW_MOD : FPGA_HF_READER_MODE_SEND_FULL_MOD));
|
||||
|
||||
if (*start_time < DELAY_ARM_TO_TAG) {
|
||||
*start_time = DELAY_ARM_TO_TAG;
|
||||
|
@ -1586,7 +1615,7 @@ void AcquireRawAdcSamplesIso15693(void) {
|
|||
tosend_t *ts = get_tosend();
|
||||
|
||||
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
|
||||
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY)) ;
|
||||
|
@ -1673,7 +1702,7 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string, bool icla
|
|||
dma_start_time = GetCountSspClk() & 0xfffffff0;
|
||||
}
|
||||
|
||||
volatile uint16_t sniffdata;
|
||||
volatile uint16_t sniffdata = 0;
|
||||
volatile uint16_t sniffdata_prev = sniffdata;
|
||||
sniffdata = *upTo++;
|
||||
|
||||
|
@ -1900,7 +1929,7 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, bool speed_fast, uint8_t
|
|||
}
|
||||
|
||||
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
|
||||
*resp_len = 0;
|
||||
|
@ -1923,7 +1952,7 @@ int SendDataTagEOF(uint8_t *recv, uint16_t max_recv_len, uint32_t start_time, ui
|
|||
|
||||
CodeIso15693AsReaderEOF();
|
||||
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
|
||||
LogTrace_ISO15693(NULL, 0, (start_time * 4), (end_time * 4), NULL, true);
|
||||
|
||||
|
@ -2098,9 +2127,28 @@ void Iso15693InitTag(void) {
|
|||
StartCountSspClk();
|
||||
}
|
||||
|
||||
|
||||
void EmlClearIso15693(void) {
|
||||
// Resetting the bitstream also frees the BigBuf memory, so we do this here to prevent
|
||||
// an inconvenient reset in the future by Iso15693InitTag
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF_15);
|
||||
BigBuf_Clear_EM();
|
||||
reply_ng(CMD_HF_ISO15693_EML_CLEAR, PM3_SUCCESS, NULL, 0);
|
||||
}
|
||||
|
||||
void EmlSetMemIso15693(uint8_t count, uint8_t *data, uint32_t offset) {
|
||||
uint8_t *emCARD = BigBuf_get_EM_addr();
|
||||
memcpy(emCARD + offset, data, count);
|
||||
}
|
||||
|
||||
void EmlGetMemIso15693(uint8_t count, uint8_t *output, uint32_t offset) {
|
||||
uint8_t *emCARD = BigBuf_get_EM_addr();
|
||||
memcpy(output, emCARD + offset, count);
|
||||
}
|
||||
|
||||
// Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
|
||||
// all demodulation performed in arm rather than host. - greg
|
||||
void SimTagIso15693(uint8_t *uid) {
|
||||
void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
|
||||
|
||||
// free eventually allocated BigBuf memory
|
||||
BigBuf_free_keep_EM();
|
||||
|
@ -2109,12 +2157,10 @@ void SimTagIso15693(uint8_t *uid) {
|
|||
|
||||
LED_A_ON();
|
||||
|
||||
Dbprintf("ISO-15963 Simulating uid: %02X%02X%02X%02X%02X%02X%02X%02X", uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]);
|
||||
Dbprintf("ISO-15963 Simulating uid: %02X%02X%02X%02X%02X%02X%02X%02X block size %d", uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7], block_size);
|
||||
|
||||
LED_C_ON();
|
||||
|
||||
|
||||
|
||||
enum { NO_FIELD, IDLE, ACTIVATED, SELECTED, HALTED } chip_state = NO_FIELD;
|
||||
|
||||
bool button_pressed = false;
|
||||
|
@ -2188,7 +2234,7 @@ void SimTagIso15693(uint8_t *uid) {
|
|||
bool slow = !(cmd[0] & ISO15_REQ_DATARATE_HIGH);
|
||||
uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM;
|
||||
|
||||
// Build GET_SYSTEM_INFO command
|
||||
// Build GET_SYSTEM_INFO response
|
||||
uint8_t resp_sysinfo[CMD_SYSINFO_RESP] = {0};
|
||||
|
||||
resp_sysinfo[0] = 0; // Response flags.
|
||||
|
@ -2207,8 +2253,8 @@ void SimTagIso15693(uint8_t *uid) {
|
|||
resp_sysinfo[10] = 0; // DSFID
|
||||
resp_sysinfo[11] = 0; // AFI
|
||||
|
||||
resp_sysinfo[12] = 0x1B; // Memory size.
|
||||
resp_sysinfo[13] = 0x03; // Memory size.
|
||||
resp_sysinfo[12] = 0x1F; // Block count
|
||||
resp_sysinfo[13] = block_size - 1; // Block size.
|
||||
resp_sysinfo[14] = 0x01; // IC reference.
|
||||
|
||||
// CRC
|
||||
|
@ -2221,28 +2267,97 @@ void SimTagIso15693(uint8_t *uid) {
|
|||
LogTrace_ISO15693(resp_sysinfo, CMD_SYSINFO_RESP, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false);
|
||||
}
|
||||
|
||||
// READ_BLOCK
|
||||
if ((cmd[1] == ISO15693_READBLOCK)) {
|
||||
// READ_BLOCK and READ_MULTI_BLOCK
|
||||
if ((cmd[1] == ISO15693_READBLOCK) || (cmd[1] == ISO15693_READ_MULTI_BLOCK)) {
|
||||
bool slow = !(cmd[0] & ISO15_REQ_DATARATE_HIGH);
|
||||
bool addressed = cmd[0] & ISO15_REQ_ADDRESS;
|
||||
bool option = cmd[0] & ISO15_REQ_OPTION;
|
||||
uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM;
|
||||
|
||||
// Build GET_SYSTEM_INFO command
|
||||
uint8_t resp_readblock[CMD_READBLOCK_RESP] = {0};
|
||||
uint8_t address_offset = 0;
|
||||
if (addressed) {
|
||||
address_offset = 8;
|
||||
}
|
||||
|
||||
resp_readblock[0] = 0; // Response flags.
|
||||
resp_readblock[1] = 0; // Block data.
|
||||
resp_readblock[2] = 0; // Block data.
|
||||
resp_readblock[3] = 0; // Block data.
|
||||
resp_readblock[4] = 0; // Block data.
|
||||
uint8_t block_idx = cmd[2 + address_offset];
|
||||
uint8_t block_count = 1;
|
||||
if (cmd[1] == ISO15693_READ_MULTI_BLOCK) {
|
||||
block_count = cmd[3 + address_offset] + 1;
|
||||
}
|
||||
|
||||
// Build READ_(MULTI_)BLOCK response
|
||||
int response_length = 3 + block_size * block_count;
|
||||
int security_offset = 0;
|
||||
if (option) {
|
||||
response_length += block_count;
|
||||
security_offset = 1;
|
||||
}
|
||||
uint8_t resp_readblock[response_length];
|
||||
memset(resp_readblock, 0, response_length);
|
||||
|
||||
resp_readblock[0] = 0; // Response flags
|
||||
for (int j = 0; j < block_count; j++) {
|
||||
// where to put the data of the current block
|
||||
int work_offset = 1 + j * (block_size + security_offset);
|
||||
if (option) {
|
||||
resp_readblock[work_offset] = 0; // Security status
|
||||
}
|
||||
// Block data
|
||||
if (block_size * (block_idx + j + 1) <= CARD_MEMORY_SIZE) {
|
||||
EmlGetMemIso15693(block_size, resp_readblock + (work_offset + security_offset),
|
||||
block_size * (block_idx + j));
|
||||
} else {
|
||||
memset(resp_readblock + work_offset + security_offset, 0, block_size);
|
||||
}
|
||||
}
|
||||
|
||||
// CRC
|
||||
AddCrc15(resp_readblock, 5);
|
||||
CodeIso15693AsTag(resp_readblock, CMD_READBLOCK_RESP);
|
||||
AddCrc15(resp_readblock, response_length - 2);
|
||||
CodeIso15693AsTag(resp_readblock, response_length);
|
||||
|
||||
tosend_t *ts = get_tosend();
|
||||
|
||||
TransmitTo15693Reader(ts->buf, ts->max, &response_time, 0, slow);
|
||||
LogTrace_ISO15693(resp_readblock, CMD_READBLOCK_RESP, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false);
|
||||
LogTrace_ISO15693(resp_readblock, response_length, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false);
|
||||
}
|
||||
|
||||
// WRITE_BLOCK and WRITE_MULTI_BLOCK
|
||||
if ((cmd[1] == ISO15693_WRITEBLOCK) || (cmd[1] == ISO15693_WRITE_MULTI_BLOCK)) {
|
||||
bool slow = !(cmd[0] & ISO15_REQ_DATARATE_HIGH);
|
||||
bool addressed = cmd[0] & ISO15_REQ_ADDRESS;
|
||||
uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM;
|
||||
|
||||
uint8_t address_offset = 0;
|
||||
if (addressed) {
|
||||
address_offset = 8;
|
||||
}
|
||||
|
||||
uint8_t block_idx = cmd[2 + address_offset];
|
||||
uint8_t block_count = 1;
|
||||
uint8_t multi_offset = 0;
|
||||
if (cmd[1] == ISO15693_WRITE_MULTI_BLOCK) {
|
||||
block_count = cmd[3 + address_offset] + 1;
|
||||
multi_offset = 1;
|
||||
}
|
||||
uint8_t *data = cmd + 3 + address_offset + multi_offset;
|
||||
|
||||
// write data
|
||||
EmlSetMemIso15693(block_count * block_size, data, block_idx * block_size);
|
||||
|
||||
// Build WRITE_(MULTI_)BLOCK response
|
||||
int response_length = 3;
|
||||
uint8_t resp_writeblock[response_length];
|
||||
memset(resp_writeblock, 0, response_length);
|
||||
resp_writeblock[0] = 0; // Response flags
|
||||
|
||||
// CRC
|
||||
AddCrc15(resp_writeblock, response_length - 2);
|
||||
CodeIso15693AsTag(resp_writeblock, response_length);
|
||||
|
||||
tosend_t *ts = get_tosend();
|
||||
|
||||
TransmitTo15693Reader(ts->buf, ts->max, &response_time, 0, slow);
|
||||
LogTrace_ISO15693(resp_writeblock, response_length, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2346,6 +2461,8 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint
|
|||
case ISO15693_WRITE_AFI:
|
||||
case ISO15693_LOCK_AFI:
|
||||
case ISO15693_WRITE_DSFID:
|
||||
case ISO15693_WRITE_PASSWORD:
|
||||
case ISO15693_PASSWORD_PROTECT_EAS:
|
||||
case ISO15693_LOCK_DSFID:
|
||||
timeout = ISO15693_READER_TIMEOUT_WRITE;
|
||||
request_answer = data[0] & ISO15_REQ_OPTION;
|
||||
|
@ -2555,7 +2672,7 @@ void SetTag15693Uid(const uint8_t *uid) {
|
|||
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, uint8_t *pwd, const uint8_t *rnd) {
|
||||
memcpy(buffer, pwd, 4);
|
||||
if (rnd) {
|
||||
buffer[0] ^= rnd[0];
|
||||
|
@ -2565,14 +2682,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.
|
||||
uint8_t c[] = {ISO15_REQ_DATARATE_HIGH, ISO15693_GET_RANDOM_NUMBER, 0x04, 0x00, 0x00 };
|
||||
AddCrc15(c, 3);
|
||||
|
||||
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);
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2583,15 +2700,16 @@ static bool get_rnd_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t
|
|||
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, uint8_t *password) {
|
||||
|
||||
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, ISO15693_SET_PASSWORD, 0x04, pass_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
init_password_15693_slixl(&c[4], password, rnd);
|
||||
uint8_t c[] = { ISO15_REQ_DATARATE_HIGH, ISO15693_SET_PASSWORD, 0x04, pass_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
init_password_15693_Slix(&c[4], password, rnd);
|
||||
AddCrc15(c, 8);
|
||||
|
||||
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
||||
|
@ -2604,16 +2722,226 @@ static uint32_t set_pass_15693_slixl(uint32_t start_time, uint32_t *eof_time, ui
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
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) {
|
||||
static uint32_t set_pass_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t pass_id, uint8_t *password, uint8_t *uid) {
|
||||
|
||||
|
||||
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, 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, 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, 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, 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, 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, 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, uint8_t *password) {
|
||||
uint8_t rnd[2];
|
||||
if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) {
|
||||
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 };
|
||||
memcpy(&c[3], uid, 8);
|
||||
init_password_15693_slixl(&c[11], password, rnd);
|
||||
init_password_15693_Slix(&c[11], password, rnd);
|
||||
AddCrc15(c, 15);
|
||||
|
||||
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
||||
|
@ -2626,16 +2954,16 @@ static uint32_t enable_privacy_15693_slixl(uint32_t start_time, uint32_t *eof_ti
|
|||
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, uint8_t *password) {
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
c[11] = pass_id;
|
||||
init_password_15693_slixl(&c[12], password, NULL);
|
||||
init_password_15693_Slix(&c[12], password, NULL);
|
||||
AddCrc15(c, 16);
|
||||
|
||||
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
||||
|
@ -2649,16 +2977,16 @@ static uint32_t write_password_15693_slixl(uint32_t start_time, uint32_t *eof_ti
|
|||
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, uint8_t *password) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
init_password_15693_slixl(&c[11], password, rnd);
|
||||
init_password_15693_Slix(&c[11], password, rnd);
|
||||
AddCrc15(c, 15);
|
||||
|
||||
start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
||||
|
@ -2673,8 +3001,32 @@ static uint32_t destroy_15693_slixl(uint32_t start_time, uint32_t *eof_time, uin
|
|||
|
||||
*/
|
||||
|
||||
// Sets a PRIVACY password to all ZEROS
|
||||
void DisablePrivacySlixLIso15693(uint8_t *password) {
|
||||
void WritePasswordSlixIso15693(uint8_t *old_password, uint8_t *new_password, uint8_t pwd_id) {
|
||||
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(uint8_t *password) {
|
||||
LED_D_ON();
|
||||
Iso15693InitReader();
|
||||
StartCountSspClk();
|
||||
|
@ -2684,13 +3036,12 @@ void DisablePrivacySlixLIso15693(uint8_t *password) {
|
|||
// 0x04 Privacy
|
||||
// 0x08 Destroy SLIX-L
|
||||
// 0x10 EAS/AFI
|
||||
int res = set_pass_15693_slixl(start_time, &eof_time, 0x04, password);
|
||||
reply_ng(CMD_HF_ISO15693_SLIX_L_DISABLE_PRIVACY, res, NULL, 0);
|
||||
int res = disable_privacy_15693_Slix(start_time, &eof_time, 0x04, password);
|
||||
reply_ng(CMD_HF_ISO15693_SLIX_DISABLE_PRIVACY, res, NULL, 0);
|
||||
switch_off();
|
||||
}
|
||||
|
||||
// Sets a EAS/AFI password to all ZEROS
|
||||
void DisableEAS_AFISlixLIso15693(uint8_t *password) {
|
||||
void EnablePrivacySlixIso15693(uint8_t *password) {
|
||||
LED_D_ON();
|
||||
Iso15693InitReader();
|
||||
StartCountSspClk();
|
||||
|
@ -2700,8 +3051,71 @@ void DisableEAS_AFISlixLIso15693(uint8_t *password) {
|
|||
// 0x04 Privacy
|
||||
// 0x08 Destroy SLIX-L
|
||||
// 0x10 EAS/AFI
|
||||
int res = set_pass_15693_slixl(start_time, &eof_time, 0x10, password);
|
||||
reply_ng(CMD_HF_ISO15693_SLIX_L_DISABLE_AESAFI, res, NULL, 0);
|
||||
int res = set_privacy_15693_Slix(start_time, &eof_time, password);
|
||||
reply_ng(CMD_HF_ISO15693_SLIX_ENABLE_PRIVACY, res, NULL, 0);
|
||||
switch_off();
|
||||
}
|
||||
|
||||
|
||||
void DisableEAS_AFISlixIso15693(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(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(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(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(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();
|
||||
}
|
||||
|
|
|
@ -40,13 +40,16 @@ 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);
|
||||
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);
|
||||
|
||||
//void RecordRawAdcSamplesIso15693(void);
|
||||
void AcquireRawAdcSamplesIso15693(void);
|
||||
void ReaderIso15693(iso15_card_select_t *p_card); // ISO15693 reader
|
||||
void SimTagIso15693(uint8_t *uid); // simulate an ISO15693 tag
|
||||
void EmlClearIso15693(void);
|
||||
void EmlSetMemIso15693(uint8_t count, uint8_t *data, uint32_t offset);
|
||||
void EmlGetMemIso15693(uint8_t count, uint8_t *output, uint32_t offset);
|
||||
void SimTagIso15693(uint8_t *uid, uint8_t block_size); // simulate an ISO15693 tag
|
||||
void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag
|
||||
void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI
|
||||
|
||||
|
@ -59,6 +62,12 @@ int SendDataTagEOF(uint8_t *recv, uint16_t max_recv_len, uint32_t start_time, ui
|
|||
|
||||
void SetTag15693Uid(const uint8_t *uid);
|
||||
|
||||
void DisablePrivacySlixLIso15693(uint8_t *password);
|
||||
void DisableEAS_AFISlixLIso15693(uint8_t *password);
|
||||
void WritePasswordSlixIso15693(uint8_t *old_password, uint8_t *new_password, uint8_t pwd_id);
|
||||
void DisablePrivacySlixIso15693(uint8_t *password);
|
||||
void EnablePrivacySlixIso15693(uint8_t *password);
|
||||
void DisableEAS_AFISlixIso15693(uint8_t *password, bool usepwd);
|
||||
void EnableEAS_AFISlixIso15693(uint8_t *password, bool usepwd);
|
||||
void PassProtextEASSlixIso15693(uint8_t *password);
|
||||
void PassProtectAFISlixIso15693(uint8_t *password);
|
||||
void WriteAFIIso15693(uint8_t *password, bool usepwd, uint8_t *uid, bool use_uid, uint8_t afi);
|
||||
#endif
|
||||
|
|
|
@ -79,6 +79,7 @@ static uint16_t rx_frame_from_fpga(void) {
|
|||
return AT91C_BASE_SSC->SSC_RHR;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -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,
|
||||
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) {
|
||||
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
|
||||
removeSignalOffset(data.buffer, samples.total_saved);
|
||||
computeSignalProperties(data.buffer, samples.total_saved);
|
||||
if (bits_per_sample == 8) {
|
||||
// these functions only consider bps==8
|
||||
removeSignalOffset(data.buffer, samples.total_saved);
|
||||
computeSignalProperties(data.buffer, samples.total_saved);
|
||||
}
|
||||
return data.numbits;
|
||||
}
|
||||
/**
|
||||
|
|
|
@ -214,6 +214,65 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
|||
LEDsoff();
|
||||
}
|
||||
|
||||
void MifareReadConfigBlockGDM(uint8_t *key) {
|
||||
|
||||
int retval = PM3_SUCCESS;
|
||||
|
||||
uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
if (par == NULL) {
|
||||
retval = PM3_EMALLOC;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
uint8_t *uid = BigBuf_malloc(10);
|
||||
if (uid == NULL) {
|
||||
retval = PM3_EMALLOC;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
// variables
|
||||
uint32_t cuid = 0;
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
|
||||
uint64_t ui64key = bytes_to_num(key, 6);
|
||||
uint8_t outbuf[16] = {0x00};
|
||||
|
||||
if (iso14443a_select_card(uid, NULL, &cuid, true, 0, true) == false) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
if (mifare_classic_authex_2(pcs, cuid, 0, 0, ui64key, AUTH_FIRST, NULL, NULL, true)) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
};
|
||||
|
||||
if (mifare_classic_readblock_ex(pcs, cuid, 0, outbuf, MIFARE_MAGIC_GDM_READ_CFG)) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
};
|
||||
|
||||
if (mifare_classic_halt(pcs, cuid)) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
};
|
||||
|
||||
OUT:
|
||||
crypto1_deinit(pcs);
|
||||
|
||||
reply_ng(CMD_HF_MIFARE_G4_GDM_CONFIG, retval, outbuf, sizeof(outbuf));
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
set_tracing(false);
|
||||
BigBuf_free();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Select, Authenticate, Read a MIFARE tag.
|
||||
// read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes)
|
||||
|
@ -394,7 +453,6 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
|||
memcpy(blockdata, datain + 10, 16);
|
||||
|
||||
// variables
|
||||
uint8_t isOK = 0;
|
||||
uint8_t uid[10] = {0x00};
|
||||
uint32_t cuid = 0;
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
|
@ -410,57 +468,202 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
|||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
||||
while (true) {
|
||||
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
|
||||
break;
|
||||
};
|
||||
uint8_t retval = 0;
|
||||
|
||||
if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error");
|
||||
break;
|
||||
};
|
||||
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
|
||||
goto OUT;
|
||||
};
|
||||
|
||||
if (mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Write block error");
|
||||
break;
|
||||
};
|
||||
if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error");
|
||||
goto OUT;
|
||||
};
|
||||
|
||||
if (mifare_classic_halt(pcs, cuid)) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error");
|
||||
break;
|
||||
};
|
||||
|
||||
isOK = 1;
|
||||
break;
|
||||
int res = mifare_classic_writeblock(pcs, cuid, blockNo, blockdata);
|
||||
if (res == PM3_ETEAROFF) {
|
||||
retval = PM3_ETEAROFF;
|
||||
goto OUT;
|
||||
} else if (res) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Write block error");
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
if (mifare_classic_halt(pcs, cuid)) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error");
|
||||
goto OUT;
|
||||
};
|
||||
|
||||
retval = 1;
|
||||
|
||||
OUT:
|
||||
crypto1_deinit(pcs);
|
||||
|
||||
if (g_dbglevel >= 2) DbpString("WRITE BLOCK FINISHED");
|
||||
|
||||
reply_mix(CMD_ACK, isOK, 0, 0, 0, 0);
|
||||
|
||||
reply_mix(CMD_ACK, retval, 0, 0, 0, 0);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
set_tracing(false);
|
||||
}
|
||||
|
||||
void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||
void MifareWriteBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key, uint8_t *datain) {
|
||||
|
||||
int retval = PM3_SUCCESS;
|
||||
|
||||
// check args
|
||||
if (datain == NULL) {
|
||||
retval = PM3_EINVARG;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
if (par == NULL) {
|
||||
retval = PM3_EMALLOC;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
uint8_t *uid = BigBuf_malloc(10);
|
||||
if (uid == NULL) {
|
||||
retval = PM3_EMALLOC;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
// variables
|
||||
uint32_t cuid = 0;
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
|
||||
uint64_t ui64key = bytes_to_num(key, 6);
|
||||
|
||||
if (iso14443a_select_card(uid, NULL, &cuid, true, 0, true) == false) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
if (mifare_classic_authex_2(pcs, cuid, blockno, keytype, ui64key, AUTH_FIRST, NULL, NULL, true)) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
};
|
||||
|
||||
int res = mifare_classic_writeblock_ex(pcs, cuid, blockno, datain, true);
|
||||
if (res == PM3_ETEAROFF) {
|
||||
retval = PM3_ETEAROFF;
|
||||
goto OUT;
|
||||
} else if (res) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
if (mifare_classic_halt(pcs, cuid)) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
};
|
||||
|
||||
OUT:
|
||||
crypto1_deinit(pcs);
|
||||
|
||||
reply_ng(CMD_HF_MIFARE_G4_GDM_WRBL, retval, NULL, 0);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
set_tracing(false);
|
||||
BigBuf_free();
|
||||
}
|
||||
|
||||
void MifareWriteConfigBlockGDM(uint8_t *datain) {
|
||||
|
||||
int retval = PM3_SUCCESS;
|
||||
|
||||
// check args
|
||||
if (datain == NULL) {
|
||||
retval = PM3_EINVARG;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
if (par == NULL) {
|
||||
retval = PM3_EMALLOC;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
uint8_t *uid = BigBuf_malloc(10);
|
||||
if (uid == NULL) {
|
||||
retval = PM3_EMALLOC;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
// variables
|
||||
uint32_t cuid = 0;
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
|
||||
if (iso14443a_select_card(uid, NULL, &cuid, true, 0, true) == false) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
uint64_t key = 0;
|
||||
if (mifare_classic_authex_2(pcs, cuid, 0, 0, key, AUTH_FIRST, NULL, NULL, true)) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
};
|
||||
|
||||
int res = mifare_classic_write_cfg_block_gdm(pcs, cuid, datain);
|
||||
if (res == PM3_ETEAROFF) {
|
||||
retval = PM3_ETEAROFF;
|
||||
goto OUT;
|
||||
} else if (res) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
if (mifare_classic_halt(pcs, cuid)) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
};
|
||||
|
||||
OUT:
|
||||
crypto1_deinit(pcs);
|
||||
|
||||
reply_ng(CMD_HF_MIFARE_G4_GDM_WRCFG, retval, NULL, 0);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
set_tracing(false);
|
||||
BigBuf_free();
|
||||
}
|
||||
|
||||
|
||||
void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) {
|
||||
// params
|
||||
uint8_t blockNo = arg0;
|
||||
uint8_t keyType = arg1;
|
||||
uint8_t transferKeyType = arg2;
|
||||
uint64_t ui64Key = 0;
|
||||
uint64_t transferUi64Key = 0;
|
||||
uint8_t blockdata[16] = {0x00};
|
||||
|
||||
ui64Key = bytes_to_num(datain, 6);
|
||||
memcpy(blockdata, datain + 10, 16);
|
||||
memcpy(blockdata, datain + 11, 16);
|
||||
transferUi64Key = bytes_to_num(datain + 27, 6);
|
||||
|
||||
// variables
|
||||
uint8_t action = datain[9];
|
||||
uint8_t transferBlk = datain[10];
|
||||
bool needAuth = datain[33];
|
||||
uint8_t isOK = 0;
|
||||
uint8_t uid[10] = {0x00};
|
||||
uint32_t cuid = 0;
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
||||
uint8_t len = 0;
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
|
@ -490,6 +693,21 @@ void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
|||
break;
|
||||
};
|
||||
|
||||
if (needAuth) {
|
||||
// transfer to other sector
|
||||
if (mifare_classic_auth(pcs, cuid, transferBlk, transferKeyType, transferUi64Key, AUTH_NESTED)) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Nested auth error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// send transfer (commit the change)
|
||||
len = mifare_sendcmd_short(pcs, 1, MIFARE_CMD_TRANSFER, (transferBlk != 0) ? transferBlk : blockNo, receivedAnswer, NULL, NULL);
|
||||
if (len != 1 && receivedAnswer[0] != 0x0A) { // 0x0a - ACK
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error in transfer: %02x", receivedAnswer[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (mifare_classic_halt(pcs, cuid)) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error");
|
||||
break;
|
||||
|
@ -775,7 +993,7 @@ void MifareAcquireNonces(uint32_t arg0, uint32_t flags) {
|
|||
|
||||
if (!have_uid) { // need a full select cycle to get the uid first
|
||||
iso14a_card_select_t card_info;
|
||||
if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
|
||||
if (iso14443a_select_card(uid, &card_info, &cuid, true, 0, true) == 0) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireNonces: Can't select card (ALL)");
|
||||
continue;
|
||||
}
|
||||
|
@ -794,7 +1012,7 @@ void MifareAcquireNonces(uint32_t arg0, uint32_t flags) {
|
|||
}
|
||||
have_uid = true;
|
||||
} else { // no need for anticollision. We can directly select the card
|
||||
if (!iso14443a_fast_select_card(uid, cascade_levels)) {
|
||||
if (iso14443a_fast_select_card(uid, cascade_levels) == 0) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireNonces: Can't select card (UID)");
|
||||
continue;
|
||||
}
|
||||
|
@ -852,7 +1070,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
|||
|
||||
uint64_t ui64Key = bytes_to_num(datain, 6);
|
||||
uint32_t cuid = 0;
|
||||
int16_t isOK = 0;
|
||||
int16_t isOK = PM3_SUCCESS;
|
||||
uint16_t num_nonces = 0;
|
||||
uint8_t nt_par_enc = 0;
|
||||
uint8_t cascade_levels = 0;
|
||||
|
@ -878,18 +1096,21 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
|||
|
||||
LED_C_ON();
|
||||
|
||||
uint8_t prev_enc_nt[] = {0, 0, 0, 0};
|
||||
uint8_t prev_counter = 0;
|
||||
|
||||
for (uint16_t i = 0; i <= PM3_CMD_DATA_SIZE - 9;) {
|
||||
|
||||
// Test if the action was cancelled
|
||||
if (BUTTON_PRESS()) {
|
||||
isOK = 2;
|
||||
isOK = PM3_EOPABORTED;
|
||||
field_off = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!have_uid) { // need a full select cycle to get the uid first
|
||||
if (have_uid == false) { // need a full select cycle to get the uid first
|
||||
iso14a_card_select_t card_info;
|
||||
if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
|
||||
if (iso14443a_select_card(uid, &card_info, &cuid, true, 0, true) == 0) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireEncryptedNonces: Can't select card (ALL)");
|
||||
continue;
|
||||
}
|
||||
|
@ -908,7 +1129,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
|||
}
|
||||
have_uid = true;
|
||||
} else { // no need for anticollision. We can directly select the card
|
||||
if (!iso14443a_fast_select_card(uid, cascade_levels)) {
|
||||
if (iso14443a_fast_select_card(uid, cascade_levels) == 0) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireEncryptedNonces: Can't select card (UID)");
|
||||
continue;
|
||||
}
|
||||
|
@ -917,7 +1138,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
|||
if (slow)
|
||||
SpinDelayUs(HARDNESTED_PRE_AUTHENTICATION_LEADTIME);
|
||||
|
||||
uint32_t nt1;
|
||||
uint32_t nt1 = 0;
|
||||
if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireEncryptedNonces: Auth1 error");
|
||||
continue;
|
||||
|
@ -939,11 +1160,32 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
|||
memcpy(buf + i, receivedAnswer, 4);
|
||||
nt_par_enc = par_enc[0] & 0xf0;
|
||||
} else {
|
||||
nt_par_enc |= par_enc[0] >> 4;
|
||||
nt_par_enc |= par_enc[0] >> 4;
|
||||
memcpy(buf + i + 4, receivedAnswer, 4);
|
||||
memcpy(buf + i + 8, &nt_par_enc, 1);
|
||||
i += 9;
|
||||
}
|
||||
|
||||
|
||||
if (prev_enc_nt[0] == receivedAnswer[0] &&
|
||||
prev_enc_nt[1] == receivedAnswer[1] &&
|
||||
prev_enc_nt[2] == receivedAnswer[2] &&
|
||||
prev_enc_nt[3] == receivedAnswer[3]
|
||||
) {
|
||||
prev_counter++;
|
||||
}
|
||||
memcpy(prev_enc_nt, receivedAnswer, 4);
|
||||
if (prev_counter == 5) {
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
DbpString("Static encrypted nonce detected, exiting...");
|
||||
uint32_t a = bytes_to_num(prev_enc_nt, 4);
|
||||
uint32_t b = bytes_to_num(receivedAnswer, 4);
|
||||
Dbprintf("( %08x vs %08x )", a, b);
|
||||
}
|
||||
isOK = PM3_ESTATIC_NONCE;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LED_C_OFF();
|
||||
|
@ -952,7 +1194,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
|||
reply_old(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf));
|
||||
LED_B_OFF();
|
||||
|
||||
if (g_dbglevel >= 3) DbpString("AcquireEncryptedNonces finished");
|
||||
if (g_dbglevel >= DBG_ERROR) DbpString("AcquireEncryptedNonces finished");
|
||||
|
||||
if (field_off) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
@ -1009,6 +1251,9 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
|
|||
LED_B_ON();
|
||||
WDT_HIT();
|
||||
|
||||
uint32_t prev_enc_nt = 0;
|
||||
uint8_t prev_counter = 0;
|
||||
|
||||
uint16_t unsuccessful_tries = 0;
|
||||
uint16_t davg = 0;
|
||||
dmax = 0;
|
||||
|
@ -1030,7 +1275,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||
if (iso14443a_select_card(uid, NULL, &cuid, true, 0, true) == 0) {
|
||||
if (g_dbglevel >= DBG_INFO) Dbprintf("Nested: Can't select card");
|
||||
rtr--;
|
||||
continue;
|
||||
|
@ -1051,10 +1296,12 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
|
|||
};
|
||||
|
||||
// cards with fixed nonce
|
||||
/*
|
||||
if (nt1 == nt2) {
|
||||
Dbprintf("Nested: %08x vs %08x", nt1, nt2);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
uint32_t nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160
|
||||
for (i = 101; i < 1200; i++) {
|
||||
|
@ -1077,6 +1324,21 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
|
|||
isOK = PM3_EFAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (nt1 == nt2) {
|
||||
prev_counter++;
|
||||
}
|
||||
prev_enc_nt = nt2;
|
||||
|
||||
if (prev_counter == 5) {
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
DbpString("Static encrypted nonce detected, exiting...");
|
||||
Dbprintf("( %08x vs %08x )", prev_enc_nt, nt2);
|
||||
}
|
||||
isOK = PM3_ESTATIC_NONCE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rtr > 1)
|
||||
|
@ -1094,10 +1356,13 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
|
|||
LED_C_ON();
|
||||
|
||||
// get crypted nonces for target sector
|
||||
for (i = 0; i < 2 && !isOK; i++) { // look for exactly two different nonces
|
||||
for (i = 0; ((i < 2) && (isOK == PM3_SUCCESS)); i++) {
|
||||
|
||||
// look for exactly two different nonces
|
||||
|
||||
target_nt[i] = 0;
|
||||
while (target_nt[i] == 0) { // continue until we have an unambiguous nonce
|
||||
// continue until we have an unambiguous nonce
|
||||
while (target_nt[i] == 0) {
|
||||
|
||||
// Test if the action was cancelled
|
||||
if (BUTTON_PRESS() || data_available()) {
|
||||
|
@ -1111,7 +1376,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||
if (iso14443a_select_card(uid, NULL, &cuid, true, 0, true) == false) {
|
||||
if (g_dbglevel >= DBG_INFO) Dbprintf("Nested: Can't select card");
|
||||
continue;
|
||||
};
|
||||
|
@ -1190,6 +1455,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
|
|||
memcpy(payload.nt_b, &target_nt[1], 4);
|
||||
memcpy(payload.ks_b, &target_ks[1], 4);
|
||||
|
||||
LED_B_ON();
|
||||
reply_ng(CMD_HF_MIFARE_NESTED, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload));
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
|
@ -1235,13 +1501,13 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo,
|
|||
continue;
|
||||
};
|
||||
|
||||
// first colleciton
|
||||
// first collection
|
||||
if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) {
|
||||
continue;
|
||||
};
|
||||
|
||||
// pre-generate nonces
|
||||
if (keyType == 1 && nt1 == 0x009080A2) {
|
||||
if (targetKeyType == 1 && nt1 == 0x009080A2) {
|
||||
target_nt[0] = prng_successor(nt1, 161);
|
||||
target_nt[1] = prng_successor(nt1, 321);
|
||||
} else {
|
||||
|
@ -1257,7 +1523,7 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo,
|
|||
nt2 = bytes_to_num(receivedAnswer, 4);
|
||||
target_ks[0] = nt2 ^ target_nt[0];
|
||||
|
||||
// second colleciton
|
||||
// second collection
|
||||
|
||||
if (mifare_classic_halt(pcs, cuid)) {
|
||||
continue;
|
||||
|
@ -1812,13 +2078,14 @@ void MifareChkKeys(uint8_t *datain, uint8_t reserved_mem) {
|
|||
|
||||
uint64_t key = 0;
|
||||
uint32_t cuid = 0;
|
||||
int i, res;
|
||||
uint8_t cascade_levels = 0;
|
||||
struct {
|
||||
uint8_t key[6];
|
||||
bool found;
|
||||
} PACKED keyresult;
|
||||
keyresult.found = false;
|
||||
memset(keyresult.key, 0x00, sizeof(keyresult.key));
|
||||
|
||||
bool have_uid = false;
|
||||
|
||||
uint8_t keyType = datain[0];
|
||||
|
@ -1849,12 +2116,12 @@ void MifareChkKeys(uint8_t *datain, uint8_t reserved_mem) {
|
|||
|
||||
set_tracing(false);
|
||||
|
||||
for (i = 0; i < key_count; i++) {
|
||||
for (uint16_t i = 0; i < key_count; i++) {
|
||||
|
||||
// Iceman: use piwi's faster nonce collecting part in hardnested.
|
||||
if (!have_uid) { // need a full select cycle to get the uid first
|
||||
if (have_uid == false) { // need a full select cycle to get the uid first
|
||||
iso14a_card_select_t card_info;
|
||||
if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
|
||||
if (iso14443a_select_card(uid, &card_info, &cuid, true, 0, true) == false) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("ChkKeys: Can't select card (ALL)");
|
||||
--i; // try same key once again
|
||||
continue;
|
||||
|
@ -1874,7 +2141,7 @@ void MifareChkKeys(uint8_t *datain, uint8_t reserved_mem) {
|
|||
}
|
||||
have_uid = true;
|
||||
} else { // no need for anticollision. We can directly select the card
|
||||
if (!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) {
|
||||
if (iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true) == false) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("ChkKeys: Can't select card (UID)");
|
||||
--i; // try same key once again
|
||||
continue;
|
||||
|
@ -1882,12 +2149,10 @@ void MifareChkKeys(uint8_t *datain, uint8_t reserved_mem) {
|
|||
}
|
||||
|
||||
key = bytes_to_num(datain + i * 6, 6);
|
||||
res = mifare_classic_auth(pcs, cuid, blockNo, keyType, key, AUTH_FIRST);
|
||||
|
||||
if (mifare_classic_auth(pcs, cuid, blockNo, keyType, key, AUTH_FIRST)) {
|
||||
// CHK_TIMEOUT();
|
||||
|
||||
if (res)
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(keyresult.key, datain + i * 6, 6);
|
||||
keyresult.found = true;
|
||||
|
@ -1895,14 +2160,12 @@ void MifareChkKeys(uint8_t *datain, uint8_t reserved_mem) {
|
|||
}
|
||||
|
||||
LED_B_ON();
|
||||
crypto1_deinit(pcs);
|
||||
|
||||
reply_ng(CMD_HF_MIFARE_CHKKEYS, PM3_SUCCESS, (uint8_t *)&keyresult, sizeof(keyresult));
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
|
||||
set_tracing(false);
|
||||
crypto1_deinit(pcs);
|
||||
|
||||
g_dbglevel = oldbg;
|
||||
}
|
||||
|
||||
|
@ -2334,9 +2597,12 @@ void MifareCIdent(bool is_mfc) {
|
|||
uint8_t isGen = 0;
|
||||
uint8_t rec[1] = {0x00};
|
||||
uint8_t recpar[1] = {0x00};
|
||||
uint8_t rats[4] = { ISO14443A_CMD_RATS, 0x80, 0x31, 0x73 };
|
||||
uint8_t rdblf0[4] = { ISO14443A_CMD_READBLOCK, 0xF0, 0x8D, 0x5f};
|
||||
uint8_t rdbl00[4] = { ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa8};
|
||||
uint8_t rats[4] = {ISO14443A_CMD_RATS, 0x80, 0x31, 0x73};
|
||||
uint8_t rdblf0[4] = {ISO14443A_CMD_READBLOCK, 0xF0, 0x8D, 0x5f};
|
||||
uint8_t rdbl00[4] = {ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa8};
|
||||
uint8_t gen4gmd[4] = {MIFARE_MAGIC_GDM_AUTH_KEY, 0x00, 0x6C, 0x92};
|
||||
uint8_t gen4GetConf[8] = {GEN_4GTU_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4GTU_GETCNF, 0, 0};
|
||||
uint8_t superGen1[9] = {0x0A, 0x00, 0x00, 0xA6, 0xB0, 0x00, 0x10, 0x14, 0x1D};
|
||||
uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
uint8_t *buf = BigBuf_malloc(PM3_CMD_DATA_SIZE);
|
||||
uint8_t *uid = BigBuf_malloc(10);
|
||||
|
@ -2368,6 +2634,24 @@ void MifareCIdent(bool is_mfc) {
|
|||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
||||
int res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
if (res == 2) {
|
||||
// Check for Magic Gen4 GTU with default password:
|
||||
// Get config should return 30 or 32 bytes
|
||||
AddCrc14A(gen4GetConf, sizeof(gen4GetConf) - 2);
|
||||
ReaderTransmit(gen4GetConf, sizeof(gen4GetConf), NULL);
|
||||
res = ReaderReceive(buf, par);
|
||||
if (res == 32 || res == 34) {
|
||||
isGen = MAGIC_GEN_4GTU;
|
||||
goto OUT;
|
||||
}
|
||||
}
|
||||
|
||||
// reset card
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(40);
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
||||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
if (res == 2) {
|
||||
if (cuid == 0xAA55C396) {
|
||||
isGen = MAGIC_GEN_UNFUSED;
|
||||
|
@ -2377,19 +2661,29 @@ void MifareCIdent(bool is_mfc) {
|
|||
ReaderTransmit(rats, sizeof(rats), NULL);
|
||||
res = ReaderReceive(buf, par);
|
||||
if (res) {
|
||||
// test for super card
|
||||
ReaderTransmit(superGen1, sizeof(superGen1), NULL);
|
||||
res = ReaderReceive(buf, par);
|
||||
if (res == 22) {
|
||||
isGen = MAGIC_SUPER_GEN1;
|
||||
|
||||
// test for some MFC gen2
|
||||
if (memcmp(buf, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10\xF0\x05", 11) == 0) {
|
||||
// check for super card gen2
|
||||
// not available after RATS, reset card before executing
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(40);
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
||||
// super card ident
|
||||
uint8_t super[] = {0x0A, 0x00, 0x00, 0xA6, 0xB0, 0x00, 0x10, 0x14, 0x1D};
|
||||
ReaderTransmit(super, sizeof(super), NULL);
|
||||
iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
ReaderTransmit(rdbl00, sizeof(rdbl00), NULL);
|
||||
res = ReaderReceive(buf, par);
|
||||
if (res == 22) {
|
||||
isGen = MAGIC_SUPER;
|
||||
goto OUT;
|
||||
if (res == 18) {
|
||||
isGen = MAGIC_SUPER_GEN2;
|
||||
}
|
||||
|
||||
goto OUT;
|
||||
}
|
||||
// test for some MFC gen2
|
||||
if (memcmp(buf, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10\xF0\x05", 11) == 0) {
|
||||
isGen = MAGIC_GEN_2;
|
||||
goto OUT;
|
||||
}
|
||||
|
@ -2439,7 +2733,7 @@ void MifareCIdent(bool is_mfc) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// magic MFC Gen3 test
|
||||
// magic MFC Gen3 test 1
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(40);
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
@ -2451,6 +2745,21 @@ void MifareCIdent(bool is_mfc) {
|
|||
isGen = MAGIC_GEN_3;
|
||||
}
|
||||
}
|
||||
|
||||
// magic MFC Gen4 GDM test
|
||||
if (isGen != MAGIC_GEN_3) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(40);
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
if (res == 2) {
|
||||
ReaderTransmit(gen4gmd, sizeof(gen4gmd), NULL);
|
||||
res = ReaderReceive(buf, par);
|
||||
if (res == 4) {
|
||||
isGen = MAGIC_GEN_4GDM;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2465,6 +2774,8 @@ OUT:
|
|||
|
||||
void MifareHasStaticNonce(void) {
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
||||
// variables
|
||||
int retval = PM3_SUCCESS;
|
||||
uint32_t nt = 0;
|
||||
|
@ -2682,42 +2993,152 @@ OUT:
|
|||
BigBuf_free();
|
||||
}
|
||||
|
||||
void MifareG4ReadBlk(uint8_t blockno, uint8_t *pwd) {
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
void MifareG4ReadBlk(uint8_t blockno, uint8_t *pwd, uint8_t workFlags) {
|
||||
bool setup = ((workFlags & MAGIC_INIT) == MAGIC_INIT) ;
|
||||
bool done = ((workFlags & MAGIC_OFF) == MAGIC_OFF) ;
|
||||
|
||||
int res = 0;
|
||||
int retval = PM3_SUCCESS;
|
||||
uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
|
||||
uint8_t *buf = BigBuf_malloc(PM3_CMD_DATA_SIZE);
|
||||
uint8_t *uid = BigBuf_malloc(10);
|
||||
if (iso14443a_select_card(uid, NULL, NULL, true, 0, true) == false) {
|
||||
retval = PM3_ESOFT;
|
||||
if (buf == NULL) {
|
||||
retval = PM3_EMALLOC;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
LED_B_ON();
|
||||
uint32_t save_iso14a_timeout = iso14a_get_timeout();
|
||||
iso14a_set_timeout(13560000 / 1000 / (8 * 16) * 1000); // 2 seconds timeout
|
||||
uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
if (par == NULL) {
|
||||
retval = PM3_EMALLOC;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
uint8_t cmd[] = { 0xCF, 0x00, 0x00, 0x00, 0x00, 0xCE, blockno, 0x00, 0x00};
|
||||
if (setup) {
|
||||
uint8_t *uid = BigBuf_malloc(10);
|
||||
if (uid == NULL) {
|
||||
retval = PM3_EMALLOC;
|
||||
goto OUT;
|
||||
}
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
if (iso14443a_select_card(uid, NULL, NULL, true, 0, true) == false) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
}
|
||||
}
|
||||
|
||||
LED_B_ON();
|
||||
|
||||
static uint32_t save_iso14a_timeout;
|
||||
if (setup) {
|
||||
save_iso14a_timeout = iso14a_get_timeout();
|
||||
iso14a_set_timeout(13560000 / 1000 / (8 * 16) * 1000); // 2 seconds timeout
|
||||
}
|
||||
|
||||
uint8_t cmd[] = { GEN_4GTU_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4GTU_READ, blockno,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
memcpy(cmd + 1, pwd, 4);
|
||||
|
||||
AddCrc14A(cmd, sizeof(cmd) - 2);
|
||||
|
||||
ReaderTransmit(cmd, sizeof(cmd), NULL);
|
||||
int res = ReaderReceive(buf, par);
|
||||
res = ReaderReceive(buf, par);
|
||||
|
||||
if (res != 18) {
|
||||
retval = PM3_ESOFT;
|
||||
}
|
||||
iso14a_set_timeout(save_iso14a_timeout);
|
||||
|
||||
if (done || retval != 0) iso14a_set_timeout(save_iso14a_timeout);
|
||||
LED_B_OFF();
|
||||
|
||||
OUT:
|
||||
reply_ng(CMD_HF_MIFARE_G4_RDBL, retval, buf, 18);
|
||||
reply_ng(CMD_HF_MIFARE_G4_RDBL, retval, buf, res);
|
||||
// turns off
|
||||
OnSuccessMagic();
|
||||
if (done || retval != 0) FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
if (done || retval != 0) set_tracing(false);
|
||||
BigBuf_free();
|
||||
}
|
||||
|
||||
void MifareG4WriteBlk(uint8_t blockno, uint8_t *pwd, uint8_t *data, uint8_t workFlags) {
|
||||
bool setup = ((workFlags & MAGIC_INIT) == MAGIC_INIT) ;
|
||||
bool done = ((workFlags & MAGIC_OFF) == MAGIC_OFF) ;
|
||||
|
||||
int res = 0;
|
||||
int retval = PM3_SUCCESS;
|
||||
|
||||
uint8_t *buf = BigBuf_malloc(PM3_CMD_DATA_SIZE);
|
||||
if (buf == NULL) {
|
||||
retval = PM3_EMALLOC;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
// check args
|
||||
if (data == NULL) {
|
||||
retval = PM3_EINVARG;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
if (par == NULL) {
|
||||
retval = PM3_EMALLOC;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
if (setup) {
|
||||
uint8_t *uid = BigBuf_malloc(10);
|
||||
if (uid == NULL) {
|
||||
retval = PM3_EMALLOC;
|
||||
goto OUT;
|
||||
}
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
if (iso14443a_select_card(uid, NULL, NULL, true, 0, true) == false) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
}
|
||||
}
|
||||
|
||||
LED_B_ON();
|
||||
|
||||
static uint32_t save_iso14a_timeout;
|
||||
if (setup) {
|
||||
save_iso14a_timeout = iso14a_get_timeout();
|
||||
iso14a_set_timeout(13560000 / 1000 / (8 * 16) * 1000); // 2 seconds timeout
|
||||
}
|
||||
|
||||
uint8_t cmd[] = { GEN_4GTU_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4GTU_WRITE, blockno,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
memcpy(cmd + 1, pwd, 4);
|
||||
memcpy(cmd + 7, data, 16);
|
||||
|
||||
AddCrc14A(cmd, sizeof(cmd) - 2);
|
||||
|
||||
ReaderTransmit(cmd, sizeof(cmd), NULL);
|
||||
res = ReaderReceive(buf, par);
|
||||
|
||||
if ((res != 4) || (memcmp(buf, "\x90\x00\xfd\x07", 4) != 0)) {
|
||||
retval = PM3_ESOFT;
|
||||
}
|
||||
|
||||
if (done || retval != 0) iso14a_set_timeout(save_iso14a_timeout);
|
||||
LED_B_OFF();
|
||||
|
||||
OUT:
|
||||
reply_ng(CMD_HF_MIFARE_G4_WRBL, retval, buf, res);
|
||||
// turns off
|
||||
if (done || retval != 0) FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
if (done || retval != 0) set_tracing(false);
|
||||
BigBuf_free();
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes);
|
|||
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 MifareValue(uint8_t arg0, uint8_t arg1, uint8_t arg2, 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);
|
||||
|
@ -46,18 +46,26 @@ void MifareEMemGet(uint8_t blockno, uint8_t blockcnt);
|
|||
int MifareECardLoad(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 MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain);
|
||||
void MifareCIdent(bool is_mfc); // is "magic chinese" card?
|
||||
void MifareHasStaticNonce(void); // Has the tag a static nonce?
|
||||
|
||||
// MFC GEN3
|
||||
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 MifareGen3Blk(uint8_t block_len, uint8_t *block); // Gen 3 magic card overwrite manufacturer block
|
||||
void MifareGen3Freez(void); // Gen 3 magic card lock further UID changes
|
||||
|
||||
// MFC GEN4 GDM
|
||||
void MifareReadConfigBlockGDM(uint8_t *key);
|
||||
void MifareWriteConfigBlockGDM(uint8_t *datain);
|
||||
void MifareWriteBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key, uint8_t *datain);
|
||||
|
||||
// MFC GEN4 GTU
|
||||
void MifareG4ReadBlk(uint8_t blockno, uint8_t *pwd);
|
||||
void MifareG4ReadBlk(uint8_t blockno, uint8_t *pwd, uint8_t workFlags);
|
||||
void MifareG4WriteBlk(uint8_t blockno, uint8_t *pwd, uint8_t *data, uint8_t workFlags);
|
||||
|
||||
void MifareSetMod(uint8_t *datain);
|
||||
void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key);
|
||||
|
|
|
@ -139,6 +139,7 @@ void MifareDesfireGetInformation(void) {
|
|||
uint8_t details[14];
|
||||
} PACKED payload;
|
||||
|
||||
memset(&payload, 0x00, sizeof(payload));
|
||||
/*
|
||||
1 = PCB 1
|
||||
2 = cid 2
|
||||
|
@ -181,6 +182,12 @@ void MifareDesfireGetInformation(void) {
|
|||
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));
|
||||
|
||||
// ADDITION_FRAME 1
|
||||
|
@ -193,6 +200,13 @@ void MifareDesfireGetInformation(void) {
|
|||
switch_off();
|
||||
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));
|
||||
|
||||
// ADDITION_FRAME 2
|
||||
|
@ -205,6 +219,12 @@ void MifareDesfireGetInformation(void) {
|
|||
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));
|
||||
|
||||
LED_B_ON();
|
||||
|
|
|
@ -486,6 +486,13 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
|
|||
uint8_t *rats = NULL;
|
||||
uint8_t rats_len = 0;
|
||||
|
||||
|
||||
// if fct is called with NULL we need to assign some memory since this pointer is passaed around
|
||||
uint8_t datain_tmp[10] = {0};
|
||||
if (datain == NULL) {
|
||||
datain = datain_tmp;
|
||||
}
|
||||
|
||||
//Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2
|
||||
// This will be used in the reader-only attack.
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "mifareutil.h"
|
||||
|
||||
#include "appmain.h" // tearoff hook
|
||||
#include "string.h"
|
||||
#include "BigBuf.h"
|
||||
#include "iso14443a.h"
|
||||
|
@ -137,25 +138,25 @@ 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) {
|
||||
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 len;
|
||||
uint32_t pos, nt, ntpp; // Supplied tag nonce
|
||||
uint8_t par[1] = {0x00};
|
||||
return mifare_classic_authex_2(pcs, uid, blockNo, keyType, ui64Key, isNested, ntptr, timing, false);
|
||||
}
|
||||
int mifare_classic_authex_2(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing, bool is_gdm) {
|
||||
|
||||
// "random" reader nonce:
|
||||
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 receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
||||
|
||||
// "random" reader nonce:
|
||||
num_to_bytes(prng_successor(GetTickCount(), 32), 4, nr);
|
||||
|
||||
// Transmit MIFARE_CLASSIC_AUTH
|
||||
len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing);
|
||||
// Transmit MIFARE_CLASSIC_AUTH 0x60, 0x61 or GDM 0x80
|
||||
uint8_t cmdbyte = (is_gdm) ? MIFARE_MAGIC_GDM_AUTH_KEY : MIFARE_AUTH_KEYA + (keyType & 0x01);
|
||||
int len = mifare_sendcmd_short(pcs, isNested, cmdbyte, blockNo, receivedAnswer, receivedAnswerPar, timing);
|
||||
if (len != 4) return 1;
|
||||
|
||||
// Save the tag nonce (nt)
|
||||
nt = bytes_to_num(receivedAnswer, 4);
|
||||
uint32_t nt = bytes_to_num(receivedAnswer, 4);
|
||||
|
||||
// ----------------------------- crypto1 create
|
||||
if (isNested)
|
||||
|
@ -181,7 +182,9 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
|
|||
*ntptr = nt;
|
||||
|
||||
// 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++) {
|
||||
mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos];
|
||||
par[0] |= (((filter(pcs->odd) ^ oddparity8(nr[pos])) & 0x01) << (7 - pos));
|
||||
|
@ -217,8 +220,8 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
|
|||
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 (g_dbglevel >= DBG_EXTENDED) Dbprintf("Authentication failed. Error card response");
|
||||
return 3;
|
||||
|
@ -227,13 +230,14 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
|
|||
}
|
||||
|
||||
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) {
|
||||
return mifare_classic_readblock_ex(pcs, uid, blockNo, blockData, ISO14443A_CMD_READBLOCK);
|
||||
}
|
||||
int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint32_t uid, 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 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 (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error %02x", receivedAnswer[0]);
|
||||
return 1;
|
||||
|
@ -243,6 +247,7 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
|
|||
return 2;
|
||||
}
|
||||
|
||||
uint8_t bt[2] = {0x00, 0x00};
|
||||
memcpy(bt, receivedAnswer + 16, 2);
|
||||
AddCrc14A(receivedAnswer, 16);
|
||||
if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
|
||||
|
@ -411,57 +416,114 @@ int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) {
|
|||
}
|
||||
|
||||
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) {
|
||||
// variables
|
||||
uint16_t len = 0;
|
||||
uint32_t pos = 0;
|
||||
uint8_t par[3] = {0x00, 0x00, 0x00}; // enough for 18 Bytes to send
|
||||
uint8_t res = 0;
|
||||
return mifare_classic_writeblock_ex(pcs, uid, blockNo, blockData, false);
|
||||
}
|
||||
int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, bool is_gdm) {
|
||||
|
||||
uint8_t d_block[18], d_block_enc[18];
|
||||
// variables
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
||||
|
||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
||||
len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||
// command MIFARE_MAGIC_GDM_WRITEBLOCK
|
||||
uint16_t len;
|
||||
if (is_gdm) {
|
||||
len = mifare_sendcmd_short(pcs, 1, MIFARE_MAGIC_GDM_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||
} else {
|
||||
len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, 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;
|
||||
}
|
||||
|
||||
uint8_t d_block[18], d_block_enc[18];
|
||||
memcpy(d_block, blockData, 16);
|
||||
AddCrc14A(d_block, 16);
|
||||
|
||||
// enough for 18 Bytes to send
|
||||
uint8_t par[3] = {0x00, 0x00, 0x00};
|
||||
// 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];
|
||||
par[pos >> 3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos & 0x0007)));
|
||||
}
|
||||
|
||||
ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL);
|
||||
|
||||
// Receive the response
|
||||
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
||||
// tearoff occurred
|
||||
if (tearoff_hook() == PM3_ETEAROFF) {
|
||||
return PM3_ETEAROFF;
|
||||
} else {
|
||||
// Receive the response
|
||||
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
||||
|
||||
res = 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], 2)) << 2;
|
||||
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3;
|
||||
uint8_t res = 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], 2)) << 2;
|
||||
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3;
|
||||
|
||||
if ((len != 1) || (res != 0x0A)) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd send data2 Error: %02x", res);
|
||||
return 2;
|
||||
if ((len != 1) || (res != 0x0A)) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd send data2 Error: %02x", res);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mifare_classic_write_cfg_block_gdm(struct Crypto1State *pcs, uint32_t uid, uint8_t *blockData) {
|
||||
|
||||
// variables
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
||||
|
||||
uint16_t len = mifare_sendcmd_short(pcs, 1, MIFARE_MAGIC_GDM_WRITE_CFG, 0, receivedAnswer, receivedAnswerPar, NULL);
|
||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t d_block[18], d_block_enc[18];
|
||||
memcpy(d_block, blockData, 16);
|
||||
AddCrc14A(d_block, 16);
|
||||
|
||||
// enough for 18 Bytes to send
|
||||
uint8_t par[3] = {0x00, 0x00, 0x00};
|
||||
// crypto
|
||||
for (uint32_t pos = 0; pos < 18; 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)));
|
||||
}
|
||||
|
||||
ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL);
|
||||
|
||||
// tearoff occurred
|
||||
if (tearoff_hook() == PM3_ETEAROFF) {
|
||||
return PM3_ETEAROFF;
|
||||
} else {
|
||||
// Receive the response
|
||||
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
||||
|
||||
uint8_t res = 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], 2)) << 2;
|
||||
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3;
|
||||
|
||||
if ((len != 1) || (res != 0x0A)) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int mifare_classic_value(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t action) {
|
||||
// variables
|
||||
uint16_t len = 0;
|
||||
uint32_t pos = 0;
|
||||
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 receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
||||
|
@ -471,6 +533,8 @@ int mifare_classic_value(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo
|
|||
|
||||
if (action == 0x01)
|
||||
command = MIFARE_CMD_DEC;
|
||||
if (action == 0x02)
|
||||
command = MIFARE_CMD_RESTORE;
|
||||
|
||||
// Send increment or decrement command
|
||||
len = mifare_sendcmd_short(pcs, 1, command, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||
|
@ -495,7 +559,7 @@ int mifare_classic_value(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo
|
|||
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
||||
|
||||
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], 1)) << 1;
|
||||
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 2)) << 2;
|
||||
|
@ -505,13 +569,6 @@ int mifare_classic_value(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo
|
|||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd send data2 Error: %02x", res);
|
||||
return 2;
|
||||
}
|
||||
} 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;
|
||||
|
|
|
@ -72,11 +72,17 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t
|
|||
// 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_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_2(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing, bool is_gdm);
|
||||
|
||||
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||
int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t iso_byte);
|
||||
|
||||
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid);
|
||||
int mifare_classic_halt_ex(struct Crypto1State *pcs);
|
||||
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||
int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, bool is_gdm);
|
||||
int mifare_classic_value(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t action);
|
||||
int mifare_classic_write_cfg_block_gdm(struct Crypto1State *pcs, uint32_t uid, uint8_t *blockData);
|
||||
|
||||
// Ultralight/NTAG...
|
||||
int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack);
|
||||
|
|
|
@ -39,14 +39,14 @@
|
|||
|
||||
typedef struct {
|
||||
uint8_t *buffer;
|
||||
uint8_t numbits;
|
||||
uint8_t position;
|
||||
uint32_t numbits;
|
||||
uint32_t position;
|
||||
} BitstreamIn_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *buffer;
|
||||
uint8_t numbits;
|
||||
uint8_t position;
|
||||
uint32_t numbits;
|
||||
uint32_t position;
|
||||
} BitstreamOut_t;
|
||||
|
||||
bool headBit(BitstreamIn_t *stream);
|
||||
|
|
123
armsrc/spiffs.c
123
armsrc/spiffs.c
|
@ -18,7 +18,7 @@
|
|||
// SPIFFS api for RDV40 Integration
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define SPIFFS_CFG_PHYS_SZ (1024 * 128)
|
||||
#define SPIFFS_CFG_PHYS_SZ (1024 * 192)
|
||||
#define SPIFFS_CFG_PHYS_ERASE_SZ (4 * 1024)
|
||||
#define SPIFFS_CFG_PHYS_ADDR (0)
|
||||
#define SPIFFS_CFG_LOG_PAGE_SZ (256)
|
||||
|
@ -69,7 +69,7 @@ static s32_t rdv40_spiffs_llread(u32_t addr, u32_t size, u8_t *dst) {
|
|||
|
||||
static s32_t rdv40_spiffs_llwrite(u32_t addr, u32_t size, u8_t *src) {
|
||||
|
||||
if (!FlashInit()) {
|
||||
if (FlashInit() == false) {
|
||||
return 129;
|
||||
}
|
||||
Flash_Write(addr, src, size);
|
||||
|
@ -77,9 +77,7 @@ static s32_t rdv40_spiffs_llwrite(u32_t addr, u32_t size, u8_t *src) {
|
|||
}
|
||||
|
||||
static s32_t rdv40_spiffs_llerase(u32_t addr, u32_t size) {
|
||||
uint8_t erased = 0;
|
||||
|
||||
if (!FlashInit()) {
|
||||
if (FlashInit() == false) {
|
||||
return 130;
|
||||
}
|
||||
|
||||
|
@ -99,10 +97,12 @@ static s32_t rdv40_spiffs_llerase(u32_t addr, u32_t size) {
|
|||
|
||||
if (g_dbglevel >= DBG_DEBUG) Dbprintf("LLERASEDBG : block : %d, sector : %d \n", block, sector);
|
||||
|
||||
erased = Flash_Erase4k(block, sector);
|
||||
uint8_t erased = Flash_Erase4k(block, sector);
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
FlashStop();
|
||||
|
||||
// iceman: SPIFFS_OK expands to 0, erased is bool from Flash_Erase4k, which returns TRUE if ok.
|
||||
// so this return logic looks wrong.
|
||||
return (SPIFFS_OK == erased);
|
||||
}
|
||||
|
||||
|
@ -151,8 +151,17 @@ int rdv40_spiffs_mount(void) {
|
|||
// uncached version
|
||||
// int ret = SPIFFS_mount(&fs, &cfg, spiffs_work_buf, spiffs_fds,
|
||||
// sizeof(spiffs_fds), 0, 0, 0); cached version, experimental
|
||||
int ret = SPIFFS_mount(&fs, &cfg, spiffs_work_buf, spiffs_fds, sizeof(spiffs_fds), spiffs_cache_buf,
|
||||
sizeof(spiffs_cache_buf), 0);
|
||||
int ret = SPIFFS_mount(
|
||||
&fs,
|
||||
&cfg,
|
||||
spiffs_work_buf,
|
||||
spiffs_fds,
|
||||
sizeof(spiffs_fds),
|
||||
spiffs_cache_buf,
|
||||
sizeof(spiffs_cache_buf),
|
||||
0
|
||||
);
|
||||
|
||||
if (ret == SPIFFS_OK) {
|
||||
RDV40_SPIFFS_MOUNT_STATUS = RDV40_SPIFFS_MOUNTED;
|
||||
}
|
||||
|
@ -189,33 +198,38 @@ int rdv40_spiffs_check(void) {
|
|||
|
||||
void write_to_spiffs(const char *filename, uint8_t *src, uint32_t size) {
|
||||
spiffs_file fd = SPIFFS_open(&fs, filename, SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0);
|
||||
if (SPIFFS_write(&fs, fd, src, size) < 0)
|
||||
Dbprintf("errno %i\n", SPIFFS_errno(&fs));
|
||||
if (SPIFFS_write(&fs, fd, src, size) < 0) {
|
||||
Dbprintf("wr errno %i\n", SPIFFS_errno(&fs));
|
||||
}
|
||||
SPIFFS_close(&fs, fd);
|
||||
}
|
||||
|
||||
void append_to_spiffs(const char *filename, uint8_t *src, uint32_t size) {
|
||||
spiffs_file fd = SPIFFS_open(&fs, filename, SPIFFS_APPEND | SPIFFS_RDWR, 0);
|
||||
if (SPIFFS_write(&fs, fd, src, size) < 0)
|
||||
if (SPIFFS_write(&fs, fd, src, size) < 0) {
|
||||
Dbprintf("errno %i\n", SPIFFS_errno(&fs));
|
||||
}
|
||||
SPIFFS_close(&fs, fd);
|
||||
}
|
||||
|
||||
void read_from_spiffs(const char *filename, uint8_t *dst, uint32_t size) {
|
||||
spiffs_file fd = SPIFFS_open(&fs, filename, SPIFFS_RDWR, 0);
|
||||
if (SPIFFS_read(&fs, fd, dst, size) < 0)
|
||||
if (SPIFFS_read(&fs, fd, dst, size) < 0) {
|
||||
Dbprintf("errno %i\n", SPIFFS_errno(&fs));
|
||||
}
|
||||
SPIFFS_close(&fs, fd);
|
||||
}
|
||||
|
||||
static void rename_in_spiffs(const char *old_filename, const char *new_filename) {
|
||||
if (SPIFFS_rename(&fs, old_filename, new_filename) < 0)
|
||||
if (SPIFFS_rename(&fs, old_filename, new_filename) < 0) {
|
||||
Dbprintf("errno %i\n", SPIFFS_errno(&fs));
|
||||
}
|
||||
}
|
||||
|
||||
static void remove_from_spiffs(const char *filename) {
|
||||
if (SPIFFS_remove(&fs, filename) < 0)
|
||||
if (SPIFFS_remove(&fs, filename) < 0) {
|
||||
Dbprintf("errno %i\n", SPIFFS_errno(&fs));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t size_in_spiffs(const char *filename) {
|
||||
|
@ -233,8 +247,11 @@ static rdv40_spiffs_fsinfo info_of_spiffs(void) {
|
|||
fsinfo.pageSize = LOG_PAGE_SIZE;
|
||||
fsinfo.maxOpenFiles = RDV40_SPIFFS_MAX_FD;
|
||||
fsinfo.maxPathLength = SPIFFS_OBJ_NAME_LEN;
|
||||
if (SPIFFS_info(&fs, &fsinfo.totalBytes, &fsinfo.usedBytes) < 0)
|
||||
|
||||
if (SPIFFS_info(&fs, &fsinfo.totalBytes, &fsinfo.usedBytes) < 0) {
|
||||
Dbprintf("errno %i\n", SPIFFS_errno(&fs));
|
||||
}
|
||||
|
||||
fsinfo.freeBytes = fsinfo.totalBytes - fsinfo.usedBytes;
|
||||
// Rounding without float may be improved
|
||||
fsinfo.usedPercent = ((100 * fsinfo.usedBytes) + (fsinfo.totalBytes / 2)) / fsinfo.totalBytes;
|
||||
|
@ -245,16 +262,18 @@ static rdv40_spiffs_fsinfo info_of_spiffs(void) {
|
|||
int exists_in_spiffs(const char *filename) {
|
||||
spiffs_stat stat;
|
||||
int rc = SPIFFS_stat(&fs, filename, &stat);
|
||||
return rc == SPIFFS_OK;
|
||||
return (rc == SPIFFS_OK);
|
||||
}
|
||||
|
||||
static RDV40SpiFFSFileType filetype_in_spiffs(const char *filename) {
|
||||
RDV40SpiFFSFileType filetype = RDV40_SPIFFS_FILETYPE_UNKNOWN;
|
||||
char symlinked[SPIFFS_OBJ_NAME_LEN];
|
||||
sprintf(symlinked, "%s.lnk", filename);
|
||||
|
||||
if (exists_in_spiffs(filename)) {
|
||||
filetype = RDV40_SPIFFS_FILETYPE_REAL;
|
||||
}
|
||||
|
||||
if (exists_in_spiffs(symlinked)) {
|
||||
if (filetype != RDV40_SPIFFS_FILETYPE_UNKNOWN) {
|
||||
filetype = RDV40_SPIFFS_FILETYPE_BOTH;
|
||||
|
@ -262,19 +281,20 @@ static RDV40SpiFFSFileType filetype_in_spiffs(const char *filename) {
|
|||
filetype = RDV40_SPIFFS_FILETYPE_SYMLINK;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_dbglevel >= DBG_DEBUG) {
|
||||
switch (filetype) {
|
||||
case RDV40_SPIFFS_FILETYPE_REAL:
|
||||
Dbprintf("Filetype is : RDV40_SPIFFS_FILETYPE_REAL");
|
||||
Dbprintf("Filetype is " _YELLOW_("RDV40_SPIFFS_FILETYPE_REAL"));
|
||||
break;
|
||||
case RDV40_SPIFFS_FILETYPE_SYMLINK:
|
||||
Dbprintf("Filetype is : RDV40_SPIFFS_FILETYPE_SYMLINK");
|
||||
Dbprintf("Filetype is " _YELLOW_("RDV40_SPIFFS_FILETYPE_SYMLINK"));
|
||||
break;
|
||||
case RDV40_SPIFFS_FILETYPE_BOTH:
|
||||
Dbprintf("Filetype is : RDV40_SPIFFS_FILETYPE_BOTH");
|
||||
Dbprintf("Filetype is " _YELLOW_("RDV40_SPIFFS_FILETYPE_BOTH"));
|
||||
break;
|
||||
case RDV40_SPIFFS_FILETYPE_UNKNOWN:
|
||||
Dbprintf("Filetype is : RDV40_SPIFFS_FILETYPE_UNKNOWN");
|
||||
Dbprintf("Filetype is " _YELLOW_("RDV40_SPIFFS_FILETYPE_UNKNOWN"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -386,10 +406,13 @@ just get back to this state. If not, just don't.
|
|||
// went well, it will return SPIFFS_OK if everything went well, and a report
|
||||
// back the chain a SPI_ERRNO if not.
|
||||
int rdv40_spiffs_lazy_mount_rollback(int changed) {
|
||||
if (!changed)
|
||||
if (!changed) {
|
||||
return SPIFFS_OK;
|
||||
if (rdv40_spiffs_mounted())
|
||||
}
|
||||
|
||||
if (rdv40_spiffs_mounted()) {
|
||||
return rdv40_spiffs_unmount();
|
||||
}
|
||||
return rdv40_spiffs_mount();
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -410,15 +433,41 @@ int rdv40_spiffs_lazy_mount_rollback(int changed) {
|
|||
// statement or some function taking function parameters
|
||||
// TODO : forbid writing to a filename which already exists as lnk !
|
||||
// TODO : forbid writing to a filename.lnk which already exists without lnk !
|
||||
// Note: Writing in SPIFFS_WRITE_CHUNK_SIZE (8192) byte chucks helps to ensure "free space" has been erased by GC (Garbage collection)
|
||||
int rdv40_spiffs_write(const char *filename, uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level) {
|
||||
RDV40_SPIFFS_SAFE_FUNCTION(
|
||||
write_to_spiffs(filename, src, size);
|
||||
uint32_t idx;
|
||||
if (size <= SPIFFS_WRITE_CHUNK_SIZE) {
|
||||
// write small file
|
||||
write_to_spiffs(filename, src, size);
|
||||
size = 0;
|
||||
} else { //
|
||||
// write first SPIFFS_WRITE_CHUNK_SIZE bytes
|
||||
// need to write the first chuck of data, then append
|
||||
write_to_spiffs(filename, src, SPIFFS_WRITE_CHUNK_SIZE);
|
||||
}
|
||||
// append remaing SPIFFS_WRITE_CHUNK_SIZE byte chuncks
|
||||
for (idx = 1; idx < (size / SPIFFS_WRITE_CHUNK_SIZE); idx++) {
|
||||
append_to_spiffs(filename, &src[SPIFFS_WRITE_CHUNK_SIZE * idx], SPIFFS_WRITE_CHUNK_SIZE);
|
||||
}
|
||||
// append remaing bytes
|
||||
if (((int64_t)size - (SPIFFS_WRITE_CHUNK_SIZE * idx)) > 0) {
|
||||
append_to_spiffs(filename, &src[SPIFFS_WRITE_CHUNK_SIZE * idx], size - (SPIFFS_WRITE_CHUNK_SIZE * idx));
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
int rdv40_spiffs_append(const char *filename, uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level) {
|
||||
RDV40_SPIFFS_SAFE_FUNCTION(
|
||||
append_to_spiffs(filename, src, size);
|
||||
uint32_t idx;
|
||||
// Append any SPIFFS_WRITE_CHUNK_SIZE byte chunks
|
||||
for (idx = 0; idx < (size / SPIFFS_WRITE_CHUNK_SIZE); idx++) {
|
||||
append_to_spiffs(filename, &src[SPIFFS_WRITE_CHUNK_SIZE * idx], SPIFFS_WRITE_CHUNK_SIZE);
|
||||
}
|
||||
// Append remain bytes
|
||||
if (((int64_t)size - (SPIFFS_WRITE_CHUNK_SIZE * idx)) > 0) {
|
||||
append_to_spiffs(filename, &src[SPIFFS_WRITE_CHUNK_SIZE * idx], size - (SPIFFS_WRITE_CHUNK_SIZE * idx));
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -433,24 +482,24 @@ int rdv40_spiffs_read(const char *filename, uint8_t *dst, uint32_t size, RDV40Sp
|
|||
// TODO : forbid writing to a filename.lnk which already exists without lnk !
|
||||
int rdv40_spiffs_rename(char *old_filename, char *new_filename, RDV40SpiFFSSafetyLevel level) {
|
||||
RDV40_SPIFFS_SAFE_FUNCTION( //
|
||||
rename_in_spiffs((char *)old_filename, (char *)new_filename); //
|
||||
rename_in_spiffs(old_filename, new_filename); //
|
||||
)
|
||||
}
|
||||
int rdv40_spiffs_remove(char *filename, RDV40SpiFFSSafetyLevel level) {
|
||||
RDV40_SPIFFS_SAFE_FUNCTION( //
|
||||
remove_from_spiffs((char *)filename); //
|
||||
remove_from_spiffs(filename); //
|
||||
)
|
||||
}
|
||||
|
||||
int rdv40_spiffs_copy(char *src, char *dst, RDV40SpiFFSSafetyLevel level) {
|
||||
RDV40_SPIFFS_SAFE_FUNCTION( //
|
||||
copy_in_spiffs((char *)src, (char *)dst); //
|
||||
copy_in_spiffs(src, dst); //
|
||||
)
|
||||
}
|
||||
|
||||
int rdv40_spiffs_stat(char *filename, uint32_t *buf, RDV40SpiFFSSafetyLevel level) {
|
||||
RDV40_SPIFFS_SAFE_FUNCTION( //
|
||||
*buf = size_in_spiffs((char *)filename); //
|
||||
*buf = size_in_spiffs(filename); //
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -489,12 +538,12 @@ int rdv40_spiffs_read_as_symlink(char *filename, uint8_t *dst, uint32_t size, RD
|
|||
sprintf(linkfilename, "%s.lnk", filename);
|
||||
|
||||
if (g_dbglevel >= DBG_DEBUG)
|
||||
Dbprintf("Linkk real filename is : " _YELLOW_("%s"), linkfilename);
|
||||
Dbprintf("Linkk real filename is " _YELLOW_("%s"), linkfilename);
|
||||
|
||||
read_from_spiffs((char *)linkfilename, (uint8_t *)linkdest, SPIFFS_OBJ_NAME_LEN);
|
||||
|
||||
if (g_dbglevel >= DBG_DEBUG)
|
||||
Dbprintf("Symlink destination is : " _YELLOW_("%s"), linkdest);
|
||||
Dbprintf("Symlink destination is " _YELLOW_("%s"), linkdest);
|
||||
|
||||
read_from_spiffs((char *)linkdest, (uint8_t *)dst, size);
|
||||
)
|
||||
|
@ -534,12 +583,12 @@ int rdv40_spiffs_read_as_filetype(char *filename, uint8_t *dst, uint32_t size, R
|
|||
rdv40_spiffs_read((char *)filename, (uint8_t *)dst, size, level);
|
||||
break;
|
||||
case RDV40_SPIFFS_FILETYPE_SYMLINK:
|
||||
rdv40_spiffs_read_as_symlink((char *)filename, (uint8_t *)dst, size, level);
|
||||
rdv40_spiffs_read_as_symlink(filename, (uint8_t *)dst, size, level);
|
||||
break;
|
||||
case RDV40_SPIFFS_FILETYPE_BOTH:
|
||||
case RDV40_SPIFFS_FILETYPE_UNKNOWN:
|
||||
default:
|
||||
;
|
||||
break;
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -559,18 +608,20 @@ void rdv40_spiffs_safe_print_fsinfo(void) {
|
|||
rdv40_spiffs_fsinfo fsinfo;
|
||||
rdv40_spiffs_getfsinfo(&fsinfo, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
|
||||
Dbprintf(" Logical block size......... " _YELLOW_("%d")" bytes", fsinfo.blockSize);
|
||||
Dbprintf(" Logical page size.......... " _YELLOW_("%d")" bytes", fsinfo.pageSize);
|
||||
Dbprintf(" Max open files............. " _YELLOW_("%d")" file descriptors", fsinfo.maxOpenFiles);
|
||||
Dbprintf(" Max path length............ " _YELLOW_("%d")" chars", fsinfo.maxPathLength);
|
||||
Dbprintf(" Logical block size... " _YELLOW_("%d")" bytes", fsinfo.blockSize);
|
||||
Dbprintf(" Logical page size.... " _YELLOW_("%d")" bytes", fsinfo.pageSize);
|
||||
Dbprintf(" Max open files....... " _YELLOW_("%d")" file descriptors", fsinfo.maxOpenFiles);
|
||||
Dbprintf(" Max path length...... " _YELLOW_("%d")" chars", fsinfo.maxPathLength);
|
||||
DbpString("");
|
||||
Dbprintf(" Filesystem size used available use% mounted");
|
||||
DbpString("------------------------------------------------------------------");
|
||||
Dbprintf(" spiffs %6d B %6d B %6d B " _YELLOW_("%2d%")" /"
|
||||
, fsinfo.totalBytes
|
||||
, fsinfo.usedBytes
|
||||
, fsinfo.freeBytes
|
||||
, fsinfo.usedPercent
|
||||
);
|
||||
DbpString("");
|
||||
}
|
||||
|
||||
// this function is safe and WILL rollback since it is only a PRINTING function,
|
||||
|
|
|
@ -24,7 +24,11 @@ extern "C" {
|
|||
|
||||
#include "spiffs_config.h"
|
||||
|
||||
typedef enum spiffs_safety_level { RDV40_SPIFFS_SAFETY_NORMAL, RDV40_SPIFFS_SAFETY_LAZY, RDV40_SPIFFS_SAFETY_SAFE } RDV40SpiFFSSafetyLevel;
|
||||
typedef enum spiffs_safety_level {
|
||||
RDV40_SPIFFS_SAFETY_NORMAL,
|
||||
RDV40_SPIFFS_SAFETY_LAZY,
|
||||
RDV40_SPIFFS_SAFETY_SAFE
|
||||
} RDV40SpiFFSSafetyLevel;
|
||||
|
||||
typedef enum spiffs_file_type {
|
||||
RDV40_SPIFFS_FILETYPE_REAL,
|
||||
|
@ -125,6 +129,8 @@ void rdv40_spiffs_safe_wipe(void);
|
|||
|
||||
#define SPIFFS_ERR_TEST -10100
|
||||
|
||||
// Amount of data to write/append to a file in one go.
|
||||
#define SPIFFS_WRITE_CHUNK_SIZE 8192
|
||||
|
||||
// spiffs file descriptor index type. must be signed
|
||||
typedef s16_t spiffs_file;
|
||||
|
@ -198,16 +204,16 @@ typedef void (*spiffs_file_callback)(struct spiffs_t *fs, spiffs_fileop_type op,
|
|||
|
||||
#ifndef SPIFFS_DBG
|
||||
#define SPIFFS_DBG(...) \
|
||||
printf(__VA_ARGS__)
|
||||
Dbprintf(__VA_ARGS__)
|
||||
#endif
|
||||
#ifndef SPIFFS_GC_DBG
|
||||
#define SPIFFS_GC_DBG(...) printf(__VA_ARGS__)
|
||||
#define SPIFFS_GC_DBG(...) Dbprintf(__VA_ARGS__)
|
||||
#endif
|
||||
#ifndef SPIFFS_CACHE_DBG
|
||||
#define SPIFFS_CACHE_DBG(...) printf(__VA_ARGS__)
|
||||
#define SPIFFS_CACHE_DBG(...) Dbprintf(__VA_ARGS__)
|
||||
#endif
|
||||
#ifndef SPIFFS_CHECK_DBG
|
||||
#define SPIFFS_CHECK_DBG(...) printf(__VA_ARGS__)
|
||||
#define SPIFFS_CHECK_DBG(...) Dbprintf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/* Any write to the filehandle is appended to end of the file */
|
||||
|
|
|
@ -136,7 +136,7 @@ typedef uint8_t u8_t;
|
|||
|
||||
// Define maximum number of gc runs to perform to reach desired free pages.
|
||||
#ifndef SPIFFS_GC_MAX_RUNS
|
||||
#define SPIFFS_GC_MAX_RUNS 5
|
||||
#define SPIFFS_GC_MAX_RUNS 10
|
||||
#endif
|
||||
|
||||
// Enable/disable statistics on gc. Debug/test purpose only.
|
||||
|
@ -236,7 +236,7 @@ typedef uint8_t u8_t;
|
|||
// Instead of giving parameters in config struct, singleton build must
|
||||
// give parameters in defines below.
|
||||
#ifndef SPIFFS_CFG_PHYS_SZ
|
||||
#define SPIFFS_CFG_PHYS_SZ(ignore) (1024*128)
|
||||
#define SPIFFS_CFG_PHYS_SZ(ignore) (1024*192)
|
||||
#endif
|
||||
#ifndef SPIFFS_CFG_PHYS_ERASE_SZ
|
||||
#define SPIFFS_CFG_PHYS_ERASE_SZ(ignore) (4*1024)
|
||||
|
|
|
@ -34,11 +34,17 @@ VERSIONSRC = version_pm3.c
|
|||
# THUMBSRC :=
|
||||
|
||||
# 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
|
||||
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
|
||||
include ../common_arm/Makefile.common
|
||||
|
@ -48,7 +54,7 @@ INSTALLFW = $(OBJDIR)/bootrom.elf
|
|||
OBJS = $(OBJDIR)/bootrom.s19
|
||||
|
||||
# version_pm3.c should be remade on every compilation
|
||||
version_pm3.c: default_version_pm3.c
|
||||
version_pm3.c: default_version_pm3.c .FORCE
|
||||
$(info [=] GEN $@)
|
||||
$(Q)$(SH) ../tools/mkversion.sh > $@ || $(PERL) ../tools/mkversion.pl > $@ || $(CP) $< $@
|
||||
|
||||
|
@ -82,7 +88,7 @@ uninstall:
|
|||
$(info [@] Uninstalling bootrom from $(DESTDIR)$(PREFIX)...)
|
||||
$(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:
|
||||
@echo Multi-OS Makefile, you are running on $(DETECTED_OS)
|
||||
@echo Possible targets:
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
#include "clocks.h"
|
||||
#include "usb_cdc.h"
|
||||
|
||||
#ifdef WITH_FLASH
|
||||
#include "flashmem.h"
|
||||
#endif
|
||||
|
||||
#include "proxmark3_arm.h"
|
||||
#define DEBUG 0
|
||||
|
||||
|
@ -214,8 +218,18 @@ static void flash_mode(void) {
|
|||
bootrom_unlocked = false;
|
||||
uint8_t rx[sizeof(PacketCommandOLD)];
|
||||
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;
|
||||
}
|
||||
|
||||
#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();
|
||||
|
||||
|
@ -296,10 +310,10 @@ void BootROM(void) {
|
|||
LED_B_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);
|
||||
|
||||
// 9 = 256, 10+ is 512kb
|
||||
// 9 = 256, 10+ is 512KB
|
||||
uint8_t id = (*(AT91C_DBGU_CIDR) & 0xF00) >> 8;
|
||||
if (id > 9)
|
||||
AT91C_BASE_EFC1->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48);
|
||||
|
|
|
@ -53,6 +53,7 @@ SECTIONS
|
|||
*(.rodata.*)
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.ramfunc)
|
||||
. = ALIGN(4);
|
||||
} >ram AT>bootphase2 :phase2
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ if (NOT SKIPREADLINE EQUAL 1)
|
|||
ExternalProject_Add_StepTargets(ncurses configure build install)
|
||||
|
||||
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
|
||||
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
|
||||
|
@ -163,11 +163,12 @@ endif (NOT SKIPJANSSONSYSTEM EQUAL 1)
|
|||
|
||||
if(EMBED_BZIP2)
|
||||
set(BZIP2_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/bzip2/src/bzip2)
|
||||
# Specify SOURCE_DIR will cause some errors
|
||||
ExternalProject_Add(bzip2
|
||||
GIT_REPOSITORY https://android.googlesource.com/platform/external/bzip2
|
||||
GIT_TAG platform-tools-30.0.2
|
||||
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
|
||||
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
|
||||
|
@ -275,6 +276,7 @@ set (TARGET_SOURCES
|
|||
${PM3_ROOT}/client/src/cmdhfepa.c
|
||||
${PM3_ROOT}/client/src/cmdhffelica.c
|
||||
${PM3_ROOT}/client/src/cmdhffido.c
|
||||
${PM3_ROOT}/client/src/cmdhffudan.c
|
||||
${PM3_ROOT}/client/src/cmdhfgallagher.c
|
||||
${PM3_ROOT}/client/src/cmdhfcipurse.c
|
||||
${PM3_ROOT}/client/src/cmdhficlass.c
|
||||
|
@ -292,9 +294,12 @@ set (TARGET_SOURCES
|
|||
${PM3_ROOT}/client/src/cmdhfseos.c
|
||||
${PM3_ROOT}/client/src/cmdhfst.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/cmdhftopaz.c
|
||||
${PM3_ROOT}/client/src/cmdhfwaveshare.c
|
||||
${PM3_ROOT}/client/src/cmdhfxerox.c
|
||||
${PM3_ROOT}/client/src/cmdhw.c
|
||||
${PM3_ROOT}/client/src/cmdlf.c
|
||||
${PM3_ROOT}/client/src/cmdlfawid.c
|
||||
|
@ -333,6 +338,7 @@ set (TARGET_SOURCES
|
|||
${PM3_ROOT}/client/src/cmdmain.c
|
||||
${PM3_ROOT}/client/src/cmdnfc.c
|
||||
${PM3_ROOT}/client/src/cmdparser.c
|
||||
${PM3_ROOT}/client/src/cmdpiv.c
|
||||
${PM3_ROOT}/client/src/cmdscript.c
|
||||
${PM3_ROOT}/client/src/cmdsmartcard.c
|
||||
${PM3_ROOT}/client/src/cmdtrace.c
|
||||
|
@ -579,6 +585,9 @@ if (MINGW)
|
|||
|
||||
set(CMAKE_C_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_CXX_FLAGS}")
|
||||
|
||||
# link Winsock2
|
||||
set(ADDITIONAL_LNK ws2_32 ${ADDITIONAL_LNK})
|
||||
endif (MINGW)
|
||||
|
||||
target_include_directories(proxmark3 PRIVATE
|
||||
|
|
|
@ -37,8 +37,7 @@ OBJDIR = obj
|
|||
ifeq ($(USE_BREW),1)
|
||||
INCLUDES += -I$(BREW_PREFIX)/include
|
||||
LDLIBS += -L$(BREW_PREFIX)/lib
|
||||
PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(BREW_PREFIX)/opt/qt/lib/pkgconfig
|
||||
PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(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
|
||||
|
||||
ifdef ($(USE_MACPORTS),1)
|
||||
|
@ -94,7 +93,6 @@ LUALIBLD =
|
|||
LUAPLATFORM = generic
|
||||
ifneq (,$(findstring MINGW,$(platform)))
|
||||
LUAPLATFORM = mingw
|
||||
LDLIBS += -lws2_32
|
||||
else
|
||||
ifeq ($(platform),Darwin)
|
||||
LUAPLATFORM = macosx
|
||||
|
@ -104,6 +102,11 @@ else
|
|||
endif
|
||||
endif
|
||||
|
||||
## Winsock2
|
||||
ifneq (,$(findstring MINGW,$(platform)))
|
||||
LDLIBS += -lws2_32
|
||||
endif
|
||||
|
||||
## Reveng
|
||||
REVENGLIBPATH = ./deps/reveng
|
||||
REVENGLIBINC = -I$(REVENGLIBPATH)
|
||||
|
@ -290,6 +293,7 @@ ifneq ($(SKIPQT),1)
|
|||
QTLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs Qt5Core Qt5Widgets 2>/dev/null)
|
||||
MOC = $(shell $(PKG_CONFIG_ENV) pkg-config --variable=host_bins Qt5Core)/moc
|
||||
UIC = $(shell $(PKG_CONFIG_ENV) pkg-config --variable=host_bins Qt5Core)/uic
|
||||
QMAKE = $(shell $(PKG_CONFIG_ENV) pkg-config --variable=host_bins Qt5Core)/qmake
|
||||
ifneq ($(QTLDLIBS),)
|
||||
QT5_FOUND = 1
|
||||
else
|
||||
|
@ -298,6 +302,7 @@ ifneq ($(SKIPQT),1)
|
|||
QTLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs QtCore QtGui 2>/dev/null)
|
||||
MOC = $(shell $(PKG_CONFIG_ENV) pkg-config --variable=moc_location QtCore)
|
||||
UIC = $(shell $(PKG_CONFIG_ENV) pkg-config --variable=uic_location QtCore)
|
||||
QMAKE = $(shell $(PKG_CONFIG_ENV) pkg-config --variable=exec_prefix QtCore)/bin/qmake
|
||||
endif
|
||||
ifeq ($(QTLDLIBS),)
|
||||
# if both pkg-config commands failed, search in common places
|
||||
|
@ -314,6 +319,7 @@ ifneq ($(SKIPQT),1)
|
|||
endif
|
||||
MOC = $(QTDIR)/bin/moc
|
||||
UIC = $(QTDIR)/bin/uic
|
||||
QMAKE = $(QTDIR)/bin/qmake
|
||||
endif
|
||||
endif
|
||||
ifneq ($(QTLDLIBS),)
|
||||
|
@ -363,9 +369,11 @@ endif
|
|||
|
||||
#######################################################################################################
|
||||
CFLAGS ?= $(DEFCFLAGS)
|
||||
CFLAGS += $(MYDEFS) $(MYCFLAGS) $(MYINCLUDES)
|
||||
|
||||
# We cannot just use CFLAGS+=... because it has impact on sub-makes if CFLAGS is defined in env:
|
||||
PM3CFLAGS = $(CFLAGS)
|
||||
PM3CFLAGS += -I./src -I./include -I../include -I../common -I../common_fpga $(PM3INCLUDES) $(INCLUDES)
|
||||
PM3CFLAGS += -g -I./src -I./include -I../include -I../common -I../common_fpga $(PM3INCLUDES) $(INCLUDES)
|
||||
# WIP Testing
|
||||
#PM3CFLAGS += -std=c11 -pedantic
|
||||
|
||||
|
@ -405,6 +413,8 @@ endif
|
|||
PM3CFLAGS += -DHAVE_SNPRINTF
|
||||
|
||||
CXXFLAGS ?= -Wall -Werror -O3
|
||||
CXXFLAGS += $(MYDEFS) $(MYCXXFLAGS) $(MYINCLUDES)
|
||||
|
||||
PM3CXXFLAGS = $(CXXFLAGS)
|
||||
PM3CXXFLAGS += -I../include -I./include
|
||||
|
||||
|
@ -420,6 +430,8 @@ endif
|
|||
PM3CXXFLAGS += -DHAVE_SNPRINTF
|
||||
|
||||
LDFLAGS ?= $(DEFLDFLAGS)
|
||||
LDFLAGS += $(MYLDFLAGS)
|
||||
|
||||
PM3LDFLAGS = $(LDFLAGS)
|
||||
ifeq ($(platform),Darwin)
|
||||
PM3LDFLAGS += -framework Foundation -framework AppKit
|
||||
|
@ -438,9 +450,9 @@ ifeq ($(SKIPQT),1)
|
|||
else
|
||||
ifeq ($(QT_FOUND),1)
|
||||
ifeq ($(QT5_FOUND),1)
|
||||
$(info GUI support: QT5 found, enabled ($(shell QT_SELECT=5 qmake -v 2>/dev/null|grep -o 'Qt version.*')))
|
||||
$(info GUI support: QT5 found, enabled ($(shell QT_SELECT=5 $(QMAKE) -v 2>/dev/null|grep -o 'Qt version.*')))
|
||||
else
|
||||
$(info GUI support: QT4 found, enabled ($(shell QT_SELECT=4 qmake -v 2>/dev/null|grep -o 'Qt version.*')))
|
||||
$(info GUI support: QT4 found, enabled ($(shell QT_SELECT=4 $(QMAKE) -v 2>/dev/null|grep -o 'Qt version.*')))
|
||||
endif
|
||||
else
|
||||
$(info GUI support: QT not found, disabled)
|
||||
|
@ -479,7 +491,7 @@ ifeq ($(SKIPPYTHON),1)
|
|||
$(info Python3 library: skipped)
|
||||
else
|
||||
ifeq ($(PYTHON_FOUND),1)
|
||||
$(info Python3 library: Python3 v$(shell pkg-config --modversion python3) found, enabled)
|
||||
$(info Python3 library: Python3 v$(shell $(PKG_CONFIG_ENV) pkg-config --modversion python3) found, enabled)
|
||||
else
|
||||
$(info Python3 library: Python3 not found, disabled)
|
||||
endif
|
||||
|
@ -557,6 +569,7 @@ SRCS = mifare/aiddesfire.c \
|
|||
cmdhfemrtd.c \
|
||||
cmdhffelica.c \
|
||||
cmdhffido.c \
|
||||
cmdhffudan.c \
|
||||
cmdhfgallagher.c \
|
||||
cmdhfksx6924.c \
|
||||
cmdhfcipurse.c \
|
||||
|
@ -574,9 +587,12 @@ SRCS = mifare/aiddesfire.c \
|
|||
cmdhfseos.c \
|
||||
cmdhfst.c \
|
||||
cmdhfst25ta.c \
|
||||
cmdhftesla.c \
|
||||
cmdhfthinfilm.c \
|
||||
cmdhftopaz.c \
|
||||
cmdhftexkom.c \
|
||||
cmdhfwaveshare.c \
|
||||
cmdhfxerox.c \
|
||||
cmdhw.c \
|
||||
cmdlf.c \
|
||||
cmdlfawid.c \
|
||||
|
@ -615,6 +631,7 @@ SRCS = mifare/aiddesfire.c \
|
|||
cmdmain.c \
|
||||
cmdnfc.c \
|
||||
cmdparser.c \
|
||||
cmdpiv.c \
|
||||
cmdscript.c \
|
||||
cmdsmartcard.c \
|
||||
cmdtrace.c \
|
||||
|
@ -747,8 +764,9 @@ all-static: LDLIBS:=-static $(LDLIBS)
|
|||
all-static: $(BINS)
|
||||
|
||||
proxmark3: $(OBJS) $(STATICLIBS) lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua
|
||||
$(info [=] LD $@)
|
||||
$(Q)$(LD) $(PM3LDFLAGS) $(OBJS) $(STATICLIBS) $(LDLIBS) -o $@
|
||||
$(info [=] CXX $@)
|
||||
# $(Q)$(CXX) $(PM3LDFLAGS) $(OBJS) $(STATICLIBS) $(LDLIBS) -o $@
|
||||
$(Q)$(CXX) $(PM3CFLAGS) $(PM3LDFLAGS) $(OBJS) $(STATICLIBS) $(LDLIBS) -o $@
|
||||
|
||||
src/proxgui.cpp: src/ui/ui_overlays.h src/ui/ui_image.h
|
||||
|
||||
|
|
|
@ -11,10 +11,10 @@
|
|||
#include "cliparser.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <util.h> // Get color constants
|
||||
#include <ui.h> // get PrintAndLogEx
|
||||
#include <ctype.h> // tolower
|
||||
#include <inttypes.h> // PRIu64
|
||||
#include <util.h> // color constants
|
||||
#include <ui.h> // PrintAndLogEx
|
||||
#include <ctype.h> // tolower
|
||||
#include <inttypes.h> // PRIu64
|
||||
|
||||
#ifndef ARRAYLEN
|
||||
# define ARRAYLEN(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
@ -22,10 +22,10 @@
|
|||
|
||||
// Custom Colors
|
||||
// To default the color return s
|
||||
#define _SectionTagColor_(s) _GREEN_(s)
|
||||
#define _ExampleColor_(s) _YELLOW_(s)
|
||||
#define _CommandColor_(s) _RED_(s)
|
||||
#define _DescriptionColor_(s) _CYAN_(s)
|
||||
#define _SectionTagColor_(s) _GREEN_(s)
|
||||
#define _ExampleColor_(s) _YELLOW_(s)
|
||||
#define _CommandColor_(s) _RED_(s)
|
||||
#define _DescriptionColor_(s) _CYAN_(s)
|
||||
#define _ArgColor_(s) s
|
||||
#define _ArgHelpColor_(s) s
|
||||
// End Custom Colors
|
||||
|
@ -33,66 +33,79 @@
|
|||
// Example width set to 50 to allow help descriptions to align. approx line 93
|
||||
|
||||
int CLIParserInit(CLIParserContext **ctx, const char *vprogramName, const char *vprogramHint, const char *vprogramHelp) {
|
||||
*ctx = malloc(sizeof(CLIParserContext));
|
||||
if (!*ctx) {
|
||||
*ctx = calloc(sizeof(CLIParserContext), sizeof(uint8_t));
|
||||
if (*ctx == NULL) {
|
||||
PrintAndLogEx(ERR, "ERROR: Insufficient memory\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
(*ctx)->argtable = NULL;
|
||||
(*ctx)->argtableLen = 0;
|
||||
(*ctx)->programName = vprogramName;
|
||||
(*ctx)->programHint = vprogramHint;
|
||||
(*ctx)->programHelp = vprogramHelp;
|
||||
memset((*ctx)->buf, 0x00, sizeof((*ctx)->buf));
|
||||
return 0;
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
void CLIParserPrintHelp(CLIParserContext *ctx) {
|
||||
if (ctx->programHint)
|
||||
if (ctx->programHint) {
|
||||
PrintAndLogEx(NORMAL, "\n"_DescriptionColor_("%s"), ctx->programHint);
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "\n"_SectionTagColor_("usage:"));
|
||||
PrintAndLogEx(NORMAL, " "_CommandColor_("%s")NOLF, ctx->programName);
|
||||
arg_print_syntax(stdout, ctx->argtable, "\n\n");
|
||||
|
||||
PrintAndLogEx(NORMAL, _SectionTagColor_("options:"));
|
||||
|
||||
arg_print_glossary(stdout, ctx->argtable, " "_ArgColor_("%-30s")" "_ArgHelpColor_("%s")"\n");
|
||||
|
||||
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;
|
||||
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)) {
|
||||
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) {
|
||||
*(p2 - 1) = 0x00;
|
||||
|
||||
if (strlen(buf) > 28)
|
||||
egWidth = strlen(buf) + 5;
|
||||
if (strlen(s) > 28)
|
||||
egWidth = strlen(s) + 5;
|
||||
else
|
||||
egWidth = 30;
|
||||
|
||||
PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s")" %s", egWidth, buf, p2);
|
||||
PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s")" %s", egWidth, s, p2);
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s"), egWidth, buf);
|
||||
PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s"), egWidth, s);
|
||||
}
|
||||
|
||||
idx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
free(s);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
free(buf);
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
@ -127,7 +140,7 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta
|
|||
return 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
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 argc = 0;
|
||||
char *argv[200] = {NULL};
|
||||
char *argv[MAX_INPUT_ARG_LENGTH] = {NULL};
|
||||
|
||||
int len = strlen(str);
|
||||
|
||||
memset(ctx->buf, 0x00, ARRAYLEN(ctx->buf));
|
||||
|
||||
char *bufptr = ctx->buf;
|
||||
char *bufptrend = ctx->buf + ARRAYLEN(ctx->buf) - 1;
|
||||
char *spaceptr = NULL;
|
||||
enum ParserState state = PS_FIRST;
|
||||
|
||||
argv[argc++] = bufptr;
|
||||
// param0 = program name
|
||||
memcpy(ctx->buf, ctx->programName, strlen(ctx->programName) + 1); // with 0x00
|
||||
// param0 = program name + with 0x00
|
||||
memcpy(ctx->buf, ctx->programName, strlen(ctx->programName) + 1);
|
||||
|
||||
bufptr += strlen(ctx->programName) + 1;
|
||||
if (len)
|
||||
if (len) {
|
||||
argv[argc++] = bufptr;
|
||||
}
|
||||
|
||||
// parse params
|
||||
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;
|
||||
|
||||
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[]
|
||||
//
|
||||
int res = CLIParamStrToBuf(argstr, tmpstr, sizeof(tmpstr), &tmplen);
|
||||
if (res || (tmplen == 0)) {
|
||||
return res;
|
||||
|
@ -242,7 +258,7 @@ int CLIParamBinToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
|
|||
*datalen = 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[]
|
||||
//
|
||||
|
@ -268,7 +284,7 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
|
|||
if (!argstr->count)
|
||||
return 0;
|
||||
|
||||
uint8_t tmpstr[(512 * 2) + 1] = {0};
|
||||
uint8_t tmpstr[MAX_INPUT_ARG_LENGTH + 1] = {0};
|
||||
int ibuf = 0;
|
||||
|
||||
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) {
|
||||
char data[200] = {0};
|
||||
int datalen = 0;
|
||||
int datalen = 200;
|
||||
int res = CLIParamStrToBuf(argstr, (uint8_t *)data, sizeof(data), &datalen);
|
||||
if (res)
|
||||
return res;
|
||||
|
@ -316,7 +332,7 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array
|
|||
|
||||
int val = -1;
|
||||
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
|
||||
if (strcmp(option_array[i].text, data) == 0) {
|
||||
*value = option_array[i].code;
|
||||
|
@ -346,9 +362,10 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array
|
|||
const char *CLIGetOptionListStr(const CLIParserOption *option_array, int value) {
|
||||
static const char *errmsg = "n/a";
|
||||
|
||||
for (int i = 0; i < CLI_MAX_OPTLIST_LEN && option_array[i].text != NULL; i++) {
|
||||
if (option_array[i].code == value)
|
||||
for (int i = 0; (i < CLI_MAX_OPTLIST_LEN) && (option_array[i].text != NULL); i++) {
|
||||
if (option_array[i].code == value) {
|
||||
return option_array[i].text;
|
||||
}
|
||||
}
|
||||
return errmsg;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#define __CLIPARSER_H
|
||||
#include "argtable3.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "util.h"
|
||||
|
||||
#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 MAX_INPUT_ARG_LENGTH 4096
|
||||
|
||||
|
||||
typedef struct {
|
||||
void **argtable;
|
||||
size_t argtableLen;
|
||||
const char *programName;
|
||||
const char *programHint;
|
||||
const char *programHelp;
|
||||
char buf[1024 + 60];
|
||||
char buf[MAX_INPUT_ARG_LENGTH + 60];
|
||||
} CLIParserContext;
|
||||
|
||||
#define CLI_MAX_OPTLIST_LEN 50
|
||||
|
|
|
@ -17,7 +17,7 @@ target_compile_definitions(pm3rrg_rdv4_hardnested_nosimd PRIVATE NOSIMD_BUILD)
|
|||
## Mingw platforms: AMD64
|
||||
set(X86_CPUS x86 x86_64 i686 AMD64)
|
||||
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}")
|
||||
|
||||
|
|
|
@ -163,7 +163,8 @@ static void *malloc_bitslice(size_t x) {
|
|||
}
|
||||
#define free_bitslice(x) free(x)
|
||||
#else
|
||||
#define malloc_bitslice(x) memalign(MAX_BITSLICES / 8, (x))
|
||||
//#define malloc_bitslice(x) memalign(MAX_BITSLICES / 8, (x))
|
||||
#define malloc_bitslice(x) __builtin_assume_aligned(memalign(MAX_BITSLICES / 8, (x)), MAX_BITSLICES / 8);
|
||||
#define free_bitslice(x) free(x)
|
||||
#endif
|
||||
|
||||
|
@ -529,7 +530,6 @@ stop_tests:
|
|||
bucket_states_tested += bucket_size[block_idx];
|
||||
// prepare to set new states
|
||||
state_p = &states[KEYSTREAM_SIZE];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
out:
|
||||
|
|
|
@ -85,7 +85,8 @@ static void *malloc_bitarray(size_t x) {
|
|||
}
|
||||
#define free_bitarray(x) free(x)
|
||||
#else
|
||||
#define malloc_bitarray(x) memalign(__BIGGEST_ALIGNMENT__, (x))
|
||||
//#define malloc_bitarray(x) memalign(__BIGGEST_ALIGNMENT__, (x))
|
||||
#define malloc_bitarray(x) __builtin_assume_aligned(memalign(__BIGGEST_ALIGNMENT__, (x)), __BIGGEST_ALIGNMENT__);
|
||||
#define free_bitarray(x) free(x)
|
||||
#endif
|
||||
|
||||
|
|
|
@ -10,3 +10,4 @@
|
|||
25293C2F
|
||||
#
|
||||
# Paxton HT2
|
||||
BDF5E846
|
||||
|
|
|
@ -10,7 +10,32 @@ AEA684A6DAB23278 # AA1
|
|||
F0E1D2C3B4A59687 # Kd from PicoPass 2k documentation
|
||||
5CBCF1DA45D5FB4F # PicoPass Default Exchange Key
|
||||
31ad7ebd2f282168 # From HID multiclassSE reader
|
||||
6EFD46EFCBB3C875 # From pastebin: https://pastebin.com/uHqpjiuU
|
||||
E033CA419AEE43F9 # From pastebin: https://pastebin.com/uHqpjiuU
|
||||
2020666666668888 # iCopy-X iCL tags
|
||||
6666202066668888 # iCopy-X iCS tags reversed from the SOs
|
||||
#
|
||||
# From pastebin: https://pastebin.com/uHqpjiuU
|
||||
6EFD46EFCBB3C875
|
||||
E033CA419AEE43F9
|
||||
#
|
||||
# iCopy-x DRM keys
|
||||
2020666666668888 # iCL tags
|
||||
6666202066668888 # iCS tags reversed from the SOs
|
||||
#
|
||||
# default picopass KD / Page 0 / Book 1
|
||||
FDCB5A52EA8F3090
|
||||
237FF9079863DF44
|
||||
5ADC25FB27181D32
|
||||
83B881F2936B2E49
|
||||
43644E61EE866BA5
|
||||
897034143D016080
|
||||
82D17B44C0122963
|
||||
4895CA7DE65E2025
|
||||
DADAD4C57BE271B7
|
||||
E41E9EDEF5719ABF
|
||||
293D275EC3AF9C7F
|
||||
C3C169251B8A70FB
|
||||
F41DAF58B20C8B91
|
||||
28877A609EC0DD2B
|
||||
66584C91EE80D5E5
|
||||
C1B74D7478053AE2
|
||||
#
|
||||
# default iCLASS RFIDeas
|
||||
6B65797374726B72
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -10,6 +10,7 @@
|
|||
# blue gun EM4305
|
||||
F9DCEBA0
|
||||
# chinese "handheld RFID writer" blue cloner from circa 2013 (also sold by xfpga.com)
|
||||
# ID/HID CARD COPER SK-663
|
||||
65857569
|
||||
# ref. http://kazus.ru/forums/showpost.php?p=1045937&postcount=77
|
||||
05D73B9F
|
||||
|
@ -25,6 +26,8 @@ A5B4C3D2
|
|||
1C0B5848
|
||||
# ref. http://www.proxmark.org/forum/viewtopic.php?pid=35075#p35075
|
||||
00434343
|
||||
# default PASS
|
||||
50415353
|
||||
# DNGR - DT default pwd
|
||||
444E4752
|
||||
4E457854
|
||||
|
@ -38,8 +41,6 @@ E9920427
|
|||
50520901
|
||||
# iCopy-X
|
||||
20206666
|
||||
# ID/HID CARD COPER SK-663
|
||||
65857569
|
||||
# password found on discord
|
||||
5469616E
|
||||
# wCopy NSR102-IDIC
|
||||
|
@ -49,8 +50,8 @@ C0F5009A
|
|||
07CEE75D
|
||||
#
|
||||
# prefered pwds of members in the community
|
||||
feedbeef
|
||||
deadc0de
|
||||
FEEDBEEF
|
||||
DEADC0DE
|
||||
# Default pwd, simple:
|
||||
00000000
|
||||
11111111
|
||||
|
@ -68,13 +69,12 @@ CCCCCCCC
|
|||
DDDDDDDD
|
||||
EEEEEEEE
|
||||
FFFFFFFF
|
||||
a0a1a2a3
|
||||
b0b1b2b3
|
||||
50415353
|
||||
A0A1A2A3
|
||||
B0B1B2B3
|
||||
00000001
|
||||
00000002
|
||||
0000000a
|
||||
0000000b
|
||||
0000000A
|
||||
0000000B
|
||||
01020304
|
||||
02030405
|
||||
03040506
|
||||
|
@ -118,8 +118,10 @@ F0000000
|
|||
AABBCCDD
|
||||
BBCCDDEE
|
||||
CCDDEEFF
|
||||
0CB7E7FC # rfidler?
|
||||
FABADA11 # china?
|
||||
# rfidler?
|
||||
0CB7E7FC
|
||||
# china?
|
||||
FABADA11
|
||||
# 20 most common len==8
|
||||
87654321
|
||||
12341234
|
||||
|
@ -130,23 +132,33 @@ FABADA11 # china?
|
|||
11112222
|
||||
13131313
|
||||
10041004
|
||||
# pii
|
||||
31415926
|
||||
#
|
||||
31415926 # pii
|
||||
abcd1234
|
||||
ABCD1234
|
||||
20002000
|
||||
19721972
|
||||
aa55aa55 # amiboo
|
||||
55aa55aa # rev amiboo
|
||||
4f271149 # seeds ul-ev1
|
||||
07d7bb0b # seeds ul-ev1
|
||||
9636ef8f # seeds ul-ev1
|
||||
b5f44686 # seeds ul-ev1
|
||||
9E3779B9 # TEA
|
||||
C6EF3720 # TEA
|
||||
7854794A # xbox tea constant :)
|
||||
F1EA5EED # burtle
|
||||
69314718 # ln2
|
||||
57721566 # euler constant (dec)
|
||||
93C467E3 # euler constant (hex)
|
||||
27182818 # natural log
|
||||
50415353 # PASS
|
||||
# rev amiboo
|
||||
AA55AA55
|
||||
55AA55AA
|
||||
# seeds ul-ev1
|
||||
4F271149
|
||||
07D7BB0B
|
||||
9636EF8F
|
||||
B5F44686
|
||||
# TEA
|
||||
9E3779B9
|
||||
C6EF3720
|
||||
#
|
||||
# xbox tea constant :)
|
||||
7854794A
|
||||
# burtle
|
||||
F1EA5EED
|
||||
# ln2
|
||||
69314718
|
||||
# euler constant (dec)
|
||||
57721566
|
||||
# euler constant (hex)
|
||||
93C467E3
|
||||
# natural log
|
||||
27182818
|
||||
|
|
|
@ -122,7 +122,7 @@ if (NOT SKIPREADLINE EQUAL 1)
|
|||
ExternalProject_Add_StepTargets(ncurses configure build install)
|
||||
|
||||
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
|
||||
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
|
||||
|
@ -276,6 +276,7 @@ set (TARGET_SOURCES
|
|||
${PM3_ROOT}/client/src/cmdhfepa.c
|
||||
${PM3_ROOT}/client/src/cmdhffelica.c
|
||||
${PM3_ROOT}/client/src/cmdhffido.c
|
||||
${PM3_ROOT}/client/src/cmdhffudan.c
|
||||
${PM3_ROOT}/client/src/cmdhfgallagher.c
|
||||
${PM3_ROOT}/client/src/cmdhfcipurse.c
|
||||
${PM3_ROOT}/client/src/cmdhficlass.c
|
||||
|
@ -293,9 +294,12 @@ set (TARGET_SOURCES
|
|||
${PM3_ROOT}/client/src/cmdhfseos.c
|
||||
${PM3_ROOT}/client/src/cmdhfst.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/cmdhftopaz.c
|
||||
${PM3_ROOT}/client/src/cmdhfwaveshare.c
|
||||
${PM3_ROOT}/client/src/cmdhfxerox.c
|
||||
${PM3_ROOT}/client/src/cmdhw.c
|
||||
${PM3_ROOT}/client/src/cmdlf.c
|
||||
${PM3_ROOT}/client/src/cmdlfawid.c
|
||||
|
@ -334,6 +338,7 @@ set (TARGET_SOURCES
|
|||
${PM3_ROOT}/client/src/cmdmain.c
|
||||
${PM3_ROOT}/client/src/cmdnfc.c
|
||||
${PM3_ROOT}/client/src/cmdparser.c
|
||||
${PM3_ROOT}/client/src/cmdpiv.c
|
||||
${PM3_ROOT}/client/src/cmdscript.c
|
||||
${PM3_ROOT}/client/src/cmdsmartcard.c
|
||||
${PM3_ROOT}/client/src/cmdtrace.c
|
||||
|
|
2648
client/lualibs/amiibo_tools.lua
Normal file
2648
client/lualibs/amiibo_tools.lua
Normal file
File diff suppressed because it is too large
Load diff
|
@ -62,7 +62,7 @@ function main(args)
|
|||
|
||||
local i
|
||||
local cmds = {}
|
||||
--check for params
|
||||
--check for params
|
||||
for o, a in getopt.getopt(args, 'h') do
|
||||
if o == 'h' then return help() end
|
||||
end
|
||||
|
|
310
client/luascripts/hf_i2c_plus_2k_utils.lua
Normal file
310
client/luascripts/hf_i2c_plus_2k_utils.lua
Normal file
|
@ -0,0 +1,310 @@
|
|||
local getopt = require('getopt')
|
||||
local lib14a = require('read14a')
|
||||
local cmds = require('commands')
|
||||
local utils = require('utils')
|
||||
local ansicolors = require('ansicolors')
|
||||
|
||||
--- Commands
|
||||
NTAG_I2C_PLUS_2K = '0004040502021503C859'
|
||||
GET_VERSION = '60'
|
||||
SELECT_SECTOR_PKT1 = 'C2FF'
|
||||
SELECT_SECTOR0_PKT2 = '00000000'
|
||||
SELECT_SECTOR1_PKT2 = '01000000'
|
||||
READ_BLOCK = '30'
|
||||
WRITE_BLOCK = 'A2'
|
||||
ACK = '0A'
|
||||
NAK = '00'
|
||||
---
|
||||
|
||||
|
||||
--- Arguments
|
||||
copyright = ''
|
||||
author = 'Shain Lakin'
|
||||
version = 'v1.0.0'
|
||||
desc =[[
|
||||
|
||||
This script can be used to read blocks, write blocks, dump sectors,
|
||||
or write a files hex bytes to sector 0 or 1 on the NTAG I2C PLUS 2K tag.
|
||||
|
||||
]]
|
||||
|
||||
example =[[
|
||||
|
||||
Read block 04 from sector 1:
|
||||
script run hf_i2c_plus_2k_utils -m r -s 1 -b 04
|
||||
|
||||
Write FFFFFFFF to block A0 sector 1:
|
||||
script run hf_i2c_plus_2k_utils -m w -s 1 -b A0 -d FFFFFFFF
|
||||
|
||||
Dump sector 1 user memory to console and file:
|
||||
script run hf_i2c_plus_2k_utils -m d -s 1
|
||||
|
||||
Write a files hex bytes to sector 1 starting at block 04:
|
||||
script run hf_i2c_plus_2k_utils -m f -s 1 -f data.txt
|
||||
|
||||
]]
|
||||
usage = [[
|
||||
|
||||
Read mode:
|
||||
script run hf_i2c_plus_2k_utils -m r -s <sector> -b <block (hex)>
|
||||
|
||||
Write mode:
|
||||
script run hf_i2c_plus_2k_utils -m w -s <sector> -b <block (hex)> -d <data (hex)>
|
||||
|
||||
Dump mode:
|
||||
script run hf_i2c_plus_2k_utils -m d -s <sector>
|
||||
|
||||
File mode:
|
||||
script run hf_i2c_plus_2k_utils -m f -s <sector> -f <file>
|
||||
|
||||
]]
|
||||
arguments = [[
|
||||
-h this help
|
||||
-m mode (r/w/f)
|
||||
-b block (hex)
|
||||
-f file
|
||||
-s sector (0/1)
|
||||
-d data (hex)
|
||||
]]
|
||||
---
|
||||
|
||||
|
||||
--- Help function
|
||||
local function help()
|
||||
|
||||
print(copyright)
|
||||
print(author)
|
||||
print(version)
|
||||
print(desc)
|
||||
print(ansicolors.cyan..'Usage'..ansicolors.reset)
|
||||
print(usage)
|
||||
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
|
||||
print(arguments)
|
||||
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
|
||||
print(example)
|
||||
|
||||
end
|
||||
---
|
||||
|
||||
|
||||
--- Message function
|
||||
local function msg(string)
|
||||
print(ansicolors.magenta..string.rep('-',29)..ansicolors.reset)
|
||||
print(ansicolors.cyan..string..ansicolors.reset)
|
||||
print(ansicolors.magenta..string.rep('-',29)..ansicolors.reset)
|
||||
end
|
||||
---
|
||||
|
||||
|
||||
--- Error handling
|
||||
local function warn(err)
|
||||
|
||||
print(ansicolors.magenta.."ERROR:"..ansicolors.reset,err)
|
||||
core.clearCommandBuffer()
|
||||
return nil, err
|
||||
|
||||
end
|
||||
---
|
||||
|
||||
|
||||
--- Setup tx/rx
|
||||
local function sendRaw(rawdata, options)
|
||||
|
||||
local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT
|
||||
+ lib14a.ISO14A_COMMAND.ISO14A_RAW
|
||||
+ lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC
|
||||
|
||||
local c = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER,
|
||||
arg1 = flags,
|
||||
arg2 = string.len(rawdata)/2,
|
||||
data = rawdata}
|
||||
|
||||
return c:sendMIX(options.ignore_response)
|
||||
end
|
||||
---
|
||||
|
||||
|
||||
--- Function to connect
|
||||
local function connect()
|
||||
core.clearCommandBuffer()
|
||||
|
||||
info, err = lib14a.read(true, true)
|
||||
if err then
|
||||
lib14a.disconnect()
|
||||
return error(err)
|
||||
else
|
||||
return info.uid
|
||||
end
|
||||
core.clearCommandBuffer()
|
||||
|
||||
end
|
||||
---
|
||||
|
||||
|
||||
--- Function to disconnect
|
||||
local function disconnect()
|
||||
core.clearCommandBuffer()
|
||||
lib14a.disconnect()
|
||||
end
|
||||
---
|
||||
|
||||
|
||||
--- Function to get response data
|
||||
local function getResponseData(usbpacket)
|
||||
|
||||
local resp = Command.parse(usbpacket)
|
||||
local len = tonumber(resp.arg1) * 2
|
||||
return string.sub(tostring(resp.data), 0, len);
|
||||
|
||||
end
|
||||
---
|
||||
|
||||
|
||||
--- Function to send raw bytes
|
||||
local function send(payload)
|
||||
|
||||
local usb, err = sendRaw(payload,{ignore_response = false})
|
||||
if err then return warn(err) end
|
||||
return getResponseData(usb)
|
||||
|
||||
end
|
||||
---
|
||||
|
||||
--- Function to select sector
|
||||
local function select_sector(sector)
|
||||
send(SELECT_SECTOR_PKT1)
|
||||
if sector == '0' then
|
||||
send(SELECT_SECTOR0_PKT2)
|
||||
elseif sector == '1' then
|
||||
send(SELECT_SECTOR1_PKT2)
|
||||
end
|
||||
end
|
||||
---
|
||||
|
||||
--- Function to write file to sector
|
||||
local function filewriter(file,sector)
|
||||
file_bytes = utils.ReadDumpFile(file)
|
||||
len = string.len(file_bytes) / 8
|
||||
start_char = 1
|
||||
end_char = 8
|
||||
block_counter = 4
|
||||
-- NTAG_I2C_PLUS_2K:SECTOR_0:225,SECTOR_1:255
|
||||
end_block = 225
|
||||
connect()
|
||||
select_sector(sector)
|
||||
for count = 1, len do
|
||||
block = file_bytes:sub(start_char, end_char)
|
||||
data = send(WRITE_BLOCK..string.format("%02x",block_counter)..block)
|
||||
print('[*] Writing bytes '..block..' to page '..string.format("%02x", block_counter))
|
||||
if data == ACK then
|
||||
print(ansicolors.cyan..'[*] Received ACK, write successful'..ansicolors.reset)
|
||||
else
|
||||
print(ansicolors.magenta..'[!] Write failed'..ansicolors.reset)
|
||||
end
|
||||
start_char = start_char + 8
|
||||
end_char = end_char + 8
|
||||
block_counter = block_counter + 1
|
||||
if block_counter == end_block then
|
||||
print(ansicolors.magenta..'[!] Not enough memory space!'..ansicolors.reset)
|
||||
break
|
||||
end
|
||||
end
|
||||
disconnect()
|
||||
end
|
||||
---
|
||||
|
||||
--- Function to dump user memory to console and disk
|
||||
local function dump(sector,uid)
|
||||
connect()
|
||||
select_sector(sector)
|
||||
counter = 0
|
||||
dest = uid..'.hex'
|
||||
file = io.open(dest, 'a')
|
||||
io.output(file)
|
||||
print("\n[+] Dumping sector "..sector.."\n")
|
||||
print(ansicolors.magenta..string.rep('--',16)..ansicolors.reset)
|
||||
for count = 1, 64 do
|
||||
result = send(READ_BLOCK..string.format("%02x", counter))
|
||||
print(ansicolors.cyan..result:sub(1,32)..ansicolors.reset)
|
||||
io.write(result:sub(1,32))
|
||||
counter = counter + 4
|
||||
end
|
||||
io.close(file)
|
||||
print(ansicolors.magenta..string.rep('--',16)..ansicolors.reset)
|
||||
print("\n[+] Memory dump saved to "..uid..".hex")
|
||||
disconnect()
|
||||
end
|
||||
---
|
||||
|
||||
|
||||
--- Function to read and write blocks
|
||||
local function exec(cmd, sector, block, bytes)
|
||||
connect()
|
||||
select_sector(sector)
|
||||
if cmd == READ_BLOCK then
|
||||
data = send(cmd..block)
|
||||
msg(data:sub(1,8))
|
||||
elseif cmd == WRITE_BLOCK then
|
||||
if bytes == 'NOP' then
|
||||
err = '[!] You need to pass some data'
|
||||
warn(err)
|
||||
print(usage)
|
||||
do return end
|
||||
else
|
||||
data = send(cmd..block..bytes)
|
||||
if data == ACK then
|
||||
print(ansicolors.cyan..'[+] Received ACK, write succesful'..ansicolors.reset)
|
||||
elseif data ~= ACK then
|
||||
print(ansicolors.magenta..'[!] Write failed'..ansicolors.reset)
|
||||
end
|
||||
end
|
||||
end
|
||||
disconnect()
|
||||
return(data)
|
||||
end
|
||||
---
|
||||
|
||||
|
||||
--- Main
|
||||
local function main(args)
|
||||
|
||||
for o, a in getopt.getopt(args, 'm:b:s:d:f:h') do
|
||||
if o == 'm' then mode = a end
|
||||
if o == 'b' then block = a end
|
||||
if o == 's' then sector = a end
|
||||
if o == 'd' then bytes = a end
|
||||
if o == 'f' then file = a end
|
||||
if o == 'h' then return help() end
|
||||
end
|
||||
|
||||
uid = connect()
|
||||
|
||||
connect()
|
||||
version = send(GET_VERSION)
|
||||
disconnect()
|
||||
|
||||
if version == NTAG_I2C_PLUS_2K then
|
||||
|
||||
if mode == 'r' then
|
||||
print('\n[+] Reading sector '..sector..' block '..block)
|
||||
exec(READ_BLOCK,sector,block,bytes)
|
||||
elseif mode == 'w' then
|
||||
print('\n[+] Writing '..bytes..' to sector '..sector..' block '..block)
|
||||
exec(WRITE_BLOCK,sector,block,bytes)
|
||||
elseif mode == 'f' then
|
||||
filewriter(file,sector)
|
||||
elseif mode == 'd' then
|
||||
dump(sector,uid)
|
||||
end
|
||||
|
||||
else
|
||||
return print(usage)
|
||||
end
|
||||
|
||||
if command == '' then return print(usage) end
|
||||
|
||||
end
|
||||
---
|
||||
|
||||
|
||||
main(args)
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
-- This Lua script is designed to run with Iceman/RRG Proxmark3 fork
|
||||
-- Just copy hf_mf_dump-luxeo.lua to client/luascripts/
|
||||
-- and run "script run hf_mf_dump-luxeo"
|
||||
-- and run "script run hf_mf_dump_luxeo"
|
||||
|
||||
-- requirements
|
||||
local cmds = require('commands')
|
||||
|
@ -12,16 +12,16 @@ local ansicolors = require('ansicolors')
|
|||
|
||||
copyright = ''
|
||||
author = '0xdrrb'
|
||||
version = 'v0.1.2'
|
||||
version = 'v0.1.3'
|
||||
desc = [[
|
||||
This is a script that tries to dump and decrypt the data of a specific type of Mifare laundromat token.
|
||||
OBS! Tag must be on the antenna.
|
||||
]]
|
||||
example = [[
|
||||
script run hf_mf_dump-luxeo
|
||||
script run hf_mf_dump_luxeo
|
||||
]]
|
||||
usage = [[
|
||||
script run hf_mf_dump-luxeo
|
||||
script run hf_mf_dump_luxeo
|
||||
]]
|
||||
arguments = [[
|
||||
-h This help
|
|
@ -63,8 +63,8 @@ local function card_format(key_a,key_b,ab,user,s70)
|
|||
core.console(cmd)
|
||||
print(cmd)
|
||||
core.clearCommandBuffer()
|
||||
if s70 == false and k > 15 then
|
||||
return
|
||||
if s70 == false and k > 15 then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
185
client/luascripts/hf_mf_sim_hid.lua
Normal file
185
client/luascripts/hf_mf_sim_hid.lua
Normal file
|
@ -0,0 +1,185 @@
|
|||
--
|
||||
-- hf_mf_sim_hid.lua - A tool to clone a large number of tags at once.
|
||||
-- Adapted from lf_hid_bulkclone.lua
|
||||
-- Created 16.08.2022
|
||||
local getopt = require('getopt')
|
||||
local ansicolors = require('ansicolors')
|
||||
|
||||
copyright = ''
|
||||
author = "Michael Micsen"
|
||||
version = 'v0.0.1'
|
||||
desc = [[
|
||||
Perform simulation of Mifare credentials with HID encoding
|
||||
This script only supports: H10301
|
||||
]]
|
||||
example = [[
|
||||
--
|
||||
script run hf_mf_sim_hid.lua -f 1 -c 10000
|
||||
]]
|
||||
usage = [[
|
||||
script run hf_mf_sim_hid.lua -f facility -c card_number
|
||||
]]
|
||||
arguments = [[
|
||||
-h : this help
|
||||
-f : facility id
|
||||
-c : starting card id
|
||||
]]
|
||||
local DEBUG = true
|
||||
--local bxor = bit32.bxor
|
||||
local bor = bit32.bor
|
||||
local lshift = bit32.lshift
|
||||
---
|
||||
-- A debug printout-function
|
||||
local function dbg(args)
|
||||
if not DEBUG then return end
|
||||
if type(args) == 'table' then
|
||||
local i = 1
|
||||
while args[i] do
|
||||
dbg(args[i])
|
||||
i = i+1
|
||||
end
|
||||
else
|
||||
print('###', args)
|
||||
end
|
||||
end
|
||||
---
|
||||
-- This is only meant to be used when errors occur
|
||||
local function oops(err)
|
||||
print('ERROR:', err)
|
||||
core.clearCommandBuffer()
|
||||
return nil, errr
|
||||
end
|
||||
---
|
||||
-- Usage help
|
||||
local function help()
|
||||
print(copyright)
|
||||
print(author)
|
||||
print(version)
|
||||
print(desc)
|
||||
print(ansicolors.cyan..'Usage'..ansicolors.reset)
|
||||
print(usage)
|
||||
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
|
||||
print(arguments)
|
||||
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
|
||||
print(example)
|
||||
end
|
||||
---
|
||||
-- Exit message
|
||||
local function exitMsg(msg)
|
||||
print( string.rep('--',20) )
|
||||
print( string.rep('--',20) )
|
||||
print(msg)
|
||||
print()
|
||||
end
|
||||
--[[Implement a function to simply visualize the bitstream in a text format
|
||||
--This is especially helpful for troubleshooting bitwise math issues]]--
|
||||
local function toBits(num,bits)
|
||||
-- returns a table of bits, most significant first.
|
||||
bits = bits or math.max(1, select(2, math.frexp(num)))
|
||||
local t = {} -- will contain the bits
|
||||
for b = bits, 1, -1 do
|
||||
t[b] = math.fmod(num, 2)
|
||||
num = math.floor((num - t[b]) / 2)
|
||||
end
|
||||
return table.concat(t)
|
||||
end
|
||||
|
||||
--[[
|
||||
Likely, I'm an idiot, but I couldn't find any parity functions in Lua
|
||||
This can also be done with a combination of bitwise operations (in fact,
|
||||
is the canonically "correct" way to do it, but my brain doesn't just
|
||||
default to this and so counting some ones is good enough for me
|
||||
]]--
|
||||
local function evenparity(s)
|
||||
local _, count = string.gsub(s, '1', '')
|
||||
local p = count % 2
|
||||
if (p == 0) then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function isempty(s)
|
||||
return s == nil or s == ''
|
||||
end
|
||||
|
||||
--[[
|
||||
The Proxmark3 "clone" functions expect the data to be in hex format so
|
||||
take the card id number and facility ID as arguments and construct the
|
||||
hex. This should be easy enough to extend to non 26bit formats
|
||||
]]--
|
||||
local function cardHex(i, f)
|
||||
|
||||
fac = lshift(f, 16)
|
||||
id = bor(i, fac)
|
||||
stream = toBits(id, 24)
|
||||
|
||||
--As the function defaults to even parity and returns a boolean,
|
||||
--perform a 'not' function to get odd parity
|
||||
high = evenparity(string.sub(stream,1,12)) and 1 or 0
|
||||
low = not evenparity(string.sub(stream,13)) and 1 or 0
|
||||
bits = bor( lshift(id, 1), low)
|
||||
bits = bor( bits, lshift(high, 25))
|
||||
|
||||
--Add sentinel bit
|
||||
sentinel = lshift(1, 26)
|
||||
bits = bor(bits, sentinel)
|
||||
|
||||
|
||||
return ('%08x'):format(bits)
|
||||
end
|
||||
---
|
||||
-- main
|
||||
local function main(args)
|
||||
|
||||
print( string.rep('--',20) )
|
||||
print( string.rep('--',20) )
|
||||
print()
|
||||
|
||||
if #args == 0 then return help() end
|
||||
|
||||
--I really wish a better getopt function would be brought in supporting
|
||||
--long arguments, but it seems this library was chosen for BSD style
|
||||
--compatibility
|
||||
for o, a in getopt.getopt(args, 'f:c:h') do
|
||||
if o == 'h' then return help() end
|
||||
if o == 'f' then
|
||||
if isempty(a) then
|
||||
print('You did not supply a facility code, using 0')
|
||||
facility = 0
|
||||
else
|
||||
facility = a
|
||||
end
|
||||
end
|
||||
if o == 'c' then
|
||||
print(a)
|
||||
if isempty(a) then return oops('You must supply the flag -c (card number)1') end
|
||||
cardnum = a
|
||||
end
|
||||
end
|
||||
|
||||
--Due to my earlier complaints about how this specific getopt library
|
||||
--works, specifying ':' does not enforce supplying a value, thus we
|
||||
--need to do these checks all over again.
|
||||
if isempty(cardnum) then return oops('You must supply the flag -c (card number)2') end
|
||||
--If the facility ID is non specified, ensure we code it as zero
|
||||
if isempty(facility) then
|
||||
print('Using 0 for the facility code as -f was not supplied')
|
||||
facility = 0
|
||||
end
|
||||
|
||||
-- Write the MAD to read for a Mifare HID credential
|
||||
core.console('hf mf esetblk -b 1 -d 1B014D48000000000000000000000000')
|
||||
core.console('hf mf esetblk -b 3 -d A0A1A2A3A4A5787788C189ECA97F8C2A')
|
||||
--Write the sector trailer for the credential sector
|
||||
core.console('hf mf esetblk -b 7 -d 484944204953787788AA204752454154')
|
||||
local cardh = cardHex(cardnum, facility)
|
||||
print('Hex')
|
||||
print(cardh)
|
||||
core.console( ('hf mf esetblk -b 5 -d 020000000000000000000000%s'):format(cardh) )
|
||||
|
||||
core.console('hf mf sim --1k -i')
|
||||
end
|
||||
|
||||
main(args)
|
|
@ -109,8 +109,8 @@ local function main(args)
|
|||
command = 'hf 14a sim -t 1 -u ' .. uid_format
|
||||
msg('Bruteforcing Mifare Classic card numbers')
|
||||
elseif mftype == 'mfc4' then
|
||||
command = 'hf 14a sim -t 8 -u ' .. uid_format
|
||||
msg('Bruteforcing Mifare Classic 4K card numbers')
|
||||
command = 'hf 14a sim -t 8 -u ' .. uid_format
|
||||
msg('Bruteforcing Mifare Classic 4K card numbers')
|
||||
elseif mftype == 'mfu' then
|
||||
command = 'hf 14a sim -t 2 -u ' .. uid_format
|
||||
msg('Bruteforcing Mifare Ultralight card numbers')
|
||||
|
|
|
@ -13,7 +13,7 @@ local err_lock = 'use -k or change cfg0 block'
|
|||
local _print = 0
|
||||
copyright = ''
|
||||
author = 'Nathan Glaser'
|
||||
version = 'v1.0.4'
|
||||
version = 'v1.0.5'
|
||||
date = 'Created - Jan 2022'
|
||||
desc = 'This script enables easy programming of an Ultimate Mifare Magic card'
|
||||
example = [[
|
||||
|
@ -50,17 +50,17 @@ arguments = [[
|
|||
-c read magic configuration
|
||||
-u UID (8-14 hexsymbols), set UID on tag
|
||||
-t tag type to impersonate
|
||||
1 = Mifare Mini S20 4-byte 12 = NTAG 210
|
||||
2 = Mifare Mini S20 7-byte 13 = NTAG 212
|
||||
3 = Mifare 1k S50 4-byte 14 = NTAG 213
|
||||
4 = Mifare 1k S50 7-byte 15 = NTAG 215
|
||||
5 = Mifare 4k S70 4-byte 16 = NTAG 216
|
||||
6 = Mifare 4k S70 7-byte 17 = NTAG I2C 1K
|
||||
*** 7 = UL - NOT WORKING FULLY 18 = NTAG I2C 2K
|
||||
*** 8 = UL-C - NOT WORKING FULLY 19 = NTAG I2C 1K PLUS
|
||||
9 = UL EV1 48b 20 = NTAG I2C 2K PLUS
|
||||
10 = UL EV1 128b 21 = NTAG 213F
|
||||
*** 11 = UL Plus - NOT WORKING YET 22 = NTAG 216F
|
||||
1 = Mifare Mini S20 4-byte 12 = NTAG 210
|
||||
2 = Mifare Mini S20 7-byte 13 = NTAG 212
|
||||
3 = Mifare 1k S50 4-byte 14 = NTAG 213
|
||||
4 = Mifare 1k S50 7-byte 15 = NTAG 215
|
||||
5 = Mifare 4k S70 4-byte 16 = NTAG 216
|
||||
6 = Mifare 4k S70 7-byte 17 = NTAG I2C 1K
|
||||
*** 7 = UL - NOT WORKING FULLY 18 = NTAG I2C 2K
|
||||
*** 8 = UL-C - NOT WORKING FULLY 19 = NTAG I2C 1K PLUS
|
||||
9 = UL EV1 48b 20 = NTAG I2C 2K PLUS
|
||||
10 = UL EV1 128b 21 = NTAG 213F
|
||||
*** 11 = UL Plus - NOT WORKING YET 22 = NTAG 216F
|
||||
|
||||
-p NTAG password (8 hexsymbols), set NTAG password on tag.
|
||||
-a NTAG pack ( 4 hexsymbols), set NTAG pack on tag.
|
||||
|
@ -178,7 +178,7 @@ local function read_config()
|
|||
if not info then return false, "Can't select card" end
|
||||
-- read Ultimate Magic Card CONFIG
|
||||
if magicconfig == nil then
|
||||
magicconfig = send("CF".._key.."C6")
|
||||
magicconfig = send("CF".._key.."C6")
|
||||
else print('No Config')
|
||||
end
|
||||
-- extract data from CONFIG - based on CONFIG in https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/magic_cards_notes.md#gen-4-gtu
|
||||
|
@ -186,7 +186,7 @@ local function read_config()
|
|||
atqaf = atqa1..' '..atqa2
|
||||
cardtype, cardprotocol, gtustr, atsstr = 'unknown', 'unknown', 'unknown', 'unknown'
|
||||
if magicconfig == nil then lib14a.disconnect(); return nil, "can't read configuration, "..err_lock end
|
||||
if #magicconfig ~= 64 then lib14a.disconnect(); return nil, "partial read of configuration, "..err_lock end
|
||||
if #magicconfig ~= 64 and #magicconfig ~= 68 then lib14a.disconnect(); return nil, "partial read of configuration, "..err_lock end
|
||||
if gtumode == '00' then gtustr = 'Pre-write/Shadow Mode'
|
||||
elseif gtumode == '01' then gtustr = 'Restore Mode'
|
||||
elseif gtumode == '02' then gtustr = 'Disabled'
|
||||
|
@ -196,93 +196,92 @@ local function read_config()
|
|||
else atsstr = (string.sub(ats, 3))
|
||||
end
|
||||
if ulprotocol == '00' then
|
||||
cardprotocol = 'MIFARE Classic Protocol'
|
||||
ultype = 'Disabled'
|
||||
if uidlength == '00' then
|
||||
uid = send("CF".._key.."CE00"):sub(1,8)
|
||||
if atqaf == '00 04' and sak == '09' then cardtype = 'MIFARE Mini S20 4-byte UID'
|
||||
elseif atqaf == '00 04' and sak == '08' then cardtype = 'MIFARE 1k S50 4-byte UID'
|
||||
elseif atqaf == '00 02' and sak == '18' then cardtype = 'MIFARE 4k S70 4-byte UID'
|
||||
end
|
||||
elseif uidlength == '01' then
|
||||
uid = send("CF".._key.."CE00"):sub(1,14)
|
||||
if atqaf == '00 44' and sak == '09' then cardtype = 'MIFARE Mini S20 7-byte UID'
|
||||
elseif atqaf == '00 44' and sak == '08' then cardtype = 'MIFARE 1k S50 7-byte UID'
|
||||
elseif atqaf == '00 42' and sak == '18' then cardtype = 'MIFARE 4k S70 7-byte UID'
|
||||
end
|
||||
end
|
||||
cardprotocol = 'MIFARE Classic Protocol'
|
||||
ultype = 'Disabled'
|
||||
if uidlength == '00' then
|
||||
uid = send("CF".._key.."CE00"):sub(1,8)
|
||||
if atqaf == '00 04' and sak == '09' then cardtype = 'MIFARE Mini S20 4-byte UID'
|
||||
elseif atqaf == '00 04' and sak == '08' then cardtype = 'MIFARE 1k S50 4-byte UID'
|
||||
elseif atqaf == '00 02' and sak == '18' then cardtype = 'MIFARE 4k S70 4-byte UID'
|
||||
end
|
||||
elseif uidlength == '01' then
|
||||
uid = send("CF".._key.."CE00"):sub(1,14)
|
||||
if atqaf == '00 44' and sak == '09' then cardtype = 'MIFARE Mini S20 7-byte UID'
|
||||
elseif atqaf == '00 44' and sak == '08' then cardtype = 'MIFARE 1k S50 7-byte UID'
|
||||
elseif atqaf == '00 42' and sak == '18' then cardtype = 'MIFARE 4k S70 7-byte UID'
|
||||
end
|
||||
end
|
||||
elseif ulprotocol == '01' then
|
||||
-- Read Ultralight config only if UL protocol is enabled
|
||||
cardprotocol = 'MIFARE Ultralight/NTAG'
|
||||
block0 = send("3000")
|
||||
uid0 = block0:sub(1,6)
|
||||
uid = uid0..block0:sub(9,16)
|
||||
if ulmode == '00' then ultype = 'Ultralight EV1'
|
||||
elseif ulmode == '01' then ultype = 'NTAG21x'
|
||||
elseif ulmode == '02' then ultype = 'Ultralight-C'
|
||||
elseif ulmode == '03' then ultype = 'Ultralight'
|
||||
end
|
||||
-- read VERSION
|
||||
cversion = send('30FA'):sub(1,16)
|
||||
-- pwdblock must be set since the 30F1 and 30F2 special commands don't work on the ntag21x part of the UMC
|
||||
if ulmode == '03' then versionstr = 'Ultralight'
|
||||
elseif ulmode == '02' then versionstr = 'Ultralight-C'
|
||||
elseif cversion == '0004030101000B03' then versionstr = 'UL EV1 48b'
|
||||
elseif cversion == '0004030101000B03' then versionstr = 'UL EV1 48b'
|
||||
elseif cversion == '0004030101000E03' then versionstr = 'UL EV1 128b'
|
||||
elseif cversion == '0004040101000B03' then versionstr = 'NTAG 210'
|
||||
elseif cversion == '0004040101000E03' then versionstr = 'NTAG 212'
|
||||
elseif cversion == '0004040201000F03' then versionstr = 'NTAG 213'
|
||||
elseif cversion == '0004040201001103' then versionstr = 'NTAG 215'
|
||||
elseif cversion == '0004040201001303' then versionstr = 'NTAG 216'
|
||||
elseif cversion == '0004040502011303' then versionstr = 'NTAG I2C 1K'
|
||||
elseif cversion == '0004040502011503' then versionstr = 'NTAG I2C 2K'
|
||||
elseif cversion == '0004040502021303' then versionstr = 'NTAG I2C 1K PLUS'
|
||||
elseif cversion == '0004040502021503' then versionstr = 'NTAG I2C 2K PLUS'
|
||||
elseif cversion == '0004040401000F03' then versionstr = 'NTAG 213F'
|
||||
elseif cversion == '0004040401001303' then versionstr = 'NTAG 216F'
|
||||
end
|
||||
-- read PWD
|
||||
cpwd = send("30F0"):sub(1,8)
|
||||
pwd = send("30E5"):sub(1,8)
|
||||
-- 04 response indicates that blocks has been locked down.
|
||||
if pwd == '04' then lib14a.disconnect(); return nil, "can't read configuration, "..err_lock end
|
||||
-- read PACK
|
||||
cpack = send("30F1"):sub(1,4)
|
||||
pack = send("30E6"):sub(1,4)
|
||||
-- read SIGNATURE
|
||||
signature1 = send('30F2'):sub(1,32)
|
||||
signature2 = send('30F6'):sub(1,32)
|
||||
lib14a.disconnect()
|
||||
-- Read Ultralight config only if UL protocol is enabled
|
||||
cardprotocol = 'MIFARE Ultralight/NTAG'
|
||||
block0 = send("3000")
|
||||
uid0 = block0:sub(1,6)
|
||||
uid = uid0..block0:sub(9,16)
|
||||
if ulmode == '00' then ultype = 'Ultralight EV1'
|
||||
elseif ulmode == '01' then ultype = 'NTAG21x'
|
||||
elseif ulmode == '02' then ultype = 'Ultralight-C'
|
||||
elseif ulmode == '03' then ultype = 'Ultralight'
|
||||
end
|
||||
-- read VERSION
|
||||
cversion = send('30FA'):sub(1,16)
|
||||
-- pwdblock must be set since the 30F1 and 30F2 special commands don't work on the ntag21x part of the UMC
|
||||
if ulmode == '03' then versionstr = 'Ultralight'
|
||||
elseif ulmode == '02' then versionstr = 'Ultralight-C'
|
||||
elseif cversion == '0004030101000B03' then versionstr = 'UL EV1 48b'
|
||||
elseif cversion == '0004030101000E03' then versionstr = 'UL EV1 128b'
|
||||
elseif cversion == '0004040101000B03' then versionstr = 'NTAG 210'
|
||||
elseif cversion == '0004040101000E03' then versionstr = 'NTAG 212'
|
||||
elseif cversion == '0004040201000F03' then versionstr = 'NTAG 213'
|
||||
elseif cversion == '0004040201001103' then versionstr = 'NTAG 215'
|
||||
elseif cversion == '0004040201001303' then versionstr = 'NTAG 216'
|
||||
elseif cversion == '0004040502011303' then versionstr = 'NTAG I2C 1K'
|
||||
elseif cversion == '0004040502011503' then versionstr = 'NTAG I2C 2K'
|
||||
elseif cversion == '0004040502021303' then versionstr = 'NTAG I2C 1K PLUS'
|
||||
elseif cversion == '0004040502021503' then versionstr = 'NTAG I2C 2K PLUS'
|
||||
elseif cversion == '0004040401000F03' then versionstr = 'NTAG 213F'
|
||||
elseif cversion == '0004040401001303' then versionstr = 'NTAG 216F'
|
||||
end
|
||||
-- read PWD
|
||||
cpwd = send("30F0"):sub(1,8)
|
||||
pwd = send("30E5"):sub(1,8)
|
||||
-- 04 response indicates that blocks has been locked down.
|
||||
if pwd == '04' then lib14a.disconnect(); return nil, "can't read configuration, "..err_lock end
|
||||
-- read PACK
|
||||
cpack = send("30F1"):sub(1,4)
|
||||
pack = send("30E6"):sub(1,4)
|
||||
-- read SIGNATURE
|
||||
signature1 = send('30F2'):sub(1,32)
|
||||
signature2 = send('30F6'):sub(1,32)
|
||||
lib14a.disconnect()
|
||||
end
|
||||
if _print < 1 then
|
||||
print(string.rep('=', 88))
|
||||
print('\t\t\tUltimate Magic Card Configuration')
|
||||
print(string.rep('=', 88))
|
||||
print(' - Raw Config ', string.sub(magicconfig, 1, -9))
|
||||
print(' - Card Protocol ', cardprotocol)
|
||||
print(' - Ultralight Mode ', ultype)
|
||||
print(' - ULM Backdoor Key ', readpass)
|
||||
print(' - GTU Mode ', gtustr)
|
||||
if ulprotocol == '01' then
|
||||
print(' - Card Type ', versionstr)
|
||||
else
|
||||
print(' - Card Type ', cardtype)
|
||||
end
|
||||
print(' - UID ', uid)
|
||||
print(' - ATQA ', atqaf)
|
||||
print(' - SAK ', sak)
|
||||
if ulprotocol == '01' then
|
||||
print('')
|
||||
print(string.rep('=', 88))
|
||||
print('\t\t\tMagic UL/NTAG 21* Configuration')
|
||||
print(string.rep('=', 88))
|
||||
print(' - ATS ', atsstr)
|
||||
print(' - Password ', '[0xE5] '..pwd, '[0xF0] '..cpwd)
|
||||
print(' - Pack ', '[0xE6] '..pack, '[0xF1] '..cpack)
|
||||
print(' - Version ', cversion)
|
||||
print(' - Signature ', signature1..signature2)
|
||||
end
|
||||
print(string.rep('=', 88))
|
||||
print('\t\t\tUltimate Magic Card Configuration')
|
||||
print(string.rep('=', 88))
|
||||
print(' - Raw Config ', string.sub(magicconfig, 1, -9))
|
||||
print(' - Card Protocol ', cardprotocol)
|
||||
print(' - Ultralight Mode ', ultype)
|
||||
print(' - ULM Backdoor Key ', readpass)
|
||||
print(' - GTU Mode ', gtustr)
|
||||
if ulprotocol == '01' then
|
||||
print(' - Card Type ', versionstr)
|
||||
else
|
||||
print(' - Card Type ', cardtype)
|
||||
end
|
||||
print(' - UID ', uid)
|
||||
print(' - ATQA ', atqaf)
|
||||
print(' - SAK ', sak)
|
||||
if ulprotocol == '01' then
|
||||
print('')
|
||||
print(string.rep('=', 88))
|
||||
print('\t\t\tMagic UL/NTAG 21* Configuration')
|
||||
print(string.rep('=', 88))
|
||||
print(' - ATS ', atsstr)
|
||||
print(' - Password ', '[0xE5] '..pwd, '[0xF0] '..cpwd)
|
||||
print(' - Pack ', '[0xE6] '..pack, '[0xF1] '..cpack)
|
||||
print(' - Version ', cversion)
|
||||
print(' - Signature ', signature1..signature2)
|
||||
end
|
||||
end
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
|
@ -292,41 +291,41 @@ end
|
|||
local function write_uid(useruid)
|
||||
-- read CONFIG
|
||||
if not magicconfig then
|
||||
_print = 1
|
||||
read_config()
|
||||
_print = 1
|
||||
read_config()
|
||||
end
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
-- Writes a MFC UID with GEN4 magic commands.
|
||||
if ulprotocol == '00' then
|
||||
-- uid string checks
|
||||
if useruid == nil then return nil, 'empty uid string' end
|
||||
if #useruid == 0 then return nil, 'empty uid string' end
|
||||
if (#useruid ~= 8) and (#useruid ~= 14) then return nil, 'UID wrong length. Should be 4 or 7 hex bytes' end
|
||||
print('Writing new UID ', useruid)
|
||||
local uidbytes = utils.ConvertHexToBytes(useruid)
|
||||
local bcc1 = bxor(bxor(bxor(uidbytes[1], uidbytes[2]), uidbytes[3]), uidbytes[4])
|
||||
local block0 = string.format('%02X%02X%02X%02X%02X', uidbytes[1], uidbytes[2], uidbytes[3], uidbytes[4], bcc1)
|
||||
local resp = send('CF'.._key..'CD00'..block0)
|
||||
-- uid string checks
|
||||
if useruid == nil then return nil, 'empty uid string' end
|
||||
if #useruid == 0 then return nil, 'empty uid string' end
|
||||
if (#useruid ~= 8) and (#useruid ~= 14) then return nil, 'UID wrong length. Should be 4 or 7 hex bytes' end
|
||||
print('Writing new UID ', useruid)
|
||||
local uidbytes = utils.ConvertHexToBytes(useruid)
|
||||
local bcc1 = bxor(bxor(bxor(uidbytes[1], uidbytes[2]), uidbytes[3]), uidbytes[4])
|
||||
local block0 = string.format('%02X%02X%02X%02X%02X', uidbytes[1], uidbytes[2], uidbytes[3], uidbytes[4], bcc1)
|
||||
local resp = send('CF'.._key..'CD00'..block0)
|
||||
-- Writes a MFUL UID with bcc1, bcc2 using NTAG21xx commands.
|
||||
elseif ulprotocol == '01' then
|
||||
-- uid string checks
|
||||
if useruid == nil then return nil, 'empty uid string' end
|
||||
if #useruid == 0 then return nil, 'empty uid string' end
|
||||
if #useruid ~= 14 then return nil, 'uid wrong length. Should be 7 hex bytes' end
|
||||
print('Writing new UID ', useruid)
|
||||
local uidbytes = utils.ConvertHexToBytes(useruid)
|
||||
local bcc1 = bxor(bxor(bxor(uidbytes[1], uidbytes[2]), uidbytes[3]), 0x88)
|
||||
local bcc2 = bxor(bxor(bxor(uidbytes[4], uidbytes[5]), uidbytes[6]), uidbytes[7])
|
||||
local block0 = string.format('%02X%02X%02X%02X', uidbytes[1], uidbytes[2], uidbytes[3], bcc1)
|
||||
local block1 = string.format('%02X%02X%02X%02X', uidbytes[4], uidbytes[5], uidbytes[6], uidbytes[7])
|
||||
local block2 = string.format('%02X%02X%02X%02X', bcc2, 0x48, 0x00, 0x00)
|
||||
local resp
|
||||
resp = send('A200'..block0)
|
||||
resp = send('A201'..block1)
|
||||
resp = send('A202'..block2)
|
||||
-- uid string checks
|
||||
if useruid == nil then return nil, 'empty uid string' end
|
||||
if #useruid == 0 then return nil, 'empty uid string' end
|
||||
if #useruid ~= 14 then return nil, 'uid wrong length. Should be 7 hex bytes' end
|
||||
print('Writing new UID ', useruid)
|
||||
local uidbytes = utils.ConvertHexToBytes(useruid)
|
||||
local bcc1 = bxor(bxor(bxor(uidbytes[1], uidbytes[2]), uidbytes[3]), 0x88)
|
||||
local bcc2 = bxor(bxor(bxor(uidbytes[4], uidbytes[5]), uidbytes[6]), uidbytes[7])
|
||||
local block0 = string.format('%02X%02X%02X%02X', uidbytes[1], uidbytes[2], uidbytes[3], bcc1)
|
||||
local block1 = string.format('%02X%02X%02X%02X', uidbytes[4], uidbytes[5], uidbytes[6], uidbytes[7])
|
||||
local block2 = string.format('%02X%02X%02X%02X', bcc2, 0x48, 0x00, 0x00)
|
||||
local resp
|
||||
resp = send('A200'..block0)
|
||||
resp = send('A201'..block1)
|
||||
resp = send('A202'..block2)
|
||||
else
|
||||
print('Incorrect ul')
|
||||
print('Incorrect ul')
|
||||
end
|
||||
lib14a.disconnect()
|
||||
if resp ~= nil then
|
||||
|
@ -340,8 +339,8 @@ end
|
|||
local function write_atqasak(atqasak)
|
||||
-- read CONFIG
|
||||
if not magicconfig then
|
||||
_print = 1
|
||||
read_config()
|
||||
_print = 1
|
||||
read_config()
|
||||
end
|
||||
if atqasak == nil then return nil, 'Empty ATQA/SAK string' end
|
||||
if #atqasak == 0 then return nil, 'Empty ATQA/SAK string' end
|
||||
|
@ -351,25 +350,25 @@ end
|
|||
local atqauserf = atqauser2..atqauser1
|
||||
local sakuser = atqasak:sub(5,6)
|
||||
if sakuser == '04' then
|
||||
print('Never set SAK bit 3 (e.g. SAK=04), it indicates an extra cascade level is required')
|
||||
return nil
|
||||
print('Never set SAK bit 3 (e.g. SAK=04), it indicates an extra cascade level is required')
|
||||
return nil
|
||||
elseif (sakuser == '20' or sakuser == '28') and atslen == '00' then
|
||||
print('When SAK equals 20 or 28, ATS must be turned on')
|
||||
return nil
|
||||
print('When SAK equals 20 or 28, ATS must be turned on')
|
||||
return nil
|
||||
elseif atqauser2 == '40' then
|
||||
print('ATQA of [00 40] will cause the card to not answer.')
|
||||
return nil
|
||||
print('ATQA of [00 40] will cause the card to not answer.')
|
||||
return nil
|
||||
else
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
print('New ATQA: '..atqauser1..' '..atqauser2..' New SAK: '..sakuser)
|
||||
local resp = send("CF".._key.."35"..atqauserf..sakuser)
|
||||
lib14a.disconnect()
|
||||
if resp == nil then
|
||||
return nil, oops('Failed to write ATQA/SAK')
|
||||
else
|
||||
return true, 'Ok'
|
||||
end
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
print('New ATQA: '..atqauser1..' '..atqauser2..' New SAK: '..sakuser)
|
||||
local resp = send("CF".._key.."35"..atqauserf..sakuser)
|
||||
lib14a.disconnect()
|
||||
if resp == nil then
|
||||
return nil, oops('Failed to write ATQA/SAK')
|
||||
else
|
||||
return true, 'Ok'
|
||||
end
|
||||
end
|
||||
end
|
||||
---
|
||||
|
@ -377,8 +376,8 @@ end
|
|||
local function write_ntagpwd(ntagpwd)
|
||||
-- read CONFIG
|
||||
if not magicconfig then
|
||||
_print = 1
|
||||
read_config()
|
||||
_print = 1
|
||||
read_config()
|
||||
end
|
||||
if ulprotocol == '00' then return nil, 'Magic Card is not using the Ultralight Protocol' end
|
||||
-- PWD string checks
|
||||
|
@ -402,8 +401,8 @@ end
|
|||
local function write_pack(userpack)
|
||||
-- read CONFIG
|
||||
if not magicconfig then
|
||||
_print = 1
|
||||
read_config()
|
||||
_print = 1
|
||||
read_config()
|
||||
end
|
||||
if ulprotocol == 0 then return nil, 'Magic Card is not using the Ultralight Protocol' end
|
||||
-- PACK string checks
|
||||
|
@ -427,8 +426,8 @@ local function write_otp(block3)
|
|||
if #block3 ~= 8 then return nil, 'OTP wrong length. Should be 4 hex bytes' end
|
||||
-- read CONFIG
|
||||
if not magicconfig then
|
||||
_print = 1
|
||||
read_config()
|
||||
_print = 1
|
||||
read_config()
|
||||
end
|
||||
if ulprotocol == '00' then return nil, 'Magic Card is not using the Ultralight Protocol' end
|
||||
local info = connect()
|
||||
|
@ -451,8 +450,8 @@ local function write_version(data)
|
|||
if #data ~= 16 then return nil, 'version wrong length. Should be 8 hex bytes' end
|
||||
-- read CONFIG
|
||||
if not magicconfig then
|
||||
_print = 1
|
||||
read_config()
|
||||
_print = 1
|
||||
read_config()
|
||||
end
|
||||
if ulprotocol == '00' then return nil, 'Magic Card is not using the Ultralight Protocol' end
|
||||
print('Writing new version', data)
|
||||
|
@ -479,22 +478,34 @@ local function write_signature(data)
|
|||
if #data ~= 64 then return nil, 'data wrong length. Should be 32 hex bytes' end
|
||||
-- read CONFIG
|
||||
if not magicconfig then
|
||||
_print = 1
|
||||
read_config()
|
||||
_print = 1
|
||||
read_config()
|
||||
end
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
if ulprotocol == '00' then return nil, 'Magic Card is not using the Ultralight Protocol' end
|
||||
print('Writing new signature',data)
|
||||
local b,c
|
||||
local cmd = 'A2F%d%s'
|
||||
local j = 2
|
||||
for i = 1, #data, 8 do
|
||||
b = data:sub(i,i+7)
|
||||
c = cmd:format(j,b)
|
||||
local resp = send(c)
|
||||
if resp ~= '0A' then lib14a.disconnect(); return nil, oops('Failed to write signature') end
|
||||
j = j + 1
|
||||
if ulprotocol == '00' then
|
||||
print('Writing new MFC signature',data)
|
||||
send('CF'.._key..'6B48')
|
||||
lib14a.disconnect()
|
||||
connect() -- not 100% sure why it's needed, but without this blocks aren't actually written
|
||||
local sig1 = data:sub(1, 32)
|
||||
local sig2 = data:sub(33, 64)
|
||||
|
||||
send('CF'.._key..'CD45'..sig1)
|
||||
send('CF'.._key..'CD46'..sig2)
|
||||
send('CF'.._key..'CD475C8FF9990DA270F0F8694B791BEA7BCC')
|
||||
else
|
||||
print('Writing new MFUL signature',data)
|
||||
local b,c
|
||||
local cmd = 'A2F%d%s'
|
||||
local j = 2
|
||||
for i = 1, #data, 8 do
|
||||
b = data:sub(i,i+7)
|
||||
c = cmd:format(j,b)
|
||||
local resp = send(c)
|
||||
if resp ~= '0A' then lib14a.disconnect(); return nil, oops('Failed to write signature') end
|
||||
j = j + 1
|
||||
end
|
||||
end
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
|
@ -509,19 +520,19 @@ local function write_gtu(gtu)
|
|||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
if gtu == '00' then
|
||||
print('Enabling GTU Pre-Write')
|
||||
send('CF'.._key..'32'..gtu)
|
||||
print('Enabling GTU Pre-Write')
|
||||
send('CF'.._key..'32'..gtu)
|
||||
elseif gtu == '01' then
|
||||
print('Enabling GTU Restore Mode')
|
||||
send('CF'.._key..'32'..gtu)
|
||||
print('Enabling GTU Restore Mode')
|
||||
send('CF'.._key..'32'..gtu)
|
||||
elseif gtu == '02' then
|
||||
print('Disabled GTU')
|
||||
send('CF'.._key..'32'..gtu)
|
||||
print('Disabled GTU')
|
||||
send('CF'.._key..'32'..gtu)
|
||||
elseif gtu == '03' then
|
||||
print('Disabled GTU, high speed R/W mode for Ultralight')
|
||||
send('CF'.._key..'32'..gtu)
|
||||
print('Disabled GTU, high speed R/W mode for Ultralight')
|
||||
send('CF'.._key..'32'..gtu)
|
||||
else
|
||||
print('Failed to set GTU mode')
|
||||
print('Failed to set GTU mode')
|
||||
end
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
|
@ -537,13 +548,13 @@ local function write_ats(atsuser)
|
|||
local atscardlendecimal = tonumber(atscardlen, 16)
|
||||
local atsf = string.sub(atsuser, 3)
|
||||
if (#atsf / 2) ~= atscardlendecimal then
|
||||
oops('Given length of ATS ('..atscardlendecimal..') does not match the ATS_length ('..(#atsf / 2)..')')
|
||||
return true, 'Ok'
|
||||
oops('Given length of ATS ('..atscardlendecimal..') does not match the ATS_length ('..(#atsf / 2)..')')
|
||||
return true, 'Ok'
|
||||
else
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
print('Writing '..atscardlendecimal..' ATS bytes of '..atsf)
|
||||
send("CF".._key.."34"..atsuser)
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
print('Writing '..atscardlendecimal..' ATS bytes of '..atsf)
|
||||
send("CF".._key.."34"..atsuser)
|
||||
end
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
|
@ -557,11 +568,11 @@ local function write_ulp(ulp)
|
|||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
if ulp == '00' then
|
||||
print('Changing card to Mifare Classic Protocol')
|
||||
send("CF".._key.."69"..ulp)
|
||||
print('Changing card to Mifare Classic Protocol')
|
||||
send("CF".._key.."69"..ulp)
|
||||
elseif ulp == '01' then
|
||||
print('Changing card to Ultralight Protocol')
|
||||
send("CF".._key.."69"..ulp)
|
||||
print('Changing card to Ultralight Protocol')
|
||||
send("CF".._key.."69"..ulp)
|
||||
else
|
||||
oops('Protocol needs to be either 00 or 01')
|
||||
end
|
||||
|
@ -577,17 +588,17 @@ local function write_ulm(ulm)
|
|||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
if ulm == '00' then
|
||||
print('Changing card UL mode to Ultralight EV1')
|
||||
send("CF".._key.."6A"..ulm)
|
||||
print('Changing card UL mode to Ultralight EV1')
|
||||
send("CF".._key.."6A"..ulm)
|
||||
elseif ulm == '01' then
|
||||
print('Changing card UL mode to NTAG')
|
||||
send("CF".._key.."6A"..ulm)
|
||||
print('Changing card UL mode to NTAG')
|
||||
send("CF".._key.."6A"..ulm)
|
||||
elseif ulm == '02' then
|
||||
print('Changing card UL mode to Ultralight-C')
|
||||
send("CF".._key.."6A"..ulm)
|
||||
print('Changing card UL mode to Ultralight-C')
|
||||
send("CF".._key.."6A"..ulm)
|
||||
elseif ulm == '03' then
|
||||
print('Changing card UL mode to Ultralight')
|
||||
send("CF".._key.."6A"..ulm)
|
||||
print('Changing card UL mode to Ultralight')
|
||||
send("CF".._key.."6A"..ulm)
|
||||
else
|
||||
oops('UL mode needs to be either 00, 01, 02, 03')
|
||||
end
|
||||
|
@ -604,50 +615,50 @@ local function set_type(tagtype)
|
|||
if tagtype == 1 then
|
||||
print('Setting: Ultimate Magic card to Mifare mini S20 4-byte')
|
||||
connect()
|
||||
send("CF".._key.."F000000000000002000978009102DABC19101011121314151604000900")
|
||||
lib14a.disconnect()
|
||||
send("CF".._key.."F000000000000002000978009102DABC19101011121314151604000900")
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233')
|
||||
-- Setting Mifare mini S20 7-byte
|
||||
elseif tagtype == 2 then
|
||||
print('Setting: Ultimate Magic card to Mifare mini S20 7-byte')
|
||||
connect()
|
||||
send("CF".._key.."F000010000000002000978009102DABC19101011121314151644000900")
|
||||
lib14a.disconnect()
|
||||
send("CF".._key.."F000010000000002000978009102DABC19101011121314151644000900")
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
-- Setting Mifare 1k S50 4--byte
|
||||
elseif tagtype == 3 then
|
||||
print('Setting: Ultimate Magic card to Mifare 1k S50 4-byte')
|
||||
connect()
|
||||
send("CF".._key.."F000000000000002000978009102DABC19101011121314151604000800")
|
||||
lib14a.disconnect()
|
||||
send("CF".._key.."F000000000000002000978009102DABC19101011121314151604000800")
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233')
|
||||
-- Setting Mifare 1k S50 7-byte
|
||||
elseif tagtype == 4 then
|
||||
print('Setting: Ultimate Magic card to Mifare 1k S50 7-byte')
|
||||
connect()
|
||||
send("CF".._key.."F000010000000002000978009102DABC19101011121314151644000800")
|
||||
lib14a.disconnect()
|
||||
send("CF".._key.."F000010000000002000978009102DABC19101011121314151644000800")
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
-- Setting Mifare 4k S70 4-byte
|
||||
elseif tagtype == 5 then
|
||||
print('Setting: Ultimate Magic card to Mifare 4k S70 4-byte')
|
||||
connect()
|
||||
send("CF".._key.."F000000000000002000978009102DABC19101011121314151602001800")
|
||||
lib14a.disconnect()
|
||||
send("CF".._key.."F000000000000002000978009102DABC19101011121314151602001800")
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233')
|
||||
-- Setting Mifare 4k S70 7-byte
|
||||
elseif tagtype == 6 then
|
||||
print('Setting: Ultimate Magic card to Mifare 4k S70 7-byte')
|
||||
connect()
|
||||
send("CF".._key.."F000010000000002000978009102DABC19101011121314151642001800")
|
||||
lib14a.disconnect()
|
||||
send("CF".._key.."F000010000000002000978009102DABC19101011121314151642001800")
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
-- Setting UL
|
||||
elseif tagtype == 7 then
|
||||
print('Setting: Ultimate Magic card to UL')
|
||||
connect()
|
||||
send("CF".._key.."F0010100000000030A0A78008102DBA0C119402AB5BA4D321A44000003")
|
||||
lib14a.disconnect()
|
||||
send("CF".._key.."F0010100000000030A0A78008102DBA0C119402AB5BA4D321A44000003")
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_otp('00000000') -- Setting OTP to default 00 00 00 00
|
||||
write_version('0000000000000000') -- UL-C does not have a version
|
||||
|
@ -655,48 +666,48 @@ local function set_type(tagtype)
|
|||
elseif tagtype == 8 then
|
||||
print('Setting: Ultimate Magic card to UL-C')
|
||||
connect()
|
||||
send("CF".._key.."F0010100000000030A0A78008102DBA0C119402AB5BA4D321A44000002")
|
||||
print('Setting default permissions and 3des key')
|
||||
send('A22A30000000') -- Auth0 page 48/0x30 and above need authentication
|
||||
send('A22B80000000') -- Auth1 read and write access restricted
|
||||
send('A22C42524541') -- Default 3des key
|
||||
send('A22D4B4D4549')
|
||||
send('A22E46594F55')
|
||||
send('A22F43414E21')
|
||||
lib14a.disconnect()
|
||||
send("CF".._key.."F0010100000000030A0A78008102DBA0C119402AB5BA4D321A44000002")
|
||||
print('Setting default permissions and 3des key')
|
||||
send('A22A30000000') -- Auth0 page 48/0x30 and above need authentication
|
||||
send('A22B80000000') -- Auth1 read and write access restricted
|
||||
send('A22C42524541') -- Default 3des key
|
||||
send('A22D4B4D4549')
|
||||
send('A22E46594F55')
|
||||
send('A22F43414E21')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_otp('00000000') -- Setting OTP to default 00 00 00 00
|
||||
write_version('0000000000000000') -- UL-C does not have a version
|
||||
elseif tagtype == 9 then
|
||||
print('Setting: Ultimate Magic card to UL-EV1 48')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000000")
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000000")
|
||||
-- Setting UL-Ev1 default config bl 16,17
|
||||
send('a2E5FFFFFFFF') -- A2F0 block does not align correctly to actual pwd block
|
||||
send('a2E6FFFFFFFF') -- A2F1 block does not align correctly to actual pack block
|
||||
send('a2E5FFFFFFFF') -- A2F0 block does not align correctly to actual pwd block
|
||||
send('a2E6FFFFFFFF') -- A2F1 block does not align correctly to actual pack block
|
||||
send('a210000000FF')
|
||||
send('a21100050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_otp('00000000') -- Setting OTP to default 00 00 00 00
|
||||
write_version('0004030101000b03') -- UL-EV1 (48) 00 04 03 01 01 00 0b 03
|
||||
elseif tagtype == 10 then
|
||||
print('Setting: Ultimate Magic card to UL-EV1 128')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000000")
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000000")
|
||||
-- Setting UL-Ev1 default config bl 37,38
|
||||
send('a2E5FFFFFFFF') -- A2F0 block does not align correctly to actual pwd block
|
||||
send('a2E6FFFFFFFF') -- A2F1 block does not align correctly to actual pack block
|
||||
send('a2E5FFFFFFFF') -- A2F0 block does not align correctly to actual pwd block
|
||||
send('a2E6FFFFFFFF') -- A2F1 block does not align correctly to actual pack block
|
||||
send('a225000000FF')
|
||||
send('a22600050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_otp('00000000') -- Setting OTP to default 00 00 00 00
|
||||
write_version('0004030101000e03') -- UL-EV1 (128) 00 04 03 01 01 00 0e 03
|
||||
elseif tagtype == 12 then
|
||||
print('Setting: Ultimate Magic card to NTAG 210')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG210 default CC block456
|
||||
send('a203e1100600')
|
||||
send('a2040300fe00')
|
||||
|
@ -704,13 +715,13 @@ local function set_type(tagtype)
|
|||
-- Setting cfg1/cfg2
|
||||
send('a210000000FF')
|
||||
send('a21100050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040101000b03') -- NTAG210 00 04 04 01 01 00 0b 03
|
||||
elseif tagtype == 13 then
|
||||
print('Setting: Ultimate Magic card to NTAG 212')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG212 default CC block456
|
||||
send('a203e1101000')
|
||||
send('a2040103900a')
|
||||
|
@ -718,13 +729,13 @@ local function set_type(tagtype)
|
|||
-- Setting cfg1/cfg2
|
||||
send('a225000000FF')
|
||||
send('a22600050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040101000E03') -- NTAG212 00 04 04 01 01 00 0E 03
|
||||
elseif tagtype == 14 then
|
||||
print('Setting: Ultimate Magic card to NTAG 213')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG213 default CC block456
|
||||
send('a203e1101200')
|
||||
send('a2040103a00c')
|
||||
|
@ -732,13 +743,13 @@ local function set_type(tagtype)
|
|||
-- setting cfg1/cfg2
|
||||
send('a229000000ff')
|
||||
send('a22a00050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040201000F03') -- NTAG213 00 04 04 02 01 00 0f 03
|
||||
elseif tagtype == 15 then
|
||||
print('Setting: Ultimate Magic card to NTAG 215')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG215 default CC block456
|
||||
send('a203e1103e00')
|
||||
send('a2040300fe00')
|
||||
|
@ -746,13 +757,13 @@ local function set_type(tagtype)
|
|||
-- setting cfg1/cfg2
|
||||
send('a283000000ff')
|
||||
send('a28400050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040201001103') -- NTAG215 00 04 04 02 01 00 11 03
|
||||
elseif tagtype == 16 then
|
||||
print('Setting: Ultimate Magic card to NTAG 216')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG216 default CC block456
|
||||
send('a203e1106d00')
|
||||
send('a2040300fe00')
|
||||
|
@ -760,56 +771,56 @@ local function set_type(tagtype)
|
|||
-- setting cfg1/cfg2
|
||||
send('a2e3000000ff')
|
||||
send('a2e400050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040201001303') -- NTAG216 00 04 04 02 01 00 13 03
|
||||
elseif tagtype == 17 then
|
||||
print('Setting: Ultimate Magic card to NTAG I2C 1K')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG I2C 1K default CC block456
|
||||
send('a203e1106D00')
|
||||
send('a2040300fe00')
|
||||
send('a20500000000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040502011303') -- NTAG_I2C_1K 00 04 04 05 02 01 13 03
|
||||
elseif tagtype == 18 then
|
||||
print('Setting: Ultimate Magic card to NTAG I2C 2K')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG I2C 2K default CC block456
|
||||
send('a203e110EA00')
|
||||
send('a2040300fe00')
|
||||
send('a20500000000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040502011503') -- NTAG_I2C_2K 00 04 04 05 02 01 15 03
|
||||
elseif tagtype == 19 then
|
||||
print('Setting: Ultimate Magic card to NTAG I2C plus 1K')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG I2C 1K default CC block456
|
||||
send('a203e1106D00')
|
||||
send('a2040300fe00')
|
||||
send('a20500000000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040502021303') -- NTAG_I2C_1K 00 04 04 05 02 02 13 03
|
||||
elseif tagtype == 20 then
|
||||
print('Setting: Ultimate Magic card to NTAG I2C plus 2K')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG I2C 2K default CC block456
|
||||
send('a203e1106D00')
|
||||
send('a2040300fe00')
|
||||
send('a20500000000')
|
||||
write_uid('04112233445566')
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040502021503') -- NTAG_I2C_2K 00 04 04 05 02 02 15 03
|
||||
elseif tagtype == 21 then
|
||||
print('Setting: Ultimate Magic card to NTAG 213F')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG213 default CC block456
|
||||
send('a203e1101200')
|
||||
send('a2040103a00c')
|
||||
|
@ -817,13 +828,13 @@ local function set_type(tagtype)
|
|||
-- setting cfg1/cfg2
|
||||
send('a229000000ff')
|
||||
send('a22a00050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040401000F03') -- NTAG213F 00 04 04 04 01 00 0f 03
|
||||
elseif tagtype == 22 then
|
||||
print('Setting: Ultimate Magic card to NTAG 216F')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG216 default CC block456
|
||||
send('a203e1106d00')
|
||||
send('a2040300fe00')
|
||||
|
@ -831,11 +842,11 @@ local function set_type(tagtype)
|
|||
-- setting cfg1/cfg2
|
||||
send('a2e3000000ff')
|
||||
send('a2e400050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040401001303') -- NTAG216F 00 04 04 04 01 00 13 03
|
||||
else
|
||||
oops('No matching tag types')
|
||||
oops('No matching tag types')
|
||||
end
|
||||
lib14a.disconnect()
|
||||
if resp == '04' then
|
||||
|
@ -845,86 +856,101 @@ local function set_type(tagtype)
|
|||
end
|
||||
end
|
||||
---
|
||||
-- returns true if b is the index of a sector trailer
|
||||
local function mfIsSectorTrailer(b)
|
||||
n=b+1
|
||||
if (n < 32*4 ) then
|
||||
if (n % 4 == 0) then return true
|
||||
else return false
|
||||
end
|
||||
end
|
||||
|
||||
if (n % 16 == 0) then return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
---
|
||||
-- wipe tag
|
||||
local function wipe(wtype)
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
if wtype == '0' then
|
||||
print('Starting Mifare Wipe')
|
||||
print('Starting Mifare Wipe')
|
||||
send("CF".._key.."F000000000000002000978009102DABC19101011121314151604000800")
|
||||
send("CF".._key.."CD000102030404080400000000000000BEAF")
|
||||
local err, msg, resp
|
||||
local cmd_empty = 'CF'.._key..'CD%02X00000000000000000000000000000000'
|
||||
local cmd_cfg1 = 'CF'.._key..'CD%02XFFFFFFFFFFFFFF078069FFFFFFFFFFFF'
|
||||
for b = 1, 0xFB do
|
||||
if b == 0x03 or b == 0x07 or b == 0x0B or b == 0x0F or b == 0x13 or b == 0x17 or b == 0x1B or b == 0x1F or b == 0x23 or b == 0x27 or b == 0x2B or b == 0x2F or b == 0x33 or b == 0x37 or b == 0x3B or b == 0x3F then
|
||||
local cmd = (cmd_cfg1):format(b)
|
||||
resp = send(cmd)
|
||||
else
|
||||
local cmd = (cmd_empty):format(b)
|
||||
resp = send(cmd)
|
||||
end
|
||||
if resp == nil then
|
||||
io.write('\nwrote block '..b, ' failed\n')
|
||||
err = true
|
||||
else
|
||||
io.write('.')
|
||||
end
|
||||
io.flush()
|
||||
end
|
||||
print('\n')
|
||||
err, msg = set_type(3)
|
||||
if err == nil then return err, msg end
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
local err, msg, resp
|
||||
local cmd_empty = 'CF'.._key..'CD%02X00000000000000000000000000000000'
|
||||
local cmd_trail = 'CF'.._key..'CD%02XFFFFFFFFFFFFFF078069FFFFFFFFFFFF'
|
||||
for b = 1, 0xFF do
|
||||
if mfIsSectorTrailer(b) then
|
||||
local cmd = (cmd_trail):format(b)
|
||||
resp = send(cmd)
|
||||
else
|
||||
local cmd = (cmd_empty):format(b)
|
||||
resp = send(cmd)
|
||||
end
|
||||
if resp == nil then
|
||||
io.write('\nwrote block '..b, ' failed\n')
|
||||
err = true
|
||||
else
|
||||
io.write('.')
|
||||
end
|
||||
io.flush()
|
||||
end
|
||||
print('\n')
|
||||
err, msg = set_type(3)
|
||||
if err == nil then return err, msg end
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
elseif wtype == '1' then
|
||||
print('Starting Ultralight Wipe')
|
||||
local err, msg, resp
|
||||
local cmd_empty = 'A2%02X00000000'
|
||||
local cmd_cfg1 = 'A2%02X000000FF'
|
||||
local cmd_cfg2 = 'A2%02X00050000'
|
||||
print('Wiping tag')
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
print('Starting Ultralight Wipe')
|
||||
local err, msg, resp
|
||||
local cmd_empty = 'A2%02X00000000'
|
||||
local cmd_cfg1 = 'A2%02X000000FF'
|
||||
local cmd_cfg2 = 'A2%02X00050000'
|
||||
print('Wiping tag')
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
for b = 3, 0xFB do
|
||||
--configuration block 0
|
||||
if b == 0x29 or b == 0x83 or b == 0xe3 then
|
||||
local cmd = (cmd_cfg1):format(b)
|
||||
resp = send(cmd)
|
||||
--configuration block 1
|
||||
elseif b == 0x2a or b == 0x84 or b == 0xe4 then
|
||||
local cmd = (cmd_cfg2):format(b)
|
||||
resp = send(cmd)
|
||||
else
|
||||
resp = send(cmd_empty:format(b))
|
||||
end
|
||||
if resp == '04' or #resp == 0 then
|
||||
io.write('\nwrote block '..b, ' failed\n')
|
||||
err = true
|
||||
else
|
||||
io.write('.')
|
||||
end
|
||||
io.flush()
|
||||
end
|
||||
io.write('\r\n')
|
||||
lib14a.disconnect()
|
||||
print('\n')
|
||||
if err then return nil, "Tag locked down, "..err_lock end
|
||||
-- set NTAG213 default values
|
||||
err, msg = set_type(14)
|
||||
if err == nil then return err, msg end
|
||||
--set UID
|
||||
err, msg = write_uid('04112233445566')
|
||||
if err == nil then return err, msg end
|
||||
--set NTAG pwd
|
||||
err, msg = write_ntagpwd('FFFFFFFF')
|
||||
if err == nil then return err, msg end
|
||||
--set pack
|
||||
err, msg = write_pack('0000')
|
||||
if err == nil then return err, msg end
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
for b = 3, 0xFB do
|
||||
--configuration block 0
|
||||
if b == 0x29 or b == 0x83 or b == 0xe3 then
|
||||
local cmd = (cmd_cfg1):format(b)
|
||||
resp = send(cmd)
|
||||
--configuration block 1
|
||||
elseif b == 0x2a or b == 0x84 or b == 0xe4 then
|
||||
local cmd = (cmd_cfg2):format(b)
|
||||
resp = send(cmd)
|
||||
else
|
||||
resp = send(cmd_empty:format(b))
|
||||
end
|
||||
if resp == '04' or #resp == 0 then
|
||||
io.write('\nwrote block '..b, ' failed\n')
|
||||
err = true
|
||||
else
|
||||
io.write('.')
|
||||
end
|
||||
io.flush()
|
||||
end
|
||||
io.write('\r\n')
|
||||
lib14a.disconnect()
|
||||
print('\n')
|
||||
if err then return nil, "Tag locked down, "..err_lock end
|
||||
-- set NTAG213 default values
|
||||
err, msg = set_type(14)
|
||||
if err == nil then return err, msg end
|
||||
--set UID
|
||||
err, msg = write_uid('04112233445566')
|
||||
if err == nil then return err, msg end
|
||||
--set NTAG pwd
|
||||
err, msg = write_ntagpwd('FFFFFFFF')
|
||||
if err == nil then return err, msg end
|
||||
--set pack
|
||||
err, msg = write_pack('0000')
|
||||
if err == nil then return err, msg end
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
else oops('Use 0 for Mifare wipe or 1 for Ultralight wipe')
|
||||
end
|
||||
end
|
||||
|
|
164
client/luascripts/hf_mfu_amiibo_restore.lua
Normal file
164
client/luascripts/hf_mfu_amiibo_restore.lua
Normal file
|
@ -0,0 +1,164 @@
|
|||
local cmds = require('commands')
|
||||
local getopt = require('getopt')
|
||||
local os = require('os')
|
||||
local io = require('io')
|
||||
local bin = require('bin')
|
||||
local utils = require('utils')
|
||||
local ansicolors = require('ansicolors')
|
||||
local amiibo_tools = require('amiibo_tools')
|
||||
|
||||
copyright = ''
|
||||
author = 'George Talusan'
|
||||
version = 'v0.0.1'
|
||||
desc = [[
|
||||
This script will try to restore a binary datadump of an Amiibo to a blank NTAG215.
|
||||
It will recalculate PWD and PACK if necessary, set the appropriate password and sector lock bytes.
|
||||
|
||||
NOTE: PyAmiibo must be installed. The helper script pyscripts/amiibo_change_uid.py depends on PyAmiibo.
|
||||
|
||||
YMMV if a non-blank NTAG215 is provided!
|
||||
]]
|
||||
example = [[
|
||||
1. script run hf_mfu_amiibo_restore
|
||||
2. script run hf_mfu_amiibo_restore -f myfile -k password
|
||||
]]
|
||||
usage = [[
|
||||
script run hf_mfu_amiibo_restore [-h] [-f <filename> -k <password>]
|
||||
]]
|
||||
arguments = [[
|
||||
-h : this help
|
||||
-f : filename for the datadump to read (bin)
|
||||
-k : password of blank NTAG 215 (use `hf mfu info` to find it)
|
||||
]]
|
||||
|
||||
local DEBUG = false -- the debug flag
|
||||
|
||||
local bxor = bit32.bxor
|
||||
local sub = string.sub
|
||||
local format = string.format
|
||||
|
||||
---
|
||||
-- A debug printout-function
|
||||
local function dbg(args)
|
||||
if not DEBUG then return end
|
||||
if type(args) == 'table' then
|
||||
local i = 1
|
||||
while result[i] do
|
||||
dbg(result[i])
|
||||
i = i+1
|
||||
end
|
||||
else
|
||||
print('###', args)
|
||||
end
|
||||
end
|
||||
---
|
||||
-- This is only meant to be used when errors occur
|
||||
local function oops(err)
|
||||
print('ERROR:', err)
|
||||
core.clearCommandBuffer()
|
||||
return nil, err
|
||||
end
|
||||
---
|
||||
-- Usage help
|
||||
local function help()
|
||||
print(copyright)
|
||||
print(author)
|
||||
print(version)
|
||||
print(desc)
|
||||
print(ansicolors.cyan..'Usage'..ansicolors.reset)
|
||||
print(usage)
|
||||
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
|
||||
print(arguments)
|
||||
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
|
||||
print(example)
|
||||
end
|
||||
--
|
||||
-- Exit message
|
||||
local function ExitMsg(msg)
|
||||
print( string.rep('--',20) )
|
||||
print( string.rep('--',20) )
|
||||
print(msg)
|
||||
print()
|
||||
end
|
||||
|
||||
local function main(args)
|
||||
print( string.rep('--',20) )
|
||||
print( string.rep('--',20) )
|
||||
|
||||
local result, err, hex
|
||||
local inputTemplate = 'dumpdata.bin'
|
||||
local password
|
||||
|
||||
for o, a in getopt.getopt(args, 'hf:k:') do
|
||||
if o == 'h' then return help() end
|
||||
if o == 'f' then inputTemplate = a end
|
||||
if o == 'k' then password = a end
|
||||
end
|
||||
|
||||
print(('Loading data from %s'):format(inputTemplate))
|
||||
hex, err = utils.ReadDumpFile(inputTemplate)
|
||||
if not hex then return oops(err) end
|
||||
|
||||
if not password or #password ~= 8 then
|
||||
return oops('Expecting 4 byte password (hint: use `hf mfu info` to get it)')
|
||||
end
|
||||
|
||||
-- chomp emu header
|
||||
if #hex == 1192 then
|
||||
hex = hex:sub(113)
|
||||
end
|
||||
|
||||
local amiibo_offset = 0
|
||||
local amiibo_info = hex:sub(amiibo_offset + 169, amiibo_offset + 169 + 15):lower()
|
||||
local amiibo_game = amiibo_info:sub(1, 3)
|
||||
local amiibo_type = amiibo_info:sub(7, 8)
|
||||
local amiibo_series = amiibo_info:sub(13, 14)
|
||||
|
||||
dbg('raw: '..ansicolors.green..amiibo_info..ansicolors.reset)
|
||||
print('game: '..ansicolors.green..amiibo_tools.db.game_series[("0x%s"):format(amiibo_game)]..ansicolors.reset)
|
||||
print('character: '..ansicolors.green..amiibo_tools.db.amiibos[("0x%s"):format(amiibo_info)].name..ansicolors.reset)
|
||||
print('type: '..ansicolors.green..amiibo_tools.db.types[("0x%s"):format(amiibo_type)]..ansicolors.reset)
|
||||
print('series: '..ansicolors.green..amiibo_tools.db.amiibo_series[("0x%s"):format(amiibo_series)]..ansicolors.reset)
|
||||
|
||||
local uid = core.ul_read_uid();
|
||||
if uid == nil then
|
||||
return oops("Can't read UID of NTAG215 card. Reposition card and try again.")
|
||||
end
|
||||
|
||||
local tmp = ('%s.bin'):format(os.tmpname())
|
||||
local amiibo_file = io.open(tmp, 'w+b')
|
||||
amiibo_file:write(bin.pack('H', hex))
|
||||
amiibo_file:close()
|
||||
local tmp2 = ('%s.bin'):format(os.tmpname())
|
||||
|
||||
print('generating new Amiibo binary for NTAG215 '..ansicolors.green..uid)
|
||||
core.clearCommandBuffer()
|
||||
core.console(('script run amiibo_change_uid %s %s %s %s'):format(uid, tmp, tmp2, core.search_file('resources/key_retail', '.bin')))
|
||||
|
||||
-- let's sanity check the output
|
||||
hex, err = utils.ReadDumpFile(tmp2)
|
||||
if not hex or #hex ~= 1080 then
|
||||
os.remove(tmp)
|
||||
os.remove(tmp2)
|
||||
return oops('There was a problem generating the output Amiibo')
|
||||
end
|
||||
|
||||
core.console(('hf mfu restore -f %s -k %s'):format(tmp2, password))
|
||||
|
||||
-- re-write some blocks because `hf mfu restore` won't write out blocks 0-3, and PyAmiibo won't give a PACK/PWD
|
||||
local pwd, pack = core.keygen_algo_b(uid)
|
||||
core.console(('hf mfu wrbl -b 3 -d F110FFEE -k %s'):format(password)) -- CC?
|
||||
core.console(('hf mfu wrbl -b 134 -d %04X0000 -k %s'):format(pack, password)) -- PACK/RFUI
|
||||
core.console(('hf mfu wrbl -b 133 -d %08X -k %s'):format(pwd, password)) -- PWD
|
||||
core.console(('hf mfu wrbl -b 131 -d 00000004 -k %08X'):format(pwd)) -- CFG0
|
||||
core.console(('hf mfu wrbl -b 132 -d 5F000000 -k %08X'):format(pwd)) -- CFG1
|
||||
|
||||
local lock_bytes = hex:sub(17, 24)
|
||||
dbg('lock_bytes: '..lock_bytes)
|
||||
core.console(('hf mfu wrbl -b 2 -d %s -k %08X'):format(lock_bytes, pwd)) -- BCC1/static lock
|
||||
core.console(('hf mfu wrbl -b 130 -d 01000FBD -k %08X'):format(pwd)) -- dynamic lock/RFUI
|
||||
|
||||
os.remove(tmp)
|
||||
os.remove(tmp2)
|
||||
end
|
||||
main(args)
|
152
client/luascripts/hf_mfu_amiibo_sim.lua
Normal file
152
client/luascripts/hf_mfu_amiibo_sim.lua
Normal file
|
@ -0,0 +1,152 @@
|
|||
local cmds = require('commands')
|
||||
local getopt = require('getopt')
|
||||
local bin = require('bin')
|
||||
local utils = require('utils')
|
||||
local ansicolors = require('ansicolors')
|
||||
local amiibo_tools = require('amiibo_tools')
|
||||
|
||||
copyright = ''
|
||||
author = 'George Talusan'
|
||||
version = 'v0.0.2'
|
||||
desc = [[
|
||||
This script will try to load a binary datadump of an Amiibo.
|
||||
It will recalculate PWD and PACK if necessary.
|
||||
]]
|
||||
example = [[
|
||||
1. script run hf_mfu_amiibo_sim
|
||||
2. script run hf_mfu_amiibo_sim -f myfile
|
||||
]]
|
||||
usage = [[
|
||||
script run hf_mfu_amiibo_sim [-h] [-f <filename>]
|
||||
]]
|
||||
arguments = [[
|
||||
-h : this help
|
||||
-f : filename for the datadump to read (bin)
|
||||
]]
|
||||
|
||||
local DEBUG = false -- the debug flag
|
||||
|
||||
local bxor = bit32.bxor
|
||||
local sub = string.sub
|
||||
local format = string.format
|
||||
|
||||
---
|
||||
-- A debug printout-function
|
||||
local function dbg(args)
|
||||
if not DEBUG then return end
|
||||
if type(args) == 'table' then
|
||||
local i = 1
|
||||
while result[i] do
|
||||
dbg(result[i])
|
||||
i = i+1
|
||||
end
|
||||
else
|
||||
print('###', args)
|
||||
end
|
||||
end
|
||||
---
|
||||
-- This is only meant to be used when errors occur
|
||||
local function oops(err)
|
||||
print('ERROR:', err)
|
||||
core.clearCommandBuffer()
|
||||
return nil, err
|
||||
end
|
||||
---
|
||||
-- Usage help
|
||||
local function help()
|
||||
print(copyright)
|
||||
print(author)
|
||||
print(version)
|
||||
print(desc)
|
||||
print(ansicolors.cyan..'Usage'..ansicolors.reset)
|
||||
print(usage)
|
||||
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
|
||||
print(arguments)
|
||||
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
|
||||
print(example)
|
||||
end
|
||||
--
|
||||
-- Exit message
|
||||
local function ExitMsg(msg)
|
||||
print( string.rep('--',20) )
|
||||
print( string.rep('--',20) )
|
||||
print(msg)
|
||||
print()
|
||||
end
|
||||
|
||||
local function LoadEmulator(uid, blocks)
|
||||
io.write('Sending Amiibo to emulator memory')
|
||||
local cmd, blockdata
|
||||
for i=0,148,1 do
|
||||
blockdata = blocks[i]
|
||||
io.write('.')
|
||||
io.flush()
|
||||
core.clearCommandBuffer()
|
||||
cmd = Command:newNG{cmd = cmds.CMD_HF_MIFARE_EML_MEMSET, data = ('%02x%02x%02x%s'):format(i, 1, 4, blockdata)}
|
||||
local err, msg = cmd:sendNG(true)
|
||||
if err == nil then return err, msg end
|
||||
end
|
||||
io.write('\n')
|
||||
end
|
||||
|
||||
local function main(args)
|
||||
print( string.rep('--',20) )
|
||||
print( string.rep('--',20) )
|
||||
|
||||
local result, err, hex
|
||||
local inputTemplate = 'dumpdata.bin'
|
||||
|
||||
for o, a in getopt.getopt(args, 'hf:u:') do
|
||||
if o == 'h' then return help() end
|
||||
if o == 'f' then inputTemplate = a end
|
||||
end
|
||||
|
||||
print(('Loading data from %s'):format(inputTemplate))
|
||||
hex, err = utils.ReadDumpFile(inputTemplate)
|
||||
if not hex then return oops(err) end
|
||||
|
||||
-- only deal with missing PWD and PACK, or with 56 emu hdr
|
||||
if #hex ~= 1064 and #hex ~= 1080 and #hex ~= 1192 then return oops('Expecting either a plain binary or emulator dump') end
|
||||
|
||||
local amiibo_offset = (#hex == 1064 or #hex == 1080) and 0 or 112
|
||||
local amiibo_info = hex:sub(amiibo_offset + 169, amiibo_offset + 169 + 15):lower()
|
||||
local amiibo_game = amiibo_info:sub(1, 3)
|
||||
local amiibo_type = amiibo_info:sub(7, 8)
|
||||
local amiibo_series = amiibo_info:sub(13, 14)
|
||||
|
||||
dbg('raw: '..ansicolors.green..amiibo_info..ansicolors.reset)
|
||||
print('game: '..ansicolors.green..amiibo_tools.db.game_series[("0x%s"):format(amiibo_game)]..ansicolors.reset)
|
||||
print('character: '..ansicolors.green..amiibo_tools.db.amiibos[("0x%s"):format(amiibo_info)].name..ansicolors.reset)
|
||||
print('type: '..ansicolors.green..amiibo_tools.db.types[("0x%s"):format(amiibo_type)]..ansicolors.reset)
|
||||
print('series: '..ansicolors.green..amiibo_tools.db.amiibo_series[("0x%s"):format(amiibo_series)]..ansicolors.reset)
|
||||
|
||||
local blocks = {}
|
||||
local blockindex = 0
|
||||
|
||||
-- add empty header if necessary
|
||||
if (#hex == 1064 or #hex == 1080) then
|
||||
for i = 0, 13, 1 do
|
||||
blocks[i] = '00000000'
|
||||
end
|
||||
blocks[2] = '00000086'
|
||||
blockindex = 14
|
||||
end
|
||||
for i = 1, #hex, 8 do
|
||||
blocks[blockindex] = hex:sub(i, i+7)
|
||||
blockindex = blockindex + 1
|
||||
end
|
||||
|
||||
-- force lock bytes, otherwise the Amiibo won't be recognized
|
||||
blocks[16] = blocks[16]:sub(1, 4)..'0FE0'
|
||||
|
||||
-- add PWD and PACK
|
||||
local uid = blocks[14]:sub(1, 6)..blocks[15]:sub(1, 8)
|
||||
blocks[147] = ("%08x"):format(bxor(bxor(tonumber(sub(uid, 2, 10), 16), tonumber(sub(uid, 6, 14), 16)), 0xaa55aa55))
|
||||
blocks[148] = "80800000"
|
||||
|
||||
err = LoadEmulator(uid, blocks)
|
||||
if err then return oops(err) end
|
||||
core.clearCommandBuffer()
|
||||
core.console(("hf mfu sim -t 7 -u %s"):format(uid))
|
||||
end
|
||||
main(args)
|
|
@ -6,20 +6,20 @@ local ansicolors = require('ansicolors')
|
|||
|
||||
copyright = ''
|
||||
author = "Iceman"
|
||||
version = 'v1.0.1'
|
||||
version = 'v1.0.2'
|
||||
desc = [[
|
||||
This script calculates mifare Ultralight-EV1 pwd based on uid diversification for an Italian ticketsystem
|
||||
Algo not found by me.
|
||||
]]
|
||||
example =[[
|
||||
-- if called without, it reads tag uid
|
||||
script run hf_mfu_uidkeycalc-italy
|
||||
script run hf_mfu_uidkeycalc_italy
|
||||
|
||||
--
|
||||
script run hf_mfu_uidkeycalc-italy -u 11223344556677
|
||||
script run hf_mfu_uidkeycalc_italy -u 11223344556677
|
||||
]]
|
||||
usage = [[
|
||||
script run hf_mfu_uidkeycalc-italy -h -u <uid> "
|
||||
script run hf_mfu_uidkeycalc_italy -h -u <uid> "
|
||||
]]
|
||||
arguments = [[
|
||||
-h : this help
|
171
client/luascripts/hf_ntag_dt.lua
Normal file
171
client/luascripts/hf_ntag_dt.lua
Normal file
|
@ -0,0 +1,171 @@
|
|||
local getopt = require('getopt')
|
||||
local ansicolors = require('ansicolors')
|
||||
|
||||
copyright = ''
|
||||
author = 'Shain Lakin'
|
||||
version = 'v1.0.0'
|
||||
desc =[[
|
||||
|
||||
This script modifies the DT NeXT implant (NTAG216) configuration pages.
|
||||
|
||||
- NeXT Defaults -
|
||||
|
||||
Default hf mfu info:
|
||||
----------------------------------------------------------------------
|
||||
[=] --- Tag Configuration
|
||||
[=] cfg0 [227/0xE3]: 04 00 00 E3
|
||||
[=] - strong modulation mode disabled
|
||||
[=] - page 227 and above need authentication
|
||||
[=] cfg1 [228/0xE4]: 00 05 00 00
|
||||
[=] - Unlimited password attempts
|
||||
[=] - NFC counter disabled
|
||||
[=] - NFC counter not protected
|
||||
[=] - user configuration writeable
|
||||
[=] - write access is protected with password
|
||||
[=] - 05, Virtual Card Type Identifier is default
|
||||
[=] PWD [229/0xE5]: 00 00 00 00 - (cannot be read)
|
||||
[=] PACK [230/0xE6]: 00 00 - (cannot be read)
|
||||
[=] RFU [230/0xE6]: 00 00 - (cannot be read)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Default blocks 0xE0 to 0xE6:
|
||||
-------------------------------------
|
||||
[=] 224/0xE0 | 00 00 00 00 | 0 | ....
|
||||
[=] 225/0xE1 | 4E 45 78 54 | 0 | NExT
|
||||
[=] 226/0xE2 | 00 00 7F BD | 0 | ....
|
||||
[=] 227/0xE3 | 04 00 00 E3 | 0 | ....
|
||||
[=] 228/0xE4 | 00 05 00 00 | 0 | ....
|
||||
[=] 229/0xE5 | 44 4E 47 52 | 0 | DNGR
|
||||
[=] 230/0xE6 | 00 00 00 00 | 0 | ....
|
||||
-------------------------------------
|
||||
]]
|
||||
|
||||
example =[[
|
||||
|
||||
Set a new password of SUDO using the default password of DNGR:
|
||||
|
||||
script run hf_ntag_dt -x pass -p DNGR -n SUDO
|
||||
|
||||
Enable password protection from hex block 04 onwards (User memory):
|
||||
|
||||
script run hf_ntag_dt -x protect -p DNGR -a 04
|
||||
|
||||
Enable password protection from hex block E3 onwards (Configuration Pages):
|
||||
|
||||
script run hf_ntag_dt -x protect -p DNGR -a E3
|
||||
|
||||
Disable password protection:
|
||||
|
||||
script run hf_ntag_dt -x protect -p DNGR -a FF
|
||||
|
||||
Enable the counter and enable read + write password protection on password protected pages
|
||||
(protected block start page specified using -x protect mode):
|
||||
|
||||
script run hf_ntag_dt -x conf -p DNGR -c enable -m rw
|
||||
|
||||
Disable the counter and enable write only password protection on password protected pages
|
||||
(protected block start specified using -x protect mode):
|
||||
|
||||
script run hf_ntag_dt -x conf -p DNGR -c disable -m w
|
||||
|
||||
]]
|
||||
usage = [[
|
||||
|
||||
script run hf_ntag_dt -x pass -p <password> -n <new_password>
|
||||
script run hf_ntag_dt -x protect -p <password> -a <auth0_block>
|
||||
script run hf_ntag_dt -x conf -p <password> -c <enable/disable> -m <r/rw>
|
||||
|
||||
]]
|
||||
arguments = [[
|
||||
-h this help
|
||||
-x mode (pass, protect, conf)
|
||||
-p password (ascii)
|
||||
-n new password (ascii)
|
||||
-a auth0 block (hex)
|
||||
-c counter (enable/disable)
|
||||
-m protection mode (r/rw)
|
||||
]]
|
||||
---
|
||||
--- Usage help
|
||||
local function help()
|
||||
print(copyright)
|
||||
print(author)
|
||||
print(version)
|
||||
print(desc)
|
||||
print(ansicolors.cyan..'Usage'..ansicolors.reset)
|
||||
print(usage)
|
||||
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
|
||||
print(arguments)
|
||||
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
|
||||
print(example)
|
||||
end
|
||||
---
|
||||
--- Print user message
|
||||
local function msg(msg)
|
||||
print( string.rep('--',20) )
|
||||
print('')
|
||||
print(msg)
|
||||
print('')
|
||||
print( string.rep('--',20) )
|
||||
end
|
||||
---
|
||||
--- String to hex function
|
||||
local function strhex(str)
|
||||
return (str:gsub(".", function(char) return string.format("%2x", char:byte()) end))
|
||||
end
|
||||
---
|
||||
-- Main
|
||||
local function main(args)
|
||||
|
||||
for o, a in getopt.getopt(args, 'b:m:c:a:p:x:n:h') do
|
||||
if o == 'm' then prot_mode = a end
|
||||
if o == 'c' then counter = a end
|
||||
if o == 'a' then auth0_block = a end
|
||||
if o == 'p' then passwd = strhex(a) end
|
||||
if o == 'x' then mode = a end
|
||||
if o == 'n' then new_pass = strhex(a) end
|
||||
if o == 'h' then return help() end
|
||||
end
|
||||
|
||||
if mode == 'pass' then
|
||||
command = 'hf mfu wrbl -b 229 -d '..new_pass..' -k '..passwd
|
||||
msg('Writing '..new_pass..' to PASSWD block (229/0xE5) : \n\n'..command)
|
||||
core.console(command)
|
||||
command = 'hf mfu rdbl -b 0 -k '..new_pass..''
|
||||
msg('Verifying password is correctly set : \n\n'..command)
|
||||
core.console(command)
|
||||
elseif mode == 'conf' then
|
||||
if counter == 'enable' then
|
||||
if prot_mode == 'r' then
|
||||
command = 'hf mfu wrbl -b 228 -d 10050000 -k '..passwd
|
||||
msg('Enabling counter and setting write access to protected pages as password protected : \n\n'..command)
|
||||
core.console(command)
|
||||
elseif prot_mode == 'rw' then
|
||||
command = 'hf mfu wrbl -b 228 -d 90050000 -k '..passwd
|
||||
msg('Enabling counter and setting read/write access to protected pages as password protected : \n\n'..command)
|
||||
core.console(command)
|
||||
end
|
||||
elseif counter == 'disable' then
|
||||
if prot_mode == 'w' then
|
||||
command = 'hf mfu wrbl -b 228 -d 00050000 -k '..passwd
|
||||
msg('Disabling counter and setting write password protection on protected pages : \n\n'..command)
|
||||
core.console(command)
|
||||
elseif prot_mode == 'rw' then
|
||||
command = 'hf mfu wrbl -b 228 -d 80050000 -k '..passwd
|
||||
msg('Disabling counter and setting read/write password protection on protected pages : \n\n'..command)
|
||||
core.console(command)
|
||||
end
|
||||
end
|
||||
elseif mode == 'protect' then
|
||||
command = 'hf mfu wrbl -k '..passwd..' -b 227 -d 040000'..auth0_block
|
||||
msg('Enabling password protection from block '..auth0_block..' onwards : \n\n'..command)
|
||||
core.console(command)
|
||||
else
|
||||
return print(usage)
|
||||
end
|
||||
|
||||
if command == '' then return print(usage) end
|
||||
|
||||
|
||||
end
|
||||
main(args)
|
|
@ -6,7 +6,7 @@ local ac = require('ansicolors')
|
|||
|
||||
copyright = ''
|
||||
author = "Christian Herrmann"
|
||||
version = 'v1.0.0'
|
||||
version = 'v1.0.1'
|
||||
desc = [[
|
||||
This script loads a json format file, with the field "data" and a hexbyte array of data. Ie t55x7 dump,
|
||||
it tries to identify which system based on block1, and detect block0 settings.
|
||||
|
@ -16,7 +16,7 @@ example = [[
|
|||
script run lf_ident_json -i lf_t55xx.json
|
||||
]]
|
||||
usage = [[
|
||||
script run lf_en4100_bulk.lua [-h] [-c] [-p password] [-s <start cn>] [-v]
|
||||
script run lf_ident_json.lua [-h] [-c] [-p password] [-s <start cn>] [-v]
|
||||
]]
|
||||
arguments = [[
|
||||
-h : this help
|
||||
|
|
44
client/pyscripts/amiibo_change_uid.py
Normal file
44
client/pyscripts/amiibo_change_uid.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
# Requirements:
|
||||
# python3 -m pip install pyamiibo
|
||||
|
||||
import sys
|
||||
from amiibo import AmiiboDump, AmiiboMasterKey
|
||||
|
||||
def main():
|
||||
if(len(sys.argv) != 5):
|
||||
print("""
|
||||
\t{0} - helper script for integrating with PyAmiibo
|
||||
|
||||
Usage: {0} <uid> <infile> <outfile> <keyfile>
|
||||
|
||||
Example:
|
||||
|
||||
\t{0} 04123456789ABC my_amiibo_original.bin my_amiibo_with_new_uid.bin keyfile.bin
|
||||
|
||||
\n""".format(sys.argv[0]))
|
||||
return 1
|
||||
|
||||
uid = sys.argv[1]
|
||||
infile = sys.argv[2]
|
||||
outfile = sys.argv[3]
|
||||
keyfile = sys.argv[4]
|
||||
|
||||
if len(uid) != 14:
|
||||
print('expecting 7 byte UID')
|
||||
return 1
|
||||
|
||||
with open(keyfile, 'rb') as keybin:
|
||||
master_key = AmiiboMasterKey.from_combined_bin(keybin.read())
|
||||
|
||||
with open(infile, 'rb') as fin, open(outfile, 'wb') as fout:
|
||||
dump = AmiiboDump(master_key, fin.read(), is_locked=True)
|
||||
dump.unlock()
|
||||
dump.uid_hex = uid
|
||||
dump.lock()
|
||||
fout.write(dump.data)
|
||||
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
|
|
@ -1247,6 +1247,14 @@
|
|||
"Description": "PIV End Point Applet. Last 2 bytes designate version",
|
||||
"Type": ""
|
||||
},
|
||||
{
|
||||
"AID": "A000000308000010000100",
|
||||
"Vendor": "National Institute of Standards and Technology",
|
||||
"Country": "United States",
|
||||
"Name": "Personal Identity Verification (PIV) / ID-ONE PIV BIO",
|
||||
"Description": "PIV End Point Applet. Last 2 bytes designate version",
|
||||
"Type": ""
|
||||
},
|
||||
{
|
||||
"AID": "A00000031510100528",
|
||||
"Vendor": "Currence Holding/PIN BV",
|
||||
|
@ -2206,5 +2214,61 @@
|
|||
"Name": "SL Resekort",
|
||||
"Description": "transport card",
|
||||
"Type": "transport"
|
||||
},
|
||||
{
|
||||
"AID": "4F53452E5641532E3031",
|
||||
"Vendor": "Apple, Google",
|
||||
"Country": "",
|
||||
"Name": "Value-Added Services (OSE.VAS.01)",
|
||||
"Description": "Used by Apple VAS and Google SmartTap",
|
||||
"Type": "loyalty"
|
||||
},
|
||||
{
|
||||
"AID": "A000000476D0000101",
|
||||
"Vendor": "Google",
|
||||
"Country": "",
|
||||
"Name": "Google SmartTap 1.3 (Deprecated)",
|
||||
"Description": "",
|
||||
"Type": "loyalty"
|
||||
},
|
||||
{
|
||||
"AID": "A000000476D0000111",
|
||||
"Vendor": "Google",
|
||||
"Country": "",
|
||||
"Name": "Google SmartTap 2.0",
|
||||
"Description": "",
|
||||
"Type": "loyalty"
|
||||
},
|
||||
{
|
||||
"AID": "A0000002480400",
|
||||
"Vendor": "ISO/IEC JTC1/SC17",
|
||||
"Country": "",
|
||||
"Name": "Personal identification (mDL)",
|
||||
"Description": "ISO/IEC 18013-5:2021 compliant Mobile driving licence (mDL) application.",
|
||||
"Type": "identity"
|
||||
},
|
||||
{
|
||||
"AID": "A000000676",
|
||||
"Vendor": "Blackboard",
|
||||
"Country": "United States",
|
||||
"Name": "Student ID",
|
||||
"Description": "Student ID cards",
|
||||
"Type": "identity"
|
||||
},
|
||||
{
|
||||
"AID": "A000000809434343444B467631",
|
||||
"Vendor": "Car Connectivity Consortium (CCC)",
|
||||
"Country": "",
|
||||
"Name": "Digital Car Key",
|
||||
"Description": "",
|
||||
"Type": "access"
|
||||
},
|
||||
{
|
||||
"AID": "A0000008580101",
|
||||
"Vendor": "Apple",
|
||||
"Country": "",
|
||||
"Name": "Apple Home Key",
|
||||
"Description": "NFC Home Key for select HomeKit-compatible locks",
|
||||
"Type": "access"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -6097,6 +6097,41 @@
|
|||
"service_provider": "CDVI",
|
||||
"system_integrator": "CDVI"
|
||||
},
|
||||
{
|
||||
"application": "(access control and security) VIGIK",
|
||||
"company": "CDV International",
|
||||
"mad": "0x4914",
|
||||
"service_provider": "CDVI",
|
||||
"system_integrator": "CDVI"
|
||||
},
|
||||
{
|
||||
"application": "(access control and security) VIGIK",
|
||||
"company": "CDV International",
|
||||
"mad": "0x4915",
|
||||
"service_provider": "CDVI",
|
||||
"system_integrator": "CDVI"
|
||||
},
|
||||
{
|
||||
"application": "(access control and security) VIGIK",
|
||||
"company": "CDV International",
|
||||
"mad": "0x4916",
|
||||
"service_provider": "CDVI",
|
||||
"system_integrator": "CDVI"
|
||||
},
|
||||
{
|
||||
"application": "(access control and security) VIGIK",
|
||||
"company": "CDV International",
|
||||
"mad": "0x4917",
|
||||
"service_provider": "CDVI",
|
||||
"system_integrator": "CDVI"
|
||||
},
|
||||
{
|
||||
"application": "(access control and security) VIGIK",
|
||||
"company": "CDV International",
|
||||
"mad": "0x4918",
|
||||
"service_provider": "CDVI",
|
||||
"system_integrator": "CDVI"
|
||||
},
|
||||
{
|
||||
"application": "(access control and security) VIGIK",
|
||||
"company": "NORALSY",
|
||||
|
|
BIN
client/resources/sim013.bin
Normal file
BIN
client/resources/sim013.bin
Normal file
Binary file not shown.
1
client/resources/sim013.sha512.txt
Normal file
1
client/resources/sim013.sha512.txt
Normal file
|
@ -0,0 +1 @@
|
|||
3bb6cbd893ce07720d8514d00706b230b4026a54d6c4dc068ca294beea3f3735c75dae65bc153f573b7b891753c85860f6427fb0ad7edb804d58925c50d1fc76 *sim013.bin
|
|
@ -17,17 +17,17 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "cipursecore.h"
|
||||
#include <string.h> // memcpy memset
|
||||
|
||||
#include "commonutil.h" // ARRAYLEN
|
||||
#include "comms.h" // DropField
|
||||
#include "util_posix.h" // msleep
|
||||
#include <string.h> // memcpy memset
|
||||
#include "commonutil.h" // ARRAYLEN
|
||||
#include "comms.h" // DropField
|
||||
#include "util_posix.h" // msleep
|
||||
#include "cmdhf14a.h"
|
||||
#include "../emv/emvcore.h"
|
||||
#include "../emv/emvjson.h"
|
||||
#include "../iso7816/apduinfo.h" // sAPDU_t
|
||||
#include "../iso7816/apduinfo.h" // sAPDU_t
|
||||
#include "ui.h"
|
||||
#include "util.h"
|
||||
#include "protocols.h" // ISO7816 APDU return codes
|
||||
|
||||
// context for secure channel
|
||||
CipurseContext_t cipurseContext;
|
||||
|
@ -112,7 +112,7 @@ static int CIPURSEExchangeEx(bool activate_field, bool leave_field_on, sAPDU_t a
|
|||
*sw = isw;
|
||||
}
|
||||
|
||||
if (isw != 0x9000) {
|
||||
if (isw != ISO7816_OK) {
|
||||
if (GetAPDULogging()) {
|
||||
if (*sw >> 8 == 0x61) {
|
||||
PrintAndLogEx(ERR, "APDU chaining len:%02x -->", *sw & 0xff);
|
||||
|
@ -255,7 +255,7 @@ bool CIPURSEChannelAuthenticate(uint8_t keyindex, uint8_t *key, bool verbose) {
|
|||
|
||||
// authenticate
|
||||
res = CIPURSEMutualAuthenticate(keyindex, authparams, sizeof(authparams), buf, sizeof(buf), &len, &sw);
|
||||
if (res != 0 || sw != 0x9000 || len != 16) {
|
||||
if (res != 0 || sw != ISO7816_OK || len != 16) {
|
||||
if (sw == 0x6988) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(WARNING, "Authentication ( " _RED_("fail") " ). Wrong key");
|
||||
|
@ -412,10 +412,14 @@ void CIPURSEPrintDGI(uint8_t *dgi, size_t dgilen) {
|
|||
}
|
||||
|
||||
for (int i = 0; i < len / 20; i++) {
|
||||
PrintAndLogEx(INFO, "Key[%d]............ %s", i + 1, sprint_hex_inrow(&dgi[3 + i * 20 + 0], 16));
|
||||
PrintAndLogEx(INFO, " Additional info.. 0x%02x", dgi[3 + i * 20 + 16]);
|
||||
|
||||
uint8_t kvv[CIPURSE_KVV_LENGTH] = {0};
|
||||
CipurseCGetKVV(&dgi[3 + i * 20 + 0], kvv);
|
||||
uint8_t aeskey[16] = {0};
|
||||
memcpy(aeskey, &dgi[3 + i * 20 + 0], sizeof(aeskey));
|
||||
|
||||
PrintAndLogEx(INFO, "Key[%d]............ %s", i + 1, sprint_hex_inrow(aeskey, sizeof(aeskey)));
|
||||
PrintAndLogEx(INFO, " Additional info.. 0x%02x", dgi[3 + i * 20 + 16]);
|
||||
CipurseCGetKVV(aeskey, kvv);
|
||||
bool kvvvalid = (memcmp(kvv, &dgi[3 + i * 20 + 17], 3) == 0);
|
||||
PrintAndLogEx(INFO, " KVV.............. %s (%s)", sprint_hex_inrow(&dgi[3 + i * 20 + 17], 3), (kvvvalid) ? _GREEN_("valid") : _RED_("invalid"));
|
||||
}
|
||||
|
|
|
@ -424,8 +424,8 @@ static int CmdrevengSearch(const char *Cmd) {
|
|||
uint8_t width[NMODELS] = {0};
|
||||
int count = 0;
|
||||
|
||||
char result[30];
|
||||
char revResult[30];
|
||||
char result[50 + 1] = {0};
|
||||
char revResult[50 + 1] = {0};
|
||||
int ans = GetModels(Models, &count, width);
|
||||
bool found = false;
|
||||
if (!ans) {
|
||||
|
@ -461,7 +461,7 @@ static int CmdrevengSearch(const char *Cmd) {
|
|||
continue;
|
||||
}
|
||||
|
||||
memset(result, 0, 30);
|
||||
memset(result, 0, sizeof(result));
|
||||
char *inCRC = calloc(crcChars + 1, sizeof(char));
|
||||
if (inCRC == NULL) {
|
||||
return 0;
|
||||
|
|
|
@ -35,6 +35,9 @@
|
|||
#include "cmdlft55xx.h" // print...
|
||||
#include "crypto/asn1utils.h" // ASN1 decode / print
|
||||
#include "cmdflashmemspiffs.h" // SPIFFS flash memory download
|
||||
#include "mbedtls/bignum.h" // big num
|
||||
#include "mbedtls/entropy.h" //
|
||||
#include "mbedtls/ctr_drbg.h" // random generator
|
||||
|
||||
uint8_t g_DemodBuffer[MAX_DEMOD_BUF_LEN];
|
||||
size_t g_DemodBufferLen = 0;
|
||||
|
@ -894,7 +897,7 @@ static int CmdAutoCorr(const char *Cmd) {
|
|||
}
|
||||
|
||||
if (window >= g_GraphTraceLen) {
|
||||
PrintAndLogEx(WARNING, "window must be smaller than trace (" _YELLOW_("%zu") " samples)", g_GraphTraceLen);
|
||||
PrintAndLogEx(WARNING, "window must be smaller than trace ( " _YELLOW_("%zu") " samples )", g_GraphTraceLen);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
|
@ -1230,7 +1233,7 @@ int FSKrawDemod(uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, bo
|
|||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, _YELLOW_("%s") " decoded bitstream", GetFSKType(fchigh, fclow, invert));
|
||||
PrintAndLogEx(INFO, "-----------------------");
|
||||
printDemodBuff(0, false, invert, false);
|
||||
printDemodBuff(0, false, false, false);
|
||||
}
|
||||
goto out;
|
||||
} else {
|
||||
|
@ -1779,7 +1782,7 @@ int getSamplesEx(uint32_t start, uint32_t end, bool verbose, bool ignore_lf_conf
|
|||
|
||||
BitstreamOut_t bout = { got, bits_per_sample * n, 0};
|
||||
uint32_t j = 0;
|
||||
for (j = 0; j * bits_per_sample < n * 8 && j < n; j++) {
|
||||
for (j = 0; j * bits_per_sample < n * 8 && j * bits_per_sample < MAX_GRAPH_TRACE_LEN * 8; j++) {
|
||||
uint8_t sample = getByte(bits_per_sample, &bout);
|
||||
g_GraphBuffer[j] = ((int) sample) - 127;
|
||||
}
|
||||
|
@ -1817,7 +1820,7 @@ static int CmdSamples(const char *Cmd) {
|
|||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_int0("n", NULL, "<dec>", "num of samples (512 - 40000)"),
|
||||
arg_lit0("v", "verbose", "verbose"),
|
||||
arg_lit0("v", "verbose", "verbose output"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -2032,6 +2035,8 @@ static int CmdLoad(const char *Cmd) {
|
|||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("f", "file", "<fn>", "file to load"),
|
||||
arg_lit0("b", "bin", "binary file"),
|
||||
arg_lit0("n", "no-fix", "Load data from file without any transformations"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -2039,6 +2044,8 @@ static int CmdLoad(const char *Cmd) {
|
|||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||
bool is_bin = arg_get_lit(ctx, 2);
|
||||
bool nofix = arg_get_lit(ctx, 3);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
char *path = NULL;
|
||||
|
@ -2048,8 +2055,13 @@ static int CmdLoad(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
FILE *f = fopen(path, "r");
|
||||
if (!f) {
|
||||
FILE *f;
|
||||
if (is_bin)
|
||||
f = fopen(path, "rb");
|
||||
else
|
||||
f = fopen(path, "r");
|
||||
|
||||
if (f == NULL) {
|
||||
PrintAndLogEx(WARNING, "couldn't open '%s'", path);
|
||||
free(path);
|
||||
return PM3_EFILE;
|
||||
|
@ -2057,24 +2069,38 @@ static int CmdLoad(const char *Cmd) {
|
|||
free(path);
|
||||
|
||||
g_GraphTraceLen = 0;
|
||||
char line[80];
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
g_GraphBuffer[g_GraphTraceLen] = atoi(line);
|
||||
g_GraphTraceLen++;
|
||||
|
||||
if (g_GraphTraceLen >= MAX_GRAPH_TRACE_LEN)
|
||||
break;
|
||||
if (is_bin) {
|
||||
uint8_t val[2];
|
||||
while (fread(val, 1, 1, f)) {
|
||||
g_GraphBuffer[g_GraphTraceLen] = val[0] - 127;
|
||||
g_GraphTraceLen++;
|
||||
|
||||
if (g_GraphTraceLen >= MAX_GRAPH_TRACE_LEN)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
char line[80];
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
g_GraphBuffer[g_GraphTraceLen] = atoi(line);
|
||||
g_GraphTraceLen++;
|
||||
|
||||
if (g_GraphTraceLen >= MAX_GRAPH_TRACE_LEN)
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
PrintAndLogEx(SUCCESS, "loaded " _YELLOW_("%zu") " samples", g_GraphTraceLen);
|
||||
|
||||
uint8_t bits[g_GraphTraceLen];
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
if (nofix == false) {
|
||||
uint8_t bits[g_GraphTraceLen];
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
|
||||
removeSignalOffset(bits, size);
|
||||
setGraphBuf(bits, size);
|
||||
computeSignalProperties(bits, size);
|
||||
removeSignalOffset(bits, size);
|
||||
setGraphBuf(bits, size);
|
||||
computeSignalProperties(bits, size);
|
||||
}
|
||||
|
||||
setClockGrid(0, 0);
|
||||
g_DemodBufferLen = 0;
|
||||
|
@ -2402,6 +2428,19 @@ static int CmdZerocrossings(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static bool data_verify_hex(uint8_t *d, size_t n) {
|
||||
if (d == NULL)
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (isxdigit(d[i]) == false) {
|
||||
PrintAndLogEx(ERR, "Non hex digit found");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Utility for conversion via cmdline.
|
||||
* @param Cmd
|
||||
|
@ -2478,12 +2517,8 @@ static int Cmdhex2bin(const char *Cmd) {
|
|||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
for (int i = 0; i < dlen; i++) {
|
||||
char x = data[i];
|
||||
if (isxdigit(x) == false) {
|
||||
PrintAndLogEx(ERR, "Non hex digit found");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
if (data_verify_hex((uint8_t *)data, dlen) == false) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "" NOLF);
|
||||
|
@ -2744,13 +2779,19 @@ static int print_modulation(lf_modulation_t b) {
|
|||
|
||||
static int try_detect_modulation(void) {
|
||||
|
||||
lf_modulation_t tests[6];
|
||||
#define LF_NUM_OF_TESTS 6
|
||||
|
||||
lf_modulation_t tests[LF_NUM_OF_TESTS];
|
||||
for (int i = 0; i < ARRAYLEN(tests); i++) {
|
||||
memset(&tests[i], 0, sizeof(lf_modulation_t));
|
||||
}
|
||||
|
||||
int clk = 0, firstClockEdge = 0;
|
||||
uint8_t hits = 0, ans = 0;
|
||||
uint8_t fc1 = 0, fc2 = 0;
|
||||
uint8_t hits = 0, fc1 = 0, fc2 = 0;
|
||||
bool st = false;
|
||||
|
||||
ans = fskClocks(&fc1, &fc2, (uint8_t *)&clk, &firstClockEdge);
|
||||
|
||||
uint8_t ans = fskClocks(&fc1, &fc2, (uint8_t *)&clk, &firstClockEdge);
|
||||
|
||||
if (ans && ((fc1 == 10 && fc2 == 8) || (fc1 == 8 && fc2 == 5))) {
|
||||
|
||||
|
@ -2874,8 +2915,8 @@ static int CmdAsn1Decoder(const char *Cmd) {
|
|||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
int dlen = 256;
|
||||
uint8_t data[256];
|
||||
int dlen = 2048;
|
||||
uint8_t data[2048];
|
||||
CLIGetHexWithReturn(ctx, 1, data, &dlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
|
@ -2886,8 +2927,6 @@ static int CmdAsn1Decoder(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int CmdDiff(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
|
@ -3034,8 +3073,8 @@ static int CmdDiff(const char *Cmd) {
|
|||
}
|
||||
*/
|
||||
|
||||
size_t n = (datalenA > datalenB) ? datalenB : datalenA;
|
||||
PrintAndLogEx(DEBUG, "data len: %zu A %zu B %zu", n, datalenA, datalenB);
|
||||
size_t biggest = (datalenA > datalenB) ? datalenA : datalenB;
|
||||
PrintAndLogEx(DEBUG, "data len: %zu A %zu B %zu", biggest, datalenA, datalenB);
|
||||
|
||||
if (inA == NULL)
|
||||
PrintAndLogEx(INFO, "inA null");
|
||||
|
@ -3062,102 +3101,68 @@ static int CmdDiff(const char *Cmd) {
|
|||
char line[880] = {0};
|
||||
|
||||
// print data diff loop
|
||||
int i;
|
||||
for (i = 0; i < n; i += width) {
|
||||
for (int i = 0 ; i < biggest ; i += width) {
|
||||
char dlnA[240] = {0};
|
||||
char dlnB[240] = {0};
|
||||
char dlnAii[180] = {0};
|
||||
char dlnBii[180] = {0};
|
||||
|
||||
memset(line, 0, sizeof(line));
|
||||
memset(dlnA, 0, sizeof(dlnA));
|
||||
memset(dlnB, 0, sizeof(dlnB));
|
||||
memset(dlnAii, 0, sizeof(dlnAii));
|
||||
memset(dlnBii, 0, sizeof(dlnBii));
|
||||
|
||||
int diff = memcmp(inA + i, inB + i, width);
|
||||
for (int j = i; j < i + width; j++) {
|
||||
int dlnALen = strlen(dlnA);
|
||||
int dlnBLen = strlen(dlnB);
|
||||
int dlnAiiLen = strlen(dlnAii);
|
||||
int dlnBiiLen = strlen(dlnBii);
|
||||
|
||||
// if ok, just print
|
||||
if (diff == 0) {
|
||||
hex_to_buffer((uint8_t *)line, inA + i, width, width, 0, 1, true);
|
||||
ascii_to_buffer((uint8_t *)(line + strlen(line)), inA + i, width, width, 0);
|
||||
strcat(line + strlen(line), " | ");
|
||||
hex_to_buffer((uint8_t *)(line + strlen(line)), inB + i, width, width, 0, 1, true);
|
||||
ascii_to_buffer((uint8_t *)(line + strlen(line)), inB + i, width, width, 0);
|
||||
} else {
|
||||
|
||||
char dlnA[240] = {0};
|
||||
char dlnB[240] = {0};
|
||||
char dlnAii[180] = {0};
|
||||
char dlnBii[180] = {0};
|
||||
|
||||
memset(dlnA, 0, sizeof(dlnA));
|
||||
memset(dlnB, 0, sizeof(dlnB));
|
||||
memset(dlnAii, 0, sizeof(dlnAii));
|
||||
memset(dlnBii, 0, sizeof(dlnBii));
|
||||
|
||||
// if diff, time to find it
|
||||
for (int j = i; j < (i + width); j++) {
|
||||
|
||||
char ca = inA[j];
|
||||
char cb = inB[j];
|
||||
|
||||
int dlnALen = strlen(dlnA);
|
||||
int dlnBLen = strlen(dlnB);
|
||||
int dlnAiiLen = strlen(dlnAii);
|
||||
int dlnBiiLen = strlen(dlnBii);
|
||||
|
||||
if (inA[j] != inB[j]) {
|
||||
|
||||
// diff / add colors
|
||||
snprintf(dlnA + dlnALen, sizeof(dlnA) - dlnALen, _GREEN_("%02X "), inA[j]);
|
||||
snprintf(dlnB + dlnBLen, sizeof(dlnB) - dlnBLen, _RED_("%02X "), inB[j]);
|
||||
snprintf(dlnAii + dlnAiiLen, sizeof(dlnAii) - dlnAiiLen, _GREEN_("%c"), ((ca < 32) || (ca == 127)) ? '.' : ca);
|
||||
snprintf(dlnBii + dlnBiiLen, sizeof(dlnBii) - dlnBiiLen, _RED_("%c"), ((cb < 32) || (cb == 127)) ? '.' : cb);
|
||||
|
||||
} else {
|
||||
// normal
|
||||
snprintf(dlnA + dlnALen, sizeof(dlnA) - dlnALen, "%02X ", inA[j]);
|
||||
snprintf(dlnB + dlnBLen, sizeof(dlnB) - dlnBLen, "%02X ", inB[j]);
|
||||
snprintf(dlnAii + dlnAiiLen, sizeof(dlnAii) - dlnAiiLen, "%c", ((ca < 32) || (ca == 127)) ? '.' : ca);
|
||||
snprintf(dlnBii + dlnBiiLen, sizeof(dlnBii) - dlnBiiLen, "%c", ((cb < 32) || (cb == 127)) ? '.' : cb);
|
||||
}
|
||||
//both files ended
|
||||
if (j >= datalenA && j >= datalenB) {
|
||||
snprintf(dlnA + dlnALen, sizeof(dlnA) - dlnALen, "-- ");
|
||||
snprintf(dlnAii + dlnAiiLen, sizeof(dlnAii) - dlnAiiLen, ".") ;
|
||||
snprintf(dlnB + dlnBLen, sizeof(dlnB) - dlnBLen, "-- ");
|
||||
snprintf(dlnBii + dlnBiiLen, sizeof(dlnBii) - dlnBiiLen, ".") ;
|
||||
continue ;
|
||||
}
|
||||
|
||||
char ca, cb;
|
||||
|
||||
if (j >= datalenA) {
|
||||
// file A ended. print B without colors
|
||||
cb = inB[j];
|
||||
snprintf(dlnA + dlnALen, sizeof(dlnA) - dlnALen, "-- ");
|
||||
snprintf(dlnAii + dlnAiiLen, sizeof(dlnAii) - dlnAiiLen, ".") ;
|
||||
snprintf(dlnB + dlnBLen, sizeof(dlnB) - dlnBLen, "%02X ", inB[j]);
|
||||
snprintf(dlnBii + dlnBiiLen, sizeof(dlnBii) - dlnBiiLen, "%c", ((cb < 32) || (cb == 127)) ? '.' : cb);
|
||||
continue ;
|
||||
}
|
||||
ca = inA[j];
|
||||
if (j >= datalenB) {
|
||||
// file B ended. print A without colors
|
||||
snprintf(dlnA + dlnALen, sizeof(dlnA) - dlnALen, "%02X ", inA[j]);
|
||||
snprintf(dlnAii + dlnAiiLen, sizeof(dlnAii) - dlnAiiLen, "%c", ((ca < 32) || (ca == 127)) ? '.' : ca);
|
||||
snprintf(dlnB + dlnBLen, sizeof(dlnB) - dlnBLen, "-- ");
|
||||
snprintf(dlnBii + dlnBiiLen, sizeof(dlnBii) - dlnBiiLen, ".") ;
|
||||
continue ;
|
||||
}
|
||||
cb = inB[j];
|
||||
if (inA[j] != inB[j]) {
|
||||
// diff / add colors
|
||||
snprintf(dlnA + dlnALen, sizeof(dlnA) - dlnALen, _GREEN_("%02X "), inA[j]);
|
||||
snprintf(dlnB + dlnBLen, sizeof(dlnB) - dlnBLen, _RED_("%02X "), inB[j]);
|
||||
snprintf(dlnAii + dlnAiiLen, sizeof(dlnAii) - dlnAiiLen, _GREEN_("%c"), ((ca < 32) || (ca == 127)) ? '.' : ca);
|
||||
snprintf(dlnBii + dlnBiiLen, sizeof(dlnBii) - dlnBiiLen, _RED_("%c"), ((cb < 32) || (cb == 127)) ? '.' : cb);
|
||||
} else {
|
||||
// normal
|
||||
snprintf(dlnA + dlnALen, sizeof(dlnA) - dlnALen, "%02X ", inA[j]);
|
||||
snprintf(dlnB + dlnBLen, sizeof(dlnB) - dlnBLen, "%02X ", inB[j]);
|
||||
snprintf(dlnAii + dlnAiiLen, sizeof(dlnAii) - dlnAiiLen, "%c", ((ca < 32) || (ca == 127)) ? '.' : ca);
|
||||
snprintf(dlnBii + dlnBiiLen, sizeof(dlnBii) - dlnBiiLen, "%c", ((cb < 32) || (cb == 127)) ? '.' : cb);
|
||||
}
|
||||
snprintf(line, sizeof(line), "%s%s | %s%s", dlnA, dlnAii, dlnB, dlnBii);
|
||||
}
|
||||
PrintAndLogEx(INFO, "%03X | %s", i, line);
|
||||
}
|
||||
|
||||
// mod
|
||||
|
||||
|
||||
// print different length
|
||||
bool tallestA = (datalenA > datalenB);
|
||||
if (tallestA) {
|
||||
n = datalenA;
|
||||
} else {
|
||||
n = datalenB;
|
||||
}
|
||||
|
||||
// print data diff loop
|
||||
for (; i < n; i += width) {
|
||||
|
||||
memset(line, 0, sizeof(line));
|
||||
|
||||
if (tallestA) {
|
||||
hex_to_buffer((uint8_t *)line, inA + i, width, width, 0, 1, true);
|
||||
ascii_to_buffer((uint8_t *)(line + strlen(line)), inA + i, width, width, 0);
|
||||
strcat(line + strlen(line), " | ");
|
||||
for (int j = 0; j < width; j++) {
|
||||
strcat(line + strlen(line), "-- ");
|
||||
}
|
||||
for (int j = 0; j < width; j++) {
|
||||
strcat(line + strlen(line), ".");
|
||||
}
|
||||
} else {
|
||||
|
||||
for (int j = 0; j < width; j++) {
|
||||
strcat(line + strlen(line), "-- ");
|
||||
}
|
||||
for (int j = 0; j < width; j++) {
|
||||
strcat(line + strlen(line), ".");
|
||||
}
|
||||
strcat(line + strlen(line), " | ");
|
||||
hex_to_buffer((uint8_t *)(line + strlen(line)), inB + i, width, width, 0, 1, true);
|
||||
ascii_to_buffer((uint8_t *)(line + strlen(line)), inB + i, width, width, 0);
|
||||
}
|
||||
snprintf(line, sizeof(line), "%s%s | %s%s", dlnA, dlnAii, dlnB, dlnBii);
|
||||
|
||||
PrintAndLogEx(INFO, "%03X | %s", i, line);
|
||||
}
|
||||
|
@ -3171,6 +3176,129 @@ static int CmdDiff(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdNumCon(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "data num",
|
||||
"Function takes a decimal or hexdecimal number and print it in decimal/hex/binary\n"
|
||||
"Will print message if number is a prime number\n",
|
||||
"data num --dec 2023\n"
|
||||
"data num --hex 0x1000\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0(NULL, "dec", "<dec>", "decimal value"),
|
||||
arg_str0(NULL, "hex", "<hex>", "hexadecimal value"),
|
||||
arg_str0(NULL, "bin", "<bin>", "binary value"),
|
||||
arg_lit0("i", NULL, "print inverted value"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
int dlen = 256;
|
||||
char dec[256];
|
||||
memset(dec, 0, sizeof(dec));
|
||||
int res = CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)dec, sizeof(dec), &dlen);
|
||||
|
||||
|
||||
int hlen = 256;
|
||||
char hex[256];
|
||||
memset(hex, 0, sizeof(hex));
|
||||
res = CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)hex, sizeof(hex), &hlen);
|
||||
|
||||
int blen = 256;
|
||||
char bin[256];
|
||||
memset(bin, 0, sizeof(bin));
|
||||
res = CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)bin, sizeof(bin), &blen);
|
||||
|
||||
bool shall_invert = arg_get_lit(ctx, 4);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// sanity checks
|
||||
if (res) {
|
||||
PrintAndLogEx(FAILED, "Error parsing bytes");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
// results for MPI actions
|
||||
bool ret = false;
|
||||
|
||||
// container of big number
|
||||
mbedtls_mpi N;
|
||||
mbedtls_mpi_init(&N);
|
||||
|
||||
|
||||
// hex
|
||||
if (hlen > 0) {
|
||||
if (data_verify_hex((uint8_t *)hex, hlen) == false) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16, hex));
|
||||
}
|
||||
|
||||
// decimal
|
||||
if (dlen > 0) {
|
||||
// should have decimal string check here too
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 10, dec));
|
||||
}
|
||||
|
||||
// binary
|
||||
if (blen > 0) {
|
||||
// should have bianry string check here too
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 2, bin));
|
||||
}
|
||||
|
||||
mbedtls_mpi base;
|
||||
mbedtls_mpi_init(&base);
|
||||
mbedtls_mpi_add_int(&base, &base, 10);
|
||||
|
||||
if (shall_invert) {
|
||||
PrintAndLogEx(INFO, "should invert");
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&N, &N, &base));
|
||||
}
|
||||
|
||||
// printing
|
||||
typedef struct {
|
||||
const char *desc;
|
||||
uint8_t radix;
|
||||
} radix_t;
|
||||
|
||||
radix_t radix[] = {
|
||||
{"dec..... ", 10},
|
||||
{"hex..... 0x", 16},
|
||||
{"bin..... 0b", 2}
|
||||
};
|
||||
|
||||
char s[600] = {0};
|
||||
size_t slen = 0;
|
||||
|
||||
for (uint8_t i = 0; i < ARRAYLEN(radix); i++) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(&N, radix[i].radix, s, sizeof(s), &slen));
|
||||
if (slen > 0) {
|
||||
PrintAndLogEx(INFO, "%s%s", radix[i].desc, s);
|
||||
}
|
||||
}
|
||||
|
||||
// check if number is a prime
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
mbedtls_entropy_init(&entropy);
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0));
|
||||
|
||||
res = mbedtls_mpi_is_prime_ext(&N, 50, mbedtls_ctr_drbg_random, &ctr_drbg);
|
||||
if (res == 0) {
|
||||
PrintAndLogEx(INFO, "prime... " _YELLOW_("yes"));
|
||||
}
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&N);
|
||||
mbedtls_mpi_free(&base);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
|
@ -3214,6 +3342,7 @@ static command_t CommandTable[] = {
|
|||
{"hexsamples", CmdHexsamples, IfPm3Present, "Dump big buffer as hex bytes"},
|
||||
{"hex2bin", Cmdhex2bin, AlwaysAvailable, "Converts hexadecimal to binary"},
|
||||
{"load", CmdLoad, AlwaysAvailable, "Load contents of file into graph window"},
|
||||
{"num", CmdNumCon, AlwaysAvailable, "Converts dec/hex/bin"},
|
||||
{"print", CmdPrintDemodBuff, AlwaysAvailable, "Print the data in the DemodBuffer"},
|
||||
{"samples", CmdSamples, IfPm3Present, "Get raw samples for graph window (GraphBuffer)"},
|
||||
{"save", CmdSave, AlwaysAvailable, "Save signal trace data (from graph window)"},
|
||||
|
|
|
@ -204,19 +204,23 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
size_t datalen = 0;
|
||||
uint32_t keycount = 0;
|
||||
int res = 0;
|
||||
uint8_t keylen = 0;
|
||||
uint8_t *data = calloc(FLASH_MEM_MAX_SIZE, sizeof(uint8_t));
|
||||
|
||||
switch (d) {
|
||||
case DICTIONARY_MIFARE:
|
||||
offset = DEFAULT_MF_KEYS_OFFSET;
|
||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, 6, &keycount);
|
||||
keylen = 6;
|
||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, keylen, &keycount);
|
||||
if (res || !keycount) {
|
||||
free(data);
|
||||
return PM3_EFILE;
|
||||
}
|
||||
// limited space on flash mem
|
||||
if (keycount > 0xFFFF)
|
||||
keycount &= 0xFFFF;
|
||||
if (keycount > DEFAULT_MF_KEYS_MAX) {
|
||||
keycount = DEFAULT_MF_KEYS_MAX;
|
||||
datalen = keycount * keylen;
|
||||
}
|
||||
|
||||
data[0] = (keycount >> 0) & 0xFF;
|
||||
data[1] = (keycount >> 8) & 0xFF;
|
||||
|
@ -224,14 +228,17 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
break;
|
||||
case DICTIONARY_T55XX:
|
||||
offset = DEFAULT_T55XX_KEYS_OFFSET;
|
||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, 4, &keycount);
|
||||
keylen = 4;
|
||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, keylen, &keycount);
|
||||
if (res || !keycount) {
|
||||
free(data);
|
||||
return PM3_EFILE;
|
||||
}
|
||||
// limited space on flash mem
|
||||
if (keycount > 0xFFFF)
|
||||
keycount &= 0xFFFF;
|
||||
if (keycount > DEFAULT_T55XX_KEYS_MAX) {
|
||||
keycount = DEFAULT_T55XX_KEYS_MAX;
|
||||
datalen = keycount * keylen;
|
||||
}
|
||||
|
||||
data[0] = (keycount >> 0) & 0xFF;
|
||||
data[1] = (keycount >> 8) & 0xFF;
|
||||
|
@ -239,14 +246,16 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
break;
|
||||
case DICTIONARY_ICLASS:
|
||||
offset = DEFAULT_ICLASS_KEYS_OFFSET;
|
||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, 8, &keycount);
|
||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, keylen, &keycount);
|
||||
if (res || !keycount) {
|
||||
free(data);
|
||||
return PM3_EFILE;
|
||||
}
|
||||
// limited space on flash mem
|
||||
if (keycount > 0xFFFF)
|
||||
keycount &= 0xFFFF;
|
||||
if (keycount > DEFAULT_ICLASS_KEYS_MAX) {
|
||||
keycount = DEFAULT_ICLASS_KEYS_MAX;
|
||||
datalen = keycount * keylen;
|
||||
}
|
||||
|
||||
data[0] = (keycount >> 0) & 0xFF;
|
||||
data[1] = (keycount >> 8) & 0xFF;
|
||||
|
@ -632,6 +641,11 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
// Verify (public key)
|
||||
bool is_verified = (mbedtls_rsa_pkcs1_verify(rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device) == 0);
|
||||
|
||||
if (got_private == false) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
free(rsa);
|
||||
}
|
||||
|
||||
mbedtls_pk_free(&pkctx);
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue