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
|
||||
proxmark3
|
||||
flasher
|
||||
!flasher/
|
||||
lua
|
||||
luac
|
||||
fpga_compress
|
||||
|
|
22
.travis.yml
22
.travis.yml
|
@ -8,22 +8,18 @@ compiler: gcc
|
|||
matrix:
|
||||
include:
|
||||
- os: osx
|
||||
osx_image: xcode9.2 # OS X 10.13
|
||||
osx_image: xcode11
|
||||
- os: linux
|
||||
dist: xenial
|
||||
sudo: required
|
||||
|
||||
before_install:
|
||||
## Install ARM toolchain on Linux.
|
||||
## add our homebrew tap for MacOS
|
||||
## Note: all dependencies on MacOS should be resolved by the brew install command
|
||||
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
sudo apt-get update -qq;
|
||||
sudo apt-get install -y gcc-arm-none-eabi libnewlib-dev;
|
||||
elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
brew update;
|
||||
brew tap RfidResearchGroup/proxmark3;
|
||||
fi
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gcc-arm-none-eabi
|
||||
- libnewlib-dev
|
||||
homebrew:
|
||||
taps: RfidResearchGroup/proxmark3
|
||||
|
||||
install:
|
||||
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
|
@ -34,8 +30,6 @@ install:
|
|||
make all;
|
||||
fi
|
||||
|
||||
before_script:
|
||||
|
||||
script:
|
||||
## start and run a test script
|
||||
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...
|
||||
|
||||
## [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)
|
||||
- Add proper Makefile halting when using incompatible STANDALONE and PLATFORM vars (@doegox)
|
||||
- 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 - handling fault bit markers (7) and partial nibbles in hex printing (@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 `hf 15 dump f` - also selects tag first (@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 reader 21` - saves in bin/eml/json (@iceman1001)
|
||||
- Change `lf hitag` - refactoring (@iceman1001)
|
||||
- Change `lf hitag` - refactoring (@piwi)
|
||||
- Fix `lf hitag` - generic fix for missing clock init (@piwi)
|
||||
- Change `lf hitag` - refactoring (@pwpiwi)
|
||||
- Fix `lf hitag` - generic fix for missing clock init (@pwpiwi)
|
||||
- Fix fsk sim operations on deviceside - avoid division by zero (@doegox)
|
||||
- Fix `hf mf fchk` - condition always false (@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 ability to execute commands from stdin (pipe) (@merlokk)
|
||||
- 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 `hf emv` commands (@merlokk)
|
||||
- lots of bug fixes (many many)
|
||||
|
|
24
Makefile
24
Makefile
|
@ -31,9 +31,9 @@ endif
|
|||
|
||||
-include Makefile.platform
|
||||
-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
|
||||
$(info [*] MAKE $@)
|
||||
|
@ -41,10 +41,13 @@ mfkey/%: FORCE
|
|||
nonce2key/%: FORCE
|
||||
$(info [*] MAKE $@)
|
||||
$(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
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C bootrom $(patsubst bootrom/%,%,$@)
|
||||
armsrc/%: FORCE cleanifplatformchanged
|
||||
armsrc/%: FORCE cleanifplatformchanged fpga_compress/%
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C armsrc $(patsubst armsrc/%,%,$@)
|
||||
client/%: FORCE
|
||||
|
@ -55,7 +58,7 @@ recovery/%: FORCE cleanifplatformchanged bootrom/% armsrc/%
|
|||
$(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)
|
||||
|
||||
.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:
|
||||
@echo "Multi-OS Makefile"
|
||||
|
@ -73,7 +76,8 @@ help:
|
|||
@echo
|
||||
@echo "+ client - Make only the OS-specific host client"
|
||||
@echo "+ mfkey - Make tools/mfkey"
|
||||
@echo "+ nounce2key - Make tools/nounce2key"
|
||||
@echo "+ nonce2key - Make tools/nonce2key"
|
||||
@echo "+ fpga_compress - Make tools/fpga_compress"
|
||||
@echo
|
||||
@echo "+ style - Apply some automated source code formatting rules"
|
||||
@echo "+ checks - Detect various encoding issues in source code"
|
||||
|
@ -93,6 +97,8 @@ mfkey: mfkey/all
|
|||
|
||||
nonce2key: nonce2key/all
|
||||
|
||||
fpga_compress: fpga_compress/all
|
||||
|
||||
flash-bootrom: bootrom/obj/bootrom.elf $(FLASH_TOOL)
|
||||
$(FLASH_TOOL) $(FLASH_PORT) -b $(subst /,$(PATHSEP),$<)
|
||||
|
||||
|
@ -145,7 +151,7 @@ style:
|
|||
# Make sure astyle is installed
|
||||
@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
|
||||
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 sh -c "tail -c1 {} | xxd -p | tail -1 | grep -q -v 0a$$" \; \
|
||||
-exec sh -c "echo >> {}" \;
|
||||
|
@ -158,11 +164,11 @@ style:
|
|||
|
||||
# Detecting weird codepages and tabs.
|
||||
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 {}" \;
|
||||
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' {} \;
|
||||
# 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
|
||||
_test:
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#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.
|
||||
// Also used to hold various smaller buffers and the Mifare Emulator Memory.
|
||||
// declare it as uint32_t to achieve alignment to 4 Byte boundary
|
||||
|
|
|
@ -12,10 +12,7 @@
|
|||
#ifndef __BIGBUF_H
|
||||
#define __BIGBUF_H
|
||||
|
||||
#include <stdbool.h> // for bool
|
||||
#include "proxmark3.h"
|
||||
#include "string.h"
|
||||
#include "ticks.h"
|
||||
#include "common.h"
|
||||
|
||||
#define BIGBUF_SIZE 40000
|
||||
#define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame
|
||||
|
@ -43,4 +40,5 @@ void set_tracelen(uint32_t value);
|
|||
bool get_tracing(void);
|
||||
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
|
||||
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length);
|
||||
|
||||
#endif /* __BIGBUF_H */
|
||||
|
|
|
@ -9,10 +9,6 @@
|
|||
#ifndef __LCD_H
|
||||
#define __LCD_H
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "fonts.h"
|
||||
|
||||
// The resolution of the LCD
|
||||
#define LCD_XRES 132
|
||||
#define LCD_YRES 132
|
|
@ -2,16 +2,14 @@
|
|||
# at your option, any later version. See the LICENSE.txt file for the text of
|
||||
# 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:
|
||||
ifeq ($(PLTNAME),)
|
||||
-include ../Makefile.platform
|
||||
-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
|
||||
ifeq ($(PLATFORM_CHANGED), true)
|
||||
$(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_ISO15693 = iso15693.c iso15693tools.c
|
||||
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c
|
||||
#UNUSED: mifaresniff.c desfire_crypto.c
|
||||
SRC_ISO14443b = iso14443b.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_ICLASS = iclass.c optimized_cipher.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
|
||||
|
||||
# RDV40 related hardware support
|
||||
ifneq (,$(findstring WITH_FLASH,$(APP_CFLAGS)))
|
||||
SRC_FLASH = flashmem.c
|
||||
SRC_SPIFFS = spiffs.c spiffs_cache.c spiffs_check.c spiffs_gc.c spiffs_nucleus.c spiffs_hydrogen.c
|
||||
else
|
||||
SRC_FLASH =
|
||||
SRC_SPIFFS =
|
||||
endif
|
||||
|
||||
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
|
||||
APP_CFLAGS += $(ZLIB_CFLAGS)
|
||||
# zlib includes:
|
||||
APP_CFLAGS += -I../zlib
|
||||
APP_CFLAGS += -I../common/zlib
|
||||
|
||||
# stdint.h provided locally until GCC 4.5 becomes C99 compliant,
|
||||
# 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)
|
||||
THUMBSRC = start.c \
|
||||
protocols.c \
|
||||
$(SRC_LCD) \
|
||||
$(SRC_ISO15693) \
|
||||
$(SRC_NFCBARCODE) \
|
||||
$(SRC_LF) \
|
||||
$(SRC_ZLIB) \
|
||||
$(SRC_LEGIC) \
|
||||
|
@ -101,6 +103,7 @@ THUMBSRC = start.c \
|
|||
$(SRC_SPIFFS) \
|
||||
appmain.c \
|
||||
printf.c \
|
||||
dbprint.c \
|
||||
commonutil.c \
|
||||
util.c \
|
||||
string.c \
|
||||
|
@ -127,12 +130,12 @@ VERSIONSRC = version.c \
|
|||
fpga_version_info.c
|
||||
|
||||
# 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
|
||||
|
||||
OBJS = $(OBJDIR)/fullimage.s19
|
||||
FPGA_COMPRESSOR = ../client/fpga_compress
|
||||
FPGA_COMPRESSOR = ../tools/fpga_compress/fpga_compress
|
||||
|
||||
all: $(OBJS)
|
||||
|
||||
|
@ -143,7 +146,7 @@ version.c: default_version.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o
|
|||
$(info [-] GEN $@)
|
||||
$(Q)perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@
|
||||
|
||||
fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR)
|
||||
fpga_version_info.c: $(FPGA_BITSTREAMS) | $(FPGA_COMPRESSOR)
|
||||
$(info [-] GEN $@)
|
||||
$(Q)$(FPGA_COMPRESSOR) -v $(filter %.bit,$^) $@
|
||||
|
||||
|
@ -151,7 +154,7 @@ $(OBJDIR)/fpga_all.o: $(OBJDIR)/fpga_all.bit.z
|
|||
$(info [-] GEN $@)
|
||||
$(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 $@)
|
||||
ifeq ($(Q),@)
|
||||
@$(FPGA_COMPRESSOR) $(filter %.bit,$^) $@ >/dev/null
|
||||
|
@ -160,8 +163,8 @@ else
|
|||
endif
|
||||
|
||||
$(FPGA_COMPRESSOR):
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C ../client $(notdir $(FPGA_COMPRESSOR))
|
||||
$(error [!] MISSING $@ => To build it, go the root of the repo and do "make $(notdir $@)")
|
||||
$(error [!] MISSING $@)
|
||||
|
||||
$(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ)
|
||||
$(info [=] LD $@)
|
||||
|
@ -179,7 +182,7 @@ $(OBJDIR)/fullimage.data.bin: $(OBJDIR)/fullimage.stage1.elf
|
|||
$(info [-] GEN $@)
|
||||
$(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 $@)
|
||||
ifeq ($(Q),@)
|
||||
@$(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)
|
||||
|
||||
clean:
|
||||
$(Q)$(DELETE) $(DEPENDENCY_FILES)
|
||||
$(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.o
|
||||
$(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.elf
|
||||
$(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.s19
|
||||
|
@ -215,3 +219,4 @@ help:
|
|||
@echo Possible targets:
|
||||
@echo + all - Build the full image $(OBJDIR)/fullimage.s19
|
||||
@echo + clean - Clean $(OBJDIR)
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ ifneq (,$(findstring WITH_STANDALONE_HF_MATTYRUN,$(APP_CFLAGS)))
|
|||
endif
|
||||
# WITH_STANDALONE_HF_COLIN
|
||||
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
|
||||
# WITH_STANDALONE_HF_BOG
|
||||
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.
|
||||
*/
|
||||
|
||||
#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_TAG_AIR2ARM_AS_SNIFFER (3 + 14 + 8)
|
||||
|
@ -62,10 +73,10 @@ void RAMFUNC SniffAndStore(uint8_t param) {
|
|||
bool ReaderIsActive = false;
|
||||
|
||||
// Set up the demodulator for tag -> reader responses.
|
||||
DemodInit(receivedResp, receivedRespPar);
|
||||
Demod14aInit(receivedResp, receivedRespPar);
|
||||
|
||||
// Set up the demodulator for the reader -> tag commands
|
||||
UartInit(receivedCmd, receivedCmdPar);
|
||||
Uart14aInit(receivedCmd, receivedCmdPar);
|
||||
|
||||
// Setup and start DMA.
|
||||
if (!FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE)) {
|
||||
|
@ -74,8 +85,8 @@ void RAMFUNC SniffAndStore(uint8_t param) {
|
|||
return;
|
||||
}
|
||||
|
||||
tUart *uart = GetUart();
|
||||
tDemod *demod = GetDemod();
|
||||
tUart14a *uart = GetUart14a();
|
||||
tDemod14a *demod = GetDemod14a();
|
||||
|
||||
// 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
|
||||
|
@ -153,13 +164,13 @@ void RAMFUNC SniffAndStore(uint8_t param) {
|
|||
break;
|
||||
}
|
||||
/* ready to receive another command. */
|
||||
UartReset();
|
||||
Uart14aReset();
|
||||
/* reset the demod code, which might have been */
|
||||
/* false-triggered by the commands from the reader. */
|
||||
DemodReset();
|
||||
Demod14aReset();
|
||||
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
|
||||
|
@ -176,13 +187,13 @@ void RAMFUNC SniffAndStore(uint8_t param) {
|
|||
triggered = true;
|
||||
|
||||
// ready to receive another response.
|
||||
DemodReset();
|
||||
Demod14aReset();
|
||||
// reset the Miller decoder including its (now outdated) input buffer
|
||||
UartReset();
|
||||
Uart14aReset();
|
||||
// UartInit(receivedCmd, receivedCmdPar);
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include <stdbool.h> // for bool
|
||||
#include <stdio.h>
|
||||
#include <inttypes.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 MF1KSZSIZE 64
|
||||
#define AUTHENTICATION_TIMEOUT 848
|
||||
#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];
|
||||
uint32_t cjcuid;
|
||||
|
@ -27,6 +96,56 @@ int curlline;
|
|||
|
||||
// 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 {
|
||||
uint8_t name[32];
|
||||
uint64_t trigger;
|
||||
|
@ -36,50 +155,49 @@ typedef struct MFC1KSchema {
|
|||
|
||||
#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 Noralsy = {
|
||||
/*MFC1KSchema Noralsy = {
|
||||
.name = "Noralsy",
|
||||
.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
|
||||
}
|
||||
};
|
||||
.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}};
|
||||
|
||||
MFC1KSchema InfiHexact = {.name = "Infineon/Hexact",
|
||||
.trigger = 0x484558414354,
|
||||
.keysA = {0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
|
||||
0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
|
||||
0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
|
||||
0x484558414354
|
||||
},
|
||||
0x484558414354},
|
||||
.keysB = {0xa22ae129c013, 0x49fae4e3849f, 0x38fcf33072e0, 0x8ad5517b4b18, 0x509359f131b1,
|
||||
0x6c78928e1317, 0xaa0720018738, 0xa6cac2886412, 0x62d0c424ed8e, 0xe64a986a5d94,
|
||||
0x8fa1d601d0a2, 0x89347350bd36, 0x66d2b7dc39ef, 0x6bc1e1ae547d, 0x22729a9bd40f
|
||||
}
|
||||
};
|
||||
0x8fa1d601d0a2, 0x89347350bd36, 0x66d2b7dc39ef, 0x6bc1e1ae547d, 0x22729a9bd40f}};
|
||||
*/
|
||||
|
||||
MFC1KSchema UrmetCaptive = {
|
||||
/*MFC1KSchema UrmetCaptive = {
|
||||
.name = "Urmet Captive",
|
||||
.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
|
||||
}
|
||||
};
|
||||
.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}};
|
||||
*/
|
||||
|
||||
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() {
|
||||
SpinOff(0);
|
||||
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]);
|
||||
|
||||
// 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
|
||||
// mode
|
||||
// unoptimized mount operations we should manage at out level the mount status before and after the whole
|
||||
// standalone mode
|
||||
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.
|
||||
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() {
|
||||
StandAloneMode();
|
||||
|
||||
add_schema(Schemas, Noralsy, &total_schemas);
|
||||
add_schema(Schemas, InfiHexact, &total_schemas);
|
||||
add_schema(Schemas, UrmetCaptive, &total_schemas);
|
||||
|
||||
// add_schema(Schemas, Noralsy, &total_schemas);
|
||||
// add_schema(Schemas, InfiHexact, &total_schemas);
|
||||
// add_schema_from_json_in_spiffs((char *)HFCOLIN_URMETCAPTIVE_JSON);
|
||||
// add_schema(Schemas, UrmetCaptive, &total_schemas);
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
currline = 20;
|
||||
|
@ -242,9 +395,7 @@ void RunMod() {
|
|||
// French VIGIK system @2017
|
||||
//----------------------------
|
||||
|
||||
#define STKEYS 37
|
||||
|
||||
const uint64_t mfKeys[STKEYS] = {
|
||||
const uint64_t mfKeys[] = {
|
||||
0xffffffffffff, // TRANSPORTS
|
||||
0x000000000000, // Blankkey
|
||||
0x484558414354, // INFINEONON A / 0F SEC B / INTRATONE / HEXACT...
|
||||
|
@ -285,8 +436,8 @@ void RunMod() {
|
|||
};
|
||||
|
||||
// Can remember something like that in case of Bigbuf
|
||||
keyBlock = BigBuf_malloc(STKEYS * 6);
|
||||
int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t);
|
||||
keyBlock = BigBuf_malloc(ARRAYLEN(mfKeys) * 6);
|
||||
int mfKeysCnt = ARRAYLEN(mfKeys);
|
||||
|
||||
for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) {
|
||||
num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6));
|
||||
|
@ -325,6 +476,8 @@ void RunMod() {
|
|||
currfline = 24;
|
||||
cjSetCursLeft();
|
||||
|
||||
add_schemas_from_json_in_spiffs((char *)HFCOLIN_SCHEMAS_JSON);
|
||||
|
||||
failtag:
|
||||
|
||||
vtsend_cursor_position_save(NULL);
|
||||
|
@ -419,8 +572,8 @@ failtag:
|
|||
if (key == -1) {
|
||||
err = 1;
|
||||
allKeysFound = false;
|
||||
// used in portable imlementation on microcontroller: it reports back the fail and open the standalone
|
||||
// lock reply_old(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0);
|
||||
// used in portable imlementation on microcontroller: it reports back the fail and open the
|
||||
// standalone lock reply_old(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0);
|
||||
break;
|
||||
} else if (key == -2) {
|
||||
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) {
|
||||
flags |= FLAG_UID_IN_EMUL;
|
||||
//}
|
||||
Mifare1ksim(flags | FLAG_MF_1K, 0, cjuid);
|
||||
Mifare1ksim(flags | FLAG_MF_1K, 0, cjuid, 0, 0);
|
||||
LED_C_OFF();
|
||||
SpinOff(50);
|
||||
vtsend_cursor_position_restore(NULL);
|
||||
|
|
|
@ -16,22 +16,6 @@
|
|||
#ifndef __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 _XGREEN_ "\x1b[32m"
|
||||
#define _XYELLOW_ "\x1b[33m"
|
||||
|
|
|
@ -33,7 +33,21 @@ on a blank card.
|
|||
## 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];
|
||||
uint32_t cuid;
|
||||
|
@ -262,7 +276,7 @@ void RunMod() {
|
|||
keys in keyBlock's memory space .
|
||||
*/
|
||||
keyBlock = BigBuf_malloc(stKeyBlock * 6);
|
||||
int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t);
|
||||
int mfKeysCnt = ARRAYLEN(mfKeys);
|
||||
|
||||
for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) {
|
||||
num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6));
|
||||
|
@ -400,7 +414,7 @@ void RunMod() {
|
|||
simflags = FLAG_4B_UID_IN_DATA;
|
||||
break;
|
||||
}
|
||||
Mifare1ksim(simflags | FLAG_MF_1K, 0, uid);
|
||||
Mifare1ksim(simflags | FLAG_MF_1K, 0, uid, 0, 0);
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "hf_young.h"
|
||||
#include "common.h"
|
||||
#include "standalone.h" // standalone definitions
|
||||
#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 {
|
||||
uint8_t uid[10];
|
||||
|
@ -138,18 +151,18 @@ void RunMod() {
|
|||
SpinDelay(500);
|
||||
// Begin clone function here:
|
||||
/* 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:
|
||||
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.
|
||||
|
||||
The get and set commands are handled in this file:
|
||||
// Work with "magic Chinese" card
|
||||
case CMD_MIFARE_CSETBLOCK:
|
||||
case CMD_HF_MIFARE_CSETBL:
|
||||
MifareCSetBlock(c->arg[0], c->arg[1], c->d.asBytes);
|
||||
break;
|
||||
case CMD_MIFARE_CGETBLOCK:
|
||||
case CMD_HF_MIFARE_CGETBL:
|
||||
MifareCGetBlock(c->arg[0], c->arg[1], c->d.asBytes);
|
||||
break;
|
||||
|
||||
|
|
|
@ -24,8 +24,19 @@
|
|||
//-----------------------------------------------------------------------------------
|
||||
// main code for LF aka HID corporate brutefore by Federico Dotta & Maurizio Agazzini
|
||||
//-----------------------------------------------------------------------------------
|
||||
#include "standalone.h" // standalone definitions
|
||||
#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) {
|
||||
DbpString(" LF HID corporate 1000 bruteforce - aka Corporatebrute (Federico dotta & Maurizio Agazzini)");
|
||||
}
|
||||
|
|
|
@ -14,10 +14,7 @@
|
|||
#ifndef __LF_HIDBRUTE_H
|
||||
#define __LF_HIDBRUTE_H
|
||||
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include "apps.h" // debugstatements, lfops?
|
||||
|
||||
#define OPTS 3
|
||||
#include <stdint.h>
|
||||
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
#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) {
|
||||
DbpString(" LF skeleton mode - aka IceRun (iceman)");
|
||||
|
|
|
@ -9,7 +9,16 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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) {
|
||||
DbpString(" LF HID ProxII bruteforce - aka Proxbrute (Brad Antoniewicz)");
|
||||
|
|
|
@ -8,7 +8,16 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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) {
|
||||
DbpString(" LF HID26 standalone - aka SamyRun (Samy Kamkar)");
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "standalone.h" // standalone definitions
|
||||
#include "apps.h" // debug statements
|
||||
|
||||
#include "dbprint.h"
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString(" No standalone mode present");
|
||||
|
|
|
@ -11,9 +11,6 @@
|
|||
#ifndef __STANDALONE_H
|
||||
#define __STANDALONE_H
|
||||
|
||||
#include <stdbool.h> // for bool
|
||||
#include <inttypes.h> // PRIu64
|
||||
|
||||
void RunMod();
|
||||
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
|
||||
#define __BUZZER_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "util.h"
|
||||
#include "common.h"
|
||||
|
||||
#define n_2_7khz 185
|
||||
#define note_1 956
|
||||
|
@ -27,24 +24,3 @@ void Ring_ALL(uint16_t count);
|
|||
void Ring_Little_Star(uint16_t count);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -30,7 +30,10 @@
|
|||
* @brief
|
||||
*/
|
||||
#include "cmd.h"
|
||||
#include "usb_cdc.h"
|
||||
#include "usart.h"
|
||||
#include "crc16.h"
|
||||
#include "string.h"
|
||||
|
||||
// Flags to tell where to add CRC on sent replies
|
||||
bool reply_with_crc_on_usb = false;
|
|
@ -35,14 +35,6 @@
|
|||
|
||||
#include "common.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
|
||||
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_usb;
|
||||
|
||||
extern void Dbprintf(const char *fmt, ...);
|
||||
#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;}
|
||||
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);
|
||||
|
||||
#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 "string.h"
|
||||
|
||||
const uint8_t sbox[256] = {
|
||||
/* S-box 1 */
|
||||
|
|
|
@ -27,8 +27,7 @@
|
|||
#ifndef __DES_H_
|
||||
#define __DES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
|
||||
/* 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 */
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#ifndef __DESFIRE_H
|
||||
#define __DESFIRE_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include "mbedtls/aes.h"
|
||||
#include "common.h"
|
||||
#include "mifare.h"
|
||||
|
||||
#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
|
||||
* May 2005
|
||||
*/
|
||||
#include <string.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 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 "string.h"
|
||||
|
||||
static inline void update_key_schedules(desfirekey_t key);
|
||||
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
#ifndef __DESFIRE_KEY_INCLUDED
|
||||
#define __DESFIRE_KEY_INCLUDED
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "iso14443a.h"
|
||||
#include "common.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_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);
|
||||
|
@ -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);
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,8 +12,7 @@
|
|||
#ifndef __EMVCARD_H
|
||||
#define __EMVCARD_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "common.h"
|
||||
|
||||
//structure to hold received/set tag values
|
||||
//variable data inputs have length specifiers
|
14
armsrc/epa.c
14
armsrc/epa.c
|
@ -12,6 +12,16 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#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
|
||||
// use regular (1x) speed in both directions
|
||||
// CRC is already included
|
||||
|
@ -470,14 +480,14 @@ void EPA_PACE_Replay(PacketCommandNG *c) {
|
|||
uint8_t response_apdu[300] = {0};
|
||||
|
||||
// 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();
|
||||
func_return = EPA_APDU(apdus_replay[i].data,
|
||||
apdu_lengths_replay[i],
|
||||
response_apdu);
|
||||
timings[i] = GetCountUS();
|
||||
// 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
|
||||
|| response_apdu[func_return - 4] != 0x90
|
||||
|| response_apdu[func_return - 3] != 0x00)) {
|
||||
|
|
10
armsrc/epa.h
10
armsrc/epa.h
|
@ -11,9 +11,8 @@
|
|||
#ifndef __EPA_H
|
||||
#define __EPA_H
|
||||
|
||||
#include "cmd.h"
|
||||
#include "iso14443a.h"
|
||||
#include "iso14443b.h"
|
||||
#include "common.h"
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
// this struct is used by EPA_Parse_CardAccess and contains info about the
|
||||
// PACE protocol supported by the chip
|
||||
|
@ -23,8 +22,6 @@ typedef struct {
|
|||
uint8_t parameter_id;
|
||||
} pace_version_info_t;
|
||||
|
||||
// note: EPA_PACE_Collect_Nonce and EPA_PACE_Replay are declared in apps.h
|
||||
|
||||
// general functions
|
||||
void EPA_Finish();
|
||||
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_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 */
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "felica.h"
|
||||
#include "proxmark3_arm.h"
|
||||
#include "BigBuf.h"
|
||||
#include "util.h"
|
||||
#include "usb_cdc.h" // for usb_poll_validate_length
|
||||
#include "protocols.h"
|
||||
#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
|
||||
// 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
|
||||
# define FELICA_REQUEST_GUARD_TIME (6800/16 + 1)
|
||||
#endif
|
||||
|
@ -746,7 +751,7 @@ void felica_dump_lite_s() {
|
|||
// for (c=0; c < 8; c++)
|
||||
// ndef[c] = FelicaFrame.framebytes[c+4];
|
||||
|
||||
for (blknum = 0; blknum < sizeof(liteblks);) {
|
||||
for (blknum = 0; blknum < ARRAYLEN(liteblks);) {
|
||||
|
||||
// block to read.
|
||||
BuildFliteRdblk(ndef, 1, &liteblks[blknum]);
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Samy Kamkar, 2011, 2012
|
||||
// Brad antoniewicz 2011
|
||||
// Christian Herrmann, 2017
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
// StandAlone Mod
|
||||
// Definitions internal to the app source.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef __FELICA_H
|
||||
#define __FELICA_H
|
||||
|
||||
#ifndef __LF_PROXBRUTE_H
|
||||
#define __LF_PROXBRUTE_H
|
||||
#include "common.h"
|
||||
#include "cmd.h"
|
||||
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include "apps.h" // debugstatements, lfops?
|
||||
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();
|
||||
|
||||
#define OPTS 2
|
||||
|
||||
#endif /* __LF_PROXBRUTE_H */
|
||||
#endif
|
|
@ -1,6 +1,11 @@
|
|||
#include "flashmem.h"
|
||||
#include "pmflash.h"
|
||||
|
||||
#include "proxmark3_arm.h"
|
||||
#include "ticks.h"
|
||||
#include "dbprint.h"
|
||||
#include "string.h"
|
||||
|
||||
/* here: use NCPS2 @ PA10: */
|
||||
#define SPI_CSR_NUM 2
|
||||
#define SPI_PCS(npcs) ((~(1 << (npcs)) & 0xF) << 16)
|
||||
|
@ -16,7 +21,7 @@ uint32_t FLASHMEM_SPIBAUDRATE = FLASH_BAUD;
|
|||
|
||||
void FlashmemSetSpiBaudrate(uint32_t baudrate) {
|
||||
FLASHMEM_SPIBAUDRATE = baudrate;
|
||||
Dbprintf("Spi Baudrate : %dMhz", FLASHMEM_SPIBAUDRATE / 1000000);
|
||||
Dbprintf("Spi Baudrate : %dMHz", FLASHMEM_SPIBAUDRATE / 1000000);
|
||||
}
|
||||
|
||||
// initialize
|
||||
|
@ -563,25 +568,28 @@ void Flashmem_print_info(void) {
|
|||
uint8_t keysum[2];
|
||||
uint16_t num;
|
||||
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
uint16_t isok = Flash_ReadDataCont(DEFAULT_MF_KEYS_OFFSET, keysum, 2);
|
||||
if (isok == 2) {
|
||||
num = ((keysum[1] << 8) | keysum[0]);
|
||||
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);
|
||||
if (isok == 2) {
|
||||
num = ((keysum[1] << 8) | keysum[0]);
|
||||
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);
|
||||
if (isok == 2) {
|
||||
num = ((keysum[1] << 8) | keysum[0]);
|
||||
if (num != 0xFFFF && num != 0x0)
|
||||
Dbprintf(" iClass................"_YELLOW_("%d")"keys", num);
|
||||
Dbprintf(" iClass.................."_YELLOW_("%d")"keys", num);
|
||||
}
|
||||
|
||||
FlashStop();
|
||||
|
|
|
@ -28,9 +28,7 @@
|
|||
#ifndef __FLASHMEM_H
|
||||
#define __FLASHMEM_H
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "ticks.h"
|
||||
#include "common.h"
|
||||
|
||||
// Used Command
|
||||
#define ID 0x90
|
||||
|
@ -102,7 +100,6 @@
|
|||
#define MAX_BLOCKS 4
|
||||
#define MAX_SECTORS 16
|
||||
|
||||
#define MCK 48000000
|
||||
//#define FLASH_BAUD 24000000
|
||||
#define FLASH_MINFAST 24000000 //33000000
|
||||
#define FLASH_BAUD MCK/2
|
||||
|
@ -112,7 +109,6 @@
|
|||
#define FASTFLASH (FLASHMEM_SPIBAUDRATE > FLASH_MINFAST)
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
|
||||
void Dbprintf(const char *fmt, ...);
|
||||
|
||||
void FlashmemSetSpiBaudrate(uint32_t baudrate);
|
||||
bool FlashInit();
|
||||
|
|
|
@ -11,6 +11,15 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#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
|
||||
static int downloaded_bitstream = 0;
|
||||
|
@ -81,7 +90,7 @@ void SetupSpi(int mode) {
|
|||
AT91C_BASE_SPI->SPI_CSR[0] =
|
||||
(1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
|
||||
(1 << 16) | // Delay Before SPCK (1 MCK period)
|
||||
(6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
|
||||
(6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24MHz/6 = 4M baud
|
||||
AT91C_SPI_BITS_16 | // Bits per Transfer (16 bits)
|
||||
(0 << 3) | // Chip Select inactive after transfer
|
||||
AT91C_SPI_NCPHA | // Clock Phase data captured on leading edge, changes on following edge
|
||||
|
@ -101,7 +110,7 @@ void SetupSpi(int mode) {
|
|||
AT91C_BASE_SPI->SPI_CSR[2] =
|
||||
( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
|
||||
( 1 << 16) | // Delay Before SPCK (1 MCK period)
|
||||
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
|
||||
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24MHz/6 = 4M baud
|
||||
AT91C_SPI_BITS_9 | // Bits per Transfer (9 bits)
|
||||
( 0 << 3) | // Chip Select inactive after transfer
|
||||
( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge
|
||||
|
@ -153,8 +162,7 @@ void FpgaSetupSsc(void) {
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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
|
||||
// ourselves, not to another buffer). The stuff to manipulate those buffers
|
||||
// is in apps.h, because it should be inlined, for speed.
|
||||
// ourselves, not to another buffer).
|
||||
//-----------------------------------------------------------------------------
|
||||
bool FpgaSetupSscDma(uint8_t *buf, int len) {
|
||||
if (buf == NULL) return false;
|
||||
|
@ -395,6 +403,8 @@ void FpgaDownloadAndGo(int bitstream_version) {
|
|||
if (downloaded_bitstream == bitstream_version)
|
||||
return;
|
||||
|
||||
// Send waiting time extension request as this will take a while
|
||||
send_wtx(1500);
|
||||
z_stream compressed_fpga_stream;
|
||||
uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00};
|
||||
|
||||
|
|
|
@ -12,32 +12,10 @@
|
|||
#ifndef __FPGALOADER_H
|
||||
#define __FPGALOADER_H
|
||||
|
||||
#include <stdint.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
|
||||
#include "common.h"
|
||||
|
||||
|
||||
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 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
|
||||
#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_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
|
||||
|
|
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 "apps.h"
|
||||
#include "proxmark3_arm.h"
|
||||
#include "BigBuf.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "ticks.h"
|
||||
#include "dbprint.h"
|
||||
#include "util.h"
|
||||
#include "usb_cdc.h" // for usb_poll_validate_length
|
||||
|
||||
static void RAMFUNC optimizedSniff(void);
|
||||
|
||||
|
|
|
@ -1,22 +1,16 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Samy Kamkar 2012
|
||||
// Christian Herrmann, 2017
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
// StandAlone Mod
|
||||
// Definitions internal to the app source.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef __HFSNOOP_H
|
||||
#define __HFSNOOP_H
|
||||
|
||||
#ifndef __LF_SAMYRUN_H
|
||||
#define __LF_SAMYRUN_H
|
||||
void HfSniff(int, int);
|
||||
|
||||
//#include <stdbool.h> // for bool
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include "apps.h" // debugstatements, lfops?
|
||||
|
||||
|
||||
#define OPTS 2
|
||||
|
||||
#endif /* __LF_SAMYRUN_H */
|
||||
#endif
|
|
@ -20,15 +20,20 @@
|
|||
|
||||
#include "hitag2.h"
|
||||
#include "hitag2_crypto.h"
|
||||
#include "hitag.h"
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "util.h"
|
||||
#include "string.h"
|
||||
#include "proxmark3_arm.h"
|
||||
#include "cmd.h"
|
||||
#include "BigBuf.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "ticks.h"
|
||||
#include "dbprint.h"
|
||||
#include "util.h"
|
||||
|
||||
// Successful crypto auth
|
||||
static bool bCrypto;
|
||||
// Is in auth stage
|
||||
static bool bAuthenticating;
|
||||
// Successful password auth
|
||||
static bool bPwd;
|
||||
static bool bSuccessful;
|
||||
|
||||
|
@ -272,8 +277,8 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_
|
|||
break;
|
||||
}
|
||||
|
||||
// LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false);
|
||||
// LogTrace(tx, nbytes(txlen), 0, 0, NULL, true);
|
||||
// LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false);
|
||||
// LogTrace(tx, nbytes(txlen), 0, 0, NULL, true);
|
||||
|
||||
if (tag.crypto_active) {
|
||||
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
|
||||
*txlen = 0;
|
||||
|
||||
if (bPwd && write) {
|
||||
if (bPwd && !bAuthenticating && write) {
|
||||
if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
|
||||
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
|
||||
case 32: {
|
||||
// stage 1, got UID
|
||||
if (!bPwd) {
|
||||
*txlen = 32;
|
||||
memcpy(tx, password, 4);
|
||||
bPwd = true;
|
||||
memcpy(tag.sectors[blocknr], rx, 4);
|
||||
blocknr++;
|
||||
bAuthenticating = true;
|
||||
memcpy(tx, password, 4);
|
||||
*txlen = 32;
|
||||
} else {
|
||||
|
||||
if (blocknr == 1) {
|
||||
//store password in block1, the TAG answers with Block3, but we need the password in memory
|
||||
memcpy(tag.sectors[blocknr], tx, 4);
|
||||
} else {
|
||||
// stage 2, got config byte+password TAG, discard as will read later
|
||||
if (bAuthenticating) {
|
||||
bAuthenticating = false;
|
||||
if (write) {
|
||||
if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// stage 2+, got data block
|
||||
else {
|
||||
memcpy(tag.sectors[blocknr], rx, 4);
|
||||
blocknr++;
|
||||
}
|
||||
|
||||
blocknr++;
|
||||
if (blocknr > 7) {
|
||||
DbpString("Read succesful!");
|
||||
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
|
||||
case 32: {
|
||||
// stage 1, got UID
|
||||
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;
|
||||
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));
|
||||
cipher_state = _hitag2_init(REV64(ui64key), REV32(ui32uid), 0);
|
||||
// PRN
|
||||
memset(tx, 0x00, 4);
|
||||
// Secret data
|
||||
memset(tx + 4, 0xff, 4);
|
||||
hitag2_cipher_transcrypt(&cipher_state, tx + 4, 4, 0);
|
||||
*txlen = 64;
|
||||
bCrypto = true;
|
||||
bAuthenticating = true;
|
||||
} else {
|
||||
// Check if we received answer tag (at)
|
||||
// stage 2, got config byte+password TAG, discard as will read later
|
||||
if (bAuthenticating) {
|
||||
bAuthenticating = false;
|
||||
if (write) {
|
||||
|
@ -509,7 +524,9 @@ static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *
|
|||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
// stage 2+, got data block
|
||||
else {
|
||||
// Store the received block
|
||||
memcpy(tag.sectors[blocknr], rx, 4);
|
||||
blocknr++;
|
||||
|
@ -692,7 +709,7 @@ void SniffHitag(void) {
|
|||
|
||||
StopTicks();
|
||||
|
||||
// int frame_count;
|
||||
// int frame_count;
|
||||
int response;
|
||||
int overflow;
|
||||
bool rising_edge;
|
||||
|
@ -750,7 +767,7 @@ void SniffHitag(void) {
|
|||
|
||||
// Reset the received frame, frame count and timing info
|
||||
memset(rx, 0x00, sizeof(rx));
|
||||
// frame_count = 0;
|
||||
// frame_count = 0;
|
||||
response = 0;
|
||||
overflow = 0;
|
||||
reader_frame = false;
|
||||
|
@ -857,7 +874,7 @@ void SniffHitag(void) {
|
|||
|
||||
// Check if frame was captured
|
||||
if (rxlen > 0) {
|
||||
// frame_count++;
|
||||
// frame_count++;
|
||||
LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame);
|
||||
|
||||
// Check if we recognize a valid authentication attempt
|
||||
|
@ -907,7 +924,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) {
|
|||
|
||||
StopTicks();
|
||||
|
||||
// int frame_count = 0;
|
||||
// int frame_count = 0;
|
||||
int response = 0, overflow = 0;
|
||||
uint8_t rx[HITAG_FRAME_LEN];
|
||||
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
|
||||
// and analog mux selection.
|
||||
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);
|
||||
|
||||
// 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
|
||||
if (rxlen > 4) {
|
||||
// frame_count++;
|
||||
// frame_count++;
|
||||
LogTrace(rx, nbytes(rxlen), response, response, NULL, true);
|
||||
|
||||
// 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();
|
||||
|
||||
// int frame_count = 0;
|
||||
// int frame_count = 0;
|
||||
int response = 0;
|
||||
uint8_t rx[HITAG_FRAME_LEN];
|
||||
size_t rxlen = 0;
|
||||
|
@ -1104,6 +1121,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
|||
memcpy(password, htd->pwd.password, 4);
|
||||
blocknr = 0;
|
||||
bPwd = false;
|
||||
bAuthenticating = false;
|
||||
break;
|
||||
}
|
||||
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
|
||||
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);
|
||||
|
||||
// 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
|
||||
if (rxlen > 0) {
|
||||
// frame_count++;
|
||||
// frame_count++;
|
||||
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
|
||||
if (txlen > 0) {
|
||||
// frame_count++;
|
||||
// frame_count++;
|
||||
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();
|
||||
|
||||
// int frame_count = 0;
|
||||
// int frame_count = 0;
|
||||
int response = 0;
|
||||
uint8_t rx[HITAG_FRAME_LEN];
|
||||
size_t rxlen = 0;
|
||||
|
@ -1405,6 +1423,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
|||
Dbhexdump(4, password, false);
|
||||
blocknr = page;
|
||||
bPwd = false;
|
||||
bAuthenticating = false;
|
||||
writestate = WRITE_STATE_START;
|
||||
}
|
||||
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
|
||||
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);
|
||||
|
||||
// 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
|
||||
if (rxlen > 0) {
|
||||
// frame_count++;
|
||||
// frame_count++;
|
||||
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
|
||||
if (txlen > 0) {
|
||||
// frame_count++;
|
||||
// frame_count++;
|
||||
LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,7 @@
|
|||
#ifndef _HITAG2_H_
|
||||
#define _HITAG2_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "common.h"
|
||||
#include "hitag.h"
|
||||
|
||||
void SniffHitag(void);
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "hitag2_crypto.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "string.h"
|
||||
|
||||
/* 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.
|
||||
// For educational purposes only.
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
#ifndef __HITAG2_CRYPTO_H
|
||||
#define __HITAG2_CRYPTO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "string.h"
|
||||
#include "util.h"
|
||||
#include "common.h"
|
||||
|
||||
struct hitag2_tag {
|
||||
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);
|
||||
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) ;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,6 +13,17 @@
|
|||
|
||||
#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_POLYNOM 0x1D
|
||||
|
||||
|
@ -983,7 +994,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) {
|
|||
// and analog mux selection.
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
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);
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
||||
// Disable modulation at default, which means enable the field
|
||||
|
|
|
@ -12,16 +12,9 @@
|
|||
#ifndef _HITAGS_H_
|
||||
#define _HITAGS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "hitag2_crypto.h"
|
||||
#include "common.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 ReadHitagS(hitag_function htf, hitag_data *htd);
|
||||
|
|
|
@ -10,6 +10,14 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#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_SCL AT91C_PIO_PA5
|
||||
#define GPIO_SDA AT91C_PIO_PA7
|
||||
|
@ -26,7 +34,7 @@
|
|||
|
||||
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
|
||||
// timer.
|
||||
// I2CSpinDelayClk(4) = 12.31us
|
||||
|
@ -41,7 +49,7 @@ void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {
|
|||
|
||||
#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) {
|
||||
|
||||
DbpString("Performing i2c bus recovery");
|
|
@ -1,10 +1,7 @@
|
|||
#ifndef __I2C_H
|
||||
#define __I2C_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "BigBuf.h"
|
||||
#include "common.h"
|
||||
#include "mifare.h"
|
||||
|
||||
#define I2C_DEVICE_ADDRESS_BOOT 0xB0
|
||||
|
@ -18,7 +15,6 @@
|
|||
#define I2C_DEVICE_CMD_GETVERSION 0x06
|
||||
#define I2C_DEVICE_CMD_SEND_T0 0x07
|
||||
|
||||
|
||||
void I2C_recovery(void);
|
||||
void I2C_init(void);
|
||||
void I2C_Reset(void);
|
||||
|
@ -48,4 +44,5 @@ void SmartCardSetBaud(uint64_t arg0);
|
|||
void SmartCardSetClock(uint64_t arg0);
|
||||
void I2C_print_status(void);
|
||||
int I2C_get_version(uint8_t *maj, uint8_t *min);
|
||||
|
||||
#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"
|
||||
// Needed for CRC in emulation mode;
|
||||
// same construction as in ISO 14443;
|
||||
// different initial value (CRC_ICLASS)
|
||||
#include "crc16.h"
|
||||
#include "protocols.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 SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay);
|
||||
|
@ -92,21 +101,21 @@ typedef struct {
|
|||
int bitBuffer;
|
||||
int dropPosition;
|
||||
uint8_t *output;
|
||||
} tUart;
|
||||
} tUartIc;
|
||||
*/
|
||||
typedef struct {
|
||||
enum {
|
||||
DEMOD_UNSYNCD,
|
||||
DEMOD_START_OF_COMMUNICATION,
|
||||
DEMOD_START_OF_COMMUNICATION2,
|
||||
DEMOD_START_OF_COMMUNICATION3,
|
||||
DEMOD_SOF_COMPLETE,
|
||||
DEMOD_MANCHESTER_D,
|
||||
DEMOD_MANCHESTER_E,
|
||||
DEMOD_END_OF_COMMUNICATION,
|
||||
DEMOD_END_OF_COMMUNICATION2,
|
||||
DEMOD_MANCHESTER_F,
|
||||
DEMOD_ERROR_WAIT
|
||||
DEMOD_IC_UNSYNCD,
|
||||
DEMOD_IC_START_OF_COMMUNICATION,
|
||||
DEMOD_IC_START_OF_COMMUNICATION2,
|
||||
DEMOD_IC_START_OF_COMMUNICATION3,
|
||||
DEMOD_IC_SOF_COMPLETE,
|
||||
DEMOD_IC_MANCHESTER_D,
|
||||
DEMOD_IC_MANCHESTER_E,
|
||||
DEMOD_IC_END_OF_COMMUNICATION,
|
||||
DEMOD_IC_END_OF_COMMUNICATION2,
|
||||
DEMOD_IC_MANCHESTER_F,
|
||||
DEMOD_IC_ERROR_WAIT
|
||||
} state;
|
||||
int bitCount;
|
||||
int posCount;
|
||||
|
@ -125,7 +134,7 @@ typedef struct {
|
|||
SUB_BOTH
|
||||
} sub;
|
||||
uint8_t *output;
|
||||
} tDemod;
|
||||
} tDemodIc;
|
||||
|
||||
/*
|
||||
* Abrasive's uart implementation
|
||||
|
@ -138,8 +147,13 @@ typedef struct {
|
|||
bool frame_done;
|
||||
uint8_t *buf;
|
||||
int len;
|
||||
} tUart;
|
||||
static tUart Uart;
|
||||
} tUartIc;
|
||||
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) {
|
||||
Uart.frame_done = false;
|
||||
|
@ -499,8 +513,8 @@ static RAMFUNC int OutOfNDecoding(int bit) {
|
|||
//=============================================================================
|
||||
// Manchester
|
||||
//=============================================================================
|
||||
static tDemod Demod;
|
||||
static void DemodReset() {
|
||||
static tDemodIc Demod;
|
||||
static void DemodIcReset() {
|
||||
Demod.bitCount = 0;
|
||||
Demod.posCount = 0;
|
||||
Demod.syncBit = 0;
|
||||
|
@ -512,11 +526,11 @@ static void DemodReset() {
|
|||
Demod.samples = 0;
|
||||
Demod.len = 0;
|
||||
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;
|
||||
DemodReset();
|
||||
DemodIcReset();
|
||||
}
|
||||
|
||||
// UART debug
|
||||
|
@ -592,7 +606,7 @@ static RAMFUNC int ManchesterDecoding_iclass(uint32_t v) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (Demod.state == DEMOD_UNSYNCD) {
|
||||
if (Demod.state == DEMOD_IC_UNSYNCD) {
|
||||
Demod.output[Demod.len] = 0xfa;
|
||||
Demod.syncBit = 0;
|
||||
//Demod.samples = 0;
|
||||
|
@ -620,7 +634,7 @@ static RAMFUNC int ManchesterDecoding_iclass(uint32_t v) {
|
|||
|
||||
if (Demod.syncBit) {
|
||||
Demod.len = 0;
|
||||
Demod.state = DEMOD_START_OF_COMMUNICATION;
|
||||
Demod.state = DEMOD_IC_START_OF_COMMUNICATION;
|
||||
Demod.sub = SUB_FIRST_HALF;
|
||||
Demod.bitCount = 0;
|
||||
Demod.shiftReg = 0;
|
||||
|
@ -644,12 +658,12 @@ static RAMFUNC int ManchesterDecoding_iclass(uint32_t v) {
|
|||
}
|
||||
// SOF must be long burst... otherwise stay unsynced!!!
|
||||
if (!(Demod.buffer & Demod.syncBit) || !(Demod.buffer2 & Demod.syncBit))
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
Demod.state = DEMOD_IC_UNSYNCD;
|
||||
|
||||
} else {
|
||||
// SOF must be long burst... otherwise stay unsynced!!!
|
||||
if (!(Demod.buffer2 & Demod.syncBit) || !(Demod.buffer3 & Demod.syncBit)) {
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
Demod.state = DEMOD_IC_UNSYNCD;
|
||||
error = 0x88;
|
||||
uart_debug(error, bit);
|
||||
return false;
|
||||
|
@ -682,74 +696,74 @@ static RAMFUNC int ManchesterDecoding_iclass(uint32_t v) {
|
|||
}
|
||||
|
||||
if (Demod.sub == SUB_NONE) {
|
||||
if (Demod.state == DEMOD_SOF_COMPLETE) {
|
||||
if (Demod.state == DEMOD_IC_SOF_COMPLETE) {
|
||||
Demod.output[Demod.len] = 0x0f;
|
||||
Demod.len++;
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
Demod.state = DEMOD_IC_UNSYNCD;
|
||||
return true;
|
||||
} else {
|
||||
Demod.state = DEMOD_ERROR_WAIT;
|
||||
Demod.state = DEMOD_IC_ERROR_WAIT;
|
||||
error = 0x33;
|
||||
}
|
||||
}
|
||||
|
||||
switch (Demod.state) {
|
||||
|
||||
case DEMOD_START_OF_COMMUNICATION:
|
||||
case DEMOD_IC_START_OF_COMMUNICATION:
|
||||
if (Demod.sub == SUB_BOTH) {
|
||||
|
||||
Demod.state = DEMOD_START_OF_COMMUNICATION2;
|
||||
Demod.state = DEMOD_IC_START_OF_COMMUNICATION2;
|
||||
Demod.posCount = 1;
|
||||
Demod.sub = SUB_NONE;
|
||||
} else {
|
||||
Demod.output[Demod.len] = 0xab;
|
||||
Demod.state = DEMOD_ERROR_WAIT;
|
||||
Demod.state = DEMOD_IC_ERROR_WAIT;
|
||||
error = 0xd2;
|
||||
}
|
||||
break;
|
||||
|
||||
case DEMOD_START_OF_COMMUNICATION2:
|
||||
case DEMOD_IC_START_OF_COMMUNICATION2:
|
||||
if (Demod.sub == SUB_SECOND_HALF) {
|
||||
Demod.state = DEMOD_START_OF_COMMUNICATION3;
|
||||
Demod.state = DEMOD_IC_START_OF_COMMUNICATION3;
|
||||
} else {
|
||||
Demod.output[Demod.len] = 0xab;
|
||||
Demod.state = DEMOD_ERROR_WAIT;
|
||||
Demod.state = DEMOD_IC_ERROR_WAIT;
|
||||
error = 0xd3;
|
||||
}
|
||||
break;
|
||||
|
||||
case DEMOD_START_OF_COMMUNICATION3:
|
||||
case DEMOD_IC_START_OF_COMMUNICATION3:
|
||||
if (Demod.sub == SUB_SECOND_HALF) {
|
||||
Demod.state = DEMOD_SOF_COMPLETE;
|
||||
Demod.state = DEMOD_IC_SOF_COMPLETE;
|
||||
} else {
|
||||
Demod.output[Demod.len] = 0xab;
|
||||
Demod.state = DEMOD_ERROR_WAIT;
|
||||
Demod.state = DEMOD_IC_ERROR_WAIT;
|
||||
error = 0xd4;
|
||||
}
|
||||
break;
|
||||
|
||||
case DEMOD_SOF_COMPLETE:
|
||||
case DEMOD_MANCHESTER_D:
|
||||
case DEMOD_MANCHESTER_E:
|
||||
case DEMOD_IC_SOF_COMPLETE:
|
||||
case DEMOD_IC_MANCHESTER_D:
|
||||
case DEMOD_IC_MANCHESTER_E:
|
||||
// OPPOSITE FROM ISO14443 - 11110000 = 0 (1 in 14443)
|
||||
// 00001111 = 1 (0 in 14443)
|
||||
if (Demod.sub == SUB_SECOND_HALF) { // SUB_FIRST_HALF
|
||||
Demod.bitCount++;
|
||||
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
|
||||
Demod.bitCount++;
|
||||
Demod.shiftReg >>= 1;
|
||||
Demod.state = DEMOD_MANCHESTER_E;
|
||||
Demod.state = DEMOD_IC_MANCHESTER_E;
|
||||
} else if (Demod.sub == SUB_BOTH) {
|
||||
Demod.state = DEMOD_MANCHESTER_F;
|
||||
Demod.state = DEMOD_IC_MANCHESTER_F;
|
||||
} else {
|
||||
Demod.state = DEMOD_ERROR_WAIT;
|
||||
Demod.state = DEMOD_IC_ERROR_WAIT;
|
||||
error = 0x55;
|
||||
}
|
||||
break;
|
||||
|
||||
case DEMOD_MANCHESTER_F:
|
||||
case DEMOD_IC_MANCHESTER_F:
|
||||
// Tag response does not need to be a complete byte!
|
||||
if (Demod.len > 0 || Demod.bitCount > 0) {
|
||||
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.state = DEMOD_UNSYNCD;
|
||||
Demod.state = DEMOD_IC_UNSYNCD;
|
||||
return true;
|
||||
} else {
|
||||
Demod.output[Demod.len] = 0xad;
|
||||
Demod.state = DEMOD_ERROR_WAIT;
|
||||
Demod.state = DEMOD_IC_ERROR_WAIT;
|
||||
error = 0x03;
|
||||
}
|
||||
break;
|
||||
|
||||
case DEMOD_ERROR_WAIT:
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
case DEMOD_IC_ERROR_WAIT:
|
||||
Demod.state = DEMOD_IC_UNSYNCD;
|
||||
break;
|
||||
|
||||
default:
|
||||
Demod.output[Demod.len] = 0xdd;
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
Demod.state = DEMOD_IC_UNSYNCD;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -818,10 +832,10 @@ static void iclass_setup_sniff(void) {
|
|||
set_tracing(true);
|
||||
|
||||
// Initialize Demod and Uart structs
|
||||
DemodInit(BigBuf_malloc(ICLASS_BUFFER_SIZE));
|
||||
DemodIcInit(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) {
|
||||
// Print debug information about the buffer sizes
|
||||
|
@ -884,9 +898,17 @@ void RAMFUNC SniffIClass(void) {
|
|||
// 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)
|
||||
// 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();
|
||||
|
||||
if (checked == 1000) {
|
||||
if (BUTTON_PRESS() || data_available()) break;
|
||||
checked = 0;
|
||||
} else {
|
||||
checked++;
|
||||
}
|
||||
|
||||
previous_data <<= 8;
|
||||
previous_data |= *data;
|
||||
|
||||
|
@ -919,7 +941,7 @@ void RAMFUNC SniffIClass(void) {
|
|||
if (Uart.frame_done) {
|
||||
time_stop = GetCountSspClk() - time_0;
|
||||
LogTrace(Uart.buf, Uart.len, time_start, time_stop, NULL, true);
|
||||
DemodReset();
|
||||
DemodIcReset();
|
||||
uart_reset();
|
||||
} else {
|
||||
time_start = GetCountSspClk() - time_0;
|
||||
|
@ -951,12 +973,12 @@ void RAMFUNC SniffIClass(void) {
|
|||
if (ManchesterDecoding_iclass(foo)) {
|
||||
time_stop = GetCountSspClk() - time_0;
|
||||
LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false);
|
||||
DemodReset();
|
||||
DemodIcReset();
|
||||
uart_reset();
|
||||
} else {
|
||||
time_start = GetCountSspClk() - time_0;
|
||||
}
|
||||
TagIsActive = (Demod.state != DEMOD_UNSYNCD);
|
||||
TagIsActive = (Demod.state != DEMOD_IC_UNSYNCD);
|
||||
}
|
||||
tag_byte = 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;
|
||||
(void)b;
|
||||
|
||||
while (!BUTTON_PRESS()) {
|
||||
uint16_t checked = 0;
|
||||
for (;;) {
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
if (checked == 1000) {
|
||||
if (BUTTON_PRESS() || data_available()) return false;
|
||||
checked = 0;
|
||||
} else {
|
||||
checked++;
|
||||
}
|
||||
|
||||
// keep tx buffer in a defined state anyway.
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))
|
||||
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)) {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
//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
|
||||
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
|
||||
goto out;
|
||||
}
|
||||
|
||||
// keyroll 2
|
||||
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
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
// 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 {
|
||||
// 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
|
||||
// Tag CSN
|
||||
|
||||
uint8_t *modulated_response;
|
||||
uint8_t *modulated_response = NULL;
|
||||
int modulated_response_size = 0;
|
||||
uint8_t *trace_data = NULL;
|
||||
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
|
||||
//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
|
||||
//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);
|
||||
SpinDelay(100);
|
||||
|
@ -1436,6 +1467,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
trace_data_size = sizeof(anticoll_data);
|
||||
goto send;
|
||||
}
|
||||
|
||||
if (len == 4) {
|
||||
// block0,1,2,5 is always readable.
|
||||
switch (receivedCmd[1]) {
|
||||
|
@ -1444,13 +1476,13 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
modulated_response_size = resp_csn_len;
|
||||
trace_data = csn_data;
|
||||
trace_data_size = sizeof(csn_data);
|
||||
break;
|
||||
goto send;
|
||||
case 1: // configuration (0c 01)
|
||||
modulated_response = resp_conf;
|
||||
modulated_response_size = resp_conf_len;
|
||||
trace_data = conf_data;
|
||||
trace_data_size = sizeof(conf_data);
|
||||
break;
|
||||
goto send;
|
||||
case 2: // e-purse (0c 02)
|
||||
modulated_response = resp_cc;
|
||||
modulated_response_size = resp_cc_len;
|
||||
|
@ -1460,19 +1492,30 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
if (reader_mac_buf != NULL) {
|
||||
memcpy(reader_mac_buf, card_challenge_data, 8);
|
||||
}
|
||||
break;
|
||||
goto send;
|
||||
case 5:// Application Issuer Area (0c 05)
|
||||
modulated_response = resp_aia;
|
||||
modulated_response_size = resp_aia_len;
|
||||
trace_data = 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;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
goto send;
|
||||
}
|
||||
|
||||
}
|
||||
}//swith
|
||||
}// if 4
|
||||
} else if (receivedCmd[0] == ICLASS_CMD_SELECT) { // 0x81
|
||||
// Reader selects anticollission 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_size = 0;
|
||||
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
|
||||
uint16_t blk = receivedCmd[1];
|
||||
//Take the data...
|
||||
memcpy(data_generic_trace, emulator + (blk << 3), 8);
|
||||
AddCrc(data_generic_trace, 8);
|
||||
memcpy(data_generic_trace, emulator + (receivedCmd[1] << 3), 8 * 4);
|
||||
AddCrc(data_generic_trace, 8 * 4);
|
||||
trace_data = data_generic_trace;
|
||||
trace_data_size = 10;
|
||||
trace_data_size = 34;
|
||||
CodeIClassTagAnswer(trace_data, trace_data_size);
|
||||
memcpy(data_response, ToSend, ToSendMax);
|
||||
modulated_response = data_response;
|
||||
memcpy(modulated_response, ToSend, ToSendMax);
|
||||
modulated_response_size = ToSendMax;
|
||||
goto send;
|
||||
} 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;
|
||||
|
||||
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
|
||||
if ((AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {
|
||||
b = AT91C_BASE_SSC->SSC_RHR;
|
||||
|
@ -1787,7 +1835,7 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples,
|
|||
bool skip = false;
|
||||
|
||||
// Setup UART/DEMOD to receive
|
||||
DemodInit(receivedResponse);
|
||||
DemodIcInit(receivedResponse);
|
||||
|
||||
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;
|
||||
(void)b;
|
||||
|
||||
while (!BUTTON_PRESS()) {
|
||||
uint16_t checked = 0;
|
||||
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
|
||||
if (checked == 1000) {
|
||||
if (BUTTON_PRESS() || data_available()) return false;
|
||||
checked = 0;
|
||||
} else {
|
||||
checked++;
|
||||
}
|
||||
|
||||
// keep tx buffer in a defined state anyway.
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||
|
@ -1993,6 +2050,7 @@ void ReaderIClass(uint8_t arg0) {
|
|||
|
||||
setupIclassReader();
|
||||
|
||||
uint16_t checked = 0;
|
||||
bool userCancelled = BUTTON_PRESS() || data_available();
|
||||
while (!userCancelled) {
|
||||
|
||||
|
@ -2092,7 +2150,13 @@ void ReaderIClass(uint8_t arg0) {
|
|||
}
|
||||
}
|
||||
LED_B_OFF();
|
||||
userCancelled = BUTTON_PRESS() || data_available();
|
||||
|
||||
if (checked == 1000) {
|
||||
userCancelled = BUTTON_PRESS() || data_available();
|
||||
checked = 0;
|
||||
} else {
|
||||
checked++;
|
||||
}
|
||||
}
|
||||
|
||||
if (userCancelled) {
|
||||
|
@ -2222,7 +2286,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac) {
|
|||
switch_off();
|
||||
}
|
||||
|
||||
// not used. ?!? ( CMD_ICLASS_READCHECK)
|
||||
// not used. ?!? ( CMD_HF_ICLASS_READCHECK)
|
||||
// turn off afterwards
|
||||
void iClass_ReadCheck(uint8_t blockno, uint8_t keytype) {
|
||||
uint8_t readcheck[] = { keytype, blockno };
|
||||
|
@ -2286,11 +2350,17 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
|
|||
|
||||
setupIclassReader();
|
||||
|
||||
uint16_t checked = 0;
|
||||
int read_status = 0;
|
||||
uint8_t startup_limit = 10;
|
||||
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);
|
||||
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++) {
|
||||
|
||||
// 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();
|
||||
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 "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
|
||||
static uint32_t iso14a_timeout;
|
||||
// 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;
|
||||
int rsamples = 0;
|
||||
|
@ -25,7 +40,7 @@ static uint8_t iso14_pcb_blocknum = 0;
|
|||
//
|
||||
// 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)
|
||||
// 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)
|
||||
|
@ -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 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.
|
||||
// We accept the following:
|
||||
|
@ -176,12 +191,12 @@ const bool Mod_Miller_LUT[] = {
|
|||
#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x000000F0) >> 4])
|
||||
#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x0000000F)])
|
||||
|
||||
tUart *GetUart() {
|
||||
tUart14a *GetUart14a() {
|
||||
return &Uart;
|
||||
}
|
||||
|
||||
void UartReset(void) {
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
void Uart14aReset(void) {
|
||||
Uart.state = STATE_14A_UNSYNCD;
|
||||
Uart.bitCount = 0;
|
||||
Uart.len = 0; // number of decoded data bytes
|
||||
Uart.parityLen = 0; // number of decoded parity bytes
|
||||
|
@ -194,17 +209,17 @@ void UartReset(void) {
|
|||
Uart.syncBit = 9999;
|
||||
}
|
||||
|
||||
void UartInit(uint8_t *data, uint8_t *par) {
|
||||
void Uart14aInit(uint8_t *data, uint8_t *par) {
|
||||
Uart.output = data;
|
||||
Uart.parity = par;
|
||||
UartReset();
|
||||
Uart14aReset();
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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
|
||||
|
||||
// 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 -= Uart.syncBit;
|
||||
Uart.endTime = Uart.startTime;
|
||||
Uart.state = STATE_START_OF_COMMUNICATION;
|
||||
Uart.state = STATE_14A_START_OF_COMMUNICATION;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) {
|
||||
if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation in both halves - error
|
||||
UartReset();
|
||||
Uart14aReset();
|
||||
} else { // Modulation in first half = Sequence Z = logic "0"
|
||||
if (Uart.state == STATE_MILLER_X) { // error - must not follow after X
|
||||
UartReset();
|
||||
if (Uart.state == STATE_14A_MILLER_X) { // error - must not follow after X
|
||||
Uart14aReset();
|
||||
} else {
|
||||
Uart.bitCount++;
|
||||
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;
|
||||
if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity)
|
||||
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"
|
||||
Uart.bitCount++;
|
||||
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;
|
||||
if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity)
|
||||
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
|
||||
if (Uart.state == STATE_MILLER_Z || Uart.state == STATE_MILLER_Y) { // Y after logic "0" - End of Communication
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
if (Uart.state == STATE_14A_MILLER_Z || Uart.state == STATE_14A_MILLER_Y) { // Y after logic "0" - End of Communication
|
||||
Uart.state = STATE_14A_UNSYNCD;
|
||||
Uart.bitCount--; // last "0" was part of EOC sequence
|
||||
Uart.shiftReg <<= 1; // drop it
|
||||
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) {
|
||||
return true; // we are finished with decoding the raw data sequence
|
||||
} 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
|
||||
UartReset();
|
||||
if (Uart.state == STATE_14A_START_OF_COMMUNICATION) { // error - must not follow directly after SOC
|
||||
Uart14aReset();
|
||||
} else { // a logic "0"
|
||||
Uart.bitCount++;
|
||||
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)
|
||||
Uart.output[Uart.len++] = (Uart.shiftReg & 0xff);
|
||||
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
|
||||
// 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)
|
||||
tDemod Demod;
|
||||
tDemod14a Demod;
|
||||
|
||||
// Lookup-Table to decide if 4 raw bits are a modulation.
|
||||
// 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 IsManchesterModulationNibble2(b) (Mod_Manchester_LUT[(b & 0x000F)])
|
||||
|
||||
tDemod *GetDemod() {
|
||||
tDemod14a *GetDemod14a() {
|
||||
return &Demod;
|
||||
}
|
||||
void DemodReset(void) {
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
void Demod14aReset(void) {
|
||||
Demod.state = DEMOD_14A_UNSYNCD;
|
||||
Demod.len = 0; // number of decoded data bytes
|
||||
Demod.parityLen = 0;
|
||||
Demod.shiftReg = 0; // shiftreg to hold decoded data bits
|
||||
|
@ -367,17 +382,17 @@ void DemodReset(void) {
|
|||
Demod.samples = 0;
|
||||
}
|
||||
|
||||
void DemodInit(uint8_t *data, uint8_t *par) {
|
||||
void Demod14aInit(uint8_t *data, uint8_t *par) {
|
||||
Demod.output = data;
|
||||
Demod.parity = par;
|
||||
DemodReset();
|
||||
Demod14aReset();
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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.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 -= Demod.syncBit;
|
||||
Demod.bitCount = offset; // number of decoded data bits
|
||||
Demod.state = DEMOD_MANCHESTER_DATA;
|
||||
Demod.state = DEMOD_14A_MANCHESTER_DATA;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -455,7 +470,7 @@ RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_t
|
|||
if (Demod.len) {
|
||||
return true; // we are finished with decoding the raw data sequence
|
||||
} 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
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
// Both sides of communication!
|
||||
|
@ -506,10 +597,10 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
|||
bool ReaderIsActive = false;
|
||||
|
||||
// Set up the demodulator for tag -> reader responses.
|
||||
DemodInit(receivedResp, receivedRespPar);
|
||||
Demod14aInit(receivedResp, receivedRespPar);
|
||||
|
||||
// Set up the demodulator for the reader -> tag commands
|
||||
UartInit(receivedCmd, receivedCmdPar);
|
||||
Uart14aInit(receivedCmd, receivedCmdPar);
|
||||
|
||||
DbpString("Starting to sniff");
|
||||
|
||||
|
@ -583,13 +674,13 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
|||
true)) break;
|
||||
}
|
||||
/* ready to receive another command. */
|
||||
UartReset();
|
||||
Uart14aReset();
|
||||
/* reset the demod code, which might have been */
|
||||
/* false-triggered by the commands from the reader. */
|
||||
DemodReset();
|
||||
Demod14aReset();
|
||||
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
|
||||
|
@ -608,13 +699,13 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
|||
if ((!triggered) && (param & 0x01)) triggered = true;
|
||||
|
||||
// ready to receive another response.
|
||||
DemodReset();
|
||||
Demod14aReset();
|
||||
// reset the Miller decoder including its (now outdated) input buffer
|
||||
UartReset();
|
||||
//UartInit(receivedCmd, receivedCmdPar);
|
||||
Uart14aReset();
|
||||
//Uart14aInit(receivedCmd, receivedCmdPar);
|
||||
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);
|
||||
|
||||
// Now run a `software UART` on the stream of incoming samples.
|
||||
UartInit(received, par);
|
||||
Uart14aInit(received, par);
|
||||
|
||||
// clear RXRDY:
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1193,7 +1284,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
|
|||
ar_nr_nonces[index].state = SECOND;
|
||||
|
||||
// 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].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);
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -1553,7 +1644,7 @@ void PrepareDelayedTransfer(uint16_t delay) {
|
|||
//-------------------------------------------------------------------------------------
|
||||
static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing) {
|
||||
|
||||
if (!iso14443a_active)
|
||||
if (!hf_field_active)
|
||||
return;
|
||||
|
||||
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;
|
||||
|
||||
// Now run a 'software UART' on the stream of incoming samples.
|
||||
UartInit(received, par);
|
||||
Uart14aInit(received, par);
|
||||
|
||||
// Clear RXRDY:
|
||||
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
|
||||
// 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;
|
||||
bool GetIso14443aAnswerFromTag_Thinfilm(uint8_t *receivedResponse, uint8_t *received_len) {
|
||||
|
||||
if (!iso14443a_active)
|
||||
if (!hf_field_active)
|
||||
return false;
|
||||
|
||||
// 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);
|
||||
|
||||
// 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:
|
||||
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)) {
|
||||
NextTransferTime = MAX(NextTransferTime, Demod.endTime - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FRAME_DELAY_TIME_PICC_TO_PCD);
|
||||
return true;
|
||||
} else if (c++ > timeout && Demod.state == DEMOD_UNSYNCD) {
|
||||
} else if (c++ > timeout && Demod.state == DEMOD_14A_UNSYNCD) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -2018,6 +2158,7 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par) {
|
|||
return Demod.len;
|
||||
}
|
||||
|
||||
|
||||
// This function misstreats the ISO 14443a anticollision procedure.
|
||||
// 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.
|
||||
|
@ -2363,8 +2504,7 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
|
|||
|
||||
LED_D_OFF();
|
||||
// Signal field is on with the appropriate LED
|
||||
if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD ||
|
||||
fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN)
|
||||
if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD || fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN)
|
||||
LED_D_ON();
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | fpga_minor_mode);
|
||||
|
@ -2374,18 +2514,19 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
|
|||
StartCountSspClk();
|
||||
|
||||
// Prepare the demodulation functions
|
||||
DemodReset();
|
||||
UartReset();
|
||||
Demod14aReset();
|
||||
Uart14aReset();
|
||||
NextTransferTime = 2 * DELAY_ARM2AIR_AS_READER;
|
||||
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);
|
||||
LEDsoff();
|
||||
iso14443a_active = false;
|
||||
hf_field_active = false;
|
||||
}
|
||||
|
||||
/* Peter Fillmore 2015
|
||||
|
@ -2590,7 +2731,7 @@ void ReaderIso14443a(PacketCommandNG *c) {
|
|||
return;
|
||||
|
||||
OUT:
|
||||
iso14443a_off();
|
||||
hf_field_off();
|
||||
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));
|
||||
|
||||
iso14443a_off();
|
||||
hf_field_off();
|
||||
set_tracing(false);
|
||||
}
|
||||
|
||||
|
@ -2893,7 +3034,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) {
|
|||
* Mifare Classic NACK-bug detection
|
||||
* 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_nr_ar[] = {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[1] = num_nacks;
|
||||
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);
|
||||
BigBuf_free();
|
||||
iso14443a_off();
|
||||
hf_field_off();
|
||||
set_tracing(false);
|
||||
}
|
||||
|
|
|
@ -13,21 +13,9 @@
|
|||
#ifndef __ISO14443A_H
|
||||
#define __ISO14443A_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "mifare.h" // struct
|
||||
#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
|
||||
// 2 ticks delay in the RF part (for the first falling edge),
|
||||
|
@ -42,11 +30,11 @@ extern "C" {
|
|||
|
||||
typedef struct {
|
||||
enum {
|
||||
DEMOD_UNSYNCD,
|
||||
// DEMOD_HALF_SYNCD,
|
||||
// DEMOD_MOD_FIRST_HALF,
|
||||
// DEMOD_NOMOD_FIRST_HALF,
|
||||
DEMOD_MANCHESTER_DATA
|
||||
DEMOD_14A_UNSYNCD,
|
||||
// DEMOD_14A_HALF_SYNCD,
|
||||
// DEMOD_14A_MOD_FIRST_HALF,
|
||||
// DEMOD_14A_NOMOD_FIRST_HALF,
|
||||
DEMOD_14A_MANCHESTER_DATA
|
||||
} state;
|
||||
uint16_t twoBits;
|
||||
uint16_t highCnt;
|
||||
|
@ -61,7 +49,7 @@ typedef struct {
|
|||
uint32_t startTime, endTime;
|
||||
uint8_t *output;
|
||||
uint8_t *parity;
|
||||
} tDemod;
|
||||
} tDemod14a;
|
||||
/*
|
||||
typedef enum {
|
||||
MOD_NOMOD = 0,
|
||||
|
@ -73,11 +61,11 @@ typedef enum {
|
|||
|
||||
typedef struct {
|
||||
enum {
|
||||
STATE_UNSYNCD,
|
||||
STATE_START_OF_COMMUNICATION,
|
||||
STATE_MILLER_X,
|
||||
STATE_MILLER_Y,
|
||||
STATE_MILLER_Z,
|
||||
STATE_14A_UNSYNCD,
|
||||
STATE_14A_START_OF_COMMUNICATION,
|
||||
STATE_14A_MILLER_X,
|
||||
STATE_14A_MILLER_Y,
|
||||
STATE_14A_MILLER_Z,
|
||||
// DROP_NONE,
|
||||
// DROP_FIRST_HALF,
|
||||
} state;
|
||||
|
@ -93,7 +81,7 @@ typedef struct {
|
|||
uint32_t startTime, endTime;
|
||||
uint8_t *output;
|
||||
uint8_t *parity;
|
||||
} tUart;
|
||||
} tUart14a;
|
||||
|
||||
#ifndef AddCrc14A
|
||||
# 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);
|
||||
|
||||
tDemod *GetDemod(void);
|
||||
void DemodReset(void);
|
||||
void DemodInit(uint8_t *data, uint8_t *par);
|
||||
tUart *GetUart(void);
|
||||
void UartReset(void);
|
||||
void UartInit(uint8_t *data, uint8_t *par);
|
||||
tDemod14a *GetDemod14a(void);
|
||||
void Demod14aReset(void);
|
||||
void Demod14aInit(uint8_t *data, uint8_t *par);
|
||||
tUart14a *GetUart14a(void);
|
||||
void Uart14aReset(void);
|
||||
void Uart14aInit(uint8_t *data, uint8_t *par);
|
||||
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);
|
||||
|
||||
|
@ -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_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades);
|
||||
void iso14a_set_trigger(bool enable);
|
||||
void hf_field_off(void);
|
||||
|
||||
int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen);
|
||||
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);
|
||||
|
||||
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype);
|
||||
void DetectNACKbug();
|
||||
void DetectNACKbug(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
bool GetIso14443aAnswerFromTag_Thinfilm(uint8_t *receivedResponse, uint8_t *received_len);
|
||||
|
||||
#endif /* __ISO14443A_H */
|
||||
|
|
|
@ -10,6 +10,20 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#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
|
||||
// defaults to 2000ms
|
||||
# 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
|
||||
// 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.
|
||||
// If it's good, then we can do something appropriate with it, and send
|
||||
// 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 {
|
||||
enum {
|
||||
STATE_UNSYNCD,
|
||||
STATE_GOT_FALLING_EDGE_OF_SOF,
|
||||
STATE_AWAITING_START_BIT,
|
||||
STATE_RECEIVING_DATA
|
||||
STATE_14B_UNSYNCD,
|
||||
STATE_14B_GOT_FALLING_EDGE_OF_SOF,
|
||||
STATE_14B_AWAITING_START_BIT,
|
||||
STATE_14B_RECEIVING_DATA
|
||||
} state;
|
||||
uint16_t shiftReg;
|
||||
int bitCnt;
|
||||
|
@ -77,8 +91,8 @@ static struct {
|
|||
uint8_t *output;
|
||||
} Uart;
|
||||
|
||||
static void UartReset() {
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
static void Uart14bReset() {
|
||||
Uart.state = STATE_14B_UNSYNCD;
|
||||
Uart.shiftReg = 0;
|
||||
Uart.bitCnt = 0;
|
||||
Uart.byteCnt = 0;
|
||||
|
@ -86,9 +100,9 @@ static void UartReset() {
|
|||
Uart.posCnt = 0;
|
||||
}
|
||||
|
||||
static void UartInit(uint8_t *data) {
|
||||
static void Uart14bInit(uint8_t *data) {
|
||||
Uart.output = data;
|
||||
UartReset();
|
||||
Uart14bReset();
|
||||
// memset(Uart.output, 0x00, MAX_FRAME_SIZE);
|
||||
}
|
||||
|
||||
|
@ -120,7 +134,7 @@ static struct {
|
|||
} Demod;
|
||||
|
||||
// Clear out the state of the "UART" that receives from the tag.
|
||||
static void DemodReset() {
|
||||
static void Demod14bReset() {
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
Demod.bitCount = 0;
|
||||
Demod.posCount = 0;
|
||||
|
@ -133,9 +147,9 @@ static void DemodReset() {
|
|||
Demod.endTime = 0;
|
||||
}
|
||||
|
||||
static void DemodInit(uint8_t *data) {
|
||||
static void Demod14bInit(uint8_t *data) {
|
||||
Demod.output = data;
|
||||
DemodReset();
|
||||
Demod14bReset();
|
||||
// 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) {
|
||||
switch (Uart.state) {
|
||||
case STATE_UNSYNCD:
|
||||
case STATE_14B_UNSYNCD:
|
||||
if (!bit) {
|
||||
// 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.bitCnt = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_GOT_FALLING_EDGE_OF_SOF:
|
||||
case STATE_14B_GOT_FALLING_EDGE_OF_SOF:
|
||||
Uart.posCnt++;
|
||||
if (Uart.posCnt == 2) { // sample every 4 1/fs in the middle of a bit
|
||||
if (bit) {
|
||||
|
@ -333,11 +347,11 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
|
|||
// zeros that it's a valid SOF
|
||||
Uart.posCnt = 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
|
||||
} else {
|
||||
// didn't stay down long enough before going high, error
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
Uart.state = STATE_14B_UNSYNCD;
|
||||
}
|
||||
} else {
|
||||
// do nothing, keep waiting
|
||||
|
@ -348,27 +362,27 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
|
|||
if (Uart.bitCnt > 12) {
|
||||
// Give up if we see too many zeros without a one, too.
|
||||
LED_A_OFF();
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
Uart.state = STATE_14B_UNSYNCD;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_AWAITING_START_BIT:
|
||||
case STATE_14B_AWAITING_START_BIT:
|
||||
Uart.posCnt++;
|
||||
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
|
||||
// stayed high for too long between characters, error
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
Uart.state = STATE_14B_UNSYNCD;
|
||||
}
|
||||
} else {
|
||||
// falling edge, this starts the data byte
|
||||
Uart.posCnt = 0;
|
||||
Uart.bitCnt = 0;
|
||||
Uart.shiftReg = 0;
|
||||
Uart.state = STATE_RECEIVING_DATA;
|
||||
Uart.state = STATE_14B_RECEIVING_DATA;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_RECEIVING_DATA:
|
||||
case STATE_14B_RECEIVING_DATA:
|
||||
Uart.posCnt++;
|
||||
if (Uart.posCnt == 2) {
|
||||
// time to sample a bit
|
||||
|
@ -391,30 +405,30 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
|
|||
if (Uart.byteCnt >= Uart.byteCntMax) {
|
||||
// Buffer overflowed, give up
|
||||
LED_A_OFF();
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
Uart.state = STATE_14B_UNSYNCD;
|
||||
} else {
|
||||
// so get the next byte now
|
||||
Uart.posCnt = 0;
|
||||
Uart.state = STATE_AWAITING_START_BIT;
|
||||
Uart.state = STATE_14B_AWAITING_START_BIT;
|
||||
}
|
||||
} else if (Uart.shiftReg == 0x000) {
|
||||
// this is an EOF byte
|
||||
LED_A_OFF(); // Finished receiving
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
Uart.state = STATE_14B_UNSYNCD;
|
||||
if (Uart.byteCnt != 0)
|
||||
return true;
|
||||
|
||||
} else {
|
||||
// this is an error
|
||||
LED_A_OFF();
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
Uart.state = STATE_14B_UNSYNCD;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LED_A_OFF();
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
Uart.state = STATE_14B_UNSYNCD;
|
||||
break;
|
||||
}
|
||||
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.
|
||||
UartInit(received);
|
||||
Uart14bInit(received);
|
||||
|
||||
uint8_t mask;
|
||||
while (!BUTTON_PRESS()) {
|
||||
|
@ -949,7 +963,7 @@ static void GetTagSamplesFor14443bDemod() {
|
|||
BigBuf_free();
|
||||
|
||||
// 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
|
||||
int8_t *dmaBuf = (int8_t *) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
|
||||
|
@ -1306,8 +1320,8 @@ void iso14443b_setup() {
|
|||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
// Initialize Demod and Uart structs
|
||||
DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
UartInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
Uart14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
|
||||
// connect Demodulated Signal to ADC:
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
@ -1411,8 +1425,8 @@ static void iso1444b_setup_sniff(void) {
|
|||
set_tracing(true);
|
||||
|
||||
// Initialize Demod and Uart structs
|
||||
DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
UartInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
Uart14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
|
||||
if (DBGLEVEL > 1) {
|
||||
// Print debug information about the buffer sizes
|
||||
|
@ -1502,8 +1516,8 @@ void RAMFUNC SniffIso14443b(void) {
|
|||
if (Handle14443bReaderUartBit(ci & 0x01)) {
|
||||
time_stop = GetCountSspClk() - time_0;
|
||||
LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true);
|
||||
UartReset();
|
||||
DemodReset();
|
||||
Uart14bReset();
|
||||
Demod14bReset();
|
||||
} else {
|
||||
time_start = GetCountSspClk() - time_0;
|
||||
}
|
||||
|
@ -1511,12 +1525,12 @@ void RAMFUNC SniffIso14443b(void) {
|
|||
if (Handle14443bReaderUartBit(cq & 0x01)) {
|
||||
time_stop = GetCountSspClk() - time_0;
|
||||
LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true);
|
||||
UartReset();
|
||||
DemodReset();
|
||||
Uart14bReset();
|
||||
Demod14bReset();
|
||||
} else {
|
||||
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
|
||||
|
@ -1527,8 +1541,8 @@ void RAMFUNC SniffIso14443b(void) {
|
|||
if (Handle14443bTagSamplesDemod(ci, cq)) {
|
||||
time_stop = GetCountSspClk() - time_0;
|
||||
LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false);
|
||||
UartReset();
|
||||
DemodReset();
|
||||
Uart14bReset();
|
||||
Demod14bReset();
|
||||
} else {
|
||||
time_start = GetCountSspClk() - time_0;
|
||||
}
|
||||
|
|
|
@ -13,18 +13,10 @@
|
|||
#ifndef __ISO14443B_H
|
||||
#define __ISO14443B_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "common.h"
|
||||
|
||||
#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 "protocols.h"
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
#ifndef AddCrc14A
|
||||
# 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)
|
||||
#endif
|
||||
|
||||
void SendRawCommand14443B_Ex(PacketCommandNG *c);
|
||||
void iso14443b_setup();
|
||||
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_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
|
||||
void WaitForFpgaDelayQueueIsEmpty(uint16_t delay);
|
||||
void ClearFpgaShiftingRegisters(void);
|
||||
|
@ -53,8 +51,4 @@ void ClearFpgaShiftingRegisters(void);
|
|||
#define SIM_ACKNOWLEDGE 5
|
||||
#define SIM_WORK 6
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ISO14443B_H */
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
//
|
||||
// VICC (tag) -> VCD (reader)
|
||||
// Modulation:
|
||||
// ASK / one subcarrier (423,75 khz)
|
||||
// FSK / two subcarriers (423,75 khz && 484,28 khz)
|
||||
// ASK / one subcarrier (423,75 kHz)
|
||||
// FSK / two subcarriers (423,75 kHz && 484,28 kHz)
|
||||
// Data Rates / Modes:
|
||||
// low ASK: 6,62 kbit/s
|
||||
// low FSK: 6.67 kbit/s
|
||||
|
@ -58,12 +58,20 @@
|
|||
// *) remove or refactor code under "depricated"
|
||||
// *) document all the functions
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "iso15693.h"
|
||||
|
||||
#include "proxmark3_arm.h"
|
||||
#include "util.h"
|
||||
#include "apps.h"
|
||||
#include "string.h"
|
||||
#include "iso15693tools.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
|
||||
|
|
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
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
INCLUDE ../common/ldscript.common
|
||||
INCLUDE ../common_arm/ldscript.common
|
||||
|
||||
PHDRS
|
||||
{
|
||||
|
|
|
@ -11,11 +11,20 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "legicrf.h"
|
||||
|
||||
#include "ticks.h" /* timers */
|
||||
#include "crc.h" /* legic crc-4 */
|
||||
#include "legic_prng.h" /* legic PRNG impl */
|
||||
#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 legic_card_select_t card;/* metadata of currently selected card */
|
||||
static crc_t legic_crc;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#ifndef __LEGICRF_H
|
||||
#define __LEGICRF_H
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "common.h"
|
||||
|
||||
void LegicRfInfo(void);
|
||||
void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv);
|
||||
|
|
|
@ -11,11 +11,17 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "legicrf.h"
|
||||
|
||||
#include "ticks.h" /* timers */
|
||||
#include "crc.h" /* legic crc-4 */
|
||||
#include "legic_prng.h" /* legic PRNG impl */
|
||||
#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 legic_card_select_t card;/* metadata of currently selected card */
|
||||
static crc_t legic_crc;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#ifndef __LEGICRFSIM_H
|
||||
#define __LEGICRFSIM_H
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "common.h"
|
||||
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "lfops.h"
|
||||
|
||||
#include "proxmark3_arm.h"
|
||||
#include "cmd.h"
|
||||
#include "BigBuf.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "ticks.h"
|
||||
#include "dbprint.h"
|
||||
#include "util.h"
|
||||
#include "hitag2.h"
|
||||
#include "commonutil.h"
|
||||
|
||||
#include "crc16.h"
|
||||
#include "string.h"
|
||||
#include "printf.h"
|
||||
#include "lfdemod.h"
|
||||
#include "lfsampling.h"
|
||||
#include "protocols.h"
|
||||
#include "usb_cdc.h" // for usb_poll_validate_length
|
||||
#include "common.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
|
||||
// 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_1 = 256 32*8; (32*8)
|
||||
|
||||
// These timings work for 4469/4269/4305 (with the 55*8 above)
|
||||
// WRITE_0 = 23*8 , 9*8
|
||||
|
||||
// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
|
||||
// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
|
||||
// Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier)
|
||||
// T0 = TIMER_CLOCK1 / 125000 = 192
|
||||
// 1 Cycle = 8 microseconds(us) == 1 field clock
|
||||
Not about ARM TIMERS
|
||||
Short note about timers on Proxmark device ARM. They are a bit differently implemented and gives decent correctness.
|
||||
|
||||
SAM7S has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
|
||||
TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
|
||||
|
||||
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
|
||||
==========================================================================================================
|
||||
|
||||
// t55xx_config t_config = { 29 * 8, 17 * 8, 15 * 8, 47 * 8, 15 * 8 } ;
|
||||
|
||||
ATA5577 Downlink Protocol Timings.
|
||||
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 |
|
||||
------------------------------+-----------------------------------+-----------------------------------+------
|
||||
|
@ -110,21 +127,23 @@
|
|||
| |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 |
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
// Initial values if not in flash
|
||||
/*
|
||||
// Note: Moved * 8 to apply when used. Saving 28 bytes here (- the *8) and 28 bytes flash.
|
||||
// StartGap WriteGap Bit 0/00 Bit 1/01 Bit 10 Bit 11 ReadGap
|
||||
t55xx_config T55xx_Timing = {{
|
||||
|
||||
Initial values if not in flash
|
||||
|
||||
SG = Start gap
|
||||
WG = Write gap
|
||||
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
|
||||
{ 31 , 20 , 18 , 50 , 0 , 0 , 15 }, // Long Leading Ref.
|
||||
{ 31 , 20 , 18 , 40 , 0 , 0 , 15 }, // Leading 0
|
||||
{ 29 , 17 , 15 , 31 , 47 , 63 , 15 } // 1 of 4
|
||||
}
|
||||
};
|
||||
*/
|
||||
// StartGap WriteGap Bit 0/00 Bit 1/01 ReadGap Bit 10 Bit 11
|
||||
t55xx_config T55xx_Timing = {{
|
||||
t55xx_configurations_t T55xx_Timing = {
|
||||
{
|
||||
{ 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, 40 * 8, 15 * 8, 0, 0 }, // Leading 0
|
||||
|
@ -134,61 +153,136 @@ t55xx_config T55xx_Timing = {{
|
|||
|
||||
|
||||
// Some defines for readability
|
||||
#define T55xx_DLMode_Fixed 0 // Default Mode
|
||||
#define T55xx_DLMode_LLR 1 // Long Leading Reference
|
||||
#define T55xx_DLMode_Leading0 2 // Leading Zero
|
||||
#define T55xx_DLMode_1of4 3 // 1 of 4
|
||||
#define T55xx_LongLeadingReference 4 // Value to tell Write Bit to send long reference
|
||||
#define T55XX_DLMODE_FIXED 0 // Default Mode
|
||||
#define T55XX_DLMODE_LLR 1 // Long Leading Reference
|
||||
#define T55XX_DLMODE_LEADING_ZERO 2 // Leading Zero
|
||||
#define T55XX_DLMODE_1OF4 3 // 1 of 4
|
||||
#define T55XX_LONGLEADINGREFERENCE 4 // Value to tell Write Bit to send long reference
|
||||
|
||||
void printT55xxConfig(void) {
|
||||
int DLMode;
|
||||
|
||||
DbpString(_BLUE_("LF T55XX config"));
|
||||
for (DLMode = 0; DLMode < 4; DLMode++) {
|
||||
switch (DLMode) {
|
||||
case T55xx_DLMode_Fixed :
|
||||
Dbprintf("r 0 fixed bit length (default)");
|
||||
break;
|
||||
case T55xx_DLMode_LLR :
|
||||
Dbprintf("r 1 long leading reference");
|
||||
break;
|
||||
case T55xx_DLMode_Leading0 :
|
||||
Dbprintf("r 2 leading zero");
|
||||
break;
|
||||
case T55xx_DLMode_1of4 :
|
||||
Dbprintf("r 3 1 of 4 coding reference");
|
||||
break;
|
||||
}
|
||||
Dbprintf(" [a] startgap............%d*8 (%d)", T55xx_Timing.m[DLMode].start_gap / 8, T55xx_Timing.m[DLMode].start_gap);
|
||||
Dbprintf(" [b] writegap............%d*8 (%d)", T55xx_Timing.m[DLMode].write_gap / 8, T55xx_Timing.m[DLMode].write_gap);
|
||||
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);
|
||||
}
|
||||
// ATA55xx shared presets & routines
|
||||
static uint32_t GetT55xxClockBit(uint32_t clock) {
|
||||
switch (clock) {
|
||||
case 128:
|
||||
return T55x7_BITRATE_RF_128;
|
||||
case 100:
|
||||
return T55x7_BITRATE_RF_100;
|
||||
case 64:
|
||||
return T55x7_BITRATE_RF_64;
|
||||
case 50:
|
||||
return T55x7_BITRATE_RF_50;
|
||||
case 40:
|
||||
return T55x7_BITRATE_RF_40;
|
||||
case 32:
|
||||
return T55x7_BITRATE_RF_32;
|
||||
case 16:
|
||||
return T55x7_BITRATE_RF_16;
|
||||
case 8:
|
||||
return T55x7_BITRATE_RF_8;
|
||||
default :
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void setT55xxConfig(uint8_t arg0, t55xx_config *c) {
|
||||
uint8_t DLMode;
|
||||
// uint8_t ClearT55Settings = c->m[0].start_gap & 0xffff; // all values will be ffff if clear requested
|
||||
void printT55xxConfig(void) {
|
||||
|
||||
#define PRN_NA sprintf(s + strlen(s), _RED_("N/A") "| ");
|
||||
|
||||
for (DLMode = 0; DLMode < 4; DLMode++) {
|
||||
if (c->m[DLMode].start_gap != 0) T55xx_Timing.m[DLMode].start_gap = c->m[DLMode].start_gap;// * 8;
|
||||
if (c->m[DLMode].write_gap != 0) T55xx_Timing.m[DLMode].write_gap = c->m[DLMode].write_gap;// * 8;
|
||||
if (c->m[DLMode].write_0 != 0) T55xx_Timing.m[DLMode].write_0 = c->m[DLMode].write_0 ;// * 8;
|
||||
if (c->m[DLMode].write_1 != 0) T55xx_Timing.m[DLMode].write_1 = c->m[DLMode].write_1 ;// * 8;
|
||||
if (DLMode == T55xx_DLMode_1of4) {
|
||||
if (c->m[DLMode].write_2 != 0) T55xx_Timing.m[DLMode].write_2 = c->m[DLMode].write_2;// * 8;
|
||||
if (c->m[DLMode].write_3 != 0) T55xx_Timing.m[DLMode].write_3 = c->m[DLMode].write_3;// * 8 ;
|
||||
} else {
|
||||
T55xx_Timing.m[DLMode].write_2 = 0x00;
|
||||
T55xx_Timing.m[DLMode].write_3 = 0x00;
|
||||
DbpString(_BLUE_("LF T55XX config"));
|
||||
Dbprintf(" [r] [a] [b] [c] [d] [e] [f] [g]");
|
||||
Dbprintf(" mode |start|write|write|write| read|write|write");
|
||||
Dbprintf(" | gap | gap | 0 | 1 | gap | 2 | 3");
|
||||
Dbprintf("---------------------------+-----+-----+-----+-----+-----+-----+------");
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
|
||||
char s[160];
|
||||
memset(s, 0, sizeof(s));
|
||||
|
||||
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();
|
||||
|
@ -203,7 +297,6 @@ void setT55xxConfig(uint8_t arg0, t55xx_config *c) {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
uint8_t *buf = BigBuf_malloc(T55XX_CONFIG_LEN);
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
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);
|
||||
|
||||
// delete old configuration
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
Flash_WriteEnable();
|
||||
Flash_Erase4k(3, 0xD);
|
||||
|
||||
// write new
|
||||
res = Flash_Write(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN);
|
||||
|
||||
if (res == T55XX_CONFIG_LEN && DBGLEVEL > 1) {
|
||||
DbpString("T55XX Config save success");
|
||||
DbpString("T55XX Config save " _GREEN_("success"));
|
||||
}
|
||||
|
||||
BigBuf_free();
|
||||
#endif
|
||||
}
|
||||
|
||||
t55xx_config *getT55xxConfig(void) {
|
||||
t55xx_configurations_t *getT55xxConfig(void) {
|
||||
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
|
||||
// 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...
|
||||
// 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
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
// 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
|
||||
|
@ -381,9 +476,9 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint
|
|||
void ReadTItag(void) {
|
||||
StartTicks();
|
||||
// some hardcoded initial params
|
||||
// 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 0 as 16 cycles of 134.2Khz
|
||||
// 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 0 as 16 cycles of 134.2kHz
|
||||
#define FSAMPLE 2000000
|
||||
#define FREQLO 123200
|
||||
#define FREQHI 134200
|
||||
|
@ -399,9 +494,9 @@ void ReadTItag(void) {
|
|||
// when to tell if we're close enough to one freq or another
|
||||
uint32_t threshold = (sampleslo - sampleshi + 1) >> 1;
|
||||
|
||||
// TI tags charge at 134.2Khz
|
||||
// TI tags charge at 134.2kHz
|
||||
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
|
||||
// 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);
|
||||
|
||||
// TI tags charge at 134.2Khz
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
|
||||
// TI tags charge at 134.2kHz
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8kHz
|
||||
// Place FPGA in passthrough mode, in this mode the CROSS_LO line
|
||||
// connects to SSP_DIN and the SSP_DOUT logic level controls
|
||||
// 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();
|
||||
|
||||
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)
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz
|
||||
else
|
||||
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) {
|
||||
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
|
||||
|
@ -984,7 +1079,7 @@ void CmdFSKsimTAG(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk,
|
|||
if (ledcontrol) LED_A_ON();
|
||||
SimulateTagLowFrequency(n, 0, ledcontrol);
|
||||
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)
|
||||
|
@ -1073,7 +1168,7 @@ void CmdASKsimTAG(uint8_t encoding, uint8_t invert, uint8_t separator, uint8_t c
|
|||
if (ledcontrol) LED_A_ON();
|
||||
SimulateTagLowFrequency(n, 0, ledcontrol);
|
||||
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
|
||||
|
@ -1120,7 +1215,7 @@ void CmdPSKsimTag(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, u
|
|||
if (ledcontrol) LED_A_ON();
|
||||
SimulateTagLowFrequency(n, 0, ledcontrol);
|
||||
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
|
||||
|
@ -1129,7 +1224,7 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol)
|
|||
size_t size;
|
||||
uint32_t hi2 = 0, hi = 0, lo = 0;
|
||||
int dummyIdx = 0;
|
||||
// Configure to go in 125Khz listen mode
|
||||
// Configure to go in 125kHz listen mode
|
||||
LFSetupFPGAForADC(95, true);
|
||||
|
||||
//clear read buffer
|
||||
|
@ -1380,7 +1475,7 @@ void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) {
|
|||
|
||||
BigBuf_Clear_keep_EM();
|
||||
|
||||
// Configure to go in 125Khz listen mode
|
||||
// Configure to go in 125kHz listen mode
|
||||
LFSetupFPGAForADC(95, true);
|
||||
|
||||
while (!BUTTON_PRESS() && !data_available()) {
|
||||
|
@ -1478,37 +1573,35 @@ void TurnReadLF_off(uint32_t delay) {
|
|||
}
|
||||
|
||||
// Macro for code readability
|
||||
#define BitStream_Byte(X) ((X) >> 3)
|
||||
#define BitStream_Bit(X) ((X) & 7)
|
||||
#define t55_llr_ref (136 * 8)
|
||||
#define t55_send_PwdMode (arg & 0x01)
|
||||
#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)
|
||||
#define BITSTREAM_BYTE(x) ((x) >> 3) // iceman note: isn't this NIBBLE???
|
||||
#define BITSTREAM_BIT(x) ((x) & 7)
|
||||
|
||||
#define T55_LLR_REF (136 * 8)
|
||||
|
||||
// Write one bit to chip
|
||||
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) {
|
||||
case 0 :
|
||||
// send bit 0/00
|
||||
TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_0);
|
||||
break; // Send bit 0/00
|
||||
break;
|
||||
case 1 :
|
||||
// send bit 1/01
|
||||
TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_1);
|
||||
break; // Send bit 1/01
|
||||
break;
|
||||
case 2 :
|
||||
// send bits 10 (1 of 4)
|
||||
TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_2);
|
||||
break; // Send bits 10 (1 of 4)
|
||||
break;
|
||||
case 3 :
|
||||
// send bits 11 (1 of 4)
|
||||
TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_3);
|
||||
break; // Send bits 11 (1 of 4)
|
||||
break;
|
||||
case 4 :
|
||||
TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_0 + t55_llr_ref);
|
||||
break; // Send Long Leading Reference
|
||||
// send Long Leading Reference
|
||||
TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_0 + T55_LLR_REF);
|
||||
break;
|
||||
}
|
||||
|
||||
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
|
||||
// max_len - how many bytes can the bit_array hold (ensure no buffer overflow)
|
||||
// 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 NextOffset = start_offset;
|
||||
int8_t next_offset = start_offset;
|
||||
|
||||
// Check if data will fit.
|
||||
if ((start_offset + num_bits) <= (max_len * 8)) {
|
||||
// Loop through the data and store
|
||||
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
|
||||
else BitStream[BitStream_Byte(NextOffset)] &= (0xff ^ (1 << BitStream_Bit(NextOffset))); // Set the bit to 0
|
||||
if ((data >> offset) & 1)
|
||||
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 {
|
||||
// Note: This should never happen unless some code changes cause it.
|
||||
// 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
|
||||
// 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
|
||||
xxxx xxxxxxx1 0x001 PwdMode
|
||||
xxxx xxxxxx1x 0x002 Page
|
||||
xxxx xxxxx1xx 0x004 testMode
|
||||
xxxx xxx11xxx 0x018 downlink mode
|
||||
xxxx xx1xxxxx 0x020 !reg_readmode
|
||||
xxxx x1xxxxxx 0x040 called for a read, so no data packet
|
||||
xxxx 1xxxxxxx 0x080 reset
|
||||
xxx1 xxxxxxxx 0x100 brute force
|
||||
111x xxxxxxxx 0xE00 Block
|
||||
xxxx xxxxxxx1 0x001 password mode (Y/N)
|
||||
xxxx xxxxxx1x 0x002 page (0|1)
|
||||
xxxx xxxxx1xx 0x004 test mode (Y/N)
|
||||
xxxx xxx11xxx 0x018 selected downlink mode (0|1|2|3|)
|
||||
xxxx xx1xxxxx 0x020 !reg_readmode (ICEMAN ?? Why use negative in the bool ??)
|
||||
xxxx x1xxxxxx 0x040 called for a read, so no data packet (Y/N)
|
||||
xxxx 1xxxxxxx 0x080 reset (Y/N)
|
||||
xxx1 xxxxxxxx 0x100 brute force (Y/N)
|
||||
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 i = 0;
|
||||
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;
|
||||
uint8_t downlink_mode = (arg >> 3) & 0x03;
|
||||
uint8_t block_no = (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.
|
||||
memset(BitStream, 0x00, sizeof(BitStream));
|
||||
// Max Downlink Command size ~74 bits, so 10 bytes (80 bits)
|
||||
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
|
||||
if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4))
|
||||
BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, 0, 1, sizeof(BitStream));
|
||||
// build bit stream to send.
|
||||
|
||||
// Add extra reference 0 for 1 of 4
|
||||
if (downlink_mode == T55xx_DLMode_1of4)
|
||||
BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, 0, 1, sizeof(BitStream));
|
||||
// add Leading 0
|
||||
if (downlink_mode == T55XX_DLMODE_LEADING_ZERO)
|
||||
len = T55xx_SetBits(bs, len, 0, 1, sizeof(bs));
|
||||
|
||||
// Add Opcode
|
||||
if (t55_send_Reset) {
|
||||
// Reset : r*) 00
|
||||
BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, 0, 2, sizeof(BitStream));
|
||||
// add 1 of 4 reference bit
|
||||
if (downlink_mode == T55XX_DLMODE_1OF4) {
|
||||
len = T55xx_SetBits(bs, len, 0, 1, sizeof(bs));
|
||||
// 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 {
|
||||
if (t55_send_TestMode) Dbprintf("TestMODE");
|
||||
BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, t55_send_TestMode ? 0 : 1, 1, sizeof(BitStream));
|
||||
BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, t55_send_TestMode ? 1 : t55_send_Page, 1, sizeof(BitStream));
|
||||
//if (PwdMode) {
|
||||
if (t55_send_PwdMode) {
|
||||
|
||||
if (t55_send_testmode)
|
||||
Dbprintf(_YELLOW_("Using Test Mode"));
|
||||
|
||||
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
|
||||
if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) {
|
||||
BitStreamLen = T55xx_SetBits(BitStream, BitStreamLen, 0, 2, sizeof(BitStream));
|
||||
if ((downlink_mode == T55XX_DLMODE_LEADING_ZERO) || (downlink_mode == T55XX_DLMODE_1OF4)) {
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
|
@ -1621,22 +1730,23 @@ void T55xx_SendCMD(uint32_t Data, uint32_t Pwd, uint16_t arg) {
|
|||
|
||||
// Trigger T55x7 in mode.
|
||||
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 (downlink_mode == T55xx_DLMode_LLR)
|
||||
T55xxWriteBit(T55xx_LongLeadingReference, downlink_mode);//Timing); // Send Long Leading Start Reference
|
||||
if (downlink_mode == T55XX_DLMODE_LLR)
|
||||
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
|
||||
for (i = 0; i < BitStreamLen - 1; i += 2) {
|
||||
SendBits = (BitStream[BitStream_Byte(i)] >> (BitStream_Bit(i)) & 1) << 1; // Bit i
|
||||
SendBits += (BitStream[BitStream_Byte(i + 1)] >> (BitStream_Bit(i + 1)) & 1); // Bit i+1;
|
||||
T55xxWriteBit(SendBits & 3, downlink_mode);//Timing);
|
||||
uint8_t sendbits;
|
||||
if ((downlink_mode == T55XX_DLMODE_1OF4) && (len > 0)) { // 1 of 4 need to send 2 bits at a time
|
||||
for (uint8_t i = 0; i < len - 1; i += 2) {
|
||||
sendbits = (bs[BITSTREAM_BYTE(i)] >> (BITSTREAM_BIT(i)) & 1) << 1; // Bit i
|
||||
sendbits += (bs[BITSTREAM_BYTE(i + 1)] >> (BITSTREAM_BIT(i + 1)) & 1); // Bit i+1;
|
||||
T55xxWriteBit(sendbits & 3, downlink_mode);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < BitStreamLen; i++) {
|
||||
SendBits = (BitStream[BitStream_Byte(i)] >> BitStream_Bit(i));
|
||||
T55xxWriteBit(SendBits & 1, downlink_mode);//Timing);
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
sendbits = (bs[BITSTREAM_BYTE(i)] >> BITSTREAM_BIT(i));
|
||||
T55xxWriteBit(sendbits & 1, downlink_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1722,7 +1832,7 @@ void T55xxWriteBlock(uint8_t *data) {
|
|||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
@ -1731,7 +1841,7 @@ void T55xxWriteBlock(uint8_t *data) {
|
|||
void T55xxWriteBlock(uint8_t *data) {
|
||||
t55xx_write_block_t *c = (t55xx_write_block_t *)data;
|
||||
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
|
||||
if (!brute_mem) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -1843,7 +1953,7 @@ void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block,
|
|||
// Turn the field off
|
||||
if (!brute_mem) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -1941,12 +2051,12 @@ OUT:
|
|||
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
|
||||
LED_B_ON();
|
||||
|
||||
T55xx_SendCMD(0, Pwd, flags);
|
||||
T55xx_SendCMD(0, pwd, flags);
|
||||
|
||||
//-- Turn and leave field on to let the begin repeating transmission
|
||||
TurnReadLFOn(20 * 1000);
|
||||
|
@ -2173,7 +2283,7 @@ uint8_t *fwd_write_ptr; //forwardlink bit pointer
|
|||
//====================================================================
|
||||
//--------------------------------------------------------------------
|
||||
// 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_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);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -2364,7 +2474,7 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
|
|||
DoPartialAcquisition(20, true, 6000, 1000);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
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 "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:
|
||||
decimation = 1 (we keep 1 out of 1 samples)
|
||||
bits_per_sample = 8
|
||||
averaging = YES
|
||||
divisor = 95 (125khz)
|
||||
divisor = 95 (125kHz)
|
||||
trigger_threshold = 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) {
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
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)
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz
|
||||
else
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
|
||||
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
#ifndef __LFSAMPLING_H
|
||||
#define __LFSAMPLING_H
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "util.h"
|
||||
#include "string.h"
|
||||
#include "usb_cdc.h" // for usb_poll_validate_length
|
||||
#include "ticks.h" // for StartTicks
|
||||
#include "common.h"
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
typedef struct BitstreamOut BitstreamOut;
|
||||
|
||||
|
@ -82,5 +78,4 @@ sample_config *getSamplingConfig();
|
|||
|
||||
void printConfig();
|
||||
|
||||
|
||||
#endif // __LFSAMPLING_H
|
||||
|
|
|
@ -15,9 +15,23 @@
|
|||
|
||||
#include "mifarecmd.h"
|
||||
|
||||
#include <inttypes.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
|
||||
# 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");
|
||||
|
||||
LED_B_ON();
|
||||
reply_ng(CMD_MIFARE_READBL, status, dataoutbuf, 16);
|
||||
reply_ng(CMD_HF_MIFARE_READBL, status, dataoutbuf, 16);
|
||||
LED_B_OFF();
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
@ -1495,7 +1509,7 @@ OUT:
|
|||
|
||||
uint16_t bar = 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++);
|
||||
}
|
||||
|
||||
|
@ -1601,7 +1615,7 @@ void MifareChkKeys(uint8_t *datain) {
|
|||
|
||||
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);
|
||||
LEDsoff();
|
||||
|
||||
|
@ -1637,7 +1651,7 @@ void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) {
|
|||
//
|
||||
size_t size = blockcnt * 16;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1646,7 +1660,7 @@ void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) {
|
|||
emlGetMem(buf, blockno, blockcnt); // data, block num, blocks count (max 4)
|
||||
|
||||
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();
|
||||
BigBuf_free_keep_EM();
|
||||
}
|
||||
|
@ -1990,7 +2004,7 @@ TEST2:
|
|||
OUT:
|
||||
|
||||
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
|
||||
OnSuccessMagic();
|
||||
BigBuf_free();
|
||||
|
@ -2059,7 +2073,7 @@ void MifareSetMod(uint8_t *datain) {
|
|||
crypto1_destroy(pcs);
|
||||
|
||||
LED_B_ON();
|
||||
reply_ng(CMD_MIFARE_SETMOD, isOK, NULL, 0);
|
||||
reply_ng(CMD_HF_MIFARE_SETMOD, isOK, NULL, 0);
|
||||
|
||||
LED_B_OFF();
|
||||
|
||||
|
|
|
@ -1,27 +1,52 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Merlok - June 2011
|
||||
// Gerhard de Koning Gans - May 2008
|
||||
// Hagen Fritsch - June 2010
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Routines to support ISO 14443 type A.
|
||||
// Definitions internal to the app source.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __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 "crc.h"
|
||||
#include "protocols.h"
|
||||
#include "parity.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);
|
||||
|
||||
void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain);
|
||||
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,20 @@
|
|||
#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_FILE_COUNT 16
|
||||
#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
|
||||
#define __MIFAREDESFIRE_H
|
||||
|
||||
#include "common.h"
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "string.h"
|
||||
#include "BigBuf.h"
|
||||
#include "iso14443a.h"
|
||||
#include "desfire_key.h"
|
||||
#include "mifareutil.h"
|
||||
#include "des.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);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,19 +20,24 @@
|
|||
// /!\ Printing Debug message is disrupting emulation,
|
||||
// Only use with caution during debugging
|
||||
|
||||
#include "mifaresim.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "iso14443a.h"
|
||||
#include "mifaresim.h"
|
||||
#include "crapto1/crapto1.h"
|
||||
#include "BigBuf.h"
|
||||
#include "string.h"
|
||||
#include "mifareutil.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "proxmark3.h"
|
||||
#include "usb_cdc.h"
|
||||
#include "proxmark3_arm.h"
|
||||
#include "cmd.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) {
|
||||
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
|
||||
// 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) {
|
||||
memcpy(rATQA, rATQA_Mini, sizeof(rATQA));
|
||||
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) {
|
||||
memcpy(rATQA, rATQA_1k, sizeof(rATQA));
|
||||
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) {
|
||||
memcpy(rATQA, rATQA_2k, sizeof(rATQA));
|
||||
rSAK[0] = rSAK_2k;
|
||||
*rats = 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) {
|
||||
memcpy(rATQA, rATQA_4k, sizeof(rATQA));
|
||||
rSAK[0] = rSAK_4k;
|
||||
Dbprintf("Mifare 4K");
|
||||
if (DBGLEVEL > DBG_NONE) Dbprintf("Enforcing Mifare 4K ATQA/SAK");
|
||||
}
|
||||
|
||||
// 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);
|
||||
// BCC
|
||||
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]);
|
||||
}
|
||||
|
||||
|
@ -300,7 +305,7 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
|
|||
// BCC
|
||||
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[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",
|
||||
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];
|
||||
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",
|
||||
rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[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");
|
||||
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
|
||||
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 ...
|
||||
* (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;
|
||||
uint8_t cardSTATE = MFEMUL_NOFIELD;
|
||||
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];
|
||||
uint32_t nonce = 0;
|
||||
|
||||
tUart *uart = GetUart();
|
||||
tUart14a *uart = GetUart14a();
|
||||
|
||||
// free eventually allocated BigBuf memory but keep Emulator Memory
|
||||
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();
|
||||
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
|
||||
//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);
|
||||
|
|
|
@ -13,14 +13,12 @@
|
|||
#ifndef __MIFARESIM_H
|
||||
#define __MIFARESIM_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "common.h"
|
||||
|
||||
#ifndef CheckCrc14A
|
||||
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
|
||||
#endif
|
||||
|
||||
void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain);
|
||||
|
||||
#define AC_DATA_READ 0
|
||||
#define AC_DATA_WRITE 1
|
||||
#define AC_DATA_INC 2
|
||||
|
@ -36,4 +34,6 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain);
|
|||
#define AUTHKEYB 1
|
||||
#define AUTHKEYNONE 0xff
|
||||
|
||||
void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -68,10 +68,10 @@ void RAMFUNC SniffMifare(uint8_t param) {
|
|||
|
||||
|
||||
// Set up the demodulator for tag -> reader responses.
|
||||
DemodInit(receivedResp, receivedRespPar);
|
||||
Demod14aInit(receivedResp, receivedRespPar);
|
||||
|
||||
// Set up the demodulator for the reader -> tag commands
|
||||
UartInit(receivedCmd, receivedCmdPar);
|
||||
Uart14aInit(receivedCmd, receivedCmdPar);
|
||||
|
||||
// Setup and start DMA.
|
||||
// set transfer address and number of bytes. Start transfer.
|
||||
|
@ -80,8 +80,8 @@ void RAMFUNC SniffMifare(uint8_t param) {
|
|||
return;
|
||||
}
|
||||
|
||||
tUart *uart = GetUart();
|
||||
tDemod *demod = GetDemod();
|
||||
tUart14a *uart = GetUart14a();
|
||||
tDemod14a *demod = GetDemod14a();
|
||||
|
||||
MfSniffInit();
|
||||
|
||||
|
@ -149,10 +149,10 @@ void RAMFUNC SniffMifare(uint8_t param) {
|
|||
uint8_t readerbyte = (previous_data & 0xF0) | (*data >> 4);
|
||||
if (MillerDecoding(readerbyte, (sniffCounter - 1) * 4)) {
|
||||
LogTrace(receivedCmd, uart->len, 0, 0, NULL, true);
|
||||
DemodReset();
|
||||
UartReset();
|
||||
Demod14aReset();
|
||||
Uart14aReset();
|
||||
}
|
||||
ReaderIsActive = (uart->state != STATE_UNSYNCD);
|
||||
ReaderIsActive = (uart->state != STATE_14A_UNSYNCD);
|
||||
}
|
||||
|
||||
// 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);
|
||||
if (ManchesterDecoding(tagbyte, 0, (sniffCounter - 1) * 4)) {
|
||||
LogTrace(receivedResp, demod->len, 0, 0, NULL, false);
|
||||
DemodReset();
|
||||
UartReset();
|
||||
Demod14aReset();
|
||||
Uart14aReset();
|
||||
}
|
||||
TagIsActive = (demod->state != DEMOD_UNSYNCD);
|
||||
TagIsActive = (demod->state != DEMOD_14A_UNSYNCD);
|
||||
}
|
||||
}
|
||||
previous_data = *data;
|
|
@ -11,13 +11,6 @@
|
|||
#ifndef __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"
|
||||
|
||||
#define SNF_INIT 0
|
|
@ -9,6 +9,17 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#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;
|
||||
|
||||
// crypto1 helpers
|
||||
|
|
|
@ -12,14 +12,8 @@
|
|||
#ifndef __MIFAREUTIL_H
|
||||
#define __MIFAREUTIL_H
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "parity.h"
|
||||
#include "util.h"
|
||||
#include "string.h"
|
||||
#include "iso14443a.h"
|
||||
#include "common.h"
|
||||
#include "crapto1/crapto1.h"
|
||||
#include "des.h"
|
||||
|
||||
// mifare authentication
|
||||
#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
|
||||
#define OPTIMIZED_CIPHER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include "common.h"
|
||||
|
||||
/**
|
||||
* 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 "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 ALLOC 16
|
||||
|
||||
|
@ -404,7 +414,7 @@ void SendCmdPCF7931(uint32_t *tab) {
|
|||
Dbprintf("Sending data frame...");
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125kHz
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
|
||||
|
||||
LED_A_ON();
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
#ifndef __PCF7931_H
|
||||
#define __PCF7931_H
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "lfsampling.h"
|
||||
#include "pcf7931.h"
|
||||
#include "string.h"
|
||||
#include "common.h"
|
||||
|
||||
size_t DemodPCF7931(uint8_t **outBlocks);
|
||||
bool IsBlock0PCF7931(uint8_t *block);
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
*/
|
||||
#include "printf.h"
|
||||
|
||||
#include "string.h"
|
||||
|
||||
typedef unsigned char u_char;
|
||||
typedef unsigned int u_int;
|
||||
typedef unsigned long long u_quad_t;
|
||||
|
|
|
@ -11,9 +11,8 @@
|
|||
#ifndef __PRINTF_H
|
||||
#define __PRINTF_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include "string.h"
|
||||
#include "common.h"
|
||||
#include <stdarg.h> // va_list
|
||||
|
||||
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)));
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#ifndef RADIXSORT_H__
|
||||
#define RADIXSORT_H__
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "common.h"
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
|
@ -20,4 +18,5 @@ typedef union {
|
|||
} rscounts_t;
|
||||
|
||||
uint64_t *radixSort(uint64_t *array, uint32_t size);
|
||||
|
||||
#endif // RADIXSORT_H__
|
|
@ -43,6 +43,12 @@
|
|||
RDV40_SPIFFS_SAFE_FOOTER
|
||||
|
||||
#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/////////////////
|
||||
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