mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-24 17:26:13 +08:00
commit
a72c11dec0
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -39,6 +39,7 @@ client/ui/ui_overlays.h
|
||||||
hardnested_stats.txt
|
hardnested_stats.txt
|
||||||
proxmark3
|
proxmark3
|
||||||
flasher
|
flasher
|
||||||
|
!flasher/
|
||||||
lua
|
lua
|
||||||
luac
|
luac
|
||||||
fpga_compress
|
fpga_compress
|
||||||
|
|
22
.travis.yml
22
.travis.yml
|
@ -8,22 +8,18 @@ compiler: gcc
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: osx
|
- os: osx
|
||||||
osx_image: xcode9.2 # OS X 10.13
|
osx_image: xcode11
|
||||||
- os: linux
|
- os: linux
|
||||||
dist: xenial
|
dist: xenial
|
||||||
sudo: required
|
sudo: required
|
||||||
|
|
||||||
before_install:
|
addons:
|
||||||
## Install ARM toolchain on Linux.
|
apt:
|
||||||
## add our homebrew tap for MacOS
|
packages:
|
||||||
## Note: all dependencies on MacOS should be resolved by the brew install command
|
- gcc-arm-none-eabi
|
||||||
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
- libnewlib-dev
|
||||||
sudo apt-get update -qq;
|
homebrew:
|
||||||
sudo apt-get install -y gcc-arm-none-eabi libnewlib-dev;
|
taps: RfidResearchGroup/proxmark3
|
||||||
elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
|
||||||
brew update;
|
|
||||||
brew tap RfidResearchGroup/proxmark3;
|
|
||||||
fi
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||||
|
@ -34,8 +30,6 @@ install:
|
||||||
make all;
|
make all;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
before_script:
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
## start and run a test script
|
## start and run a test script
|
||||||
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||||
|
|
27
.vscode/tasks.json
vendored
Normal file
27
.vscode/tasks.json
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
|
// for the documentation about the tasks.json format
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "build",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make clean && make all -j$(nproc --all)",
|
||||||
|
"problemMatcher": [
|
||||||
|
"$gcc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "flash fullimage",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "./flash-fullimage.sh",
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "FLASH BOOTROM",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "./flash-bootrom.sh",
|
||||||
|
"problemMatcher": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
24
CHANGELOG.md
24
CHANGELOG.md
|
@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file.
|
||||||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||||
|
|
||||||
## [unreleased][unreleased]
|
## [unreleased][unreleased]
|
||||||
|
- Rework hitag2 read/write help (@ViRb3)
|
||||||
|
- Add 'lf nedap' - encoding / decoding (anon)
|
||||||
|
- Add client option `-i` to stay in interactive mode after a script or command (@DidierStevens/@doegox)
|
||||||
|
- Add VSCode tasks (@ViRb3)
|
||||||
|
- Better warn user of hardcoded hitag info (@ViRb3)
|
||||||
|
- Format and docs hitag (@ViRb3)
|
||||||
|
- Fix hitag password write offset by 1 (@ViRb3)
|
||||||
|
- Fix momentarily flash read/write of dicts (@doegox/@cjbrigato)
|
||||||
|
- Add some more default keys (@anon)
|
||||||
|
- Add 'hf thinfilm sim' simulating Thinfilm NFC barcode tags (@doegox)
|
||||||
|
- Add 'hf thinfilm list' specific trace decoding (Thinfilm NFC barcode tags) (@doegox)
|
||||||
|
- Fix 'hf topaz reader' - don't crash when trying to read a Thinfilm tag (@iceman1001)
|
||||||
|
- Add 'hf thinfilm info' - read / decode Kovio Thinfilm NFC barcode tags (@iceman1001)
|
||||||
|
- Add FPGA LF adc path (@anon)
|
||||||
|
- Add ECC support / check for NID_secp128r1 (@pwpiwi)
|
||||||
|
- Add some more default keys (ollibolli)
|
||||||
- Fix T55x7 Downlink timings backward compatible (@mwalker33)
|
- Fix T55x7 Downlink timings backward compatible (@mwalker33)
|
||||||
- Add proper Makefile halting when using incompatible STANDALONE and PLATFORM vars (@doegox)
|
- Add proper Makefile halting when using incompatible STANDALONE and PLATFORM vars (@doegox)
|
||||||
- Add T55x7 Downlink mode support (@mwalker33)
|
- Add T55x7 Downlink mode support (@mwalker33)
|
||||||
|
@ -152,7 +168,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||||
- Change `lf indala demod` - refactoring (@iceman1001)
|
- Change `lf indala demod` - refactoring (@iceman1001)
|
||||||
- Change - handling fault bit markers (7) and partial nibbles in hex printing (@doegox)
|
- Change - handling fault bit markers (7) and partial nibbles in hex printing (@doegox)
|
||||||
- Change - printing of fault bit markers (7) using a dot (@doegox)
|
- Change - printing of fault bit markers (7) using a dot (@doegox)
|
||||||
- Change `sc upgrade` - firmware file integrity check (@piwi)
|
- Change `sc upgrade` - firmware file integrity check (@pwpiwi)
|
||||||
- Fix `data rawdemod am` - last bit was missing (@doegox)
|
- Fix `data rawdemod am` - last bit was missing (@doegox)
|
||||||
- Fix `hf 15 dump f` - also selects tag first (@iceman1001)
|
- Fix `hf 15 dump f` - also selects tag first (@iceman1001)
|
||||||
- Fix `hf iclass clone` - missing fileclose (@iceman1001)
|
- Fix `hf iclass clone` - missing fileclose (@iceman1001)
|
||||||
|
@ -160,8 +176,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||||
- Change `lf hitag sim` - loads bin/eml/json (@iceman1001)
|
- Change `lf hitag sim` - loads bin/eml/json (@iceman1001)
|
||||||
- Change `lf hitag reader 21` - saves in bin/eml/json (@iceman1001)
|
- Change `lf hitag reader 21` - saves in bin/eml/json (@iceman1001)
|
||||||
- Change `lf hitag` - refactoring (@iceman1001)
|
- Change `lf hitag` - refactoring (@iceman1001)
|
||||||
- Change `lf hitag` - refactoring (@piwi)
|
- Change `lf hitag` - refactoring (@pwpiwi)
|
||||||
- Fix `lf hitag` - generic fix for missing clock init (@piwi)
|
- Fix `lf hitag` - generic fix for missing clock init (@pwpiwi)
|
||||||
- Fix fsk sim operations on deviceside - avoid division by zero (@doegox)
|
- Fix fsk sim operations on deviceside - avoid division by zero (@doegox)
|
||||||
- Fix `hf mf fchk` - condition always false (@doegox)
|
- Fix `hf mf fchk` - condition always false (@doegox)
|
||||||
- Fix `lf t55xx recoverpw` - shift as u32 (@doegox)
|
- Fix `lf t55xx recoverpw` - shift as u32 (@doegox)
|
||||||
|
@ -290,7 +306,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||||
- Added to proxmark command line parameters `c` and `l` - execute command and lua script from command line (@merlokk)
|
- Added to proxmark command line parameters `c` and `l` - execute command and lua script from command line (@merlokk)
|
||||||
- Added to proxmark ability to execute commands from stdin (pipe) (@merlokk)
|
- Added to proxmark ability to execute commands from stdin (pipe) (@merlokk)
|
||||||
- Added new standalone mode "HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN" (@cjbrigato)
|
- Added new standalone mode "HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN" (@cjbrigato)
|
||||||
- Added to `hf 14a apdu` - exchange apdu via iso1443-4 (@merlokk)
|
- Added to `hf 14a apdu` - exchange apdu via iso14443-4 (@merlokk)
|
||||||
- Added to `hf 14a apdu` - apdu and tlv results parser (@merlokk)
|
- Added to `hf 14a apdu` - apdu and tlv results parser (@merlokk)
|
||||||
- Added `hf emv` commands (@merlokk)
|
- Added `hf emv` commands (@merlokk)
|
||||||
- lots of bug fixes (many many)
|
- lots of bug fixes (many many)
|
||||||
|
|
24
Makefile
24
Makefile
|
@ -31,9 +31,9 @@ endif
|
||||||
|
|
||||||
-include Makefile.platform
|
-include Makefile.platform
|
||||||
-include .Makefile.options.cache
|
-include .Makefile.options.cache
|
||||||
include common/Makefile.hal
|
include common_arm/Makefile.hal
|
||||||
|
|
||||||
all clean: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/%
|
all clean: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/% fpga_compress/%
|
||||||
|
|
||||||
mfkey/%: FORCE
|
mfkey/%: FORCE
|
||||||
$(info [*] MAKE $@)
|
$(info [*] MAKE $@)
|
||||||
|
@ -41,10 +41,13 @@ mfkey/%: FORCE
|
||||||
nonce2key/%: FORCE
|
nonce2key/%: FORCE
|
||||||
$(info [*] MAKE $@)
|
$(info [*] MAKE $@)
|
||||||
$(Q)$(MAKE) --no-print-directory -C tools/nonce2key $(patsubst nonce2key/%,%,$@)
|
$(Q)$(MAKE) --no-print-directory -C tools/nonce2key $(patsubst nonce2key/%,%,$@)
|
||||||
|
fpga_compress/%: FORCE
|
||||||
|
$(info [*] MAKE $@)
|
||||||
|
$(Q)$(MAKE) --no-print-directory -C tools/fpga_compress $(patsubst fpga_compress/%,%,$@)
|
||||||
bootrom/%: FORCE cleanifplatformchanged
|
bootrom/%: FORCE cleanifplatformchanged
|
||||||
$(info [*] MAKE $@)
|
$(info [*] MAKE $@)
|
||||||
$(Q)$(MAKE) --no-print-directory -C bootrom $(patsubst bootrom/%,%,$@)
|
$(Q)$(MAKE) --no-print-directory -C bootrom $(patsubst bootrom/%,%,$@)
|
||||||
armsrc/%: FORCE cleanifplatformchanged
|
armsrc/%: FORCE cleanifplatformchanged fpga_compress/%
|
||||||
$(info [*] MAKE $@)
|
$(info [*] MAKE $@)
|
||||||
$(Q)$(MAKE) --no-print-directory -C armsrc $(patsubst armsrc/%,%,$@)
|
$(Q)$(MAKE) --no-print-directory -C armsrc $(patsubst armsrc/%,%,$@)
|
||||||
client/%: FORCE
|
client/%: FORCE
|
||||||
|
@ -55,7 +58,7 @@ recovery/%: FORCE cleanifplatformchanged bootrom/% armsrc/%
|
||||||
$(Q)$(MAKE) --no-print-directory -C recovery $(patsubst recovery/%,%,$@)
|
$(Q)$(MAKE) --no-print-directory -C recovery $(patsubst recovery/%,%,$@)
|
||||||
FORCE: # Dummy target to force remake in the subdirectories, even if files exist (this Makefile doesn't know about the prerequisites)
|
FORCE: # Dummy target to force remake in the subdirectories, even if files exist (this Makefile doesn't know about the prerequisites)
|
||||||
|
|
||||||
.PHONY: all clean help _test bootrom flash-bootrom os flash-os flash-all recovery client mfkey nounce2key style checks FORCE udev accessrights cleanifplatformchanged
|
.PHONY: all clean help _test bootrom flash-bootrom os flash-os flash-all recovery client mfkey nonce2key style checks FORCE udev accessrights cleanifplatformchanged
|
||||||
|
|
||||||
help:
|
help:
|
||||||
@echo "Multi-OS Makefile"
|
@echo "Multi-OS Makefile"
|
||||||
|
@ -73,7 +76,8 @@ help:
|
||||||
@echo
|
@echo
|
||||||
@echo "+ client - Make only the OS-specific host client"
|
@echo "+ client - Make only the OS-specific host client"
|
||||||
@echo "+ mfkey - Make tools/mfkey"
|
@echo "+ mfkey - Make tools/mfkey"
|
||||||
@echo "+ nounce2key - Make tools/nounce2key"
|
@echo "+ nonce2key - Make tools/nonce2key"
|
||||||
|
@echo "+ fpga_compress - Make tools/fpga_compress"
|
||||||
@echo
|
@echo
|
||||||
@echo "+ style - Apply some automated source code formatting rules"
|
@echo "+ style - Apply some automated source code formatting rules"
|
||||||
@echo "+ checks - Detect various encoding issues in source code"
|
@echo "+ checks - Detect various encoding issues in source code"
|
||||||
|
@ -93,6 +97,8 @@ mfkey: mfkey/all
|
||||||
|
|
||||||
nonce2key: nonce2key/all
|
nonce2key: nonce2key/all
|
||||||
|
|
||||||
|
fpga_compress: fpga_compress/all
|
||||||
|
|
||||||
flash-bootrom: bootrom/obj/bootrom.elf $(FLASH_TOOL)
|
flash-bootrom: bootrom/obj/bootrom.elf $(FLASH_TOOL)
|
||||||
$(FLASH_TOOL) $(FLASH_PORT) -b $(subst /,$(PATHSEP),$<)
|
$(FLASH_TOOL) $(FLASH_PORT) -b $(subst /,$(PATHSEP),$<)
|
||||||
|
|
||||||
|
@ -145,7 +151,7 @@ style:
|
||||||
# Make sure astyle is installed
|
# Make sure astyle is installed
|
||||||
@which astyle >/dev/null || ( echo "Please install 'astyle' package first" ; exit 1 )
|
@which astyle >/dev/null || ( echo "Please install 'astyle' package first" ; exit 1 )
|
||||||
# Remove spaces & tabs at EOL, add LF at EOF if needed on *.c, *.h, *.cpp. *.lua, *.py, *.pl, Makefile
|
# Remove spaces & tabs at EOL, add LF at EOF if needed on *.c, *.h, *.cpp. *.lua, *.py, *.pl, Makefile
|
||||||
find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" \) \
|
find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" -or -name "*.v" \) \
|
||||||
-exec perl -pi -e 's/[ \t]+$$//' {} \; \
|
-exec perl -pi -e 's/[ \t]+$$//' {} \; \
|
||||||
-exec sh -c "tail -c1 {} | xxd -p | tail -1 | grep -q -v 0a$$" \; \
|
-exec sh -c "tail -c1 {} | xxd -p | tail -1 | grep -q -v 0a$$" \; \
|
||||||
-exec sh -c "echo >> {}" \;
|
-exec sh -c "echo >> {}" \;
|
||||||
|
@ -158,11 +164,11 @@ style:
|
||||||
|
|
||||||
# Detecting weird codepages and tabs.
|
# Detecting weird codepages and tabs.
|
||||||
checks:
|
checks:
|
||||||
find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" \) \
|
find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" -or -name "*.v" \) \
|
||||||
-exec sh -c "cat {} |recode utf8.. >/dev/null || echo {}" \;
|
-exec sh -c "cat {} |recode utf8.. >/dev/null || echo {}" \;
|
||||||
find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "*.md" -or -name "*.txt" -or -name "*.awk" \) \
|
find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "*.md" -or -name "*.txt" -or -name "*.awk" -or -name "*.v" \) \
|
||||||
-exec grep -lP '\t' {} \;
|
-exec grep -lP '\t' {} \;
|
||||||
# to remove tabs within lines, one can try with vi: :set tabstop=4 :set et|retab
|
# to remove tabs within lines, one can try with: vi $file -c ':set tabstop=4' -c ':set et|retab' -c ':wq'
|
||||||
|
|
||||||
# Dummy target to test for GNU make availability
|
# Dummy target to test for GNU make availability
|
||||||
_test:
|
_test:
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "BigBuf.h"
|
#include "BigBuf.h"
|
||||||
|
|
||||||
|
#include "string.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
|
||||||
// BigBuf is the large multi-purpose buffer, typically used to hold A/D samples or traces.
|
// BigBuf is the large multi-purpose buffer, typically used to hold A/D samples or traces.
|
||||||
// Also used to hold various smaller buffers and the Mifare Emulator Memory.
|
// Also used to hold various smaller buffers and the Mifare Emulator Memory.
|
||||||
// declare it as uint32_t to achieve alignment to 4 Byte boundary
|
// declare it as uint32_t to achieve alignment to 4 Byte boundary
|
||||||
|
|
|
@ -12,10 +12,7 @@
|
||||||
#ifndef __BIGBUF_H
|
#ifndef __BIGBUF_H
|
||||||
#define __BIGBUF_H
|
#define __BIGBUF_H
|
||||||
|
|
||||||
#include <stdbool.h> // for bool
|
#include "common.h"
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "string.h"
|
|
||||||
#include "ticks.h"
|
|
||||||
|
|
||||||
#define BIGBUF_SIZE 40000
|
#define BIGBUF_SIZE 40000
|
||||||
#define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame
|
#define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame
|
||||||
|
@ -43,4 +40,5 @@ void set_tracelen(uint32_t value);
|
||||||
bool get_tracing(void);
|
bool get_tracing(void);
|
||||||
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
|
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
|
||||||
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length);
|
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length);
|
||||||
|
|
||||||
#endif /* __BIGBUF_H */
|
#endif /* __BIGBUF_H */
|
||||||
|
|
|
@ -9,10 +9,6 @@
|
||||||
#ifndef __LCD_H
|
#ifndef __LCD_H
|
||||||
#define __LCD_H
|
#define __LCD_H
|
||||||
|
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "apps.h"
|
|
||||||
#include "fonts.h"
|
|
||||||
|
|
||||||
// The resolution of the LCD
|
// The resolution of the LCD
|
||||||
#define LCD_XRES 132
|
#define LCD_XRES 132
|
||||||
#define LCD_YRES 132
|
#define LCD_YRES 132
|
|
@ -2,16 +2,14 @@
|
||||||
# at your option, any later version. See the LICENSE.txt file for the text of
|
# at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
# the license.
|
# the license.
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
# Makefile for armsrc, see ../common/Makefile.common for common settings
|
# Makefile for armsrc, see ../common_arm/Makefile.common for common settings
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
APP_INCLUDES = apps.h
|
|
||||||
|
|
||||||
# This Makefile might have been called directly, not via the root Makefile, so:
|
# This Makefile might have been called directly, not via the root Makefile, so:
|
||||||
ifeq ($(PLTNAME),)
|
ifeq ($(PLTNAME),)
|
||||||
-include ../Makefile.platform
|
-include ../Makefile.platform
|
||||||
-include ../.Makefile.options.cache
|
-include ../.Makefile.options.cache
|
||||||
include ../common/Makefile.hal
|
include ../common_arm/Makefile.hal
|
||||||
# detect if there were changes in the platform definitions, requiring a clean
|
# detect if there were changes in the platform definitions, requiring a clean
|
||||||
ifeq ($(PLATFORM_CHANGED), true)
|
ifeq ($(PLATFORM_CHANGED), true)
|
||||||
$(error platform definitions have been changed, please "make clean" at the root of the project)
|
$(error platform definitions have been changed, please "make clean" at the root of the project)
|
||||||
|
@ -28,20 +26,24 @@ APP_CFLAGS = $(PLATFORM_DEFS) \
|
||||||
SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c
|
SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c
|
||||||
SRC_ISO15693 = iso15693.c iso15693tools.c
|
SRC_ISO15693 = iso15693.c iso15693tools.c
|
||||||
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c
|
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c
|
||||||
|
#UNUSED: mifaresniff.c desfire_crypto.c
|
||||||
SRC_ISO14443b = iso14443b.c
|
SRC_ISO14443b = iso14443b.c
|
||||||
SRC_FELICA = felica.c
|
SRC_FELICA = felica.c
|
||||||
SRC_CRAPTO1 = crypto1.c des.c desfire_key.c desfire_crypto.c mifaredesfire.c aes.c platform_util.c
|
SRC_CRAPTO1 = crypto1.c des.c desfire_key.c mifaredesfire.c aes.c platform_util.c
|
||||||
SRC_CRC = crc.c crc16.c crc32.c
|
SRC_CRC = crc.c crc16.c crc32.c
|
||||||
SRC_ICLASS = iclass.c optimized_cipher.c
|
SRC_ICLASS = iclass.c optimized_cipher.c
|
||||||
SRC_LEGIC = legicrf.c legicrfsim.c legic_prng.c
|
SRC_LEGIC = legicrf.c legicrfsim.c legic_prng.c
|
||||||
SRC_SPIFFS = spiffs.c spiffs_cache.c spiffs_check.c spiffs_gc.c spiffs_nucleus.c spiffs_hydrogen.c
|
SRC_NFCBARCODE = thinfilm.c
|
||||||
|
|
||||||
# SRC_BEE = bee.c
|
# SRC_BEE = bee.c
|
||||||
|
|
||||||
# RDV40 related hardware support
|
# RDV40 related hardware support
|
||||||
ifneq (,$(findstring WITH_FLASH,$(APP_CFLAGS)))
|
ifneq (,$(findstring WITH_FLASH,$(APP_CFLAGS)))
|
||||||
SRC_FLASH = flashmem.c
|
SRC_FLASH = flashmem.c
|
||||||
|
SRC_SPIFFS = spiffs.c spiffs_cache.c spiffs_check.c spiffs_gc.c spiffs_nucleus.c spiffs_hydrogen.c
|
||||||
else
|
else
|
||||||
SRC_FLASH =
|
SRC_FLASH =
|
||||||
|
SRC_SPIFFS =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq (,$(findstring WITH_SMARTCARD,$(APP_CFLAGS)))
|
ifneq (,$(findstring WITH_SMARTCARD,$(APP_CFLAGS)))
|
||||||
|
@ -80,7 +82,7 @@ SRC_ZLIB = inflate.c inffast.c inftrees.c adler32.c zutil.c
|
||||||
ZLIB_CFLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED
|
ZLIB_CFLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED
|
||||||
APP_CFLAGS += $(ZLIB_CFLAGS)
|
APP_CFLAGS += $(ZLIB_CFLAGS)
|
||||||
# zlib includes:
|
# zlib includes:
|
||||||
APP_CFLAGS += -I../zlib
|
APP_CFLAGS += -I../common/zlib
|
||||||
|
|
||||||
# stdint.h provided locally until GCC 4.5 becomes C99 compliant,
|
# stdint.h provided locally until GCC 4.5 becomes C99 compliant,
|
||||||
# stack-protect , no-pie reduces size on Gentoo Hardened 8.2 gcc
|
# stack-protect , no-pie reduces size on Gentoo Hardened 8.2 gcc
|
||||||
|
@ -88,9 +90,9 @@ APP_CFLAGS += -I. -fno-stack-protector -fno-pie
|
||||||
|
|
||||||
# Compile these in thumb mode (small size)
|
# Compile these in thumb mode (small size)
|
||||||
THUMBSRC = start.c \
|
THUMBSRC = start.c \
|
||||||
protocols.c \
|
|
||||||
$(SRC_LCD) \
|
$(SRC_LCD) \
|
||||||
$(SRC_ISO15693) \
|
$(SRC_ISO15693) \
|
||||||
|
$(SRC_NFCBARCODE) \
|
||||||
$(SRC_LF) \
|
$(SRC_LF) \
|
||||||
$(SRC_ZLIB) \
|
$(SRC_ZLIB) \
|
||||||
$(SRC_LEGIC) \
|
$(SRC_LEGIC) \
|
||||||
|
@ -101,6 +103,7 @@ THUMBSRC = start.c \
|
||||||
$(SRC_SPIFFS) \
|
$(SRC_SPIFFS) \
|
||||||
appmain.c \
|
appmain.c \
|
||||||
printf.c \
|
printf.c \
|
||||||
|
dbprint.c \
|
||||||
commonutil.c \
|
commonutil.c \
|
||||||
util.c \
|
util.c \
|
||||||
string.c \
|
string.c \
|
||||||
|
@ -127,12 +130,12 @@ VERSIONSRC = version.c \
|
||||||
fpga_version_info.c
|
fpga_version_info.c
|
||||||
|
|
||||||
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
|
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
|
||||||
include ../common/Makefile.common
|
include ../common_arm/Makefile.common
|
||||||
|
|
||||||
COMMON_FLAGS = -Os
|
COMMON_FLAGS = -Os
|
||||||
|
|
||||||
OBJS = $(OBJDIR)/fullimage.s19
|
OBJS = $(OBJDIR)/fullimage.s19
|
||||||
FPGA_COMPRESSOR = ../client/fpga_compress
|
FPGA_COMPRESSOR = ../tools/fpga_compress/fpga_compress
|
||||||
|
|
||||||
all: $(OBJS)
|
all: $(OBJS)
|
||||||
|
|
||||||
|
@ -143,7 +146,7 @@ version.c: default_version.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o
|
||||||
$(info [-] GEN $@)
|
$(info [-] GEN $@)
|
||||||
$(Q)perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@
|
$(Q)perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@
|
||||||
|
|
||||||
fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR)
|
fpga_version_info.c: $(FPGA_BITSTREAMS) | $(FPGA_COMPRESSOR)
|
||||||
$(info [-] GEN $@)
|
$(info [-] GEN $@)
|
||||||
$(Q)$(FPGA_COMPRESSOR) -v $(filter %.bit,$^) $@
|
$(Q)$(FPGA_COMPRESSOR) -v $(filter %.bit,$^) $@
|
||||||
|
|
||||||
|
@ -151,7 +154,7 @@ $(OBJDIR)/fpga_all.o: $(OBJDIR)/fpga_all.bit.z
|
||||||
$(info [-] GEN $@)
|
$(info [-] GEN $@)
|
||||||
$(Q)$(OBJCOPY) -O elf32-littlearm -I binary -B arm --prefix-sections=fpga_all_bit $^ $@
|
$(Q)$(OBJCOPY) -O elf32-littlearm -I binary -B arm --prefix-sections=fpga_all_bit $^ $@
|
||||||
|
|
||||||
$(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR)
|
$(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) | $(FPGA_COMPRESSOR)
|
||||||
$(info [-] GEN $@)
|
$(info [-] GEN $@)
|
||||||
ifeq ($(Q),@)
|
ifeq ($(Q),@)
|
||||||
@$(FPGA_COMPRESSOR) $(filter %.bit,$^) $@ >/dev/null
|
@$(FPGA_COMPRESSOR) $(filter %.bit,$^) $@ >/dev/null
|
||||||
|
@ -160,8 +163,8 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(FPGA_COMPRESSOR):
|
$(FPGA_COMPRESSOR):
|
||||||
$(info [*] MAKE $@)
|
$(error [!] MISSING $@ => To build it, go the root of the repo and do "make $(notdir $@)")
|
||||||
$(Q)$(MAKE) --no-print-directory -C ../client $(notdir $(FPGA_COMPRESSOR))
|
$(error [!] MISSING $@)
|
||||||
|
|
||||||
$(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ)
|
$(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ)
|
||||||
$(info [=] LD $@)
|
$(info [=] LD $@)
|
||||||
|
@ -179,7 +182,7 @@ $(OBJDIR)/fullimage.data.bin: $(OBJDIR)/fullimage.stage1.elf
|
||||||
$(info [-] GEN $@)
|
$(info [-] GEN $@)
|
||||||
$(Q)$(OBJCOPY) -O binary -I elf32-littlearm --only-section .data $^ $@
|
$(Q)$(OBJCOPY) -O binary -I elf32-littlearm --only-section .data $^ $@
|
||||||
|
|
||||||
$(OBJDIR)/fullimage.data.bin.z: $(OBJDIR)/fullimage.data.bin $(FPGA_COMPRESSOR)
|
$(OBJDIR)/fullimage.data.bin.z: $(OBJDIR)/fullimage.data.bin | $(FPGA_COMPRESSOR)
|
||||||
$(info [-] GEN $@)
|
$(info [-] GEN $@)
|
||||||
ifeq ($(Q),@)
|
ifeq ($(Q),@)
|
||||||
@$(FPGA_COMPRESSOR) $(filter %.bin,$^) $@ >/dev/null
|
@$(FPGA_COMPRESSOR) $(filter %.bin,$^) $@ >/dev/null
|
||||||
|
@ -200,6 +203,7 @@ tarbin: $(OBJS)
|
||||||
$(Q)$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=armsrc/%) $(OBJS:%.s19=armsrc/%.elf)
|
$(Q)$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=armsrc/%) $(OBJS:%.s19=armsrc/%.elf)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
$(Q)$(DELETE) $(DEPENDENCY_FILES)
|
||||||
$(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.o
|
$(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.o
|
||||||
$(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.elf
|
$(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.elf
|
||||||
$(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.s19
|
$(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.s19
|
||||||
|
@ -215,3 +219,4 @@ help:
|
||||||
@echo Possible targets:
|
@echo Possible targets:
|
||||||
@echo + all - Build the full image $(OBJDIR)/fullimage.s19
|
@echo + all - Build the full image $(OBJDIR)/fullimage.s19
|
||||||
@echo + clean - Clean $(OBJDIR)
|
@echo + clean - Clean $(OBJDIR)
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ ifneq (,$(findstring WITH_STANDALONE_HF_MATTYRUN,$(APP_CFLAGS)))
|
||||||
endif
|
endif
|
||||||
# WITH_STANDALONE_HF_COLIN
|
# WITH_STANDALONE_HF_COLIN
|
||||||
ifneq (,$(findstring WITH_STANDALONE_HF_COLIN,$(APP_CFLAGS)))
|
ifneq (,$(findstring WITH_STANDALONE_HF_COLIN,$(APP_CFLAGS)))
|
||||||
SRC_STANDALONE = vtsend.c hf_colin.c
|
SRC_STANDALONE = vtsend.c hf_colin.c frozen.c nprintf.c
|
||||||
endif
|
endif
|
||||||
# WITH_STANDALONE_HF_BOG
|
# WITH_STANDALONE_HF_BOG
|
||||||
ifneq (,$(findstring WITH_STANDALONE_HF_BOG,$(APP_CFLAGS)))
|
ifneq (,$(findstring WITH_STANDALONE_HF_BOG,$(APP_CFLAGS)))
|
||||||
|
|
|
@ -19,7 +19,18 @@ you can simply run 'script run read_pwd_mem' or just 'mem dump p l 256'
|
||||||
from the client to view the stored quadlets.
|
from the client to view the stored quadlets.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hf_bog.h"
|
#include "standalone.h" // standalone definitions
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "iso14443a.h"
|
||||||
|
#include "protocols.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "spiffs.h"
|
||||||
|
#include "appmain.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
#define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8)
|
#define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8)
|
||||||
#define DELAY_TAG_AIR2ARM_AS_SNIFFER (3 + 14 + 8)
|
#define DELAY_TAG_AIR2ARM_AS_SNIFFER (3 + 14 + 8)
|
||||||
|
@ -62,10 +73,10 @@ void RAMFUNC SniffAndStore(uint8_t param) {
|
||||||
bool ReaderIsActive = false;
|
bool ReaderIsActive = false;
|
||||||
|
|
||||||
// Set up the demodulator for tag -> reader responses.
|
// Set up the demodulator for tag -> reader responses.
|
||||||
DemodInit(receivedResp, receivedRespPar);
|
Demod14aInit(receivedResp, receivedRespPar);
|
||||||
|
|
||||||
// Set up the demodulator for the reader -> tag commands
|
// Set up the demodulator for the reader -> tag commands
|
||||||
UartInit(receivedCmd, receivedCmdPar);
|
Uart14aInit(receivedCmd, receivedCmdPar);
|
||||||
|
|
||||||
// Setup and start DMA.
|
// Setup and start DMA.
|
||||||
if (!FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE)) {
|
if (!FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE)) {
|
||||||
|
@ -74,8 +85,8 @@ void RAMFUNC SniffAndStore(uint8_t param) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tUart *uart = GetUart();
|
tUart14a *uart = GetUart14a();
|
||||||
tDemod *demod = GetDemod();
|
tDemod14a *demod = GetDemod14a();
|
||||||
|
|
||||||
// We won't start recording the frames that we acquire until we trigger;
|
// We won't start recording the frames that we acquire until we trigger;
|
||||||
// a good trigger condition to get started is probably when we see a
|
// a good trigger condition to get started is probably when we see a
|
||||||
|
@ -153,13 +164,13 @@ void RAMFUNC SniffAndStore(uint8_t param) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* ready to receive another command. */
|
/* ready to receive another command. */
|
||||||
UartReset();
|
Uart14aReset();
|
||||||
/* reset the demod code, which might have been */
|
/* reset the demod code, which might have been */
|
||||||
/* false-triggered by the commands from the reader. */
|
/* false-triggered by the commands from the reader. */
|
||||||
DemodReset();
|
Demod14aReset();
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
}
|
}
|
||||||
ReaderIsActive = (uart->state != STATE_UNSYNCD);
|
ReaderIsActive = (uart->state != STATE_14A_UNSYNCD);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no need to try decoding tag data if the reader is sending - and we cannot afford the time
|
// no need to try decoding tag data if the reader is sending - and we cannot afford the time
|
||||||
|
@ -176,13 +187,13 @@ void RAMFUNC SniffAndStore(uint8_t param) {
|
||||||
triggered = true;
|
triggered = true;
|
||||||
|
|
||||||
// ready to receive another response.
|
// ready to receive another response.
|
||||||
DemodReset();
|
Demod14aReset();
|
||||||
// reset the Miller decoder including its (now outdated) input buffer
|
// reset the Miller decoder including its (now outdated) input buffer
|
||||||
UartReset();
|
Uart14aReset();
|
||||||
// UartInit(receivedCmd, receivedCmdPar);
|
// UartInit(receivedCmd, receivedCmdPar);
|
||||||
LED_C_OFF();
|
LED_C_OFF();
|
||||||
}
|
}
|
||||||
TagIsActive = (demod->state != DEMOD_UNSYNCD);
|
TagIsActive = (demod->state != DEMOD_14A_UNSYNCD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
|
||||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
|
||||||
// the license.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// StandAlone Mod
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifndef __HF_BOG_H
|
|
||||||
#define __HF_BOG_H
|
|
||||||
|
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "mifareutil.h"
|
|
||||||
#include "iso14443a.h"
|
|
||||||
#include "protocols.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "standalone.h" // standalone definitions
|
|
||||||
#include <stdbool.h> // for bool
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "apps.h"
|
|
||||||
#include "printf.h"
|
|
||||||
#include "parity.h"
|
|
||||||
#include "spiffs.h"
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* __HF_BOG_H */
|
|
|
@ -8,12 +8,81 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// main code for HF Mifare aka ColinRun by Colin Brigato
|
// main code for HF Mifare aka ColinRun by Colin Brigato
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
#include "standalone.h" // standalone definitions
|
||||||
|
#include <stdbool.h> // for bool
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include "hf_colin.h"
|
#include "hf_colin.h"
|
||||||
|
#include "appmain.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "commonutil.h"
|
||||||
|
#include "crc16.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "frozen.h"
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "mifaresim.h" // mifare1ksim
|
||||||
|
#include "mifareutil.h"
|
||||||
|
#include "iso14443a.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "vtsend.h"
|
||||||
|
#include "spiffs.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
#define MF1KSZ 1024
|
#define MF1KSZ 1024
|
||||||
#define MF1KSZSIZE 64
|
#define MF1KSZSIZE 64
|
||||||
#define AUTHENTICATION_TIMEOUT 848
|
#define AUTHENTICATION_TIMEOUT 848
|
||||||
#define HFCOLIN_LASTTAG_SYMLINK "hf_colin/lasttag.bin"
|
#define HFCOLIN_LASTTAG_SYMLINK "hf_colin/lasttag.bin"
|
||||||
|
#define HFCOLIN_SCHEMAS_JSON "hf_colin/schemas.json"
|
||||||
|
|
||||||
|
/* Example jsonconfig file schemas.json : (array !)
|
||||||
|
[{
|
||||||
|
"name": "UrmetCaptive",
|
||||||
|
"trigger": "0x8829da9daf76",
|
||||||
|
"keysA": [
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76"
|
||||||
|
],
|
||||||
|
"keysB": [
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76",
|
||||||
|
"0x8829da9daf76"
|
||||||
|
]
|
||||||
|
},{
|
||||||
|
"name": "Noralsy",
|
||||||
|
...
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
uint8_t cjuid[10];
|
uint8_t cjuid[10];
|
||||||
uint32_t cjcuid;
|
uint32_t cjcuid;
|
||||||
|
@ -27,6 +96,56 @@ int curlline;
|
||||||
|
|
||||||
// Colin's VIGIKPWN sniff/simulate/clone repeat routine for HF Mifare
|
// Colin's VIGIKPWN sniff/simulate/clone repeat routine for HF Mifare
|
||||||
|
|
||||||
|
static const uint8_t is_hex[] = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline uint64_t hex2i(const char *s) {
|
||||||
|
uint64_t val = 0;
|
||||||
|
if (s == NULL || s[0] == 0)
|
||||||
|
return 0;
|
||||||
|
if (s[1] == 'x')
|
||||||
|
s += 2;
|
||||||
|
else if (*s == 'x')
|
||||||
|
s++;
|
||||||
|
while (is_hex[(uint8_t)*s])
|
||||||
|
val = (val << 4) | (is_hex[(uint8_t) * (s++)] - 1);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*char *noralsy2test =
|
||||||
|
"{\"name\":\"noralsy2\",\"trigger\":\"0x414C41524F4E\",\"keysA\":[\"0x414C41524F4E\",\"0x414C41524F4E\","
|
||||||
|
"\"0x414C41524F4E\","
|
||||||
|
"\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\","
|
||||||
|
"\"0x414C41524F4E\",\"0x414C41524F4E\","
|
||||||
|
"\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\","
|
||||||
|
"\"0x414C41524F4E\"],\"keysB\":["
|
||||||
|
"\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\","
|
||||||
|
"\"0x424C41524F4E\",\"0x424C41524F4E\","
|
||||||
|
"\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\","
|
||||||
|
"\"0x424C41524F4E\",\"0x424C41524F4E\","
|
||||||
|
"\"0x424C41524F4E\",\"0x424C41524F4E\"]}";*/
|
||||||
|
|
||||||
|
/*char *urmetcaptive2test =
|
||||||
|
"{\"name\":\"urmetcaptive2\",\"trigger\":\"0x8829da9daf76\",\"keysA\":[\"0x8829da9daf76\",\"0x8829da9daf76\","
|
||||||
|
"\"0x8829da9daf76\","
|
||||||
|
"\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\","
|
||||||
|
"\"0x8829da9daf76\",\"0x8829da9daf76\","
|
||||||
|
"\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\","
|
||||||
|
"\"0x8829da9daf76\"],\"keysB\":["
|
||||||
|
"\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\","
|
||||||
|
"\"0x8829da9daf76\",\"0x8829da9daf76\","
|
||||||
|
"\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\","
|
||||||
|
"\"0x8829da9daf76\",\"0x8829da9daf76\","
|
||||||
|
"\"0x8829da9daf76\",\"0x8829da9daf76\"]}";*/
|
||||||
|
|
||||||
typedef struct MFC1KSchema {
|
typedef struct MFC1KSchema {
|
||||||
uint8_t name[32];
|
uint8_t name[32];
|
||||||
uint64_t trigger;
|
uint64_t trigger;
|
||||||
|
@ -36,50 +155,49 @@ typedef struct MFC1KSchema {
|
||||||
|
|
||||||
#define MAX_SCHEMAS 4
|
#define MAX_SCHEMAS 4
|
||||||
|
|
||||||
|
static void scan_keys(const char *str, int len, uint64_t *user_data) {
|
||||||
|
struct json_token t;
|
||||||
|
int i;
|
||||||
|
char ks[32];
|
||||||
|
for (i = 0; json_scanf_array_elem(str, len, "", i, &t) > 0; i++) {
|
||||||
|
sprintf(ks, "%.*s", t.len, t.ptr);
|
||||||
|
user_data[i] = hex2i(ks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MFC1KSchema Schemas[MAX_SCHEMAS];
|
MFC1KSchema Schemas[MAX_SCHEMAS];
|
||||||
|
|
||||||
MFC1KSchema Noralsy = {
|
/*MFC1KSchema Noralsy = {
|
||||||
.name = "Noralsy",
|
.name = "Noralsy",
|
||||||
.trigger = 0x414c41524f4e,
|
.trigger = 0x414c41524f4e,
|
||||||
.keysA = {
|
.keysA = {0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e,
|
||||||
0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e,
|
0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e,
|
||||||
0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e,
|
0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e},
|
||||||
0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e
|
.keysB = {0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e,
|
||||||
},
|
0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e,
|
||||||
.keysB = {
|
0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e}};
|
||||||
0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e,
|
|
||||||
0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e,
|
|
||||||
0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MFC1KSchema InfiHexact = {.name = "Infineon/Hexact",
|
MFC1KSchema InfiHexact = {.name = "Infineon/Hexact",
|
||||||
.trigger = 0x484558414354,
|
.trigger = 0x484558414354,
|
||||||
.keysA = {0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
|
.keysA = {0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
|
||||||
0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
|
0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
|
||||||
0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
|
0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
|
||||||
0x484558414354
|
0x484558414354},
|
||||||
},
|
|
||||||
.keysB = {0xa22ae129c013, 0x49fae4e3849f, 0x38fcf33072e0, 0x8ad5517b4b18, 0x509359f131b1,
|
.keysB = {0xa22ae129c013, 0x49fae4e3849f, 0x38fcf33072e0, 0x8ad5517b4b18, 0x509359f131b1,
|
||||||
0x6c78928e1317, 0xaa0720018738, 0xa6cac2886412, 0x62d0c424ed8e, 0xe64a986a5d94,
|
0x6c78928e1317, 0xaa0720018738, 0xa6cac2886412, 0x62d0c424ed8e, 0xe64a986a5d94,
|
||||||
0x8fa1d601d0a2, 0x89347350bd36, 0x66d2b7dc39ef, 0x6bc1e1ae547d, 0x22729a9bd40f
|
0x8fa1d601d0a2, 0x89347350bd36, 0x66d2b7dc39ef, 0x6bc1e1ae547d, 0x22729a9bd40f}};
|
||||||
}
|
*/
|
||||||
};
|
|
||||||
|
|
||||||
MFC1KSchema UrmetCaptive = {
|
/*MFC1KSchema UrmetCaptive = {
|
||||||
.name = "Urmet Captive",
|
.name = "Urmet Captive",
|
||||||
.trigger = 0x8829da9daf76,
|
.trigger = 0x8829da9daf76,
|
||||||
.keysA = {
|
.keysA = {0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
|
||||||
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
|
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
|
||||||
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
|
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76},
|
||||||
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76
|
.keysB = {0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
|
||||||
},
|
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
|
||||||
.keysB = {
|
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76}};
|
||||||
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
|
*/
|
||||||
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
|
|
||||||
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int total_schemas = 0;
|
int total_schemas = 0;
|
||||||
|
|
||||||
|
@ -125,6 +243,41 @@ foundKey[5]); cjSetCursRight(); DbprintfEx(FLAG_NEWLINE, "SEC: %02x | KEY : %s |
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
char *ReadSchemasFromSPIFFS(char *filename) {
|
||||||
|
SpinOff(0);
|
||||||
|
|
||||||
|
int changed = rdv40_spiffs_lazy_mount();
|
||||||
|
uint32_t size = size_in_spiffs((char *)filename);
|
||||||
|
uint8_t *mem = BigBuf_malloc(size);
|
||||||
|
rdv40_spiffs_read_as_filetype((char *)filename, (uint8_t *)mem, size, RDV40_SPIFFS_SAFETY_SAFE);
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
rdv40_spiffs_lazy_unmount();
|
||||||
|
}
|
||||||
|
SpinOff(0);
|
||||||
|
return (char *)mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_schemas_from_json_in_spiffs(char *filename) {
|
||||||
|
|
||||||
|
char *jsonfile = ReadSchemasFromSPIFFS((char *)filename);
|
||||||
|
|
||||||
|
int i, len = strlen(jsonfile);
|
||||||
|
struct json_token t;
|
||||||
|
for (i = 0; json_scanf_array_elem(jsonfile, len, "", i, &t) > 0; i++) {
|
||||||
|
char *tmpname;
|
||||||
|
char *tmptrigger;
|
||||||
|
MFC1KSchema tmpscheme;
|
||||||
|
json_scanf(t.ptr, t.len, "{ name:%Q, trigger:%Q, keysA:%M, keysB:%M}", &tmpname, &tmptrigger, scan_keys,
|
||||||
|
&tmpscheme.keysA, scan_keys, &tmpscheme.keysB);
|
||||||
|
memcpy(tmpscheme.name, tmpname, 32);
|
||||||
|
tmpscheme.trigger = hex2i(tmptrigger);
|
||||||
|
add_schema(Schemas, tmpscheme, &total_schemas);
|
||||||
|
DbprintfEx(FLAG_NEWLINE, "Schema loaded : %s", tmpname);
|
||||||
|
cjSetCursLeft();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ReadLastTagFromFlash() {
|
void ReadLastTagFromFlash() {
|
||||||
SpinOff(0);
|
SpinOff(0);
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
|
@ -168,8 +321,8 @@ void WriteTagToFlash(uint32_t uid, size_t size) {
|
||||||
sprintf(dest, "hf_colin/mf_%02x%02x%02x%02x.bin", buid[0], buid[1], buid[2], buid[3]);
|
sprintf(dest, "hf_colin/mf_%02x%02x%02x%02x.bin", buid[0], buid[1], buid[2], buid[3]);
|
||||||
|
|
||||||
// TODO : by using safe function for multiple writes we are both breaking cache mecanisms and making useless and
|
// TODO : by using safe function for multiple writes we are both breaking cache mecanisms and making useless and
|
||||||
// unoptimized mount operations we should manage at out level the mount status before and after the whole standalone
|
// unoptimized mount operations we should manage at out level the mount status before and after the whole
|
||||||
// mode
|
// standalone mode
|
||||||
rdv40_spiffs_write((char *)dest, (uint8_t *)data, len, RDV40_SPIFFS_SAFETY_SAFE);
|
rdv40_spiffs_write((char *)dest, (uint8_t *)data, len, RDV40_SPIFFS_SAFETY_SAFE);
|
||||||
// lastag will only contain filename/path to last written tag file so we don't loose time or space.
|
// lastag will only contain filename/path to last written tag file so we don't loose time or space.
|
||||||
rdv40_spiffs_make_symlink((char *)dest, (char *)HFCOLIN_LASTTAG_SYMLINK, RDV40_SPIFFS_SAFETY_SAFE);
|
rdv40_spiffs_make_symlink((char *)dest, (char *)HFCOLIN_LASTTAG_SYMLINK, RDV40_SPIFFS_SAFETY_SAFE);
|
||||||
|
@ -185,10 +338,10 @@ void ModInfo(void) { DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIG
|
||||||
void RunMod() {
|
void RunMod() {
|
||||||
StandAloneMode();
|
StandAloneMode();
|
||||||
|
|
||||||
add_schema(Schemas, Noralsy, &total_schemas);
|
// add_schema(Schemas, Noralsy, &total_schemas);
|
||||||
add_schema(Schemas, InfiHexact, &total_schemas);
|
// add_schema(Schemas, InfiHexact, &total_schemas);
|
||||||
add_schema(Schemas, UrmetCaptive, &total_schemas);
|
// add_schema_from_json_in_spiffs((char *)HFCOLIN_URMETCAPTIVE_JSON);
|
||||||
|
// add_schema(Schemas, UrmetCaptive, &total_schemas);
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
|
|
||||||
currline = 20;
|
currline = 20;
|
||||||
|
@ -242,9 +395,7 @@ void RunMod() {
|
||||||
// French VIGIK system @2017
|
// French VIGIK system @2017
|
||||||
//----------------------------
|
//----------------------------
|
||||||
|
|
||||||
#define STKEYS 37
|
const uint64_t mfKeys[] = {
|
||||||
|
|
||||||
const uint64_t mfKeys[STKEYS] = {
|
|
||||||
0xffffffffffff, // TRANSPORTS
|
0xffffffffffff, // TRANSPORTS
|
||||||
0x000000000000, // Blankkey
|
0x000000000000, // Blankkey
|
||||||
0x484558414354, // INFINEONON A / 0F SEC B / INTRATONE / HEXACT...
|
0x484558414354, // INFINEONON A / 0F SEC B / INTRATONE / HEXACT...
|
||||||
|
@ -285,8 +436,8 @@ void RunMod() {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Can remember something like that in case of Bigbuf
|
// Can remember something like that in case of Bigbuf
|
||||||
keyBlock = BigBuf_malloc(STKEYS * 6);
|
keyBlock = BigBuf_malloc(ARRAYLEN(mfKeys) * 6);
|
||||||
int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t);
|
int mfKeysCnt = ARRAYLEN(mfKeys);
|
||||||
|
|
||||||
for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) {
|
for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) {
|
||||||
num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6));
|
num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6));
|
||||||
|
@ -325,6 +476,8 @@ void RunMod() {
|
||||||
currfline = 24;
|
currfline = 24;
|
||||||
cjSetCursLeft();
|
cjSetCursLeft();
|
||||||
|
|
||||||
|
add_schemas_from_json_in_spiffs((char *)HFCOLIN_SCHEMAS_JSON);
|
||||||
|
|
||||||
failtag:
|
failtag:
|
||||||
|
|
||||||
vtsend_cursor_position_save(NULL);
|
vtsend_cursor_position_save(NULL);
|
||||||
|
@ -419,8 +572,8 @@ failtag:
|
||||||
if (key == -1) {
|
if (key == -1) {
|
||||||
err = 1;
|
err = 1;
|
||||||
allKeysFound = false;
|
allKeysFound = false;
|
||||||
// used in portable imlementation on microcontroller: it reports back the fail and open the standalone
|
// used in portable imlementation on microcontroller: it reports back the fail and open the
|
||||||
// lock reply_old(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0);
|
// standalone lock reply_old(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0);
|
||||||
break;
|
break;
|
||||||
} else if (key == -2) {
|
} else if (key == -2) {
|
||||||
err = 1; // Can't select card.
|
err = 1; // Can't select card.
|
||||||
|
@ -587,7 +740,7 @@ readysim:
|
||||||
// if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) {
|
// if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) {
|
||||||
flags |= FLAG_UID_IN_EMUL;
|
flags |= FLAG_UID_IN_EMUL;
|
||||||
//}
|
//}
|
||||||
Mifare1ksim(flags | FLAG_MF_1K, 0, cjuid);
|
Mifare1ksim(flags | FLAG_MF_1K, 0, cjuid, 0, 0);
|
||||||
LED_C_OFF();
|
LED_C_OFF();
|
||||||
SpinOff(50);
|
SpinOff(50);
|
||||||
vtsend_cursor_position_restore(NULL);
|
vtsend_cursor_position_restore(NULL);
|
||||||
|
|
|
@ -16,22 +16,6 @@
|
||||||
#ifndef __HF_COLIN_H
|
#ifndef __HF_COLIN_H
|
||||||
#define __HF_COLIN_H
|
#define __HF_COLIN_H
|
||||||
|
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "mifaresim.h" // mifare1ksim
|
|
||||||
#include "mifareutil.h"
|
|
||||||
#include "iso14443a.h"
|
|
||||||
#include "protocols.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "pmflash.h"
|
|
||||||
#include "standalone.h" // standalone definitions
|
|
||||||
#include <stdbool.h> // for bool
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "vtsend.h"
|
|
||||||
#include "apps.h"
|
|
||||||
#include "printf.h"
|
|
||||||
#include "spiffs.h"
|
|
||||||
|
|
||||||
#define _XRED_ "\x1b[31m"
|
#define _XRED_ "\x1b[31m"
|
||||||
#define _XGREEN_ "\x1b[32m"
|
#define _XGREEN_ "\x1b[32m"
|
||||||
#define _XYELLOW_ "\x1b[33m"
|
#define _XYELLOW_ "\x1b[33m"
|
||||||
|
|
|
@ -33,7 +33,21 @@ on a blank card.
|
||||||
## Spanish full description of the project [here](http://bit.ly/2c9nZXR).
|
## Spanish full description of the project [here](http://bit.ly/2c9nZXR).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hf_mattyrun.h"
|
#include "standalone.h" // standalone definitions
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "appmain.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "commonutil.h"
|
||||||
|
#include "iso14443a.h"
|
||||||
|
#include "mifarecmd.h"
|
||||||
|
#include "crc16.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "mifaresim.h" // mifare1ksim
|
||||||
|
#include "mifareutil.h"
|
||||||
|
|
||||||
uint8_t uid[10];
|
uint8_t uid[10];
|
||||||
uint32_t cuid;
|
uint32_t cuid;
|
||||||
|
@ -262,7 +276,7 @@ void RunMod() {
|
||||||
keys in keyBlock's memory space .
|
keys in keyBlock's memory space .
|
||||||
*/
|
*/
|
||||||
keyBlock = BigBuf_malloc(stKeyBlock * 6);
|
keyBlock = BigBuf_malloc(stKeyBlock * 6);
|
||||||
int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t);
|
int mfKeysCnt = ARRAYLEN(mfKeys);
|
||||||
|
|
||||||
for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) {
|
for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) {
|
||||||
num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6));
|
num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6));
|
||||||
|
@ -400,7 +414,7 @@ void RunMod() {
|
||||||
simflags = FLAG_4B_UID_IN_DATA;
|
simflags = FLAG_4B_UID_IN_DATA;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Mifare1ksim(simflags | FLAG_MF_1K, 0, uid);
|
Mifare1ksim(simflags | FLAG_MF_1K, 0, uid, 0, 0);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Matías A. Ré Medina 2016
|
|
||||||
// Christian Herrmann, 2018
|
|
||||||
//
|
|
||||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
|
||||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
|
||||||
// the license.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// StandAlone Mod
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifndef __HF_MATTYRUN_H
|
|
||||||
#define __HF_MATTYRUN_H
|
|
||||||
|
|
||||||
#include "standalone.h" // standalone definitions
|
|
||||||
#include "apps.h" // debugstatements, lfops?
|
|
||||||
#include "pm3_cmd.h" // mifare1ksim flags
|
|
||||||
#include "mifaresim.h" // mifare1ksim
|
|
||||||
#include "mifareutil.h"
|
|
||||||
|
|
||||||
#define OPTS 2
|
|
||||||
|
|
||||||
#endif /* __HF_MATTYRUN_H */
|
|
|
@ -9,8 +9,21 @@
|
||||||
// main code for HF standalone mode Mifare /sniff/emulation by Craig Young
|
// main code for HF standalone mode Mifare /sniff/emulation by Craig Young
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "hf_young.h"
|
#include "standalone.h" // standalone definitions
|
||||||
#include "common.h"
|
#include <inttypes.h>
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "appmain.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "commonutil.h"
|
||||||
|
#include "mifarecmd.h"
|
||||||
|
#include "iso14443a.h"
|
||||||
|
#include "protocols.h"
|
||||||
|
|
||||||
|
#define OPTS 2
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t uid[10];
|
uint8_t uid[10];
|
||||||
|
@ -138,18 +151,18 @@ void RunMod() {
|
||||||
SpinDelay(500);
|
SpinDelay(500);
|
||||||
// Begin clone function here:
|
// Begin clone function here:
|
||||||
/* Example from client/mifarehost.c for commanding a block write for "magic Chinese" cards:
|
/* Example from client/mifarehost.c for commanding a block write for "magic Chinese" cards:
|
||||||
SendCommandOLD(CMD_MIFARE_CSETBLOCK, params & (0xFE | (uid == NULL ? 0:1)), blockNo, 0, data, 16);
|
SendCommandOLD(CMD_HF_MIFARE_CSETBL, params & (0xFE | (uid == NULL ? 0:1)), blockNo, 0, data, 16);
|
||||||
|
|
||||||
Block read is similar:
|
Block read is similar:
|
||||||
SendCommandOLD(CMD_MIFARE_CGETBLOCK, params, blockNo, 0,...};
|
SendCommandOLD(CMD_HF_MIFARE_CGETBL, params, blockNo, 0,...};
|
||||||
We need to imitate that call with blockNo 0 to set a uid.
|
We need to imitate that call with blockNo 0 to set a uid.
|
||||||
|
|
||||||
The get and set commands are handled in this file:
|
The get and set commands are handled in this file:
|
||||||
// Work with "magic Chinese" card
|
// Work with "magic Chinese" card
|
||||||
case CMD_MIFARE_CSETBLOCK:
|
case CMD_HF_MIFARE_CSETBL:
|
||||||
MifareCSetBlock(c->arg[0], c->arg[1], c->d.asBytes);
|
MifareCSetBlock(c->arg[0], c->arg[1], c->d.asBytes);
|
||||||
break;
|
break;
|
||||||
case CMD_MIFARE_CGETBLOCK:
|
case CMD_HF_MIFARE_CGETBL:
|
||||||
MifareCGetBlock(c->arg[0], c->arg[1], c->d.asBytes);
|
MifareCGetBlock(c->arg[0], c->arg[1], c->d.asBytes);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,19 @@
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
// main code for LF aka HID corporate brutefore by Federico Dotta & Maurizio Agazzini
|
// main code for LF aka HID corporate brutefore by Federico Dotta & Maurizio Agazzini
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
|
#include "standalone.h" // standalone definitions
|
||||||
#include "lf_hidbrute.h"
|
#include "lf_hidbrute.h"
|
||||||
|
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "appmain.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "lfops.h"
|
||||||
|
|
||||||
|
#define OPTS 3
|
||||||
|
|
||||||
void ModInfo(void) {
|
void ModInfo(void) {
|
||||||
DbpString(" LF HID corporate 1000 bruteforce - aka Corporatebrute (Federico dotta & Maurizio Agazzini)");
|
DbpString(" LF HID corporate 1000 bruteforce - aka Corporatebrute (Federico dotta & Maurizio Agazzini)");
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,7 @@
|
||||||
#ifndef __LF_HIDBRUTE_H
|
#ifndef __LF_HIDBRUTE_H
|
||||||
#define __LF_HIDBRUTE_H
|
#define __LF_HIDBRUTE_H
|
||||||
|
|
||||||
#include "standalone.h" // standalone definitions
|
#include <stdint.h>
|
||||||
#include "apps.h" // debugstatements, lfops?
|
|
||||||
|
|
||||||
#define OPTS 3
|
|
||||||
|
|
||||||
void hid_corporate_1000_calculate_checksum_and_set(uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc);
|
void hid_corporate_1000_calculate_checksum_and_set(uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc);
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,12 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// main code for skeleton aka IceRun by Iceman
|
// main code for skeleton aka IceRun by Iceman
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "lf_icerun.h"
|
#include "standalone.h" // standalone definitions
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "appmain.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
|
||||||
void ModInfo(void) {
|
void ModInfo(void) {
|
||||||
DbpString(" LF skeleton mode - aka IceRun (iceman)");
|
DbpString(" LF skeleton mode - aka IceRun (iceman)");
|
||||||
|
|
|
@ -9,7 +9,16 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// main code for LF aka Proxbrute by Brad antoniewicz
|
// main code for LF aka Proxbrute by Brad antoniewicz
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "lf_proxbrute.h"
|
#include "standalone.h" // standalone definitions
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "appmain.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "lfops.h"
|
||||||
|
|
||||||
|
#define OPTS 2
|
||||||
|
|
||||||
void ModInfo(void) {
|
void ModInfo(void) {
|
||||||
DbpString(" LF HID ProxII bruteforce - aka Proxbrute (Brad Antoniewicz)");
|
DbpString(" LF HID ProxII bruteforce - aka Proxbrute (Brad Antoniewicz)");
|
||||||
|
|
|
@ -8,7 +8,16 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// main code for LF aka SamyRun by Samy Kamkar
|
// main code for LF aka SamyRun by Samy Kamkar
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "lf_samyrun.h"
|
#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 "ticks.h"
|
||||||
|
|
||||||
|
#define OPTS 2
|
||||||
|
|
||||||
void ModInfo(void) {
|
void ModInfo(void) {
|
||||||
DbpString(" LF HID26 standalone - aka SamyRun (Samy Kamkar)");
|
DbpString(" LF HID26 standalone - aka SamyRun (Samy Kamkar)");
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "standalone.h" // standalone definitions
|
#include "standalone.h" // standalone definitions
|
||||||
#include "apps.h" // debug statements
|
|
||||||
|
#include "dbprint.h"
|
||||||
|
|
||||||
void ModInfo(void) {
|
void ModInfo(void) {
|
||||||
DbpString(" No standalone mode present");
|
DbpString(" No standalone mode present");
|
||||||
|
|
|
@ -11,9 +11,6 @@
|
||||||
#ifndef __STANDALONE_H
|
#ifndef __STANDALONE_H
|
||||||
#define __STANDALONE_H
|
#define __STANDALONE_H
|
||||||
|
|
||||||
#include <stdbool.h> // for bool
|
|
||||||
#include <inttypes.h> // PRIu64
|
|
||||||
|
|
||||||
void RunMod();
|
void RunMod();
|
||||||
void ModInfo();
|
void ModInfo();
|
||||||
|
|
||||||
|
|
487
armsrc/appmain.c
487
armsrc/appmain.c
File diff suppressed because it is too large
Load diff
45
armsrc/appmain.h
Normal file
45
armsrc/appmain.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Jonathan Westhues, Aug 2005
|
||||||
|
// Gerhard de Koning Gans, April 2008, May 2011
|
||||||
|
//
|
||||||
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
// the license.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Definitions internal to the app source.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifndef __APPMAIN_H
|
||||||
|
#define __APPMAIN_H
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
extern const uint8_t OddByteParity[256];
|
||||||
|
extern int rsamples; // = 0;
|
||||||
|
extern uint8_t trigger;
|
||||||
|
extern bool allow_send_wtx;
|
||||||
|
|
||||||
|
// ADC Vref = 3300mV, and an (10M+1M):1M voltage divider on the HF input can measure voltages up to 36300 mV
|
||||||
|
#define MAX_ADC_HF_VOLTAGE 36300
|
||||||
|
// ADC Vref = 3300mV, (240k-10M):240k voltage divider, 140800 mV
|
||||||
|
#define MAX_ADC_HF_VOLTAGE_RDV40 140800
|
||||||
|
// ADC Vref = 3300mV, and an (10000k+240k):240k voltage divider on the LF input can measure voltages up to 140800 mV
|
||||||
|
#define MAX_ADC_LF_VOLTAGE 140800
|
||||||
|
|
||||||
|
extern int ToSendMax;
|
||||||
|
extern uint8_t ToSend[];
|
||||||
|
|
||||||
|
void send_wtx(uint16_t wtx);
|
||||||
|
void ReadMem(int addr);
|
||||||
|
void __attribute__((noreturn)) AppMain(void);
|
||||||
|
|
||||||
|
uint16_t AvgAdc(int ch);
|
||||||
|
|
||||||
|
void print_result(char *name, uint8_t *buf, size_t len);
|
||||||
|
//void PrintToSendBuffer(void);
|
||||||
|
void ToSendStuffBit(int b);
|
||||||
|
void ToSendReset(void);
|
||||||
|
void ListenReaderField(uint8_t limit);
|
||||||
|
void StandAloneMode(void);
|
||||||
|
void printStandAloneModes(void);
|
||||||
|
|
||||||
|
#endif
|
253
armsrc/apps.h
253
armsrc/apps.h
|
@ -1,253 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Jonathan Westhues, Aug 2005
|
|
||||||
// Gerhard de Koning Gans, April 2008, May 2011
|
|
||||||
//
|
|
||||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
|
||||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
|
||||||
// the license.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Definitions internal to the app source.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#ifndef __APPS_H
|
|
||||||
#define __APPS_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include "common.h"
|
|
||||||
#include "usb_cdc.h"
|
|
||||||
#include "crc32.h"
|
|
||||||
#include "lfdemod.h"
|
|
||||||
#include "BigBuf.h"
|
|
||||||
#include "fpgaloader.h"
|
|
||||||
#include "hitag2.h"
|
|
||||||
#include "hitagS.h"
|
|
||||||
#include "mifare.h"
|
|
||||||
#include "pcf7931.h"
|
|
||||||
#include "desfire.h"
|
|
||||||
#include "iso14443b.h"
|
|
||||||
#include "Standalone/standalone.h"
|
|
||||||
#include "flashmem.h"
|
|
||||||
|
|
||||||
extern const uint8_t OddByteParity[256];
|
|
||||||
extern int rsamples; // = 0;
|
|
||||||
extern uint8_t trigger;
|
|
||||||
|
|
||||||
// This may be used (sparingly) to declare a function to be copied to
|
|
||||||
// and executed from RAM
|
|
||||||
#define RAMFUNC __attribute((long_call, section(".ramfunc")))
|
|
||||||
|
|
||||||
/// appmain.h
|
|
||||||
void ReadMem(int addr);
|
|
||||||
void __attribute__((noreturn)) AppMain(void);
|
|
||||||
//void DbpIntegers(int a, int b, int c);
|
|
||||||
void DbpString(char *str);
|
|
||||||
void DbpStringEx(uint32_t flags, char *str);
|
|
||||||
void Dbprintf(const char *fmt, ...);
|
|
||||||
void DbprintfEx(uint32_t flags, const char *fmt, ...);
|
|
||||||
void Dbhexdump(int len, uint8_t *d, bool bAsci);
|
|
||||||
|
|
||||||
// ADC Vref = 3300mV, and an (10M+1M):1M voltage divider on the HF input can measure voltages up to 36300 mV
|
|
||||||
#define MAX_ADC_HF_VOLTAGE 36300
|
|
||||||
// ADC Vref = 3300mV, (240k-10M):240k voltage divider, 140800 mV
|
|
||||||
#define MAX_ADC_HF_VOLTAGE_RDV40 140800
|
|
||||||
// ADC Vref = 3300mV, and an (10000k+240k):240k voltage divider on the LF input can measure voltages up to 140800 mV
|
|
||||||
#define MAX_ADC_LF_VOLTAGE 140800
|
|
||||||
uint16_t AvgAdc(int ch);
|
|
||||||
|
|
||||||
void print_result(char *name, uint8_t *buf, size_t len);
|
|
||||||
//void PrintToSendBuffer(void);
|
|
||||||
void ToSendStuffBit(int b);
|
|
||||||
void ToSendReset(void);
|
|
||||||
void ListenReaderField(uint8_t limit);
|
|
||||||
extern int ToSendMax;
|
|
||||||
extern uint8_t ToSend[];
|
|
||||||
|
|
||||||
void StandAloneMode(void);
|
|
||||||
void printStandAloneModes(void);
|
|
||||||
|
|
||||||
/// lfops.h
|
|
||||||
extern uint8_t decimation;
|
|
||||||
extern uint8_t bits_per_sample ;
|
|
||||||
extern bool averaging;
|
|
||||||
|
|
||||||
void AcquireRawAdcSamples125k(int divisor);
|
|
||||||
void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command);
|
|
||||||
void ReadTItag(void);
|
|
||||||
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);
|
|
||||||
|
|
||||||
void AcquireTiType(void);
|
|
||||||
void AcquireRawBitsTI(void);
|
|
||||||
void SimulateTagLowFrequencyEx(int period, int gap, bool ledcontrol, int numcycles);
|
|
||||||
void SimulateTagLowFrequency(int period, int gap, bool ledcontrol);
|
|
||||||
void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
|
|
||||||
|
|
||||||
void CmdHIDsimTAGEx(uint32_t hi, uint32_t lo, bool ledcontrol, int numcycles);
|
|
||||||
void CmdHIDsimTAG(uint32_t hi, uint32_t lo, bool ledcontrol);
|
|
||||||
|
|
||||||
void CmdFSKsimTAG(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, uint8_t *bits, bool ledcontrol);
|
|
||||||
void CmdASKsimTAG(uint8_t encoding, uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol);
|
|
||||||
void CmdPSKsimTag(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol);
|
|
||||||
|
|
||||||
void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol);
|
|
||||||
void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); // Realtime demodulation mode for AWID26
|
|
||||||
void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol);
|
|
||||||
void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol);
|
|
||||||
void CopyIOtoT55x7(uint32_t hi, uint32_t lo); // Clone an ioProx card to T5557/T5567
|
|
||||||
void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567
|
|
||||||
void CopyVikingtoT55xx(uint32_t block1, uint32_t block2, uint8_t Q5);
|
|
||||||
void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo);
|
|
||||||
void CopyIndala64toT55x7(uint32_t hi, uint32_t lo); // Clone Indala 64-bit tag by UID to T55x7
|
|
||||||
void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7); // Clone Indala 224-bit tag by UID to T55x7
|
|
||||||
void T55xxResetRead(uint8_t flags);
|
|
||||||
//id T55xxWriteBlock(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags);
|
|
||||||
void T55xxWriteBlock(uint8_t *data);
|
|
||||||
// void T55xxWriteBlockExt(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags);
|
|
||||||
void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block, uint32_t pwd, uint8_t downlink_mode);
|
|
||||||
void T55xxWakeUp(uint32_t Pwd, uint8_t flags);
|
|
||||||
void T55xx_ChkPwds(uint8_t flags);
|
|
||||||
|
|
||||||
void TurnReadLFOn(uint32_t delay);
|
|
||||||
|
|
||||||
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd);
|
|
||||||
void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd);
|
|
||||||
|
|
||||||
void Cotag(uint32_t arg0);
|
|
||||||
void setT55xxConfig(uint8_t arg0, t55xx_config *c);
|
|
||||||
t55xx_config *getT55xxConfig(void);
|
|
||||||
void printT55xxConfig(void);
|
|
||||||
void loadT55xxConfig(void);
|
|
||||||
|
|
||||||
/// iso14443b.h
|
|
||||||
void SimulateIso14443bTag(uint32_t pupi);
|
|
||||||
void AcquireRawAdcSamplesIso14443b(uint32_t parameter);
|
|
||||||
void ReadSTMemoryIso14443b(uint8_t numofblocks);
|
|
||||||
void RAMFUNC SniffIso14443b(void);
|
|
||||||
void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]);
|
|
||||||
void SendRawCommand14443B_Ex(PacketCommandNG *c);
|
|
||||||
void ClearFpgaShiftingRegisters(void);
|
|
||||||
|
|
||||||
// iso14443a.h
|
|
||||||
void RAMFUNC SniffIso14443a(uint8_t param);
|
|
||||||
void ReaderIso14443a(PacketCommandNG *c);
|
|
||||||
|
|
||||||
// Also used in iclass.c
|
|
||||||
//bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t len, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
|
|
||||||
void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par);
|
|
||||||
void iso14a_set_trigger(bool enable);
|
|
||||||
// also used in emv
|
|
||||||
//bool prepare_allocated_tag_modulation(tag_response_info_t *response_info);
|
|
||||||
//int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len);
|
|
||||||
|
|
||||||
// epa.h
|
|
||||||
void EPA_PACE_Collect_Nonce(PacketCommandNG *c);
|
|
||||||
void EPA_PACE_Replay(PacketCommandNG *c);
|
|
||||||
|
|
||||||
// mifarecmd.h
|
|
||||||
void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain);
|
|
||||||
|
|
||||||
void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
|
||||||
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 MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain);
|
|
||||||
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
|
||||||
void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
|
||||||
void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
|
|
||||||
void MifareAcquireNonces(uint32_t arg0, uint32_t flags);
|
|
||||||
void MifareChkKeys(uint8_t *datain);
|
|
||||||
void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
|
||||||
|
|
||||||
void MifareEMemClr(void);
|
|
||||||
void MifareEMemSet(uint8_t blockno, uint8_t blockcnt, uint8_t blockwidth, uint8_t *datain);
|
|
||||||
void MifareEMemGet(uint8_t blockno, uint8_t blockcnt);
|
|
||||||
int MifareECardLoad(uint32_t arg0, uint32_t arg1);
|
|
||||||
|
|
||||||
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(); // is "magic chinese" card?
|
|
||||||
|
|
||||||
void MifareSetMod(uint8_t *datain);
|
|
||||||
void MifareUSetPwd(uint8_t arg0, uint8_t *datain);
|
|
||||||
void OnSuccessMagic();
|
|
||||||
void OnErrorMagic(uint8_t reason);
|
|
||||||
|
|
||||||
int32_t dist_nt(uint32_t nt1, uint32_t nt2);
|
|
||||||
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype);
|
|
||||||
//void RAMFUNC SniffMifare(uint8_t param);
|
|
||||||
|
|
||||||
//desfire
|
|
||||||
void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain);
|
|
||||||
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
|
|
||||||
|
|
||||||
// mifaredesfire.h
|
|
||||||
bool InitDesfireCard();
|
|
||||||
void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
|
||||||
void MifareDesfireGetInformation();
|
|
||||||
void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
|
||||||
void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t *datain);
|
|
||||||
int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout);
|
|
||||||
size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout);
|
|
||||||
void OnSuccess();
|
|
||||||
void OnError(uint8_t reason);
|
|
||||||
|
|
||||||
// desfire_crypto.h
|
|
||||||
void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings);
|
|
||||||
void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings);
|
|
||||||
void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size);
|
|
||||||
void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation);
|
|
||||||
size_t key_block_size(const desfirekey_t key);
|
|
||||||
size_t padded_data_length(const size_t nbytes, const size_t block_size);
|
|
||||||
size_t maced_data_length(const desfirekey_t key, const size_t nbytes);
|
|
||||||
size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int communication_settings);
|
|
||||||
void cmac_generate_subkeys(desfirekey_t key);
|
|
||||||
void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
|
|
||||||
|
|
||||||
// iso15693.h
|
|
||||||
void RecordRawAdcSamplesIso15693(void);
|
|
||||||
void AcquireRawAdcSamplesIso15693(void);
|
|
||||||
void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg
|
|
||||||
void SimTagIso15693(uint32_t parameter, uint8_t *uid); // simulate an ISO15693 tag - greg
|
|
||||||
void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox
|
|
||||||
void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI - atrox
|
|
||||||
void Iso15693InitReader(void);
|
|
||||||
|
|
||||||
// iclass.h
|
|
||||||
void RAMFUNC SniffIClass(void);
|
|
||||||
void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
|
||||||
void ReaderIClass(uint8_t arg0);
|
|
||||||
void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac);
|
|
||||||
void iClass_Authentication(uint8_t *mac);
|
|
||||||
void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain);
|
|
||||||
void iClass_WriteBlock(uint8_t blockno, uint8_t *data);
|
|
||||||
void iClass_ReadBlk(uint8_t blockno);
|
|
||||||
bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len);
|
|
||||||
void iClass_Dump(uint8_t blockno, uint8_t numblks);
|
|
||||||
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data);
|
|
||||||
void iClass_ReadCheck(uint8_t blockno, uint8_t keytype);
|
|
||||||
|
|
||||||
// cmd.h
|
|
||||||
int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
|
|
||||||
int reply_mix(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
|
|
||||||
int reply_ng(uint16_t cmd, int16_t status, uint8_t *data, size_t len);
|
|
||||||
int receive_ng(PacketCommandNG *rx);
|
|
||||||
|
|
||||||
// util.h
|
|
||||||
void HfSniff(int, int);
|
|
||||||
|
|
||||||
//felica.c
|
|
||||||
void felica_sendraw(PacketCommandNG *c);
|
|
||||||
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip);
|
|
||||||
void felica_sim_lite(uint64_t uid);
|
|
||||||
void felica_dump_lite_s();
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -5,10 +5,7 @@
|
||||||
#ifndef __BUZZER_H
|
#ifndef __BUZZER_H
|
||||||
#define __BUZZER_H
|
#define __BUZZER_H
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include "common.h"
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "apps.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
#define n_2_7khz 185
|
#define n_2_7khz 185
|
||||||
#define note_1 956
|
#define note_1 956
|
||||||
|
@ -27,24 +24,3 @@ void Ring_ALL(uint16_t count);
|
||||||
void Ring_Little_Star(uint16_t count);
|
void Ring_Little_Star(uint16_t count);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,10 @@
|
||||||
* @brief
|
* @brief
|
||||||
*/
|
*/
|
||||||
#include "cmd.h"
|
#include "cmd.h"
|
||||||
|
#include "usb_cdc.h"
|
||||||
|
#include "usart.h"
|
||||||
#include "crc16.h"
|
#include "crc16.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
// Flags to tell where to add CRC on sent replies
|
// Flags to tell where to add CRC on sent replies
|
||||||
bool reply_with_crc_on_usb = false;
|
bool reply_with_crc_on_usb = false;
|
|
@ -35,14 +35,6 @@
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "pm3_cmd.h"
|
#include "pm3_cmd.h"
|
||||||
#include "usb_cdc.h"
|
|
||||||
#include "usart.h"
|
|
||||||
#include "proxmark3.h"
|
|
||||||
|
|
||||||
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_mix(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
|
|
||||||
int receive_ng(PacketCommandNG *rx);
|
|
||||||
|
|
||||||
// Flags to tell where to add CRC on sent replies
|
// Flags to tell where to add CRC on sent replies
|
||||||
extern bool reply_with_crc_on_usb;
|
extern bool reply_with_crc_on_usb;
|
||||||
|
@ -51,33 +43,10 @@ extern bool reply_with_crc_on_fpc;
|
||||||
extern bool reply_via_fpc;
|
extern bool reply_via_fpc;
|
||||||
extern bool reply_via_usb;
|
extern bool reply_via_usb;
|
||||||
|
|
||||||
extern void Dbprintf(const char *fmt, ...);
|
int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
|
||||||
#define Dbprintf_usb(...) {\
|
int reply_ng(uint16_t cmd, int16_t status, uint8_t *data, size_t len);
|
||||||
bool tmpfpc = reply_via_fpc;\
|
int reply_mix(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
|
||||||
bool tmpusb = reply_via_usb;\
|
int receive_ng(PacketCommandNG *rx);
|
||||||
reply_via_fpc = false;\
|
|
||||||
reply_via_usb = true;\
|
|
||||||
Dbprintf(__VA_ARGS__);\
|
|
||||||
reply_via_fpc = tmpfpc;\
|
|
||||||
reply_via_usb = tmpusb;}
|
|
||||||
|
|
||||||
#define Dbprintf_fpc(...) {\
|
|
||||||
bool tmpfpc = reply_via_fpc;\
|
|
||||||
bool tmpusb = reply_via_usb;\
|
|
||||||
reply_via_fpc = true;\
|
|
||||||
reply_via_usb = false;\
|
|
||||||
Dbprintf(__VA_ARGS__);\
|
|
||||||
reply_via_fpc = tmpfpc;\
|
|
||||||
reply_via_usb = tmpusb;}
|
|
||||||
|
|
||||||
#define Dbprintf_all(...) {\
|
|
||||||
bool tmpfpc = reply_via_fpc;\
|
|
||||||
bool tmpusb = reply_via_usb;\
|
|
||||||
reply_via_fpc = true;\
|
|
||||||
reply_via_usb = true;\
|
|
||||||
Dbprintf(__VA_ARGS__);\
|
|
||||||
reply_via_fpc = tmpfpc;\
|
|
||||||
reply_via_usb = tmpusb;}
|
|
||||||
|
|
||||||
#endif // _PROXMARK_CMD_H_
|
#endif // _PROXMARK_CMD_H_
|
||||||
|
|
130
armsrc/dbprint.c
Normal file
130
armsrc/dbprint.c
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Jonathan Westhues, Mar 2006
|
||||||
|
// Edits by Gerhard de Koning Gans, Sep 2007 (##)
|
||||||
|
//
|
||||||
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
// the license.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// The main application code. This is the first thing called after start.c
|
||||||
|
// executes.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "dbprint.h"
|
||||||
|
|
||||||
|
#include "string.h"
|
||||||
|
#include "cmd.h"
|
||||||
|
#include "printf.h"
|
||||||
|
|
||||||
|
#define DEBUG 1
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Debug print functions, to go out over USB, to the usual PC-side client.
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void DbpStringEx(uint32_t flags, char *str) {
|
||||||
|
#if DEBUG
|
||||||
|
struct {
|
||||||
|
uint16_t flag;
|
||||||
|
uint8_t buf[PM3_CMD_DATA_SIZE - sizeof(uint16_t)];
|
||||||
|
} PACKED data;
|
||||||
|
data.flag = flags;
|
||||||
|
uint16_t len = MIN(strlen(str), sizeof(data.buf));
|
||||||
|
memcpy(data.buf, str, len);
|
||||||
|
reply_ng(CMD_DEBUG_PRINT_STRING, PM3_SUCCESS, (uint8_t *)&data, sizeof(data.flag) + len);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void DbpString(char *str) {
|
||||||
|
#if DEBUG
|
||||||
|
DbpStringEx(FLAG_LOG, str);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void DbprintfEx(uint32_t flags, const char *fmt, ...) {
|
||||||
|
#if DEBUG
|
||||||
|
// should probably limit size here; oh well, let's just use a big buffer
|
||||||
|
char output_string[128] = {0x00};
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
kvsprintf(fmt, output_string, 10, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
DbpStringEx(flags, output_string);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dbprintf(const char *fmt, ...) {
|
||||||
|
#if DEBUG
|
||||||
|
// should probably limit size here; oh well, let's just use a big buffer
|
||||||
|
char output_string[128] = {0x00};
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
kvsprintf(fmt, output_string, 10, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
DbpString(output_string);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// prints HEX & ASCII
|
||||||
|
void Dbhexdump(int len, uint8_t *d, bool bAsci) {
|
||||||
|
#if DEBUG
|
||||||
|
char ascii[9];
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
|
||||||
|
int l = (len > 8) ? 8 : len;
|
||||||
|
|
||||||
|
memcpy(ascii, d, l);
|
||||||
|
ascii[l] = 0;
|
||||||
|
|
||||||
|
// filter safe ascii
|
||||||
|
for (int i = 0; i < l; i++) {
|
||||||
|
if (ascii[i] < 32 || ascii[i] > 126) {
|
||||||
|
ascii[i] = '.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bAsci)
|
||||||
|
Dbprintf("%-8s %*D", ascii, l, d, " ");
|
||||||
|
else
|
||||||
|
Dbprintf("%*D", l, d, " ");
|
||||||
|
|
||||||
|
len -= 8;
|
||||||
|
d += 8;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_result(char *name, uint8_t *buf, size_t len) {
|
||||||
|
|
||||||
|
uint8_t *p = buf;
|
||||||
|
uint16_t tmp = len & 0xFFF0;
|
||||||
|
|
||||||
|
for (; p - buf < tmp; p += 16) {
|
||||||
|
Dbprintf("[%s: %02d/%02d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||||
|
name,
|
||||||
|
p - buf,
|
||||||
|
len,
|
||||||
|
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (len % 16 != 0) {
|
||||||
|
char s[46] = {0};
|
||||||
|
char *sp = s;
|
||||||
|
for (; p - buf < len; p++) {
|
||||||
|
sprintf(sp, "%02x ", p[0]);
|
||||||
|
sp += 3;
|
||||||
|
}
|
||||||
|
Dbprintf("[%s: %02d/%02d] %s", name, p - buf, len, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* useful when debugging new protocol implementations like FeliCa
|
||||||
|
void PrintToSendBuffer(void) {
|
||||||
|
DbpString("Printing ToSendBuffer:");
|
||||||
|
Dbhexdump(ToSendMax, ToSend, 0);
|
||||||
|
}
|
||||||
|
*/
|
53
armsrc/dbprint.h
Normal file
53
armsrc/dbprint.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Jonathan Westhues, Aug 2005
|
||||||
|
// Gerhard de Koning Gans, April 2008, May 2011
|
||||||
|
//
|
||||||
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
// the license.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Definitions internal to the app source.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifndef __DBPRINT_H
|
||||||
|
#define __DBPRINT_H
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "ansi.h"
|
||||||
|
|
||||||
|
#define Dbprintf_usb(...) {\
|
||||||
|
bool tmpfpc = reply_via_fpc;\
|
||||||
|
bool tmpusb = reply_via_usb;\
|
||||||
|
reply_via_fpc = false;\
|
||||||
|
reply_via_usb = true;\
|
||||||
|
Dbprintf(__VA_ARGS__);\
|
||||||
|
reply_via_fpc = tmpfpc;\
|
||||||
|
reply_via_usb = tmpusb;}
|
||||||
|
|
||||||
|
#define Dbprintf_fpc(...) {\
|
||||||
|
bool tmpfpc = reply_via_fpc;\
|
||||||
|
bool tmpusb = reply_via_usb;\
|
||||||
|
reply_via_fpc = true;\
|
||||||
|
reply_via_usb = false;\
|
||||||
|
Dbprintf(__VA_ARGS__);\
|
||||||
|
reply_via_fpc = tmpfpc;\
|
||||||
|
reply_via_usb = tmpusb;}
|
||||||
|
|
||||||
|
#define Dbprintf_all(...) {\
|
||||||
|
bool tmpfpc = reply_via_fpc;\
|
||||||
|
bool tmpusb = reply_via_usb;\
|
||||||
|
reply_via_fpc = true;\
|
||||||
|
reply_via_usb = true;\
|
||||||
|
Dbprintf(__VA_ARGS__);\
|
||||||
|
reply_via_fpc = tmpfpc;\
|
||||||
|
reply_via_usb = tmpusb;}
|
||||||
|
|
||||||
|
|
||||||
|
void DbpString(char *str);
|
||||||
|
void DbpStringEx(uint32_t flags, char *str);
|
||||||
|
void Dbprintf(const char *fmt, ...);
|
||||||
|
void DbprintfEx(uint32_t flags, const char *fmt, ...);
|
||||||
|
void Dbhexdump(int len, uint8_t *d, bool bAsci);
|
||||||
|
void print_result(char *name, uint8_t *buf, size_t len);
|
||||||
|
//void PrintToSendBuffer(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -27,6 +27,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "des.h"
|
#include "des.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
const uint8_t sbox[256] = {
|
const uint8_t sbox[256] = {
|
||||||
/* S-box 1 */
|
/* S-box 1 */
|
||||||
|
|
|
@ -27,8 +27,7 @@
|
||||||
#ifndef __DES_H_
|
#ifndef __DES_H_
|
||||||
#define __DES_H_
|
#define __DES_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include "common.h"
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/* the FIPS 46-3 (1999-10-25) name for triple DES is triple data encryption algorithm so TDEA.
|
/* the FIPS 46-3 (1999-10-25) name for triple DES is triple data encryption algorithm so TDEA.
|
||||||
* Also we only implement the three key mode */
|
* Also we only implement the three key mode */
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
#ifndef __DESFIRE_H
|
#ifndef __DESFIRE_H
|
||||||
#define __DESFIRE_H
|
#define __DESFIRE_H
|
||||||
|
|
||||||
#include <string.h>
|
#include "common.h"
|
||||||
#include <stdarg.h>
|
|
||||||
#include "mbedtls/aes.h"
|
|
||||||
#include "mifare.h"
|
#include "mifare.h"
|
||||||
|
|
||||||
#define MAX_CRYPTO_BLOCK_SIZE 16
|
#define MAX_CRYPTO_BLOCK_SIZE 16
|
|
@ -1,18 +0,0 @@
|
||||||
#ifndef __DESFIRE_CRYPTO_H
|
|
||||||
#define __DESFIRE_CRYPTO_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include "crc32.h"
|
|
||||||
#include "printf.h"
|
|
||||||
#include "desfire.h"
|
|
||||||
#include "iso14443a.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -25,8 +25,16 @@
|
||||||
* Recommendation for Block Cipher Modes of Operation: The CMAC Mode for Authentication
|
* Recommendation for Block Cipher Modes of Operation: The CMAC Mode for Authentication
|
||||||
* May 2005
|
* May 2005
|
||||||
*/
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "desfire_crypto.h"
|
#include "desfire_crypto.h"
|
||||||
|
|
||||||
|
#include "crc32.h"
|
||||||
|
#include "printf.h"
|
||||||
|
#include "desfire.h"
|
||||||
|
#include "iso14443a.h"
|
||||||
|
#include "mbedtls/aes.h"
|
||||||
|
|
||||||
static void xor(const uint8_t *ivect, uint8_t *data, const size_t len);
|
static void xor(const uint8_t *ivect, uint8_t *data, const size_t len);
|
||||||
static size_t key_macing_length(desfirekey_t key);
|
static size_t key_macing_length(desfirekey_t key);
|
||||||
|
|
18
armsrc/desfire_crypto_disabled.h
Normal file
18
armsrc/desfire_crypto_disabled.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef __DESFIRE_CRYPTO_H
|
||||||
|
#define __DESFIRE_CRYPTO_H
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "desfire.h"
|
||||||
|
|
||||||
|
void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings);
|
||||||
|
void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings);
|
||||||
|
void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size);
|
||||||
|
void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation);
|
||||||
|
size_t key_block_size(const desfirekey_t key);
|
||||||
|
size_t padded_data_length(const size_t nbytes, const size_t block_size);
|
||||||
|
size_t maced_data_length(const desfirekey_t key, const size_t nbytes);
|
||||||
|
size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int communication_settings);
|
||||||
|
void cmac_generate_subkeys(desfirekey_t key);
|
||||||
|
void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
|
||||||
|
|
||||||
|
#endif
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "desfire_key.h"
|
#include "desfire_key.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
static inline void update_key_schedules(desfirekey_t key);
|
static inline void update_key_schedules(desfirekey_t key);
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
#ifndef __DESFIRE_KEY_INCLUDED
|
#ifndef __DESFIRE_KEY_INCLUDED
|
||||||
#define __DESFIRE_KEY_INCLUDED
|
#define __DESFIRE_KEY_INCLUDED
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include "common.h"
|
||||||
#include <stdint.h>
|
|
||||||
#include "iso14443a.h"
|
|
||||||
#include "desfire.h"
|
#include "desfire.h"
|
||||||
//#include "mifare.h" // iso14a_card_select_t struct
|
|
||||||
void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key);
|
void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key);
|
||||||
void Desfire_3des_key_new(const uint8_t value[16], desfirekey_t key);
|
void Desfire_3des_key_new(const uint8_t value[16], desfirekey_t key);
|
||||||
void Desfire_des_key_new_with_version(const uint8_t value[8], desfirekey_t key);
|
void Desfire_des_key_new_with_version(const uint8_t value[8], desfirekey_t key);
|
||||||
|
@ -17,4 +14,5 @@ void Desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version,
|
||||||
uint8_t Desfire_key_get_version(desfirekey_t key);
|
uint8_t Desfire_key_get_version(desfirekey_t key);
|
||||||
void Desfire_key_set_version(desfirekey_t key, uint8_t version);
|
void Desfire_key_set_version(desfirekey_t key, uint8_t version);
|
||||||
void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key);
|
void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
#ifndef __EMVCARD_H
|
#ifndef __EMVCARD_H
|
||||||
#define __EMVCARD_H
|
#define __EMVCARD_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include "common.h"
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
//structure to hold received/set tag values
|
//structure to hold received/set tag values
|
||||||
//variable data inputs have length specifiers
|
//variable data inputs have length specifiers
|
14
armsrc/epa.c
14
armsrc/epa.c
|
@ -12,6 +12,16 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "epa.h"
|
#include "epa.h"
|
||||||
|
|
||||||
|
#include "cmd.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "iso14443a.h"
|
||||||
|
#include "iso14443b.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "commonutil.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
|
||||||
// Protocol and Parameter Selection Request for ISO 14443 type A cards
|
// Protocol and Parameter Selection Request for ISO 14443 type A cards
|
||||||
// use regular (1x) speed in both directions
|
// use regular (1x) speed in both directions
|
||||||
// CRC is already included
|
// CRC is already included
|
||||||
|
@ -470,14 +480,14 @@ void EPA_PACE_Replay(PacketCommandNG *c) {
|
||||||
uint8_t response_apdu[300] = {0};
|
uint8_t response_apdu[300] = {0};
|
||||||
|
|
||||||
// now replay the data and measure the timings
|
// now replay the data and measure the timings
|
||||||
for (int i = 0; i < sizeof(apdu_lengths_replay); i++) {
|
for (int i = 0; i < ARRAYLEN(apdu_lengths_replay); i++) {
|
||||||
StartCountUS();
|
StartCountUS();
|
||||||
func_return = EPA_APDU(apdus_replay[i].data,
|
func_return = EPA_APDU(apdus_replay[i].data,
|
||||||
apdu_lengths_replay[i],
|
apdu_lengths_replay[i],
|
||||||
response_apdu);
|
response_apdu);
|
||||||
timings[i] = GetCountUS();
|
timings[i] = GetCountUS();
|
||||||
// every step but the last one should succeed
|
// every step but the last one should succeed
|
||||||
if (i < sizeof(apdu_lengths_replay) - 1
|
if (i < ARRAYLEN(apdu_lengths_replay) - 1
|
||||||
&& (func_return < 6
|
&& (func_return < 6
|
||||||
|| response_apdu[func_return - 4] != 0x90
|
|| response_apdu[func_return - 4] != 0x90
|
||||||
|| response_apdu[func_return - 3] != 0x00)) {
|
|| response_apdu[func_return - 3] != 0x00)) {
|
||||||
|
|
10
armsrc/epa.h
10
armsrc/epa.h
|
@ -11,9 +11,8 @@
|
||||||
#ifndef __EPA_H
|
#ifndef __EPA_H
|
||||||
#define __EPA_H
|
#define __EPA_H
|
||||||
|
|
||||||
#include "cmd.h"
|
#include "common.h"
|
||||||
#include "iso14443a.h"
|
#include "pm3_cmd.h"
|
||||||
#include "iso14443b.h"
|
|
||||||
|
|
||||||
// this struct is used by EPA_Parse_CardAccess and contains info about the
|
// this struct is used by EPA_Parse_CardAccess and contains info about the
|
||||||
// PACE protocol supported by the chip
|
// PACE protocol supported by the chip
|
||||||
|
@ -23,8 +22,6 @@ typedef struct {
|
||||||
uint8_t parameter_id;
|
uint8_t parameter_id;
|
||||||
} pace_version_info_t;
|
} pace_version_info_t;
|
||||||
|
|
||||||
// note: EPA_PACE_Collect_Nonce and EPA_PACE_Replay are declared in apps.h
|
|
||||||
|
|
||||||
// general functions
|
// general functions
|
||||||
void EPA_Finish();
|
void EPA_Finish();
|
||||||
size_t EPA_Parse_CardAccess(uint8_t *data,
|
size_t EPA_Parse_CardAccess(uint8_t *data,
|
||||||
|
@ -37,4 +34,7 @@ int EPA_Setup();
|
||||||
int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password);
|
int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password);
|
||||||
int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce);
|
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);
|
||||||
|
|
||||||
#endif /* __EPA_H */
|
#endif /* __EPA_H */
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
#include "proxmark3.h"
|
#include "felica.h"
|
||||||
#include "apps.h"
|
#include "proxmark3_arm.h"
|
||||||
#include "BigBuf.h"
|
#include "BigBuf.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "usb_cdc.h" // for usb_poll_validate_length
|
|
||||||
#include "protocols.h"
|
#include "protocols.h"
|
||||||
#include "crc16.h" // crc16 ccitt
|
#include "crc16.h" // crc16 ccitt
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "commonutil.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "mifare.h"
|
||||||
|
|
||||||
// FeliCa timings
|
// FeliCa timings
|
||||||
// minimum time between the start bits of consecutive transfers from reader to tag: 6800 carrier (13.56Mhz) cycles
|
// minimum time between the start bits of consecutive transfers from reader to tag: 6800 carrier (13.56MHz) cycles
|
||||||
#ifndef FELICA_REQUEST_GUARD_TIME
|
#ifndef FELICA_REQUEST_GUARD_TIME
|
||||||
# define FELICA_REQUEST_GUARD_TIME (6800/16 + 1)
|
# define FELICA_REQUEST_GUARD_TIME (6800/16 + 1)
|
||||||
#endif
|
#endif
|
||||||
|
@ -746,7 +751,7 @@ void felica_dump_lite_s() {
|
||||||
// for (c=0; c < 8; c++)
|
// for (c=0; c < 8; c++)
|
||||||
// ndef[c] = FelicaFrame.framebytes[c+4];
|
// ndef[c] = FelicaFrame.framebytes[c+4];
|
||||||
|
|
||||||
for (blknum = 0; blknum < sizeof(liteblks);) {
|
for (blknum = 0; blknum < ARRAYLEN(liteblks);) {
|
||||||
|
|
||||||
// block to read.
|
// block to read.
|
||||||
BuildFliteRdblk(ndef, 1, &liteblks[blknum]);
|
BuildFliteRdblk(ndef, 1, &liteblks[blknum]);
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Samy Kamkar, 2011, 2012
|
// Jonathan Westhues, Aug 2005
|
||||||
// Brad antoniewicz 2011
|
// Gerhard de Koning Gans, April 2008, May 2011
|
||||||
// Christian Herrmann, 2017
|
|
||||||
//
|
//
|
||||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
// the license.
|
// the license.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// StandAlone Mod
|
// Definitions internal to the app source.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifndef __FELICA_H
|
||||||
|
#define __FELICA_H
|
||||||
|
|
||||||
#ifndef __LF_PROXBRUTE_H
|
#include "common.h"
|
||||||
#define __LF_PROXBRUTE_H
|
#include "cmd.h"
|
||||||
|
|
||||||
#include "standalone.h" // standalone definitions
|
void felica_sendraw(PacketCommandNG *c);
|
||||||
#include "apps.h" // debugstatements, lfops?
|
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip);
|
||||||
|
void felica_sim_lite(uint64_t uid);
|
||||||
|
void felica_dump_lite_s();
|
||||||
|
|
||||||
#define OPTS 2
|
#endif
|
||||||
|
|
||||||
#endif /* __LF_PROXBRUTE_H */
|
|
|
@ -1,6 +1,11 @@
|
||||||
#include "flashmem.h"
|
#include "flashmem.h"
|
||||||
#include "pmflash.h"
|
#include "pmflash.h"
|
||||||
|
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
/* here: use NCPS2 @ PA10: */
|
/* here: use NCPS2 @ PA10: */
|
||||||
#define SPI_CSR_NUM 2
|
#define SPI_CSR_NUM 2
|
||||||
#define SPI_PCS(npcs) ((~(1 << (npcs)) & 0xF) << 16)
|
#define SPI_PCS(npcs) ((~(1 << (npcs)) & 0xF) << 16)
|
||||||
|
@ -16,7 +21,7 @@ uint32_t FLASHMEM_SPIBAUDRATE = FLASH_BAUD;
|
||||||
|
|
||||||
void FlashmemSetSpiBaudrate(uint32_t baudrate) {
|
void FlashmemSetSpiBaudrate(uint32_t baudrate) {
|
||||||
FLASHMEM_SPIBAUDRATE = baudrate;
|
FLASHMEM_SPIBAUDRATE = baudrate;
|
||||||
Dbprintf("Spi Baudrate : %dMhz", FLASHMEM_SPIBAUDRATE / 1000000);
|
Dbprintf("Spi Baudrate : %dMHz", FLASHMEM_SPIBAUDRATE / 1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize
|
// initialize
|
||||||
|
@ -563,25 +568,28 @@ void Flashmem_print_info(void) {
|
||||||
uint8_t keysum[2];
|
uint8_t keysum[2];
|
||||||
uint16_t num;
|
uint16_t num;
|
||||||
|
|
||||||
|
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||||
uint16_t isok = Flash_ReadDataCont(DEFAULT_MF_KEYS_OFFSET, keysum, 2);
|
uint16_t isok = Flash_ReadDataCont(DEFAULT_MF_KEYS_OFFSET, keysum, 2);
|
||||||
if (isok == 2) {
|
if (isok == 2) {
|
||||||
num = ((keysum[1] << 8) | keysum[0]);
|
num = ((keysum[1] << 8) | keysum[0]);
|
||||||
if (num != 0xFFFF && num != 0x0)
|
if (num != 0xFFFF && num != 0x0)
|
||||||
Dbprintf(" Mifare................"_YELLOW_("%d")"keys", num);
|
Dbprintf(" Mifare.................."_YELLOW_("%d")"keys", num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||||
isok = Flash_ReadDataCont(DEFAULT_T55XX_KEYS_OFFSET, keysum, 2);
|
isok = Flash_ReadDataCont(DEFAULT_T55XX_KEYS_OFFSET, keysum, 2);
|
||||||
if (isok == 2) {
|
if (isok == 2) {
|
||||||
num = ((keysum[1] << 8) | keysum[0]);
|
num = ((keysum[1] << 8) | keysum[0]);
|
||||||
if (num != 0xFFFF && num != 0x0)
|
if (num != 0xFFFF && num != 0x0)
|
||||||
Dbprintf(" T55x7................."_YELLOW_("%d")"keys", num);
|
Dbprintf(" T55x7..................."_YELLOW_("%d")"keys", num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||||
isok = Flash_ReadDataCont(DEFAULT_ICLASS_KEYS_OFFSET, keysum, 2);
|
isok = Flash_ReadDataCont(DEFAULT_ICLASS_KEYS_OFFSET, keysum, 2);
|
||||||
if (isok == 2) {
|
if (isok == 2) {
|
||||||
num = ((keysum[1] << 8) | keysum[0]);
|
num = ((keysum[1] << 8) | keysum[0]);
|
||||||
if (num != 0xFFFF && num != 0x0)
|
if (num != 0xFFFF && num != 0x0)
|
||||||
Dbprintf(" iClass................"_YELLOW_("%d")"keys", num);
|
Dbprintf(" iClass.................."_YELLOW_("%d")"keys", num);
|
||||||
}
|
}
|
||||||
|
|
||||||
FlashStop();
|
FlashStop();
|
||||||
|
|
|
@ -28,9 +28,7 @@
|
||||||
#ifndef __FLASHMEM_H
|
#ifndef __FLASHMEM_H
|
||||||
#define __FLASHMEM_H
|
#define __FLASHMEM_H
|
||||||
|
|
||||||
#include "proxmark3.h"
|
#include "common.h"
|
||||||
#include "apps.h"
|
|
||||||
#include "ticks.h"
|
|
||||||
|
|
||||||
// Used Command
|
// Used Command
|
||||||
#define ID 0x90
|
#define ID 0x90
|
||||||
|
@ -102,7 +100,6 @@
|
||||||
#define MAX_BLOCKS 4
|
#define MAX_BLOCKS 4
|
||||||
#define MAX_SECTORS 16
|
#define MAX_SECTORS 16
|
||||||
|
|
||||||
#define MCK 48000000
|
|
||||||
//#define FLASH_BAUD 24000000
|
//#define FLASH_BAUD 24000000
|
||||||
#define FLASH_MINFAST 24000000 //33000000
|
#define FLASH_MINFAST 24000000 //33000000
|
||||||
#define FLASH_BAUD MCK/2
|
#define FLASH_BAUD MCK/2
|
||||||
|
@ -112,7 +109,6 @@
|
||||||
#define FASTFLASH (FLASHMEM_SPIBAUDRATE > FLASH_MINFAST)
|
#define FASTFLASH (FLASHMEM_SPIBAUDRATE > FLASH_MINFAST)
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
|
||||||
void Dbprintf(const char *fmt, ...);
|
|
||||||
|
|
||||||
void FlashmemSetSpiBaudrate(uint32_t baudrate);
|
void FlashmemSetSpiBaudrate(uint32_t baudrate);
|
||||||
bool FlashInit();
|
bool FlashInit();
|
||||||
|
|
|
@ -11,6 +11,15 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "fpgaloader.h"
|
#include "fpgaloader.h"
|
||||||
|
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "appmain.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "zlib.h"
|
||||||
|
#include "fpga.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
// remember which version of the bitstream we have already downloaded to the FPGA
|
// remember which version of the bitstream we have already downloaded to the FPGA
|
||||||
static int downloaded_bitstream = 0;
|
static int downloaded_bitstream = 0;
|
||||||
|
@ -81,7 +90,7 @@ void SetupSpi(int mode) {
|
||||||
AT91C_BASE_SPI->SPI_CSR[0] =
|
AT91C_BASE_SPI->SPI_CSR[0] =
|
||||||
(1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
|
(1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
|
||||||
(1 << 16) | // Delay Before SPCK (1 MCK period)
|
(1 << 16) | // Delay Before SPCK (1 MCK period)
|
||||||
(6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
|
(6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24MHz/6 = 4M baud
|
||||||
AT91C_SPI_BITS_16 | // Bits per Transfer (16 bits)
|
AT91C_SPI_BITS_16 | // Bits per Transfer (16 bits)
|
||||||
(0 << 3) | // Chip Select inactive after transfer
|
(0 << 3) | // Chip Select inactive after transfer
|
||||||
AT91C_SPI_NCPHA | // Clock Phase data captured on leading edge, changes on following edge
|
AT91C_SPI_NCPHA | // Clock Phase data captured on leading edge, changes on following edge
|
||||||
|
@ -101,7 +110,7 @@ void SetupSpi(int mode) {
|
||||||
AT91C_BASE_SPI->SPI_CSR[2] =
|
AT91C_BASE_SPI->SPI_CSR[2] =
|
||||||
( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
|
( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
|
||||||
( 1 << 16) | // Delay Before SPCK (1 MCK period)
|
( 1 << 16) | // Delay Before SPCK (1 MCK period)
|
||||||
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
|
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24MHz/6 = 4M baud
|
||||||
AT91C_SPI_BITS_9 | // Bits per Transfer (9 bits)
|
AT91C_SPI_BITS_9 | // Bits per Transfer (9 bits)
|
||||||
( 0 << 3) | // Chip Select inactive after transfer
|
( 0 << 3) | // Chip Select inactive after transfer
|
||||||
( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge
|
( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge
|
||||||
|
@ -153,8 +162,7 @@ void FpgaSetupSsc(void) {
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Set up DMA to receive samples from the FPGA. We will use the PDC, with
|
// Set up DMA to receive samples from the FPGA. We will use the PDC, with
|
||||||
// a single buffer as a circular buffer (so that we just chain back to
|
// a single buffer as a circular buffer (so that we just chain back to
|
||||||
// ourselves, not to another buffer). The stuff to manipulate those buffers
|
// ourselves, not to another buffer).
|
||||||
// is in apps.h, because it should be inlined, for speed.
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
bool FpgaSetupSscDma(uint8_t *buf, int len) {
|
bool FpgaSetupSscDma(uint8_t *buf, int len) {
|
||||||
if (buf == NULL) return false;
|
if (buf == NULL) return false;
|
||||||
|
@ -395,6 +403,8 @@ void FpgaDownloadAndGo(int bitstream_version) {
|
||||||
if (downloaded_bitstream == bitstream_version)
|
if (downloaded_bitstream == bitstream_version)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Send waiting time extension request as this will take a while
|
||||||
|
send_wtx(1500);
|
||||||
z_stream compressed_fpga_stream;
|
z_stream compressed_fpga_stream;
|
||||||
uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00};
|
uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00};
|
||||||
|
|
||||||
|
|
|
@ -12,32 +12,10 @@
|
||||||
#ifndef __FPGALOADER_H
|
#ifndef __FPGALOADER_H
|
||||||
#define __FPGALOADER_H
|
#define __FPGALOADER_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include "common.h"
|
||||||
#include <stdbool.h>
|
|
||||||
#include "apps.h"
|
|
||||||
#include "fpga.h"
|
|
||||||
#include "common.h" // standard definitions
|
|
||||||
#include "proxmark3.h" // common area
|
|
||||||
#include "string.h"
|
|
||||||
#include "BigBuf.h" // bigbuf mem
|
|
||||||
#include "zlib.h" // uncompress
|
|
||||||
|
|
||||||
|
|
||||||
void FpgaSendCommand(uint16_t cmd, uint16_t v);
|
|
||||||
void FpgaWriteConfWord(uint8_t v);
|
|
||||||
void FpgaDownloadAndGo(int bitstream_version);
|
|
||||||
// void FpgaGatherVersion(int bitstream_version, char *dst, int len);
|
|
||||||
void FpgaSetupSsc(void);
|
|
||||||
void SetupSpi(int mode);
|
|
||||||
bool FpgaSetupSscDma(uint8_t *buf, int len);
|
|
||||||
void Fpga_print_status(void);
|
|
||||||
int FpgaGetCurrent(void);
|
|
||||||
#define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
|
#define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
|
||||||
#define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
|
#define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
|
||||||
void SetAdcMuxFor(uint32_t whichGpio);
|
|
||||||
|
|
||||||
// extern and generel turn off the antenna method
|
|
||||||
void switch_off(void);
|
|
||||||
|
|
||||||
// definitions for multiple FPGA config files support
|
// definitions for multiple FPGA config files support
|
||||||
#define FPGA_BITSTREAM_LF 1
|
#define FPGA_BITSTREAM_LF 1
|
||||||
|
@ -97,4 +75,18 @@ void switch_off(void);
|
||||||
#define FPGA_HF_ISO18092_FLAG_424K (2<<0) // 0010 should enable 414k mode (untested). No autodetect
|
#define FPGA_HF_ISO18092_FLAG_424K (2<<0) // 0010 should enable 414k mode (untested). No autodetect
|
||||||
#define FPGA_HF_ISO18092_FLAG_READER (4<<0) // 0100 enables antenna power, to act as a reader instead of tag
|
#define FPGA_HF_ISO18092_FLAG_READER (4<<0) // 0100 enables antenna power, to act as a reader instead of tag
|
||||||
|
|
||||||
|
void FpgaSendCommand(uint16_t cmd, uint16_t v);
|
||||||
|
void FpgaWriteConfWord(uint8_t v);
|
||||||
|
void FpgaDownloadAndGo(int bitstream_version);
|
||||||
|
// void FpgaGatherVersion(int bitstream_version, char *dst, int len);
|
||||||
|
void FpgaSetupSsc(void);
|
||||||
|
void SetupSpi(int mode);
|
||||||
|
bool FpgaSetupSscDma(uint8_t *buf, int len);
|
||||||
|
void Fpga_print_status(void);
|
||||||
|
int FpgaGetCurrent(void);
|
||||||
|
void SetAdcMuxFor(uint32_t whichGpio);
|
||||||
|
|
||||||
|
// extern and generel turn off the antenna method
|
||||||
|
void switch_off(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
1470
armsrc/frozen.c
Normal file
1470
armsrc/frozen.c
Normal file
File diff suppressed because it is too large
Load diff
313
armsrc/frozen.h
Normal file
313
armsrc/frozen.h
Normal file
|
@ -0,0 +1,313 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
|
||||||
|
* Copyright (c) 2018 Cesanta Software Limited
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CS_FROZEN_FROZEN_H_
|
||||||
|
#define CS_FROZEN_FROZEN_H_
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* JSON token type */
|
||||||
|
enum json_token_type {
|
||||||
|
JSON_TYPE_INVALID = 0, /* memsetting to 0 should create INVALID value */
|
||||||
|
JSON_TYPE_STRING,
|
||||||
|
JSON_TYPE_NUMBER,
|
||||||
|
JSON_TYPE_TRUE,
|
||||||
|
JSON_TYPE_FALSE,
|
||||||
|
JSON_TYPE_NULL,
|
||||||
|
JSON_TYPE_OBJECT_START,
|
||||||
|
JSON_TYPE_OBJECT_END,
|
||||||
|
JSON_TYPE_ARRAY_START,
|
||||||
|
JSON_TYPE_ARRAY_END,
|
||||||
|
|
||||||
|
JSON_TYPES_CNT
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure containing token type and value. Used in `json_walk()` and
|
||||||
|
* `json_scanf()` with the format specifier `%T`.
|
||||||
|
*/
|
||||||
|
struct json_token {
|
||||||
|
const char *ptr; /* Points to the beginning of the value */
|
||||||
|
int len; /* Value length */
|
||||||
|
enum json_token_type type; /* Type of the token, possible values are above */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define JSON_INVALID_TOKEN \
|
||||||
|
{ 0, 0, JSON_TYPE_INVALID }
|
||||||
|
|
||||||
|
/* Error codes */
|
||||||
|
#define JSON_STRING_INVALID -1
|
||||||
|
#define JSON_STRING_INCOMPLETE -2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Callback-based SAX-like API.
|
||||||
|
*
|
||||||
|
* Property name and length is given only if it's available: i.e. if current
|
||||||
|
* event is an object's property. In other cases, `name` is `NULL`. For
|
||||||
|
* example, name is never given:
|
||||||
|
* - For the first value in the JSON string;
|
||||||
|
* - For events JSON_TYPE_OBJECT_END and JSON_TYPE_ARRAY_END
|
||||||
|
*
|
||||||
|
* E.g. for the input `{ "foo": 123, "bar": [ 1, 2, { "baz": true } ] }`,
|
||||||
|
* the sequence of callback invocations will be as follows:
|
||||||
|
*
|
||||||
|
* - type: JSON_TYPE_OBJECT_START, name: NULL, path: "", value: NULL
|
||||||
|
* - type: JSON_TYPE_NUMBER, name: "foo", path: ".foo", value: "123"
|
||||||
|
* - type: JSON_TYPE_ARRAY_START, name: "bar", path: ".bar", value: NULL
|
||||||
|
* - type: JSON_TYPE_NUMBER, name: "0", path: ".bar[0]", value: "1"
|
||||||
|
* - type: JSON_TYPE_NUMBER, name: "1", path: ".bar[1]", value: "2"
|
||||||
|
* - type: JSON_TYPE_OBJECT_START, name: "2", path: ".bar[2]", value: NULL
|
||||||
|
* - type: JSON_TYPE_TRUE, name: "baz", path: ".bar[2].baz", value: "true"
|
||||||
|
* - type: JSON_TYPE_OBJECT_END, name: NULL, path: ".bar[2]", value: "{ \"baz\":
|
||||||
|
*true }"
|
||||||
|
* - type: JSON_TYPE_ARRAY_END, name: NULL, path: ".bar", value: "[ 1, 2, {
|
||||||
|
*\"baz\": true } ]"
|
||||||
|
* - type: JSON_TYPE_OBJECT_END, name: NULL, path: "", value: "{ \"foo\": 123,
|
||||||
|
*\"bar\": [ 1, 2, { \"baz\": true } ] }"
|
||||||
|
*/
|
||||||
|
typedef void (*json_walk_callback_t)(void *callback_data, const char *name,
|
||||||
|
size_t name_len, const char *path,
|
||||||
|
const struct json_token *token);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse `json_string`, invoking `callback` in a way similar to SAX parsers;
|
||||||
|
* see `json_walk_callback_t`.
|
||||||
|
* Return number of processed bytes, or a negative error code.
|
||||||
|
*/
|
||||||
|
int json_walk(const char *json_string, int json_string_length,
|
||||||
|
json_walk_callback_t callback, void *callback_data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* JSON generation API.
|
||||||
|
* struct json_out abstracts output, allowing alternative printing plugins.
|
||||||
|
*/
|
||||||
|
struct json_out {
|
||||||
|
int (*printer)(struct json_out *, const char *str, size_t len);
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
char *buf;
|
||||||
|
size_t size;
|
||||||
|
size_t len;
|
||||||
|
} buf;
|
||||||
|
void *data;
|
||||||
|
FILE *fp;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int json_printer_buf(struct json_out *, const char *, size_t);
|
||||||
|
extern int json_printer_file(struct json_out *, const char *, size_t);
|
||||||
|
|
||||||
|
#define JSON_OUT_BUF(buf, len) \
|
||||||
|
{ \
|
||||||
|
json_printer_buf, { \
|
||||||
|
{ buf, len, 0 } \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#define JSON_OUT_FILE(fp) \
|
||||||
|
{ \
|
||||||
|
json_printer_file, { \
|
||||||
|
{ (char *) fp, 0, 0 } \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int (*json_printf_callback_t)(struct json_out *, va_list *ap);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate formatted output into a given sting buffer.
|
||||||
|
* This is a superset of printf() function, with extra format specifiers:
|
||||||
|
* - `%B` print json boolean, `true` or `false`. Accepts an `int`.
|
||||||
|
* - `%Q` print quoted escaped string or `null`. Accepts a `const char *`.
|
||||||
|
* - `%.*Q` same as `%Q`, but with length. Accepts `int`, `const char *`
|
||||||
|
* - `%V` print quoted base64-encoded string. Accepts a `const char *`, `int`.
|
||||||
|
* - `%H` print quoted hex-encoded string. Accepts a `int`, `const char *`.
|
||||||
|
* - `%M` invokes a json_printf_callback_t function. That callback function
|
||||||
|
* can consume more parameters.
|
||||||
|
*
|
||||||
|
* Return number of bytes printed. If the return value is bigger than the
|
||||||
|
* supplied buffer, that is an indicator of overflow. In the overflow case,
|
||||||
|
* overflown bytes are not printed.
|
||||||
|
*/
|
||||||
|
int json_printf(struct json_out *, const char *fmt, ...);
|
||||||
|
int json_vprintf(struct json_out *, const char *fmt, va_list ap);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Same as json_printf, but prints to a file.
|
||||||
|
* File is created if does not exist. File is truncated if already exists.
|
||||||
|
*/
|
||||||
|
int json_fprintf(const char *file_name, const char *fmt, ...);
|
||||||
|
int json_vfprintf(const char *file_name, const char *fmt, va_list ap);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print JSON into an allocated 0-terminated string.
|
||||||
|
* Return allocated string, or NULL on error.
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ```c
|
||||||
|
* char *str = json_asprintf("{a:%H}", 3, "abc");
|
||||||
|
* printf("%s\n", str); // Prints "616263"
|
||||||
|
* free(str);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
char *json_asprintf(const char *fmt, ...);
|
||||||
|
char *json_vasprintf(const char *fmt, va_list ap);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper %M callback that prints contiguous C arrays.
|
||||||
|
* Consumes void *array_ptr, size_t array_size, size_t elem_size, char *fmt
|
||||||
|
* Return number of bytes printed.
|
||||||
|
*/
|
||||||
|
int json_printf_array(struct json_out *, va_list *ap);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scan JSON string `str`, performing scanf-like conversions according to `fmt`.
|
||||||
|
* This is a `scanf()` - like function, with following differences:
|
||||||
|
*
|
||||||
|
* 1. Object keys in the format string may be not quoted, e.g. "{key: %d}"
|
||||||
|
* 2. Order of keys in an object is irrelevant.
|
||||||
|
* 3. Several extra format specifiers are supported:
|
||||||
|
* - %B: consumes `int *` (or `char *`, if `sizeof(bool) == sizeof(char)`),
|
||||||
|
* expects boolean `true` or `false`.
|
||||||
|
* - %Q: consumes `char **`, expects quoted, JSON-encoded string. Scanned
|
||||||
|
* string is malloc-ed, caller must free() the string.
|
||||||
|
* - %V: consumes `char **`, `int *`. Expects base64-encoded string.
|
||||||
|
* Result string is base64-decoded, malloced and NUL-terminated.
|
||||||
|
* The length of result string is stored in `int *` placeholder.
|
||||||
|
* Caller must free() the result.
|
||||||
|
* - %H: consumes `int *`, `char **`.
|
||||||
|
* Expects a hex-encoded string, e.g. "fa014f".
|
||||||
|
* Result string is hex-decoded, malloced and NUL-terminated.
|
||||||
|
* The length of the result string is stored in `int *` placeholder.
|
||||||
|
* Caller must free() the result.
|
||||||
|
* - %M: consumes custom scanning function pointer and
|
||||||
|
* `void *user_data` parameter - see json_scanner_t definition.
|
||||||
|
* - %T: consumes `struct json_token *`, fills it out with matched token.
|
||||||
|
*
|
||||||
|
* Return number of elements successfully scanned & converted.
|
||||||
|
* Negative number means scan error.
|
||||||
|
*/
|
||||||
|
int json_scanf(const char *str, int str_len, const char *fmt, ...);
|
||||||
|
int json_vscanf(const char *str, int str_len, const char *fmt, va_list ap);
|
||||||
|
|
||||||
|
/* json_scanf's %M handler */
|
||||||
|
typedef void (*json_scanner_t)(const char *str, int len, void *user_data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function to scan array item with given path and index.
|
||||||
|
* Fills `token` with the matched JSON token.
|
||||||
|
* Return -1 if no array element found, otherwise non-negative token length.
|
||||||
|
*/
|
||||||
|
int json_scanf_array_elem(const char *s, int len, const char *path, int index,
|
||||||
|
struct json_token *token);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unescape JSON-encoded string src,slen into dst, dlen.
|
||||||
|
* src and dst may overlap.
|
||||||
|
* If destination buffer is too small (or zero-length), result string is not
|
||||||
|
* written but the length is counted nevertheless (similar to snprintf).
|
||||||
|
* Return the length of unescaped string in bytes.
|
||||||
|
*/
|
||||||
|
int json_unescape(const char *src, int slen, char *dst, int dlen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Escape a string `str`, `str_len` into the printer `out`.
|
||||||
|
* Return the number of bytes printed.
|
||||||
|
*/
|
||||||
|
int json_escape(struct json_out *out, const char *str, size_t str_len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read the whole file in memory.
|
||||||
|
* Return malloc-ed file content, or NULL on error. The caller must free().
|
||||||
|
*/
|
||||||
|
char *json_fread(const char *file_name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update given JSON string `s,len` by changing the value at given `json_path`.
|
||||||
|
* The result is saved to `out`. If `json_fmt` == NULL, that deletes the key.
|
||||||
|
* If path is not present, missing keys are added. Array path without an
|
||||||
|
* index pushes a value to the end of an array.
|
||||||
|
* Return 1 if the string was changed, 0 otherwise.
|
||||||
|
*
|
||||||
|
* Example: s is a JSON string { "a": 1, "b": [ 2 ] }
|
||||||
|
* json_setf(s, len, out, ".a", "7"); // { "a": 7, "b": [ 2 ] }
|
||||||
|
* json_setf(s, len, out, ".b", "7"); // { "a": 1, "b": 7 }
|
||||||
|
* json_setf(s, len, out, ".b[]", "7"); // { "a": 1, "b": [ 2,7 ] }
|
||||||
|
* json_setf(s, len, out, ".b", NULL); // { "a": 1 }
|
||||||
|
*/
|
||||||
|
int json_setf(const char *s, int len, struct json_out *out,
|
||||||
|
const char *json_path, const char *json_fmt, ...);
|
||||||
|
|
||||||
|
int json_vsetf(const char *s, int len, struct json_out *out,
|
||||||
|
const char *json_path, const char *json_fmt, va_list ap);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pretty-print JSON string `s,len` into `out`.
|
||||||
|
* Return number of processed bytes in `s`.
|
||||||
|
*/
|
||||||
|
int json_prettify(const char *s, int len, struct json_out *out);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prettify JSON file `file_name`.
|
||||||
|
* Return number of processed bytes, or negative number of error.
|
||||||
|
* On error, file content is not modified.
|
||||||
|
*/
|
||||||
|
int json_prettify_file(const char *file_name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterate over an object at given JSON `path`.
|
||||||
|
* On each iteration, fill the `key` and `val` tokens. It is OK to pass NULL
|
||||||
|
* for `key`, or `val`, in which case they won't be populated.
|
||||||
|
* Return an opaque value suitable for the next iteration, or NULL when done.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ```c
|
||||||
|
* void *h = NULL;
|
||||||
|
* struct json_token key, val;
|
||||||
|
* while ((h = json_next_key(s, len, h, ".foo", &key, &val)) != NULL) {
|
||||||
|
* printf("[%.*s] -> [%.*s]\n", key.len, key.ptr, val.len, val.ptr);
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
void *json_next_key(const char *s, int len, void *handle, const char *path,
|
||||||
|
struct json_token *key, struct json_token *val);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterate over an array at given JSON `path`.
|
||||||
|
* Similar to `json_next_key`, but fills array index `idx` instead of `key`.
|
||||||
|
*/
|
||||||
|
void *json_next_elem(const char *s, int len, void *handle, const char *path,
|
||||||
|
int *idx, struct json_token *val);
|
||||||
|
|
||||||
|
#ifndef JSON_MAX_PATH_LEN
|
||||||
|
#define JSON_MAX_PATH_LEN 256
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef JSON_MINIMAL
|
||||||
|
#define JSON_MINIMAL 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef JSON_ENABLE_BASE64
|
||||||
|
#define JSON_ENABLE_BASE64 !JSON_MINIMAL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef JSON_ENABLE_HEX
|
||||||
|
#define JSON_ENABLE_HEX !JSON_MINIMAL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CS_FROZEN_FROZEN_H_ */
|
|
@ -1,8 +1,9 @@
|
||||||
#include "proxmark3.h"
|
#include "proxmark3_arm.h"
|
||||||
#include "apps.h"
|
|
||||||
#include "BigBuf.h"
|
#include "BigBuf.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "dbprint.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "usb_cdc.h" // for usb_poll_validate_length
|
|
||||||
|
|
||||||
static void RAMFUNC optimizedSniff(void);
|
static void RAMFUNC optimizedSniff(void);
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,16 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Samy Kamkar 2012
|
// Jonathan Westhues, Aug 2005
|
||||||
// Christian Herrmann, 2017
|
// Gerhard de Koning Gans, April 2008, May 2011
|
||||||
//
|
//
|
||||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
// the license.
|
// the license.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// StandAlone Mod
|
// Definitions internal to the app source.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifndef __HFSNOOP_H
|
||||||
|
#define __HFSNOOP_H
|
||||||
|
|
||||||
#ifndef __LF_SAMYRUN_H
|
void HfSniff(int, int);
|
||||||
#define __LF_SAMYRUN_H
|
|
||||||
|
|
||||||
//#include <stdbool.h> // for bool
|
#endif
|
||||||
#include "standalone.h" // standalone definitions
|
|
||||||
#include "apps.h" // debugstatements, lfops?
|
|
||||||
|
|
||||||
|
|
||||||
#define OPTS 2
|
|
||||||
|
|
||||||
#endif /* __LF_SAMYRUN_H */
|
|
|
@ -20,15 +20,20 @@
|
||||||
|
|
||||||
#include "hitag2.h"
|
#include "hitag2.h"
|
||||||
#include "hitag2_crypto.h"
|
#include "hitag2_crypto.h"
|
||||||
#include "hitag.h"
|
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "apps.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "cmd.h"
|
||||||
#include "BigBuf.h"
|
#include "BigBuf.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
// Successful crypto auth
|
||||||
static bool bCrypto;
|
static bool bCrypto;
|
||||||
|
// Is in auth stage
|
||||||
static bool bAuthenticating;
|
static bool bAuthenticating;
|
||||||
|
// Successful password auth
|
||||||
static bool bPwd;
|
static bool bPwd;
|
||||||
static bool bSuccessful;
|
static bool bSuccessful;
|
||||||
|
|
||||||
|
@ -272,8 +277,8 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false);
|
// LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false);
|
||||||
// LogTrace(tx, nbytes(txlen), 0, 0, NULL, true);
|
// LogTrace(tx, nbytes(txlen), 0, 0, NULL, true);
|
||||||
|
|
||||||
if (tag.crypto_active) {
|
if (tag.crypto_active) {
|
||||||
hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen / 8, *txlen % 8);
|
hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen / 8, *txlen % 8);
|
||||||
|
@ -377,7 +382,7 @@ static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t
|
||||||
// Reset the transmission frame length
|
// Reset the transmission frame length
|
||||||
*txlen = 0;
|
*txlen = 0;
|
||||||
|
|
||||||
if (bPwd && write) {
|
if (bPwd && !bAuthenticating && write) {
|
||||||
if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
|
if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -398,22 +403,29 @@ static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t
|
||||||
|
|
||||||
// Received UID, tag password
|
// Received UID, tag password
|
||||||
case 32: {
|
case 32: {
|
||||||
|
// stage 1, got UID
|
||||||
if (!bPwd) {
|
if (!bPwd) {
|
||||||
*txlen = 32;
|
|
||||||
memcpy(tx, password, 4);
|
|
||||||
bPwd = true;
|
bPwd = true;
|
||||||
memcpy(tag.sectors[blocknr], rx, 4);
|
bAuthenticating = true;
|
||||||
blocknr++;
|
memcpy(tx, password, 4);
|
||||||
|
*txlen = 32;
|
||||||
} else {
|
} else {
|
||||||
|
// stage 2, got config byte+password TAG, discard as will read later
|
||||||
if (blocknr == 1) {
|
if (bAuthenticating) {
|
||||||
//store password in block1, the TAG answers with Block3, but we need the password in memory
|
bAuthenticating = false;
|
||||||
memcpy(tag.sectors[blocknr], tx, 4);
|
if (write) {
|
||||||
} else {
|
if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// stage 2+, got data block
|
||||||
|
else {
|
||||||
memcpy(tag.sectors[blocknr], rx, 4);
|
memcpy(tag.sectors[blocknr], rx, 4);
|
||||||
|
blocknr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
blocknr++;
|
|
||||||
if (blocknr > 7) {
|
if (blocknr > 7) {
|
||||||
DbpString("Read succesful!");
|
DbpString("Read succesful!");
|
||||||
bSuccessful = true;
|
bSuccessful = true;
|
||||||
|
@ -488,19 +500,22 @@ static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *
|
||||||
}
|
}
|
||||||
// Received UID, crypto tag answer
|
// Received UID, crypto tag answer
|
||||||
case 32: {
|
case 32: {
|
||||||
|
// stage 1, got UID
|
||||||
if (!bCrypto) {
|
if (!bCrypto) {
|
||||||
uint64_t ui64key = key[0] | ((uint64_t)key[1]) << 8 | ((uint64_t)key[2]) << 16 | ((uint64_t)key[3]) << 24 | ((uint64_t)key[4]) << 32 | ((uint64_t)key[5]) << 40;
|
uint64_t ui64key = key[0] | ((uint64_t)key[1]) << 8 | ((uint64_t)key[2]) << 16 | ((uint64_t)key[3]) << 24 | ((uint64_t)key[4]) << 32 | ((uint64_t)key[5]) << 40;
|
||||||
uint32_t ui32uid = rx[0] | ((uint32_t)rx[1]) << 8 | ((uint32_t)rx[2]) << 16 | ((uint32_t)rx[3]) << 24;
|
uint32_t ui32uid = rx[0] | ((uint32_t)rx[1]) << 8 | ((uint32_t)rx[2]) << 16 | ((uint32_t)rx[3]) << 24;
|
||||||
Dbprintf("hitag2_crypto: key=0x%x%x uid=0x%x", (uint32_t)((REV64(ui64key)) >> 32), (uint32_t)((REV64(ui64key)) & 0xffffffff), REV32(ui32uid));
|
Dbprintf("hitag2_crypto: key=0x%x%x uid=0x%x", (uint32_t)((REV64(ui64key)) >> 32), (uint32_t)((REV64(ui64key)) & 0xffffffff), REV32(ui32uid));
|
||||||
cipher_state = _hitag2_init(REV64(ui64key), REV32(ui32uid), 0);
|
cipher_state = _hitag2_init(REV64(ui64key), REV32(ui32uid), 0);
|
||||||
|
// PRN
|
||||||
memset(tx, 0x00, 4);
|
memset(tx, 0x00, 4);
|
||||||
|
// Secret data
|
||||||
memset(tx + 4, 0xff, 4);
|
memset(tx + 4, 0xff, 4);
|
||||||
hitag2_cipher_transcrypt(&cipher_state, tx + 4, 4, 0);
|
hitag2_cipher_transcrypt(&cipher_state, tx + 4, 4, 0);
|
||||||
*txlen = 64;
|
*txlen = 64;
|
||||||
bCrypto = true;
|
bCrypto = true;
|
||||||
bAuthenticating = true;
|
bAuthenticating = true;
|
||||||
} else {
|
} else {
|
||||||
// Check if we received answer tag (at)
|
// stage 2, got config byte+password TAG, discard as will read later
|
||||||
if (bAuthenticating) {
|
if (bAuthenticating) {
|
||||||
bAuthenticating = false;
|
bAuthenticating = false;
|
||||||
if (write) {
|
if (write) {
|
||||||
|
@ -509,7 +524,9 @@ static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
// stage 2+, got data block
|
||||||
|
else {
|
||||||
// Store the received block
|
// Store the received block
|
||||||
memcpy(tag.sectors[blocknr], rx, 4);
|
memcpy(tag.sectors[blocknr], rx, 4);
|
||||||
blocknr++;
|
blocknr++;
|
||||||
|
@ -692,7 +709,7 @@ void SniffHitag(void) {
|
||||||
|
|
||||||
StopTicks();
|
StopTicks();
|
||||||
|
|
||||||
// int frame_count;
|
// int frame_count;
|
||||||
int response;
|
int response;
|
||||||
int overflow;
|
int overflow;
|
||||||
bool rising_edge;
|
bool rising_edge;
|
||||||
|
@ -750,7 +767,7 @@ void SniffHitag(void) {
|
||||||
|
|
||||||
// Reset the received frame, frame count and timing info
|
// Reset the received frame, frame count and timing info
|
||||||
memset(rx, 0x00, sizeof(rx));
|
memset(rx, 0x00, sizeof(rx));
|
||||||
// frame_count = 0;
|
// frame_count = 0;
|
||||||
response = 0;
|
response = 0;
|
||||||
overflow = 0;
|
overflow = 0;
|
||||||
reader_frame = false;
|
reader_frame = false;
|
||||||
|
@ -857,7 +874,7 @@ void SniffHitag(void) {
|
||||||
|
|
||||||
// Check if frame was captured
|
// Check if frame was captured
|
||||||
if (rxlen > 0) {
|
if (rxlen > 0) {
|
||||||
// frame_count++;
|
// frame_count++;
|
||||||
LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame);
|
LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame);
|
||||||
|
|
||||||
// Check if we recognize a valid authentication attempt
|
// Check if we recognize a valid authentication attempt
|
||||||
|
@ -907,7 +924,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) {
|
||||||
|
|
||||||
StopTicks();
|
StopTicks();
|
||||||
|
|
||||||
// int frame_count = 0;
|
// int frame_count = 0;
|
||||||
int response = 0, overflow = 0;
|
int response = 0, overflow = 0;
|
||||||
uint8_t rx[HITAG_FRAME_LEN];
|
uint8_t rx[HITAG_FRAME_LEN];
|
||||||
size_t rxlen = 0;
|
size_t rxlen = 0;
|
||||||
|
@ -950,7 +967,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) {
|
||||||
// Set up simulator mode, frequency divisor which will drive the FPGA
|
// Set up simulator mode, frequency divisor which will drive the FPGA
|
||||||
// and analog mux selection.
|
// and analog mux selection.
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||||
|
|
||||||
// Configure output pin that is connected to the FPGA (for modulating)
|
// Configure output pin that is connected to the FPGA (for modulating)
|
||||||
|
@ -1025,7 +1042,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) {
|
||||||
|
|
||||||
// Check if frame was captured
|
// Check if frame was captured
|
||||||
if (rxlen > 4) {
|
if (rxlen > 4) {
|
||||||
// frame_count++;
|
// frame_count++;
|
||||||
LogTrace(rx, nbytes(rxlen), response, response, NULL, true);
|
LogTrace(rx, nbytes(rxlen), response, response, NULL, true);
|
||||||
|
|
||||||
// Disable timer 1 with external trigger to avoid triggers during our own modulation
|
// Disable timer 1 with external trigger to avoid triggers during our own modulation
|
||||||
|
@ -1081,7 +1098,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
||||||
|
|
||||||
StopTicks();
|
StopTicks();
|
||||||
|
|
||||||
// int frame_count = 0;
|
// int frame_count = 0;
|
||||||
int response = 0;
|
int response = 0;
|
||||||
uint8_t rx[HITAG_FRAME_LEN];
|
uint8_t rx[HITAG_FRAME_LEN];
|
||||||
size_t rxlen = 0;
|
size_t rxlen = 0;
|
||||||
|
@ -1104,6 +1121,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
||||||
memcpy(password, htd->pwd.password, 4);
|
memcpy(password, htd->pwd.password, 4);
|
||||||
blocknr = 0;
|
blocknr = 0;
|
||||||
bPwd = false;
|
bPwd = false;
|
||||||
|
bAuthenticating = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case RHT2F_AUTHENTICATE: {
|
case RHT2F_AUTHENTICATE: {
|
||||||
|
@ -1155,7 +1173,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
||||||
|
|
||||||
// Set fpga in edge detect with reader field, we can modulate as reader now
|
// Set fpga in edge detect with reader field, we can modulate as reader now
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||||
|
|
||||||
// Configure output and enable pin that is connected to the FPGA (for modulating)
|
// Configure output and enable pin that is connected to the FPGA (for modulating)
|
||||||
|
@ -1216,7 +1234,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
||||||
|
|
||||||
// Check if frame was captured and store it
|
// Check if frame was captured and store it
|
||||||
if (rxlen > 0) {
|
if (rxlen > 0) {
|
||||||
// frame_count++;
|
// frame_count++;
|
||||||
LogTrace(rx, nbytes(rxlen), response, response, NULL, false);
|
LogTrace(rx, nbytes(rxlen), response, response, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1272,7 +1290,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
||||||
|
|
||||||
// Add transmitted frame to total count
|
// Add transmitted frame to total count
|
||||||
if (txlen > 0) {
|
if (txlen > 0) {
|
||||||
// frame_count++;
|
// frame_count++;
|
||||||
LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true);
|
LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1366,7 +1384,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
||||||
|
|
||||||
StopTicks();
|
StopTicks();
|
||||||
|
|
||||||
// int frame_count = 0;
|
// int frame_count = 0;
|
||||||
int response = 0;
|
int response = 0;
|
||||||
uint8_t rx[HITAG_FRAME_LEN];
|
uint8_t rx[HITAG_FRAME_LEN];
|
||||||
size_t rxlen = 0;
|
size_t rxlen = 0;
|
||||||
|
@ -1405,6 +1423,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
||||||
Dbhexdump(4, password, false);
|
Dbhexdump(4, password, false);
|
||||||
blocknr = page;
|
blocknr = page;
|
||||||
bPwd = false;
|
bPwd = false;
|
||||||
|
bAuthenticating = false;
|
||||||
writestate = WRITE_STATE_START;
|
writestate = WRITE_STATE_START;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1425,7 +1444,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
||||||
|
|
||||||
// Set fpga in edge detect with reader field, we can modulate as reader now
|
// Set fpga in edge detect with reader field, we can modulate as reader now
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||||
|
|
||||||
// Disable modulation at default, which means enable the field
|
// Disable modulation at default, which means enable the field
|
||||||
|
@ -1486,7 +1505,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
||||||
|
|
||||||
// Check if frame was captured and store it
|
// Check if frame was captured and store it
|
||||||
if (rxlen > 0) {
|
if (rxlen > 0) {
|
||||||
// frame_count++;
|
// frame_count++;
|
||||||
LogTrace(rx, nbytes(rxlen), response, response, NULL, false);
|
LogTrace(rx, nbytes(rxlen), response, response, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1527,7 +1546,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
||||||
|
|
||||||
// Add transmitted frame to total count
|
// Add transmitted frame to total count
|
||||||
if (txlen > 0) {
|
if (txlen > 0) {
|
||||||
// frame_count++;
|
// frame_count++;
|
||||||
LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true);
|
LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,7 @@
|
||||||
#ifndef _HITAG2_H_
|
#ifndef _HITAG2_H_
|
||||||
#define _HITAG2_H_
|
#define _HITAG2_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include "common.h"
|
||||||
#include <stdbool.h>
|
|
||||||
#include "hitag.h"
|
#include "hitag.h"
|
||||||
|
|
||||||
void SniffHitag(void);
|
void SniffHitag(void);
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "hitag2_crypto.h"
|
#include "hitag2_crypto.h"
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */
|
/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */
|
||||||
// Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007.
|
// Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007.
|
||||||
// For educational purposes only.
|
// For educational purposes only.
|
||||||
|
|
|
@ -1,12 +1,7 @@
|
||||||
#ifndef __HITAG2_CRYPTO_H
|
#ifndef __HITAG2_CRYPTO_H
|
||||||
#define __HITAG2_CRYPTO_H
|
#define __HITAG2_CRYPTO_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#include "common.h"
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "string.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
struct hitag2_tag {
|
struct hitag2_tag {
|
||||||
uint32_t uid;
|
uint32_t uid;
|
||||||
|
@ -29,8 +24,5 @@ uint32_t _hitag2_byte(uint64_t *x);
|
||||||
void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv);
|
void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv);
|
||||||
int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is);
|
int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is);
|
||||||
int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) ;
|
int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) ;
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,6 +13,17 @@
|
||||||
|
|
||||||
#include "hitagS.h"
|
#include "hitagS.h"
|
||||||
|
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "cmd.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "commonutil.h"
|
||||||
|
#include "hitag2_crypto.h"
|
||||||
|
|
||||||
#define CRC_PRESET 0xFF
|
#define CRC_PRESET 0xFF
|
||||||
#define CRC_POLYNOM 0x1D
|
#define CRC_POLYNOM 0x1D
|
||||||
|
|
||||||
|
@ -983,7 +994,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) {
|
||||||
// and analog mux selection.
|
// and analog mux selection.
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||||
|
|
||||||
// Configure output pin that is connected to the FPGA (for modulating)
|
// Configure output pin that is connected to the FPGA (for modulating)
|
||||||
|
@ -1182,7 +1193,7 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) {
|
||||||
|
|
||||||
// Set fpga in edge detect with reader field, we can modulate as reader now
|
// Set fpga in edge detect with reader field, we can modulate as reader now
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||||
|
|
||||||
// Configure output and enable pin that is connected to the FPGA (for modulating)
|
// Configure output and enable pin that is connected to the FPGA (for modulating)
|
||||||
|
@ -1517,7 +1528,7 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) {
|
||||||
|
|
||||||
// Set fpga in edge detect with reader field, we can modulate as reader now
|
// Set fpga in edge detect with reader field, we can modulate as reader now
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||||
|
|
||||||
// Disable modulation at default, which means enable the field
|
// Disable modulation at default, which means enable the field
|
||||||
|
@ -1778,7 +1789,7 @@ void check_challenges(bool file_given, uint8_t *data) {
|
||||||
|
|
||||||
// Set fpga in edge detect with reader field, we can modulate as reader now
|
// Set fpga in edge detect with reader field, we can modulate as reader now
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||||
|
|
||||||
// Disable modulation at default, which means enable the field
|
// Disable modulation at default, which means enable the field
|
||||||
|
|
|
@ -12,16 +12,9 @@
|
||||||
#ifndef _HITAGS_H_
|
#ifndef _HITAGS_H_
|
||||||
#define _HITAGS_H_
|
#define _HITAGS_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include "common.h"
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "hitag2_crypto.h"
|
|
||||||
#include "hitag.h"
|
#include "hitag.h"
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "apps.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "string.h"
|
|
||||||
#include "BigBuf.h"
|
|
||||||
|
|
||||||
void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data);
|
void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data);
|
||||||
void ReadHitagS(hitag_function htf, hitag_data *htd);
|
void ReadHitagS(hitag_function htf, hitag_data *htd);
|
||||||
|
|
|
@ -10,6 +10,14 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
|
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "cmd.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
#define GPIO_RST AT91C_PIO_PA1
|
#define GPIO_RST AT91C_PIO_PA1
|
||||||
#define GPIO_SCL AT91C_PIO_PA5
|
#define GPIO_SCL AT91C_PIO_PA5
|
||||||
#define GPIO_SDA AT91C_PIO_PA7
|
#define GPIO_SDA AT91C_PIO_PA7
|
||||||
|
@ -26,7 +34,7 @@
|
||||||
|
|
||||||
volatile unsigned long c;
|
volatile unsigned long c;
|
||||||
|
|
||||||
// Direct use the loop to delay. 6 instructions loop, Masterclock 48Mhz,
|
// Direct use the loop to delay. 6 instructions loop, Masterclock 48MHz,
|
||||||
// delay=1 is about 200kbps
|
// delay=1 is about 200kbps
|
||||||
// timer.
|
// timer.
|
||||||
// I2CSpinDelayClk(4) = 12.31us
|
// I2CSpinDelayClk(4) = 12.31us
|
||||||
|
@ -41,7 +49,7 @@ void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {
|
||||||
|
|
||||||
#define ISO7618_MAX_FRAME 255
|
#define ISO7618_MAX_FRAME 255
|
||||||
|
|
||||||
// try i2c bus recovery at 100kHz = 5uS high, 5uS low
|
// try i2c bus recovery at 100kHz = 5us high, 5us low
|
||||||
void I2C_recovery(void) {
|
void I2C_recovery(void) {
|
||||||
|
|
||||||
DbpString("Performing i2c bus recovery");
|
DbpString("Performing i2c bus recovery");
|
|
@ -1,10 +1,7 @@
|
||||||
#ifndef __I2C_H
|
#ifndef __I2C_H
|
||||||
#define __I2C_H
|
#define __I2C_H
|
||||||
|
|
||||||
#include <stddef.h>
|
#include "common.h"
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "apps.h"
|
|
||||||
#include "BigBuf.h"
|
|
||||||
#include "mifare.h"
|
#include "mifare.h"
|
||||||
|
|
||||||
#define I2C_DEVICE_ADDRESS_BOOT 0xB0
|
#define I2C_DEVICE_ADDRESS_BOOT 0xB0
|
||||||
|
@ -18,7 +15,6 @@
|
||||||
#define I2C_DEVICE_CMD_GETVERSION 0x06
|
#define I2C_DEVICE_CMD_GETVERSION 0x06
|
||||||
#define I2C_DEVICE_CMD_SEND_T0 0x07
|
#define I2C_DEVICE_CMD_SEND_T0 0x07
|
||||||
|
|
||||||
|
|
||||||
void I2C_recovery(void);
|
void I2C_recovery(void);
|
||||||
void I2C_init(void);
|
void I2C_init(void);
|
||||||
void I2C_Reset(void);
|
void I2C_Reset(void);
|
||||||
|
@ -48,4 +44,5 @@ void SmartCardSetBaud(uint64_t arg0);
|
||||||
void SmartCardSetClock(uint64_t arg0);
|
void SmartCardSetClock(uint64_t arg0);
|
||||||
void I2C_print_status(void);
|
void I2C_print_status(void);
|
||||||
int I2C_get_version(uint8_t *maj, uint8_t *min);
|
int I2C_get_version(uint8_t *maj, uint8_t *min);
|
||||||
|
|
||||||
#endif
|
#endif
|
255
armsrc/iclass.c
255
armsrc/iclass.c
|
@ -36,15 +36,24 @@
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "apps.h"
|
#include "iclass.h"
|
||||||
|
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
#include "cmd.h"
|
#include "cmd.h"
|
||||||
// Needed for CRC in emulation mode;
|
// Needed for CRC in emulation mode;
|
||||||
// same construction as in ISO 14443;
|
// same construction as in ISO 14443;
|
||||||
// different initial value (CRC_ICLASS)
|
// different initial value (CRC_ICLASS)
|
||||||
#include "crc16.h"
|
#include "crc16.h"
|
||||||
#include "protocols.h"
|
|
||||||
#include "optimized_cipher.h"
|
#include "optimized_cipher.h"
|
||||||
#include "usb_cdc.h" // for usb_poll_validate_length
|
|
||||||
|
#include "appmain.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "protocols.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
|
||||||
static int timeout = 4096;
|
static int timeout = 4096;
|
||||||
static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay);
|
static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay);
|
||||||
|
@ -92,21 +101,21 @@ typedef struct {
|
||||||
int bitBuffer;
|
int bitBuffer;
|
||||||
int dropPosition;
|
int dropPosition;
|
||||||
uint8_t *output;
|
uint8_t *output;
|
||||||
} tUart;
|
} tUartIc;
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum {
|
enum {
|
||||||
DEMOD_UNSYNCD,
|
DEMOD_IC_UNSYNCD,
|
||||||
DEMOD_START_OF_COMMUNICATION,
|
DEMOD_IC_START_OF_COMMUNICATION,
|
||||||
DEMOD_START_OF_COMMUNICATION2,
|
DEMOD_IC_START_OF_COMMUNICATION2,
|
||||||
DEMOD_START_OF_COMMUNICATION3,
|
DEMOD_IC_START_OF_COMMUNICATION3,
|
||||||
DEMOD_SOF_COMPLETE,
|
DEMOD_IC_SOF_COMPLETE,
|
||||||
DEMOD_MANCHESTER_D,
|
DEMOD_IC_MANCHESTER_D,
|
||||||
DEMOD_MANCHESTER_E,
|
DEMOD_IC_MANCHESTER_E,
|
||||||
DEMOD_END_OF_COMMUNICATION,
|
DEMOD_IC_END_OF_COMMUNICATION,
|
||||||
DEMOD_END_OF_COMMUNICATION2,
|
DEMOD_IC_END_OF_COMMUNICATION2,
|
||||||
DEMOD_MANCHESTER_F,
|
DEMOD_IC_MANCHESTER_F,
|
||||||
DEMOD_ERROR_WAIT
|
DEMOD_IC_ERROR_WAIT
|
||||||
} state;
|
} state;
|
||||||
int bitCount;
|
int bitCount;
|
||||||
int posCount;
|
int posCount;
|
||||||
|
@ -125,7 +134,7 @@ typedef struct {
|
||||||
SUB_BOTH
|
SUB_BOTH
|
||||||
} sub;
|
} sub;
|
||||||
uint8_t *output;
|
uint8_t *output;
|
||||||
} tDemod;
|
} tDemodIc;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Abrasive's uart implementation
|
* Abrasive's uart implementation
|
||||||
|
@ -138,8 +147,13 @@ typedef struct {
|
||||||
bool frame_done;
|
bool frame_done;
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
int len;
|
int len;
|
||||||
} tUart;
|
} tUartIc;
|
||||||
static tUart Uart;
|
static tUartIc Uart;
|
||||||
|
|
||||||
|
static void OnError(uint8_t reason) {
|
||||||
|
reply_old(CMD_ACK, 0, reason, 0, 0, 0);
|
||||||
|
switch_off();
|
||||||
|
}
|
||||||
|
|
||||||
static void uart_reset(void) {
|
static void uart_reset(void) {
|
||||||
Uart.frame_done = false;
|
Uart.frame_done = false;
|
||||||
|
@ -499,8 +513,8 @@ static RAMFUNC int OutOfNDecoding(int bit) {
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// Manchester
|
// Manchester
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
static tDemod Demod;
|
static tDemodIc Demod;
|
||||||
static void DemodReset() {
|
static void DemodIcReset() {
|
||||||
Demod.bitCount = 0;
|
Demod.bitCount = 0;
|
||||||
Demod.posCount = 0;
|
Demod.posCount = 0;
|
||||||
Demod.syncBit = 0;
|
Demod.syncBit = 0;
|
||||||
|
@ -512,11 +526,11 @@ static void DemodReset() {
|
||||||
Demod.samples = 0;
|
Demod.samples = 0;
|
||||||
Demod.len = 0;
|
Demod.len = 0;
|
||||||
Demod.sub = SUB_NONE;
|
Demod.sub = SUB_NONE;
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_IC_UNSYNCD;
|
||||||
}
|
}
|
||||||
static void DemodInit(uint8_t *data) {
|
static void DemodIcInit(uint8_t *data) {
|
||||||
Demod.output = data;
|
Demod.output = data;
|
||||||
DemodReset();
|
DemodIcReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// UART debug
|
// UART debug
|
||||||
|
@ -592,7 +606,7 @@ static RAMFUNC int ManchesterDecoding_iclass(uint32_t v) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Demod.state == DEMOD_UNSYNCD) {
|
if (Demod.state == DEMOD_IC_UNSYNCD) {
|
||||||
Demod.output[Demod.len] = 0xfa;
|
Demod.output[Demod.len] = 0xfa;
|
||||||
Demod.syncBit = 0;
|
Demod.syncBit = 0;
|
||||||
//Demod.samples = 0;
|
//Demod.samples = 0;
|
||||||
|
@ -620,7 +634,7 @@ static RAMFUNC int ManchesterDecoding_iclass(uint32_t v) {
|
||||||
|
|
||||||
if (Demod.syncBit) {
|
if (Demod.syncBit) {
|
||||||
Demod.len = 0;
|
Demod.len = 0;
|
||||||
Demod.state = DEMOD_START_OF_COMMUNICATION;
|
Demod.state = DEMOD_IC_START_OF_COMMUNICATION;
|
||||||
Demod.sub = SUB_FIRST_HALF;
|
Demod.sub = SUB_FIRST_HALF;
|
||||||
Demod.bitCount = 0;
|
Demod.bitCount = 0;
|
||||||
Demod.shiftReg = 0;
|
Demod.shiftReg = 0;
|
||||||
|
@ -644,12 +658,12 @@ static RAMFUNC int ManchesterDecoding_iclass(uint32_t v) {
|
||||||
}
|
}
|
||||||
// SOF must be long burst... otherwise stay unsynced!!!
|
// SOF must be long burst... otherwise stay unsynced!!!
|
||||||
if (!(Demod.buffer & Demod.syncBit) || !(Demod.buffer2 & Demod.syncBit))
|
if (!(Demod.buffer & Demod.syncBit) || !(Demod.buffer2 & Demod.syncBit))
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_IC_UNSYNCD;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// SOF must be long burst... otherwise stay unsynced!!!
|
// SOF must be long burst... otherwise stay unsynced!!!
|
||||||
if (!(Demod.buffer2 & Demod.syncBit) || !(Demod.buffer3 & Demod.syncBit)) {
|
if (!(Demod.buffer2 & Demod.syncBit) || !(Demod.buffer3 & Demod.syncBit)) {
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_IC_UNSYNCD;
|
||||||
error = 0x88;
|
error = 0x88;
|
||||||
uart_debug(error, bit);
|
uart_debug(error, bit);
|
||||||
return false;
|
return false;
|
||||||
|
@ -682,74 +696,74 @@ static RAMFUNC int ManchesterDecoding_iclass(uint32_t v) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Demod.sub == SUB_NONE) {
|
if (Demod.sub == SUB_NONE) {
|
||||||
if (Demod.state == DEMOD_SOF_COMPLETE) {
|
if (Demod.state == DEMOD_IC_SOF_COMPLETE) {
|
||||||
Demod.output[Demod.len] = 0x0f;
|
Demod.output[Demod.len] = 0x0f;
|
||||||
Demod.len++;
|
Demod.len++;
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_IC_UNSYNCD;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
Demod.state = DEMOD_ERROR_WAIT;
|
Demod.state = DEMOD_IC_ERROR_WAIT;
|
||||||
error = 0x33;
|
error = 0x33;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Demod.state) {
|
switch (Demod.state) {
|
||||||
|
|
||||||
case DEMOD_START_OF_COMMUNICATION:
|
case DEMOD_IC_START_OF_COMMUNICATION:
|
||||||
if (Demod.sub == SUB_BOTH) {
|
if (Demod.sub == SUB_BOTH) {
|
||||||
|
|
||||||
Demod.state = DEMOD_START_OF_COMMUNICATION2;
|
Demod.state = DEMOD_IC_START_OF_COMMUNICATION2;
|
||||||
Demod.posCount = 1;
|
Demod.posCount = 1;
|
||||||
Demod.sub = SUB_NONE;
|
Demod.sub = SUB_NONE;
|
||||||
} else {
|
} else {
|
||||||
Demod.output[Demod.len] = 0xab;
|
Demod.output[Demod.len] = 0xab;
|
||||||
Demod.state = DEMOD_ERROR_WAIT;
|
Demod.state = DEMOD_IC_ERROR_WAIT;
|
||||||
error = 0xd2;
|
error = 0xd2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEMOD_START_OF_COMMUNICATION2:
|
case DEMOD_IC_START_OF_COMMUNICATION2:
|
||||||
if (Demod.sub == SUB_SECOND_HALF) {
|
if (Demod.sub == SUB_SECOND_HALF) {
|
||||||
Demod.state = DEMOD_START_OF_COMMUNICATION3;
|
Demod.state = DEMOD_IC_START_OF_COMMUNICATION3;
|
||||||
} else {
|
} else {
|
||||||
Demod.output[Demod.len] = 0xab;
|
Demod.output[Demod.len] = 0xab;
|
||||||
Demod.state = DEMOD_ERROR_WAIT;
|
Demod.state = DEMOD_IC_ERROR_WAIT;
|
||||||
error = 0xd3;
|
error = 0xd3;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEMOD_START_OF_COMMUNICATION3:
|
case DEMOD_IC_START_OF_COMMUNICATION3:
|
||||||
if (Demod.sub == SUB_SECOND_HALF) {
|
if (Demod.sub == SUB_SECOND_HALF) {
|
||||||
Demod.state = DEMOD_SOF_COMPLETE;
|
Demod.state = DEMOD_IC_SOF_COMPLETE;
|
||||||
} else {
|
} else {
|
||||||
Demod.output[Demod.len] = 0xab;
|
Demod.output[Demod.len] = 0xab;
|
||||||
Demod.state = DEMOD_ERROR_WAIT;
|
Demod.state = DEMOD_IC_ERROR_WAIT;
|
||||||
error = 0xd4;
|
error = 0xd4;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEMOD_SOF_COMPLETE:
|
case DEMOD_IC_SOF_COMPLETE:
|
||||||
case DEMOD_MANCHESTER_D:
|
case DEMOD_IC_MANCHESTER_D:
|
||||||
case DEMOD_MANCHESTER_E:
|
case DEMOD_IC_MANCHESTER_E:
|
||||||
// OPPOSITE FROM ISO14443 - 11110000 = 0 (1 in 14443)
|
// OPPOSITE FROM ISO14443 - 11110000 = 0 (1 in 14443)
|
||||||
// 00001111 = 1 (0 in 14443)
|
// 00001111 = 1 (0 in 14443)
|
||||||
if (Demod.sub == SUB_SECOND_HALF) { // SUB_FIRST_HALF
|
if (Demod.sub == SUB_SECOND_HALF) { // SUB_FIRST_HALF
|
||||||
Demod.bitCount++;
|
Demod.bitCount++;
|
||||||
Demod.shiftReg = (Demod.shiftReg >> 1) ^ 0x100;
|
Demod.shiftReg = (Demod.shiftReg >> 1) ^ 0x100;
|
||||||
Demod.state = DEMOD_MANCHESTER_D;
|
Demod.state = DEMOD_IC_MANCHESTER_D;
|
||||||
} else if (Demod.sub == SUB_FIRST_HALF) { // SUB_SECOND_HALF
|
} else if (Demod.sub == SUB_FIRST_HALF) { // SUB_SECOND_HALF
|
||||||
Demod.bitCount++;
|
Demod.bitCount++;
|
||||||
Demod.shiftReg >>= 1;
|
Demod.shiftReg >>= 1;
|
||||||
Demod.state = DEMOD_MANCHESTER_E;
|
Demod.state = DEMOD_IC_MANCHESTER_E;
|
||||||
} else if (Demod.sub == SUB_BOTH) {
|
} else if (Demod.sub == SUB_BOTH) {
|
||||||
Demod.state = DEMOD_MANCHESTER_F;
|
Demod.state = DEMOD_IC_MANCHESTER_F;
|
||||||
} else {
|
} else {
|
||||||
Demod.state = DEMOD_ERROR_WAIT;
|
Demod.state = DEMOD_IC_ERROR_WAIT;
|
||||||
error = 0x55;
|
error = 0x55;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEMOD_MANCHESTER_F:
|
case DEMOD_IC_MANCHESTER_F:
|
||||||
// Tag response does not need to be a complete byte!
|
// Tag response does not need to be a complete byte!
|
||||||
if (Demod.len > 0 || Demod.bitCount > 0) {
|
if (Demod.len > 0 || Demod.bitCount > 0) {
|
||||||
if (Demod.bitCount > 1) { // was > 0, do not interpret last closing bit, is part of EOF
|
if (Demod.bitCount > 1) { // was > 0, do not interpret last closing bit, is part of EOF
|
||||||
|
@ -758,22 +772,22 @@ static RAMFUNC int ManchesterDecoding_iclass(uint32_t v) {
|
||||||
Demod.len++;
|
Demod.len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_IC_UNSYNCD;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
Demod.output[Demod.len] = 0xad;
|
Demod.output[Demod.len] = 0xad;
|
||||||
Demod.state = DEMOD_ERROR_WAIT;
|
Demod.state = DEMOD_IC_ERROR_WAIT;
|
||||||
error = 0x03;
|
error = 0x03;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEMOD_ERROR_WAIT:
|
case DEMOD_IC_ERROR_WAIT:
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_IC_UNSYNCD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Demod.output[Demod.len] = 0xdd;
|
Demod.output[Demod.len] = 0xdd;
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_IC_UNSYNCD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -818,10 +832,10 @@ static void iclass_setup_sniff(void) {
|
||||||
set_tracing(true);
|
set_tracing(true);
|
||||||
|
|
||||||
// Initialize Demod and Uart structs
|
// Initialize Demod and Uart structs
|
||||||
DemodInit(BigBuf_malloc(ICLASS_BUFFER_SIZE));
|
DemodIcInit(BigBuf_malloc(ICLASS_BUFFER_SIZE));
|
||||||
|
|
||||||
uart_init(BigBuf_malloc(ICLASS_BUFFER_SIZE));
|
uart_init(BigBuf_malloc(ICLASS_BUFFER_SIZE));
|
||||||
//UartInit(BigBuf_malloc(ICLASS_BUFFER_SIZE));
|
//UartIcInit(BigBuf_malloc(ICLASS_BUFFER_SIZE));
|
||||||
|
|
||||||
if (DBGLEVEL > 1) {
|
if (DBGLEVEL > 1) {
|
||||||
// Print debug information about the buffer sizes
|
// Print debug information about the buffer sizes
|
||||||
|
@ -884,9 +898,17 @@ void RAMFUNC SniffIClass(void) {
|
||||||
// contains LOW nibble = tag data
|
// contains LOW nibble = tag data
|
||||||
// so two bytes are needed in order to get 1byte of either reader or tag data. (ie 2 sample bytes)
|
// so two bytes are needed in order to get 1byte of either reader or tag data. (ie 2 sample bytes)
|
||||||
// since reader data is manchester encoded, we need 2bytes of data in order to get one demoded byte. (ie: 4 sample bytes)
|
// since reader data is manchester encoded, we need 2bytes of data in order to get one demoded byte. (ie: 4 sample bytes)
|
||||||
while (!BUTTON_PRESS()) {
|
uint16_t checked = 0;
|
||||||
|
for (;;) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
|
if (checked == 1000) {
|
||||||
|
if (BUTTON_PRESS() || data_available()) break;
|
||||||
|
checked = 0;
|
||||||
|
} else {
|
||||||
|
checked++;
|
||||||
|
}
|
||||||
|
|
||||||
previous_data <<= 8;
|
previous_data <<= 8;
|
||||||
previous_data |= *data;
|
previous_data |= *data;
|
||||||
|
|
||||||
|
@ -919,7 +941,7 @@ void RAMFUNC SniffIClass(void) {
|
||||||
if (Uart.frame_done) {
|
if (Uart.frame_done) {
|
||||||
time_stop = GetCountSspClk() - time_0;
|
time_stop = GetCountSspClk() - time_0;
|
||||||
LogTrace(Uart.buf, Uart.len, time_start, time_stop, NULL, true);
|
LogTrace(Uart.buf, Uart.len, time_start, time_stop, NULL, true);
|
||||||
DemodReset();
|
DemodIcReset();
|
||||||
uart_reset();
|
uart_reset();
|
||||||
} else {
|
} else {
|
||||||
time_start = GetCountSspClk() - time_0;
|
time_start = GetCountSspClk() - time_0;
|
||||||
|
@ -951,12 +973,12 @@ void RAMFUNC SniffIClass(void) {
|
||||||
if (ManchesterDecoding_iclass(foo)) {
|
if (ManchesterDecoding_iclass(foo)) {
|
||||||
time_stop = GetCountSspClk() - time_0;
|
time_stop = GetCountSspClk() - time_0;
|
||||||
LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false);
|
LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false);
|
||||||
DemodReset();
|
DemodIcReset();
|
||||||
uart_reset();
|
uart_reset();
|
||||||
} else {
|
} else {
|
||||||
time_start = GetCountSspClk() - time_0;
|
time_start = GetCountSspClk() - time_0;
|
||||||
}
|
}
|
||||||
TagIsActive = (Demod.state != DEMOD_UNSYNCD);
|
TagIsActive = (Demod.state != DEMOD_IC_UNSYNCD);
|
||||||
}
|
}
|
||||||
tag_byte = 0;
|
tag_byte = 0;
|
||||||
foo = 0;
|
foo = 0;
|
||||||
|
@ -996,9 +1018,18 @@ static bool GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen)
|
||||||
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
(void)b;
|
(void)b;
|
||||||
|
|
||||||
while (!BUTTON_PRESS()) {
|
uint16_t checked = 0;
|
||||||
|
for (;;) {
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
|
if (checked == 1000) {
|
||||||
|
if (BUTTON_PRESS() || data_available()) return false;
|
||||||
|
checked = 0;
|
||||||
|
} else {
|
||||||
|
checked++;
|
||||||
|
}
|
||||||
|
|
||||||
// keep tx buffer in a defined state anyway.
|
// keep tx buffer in a defined state anyway.
|
||||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))
|
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))
|
||||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||||
|
@ -1195,11 +1226,11 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
|
||||||
|
|
||||||
if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) {
|
if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) {
|
||||||
// Button pressed
|
// Button pressed
|
||||||
reply_old(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i, 0, mac_responses, i * EPURSE_MAC_SIZE);
|
reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i, 0, mac_responses, i * EPURSE_MAC_SIZE);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reply_old(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i, 0, mac_responses, i * EPURSE_MAC_SIZE);
|
reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i, 0, mac_responses, i * EPURSE_MAC_SIZE);
|
||||||
|
|
||||||
} else if (simType == 3) {
|
} else if (simType == 3) {
|
||||||
//This is 'full sim' mode, where we use the emulator storage for data.
|
//This is 'full sim' mode, where we use the emulator storage for data.
|
||||||
|
@ -1226,20 +1257,20 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
|
||||||
|
|
||||||
// keyroll 1
|
// keyroll 1
|
||||||
if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) {
|
if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) {
|
||||||
reply_old(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2);
|
reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2);
|
||||||
// Button pressed
|
// Button pressed
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// keyroll 2
|
// keyroll 2
|
||||||
if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + (i + numberOfCSNS) * EPURSE_MAC_SIZE)) {
|
if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + (i + numberOfCSNS) * EPURSE_MAC_SIZE)) {
|
||||||
reply_old(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2);
|
reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2);
|
||||||
// Button pressed
|
// Button pressed
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// double the amount of collected data.
|
// double the amount of collected data.
|
||||||
reply_old(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2);
|
reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// We may want a mode here where we hardcode the csns to use (from proxclone).
|
// We may want a mode here where we hardcode the csns to use (from proxclone).
|
||||||
|
@ -1307,7 +1338,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
// Reader 81 anticoll. CSN
|
// Reader 81 anticoll. CSN
|
||||||
// Tag CSN
|
// Tag CSN
|
||||||
|
|
||||||
uint8_t *modulated_response;
|
uint8_t *modulated_response = NULL;
|
||||||
int modulated_response_size = 0;
|
int modulated_response_size = 0;
|
||||||
uint8_t *trace_data = NULL;
|
uint8_t *trace_data = NULL;
|
||||||
int trace_data_size = 0;
|
int trace_data_size = 0;
|
||||||
|
@ -1382,11 +1413,11 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
|
|
||||||
//This is used for responding to READ-block commands or other data which is dynamically generated
|
//This is used for responding to READ-block commands or other data which is dynamically generated
|
||||||
//First the 'trace'-data, not encoded for FPGA
|
//First the 'trace'-data, not encoded for FPGA
|
||||||
uint8_t *data_generic_trace = BigBuf_malloc(8 + 2);//8 bytes data + 2byte CRC is max tag answer
|
uint8_t *data_generic_trace = BigBuf_malloc((8 * 4) + 2);//8 bytes data + 2byte CRC is max tag answer
|
||||||
|
|
||||||
//Then storage for the modulated data
|
//Then storage for the modulated data
|
||||||
//Each bit is doubled when modulated for FPGA, and we also have SOF and EOF (2 bytes)
|
//Each bit is doubled when modulated for FPGA, and we also have SOF and EOF (2 bytes)
|
||||||
uint8_t *data_response = BigBuf_malloc((8 + 2) * 2 + 2);
|
uint8_t *data_response = BigBuf_malloc(((8 * 4) + 2) * 2 + 2);
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
|
||||||
SpinDelay(100);
|
SpinDelay(100);
|
||||||
|
@ -1436,6 +1467,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
trace_data_size = sizeof(anticoll_data);
|
trace_data_size = sizeof(anticoll_data);
|
||||||
goto send;
|
goto send;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len == 4) {
|
if (len == 4) {
|
||||||
// block0,1,2,5 is always readable.
|
// block0,1,2,5 is always readable.
|
||||||
switch (receivedCmd[1]) {
|
switch (receivedCmd[1]) {
|
||||||
|
@ -1444,13 +1476,13 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
modulated_response_size = resp_csn_len;
|
modulated_response_size = resp_csn_len;
|
||||||
trace_data = csn_data;
|
trace_data = csn_data;
|
||||||
trace_data_size = sizeof(csn_data);
|
trace_data_size = sizeof(csn_data);
|
||||||
break;
|
goto send;
|
||||||
case 1: // configuration (0c 01)
|
case 1: // configuration (0c 01)
|
||||||
modulated_response = resp_conf;
|
modulated_response = resp_conf;
|
||||||
modulated_response_size = resp_conf_len;
|
modulated_response_size = resp_conf_len;
|
||||||
trace_data = conf_data;
|
trace_data = conf_data;
|
||||||
trace_data_size = sizeof(conf_data);
|
trace_data_size = sizeof(conf_data);
|
||||||
break;
|
goto send;
|
||||||
case 2: // e-purse (0c 02)
|
case 2: // e-purse (0c 02)
|
||||||
modulated_response = resp_cc;
|
modulated_response = resp_cc;
|
||||||
modulated_response_size = resp_cc_len;
|
modulated_response_size = resp_cc_len;
|
||||||
|
@ -1460,19 +1492,30 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
if (reader_mac_buf != NULL) {
|
if (reader_mac_buf != NULL) {
|
||||||
memcpy(reader_mac_buf, card_challenge_data, 8);
|
memcpy(reader_mac_buf, card_challenge_data, 8);
|
||||||
}
|
}
|
||||||
break;
|
goto send;
|
||||||
case 5:// Application Issuer Area (0c 05)
|
case 5:// Application Issuer Area (0c 05)
|
||||||
modulated_response = resp_aia;
|
modulated_response = resp_aia;
|
||||||
modulated_response_size = resp_aia_len;
|
modulated_response_size = resp_aia_len;
|
||||||
trace_data = aia_data;
|
trace_data = aia_data;
|
||||||
trace_data_size = sizeof(aia_data);
|
trace_data_size = sizeof(aia_data);
|
||||||
|
goto send;
|
||||||
|
default : {
|
||||||
|
if (simulationMode == MODE_FULLSIM) { // 0x0C
|
||||||
|
//Read block
|
||||||
|
//Take the data...
|
||||||
|
memcpy(data_generic_trace, emulator + (receivedCmd[1] << 3), 8);
|
||||||
|
AddCrc(data_generic_trace, 8);
|
||||||
|
trace_data = data_generic_trace;
|
||||||
|
trace_data_size = 10;
|
||||||
|
CodeIClassTagAnswer(trace_data, trace_data_size);
|
||||||
|
memcpy(modulated_response, ToSend, ToSendMax);
|
||||||
|
modulated_response_size = ToSendMax;
|
||||||
|
goto send;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
}
|
||||||
break;
|
}//swith
|
||||||
}
|
}// if 4
|
||||||
goto send;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (receivedCmd[0] == ICLASS_CMD_SELECT) { // 0x81
|
} else if (receivedCmd[0] == ICLASS_CMD_SELECT) { // 0x81
|
||||||
// Reader selects anticollission CSN.
|
// Reader selects anticollission CSN.
|
||||||
// Tag sends the corresponding real CSN
|
// Tag sends the corresponding real CSN
|
||||||
|
@ -1542,17 +1585,15 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
trace_data = NULL;
|
trace_data = NULL;
|
||||||
trace_data_size = 0;
|
trace_data_size = 0;
|
||||||
goto send;
|
goto send;
|
||||||
} else if (simulationMode == MODE_FULLSIM && receivedCmd[0] == ICLASS_CMD_READ_OR_IDENTIFY && len == 4) { // 0x0C
|
} else if (simulationMode == MODE_FULLSIM && receivedCmd[0] == ICLASS_CMD_READ4 && len == 4) { // 0x06
|
||||||
//Read block
|
//Read block
|
||||||
uint16_t blk = receivedCmd[1];
|
|
||||||
//Take the data...
|
//Take the data...
|
||||||
memcpy(data_generic_trace, emulator + (blk << 3), 8);
|
memcpy(data_generic_trace, emulator + (receivedCmd[1] << 3), 8 * 4);
|
||||||
AddCrc(data_generic_trace, 8);
|
AddCrc(data_generic_trace, 8 * 4);
|
||||||
trace_data = data_generic_trace;
|
trace_data = data_generic_trace;
|
||||||
trace_data_size = 10;
|
trace_data_size = 34;
|
||||||
CodeIClassTagAnswer(trace_data, trace_data_size);
|
CodeIClassTagAnswer(trace_data, trace_data_size);
|
||||||
memcpy(data_response, ToSend, ToSendMax);
|
memcpy(modulated_response, ToSend, ToSendMax);
|
||||||
modulated_response = data_response;
|
|
||||||
modulated_response_size = ToSendMax;
|
modulated_response_size = ToSendMax;
|
||||||
goto send;
|
goto send;
|
||||||
} else if (simulationMode == MODE_FULLSIM && receivedCmd[0] == ICLASS_CMD_UPDATE) {
|
} else if (simulationMode == MODE_FULLSIM && receivedCmd[0] == ICLASS_CMD_UPDATE) {
|
||||||
|
@ -1632,8 +1673,15 @@ static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay) {
|
||||||
|
|
||||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||||
|
|
||||||
while (!BUTTON_PRESS()) {
|
uint16_t checked = 0;
|
||||||
|
for (;;) {
|
||||||
|
|
||||||
|
if (checked == 1000) {
|
||||||
|
if (BUTTON_PRESS() || data_available()) return 0;
|
||||||
|
checked = 0;
|
||||||
|
} else {
|
||||||
|
checked++;
|
||||||
|
}
|
||||||
// Prevent rx holding register from overflowing
|
// Prevent rx holding register from overflowing
|
||||||
if ((AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {
|
if ((AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {
|
||||||
b = AT91C_BASE_SSC->SSC_RHR;
|
b = AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
@ -1787,7 +1835,7 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples,
|
||||||
bool skip = false;
|
bool skip = false;
|
||||||
|
|
||||||
// Setup UART/DEMOD to receive
|
// Setup UART/DEMOD to receive
|
||||||
DemodInit(receivedResponse);
|
DemodIcInit(receivedResponse);
|
||||||
|
|
||||||
if (elapsed) *elapsed = 0;
|
if (elapsed) *elapsed = 0;
|
||||||
|
|
||||||
|
@ -1800,9 +1848,18 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples,
|
||||||
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
(void)b;
|
(void)b;
|
||||||
|
|
||||||
while (!BUTTON_PRESS()) {
|
uint16_t checked = 0;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
|
if (checked == 1000) {
|
||||||
|
if (BUTTON_PRESS() || data_available()) return false;
|
||||||
|
checked = 0;
|
||||||
|
} else {
|
||||||
|
checked++;
|
||||||
|
}
|
||||||
|
|
||||||
// keep tx buffer in a defined state anyway.
|
// keep tx buffer in a defined state anyway.
|
||||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||||
|
@ -1993,6 +2050,7 @@ void ReaderIClass(uint8_t arg0) {
|
||||||
|
|
||||||
setupIclassReader();
|
setupIclassReader();
|
||||||
|
|
||||||
|
uint16_t checked = 0;
|
||||||
bool userCancelled = BUTTON_PRESS() || data_available();
|
bool userCancelled = BUTTON_PRESS() || data_available();
|
||||||
while (!userCancelled) {
|
while (!userCancelled) {
|
||||||
|
|
||||||
|
@ -2092,7 +2150,13 @@ void ReaderIClass(uint8_t arg0) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
userCancelled = BUTTON_PRESS() || data_available();
|
|
||||||
|
if (checked == 1000) {
|
||||||
|
userCancelled = BUTTON_PRESS() || data_available();
|
||||||
|
checked = 0;
|
||||||
|
} else {
|
||||||
|
checked++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userCancelled) {
|
if (userCancelled) {
|
||||||
|
@ -2222,7 +2286,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac) {
|
||||||
switch_off();
|
switch_off();
|
||||||
}
|
}
|
||||||
|
|
||||||
// not used. ?!? ( CMD_ICLASS_READCHECK)
|
// not used. ?!? ( CMD_HF_ICLASS_READCHECK)
|
||||||
// turn off afterwards
|
// turn off afterwards
|
||||||
void iClass_ReadCheck(uint8_t blockno, uint8_t keytype) {
|
void iClass_ReadCheck(uint8_t blockno, uint8_t keytype) {
|
||||||
uint8_t readcheck[] = { keytype, blockno };
|
uint8_t readcheck[] = { keytype, blockno };
|
||||||
|
@ -2286,11 +2350,17 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
|
||||||
|
|
||||||
setupIclassReader();
|
setupIclassReader();
|
||||||
|
|
||||||
|
uint16_t checked = 0;
|
||||||
int read_status = 0;
|
int read_status = 0;
|
||||||
uint8_t startup_limit = 10;
|
uint8_t startup_limit = 10;
|
||||||
while (read_status != 2) {
|
while (read_status != 2) {
|
||||||
|
|
||||||
if (BUTTON_PRESS() && !data_available()) goto out;
|
if (checked == 1000) {
|
||||||
|
if (BUTTON_PRESS() || !data_available()) goto out;
|
||||||
|
checked = 0;
|
||||||
|
} else {
|
||||||
|
checked++;
|
||||||
|
}
|
||||||
|
|
||||||
read_status = handshakeIclassTag_ext(card_data, use_credit_key);
|
read_status = handshakeIclassTag_ext(card_data, use_credit_key);
|
||||||
if (startup_limit-- == 0) {
|
if (startup_limit-- == 0) {
|
||||||
|
@ -2305,7 +2375,12 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
|
||||||
for (i = 0; i < keyCount; i++) {
|
for (i = 0; i < keyCount; i++) {
|
||||||
|
|
||||||
// Allow button press / usb cmd to interrupt device
|
// Allow button press / usb cmd to interrupt device
|
||||||
if (BUTTON_PRESS() && !data_available()) break;
|
if (checked == 1000) {
|
||||||
|
if (BUTTON_PRESS() || !data_available()) goto out;
|
||||||
|
checked = 0;
|
||||||
|
} else {
|
||||||
|
checked++;
|
||||||
|
}
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
|
|
29
armsrc/iclass.h
Normal file
29
armsrc/iclass.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Jonathan Westhues, Aug 2005
|
||||||
|
// Gerhard de Koning Gans, April 2008, May 2011
|
||||||
|
//
|
||||||
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
// the license.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Definitions internal to the app source.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifndef __ICLASS_H
|
||||||
|
#define __ICLASS_H
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
void RAMFUNC SniffIClass(void);
|
||||||
|
void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||||
|
void ReaderIClass(uint8_t arg0);
|
||||||
|
void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac);
|
||||||
|
void iClass_Authentication(uint8_t *mac);
|
||||||
|
void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain);
|
||||||
|
void iClass_WriteBlock(uint8_t blockno, uint8_t *data);
|
||||||
|
void iClass_ReadBlk(uint8_t blockno);
|
||||||
|
bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len);
|
||||||
|
void iClass_Dump(uint8_t blockno, uint8_t numblks);
|
||||||
|
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data);
|
||||||
|
void iClass_ReadCheck(uint8_t blockno, uint8_t keytype);
|
||||||
|
|
||||||
|
#endif
|
|
@ -11,10 +11,25 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "iso14443a.h"
|
#include "iso14443a.h"
|
||||||
|
|
||||||
|
#include "string.h"
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "cmd.h"
|
||||||
|
#include "appmain.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "parity.h"
|
||||||
|
#include "mifareutil.h"
|
||||||
|
#include "commonutil.h"
|
||||||
|
#include "crc16.h"
|
||||||
|
#include "protocols.h"
|
||||||
|
|
||||||
#define MAX_ISO14A_TIMEOUT 524288
|
#define MAX_ISO14A_TIMEOUT 524288
|
||||||
static uint32_t iso14a_timeout;
|
static uint32_t iso14a_timeout;
|
||||||
// if iso14443a not active - transmit/receive dont try to execute
|
// if iso14443a not active - transmit/receive dont try to execute
|
||||||
static bool iso14443a_active = false;
|
static bool hf_field_active = false;
|
||||||
|
|
||||||
uint8_t colpos = 0;
|
uint8_t colpos = 0;
|
||||||
int rsamples = 0;
|
int rsamples = 0;
|
||||||
|
@ -25,7 +40,7 @@ static uint8_t iso14_pcb_blocknum = 0;
|
||||||
//
|
//
|
||||||
// ISO14443 timing:
|
// ISO14443 timing:
|
||||||
//
|
//
|
||||||
// minimum time between the start bits of consecutive transfers from reader to tag: 7000 carrier (13.56Mhz) cycles
|
// minimum time between the start bits of consecutive transfers from reader to tag: 7000 carrier (13.56MHz) cycles
|
||||||
#define REQUEST_GUARD_TIME (7000/16 + 1)
|
#define REQUEST_GUARD_TIME (7000/16 + 1)
|
||||||
// minimum time between last modulation of tag and next start bit from reader to tag: 1172 carrier cycles
|
// minimum time between last modulation of tag and next start bit from reader to tag: 1172 carrier cycles
|
||||||
#define FRAME_DELAY_TIME_PICC_TO_PCD (1172/16 + 1)
|
#define FRAME_DELAY_TIME_PICC_TO_PCD (1172/16 + 1)
|
||||||
|
@ -161,7 +176,7 @@ void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par) {
|
||||||
// Note 1: the bitstream may start at any time. We therefore need to sync.
|
// Note 1: the bitstream may start at any time. We therefore need to sync.
|
||||||
// Note 2: the interpretation of Sequence Y and Z depends on the preceding sequence.
|
// Note 2: the interpretation of Sequence Y and Z depends on the preceding sequence.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static tUart Uart;
|
static tUart14a Uart;
|
||||||
|
|
||||||
// Lookup-Table to decide if 4 raw bits are a modulation.
|
// Lookup-Table to decide if 4 raw bits are a modulation.
|
||||||
// We accept the following:
|
// We accept the following:
|
||||||
|
@ -176,12 +191,12 @@ const bool Mod_Miller_LUT[] = {
|
||||||
#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x000000F0) >> 4])
|
#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x000000F0) >> 4])
|
||||||
#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x0000000F)])
|
#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x0000000F)])
|
||||||
|
|
||||||
tUart *GetUart() {
|
tUart14a *GetUart14a() {
|
||||||
return &Uart;
|
return &Uart;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UartReset(void) {
|
void Uart14aReset(void) {
|
||||||
Uart.state = STATE_UNSYNCD;
|
Uart.state = STATE_14A_UNSYNCD;
|
||||||
Uart.bitCount = 0;
|
Uart.bitCount = 0;
|
||||||
Uart.len = 0; // number of decoded data bytes
|
Uart.len = 0; // number of decoded data bytes
|
||||||
Uart.parityLen = 0; // number of decoded parity bytes
|
Uart.parityLen = 0; // number of decoded parity bytes
|
||||||
|
@ -194,17 +209,17 @@ void UartReset(void) {
|
||||||
Uart.syncBit = 9999;
|
Uart.syncBit = 9999;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UartInit(uint8_t *data, uint8_t *par) {
|
void Uart14aInit(uint8_t *data, uint8_t *par) {
|
||||||
Uart.output = data;
|
Uart.output = data;
|
||||||
Uart.parity = par;
|
Uart.parity = par;
|
||||||
UartReset();
|
Uart14aReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time
|
// use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time
|
||||||
RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) {
|
RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) {
|
||||||
Uart.fourBits = (Uart.fourBits << 8) | bit;
|
Uart.fourBits = (Uart.fourBits << 8) | bit;
|
||||||
|
|
||||||
if (Uart.state == STATE_UNSYNCD) { // not yet synced
|
if (Uart.state == STATE_14A_UNSYNCD) { // not yet synced
|
||||||
Uart.syncBit = 9999; // not set
|
Uart.syncBit = 9999; // not set
|
||||||
|
|
||||||
// 00x11111 2|3 ticks pause followed by 6|5 ticks unmodulated Sequence Z (a "0" or "start of communication")
|
// 00x11111 2|3 ticks pause followed by 6|5 ticks unmodulated Sequence Z (a "0" or "start of communication")
|
||||||
|
@ -230,20 +245,20 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) {
|
||||||
Uart.startTime = non_real_time ? non_real_time : (GetCountSspClk() & 0xfffffff8);
|
Uart.startTime = non_real_time ? non_real_time : (GetCountSspClk() & 0xfffffff8);
|
||||||
Uart.startTime -= Uart.syncBit;
|
Uart.startTime -= Uart.syncBit;
|
||||||
Uart.endTime = Uart.startTime;
|
Uart.endTime = Uart.startTime;
|
||||||
Uart.state = STATE_START_OF_COMMUNICATION;
|
Uart.state = STATE_14A_START_OF_COMMUNICATION;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) {
|
if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) {
|
||||||
if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation in both halves - error
|
if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation in both halves - error
|
||||||
UartReset();
|
Uart14aReset();
|
||||||
} else { // Modulation in first half = Sequence Z = logic "0"
|
} else { // Modulation in first half = Sequence Z = logic "0"
|
||||||
if (Uart.state == STATE_MILLER_X) { // error - must not follow after X
|
if (Uart.state == STATE_14A_MILLER_X) { // error - must not follow after X
|
||||||
UartReset();
|
Uart14aReset();
|
||||||
} else {
|
} else {
|
||||||
Uart.bitCount++;
|
Uart.bitCount++;
|
||||||
Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg
|
Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg
|
||||||
Uart.state = STATE_MILLER_Z;
|
Uart.state = STATE_14A_MILLER_Z;
|
||||||
Uart.endTime = Uart.startTime + 8 * (9 * Uart.len + Uart.bitCount + 1) - 6;
|
Uart.endTime = Uart.startTime + 8 * (9 * Uart.len + Uart.bitCount + 1) - 6;
|
||||||
if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity)
|
if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity)
|
||||||
Uart.output[Uart.len++] = (Uart.shiftReg & 0xff);
|
Uart.output[Uart.len++] = (Uart.shiftReg & 0xff);
|
||||||
|
@ -262,7 +277,7 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) {
|
||||||
if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation second half = Sequence X = logic "1"
|
if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation second half = Sequence X = logic "1"
|
||||||
Uart.bitCount++;
|
Uart.bitCount++;
|
||||||
Uart.shiftReg = (Uart.shiftReg >> 1) | 0x100; // add a 1 to the shiftreg
|
Uart.shiftReg = (Uart.shiftReg >> 1) | 0x100; // add a 1 to the shiftreg
|
||||||
Uart.state = STATE_MILLER_X;
|
Uart.state = STATE_14A_MILLER_X;
|
||||||
Uart.endTime = Uart.startTime + 8 * (9 * Uart.len + Uart.bitCount + 1) - 2;
|
Uart.endTime = Uart.startTime + 8 * (9 * Uart.len + Uart.bitCount + 1) - 2;
|
||||||
if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity)
|
if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity)
|
||||||
Uart.output[Uart.len++] = (Uart.shiftReg & 0xff);
|
Uart.output[Uart.len++] = (Uart.shiftReg & 0xff);
|
||||||
|
@ -276,8 +291,8 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // no modulation in both halves - Sequence Y
|
} else { // no modulation in both halves - Sequence Y
|
||||||
if (Uart.state == STATE_MILLER_Z || Uart.state == STATE_MILLER_Y) { // Y after logic "0" - End of Communication
|
if (Uart.state == STATE_14A_MILLER_Z || Uart.state == STATE_14A_MILLER_Y) { // Y after logic "0" - End of Communication
|
||||||
Uart.state = STATE_UNSYNCD;
|
Uart.state = STATE_14A_UNSYNCD;
|
||||||
Uart.bitCount--; // last "0" was part of EOC sequence
|
Uart.bitCount--; // last "0" was part of EOC sequence
|
||||||
Uart.shiftReg <<= 1; // drop it
|
Uart.shiftReg <<= 1; // drop it
|
||||||
if (Uart.bitCount > 0) { // if we decoded some bits
|
if (Uart.bitCount > 0) { // if we decoded some bits
|
||||||
|
@ -294,15 +309,15 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) {
|
||||||
if (Uart.len) {
|
if (Uart.len) {
|
||||||
return true; // we are finished with decoding the raw data sequence
|
return true; // we are finished with decoding the raw data sequence
|
||||||
} else {
|
} else {
|
||||||
UartReset(); // Nothing received - start over
|
Uart14aReset(); // Nothing received - start over
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Uart.state == STATE_START_OF_COMMUNICATION) { // error - must not follow directly after SOC
|
if (Uart.state == STATE_14A_START_OF_COMMUNICATION) { // error - must not follow directly after SOC
|
||||||
UartReset();
|
Uart14aReset();
|
||||||
} else { // a logic "0"
|
} else { // a logic "0"
|
||||||
Uart.bitCount++;
|
Uart.bitCount++;
|
||||||
Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg
|
Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg
|
||||||
Uart.state = STATE_MILLER_Y;
|
Uart.state = STATE_14A_MILLER_Y;
|
||||||
if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity)
|
if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity)
|
||||||
Uart.output[Uart.len++] = (Uart.shiftReg & 0xff);
|
Uart.output[Uart.len++] = (Uart.shiftReg & 0xff);
|
||||||
Uart.parityBits <<= 1; // make room for the parity bit
|
Uart.parityBits <<= 1; // make room for the parity bit
|
||||||
|
@ -336,7 +351,7 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) {
|
||||||
// 8 ticks modulated: A collision. Save the collision position and treat as Sequence D
|
// 8 ticks modulated: A collision. Save the collision position and treat as Sequence D
|
||||||
// Note 1: the bitstream may start at any time. We therefore need to sync.
|
// Note 1: the bitstream may start at any time. We therefore need to sync.
|
||||||
// Note 2: parameter offset is used to determine the position of the parity bits (required for the anticollision command only)
|
// Note 2: parameter offset is used to determine the position of the parity bits (required for the anticollision command only)
|
||||||
tDemod Demod;
|
tDemod14a Demod;
|
||||||
|
|
||||||
// Lookup-Table to decide if 4 raw bits are a modulation.
|
// Lookup-Table to decide if 4 raw bits are a modulation.
|
||||||
// We accept three or four "1" in any position
|
// We accept three or four "1" in any position
|
||||||
|
@ -348,11 +363,11 @@ const bool Mod_Manchester_LUT[] = {
|
||||||
#define IsManchesterModulationNibble1(b) (Mod_Manchester_LUT[(b & 0x00F0) >> 4])
|
#define IsManchesterModulationNibble1(b) (Mod_Manchester_LUT[(b & 0x00F0) >> 4])
|
||||||
#define IsManchesterModulationNibble2(b) (Mod_Manchester_LUT[(b & 0x000F)])
|
#define IsManchesterModulationNibble2(b) (Mod_Manchester_LUT[(b & 0x000F)])
|
||||||
|
|
||||||
tDemod *GetDemod() {
|
tDemod14a *GetDemod14a() {
|
||||||
return &Demod;
|
return &Demod;
|
||||||
}
|
}
|
||||||
void DemodReset(void) {
|
void Demod14aReset(void) {
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_14A_UNSYNCD;
|
||||||
Demod.len = 0; // number of decoded data bytes
|
Demod.len = 0; // number of decoded data bytes
|
||||||
Demod.parityLen = 0;
|
Demod.parityLen = 0;
|
||||||
Demod.shiftReg = 0; // shiftreg to hold decoded data bits
|
Demod.shiftReg = 0; // shiftreg to hold decoded data bits
|
||||||
|
@ -367,17 +382,17 @@ void DemodReset(void) {
|
||||||
Demod.samples = 0;
|
Demod.samples = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodInit(uint8_t *data, uint8_t *par) {
|
void Demod14aInit(uint8_t *data, uint8_t *par) {
|
||||||
Demod.output = data;
|
Demod.output = data;
|
||||||
Demod.parity = par;
|
Demod.parity = par;
|
||||||
DemodReset();
|
Demod14aReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time
|
// use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time
|
||||||
RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time) {
|
RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time) {
|
||||||
Demod.twoBits = (Demod.twoBits << 8) | bit;
|
Demod.twoBits = (Demod.twoBits << 8) | bit;
|
||||||
|
|
||||||
if (Demod.state == DEMOD_UNSYNCD) {
|
if (Demod.state == DEMOD_14A_UNSYNCD) {
|
||||||
|
|
||||||
if (Demod.highCnt < 2) { // wait for a stable unmodulated signal
|
if (Demod.highCnt < 2) { // wait for a stable unmodulated signal
|
||||||
if (Demod.twoBits == 0x0000) {
|
if (Demod.twoBits == 0x0000) {
|
||||||
|
@ -399,7 +414,7 @@ RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_t
|
||||||
Demod.startTime = non_real_time ? non_real_time : (GetCountSspClk() & 0xfffffff8);
|
Demod.startTime = non_real_time ? non_real_time : (GetCountSspClk() & 0xfffffff8);
|
||||||
Demod.startTime -= Demod.syncBit;
|
Demod.startTime -= Demod.syncBit;
|
||||||
Demod.bitCount = offset; // number of decoded data bits
|
Demod.bitCount = offset; // number of decoded data bits
|
||||||
Demod.state = DEMOD_MANCHESTER_DATA;
|
Demod.state = DEMOD_14A_MANCHESTER_DATA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -455,7 +470,7 @@ RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_t
|
||||||
if (Demod.len) {
|
if (Demod.len) {
|
||||||
return true; // we are finished with decoding the raw data sequence
|
return true; // we are finished with decoding the raw data sequence
|
||||||
} else { // nothing received. Start over
|
} else { // nothing received. Start over
|
||||||
DemodReset();
|
Demod14aReset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -463,6 +478,82 @@ RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_t
|
||||||
return false; // not finished yet, need more data
|
return false; // not finished yet, need more data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Thinfilm, Kovio mangels ISO14443A in the way that they don't use start bit nor parity bits.
|
||||||
|
RAMFUNC int ManchesterDecoding_Thinfilm(uint8_t bit) {
|
||||||
|
Demod.twoBits = (Demod.twoBits << 8) | bit;
|
||||||
|
|
||||||
|
if (Demod.state == DEMOD_14A_UNSYNCD) {
|
||||||
|
|
||||||
|
if (Demod.highCnt < 2) { // wait for a stable unmodulated signal
|
||||||
|
if (Demod.twoBits == 0x0000) {
|
||||||
|
Demod.highCnt++;
|
||||||
|
} else {
|
||||||
|
Demod.highCnt = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Demod.syncBit = 0xFFFF; // not set
|
||||||
|
if ((Demod.twoBits & 0x7700) == 0x7000) Demod.syncBit = 7;
|
||||||
|
else if ((Demod.twoBits & 0x3B80) == 0x3800) Demod.syncBit = 6;
|
||||||
|
else if ((Demod.twoBits & 0x1DC0) == 0x1C00) Demod.syncBit = 5;
|
||||||
|
else if ((Demod.twoBits & 0x0EE0) == 0x0E00) Demod.syncBit = 4;
|
||||||
|
else if ((Demod.twoBits & 0x0770) == 0x0700) Demod.syncBit = 3;
|
||||||
|
else if ((Demod.twoBits & 0x03B8) == 0x0380) Demod.syncBit = 2;
|
||||||
|
else if ((Demod.twoBits & 0x01DC) == 0x01C0) Demod.syncBit = 1;
|
||||||
|
else if ((Demod.twoBits & 0x00EE) == 0x00E0) Demod.syncBit = 0;
|
||||||
|
if (Demod.syncBit != 0xFFFF) {
|
||||||
|
Demod.startTime = (GetCountSspClk() & 0xfffffff8);
|
||||||
|
Demod.startTime -= Demod.syncBit;
|
||||||
|
Demod.bitCount = 1; // number of decoded data bits
|
||||||
|
Demod.shiftReg = 1;
|
||||||
|
Demod.state = DEMOD_14A_MANCHESTER_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (IsManchesterModulationNibble1(Demod.twoBits >> Demod.syncBit)) { // modulation in first half
|
||||||
|
if (IsManchesterModulationNibble2(Demod.twoBits >> Demod.syncBit)) { // ... and in second half = collision
|
||||||
|
if (!Demod.collisionPos) {
|
||||||
|
Demod.collisionPos = (Demod.len << 3) + Demod.bitCount;
|
||||||
|
}
|
||||||
|
} // modulation in first half only - Sequence D = 1
|
||||||
|
Demod.bitCount++;
|
||||||
|
Demod.shiftReg = (Demod.shiftReg << 1) | 0x1; // in both cases, add a 1 to the shiftreg
|
||||||
|
if (Demod.bitCount == 8) { // if we decoded a full byte
|
||||||
|
Demod.output[Demod.len++] = (Demod.shiftReg & 0xff);
|
||||||
|
Demod.bitCount = 0;
|
||||||
|
Demod.shiftReg = 0;
|
||||||
|
}
|
||||||
|
Demod.endTime = Demod.startTime + 8 * (8 * Demod.len + Demod.bitCount + 1) - 4;
|
||||||
|
} else { // no modulation in first half
|
||||||
|
if (IsManchesterModulationNibble2(Demod.twoBits >> Demod.syncBit)) { // and modulation in second half = Sequence E = 0
|
||||||
|
Demod.bitCount++;
|
||||||
|
Demod.shiftReg = (Demod.shiftReg << 1); // add a 0 to the shiftreg
|
||||||
|
if (Demod.bitCount >= 8) { // if we decoded a full byte
|
||||||
|
Demod.output[Demod.len++] = (Demod.shiftReg & 0xff);
|
||||||
|
Demod.bitCount = 0;
|
||||||
|
Demod.shiftReg = 0;
|
||||||
|
}
|
||||||
|
Demod.endTime = Demod.startTime + 8 * (8 * Demod.len + Demod.bitCount + 1);
|
||||||
|
} else { // no modulation in both halves - End of communication
|
||||||
|
if (Demod.bitCount > 0) { // there are some remaining data bits
|
||||||
|
Demod.shiftReg <<= (8 - Demod.bitCount); // left align the decoded bits
|
||||||
|
Demod.output[Demod.len++] = Demod.shiftReg & 0xff; // and add them to the output
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Demod.len) {
|
||||||
|
return true; // we are finished with decoding the raw data sequence
|
||||||
|
} else { // nothing received. Start over
|
||||||
|
Demod14aReset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false; // not finished yet, need more data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// Finally, a `sniffer' for ISO 14443 Type A
|
// Finally, a `sniffer' for ISO 14443 Type A
|
||||||
// Both sides of communication!
|
// Both sides of communication!
|
||||||
|
@ -506,10 +597,10 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
||||||
bool ReaderIsActive = false;
|
bool ReaderIsActive = false;
|
||||||
|
|
||||||
// Set up the demodulator for tag -> reader responses.
|
// Set up the demodulator for tag -> reader responses.
|
||||||
DemodInit(receivedResp, receivedRespPar);
|
Demod14aInit(receivedResp, receivedRespPar);
|
||||||
|
|
||||||
// Set up the demodulator for the reader -> tag commands
|
// Set up the demodulator for the reader -> tag commands
|
||||||
UartInit(receivedCmd, receivedCmdPar);
|
Uart14aInit(receivedCmd, receivedCmdPar);
|
||||||
|
|
||||||
DbpString("Starting to sniff");
|
DbpString("Starting to sniff");
|
||||||
|
|
||||||
|
@ -583,13 +674,13 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
||||||
true)) break;
|
true)) break;
|
||||||
}
|
}
|
||||||
/* ready to receive another command. */
|
/* ready to receive another command. */
|
||||||
UartReset();
|
Uart14aReset();
|
||||||
/* reset the demod code, which might have been */
|
/* reset the demod code, which might have been */
|
||||||
/* false-triggered by the commands from the reader. */
|
/* false-triggered by the commands from the reader. */
|
||||||
DemodReset();
|
Demod14aReset();
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
}
|
}
|
||||||
ReaderIsActive = (Uart.state != STATE_UNSYNCD);
|
ReaderIsActive = (Uart.state != STATE_14A_UNSYNCD);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no need to try decoding tag data if the reader is sending - and we cannot afford the time
|
// no need to try decoding tag data if the reader is sending - and we cannot afford the time
|
||||||
|
@ -608,13 +699,13 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
||||||
if ((!triggered) && (param & 0x01)) triggered = true;
|
if ((!triggered) && (param & 0x01)) triggered = true;
|
||||||
|
|
||||||
// ready to receive another response.
|
// ready to receive another response.
|
||||||
DemodReset();
|
Demod14aReset();
|
||||||
// reset the Miller decoder including its (now outdated) input buffer
|
// reset the Miller decoder including its (now outdated) input buffer
|
||||||
UartReset();
|
Uart14aReset();
|
||||||
//UartInit(receivedCmd, receivedCmdPar);
|
//Uart14aInit(receivedCmd, receivedCmdPar);
|
||||||
LED_C_OFF();
|
LED_C_OFF();
|
||||||
}
|
}
|
||||||
TagIsActive = (Demod.state != DEMOD_UNSYNCD);
|
TagIsActive = (Demod.state != DEMOD_14A_UNSYNCD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -754,7 +845,7 @@ static bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int *
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
|
||||||
|
|
||||||
// Now run a `software UART` on the stream of incoming samples.
|
// Now run a `software UART` on the stream of incoming samples.
|
||||||
UartInit(received, par);
|
Uart14aInit(received, par);
|
||||||
|
|
||||||
// clear RXRDY:
|
// clear RXRDY:
|
||||||
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
@ -1073,7 +1164,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
|
||||||
|
|
||||||
if (SimulateIso14443aInit(tagType, flags, data, &responses, &cuid, counters, tearings, &pages) == false) {
|
if (SimulateIso14443aInit(tagType, flags, data, &responses, &cuid, counters, tearings, &pages) == false) {
|
||||||
BigBuf_free_keep_EM();
|
BigBuf_free_keep_EM();
|
||||||
reply_ng(CMD_SIMULATE_MIFARE_CARD, PM3_EINIT, NULL, 0);
|
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1193,7 +1284,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
|
||||||
ar_nr_nonces[index].state = SECOND;
|
ar_nr_nonces[index].state = SECOND;
|
||||||
|
|
||||||
// send to client (one struct nonces_t)
|
// send to client (one struct nonces_t)
|
||||||
reply_ng(CMD_SIMULATE_MIFARE_CARD, PM3_SUCCESS, (uint8_t *)&ar_nr_nonces[index], sizeof(nonces_t));
|
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_SUCCESS, (uint8_t *)&ar_nr_nonces[index], sizeof(nonces_t));
|
||||||
|
|
||||||
ar_nr_nonces[index].state = EMPTY;
|
ar_nr_nonces[index].state = EMPTY;
|
||||||
ar_nr_nonces[index].sector = 0;
|
ar_nr_nonces[index].sector = 0;
|
||||||
|
@ -1517,7 +1608,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
|
||||||
Dbprintf("-[ Num of moebius tries [%d]", moebius_count);
|
Dbprintf("-[ Num of moebius tries [%d]", moebius_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
reply_ng(CMD_SIMULATE_MIFARE_CARD, retval, NULL, 0);
|
reply_ng(CMD_HF_MIFARE_SIMULATE, retval, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare a delayed transfer. This simply shifts ToSend[] by a number
|
// prepare a delayed transfer. This simply shifts ToSend[] by a number
|
||||||
|
@ -1553,7 +1644,7 @@ void PrepareDelayedTransfer(uint16_t delay) {
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing) {
|
static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing) {
|
||||||
|
|
||||||
if (!iso14443a_active)
|
if (!hf_field_active)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
|
||||||
|
@ -1719,7 +1810,7 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
|
||||||
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
|
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
|
||||||
|
|
||||||
// Now run a 'software UART' on the stream of incoming samples.
|
// Now run a 'software UART' on the stream of incoming samples.
|
||||||
UartInit(received, par);
|
Uart14aInit(received, par);
|
||||||
|
|
||||||
// Clear RXRDY:
|
// Clear RXRDY:
|
||||||
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
@ -1931,14 +2022,14 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
// Kovio - Thinfilm barcode. TAG-TALK-FIRST -
|
||||||
// Wait a certain time for tag response
|
// Wait a certain time for tag response
|
||||||
// If a response is captured return TRUE
|
// If a response is captured return TRUE
|
||||||
// If it takes too long return FALSE
|
// If it takes too long return FALSE
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset) {
|
bool GetIso14443aAnswerFromTag_Thinfilm(uint8_t *receivedResponse, uint8_t *received_len) {
|
||||||
uint32_t c = 0;
|
|
||||||
|
|
||||||
if (!iso14443a_active)
|
if (!hf_field_active)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Set FPGA mode to "reader listen mode", no modulation (listen
|
// Set FPGA mode to "reader listen mode", no modulation (listen
|
||||||
|
@ -1948,7 +2039,56 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN);
|
||||||
|
|
||||||
// Now get the answer from the card
|
// Now get the answer from the card
|
||||||
DemodInit(receivedResponse, receivedResponsePar);
|
Demod14aInit(receivedResponse, NULL);
|
||||||
|
|
||||||
|
// clear RXRDY:
|
||||||
|
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
(void)b;
|
||||||
|
|
||||||
|
uint32_t receive_timer = GetTickCount();
|
||||||
|
for (;;) {
|
||||||
|
WDT_HIT();
|
||||||
|
|
||||||
|
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||||
|
b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
if (ManchesterDecoding_Thinfilm(b)) {
|
||||||
|
*received_len = Demod.len;
|
||||||
|
// log
|
||||||
|
LogTrace(receivedResponse, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, NULL, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// timeout already in ms + 10ms guard time
|
||||||
|
if (GetTickCount() - receive_timer > 1160)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*received_len = Demod.len;
|
||||||
|
// log
|
||||||
|
LogTrace(receivedResponse, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, NULL, false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Wait a certain time for tag response
|
||||||
|
// If a response is captured return TRUE
|
||||||
|
// If it takes too long return FALSE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset) {
|
||||||
|
uint32_t c = 0;
|
||||||
|
|
||||||
|
if (!hf_field_active)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Set FPGA mode to "reader listen mode", no modulation (listen
|
||||||
|
// only, since we are receiving, not transmitting).
|
||||||
|
// Signal field is on with the appropriate LED
|
||||||
|
LED_D_ON();
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN);
|
||||||
|
|
||||||
|
// Now get the answer from the card
|
||||||
|
Demod14aInit(receivedResponse, receivedResponsePar);
|
||||||
|
|
||||||
// clear RXRDY:
|
// clear RXRDY:
|
||||||
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
@ -1964,7 +2104,7 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive
|
||||||
if (ManchesterDecoding(b, offset, 0)) {
|
if (ManchesterDecoding(b, offset, 0)) {
|
||||||
NextTransferTime = MAX(NextTransferTime, Demod.endTime - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FRAME_DELAY_TIME_PICC_TO_PCD);
|
NextTransferTime = MAX(NextTransferTime, Demod.endTime - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FRAME_DELAY_TIME_PICC_TO_PCD);
|
||||||
return true;
|
return true;
|
||||||
} else if (c++ > timeout && Demod.state == DEMOD_UNSYNCD) {
|
} else if (c++ > timeout && Demod.state == DEMOD_14A_UNSYNCD) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2018,6 +2158,7 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par) {
|
||||||
return Demod.len;
|
return Demod.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// This function misstreats the ISO 14443a anticollision procedure.
|
// This function misstreats the ISO 14443a anticollision procedure.
|
||||||
// by fooling the reader there is a collision and forceing the reader to
|
// by fooling the reader there is a collision and forceing the reader to
|
||||||
// increase the uid bytes. The might be an overflow, DoS will occure.
|
// increase the uid bytes. The might be an overflow, DoS will occure.
|
||||||
|
@ -2363,8 +2504,7 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
|
||||||
|
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
// Signal field is on with the appropriate LED
|
// Signal field is on with the appropriate LED
|
||||||
if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD ||
|
if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD || fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN)
|
||||||
fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN)
|
|
||||||
LED_D_ON();
|
LED_D_ON();
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | fpga_minor_mode);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | fpga_minor_mode);
|
||||||
|
@ -2374,18 +2514,19 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
|
||||||
StartCountSspClk();
|
StartCountSspClk();
|
||||||
|
|
||||||
// Prepare the demodulation functions
|
// Prepare the demodulation functions
|
||||||
DemodReset();
|
Demod14aReset();
|
||||||
UartReset();
|
Uart14aReset();
|
||||||
NextTransferTime = 2 * DELAY_ARM2AIR_AS_READER;
|
NextTransferTime = 2 * DELAY_ARM2AIR_AS_READER;
|
||||||
iso14a_set_timeout(1060); // 106 * 10ms default
|
iso14a_set_timeout(1060); // 106 * 10ms default
|
||||||
|
|
||||||
iso14443a_active = true;
|
hf_field_active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void iso14443a_off() {
|
|
||||||
|
void hf_field_off(void) {
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
iso14443a_active = false;
|
hf_field_active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Peter Fillmore 2015
|
/* Peter Fillmore 2015
|
||||||
|
@ -2590,7 +2731,7 @@ void ReaderIso14443a(PacketCommandNG *c) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
OUT:
|
OUT:
|
||||||
iso14443a_off();
|
hf_field_off();
|
||||||
set_tracing(false);
|
set_tracing(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2885,7 +3026,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) {
|
||||||
|
|
||||||
reply_mix(CMD_ACK, isOK, 0, 0, buf, sizeof(buf));
|
reply_mix(CMD_ACK, isOK, 0, 0, buf, sizeof(buf));
|
||||||
|
|
||||||
iso14443a_off();
|
hf_field_off();
|
||||||
set_tracing(false);
|
set_tracing(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2893,7 +3034,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) {
|
||||||
* Mifare Classic NACK-bug detection
|
* Mifare Classic NACK-bug detection
|
||||||
* Thanks to @doegox for the feedback and new approaches.
|
* Thanks to @doegox for the feedback and new approaches.
|
||||||
*/
|
*/
|
||||||
void DetectNACKbug() {
|
void DetectNACKbug(void) {
|
||||||
uint8_t mf_auth[] = {0x60, 0x00, 0xF5, 0x7B};
|
uint8_t mf_auth[] = {0x60, 0x00, 0xF5, 0x7B};
|
||||||
uint8_t mf_nr_ar[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
uint8_t mf_nr_ar[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
@ -3120,10 +3261,10 @@ void DetectNACKbug() {
|
||||||
data[0] = isOK;
|
data[0] = isOK;
|
||||||
data[1] = num_nacks;
|
data[1] = num_nacks;
|
||||||
num_to_bytes(i, 2, data + 2);
|
num_to_bytes(i, 2, data + 2);
|
||||||
reply_ng(CMD_MIFARE_NACK_DETECT, status, data, 4);
|
reply_ng(CMD_HF_MIFARE_NACK_DETECT, status, data, 4);
|
||||||
|
|
||||||
//reply_mix(CMD_ACK, isOK, num_nacks, i, 0, 0);
|
//reply_mix(CMD_ACK, isOK, num_nacks, i, 0, 0);
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
iso14443a_off();
|
hf_field_off();
|
||||||
set_tracing(false);
|
set_tracing(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,21 +13,9 @@
|
||||||
#ifndef __ISO14443A_H
|
#ifndef __ISO14443A_H
|
||||||
#define __ISO14443A_H
|
#define __ISO14443A_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#include "common.h"
|
||||||
extern "C" {
|
#include "mifare.h" // struct
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "pm3_cmd.h"
|
#include "pm3_cmd.h"
|
||||||
#include "cmd.h"
|
|
||||||
#include "apps.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "string.h"
|
|
||||||
#include "crc16.h"
|
|
||||||
#include "mifaresniff.h"
|
|
||||||
#include "crapto1/crapto1.h"
|
|
||||||
#include "mifareutil.h"
|
|
||||||
#include "parity.h"
|
|
||||||
#include "mifare.h" // structs
|
|
||||||
|
|
||||||
// When the PM acts as tag and is receiving it takes
|
// When the PM acts as tag and is receiving it takes
|
||||||
// 2 ticks delay in the RF part (for the first falling edge),
|
// 2 ticks delay in the RF part (for the first falling edge),
|
||||||
|
@ -42,11 +30,11 @@ extern "C" {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum {
|
enum {
|
||||||
DEMOD_UNSYNCD,
|
DEMOD_14A_UNSYNCD,
|
||||||
// DEMOD_HALF_SYNCD,
|
// DEMOD_14A_HALF_SYNCD,
|
||||||
// DEMOD_MOD_FIRST_HALF,
|
// DEMOD_14A_MOD_FIRST_HALF,
|
||||||
// DEMOD_NOMOD_FIRST_HALF,
|
// DEMOD_14A_NOMOD_FIRST_HALF,
|
||||||
DEMOD_MANCHESTER_DATA
|
DEMOD_14A_MANCHESTER_DATA
|
||||||
} state;
|
} state;
|
||||||
uint16_t twoBits;
|
uint16_t twoBits;
|
||||||
uint16_t highCnt;
|
uint16_t highCnt;
|
||||||
|
@ -61,7 +49,7 @@ typedef struct {
|
||||||
uint32_t startTime, endTime;
|
uint32_t startTime, endTime;
|
||||||
uint8_t *output;
|
uint8_t *output;
|
||||||
uint8_t *parity;
|
uint8_t *parity;
|
||||||
} tDemod;
|
} tDemod14a;
|
||||||
/*
|
/*
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MOD_NOMOD = 0,
|
MOD_NOMOD = 0,
|
||||||
|
@ -73,11 +61,11 @@ typedef enum {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum {
|
enum {
|
||||||
STATE_UNSYNCD,
|
STATE_14A_UNSYNCD,
|
||||||
STATE_START_OF_COMMUNICATION,
|
STATE_14A_START_OF_COMMUNICATION,
|
||||||
STATE_MILLER_X,
|
STATE_14A_MILLER_X,
|
||||||
STATE_MILLER_Y,
|
STATE_14A_MILLER_Y,
|
||||||
STATE_MILLER_Z,
|
STATE_14A_MILLER_Z,
|
||||||
// DROP_NONE,
|
// DROP_NONE,
|
||||||
// DROP_FIRST_HALF,
|
// DROP_FIRST_HALF,
|
||||||
} state;
|
} state;
|
||||||
|
@ -93,7 +81,7 @@ typedef struct {
|
||||||
uint32_t startTime, endTime;
|
uint32_t startTime, endTime;
|
||||||
uint8_t *output;
|
uint8_t *output;
|
||||||
uint8_t *parity;
|
uint8_t *parity;
|
||||||
} tUart;
|
} tUart14a;
|
||||||
|
|
||||||
#ifndef AddCrc14A
|
#ifndef AddCrc14A
|
||||||
# define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1)
|
# define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1)
|
||||||
|
@ -109,12 +97,12 @@ typedef struct {
|
||||||
|
|
||||||
void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par);
|
void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par);
|
||||||
|
|
||||||
tDemod *GetDemod(void);
|
tDemod14a *GetDemod14a(void);
|
||||||
void DemodReset(void);
|
void Demod14aReset(void);
|
||||||
void DemodInit(uint8_t *data, uint8_t *par);
|
void Demod14aInit(uint8_t *data, uint8_t *par);
|
||||||
tUart *GetUart(void);
|
tUart14a *GetUart14a(void);
|
||||||
void UartReset(void);
|
void Uart14aReset(void);
|
||||||
void UartInit(uint8_t *data, uint8_t *par);
|
void Uart14aInit(uint8_t *data, uint8_t *par);
|
||||||
RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time);
|
RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time);
|
||||||
RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time);
|
RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time);
|
||||||
|
|
||||||
|
@ -132,6 +120,7 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, u
|
||||||
int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats);
|
int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats);
|
||||||
int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades);
|
int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades);
|
||||||
void iso14a_set_trigger(bool enable);
|
void iso14a_set_trigger(bool enable);
|
||||||
|
void hf_field_off(void);
|
||||||
|
|
||||||
int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen);
|
int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen);
|
||||||
int EmSend4bit(uint8_t resp);
|
int EmSend4bit(uint8_t resp);
|
||||||
|
@ -148,10 +137,8 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start
|
||||||
uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity);
|
uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity);
|
||||||
|
|
||||||
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype);
|
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype);
|
||||||
void DetectNACKbug();
|
void DetectNACKbug(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
bool GetIso14443aAnswerFromTag_Thinfilm(uint8_t *receivedResponse, uint8_t *received_len);
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __ISO14443A_H */
|
#endif /* __ISO14443A_H */
|
||||||
|
|
|
@ -10,6 +10,20 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "iso14443b.h"
|
#include "iso14443b.h"
|
||||||
|
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "common.h" // access to global variable: DBGLEVEL
|
||||||
|
#include "util.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "crc16.h"
|
||||||
|
#include "protocols.h"
|
||||||
|
#include "appmain.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "cmd.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "commonutil.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
|
||||||
#ifndef FWT_TIMEOUT_14B
|
#ifndef FWT_TIMEOUT_14B
|
||||||
// defaults to 2000ms
|
// defaults to 2000ms
|
||||||
# define FWT_TIMEOUT_14B 35312
|
# define FWT_TIMEOUT_14B 35312
|
||||||
|
@ -52,7 +66,7 @@ static uint32_t iso14b_timeout = FWT_TIMEOUT_14B;
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// An ISO 14443 Type B tag. We listen for commands from the reader, using
|
// An ISO 14443 Type B tag. We listen for commands from the reader, using
|
||||||
// a UART kind of thing that's implemented in software. When we get a
|
// a kind of thing that's implemented in software. When we get a
|
||||||
// frame (i.e., a group of bytes between SOF and EOF), we check the CRC.
|
// frame (i.e., a group of bytes between SOF and EOF), we check the CRC.
|
||||||
// If it's good, then we can do something appropriate with it, and send
|
// If it's good, then we can do something appropriate with it, and send
|
||||||
// a response.
|
// a response.
|
||||||
|
@ -60,14 +74,14 @@ static uint32_t iso14b_timeout = FWT_TIMEOUT_14B;
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// The software UART that receives commands from the reader, and its state variables.
|
// The software that receives commands from the reader, and its state variables.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static struct {
|
static struct {
|
||||||
enum {
|
enum {
|
||||||
STATE_UNSYNCD,
|
STATE_14B_UNSYNCD,
|
||||||
STATE_GOT_FALLING_EDGE_OF_SOF,
|
STATE_14B_GOT_FALLING_EDGE_OF_SOF,
|
||||||
STATE_AWAITING_START_BIT,
|
STATE_14B_AWAITING_START_BIT,
|
||||||
STATE_RECEIVING_DATA
|
STATE_14B_RECEIVING_DATA
|
||||||
} state;
|
} state;
|
||||||
uint16_t shiftReg;
|
uint16_t shiftReg;
|
||||||
int bitCnt;
|
int bitCnt;
|
||||||
|
@ -77,8 +91,8 @@ static struct {
|
||||||
uint8_t *output;
|
uint8_t *output;
|
||||||
} Uart;
|
} Uart;
|
||||||
|
|
||||||
static void UartReset() {
|
static void Uart14bReset() {
|
||||||
Uart.state = STATE_UNSYNCD;
|
Uart.state = STATE_14B_UNSYNCD;
|
||||||
Uart.shiftReg = 0;
|
Uart.shiftReg = 0;
|
||||||
Uart.bitCnt = 0;
|
Uart.bitCnt = 0;
|
||||||
Uart.byteCnt = 0;
|
Uart.byteCnt = 0;
|
||||||
|
@ -86,9 +100,9 @@ static void UartReset() {
|
||||||
Uart.posCnt = 0;
|
Uart.posCnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UartInit(uint8_t *data) {
|
static void Uart14bInit(uint8_t *data) {
|
||||||
Uart.output = data;
|
Uart.output = data;
|
||||||
UartReset();
|
Uart14bReset();
|
||||||
// memset(Uart.output, 0x00, MAX_FRAME_SIZE);
|
// memset(Uart.output, 0x00, MAX_FRAME_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +134,7 @@ static struct {
|
||||||
} Demod;
|
} Demod;
|
||||||
|
|
||||||
// Clear out the state of the "UART" that receives from the tag.
|
// Clear out the state of the "UART" that receives from the tag.
|
||||||
static void DemodReset() {
|
static void Demod14bReset() {
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_UNSYNCD;
|
||||||
Demod.bitCount = 0;
|
Demod.bitCount = 0;
|
||||||
Demod.posCount = 0;
|
Demod.posCount = 0;
|
||||||
|
@ -133,9 +147,9 @@ static void DemodReset() {
|
||||||
Demod.endTime = 0;
|
Demod.endTime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DemodInit(uint8_t *data) {
|
static void Demod14bInit(uint8_t *data) {
|
||||||
Demod.output = data;
|
Demod.output = data;
|
||||||
DemodReset();
|
Demod14bReset();
|
||||||
// memset(Demod.output, 0x00, MAX_FRAME_SIZE);
|
// memset(Demod.output, 0x00, MAX_FRAME_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,16 +329,16 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) {
|
||||||
*/
|
*/
|
||||||
static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
|
static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
|
||||||
switch (Uart.state) {
|
switch (Uart.state) {
|
||||||
case STATE_UNSYNCD:
|
case STATE_14B_UNSYNCD:
|
||||||
if (!bit) {
|
if (!bit) {
|
||||||
// we went low, so this could be the beginning of an SOF
|
// we went low, so this could be the beginning of an SOF
|
||||||
Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF;
|
Uart.state = STATE_14B_GOT_FALLING_EDGE_OF_SOF;
|
||||||
Uart.posCnt = 0;
|
Uart.posCnt = 0;
|
||||||
Uart.bitCnt = 0;
|
Uart.bitCnt = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STATE_GOT_FALLING_EDGE_OF_SOF:
|
case STATE_14B_GOT_FALLING_EDGE_OF_SOF:
|
||||||
Uart.posCnt++;
|
Uart.posCnt++;
|
||||||
if (Uart.posCnt == 2) { // sample every 4 1/fs in the middle of a bit
|
if (Uart.posCnt == 2) { // sample every 4 1/fs in the middle of a bit
|
||||||
if (bit) {
|
if (bit) {
|
||||||
|
@ -333,11 +347,11 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
|
||||||
// zeros that it's a valid SOF
|
// zeros that it's a valid SOF
|
||||||
Uart.posCnt = 0;
|
Uart.posCnt = 0;
|
||||||
Uart.byteCnt = 0;
|
Uart.byteCnt = 0;
|
||||||
Uart.state = STATE_AWAITING_START_BIT;
|
Uart.state = STATE_14B_AWAITING_START_BIT;
|
||||||
LED_A_ON(); // Indicate we got a valid SOF
|
LED_A_ON(); // Indicate we got a valid SOF
|
||||||
} else {
|
} else {
|
||||||
// didn't stay down long enough before going high, error
|
// didn't stay down long enough before going high, error
|
||||||
Uart.state = STATE_UNSYNCD;
|
Uart.state = STATE_14B_UNSYNCD;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// do nothing, keep waiting
|
// do nothing, keep waiting
|
||||||
|
@ -348,27 +362,27 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
|
||||||
if (Uart.bitCnt > 12) {
|
if (Uart.bitCnt > 12) {
|
||||||
// Give up if we see too many zeros without a one, too.
|
// Give up if we see too many zeros without a one, too.
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
Uart.state = STATE_UNSYNCD;
|
Uart.state = STATE_14B_UNSYNCD;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STATE_AWAITING_START_BIT:
|
case STATE_14B_AWAITING_START_BIT:
|
||||||
Uart.posCnt++;
|
Uart.posCnt++;
|
||||||
if (bit) {
|
if (bit) {
|
||||||
if (Uart.posCnt > 50 / 2) { // max 57us between characters = 49 1/fs, max 3 etus after low phase of SOF = 24 1/fs
|
if (Uart.posCnt > 50 / 2) { // max 57us between characters = 49 1/fs, max 3 etus after low phase of SOF = 24 1/fs
|
||||||
// stayed high for too long between characters, error
|
// stayed high for too long between characters, error
|
||||||
Uart.state = STATE_UNSYNCD;
|
Uart.state = STATE_14B_UNSYNCD;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// falling edge, this starts the data byte
|
// falling edge, this starts the data byte
|
||||||
Uart.posCnt = 0;
|
Uart.posCnt = 0;
|
||||||
Uart.bitCnt = 0;
|
Uart.bitCnt = 0;
|
||||||
Uart.shiftReg = 0;
|
Uart.shiftReg = 0;
|
||||||
Uart.state = STATE_RECEIVING_DATA;
|
Uart.state = STATE_14B_RECEIVING_DATA;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STATE_RECEIVING_DATA:
|
case STATE_14B_RECEIVING_DATA:
|
||||||
Uart.posCnt++;
|
Uart.posCnt++;
|
||||||
if (Uart.posCnt == 2) {
|
if (Uart.posCnt == 2) {
|
||||||
// time to sample a bit
|
// time to sample a bit
|
||||||
|
@ -391,30 +405,30 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
|
||||||
if (Uart.byteCnt >= Uart.byteCntMax) {
|
if (Uart.byteCnt >= Uart.byteCntMax) {
|
||||||
// Buffer overflowed, give up
|
// Buffer overflowed, give up
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
Uart.state = STATE_UNSYNCD;
|
Uart.state = STATE_14B_UNSYNCD;
|
||||||
} else {
|
} else {
|
||||||
// so get the next byte now
|
// so get the next byte now
|
||||||
Uart.posCnt = 0;
|
Uart.posCnt = 0;
|
||||||
Uart.state = STATE_AWAITING_START_BIT;
|
Uart.state = STATE_14B_AWAITING_START_BIT;
|
||||||
}
|
}
|
||||||
} else if (Uart.shiftReg == 0x000) {
|
} else if (Uart.shiftReg == 0x000) {
|
||||||
// this is an EOF byte
|
// this is an EOF byte
|
||||||
LED_A_OFF(); // Finished receiving
|
LED_A_OFF(); // Finished receiving
|
||||||
Uart.state = STATE_UNSYNCD;
|
Uart.state = STATE_14B_UNSYNCD;
|
||||||
if (Uart.byteCnt != 0)
|
if (Uart.byteCnt != 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// this is an error
|
// this is an error
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
Uart.state = STATE_UNSYNCD;
|
Uart.state = STATE_14B_UNSYNCD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
Uart.state = STATE_UNSYNCD;
|
Uart.state = STATE_14B_UNSYNCD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -454,7 +468,7 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
// Now run a `software UART' on the stream of incoming samples.
|
// Now run a `software UART' on the stream of incoming samples.
|
||||||
UartInit(received);
|
Uart14bInit(received);
|
||||||
|
|
||||||
uint8_t mask;
|
uint8_t mask;
|
||||||
while (!BUTTON_PRESS()) {
|
while (!BUTTON_PRESS()) {
|
||||||
|
@ -949,7 +963,7 @@ static void GetTagSamplesFor14443bDemod() {
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
|
|
||||||
// Set up the demodulator for tag -> reader responses.
|
// Set up the demodulator for tag -> reader responses.
|
||||||
DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||||
|
|
||||||
// The DMA buffer, used to stream samples from the FPGA
|
// The DMA buffer, used to stream samples from the FPGA
|
||||||
int8_t *dmaBuf = (int8_t *) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
|
int8_t *dmaBuf = (int8_t *) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
|
||||||
|
@ -1306,8 +1320,8 @@ void iso14443b_setup() {
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
|
|
||||||
// Initialize Demod and Uart structs
|
// Initialize Demod and Uart structs
|
||||||
DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||||
UartInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
Uart14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||||
|
|
||||||
// connect Demodulated Signal to ADC:
|
// connect Demodulated Signal to ADC:
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||||
|
@ -1411,8 +1425,8 @@ static void iso1444b_setup_sniff(void) {
|
||||||
set_tracing(true);
|
set_tracing(true);
|
||||||
|
|
||||||
// Initialize Demod and Uart structs
|
// Initialize Demod and Uart structs
|
||||||
DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||||
UartInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
Uart14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||||
|
|
||||||
if (DBGLEVEL > 1) {
|
if (DBGLEVEL > 1) {
|
||||||
// Print debug information about the buffer sizes
|
// Print debug information about the buffer sizes
|
||||||
|
@ -1502,8 +1516,8 @@ void RAMFUNC SniffIso14443b(void) {
|
||||||
if (Handle14443bReaderUartBit(ci & 0x01)) {
|
if (Handle14443bReaderUartBit(ci & 0x01)) {
|
||||||
time_stop = GetCountSspClk() - time_0;
|
time_stop = GetCountSspClk() - time_0;
|
||||||
LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true);
|
LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true);
|
||||||
UartReset();
|
Uart14bReset();
|
||||||
DemodReset();
|
Demod14bReset();
|
||||||
} else {
|
} else {
|
||||||
time_start = GetCountSspClk() - time_0;
|
time_start = GetCountSspClk() - time_0;
|
||||||
}
|
}
|
||||||
|
@ -1511,12 +1525,12 @@ void RAMFUNC SniffIso14443b(void) {
|
||||||
if (Handle14443bReaderUartBit(cq & 0x01)) {
|
if (Handle14443bReaderUartBit(cq & 0x01)) {
|
||||||
time_stop = GetCountSspClk() - time_0;
|
time_stop = GetCountSspClk() - time_0;
|
||||||
LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true);
|
LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true);
|
||||||
UartReset();
|
Uart14bReset();
|
||||||
DemodReset();
|
Demod14bReset();
|
||||||
} else {
|
} else {
|
||||||
time_start = GetCountSspClk() - time_0;
|
time_start = GetCountSspClk() - time_0;
|
||||||
}
|
}
|
||||||
ReaderIsActive = (Uart.state > STATE_GOT_FALLING_EDGE_OF_SOF);
|
ReaderIsActive = (Uart.state > STATE_14B_GOT_FALLING_EDGE_OF_SOF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no need to try decoding tag data if the reader is sending - and we cannot afford the time
|
// no need to try decoding tag data if the reader is sending - and we cannot afford the time
|
||||||
|
@ -1527,8 +1541,8 @@ void RAMFUNC SniffIso14443b(void) {
|
||||||
if (Handle14443bTagSamplesDemod(ci, cq)) {
|
if (Handle14443bTagSamplesDemod(ci, cq)) {
|
||||||
time_stop = GetCountSspClk() - time_0;
|
time_stop = GetCountSspClk() - time_0;
|
||||||
LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false);
|
LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false);
|
||||||
UartReset();
|
Uart14bReset();
|
||||||
DemodReset();
|
Demod14bReset();
|
||||||
} else {
|
} else {
|
||||||
time_start = GetCountSspClk() - time_0;
|
time_start = GetCountSspClk() - time_0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,18 +13,10 @@
|
||||||
#ifndef __ISO14443B_H
|
#ifndef __ISO14443B_H
|
||||||
#define __ISO14443B_H
|
#define __ISO14443B_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#include "common.h"
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "common.h" // access to global variable: DBGLEVEL
|
|
||||||
#include "apps.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "string.h"
|
|
||||||
#include "crc16.h"
|
|
||||||
#include "mifare.h"
|
#include "mifare.h"
|
||||||
#include "protocols.h"
|
#include "pm3_cmd.h"
|
||||||
|
|
||||||
#ifndef AddCrc14A
|
#ifndef AddCrc14A
|
||||||
# define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1)
|
# define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1)
|
||||||
|
@ -34,12 +26,18 @@ extern "C" {
|
||||||
# define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1)
|
# define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void SendRawCommand14443B_Ex(PacketCommandNG *c);
|
|
||||||
void iso14443b_setup();
|
void iso14443b_setup();
|
||||||
uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response);
|
uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response);
|
||||||
uint8_t iso14443b_select_card(iso14b_card_select_t *card);
|
uint8_t iso14443b_select_card(iso14b_card_select_t *card);
|
||||||
uint8_t iso14443b_select_card_srx(iso14b_card_select_t *card);
|
uint8_t iso14443b_select_card_srx(iso14b_card_select_t *card);
|
||||||
|
|
||||||
|
void SimulateIso14443bTag(uint32_t pupi);
|
||||||
|
void AcquireRawAdcSamplesIso14443b(uint32_t parameter);
|
||||||
|
void ReadSTMemoryIso14443b(uint8_t numofblocks);
|
||||||
|
void RAMFUNC SniffIso14443b(void);
|
||||||
|
void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]);
|
||||||
|
void SendRawCommand14443B_Ex(PacketCommandNG *c);
|
||||||
|
|
||||||
// testfunctions
|
// testfunctions
|
||||||
void WaitForFpgaDelayQueueIsEmpty(uint16_t delay);
|
void WaitForFpgaDelayQueueIsEmpty(uint16_t delay);
|
||||||
void ClearFpgaShiftingRegisters(void);
|
void ClearFpgaShiftingRegisters(void);
|
||||||
|
@ -53,8 +51,4 @@ void ClearFpgaShiftingRegisters(void);
|
||||||
#define SIM_ACKNOWLEDGE 5
|
#define SIM_ACKNOWLEDGE 5
|
||||||
#define SIM_WORK 6
|
#define SIM_WORK 6
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __ISO14443B_H */
|
#endif /* __ISO14443B_H */
|
||||||
|
|
|
@ -32,8 +32,8 @@
|
||||||
//
|
//
|
||||||
// VICC (tag) -> VCD (reader)
|
// VICC (tag) -> VCD (reader)
|
||||||
// Modulation:
|
// Modulation:
|
||||||
// ASK / one subcarrier (423,75 khz)
|
// ASK / one subcarrier (423,75 kHz)
|
||||||
// FSK / two subcarriers (423,75 khz && 484,28 khz)
|
// FSK / two subcarriers (423,75 kHz && 484,28 kHz)
|
||||||
// Data Rates / Modes:
|
// Data Rates / Modes:
|
||||||
// low ASK: 6,62 kbit/s
|
// low ASK: 6,62 kbit/s
|
||||||
// low FSK: 6.67 kbit/s
|
// low FSK: 6.67 kbit/s
|
||||||
|
@ -58,12 +58,20 @@
|
||||||
// *) remove or refactor code under "depricated"
|
// *) remove or refactor code under "depricated"
|
||||||
// *) document all the functions
|
// *) document all the functions
|
||||||
|
|
||||||
#include "proxmark3.h"
|
#include "iso15693.h"
|
||||||
|
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "apps.h"
|
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "iso15693tools.h"
|
#include "iso15693tools.h"
|
||||||
#include "cmd.h"
|
#include "cmd.h"
|
||||||
|
#include "appmain.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "commonutil.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "crc16.h"
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
// ISO 15693 Part 2 - Air Interface
|
// ISO 15693 Part 2 - Air Interface
|
||||||
|
|
26
armsrc/iso15693.h
Normal file
26
armsrc/iso15693.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Jonathan Westhues, Aug 2005
|
||||||
|
// Gerhard de Koning Gans, April 2008, May 2011
|
||||||
|
//
|
||||||
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
// the license.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Definitions internal to the app source.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifndef __ISO15693_H
|
||||||
|
#define __ISO15693_H
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#include "pm3_cmd.h" // struct
|
||||||
|
|
||||||
|
void RecordRawAdcSamplesIso15693(void);
|
||||||
|
void AcquireRawAdcSamplesIso15693(void);
|
||||||
|
void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg
|
||||||
|
void SimTagIso15693(uint32_t parameter, uint8_t *uid); // simulate an ISO15693 tag - greg
|
||||||
|
void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox
|
||||||
|
void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI - atrox
|
||||||
|
void Iso15693InitReader(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -7,7 +7,7 @@
|
||||||
Linker script for the ARM binary
|
Linker script for the ARM binary
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
INCLUDE ../common/ldscript.common
|
INCLUDE ../common_arm/ldscript.common
|
||||||
|
|
||||||
PHDRS
|
PHDRS
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,11 +11,20 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "legicrf.h"
|
#include "legicrf.h"
|
||||||
|
|
||||||
#include "ticks.h" /* timers */
|
|
||||||
#include "crc.h" /* legic crc-4 */
|
#include "crc.h" /* legic crc-4 */
|
||||||
#include "legic_prng.h" /* legic PRNG impl */
|
#include "legic_prng.h" /* legic PRNG impl */
|
||||||
#include "legic.h" /* legic_card_select_t struct */
|
#include "legic.h" /* legic_card_select_t struct */
|
||||||
|
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "cmd.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "protocols.h"
|
||||||
|
|
||||||
static uint8_t *legic_mem; /* card memory, used for read, write */
|
static uint8_t *legic_mem; /* card memory, used for read, write */
|
||||||
static legic_card_select_t card;/* metadata of currently selected card */
|
static legic_card_select_t card;/* metadata of currently selected card */
|
||||||
static crc_t legic_crc;
|
static crc_t legic_crc;
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#ifndef __LEGICRF_H
|
#ifndef __LEGICRF_H
|
||||||
#define __LEGICRF_H
|
#define __LEGICRF_H
|
||||||
|
|
||||||
#include "proxmark3.h"
|
#include "common.h"
|
||||||
|
|
||||||
void LegicRfInfo(void);
|
void LegicRfInfo(void);
|
||||||
void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv);
|
void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv);
|
||||||
|
|
|
@ -11,11 +11,17 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "legicrf.h"
|
#include "legicrf.h"
|
||||||
|
|
||||||
#include "ticks.h" /* timers */
|
|
||||||
#include "crc.h" /* legic crc-4 */
|
#include "crc.h" /* legic crc-4 */
|
||||||
#include "legic_prng.h" /* legic PRNG impl */
|
#include "legic_prng.h" /* legic PRNG impl */
|
||||||
#include "legic.h" /* legic_card_select_t struct */
|
#include "legic.h" /* legic_card_select_t struct */
|
||||||
|
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
static uint8_t *legic_mem; /* card memory, used for sim */
|
static uint8_t *legic_mem; /* card memory, used for sim */
|
||||||
static legic_card_select_t card;/* metadata of currently selected card */
|
static legic_card_select_t card;/* metadata of currently selected card */
|
||||||
static crc_t legic_crc;
|
static crc_t legic_crc;
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#ifndef __LEGICRFSIM_H
|
#ifndef __LEGICRFSIM_H
|
||||||
#define __LEGICRFSIM_H
|
#define __LEGICRFSIM_H
|
||||||
|
|
||||||
#include "proxmark3.h"
|
#include "common.h"
|
||||||
|
|
||||||
void LegicRfSimulate(uint8_t tagtype);
|
void LegicRfSimulate(uint8_t tagtype);
|
||||||
|
|
||||||
|
|
488
armsrc/lfops.c
488
armsrc/lfops.c
|
@ -8,54 +8,71 @@
|
||||||
// Also routines for raw mode reading/simulating of LF waveform
|
// Also routines for raw mode reading/simulating of LF waveform
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "proxmark3.h"
|
#include "lfops.h"
|
||||||
#include "apps.h"
|
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "cmd.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "dbprint.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "hitag2.h"
|
#include "commonutil.h"
|
||||||
|
|
||||||
#include "crc16.h"
|
#include "crc16.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
#include "printf.h"
|
||||||
#include "lfdemod.h"
|
#include "lfdemod.h"
|
||||||
#include "lfsampling.h"
|
#include "lfsampling.h"
|
||||||
#include "protocols.h"
|
#include "protocols.h"
|
||||||
#include "usb_cdc.h" // for usb_poll_validate_length
|
|
||||||
#include "common.h"
|
|
||||||
#include "pmflash.h"
|
#include "pmflash.h"
|
||||||
#include "flashmem.h" // persistence on mem
|
#include "flashmem.h" // persistence on flash
|
||||||
|
|
||||||
|
/*
|
||||||
|
Notes about EM4xxx timings.
|
||||||
|
|
||||||
|
The timing values differs between cards, we got EM410x, EM43x5, EM445x etc.
|
||||||
|
We are trying to unify and enable the Proxmark to easily detect and select correct timings automatic.
|
||||||
|
The measures from datasheets doesn't always match correct the hardware features of RDV4 antenans and we still wanted to let other devices with other custom antennas
|
||||||
|
still benefit from this repo. This is why its configurable and we use to set these dynamic settings in device external flash memory.
|
||||||
|
|
||||||
//#define START_GAP 31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc)
|
|
||||||
//#define WRITE_GAP 8*8 // 17*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc)
|
|
||||||
//#define WRITE_0 15*8 // 18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc)
|
|
||||||
//#define WRITE_1 47*8 // 50*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (56fc) 432 for T55x7; 448 for E5550
|
|
||||||
//#define READ_GAP 15*8
|
|
||||||
|
|
||||||
// VALUES TAKEN FROM EM4x function: SendForward
|
// VALUES TAKEN FROM EM4x function: SendForward
|
||||||
// START_GAP = 440; (55*8) cycles at 125Khz (8us = 1cycle)
|
// START_GAP = 440; (55*8) cycles at 125kHz (8us = 1cycle)
|
||||||
// WRITE_GAP = 128; (16*8)
|
// WRITE_GAP = 128; (16*8)
|
||||||
// WRITE_1 = 256 32*8; (32*8)
|
// WRITE_1 = 256 32*8; (32*8)
|
||||||
|
|
||||||
// These timings work for 4469/4269/4305 (with the 55*8 above)
|
// These timings work for 4469/4269/4305 (with the 55*8 above)
|
||||||
// WRITE_0 = 23*8 , 9*8
|
// WRITE_0 = 23*8 , 9*8
|
||||||
|
|
||||||
// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
|
Not about ARM TIMERS
|
||||||
// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
|
Short note about timers on Proxmark device ARM. They are a bit differently implemented and gives decent correctness.
|
||||||
// Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier)
|
|
||||||
// T0 = TIMER_CLOCK1 / 125000 = 192
|
SAM7S has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
|
||||||
// 1 Cycle = 8 microseconds(us) == 1 field clock
|
TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
|
||||||
|
|
||||||
|
New timer implemenation in ticks.c, which is used in LFOPS.c
|
||||||
|
1us = 1.5ticks
|
||||||
|
1fc = 8us = 12ticks
|
||||||
|
|
||||||
|
Terms you find in different datasheets and how they match.
|
||||||
|
1 Cycle = 8 microseconds(us) == 1 field clock (fc)
|
||||||
|
|
||||||
|
Note about HITAG timing
|
||||||
|
Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier)
|
||||||
|
T0 = TIMER_CLOCK1 / 125000 = 192
|
||||||
|
|
||||||
|
|
||||||
// new timer:
|
|
||||||
// = 1us = 1.5ticks
|
|
||||||
// 1fc = 8us = 12ticks
|
|
||||||
/*
|
|
||||||
==========================================================================================================
|
==========================================================================================================
|
||||||
T55x7 Timing
|
T55x7 Timing
|
||||||
==========================================================================================================
|
==========================================================================================================
|
||||||
|
|
||||||
// t55xx_config t_config = { 29 * 8, 17 * 8, 15 * 8, 47 * 8, 15 * 8 } ;
|
|
||||||
|
|
||||||
ATA5577 Downlink Protocol Timings.
|
ATA5577 Downlink Protocol Timings.
|
||||||
Note: All absolute times assume TC = 1 / fC = 8 μs (fC = 125 kHz)
|
Note: All absolute times assume TC = 1 / fC = 8 μs (fC = 125 kHz)
|
||||||
|
|
||||||
|
Note: These timings are from the datasheet and doesn't map the best to the features of the RVD4 LF antenna.
|
||||||
|
RDV4 LF antenna has high voltage and the drop of power when turning off the rf field takes about 1-2 TC longer.
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
Fixed-bit-length Protocol | Normal Downlink | Fast Downlink |
|
Fixed-bit-length Protocol | Normal Downlink | Fast Downlink |
|
||||||
------------------------------+-----------------------------------+-----------------------------------+------
|
------------------------------+-----------------------------------+-----------------------------------+------
|
||||||
|
@ -110,21 +127,23 @@
|
||||||
| |10 data | d10 | dref + 25 | dref + 32 | dref + 40 | dref + 13 | dref + 16 | dref + 20 | Tc |
|
| |10 data | d10 | dref + 25 | dref + 32 | dref + 40 | dref + 13 | dref + 16 | dref + 20 | Tc |
|
||||||
| |11 data | d11 | dref + 41 | dref + 48 | dref + 56 | dref + 21 | dref + 24 | dref + 28 | Tc |
|
| |11 data | d11 | dref + 41 | dref + 48 | dref + 56 | dref + 21 | dref + 24 | dref + 28 | Tc |
|
||||||
-------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------
|
||||||
*/
|
|
||||||
// Initial values if not in flash
|
Initial values if not in flash
|
||||||
/*
|
|
||||||
// Note: Moved * 8 to apply when used. Saving 28 bytes here (- the *8) and 28 bytes flash.
|
SG = Start gap
|
||||||
// StartGap WriteGap Bit 0/00 Bit 1/01 Bit 10 Bit 11 ReadGap
|
WG = Write gap
|
||||||
t55xx_config T55xx_Timing = {{
|
RG = Read gap
|
||||||
|
|
||||||
|
Explainations for array T55xx_Timing below
|
||||||
|
SG WG Bit 0/00 Bit 1/01 Bit 10 Bit 11 RG
|
||||||
|
--------------------------------------------------------------------
|
||||||
{ 29 , 17 , 15 , 47 , 0 , 0 , 15 }, // Default Fixed
|
{ 29 , 17 , 15 , 47 , 0 , 0 , 15 }, // Default Fixed
|
||||||
{ 31 , 20 , 18 , 50 , 0 , 0 , 15 }, // Long Leading Ref.
|
{ 31 , 20 , 18 , 50 , 0 , 0 , 15 }, // Long Leading Ref.
|
||||||
{ 31 , 20 , 18 , 40 , 0 , 0 , 15 }, // Leading 0
|
{ 31 , 20 , 18 , 40 , 0 , 0 , 15 }, // Leading 0
|
||||||
{ 29 , 17 , 15 , 31 , 47 , 63 , 15 } // 1 of 4
|
{ 29 , 17 , 15 , 31 , 47 , 63 , 15 } // 1 of 4
|
||||||
}
|
|
||||||
};
|
|
||||||
*/
|
*/
|
||||||
// StartGap WriteGap Bit 0/00 Bit 1/01 ReadGap Bit 10 Bit 11
|
t55xx_configurations_t T55xx_Timing = {
|
||||||
t55xx_config T55xx_Timing = {{
|
{
|
||||||
{ 29 * 8, 17 * 8, 15 * 8, 47 * 8, 15 * 8, 0, 0 }, // Default Fixed
|
{ 29 * 8, 17 * 8, 15 * 8, 47 * 8, 15 * 8, 0, 0 }, // Default Fixed
|
||||||
{ 31 * 8, 20 * 8, 18 * 8, 50 * 8, 15 * 8, 0, 0 }, // Long Leading Ref.
|
{ 31 * 8, 20 * 8, 18 * 8, 50 * 8, 15 * 8, 0, 0 }, // Long Leading Ref.
|
||||||
{ 31 * 8, 20 * 8, 18 * 8, 40 * 8, 15 * 8, 0, 0 }, // Leading 0
|
{ 31 * 8, 20 * 8, 18 * 8, 40 * 8, 15 * 8, 0, 0 }, // Leading 0
|
||||||
|
@ -134,61 +153,136 @@ t55xx_config T55xx_Timing = {{
|
||||||
|
|
||||||
|
|
||||||
// Some defines for readability
|
// Some defines for readability
|
||||||
#define T55xx_DLMode_Fixed 0 // Default Mode
|
#define T55XX_DLMODE_FIXED 0 // Default Mode
|
||||||
#define T55xx_DLMode_LLR 1 // Long Leading Reference
|
#define T55XX_DLMODE_LLR 1 // Long Leading Reference
|
||||||
#define T55xx_DLMode_Leading0 2 // Leading Zero
|
#define T55XX_DLMODE_LEADING_ZERO 2 // Leading Zero
|
||||||
#define T55xx_DLMode_1of4 3 // 1 of 4
|
#define T55XX_DLMODE_1OF4 3 // 1 of 4
|
||||||
#define T55xx_LongLeadingReference 4 // Value to tell Write Bit to send long reference
|
#define T55XX_LONGLEADINGREFERENCE 4 // Value to tell Write Bit to send long reference
|
||||||
|
|
||||||
void printT55xxConfig(void) {
|
// ATA55xx shared presets & routines
|
||||||
int DLMode;
|
static uint32_t GetT55xxClockBit(uint32_t clock) {
|
||||||
|
switch (clock) {
|
||||||
DbpString(_BLUE_("LF T55XX config"));
|
case 128:
|
||||||
for (DLMode = 0; DLMode < 4; DLMode++) {
|
return T55x7_BITRATE_RF_128;
|
||||||
switch (DLMode) {
|
case 100:
|
||||||
case T55xx_DLMode_Fixed :
|
return T55x7_BITRATE_RF_100;
|
||||||
Dbprintf("r 0 fixed bit length (default)");
|
case 64:
|
||||||
break;
|
return T55x7_BITRATE_RF_64;
|
||||||
case T55xx_DLMode_LLR :
|
case 50:
|
||||||
Dbprintf("r 1 long leading reference");
|
return T55x7_BITRATE_RF_50;
|
||||||
break;
|
case 40:
|
||||||
case T55xx_DLMode_Leading0 :
|
return T55x7_BITRATE_RF_40;
|
||||||
Dbprintf("r 2 leading zero");
|
case 32:
|
||||||
break;
|
return T55x7_BITRATE_RF_32;
|
||||||
case T55xx_DLMode_1of4 :
|
case 16:
|
||||||
Dbprintf("r 3 1 of 4 coding reference");
|
return T55x7_BITRATE_RF_16;
|
||||||
break;
|
case 8:
|
||||||
}
|
return T55x7_BITRATE_RF_8;
|
||||||
Dbprintf(" [a] startgap............%d*8 (%d)", T55xx_Timing.m[DLMode].start_gap / 8, T55xx_Timing.m[DLMode].start_gap);
|
default :
|
||||||
Dbprintf(" [b] writegap............%d*8 (%d)", T55xx_Timing.m[DLMode].write_gap / 8, T55xx_Timing.m[DLMode].write_gap);
|
return 0;
|
||||||
Dbprintf(" [c] write_0.............%d*8 (%d)", T55xx_Timing.m[DLMode].write_0 / 8, T55xx_Timing.m[DLMode].write_0);
|
|
||||||
Dbprintf(" [d] write_1.............%d*8 (%d)", T55xx_Timing.m[DLMode].write_1 / 8, T55xx_Timing.m[DLMode].write_1);
|
|
||||||
Dbprintf(" [e] readgap.............%d*8 (%d)", T55xx_Timing.m[DLMode].read_gap / 8, T55xx_Timing.m[DLMode].read_gap);
|
|
||||||
if (DLMode == T55xx_DLMode_1of4) {
|
|
||||||
Dbprintf(" [f] write_2.............%d*8 (%d)", T55xx_Timing.m[DLMode].write_2 / 8, T55xx_Timing.m[DLMode].write_2);
|
|
||||||
Dbprintf(" [g] write_3.............%d*8 (%d)", T55xx_Timing.m[DLMode].write_3 / 8, T55xx_Timing.m[DLMode].write_3);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setT55xxConfig(uint8_t arg0, t55xx_config *c) {
|
void printT55xxConfig(void) {
|
||||||
uint8_t DLMode;
|
|
||||||
// uint8_t ClearT55Settings = c->m[0].start_gap & 0xffff; // all values will be ffff if clear requested
|
|
||||||
|
|
||||||
|
#define PRN_NA sprintf(s + strlen(s), _RED_("N/A") "| ");
|
||||||
|
|
||||||
for (DLMode = 0; DLMode < 4; DLMode++) {
|
DbpString(_BLUE_("LF T55XX config"));
|
||||||
if (c->m[DLMode].start_gap != 0) T55xx_Timing.m[DLMode].start_gap = c->m[DLMode].start_gap;// * 8;
|
Dbprintf(" [r] [a] [b] [c] [d] [e] [f] [g]");
|
||||||
if (c->m[DLMode].write_gap != 0) T55xx_Timing.m[DLMode].write_gap = c->m[DLMode].write_gap;// * 8;
|
Dbprintf(" mode |start|write|write|write| read|write|write");
|
||||||
if (c->m[DLMode].write_0 != 0) T55xx_Timing.m[DLMode].write_0 = c->m[DLMode].write_0 ;// * 8;
|
Dbprintf(" | gap | gap | 0 | 1 | gap | 2 | 3");
|
||||||
if (c->m[DLMode].write_1 != 0) T55xx_Timing.m[DLMode].write_1 = c->m[DLMode].write_1 ;// * 8;
|
Dbprintf("---------------------------+-----+-----+-----+-----+-----+-----+------");
|
||||||
if (DLMode == T55xx_DLMode_1of4) {
|
|
||||||
if (c->m[DLMode].write_2 != 0) T55xx_Timing.m[DLMode].write_2 = c->m[DLMode].write_2;// * 8;
|
for (uint8_t i = 0; i < 4; i++) {
|
||||||
if (c->m[DLMode].write_3 != 0) T55xx_Timing.m[DLMode].write_3 = c->m[DLMode].write_3;// * 8 ;
|
|
||||||
} else {
|
char s[160];
|
||||||
T55xx_Timing.m[DLMode].write_2 = 0x00;
|
memset(s, 0, sizeof(s));
|
||||||
T55xx_Timing.m[DLMode].write_3 = 0x00;
|
|
||||||
|
switch (i) {
|
||||||
|
case T55XX_DLMODE_FIXED :
|
||||||
|
sprintf(s, _YELLOW_("fixed bit length") _GREEN_("(default)") "|");
|
||||||
|
break;
|
||||||
|
case T55XX_DLMODE_LLR :
|
||||||
|
sprintf(s, _YELLOW_(" long leading reference") "|");
|
||||||
|
break;
|
||||||
|
case T55XX_DLMODE_LEADING_ZERO :
|
||||||
|
sprintf(s, _YELLOW_(" leading zero") "|");
|
||||||
|
break;
|
||||||
|
case T55XX_DLMODE_1OF4 :
|
||||||
|
sprintf(s, _YELLOW_(" 1 of 4 coding reference") "|");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (c->m[DLMode].read_gap != 0) T55xx_Timing.m[DLMode].read_gap = c->m[DLMode].read_gap;//* 8;
|
|
||||||
|
if (T55xx_Timing.m[i].start_gap != 0xFFFF)
|
||||||
|
sprintf(s + strlen(s), " %3d | ", T55xx_Timing.m[i].start_gap / 8);
|
||||||
|
else
|
||||||
|
PRN_NA;
|
||||||
|
|
||||||
|
if (T55xx_Timing.m[i].write_gap != 0xFFFF)
|
||||||
|
sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].write_gap / 8);
|
||||||
|
else
|
||||||
|
PRN_NA;
|
||||||
|
|
||||||
|
if (T55xx_Timing.m[i].write_0 != 0xFFFF)
|
||||||
|
sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].write_0 / 8);
|
||||||
|
else
|
||||||
|
PRN_NA;
|
||||||
|
|
||||||
|
if (T55xx_Timing.m[i].write_1 != 0xFFFF)
|
||||||
|
sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].write_1 / 8);
|
||||||
|
else
|
||||||
|
PRN_NA;
|
||||||
|
|
||||||
|
if (T55xx_Timing.m[i].read_gap != 0xFFFF)
|
||||||
|
sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].read_gap / 8);
|
||||||
|
else
|
||||||
|
PRN_NA;
|
||||||
|
|
||||||
|
if (T55xx_Timing.m[i].write_2 != 0xFFFF && i == T55XX_DLMODE_1OF4)
|
||||||
|
sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].write_2 / 8);
|
||||||
|
else
|
||||||
|
PRN_NA
|
||||||
|
|
||||||
|
if (T55xx_Timing.m[i].write_3 != 0xFFFF && i == T55XX_DLMODE_1OF4)
|
||||||
|
sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].write_3 / 8);
|
||||||
|
else
|
||||||
|
PRN_NA;
|
||||||
|
|
||||||
|
s[strlen(s)] = 0;
|
||||||
|
DbpString(s);
|
||||||
|
}
|
||||||
|
DbpString("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setT55xxConfig(uint8_t arg0, t55xx_configurations_t *c) {
|
||||||
|
for (uint8_t i = 0; i < 4; i++) {
|
||||||
|
if (c->m[i].start_gap != 0)
|
||||||
|
T55xx_Timing.m[i].start_gap = c->m[i].start_gap;
|
||||||
|
|
||||||
|
if (c->m[i].write_gap != 0)
|
||||||
|
T55xx_Timing.m[i].write_gap = c->m[i].write_gap;
|
||||||
|
|
||||||
|
if (c->m[i].write_0 != 0)
|
||||||
|
T55xx_Timing.m[i].write_0 = c->m[i].write_0;
|
||||||
|
|
||||||
|
if (c->m[i].write_1 != 0)
|
||||||
|
T55xx_Timing.m[i].write_1 = c->m[i].write_1;
|
||||||
|
|
||||||
|
if (i == T55XX_DLMODE_1OF4) {
|
||||||
|
if (c->m[i].write_2 != 0)
|
||||||
|
T55xx_Timing.m[i].write_2 = c->m[i].write_2;
|
||||||
|
|
||||||
|
if (c->m[i].write_3 != 0)
|
||||||
|
T55xx_Timing.m[i].write_3 = c->m[i].write_3;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
T55xx_Timing.m[i].write_2 = 0x00;
|
||||||
|
T55xx_Timing.m[i].write_3 = 0x00;
|
||||||
|
}
|
||||||
|
if (c->m[i].read_gap != 0)
|
||||||
|
T55xx_Timing.m[i].read_gap = c->m[i].read_gap;
|
||||||
}
|
}
|
||||||
|
|
||||||
printT55xxConfig();
|
printT55xxConfig();
|
||||||
|
@ -203,7 +297,6 @@ void setT55xxConfig(uint8_t arg0, t55xx_config *c) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t *buf = BigBuf_malloc(T55XX_CONFIG_LEN);
|
uint8_t *buf = BigBuf_malloc(T55XX_CONFIG_LEN);
|
||||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||||
uint16_t res = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN);
|
uint16_t res = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN);
|
||||||
|
@ -215,21 +308,23 @@ void setT55xxConfig(uint8_t arg0, t55xx_config *c) {
|
||||||
|
|
||||||
memcpy(buf, &T55xx_Timing, T55XX_CONFIG_LEN);
|
memcpy(buf, &T55xx_Timing, T55XX_CONFIG_LEN);
|
||||||
|
|
||||||
|
// delete old configuration
|
||||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||||
Flash_WriteEnable();
|
Flash_WriteEnable();
|
||||||
Flash_Erase4k(3, 0xD);
|
Flash_Erase4k(3, 0xD);
|
||||||
|
|
||||||
|
// write new
|
||||||
res = Flash_Write(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN);
|
res = Flash_Write(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN);
|
||||||
|
|
||||||
if (res == T55XX_CONFIG_LEN && DBGLEVEL > 1) {
|
if (res == T55XX_CONFIG_LEN && DBGLEVEL > 1) {
|
||||||
DbpString("T55XX Config save success");
|
DbpString("T55XX Config save " _GREEN_("success"));
|
||||||
}
|
}
|
||||||
|
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
t55xx_config *getT55xxConfig(void) {
|
t55xx_configurations_t *getT55xxConfig(void) {
|
||||||
return &T55xx_Timing;//_FixedBit;
|
return &T55xx_Timing;//_FixedBit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,7 +403,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint
|
||||||
}
|
}
|
||||||
|
|
||||||
// hack2 needed--- it appears to take about 8-16us to turn the antenna back on
|
// hack2 needed--- it appears to take about 8-16us to turn the antenna back on
|
||||||
// leading to ~ 1 to 2 125khz samples extra in every off period
|
// leading to ~ 1 to 2 125kHz samples extra in every off period
|
||||||
// so we should test for last 0 before next 1 and reduce period_0 by this extra amount...
|
// so we should test for last 0 before next 1 and reduce period_0 by this extra amount...
|
||||||
// but is this time different for every antenna or other hw builds??? more testing needed
|
// but is this time different for every antenna or other hw builds??? more testing needed
|
||||||
|
|
||||||
|
@ -366,7 +461,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint
|
||||||
// Turn off antenna
|
// Turn off antenna
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
// tell client we are done
|
// tell client we are done
|
||||||
reply_ng(CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K, PM3_SUCCESS, NULL, 0);
|
reply_ng(CMD_LF_MOD_THEN_ACQ_RAW_ADC, PM3_SUCCESS, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* blank r/w tag data stream
|
/* blank r/w tag data stream
|
||||||
|
@ -381,9 +476,9 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint
|
||||||
void ReadTItag(void) {
|
void ReadTItag(void) {
|
||||||
StartTicks();
|
StartTicks();
|
||||||
// some hardcoded initial params
|
// some hardcoded initial params
|
||||||
// when we read a TI tag we sample the zerocross line at 2Mhz
|
// when we read a TI tag we sample the zerocross line at 2MHz
|
||||||
// TI tags modulate a 1 as 16 cycles of 123.2Khz
|
// TI tags modulate a 1 as 16 cycles of 123.2kHz
|
||||||
// TI tags modulate a 0 as 16 cycles of 134.2Khz
|
// TI tags modulate a 0 as 16 cycles of 134.2kHz
|
||||||
#define FSAMPLE 2000000
|
#define FSAMPLE 2000000
|
||||||
#define FREQLO 123200
|
#define FREQLO 123200
|
||||||
#define FREQHI 134200
|
#define FREQHI 134200
|
||||||
|
@ -399,9 +494,9 @@ void ReadTItag(void) {
|
||||||
// when to tell if we're close enough to one freq or another
|
// when to tell if we're close enough to one freq or another
|
||||||
uint32_t threshold = (sampleslo - sampleshi + 1) >> 1;
|
uint32_t threshold = (sampleslo - sampleshi + 1) >> 1;
|
||||||
|
|
||||||
// TI tags charge at 134.2Khz
|
// TI tags charge at 134.2kHz
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8kHz
|
||||||
|
|
||||||
// Place FPGA in passthrough mode, in this mode the CROSS_LO line
|
// Place FPGA in passthrough mode, in this mode the CROSS_LO line
|
||||||
// connects to SSP_DIN and the SSP_DOUT logic level controls
|
// connects to SSP_DIN and the SSP_DOUT logic level controls
|
||||||
|
@ -627,8 +722,8 @@ void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc) {
|
||||||
}
|
}
|
||||||
Dbprintf("Writing to tag: %x%08x, crc=%x", idhi, idlo, crc);
|
Dbprintf("Writing to tag: %x%08x, crc=%x", idhi, idlo, crc);
|
||||||
|
|
||||||
// TI tags charge at 134.2Khz
|
// TI tags charge at 134.2kHz
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8kHz
|
||||||
// Place FPGA in passthrough mode, in this mode the CROSS_LO line
|
// Place FPGA in passthrough mode, in this mode the CROSS_LO line
|
||||||
// connects to SSP_DIN and the SSP_DOUT logic level controls
|
// connects to SSP_DIN and the SSP_DOUT logic level controls
|
||||||
// whether we're modulating the antenna (high)
|
// whether we're modulating the antenna (high)
|
||||||
|
@ -701,9 +796,9 @@ void SimulateTagLowFrequencyEx(int period, int gap, bool ledcontrol, int numcycl
|
||||||
sample_config *sc = getSamplingConfig();
|
sample_config *sc = getSamplingConfig();
|
||||||
|
|
||||||
if ((sc->divisor == 1) || (sc->divisor < 0) || (sc->divisor > 255))
|
if ((sc->divisor == 1) || (sc->divisor < 0) || (sc->divisor > 255))
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8kHz
|
||||||
else if (sc->divisor == 0)
|
else if (sc->divisor == 0)
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz
|
||||||
else
|
else
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor);
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor);
|
||||||
|
|
||||||
|
@ -946,7 +1041,7 @@ void CmdHIDsimTAGEx(uint32_t hi, uint32_t lo, bool ledcontrol, int numcycles) {
|
||||||
|
|
||||||
void CmdHIDsimTAG(uint32_t hi, uint32_t lo, bool ledcontrol) {
|
void CmdHIDsimTAG(uint32_t hi, uint32_t lo, bool ledcontrol) {
|
||||||
CmdHIDsimTAGEx(hi, lo, ledcontrol, -1);
|
CmdHIDsimTAGEx(hi, lo, ledcontrol, -1);
|
||||||
reply_ng(CMD_HID_SIM_TAG, PM3_EOPABORTED, NULL, 0);
|
reply_ng(CMD_LF_HID_SIMULATE, PM3_EOPABORTED, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare a waveform pattern in the buffer based on the ID given then
|
// prepare a waveform pattern in the buffer based on the ID given then
|
||||||
|
@ -984,7 +1079,7 @@ void CmdFSKsimTAG(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk,
|
||||||
if (ledcontrol) LED_A_ON();
|
if (ledcontrol) LED_A_ON();
|
||||||
SimulateTagLowFrequency(n, 0, ledcontrol);
|
SimulateTagLowFrequency(n, 0, ledcontrol);
|
||||||
if (ledcontrol) LED_A_OFF();
|
if (ledcontrol) LED_A_OFF();
|
||||||
reply_ng(CMD_FSK_SIM_TAG, PM3_EOPABORTED, NULL, 0);
|
reply_ng(CMD_LF_FSK_SIMULATE, PM3_EOPABORTED, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// compose ask waveform for one bit(ASK)
|
// compose ask waveform for one bit(ASK)
|
||||||
|
@ -1073,7 +1168,7 @@ void CmdASKsimTAG(uint8_t encoding, uint8_t invert, uint8_t separator, uint8_t c
|
||||||
if (ledcontrol) LED_A_ON();
|
if (ledcontrol) LED_A_ON();
|
||||||
SimulateTagLowFrequency(n, 0, ledcontrol);
|
SimulateTagLowFrequency(n, 0, ledcontrol);
|
||||||
if (ledcontrol) LED_A_OFF();
|
if (ledcontrol) LED_A_OFF();
|
||||||
reply_ng(CMD_ASK_SIM_TAG, PM3_EOPABORTED, NULL, 0);
|
reply_ng(CMD_LF_ASK_SIMULATE, PM3_EOPABORTED, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//carrier can be 2,4 or 8
|
//carrier can be 2,4 or 8
|
||||||
|
@ -1120,7 +1215,7 @@ void CmdPSKsimTag(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, u
|
||||||
if (ledcontrol) LED_A_ON();
|
if (ledcontrol) LED_A_ON();
|
||||||
SimulateTagLowFrequency(n, 0, ledcontrol);
|
SimulateTagLowFrequency(n, 0, ledcontrol);
|
||||||
if (ledcontrol) LED_A_OFF();
|
if (ledcontrol) LED_A_OFF();
|
||||||
reply_ng(CMD_PSK_SIM_TAG, PM3_EOPABORTED, NULL, 0);
|
reply_ng(CMD_LF_PSK_SIMULATE, PM3_EOPABORTED, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop to get raw HID waveform then FSK demodulate the TAG ID from it
|
// loop to get raw HID waveform then FSK demodulate the TAG ID from it
|
||||||
|
@ -1129,7 +1224,7 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol)
|
||||||
size_t size;
|
size_t size;
|
||||||
uint32_t hi2 = 0, hi = 0, lo = 0;
|
uint32_t hi2 = 0, hi = 0, lo = 0;
|
||||||
int dummyIdx = 0;
|
int dummyIdx = 0;
|
||||||
// Configure to go in 125Khz listen mode
|
// Configure to go in 125kHz listen mode
|
||||||
LFSetupFPGAForADC(95, true);
|
LFSetupFPGAForADC(95, true);
|
||||||
|
|
||||||
//clear read buffer
|
//clear read buffer
|
||||||
|
@ -1380,7 +1475,7 @@ void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) {
|
||||||
|
|
||||||
BigBuf_Clear_keep_EM();
|
BigBuf_Clear_keep_EM();
|
||||||
|
|
||||||
// Configure to go in 125Khz listen mode
|
// Configure to go in 125kHz listen mode
|
||||||
LFSetupFPGAForADC(95, true);
|
LFSetupFPGAForADC(95, true);
|
||||||
|
|
||||||
while (!BUTTON_PRESS() && !data_available()) {
|
while (!BUTTON_PRESS() && !data_available()) {
|
||||||
|
@ -1478,37 +1573,35 @@ void TurnReadLF_off(uint32_t delay) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Macro for code readability
|
// Macro for code readability
|
||||||
#define BitStream_Byte(X) ((X) >> 3)
|
#define BITSTREAM_BYTE(x) ((x) >> 3) // iceman note: isn't this NIBBLE???
|
||||||
#define BitStream_Bit(X) ((X) & 7)
|
#define BITSTREAM_BIT(x) ((x) & 7)
|
||||||
#define t55_llr_ref (136 * 8)
|
|
||||||
#define t55_send_PwdMode (arg & 0x01)
|
#define T55_LLR_REF (136 * 8)
|
||||||
#define t55_send_Page ((arg & 0x02) >> 1)
|
|
||||||
#define t55_send_TestMode ((arg & 0x04) >> 2)
|
|
||||||
#define t55_send_RegReadMode ((arg & 0x20) >> 5)
|
|
||||||
#define t55_send_ReadCmd ((arg & 0x40) >> 6)
|
|
||||||
#define t55_send_Reset ((arg & 0x80) >> 7)
|
|
||||||
|
|
||||||
// Write one bit to chip
|
// Write one bit to chip
|
||||||
void T55xxWriteBit(uint8_t bit, uint8_t downlink_idx) {
|
void T55xxWriteBit(uint8_t bit, uint8_t downlink_idx) {
|
||||||
|
|
||||||
// Dbprintf ("%d",bit);
|
|
||||||
// If bit = 4 Send Long Leading Reference which is (138*8) + WRITE_0
|
|
||||||
switch (bit) {
|
switch (bit) {
|
||||||
case 0 :
|
case 0 :
|
||||||
|
// send bit 0/00
|
||||||
TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_0);
|
TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_0);
|
||||||
break; // Send bit 0/00
|
break;
|
||||||
case 1 :
|
case 1 :
|
||||||
|
// send bit 1/01
|
||||||
TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_1);
|
TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_1);
|
||||||
break; // Send bit 1/01
|
break;
|
||||||
case 2 :
|
case 2 :
|
||||||
|
// send bits 10 (1 of 4)
|
||||||
TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_2);
|
TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_2);
|
||||||
break; // Send bits 10 (1 of 4)
|
break;
|
||||||
case 3 :
|
case 3 :
|
||||||
|
// send bits 11 (1 of 4)
|
||||||
TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_3);
|
TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_3);
|
||||||
break; // Send bits 11 (1 of 4)
|
break;
|
||||||
case 4 :
|
case 4 :
|
||||||
TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_0 + t55_llr_ref);
|
// send Long Leading Reference
|
||||||
break; // Send Long Leading Reference
|
TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_0 + T55_LLR_REF);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
@ -1522,94 +1615,110 @@ void T55xxWriteBit(uint8_t bit, uint8_t downlink_idx) {
|
||||||
// num_bits - how many bits (low x bits of data) Max 32 bits at a time
|
// num_bits - how many bits (low x bits of data) Max 32 bits at a time
|
||||||
// max_len - how many bytes can the bit_array hold (ensure no buffer overflow)
|
// max_len - how many bytes can the bit_array hold (ensure no buffer overflow)
|
||||||
// returns "Next" bit offset / bits stored (for next store)
|
// returns "Next" bit offset / bits stored (for next store)
|
||||||
uint8_t T55xx_SetBits(uint8_t *BitStream, uint8_t start_offset, uint32_t data, uint8_t num_bits, uint8_t max_len) {
|
uint8_t T55xx_SetBits(uint8_t *bs, uint8_t start_offset, uint32_t data, uint8_t num_bits, uint8_t max_len) {
|
||||||
int8_t offset;
|
int8_t offset;
|
||||||
int8_t NextOffset = start_offset;
|
int8_t next_offset = start_offset;
|
||||||
|
|
||||||
// Check if data will fit.
|
// Check if data will fit.
|
||||||
if ((start_offset + num_bits) <= (max_len * 8)) {
|
if ((start_offset + num_bits) <= (max_len * 8)) {
|
||||||
// Loop through the data and store
|
// Loop through the data and store
|
||||||
for (offset = (num_bits - 1); offset >= 0; offset--) {
|
for (offset = (num_bits - 1); offset >= 0; offset--) {
|
||||||
|
|
||||||
if ((data >> offset) & 1) BitStream[BitStream_Byte(NextOffset)] |= (1 << BitStream_Bit(NextOffset)); // Set the bit to 1
|
if ((data >> offset) & 1)
|
||||||
else BitStream[BitStream_Byte(NextOffset)] &= (0xff ^ (1 << BitStream_Bit(NextOffset))); // Set the bit to 0
|
bs[BITSTREAM_BYTE(next_offset)] |= (1 << BITSTREAM_BIT(next_offset)); // Set 1
|
||||||
|
else
|
||||||
|
bs[BITSTREAM_BYTE(next_offset)] &= (0xff ^ (1 << BITSTREAM_BIT(next_offset))); // Set 0
|
||||||
|
|
||||||
NextOffset++;
|
next_offset++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Note: This should never happen unless some code changes cause it.
|
// Note: This should never happen unless some code changes cause it.
|
||||||
// So short message for coders when testing.
|
// So short message for coders when testing.
|
||||||
Dbprintf("T55 too many bits");
|
Dbprintf(_RED_("T55 too many bits"));
|
||||||
}
|
}
|
||||||
return NextOffset;
|
return next_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send one downlink command to the card
|
// Send one downlink command to the card
|
||||||
// void T55xx_SendCMD (uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) {
|
void T55xx_SendCMD(uint32_t data, uint32_t pwd, uint16_t arg) {
|
||||||
void T55xx_SendCMD(uint32_t Data, uint32_t Pwd, uint16_t arg) {
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
arg bits
|
arg bits
|
||||||
xxxx xxxxxxx1 0x001 PwdMode
|
xxxx xxxxxxx1 0x001 password mode (Y/N)
|
||||||
xxxx xxxxxx1x 0x002 Page
|
xxxx xxxxxx1x 0x002 page (0|1)
|
||||||
xxxx xxxxx1xx 0x004 testMode
|
xxxx xxxxx1xx 0x004 test mode (Y/N)
|
||||||
xxxx xxx11xxx 0x018 downlink mode
|
xxxx xxx11xxx 0x018 selected downlink mode (0|1|2|3|)
|
||||||
xxxx xx1xxxxx 0x020 !reg_readmode
|
xxxx xx1xxxxx 0x020 !reg_readmode (ICEMAN ?? Why use negative in the bool ??)
|
||||||
xxxx x1xxxxxx 0x040 called for a read, so no data packet
|
xxxx x1xxxxxx 0x040 called for a read, so no data packet (Y/N)
|
||||||
xxxx 1xxxxxxx 0x080 reset
|
xxxx 1xxxxxxx 0x080 reset (Y/N)
|
||||||
xxx1 xxxxxxxx 0x100 brute force
|
xxx1 xxxxxxxx 0x100 brute force (Y/N)
|
||||||
111x xxxxxxxx 0xE00 Block
|
111x xxxxxxxx 0xE00 block to write (0-7)
|
||||||
*/
|
*/
|
||||||
|
bool t55_send_pwdmode = (arg & 0x1);
|
||||||
|
bool t55_send_page = ((arg >> 1) & 0x1);
|
||||||
|
bool t55_send_testmode = ((arg >> 2) & 0x1);
|
||||||
|
bool t55_send_regreadmode = ((arg >> 5) & 0x1);
|
||||||
|
bool t55_send_readcmd = ((arg >> 6) & 0x1);
|
||||||
|
bool t55_send_reset = ((arg >> 7) & 0x1);
|
||||||
|
bool t55_brute_mem = ((arg >> 8) & 0x1);
|
||||||
|
|
||||||
uint8_t downlink_mode = (arg >> 3) & 0x03;
|
uint8_t downlink_mode = (arg >> 3) & 0x03;
|
||||||
uint8_t i = 0;
|
uint8_t block_no = (arg >> 9) & 0x07;
|
||||||
uint8_t BitStream[10]; // Max Downlink Command size ~74 bits, so 10 bytes (80 bits)
|
|
||||||
uint8_t BitStreamLen = 0;
|
|
||||||
uint8_t SendBits;
|
|
||||||
uint8_t start_wait = 4;
|
|
||||||
bool brute_mem = (arg & 0x100);
|
|
||||||
uint8_t Block = (arg >> 9) & 0x07;
|
|
||||||
|
|
||||||
if (brute_mem) start_wait = 0;
|
// no startup delay when in bruteforce command
|
||||||
|
uint8_t start_wait = (t55_brute_mem) ? 0 : 4;
|
||||||
|
|
||||||
// Build Bit Stream to send.
|
// Max Downlink Command size ~74 bits, so 10 bytes (80 bits)
|
||||||
memset(BitStream, 0x00, sizeof(BitStream));
|
uint8_t bs[10];
|
||||||
|
memset(bs, 0x00, sizeof(bs));
|
||||||
|
|
||||||
BitStreamLen = 0; // Ensure 0 bit index to start.
|
uint8_t len = 0;
|
||||||
|
|
||||||
// Add Leading 0 and 1 of 4 reference bit
|
// build bit stream to send.
|
||||||
if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4))
|
|
||||||
BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, 0, 1, sizeof(BitStream));
|
|
||||||
|
|
||||||
// Add extra reference 0 for 1 of 4
|
// add Leading 0
|
||||||
if (downlink_mode == T55xx_DLMode_1of4)
|
if (downlink_mode == T55XX_DLMODE_LEADING_ZERO)
|
||||||
BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, 0, 1, sizeof(BitStream));
|
len = T55xx_SetBits(bs, len, 0, 1, sizeof(bs));
|
||||||
|
|
||||||
// Add Opcode
|
// add 1 of 4 reference bit
|
||||||
if (t55_send_Reset) {
|
if (downlink_mode == T55XX_DLMODE_1OF4) {
|
||||||
// Reset : r*) 00
|
len = T55xx_SetBits(bs, len, 0, 1, sizeof(bs));
|
||||||
BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, 0, 2, sizeof(BitStream));
|
// add extra zero
|
||||||
|
len = T55xx_SetBits(bs, len, 0, 1, sizeof(bs));
|
||||||
|
}
|
||||||
|
|
||||||
|
// add Opcode
|
||||||
|
if (t55_send_reset) {
|
||||||
|
// reset : r*) 00
|
||||||
|
len = T55xx_SetBits(bs, len, 0, 2, sizeof(bs));
|
||||||
} else {
|
} else {
|
||||||
if (t55_send_TestMode) Dbprintf("TestMODE");
|
|
||||||
BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, t55_send_TestMode ? 0 : 1, 1, sizeof(BitStream));
|
if (t55_send_testmode)
|
||||||
BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, t55_send_TestMode ? 1 : t55_send_Page, 1, sizeof(BitStream));
|
Dbprintf(_YELLOW_("Using Test Mode"));
|
||||||
//if (PwdMode) {
|
|
||||||
if (t55_send_PwdMode) {
|
len = T55xx_SetBits(bs, len, t55_send_testmode ? 0 : 1, 1, sizeof(bs));
|
||||||
|
|
||||||
|
len = T55xx_SetBits(bs, len, t55_send_testmode ? 1 : t55_send_page, 1, sizeof(bs));
|
||||||
|
|
||||||
|
if (t55_send_pwdmode) {
|
||||||
// Leading 0 and 1 of 4 00 fixed bits if passsword used
|
// Leading 0 and 1 of 4 00 fixed bits if passsword used
|
||||||
if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) {
|
if ((downlink_mode == T55XX_DLMODE_LEADING_ZERO) || (downlink_mode == T55XX_DLMODE_1OF4)) {
|
||||||
BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, 0, 2, sizeof(BitStream));
|
len = T55xx_SetBits(bs, len, 0, 2, sizeof(bs));
|
||||||
}
|
}
|
||||||
BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, Pwd, 32, sizeof(BitStream));
|
len = T55xx_SetBits(bs, len, pwd, 32, sizeof(bs));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add Lock bit 0
|
// Add Lock bit 0
|
||||||
if (!t55_send_RegReadMode) BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, 0, 1, sizeof(BitStream));
|
if (t55_send_regreadmode == false)
|
||||||
|
len = T55xx_SetBits(bs, len, 0, 1, sizeof(bs));
|
||||||
|
|
||||||
// Add Data if a write command
|
// Add Data if a write command
|
||||||
if (!t55_send_ReadCmd) BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, Data, 32, sizeof(BitStream));
|
if (t55_send_readcmd == false)
|
||||||
|
len = T55xx_SetBits(bs, len, data, 32, sizeof(bs));
|
||||||
|
|
||||||
// Add Address
|
// Add Address
|
||||||
if (!t55_send_RegReadMode) BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, Block, 3, sizeof(BitStream));
|
if (t55_send_regreadmode == false)
|
||||||
|
len = T55xx_SetBits(bs, len, block_no, 3, sizeof(bs));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send Bits to T55xx
|
// Send Bits to T55xx
|
||||||
|
@ -1621,22 +1730,23 @@ void T55xx_SendCMD(uint32_t Data, uint32_t Pwd, uint16_t arg) {
|
||||||
|
|
||||||
// Trigger T55x7 in mode.
|
// Trigger T55x7 in mode.
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
WaitUS(T55xx_Timing.m[downlink_mode].start_gap * 8);
|
WaitUS(T55xx_Timing.m[downlink_mode].start_gap);
|
||||||
|
|
||||||
// If long leading 0 send long reference pulse
|
// If long leading 0 send long reference pulse
|
||||||
if (downlink_mode == T55xx_DLMode_LLR)
|
if (downlink_mode == T55XX_DLMODE_LLR)
|
||||||
T55xxWriteBit(T55xx_LongLeadingReference, downlink_mode);//Timing); // Send Long Leading Start Reference
|
T55xxWriteBit(T55XX_LONGLEADINGREFERENCE, downlink_mode);//Timing); // Send Long Leading Start Reference
|
||||||
|
|
||||||
if ((downlink_mode == T55xx_DLMode_1of4) && (BitStreamLen > 0)) { // 1 of 4 need to send 2 bits at a time
|
uint8_t sendbits;
|
||||||
for (i = 0; i < BitStreamLen - 1; i += 2) {
|
if ((downlink_mode == T55XX_DLMODE_1OF4) && (len > 0)) { // 1 of 4 need to send 2 bits at a time
|
||||||
SendBits = (BitStream[BitStream_Byte(i)] >> (BitStream_Bit(i)) & 1) << 1; // Bit i
|
for (uint8_t i = 0; i < len - 1; i += 2) {
|
||||||
SendBits += (BitStream[BitStream_Byte(i + 1)] >> (BitStream_Bit(i + 1)) & 1); // Bit i+1;
|
sendbits = (bs[BITSTREAM_BYTE(i)] >> (BITSTREAM_BIT(i)) & 1) << 1; // Bit i
|
||||||
T55xxWriteBit(SendBits & 3, downlink_mode);//Timing);
|
sendbits += (bs[BITSTREAM_BYTE(i + 1)] >> (BITSTREAM_BIT(i + 1)) & 1); // Bit i+1;
|
||||||
|
T55xxWriteBit(sendbits & 3, downlink_mode);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < BitStreamLen; i++) {
|
for (uint8_t i = 0; i < len; i++) {
|
||||||
SendBits = (BitStream[BitStream_Byte(i)] >> BitStream_Bit(i));
|
sendbits = (bs[BITSTREAM_BYTE(i)] >> BITSTREAM_BIT(i));
|
||||||
T55xxWriteBit(SendBits & 1, downlink_mode);//Timing);
|
T55xxWriteBit(sendbits & 1, downlink_mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1722,7 +1832,7 @@ void T55xxWriteBlock(uint8_t *data) {
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
|
||||||
// cmd_send(CMD_ACK,0,0,0,0,0);
|
// cmd_send(CMD_ACK,0,0,0,0,0);
|
||||||
reply_ng(CMD_T55XX_WRITE_BLOCK, PM3_SUCCESS, NULL, 0);
|
reply_ng(CMD_LF_T55XX_WRITEBL, PM3_SUCCESS, NULL, 0);
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1731,7 +1841,7 @@ void T55xxWriteBlock(uint8_t *data) {
|
||||||
void T55xxWriteBlock(uint8_t *data) {
|
void T55xxWriteBlock(uint8_t *data) {
|
||||||
t55xx_write_block_t *c = (t55xx_write_block_t *)data;
|
t55xx_write_block_t *c = (t55xx_write_block_t *)data;
|
||||||
T55xxWriteBlockExt(c->data, c->blockno, c->pwd, c->flags);
|
T55xxWriteBlockExt(c->data, c->blockno, c->pwd, c->flags);
|
||||||
// reply_ng(CMD_T55XX_WRITE_BLOCK, PM3_SUCCESS, NULL, 0);
|
// reply_ng(CMD_LF_T55XX_WRITEBL, PM3_SUCCESS, NULL, 0);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
|
@ -1783,7 +1893,7 @@ bool brute_mem = (flags & 0x0100) >> 8;
|
||||||
// Turn the field off
|
// Turn the field off
|
||||||
if (!brute_mem) {
|
if (!brute_mem) {
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
reply_ng(CMD_T55XX_READ_BLOCK, PM3_SUCCESS, NULL, 0);
|
reply_ng(CMD_LF_T55XX_READBL, PM3_SUCCESS, NULL, 0);
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1843,7 +1953,7 @@ void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block,
|
||||||
// Turn the field off
|
// Turn the field off
|
||||||
if (!brute_mem) {
|
if (!brute_mem) {
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
reply_ng(CMD_T55XX_READ_BLOCK, PM3_SUCCESS, NULL, 0);
|
reply_ng(CMD_LF_T55XX_READBL, PM3_SUCCESS, NULL, 0);
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1941,12 +2051,12 @@ OUT:
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
|
||||||
void T55xxWakeUp(uint32_t Pwd, uint8_t flags) {
|
void T55xxWakeUp(uint32_t pwd, uint8_t flags) {
|
||||||
|
|
||||||
flags |= 0x01 | 0x40 | 0x20; //Password | Read Call (no data) | reg_read no block
|
flags |= 0x01 | 0x40 | 0x20; //Password | Read Call (no data) | reg_read no block
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
|
|
||||||
T55xx_SendCMD(0, Pwd, flags);
|
T55xx_SendCMD(0, pwd, flags);
|
||||||
|
|
||||||
//-- Turn and leave field on to let the begin repeating transmission
|
//-- Turn and leave field on to let the begin repeating transmission
|
||||||
TurnReadLFOn(20 * 1000);
|
TurnReadLFOn(20 * 1000);
|
||||||
|
@ -2173,7 +2283,7 @@ uint8_t *fwd_write_ptr; //forwardlink bit pointer
|
||||||
//====================================================================
|
//====================================================================
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// VALUES TAKEN FROM EM4x function: SendForward
|
// VALUES TAKEN FROM EM4x function: SendForward
|
||||||
// START_GAP = 440; (55*8) cycles at 125Khz (8us = 1cycle)
|
// START_GAP = 440; (55*8) cycles at 125kHz (8us = 1cycle)
|
||||||
// WRITE_GAP = 128; (16*8)
|
// WRITE_GAP = 128; (16*8)
|
||||||
// WRITE_1 = 256 32*8; (32*8)
|
// WRITE_1 = 256 32*8; (32*8)
|
||||||
|
|
||||||
|
@ -2331,7 +2441,7 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
|
||||||
DoPartialAcquisition(20, true, 6000, 1000);
|
DoPartialAcquisition(20, true, 6000, 1000);
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
reply_ng(CMD_EM4X_READ_WORD, PM3_SUCCESS, NULL, 0);
|
reply_ng(CMD_LF_EM4X_READWORD, PM3_SUCCESS, NULL, 0);
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2364,7 +2474,7 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
|
||||||
DoPartialAcquisition(20, true, 6000, 1000);
|
DoPartialAcquisition(20, true, 6000, 1000);
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
reply_ng(CMD_EM4X_WRITE_WORD, PM3_SUCCESS, NULL, 0);
|
reply_ng(CMD_LF_EM4X_WRITEWORD, PM3_SUCCESS, NULL, 0);
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
69
armsrc/lfops.h
Normal file
69
armsrc/lfops.h
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Jonathan Westhues, Aug 2005
|
||||||
|
// Gerhard de Koning Gans, April 2008, May 2011
|
||||||
|
//
|
||||||
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
// the license.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Definitions internal to the app source.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifndef __LFOPS_H
|
||||||
|
#define __LFOPS_H
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#include "pm3_cmd.h" // struct
|
||||||
|
|
||||||
|
extern uint8_t decimation;
|
||||||
|
extern uint8_t bits_per_sample ;
|
||||||
|
extern bool averaging;
|
||||||
|
|
||||||
|
void AcquireRawAdcSamples125k(int divisor);
|
||||||
|
void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command);
|
||||||
|
void ReadTItag(void);
|
||||||
|
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);
|
||||||
|
|
||||||
|
void AcquireTiType(void);
|
||||||
|
void AcquireRawBitsTI(void);
|
||||||
|
void SimulateTagLowFrequencyEx(int period, int gap, bool ledcontrol, int numcycles);
|
||||||
|
void SimulateTagLowFrequency(int period, int gap, bool ledcontrol);
|
||||||
|
void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
|
||||||
|
|
||||||
|
void CmdHIDsimTAGEx(uint32_t hi, uint32_t lo, bool ledcontrol, int numcycles);
|
||||||
|
void CmdHIDsimTAG(uint32_t hi, uint32_t lo, bool ledcontrol);
|
||||||
|
|
||||||
|
void CmdFSKsimTAG(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, uint8_t *bits, bool ledcontrol);
|
||||||
|
void CmdASKsimTAG(uint8_t encoding, uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol);
|
||||||
|
void CmdPSKsimTag(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol);
|
||||||
|
|
||||||
|
void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol);
|
||||||
|
void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); // Realtime demodulation mode for AWID26
|
||||||
|
void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol);
|
||||||
|
void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol);
|
||||||
|
void CopyIOtoT55x7(uint32_t hi, uint32_t lo); // Clone an ioProx card to T5557/T5567
|
||||||
|
void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567
|
||||||
|
void CopyVikingtoT55xx(uint32_t block1, uint32_t block2, uint8_t Q5);
|
||||||
|
void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo);
|
||||||
|
void CopyIndala64toT55x7(uint32_t hi, uint32_t lo); // Clone Indala 64-bit tag by UID to T55x7
|
||||||
|
void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7); // Clone Indala 224-bit tag by UID to T55x7
|
||||||
|
void T55xxResetRead(uint8_t flags);
|
||||||
|
//id T55xxWriteBlock(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags);
|
||||||
|
void T55xxWriteBlock(uint8_t *data);
|
||||||
|
// void T55xxWriteBlockExt(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags);
|
||||||
|
void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block, uint32_t pwd, uint8_t downlink_mode);
|
||||||
|
void T55xxWakeUp(uint32_t pwd, uint8_t flags);
|
||||||
|
void T55xx_ChkPwds(uint8_t flags);
|
||||||
|
|
||||||
|
void TurnReadLFOn(uint32_t delay);
|
||||||
|
|
||||||
|
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd);
|
||||||
|
void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd);
|
||||||
|
|
||||||
|
void Cotag(uint32_t arg0);
|
||||||
|
void setT55xxConfig(uint8_t arg0, t55xx_configurations_t *c);
|
||||||
|
t55xx_configurations_t *getT55xxConfig(void);
|
||||||
|
void printT55xxConfig(void);
|
||||||
|
void loadT55xxConfig(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -8,12 +8,20 @@
|
||||||
|
|
||||||
#include "lfsampling.h"
|
#include "lfsampling.h"
|
||||||
|
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "lfdemod.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Default LF config is set to:
|
Default LF config is set to:
|
||||||
decimation = 1 (we keep 1 out of 1 samples)
|
decimation = 1 (we keep 1 out of 1 samples)
|
||||||
bits_per_sample = 8
|
bits_per_sample = 8
|
||||||
averaging = YES
|
averaging = YES
|
||||||
divisor = 95 (125khz)
|
divisor = 95 (125kHz)
|
||||||
trigger_threshold = 0
|
trigger_threshold = 0
|
||||||
*/
|
*/
|
||||||
sample_config config = { 1, 8, 1, 95, 0 } ;
|
sample_config config = { 1, 8, 1, 95, 0 } ;
|
||||||
|
@ -83,9 +91,9 @@ void pushBit(BitstreamOut *stream, uint8_t bit) {
|
||||||
void LFSetupFPGAForADC(int divisor, bool lf_field) {
|
void LFSetupFPGAForADC(int divisor, bool lf_field) {
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
if ((divisor == 1) || (divisor < 0) || (divisor > 255))
|
if ((divisor == 1) || (divisor < 0) || (divisor > 255))
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8kHz
|
||||||
else if (divisor == 0)
|
else if (divisor == 0)
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz
|
||||||
else
|
else
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
#ifndef __LFSAMPLING_H
|
#ifndef __LFSAMPLING_H
|
||||||
#define __LFSAMPLING_H
|
#define __LFSAMPLING_H
|
||||||
|
|
||||||
#include "proxmark3.h"
|
#include "common.h"
|
||||||
#include "apps.h"
|
#include "pm3_cmd.h"
|
||||||
#include "util.h"
|
|
||||||
#include "string.h"
|
|
||||||
#include "usb_cdc.h" // for usb_poll_validate_length
|
|
||||||
#include "ticks.h" // for StartTicks
|
|
||||||
|
|
||||||
typedef struct BitstreamOut BitstreamOut;
|
typedef struct BitstreamOut BitstreamOut;
|
||||||
|
|
||||||
|
@ -82,5 +78,4 @@ sample_config *getSamplingConfig();
|
||||||
|
|
||||||
void printConfig();
|
void printConfig();
|
||||||
|
|
||||||
|
|
||||||
#endif // __LFSAMPLING_H
|
#endif // __LFSAMPLING_H
|
||||||
|
|
|
@ -15,9 +15,23 @@
|
||||||
|
|
||||||
#include "mifarecmd.h"
|
#include "mifarecmd.h"
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#include "pmflash.h"
|
#include "pmflash.h"
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "mifareutil.h"
|
||||||
|
#include "protocols.h"
|
||||||
|
#include "parity.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "cmd.h"
|
||||||
|
#include "flashmem.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "iso14443a.h"
|
||||||
|
#include "mifaredesfire.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "commonutil.h"
|
||||||
|
#include "crc16.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
|
||||||
#ifndef HARDNESTED_AUTHENTICATION_TIMEOUT
|
#ifndef HARDNESTED_AUTHENTICATION_TIMEOUT
|
||||||
# define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
|
# define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
|
||||||
|
@ -94,7 +108,7 @@ void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain) {
|
||||||
if (DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
|
if (DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
reply_ng(CMD_MIFARE_READBL, status, dataoutbuf, 16);
|
reply_ng(CMD_HF_MIFARE_READBL, status, dataoutbuf, 16);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
@ -1495,7 +1509,7 @@ OUT:
|
||||||
|
|
||||||
uint16_t bar = 0;
|
uint16_t bar = 0;
|
||||||
uint8_t j = 0;
|
uint8_t j = 0;
|
||||||
for (uint8_t m = 64; m < sizeof(found); m++) {
|
for (uint8_t m = 64; m < ARRAYLEN(found); m++) {
|
||||||
bar |= ((uint16_t)(found[m] & 1) << j++);
|
bar |= ((uint16_t)(found[m] & 1) << j++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1601,7 +1615,7 @@ void MifareChkKeys(uint8_t *datain) {
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
|
|
||||||
reply_ng(CMD_MIFARE_CHKKEYS, PM3_SUCCESS, (uint8_t *)&keyresult, sizeof(keyresult));
|
reply_ng(CMD_HF_MIFARE_CHKKEYS, PM3_SUCCESS, (uint8_t *)&keyresult, sizeof(keyresult));
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
|
|
||||||
|
@ -1637,7 +1651,7 @@ void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) {
|
||||||
//
|
//
|
||||||
size_t size = blockcnt * 16;
|
size_t size = blockcnt * 16;
|
||||||
if (size > PM3_CMD_DATA_SIZE) {
|
if (size > PM3_CMD_DATA_SIZE) {
|
||||||
reply_ng(CMD_MIFARE_EML_MEMGET, PM3_EMALLOC, NULL, 0);
|
reply_ng(CMD_HF_MIFARE_EML_MEMGET, PM3_EMALLOC, NULL, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1646,7 +1660,7 @@ void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) {
|
||||||
emlGetMem(buf, blockno, blockcnt); // data, block num, blocks count (max 4)
|
emlGetMem(buf, blockno, blockcnt); // data, block num, blocks count (max 4)
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
reply_ng(CMD_MIFARE_EML_MEMGET, PM3_SUCCESS, buf, size);
|
reply_ng(CMD_HF_MIFARE_EML_MEMGET, PM3_SUCCESS, buf, size);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
BigBuf_free_keep_EM();
|
BigBuf_free_keep_EM();
|
||||||
}
|
}
|
||||||
|
@ -1990,7 +2004,7 @@ TEST2:
|
||||||
OUT:
|
OUT:
|
||||||
|
|
||||||
data[0] = isGen;
|
data[0] = isGen;
|
||||||
reply_ng(CMD_MIFARE_CIDENT, PM3_SUCCESS, data, sizeof(data));
|
reply_ng(CMD_HF_MIFARE_CIDENT, PM3_SUCCESS, data, sizeof(data));
|
||||||
// turns off
|
// turns off
|
||||||
OnSuccessMagic();
|
OnSuccessMagic();
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
|
@ -2059,7 +2073,7 @@ void MifareSetMod(uint8_t *datain) {
|
||||||
crypto1_destroy(pcs);
|
crypto1_destroy(pcs);
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
reply_ng(CMD_MIFARE_SETMOD, isOK, NULL, 0);
|
reply_ng(CMD_HF_MIFARE_SETMOD, isOK, NULL, 0);
|
||||||
|
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,52 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Merlok - June 2011
|
// Jonathan Westhues, Aug 2005
|
||||||
// Gerhard de Koning Gans - May 2008
|
// Gerhard de Koning Gans, April 2008, May 2011
|
||||||
// Hagen Fritsch - June 2010
|
|
||||||
//
|
//
|
||||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
// the license.
|
// the license.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Routines to support ISO 14443 type A.
|
// Definitions internal to the app source.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#ifndef __MIFARECMD_H
|
#ifndef __MIFARECMD_H
|
||||||
#define __MIFARECMD_H
|
#define __MIFARECMD_H
|
||||||
|
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "apps.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "string.h"
|
|
||||||
#include "iso14443a.h"
|
|
||||||
#include "crapto1/crapto1.h"
|
|
||||||
#include "mifareutil.h"
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "crc.h"
|
|
||||||
#include "protocols.h"
|
void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain);
|
||||||
#include "parity.h"
|
|
||||||
|
void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||||
|
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 MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain);
|
||||||
|
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||||
|
void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||||
|
void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
|
||||||
|
void MifareAcquireNonces(uint32_t arg0, uint32_t flags);
|
||||||
|
void MifareChkKeys(uint8_t *datain);
|
||||||
|
void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||||
|
|
||||||
|
void MifareEMemClr(void);
|
||||||
|
void MifareEMemSet(uint8_t blockno, uint8_t blockcnt, uint8_t blockwidth, uint8_t *datain);
|
||||||
|
void MifareEMemGet(uint8_t blockno, uint8_t blockcnt);
|
||||||
|
int MifareECardLoad(uint32_t arg0, uint32_t arg1);
|
||||||
|
|
||||||
|
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(); // is "magic chinese" card?
|
||||||
|
|
||||||
|
void MifareSetMod(uint8_t *datain);
|
||||||
|
void MifareUSetPwd(uint8_t arg0, uint8_t *datain);
|
||||||
|
void OnSuccessMagic();
|
||||||
|
void OnErrorMagic(uint8_t reason);
|
||||||
|
|
||||||
|
int32_t dist_nt(uint32_t nt1, uint32_t nt2);
|
||||||
|
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype);
|
||||||
|
//void RAMFUNC SniffMifare(uint8_t param);
|
||||||
|
|
||||||
|
void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain);
|
||||||
|
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,20 @@
|
||||||
#include "mifaredesfire.h"
|
#include "mifaredesfire.h"
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "desfire_key.h"
|
||||||
|
#include "mifareutil.h"
|
||||||
|
#include "des.h"
|
||||||
|
#include "cmd.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "iso14443a.h"
|
||||||
|
#include "crc16.h"
|
||||||
|
#include "mbedtls/aes.h"
|
||||||
|
#include "commonutil.h"
|
||||||
|
|
||||||
#define MAX_APPLICATION_COUNT 28
|
#define MAX_APPLICATION_COUNT 28
|
||||||
#define MAX_FILE_COUNT 16
|
#define MAX_FILE_COUNT 16
|
||||||
#define MAX_DESFIRE_FRAME_SIZE 60
|
#define MAX_DESFIRE_FRAME_SIZE 60
|
||||||
|
|
|
@ -1,13 +1,26 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Jonathan Westhues, Aug 2005
|
||||||
|
// Gerhard de Koning Gans, April 2008, May 2011
|
||||||
|
//
|
||||||
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
// the license.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Definitions internal to the app source.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
#ifndef __MIFAREDESFIRE_H
|
#ifndef __MIFAREDESFIRE_H
|
||||||
#define __MIFAREDESFIRE_H
|
#define __MIFAREDESFIRE_H
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "apps.h"
|
bool InitDesfireCard();
|
||||||
#include "string.h"
|
void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||||
#include "BigBuf.h"
|
void MifareDesfireGetInformation();
|
||||||
#include "iso14443a.h"
|
void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
||||||
#include "desfire_key.h"
|
void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t *datain);
|
||||||
#include "mifareutil.h"
|
int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout);
|
||||||
#include "des.h"
|
size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout);
|
||||||
|
void OnSuccess();
|
||||||
|
void OnError(uint8_t reason);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -20,19 +20,24 @@
|
||||||
// /!\ Printing Debug message is disrupting emulation,
|
// /!\ Printing Debug message is disrupting emulation,
|
||||||
// Only use with caution during debugging
|
// Only use with caution during debugging
|
||||||
|
|
||||||
|
#include "mifaresim.h"
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include "iso14443a.h"
|
#include "iso14443a.h"
|
||||||
#include "mifaresim.h"
|
|
||||||
#include "crapto1/crapto1.h"
|
|
||||||
#include "BigBuf.h"
|
#include "BigBuf.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "mifareutil.h"
|
#include "mifareutil.h"
|
||||||
#include "fpgaloader.h"
|
#include "fpgaloader.h"
|
||||||
#include "proxmark3.h"
|
#include "proxmark3_arm.h"
|
||||||
#include "usb_cdc.h"
|
|
||||||
#include "cmd.h"
|
#include "cmd.h"
|
||||||
#include "protocols.h"
|
#include "protocols.h"
|
||||||
#include "apps.h"
|
#include "appmain.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "commonutil.h"
|
||||||
|
#include "crc16.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
|
||||||
static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
|
static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
|
||||||
uint8_t sector_trailer[16];
|
uint8_t sector_trailer[16];
|
||||||
|
@ -163,7 +168,7 @@ static bool IsAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len, uint8_t **rats, uint8_t *rats_len) {
|
static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_t sak, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len, uint8_t **rats, uint8_t *rats_len) {
|
||||||
|
|
||||||
// SPEC: https://www.nxp.com/docs/en/application-note/AN10833.pdf
|
// SPEC: https://www.nxp.com/docs/en/application-note/AN10833.pdf
|
||||||
// ATQA
|
// ATQA
|
||||||
|
@ -250,21 +255,21 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
|
||||||
if ((flags & FLAG_MF_MINI) == FLAG_MF_MINI) {
|
if ((flags & FLAG_MF_MINI) == FLAG_MF_MINI) {
|
||||||
memcpy(rATQA, rATQA_Mini, sizeof(rATQA));
|
memcpy(rATQA, rATQA_Mini, sizeof(rATQA));
|
||||||
rSAK[0] = rSAK_Mini;
|
rSAK[0] = rSAK_Mini;
|
||||||
Dbprintf("Mifare Mini");
|
if (DBGLEVEL > DBG_NONE) Dbprintf("Enforcing Mifare Mini ATQA/SAK");
|
||||||
} else if ((flags & FLAG_MF_1K) == FLAG_MF_1K) {
|
} else if ((flags & FLAG_MF_1K) == FLAG_MF_1K) {
|
||||||
memcpy(rATQA, rATQA_1k, sizeof(rATQA));
|
memcpy(rATQA, rATQA_1k, sizeof(rATQA));
|
||||||
rSAK[0] = rSAK_1k;
|
rSAK[0] = rSAK_1k;
|
||||||
Dbprintf("Mifare 1K");
|
if (DBGLEVEL > DBG_NONE) Dbprintf("Enforcing Mifare 1K ATQA/SAK");
|
||||||
} else if ((flags & FLAG_MF_2K) == FLAG_MF_2K) {
|
} else if ((flags & FLAG_MF_2K) == FLAG_MF_2K) {
|
||||||
memcpy(rATQA, rATQA_2k, sizeof(rATQA));
|
memcpy(rATQA, rATQA_2k, sizeof(rATQA));
|
||||||
rSAK[0] = rSAK_2k;
|
rSAK[0] = rSAK_2k;
|
||||||
*rats = rRATS;
|
*rats = rRATS;
|
||||||
*rats_len = sizeof(rRATS);
|
*rats_len = sizeof(rRATS);
|
||||||
Dbprintf("Mifare 2K with RATS support");
|
if (DBGLEVEL > DBG_NONE) Dbprintf("Enforcing Mifare 2K ATQA/SAK with RATS support");
|
||||||
} else if ((flags & FLAG_MF_4K) == FLAG_MF_4K) {
|
} else if ((flags & FLAG_MF_4K) == FLAG_MF_4K) {
|
||||||
memcpy(rATQA, rATQA_4k, sizeof(rATQA));
|
memcpy(rATQA, rATQA_4k, sizeof(rATQA));
|
||||||
rSAK[0] = rSAK_4k;
|
rSAK[0] = rSAK_4k;
|
||||||
Dbprintf("Mifare 4K");
|
if (DBGLEVEL > DBG_NONE) Dbprintf("Enforcing Mifare 4K ATQA/SAK");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare UID arrays
|
// Prepare UID arrays
|
||||||
|
@ -279,7 +284,7 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
|
||||||
*cuid = bytes_to_num(rUIDBCC1, 4);
|
*cuid = bytes_to_num(rUIDBCC1, 4);
|
||||||
// BCC
|
// BCC
|
||||||
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
|
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
|
||||||
if (DBGLEVEL >= DBG_NONE) {
|
if (DBGLEVEL > DBG_NONE) {
|
||||||
Dbprintf("4B UID: %02x%02x%02x%02x", rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3]);
|
Dbprintf("4B UID: %02x%02x%02x%02x", rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +305,7 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
|
||||||
// BCC
|
// BCC
|
||||||
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
|
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
|
||||||
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
|
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
|
||||||
if (DBGLEVEL >= DBG_NONE) {
|
if (DBGLEVEL > DBG_NONE) {
|
||||||
Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x",
|
Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x",
|
||||||
rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], rUIDBCC2[0], rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3]);
|
rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], rUIDBCC2[0], rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3]);
|
||||||
}
|
}
|
||||||
|
@ -326,7 +331,7 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
|
||||||
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
|
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
|
||||||
rUIDBCC3[4] = rUIDBCC3[0] ^ rUIDBCC3[1] ^ rUIDBCC3[2] ^ rUIDBCC3[3];
|
rUIDBCC3[4] = rUIDBCC3[0] ^ rUIDBCC3[1] ^ rUIDBCC3[2] ^ rUIDBCC3[3];
|
||||||
|
|
||||||
if (DBGLEVEL >= DBG_NONE) {
|
if (DBGLEVEL > DBG_NONE) {
|
||||||
Dbprintf("10B UID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
|
Dbprintf("10B UID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||||
rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3],
|
rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3],
|
||||||
rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3],
|
rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3],
|
||||||
|
@ -340,6 +345,17 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
|
||||||
Dbprintf("[-] ERROR: UID size not defined");
|
Dbprintf("[-] ERROR: UID size not defined");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (flags & FLAG_FORCED_ATQA) {
|
||||||
|
rATQA[0] = atqa >> 8;
|
||||||
|
rATQA[1] = atqa & 0xff;
|
||||||
|
}
|
||||||
|
if (flags & FLAG_FORCED_SAK) {
|
||||||
|
rSAK[0] = sak;
|
||||||
|
}
|
||||||
|
if (DBGLEVEL > DBG_NONE) {
|
||||||
|
Dbprintf("ATQA : %02X %02X", rATQA[1], rATQA[0]);
|
||||||
|
Dbprintf("SAK : %02X", rSAK[0]);
|
||||||
|
}
|
||||||
|
|
||||||
// clone UIDs for byte-frame anti-collision multiple tag selection procedure
|
// clone UIDs for byte-frame anti-collision multiple tag selection procedure
|
||||||
memcpy(rUIDBCC1b4, &rUIDBCC1[1], 4);
|
memcpy(rUIDBCC1b4, &rUIDBCC1[1], 4);
|
||||||
|
@ -432,7 +448,7 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
|
||||||
*@param exitAfterNReads, exit simulation after n blocks have been read, 0 is infinite ...
|
*@param exitAfterNReads, exit simulation after n blocks have been read, 0 is infinite ...
|
||||||
* (unless reader attack mode enabled then it runs util it gets enough nonces to recover all keys attmpted)
|
* (unless reader attack mode enabled then it runs util it gets enough nonces to recover all keys attmpted)
|
||||||
*/
|
*/
|
||||||
void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
|
void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak) {
|
||||||
tag_response_info_t *responses;
|
tag_response_info_t *responses;
|
||||||
uint8_t cardSTATE = MFEMUL_NOFIELD;
|
uint8_t cardSTATE = MFEMUL_NOFIELD;
|
||||||
uint8_t uid_len = 0; // 4,7, 10
|
uint8_t uid_len = 0; // 4,7, 10
|
||||||
|
@ -495,12 +511,12 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
|
||||||
uint8_t rAUTH_NT_keystream[4];
|
uint8_t rAUTH_NT_keystream[4];
|
||||||
uint32_t nonce = 0;
|
uint32_t nonce = 0;
|
||||||
|
|
||||||
tUart *uart = GetUart();
|
tUart14a *uart = GetUart14a();
|
||||||
|
|
||||||
// free eventually allocated BigBuf memory but keep Emulator Memory
|
// free eventually allocated BigBuf memory but keep Emulator Memory
|
||||||
BigBuf_free_keep_EM();
|
BigBuf_free_keep_EM();
|
||||||
|
|
||||||
if (MifareSimInit(flags, datain, &responses, &cuid, &uid_len, &rats, &rats_len) == false) {
|
if (MifareSimInit(flags, datain, atqa, sak, &responses, &cuid, &uid_len, &rats, &rats_len) == false) {
|
||||||
BigBuf_free_keep_EM();
|
BigBuf_free_keep_EM();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1221,7 +1237,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
|
||||||
|
|
||||||
if ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK
|
if ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK
|
||||||
//Send the collected ar_nr in the response
|
//Send the collected ar_nr in the response
|
||||||
reply_old(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, button_pushed, 0, &ar_nr_resp, sizeof(ar_nr_resp));
|
reply_old(CMD_ACK, CMD_HF_MIFARE_SIMULATE, button_pushed, 0, &ar_nr_resp, sizeof(ar_nr_resp));
|
||||||
}
|
}
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
|
|
@ -13,14 +13,12 @@
|
||||||
#ifndef __MIFARESIM_H
|
#ifndef __MIFARESIM_H
|
||||||
#define __MIFARESIM_H
|
#define __MIFARESIM_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include "common.h"
|
||||||
|
|
||||||
#ifndef CheckCrc14A
|
#ifndef CheckCrc14A
|
||||||
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
|
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain);
|
|
||||||
|
|
||||||
#define AC_DATA_READ 0
|
#define AC_DATA_READ 0
|
||||||
#define AC_DATA_WRITE 1
|
#define AC_DATA_WRITE 1
|
||||||
#define AC_DATA_INC 2
|
#define AC_DATA_INC 2
|
||||||
|
@ -36,4 +34,6 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain);
|
||||||
#define AUTHKEYB 1
|
#define AUTHKEYB 1
|
||||||
#define AUTHKEYNONE 0xff
|
#define AUTHKEYNONE 0xff
|
||||||
|
|
||||||
|
void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -68,10 +68,10 @@ void RAMFUNC SniffMifare(uint8_t param) {
|
||||||
|
|
||||||
|
|
||||||
// Set up the demodulator for tag -> reader responses.
|
// Set up the demodulator for tag -> reader responses.
|
||||||
DemodInit(receivedResp, receivedRespPar);
|
Demod14aInit(receivedResp, receivedRespPar);
|
||||||
|
|
||||||
// Set up the demodulator for the reader -> tag commands
|
// Set up the demodulator for the reader -> tag commands
|
||||||
UartInit(receivedCmd, receivedCmdPar);
|
Uart14aInit(receivedCmd, receivedCmdPar);
|
||||||
|
|
||||||
// Setup and start DMA.
|
// Setup and start DMA.
|
||||||
// set transfer address and number of bytes. Start transfer.
|
// set transfer address and number of bytes. Start transfer.
|
||||||
|
@ -80,8 +80,8 @@ void RAMFUNC SniffMifare(uint8_t param) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tUart *uart = GetUart();
|
tUart14a *uart = GetUart14a();
|
||||||
tDemod *demod = GetDemod();
|
tDemod14a *demod = GetDemod14a();
|
||||||
|
|
||||||
MfSniffInit();
|
MfSniffInit();
|
||||||
|
|
||||||
|
@ -149,10 +149,10 @@ void RAMFUNC SniffMifare(uint8_t param) {
|
||||||
uint8_t readerbyte = (previous_data & 0xF0) | (*data >> 4);
|
uint8_t readerbyte = (previous_data & 0xF0) | (*data >> 4);
|
||||||
if (MillerDecoding(readerbyte, (sniffCounter - 1) * 4)) {
|
if (MillerDecoding(readerbyte, (sniffCounter - 1) * 4)) {
|
||||||
LogTrace(receivedCmd, uart->len, 0, 0, NULL, true);
|
LogTrace(receivedCmd, uart->len, 0, 0, NULL, true);
|
||||||
DemodReset();
|
Demod14aReset();
|
||||||
UartReset();
|
Uart14aReset();
|
||||||
}
|
}
|
||||||
ReaderIsActive = (uart->state != STATE_UNSYNCD);
|
ReaderIsActive = (uart->state != STATE_14A_UNSYNCD);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no need to try decoding tag data if the reader is sending
|
// no need to try decoding tag data if the reader is sending
|
||||||
|
@ -160,10 +160,10 @@ void RAMFUNC SniffMifare(uint8_t param) {
|
||||||
uint8_t tagbyte = (previous_data << 4) | (*data & 0x0F);
|
uint8_t tagbyte = (previous_data << 4) | (*data & 0x0F);
|
||||||
if (ManchesterDecoding(tagbyte, 0, (sniffCounter - 1) * 4)) {
|
if (ManchesterDecoding(tagbyte, 0, (sniffCounter - 1) * 4)) {
|
||||||
LogTrace(receivedResp, demod->len, 0, 0, NULL, false);
|
LogTrace(receivedResp, demod->len, 0, 0, NULL, false);
|
||||||
DemodReset();
|
Demod14aReset();
|
||||||
UartReset();
|
Uart14aReset();
|
||||||
}
|
}
|
||||||
TagIsActive = (demod->state != DEMOD_UNSYNCD);
|
TagIsActive = (demod->state != DEMOD_14A_UNSYNCD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
previous_data = *data;
|
previous_data = *data;
|
|
@ -11,13 +11,6 @@
|
||||||
#ifndef __MIFARESNIFF_H
|
#ifndef __MIFARESNIFF_H
|
||||||
#define __MIFARESNIFF_H
|
#define __MIFARESNIFF_H
|
||||||
|
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "apps.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "string.h"
|
|
||||||
#include "iso14443a.h"
|
|
||||||
#include "crapto1/crapto1.h"
|
|
||||||
#include "mifareutil.h"
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#define SNF_INIT 0
|
#define SNF_INIT 0
|
|
@ -9,6 +9,17 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "mifareutil.h"
|
#include "mifareutil.h"
|
||||||
|
|
||||||
|
#include "string.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "iso14443a.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "parity.h"
|
||||||
|
#include "commonutil.h"
|
||||||
|
#include "crc16.h"
|
||||||
|
#include "protocols.h"
|
||||||
|
#include "des.h"
|
||||||
|
|
||||||
int DBGLEVEL = DBG_ERROR;
|
int DBGLEVEL = DBG_ERROR;
|
||||||
|
|
||||||
// crypto1 helpers
|
// crypto1 helpers
|
||||||
|
|
|
@ -12,14 +12,8 @@
|
||||||
#ifndef __MIFAREUTIL_H
|
#ifndef __MIFAREUTIL_H
|
||||||
#define __MIFAREUTIL_H
|
#define __MIFAREUTIL_H
|
||||||
|
|
||||||
#include "proxmark3.h"
|
#include "common.h"
|
||||||
#include "apps.h"
|
|
||||||
#include "parity.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "string.h"
|
|
||||||
#include "iso14443a.h"
|
|
||||||
#include "crapto1/crapto1.h"
|
#include "crapto1/crapto1.h"
|
||||||
#include "des.h"
|
|
||||||
|
|
||||||
// mifare authentication
|
// mifare authentication
|
||||||
#define CRYPT_NONE 0
|
#define CRYPT_NONE 0
|
||||||
|
|
894
armsrc/nprintf.c
Normal file
894
armsrc/nprintf.c
Normal file
|
@ -0,0 +1,894 @@
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// \author (c) Marco Paland (info@paland.com)
|
||||||
|
// 2014-2019, PALANDesign Hannover, Germany
|
||||||
|
//
|
||||||
|
// \license The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on
|
||||||
|
// embedded systems with a very limited resources. These routines are thread
|
||||||
|
// safe and reentrant!
|
||||||
|
// Use this instead of the bloated standard/newlib printf cause these use
|
||||||
|
// malloc for printf (and may not be thread safe).
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "nprintf.h"
|
||||||
|
|
||||||
|
|
||||||
|
// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the
|
||||||
|
// printf_config.h header file
|
||||||
|
// default: undefined
|
||||||
|
#ifdef PRINTF_INCLUDE_CONFIG_H
|
||||||
|
#include "printf_config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// 'ntoa' conversion buffer size, this must be big enough to hold one converted
|
||||||
|
// numeric number including padded zeros (dynamically created on stack)
|
||||||
|
// default: 32 byte
|
||||||
|
#ifndef PRINTF_NTOA_BUFFER_SIZE
|
||||||
|
#define PRINTF_NTOA_BUFFER_SIZE 32U
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 'ftoa' conversion buffer size, this must be big enough to hold one converted
|
||||||
|
// float number including padded zeros (dynamically created on stack)
|
||||||
|
// default: 32 byte
|
||||||
|
#ifndef PRINTF_FTOA_BUFFER_SIZE
|
||||||
|
#define PRINTF_FTOA_BUFFER_SIZE 32U
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// support for the floating point type (%f)
|
||||||
|
// default: activated
|
||||||
|
#ifndef PRINTF_DISABLE_SUPPORT_FLOAT
|
||||||
|
#define PRINTF_SUPPORT_FLOAT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// support for exponential floating point notation (%e/%g)
|
||||||
|
// default: activated
|
||||||
|
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL
|
||||||
|
#define PRINTF_SUPPORT_EXPONENTIAL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// define the default floating point precision
|
||||||
|
// default: 6 digits
|
||||||
|
#ifndef PRINTF_DEFAULT_FLOAT_PRECISION
|
||||||
|
#define PRINTF_DEFAULT_FLOAT_PRECISION 6U
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// define the largest float suitable to print with %f
|
||||||
|
// default: 1e9
|
||||||
|
#ifndef PRINTF_MAX_FLOAT
|
||||||
|
#define PRINTF_MAX_FLOAT 1e9
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// support for the long long types (%llu or %p)
|
||||||
|
// default: activated
|
||||||
|
#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG
|
||||||
|
#define PRINTF_SUPPORT_LONG_LONG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// support for the ptrdiff_t type (%t)
|
||||||
|
// ptrdiff_t is normally defined in <stddef.h> as long or long long type
|
||||||
|
// default: activated
|
||||||
|
#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T
|
||||||
|
#define PRINTF_SUPPORT_PTRDIFF_T
|
||||||
|
#endif
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// internal flag definitions
|
||||||
|
#define FLAGS_ZEROPAD (1U << 0U)
|
||||||
|
#define FLAGS_LEFT (1U << 1U)
|
||||||
|
#define FLAGS_PLUS (1U << 2U)
|
||||||
|
#define FLAGS_SPACE (1U << 3U)
|
||||||
|
#define FLAGS_HASH (1U << 4U)
|
||||||
|
#define FLAGS_UPPERCASE (1U << 5U)
|
||||||
|
#define FLAGS_CHAR (1U << 6U)
|
||||||
|
#define FLAGS_SHORT (1U << 7U)
|
||||||
|
#define FLAGS_LONG (1U << 8U)
|
||||||
|
#define FLAGS_LONG_LONG (1U << 9U)
|
||||||
|
#define FLAGS_PRECISION (1U << 10U)
|
||||||
|
#define FLAGS_ADAPT_EXP (1U << 11U)
|
||||||
|
|
||||||
|
|
||||||
|
// import float.h for DBL_MAX
|
||||||
|
#if defined(PRINTF_SUPPORT_FLOAT)
|
||||||
|
#include <float.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// output function type
|
||||||
|
typedef void (*out_fct_type)(char character, void *buffer, size_t idx, size_t maxlen);
|
||||||
|
|
||||||
|
|
||||||
|
// wrapper (used as buffer) for output function type
|
||||||
|
typedef struct {
|
||||||
|
void (*fct)(char character, void *arg);
|
||||||
|
void *arg;
|
||||||
|
} out_fct_wrap_type;
|
||||||
|
|
||||||
|
|
||||||
|
// internal buffer output
|
||||||
|
static inline void _out_buffer(char character, void *buffer, size_t idx, size_t maxlen) {
|
||||||
|
if (idx < maxlen) {
|
||||||
|
((char *)buffer)[idx] = character;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// internal null output
|
||||||
|
static inline void _out_null(char character, void *buffer, size_t idx, size_t maxlen) {
|
||||||
|
(void)character;
|
||||||
|
(void)buffer;
|
||||||
|
(void)idx;
|
||||||
|
(void)maxlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// internal _putchar wrapper
|
||||||
|
static inline void _out_char(char character, void *buffer, size_t idx, size_t maxlen) {
|
||||||
|
(void)buffer;
|
||||||
|
(void)idx;
|
||||||
|
(void)maxlen;
|
||||||
|
if (character) {
|
||||||
|
_putchar(character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// internal output function wrapper
|
||||||
|
static inline void _out_fct(char character, void *buffer, size_t idx, size_t maxlen) {
|
||||||
|
(void)idx;
|
||||||
|
(void)maxlen;
|
||||||
|
if (character) {
|
||||||
|
// buffer is the output fct pointer
|
||||||
|
((out_fct_wrap_type *)buffer)->fct(character, ((out_fct_wrap_type *)buffer)->arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// internal secure strlen
|
||||||
|
// \return The length of the string (excluding the terminating 0) limited by 'maxsize'
|
||||||
|
static inline unsigned int _strnlen_s(const char *str, size_t maxsize) {
|
||||||
|
const char *s;
|
||||||
|
for (s = str; *s && maxsize--; ++s);
|
||||||
|
return (unsigned int)(s - str);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// internal test if char is a digit (0-9)
|
||||||
|
// \return true if char is a digit
|
||||||
|
static inline bool _is_digit(char ch) {
|
||||||
|
return (ch >= '0') && (ch <= '9');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// internal ASCII string to unsigned int conversion
|
||||||
|
static unsigned int _atoi(const char **str) {
|
||||||
|
unsigned int i = 0U;
|
||||||
|
while (_is_digit(**str)) {
|
||||||
|
i = i * 10U + (unsigned int)(*((*str)++) - '0');
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// output the specified string in reverse, taking care of any zero-padding
|
||||||
|
static size_t _out_rev(out_fct_type out, char *buffer, size_t idx, size_t maxlen, const char *buf, size_t len, unsigned int width, unsigned int flags) {
|
||||||
|
const size_t start_idx = idx;
|
||||||
|
|
||||||
|
// pad spaces up to given width
|
||||||
|
if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
|
||||||
|
for (size_t i = len; i < width; i++) {
|
||||||
|
out(' ', buffer, idx++, maxlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reverse string
|
||||||
|
while (len) {
|
||||||
|
out(buf[--len], buffer, idx++, maxlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// append pad spaces up to given width
|
||||||
|
if (flags & FLAGS_LEFT) {
|
||||||
|
while (idx - start_idx < width) {
|
||||||
|
out(' ', buffer, idx++, maxlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// internal itoa format
|
||||||
|
static size_t _ntoa_format(out_fct_type out, char *buffer, size_t idx, size_t maxlen, char *buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags) {
|
||||||
|
// pad leading zeros
|
||||||
|
if (!(flags & FLAGS_LEFT)) {
|
||||||
|
if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
|
||||||
|
width--;
|
||||||
|
}
|
||||||
|
while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||||
|
buf[len++] = '0';
|
||||||
|
}
|
||||||
|
while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||||
|
buf[len++] = '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle hash
|
||||||
|
if (flags & FLAGS_HASH) {
|
||||||
|
if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) {
|
||||||
|
len--;
|
||||||
|
if (len && (base == 16U)) {
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||||
|
buf[len++] = 'x';
|
||||||
|
} else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||||
|
buf[len++] = 'X';
|
||||||
|
} else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||||
|
buf[len++] = 'b';
|
||||||
|
}
|
||||||
|
if (len < PRINTF_NTOA_BUFFER_SIZE) {
|
||||||
|
buf[len++] = '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < PRINTF_NTOA_BUFFER_SIZE) {
|
||||||
|
if (negative) {
|
||||||
|
buf[len++] = '-';
|
||||||
|
} else if (flags & FLAGS_PLUS) {
|
||||||
|
buf[len++] = '+'; // ignore the space if the '+' exists
|
||||||
|
} else if (flags & FLAGS_SPACE) {
|
||||||
|
buf[len++] = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// internal itoa for 'long' type
|
||||||
|
static size_t _ntoa_long(out_fct_type out, char *buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags) {
|
||||||
|
char buf[PRINTF_NTOA_BUFFER_SIZE];
|
||||||
|
size_t len = 0U;
|
||||||
|
|
||||||
|
// no hash for 0 values
|
||||||
|
if (!value) {
|
||||||
|
flags &= ~FLAGS_HASH;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write if precision != 0 and value is != 0
|
||||||
|
if (!(flags & FLAGS_PRECISION) || value) {
|
||||||
|
do {
|
||||||
|
const char digit = (char)(value % base);
|
||||||
|
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
|
||||||
|
value /= base;
|
||||||
|
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// internal itoa for 'long long' type
|
||||||
|
#if defined(PRINTF_SUPPORT_LONG_LONG)
|
||||||
|
static size_t _ntoa_long_long(out_fct_type out, char *buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags) {
|
||||||
|
char buf[PRINTF_NTOA_BUFFER_SIZE];
|
||||||
|
size_t len = 0U;
|
||||||
|
|
||||||
|
// no hash for 0 values
|
||||||
|
if (!value) {
|
||||||
|
flags &= ~FLAGS_HASH;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write if precision != 0 and value is != 0
|
||||||
|
if (!(flags & FLAGS_PRECISION) || value) {
|
||||||
|
do {
|
||||||
|
const char digit = (char)(value % base);
|
||||||
|
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
|
||||||
|
value /= base;
|
||||||
|
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
|
||||||
|
}
|
||||||
|
#endif // PRINTF_SUPPORT_LONG_LONG
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(PRINTF_SUPPORT_FLOAT)
|
||||||
|
|
||||||
|
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
|
||||||
|
// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT
|
||||||
|
static size_t _etoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// internal ftoa for fixed decimal floating point
|
||||||
|
static size_t _ftoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) {
|
||||||
|
char buf[PRINTF_FTOA_BUFFER_SIZE];
|
||||||
|
size_t len = 0U;
|
||||||
|
double diff = 0.0;
|
||||||
|
|
||||||
|
// powers of 10
|
||||||
|
static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
|
||||||
|
|
||||||
|
// test for special values
|
||||||
|
if (value != value)
|
||||||
|
return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags);
|
||||||
|
if (value < -DBL_MAX)
|
||||||
|
return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags);
|
||||||
|
if (value > DBL_MAX)
|
||||||
|
return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
|
||||||
|
|
||||||
|
// test for very large values
|
||||||
|
// standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad
|
||||||
|
if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) {
|
||||||
|
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
|
||||||
|
return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
|
||||||
|
#else
|
||||||
|
return 0U;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// test for negative
|
||||||
|
bool negative = false;
|
||||||
|
if (value < 0) {
|
||||||
|
negative = true;
|
||||||
|
value = 0 - value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set default precision, if not set explicitly
|
||||||
|
if (!(flags & FLAGS_PRECISION)) {
|
||||||
|
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
|
||||||
|
}
|
||||||
|
// limit precision to 9, cause a prec >= 10 can lead to overflow errors
|
||||||
|
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {
|
||||||
|
buf[len++] = '0';
|
||||||
|
prec--;
|
||||||
|
}
|
||||||
|
|
||||||
|
int whole = (int)value;
|
||||||
|
double tmp = (value - whole) * pow10[prec];
|
||||||
|
unsigned long frac = (unsigned long)tmp;
|
||||||
|
diff = tmp - frac;
|
||||||
|
|
||||||
|
if (diff > 0.5) {
|
||||||
|
++frac;
|
||||||
|
// handle rollover, e.g. case 0.99 with prec 1 is 1.0
|
||||||
|
if (frac >= pow10[prec]) {
|
||||||
|
frac = 0;
|
||||||
|
++whole;
|
||||||
|
}
|
||||||
|
} else if (diff < 0.5) {
|
||||||
|
} else if ((frac == 0U) || (frac & 1U)) {
|
||||||
|
// if halfway, round up if odd OR if last digit is 0
|
||||||
|
++frac;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prec == 0U) {
|
||||||
|
diff = value - (double)whole;
|
||||||
|
if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
|
||||||
|
// exactly 0.5 and ODD, then round up
|
||||||
|
// 1.5 -> 2, but 2.5 -> 2
|
||||||
|
++whole;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsigned int count = prec;
|
||||||
|
// now do fractional part, as an unsigned number
|
||||||
|
while (len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||||
|
--count;
|
||||||
|
buf[len++] = (char)(48U + (frac % 10U));
|
||||||
|
if (!(frac /= 10U)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add extra 0s
|
||||||
|
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
|
||||||
|
buf[len++] = '0';
|
||||||
|
}
|
||||||
|
if (len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||||
|
// add decimal
|
||||||
|
buf[len++] = '.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// do whole part, number is reversed
|
||||||
|
while (len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||||
|
buf[len++] = (char)(48 + (whole % 10));
|
||||||
|
if (!(whole /= 10)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pad leading zeros
|
||||||
|
if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
|
||||||
|
if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
|
||||||
|
width--;
|
||||||
|
}
|
||||||
|
while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
|
||||||
|
buf[len++] = '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||||
|
if (negative) {
|
||||||
|
buf[len++] = '-';
|
||||||
|
} else if (flags & FLAGS_PLUS) {
|
||||||
|
buf[len++] = '+'; // ignore the space if the '+' exists
|
||||||
|
} else if (flags & FLAGS_SPACE) {
|
||||||
|
buf[len++] = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
|
||||||
|
// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse <m.jasperse@gmail.com>
|
||||||
|
static size_t _etoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) {
|
||||||
|
// check for NaN and special values
|
||||||
|
if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {
|
||||||
|
return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine the sign
|
||||||
|
const bool negative = value < 0;
|
||||||
|
if (negative) {
|
||||||
|
value = -value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// default precision
|
||||||
|
if (!(flags & FLAGS_PRECISION)) {
|
||||||
|
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine the decimal exponent
|
||||||
|
// based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c)
|
||||||
|
union {
|
||||||
|
uint64_t U;
|
||||||
|
double F;
|
||||||
|
} conv;
|
||||||
|
|
||||||
|
conv.F = value;
|
||||||
|
int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2
|
||||||
|
conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2)
|
||||||
|
// now approximate log10 from the log2 integer part and an expansion of ln around 1.5
|
||||||
|
int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
|
||||||
|
// now we want to compute 10^expval but we want to be sure it won't overflow
|
||||||
|
exp2 = (int)(expval * 3.321928094887362 + 0.5);
|
||||||
|
const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
|
||||||
|
const double z2 = z * z;
|
||||||
|
conv.U = (uint64_t)(exp2 + 1023) << 52U;
|
||||||
|
// compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
|
||||||
|
conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
|
||||||
|
// correct for rounding errors
|
||||||
|
if (value < conv.F) {
|
||||||
|
expval--;
|
||||||
|
conv.F /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters
|
||||||
|
unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;
|
||||||
|
|
||||||
|
// in "%g" mode, "prec" is the number of *significant figures* not decimals
|
||||||
|
if (flags & FLAGS_ADAPT_EXP) {
|
||||||
|
// do we want to fall-back to "%f" mode?
|
||||||
|
if ((value >= 1e-4) && (value < 1e6)) {
|
||||||
|
if ((int)prec > expval) {
|
||||||
|
prec = (unsigned)((int)prec - expval - 1);
|
||||||
|
} else {
|
||||||
|
prec = 0;
|
||||||
|
}
|
||||||
|
flags |= FLAGS_PRECISION; // make sure _ftoa respects precision
|
||||||
|
// no characters in exponent
|
||||||
|
minwidth = 0U;
|
||||||
|
expval = 0;
|
||||||
|
} else {
|
||||||
|
// we use one sigfig for the whole part
|
||||||
|
if ((prec > 0) && (flags & FLAGS_PRECISION)) {
|
||||||
|
--prec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// will everything fit?
|
||||||
|
unsigned int fwidth = width;
|
||||||
|
if (width > minwidth) {
|
||||||
|
// we didn't fall-back so subtract the characters required for the exponent
|
||||||
|
fwidth -= minwidth;
|
||||||
|
} else {
|
||||||
|
// not enough characters, so go back to default sizing
|
||||||
|
fwidth = 0U;
|
||||||
|
}
|
||||||
|
if ((flags & FLAGS_LEFT) && minwidth) {
|
||||||
|
// if we're padding on the right, DON'T pad the floating part
|
||||||
|
fwidth = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rescale the float value
|
||||||
|
if (expval) {
|
||||||
|
value /= conv.F;
|
||||||
|
}
|
||||||
|
|
||||||
|
// output the floating part
|
||||||
|
const size_t start_idx = idx;
|
||||||
|
idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP);
|
||||||
|
|
||||||
|
// output the exponent part
|
||||||
|
if (minwidth) {
|
||||||
|
// output the exponential symbol
|
||||||
|
out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);
|
||||||
|
// output the exponent value
|
||||||
|
idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth - 1, FLAGS_ZEROPAD | FLAGS_PLUS);
|
||||||
|
// might need to right-pad spaces
|
||||||
|
if (flags & FLAGS_LEFT) {
|
||||||
|
while (idx - start_idx < width) out(' ', buffer, idx++, maxlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
#endif // PRINTF_SUPPORT_EXPONENTIAL
|
||||||
|
#endif // PRINTF_SUPPORT_FLOAT
|
||||||
|
|
||||||
|
|
||||||
|
// internal vsnprintf
|
||||||
|
static int _vsnprintf(out_fct_type out, char *buffer, const size_t maxlen, const char *format, va_list va) {
|
||||||
|
unsigned int flags, width, precision, n;
|
||||||
|
size_t idx = 0U;
|
||||||
|
|
||||||
|
if (!buffer) {
|
||||||
|
// use null output function
|
||||||
|
out = _out_null;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*format) {
|
||||||
|
// format specifier? %[flags][width][.precision][length]
|
||||||
|
if (*format != '%') {
|
||||||
|
// no
|
||||||
|
out(*format, buffer, idx++, maxlen);
|
||||||
|
format++;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// yes, evaluate it
|
||||||
|
format++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// evaluate flags
|
||||||
|
flags = 0U;
|
||||||
|
do {
|
||||||
|
switch (*format) {
|
||||||
|
case '0':
|
||||||
|
flags |= FLAGS_ZEROPAD;
|
||||||
|
format++;
|
||||||
|
n = 1U;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
flags |= FLAGS_LEFT;
|
||||||
|
format++;
|
||||||
|
n = 1U;
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
flags |= FLAGS_PLUS;
|
||||||
|
format++;
|
||||||
|
n = 1U;
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
flags |= FLAGS_SPACE;
|
||||||
|
format++;
|
||||||
|
n = 1U;
|
||||||
|
break;
|
||||||
|
case '#':
|
||||||
|
flags |= FLAGS_HASH;
|
||||||
|
format++;
|
||||||
|
n = 1U;
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
n = 0U;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (n);
|
||||||
|
|
||||||
|
// evaluate width field
|
||||||
|
width = 0U;
|
||||||
|
if (_is_digit(*format)) {
|
||||||
|
width = _atoi(&format);
|
||||||
|
} else if (*format == '*') {
|
||||||
|
const int w = va_arg(va, int);
|
||||||
|
if (w < 0) {
|
||||||
|
flags |= FLAGS_LEFT; // reverse padding
|
||||||
|
width = (unsigned int) - w;
|
||||||
|
} else {
|
||||||
|
width = (unsigned int)w;
|
||||||
|
}
|
||||||
|
format++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// evaluate precision field
|
||||||
|
precision = 0U;
|
||||||
|
if (*format == '.') {
|
||||||
|
flags |= FLAGS_PRECISION;
|
||||||
|
format++;
|
||||||
|
if (_is_digit(*format)) {
|
||||||
|
precision = _atoi(&format);
|
||||||
|
} else if (*format == '*') {
|
||||||
|
const int prec = (int)va_arg(va, int);
|
||||||
|
precision = prec > 0 ? (unsigned int)prec : 0U;
|
||||||
|
format++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// evaluate length field
|
||||||
|
switch (*format) {
|
||||||
|
case 'l' :
|
||||||
|
flags |= FLAGS_LONG;
|
||||||
|
format++;
|
||||||
|
if (*format == 'l') {
|
||||||
|
flags |= FLAGS_LONG_LONG;
|
||||||
|
format++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'h' :
|
||||||
|
flags |= FLAGS_SHORT;
|
||||||
|
format++;
|
||||||
|
if (*format == 'h') {
|
||||||
|
flags |= FLAGS_CHAR;
|
||||||
|
format++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#if defined(PRINTF_SUPPORT_PTRDIFF_T)
|
||||||
|
case 't' :
|
||||||
|
flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
|
||||||
|
format++;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case 'j' :
|
||||||
|
flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
|
||||||
|
format++;
|
||||||
|
break;
|
||||||
|
case 'z' :
|
||||||
|
flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
|
||||||
|
format++;
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// evaluate specifier
|
||||||
|
switch (*format) {
|
||||||
|
case 'd' :
|
||||||
|
case 'i' :
|
||||||
|
case 'u' :
|
||||||
|
case 'x' :
|
||||||
|
case 'X' :
|
||||||
|
case 'o' :
|
||||||
|
case 'b' : {
|
||||||
|
// set the base
|
||||||
|
unsigned int base;
|
||||||
|
if (*format == 'x' || *format == 'X') {
|
||||||
|
base = 16U;
|
||||||
|
} else if (*format == 'o') {
|
||||||
|
base = 8U;
|
||||||
|
} else if (*format == 'b') {
|
||||||
|
base = 2U;
|
||||||
|
} else {
|
||||||
|
base = 10U;
|
||||||
|
flags &= ~FLAGS_HASH; // no hash for dec format
|
||||||
|
}
|
||||||
|
// uppercase
|
||||||
|
if (*format == 'X') {
|
||||||
|
flags |= FLAGS_UPPERCASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no plus or space flag for u, x, X, o, b
|
||||||
|
if ((*format != 'i') && (*format != 'd')) {
|
||||||
|
flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore '0' flag when precision is given
|
||||||
|
if (flags & FLAGS_PRECISION) {
|
||||||
|
flags &= ~FLAGS_ZEROPAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert the integer
|
||||||
|
if ((*format == 'i') || (*format == 'd')) {
|
||||||
|
// signed
|
||||||
|
if (flags & FLAGS_LONG_LONG) {
|
||||||
|
#if defined(PRINTF_SUPPORT_LONG_LONG)
|
||||||
|
const long long value = va_arg(va, long long);
|
||||||
|
idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
|
||||||
|
#endif
|
||||||
|
} else if (flags & FLAGS_LONG) {
|
||||||
|
const long value = va_arg(va, long);
|
||||||
|
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
|
||||||
|
} else {
|
||||||
|
const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int);
|
||||||
|
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// unsigned
|
||||||
|
if (flags & FLAGS_LONG_LONG) {
|
||||||
|
#if defined(PRINTF_SUPPORT_LONG_LONG)
|
||||||
|
idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags);
|
||||||
|
#endif
|
||||||
|
} else if (flags & FLAGS_LONG) {
|
||||||
|
idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags);
|
||||||
|
} else {
|
||||||
|
const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int);
|
||||||
|
idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
format++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#if defined(PRINTF_SUPPORT_FLOAT)
|
||||||
|
case 'f' :
|
||||||
|
case 'F' :
|
||||||
|
if (*format == 'F') flags |= FLAGS_UPPERCASE;
|
||||||
|
idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
|
||||||
|
format++;
|
||||||
|
break;
|
||||||
|
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
|
||||||
|
case 'e':
|
||||||
|
case 'E':
|
||||||
|
case 'g':
|
||||||
|
case 'G':
|
||||||
|
if ((*format == 'g') || (*format == 'G')) flags |= FLAGS_ADAPT_EXP;
|
||||||
|
if ((*format == 'E') || (*format == 'G')) flags |= FLAGS_UPPERCASE;
|
||||||
|
idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
|
||||||
|
format++;
|
||||||
|
break;
|
||||||
|
#endif // PRINTF_SUPPORT_EXPONENTIAL
|
||||||
|
#endif // PRINTF_SUPPORT_FLOAT
|
||||||
|
case 'c' : {
|
||||||
|
unsigned int l = 1U;
|
||||||
|
// pre padding
|
||||||
|
if (!(flags & FLAGS_LEFT)) {
|
||||||
|
while (l++ < width) {
|
||||||
|
out(' ', buffer, idx++, maxlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// char output
|
||||||
|
out((char)va_arg(va, int), buffer, idx++, maxlen);
|
||||||
|
// post padding
|
||||||
|
if (flags & FLAGS_LEFT) {
|
||||||
|
while (l++ < width) {
|
||||||
|
out(' ', buffer, idx++, maxlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
format++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 's' : {
|
||||||
|
const char *p = va_arg(va, char *);
|
||||||
|
unsigned int l = _strnlen_s(p, precision ? precision : (size_t) -1);
|
||||||
|
// pre padding
|
||||||
|
if (flags & FLAGS_PRECISION) {
|
||||||
|
l = (l < precision ? l : precision);
|
||||||
|
}
|
||||||
|
if (!(flags & FLAGS_LEFT)) {
|
||||||
|
while (l++ < width) {
|
||||||
|
out(' ', buffer, idx++, maxlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// string output
|
||||||
|
while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) {
|
||||||
|
out(*(p++), buffer, idx++, maxlen);
|
||||||
|
}
|
||||||
|
// post padding
|
||||||
|
if (flags & FLAGS_LEFT) {
|
||||||
|
while (l++ < width) {
|
||||||
|
out(' ', buffer, idx++, maxlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
format++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'p' : {
|
||||||
|
width = sizeof(void *) * 2U;
|
||||||
|
flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE;
|
||||||
|
#if defined(PRINTF_SUPPORT_LONG_LONG)
|
||||||
|
const bool is_ll = sizeof(uintptr_t) == sizeof(long long);
|
||||||
|
if (is_ll) {
|
||||||
|
idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void *), false, 16U, precision, width, flags);
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void *)), false, 16U, precision, width, flags);
|
||||||
|
#if defined(PRINTF_SUPPORT_LONG_LONG)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
format++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '%' :
|
||||||
|
out('%', buffer, idx++, maxlen);
|
||||||
|
format++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
out(*format, buffer, idx++, maxlen);
|
||||||
|
format++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// termination
|
||||||
|
out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
|
||||||
|
|
||||||
|
// return written chars without terminating \0
|
||||||
|
return (int)idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int printf_(const char *format, ...) {
|
||||||
|
va_list va;
|
||||||
|
va_start(va, format);
|
||||||
|
char buffer[1];
|
||||||
|
const int ret = _vsnprintf(_out_char, buffer, (size_t) -1, format, va);
|
||||||
|
va_end(va);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int sprintf_(char *buffer, const char *format, ...) {
|
||||||
|
va_list va;
|
||||||
|
va_start(va, format);
|
||||||
|
const int ret = _vsnprintf(_out_buffer, buffer, (size_t) -1, format, va);
|
||||||
|
va_end(va);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int snprintf_(char *buffer, size_t count, const char *format, ...) {
|
||||||
|
va_list va;
|
||||||
|
va_start(va, format);
|
||||||
|
const int ret = _vsnprintf(_out_buffer, buffer, count, format, va);
|
||||||
|
va_end(va);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int vprintf_(const char *format, va_list va) {
|
||||||
|
char buffer[1];
|
||||||
|
return _vsnprintf(_out_char, buffer, (size_t) -1, format, va);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int vsnprintf_(char *buffer, size_t count, const char *format, va_list va) {
|
||||||
|
return _vsnprintf(_out_buffer, buffer, count, format, va);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int fctprintf(void (*out)(char character, void *arg), void *arg, const char *format, ...) {
|
||||||
|
va_list va;
|
||||||
|
va_start(va, format);
|
||||||
|
const out_fct_wrap_type out_fct_wrap = { out, arg };
|
||||||
|
const int ret = _vsnprintf(_out_fct, (char *)(uintptr_t)&out_fct_wrap, (size_t) -1, format, va);
|
||||||
|
va_end(va);
|
||||||
|
return ret;
|
||||||
|
}
|
107
armsrc/nprintf.h
Normal file
107
armsrc/nprintf.h
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// \author (c) Marco Paland (info@paland.com)
|
||||||
|
// 2014-2019, PALANDesign Hannover, Germany
|
||||||
|
//
|
||||||
|
// \license The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on
|
||||||
|
// embedded systems with a very limited resources.
|
||||||
|
// Use this instead of bloated standard/newlib printf.
|
||||||
|
// These routines are thread safe and reentrant.
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef _PRINTF_H_
|
||||||
|
#define _PRINTF_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output a character to a custom device like UART, used by the printf() function
|
||||||
|
* This function is declared here only. You have to write your custom implementation somewhere
|
||||||
|
* \param character Character to output
|
||||||
|
*/
|
||||||
|
void _putchar(char character);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tiny printf implementation
|
||||||
|
* You have to implement _putchar if you use printf()
|
||||||
|
* To avoid conflicts with the regular printf() API it is overridden by macro defines
|
||||||
|
* and internal underscore-appended functions like printf_() are used
|
||||||
|
* \param format A string that specifies the format of the output
|
||||||
|
* \return The number of characters that are written into the array, not counting the terminating null character
|
||||||
|
*/
|
||||||
|
#define printf printf_
|
||||||
|
int printf_(const char *format, ...);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tiny sprintf implementation
|
||||||
|
* Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD!
|
||||||
|
* \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output!
|
||||||
|
* \param format A string that specifies the format of the output
|
||||||
|
* \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character
|
||||||
|
*/
|
||||||
|
#define sprintf sprintf_
|
||||||
|
int sprintf_(char *buffer, const char *format, ...);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tiny snprintf/vsnprintf implementation
|
||||||
|
* \param buffer A pointer to the buffer where to store the formatted string
|
||||||
|
* \param count The maximum number of characters to store in the buffer, including a terminating null character
|
||||||
|
* \param format A string that specifies the format of the output
|
||||||
|
* \param va A value identifying a variable arguments list
|
||||||
|
* \return The number of characters that COULD have been written into the buffer, not counting the terminating
|
||||||
|
* null character. A value equal or larger than count indicates truncation. Only when the returned value
|
||||||
|
* is non-negative and less than count, the string has been completely written.
|
||||||
|
*/
|
||||||
|
#define snprintf snprintf_
|
||||||
|
#define vsnprintf vsnprintf_
|
||||||
|
int snprintf_(char *buffer, size_t count, const char *format, ...);
|
||||||
|
int vsnprintf_(char *buffer, size_t count, const char *format, va_list va);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tiny vprintf implementation
|
||||||
|
* \param format A string that specifies the format of the output
|
||||||
|
* \param va A value identifying a variable arguments list
|
||||||
|
* \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character
|
||||||
|
*/
|
||||||
|
#define vprintf vprintf_
|
||||||
|
int vprintf_(const char *format, va_list va);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* printf with output function
|
||||||
|
* You may use this as dynamic alternative to printf() with its fixed _putchar() output
|
||||||
|
* \param out An output function which takes one character and an argument pointer
|
||||||
|
* \param arg An argument pointer for user data passed to output function
|
||||||
|
* \param format A string that specifies the format of the output
|
||||||
|
* \return The number of characters that are sent to the output function, not counting the terminating null character
|
||||||
|
*/
|
||||||
|
int fctprintf(void (*out)(char character, void *arg), void *arg, const char *format, ...);
|
||||||
|
|
||||||
|
#endif // _PRINTF_H_
|
|
@ -1,9 +1,7 @@
|
||||||
#ifndef OPTIMIZED_CIPHER_H
|
#ifndef OPTIMIZED_CIPHER_H
|
||||||
#define OPTIMIZED_CIPHER_H
|
#define OPTIMIZED_CIPHER_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include "common.h"
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Definition 1 (Cipher state). A cipher state of iClass s is an element of F 40/2
|
* Definition 1 (Cipher state). A cipher state of iClass s is an element of F 40/2
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
#include "pcf7931.h"
|
#include "pcf7931.h"
|
||||||
|
|
||||||
|
#include "proxmark3_arm.h"
|
||||||
|
#include "cmd.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "lfsampling.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
#define T0_PCF 8 //period for the pcf7931 in us
|
#define T0_PCF 8 //period for the pcf7931 in us
|
||||||
#define ALLOC 16
|
#define ALLOC 16
|
||||||
|
|
||||||
|
@ -404,7 +414,7 @@ void SendCmdPCF7931(uint32_t *tab) {
|
||||||
Dbprintf("Sending data frame...");
|
Dbprintf("Sending data frame...");
|
||||||
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
|
||||||
|
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
#ifndef __PCF7931_H
|
#ifndef __PCF7931_H
|
||||||
#define __PCF7931_H
|
#define __PCF7931_H
|
||||||
|
|
||||||
#include "proxmark3.h"
|
#include "common.h"
|
||||||
#include "apps.h"
|
|
||||||
#include "lfsampling.h"
|
|
||||||
#include "pcf7931.h"
|
|
||||||
#include "string.h"
|
|
||||||
|
|
||||||
size_t DemodPCF7931(uint8_t **outBlocks);
|
size_t DemodPCF7931(uint8_t **outBlocks);
|
||||||
bool IsBlock0PCF7931(uint8_t *block);
|
bool IsBlock0PCF7931(uint8_t *block);
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
*/
|
*/
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
|
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
typedef unsigned char u_char;
|
typedef unsigned char u_char;
|
||||||
typedef unsigned int u_int;
|
typedef unsigned int u_int;
|
||||||
typedef unsigned long long u_quad_t;
|
typedef unsigned long long u_quad_t;
|
||||||
|
|
|
@ -11,9 +11,8 @@
|
||||||
#ifndef __PRINTF_H
|
#ifndef __PRINTF_H
|
||||||
#define __PRINTF_H
|
#define __PRINTF_H
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include "common.h"
|
||||||
#include <stddef.h>
|
#include <stdarg.h> // va_list
|
||||||
#include "string.h"
|
|
||||||
|
|
||||||
int kvsprintf(const char *fmt, void *arg, int radix, va_list ap) __attribute__((format(printf, 1, 0)));
|
int kvsprintf(const char *fmt, void *arg, int radix, va_list ap) __attribute__((format(printf, 1, 0)));
|
||||||
int vsprintf(char *dest, const char *fmt, va_list ap) __attribute__((format(printf, 2, 0)));
|
int vsprintf(char *dest, const char *fmt, va_list ap) __attribute__((format(printf, 2, 0)));
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
#ifndef RADIXSORT_H__
|
#ifndef RADIXSORT_H__
|
||||||
#define RADIXSORT_H__
|
#define RADIXSORT_H__
|
||||||
|
|
||||||
#include <string.h>
|
#include "common.h"
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
struct {
|
struct {
|
||||||
|
@ -20,4 +18,5 @@ typedef union {
|
||||||
} rscounts_t;
|
} rscounts_t;
|
||||||
|
|
||||||
uint64_t *radixSort(uint64_t *array, uint32_t size);
|
uint64_t *radixSort(uint64_t *array, uint32_t size);
|
||||||
|
|
||||||
#endif // RADIXSORT_H__
|
#endif // RADIXSORT_H__
|
|
@ -43,6 +43,12 @@
|
||||||
RDV40_SPIFFS_SAFE_FOOTER
|
RDV40_SPIFFS_SAFE_FOOTER
|
||||||
|
|
||||||
#include "spiffs.h"
|
#include "spiffs.h"
|
||||||
|
#include "flashmem.h"
|
||||||
|
#include "dbprint.h"
|
||||||
|
#include "printf.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
|
||||||
///// FLASH LEVEL R/W/E operations for feeding SPIFFS Driver/////////////////
|
///// FLASH LEVEL R/W/E operations for feeding SPIFFS Driver/////////////////
|
||||||
static s32_t rdv40_spiffs_llread(u32_t addr, u32_t size, u8_t *dst) {
|
static s32_t rdv40_spiffs_llread(u32_t addr, u32_t size, u8_t *dst) {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue